open-agents-ai 0.103.35 → 0.103.36

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 +234 -40
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -27527,6 +27527,33 @@ function isProcessAlive(pid) {
27527
27527
  return false;
27528
27528
  }
27529
27529
  }
27530
+ function parseRateLimitHeaders(headers) {
27531
+ const get = (name) => {
27532
+ const v = headers[name] ?? headers[name.toLowerCase()];
27533
+ return typeof v === "string" ? v : Array.isArray(v) ? v[0] : void 0;
27534
+ };
27535
+ const remaining = parseInt(get("x-ratelimit-remaining-tokens") ?? get("x-ratelimit-remaining") ?? "", 10);
27536
+ const total = parseInt(get("x-ratelimit-limit-tokens") ?? get("x-ratelimit-limit") ?? "", 10);
27537
+ const resetRaw = get("x-ratelimit-reset-tokens") ?? get("x-ratelimit-reset") ?? "";
27538
+ let resetAt = 0;
27539
+ if (resetRaw) {
27540
+ const n = Number(resetRaw);
27541
+ if (!isNaN(n)) {
27542
+ resetAt = n < 1e12 ? n * 1e3 : n;
27543
+ } else {
27544
+ const d = new Date(resetRaw).getTime();
27545
+ if (!isNaN(d))
27546
+ resetAt = d;
27547
+ }
27548
+ }
27549
+ if (isNaN(remaining) && isNaN(total))
27550
+ return null;
27551
+ return {
27552
+ remaining: isNaN(remaining) ? 0 : remaining,
27553
+ total: isNaN(total) ? 0 : total,
27554
+ resetAt
27555
+ };
27556
+ }
27530
27557
  async function collectSystemMetricsAsync() {
27531
27558
  const [l1, l5, l15] = loadavg();
27532
27559
  const cores = cpus().length;
@@ -27602,7 +27629,7 @@ function removeP2PExposeState(stateDir) {
27602
27629
  } catch {
27603
27630
  }
27604
27631
  }
