nothumanallowed 13.5.167 → 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 +1 -1
- package/src/commands/ui.mjs +23 -0
- package/src/constants.mjs +1 -1
- package/src/services/message-responder.mjs +69 -5
- package/src/services/web-ui.mjs +48 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.5.
|
|
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/commands/ui.mjs
CHANGED
|
@@ -625,6 +625,29 @@ export async function cmdUI(args) {
|
|
|
625
625
|
return;
|
|
626
626
|
}
|
|
627
627
|
|
|
628
|
+
// POST /api/update-npm — install latest nothumanallowed package and restart
|
|
629
|
+
if (method === 'POST' && pathname === '/api/update-npm') {
|
|
630
|
+
sendJSON(res, 200, { ok: true, message: 'Update started' });
|
|
631
|
+
logRequest(method, pathname, 200, Date.now() - start);
|
|
632
|
+
// Stream npm install output via WebSocket, then restart
|
|
633
|
+
setTimeout(async () => {
|
|
634
|
+
const { spawn } = await import('child_process');
|
|
635
|
+
wsBroadcast({ type: 'npm-update', line: '⟳ Running: npm install -g nothumanallowed@latest\n' });
|
|
636
|
+
const child = spawn('npm', ['install', '-g', 'nothumanallowed@latest'], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
637
|
+
child.stdout.on('data', (d) => wsBroadcast({ type: 'npm-update', line: d.toString() }));
|
|
638
|
+
child.stderr.on('data', (d) => wsBroadcast({ type: 'npm-update', line: d.toString() }));
|
|
639
|
+
child.on('close', (code) => {
|
|
640
|
+
if (code === 0) {
|
|
641
|
+
wsBroadcast({ type: 'npm-update', line: '\n✅ Update complete! Restarting server...\n', done: true });
|
|
642
|
+
} else {
|
|
643
|
+
wsBroadcast({ type: 'npm-update', line: '\n❌ Update failed (exit code ' + code + '). Check output above.\n', error: true });
|
|
644
|
+
}
|
|
645
|
+
setTimeout(() => process.exit(0), 1500);
|
|
646
|
+
});
|
|
647
|
+
}, 100);
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
|
|
628
651
|
// GET /api/version/check — check npm registry for latest version
|
|
629
652
|
if (method === 'GET' && pathname === '/api/version/check') {
|
|
630
653
|
try {
|
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.
|
|
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
|
-
//
|
|
230
|
-
|
|
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
|
-
//
|
|
611
|
-
const
|
|
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
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -3808,9 +3808,56 @@ function handleDaemonEvent(msg) {
|
|
|
3808
3808
|
}
|
|
3809
3809
|
}
|
|
3810
3810
|
break;
|
|
3811
|
+
|
|
3812
|
+
case 'npm-update':
|
|
3813
|
+
var upLog = document.getElementById('npmUpdateLog');
|
|
3814
|
+
if (upLog) {
|
|
3815
|
+
upLog.textContent += msg.line || '';
|
|
3816
|
+
upLog.scrollTop = upLog.scrollHeight;
|
|
3817
|
+
}
|
|
3818
|
+
if (msg.done) {
|
|
3819
|
+
var upStatus = document.getElementById('npmUpdateStatus');
|
|
3820
|
+
if (upStatus) upStatus.textContent = 'Restarting server — reconnecting...';
|
|
3821
|
+
// Poll until server is back up, then reload
|
|
3822
|
+
setTimeout(function pollReconnect() {
|
|
3823
|
+
fetch(API + '/api/status').then(function() {
|
|
3824
|
+
window.location.reload();
|
|
3825
|
+
}).catch(function() {
|
|
3826
|
+
setTimeout(pollReconnect, 1500);
|
|
3827
|
+
});
|
|
3828
|
+
}, 3000);
|
|
3829
|
+
}
|
|
3830
|
+
if (msg.error) {
|
|
3831
|
+
var upStatus2 = document.getElementById('npmUpdateStatus');
|
|
3832
|
+
if (upStatus2) { upStatus2.textContent = 'Update failed. See output above.'; upStatus2.style.color = 'var(--red)'; }
|
|
3833
|
+
var upBtn = document.getElementById('npmUpdateCloseBtn');
|
|
3834
|
+
if (upBtn) upBtn.style.display = 'inline-block';
|
|
3835
|
+
}
|
|
3836
|
+
break;
|
|
3811
3837
|
}
|
|
3812
3838
|
}
|
|
3813
3839
|
|
|
3840
|
+
function npmUpdate() {
|
|
3841
|
+
// Show modal
|
|
3842
|
+
var existing = document.getElementById('npmUpdateModal');
|
|
3843
|
+
if (existing) existing.remove();
|
|
3844
|
+
var modal = document.createElement('div');
|
|
3845
|
+
modal.id = 'npmUpdateModal';
|
|
3846
|
+
modal.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.7);z-index:9999;display:flex;align-items:center;justify-content:center';
|
|
3847
|
+
modal.innerHTML =
|
|
3848
|
+
'<div style="background:var(--bg2);border:1px solid var(--border);border-radius:10px;padding:24px;width:540px;max-width:95vw;display:flex;flex-direction:column;gap:12px">' +
|
|
3849
|
+
'<div style="font-size:14px;font-weight:700;color:var(--fg)">↑ Updating NotHumanAllowed</div>' +
|
|
3850
|
+
'<div id="npmUpdateStatus" style="font-size:11px;color:var(--dim)">Installing latest version...</div>' +
|
|
3851
|
+
'<pre id="npmUpdateLog" style="background:var(--bg);border:1px solid var(--border);border-radius:6px;padding:12px;font-size:10px;color:var(--green);max-height:300px;overflow-y:auto;white-space:pre-wrap;word-break:break-all;margin:0"></pre>' +
|
|
3852
|
+
'<div style="display:flex;justify-content:flex-end">' +
|
|
3853
|
+
'<button id="npmUpdateCloseBtn" onclick="document.getElementById(String.fromCharCode(110,112,109,85,112,100,97,116,101,77,111,100,97,108)).remove()" style="display:none;padding:6px 16px;background:var(--bg);color:var(--dim);border:1px solid var(--border);border-radius:5px;cursor:pointer;font-size:11px">Close</button>' +
|
|
3854
|
+
'</div>' +
|
|
3855
|
+
'</div>';
|
|
3856
|
+
document.body.appendChild(modal);
|
|
3857
|
+
// Start update
|
|
3858
|
+
apiPost('/api/update-npm', {}).catch(function(){});
|
|
3859
|
+
}
|
|
3860
|
+
|
|
3814
3861
|
// ---- VOICE INPUT (in chat view) ----
|
|
3815
3862
|
var voiceRecognition = null;
|
|
3816
3863
|
var voiceRecording = false;
|
|
@@ -4164,7 +4211,7 @@ function renderSidebar() {
|
|
|
4164
4211
|
\x27<a href="https://nothumanallowed.com/docs/mobile" target="_blank" class="nav-item" style="text-decoration:none"><span class="nav-item__icon">📱</span> \x27+t(\x27nav_mobile\x27)+\x27</a>\x27+
|
|
4165
4212
|
\x27</div>\x27+
|
|
4166
4213
|
\x27<div style="padding:12px 16px;margin-top:auto;border-top:1px solid var(--border);font-size:10px;color:var(--dim)">nothumanallowed.com<span style="margin-left:6px;opacity:.5">v${VERSION}</span>\x27+
|
|
4167
|
-
(_updateInfo&&_updateInfo.updateAvailable?\x27<span style="margin-left:8px;background:#f59e0b;color:#000;border-radius:4px;padding:1px 6px;font-weight:700;cursor:pointer" title="
|
|
4214
|
+
(_updateInfo&&_updateInfo.updateAvailable?\x27<span onclick="npmUpdate()" style="margin-left:8px;background:#f59e0b;color:#000;border-radius:4px;padding:1px 6px;font-weight:700;cursor:pointer" title="Click to update to v\x27+(_updateInfo.latest||\x27\x27)+\x27">↑ Update v\x27+(_updateInfo.latest||\x27\x27)+\x27</span>\x27:\x27\x27)+
|
|
4168
4215
|
\x27</div>\x27;
|
|
4169
4216
|
}
|
|
4170
4217
|
|