open-agents-ai 0.184.30 → 0.184.31
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 +1267 -337
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -672,20 +672,20 @@ var init_VllmBackend = __esm({
|
|
|
672
672
|
// -------------------------------------------------------------------------
|
|
673
673
|
// LLMBackend — complete
|
|
674
674
|
// -------------------------------------------------------------------------
|
|
675
|
-
async complete(
|
|
676
|
-
const messages =
|
|
675
|
+
async complete(request2) {
|
|
676
|
+
const messages = request2.messages.map(agentMessageToChatMessage);
|
|
677
677
|
const body = {
|
|
678
678
|
model: this.model,
|
|
679
679
|
messages,
|
|
680
|
-
temperature:
|
|
681
|
-
max_tokens:
|
|
680
|
+
temperature: request2.temperature ?? 0,
|
|
681
|
+
max_tokens: request2.maxTokens ?? 4096
|
|
682
682
|
};
|
|
683
|
-
if (
|
|
684
|
-
body.tools =
|
|
683
|
+
if (request2.tools && request2.tools.length > 0) {
|
|
684
|
+
body.tools = request2.tools;
|
|
685
685
|
body.tool_choice = "auto";
|
|
686
686
|
}
|
|
687
|
-
if (
|
|
688
|
-
body.response_format =
|
|
687
|
+
if (request2.responseFormat) {
|
|
688
|
+
body.response_format = request2.responseFormat;
|
|
689
689
|
}
|
|
690
690
|
const start = Date.now();
|
|
691
691
|
const rawResponse = await this.postWithRetry("/v1/chat/completions", body);
|
|
@@ -822,24 +822,24 @@ var init_OllamaBackend = __esm({
|
|
|
822
822
|
// -------------------------------------------------------------------------
|
|
823
823
|
// LLMBackend — complete
|
|
824
824
|
// -------------------------------------------------------------------------
|
|
825
|
-
async complete(
|
|
826
|
-
const messages =
|
|
825
|
+
async complete(request2) {
|
|
826
|
+
const messages = request2.messages.map(agentMessageToChatMessage2);
|
|
827
827
|
const body = {
|
|
828
828
|
model: this.model,
|
|
829
829
|
messages,
|
|
830
|
-
temperature:
|
|
831
|
-
max_tokens:
|
|
830
|
+
temperature: request2.temperature ?? 0,
|
|
831
|
+
max_tokens: request2.maxTokens ?? 4096,
|
|
832
832
|
// Disable Qwen thinking mode by default so tokens go to content,
|
|
833
833
|
// not reasoning. The model still produces good output without it
|
|
834
834
|
// and coding agents need structured JSON in the content field.
|
|
835
835
|
think: false
|
|
836
836
|
};
|
|
837
|
-
if (
|
|
838
|
-
body.tools =
|
|
837
|
+
if (request2.tools && request2.tools.length > 0) {
|
|
838
|
+
body.tools = request2.tools;
|
|
839
839
|
body.tool_choice = "auto";
|
|
840
840
|
}
|
|
841
|
-
if (
|
|
842
|
-
body.response_format =
|
|
841
|
+
if (request2.responseFormat) {
|
|
842
|
+
body.response_format = request2.responseFormat;
|
|
843
843
|
}
|
|
844
844
|
const start = Date.now();
|
|
845
845
|
const rawResponse = await this.postWithRetry("/v1/chat/completions", body);
|
|
@@ -1003,19 +1003,19 @@ var init_FakeBackend = __esm({
|
|
|
1003
1003
|
this._healthCheckCount++;
|
|
1004
1004
|
return this.options.healthy;
|
|
1005
1005
|
}
|
|
1006
|
-
async complete(
|
|
1006
|
+
async complete(request2) {
|
|
1007
1007
|
this._completeCount++;
|
|
1008
1008
|
if (this.options.shouldThrow) {
|
|
1009
1009
|
throw new Error(this.options.errorMessage);
|
|
1010
1010
|
}
|
|
1011
|
-
const lastMessage =
|
|
1011
|
+
const lastMessage = request2.messages[request2.messages.length - 1];
|
|
1012
1012
|
const inputKey = lastMessage ? `${lastMessage.role}:${lastMessage.content}` : "empty";
|
|
1013
1013
|
const hash = fnv1a32(inputKey);
|
|
1014
1014
|
const deterministicContent = `fake-response-${hash.toString(16).padStart(8, "0")}`;
|
|
1015
1015
|
const usage = {
|
|
1016
|
-
prompt_tokens:
|
|
1016
|
+
prompt_tokens: request2.messages.length * 10,
|
|
1017
1017
|
completion_tokens: 20,
|
|
1018
|
-
total_tokens:
|
|
1018
|
+
total_tokens: request2.messages.length * 10 + 20
|
|
1019
1019
|
};
|
|
1020
1020
|
if (this.options.toolCallResponses.length > 0) {
|
|
1021
1021
|
return {
|
|
@@ -1374,7 +1374,7 @@ ${stdinInput ?? ""}`);
|
|
|
1374
1374
|
}
|
|
1375
1375
|
runCommand(command, timeout, stdinInput) {
|
|
1376
1376
|
const start = performance.now();
|
|
1377
|
-
return new Promise((
|
|
1377
|
+
return new Promise((resolve36) => {
|
|
1378
1378
|
const child = spawn("bash", ["-c", command], {
|
|
1379
1379
|
cwd: this.workingDir,
|
|
1380
1380
|
env: {
|
|
@@ -1405,7 +1405,7 @@ ${stdinInput ?? ""}`);
|
|
|
1405
1405
|
clearTimeout(timer);
|
|
1406
1406
|
if (exitFlushTimer)
|
|
1407
1407
|
clearTimeout(exitFlushTimer);
|
|
1408
|
-
|
|
1408
|
+
resolve36(result);
|
|
1409
1409
|
};
|
|
1410
1410
|
const timer = setTimeout(() => {
|
|
1411
1411
|
killed = true;
|
|
@@ -3161,7 +3161,7 @@ ${JSON.stringify(extracted, null, 2)}`);
|
|
|
3161
3161
|
return null;
|
|
3162
3162
|
}
|
|
3163
3163
|
runProcess(cmd, args, timeoutMs) {
|
|
3164
|
-
return new Promise((
|
|
3164
|
+
return new Promise((resolve36, reject) => {
|
|
3165
3165
|
const proc = execFile3(cmd, args, {
|
|
3166
3166
|
timeout: timeoutMs,
|
|
3167
3167
|
maxBuffer: 10 * 1024 * 1024,
|
|
@@ -3171,7 +3171,7 @@ ${JSON.stringify(extracted, null, 2)}`);
|
|
|
3171
3171
|
reject(new Error(`Process timeout after ${timeoutMs}ms`));
|
|
3172
3172
|
return;
|
|
3173
3173
|
}
|
|
3174
|
-
|
|
3174
|
+
resolve36({
|
|
3175
3175
|
stdout: String(stdout),
|
|
3176
3176
|
stderr: String(stderr),
|
|
3177
3177
|
exitCode: error ? error.code ?? 1 : 0
|
|
@@ -10798,7 +10798,7 @@ var init_custom_tool = __esm({
|
|
|
10798
10798
|
}
|
|
10799
10799
|
/** Execute a single shell command and return output */
|
|
10800
10800
|
runCommand(command) {
|
|
10801
|
-
return new Promise((
|
|
10801
|
+
return new Promise((resolve36) => {
|
|
10802
10802
|
const child = spawn4("bash", ["-c", command], {
|
|
10803
10803
|
cwd: this.workingDir,
|
|
10804
10804
|
env: { ...process.env, CI: "true", NO_COLOR: "1" },
|
|
@@ -10823,11 +10823,11 @@ var init_custom_tool = __esm({
|
|
|
10823
10823
|
child.kill("SIGTERM");
|
|
10824
10824
|
} catch {
|
|
10825
10825
|
}
|
|
10826
|
-
|
|
10826
|
+
resolve36({ success: false, output: stdout, error: "Command timed out after 60s" });
|
|
10827
10827
|
}, 6e4);
|
|
10828
10828
|
child.on("close", (code) => {
|
|
10829
10829
|
clearTimeout(timer);
|
|
10830
|
-
|
|
10830
|
+
resolve36({
|
|
10831
10831
|
success: code === 0,
|
|
10832
10832
|
output: stdout + (stderr && code === 0 ? `
|
|
10833
10833
|
STDERR:
|
|
@@ -10837,7 +10837,7 @@ ${stderr}` : ""),
|
|
|
10837
10837
|
});
|
|
10838
10838
|
child.on("error", (err) => {
|
|
10839
10839
|
clearTimeout(timer);
|
|
10840
|
-
|
|
10840
|
+
resolve36({ success: false, output: stdout, error: err.message });
|
|
10841
10841
|
});
|
|
10842
10842
|
});
|
|
10843
10843
|
}
|
|
@@ -11711,13 +11711,13 @@ Validation: ${validation.pass ? "PASS" : "NEEDS IMPROVEMENT"} (${validation.over
|
|
|
11711
11711
|
// -------------------------------------------------------------------------
|
|
11712
11712
|
// Phase 1: Seed Analysis
|
|
11713
11713
|
// -------------------------------------------------------------------------
|
|
11714
|
-
async analyzeSeed(
|
|
11714
|
+
async analyzeSeed(request2) {
|
|
11715
11715
|
const prompt = loadBuilderPrompt("seed-analysis.md", {
|
|
11716
|
-
skill_request:
|
|
11716
|
+
skill_request: request2
|
|
11717
11717
|
});
|
|
11718
11718
|
const response = await this.llmCall([
|
|
11719
11719
|
{ role: "system", content: prompt },
|
|
11720
|
-
{ role: "user", content: `Analyze this skill request: "${
|
|
11720
|
+
{ role: "user", content: `Analyze this skill request: "${request2}"` }
|
|
11721
11721
|
]);
|
|
11722
11722
|
const jsonStr = extractJSON(response);
|
|
11723
11723
|
const seed = JSON.parse(jsonStr);
|
|
@@ -11845,8 +11845,8 @@ async function loadTranscribeCli() {
|
|
|
11845
11845
|
}).trim();
|
|
11846
11846
|
const tcPath = join19(globalRoot, "transcribe-cli");
|
|
11847
11847
|
if (existsSync16(join19(tcPath, "dist", "index.js"))) {
|
|
11848
|
-
const { createRequire:
|
|
11849
|
-
const req =
|
|
11848
|
+
const { createRequire: createRequire5 } = await import("node:module");
|
|
11849
|
+
const req = createRequire5(import.meta.url);
|
|
11850
11850
|
_tcModule = req(join19(tcPath, "dist", "index.js"));
|
|
11851
11851
|
return _tcModule;
|
|
11852
11852
|
}
|
|
@@ -11855,12 +11855,12 @@ async function loadTranscribeCli() {
|
|
|
11855
11855
|
const nvmBase = join19(homedir7(), ".nvm", "versions", "node");
|
|
11856
11856
|
if (existsSync16(nvmBase)) {
|
|
11857
11857
|
try {
|
|
11858
|
-
const { readdirSync:
|
|
11859
|
-
for (const ver of
|
|
11858
|
+
const { readdirSync: readdirSync22 } = await import("node:fs");
|
|
11859
|
+
for (const ver of readdirSync22(nvmBase)) {
|
|
11860
11860
|
const tcPath = join19(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
|
|
11861
11861
|
if (existsSync16(join19(tcPath, "dist", "index.js"))) {
|
|
11862
|
-
const { createRequire:
|
|
11863
|
-
const req =
|
|
11862
|
+
const { createRequire: createRequire5 } = await import("node:module");
|
|
11863
|
+
const req = createRequire5(import.meta.url);
|
|
11864
11864
|
_tcModule = req(join19(tcPath, "dist", "index.js"));
|
|
11865
11865
|
return _tcModule;
|
|
11866
11866
|
}
|
|
@@ -12401,7 +12401,7 @@ import { writeFile as writeFile8, mkdtemp, rm, readdir as readdir3, stat } from
|
|
|
12401
12401
|
import { join as join20 } from "node:path";
|
|
12402
12402
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
12403
12403
|
function runProcess(cmd, args, options) {
|
|
12404
|
-
return new Promise((
|
|
12404
|
+
return new Promise((resolve36) => {
|
|
12405
12405
|
const proc = spawn6(cmd, args, {
|
|
12406
12406
|
cwd: options.cwd,
|
|
12407
12407
|
timeout: options.timeout,
|
|
@@ -12431,7 +12431,7 @@ function runProcess(cmd, args, options) {
|
|
|
12431
12431
|
}
|
|
12432
12432
|
});
|
|
12433
12433
|
proc.on("error", (err) => {
|
|
12434
|
-
|
|
12434
|
+
resolve36({
|
|
12435
12435
|
stdout,
|
|
12436
12436
|
stderr: stderr || err.message,
|
|
12437
12437
|
exitCode: 1,
|
|
@@ -12443,7 +12443,7 @@ function runProcess(cmd, args, options) {
|
|
|
12443
12443
|
if (signal === "SIGTERM" || signal === "SIGKILL") {
|
|
12444
12444
|
timedOut = true;
|
|
12445
12445
|
}
|
|
12446
|
-
|
|
12446
|
+
resolve36({
|
|
12447
12447
|
stdout,
|
|
12448
12448
|
stderr,
|
|
12449
12449
|
exitCode: code ?? (timedOut ? 124 : 1),
|
|
@@ -12926,7 +12926,7 @@ Justification: ${justification || "(none provided)"}`,
|
|
|
12926
12926
|
})();
|
|
12927
12927
|
const ipfsResult = await Promise.race([
|
|
12928
12928
|
ipfsPromise,
|
|
12929
|
-
new Promise((
|
|
12929
|
+
new Promise((resolve36) => setTimeout(() => resolve36(null), 2e3))
|
|
12930
12930
|
]);
|
|
12931
12931
|
if (ipfsResult && ipfsResult.success) {
|
|
12932
12932
|
const cidData = JSON.parse(ipfsResult.output);
|
|
@@ -13373,7 +13373,7 @@ print("__OA_REPL_READY__")
|
|
|
13373
13373
|
return;
|
|
13374
13374
|
const sockId = randomBytes5(8).toString("hex");
|
|
13375
13375
|
this.ipcPath = join22(tmpdir3(), `oa-repl-ipc-${sockId}.sock`);
|
|
13376
|
-
return new Promise((
|
|
13376
|
+
return new Promise((resolve36, reject) => {
|
|
13377
13377
|
this.ipcServer = createServer((conn) => {
|
|
13378
13378
|
let buffer = new Uint8Array(0);
|
|
13379
13379
|
conn.on("data", (chunk) => {
|
|
@@ -13389,7 +13389,7 @@ print("__OA_REPL_READY__")
|
|
|
13389
13389
|
});
|
|
13390
13390
|
});
|
|
13391
13391
|
this.ipcServer.on("error", reject);
|
|
13392
|
-
this.ipcServer.listen(this.ipcPath, () =>
|
|
13392
|
+
this.ipcServer.listen(this.ipcPath, () => resolve36());
|
|
13393
13393
|
});
|
|
13394
13394
|
}
|
|
13395
13395
|
async processIpcBuffer(conn, input) {
|
|
@@ -13452,9 +13452,9 @@ print("__OA_REPL_READY__")
|
|
|
13452
13452
|
}
|
|
13453
13453
|
// ── Code execution ─────────────────────────────────────────────────────
|
|
13454
13454
|
executeCode(code, isInit = false) {
|
|
13455
|
-
return new Promise((
|
|
13455
|
+
return new Promise((resolve36) => {
|
|
13456
13456
|
if (!this.proc?.stdin || !this.proc?.stdout || !this.proc?.stderr) {
|
|
13457
|
-
|
|
13457
|
+
resolve36({ success: false, output: "REPL process not available", error: "No process", durationMs: 0 });
|
|
13458
13458
|
return;
|
|
13459
13459
|
}
|
|
13460
13460
|
const sentinel = `__OA_SENTINEL_${randomBytes5(6).toString("hex")}__`;
|
|
@@ -13464,7 +13464,7 @@ print("__OA_REPL_READY__")
|
|
|
13464
13464
|
const timeout = setTimeout(() => {
|
|
13465
13465
|
if (!resolved) {
|
|
13466
13466
|
resolved = true;
|
|
13467
|
-
|
|
13467
|
+
resolve36({
|
|
13468
13468
|
success: false,
|
|
13469
13469
|
output: stdout || "Execution timed out",
|
|
13470
13470
|
error: `Timeout after ${this.execTimeout / 1e3}s`,
|
|
@@ -13481,13 +13481,13 @@ print("__OA_REPL_READY__")
|
|
|
13481
13481
|
if (isInit) {
|
|
13482
13482
|
const ready = cleanOutput.includes("__OA_REPL_READY__");
|
|
13483
13483
|
const displayOutput = cleanOutput.replace("__OA_REPL_READY__", "").trim();
|
|
13484
|
-
|
|
13484
|
+
resolve36({
|
|
13485
13485
|
success: ready,
|
|
13486
13486
|
output: displayOutput || "REPL initialized",
|
|
13487
13487
|
durationMs: 0
|
|
13488
13488
|
});
|
|
13489
13489
|
} else {
|
|
13490
|
-
|
|
13490
|
+
resolve36({
|
|
13491
13491
|
success: true,
|
|
13492
13492
|
output: cleanOutput || "(no output)",
|
|
13493
13493
|
durationMs: 0
|
|
@@ -13496,7 +13496,7 @@ print("__OA_REPL_READY__")
|
|
|
13496
13496
|
}
|
|
13497
13497
|
if (stdout.length > 2e5) {
|
|
13498
13498
|
cleanup();
|
|
13499
|
-
|
|
13499
|
+
resolve36({
|
|
13500
13500
|
success: true,
|
|
13501
13501
|
output: stdout.slice(0, 2e5) + "\n[output truncated at 200KB]",
|
|
13502
13502
|
durationMs: 0
|
|
@@ -13598,9 +13598,9 @@ print("${sentinel}")
|
|
|
13598
13598
|
if (!this.proc || this.proc.killed) {
|
|
13599
13599
|
return { success: false, path: "" };
|
|
13600
13600
|
}
|
|
13601
|
-
const { mkdirSync:
|
|
13601
|
+
const { mkdirSync: mkdirSync28, writeFileSync: writeFileSync27 } = await import("node:fs");
|
|
13602
13602
|
const sessionDir = join22(this.cwd, ".oa", "rlm");
|
|
13603
|
-
|
|
13603
|
+
mkdirSync28(sessionDir, { recursive: true });
|
|
13604
13604
|
const sessionPath = join22(sessionDir, "session.json");
|
|
13605
13605
|
try {
|
|
13606
13606
|
const inspectCode = `
|
|
@@ -13624,7 +13624,7 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
|
|
|
13624
13624
|
trajectoryCount: this.trajectory.length,
|
|
13625
13625
|
subCallCount: this.subCallCount
|
|
13626
13626
|
};
|
|
13627
|
-
|
|
13627
|
+
writeFileSync27(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
|
|
13628
13628
|
return { success: true, path: sessionPath };
|
|
13629
13629
|
}
|
|
13630
13630
|
} catch {
|
|
@@ -13636,11 +13636,11 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
|
|
|
13636
13636
|
* what was previously computed. */
|
|
13637
13637
|
async loadSessionInfo() {
|
|
13638
13638
|
try {
|
|
13639
|
-
const { readFileSync:
|
|
13639
|
+
const { readFileSync: readFileSync42, existsSync: existsSync54 } = await import("node:fs");
|
|
13640
13640
|
const sessionPath = join22(this.cwd, ".oa", "rlm", "session.json");
|
|
13641
|
-
if (!
|
|
13641
|
+
if (!existsSync54(sessionPath))
|
|
13642
13642
|
return null;
|
|
13643
|
-
return JSON.parse(
|
|
13643
|
+
return JSON.parse(readFileSync42(sessionPath, "utf8"));
|
|
13644
13644
|
} catch {
|
|
13645
13645
|
return null;
|
|
13646
13646
|
}
|
|
@@ -13817,10 +13817,10 @@ var init_memory_metabolism = __esm({
|
|
|
13817
13817
|
const trajDir = join23(this.cwd, ".oa", "rlm-trajectories");
|
|
13818
13818
|
let lessons = [];
|
|
13819
13819
|
try {
|
|
13820
|
-
const { readdirSync:
|
|
13821
|
-
const files =
|
|
13820
|
+
const { readdirSync: readdirSync22, readFileSync: readFileSync42 } = await import("node:fs");
|
|
13821
|
+
const files = readdirSync22(trajDir).filter((f) => f.endsWith(".jsonl")).sort().reverse().slice(0, 3);
|
|
13822
13822
|
for (const file of files) {
|
|
13823
|
-
const lines =
|
|
13823
|
+
const lines = readFileSync42(join23(trajDir, file), "utf8").split("\n").filter((l) => l.trim());
|
|
13824
13824
|
for (const line of lines) {
|
|
13825
13825
|
try {
|
|
13826
13826
|
const entry = JSON.parse(line);
|
|
@@ -14204,14 +14204,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14204
14204
|
* Optionally filter by task type for phase-aware context (FSM paper insight).
|
|
14205
14205
|
*/
|
|
14206
14206
|
getTopMemoriesSync(k = 5, taskType) {
|
|
14207
|
-
const { readFileSync:
|
|
14207
|
+
const { readFileSync: readFileSync42, existsSync: existsSync54 } = __require("node:fs");
|
|
14208
14208
|
const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14209
14209
|
const storeFile = join23(metaDir, "store.json");
|
|
14210
|
-
if (!
|
|
14210
|
+
if (!existsSync54(storeFile))
|
|
14211
14211
|
return "";
|
|
14212
14212
|
let store = [];
|
|
14213
14213
|
try {
|
|
14214
|
-
store = JSON.parse(
|
|
14214
|
+
store = JSON.parse(readFileSync42(storeFile, "utf8"));
|
|
14215
14215
|
} catch {
|
|
14216
14216
|
return "";
|
|
14217
14217
|
}
|
|
@@ -14233,14 +14233,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14233
14233
|
/** Update memory scores based on task outcome. Called after task completion.
|
|
14234
14234
|
* Memories used in successful tasks get boosted. Memories present during failures get decayed. */
|
|
14235
14235
|
updateFromOutcomeSync(surfacedMemoryText, succeeded) {
|
|
14236
|
-
const { readFileSync:
|
|
14236
|
+
const { readFileSync: readFileSync42, writeFileSync: writeFileSync27, existsSync: existsSync54, mkdirSync: mkdirSync28 } = __require("node:fs");
|
|
14237
14237
|
const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14238
14238
|
const storeFile = join23(metaDir, "store.json");
|
|
14239
|
-
if (!
|
|
14239
|
+
if (!existsSync54(storeFile))
|
|
14240
14240
|
return;
|
|
14241
14241
|
let store = [];
|
|
14242
14242
|
try {
|
|
14243
|
-
store = JSON.parse(
|
|
14243
|
+
store = JSON.parse(readFileSync42(storeFile, "utf8"));
|
|
14244
14244
|
} catch {
|
|
14245
14245
|
return;
|
|
14246
14246
|
}
|
|
@@ -14264,8 +14264,8 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14264
14264
|
updated = true;
|
|
14265
14265
|
}
|
|
14266
14266
|
if (updated) {
|
|
14267
|
-
|
|
14268
|
-
|
|
14267
|
+
mkdirSync28(metaDir, { recursive: true });
|
|
14268
|
+
writeFileSync27(storeFile, JSON.stringify(store, null, 2));
|
|
14269
14269
|
}
|
|
14270
14270
|
}
|
|
14271
14271
|
// ── Storage ──────────────────────────────────────────────────────────
|
|
@@ -14687,13 +14687,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
14687
14687
|
// Per EvoSkill (arXiv:2603.02766): retrieve relevant strategies from archive.
|
|
14688
14688
|
/** Retrieve top-K strategies for context injection. Returns "" if none. */
|
|
14689
14689
|
getRelevantStrategiesSync(k = 3, taskType) {
|
|
14690
|
-
const { readFileSync:
|
|
14690
|
+
const { readFileSync: readFileSync42, existsSync: existsSync54 } = __require("node:fs");
|
|
14691
14691
|
const archiveFile = join25(this.cwd, ".oa", "arche", "variants.json");
|
|
14692
|
-
if (!
|
|
14692
|
+
if (!existsSync54(archiveFile))
|
|
14693
14693
|
return "";
|
|
14694
14694
|
let variants = [];
|
|
14695
14695
|
try {
|
|
14696
|
-
variants = JSON.parse(
|
|
14696
|
+
variants = JSON.parse(readFileSync42(archiveFile, "utf8"));
|
|
14697
14697
|
} catch {
|
|
14698
14698
|
return "";
|
|
14699
14699
|
}
|
|
@@ -14711,13 +14711,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
14711
14711
|
}
|
|
14712
14712
|
/** Archive a strategy variant synchronously (for task completion path) */
|
|
14713
14713
|
archiveVariantSync(strategy, outcome, tags = []) {
|
|
14714
|
-
const { readFileSync:
|
|
14714
|
+
const { readFileSync: readFileSync42, writeFileSync: writeFileSync27, existsSync: existsSync54, mkdirSync: mkdirSync28 } = __require("node:fs");
|
|
14715
14715
|
const dir = join25(this.cwd, ".oa", "arche");
|
|
14716
14716
|
const archiveFile = join25(dir, "variants.json");
|
|
14717
14717
|
let variants = [];
|
|
14718
14718
|
try {
|
|
14719
|
-
if (
|
|
14720
|
-
variants = JSON.parse(
|
|
14719
|
+
if (existsSync54(archiveFile))
|
|
14720
|
+
variants = JSON.parse(readFileSync42(archiveFile, "utf8"));
|
|
14721
14721
|
} catch {
|
|
14722
14722
|
}
|
|
14723
14723
|
variants.push({
|
|
@@ -14732,8 +14732,8 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
14732
14732
|
});
|
|
14733
14733
|
if (variants.length > 50)
|
|
14734
14734
|
variants = variants.slice(-50);
|
|
14735
|
-
|
|
14736
|
-
|
|
14735
|
+
mkdirSync28(dir, { recursive: true });
|
|
14736
|
+
writeFileSync27(archiveFile, JSON.stringify(variants, null, 2));
|
|
14737
14737
|
}
|
|
14738
14738
|
async saveArchive(variants) {
|
|
14739
14739
|
const dir = join25(this.cwd, ".oa", "arche");
|
|
@@ -21880,7 +21880,7 @@ import { spawn as spawn14 } from "node:child_process";
|
|
|
21880
21880
|
async function runShell(options) {
|
|
21881
21881
|
const { command, args = [], cwd: cwd4, env, timeoutMs = DEFAULT_TIMEOUT_MS } = options;
|
|
21882
21882
|
const mergedEnv = env ? { ...process.env, ...env } : process.env;
|
|
21883
|
-
return new Promise((
|
|
21883
|
+
return new Promise((resolve36) => {
|
|
21884
21884
|
const start = Date.now();
|
|
21885
21885
|
let timedOut = false;
|
|
21886
21886
|
const child = spawn14(command, args, {
|
|
@@ -21904,7 +21904,7 @@ async function runShell(options) {
|
|
|
21904
21904
|
clearTimeout(timer);
|
|
21905
21905
|
const durationMs = Date.now() - start;
|
|
21906
21906
|
const exitCode = timedOut ? -1 : code ?? -1;
|
|
21907
|
-
|
|
21907
|
+
resolve36({
|
|
21908
21908
|
stdout,
|
|
21909
21909
|
stderr,
|
|
21910
21910
|
exitCode,
|
|
@@ -21916,7 +21916,7 @@ async function runShell(options) {
|
|
|
21916
21916
|
child.on("error", (err) => {
|
|
21917
21917
|
clearTimeout(timer);
|
|
21918
21918
|
const durationMs = Date.now() - start;
|
|
21919
|
-
|
|
21919
|
+
resolve36({
|
|
21920
21920
|
stdout,
|
|
21921
21921
|
stderr: stderr + err.message,
|
|
21922
21922
|
exitCode: -1,
|
|
@@ -22031,7 +22031,7 @@ async function applyUnifiedDiff(patch) {
|
|
|
22031
22031
|
}
|
|
22032
22032
|
function runWithStdin(options) {
|
|
22033
22033
|
const { command, args, cwd: cwd4, stdin } = options;
|
|
22034
|
-
return new Promise((
|
|
22034
|
+
return new Promise((resolve36) => {
|
|
22035
22035
|
const child = spawn15(command, args, {
|
|
22036
22036
|
cwd: cwd4,
|
|
22037
22037
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -22048,10 +22048,10 @@ function runWithStdin(options) {
|
|
|
22048
22048
|
child.stdin.end();
|
|
22049
22049
|
child.on("close", (code) => {
|
|
22050
22050
|
const exitCode = code ?? -1;
|
|
22051
|
-
|
|
22051
|
+
resolve36({ success: exitCode === 0, exitCode, stdout, stderr });
|
|
22052
22052
|
});
|
|
22053
22053
|
child.on("error", (err) => {
|
|
22054
|
-
|
|
22054
|
+
resolve36({ success: false, exitCode: -1, stdout, stderr: err.message });
|
|
22055
22055
|
});
|
|
22056
22056
|
});
|
|
22057
22057
|
}
|
|
@@ -24287,22 +24287,22 @@ var init_snippetPacker = __esm({
|
|
|
24287
24287
|
});
|
|
24288
24288
|
|
|
24289
24289
|
// packages/retrieval/dist/contextAssembler.js
|
|
24290
|
-
async function assembleContext(
|
|
24290
|
+
async function assembleContext(request2, opts) {
|
|
24291
24291
|
const { repoRoot, graph, semanticEngine, summaryMap, maxFiles = 8, maxSnippets = 20, maxLogs = 3, maxTokens = 24e3, expandNeighbors = true, architectureNote, priorAttemptNote } = opts;
|
|
24292
24292
|
const lexOpts = {
|
|
24293
24293
|
rootDir: repoRoot,
|
|
24294
24294
|
includePatterns: [],
|
|
24295
|
-
includeTests:
|
|
24296
|
-
includeConfigs:
|
|
24295
|
+
includeTests: request2.includeTests,
|
|
24296
|
+
includeConfigs: request2.includeConfigs,
|
|
24297
24297
|
maxMatches: 30
|
|
24298
24298
|
};
|
|
24299
24299
|
const [pathMatches, symbolMatches, errorMatches, semanticResults] = await Promise.all([
|
|
24300
|
-
Promise.all(
|
|
24301
|
-
Promise.all(
|
|
24302
|
-
Promise.all(
|
|
24303
|
-
semanticEngine?.isAvailable ? semanticEngine.search(
|
|
24300
|
+
Promise.all(request2.pathsHint.map((p) => searchByPath(p, { rootDir: repoRoot, maxMatches: 10 }))).then((res) => res.flat()),
|
|
24301
|
+
Promise.all(request2.symbolHint.map((s) => searchBySymbol(s, { rootDir: repoRoot, maxMatches: 10 }))).then((res) => res.flat()),
|
|
24302
|
+
Promise.all(request2.errorHint.slice(0, maxLogs).map((e) => searchByError(e, { rootDir: repoRoot, maxMatches: 5 }))).then((res) => res.flat()),
|
|
24303
|
+
semanticEngine?.isAvailable ? semanticEngine.search(request2.query, maxFiles) : Promise.resolve([])
|
|
24304
24304
|
]);
|
|
24305
|
-
const queryType = classifyQuery(
|
|
24305
|
+
const queryType = classifyQuery(request2.query);
|
|
24306
24306
|
const rrfK = adaptiveK(queryType, opts.rrfConfig?.k);
|
|
24307
24307
|
const wFts = opts.rrfConfig?.weightFts ?? 1;
|
|
24308
24308
|
const wSem = opts.rrfConfig?.weightSemantic ?? 1;
|
|
@@ -24373,7 +24373,7 @@ async function assembleContext(request, opts) {
|
|
|
24373
24373
|
}
|
|
24374
24374
|
}
|
|
24375
24375
|
return {
|
|
24376
|
-
request,
|
|
24376
|
+
request: request2,
|
|
24377
24377
|
files,
|
|
24378
24378
|
snippets: packed.slice(0, maxSnippets),
|
|
24379
24379
|
architectureNote,
|
|
@@ -25116,14 +25116,14 @@ var init_ralphLoop = __esm({
|
|
|
25116
25116
|
* @param repoRoot Absolute path to the repository root.
|
|
25117
25117
|
*/
|
|
25118
25118
|
async run(rawRequest, repoRoot) {
|
|
25119
|
-
const
|
|
25119
|
+
const startedAt2 = isoNow();
|
|
25120
25120
|
const effectiveRepoRoot = this.options.repoRootOverride || repoRoot;
|
|
25121
25121
|
let task;
|
|
25122
25122
|
try {
|
|
25123
25123
|
const normalized = await this.normalizer.normalize(rawRequest, effectiveRepoRoot);
|
|
25124
25124
|
task = { ...normalized, repoRoot: effectiveRepoRoot };
|
|
25125
25125
|
} catch (err) {
|
|
25126
|
-
return this.buildErrorReport(void 0, rawRequest, effectiveRepoRoot,
|
|
25126
|
+
return this.buildErrorReport(void 0, rawRequest, effectiveRepoRoot, startedAt2, `Task normalization failed: ${String(err)}`);
|
|
25127
25127
|
}
|
|
25128
25128
|
const repoProfile = void 0;
|
|
25129
25129
|
let dispatchDecision;
|
|
@@ -25157,7 +25157,7 @@ var init_ralphLoop = __esm({
|
|
|
25157
25157
|
const executions = [];
|
|
25158
25158
|
const completedIds = /* @__PURE__ */ new Set();
|
|
25159
25159
|
for (const subtask of subtasks) {
|
|
25160
|
-
if (elapsedMs(
|
|
25160
|
+
if (elapsedMs(startedAt2) > this.options.timeoutMs) {
|
|
25161
25161
|
const execution2 = {
|
|
25162
25162
|
subtaskId: subtask.id,
|
|
25163
25163
|
status: "failed",
|
|
@@ -25209,7 +25209,7 @@ var init_ralphLoop = __esm({
|
|
|
25209
25209
|
repoProfile,
|
|
25210
25210
|
dispatchDecision,
|
|
25211
25211
|
subtaskExecutions: executions,
|
|
25212
|
-
startedAt,
|
|
25212
|
+
startedAt: startedAt2,
|
|
25213
25213
|
completedAt: isoNow(),
|
|
25214
25214
|
summary: summaryParts.join(". "),
|
|
25215
25215
|
filesChanged
|
|
@@ -25322,7 +25322,7 @@ var init_ralphLoop = __esm({
|
|
|
25322
25322
|
// -------------------------------------------------------------------------
|
|
25323
25323
|
// Private: error report builder
|
|
25324
25324
|
// -------------------------------------------------------------------------
|
|
25325
|
-
buildErrorReport(task, rawRequest, repoRoot,
|
|
25325
|
+
buildErrorReport(task, rawRequest, repoRoot, startedAt2, errorMessage) {
|
|
25326
25326
|
const fallbackTask = task ?? {
|
|
25327
25327
|
id: `task-error-${Date.now()}`,
|
|
25328
25328
|
goal: rawRequest.slice(0, 200),
|
|
@@ -25342,7 +25342,7 @@ var init_ralphLoop = __esm({
|
|
|
25342
25342
|
repoProfile: void 0,
|
|
25343
25343
|
dispatchDecision: void 0,
|
|
25344
25344
|
subtaskExecutions: [],
|
|
25345
|
-
startedAt,
|
|
25345
|
+
startedAt: startedAt2,
|
|
25346
25346
|
completedAt: isoNow(),
|
|
25347
25347
|
summary: errorMessage,
|
|
25348
25348
|
filesChanged: []
|
|
@@ -25793,8 +25793,8 @@ ${this.options.dynamicContext}`,
|
|
|
25793
25793
|
async waitIfPaused() {
|
|
25794
25794
|
if (!this._paused)
|
|
25795
25795
|
return true;
|
|
25796
|
-
await new Promise((
|
|
25797
|
-
this._pauseResolve =
|
|
25796
|
+
await new Promise((resolve36) => {
|
|
25797
|
+
this._pauseResolve = resolve36;
|
|
25798
25798
|
});
|
|
25799
25799
|
return !this.aborted;
|
|
25800
25800
|
}
|
|
@@ -26951,14 +26951,14 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
|
|
|
26951
26951
|
waitForSudoPassword(timeoutMs = 12e4) {
|
|
26952
26952
|
if (this._sudoPassword)
|
|
26953
26953
|
return Promise.resolve(this._sudoPassword);
|
|
26954
|
-
return new Promise((
|
|
26954
|
+
return new Promise((resolve36) => {
|
|
26955
26955
|
const timer = setTimeout(() => {
|
|
26956
26956
|
this._sudoResolve = null;
|
|
26957
|
-
|
|
26957
|
+
resolve36(null);
|
|
26958
26958
|
}, timeoutMs);
|
|
26959
26959
|
this._sudoResolve = (pw) => {
|
|
26960
26960
|
clearTimeout(timer);
|
|
26961
|
-
|
|
26961
|
+
resolve36(pw);
|
|
26962
26962
|
};
|
|
26963
26963
|
});
|
|
26964
26964
|
}
|
|
@@ -27091,10 +27091,10 @@ ${marker}` : marker);
|
|
|
27091
27091
|
if (!this._workingDirectory)
|
|
27092
27092
|
return;
|
|
27093
27093
|
try {
|
|
27094
|
-
const { mkdirSync:
|
|
27095
|
-
const { join:
|
|
27096
|
-
const sessionDir =
|
|
27097
|
-
|
|
27094
|
+
const { mkdirSync: mkdirSync28, writeFileSync: writeFileSync27 } = __require("node:fs");
|
|
27095
|
+
const { join: join74 } = __require("node:path");
|
|
27096
|
+
const sessionDir = join74(this._workingDirectory, ".oa", "session", this._sessionId);
|
|
27097
|
+
mkdirSync28(sessionDir, { recursive: true });
|
|
27098
27098
|
const checkpoint = {
|
|
27099
27099
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27100
27100
|
sessionId: this._sessionId,
|
|
@@ -27106,7 +27106,7 @@ ${marker}` : marker);
|
|
|
27106
27106
|
memexEntryCount: this._memexArchive.size,
|
|
27107
27107
|
fileRegistrySize: this._fileRegistry.size
|
|
27108
27108
|
};
|
|
27109
|
-
|
|
27109
|
+
writeFileSync27(join74(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
|
|
27110
27110
|
} catch {
|
|
27111
27111
|
}
|
|
27112
27112
|
}
|
|
@@ -28232,14 +28232,14 @@ ${transcript}`
|
|
|
28232
28232
|
* assembles and returns the same response format as chatCompletion().
|
|
28233
28233
|
* The non-streaming chatCompletion path is NEVER touched by this code.
|
|
28234
28234
|
*/
|
|
28235
|
-
async streamingRequest(
|
|
28235
|
+
async streamingRequest(request2, turn) {
|
|
28236
28236
|
const backend = this.backend;
|
|
28237
28237
|
let content = "";
|
|
28238
28238
|
let inThinkTag = false;
|
|
28239
28239
|
const toolCallAccumulators = /* @__PURE__ */ new Map();
|
|
28240
28240
|
let streamUsage;
|
|
28241
28241
|
this.emit({ type: "stream_start", turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
28242
|
-
for await (const chunk of backend.chatCompletionStream(
|
|
28242
|
+
for await (const chunk of backend.chatCompletionStream(request2)) {
|
|
28243
28243
|
if (this.aborted)
|
|
28244
28244
|
break;
|
|
28245
28245
|
if (chunk.type === "usage" && chunk.usage) {
|
|
@@ -28349,13 +28349,13 @@ ${transcript}`
|
|
|
28349
28349
|
}
|
|
28350
28350
|
return headers;
|
|
28351
28351
|
}
|
|
28352
|
-
async chatCompletion(
|
|
28352
|
+
async chatCompletion(request2) {
|
|
28353
28353
|
const body = {
|
|
28354
28354
|
model: this.model,
|
|
28355
|
-
messages:
|
|
28356
|
-
tools:
|
|
28357
|
-
temperature:
|
|
28358
|
-
max_tokens:
|
|
28355
|
+
messages: request2.messages,
|
|
28356
|
+
tools: request2.tools,
|
|
28357
|
+
temperature: request2.temperature,
|
|
28358
|
+
max_tokens: request2.maxTokens,
|
|
28359
28359
|
think: this.thinking
|
|
28360
28360
|
};
|
|
28361
28361
|
const fetchOpts = {
|
|
@@ -28412,13 +28412,13 @@ ${transcript}`
|
|
|
28412
28412
|
* Uses `stream: true` and the current thinking setting.
|
|
28413
28413
|
* The existing chatCompletion() method is completely unmodified.
|
|
28414
28414
|
*/
|
|
28415
|
-
async *chatCompletionStream(
|
|
28415
|
+
async *chatCompletionStream(request2) {
|
|
28416
28416
|
const body = {
|
|
28417
28417
|
model: this.model,
|
|
28418
|
-
messages:
|
|
28419
|
-
tools:
|
|
28420
|
-
temperature:
|
|
28421
|
-
max_tokens:
|
|
28418
|
+
messages: request2.messages,
|
|
28419
|
+
tools: request2.tools,
|
|
28420
|
+
temperature: request2.temperature,
|
|
28421
|
+
max_tokens: request2.maxTokens,
|
|
28422
28422
|
stream: true,
|
|
28423
28423
|
stream_options: { include_usage: true },
|
|
28424
28424
|
think: this.thinking
|
|
@@ -28538,7 +28538,7 @@ var init_nexusBackend = __esm({
|
|
|
28538
28538
|
this.targetPeer = peerId;
|
|
28539
28539
|
this.consecutiveFailures = 0;
|
|
28540
28540
|
}
|
|
28541
|
-
async chatCompletion(
|
|
28541
|
+
async chatCompletion(request2) {
|
|
28542
28542
|
if (this.consecutiveFailures >= _NexusAgenticBackend.MAX_CONSECUTIVE_FAILURES) {
|
|
28543
28543
|
const err = new Error(`Remote peer unreachable after ${this.consecutiveFailures} attempts. Use /endpoint to switch to a local model or reconnect.`);
|
|
28544
28544
|
err.fatal = true;
|
|
@@ -28546,10 +28546,10 @@ var init_nexusBackend = __esm({
|
|
|
28546
28546
|
}
|
|
28547
28547
|
const daemonArgs = {
|
|
28548
28548
|
model: this.model,
|
|
28549
|
-
messages: JSON.stringify(
|
|
28550
|
-
tools: JSON.stringify(
|
|
28551
|
-
temperature: String(
|
|
28552
|
-
max_tokens: String(
|
|
28549
|
+
messages: JSON.stringify(request2.messages),
|
|
28550
|
+
tools: JSON.stringify(request2.tools),
|
|
28551
|
+
temperature: String(request2.temperature),
|
|
28552
|
+
max_tokens: String(request2.maxTokens)
|
|
28553
28553
|
};
|
|
28554
28554
|
if (this.targetPeer) {
|
|
28555
28555
|
daemonArgs.target_peer = this.targetPeer;
|
|
@@ -28560,7 +28560,7 @@ var init_nexusBackend = __esm({
|
|
|
28560
28560
|
daemonArgs.think = String(this.thinking);
|
|
28561
28561
|
let rawResult;
|
|
28562
28562
|
try {
|
|
28563
|
-
rawResult = await this.sendFn("remote_infer", daemonArgs,
|
|
28563
|
+
rawResult = await this.sendFn("remote_infer", daemonArgs, request2.timeoutMs || 12e4);
|
|
28564
28564
|
} catch (sendErr) {
|
|
28565
28565
|
this.consecutiveFailures++;
|
|
28566
28566
|
throw sendErr;
|
|
@@ -28653,15 +28653,15 @@ var init_nexusBackend = __esm({
|
|
|
28653
28653
|
* the file for token-by-token delivery from the remote peer.
|
|
28654
28654
|
* Falls back to unary + word-split if streaming setup fails.
|
|
28655
28655
|
*/
|
|
28656
|
-
async *chatCompletionStream(
|
|
28656
|
+
async *chatCompletionStream(request2) {
|
|
28657
28657
|
const streamFile = join47(tmpdir7(), `nexus-stream-${randomBytes11(6).toString("hex")}.jsonl`);
|
|
28658
28658
|
writeFileSync11(streamFile, "", "utf8");
|
|
28659
28659
|
const daemonArgs = {
|
|
28660
28660
|
model: this.model,
|
|
28661
|
-
messages: JSON.stringify(
|
|
28662
|
-
tools: JSON.stringify(
|
|
28663
|
-
temperature: String(
|
|
28664
|
-
max_tokens: String(
|
|
28661
|
+
messages: JSON.stringify(request2.messages),
|
|
28662
|
+
tools: JSON.stringify(request2.tools),
|
|
28663
|
+
temperature: String(request2.temperature),
|
|
28664
|
+
max_tokens: String(request2.maxTokens),
|
|
28665
28665
|
stream_file: streamFile
|
|
28666
28666
|
};
|
|
28667
28667
|
if (this.targetPeer)
|
|
@@ -28671,7 +28671,7 @@ var init_nexusBackend = __esm({
|
|
|
28671
28671
|
daemonArgs.think = String(this.thinking);
|
|
28672
28672
|
let rawResult;
|
|
28673
28673
|
try {
|
|
28674
|
-
rawResult = await this.sendFn("remote_infer", daemonArgs,
|
|
28674
|
+
rawResult = await this.sendFn("remote_infer", daemonArgs, request2.timeoutMs || 12e4);
|
|
28675
28675
|
} catch (sendErr) {
|
|
28676
28676
|
this.consecutiveFailures++;
|
|
28677
28677
|
try {
|
|
@@ -28744,15 +28744,15 @@ var init_nexusBackend = __esm({
|
|
|
28744
28744
|
this.consecutiveFailures = 0;
|
|
28745
28745
|
let position = 0;
|
|
28746
28746
|
let done = false;
|
|
28747
|
-
const deadline = Date.now() + (
|
|
28747
|
+
const deadline = Date.now() + (request2.timeoutMs ?? 12e4);
|
|
28748
28748
|
try {
|
|
28749
28749
|
while (!done && Date.now() < deadline) {
|
|
28750
|
-
await new Promise((
|
|
28750
|
+
await new Promise((resolve36) => {
|
|
28751
28751
|
let resolved = false;
|
|
28752
28752
|
const finish = () => {
|
|
28753
28753
|
if (!resolved) {
|
|
28754
28754
|
resolved = true;
|
|
28755
|
-
|
|
28755
|
+
resolve36();
|
|
28756
28756
|
}
|
|
28757
28757
|
};
|
|
28758
28758
|
let watcher = null;
|
|
@@ -28917,10 +28917,10 @@ var init_cascadeBackend = __esm({
|
|
|
28917
28917
|
get fallbackCount() {
|
|
28918
28918
|
return this.endpoints.filter((ep, i) => i !== this.activeIndex && ep.modelAvailable !== false).length;
|
|
28919
28919
|
}
|
|
28920
|
-
async chatCompletion(
|
|
28920
|
+
async chatCompletion(request2) {
|
|
28921
28921
|
const backend = this.getActiveBackend();
|
|
28922
28922
|
try {
|
|
28923
|
-
const result = await backend.chatCompletion(
|
|
28923
|
+
const result = await backend.chatCompletion(request2);
|
|
28924
28924
|
this.consecutiveFailures = 0;
|
|
28925
28925
|
return result;
|
|
28926
28926
|
} catch (err) {
|
|
@@ -28936,7 +28936,7 @@ var init_cascadeBackend = __esm({
|
|
|
28936
28936
|
this.onSwitch?.(from, to, reason);
|
|
28937
28937
|
const newBackend = this.getActiveBackend();
|
|
28938
28938
|
try {
|
|
28939
|
-
const result = await newBackend.chatCompletion(
|
|
28939
|
+
const result = await newBackend.chatCompletion(request2);
|
|
28940
28940
|
return result;
|
|
28941
28941
|
} catch (cascadeErr) {
|
|
28942
28942
|
this.consecutiveFailures++;
|
|
@@ -28950,11 +28950,11 @@ var init_cascadeBackend = __esm({
|
|
|
28950
28950
|
/**
|
|
28951
28951
|
* Streaming support — delegates to active backend's stream method if available.
|
|
28952
28952
|
*/
|
|
28953
|
-
async *chatCompletionStream(
|
|
28953
|
+
async *chatCompletionStream(request2) {
|
|
28954
28954
|
const backend = this.getActiveBackend();
|
|
28955
28955
|
const streamable = backend;
|
|
28956
28956
|
if (typeof streamable.chatCompletionStream !== "function") {
|
|
28957
|
-
const result = await this.chatCompletion(
|
|
28957
|
+
const result = await this.chatCompletion(request2);
|
|
28958
28958
|
const choice = result.choices[0];
|
|
28959
28959
|
if (choice?.message.content) {
|
|
28960
28960
|
yield { type: "content", content: choice.message.content };
|
|
@@ -28985,7 +28985,7 @@ var init_cascadeBackend = __esm({
|
|
|
28985
28985
|
return;
|
|
28986
28986
|
}
|
|
28987
28987
|
try {
|
|
28988
|
-
for await (const chunk of streamable.chatCompletionStream(
|
|
28988
|
+
for await (const chunk of streamable.chatCompletionStream(request2)) {
|
|
28989
28989
|
yield chunk;
|
|
28990
28990
|
}
|
|
28991
28991
|
this.consecutiveFailures = 0;
|
|
@@ -28999,7 +28999,7 @@ var init_cascadeBackend = __esm({
|
|
|
28999
28999
|
this.activeIndex = nextIdx;
|
|
29000
29000
|
this.consecutiveFailures = 0;
|
|
29001
29001
|
this.onSwitch?.(from, to, err instanceof Error ? err.message : String(err));
|
|
29002
|
-
const result = await this.chatCompletion(
|
|
29002
|
+
const result = await this.chatCompletion(request2);
|
|
29003
29003
|
const choice = result.choices[0];
|
|
29004
29004
|
if (choice?.message.content) {
|
|
29005
29005
|
yield { type: "content", content: choice.message.content };
|
|
@@ -29834,9 +29834,9 @@ function ensureTranscribeCliBackground() {
|
|
|
29834
29834
|
}
|
|
29835
29835
|
try {
|
|
29836
29836
|
const { exec: exec4 } = await import("node:child_process");
|
|
29837
|
-
return new Promise((
|
|
29837
|
+
return new Promise((resolve36) => {
|
|
29838
29838
|
exec4("npm i -g transcribe-cli", { timeout: 18e4 }, (err) => {
|
|
29839
|
-
|
|
29839
|
+
resolve36(!err);
|
|
29840
29840
|
});
|
|
29841
29841
|
});
|
|
29842
29842
|
} catch {
|
|
@@ -29895,7 +29895,7 @@ var init_listen = __esm({
|
|
|
29895
29895
|
return this._ready;
|
|
29896
29896
|
}
|
|
29897
29897
|
async start() {
|
|
29898
|
-
return new Promise((
|
|
29898
|
+
return new Promise((resolve36, reject) => {
|
|
29899
29899
|
const timeout = setTimeout(() => {
|
|
29900
29900
|
reject(new Error("Whisper fallback: model load timeout (5 min). First run downloads the model."));
|
|
29901
29901
|
}, 3e5);
|
|
@@ -29923,7 +29923,7 @@ var init_listen = __esm({
|
|
|
29923
29923
|
this._ready = true;
|
|
29924
29924
|
clearTimeout(timeout);
|
|
29925
29925
|
this.emit("ready");
|
|
29926
|
-
|
|
29926
|
+
resolve36();
|
|
29927
29927
|
break;
|
|
29928
29928
|
case "transcript":
|
|
29929
29929
|
this.emit("transcript", {
|
|
@@ -30039,8 +30039,8 @@ var init_listen = __esm({
|
|
|
30039
30039
|
/** Load transcribe-cli — bundled as a dependency of open-agents-ai. */
|
|
30040
30040
|
async loadTranscribeCli() {
|
|
30041
30041
|
try {
|
|
30042
|
-
const { createRequire:
|
|
30043
|
-
const req =
|
|
30042
|
+
const { createRequire: createRequire5 } = await import("node:module");
|
|
30043
|
+
const req = createRequire5(import.meta.url);
|
|
30044
30044
|
return req("transcribe-cli");
|
|
30045
30045
|
} catch {
|
|
30046
30046
|
}
|
|
@@ -30052,8 +30052,8 @@ var init_listen = __esm({
|
|
|
30052
30052
|
}).trim();
|
|
30053
30053
|
const tcPath = join48(globalRoot, "transcribe-cli");
|
|
30054
30054
|
if (existsSync32(join48(tcPath, "dist", "index.js"))) {
|
|
30055
|
-
const { createRequire:
|
|
30056
|
-
const req =
|
|
30055
|
+
const { createRequire: createRequire5 } = await import("node:module");
|
|
30056
|
+
const req = createRequire5(import.meta.url);
|
|
30057
30057
|
return req(join48(tcPath, "dist", "index.js"));
|
|
30058
30058
|
}
|
|
30059
30059
|
} catch {
|
|
@@ -30061,12 +30061,12 @@ var init_listen = __esm({
|
|
|
30061
30061
|
const nvmBase = join48(homedir11(), ".nvm", "versions", "node");
|
|
30062
30062
|
if (existsSync32(nvmBase)) {
|
|
30063
30063
|
try {
|
|
30064
|
-
const { readdirSync:
|
|
30065
|
-
for (const ver of
|
|
30064
|
+
const { readdirSync: readdirSync22 } = await import("node:fs");
|
|
30065
|
+
for (const ver of readdirSync22(nvmBase)) {
|
|
30066
30066
|
const tcPath = join48(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
|
|
30067
30067
|
if (existsSync32(join48(tcPath, "dist", "index.js"))) {
|
|
30068
|
-
const { createRequire:
|
|
30069
|
-
const req =
|
|
30068
|
+
const { createRequire: createRequire5 } = await import("node:module");
|
|
30069
|
+
const req = createRequire5(import.meta.url);
|
|
30070
30070
|
return req(join48(tcPath, "dist", "index.js"));
|
|
30071
30071
|
}
|
|
30072
30072
|
}
|
|
@@ -30127,11 +30127,11 @@ var init_listen = __esm({
|
|
|
30127
30127
|
this.liveTranscriber.on("error", (err) => {
|
|
30128
30128
|
this.emit("error", err);
|
|
30129
30129
|
});
|
|
30130
|
-
await new Promise((
|
|
30130
|
+
await new Promise((resolve36, reject) => {
|
|
30131
30131
|
const timeout = setTimeout(() => reject(new Error("Model load timeout (60s)")), 6e4);
|
|
30132
30132
|
this.liveTranscriber.on("ready", () => {
|
|
30133
30133
|
clearTimeout(timeout);
|
|
30134
|
-
|
|
30134
|
+
resolve36();
|
|
30135
30135
|
});
|
|
30136
30136
|
this.liveTranscriber.on("error", (err) => {
|
|
30137
30137
|
clearTimeout(timeout);
|
|
@@ -30293,11 +30293,11 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
30293
30293
|
sampleWidth: 2,
|
|
30294
30294
|
chunkDuration: 3
|
|
30295
30295
|
});
|
|
30296
|
-
await new Promise((
|
|
30296
|
+
await new Promise((resolve36, reject) => {
|
|
30297
30297
|
const timeout = setTimeout(() => reject(new Error("Model load timeout (60s)")), 6e4);
|
|
30298
30298
|
transcriber.on("ready", () => {
|
|
30299
30299
|
clearTimeout(timeout);
|
|
30300
|
-
|
|
30300
|
+
resolve36();
|
|
30301
30301
|
});
|
|
30302
30302
|
transcriber.on("error", (err) => {
|
|
30303
30303
|
clearTimeout(timeout);
|
|
@@ -32597,10 +32597,10 @@ var require_websocket = __commonJS({
|
|
|
32597
32597
|
"use strict";
|
|
32598
32598
|
var EventEmitter7 = __require("events");
|
|
32599
32599
|
var https = __require("https");
|
|
32600
|
-
var
|
|
32600
|
+
var http2 = __require("http");
|
|
32601
32601
|
var net = __require("net");
|
|
32602
32602
|
var tls = __require("tls");
|
|
32603
|
-
var { randomBytes:
|
|
32603
|
+
var { randomBytes: randomBytes17, createHash: createHash6 } = __require("crypto");
|
|
32604
32604
|
var { Duplex, Readable } = __require("stream");
|
|
32605
32605
|
var { URL: URL3 } = __require("url");
|
|
32606
32606
|
var PerMessageDeflate = require_permessage_deflate();
|
|
@@ -33130,8 +33130,8 @@ var require_websocket = __commonJS({
|
|
|
33130
33130
|
}
|
|
33131
33131
|
}
|
|
33132
33132
|
const defaultPort = isSecure ? 443 : 80;
|
|
33133
|
-
const key =
|
|
33134
|
-
const
|
|
33133
|
+
const key = randomBytes17(16).toString("base64");
|
|
33134
|
+
const request2 = isSecure ? https.request : http2.request;
|
|
33135
33135
|
const protocolSet = /* @__PURE__ */ new Set();
|
|
33136
33136
|
let perMessageDeflate;
|
|
33137
33137
|
opts.createConnection = opts.createConnection || (isSecure ? tlsConnect : netConnect);
|
|
@@ -33208,12 +33208,12 @@ var require_websocket = __commonJS({
|
|
|
33208
33208
|
if (opts.auth && !options.headers.authorization) {
|
|
33209
33209
|
options.headers.authorization = "Basic " + Buffer.from(opts.auth).toString("base64");
|
|
33210
33210
|
}
|
|
33211
|
-
req = websocket._req =
|
|
33211
|
+
req = websocket._req = request2(opts);
|
|
33212
33212
|
if (websocket._redirects) {
|
|
33213
33213
|
websocket.emit("redirect", websocket.url, req);
|
|
33214
33214
|
}
|
|
33215
33215
|
} else {
|
|
33216
|
-
req = websocket._req =
|
|
33216
|
+
req = websocket._req = request2(opts);
|
|
33217
33217
|
}
|
|
33218
33218
|
if (opts.timeout) {
|
|
33219
33219
|
req.on("timeout", () => {
|
|
@@ -33625,7 +33625,7 @@ var require_websocket_server = __commonJS({
|
|
|
33625
33625
|
"node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket-server.js"(exports, module) {
|
|
33626
33626
|
"use strict";
|
|
33627
33627
|
var EventEmitter7 = __require("events");
|
|
33628
|
-
var
|
|
33628
|
+
var http2 = __require("http");
|
|
33629
33629
|
var { Duplex } = __require("stream");
|
|
33630
33630
|
var { createHash: createHash6 } = __require("crypto");
|
|
33631
33631
|
var extension = require_extension();
|
|
@@ -33700,8 +33700,8 @@ var require_websocket_server = __commonJS({
|
|
|
33700
33700
|
);
|
|
33701
33701
|
}
|
|
33702
33702
|
if (options.port != null) {
|
|
33703
|
-
this._server =
|
|
33704
|
-
const body =
|
|
33703
|
+
this._server = http2.createServer((req, res) => {
|
|
33704
|
+
const body = http2.STATUS_CODES[426];
|
|
33705
33705
|
res.writeHead(426, {
|
|
33706
33706
|
"Content-Length": body.length,
|
|
33707
33707
|
"Content-Type": "text/plain"
|
|
@@ -33988,7 +33988,7 @@ var require_websocket_server = __commonJS({
|
|
|
33988
33988
|
this.destroy();
|
|
33989
33989
|
}
|
|
33990
33990
|
function abortHandshake(socket, code, message, headers) {
|
|
33991
|
-
message = message ||
|
|
33991
|
+
message = message || http2.STATUS_CODES[code];
|
|
33992
33992
|
headers = {
|
|
33993
33993
|
Connection: "close",
|
|
33994
33994
|
"Content-Type": "text/html",
|
|
@@ -33997,7 +33997,7 @@ var require_websocket_server = __commonJS({
|
|
|
33997
33997
|
};
|
|
33998
33998
|
socket.once("finish", socket.destroy);
|
|
33999
33999
|
socket.end(
|
|
34000
|
-
`HTTP/1.1 ${code} ${
|
|
34000
|
+
`HTTP/1.1 ${code} ${http2.STATUS_CODES[code]}\r
|
|
34001
34001
|
` + Object.keys(headers).map((h) => `${h}: ${headers[h]}`).join("\r\n") + "\r\n\r\n" + message
|
|
34002
34002
|
);
|
|
34003
34003
|
}
|
|
@@ -35277,8 +35277,8 @@ var init_voice_session = __esm({
|
|
|
35277
35277
|
this.server.keepAliveTimeout = 0;
|
|
35278
35278
|
this.wss = new import_websocket_server.default({ server: this.server, path: "/ws" });
|
|
35279
35279
|
this.wss.on("connection", (ws, req) => this.handleWSConnection(ws, req));
|
|
35280
|
-
await new Promise((
|
|
35281
|
-
this.server.listen(port, "127.0.0.1", () =>
|
|
35280
|
+
await new Promise((resolve36, reject) => {
|
|
35281
|
+
this.server.listen(port, "127.0.0.1", () => resolve36());
|
|
35282
35282
|
this.server.on("error", reject);
|
|
35283
35283
|
});
|
|
35284
35284
|
try {
|
|
@@ -35496,7 +35496,7 @@ var init_voice_session = __esm({
|
|
|
35496
35496
|
}
|
|
35497
35497
|
// ── Cloudflared tunnel ────────────────────────────────────────────────
|
|
35498
35498
|
startCloudflared(port) {
|
|
35499
|
-
return new Promise((
|
|
35499
|
+
return new Promise((resolve36, reject) => {
|
|
35500
35500
|
const timeout = setTimeout(() => {
|
|
35501
35501
|
reject(new Error("Cloudflared tunnel start timeout (30s)"));
|
|
35502
35502
|
}, 3e4);
|
|
@@ -35514,7 +35514,7 @@ var init_voice_session = __esm({
|
|
|
35514
35514
|
if (urlMatch && !urlFound) {
|
|
35515
35515
|
urlFound = true;
|
|
35516
35516
|
clearTimeout(timeout);
|
|
35517
|
-
|
|
35517
|
+
resolve36(urlMatch[0]);
|
|
35518
35518
|
}
|
|
35519
35519
|
};
|
|
35520
35520
|
this.cloudflaredProcess.stdout?.on("data", handleOutput);
|
|
@@ -35554,13 +35554,13 @@ var init_voice_session = __esm({
|
|
|
35554
35554
|
}
|
|
35555
35555
|
// ── Helpers ───────────────────────────────────────────────────────────
|
|
35556
35556
|
findFreePort() {
|
|
35557
|
-
return new Promise((
|
|
35557
|
+
return new Promise((resolve36, reject) => {
|
|
35558
35558
|
const srv = createServer2();
|
|
35559
35559
|
srv.listen(0, "127.0.0.1", () => {
|
|
35560
35560
|
const addr = srv.address();
|
|
35561
35561
|
if (addr && typeof addr === "object") {
|
|
35562
35562
|
const port = addr.port;
|
|
35563
|
-
srv.close(() =>
|
|
35563
|
+
srv.close(() => resolve36(port));
|
|
35564
35564
|
} else {
|
|
35565
35565
|
srv.close(() => reject(new Error("Could not find free port")));
|
|
35566
35566
|
}
|
|
@@ -35683,8 +35683,8 @@ async function collectSystemMetricsAsync() {
|
|
|
35683
35683
|
vramUtilization: 0
|
|
35684
35684
|
};
|
|
35685
35685
|
try {
|
|
35686
|
-
const smi = await new Promise((
|
|
35687
|
-
exec("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) :
|
|
35686
|
+
const smi = await new Promise((resolve36, reject) => {
|
|
35687
|
+
exec("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve36(stdout));
|
|
35688
35688
|
});
|
|
35689
35689
|
const line = smi.trim().split("\n")[0];
|
|
35690
35690
|
if (line) {
|
|
@@ -35885,8 +35885,8 @@ var init_expose = __esm({
|
|
|
35885
35885
|
throw new Error("Gateway already running");
|
|
35886
35886
|
const port = await this.findFreePort();
|
|
35887
35887
|
this.server = this.createProxyServer(port);
|
|
35888
|
-
await new Promise((
|
|
35889
|
-
this.server.listen(port, "127.0.0.1", () =>
|
|
35888
|
+
await new Promise((resolve36, reject) => {
|
|
35889
|
+
this.server.listen(port, "127.0.0.1", () => resolve36());
|
|
35890
35890
|
this.server.on("error", reject);
|
|
35891
35891
|
});
|
|
35892
35892
|
let lastStartErr;
|
|
@@ -35951,8 +35951,8 @@ var init_expose = __esm({
|
|
|
35951
35951
|
this._cloudflaredPid = state.pid;
|
|
35952
35952
|
this._proxyPort = state.proxyPort;
|
|
35953
35953
|
this.server = this.createProxyServer(state.proxyPort);
|
|
35954
|
-
await new Promise((
|
|
35955
|
-
this.server.listen(state.proxyPort, "127.0.0.1", () =>
|
|
35954
|
+
await new Promise((resolve36, reject) => {
|
|
35955
|
+
this.server.listen(state.proxyPort, "127.0.0.1", () => resolve36());
|
|
35956
35956
|
this.server.on("error", reject);
|
|
35957
35957
|
});
|
|
35958
35958
|
this._stats.status = "active";
|
|
@@ -35977,8 +35977,8 @@ var init_expose = __esm({
|
|
|
35977
35977
|
}
|
|
35978
35978
|
this._cloudflaredPid = null;
|
|
35979
35979
|
if (this.server) {
|
|
35980
|
-
await new Promise((
|
|
35981
|
-
this.server.close(() =>
|
|
35980
|
+
await new Promise((resolve36) => {
|
|
35981
|
+
this.server.close(() => resolve36());
|
|
35982
35982
|
});
|
|
35983
35983
|
this.server = null;
|
|
35984
35984
|
}
|
|
@@ -36033,7 +36033,7 @@ var init_expose = __esm({
|
|
|
36033
36033
|
return;
|
|
36034
36034
|
}
|
|
36035
36035
|
if (url.pathname === "/v1/system/metrics" && req.method === "GET") {
|
|
36036
|
-
collectSystemMetricsAsync().then((
|
|
36036
|
+
collectSystemMetricsAsync().then((metrics2) => {
|
|
36037
36037
|
const gatewayStats = {
|
|
36038
36038
|
totalRequests: this._stats.totalRequests,
|
|
36039
36039
|
activeConnections: this._stats.activeConnections,
|
|
@@ -36054,7 +36054,7 @@ var init_expose = __esm({
|
|
|
36054
36054
|
}))
|
|
36055
36055
|
};
|
|
36056
36056
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
36057
|
-
res.end(JSON.stringify({ ...
|
|
36057
|
+
res.end(JSON.stringify({ ...metrics2, gateway: gatewayStats }));
|
|
36058
36058
|
}).catch(() => {
|
|
36059
36059
|
res.writeHead(500);
|
|
36060
36060
|
res.end("metrics error");
|
|
@@ -36347,7 +36347,7 @@ var init_expose = __esm({
|
|
|
36347
36347
|
_proxyPort = 0;
|
|
36348
36348
|
startCloudflared(port) {
|
|
36349
36349
|
this._proxyPort = port;
|
|
36350
|
-
return new Promise((
|
|
36350
|
+
return new Promise((resolve36, reject) => {
|
|
36351
36351
|
const TUNNEL_TIMEOUT_MS = 6e4;
|
|
36352
36352
|
const timeout = setTimeout(() => {
|
|
36353
36353
|
reject(new Error("Cloudflared tunnel start timeout (60s). Slow network? Try again."));
|
|
@@ -36391,7 +36391,7 @@ var init_expose = __esm({
|
|
|
36391
36391
|
this.cloudflaredProcess?.unref();
|
|
36392
36392
|
this.cloudflaredProcess?.stdout?.destroy();
|
|
36393
36393
|
this.cloudflaredProcess?.stderr?.destroy();
|
|
36394
|
-
|
|
36394
|
+
resolve36(urlMatch[0]);
|
|
36395
36395
|
}
|
|
36396
36396
|
};
|
|
36397
36397
|
this.cloudflaredProcess.stdout?.on("data", handleOutput);
|
|
@@ -36501,13 +36501,13 @@ ${this.formatConnectionInfo()}`);
|
|
|
36501
36501
|
}
|
|
36502
36502
|
// ── Helpers ─────────────────────────────────────────────────────────────
|
|
36503
36503
|
findFreePort() {
|
|
36504
|
-
return new Promise((
|
|
36504
|
+
return new Promise((resolve36, reject) => {
|
|
36505
36505
|
const srv = createServer3();
|
|
36506
36506
|
srv.listen(0, "127.0.0.1", () => {
|
|
36507
36507
|
const addr = srv.address();
|
|
36508
36508
|
if (addr && typeof addr === "object") {
|
|
36509
36509
|
const port = addr.port;
|
|
36510
|
-
srv.close(() =>
|
|
36510
|
+
srv.close(() => resolve36(port));
|
|
36511
36511
|
} else {
|
|
36512
36512
|
srv.close(() => reject(new Error("Could not find free port")));
|
|
36513
36513
|
}
|
|
@@ -37454,8 +37454,8 @@ var init_peer_mesh = __esm({
|
|
|
37454
37454
|
this.wss.on("connection", (ws, req) => {
|
|
37455
37455
|
this.handleInboundConnection(ws, req.url ?? "");
|
|
37456
37456
|
});
|
|
37457
|
-
await new Promise((
|
|
37458
|
-
this.server.listen(port, "127.0.0.1", () =>
|
|
37457
|
+
await new Promise((resolve36, reject) => {
|
|
37458
|
+
this.server.listen(port, "127.0.0.1", () => resolve36());
|
|
37459
37459
|
this.server.on("error", reject);
|
|
37460
37460
|
});
|
|
37461
37461
|
this.pingTimer = setInterval(() => this.pingAll(), PING_INTERVAL_MS);
|
|
@@ -37494,7 +37494,7 @@ var init_peer_mesh = __esm({
|
|
|
37494
37494
|
this.wss = null;
|
|
37495
37495
|
}
|
|
37496
37496
|
if (this.server) {
|
|
37497
|
-
await new Promise((
|
|
37497
|
+
await new Promise((resolve36) => this.server.close(() => resolve36()));
|
|
37498
37498
|
this.server = null;
|
|
37499
37499
|
}
|
|
37500
37500
|
this.emit("stopped");
|
|
@@ -37512,7 +37512,7 @@ var init_peer_mesh = __esm({
|
|
|
37512
37512
|
if (!wsUrl.includes("/p2p"))
|
|
37513
37513
|
wsUrl += "/p2p";
|
|
37514
37514
|
wsUrl += `?key=${encodeURIComponent(this._authKey)}`;
|
|
37515
|
-
return new Promise((
|
|
37515
|
+
return new Promise((resolve36, reject) => {
|
|
37516
37516
|
const ws = new import_websocket.default(wsUrl, { handshakeTimeout: 1e4 });
|
|
37517
37517
|
let resolved = false;
|
|
37518
37518
|
const timeout = setTimeout(() => {
|
|
@@ -37552,7 +37552,7 @@ var init_peer_mesh = __esm({
|
|
|
37552
37552
|
this.connections.set(peer.peerId, ws);
|
|
37553
37553
|
this.setupPeerHandlers(ws, peer.peerId);
|
|
37554
37554
|
this.emit("peer_connected", peer);
|
|
37555
|
-
|
|
37555
|
+
resolve36(peer);
|
|
37556
37556
|
} else {
|
|
37557
37557
|
this.handleMessage(msg, ws);
|
|
37558
37558
|
}
|
|
@@ -37601,19 +37601,19 @@ var init_peer_mesh = __esm({
|
|
|
37601
37601
|
* Send an inference request to a specific peer.
|
|
37602
37602
|
* Returns a promise that resolves when the response arrives.
|
|
37603
37603
|
*/
|
|
37604
|
-
async requestInference(peerId,
|
|
37604
|
+
async requestInference(peerId, request2, timeoutMs = 12e4) {
|
|
37605
37605
|
const ws = this.connections.get(peerId);
|
|
37606
37606
|
if (!ws || ws.readyState !== import_websocket.default.OPEN) {
|
|
37607
37607
|
throw new Error(`Peer ${peerId} not connected`);
|
|
37608
37608
|
}
|
|
37609
37609
|
const msgId = randomBytes14(8).toString("hex");
|
|
37610
|
-
return new Promise((
|
|
37610
|
+
return new Promise((resolve36, reject) => {
|
|
37611
37611
|
const timeout = setTimeout(() => {
|
|
37612
37612
|
this.pendingRequests.delete(msgId);
|
|
37613
37613
|
reject(new Error(`Inference timeout (${timeoutMs}ms)`));
|
|
37614
37614
|
}, timeoutMs);
|
|
37615
|
-
this.pendingRequests.set(msgId, { resolve:
|
|
37616
|
-
this.sendMsg(ws, "infer_request",
|
|
37615
|
+
this.pendingRequests.set(msgId, { resolve: resolve36, reject, timeout, chunks: [] });
|
|
37616
|
+
this.sendMsg(ws, "infer_request", request2, msgId);
|
|
37617
37617
|
});
|
|
37618
37618
|
}
|
|
37619
37619
|
// ── Inbound connection handling ─────────────────────────────────────────
|
|
@@ -37834,13 +37834,13 @@ var init_peer_mesh = __esm({
|
|
|
37834
37834
|
ws.send(JSON.stringify(msg));
|
|
37835
37835
|
}
|
|
37836
37836
|
findFreePort() {
|
|
37837
|
-
return new Promise((
|
|
37837
|
+
return new Promise((resolve36, reject) => {
|
|
37838
37838
|
const srv = createServer4();
|
|
37839
37839
|
srv.listen(0, "127.0.0.1", () => {
|
|
37840
37840
|
const addr = srv.address();
|
|
37841
37841
|
if (addr && typeof addr === "object") {
|
|
37842
37842
|
const port = addr.port;
|
|
37843
|
-
srv.close(() =>
|
|
37843
|
+
srv.close(() => resolve36(port));
|
|
37844
37844
|
} else {
|
|
37845
37845
|
srv.close(() => reject(new Error("Could not find free port")));
|
|
37846
37846
|
}
|
|
@@ -37955,7 +37955,7 @@ var init_inference_router = __esm({
|
|
|
37955
37955
|
}
|
|
37956
37956
|
}));
|
|
37957
37957
|
}
|
|
37958
|
-
const
|
|
37958
|
+
const request2 = {
|
|
37959
37959
|
model,
|
|
37960
37960
|
messages: redactedMessages,
|
|
37961
37961
|
tools: redactedTools,
|
|
@@ -37968,7 +37968,7 @@ var init_inference_router = __esm({
|
|
|
37968
37968
|
if (redactedCount > 0)
|
|
37969
37969
|
this._totalRedacted++;
|
|
37970
37970
|
try {
|
|
37971
|
-
const response = await this.mesh.requestInference(peer.peerId,
|
|
37971
|
+
const response = await this.mesh.requestInference(peer.peerId, request2, options?.timeoutMs ?? this.defaultTimeoutMs);
|
|
37972
37972
|
const injectedContent = this.vault.inject(response.content);
|
|
37973
37973
|
const injectedToolCalls = response.toolCalls?.map((tc) => ({
|
|
37974
37974
|
...tc,
|
|
@@ -38001,8 +38001,8 @@ var init_inference_router = __esm({
|
|
|
38001
38001
|
* The response text may contain placeholders from the requester's vault,
|
|
38002
38002
|
* which is fine — we don't have their secrets and don't need them.
|
|
38003
38003
|
*/
|
|
38004
|
-
async handleInboundRequest(
|
|
38005
|
-
for (const msg of
|
|
38004
|
+
async handleInboundRequest(request2, inferFn) {
|
|
38005
|
+
for (const msg of request2.messages) {
|
|
38006
38006
|
const found = this.vault.scan(msg.content);
|
|
38007
38007
|
if (found.length > 0) {
|
|
38008
38008
|
this.emit("leaked_secrets_detected", {
|
|
@@ -38011,7 +38011,7 @@ var init_inference_router = __esm({
|
|
|
38011
38011
|
});
|
|
38012
38012
|
}
|
|
38013
38013
|
}
|
|
38014
|
-
return inferFn(
|
|
38014
|
+
return inferFn(request2);
|
|
38015
38015
|
}
|
|
38016
38016
|
// ── Scoring ────────────────────────────────────────────────────────────
|
|
38017
38017
|
scoreRoute(peer, model) {
|
|
@@ -38470,26 +38470,26 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
|
|
|
38470
38470
|
async function fetchPeerModels(peerId, authKey) {
|
|
38471
38471
|
try {
|
|
38472
38472
|
const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
|
|
38473
|
-
const { existsSync:
|
|
38474
|
-
const { join:
|
|
38473
|
+
const { existsSync: existsSync54, readFileSync: readFileSync42 } = await import("node:fs");
|
|
38474
|
+
const { join: join74 } = await import("node:path");
|
|
38475
38475
|
const cwd4 = process.cwd();
|
|
38476
38476
|
const nexusTool = new NexusTool2(cwd4);
|
|
38477
38477
|
const nexusDir = nexusTool.getNexusDir();
|
|
38478
38478
|
let isLocalPeer = false;
|
|
38479
38479
|
try {
|
|
38480
|
-
const statusPath =
|
|
38481
|
-
if (
|
|
38482
|
-
const status = JSON.parse(
|
|
38480
|
+
const statusPath = join74(nexusDir, "status.json");
|
|
38481
|
+
if (existsSync54(statusPath)) {
|
|
38482
|
+
const status = JSON.parse(readFileSync42(statusPath, "utf8"));
|
|
38483
38483
|
if (status.peerId === peerId)
|
|
38484
38484
|
isLocalPeer = true;
|
|
38485
38485
|
}
|
|
38486
38486
|
} catch {
|
|
38487
38487
|
}
|
|
38488
38488
|
if (isLocalPeer) {
|
|
38489
|
-
const pricingPath =
|
|
38490
|
-
if (
|
|
38489
|
+
const pricingPath = join74(nexusDir, "pricing.json");
|
|
38490
|
+
if (existsSync54(pricingPath)) {
|
|
38491
38491
|
try {
|
|
38492
|
-
const pricing = JSON.parse(
|
|
38492
|
+
const pricing = JSON.parse(readFileSync42(pricingPath, "utf8"));
|
|
38493
38493
|
const localModels = (pricing.models || []).map((m) => ({
|
|
38494
38494
|
name: m.model || "unknown",
|
|
38495
38495
|
size: m.parameterSize || "",
|
|
@@ -38503,10 +38503,10 @@ async function fetchPeerModels(peerId, authKey) {
|
|
|
38503
38503
|
}
|
|
38504
38504
|
}
|
|
38505
38505
|
}
|
|
38506
|
-
const cachePath =
|
|
38507
|
-
if (
|
|
38506
|
+
const cachePath = join74(nexusDir, "peer-models-cache.json");
|
|
38507
|
+
if (existsSync54(cachePath)) {
|
|
38508
38508
|
try {
|
|
38509
|
-
const cache4 = JSON.parse(
|
|
38509
|
+
const cache4 = JSON.parse(readFileSync42(cachePath, "utf8"));
|
|
38510
38510
|
if (cache4.peerId === peerId && cache4.models?.length > 0) {
|
|
38511
38511
|
const age = Date.now() - new Date(cache4.cachedAt).getTime();
|
|
38512
38512
|
if (age < 5 * 60 * 1e3) {
|
|
@@ -38621,10 +38621,10 @@ async function fetchPeerModels(peerId, authKey) {
|
|
|
38621
38621
|
} catch {
|
|
38622
38622
|
}
|
|
38623
38623
|
if (isLocalPeer) {
|
|
38624
|
-
const pricingPath =
|
|
38625
|
-
if (
|
|
38624
|
+
const pricingPath = join74(nexusDir, "pricing.json");
|
|
38625
|
+
if (existsSync54(pricingPath)) {
|
|
38626
38626
|
try {
|
|
38627
|
-
const pricing = JSON.parse(
|
|
38627
|
+
const pricing = JSON.parse(readFileSync42(pricingPath, "utf8"));
|
|
38628
38628
|
return (pricing.models || []).map((m) => ({
|
|
38629
38629
|
name: m.model || "unknown",
|
|
38630
38630
|
size: m.parameterSize || "",
|
|
@@ -39762,12 +39762,12 @@ function calculateContextWindow(specs, modelSizeGB2, kvBytesPerToken, archMax) {
|
|
|
39762
39762
|
return { numCtx, label };
|
|
39763
39763
|
}
|
|
39764
39764
|
function ask(rl, question) {
|
|
39765
|
-
return new Promise((
|
|
39766
|
-
rl.question(question, (answer) =>
|
|
39765
|
+
return new Promise((resolve36) => {
|
|
39766
|
+
rl.question(question, (answer) => resolve36(answer.trim()));
|
|
39767
39767
|
});
|
|
39768
39768
|
}
|
|
39769
39769
|
function askSecret(rl, question) {
|
|
39770
|
-
return new Promise((
|
|
39770
|
+
return new Promise((resolve36) => {
|
|
39771
39771
|
process.stdout.write(question);
|
|
39772
39772
|
let secret = "";
|
|
39773
39773
|
const stdin = process.stdin;
|
|
@@ -39785,7 +39785,7 @@ function askSecret(rl, question) {
|
|
|
39785
39785
|
stdin.setRawMode(hadRawMode ?? false);
|
|
39786
39786
|
}
|
|
39787
39787
|
process.stdout.write("\n");
|
|
39788
|
-
|
|
39788
|
+
resolve36(secret.trim());
|
|
39789
39789
|
return;
|
|
39790
39790
|
} else if (c3 === "") {
|
|
39791
39791
|
stdin.removeListener("data", onData);
|
|
@@ -39793,7 +39793,7 @@ function askSecret(rl, question) {
|
|
|
39793
39793
|
stdin.setRawMode(hadRawMode ?? false);
|
|
39794
39794
|
}
|
|
39795
39795
|
process.stdout.write("\n");
|
|
39796
|
-
|
|
39796
|
+
resolve36("");
|
|
39797
39797
|
return;
|
|
39798
39798
|
} else if (c3 === "\x7F" || c3 === "\b") {
|
|
39799
39799
|
if (secret.length > 0) {
|
|
@@ -40028,7 +40028,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
|
|
|
40028
40028
|
return false;
|
|
40029
40029
|
}
|
|
40030
40030
|
for (let i = 0; i < 5; i++) {
|
|
40031
|
-
await new Promise((
|
|
40031
|
+
await new Promise((resolve36) => setTimeout(resolve36, 2e3));
|
|
40032
40032
|
try {
|
|
40033
40033
|
const resp = await fetch(`${backendUrl}/api/tags`, {
|
|
40034
40034
|
signal: AbortSignal.timeout(3e3)
|
|
@@ -40489,7 +40489,7 @@ async function doSetup(config, rl) {
|
|
|
40489
40489
|
try {
|
|
40490
40490
|
const child = spawn19("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
40491
40491
|
child.unref();
|
|
40492
|
-
await new Promise((
|
|
40492
|
+
await new Promise((resolve36) => setTimeout(resolve36, 3e3));
|
|
40493
40493
|
try {
|
|
40494
40494
|
models = await fetchOllamaModels(config.backendUrl);
|
|
40495
40495
|
process.stdout.write(` ${c2.green("\u2714")} Ollama is running.
|
|
@@ -40517,7 +40517,7 @@ async function doSetup(config, rl) {
|
|
|
40517
40517
|
try {
|
|
40518
40518
|
const child = spawn19("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
40519
40519
|
child.unref();
|
|
40520
|
-
await new Promise((
|
|
40520
|
+
await new Promise((resolve36) => setTimeout(resolve36, 3e3));
|
|
40521
40521
|
try {
|
|
40522
40522
|
models = await fetchOllamaModels(config.backendUrl);
|
|
40523
40523
|
process.stdout.write(` ${c2.green("\u2714")} Ollama is running.
|
|
@@ -41506,7 +41506,7 @@ function tuiSelect(opts) {
|
|
|
41506
41506
|
const maxVisible = opts.maxVisible ?? Math.max(3, contentArea - selectChrome);
|
|
41507
41507
|
let scrollOffset = 0;
|
|
41508
41508
|
let lastRenderedLines = 0;
|
|
41509
|
-
return new Promise((
|
|
41509
|
+
return new Promise((resolve36) => {
|
|
41510
41510
|
const stdin = process.stdin;
|
|
41511
41511
|
const hadRawMode = stdin.isRaw;
|
|
41512
41512
|
const savedRlListeners = [];
|
|
@@ -41681,7 +41681,7 @@ function tuiSelect(opts) {
|
|
|
41681
41681
|
if (!isSkippable(itemIdx) && matchSet.has(itemIdx)) {
|
|
41682
41682
|
cursor = itemIdx;
|
|
41683
41683
|
cleanup();
|
|
41684
|
-
|
|
41684
|
+
resolve36({ confirmed: true, key: items[cursor].key, index: cursor });
|
|
41685
41685
|
return;
|
|
41686
41686
|
} else if (!isSkippable(itemIdx)) {
|
|
41687
41687
|
cursor = itemIdx;
|
|
@@ -41757,7 +41757,7 @@ function tuiSelect(opts) {
|
|
|
41757
41757
|
items.splice(deletedIdx, 1);
|
|
41758
41758
|
if (items.length === 0) {
|
|
41759
41759
|
cleanup();
|
|
41760
|
-
|
|
41760
|
+
resolve36({ confirmed: false, key: null, index: -1 });
|
|
41761
41761
|
return;
|
|
41762
41762
|
}
|
|
41763
41763
|
updateFilter();
|
|
@@ -41850,7 +41850,7 @@ function tuiSelect(opts) {
|
|
|
41850
41850
|
done: () => render(),
|
|
41851
41851
|
resolve: (result) => {
|
|
41852
41852
|
cleanup();
|
|
41853
|
-
|
|
41853
|
+
resolve36(result);
|
|
41854
41854
|
},
|
|
41855
41855
|
getInput: (prompt, prefill) => getInputFromUser(prompt, prefill),
|
|
41856
41856
|
render: () => render(),
|
|
@@ -41863,7 +41863,7 @@ function tuiSelect(opts) {
|
|
|
41863
41863
|
return;
|
|
41864
41864
|
}
|
|
41865
41865
|
cleanup();
|
|
41866
|
-
|
|
41866
|
+
resolve36({ confirmed: true, key: items[cursor].key, index: cursor });
|
|
41867
41867
|
}
|
|
41868
41868
|
} else if (seq === "\x1B" || seq === "\x1B\x1B") {
|
|
41869
41869
|
if (filter) {
|
|
@@ -41876,14 +41876,14 @@ function tuiSelect(opts) {
|
|
|
41876
41876
|
render();
|
|
41877
41877
|
} else if (hasBreadcrumbs) {
|
|
41878
41878
|
cleanup();
|
|
41879
|
-
|
|
41879
|
+
resolve36({ confirmed: false, key: "__back__", index: cursor });
|
|
41880
41880
|
} else {
|
|
41881
41881
|
cleanup();
|
|
41882
|
-
|
|
41882
|
+
resolve36({ confirmed: false, key: null, index: cursor });
|
|
41883
41883
|
}
|
|
41884
41884
|
} else if (seq === "") {
|
|
41885
41885
|
cleanup();
|
|
41886
|
-
|
|
41886
|
+
resolve36({ confirmed: false, key: null, index: cursor });
|
|
41887
41887
|
} else if (seq === "\x7F" || seq === "\b") {
|
|
41888
41888
|
if (filter.length > 0) {
|
|
41889
41889
|
filter = filter.slice(0, -1);
|
|
@@ -41897,7 +41897,7 @@ function tuiSelect(opts) {
|
|
|
41897
41897
|
render();
|
|
41898
41898
|
} else if (hasBreadcrumbs) {
|
|
41899
41899
|
cleanup();
|
|
41900
|
-
|
|
41900
|
+
resolve36({ confirmed: false, key: "__back__", index: cursor });
|
|
41901
41901
|
}
|
|
41902
41902
|
} else if (seq.length === 1 && seq.charCodeAt(0) >= 32 && seq.charCodeAt(0) < 127) {
|
|
41903
41903
|
if (opts.onCustomKey && !isSkippable(cursor) && matchSet.has(cursor)) {
|
|
@@ -41905,7 +41905,7 @@ function tuiSelect(opts) {
|
|
|
41905
41905
|
done: () => render(),
|
|
41906
41906
|
resolve: (result) => {
|
|
41907
41907
|
cleanup();
|
|
41908
|
-
|
|
41908
|
+
resolve36(result);
|
|
41909
41909
|
},
|
|
41910
41910
|
getInput: (prompt, prefill) => getInputFromUser(prompt, prefill),
|
|
41911
41911
|
render: () => render(),
|
|
@@ -42447,12 +42447,12 @@ function stopNeovimMode() {
|
|
|
42447
42447
|
} catch {
|
|
42448
42448
|
}
|
|
42449
42449
|
const s = _state;
|
|
42450
|
-
return new Promise((
|
|
42450
|
+
return new Promise((resolve36) => {
|
|
42451
42451
|
setTimeout(() => {
|
|
42452
42452
|
if (s && !s.cleanedUp) {
|
|
42453
42453
|
doCleanup(s);
|
|
42454
42454
|
}
|
|
42455
|
-
|
|
42455
|
+
resolve36();
|
|
42456
42456
|
}, 300);
|
|
42457
42457
|
});
|
|
42458
42458
|
}
|
|
@@ -45237,7 +45237,7 @@ var init_voice = __esm({
|
|
|
45237
45237
|
this.speaking = false;
|
|
45238
45238
|
}
|
|
45239
45239
|
sleep(ms) {
|
|
45240
|
-
return new Promise((
|
|
45240
|
+
return new Promise((resolve36) => setTimeout(resolve36, ms));
|
|
45241
45241
|
}
|
|
45242
45242
|
// -------------------------------------------------------------------------
|
|
45243
45243
|
// Synthesis pipeline
|
|
@@ -45503,7 +45503,7 @@ var init_voice = __esm({
|
|
|
45503
45503
|
const cmd = this.getPlayCommand(path);
|
|
45504
45504
|
if (!cmd)
|
|
45505
45505
|
return;
|
|
45506
|
-
return new Promise((
|
|
45506
|
+
return new Promise((resolve36) => {
|
|
45507
45507
|
const child = nodeSpawn(cmd[0], cmd.slice(1), {
|
|
45508
45508
|
stdio: "ignore",
|
|
45509
45509
|
detached: false
|
|
@@ -45512,12 +45512,12 @@ var init_voice = __esm({
|
|
|
45512
45512
|
child.on("close", () => {
|
|
45513
45513
|
if (this.currentPlayback === child)
|
|
45514
45514
|
this.currentPlayback = null;
|
|
45515
|
-
|
|
45515
|
+
resolve36();
|
|
45516
45516
|
});
|
|
45517
45517
|
child.on("error", () => {
|
|
45518
45518
|
if (this.currentPlayback === child)
|
|
45519
45519
|
this.currentPlayback = null;
|
|
45520
|
-
|
|
45520
|
+
resolve36();
|
|
45521
45521
|
});
|
|
45522
45522
|
setTimeout(() => {
|
|
45523
45523
|
if (this.currentPlayback === child) {
|
|
@@ -45527,7 +45527,7 @@ var init_voice = __esm({
|
|
|
45527
45527
|
}
|
|
45528
45528
|
this.currentPlayback = null;
|
|
45529
45529
|
}
|
|
45530
|
-
|
|
45530
|
+
resolve36();
|
|
45531
45531
|
}, 15e3);
|
|
45532
45532
|
});
|
|
45533
45533
|
}
|
|
@@ -45602,7 +45602,7 @@ var init_voice = __esm({
|
|
|
45602
45602
|
/** Non-blocking shell execution — async alternative to execSync.
|
|
45603
45603
|
* Returns stdout string on exit 0, rejects otherwise. */
|
|
45604
45604
|
asyncShell(command, timeoutMs = 3e4) {
|
|
45605
|
-
return new Promise((
|
|
45605
|
+
return new Promise((resolve36, reject) => {
|
|
45606
45606
|
const proc = nodeSpawn("sh", ["-c", command], {
|
|
45607
45607
|
stdio: ["ignore", "pipe", "pipe"],
|
|
45608
45608
|
cwd: tmpdir9()
|
|
@@ -45623,7 +45623,7 @@ var init_voice = __esm({
|
|
|
45623
45623
|
proc.on("close", (code) => {
|
|
45624
45624
|
clearTimeout(timer);
|
|
45625
45625
|
if (code === 0)
|
|
45626
|
-
|
|
45626
|
+
resolve36(stdout.trim());
|
|
45627
45627
|
else
|
|
45628
45628
|
reject(new Error(stderr.slice(0, 300) || `Exit code ${code}`));
|
|
45629
45629
|
});
|
|
@@ -46115,7 +46115,7 @@ if __name__ == '__main__':
|
|
|
46115
46115
|
const venvPy = luxttsVenvPy();
|
|
46116
46116
|
if (!existsSync41(venvPy))
|
|
46117
46117
|
return false;
|
|
46118
|
-
return new Promise((
|
|
46118
|
+
return new Promise((resolve36) => {
|
|
46119
46119
|
const env = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
|
|
46120
46120
|
const daemon = nodeSpawn(venvPy, [luxttsInferScript()], {
|
|
46121
46121
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -46134,7 +46134,7 @@ if __name__ == '__main__':
|
|
|
46134
46134
|
try {
|
|
46135
46135
|
const msg = JSON.parse(line);
|
|
46136
46136
|
if (msg.type === "ready") {
|
|
46137
|
-
|
|
46137
|
+
resolve36(true);
|
|
46138
46138
|
} else if (msg.type === "result" || msg.type === "error") {
|
|
46139
46139
|
const pending = this._luxttsPending.get(msg.id);
|
|
46140
46140
|
if (pending) {
|
|
@@ -46158,25 +46158,25 @@ if __name__ == '__main__':
|
|
|
46158
46158
|
});
|
|
46159
46159
|
daemon.on("error", () => {
|
|
46160
46160
|
this._luxttsDaemon = null;
|
|
46161
|
-
|
|
46161
|
+
resolve36(false);
|
|
46162
46162
|
});
|
|
46163
46163
|
setTimeout(() => {
|
|
46164
46164
|
if (this._luxttsDaemon === daemon && !this._luxttsPending.has("__ready__")) {
|
|
46165
|
-
|
|
46165
|
+
resolve36(false);
|
|
46166
46166
|
}
|
|
46167
46167
|
}, 6e4);
|
|
46168
46168
|
});
|
|
46169
46169
|
}
|
|
46170
46170
|
/** Send a request to the LuxTTS daemon and await the response */
|
|
46171
46171
|
luxttsRequest(req) {
|
|
46172
|
-
return new Promise((
|
|
46172
|
+
return new Promise((resolve36, reject) => {
|
|
46173
46173
|
if (!this._luxttsDaemon || this._luxttsDaemon.killed) {
|
|
46174
46174
|
reject(new Error("LuxTTS daemon not running"));
|
|
46175
46175
|
return;
|
|
46176
46176
|
}
|
|
46177
46177
|
const id = `req_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
46178
46178
|
req.id = id;
|
|
46179
|
-
this._luxttsPending.set(id, { resolve:
|
|
46179
|
+
this._luxttsPending.set(id, { resolve: resolve36, reject });
|
|
46180
46180
|
this._luxttsDaemon.stdin.write(JSON.stringify(req) + "\n");
|
|
46181
46181
|
setTimeout(() => {
|
|
46182
46182
|
if (this._luxttsPending.has(id)) {
|
|
@@ -47641,8 +47641,8 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47641
47641
|
writeFileSync19(jwtFile, JSON.stringify(jwtPayload, null, 2));
|
|
47642
47642
|
renderInfo(`Launching fortemi-react from ${fDir}...`);
|
|
47643
47643
|
try {
|
|
47644
|
-
const { spawn:
|
|
47645
|
-
const child =
|
|
47644
|
+
const { spawn: spawn23 } = __require("node:child_process");
|
|
47645
|
+
const child = spawn23("npx", ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"], {
|
|
47646
47646
|
cwd: join58(fDir, "apps", "standalone"),
|
|
47647
47647
|
stdio: "ignore",
|
|
47648
47648
|
detached: true,
|
|
@@ -49621,12 +49621,12 @@ async function handleVoiceMenu(ctx, save, hasLocal) {
|
|
|
49621
49621
|
continue;
|
|
49622
49622
|
}
|
|
49623
49623
|
const { basename: basename18, join: pathJoin } = await import("node:path");
|
|
49624
|
-
const { copyFileSync: copyFileSync2, mkdirSync:
|
|
49624
|
+
const { copyFileSync: copyFileSync2, mkdirSync: mkdirSync28, existsSync: exists } = await import("node:fs");
|
|
49625
49625
|
const { homedir: homedir19 } = await import("node:os");
|
|
49626
49626
|
const modelName = basename18(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
49627
49627
|
const destDir = pathJoin(homedir19(), ".open-agents", "voice", "models", modelName);
|
|
49628
49628
|
if (!exists(destDir))
|
|
49629
|
-
|
|
49629
|
+
mkdirSync28(destDir, { recursive: true });
|
|
49630
49630
|
copyFileSync2(onnxDrop.path, pathJoin(destDir, "model.onnx"));
|
|
49631
49631
|
copyFileSync2(jsonDrop.path, pathJoin(destDir, "config.json"));
|
|
49632
49632
|
const { registerCustomOnnxModel: registerCustomOnnxModel2 } = await Promise.resolve().then(() => (init_voice(), voice_exports));
|
|
@@ -50304,11 +50304,11 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
|
|
|
50304
50304
|
const models = await fetchModels(peerUrl, authKey);
|
|
50305
50305
|
if (models.length > 0) {
|
|
50306
50306
|
try {
|
|
50307
|
-
const { writeFileSync:
|
|
50308
|
-
const { join:
|
|
50309
|
-
const cachePath =
|
|
50310
|
-
|
|
50311
|
-
|
|
50307
|
+
const { writeFileSync: writeFileSync27, mkdirSync: mkdirSync28 } = await import("node:fs");
|
|
50308
|
+
const { join: join74, dirname: dirname23 } = await import("node:path");
|
|
50309
|
+
const cachePath = join74(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
|
|
50310
|
+
mkdirSync28(dirname23(cachePath), { recursive: true });
|
|
50311
|
+
writeFileSync27(cachePath, JSON.stringify({
|
|
50312
50312
|
peerId,
|
|
50313
50313
|
cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
50314
50314
|
models: models.map((m) => ({ name: m.name, size: m.size, parameterSize: m.parameterSize }))
|
|
@@ -50459,8 +50459,8 @@ Environment="OLLAMA_NUM_PARALLEL=${n}"
|
|
|
50459
50459
|
}
|
|
50460
50460
|
await new Promise((r) => setTimeout(r, 1e3));
|
|
50461
50461
|
process.env.OLLAMA_NUM_PARALLEL = String(n);
|
|
50462
|
-
const { spawn:
|
|
50463
|
-
const child =
|
|
50462
|
+
const { spawn: spawn23 } = await import("node:child_process");
|
|
50463
|
+
const child = spawn23("ollama", ["serve"], {
|
|
50464
50464
|
stdio: "ignore",
|
|
50465
50465
|
detached: true,
|
|
50466
50466
|
env: { ...process.env, OLLAMA_NUM_PARALLEL: String(n) }
|
|
@@ -50505,19 +50505,19 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
50505
50505
|
}
|
|
50506
50506
|
let currentVersion = "0.0.0";
|
|
50507
50507
|
try {
|
|
50508
|
-
const { createRequire:
|
|
50509
|
-
const { fileURLToPath:
|
|
50510
|
-
const { dirname:
|
|
50511
|
-
const { existsSync:
|
|
50512
|
-
const req =
|
|
50513
|
-
const thisDir =
|
|
50508
|
+
const { createRequire: createRequire5 } = await import("node:module");
|
|
50509
|
+
const { fileURLToPath: fileURLToPath15 } = await import("node:url");
|
|
50510
|
+
const { dirname: dirname23, join: join74 } = await import("node:path");
|
|
50511
|
+
const { existsSync: existsSync54 } = await import("node:fs");
|
|
50512
|
+
const req = createRequire5(import.meta.url);
|
|
50513
|
+
const thisDir = dirname23(fileURLToPath15(import.meta.url));
|
|
50514
50514
|
const candidates = [
|
|
50515
|
-
|
|
50516
|
-
|
|
50517
|
-
|
|
50515
|
+
join74(thisDir, "..", "package.json"),
|
|
50516
|
+
join74(thisDir, "..", "..", "package.json"),
|
|
50517
|
+
join74(thisDir, "..", "..", "..", "package.json")
|
|
50518
50518
|
];
|
|
50519
50519
|
for (const pkgPath of candidates) {
|
|
50520
|
-
if (
|
|
50520
|
+
if (existsSync54(pkgPath)) {
|
|
50521
50521
|
const pkg = req(pkgPath);
|
|
50522
50522
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
50523
50523
|
currentVersion = pkg.version ?? "0.0.0";
|
|
@@ -50711,11 +50711,11 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
50711
50711
|
const targetVersion = info?.latestVersion ?? currentVersion;
|
|
50712
50712
|
const installOverlay = startInstallOverlay(targetVersion);
|
|
50713
50713
|
let installError = "";
|
|
50714
|
-
const runInstall2 = (cmd) => new Promise((
|
|
50714
|
+
const runInstall2 = (cmd) => new Promise((resolve36) => {
|
|
50715
50715
|
const child = exec4(cmd, { timeout: 18e4 }, (err, _stdout, stderr) => {
|
|
50716
50716
|
if (err)
|
|
50717
50717
|
installError = (stderr || err.message || "").trim();
|
|
50718
|
-
|
|
50718
|
+
resolve36(!err);
|
|
50719
50719
|
});
|
|
50720
50720
|
child.stdout?.on("data", (chunk) => {
|
|
50721
50721
|
const text = String(chunk);
|
|
@@ -50809,8 +50809,8 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
50809
50809
|
}
|
|
50810
50810
|
if (doRebuild) {
|
|
50811
50811
|
installOverlay.setStatus("Rebuilding native modules...");
|
|
50812
|
-
await new Promise((
|
|
50813
|
-
const child = exec4(`${sudoPrefix}npm rebuild -g open-agents-ai 2>/dev/null || true`, { timeout: 12e4 }, () =>
|
|
50812
|
+
await new Promise((resolve36) => {
|
|
50813
|
+
const child = exec4(`${sudoPrefix}npm rebuild -g open-agents-ai 2>/dev/null || true`, { timeout: 12e4 }, () => resolve36(true));
|
|
50814
50814
|
child.stdout?.resume();
|
|
50815
50815
|
child.stderr?.resume();
|
|
50816
50816
|
});
|
|
@@ -50842,8 +50842,8 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
50842
50842
|
const venvPip2 = isWin2 ? pathJoin(venvDir, "Scripts", "pip.exe") : pathJoin(venvDir, "bin", "pip");
|
|
50843
50843
|
if (fsExists(venvPip2)) {
|
|
50844
50844
|
installOverlay.setStatus("Upgrading Python packages...");
|
|
50845
|
-
await new Promise((
|
|
50846
|
-
const child = exec4(`"${venvPip2}" install --upgrade moondream-station pytesseract Pillow opencv-python-headless numpy 2>/dev/null || true`, { timeout: 3e5 }, (err) =>
|
|
50845
|
+
await new Promise((resolve36) => {
|
|
50846
|
+
const child = exec4(`"${venvPip2}" install --upgrade moondream-station pytesseract Pillow opencv-python-headless numpy 2>/dev/null || true`, { timeout: 3e5 }, (err) => resolve36(!err));
|
|
50847
50847
|
child.stdout?.resume();
|
|
50848
50848
|
child.stderr?.resume();
|
|
50849
50849
|
});
|
|
@@ -51239,16 +51239,16 @@ async function showExposeDashboard(gateway, rl, ctx) {
|
|
|
51239
51239
|
renderDashboard();
|
|
51240
51240
|
}, 1e3);
|
|
51241
51241
|
let stopGateway = false;
|
|
51242
|
-
await new Promise((
|
|
51242
|
+
await new Promise((resolve36) => {
|
|
51243
51243
|
const onData = (data) => {
|
|
51244
51244
|
const key = data.toString();
|
|
51245
51245
|
if (key === "q" || key === "Q" || key === "\x1B" || key === "") {
|
|
51246
|
-
|
|
51246
|
+
resolve36();
|
|
51247
51247
|
return;
|
|
51248
51248
|
}
|
|
51249
51249
|
if (key === "s" || key === "S") {
|
|
51250
51250
|
stopGateway = true;
|
|
51251
|
-
|
|
51251
|
+
resolve36();
|
|
51252
51252
|
return;
|
|
51253
51253
|
}
|
|
51254
51254
|
if (key === "c" || key === "C") {
|
|
@@ -51299,8 +51299,8 @@ async function showExposeDashboard(gateway, rl, ctx) {
|
|
|
51299
51299
|
process.stdout.write("\x1B[?1002h\x1B[?1006h");
|
|
51300
51300
|
}
|
|
51301
51301
|
};
|
|
51302
|
-
const origResolve =
|
|
51303
|
-
|
|
51302
|
+
const origResolve = resolve36;
|
|
51303
|
+
resolve36 = (() => {
|
|
51304
51304
|
cleanup();
|
|
51305
51305
|
origResolve();
|
|
51306
51306
|
});
|
|
@@ -58562,17 +58562,17 @@ var init_braille_spinner = __esm({
|
|
|
58562
58562
|
* Update real-time metrics that drive animation dynamics.
|
|
58563
58563
|
* Call frequently (e.g. on each metrics update / stream tick).
|
|
58564
58564
|
*/
|
|
58565
|
-
setMetrics(
|
|
58566
|
-
if (
|
|
58567
|
-
this._metrics.contextPct =
|
|
58568
|
-
if (
|
|
58569
|
-
this._metrics.tokenRate =
|
|
58570
|
-
if (
|
|
58571
|
-
this._metrics.isStreaming =
|
|
58572
|
-
if (
|
|
58573
|
-
this._metrics.snr = Math.max(0, Math.min(1,
|
|
58574
|
-
if (
|
|
58575
|
-
this._metrics.isDreaming =
|
|
58565
|
+
setMetrics(metrics2) {
|
|
58566
|
+
if (metrics2.contextPct !== void 0)
|
|
58567
|
+
this._metrics.contextPct = metrics2.contextPct;
|
|
58568
|
+
if (metrics2.tokenRate !== void 0)
|
|
58569
|
+
this._metrics.tokenRate = metrics2.tokenRate;
|
|
58570
|
+
if (metrics2.isStreaming !== void 0)
|
|
58571
|
+
this._metrics.isStreaming = metrics2.isStreaming;
|
|
58572
|
+
if (metrics2.snr !== void 0)
|
|
58573
|
+
this._metrics.snr = Math.max(0, Math.min(1, metrics2.snr));
|
|
58574
|
+
if (metrics2.isDreaming !== void 0)
|
|
58575
|
+
this._metrics.isDreaming = metrics2.isDreaming;
|
|
58576
58576
|
}
|
|
58577
58577
|
/**
|
|
58578
58578
|
* Render the current animation frame as an ANSI-colored string.
|
|
@@ -58723,8 +58723,8 @@ async function collectNetworkMetrics() {
|
|
|
58723
58723
|
}
|
|
58724
58724
|
if (plat === "darwin") {
|
|
58725
58725
|
try {
|
|
58726
|
-
const output = await new Promise((
|
|
58727
|
-
exec3("netstat -ib 2>/dev/null | head -30", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) :
|
|
58726
|
+
const output = await new Promise((resolve36, reject) => {
|
|
58727
|
+
exec3("netstat -ib 2>/dev/null | head -30", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve36(stdout));
|
|
58728
58728
|
});
|
|
58729
58729
|
let rxBytes = 0, txBytes = 0;
|
|
58730
58730
|
for (const line of output.split("\n")) {
|
|
@@ -58758,8 +58758,8 @@ async function collectGpuMetrics() {
|
|
|
58758
58758
|
if (_nvidiaSmiAvailable === false)
|
|
58759
58759
|
return noGpu;
|
|
58760
58760
|
try {
|
|
58761
|
-
const smi = await new Promise((
|
|
58762
|
-
exec3("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) :
|
|
58761
|
+
const smi = await new Promise((resolve36, reject) => {
|
|
58762
|
+
exec3("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve36(stdout));
|
|
58763
58763
|
});
|
|
58764
58764
|
_nvidiaSmiAvailable = true;
|
|
58765
58765
|
const line = smi.trim().split("\n")[0];
|
|
@@ -59674,8 +59674,8 @@ var init_status_bar = __esm({
|
|
|
59674
59674
|
* Forward metrics directly to the braille spinner.
|
|
59675
59675
|
* Used for SNR, dream mode, and other neural activity indicators.
|
|
59676
59676
|
*/
|
|
59677
|
-
setBrailleMetrics(
|
|
59678
|
-
this._brailleSpinner.setMetrics(
|
|
59677
|
+
setBrailleMetrics(metrics2) {
|
|
59678
|
+
this._brailleSpinner.setMetrics(metrics2);
|
|
59679
59679
|
}
|
|
59680
59680
|
/** Context window size to display. Can be updated if model changes. */
|
|
59681
59681
|
setContextWindowSize(size) {
|
|
@@ -59829,7 +59829,7 @@ var init_status_bar = __esm({
|
|
|
59829
59829
|
/** Legacy remote metrics polling timer (for peer/HTTP polling) */
|
|
59830
59830
|
_remoteMetricsTimer = null;
|
|
59831
59831
|
/** Update remote host system metrics (from polling /v1/system/metrics) */
|
|
59832
|
-
setRemoteMetrics(
|
|
59832
|
+
setRemoteMetrics(metrics2) {
|
|
59833
59833
|
if (!this._metricsCollector.isActive || this._metricsCollector.source !== "remote") {
|
|
59834
59834
|
this._metricsCollector.startRemote((m) => {
|
|
59835
59835
|
this._unifiedMetrics = m;
|
|
@@ -59838,17 +59838,17 @@ var init_status_bar = __esm({
|
|
|
59838
59838
|
});
|
|
59839
59839
|
}
|
|
59840
59840
|
this._metricsCollector.pushRemoteMetrics({
|
|
59841
|
-
cpuUtil:
|
|
59842
|
-
cpuCores:
|
|
59843
|
-
cpuModel:
|
|
59844
|
-
gpuUtil:
|
|
59845
|
-
gpuName:
|
|
59846
|
-
vramUtil:
|
|
59847
|
-
vramUsedMB:
|
|
59848
|
-
vramTotalMB:
|
|
59849
|
-
memUtil:
|
|
59850
|
-
memTotalGB:
|
|
59851
|
-
memUsedGB:
|
|
59841
|
+
cpuUtil: metrics2.cpuUtil,
|
|
59842
|
+
cpuCores: metrics2.cpuCores ?? 0,
|
|
59843
|
+
cpuModel: metrics2.cpuModel ?? "",
|
|
59844
|
+
gpuUtil: metrics2.gpuUtil,
|
|
59845
|
+
gpuName: metrics2.gpuName,
|
|
59846
|
+
vramUtil: metrics2.vramUtil,
|
|
59847
|
+
vramUsedMB: metrics2.vramUsedMB ?? 0,
|
|
59848
|
+
vramTotalMB: metrics2.vramTotalMB ?? 0,
|
|
59849
|
+
memUtil: metrics2.memUtil,
|
|
59850
|
+
memTotalGB: metrics2.memTotalGB ?? 0,
|
|
59851
|
+
memUsedGB: metrics2.memUsedGB ?? 0
|
|
59852
59852
|
});
|
|
59853
59853
|
}
|
|
59854
59854
|
/** Clear remote metrics and switch back to local collection */
|
|
@@ -63130,14 +63130,14 @@ Review its full output in the [${id}] tab or via full_sub_agent(action='output',
|
|
|
63130
63130
|
renderInfo(msg);
|
|
63131
63131
|
statusBar.endContentWrite();
|
|
63132
63132
|
}
|
|
63133
|
-
}, () => new Promise((
|
|
63133
|
+
}, () => new Promise((resolve36) => {
|
|
63134
63134
|
depSudoPromptPending = true;
|
|
63135
63135
|
depSudoResolver = (pw) => {
|
|
63136
63136
|
depSudoPromptPending = false;
|
|
63137
63137
|
depSudoResolver = null;
|
|
63138
63138
|
if (pw)
|
|
63139
63139
|
sessionSudoPassword = pw;
|
|
63140
|
-
|
|
63140
|
+
resolve36(pw);
|
|
63141
63141
|
};
|
|
63142
63142
|
const pwPrompt1 = ` ${c2.bold(c2.yellow("\u{1F511} Password needed for dependency install:"))}
|
|
63143
63143
|
`;
|
|
@@ -66659,7 +66659,7 @@ async function indexRepoCommand(opts, _config) {
|
|
|
66659
66659
|
});
|
|
66660
66660
|
const spinner = new Spinner("Scanning files ...");
|
|
66661
66661
|
spinner.start();
|
|
66662
|
-
const
|
|
66662
|
+
const startedAt2 = Date.now();
|
|
66663
66663
|
let files;
|
|
66664
66664
|
try {
|
|
66665
66665
|
files = await indexer.index();
|
|
@@ -66668,7 +66668,7 @@ async function indexRepoCommand(opts, _config) {
|
|
|
66668
66668
|
printError(err instanceof Error ? err.message : String(err));
|
|
66669
66669
|
process.exit(1);
|
|
66670
66670
|
}
|
|
66671
|
-
const elapsed = Date.now() -
|
|
66671
|
+
const elapsed = Date.now() - startedAt2;
|
|
66672
66672
|
spinner.succeed(`Indexed ${files.length} files in ${formatDuration(elapsed)}`);
|
|
66673
66673
|
printSection("Index Summary");
|
|
66674
66674
|
printKeyValue("Repository", repoRoot, 2);
|
|
@@ -67085,12 +67085,929 @@ var init_config3 = __esm({
|
|
|
67085
67085
|
}
|
|
67086
67086
|
});
|
|
67087
67087
|
|
|
67088
|
+
// packages/cli/dist/api/serve.js
|
|
67089
|
+
import * as http from "node:http";
|
|
67090
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
67091
|
+
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
67092
|
+
import { dirname as dirname21, join as join71, resolve as resolve35 } from "node:path";
|
|
67093
|
+
import { spawn as spawn21 } from "node:child_process";
|
|
67094
|
+
import { mkdirSync as mkdirSync26, writeFileSync as writeFileSync25, readFileSync as readFileSync41, readdirSync as readdirSync21, existsSync as existsSync53 } from "node:fs";
|
|
67095
|
+
import { randomBytes as randomBytes16 } from "node:crypto";
|
|
67096
|
+
function getVersion4() {
|
|
67097
|
+
try {
|
|
67098
|
+
const require2 = createRequire3(import.meta.url);
|
|
67099
|
+
const pkgPath = join71(dirname21(fileURLToPath13(import.meta.url)), "..", "..", "package.json");
|
|
67100
|
+
const pkg = require2(pkgPath);
|
|
67101
|
+
return pkg.version;
|
|
67102
|
+
} catch {
|
|
67103
|
+
return "0.0.0";
|
|
67104
|
+
}
|
|
67105
|
+
}
|
|
67106
|
+
function recordMetric(method, path, status) {
|
|
67107
|
+
const key = `${method}|${path}|${status}`;
|
|
67108
|
+
const existing = metrics.requests.get(key);
|
|
67109
|
+
if (existing) {
|
|
67110
|
+
existing.count++;
|
|
67111
|
+
} else {
|
|
67112
|
+
metrics.requests.set(key, { method, path, status, count: 1 });
|
|
67113
|
+
}
|
|
67114
|
+
}
|
|
67115
|
+
function formatMetrics() {
|
|
67116
|
+
const lines = [];
|
|
67117
|
+
lines.push("# HELP oa_requests_total Total HTTP requests");
|
|
67118
|
+
lines.push("# TYPE oa_requests_total counter");
|
|
67119
|
+
for (const entry of metrics.requests.values()) {
|
|
67120
|
+
lines.push(`oa_requests_total{method="${entry.method}",path="${entry.path}",status="${entry.status}"} ${entry.count}`);
|
|
67121
|
+
}
|
|
67122
|
+
lines.push("# HELP oa_tokens_in_total Total input tokens proxied");
|
|
67123
|
+
lines.push("# TYPE oa_tokens_in_total counter");
|
|
67124
|
+
lines.push(`oa_tokens_in_total ${metrics.totalTokensIn}`);
|
|
67125
|
+
lines.push("# HELP oa_tokens_out_total Total output tokens proxied");
|
|
67126
|
+
lines.push("# TYPE oa_tokens_out_total counter");
|
|
67127
|
+
lines.push(`oa_tokens_out_total ${metrics.totalTokensOut}`);
|
|
67128
|
+
lines.push("# HELP oa_errors_total Total error responses");
|
|
67129
|
+
lines.push("# TYPE oa_errors_total counter");
|
|
67130
|
+
lines.push(`oa_errors_total ${metrics.totalErrors}`);
|
|
67131
|
+
return lines.join("\n") + "\n";
|
|
67132
|
+
}
|
|
67133
|
+
function jsonResponse(res, status, body) {
|
|
67134
|
+
const payload = JSON.stringify(body);
|
|
67135
|
+
res.writeHead(status, {
|
|
67136
|
+
"Content-Type": "application/json",
|
|
67137
|
+
"Access-Control-Allow-Origin": "*",
|
|
67138
|
+
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
67139
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization"
|
|
67140
|
+
});
|
|
67141
|
+
res.end(payload);
|
|
67142
|
+
}
|
|
67143
|
+
function textResponse(res, status, body, contentType = "text/plain") {
|
|
67144
|
+
res.writeHead(status, {
|
|
67145
|
+
"Content-Type": contentType,
|
|
67146
|
+
"Access-Control-Allow-Origin": "*",
|
|
67147
|
+
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
67148
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization"
|
|
67149
|
+
});
|
|
67150
|
+
res.end(body);
|
|
67151
|
+
}
|
|
67152
|
+
function corsHeaders(res) {
|
|
67153
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
67154
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS");
|
|
67155
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
|
67156
|
+
}
|
|
67157
|
+
function readBody(req) {
|
|
67158
|
+
return new Promise((resolve36, reject) => {
|
|
67159
|
+
const chunks = [];
|
|
67160
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
67161
|
+
req.on("end", () => resolve36(Buffer.concat(chunks).toString("utf-8")));
|
|
67162
|
+
req.on("error", reject);
|
|
67163
|
+
});
|
|
67164
|
+
}
|
|
67165
|
+
async function parseJsonBody(req) {
|
|
67166
|
+
const raw = await readBody(req);
|
|
67167
|
+
if (!raw)
|
|
67168
|
+
return null;
|
|
67169
|
+
try {
|
|
67170
|
+
return JSON.parse(raw);
|
|
67171
|
+
} catch {
|
|
67172
|
+
return null;
|
|
67173
|
+
}
|
|
67174
|
+
}
|
|
67175
|
+
function ollamaRequest(ollamaUrl, path, method, body) {
|
|
67176
|
+
return new Promise((resolve36, reject) => {
|
|
67177
|
+
const url = new URL(path, ollamaUrl);
|
|
67178
|
+
const options = {
|
|
67179
|
+
hostname: url.hostname,
|
|
67180
|
+
port: url.port,
|
|
67181
|
+
path: url.pathname + url.search,
|
|
67182
|
+
method,
|
|
67183
|
+
headers: {
|
|
67184
|
+
"Content-Type": "application/json",
|
|
67185
|
+
...body ? { "Content-Length": Buffer.byteLength(body) } : {}
|
|
67186
|
+
}
|
|
67187
|
+
};
|
|
67188
|
+
const proxyReq = http.request(options, (proxyRes) => {
|
|
67189
|
+
const chunks = [];
|
|
67190
|
+
proxyRes.on("data", (chunk) => chunks.push(chunk));
|
|
67191
|
+
proxyRes.on("end", () => {
|
|
67192
|
+
resolve36({
|
|
67193
|
+
status: proxyRes.statusCode ?? 500,
|
|
67194
|
+
headers: proxyRes.headers,
|
|
67195
|
+
body: Buffer.concat(chunks).toString("utf-8")
|
|
67196
|
+
});
|
|
67197
|
+
});
|
|
67198
|
+
});
|
|
67199
|
+
proxyReq.on("error", reject);
|
|
67200
|
+
if (body)
|
|
67201
|
+
proxyReq.write(body);
|
|
67202
|
+
proxyReq.end();
|
|
67203
|
+
});
|
|
67204
|
+
}
|
|
67205
|
+
function ollamaStream(ollamaUrl, path, method, body, onData, onEnd, onError) {
|
|
67206
|
+
const url = new URL(path, ollamaUrl);
|
|
67207
|
+
const options = {
|
|
67208
|
+
hostname: url.hostname,
|
|
67209
|
+
port: url.port,
|
|
67210
|
+
path: url.pathname + url.search,
|
|
67211
|
+
method,
|
|
67212
|
+
headers: {
|
|
67213
|
+
"Content-Type": "application/json",
|
|
67214
|
+
...body ? { "Content-Length": Buffer.byteLength(body) } : {}
|
|
67215
|
+
}
|
|
67216
|
+
};
|
|
67217
|
+
const proxyReq = http.request(options, (proxyRes) => {
|
|
67218
|
+
proxyRes.setEncoding("utf-8");
|
|
67219
|
+
proxyRes.on("data", onData);
|
|
67220
|
+
proxyRes.on("end", onEnd);
|
|
67221
|
+
});
|
|
67222
|
+
proxyReq.on("error", onError);
|
|
67223
|
+
if (body)
|
|
67224
|
+
proxyReq.write(body);
|
|
67225
|
+
proxyReq.end();
|
|
67226
|
+
}
|
|
67227
|
+
function jobsDir2() {
|
|
67228
|
+
const root = resolve35(process.cwd());
|
|
67229
|
+
const dir = join71(root, ".oa", "jobs");
|
|
67230
|
+
mkdirSync26(dir, { recursive: true });
|
|
67231
|
+
return dir;
|
|
67232
|
+
}
|
|
67233
|
+
function loadJob(id) {
|
|
67234
|
+
const file = join71(jobsDir2(), `${id}.json`);
|
|
67235
|
+
if (!existsSync53(file))
|
|
67236
|
+
return null;
|
|
67237
|
+
try {
|
|
67238
|
+
return JSON.parse(readFileSync41(file, "utf-8"));
|
|
67239
|
+
} catch {
|
|
67240
|
+
return null;
|
|
67241
|
+
}
|
|
67242
|
+
}
|
|
67243
|
+
function listJobs() {
|
|
67244
|
+
const dir = jobsDir2();
|
|
67245
|
+
if (!existsSync53(dir))
|
|
67246
|
+
return [];
|
|
67247
|
+
const files = readdirSync21(dir).filter((f) => f.endsWith(".json")).sort();
|
|
67248
|
+
const jobs = [];
|
|
67249
|
+
for (const file of files) {
|
|
67250
|
+
try {
|
|
67251
|
+
jobs.push(JSON.parse(readFileSync41(join71(dir, file), "utf-8")));
|
|
67252
|
+
} catch {
|
|
67253
|
+
}
|
|
67254
|
+
}
|
|
67255
|
+
return jobs;
|
|
67256
|
+
}
|
|
67257
|
+
function checkAuth(req, res) {
|
|
67258
|
+
const apiKey = process.env["OA_API_KEY"];
|
|
67259
|
+
if (!apiKey)
|
|
67260
|
+
return true;
|
|
67261
|
+
const authHeader = req.headers["authorization"];
|
|
67262
|
+
if (!authHeader || authHeader !== `Bearer ${apiKey}`) {
|
|
67263
|
+
jsonResponse(res, 401, { error: "Unauthorized", message: "Invalid or missing Bearer token" });
|
|
67264
|
+
return false;
|
|
67265
|
+
}
|
|
67266
|
+
return true;
|
|
67267
|
+
}
|
|
67268
|
+
function handleHealth(res) {
|
|
67269
|
+
const version = getVersion4();
|
|
67270
|
+
jsonResponse(res, 200, {
|
|
67271
|
+
status: "ok",
|
|
67272
|
+
uptime_s: Math.floor((Date.now() - startedAt) / 1e3),
|
|
67273
|
+
version
|
|
67274
|
+
});
|
|
67275
|
+
}
|
|
67276
|
+
async function handleHealthReady(res, ollamaUrl) {
|
|
67277
|
+
try {
|
|
67278
|
+
const result = await ollamaRequest(ollamaUrl, "/api/tags", "GET");
|
|
67279
|
+
if (result.status === 200) {
|
|
67280
|
+
jsonResponse(res, 200, { status: "ready", ollama: "reachable" });
|
|
67281
|
+
} else {
|
|
67282
|
+
jsonResponse(res, 503, { status: "not_ready", ollama: "unreachable", code: result.status });
|
|
67283
|
+
}
|
|
67284
|
+
} catch {
|
|
67285
|
+
jsonResponse(res, 503, { status: "not_ready", ollama: "unreachable" });
|
|
67286
|
+
}
|
|
67287
|
+
}
|
|
67288
|
+
function handleHealthStartup(res) {
|
|
67289
|
+
jsonResponse(res, 200, { status: "started" });
|
|
67290
|
+
}
|
|
67291
|
+
function handleVersion(res) {
|
|
67292
|
+
const version = getVersion4();
|
|
67293
|
+
jsonResponse(res, 200, {
|
|
67294
|
+
version,
|
|
67295
|
+
node: process.version,
|
|
67296
|
+
platform: process.platform
|
|
67297
|
+
});
|
|
67298
|
+
}
|
|
67299
|
+
function handleMetrics(res) {
|
|
67300
|
+
textResponse(res, 200, formatMetrics(), "text/plain; version=0.0.4; charset=utf-8");
|
|
67301
|
+
}
|
|
67302
|
+
async function handleV1Models(res, ollamaUrl) {
|
|
67303
|
+
try {
|
|
67304
|
+
const result = await ollamaRequest(ollamaUrl, "/api/tags", "GET");
|
|
67305
|
+
if (result.status !== 200) {
|
|
67306
|
+
jsonResponse(res, result.status, { error: "Failed to fetch models from Ollama" });
|
|
67307
|
+
return;
|
|
67308
|
+
}
|
|
67309
|
+
const ollamaBody = JSON.parse(result.body);
|
|
67310
|
+
const models = (ollamaBody.models ?? []).map((m) => ({
|
|
67311
|
+
id: m.name,
|
|
67312
|
+
object: "model",
|
|
67313
|
+
created: m.modified_at ? Math.floor(new Date(m.modified_at).getTime() / 1e3) : 0,
|
|
67314
|
+
owned_by: "local"
|
|
67315
|
+
}));
|
|
67316
|
+
jsonResponse(res, 200, { object: "list", data: models });
|
|
67317
|
+
} catch (err) {
|
|
67318
|
+
jsonResponse(res, 502, {
|
|
67319
|
+
error: "Failed to proxy to Ollama",
|
|
67320
|
+
message: err instanceof Error ? err.message : String(err)
|
|
67321
|
+
});
|
|
67322
|
+
}
|
|
67323
|
+
}
|
|
67324
|
+
async function handleV1ChatCompletions(req, res, ollamaUrl) {
|
|
67325
|
+
const body = await parseJsonBody(req);
|
|
67326
|
+
if (!body || typeof body !== "object") {
|
|
67327
|
+
jsonResponse(res, 400, { error: "Invalid request body" });
|
|
67328
|
+
return;
|
|
67329
|
+
}
|
|
67330
|
+
const requestBody = body;
|
|
67331
|
+
const stream = requestBody["stream"] === true;
|
|
67332
|
+
const model = requestBody["model"] || "unknown";
|
|
67333
|
+
const ollamaPayload = JSON.stringify({
|
|
67334
|
+
...requestBody,
|
|
67335
|
+
stream,
|
|
67336
|
+
think: false
|
|
67337
|
+
});
|
|
67338
|
+
if (stream) {
|
|
67339
|
+
res.writeHead(200, {
|
|
67340
|
+
"Content-Type": "text/event-stream",
|
|
67341
|
+
"Cache-Control": "no-cache",
|
|
67342
|
+
"Connection": "keep-alive",
|
|
67343
|
+
"Access-Control-Allow-Origin": "*",
|
|
67344
|
+
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
67345
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization"
|
|
67346
|
+
});
|
|
67347
|
+
const chatId = `chatcmpl-${randomBytes16(12).toString("hex")}`;
|
|
67348
|
+
let buffer = "";
|
|
67349
|
+
ollamaStream(ollamaUrl, "/api/chat", "POST", ollamaPayload, (chunk) => {
|
|
67350
|
+
buffer += chunk;
|
|
67351
|
+
const lines = buffer.split("\n");
|
|
67352
|
+
buffer = lines.pop() ?? "";
|
|
67353
|
+
for (const line of lines) {
|
|
67354
|
+
if (!line.trim())
|
|
67355
|
+
continue;
|
|
67356
|
+
try {
|
|
67357
|
+
const ollamaChunk = JSON.parse(line);
|
|
67358
|
+
if (ollamaChunk.done) {
|
|
67359
|
+
if (ollamaChunk.eval_count)
|
|
67360
|
+
metrics.totalTokensOut += ollamaChunk.eval_count;
|
|
67361
|
+
if (ollamaChunk.prompt_eval_count)
|
|
67362
|
+
metrics.totalTokensIn += ollamaChunk.prompt_eval_count;
|
|
67363
|
+
const doneEvent = {
|
|
67364
|
+
id: chatId,
|
|
67365
|
+
object: "chat.completion.chunk",
|
|
67366
|
+
created: Math.floor(Date.now() / 1e3),
|
|
67367
|
+
model,
|
|
67368
|
+
choices: [
|
|
67369
|
+
{
|
|
67370
|
+
index: 0,
|
|
67371
|
+
delta: {},
|
|
67372
|
+
finish_reason: "stop"
|
|
67373
|
+
}
|
|
67374
|
+
]
|
|
67375
|
+
};
|
|
67376
|
+
res.write(`data: ${JSON.stringify(doneEvent)}
|
|
67377
|
+
|
|
67378
|
+
`);
|
|
67379
|
+
res.write("data: [DONE]\n\n");
|
|
67380
|
+
} else if (ollamaChunk.message?.content) {
|
|
67381
|
+
const sseEvent = {
|
|
67382
|
+
id: chatId,
|
|
67383
|
+
object: "chat.completion.chunk",
|
|
67384
|
+
created: Math.floor(Date.now() / 1e3),
|
|
67385
|
+
model,
|
|
67386
|
+
choices: [
|
|
67387
|
+
{
|
|
67388
|
+
index: 0,
|
|
67389
|
+
delta: {
|
|
67390
|
+
role: ollamaChunk.message.role ?? "assistant",
|
|
67391
|
+
content: ollamaChunk.message.content
|
|
67392
|
+
},
|
|
67393
|
+
finish_reason: null
|
|
67394
|
+
}
|
|
67395
|
+
]
|
|
67396
|
+
};
|
|
67397
|
+
res.write(`data: ${JSON.stringify(sseEvent)}
|
|
67398
|
+
|
|
67399
|
+
`);
|
|
67400
|
+
}
|
|
67401
|
+
} catch {
|
|
67402
|
+
}
|
|
67403
|
+
}
|
|
67404
|
+
}, () => {
|
|
67405
|
+
if (buffer.trim()) {
|
|
67406
|
+
try {
|
|
67407
|
+
const ollamaChunk = JSON.parse(buffer);
|
|
67408
|
+
if (ollamaChunk.done) {
|
|
67409
|
+
if (ollamaChunk.eval_count)
|
|
67410
|
+
metrics.totalTokensOut += ollamaChunk.eval_count;
|
|
67411
|
+
if (ollamaChunk.prompt_eval_count)
|
|
67412
|
+
metrics.totalTokensIn += ollamaChunk.prompt_eval_count;
|
|
67413
|
+
res.write(`data: ${JSON.stringify({
|
|
67414
|
+
id: chatId,
|
|
67415
|
+
object: "chat.completion.chunk",
|
|
67416
|
+
created: Math.floor(Date.now() / 1e3),
|
|
67417
|
+
model,
|
|
67418
|
+
choices: [{ index: 0, delta: {}, finish_reason: "stop" }]
|
|
67419
|
+
})}
|
|
67420
|
+
|
|
67421
|
+
`);
|
|
67422
|
+
res.write("data: [DONE]\n\n");
|
|
67423
|
+
}
|
|
67424
|
+
} catch {
|
|
67425
|
+
}
|
|
67426
|
+
}
|
|
67427
|
+
res.end();
|
|
67428
|
+
}, (err) => {
|
|
67429
|
+
try {
|
|
67430
|
+
res.write(`data: ${JSON.stringify({ error: err.message })}
|
|
67431
|
+
|
|
67432
|
+
`);
|
|
67433
|
+
} catch {
|
|
67434
|
+
}
|
|
67435
|
+
res.end();
|
|
67436
|
+
});
|
|
67437
|
+
} else {
|
|
67438
|
+
try {
|
|
67439
|
+
const result = await ollamaRequest(ollamaUrl, "/api/chat", "POST", ollamaPayload);
|
|
67440
|
+
if (result.status !== 200) {
|
|
67441
|
+
jsonResponse(res, result.status, {
|
|
67442
|
+
error: "Ollama request failed",
|
|
67443
|
+
details: result.body
|
|
67444
|
+
});
|
|
67445
|
+
return;
|
|
67446
|
+
}
|
|
67447
|
+
const ollamaResp = JSON.parse(result.body);
|
|
67448
|
+
if (ollamaResp.eval_count)
|
|
67449
|
+
metrics.totalTokensOut += ollamaResp.eval_count;
|
|
67450
|
+
if (ollamaResp.prompt_eval_count)
|
|
67451
|
+
metrics.totalTokensIn += ollamaResp.prompt_eval_count;
|
|
67452
|
+
const chatId = `chatcmpl-${randomBytes16(12).toString("hex")}`;
|
|
67453
|
+
const openaiResponse = {
|
|
67454
|
+
id: chatId,
|
|
67455
|
+
object: "chat.completion",
|
|
67456
|
+
created: Math.floor(Date.now() / 1e3),
|
|
67457
|
+
model,
|
|
67458
|
+
choices: [
|
|
67459
|
+
{
|
|
67460
|
+
index: 0,
|
|
67461
|
+
message: {
|
|
67462
|
+
role: ollamaResp.message?.role ?? "assistant",
|
|
67463
|
+
content: ollamaResp.message?.content ?? ""
|
|
67464
|
+
},
|
|
67465
|
+
finish_reason: "stop"
|
|
67466
|
+
}
|
|
67467
|
+
],
|
|
67468
|
+
usage: {
|
|
67469
|
+
prompt_tokens: ollamaResp.prompt_eval_count ?? 0,
|
|
67470
|
+
completion_tokens: ollamaResp.eval_count ?? 0,
|
|
67471
|
+
total_tokens: (ollamaResp.prompt_eval_count ?? 0) + (ollamaResp.eval_count ?? 0)
|
|
67472
|
+
}
|
|
67473
|
+
};
|
|
67474
|
+
jsonResponse(res, 200, openaiResponse);
|
|
67475
|
+
} catch (err) {
|
|
67476
|
+
jsonResponse(res, 502, {
|
|
67477
|
+
error: "Failed to proxy to Ollama",
|
|
67478
|
+
message: err instanceof Error ? err.message : String(err)
|
|
67479
|
+
});
|
|
67480
|
+
}
|
|
67481
|
+
}
|
|
67482
|
+
}
|
|
67483
|
+
async function handleV1Embeddings(req, res, ollamaUrl) {
|
|
67484
|
+
const body = await parseJsonBody(req);
|
|
67485
|
+
if (!body || typeof body !== "object") {
|
|
67486
|
+
jsonResponse(res, 400, { error: "Invalid request body" });
|
|
67487
|
+
return;
|
|
67488
|
+
}
|
|
67489
|
+
const requestBody = body;
|
|
67490
|
+
const ollamaPayload = JSON.stringify({
|
|
67491
|
+
model: requestBody["model"],
|
|
67492
|
+
input: requestBody["input"]
|
|
67493
|
+
});
|
|
67494
|
+
try {
|
|
67495
|
+
const result = await ollamaRequest(ollamaUrl, "/api/embed", "POST", ollamaPayload);
|
|
67496
|
+
if (result.status !== 200) {
|
|
67497
|
+
jsonResponse(res, result.status, {
|
|
67498
|
+
error: "Ollama embeddings request failed",
|
|
67499
|
+
details: result.body
|
|
67500
|
+
});
|
|
67501
|
+
return;
|
|
67502
|
+
}
|
|
67503
|
+
const ollamaResp = JSON.parse(result.body);
|
|
67504
|
+
const data = (ollamaResp.embeddings ?? []).map((embedding, index) => ({
|
|
67505
|
+
object: "embedding",
|
|
67506
|
+
embedding,
|
|
67507
|
+
index
|
|
67508
|
+
}));
|
|
67509
|
+
jsonResponse(res, 200, {
|
|
67510
|
+
object: "list",
|
|
67511
|
+
data,
|
|
67512
|
+
model: ollamaResp.model ?? requestBody["model"],
|
|
67513
|
+
usage: { prompt_tokens: 0, total_tokens: 0 }
|
|
67514
|
+
});
|
|
67515
|
+
} catch (err) {
|
|
67516
|
+
jsonResponse(res, 502, {
|
|
67517
|
+
error: "Failed to proxy to Ollama",
|
|
67518
|
+
message: err instanceof Error ? err.message : String(err)
|
|
67519
|
+
});
|
|
67520
|
+
}
|
|
67521
|
+
}
|
|
67522
|
+
async function handleV1Run(req, res) {
|
|
67523
|
+
const body = await parseJsonBody(req);
|
|
67524
|
+
if (!body || typeof body !== "object") {
|
|
67525
|
+
jsonResponse(res, 400, { error: "Invalid request body" });
|
|
67526
|
+
return;
|
|
67527
|
+
}
|
|
67528
|
+
const requestBody = body;
|
|
67529
|
+
const task = requestBody["task"];
|
|
67530
|
+
const streamMode = requestBody["stream"] === true;
|
|
67531
|
+
if (!task || typeof task !== "string") {
|
|
67532
|
+
jsonResponse(res, 400, { error: "Missing required field: task" });
|
|
67533
|
+
return;
|
|
67534
|
+
}
|
|
67535
|
+
const id = `job-${randomBytes16(3).toString("hex")}`;
|
|
67536
|
+
const dir = jobsDir2();
|
|
67537
|
+
const repoRoot = resolve35(process.cwd());
|
|
67538
|
+
const job = {
|
|
67539
|
+
id,
|
|
67540
|
+
pid: 0,
|
|
67541
|
+
task,
|
|
67542
|
+
status: "running",
|
|
67543
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
67544
|
+
};
|
|
67545
|
+
const oaBin = process.argv[1] || "oa";
|
|
67546
|
+
const args = [task, "--json"];
|
|
67547
|
+
const modelArg = requestBody["model"];
|
|
67548
|
+
if (modelArg)
|
|
67549
|
+
args.push("--model", modelArg);
|
|
67550
|
+
const child = spawn21("node", [oaBin, ...args], {
|
|
67551
|
+
cwd: repoRoot,
|
|
67552
|
+
env: { ...process.env, OA_JOB_ID: id, __OPEN_AGENTS_NO_AUTO_RUN: "" },
|
|
67553
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
67554
|
+
detached: true
|
|
67555
|
+
});
|
|
67556
|
+
child.unref();
|
|
67557
|
+
job.pid = child.pid ?? 0;
|
|
67558
|
+
writeFileSync25(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
67559
|
+
runningProcesses.set(id, child);
|
|
67560
|
+
if (streamMode) {
|
|
67561
|
+
res.writeHead(200, {
|
|
67562
|
+
"Content-Type": "text/event-stream",
|
|
67563
|
+
"Cache-Control": "no-cache",
|
|
67564
|
+
"Connection": "keep-alive",
|
|
67565
|
+
"Access-Control-Allow-Origin": "*",
|
|
67566
|
+
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
67567
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization"
|
|
67568
|
+
});
|
|
67569
|
+
res.write(`data: ${JSON.stringify({ type: "run_started", run_id: id, pid: job.pid })}
|
|
67570
|
+
|
|
67571
|
+
`);
|
|
67572
|
+
child.stdout?.on("data", (chunk) => {
|
|
67573
|
+
const text = chunk.toString("utf-8");
|
|
67574
|
+
res.write(`data: ${JSON.stringify({ type: "stdout", data: text })}
|
|
67575
|
+
|
|
67576
|
+
`);
|
|
67577
|
+
});
|
|
67578
|
+
child.stderr?.on("data", (chunk) => {
|
|
67579
|
+
const text = chunk.toString("utf-8");
|
|
67580
|
+
res.write(`data: ${JSON.stringify({ type: "stderr", data: text })}
|
|
67581
|
+
|
|
67582
|
+
`);
|
|
67583
|
+
});
|
|
67584
|
+
child.on("exit", (code) => {
|
|
67585
|
+
job.status = code === 0 ? "completed" : "failed";
|
|
67586
|
+
job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
67587
|
+
try {
|
|
67588
|
+
writeFileSync25(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
67589
|
+
} catch {
|
|
67590
|
+
}
|
|
67591
|
+
runningProcesses.delete(id);
|
|
67592
|
+
res.write(`data: ${JSON.stringify({ type: "run_completed", run_id: id, exit_code: code })}
|
|
67593
|
+
|
|
67594
|
+
`);
|
|
67595
|
+
res.write("data: [DONE]\n\n");
|
|
67596
|
+
res.end();
|
|
67597
|
+
});
|
|
67598
|
+
} else {
|
|
67599
|
+
let output = "";
|
|
67600
|
+
child.stdout?.on("data", (chunk) => {
|
|
67601
|
+
output += chunk.toString();
|
|
67602
|
+
});
|
|
67603
|
+
child.stderr?.on("data", (chunk) => {
|
|
67604
|
+
output += chunk.toString();
|
|
67605
|
+
});
|
|
67606
|
+
child.on("exit", (code) => {
|
|
67607
|
+
try {
|
|
67608
|
+
const result = output.trim() ? JSON.parse(output) : { status: code === 0 ? "completed" : "failed" };
|
|
67609
|
+
job.status = result["status"] === "completed" ? "completed" : code === 0 ? "completed" : "failed";
|
|
67610
|
+
job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
67611
|
+
job.summary = result["summary"];
|
|
67612
|
+
job.durationMs = result["durationMs"];
|
|
67613
|
+
job.error = result["error"];
|
|
67614
|
+
} catch {
|
|
67615
|
+
job.status = code === 0 ? "completed" : "failed";
|
|
67616
|
+
job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
67617
|
+
}
|
|
67618
|
+
try {
|
|
67619
|
+
writeFileSync25(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
67620
|
+
} catch {
|
|
67621
|
+
}
|
|
67622
|
+
runningProcesses.delete(id);
|
|
67623
|
+
});
|
|
67624
|
+
jsonResponse(res, 202, { run_id: id, status: "running", pid: job.pid });
|
|
67625
|
+
}
|
|
67626
|
+
}
|
|
67627
|
+
function handleV1Runs(res) {
|
|
67628
|
+
const jobs = listJobs();
|
|
67629
|
+
jsonResponse(res, 200, { runs: jobs });
|
|
67630
|
+
}
|
|
67631
|
+
function handleV1RunsById(res, id) {
|
|
67632
|
+
const job = loadJob(id);
|
|
67633
|
+
if (!job) {
|
|
67634
|
+
jsonResponse(res, 404, { error: "Run not found", run_id: id });
|
|
67635
|
+
return;
|
|
67636
|
+
}
|
|
67637
|
+
jsonResponse(res, 200, job);
|
|
67638
|
+
}
|
|
67639
|
+
function handleV1RunsDelete(res, id) {
|
|
67640
|
+
const job = loadJob(id);
|
|
67641
|
+
if (!job) {
|
|
67642
|
+
jsonResponse(res, 404, { error: "Run not found", run_id: id });
|
|
67643
|
+
return;
|
|
67644
|
+
}
|
|
67645
|
+
if (job.status === "running") {
|
|
67646
|
+
const child = runningProcesses.get(id);
|
|
67647
|
+
if (child && !child.killed) {
|
|
67648
|
+
child.kill("SIGTERM");
|
|
67649
|
+
} else if (job.pid > 0) {
|
|
67650
|
+
try {
|
|
67651
|
+
process.kill(job.pid, "SIGTERM");
|
|
67652
|
+
} catch {
|
|
67653
|
+
}
|
|
67654
|
+
}
|
|
67655
|
+
job.status = "failed";
|
|
67656
|
+
job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
67657
|
+
job.error = "Aborted via API";
|
|
67658
|
+
const dir = jobsDir2();
|
|
67659
|
+
try {
|
|
67660
|
+
writeFileSync25(join71(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
67661
|
+
} catch {
|
|
67662
|
+
}
|
|
67663
|
+
runningProcesses.delete(id);
|
|
67664
|
+
}
|
|
67665
|
+
jsonResponse(res, 200, { run_id: id, status: "aborted" });
|
|
67666
|
+
}
|
|
67667
|
+
function handleGetConfig(res) {
|
|
67668
|
+
const config = loadConfig();
|
|
67669
|
+
const settings = loadGlobalSettings();
|
|
67670
|
+
jsonResponse(res, 200, { config, settings });
|
|
67671
|
+
}
|
|
67672
|
+
async function handlePatchConfig(req, res) {
|
|
67673
|
+
const body = await parseJsonBody(req);
|
|
67674
|
+
if (!body || typeof body !== "object") {
|
|
67675
|
+
jsonResponse(res, 400, { error: "Invalid request body" });
|
|
67676
|
+
return;
|
|
67677
|
+
}
|
|
67678
|
+
const updates = body;
|
|
67679
|
+
const settingsUpdate = {};
|
|
67680
|
+
if (typeof updates["model"] === "string")
|
|
67681
|
+
settingsUpdate.model = updates["model"];
|
|
67682
|
+
if (typeof updates["backendUrl"] === "string")
|
|
67683
|
+
settingsUpdate.backendUrl = updates["backendUrl"];
|
|
67684
|
+
if (typeof updates["backendType"] === "string")
|
|
67685
|
+
settingsUpdate.backendType = updates["backendType"];
|
|
67686
|
+
if (typeof updates["apiKey"] === "string")
|
|
67687
|
+
settingsUpdate.apiKey = updates["apiKey"];
|
|
67688
|
+
if (typeof updates["verbose"] === "boolean")
|
|
67689
|
+
settingsUpdate.verbose = updates["verbose"];
|
|
67690
|
+
if (typeof updates["dryRun"] === "boolean")
|
|
67691
|
+
settingsUpdate.dryRun = updates["dryRun"];
|
|
67692
|
+
if (typeof updates["maxRetries"] === "number")
|
|
67693
|
+
settingsUpdate.maxRetries = updates["maxRetries"];
|
|
67694
|
+
if (typeof updates["timeoutMs"] === "number")
|
|
67695
|
+
settingsUpdate.timeoutMs = updates["timeoutMs"];
|
|
67696
|
+
saveGlobalSettings(settingsUpdate);
|
|
67697
|
+
const updatedConfig = loadConfig();
|
|
67698
|
+
jsonResponse(res, 200, { config: updatedConfig, updated: Object.keys(settingsUpdate) });
|
|
67699
|
+
}
|
|
67700
|
+
function handleGetConfigModel(res) {
|
|
67701
|
+
const config = loadConfig();
|
|
67702
|
+
jsonResponse(res, 200, { model: config.model });
|
|
67703
|
+
}
|
|
67704
|
+
async function handlePutConfigModel(req, res) {
|
|
67705
|
+
const body = await parseJsonBody(req);
|
|
67706
|
+
if (!body || typeof body !== "object") {
|
|
67707
|
+
jsonResponse(res, 400, { error: "Invalid request body" });
|
|
67708
|
+
return;
|
|
67709
|
+
}
|
|
67710
|
+
const requestBody = body;
|
|
67711
|
+
const model = requestBody["model"];
|
|
67712
|
+
if (typeof model !== "string" || !model) {
|
|
67713
|
+
jsonResponse(res, 400, { error: "Missing required field: model" });
|
|
67714
|
+
return;
|
|
67715
|
+
}
|
|
67716
|
+
saveGlobalSettings({ model });
|
|
67717
|
+
jsonResponse(res, 200, { model, status: "updated" });
|
|
67718
|
+
}
|
|
67719
|
+
function handleGetConfigEndpoint(res) {
|
|
67720
|
+
const config = loadConfig();
|
|
67721
|
+
jsonResponse(res, 200, {
|
|
67722
|
+
url: config.backendUrl,
|
|
67723
|
+
backendType: config.backendType,
|
|
67724
|
+
auth: config.apiKey ? "[set]" : ""
|
|
67725
|
+
});
|
|
67726
|
+
}
|
|
67727
|
+
async function handlePutConfigEndpoint(req, res) {
|
|
67728
|
+
const body = await parseJsonBody(req);
|
|
67729
|
+
if (!body || typeof body !== "object") {
|
|
67730
|
+
jsonResponse(res, 400, { error: "Invalid request body" });
|
|
67731
|
+
return;
|
|
67732
|
+
}
|
|
67733
|
+
const requestBody = body;
|
|
67734
|
+
const url = requestBody["url"];
|
|
67735
|
+
if (typeof url !== "string" || !url) {
|
|
67736
|
+
jsonResponse(res, 400, { error: "Missing required field: url" });
|
|
67737
|
+
return;
|
|
67738
|
+
}
|
|
67739
|
+
const settings = { backendUrl: url };
|
|
67740
|
+
if (typeof requestBody["auth"] === "string")
|
|
67741
|
+
settings.apiKey = requestBody["auth"];
|
|
67742
|
+
if (typeof requestBody["backendType"] === "string")
|
|
67743
|
+
settings.backendType = requestBody["backendType"];
|
|
67744
|
+
saveGlobalSettings(settings);
|
|
67745
|
+
jsonResponse(res, 200, { url, status: "updated" });
|
|
67746
|
+
}
|
|
67747
|
+
function handleGetCommands(res) {
|
|
67748
|
+
const commands = SLASH_COMMANDS.map(([cmd, desc]) => ({
|
|
67749
|
+
command: cmd,
|
|
67750
|
+
description: desc
|
|
67751
|
+
}));
|
|
67752
|
+
jsonResponse(res, 200, { commands });
|
|
67753
|
+
}
|
|
67754
|
+
async function handlePostCommand(res, cmd) {
|
|
67755
|
+
const oaBin = process.argv[1] || "oa";
|
|
67756
|
+
const blocked = /* @__PURE__ */ new Set(["quit", "exit", "destroy", "full-send-bless", "bless", "call", "hangup", "listen", "neovim", "dream"]);
|
|
67757
|
+
const cmdBase = cmd.split(" ")[0]?.replace(/^\//, "") ?? "";
|
|
67758
|
+
if (blocked.has(cmdBase)) {
|
|
67759
|
+
jsonResponse(res, 403, {
|
|
67760
|
+
error: "Blocked command",
|
|
67761
|
+
message: `Command "/${cmdBase}" is not available via the API (interactive or destructive)`
|
|
67762
|
+
});
|
|
67763
|
+
return;
|
|
67764
|
+
}
|
|
67765
|
+
try {
|
|
67766
|
+
const child = spawn21("node", [oaBin, "run", `/${cmd}`, "--json"], {
|
|
67767
|
+
env: { ...process.env, __OPEN_AGENTS_NO_AUTO_RUN: "" },
|
|
67768
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
67769
|
+
timeout: 3e4
|
|
67770
|
+
});
|
|
67771
|
+
let stdout = "";
|
|
67772
|
+
let stderr = "";
|
|
67773
|
+
child.stdout?.on("data", (chunk) => {
|
|
67774
|
+
stdout += chunk.toString();
|
|
67775
|
+
});
|
|
67776
|
+
child.stderr?.on("data", (chunk) => {
|
|
67777
|
+
stderr += chunk.toString();
|
|
67778
|
+
});
|
|
67779
|
+
await new Promise((resolve36) => {
|
|
67780
|
+
child.on("exit", () => resolve36());
|
|
67781
|
+
child.on("error", () => resolve36());
|
|
67782
|
+
});
|
|
67783
|
+
jsonResponse(res, 200, {
|
|
67784
|
+
command: cmd,
|
|
67785
|
+
output: stdout.trim() || stderr.trim() || "(no output)"
|
|
67786
|
+
});
|
|
67787
|
+
} catch (err) {
|
|
67788
|
+
jsonResponse(res, 500, {
|
|
67789
|
+
error: "Command execution failed",
|
|
67790
|
+
message: err instanceof Error ? err.message : String(err)
|
|
67791
|
+
});
|
|
67792
|
+
}
|
|
67793
|
+
}
|
|
67794
|
+
async function handleRequest(req, res, ollamaUrl, verbose) {
|
|
67795
|
+
const method = req.method ?? "GET";
|
|
67796
|
+
const urlObj = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
|
|
67797
|
+
const pathname = urlObj.pathname;
|
|
67798
|
+
if (verbose) {
|
|
67799
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().split("T")[1]?.slice(0, 8) ?? "";
|
|
67800
|
+
process.stderr.write(`[${ts}] ${method} ${pathname}
|
|
67801
|
+
`);
|
|
67802
|
+
}
|
|
67803
|
+
if (method === "OPTIONS") {
|
|
67804
|
+
corsHeaders(res);
|
|
67805
|
+
res.writeHead(204);
|
|
67806
|
+
res.end();
|
|
67807
|
+
return;
|
|
67808
|
+
}
|
|
67809
|
+
let status = 200;
|
|
67810
|
+
try {
|
|
67811
|
+
if (pathname === "/health" && method === "GET") {
|
|
67812
|
+
handleHealth(res);
|
|
67813
|
+
return;
|
|
67814
|
+
}
|
|
67815
|
+
if (pathname === "/health/ready" && method === "GET") {
|
|
67816
|
+
await handleHealthReady(res, ollamaUrl);
|
|
67817
|
+
return;
|
|
67818
|
+
}
|
|
67819
|
+
if (pathname === "/health/startup" && method === "GET") {
|
|
67820
|
+
handleHealthStartup(res);
|
|
67821
|
+
return;
|
|
67822
|
+
}
|
|
67823
|
+
if (pathname === "/version" && method === "GET") {
|
|
67824
|
+
handleVersion(res);
|
|
67825
|
+
return;
|
|
67826
|
+
}
|
|
67827
|
+
if (pathname === "/metrics" && method === "GET") {
|
|
67828
|
+
handleMetrics(res);
|
|
67829
|
+
return;
|
|
67830
|
+
}
|
|
67831
|
+
if (pathname.startsWith("/v1/")) {
|
|
67832
|
+
if (!checkAuth(req, res)) {
|
|
67833
|
+
status = 401;
|
|
67834
|
+
return;
|
|
67835
|
+
}
|
|
67836
|
+
}
|
|
67837
|
+
if (pathname === "/v1/models" && method === "GET") {
|
|
67838
|
+
await handleV1Models(res, ollamaUrl);
|
|
67839
|
+
return;
|
|
67840
|
+
}
|
|
67841
|
+
if (pathname === "/v1/chat/completions" && method === "POST") {
|
|
67842
|
+
await handleV1ChatCompletions(req, res, ollamaUrl);
|
|
67843
|
+
return;
|
|
67844
|
+
}
|
|
67845
|
+
if (pathname === "/v1/embeddings" && method === "POST") {
|
|
67846
|
+
await handleV1Embeddings(req, res, ollamaUrl);
|
|
67847
|
+
return;
|
|
67848
|
+
}
|
|
67849
|
+
if (pathname === "/v1/run" && method === "POST") {
|
|
67850
|
+
await handleV1Run(req, res);
|
|
67851
|
+
return;
|
|
67852
|
+
}
|
|
67853
|
+
if (pathname === "/v1/runs" && method === "GET") {
|
|
67854
|
+
handleV1Runs(res);
|
|
67855
|
+
return;
|
|
67856
|
+
}
|
|
67857
|
+
const runsMatch = pathname.match(/^\/v1\/runs\/([a-zA-Z0-9_-]+)$/);
|
|
67858
|
+
if (runsMatch) {
|
|
67859
|
+
const runId = runsMatch[1];
|
|
67860
|
+
if (method === "GET") {
|
|
67861
|
+
handleV1RunsById(res, runId);
|
|
67862
|
+
return;
|
|
67863
|
+
}
|
|
67864
|
+
if (method === "DELETE") {
|
|
67865
|
+
handleV1RunsDelete(res, runId);
|
|
67866
|
+
return;
|
|
67867
|
+
}
|
|
67868
|
+
}
|
|
67869
|
+
if (pathname === "/v1/config" && method === "GET") {
|
|
67870
|
+
handleGetConfig(res);
|
|
67871
|
+
return;
|
|
67872
|
+
}
|
|
67873
|
+
if (pathname === "/v1/config" && method === "PATCH") {
|
|
67874
|
+
await handlePatchConfig(req, res);
|
|
67875
|
+
return;
|
|
67876
|
+
}
|
|
67877
|
+
if (pathname === "/v1/config/model" && method === "GET") {
|
|
67878
|
+
handleGetConfigModel(res);
|
|
67879
|
+
return;
|
|
67880
|
+
}
|
|
67881
|
+
if (pathname === "/v1/config/model" && method === "PUT") {
|
|
67882
|
+
await handlePutConfigModel(req, res);
|
|
67883
|
+
return;
|
|
67884
|
+
}
|
|
67885
|
+
if (pathname === "/v1/config/endpoint" && method === "GET") {
|
|
67886
|
+
handleGetConfigEndpoint(res);
|
|
67887
|
+
return;
|
|
67888
|
+
}
|
|
67889
|
+
if (pathname === "/v1/config/endpoint" && method === "PUT") {
|
|
67890
|
+
await handlePutConfigEndpoint(req, res);
|
|
67891
|
+
return;
|
|
67892
|
+
}
|
|
67893
|
+
if (pathname === "/v1/commands" && method === "GET") {
|
|
67894
|
+
handleGetCommands(res);
|
|
67895
|
+
return;
|
|
67896
|
+
}
|
|
67897
|
+
const cmdMatch = pathname.match(/^\/v1\/commands\/(.+)$/);
|
|
67898
|
+
if (cmdMatch && method === "POST") {
|
|
67899
|
+
const cmd = decodeURIComponent(cmdMatch[1]);
|
|
67900
|
+
await handlePostCommand(res, cmd);
|
|
67901
|
+
return;
|
|
67902
|
+
}
|
|
67903
|
+
status = 404;
|
|
67904
|
+
jsonResponse(res, 404, { error: "Not found", path: pathname });
|
|
67905
|
+
} catch (err) {
|
|
67906
|
+
status = 500;
|
|
67907
|
+
metrics.totalErrors++;
|
|
67908
|
+
jsonResponse(res, 500, {
|
|
67909
|
+
error: "Internal server error",
|
|
67910
|
+
message: err instanceof Error ? err.message : String(err)
|
|
67911
|
+
});
|
|
67912
|
+
} finally {
|
|
67913
|
+
recordMetric(method, pathname, status);
|
|
67914
|
+
}
|
|
67915
|
+
}
|
|
67916
|
+
function startApiServer(options = {}) {
|
|
67917
|
+
let host = "127.0.0.1";
|
|
67918
|
+
let port = 11435;
|
|
67919
|
+
const envHost = process.env["OA_HOST"];
|
|
67920
|
+
if (envHost) {
|
|
67921
|
+
const parts = envHost.split(":");
|
|
67922
|
+
if (parts.length === 2) {
|
|
67923
|
+
host = parts[0];
|
|
67924
|
+
port = parseInt(parts[1], 10);
|
|
67925
|
+
} else if (parts.length === 1 && /^\d+$/.test(parts[0])) {
|
|
67926
|
+
port = parseInt(parts[0], 10);
|
|
67927
|
+
} else {
|
|
67928
|
+
host = parts[0];
|
|
67929
|
+
}
|
|
67930
|
+
}
|
|
67931
|
+
if (options.host)
|
|
67932
|
+
host = options.host;
|
|
67933
|
+
if (options.port)
|
|
67934
|
+
port = options.port;
|
|
67935
|
+
const verbose = options.verbose ?? false;
|
|
67936
|
+
const config = loadConfig();
|
|
67937
|
+
const ollamaUrl = options.ollamaUrl ?? config.backendUrl;
|
|
67938
|
+
const server = http.createServer((req, res) => {
|
|
67939
|
+
handleRequest(req, res, ollamaUrl, verbose).catch((err) => {
|
|
67940
|
+
metrics.totalErrors++;
|
|
67941
|
+
try {
|
|
67942
|
+
jsonResponse(res, 500, {
|
|
67943
|
+
error: "Unhandled error",
|
|
67944
|
+
message: err instanceof Error ? err.message : String(err)
|
|
67945
|
+
});
|
|
67946
|
+
} catch {
|
|
67947
|
+
}
|
|
67948
|
+
});
|
|
67949
|
+
});
|
|
67950
|
+
server.listen(port, host, () => {
|
|
67951
|
+
const version = getVersion4();
|
|
67952
|
+
process.stderr.write(`
|
|
67953
|
+
open-agents API server v${version}
|
|
67954
|
+
`);
|
|
67955
|
+
process.stderr.write(` Listening on http://${host}:${port}
|
|
67956
|
+
`);
|
|
67957
|
+
process.stderr.write(` Ollama proxy: ${ollamaUrl}
|
|
67958
|
+
`);
|
|
67959
|
+
if (process.env["OA_API_KEY"]) {
|
|
67960
|
+
process.stderr.write(` Auth: Bearer token required for /v1/* endpoints
|
|
67961
|
+
`);
|
|
67962
|
+
} else {
|
|
67963
|
+
process.stderr.write(` Auth: disabled (set OA_API_KEY to enable)
|
|
67964
|
+
`);
|
|
67965
|
+
}
|
|
67966
|
+
process.stderr.write(`
|
|
67967
|
+
`);
|
|
67968
|
+
});
|
|
67969
|
+
const shutdown = () => {
|
|
67970
|
+
process.stderr.write("\n Shutting down API server...\n");
|
|
67971
|
+
for (const [id, child] of runningProcesses) {
|
|
67972
|
+
if (!child.killed) {
|
|
67973
|
+
child.kill("SIGTERM");
|
|
67974
|
+
}
|
|
67975
|
+
runningProcesses.delete(id);
|
|
67976
|
+
}
|
|
67977
|
+
server.close(() => {
|
|
67978
|
+
process.stderr.write(" Server stopped.\n");
|
|
67979
|
+
process.exit(0);
|
|
67980
|
+
});
|
|
67981
|
+
setTimeout(() => process.exit(1), 5e3).unref();
|
|
67982
|
+
};
|
|
67983
|
+
process.on("SIGINT", shutdown);
|
|
67984
|
+
process.on("SIGTERM", shutdown);
|
|
67985
|
+
return server;
|
|
67986
|
+
}
|
|
67987
|
+
var metrics, startedAt, runningProcesses;
|
|
67988
|
+
var init_serve = __esm({
|
|
67989
|
+
"packages/cli/dist/api/serve.js"() {
|
|
67990
|
+
"use strict";
|
|
67991
|
+
init_config();
|
|
67992
|
+
init_oa_directory();
|
|
67993
|
+
init_render();
|
|
67994
|
+
metrics = {
|
|
67995
|
+
requests: /* @__PURE__ */ new Map(),
|
|
67996
|
+
totalTokensIn: 0,
|
|
67997
|
+
totalTokensOut: 0,
|
|
67998
|
+
totalErrors: 0
|
|
67999
|
+
};
|
|
68000
|
+
startedAt = Date.now();
|
|
68001
|
+
runningProcesses = /* @__PURE__ */ new Map();
|
|
68002
|
+
}
|
|
68003
|
+
});
|
|
68004
|
+
|
|
67088
68005
|
// packages/cli/dist/commands/serve.js
|
|
67089
68006
|
var serve_exports = {};
|
|
67090
68007
|
__export(serve_exports, {
|
|
67091
68008
|
serveCommand: () => serveCommand
|
|
67092
68009
|
});
|
|
67093
|
-
import { spawn as
|
|
68010
|
+
import { spawn as spawn22 } from "node:child_process";
|
|
67094
68011
|
async function serveCommand(opts, config) {
|
|
67095
68012
|
const backendType = config.backendType;
|
|
67096
68013
|
if (backendType === "ollama") {
|
|
@@ -67147,6 +68064,18 @@ async function serveOllama(opts, config) {
|
|
|
67147
68064
|
printInfo(`Run a task: open-agents run "your task here" --backend ollama`);
|
|
67148
68065
|
printInfo(`Check status: open-agents status`);
|
|
67149
68066
|
}
|
|
68067
|
+
const apiPort = opts.port ?? 11435;
|
|
68068
|
+
printSection("Starting API Server");
|
|
68069
|
+
printKeyValue("Port", String(apiPort), 2);
|
|
68070
|
+
printKeyValue("Ollama proxy", baseUrl, 2);
|
|
68071
|
+
const server = startApiServer({
|
|
68072
|
+
port: apiPort,
|
|
68073
|
+
verbose: opts.verbose,
|
|
68074
|
+
ollamaUrl: baseUrl
|
|
68075
|
+
});
|
|
68076
|
+
await new Promise((resolve36) => {
|
|
68077
|
+
server.on("close", resolve36);
|
|
68078
|
+
});
|
|
67150
68079
|
}
|
|
67151
68080
|
async function serveVllm(opts, config) {
|
|
67152
68081
|
const port = opts.port ?? 8e3;
|
|
@@ -67182,8 +68111,8 @@ async function serveVllm(opts, config) {
|
|
|
67182
68111
|
await runVllmServer(args, opts.verbose ?? false);
|
|
67183
68112
|
}
|
|
67184
68113
|
async function runVllmServer(args, verbose) {
|
|
67185
|
-
return new Promise((
|
|
67186
|
-
const child =
|
|
68114
|
+
return new Promise((resolve36, reject) => {
|
|
68115
|
+
const child = spawn22("python", args, {
|
|
67187
68116
|
stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
|
|
67188
68117
|
env: { ...process.env }
|
|
67189
68118
|
});
|
|
@@ -67217,10 +68146,10 @@ async function runVllmServer(args, verbose) {
|
|
|
67217
68146
|
child.once("exit", (code, signal) => {
|
|
67218
68147
|
if (signal) {
|
|
67219
68148
|
printInfo(`vLLM server stopped by signal ${signal}`);
|
|
67220
|
-
|
|
68149
|
+
resolve36();
|
|
67221
68150
|
} else if (code === 0) {
|
|
67222
68151
|
printSuccess("vLLM server exited cleanly");
|
|
67223
|
-
|
|
68152
|
+
resolve36();
|
|
67224
68153
|
} else {
|
|
67225
68154
|
printError(`vLLM server exited with code ${code}`);
|
|
67226
68155
|
reject(new Error(`vLLM exited with code ${code}`));
|
|
@@ -67234,11 +68163,12 @@ async function runVllmServer(args, verbose) {
|
|
|
67234
68163
|
process.once("SIGTERM", () => forwardSignal("SIGTERM"));
|
|
67235
68164
|
});
|
|
67236
68165
|
}
|
|
67237
|
-
var
|
|
68166
|
+
var init_serve2 = __esm({
|
|
67238
68167
|
"packages/cli/dist/commands/serve.js"() {
|
|
67239
68168
|
"use strict";
|
|
67240
68169
|
init_dist();
|
|
67241
68170
|
init_output();
|
|
68171
|
+
init_serve();
|
|
67242
68172
|
}
|
|
67243
68173
|
});
|
|
67244
68174
|
|
|
@@ -67248,8 +68178,8 @@ __export(eval_exports, {
|
|
|
67248
68178
|
evalCommand: () => evalCommand
|
|
67249
68179
|
});
|
|
67250
68180
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
67251
|
-
import { mkdirSync as
|
|
67252
|
-
import { join as
|
|
68181
|
+
import { mkdirSync as mkdirSync27, writeFileSync as writeFileSync26 } from "node:fs";
|
|
68182
|
+
import { join as join72 } from "node:path";
|
|
67253
68183
|
async function evalCommand(opts, config) {
|
|
67254
68184
|
const suiteName = opts.suite ?? "basic";
|
|
67255
68185
|
const suite = SUITES[suiteName];
|
|
@@ -67290,17 +68220,17 @@ async function evalCommand(opts, config) {
|
|
|
67290
68220
|
rawBackend = new FakeBackend();
|
|
67291
68221
|
}
|
|
67292
68222
|
const backend = {
|
|
67293
|
-
async complete(
|
|
68223
|
+
async complete(request2) {
|
|
67294
68224
|
const result = await rawBackend.complete({
|
|
67295
|
-
messages:
|
|
68225
|
+
messages: request2.messages.map((m) => ({
|
|
67296
68226
|
id: globalThis.crypto.randomUUID(),
|
|
67297
68227
|
sessionId: globalThis.crypto.randomUUID(),
|
|
67298
68228
|
role: m.role,
|
|
67299
68229
|
content: m.content,
|
|
67300
68230
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
67301
68231
|
})),
|
|
67302
|
-
maxTokens:
|
|
67303
|
-
temperature:
|
|
68232
|
+
maxTokens: request2.maxTokens,
|
|
68233
|
+
temperature: request2.temperature
|
|
67304
68234
|
});
|
|
67305
68235
|
return { content: result.content ?? "" };
|
|
67306
68236
|
}
|
|
@@ -67374,9 +68304,9 @@ async function evalCommand(opts, config) {
|
|
|
67374
68304
|
process.exit(failed > 0 ? 1 : 0);
|
|
67375
68305
|
}
|
|
67376
68306
|
function createTempEvalRepo() {
|
|
67377
|
-
const dir =
|
|
67378
|
-
|
|
67379
|
-
|
|
68307
|
+
const dir = join72(tmpdir10(), `open-agents-eval-${Date.now()}`);
|
|
68308
|
+
mkdirSync27(dir, { recursive: true });
|
|
68309
|
+
writeFileSync26(join72(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
|
|
67380
68310
|
return dir;
|
|
67381
68311
|
}
|
|
67382
68312
|
var BASIC_SUITE, FULL_SUITE, SUITES;
|
|
@@ -67434,9 +68364,9 @@ init_config();
|
|
|
67434
68364
|
init_output();
|
|
67435
68365
|
init_updater();
|
|
67436
68366
|
import { parseArgs as nodeParseArgs2 } from "node:util";
|
|
67437
|
-
import { createRequire as
|
|
67438
|
-
import { fileURLToPath as
|
|
67439
|
-
import { dirname as
|
|
68367
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
68368
|
+
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
68369
|
+
import { dirname as dirname22, join as join73 } from "node:path";
|
|
67440
68370
|
|
|
67441
68371
|
// packages/cli/dist/cli.js
|
|
67442
68372
|
import { createInterface } from "node:readline";
|
|
@@ -67540,10 +68470,10 @@ Options:
|
|
|
67540
68470
|
init_config();
|
|
67541
68471
|
init_spinner();
|
|
67542
68472
|
init_output();
|
|
67543
|
-
function
|
|
68473
|
+
function getVersion5() {
|
|
67544
68474
|
try {
|
|
67545
|
-
const require2 =
|
|
67546
|
-
const pkgPath =
|
|
68475
|
+
const require2 = createRequire4(import.meta.url);
|
|
68476
|
+
const pkgPath = join73(dirname22(fileURLToPath14(import.meta.url)), "..", "package.json");
|
|
67547
68477
|
const pkg = require2(pkgPath);
|
|
67548
68478
|
return pkg.version;
|
|
67549
68479
|
} catch {
|
|
@@ -67697,7 +68627,7 @@ Examples:
|
|
|
67697
68627
|
process.stdout.write(text + "\n");
|
|
67698
68628
|
}
|
|
67699
68629
|
async function main() {
|
|
67700
|
-
const version =
|
|
68630
|
+
const version = getVersion5();
|
|
67701
68631
|
const parsed = parseCliArgs(process.argv);
|
|
67702
68632
|
if (parsed.version) {
|
|
67703
68633
|
process.stdout.write(`open-agents v${version}
|
|
@@ -67778,7 +68708,7 @@ async function main() {
|
|
|
67778
68708
|
break;
|
|
67779
68709
|
}
|
|
67780
68710
|
case "serve": {
|
|
67781
|
-
const { serveCommand: serveCommand2 } = await Promise.resolve().then(() => (
|
|
68711
|
+
const { serveCommand: serveCommand2 } = await Promise.resolve().then(() => (init_serve2(), serve_exports));
|
|
67782
68712
|
await serveCommand2({
|
|
67783
68713
|
port: parsed.servePort,
|
|
67784
68714
|
model: parsed.model,
|