open-agents-ai 0.104.24 → 0.104.26

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 +175 -188
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -13325,7 +13325,7 @@ async function handleCmd(cmd) {
13325
13325
  dlog('system_metrics: auth OK');
13326
13326
  }
13327
13327
  try {
13328
- var os = require('os');
13328
+ var os = await import('node:os');
13329
13329
  var loads = os.loadavg();
13330
13330
  var cores = os.cpus().length;
13331
13331
  var totalMem = os.totalmem();
@@ -13333,7 +13333,7 @@ async function handleCmd(cmd) {
13333
13333
  var usedMem = totalMem - freeMem;
13334
13334
  var gpuInfo = { available: false, name: '', utilization: 0, vramUsedMB: 0, vramTotalMB: 0, vramUtilization: 0 };
13335
13335
  try {
13336
- var cp = require('child_process');
13336
+ var cp = await import('node:child_process');
13337
13337
  var smiOut = cp.execSync('nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null', { encoding: 'utf8', timeout: 3000 });
13338
13338
  var smiLine = smiOut.trim().split('\\n')[0];
13339
13339
  if (smiLine) {
@@ -29494,6 +29494,8 @@ ${this.formatConnectionInfo()}`);
29494
29494
  this._stats.totalRequests = invocCount;
29495
29495
  this._prevInvocCount = invocCount;
29496
29496
  this.emitStats();
29497
+ for (let i = 0; i < newRequests; i++)
29498
+ this.emit("token_flash");
29497
29499
  return;
29498
29500
  }
29499
29501
  const now = Date.now();
@@ -29619,6 +29621,7 @@ ${this.formatConnectionInfo()}`);
29619
29621
  }
29620
29622
  }
29621
29623
  this.emitStats();
29624
+ this.emit("token_flash");
29622
29625
  }
29623
29626
  }
29624
29627
  } catch {
@@ -37431,6 +37434,8 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
37431
37434
  });
37432
37435
 
37433
37436
  // packages/cli/dist/tui/commands.js