27605
- var HOP_BY_HOP_HEADERS, CF_HEADERS_PREFIX, DEFAULT_TARGETS, STATE_FILE_NAME, ExposeGateway, P2P_STATE_FILE_NAME, ExposeP2PGateway;
27632
+ var HOP_BY_HOP_HEADERS, CF_HEADERS_PREFIX, INTERNAL_CAPABILITIES, DEFAULT_TARGETS, STATE_FILE_NAME, ExposeGateway, P2P_STATE_FILE_NAME, ExposeP2PGateway;
27606
27633
  var init_expose = __esm({
27607
27634
  "packages/cli/dist/tui/expose.js"() {
27608
27635
  "use strict";
@@ -27618,6 +27645,7 @@ var init_expose = __esm({
27618
27645
  "upgrade"
27619
27646
  ]);
27620
27647
  CF_HEADERS_PREFIX = ["cf-", "cdn-"];
27648
+ INTERNAL_CAPABILITIES = /* @__PURE__ */ new Set(["system_metrics", "__list_capabilities"]);
27621
27649
  DEFAULT_TARGETS = {
27622
27650
  ollama: "http://127.0.0.1:11434",
27623
27651
  vllm: "http://127.0.0.1:8000",
@@ -27648,7 +27676,10 @@ var init_expose = __esm({
27648
27676
  totalTokensOut: 0,
27649
27677
  startedAt: Date.now(),
27650
27678
  modelUsage: /* @__PURE__ */ new Map(),
27651
- users: /* @__PURE__ */ new Map()
27679
+ users: /* @__PURE__ */ new Map(),
27680
+ budgetTokensRemaining: 0,
27681
+ budgetTokensTotal: 0,
27682
+ budgetResetAt: 0
27652
27683
  };
27653
27684
  get tunnelUrl() {
27654
27685
  return this._tunnelUrl;
@@ -27995,6 +28026,13 @@ var init_expose = __esm({
27995
28026
  headers: forwardHeaders
27996
28027
  }, (proxyRes) => {
27997
28028
  cleanupHeartbeat();
28029
+ const rlHeaders = proxyRes.headers;
28030
+ const rl = parseRateLimitHeaders(rlHeaders);
28031
+ if (rl && (rl.total > 0 || rl.remaining > 0)) {
28032
+ this._stats.budgetTokensRemaining = rl.remaining;
28033
+ this._stats.budgetTokensTotal = rl.total;
28034
+ this._stats.budgetResetAt = rl.resetAt;
28035
+ }
27998
28036
  proxyRes.on("error", () => {
27999
28037
  finalizeRequest();
28000
28038
  });
@@ -28250,10 +28288,16 @@ ${this.formatConnectionInfo()}`);
28250
28288
  lines.push(` ${c2.cyan("Errors".padEnd(18))} ${s.errors}`);
28251
28289
  lines.push(` ${c2.cyan("Tokens in".padEnd(18))} ${fmtTokens(s.totalTokensIn)}`);
28252
28290
  lines.push(` ${c2.cyan("Tokens out".padEnd(18))} ${fmtTokens(s.totalTokensOut)}`);
28253
- if (s.modelUsage.size > 0) {
28291
+ if (s.budgetTokensTotal > 0) {
28292
+ const pct = Math.round(s.budgetTokensRemaining / s.budgetTokensTotal * 100);
28293
+ const budgetColor = pct > 50 ? c2.green : pct > 20 ? c2.yellow : c2.red;
28294
+ lines.push(` ${c2.cyan("Budget".padEnd(18))} ${budgetColor(fmtTokens(s.budgetTokensRemaining))}${c2.dim("/")}${fmtTokens(s.budgetTokensTotal)} ${c2.dim(`(${pct}% left)`)}`);
28295
+ }
28296
+ const visibleModels = Array.from(s.modelUsage.entries()).filter(([model]) => !INTERNAL_CAPABILITIES.has(model));
28297
+ if (visibleModels.length > 0) {
28254
28298
  lines.push("");
28255
28299
  lines.push(` ${c2.bold("Models")}`);
28256
- for (const [model, count] of s.modelUsage) {
28300
+ for (const [model, count] of visibleModels) {
28257
28301
  let mIn = 0, mOut = 0;
28258
28302
  for (const user of s.users.values()) {
28259
28303
  const mm = user.models.get(model);
@@ -28277,17 +28321,23 @@ ${this.formatConnectionInfo()}`);
28277
28321
  lines.push(` ${c2.bold(user.ip)}${activeTag}`);
28278
28322
  lines.push(` ${c2.dim("Session:")} ${ageStr} ${c2.dim("Last seen:")} ${lastStr} ${c2.dim("Requests:")} ${user.requests}`);
28279
28323
  lines.push(` ${c2.dim("Tokens:")} in:${fmtTokens(user.tokensIn)} out:${fmtTokens(user.tokensOut)} ${c2.dim("Total:")} ${fmtTokens(user.tokensIn + user.tokensOut)}`);
28280
- if (user.models.size > 0) {
28281
- const modelParts = [];
28282
- for (const [m, mm] of user.models) {
28283
- modelParts.push(`${m} (${mm.requests} reqs, ${fmtTokens(mm.tokensIn + mm.tokensOut)} tokens)`);
28324
+ const userModels = Array.from(user.models.entries()).filter(([m]) => !INTERNAL_CAPABILITIES.has(m));
28325
+ if (userModels.length > 0) {
28326
+ for (const [m, mm] of userModels) {
28327
+ lines.push(` ${c2.dim("\xB7")} ${c2.cyan(m)} ${c2.dim(`${mm.requests}req ${fmtTokens(mm.tokensIn + mm.tokensOut)}tok`)}`);
28284
28328
  }
28285
- lines.push(` ${c2.dim("Models:")} ${modelParts.join(", ")}`);
28286
28329
  }
28287
28330
  }
28288
28331
  }
28289
28332
  return lines.join("\n");
28290
28333
  }
28334
+ /** Update budget from rate limit headers */
28335
+ updateBudget(remaining, total, resetAt) {
28336
+ this._stats.budgetTokensRemaining = remaining;
28337
+ this._stats.budgetTokensTotal = total;
28338
+ this._stats.budgetResetAt = resetAt;
28339
+ this.emitStats();
28340
+ }
28291
28341
  };
28292
28342
  P2P_STATE_FILE_NAME = "expose-p2p-state.json";
28293
28343
  ExposeP2PGateway = class _ExposeP2PGateway extends EventEmitter3 {
@@ -28301,6 +28351,8 @@ ${this.formatConnectionInfo()}`);
28301
28351
  _exposedModels = 0;
28302
28352
  _stateDir;
28303
28353
  _margin;
28354
+ _passthrough = false;
28355
+ _loadbalance = false;
28304
28356
  _pollTimer = null;
28305
28357
  _stats = {
28306
28358
  status: "standby",
@@ -28311,7 +28363,10 @@ ${this.formatConnectionInfo()}`);
28311
28363
  totalTokensOut: 0,
28312
28364
  startedAt: Date.now(),
28313
28365
  modelUsage: /* @__PURE__ */ new Map(),
28314
- users: /* @__PURE__ */ new Map()
28366
+ users: /* @__PURE__ */ new Map(),
28367
+ budgetTokensRemaining: 0,
28368
+ budgetTokensTotal: 0,
28369
+ budgetResetAt: 0
28315
28370
  };
28316
28371
  get peerId() {
28317
28372
  return this._peerId;
@@ -28340,6 +28395,8 @@ ${this.formatConnectionInfo()}`);
28340
28395
  this._targetUrl = options.targetUrl ?? DEFAULT_TARGETS[options.kind];
28341
28396
  this._stateDir = options.stateDir ?? null;
28342
28397
  this._margin = options.margin ?? 0.5;
28398
+ this._passthrough = options.passthrough ?? false;
28399
+ this._loadbalance = options.loadbalance ?? false;
28343
28400
  this._onInfo = options.onInfo;
28344
28401
  this._onError = options.onError;
28345
28402
  if (options.authKey === void 0 || options.authKey === "") {
@@ -28406,6 +28463,8 @@ ${this.formatConnectionInfo()}`);
28406
28463
  kind: this._kind,
28407
28464
  targetUrl: this._targetUrl,
28408
28465
  margin: this._margin,
28466
+ passthrough: this._passthrough || void 0,
28467
+ loadbalance: this._loadbalance || void 0,
28409
28468
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
28410
28469
  });
28411
28470
  }
@@ -28456,6 +28515,8 @@ ${this.formatConnectionInfo()}`);
28456
28515
  authKey: state.authKey,
28457
28516
  stateDir,
28458
28517
  margin: state.margin,
28518
+ passthrough: state.passthrough,
28519
+ loadbalance: state.loadbalance,
28459
28520
  ...options
28460
28521
  }, nexusTool);
28461
28522
  gateway._peerId = state.peerId;
@@ -28575,8 +28636,9 @@ ${this.formatConnectionInfo()}`);
28575
28636
  formatConnectionInfo() {
28576
28637
  const endpointCmd = `/endpoint ${this._peerId ?? "<peer-id>"} --auth ${this._authKey}`;
28577
28638
  const lines = [];
28578
- lines.push(` ${c2.green("\u25CF")} Expose gateway active ${c2.dim("(libp2p)")}`);
28579
- lines.push(` ${c2.cyan("Backend".padEnd(12))} ${this._kind} (${this._targetUrl})`);
28639
+ const modeLabel = this._passthrough ? "libp2p passthrough" : "libp2p";
28640
+ lines.push(` ${c2.green("\u25CF")} Expose gateway active ${c2.dim(`(${modeLabel})`)}`);
28641
+ lines.push(` ${c2.cyan("Backend".padEnd(12))} ${this._passthrough ? "passthrough" : this._kind} (${this._targetUrl})`);
28580
28642
  lines.push(` ${c2.cyan("Transport".padEnd(12))} ${c2.bold("libp2p")} (DHT + mDNS + NATS relay)`);
28581
28643
  lines.push(` ${c2.cyan("Peer ID".padEnd(12))} ${c2.bold(this._peerId ?? "connecting...")}`);
28582
28644
  lines.push(` ${c2.cyan("Auth Key".padEnd(12))} ${c2.bold(this._authKey)}`);
@@ -28607,9 +28669,10 @@ ${this.formatConnectionInfo()}`);
28607
28669
  const lines = [];
28608
28670
  const uptimeSec = Math.floor((Date.now() - s.startedAt) / 1e3);
28609
28671
  const uptimeStr = uptimeSec < 60 ? `${uptimeSec}s` : uptimeSec < 3600 ? `${Math.floor(uptimeSec / 60)}m ${uptimeSec % 60}s` : `${Math.floor(uptimeSec / 3600)}h ${Math.floor(uptimeSec % 3600 / 60)}m`;
28610
- lines.push(` ${c2.bold("Expose Gateway Stats")} ${c2.dim("(libp2p)")}`);
28672
+ const modeTag = this._passthrough ? c2.dim("(libp2p passthrough)") : c2.dim("(libp2p)");
28673
+ lines.push(` ${c2.bold("Expose Gateway Stats")} ${modeTag}`);
28611
28674
  lines.push(` ${c2.cyan("Status".padEnd(18))} ${s.status === "active" ? c2.green("active") : s.status === "error" ? c2.red("error") : c2.yellow("standby")}`);
28612
- lines.push(` ${c2.cyan("Transport".padEnd(18))} libp2p`);
28675
+ lines.push(` ${c2.cyan("Transport".padEnd(18))} libp2p${this._passthrough ? " (passthrough)" : ""}`);
28613
28676
  lines.push(` ${c2.cyan("Peer ID".padEnd(18))} ${this._peerId ?? "n/a"}`);
28614
28677
  lines.push(` ${c2.cyan("Uptime".padEnd(18))} ${uptimeStr}`);
28615
28678
  lines.push(` ${c2.cyan("Total requests".padEnd(18))} ${s.totalRequests}`);
@@ -28617,10 +28680,16 @@ ${this.formatConnectionInfo()}`);
28617
28680
  lines.push(` ${c2.cyan("Errors".padEnd(18))} ${s.errors}`);
