open-agents-ai 0.103.70 → 0.103.72

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.
Files changed (2) hide show
  1. package/dist/index.js +84 -108
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12304,43 +12304,34 @@ async function handleCmd(cmd) {
12304
12304
  var QPC_TIMEOUT = 15000;
12305
12305
  var qpcInput = {};
12306
12306
  if (args.auth_key) qpcInput.auth_key = args.auth_key;
12307
- var qpcPromise = nexus.invokeCapability(String(qpcPeerId), '__list_capabilities', qpcInput, { stream: false, maxDurationMs: 10000 });
12308
- var qpcTimeoutPromise = new Promise(function(_, reject) { setTimeout(function() { reject(new Error('query_peer_caps timed out after 15s')); }, QPC_TIMEOUT); });
12309
- var qpcResult = await Promise.race([qpcPromise, qpcTimeoutPromise]);
12307
+
12308
+ // Race libp2p + NATS in parallel \u2014 fastest route wins
12309
+ var qpcLibp2p = nexus.invokeCapability(String(qpcPeerId), '__list_capabilities', qpcInput, { stream: false, maxDurationMs: 10000 });
12310
+ var qpcTimeout = new Promise(function(_, reject) { setTimeout(function() { reject(new Error('query_peer_caps timed out')); }, QPC_TIMEOUT); });
12311
+ var qpcRace = [qpcLibp2p, qpcTimeout];
12312
+
12313
+ if (_natsConn && _natsCodec) {
12314
+ var _qpcNatsP = (async function() {
12315
+ var _s = 'nexus.invoke.' + String(qpcPeerId);
12316
+ var _p = JSON.stringify({ capability: '__list_capabilities', input: qpcInput, from: nexus.peerId || '' });
12317
+ var _r = await _natsConn.request(_s, _natsCodec.encode(_p), { timeout: 15000 });
12318
+ var _res = JSON.parse(_natsCodec.decode(_r.data));
12319
+ if (_res && _res.error) throw new Error('NATS: ' + _res.error);
12320
+ dlog('query_peer_caps: NATS won the race');
12321
+ return _res;
12322
+ })();
12323
+ qpcRace.push(_qpcNatsP);
12324
+ }
12325
+
12326
+ var qpcResult = await Promise.any(qpcRace.map(function(p) {
12327
+ return p.catch(function(e) { return Promise.reject(e); });
12328
+ }));
12310
12329
  dlog('query_peer_caps: SUCCESS');
12311
12330
  writeResp(id, { ok: true, output: typeof qpcResult === 'string' ? qpcResult : JSON.stringify(qpcResult, null, 2) });
12312
12331
  } catch (qpcErr) {
12313
- var qpcErrMsg = qpcErr.message || String(qpcErr);
12314
- dlog('query_peer_caps: ERROR ' + qpcErrMsg);
12315
- // NATS fallback for peer cap discovery across NAT
12316
- if (_natsConn && _natsCodec && isDialFailure(qpcErrMsg)) {
12317
- dlog('query_peer_caps: trying NATS relay fallback');
12318
- try {
12319
- var _qpcNatsSubject = 'nexus.invoke.' + String(qpcPeerId);
12320
- var _qpcNatsPayload = JSON.stringify({
12321
- capability: '__list_capabilities',
12322
- input: qpcInput,
12323
- from: nexus.peerId || '',
12324
- });
12325
- var _qpcNatsResp = await _natsConn.request(
12326
- _qpcNatsSubject,
12327
- _natsCodec.encode(_qpcNatsPayload),
12328
- { timeout: 15000 }
12329
- );
12330
- var _qpcNatsResult = JSON.parse(_natsCodec.decode(_qpcNatsResp.data));
12331
- if (_qpcNatsResult && _qpcNatsResult.error) {
12332
- writeResp(id, { ok: false, output: 'query_peer_caps (NATS): ' + _qpcNatsResult.error });
12333
- } else {
12334
- dlog('query_peer_caps: SUCCESS via NATS relay');
12335
- writeResp(id, { ok: true, output: typeof _qpcNatsResult === 'string' ? _qpcNatsResult : JSON.stringify(_qpcNatsResult, null, 2) });
12336
- }
12337
- } catch (_qpcNatsErr) {
12338
- dlog('query_peer_caps: NATS fallback also failed: ' + (_qpcNatsErr.message || _qpcNatsErr));
12339
- writeResp(id, { ok: false, output: 'query_peer_caps error (libp2p + NATS): ' + qpcErrMsg });
12340
- }
12341
- } else {
12342
- writeResp(id, { ok: false, output: 'query_peer_caps error: ' + qpcErrMsg });
12343
- }
12332
+ var qpcErrMsg = qpcErr.errors ? qpcErr.errors.map(function(e) { return e.message || String(e); }).join('; ') : (qpcErr.message || String(qpcErr));
12333
+ dlog('query_peer_caps: ALL paths failed: ' + qpcErrMsg);
12334
+ writeResp(id, { ok: false, output: 'query_peer_caps error: ' + qpcErrMsg });
12344
12335
  }
