open-agents-ai 0.103.87 → 0.103.89

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 +403 -82
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11057,9 +11057,9 @@ function getVersion(binary) {
11057
11057
  }
11058
11058
  }
11059
11059
  function installOpencode() {
11060
- const platform4 = process.platform;
11060
+ const platform5 = process.platform;
11061
11061
  try {
11062
- if (platform4 === "win32") {
11062
+ if (platform5 === "win32") {
11063
11063
  execSync19('powershell -Command "irm https://opencode.ai/install | iex"', {
11064
11064
  stdio: "pipe",
11065
11065
  timeout: 12e4
@@ -11331,9 +11331,9 @@ function getVersion2(binary) {
11331
11331
  }
11332
11332
  }
11333
11333
  function installDroid() {
11334
- const platform4 = process.platform;
11334
+ const platform5 = process.platform;
11335
11335
  try {
11336
- if (platform4 === "win32") {
11336
+ if (platform5 === "win32") {
11337
11337
  execSync20('powershell -Command "irm https://app.factory.ai/cli/windows | iex"', {
11338
11338
  stdio: "pipe",
11339
11339
  timeout: 12e4
@@ -16925,8 +16925,8 @@ var init_code_retriever = __esm({
16925
16925
  });
16926
16926
  }
16927
16927
  async getFileContent(filePath, startLine, endLine) {
16928
- const { readFile: readFile17 } = await import("node:fs/promises");
16929
- const content = await readFile17(filePath, "utf-8");
16928
+ const { readFile: readFile18 } = await import("node:fs/promises");
16929
+ const content = await readFile18(filePath, "utf-8");
16930
16930
  if (startLine === void 0)
16931
16931
  return content;
16932
16932
  const lines = content.split("\n");
@@ -22272,8 +22272,8 @@ function isTranscribablePath(path) {
22272
22272
  return isAudioPath(path) || isVideoPath(path);
22273
22273
  }
22274
22274
  function findMicCaptureCommand() {
22275
- const platform4 = process.platform;
22276
- if (platform4 === "linux") {
22275
+ const platform5 = process.platform;
22276
+ if (platform5 === "linux") {
22277
22277
  try {
22278
22278
  execSync23("which arecord", { stdio: "pipe" });
22279
22279
  return {
@@ -22283,7 +22283,7 @@ function findMicCaptureCommand() {
22283
22283
  } catch {
22284
22284
  }
22285
22285
  }
22286
- if (platform4 === "darwin") {
22286
+ if (platform5 === "darwin") {
22287
22287
  try {
22288
22288
  execSync23("which sox", { stdio: "pipe" });
22289
22289
  return {
@@ -22295,7 +22295,7 @@ function findMicCaptureCommand() {
22295
22295
  }
22296
22296
  try {
22297
22297
  execSync23("which ffmpeg", { stdio: "pipe" });
22298
- if (platform4 === "linux") {
22298
+ if (platform5 === "linux") {
22299
22299
  return {
22300
22300
  cmd: "ffmpeg",
22301
22301
  args: [
@@ -22314,7 +22314,7 @@ function findMicCaptureCommand() {
22314
22314
  "pipe:1"
22315
22315
  ]
22316
22316
  };
22317
- } else if (platform4 === "darwin") {
22317
+ } else if (platform5 === "darwin") {
22318
22318
  return {
22319
22319
  cmd: "ffmpeg",
22320
22320
  args: [
@@ -22397,9 +22397,9 @@ function ensureTranscribeCliBackground() {
22397
22397
  } catch {
22398
22398
  }
22399
22399
  try {
22400
- const { exec: exec3 } = await import("node:child_process");
22400
+ const { exec: exec4 } = await import("node:child_process");
22401
22401
  return new Promise((resolve31) => {
22402
- exec3("npm i -g transcribe-cli", { timeout: 18e4 }, (err) => {
22402
+ exec4("npm i -g transcribe-cli", { timeout: 18e4 }, (err) => {
22403
22403
  resolve31(!err);
22404
22404
  });
22405
22405
  });
@@ -36125,7 +36125,7 @@ async function handleUpdate(subcommand, ctx) {
36125
36125
  process.stdout.write("\n");
36126
36126
  const checkSpinner = startInlineSpinner(`Checking for updates ${c2.dim(`(current: v${currentVersion})`)}`);
36127
36127
  const info = await checkForUpdate(currentVersion, true);
36128
- const { exec: exec3, execSync: es2 } = await import("node:child_process");
36128
+ const { exec: exec4, execSync: es2 } = await import("node:child_process");
36129
36129
  let needsSudo = false;
36130
36130
  try {
36131
36131
  const prefix = es2("npm prefix -g", { encoding: "utf8", timeout: 5e3 }).trim();
@@ -36139,7 +36139,7 @@ async function handleUpdate(subcommand, ctx) {
36139
36139
  }
36140
36140
  let installError = "";
36141
36141
  const runInstall2 = (cmd) => new Promise((resolve31) => {
36142
- const child = exec3(cmd, { timeout: 18e4 }, (err, _stdout, stderr) => {
36142
+ const child = exec4(cmd, { timeout: 18e4 }, (err, _stdout, stderr) => {
36143
36143
  if (err)
36144
36144
  installError = (stderr || err.message || "").trim();
36145
36145
  resolve31(!err);
@@ -36226,7 +36226,7 @@ async function handleUpdate(subcommand, ctx) {
36226
36226
  }
36227
36227
  const rebuildSpinner = startInlineSpinner("Rebuilding native modules");
36228
36228
  const rebuildOk = await new Promise((resolve31) => {
36229
- const child = exec3(`${sudoPrefix}npm rebuild -g open-agents-ai 2>/dev/null || true`, { timeout: 12e4 }, () => resolve31(true));
36229
+ const child = exec4(`${sudoPrefix}npm rebuild -g open-agents-ai 2>/dev/null || true`, { timeout: 12e4 }, () => resolve31(true));
36230
36230
  child.stdout?.resume();
36231
36231
  child.stderr?.resume();
36232
36232
  });
@@ -36259,7 +36259,7 @@ async function handleUpdate(subcommand, ctx) {
36259
36259
  if (fsExists(venvPip)) {
36260
36260
  const pySpinner = startInlineSpinner("Upgrading Python venv packages");
36261
36261
  const pyOk = await new Promise((resolve31) => {
36262
- const child = exec3(`"${venvPip}" install --upgrade moondream-station pytesseract Pillow opencv-python-headless numpy 2>/dev/null || true`, { timeout: 3e5 }, (err) => resolve31(!err));
36262
+ const child = exec4(`"${venvPip}" install --upgrade moondream-station pytesseract Pillow opencv-python-headless numpy 2>/dev/null || true`, { timeout: 3e5 }, (err) => resolve31(!err));
36263
36263
  child.stdout?.resume();
36264
36264
  child.stderr?.resume();
36265
36265
  });
@@ -36406,15 +36406,15 @@ function fmtUptime(ms) {
36406
36406
  }
36407
36407
  function getLocalSystemMetrics() {
36408
36408
  const os = __require("node:os");
36409
- const cpus2 = os.cpus();
36409
+ const cpus3 = os.cpus();
36410
36410
  const loads = os.loadavg();
36411
36411
  const totalMem = os.totalmem();
36412
36412
  const freeMem = os.freemem();
36413
36413
  const usedMem = totalMem - freeMem;
36414
36414
  const result = {
36415
- cpuModel: cpus2[0]?.model?.trim() ?? "unknown",
36416
- cpuCores: cpus2.length,
36417
- cpuUtil: Math.min(100, Math.round(loads[0] / cpus2.length * 100)),
36415
+ cpuModel: cpus3[0]?.model?.trim() ?? "unknown",
36416
+ cpuCores: cpus3.length,
36417
+ cpuUtil: Math.min(100, Math.round(loads[0] / cpus3.length * 100)),
36418
36418
  memTotalGB: Math.round(totalMem / (1024 * 1024 * 1024) * 10) / 10,
36419
36419
  memUsedGB: Math.round(usedMem / (1024 * 1024 * 1024) * 10) / 10,
36420
36420
  memUtil: Math.round(usedMem / totalMem * 100),
@@ -45719,6 +45719,267 @@ var init_braille_spinner = __esm({
45719
45719
  }
45720
45720
  });
45721
45721
 
45722
+ // packages/cli/dist/tui/system-metrics.js
45723
+ import { loadavg as loadavg2, cpus as cpus2, totalmem as totalmem2, freemem as freemem2, platform as platform4 } from "node:os";
45724
+ import { exec as exec3 } from "node:child_process";
45725
+ import { readFile as readFile16 } from "node:fs/promises";
45726
+ function formatRate(bytesPerSec) {
45727
+ if (bytesPerSec < 1024)
45728
+ return `${Math.round(bytesPerSec)}B`;
45729
+ if (bytesPerSec < 1024 * 1024)
45730
+ return `${(bytesPerSec / 1024).toFixed(1)}K`;
45731
+ if (bytesPerSec < 1024 * 1024 * 1024)
45732
+ return `${(bytesPerSec / (1024 * 1024)).toFixed(1)}M`;
45733
+ return `${(bytesPerSec / (1024 * 1024 * 1024)).toFixed(2)}G`;
45734
+ }
45735
+ async function readProcNetDev() {
45736
+ try {
45737
+ const data = await readFile16("/proc/net/dev", "utf8");
45738
+ let rxTotal = 0;
45739
+ let txTotal = 0;
45740
+ for (const line of data.split("\n")) {
45741
+ const trimmed = line.trim();
45742
+ if (trimmed.startsWith("Inter") || trimmed.startsWith("face") || trimmed.startsWith("lo:"))
45743
+ continue;
45744
+ const match = trimmed.match(/^\S+:\s*(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)/);
45745
+ if (match) {
45746
+ rxTotal += parseInt(match[1], 10);
45747
+ txTotal += parseInt(match[2], 10);
45748
+ }
45749
+ }
45750
+ return { rxBytes: rxTotal, txBytes: txTotal };
45751
+ } catch {
45752
+ return null;
45753
+ }
45754
+ }
45755
+ async function collectNetworkMetrics() {
45756
+ const now = Date.now();
45757
+ const plat = platform4();
45758
+ if (plat === "linux") {
45759
+ const snap = await readProcNetDev();
45760
+ if (!snap)
45761
+ return { rxBytesPerSec: 0, txBytesPerSec: 0 };
45762
+ const current = { rxBytes: snap.rxBytes, txBytes: snap.txBytes, timestamp: now };
45763
+ if (!_lastNetSnapshot) {
45764
+ _lastNetSnapshot = current;
45765
+ return { rxBytesPerSec: 0, txBytesPerSec: 0 };
45766
+ }
45767
+ const dtSec = Math.max(0.1, (now - _lastNetSnapshot.timestamp) / 1e3);
45768
+ const rxRate = Math.max(0, (current.rxBytes - _lastNetSnapshot.rxBytes) / dtSec);
45769
+ const txRate = Math.max(0, (current.txBytes - _lastNetSnapshot.txBytes) / dtSec);
45770
+ _lastNetSnapshot = current;
45771
+ return { rxBytesPerSec: rxRate, txBytesPerSec: txRate };
45772
+ }
45773
+ if (plat === "darwin") {
45774
+ try {
45775
+ const output = await new Promise((resolve31, reject) => {
45776
+ exec3("netstat -ib 2>/dev/null | head -30", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve31(stdout));
45777
+ });
45778
+ let rxBytes = 0, txBytes = 0;
45779
+ for (const line of output.split("\n")) {
45780
+ if (line.includes("en0") && !line.includes("Name")) {
45781
+ const parts = line.trim().split(/\s+/);
45782
+ if (parts.length >= 10) {
45783
+ rxBytes = parseInt(parts[6] ?? "0", 10) || 0;
45784
+ txBytes = parseInt(parts[9] ?? "0", 10) || 0;
45785
+ break;
45786
+ }
45787
+ }
45788
+ }
45789
+ const current = { rxBytes, txBytes, timestamp: now };
45790
+ if (!_lastNetSnapshot) {
45791
+ _lastNetSnapshot = current;
45792
+ return { rxBytesPerSec: 0, txBytesPerSec: 0 };
45793
+ }
45794
+ const dtSec = Math.max(0.1, (now - _lastNetSnapshot.timestamp) / 1e3);
45795
+ const rxRate = Math.max(0, (current.rxBytes - _lastNetSnapshot.rxBytes) / dtSec);
45796
+ const txRate = Math.max(0, (current.txBytes - _lastNetSnapshot.txBytes) / dtSec);
45797
+ _lastNetSnapshot = current;
45798
+ return { rxBytesPerSec: rxRate, txBytesPerSec: txRate };
45799
+ } catch {
45800
+ return { rxBytesPerSec: 0, txBytesPerSec: 0 };
45801
+ }
45802
+ }
45803
+ return { rxBytesPerSec: 0, txBytesPerSec: 0 };
45804
+ }
45805
+ async function collectGpuMetrics() {
45806
+ const noGpu = { available: false, name: "", utilization: 0, vramUsedMB: 0, vramTotalMB: 0, vramUtilization: 0 };
45807
+ if (_nvidiaSmiAvailable === false)
45808
+ return noGpu;
45809
+ try {
45810
+ const smi = await new Promise((resolve31, reject) => {
45811
+ exec3("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve31(stdout));
45812
+ });
45813
+ _nvidiaSmiAvailable = true;
45814
+ const line = smi.trim().split("\n")[0];
45815
+ if (!line)
45816
+ return noGpu;
45817
+ const parts = line.split(",").map((s) => s.trim());
45818
+ const vramUsed = parseInt(parts[1] ?? "0", 10) || 0;
45819
+ const vramTotal = parseInt(parts[2] ?? "0", 10) || 0;
45820
+ return {
45821
+ available: true,
45822
+ utilization: parseInt(parts[0] ?? "0", 10) || 0,
45823
+ vramUsedMB: vramUsed,
45824
+ vramTotalMB: vramTotal,
45825
+ name: parts[3] ?? "",
45826
+ vramUtilization: vramTotal > 0 ? Math.round(vramUsed / vramTotal * 100) : 0
45827
+ };
45828
+ } catch {
45829
+ _nvidiaSmiAvailable = false;
45830
+ return noGpu;
45831
+ }
45832
+ }
45833
+ function collectCpuRam() {
45834
+ const [l1] = loadavg2();
45835
+ const cores = cpus2().length;
45836
+ const cpuModel = cpus2()[0]?.model ?? "";
45837
+ const totalMem = totalmem2();
45838
+ const usedMem = totalMem - freemem2();
45839
+ return {
45840
+ cpuUtil: Math.min(100, Math.round(l1 / cores * 100)),
45841
+ cpuCores: cores,
45842
+ cpuModel,
45843
+ memUtil: Math.round(usedMem / totalMem * 100),
45844
+ memUsedGB: Math.round(usedMem / 1024 ** 3 * 10) / 10,
45845
+ memTotalGB: Math.round(totalMem / 1024 ** 3 * 10) / 10
45846
+ };
45847
+ }
45848
+ async function collectLocalMetrics() {
45849
+ const cpuRam = collectCpuRam();
45850
+ const [gpu, network] = await Promise.all([
45851
+ collectGpuMetrics(),
45852
+ collectNetworkMetrics()
45853
+ ]);
45854
+ return {
45855
+ source: "local",
45856
+ hardware: {
45857
+ cpuUtil: cpuRam.cpuUtil,
45858
+ cpuCores: cpuRam.cpuCores,
45859
+ cpuModel: cpuRam.cpuModel,
45860
+ gpuUtil: gpu.available ? gpu.utilization : -1,
45861
+ gpuName: gpu.name,
45862
+ vramUtil: gpu.available ? gpu.vramUtilization : -1,
45863
+ vramUsedMB: gpu.vramUsedMB,
45864
+ vramTotalMB: gpu.vramTotalMB,
45865
+ memUtil: cpuRam.memUtil,
45866
+ memUsedGB: cpuRam.memUsedGB,
45867
+ memTotalGB: cpuRam.memTotalGB
45868
+ },
45869
+ network
45870
+ };
45871
+ }
45872
+ var _lastNetSnapshot, _nvidiaSmiAvailable, SystemMetricsCollector;
45873
+ var init_system_metrics = __esm({
45874
+ "packages/cli/dist/tui/system-metrics.js"() {
45875
+ "use strict";
45876
+ _lastNetSnapshot = null;
45877
+ _nvidiaSmiAvailable = null;
45878
+ SystemMetricsCollector = class {
45879
+ _timer = null;
45880
+ _source = "local";
45881
+ _callback = null;
45882
+ _latest = null;
45883
+ _intervalMs = 3e3;
45884
+ _collecting = false;
45885
+ /** Current metrics snapshot (may be null before first poll) */
45886
+ get latest() {
45887
+ return this._latest;
45888
+ }
45889
+ /** Current source mode */
45890
+ get source() {
45891
+ return this._source;
45892
+ }
45893
+ /**
45894
+ * Start collecting LOCAL metrics on an interval.
45895
+ * @param callback Called each time new metrics arrive
45896
+ * @param intervalMs Polling interval (default 3000ms)
45897
+ */
45898
+ startLocal(callback, intervalMs = 3e3) {
45899
+ this.stop();
45900
+ this._source = "local";
45901
+ this._callback = callback;
45902
+ this._intervalMs = intervalMs;
45903
+ this._poll();
45904
+ this._timer = setInterval(() => this._poll(), intervalMs);
45905
+ }
45906
+ /**
45907
+ * Switch to REMOTE mode — stops local polling, accepts pushed metrics.
45908
+ * Call pushRemoteMetrics() to feed data from the remote provider.
45909
+ */
45910
+ startRemote(callback) {
45911
+ this.stop();
45912
+ this._source = "remote";
45913
+ this._callback = callback;
45914
+ this._timer = setInterval(() => this._pollNetworkOnly(), this._intervalMs);
45915
+ this._pollNetworkOnly();
45916
+ }
45917
+ /**
45918
+ * Push hardware metrics received from a remote /expose provider.
45919
+ * Network metrics are always collected locally regardless.
45920
+ */
45921
+ pushRemoteMetrics(hw) {
45922
+ if (this._source !== "remote")
45923
+ return;
45924
+ const hardware = {
45925
+ cpuUtil: hw.cpuUtil ?? -1,
45926
+ cpuCores: hw.cpuCores ?? 0,
45927
+ cpuModel: hw.cpuModel ?? "",
45928
+ gpuUtil: hw.gpuUtil ?? -1,
45929
+ gpuName: hw.gpuName ?? "",
45930
+ vramUtil: hw.vramUtil ?? -1,
45931
+ vramUsedMB: hw.vramUsedMB ?? 0,
45932
+ vramTotalMB: hw.vramTotalMB ?? 0,
45933
+ memUtil: hw.memUtil ?? -1,
45934
+ memUsedGB: hw.memUsedGB ?? 0,
45935
+ memTotalGB: hw.memTotalGB ?? 0
45936
+ };
45937
+ this._latest = {
45938
+ source: "remote",
45939
+ hardware,
45940
+ network: this._latest?.network ?? { rxBytesPerSec: 0, txBytesPerSec: 0 }
45941
+ };
45942
+ this._callback?.(this._latest);
45943
+ }
45944
+ /** Stop all polling and clear state */
45945
+ stop() {
45946
+ if (this._timer) {
45947
+ clearInterval(this._timer);
45948
+ this._timer = null;
45949
+ }
45950
+ this._latest = null;
45951
+ this._callback = null;
45952
+ this._collecting = false;
45953
+ }
45954
+ /** Whether the collector is active */
45955
+ get isActive() {
45956
+ return this._timer !== null;
45957
+ }
45958
+ async _poll() {
45959
+ if (this._collecting)
45960
+ return;
45961
+ this._collecting = true;
45962
+ try {
45963
+ this._latest = await collectLocalMetrics();
45964
+ this._callback?.(this._latest);
45965
+ } catch {
45966
+ }
45967
+ this._collecting = false;
45968
+ }
45969
+ async _pollNetworkOnly() {
45970
+ try {
45971
+ const network = await collectNetworkMetrics();
45972
+ if (this._latest) {
45973
+ this._latest = { ...this._latest, network };
45974
+ this._callback?.(this._latest);
45975
+ }
45976
+ } catch {
45977
+ }
45978
+ }
45979
+ };
45980
+ }
45981
+ });
45982
+
45722
45983
  // packages/cli/dist/tui/status-bar.js
45723
45984
  var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, StatusBar;
45724
45985
  var init_status_bar = __esm({
@@ -45726,6 +45987,7 @@ var init_status_bar = __esm({
45726
45987
  "use strict";
45727
45988
  init_render();
45728
45989
  init_braille_spinner();
45990
+ init_system_metrics();
45729
45991
  EXPERT_TOOL_BASELINES = {
45730
45992
  file_read: 12,
45731
45993
  structured_read: 15,
@@ -46145,39 +46407,77 @@ var init_status_bar = __esm({
46145
46407
  if (this.active)
46146
46408
  this.renderFooterPreserveCursor();
46147
46409
  }
46148
- /** Remote host metrics (when connected to a remote endpoint) */
46149
- _remoteMetrics = null;
46410
+ /** Unified system metrics collector (local or remote) */
46411
+ _metricsCollector = new SystemMetricsCollector();
46412
+ /** Cached unified metrics snapshot — updated by collector callback */
46413
+ _unifiedMetrics = null;
46414
+ /** Legacy remote metrics polling timer (for peer/HTTP polling) */
46150
46415
  _remoteMetricsTimer = null;
46151
46416
  /** Update remote host system metrics (from polling /v1/system/metrics) */
46152
46417
  setRemoteMetrics(metrics) {
46153
- this._remoteMetrics = {
46154
- ...metrics,
46418
+ if (!this._metricsCollector.isActive || this._metricsCollector.source !== "remote") {
46419
+ this._metricsCollector.startRemote((m) => {
46420
+ this._unifiedMetrics = m;
46421
+ if (this.active)
46422
+ this.renderFooterPreserveCursor();
46423
+ });
46424
+ }
46425
+ this._metricsCollector.pushRemoteMetrics({
46426
+ cpuUtil: metrics.cpuUtil,
46155
46427
  cpuCores: metrics.cpuCores ?? 0,
46156
46428
  cpuModel: metrics.cpuModel ?? "",
46429
+ gpuUtil: metrics.gpuUtil,
46430
+ gpuName: metrics.gpuName,
46431
+ vramUtil: metrics.vramUtil,
46157
46432
  vramUsedMB: metrics.vramUsedMB ?? 0,
46158
46433
  vramTotalMB: metrics.vramTotalMB ?? 0,
46434
+ memUtil: metrics.memUtil,
46159
46435
  memTotalGB: metrics.memTotalGB ?? 0,
46160
46436
  memUsedGB: metrics.memUsedGB ?? 0
46161
- };
46162
- if (this.active)
46163
- this.renderFooterPreserveCursor();
46437
+ });
46164
46438
  }
46165
- /** Clear remote metrics (e.g. when switching to local endpoint) */
46439
+ /** Clear remote metrics and switch back to local collection */
46166
46440
  clearRemoteMetrics() {
46167
- this._remoteMetrics = null;
46441
+ this._unifiedMetrics = null;
46168
46442
  if (this._remoteMetricsTimer) {
46169
46443
  clearInterval(this._remoteMetricsTimer);
46170
46444
  this._remoteMetricsTimer = null;
46171
46445
  }
46446
+ this.startLocalMetrics();
46172
46447
  if (this.active)
46173
46448
  this.renderFooterPreserveCursor();
46174
46449
  }
46450
+ /**
46451
+ * Start collecting LOCAL system metrics (CPU/RAM/GPU + network I/O).
46452
+ * Called automatically on startup when endpoint is local.
46453
+ */
46454
+ startLocalMetrics(intervalMs = 3e3) {
46455
+ this._metricsCollector.startLocal((m) => {
46456
+ this._unifiedMetrics = m;
46457
+ if (this.active)
46458
+ this.renderFooterPreserveCursor();
46459
+ }, intervalMs);
46460
+ }
46461
+ /** Stop all metrics collection (local and remote) */
46462
+ stopAllMetrics() {
46463
+ this._metricsCollector.stop();
46464
+ this._unifiedMetrics = null;
46465
+ if (this._remoteMetricsTimer) {
46466
+ clearInterval(this._remoteMetricsTimer);
46467
+ this._remoteMetricsTimer = null;
46468
+ }
46469
+ }
46175
46470
  /**
46176
46471
  * Start polling a remote endpoint for system metrics.
46177
46472
  * Call when /endpoint is set to a remote URL that has /v1/system/metrics.
46178
46473
  */
46179
46474
  startRemoteMetricsPolling(endpointUrl, authKey) {
46180
46475
  this.stopRemoteMetricsPolling();
46476
+ this._metricsCollector.startRemote((m) => {
46477
+ this._unifiedMetrics = m;
46478
+ if (this.active)
46479
+ this.renderFooterPreserveCursor();
46480
+ });
46181
46481
  const poll = async () => {
46182
46482
  try {
46183
46483
  const url = new URL("/v1/system/metrics", endpointUrl);
@@ -46208,6 +46508,11 @@ var init_status_bar = __esm({
46208
46508
  */
46209
46509
  startPeerMetricsPolling(sendCommand, peerId, authKey) {
46210
46510
  this.stopRemoteMetricsPolling();
46511
+ this._metricsCollector.startRemote((m) => {
46512
+ this._unifiedMetrics = m;
46513
+ if (this.active)
46514
+ this.renderFooterPreserveCursor();
46515
+ });
46211
46516
  const poll = async () => {
46212
46517
  try {
46213
46518
  const queryData = { type: "query" };
@@ -46288,7 +46593,7 @@ var init_status_bar = __esm({
46288
46593
  clearInterval(this._remoteMetricsTimer);
46289
46594
  this._remoteMetricsTimer = null;
46290
46595
  }
46291
- this._remoteMetrics = null;
46596
+ this._unifiedMetrics = null;
46292
46597
  }
46293
46598
  /** Update token metrics from a token_usage event */
46294
46599
  updateMetrics(update) {
@@ -46349,10 +46654,14 @@ var init_status_bar = __esm({
46349
46654
  this.applyScrollRegion();
46350
46655
  this.renderFooterAndPositionInput();
46351
46656
  this.hookStdin();
46657
+ if (!this._metricsCollector.isActive) {
46658
+ this.startLocalMetrics();
46659
+ }
46352
46660
  }
46353
46661
  /** Deactivate — restore full-screen scroll region */
46354
46662
  deactivate() {
46355
46663
  this.active = false;
46664
+ this.stopAllMetrics();
46356
46665
  const rows = process.stdout.rows ?? 24;
46357
46666
  process.stdout.write(`\x1B[1;${rows}r`);
46358
46667
  }
@@ -46422,28 +46731,28 @@ var init_status_bar = __esm({
46422
46731
  const pos = this.rowPositions(rows);
46423
46732
  const w = getTermWidth();
46424
46733
  const sep = c2.dim("\u2500".repeat(w));
46425
- let clearBuf = "";
46426
- if (prevRows > 0 && (rows !== prevRows || cols !== prevCols)) {
46427
- const wrapFactor = cols > 0 ? Math.ceil(prevCols / cols) : 1;
46428
- const extraWrappedRows = Math.max(0, (wrapFactor - 1) * 3);
46429
- const safetyMargin = extraWrappedRows + 2;
46430
- const clearFrom = Math.max(1, pos.bufferRow - safetyMargin);
46431
- clearBuf = "\x1B[1;" + rows + `r\x1B[${clearFrom};1H\x1B[J`;
46432
- }
46433
46734
  if (this.writeDepth > 0) {
46434
46735
  const inputWrap = this.wrapInput(w);
46435
- let buf = clearBuf + `\x1B[${this.scrollRegionTop};${pos.scrollEnd}r\x1B[?25l\x1B[?7l\x1B[${pos.bufferRow};1H\x1B[2K${this.buildBufferContent(w)}\x1B[${pos.topSepRow};1H\x1B[2K${sep}`;
46736
+ let buf = `\x1B[${this.scrollRegionTop};${pos.scrollEnd}r\x1B[?25l\x1B[?7l`;
46737
+ for (let row = pos.bufferRow; row <= rows; row++) {
46738
+ buf += `\x1B[${row};1H\x1B[2K`;
46739
+ }
46740
+ buf += `\x1B[${pos.bufferRow};1H${this.buildBufferContent(w)}\x1B[${pos.topSepRow};1H${sep}`;
46436
46741
  for (let i = 0; i < inputWrap.lines.length; i++) {
46437
46742
  const row = pos.inputStartRow + i;
46438
46743
  const prefix = i === 0 ? this.promptText : " ".repeat(this.promptWidth);
46439
- buf += `\x1B[${row};1H\x1B[2K${prefix}${inputWrap.lines[i]}`;
46744
+ buf += `\x1B[${row};1H${prefix}${inputWrap.lines[i]}`;
46440
46745
  }
46441
- buf += `\x1B[${pos.bottomSepRow};1H\x1B[2K${sep}\x1B[${pos.metricsRow};1H\x1B[2K${this.buildMetricsLine()}\x1B[?7h\x1B[${pos.scrollEnd};1H`;
46746
+ buf += `\x1B[${pos.bottomSepRow};1H${sep}\x1B[${pos.metricsRow};1H${this.buildMetricsLine()}\x1B[?7h\x1B[${pos.scrollEnd};1H`;
46442
46747
  process.stdout.write(buf);
46443
46748
  } else {
46444
- if (clearBuf)
46445
- process.stdout.write(clearBuf);
46446
46749
  this.applyScrollRegion();
46750
+ let clearBuf = "\x1B[?7l";
46751
+ for (let row = pos.bufferRow; row <= rows; row++) {
46752
+ clearBuf += `\x1B[${row};1H\x1B[2K`;
46753
+ }
46754
+ clearBuf += "\x1B[?7h";
46755
+ process.stdout.write(clearBuf);
46447
46756
  this.renderFooterAndPositionInput();
46448
46757
  }
46449
46758
  }
@@ -46688,47 +46997,59 @@ var init_status_bar = __esm({
46688
46997
  empty: false
46689
46998
  });
46690
46999
  }
46691
- if (this._remoteMetrics) {
46692
- const rm2 = this._remoteMetrics;
46693
- const cpuColor = rm2.cpuUtil > 80 ? c2.red : rm2.cpuUtil > 50 ? c2.yellow : c2.green;
46694
- const cpuCoresInfo = rm2.cpuCores > 0 ? ` (${rm2.cpuCores}c` + (rm2.cpuModel ? " " + rm2.cpuModel.replace(/\s+/g, " ").slice(0, 30) : "") + ")" : "";
46695
- const cpuExpStr = `CPU:${cpuColor(rm2.cpuUtil + "%")}${c2.dim(cpuCoresInfo)}`;
46696
- const cpuCompStr = `CPU:${cpuColor(rm2.cpuUtil + "%")}`;
46697
- const cpuExpW = 4 + `${rm2.cpuUtil}%`.length + cpuCoresInfo.length;
46698
- const cpuCompW = 4 + `${rm2.cpuUtil}%`.length;
46699
- const memColor = rm2.memUtil > 80 ? c2.red : rm2.memUtil > 50 ? c2.yellow : c2.green;
46700
- const memDetail = rm2.memTotalGB > 0 ? ` (${rm2.memUsedGB}/${rm2.memTotalGB}GB)` : "";
46701
- const memExpStr = ` RAM:${memColor(rm2.memUtil + "%")}${c2.dim(memDetail)}`;
46702
- const memCompStr = ` RAM:${memColor(rm2.memUtil + "%")}`;
46703
- const memExpW = 5 + `${rm2.memUtil}%`.length + memDetail.length;
46704
- const memCompW = 5 + `${rm2.memUtil}%`.length;
46705
- let gpuExpStr = "";
46706
- let gpuCompStr = "";
46707
- let gpuExpW = 0;
46708
- let gpuCompW = 0;
47000
+ if (this._unifiedMetrics) {
47001
+ const um = this._unifiedMetrics;
47002
+ const rm2 = um.hardware;
47003
+ const isLocal = um.source === "local";
47004
+ const srcTag = isLocal ? pastel2(120, "L") : pastel2(117, "R");
47005
+ const srcW = 1;
47006
+ let hwExpStr = "";
47007
+ let hwCompStr = "";
47008
+ let hwExpW = 0;
47009
+ let hwCompW = 0;
47010
+ if (rm2.cpuUtil >= 0) {
47011
+ const cpuColor = rm2.cpuUtil > 80 ? c2.red : rm2.cpuUtil > 50 ? c2.yellow : c2.green;
47012
+ const cpuCoresInfo = rm2.cpuCores > 0 ? ` (${rm2.cpuCores}c` + (rm2.cpuModel ? " " + rm2.cpuModel.replace(/\s+/g, " ").slice(0, 30) : "") + ")" : "";
47013
+ hwExpStr += `CPU:${cpuColor(rm2.cpuUtil + "%")}${c2.dim(cpuCoresInfo)}`;
47014
+ hwCompStr += `CPU:${cpuColor(rm2.cpuUtil + "%")}`;
47015
+ hwExpW += 4 + `${rm2.cpuUtil}%`.length + cpuCoresInfo.length;
47016
+ hwCompW += 4 + `${rm2.cpuUtil}%`.length;
47017
+ }
47018
+ if (rm2.memUtil >= 0) {
47019
+ const memColor = rm2.memUtil > 80 ? c2.red : rm2.memUtil > 50 ? c2.yellow : c2.green;
47020
+ const memDetail = rm2.memTotalGB > 0 ? ` (${rm2.memUsedGB}/${rm2.memTotalGB}GB)` : "";
47021
+ hwExpStr += ` RAM:${memColor(rm2.memUtil + "%")}${c2.dim(memDetail)}`;
47022
+ hwCompStr += ` RAM:${memColor(rm2.memUtil + "%")}`;
47023
+ hwExpW += 5 + `${rm2.memUtil}%`.length + memDetail.length;
47024
+ hwCompW += 5 + `${rm2.memUtil}%`.length;
47025
+ }
46709
47026
  if (rm2.gpuUtil >= 0) {
46710
47027
  const gpuColor = rm2.gpuUtil > 80 ? c2.red : rm2.gpuUtil > 50 ? c2.yellow : c2.green;
46711
47028
  const gpuNameShort = rm2.gpuName ? ` (${rm2.gpuName.slice(0, 20)})` : "";
46712
- gpuExpStr = ` GPU:${gpuColor(rm2.gpuUtil + "%")}${c2.dim(gpuNameShort)}`;
46713
- gpuCompStr = ` GPU:${gpuColor(rm2.gpuUtil + "%")}`;
46714
- gpuExpW = 5 + `${rm2.gpuUtil}%`.length + gpuNameShort.length;
46715
- gpuCompW = 5 + `${rm2.gpuUtil}%`.length;
47029
+ hwExpStr += ` GPU:${gpuColor(rm2.gpuUtil + "%")}${c2.dim(gpuNameShort)}`;
47030
+ hwCompStr += ` GPU:${gpuColor(rm2.gpuUtil + "%")}`;
47031
+ hwExpW += 5 + `${rm2.gpuUtil}%`.length + gpuNameShort.length;
47032
+ hwCompW += 5 + `${rm2.gpuUtil}%`.length;
46716
47033
  }
46717
- let vramStr = "";
46718
- let vramW = 0;
46719
47034
  if (rm2.vramUtil >= 0) {
46720
47035
  const vramColor = rm2.vramUtil > 80 ? c2.red : rm2.vramUtil > 50 ? c2.yellow : c2.green;
46721
47036
  const vramDetail = rm2.vramTotalMB > 0 ? ` (${rm2.vramUsedMB}/${rm2.vramTotalMB}MB)` : "";
46722
- vramStr = ` VRAM:${vramColor(rm2.vramUtil + "%")}${c2.dim(vramDetail)}`;
46723
- vramW = 6 + `${rm2.vramUtil}%`.length + vramDetail.length;
46724
- }
46725
- const remoteExpanded = pastel2(117, "\u{1F4E1}") + " " + cpuExpStr + memExpStr + gpuExpStr + vramStr;
46726
- const remoteCompact = pastel2(117, "\u{1F4E1}") + " " + cpuCompStr + gpuCompStr;
47037
+ hwExpStr += ` VRAM:${vramColor(rm2.vramUtil + "%")}${c2.dim(vramDetail)}`;
47038
+ hwExpW += 6 + `${rm2.vramUtil}%`.length + vramDetail.length;
47039
+ }
47040
+ const net = um.network;
47041
+ const rxStr = formatRate(net.rxBytesPerSec);
47042
+ const txStr = formatRate(net.txBytesPerSec);
47043
+ const netExpStr = ` ${c2.dim("i:")}${pastel2(116, rxStr)} ${c2.dim("o:")}${pastel2(218, txStr)}`;
47044
+ const netCompStr = ` ${c2.dim("i:")}${pastel2(116, rxStr)} ${c2.dim("o:")}${pastel2(218, txStr)}`;
47045
+ const netW = 3 + rxStr.length + 3 + txStr.length;
47046
+ const sysExpanded = srcTag + " " + hwExpStr + netExpStr;
47047
+ const sysCompact = srcTag + " " + hwCompStr + netCompStr;
46727
47048
  sections.push({
46728
- expanded: remoteExpanded,
46729
- compact: remoteCompact,
46730
- expandedW: 3 + cpuExpW + memExpW + gpuExpW + vramW,
46731
- compactW: 3 + cpuCompW + gpuCompW,
47049
+ expanded: sysExpanded,
47050
+ compact: sysCompact,
47051
+ expandedW: srcW + 1 + hwExpW + netW,
47052
+ compactW: srcW + 1 + hwCompW + netW,
46732
47053
  empty: false
46733
47054
  });
46734
47055
  }
@@ -50227,8 +50548,8 @@ NEW TASK: ${fullInput}`;
50227
50548
  try {
50228
50549
  const updateInfo = await checkForUpdate(version);
50229
50550
  if (updateInfo) {
50230
- const { exec: exec3 } = await import("node:child_process");
50231
- exec3(`npm install -g open-agents-ai@latest --prefer-online`, { timeout: 18e4 }, (err) => {
50551
+ const { exec: exec4 } = await import("node:child_process");
50552
+ exec4(`npm install -g open-agents-ai@latest --prefer-online`, { timeout: 18e4 }, (err) => {
50232
50553
  if (!err) {
50233
50554
  writeContent(() => renderInfo(`Updated to v${updateInfo.latestVersion} in background. Takes effect next session.`));
50234
50555
  }
@@ -50526,7 +50847,7 @@ var init_run = __esm({
50526
50847
  // packages/indexer/dist/codebase-indexer.js
50527
50848
  import { glob } from "glob";
50528
50849
  import ignore from "ignore";
50529
- import { readFile as readFile16, stat as stat4 } from "node:fs/promises";
50850
+ import { readFile as readFile17, stat as stat4 } from "node:fs/promises";
50530
50851
  import { createHash as createHash4 } from "node:crypto";
50531
50852
  import { join as join51, relative as relative3, extname as extname10, basename as basename15 } from "node:path";
50532
50853
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
@@ -50572,7 +50893,7 @@ var init_codebase_indexer = __esm({
50572
50893
  const ig = ignore.default();
50573
50894
  if (this.config.respectGitignore) {
50574
50895
  try {
50575
- const gitignoreContent = await readFile16(join51(this.config.rootDir, ".gitignore"), "utf-8");
50896
+ const gitignoreContent = await readFile17(join51(this.config.rootDir, ".gitignore"), "utf-8");
50576
50897
  ig.add(gitignoreContent);
50577
50898
  } catch {
50578
50899
  }
@@ -50592,7 +50913,7 @@ var init_codebase_indexer = __esm({
50592
50913
  const fileStat = await stat4(fullPath);
50593
50914
  if (fileStat.size > this.config.maxFileSize)
50594
50915
  continue;
50595
- const content = await readFile16(fullPath);
50916
+ const content = await readFile17(fullPath);
50596
50917
  const hash = createHash4("sha256").update(content).digest("hex");
50597
50918
  const ext = extname10(relativePath);
50598
50919
  indexed.push({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.103.87",
3
+ "version": "0.103.89",
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",