nothumanallowed 9.3.12 → 9.3.14
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 +8 -5
- package/src/config.mjs +2 -0
- package/src/constants.mjs +1 -1
- package/src/services/browser-engine.mjs +1 -1
- package/src/services/tool-executor.mjs +31 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.14",
|
|
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
|
@@ -1210,13 +1210,16 @@ export async function cmdUI(args) {
|
|
|
1210
1210
|
sendSSE('tool', { action, status: 'error', error: 'No browser open' });
|
|
1211
1211
|
continue;
|
|
1212
1212
|
}
|
|
1213
|
+
// Scroll to top for best viewport
|
|
1214
|
+
await be.browserScroll({ direction: 'top' });
|
|
1215
|
+
await new Promise(r => setTimeout(r, 300));
|
|
1213
1216
|
const ssResult = await be.browserScreenshot({
|
|
1214
|
-
fullPage:
|
|
1215
|
-
format:
|
|
1216
|
-
quality:
|
|
1217
|
+
fullPage: false, // Always viewport
|
|
1218
|
+
format: 'jpeg',
|
|
1219
|
+
quality: 75,
|
|
1217
1220
|
});
|
|
1218
1221
|
if (!ssResult.error) {
|
|
1219
|
-
sendSSE('screenshot', { base64: ssResult.base64, format:
|
|
1222
|
+
sendSSE('screenshot', { base64: ssResult.base64, format: 'jpeg' });
|
|
1220
1223
|
toolResults.push({ action, result: `Screenshot captured (${Math.round(ssResult.size / 1024)}KB)` });
|
|
1221
1224
|
sendSSE('tool', { action, status: 'done', result: 'Screenshot captured' });
|
|
1222
1225
|
} else {
|
|
@@ -1236,7 +1239,7 @@ export async function cmdUI(args) {
|
|
|
1236
1239
|
try {
|
|
1237
1240
|
const be = await import('../services/browser-engine.mjs');
|
|
1238
1241
|
if (be.isBrowserRunning()) {
|
|
1239
|
-
const ssResult = await be.browserScreenshot({ fullPage:
|
|
1242
|
+
const ssResult = await be.browserScreenshot({ fullPage: false, format: 'jpeg', quality: 75 });
|
|
1240
1243
|
if (!ssResult.error) {
|
|
1241
1244
|
sendSSE('screenshot', { base64: ssResult.base64, format: 'png' });
|
|
1242
1245
|
}
|
package/src/config.mjs
CHANGED
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.14';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -612,7 +612,7 @@ async function launchBrowser() {
|
|
|
612
612
|
await ws.send('Page.addScriptToEvaluateOnNewDocument', {
|
|
613
613
|
source: `
|
|
614
614
|
Object.defineProperty(navigator, 'webdriver', { get: () => false });
|
|
615
|
-
Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
|
|
615
|
+
Object.defineProperty(navigator, 'languages', { get: () => ['it-IT', 'it', 'en-US', 'en'] });
|
|
616
616
|
Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] });
|
|
617
617
|
window.chrome = { runtime: {} };
|
|
618
618
|
`,
|
|
@@ -73,8 +73,6 @@ export const DESTRUCTIVE_ACTIONS = new Set([
|
|
|
73
73
|
* Callers replace {{TODAY}} and {{TIMEZONE}} and append their own persona.
|
|
74
74
|
*/
|
|
75
75
|
export const TOOL_DEFINITIONS = `
|
|
76
|
-
IMPORTANT — LANGUAGE RULE: Detect the language of the user's CURRENT message and respond ENTIRELY in that same language. English message = English response. Italian message = Italian response. Do NOT default to Italian just because the user profile or timezone is Italian. Match the language of what the user JUST wrote, not the system context.
|
|
77
|
-
|
|
78
76
|
You have access to the following tools. When the user's message requires an action,
|
|
79
77
|
output EXACTLY ONE fenced JSON block per action:
|
|
80
78
|
|
|
@@ -289,10 +287,11 @@ TOOLS:
|
|
|
289
287
|
Use this when you need to interact with a page (click, type, screenshot) or when fetch_url fails on JS-rendered content.
|
|
290
288
|
WARNING: Do NOT use this to search the web — use web_search instead. Google/Bing block automated browsers with CAPTCHAs.
|
|
291
289
|
|
|
292
|
-
50. browser_screenshot(
|
|
293
|
-
Capture a screenshot of the current browser
|
|
294
|
-
|
|
295
|
-
|
|
290
|
+
50. browser_screenshot(saveTo?: string)
|
|
291
|
+
Capture a screenshot of the current browser viewport (what's visible on screen).
|
|
292
|
+
saveTo saves to a file path (e.g. "~/screenshot.png"). Returns base64-encoded image.
|
|
293
|
+
ALWAYS use viewport screenshots (the default). Do NOT pass fullPage=true — it produces oversized images.
|
|
294
|
+
Screenshots are automatically compressed as JPEG for efficiency.
|
|
296
295
|
|
|
297
296
|
51. browser_click(text?: string, selector?: string, x?: number, y?: number)
|
|
298
297
|
Click an element on the page by visible text, CSS selector, or x/y coordinates.
|
|
@@ -346,7 +345,7 @@ RULES:
|
|
|
346
345
|
- Dates: today is {{TODAY}}. Infer relative dates from this.
|
|
347
346
|
- The user's timezone is {{TIMEZONE}}.
|
|
348
347
|
- CRITICAL: when creating calendar events, always use LOCAL time in format "YYYY-MM-DDTHH:MM:SS" WITHOUT any Z suffix or timezone offset.
|
|
349
|
-
- LANGUAGE: Respond in
|
|
348
|
+
- LANGUAGE: Respond in {{LANGUAGE}}. All conversational text, explanations, and descriptions must be in {{LANGUAGE}}. Tool names and JSON blocks remain in English.
|
|
350
349
|
`.trim();
|
|
351
350
|
|
|
352
351
|
// ── Action Parser ────────────────────────────────────────────────────────────
|
|
@@ -498,9 +497,23 @@ export function buildSystemPrompt(persona, personaDescription, config, initialCo
|
|
|
498
497
|
const today = new Date().toISOString().split('T')[0];
|
|
499
498
|
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
500
499
|
|
|
500
|
+
// Detect system language from locale
|
|
501
|
+
const locale = Intl.DateTimeFormat().resolvedOptions().locale || 'en';
|
|
502
|
+
const langCode = locale.split('-')[0];
|
|
503
|
+
const LANG_MAP = {
|
|
504
|
+
en: 'English', it: 'Italian', es: 'Spanish', fr: 'French', de: 'German',
|
|
505
|
+
pt: 'Portuguese', nl: 'Dutch', pl: 'Polish', ru: 'Russian', ja: 'Japanese',
|
|
506
|
+
ko: 'Korean', zh: 'Chinese', ar: 'Arabic', hi: 'Hindi', tr: 'Turkish',
|
|
507
|
+
sv: 'Swedish', da: 'Danish', no: 'Norwegian', fi: 'Finnish', cs: 'Czech',
|
|
508
|
+
ro: 'Romanian', hu: 'Hungarian', el: 'Greek', th: 'Thai', vi: 'Vietnamese',
|
|
509
|
+
uk: 'Ukrainian', he: 'Hebrew', id: 'Indonesian', ms: 'Malay',
|
|
510
|
+
};
|
|
511
|
+
const language = config?.language || LANG_MAP[langCode] || 'English';
|
|
512
|
+
|
|
501
513
|
let prompt = TOOL_DEFINITIONS
|
|
502
514
|
.replace('{{TODAY}}', today)
|
|
503
|
-
.replace('{{TIMEZONE}}', tz)
|
|
515
|
+
.replace('{{TIMEZONE}}', tz)
|
|
516
|
+
.replace(/\{\{LANGUAGE\}\}/g, language);
|
|
504
517
|
|
|
505
518
|
prompt += `\n\n${personaDescription}`;
|
|
506
519
|
|
|
@@ -520,7 +533,7 @@ export function buildSystemPrompt(persona, personaDescription, config, initialCo
|
|
|
520
533
|
if (profile.notes) fields.push(`Notes: ${profile.notes}`);
|
|
521
534
|
|
|
522
535
|
if (fields.length > 0) {
|
|
523
|
-
prompt += `\n\n--- USER PROFILE (use this for personal references like "my home", "my city", etc.) ---\n${fields.join('\n')}
|
|
536
|
+
prompt += `\n\n--- USER PROFILE (use this for personal references like "my home", "my city", etc.) ---\n${fields.join('\n')}`;
|
|
524
537
|
}
|
|
525
538
|
}
|
|
526
539
|
|
|
@@ -1127,14 +1140,19 @@ export async function executeTool(action, params, config) {
|
|
|
1127
1140
|
const be = await import('./browser-engine.mjs');
|
|
1128
1141
|
if (!be.isBrowserRunning()) return 'No browser open. Use browser_open first.';
|
|
1129
1142
|
|
|
1143
|
+
// Scroll to top before screenshot so user sees the most important content
|
|
1144
|
+
await be.browserScroll({ direction: 'top' });
|
|
1145
|
+
await new Promise(r => setTimeout(r, 300));
|
|
1146
|
+
|
|
1130
1147
|
const saveTo = params.saveTo
|
|
1131
1148
|
? params.saveTo.replace(/^~/, os.homedir())
|
|
1132
1149
|
: null;
|
|
1133
1150
|
|
|
1151
|
+
// Always use JPEG for efficiency (smaller base64, faster rendering in web UI)
|
|
1134
1152
|
const result = await be.browserScreenshot({
|
|
1135
|
-
fullPage:
|
|
1136
|
-
format:
|
|
1137
|
-
quality:
|
|
1153
|
+
fullPage: false, // Always viewport — fullPage produces oversized images
|
|
1154
|
+
format: 'jpeg',
|
|
1155
|
+
quality: 75,
|
|
1138
1156
|
saveTo,
|
|
1139
1157
|
});
|
|
1140
1158
|
if (result.error) return `Screenshot error: ${result.message}`;
|
|
@@ -1314,7 +1332,7 @@ export async function executeTool(action, params, config) {
|
|
|
1314
1332
|
// Render by injecting HTML into current page via JS
|
|
1315
1333
|
await be.browserEval(`document.open();document.write(${JSON.stringify(fullHtml)});document.close();`);
|
|
1316
1334
|
await new Promise(r => setTimeout(r, 300));
|
|
1317
|
-
const ss = await be.browserScreenshot({ fullPage:
|
|
1335
|
+
const ss = await be.browserScreenshot({ fullPage: false, format: 'jpeg', quality: 75 });
|
|
1318
1336
|
if (!ss.error) {
|
|
1319
1337
|
return textResult + `\n\n[Screenshot of results captured (${Math.round(ss.size / 1024)}KB)]`;
|
|
1320
1338
|
}
|