12345
12336
  break;
12346
12337
  }
@@ -12351,45 +12342,36 @@ async function handleCmd(cmd) {
12351
12342
  if (!peerId) { writeResp(id, { ok: false, output: 'target_peer is required' }); return; }
12352
12343
  dlog('invoke_capability: peer=' + peerId.slice(0, 20) + ' cap=' + capability);
12353
12344
  try {
12354
- // Wrap in a 300s timeout \u2014 remote API inference (Chutes, etc.) can take 60-180s for large models
12345
+ // Race libp2p + NATS in parallel \u2014 whichever route works first wins
12355
12346
  const INVOKE_TIMEOUT = 300_000;
12356
- const invokePromise = nexus.invokeCapability(peerId, capability, typeof input === 'string' ? { prompt: input } : input, { stream: false, maxDurationMs: 240000 });
12357
- const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('invoke_capability timed out after ' + (INVOKE_TIMEOUT / 1000) + 's (client-side timeout)')), INVOKE_TIMEOUT));
12358
- const result = await Promise.race([invokePromise, timeoutPromise]);
12347
+ const invokeInput = typeof input === 'string' ? { prompt: input } : input;
12348
+ const invokePromise = nexus.invokeCapability(peerId, capability, invokeInput, { stream: false, maxDurationMs: 240000 });
12349
+ const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('invoke_capability timed out after ' + (INVOKE_TIMEOUT / 1000) + 's')), INVOKE_TIMEOUT));
12350
+
12351
+ var icRaceCandidates = [invokePromise, timeoutPromise];
12352
+
12353
+ if (_natsConn && _natsCodec) {
12354
+ var _icNatsRaceP = (async function() {
12355
+ var _s = 'nexus.invoke.' + peerId;
12356
+ var _p = JSON.stringify({ capability: capability, input: invokeInput, from: nexus.peerId || '' });
12357
+ var _r = await _natsConn.request(_s, _natsCodec.encode(_p), { timeout: 240000 });
12358
+ var _res = JSON.parse(_natsCodec.decode(_r.data));
12359
+ if (_res && _res.error) throw new Error('NATS: ' + _res.error);
12360
+ dlog('invoke_capability: NATS won the race');
12361
+ return _res;
12362
+ })();
12363
+ icRaceCandidates.push(_icNatsRaceP);
12364
+ }
12365
+
12366
+ const result = await Promise.any(icRaceCandidates.map(function(p) {
12367
+ return p.catch(function(e) { return Promise.reject(e); });
12368
+ }));
12359
12369
  dlog('invoke_capability: SUCCESS');
