open-agents-ai 0.103.67 → 0.103.69

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 +201 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12126,6 +12126,11 @@ const rooms = new Map();
12126
12126
  let connected = false;
12127
12127
  const blockedPeers = [];
12128
12128
 
12129
+ // NATS invoke relay \u2014 for cross-NAT fallback when direct libp2p dial fails.
12130
+ // Both peers connect to wss://demo.nats.io:8443, so NATS request/reply bridges the gap.
12131
+ var _natsConn = null;
12132
+ var _natsCodec = null;
12133
+
12129
12134
  function writeStatus(extra = {}) {
12130
12135
  const caps = typeof nexus.getRegisteredCapabilities === 'function'
12131
12136
  ? nexus.getRegisteredCapabilities() : [];
@@ -12285,8 +12290,37 @@ async function handleCmd(cmd) {
12285
12290
  dlog('query_peer_caps: SUCCESS');
12286
12291
  writeResp(id, { ok: true, output: typeof qpcResult === 'string' ? qpcResult : JSON.stringify(qpcResult, null, 2) });
12287
12292
  } 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)) });
12293
+ var qpcErrMsg = qpcErr.message || String(qpcErr);
12294
+ dlog('query_peer_caps: ERROR ' + qpcErrMsg);
12295
+ // NATS fallback for peer cap discovery across NAT
12296
+ if (_natsConn && _natsCodec && qpcErrMsg.includes('multiaddrs failed')) {
12297
+ dlog('query_peer_caps: trying NATS relay fallback');
12298
+ try {
12299
+ var _qpcNatsSubject = 'nexus.invoke.' + String(qpcPeerId);
12300
+ var _qpcNatsPayload = JSON.stringify({
12301
+ capability: '__list_capabilities',
12302
+ input: qpcInput,
12303
+ from: nexus.peerId || '',
12304
+ });
12305
+ var _qpcNatsResp = await _natsConn.request(
12306
+ _qpcNatsSubject,
12307
+ _natsCodec.encode(_qpcNatsPayload),
12308
+ { timeout: 15000 }
12309
+ );
12310
+ var _qpcNatsResult = JSON.parse(_natsCodec.decode(_qpcNatsResp.data));
12311
+ if (_qpcNatsResult && _qpcNatsResult.error) {
12312
+ writeResp(id, { ok: false, output: 'query_peer_caps (NATS): ' + _qpcNatsResult.error });
12313
+ } else {
12314
+ dlog('query_peer_caps: SUCCESS via NATS relay');
12315
+ writeResp(id, { ok: true, output: typeof _qpcNatsResult === 'string' ? _qpcNatsResult : JSON.stringify(_qpcNatsResult, null, 2) });
12316
+ }
12317
+ } catch (_qpcNatsErr) {
12318
+ dlog('query_peer_caps: NATS fallback also failed: ' + (_qpcNatsErr.message || _qpcNatsErr));
12319
+ writeResp(id, { ok: false, output: 'query_peer_caps error (libp2p + NATS): ' + qpcErrMsg });
12320
+ }
12321
+ } else {
12322
+ writeResp(id, { ok: false, output: 'query_peer_caps error: ' + qpcErrMsg });
12323
+ }
12290
12324
  }
12291
12325
  break;
12292
12326
  }
@@ -12305,8 +12339,37 @@ async function handleCmd(cmd) {
12305
12339
  dlog('invoke_capability: SUCCESS');
12306
12340
  writeResp(id, { ok: true, output: JSON.stringify(result, null, 2) });
12307
12341
  } catch (invokeErr) {
12308
- dlog('invoke_capability: ERROR ' + (invokeErr.message || String(invokeErr)));
12309
- writeResp(id, { ok: false, output: 'Invoke error: ' + (invokeErr.message || String(invokeErr)) });
12342
+ var invokeErrMsg = invokeErr.message || String(invokeErr);
12343
+ dlog('invoke_capability: ERROR ' + invokeErrMsg);
12344
+ // NATS fallback \u2014 if direct dial failed (NAT), retry via NATS relay
12345
+ if (_natsConn && _natsCodec && invokeErrMsg.includes('multiaddrs failed')) {
12346
+ dlog('invoke_capability: trying NATS relay fallback for ' + peerId.slice(0, 20));
12347
+ try {
12348
+ var _icNatsSubject = 'nexus.invoke.' + peerId;
12349
+ var _icNatsPayload = JSON.stringify({
12350
+ capability: capability,
12351
+ input: typeof input === 'string' ? { prompt: input } : input,
12352
+ from: nexus.peerId || '',
12353
+ });
12354
+ var _icNatsResp = await _natsConn.request(
12355
+ _icNatsSubject,
12356
+ _natsCodec.encode(_icNatsPayload),
12357
+ { timeout: 240000 }
12358
+ );
12359
+ var _icNatsResult = JSON.parse(_natsCodec.decode(_icNatsResp.data));
12360
+ if (_icNatsResult && _icNatsResult.error) {
12361
+ writeResp(id, { ok: false, output: 'NATS relay error: ' + _icNatsResult.error });
12362
+ } else {
12363
+ dlog('invoke_capability: SUCCESS via NATS relay');
12364
+ writeResp(id, { ok: true, output: typeof _icNatsResult === 'string' ? _icNatsResult : JSON.stringify(_icNatsResult, null, 2) });
12365
+ }
12366
+ } catch (_icNatsErr) {
12367
+ dlog('invoke_capability: NATS fallback also failed: ' + (_icNatsErr.message || _icNatsErr));
12368
+ writeResp(id, { ok: false, output: 'Invoke error (libp2p + NATS fallback failed): ' + invokeErrMsg });
12369
+ }
12370
+ } else {
12371
+ writeResp(id, { ok: false, output: 'Invoke error: ' + invokeErrMsg });
12372
+ }
12310
12373
  }
