nothumanallowed 9.4.2 → 9.4.4
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 +19 -7
- package/src/constants.mjs +1 -1
- package/src/services/web-ui.mjs +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "9.4.
|
|
3
|
+
"version": "9.4.4",
|
|
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
|
@@ -1027,8 +1027,11 @@ export async function cmdUI(args) {
|
|
|
1027
1027
|
let fullResponse;
|
|
1028
1028
|
if (toolResults.length > 0) {
|
|
1029
1029
|
// Second LLM call with real tool results — forces the LLM to use actual data
|
|
1030
|
-
const toolContext = toolResults.map(t =>
|
|
1031
|
-
|
|
1030
|
+
const toolContext = toolResults.map(t => {
|
|
1031
|
+
let clean = t.result.replace(/\[Screenshot[^\]]*\]/g, '').replace(/!\[.*?\]\(data:image[^)]+\)/g, '').slice(0, 3000);
|
|
1032
|
+
return `[${t.action} result]: ${clean.trim()}`;
|
|
1033
|
+
}).join('\n\n');
|
|
1034
|
+
const followUp = `The user asked: "${body.message}"\n\nI executed these tools and got REAL results:\n\n${toolContext}\n\nNow respond conversationally based ONLY on the REAL data above. Do NOT output any JSON blocks, base64, or image markdown — just natural text.`;
|
|
1032
1035
|
try {
|
|
1033
1036
|
fullResponse = await callLLM(config, enrichedSystemPrompt, followUp);
|
|
1034
1037
|
} catch {
|
|
@@ -1295,7 +1298,6 @@ export async function cmdUI(args) {
|
|
|
1295
1298
|
// If the tool produced a screenshot (web_search with screenshot=true), send it via SSE
|
|
1296
1299
|
if (resultStr.includes('[Screenshot of results captured')) {
|
|
1297
1300
|
try {
|
|
1298
|
-
// Extract filename from result (tool-executor already saved it)
|
|
1299
1301
|
const fileMatch = resultStr.match(/file:(ss-\d+\.jpg)/);
|
|
1300
1302
|
if (fileMatch) {
|
|
1301
1303
|
const ssFilename = fileMatch[1];
|
|
@@ -1303,6 +1305,8 @@ export async function cmdUI(args) {
|
|
|
1303
1305
|
if (fs.existsSync(ssPath)) {
|
|
1304
1306
|
const ssBase64 = fs.readFileSync(ssPath).toString('base64');
|
|
1305
1307
|
sendSSE('screenshot', { base64: ssBase64, format: 'jpeg', filename: ssFilename });
|
|
1308
|
+
// Also send as browser_frame for the viewer
|
|
1309
|
+
sendSSE('browser_frame', { base64: ssBase64, format: 'jpeg', url: 'Search results' });
|
|
1306
1310
|
if (!res._screenshotFiles) res._screenshotFiles = [];
|
|
1307
1311
|
res._screenshotFiles.push(ssFilename);
|
|
1308
1312
|
}
|
|
@@ -1318,15 +1322,23 @@ export async function cmdUI(args) {
|
|
|
1318
1322
|
// If tools were executed, make a second LLM call with results
|
|
1319
1323
|
let finalResponse = fullResponse;
|
|
1320
1324
|
if (toolResults.length > 0) {
|
|
1321
|
-
const toolContext = toolResults.map(t =>
|
|
1322
|
-
|
|
1325
|
+
const toolContext = toolResults.map(t => {
|
|
1326
|
+
// Strip screenshot file references and base64 from tool results — the screenshot was already sent to the UI
|
|
1327
|
+
let clean = t.result.replace(/\[Screenshot[^\]]*\]/g, '').replace(/!\[.*?\]\(data:image[^)]+\)/g, '').slice(0, 3000);
|
|
1328
|
+
return `[${t.action} result]: ${clean.trim()}`;
|
|
1329
|
+
}).join('\n\n');
|
|
1330
|
+
const followUp = `The user asked: "${msg}"\n\nI executed these tools and got REAL results:\n\n${toolContext}\n\nNow respond to the user conversationally based ONLY on the REAL data above. Present the results clearly. Do NOT output any JSON blocks, any base64 data, or any image markdown — just natural text. If a screenshot was taken, just mention "Screenshot captured" without embedding it.`;
|
|
1323
1331
|
sendSSE('tool_synthesis', {});
|
|
1324
1332
|
try {
|
|
1325
1333
|
finalResponse = await callLLMStream(config, enrichedPrompt, followUp, (chunk) => {
|
|
1326
1334
|
sendSSE('token', { content: chunk });
|
|
1327
1335
|
});
|
|
1328
|
-
// Strip any JSON blocks the LLM might have emitted
|
|
1329
|
-
finalResponse = finalResponse
|
|
1336
|
+
// Strip any JSON blocks and base64 the LLM might have emitted
|
|
1337
|
+
finalResponse = finalResponse
|
|
1338
|
+
.replace(/```json[\s\S]*?```/g, '')
|
|
1339
|
+
.replace(/!\[.*?\]\(data:image\/[^)]+\)/g, '')
|
|
1340
|
+
.replace(/data:image\/[a-z]+;base64,[A-Za-z0-9+/=]{100,}/g, '[image]')
|
|
1341
|
+
.trim();
|
|
1330
1342
|
} catch {
|
|
1331
1343
|
finalResponse = toolResults.map(t => `${t.action}: ${t.result}`).join('\n\n');
|
|
1332
1344
|
}
|
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.4.
|
|
8
|
+
export const VERSION = '9.4.4';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -564,8 +564,8 @@ function sendChat(){
|
|
|
564
564
|
var label=toolLabels[data.action]||data.action;
|
|
565
565
|
var indicator=data.status==='executing'?'\\u23f3 '+label+'...':'\\u2705 '+label;
|
|
566
566
|
if(data.status==='error')indicator='\\u274c '+label+' failed';
|
|
567
|
-
// Show browser viewer for browser actions
|
|
568
|
-
var isBrowserAction=data.action&&data.action.startsWith('browser_');
|
|
567
|
+
// Show browser viewer for browser and web_search actions
|
|
568
|
+
var isBrowserAction=data.action&&(data.action.startsWith('browser_')||data.action==='web_search');
|
|
569
569
|
if(isBrowserAction&&data.status==='executing'){showBrowserViewer(label,'Executing...');}
|
|
570
570
|
if(isBrowserAction&&data.status==='done'){updateBrowserStatus('\\u2705 '+label);}
|
|
571
571
|
if(isBrowserAction&&data.status==='error'){updateBrowserStatus('\\u274c '+label);}
|