Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

nothumanallowed

Package Overview
Dependencies
Maintainers
1
Versions
847
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nothumanallowed - npm Package Compare versions

Comparing version
16.0.57
to
16.0.58
+1
-1
package.json
{
"name": "nothumanallowed",
"version": "16.0.57",
"version": "16.0.58",
"description": "Local AI assistant: 80 tools (Gmail, Calendar, Drive, GitHub, Slack, browser, code, files), 38 agents, visual workflows (Studio, AWF, WebCraft). Install with `npm i -g nothumanallowed`, run with `nha ui`. Free tier built-in (Liara), no API key required. Your data stays on your PC — OAuth tokens local, no cloud. Open-source MIT.",

@@ -5,0 +5,0 @@ "type": "module",

@@ -8,3 +8,3 @@ import os from 'os';

export const VERSION = '16.0.57';
export const VERSION = '16.0.58';
export const BASE_URL = 'https://nothumanallowed.com/cli';

@@ -11,0 +11,0 @@ export const API_BASE = 'https://nothumanallowed.com/api/v1';

@@ -128,2 +128,6 @@ /**

'/usr/bin/microsoft-edge',
// Termux on Android — chromium installed via "pkg install chromium"
'/data/data/com.termux/files/usr/bin/chromium',
'/data/data/com.termux/files/usr/bin/chromium-browser',
'/data/data/com.termux/files/usr/bin/google-chrome',
],

@@ -661,2 +665,100 @@ win32: [

*/
/**
* Lightweight HTTP fallback when Chrome/Chromium is not available.
* Uses fetch() + regex-based HTML→text extraction. No JS rendering, no clicks.
* Good enough for: news sites, blog posts, static pages, API responses,
* documentation pages. NOT good for: SPAs, login flows, dynamic dashboards.
*/
async function browserOpenViaFetch(url, options = {}) {
const timeout = options.timeout || 15000;
try {
const ac = new AbortController();
const timer = setTimeout(() => ac.abort(), timeout);
const res = await fetch(url, {
redirect: 'follow',
signal: ac.signal,
headers: {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9,it;q=0.8',
},
});
clearTimeout(timer);
const status = res.status;
const finalUrl = res.url || url;
const ct = res.headers.get('content-type') || '';
const isHtml = /html/i.test(ct);
const raw = await res.text();
if (!isHtml) {
return {
title: finalUrl,
url: finalUrl,
status,
mode: 'fetch-fallback',
warning: 'Chrome not installed — used HTTP fetch. No JS rendering. Limited interactivity.',
content: raw.slice(0, 50_000),
};
}
// Extract title
const titleMatch = raw.match(/<title[^>]*>([\s\S]*?)<\/title>/i);
const title = titleMatch ? titleMatch[1].replace(/\s+/g, ' ').trim() : finalUrl;
// Extract main text content: strip script/style/svg/comments, then strip tags
let textContent = raw
.replace(/<!--[\s\S]*?-->/g, '')
.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, ' ')
.replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, ' ')
.replace(/<svg\b[^>]*>[\s\S]*?<\/svg>/gi, ' ')
.replace(/<noscript\b[^>]*>[\s\S]*?<\/noscript>/gi, ' ')
.replace(/<header\b[^>]*>[\s\S]*?<\/header>/gi, ' ') // strip nav/header noise
.replace(/<nav\b[^>]*>[\s\S]*?<\/nav>/gi, ' ')
.replace(/<footer\b[^>]*>[\s\S]*?<\/footer>/gi, ' ')
.replace(/<aside\b[^>]*>[\s\S]*?<\/aside>/gi, ' ');
// Extract headlines + links separately for news sites
const headlines = [];
const linkRe = /<a\b[^>]*href=["']([^"']+)["'][^>]*>([\s\S]*?)<\/a>/gi;
let lm;
while ((lm = linkRe.exec(raw)) !== null && headlines.length < 50) {
const linkText = lm[2].replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
const href = lm[1];
if (linkText.length > 20 && linkText.length < 200 && !href.startsWith('#') && !href.startsWith('javascript:')) {
const absHref = href.startsWith('http') ? href : new URL(href, finalUrl).toString();
headlines.push({ text: linkText, url: absHref });
}
}
// Strip remaining tags to get plain text
textContent = textContent
.replace(/<[^>]+>/g, ' ')
.replace(/&nbsp;/g, ' ')
.replace(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&quot;/g, '"')
.replace(/&#39;/g, "'")
.replace(/&#x?[0-9a-f]+;/gi, '')
.replace(/\s+/g, ' ')
.trim();
return {
title,
url: finalUrl,
status,
mode: 'fetch-fallback',
warning: 'Chrome/Chromium not installed — used HTTP fetch fallback. No JS rendering, no interactive clicks/forms. To install: macOS use brew, Linux apt-get, Termux "pkg install chromium".',
headlines: headlines.slice(0, 30),
content: textContent.slice(0, 30_000),
};
} catch (e) {
if (e.name === 'AbortError') {
return { error: true, message: `HTTP fetch timeout after ${timeout / 1000}s. The site may be slow or blocking the request.` };
}
return { error: true, message: `HTTP fetch failed: ${e.message}. ${/ENOTFOUND|ECONNREFUSED/.test(e.message) ? 'Network or DNS issue.' : ''}` };
}
}
export async function browserOpen(url, options = {}) {

@@ -669,3 +771,19 @@ // SSRF check

const browser = await getBrowser();
// Fast fallback: if Chrome/Chromium is not installed (e.g. Termux on Android),
// do a plain HTTP fetch and extract text content. Limited (no JS rendering,
// no clicks), but works for news sites / blog posts / static pages.
if (!findChromePath()) {
return browserOpenViaFetch(url, options);
}
let browser;
try {
browser = await getBrowser();
} catch (e) {
// Chrome detection failed at launch — same fallback
if (/Chrome\/Chromium not found/i.test(e.message || '')) {
return browserOpenViaFetch(url, options);
}
throw e;
}
const timeout = options.timeout || NAV_TIMEOUT_MS;

@@ -672,0 +790,0 @@ const waitForLoad = options.waitForLoad !== false;

@@ -15,4 +15,9 @@ /**

// NHA published OAuth client (Desktop app type — client_id is not a secret)
const DEFAULT_CLIENT_ID = '516893094132-8u2jf6h6h3j6h8j9k0l1m2n3o4p5q6r7.apps.googleusercontent.com'; // NHA Official OAuth Client
// IMPORTANT: NHA does NOT ship a default Google OAuth client ID.
// The previous placeholder (516893094132-8u2jf...) was a fake-looking value
// that always returned `invalid_client` from Google. Each user must register
// their own OAuth client in Google Cloud Console — this is by design for
// privacy (no shared client app), and it's a one-time 3-minute setup.
// See https://nothumanallowed.com/docs/google for the full guide.
const DEFAULT_CLIENT_ID = '';
const SCOPES = [

@@ -225,10 +230,23 @@ 'https://www.googleapis.com/auth/gmail.modify',

fail('Google OAuth client ID not configured.');
info('Get credentials from Google Cloud Console:');
info(' 1. Go to https://console.cloud.google.com/apis/credentials');
info(' 2. Create an OAuth 2.0 Client ID (Desktop app type)');
info(' 3. Enable Gmail API and Calendar API');
info(' 4. Run:');
info('');
info('NHA does not ship a shared OAuth client (your data never goes through');
info('our servers — Gmail/Calendar API calls go from your PC directly to');
info('Google). You need a 3-minute one-time setup of your own OAuth client.');
info('');
info('STEPS:');
info(' 1. Open https://console.cloud.google.com/apis/credentials');
info(' 2. Click + CREATE CREDENTIALS → OAuth client ID');
info(' 3. Application type: "Desktop app", give it a name (e.g. "NHA local")');
info(' 4. Click CREATE. Google shows you Client ID + Client Secret.');
info(' 5. Enable the APIs you need:');
info(' - Gmail API: https://console.cloud.google.com/apis/library/gmail.googleapis.com');
info(' - Calendar: https://console.cloud.google.com/apis/library/calendar-json.googleapis.com');
info(' - Drive: https://console.cloud.google.com/apis/library/drive.googleapis.com');
info(' - People API: https://console.cloud.google.com/apis/library/people.googleapis.com');
info(' 6. Save the credentials in NHA:');
info(' nha config set google-client-id YOUR_CLIENT_ID');
info(' nha config set google-client-secret YOUR_CLIENT_SECRET');
info(' 5. Run: nha google auth');
info(' 7. Re-run: nha google auth');
info('');
info('Full guide with screenshots: https://nothumanallowed.com/docs/google');
return false;

@@ -235,0 +253,0 @@ }