nothumanallowed 9.3.10 → 9.3.12
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.12",
|
|
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/chat.mjs
CHANGED
|
@@ -59,8 +59,7 @@ const MAX_HISTORY = 20;
|
|
|
59
59
|
const CHAT_PERSONA = `You are NHA Chat, a personal operations assistant inside the NotHumanAllowed CLI. ` +
|
|
60
60
|
`You help the user manage their emails, calendar, tasks, GitHub issues, Notion pages, and Slack channels through natural conversation. ` +
|
|
61
61
|
`Be concise, helpful, and proactive. When presenting data, format it clearly. ` +
|
|
62
|
-
`Never output raw JSON to the user — always wrap results in natural language
|
|
63
|
-
`ALWAYS respond in the same language the user writes in. If the user writes in English, respond in English. If the user writes in Italian, respond in Italian. Match their language exactly.`;
|
|
62
|
+
`Never output raw JSON to the user — always wrap results in natural language.`;
|
|
64
63
|
|
|
65
64
|
// ── System Prompt Builder ────────────────────────────────────────────────────
|
|
66
65
|
|
package/src/commands/ui.mjs
CHANGED
|
@@ -175,8 +175,7 @@ export async function cmdUI(args) {
|
|
|
175
175
|
const UI_PERSONA = `You are NHA Chat, a personal operations assistant inside the NotHumanAllowed web UI. ` +
|
|
176
176
|
`You help the user manage their emails, calendar, tasks, GitHub issues, Notion pages, and Slack channels through natural conversation. ` +
|
|
177
177
|
`Be concise, helpful, and proactive. When presenting data, format it clearly. ` +
|
|
178
|
-
`Never output raw JSON to the user
|
|
179
|
-
`ALWAYS respond in the same language the user writes in. If the user writes in English, respond in English. If the user writes in Italian, respond in Italian. Match their language exactly.`;
|
|
178
|
+
`Never output raw JSON to the user.`;
|
|
180
179
|
const chatSystemPrompt = buildSystemPrompt('NHA UI', UI_PERSONA, config);
|
|
181
180
|
|
|
182
181
|
// ── Route Handlers ──────────────────────────────────────────────────────
|
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.12';
|
|
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: () => ['
|
|
615
|
+
Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
|
|
616
616
|
Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] });
|
|
617
617
|
window.chrome = { runtime: {} };
|
|
618
618
|
`,
|
|
@@ -73,6 +73,8 @@ 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
|
+
|
|
76
78
|
You have access to the following tools. When the user's message requires an action,
|
|
77
79
|
output EXACTLY ONE fenced JSON block per action:
|
|
78
80
|
|
|
@@ -344,7 +346,7 @@ RULES:
|
|
|
344
346
|
- Dates: today is {{TODAY}}. Infer relative dates from this.
|
|
345
347
|
- The user's timezone is {{TIMEZONE}}.
|
|
346
348
|
- CRITICAL: when creating calendar events, always use LOCAL time in format "YYYY-MM-DDTHH:MM:SS" WITHOUT any Z suffix or timezone offset.
|
|
347
|
-
- LANGUAGE:
|
|
349
|
+
- LANGUAGE: Respond in the language of the user's LAST message. Not the profile language, not the timezone — the actual message language.
|
|
348
350
|
`.trim();
|
|
349
351
|
|
|
350
352
|
// ── Action Parser ────────────────────────────────────────────────────────────
|
|
@@ -518,7 +520,7 @@ export function buildSystemPrompt(persona, personaDescription, config, initialCo
|
|
|
518
520
|
if (profile.notes) fields.push(`Notes: ${profile.notes}`);
|
|
519
521
|
|
|
520
522
|
if (fields.length > 0) {
|
|
521
|
-
prompt += `\n\n--- USER PROFILE (use this for personal references like "my home", "my city", etc.) ---\n${fields.join('\n')}
|
|
523
|
+
prompt += `\n\n--- USER PROFILE (use this for personal references like "my home", "my city", etc.) ---\n${fields.join('\n')}\nNOTE: The profile above is for context only. It does NOT determine your response language. Always respond in the language of the user's message.`;
|
|
522
524
|
}
|
|
523
525
|
}
|
|
524
526
|
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -105,6 +105,8 @@ input:focus,textarea:focus{border-color:var(--green3)}
|
|
|
105
105
|
.chat__input{flex:1;resize:none;min-height:40px;max-height:100px;padding:10px 14px}
|
|
106
106
|
.chat__send{background:var(--green3);color:var(--bg);padding:10px 16px;border-radius:var(--r);font-weight:700;font-size:12px}
|
|
107
107
|
.chat__send:disabled{opacity:.4}
|
|
108
|
+
.chat__stop{background:var(--red);color:var(--bright);padding:10px 16px;border-radius:var(--r);font-weight:700;font-size:12px;display:none}
|
|
109
|
+
.chat__stop--visible{display:block}
|
|
108
110
|
|
|
109
111
|
/* ---- TASKS ---- */
|
|
110
112
|
.task-bar{display:flex;gap:8px;margin-bottom:12px;flex-wrap:wrap}
|
|
@@ -207,6 +209,22 @@ var convList = [];
|
|
|
207
209
|
var dash = {emails:[],events:[],tasks:[],plan:null,status:null};
|
|
208
210
|
var dashLoaded = {emails:false,events:false,tasks:false,contacts:false,notes:false,drive:false,github:false,notion:false,slack:false};
|
|
209
211
|
var chatStreaming = false;
|
|
212
|
+
var chatAbortController = null;
|
|
213
|
+
|
|
214
|
+
function endStreaming(){
|
|
215
|
+
chatStreaming=false;chatAbortController=null;
|
|
216
|
+
var stopBtn=document.getElementById('chatStop');if(stopBtn)stopBtn.classList.remove('chat__stop--visible');
|
|
217
|
+
var sendBtn=document.getElementById('chatSend');if(sendBtn)sendBtn.style.display='';
|
|
218
|
+
}
|
|
219
|
+
function stopChat(){
|
|
220
|
+
if(chatAbortController){try{chatAbortController.abort()}catch(e){}}
|
|
221
|
+
endStreaming();
|
|
222
|
+
if(chatHistory.length>0){
|
|
223
|
+
var last=chatHistory[chatHistory.length-1];
|
|
224
|
+
if(last.role==='assistant'&&(!last.content||last.content===''))last.content='[Stopped]';
|
|
225
|
+
}
|
|
226
|
+
renderMessages();
|
|
227
|
+
}
|
|
210
228
|
|
|
211
229
|
function loadConvList(){return apiGet('/api/conversations').then(function(r){convList=(r&&r.conversations)||[];renderConvSidebar();})}
|
|
212
230
|
function loadConv(id){return apiGet('/api/conversations/'+id).then(function(r){if(r&&r.conversation){activeConvId=r.conversation.id;chatHistory=r.conversation.messages||[];renderMessages();renderConvSidebar();}})}
|
|
@@ -347,7 +365,7 @@ function renderChat(el){
|
|
|
347
365
|
'</div>'+
|
|
348
366
|
'<div class="chat"><div class="chat__messages" id="chatMessages"></div>'+
|
|
349
367
|
'<div id="chatAttachInfo" style="display:none;padding:4px 12px;font-size:11px;color:var(--cyan);background:var(--bg2);border-top:1px solid var(--border)"><span id="chatAttachName"></span> <button onclick="clearChatAttach()" style="background:none;border:none;color:#f44;cursor:pointer;font-size:14px;font-weight:700">×</button></div>'+
|
|
350
|
-
'<div class="chat__bar"><button class="chat__mic" id="chatMic" onclick="toggleVoiceInput()" title="Voice input">🎤</button><button onclick="document.getElementById(\\x27chatFileInput\\x27).click()" style="background:none;border:none;cursor:pointer;font-size:16px;padding:4px" title="Attach file">📎</button><button onclick="document.getElementById(\\x27chatImageInput\\x27).click()" style="background:none;border:none;cursor:pointer;font-size:16px;padding:4px" title="Attach image">📷</button><input type="file" id="chatFileInput" style="display:none" onchange="handleChatFile(this)"><input type="file" id="chatImageInput" accept="image/*" style="display:none" onchange="handleChatImage(this)"><textarea class="chat__input" id="chatInput" placeholder="Ask anything... (or attach file/image first)" rows="1"></textarea><button class="chat__send" id="chatSend">Send</button></div>'+
|
|
368
|
+
'<div class="chat__bar"><button class="chat__mic" id="chatMic" onclick="toggleVoiceInput()" title="Voice input">🎤</button><button onclick="document.getElementById(\\x27chatFileInput\\x27).click()" style="background:none;border:none;cursor:pointer;font-size:16px;padding:4px" title="Attach file">📎</button><button onclick="document.getElementById(\\x27chatImageInput\\x27).click()" style="background:none;border:none;cursor:pointer;font-size:16px;padding:4px" title="Attach image">📷</button><input type="file" id="chatFileInput" style="display:none" onchange="handleChatFile(this)"><input type="file" id="chatImageInput" accept="image/*" style="display:none" onchange="handleChatImage(this)"><textarea class="chat__input" id="chatInput" placeholder="Ask anything... (or attach file/image first)" rows="1"></textarea><button class="chat__send" id="chatSend">Send</button><button class="chat__stop" id="chatStop" onclick="stopChat()">Stop</button></div>'+
|
|
351
369
|
'</div>'+
|
|
352
370
|
'</div>'+
|
|
353
371
|
'</div>';
|
|
@@ -480,18 +498,22 @@ function sendChat(){
|
|
|
480
498
|
|
|
481
499
|
// Streaming SSE
|
|
482
500
|
chatStreaming=true;
|
|
501
|
+
chatAbortController=new AbortController();
|
|
502
|
+
// Show Stop button, hide Send button
|
|
503
|
+
var stopBtn=document.getElementById('chatStop');if(stopBtn)stopBtn.classList.add('chat__stop--visible');
|
|
504
|
+
var sendBtn=document.getElementById('chatSend');if(sendBtn)sendBtn.style.display='none';
|
|
483
505
|
chatHistory.push({role:'assistant',content:''});
|
|
484
506
|
renderMessages();
|
|
485
507
|
var streamIdx=chatHistory.length-1;
|
|
486
508
|
var allHistory=chatHistory.slice(0,-1).map(function(m){return{role:m.role,content:(m.content||'').replace(/!\\[Screenshot\\]\\(data:image\\/[^)]+\\)/g,'[Screenshot taken]')};});
|
|
487
509
|
var payload={message:msg,history:allHistory,conversationId:activeConvId};
|
|
488
510
|
|
|
489
|
-
fetch(API+'/api/chat/stream',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)}).then(function(response){
|
|
490
|
-
if(!response.ok||!response.body){chatHistory[streamIdx].content='Error: connection failed';
|
|
511
|
+
fetch(API+'/api/chat/stream',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload),signal:chatAbortController.signal}).then(function(response){
|
|
512
|
+
if(!response.ok||!response.body){chatHistory[streamIdx].content='Error: connection failed';endStreaming();renderMessages();return;}
|
|
491
513
|
var reader=response.body.getReader();var decoder=new TextDecoder();var buffer='';var currentEvent='';
|
|
492
514
|
function pump(){
|
|
493
515
|
reader.read().then(function(result){
|
|
494
|
-
if(result.done){
|
|
516
|
+
if(result.done){endStreaming();renderMessages();loadConvList();return;}
|
|
495
517
|
buffer+=decoder.decode(result.value,{stream:true});
|
|
496
518
|
var lines=buffer.split('\\n');buffer=lines.pop()||'';
|
|
497
519
|
for(var i=0;i<lines.length;i++){
|
|
@@ -522,16 +544,16 @@ function sendChat(){
|
|
|
522
544
|
renderMessages();
|
|
523
545
|
}
|
|
524
546
|
if(currentEvent==='tool_synthesis'){chatHistory[streamIdx].content='';renderMessages();}
|
|
525
|
-
if(currentEvent==='done'){
|
|
526
|
-
if(currentEvent==='error'){
|
|
547
|
+
if(currentEvent==='done'){endStreaming();if(data.content)chatHistory[streamIdx].content=data.content;var ss=chatHistory[streamIdx]._screenshots;if(ss&&ss.length>0){for(var si=0;si<ss.length;si++){chatHistory[streamIdx].content+='\\n\\n';}}renderMessages();loadConvList();}
|
|
548
|
+
if(currentEvent==='error'){endStreaming();chatHistory[streamIdx].content='Error: '+(data.message||'Unknown');renderMessages();}
|
|
527
549
|
}catch(e){}
|
|
528
550
|
}
|
|
529
551
|
}
|
|
530
552
|
pump();
|
|
531
|
-
}).catch(function(e){
|
|
553
|
+
}).catch(function(e){endStreaming();if(e.name!=='AbortError'){chatHistory[streamIdx].content='Error: '+e.message;renderMessages();}});
|
|
532
554
|
}
|
|
533
555
|
pump();
|
|
534
|
-
}).catch(function(e){
|
|
556
|
+
}).catch(function(e){endStreaming();if(e.name!=='AbortError'){chatHistory[streamIdx].content='Error: '+e.message;renderMessages();}});
|
|
535
557
|
}
|
|
536
558
|
|
|
537
559
|
// ---- TASKS ----
|