37437
+ import * as nodeOs from "node:os";
37438
+ import { execSync as nodeExecSync } from "node:child_process";
37434
37439
  function safeLog(text) {
37435
37440
  if (isNeovimActive()) {
37436
37441
  writeToNeovimOutput(text + "\n");
@@ -38238,7 +38243,7 @@ async function handleSlashCommand(input, ctx) {
38238
38243
  renderWarning("No active expose gateway.");
38239
38244
  return "handled";
38240
38245
  }
38241
- await showExposeDashboard(gateway, ctx.rl);
38246
+ await showExposeDashboard(gateway, ctx.rl, ctx);
38242
38247
  return "handled";
38243
38248
  }
38244
38249
  if (arg === "config") {
@@ -38299,9 +38304,13 @@ async function handleSlashCommand(input, ctx) {
38299
38304
  try {
38300
38305
  const tunnelUrl = await ctx.exposeStart(kindOrUrl, exposeAuthKey, exposeTransport, exposeFullAccess);
38301
38306
  if (tunnelUrl) {
38302
- const info = ctx.getExposeInfo?.();
38303
- if (info) {
38304
- process.stdout.write("\n" + info.stats + "\n\n");
38307
+ const gw = ctx.getExposeGateway?.();
38308
+ if (gw) {
38309
+ await showExposeDashboard(gw, ctx.rl, ctx);
38310
+ } else {
38311
+ const info = ctx.getExposeInfo?.();
38312
+ if (info)
38313
+ process.stdout.write("\n" + info.stats + "\n\n");
38305
38314
  }
38306
38315
  } else {
38307
38316
  renderError("Failed to start expose gateway.");
@@ -40167,16 +40176,15 @@ function fmtUptime(ms) {
40167
40176
  return `${Math.floor(sec / 3600)}h ${Math.floor(sec % 3600 / 60)}m`;
40168
40177
  }
40169
40178
  function getLocalSystemMetrics() {
40170
- const os = __require("node:os");
40171
- const cpus3 = os.cpus();
40172
- const loads = os.loadavg();
40173
- const totalMem = os.totalmem();
40174
- const freeMem = os.freemem();
40179
+ const cpus4 = nodeOs.cpus();
40180
+ const loads = nodeOs.loadavg();
40181
+ const totalMem = nodeOs.totalmem();
40182
+ const freeMem = nodeOs.freemem();
40175
40183
  const usedMem = totalMem - freeMem;
40176
40184
  const result = {
40177
- cpuModel: cpus3[0]?.model?.trim() ?? "unknown",
40178
- cpuCores: cpus3.length,
40179
- cpuUtil: Math.min(100, Math.round(loads[0] / cpus3.length * 100)),
40185
+ cpuModel: cpus4[0]?.model?.trim() ?? "unknown",
40186
+ cpuCores: cpus4.length,
40187
+ cpuUtil: Math.min(100, Math.round(loads[0] / cpus4.length * 100)),
40180
40188
  memTotalGB: Math.round(totalMem / (1024 * 1024 * 1024) * 10) / 10,
40181
40189
  memUsedGB: Math.round(usedMem / (1024 * 1024 * 1024) * 10) / 10,
40182
40190
  memUtil: Math.round(usedMem / totalMem * 100),
@@ -40188,8 +40196,7 @@ function getLocalSystemMetrics() {
40188
40196
  vramUtil: 0
40189
40197
  };
40190
40198
  try {
40191
- const { execSync: execSync30 } = __require("node:child_process");
40192
- const smiOut = execSync30("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 });
40199
+ const smiOut = nodeExecSync("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 });
40193
40200
  const line = smiOut.trim().split("\n")[0];
40194
40201
  if (line) {
40195
40202
  const parts = line.split(",").map((s) => s.trim());
@@ -40204,74 +40211,62 @@ function getLocalSystemMetrics() {
40204
40211
  }
40205
40212
  return result;
40206
40213
  }
40207
- async function showExposeDashboard(gateway, rl) {
40208
- const stdin = process.stdin;
40209
- const stdout = process.stdout;
40210
- if (!stdin.isTTY) {
40214
+ async function showExposeDashboard(gateway, rl, ctx) {
40215
+ if (!process.stdin.isTTY) {
40211
40216
  if (typeof gateway.formatStats === "function") {
40212
- stdout.write("\n" + gateway.formatStats() + "\n\n");
40217
+ process.stdout.write("\n" + gateway.formatStats() + "\n\n");
40213
40218
  }
40214
40219
  return;
40215
40220
  }
40216
- let lastRenderedLines = 0;
40217
- let refreshTimer = null;
40218
- const hadRawMode = stdin.isRaw;
40219
- let sysMetrics = getLocalSystemMetrics();
40220
- const savedListeners = rl ? stdin.listeners("data").slice() : [];
40221
- if (rl) {
40222
- rl.pause();
40223
- for (const fn of savedListeners)
40224
- stdin.removeListener("data", fn);
40225
- }
40226
- stdin.setRawMode(true);
40227
- stdin.resume();
40228
- stdout.write("\x1B[?25l");
40229
- function buildDashboard() {
40221
+ const peerLedColor = (peerIdx) => {
40222
+ const stops = [51, 81, 111, 141, 171, 201];
40223
+ const code = stops[Math.min(peerIdx, stops.length - 1)] ?? 51;
40224
+ return `\x1B[38;5;${code}m\u25CF\x1B[0m`;
40225
+ };
40226
+ while (true) {
40230
40227
  const s = gateway.stats ?? gateway._stats;
40231
- if (!s)
40232
- return [" No stats available.", "", " Press Escape or 'q' to close."];
40233
- const lines = [];
40234
40228
  const now = Date.now();
40235
- const uptime = fmtUptime(now - (s.startedAt || now));
40236
- const statusColor = s.status === "active" ? c2.green : s.status === "error" ? c2.red : c2.yellow;
40237
- lines.push("");
40238
- lines.push(` ${c2.bold("Expose Dashboard")} ${statusColor("\u25CF")} ${statusColor(s.status || "unknown")} ${c2.dim(`uptime ${uptime}`)}`);
40239
- lines.push(` ${c2.dim("\u2500".repeat(60))}`);
40240
- const activeConns = s.activeConnections || 0;
40241
- const totalReqs = s.totalRequests || 0;
40242
- const errors = s.errors || 0;
40243
- const tokIn = s.totalTokensIn || 0;
40244
- const tokOut = s.totalTokensOut || 0;
40245
- lines.push(` ${c2.cyan("Requests")} ${c2.bold(String(totalReqs))} ${c2.dim("|")} ${c2.cyan("Active")} ${activeConns > 0 ? c2.green(c2.bold(String(activeConns))) : c2.dim("0")} ${c2.dim("|")} ${c2.cyan("Errors")} ${errors > 0 ? c2.red(String(errors)) : c2.dim("0")}`);
40246
- lines.push(` ${c2.cyan("Tokens")} ${c2.dim("in:")}${c2.bold(fmtDashTokens(tokIn))} ${c2.dim("out:")}${c2.bold(fmtDashTokens(tokOut))} ${c2.dim("total:")}${fmtDashTokens(tokIn + tokOut)}`);
40247
- if (s.budgetTokensTotal > 0) {
40248
- const pct = Math.round(s.budgetTokensRemaining / s.budgetTokensTotal * 100);
40249
- const budgetColor = pct > 50 ? c2.green : pct > 20 ? c2.yellow : c2.red;
40250
- const barLen = 20;
40251
- const filledLen = Math.round(pct / 100 * barLen);
40252
- const bar = budgetColor("\u2588".repeat(filledLen)) + c2.dim("\u2591".repeat(barLen - filledLen));
40253
- lines.push(` ${c2.cyan("Budget")} ${bar} ${budgetColor(`${pct}%`)} ${c2.dim(`(${fmtDashTokens(s.budgetTokensRemaining)}/${fmtDashTokens(s.budgetTokensTotal)})`)}`);
40254
- }
40255
- const sys = sysMetrics;
40256
- lines.push("");
40257
- lines.push(` ${c2.bold("System")}`);
40258
- const cpuColor = sys.cpuUtil > 80 ? c2.red : sys.cpuUtil > 50 ? c2.yellow : c2.green;
40259
- const memColor = sys.memUtil > 80 ? c2.red : sys.memUtil > 50 ? c2.yellow : c2.green;
40260
- lines.push(` ${c2.cyan("CPU")} ${cpuColor(sys.cpuUtil + "%")} ${c2.dim(`(${sys.cpuCores} cores, ${sys.cpuModel.slice(0, 40)})`)}`);
40261
- lines.push(` ${c2.cyan("RAM")} ${memColor(sys.memUtil + "%")} ${c2.dim(`(${sys.memUsedGB}/${sys.memTotalGB} GB)`)}`);
40262
- if (sys.gpuAvailable) {
40263
- const gpuColor = sys.gpuUtil > 80 ? c2.red : sys.gpuUtil > 50 ? c2.yellow : c2.green;
40264
- const vramColor = sys.vramUtil > 80 ? c2.red : sys.vramUtil > 50 ? c2.yellow : c2.green;
40265
- lines.push(` ${c2.cyan("GPU")} ${gpuColor(sys.gpuUtil + "%")} ${c2.dim(`(${sys.gpuName.trim()})`)}`);
40266
- lines.push(` ${c2.cyan("VRAM")} ${vramColor(sys.vramUtil + "%")} ${c2.dim(`(${sys.vramUsedMB}/${sys.vramTotalMB} MB)`)}`);
40267
- }
40268
- const modelEntries = s.modelUsage ? Array.from(s.modelUsage.entries()).filter(([m]) => !DASH_INTERNAL.has(m)) : [];
40229
+ const uptime = s ? fmtUptime(now - (s.startedAt || now)) : "0s";
40230
+ const statusColor = !s ? c2.dim : s.status === "active" ? c2.green : s.status === "error" ? c2.red : c2.yellow;
40231
+ const statusLabel = s?.status || "unknown";
40232
+ const items = [];
40233
+ const skipKeys = [];
40234
+ items.push({ key: "hdr_status", label: selectColors.dim(`\u2500\u2500\u2500 ${statusColor("\u25CF")} ${statusLabel} uptime ${uptime} \u2500\u2500\u2500`), kind: "header" });
40235
+ skipKeys.push("hdr_status");
40236
+ const isTunnel = !!gateway.tunnelUrl;
40237
+ const isP2P = !!gateway.peerId;
40238
+ const endpointId = isTunnel ? gateway.tunnelUrl : isP2P ? gateway.peerId : null;
40239
+ const authKey = gateway.authKey ?? "";
40240
+ if (endpointId) {
40241
+ const endpointCmd = `/endpoint ${endpointId} --auth ${authKey}`;
40242
+ items.push({ key: "endpoint", label: "\u{1F517} Endpoint", detail: endpointCmd, kind: "action" });
40243
+ }
40244
+ if (s) {
40245
+ const totalReqs = s.totalRequests || 0;
40246
+ const activeConns = s.activeConnections || 0;
40247
+ const tokIn = s.totalTokensIn || 0;
40248
+ const tokOut = s.totalTokensOut || 0;
40249
+ const errors = s.errors || 0;
40250
+ const statsLine = `Req: ${totalReqs} Active: ${activeConns} Err: ${errors} Tok \u2191${fmtDashTokens(tokIn)} \u2193${fmtDashTokens(tokOut)}`;
40251
+ items.push({ key: "info_stats", label: c2.dim(statsLine), kind: "info" });
40252
+ skipKeys.push("info_stats");
40253
+ if (s.budgetTokensTotal > 0) {
40254
+ const pct = Math.round(s.budgetTokensRemaining / s.budgetTokensTotal * 100);
40255
+ const budgetColor = pct > 50 ? c2.green : pct > 20 ? c2.yellow : c2.red;
40256
+ const barLen = 20;
40257
+ const filledLen = Math.round(pct / 100 * barLen);
40258
+ const bar = budgetColor("\u2588".repeat(filledLen)) + c2.dim("\u2591".repeat(barLen - filledLen));
40259
+ items.push({ key: "info_budget", label: ` Budget ${bar} ${budgetColor(`${pct}%`)}`, kind: "info" });
40260
+ skipKeys.push("info_budget");
40261
+ }
40262
+ }
40263
+ const modelEntries = s?.modelUsage ? Array.from(s.modelUsage.entries()).filter(([m]) => !DASH_INTERNAL.has(m)) : [];
40269
40264
  if (modelEntries.length > 0) {
40270
- lines.push("");
40271
- lines.push(` ${c2.bold("Models")}`);
40265
+ items.push({ key: "hdr_models", label: selectColors.dim(`\u2500\u2500\u2500 Models (${modelEntries.length}) \u2500\u2500\u2500`), kind: "header" });
40266
+ skipKeys.push("hdr_models");
40272
40267
  for (const [model, count] of modelEntries) {
40273
40268
  let mIn = 0, mOut = 0;
40274
- if (s.users) {
40269
+ if (s?.users) {
40275
40270
  for (const user of s.users.values()) {
40276
40271
  const mm = user.models?.get?.(model);
40277
40272
  if (mm) {
@@ -40280,123 +40275,113 @@ async function showExposeDashboard(gateway, rl) {
40280
40275
  }
40281
40276
  }
40282
40277
  }
40283
- const bar = count > 0 ? c2.green("\u25AE".repeat(Math.min(count, 20))) : "";
40284
- lines.push(` ${c2.cyan(model.padEnd(35))} ${c2.bold(String(count).padStart(4))} req ${c2.dim(`in:${fmtDashTokens(mIn).padStart(6)} out:${fmtDashTokens(mOut).padStart(6)}`)} ${bar}`);
40278
+ const bar = count > 0 ? c2.green("\u25AE".repeat(Math.min(count, 10))) : "";
40279
+ items.push({
40280
+ key: `model_${model}`,
40281
+ label: `${model}`,
40282
+ detail: `${count} req \u2191${fmtDashTokens(mIn)} \u2193${fmtDashTokens(mOut)} ${bar}`,
40283
+ kind: "model"
40284
+ });
40285
40285
  }
40286
40286
  }
40287
- const users = s.users ? Array.from(s.users.values()) : [];
40287
+ const users = s?.users ? Array.from(s.users.values()) : [];
40288
40288
  if (users.length > 0) {
40289
- lines.push("");
40290
- lines.push(` ${c2.bold("Connected Peers")} (${users.length})`);
40291
- for (const user of users) {
40289
+ items.push({ key: "hdr_peers", label: selectColors.dim(`\u2500\u2500\u2500 Peers (${users.length}) \u2500\u2500\u2500`), kind: "header" });
40290
+ skipKeys.push("hdr_peers");
40291
+ for (let i = 0; i < users.length; i++) {
40292
+ const user = users[i];
40292
40293
  const ageSec = Math.floor((now - (user.firstSeen || now)) / 1e3);
40293
- const ageStr = ageSec < 60 ? `${ageSec}s` : ageSec < 3600 ? `${Math.floor(ageSec / 60)}m` : `${Math.floor(ageSec / 3600)}h${Math.floor(ageSec % 3600 / 60)}m`;
40294
+ const ageStr = ageSec < 60 ? `${ageSec}s` : ageSec < 3600 ? `${Math.floor(ageSec / 60)}m` : `${Math.floor(ageSec / 3600)}h`;
40294
40295
  const lastSec = Math.floor((now - (user.lastSeen || now)) / 1e3);
40295
40296
  const lastStr = lastSec < 5 ? c2.green("now") : lastSec < 60 ? `${lastSec}s ago` : `${Math.floor(lastSec / 60)}m ago`;
40296
- const activeStr = (user.activeRequests || 0) > 0 ? c2.green(` \u25CF ${user.activeRequests} active`) : "";
40297
- lines.push(` ${c2.bold(user.ip || "unknown")}${activeStr}`);
40298
- lines.push(` ${c2.dim("session")} ${ageStr} ${c2.dim("last")} ${lastStr} ${c2.dim("reqs")} ${user.requests || 0} ${c2.dim("tok")} ${c2.cyan("in:")}${fmtDashTokens(user.tokensIn || 0)} ${c2.cyan("out:")}${fmtDashTokens(user.tokensOut || 0)}`);
40299
- const userModels = user.models ? Array.from(user.models.entries()).filter(([m]) => !DASH_INTERNAL.has(m)) : [];
40300
- for (const [m, mm] of userModels) {
40301
- lines.push(` ${c2.dim("\u2514")} ${c2.cyan(m)} ${c2.dim(`${mm.requests || 0}req ${fmtDashTokens((mm.tokensIn || 0) + (mm.tokensOut || 0))}tok`)}`);
40302
- }
40303
- }
40304
- }
40305
- lines.push("");
40306
- lines.push(` ${c2.dim("Press Escape or 'q' to close \u2502 Live \u25CF updates every 2s")}`);
40307
- lines.push("");
40308
- return lines;
40309
- }
40310
- function render() {
40311
- sysMetrics = getLocalSystemMetrics();
40312
- const lines = buildDashboard();
40313
- if (lastRenderedLines > 0) {
40314
- stdout.write(`\x1B[${lastRenderedLines}A`);
40315
- for (let i = 0; i < lastRenderedLines; i++) {
40316
- stdout.write("\x1B[2K\n");
40317
- }
40318
- stdout.write(`\x1B[${lastRenderedLines}A`);
40319
- }
40320
- stdout.write(lines.join("\n") + "\n");
40321
- lastRenderedLines = lines.length;
40322
- }
40323
- function cleanup() {
40324
- if (refreshTimer) {
40325
- clearInterval(refreshTimer);
40326
- refreshTimer = null;
40327
- }
40328
- gateway.removeListener?.("stats", onStats);
40329
- if (lastRenderedLines > 0) {
40330
- stdout.write(`\x1B[${lastRenderedLines}A`);
40331
- for (let i = 0; i < lastRenderedLines; i++) {
40332
- stdout.write("\x1B[2K\n");
40297
+ const activeFlag = (user.activeRequests || 0) > 0 ? ` ${c2.green(`\u25CF ${user.activeRequests} active`)}` : "";
40298
+ const led = peerLedColor(i);
40299
+ const peerTok = `\u2191${fmtDashTokens(user.tokensIn || 0)} \u2193${fmtDashTokens(user.tokensOut || 0)}`;
40300
+ items.push({
40301
+ key: `peer_${user.ip || i}`,
40302
+ label: `${led} ${user.ip || "unknown"}${activeFlag}`,
40303
+ detail: `${user.requests || 0}req ${peerTok} ${c2.dim(ageStr)} last: ${lastStr}`,
40304
+ kind: "peer"
40305
+ });
40333
40306
  }
40334
- stdout.write(`\x1B[${lastRenderedLines}A`);
40335
- }
40336
- stdout.write("\x1B[?25h");
40337
- stdin.setRawMode(hadRawMode ?? false);
40338
- stdin.removeListener("data", onKey);
40339
- if (rl) {
40340
- for (const fn of savedListeners)
40341
- stdin.on("data", fn);
40342
- rl.resume();
40343
- }
40344
- }
40345
- function onStats() {
40346
- render();
40347
- }
40348
- function onKey(chunk) {
40349
- const key = chunk.toString();
40350
- if (key === "\x1B" || key === "q" || key === "Q") {
40351
- cleanup();
40352
- return;
40353
- }
40354
- if (key === "") {
40355
- cleanup();
40356
- return;
40357
40307
  }
40358
- }
40359
- if (typeof gateway.on === "function") {
40360
- gateway.on("stats", onStats);
40361
- }
40362
- refreshTimer = setInterval(render, 2e3);
40363
- render();
40364
- stdin.on("data", onKey);
40365
- return new Promise((resolve32) => {
40366
- const origCleanup = cleanup;
40367
- function wrappedCleanup() {
40368
- origCleanup();
40369
- resolve32();
40370
- }
40371
- stdin.removeListener("data", onKey);
40372
- function onKeyWrapped(chunk) {
40373
- const key = chunk.toString();
40374
- if (key === "\x1B" || key === "q" || key === "Q" || key === "") {
40375
- if (refreshTimer) {
40376
- clearInterval(refreshTimer);
40377
- refreshTimer = null;
40308
+ const sys = getLocalSystemMetrics();
40309
+ items.push({ key: "hdr_system", label: selectColors.dim("\u2500\u2500\u2500 System \u2500\u2500\u2500"), kind: "header" });
40310
+ skipKeys.push("hdr_system");
40311
+ const cpuColor = sys.cpuUtil > 80 ? c2.red : sys.cpuUtil > 50 ? c2.yellow : c2.green;
40312
+ const memColor = sys.memUtil > 80 ? c2.red : sys.memUtil > 50 ? c2.yellow : c2.green;
40313
+ let sysLine = `CPU ${cpuColor(sys.cpuUtil + "%")} (${sys.cpuCores}c) RAM ${memColor(sys.memUtil + "%")} (${sys.memUsedGB}/${sys.memTotalGB}GB)`;
40314
+ if (sys.gpuAvailable) {
40315
+ const gpuColor = sys.gpuUtil > 80 ? c2.red : sys.gpuUtil > 50 ? c2.yellow : c2.green;
40316
+ const vramColor = sys.vramUtil > 80 ? c2.red : sys.vramUtil > 50 ? c2.yellow : c2.green;
40317
+ sysLine += ` GPU ${gpuColor(sys.gpuUtil + "%")} VRAM ${vramColor(sys.vramUtil + "%")} (${sys.vramUsedMB}/${sys.vramTotalMB}MB)`;
40318
+ }
40319
+ items.push({ key: "info_system", label: c2.dim(sysLine), kind: "info" });
40320
+ skipKeys.push("info_system");
40321
+ items.push({ key: "hdr_actions", label: selectColors.dim("\u2500\u2500\u2500 Actions \u2500\u2500\u2500"), kind: "header" });
40322
+ skipKeys.push("hdr_actions");
40323
+ items.push({ key: "refresh", label: "\u{1F504} Refresh", detail: "Rebuild dashboard with latest data", kind: "action" });
40324
+ items.push({ key: "stop", label: "\u{1F6D1} Stop Gateway", detail: "Shut down the expose gateway", kind: "action" });
40325
+ const result = await tuiSelect({
40326
+ items,
40327
+ title: "Expose Dashboard",
40328
+ rl,
40329
+ skipKeys,
40330
+ availableRows: ctx?.availableContentRows?.()
40331
+ });
40332
+ if (!result.confirmed || !result.key)
40333
+ break;
40334
+ switch (result.key) {
40335
+ case "endpoint": {
40336
+ const id = isTunnel ? gateway.tunnelUrl : gateway.peerId;
40337
+ const cmd = `/endpoint ${id} --auth ${authKey}`;
40338
+ if (process.stdout.isTTY && id) {
40339
+ const b64 = Buffer.from(cmd).toString("base64");
40340
+ process.stdout.write(`\x1B]52;c;${b64}\x07`);
40378
40341
  }
40379
- gateway.removeListener?.("stats", onStats);
40380
- if (lastRenderedLines > 0) {
40381
- stdout.write(`\x1B[${lastRenderedLines}A`);
40382
- for (let i = 0; i < lastRenderedLines; i++) {
40383
- stdout.write("\x1B[2K\n");
40342
+ process.stdout.write(`
40343
+ ${c2.bold("Endpoint command")} ${c2.dim("(copied to clipboard)")}
40344
+ ${c2.cyan(cmd)}
40345
+
40346
+ `);
40347
+ await new Promise((resolve32) => {
40348
+ const onData = () => {
40349
+ process.stdin.removeListener("data", onData);
40350
+ resolve32();
40351
+ };
40352
+ process.stdin.once("data", onData);
40353
+ });
40354
+ continue;
40355
+ }
40356
+ case "refresh":
40357
+ continue;
40358
+ // Loop rebuilds items with fresh data
40359
+ case "stop":
40360
+ await ctx?.exposeStop?.();
40361
+ renderInfo("Expose gateway stopped.");
40362
+ return;
40363
+ default:
40364
+ if (result.key.startsWith("peer_")) {
40365
+ const peerId = result.key.slice(5);
40366
+ const user = users.find((u) => (u.ip || String(users.indexOf(u))) === peerId);
40367
+ if (user) {
40368
+ const userModels = user.models ? Array.from(user.models.entries()).filter(([m]) => !DASH_INTERNAL.has(m)) : [];
40369
+ if (userModels.length > 0) {
40370
+ process.stdout.write(`
40371
+ ${c2.bold(user.ip || "unknown")} \u2014 model usage:
40372
+ `);
40373
+ for (const [m, mm] of userModels) {
40374
+ process.stdout.write(` ${c2.cyan(m)} ${c2.dim(`${mm.requests}req \u2191${fmtDashTokens(mm.tokensIn)} \u2193${fmtDashTokens(mm.tokensOut)}`)}
40375
+ `);
40376
+ }
40377
+ process.stdout.write("\n");
40378
+ }
40384
40379
  }
40385
- stdout.write(`\x1B[${lastRenderedLines}A`);
40386
- }
40387
- stdout.write("\x1B[?25h");
40388
- stdin.setRawMode(hadRawMode ?? false);
40389
- stdin.removeListener("data", onKeyWrapped);
40390
- if (rl) {
40391
- for (const fn of savedListeners)
40392
- stdin.on("data", fn);
40393
- rl.resume();
40380
+ continue;
40394
40381
  }
40395
- resolve32();
40396
- }
40382
+ continue;
40397
40383
  }
40398
- stdin.on("data", onKeyWrapped);
40399
- });
40384
+ }
40400
40385
  }
40401
40386
  var DASH_INTERNAL;
40402
40387
  var init_commands = __esm({
@@ -47138,7 +47123,7 @@ var init_braille_spinner = __esm({
47138
47123
  });
47139
47124
 
47140
47125
  // packages/cli/dist/tui/system-metrics.js
47141
- import { loadavg as loadavg2, cpus as cpus2, totalmem as totalmem3, freemem as freemem2, platform as platform4 } from "node:os";
47126
+ import { loadavg as loadavg3, cpus as cpus3, totalmem as totalmem4, freemem as freemem3, platform as platform4 } from "node:os";
47142
47127
  import { exec as exec3 } from "node:child_process";
47143
47128
  import { readFile as readFile16 } from "node:fs/promises";
47144
47129
  function formatRate(bytesPerSec) {
@@ -47269,11 +47254,11 @@ function getInstantSnapshot() {
47269
47254
  };
47270
47255
  }
47271
47256
  function collectCpuRam() {
47272
- const [l1] = loadavg2();
47273
- const cores = cpus2().length;
47274
- const cpuModel = cpus2()[0]?.model ?? "";
47275
- const totalMem = totalmem3();
47276
- const usedMem = totalMem - freemem2();
47257
+ const [l1] = loadavg3();
47258
+ const cores = cpus3().length;
47259
+ const cpuModel = cpus3()[0]?.model ?? "";
47260
+ const totalMem = totalmem4();
47261
+ const usedMem = totalMem - freemem3();
47277
47262
  return {
47278
47263
  cpuUtil: Math.min(100, Math.round(l1 / cores * 100)),
47279
47264
  cpuCores: cores,
@@ -48377,8 +48362,8 @@ var init_status_bar = __esm({
48377
48362
  const compactOrder = [];
48378
48363
  let modelSectionIdx = -1;
48379
48364
  let versionSectionIdx = -1;
48380
- if (this._exposeFlashOn) {
48381
- const ledColor = this._aliveLedColor();
48365
+ if (this._expose) {
48366
+ const ledColor = this._exposeFlashOn ? this._aliveLedColor() : 240;
48382
48367
  const dot = `\x1B[38;5;${ledColor}m\u2B24\x1B[0m`;
48383
48368
  sections.push({ expanded: dot, compact: dot, expandedW: 1, compactW: 1, empty: false });
48384
48369
  }
@@ -50612,6 +50597,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
50612
50597
  modelUsage: stats.modelUsage
50613
50598
  });
50614
50599
  });
50600
+ reconnectedP2P.on("token_flash", () => statusBar.flashExposeToken());
50615
50601
  writeContent(() => {
50616
50602
  renderInfo(`Reconnected to existing P2P expose: ${reconnectedP2P.peerId}`);
50617
50603
  });
@@ -51434,6 +51420,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
51434
51420
  modelUsage: stats.modelUsage
51435
51421
  });
51436
51422
  });
51423
+ newP2P.on("token_flash", () => statusBar.flashExposeToken());
51437
51424
  try {
51438
51425
  const peerId = await newP2P.start();
51439
51426
  clearInterval(exposeSpinner);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.104.24",
3
+ "version": "0.104.26",
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",