nothumanallowed 13.5.168 → 13.5.169

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.168",
3
+ "version": "13.5.169",
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.168';
8
+ export const VERSION = '13.5.169';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -8,7 +8,8 @@
8
8
  * Routing: keyword-based (no LLM call) to save API costs. Falls back to CONDUCTOR.
9
9
  */
10
10
 
11
- import { callAgent } from './llm.mjs';
11
+ import { callAgent, callLLM } from './llm.mjs';
12
+ import { buildSystemPrompt, parseActions, executeTool, TOOL_DEFINITIONS } from './tool-executor.mjs';
12
13
  import https from 'https';
13
14
  import http from 'http';
14
15
  import { URL } from 'url';
@@ -109,6 +110,64 @@ function routeMessage(text, useAutoRoute = true) {
109
110
  return bestAgent;
110
111
  }
111
112
 
113
+ // ── Tool-aware agent call (LLM + tool execution loop) ────────────────────────
114
+
115
+ /**
116
+ * Call an agent with full tool execution support.
117
+ * Like chat.mjs but headless — no confirmation prompts, all tools auto-executed.
118
+ * Returns a human-readable summary of what was done.
119
+ */
120
+ async function callAgentWithTools(config, agentName, userMessage) {
121
+ const today = new Date().toISOString().split('T')[0];
122
+ const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
123
+ const locale = Intl.DateTimeFormat().resolvedOptions().locale || 'en';
124
+ const LANG_MAP = { en: 'English', it: 'Italian', es: 'Spanish', fr: 'French', de: 'German', pt: 'Portuguese', nl: 'Dutch', pl: 'Polish', ru: 'Russian', ja: 'Japanese', ko: 'Korean', zh: 'Chinese', ar: 'Arabic', hi: 'Hindi', tr: 'Turkish' };
125
+ const language = config?.language || LANG_MAP[locale.split('-')[0]] || 'English';
126
+
127
+ const systemPrompt = TOOL_DEFINITIONS
128
+ .replace('{{TODAY}}', today)
129
+ .replace('{{TIMEZONE}}', tz)
130
+ .replace(/\{\{LANGUAGE\}\}/g, language);
131
+
132
+ // Multi-turn: serialize history as [User]/[Assistant] string (same pattern as chat.mjs)
133
+ const history = []; // [{role, content}]
134
+ let finalText = '';
135
+
136
+ for (let round = 0; round < 3; round++) {
137
+ // Build serialized message
138
+ const parts = history.map(h => (h.role === 'user' ? '[User]' : '[Assistant]') + ' ' + h.content);
139
+ parts.push('[User] ' + userMessage);
140
+ if (round > 0) {
141
+ // Replace last user with tool results continuation
142
+ }
143
+ const serialized = parts.join('\n\n');
144
+
145
+ const response = await callLLM(config, systemPrompt, serialized);
146
+ const { textParts, actions } = parseActions(response);
147
+ finalText = textParts.join('\n').trim();
148
+
149
+ if (actions.length === 0) break; // No tools — pure text response
150
+
151
+ // Execute all tools and collect results
152
+ const toolResults = [];
153
+ for (const { action, params } of actions) {
154
+ try {
155
+ const result = await executeTool(action, params, config);
156
+ const resultStr = typeof result === 'string' ? result : JSON.stringify(result);
157
+ toolResults.push(`[${action}] ${resultStr}`);
158
+ } catch (err) {
159
+ toolResults.push(`[${action}] Error: ${err.message}`);
160
+ }
161
+ }
162
+
163
+ // Feed results back: append assistant response + tool results as next user turn
164
+ history.push({ role: 'assistant', content: response });
165
+ userMessage = 'Tool results:\n' + toolResults.join('\n') + '\n\nNow give the user a concise confirmation in ' + language + '. Do NOT use HERALD format — respond conversationally.';
166
+ }
167
+
168
+ return finalText || 'Done.';
169
+ }
170
+
112
171
  // ── Telegram Bot (Long Polling via native fetch) ─────────────────────────────
113
172
 
114
173
  class TelegramResponder {
@@ -226,8 +285,11 @@ class TelegramResponder {
226
285
  // Send typing indicator
227
286
  await this._telegramCall('sendChatAction', { chat_id: chatId, action: 'typing' });
228
287
 
229
- // Call agent
230
- const response = await callAgent(this.config, agent, cleanText);
288
+ // Tool-capable agents use the full tool execution loop
289
+ // Pure reasoning/analysis agents use the simple callAgent (no tools)
290
+ const TOOL_AGENTS = new Set(['herald', 'hermes', 'edi', 'jarvis', 'flux', 'echo', 'mercury', 'pipe', 'navi', 'link', 'prometheus', 'tempest']);
291
+ const callFn = TOOL_AGENTS.has(agent) ? callAgentWithTools : callAgent;
292
+ const response = await callFn(this.config, agent, cleanText);
231
293
 
232
294
  // Truncate if too long for Telegram (4096 char limit)
233
295
  const truncated = response.length > 4000
@@ -607,8 +669,10 @@ class DiscordResponder {
607
669
  // Send typing indicator
608
670
  await this._discordApiCall('POST', `/channels/${channelId}/typing`);
609
671
 
610
- // Call agent
611
- const response = await callAgent(this.config, agent, cleanText);
672
+ // Tool-capable agents use the full tool execution loop
673
+ const TOOL_AGENTS = new Set(['herald', 'hermes', 'edi', 'jarvis', 'flux', 'echo', 'mercury', 'pipe', 'navi', 'link', 'prometheus', 'tempest']);
674
+ const callFn = TOOL_AGENTS.has(agent) ? callAgentWithTools : callAgent;
675
+ const response = await callFn(this.config, agent, cleanText);
612
676
 
613
677
  // Discord message limit is 2000 chars
614
678
  const truncated = response.length > 1900