open-agents-ai 0.103.28 → 0.103.29
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 +219 -22
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12206,7 +12206,43 @@ async function handleCmd(cmd) {
|
|
|
12206
12206
|
const node = nexus.network?.node;
|
|
12207
12207
|
const peers = node?.getPeers?.() || [];
|
|
12208
12208
|
const list = peers.slice(0, 20).map(p => p.toString?.() || String(p));
|
|
12209
|
-
|
|
12209
|
+
// Include NATS-discovered peers with capabilities
|
|
12210
|
+
var dpNatsFile = join(nexusDir, 'discovered-peers.json');
|
|
12211
|
+
var dpNats = {};
|
|
12212
|
+
try { if (existsSync(dpNatsFile)) dpNats = JSON.parse(readFileSync(dpNatsFile, 'utf8')); } catch {}
|
|
12213
|
+
var dpNatsCount = Object.keys(dpNats).length;
|
|
12214
|
+
var dpLines = ['Connected peers: ' + list.length];
|
|
12215
|
+
for (var dpi = 0; dpi < list.length; dpi++) {
|
|
12216
|
+
dpLines.push(' ' + list[dpi]);
|
|
12217
|
+
}
|
|
12218
|
+
if (dpNatsCount > 0) {
|
|
12219
|
+
dpLines.push('NATS-discovered peers: ' + dpNatsCount);
|
|
12220
|
+
for (var dpKey of Object.keys(dpNats)) {
|
|
12221
|
+
var dpEntry = dpNats[dpKey];
|
|
12222
|
+
var dpAge = Math.round((Date.now() - dpEntry.lastSeen) / 1000);
|
|
12223
|
+
dpLines.push(' ' + dpKey.slice(0, 20) + '... (' + dpEntry.agentName + ') caps=' + (dpEntry.capabilities || []).length + ' seen=' + dpAge + 's ago');
|
|
12224
|
+
}
|
|
12225
|
+
}
|
|
12226
|
+
writeResp(id, { ok: true, output: dpLines.join('\\n') });
|
|
12227
|
+
break;
|
|
12228
|
+
}
|
|
12229
|
+
case 'discover_peer_caps': {
|
|
12230
|
+
var dpcPeerId = args.peer_id;
|
|
12231
|
+
if (!dpcPeerId) { writeResp(id, { ok: false, output: 'peer_id is required' }); return; }
|
|
12232
|
+
var dpcFile = join(nexusDir, 'discovered-peers.json');
|
|
12233
|
+
var dpcPeers = {};
|
|
12234
|
+
try { if (existsSync(dpcFile)) dpcPeers = JSON.parse(readFileSync(dpcFile, 'utf8')); } catch {}
|
|
12235
|
+
var dpcEntry = dpcPeers[String(dpcPeerId)];
|
|
12236
|
+
if (dpcEntry && dpcEntry.capabilities && dpcEntry.capabilities.length > 0) {
|
|
12237
|
+
var dpcAge = Date.now() - dpcEntry.lastSeen;
|
|
12238
|
+
if (dpcAge < 5 * 60 * 1000) { // 5 minute freshness
|
|
12239
|
+
writeResp(id, { ok: true, output: JSON.stringify(dpcEntry, null, 2) });
|
|
12240
|
+
} else {
|
|
12241
|
+
writeResp(id, { ok: false, output: 'Peer data stale (' + Math.round(dpcAge / 1000) + 's old). Wait for NATS re-announce.' });
|
|
12242
|
+
}
|
|
12243
|
+
} else {
|
|
12244
|
+
writeResp(id, { ok: false, output: 'Peer not found in NATS discovery cache. Peer may not have announced yet (announcements every 30s).' });
|
|
12245
|
+
}
|
|
12210
12246
|
break;
|
|
12211
12247
|
}
|
|
12212
12248
|
case 'list_rooms': {
|
|
@@ -12224,8 +12260,34 @@ async function handleCmd(cmd) {
|
|
|
12224
12260
|
case 'find_agent': {
|
|
12225
12261
|
const peerId = args.peer_id;
|
|
12226
12262
|
if (!peerId) { writeResp(id, { ok: false, output: 'peer_id is required' }); return; }
|
|
12227
|
-
|
|
12228
|
-
|
|
12263
|
+
try {
|
|
12264
|
+
var FIND_TIMEOUT = 15000;
|
|
12265
|
+
var findPromise = nexus.findAgent(peerId);
|
|
12266
|
+
var findTimeoutPromise = new Promise(function(resolve) { setTimeout(function() { resolve(null); }, FIND_TIMEOUT); });
|
|
12267
|
+
var profile = await Promise.race([findPromise, findTimeoutPromise]);
|
|
12268
|
+
writeResp(id, { ok: true, output: profile ? JSON.stringify(profile, null, 2) : 'Agent not found: ' + peerId });
|
|
12269
|
+
} catch (findErr) {
|
|
12270
|
+
writeResp(id, { ok: false, output: 'find_agent error: ' + (findErr.message || String(findErr)) });
|
|
12271
|
+
}
|
|
12272
|
+
break;
|
|
12273
|
+
}
|
|
12274
|
+
case 'query_peer_caps': {
|
|
12275
|
+
var qpcPeerId = args.peer_id;
|
|
12276
|
+
if (!qpcPeerId) { writeResp(id, { ok: false, output: 'peer_id is required' }); return; }
|
|
12277
|
+
dlog('query_peer_caps: peer=' + String(qpcPeerId).slice(0, 20));
|
|
12278
|
+
try {
|
|
12279
|
+
var QPC_TIMEOUT = 15000;
|
|
12280
|
+
var qpcInput = {};
|
|
12281
|
+
if (args.auth_key) qpcInput.auth_key = args.auth_key;
|
|
12282
|
+
var qpcPromise = nexus.invokeCapability(String(qpcPeerId), '__list_capabilities', qpcInput, { stream: false, maxDurationMs: 10000 });
|
|
12283
|
+
var qpcTimeoutPromise = new Promise(function(_, reject) { setTimeout(function() { reject(new Error('query_peer_caps timed out after 15s')); }, QPC_TIMEOUT); });
|
|
12284
|
+
var qpcResult = await Promise.race([qpcPromise, qpcTimeoutPromise]);
|
|
12285
|
+
dlog('query_peer_caps: SUCCESS');
|
|
12286
|
+
writeResp(id, { ok: true, output: typeof qpcResult === 'string' ? qpcResult : JSON.stringify(qpcResult, null, 2) });
|
|
12287
|
+
} catch (qpcErr) {
|
|
12288
|
+
dlog('query_peer_caps: ERROR ' + (qpcErr.message || String(qpcErr)));
|
|
12289
|
+
writeResp(id, { ok: false, output: 'query_peer_caps error: ' + (qpcErr.message || String(qpcErr)) });
|
|
12290
|
+
}
|
|
12229
12291
|
break;
|
|
12230
12292
|
}
|
|
12231
12293
|
case 'invoke_capability': {
|
|
@@ -12849,6 +12911,30 @@ async function handleCmd(cmd) {
|
|
|
12849
12911
|
dlog('system_metrics capability registered');
|
|
12850
12912
|
}
|
|
12851
12913
|
|
|
12914
|
+
// Register __list_capabilities \u2014 allows remote peers to discover available models
|
|
12915
|
+
if (typeof nexus.registerCapability === 'function') {
|
|
12916
|
+
nexus.registerCapability('__list_capabilities', async (request, stream) => {
|
|
12917
|
+
dlog('__list_capabilities invoked from ' + (request.from || 'unknown'));
|
|
12918
|
+
await stream.write({ type: 'invoke.accept', version: 1, requestId: request.requestId, accepted: true });
|
|
12919
|
+
var allCaps = typeof nexus.getRegisteredCapabilities === 'function' ? nexus.getRegisteredCapabilities() : [];
|
|
12920
|
+
var modelsInfo = [];
|
|
12921
|
+
for (var ci = 0; ci < pricingMenu.length; ci++) {
|
|
12922
|
+
var pm = pricingMenu[ci];
|
|
12923
|
+
modelsInfo.push({
|
|
12924
|
+
name: pm.model,
|
|
12925
|
+
parameterSize: pm.parameterSize || '',
|
|
12926
|
+
family: pm.family || '',
|
|
12927
|
+
quantization: pm.quantization || '',
|
|
12928
|
+
});
|
|
12929
|
+
}
|
|
12930
|
+
var capsPayload = JSON.stringify({ capabilities: allCaps, models: modelsInfo, agentName: agentName, peerId: nexus.peerId });
|
|
12931
|
+
await stream.write({ type: 'invoke.event', version: 1, requestId: request.requestId, seq: 0, event: 'result', data: capsPayload });
|
|
12932
|
+
await stream.write({ type: 'invoke.done', version: 1, requestId: request.requestId, usage: { inputBytes: 0, outputBytes: capsPayload.length } });
|
|
12933
|
+
stream.close();
|
|
12934
|
+
});
|
|
12935
|
+
dlog('__list_capabilities capability registered');
|
|
12936
|
+
}
|
|
12937
|
+
|
|
12852
12938
|
// Write pricing menu to file
|
|
12853
12939
|
const pricingFile = join(nexusDir, 'pricing.json');
|
|
12854
12940
|
writeFileSync(pricingFile, JSON.stringify({ updated: new Date().toISOString(), models: pricingMenu }, null, 2));
|
|
@@ -13014,6 +13100,35 @@ process.on('unhandledRejection', (reason) => {
|
|
|
13014
13100
|
}
|
|
13015
13101
|
} catch {}
|
|
13016
13102
|
|
|
13103
|
+
// Subscribe to NATS peer announcements \u2014 cache remote peer capabilities
|
|
13104
|
+
var discoveredPeers = {};
|
|
13105
|
+
var discoveredPeersFile = join(nexusDir, 'discovered-peers.json');
|
|
13106
|
+
try {
|
|
13107
|
+
if (existsSync(discoveredPeersFile)) {
|
|
13108
|
+
discoveredPeers = JSON.parse(readFileSync(discoveredPeersFile, 'utf8'));
|
|
13109
|
+
}
|
|
13110
|
+
} catch {}
|
|
13111
|
+
try {
|
|
13112
|
+
if (nexus.nats && typeof nexus.nats.subscribe === 'function') {
|
|
13113
|
+
nexus.nats.subscribe(function(announcement) {
|
|
13114
|
+
if (!announcement || !announcement.peerId) return;
|
|
13115
|
+
if (announcement.peerId === nexus.peerId) return; // skip self
|
|
13116
|
+
discoveredPeers[announcement.peerId] = {
|
|
13117
|
+
peerId: announcement.peerId,
|
|
13118
|
+
agentName: announcement.agentName || '',
|
|
13119
|
+
capabilities: announcement.capabilities || [],
|
|
13120
|
+
multiaddrs: announcement.multiaddrs || [],
|
|
13121
|
+
lastSeen: Date.now(),
|
|
13122
|
+
};
|
|
13123
|
+
try { writeFileSync(discoveredPeersFile, JSON.stringify(discoveredPeers, null, 2)); } catch {}
|
|
13124
|
+
dlog('NATS peer discovered: ' + String(announcement.peerId).slice(0, 20) + ' caps=' + (announcement.capabilities || []).length);
|
|
13125
|
+
});
|
|
13126
|
+
dlog('NATS peer discovery subscription active');
|
|
13127
|
+
}
|
|
13128
|
+
} catch (natsSubErr) {
|
|
13129
|
+
dlog('NATS subscribe failed: ' + (natsSubErr.message || natsSubErr));
|
|
13130
|
+
}
|
|
13131
|
+
|
|
13017
13132
|
writeStatus();
|
|
13018
13133
|
console.log('Nexus daemon connected as ' + nexus.peerId);
|
|
13019
13134
|
} catch (err) {
|
|
@@ -13215,6 +13330,9 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13215
13330
|
case "discover_peers":
|
|
13216
13331
|
result = await this.sendDaemonCmd("discover_peers", args);
|
|
13217
13332
|
break;
|
|
13333
|
+
case "discover_peer_caps":
|
|
13334
|
+
result = await this.sendDaemonCmd("discover_peer_caps", args, 5e3);
|
|
13335
|
+
break;
|
|
13218
13336
|
case "list_rooms":
|
|
13219
13337
|
result = await this.sendDaemonCmd("list_rooms", args);
|
|
13220
13338
|
break;
|
|
@@ -13224,6 +13342,9 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13224
13342
|
case "find_agent":
|
|
13225
13343
|
result = await this.sendDaemonCmd("find_agent", args, 3e4);
|
|
13226
13344
|
break;
|
|
13345
|
+
case "query_peer_caps":
|
|
13346
|
+
result = await this.sendDaemonCmd("query_peer_caps", args, 2e4);
|
|
13347
|
+
break;
|
|
13227
13348
|
case "invoke_capability":
|
|
13228
13349
|
result = await this.sendDaemonCmd("invoke_capability", args, 1e5);
|
|
13229
13350
|
break;
|
|
@@ -29845,26 +29966,102 @@ async function fetchPeerModels(peerId) {
|
|
|
29845
29966
|
} catch {
|
|
29846
29967
|
}
|
|
29847
29968
|
}
|
|
29848
|
-
|
|
29849
|
-
|
|
29850
|
-
|
|
29851
|
-
|
|
29852
|
-
|
|
29853
|
-
|
|
29854
|
-
|
|
29855
|
-
|
|
29856
|
-
|
|
29857
|
-
|
|
29858
|
-
|
|
29859
|
-
|
|
29860
|
-
|
|
29861
|
-
|
|
29862
|
-
|
|
29863
|
-
|
|
29864
|
-
|
|
29969
|
+
try {
|
|
29970
|
+
const capsResult = await nexusTool.execute({
|
|
29971
|
+
action: "query_peer_caps",
|
|
29972
|
+
peer_id: peerId
|
|
29973
|
+
});
|
|
29974
|
+
if (capsResult.success && capsResult.output) {
|
|
29975
|
+
let capsData = null;
|
|
29976
|
+
try {
|
|
29977
|
+
capsData = JSON.parse(capsResult.output);
|
|
29978
|
+
} catch {
|
|
29979
|
+
}
|
|
29980
|
+
if (capsData?.models && capsData.models.length > 0) {
|
|
29981
|
+
return capsData.models.map((m) => ({
|
|
29982
|
+
name: m.name || "unknown",
|
|
29983
|
+
size: m.parameterSize || "",
|
|
29984
|
+
modified: "",
|
|
29985
|
+
sizeBytes: 0,
|
|
29986
|
+
parameterSize: m.parameterSize || "remote"
|
|
29987
|
+
}));
|
|
29988
|
+
}
|
|
29989
|
+
if (capsData?.capabilities && capsData.capabilities.length > 0) {
|
|
29990
|
+
const models = [];
|
|
29991
|
+
for (const cap of capsData.capabilities) {
|
|
29992
|
+
if (typeof cap === "string" && cap.startsWith("inference:")) {
|
|
29993
|
+
const capName = cap.slice(10);
|
|
29994
|
+
const modelName = capName.replace(/_(\d+[bBmMkK])$/, ":$1").replace(/_latest$/, ":latest");
|
|
29995
|
+
models.push({
|
|
29996
|
+
name: modelName,
|
|
29997
|
+
size: "",
|
|
29998
|
+
modified: "",
|
|
29999
|
+
sizeBytes: 0,
|
|
30000
|
+
parameterSize: "remote"
|
|
30001
|
+
});
|
|
30002
|
+
}
|
|
30003
|
+
}
|
|
30004
|
+
if (models.length > 0)
|
|
30005
|
+
return models;
|
|
30006
|
+
}
|
|
29865
30007
|
}
|
|
29866
|
-
|
|
29867
|
-
|
|
30008
|
+
} catch {
|
|
30009
|
+
}
|
|
30010
|
+
try {
|
|
30011
|
+
const natsResult = await nexusTool.execute({
|
|
30012
|
+
action: "discover_peer_caps",
|
|
30013
|
+
peer_id: peerId
|
|
30014
|
+
});
|
|
30015
|
+
if (natsResult.success && natsResult.output) {
|
|
30016
|
+
let natsPeer = null;
|
|
30017
|
+
try {
|
|
30018
|
+
natsPeer = JSON.parse(natsResult.output);
|
|
30019
|
+
} catch {
|
|
30020
|
+
}
|
|
30021
|
+
if (natsPeer?.capabilities && natsPeer.capabilities.length > 0) {
|
|
30022
|
+
const models = [];
|
|
30023
|
+
for (const cap of natsPeer.capabilities) {
|
|
30024
|
+
if (typeof cap === "string" && cap.startsWith("inference:")) {
|
|
30025
|
+
const capName = cap.slice(10);
|
|
30026
|
+
const modelName = capName.replace(/_(\d+[bBmMkK])$/, ":$1").replace(/_latest$/, ":latest");
|
|
30027
|
+
models.push({
|
|
30028
|
+
name: modelName,
|
|
30029
|
+
size: "",
|
|
30030
|
+
modified: "",
|
|
30031
|
+
sizeBytes: 0,
|
|
30032
|
+
parameterSize: "remote"
|
|
30033
|
+
});
|
|
30034
|
+
}
|
|
30035
|
+
}
|
|
30036
|
+
if (models.length > 0)
|
|
30037
|
+
return models;
|
|
30038
|
+
}
|
|
30039
|
+
}
|
|
30040
|
+
} catch {
|
|
30041
|
+
}
|
|
30042
|
+
try {
|
|
30043
|
+
const result = await nexusTool.execute({
|
|
30044
|
+
action: "find_agent",
|
|
30045
|
+
peer_id: peerId
|
|
30046
|
+
});
|
|
30047
|
+
if (result.success && result.output) {
|
|
30048
|
+
const models = [];
|
|
30049
|
+
const capMatches = result.output.matchAll(/inference:([^\s,\]]+)/g);
|
|
30050
|
+
for (const m of capMatches) {
|
|
30051
|
+
const capName = m[1];
|
|
30052
|
+
const modelName = capName.replace(/_(\d+[bBmMkK])$/, ":$1").replace(/_latest$/, ":latest");
|
|
30053
|
+
models.push({
|
|
30054
|
+
name: modelName,
|
|
30055
|
+
size: "",
|
|
30056
|
+
modified: "",
|
|
30057
|
+
sizeBytes: 0,
|
|
30058
|
+
parameterSize: "remote"
|
|
30059
|
+
});
|
|
30060
|
+
}
|
|
30061
|
+
if (models.length > 0)
|
|
30062
|
+
return models;
|
|
30063
|
+
}
|
|
30064
|
+
} catch {
|
|
29868
30065
|
}
|
|
29869
30066
|
if (isLocalPeer) {
|
|
29870
30067
|
const pricingPath = join55(nexusDir, "pricing.json");
|
package/package.json
CHANGED