12360
- writeResp(id, { ok: true, output: JSON.stringify(result, null, 2) });
12370
+ writeResp(id, { ok: true, output: typeof result === 'string' ? result : JSON.stringify(result, null, 2) });
12361
12371
  } catch (invokeErr) {
12362
- var invokeErrMsg = invokeErr.message || String(invokeErr);
12363
- dlog('invoke_capability: ERROR ' + invokeErrMsg);
12364
- // NATS fallback \u2014 if direct dial failed (NAT/timeout/refused), retry via NATS relay
12365
- if (_natsConn && _natsCodec && isDialFailure(invokeErrMsg)) {
12366
- dlog('invoke_capability: trying NATS relay fallback for ' + peerId.slice(0, 20));
12367
- try {
12368
- var _icNatsSubject = 'nexus.invoke.' + peerId;
12369
- var _icNatsPayload = JSON.stringify({
12370
- capability: capability,
12371
- input: typeof input === 'string' ? { prompt: input } : input,
12372
- from: nexus.peerId || '',
12373
- });
12374
- var _icNatsResp = await _natsConn.request(
12375
- _icNatsSubject,
12376
- _natsCodec.encode(_icNatsPayload),
12377
- { timeout: 240000 }
12378
- );
12379
- var _icNatsResult = JSON.parse(_natsCodec.decode(_icNatsResp.data));
12380
- if (_icNatsResult && _icNatsResult.error) {
12381
- writeResp(id, { ok: false, output: 'NATS relay error: ' + _icNatsResult.error });
12382
- } else {
12383
- dlog('invoke_capability: SUCCESS via NATS relay');
12384
- writeResp(id, { ok: true, output: typeof _icNatsResult === 'string' ? _icNatsResult : JSON.stringify(_icNatsResult, null, 2) });
12385
- }
12386
- } catch (_icNatsErr) {
12387
- dlog('invoke_capability: NATS fallback also failed: ' + (_icNatsErr.message || _icNatsErr));
12388
- writeResp(id, { ok: false, output: 'Invoke error (libp2p + NATS fallback failed): ' + invokeErrMsg });
12389
- }
12390
- } else {
12391
- writeResp(id, { ok: false, output: 'Invoke error: ' + invokeErrMsg });
12392
- }
12372
+ var invokeErrMsg = invokeErr.errors ? invokeErr.errors.map(function(e) { return e.message || String(e); }).join('; ') : (invokeErr.message || String(invokeErr));
12373
+ dlog('invoke_capability: ALL paths failed: ' + invokeErrMsg);
12374
+ writeResp(id, { ok: false, output: 'Invoke error: ' + invokeErrMsg });
12393
12375
  }
12394
12376
  break;
12395
12377
  }
