open-agents-ai 0.187.225 → 0.187.226

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 +91 -25
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -287697,6 +287697,13 @@ var init_braille_spinner = __esm({
287697
287697
  });
287698
287698
 
287699
287699
  // packages/cli/src/tui/system-metrics.ts
287700
+ var system_metrics_exports = {};
287701
+ __export(system_metrics_exports, {
287702
+ SystemMetricsCollector: () => SystemMetricsCollector,
287703
+ formatRate: () => formatRate,
287704
+ getInstantSnapshot: () => getInstantSnapshot,
287705
+ instantaneousCpuPct: () => instantaneousCpuPct
287706
+ });
287700
287707
  import { loadavg as loadavg2, cpus as cpus3, totalmem as totalmem4, freemem as freemem3, platform as platform2 } from "node:os";
287701
287708
  import { exec as exec3 } from "node:child_process";
287702
287709
  import { readFile as readFile22 } from "node:fs/promises";
@@ -287824,14 +287831,39 @@ function getInstantSnapshot() {
287824
287831
  network: { rxBytesPerSec: 0, txBytesPerSec: 0 }
287825
287832
  };
287826
287833
  }
287834
+ function readCpuTimes() {
287835
+ let idle = 0;
287836
+ let total = 0;
287837
+ for (const cpu of cpus3()) {
287838
+ const t2 = cpu.times;
287839
+ idle += t2.idle;
287840
+ total += t2.user + t2.nice + t2.sys + t2.idle + t2.irq;
287841
+ }
287842
+ return { idle, total };
287843
+ }
287844
+ function instantaneousCpuPct() {
287845
+ const cur = readCpuTimes();
287846
+ const prev = _cpuPrevSnapshot;
287847
+ _cpuPrevSnapshot = cur;
287848
+ if (!prev) return -1;
287849
+ const idleDelta = cur.idle - prev.idle;
287850
+ const totalDelta = cur.total - prev.total;
287851
+ if (totalDelta <= 0) return 0;
287852
+ const usage = 1 - idleDelta / totalDelta;
287853
+ return Math.max(0, Math.min(100, Math.round(usage * 100)));
287854
+ }
287827
287855
  function collectCpuRam() {
287828
- const [l1] = loadavg2();
287829
287856
  const cores = cpus3().length;
287830
287857
  const cpuModel = cpus3()[0]?.model ?? "";
287831
287858
  const totalMem = totalmem4();
287832
287859
  const usedMem = totalMem - freemem3();
287860
+ let cpuUtil = instantaneousCpuPct();
287861
+ if (cpuUtil < 0) {
287862
+ const [l1] = loadavg2();
287863
+ cpuUtil = Math.max(0, Math.min(100, Math.round(l1 / cores * 100)));
287864
+ }
287833
287865
  return {
287834
- cpuUtil: Math.min(100, Math.round(l1 / cores * 100)),
287866
+ cpuUtil,
287835
287867
  cpuCores: cores,
287836
287868
  cpuModel,
287837
287869
  memUtil: Math.round(usedMem / totalMem * 100),
@@ -287863,12 +287895,13 @@ async function collectLocalMetrics() {
287863
287895
  network
287864
287896
  };
287865
287897
  }
287866
- var _lastNetSnapshot, _nvidiaSmiAvailable, SystemMetricsCollector;
287898
+ var _lastNetSnapshot, _nvidiaSmiAvailable, _cpuPrevSnapshot, SystemMetricsCollector;
287867
287899
  var init_system_metrics = __esm({
287868
287900
  "packages/cli/src/tui/system-metrics.ts"() {
287869
287901
  "use strict";
287870
287902
  _lastNetSnapshot = null;
287871
287903
  _nvidiaSmiAvailable = null;
287904
+ _cpuPrevSnapshot = null;
287872
287905
  SystemMetricsCollector = class {
287873
287906
  _timer = null;
287874
287907
  _source = "local";
@@ -318887,7 +318920,10 @@ async function sendMessage() {
318887
318920
  actions.appendChild(copyBtn);
318888
318921
  msgDiv.appendChild(actions);
318889
318922
  } catch (err) {
318890
- msgDiv.innerHTML = '<span style="color:#ff4444">Error: ' + escHtml(err.message) + '</span>';
318923
+ // Match the red left-border styling used by failed tool_result
318924
+ // and the stop-button. Sits inside the assistant bubble so it
318925
+ // visually parents to the same turn the user initiated.
318926
+ msgDiv.innerHTML = '<div style="background:#2a1e1e;border-left:3px solid #ff4444;color:#ff4444;padding:6px 10px 6px 14px;margin:3px 0;font-family:inherit"><div style="color:#ff4444;font-size:0.6rem;text-transform:uppercase;letter-spacing:0.08em;margin-bottom:2px">\\u25B8 error</div><div style="color:#ff7777;white-space:pre-wrap;word-break:break-word">' + escHtml(err.message) + '</div></div>';
318891
318927
  }
318892
318928
 
318893
318929
  streaming = false;
@@ -319193,7 +319229,7 @@ async function submitAgentTask() {
319193
319229
  }
319194
319230
  }
319195
319231
  } catch (err) {
319196
- eventsDiv.innerHTML += '<div style="color:#ff4444">Error: ' + escHtml(err.message) + '</div>';
319232
+ eventsDiv.innerHTML += '<div style="background:#2a1e1e;border-left:3px solid #ff4444;color:#ff7777;padding:6px 10px 6px 14px;margin:3px 0"><div style="color:#ff4444;font-size:0.6rem;text-transform:uppercase;letter-spacing:0.08em;margin-bottom:2px">\\u25B8 error</div>' + escHtml(err.message) + '</div>';
319197
319233
  }
319198
319234
  document.getElementById('agent-submit').style.display = 'inline-block';
319199
319235
  document.getElementById('agent-abort').style.display = 'none';
@@ -320404,13 +320440,39 @@ function hideProcPopover() {
320404
320440
  procPopover.classList.remove('visible');
320405
320441
  }
320406
320442
 
320443
+ // Render a transient error toast in the conversation with the same
320444
+ // red-left-border styling used by failed tool_result entries. Replaces
320445
+ // alert() popups so users can see "Task not found" inline with the
320446
+ // rest of the agent's activity instead of in a modal.
320447
+ function renderInlineError(message) {
320448
+ const conv = document.getElementById('conversation');
320449
+ if (!conv) {
320450
+ // Fallback if conversation doesn't exist (config tab, etc.)
320451
+ console.error(message);
320452
+ return;
320453
+ }
320454
+ const wrap = document.createElement('div');
320455
+ wrap.className = 'msg assistant';
320456
+ wrap.innerHTML = '<div style="background:#2a1e1e;border-left:3px solid #ff4444;color:#ff7777;padding:6px 10px 6px 14px;margin:3px 0;font-family:inherit"><div style="color:#ff4444;font-size:0.6rem;text-transform:uppercase;letter-spacing:0.08em;margin-bottom:2px">\\u25B8 error</div><div style="color:#ff7777;white-space:pre-wrap;word-break:break-word">' + escHtml(message) + '</div></div>';
320457
+ conv.appendChild(wrap);
320458
+ maybeAutoScroll();
320459
+ }
320460
+
320407
320461
  async function killRun(id) {
320408
320462
  try {
320409
320463
  const r = await fetch('/v1/runs/' + encodeURIComponent(id), { method: 'DELETE', headers: headers() });
320410
320464
  const text = await r.text().catch(() => '');
320411
- alert('Kill ' + id + ': ' + r.status + (text ? ' — ' + text.slice(0, 100) : ''));
320465
+ if (!r.ok) {
320466
+ // Try to extract a clean error message from the response body
320467
+ let msg = 'Kill ' + id + ' (HTTP ' + r.status + ')';
320468
+ try {
320469
+ const j = JSON.parse(text);
320470
+ if (j.error) msg = String(j.error);
320471
+ } catch { if (text) msg = text.slice(0, 200); }
320472
+ renderInlineError(msg);
320473
+ }
320412
320474
  } catch (e) {
320413
- alert('Kill failed: ' + e.message);
320475
+ renderInlineError('Kill failed: ' + (e && e.message || String(e)));
320414
320476
  }
320415
320477
  hideProcPopover();
320416
320478
  }
@@ -320418,10 +320480,21 @@ async function killRun(id) {
320418
320480
  async function viewRun(id) {
320419
320481
  try {
320420
320482
  const r = await fetch('/v1/runs/' + encodeURIComponent(id), { headers: headers() });
320483
+ if (!r.ok) {
320484
+ const text = await r.text().catch(() => '');
320485
+ let msg = 'View ' + id + ' (HTTP ' + r.status + ')';
320486
+ try { const j = JSON.parse(text); if (j.error) msg = String(j.error); }
320487
+ catch { if (text) msg = text.slice(0, 200); }
320488
+ renderInlineError(msg);
320489
+ return;
320490
+ }
320421
320491
  const j = await r.json();
320492
+ // Detail rendering still uses alert because the JSON dump is huge
320493
+ // and overflowing the conversation isn't useful — but errors fall
320494
+ // through to the inline path.
320422
320495
  alert(JSON.stringify(j, null, 2).slice(0, 1500));
320423
320496
  } catch (e) {
320424
- alert('Fetch failed: ' + e.message);
320497
+ renderInlineError('Fetch failed: ' + (e && e.message || String(e)));
320425
320498
  }
320426
320499
  }
320427
320500
 
@@ -324203,8 +324276,12 @@ async function handleRequest(req2, res, ollamaUrl, verbose) {
324203
324276
  const freeMem = os8.freemem();
324204
324277
  const totalMem = os8.totalmem();
324205
324278
  const ramUsedPct = Math.round((1 - freeMem / totalMem) * 100);
324206
- const cpuLoad = os8.loadavg()[0] ?? 0;
324207
- const cpuPct = Math.min(100, Math.round(cpuLoad / os8.cpus().length * 100));
324279
+ const { instantaneousCpuPct: instantaneousCpuPct2 } = await Promise.resolve().then(() => (init_system_metrics(), system_metrics_exports));
324280
+ let cpuPct = instantaneousCpuPct2();
324281
+ if (cpuPct < 0) {
324282
+ const cpuLoad = os8.loadavg()[0] ?? 0;
324283
+ cpuPct = Math.max(0, Math.min(100, Math.round(cpuLoad / os8.cpus().length * 100)));
324284
+ }
324208
324285
  let gpuUtil = [];
324209
324286
  try {
324210
324287
  const util2 = es("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total --format=csv,noheader,nounits", { encoding: "utf8", timeout: 3e3, stdio: "pipe" });
@@ -324706,7 +324783,8 @@ ${historyLines}
324706
324783
  addCheckinMessage(checkinSession, body.message);
324707
324784
  } catch {
324708
324785
  }
324709
- let acknowledgment = "Got it, adapting course.";
324786
+ const truncatedInput = body.message.length > 80 ? body.message.slice(0, 77) + "..." : body.message;
324787
+ let acknowledgment = `Acknowledged: ${truncatedInput}`;
324710
324788
  let steering = body.message;
324711
324789
  try {
324712
324790
  const cfg = loadConfig();
@@ -330537,20 +330615,8 @@ ${result.text}`;
330537
330615
  `- summary: expanded instruction for the main agent (e.g. "The user wants X instead of Y. Adjust your approach to prioritize Z. Specifically, they are asking you to...")`
330538
330616
  ].join("\n");
330539
330617
  const result = await steerAgent.run(steerPrompt, "Steering sub-agent — interpret user input and produce instruction.");
330540
- const STEER_FALLBACKS = [
330541
- `Noted, changing course.`,
330542
- `On it, shifting approach.`,
330543
- `Understood, recalibrating.`,
330544
- `Right, let me rework that.`,
330545
- `Okay, taking a different angle.`,
330546
- `Heard you, pivoting now.`,
330547
- `Sure thing, rethinking this.`,
330548
- `Copy that, adapting.`,
330549
- `Makes sense, re-routing.`,
330550
- `Roger, new plan.`
330551
- ];
330552
- const fbIdx = Math.floor(Math.random() * STEER_FALLBACKS.length);
330553
- let acknowledgment = STEER_FALLBACKS[fbIdx];
330618
+ const truncatedInputForAck = input.length > 80 ? input.slice(0, 77) + "..." : input;
330619
+ let acknowledgment = `Acknowledged: ${truncatedInputForAck}`;
330554
330620
  let steering = input;
330555
330621
  try {
330556
330622
  const parsed = JSON.parse(result.summary || "{}");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.225",
3
+ "version": "0.187.226",
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",