open-agents-ai 0.103.43 → 0.103.44

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 +73 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12754,6 +12754,16 @@ async function handleCmd(cmd) {
12754
12754
  const logFile = join(invocationsDir, Date.now() + '-' + capName + '.json');
12755
12755
  try { writeFileSync(logFile, JSON.stringify(logEntry, null, 2)); } catch {}
12756
12756
 
12757
+ // Safe stream write \u2014 consumer may have timed out and closed the stream
12758
+ var streamClosed = false;
12759
+ async function swrite(msg) {
12760
+ if (streamClosed) return;
12761
+ try { await stream.write(msg); } catch (swErr) {
12762
+ dlog('stream.write failed (consumer likely timed out): ' + (swErr.message || swErr));
12763
+ streamClosed = true;
12764
+ }
12765
+ }
12766
+
12757
12767
  // Collect input via stream data events
12758
12768
  // NOTE: auth_key arrives in invoke.chunk data, NOT in invoke.open (request).
12759
12769
  // We must accept + read data FIRST, then validate auth.
@@ -12771,7 +12781,7 @@ async function handleCmd(cmd) {
12771
12781
  });
12772
12782
 
12773
12783
  // Accept the invocation so the consumer sends data
12774
- await stream.write({
12784
+ await swrite({
12775
12785
  type: 'invoke.accept', version: 1,
12776
12786
  requestId: request.requestId, accepted: true,
12777
12787
  });
@@ -12802,9 +12812,9 @@ async function handleCmd(cmd) {
12802
12812
  }
12803
12813
  if (reqAuthKey !== exposeAuthKey) {
12804
12814
  dlog('expose: auth REJECTED for ' + capName + ' from ' + (request.from || 'unknown'));
12805
- await stream.write({ type: 'invoke.event', version: 1, requestId: request.requestId, seq: 0, event: 'error', data: 'Unauthorized \u2014 invalid or missing auth key' });
12806
- await stream.write({ type: 'invoke.done', version: 1, requestId: request.requestId, usage: { inputBytes: 0, outputBytes: 0 } });
12807
- stream.close();
12815
+ await swrite({ type: 'invoke.event', version: 1, requestId: request.requestId, seq: 0, event: 'error', data: 'Unauthorized \u2014 invalid or missing auth key' });
12816
+ await swrite({ type: 'invoke.done', version: 1, requestId: request.requestId, usage: { inputBytes: 0, outputBytes: 0 } });
12817
+ try { stream.close(); } catch {}
12808
12818
  return;
12809
12819
  }
12810
12820
  dlog('expose: auth OK for ' + capName);
@@ -12923,14 +12933,14 @@ async function handleCmd(cmd) {
12923
12933
  }
12924
12934
 
12925
12935
  // Stream result back
12926
- await stream.write({
12936
+ await swrite({
12927
12937
  type: 'invoke.event', version: 1,
12928
12938
  requestId: request.requestId, seq: 0,
12929
12939
  event: 'result',
12930
12940
  data: JSON.stringify(responsePayload),
12931
12941
  });
12932
12942
 
12933
- await stream.write({
12943
+ await swrite({
12934
12944
  type: 'invoke.done', version: 1,
12935
12945
  requestId: request.requestId,
12936
12946
  usage: {
@@ -12940,18 +12950,19 @@ async function handleCmd(cmd) {
12940
12950
  },
12941
12951
  });
12942
12952
  } catch (e) {
12943
- await stream.write({
12953
+ dlog('expose: inference error: ' + (e.message || e));
12954
+ await swrite({
12944
12955
  type: 'invoke.event', version: 1,
12945
12956
  requestId: request.requestId, seq: 0,
12946
12957
  event: 'error', data: 'Inference failed: ' + e.message,
12947
12958
  });
12948
- await stream.write({
12959
+ await swrite({
12949
12960
  type: 'invoke.done', version: 1,
12950
12961
  requestId: request.requestId,
12951
12962
  usage: { inputBytes: 0, outputBytes: 0 },
12952
12963
  });
12953
12964
  }
12954
- stream.close();
12965
+ try { stream.close(); } catch {}
12955
12966
  }, capOpts);
12956
12967
  }
12957
12968
  }
@@ -13350,7 +13361,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13350
13361
  },
13351
13362
  margin: {
13352
13363
  type: "string",
13353
- description: "Price margin multiplier for expose (0.5 = 50% of market rate, 0 = free). Default: 0.5"
13364
+ description: "Price margin multiplier for expose (0.5 = 50% of market rate, 0 = free). Default: 0 (free)"
13354
13365
  },
13355
13366
  daily_limit: {
13356
13367
  type: "string",
@@ -13703,6 +13714,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13703
13714
  }
13704
13715
  }
13705
13716
  }
13717
+ await this.ensureWallet();
13706
13718
  const daemonPath = join30(this.nexusDir, "nexus-daemon.mjs");
13707
13719
  await writeFile12(daemonPath, DAEMON_SCRIPT);
13708
13720
  const agentName = args.agent_name || "open-agents-node";
@@ -14019,6 +14031,57 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14019
14031
  `Free inference (margin=0) works without funding.`
14020
14032
  ].join("\n");
14021
14033
  }
14034
+ /**
14035
+ * Auto-create wallet + x402-wallet.key if none exists.
14036
+ * Called from doConnect() before daemon spawn so the daemon starts x402-ready.
14037
+ * Silent — no user output, just ensures the files exist.
14038
+ */
14039
+ async ensureWallet() {
14040
+ const walletPath = join30(this.nexusDir, "wallet.enc");
14041
+ if (existsSync23(walletPath))
14042
+ return;
14043
+ let address;
14044
+ let privKeyHex;
14045
+ try {
14046
+ const { privateKeyToAccount } = await import("viem/accounts");
14047
+ const privKey = randomBytes6(32);
14048
+ privKeyHex = privKey.toString("hex");
14049
+ const account = privateKeyToAccount(`0x${privKeyHex}`);
14050
+ address = account.address;
14051
+ privKey.fill(0);
14052
+ } catch {
14053
+ const privKey = randomBytes6(32);
14054
+ privKeyHex = privKey.toString("hex");
14055
+ address = "0x" + createHash("sha256").update(privKey).digest("hex").slice(0, 40);
14056
+ privKey.fill(0);
14057
+ }
14058
+ const salt = randomBytes6(32);
14059
+ const key = scryptSync(`${hostname()}:${userInfo().username}:nexus-wallet`, salt, 32, { N: 16384, r: 8, p: 1 });
14060
+ const iv = randomBytes6(16);
14061
+ const cipher = createCipheriv("aes-256-gcm", key, iv);
14062
+ let enc = cipher.update(privKeyHex, "utf8", "hex");
14063
+ enc += cipher.final("hex");
14064
+ const x402KeyPath = join30(this.nexusDir, "x402-wallet.key");
14065
+ const x402Fh = await fsOpen(x402KeyPath, "w", 384);
14066
+ await x402Fh.writeFile("0x" + privKeyHex);
14067
+ await x402Fh.close();
14068
+ privKeyHex = "0".repeat(64);
14069
+ const w = {
14070
+ version: 2,
14071
+ address,
14072
+ encryptedKey: enc,
14073
+ iv: iv.toString("hex"),
14074
+ authTag: cipher.getAuthTag().toString("hex"),
14075
+ salt: salt.toString("hex"),
14076
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
14077
+ network: "base",
14078
+ chainId: 8453
14079
+ };
14080
+ const walletFh = await fsOpen(walletPath, "w", 384);
14081
+ await walletFh.writeFile(JSON.stringify(w, null, 2));
14082
+ await walletFh.close();
14083
+ await this.ensureDefaultBudget();
14084
+ }
14022
14085
  // ---------------------------------------------------------------------------
14023
14086
  // Step 2: USDC Balance Query via Base RPC
14024
14087
  // ---------------------------------------------------------------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.103.43",
3
+ "version": "0.103.44",
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",