open-agents-ai 0.82.0 → 0.84.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/dist/index.js +250 -6
- package/package.json +2 -2
- package/prompts/agentic/system-large.md +21 -3
- package/prompts/agentic/system-medium.md +1 -1
package/dist/index.js
CHANGED
|
@@ -11223,12 +11223,13 @@ var init_nexus = __esm({
|
|
|
11223
11223
|
/**
|
|
11224
11224
|
* nexus-daemon.mjs \u2014 Standalone nexus process with real TCP/UDP sockets.
|
|
11225
11225
|
* Spawned by the open-agents nexus tool. Communicates via JSON files.
|
|
11226
|
+
* v1.5.0: capability registration, peer blocking, metering, room members.
|
|
11226
11227
|
*
|
|
11227
11228
|
* Usage: node nexus-daemon.mjs <nexus-dir> <agent-name> [agent-type]
|
|
11228
11229
|
*/
|
|
11229
11230
|
|
|
11230
|
-
import { NexusClient } from 'open-agents-nexus';
|
|
11231
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync, readdirSync } from 'node:fs';
|
|
11231
|
+
import { NexusClient, createFileAuditHook } from 'open-agents-nexus';
|
|
11232
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync, readdirSync, appendFileSync } from 'node:fs';
|
|
11232
11233
|
import { join } from 'node:path';
|
|
11233
11234
|
|
|
11234
11235
|
const nexusDir = process.argv[2];
|
|
@@ -11239,8 +11240,11 @@ const respFile = join(nexusDir, 'resp.json');
|
|
|
11239
11240
|
const statusFile = join(nexusDir, 'status.json');
|
|
11240
11241
|
const inboxDir = join(nexusDir, 'inbox');
|
|
11241
11242
|
const pidFile = join(nexusDir, 'daemon.pid');
|
|
11243
|
+
const invocationsDir = join(nexusDir, 'invocations');
|
|
11244
|
+
const meteringFile = join(nexusDir, 'metering.jsonl');
|
|
11242
11245
|
|
|
11243
11246
|
mkdirSync(inboxDir, { recursive: true });
|
|
11247
|
+
mkdirSync(invocationsDir, { recursive: true });
|
|
11244
11248
|
|
|
11245
11249
|
// Write PID so the agent can kill us
|
|
11246
11250
|
writeFileSync(pidFile, String(process.pid));
|
|
@@ -11257,12 +11261,16 @@ const nexus = new NexusClient({
|
|
|
11257
11261
|
natsServers: ['wss://demo.nats.io:8443'],
|
|
11258
11262
|
enableCircuitRelay: true,
|
|
11259
11263
|
usePublicBootstrap: true,
|
|
11264
|
+
trustPolicy: { denylist: [], allowlist: [] },
|
|
11260
11265
|
});
|
|
11261
11266
|
|
|
11262
11267
|
const rooms = new Map();
|
|
11263
11268
|
let connected = false;
|
|
11269
|
+
const blockedPeers = [];
|
|
11264
11270
|
|
|
11265
11271
|
function writeStatus(extra = {}) {
|
|
11272
|
+
const caps = typeof nexus.getRegisteredCapabilities === 'function'
|
|
11273
|
+
? nexus.getRegisteredCapabilities() : [];
|
|
11266
11274
|
const data = {
|
|
11267
11275
|
pid: process.pid,
|
|
11268
11276
|
connected,
|
|
@@ -11270,6 +11278,8 @@ function writeStatus(extra = {}) {
|
|
|
11270
11278
|
agentName,
|
|
11271
11279
|
agentType,
|
|
11272
11280
|
rooms: [...rooms.keys()],
|
|
11281
|
+
capabilities: caps,
|
|
11282
|
+
blockedPeers,
|
|
11273
11283
|
connectedAt: connected ? new Date().toISOString() : null,
|
|
11274
11284
|
...extra,
|
|
11275
11285
|
};
|
|
@@ -11289,6 +11299,7 @@ async function handleCmd(cmd) {
|
|
|
11289
11299
|
if (rooms.has(roomId)) { writeResp(id, { ok: true, output: 'Already in room: ' + roomId }); return; }
|
|
11290
11300
|
const room = await nexus.joinRoom(roomId);
|
|
11291
11301
|
rooms.set(roomId, room);
|
|
11302
|
+
// Per-room message listener (also captured by client-level event)
|
|
11292
11303
|
room.on('message', (msg) => {
|
|
11293
11304
|
const roomInbox = join(inboxDir, roomId);
|
|
11294
11305
|
mkdirSync(roomInbox, { recursive: true });
|
|
@@ -11302,6 +11313,15 @@ async function handleCmd(cmd) {
|
|
|
11302
11313
|
};
|
|
11303
11314
|
try { writeFileSync(join(roomInbox, fname), JSON.stringify(entry, null, 2)); } catch {}
|
|
11304
11315
|
});
|
|
11316
|
+
// v1.5.0: Room member tracking
|
|
11317
|
+
if (room.on) {
|
|
11318
|
+
room.on('member:join', (member) => {
|
|
11319
|
+
console.log('Member joined ' + roomId + ': ' + (member.agentName || member.peerId));
|
|
11320
|
+
});
|
|
11321
|
+
room.on('member:leave', (member) => {
|
|
11322
|
+
console.log('Member left ' + roomId + ': ' + (member.agentName || member.peerId));
|
|
11323
|
+
});
|
|
11324
|
+
}
|
|
11305
11325
|
writeStatus();
|
|
11306
11326
|
writeResp(id, { ok: true, output: 'Joined room: ' + roomId });
|
|
11307
11327
|
break;
|
|
@@ -11372,6 +11392,165 @@ async function handleCmd(cmd) {
|
|
|
11372
11392
|
writeResp(id, { ok: true, output: JSON.stringify(data, null, 2) });
|
|
11373
11393
|
break;
|
|
11374
11394
|
}
|
|
11395
|
+
|
|
11396
|
+
// \u2500\u2500 v1.5.0: Capability Registration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
11397
|
+
case 'register_capability': {
|
|
11398
|
+
const name = args.capability;
|
|
11399
|
+
if (!name) { writeResp(id, { ok: false, output: 'capability name is required' }); return; }
|
|
11400
|
+
if (typeof nexus.registerCapability !== 'function') {
|
|
11401
|
+
writeResp(id, { ok: false, output: 'registerCapability not available (nexus version too old)' });
|
|
11402
|
+
return;
|
|
11403
|
+
}
|
|
11404
|
+
nexus.registerCapability(name, async (request, stream) => {
|
|
11405
|
+
// Log inbound invocation
|
|
11406
|
+
const logEntry = {
|
|
11407
|
+
ts: Date.now(),
|
|
11408
|
+
from: request.from || 'unknown',
|
|
11409
|
+
capability: request.capability || name,
|
|
11410
|
+
requestId: request.requestId,
|
|
11411
|
+
};
|
|
11412
|
+
const logFile = join(invocationsDir, Date.now() + '-' + name + '.json');
|
|
11413
|
+
try { writeFileSync(logFile, JSON.stringify(logEntry, null, 2)); } catch {}
|
|
11414
|
+
|
|
11415
|
+
// Collect input chunks
|
|
11416
|
+
let inputData = '';
|
|
11417
|
+
stream.onData((msg) => {
|
|
11418
|
+
if (msg.type === 'invoke.chunk') {
|
|
11419
|
+
inputData += (typeof msg.data === 'string' ? msg.data : JSON.stringify(msg.data));
|
|
11420
|
+
}
|
|
11421
|
+
});
|
|
11422
|
+
|
|
11423
|
+
// Accept the invocation
|
|
11424
|
+
await stream.write({
|
|
11425
|
+
type: 'invoke.accept', version: 1,
|
|
11426
|
+
requestId: request.requestId, accepted: true,
|
|
11427
|
+
});
|
|
11428
|
+
|
|
11429
|
+
// Send event with acknowledgment
|
|
11430
|
+
await stream.write({
|
|
11431
|
+
type: 'invoke.event', version: 1,
|
|
11432
|
+
requestId: request.requestId, seq: 0,
|
|
11433
|
+
event: 'ack', data: agentName + ' received invocation for ' + name,
|
|
11434
|
+
});
|
|
11435
|
+
|
|
11436
|
+
// Complete
|
|
11437
|
+
await stream.write({
|
|
11438
|
+
type: 'invoke.done', version: 1,
|
|
11439
|
+
requestId: request.requestId,
|
|
11440
|
+
usage: { inputBytes: inputData.length, outputBytes: 0 },
|
|
11441
|
+
});
|
|
11442
|
+
stream.close();
|
|
11443
|
+
});
|
|
11444
|
+
writeStatus();
|
|
11445
|
+
writeResp(id, { ok: true, output: 'Capability registered: ' + name + '. Now advertised via NATS.' });
|
|
11446
|
+
break;
|
|
11447
|
+
}
|
|
11448
|
+
case 'unregister_capability': {
|
|
11449
|
+
const name = args.capability;
|
|
11450
|
+
if (!name) { writeResp(id, { ok: false, output: 'capability name is required' }); return; }
|
|
11451
|
+
if (typeof nexus.unregisterCapability === 'function') {
|
|
11452
|
+
nexus.unregisterCapability(name);
|
|
11453
|
+
}
|
|
11454
|
+
writeStatus();
|
|
11455
|
+
writeResp(id, { ok: true, output: 'Capability unregistered: ' + name });
|
|
11456
|
+
break;
|
|
11457
|
+
}
|
|
11458
|
+
case 'list_capabilities': {
|
|
11459
|
+
const caps = typeof nexus.getRegisteredCapabilities === 'function'
|
|
11460
|
+
? nexus.getRegisteredCapabilities() : [];
|
|
11461
|
+
writeResp(id, { ok: true, output: caps.length ? 'Capabilities: ' + caps.join(', ') : 'No capabilities registered.' });
|
|
11462
|
+
break;
|
|
11463
|
+
}
|
|
11464
|
+
|
|
11465
|
+
// \u2500\u2500 v1.5.0: Peer Blocking \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
11466
|
+
case 'block_peer': {
|
|
11467
|
+
const peerId = args.target_peer || args.peer_id;
|
|
11468
|
+
if (!peerId) { writeResp(id, { ok: false, output: 'peer_id or target_peer is required' }); return; }
|
|
11469
|
+
if (typeof nexus.blockPeer === 'function') {
|
|
11470
|
+
nexus.blockPeer(peerId);
|
|
11471
|
+
}
|
|
11472
|
+
if (!blockedPeers.includes(peerId)) blockedPeers.push(peerId);
|
|
11473
|
+
writeStatus();
|
|
11474
|
+
writeResp(id, { ok: true, output: 'Blocked peer: ' + peerId.slice(0, 20) + '...' });
|
|
11475
|
+
break;
|
|
11476
|
+
}
|
|
11477
|
+
case 'unblock_peer': {
|
|
11478
|
+
const peerId = args.target_peer || args.peer_id;
|
|
11479
|
+
if (!peerId) { writeResp(id, { ok: false, output: 'peer_id or target_peer is required' }); return; }
|
|
11480
|
+
if (typeof nexus.unblockPeer === 'function') {
|
|
11481
|
+
nexus.unblockPeer(peerId);
|
|
11482
|
+
}
|
|
11483
|
+
const idx = blockedPeers.indexOf(peerId);
|
|
11484
|
+
if (idx >= 0) blockedPeers.splice(idx, 1);
|
|
11485
|
+
writeStatus();
|
|
11486
|
+
writeResp(id, { ok: true, output: 'Unblocked peer: ' + peerId.slice(0, 20) + '...' });
|
|
11487
|
+
break;
|
|
11488
|
+
}
|
|
11489
|
+
|
|
11490
|
+
// \u2500\u2500 v1.5.0: Metering \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
11491
|
+
case 'metering_status': {
|
|
11492
|
+
if (!nexus.metering) {
|
|
11493
|
+
writeResp(id, { ok: true, output: 'Metering not available (nexus version too old).' });
|
|
11494
|
+
return;
|
|
11495
|
+
}
|
|
11496
|
+
const filter = {};
|
|
11497
|
+
if (args.peer_id) filter.peerId = args.peer_id;
|
|
11498
|
+
if (args.capability) filter.service = args.capability;
|
|
11499
|
+
|
|
11500
|
+
// Try per-peer summary first
|
|
11501
|
+
if (args.peer_id && typeof nexus.metering.getSummary === 'function') {
|
|
11502
|
+
const summary = nexus.metering.getSummary(args.peer_id);
|
|
11503
|
+
if (summary) {
|
|
11504
|
+
writeResp(id, { ok: true, output: JSON.stringify(summary, null, 2) });
|
|
11505
|
+
return;
|
|
11506
|
+
}
|
|
11507
|
+
}
|
|
11508
|
+
|
|
11509
|
+
// All summaries
|
|
11510
|
+
if (typeof nexus.metering.getAllSummaries === 'function') {
|
|
11511
|
+
const all = nexus.metering.getAllSummaries();
|
|
11512
|
+
if (all && (all.size > 0 || Object.keys(all).length > 0)) {
|
|
11513
|
+
const entries = all instanceof Map ? Object.fromEntries(all) : all;
|
|
11514
|
+
writeResp(id, { ok: true, output: 'Metering summaries:\\n' + JSON.stringify(entries, null, 2) });
|
|
11515
|
+
return;
|
|
11516
|
+
}
|
|
11517
|
+
}
|
|
11518
|
+
|
|
11519
|
+
// Fall back to raw records
|
|
11520
|
+
if (typeof nexus.metering.getRecords === 'function') {
|
|
11521
|
+
const records = nexus.metering.getRecords(filter);
|
|
11522
|
+
writeResp(id, { ok: true, output: 'Records: ' + records.length + '\\n' + JSON.stringify(records.slice(-10), null, 2) });
|
|
11523
|
+
return;
|
|
11524
|
+
}
|
|
11525
|
+
|
|
11526
|
+
writeResp(id, { ok: true, output: 'No metering data yet.' });
|
|
11527
|
+
break;
|
|
11528
|
+
}
|
|
11529
|
+
|
|
11530
|
+
// \u2500\u2500 v1.5.0: Room Members \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
11531
|
+
case 'room_members': {
|
|
11532
|
+
const roomId = args.room_id;
|
|
11533
|
+
if (!roomId) { writeResp(id, { ok: false, output: 'room_id is required' }); return; }
|
|
11534
|
+
const room = rooms.get(roomId);
|
|
11535
|
+
if (!room) { writeResp(id, { ok: false, output: 'Not in room: ' + roomId }); return; }
|
|
11536
|
+
|
|
11537
|
+
const members = room.members || [];
|
|
11538
|
+
if (members.length === 0) {
|
|
11539
|
+
writeResp(id, { ok: true, output: 'No members tracked in room: ' + roomId });
|
|
11540
|
+
return;
|
|
11541
|
+
}
|
|
11542
|
+
const lines = ['Members in ' + roomId + ' (' + members.length + '):'];
|
|
11543
|
+
for (const m of members) {
|
|
11544
|
+
const name = m.agentName || 'unknown';
|
|
11545
|
+
const type = m.agentType || '?';
|
|
11546
|
+
const caps = m.capabilities?.join(', ') || 'none';
|
|
11547
|
+
const status = m.status || 'active';
|
|
11548
|
+
lines.push(' ' + m.peerId.slice(0, 16) + '... ' + name + ' (' + type + ') [' + status + '] caps: ' + caps);
|
|
11549
|
+
}
|
|
11550
|
+
writeResp(id, { ok: true, output: lines.join('\\n') });
|
|
11551
|
+
break;
|
|
11552
|
+
}
|
|
11553
|
+
|
|
11375
11554
|
case 'ping': {
|
|
11376
11555
|
writeResp(id, { ok: true, output: 'pong' });
|
|
11377
11556
|
break;
|
|
@@ -11418,6 +11597,41 @@ process.on('unhandledRejection', (reason) => {
|
|
|
11418
11597
|
await node.start();
|
|
11419
11598
|
}
|
|
11420
11599
|
connected = true;
|
|
11600
|
+
|
|
11601
|
+
// v1.5.0: Setup metering audit hook
|
|
11602
|
+
try {
|
|
11603
|
+
if (nexus.metering && typeof nexus.metering.addHook === 'function') {
|
|
11604
|
+
nexus.metering.addHook(createFileAuditHook(meteringFile));
|
|
11605
|
+
}
|
|
11606
|
+
} catch {}
|
|
11607
|
+
|
|
11608
|
+
// v1.5.0: Client-level events for global message/DM/invoke routing
|
|
11609
|
+
try {
|
|
11610
|
+
if (typeof nexus.on === 'function') {
|
|
11611
|
+
nexus.on('message', ({ roomId, message }) => {
|
|
11612
|
+
// Already handled by per-room listener, but log globally
|
|
11613
|
+
console.log('[msg] ' + roomId + ' from ' + (message?.sender || '?').slice(0, 16));
|
|
11614
|
+
});
|
|
11615
|
+
nexus.on('dm', ({ from, content, format, messageId }) => {
|
|
11616
|
+
// Log DMs to inbox/dm/
|
|
11617
|
+
const dmDir = join(inboxDir, '_dm');
|
|
11618
|
+
mkdirSync(dmDir, { recursive: true });
|
|
11619
|
+
const entry = {
|
|
11620
|
+
sender: from,
|
|
11621
|
+
content: content || '',
|
|
11622
|
+
format: format || 'text/plain',
|
|
11623
|
+
timestamp: Date.now(),
|
|
11624
|
+
id: messageId,
|
|
11625
|
+
};
|
|
11626
|
+
try { writeFileSync(join(dmDir, Date.now() + '.json'), JSON.stringify(entry, null, 2)); } catch {}
|
|
11627
|
+
console.log('[dm] from ' + (from || '?').slice(0, 16));
|
|
11628
|
+
});
|
|
11629
|
+
nexus.on('invoke', ({ from, capability, requestId }) => {
|
|
11630
|
+
console.log('[invoke] ' + capability + ' from ' + (from || '?').slice(0, 16) + ' req=' + requestId);
|
|
11631
|
+
});
|
|
11632
|
+
}
|
|
11633
|
+
} catch {}
|
|
11634
|
+
|
|
11421
11635
|
writeStatus();
|
|
11422
11636
|
console.log('Nexus daemon connected as ' + nexus.peerId);
|
|
11423
11637
|
} catch (err) {
|
|
@@ -11445,7 +11659,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
11445
11659
|
];
|
|
11446
11660
|
NexusTool = class {
|
|
11447
11661
|
name = "nexus";
|
|
11448
|
-
description = "Decentralized agent-to-agent communication via open-agents-nexus v1.
|
|
11662
|
+
description = "Decentralized agent-to-agent communication via open-agents-nexus v1.5.0. Spawns a background Node.js process with real network sockets for libp2p + NATS P2P mesh. Simple flow: connect \u2192 join room \u2192 send messages. Auto-installs/updates nexus if needed. v1.5.0: register_capability (serve invocations), block_peer/unblock_peer (trust policy), metering_status (usage tracking), room_members (live member tracking). Also supports direct peer invoke (streaming inference), IPFS content storage, direct messages, peer discovery, x402 micropayments, and inference proofs.";
|
|
11449
11663
|
parameters = {
|
|
11450
11664
|
type: "object",
|
|
11451
11665
|
properties: {
|
|
@@ -11468,7 +11682,14 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
11468
11682
|
"retrieve_content",
|
|
11469
11683
|
"wallet_status",
|
|
11470
11684
|
"wallet_create",
|
|
11471
|
-
"inference_proof"
|
|
11685
|
+
"inference_proof",
|
|
11686
|
+
"register_capability",
|
|
11687
|
+
"unregister_capability",
|
|
11688
|
+
"list_capabilities",
|
|
11689
|
+
"block_peer",
|
|
11690
|
+
"unblock_peer",
|
|
11691
|
+
"metering_status",
|
|
11692
|
+
"room_members"
|
|
11472
11693
|
],
|
|
11473
11694
|
description: "The nexus action to perform"
|
|
11474
11695
|
},
|
|
@@ -11588,6 +11809,27 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
11588
11809
|
case "inference_proof":
|
|
11589
11810
|
result = await this.doInferenceProof();
|
|
11590
11811
|
break;
|
|
11812
|
+
case "register_capability":
|
|
11813
|
+
result = await this.sendDaemonCmd("register_capability", args);
|
|
11814
|
+
break;
|
|
11815
|
+
case "unregister_capability":
|
|
11816
|
+
result = await this.sendDaemonCmd("unregister_capability", args);
|
|
11817
|
+
break;
|
|
11818
|
+
case "list_capabilities":
|
|
11819
|
+
result = await this.sendDaemonCmd("list_capabilities", args);
|
|
11820
|
+
break;
|
|
11821
|
+
case "block_peer":
|
|
11822
|
+
result = await this.sendDaemonCmd("block_peer", args);
|
|
11823
|
+
break;
|
|
11824
|
+
case "unblock_peer":
|
|
11825
|
+
result = await this.sendDaemonCmd("unblock_peer", args);
|
|
11826
|
+
break;
|
|
11827
|
+
case "metering_status":
|
|
11828
|
+
result = await this.sendDaemonCmd("metering_status", args);
|
|
11829
|
+
break;
|
|
11830
|
+
case "room_members":
|
|
11831
|
+
result = await this.sendDaemonCmd("room_members", args);
|
|
11832
|
+
break;
|
|
11591
11833
|
default:
|
|
11592
11834
|
return { success: false, output: "", error: `Unknown nexus action: ${action}`, durationMs: Date.now() - start };
|
|
11593
11835
|
}
|
|
@@ -11812,12 +12054,14 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
11812
12054
|
try {
|
|
11813
12055
|
const status = JSON.parse(await readFile13(statusFile, "utf8"));
|
|
11814
12056
|
const lines = [
|
|
11815
|
-
`Nexus Status`,
|
|
12057
|
+
`Nexus Status (v1.5.0)`,
|
|
11816
12058
|
` Connected: ${status.connected}`,
|
|
11817
12059
|
` Peer ID: ${status.peerId || "n/a"}`,
|
|
11818
12060
|
` Agent: ${status.agentName} (${status.agentType})`,
|
|
11819
12061
|
` Daemon PID: ${status.pid}`,
|
|
11820
|
-
` Rooms: ${status.rooms?.length || 0} [${(status.rooms || []).join(", ")}]
|
|
12062
|
+
` Rooms: ${status.rooms?.length || 0} [${(status.rooms || []).join(", ")}]`,
|
|
12063
|
+
` Capabilities: ${(status.capabilities || []).length ? (status.capabilities || []).join(", ") : "none"}`,
|
|
12064
|
+
` Blocked peers: ${(status.blockedPeers || []).length || 0}`
|
|
11821
12065
|
];
|
|
11822
12066
|
const walletPath = join28(this.nexusDir, "wallet.enc");
|
|
11823
12067
|
if (existsSync21(walletPath)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "open-agents-ai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.84.0",
|
|
4
4
|
"description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -70,6 +70,6 @@
|
|
|
70
70
|
},
|
|
71
71
|
"optionalDependencies": {
|
|
72
72
|
"moondream": "^0.2.0",
|
|
73
|
-
"open-agents-nexus": "^1.
|
|
73
|
+
"open-agents-nexus": "^1.5.0"
|
|
74
74
|
}
|
|
75
75
|
}
|
|
@@ -26,7 +26,7 @@ If a tool fails, try a different approach. If you're unsure, explore with your t
|
|
|
26
26
|
- web_fetch: Fetch a web page and extract text content (for docs, MDN, w3schools.com, etc.)
|
|
27
27
|
- memory_read: Read from persistent memory (learned patterns, solutions)
|
|
28
28
|
- memory_write: Store a fact, pattern, or solution in persistent memory for future tasks
|
|
29
|
-
- nexus: P2P agent networking (libp2p + NATS + IPFS). Connect to other agents, join rooms, send messages, discover peers, invoke capabilities, store content, manage wallet. Actions: connect, disconnect, status, join_room, leave_room, send_message, read_messages, discover_peers, list_rooms, send_dm, find_agent, invoke_capability, store_content, retrieve_content, wallet_status, wallet_create, inference_proof.
|
|
29
|
+
- nexus: P2P agent networking (libp2p + NATS + IPFS). Connect to other agents, join rooms, send messages, discover peers, invoke capabilities, store content, manage wallet. Actions: connect, disconnect, status, join_room, leave_room, send_message, read_messages, discover_peers, list_rooms, send_dm, find_agent, invoke_capability, store_content, retrieve_content, wallet_status, wallet_create, inference_proof, register_capability, unregister_capability, list_capabilities, block_peer, unblock_peer, metering_status, room_members.
|
|
30
30
|
- task_complete: Signal task completion with a summary
|
|
31
31
|
|
|
32
32
|
## Parallel Execution & Sub-Agents
|
|
@@ -185,7 +185,7 @@ If you notice you're performing the SAME multi-step sequence for the 3rd time or
|
|
|
185
185
|
- Test the tool mentally before creating — ensure the steps would work in order
|
|
186
186
|
- Prefer 'project' scope unless the pattern genuinely applies to all projects
|
|
187
187
|
|
|
188
|
-
## Nexus P2P Networking (v1.
|
|
188
|
+
## Nexus P2P Networking (v1.5.0) — Decentralized Agent Communication
|
|
189
189
|
|
|
190
190
|
You HAVE the nexus tool. It is one of your registered tools. USE IT when asked about connecting, messaging, or networking with other agents.
|
|
191
191
|
|
|
@@ -234,11 +234,29 @@ Use invoke_capability for real work (inference, tool calls) — NOT room message
|
|
|
234
234
|
nexus(action='wallet_create')
|
|
235
235
|
nexus(action='inference_proof')
|
|
236
236
|
|
|
237
|
+
### v1.5.0: Serve Capabilities
|
|
238
|
+
nexus(action='register_capability', capability='text-generation') — register handler for incoming invocations
|
|
239
|
+
nexus(action='unregister_capability', capability='text-generation')
|
|
240
|
+
nexus(action='list_capabilities') — list registered capability names
|
|
241
|
+
|
|
242
|
+
### v1.5.0: Trust & Blocking
|
|
243
|
+
nexus(action='block_peer', target_peer='12D3KooW...') — blocks invoke + DM from peer
|
|
244
|
+
nexus(action='unblock_peer', target_peer='12D3KooW...')
|
|
245
|
+
|
|
246
|
+
### v1.5.0: Usage Metering
|
|
247
|
+
nexus(action='metering_status') — all peer summaries
|
|
248
|
+
nexus(action='metering_status', peer_id='12D3KooW...') — per-peer summary
|
|
249
|
+
nexus(action='metering_status', capability='chat') — filter by service
|
|
250
|
+
|
|
251
|
+
### v1.5.0: Room Members
|
|
252
|
+
nexus(action='room_members', room_id='general') — live member list with capabilities
|
|
253
|
+
|
|
237
254
|
SECURITY: Wallet private keys are AES-256-GCM encrypted and NEVER accessible to you.
|
|
238
255
|
All outbound messages are scanned for key material leaks.
|
|
239
256
|
|
|
240
257
|
When the user asks about expanding capabilities or connecting with other agents, suggest
|
|
241
|
-
enabling nexus networking. Use
|
|
258
|
+
enabling nexus networking. Use register_capability to serve invocations, inference_proof
|
|
259
|
+
to benchmark, and room_members to discover who's online.
|
|
242
260
|
|
|
243
261
|
## Temporal Agency — Scheduling, Reminders & Long-Horizon Tasks
|
|
244
262
|
|
|
@@ -17,7 +17,7 @@ NEVER say "I can't do that". ALWAYS attempt the task using your tools. If a tool
|
|
|
17
17
|
- web_search: Search the web
|
|
18
18
|
- web_fetch: Fetch a web page's text
|
|
19
19
|
- memory_read / memory_write: Persistent memory across sessions
|
|
20
|
-
- nexus: P2P agent networking (connect, join_room, send_message, discover_peers, invoke_capability, wallet, etc.)
|
|
20
|
+
- nexus: P2P agent networking (connect, join_room, send_message, discover_peers, invoke_capability, register_capability, block_peer, metering_status, room_members, wallet, etc.)
|
|
21
21
|
- task_complete: Signal completion with a summary
|
|
22
22
|
- background_run / task_status / task_output / task_stop: Background tasks
|
|
23
23
|
- batch_edit: Multiple edits across files in one call
|