open-agents-ai 0.103.15 → 0.103.17
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 +535 -56
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6598,8 +6598,8 @@ async function loadTranscribeCli() {
|
|
|
6598
6598
|
const nvmBase = join16(homedir6(), ".nvm", "versions", "node");
|
|
6599
6599
|
if (existsSync13(nvmBase)) {
|
|
6600
6600
|
try {
|
|
6601
|
-
const { readdirSync:
|
|
6602
|
-
for (const ver of
|
|
6601
|
+
const { readdirSync: readdirSync16 } = await import("node:fs");
|
|
6602
|
+
for (const ver of readdirSync16(nvmBase)) {
|
|
6603
6603
|
const tcPath = join16(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
|
|
6604
6604
|
if (existsSync13(join16(tcPath, "dist", "index.js"))) {
|
|
6605
6605
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
@@ -13062,7 +13062,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13062
13062
|
result = await this.sendDaemonCmd("room_members", args);
|
|
13063
13063
|
break;
|
|
13064
13064
|
case "expose":
|
|
13065
|
-
result = await this.sendDaemonCmd("expose", args,
|
|
13065
|
+
result = await this.sendDaemonCmd("expose", args, 6e4);
|
|
13066
13066
|
break;
|
|
13067
13067
|
case "pricing_menu":
|
|
13068
13068
|
result = await this.sendDaemonCmd("pricing_menu", args);
|
|
@@ -20590,8 +20590,8 @@ var init_listen = __esm({
|
|
|
20590
20590
|
const nvmBase = join34(homedir8(), ".nvm", "versions", "node");
|
|
20591
20591
|
if (existsSync25(nvmBase)) {
|
|
20592
20592
|
try {
|
|
20593
|
-
const { readdirSync:
|
|
20594
|
-
for (const ver of
|
|
20593
|
+
const { readdirSync: readdirSync16 } = await import("node:fs");
|
|
20594
|
+
for (const ver of readdirSync16(nvmBase)) {
|
|
20595
20595
|
const tcPath = join34(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
|
|
20596
20596
|
if (existsSync25(join34(tcPath, "dist", "index.js"))) {
|
|
20597
20597
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
@@ -26203,7 +26203,7 @@ import { EventEmitter as EventEmitter3 } from "node:events";
|
|
|
26203
26203
|
import { randomBytes as randomBytes7 } from "node:crypto";
|
|
26204
26204
|
import { URL as URL2 } from "node:url";
|
|
26205
26205
|
import { loadavg, cpus, totalmem, freemem } from "node:os";
|
|
26206
|
-
import { existsSync as existsSync26, readFileSync as readFileSync18, writeFileSync as writeFileSync8, unlinkSync as unlinkSync3, mkdirSync as mkdirSync8 } from "node:fs";
|
|
26206
|
+
import { existsSync as existsSync26, readFileSync as readFileSync18, writeFileSync as writeFileSync8, unlinkSync as unlinkSync3, mkdirSync as mkdirSync8, readdirSync as readdirSync7 } from "node:fs";
|
|
26207
26207
|
import { join as join35 } from "node:path";
|
|
26208
26208
|
function cleanForwardHeaders(raw, targetHost) {
|
|
26209
26209
|
const out = {};
|
|
@@ -26223,6 +26223,13 @@ function cleanForwardHeaders(raw, targetHost) {
|
|
|
26223
26223
|
out.host = targetHost;
|
|
26224
26224
|
return out;
|
|
26225
26225
|
}
|
|
26226
|
+
function fmtTokens(n) {
|
|
26227
|
+
if (n < 1e3)
|
|
26228
|
+
return String(n);
|
|
26229
|
+
if (n < 1e6)
|
|
26230
|
+
return `${(n / 1e3).toFixed(1)}K`;
|
|
26231
|
+
return `${(n / 1e6).toFixed(1)}M`;
|
|
26232
|
+
}
|
|
26226
26233
|
function readExposeState(stateDir) {
|
|
26227
26234
|
try {
|
|
26228
26235
|
const path = join35(stateDir, STATE_FILE_NAME);
|
|
@@ -26306,7 +26313,7 @@ async function collectSystemMetricsAsync() {
|
|
|
26306
26313
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
26307
26314
|
};
|
|
26308
26315
|
}
|
|
26309
|
-
var HOP_BY_HOP_HEADERS, CF_HEADERS_PREFIX, DEFAULT_TARGETS, STATE_FILE_NAME, ExposeGateway;
|
|
26316
|
+
var HOP_BY_HOP_HEADERS, CF_HEADERS_PREFIX, DEFAULT_TARGETS, STATE_FILE_NAME, ExposeGateway, ExposeP2PGateway;
|
|
26310
26317
|
var init_expose = __esm({
|
|
26311
26318
|
"packages/cli/dist/tui/expose.js"() {
|
|
26312
26319
|
"use strict";
|
|
@@ -26347,7 +26354,11 @@ var init_expose = __esm({
|
|
|
26347
26354
|
totalRequests: 0,
|
|
26348
26355
|
activeConnections: 0,
|
|
26349
26356
|
errors: 0,
|
|
26350
|
-
|
|
26357
|
+
totalTokensIn: 0,
|
|
26358
|
+
totalTokensOut: 0,
|
|
26359
|
+
startedAt: Date.now(),
|
|
26360
|
+
modelUsage: /* @__PURE__ */ new Map(),
|
|
26361
|
+
users: /* @__PURE__ */ new Map()
|
|
26351
26362
|
};
|
|
26352
26363
|
get tunnelUrl() {
|
|
26353
26364
|
return this._tunnelUrl;
|
|
@@ -26509,7 +26520,20 @@ var init_expose = __esm({
|
|
|
26509
26520
|
totalRequests: this._stats.totalRequests,
|
|
26510
26521
|
activeConnections: this._stats.activeConnections,
|
|
26511
26522
|
errors: this._stats.errors,
|
|
26512
|
-
|
|
26523
|
+
totalTokensIn: this._stats.totalTokensIn,
|
|
26524
|
+
totalTokensOut: this._stats.totalTokensOut,
|
|
26525
|
+
uptimeSeconds: Math.floor((Date.now() - this._stats.startedAt) / 1e3),
|
|
26526
|
+
modelUsage: Object.fromEntries(this._stats.modelUsage),
|
|
26527
|
+
users: Array.from(this._stats.users.values()).map((u) => ({
|
|
26528
|
+
ip: u.ip,
|
|
26529
|
+
requests: u.requests,
|
|
26530
|
+
tokensIn: u.tokensIn,
|
|
26531
|
+
tokensOut: u.tokensOut,
|
|
26532
|
+
activeRequests: u.activeRequests,
|
|
26533
|
+
firstSeen: new Date(u.firstSeen).toISOString(),
|
|
26534
|
+
lastSeen: new Date(u.lastSeen).toISOString(),
|
|
26535
|
+
models: Object.fromEntries(Array.from(u.models.entries()).map(([m, v]) => [m, { requests: v.requests, tokensIn: v.tokensIn, tokensOut: v.tokensOut }]))
|
|
26536
|
+
}))
|
|
26513
26537
|
};
|
|
26514
26538
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
26515
26539
|
res.end(JSON.stringify({ ...metrics, gateway: gatewayStats }));
|
|
@@ -26519,8 +26543,26 @@ var init_expose = __esm({
|
|
|
26519
26543
|
});
|
|
26520
26544
|
return;
|
|
26521
26545
|
}
|
|
26546
|
+
const userIp = req.headers["cf-connecting-ip"] ?? req.headers["x-forwarded-for"]?.split(",")[0]?.trim() ?? req.socket.remoteAddress ?? "unknown";
|
|
26547
|
+
let user = this._stats.users.get(userIp);
|
|
26548
|
+
if (!user) {
|
|
26549
|
+
user = {
|
|
26550
|
+
ip: userIp,
|
|
26551
|
+
firstSeen: Date.now(),
|
|
26552
|
+
lastSeen: Date.now(),
|
|
26553
|
+
requests: 0,
|
|
26554
|
+
tokensIn: 0,
|
|
26555
|
+
tokensOut: 0,
|
|
26556
|
+
activeRequests: 0,
|
|
26557
|
+
models: /* @__PURE__ */ new Map()
|
|
26558
|
+
};
|
|
26559
|
+
this._stats.users.set(userIp, user);
|
|
26560
|
+
}
|
|
26522
26561
|
this._stats.totalRequests++;
|
|
26523
26562
|
this._stats.activeConnections++;
|
|
26563
|
+
user.requests++;
|
|
26564
|
+
user.activeRequests++;
|
|
26565
|
+
user.lastSeen = Date.now();
|
|
26524
26566
|
this.emitStats();
|
|
26525
26567
|
url.searchParams.delete("key");
|
|
26526
26568
|
const forwardPath = url.pathname + url.search;
|
|
@@ -26529,14 +26571,22 @@ var init_expose = __esm({
|
|
|
26529
26571
|
req.on("end", () => {
|
|
26530
26572
|
const body = Buffer.concat(bodyChunks);
|
|
26531
26573
|
let isStreaming = false;
|
|
26574
|
+
let requestModel = "";
|
|
26532
26575
|
if (req.method === "POST" && body.length > 0) {
|
|
26533
26576
|
try {
|
|
26534
26577
|
const text = body.toString("utf8", 0, Math.min(body.length, 1024));
|
|
26535
26578
|
const modelMatch = text.match(/"model"\s*:\s*"([^"]+)"/);
|
|
26536
26579
|
if (modelMatch) {
|
|
26537
|
-
|
|
26538
|
-
const count = this._stats.modelUsage.get(
|
|
26539
|
-
this._stats.modelUsage.set(
|
|
26580
|
+
requestModel = modelMatch[1];
|
|
26581
|
+
const count = this._stats.modelUsage.get(requestModel) ?? 0;
|
|
26582
|
+
this._stats.modelUsage.set(requestModel, count + 1);
|
|
26583
|
+
let mm = user.models.get(requestModel);
|
|
26584
|
+
if (!mm) {
|
|
26585
|
+
mm = { requests: 0, tokensIn: 0, tokensOut: 0, lastUsed: Date.now() };
|
|
26586
|
+
user.models.set(requestModel, mm);
|
|
26587
|
+
}
|
|
26588
|
+
mm.requests++;
|
|
26589
|
+
mm.lastUsed = Date.now();
|
|
26540
26590
|
}
|
|
26541
26591
|
isStreaming = /"stream"\s*:\s*true/.test(text);
|
|
26542
26592
|
} catch {
|
|
@@ -26567,6 +26617,50 @@ var init_expose = __esm({
|
|
|
26567
26617
|
heartbeatTimer = null;
|
|
26568
26618
|
}
|
|
26569
26619
|
};
|
|
26620
|
+
let responseTail = "";
|
|
26621
|
+
const finalizeRequest = () => {
|
|
26622
|
+
user.activeRequests = Math.max(0, user.activeRequests - 1);
|
|
26623
|
+
this._stats.activeConnections = Math.max(0, this._stats.activeConnections - 1);
|
|
26624
|
+
try {
|
|
26625
|
+
const promptEval = responseTail.match(/"prompt_eval_count"\s*:\s*(\d+)/);
|
|
26626
|
+
const evalCount = responseTail.match(/"eval_count"\s*:\s*(\d+)/);
|
|
26627
|
+
if (promptEval || evalCount) {
|
|
26628
|
+
const tIn = parseInt(promptEval?.[1] ?? "0", 10);
|
|
26629
|
+
const tOut = parseInt(evalCount?.[1] ?? "0", 10);
|
|
26630
|
+
this._stats.totalTokensIn += tIn;
|
|
26631
|
+
this._stats.totalTokensOut += tOut;
|
|
26632
|
+
user.tokensIn += tIn;
|
|
26633
|
+
user.tokensOut += tOut;
|
|
26634
|
+
if (requestModel) {
|
|
26635
|
+
const mm = user.models.get(requestModel);
|
|
26636
|
+
if (mm) {
|
|
26637
|
+
mm.tokensIn += tIn;
|
|
26638
|
+
mm.tokensOut += tOut;
|
|
26639
|
+
}
|
|
26640
|
+
}
|
|
26641
|
+
} else {
|
|
26642
|
+
const promptTokens = responseTail.match(/"prompt_tokens"\s*:\s*(\d+)/);
|
|
26643
|
+
const completionTokens = responseTail.match(/"completion_tokens"\s*:\s*(\d+)/);
|
|
26644
|
+
if (promptTokens || completionTokens) {
|
|
26645
|
+
const tIn = parseInt(promptTokens?.[1] ?? "0", 10);
|
|
26646
|
+
const tOut = parseInt(completionTokens?.[1] ?? "0", 10);
|
|
26647
|
+
this._stats.totalTokensIn += tIn;
|
|
26648
|
+
this._stats.totalTokensOut += tOut;
|
|
26649
|
+
user.tokensIn += tIn;
|
|
26650
|
+
user.tokensOut += tOut;
|
|
26651
|
+
if (requestModel) {
|
|
26652
|
+
const mm = user.models.get(requestModel);
|
|
26653
|
+
if (mm) {
|
|
26654
|
+
mm.tokensIn += tIn;
|
|
26655
|
+
mm.tokensOut += tOut;
|
|
26656
|
+
}
|
|
26657
|
+
}
|
|
26658
|
+
}
|
|
26659
|
+
}
|
|
26660
|
+
} catch {
|
|
26661
|
+
}
|
|
26662
|
+
this.emitStats();
|
|
26663
|
+
};
|
|
26570
26664
|
const proxyReq = httpRequest({
|
|
26571
26665
|
hostname: target.hostname,
|
|
26572
26666
|
port: target.port || (target.protocol === "https:" ? 443 : 80),
|
|
@@ -26576,8 +26670,14 @@ var init_expose = __esm({
|
|
|
26576
26670
|
}, (proxyRes) => {
|
|
26577
26671
|
cleanupHeartbeat();
|
|
26578
26672
|
proxyRes.on("error", () => {
|
|
26579
|
-
|
|
26580
|
-
|
|
26673
|
+
finalizeRequest();
|
|
26674
|
+
});
|
|
26675
|
+
proxyRes.on("data", (chunk) => {
|
|
26676
|
+
const text = chunk.toString();
|
|
26677
|
+
responseTail += text;
|
|
26678
|
+
if (responseTail.length > 2048) {
|
|
26679
|
+
responseTail = responseTail.slice(-2048);
|
|
26680
|
+
}
|
|
26581
26681
|
});
|
|
26582
26682
|
if (isStreaming) {
|
|
26583
26683
|
if (proxyRes.statusCode !== 200) {
|
|
@@ -26597,8 +26697,7 @@ var init_expose = __esm({
|
|
|
26597
26697
|
} catch {
|
|
26598
26698
|
}
|
|
26599
26699
|
this._stats.errors++;
|
|
26600
|
-
|
|
26601
|
-
this.emitStats();
|
|
26700
|
+
finalizeRequest();
|
|
26602
26701
|
});
|
|
26603
26702
|
return;
|
|
26604
26703
|
}
|
|
@@ -26608,14 +26707,12 @@ var init_expose = __esm({
|
|
|
26608
26707
|
proxyRes.pipe(res);
|
|
26609
26708
|
}
|
|
26610
26709
|
proxyRes.on("end", () => {
|
|
26611
|
-
|
|
26612
|
-
this.emitStats();
|
|
26710
|
+
finalizeRequest();
|
|
26613
26711
|
});
|
|
26614
26712
|
});
|
|
26615
26713
|
proxyReq.on("error", (err) => {
|
|
26616
26714
|
cleanupHeartbeat();
|
|
26617
26715
|
this._stats.errors++;
|
|
26618
|
-
this._stats.activeConnections = Math.max(0, this._stats.activeConnections - 1);
|
|
26619
26716
|
if (!res.headersSent) {
|
|
26620
26717
|
res.writeHead(502, { "Content-Type": "application/json" });
|
|
26621
26718
|
res.end(JSON.stringify({ error: `Backend unreachable: ${err.message}` }));
|
|
@@ -26631,7 +26728,7 @@ var init_expose = __esm({
|
|
|
26631
26728
|
} catch {
|
|
26632
26729
|
}
|
|
26633
26730
|
}
|
|
26634
|
-
|
|
26731
|
+
finalizeRequest();
|
|
26635
26732
|
});
|
|
26636
26733
|
if (body.length > 0) {
|
|
26637
26734
|
proxyReq.write(body);
|
|
@@ -26639,6 +26736,7 @@ var init_expose = __esm({
|
|
|
26639
26736
|
proxyReq.end();
|
|
26640
26737
|
});
|
|
26641
26738
|
req.on("error", () => {
|
|
26739
|
+
user.activeRequests = Math.max(0, user.activeRequests - 1);
|
|
26642
26740
|
this._stats.activeConnections = Math.max(0, this._stats.activeConnections - 1);
|
|
26643
26741
|
this.emitStats();
|
|
26644
26742
|
});
|
|
@@ -26669,8 +26767,12 @@ var init_expose = __esm({
|
|
|
26669
26767
|
});
|
|
26670
26768
|
this._cloudflaredPid = this.cloudflaredProcess.pid ?? null;
|
|
26671
26769
|
let urlFound = false;
|
|
26770
|
+
let stderrOutput = "";
|
|
26672
26771
|
const handleOutput = (data) => {
|
|
26673
26772
|
const text = data.toString();
|
|
26773
|
+
stderrOutput += text;
|
|
26774
|
+
if (stderrOutput.length > 4096)
|
|
26775
|
+
stderrOutput = stderrOutput.slice(-4096);
|
|
26674
26776
|
const urlMatch = text.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/);
|
|
26675
26777
|
if (urlMatch && !urlFound) {
|
|
26676
26778
|
urlFound = true;
|
|
@@ -26690,7 +26792,8 @@ var init_expose = __esm({
|
|
|
26690
26792
|
this.cloudflaredProcess.on("close", (code) => {
|
|
26691
26793
|
if (!urlFound) {
|
|
26692
26794
|
clearTimeout(timeout);
|
|
26693
|
-
|
|
26795
|
+
const hint = stderrOutput.trim().split("\n").slice(-3).join(" | ");
|
|
26796
|
+
reject(new Error(`Cloudflared exited with code ${code}. ${hint ? "Output: " + hint : ""}`));
|
|
26694
26797
|
}
|
|
26695
26798
|
if (this._stats.status === "active") {
|
|
26696
26799
|
this.options.onInfo?.("Cloudflared tunnel died \u2014 restarting...");
|
|
@@ -26769,7 +26872,11 @@ ${this.formatConnectionInfo()}`);
|
|
|
26769
26872
|
});
|
|
26770
26873
|
}
|
|
26771
26874
|
emitStats() {
|
|
26772
|
-
this.emit("stats", {
|
|
26875
|
+
this.emit("stats", {
|
|
26876
|
+
...this._stats,
|
|
26877
|
+
modelUsage: new Map(this._stats.modelUsage),
|
|
26878
|
+
users: new Map(this._stats.users)
|
|
26879
|
+
});
|
|
26773
26880
|
}
|
|
26774
26881
|
/** Format connection info for display */
|
|
26775
26882
|
formatConnectionInfo() {
|
|
@@ -26795,15 +26902,337 @@ ${this.formatConnectionInfo()}`);
|
|
|
26795
26902
|
formatStats() {
|
|
26796
26903
|
const s = this._stats;
|
|
26797
26904
|
const lines = [];
|
|
26905
|
+
const uptimeSec = Math.floor((Date.now() - s.startedAt) / 1e3);
|
|
26906
|
+
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`;
|
|
26798
26907
|
lines.push(` ${c2.bold("Expose Gateway Stats")}`);
|
|
26799
|
-
lines.push(` ${c2.cyan("Status".padEnd(
|
|
26800
|
-
lines.push(` ${c2.cyan("
|
|
26801
|
-
lines.push(` ${c2.cyan("
|
|
26802
|
-
lines.push(` ${c2.cyan("
|
|
26908
|
+
lines.push(` ${c2.cyan("Status".padEnd(18))} ${s.status === "active" ? c2.green("active") : s.status === "error" ? c2.red("error") : c2.yellow("standby")}`);
|
|
26909
|
+
lines.push(` ${c2.cyan("Uptime".padEnd(18))} ${uptimeStr}`);
|
|
26910
|
+
lines.push(` ${c2.cyan("Total requests".padEnd(18))} ${s.totalRequests}`);
|
|
26911
|
+
lines.push(` ${c2.cyan("Active conns".padEnd(18))} ${s.activeConnections}`);
|
|
26912
|
+
lines.push(` ${c2.cyan("Errors".padEnd(18))} ${s.errors}`);
|
|
26913
|
+
lines.push(` ${c2.cyan("Tokens in".padEnd(18))} ${fmtTokens(s.totalTokensIn)}`);
|
|
26914
|
+
lines.push(` ${c2.cyan("Tokens out".padEnd(18))} ${fmtTokens(s.totalTokensOut)}`);
|
|
26803
26915
|
if (s.modelUsage.size > 0) {
|
|
26804
|
-
lines.push(
|
|
26916
|
+
lines.push("");
|
|
26917
|
+
lines.push(` ${c2.bold("Models")}`);
|
|
26805
26918
|
for (const [model, count] of s.modelUsage) {
|
|
26806
|
-
|
|
26919
|
+
let mIn = 0, mOut = 0;
|
|
26920
|
+
for (const user of s.users.values()) {
|
|
26921
|
+
const mm = user.models.get(model);
|
|
26922
|
+
if (mm) {
|
|
26923
|
+
mIn += mm.tokensIn;
|
|
26924
|
+
mOut += mm.tokensOut;
|
|
26925
|
+
}
|
|
26926
|
+
}
|
|
26927
|
+
lines.push(` ${c2.cyan(model.padEnd(30))} ${count} reqs ${c2.dim(`in:${fmtTokens(mIn)} out:${fmtTokens(mOut)}`)}`);
|
|
26928
|
+
}
|
|
26929
|
+
}
|
|
26930
|
+
if (s.users.size > 0) {
|
|
26931
|
+
lines.push("");
|
|
26932
|
+
lines.push(` ${c2.bold("Active Users")} (${s.users.size})`);
|
|
26933
|
+
for (const user of s.users.values()) {
|
|
26934
|
+
const ageSec = Math.floor((Date.now() - user.firstSeen) / 1e3);
|
|
26935
|
+
const ageStr = ageSec < 60 ? `${ageSec}s` : ageSec < 3600 ? `${Math.floor(ageSec / 60)}m` : `${Math.floor(ageSec / 3600)}h ${Math.floor(ageSec % 3600 / 60)}m`;
|
|
26936
|
+
const lastSec = Math.floor((Date.now() - user.lastSeen) / 1e3);
|
|
26937
|
+
const lastStr = lastSec < 5 ? "now" : lastSec < 60 ? `${lastSec}s ago` : `${Math.floor(lastSec / 60)}m ago`;
|
|
26938
|
+
const activeTag = user.activeRequests > 0 ? c2.green(` [${user.activeRequests} active]`) : "";
|
|
26939
|
+
lines.push(` ${c2.bold(user.ip)}${activeTag}`);
|
|
26940
|
+
lines.push(` ${c2.dim("Session:")} ${ageStr} ${c2.dim("Last seen:")} ${lastStr} ${c2.dim("Requests:")} ${user.requests}`);
|
|
26941
|
+
lines.push(` ${c2.dim("Tokens:")} in:${fmtTokens(user.tokensIn)} out:${fmtTokens(user.tokensOut)} ${c2.dim("Total:")} ${fmtTokens(user.tokensIn + user.tokensOut)}`);
|
|
26942
|
+
if (user.models.size > 0) {
|
|
26943
|
+
const modelParts = [];
|
|
26944
|
+
for (const [m, mm] of user.models) {
|
|
26945
|
+
modelParts.push(`${m} (${mm.requests} reqs, ${fmtTokens(mm.tokensIn + mm.tokensOut)} tokens)`);
|
|
26946
|
+
}
|
|
26947
|
+
lines.push(` ${c2.dim("Models:")} ${modelParts.join(", ")}`);
|
|
26948
|
+
}
|
|
26949
|
+
}
|
|
26950
|
+
}
|
|
26951
|
+
return lines.join("\n");
|
|
26952
|
+
}
|
|
26953
|
+
};
|
|
26954
|
+
ExposeP2PGateway = class extends EventEmitter3 {
|
|
26955
|
+
_nexusTool;
|
|
26956
|
+
// NexusTool instance
|
|
26957
|
+
_kind;
|
|
26958
|
+
_targetUrl;
|
|
26959
|
+
_peerId = null;
|
|
26960
|
+
_capabilities = [];
|
|
26961
|
+
_exposedModels = 0;
|
|
26962
|
+
_stateDir;
|
|
26963
|
+
_margin;
|
|
26964
|
+
_pollTimer = null;
|
|
26965
|
+
_stats = {
|
|
26966
|
+
status: "standby",
|
|
26967
|
+
totalRequests: 0,
|
|
26968
|
+
activeConnections: 0,
|
|
26969
|
+
errors: 0,
|
|
26970
|
+
totalTokensIn: 0,
|
|
26971
|
+
totalTokensOut: 0,
|
|
26972
|
+
startedAt: Date.now(),
|
|
26973
|
+
modelUsage: /* @__PURE__ */ new Map(),
|
|
26974
|
+
users: /* @__PURE__ */ new Map()
|
|
26975
|
+
};
|
|
26976
|
+
get peerId() {
|
|
26977
|
+
return this._peerId;
|
|
26978
|
+
}
|
|
26979
|
+
get stats() {
|
|
26980
|
+
return this._stats;
|
|
26981
|
+
}
|
|
26982
|
+
get kind() {
|
|
26983
|
+
return this._kind;
|
|
26984
|
+
}
|
|
26985
|
+
get isActive() {
|
|
26986
|
+
return this._stats.status === "active";
|
|
26987
|
+
}
|
|
26988
|
+
get transport() {
|
|
26989
|
+
return "libp2p";
|
|
26990
|
+
}
|
|
26991
|
+
_onInfo;
|
|
26992
|
+
_onError;
|
|
26993
|
+
constructor(options, nexusTool) {
|
|
26994
|
+
super();
|
|
26995
|
+
this._nexusTool = nexusTool;
|
|
26996
|
+
this._kind = options.kind;
|
|
26997
|
+
this._targetUrl = options.targetUrl ?? DEFAULT_TARGETS[options.kind];
|
|
26998
|
+
this._stateDir = options.stateDir ?? null;
|
|
26999
|
+
this._margin = options.margin ?? 0.5;
|
|
27000
|
+
this._onInfo = options.onInfo;
|
|
27001
|
+
this._onError = options.onError;
|
|
27002
|
+
}
|
|
27003
|
+
async start() {
|
|
27004
|
+
this._onInfo?.("Connecting to nexus P2P network...");
|
|
27005
|
+
const connectResult = await this._nexusTool.execute({
|
|
27006
|
+
action: "connect",
|
|
27007
|
+
agent_name: "open-agents-node",
|
|
27008
|
+
agent_type: "general"
|
|
27009
|
+
});
|
|
27010
|
+
if (!connectResult.success) {
|
|
27011
|
+
throw new Error(`Nexus daemon connect failed: ${connectResult.error}`);
|
|
27012
|
+
}
|
|
27013
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
27014
|
+
this._onInfo?.("Registering inference capabilities...");
|
|
27015
|
+
let exposeResult = await this._nexusTool.execute({
|
|
27016
|
+
action: "expose",
|
|
27017
|
+
ollama_url: this._targetUrl,
|
|
27018
|
+
margin: String(this._margin)
|
|
27019
|
+
});
|
|
27020
|
+
if (!exposeResult.success && exposeResult.error?.includes("not running")) {
|
|
27021
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
27022
|
+
exposeResult = await this._nexusTool.execute({
|
|
27023
|
+
action: "expose",
|
|
27024
|
+
ollama_url: this._targetUrl,
|
|
27025
|
+
margin: String(this._margin)
|
|
27026
|
+
});
|
|
27027
|
+
}
|
|
27028
|
+
if (!exposeResult.success) {
|
|
27029
|
+
throw new Error(`Expose failed: ${exposeResult.error}`);
|
|
27030
|
+
}
|
|
27031
|
+
const nexusDir = this._nexusTool.getNexusDir();
|
|
27032
|
+
const statusPath = join35(nexusDir, "status.json");
|
|
27033
|
+
for (let i = 0; i < 60; i++) {
|
|
27034
|
+
try {
|
|
27035
|
+
const raw = readFileSync18(statusPath, "utf8");
|
|
27036
|
+
if (raw.length > 10) {
|
|
27037
|
+
const status = JSON.parse(raw);
|
|
27038
|
+
if (status.connected && status.peerId) {
|
|
27039
|
+
this._peerId = status.peerId;
|
|
27040
|
+
this._capabilities = status.capabilities || [];
|
|
27041
|
+
this._exposedModels = status.exposedModels || 0;
|
|
27042
|
+
break;
|
|
27043
|
+
}
|
|
27044
|
+
}
|
|
27045
|
+
} catch {
|
|
27046
|
+
}
|
|
27047
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
27048
|
+
}
|
|
27049
|
+
this._stats.status = "active";
|
|
27050
|
+
this._stats.startedAt = Date.now();
|
|
27051
|
+
this.emitStats();
|
|
27052
|
+
this.startMeteringPoll(nexusDir);
|
|
27053
|
+
return this._peerId ?? "connected (peer ID pending)";
|
|
27054
|
+
}
|
|
27055
|
+
async stop() {
|
|
27056
|
+
this.stopMeteringPoll();
|
|
27057
|
+
this._stats.status = "standby";
|
|
27058
|
+
this._stats.activeConnections = 0;
|
|
27059
|
+
this.emitStats();
|
|
27060
|
+
}
|
|
27061
|
+
/** Poll the daemon's metering.jsonl and status.json for stats */
|
|
27062
|
+
startMeteringPoll(nexusDir) {
|
|
27063
|
+
this.stopMeteringPoll();
|
|
27064
|
+
let lastMeteringSize = 0;
|
|
27065
|
+
this._pollTimer = setInterval(() => {
|
|
27066
|
+
try {
|
|
27067
|
+
const statusPath = join35(nexusDir, "status.json");
|
|
27068
|
+
if (existsSync26(statusPath)) {
|
|
27069
|
+
const status = JSON.parse(readFileSync18(statusPath, "utf8"));
|
|
27070
|
+
if (status.peerId && !this._peerId) {
|
|
27071
|
+
this._peerId = status.peerId;
|
|
27072
|
+
}
|
|
27073
|
+
this._capabilities = status.capabilities || [];
|
|
27074
|
+
}
|
|
27075
|
+
} catch {
|
|
27076
|
+
}
|
|
27077
|
+
try {
|
|
27078
|
+
const invocDir = join35(nexusDir, "invocations");
|
|
27079
|
+
if (existsSync26(invocDir)) {
|
|
27080
|
+
const files = readdirSync7(invocDir);
|
|
27081
|
+
const invocCount = files.filter((f) => f.endsWith(".json")).length;
|
|
27082
|
+
if (invocCount > this._stats.totalRequests) {
|
|
27083
|
+
this._stats.totalRequests = invocCount;
|
|
27084
|
+
this.emitStats();
|
|
27085
|
+
}
|
|
27086
|
+
}
|
|
27087
|
+
} catch {
|
|
27088
|
+
}
|
|
27089
|
+
try {
|
|
27090
|
+
const meteringFile = join35(nexusDir, "metering.jsonl");
|
|
27091
|
+
if (existsSync26(meteringFile)) {
|
|
27092
|
+
const content = readFileSync18(meteringFile, "utf8");
|
|
27093
|
+
if (content.length > lastMeteringSize) {
|
|
27094
|
+
const newContent = content.slice(lastMeteringSize);
|
|
27095
|
+
lastMeteringSize = content.length;
|
|
27096
|
+
for (const line of newContent.split("\n")) {
|
|
27097
|
+
if (!line.trim())
|
|
27098
|
+
continue;
|
|
27099
|
+
try {
|
|
27100
|
+
const record = JSON.parse(line);
|
|
27101
|
+
if (record.tokens) {
|
|
27102
|
+
this._stats.totalTokensIn += record.tokens.input || 0;
|
|
27103
|
+
this._stats.totalTokensOut += record.tokens.output || 0;
|
|
27104
|
+
}
|
|
27105
|
+
const peerId = record.from || record.peerId || "unknown";
|
|
27106
|
+
const shortPeer = peerId.length > 16 ? peerId.slice(0, 16) + "..." : peerId;
|
|
27107
|
+
let user = this._stats.users.get(shortPeer);
|
|
27108
|
+
if (!user) {
|
|
27109
|
+
user = {
|
|
27110
|
+
ip: shortPeer,
|
|
27111
|
+
firstSeen: Date.now(),
|
|
27112
|
+
lastSeen: Date.now(),
|
|
27113
|
+
requests: 0,
|
|
27114
|
+
tokensIn: 0,
|
|
27115
|
+
tokensOut: 0,
|
|
27116
|
+
activeRequests: 0,
|
|
27117
|
+
models: /* @__PURE__ */ new Map()
|
|
27118
|
+
};
|
|
27119
|
+
this._stats.users.set(shortPeer, user);
|
|
27120
|
+
}
|
|
27121
|
+
user.requests++;
|
|
27122
|
+
user.lastSeen = Date.now();
|
|
27123
|
+
if (record.tokens) {
|
|
27124
|
+
user.tokensIn += record.tokens.input || 0;
|
|
27125
|
+
user.tokensOut += record.tokens.output || 0;
|
|
27126
|
+
}
|
|
27127
|
+
if (record.model || record.capability) {
|
|
27128
|
+
const modelName = record.model || record.capability.replace("inference:", "") || "unknown";
|
|
27129
|
+
this._stats.modelUsage.set(modelName, (this._stats.modelUsage.get(modelName) ?? 0) + 1);
|
|
27130
|
+
let mm = user.models.get(modelName);
|
|
27131
|
+
if (!mm) {
|
|
27132
|
+
mm = { requests: 0, tokensIn: 0, tokensOut: 0, lastUsed: Date.now() };
|
|
27133
|
+
user.models.set(modelName, mm);
|
|
27134
|
+
}
|
|
27135
|
+
mm.requests++;
|
|
27136
|
+
mm.lastUsed = Date.now();
|
|
27137
|
+
if (record.tokens) {
|
|
27138
|
+
mm.tokensIn += record.tokens.input || 0;
|
|
27139
|
+
mm.tokensOut += record.tokens.output || 0;
|
|
27140
|
+
}
|
|
27141
|
+
}
|
|
27142
|
+
} catch {
|
|
27143
|
+
}
|
|
27144
|
+
}
|
|
27145
|
+
this.emitStats();
|
|
27146
|
+
}
|
|
27147
|
+
}
|
|
27148
|
+
} catch {
|
|
27149
|
+
}
|
|
27150
|
+
}, 5e3);
|
|
27151
|
+
this._pollTimer.unref();
|
|
27152
|
+
}
|
|
27153
|
+
stopMeteringPoll() {
|
|
27154
|
+
if (this._pollTimer) {
|
|
27155
|
+
clearInterval(this._pollTimer);
|
|
27156
|
+
this._pollTimer = null;
|
|
27157
|
+
}
|
|
27158
|
+
}
|
|
27159
|
+
emitStats() {
|
|
27160
|
+
this.emit("stats", {
|
|
27161
|
+
...this._stats,
|
|
27162
|
+
modelUsage: new Map(this._stats.modelUsage),
|
|
27163
|
+
users: new Map(this._stats.users)
|
|
27164
|
+
});
|
|
27165
|
+
}
|
|
27166
|
+
/** Format connection info for display */
|
|
27167
|
+
formatConnectionInfo() {
|
|
27168
|
+
const lines = [];
|
|
27169
|
+
lines.push(` ${c2.green("\u25CF")} Expose gateway active ${c2.dim("(libp2p)")}`);
|
|
27170
|
+
lines.push(` ${c2.cyan("Backend".padEnd(12))} ${this._kind} (${this._targetUrl})`);
|
|
27171
|
+
lines.push(` ${c2.cyan("Transport".padEnd(12))} ${c2.bold("libp2p")} (DHT + mDNS + NATS relay)`);
|
|
27172
|
+
lines.push(` ${c2.cyan("Peer ID".padEnd(12))} ${c2.bold(this._peerId ?? "connecting...")}`);
|
|
27173
|
+
lines.push(` ${c2.cyan("Models".padEnd(12))} ${this._exposedModels || this._capabilities.filter((cap) => cap.startsWith("inference:")).length} exposed`);
|
|
27174
|
+
lines.push("");
|
|
27175
|
+
lines.push(` ${c2.dim("Remote peers discover your models via nexus network.")}`);
|
|
27176
|
+
lines.push(` ${c2.dim("Consumers use: /nexus invoke_capability inference:<model>")}`);
|
|
27177
|
+
const infCaps = this._capabilities.filter((cap) => cap.startsWith("inference:"));
|
|
27178
|
+
if (infCaps.length > 0) {
|
|
27179
|
+
lines.push("");
|
|
27180
|
+
lines.push(` ${c2.bold("Exposed capabilities:")}`);
|
|
27181
|
+
for (const cap of infCaps) {
|
|
27182
|
+
lines.push(` ${c2.cyan(cap)}`);
|
|
27183
|
+
}
|
|
27184
|
+
}
|
|
27185
|
+
return lines.join("\n");
|
|
27186
|
+
}
|
|
27187
|
+
/** Format usage stats for display */
|
|
27188
|
+
formatStats() {
|
|
27189
|
+
const s = this._stats;
|
|
27190
|
+
const lines = [];
|
|
27191
|
+
const uptimeSec = Math.floor((Date.now() - s.startedAt) / 1e3);
|
|
27192
|
+
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`;
|
|
27193
|
+
lines.push(` ${c2.bold("Expose Gateway Stats")} ${c2.dim("(libp2p)")}`);
|
|
27194
|
+
lines.push(` ${c2.cyan("Status".padEnd(18))} ${s.status === "active" ? c2.green("active") : s.status === "error" ? c2.red("error") : c2.yellow("standby")}`);
|
|
27195
|
+
lines.push(` ${c2.cyan("Transport".padEnd(18))} libp2p`);
|
|
27196
|
+
lines.push(` ${c2.cyan("Peer ID".padEnd(18))} ${this._peerId ?? "n/a"}`);
|
|
27197
|
+
lines.push(` ${c2.cyan("Uptime".padEnd(18))} ${uptimeStr}`);
|
|
27198
|
+
lines.push(` ${c2.cyan("Total requests".padEnd(18))} ${s.totalRequests}`);
|
|
27199
|
+
lines.push(` ${c2.cyan("Active conns".padEnd(18))} ${s.activeConnections}`);
|
|
27200
|
+
lines.push(` ${c2.cyan("Errors".padEnd(18))} ${s.errors}`);
|
|
27201
|
+
lines.push(` ${c2.cyan("Tokens in".padEnd(18))} ${fmtTokens(s.totalTokensIn)}`);
|
|
27202
|
+
lines.push(` ${c2.cyan("Tokens out".padEnd(18))} ${fmtTokens(s.totalTokensOut)}`);
|
|
27203
|
+
if (s.modelUsage.size > 0) {
|
|
27204
|
+
lines.push("");
|
|
27205
|
+
lines.push(` ${c2.bold("Models")}`);
|
|
27206
|
+
for (const [model, count] of s.modelUsage) {
|
|
27207
|
+
let mIn = 0, mOut = 0;
|
|
27208
|
+
for (const user of s.users.values()) {
|
|
27209
|
+
const mm = user.models.get(model);
|
|
27210
|
+
if (mm) {
|
|
27211
|
+
mIn += mm.tokensIn;
|
|
27212
|
+
mOut += mm.tokensOut;
|
|
27213
|
+
}
|
|
27214
|
+
}
|
|
27215
|
+
lines.push(` ${c2.cyan(model.padEnd(30))} ${count} reqs ${c2.dim(`in:${fmtTokens(mIn)} out:${fmtTokens(mOut)}`)}`);
|
|
27216
|
+
}
|
|
27217
|
+
}
|
|
27218
|
+
if (s.users.size > 0) {
|
|
27219
|
+
lines.push("");
|
|
27220
|
+
lines.push(` ${c2.bold("Active Peers")} (${s.users.size})`);
|
|
27221
|
+
for (const user of s.users.values()) {
|
|
27222
|
+
const ageSec = Math.floor((Date.now() - user.firstSeen) / 1e3);
|
|
27223
|
+
const ageStr = ageSec < 60 ? `${ageSec}s` : ageSec < 3600 ? `${Math.floor(ageSec / 60)}m` : `${Math.floor(ageSec / 3600)}h ${Math.floor(ageSec % 3600 / 60)}m`;
|
|
27224
|
+
const lastSec = Math.floor((Date.now() - user.lastSeen) / 1e3);
|
|
27225
|
+
const lastStr = lastSec < 5 ? "now" : lastSec < 60 ? `${lastSec}s ago` : `${Math.floor(lastSec / 60)}m ago`;
|
|
27226
|
+
lines.push(` ${c2.bold(user.ip)}`);
|
|
27227
|
+
lines.push(` ${c2.dim("Session:")} ${ageStr} ${c2.dim("Last seen:")} ${lastStr} ${c2.dim("Requests:")} ${user.requests}`);
|
|
27228
|
+
lines.push(` ${c2.dim("Tokens:")} in:${fmtTokens(user.tokensIn)} out:${fmtTokens(user.tokensOut)}`);
|
|
27229
|
+
if (user.models.size > 0) {
|
|
27230
|
+
const modelParts = [];
|
|
27231
|
+
for (const [m, mm] of user.models) {
|
|
27232
|
+
modelParts.push(`${m} (${mm.requests} reqs, ${fmtTokens(mm.tokensIn + mm.tokensOut)} tokens)`);
|
|
27233
|
+
}
|
|
27234
|
+
lines.push(` ${c2.dim("Models:")} ${modelParts.join(", ")}`);
|
|
27235
|
+
}
|
|
26807
27236
|
}
|
|
26808
27237
|
}
|
|
26809
27238
|
return lines.join("\n");
|
|
@@ -28422,7 +28851,7 @@ var init_dist6 = __esm({
|
|
|
28422
28851
|
});
|
|
28423
28852
|
|
|
28424
28853
|
// packages/cli/dist/tui/oa-directory.js
|
|
28425
|
-
import { existsSync as existsSync29, mkdirSync as mkdirSync10, readFileSync as readFileSync21, writeFileSync as writeFileSync10, readdirSync as
|
|
28854
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync10, readFileSync as readFileSync21, writeFileSync as writeFileSync10, readdirSync as readdirSync8, statSync as statSync9, unlinkSync as unlinkSync4 } from "node:fs";
|
|
28426
28855
|
import { join as join39, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
|
|
28427
28856
|
import { homedir as homedir9 } from "node:os";
|
|
28428
28857
|
function initOaDirectory(repoRoot) {
|
|
@@ -28614,7 +29043,7 @@ function loadRecentSessions(repoRoot, limit = 5) {
|
|
|
28614
29043
|
if (!existsSync29(historyDir))
|
|
28615
29044
|
return [];
|
|
28616
29045
|
try {
|
|
28617
|
-
const files =
|
|
29046
|
+
const files = readdirSync8(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
|
|
28618
29047
|
const stat5 = statSync9(join39(historyDir, f));
|
|
28619
29048
|
return { file: f, mtime: stat5.mtimeMs };
|
|
28620
29049
|
}).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
|
|
@@ -28767,7 +29196,7 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
28767
29196
|
return "";
|
|
28768
29197
|
let result = "";
|
|
28769
29198
|
try {
|
|
28770
|
-
const entries =
|
|
29199
|
+
const entries = readdirSync8(root, { withFileTypes: true }).filter((e) => !e.name.startsWith(".") || e.name === ".github").filter((e) => !SKIP_DIRS.has(e.name)).sort((a, b) => {
|
|
28771
29200
|
if (a.isDirectory() && !b.isDirectory())
|
|
28772
29201
|
return -1;
|
|
28773
29202
|
if (!a.isDirectory() && b.isDirectory())
|
|
@@ -28782,7 +29211,7 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
28782
29211
|
if (entry.isDirectory()) {
|
|
28783
29212
|
let fileCount = 0;
|
|
28784
29213
|
try {
|
|
28785
|
-
fileCount =
|
|
29214
|
+
fileCount = readdirSync8(join39(root, entry.name)).filter((f) => !f.startsWith(".")).length;
|
|
28786
29215
|
} catch {
|
|
28787
29216
|
}
|
|
28788
29217
|
result += `${prefix}${connector}${entry.name}/ (${fileCount})
|
|
@@ -31398,15 +31827,17 @@ async function handleSlashCommand(input, ctx) {
|
|
|
31398
31827
|
if (info && ctx.isExposeActive?.()) {
|
|
31399
31828
|
process.stdout.write("\n" + info.stats + "\n\n");
|
|
31400
31829
|
} else {
|
|
31401
|
-
renderInfo("Usage: /expose <backend> [
|
|
31402
|
-
renderInfo(" /expose ollama Expose local Ollama (
|
|
31830
|
+
renderInfo("Usage: /expose <backend> [options]");
|
|
31831
|
+
renderInfo(" /expose ollama Expose local Ollama via libp2p (default)");
|
|
31832
|
+
renderInfo(" /expose ollama --tunnel Expose via cloudflared tunnel");
|
|
31833
|
+
renderInfo(" /expose ollama --libp2p Expose via libp2p (explicit)");
|
|
31403
31834
|
renderInfo(" /expose vllm Expose local vLLM (8000)");
|
|
31404
31835
|
renderInfo(" /expose llvm Expose local LLVM (8080)");
|
|
31405
31836
|
renderInfo(" /expose host:port Expose custom address");
|
|
31406
31837
|
renderInfo(" /expose stop Stop the gateway");
|
|
31407
31838
|
renderInfo(" /expose status Show usage stats");
|
|
31408
|
-
renderInfo(" --key <key> Use specific auth key");
|
|
31409
|
-
renderInfo(" --key Auto-generate auth key");
|
|
31839
|
+
renderInfo(" --key <key> Use specific auth key (tunnel mode)");
|
|
31840
|
+
renderInfo(" --key Auto-generate auth key (tunnel mode)");
|
|
31410
31841
|
}
|
|
31411
31842
|
return "handled";
|
|
31412
31843
|
}
|
|
@@ -31416,12 +31847,18 @@ async function handleSlashCommand(input, ctx) {
|
|
|
31416
31847
|
const exposeParts = arg.split(/\s+/);
|
|
31417
31848
|
const kindOrUrl = exposeParts[0];
|
|
31418
31849
|
let exposeAuthKey;
|
|
31850
|
+
let exposeTransport;
|
|
31419
31851
|
const keyIdx = exposeParts.indexOf("--key");
|
|
31420
31852
|
if (keyIdx !== -1) {
|
|
31421
31853
|
exposeAuthKey = exposeParts[keyIdx + 1] ?? "";
|
|
31422
31854
|
}
|
|
31855
|
+
if (exposeParts.includes("--tunnel")) {
|
|
31856
|
+
exposeTransport = "tunnel";
|
|
31857
|
+
} else if (exposeParts.includes("--libp2p")) {
|
|
31858
|
+
exposeTransport = "libp2p";
|
|
31859
|
+
}
|
|
31423
31860
|
try {
|
|
31424
|
-
const tunnelUrl = await ctx.exposeStart(kindOrUrl, exposeAuthKey);
|
|
31861
|
+
const tunnelUrl = await ctx.exposeStart(kindOrUrl, exposeAuthKey, exposeTransport);
|
|
31425
31862
|
if (tunnelUrl) {
|
|
31426
31863
|
const info = ctx.getExposeInfo?.();
|
|
31427
31864
|
if (info) {
|
|
@@ -32619,7 +33056,7 @@ var init_commands = __esm({
|
|
|
32619
33056
|
});
|
|
32620
33057
|
|
|
32621
33058
|
// packages/cli/dist/tui/project-context.js
|
|
32622
|
-
import { existsSync as existsSync31, readFileSync as readFileSync22, readdirSync as
|
|
33059
|
+
import { existsSync as existsSync31, readFileSync as readFileSync22, readdirSync as readdirSync9 } from "node:fs";
|
|
32623
33060
|
import { join as join41, basename as basename10 } from "node:path";
|
|
32624
33061
|
import { execSync as execSync26 } from "node:child_process";
|
|
32625
33062
|
import { homedir as homedir11, platform as platform2, release } from "node:os";
|
|
@@ -32720,7 +33157,7 @@ function loadMemoryDir(memDir, scope) {
|
|
|
32720
33157
|
return "";
|
|
32721
33158
|
const lines = [];
|
|
32722
33159
|
try {
|
|
32723
|
-
const files =
|
|
33160
|
+
const files = readdirSync9(memDir).filter((f) => f.endsWith(".json"));
|
|
32724
33161
|
for (const file of files.slice(0, 10)) {
|
|
32725
33162
|
try {
|
|
32726
33163
|
const raw = readFileSync22(join41(memDir, file), "utf-8");
|
|
@@ -33746,7 +34183,7 @@ var init_carousel = __esm({
|
|
|
33746
34183
|
});
|
|
33747
34184
|
|
|
33748
34185
|
// packages/cli/dist/tui/carousel-descriptors.js
|
|
33749
|
-
import { existsSync as existsSync32, readFileSync as readFileSync23, writeFileSync as writeFileSync12, mkdirSync as mkdirSync12, readdirSync as
|
|
34186
|
+
import { existsSync as existsSync32, readFileSync as readFileSync23, writeFileSync as writeFileSync12, mkdirSync as mkdirSync12, readdirSync as readdirSync10 } from "node:fs";
|
|
33750
34187
|
import { join as join42, basename as basename11 } from "node:path";
|
|
33751
34188
|
function loadToolProfile(repoRoot) {
|
|
33752
34189
|
const filePath = join42(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
|
|
@@ -33959,7 +34396,7 @@ function extractFromMemory(repoRoot, tags) {
|
|
|
33959
34396
|
try {
|
|
33960
34397
|
if (!existsSync32(memoryDir))
|
|
33961
34398
|
return;
|
|
33962
|
-
const files =
|
|
34399
|
+
const files = readdirSync10(memoryDir).filter((f) => f.endsWith(".json"));
|
|
33963
34400
|
for (const file of files) {
|
|
33964
34401
|
const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
|
|
33965
34402
|
tags.push(topic);
|
|
@@ -36520,7 +36957,7 @@ var init_promptLoader3 = __esm({
|
|
|
36520
36957
|
});
|
|
36521
36958
|
|
|
36522
36959
|
// packages/cli/dist/tui/dream-engine.js
|
|
36523
|
-
import { mkdirSync as mkdirSync15, writeFileSync as writeFileSync14, readFileSync as readFileSync26, existsSync as existsSync35, cpSync, rmSync, readdirSync as
|
|
36960
|
+
import { mkdirSync as mkdirSync15, writeFileSync as writeFileSync14, readFileSync as readFileSync26, existsSync as existsSync35, cpSync, rmSync, readdirSync as readdirSync11 } from "node:fs";
|
|
36524
36961
|
import { join as join46, basename as basename12 } from "node:path";
|
|
36525
36962
|
import { execSync as execSync28 } from "node:child_process";
|
|
36526
36963
|
function loadAutoresearchMemory(repoRoot) {
|
|
@@ -37726,7 +38163,7 @@ Each proposal includes implementation entrypoints and estimated effort.
|
|
|
37726
38163
|
/** Update the master proposal index */
|
|
37727
38164
|
updateProposalIndex() {
|
|
37728
38165
|
try {
|
|
37729
|
-
const files =
|
|
38166
|
+
const files = readdirSync11(this.dreamsDir).filter((f) => f.endsWith(".md") && f !== "PROPOSAL-INDEX.md" && f !== "dream-state.json").sort();
|
|
37730
38167
|
const index = `# Dream Proposals Index
|
|
37731
38168
|
|
|
37732
38169
|
**Last updated**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
@@ -38128,7 +38565,7 @@ var init_bless_engine = __esm({
|
|
|
38128
38565
|
});
|
|
38129
38566
|
|
|
38130
38567
|
// packages/cli/dist/tui/dmn-engine.js
|
|
38131
|
-
import { existsSync as existsSync36, readFileSync as readFileSync27, writeFileSync as writeFileSync15, mkdirSync as mkdirSync16, readdirSync as
|
|
38568
|
+
import { existsSync as existsSync36, readFileSync as readFileSync27, writeFileSync as writeFileSync15, mkdirSync as mkdirSync16, readdirSync as readdirSync12, unlinkSync as unlinkSync6 } from "node:fs";
|
|
38132
38569
|
import { join as join47, basename as basename13 } from "node:path";
|
|
38133
38570
|
function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
|
|
38134
38571
|
const competenceReport = competence.length > 0 ? competence.map((c3) => {
|
|
@@ -38840,7 +39277,7 @@ OUTPUT: Call task_complete with JSON:
|
|
|
38840
39277
|
if (!existsSync36(dir))
|
|
38841
39278
|
continue;
|
|
38842
39279
|
try {
|
|
38843
|
-
const files =
|
|
39280
|
+
const files = readdirSync12(dir).filter((f) => f.endsWith(".json"));
|
|
38844
39281
|
for (const f of files) {
|
|
38845
39282
|
const topic = basename13(f, ".json");
|
|
38846
39283
|
if (!topics.includes(topic))
|
|
@@ -38871,7 +39308,7 @@ OUTPUT: Call task_complete with JSON:
|
|
|
38871
39308
|
try {
|
|
38872
39309
|
const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
|
|
38873
39310
|
writeFileSync15(join47(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
|
|
38874
|
-
const files =
|
|
39311
|
+
const files = readdirSync12(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
|
|
38875
39312
|
if (files.length > 50) {
|
|
38876
39313
|
for (const old of files.slice(0, files.length - 50)) {
|
|
38877
39314
|
try {
|
|
@@ -38888,7 +39325,7 @@ OUTPUT: Call task_complete with JSON:
|
|
|
38888
39325
|
});
|
|
38889
39326
|
|
|
38890
39327
|
// packages/cli/dist/tui/snr-engine.js
|
|
38891
|
-
import { existsSync as existsSync37, readdirSync as
|
|
39328
|
+
import { existsSync as existsSync37, readdirSync as readdirSync13, readFileSync as readFileSync28 } from "node:fs";
|
|
38892
39329
|
import { join as join48, basename as basename14 } from "node:path";
|
|
38893
39330
|
function computeDPrime(signalScores, noiseScores) {
|
|
38894
39331
|
if (signalScores.length === 0 || noiseScores.length === 0)
|
|
@@ -39136,7 +39573,7 @@ Call task_complete with the JSON array when done.`, onEvent)
|
|
|
39136
39573
|
if (!existsSync37(dir))
|
|
39137
39574
|
continue;
|
|
39138
39575
|
try {
|
|
39139
|
-
const files =
|
|
39576
|
+
const files = readdirSync13(dir).filter((f) => f.endsWith(".json"));
|
|
39140
39577
|
for (const f of files) {
|
|
39141
39578
|
const topic = basename14(f, ".json");
|
|
39142
39579
|
if (topics.length > 0 && !topics.includes(topic))
|
|
@@ -39709,7 +40146,7 @@ var init_tool_policy = __esm({
|
|
|
39709
40146
|
});
|
|
39710
40147
|
|
|
39711
40148
|
// packages/cli/dist/tui/telegram-bridge.js
|
|
39712
|
-
import { mkdirSync as mkdirSync17, existsSync as existsSync38, unlinkSync as unlinkSync7, readdirSync as
|
|
40149
|
+
import { mkdirSync as mkdirSync17, existsSync as existsSync38, unlinkSync as unlinkSync7, readdirSync as readdirSync14, statSync as statSync10 } from "node:fs";
|
|
39713
40150
|
import { join as join49, resolve as resolve27 } from "node:path";
|
|
39714
40151
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
39715
40152
|
function convertMarkdownToTelegramHTML(md) {
|
|
@@ -42311,7 +42748,7 @@ import { cwd } from "node:process";
|
|
|
42311
42748
|
import { resolve as resolve28, join as join50, dirname as dirname17, extname as extname9 } from "node:path";
|
|
42312
42749
|
import { createRequire as createRequire2 } from "node:module";
|
|
42313
42750
|
import { fileURLToPath as fileURLToPath12 } from "node:url";
|
|
42314
|
-
import { readFileSync as readFileSync29, writeFileSync as writeFileSync16, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as
|
|
42751
|
+
import { readFileSync as readFileSync29, writeFileSync as writeFileSync16, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as readdirSync15, mkdirSync as mkdirSync18 } from "node:fs";
|
|
42315
42752
|
import { existsSync as existsSync39 } from "node:fs";
|
|
42316
42753
|
import { homedir as homedir13 } from "node:os";
|
|
42317
42754
|
function formatTimeAgo(date) {
|
|
@@ -42550,7 +42987,7 @@ function gatherMemorySnippets(root) {
|
|
|
42550
42987
|
if (!existsSync39(dir))
|
|
42551
42988
|
continue;
|
|
42552
42989
|
try {
|
|
42553
|
-
for (const f of
|
|
42990
|
+
for (const f of readdirSync15(dir).filter((f2) => f2.endsWith(".json"))) {
|
|
42554
42991
|
const data = JSON.parse(readFileSync29(join50(dir, f), "utf-8"));
|
|
42555
42992
|
for (const val of Object.values(data)) {
|
|
42556
42993
|
const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
@@ -44277,7 +44714,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
44277
44714
|
getCallUrl() {
|
|
44278
44715
|
return voiceSession?.tunnelUrl ?? null;
|
|
44279
44716
|
},
|
|
44280
|
-
async exposeStart(kindOrUrl, authKey) {
|
|
44717
|
+
async exposeStart(kindOrUrl, authKey, transport) {
|
|
44281
44718
|
const knownKinds = ["ollama", "vllm", "llvm"];
|
|
44282
44719
|
let kind;
|
|
44283
44720
|
let targetUrl;
|
|
@@ -44287,8 +44724,42 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
44287
44724
|
kind = "custom";
|
|
44288
44725
|
targetUrl = kindOrUrl.includes("://") ? kindOrUrl : `http://${kindOrUrl}`;
|
|
44289
44726
|
}
|
|
44290
|
-
|
|
44291
|
-
|
|
44727
|
+
const effectiveTransport = transport ?? "libp2p";
|
|
44728
|
+
if (effectiveTransport === "libp2p") {
|
|
44729
|
+
const nexusTool = new NexusTool(repoRoot);
|
|
44730
|
+
const p2pGateway = new ExposeP2PGateway({
|
|
44731
|
+
kind,
|
|
44732
|
+
targetUrl,
|
|
44733
|
+
stateDir: join50(repoRoot, ".oa")
|
|
44734
|
+
}, nexusTool);
|
|
44735
|
+
p2pGateway.on("stats", (stats) => {
|
|
44736
|
+
statusBar.setExposeStatus({
|
|
44737
|
+
status: stats.status,
|
|
44738
|
+
totalRequests: stats.totalRequests,
|
|
44739
|
+
activeConnections: stats.activeConnections,
|
|
44740
|
+
modelUsage: stats.modelUsage
|
|
44741
|
+
});
|
|
44742
|
+
});
|
|
44743
|
+
try {
|
|
44744
|
+
const peerId = await p2pGateway.start();
|
|
44745
|
+
exposeGateway = p2pGateway;
|
|
44746
|
+
writeContent(() => {
|
|
44747
|
+
process.stdout.write("\n" + p2pGateway.formatConnectionInfo() + "\n\n");
|
|
44748
|
+
});
|
|
44749
|
+
return peerId;
|
|
44750
|
+
} catch (err) {
|
|
44751
|
+
if (!transport) {
|
|
44752
|
+
writeContent(() => {
|
|
44753
|
+
renderWarning(`libp2p expose failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
44754
|
+
renderInfo("Falling back to cloudflared tunnel...");
|
|
44755
|
+
});
|
|
44756
|
+
} else {
|
|
44757
|
+
throw err;
|
|
44758
|
+
}
|
|
44759
|
+
}
|
|
44760
|
+
}
|
|
44761
|
+
const tunnelGateway = new ExposeGateway({ kind, targetUrl, authKey, stateDir: join50(repoRoot, ".oa") });
|
|
44762
|
+
tunnelGateway.on("stats", (stats) => {
|
|
44292
44763
|
statusBar.setExposeStatus({
|
|
44293
44764
|
status: stats.status,
|
|
44294
44765
|
totalRequests: stats.totalRequests,
|
|
@@ -44297,9 +44768,10 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
44297
44768
|
});
|
|
44298
44769
|
});
|
|
44299
44770
|
try {
|
|
44300
|
-
const url = await
|
|
44771
|
+
const url = await tunnelGateway.start();
|
|
44772
|
+
exposeGateway = tunnelGateway;
|
|
44301
44773
|
writeContent(() => {
|
|
44302
|
-
process.stdout.write("\n" +
|
|
44774
|
+
process.stdout.write("\n" + tunnelGateway.formatConnectionInfo() + "\n\n");
|
|
44303
44775
|
});
|
|
44304
44776
|
return url;
|
|
44305
44777
|
} catch (err) {
|
|
@@ -44320,6 +44792,13 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
44320
44792
|
getExposeInfo() {
|
|
44321
44793
|
if (!exposeGateway)
|
|
44322
44794
|
return null;
|
|
44795
|
+
if (exposeGateway instanceof ExposeP2PGateway) {
|
|
44796
|
+
return {
|
|
44797
|
+
tunnelUrl: exposeGateway.peerId,
|
|
44798
|
+
authKey: "",
|
|
44799
|
+
stats: exposeGateway.formatStats()
|
|
44800
|
+
};
|
|
44801
|
+
}
|
|
44323
44802
|
return {
|
|
44324
44803
|
tunnelUrl: exposeGateway.tunnelUrl,
|
|
44325
44804
|
authKey: exposeGateway.authKey,
|
package/package.json
CHANGED