nothumanallowed 10.8.1 → 10.9.0
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 +9 -3
- package/src/constants.mjs +1 -1
- package/src/services/tool-executor.mjs +59 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.9.0",
|
|
4
4
|
"description": "NotHumanAllowed — 38 AI agents, 53 tools. Email, calendar, browser automation, screen capture, canvas, cron/heartbeat, GitHub, Notion, Slack, voice chat, 28 languages. Zero-dependency CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/commands/ui.mjs
CHANGED
|
@@ -2117,12 +2117,12 @@ export async function cmdUI(args) {
|
|
|
2117
2117
|
function connectAlexandriaWs(channelId, channelName) {
|
|
2118
2118
|
if (alexWsConnections.has(channelId)) return;
|
|
2119
2119
|
try {
|
|
2120
|
-
const { WebSocket: WsClient } = require('ws');
|
|
2121
2120
|
const wsUrl = 'wss://nothumanallowed.com/ws/alexandria/' + channelId;
|
|
2122
2121
|
const alexWs = new WsClient(wsUrl);
|
|
2123
2122
|
|
|
2124
2123
|
alexWs.on('open', () => {
|
|
2125
2124
|
alexWsConnections.set(channelId, alexWs);
|
|
2125
|
+
console.log(` [Alexandria WS] Connected to channel ${channelId.slice(0, 8)}...`);
|
|
2126
2126
|
});
|
|
2127
2127
|
|
|
2128
2128
|
alexWs.on('message', (data) => {
|
|
@@ -2166,7 +2166,8 @@ export async function cmdUI(args) {
|
|
|
2166
2166
|
// Reconnect after 5s
|
|
2167
2167
|
setTimeout(() => connectAlexandriaWs(channelId, channelName), 5000);
|
|
2168
2168
|
});
|
|
2169
|
-
alexWs.on('error', () => {
|
|
2169
|
+
alexWs.on('error', (e) => {
|
|
2170
|
+
console.log(` [Alexandria WS] Error on ${channelId.slice(0, 8)}: ${e.message}`);
|
|
2170
2171
|
alexWsConnections.delete(channelId);
|
|
2171
2172
|
});
|
|
2172
2173
|
} catch {}
|
|
@@ -2178,11 +2179,16 @@ export async function cmdUI(args) {
|
|
|
2178
2179
|
const chFile = path.join(collabDir, 'channels.json');
|
|
2179
2180
|
if (fs.existsSync(chFile)) {
|
|
2180
2181
|
const channels = JSON.parse(fs.readFileSync(chFile, 'utf-8'));
|
|
2182
|
+
console.log(` [Alexandria WS] Connecting to ${channels.length} channel(s)...`);
|
|
2181
2183
|
for (const ch of channels) {
|
|
2182
2184
|
connectAlexandriaWs(ch.id, ch.name);
|
|
2183
2185
|
}
|
|
2186
|
+
} else {
|
|
2187
|
+
console.log(' [Alexandria WS] No channels file found');
|
|
2184
2188
|
}
|
|
2185
|
-
} catch {
|
|
2189
|
+
} catch (e) {
|
|
2190
|
+
console.log(` [Alexandria WS] Startup error: ${e.message}`);
|
|
2191
|
+
}
|
|
2186
2192
|
}, 2000);
|
|
2187
2193
|
|
|
2188
2194
|
} catch {
|
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 = '10.
|
|
8
|
+
export const VERSION = '10.9.0';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -365,6 +365,13 @@ TOOLS:
|
|
|
365
365
|
65. canvas_clear()
|
|
366
366
|
Clear the canvas panel.
|
|
367
367
|
|
|
368
|
+
--- AGENT MESSENGER ---
|
|
369
|
+
|
|
370
|
+
66. collab_send(message: string, channel?: string)
|
|
371
|
+
Send an E2E encrypted message to the active Alexandria channel (AgentMessenger).
|
|
372
|
+
Use this when the user asks to notify collaborators, share progress, or send a message to other agents/team members.
|
|
373
|
+
If channel is not specified, sends to the active channel.
|
|
374
|
+
|
|
368
375
|
RULES:
|
|
369
376
|
- ABSOLUTE RULE: NEVER LIE. NEVER fabricate, invent, or guess information. If you do not know, say "I don't know." If a tool fails, say it failed. If you cannot see something, say so. Honesty is MORE important than being helpful.
|
|
370
377
|
- CRITICAL: For web searches, ALWAYS use web_search — NEVER open Google/Bing/DuckDuckGo in the browser.
|
|
@@ -1443,6 +1450,58 @@ export async function executeTool(action, params, config) {
|
|
|
1443
1450
|
return '[CANVAS_CLEAR]Canvas cleared.[/CANVAS_CLEAR]';
|
|
1444
1451
|
}
|
|
1445
1452
|
|
|
1453
|
+
// ── Agent Messenger ──────────────────────────────────────────────────
|
|
1454
|
+
case 'collab_send': {
|
|
1455
|
+
const { addCronJob, listCronJobs, loadChannels, getActiveChannel } = await import('./ops-daemon.mjs').catch(() => ({}));
|
|
1456
|
+
const collabMod = await import('../commands/collab.mjs').catch(() => null);
|
|
1457
|
+
if (!collabMod) return 'AgentMessenger not available.';
|
|
1458
|
+
|
|
1459
|
+
const msg = params.message;
|
|
1460
|
+
if (!msg) return 'Message is required.';
|
|
1461
|
+
|
|
1462
|
+
// Use collab CLI to send
|
|
1463
|
+
try {
|
|
1464
|
+
const fs = await import('fs');
|
|
1465
|
+
const path = await import('path');
|
|
1466
|
+
const crypto = await import('crypto');
|
|
1467
|
+
const os = await import('os');
|
|
1468
|
+
const NHA_DIR = path.default.join(os.default.homedir(), '.nha');
|
|
1469
|
+
const chFile = path.default.join(NHA_DIR, 'collab', 'channels.json');
|
|
1470
|
+
const idFile = path.default.join(NHA_DIR, 'collab', 'identity.json');
|
|
1471
|
+
|
|
1472
|
+
if (!fs.default.existsSync(chFile) || !fs.default.existsSync(idFile)) {
|
|
1473
|
+
return 'No Alexandria channels configured. Create one first: nha collab create "name"';
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
const channels = JSON.parse(fs.default.readFileSync(chFile, 'utf-8'));
|
|
1477
|
+
const identity = JSON.parse(fs.default.readFileSync(idFile, 'utf-8'));
|
|
1478
|
+
const channel = params.channel
|
|
1479
|
+
? channels.find(c => c.name?.toLowerCase().includes(params.channel.toLowerCase()) || c.id === params.channel)
|
|
1480
|
+
: channels.find(c => c.active) || channels[0];
|
|
1481
|
+
|
|
1482
|
+
if (!channel) return 'No active channel found.';
|
|
1483
|
+
|
|
1484
|
+
const API = 'https://nothumanallowed.com/api/v1/alexandria';
|
|
1485
|
+
const channelKey = crypto.default.createHash('sha256').update('alexandria-e2e-key-v2').update(channel.id).update(channel.secret || '').digest();
|
|
1486
|
+
const nonce = crypto.default.randomBytes(12);
|
|
1487
|
+
const cipher = crypto.default.createCipheriv('aes-256-gcm', channelKey, nonce);
|
|
1488
|
+
const encrypted = Buffer.concat([cipher.update(msg, 'utf-8'), cipher.final()]);
|
|
1489
|
+
const tag = cipher.getAuthTag();
|
|
1490
|
+
const ciphertext = Buffer.concat([encrypted, tag]).toString('base64');
|
|
1491
|
+
|
|
1492
|
+
const r = await fetch(API + '/channels/' + channel.id + '/messages', {
|
|
1493
|
+
method: 'POST',
|
|
1494
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1495
|
+
body: JSON.stringify({ senderFingerprint: identity.fingerprint, nonce: nonce.toString('base64'), ciphertext, type: 'text' }),
|
|
1496
|
+
});
|
|
1497
|
+
|
|
1498
|
+
if (!r.ok) return `Failed to send: ${r.status}`;
|
|
1499
|
+
return `Message sent to "${channel.name}" (encrypted). Other members will see it in real-time.`;
|
|
1500
|
+
} catch (e) {
|
|
1501
|
+
return `Failed to send: ${e.message}`;
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1446
1505
|
default:
|
|
1447
1506
|
return `Unknown action: ${action}`;
|
|
1448
1507
|
}
|