12311
12374
  break;
12312
12375
  }
@@ -12355,9 +12418,39 @@ async function handleCmd(cmd) {
12355
12418
  var riResult = await Promise.race([riInvokeP, riTimeoutP]);
12356
12419
  dlog('remote_infer: SUCCESS (explicit peer)');
12357
12420
  } catch (riErr) {
12358
- dlog('remote_infer: ERROR (explicit peer) ' + (riErr.message || String(riErr)));
12359
- writeResp(id, { ok: false, output: 'Remote inference failed: ' + (riErr.message || String(riErr)) });
12360
- return;
12421
+ var riErrMsg = riErr.message || String(riErr);
12422
+ dlog('remote_infer: ERROR (explicit peer) ' + riErrMsg);
12423
+ // NATS fallback \u2014 if direct dial failed (NAT/firewall), retry via NATS relay
12424
+ if (_natsConn && _natsCodec && riErrMsg.includes('multiaddrs failed')) {
12425
+ dlog('remote_infer: trying NATS relay fallback for ' + riTargetPeer.slice(0, 20));
12426
+ try {
12427
+ var _riNatsSubject = 'nexus.invoke.' + riTargetPeer;
12428
+ var _riNatsPayload = JSON.stringify({
12429
+ capability: riCapName,
12430
+ input: riData,
12431
+ from: nexus.peerId || '',
12432
+ });
12433
+ var _riNatsResp = await _natsConn.request(
12434
+ _riNatsSubject,
12435
+ _natsCodec.encode(_riNatsPayload),
12436
+ { timeout: 240000 }
12437
+ );
12438
+ var _riNatsResult = JSON.parse(_natsCodec.decode(_riNatsResp.data));
12439
+ if (_riNatsResult && _riNatsResult.error) {
12440
+ writeResp(id, { ok: false, output: 'Remote inference failed (NATS relay): ' + _riNatsResult.error });
12441
+ return;
12442
+ }
12443
+ riResult = _riNatsResult;
12444
+ dlog('remote_infer: SUCCESS via NATS relay');
12445
+ } catch (_riNatsErr) {
12446
+ dlog('remote_infer: NATS fallback also failed: ' + (_riNatsErr.message || _riNatsErr));
12447
+ writeResp(id, { ok: false, output: 'Remote inference failed (libp2p + NATS): ' + riErrMsg });
12448
+ return;
12449
+ }
12450
+ } else {
12451
+ writeResp(id, { ok: false, output: 'Remote inference failed: ' + riErrMsg });
12452
+ return;
12453
+ }
12361
12454
  }