@@ -12429,48 +12411,42 @@ async function handleCmd(cmd) {
12429
12411
 
12430
12412
  // If target_peer specified, invoke directly. Otherwise auto-discover.
12431
12413
  if (riTargetPeer) {
12432
- // Direct invoke on specified peer
12433
- dlog('remote_infer: invoking ' + riCapName + ' on explicit peer ' + riTargetPeer.slice(0, 20));
12414
+ // Race libp2p direct dial and NATS relay IN PARALLEL.
12415
+ // For cross-NAT peers, libp2p dial can take 10-60s to fail while NATS
12416
+ // succeeds in <1s. Racing them eliminates the wait.
12417
+ dlog('remote_infer: invoking ' + riCapName + ' on peer ' + riTargetPeer.slice(0, 20) + ' (libp2p' + (_natsConn ? ' + NATS parallel' : '') + ')');
12434
12418
  try {
12435
- var RI_TIMEOUT = 300000; // 5 min \u2014 remote APIs (Chutes, etc.) can be slow for large models
12419
+ var RI_TIMEOUT = 300000;
12436
12420
  var riInvokeP = nexus.invokeCapability(riTargetPeer, riCapName, riData, { stream: false, maxDurationMs: 240000 });
12437
12421
  var riTimeoutP = new Promise(function(_, reject) { setTimeout(function() { reject(new Error('remote_infer timed out after ' + (RI_TIMEOUT / 1000) + 's')); }, RI_TIMEOUT); });
12438
- var riResult = await Promise.race([riInvokeP, riTimeoutP]);
12439
- dlog('remote_infer: SUCCESS (explicit peer)');
12440
- } catch (riErr) {
12441
- var riErrMsg = riErr.message || String(riErr);
12442
- dlog('remote_infer: ERROR (explicit peer) ' + riErrMsg);
12443
- // NATS fallback \u2014 if direct dial failed (NAT/firewall/timeout), retry via NATS relay
12444
- if (_natsConn && _natsCodec && isDialFailure(riErrMsg)) {
12445
- dlog('remote_infer: trying NATS relay fallback for ' + riTargetPeer.slice(0, 20));
12446
- try {
12447
- var _riNatsSubject = 'nexus.invoke.' + riTargetPeer;
12448
- var _riNatsPayload = JSON.stringify({
12449
- capability: riCapName,
12450
- input: riData,
12451
- from: nexus.peerId || '',
12452
- });
12453
- var _riNatsResp = await _natsConn.request(
12454
- _riNatsSubject,
12455
- _natsCodec.encode(_riNatsPayload),
12456
- { timeout: 240000 }
12457
- );
12458
- var _riNatsResult = JSON.parse(_natsCodec.decode(_riNatsResp.data));
12459
- if (_riNatsResult && _riNatsResult.error) {
12460
- writeResp(id, { ok: false, output: 'Remote inference failed (NATS relay): ' + _riNatsResult.error });
12461
- return;
12462
- }
12463
- riResult = _riNatsResult;
12464
- dlog('remote_infer: SUCCESS via NATS relay');
12465
- } catch (_riNatsErr) {
12466
- dlog('remote_infer: NATS fallback also failed: ' + (_riNatsErr.message || _riNatsErr));
12467
- writeResp(id, { ok: false, output: 'Remote inference failed (libp2p + NATS): ' + riErrMsg });
12468
- return;
12469
- }
12470
- } else {
12471
- writeResp(id, { ok: false, output: 'Remote inference failed: ' + riErrMsg });
12472
- return;
12422
+
12423
+ // Build race candidates \u2014 libp2p + timeout always present
12424
+ var riRaceCandidates = [riInvokeP, riTimeoutP];
12425
+
12426
+ // Add NATS as a parallel candidate if available
12427
+ if (_natsConn && _natsCodec) {
12428
+ var _riNatsRaceP = (async function() {
12429
+ var _rSubject = 'nexus.invoke.' + riTargetPeer;
12430
+ var _rPayload = JSON.stringify({ capability: riCapName, input: riData, from: nexus.peerId || '' });
12431
+ var _rResp = await _natsConn.request(_rSubject, _natsCodec.encode(_rPayload), { timeout: 240000 });
12432
+ var _rResult = JSON.parse(_natsCodec.decode(_rResp.data));
12433
+ if (_rResult && _rResult.error) throw new Error('NATS: ' + _rResult.error);
12434
+ dlog('remote_infer: NATS won the race');
12435
+ return _rResult;
12436
+ })();
12437
+ riRaceCandidates.push(_riNatsRaceP);
12473
12438
  }
12439
+
12440
+ var riResult = await Promise.any(riRaceCandidates.map(function(p) {
12441
+ return p.catch(function(e) { return Promise.reject(e); });
12442
+ }));
12443
+ dlog('remote_infer: SUCCESS (peer ' + riTargetPeer.slice(0, 20) + ')');
12444
+ } catch (riErr) {
12445
+ // Promise.any throws AggregateError when ALL candidates fail
12446
+ var riErrMsg = riErr.errors ? riErr.errors.map(function(e) { return e.message || String(e); }).join('; ') : (riErr.message || String(riErr));
12447
+ dlog('remote_infer: ALL paths failed: ' + riErrMsg);
12448
+ writeResp(id, { ok: false, output: 'Remote inference failed: ' + riErrMsg });
12449
+ return;
12474
12450
  }
12475
12451
  } else {
12476
12452
  // Auto-discover: try speculative invoke on each 12D3KooW peer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.103.70",
3
+ "version": "0.103.72",
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",