open-agents-ai 0.103.51 → 0.103.52

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 +104 -18
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -13579,9 +13579,19 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13579
13579
  }
13580
13580
  }
13581
13581
  async sendDaemonCmd(action, args, timeoutMs = 15e3) {
13582
- const pid = this.getDaemonPid();
13583
- if (!pid)
13584
- throw new Error("Nexus daemon not running. Use action 'connect' first.");
13582
+ let pid = this.getDaemonPid();
13583
+ if (!pid) {
13584
+ try {
13585
+ await this.doConnect({
13586
+ agent_name: "open-agents-node",
13587
+ agent_type: "general"
13588
+ });
13589
+ pid = this.getDaemonPid();
13590
+ } catch {
13591
+ }
13592
+ if (!pid)
13593
+ throw new Error("Nexus daemon not running. Use action 'connect' first.");
13594
+ }
13585
13595
  const cmdId = randomBytes6(8).toString("hex");
13586
13596
  const cmdFile = join30(this.nexusDir, "cmd.json");
13587
13597
  const respFile = join30(this.nexusDir, "resp.json");
@@ -20732,11 +20742,13 @@ var NexusAgenticBackend;
20732
20742
  var init_nexusBackend = __esm({
20733
20743
  "packages/orchestrator/dist/nexusBackend.js"() {
20734
20744
  "use strict";
20735
- NexusAgenticBackend = class {
20745
+ NexusAgenticBackend = class _NexusAgenticBackend {
20736
20746
  sendFn;
20737
20747
  model;
20738
20748
  targetPeer;
20739
20749
  authKey;
20750
+ consecutiveFailures = 0;
20751
+ static MAX_CONSECUTIVE_FAILURES = 3;
20740
20752
  constructor(sendFn, model, targetPeer, authKey) {
20741
20753
  this.sendFn = sendFn;
20742
20754
  this.model = model;
@@ -20744,6 +20756,11 @@ var init_nexusBackend = __esm({
20744
20756
  this.authKey = authKey || "";
20745
20757
  }
20746
20758
  async chatCompletion(request) {
20759
+ if (this.consecutiveFailures >= _NexusAgenticBackend.MAX_CONSECUTIVE_FAILURES) {
20760
+ const err = new Error(`Remote peer unreachable after ${this.consecutiveFailures} attempts. Use /endpoint to switch to a local model or reconnect.`);
20761
+ err.fatal = true;
20762
+ throw err;
20763
+ }
20747
20764
  const daemonArgs = {
20748
20765
  model: this.model,
20749
20766
  messages: JSON.stringify(request.messages),
@@ -20757,16 +20774,25 @@ var init_nexusBackend = __esm({
20757
20774
  if (this.authKey) {
20758
20775
  daemonArgs.auth_key = this.authKey;
20759
20776
  }
20760
- const rawResult = await this.sendFn("remote_infer", daemonArgs, request.timeoutMs || 12e4);
20777
+ let rawResult;
20778
+ try {
20779
+ rawResult = await this.sendFn("remote_infer", daemonArgs, request.timeoutMs || 12e4);
20780
+ } catch (sendErr) {
20781
+ this.consecutiveFailures++;
20782
+ throw sendErr;
20783
+ }
20761
20784
  let parsed;
20762
20785
  try {
20763
20786
  parsed = JSON.parse(rawResult);
20764
20787
  } catch {
20788
+ this.consecutiveFailures++;
20765
20789
  throw new Error(rawResult.slice(0, 500));
20766
20790
  }
20767
20791
  if (parsed.success === false) {
20792
+ this.consecutiveFailures++;
20768
20793
  throw new Error(`Remote inference failed: ${parsed.output || rawResult}`);
20769
20794
  }
20795
+ this.consecutiveFailures = 0;
20770
20796
  const invokeResult = parsed.result;
20771
20797
  let responseData = null;
20772
20798
  if (typeof invokeResult === "string") {
@@ -28811,10 +28837,21 @@ ${this.formatConnectionInfo()}`);
28811
28837
  continue;
28812
28838
  try {
28813
28839
  const record = JSON.parse(line);
28814
- if (record.tokens) {
28815
- this._stats.totalTokensIn += record.tokens.input || 0;
28816
- this._stats.totalTokensOut += record.tokens.output || 0;
28840
+ const recInputBytes = record.inputBytes || 0;
28841
+ const recOutputBytes = record.outputBytes || 0;
28842
+ const recTotalTokens = typeof record.tokens === "number" ? record.tokens : typeof record.tokens === "object" && record.tokens ? (record.tokens.input || 0) + (record.tokens.output || 0) : 0;
28843
+ const totalBytes = recInputBytes + recOutputBytes;
28844
+ let tokIn = 0;
28845
+ let tokOut = 0;
28846
+ if (recTotalTokens > 0 && totalBytes > 0) {
28847
+ tokIn = Math.round(recTotalTokens * (recInputBytes / totalBytes));
28848
+ tokOut = recTotalTokens - tokIn;
28849
+ } else if (recTotalTokens > 0) {
28850
+ tokIn = Math.round(recTotalTokens / 2);
28851
+ tokOut = recTotalTokens - tokIn;
28817
28852
  }
28853
+ this._stats.totalTokensIn += tokIn;
28854
+ this._stats.totalTokensOut += tokOut;
28818
28855
  const peerId = record.from || record.peerId || "unknown";
28819
28856
  const shortPeer = peerId.length > 16 ? peerId.slice(0, 16) + "..." : peerId;
28820
28857
  let user = this._stats.users.get(shortPeer);
@@ -28833,12 +28870,10 @@ ${this.formatConnectionInfo()}`);
28833
28870
  }
28834
28871
  user.requests++;
28835
28872
  user.lastSeen = Date.now();
28836
- if (record.tokens) {
28837
- user.tokensIn += record.tokens.input || 0;
28838
- user.tokensOut += record.tokens.output || 0;
28839
- }
28840
- if (record.model || record.capability) {
28841
- const modelName = record.model || record.capability.replace("inference:", "") || "unknown";
28873
+ user.tokensIn += tokIn;
28874
+ user.tokensOut += tokOut;
28875
+ if (record.model || record.capability || record.service) {
28876
+ const modelName = record.model || (record.capability || record.service || "").replace("inference:", "") || "unknown";
28842
28877
  this._stats.modelUsage.set(modelName, (this._stats.modelUsage.get(modelName) ?? 0) + 1);
28843
28878
  let mm = user.models.get(modelName);
28844
28879
  if (!mm) {
@@ -28847,10 +28882,8 @@ ${this.formatConnectionInfo()}`);
28847
28882
  }
28848
28883
  mm.requests++;
28849
28884
  mm.lastUsed = Date.now();
28850
- if (record.tokens) {
28851
- mm.tokensIn += record.tokens.input || 0;
28852
- mm.tokensOut += record.tokens.output || 0;
28853
- }
28885
+ mm.tokensIn += tokIn;
28886
+ mm.tokensOut += tokOut;
28854
28887
  }
28855
28888
  } catch {
28856
28889
  }
@@ -35307,6 +35340,44 @@ function fmtUptime(ms) {
35307
35340
  return `${Math.floor(sec / 60)}m ${sec % 60}s`;
35308
35341
  return `${Math.floor(sec / 3600)}h ${Math.floor(sec % 3600 / 60)}m`;
35309
35342
  }
35343
+ function getLocalSystemMetrics() {
35344
+ const os = __require("node:os");
35345
+ const cpus2 = os.cpus();
35346
+ const loads = os.loadavg();
35347
+ const totalMem = os.totalmem();
35348
+ const freeMem = os.freemem();
35349
+ const usedMem = totalMem - freeMem;
35350
+ const result = {
35351
+ cpuModel: cpus2[0]?.model?.trim() ?? "unknown",
35352
+ cpuCores: cpus2.length,
35353
+ cpuUtil: Math.min(100, Math.round(loads[0] / cpus2.length * 100)),
35354
+ memTotalGB: Math.round(totalMem / (1024 * 1024 * 1024) * 10) / 10,
35355
+ memUsedGB: Math.round(usedMem / (1024 * 1024 * 1024) * 10) / 10,
35356
+ memUtil: Math.round(usedMem / totalMem * 100),
35357
+ gpuAvailable: false,
35358
+ gpuName: "",
35359
+ gpuUtil: 0,
35360
+ vramUsedMB: 0,
35361
+ vramTotalMB: 0,
35362
+ vramUtil: 0
35363
+ };
35364
+ try {
35365
+ const { execSync: execSync29 } = __require("node:child_process");
35366
+ const smiOut = execSync29("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 });
35367
+ const line = smiOut.trim().split("\n")[0];
35368
+ if (line) {
35369
+ const parts = line.split(",").map((s) => s.trim());
35370
+ result.gpuAvailable = true;
35371
+ result.gpuUtil = parseInt(parts[0] || "0", 10) || 0;
35372
+ result.vramUsedMB = parseInt(parts[1] || "0", 10) || 0;
35373
+ result.vramTotalMB = parseInt(parts[2] || "0", 10) || 0;
35374
+ result.gpuName = parts[3] || "";
35375
+ result.vramUtil = result.vramTotalMB > 0 ? Math.round(result.vramUsedMB / result.vramTotalMB * 100) : 0;
35376
+ }
35377
+ } catch {
35378
+ }
35379
+ return result;
35380
+ }
35310
35381
  async function showExposeDashboard(gateway, rl) {
35311
35382
  const stdin = process.stdin;
35312
35383
  const stdout = process.stdout;
@@ -35319,6 +35390,7 @@ async function showExposeDashboard(gateway, rl) {
35319
35390
  let lastRenderedLines = 0;
35320
35391
  let refreshTimer = null;
35321
35392
  const hadRawMode = stdin.isRaw;
35393
+ let sysMetrics = getLocalSystemMetrics();
35322
35394
  const savedListeners = rl ? stdin.listeners("data").slice() : [];
35323
35395
  if (rl) {
35324
35396
  rl.pause();
@@ -35354,6 +35426,19 @@ async function showExposeDashboard(gateway, rl) {
35354
35426
  const bar = budgetColor("\u2588".repeat(filledLen)) + c2.dim("\u2591".repeat(barLen - filledLen));
35355
35427
  lines.push(` ${c2.cyan("Budget")} ${bar} ${budgetColor(`${pct}%`)} ${c2.dim(`(${fmtDashTokens(s.budgetTokensRemaining)}/${fmtDashTokens(s.budgetTokensTotal)})`)}`);
35356
35428
  }
35429
+ const sys = sysMetrics;
35430
+ lines.push("");
35431
+ lines.push(` ${c2.bold("System")}`);
35432
+ const cpuColor = sys.cpuUtil > 80 ? c2.red : sys.cpuUtil > 50 ? c2.yellow : c2.green;
35433
+ const memColor = sys.memUtil > 80 ? c2.red : sys.memUtil > 50 ? c2.yellow : c2.green;
35434
+ lines.push(` ${c2.cyan("CPU")} ${cpuColor(sys.cpuUtil + "%")} ${c2.dim(`(${sys.cpuCores} cores, ${sys.cpuModel.slice(0, 40)})`)}`);
35435
+ lines.push(` ${c2.cyan("RAM")} ${memColor(sys.memUtil + "%")} ${c2.dim(`(${sys.memUsedGB}/${sys.memTotalGB} GB)`)}`);
35436
+ if (sys.gpuAvailable) {
35437
+ const gpuColor = sys.gpuUtil > 80 ? c2.red : sys.gpuUtil > 50 ? c2.yellow : c2.green;
35438
+ const vramColor = sys.vramUtil > 80 ? c2.red : sys.vramUtil > 50 ? c2.yellow : c2.green;
35439
+ lines.push(` ${c2.cyan("GPU")} ${gpuColor(sys.gpuUtil + "%")} ${c2.dim(`(${sys.gpuName.trim()})`)}`);
35440
+ lines.push(` ${c2.cyan("VRAM")} ${vramColor(sys.vramUtil + "%")} ${c2.dim(`(${sys.vramUsedMB}/${sys.vramTotalMB} MB)`)}`);
35441
+ }
35357
35442
  const modelEntries = s.modelUsage ? Array.from(s.modelUsage.entries()).filter(([m]) => !DASH_INTERNAL.has(m)) : [];
35358
35443
  if (modelEntries.length > 0) {
35359
35444
  lines.push("");
@@ -35397,6 +35482,7 @@ async function showExposeDashboard(gateway, rl) {
35397
35482
  return lines;
35398
35483
  }
35399
35484
  function render() {
35485
+ sysMetrics = getLocalSystemMetrics();
35400
35486
  const lines = buildDashboard();
35401
35487
  if (lastRenderedLines > 0) {
35402
35488
  stdout.write(`\x1B[${lastRenderedLines}A`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.103.51",
3
+ "version": "0.103.52",
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",