nothumanallowed 9.3.8 → 9.3.10

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.8",
3
+ "version": "9.3.10",
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": {
@@ -815,12 +815,25 @@ export async function cmdUI(args) {
815
815
  return;
816
816
  }
817
817
 
818
- // Build message with history (merge persisted + request history)
819
- const requestHistory = body.history || [];
818
+ // Build message with rolling context (same strategy as streaming path)
819
+ const requestHistory = (body.history || []).map(h => ({
820
+ role: h.role,
821
+ content: (h.content || '').replace(/!\[Screenshot\]\(data:image\/[^)]+\)/g, '[Screenshot taken]'),
822
+ }));
823
+ const RECENT = 6;
820
824
  const parts = [];
821
- for (const turn of requestHistory) {
822
- const prefix = turn.role === 'user' ? '[User]' : '[Assistant]';
823
- parts.push(`${prefix} ${turn.content}`);
825
+ if (requestHistory.length > RECENT) {
826
+ const older = requestHistory.slice(0, -RECENT);
827
+ const sLines = [];
828
+ for (let i = 0; i < older.length; i += 2) {
829
+ const u = older[i]?.content?.slice(0, 150)?.replace(/\n/g, ' ') || '';
830
+ const a = older[i + 1]?.content?.slice(0, 200)?.replace(/\n/g, ' ') || '';
831
+ if (u) sLines.push(`- User: "${u.trim()}${u.length >= 150 ? '...' : ''}" → ${a.trim()}${a.length >= 200 ? '...' : ''}`);
832
+ }
833
+ if (sLines.length > 0) parts.push(`[CONTEXT — ${sLines.length} earlier exchanges]\n${sLines.join('\n')}\n[END CONTEXT]`);
834
+ }
835
+ for (const turn of requestHistory.slice(-RECENT)) {
836
+ parts.push(`${turn.role === 'user' ? '[User]' : '[Assistant]'} ${turn.content.slice(0, 2000)}`);
824
837
  }
825
838
  parts.push(`[User] ${body.message}`);
826
839
  let userMessage = parts.join('\n\n');
@@ -1120,15 +1133,38 @@ export async function cmdUI(args) {
1120
1133
  let enrichedPrompt = basePrompt;
1121
1134
  try { const m = buildMemoryContext('chat', effectiveMsg); if (m) enrichedPrompt = basePrompt + m; } catch {}
1122
1135
 
1123
- // Build message with conversation history (capped to prevent token overflow)
1124
- const history = (body.history || []).slice(-20);
1136
+ // Build message with rolling context window:
1137
+ // - Recent messages (last 6): full content up to 2000 chars
1138
+ // - Older messages: compressed to 1-line summaries preserving full context
1139
+ const rawHistory = (body.history || []).map(h => ({
1140
+ role: h.role,
1141
+ content: (h.content || '').replace(/!\[Screenshot\]\(data:image\/[^)]+\)/g, '[Screenshot taken]'),
1142
+ }));
1143
+
1144
+ const RECENT_COUNT = 6;
1125
1145
  const parts = [];
1126
- for (const turn of history) {
1146
+
1147
+ if (rawHistory.length > RECENT_COUNT) {
1148
+ // Compress older messages into a conversation summary
1149
+ const older = rawHistory.slice(0, -RECENT_COUNT);
1150
+ const summaryLines = [];
1151
+ for (let i = 0; i < older.length; i += 2) {
1152
+ const userMsg = older[i]?.content?.slice(0, 150)?.replace(/\n/g, ' ') || '';
1153
+ const assistantMsg = older[i + 1]?.content?.slice(0, 200)?.replace(/\n/g, ' ') || '';
1154
+ if (userMsg) summaryLines.push(`- User asked: "${userMsg.trim()}${userMsg.length >= 150 ? '...' : ''}" → Assistant: ${assistantMsg.trim()}${assistantMsg.length >= 200 ? '...' : ''}`);
1155
+ }
1156
+ if (summaryLines.length > 0) {
1157
+ parts.push(`[CONVERSATION CONTEXT — ${summaryLines.length} earlier exchanges]\n${summaryLines.join('\n')}\n[END CONTEXT]`);
1158
+ }
1159
+ }
1160
+
1161
+ // Recent messages in full
1162
+ const recent = rawHistory.slice(-RECENT_COUNT);
1163
+ for (const turn of recent) {
1127
1164
  const prefix = turn.role === 'user' ? '[User]' : '[Assistant]';
1128
- // Strip any base64 image data that leaked into history
1129
- const clean = (turn.content || '').replace(/!\[Screenshot\]\(data:image\/[^)]+\)/g, '[Screenshot]').slice(0, 2000);
1130
- parts.push(`${prefix} ${clean}`);
1165
+ parts.push(`${prefix} ${turn.content.slice(0, 2000)}`);
1131
1166
  }
1167
+
1132
1168
  parts.push(`[User] ${effectiveMsg}`);
1133
1169
  const userMessage = parts.join('\n\n');
1134
1170
 
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';
8
+ export const VERSION = '9.3.10';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -344,6 +344,7 @@ RULES:
344
344
  - Dates: today is {{TODAY}}. Infer relative dates from this.
345
345
  - The user's timezone is {{TIMEZONE}}.
346
346
  - 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: You MUST respond entirely in the same language the user writes in. If the user writes in English, respond 100% in English. If the user writes in Italian, respond 100% in Italian. Never mix languages. Tool names and JSON blocks stay in English, but all explanatory text, descriptions, and conversation must match the user's language.
347
348
  `.trim();
348
349
 
349
350
  // ── Action Parser ────────────────────────────────────────────────────────────
@@ -483,9 +483,8 @@ function sendChat(){
483
483
  chatHistory.push({role:'assistant',content:''});
484
484
  renderMessages();
485
485
  var streamIdx=chatHistory.length-1;
486
- var recentHistory=chatHistory.slice(-21,-1);
487
- var cleanHistory=recentHistory.map(function(m){return{role:m.role,content:(m.content||'').replace(/!\\[Screenshot\\]\\(data:image\\/[^)]+\\)/g,'[Screenshot was shown]').slice(0,2000)};});
488
- var payload={message:msg,history:cleanHistory,conversationId:activeConvId};
486
+ var allHistory=chatHistory.slice(0,-1).map(function(m){return{role:m.role,content:(m.content||'').replace(/!\\[Screenshot\\]\\(data:image\\/[^)]+\\)/g,'[Screenshot taken]')};});
487
+ var payload={message:msg,history:allHistory,conversationId:activeConvId};
489
488
 
490
489
  fetch(API+'/api/chat/stream',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)}).then(function(response){
491
490
  if(!response.ok||!response.body){chatHistory[streamIdx].content='Error: connection failed';chatStreaming=false;renderMessages();return;}