nothumanallowed 13.5.193 → 13.5.195

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": "13.5.193",
3
+ "version": "13.5.195",
4
4
  "description": "NotHumanAllowed — 38 AI agents, 80 tools, Studio (visual agentic workflows). Email, calendar, browser automation, screen capture, canvas, cron/heartbeat, Alexandria E2E messaging, GitHub, Notion, Slack, voice chat, free AI (Liara), 28 languages. Zero-dependency CLI.",
5
5
  "type": "module",
6
6
  "bin": {
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 = '13.5.193';
8
+ export const VERSION = '13.5.195';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  import { callAgent, callLLM } from './llm.mjs';
12
- import { buildSystemPrompt, parseActions, executeTool, TOOL_DEFINITIONS } from './tool-executor.mjs';
12
+ import { buildSystemPrompt, parseActions, executeTool, TOOL_DEFINITIONS, LIARA_TOOL_DEFINITIONS } from './tool-executor.mjs';
13
13
  import https from 'https';
14
14
  import http from 'http';
15
15
  import { URL } from 'url';
@@ -179,7 +179,7 @@ function detectLanguage(text) {
179
179
  * Like chat.mjs but headless — no confirmation prompts, all tools auto-executed.
180
180
  * Returns a human-readable summary of what was done.
181
181
  */
182
- async function callAgentWithTools(config, agentName, userMessage, languageOverride) {
182
+ async function callAgentWithTools(config, agentName, userMessage, languageOverride, preHistory) {
183
183
  const today = new Date().toISOString().split('T')[0];
184
184
  const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
185
185
  const locale = Intl.DateTimeFormat().resolvedOptions().locale || 'en';
@@ -187,22 +187,26 @@ async function callAgentWithTools(config, agentName, userMessage, languageOverri
187
187
  // Priority: explicit override (from message text detection) → config setting → system locale
188
188
  const language = languageOverride || config?.profile?.language || config?.language || LANG_MAP[locale.split('-')[0]] || 'English';
189
189
 
190
- const systemPrompt = TOOL_DEFINITIONS
190
+ // Use compact Liara prompt when provider is 'nha' (same logic as buildSystemPrompt)
191
+ const isLiara = config?.llm?.provider === 'nha';
192
+ const baseDefinitions = isLiara ? LIARA_TOOL_DEFINITIONS : TOOL_DEFINITIONS;
193
+ const systemPrompt = baseDefinitions
191
194
  .replace('{{TODAY}}', today)
192
195
  .replace('{{TIMEZONE}}', tz)
193
- .replace(/\{\{LANGUAGE\}\}/g, language);
196
+ .replace(/\{\{LANGUAGE\}\}/g, language) +
197
+ // For Telegram: user confirmation already happened in the chat — execute destructive actions directly
198
+ '\n\nIMPORTANT: This is a Telegram bot context. The user has already confirmed destructive actions (delete, send, etc.) via chat messages. Execute them immediately without asking again — do NOT describe what you are about to do, just do it and confirm when done.';
194
199
 
195
200
  // Multi-turn: serialize history as [User]/[Assistant] string (same pattern as chat.mjs)
196
- const history = []; // [{role, content}]
201
+ // preHistory: optional [{role, content}] from previous conversation turn (for sticky confirmations)
202
+ const history = preHistory ? [...preHistory] : [];
197
203
  let finalText = '';
204
+ let lastToolResults = null; // saved for context return
198
205
 
199
- for (let round = 0; round < 3; round++) {
206
+ for (let round = 0; round < 4; round++) {
200
207
  // Build serialized message
201
208
  const parts = history.map(h => (h.role === 'user' ? '[User]' : '[Assistant]') + ' ' + h.content);
202
209
  parts.push('[User] ' + userMessage);
203
- if (round > 0) {
204
- // Replace last user with tool results continuation
205
- }
206
210
  const serialized = parts.join('\n\n');
207
211
 
208
212
  const response = await callLLM(config, systemPrompt, serialized);
@@ -226,13 +230,14 @@ async function callAgentWithTools(config, agentName, userMessage, languageOverri
226
230
  toolResults.push(`[${action}] Error: ${err.message}`);
227
231
  }
228
232
  }
233
+ lastToolResults = toolResults;
229
234
 
230
235
  // Feed results back: append assistant response + tool results as next user turn
231
236
  history.push({ role: 'assistant', content: response });
232
237
  userMessage = 'Tool results:\n' + toolResults.join('\n') + '\n\nNow give the user a concise confirmation in ' + language + '. Do NOT use HERALD format — respond conversationally.';
233
238
  }
234
239
 
235
- return finalText || 'Done.';
240
+ return { text: finalText || 'Done.', history, lastToolResults };
236
241
  }
237
242
 
238
243
  // ── Telegram Bot (Long Polling via native fetch) ─────────────────────────────
@@ -587,17 +592,24 @@ class TelegramResponder {
587
592
 
588
593
  let agent;
589
594
  let enrichedMessage = cleanText;
595
+ let preHistory = null;
590
596
  if (useStickyAgent) {
591
597
  agent = lastCtx.agent;
592
- // Inject previous turn context so agent understands what "Sì" refers to
593
- const nl = '\n';
594
- enrichedMessage =
595
- '[Conversazione precedente]' + nl +
596
- 'Utente: ' + lastCtx.userMsg + nl +
597
- 'Tu (' + agent.toUpperCase() + '): ' + lastCtx.agentReply.slice(0, 400) + nl + nl +
598
- '[Nuovo messaggio utente]' + nl +
599
- cleanText;
600
- this.log(`[Telegram] ${fromUser}: sticky agent ${agent.toUpperCase()} (ambiguous message, last ctx ${Math.round(stickyAge/1000)}s ago)`);
598
+ // Re-inject the full conversation history from last turn so the agent
599
+ // has the eventId/context already and can proceed directly (e.g. calendar_delete)
600
+ if (lastCtx.history && lastCtx.history.length > 0) {
601
+ preHistory = lastCtx.history;
602
+ } else {
603
+ // Fallback: text-only context injection
604
+ const nl = '\n';
605
+ enrichedMessage =
606
+ '[Conversazione precedente]' + nl +
607
+ 'Utente: ' + lastCtx.userMsg + nl +
608
+ 'Tu (' + agent.toUpperCase() + '): ' + lastCtx.agentReply.slice(0, 600) + nl + nl +
609
+ '[Nuovo messaggio utente — è una conferma/risposta al turno precedente]' + nl +
610
+ cleanText;
611
+ }
612
+ this.log(`[Telegram] ${fromUser}: sticky agent ${agent.toUpperCase()} (ambiguous, last ctx ${Math.round(stickyAge/1000)}s ago, preHistory=${preHistory ? preHistory.length : 0} turns)`);
601
613
  } else {
602
614
  agent = routeMessage(cleanText, this.autoRoute);
603
615
  this.log(`[Telegram] ${fromUser} (chat ${chatId}): routed to ${agent.toUpperCase()}${isVoice ? ' [voice]' : ''}`);
@@ -620,25 +632,30 @@ class TelegramResponder {
620
632
  // Tool-capable agents use the full tool execution loop
621
633
  // Pure reasoning/analysis agents use the simple callAgent (no tools)
622
634
  const TOOL_AGENTS = new Set(['herald', 'hermes', 'edi', 'jarvis', 'flux', 'echo', 'mercury', 'pipe', 'navi', 'link', 'prometheus', 'tempest']);
623
- let response;
635
+ let responseText;
636
+ let responseHistory = null;
624
637
  if (TOOL_AGENTS.has(agent)) {
625
- response = await callAgentWithTools(this.config, agent, enrichedMessage, detectedLang);
638
+ const result = await callAgentWithTools(this.config, agent, enrichedMessage, detectedLang, preHistory);
639
+ responseText = result.text;
640
+ responseHistory = result.history;
626
641
  } else {
627
642
  // For non-tool agents: inject language instruction into the message
628
643
  const langInstruction = detectedLang ? `[Respond in ${detectedLang}] ` : '';
629
- response = await callAgent(this.config, agent, langInstruction + enrichedMessage);
644
+ responseText = await callAgent(this.config, agent, langInstruction + enrichedMessage);
630
645
  }
631
646
 
632
647
  // Truncate if too long for Telegram (4096 char limit)
633
- const truncated = response.length > 4000
634
- ? response.slice(0, 3950) + '\n\n... [truncated]'
635
- : response;
648
+ const truncated = responseText.length > 4000
649
+ ? responseText.slice(0, 3950) + '\n\n... [truncated]'
650
+ : responseText;
636
651
 
637
652
  // Save context for sticky agent continuity (next short message reuses this agent)
653
+ // Save full history so next confirmation turn has the eventId already resolved
638
654
  this._lastContextByChatId[chatId] = {
639
655
  agent,
640
656
  userMsg: cleanText,
641
- agentReply: response,
657
+ agentReply: responseText,
658
+ history: responseHistory,
642
659
  ts: Date.now(),
643
660
  };
644
661
  this._lastAgentByChatId[chatId] = agent;
@@ -649,7 +666,7 @@ class TelegramResponder {
649
666
  text: `[${agent.toUpperCase()}]\n\n${truncated}`,
650
667
  });
651
668
 
652
- this.log(`[Telegram] Responded to ${fromUser} via ${agent.toUpperCase()} (${response.length} chars)`);
669
+ this.log(`[Telegram] Responded to ${fromUser} via ${agent.toUpperCase()} (${responseText.length} chars)`);
653
670
  } catch (err) {
654
671
  this.log(`[Telegram] Agent call failed: ${err.message}`);
655
672
  // Send error message to user