open-agents-ai 0.92.0 → 0.93.1
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 +770 -424
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -320,23 +320,39 @@ async function checkForUpdate(currentVersion, forceCheck = false) {
|
|
|
320
320
|
latestVersion: latest
|
|
321
321
|
};
|
|
322
322
|
}
|
|
323
|
+
function cleanStaleNpmTempDirs(sudo) {
|
|
324
|
+
try {
|
|
325
|
+
const prefix = execSync("npm prefix -g", { encoding: "utf-8", stdio: "pipe", timeout: 5e3 }).trim();
|
|
326
|
+
const globalModules = prefix.endsWith("/lib") ? prefix + "/node_modules" : prefix + "/lib/node_modules";
|
|
327
|
+
const sudoCmd = sudo ? "sudo " : "";
|
|
328
|
+
execSync(`${sudoCmd}find "${globalModules}" -maxdepth 1 -name ".${PACKAGE_NAME}-*" -type d -exec rm -rf {} + 2>/dev/null || true`, { stdio: "pipe", timeout: 15e3 });
|
|
329
|
+
execSync(`${sudoCmd}rm -rf "${globalModules}/${PACKAGE_NAME}" 2>/dev/null || true`, { stdio: "pipe", timeout: 15e3 });
|
|
330
|
+
} catch {
|
|
331
|
+
}
|
|
332
|
+
}
|
|
323
333
|
function performSilentUpdate() {
|
|
324
334
|
const installCmd = `npm install -g ${PACKAGE_NAME}@latest --prefer-online`;
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
335
|
+
const trySilent = (cmd, sudo) => {
|
|
336
|
+
try {
|
|
337
|
+
execSync(cmd, { stdio: "pipe", timeout: 12e4 });
|
|
338
|
+
return true;
|
|
339
|
+
} catch (err) {
|
|
340
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
341
|
+
if (/ENOTEMPTY|errno -39/i.test(msg)) {
|
|
342
|
+
cleanStaleNpmTempDirs(sudo);
|
|
343
|
+
try {
|
|
344
|
+
execSync(cmd, { stdio: "pipe", timeout: 12e4 });
|
|
345
|
+
return true;
|
|
346
|
+
} catch {
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
336
349
|
}
|
|
350
|
+
return false;
|
|
337
351
|
}
|
|
338
|
-
|
|
339
|
-
|
|
352
|
+
};
|
|
353
|
+
if (trySilent(installCmd, false))
|
|
354
|
+
return true;
|
|
355
|
+
return trySilent(`sudo -n ${installCmd}`, true);
|
|
340
356
|
}
|
|
341
357
|
function formatUpdateBanner(info) {
|
|
342
358
|
return `
|
|
@@ -10743,10 +10759,319 @@ var init_opencode = __esm({
|
|
|
10743
10759
|
}
|
|
10744
10760
|
});
|
|
10745
10761
|
|
|
10762
|
+
// packages/execution/dist/tools/factory.js
|
|
10763
|
+
import { execSync as execSync20, spawn as spawn10 } from "node:child_process";
|
|
10764
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
10765
|
+
import { join as join27 } from "node:path";
|
|
10766
|
+
function findDroid() {
|
|
10767
|
+
for (const cmd of ["droid"]) {
|
|
10768
|
+
try {
|
|
10769
|
+
const path = execSync20(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
|
|
10770
|
+
if (path)
|
|
10771
|
+
return path;
|
|
10772
|
+
} catch {
|
|
10773
|
+
}
|
|
10774
|
+
}
|
|
10775
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
10776
|
+
const candidates = [
|
|
10777
|
+
join27(homeDir, ".factory", "bin", "droid"),
|
|
10778
|
+
join27(homeDir, "bin", "droid"),
|
|
10779
|
+
"/usr/local/bin/droid"
|
|
10780
|
+
];
|
|
10781
|
+
for (const p of candidates) {
|
|
10782
|
+
if (existsSync21(p))
|
|
10783
|
+
return p;
|
|
10784
|
+
}
|
|
10785
|
+
return null;
|
|
10786
|
+
}
|
|
10787
|
+
function getVersion2(binary) {
|
|
10788
|
+
try {
|
|
10789
|
+
return execSync20(`${binary} --version 2>/dev/null`, { stdio: "pipe", timeout: 1e4 }).toString().trim();
|
|
10790
|
+
} catch {
|
|
10791
|
+
return "unknown";
|
|
10792
|
+
}
|
|
10793
|
+
}
|
|
10794
|
+
function installDroid() {
|
|
10795
|
+
const platform4 = process.platform;
|
|
10796
|
+
try {
|
|
10797
|
+
if (platform4 === "win32") {
|
|
10798
|
+
execSync20('powershell -Command "irm https://app.factory.ai/cli/windows | iex"', {
|
|
10799
|
+
stdio: "pipe",
|
|
10800
|
+
timeout: 12e4
|
|
10801
|
+
});
|
|
10802
|
+
} else {
|
|
10803
|
+
execSync20("curl -fsSL https://app.factory.ai/cli | sh", {
|
|
10804
|
+
stdio: "pipe",
|
|
10805
|
+
timeout: 12e4
|
|
10806
|
+
});
|
|
10807
|
+
}
|
|
10808
|
+
const binary = findDroid();
|
|
10809
|
+
if (binary) {
|
|
10810
|
+
const version = getVersion2(binary);
|
|
10811
|
+
return { success: true, message: `Factory CLI installed successfully (${version}) at ${binary}` };
|
|
10812
|
+
}
|
|
10813
|
+
return { success: false, message: "Install script completed but droid binary not found in PATH" };
|
|
10814
|
+
} catch (err) {
|
|
10815
|
+
return {
|
|
10816
|
+
success: false,
|
|
10817
|
+
message: `Installation failed: ${err instanceof Error ? err.message : String(err)}`
|
|
10818
|
+
};
|
|
10819
|
+
}
|
|
10820
|
+
}
|
|
10821
|
+
var FactoryTool;
|
|
10822
|
+
var init_factory = __esm({
|
|
10823
|
+
"packages/execution/dist/tools/factory.js"() {
|
|
10824
|
+
"use strict";
|
|
10825
|
+
FactoryTool = class {
|
|
10826
|
+
name = "factory";
|
|
10827
|
+
description = "Delegate coding tasks to Factory AI's Droid, a high-performance autonomous coding agent. Actions: 'install' the Factory CLI if not present, 'run' a coding task via droid exec (non-interactive, fully autonomous), 'status' check availability and API key. Factory's Droid leads the Terminal Bench for code generation. Use this to offload complex coding tasks to a separate agent that can read, write, search, test, and commit code independently. Requires FACTORY_API_KEY environment variable.";
|
|
10828
|
+
parameters = {
|
|
10829
|
+
type: "object",
|
|
10830
|
+
properties: {
|
|
10831
|
+
action: {
|
|
10832
|
+
type: "string",
|
|
10833
|
+
enum: ["install", "run", "status"],
|
|
10834
|
+
description: "Action: 'install' Factory CLI, 'run' a coding task, 'status' check availability"
|
|
10835
|
+
},
|
|
10836
|
+
task: {
|
|
10837
|
+
type: "string",
|
|
10838
|
+
description: "The coding task to delegate (for 'run' action). Be specific about what files to modify and what outcome to achieve."
|
|
10839
|
+
},
|
|
10840
|
+
auto: {
|
|
10841
|
+
type: "string",
|
|
10842
|
+
enum: ["low", "medium", "high"],
|
|
10843
|
+
description: "Autonomy level controlling what droid can do. 'low': file edits only, 'medium': + install deps/git commit/build, 'high': + git push/prod deploys. Default: read-only (no --auto flag)."
|
|
10844
|
+
},
|
|
10845
|
+
model: {
|
|
10846
|
+
type: "string",
|
|
10847
|
+
description: "Model ID to use (optional, uses Factory default if omitted)"
|
|
10848
|
+
},
|
|
10849
|
+
directory: {
|
|
10850
|
+
type: "string",
|
|
10851
|
+
description: "Working directory for the task (optional, defaults to current project root)"
|
|
10852
|
+
},
|
|
10853
|
+
timeout_seconds: {
|
|
10854
|
+
type: "number",
|
|
10855
|
+
description: "Maximum execution time in seconds (default: 600 = 10 minutes)"
|
|
10856
|
+
},
|
|
10857
|
+
reasoning_effort: {
|
|
10858
|
+
type: "string",
|
|
10859
|
+
enum: ["low", "medium", "high"],
|
|
10860
|
+
description: "Reasoning effort level (optional, defaults to medium)"
|
|
10861
|
+
},
|
|
10862
|
+
output_format: {
|
|
10863
|
+
type: "string",
|
|
10864
|
+
enum: ["text", "json", "stream-json"],
|
|
10865
|
+
description: "Output format: 'text' for human-readable, 'json' for structured, 'stream-json' for JSONL events (default: 'text')"
|
|
10866
|
+
},
|
|
10867
|
+
session_id: {
|
|
10868
|
+
type: "string",
|
|
10869
|
+
description: "Continue an existing session by ID (optional)"
|
|
10870
|
+
}
|
|
10871
|
+
},
|
|
10872
|
+
required: ["action"]
|
|
10873
|
+
};
|
|
10874
|
+
workingDir;
|
|
10875
|
+
constructor(workingDir) {
|
|
10876
|
+
this.workingDir = workingDir;
|
|
10877
|
+
}
|
|
10878
|
+
async execute(args) {
|
|
10879
|
+
const start = performance.now();
|
|
10880
|
+
const action = String(args["action"] ?? "status");
|
|
10881
|
+
try {
|
|
10882
|
+
switch (action) {
|
|
10883
|
+
case "install":
|
|
10884
|
+
return this.doInstall(start);
|
|
10885
|
+
case "run":
|
|
10886
|
+
return await this.doRun(args, start);
|
|
10887
|
+
case "status":
|
|
10888
|
+
return this.doStatus(start);
|
|
10889
|
+
default:
|
|
10890
|
+
return {
|
|
10891
|
+
success: false,
|
|
10892
|
+
output: "",
|
|
10893
|
+
error: `Unknown action '${action}'. Use: install, run, status`,
|
|
10894
|
+
durationMs: performance.now() - start
|
|
10895
|
+
};
|
|
10896
|
+
}
|
|
10897
|
+
} catch (err) {
|
|
10898
|
+
return {
|
|
10899
|
+
success: false,
|
|
10900
|
+
output: "",
|
|
10901
|
+
error: `factory error: ${err instanceof Error ? err.message : String(err)}`,
|
|
10902
|
+
durationMs: performance.now() - start
|
|
10903
|
+
};
|
|
10904
|
+
}
|
|
10905
|
+
}
|
|
10906
|
+
doInstall(start) {
|
|
10907
|
+
const existing = findDroid();
|
|
10908
|
+
if (existing) {
|
|
10909
|
+
const version = getVersion2(existing);
|
|
10910
|
+
return {
|
|
10911
|
+
success: true,
|
|
10912
|
+
output: `Factory CLI (droid) is already installed at ${existing} (${version}). No action needed.`,
|
|
10913
|
+
durationMs: performance.now() - start
|
|
10914
|
+
};
|
|
10915
|
+
}
|
|
10916
|
+
const result = installDroid();
|
|
10917
|
+
return {
|
|
10918
|
+
success: result.success,
|
|
10919
|
+
output: result.success ? result.message : "",
|
|
10920
|
+
error: result.success ? void 0 : result.message,
|
|
10921
|
+
durationMs: performance.now() - start
|
|
10922
|
+
};
|
|
10923
|
+
}
|
|
10924
|
+
async doRun(args, start) {
|
|
10925
|
+
const task = String(args["task"] ?? "");
|
|
10926
|
+
if (!task) {
|
|
10927
|
+
return { success: false, output: "", error: "task is required for run action", durationMs: performance.now() - start };
|
|
10928
|
+
}
|
|
10929
|
+
if (!process.env.FACTORY_API_KEY) {
|
|
10930
|
+
return {
|
|
10931
|
+
success: false,
|
|
10932
|
+
output: "",
|
|
10933
|
+
error: "FACTORY_API_KEY environment variable is not set. Get one from https://app.factory.ai/settings and export FACTORY_API_KEY=fk-...",
|
|
10934
|
+
durationMs: performance.now() - start
|
|
10935
|
+
};
|
|
10936
|
+
}
|
|
10937
|
+
let binary = findDroid();
|
|
10938
|
+
if (!binary) {
|
|
10939
|
+
const installResult = installDroid();
|
|
10940
|
+
if (!installResult.success) {
|
|
10941
|
+
return {
|
|
10942
|
+
success: false,
|
|
10943
|
+
output: "",
|
|
10944
|
+
error: `droid CLI not found and auto-install failed: ${installResult.message}`,
|
|
10945
|
+
durationMs: performance.now() - start
|
|
10946
|
+
};
|
|
10947
|
+
}
|
|
10948
|
+
binary = findDroid();
|
|
10949
|
+
if (!binary) {
|
|
10950
|
+
return {
|
|
10951
|
+
success: false,
|
|
10952
|
+
output: "",
|
|
10953
|
+
error: "Factory CLI installed but droid binary not found in PATH. Try adding it to your PATH.",
|
|
10954
|
+
durationMs: performance.now() - start
|
|
10955
|
+
};
|
|
10956
|
+
}
|
|
10957
|
+
}
|
|
10958
|
+
const dir = String(args["directory"] ?? this.workingDir);
|
|
10959
|
+
const model = args["model"] ? String(args["model"]) : void 0;
|
|
10960
|
+
const auto = args["auto"] ? String(args["auto"]) : void 0;
|
|
10961
|
+
const outputFormat = args["output_format"] ? String(args["output_format"]) : "text";
|
|
10962
|
+
const reasoningEffort = args["reasoning_effort"] ? String(args["reasoning_effort"]) : void 0;
|
|
10963
|
+
const sessionId = args["session_id"] ? String(args["session_id"]) : void 0;
|
|
10964
|
+
const timeoutSec = typeof args["timeout_seconds"] === "number" ? args["timeout_seconds"] : 600;
|
|
10965
|
+
const cmdArgs = ["exec"];
|
|
10966
|
+
if (model)
|
|
10967
|
+
cmdArgs.push("--model", model);
|
|
10968
|
+
if (auto)
|
|
10969
|
+
cmdArgs.push("--auto", auto);
|
|
10970
|
+
if (outputFormat !== "text")
|
|
10971
|
+
cmdArgs.push("--output-format", outputFormat);
|
|
10972
|
+
if (reasoningEffort)
|
|
10973
|
+
cmdArgs.push("--reasoning-effort", reasoningEffort);
|
|
10974
|
+
if (sessionId)
|
|
10975
|
+
cmdArgs.push("--session-id", sessionId);
|
|
10976
|
+
cmdArgs.push("--cwd", dir);
|
|
10977
|
+
cmdArgs.push(task);
|
|
10978
|
+
return new Promise((resolvePromise) => {
|
|
10979
|
+
let output = "";
|
|
10980
|
+
const maxOutput = 5e5;
|
|
10981
|
+
let timedOut = false;
|
|
10982
|
+
const child = spawn10(binary, cmdArgs, {
|
|
10983
|
+
cwd: dir,
|
|
10984
|
+
env: { ...process.env },
|
|
10985
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
10986
|
+
});
|
|
10987
|
+
child.stdout?.on("data", (chunk) => {
|
|
10988
|
+
if (output.length < maxOutput) {
|
|
10989
|
+
output += chunk.toString();
|
|
10990
|
+
}
|
|
10991
|
+
});
|
|
10992
|
+
child.stderr?.on("data", (chunk) => {
|
|
10993
|
+
if (output.length < maxOutput) {
|
|
10994
|
+
output += chunk.toString();
|
|
10995
|
+
}
|
|
10996
|
+
});
|
|
10997
|
+
const timer = setTimeout(() => {
|
|
10998
|
+
timedOut = true;
|
|
10999
|
+
try {
|
|
11000
|
+
child.kill("SIGTERM");
|
|
11001
|
+
} catch {
|
|
11002
|
+
}
|
|
11003
|
+
}, timeoutSec * 1e3);
|
|
11004
|
+
child.on("close", (code) => {
|
|
11005
|
+
clearTimeout(timer);
|
|
11006
|
+
if (timedOut) {
|
|
11007
|
+
resolvePromise({
|
|
11008
|
+
success: false,
|
|
11009
|
+
output: output.slice(-1e4),
|
|
11010
|
+
error: `droid exec timed out after ${timeoutSec}s. Partial output included.`,
|
|
11011
|
+
durationMs: performance.now() - start
|
|
11012
|
+
});
|
|
11013
|
+
return;
|
|
11014
|
+
}
|
|
11015
|
+
const truncated = output.length > 5e4 ? output.slice(0, 5e3) + "\n\n...(truncated)...\n\n" + output.slice(-1e4) : output;
|
|
11016
|
+
resolvePromise({
|
|
11017
|
+
success: code === 0,
|
|
11018
|
+
output: truncated || "(no output)",
|
|
11019
|
+
error: code !== 0 ? `droid exec exited with code ${code}` : void 0,
|
|
11020
|
+
durationMs: performance.now() - start
|
|
11021
|
+
});
|
|
11022
|
+
});
|
|
11023
|
+
child.on("error", (err) => {
|
|
11024
|
+
clearTimeout(timer);
|
|
11025
|
+
resolvePromise({
|
|
11026
|
+
success: false,
|
|
11027
|
+
output: "",
|
|
11028
|
+
error: `Failed to spawn droid: ${err.message}`,
|
|
11029
|
+
durationMs: performance.now() - start
|
|
11030
|
+
});
|
|
11031
|
+
});
|
|
11032
|
+
});
|
|
11033
|
+
}
|
|
11034
|
+
doStatus(start) {
|
|
11035
|
+
const binary = findDroid();
|
|
11036
|
+
const hasApiKey = !!process.env.FACTORY_API_KEY;
|
|
11037
|
+
if (binary) {
|
|
11038
|
+
const version = getVersion2(binary);
|
|
11039
|
+
const lines = [
|
|
11040
|
+
`Factory CLI (droid) is installed`,
|
|
11041
|
+
` Binary: ${binary}`,
|
|
11042
|
+
` Version: ${version}`,
|
|
11043
|
+
` API Key: ${hasApiKey ? "set" : "NOT SET \u2014 export FACTORY_API_KEY=fk-..."}`,
|
|
11044
|
+
``,
|
|
11045
|
+
`Usage: factory(action='run', task='your coding task', auto='low')`,
|
|
11046
|
+
` Autonomy levels: omit for read-only, 'low' for edits, 'medium' for builds/deps, 'high' for git push`,
|
|
11047
|
+
` The task runs fully autonomously via droid exec.`
|
|
11048
|
+
];
|
|
11049
|
+
return {
|
|
11050
|
+
success: true,
|
|
11051
|
+
output: lines.join("\n"),
|
|
11052
|
+
durationMs: performance.now() - start
|
|
11053
|
+
};
|
|
11054
|
+
}
|
|
11055
|
+
return {
|
|
11056
|
+
success: true,
|
|
11057
|
+
output: [
|
|
11058
|
+
`Factory CLI (droid) is NOT installed.`,
|
|
11059
|
+
` API Key: ${hasApiKey ? "set" : "NOT SET \u2014 export FACTORY_API_KEY=fk-..."}`,
|
|
11060
|
+
``,
|
|
11061
|
+
`Use factory(action='install') to install it.`,
|
|
11062
|
+
`Manual install: curl -fsSL https://app.factory.ai/cli | sh`
|
|
11063
|
+
].join("\n"),
|
|
11064
|
+
durationMs: performance.now() - start
|
|
11065
|
+
};
|
|
11066
|
+
}
|
|
11067
|
+
};
|
|
11068
|
+
}
|
|
11069
|
+
});
|
|
11070
|
+
|
|
10746
11071
|
// packages/execution/dist/tools/cron-agent.js
|
|
10747
|
-
import { execSync as
|
|
11072
|
+
import { execSync as execSync21 } from "node:child_process";
|
|
10748
11073
|
import { readFile as readFile12, writeFile as writeFile11, mkdir as mkdir7 } from "node:fs/promises";
|
|
10749
|
-
import { resolve as resolve25, join as
|
|
11074
|
+
import { resolve as resolve25, join as join28 } from "node:path";
|
|
10750
11075
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
10751
11076
|
function isValidCron2(expr) {
|
|
10752
11077
|
const parts = expr.trim().split(/\s+/);
|
|
@@ -10808,19 +11133,19 @@ function resolveSchedule2(schedule) {
|
|
|
10808
11133
|
}
|
|
10809
11134
|
function getCurrentCrontab2() {
|
|
10810
11135
|
try {
|
|
10811
|
-
return
|
|
11136
|
+
return execSync21("crontab -l 2>/dev/null", { stdio: "pipe" }).toString().split("\n");
|
|
10812
11137
|
} catch {
|
|
10813
11138
|
return [];
|
|
10814
11139
|
}
|
|
10815
11140
|
}
|
|
10816
11141
|
function writeCrontab2(lines) {
|
|
10817
11142
|
const content = lines.join("\n") + "\n";
|
|
10818
|
-
|
|
11143
|
+
execSync21(`echo ${JSON.stringify(content)} | crontab -`, { stdio: "pipe" });
|
|
10819
11144
|
}
|
|
10820
11145
|
function findOaBinary2() {
|
|
10821
11146
|
for (const cmd of ["oa", "open-agents"]) {
|
|
10822
11147
|
try {
|
|
10823
|
-
const path =
|
|
11148
|
+
const path = execSync21(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
|
|
10824
11149
|
if (path)
|
|
10825
11150
|
return path;
|
|
10826
11151
|
} catch {
|
|
@@ -10832,7 +11157,7 @@ function installCronAgentJob(job, workingDir) {
|
|
|
10832
11157
|
const lines = getCurrentCrontab2();
|
|
10833
11158
|
const oaBin = findOaBinary2();
|
|
10834
11159
|
const logDir = resolve25(workingDir, ".oa", "cron-agents", "logs");
|
|
10835
|
-
const logFile =
|
|
11160
|
+
const logFile = join28(logDir, `${job.id}.log`);
|
|
10836
11161
|
const storeFile = resolve25(workingDir, ".oa", "cron-agents", "store.json");
|
|
10837
11162
|
const taskEscaped = job.task.replace(/'/g, "'\\''");
|
|
10838
11163
|
const jobId = job.id;
|
|
@@ -10871,9 +11196,9 @@ async function loadStore2(workingDir) {
|
|
|
10871
11196
|
async function saveStore2(workingDir, store) {
|
|
10872
11197
|
const dir = resolve25(workingDir, ".oa", "cron-agents");
|
|
10873
11198
|
await mkdir7(dir, { recursive: true });
|
|
10874
|
-
await mkdir7(
|
|
11199
|
+
await mkdir7(join28(dir, "logs"), { recursive: true });
|
|
10875
11200
|
store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
10876
|
-
await writeFile11(
|
|
11201
|
+
await writeFile11(join28(dir, "store.json"), JSON.stringify(store, null, 2), "utf-8");
|
|
10877
11202
|
}
|
|
10878
11203
|
var LONG_HORIZON_PRESETS, CRON_AGENT_MARKER, CronAgentTool;
|
|
10879
11204
|
var init_cron_agent = __esm({
|
|
@@ -11163,7 +11488,7 @@ ${truncated}`, durationMs: performance.now() - start };
|
|
|
11163
11488
|
];
|
|
11164
11489
|
if (job.verifyCommand) {
|
|
11165
11490
|
try {
|
|
11166
|
-
const result =
|
|
11491
|
+
const result = execSync21(job.verifyCommand, {
|
|
11167
11492
|
cwd: this.workingDir,
|
|
11168
11493
|
stdio: "pipe",
|
|
11169
11494
|
timeout: 3e4
|
|
@@ -11210,10 +11535,10 @@ ${truncated}`, durationMs: performance.now() - start };
|
|
|
11210
11535
|
|
|
11211
11536
|
// packages/execution/dist/tools/nexus.js
|
|
11212
11537
|
import { readFile as readFile13, writeFile as writeFile12, mkdir as mkdir8, chmod, unlink, readdir as readdir3, open as fsOpen } from "node:fs/promises";
|
|
11213
|
-
import { existsSync as
|
|
11214
|
-
import { resolve as resolve26, join as
|
|
11538
|
+
import { existsSync as existsSync22, readFileSync as readFileSync15 } from "node:fs";
|
|
11539
|
+
import { resolve as resolve26, join as join29 } from "node:path";
|
|
11215
11540
|
import { randomBytes as randomBytes6, createCipheriv, createDecipheriv, scryptSync, createHash } from "node:crypto";
|
|
11216
|
-
import { execSync as
|
|
11541
|
+
import { execSync as execSync22, spawn as spawn11 } from "node:child_process";
|
|
11217
11542
|
import { hostname, userInfo } from "node:os";
|
|
11218
11543
|
function containsKeyMaterial(input) {
|
|
11219
11544
|
for (const pattern of KEY_PATTERNS) {
|
|
@@ -12247,7 +12572,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12247
12572
|
this.nexusDir = resolve26(repoRoot, ".oa", "nexus");
|
|
12248
12573
|
}
|
|
12249
12574
|
async ensureDir() {
|
|
12250
|
-
if (!
|
|
12575
|
+
if (!existsSync22(this.nexusDir)) {
|
|
12251
12576
|
await mkdir8(this.nexusDir, { recursive: true });
|
|
12252
12577
|
}
|
|
12253
12578
|
}
|
|
@@ -12362,8 +12687,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12362
12687
|
// Daemon management
|
|
12363
12688
|
// =========================================================================
|
|
12364
12689
|
getDaemonPid() {
|
|
12365
|
-
const pidFile =
|
|
12366
|
-
if (!
|
|
12690
|
+
const pidFile = join29(this.nexusDir, "daemon.pid");
|
|
12691
|
+
if (!existsSync22(pidFile))
|
|
12367
12692
|
return null;
|
|
12368
12693
|
try {
|
|
12369
12694
|
const pid = parseInt(readFileSync15(pidFile, "utf8").trim(), 10);
|
|
@@ -12378,16 +12703,16 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12378
12703
|
if (!pid)
|
|
12379
12704
|
throw new Error("Nexus daemon not running. Use action 'connect' first.");
|
|
12380
12705
|
const cmdId = randomBytes6(8).toString("hex");
|
|
12381
|
-
const cmdFile =
|
|
12382
|
-
const respFile =
|
|
12383
|
-
if (
|
|
12706
|
+
const cmdFile = join29(this.nexusDir, "cmd.json");
|
|
12707
|
+
const respFile = join29(this.nexusDir, "resp.json");
|
|
12708
|
+
if (existsSync22(respFile))
|
|
12384
12709
|
await unlink(respFile).catch(() => {
|
|
12385
12710
|
});
|
|
12386
12711
|
await writeFile12(cmdFile, JSON.stringify({ id: cmdId, action, args }, null, 2));
|
|
12387
12712
|
const polls = Math.ceil(timeoutMs / 500);
|
|
12388
12713
|
for (let i = 0; i < polls; i++) {
|
|
12389
12714
|
await new Promise((r) => setTimeout(r, 500));
|
|
12390
|
-
if (!
|
|
12715
|
+
if (!existsSync22(respFile))
|
|
12391
12716
|
continue;
|
|
12392
12717
|
try {
|
|
12393
12718
|
const resp = JSON.parse(await readFile13(respFile, "utf8"));
|
|
@@ -12414,8 +12739,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12414
12739
|
await this.ensureDir();
|
|
12415
12740
|
const existingPid = this.getDaemonPid();
|
|
12416
12741
|
if (existingPid) {
|
|
12417
|
-
const statusFile2 =
|
|
12418
|
-
if (
|
|
12742
|
+
const statusFile2 = join29(this.nexusDir, "status.json");
|
|
12743
|
+
if (existsSync22(statusFile2)) {
|
|
12419
12744
|
try {
|
|
12420
12745
|
const status = JSON.parse(await readFile13(statusFile2, "utf8"));
|
|
12421
12746
|
if (status.connected && status.peerId) {
|
|
@@ -12431,8 +12756,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12431
12756
|
await new Promise((r) => setTimeout(r, 500));
|
|
12432
12757
|
}
|
|
12433
12758
|
for (const f of ["daemon.pid", "status.json", "cmd.json", "resp.json"]) {
|
|
12434
|
-
const p =
|
|
12435
|
-
if (
|
|
12759
|
+
const p = join29(this.nexusDir, f);
|
|
12760
|
+
if (existsSync22(p))
|
|
12436
12761
|
await unlink(p).catch(() => {
|
|
12437
12762
|
});
|
|
12438
12763
|
}
|
|
@@ -12440,8 +12765,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12440
12765
|
let nexusResolved = false;
|
|
12441
12766
|
let installedVersion = "";
|
|
12442
12767
|
try {
|
|
12443
|
-
const nexusPkg =
|
|
12444
|
-
if (
|
|
12768
|
+
const nexusPkg = join29(nodeModulesDir, "open-agents-nexus", "package.json");
|
|
12769
|
+
if (existsSync22(nexusPkg)) {
|
|
12445
12770
|
nexusResolved = true;
|
|
12446
12771
|
try {
|
|
12447
12772
|
const pkg = JSON.parse(readFileSync15(nexusPkg, "utf8"));
|
|
@@ -12449,9 +12774,9 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12449
12774
|
} catch {
|
|
12450
12775
|
}
|
|
12451
12776
|
} else {
|
|
12452
|
-
const globalDir =
|
|
12453
|
-
const globalPkg =
|
|
12454
|
-
if (
|
|
12777
|
+
const globalDir = execSync22("npm root -g", { encoding: "utf8", timeout: 5e3 }).trim();
|
|
12778
|
+
const globalPkg = join29(globalDir, "open-agents-nexus", "package.json");
|
|
12779
|
+
if (existsSync22(globalPkg)) {
|
|
12455
12780
|
nexusResolved = true;
|
|
12456
12781
|
try {
|
|
12457
12782
|
const pkg = JSON.parse(readFileSync15(globalPkg, "utf8"));
|
|
@@ -12464,13 +12789,13 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12464
12789
|
}
|
|
12465
12790
|
if (nexusResolved && installedVersion) {
|
|
12466
12791
|
try {
|
|
12467
|
-
const latestRaw =
|
|
12792
|
+
const latestRaw = execSync22("npm view open-agents-nexus version 2>/dev/null", {
|
|
12468
12793
|
encoding: "utf8",
|
|
12469
12794
|
timeout: 8e3
|
|
12470
12795
|
}).trim();
|
|
12471
12796
|
if (latestRaw && latestRaw !== installedVersion) {
|
|
12472
12797
|
try {
|
|
12473
|
-
|
|
12798
|
+
execSync22(`npm install open-agents-nexus@${latestRaw} --save 2>&1`, {
|
|
12474
12799
|
cwd: this.repoRoot,
|
|
12475
12800
|
stdio: "pipe",
|
|
12476
12801
|
timeout: 6e4
|
|
@@ -12484,30 +12809,30 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12484
12809
|
}
|
|
12485
12810
|
if (!nexusResolved) {
|
|
12486
12811
|
try {
|
|
12487
|
-
|
|
12812
|
+
execSync22("npm install open-agents-nexus@latest 2>&1", {
|
|
12488
12813
|
cwd: this.repoRoot,
|
|
12489
12814
|
stdio: "pipe",
|
|
12490
12815
|
timeout: 12e4
|
|
12491
12816
|
});
|
|
12492
12817
|
} catch {
|
|
12493
12818
|
try {
|
|
12494
|
-
|
|
12819
|
+
execSync22("npm install -g open-agents-nexus@latest 2>&1", { stdio: "pipe", timeout: 12e4 });
|
|
12495
12820
|
} catch {
|
|
12496
12821
|
throw new Error("Failed to install open-agents-nexus. Run: npm install open-agents-nexus");
|
|
12497
12822
|
}
|
|
12498
12823
|
}
|
|
12499
12824
|
}
|
|
12500
|
-
const daemonPath =
|
|
12825
|
+
const daemonPath = join29(this.nexusDir, "nexus-daemon.mjs");
|
|
12501
12826
|
await writeFile12(daemonPath, DAEMON_SCRIPT);
|
|
12502
12827
|
const agentName = args.agent_name || "open-agents-node";
|
|
12503
12828
|
const agentType = args.agent_type || "general";
|
|
12504
12829
|
const nodePaths = [nodeModulesDir];
|
|
12505
12830
|
try {
|
|
12506
|
-
const globalDir =
|
|
12831
|
+
const globalDir = execSync22("npm root -g", { encoding: "utf8", timeout: 5e3 }).trim();
|
|
12507
12832
|
nodePaths.push(globalDir);
|
|
12508
12833
|
} catch {
|
|
12509
12834
|
}
|
|
12510
|
-
const child =
|
|
12835
|
+
const child = spawn11("node", [daemonPath, this.nexusDir, agentName, agentType], {
|
|
12511
12836
|
detached: true,
|
|
12512
12837
|
stdio: ["ignore", "pipe", "pipe"],
|
|
12513
12838
|
cwd: this.repoRoot,
|
|
@@ -12522,10 +12847,10 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12522
12847
|
child.stderr?.on("data", (d) => {
|
|
12523
12848
|
earlyError += d.toString();
|
|
12524
12849
|
});
|
|
12525
|
-
const statusFile =
|
|
12850
|
+
const statusFile = join29(this.nexusDir, "status.json");
|
|
12526
12851
|
for (let i = 0; i < 40; i++) {
|
|
12527
12852
|
await new Promise((r) => setTimeout(r, 500));
|
|
12528
|
-
if (
|
|
12853
|
+
if (existsSync22(statusFile)) {
|
|
12529
12854
|
try {
|
|
12530
12855
|
const status = JSON.parse(await readFile13(statusFile, "utf8"));
|
|
12531
12856
|
if (status.error) {
|
|
@@ -12566,8 +12891,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12566
12891
|
} catch {
|
|
12567
12892
|
}
|
|
12568
12893
|
for (const f of ["daemon.pid", "status.json", "cmd.json", "resp.json"]) {
|
|
12569
|
-
const p =
|
|
12570
|
-
if (
|
|
12894
|
+
const p = join29(this.nexusDir, f);
|
|
12895
|
+
if (existsSync22(p))
|
|
12571
12896
|
await unlink(p).catch(() => {
|
|
12572
12897
|
});
|
|
12573
12898
|
}
|
|
@@ -12577,8 +12902,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12577
12902
|
const pid = this.getDaemonPid();
|
|
12578
12903
|
if (!pid)
|
|
12579
12904
|
return "Nexus daemon not running. Use action 'connect' to start.";
|
|
12580
|
-
const statusFile =
|
|
12581
|
-
if (!
|
|
12905
|
+
const statusFile = join29(this.nexusDir, "status.json");
|
|
12906
|
+
if (!existsSync22(statusFile))
|
|
12582
12907
|
return `Daemon running (pid: ${pid}) but no status yet.`;
|
|
12583
12908
|
try {
|
|
12584
12909
|
const status = JSON.parse(await readFile13(statusFile, "utf8"));
|
|
@@ -12592,8 +12917,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12592
12917
|
` Capabilities: ${(status.capabilities || []).length ? (status.capabilities || []).join(", ") : "none"}`,
|
|
12593
12918
|
` Blocked peers: ${(status.blockedPeers || []).length || 0}`
|
|
12594
12919
|
];
|
|
12595
|
-
const walletPath =
|
|
12596
|
-
if (
|
|
12920
|
+
const walletPath = join29(this.nexusDir, "wallet.enc");
|
|
12921
|
+
if (existsSync22(walletPath)) {
|
|
12597
12922
|
try {
|
|
12598
12923
|
const w = JSON.parse(await readFile13(walletPath, "utf8"));
|
|
12599
12924
|
lines.push(` Wallet: ${w.address}`);
|
|
@@ -12603,14 +12928,14 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12603
12928
|
} else {
|
|
12604
12929
|
lines.push(` Wallet: not configured`);
|
|
12605
12930
|
}
|
|
12606
|
-
const inboxDir =
|
|
12607
|
-
if (
|
|
12931
|
+
const inboxDir = join29(this.nexusDir, "inbox");
|
|
12932
|
+
if (existsSync22(inboxDir)) {
|
|
12608
12933
|
try {
|
|
12609
12934
|
const roomDirs = await readdir3(inboxDir);
|
|
12610
12935
|
let totalMsgs = 0;
|
|
12611
12936
|
for (const rd of roomDirs) {
|
|
12612
12937
|
try {
|
|
12613
|
-
totalMsgs += (await readdir3(
|
|
12938
|
+
totalMsgs += (await readdir3(join29(inboxDir, rd))).length;
|
|
12614
12939
|
} catch {
|
|
12615
12940
|
}
|
|
12616
12941
|
}
|
|
@@ -12657,10 +12982,10 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12657
12982
|
}
|
|
12658
12983
|
async doReadMessages(args) {
|
|
12659
12984
|
const roomId = args.room_id;
|
|
12660
|
-
const inboxDir =
|
|
12985
|
+
const inboxDir = join29(this.nexusDir, "inbox");
|
|
12661
12986
|
if (roomId) {
|
|
12662
|
-
const roomInbox =
|
|
12663
|
-
if (!
|
|
12987
|
+
const roomInbox = join29(inboxDir, roomId);
|
|
12988
|
+
if (!existsSync22(roomInbox))
|
|
12664
12989
|
return `No messages in room: ${roomId}`;
|
|
12665
12990
|
const files = (await readdir3(roomInbox)).sort().slice(-20);
|
|
12666
12991
|
if (files.length === 0)
|
|
@@ -12668,7 +12993,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12668
12993
|
const messages = [`Messages in ${roomId} (last ${files.length}):`];
|
|
12669
12994
|
for (const f of files) {
|
|
12670
12995
|
try {
|
|
12671
|
-
const msg = JSON.parse(await readFile13(
|
|
12996
|
+
const msg = JSON.parse(await readFile13(join29(roomInbox, f), "utf8"));
|
|
12672
12997
|
const sender = (msg.sender || "unknown").slice(0, 12);
|
|
12673
12998
|
messages.push(` [${new Date(msg.timestamp).toLocaleTimeString()}] ${sender}...: ${msg.content}`);
|
|
12674
12999
|
} catch {
|
|
@@ -12676,7 +13001,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12676
13001
|
}
|
|
12677
13002
|
return messages.join("\n");
|
|
12678
13003
|
}
|
|
12679
|
-
if (!
|
|
13004
|
+
if (!existsSync22(inboxDir))
|
|
12680
13005
|
return "No messages received yet.";
|
|
12681
13006
|
const roomDirs = await readdir3(inboxDir);
|
|
12682
13007
|
if (roomDirs.length === 0)
|
|
@@ -12684,7 +13009,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12684
13009
|
const lines = ["Inbox:"];
|
|
12685
13010
|
for (const rd of roomDirs) {
|
|
12686
13011
|
try {
|
|
12687
|
-
const count = (await readdir3(
|
|
13012
|
+
const count = (await readdir3(join29(inboxDir, rd))).length;
|
|
12688
13013
|
lines.push(` ${rd}: ${count} message(s)`);
|
|
12689
13014
|
} catch {
|
|
12690
13015
|
}
|
|
@@ -12696,8 +13021,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12696
13021
|
// ---------------------------------------------------------------------------
|
|
12697
13022
|
async doWalletStatus() {
|
|
12698
13023
|
await this.ensureDir();
|
|
12699
|
-
const walletPath =
|
|
12700
|
-
if (!
|
|
13024
|
+
const walletPath = join29(this.nexusDir, "wallet.enc");
|
|
13025
|
+
if (!existsSync22(walletPath)) {
|
|
12701
13026
|
return "No wallet configured. Use wallet_create to set one up.";
|
|
12702
13027
|
}
|
|
12703
13028
|
try {
|
|
@@ -12735,8 +13060,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12735
13060
|
}
|
|
12736
13061
|
async doWalletCreate(args) {
|
|
12737
13062
|
await this.ensureDir();
|
|
12738
|
-
const walletPath =
|
|
12739
|
-
if (
|
|
13063
|
+
const walletPath = join29(this.nexusDir, "wallet.enc");
|
|
13064
|
+
if (existsSync22(walletPath))
|
|
12740
13065
|
return "Wallet already exists. Delete wallet.enc to create a new one.";
|
|
12741
13066
|
const userAddress = args.wallet_address;
|
|
12742
13067
|
if (userAddress) {
|
|
@@ -12781,7 +13106,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12781
13106
|
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
12782
13107
|
let enc = cipher.update(privKeyHex, "utf8", "hex");
|
|
12783
13108
|
enc += cipher.final("hex");
|
|
12784
|
-
const x402KeyPath =
|
|
13109
|
+
const x402KeyPath = join29(this.nexusDir, "x402-wallet.key");
|
|
12785
13110
|
const x402Fh = await fsOpen(x402KeyPath, "w", 384);
|
|
12786
13111
|
await x402Fh.writeFile("0x" + privKeyHex);
|
|
12787
13112
|
await x402Fh.close();
|
|
@@ -12852,8 +13177,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12852
13177
|
// ---------------------------------------------------------------------------
|
|
12853
13178
|
async doLedgerStatus() {
|
|
12854
13179
|
await this.ensureDir();
|
|
12855
|
-
const ledgerPath =
|
|
12856
|
-
if (!
|
|
13180
|
+
const ledgerPath = join29(this.nexusDir, "ledger.jsonl");
|
|
13181
|
+
if (!existsSync22(ledgerPath)) {
|
|
12857
13182
|
return "No ledger entries. Earnings and spending will be tracked here after x402 transactions.";
|
|
12858
13183
|
}
|
|
12859
13184
|
try {
|
|
@@ -12894,8 +13219,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12894
13219
|
}
|
|
12895
13220
|
}
|
|
12896
13221
|
async getLedgerSummary() {
|
|
12897
|
-
const ledgerPath =
|
|
12898
|
-
if (!
|
|
13222
|
+
const ledgerPath = join29(this.nexusDir, "ledger.jsonl");
|
|
13223
|
+
if (!existsSync22(ledgerPath))
|
|
12899
13224
|
return null;
|
|
12900
13225
|
try {
|
|
12901
13226
|
const raw = await readFile13(ledgerPath, "utf8");
|
|
@@ -12919,16 +13244,16 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12919
13244
|
}
|
|
12920
13245
|
async appendLedger(entry) {
|
|
12921
13246
|
await this.ensureDir();
|
|
12922
|
-
const ledgerPath =
|
|
13247
|
+
const ledgerPath = join29(this.nexusDir, "ledger.jsonl");
|
|
12923
13248
|
const line = JSON.stringify(entry) + "\n";
|
|
12924
|
-
await writeFile12(ledgerPath,
|
|
13249
|
+
await writeFile12(ledgerPath, existsSync22(ledgerPath) ? await readFile13(ledgerPath, "utf8") + line : line);
|
|
12925
13250
|
}
|
|
12926
13251
|
// ---------------------------------------------------------------------------
|
|
12927
13252
|
// Step 4: Budget Policy — Spending limits and auto-approve thresholds
|
|
12928
13253
|
// ---------------------------------------------------------------------------
|
|
12929
13254
|
async loadBudget() {
|
|
12930
|
-
const budgetPath =
|
|
12931
|
-
if (!
|
|
13255
|
+
const budgetPath = join29(this.nexusDir, "budget.json");
|
|
13256
|
+
if (!existsSync22(budgetPath))
|
|
12932
13257
|
return null;
|
|
12933
13258
|
try {
|
|
12934
13259
|
return JSON.parse(await readFile13(budgetPath, "utf8"));
|
|
@@ -12937,8 +13262,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12937
13262
|
}
|
|
12938
13263
|
}
|
|
12939
13264
|
async ensureDefaultBudget() {
|
|
12940
|
-
const budgetPath =
|
|
12941
|
-
if (
|
|
13265
|
+
const budgetPath = join29(this.nexusDir, "budget.json");
|
|
13266
|
+
if (existsSync22(budgetPath))
|
|
12942
13267
|
return;
|
|
12943
13268
|
const defaultBudget = {
|
|
12944
13269
|
version: 1,
|
|
@@ -13007,13 +13332,13 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13007
13332
|
if (changes.length === 0) {
|
|
13008
13333
|
return "No budget parameters provided. Use daily_limit, per_invoke_max, or auto_approve_below.";
|
|
13009
13334
|
}
|
|
13010
|
-
const budgetPath =
|
|
13335
|
+
const budgetPath = join29(this.nexusDir, "budget.json");
|
|
13011
13336
|
await writeFile12(budgetPath, JSON.stringify(budget, null, 2));
|
|
13012
13337
|
return `Budget updated: ${changes.join(", ")}`;
|
|
13013
13338
|
}
|
|
13014
13339
|
async getTodaySpending() {
|
|
13015
|
-
const ledgerPath =
|
|
13016
|
-
if (!
|
|
13340
|
+
const ledgerPath = join29(this.nexusDir, "ledger.jsonl");
|
|
13341
|
+
if (!existsSync22(ledgerPath))
|
|
13017
13342
|
return 0;
|
|
13018
13343
|
try {
|
|
13019
13344
|
const todayPrefix = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -13056,8 +13381,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13056
13381
|
if (todaySpent + amountUsdc > budget.dailyLimitUsdc) {
|
|
13057
13382
|
return { allowed: false, reason: `Would exceed daily limit ($${((todaySpent + amountUsdc) / 1e6).toFixed(6)} > $${(budget.dailyLimitUsdc / 1e6).toFixed(6)})` };
|
|
13058
13383
|
}
|
|
13059
|
-
const walletPath =
|
|
13060
|
-
if (
|
|
13384
|
+
const walletPath = join29(this.nexusDir, "wallet.enc");
|
|
13385
|
+
if (existsSync22(walletPath)) {
|
|
13061
13386
|
try {
|
|
13062
13387
|
const w = JSON.parse(await readFile13(walletPath, "utf8"));
|
|
13063
13388
|
if (w.version === 2 && w.address) {
|
|
@@ -13087,8 +13412,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13087
13412
|
const budgetResult = await this.checkBudget(amountSmallest, "transfer:direct", targetAddress);
|
|
13088
13413
|
if (!budgetResult.allowed)
|
|
13089
13414
|
return `BLOCKED by budget policy: ${budgetResult.reason}`;
|
|
13090
|
-
const walletPath =
|
|
13091
|
-
if (!
|
|
13415
|
+
const walletPath = join29(this.nexusDir, "wallet.enc");
|
|
13416
|
+
if (!existsSync22(walletPath))
|
|
13092
13417
|
throw new Error("No wallet. Use wallet_create first.");
|
|
13093
13418
|
const w = JSON.parse(await readFile13(walletPath, "utf8"));
|
|
13094
13419
|
if (!w.encryptedKey)
|
|
@@ -13148,7 +13473,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13148
13473
|
capability: "transfer:direct",
|
|
13149
13474
|
note: "signed, awaiting submission"
|
|
13150
13475
|
});
|
|
13151
|
-
const proofFile =
|
|
13476
|
+
const proofFile = join29(this.nexusDir, "pending-transfer.json");
|
|
13152
13477
|
const proof = {
|
|
13153
13478
|
from: account.address,
|
|
13154
13479
|
to: targetAddress,
|
|
@@ -13190,8 +13515,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13190
13515
|
throw new Error("prompt is required");
|
|
13191
13516
|
const estimatedTokens = Math.ceil(prompt.length / 4) + 1e3;
|
|
13192
13517
|
let estimatedCostSmallest = 0;
|
|
13193
|
-
const pricingPath =
|
|
13194
|
-
if (
|
|
13518
|
+
const pricingPath = join29(this.nexusDir, "pricing.json");
|
|
13519
|
+
if (existsSync22(pricingPath)) {
|
|
13195
13520
|
try {
|
|
13196
13521
|
const pricing = JSON.parse(await readFile13(pricingPath, "utf8"));
|
|
13197
13522
|
const modelPricing = (pricing.models || []).find((m) => m.model === model || m.model.startsWith(model.split(":")[0]));
|
|
@@ -13283,7 +13608,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13283
13608
|
}
|
|
13284
13609
|
async doInferenceProof() {
|
|
13285
13610
|
try {
|
|
13286
|
-
const psRaw =
|
|
13611
|
+
const psRaw = execSync22("ollama ps 2>/dev/null", { timeout: 1e4, encoding: "utf8" });
|
|
13287
13612
|
const lines = psRaw.trim().split("\n").filter((l) => l.trim());
|
|
13288
13613
|
if (lines.length < 2)
|
|
13289
13614
|
return "No model loaded. Run 'ollama ps' to check.";
|
|
@@ -13291,7 +13616,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13291
13616
|
const modelName = parts[0] || "unknown";
|
|
13292
13617
|
let gpuName = "none", vramMb = 0;
|
|
13293
13618
|
try {
|
|
13294
|
-
const smi =
|
|
13619
|
+
const smi = execSync22("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader 2>/dev/null", {
|
|
13295
13620
|
timeout: 5e3,
|
|
13296
13621
|
encoding: "utf8"
|
|
13297
13622
|
});
|
|
@@ -13300,7 +13625,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13300
13625
|
vramMb = parseInt(gp[1]?.trim() || "0", 10);
|
|
13301
13626
|
} catch {
|
|
13302
13627
|
try {
|
|
13303
|
-
|
|
13628
|
+
execSync22("rocm-smi 2>/dev/null", { timeout: 5e3 });
|
|
13304
13629
|
gpuName = "AMD GPU";
|
|
13305
13630
|
} catch {
|
|
13306
13631
|
}
|
|
@@ -13310,7 +13635,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13310
13635
|
const bar = (s) => "\u2588".repeat(Math.round(s / 5)) + "\u2591".repeat(20 - Math.round(s / 5));
|
|
13311
13636
|
const mem = vramMb > 24e3 ? 95 : vramMb > 16e3 ? 80 : vramMb > 8e3 ? 60 : vramMb > 0 ? 40 : 20;
|
|
13312
13637
|
await this.ensureDir();
|
|
13313
|
-
await writeFile12(
|
|
13638
|
+
await writeFile12(join29(this.nexusDir, "inference-proof.json"), JSON.stringify({
|
|
13314
13639
|
modelName,
|
|
13315
13640
|
gpuName,
|
|
13316
13641
|
vramMb,
|
|
@@ -13453,6 +13778,7 @@ var init_dist2 = __esm({
|
|
|
13453
13778
|
init_reminder();
|
|
13454
13779
|
init_agenda();
|
|
13455
13780
|
init_opencode();
|
|
13781
|
+
init_factory();
|
|
13456
13782
|
init_cron_agent();
|
|
13457
13783
|
init_nexus();
|
|
13458
13784
|
init_system_deps();
|
|
@@ -14139,14 +14465,14 @@ var init_dist3 = __esm({
|
|
|
14139
14465
|
});
|
|
14140
14466
|
|
|
14141
14467
|
// packages/orchestrator/dist/promptLoader.js
|
|
14142
|
-
import { readFileSync as readFileSync16, existsSync as
|
|
14143
|
-
import { join as
|
|
14468
|
+
import { readFileSync as readFileSync16, existsSync as existsSync23 } from "node:fs";
|
|
14469
|
+
import { join as join30, dirname as dirname10 } from "node:path";
|
|
14144
14470
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
14145
14471
|
function loadPrompt(promptPath, vars) {
|
|
14146
14472
|
let content = cache.get(promptPath);
|
|
14147
14473
|
if (content === void 0) {
|
|
14148
|
-
const fullPath =
|
|
14149
|
-
if (!
|
|
14474
|
+
const fullPath = join30(PROMPTS_DIR, promptPath);
|
|
14475
|
+
if (!existsSync23(fullPath)) {
|
|
14150
14476
|
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
14151
14477
|
}
|
|
14152
14478
|
content = readFileSync16(fullPath, "utf-8");
|
|
@@ -14162,7 +14488,7 @@ var init_promptLoader = __esm({
|
|
|
14162
14488
|
"use strict";
|
|
14163
14489
|
__filename = fileURLToPath7(import.meta.url);
|
|
14164
14490
|
__dirname3 = dirname10(__filename);
|
|
14165
|
-
PROMPTS_DIR =
|
|
14491
|
+
PROMPTS_DIR = join30(__dirname3, "..", "prompts");
|
|
14166
14492
|
cache = /* @__PURE__ */ new Map();
|
|
14167
14493
|
}
|
|
14168
14494
|
});
|
|
@@ -14542,7 +14868,7 @@ var init_code_retriever = __esm({
|
|
|
14542
14868
|
import { execFile as execFile5 } from "node:child_process";
|
|
14543
14869
|
import { promisify as promisify4 } from "node:util";
|
|
14544
14870
|
import { readFile as readFile14, readdir as readdir4, stat as stat3 } from "node:fs/promises";
|
|
14545
|
-
import { join as
|
|
14871
|
+
import { join as join31, extname as extname7 } from "node:path";
|
|
14546
14872
|
async function searchByPath(pathPattern, options) {
|
|
14547
14873
|
const allFiles = await collectFiles(options.rootDir, options.includeGlobs ?? DEFAULT_INCLUDE_GLOBS, options.excludeGlobs ?? DEFAULT_EXCLUDE_GLOBS);
|
|
14548
14874
|
const pattern = options.caseInsensitive ? pathPattern.toLowerCase() : pathPattern;
|
|
@@ -14684,7 +15010,7 @@ async function walkForFiles(rootDir, dir, excludeGlobs, results) {
|
|
|
14684
15010
|
continue;
|
|
14685
15011
|
if (excludeGlobs.some((g) => entry.name === g || matchesGlob(entry.name, g)))
|
|
14686
15012
|
continue;
|
|
14687
|
-
const absPath =
|
|
15013
|
+
const absPath = join31(dir, entry.name);
|
|
14688
15014
|
if (entry.isDirectory()) {
|
|
14689
15015
|
await walkForFiles(rootDir, absPath, excludeGlobs, results);
|
|
14690
15016
|
} else if (entry.isFile()) {
|
|
@@ -14991,7 +15317,7 @@ var init_graphExpand = __esm({
|
|
|
14991
15317
|
|
|
14992
15318
|
// packages/retrieval/dist/snippetPacker.js
|
|
14993
15319
|
import { readFile as readFile15 } from "node:fs/promises";
|
|
14994
|
-
import { join as
|
|
15320
|
+
import { join as join32 } from "node:path";
|
|
14995
15321
|
async function packSnippets(requests, opts = {}) {
|
|
14996
15322
|
const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
14997
15323
|
const contextLines = opts.contextLines ?? DEFAULT_CONTEXT_LINES;
|
|
@@ -15017,7 +15343,7 @@ async function packSnippets(requests, opts = {}) {
|
|
|
15017
15343
|
return { packed, dropped, totalTokens };
|
|
15018
15344
|
}
|
|
15019
15345
|
async function extractSnippet(req, repoRoot, contextLines = DEFAULT_CONTEXT_LINES) {
|
|
15020
|
-
const absPath = req.filePath.startsWith("/") ? req.filePath :
|
|
15346
|
+
const absPath = req.filePath.startsWith("/") ? req.filePath : join32(repoRoot, req.filePath);
|
|
15021
15347
|
let content;
|
|
15022
15348
|
try {
|
|
15023
15349
|
content = await readFile15(absPath, "utf-8");
|
|
@@ -17187,8 +17513,8 @@ ${marker}` : marker);
|
|
|
17187
17513
|
return;
|
|
17188
17514
|
try {
|
|
17189
17515
|
const { mkdirSync: mkdirSync18, writeFileSync: writeFileSync16 } = __require("node:fs");
|
|
17190
|
-
const { join:
|
|
17191
|
-
const sessionDir =
|
|
17516
|
+
const { join: join53 } = __require("node:path");
|
|
17517
|
+
const sessionDir = join53(this._workingDirectory, ".oa", "session", this._sessionId);
|
|
17192
17518
|
mkdirSync18(sessionDir, { recursive: true });
|
|
17193
17519
|
const checkpoint = {
|
|
17194
17520
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -17201,7 +17527,7 @@ ${marker}` : marker);
|
|
|
17201
17527
|
memexEntryCount: this._memexArchive.size,
|
|
17202
17528
|
fileRegistrySize: this._fileRegistry.size
|
|
17203
17529
|
};
|
|
17204
|
-
writeFileSync16(
|
|
17530
|
+
writeFileSync16(join53(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
|
|
17205
17531
|
} catch {
|
|
17206
17532
|
}
|
|
17207
17533
|
}
|
|
@@ -18978,9 +19304,9 @@ __export(listen_exports, {
|
|
|
18978
19304
|
isVideoPath: () => isVideoPath,
|
|
18979
19305
|
waitForTranscribeCli: () => waitForTranscribeCli
|
|
18980
19306
|
});
|
|
18981
|
-
import { spawn as
|
|
18982
|
-
import { existsSync as
|
|
18983
|
-
import { join as
|
|
19307
|
+
import { spawn as spawn12, execSync as execSync23 } from "node:child_process";
|
|
19308
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6, readdirSync as readdirSync6 } from "node:fs";
|
|
19309
|
+
import { join as join33, dirname as dirname11 } from "node:path";
|
|
18984
19310
|
import { homedir as homedir8 } from "node:os";
|
|
18985
19311
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
18986
19312
|
import { EventEmitter } from "node:events";
|
|
@@ -19000,7 +19326,7 @@ function findMicCaptureCommand() {
|
|
|
19000
19326
|
const platform4 = process.platform;
|
|
19001
19327
|
if (platform4 === "linux") {
|
|
19002
19328
|
try {
|
|
19003
|
-
|
|
19329
|
+
execSync23("which arecord", { stdio: "pipe" });
|
|
19004
19330
|
return {
|
|
19005
19331
|
cmd: "arecord",
|
|
19006
19332
|
args: ["-f", "S16_LE", "-r", "16000", "-c", "1", "-t", "raw", "-q", "-"]
|
|
@@ -19010,7 +19336,7 @@ function findMicCaptureCommand() {
|
|
|
19010
19336
|
}
|
|
19011
19337
|
if (platform4 === "darwin") {
|
|
19012
19338
|
try {
|
|
19013
|
-
|
|
19339
|
+
execSync23("which sox", { stdio: "pipe" });
|
|
19014
19340
|
return {
|
|
19015
19341
|
cmd: "sox",
|
|
19016
19342
|
args: ["-d", "-t", "raw", "-r", "16000", "-c", "1", "-b", "16", "-e", "signed-integer", "-"]
|
|
@@ -19019,7 +19345,7 @@ function findMicCaptureCommand() {
|
|
|
19019
19345
|
}
|
|
19020
19346
|
}
|
|
19021
19347
|
try {
|
|
19022
|
-
|
|
19348
|
+
execSync23("which ffmpeg", { stdio: "pipe" });
|
|
19023
19349
|
if (platform4 === "linux") {
|
|
19024
19350
|
return {
|
|
19025
19351
|
cmd: "ffmpeg",
|
|
@@ -19066,39 +19392,39 @@ function findMicCaptureCommand() {
|
|
|
19066
19392
|
function findLiveWhisperScript() {
|
|
19067
19393
|
const thisDir = dirname11(fileURLToPath8(import.meta.url));
|
|
19068
19394
|
const candidates = [
|
|
19069
|
-
|
|
19070
|
-
|
|
19071
|
-
|
|
19395
|
+
join33(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
|
|
19396
|
+
join33(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
|
|
19397
|
+
join33(thisDir, "../../execution/scripts/live-whisper.py"),
|
|
19072
19398
|
// npm install layout — scripts bundled alongside dist
|
|
19073
|
-
|
|
19074
|
-
|
|
19399
|
+
join33(thisDir, "../scripts/live-whisper.py"),
|
|
19400
|
+
join33(thisDir, "../../scripts/live-whisper.py")
|
|
19075
19401
|
];
|
|
19076
19402
|
for (const p of candidates) {
|
|
19077
|
-
if (
|
|
19403
|
+
if (existsSync24(p))
|
|
19078
19404
|
return p;
|
|
19079
19405
|
}
|
|
19080
19406
|
try {
|
|
19081
|
-
const globalRoot =
|
|
19407
|
+
const globalRoot = execSync23("npm root -g", {
|
|
19082
19408
|
encoding: "utf-8",
|
|
19083
19409
|
timeout: 5e3,
|
|
19084
19410
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19085
19411
|
}).trim();
|
|
19086
19412
|
const candidates2 = [
|
|
19087
|
-
|
|
19088
|
-
|
|
19413
|
+
join33(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
|
|
19414
|
+
join33(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
|
|
19089
19415
|
];
|
|
19090
19416
|
for (const p of candidates2) {
|
|
19091
|
-
if (
|
|
19417
|
+
if (existsSync24(p))
|
|
19092
19418
|
return p;
|
|
19093
19419
|
}
|
|
19094
19420
|
} catch {
|
|
19095
19421
|
}
|
|
19096
|
-
const nvmBase =
|
|
19097
|
-
if (
|
|
19422
|
+
const nvmBase = join33(homedir8(), ".nvm", "versions", "node");
|
|
19423
|
+
if (existsSync24(nvmBase)) {
|
|
19098
19424
|
try {
|
|
19099
19425
|
for (const ver of readdirSync6(nvmBase)) {
|
|
19100
|
-
const p =
|
|
19101
|
-
if (
|
|
19426
|
+
const p = join33(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
|
|
19427
|
+
if (existsSync24(p))
|
|
19102
19428
|
return p;
|
|
19103
19429
|
}
|
|
19104
19430
|
} catch {
|
|
@@ -19111,12 +19437,12 @@ function ensureTranscribeCliBackground() {
|
|
|
19111
19437
|
return;
|
|
19112
19438
|
_bgInstallPromise = (async () => {
|
|
19113
19439
|
try {
|
|
19114
|
-
const globalRoot =
|
|
19440
|
+
const globalRoot = execSync23("npm root -g", {
|
|
19115
19441
|
encoding: "utf-8",
|
|
19116
19442
|
timeout: 5e3,
|
|
19117
19443
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19118
19444
|
}).trim();
|
|
19119
|
-
if (
|
|
19445
|
+
if (existsSync24(join33(globalRoot, "transcribe-cli", "dist", "index.js"))) {
|
|
19120
19446
|
return true;
|
|
19121
19447
|
}
|
|
19122
19448
|
} catch {
|
|
@@ -19188,7 +19514,7 @@ var init_listen = __esm({
|
|
|
19188
19514
|
const timeout = setTimeout(() => {
|
|
19189
19515
|
reject(new Error("Whisper fallback: model load timeout (5 min). First run downloads the model."));
|
|
19190
19516
|
}, 3e5);
|
|
19191
|
-
this.process =
|
|
19517
|
+
this.process = spawn12("python3", [
|
|
19192
19518
|
this.scriptPath,
|
|
19193
19519
|
"--model",
|
|
19194
19520
|
this.model,
|
|
@@ -19317,7 +19643,7 @@ var init_listen = __esm({
|
|
|
19317
19643
|
}
|
|
19318
19644
|
if (!this.transcribeCliAvailable) {
|
|
19319
19645
|
try {
|
|
19320
|
-
|
|
19646
|
+
execSync23("which transcribe-cli", { stdio: "pipe" });
|
|
19321
19647
|
this.transcribeCliAvailable = true;
|
|
19322
19648
|
} catch {
|
|
19323
19649
|
this.transcribeCliAvailable = false;
|
|
@@ -19334,29 +19660,29 @@ var init_listen = __esm({
|
|
|
19334
19660
|
} catch {
|
|
19335
19661
|
}
|
|
19336
19662
|
try {
|
|
19337
|
-
const globalRoot =
|
|
19663
|
+
const globalRoot = execSync23("npm root -g", {
|
|
19338
19664
|
encoding: "utf-8",
|
|
19339
19665
|
timeout: 5e3,
|
|
19340
19666
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19341
19667
|
}).trim();
|
|
19342
|
-
const tcPath =
|
|
19343
|
-
if (
|
|
19668
|
+
const tcPath = join33(globalRoot, "transcribe-cli");
|
|
19669
|
+
if (existsSync24(join33(tcPath, "dist", "index.js"))) {
|
|
19344
19670
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
19345
19671
|
const req = createRequire4(import.meta.url);
|
|
19346
|
-
return req(
|
|
19672
|
+
return req(join33(tcPath, "dist", "index.js"));
|
|
19347
19673
|
}
|
|
19348
19674
|
} catch {
|
|
19349
19675
|
}
|
|
19350
|
-
const nvmBase =
|
|
19351
|
-
if (
|
|
19676
|
+
const nvmBase = join33(homedir8(), ".nvm", "versions", "node");
|
|
19677
|
+
if (existsSync24(nvmBase)) {
|
|
19352
19678
|
try {
|
|
19353
19679
|
const { readdirSync: readdirSync15 } = await import("node:fs");
|
|
19354
19680
|
for (const ver of readdirSync15(nvmBase)) {
|
|
19355
|
-
const tcPath =
|
|
19356
|
-
if (
|
|
19681
|
+
const tcPath = join33(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
|
|
19682
|
+
if (existsSync24(join33(tcPath, "dist", "index.js"))) {
|
|
19357
19683
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
19358
19684
|
const req = createRequire4(import.meta.url);
|
|
19359
|
-
return req(
|
|
19685
|
+
return req(join33(tcPath, "dist", "index.js"));
|
|
19360
19686
|
}
|
|
19361
19687
|
}
|
|
19362
19688
|
} catch {
|
|
@@ -19384,7 +19710,7 @@ var init_listen = __esm({
|
|
|
19384
19710
|
}
|
|
19385
19711
|
if (!tc) {
|
|
19386
19712
|
try {
|
|
19387
|
-
|
|
19713
|
+
execSync23("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
|
|
19388
19714
|
this.transcribeCliAvailable = null;
|
|
19389
19715
|
tc = await this.loadTranscribeCli();
|
|
19390
19716
|
} catch {
|
|
@@ -19470,7 +19796,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
19470
19796
|
return `Failed to start live transcription: ${msg}${tcHint}`;
|
|
19471
19797
|
}
|
|
19472
19798
|
}
|
|
19473
|
-
this.micProcess =
|
|
19799
|
+
this.micProcess = spawn12(micCmd.cmd, micCmd.args, {
|
|
19474
19800
|
stdio: ["pipe", "pipe", "pipe"],
|
|
19475
19801
|
env: { ...process.env }
|
|
19476
19802
|
});
|
|
@@ -19567,7 +19893,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
19567
19893
|
}
|
|
19568
19894
|
if (!tc) {
|
|
19569
19895
|
try {
|
|
19570
|
-
|
|
19896
|
+
execSync23("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
|
|
19571
19897
|
this.transcribeCliAvailable = null;
|
|
19572
19898
|
tc = await this.loadTranscribeCli();
|
|
19573
19899
|
} catch {
|
|
@@ -19621,7 +19947,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
19621
19947
|
}
|
|
19622
19948
|
if (!tc) {
|
|
19623
19949
|
try {
|
|
19624
|
-
|
|
19950
|
+
execSync23("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
|
|
19625
19951
|
this.transcribeCliAvailable = null;
|
|
19626
19952
|
tc = await this.loadTranscribeCli();
|
|
19627
19953
|
} catch {
|
|
@@ -19638,9 +19964,9 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
19638
19964
|
});
|
|
19639
19965
|
if (outputDir) {
|
|
19640
19966
|
const { basename: basename16 } = await import("node:path");
|
|
19641
|
-
const transcriptDir =
|
|
19967
|
+
const transcriptDir = join33(outputDir, ".oa", "transcripts");
|
|
19642
19968
|
mkdirSync6(transcriptDir, { recursive: true });
|
|
19643
|
-
const outFile =
|
|
19969
|
+
const outFile = join33(transcriptDir, `${basename16(filePath)}.txt`);
|
|
19644
19970
|
writeFileSync6(outFile, result.text, "utf-8");
|
|
19645
19971
|
}
|
|
19646
19972
|
return {
|
|
@@ -24209,7 +24535,7 @@ var init_render = __esm({
|
|
|
24209
24535
|
|
|
24210
24536
|
// packages/cli/dist/tui/voice-session.js
|
|
24211
24537
|
import { createServer } from "node:http";
|
|
24212
|
-
import { spawn as
|
|
24538
|
+
import { spawn as spawn13, execSync as execSync24 } from "node:child_process";
|
|
24213
24539
|
import { EventEmitter as EventEmitter2 } from "node:events";
|
|
24214
24540
|
function generateFrontendHTML() {
|
|
24215
24541
|
return `<!DOCTYPE html>
|
|
@@ -24863,7 +25189,7 @@ var init_voice_session = __esm({
|
|
|
24863
25189
|
const timeout = setTimeout(() => {
|
|
24864
25190
|
reject(new Error("Cloudflared tunnel start timeout (30s)"));
|
|
24865
25191
|
}, 3e4);
|
|
24866
|
-
this.cloudflaredProcess =
|
|
25192
|
+
this.cloudflaredProcess = spawn13("cloudflared", [
|
|
24867
25193
|
"tunnel",
|
|
24868
25194
|
"--url",
|
|
24869
25195
|
`http://127.0.0.1:${port}`
|
|
@@ -24937,7 +25263,7 @@ var init_voice_session = __esm({
|
|
|
24937
25263
|
|
|
24938
25264
|
// packages/cli/dist/tui/expose.js
|
|
24939
25265
|
import { createServer as createServer2, request as httpRequest } from "node:http";
|
|
24940
|
-
import { spawn as
|
|
25266
|
+
import { spawn as spawn14 } from "node:child_process";
|
|
24941
25267
|
import { EventEmitter as EventEmitter3 } from "node:events";
|
|
24942
25268
|
import { randomBytes as randomBytes7 } from "node:crypto";
|
|
24943
25269
|
import { URL as URL2 } from "node:url";
|
|
@@ -25113,7 +25439,7 @@ var init_expose = __esm({
|
|
|
25113
25439
|
const timeout = setTimeout(() => {
|
|
25114
25440
|
reject(new Error("Cloudflared tunnel start timeout (30s)"));
|
|
25115
25441
|
}, 3e4);
|
|
25116
|
-
this.cloudflaredProcess =
|
|
25442
|
+
this.cloudflaredProcess = spawn14("cloudflared", [
|
|
25117
25443
|
"tunnel",
|
|
25118
25444
|
"--url",
|
|
25119
25445
|
`http://127.0.0.1:${port}`
|
|
@@ -25216,8 +25542,8 @@ var init_types = __esm({
|
|
|
25216
25542
|
|
|
25217
25543
|
// packages/cli/dist/tui/p2p/secret-vault.js
|
|
25218
25544
|
import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes8, scryptSync as scryptSync2, createHash as createHash2 } from "node:crypto";
|
|
25219
|
-
import { readFileSync as readFileSync17, writeFileSync as writeFileSync7, existsSync as
|
|
25220
|
-
import { join as
|
|
25545
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync7, existsSync as existsSync25, mkdirSync as mkdirSync7 } from "node:fs";
|
|
25546
|
+
import { join as join34, dirname as dirname12 } from "node:path";
|
|
25221
25547
|
var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
|
|
25222
25548
|
var init_secret_vault = __esm({
|
|
25223
25549
|
"packages/cli/dist/tui/p2p/secret-vault.js"() {
|
|
@@ -25429,7 +25755,7 @@ var init_secret_vault = __esm({
|
|
|
25429
25755
|
const tag = cipher.getAuthTag();
|
|
25430
25756
|
const blob = Buffer.concat([salt, iv, tag, encrypted]);
|
|
25431
25757
|
const dir = dirname12(this.storePath);
|
|
25432
|
-
if (!
|
|
25758
|
+
if (!existsSync25(dir))
|
|
25433
25759
|
mkdirSync7(dir, { recursive: true });
|
|
25434
25760
|
writeFileSync7(this.storePath, blob, { mode: 384 });
|
|
25435
25761
|
}
|
|
@@ -25438,7 +25764,7 @@ var init_secret_vault = __esm({
|
|
|
25438
25764
|
* Returns the number of secrets loaded.
|
|
25439
25765
|
*/
|
|
25440
25766
|
load(passphrase) {
|
|
25441
|
-
if (!this.storePath || !
|
|
25767
|
+
if (!this.storePath || !existsSync25(this.storePath))
|
|
25442
25768
|
return 0;
|
|
25443
25769
|
const blob = readFileSync17(this.storePath);
|
|
25444
25770
|
if (blob.length < SALT_LEN + IV_LEN + 16) {
|
|
@@ -26660,14 +26986,14 @@ var init_render2 = __esm({
|
|
|
26660
26986
|
});
|
|
26661
26987
|
|
|
26662
26988
|
// packages/prompts/dist/promptLoader.js
|
|
26663
|
-
import { readFileSync as readFileSync18, existsSync as
|
|
26664
|
-
import { join as
|
|
26989
|
+
import { readFileSync as readFileSync18, existsSync as existsSync26 } from "node:fs";
|
|
26990
|
+
import { join as join35, dirname as dirname13 } from "node:path";
|
|
26665
26991
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
26666
26992
|
function loadPrompt2(promptPath, vars) {
|
|
26667
26993
|
let content = cache2.get(promptPath);
|
|
26668
26994
|
if (content === void 0) {
|
|
26669
|
-
const fullPath =
|
|
26670
|
-
if (!
|
|
26995
|
+
const fullPath = join35(PROMPTS_DIR2, promptPath);
|
|
26996
|
+
if (!existsSync26(fullPath)) {
|
|
26671
26997
|
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
26672
26998
|
}
|
|
26673
26999
|
content = readFileSync18(fullPath, "utf-8");
|
|
@@ -26683,9 +27009,9 @@ var init_promptLoader2 = __esm({
|
|
|
26683
27009
|
"use strict";
|
|
26684
27010
|
__filename2 = fileURLToPath9(import.meta.url);
|
|
26685
27011
|
__dirname4 = dirname13(__filename2);
|
|
26686
|
-
devPath =
|
|
26687
|
-
publishedPath =
|
|
26688
|
-
PROMPTS_DIR2 =
|
|
27012
|
+
devPath = join35(__dirname4, "..", "templates");
|
|
27013
|
+
publishedPath = join35(__dirname4, "..", "prompts", "templates");
|
|
27014
|
+
PROMPTS_DIR2 = existsSync26(devPath) ? devPath : publishedPath;
|
|
26689
27015
|
cache2 = /* @__PURE__ */ new Map();
|
|
26690
27016
|
}
|
|
26691
27017
|
});
|
|
@@ -26796,7 +27122,7 @@ var init_task_templates = __esm({
|
|
|
26796
27122
|
});
|
|
26797
27123
|
|
|
26798
27124
|
// packages/prompts/dist/index.js
|
|
26799
|
-
import { join as
|
|
27125
|
+
import { join as join36, dirname as dirname14 } from "node:path";
|
|
26800
27126
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
26801
27127
|
var _dir, _packageRoot;
|
|
26802
27128
|
var init_dist6 = __esm({
|
|
@@ -26807,23 +27133,23 @@ var init_dist6 = __esm({
|
|
|
26807
27133
|
init_task_templates();
|
|
26808
27134
|
init_render2();
|
|
26809
27135
|
_dir = dirname14(fileURLToPath10(import.meta.url));
|
|
26810
|
-
_packageRoot =
|
|
27136
|
+
_packageRoot = join36(_dir, "..");
|
|
26811
27137
|
}
|
|
26812
27138
|
});
|
|
26813
27139
|
|
|
26814
27140
|
// packages/cli/dist/tui/oa-directory.js
|
|
26815
|
-
import { existsSync as
|
|
26816
|
-
import { join as
|
|
27141
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync8, readFileSync as readFileSync19, writeFileSync as writeFileSync8, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync3 } from "node:fs";
|
|
27142
|
+
import { join as join37, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
|
|
26817
27143
|
import { homedir as homedir9 } from "node:os";
|
|
26818
27144
|
function initOaDirectory(repoRoot) {
|
|
26819
|
-
const oaPath =
|
|
27145
|
+
const oaPath = join37(repoRoot, OA_DIR);
|
|
26820
27146
|
for (const sub of SUBDIRS) {
|
|
26821
|
-
mkdirSync8(
|
|
27147
|
+
mkdirSync8(join37(oaPath, sub), { recursive: true });
|
|
26822
27148
|
}
|
|
26823
27149
|
try {
|
|
26824
|
-
const gitignorePath =
|
|
27150
|
+
const gitignorePath = join37(repoRoot, ".gitignore");
|
|
26825
27151
|
const settingsPattern = ".oa/settings.json";
|
|
26826
|
-
if (
|
|
27152
|
+
if (existsSync27(gitignorePath)) {
|
|
26827
27153
|
const content = readFileSync19(gitignorePath, "utf-8");
|
|
26828
27154
|
if (!content.includes(settingsPattern)) {
|
|
26829
27155
|
writeFileSync8(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
|
|
@@ -26834,12 +27160,12 @@ function initOaDirectory(repoRoot) {
|
|
|
26834
27160
|
return oaPath;
|
|
26835
27161
|
}
|
|
26836
27162
|
function hasOaDirectory(repoRoot) {
|
|
26837
|
-
return
|
|
27163
|
+
return existsSync27(join37(repoRoot, OA_DIR, "index"));
|
|
26838
27164
|
}
|
|
26839
27165
|
function loadProjectSettings(repoRoot) {
|
|
26840
|
-
const settingsPath =
|
|
27166
|
+
const settingsPath = join37(repoRoot, OA_DIR, "settings.json");
|
|
26841
27167
|
try {
|
|
26842
|
-
if (
|
|
27168
|
+
if (existsSync27(settingsPath)) {
|
|
26843
27169
|
return JSON.parse(readFileSync19(settingsPath, "utf-8"));
|
|
26844
27170
|
}
|
|
26845
27171
|
} catch {
|
|
@@ -26847,16 +27173,16 @@ function loadProjectSettings(repoRoot) {
|
|
|
26847
27173
|
return {};
|
|
26848
27174
|
}
|
|
26849
27175
|
function saveProjectSettings(repoRoot, settings) {
|
|
26850
|
-
const oaPath =
|
|
27176
|
+
const oaPath = join37(repoRoot, OA_DIR);
|
|
26851
27177
|
mkdirSync8(oaPath, { recursive: true });
|
|
26852
27178
|
const existing = loadProjectSettings(repoRoot);
|
|
26853
27179
|
const merged = { ...existing, ...settings };
|
|
26854
|
-
writeFileSync8(
|
|
27180
|
+
writeFileSync8(join37(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
26855
27181
|
}
|
|
26856
27182
|
function loadGlobalSettings() {
|
|
26857
|
-
const settingsPath =
|
|
27183
|
+
const settingsPath = join37(homedir9(), ".open-agents", "settings.json");
|
|
26858
27184
|
try {
|
|
26859
|
-
if (
|
|
27185
|
+
if (existsSync27(settingsPath)) {
|
|
26860
27186
|
return JSON.parse(readFileSync19(settingsPath, "utf-8"));
|
|
26861
27187
|
}
|
|
26862
27188
|
} catch {
|
|
@@ -26864,11 +27190,11 @@ function loadGlobalSettings() {
|
|
|
26864
27190
|
return {};
|
|
26865
27191
|
}
|
|
26866
27192
|
function saveGlobalSettings(settings) {
|
|
26867
|
-
const dir =
|
|
27193
|
+
const dir = join37(homedir9(), ".open-agents");
|
|
26868
27194
|
mkdirSync8(dir, { recursive: true });
|
|
26869
27195
|
const existing = loadGlobalSettings();
|
|
26870
27196
|
const merged = { ...existing, ...settings };
|
|
26871
|
-
writeFileSync8(
|
|
27197
|
+
writeFileSync8(join37(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
26872
27198
|
}
|
|
26873
27199
|
function resolveSettings(repoRoot) {
|
|
26874
27200
|
const global = loadGlobalSettings();
|
|
@@ -26883,9 +27209,9 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
26883
27209
|
while (dir && !visited.has(dir)) {
|
|
26884
27210
|
visited.add(dir);
|
|
26885
27211
|
for (const name of CONTEXT_FILES) {
|
|
26886
|
-
const filePath =
|
|
27212
|
+
const filePath = join37(dir, name);
|
|
26887
27213
|
const normalizedName = name.toLowerCase();
|
|
26888
|
-
if (
|
|
27214
|
+
if (existsSync27(filePath) && !seen.has(filePath)) {
|
|
26889
27215
|
seen.add(filePath);
|
|
26890
27216
|
try {
|
|
26891
27217
|
let content = readFileSync19(filePath, "utf-8");
|
|
@@ -26902,8 +27228,8 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
26902
27228
|
}
|
|
26903
27229
|
}
|
|
26904
27230
|
}
|
|
26905
|
-
const projectMap =
|
|
26906
|
-
if (
|
|
27231
|
+
const projectMap = join37(dir, OA_DIR, "context", "project-map.md");
|
|
27232
|
+
if (existsSync27(projectMap) && !seen.has(projectMap)) {
|
|
26907
27233
|
seen.add(projectMap);
|
|
26908
27234
|
try {
|
|
26909
27235
|
let content = readFileSync19(projectMap, "utf-8");
|
|
@@ -26918,7 +27244,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
26918
27244
|
} catch {
|
|
26919
27245
|
}
|
|
26920
27246
|
}
|
|
26921
|
-
const parent =
|
|
27247
|
+
const parent = join37(dir, "..");
|
|
26922
27248
|
if (parent === dir)
|
|
26923
27249
|
break;
|
|
26924
27250
|
dir = parent;
|
|
@@ -26936,7 +27262,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
26936
27262
|
return found;
|
|
26937
27263
|
}
|
|
26938
27264
|
function readIndexMeta(repoRoot) {
|
|
26939
|
-
const metaPath =
|
|
27265
|
+
const metaPath = join37(repoRoot, OA_DIR, "index", "meta.json");
|
|
26940
27266
|
try {
|
|
26941
27267
|
return JSON.parse(readFileSync19(metaPath, "utf-8"));
|
|
26942
27268
|
} catch {
|
|
@@ -26989,28 +27315,28 @@ ${tree}\`\`\`
|
|
|
26989
27315
|
sections.push("");
|
|
26990
27316
|
}
|
|
26991
27317
|
const content = sections.join("\n");
|
|
26992
|
-
const contextDir =
|
|
27318
|
+
const contextDir = join37(repoRoot, OA_DIR, "context");
|
|
26993
27319
|
mkdirSync8(contextDir, { recursive: true });
|
|
26994
|
-
writeFileSync8(
|
|
27320
|
+
writeFileSync8(join37(contextDir, "project-map.md"), content, "utf-8");
|
|
26995
27321
|
return content;
|
|
26996
27322
|
}
|
|
26997
27323
|
function saveSession(repoRoot, session) {
|
|
26998
|
-
const historyDir =
|
|
27324
|
+
const historyDir = join37(repoRoot, OA_DIR, "history");
|
|
26999
27325
|
mkdirSync8(historyDir, { recursive: true });
|
|
27000
|
-
writeFileSync8(
|
|
27326
|
+
writeFileSync8(join37(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
|
|
27001
27327
|
}
|
|
27002
27328
|
function loadRecentSessions(repoRoot, limit = 5) {
|
|
27003
|
-
const historyDir =
|
|
27004
|
-
if (!
|
|
27329
|
+
const historyDir = join37(repoRoot, OA_DIR, "history");
|
|
27330
|
+
if (!existsSync27(historyDir))
|
|
27005
27331
|
return [];
|
|
27006
27332
|
try {
|
|
27007
27333
|
const files = readdirSync7(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
|
|
27008
|
-
const stat5 = statSync9(
|
|
27334
|
+
const stat5 = statSync9(join37(historyDir, f));
|
|
27009
27335
|
return { file: f, mtime: stat5.mtimeMs };
|
|
27010
27336
|
}).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
|
|
27011
27337
|
return files.map((f) => {
|
|
27012
27338
|
try {
|
|
27013
|
-
return JSON.parse(readFileSync19(
|
|
27339
|
+
return JSON.parse(readFileSync19(join37(historyDir, f.file), "utf-8"));
|
|
27014
27340
|
} catch {
|
|
27015
27341
|
return null;
|
|
27016
27342
|
}
|
|
@@ -27020,14 +27346,14 @@ function loadRecentSessions(repoRoot, limit = 5) {
|
|
|
27020
27346
|
}
|
|
27021
27347
|
}
|
|
27022
27348
|
function savePendingTask(repoRoot, task) {
|
|
27023
|
-
const historyDir =
|
|
27349
|
+
const historyDir = join37(repoRoot, OA_DIR, "history");
|
|
27024
27350
|
mkdirSync8(historyDir, { recursive: true });
|
|
27025
|
-
writeFileSync8(
|
|
27351
|
+
writeFileSync8(join37(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
|
|
27026
27352
|
}
|
|
27027
27353
|
function loadPendingTask(repoRoot) {
|
|
27028
|
-
const filePath =
|
|
27354
|
+
const filePath = join37(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
|
|
27029
27355
|
try {
|
|
27030
|
-
if (!
|
|
27356
|
+
if (!existsSync27(filePath))
|
|
27031
27357
|
return null;
|
|
27032
27358
|
const data = JSON.parse(readFileSync19(filePath, "utf-8"));
|
|
27033
27359
|
try {
|
|
@@ -27040,12 +27366,12 @@ function loadPendingTask(repoRoot) {
|
|
|
27040
27366
|
}
|
|
27041
27367
|
}
|
|
27042
27368
|
function saveSessionContext(repoRoot, entry) {
|
|
27043
|
-
const contextDir =
|
|
27369
|
+
const contextDir = join37(repoRoot, OA_DIR, "context");
|
|
27044
27370
|
mkdirSync8(contextDir, { recursive: true });
|
|
27045
|
-
const filePath =
|
|
27371
|
+
const filePath = join37(contextDir, CONTEXT_SAVE_FILE);
|
|
27046
27372
|
let ctx;
|
|
27047
27373
|
try {
|
|
27048
|
-
if (
|
|
27374
|
+
if (existsSync27(filePath)) {
|
|
27049
27375
|
ctx = JSON.parse(readFileSync19(filePath, "utf-8"));
|
|
27050
27376
|
} else {
|
|
27051
27377
|
ctx = { entries: [], maxEntries: MAX_CONTEXT_ENTRIES, updatedAt: "" };
|
|
@@ -27061,9 +27387,9 @@ function saveSessionContext(repoRoot, entry) {
|
|
|
27061
27387
|
writeFileSync8(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
|
|
27062
27388
|
}
|
|
27063
27389
|
function loadSessionContext(repoRoot) {
|
|
27064
|
-
const filePath =
|
|
27390
|
+
const filePath = join37(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
|
|
27065
27391
|
try {
|
|
27066
|
-
if (!
|
|
27392
|
+
if (!existsSync27(filePath))
|
|
27067
27393
|
return null;
|
|
27068
27394
|
return JSON.parse(readFileSync19(filePath, "utf-8"));
|
|
27069
27395
|
} catch {
|
|
@@ -27112,8 +27438,8 @@ function detectManifests(repoRoot) {
|
|
|
27112
27438
|
{ file: "docker-compose.yaml", type: "Docker Compose" }
|
|
27113
27439
|
];
|
|
27114
27440
|
for (const check of checks) {
|
|
27115
|
-
const filePath =
|
|
27116
|
-
if (
|
|
27441
|
+
const filePath = join37(repoRoot, check.file);
|
|
27442
|
+
if (existsSync27(filePath)) {
|
|
27117
27443
|
let name;
|
|
27118
27444
|
if (check.nameField) {
|
|
27119
27445
|
try {
|
|
@@ -27146,7 +27472,7 @@ function findKeyFiles(repoRoot) {
|
|
|
27146
27472
|
{ pattern: "CLAUDE.md", description: "Claude Code context" }
|
|
27147
27473
|
];
|
|
27148
27474
|
for (const check of checks) {
|
|
27149
|
-
if (
|
|
27475
|
+
if (existsSync27(join37(repoRoot, check.pattern))) {
|
|
27150
27476
|
keyFiles.push({ path: check.pattern, description: check.description });
|
|
27151
27477
|
}
|
|
27152
27478
|
}
|
|
@@ -27172,12 +27498,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
27172
27498
|
if (entry.isDirectory()) {
|
|
27173
27499
|
let fileCount = 0;
|
|
27174
27500
|
try {
|
|
27175
|
-
fileCount = readdirSync7(
|
|
27501
|
+
fileCount = readdirSync7(join37(root, entry.name)).filter((f) => !f.startsWith(".")).length;
|
|
27176
27502
|
} catch {
|
|
27177
27503
|
}
|
|
27178
27504
|
result += `${prefix}${connector}${entry.name}/ (${fileCount})
|
|
27179
27505
|
`;
|
|
27180
|
-
result += buildDirTree(
|
|
27506
|
+
result += buildDirTree(join37(root, entry.name), maxDepth, childPrefix, depth + 1);
|
|
27181
27507
|
} else if (depth < maxDepth) {
|
|
27182
27508
|
result += `${prefix}${connector}${entry.name}
|
|
27183
27509
|
`;
|
|
@@ -27230,9 +27556,9 @@ var init_oa_directory = __esm({
|
|
|
27230
27556
|
|
|
27231
27557
|
// packages/cli/dist/tui/setup.js
|
|
27232
27558
|
import * as readline from "node:readline";
|
|
27233
|
-
import { execSync as
|
|
27234
|
-
import { existsSync as
|
|
27235
|
-
import { join as
|
|
27559
|
+
import { execSync as execSync25, spawn as spawn15 } from "node:child_process";
|
|
27560
|
+
import { existsSync as existsSync28, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9 } from "node:fs";
|
|
27561
|
+
import { join as join38 } from "node:path";
|
|
27236
27562
|
import { homedir as homedir10, platform } from "node:os";
|
|
27237
27563
|
function detectSystemSpecs() {
|
|
27238
27564
|
let totalRamGB = 0;
|
|
@@ -27240,7 +27566,7 @@ function detectSystemSpecs() {
|
|
|
27240
27566
|
let gpuVramGB = 0;
|
|
27241
27567
|
let gpuName = "";
|
|
27242
27568
|
try {
|
|
27243
|
-
const memInfo =
|
|
27569
|
+
const memInfo = execSync25("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
|
|
27244
27570
|
encoding: "utf8",
|
|
27245
27571
|
timeout: 5e3
|
|
27246
27572
|
});
|
|
@@ -27260,7 +27586,7 @@ function detectSystemSpecs() {
|
|
|
27260
27586
|
} catch {
|
|
27261
27587
|
}
|
|
27262
27588
|
try {
|
|
27263
|
-
const nvidiaSmi =
|
|
27589
|
+
const nvidiaSmi = execSync25("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
|
|
27264
27590
|
const lines = nvidiaSmi.trim().split("\n");
|
|
27265
27591
|
if (lines.length > 0) {
|
|
27266
27592
|
for (const line of lines) {
|
|
@@ -27385,7 +27711,7 @@ function ensureCurl() {
|
|
|
27385
27711
|
for (const s of strategies) {
|
|
27386
27712
|
if (hasCmd(s.check)) {
|
|
27387
27713
|
try {
|
|
27388
|
-
|
|
27714
|
+
execSync25(s.install, { stdio: "inherit", timeout: 12e4 });
|
|
27389
27715
|
if (hasCmd("curl")) {
|
|
27390
27716
|
process.stdout.write(` ${c2.green("\u2714")} curl installed via ${s.label}.
|
|
27391
27717
|
`);
|
|
@@ -27399,7 +27725,7 @@ function ensureCurl() {
|
|
|
27399
27725
|
}
|
|
27400
27726
|
if (plat === "darwin") {
|
|
27401
27727
|
try {
|
|
27402
|
-
|
|
27728
|
+
execSync25("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
|
|
27403
27729
|
if (hasCmd("curl"))
|
|
27404
27730
|
return true;
|
|
27405
27731
|
} catch {
|
|
@@ -27434,7 +27760,7 @@ function installOllamaLinux() {
|
|
|
27434
27760
|
|
|
27435
27761
|
`);
|
|
27436
27762
|
try {
|
|
27437
|
-
|
|
27763
|
+
execSync25("curl -fsSL https://ollama.com/install.sh | sh", {
|
|
27438
27764
|
stdio: "inherit",
|
|
27439
27765
|
timeout: 3e5
|
|
27440
27766
|
});
|
|
@@ -27462,10 +27788,10 @@ async function installOllamaMac(_rl) {
|
|
|
27462
27788
|
|
|
27463
27789
|
`);
|
|
27464
27790
|
try {
|
|
27465
|
-
|
|
27791
|
+
execSync25('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
|
|
27466
27792
|
if (!hasCmd("brew")) {
|
|
27467
27793
|
try {
|
|
27468
|
-
const brewPrefix =
|
|
27794
|
+
const brewPrefix = existsSync28("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
|
|
27469
27795
|
process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
|
|
27470
27796
|
} catch {
|
|
27471
27797
|
}
|
|
@@ -27495,7 +27821,7 @@ async function installOllamaMac(_rl) {
|
|
|
27495
27821
|
|
|
27496
27822
|
`);
|
|
27497
27823
|
try {
|
|
27498
|
-
|
|
27824
|
+
execSync25("brew install ollama", {
|
|
27499
27825
|
stdio: "inherit",
|
|
27500
27826
|
timeout: 3e5
|
|
27501
27827
|
});
|
|
@@ -27522,7 +27848,7 @@ function installOllamaWindows() {
|
|
|
27522
27848
|
|
|
27523
27849
|
`);
|
|
27524
27850
|
try {
|
|
27525
|
-
|
|
27851
|
+
execSync25('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
|
|
27526
27852
|
stdio: "inherit",
|
|
27527
27853
|
timeout: 3e5
|
|
27528
27854
|
});
|
|
@@ -27573,7 +27899,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
|
|
|
27573
27899
|
process.stdout.write(` ${c2.cyan("\u25CF")} Starting ollama serve...
|
|
27574
27900
|
`);
|
|
27575
27901
|
try {
|
|
27576
|
-
const child =
|
|
27902
|
+
const child = spawn15("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
27577
27903
|
child.unref();
|
|
27578
27904
|
} catch {
|
|
27579
27905
|
process.stdout.write(` ${c2.yellow("\u26A0")} Could not start ollama serve.
|
|
@@ -27603,7 +27929,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
|
|
|
27603
27929
|
}
|
|
27604
27930
|
function pullModelWithAutoUpdate(tag) {
|
|
27605
27931
|
try {
|
|
27606
|
-
|
|
27932
|
+
execSync25(`ollama pull ${tag}`, {
|
|
27607
27933
|
stdio: "inherit",
|
|
27608
27934
|
timeout: 36e5
|
|
27609
27935
|
// 1 hour max
|
|
@@ -27623,7 +27949,7 @@ function pullModelWithAutoUpdate(tag) {
|
|
|
27623
27949
|
|
|
27624
27950
|
`);
|
|
27625
27951
|
try {
|
|
27626
|
-
|
|
27952
|
+
execSync25("curl -fsSL https://ollama.com/install.sh | sh", {
|
|
27627
27953
|
stdio: "inherit",
|
|
27628
27954
|
timeout: 3e5
|
|
27629
27955
|
// 5 min max for install
|
|
@@ -27634,7 +27960,7 @@ function pullModelWithAutoUpdate(tag) {
|
|
|
27634
27960
|
process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
|
|
27635
27961
|
|
|
27636
27962
|
`);
|
|
27637
|
-
|
|
27963
|
+
execSync25(`ollama pull ${tag}`, {
|
|
27638
27964
|
stdio: "inherit",
|
|
27639
27965
|
timeout: 36e5
|
|
27640
27966
|
});
|
|
@@ -27736,7 +28062,7 @@ function ensurePython3() {
|
|
|
27736
28062
|
if (plat === "darwin") {
|
|
27737
28063
|
if (hasCmd("brew")) {
|
|
27738
28064
|
try {
|
|
27739
|
-
|
|
28065
|
+
execSync25("brew install python3", { stdio: "inherit", timeout: 3e5 });
|
|
27740
28066
|
if (hasCmd("python3")) {
|
|
27741
28067
|
process.stdout.write(` ${c2.green("\u2714")} Python3 installed via Homebrew.
|
|
27742
28068
|
`);
|
|
@@ -27749,7 +28075,7 @@ function ensurePython3() {
|
|
|
27749
28075
|
for (const s of strategies) {
|
|
27750
28076
|
if (hasCmd(s.check)) {
|
|
27751
28077
|
try {
|
|
27752
|
-
|
|
28078
|
+
execSync25(s.install, { stdio: "inherit", timeout: 12e4 });
|
|
27753
28079
|
if (hasCmd("python3") || hasCmd("python")) {
|
|
27754
28080
|
process.stdout.write(` ${c2.green("\u2714")} Python3 installed via ${s.label}.
|
|
27755
28081
|
`);
|
|
@@ -27765,11 +28091,11 @@ function ensurePython3() {
|
|
|
27765
28091
|
}
|
|
27766
28092
|
function checkPythonVenv() {
|
|
27767
28093
|
try {
|
|
27768
|
-
|
|
28094
|
+
execSync25("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
27769
28095
|
return true;
|
|
27770
28096
|
} catch {
|
|
27771
28097
|
try {
|
|
27772
|
-
|
|
28098
|
+
execSync25("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
27773
28099
|
return true;
|
|
27774
28100
|
} catch {
|
|
27775
28101
|
return false;
|
|
@@ -27788,7 +28114,7 @@ function ensurePythonVenv() {
|
|
|
27788
28114
|
for (const s of strategies) {
|
|
27789
28115
|
if (hasCmd(s.check)) {
|
|
27790
28116
|
try {
|
|
27791
|
-
|
|
28117
|
+
execSync25(s.install, { stdio: "inherit", timeout: 12e4 });
|
|
27792
28118
|
if (checkPythonVenv()) {
|
|
27793
28119
|
process.stdout.write(` ${c2.green("\u2714")} python3-venv installed via ${s.label}.
|
|
27794
28120
|
`);
|
|
@@ -28041,7 +28367,7 @@ async function doSetup(config, rl) {
|
|
|
28041
28367
|
${c2.cyan("\u25CF")} Ollama is installed but not running. Starting automatically...
|
|
28042
28368
|
`);
|
|
28043
28369
|
try {
|
|
28044
|
-
const child =
|
|
28370
|
+
const child = spawn15("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
28045
28371
|
child.unref();
|
|
28046
28372
|
await new Promise((resolve31) => setTimeout(resolve31, 3e3));
|
|
28047
28373
|
try {
|
|
@@ -28069,7 +28395,7 @@ async function doSetup(config, rl) {
|
|
|
28069
28395
|
${c2.cyan("\u25CF")} Starting ollama serve...
|
|
28070
28396
|
`);
|
|
28071
28397
|
try {
|
|
28072
|
-
const child =
|
|
28398
|
+
const child = spawn15("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
28073
28399
|
child.unref();
|
|
28074
28400
|
await new Promise((resolve31) => setTimeout(resolve31, 3e3));
|
|
28075
28401
|
try {
|
|
@@ -28219,12 +28545,12 @@ async function doSetup(config, rl) {
|
|
|
28219
28545
|
`PARAMETER num_predict ${numPredict}`,
|
|
28220
28546
|
`PARAMETER stop "<|endoftext|>"`
|
|
28221
28547
|
].join("\n");
|
|
28222
|
-
const modelDir2 =
|
|
28548
|
+
const modelDir2 = join38(homedir10(), ".open-agents", "models");
|
|
28223
28549
|
mkdirSync9(modelDir2, { recursive: true });
|
|
28224
|
-
const modelfilePath =
|
|
28550
|
+
const modelfilePath = join38(modelDir2, `Modelfile.${customName}`);
|
|
28225
28551
|
writeFileSync9(modelfilePath, modelfileContent + "\n", "utf8");
|
|
28226
28552
|
process.stdout.write(` ${c2.dim("Creating model...")} `);
|
|
28227
|
-
|
|
28553
|
+
execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
28228
28554
|
stdio: "pipe",
|
|
28229
28555
|
timeout: 12e4
|
|
28230
28556
|
});
|
|
@@ -28267,7 +28593,7 @@ async function isModelAvailable(config) {
|
|
|
28267
28593
|
}
|
|
28268
28594
|
function isFirstRun() {
|
|
28269
28595
|
try {
|
|
28270
|
-
return !
|
|
28596
|
+
return !existsSync28(join38(homedir10(), ".open-agents", "config.json"));
|
|
28271
28597
|
} catch {
|
|
28272
28598
|
return true;
|
|
28273
28599
|
}
|
|
@@ -28275,7 +28601,7 @@ function isFirstRun() {
|
|
|
28275
28601
|
function hasCmd(cmd) {
|
|
28276
28602
|
try {
|
|
28277
28603
|
const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
|
|
28278
|
-
|
|
28604
|
+
execSync25(whichCmd, { stdio: "pipe", timeout: 3e3 });
|
|
28279
28605
|
return true;
|
|
28280
28606
|
} catch {
|
|
28281
28607
|
return false;
|
|
@@ -28304,11 +28630,11 @@ function detectPkgManager() {
|
|
|
28304
28630
|
return null;
|
|
28305
28631
|
}
|
|
28306
28632
|
function getVenvDir() {
|
|
28307
|
-
return
|
|
28633
|
+
return join38(homedir10(), ".open-agents", "venv");
|
|
28308
28634
|
}
|
|
28309
28635
|
function hasVenvModule() {
|
|
28310
28636
|
try {
|
|
28311
|
-
|
|
28637
|
+
execSync25("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
28312
28638
|
return true;
|
|
28313
28639
|
} catch {
|
|
28314
28640
|
return false;
|
|
@@ -28316,8 +28642,8 @@ function hasVenvModule() {
|
|
|
28316
28642
|
}
|
|
28317
28643
|
function ensureVenv(log) {
|
|
28318
28644
|
const venvDir = getVenvDir();
|
|
28319
|
-
const venvPip =
|
|
28320
|
-
if (
|
|
28645
|
+
const venvPip = join38(venvDir, "bin", "pip");
|
|
28646
|
+
if (existsSync28(venvPip))
|
|
28321
28647
|
return venvDir;
|
|
28322
28648
|
log("Creating Python venv for vision deps...");
|
|
28323
28649
|
if (!hasCmd("python3")) {
|
|
@@ -28329,9 +28655,9 @@ function ensureVenv(log) {
|
|
|
28329
28655
|
return null;
|
|
28330
28656
|
}
|
|
28331
28657
|
try {
|
|
28332
|
-
mkdirSync9(
|
|
28333
|
-
|
|
28334
|
-
|
|
28658
|
+
mkdirSync9(join38(homedir10(), ".open-agents"), { recursive: true });
|
|
28659
|
+
execSync25(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
|
|
28660
|
+
execSync25(`"${join38(venvDir, "bin", "pip")}" install --upgrade pip`, {
|
|
28335
28661
|
stdio: "pipe",
|
|
28336
28662
|
timeout: 6e4
|
|
28337
28663
|
});
|
|
@@ -28344,7 +28670,7 @@ function ensureVenv(log) {
|
|
|
28344
28670
|
}
|
|
28345
28671
|
function trySudoPasswordless(cmd, timeoutMs = 12e4) {
|
|
28346
28672
|
try {
|
|
28347
|
-
|
|
28673
|
+
execSync25(`sudo -n ${cmd}`, {
|
|
28348
28674
|
stdio: "pipe",
|
|
28349
28675
|
timeout: timeoutMs,
|
|
28350
28676
|
env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
|
|
@@ -28356,7 +28682,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
|
|
|
28356
28682
|
}
|
|
28357
28683
|
function runWithSudo(cmd, password, timeoutMs = 12e4) {
|
|
28358
28684
|
try {
|
|
28359
|
-
|
|
28685
|
+
execSync25(`sudo -S ${cmd}`, {
|
|
28360
28686
|
input: password + "\n",
|
|
28361
28687
|
stdio: ["pipe", "pipe", "pipe"],
|
|
28362
28688
|
timeout: timeoutMs,
|
|
@@ -28416,7 +28742,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
28416
28742
|
} else {
|
|
28417
28743
|
log("Installing tesseract-ocr...");
|
|
28418
28744
|
try {
|
|
28419
|
-
|
|
28745
|
+
execSync25(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
|
|
28420
28746
|
if (hasCmd("tesseract")) {
|
|
28421
28747
|
log("tesseract-ocr installed successfully.");
|
|
28422
28748
|
} else {
|
|
@@ -28488,7 +28814,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
28488
28814
|
} else {
|
|
28489
28815
|
log(`Installing ${dep.label}...`);
|
|
28490
28816
|
try {
|
|
28491
|
-
|
|
28817
|
+
execSync25(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
|
|
28492
28818
|
if (hasCmd(dep.binary)) {
|
|
28493
28819
|
log(`${dep.label} installed successfully.`);
|
|
28494
28820
|
} else {
|
|
@@ -28519,7 +28845,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
28519
28845
|
const venvCmds = {
|
|
28520
28846
|
apt: () => {
|
|
28521
28847
|
try {
|
|
28522
|
-
const pyVer =
|
|
28848
|
+
const pyVer = execSync25(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
|
|
28523
28849
|
return `apt-get install -y python3-venv python${pyVer}-venv`;
|
|
28524
28850
|
} catch {
|
|
28525
28851
|
return "apt-get install -y python3-venv";
|
|
@@ -28540,19 +28866,19 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
28540
28866
|
}
|
|
28541
28867
|
}
|
|
28542
28868
|
const venvDir = getVenvDir();
|
|
28543
|
-
const venvBin =
|
|
28544
|
-
const venvMoondream =
|
|
28869
|
+
const venvBin = join38(venvDir, "bin");
|
|
28870
|
+
const venvMoondream = join38(venvBin, "moondream-station");
|
|
28545
28871
|
const venv = ensureVenv(log);
|
|
28546
|
-
if (venv && !hasCmd("moondream-station") && !
|
|
28547
|
-
const venvPip =
|
|
28872
|
+
if (venv && !hasCmd("moondream-station") && !existsSync28(venvMoondream)) {
|
|
28873
|
+
const venvPip = join38(venvBin, "pip");
|
|
28548
28874
|
log("Installing moondream-station in ~/.open-agents/venv...");
|
|
28549
28875
|
try {
|
|
28550
|
-
|
|
28551
|
-
if (
|
|
28876
|
+
execSync25(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
|
|
28877
|
+
if (existsSync28(venvMoondream)) {
|
|
28552
28878
|
log("moondream-station installed successfully.");
|
|
28553
28879
|
} else {
|
|
28554
28880
|
try {
|
|
28555
|
-
const check =
|
|
28881
|
+
const check = execSync25(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
|
|
28556
28882
|
if (check.includes("moondream")) {
|
|
28557
28883
|
log("moondream-station package installed.");
|
|
28558
28884
|
}
|
|
@@ -28565,11 +28891,11 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
28565
28891
|
}
|
|
28566
28892
|
}
|
|
28567
28893
|
if (venv) {
|
|
28568
|
-
const venvPython =
|
|
28569
|
-
const venvPip2 =
|
|
28894
|
+
const venvPython = join38(venvBin, "python");
|
|
28895
|
+
const venvPip2 = join38(venvBin, "pip");
|
|
28570
28896
|
let ocrStackInstalled = false;
|
|
28571
28897
|
try {
|
|
28572
|
-
|
|
28898
|
+
execSync25(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
|
|
28573
28899
|
ocrStackInstalled = true;
|
|
28574
28900
|
} catch {
|
|
28575
28901
|
}
|
|
@@ -28577,9 +28903,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
28577
28903
|
const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
|
|
28578
28904
|
log("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
|
|
28579
28905
|
try {
|
|
28580
|
-
|
|
28906
|
+
execSync25(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
|
|
28581
28907
|
try {
|
|
28582
|
-
|
|
28908
|
+
execSync25(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
|
|
28583
28909
|
log("OCR Python stack installed successfully.");
|
|
28584
28910
|
} catch {
|
|
28585
28911
|
log("OCR Python stack install completed but import verification failed.");
|
|
@@ -28613,7 +28939,7 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
28613
28939
|
const archMap = { x64: "amd64", arm64: "arm64", arm: "arm" };
|
|
28614
28940
|
const cfArch = archMap[arch] ?? "amd64";
|
|
28615
28941
|
try {
|
|
28616
|
-
|
|
28942
|
+
execSync25(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir10()}/.local/bin" && mv /tmp/cloudflared "${homedir10()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
|
|
28617
28943
|
if (!process.env.PATH?.includes(`${homedir10()}/.local/bin`)) {
|
|
28618
28944
|
process.env.PATH = `${homedir10()}/.local/bin:${process.env.PATH}`;
|
|
28619
28945
|
}
|
|
@@ -28624,7 +28950,7 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
28624
28950
|
} catch {
|
|
28625
28951
|
}
|
|
28626
28952
|
try {
|
|
28627
|
-
|
|
28953
|
+
execSync25(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && sudo mv /tmp/cloudflared /usr/local/bin/cloudflared 2>/dev/null`, { stdio: "pipe", timeout: 6e4 });
|
|
28628
28954
|
if (hasCmd("cloudflared")) {
|
|
28629
28955
|
log("cloudflared installed.");
|
|
28630
28956
|
return true;
|
|
@@ -28633,7 +28959,7 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
28633
28959
|
}
|
|
28634
28960
|
} else if (os === "darwin") {
|
|
28635
28961
|
try {
|
|
28636
|
-
|
|
28962
|
+
execSync25("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
|
|
28637
28963
|
if (hasCmd("cloudflared")) {
|
|
28638
28964
|
log("cloudflared installed via Homebrew.");
|
|
28639
28965
|
return true;
|
|
@@ -28679,11 +29005,11 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
|
|
|
28679
29005
|
`PARAMETER num_predict ${numPredict}`,
|
|
28680
29006
|
`PARAMETER stop "<|endoftext|>"`
|
|
28681
29007
|
].join("\n");
|
|
28682
|
-
const modelDir2 =
|
|
29008
|
+
const modelDir2 = join38(homedir10(), ".open-agents", "models");
|
|
28683
29009
|
mkdirSync9(modelDir2, { recursive: true });
|
|
28684
|
-
const modelfilePath =
|
|
29010
|
+
const modelfilePath = join38(modelDir2, `Modelfile.${customName}`);
|
|
28685
29011
|
writeFileSync9(modelfilePath, modelfileContent + "\n", "utf8");
|
|
28686
|
-
|
|
29012
|
+
execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
28687
29013
|
stdio: "pipe",
|
|
28688
29014
|
timeout: 12e4
|
|
28689
29015
|
});
|
|
@@ -29986,17 +30312,17 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
29986
30312
|
try {
|
|
29987
30313
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
29988
30314
|
const { fileURLToPath: fileURLToPath14 } = await import("node:url");
|
|
29989
|
-
const { dirname: dirname18, join:
|
|
29990
|
-
const { existsSync:
|
|
30315
|
+
const { dirname: dirname18, join: join53 } = await import("node:path");
|
|
30316
|
+
const { existsSync: existsSync39 } = await import("node:fs");
|
|
29991
30317
|
const req = createRequire4(import.meta.url);
|
|
29992
30318
|
const thisDir = dirname18(fileURLToPath14(import.meta.url));
|
|
29993
30319
|
const candidates = [
|
|
29994
|
-
|
|
29995
|
-
|
|
29996
|
-
|
|
30320
|
+
join53(thisDir, "..", "package.json"),
|
|
30321
|
+
join53(thisDir, "..", "..", "package.json"),
|
|
30322
|
+
join53(thisDir, "..", "..", "..", "package.json")
|
|
29997
30323
|
];
|
|
29998
30324
|
for (const pkgPath of candidates) {
|
|
29999
|
-
if (
|
|
30325
|
+
if (existsSync39(pkgPath)) {
|
|
30000
30326
|
const pkg = req(pkgPath);
|
|
30001
30327
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
30002
30328
|
currentVersion = pkg.version ?? "0.0.0";
|
|
@@ -30060,14 +30386,33 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
30060
30386
|
const installCmd = `${sudoPrefix}npm install -g open-agents-ai@latest --prefer-online`;
|
|
30061
30387
|
let installOk = false;
|
|
30062
30388
|
let installError = "";
|
|
30063
|
-
|
|
30064
|
-
const child = exec(
|
|
30389
|
+
const runInstall2 = (cmd) => new Promise((resolve31) => {
|
|
30390
|
+
const child = exec(cmd, { timeout: 18e4 }, (err, _stdout, stderr) => {
|
|
30065
30391
|
if (err)
|
|
30066
30392
|
installError = (stderr || err.message || "").trim();
|
|
30067
30393
|
resolve31(!err);
|
|
30068
30394
|
});
|
|
30069
30395
|
child.stdout?.resume();
|
|
30070
30396
|
});
|
|
30397
|
+
installOk = await runInstall2(installCmd);
|
|
30398
|
+
if (!installOk && /ENOTEMPTY|errno -39/i.test(installError)) {
|
|
30399
|
+
installSpinner.stop("Cleaning stale npm temp files...");
|
|
30400
|
+
try {
|
|
30401
|
+
const prefix = es2("npm prefix -g", { encoding: "utf8", timeout: 5e3 }).trim();
|
|
30402
|
+
const globalModules = prefix.endsWith("/lib") ? prefix + "/node_modules" : prefix + "/lib/node_modules";
|
|
30403
|
+
es2(`${sudoPrefix}find "${globalModules}" -maxdepth 1 -name ".open-agents-ai-*" -type d -exec rm -rf {} + 2>/dev/null || true`, { timeout: 15e3 });
|
|
30404
|
+
es2(`${sudoPrefix}rm -rf "${globalModules}/open-agents-ai" 2>/dev/null || true`, { timeout: 15e3 });
|
|
30405
|
+
} catch {
|
|
30406
|
+
}
|
|
30407
|
+
const retrySpinner = startInlineSpinner("Retrying install");
|
|
30408
|
+
installError = "";
|
|
30409
|
+
installOk = await runInstall2(installCmd);
|
|
30410
|
+
if (!installOk) {
|
|
30411
|
+
retrySpinner.stop("Retry failed.");
|
|
30412
|
+
} else {
|
|
30413
|
+
retrySpinner.stop(`Update installed (v${info.latestVersion}).`);
|
|
30414
|
+
}
|
|
30415
|
+
}
|
|
30071
30416
|
if (!installOk) {
|
|
30072
30417
|
installSpinner.stop("Update install failed.");
|
|
30073
30418
|
const errPreview = installError.split("\n").filter((l) => l.trim()).slice(-3).join("\n ");
|
|
@@ -30252,9 +30597,9 @@ var init_commands = __esm({
|
|
|
30252
30597
|
});
|
|
30253
30598
|
|
|
30254
30599
|
// packages/cli/dist/tui/project-context.js
|
|
30255
|
-
import { existsSync as
|
|
30256
|
-
import { join as
|
|
30257
|
-
import { execSync as
|
|
30600
|
+
import { existsSync as existsSync29, readFileSync as readFileSync20, readdirSync as readdirSync8 } from "node:fs";
|
|
30601
|
+
import { join as join39, basename as basename10 } from "node:path";
|
|
30602
|
+
import { execSync as execSync26 } from "node:child_process";
|
|
30258
30603
|
import { homedir as homedir11, platform as platform2, release } from "node:os";
|
|
30259
30604
|
function getModelTier(modelName) {
|
|
30260
30605
|
const m = modelName.toLowerCase();
|
|
@@ -30288,8 +30633,8 @@ function loadProjectMap(repoRoot) {
|
|
|
30288
30633
|
if (!hasOaDirectory(repoRoot)) {
|
|
30289
30634
|
initOaDirectory(repoRoot);
|
|
30290
30635
|
}
|
|
30291
|
-
const mapPath =
|
|
30292
|
-
if (
|
|
30636
|
+
const mapPath = join39(repoRoot, OA_DIR, "context", "project-map.md");
|
|
30637
|
+
if (existsSync29(mapPath)) {
|
|
30293
30638
|
try {
|
|
30294
30639
|
const content = readFileSync20(mapPath, "utf-8");
|
|
30295
30640
|
return content;
|
|
@@ -30300,19 +30645,19 @@ function loadProjectMap(repoRoot) {
|
|
|
30300
30645
|
}
|
|
30301
30646
|
function getGitInfo(repoRoot) {
|
|
30302
30647
|
try {
|
|
30303
|
-
|
|
30648
|
+
execSync26("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
|
|
30304
30649
|
} catch {
|
|
30305
30650
|
return "";
|
|
30306
30651
|
}
|
|
30307
30652
|
const lines = [];
|
|
30308
30653
|
try {
|
|
30309
|
-
const branch =
|
|
30654
|
+
const branch = execSync26("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
30310
30655
|
if (branch)
|
|
30311
30656
|
lines.push(`Branch: ${branch}`);
|
|
30312
30657
|
} catch {
|
|
30313
30658
|
}
|
|
30314
30659
|
try {
|
|
30315
|
-
const status =
|
|
30660
|
+
const status = execSync26("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
30316
30661
|
if (status) {
|
|
30317
30662
|
const changed = status.split("\n").length;
|
|
30318
30663
|
lines.push(`Working tree: ${changed} changed file(s)`);
|
|
@@ -30322,7 +30667,7 @@ function getGitInfo(repoRoot) {
|
|
|
30322
30667
|
} catch {
|
|
30323
30668
|
}
|
|
30324
30669
|
try {
|
|
30325
|
-
const log =
|
|
30670
|
+
const log = execSync26("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
30326
30671
|
if (log)
|
|
30327
30672
|
lines.push(`Recent commits:
|
|
30328
30673
|
${log}`);
|
|
@@ -30332,31 +30677,31 @@ ${log}`);
|
|
|
30332
30677
|
}
|
|
30333
30678
|
function loadMemoryContext(repoRoot) {
|
|
30334
30679
|
const sections = [];
|
|
30335
|
-
const oaMemDir =
|
|
30680
|
+
const oaMemDir = join39(repoRoot, OA_DIR, "memory");
|
|
30336
30681
|
const oaEntries = loadMemoryDir(oaMemDir, "project");
|
|
30337
30682
|
if (oaEntries)
|
|
30338
30683
|
sections.push(oaEntries);
|
|
30339
|
-
const legacyMemDir =
|
|
30340
|
-
if (legacyMemDir !== oaMemDir &&
|
|
30684
|
+
const legacyMemDir = join39(repoRoot, ".open-agents", "memory");
|
|
30685
|
+
if (legacyMemDir !== oaMemDir && existsSync29(legacyMemDir)) {
|
|
30341
30686
|
const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
|
|
30342
30687
|
if (legacyEntries)
|
|
30343
30688
|
sections.push(legacyEntries);
|
|
30344
30689
|
}
|
|
30345
|
-
const globalMemDir =
|
|
30690
|
+
const globalMemDir = join39(homedir11(), ".open-agents", "memory");
|
|
30346
30691
|
const globalEntries = loadMemoryDir(globalMemDir, "global");
|
|
30347
30692
|
if (globalEntries)
|
|
30348
30693
|
sections.push(globalEntries);
|
|
30349
30694
|
return sections.join("\n\n");
|
|
30350
30695
|
}
|
|
30351
30696
|
function loadMemoryDir(memDir, scope) {
|
|
30352
|
-
if (!
|
|
30697
|
+
if (!existsSync29(memDir))
|
|
30353
30698
|
return "";
|
|
30354
30699
|
const lines = [];
|
|
30355
30700
|
try {
|
|
30356
30701
|
const files = readdirSync8(memDir).filter((f) => f.endsWith(".json"));
|
|
30357
30702
|
for (const file of files.slice(0, 10)) {
|
|
30358
30703
|
try {
|
|
30359
|
-
const raw = readFileSync20(
|
|
30704
|
+
const raw = readFileSync20(join39(memDir, file), "utf-8");
|
|
30360
30705
|
const entries = JSON.parse(raw);
|
|
30361
30706
|
const topic = basename10(file, ".json");
|
|
30362
30707
|
const keys = Object.keys(entries);
|
|
@@ -31383,12 +31728,12 @@ var init_carousel = __esm({
|
|
|
31383
31728
|
});
|
|
31384
31729
|
|
|
31385
31730
|
// packages/cli/dist/tui/carousel-descriptors.js
|
|
31386
|
-
import { existsSync as
|
|
31387
|
-
import { join as
|
|
31731
|
+
import { existsSync as existsSync30, readFileSync as readFileSync21, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, readdirSync as readdirSync9 } from "node:fs";
|
|
31732
|
+
import { join as join40, basename as basename11 } from "node:path";
|
|
31388
31733
|
function loadToolProfile(repoRoot) {
|
|
31389
|
-
const filePath =
|
|
31734
|
+
const filePath = join40(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
|
|
31390
31735
|
try {
|
|
31391
|
-
if (!
|
|
31736
|
+
if (!existsSync30(filePath))
|
|
31392
31737
|
return null;
|
|
31393
31738
|
return JSON.parse(readFileSync21(filePath, "utf-8"));
|
|
31394
31739
|
} catch {
|
|
@@ -31396,9 +31741,9 @@ function loadToolProfile(repoRoot) {
|
|
|
31396
31741
|
}
|
|
31397
31742
|
}
|
|
31398
31743
|
function saveToolProfile(repoRoot, profile) {
|
|
31399
|
-
const contextDir =
|
|
31744
|
+
const contextDir = join40(repoRoot, OA_DIR, "context");
|
|
31400
31745
|
mkdirSync10(contextDir, { recursive: true });
|
|
31401
|
-
writeFileSync10(
|
|
31746
|
+
writeFileSync10(join40(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
|
|
31402
31747
|
}
|
|
31403
31748
|
function categorizeToolCall(toolName) {
|
|
31404
31749
|
for (const cat of TOOL_CATEGORIES) {
|
|
@@ -31456,9 +31801,9 @@ function weightedColor(profile) {
|
|
|
31456
31801
|
return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
|
|
31457
31802
|
}
|
|
31458
31803
|
function loadCachedDescriptors(repoRoot) {
|
|
31459
|
-
const filePath =
|
|
31804
|
+
const filePath = join40(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
|
|
31460
31805
|
try {
|
|
31461
|
-
if (!
|
|
31806
|
+
if (!existsSync30(filePath))
|
|
31462
31807
|
return null;
|
|
31463
31808
|
const cached = JSON.parse(readFileSync21(filePath, "utf-8"));
|
|
31464
31809
|
return cached.phrases.length > 0 ? cached.phrases : null;
|
|
@@ -31467,14 +31812,14 @@ function loadCachedDescriptors(repoRoot) {
|
|
|
31467
31812
|
}
|
|
31468
31813
|
}
|
|
31469
31814
|
function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
|
|
31470
|
-
const contextDir =
|
|
31815
|
+
const contextDir = join40(repoRoot, OA_DIR, "context");
|
|
31471
31816
|
mkdirSync10(contextDir, { recursive: true });
|
|
31472
31817
|
const cached = {
|
|
31473
31818
|
phrases,
|
|
31474
31819
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
31475
31820
|
sourceHash
|
|
31476
31821
|
};
|
|
31477
|
-
writeFileSync10(
|
|
31822
|
+
writeFileSync10(join40(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
|
|
31478
31823
|
}
|
|
31479
31824
|
function generateDescriptors(repoRoot) {
|
|
31480
31825
|
const profile = loadToolProfile(repoRoot);
|
|
@@ -31522,9 +31867,9 @@ function generateDescriptors(repoRoot) {
|
|
|
31522
31867
|
return phrases;
|
|
31523
31868
|
}
|
|
31524
31869
|
function extractFromPackageJson(repoRoot, tags) {
|
|
31525
|
-
const pkgPath =
|
|
31870
|
+
const pkgPath = join40(repoRoot, "package.json");
|
|
31526
31871
|
try {
|
|
31527
|
-
if (!
|
|
31872
|
+
if (!existsSync30(pkgPath))
|
|
31528
31873
|
return;
|
|
31529
31874
|
const pkg = JSON.parse(readFileSync21(pkgPath, "utf-8"));
|
|
31530
31875
|
if (pkg.name && typeof pkg.name === "string") {
|
|
@@ -31570,7 +31915,7 @@ function extractFromManifests(repoRoot, tags) {
|
|
|
31570
31915
|
{ file: ".github/workflows", tag: "ci/cd" }
|
|
31571
31916
|
];
|
|
31572
31917
|
for (const check of manifestChecks) {
|
|
31573
|
-
if (
|
|
31918
|
+
if (existsSync30(join40(repoRoot, check.file))) {
|
|
31574
31919
|
tags.push(check.tag);
|
|
31575
31920
|
}
|
|
31576
31921
|
}
|
|
@@ -31592,16 +31937,16 @@ function extractFromSessions(repoRoot, tags) {
|
|
|
31592
31937
|
}
|
|
31593
31938
|
}
|
|
31594
31939
|
function extractFromMemory(repoRoot, tags) {
|
|
31595
|
-
const memoryDir =
|
|
31940
|
+
const memoryDir = join40(repoRoot, OA_DIR, "memory");
|
|
31596
31941
|
try {
|
|
31597
|
-
if (!
|
|
31942
|
+
if (!existsSync30(memoryDir))
|
|
31598
31943
|
return;
|
|
31599
31944
|
const files = readdirSync9(memoryDir).filter((f) => f.endsWith(".json"));
|
|
31600
31945
|
for (const file of files) {
|
|
31601
31946
|
const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
|
|
31602
31947
|
tags.push(topic);
|
|
31603
31948
|
try {
|
|
31604
|
-
const data = JSON.parse(readFileSync21(
|
|
31949
|
+
const data = JSON.parse(readFileSync21(join40(memoryDir, file), "utf-8"));
|
|
31605
31950
|
if (data && typeof data === "object") {
|
|
31606
31951
|
const keys = Object.keys(data).slice(0, 3);
|
|
31607
31952
|
for (const key of keys) {
|
|
@@ -31736,25 +32081,25 @@ var init_carousel_descriptors = __esm({
|
|
|
31736
32081
|
});
|
|
31737
32082
|
|
|
31738
32083
|
// packages/cli/dist/tui/voice.js
|
|
31739
|
-
import { existsSync as
|
|
31740
|
-
import { join as
|
|
32084
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11, readFileSync as readFileSync22, unlinkSync as unlinkSync4 } from "node:fs";
|
|
32085
|
+
import { join as join41 } from "node:path";
|
|
31741
32086
|
import { homedir as homedir12, tmpdir as tmpdir6, platform as platform3 } from "node:os";
|
|
31742
|
-
import { execSync as
|
|
32087
|
+
import { execSync as execSync27, spawn as nodeSpawn } from "node:child_process";
|
|
31743
32088
|
import { createRequire } from "node:module";
|
|
31744
32089
|
function voiceDir() {
|
|
31745
|
-
return
|
|
32090
|
+
return join41(homedir12(), ".open-agents", "voice");
|
|
31746
32091
|
}
|
|
31747
32092
|
function modelsDir() {
|
|
31748
|
-
return
|
|
32093
|
+
return join41(voiceDir(), "models");
|
|
31749
32094
|
}
|
|
31750
32095
|
function modelDir(id) {
|
|
31751
|
-
return
|
|
32096
|
+
return join41(modelsDir(), id);
|
|
31752
32097
|
}
|
|
31753
32098
|
function modelOnnxPath(id) {
|
|
31754
|
-
return
|
|
32099
|
+
return join41(modelDir(id), "model.onnx");
|
|
31755
32100
|
}
|
|
31756
32101
|
function modelConfigPath(id) {
|
|
31757
|
-
return
|
|
32102
|
+
return join41(modelDir(id), "config.json");
|
|
31758
32103
|
}
|
|
31759
32104
|
function emotionToPitchBias(emotion) {
|
|
31760
32105
|
const raw = emotion.valence * 0.6 + (emotion.arousal - 0.5) * 0.4;
|
|
@@ -32477,7 +32822,7 @@ var init_voice = __esm({
|
|
|
32477
32822
|
}
|
|
32478
32823
|
this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
|
|
32479
32824
|
}
|
|
32480
|
-
const wavPath =
|
|
32825
|
+
const wavPath = join41(tmpdir6(), `oa-voice-${Date.now()}.wav`);
|
|
32481
32826
|
this.writeWav(audioData, sampleRate, wavPath);
|
|
32482
32827
|
await this.playWav(wavPath);
|
|
32483
32828
|
try {
|
|
@@ -32659,7 +33004,7 @@ var init_voice = __esm({
|
|
|
32659
33004
|
}
|
|
32660
33005
|
for (const player of ["paplay", "pw-play", "aplay"]) {
|
|
32661
33006
|
try {
|
|
32662
|
-
|
|
33007
|
+
execSync27(`which ${player}`, { stdio: "pipe" });
|
|
32663
33008
|
return [player, path];
|
|
32664
33009
|
} catch {
|
|
32665
33010
|
}
|
|
@@ -32683,12 +33028,12 @@ var init_voice = __esm({
|
|
|
32683
33028
|
return;
|
|
32684
33029
|
const arch = process.arch;
|
|
32685
33030
|
mkdirSync11(voiceDir(), { recursive: true });
|
|
32686
|
-
const pkgPath =
|
|
33031
|
+
const pkgPath = join41(voiceDir(), "package.json");
|
|
32687
33032
|
const expectedDeps = {
|
|
32688
33033
|
"onnxruntime-node": "^1.21.0",
|
|
32689
33034
|
"phonemizer": "^1.2.1"
|
|
32690
33035
|
};
|
|
32691
|
-
if (
|
|
33036
|
+
if (existsSync31(pkgPath)) {
|
|
32692
33037
|
try {
|
|
32693
33038
|
const existing = JSON.parse(readFileSync22(pkgPath, "utf8"));
|
|
32694
33039
|
if (!existing.dependencies?.["phonemizer"]) {
|
|
@@ -32698,17 +33043,17 @@ var init_voice = __esm({
|
|
|
32698
33043
|
} catch {
|
|
32699
33044
|
}
|
|
32700
33045
|
}
|
|
32701
|
-
if (!
|
|
33046
|
+
if (!existsSync31(pkgPath)) {
|
|
32702
33047
|
writeFileSync11(pkgPath, JSON.stringify({
|
|
32703
33048
|
name: "open-agents-voice",
|
|
32704
33049
|
private: true,
|
|
32705
33050
|
dependencies: expectedDeps
|
|
32706
33051
|
}, null, 2));
|
|
32707
33052
|
}
|
|
32708
|
-
const voiceRequire = createRequire(
|
|
33053
|
+
const voiceRequire = createRequire(join41(voiceDir(), "index.js"));
|
|
32709
33054
|
const probeOnnx = () => {
|
|
32710
33055
|
try {
|
|
32711
|
-
const result =
|
|
33056
|
+
const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join41(voiceDir(), "node_modules") } });
|
|
32712
33057
|
const output = result.toString().trim();
|
|
32713
33058
|
if (output === "OK")
|
|
32714
33059
|
return true;
|
|
@@ -32725,8 +33070,8 @@ var init_voice = __esm({
|
|
|
32725
33070
|
return false;
|
|
32726
33071
|
}
|
|
32727
33072
|
};
|
|
32728
|
-
const onnxNodeModules =
|
|
32729
|
-
const onnxInstalled =
|
|
33073
|
+
const onnxNodeModules = join41(voiceDir(), "node_modules", "onnxruntime-node");
|
|
33074
|
+
const onnxInstalled = existsSync31(onnxNodeModules);
|
|
32730
33075
|
if (onnxInstalled && !probeOnnx()) {
|
|
32731
33076
|
throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
|
|
32732
33077
|
}
|
|
@@ -32735,7 +33080,7 @@ var init_voice = __esm({
|
|
|
32735
33080
|
} catch {
|
|
32736
33081
|
renderInfo("Installing ONNX runtime for voice synthesis...");
|
|
32737
33082
|
try {
|
|
32738
|
-
|
|
33083
|
+
execSync27("npm install --no-audit --no-fund", {
|
|
32739
33084
|
cwd: voiceDir(),
|
|
32740
33085
|
stdio: "pipe",
|
|
32741
33086
|
timeout: 12e4
|
|
@@ -32760,7 +33105,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
32760
33105
|
} catch {
|
|
32761
33106
|
renderInfo("Installing phonemizer for voice synthesis...");
|
|
32762
33107
|
try {
|
|
32763
|
-
|
|
33108
|
+
execSync27("npm install --no-audit --no-fund", {
|
|
32764
33109
|
cwd: voiceDir(),
|
|
32765
33110
|
stdio: "pipe",
|
|
32766
33111
|
timeout: 12e4
|
|
@@ -32784,10 +33129,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
32784
33129
|
const dir = modelDir(id);
|
|
32785
33130
|
const onnxPath = modelOnnxPath(id);
|
|
32786
33131
|
const configPath = modelConfigPath(id);
|
|
32787
|
-
if (
|
|
33132
|
+
if (existsSync31(onnxPath) && existsSync31(configPath))
|
|
32788
33133
|
return;
|
|
32789
33134
|
mkdirSync11(dir, { recursive: true });
|
|
32790
|
-
if (!
|
|
33135
|
+
if (!existsSync31(configPath)) {
|
|
32791
33136
|
renderInfo(`Downloading ${model.label} voice config...`);
|
|
32792
33137
|
const configResp = await fetch(model.configUrl);
|
|
32793
33138
|
if (!configResp.ok)
|
|
@@ -32795,7 +33140,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
32795
33140
|
const configText = await configResp.text();
|
|
32796
33141
|
writeFileSync11(configPath, configText);
|
|
32797
33142
|
}
|
|
32798
|
-
if (!
|
|
33143
|
+
if (!existsSync31(onnxPath)) {
|
|
32799
33144
|
renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
|
|
32800
33145
|
const onnxResp = await fetch(model.onnxUrl);
|
|
32801
33146
|
if (!onnxResp.ok)
|
|
@@ -32831,7 +33176,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
32831
33176
|
throw new Error("ONNX runtime not loaded");
|
|
32832
33177
|
const onnxPath = modelOnnxPath(this.modelId);
|
|
32833
33178
|
const configPath = modelConfigPath(this.modelId);
|
|
32834
|
-
if (!
|
|
33179
|
+
if (!existsSync31(onnxPath) || !existsSync31(configPath)) {
|
|
32835
33180
|
throw new Error(`Model files not found for ${this.modelId}`);
|
|
32836
33181
|
}
|
|
32837
33182
|
this.config = JSON.parse(readFileSync22(configPath, "utf8"));
|
|
@@ -33698,10 +34043,10 @@ var init_stream_renderer = __esm({
|
|
|
33698
34043
|
|
|
33699
34044
|
// packages/cli/dist/tui/edit-history.js
|
|
33700
34045
|
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync12 } from "node:fs";
|
|
33701
|
-
import { join as
|
|
34046
|
+
import { join as join42 } from "node:path";
|
|
33702
34047
|
function createEditHistoryLogger(repoRoot, sessionId) {
|
|
33703
|
-
const historyDir =
|
|
33704
|
-
const logPath =
|
|
34048
|
+
const historyDir = join42(repoRoot, ".oa", "history");
|
|
34049
|
+
const logPath = join42(historyDir, "edits.jsonl");
|
|
33705
34050
|
try {
|
|
33706
34051
|
mkdirSync12(historyDir, { recursive: true });
|
|
33707
34052
|
} catch {
|
|
@@ -33812,14 +34157,14 @@ var init_edit_history = __esm({
|
|
|
33812
34157
|
});
|
|
33813
34158
|
|
|
33814
34159
|
// packages/cli/dist/tui/promptLoader.js
|
|
33815
|
-
import { readFileSync as readFileSync23, existsSync as
|
|
33816
|
-
import { join as
|
|
34160
|
+
import { readFileSync as readFileSync23, existsSync as existsSync32 } from "node:fs";
|
|
34161
|
+
import { join as join43, dirname as dirname15 } from "node:path";
|
|
33817
34162
|
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
33818
34163
|
function loadPrompt3(promptPath, vars) {
|
|
33819
34164
|
let content = cache3.get(promptPath);
|
|
33820
34165
|
if (content === void 0) {
|
|
33821
|
-
const fullPath =
|
|
33822
|
-
if (!
|
|
34166
|
+
const fullPath = join43(PROMPTS_DIR3, promptPath);
|
|
34167
|
+
if (!existsSync32(fullPath)) {
|
|
33823
34168
|
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
33824
34169
|
}
|
|
33825
34170
|
content = readFileSync23(fullPath, "utf-8");
|
|
@@ -33835,20 +34180,20 @@ var init_promptLoader3 = __esm({
|
|
|
33835
34180
|
"use strict";
|
|
33836
34181
|
__filename3 = fileURLToPath11(import.meta.url);
|
|
33837
34182
|
__dirname5 = dirname15(__filename3);
|
|
33838
|
-
devPath2 =
|
|
33839
|
-
publishedPath2 =
|
|
33840
|
-
PROMPTS_DIR3 =
|
|
34183
|
+
devPath2 = join43(__dirname5, "..", "..", "prompts");
|
|
34184
|
+
publishedPath2 = join43(__dirname5, "..", "prompts");
|
|
34185
|
+
PROMPTS_DIR3 = existsSync32(devPath2) ? devPath2 : publishedPath2;
|
|
33841
34186
|
cache3 = /* @__PURE__ */ new Map();
|
|
33842
34187
|
}
|
|
33843
34188
|
});
|
|
33844
34189
|
|
|
33845
34190
|
// packages/cli/dist/tui/dream-engine.js
|
|
33846
|
-
import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync12, readFileSync as readFileSync24, existsSync as
|
|
33847
|
-
import { join as
|
|
33848
|
-
import { execSync as
|
|
34191
|
+
import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync12, readFileSync as readFileSync24, existsSync as existsSync33, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
|
|
34192
|
+
import { join as join44, basename as basename12 } from "node:path";
|
|
34193
|
+
import { execSync as execSync28 } from "node:child_process";
|
|
33849
34194
|
function loadAutoresearchMemory(repoRoot) {
|
|
33850
|
-
const memoryPath =
|
|
33851
|
-
if (!
|
|
34195
|
+
const memoryPath = join44(repoRoot, ".oa", "memory", "autoresearch.json");
|
|
34196
|
+
if (!existsSync33(memoryPath))
|
|
33852
34197
|
return "";
|
|
33853
34198
|
try {
|
|
33854
34199
|
const raw = readFileSync24(memoryPath, "utf-8");
|
|
@@ -34041,12 +34386,12 @@ var init_dream_engine = __esm({
|
|
|
34041
34386
|
const content = String(args["content"] ?? "");
|
|
34042
34387
|
if (!rawPath)
|
|
34043
34388
|
return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
|
|
34044
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ?
|
|
34389
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join44(this.autoresearchDir, basename12(rawPath)) : join44(this.autoresearchDir, rawPath);
|
|
34045
34390
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
34046
34391
|
return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
|
|
34047
34392
|
}
|
|
34048
34393
|
try {
|
|
34049
|
-
const dir =
|
|
34394
|
+
const dir = join44(targetPath, "..");
|
|
34050
34395
|
mkdirSync13(dir, { recursive: true });
|
|
34051
34396
|
writeFileSync12(targetPath, content, "utf-8");
|
|
34052
34397
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
|
|
@@ -34076,12 +34421,12 @@ var init_dream_engine = __esm({
|
|
|
34076
34421
|
const rawPath = String(args["path"] ?? "");
|
|
34077
34422
|
const oldStr = String(args["old_string"] ?? "");
|
|
34078
34423
|
const newStr = String(args["new_string"] ?? "");
|
|
34079
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ?
|
|
34424
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join44(this.autoresearchDir, basename12(rawPath)) : join44(this.autoresearchDir, rawPath);
|
|
34080
34425
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
34081
34426
|
return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
|
|
34082
34427
|
}
|
|
34083
34428
|
try {
|
|
34084
|
-
if (!
|
|
34429
|
+
if (!existsSync33(targetPath)) {
|
|
34085
34430
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
|
|
34086
34431
|
}
|
|
34087
34432
|
let content = readFileSync24(targetPath, "utf-8");
|
|
@@ -34130,12 +34475,12 @@ var init_dream_engine = __esm({
|
|
|
34130
34475
|
const content = String(args["content"] ?? "");
|
|
34131
34476
|
if (!rawPath)
|
|
34132
34477
|
return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
|
|
34133
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
34478
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join44(this.dreamsDir, basename12(rawPath)) : join44(this.dreamsDir, rawPath);
|
|
34134
34479
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
34135
34480
|
return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
34136
34481
|
}
|
|
34137
34482
|
try {
|
|
34138
|
-
const dir =
|
|
34483
|
+
const dir = join44(targetPath, "..");
|
|
34139
34484
|
mkdirSync13(dir, { recursive: true });
|
|
34140
34485
|
writeFileSync12(targetPath, content, "utf-8");
|
|
34141
34486
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
|
|
@@ -34165,12 +34510,12 @@ var init_dream_engine = __esm({
|
|
|
34165
34510
|
const rawPath = String(args["path"] ?? "");
|
|
34166
34511
|
const oldStr = String(args["old_string"] ?? "");
|
|
34167
34512
|
const newStr = String(args["new_string"] ?? "");
|
|
34168
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
34513
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join44(this.dreamsDir, basename12(rawPath)) : join44(this.dreamsDir, rawPath);
|
|
34169
34514
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
34170
34515
|
return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
34171
34516
|
}
|
|
34172
34517
|
try {
|
|
34173
|
-
if (!
|
|
34518
|
+
if (!existsSync33(targetPath)) {
|
|
34174
34519
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
|
|
34175
34520
|
}
|
|
34176
34521
|
let content = readFileSync24(targetPath, "utf-8");
|
|
@@ -34209,7 +34554,7 @@ var init_dream_engine = __esm({
|
|
|
34209
34554
|
}
|
|
34210
34555
|
}
|
|
34211
34556
|
try {
|
|
34212
|
-
const output =
|
|
34557
|
+
const output = execSync28(cmd, {
|
|
34213
34558
|
cwd: this.repoRoot,
|
|
34214
34559
|
timeout: 3e4,
|
|
34215
34560
|
encoding: "utf-8",
|
|
@@ -34232,7 +34577,7 @@ var init_dream_engine = __esm({
|
|
|
34232
34577
|
constructor(config, repoRoot) {
|
|
34233
34578
|
this.config = config;
|
|
34234
34579
|
this.repoRoot = repoRoot;
|
|
34235
|
-
this.dreamsDir =
|
|
34580
|
+
this.dreamsDir = join44(repoRoot, ".oa", "dreams");
|
|
34236
34581
|
this.state = {
|
|
34237
34582
|
mode: "default",
|
|
34238
34583
|
active: false,
|
|
@@ -34316,7 +34661,7 @@ ${result.summary}`;
|
|
|
34316
34661
|
if (mode !== "default" || cycle === totalCycles) {
|
|
34317
34662
|
renderDreamContraction(cycle);
|
|
34318
34663
|
const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
|
|
34319
|
-
const summaryPath =
|
|
34664
|
+
const summaryPath = join44(this.dreamsDir, `cycle-${cycle}-summary.md`);
|
|
34320
34665
|
writeFileSync12(summaryPath, cycleSummary, "utf-8");
|
|
34321
34666
|
}
|
|
34322
34667
|
if (mode === "lucid" && !this.abortController.signal.aborted) {
|
|
@@ -34529,7 +34874,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
|
|
|
34529
34874
|
}
|
|
34530
34875
|
/** Build role-specific tool sets for swarm agents */
|
|
34531
34876
|
buildSwarmTools(role, _workspace) {
|
|
34532
|
-
const autoresearchDir =
|
|
34877
|
+
const autoresearchDir = join44(this.repoRoot, ".oa", "autoresearch");
|
|
34533
34878
|
const taskComplete = this.createSwarmTaskCompleteTool(role);
|
|
34534
34879
|
switch (role) {
|
|
34535
34880
|
case "researcher": {
|
|
@@ -34893,7 +35238,7 @@ INSTRUCTIONS:
|
|
|
34893
35238
|
2. Summarize the key learnings and next steps
|
|
34894
35239
|
|
|
34895
35240
|
Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
|
|
34896
|
-
const reportPath =
|
|
35241
|
+
const reportPath = join44(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
|
|
34897
35242
|
const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
|
|
34898
35243
|
|
|
34899
35244
|
**Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
@@ -34982,29 +35327,29 @@ ${summaryResult}
|
|
|
34982
35327
|
}
|
|
34983
35328
|
/** Save workspace backup for lucid mode */
|
|
34984
35329
|
saveVersionCheckpoint(cycle) {
|
|
34985
|
-
const checkpointDir =
|
|
35330
|
+
const checkpointDir = join44(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
|
|
34986
35331
|
try {
|
|
34987
35332
|
mkdirSync13(checkpointDir, { recursive: true });
|
|
34988
35333
|
try {
|
|
34989
|
-
const gitStatus =
|
|
35334
|
+
const gitStatus = execSync28("git status --porcelain", {
|
|
34990
35335
|
cwd: this.repoRoot,
|
|
34991
35336
|
encoding: "utf-8",
|
|
34992
35337
|
timeout: 1e4
|
|
34993
35338
|
});
|
|
34994
|
-
const gitDiff =
|
|
35339
|
+
const gitDiff = execSync28("git diff", {
|
|
34995
35340
|
cwd: this.repoRoot,
|
|
34996
35341
|
encoding: "utf-8",
|
|
34997
35342
|
timeout: 1e4
|
|
34998
35343
|
});
|
|
34999
|
-
const gitHash =
|
|
35344
|
+
const gitHash = execSync28("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
|
|
35000
35345
|
cwd: this.repoRoot,
|
|
35001
35346
|
encoding: "utf-8",
|
|
35002
35347
|
timeout: 5e3
|
|
35003
35348
|
}).trim();
|
|
35004
|
-
writeFileSync12(
|
|
35005
|
-
writeFileSync12(
|
|
35006
|
-
writeFileSync12(
|
|
35007
|
-
writeFileSync12(
|
|
35349
|
+
writeFileSync12(join44(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
|
|
35350
|
+
writeFileSync12(join44(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
|
|
35351
|
+
writeFileSync12(join44(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
|
|
35352
|
+
writeFileSync12(join44(checkpointDir, "checkpoint.json"), JSON.stringify({
|
|
35008
35353
|
cycle,
|
|
35009
35354
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
35010
35355
|
gitHash,
|
|
@@ -35012,7 +35357,7 @@ ${summaryResult}
|
|
|
35012
35357
|
}, null, 2), "utf-8");
|
|
35013
35358
|
renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
|
|
35014
35359
|
} catch {
|
|
35015
|
-
writeFileSync12(
|
|
35360
|
+
writeFileSync12(join44(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
|
|
35016
35361
|
renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
|
|
35017
35362
|
}
|
|
35018
35363
|
} catch (err) {
|
|
@@ -35070,14 +35415,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
|
|
|
35070
35415
|
---
|
|
35071
35416
|
*Auto-generated by open-agents dream engine*
|
|
35072
35417
|
`;
|
|
35073
|
-
writeFileSync12(
|
|
35418
|
+
writeFileSync12(join44(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
|
|
35074
35419
|
} catch {
|
|
35075
35420
|
}
|
|
35076
35421
|
}
|
|
35077
35422
|
/** Save dream state for resume/inspection */
|
|
35078
35423
|
saveDreamState() {
|
|
35079
35424
|
try {
|
|
35080
|
-
writeFileSync12(
|
|
35425
|
+
writeFileSync12(join44(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
|
|
35081
35426
|
} catch {
|
|
35082
35427
|
}
|
|
35083
35428
|
}
|
|
@@ -35451,8 +35796,8 @@ var init_bless_engine = __esm({
|
|
|
35451
35796
|
});
|
|
35452
35797
|
|
|
35453
35798
|
// packages/cli/dist/tui/dmn-engine.js
|
|
35454
|
-
import { existsSync as
|
|
35455
|
-
import { join as
|
|
35799
|
+
import { existsSync as existsSync34, readFileSync as readFileSync25, writeFileSync as writeFileSync13, mkdirSync as mkdirSync14, readdirSync as readdirSync11, unlinkSync as unlinkSync5 } from "node:fs";
|
|
35800
|
+
import { join as join45, basename as basename13 } from "node:path";
|
|
35456
35801
|
function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
|
|
35457
35802
|
const competenceReport = competence.length > 0 ? competence.map((c3) => {
|
|
35458
35803
|
const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
|
|
@@ -35565,8 +35910,8 @@ var init_dmn_engine = __esm({
|
|
|
35565
35910
|
constructor(config, repoRoot) {
|
|
35566
35911
|
this.config = config;
|
|
35567
35912
|
this.repoRoot = repoRoot;
|
|
35568
|
-
this.stateDir =
|
|
35569
|
-
this.historyDir =
|
|
35913
|
+
this.stateDir = join45(repoRoot, ".oa", "dmn");
|
|
35914
|
+
this.historyDir = join45(repoRoot, ".oa", "dmn", "cycles");
|
|
35570
35915
|
mkdirSync14(this.historyDir, { recursive: true });
|
|
35571
35916
|
this.loadState();
|
|
35572
35917
|
}
|
|
@@ -36156,11 +36501,11 @@ OUTPUT: Call task_complete with JSON:
|
|
|
36156
36501
|
async gatherMemoryTopics() {
|
|
36157
36502
|
const topics = [];
|
|
36158
36503
|
const dirs = [
|
|
36159
|
-
|
|
36160
|
-
|
|
36504
|
+
join45(this.repoRoot, ".oa", "memory"),
|
|
36505
|
+
join45(this.repoRoot, ".open-agents", "memory")
|
|
36161
36506
|
];
|
|
36162
36507
|
for (const dir of dirs) {
|
|
36163
|
-
if (!
|
|
36508
|
+
if (!existsSync34(dir))
|
|
36164
36509
|
continue;
|
|
36165
36510
|
try {
|
|
36166
36511
|
const files = readdirSync11(dir).filter((f) => f.endsWith(".json"));
|
|
@@ -36176,8 +36521,8 @@ OUTPUT: Call task_complete with JSON:
|
|
|
36176
36521
|
}
|
|
36177
36522
|
// ── State persistence ─────────────────────────────────────────────────
|
|
36178
36523
|
loadState() {
|
|
36179
|
-
const path =
|
|
36180
|
-
if (
|
|
36524
|
+
const path = join45(this.stateDir, "state.json");
|
|
36525
|
+
if (existsSync34(path)) {
|
|
36181
36526
|
try {
|
|
36182
36527
|
this.state = JSON.parse(readFileSync25(path, "utf-8"));
|
|
36183
36528
|
} catch {
|
|
@@ -36186,19 +36531,19 @@ OUTPUT: Call task_complete with JSON:
|
|
|
36186
36531
|
}
|
|
36187
36532
|
saveState() {
|
|
36188
36533
|
try {
|
|
36189
|
-
writeFileSync13(
|
|
36534
|
+
writeFileSync13(join45(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
|
|
36190
36535
|
} catch {
|
|
36191
36536
|
}
|
|
36192
36537
|
}
|
|
36193
36538
|
saveCycleResult(result) {
|
|
36194
36539
|
try {
|
|
36195
36540
|
const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
|
|
36196
|
-
writeFileSync13(
|
|
36541
|
+
writeFileSync13(join45(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
|
|
36197
36542
|
const files = readdirSync11(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
|
|
36198
36543
|
if (files.length > 50) {
|
|
36199
36544
|
for (const old of files.slice(0, files.length - 50)) {
|
|
36200
36545
|
try {
|
|
36201
|
-
unlinkSync5(
|
|
36546
|
+
unlinkSync5(join45(this.historyDir, old));
|
|
36202
36547
|
} catch {
|
|
36203
36548
|
}
|
|
36204
36549
|
}
|
|
@@ -36211,8 +36556,8 @@ OUTPUT: Call task_complete with JSON:
|
|
|
36211
36556
|
});
|
|
36212
36557
|
|
|
36213
36558
|
// packages/cli/dist/tui/snr-engine.js
|
|
36214
|
-
import { existsSync as
|
|
36215
|
-
import { join as
|
|
36559
|
+
import { existsSync as existsSync35, readdirSync as readdirSync12, readFileSync as readFileSync26 } from "node:fs";
|
|
36560
|
+
import { join as join46, basename as basename14 } from "node:path";
|
|
36216
36561
|
function computeDPrime(signalScores, noiseScores) {
|
|
36217
36562
|
if (signalScores.length === 0 || noiseScores.length === 0)
|
|
36218
36563
|
return 0;
|
|
@@ -36452,11 +36797,11 @@ Call task_complete with the JSON array when done.`, onEvent)
|
|
|
36452
36797
|
loadMemoryEntries(topics) {
|
|
36453
36798
|
const entries = [];
|
|
36454
36799
|
const dirs = [
|
|
36455
|
-
|
|
36456
|
-
|
|
36800
|
+
join46(this.repoRoot, ".oa", "memory"),
|
|
36801
|
+
join46(this.repoRoot, ".open-agents", "memory")
|
|
36457
36802
|
];
|
|
36458
36803
|
for (const dir of dirs) {
|
|
36459
|
-
if (!
|
|
36804
|
+
if (!existsSync35(dir))
|
|
36460
36805
|
continue;
|
|
36461
36806
|
try {
|
|
36462
36807
|
const files = readdirSync12(dir).filter((f) => f.endsWith(".json"));
|
|
@@ -36465,7 +36810,7 @@ Call task_complete with the JSON array when done.`, onEvent)
|
|
|
36465
36810
|
if (topics.length > 0 && !topics.includes(topic))
|
|
36466
36811
|
continue;
|
|
36467
36812
|
try {
|
|
36468
|
-
const data = JSON.parse(readFileSync26(
|
|
36813
|
+
const data = JSON.parse(readFileSync26(join46(dir, f), "utf-8"));
|
|
36469
36814
|
for (const [key, val] of Object.entries(data)) {
|
|
36470
36815
|
const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
36471
36816
|
entries.push({ topic, key, value });
|
|
@@ -37016,8 +37361,8 @@ var init_tool_policy = __esm({
|
|
|
37016
37361
|
});
|
|
37017
37362
|
|
|
37018
37363
|
// packages/cli/dist/tui/telegram-bridge.js
|
|
37019
|
-
import { mkdirSync as mkdirSync15, existsSync as
|
|
37020
|
-
import { join as
|
|
37364
|
+
import { mkdirSync as mkdirSync15, existsSync as existsSync36, unlinkSync as unlinkSync6, readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
|
|
37365
|
+
import { join as join47, resolve as resolve27 } from "node:path";
|
|
37021
37366
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
37022
37367
|
function convertMarkdownToTelegramHTML(md) {
|
|
37023
37368
|
let html = md;
|
|
@@ -37782,7 +38127,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
|
|
|
37782
38127
|
return null;
|
|
37783
38128
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
37784
38129
|
const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
|
|
37785
|
-
const localPath =
|
|
38130
|
+
const localPath = join47(this.mediaCacheDir, fileName);
|
|
37786
38131
|
await writeFileAsync(localPath, buffer);
|
|
37787
38132
|
return localPath;
|
|
37788
38133
|
} catch {
|
|
@@ -39505,11 +39850,11 @@ var init_status_bar = __esm({
|
|
|
39505
39850
|
import * as readline2 from "node:readline";
|
|
39506
39851
|
import { Writable } from "node:stream";
|
|
39507
39852
|
import { cwd } from "node:process";
|
|
39508
|
-
import { resolve as resolve28, join as
|
|
39853
|
+
import { resolve as resolve28, join as join48, dirname as dirname16, extname as extname9 } from "node:path";
|
|
39509
39854
|
import { createRequire as createRequire2 } from "node:module";
|
|
39510
39855
|
import { fileURLToPath as fileURLToPath12 } from "node:url";
|
|
39511
39856
|
import { readFileSync as readFileSync27, writeFileSync as writeFileSync14, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as readdirSync14, mkdirSync as mkdirSync16 } from "node:fs";
|
|
39512
|
-
import { existsSync as
|
|
39857
|
+
import { existsSync as existsSync37 } from "node:fs";
|
|
39513
39858
|
import { homedir as homedir13 } from "node:os";
|
|
39514
39859
|
function formatTimeAgo(date) {
|
|
39515
39860
|
const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
|
|
@@ -39524,17 +39869,17 @@ function formatTimeAgo(date) {
|
|
|
39524
39869
|
const days = Math.floor(hours / 24);
|
|
39525
39870
|
return `${days}d ago`;
|
|
39526
39871
|
}
|
|
39527
|
-
function
|
|
39872
|
+
function getVersion3() {
|
|
39528
39873
|
try {
|
|
39529
39874
|
const require2 = createRequire2(import.meta.url);
|
|
39530
39875
|
const thisDir = dirname16(fileURLToPath12(import.meta.url));
|
|
39531
39876
|
const candidates = [
|
|
39532
|
-
|
|
39533
|
-
|
|
39534
|
-
|
|
39877
|
+
join48(thisDir, "..", "package.json"),
|
|
39878
|
+
join48(thisDir, "..", "..", "package.json"),
|
|
39879
|
+
join48(thisDir, "..", "..", "..", "package.json")
|
|
39535
39880
|
];
|
|
39536
39881
|
for (const pkgPath of candidates) {
|
|
39537
|
-
if (
|
|
39882
|
+
if (existsSync37(pkgPath)) {
|
|
39538
39883
|
const pkg = require2(pkgPath);
|
|
39539
39884
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
39540
39885
|
return pkg.version ?? "0.0.0";
|
|
@@ -39641,8 +39986,9 @@ function buildTools(repoRoot, config, contextWindowSize) {
|
|
|
39641
39986
|
new SchedulerTool(repoRoot),
|
|
39642
39987
|
new ReminderTool(repoRoot),
|
|
39643
39988
|
new AgendaTool(repoRoot),
|
|
39644
|
-
// OpenCode delegation + long-horizon cron agent
|
|
39989
|
+
// OpenCode + Factory AI delegation + long-horizon cron agent
|
|
39645
39990
|
new OpenCodeTool(repoRoot),
|
|
39991
|
+
new FactoryTool(repoRoot),
|
|
39646
39992
|
new CronAgentTool(repoRoot),
|
|
39647
39993
|
// Nexus P2P networking + x402 micropayments
|
|
39648
39994
|
new NexusTool(repoRoot)
|
|
@@ -39739,15 +40085,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
|
|
|
39739
40085
|
function gatherMemorySnippets(root) {
|
|
39740
40086
|
const snippets = [];
|
|
39741
40087
|
const dirs = [
|
|
39742
|
-
|
|
39743
|
-
|
|
40088
|
+
join48(root, ".oa", "memory"),
|
|
40089
|
+
join48(root, ".open-agents", "memory")
|
|
39744
40090
|
];
|
|
39745
40091
|
for (const dir of dirs) {
|
|
39746
|
-
if (!
|
|
40092
|
+
if (!existsSync37(dir))
|
|
39747
40093
|
continue;
|
|
39748
40094
|
try {
|
|
39749
40095
|
for (const f of readdirSync14(dir).filter((f2) => f2.endsWith(".json"))) {
|
|
39750
|
-
const data = JSON.parse(readFileSync27(
|
|
40096
|
+
const data = JSON.parse(readFileSync27(join48(dir, f), "utf-8"));
|
|
39751
40097
|
for (const val of Object.values(data)) {
|
|
39752
40098
|
const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
39753
40099
|
if (v.length > 10)
|
|
@@ -40285,7 +40631,7 @@ async function startInteractive(config, repoPath) {
|
|
|
40285
40631
|
}
|
|
40286
40632
|
const carousel = new Carousel(carouselPhrases ?? void 0);
|
|
40287
40633
|
let carouselLines = 0;
|
|
40288
|
-
const version =
|
|
40634
|
+
const version = getVersion3();
|
|
40289
40635
|
if (isResumed) {
|
|
40290
40636
|
const resumeMsg = hasTaskToResume ? `Updated to v${version} \u2014 picking up where you left off.
|
|
40291
40637
|
` : `Updated to v${version}.
|
|
@@ -40397,7 +40743,7 @@ async function startInteractive(config, repoPath) {
|
|
|
40397
40743
|
let exposeGateway = null;
|
|
40398
40744
|
let peerMesh = null;
|
|
40399
40745
|
let inferenceRouter = null;
|
|
40400
|
-
const secretVault = new SecretVault(
|
|
40746
|
+
const secretVault = new SecretVault(join48(repoRoot, ".oa", "vault.enc"));
|
|
40401
40747
|
let adminSessionKey = null;
|
|
40402
40748
|
const callSubAgents = /* @__PURE__ */ new Map();
|
|
40403
40749
|
const streamRenderer = new StreamRenderer();
|
|
@@ -40602,12 +40948,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
40602
40948
|
const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
|
|
40603
40949
|
return [hits, line];
|
|
40604
40950
|
}
|
|
40605
|
-
const HISTORY_DIR =
|
|
40606
|
-
const HISTORY_FILE =
|
|
40951
|
+
const HISTORY_DIR = join48(homedir13(), ".open-agents");
|
|
40952
|
+
const HISTORY_FILE = join48(HISTORY_DIR, "repl-history");
|
|
40607
40953
|
const MAX_HISTORY_LINES = 500;
|
|
40608
40954
|
let savedHistory = [];
|
|
40609
40955
|
try {
|
|
40610
|
-
if (
|
|
40956
|
+
if (existsSync37(HISTORY_FILE)) {
|
|
40611
40957
|
const raw = readFileSync27(HISTORY_FILE, "utf8").trim();
|
|
40612
40958
|
if (raw)
|
|
40613
40959
|
savedHistory = raw.split("\n").reverse();
|
|
@@ -41486,8 +41832,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
41486
41832
|
return true;
|
|
41487
41833
|
},
|
|
41488
41834
|
destroyProject() {
|
|
41489
|
-
const oaPath =
|
|
41490
|
-
if (
|
|
41835
|
+
const oaPath = join48(repoRoot, OA_DIR);
|
|
41836
|
+
if (existsSync37(oaPath)) {
|
|
41491
41837
|
try {
|
|
41492
41838
|
rmSync2(oaPath, { recursive: true, force: true });
|
|
41493
41839
|
writeContent(() => renderInfo(`Removed ${OA_DIR}/ directory.`));
|
|
@@ -41788,8 +42134,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
41788
42134
|
}
|
|
41789
42135
|
}
|
|
41790
42136
|
const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
|
|
41791
|
-
const isImage = isImagePath(cleanPath) &&
|
|
41792
|
-
const isMedia = !isImage && isTranscribablePath(cleanPath) &&
|
|
42137
|
+
const isImage = isImagePath(cleanPath) && existsSync37(resolve28(repoRoot, cleanPath));
|
|
42138
|
+
const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync37(resolve28(repoRoot, cleanPath));
|
|
41793
42139
|
if (activeTask) {
|
|
41794
42140
|
if (isImage) {
|
|
41795
42141
|
try {
|
|
@@ -42308,7 +42654,7 @@ import { glob } from "glob";
|
|
|
42308
42654
|
import ignore from "ignore";
|
|
42309
42655
|
import { readFile as readFile16, stat as stat4 } from "node:fs/promises";
|
|
42310
42656
|
import { createHash as createHash4 } from "node:crypto";
|
|
42311
|
-
import { join as
|
|
42657
|
+
import { join as join49, relative as relative3, extname as extname10, basename as basename15 } from "node:path";
|
|
42312
42658
|
var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
|
|
42313
42659
|
var init_codebase_indexer = __esm({
|
|
42314
42660
|
"packages/indexer/dist/codebase-indexer.js"() {
|
|
@@ -42352,7 +42698,7 @@ var init_codebase_indexer = __esm({
|
|
|
42352
42698
|
const ig = ignore.default();
|
|
42353
42699
|
if (this.config.respectGitignore) {
|
|
42354
42700
|
try {
|
|
42355
|
-
const gitignoreContent = await readFile16(
|
|
42701
|
+
const gitignoreContent = await readFile16(join49(this.config.rootDir, ".gitignore"), "utf-8");
|
|
42356
42702
|
ig.add(gitignoreContent);
|
|
42357
42703
|
} catch {
|
|
42358
42704
|
}
|
|
@@ -42367,7 +42713,7 @@ var init_codebase_indexer = __esm({
|
|
|
42367
42713
|
for (const relativePath of files) {
|
|
42368
42714
|
if (ig.ignores(relativePath))
|
|
42369
42715
|
continue;
|
|
42370
|
-
const fullPath =
|
|
42716
|
+
const fullPath = join49(this.config.rootDir, relativePath);
|
|
42371
42717
|
try {
|
|
42372
42718
|
const fileStat = await stat4(fullPath);
|
|
42373
42719
|
if (fileStat.size > this.config.maxFileSize)
|
|
@@ -42413,7 +42759,7 @@ var init_codebase_indexer = __esm({
|
|
|
42413
42759
|
if (!child) {
|
|
42414
42760
|
child = {
|
|
42415
42761
|
name: part,
|
|
42416
|
-
path:
|
|
42762
|
+
path: join49(current.path, part),
|
|
42417
42763
|
type: "directory",
|
|
42418
42764
|
children: []
|
|
42419
42765
|
};
|
|
@@ -42496,13 +42842,13 @@ __export(index_repo_exports, {
|
|
|
42496
42842
|
indexRepoCommand: () => indexRepoCommand
|
|
42497
42843
|
});
|
|
42498
42844
|
import { resolve as resolve29 } from "node:path";
|
|
42499
|
-
import { existsSync as
|
|
42845
|
+
import { existsSync as existsSync38, statSync as statSync11 } from "node:fs";
|
|
42500
42846
|
import { cwd as cwd2 } from "node:process";
|
|
42501
42847
|
async function indexRepoCommand(opts, _config) {
|
|
42502
42848
|
const repoRoot = resolve29(opts.repoPath ?? cwd2());
|
|
42503
42849
|
printHeader("Index Repository");
|
|
42504
42850
|
printInfo(`Indexing: ${repoRoot}`);
|
|
42505
|
-
if (!
|
|
42851
|
+
if (!existsSync38(repoRoot)) {
|
|
42506
42852
|
printError(`Path does not exist: ${repoRoot}`);
|
|
42507
42853
|
process.exit(1);
|
|
42508
42854
|
}
|
|
@@ -42754,7 +43100,7 @@ var config_exports = {};
|
|
|
42754
43100
|
__export(config_exports, {
|
|
42755
43101
|
configCommand: () => configCommand
|
|
42756
43102
|
});
|
|
42757
|
-
import { join as
|
|
43103
|
+
import { join as join50, resolve as resolve30 } from "node:path";
|
|
42758
43104
|
import { homedir as homedir14 } from "node:os";
|
|
42759
43105
|
import { cwd as cwd3 } from "node:process";
|
|
42760
43106
|
function redactIfSensitive(key, value) {
|
|
@@ -42813,7 +43159,7 @@ function handleShow(opts, config) {
|
|
|
42813
43159
|
}
|
|
42814
43160
|
}
|
|
42815
43161
|
printSection("Config File");
|
|
42816
|
-
printInfo(`~/.open-agents/config.json (${
|
|
43162
|
+
printInfo(`~/.open-agents/config.json (${join50(homedir14(), ".open-agents", "config.json")})`);
|
|
42817
43163
|
printSection("Priority Chain");
|
|
42818
43164
|
printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
|
|
42819
43165
|
printInfo(" 2. Project .oa/settings.json (--local)");
|
|
@@ -42852,7 +43198,7 @@ function handleSet(opts, _config) {
|
|
|
42852
43198
|
const coerced = coerceForSettings(key, value);
|
|
42853
43199
|
saveProjectSettings(repoRoot, { [key]: coerced });
|
|
42854
43200
|
printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
|
|
42855
|
-
printInfo(`Saved to ${
|
|
43201
|
+
printInfo(`Saved to ${join50(repoRoot, ".oa", "settings.json")}`);
|
|
42856
43202
|
printInfo("This override applies only when running in this workspace.");
|
|
42857
43203
|
} catch (err) {
|
|
42858
43204
|
printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -42913,7 +43259,7 @@ var serve_exports = {};
|
|
|
42913
43259
|
__export(serve_exports, {
|
|
42914
43260
|
serveCommand: () => serveCommand
|
|
42915
43261
|
});
|
|
42916
|
-
import { spawn as
|
|
43262
|
+
import { spawn as spawn16 } from "node:child_process";
|
|
42917
43263
|
async function serveCommand(opts, config) {
|
|
42918
43264
|
const backendType = config.backendType;
|
|
42919
43265
|
if (backendType === "ollama") {
|
|
@@ -43006,7 +43352,7 @@ async function serveVllm(opts, config) {
|
|
|
43006
43352
|
}
|
|
43007
43353
|
async function runVllmServer(args, verbose) {
|
|
43008
43354
|
return new Promise((resolve31, reject) => {
|
|
43009
|
-
const child =
|
|
43355
|
+
const child = spawn16("python", args, {
|
|
43010
43356
|
stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
|
|
43011
43357
|
env: { ...process.env }
|
|
43012
43358
|
});
|
|
@@ -43072,7 +43418,7 @@ __export(eval_exports, {
|
|
|
43072
43418
|
});
|
|
43073
43419
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
43074
43420
|
import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync15 } from "node:fs";
|
|
43075
|
-
import { join as
|
|
43421
|
+
import { join as join51 } from "node:path";
|
|
43076
43422
|
async function evalCommand(opts, config) {
|
|
43077
43423
|
const suiteName = opts.suite ?? "basic";
|
|
43078
43424
|
const suite = SUITES[suiteName];
|
|
@@ -43197,9 +43543,9 @@ async function evalCommand(opts, config) {
|
|
|
43197
43543
|
process.exit(failed > 0 ? 1 : 0);
|
|
43198
43544
|
}
|
|
43199
43545
|
function createTempEvalRepo() {
|
|
43200
|
-
const dir =
|
|
43546
|
+
const dir = join51(tmpdir7(), `open-agents-eval-${Date.now()}`);
|
|
43201
43547
|
mkdirSync17(dir, { recursive: true });
|
|
43202
|
-
writeFileSync15(
|
|
43548
|
+
writeFileSync15(join51(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
|
|
43203
43549
|
return dir;
|
|
43204
43550
|
}
|
|
43205
43551
|
var BASIC_SUITE, FULL_SUITE, SUITES;
|
|
@@ -43259,7 +43605,7 @@ init_updater();
|
|
|
43259
43605
|
import { parseArgs as nodeParseArgs2 } from "node:util";
|
|
43260
43606
|
import { createRequire as createRequire3 } from "node:module";
|
|
43261
43607
|
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
43262
|
-
import { dirname as dirname17, join as
|
|
43608
|
+
import { dirname as dirname17, join as join52 } from "node:path";
|
|
43263
43609
|
|
|
43264
43610
|
// packages/cli/dist/cli.js
|
|
43265
43611
|
import { createInterface } from "node:readline";
|
|
@@ -43363,10 +43709,10 @@ Options:
|
|
|
43363
43709
|
init_config();
|
|
43364
43710
|
init_spinner();
|
|
43365
43711
|
init_output();
|
|
43366
|
-
function
|
|
43712
|
+
function getVersion4() {
|
|
43367
43713
|
try {
|
|
43368
43714
|
const require2 = createRequire3(import.meta.url);
|
|
43369
|
-
const pkgPath =
|
|
43715
|
+
const pkgPath = join52(dirname17(fileURLToPath13(import.meta.url)), "..", "package.json");
|
|
43370
43716
|
const pkg = require2(pkgPath);
|
|
43371
43717
|
return pkg.version;
|
|
43372
43718
|
} catch {
|
|
@@ -43513,7 +43859,7 @@ Examples:
|
|
|
43513
43859
|
process.stdout.write(text + "\n");
|
|
43514
43860
|
}
|
|
43515
43861
|
async function main() {
|
|
43516
|
-
const version =
|
|
43862
|
+
const version = getVersion4();
|
|
43517
43863
|
const parsed = parseCliArgs(process.argv);
|
|
43518
43864
|
if (parsed.version) {
|
|
43519
43865
|
process.stdout.write(`open-agents v${version}
|