28618
28681
  lines.push(` ${c2.cyan("Tokens in".padEnd(18))} ${fmtTokens(s.totalTokensIn)}`);
28619
28682
  lines.push(` ${c2.cyan("Tokens out".padEnd(18))} ${fmtTokens(s.totalTokensOut)}`);
28620
- if (s.modelUsage.size > 0) {
28683
+ if (s.budgetTokensTotal > 0) {
28684
+ const pct = Math.round(s.budgetTokensRemaining / s.budgetTokensTotal * 100);
28685
+ const budgetColor = pct > 50 ? c2.green : pct > 20 ? c2.yellow : c2.red;
28686
+ lines.push(` ${c2.cyan("Budget".padEnd(18))} ${budgetColor(fmtTokens(s.budgetTokensRemaining))}${c2.dim("/")}${fmtTokens(s.budgetTokensTotal)} ${c2.dim(`(${pct}% left)`)}`);
28687
+ }
28688
+ const visibleModels = Array.from(s.modelUsage.entries()).filter(([model]) => !INTERNAL_CAPABILITIES.has(model));
28689
+ if (visibleModels.length > 0) {
28621
28690
  lines.push("");
28622
28691
  lines.push(` ${c2.bold("Models")}`);
28623
- for (const [model, count] of s.modelUsage) {
28692
+ for (const [model, count] of visibleModels) {
28624
28693
  let mIn = 0, mOut = 0;
28625
28694
  for (const user of s.users.values()) {
28626
28695
  const mm = user.models.get(model);
@@ -28643,17 +28712,29 @@ ${this.formatConnectionInfo()}`);
28643
28712
  lines.push(` ${c2.bold(user.ip)}`);
28644
28713
  lines.push(` ${c2.dim("Session:")} ${ageStr} ${c2.dim("Last seen:")} ${lastStr} ${c2.dim("Requests:")} ${user.requests}`);
28645
28714
  lines.push(` ${c2.dim("Tokens:")} in:${fmtTokens(user.tokensIn)} out:${fmtTokens(user.tokensOut)}`);
28646
- if (user.models.size > 0) {
28647
- const modelParts = [];
28648
- for (const [m, mm] of user.models) {
28649
- modelParts.push(`${m} (${mm.requests} reqs, ${fmtTokens(mm.tokensIn + mm.tokensOut)} tokens)`);
28715
+ const userModels = Array.from(user.models.entries()).filter(([m]) => !INTERNAL_CAPABILITIES.has(m));
28716
+ if (userModels.length > 0) {
28717
+ for (const [m, mm] of userModels) {
28718
+ lines.push(` ${c2.dim("\xB7")} ${c2.cyan(m)} ${c2.dim(`${mm.requests}req ${fmtTokens(mm.tokensIn + mm.tokensOut)}tok`)}`);
28650
28719
  }
28651
- lines.push(` ${c2.dim("Models:")} ${modelParts.join(", ")}`);
28652
28720
  }
28653
28721
  }
28654
28722
  }
28655
28723
  return lines.join("\n");
28656
28724
  }
28725
+ /** Update budget from rate limit headers */
28726
+ updateBudget(remaining, total, resetAt) {
28727
+ this._stats.budgetTokensRemaining = remaining;
28728
+ this._stats.budgetTokensTotal = total;
28729
+ this._stats.budgetResetAt = resetAt;
28730
+ this.emitStats();
28731
+ }
28732
+ get isPassthrough() {
28733
+ return this._passthrough;
28734
+ }
28735
+ get isLoadbalance() {
28736
+ return this._loadbalance;
28737
+ }
28657
28738
  };
28658
28739
  }
28659
28740
  });
@@ -33519,25 +33600,44 @@ async function handleSlashCommand(input, ctx) {
33519
33600
  }
33520
33601
  return "handled";
33521
33602
  }
33603
+ if (arg === "config") {
33604
+ await handleExposeConfig(ctx);
33605
+ return "handled";
33606
+ }
33607
+ if (arg?.startsWith("passthrough") || arg?.startsWith("forward")) {
33608
+ const ptParts = (arg ?? "").split(/\s+/);
33609
+ const ptLoadbalance = ptParts.includes("--loadbalance");
33610
+ try {
33611
+ const tunnelUrl = await ctx.exposeStart("passthrough", void 0, "libp2p", false, true, ptLoadbalance);
33612
+ if (tunnelUrl) {
33613
+ const info = ctx.getExposeInfo?.();
33614
+ if (info) {
33615
+ process.stdout.write("\n" + info.stats + "\n\n");
33616
+ }
33617
+ } else {
33618
+ renderError("Failed to start passthrough expose gateway.");
33619
+ }
33620
+ } catch (err) {
33621
+ renderError(`Expose passthrough error: ${err instanceof Error ? err.message : String(err)}`);
33622
+ }
33623
+ return "handled";
33624
+ }
33522
33625
  if (!arg) {
33523
33626
  const info = ctx.getExposeInfo?.();
33524
33627
  if (info && ctx.isExposeActive?.()) {
33525
33628
  process.stdout.write("\n" + info.stats + "\n\n");
33526
33629
  } else {
33527
33630
  renderInfo("Usage: /expose <backend> [options]");
33528
- renderInfo(" /expose ollama Expose local Ollama via libp2p (default)");
33529
- renderInfo(" /expose ollama --tunnel Expose via cloudflared tunnel");
33530
- renderInfo(" /expose ollama --libp2p Expose via libp2p (explicit)");
33531
- renderInfo(" /expose vllm Expose local vLLM (8000)");
33532
- renderInfo(" /expose llvm Expose local LLVM (8080)");
33533
- renderInfo(" /expose host:port Expose custom address");
33534
- renderInfo(" /expose stop Stop all gateways");
33535
- renderInfo(" /expose stop --tunnel Stop tunnel only");
33536
- renderInfo(" /expose stop --libp2p Stop libp2p only");
33537
- renderInfo(" /expose status Show usage stats");
33538
- renderInfo(" --key <key> Use specific auth key (tunnel mode)");
33539
- renderInfo(" --key Auto-generate auth key (tunnel mode)");
33540
- renderInfo(" --full Allow full Ollama API access (pull/delete/etc)");
33631
+ renderInfo(" /expose ollama Expose local Ollama via libp2p");
33632
+ renderInfo(" /expose ollama --tunnel Expose via cloudflared tunnel");
33633
+ renderInfo(" /expose vllm Expose local vLLM (8000)");
33634
+ renderInfo(" /expose passthrough --libp2p Forward /endpoint through libp2p");
33635
+ renderInfo(" /expose forward --loadbalance Forward with rate-limit distribution");
33636
+ renderInfo(" /expose config Configure expose settings");
33637
+ renderInfo(" /expose stop Stop all gateways");
33638
+ renderInfo(" /expose status Show usage stats");
33639
+ renderInfo(" --key <key> Use specific auth key (tunnel mode)");
33640
+ renderInfo(" --full Full Ollama API access");
33541
33641
  }
33542
33642
  return "handled";
33543
33643
  }
@@ -34168,6 +34268,92 @@ function applyConfigChanges(ctx, changes) {
34168
34268
  if (changes.commandsMode !== void 0)
34169
34269
  ctx.setCommandsMode?.(changes.commandsMode);
34170
34270
  }
34271
+ async function handleExposeConfig(ctx) {
34272
+ const info = ctx.getExposeInfo?.();
34273
+ const isActive = ctx.isExposeActive?.() ?? false;
34274
+ const items = [
34275
+ { key: "hdr_status", label: "Status", kind: "header" },
34276
+ { key: "status", label: isActive ? "Active" : "Inactive", detail: isActive ? "Gateway is running" : "No gateway active", kind: "info" }
34277
+ ];
34278
+ if (isActive && info) {
34279
+ items.push({ key: "view_stats", label: "View Stats", detail: "Show current gateway statistics", kind: "action" });
34280
+ items.push({ key: "stop_all", label: "Stop All Gateways", detail: "Shut down all expose transports", kind: "action" });
34281
+ }
34282
+ items.push({ key: "hdr_start", label: "Start Gateway", kind: "header" });
34283
+ items.push({ key: "start_ollama", label: "Expose Ollama (libp2p)", detail: "Expose local Ollama via P2P network", kind: "action" });
34284
+ items.push({ key: "start_ollama_tunnel", label: "Expose Ollama (tunnel)", detail: "Expose via cloudflared public tunnel", kind: "action" });
34285
+ items.push({ key: "start_passthrough", label: "Passthrough /endpoint (libp2p)", detail: "Forward configured endpoint through P2P", kind: "action" });
34286
+ items.push({ key: "start_passthrough_lb", label: "Passthrough + Load Balance", detail: "Forward with distributed rate-limit budget", kind: "action" });
34287
+ items.push({ key: "start_vllm", label: "Expose vLLM (libp2p)", detail: "Expose local vLLM server (port 8000)", kind: "action" });
34288
+ const skipKeys = items.filter((e) => e.kind === "header" || e.kind === "info").map((e) => e.key);
34289
+ const result = await tuiSelect({
34290
+ items,
34291
+ title: "Expose Configuration",
34292
+ rl: ctx.rl,
34293
+ skipKeys
34294
+ });
34295
+ if (!result.confirmed || !result.key) {
34296
+ renderInfo("Expose config cancelled.");
34297
+ return;
34298
+ }
34299
+ switch (result.key) {
34300
+ case "view_stats": {
34301
+ const freshInfo = ctx.getExposeInfo?.();
34302
+ if (freshInfo)
34303
+ process.stdout.write("\n" + freshInfo.stats + "\n\n");
34304
+ break;
34305
+ }
34306
+ case "stop_all":
34307
+ await ctx.exposeStop?.();
34308
+ renderInfo("All expose gateways stopped.");
34309
+ break;
34310
+ case "start_ollama": {
34311
+ const url = await ctx.exposeStart?.("ollama", void 0, "libp2p");
34312
+ if (url) {
34313
+ const i = ctx.getExposeInfo?.();
34314
+ if (i)
34315
+ process.stdout.write("\n" + i.stats + "\n\n");
34316
+ }
34317
+ break;
34318
+ }
34319
+ case "start_ollama_tunnel": {
34320
+ const url = await ctx.exposeStart?.("ollama", "", "tunnel");
34321
+ if (url) {
34322
+ const i = ctx.getExposeInfo?.();
34323
+ if (i)
34324
+ process.stdout.write("\n" + i.stats + "\n\n");
34325
+ }
34326
+ break;
34327
+ }
34328
+ case "start_passthrough": {
34329
+ const url = await ctx.exposeStart?.("passthrough", void 0, "libp2p", false, true, false);
34330
+ if (url) {
34331
+ const i = ctx.getExposeInfo?.();
34332
+ if (i)
34333
+ process.stdout.write("\n" + i.stats + "\n\n");
34334
+ }
34335
+ break;
34336
+ }
34337
+ case "start_passthrough_lb": {
34338
+ const url = await ctx.exposeStart?.("passthrough", void 0, "libp2p", false, true, true);
34339
+ if (url) {
34340
+ const i = ctx.getExposeInfo?.();
34341
+ if (i)
34342
+ process.stdout.write("\n" + i.stats + "\n\n");
34343
+ }
34344
+ break;
34345
+ }
34346
+ case "start_vllm": {
34347
+ const url = await ctx.exposeStart?.("vllm", void 0, "libp2p");
34348
+ if (url) {
34349
+ const i = ctx.getExposeInfo?.();
34350
+ if (i)
34351
+ process.stdout.write("\n" + i.stats + "\n\n");
34352
+ }
34353
+ break;
34354
+ }
34355
+ }
34356
+ }
34171
34357
  async function showModelPicker(ctx, local = false) {
34172
34358
  try {
34173
34359
  const models = await fetchModels(ctx.config.backendUrl, ctx.config.apiKey);
@@ -44237,14 +44423,16 @@ var init_status_bar = __esm({
44237
44423
  }
44238
44424
  }
44239
44425
  if (this._expose) {
44426
+ const INTERNAL_CAPS = /* @__PURE__ */ new Set(["system_metrics", "__list_capabilities"]);
44240
44427
  const statusEmoji = this._expose.status === "active" ? "\u{1F7E2}" : this._expose.status === "error" ? "\u{1F534}" : "\u{1F7E0}";
44241
- const models = Array.from(this._expose.modelUsage.keys());
44428
+ const models = Array.from(this._expose.modelUsage.keys()).filter((m2) => !INTERNAL_CAPS.has(m2));
44242
44429
  const modelParams = models.map((mdl) => {
44243
44430
  const pm = mdl.match(/(\d+[bBmM])/);
44244
44431
  return pm ? pm[1] : mdl.split(":")[0]?.split("/").pop() ?? mdl;
44245
44432
  });
44246
44433
  const modelStr = modelParams.join(",");
44247
- const reqStr = this._expose.totalRequests > 0 ? ` ${this._expose.totalRequests}req` : "";
44434
+ const visibleReqs = Array.from(this._expose.modelUsage.entries()).filter(([m2]) => !INTERNAL_CAPS.has(m2)).reduce((sum, [, n]) => sum + n, 0);
44435
+ const reqStr = visibleReqs > 0 ? ` ${visibleReqs}req` : "";
44248
44436
  const connStr = this._expose.activeConnections > 0 ? ` ${this._expose.activeConnections}conn` : "";
44249
44437
  const exposeExpanded = statusEmoji + pastel2(183, (modelStr ? " " + modelStr : "") + reqStr + connStr);
44250
44438
  const exposeCompact = statusEmoji + (modelStr ? pastel2(183, " " + modelStr) : "");
@@ -46689,11 +46877,15 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
46689
46877
  getCallUrl() {
46690
46878
  return voiceSession?.tunnelUrl ?? null;
46691
46879
  },
46692
- async exposeStart(kindOrUrl, authKey, transport, fullAccess) {
46693
- const knownKinds = ["ollama", "vllm", "llvm"];
46880
+ async exposeStart(kindOrUrl, authKey, transport, fullAccess, passthrough, loadbalance) {
46881
+ const knownKinds = ["ollama", "vllm", "llvm", "passthrough"];
46694
46882
  let kind;
46695
46883
  let targetUrl;
46696
- if (knownKinds.includes(kindOrUrl)) {
46884
+ if (kindOrUrl === "passthrough" || passthrough) {
46885
+ kind = "custom";
46886
+ targetUrl = config.backendUrl;
46887
+ passthrough = true;
46888
+ } else if (knownKinds.includes(kindOrUrl)) {
46697
46889
  kind = kindOrUrl;
46698
46890
  } else {
46699
46891
  kind = "custom";
@@ -46706,7 +46898,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
46706
46898
  p2pGateway = null;
46707
46899
  }
46708
46900
  const nexusTool = new NexusTool(repoRoot);
46709
- let exposeSpinnerMsg = "Connecting to nexus P2P network...";
46901
+ let exposeSpinnerMsg = passthrough ? `Connecting to nexus P2P network (passthrough \u2192 ${targetUrl})...` : "Connecting to nexus P2P network...";
46710
46902
  const exposeFrames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
46711
46903
  let exposeFrame = 0;
46712
46904
  const exposeSpinner = setInterval(() => {
@@ -46718,6 +46910,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
46718
46910
  targetUrl,
46719
46911
  authKey,
46720
46912
  stateDir: join50(repoRoot, ".oa"),
46913
+ passthrough: passthrough ?? false,
46914
+ loadbalance: loadbalance ?? false,
46721
46915
  onInfo: (msg) => {
46722
46916
  exposeSpinnerMsg = msg;
46723
46917
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.103.35",
3
+ "version": "0.103.36",
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",