12362
12455
  } else {
12363
12456
  // Auto-discover: try speculative invoke on each 12D3KooW peer
@@ -13402,6 +13495,97 @@ process.on('unhandledRejection', (reason) => {
13402
13495
  dlog('NATS subscribe failed: ' + (natsSubErr.message || natsSubErr));
13403
13496
  }
13404
13497
 
13498
+ // NATS invoke relay \u2014 subscribe to nexus.invoke.<myPeerId> for cross-NAT invoke fallback.
13499
+ // When a remote peer can't direct-dial us (all multiaddrs are private), they retry
13500
+ // via NATS request/reply. We dispatch to the registered capability handler using a
13501
+ // mock stream interface, then reply with the result.
13502
+ try {
13503
+ var _nc = nexus.nats && nexus.nats.nc ? nexus.nats.nc : null;
13504
+ if (_nc) {
13505
+ var _nws = await import('nats.ws');
13506
+ _natsConn = _nc;
13507
+ _natsCodec = _nws.StringCodec();
13508
+ var _natsInvSubject = 'nexus.invoke.' + nexus.peerId;
13509
+ var _natsInvSub = _nc.subscribe(_natsInvSubject);
13510
+ dlog('NATS invoke relay listening on ' + _natsInvSubject);
13511
+
13512
+ (async function _natsInvokeLoop() {
13513
+ for await (var _nm of _natsInvSub) {
13514
+ try {
13515
+ var _nReq = JSON.parse(_natsCodec.decode(_nm.data));
13516
+ var _nCap = _nReq.capability || '';
13517
+ var _nInput = _nReq.input || {};
13518
+ var _nInputStr = typeof _nInput === 'string' ? _nInput : JSON.stringify(_nInput);
13519
+ dlog('NATS relay invoke: cap=' + _nCap + ' from=' + (_nReq.from || 'unknown').slice(0, 20));
13520
+
13521
+ // Look up registered handler
13522
+ var _nHandler = null;
13523
+ if (nexus.capabilityHandlers && typeof nexus.capabilityHandlers.get === 'function') {
13524
+ _nHandler = nexus.capabilityHandlers.get(_nCap);
13525
+ }
13526
+ if (!_nHandler) {
13527
+ var _nCaps = typeof nexus.getRegisteredCapabilities === 'function'
13528
+ ? nexus.getRegisteredCapabilities() : [];
13529
+ _nm.respond(_natsCodec.encode(JSON.stringify({
13530
+ error: 'Capability not found: ' + _nCap + '. Available: ' + _nCaps.join(', ')
13531
+ })));
13532
+ continue;
13533
+ }
13534
+
13535
+ // Create mock stream handle that captures the handler's output
13536
+ var _nResults = [];
13537
+ var _nHandleDone = false;
13538
+ var _nHandle = {
13539
+ write: async function(msg) {
13540
+ if (msg && msg.type === 'invoke.event') _nResults.push(msg);
13541
+ if (msg && msg.type === 'invoke.done') _nHandleDone = true;
13542
+ },
13543
+ onData: function(cb) {
13544
+ // Deliver input data asynchronously after handler registers its listener
13545
+ setTimeout(function() {
13546
+ try {
13547
+ cb({ type: 'invoke.chunk', data: _nInputStr, seq: 0 });
13548
+ cb({ type: 'invoke.done' });
13549
+ } catch {}
13550
+ }, 5);
13551
+ },
13552
+ close: function() {},
13553
+ };
13554
+
13555
+ var _nRequest = {
13556
+ type: 'invoke.open',
13557
+ requestId: 'nats-' + Date.now() + '-' + Math.random().toString(36).slice(2, 8),
13558
+ capability: _nCap,
13559
+ from: _nReq.from || 'nats-peer',
13560
+ };
13561
+
13562
+ await _nHandler(_nRequest, _nHandle);
13563
+
13564
+ // Extract result from captured invoke.event messages
13565
+ var _nResult = null;
13566
+ if (_nResults.length === 1) {
13567
+ _nResult = _nResults[0].data;
13568
+ } else if (_nResults.length > 1) {
13569
+ _nResult = _nResults.map(function(r) { return r.data; });
13570
+ }
13571
+
13572
+ _nm.respond(_natsCodec.encode(JSON.stringify(_nResult !== null && _nResult !== undefined ? _nResult : { ok: true })));
13573
+ dlog('NATS relay invoke SUCCESS: ' + _nCap);
13574
+ } catch (_nErr) {
13575
+ dlog('NATS relay invoke error: ' + (_nErr.message || _nErr));
13576
+ try {
13577
+ _nm.respond(_natsCodec.encode(JSON.stringify({ error: String(_nErr.message || _nErr) })));
13578
+ } catch {}
13579
+ }
13580
+ }
13581
+ })().catch(function(e) { dlog('NATS invoke relay loop error: ' + (e.message || e)); });
13582
+ } else {
13583
+ dlog('NATS not connected \u2014 invoke relay disabled (cross-NAT invoke will not work)');
13584
+ }
13585
+ } catch (_nSetupErr) {
13586
+ dlog('NATS invoke relay setup failed: ' + (_nSetupErr.message || _nSetupErr));
13587
+ }
13588
+
13405
13589
  writeStatus();
13406
13590
  console.log('Nexus daemon connected as ' + nexus.peerId);
13407
13591
  } catch (err) {
@@ -47315,6 +47499,16 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
47315
47499
  });
47316
47500
  }
47317
47501
  }
47502
+ try {
47503
+ const autoNexus = new NexusTool(repoRoot);
47504
+ autoNexus.execute({ action: "connect" }).then((r) => {
47505
+ if (r.success && r.output.includes("Connected")) {
47506
+ writeContent(() => renderInfo("Nexus P2P network connected."));
47507
+ }
47508
+ }).catch(() => {
47509
+ });
47510
+ } catch {
47511
+ }
47318
47512
  try {
47319
47513
  const oaDir = join50(repoRoot, ".oa");
47320
47514
  const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.103.67",
3
+ "version": "0.103.69",
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",