open-agents-ai 0.103.49 → 0.103.51
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.
- package/dist/index.js +248 -26
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12122,27 +12122,6 @@ if (hasX402Key) {
|
|
|
12122
12122
|
}
|
|
12123
12123
|
const nexus = new NexusClient(nexusOpts);
|
|
12124
12124
|
|
|
12125
|
-
// Monkey-patch dialPeerProtocol to convert string multiaddrs to proper Multiaddr objects.
|
|
12126
|
-
// libp2p v3 (3.1.x) requires Multiaddr objects (with .getComponents()), but
|
|
12127
|
-
// open-agents-nexus resolves multiaddrs as plain strings. This shim wraps
|
|
12128
|
-
// node.dialProtocol to auto-convert strings before they reach libp2p's getPeerAddress().
|
|
12129
|
-
if (nexus.node && typeof nexus.node.dialProtocol === 'function') {
|
|
12130
|
-
var _origDialProtocol = nexus.node.dialProtocol.bind(nexus.node);
|
|
12131
|
-
nexus.node.dialProtocol = async function patchedDialProtocol(peer, protocols, options) {
|
|
12132
|
-
// If peer is a string (multiaddr), convert to a proper Multiaddr object
|
|
12133
|
-
if (typeof peer === 'string' && peer.startsWith('/')) {
|
|
12134
|
-
try {
|
|
12135
|
-
var { multiaddr: maFromStr } = await import('@multiformats/multiaddr');
|
|
12136
|
-
peer = maFromStr(peer);
|
|
12137
|
-
} catch (convErr) {
|
|
12138
|
-
dlog('multiaddr conversion failed: ' + (convErr.message || convErr));
|
|
12139
|
-
}
|
|
12140
|
-
}
|
|
12141
|
-
return _origDialProtocol(peer, protocols, options);
|
|
12142
|
-
};
|
|
12143
|
-
dlog('patched node.dialProtocol for multiaddr string conversion');
|
|
12144
|
-
}
|
|
12145
|
-
|
|
12146
12125
|
const rooms = new Map();
|
|
12147
12126
|
let connected = false;
|
|
12148
12127
|
const blockedPeers = [];
|
|
@@ -13182,6 +13161,30 @@ process.on('unhandledRejection', (reason) => {
|
|
|
13182
13161
|
}
|
|
13183
13162
|
connected = true;
|
|
13184
13163
|
|
|
13164
|
+
// Monkey-patch node.dialProtocol to convert string multiaddrs to Multiaddr objects.
|
|
13165
|
+
// libp2p v3 requires Multiaddr objects (with .getComponents()), but
|
|
13166
|
+
// open-agents-nexus resolves multiaddrs as plain strings in dialPeerProtocol().
|
|
13167
|
+
// nexus.node is only available AFTER connect(), so we patch here.
|
|
13168
|
+
var _patchNode = nexus.network ? nexus.network.node : nexus.node;
|
|
13169
|
+
if (_patchNode && typeof _patchNode.dialProtocol === 'function') {
|
|
13170
|
+
var _origDialProtocol = _patchNode.dialProtocol.bind(_patchNode);
|
|
13171
|
+
_patchNode.dialProtocol = async function patchedDialProtocol(peer, protocols, options) {
|
|
13172
|
+
if (typeof peer === 'string' && peer.startsWith('/')) {
|
|
13173
|
+
try {
|
|
13174
|
+
var { multiaddr: maFromStr } = await import('@multiformats/multiaddr');
|
|
13175
|
+
peer = maFromStr(peer);
|
|
13176
|
+
dlog('converted string multiaddr to Multiaddr object');
|
|
13177
|
+
} catch (convErr) {
|
|
13178
|
+
dlog('multiaddr conversion failed: ' + (convErr.message || convErr));
|
|
13179
|
+
}
|
|
13180
|
+
}
|
|
13181
|
+
return _origDialProtocol(peer, protocols, options);
|
|
13182
|
+
};
|
|
13183
|
+
dlog('patched node.dialProtocol for multiaddr string conversion');
|
|
13184
|
+
} else {
|
|
13185
|
+
dlog('WARNING: could not patch node.dialProtocol \u2014 node=' + !!_patchNode);
|
|
13186
|
+
}
|
|
13187
|
+
|
|
13185
13188
|
// v1.5.0: Setup metering audit hook
|
|
13186
13189
|
try {
|
|
13187
13190
|
if (nexus.metering && typeof nexus.metering.addHook === 'function') {
|
|
@@ -33833,12 +33836,12 @@ async function handleSlashCommand(input, ctx) {
|
|
|
33833
33836
|
return "handled";
|
|
33834
33837
|
}
|
|
33835
33838
|
if (arg === "status") {
|
|
33836
|
-
const
|
|
33837
|
-
if (
|
|
33838
|
-
process.stdout.write("\n" + info.stats + "\n\n");
|
|
33839
|
-
} else {
|
|
33839
|
+
const gateway = ctx.getExposeGateway?.();
|
|
33840
|
+
if (!gateway) {
|
|
33840
33841
|
renderWarning("No active expose gateway.");
|
|
33842
|
+
return "handled";
|
|
33841
33843
|
}
|
|
33844
|
+
await showExposeDashboard(gateway, ctx.rl);
|
|
33842
33845
|
return "handled";
|
|
33843
33846
|
}
|
|
33844
33847
|
if (arg === "config") {
|
|
@@ -35289,6 +35292,201 @@ async function switchModel(query, ctx, local = false) {
|
|
|
35289
35292
|
renderError(`Failed to switch model: ${err instanceof Error ? err.message : String(err)}`);
|
|
35290
35293
|
}
|
|
35291
35294
|
}
|
|
35295
|
+
function fmtDashTokens(n) {
|
|
35296
|
+
if (n < 1e3)
|
|
35297
|
+
return String(n);
|
|
35298
|
+
if (n < 1e6)
|
|
35299
|
+
return `${(n / 1e3).toFixed(1)}K`;
|
|
35300
|
+
return `${(n / 1e6).toFixed(1)}M`;
|
|
35301
|
+
}
|
|
35302
|
+
function fmtUptime(ms) {
|
|
35303
|
+
const sec = Math.floor(ms / 1e3);
|
|
35304
|
+
if (sec < 60)
|
|
35305
|
+
return `${sec}s`;
|
|
35306
|
+
if (sec < 3600)
|
|
35307
|
+
return `${Math.floor(sec / 60)}m ${sec % 60}s`;
|
|
35308
|
+
return `${Math.floor(sec / 3600)}h ${Math.floor(sec % 3600 / 60)}m`;
|
|
35309
|
+
}
|
|
35310
|
+
async function showExposeDashboard(gateway, rl) {
|
|
35311
|
+
const stdin = process.stdin;
|
|
35312
|
+
const stdout = process.stdout;
|
|
35313
|
+
if (!stdin.isTTY) {
|
|
35314
|
+
if (typeof gateway.formatStats === "function") {
|
|
35315
|
+
stdout.write("\n" + gateway.formatStats() + "\n\n");
|
|
35316
|
+
}
|
|
35317
|
+
return;
|
|
35318
|
+
}
|
|
35319
|
+
let lastRenderedLines = 0;
|
|
35320
|
+
let refreshTimer = null;
|
|
35321
|
+
const hadRawMode = stdin.isRaw;
|
|
35322
|
+
const savedListeners = rl ? stdin.listeners("data").slice() : [];
|
|
35323
|
+
if (rl) {
|
|
35324
|
+
rl.pause();
|
|
35325
|
+
for (const fn of savedListeners)
|
|
35326
|
+
stdin.removeListener("data", fn);
|
|
35327
|
+
}
|
|
35328
|
+
stdin.setRawMode(true);
|
|
35329
|
+
stdin.resume();
|
|
35330
|
+
stdout.write("\x1B[?25l");
|
|
35331
|
+
function buildDashboard() {
|
|
35332
|
+
const s = gateway.stats ?? gateway._stats;
|
|
35333
|
+
if (!s)
|
|
35334
|
+
return [" No stats available.", "", " Press Escape or 'q' to close."];
|
|
35335
|
+
const lines = [];
|
|
35336
|
+
const now = Date.now();
|
|
35337
|
+
const uptime = fmtUptime(now - (s.startedAt || now));
|
|
35338
|
+
const statusColor = s.status === "active" ? c2.green : s.status === "error" ? c2.red : c2.yellow;
|
|
35339
|
+
lines.push("");
|
|
35340
|
+
lines.push(` ${c2.bold("Expose Dashboard")} ${statusColor("\u25CF")} ${statusColor(s.status || "unknown")} ${c2.dim(`uptime ${uptime}`)}`);
|
|
35341
|
+
lines.push(` ${c2.dim("\u2500".repeat(60))}`);
|
|
35342
|
+
const activeConns = s.activeConnections || 0;
|
|
35343
|
+
const totalReqs = s.totalRequests || 0;
|
|
35344
|
+
const errors = s.errors || 0;
|
|
35345
|
+
const tokIn = s.totalTokensIn || 0;
|
|
35346
|
+
const tokOut = s.totalTokensOut || 0;
|
|
35347
|
+
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")}`);
|
|
35348
|
+
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)}`);
|
|
35349
|
+
if (s.budgetTokensTotal > 0) {
|
|
35350
|
+
const pct = Math.round(s.budgetTokensRemaining / s.budgetTokensTotal * 100);
|
|
35351
|
+
const budgetColor = pct > 50 ? c2.green : pct > 20 ? c2.yellow : c2.red;
|
|
35352
|
+
const barLen = 20;
|
|
35353
|
+
const filledLen = Math.round(pct / 100 * barLen);
|
|
35354
|
+
const bar = budgetColor("\u2588".repeat(filledLen)) + c2.dim("\u2591".repeat(barLen - filledLen));
|
|
35355
|
+
lines.push(` ${c2.cyan("Budget")} ${bar} ${budgetColor(`${pct}%`)} ${c2.dim(`(${fmtDashTokens(s.budgetTokensRemaining)}/${fmtDashTokens(s.budgetTokensTotal)})`)}`);
|
|
35356
|
+
}
|
|
35357
|
+
const modelEntries = s.modelUsage ? Array.from(s.modelUsage.entries()).filter(([m]) => !DASH_INTERNAL.has(m)) : [];
|
|
35358
|
+
if (modelEntries.length > 0) {
|
|
35359
|
+
lines.push("");
|
|
35360
|
+
lines.push(` ${c2.bold("Models")}`);
|
|
35361
|
+
for (const [model, count] of modelEntries) {
|
|
35362
|
+
let mIn = 0, mOut = 0;
|
|
35363
|
+
if (s.users) {
|
|
35364
|
+
for (const user of s.users.values()) {
|
|
35365
|
+
const mm = user.models?.get?.(model);
|
|
35366
|
+
if (mm) {
|
|
35367
|
+
mIn += mm.tokensIn || 0;
|
|
35368
|
+
mOut += mm.tokensOut || 0;
|
|
35369
|
+
}
|
|
35370
|
+
}
|
|
35371
|
+
}
|
|
35372
|
+
const bar = count > 0 ? c2.green("\u25AE".repeat(Math.min(count, 20))) : "";
|
|
35373
|
+
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}`);
|
|
35374
|
+
}
|
|
35375
|
+
}
|
|
35376
|
+
const users = s.users ? Array.from(s.users.values()) : [];
|
|
35377
|
+
if (users.length > 0) {
|
|
35378
|
+
lines.push("");
|
|
35379
|
+
lines.push(` ${c2.bold("Connected Peers")} (${users.length})`);
|
|
35380
|
+
for (const user of users) {
|
|
35381
|
+
const ageSec = Math.floor((now - (user.firstSeen || now)) / 1e3);
|
|
35382
|
+
const ageStr = ageSec < 60 ? `${ageSec}s` : ageSec < 3600 ? `${Math.floor(ageSec / 60)}m` : `${Math.floor(ageSec / 3600)}h${Math.floor(ageSec % 3600 / 60)}m`;
|
|
35383
|
+
const lastSec = Math.floor((now - (user.lastSeen || now)) / 1e3);
|
|
35384
|
+
const lastStr = lastSec < 5 ? c2.green("now") : lastSec < 60 ? `${lastSec}s ago` : `${Math.floor(lastSec / 60)}m ago`;
|
|
35385
|
+
const activeStr = (user.activeRequests || 0) > 0 ? c2.green(` \u25CF ${user.activeRequests} active`) : "";
|
|
35386
|
+
lines.push(` ${c2.bold(user.ip || "unknown")}${activeStr}`);
|
|
35387
|
+
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)}`);
|
|
35388
|
+
const userModels = user.models ? Array.from(user.models.entries()).filter(([m]) => !DASH_INTERNAL.has(m)) : [];
|
|
35389
|
+
for (const [m, mm] of userModels) {
|
|
35390
|
+
lines.push(` ${c2.dim("\u2514")} ${c2.cyan(m)} ${c2.dim(`${mm.requests || 0}req ${fmtDashTokens((mm.tokensIn || 0) + (mm.tokensOut || 0))}tok`)}`);
|
|
35391
|
+
}
|
|
35392
|
+
}
|
|
35393
|
+
}
|
|
35394
|
+
lines.push("");
|
|
35395
|
+
lines.push(` ${c2.dim("Press Escape or 'q' to close \u2502 Live \u25CF updates every 2s")}`);
|
|
35396
|
+
lines.push("");
|
|
35397
|
+
return lines;
|
|
35398
|
+
}
|
|
35399
|
+
function render() {
|
|
35400
|
+
const lines = buildDashboard();
|
|
35401
|
+
if (lastRenderedLines > 0) {
|
|
35402
|
+
stdout.write(`\x1B[${lastRenderedLines}A`);
|
|
35403
|
+
for (let i = 0; i < lastRenderedLines; i++) {
|
|
35404
|
+
stdout.write("\x1B[2K\n");
|
|
35405
|
+
}
|
|
35406
|
+
stdout.write(`\x1B[${lastRenderedLines}A`);
|
|
35407
|
+
}
|
|
35408
|
+
stdout.write(lines.join("\n") + "\n");
|
|
35409
|
+
lastRenderedLines = lines.length;
|
|
35410
|
+
}
|
|
35411
|
+
function cleanup() {
|
|
35412
|
+
if (refreshTimer) {
|
|
35413
|
+
clearInterval(refreshTimer);
|
|
35414
|
+
refreshTimer = null;
|
|
35415
|
+
}
|
|
35416
|
+
gateway.removeListener?.("stats", onStats);
|
|
35417
|
+
if (lastRenderedLines > 0) {
|
|
35418
|
+
stdout.write(`\x1B[${lastRenderedLines}A`);
|
|
35419
|
+
for (let i = 0; i < lastRenderedLines; i++) {
|
|
35420
|
+
stdout.write("\x1B[2K\n");
|
|
35421
|
+
}
|
|
35422
|
+
stdout.write(`\x1B[${lastRenderedLines}A`);
|
|
35423
|
+
}
|
|
35424
|
+
stdout.write("\x1B[?25h");
|
|
35425
|
+
stdin.setRawMode(hadRawMode ?? false);
|
|
35426
|
+
stdin.removeListener("data", onKey);
|
|
35427
|
+
if (rl) {
|
|
35428
|
+
for (const fn of savedListeners)
|
|
35429
|
+
stdin.on("data", fn);
|
|
35430
|
+
rl.resume();
|
|
35431
|
+
}
|
|
35432
|
+
}
|
|
35433
|
+
function onStats() {
|
|
35434
|
+
render();
|
|
35435
|
+
}
|
|
35436
|
+
function onKey(chunk) {
|
|
35437
|
+
const key = chunk.toString();
|
|
35438
|
+
if (key === "\x1B" || key === "q" || key === "Q") {
|
|
35439
|
+
cleanup();
|
|
35440
|
+
return;
|
|
35441
|
+
}
|
|
35442
|
+
if (key === "") {
|
|
35443
|
+
cleanup();
|
|
35444
|
+
return;
|
|
35445
|
+
}
|
|
35446
|
+
}
|
|
35447
|
+
if (typeof gateway.on === "function") {
|
|
35448
|
+
gateway.on("stats", onStats);
|
|
35449
|
+
}
|
|
35450
|
+
refreshTimer = setInterval(render, 2e3);
|
|
35451
|
+
render();
|
|
35452
|
+
stdin.on("data", onKey);
|
|
35453
|
+
return new Promise((resolve31) => {
|
|
35454
|
+
const origCleanup = cleanup;
|
|
35455
|
+
function wrappedCleanup() {
|
|
35456
|
+
origCleanup();
|
|
35457
|
+
resolve31();
|
|
35458
|
+
}
|
|
35459
|
+
stdin.removeListener("data", onKey);
|
|
35460
|
+
function onKeyWrapped(chunk) {
|
|
35461
|
+
const key = chunk.toString();
|
|
35462
|
+
if (key === "\x1B" || key === "q" || key === "Q" || key === "") {
|
|
35463
|
+
if (refreshTimer) {
|
|
35464
|
+
clearInterval(refreshTimer);
|
|
35465
|
+
refreshTimer = null;
|
|
35466
|
+
}
|
|
35467
|
+
gateway.removeListener?.("stats", onStats);
|
|
35468
|
+
if (lastRenderedLines > 0) {
|
|
35469
|
+
stdout.write(`\x1B[${lastRenderedLines}A`);
|
|
35470
|
+
for (let i = 0; i < lastRenderedLines; i++) {
|
|
35471
|
+
stdout.write("\x1B[2K\n");
|
|
35472
|
+
}
|
|
35473
|
+
stdout.write(`\x1B[${lastRenderedLines}A`);
|
|
35474
|
+
}
|
|
35475
|
+
stdout.write("\x1B[?25h");
|
|
35476
|
+
stdin.setRawMode(hadRawMode ?? false);
|
|
35477
|
+
stdin.removeListener("data", onKeyWrapped);
|
|
35478
|
+
if (rl) {
|
|
35479
|
+
for (const fn of savedListeners)
|
|
35480
|
+
stdin.on("data", fn);
|
|
35481
|
+
rl.resume();
|
|
35482
|
+
}
|
|
35483
|
+
resolve31();
|
|
35484
|
+
}
|
|
35485
|
+
}
|
|
35486
|
+
stdin.on("data", onKeyWrapped);
|
|
35487
|
+
});
|
|
35488
|
+
}
|
|
35489
|
+
var DASH_INTERNAL;
|
|
35292
35490
|
var init_commands = __esm({
|
|
35293
35491
|
"packages/cli/dist/tui/commands.js"() {
|
|
35294
35492
|
"use strict";
|
|
@@ -35304,6 +35502,7 @@ var init_commands = __esm({
|
|
|
35304
35502
|
init_listen();
|
|
35305
35503
|
init_dist();
|
|
35306
35504
|
init_tui_select();
|
|
35505
|
+
DASH_INTERNAL = /* @__PURE__ */ new Set(["system_metrics", "__list_capabilities"]);
|
|
35307
35506
|
}
|
|
35308
35507
|
});
|
|
35309
35508
|
|
|
@@ -44204,15 +44403,34 @@ var init_status_bar = __esm({
|
|
|
44204
44403
|
}
|
|
44205
44404
|
/** Expose gateway status — shown after capability emojis */
|
|
44206
44405
|
_expose = null;
|
|
44406
|
+
/** Blink state for expose icon during active inference */
|
|
44407
|
+
_exposeBlinkOn = true;
|
|
44408
|
+
_exposeBlinkTimer = null;
|
|
44207
44409
|
/** Update expose gateway status */
|
|
44208
44410
|
setExposeStatus(status) {
|
|
44209
44411
|
this._expose = status;
|
|
44412
|
+
if (status.activeConnections > 0 && !this._exposeBlinkTimer) {
|
|
44413
|
+
this._exposeBlinkTimer = setInterval(() => {
|
|
44414
|
+
this._exposeBlinkOn = !this._exposeBlinkOn;
|
|
44415
|
+
if (this.active)
|
|
44416
|
+
this.renderFooterPreserveCursor();
|
|
44417
|
+
}, 500);
|
|
44418
|
+
} else if (status.activeConnections === 0 && this._exposeBlinkTimer) {
|
|
44419
|
+
clearInterval(this._exposeBlinkTimer);
|
|
44420
|
+
this._exposeBlinkTimer = null;
|
|
44421
|
+
this._exposeBlinkOn = true;
|
|
44422
|
+
}
|
|
44210
44423
|
if (this.active)
|
|
44211
44424
|
this.renderFooterPreserveCursor();
|
|
44212
44425
|
}
|
|
44213
44426
|
/** Clear expose gateway status */
|
|
44214
44427
|
clearExposeStatus() {
|
|
44215
44428
|
this._expose = null;
|
|
44429
|
+
if (this._exposeBlinkTimer) {
|
|
44430
|
+
clearInterval(this._exposeBlinkTimer);
|
|
44431
|
+
this._exposeBlinkTimer = null;
|
|
44432
|
+
this._exposeBlinkOn = true;
|
|
44433
|
+
}
|
|
44216
44434
|
if (this.active)
|
|
44217
44435
|
this.renderFooterPreserveCursor();
|
|
44218
44436
|
}
|
|
@@ -44671,7 +44889,7 @@ var init_status_bar = __esm({
|
|
|
44671
44889
|
}
|
|
44672
44890
|
if (this._expose) {
|
|
44673
44891
|
const INTERNAL_CAPS = /* @__PURE__ */ new Set(["system_metrics", "__list_capabilities"]);
|
|
44674
|
-
const statusEmoji = this._expose.status === "active" ? "\u{1F7E2}" : this._expose.status === "error" ? "\u{1F534}" : "\u{1F7E0}";
|
|
44892
|
+
const statusEmoji = this._expose.activeConnections > 0 ? this._exposeBlinkOn ? "\u{1F7E2}" : "\u26AB" : this._expose.status === "active" ? "\u{1F7E2}" : this._expose.status === "error" ? "\u{1F534}" : "\u{1F7E0}";
|
|
44675
44893
|
const models = Array.from(this._expose.modelUsage.keys()).filter((m2) => !INTERNAL_CAPS.has(m2));
|
|
44676
44894
|
const modelParams = models.map((mdl) => {
|
|
44677
44895
|
const pm = mdl.match(/(\d+[bBmM])/);
|
|
@@ -47274,6 +47492,10 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
47274
47492
|
stats: infos[0].stats
|
|
47275
47493
|
};
|
|
47276
47494
|
},
|
|
47495
|
+
/** Get the raw expose gateway instance for live dashboard */
|
|
47496
|
+
getExposeGateway() {
|
|
47497
|
+
return p2pGateway ?? tunnelGateway ?? null;
|
|
47498
|
+
},
|
|
47277
47499
|
// ── Nexus daemon connect ──────────────────────────────────────────────
|
|
47278
47500
|
async nexusConnect() {
|
|
47279
47501
|
const nexusTool = new NexusTool(repoRoot);
|
package/package.json
CHANGED