nothumanallowed 9.3.4 → 9.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/commands/ui.mjs +16 -2
- package/src/constants.mjs +1 -1
- package/src/services/tool-executor.mjs +45 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.6",
|
|
4
4
|
"description": "NotHumanAllowed — 38 AI agents + 58 tools + browser automation + web search. Streaming chat, headless Chrome CDP, multi-conversation, export. Gmail, Calendar, Drive, GitHub, Notion, Slack. Zero-dependency CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/commands/ui.mjs
CHANGED
|
@@ -1189,8 +1189,22 @@ export async function cmdUI(args) {
|
|
|
1189
1189
|
}
|
|
1190
1190
|
|
|
1191
1191
|
const result = await executeTool(action, params, config);
|
|
1192
|
-
|
|
1193
|
-
|
|
1192
|
+
const resultStr = typeof result === 'object' ? JSON.stringify(result) : String(result);
|
|
1193
|
+
toolResults.push({ action, result: resultStr });
|
|
1194
|
+
sendSSE('tool', { action, status: 'done', result: typeof resultStr === 'string' ? resultStr.slice(0, 500) : '' });
|
|
1195
|
+
|
|
1196
|
+
// If the tool produced a screenshot (web_search with screenshot=true), send it via SSE
|
|
1197
|
+
if (resultStr.includes('[Screenshot of results captured')) {
|
|
1198
|
+
try {
|
|
1199
|
+
const be = await import('../services/browser-engine.mjs');
|
|
1200
|
+
if (be.isBrowserRunning()) {
|
|
1201
|
+
const ssResult = await be.browserScreenshot({ fullPage: true, format: 'png' });
|
|
1202
|
+
if (!ssResult.error) {
|
|
1203
|
+
sendSSE('screenshot', { base64: ssResult.base64, format: 'png' });
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
} catch { /* screenshot send failed */ }
|
|
1207
|
+
}
|
|
1194
1208
|
} catch (e) {
|
|
1195
1209
|
toolResults.push({ action, result: `Error: ${e.message}` });
|
|
1196
1210
|
sendSSE('tool', { action, status: 'error', error: e.message });
|
package/src/constants.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'url';
|
|
|
5
5
|
const __filename = fileURLToPath(import.meta.url);
|
|
6
6
|
const __dirname = path.dirname(__filename);
|
|
7
7
|
|
|
8
|
-
export const VERSION = '9.3.
|
|
8
|
+
export const VERSION = '9.3.6';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -267,9 +267,10 @@ TOOLS:
|
|
|
267
267
|
|
|
268
268
|
--- WEB SEARCH & FETCH ---
|
|
269
269
|
|
|
270
|
-
47. web_search(query: string, deep?: boolean)
|
|
270
|
+
47. web_search(query: string, deep?: boolean, screenshot?: boolean)
|
|
271
271
|
Search the web using DuckDuckGo. Returns titles, URLs, and snippets.
|
|
272
272
|
Set deep=true to also fetch and extract the top 3 pages' full content (slower but more detailed).
|
|
273
|
+
Set screenshot=true to also render the search results as a visual page and capture a screenshot (useful when the user asks to "see" results or wants a screenshot of search results).
|
|
273
274
|
ALWAYS use this for ANY web search request ("search for X", "find X", "look up X", "cerca X").
|
|
274
275
|
Do NOT open Google/Bing in the browser for searches — use this tool instead. It's faster and never gets blocked.
|
|
275
276
|
|
|
@@ -1092,10 +1093,25 @@ export async function executeTool(action, params, config) {
|
|
|
1092
1093
|
|
|
1093
1094
|
// ── Browser Automation ────────────────────────────────────────────
|
|
1094
1095
|
case 'browser_open': {
|
|
1095
|
-
const be = await import('./browser-engine.mjs');
|
|
1096
1096
|
const url = params.url;
|
|
1097
1097
|
if (!url) return 'A URL is required.';
|
|
1098
1098
|
|
|
1099
|
+
// Intercept search engine URLs — redirect to web_search tool
|
|
1100
|
+
const searchEngines = /^https?:\/\/(www\.)?(google|bing|duckduckgo|yahoo|baidu|yandex)\.(com|it|co\.uk|de|fr|es|org|net)/i;
|
|
1101
|
+
if (searchEngines.test(url)) {
|
|
1102
|
+
// Extract search query if present in URL
|
|
1103
|
+
try {
|
|
1104
|
+
const u = new URL(url);
|
|
1105
|
+
const q = u.searchParams.get('q') || u.searchParams.get('query') || u.searchParams.get('p');
|
|
1106
|
+
if (q) {
|
|
1107
|
+
return `REDIRECT: Use web_search instead. Search engines block automated browsers. Executing web_search for "${q}"...\n\n` +
|
|
1108
|
+
await executeTool('web_search', { query: q }, config);
|
|
1109
|
+
}
|
|
1110
|
+
} catch {}
|
|
1111
|
+
return 'Do NOT open search engines in the browser — they block automated access with CAPTCHAs. Use the web_search tool instead: {"action": "web_search", "params": {"query": "your search terms"}}';
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
const be = await import('./browser-engine.mjs');
|
|
1099
1115
|
const result = await be.browserOpen(url, {
|
|
1100
1116
|
waitForLoad: params.waitForLoad !== false,
|
|
1101
1117
|
});
|
|
@@ -1273,10 +1289,36 @@ export async function executeTool(action, params, config) {
|
|
|
1273
1289
|
if (result.error) return `Search error: ${result.message}`;
|
|
1274
1290
|
if (result.results.length === 0) return `No results found for "${query}".`;
|
|
1275
1291
|
|
|
1276
|
-
|
|
1292
|
+
const textResult = `Web search: "${query}" — ${result.resultCount} results\n\n` +
|
|
1277
1293
|
result.results.map((r, i) =>
|
|
1278
1294
|
`${i + 1}. ${r.title}\n ${r.url}\n ${r.snippet}`
|
|
1279
1295
|
).join('\n\n');
|
|
1296
|
+
|
|
1297
|
+
// If screenshot requested, render results as HTML in browser and capture
|
|
1298
|
+
if (params.screenshot) {
|
|
1299
|
+
try {
|
|
1300
|
+
const be = await import('./browser-engine.mjs');
|
|
1301
|
+
// Ensure browser is running (open about:blank if needed)
|
|
1302
|
+
if (!be.isBrowserRunning()) {
|
|
1303
|
+
await be.browserOpen('https://example.com', { waitForLoad: true });
|
|
1304
|
+
}
|
|
1305
|
+
// Build search results HTML
|
|
1306
|
+
const esc = (s) => (s || '').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
|
|
1307
|
+
const htmlItems = result.results.map((r, i) =>
|
|
1308
|
+
`<div style="margin-bottom:24px;padding-bottom:16px;border-bottom:1px solid #3c4043"><div style="font-size:18px;color:#8ab4f8;margin-bottom:4px;font-weight:600">${i + 1}. ${esc(r.title)}</div><div style="font-size:13px;color:#bdc1c6;margin-bottom:6px">${esc(r.url)}</div><div style="font-size:14px;color:#969ba1;line-height:1.5">${esc(r.snippet)}</div></div>`
|
|
1309
|
+
).join('');
|
|
1310
|
+
const fullHtml = `<html><head><style>body{background:#202124;color:#e8eaed;font-family:Arial,Helvetica,sans-serif;padding:24px 40px;max-width:800px;margin:0 auto}h1{font-size:22px;color:#8ab4f8;margin-bottom:24px;border-bottom:2px solid #3c4043;padding-bottom:12px}</style></head><body><h1>Search results: "${esc(query)}"</h1>${htmlItems}<div style="color:#5f6368;font-size:12px;margin-top:16px">Powered by NHA web_search — ${result.resultCount} results via DuckDuckGo</div></body></html>`;
|
|
1311
|
+
// Render by injecting HTML into current page via JS
|
|
1312
|
+
await be.browserEval(`document.open();document.write(${JSON.stringify(fullHtml)});document.close();`);
|
|
1313
|
+
await new Promise(r => setTimeout(r, 300));
|
|
1314
|
+
const ss = await be.browserScreenshot({ fullPage: true });
|
|
1315
|
+
if (!ss.error) {
|
|
1316
|
+
return textResult + `\n\n[Screenshot of results captured (${Math.round(ss.size / 1024)}KB)]`;
|
|
1317
|
+
}
|
|
1318
|
+
} catch { /* screenshot failed, return text only */ }
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
return textResult;
|
|
1280
1322
|
}
|
|
1281
1323
|
|
|
1282
1324
|
case 'fetch_url': {
|