nothumanallowed 10.9.0 → 10.9.1
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/constants.mjs +1 -1
- package/src/services/tool-executor.mjs +63 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "10.9.
|
|
3
|
+
"version": "10.9.1",
|
|
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/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.9.
|
|
8
|
+
export const VERSION = '10.9.1';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -372,6 +372,11 @@ TOOLS:
|
|
|
372
372
|
Use this when the user asks to notify collaborators, share progress, or send a message to other agents/team members.
|
|
373
373
|
If channel is not specified, sends to the active channel.
|
|
374
374
|
|
|
375
|
+
67. collab_read(channel?: string, limit?: number)
|
|
376
|
+
Read and decrypt messages from an Alexandria channel. Returns the latest messages (default 20).
|
|
377
|
+
Use this when the user asks to check messages, read a conversation, or see what others wrote.
|
|
378
|
+
If channel is not specified, reads from the active channel. Channel can be an ID or a name.
|
|
379
|
+
|
|
375
380
|
RULES:
|
|
376
381
|
- 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.
|
|
377
382
|
- CRITICAL: For web searches, ALWAYS use web_search — NEVER open Google/Bing/DuckDuckGo in the browser.
|
|
@@ -1502,6 +1507,64 @@ export async function executeTool(action, params, config) {
|
|
|
1502
1507
|
}
|
|
1503
1508
|
}
|
|
1504
1509
|
|
|
1510
|
+
case 'collab_read': {
|
|
1511
|
+
try {
|
|
1512
|
+
const fs2 = await import('fs');
|
|
1513
|
+
const path2 = await import('path');
|
|
1514
|
+
const crypto2 = await import('crypto');
|
|
1515
|
+
const os2 = await import('os');
|
|
1516
|
+
const NHA2 = path2.default.join(os2.default.homedir(), '.nha');
|
|
1517
|
+
const chFile2 = path2.default.join(NHA2, 'collab', 'channels.json');
|
|
1518
|
+
const idFile2 = path2.default.join(NHA2, 'collab', 'identity.json');
|
|
1519
|
+
|
|
1520
|
+
if (!fs2.default.existsSync(chFile2) || !fs2.default.existsSync(idFile2)) {
|
|
1521
|
+
return 'No Alexandria channels configured.';
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
const channels2 = JSON.parse(fs2.default.readFileSync(chFile2, 'utf-8'));
|
|
1525
|
+
const identity2 = JSON.parse(fs2.default.readFileSync(idFile2, 'utf-8'));
|
|
1526
|
+
const channel2 = params.channel
|
|
1527
|
+
? channels2.find(c => c.name?.toLowerCase().includes(params.channel.toLowerCase()) || c.id === params.channel || c.id.startsWith(params.channel))
|
|
1528
|
+
: channels2.find(c => c.active) || channels2[0];
|
|
1529
|
+
|
|
1530
|
+
if (!channel2) return 'No matching channel found.';
|
|
1531
|
+
|
|
1532
|
+
const AAPI = 'https://nothumanallowed.com/api/v1/alexandria';
|
|
1533
|
+
const r2 = await fetch(AAPI + '/channels/' + channel2.id + '/messages?fp=' + identity2.fingerprint);
|
|
1534
|
+
if (!r2.ok) return 'Channel not found or expired.';
|
|
1535
|
+
const data2 = await r2.json();
|
|
1536
|
+
if (!data2.messages || data2.messages.length === 0) return `No messages in "${channel2.name}".`;
|
|
1537
|
+
|
|
1538
|
+
const cKey = crypto2.default.createHash('sha256').update('alexandria-e2e-key-v2').update(channel2.id).update(channel2.secret || '').digest();
|
|
1539
|
+
const lim = params.limit || 20;
|
|
1540
|
+
const msgs2 = data2.messages.slice(-lim);
|
|
1541
|
+
const lines = [`Channel: ${channel2.name} (${data2.messages.length} total)\n`];
|
|
1542
|
+
|
|
1543
|
+
for (const msg of msgs2) {
|
|
1544
|
+
if (msg.type === 'system') { lines.push('[system] member joined'); continue; }
|
|
1545
|
+
let content = '[encrypted]';
|
|
1546
|
+
if (msg.ciphertext && msg.nonce) {
|
|
1547
|
+
try {
|
|
1548
|
+
const nonce = Buffer.from(msg.nonce, 'base64');
|
|
1549
|
+
const raw = Buffer.from(msg.ciphertext, 'base64');
|
|
1550
|
+
const tag = raw.subarray(raw.length - 16);
|
|
1551
|
+
const enc = raw.subarray(0, raw.length - 16);
|
|
1552
|
+
const dec = crypto2.default.createDecipheriv('aes-256-gcm', cKey, nonce);
|
|
1553
|
+
dec.setAuthTag(tag);
|
|
1554
|
+
content = dec.update(enc) + dec.final('utf-8');
|
|
1555
|
+
} catch {}
|
|
1556
|
+
}
|
|
1557
|
+
const sender = data2.members?.find(m => m.fingerprint === msg.senderFingerprint);
|
|
1558
|
+
const time = new Date(msg.timestamp).toLocaleTimeString();
|
|
1559
|
+
lines.push(`[${time}] ${sender?.displayName || '?'}: ${content}`);
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
return lines.join('\n');
|
|
1563
|
+
} catch (e) {
|
|
1564
|
+
return `Failed to read: ${e.message}`;
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1505
1568
|
default:
|
|
1506
1569
|
return `Unknown action: ${action}`;
|
|
1507
1570
|
}
|