open-agents-ai 0.169.0 → 0.171.0
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 +1142 -834
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10483,8 +10483,8 @@ function deleteCustomToolDefinition(name, scope, repoRoot) {
|
|
|
10483
10483
|
const dir = scope === "project" && repoRoot ? projectToolsDir(repoRoot) : globalToolsDir();
|
|
10484
10484
|
const filePath = join16(dir, `${name}.json`);
|
|
10485
10485
|
if (existsSync13(filePath)) {
|
|
10486
|
-
const { unlinkSync:
|
|
10487
|
-
|
|
10486
|
+
const { unlinkSync: unlinkSync12 } = __require("node:fs");
|
|
10487
|
+
unlinkSync12(filePath);
|
|
10488
10488
|
return true;
|
|
10489
10489
|
}
|
|
10490
10490
|
return false;
|
|
@@ -11659,8 +11659,8 @@ async function loadTranscribeCli() {
|
|
|
11659
11659
|
const nvmBase = join19(homedir6(), ".nvm", "versions", "node");
|
|
11660
11660
|
if (existsSync16(nvmBase)) {
|
|
11661
11661
|
try {
|
|
11662
|
-
const { readdirSync:
|
|
11663
|
-
for (const ver of
|
|
11662
|
+
const { readdirSync: readdirSync20 } = await import("node:fs");
|
|
11663
|
+
for (const ver of readdirSync20(nvmBase)) {
|
|
11664
11664
|
const tcPath = join19(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
|
|
11665
11665
|
if (existsSync16(join19(tcPath, "dist", "index.js"))) {
|
|
11666
11666
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
@@ -12713,13 +12713,13 @@ Justification: ${justification || "(none provided)"}`,
|
|
|
12713
12713
|
}
|
|
12714
12714
|
const snapshot = JSON.stringify(this.selfState, null, 2);
|
|
12715
12715
|
try {
|
|
12716
|
-
const { createHash:
|
|
12716
|
+
const { createHash: createHash6 } = await import("node:crypto");
|
|
12717
12717
|
const snapshotDir = join21(this.cwd, ".oa", "identity", "snapshots");
|
|
12718
12718
|
await mkdir5(snapshotDir, { recursive: true });
|
|
12719
12719
|
const version = this.selfState.version;
|
|
12720
12720
|
const snapshotPath = join21(snapshotDir, `v${version}.json`);
|
|
12721
12721
|
await writeFile9(snapshotPath, snapshot, "utf8");
|
|
12722
|
-
const hash =
|
|
12722
|
+
const hash = createHash6("sha256").update(snapshot).digest("hex");
|
|
12723
12723
|
await writeFile9(join21(this.cwd, ".oa", "identity", "latest-hash.txt"), hash, "utf8");
|
|
12724
12724
|
let ipfsCid = "";
|
|
12725
12725
|
try {
|
|
@@ -12852,8 +12852,8 @@ New: ${newNarrative.slice(0, 200)}...`,
|
|
|
12852
12852
|
}
|
|
12853
12853
|
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
12854
12854
|
createDefaultState() {
|
|
12855
|
-
const { createHash:
|
|
12856
|
-
const machineId =
|
|
12855
|
+
const { createHash: createHash6 } = __require("node:crypto");
|
|
12856
|
+
const machineId = createHash6("sha256").update(this.cwd).digest("hex").slice(0, 12);
|
|
12857
12857
|
return {
|
|
12858
12858
|
self_id: `oa-${machineId}`,
|
|
12859
12859
|
version: 1,
|
|
@@ -13402,9 +13402,9 @@ print("${sentinel}")
|
|
|
13402
13402
|
if (!this.proc || this.proc.killed) {
|
|
13403
13403
|
return { success: false, path: "" };
|
|
13404
13404
|
}
|
|
13405
|
-
const { mkdirSync:
|
|
13405
|
+
const { mkdirSync: mkdirSync25, writeFileSync: writeFileSync24 } = await import("node:fs");
|
|
13406
13406
|
const sessionDir = join22(this.cwd, ".oa", "rlm");
|
|
13407
|
-
|
|
13407
|
+
mkdirSync25(sessionDir, { recursive: true });
|
|
13408
13408
|
const sessionPath = join22(sessionDir, "session.json");
|
|
13409
13409
|
try {
|
|
13410
13410
|
const inspectCode = `
|
|
@@ -13428,7 +13428,7 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
|
|
|
13428
13428
|
trajectoryCount: this.trajectory.length,
|
|
13429
13429
|
subCallCount: this.subCallCount
|
|
13430
13430
|
};
|
|
13431
|
-
|
|
13431
|
+
writeFileSync24(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
|
|
13432
13432
|
return { success: true, path: sessionPath };
|
|
13433
13433
|
}
|
|
13434
13434
|
} catch {
|
|
@@ -13440,11 +13440,11 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
|
|
|
13440
13440
|
* what was previously computed. */
|
|
13441
13441
|
async loadSessionInfo() {
|
|
13442
13442
|
try {
|
|
13443
|
-
const { readFileSync:
|
|
13443
|
+
const { readFileSync: readFileSync39, existsSync: existsSync51 } = await import("node:fs");
|
|
13444
13444
|
const sessionPath = join22(this.cwd, ".oa", "rlm", "session.json");
|
|
13445
|
-
if (!
|
|
13445
|
+
if (!existsSync51(sessionPath))
|
|
13446
13446
|
return null;
|
|
13447
|
-
return JSON.parse(
|
|
13447
|
+
return JSON.parse(readFileSync39(sessionPath, "utf8"));
|
|
13448
13448
|
} catch {
|
|
13449
13449
|
return null;
|
|
13450
13450
|
}
|
|
@@ -13621,10 +13621,10 @@ var init_memory_metabolism = __esm({
|
|
|
13621
13621
|
const trajDir = join23(this.cwd, ".oa", "rlm-trajectories");
|
|
13622
13622
|
let lessons = [];
|
|
13623
13623
|
try {
|
|
13624
|
-
const { readdirSync:
|
|
13625
|
-
const files =
|
|
13624
|
+
const { readdirSync: readdirSync20, readFileSync: readFileSync39 } = await import("node:fs");
|
|
13625
|
+
const files = readdirSync20(trajDir).filter((f) => f.endsWith(".jsonl")).sort().reverse().slice(0, 3);
|
|
13626
13626
|
for (const file of files) {
|
|
13627
|
-
const lines =
|
|
13627
|
+
const lines = readFileSync39(join23(trajDir, file), "utf8").split("\n").filter((l) => l.trim());
|
|
13628
13628
|
for (const line of lines) {
|
|
13629
13629
|
try {
|
|
13630
13630
|
const entry = JSON.parse(line);
|
|
@@ -14008,14 +14008,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14008
14008
|
* Optionally filter by task type for phase-aware context (FSM paper insight).
|
|
14009
14009
|
*/
|
|
14010
14010
|
getTopMemoriesSync(k = 5, taskType) {
|
|
14011
|
-
const { readFileSync:
|
|
14011
|
+
const { readFileSync: readFileSync39, existsSync: existsSync51 } = __require("node:fs");
|
|
14012
14012
|
const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14013
14013
|
const storeFile = join23(metaDir, "store.json");
|
|
14014
|
-
if (!
|
|
14014
|
+
if (!existsSync51(storeFile))
|
|
14015
14015
|
return "";
|
|
14016
14016
|
let store = [];
|
|
14017
14017
|
try {
|
|
14018
|
-
store = JSON.parse(
|
|
14018
|
+
store = JSON.parse(readFileSync39(storeFile, "utf8"));
|
|
14019
14019
|
} catch {
|
|
14020
14020
|
return "";
|
|
14021
14021
|
}
|
|
@@ -14037,14 +14037,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14037
14037
|
/** Update memory scores based on task outcome. Called after task completion.
|
|
14038
14038
|
* Memories used in successful tasks get boosted. Memories present during failures get decayed. */
|
|
14039
14039
|
updateFromOutcomeSync(surfacedMemoryText, succeeded) {
|
|
14040
|
-
const { readFileSync:
|
|
14040
|
+
const { readFileSync: readFileSync39, writeFileSync: writeFileSync24, existsSync: existsSync51, mkdirSync: mkdirSync25 } = __require("node:fs");
|
|
14041
14041
|
const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14042
14042
|
const storeFile = join23(metaDir, "store.json");
|
|
14043
|
-
if (!
|
|
14043
|
+
if (!existsSync51(storeFile))
|
|
14044
14044
|
return;
|
|
14045
14045
|
let store = [];
|
|
14046
14046
|
try {
|
|
14047
|
-
store = JSON.parse(
|
|
14047
|
+
store = JSON.parse(readFileSync39(storeFile, "utf8"));
|
|
14048
14048
|
} catch {
|
|
14049
14049
|
return;
|
|
14050
14050
|
}
|
|
@@ -14068,8 +14068,8 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14068
14068
|
updated = true;
|
|
14069
14069
|
}
|
|
14070
14070
|
if (updated) {
|
|
14071
|
-
|
|
14072
|
-
|
|
14071
|
+
mkdirSync25(metaDir, { recursive: true });
|
|
14072
|
+
writeFileSync24(storeFile, JSON.stringify(store, null, 2));
|
|
14073
14073
|
}
|
|
14074
14074
|
}
|
|
14075
14075
|
// ── Storage ──────────────────────────────────────────────────────────
|
|
@@ -14491,13 +14491,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
14491
14491
|
// Per EvoSkill (arXiv:2603.02766): retrieve relevant strategies from archive.
|
|
14492
14492
|
/** Retrieve top-K strategies for context injection. Returns "" if none. */
|
|
14493
14493
|
getRelevantStrategiesSync(k = 3, taskType) {
|
|
14494
|
-
const { readFileSync:
|
|
14494
|
+
const { readFileSync: readFileSync39, existsSync: existsSync51 } = __require("node:fs");
|
|
14495
14495
|
const archiveFile = join25(this.cwd, ".oa", "arche", "variants.json");
|
|
14496
|
-
if (!
|
|
14496
|
+
if (!existsSync51(archiveFile))
|
|
14497
14497
|
return "";
|
|
14498
14498
|
let variants = [];
|
|
14499
14499
|
try {
|
|
14500
|
-
variants = JSON.parse(
|
|
14500
|
+
variants = JSON.parse(readFileSync39(archiveFile, "utf8"));
|
|
14501
14501
|
} catch {
|
|
14502
14502
|
return "";
|
|
14503
14503
|
}
|
|
@@ -14515,13 +14515,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
14515
14515
|
}
|
|
14516
14516
|
/** Archive a strategy variant synchronously (for task completion path) */
|
|
14517
14517
|
archiveVariantSync(strategy, outcome, tags = []) {
|
|
14518
|
-
const { readFileSync:
|
|
14518
|
+
const { readFileSync: readFileSync39, writeFileSync: writeFileSync24, existsSync: existsSync51, mkdirSync: mkdirSync25 } = __require("node:fs");
|
|
14519
14519
|
const dir = join25(this.cwd, ".oa", "arche");
|
|
14520
14520
|
const archiveFile = join25(dir, "variants.json");
|
|
14521
14521
|
let variants = [];
|
|
14522
14522
|
try {
|
|
14523
|
-
if (
|
|
14524
|
-
variants = JSON.parse(
|
|
14523
|
+
if (existsSync51(archiveFile))
|
|
14524
|
+
variants = JSON.parse(readFileSync39(archiveFile, "utf8"));
|
|
14525
14525
|
} catch {
|
|
14526
14526
|
}
|
|
14527
14527
|
variants.push({
|
|
@@ -14536,8 +14536,8 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
14536
14536
|
});
|
|
14537
14537
|
if (variants.length > 50)
|
|
14538
14538
|
variants = variants.slice(-50);
|
|
14539
|
-
|
|
14540
|
-
|
|
14539
|
+
mkdirSync25(dir, { recursive: true });
|
|
14540
|
+
writeFileSync24(archiveFile, JSON.stringify(variants, null, 2));
|
|
14541
14541
|
}
|
|
14542
14542
|
async saveArchive(variants) {
|
|
14543
14543
|
const dir = join25(this.cwd, ".oa", "arche");
|
|
@@ -21201,19 +21201,324 @@ var init_environment_snapshot = __esm({
|
|
|
21201
21201
|
}
|
|
21202
21202
|
});
|
|
21203
21203
|
|
|
21204
|
+
// packages/execution/dist/tools/video-understand.js
|
|
21205
|
+
import { execSync as execSync24 } from "node:child_process";
|
|
21206
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9, readFileSync as readFileSync20, readdirSync as readdirSync7, unlinkSync as unlinkSync4 } from "node:fs";
|
|
21207
|
+
import { join as join41, basename as basename10 } from "node:path";
|
|
21208
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
21209
|
+
function isYouTubeUrl2(url) {
|
|
21210
|
+
return /(?:youtube\.com\/(?:watch|shorts|live|embed|v\/)|youtu\.be\/)/i.test(url);
|
|
21211
|
+
}
|
|
21212
|
+
function ensureYtDlp2() {
|
|
21213
|
+
try {
|
|
21214
|
+
execSync24("yt-dlp --version", { timeout: 5e3, stdio: "pipe" });
|
|
21215
|
+
return true;
|
|
21216
|
+
} catch {
|
|
21217
|
+
try {
|
|
21218
|
+
execSync24("pip3 install --break-system-packages yt-dlp 2>/dev/null || pip3 install --user yt-dlp 2>/dev/null", { timeout: 6e4, stdio: "pipe" });
|
|
21219
|
+
return true;
|
|
21220
|
+
} catch {
|
|
21221
|
+
return false;
|
|
21222
|
+
}
|
|
21223
|
+
}
|
|
21224
|
+
}
|
|
21225
|
+
function ensureFfmpeg() {
|
|
21226
|
+
try {
|
|
21227
|
+
execSync24("ffmpeg -version", { timeout: 3e3, stdio: "pipe" });
|
|
21228
|
+
return true;
|
|
21229
|
+
} catch {
|
|
21230
|
+
return false;
|
|
21231
|
+
}
|
|
21232
|
+
}
|
|
21233
|
+
function imageHash(imagePath) {
|
|
21234
|
+
try {
|
|
21235
|
+
const data = readFileSync20(imagePath);
|
|
21236
|
+
return createHash2("md5").update(data).digest("hex").slice(0, 12);
|
|
21237
|
+
} catch {
|
|
21238
|
+
return "unknown";
|
|
21239
|
+
}
|
|
21240
|
+
}
|
|
21241
|
+
function deduplicateFrames(frames, similarityThreshold = 0) {
|
|
21242
|
+
if (frames.length <= 1)
|
|
21243
|
+
return frames;
|
|
21244
|
+
let prevHash = "";
|
|
21245
|
+
for (const frame of frames) {
|
|
21246
|
+
if (frame.hash === prevHash) {
|
|
21247
|
+
frame.isDuplicate = true;
|
|
21248
|
+
}
|
|
21249
|
+
prevHash = frame.hash;
|
|
21250
|
+
}
|
|
21251
|
+
return frames;
|
|
21252
|
+
}
|
|
21253
|
+
function formatTime2(seconds) {
|
|
21254
|
+
const m = Math.floor(seconds / 60);
|
|
21255
|
+
const s = Math.floor(seconds % 60);
|
|
21256
|
+
const ms = Math.floor(seconds % 1 * 10);
|
|
21257
|
+
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}.${ms}`;
|
|
21258
|
+
}
|
|
21259
|
+
var VideoUnderstandTool;
|
|
21260
|
+
var init_video_understand = __esm({
|
|
21261
|
+
"packages/execution/dist/tools/video-understand.js"() {
|
|
21262
|
+
"use strict";
|
|
21263
|
+
VideoUnderstandTool = class {
|
|
21264
|
+
name = "video_understand";
|
|
21265
|
+
description = "Analyze a video from URL or local file. Produces timestamped transcript aligned with keyframe descriptions. Supports YouTube URLs and direct video files. Pipeline: download \u2192 transcribe (Whisper) \u2192 extract keyframes (scene detection) \u2192 describe frames \u2192 align timestamps \u2192 save structured output.";
|
|
21266
|
+
parameters = {
|
|
21267
|
+
type: "object",
|
|
21268
|
+
properties: {
|
|
21269
|
+
url: { type: "string", description: "YouTube URL or direct video URL" },
|
|
21270
|
+
path: { type: "string", description: "Local video file path (alternative to url)" },
|
|
21271
|
+
model: { type: "string", description: "Whisper model: tiny, base, small, medium (default: base)" },
|
|
21272
|
+
frame_interval: { type: "number", description: "Seconds between forced frame samples (default: 30)" },
|
|
21273
|
+
scene_threshold: { type: "number", description: "Scene change sensitivity 0-1 (default: 0.1)" },
|
|
21274
|
+
skip_frames: { type: "boolean", description: "Skip frame extraction (audio-only, default: false)" }
|
|
21275
|
+
},
|
|
21276
|
+
required: []
|
|
21277
|
+
};
|
|
21278
|
+
workingDir;
|
|
21279
|
+
constructor(workingDir) {
|
|
21280
|
+
this.workingDir = workingDir;
|
|
21281
|
+
}
|
|
21282
|
+
async execute(args) {
|
|
21283
|
+
const start = performance.now();
|
|
21284
|
+
const url = args["url"];
|
|
21285
|
+
const localPath = args["path"];
|
|
21286
|
+
const whisperModel = String(args["model"] ?? "base");
|
|
21287
|
+
const frameInterval = Number(args["frame_interval"] ?? 30);
|
|
21288
|
+
const sceneThreshold = Number(args["scene_threshold"] ?? 0.1);
|
|
21289
|
+
const skipFrames = Boolean(args["skip_frames"]);
|
|
21290
|
+
if (!url && !localPath) {
|
|
21291
|
+
return { success: false, output: "", error: "url or path required", durationMs: performance.now() - start };
|
|
21292
|
+
}
|
|
21293
|
+
const outDir = join41(this.workingDir, ".oa", "video-analysis");
|
|
21294
|
+
mkdirSync9(outDir, { recursive: true });
|
|
21295
|
+
const tmpDir = join41(outDir, `tmp-${Date.now()}`);
|
|
21296
|
+
mkdirSync9(tmpDir, { recursive: true });
|
|
21297
|
+
try {
|
|
21298
|
+
let videoPath;
|
|
21299
|
+
let audioPath;
|
|
21300
|
+
let title;
|
|
21301
|
+
if (url) {
|
|
21302
|
+
if (isYouTubeUrl2(url)) {
|
|
21303
|
+
if (!ensureYtDlp2()) {
|
|
21304
|
+
return { success: false, output: "", error: "yt-dlp required but not available. Install: pip3 install yt-dlp", durationMs: performance.now() - start };
|
|
21305
|
+
}
|
|
21306
|
+
try {
|
|
21307
|
+
execSync24(`yt-dlp -f "worst[ext=mp4]" -o "${join41(tmpDir, "video.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
|
|
21308
|
+
} catch {
|
|
21309
|
+
execSync24(`yt-dlp -f worst -o "${join41(tmpDir, "video.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
|
|
21310
|
+
}
|
|
21311
|
+
execSync24(`yt-dlp -x --audio-format mp3 --audio-quality 5 -o "${join41(tmpDir, "audio.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
|
|
21312
|
+
try {
|
|
21313
|
+
title = execSync24(`yt-dlp --get-title "${url}"`, { encoding: "utf-8", timeout: 15e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
21314
|
+
} catch {
|
|
21315
|
+
}
|
|
21316
|
+
} else {
|
|
21317
|
+
execSync24(`curl -sL -o "${join41(tmpDir, "video.mp4")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
|
|
21318
|
+
execSync24(`ffmpeg -i "${join41(tmpDir, "video.mp4")}" -vn -acodec libmp3lame -q:a 5 "${join41(tmpDir, "audio.mp3")}" -y`, { timeout: 12e4, stdio: "pipe" });
|
|
21319
|
+
}
|
|
21320
|
+
videoPath = readdirSync7(tmpDir).find((f) => f.startsWith("video")) ? join41(tmpDir, readdirSync7(tmpDir).find((f) => f.startsWith("video"))) : join41(tmpDir, "video.mp4");
|
|
21321
|
+
audioPath = readdirSync7(tmpDir).find((f) => f.startsWith("audio")) ? join41(tmpDir, readdirSync7(tmpDir).find((f) => f.startsWith("audio"))) : join41(tmpDir, "audio.mp3");
|
|
21322
|
+
} else {
|
|
21323
|
+
videoPath = localPath;
|
|
21324
|
+
audioPath = join41(tmpDir, "audio.mp3");
|
|
21325
|
+
execSync24(`ffmpeg -i "${videoPath}" -vn -acodec libmp3lame -q:a 5 "${audioPath}" -y`, { timeout: 12e4, stdio: "pipe" });
|
|
21326
|
+
}
|
|
21327
|
+
let segments = [];
|
|
21328
|
+
let language = "en";
|
|
21329
|
+
let duration = 0;
|
|
21330
|
+
try {
|
|
21331
|
+
const jsonOut = join41(tmpDir, "transcript.json");
|
|
21332
|
+
execSync24(`transcribe-cli transcribe "${audioPath}" --model ${whisperModel} --format json -o "${tmpDir}"`, { timeout: 6e5, stdio: "pipe" });
|
|
21333
|
+
const jsonFile = readdirSync7(tmpDir).find((f) => f.endsWith(".json") && f !== "result.json");
|
|
21334
|
+
if (jsonFile) {
|
|
21335
|
+
const data = JSON.parse(readFileSync20(join41(tmpDir, jsonFile), "utf-8"));
|
|
21336
|
+
segments = (data.segments || []).map((s) => ({
|
|
21337
|
+
start: s.start ?? 0,
|
|
21338
|
+
end: s.end ?? 0,
|
|
21339
|
+
text: (s.text || "").trim(),
|
|
21340
|
+
speaker: s.speaker
|
|
21341
|
+
}));
|
|
21342
|
+
language = data.language || "en";
|
|
21343
|
+
duration = data.duration || 0;
|
|
21344
|
+
}
|
|
21345
|
+
} catch (err) {
|
|
21346
|
+
segments = [];
|
|
21347
|
+
}
|
|
21348
|
+
let frames = [];
|
|
21349
|
+
if (!skipFrames && ensureFfmpeg() && existsSync27(videoPath)) {
|
|
21350
|
+
const framesDir = join41(tmpDir, "frames");
|
|
21351
|
+
mkdirSync9(framesDir, { recursive: true });
|
|
21352
|
+
const fps = 25;
|
|
21353
|
+
const intervalFrames = Math.max(1, frameInterval * fps);
|
|
21354
|
+
try {
|
|
21355
|
+
execSync24(`ffmpeg -i "${videoPath}" -vf "select='gt(scene\\,${sceneThreshold})+not(mod(n\\,${intervalFrames}))',showinfo" -vsync vfr "${join41(framesDir, "frame_%04d.jpg")}" -y`, { timeout: 3e5, stdio: "pipe" });
|
|
21356
|
+
} catch {
|
|
21357
|
+
}
|
|
21358
|
+
const frameFiles = readdirSync7(framesDir).filter((f) => f.endsWith(".jpg")).sort();
|
|
21359
|
+
for (let i = 0; i < frameFiles.length; i++) {
|
|
21360
|
+
const framePath = join41(framesDir, frameFiles[i]);
|
|
21361
|
+
const hash = imageHash(framePath);
|
|
21362
|
+
const timestamp2 = duration > 0 ? i / Math.max(1, frameFiles.length - 1) * duration : i * frameInterval;
|
|
21363
|
+
frames.push({
|
|
21364
|
+
path: framePath,
|
|
21365
|
+
timestamp: timestamp2,
|
|
21366
|
+
hash,
|
|
21367
|
+
isDuplicate: false
|
|
21368
|
+
});
|
|
21369
|
+
}
|
|
21370
|
+
deduplicateFrames(frames);
|
|
21371
|
+
const permanentDir = join41(outDir, `frames-${Date.now()}`);
|
|
21372
|
+
mkdirSync9(permanentDir, { recursive: true });
|
|
21373
|
+
for (const frame of frames.filter((f) => !f.isDuplicate)) {
|
|
21374
|
+
const dest = join41(permanentDir, basename10(frame.path));
|
|
21375
|
+
try {
|
|
21376
|
+
writeFileSync9(dest, readFileSync20(frame.path));
|
|
21377
|
+
frame.path = dest;
|
|
21378
|
+
} catch {
|
|
21379
|
+
}
|
|
21380
|
+
}
|
|
21381
|
+
}
|
|
21382
|
+
const uniqueFrames = frames.filter((f) => !f.isDuplicate);
|
|
21383
|
+
const alignedTimeline = segments.map((seg) => {
|
|
21384
|
+
const mid = (seg.start + seg.end) / 2;
|
|
21385
|
+
let nearestFrame;
|
|
21386
|
+
let minDist = Infinity;
|
|
21387
|
+
for (const frame of uniqueFrames) {
|
|
21388
|
+
const dist = Math.abs(frame.timestamp - mid);
|
|
21389
|
+
if (dist < minDist) {
|
|
21390
|
+
minDist = dist;
|
|
21391
|
+
nearestFrame = frame;
|
|
21392
|
+
}
|
|
21393
|
+
}
|
|
21394
|
+
return {
|
|
21395
|
+
start: seg.start,
|
|
21396
|
+
end: seg.end,
|
|
21397
|
+
speech: seg.text,
|
|
21398
|
+
frameDescription: nearestFrame?.description,
|
|
21399
|
+
frameOcr: nearestFrame?.ocrText
|
|
21400
|
+
};
|
|
21401
|
+
});
|
|
21402
|
+
const result = {
|
|
21403
|
+
source: url || localPath || "unknown",
|
|
21404
|
+
title,
|
|
21405
|
+
duration,
|
|
21406
|
+
language,
|
|
21407
|
+
segments,
|
|
21408
|
+
frames: frames.filter((f) => !f.isDuplicate),
|
|
21409
|
+
alignedTimeline
|
|
21410
|
+
};
|
|
21411
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
21412
|
+
const resultFile = join41(outDir, `understanding-${timestamp}.json`);
|
|
21413
|
+
writeFileSync9(resultFile, JSON.stringify(result, null, 2), "utf-8");
|
|
21414
|
+
try {
|
|
21415
|
+
const memDir = join41(this.workingDir, ".oa", "memory");
|
|
21416
|
+
mkdirSync9(memDir, { recursive: true });
|
|
21417
|
+
const indexFile = join41(memDir, "video-analyses.json");
|
|
21418
|
+
let indexEntries = [];
|
|
21419
|
+
try {
|
|
21420
|
+
indexEntries = JSON.parse(readFileSync20(indexFile, "utf-8"));
|
|
21421
|
+
} catch {
|
|
21422
|
+
}
|
|
21423
|
+
indexEntries.push({
|
|
21424
|
+
source: url || localPath,
|
|
21425
|
+
title,
|
|
21426
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21427
|
+
duration,
|
|
21428
|
+
language,
|
|
21429
|
+
segmentCount: segments.length,
|
|
21430
|
+
frameCount: uniqueFrames.length,
|
|
21431
|
+
resultPath: resultFile,
|
|
21432
|
+
summary: segments.slice(0, 3).map((s) => s.text).join(" ").slice(0, 200)
|
|
21433
|
+
});
|
|
21434
|
+
if (indexEntries.length > 30)
|
|
21435
|
+
indexEntries = indexEntries.slice(-30);
|
|
21436
|
+
writeFileSync9(indexFile, JSON.stringify(indexEntries, null, 2), "utf-8");
|
|
21437
|
+
const CHUNK_WINDOW = 30;
|
|
21438
|
+
const transcriptFile = join41(memDir, "video-transcripts.json");
|
|
21439
|
+
let transcriptEntries = {};
|
|
21440
|
+
try {
|
|
21441
|
+
transcriptEntries = JSON.parse(readFileSync20(transcriptFile, "utf-8"));
|
|
21442
|
+
} catch {
|
|
21443
|
+
}
|
|
21444
|
+
const videoLabel = title || basename10(url || localPath || "unknown");
|
|
21445
|
+
const chunks = /* @__PURE__ */ new Map();
|
|
21446
|
+
for (const seg of segments) {
|
|
21447
|
+
const chunkIdx = Math.floor(seg.start / CHUNK_WINDOW);
|
|
21448
|
+
if (!chunks.has(chunkIdx))
|
|
21449
|
+
chunks.set(chunkIdx, []);
|
|
21450
|
+
chunks.get(chunkIdx).push(`[${formatTime2(seg.start)}] ${seg.text}`);
|
|
21451
|
+
}
|
|
21452
|
+
for (const [chunkIdx, lines2] of chunks) {
|
|
21453
|
+
const startSec = chunkIdx * CHUNK_WINDOW;
|
|
21454
|
+
const endSec = startSec + CHUNK_WINDOW;
|
|
21455
|
+
const key = `${videoLabel} [${formatTime2(startSec)}-${formatTime2(endSec)}]`;
|
|
21456
|
+
transcriptEntries[key] = {
|
|
21457
|
+
value: `Video: ${videoLabel} | Time: ${formatTime2(startSec)} to ${formatTime2(endSec)}
|
|
21458
|
+
` + lines2.join("\n"),
|
|
21459
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
21460
|
+
};
|
|
21461
|
+
}
|
|
21462
|
+
transcriptEntries[`${videoLabel} \u2014 summary`] = {
|
|
21463
|
+
value: `Video: ${videoLabel} | Duration: ${formatTime2(duration)} | ${segments.length} segments | ${uniqueFrames.length} frames
|
|
21464
|
+
Topic: ${segments.slice(0, 5).map((s) => s.text).join(" ").slice(0, 300)}`,
|
|
21465
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
21466
|
+
};
|
|
21467
|
+
writeFileSync9(transcriptFile, JSON.stringify(transcriptEntries, null, 2), "utf-8");
|
|
21468
|
+
} catch {
|
|
21469
|
+
}
|
|
21470
|
+
const lines = [];
|
|
21471
|
+
lines.push(`# Video Analysis${title ? `: ${title}` : ""}`);
|
|
21472
|
+
lines.push(`Source: ${url || localPath}`);
|
|
21473
|
+
lines.push(`Duration: ${duration.toFixed(1)}s | Language: ${language} | Segments: ${segments.length} | Frames: ${uniqueFrames.length}`);
|
|
21474
|
+
lines.push(`Saved: ${resultFile}`);
|
|
21475
|
+
lines.push("");
|
|
21476
|
+
lines.push("## Transcript");
|
|
21477
|
+
for (const seg of segments) {
|
|
21478
|
+
lines.push(`[${formatTime2(seg.start)} \u2192 ${formatTime2(seg.end)}] ${seg.text}`);
|
|
21479
|
+
}
|
|
21480
|
+
if (uniqueFrames.length > 0) {
|
|
21481
|
+
lines.push("");
|
|
21482
|
+
lines.push(`## Frames (${uniqueFrames.length} unique, ${frames.length - uniqueFrames.length} duplicates removed)`);
|
|
21483
|
+
for (const frame of uniqueFrames) {
|
|
21484
|
+
lines.push(` [${formatTime2(frame.timestamp)}] ${basename10(frame.path)}${frame.description ? ` \u2014 ${frame.description}` : ""}`);
|
|
21485
|
+
}
|
|
21486
|
+
}
|
|
21487
|
+
try {
|
|
21488
|
+
execSync24(`rm -rf "${tmpDir}"`, { timeout: 1e4, stdio: "pipe" });
|
|
21489
|
+
} catch {
|
|
21490
|
+
}
|
|
21491
|
+
return {
|
|
21492
|
+
success: true,
|
|
21493
|
+
output: lines.join("\n"),
|
|
21494
|
+
durationMs: performance.now() - start
|
|
21495
|
+
};
|
|
21496
|
+
} catch (err) {
|
|
21497
|
+
return {
|
|
21498
|
+
success: false,
|
|
21499
|
+
output: "",
|
|
21500
|
+
error: `Video analysis failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
21501
|
+
durationMs: performance.now() - start
|
|
21502
|
+
};
|
|
21503
|
+
}
|
|
21504
|
+
}
|
|
21505
|
+
};
|
|
21506
|
+
}
|
|
21507
|
+
});
|
|
21508
|
+
|
|
21204
21509
|
// packages/execution/dist/venv-paths.js
|
|
21205
|
-
import { join as
|
|
21510
|
+
import { join as join42 } from "node:path";
|
|
21206
21511
|
function venvPython(venvDir) {
|
|
21207
|
-
return isWin ?
|
|
21512
|
+
return isWin ? join42(venvDir, "Scripts", "python.exe") : join42(venvDir, "bin", "python");
|
|
21208
21513
|
}
|
|
21209
21514
|
function venvPip(venvDir) {
|
|
21210
|
-
return isWin ?
|
|
21515
|
+
return isWin ? join42(venvDir, "Scripts", "pip.exe") : join42(venvDir, "bin", "pip");
|
|
21211
21516
|
}
|
|
21212
21517
|
function venvBinDir(venvDir) {
|
|
21213
|
-
return isWin ?
|
|
21518
|
+
return isWin ? join42(venvDir, "Scripts") : join42(venvDir, "bin");
|
|
21214
21519
|
}
|
|
21215
21520
|
function venvExe(venvDir, name) {
|
|
21216
|
-
return isWin ?
|
|
21521
|
+
return isWin ? join42(venvDir, "Scripts", `${name}.exe`) : join42(venvDir, "bin", name);
|
|
21217
21522
|
}
|
|
21218
21523
|
var isWin;
|
|
21219
21524
|
var init_venv_paths = __esm({
|
|
@@ -21224,14 +21529,14 @@ var init_venv_paths = __esm({
|
|
|
21224
21529
|
});
|
|
21225
21530
|
|
|
21226
21531
|
// packages/execution/dist/tools/fortemi-bridge.js
|
|
21227
|
-
import { existsSync as
|
|
21228
|
-
import { join as
|
|
21532
|
+
import { existsSync as existsSync28, readFileSync as readFileSync21 } from "node:fs";
|
|
21533
|
+
import { join as join43 } from "node:path";
|
|
21229
21534
|
function loadBridgeState(repoRoot) {
|
|
21230
|
-
const bridgeFile =
|
|
21231
|
-
if (!
|
|
21535
|
+
const bridgeFile = join43(repoRoot, ".oa", "fortemi-bridge.json");
|
|
21536
|
+
if (!existsSync28(bridgeFile))
|
|
21232
21537
|
return null;
|
|
21233
21538
|
try {
|
|
21234
|
-
return JSON.parse(
|
|
21539
|
+
return JSON.parse(readFileSync21(bridgeFile, "utf8"));
|
|
21235
21540
|
} catch {
|
|
21236
21541
|
return null;
|
|
21237
21542
|
}
|
|
@@ -21479,7 +21784,7 @@ var init_gitWorktree = __esm({
|
|
|
21479
21784
|
});
|
|
21480
21785
|
|
|
21481
21786
|
// packages/execution/dist/patchApplier.js
|
|
21482
|
-
import { readFileSync as
|
|
21787
|
+
import { readFileSync as readFileSync22, writeFileSync as writeFileSync10, existsSync as existsSync29, mkdirSync as mkdirSync10 } from "node:fs";
|
|
21483
21788
|
import { dirname as dirname12 } from "node:path";
|
|
21484
21789
|
import { spawn as spawn15 } from "node:child_process";
|
|
21485
21790
|
async function applyPatch(patch) {
|
|
@@ -21495,22 +21800,22 @@ async function applyPatch(patch) {
|
|
|
21495
21800
|
}
|
|
21496
21801
|
}
|
|
21497
21802
|
function applyBlockReplace(patch) {
|
|
21498
|
-
const original =
|
|
21803
|
+
const original = readFileSync22(patch.filePath, "utf-8");
|
|
21499
21804
|
if (!original.includes(patch.oldContent)) {
|
|
21500
21805
|
throw new Error(`Block not found in "${patch.filePath}": the oldContent string was not found in the file.`);
|
|
21501
21806
|
}
|
|
21502
21807
|
const updated = original.replace(patch.oldContent, patch.newContent);
|
|
21503
|
-
|
|
21808
|
+
writeFileSync10(patch.filePath, updated, "utf-8");
|
|
21504
21809
|
}
|
|
21505
21810
|
function applyRewrite(patch) {
|
|
21506
|
-
|
|
21811
|
+
writeFileSync10(patch.filePath, patch.newContent, "utf-8");
|
|
21507
21812
|
}
|
|
21508
21813
|
function applyNewFile(patch) {
|
|
21509
|
-
if (
|
|
21814
|
+
if (existsSync29(patch.filePath)) {
|
|
21510
21815
|
throw new Error(`Cannot create new file: "${patch.filePath}" already exists.`);
|
|
21511
21816
|
}
|
|
21512
|
-
|
|
21513
|
-
|
|
21817
|
+
mkdirSync10(dirname12(patch.filePath), { recursive: true });
|
|
21818
|
+
writeFileSync10(patch.filePath, patch.newContent, "utf-8");
|
|
21514
21819
|
}
|
|
21515
21820
|
async function applyUnifiedDiff(patch) {
|
|
21516
21821
|
const { filePath, diff } = patch;
|
|
@@ -22041,6 +22346,7 @@ __export(dist_exports, {
|
|
|
22041
22346
|
ToolExecutor: () => ToolExecutor,
|
|
22042
22347
|
TranscribeFileTool: () => TranscribeFileTool,
|
|
22043
22348
|
TranscribeUrlTool: () => TranscribeUrlTool,
|
|
22349
|
+
VideoUnderstandTool: () => VideoUnderstandTool,
|
|
22044
22350
|
VisionTool: () => VisionTool,
|
|
22045
22351
|
WebCrawlTool: () => WebCrawlTool,
|
|
22046
22352
|
WebFetchTool: () => WebFetchTool,
|
|
@@ -22175,6 +22481,7 @@ var init_dist2 = __esm({
|
|
|
22175
22481
|
init_process_health();
|
|
22176
22482
|
init_full_sub_agent();
|
|
22177
22483
|
init_environment_snapshot();
|
|
22484
|
+
init_video_understand();
|
|
22178
22485
|
init_venv_paths();
|
|
22179
22486
|
init_nexus();
|
|
22180
22487
|
init_fortemi_bridge();
|
|
@@ -22862,17 +23169,17 @@ var init_dist3 = __esm({
|
|
|
22862
23169
|
});
|
|
22863
23170
|
|
|
22864
23171
|
// packages/orchestrator/dist/promptLoader.js
|
|
22865
|
-
import { readFileSync as
|
|
22866
|
-
import { join as
|
|
23172
|
+
import { readFileSync as readFileSync23, existsSync as existsSync30 } from "node:fs";
|
|
23173
|
+
import { join as join44, dirname as dirname13 } from "node:path";
|
|
22867
23174
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
22868
23175
|
function loadPrompt(promptPath, vars) {
|
|
22869
23176
|
let content = cache.get(promptPath);
|
|
22870
23177
|
if (content === void 0) {
|
|
22871
|
-
const fullPath =
|
|
22872
|
-
if (!
|
|
23178
|
+
const fullPath = join44(PROMPTS_DIR, promptPath);
|
|
23179
|
+
if (!existsSync30(fullPath)) {
|
|
22873
23180
|
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
22874
23181
|
}
|
|
22875
|
-
content =
|
|
23182
|
+
content = readFileSync23(fullPath, "utf-8");
|
|
22876
23183
|
cache.set(promptPath, content);
|
|
22877
23184
|
}
|
|
22878
23185
|
if (!vars)
|
|
@@ -22885,7 +23192,7 @@ var init_promptLoader = __esm({
|
|
|
22885
23192
|
"use strict";
|
|
22886
23193
|
__filename = fileURLToPath7(import.meta.url);
|
|
22887
23194
|
__dirname4 = dirname13(__filename);
|
|
22888
|
-
PROMPTS_DIR =
|
|
23195
|
+
PROMPTS_DIR = join44(__dirname4, "..", "prompts");
|
|
22889
23196
|
cache = /* @__PURE__ */ new Map();
|
|
22890
23197
|
}
|
|
22891
23198
|
});
|
|
@@ -23265,7 +23572,7 @@ var init_code_retriever = __esm({
|
|
|
23265
23572
|
import { execFile as execFile6 } from "node:child_process";
|
|
23266
23573
|
import { promisify as promisify5 } from "node:util";
|
|
23267
23574
|
import { readFile as readFile20, readdir as readdir5, stat as stat3 } from "node:fs/promises";
|
|
23268
|
-
import { join as
|
|
23575
|
+
import { join as join45, extname as extname8 } from "node:path";
|
|
23269
23576
|
async function searchByPath(pathPattern, options) {
|
|
23270
23577
|
const allFiles = await collectFiles(options.rootDir, options.includeGlobs ?? DEFAULT_INCLUDE_GLOBS, options.excludeGlobs ?? DEFAULT_EXCLUDE_GLOBS);
|
|
23271
23578
|
const pattern = options.caseInsensitive ? pathPattern.toLowerCase() : pathPattern;
|
|
@@ -23407,7 +23714,7 @@ async function walkForFiles(rootDir, dir, excludeGlobs, results) {
|
|
|
23407
23714
|
continue;
|
|
23408
23715
|
if (excludeGlobs.some((g) => entry.name === g || matchesGlob(entry.name, g)))
|
|
23409
23716
|
continue;
|
|
23410
|
-
const absPath =
|
|
23717
|
+
const absPath = join45(dir, entry.name);
|
|
23411
23718
|
if (entry.isDirectory()) {
|
|
23412
23719
|
await walkForFiles(rootDir, absPath, excludeGlobs, results);
|
|
23413
23720
|
} else if (entry.isFile()) {
|
|
@@ -23714,7 +24021,7 @@ var init_graphExpand = __esm({
|
|
|
23714
24021
|
|
|
23715
24022
|
// packages/retrieval/dist/snippetPacker.js
|
|
23716
24023
|
import { readFile as readFile21 } from "node:fs/promises";
|
|
23717
|
-
import { join as
|
|
24024
|
+
import { join as join46 } from "node:path";
|
|
23718
24025
|
async function packSnippets(requests, opts = {}) {
|
|
23719
24026
|
const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
23720
24027
|
const contextLines = opts.contextLines ?? DEFAULT_CONTEXT_LINES;
|
|
@@ -23740,7 +24047,7 @@ async function packSnippets(requests, opts = {}) {
|
|
|
23740
24047
|
return { packed, dropped, totalTokens };
|
|
23741
24048
|
}
|
|
23742
24049
|
async function extractSnippet(req, repoRoot, contextLines = DEFAULT_CONTEXT_LINES) {
|
|
23743
|
-
const absPath = req.filePath.startsWith("/") ? req.filePath :
|
|
24050
|
+
const absPath = req.filePath.startsWith("/") ? req.filePath : join46(repoRoot, req.filePath);
|
|
23744
24051
|
let content;
|
|
23745
24052
|
try {
|
|
23746
24053
|
content = await readFile21(absPath, "utf-8");
|
|
@@ -26473,10 +26780,10 @@ ${marker}` : marker);
|
|
|
26473
26780
|
if (!this._workingDirectory)
|
|
26474
26781
|
return;
|
|
26475
26782
|
try {
|
|
26476
|
-
const { mkdirSync:
|
|
26477
|
-
const { join:
|
|
26478
|
-
const sessionDir =
|
|
26479
|
-
|
|
26783
|
+
const { mkdirSync: mkdirSync25, writeFileSync: writeFileSync24 } = __require("node:fs");
|
|
26784
|
+
const { join: join71 } = __require("node:path");
|
|
26785
|
+
const sessionDir = join71(this._workingDirectory, ".oa", "session", this._sessionId);
|
|
26786
|
+
mkdirSync25(sessionDir, { recursive: true });
|
|
26480
26787
|
const checkpoint = {
|
|
26481
26788
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26482
26789
|
sessionId: this._sessionId,
|
|
@@ -26488,7 +26795,7 @@ ${marker}` : marker);
|
|
|
26488
26795
|
memexEntryCount: this._memexArchive.size,
|
|
26489
26796
|
fileRegistrySize: this._fileRegistry.size
|
|
26490
26797
|
};
|
|
26491
|
-
|
|
26798
|
+
writeFileSync24(join71(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
|
|
26492
26799
|
} catch {
|
|
26493
26800
|
}
|
|
26494
26801
|
}
|
|
@@ -27819,9 +28126,9 @@ ${transcript}`
|
|
|
27819
28126
|
});
|
|
27820
28127
|
|
|
27821
28128
|
// packages/orchestrator/dist/nexusBackend.js
|
|
27822
|
-
import { existsSync as
|
|
28129
|
+
import { existsSync as existsSync31, statSync as statSync10, openSync, readSync, closeSync, unlinkSync as unlinkSync5, writeFileSync as writeFileSync11 } from "node:fs";
|
|
27823
28130
|
import { watch as fsWatch } from "node:fs";
|
|
27824
|
-
import { join as
|
|
28131
|
+
import { join as join47 } from "node:path";
|
|
27825
28132
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
27826
28133
|
import { randomBytes as randomBytes11 } from "node:crypto";
|
|
27827
28134
|
var NexusAgenticBackend;
|
|
@@ -27971,8 +28278,8 @@ var init_nexusBackend = __esm({
|
|
|
27971
28278
|
* Falls back to unary + word-split if streaming setup fails.
|
|
27972
28279
|
*/
|
|
27973
28280
|
async *chatCompletionStream(request) {
|
|
27974
|
-
const streamFile =
|
|
27975
|
-
|
|
28281
|
+
const streamFile = join47(tmpdir7(), `nexus-stream-${randomBytes11(6).toString("hex")}.jsonl`);
|
|
28282
|
+
writeFileSync11(streamFile, "", "utf8");
|
|
27976
28283
|
const daemonArgs = {
|
|
27977
28284
|
model: this.model,
|
|
27978
28285
|
messages: JSON.stringify(request.messages),
|
|
@@ -27992,7 +28299,7 @@ var init_nexusBackend = __esm({
|
|
|
27992
28299
|
} catch (sendErr) {
|
|
27993
28300
|
this.consecutiveFailures++;
|
|
27994
28301
|
try {
|
|
27995
|
-
|
|
28302
|
+
unlinkSync5(streamFile);
|
|
27996
28303
|
} catch {
|
|
27997
28304
|
}
|
|
27998
28305
|
throw sendErr;
|
|
@@ -28007,7 +28314,7 @@ var init_nexusBackend = __esm({
|
|
|
28007
28314
|
}
|
|
28008
28315
|
if (!isStreaming) {
|
|
28009
28316
|
try {
|
|
28010
|
-
|
|
28317
|
+
unlinkSync5(streamFile);
|
|
28011
28318
|
} catch {
|
|
28012
28319
|
}
|
|
28013
28320
|
let parsed;
|
|
@@ -28163,7 +28470,7 @@ var init_nexusBackend = __esm({
|
|
|
28163
28470
|
}
|
|
28164
28471
|
} finally {
|
|
28165
28472
|
try {
|
|
28166
|
-
|
|
28473
|
+
unlinkSync5(streamFile);
|
|
28167
28474
|
} catch {
|
|
28168
28475
|
}
|
|
28169
28476
|
}
|
|
@@ -29006,9 +29313,9 @@ __export(listen_exports, {
|
|
|
29006
29313
|
isVideoPath: () => isVideoPath,
|
|
29007
29314
|
waitForTranscribeCli: () => waitForTranscribeCli
|
|
29008
29315
|
});
|
|
29009
|
-
import { spawn as spawn16, execSync as
|
|
29010
|
-
import { existsSync as
|
|
29011
|
-
import { join as
|
|
29316
|
+
import { spawn as spawn16, execSync as execSync25 } from "node:child_process";
|
|
29317
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync11, writeFileSync as writeFileSync12, readdirSync as readdirSync8 } from "node:fs";
|
|
29318
|
+
import { join as join48, dirname as dirname14 } from "node:path";
|
|
29012
29319
|
import { homedir as homedir10 } from "node:os";
|
|
29013
29320
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
29014
29321
|
import { EventEmitter } from "node:events";
|
|
@@ -29028,7 +29335,7 @@ function findMicCaptureCommand() {
|
|
|
29028
29335
|
const platform6 = process.platform;
|
|
29029
29336
|
if (platform6 === "linux") {
|
|
29030
29337
|
try {
|
|
29031
|
-
|
|
29338
|
+
execSync25("which arecord", { stdio: "pipe" });
|
|
29032
29339
|
return {
|
|
29033
29340
|
cmd: "arecord",
|
|
29034
29341
|
args: ["-f", "S16_LE", "-r", "16000", "-c", "1", "-t", "raw", "-q", "-"]
|
|
@@ -29038,7 +29345,7 @@ function findMicCaptureCommand() {
|
|
|
29038
29345
|
}
|
|
29039
29346
|
if (platform6 === "darwin") {
|
|
29040
29347
|
try {
|
|
29041
|
-
|
|
29348
|
+
execSync25("which sox", { stdio: "pipe" });
|
|
29042
29349
|
return {
|
|
29043
29350
|
cmd: "sox",
|
|
29044
29351
|
args: ["-d", "-t", "raw", "-r", "16000", "-c", "1", "-b", "16", "-e", "signed-integer", "-"]
|
|
@@ -29047,7 +29354,7 @@ function findMicCaptureCommand() {
|
|
|
29047
29354
|
}
|
|
29048
29355
|
}
|
|
29049
29356
|
try {
|
|
29050
|
-
|
|
29357
|
+
execSync25("which ffmpeg", { stdio: "pipe" });
|
|
29051
29358
|
if (platform6 === "linux") {
|
|
29052
29359
|
return {
|
|
29053
29360
|
cmd: "ffmpeg",
|
|
@@ -29094,39 +29401,39 @@ function findMicCaptureCommand() {
|
|
|
29094
29401
|
function findLiveWhisperScript() {
|
|
29095
29402
|
const thisDir = dirname14(fileURLToPath8(import.meta.url));
|
|
29096
29403
|
const candidates = [
|
|
29097
|
-
|
|
29098
|
-
|
|
29099
|
-
|
|
29404
|
+
join48(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
|
|
29405
|
+
join48(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
|
|
29406
|
+
join48(thisDir, "../../execution/scripts/live-whisper.py"),
|
|
29100
29407
|
// npm install layout — scripts bundled alongside dist
|
|
29101
|
-
|
|
29102
|
-
|
|
29408
|
+
join48(thisDir, "../scripts/live-whisper.py"),
|
|
29409
|
+
join48(thisDir, "../../scripts/live-whisper.py")
|
|
29103
29410
|
];
|
|
29104
29411
|
for (const p of candidates) {
|
|
29105
|
-
if (
|
|
29412
|
+
if (existsSync32(p))
|
|
29106
29413
|
return p;
|
|
29107
29414
|
}
|
|
29108
29415
|
try {
|
|
29109
|
-
const globalRoot =
|
|
29416
|
+
const globalRoot = execSync25("npm root -g", {
|
|
29110
29417
|
encoding: "utf-8",
|
|
29111
29418
|
timeout: 5e3,
|
|
29112
29419
|
stdio: ["pipe", "pipe", "pipe"]
|
|
29113
29420
|
}).trim();
|
|
29114
29421
|
const candidates2 = [
|
|
29115
|
-
|
|
29116
|
-
|
|
29422
|
+
join48(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
|
|
29423
|
+
join48(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
|
|
29117
29424
|
];
|
|
29118
29425
|
for (const p of candidates2) {
|
|
29119
|
-
if (
|
|
29426
|
+
if (existsSync32(p))
|
|
29120
29427
|
return p;
|
|
29121
29428
|
}
|
|
29122
29429
|
} catch {
|
|
29123
29430
|
}
|
|
29124
|
-
const nvmBase =
|
|
29125
|
-
if (
|
|
29431
|
+
const nvmBase = join48(homedir10(), ".nvm", "versions", "node");
|
|
29432
|
+
if (existsSync32(nvmBase)) {
|
|
29126
29433
|
try {
|
|
29127
|
-
for (const ver of
|
|
29128
|
-
const p =
|
|
29129
|
-
if (
|
|
29434
|
+
for (const ver of readdirSync8(nvmBase)) {
|
|
29435
|
+
const p = join48(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
|
|
29436
|
+
if (existsSync32(p))
|
|
29130
29437
|
return p;
|
|
29131
29438
|
}
|
|
29132
29439
|
} catch {
|
|
@@ -29139,12 +29446,12 @@ function ensureTranscribeCliBackground() {
|
|
|
29139
29446
|
return;
|
|
29140
29447
|
_bgInstallPromise = (async () => {
|
|
29141
29448
|
try {
|
|
29142
|
-
const globalRoot =
|
|
29449
|
+
const globalRoot = execSync25("npm root -g", {
|
|
29143
29450
|
encoding: "utf-8",
|
|
29144
29451
|
timeout: 5e3,
|
|
29145
29452
|
stdio: ["pipe", "pipe", "pipe"]
|
|
29146
29453
|
}).trim();
|
|
29147
|
-
if (
|
|
29454
|
+
if (existsSync32(join48(globalRoot, "transcribe-cli", "dist", "index.js"))) {
|
|
29148
29455
|
return true;
|
|
29149
29456
|
}
|
|
29150
29457
|
} catch {
|
|
@@ -29345,7 +29652,7 @@ var init_listen = __esm({
|
|
|
29345
29652
|
}
|
|
29346
29653
|
if (!this.transcribeCliAvailable) {
|
|
29347
29654
|
try {
|
|
29348
|
-
|
|
29655
|
+
execSync25("which transcribe-cli", { stdio: "pipe" });
|
|
29349
29656
|
this.transcribeCliAvailable = true;
|
|
29350
29657
|
} catch {
|
|
29351
29658
|
this.transcribeCliAvailable = false;
|
|
@@ -29362,29 +29669,29 @@ var init_listen = __esm({
|
|
|
29362
29669
|
} catch {
|
|
29363
29670
|
}
|
|
29364
29671
|
try {
|
|
29365
|
-
const globalRoot =
|
|
29672
|
+
const globalRoot = execSync25("npm root -g", {
|
|
29366
29673
|
encoding: "utf-8",
|
|
29367
29674
|
timeout: 5e3,
|
|
29368
29675
|
stdio: ["pipe", "pipe", "pipe"]
|
|
29369
29676
|
}).trim();
|
|
29370
|
-
const tcPath =
|
|
29371
|
-
if (
|
|
29677
|
+
const tcPath = join48(globalRoot, "transcribe-cli");
|
|
29678
|
+
if (existsSync32(join48(tcPath, "dist", "index.js"))) {
|
|
29372
29679
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
29373
29680
|
const req = createRequire4(import.meta.url);
|
|
29374
|
-
return req(
|
|
29681
|
+
return req(join48(tcPath, "dist", "index.js"));
|
|
29375
29682
|
}
|
|
29376
29683
|
} catch {
|
|
29377
29684
|
}
|
|
29378
|
-
const nvmBase =
|
|
29379
|
-
if (
|
|
29685
|
+
const nvmBase = join48(homedir10(), ".nvm", "versions", "node");
|
|
29686
|
+
if (existsSync32(nvmBase)) {
|
|
29380
29687
|
try {
|
|
29381
|
-
const { readdirSync:
|
|
29382
|
-
for (const ver of
|
|
29383
|
-
const tcPath =
|
|
29384
|
-
if (
|
|
29688
|
+
const { readdirSync: readdirSync20 } = await import("node:fs");
|
|
29689
|
+
for (const ver of readdirSync20(nvmBase)) {
|
|
29690
|
+
const tcPath = join48(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
|
|
29691
|
+
if (existsSync32(join48(tcPath, "dist", "index.js"))) {
|
|
29385
29692
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
29386
29693
|
const req = createRequire4(import.meta.url);
|
|
29387
|
-
return req(
|
|
29694
|
+
return req(join48(tcPath, "dist", "index.js"));
|
|
29388
29695
|
}
|
|
29389
29696
|
}
|
|
29390
29697
|
} catch {
|
|
@@ -29412,7 +29719,7 @@ var init_listen = __esm({
|
|
|
29412
29719
|
}
|
|
29413
29720
|
if (!tc) {
|
|
29414
29721
|
try {
|
|
29415
|
-
|
|
29722
|
+
execSync25("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
|
|
29416
29723
|
this.transcribeCliAvailable = null;
|
|
29417
29724
|
tc = await this.loadTranscribeCli();
|
|
29418
29725
|
} catch {
|
|
@@ -29595,7 +29902,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
29595
29902
|
}
|
|
29596
29903
|
if (!tc) {
|
|
29597
29904
|
try {
|
|
29598
|
-
|
|
29905
|
+
execSync25("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
|
|
29599
29906
|
this.transcribeCliAvailable = null;
|
|
29600
29907
|
tc = await this.loadTranscribeCli();
|
|
29601
29908
|
} catch {
|
|
@@ -29649,7 +29956,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
29649
29956
|
}
|
|
29650
29957
|
if (!tc) {
|
|
29651
29958
|
try {
|
|
29652
|
-
|
|
29959
|
+
execSync25("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
|
|
29653
29960
|
this.transcribeCliAvailable = null;
|
|
29654
29961
|
tc = await this.loadTranscribeCli();
|
|
29655
29962
|
} catch {
|
|
@@ -29665,11 +29972,11 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
29665
29972
|
wordTimestamps: false
|
|
29666
29973
|
});
|
|
29667
29974
|
if (outputDir) {
|
|
29668
|
-
const { basename:
|
|
29669
|
-
const transcriptDir =
|
|
29670
|
-
|
|
29671
|
-
const outFile =
|
|
29672
|
-
|
|
29975
|
+
const { basename: basename18 } = await import("node:path");
|
|
29976
|
+
const transcriptDir = join48(outputDir, ".oa", "transcripts");
|
|
29977
|
+
mkdirSync11(transcriptDir, { recursive: true });
|
|
29978
|
+
const outFile = join48(transcriptDir, `${basename18(filePath)}.txt`);
|
|
29979
|
+
writeFileSync12(outFile, result.text, "utf-8");
|
|
29673
29980
|
}
|
|
29674
29981
|
return {
|
|
29675
29982
|
text: result.text,
|
|
@@ -31917,7 +32224,7 @@ var require_websocket = __commonJS({
|
|
|
31917
32224
|
var http = __require("http");
|
|
31918
32225
|
var net = __require("net");
|
|
31919
32226
|
var tls = __require("tls");
|
|
31920
|
-
var { randomBytes: randomBytes15, createHash:
|
|
32227
|
+
var { randomBytes: randomBytes15, createHash: createHash6 } = __require("crypto");
|
|
31921
32228
|
var { Duplex, Readable } = __require("stream");
|
|
31922
32229
|
var { URL: URL3 } = __require("url");
|
|
31923
32230
|
var PerMessageDeflate = require_permessage_deflate();
|
|
@@ -32577,7 +32884,7 @@ var require_websocket = __commonJS({
|
|
|
32577
32884
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
32578
32885
|
return;
|
|
32579
32886
|
}
|
|
32580
|
-
const digest =
|
|
32887
|
+
const digest = createHash6("sha1").update(key + GUID).digest("base64");
|
|
32581
32888
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
32582
32889
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
32583
32890
|
return;
|
|
@@ -32944,7 +33251,7 @@ var require_websocket_server = __commonJS({
|
|
|
32944
33251
|
var EventEmitter7 = __require("events");
|
|
32945
33252
|
var http = __require("http");
|
|
32946
33253
|
var { Duplex } = __require("stream");
|
|
32947
|
-
var { createHash:
|
|
33254
|
+
var { createHash: createHash6 } = __require("crypto");
|
|
32948
33255
|
var extension = require_extension();
|
|
32949
33256
|
var PerMessageDeflate = require_permessage_deflate();
|
|
32950
33257
|
var subprotocol = require_subprotocol();
|
|
@@ -33245,7 +33552,7 @@ var require_websocket_server = __commonJS({
|
|
|
33245
33552
|
);
|
|
33246
33553
|
}
|
|
33247
33554
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
33248
|
-
const digest =
|
|
33555
|
+
const digest = createHash6("sha1").update(key + GUID).digest("base64");
|
|
33249
33556
|
const headers = [
|
|
33250
33557
|
"HTTP/1.1 101 Switching Protocols",
|
|
33251
33558
|
"Upgrade: websocket",
|
|
@@ -34156,7 +34463,7 @@ var init_render = __esm({
|
|
|
34156
34463
|
|
|
34157
34464
|
// packages/cli/dist/tui/voice-session.js
|
|
34158
34465
|
import { createServer as createServer2 } from "node:http";
|
|
34159
|
-
import { spawn as spawn17, execSync as
|
|
34466
|
+
import { spawn as spawn17, execSync as execSync26 } from "node:child_process";
|
|
34160
34467
|
import { EventEmitter as EventEmitter2 } from "node:events";
|
|
34161
34468
|
function generateFrontendHTML() {
|
|
34162
34469
|
return `<!DOCTYPE html>
|
|
@@ -34889,8 +35196,8 @@ import { EventEmitter as EventEmitter3 } from "node:events";
|
|
|
34889
35196
|
import { randomBytes as randomBytes12 } from "node:crypto";
|
|
34890
35197
|
import { URL as URL2 } from "node:url";
|
|
34891
35198
|
import { loadavg, cpus as cpus2, totalmem as totalmem2, freemem as freemem2 } from "node:os";
|
|
34892
|
-
import { existsSync as
|
|
34893
|
-
import { join as
|
|
35199
|
+
import { existsSync as existsSync33, readFileSync as readFileSync24, writeFileSync as writeFileSync13, unlinkSync as unlinkSync6, mkdirSync as mkdirSync12, readdirSync as readdirSync9, statSync as statSync11 } from "node:fs";
|
|
35200
|
+
import { join as join49 } from "node:path";
|
|
34894
35201
|
function cleanForwardHeaders(raw, targetHost) {
|
|
34895
35202
|
const out = {};
|
|
34896
35203
|
for (const [key, value] of Object.entries(raw)) {
|
|
@@ -34918,10 +35225,10 @@ function fmtTokens(n) {
|
|
|
34918
35225
|
}
|
|
34919
35226
|
function readExposeState(stateDir) {
|
|
34920
35227
|
try {
|
|
34921
|
-
const path =
|
|
34922
|
-
if (!
|
|
35228
|
+
const path = join49(stateDir, STATE_FILE_NAME);
|
|
35229
|
+
if (!existsSync33(path))
|
|
34923
35230
|
return null;
|
|
34924
|
-
const raw =
|
|
35231
|
+
const raw = readFileSync24(path, "utf8");
|
|
34925
35232
|
const data = JSON.parse(raw);
|
|
34926
35233
|
if (!data.pid || !data.tunnelUrl || !data.authKey || !data.proxyPort)
|
|
34927
35234
|
return null;
|
|
@@ -34932,14 +35239,14 @@ function readExposeState(stateDir) {
|
|
|
34932
35239
|
}
|
|
34933
35240
|
function writeExposeState(stateDir, state) {
|
|
34934
35241
|
try {
|
|
34935
|
-
|
|
34936
|
-
|
|
35242
|
+
mkdirSync12(stateDir, { recursive: true });
|
|
35243
|
+
writeFileSync13(join49(stateDir, STATE_FILE_NAME), JSON.stringify(state, null, 2));
|
|
34937
35244
|
} catch {
|
|
34938
35245
|
}
|
|
34939
35246
|
}
|
|
34940
35247
|
function removeExposeState(stateDir) {
|
|
34941
35248
|
try {
|
|
34942
|
-
|
|
35249
|
+
unlinkSync6(join49(stateDir, STATE_FILE_NAME));
|
|
34943
35250
|
} catch {
|
|
34944
35251
|
}
|
|
34945
35252
|
}
|
|
@@ -35028,10 +35335,10 @@ async function collectSystemMetricsAsync() {
|
|
|
35028
35335
|
}
|
|
35029
35336
|
function readP2PExposeState(stateDir) {
|
|
35030
35337
|
try {
|
|
35031
|
-
const path =
|
|
35032
|
-
if (!
|
|
35338
|
+
const path = join49(stateDir, P2P_STATE_FILE_NAME);
|
|
35339
|
+
if (!existsSync33(path))
|
|
35033
35340
|
return null;
|
|
35034
|
-
const raw =
|
|
35341
|
+
const raw = readFileSync24(path, "utf8");
|
|
35035
35342
|
const data = JSON.parse(raw);
|
|
35036
35343
|
if (!data.peerId || !data.authKey)
|
|
35037
35344
|
return null;
|
|
@@ -35042,14 +35349,14 @@ function readP2PExposeState(stateDir) {
|
|
|
35042
35349
|
}
|
|
35043
35350
|
function writeP2PExposeState(stateDir, state) {
|
|
35044
35351
|
try {
|
|
35045
|
-
|
|
35046
|
-
|
|
35352
|
+
mkdirSync12(stateDir, { recursive: true });
|
|
35353
|
+
writeFileSync13(join49(stateDir, P2P_STATE_FILE_NAME), JSON.stringify(state, null, 2));
|
|
35047
35354
|
} catch {
|
|
35048
35355
|
}
|
|
35049
35356
|
}
|
|
35050
35357
|
function removeP2PExposeState(stateDir) {
|
|
35051
35358
|
try {
|
|
35052
|
-
|
|
35359
|
+
unlinkSync6(join49(stateDir, P2P_STATE_FILE_NAME));
|
|
35053
35360
|
} catch {
|
|
35054
35361
|
}
|
|
35055
35362
|
}
|
|
@@ -35897,10 +36204,10 @@ ${this.formatConnectionInfo()}`);
|
|
|
35897
36204
|
throw new Error(`Expose failed: ${exposeResult.error}`);
|
|
35898
36205
|
}
|
|
35899
36206
|
const nexusDir = this._nexusTool.getNexusDir();
|
|
35900
|
-
const statusPath =
|
|
36207
|
+
const statusPath = join49(nexusDir, "status.json");
|
|
35901
36208
|
for (let i = 0; i < 80; i++) {
|
|
35902
36209
|
try {
|
|
35903
|
-
const raw =
|
|
36210
|
+
const raw = readFileSync24(statusPath, "utf8");
|
|
35904
36211
|
if (raw.length > 10) {
|
|
35905
36212
|
const status = JSON.parse(raw);
|
|
35906
36213
|
if (status.connected && status.peerId) {
|
|
@@ -35931,9 +36238,9 @@ ${this.formatConnectionInfo()}`);
|
|
|
35931
36238
|
});
|
|
35932
36239
|
}
|
|
35933
36240
|
try {
|
|
35934
|
-
const invocDir =
|
|
35935
|
-
if (
|
|
35936
|
-
this._prevInvocCount =
|
|
36241
|
+
const invocDir = join49(nexusDir, "invocations");
|
|
36242
|
+
if (existsSync33(invocDir)) {
|
|
36243
|
+
this._prevInvocCount = readdirSync9(invocDir).filter((f) => f.endsWith(".json")).length;
|
|
35937
36244
|
this._stats.totalRequests = this._prevInvocCount;
|
|
35938
36245
|
}
|
|
35939
36246
|
} catch {
|
|
@@ -35961,13 +36268,13 @@ ${this.formatConnectionInfo()}`);
|
|
|
35961
36268
|
if (!state)
|
|
35962
36269
|
return null;
|
|
35963
36270
|
const nexusDir = nexusTool.getNexusDir();
|
|
35964
|
-
const statusPath =
|
|
36271
|
+
const statusPath = join49(nexusDir, "status.json");
|
|
35965
36272
|
try {
|
|
35966
|
-
if (!
|
|
36273
|
+
if (!existsSync33(statusPath)) {
|
|
35967
36274
|
removeP2PExposeState(stateDir);
|
|
35968
36275
|
return null;
|
|
35969
36276
|
}
|
|
35970
|
-
const status = JSON.parse(
|
|
36277
|
+
const status = JSON.parse(readFileSync24(statusPath, "utf8"));
|
|
35971
36278
|
if (!status.connected || !status.peerId) {
|
|
35972
36279
|
removeP2PExposeState(stateDir);
|
|
35973
36280
|
return null;
|
|
@@ -36020,10 +36327,10 @@ ${this.formatConnectionInfo()}`);
|
|
|
36020
36327
|
let lastMeteringLineCount = 0;
|
|
36021
36328
|
this._activityPollTimer = setInterval(() => {
|
|
36022
36329
|
try {
|
|
36023
|
-
const invocDir =
|
|
36024
|
-
if (!
|
|
36330
|
+
const invocDir = join49(nexusDir, "invocations");
|
|
36331
|
+
if (!existsSync33(invocDir))
|
|
36025
36332
|
return;
|
|
36026
|
-
const files =
|
|
36333
|
+
const files = readdirSync9(invocDir).filter((f) => f.endsWith(".json"));
|
|
36027
36334
|
const invocCount = files.length;
|
|
36028
36335
|
const newRequests = invocCount - this._prevInvocCount;
|
|
36029
36336
|
if (newRequests > 0) {
|
|
@@ -36036,17 +36343,17 @@ ${this.formatConnectionInfo()}`);
|
|
|
36036
36343
|
let recentActive = 0;
|
|
36037
36344
|
for (const f of files.slice(-10)) {
|
|
36038
36345
|
try {
|
|
36039
|
-
const st = statSync11(
|
|
36346
|
+
const st = statSync11(join49(invocDir, f));
|
|
36040
36347
|
if (now - st.mtimeMs < 1e4)
|
|
36041
36348
|
recentActive++;
|
|
36042
36349
|
} catch {
|
|
36043
36350
|
}
|
|
36044
36351
|
}
|
|
36045
|
-
const meteringFile =
|
|
36352
|
+
const meteringFile = join49(nexusDir, "metering.jsonl");
|
|
36046
36353
|
let meteringLines = lastMeteringLineCount;
|
|
36047
36354
|
try {
|
|
36048
|
-
if (
|
|
36049
|
-
const content =
|
|
36355
|
+
if (existsSync33(meteringFile)) {
|
|
36356
|
+
const content = readFileSync24(meteringFile, "utf8");
|
|
36050
36357
|
meteringLines = content.split("\n").filter((l) => l.trim()).length;
|
|
36051
36358
|
}
|
|
36052
36359
|
} catch {
|
|
@@ -36072,9 +36379,9 @@ ${this.formatConnectionInfo()}`);
|
|
|
36072
36379
|
this._activityPollTimer.unref();
|
|
36073
36380
|
this._pollTimer = setInterval(() => {
|
|
36074
36381
|
try {
|
|
36075
|
-
const statusPath =
|
|
36076
|
-
if (
|
|
36077
|
-
const status = JSON.parse(
|
|
36382
|
+
const statusPath = join49(nexusDir, "status.json");
|
|
36383
|
+
if (existsSync33(statusPath)) {
|
|
36384
|
+
const status = JSON.parse(readFileSync24(statusPath, "utf8"));
|
|
36078
36385
|
if (status.peerId && !this._peerId) {
|
|
36079
36386
|
this._peerId = status.peerId;
|
|
36080
36387
|
}
|
|
@@ -36083,9 +36390,9 @@ ${this.formatConnectionInfo()}`);
|
|
|
36083
36390
|
} catch {
|
|
36084
36391
|
}
|
|
36085
36392
|
try {
|
|
36086
|
-
const invocDir =
|
|
36087
|
-
if (
|
|
36088
|
-
const files =
|
|
36393
|
+
const invocDir = join49(nexusDir, "invocations");
|
|
36394
|
+
if (existsSync33(invocDir)) {
|
|
36395
|
+
const files = readdirSync9(invocDir);
|
|
36089
36396
|
const invocCount = files.filter((f) => f.endsWith(".json")).length;
|
|
36090
36397
|
if (invocCount > this._stats.totalRequests) {
|
|
36091
36398
|
this._stats.totalRequests = invocCount;
|
|
@@ -36095,9 +36402,9 @@ ${this.formatConnectionInfo()}`);
|
|
|
36095
36402
|
} catch {
|
|
36096
36403
|
}
|
|
36097
36404
|
try {
|
|
36098
|
-
const meteringFile =
|
|
36099
|
-
if (
|
|
36100
|
-
const content =
|
|
36405
|
+
const meteringFile = join49(nexusDir, "metering.jsonl");
|
|
36406
|
+
if (existsSync33(meteringFile)) {
|
|
36407
|
+
const content = readFileSync24(meteringFile, "utf8");
|
|
36101
36408
|
if (content.length > lastMeteringSize) {
|
|
36102
36409
|
const newContent = content.slice(lastMeteringSize);
|
|
36103
36410
|
lastMeteringSize = content.length;
|
|
@@ -36305,9 +36612,9 @@ var init_types = __esm({
|
|
|
36305
36612
|
});
|
|
36306
36613
|
|
|
36307
36614
|
// packages/cli/dist/tui/p2p/secret-vault.js
|
|
36308
|
-
import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes13, scryptSync as scryptSync2, createHash as
|
|
36309
|
-
import { readFileSync as
|
|
36310
|
-
import { join as
|
|
36615
|
+
import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes13, scryptSync as scryptSync2, createHash as createHash3 } from "node:crypto";
|
|
36616
|
+
import { readFileSync as readFileSync25, writeFileSync as writeFileSync14, existsSync as existsSync34, mkdirSync as mkdirSync13 } from "node:fs";
|
|
36617
|
+
import { join as join50, dirname as dirname15 } from "node:path";
|
|
36311
36618
|
var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
|
|
36312
36619
|
var init_secret_vault = __esm({
|
|
36313
36620
|
"packages/cli/dist/tui/p2p/secret-vault.js"() {
|
|
@@ -36519,18 +36826,18 @@ var init_secret_vault = __esm({
|
|
|
36519
36826
|
const tag = cipher.getAuthTag();
|
|
36520
36827
|
const blob = Buffer.concat([salt, iv, tag, encrypted]);
|
|
36521
36828
|
const dir = dirname15(this.storePath);
|
|
36522
|
-
if (!
|
|
36523
|
-
|
|
36524
|
-
|
|
36829
|
+
if (!existsSync34(dir))
|
|
36830
|
+
mkdirSync13(dir, { recursive: true });
|
|
36831
|
+
writeFileSync14(this.storePath, blob, { mode: 384 });
|
|
36525
36832
|
}
|
|
36526
36833
|
/**
|
|
36527
36834
|
* Load vault from disk, decrypting with the given passphrase.
|
|
36528
36835
|
* Returns the number of secrets loaded.
|
|
36529
36836
|
*/
|
|
36530
36837
|
load(passphrase) {
|
|
36531
|
-
if (!this.storePath || !
|
|
36838
|
+
if (!this.storePath || !existsSync34(this.storePath))
|
|
36532
36839
|
return 0;
|
|
36533
|
-
const blob =
|
|
36840
|
+
const blob = readFileSync25(this.storePath);
|
|
36534
36841
|
if (blob.length < SALT_LEN + IV_LEN + 16) {
|
|
36535
36842
|
throw new Error("Vault file is corrupted (too small)");
|
|
36536
36843
|
}
|
|
@@ -36556,7 +36863,7 @@ var init_secret_vault = __esm({
|
|
|
36556
36863
|
/** Generate a deterministic fingerprint of vault contents (for sync verification) */
|
|
36557
36864
|
fingerprint() {
|
|
36558
36865
|
const names = Array.from(this.secrets.keys()).sort();
|
|
36559
|
-
const hash =
|
|
36866
|
+
const hash = createHash3("sha256");
|
|
36560
36867
|
for (const name of names) {
|
|
36561
36868
|
hash.update(name + ":");
|
|
36562
36869
|
hash.update(this.secrets.get(name).value);
|
|
@@ -36571,7 +36878,7 @@ var init_secret_vault = __esm({
|
|
|
36571
36878
|
// packages/cli/dist/tui/p2p/peer-mesh.js
|
|
36572
36879
|
import { EventEmitter as EventEmitter4 } from "node:events";
|
|
36573
36880
|
import { createServer as createServer4 } from "node:http";
|
|
36574
|
-
import { randomBytes as randomBytes14, createHash as
|
|
36881
|
+
import { randomBytes as randomBytes14, createHash as createHash4, generateKeyPairSync } from "node:crypto";
|
|
36575
36882
|
var PING_INTERVAL_MS, PEER_TIMEOUT_MS, GOSSIP_INTERVAL_MS, MAX_PEERS, PeerMesh;
|
|
36576
36883
|
var init_peer_mesh = __esm({
|
|
36577
36884
|
"packages/cli/dist/tui/p2p/peer-mesh.js"() {
|
|
@@ -36620,7 +36927,7 @@ var init_peer_mesh = __esm({
|
|
|
36620
36927
|
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
36621
36928
|
this.publicKey = publicKey.export({ type: "spki", format: "der" });
|
|
36622
36929
|
this.privateKey = privateKey.export({ type: "pkcs8", format: "der" });
|
|
36623
|
-
this.peerId =
|
|
36930
|
+
this.peerId = createHash4("sha256").update(this.publicKey).digest("base64url").slice(0, 22);
|
|
36624
36931
|
this.capabilities = options.capabilities;
|
|
36625
36932
|
this.displayName = options.displayName;
|
|
36626
36933
|
this._authKey = options.authKey ?? randomBytes14(24).toString("base64url");
|
|
@@ -37651,26 +37958,26 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
|
|
|
37651
37958
|
async function fetchPeerModels(peerId, authKey) {
|
|
37652
37959
|
try {
|
|
37653
37960
|
const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
|
|
37654
|
-
const { existsSync:
|
|
37655
|
-
const { join:
|
|
37961
|
+
const { existsSync: existsSync51, readFileSync: readFileSync39 } = await import("node:fs");
|
|
37962
|
+
const { join: join71 } = await import("node:path");
|
|
37656
37963
|
const cwd4 = process.cwd();
|
|
37657
37964
|
const nexusTool = new NexusTool2(cwd4);
|
|
37658
37965
|
const nexusDir = nexusTool.getNexusDir();
|
|
37659
37966
|
let isLocalPeer = false;
|
|
37660
37967
|
try {
|
|
37661
|
-
const statusPath =
|
|
37662
|
-
if (
|
|
37663
|
-
const status = JSON.parse(
|
|
37968
|
+
const statusPath = join71(nexusDir, "status.json");
|
|
37969
|
+
if (existsSync51(statusPath)) {
|
|
37970
|
+
const status = JSON.parse(readFileSync39(statusPath, "utf8"));
|
|
37664
37971
|
if (status.peerId === peerId)
|
|
37665
37972
|
isLocalPeer = true;
|
|
37666
37973
|
}
|
|
37667
37974
|
} catch {
|
|
37668
37975
|
}
|
|
37669
37976
|
if (isLocalPeer) {
|
|
37670
|
-
const pricingPath =
|
|
37671
|
-
if (
|
|
37977
|
+
const pricingPath = join71(nexusDir, "pricing.json");
|
|
37978
|
+
if (existsSync51(pricingPath)) {
|
|
37672
37979
|
try {
|
|
37673
|
-
const pricing = JSON.parse(
|
|
37980
|
+
const pricing = JSON.parse(readFileSync39(pricingPath, "utf8"));
|
|
37674
37981
|
const localModels = (pricing.models || []).map((m) => ({
|
|
37675
37982
|
name: m.model || "unknown",
|
|
37676
37983
|
size: m.parameterSize || "",
|
|
@@ -37684,10 +37991,10 @@ async function fetchPeerModels(peerId, authKey) {
|
|
|
37684
37991
|
}
|
|
37685
37992
|
}
|
|
37686
37993
|
}
|
|
37687
|
-
const cachePath =
|
|
37688
|
-
if (
|
|
37994
|
+
const cachePath = join71(nexusDir, "peer-models-cache.json");
|
|
37995
|
+
if (existsSync51(cachePath)) {
|
|
37689
37996
|
try {
|
|
37690
|
-
const cache4 = JSON.parse(
|
|
37997
|
+
const cache4 = JSON.parse(readFileSync39(cachePath, "utf8"));
|
|
37691
37998
|
if (cache4.peerId === peerId && cache4.models?.length > 0) {
|
|
37692
37999
|
const age = Date.now() - new Date(cache4.cachedAt).getTime();
|
|
37693
38000
|
if (age < 5 * 60 * 1e3) {
|
|
@@ -37802,10 +38109,10 @@ async function fetchPeerModels(peerId, authKey) {
|
|
|
37802
38109
|
} catch {
|
|
37803
38110
|
}
|
|
37804
38111
|
if (isLocalPeer) {
|
|
37805
|
-
const pricingPath =
|
|
37806
|
-
if (
|
|
38112
|
+
const pricingPath = join71(nexusDir, "pricing.json");
|
|
38113
|
+
if (existsSync51(pricingPath)) {
|
|
37807
38114
|
try {
|
|
37808
|
-
const pricing = JSON.parse(
|
|
38115
|
+
const pricing = JSON.parse(readFileSync39(pricingPath, "utf8"));
|
|
37809
38116
|
return (pricing.models || []).map((m) => ({
|
|
37810
38117
|
name: m.model || "unknown",
|
|
37811
38118
|
size: m.parameterSize || "",
|
|
@@ -38085,17 +38392,17 @@ var init_render2 = __esm({
|
|
|
38085
38392
|
});
|
|
38086
38393
|
|
|
38087
38394
|
// packages/prompts/dist/promptLoader.js
|
|
38088
|
-
import { readFileSync as
|
|
38089
|
-
import { join as
|
|
38395
|
+
import { readFileSync as readFileSync26, existsSync as existsSync35 } from "node:fs";
|
|
38396
|
+
import { join as join51, dirname as dirname16 } from "node:path";
|
|
38090
38397
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
38091
38398
|
function loadPrompt2(promptPath, vars) {
|
|
38092
38399
|
let content = cache2.get(promptPath);
|
|
38093
38400
|
if (content === void 0) {
|
|
38094
|
-
const fullPath =
|
|
38095
|
-
if (!
|
|
38401
|
+
const fullPath = join51(PROMPTS_DIR2, promptPath);
|
|
38402
|
+
if (!existsSync35(fullPath)) {
|
|
38096
38403
|
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
38097
38404
|
}
|
|
38098
|
-
content =
|
|
38405
|
+
content = readFileSync26(fullPath, "utf-8");
|
|
38099
38406
|
cache2.set(promptPath, content);
|
|
38100
38407
|
}
|
|
38101
38408
|
if (!vars)
|
|
@@ -38108,9 +38415,9 @@ var init_promptLoader2 = __esm({
|
|
|
38108
38415
|
"use strict";
|
|
38109
38416
|
__filename2 = fileURLToPath9(import.meta.url);
|
|
38110
38417
|
__dirname5 = dirname16(__filename2);
|
|
38111
|
-
devPath =
|
|
38112
|
-
publishedPath =
|
|
38113
|
-
PROMPTS_DIR2 =
|
|
38418
|
+
devPath = join51(__dirname5, "..", "templates");
|
|
38419
|
+
publishedPath = join51(__dirname5, "..", "prompts", "templates");
|
|
38420
|
+
PROMPTS_DIR2 = existsSync35(devPath) ? devPath : publishedPath;
|
|
38114
38421
|
cache2 = /* @__PURE__ */ new Map();
|
|
38115
38422
|
}
|
|
38116
38423
|
});
|
|
@@ -38221,7 +38528,7 @@ var init_task_templates = __esm({
|
|
|
38221
38528
|
});
|
|
38222
38529
|
|
|
38223
38530
|
// packages/prompts/dist/index.js
|
|
38224
|
-
import { join as
|
|
38531
|
+
import { join as join52, dirname as dirname17 } from "node:path";
|
|
38225
38532
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
38226
38533
|
var _dir, _packageRoot;
|
|
38227
38534
|
var init_dist6 = __esm({
|
|
@@ -38232,7 +38539,7 @@ var init_dist6 = __esm({
|
|
|
38232
38539
|
init_task_templates();
|
|
38233
38540
|
init_render2();
|
|
38234
38541
|
_dir = dirname17(fileURLToPath10(import.meta.url));
|
|
38235
|
-
_packageRoot =
|
|
38542
|
+
_packageRoot = join52(_dir, "..");
|
|
38236
38543
|
}
|
|
38237
38544
|
});
|
|
38238
38545
|
|
|
@@ -38265,21 +38572,21 @@ __export(oa_directory_exports, {
|
|
|
38265
38572
|
writeIndexData: () => writeIndexData,
|
|
38266
38573
|
writeIndexMeta: () => writeIndexMeta
|
|
38267
38574
|
});
|
|
38268
|
-
import { existsSync as
|
|
38269
|
-
import { join as
|
|
38575
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync14, readFileSync as readFileSync27, writeFileSync as writeFileSync15, readdirSync as readdirSync10, statSync as statSync12, unlinkSync as unlinkSync7 } from "node:fs";
|
|
38576
|
+
import { join as join53, relative as relative3, basename as basename11, extname as extname9 } from "node:path";
|
|
38270
38577
|
import { homedir as homedir11 } from "node:os";
|
|
38271
38578
|
function initOaDirectory(repoRoot) {
|
|
38272
|
-
const oaPath =
|
|
38579
|
+
const oaPath = join53(repoRoot, OA_DIR);
|
|
38273
38580
|
for (const sub of SUBDIRS) {
|
|
38274
|
-
|
|
38581
|
+
mkdirSync14(join53(oaPath, sub), { recursive: true });
|
|
38275
38582
|
}
|
|
38276
38583
|
try {
|
|
38277
|
-
const gitignorePath =
|
|
38584
|
+
const gitignorePath = join53(repoRoot, ".gitignore");
|
|
38278
38585
|
const settingsPattern = ".oa/settings.json";
|
|
38279
|
-
if (
|
|
38280
|
-
const content =
|
|
38586
|
+
if (existsSync36(gitignorePath)) {
|
|
38587
|
+
const content = readFileSync27(gitignorePath, "utf-8");
|
|
38281
38588
|
if (!content.includes(settingsPattern)) {
|
|
38282
|
-
|
|
38589
|
+
writeFileSync15(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
|
|
38283
38590
|
}
|
|
38284
38591
|
}
|
|
38285
38592
|
} catch {
|
|
@@ -38287,41 +38594,41 @@ function initOaDirectory(repoRoot) {
|
|
|
38287
38594
|
return oaPath;
|
|
38288
38595
|
}
|
|
38289
38596
|
function hasOaDirectory(repoRoot) {
|
|
38290
|
-
return
|
|
38597
|
+
return existsSync36(join53(repoRoot, OA_DIR, "index"));
|
|
38291
38598
|
}
|
|
38292
38599
|
function loadProjectSettings(repoRoot) {
|
|
38293
|
-
const settingsPath =
|
|
38600
|
+
const settingsPath = join53(repoRoot, OA_DIR, "settings.json");
|
|
38294
38601
|
try {
|
|
38295
|
-
if (
|
|
38296
|
-
return JSON.parse(
|
|
38602
|
+
if (existsSync36(settingsPath)) {
|
|
38603
|
+
return JSON.parse(readFileSync27(settingsPath, "utf-8"));
|
|
38297
38604
|
}
|
|
38298
38605
|
} catch {
|
|
38299
38606
|
}
|
|
38300
38607
|
return {};
|
|
38301
38608
|
}
|
|
38302
38609
|
function saveProjectSettings(repoRoot, settings) {
|
|
38303
|
-
const oaPath =
|
|
38304
|
-
|
|
38610
|
+
const oaPath = join53(repoRoot, OA_DIR);
|
|
38611
|
+
mkdirSync14(oaPath, { recursive: true });
|
|
38305
38612
|
const existing = loadProjectSettings(repoRoot);
|
|
38306
38613
|
const merged = { ...existing, ...settings };
|
|
38307
|
-
|
|
38614
|
+
writeFileSync15(join53(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
38308
38615
|
}
|
|
38309
38616
|
function loadGlobalSettings() {
|
|
38310
|
-
const settingsPath =
|
|
38617
|
+
const settingsPath = join53(homedir11(), ".open-agents", "settings.json");
|
|
38311
38618
|
try {
|
|
38312
|
-
if (
|
|
38313
|
-
return JSON.parse(
|
|
38619
|
+
if (existsSync36(settingsPath)) {
|
|
38620
|
+
return JSON.parse(readFileSync27(settingsPath, "utf-8"));
|
|
38314
38621
|
}
|
|
38315
38622
|
} catch {
|
|
38316
38623
|
}
|
|
38317
38624
|
return {};
|
|
38318
38625
|
}
|
|
38319
38626
|
function saveGlobalSettings(settings) {
|
|
38320
|
-
const dir =
|
|
38321
|
-
|
|
38627
|
+
const dir = join53(homedir11(), ".open-agents");
|
|
38628
|
+
mkdirSync14(dir, { recursive: true });
|
|
38322
38629
|
const existing = loadGlobalSettings();
|
|
38323
38630
|
const merged = { ...existing, ...settings };
|
|
38324
|
-
|
|
38631
|
+
writeFileSync15(join53(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
38325
38632
|
}
|
|
38326
38633
|
function resolveSettings(repoRoot) {
|
|
38327
38634
|
const global = loadGlobalSettings();
|
|
@@ -38336,12 +38643,12 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
38336
38643
|
while (dir && !visited.has(dir)) {
|
|
38337
38644
|
visited.add(dir);
|
|
38338
38645
|
for (const name of CONTEXT_FILES) {
|
|
38339
|
-
const filePath =
|
|
38646
|
+
const filePath = join53(dir, name);
|
|
38340
38647
|
const normalizedName = name.toLowerCase();
|
|
38341
|
-
if (
|
|
38648
|
+
if (existsSync36(filePath) && !seen.has(filePath)) {
|
|
38342
38649
|
seen.add(filePath);
|
|
38343
38650
|
try {
|
|
38344
|
-
let content =
|
|
38651
|
+
let content = readFileSync27(filePath, "utf-8");
|
|
38345
38652
|
if (content.length > maxContentLen) {
|
|
38346
38653
|
content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
|
|
38347
38654
|
}
|
|
@@ -38355,11 +38662,11 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
38355
38662
|
}
|
|
38356
38663
|
}
|
|
38357
38664
|
}
|
|
38358
|
-
const projectMap =
|
|
38359
|
-
if (
|
|
38665
|
+
const projectMap = join53(dir, OA_DIR, "context", "project-map.md");
|
|
38666
|
+
if (existsSync36(projectMap) && !seen.has(projectMap)) {
|
|
38360
38667
|
seen.add(projectMap);
|
|
38361
38668
|
try {
|
|
38362
|
-
let content =
|
|
38669
|
+
let content = readFileSync27(projectMap, "utf-8");
|
|
38363
38670
|
if (content.length > maxContentLen) {
|
|
38364
38671
|
content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
|
|
38365
38672
|
}
|
|
@@ -38371,7 +38678,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
38371
38678
|
} catch {
|
|
38372
38679
|
}
|
|
38373
38680
|
}
|
|
38374
|
-
const parent =
|
|
38681
|
+
const parent = join53(dir, "..");
|
|
38375
38682
|
if (parent === dir)
|
|
38376
38683
|
break;
|
|
38377
38684
|
dir = parent;
|
|
@@ -38389,34 +38696,34 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
38389
38696
|
return found;
|
|
38390
38697
|
}
|
|
38391
38698
|
function readIndexMeta(repoRoot) {
|
|
38392
|
-
const metaPath =
|
|
38699
|
+
const metaPath = join53(repoRoot, OA_DIR, "index", "meta.json");
|
|
38393
38700
|
try {
|
|
38394
|
-
return JSON.parse(
|
|
38701
|
+
return JSON.parse(readFileSync27(metaPath, "utf-8"));
|
|
38395
38702
|
} catch {
|
|
38396
38703
|
return null;
|
|
38397
38704
|
}
|
|
38398
38705
|
}
|
|
38399
38706
|
function writeIndexMeta(repoRoot, meta) {
|
|
38400
|
-
const metaPath =
|
|
38401
|
-
|
|
38402
|
-
|
|
38707
|
+
const metaPath = join53(repoRoot, OA_DIR, "index", "meta.json");
|
|
38708
|
+
mkdirSync14(join53(repoRoot, OA_DIR, "index"), { recursive: true });
|
|
38709
|
+
writeFileSync15(metaPath, JSON.stringify(meta, null, 2), "utf-8");
|
|
38403
38710
|
}
|
|
38404
38711
|
function readIndexData(repoRoot, filename) {
|
|
38405
|
-
const filePath =
|
|
38712
|
+
const filePath = join53(repoRoot, OA_DIR, "index", filename);
|
|
38406
38713
|
try {
|
|
38407
|
-
return JSON.parse(
|
|
38714
|
+
return JSON.parse(readFileSync27(filePath, "utf-8"));
|
|
38408
38715
|
} catch {
|
|
38409
38716
|
return null;
|
|
38410
38717
|
}
|
|
38411
38718
|
}
|
|
38412
38719
|
function writeIndexData(repoRoot, filename, data) {
|
|
38413
|
-
const filePath =
|
|
38414
|
-
|
|
38415
|
-
|
|
38720
|
+
const filePath = join53(repoRoot, OA_DIR, "index", filename);
|
|
38721
|
+
mkdirSync14(join53(repoRoot, OA_DIR, "index"), { recursive: true });
|
|
38722
|
+
writeFileSync15(filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
38416
38723
|
}
|
|
38417
38724
|
function generateProjectMap(repoRoot) {
|
|
38418
38725
|
const sections = [];
|
|
38419
|
-
const repoName2 =
|
|
38726
|
+
const repoName2 = basename11(repoRoot);
|
|
38420
38727
|
sections.push(`# Project Map: ${repoName2}
|
|
38421
38728
|
`);
|
|
38422
38729
|
sections.push(`> Auto-generated by open-agents. Updated: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
@@ -38460,28 +38767,28 @@ ${tree}\`\`\`
|
|
|
38460
38767
|
sections.push("");
|
|
38461
38768
|
}
|
|
38462
38769
|
const content = sections.join("\n");
|
|
38463
|
-
const contextDir =
|
|
38464
|
-
|
|
38465
|
-
|
|
38770
|
+
const contextDir = join53(repoRoot, OA_DIR, "context");
|
|
38771
|
+
mkdirSync14(contextDir, { recursive: true });
|
|
38772
|
+
writeFileSync15(join53(contextDir, "project-map.md"), content, "utf-8");
|
|
38466
38773
|
return content;
|
|
38467
38774
|
}
|
|
38468
38775
|
function saveSession(repoRoot, session) {
|
|
38469
|
-
const historyDir =
|
|
38470
|
-
|
|
38471
|
-
|
|
38776
|
+
const historyDir = join53(repoRoot, OA_DIR, "history");
|
|
38777
|
+
mkdirSync14(historyDir, { recursive: true });
|
|
38778
|
+
writeFileSync15(join53(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
|
|
38472
38779
|
}
|
|
38473
38780
|
function loadRecentSessions(repoRoot, limit = 5) {
|
|
38474
|
-
const historyDir =
|
|
38475
|
-
if (!
|
|
38781
|
+
const historyDir = join53(repoRoot, OA_DIR, "history");
|
|
38782
|
+
if (!existsSync36(historyDir))
|
|
38476
38783
|
return [];
|
|
38477
38784
|
try {
|
|
38478
|
-
const files =
|
|
38479
|
-
const stat5 = statSync12(
|
|
38785
|
+
const files = readdirSync10(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
|
|
38786
|
+
const stat5 = statSync12(join53(historyDir, f));
|
|
38480
38787
|
return { file: f, mtime: stat5.mtimeMs };
|
|
38481
38788
|
}).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
|
|
38482
38789
|
return files.map((f) => {
|
|
38483
38790
|
try {
|
|
38484
|
-
return JSON.parse(
|
|
38791
|
+
return JSON.parse(readFileSync27(join53(historyDir, f.file), "utf-8"));
|
|
38485
38792
|
} catch {
|
|
38486
38793
|
return null;
|
|
38487
38794
|
}
|
|
@@ -38491,18 +38798,18 @@ function loadRecentSessions(repoRoot, limit = 5) {
|
|
|
38491
38798
|
}
|
|
38492
38799
|
}
|
|
38493
38800
|
function savePendingTask(repoRoot, task) {
|
|
38494
|
-
const historyDir =
|
|
38495
|
-
|
|
38496
|
-
|
|
38801
|
+
const historyDir = join53(repoRoot, OA_DIR, "history");
|
|
38802
|
+
mkdirSync14(historyDir, { recursive: true });
|
|
38803
|
+
writeFileSync15(join53(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
|
|
38497
38804
|
}
|
|
38498
38805
|
function loadPendingTask(repoRoot) {
|
|
38499
|
-
const filePath =
|
|
38806
|
+
const filePath = join53(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
|
|
38500
38807
|
try {
|
|
38501
|
-
if (!
|
|
38808
|
+
if (!existsSync36(filePath))
|
|
38502
38809
|
return null;
|
|
38503
|
-
const data = JSON.parse(
|
|
38810
|
+
const data = JSON.parse(readFileSync27(filePath, "utf-8"));
|
|
38504
38811
|
try {
|
|
38505
|
-
|
|
38812
|
+
unlinkSync7(filePath);
|
|
38506
38813
|
} catch {
|
|
38507
38814
|
}
|
|
38508
38815
|
return data;
|
|
@@ -38511,13 +38818,13 @@ function loadPendingTask(repoRoot) {
|
|
|
38511
38818
|
}
|
|
38512
38819
|
}
|
|
38513
38820
|
function saveSessionContext(repoRoot, entry) {
|
|
38514
|
-
const contextDir =
|
|
38515
|
-
|
|
38516
|
-
const filePath =
|
|
38821
|
+
const contextDir = join53(repoRoot, OA_DIR, "context");
|
|
38822
|
+
mkdirSync14(contextDir, { recursive: true });
|
|
38823
|
+
const filePath = join53(contextDir, CONTEXT_SAVE_FILE);
|
|
38517
38824
|
let ctx;
|
|
38518
38825
|
try {
|
|
38519
|
-
if (
|
|
38520
|
-
ctx = JSON.parse(
|
|
38826
|
+
if (existsSync36(filePath)) {
|
|
38827
|
+
ctx = JSON.parse(readFileSync27(filePath, "utf-8"));
|
|
38521
38828
|
} else {
|
|
38522
38829
|
ctx = { entries: [], maxEntries: MAX_CONTEXT_ENTRIES, updatedAt: "" };
|
|
38523
38830
|
}
|
|
@@ -38529,14 +38836,14 @@ function saveSessionContext(repoRoot, entry) {
|
|
|
38529
38836
|
ctx.entries = ctx.entries.slice(-ctx.maxEntries);
|
|
38530
38837
|
}
|
|
38531
38838
|
ctx.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
38532
|
-
|
|
38839
|
+
writeFileSync15(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
|
|
38533
38840
|
}
|
|
38534
38841
|
function loadSessionContext(repoRoot) {
|
|
38535
|
-
const filePath =
|
|
38842
|
+
const filePath = join53(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
|
|
38536
38843
|
try {
|
|
38537
|
-
if (!
|
|
38844
|
+
if (!existsSync36(filePath))
|
|
38538
38845
|
return null;
|
|
38539
|
-
return JSON.parse(
|
|
38846
|
+
return JSON.parse(readFileSync27(filePath, "utf-8"));
|
|
38540
38847
|
} catch {
|
|
38541
38848
|
return null;
|
|
38542
38849
|
}
|
|
@@ -38582,12 +38889,12 @@ function detectManifests(repoRoot) {
|
|
|
38582
38889
|
{ file: "docker-compose.yaml", type: "Docker Compose" }
|
|
38583
38890
|
];
|
|
38584
38891
|
for (const check of checks) {
|
|
38585
|
-
const filePath =
|
|
38586
|
-
if (
|
|
38892
|
+
const filePath = join53(repoRoot, check.file);
|
|
38893
|
+
if (existsSync36(filePath)) {
|
|
38587
38894
|
let name;
|
|
38588
38895
|
if (check.nameField) {
|
|
38589
38896
|
try {
|
|
38590
|
-
const data = JSON.parse(
|
|
38897
|
+
const data = JSON.parse(readFileSync27(filePath, "utf-8"));
|
|
38591
38898
|
name = data[check.nameField];
|
|
38592
38899
|
} catch {
|
|
38593
38900
|
}
|
|
@@ -38616,7 +38923,7 @@ function findKeyFiles(repoRoot) {
|
|
|
38616
38923
|
{ pattern: "CLAUDE.md", description: "Claude Code context" }
|
|
38617
38924
|
];
|
|
38618
38925
|
for (const check of checks) {
|
|
38619
|
-
if (
|
|
38926
|
+
if (existsSync36(join53(repoRoot, check.pattern))) {
|
|
38620
38927
|
keyFiles.push({ path: check.pattern, description: check.description });
|
|
38621
38928
|
}
|
|
38622
38929
|
}
|
|
@@ -38627,7 +38934,7 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
38627
38934
|
return "";
|
|
38628
38935
|
let result = "";
|
|
38629
38936
|
try {
|
|
38630
|
-
const entries =
|
|
38937
|
+
const entries = readdirSync10(root, { withFileTypes: true }).filter((e) => !e.name.startsWith(".") || e.name === ".github").filter((e) => !SKIP_DIRS.has(e.name)).sort((a, b) => {
|
|
38631
38938
|
if (a.isDirectory() && !b.isDirectory())
|
|
38632
38939
|
return -1;
|
|
38633
38940
|
if (!a.isDirectory() && b.isDirectory())
|
|
@@ -38642,12 +38949,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
38642
38949
|
if (entry.isDirectory()) {
|
|
38643
38950
|
let fileCount = 0;
|
|
38644
38951
|
try {
|
|
38645
|
-
fileCount =
|
|
38952
|
+
fileCount = readdirSync10(join53(root, entry.name)).filter((f) => !f.startsWith(".")).length;
|
|
38646
38953
|
} catch {
|
|
38647
38954
|
}
|
|
38648
38955
|
result += `${prefix}${connector}${entry.name}/ (${fileCount})
|
|
38649
38956
|
`;
|
|
38650
|
-
result += buildDirTree(
|
|
38957
|
+
result += buildDirTree(join53(root, entry.name), maxDepth, childPrefix, depth + 1);
|
|
38651
38958
|
} else if (depth < maxDepth) {
|
|
38652
38959
|
result += `${prefix}${connector}${entry.name}
|
|
38653
38960
|
`;
|
|
@@ -38659,17 +38966,17 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
38659
38966
|
}
|
|
38660
38967
|
function loadUsageFile(filePath) {
|
|
38661
38968
|
try {
|
|
38662
|
-
if (
|
|
38663
|
-
return JSON.parse(
|
|
38969
|
+
if (existsSync36(filePath)) {
|
|
38970
|
+
return JSON.parse(readFileSync27(filePath, "utf-8"));
|
|
38664
38971
|
}
|
|
38665
38972
|
} catch {
|
|
38666
38973
|
}
|
|
38667
38974
|
return { records: [] };
|
|
38668
38975
|
}
|
|
38669
38976
|
function saveUsageFile(filePath, data) {
|
|
38670
|
-
const dir =
|
|
38671
|
-
|
|
38672
|
-
|
|
38977
|
+
const dir = join53(filePath, "..");
|
|
38978
|
+
mkdirSync14(dir, { recursive: true });
|
|
38979
|
+
writeFileSync15(filePath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
38673
38980
|
}
|
|
38674
38981
|
function recordUsage(kind, value, opts) {
|
|
38675
38982
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -38697,15 +39004,15 @@ function recordUsage(kind, value, opts) {
|
|
|
38697
39004
|
}
|
|
38698
39005
|
saveUsageFile(filePath, data);
|
|
38699
39006
|
};
|
|
38700
|
-
update(
|
|
39007
|
+
update(join53(homedir11(), ".open-agents", USAGE_HISTORY_FILE));
|
|
38701
39008
|
if (opts?.repoRoot) {
|
|
38702
|
-
update(
|
|
39009
|
+
update(join53(opts.repoRoot, OA_DIR, USAGE_HISTORY_FILE));
|
|
38703
39010
|
}
|
|
38704
39011
|
}
|
|
38705
39012
|
function loadUsageHistory(kind, repoRoot) {
|
|
38706
|
-
const globalPath =
|
|
39013
|
+
const globalPath = join53(homedir11(), ".open-agents", USAGE_HISTORY_FILE);
|
|
38707
39014
|
const globalData = loadUsageFile(globalPath);
|
|
38708
|
-
const localData = repoRoot ? loadUsageFile(
|
|
39015
|
+
const localData = repoRoot ? loadUsageFile(join53(repoRoot, OA_DIR, USAGE_HISTORY_FILE)) : { records: [] };
|
|
38709
39016
|
const map = /* @__PURE__ */ new Map();
|
|
38710
39017
|
for (const r of globalData.records) {
|
|
38711
39018
|
if (r.kind !== kind)
|
|
@@ -38736,9 +39043,9 @@ function deleteUsageRecord(kind, value, repoRoot) {
|
|
|
38736
39043
|
saveUsageFile(filePath, data);
|
|
38737
39044
|
}
|
|
38738
39045
|
};
|
|
38739
|
-
remove(
|
|
39046
|
+
remove(join53(homedir11(), ".open-agents", USAGE_HISTORY_FILE));
|
|
38740
39047
|
if (repoRoot) {
|
|
38741
|
-
remove(
|
|
39048
|
+
remove(join53(repoRoot, OA_DIR, USAGE_HISTORY_FILE));
|
|
38742
39049
|
}
|
|
38743
39050
|
}
|
|
38744
39051
|
var OA_DIR, SUBDIRS, CONTEXT_FILES, PENDING_TASK_FILE, CONTEXT_SAVE_FILE, MAX_CONTEXT_ENTRIES, SKIP_DIRS, USAGE_HISTORY_FILE, MAX_HISTORY_RECORDS;
|
|
@@ -38786,10 +39093,10 @@ var init_oa_directory = __esm({
|
|
|
38786
39093
|
|
|
38787
39094
|
// packages/cli/dist/tui/setup.js
|
|
38788
39095
|
import * as readline from "node:readline";
|
|
38789
|
-
import { execSync as
|
|
39096
|
+
import { execSync as execSync27, spawn as spawn19, exec as exec2 } from "node:child_process";
|
|
38790
39097
|
import { promisify as promisify6 } from "node:util";
|
|
38791
|
-
import { existsSync as
|
|
38792
|
-
import { join as
|
|
39098
|
+
import { existsSync as existsSync37, writeFileSync as writeFileSync16, readFileSync as readFileSync28, appendFileSync as appendFileSync2, mkdirSync as mkdirSync15 } from "node:fs";
|
|
39099
|
+
import { join as join54 } from "node:path";
|
|
38793
39100
|
import { homedir as homedir12, platform as platform2 } from "node:os";
|
|
38794
39101
|
function detectSystemSpecs() {
|
|
38795
39102
|
let totalRamGB = 0;
|
|
@@ -38797,7 +39104,7 @@ function detectSystemSpecs() {
|
|
|
38797
39104
|
let gpuVramGB = 0;
|
|
38798
39105
|
let gpuName = "";
|
|
38799
39106
|
try {
|
|
38800
|
-
const memInfo =
|
|
39107
|
+
const memInfo = execSync27("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
|
|
38801
39108
|
encoding: "utf8",
|
|
38802
39109
|
timeout: 5e3
|
|
38803
39110
|
});
|
|
@@ -38817,7 +39124,7 @@ function detectSystemSpecs() {
|
|
|
38817
39124
|
} catch {
|
|
38818
39125
|
}
|
|
38819
39126
|
try {
|
|
38820
|
-
const nvidiaSmi =
|
|
39127
|
+
const nvidiaSmi = execSync27("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
|
|
38821
39128
|
const lines = nvidiaSmi.trim().split("\n");
|
|
38822
39129
|
if (lines.length > 0) {
|
|
38823
39130
|
for (const line of lines) {
|
|
@@ -38996,7 +39303,7 @@ function ensureCurl() {
|
|
|
38996
39303
|
for (const s of strategies) {
|
|
38997
39304
|
if (hasCmd(s.check)) {
|
|
38998
39305
|
try {
|
|
38999
|
-
|
|
39306
|
+
execSync27(s.install, { stdio: "inherit", timeout: 12e4 });
|
|
39000
39307
|
if (hasCmd("curl")) {
|
|
39001
39308
|
process.stdout.write(` ${c2.green("\u2714")} curl installed via ${s.label}.
|
|
39002
39309
|
`);
|
|
@@ -39010,7 +39317,7 @@ function ensureCurl() {
|
|
|
39010
39317
|
}
|
|
39011
39318
|
if (plat === "darwin") {
|
|
39012
39319
|
try {
|
|
39013
|
-
|
|
39320
|
+
execSync27("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
|
|
39014
39321
|
if (hasCmd("curl"))
|
|
39015
39322
|
return true;
|
|
39016
39323
|
} catch {
|
|
@@ -39045,7 +39352,7 @@ function installOllamaLinux() {
|
|
|
39045
39352
|
|
|
39046
39353
|
`);
|
|
39047
39354
|
try {
|
|
39048
|
-
|
|
39355
|
+
execSync27("curl -fsSL https://ollama.com/install.sh | sh", {
|
|
39049
39356
|
stdio: "inherit",
|
|
39050
39357
|
timeout: 3e5
|
|
39051
39358
|
});
|
|
@@ -39073,10 +39380,10 @@ async function installOllamaMac(_rl) {
|
|
|
39073
39380
|
|
|
39074
39381
|
`);
|
|
39075
39382
|
try {
|
|
39076
|
-
|
|
39383
|
+
execSync27('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
|
|
39077
39384
|
if (!hasCmd("brew")) {
|
|
39078
39385
|
try {
|
|
39079
|
-
const brewPrefix =
|
|
39386
|
+
const brewPrefix = existsSync37("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
|
|
39080
39387
|
process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
|
|
39081
39388
|
} catch {
|
|
39082
39389
|
}
|
|
@@ -39106,7 +39413,7 @@ async function installOllamaMac(_rl) {
|
|
|
39106
39413
|
|
|
39107
39414
|
`);
|
|
39108
39415
|
try {
|
|
39109
|
-
|
|
39416
|
+
execSync27("brew install ollama", {
|
|
39110
39417
|
stdio: "inherit",
|
|
39111
39418
|
timeout: 3e5
|
|
39112
39419
|
});
|
|
@@ -39133,7 +39440,7 @@ function installOllamaWindows() {
|
|
|
39133
39440
|
|
|
39134
39441
|
`);
|
|
39135
39442
|
try {
|
|
39136
|
-
|
|
39443
|
+
execSync27('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
|
|
39137
39444
|
stdio: "inherit",
|
|
39138
39445
|
timeout: 3e5
|
|
39139
39446
|
});
|
|
@@ -39214,7 +39521,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
|
|
|
39214
39521
|
}
|
|
39215
39522
|
function pullModelWithAutoUpdate(tag) {
|
|
39216
39523
|
try {
|
|
39217
|
-
|
|
39524
|
+
execSync27(`ollama pull ${tag}`, {
|
|
39218
39525
|
stdio: "inherit",
|
|
39219
39526
|
timeout: 36e5
|
|
39220
39527
|
// 1 hour max
|
|
@@ -39234,7 +39541,7 @@ function pullModelWithAutoUpdate(tag) {
|
|
|
39234
39541
|
|
|
39235
39542
|
`);
|
|
39236
39543
|
try {
|
|
39237
|
-
|
|
39544
|
+
execSync27("curl -fsSL https://ollama.com/install.sh | sh", {
|
|
39238
39545
|
stdio: "inherit",
|
|
39239
39546
|
timeout: 3e5
|
|
39240
39547
|
// 5 min max for install
|
|
@@ -39245,7 +39552,7 @@ function pullModelWithAutoUpdate(tag) {
|
|
|
39245
39552
|
process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
|
|
39246
39553
|
|
|
39247
39554
|
`);
|
|
39248
|
-
|
|
39555
|
+
execSync27(`ollama pull ${tag}`, {
|
|
39249
39556
|
stdio: "inherit",
|
|
39250
39557
|
timeout: 36e5
|
|
39251
39558
|
});
|
|
@@ -39347,7 +39654,7 @@ function ensurePython3() {
|
|
|
39347
39654
|
if (plat === "darwin") {
|
|
39348
39655
|
if (hasCmd("brew")) {
|
|
39349
39656
|
try {
|
|
39350
|
-
|
|
39657
|
+
execSync27("brew install python3", { stdio: "inherit", timeout: 3e5 });
|
|
39351
39658
|
if (hasCmd("python3")) {
|
|
39352
39659
|
process.stdout.write(` ${c2.green("\u2714")} Python3 installed via Homebrew.
|
|
39353
39660
|
`);
|
|
@@ -39360,7 +39667,7 @@ function ensurePython3() {
|
|
|
39360
39667
|
for (const s of strategies) {
|
|
39361
39668
|
if (hasCmd(s.check)) {
|
|
39362
39669
|
try {
|
|
39363
|
-
|
|
39670
|
+
execSync27(s.install, { stdio: "inherit", timeout: 12e4 });
|
|
39364
39671
|
if (hasCmd("python3") || hasCmd("python")) {
|
|
39365
39672
|
process.stdout.write(` ${c2.green("\u2714")} Python3 installed via ${s.label}.
|
|
39366
39673
|
`);
|
|
@@ -39376,11 +39683,11 @@ function ensurePython3() {
|
|
|
39376
39683
|
}
|
|
39377
39684
|
function checkPythonVenv() {
|
|
39378
39685
|
try {
|
|
39379
|
-
|
|
39686
|
+
execSync27("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
39380
39687
|
return true;
|
|
39381
39688
|
} catch {
|
|
39382
39689
|
try {
|
|
39383
|
-
|
|
39690
|
+
execSync27("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
39384
39691
|
return true;
|
|
39385
39692
|
} catch {
|
|
39386
39693
|
return false;
|
|
@@ -39399,7 +39706,7 @@ function ensurePythonVenv() {
|
|
|
39399
39706
|
for (const s of strategies) {
|
|
39400
39707
|
if (hasCmd(s.check)) {
|
|
39401
39708
|
try {
|
|
39402
|
-
|
|
39709
|
+
execSync27(s.install, { stdio: "inherit", timeout: 12e4 });
|
|
39403
39710
|
if (checkPythonVenv()) {
|
|
39404
39711
|
process.stdout.write(` ${c2.green("\u2714")} python3-venv installed via ${s.label}.
|
|
39405
39712
|
`);
|
|
@@ -39830,12 +40137,12 @@ async function doSetup(config, rl) {
|
|
|
39830
40137
|
`PARAMETER num_predict ${numPredict}`,
|
|
39831
40138
|
`PARAMETER stop "<|endoftext|>"`
|
|
39832
40139
|
].join("\n");
|
|
39833
|
-
const modelDir2 =
|
|
39834
|
-
|
|
39835
|
-
const modelfilePath =
|
|
39836
|
-
|
|
40140
|
+
const modelDir2 = join54(homedir12(), ".open-agents", "models");
|
|
40141
|
+
mkdirSync15(modelDir2, { recursive: true });
|
|
40142
|
+
const modelfilePath = join54(modelDir2, `Modelfile.${customName}`);
|
|
40143
|
+
writeFileSync16(modelfilePath, modelfileContent + "\n", "utf8");
|
|
39837
40144
|
process.stdout.write(` ${c2.dim("Creating model...")} `);
|
|
39838
|
-
|
|
40145
|
+
execSync27(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
39839
40146
|
stdio: "pipe",
|
|
39840
40147
|
timeout: 12e4
|
|
39841
40148
|
});
|
|
@@ -39878,7 +40185,7 @@ async function isModelAvailable(config) {
|
|
|
39878
40185
|
}
|
|
39879
40186
|
function isFirstRun() {
|
|
39880
40187
|
try {
|
|
39881
|
-
return !
|
|
40188
|
+
return !existsSync37(join54(homedir12(), ".open-agents", "config.json"));
|
|
39882
40189
|
} catch {
|
|
39883
40190
|
return true;
|
|
39884
40191
|
}
|
|
@@ -39886,7 +40193,7 @@ function isFirstRun() {
|
|
|
39886
40193
|
function hasCmd(cmd) {
|
|
39887
40194
|
try {
|
|
39888
40195
|
const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
|
|
39889
|
-
|
|
40196
|
+
execSync27(whichCmd, { stdio: "pipe", timeout: 3e3 });
|
|
39890
40197
|
return true;
|
|
39891
40198
|
} catch {
|
|
39892
40199
|
return false;
|
|
@@ -39915,11 +40222,11 @@ function detectPkgManager() {
|
|
|
39915
40222
|
return null;
|
|
39916
40223
|
}
|
|
39917
40224
|
function getVenvDir() {
|
|
39918
|
-
return
|
|
40225
|
+
return join54(homedir12(), ".open-agents", "venv");
|
|
39919
40226
|
}
|
|
39920
40227
|
function hasVenvModule() {
|
|
39921
40228
|
try {
|
|
39922
|
-
|
|
40229
|
+
execSync27("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
39923
40230
|
return true;
|
|
39924
40231
|
} catch {
|
|
39925
40232
|
return false;
|
|
@@ -39928,9 +40235,9 @@ function hasVenvModule() {
|
|
|
39928
40235
|
function ensureVenv(log) {
|
|
39929
40236
|
const venvDir = getVenvDir();
|
|
39930
40237
|
const isWin2 = process.platform === "win32";
|
|
39931
|
-
const pipPath = isWin2 ?
|
|
40238
|
+
const pipPath = isWin2 ? join54(venvDir, "Scripts", "pip.exe") : join54(venvDir, "bin", "pip");
|
|
39932
40239
|
const pythonCmd = isWin2 ? "python" : "python3";
|
|
39933
|
-
if (
|
|
40240
|
+
if (existsSync37(pipPath))
|
|
39934
40241
|
return venvDir;
|
|
39935
40242
|
log("Creating Python venv for vision deps...");
|
|
39936
40243
|
if (!hasCmd(pythonCmd) && !hasCmd("python3")) {
|
|
@@ -39942,10 +40249,10 @@ function ensureVenv(log) {
|
|
|
39942
40249
|
return null;
|
|
39943
40250
|
}
|
|
39944
40251
|
try {
|
|
39945
|
-
|
|
40252
|
+
mkdirSync15(join54(homedir12(), ".open-agents"), { recursive: true });
|
|
39946
40253
|
const pyCmd = hasCmd(pythonCmd) ? pythonCmd : "python3";
|
|
39947
|
-
|
|
39948
|
-
|
|
40254
|
+
execSync27(`${pyCmd} -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
|
|
40255
|
+
execSync27(`"${pipPath}" install --upgrade pip`, {
|
|
39949
40256
|
stdio: "pipe",
|
|
39950
40257
|
timeout: 6e4
|
|
39951
40258
|
});
|
|
@@ -39958,7 +40265,7 @@ function ensureVenv(log) {
|
|
|
39958
40265
|
}
|
|
39959
40266
|
function trySudoPasswordless(cmd, timeoutMs = 12e4) {
|
|
39960
40267
|
try {
|
|
39961
|
-
|
|
40268
|
+
execSync27(`sudo -n ${cmd}`, {
|
|
39962
40269
|
stdio: "pipe",
|
|
39963
40270
|
timeout: timeoutMs,
|
|
39964
40271
|
env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
|
|
@@ -39971,7 +40278,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
|
|
|
39971
40278
|
function runWithSudo(cmd, password, timeoutMs = 12e4) {
|
|
39972
40279
|
try {
|
|
39973
40280
|
const escaped = cmd.replace(/'/g, "'\\''");
|
|
39974
|
-
|
|
40281
|
+
execSync27(`sudo -S bash -c '${escaped}'`, {
|
|
39975
40282
|
input: password + "\n",
|
|
39976
40283
|
stdio: ["pipe", "pipe", "pipe"],
|
|
39977
40284
|
timeout: timeoutMs,
|
|
@@ -40078,7 +40385,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
40078
40385
|
ok = await sudoInstall(batchCmd, getPassword, log, cachedPasswordRef, 18e4);
|
|
40079
40386
|
} else {
|
|
40080
40387
|
try {
|
|
40081
|
-
|
|
40388
|
+
execSync27(batchCmd, { stdio: "pipe", timeout: 18e4 });
|
|
40082
40389
|
ok = true;
|
|
40083
40390
|
} catch {
|
|
40084
40391
|
ok = false;
|
|
@@ -40115,7 +40422,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
40115
40422
|
const venvCmds = {
|
|
40116
40423
|
apt: () => {
|
|
40117
40424
|
try {
|
|
40118
|
-
const pyVer =
|
|
40425
|
+
const pyVer = execSync27(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
|
|
40119
40426
|
return `apt-get install -y python3-venv python${pyVer}-venv`;
|
|
40120
40427
|
} catch {
|
|
40121
40428
|
return "apt-get install -y python3-venv";
|
|
@@ -40136,19 +40443,19 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
40136
40443
|
}
|
|
40137
40444
|
}
|
|
40138
40445
|
const venvDir = getVenvDir();
|
|
40139
|
-
const venvBin =
|
|
40140
|
-
const venvMoondream =
|
|
40446
|
+
const venvBin = join54(venvDir, "bin");
|
|
40447
|
+
const venvMoondream = join54(venvBin, "moondream-station");
|
|
40141
40448
|
const venv = ensureVenv(log);
|
|
40142
|
-
if (venv && !hasCmd("moondream-station") && !
|
|
40143
|
-
const venvPip2 =
|
|
40449
|
+
if (venv && !hasCmd("moondream-station") && !existsSync37(venvMoondream)) {
|
|
40450
|
+
const venvPip2 = join54(venvBin, "pip");
|
|
40144
40451
|
log("Installing moondream-station in ~/.open-agents/venv...");
|
|
40145
40452
|
try {
|
|
40146
|
-
|
|
40147
|
-
if (
|
|
40453
|
+
execSync27(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
|
|
40454
|
+
if (existsSync37(venvMoondream)) {
|
|
40148
40455
|
log("moondream-station installed successfully.");
|
|
40149
40456
|
} else {
|
|
40150
40457
|
try {
|
|
40151
|
-
const check =
|
|
40458
|
+
const check = execSync27(`"${venvPip2}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
|
|
40152
40459
|
if (check.includes("moondream")) {
|
|
40153
40460
|
log("moondream-station package installed.");
|
|
40154
40461
|
}
|
|
@@ -40161,11 +40468,11 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
40161
40468
|
}
|
|
40162
40469
|
}
|
|
40163
40470
|
if (venv) {
|
|
40164
|
-
const venvPython2 =
|
|
40165
|
-
const venvPip2 =
|
|
40471
|
+
const venvPython2 = join54(venvBin, "python");
|
|
40472
|
+
const venvPip2 = join54(venvBin, "pip");
|
|
40166
40473
|
let ocrStackInstalled = false;
|
|
40167
40474
|
try {
|
|
40168
|
-
|
|
40475
|
+
execSync27(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
|
|
40169
40476
|
ocrStackInstalled = true;
|
|
40170
40477
|
} catch {
|
|
40171
40478
|
}
|
|
@@ -40173,9 +40480,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
40173
40480
|
const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
|
|
40174
40481
|
log("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
|
|
40175
40482
|
try {
|
|
40176
|
-
|
|
40483
|
+
execSync27(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
|
|
40177
40484
|
try {
|
|
40178
|
-
|
|
40485
|
+
execSync27(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
|
|
40179
40486
|
log("OCR Python stack installed successfully.");
|
|
40180
40487
|
} catch {
|
|
40181
40488
|
log("OCR Python stack install completed but import verification failed.");
|
|
@@ -40209,7 +40516,7 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
40209
40516
|
const archMap = { x64: "amd64", arm64: "arm64", arm: "arm" };
|
|
40210
40517
|
const cfArch = archMap[arch2] ?? "amd64";
|
|
40211
40518
|
try {
|
|
40212
|
-
|
|
40519
|
+
execSync27(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir12()}/.local/bin" && mv /tmp/cloudflared "${homedir12()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
|
|
40213
40520
|
if (!process.env.PATH?.includes(`${homedir12()}/.local/bin`)) {
|
|
40214
40521
|
process.env.PATH = `${homedir12()}/.local/bin:${process.env.PATH}`;
|
|
40215
40522
|
}
|
|
@@ -40220,7 +40527,7 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
40220
40527
|
} catch {
|
|
40221
40528
|
}
|
|
40222
40529
|
try {
|
|
40223
|
-
|
|
40530
|
+
execSync27(`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 });
|
|
40224
40531
|
if (hasCmd("cloudflared")) {
|
|
40225
40532
|
log("cloudflared installed.");
|
|
40226
40533
|
return true;
|
|
@@ -40229,7 +40536,7 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
40229
40536
|
}
|
|
40230
40537
|
} else if (os === "darwin") {
|
|
40231
40538
|
try {
|
|
40232
|
-
|
|
40539
|
+
execSync27("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
|
|
40233
40540
|
if (hasCmd("cloudflared")) {
|
|
40234
40541
|
log("cloudflared installed via Homebrew.");
|
|
40235
40542
|
return true;
|
|
@@ -40306,10 +40613,10 @@ async function createExpandedVariantAsync(baseModel, specs, sizeGB, kvBytesPerTo
|
|
|
40306
40613
|
`PARAMETER num_predict ${numPredict}`,
|
|
40307
40614
|
`PARAMETER stop "<|endoftext|>"`
|
|
40308
40615
|
].join("\n");
|
|
40309
|
-
const modelDir2 =
|
|
40310
|
-
|
|
40311
|
-
const modelfilePath =
|
|
40312
|
-
|
|
40616
|
+
const modelDir2 = join54(homedir12(), ".open-agents", "models");
|
|
40617
|
+
mkdirSync15(modelDir2, { recursive: true });
|
|
40618
|
+
const modelfilePath = join54(modelDir2, `Modelfile.${customName}`);
|
|
40619
|
+
writeFileSync16(modelfilePath, modelfileContent + "\n", "utf8");
|
|
40313
40620
|
await execAsync(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
40314
40621
|
timeout: 12e4
|
|
40315
40622
|
});
|
|
@@ -40371,7 +40678,7 @@ async function ensureExpandedContext(modelName, backendUrl) {
|
|
|
40371
40678
|
}
|
|
40372
40679
|
async function ensureNeovim() {
|
|
40373
40680
|
try {
|
|
40374
|
-
const nvimPath =
|
|
40681
|
+
const nvimPath = execSync27("which nvim 2>/dev/null || where nvim 2>nul", {
|
|
40375
40682
|
encoding: "utf8",
|
|
40376
40683
|
stdio: "pipe",
|
|
40377
40684
|
timeout: 5e3
|
|
@@ -40383,24 +40690,24 @@ async function ensureNeovim() {
|
|
|
40383
40690
|
const platform6 = process.platform;
|
|
40384
40691
|
const arch2 = process.arch;
|
|
40385
40692
|
if (platform6 === "linux") {
|
|
40386
|
-
const binDir =
|
|
40387
|
-
const nvimDest =
|
|
40693
|
+
const binDir = join54(homedir12(), ".local", "bin");
|
|
40694
|
+
const nvimDest = join54(binDir, "nvim");
|
|
40388
40695
|
try {
|
|
40389
|
-
|
|
40696
|
+
mkdirSync15(binDir, { recursive: true });
|
|
40390
40697
|
} catch {
|
|
40391
40698
|
}
|
|
40392
40699
|
const appImageName = arch2 === "arm64" ? "nvim-linux-arm64.appimage" : "nvim-linux-x86_64.appimage";
|
|
40393
40700
|
const url = `https://github.com/neovim/neovim/releases/latest/download/${appImageName}`;
|
|
40394
40701
|
console.log(` Downloading Neovim (${appImageName})...`);
|
|
40395
40702
|
try {
|
|
40396
|
-
|
|
40397
|
-
|
|
40703
|
+
execSync27(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
|
|
40704
|
+
execSync27(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
|
|
40398
40705
|
} catch (err) {
|
|
40399
40706
|
console.log(` Failed to download Neovim: ${err instanceof Error ? err.message : String(err)}`);
|
|
40400
40707
|
return null;
|
|
40401
40708
|
}
|
|
40402
40709
|
try {
|
|
40403
|
-
const ver =
|
|
40710
|
+
const ver = execSync27(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
|
|
40404
40711
|
console.log(` Installed: ${ver}`);
|
|
40405
40712
|
} catch {
|
|
40406
40713
|
console.log(" Warning: nvim binary downloaded but may not work (missing FUSE? Try: nvim --appimage-extract)");
|
|
@@ -40415,8 +40722,8 @@ async function ensureNeovim() {
|
|
|
40415
40722
|
if (hasCmd("brew")) {
|
|
40416
40723
|
console.log(" Installing Neovim via Homebrew...");
|
|
40417
40724
|
try {
|
|
40418
|
-
|
|
40419
|
-
const nvimPath =
|
|
40725
|
+
execSync27("brew install neovim", { stdio: "inherit", timeout: 12e4 });
|
|
40726
|
+
const nvimPath = execSync27("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
|
|
40420
40727
|
return nvimPath || null;
|
|
40421
40728
|
} catch {
|
|
40422
40729
|
console.log(" brew install neovim failed.");
|
|
@@ -40430,7 +40737,7 @@ async function ensureNeovim() {
|
|
|
40430
40737
|
if (hasCmd("choco")) {
|
|
40431
40738
|
console.log(" Installing Neovim via Chocolatey...");
|
|
40432
40739
|
try {
|
|
40433
|
-
|
|
40740
|
+
execSync27("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
|
|
40434
40741
|
return "nvim";
|
|
40435
40742
|
} catch {
|
|
40436
40743
|
console.log(" choco install neovim failed.");
|
|
@@ -40439,7 +40746,7 @@ async function ensureNeovim() {
|
|
|
40439
40746
|
if (hasCmd("winget")) {
|
|
40440
40747
|
console.log(" Installing Neovim via winget...");
|
|
40441
40748
|
try {
|
|
40442
|
-
|
|
40749
|
+
execSync27("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
|
|
40443
40750
|
stdio: "inherit",
|
|
40444
40751
|
timeout: 12e4
|
|
40445
40752
|
});
|
|
@@ -40455,9 +40762,9 @@ async function ensureNeovim() {
|
|
|
40455
40762
|
}
|
|
40456
40763
|
function ensurePathInShellRc(binDir) {
|
|
40457
40764
|
const shell = process.env.SHELL ?? "";
|
|
40458
|
-
const rcFile = shell.includes("zsh") ?
|
|
40765
|
+
const rcFile = shell.includes("zsh") ? join54(homedir12(), ".zshrc") : join54(homedir12(), ".bashrc");
|
|
40459
40766
|
try {
|
|
40460
|
-
const rcContent =
|
|
40767
|
+
const rcContent = existsSync37(rcFile) ? readFileSync28(rcFile, "utf8") : "";
|
|
40461
40768
|
if (rcContent.includes(binDir))
|
|
40462
40769
|
return;
|
|
40463
40770
|
const exportLine = `
|
|
@@ -41172,7 +41479,7 @@ var init_tui_select = __esm({
|
|
|
41172
41479
|
});
|
|
41173
41480
|
|
|
41174
41481
|
// packages/cli/dist/tui/drop-panel.js
|
|
41175
|
-
import { existsSync as
|
|
41482
|
+
import { existsSync as existsSync38 } from "node:fs";
|
|
41176
41483
|
import { extname as extname10, resolve as resolve29 } from "node:path";
|
|
41177
41484
|
function ansi4(code, text) {
|
|
41178
41485
|
return isTTY4 ? `\x1B[${code}m${text}\x1B[0m` : text;
|
|
@@ -41287,7 +41594,7 @@ function showDropPanel(opts) {
|
|
|
41287
41594
|
filePath = decodeURIComponent(filePath.slice(7));
|
|
41288
41595
|
}
|
|
41289
41596
|
filePath = resolve29(filePath);
|
|
41290
|
-
if (!
|
|
41597
|
+
if (!existsSync38(filePath)) {
|
|
41291
41598
|
errorMsg = `File not found: ${filePath}`;
|
|
41292
41599
|
render();
|
|
41293
41600
|
return;
|
|
@@ -41358,10 +41665,10 @@ var init_drop_panel = __esm({
|
|
|
41358
41665
|
});
|
|
41359
41666
|
|
|
41360
41667
|
// packages/cli/dist/tui/neovim-mode.js
|
|
41361
|
-
import { existsSync as
|
|
41668
|
+
import { existsSync as existsSync39, unlinkSync as unlinkSync8 } from "node:fs";
|
|
41362
41669
|
import { tmpdir as tmpdir8 } from "node:os";
|
|
41363
|
-
import { join as
|
|
41364
|
-
import { execSync as
|
|
41670
|
+
import { join as join55 } from "node:path";
|
|
41671
|
+
import { execSync as execSync28 } from "node:child_process";
|
|
41365
41672
|
function isNeovimActive() {
|
|
41366
41673
|
return _state !== null && !_state.cleanedUp;
|
|
41367
41674
|
}
|
|
@@ -41379,7 +41686,7 @@ async function startNeovimMode(opts) {
|
|
|
41379
41686
|
}
|
|
41380
41687
|
let nvimPath;
|
|
41381
41688
|
try {
|
|
41382
|
-
nvimPath =
|
|
41689
|
+
nvimPath = execSync28("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
|
|
41383
41690
|
if (!nvimPath)
|
|
41384
41691
|
throw new Error();
|
|
41385
41692
|
} catch {
|
|
@@ -41408,10 +41715,10 @@ async function startNeovimMode(opts) {
|
|
|
41408
41715
|
);
|
|
41409
41716
|
} catch {
|
|
41410
41717
|
}
|
|
41411
|
-
const socketPath =
|
|
41718
|
+
const socketPath = join55(tmpdir8(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
|
|
41412
41719
|
try {
|
|
41413
|
-
if (
|
|
41414
|
-
|
|
41720
|
+
if (existsSync39(socketPath))
|
|
41721
|
+
unlinkSync8(socketPath);
|
|
41415
41722
|
} catch {
|
|
41416
41723
|
}
|
|
41417
41724
|
const ptyCols = opts.cols;
|
|
@@ -41637,13 +41944,13 @@ function resizeNeovim(cols, contentRows) {
|
|
|
41637
41944
|
}
|
|
41638
41945
|
async function connectRPC(state, neovimPkg, cols) {
|
|
41639
41946
|
let attempts = 0;
|
|
41640
|
-
while (!
|
|
41947
|
+
while (!existsSync39(state.socketPath) && attempts < 30) {
|
|
41641
41948
|
await new Promise((r) => setTimeout(r, 200));
|
|
41642
41949
|
attempts++;
|
|
41643
41950
|
if (state.cleanedUp)
|
|
41644
41951
|
return;
|
|
41645
41952
|
}
|
|
41646
|
-
if (!
|
|
41953
|
+
if (!existsSync39(state.socketPath))
|
|
41647
41954
|
return;
|
|
41648
41955
|
const nvim = neovimPkg.attach({ socket: state.socketPath });
|
|
41649
41956
|
state.nvim = nvim;
|
|
@@ -41780,8 +42087,8 @@ function doCleanup(state) {
|
|
|
41780
42087
|
state.pty = null;
|
|
41781
42088
|
}
|
|
41782
42089
|
try {
|
|
41783
|
-
if (
|
|
41784
|
-
|
|
42090
|
+
if (existsSync39(state.socketPath))
|
|
42091
|
+
unlinkSync8(state.socketPath);
|
|
41785
42092
|
} catch {
|
|
41786
42093
|
}
|
|
41787
42094
|
if (state.stdinHandler) {
|
|
@@ -41837,10 +42144,10 @@ __export(voice_exports, {
|
|
|
41837
42144
|
registerCustomOnnxModel: () => registerCustomOnnxModel,
|
|
41838
42145
|
resetNarrationContext: () => resetNarrationContext
|
|
41839
42146
|
});
|
|
41840
|
-
import { existsSync as
|
|
41841
|
-
import { join as
|
|
42147
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync16, writeFileSync as writeFileSync17, readFileSync as readFileSync29, unlinkSync as unlinkSync9, readdirSync as readdirSync11, renameSync, statSync as statSync13 } from "node:fs";
|
|
42148
|
+
import { join as join56, dirname as dirname18 } from "node:path";
|
|
41842
42149
|
import { homedir as homedir13, tmpdir as tmpdir9, platform as platform3 } from "node:os";
|
|
41843
|
-
import { execSync as
|
|
42150
|
+
import { execSync as execSync29, spawn as nodeSpawn } from "node:child_process";
|
|
41844
42151
|
import { createRequire } from "node:module";
|
|
41845
42152
|
function sanitizeForTTS(text) {
|
|
41846
42153
|
return text.replace(/^#{1,6}\s+/gm, "").replace(/\*{1,3}([^*]+)\*{1,3}/g, "$1").replace(/_{1,3}([^_]+)_{1,3}/g, "$1").replace(/~~([^~]+)~~/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/```[\s\S]*?```/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/^[\s]*[-*+]\s+/gm, "").replace(/^[\s]*\d+\.\s+/gm, "").replace(/^>\s+/gm, "").replace(/^[-*_]{3,}$/gm, "").replace(/\[[ xX]\]\s*/g, "").replace(/[\u{1F600}-\u{1F64F}]/gu, "").replace(/[\u{1F300}-\u{1F5FF}]/gu, "").replace(/[\u{1F680}-\u{1F6FF}]/gu, "").replace(/[\u{1F1E0}-\u{1F1FF}]/gu, "").replace(/[\u{2600}-\u{26FF}]/gu, "").replace(/[\u{2700}-\u{27BF}]/gu, "").replace(/[\u{FE00}-\u{FE0F}]/gu, "").replace(/[\u{1F900}-\u{1F9FF}]/gu, "").replace(/[\u{1FA00}-\u{1FA6F}]/gu, "").replace(/[\u{1FA70}-\u{1FAFF}]/gu, "").replace(/[\u{200D}]/gu, "").replace(/[\u{20E3}]/gu, "").replace(/[✓✔✗✘✕✖⚠️⏸⏹⏵●○◆◇■□▪▫►▼▲◀⬆⬇⬅➡↑↓←→⇐⇒⇑⇓]/g, "").replace(/[─━│┃┌┐└┘├┤┬┴┼╔╗╚╝╠╣╦╩╬⎿⎾▕▏⏐░▒▓█⠀-⣿]/g, "").replace(/\s{2,}/g, " ").trim();
|
|
@@ -41863,40 +42170,40 @@ function listVoiceModels() {
|
|
|
41863
42170
|
}));
|
|
41864
42171
|
}
|
|
41865
42172
|
function voiceDir() {
|
|
41866
|
-
return
|
|
42173
|
+
return join56(homedir13(), ".open-agents", "voice");
|
|
41867
42174
|
}
|
|
41868
42175
|
function modelsDir() {
|
|
41869
|
-
return
|
|
42176
|
+
return join56(voiceDir(), "models");
|
|
41870
42177
|
}
|
|
41871
42178
|
function modelDir(id) {
|
|
41872
|
-
return
|
|
42179
|
+
return join56(modelsDir(), id);
|
|
41873
42180
|
}
|
|
41874
42181
|
function modelOnnxPath(id) {
|
|
41875
|
-
return
|
|
42182
|
+
return join56(modelDir(id), "model.onnx");
|
|
41876
42183
|
}
|
|
41877
42184
|
function modelConfigPath(id) {
|
|
41878
|
-
return
|
|
42185
|
+
return join56(modelDir(id), "config.json");
|
|
41879
42186
|
}
|
|
41880
42187
|
function luxttsVenvDir() {
|
|
41881
|
-
return
|
|
42188
|
+
return join56(voiceDir(), "luxtts-venv");
|
|
41882
42189
|
}
|
|
41883
42190
|
function luxttsVenvPy() {
|
|
41884
|
-
return platform3() === "win32" ?
|
|
42191
|
+
return platform3() === "win32" ? join56(luxttsVenvDir(), "Scripts", "python.exe") : join56(luxttsVenvDir(), "bin", "python3");
|
|
41885
42192
|
}
|
|
41886
42193
|
function luxttsRepoDir() {
|
|
41887
|
-
return
|
|
42194
|
+
return join56(voiceDir(), "LuxTTS");
|
|
41888
42195
|
}
|
|
41889
42196
|
function luxttsCloneRefsDir() {
|
|
41890
|
-
return
|
|
42197
|
+
return join56(voiceDir(), "clone-refs");
|
|
41891
42198
|
}
|
|
41892
42199
|
function luxttsInferScript() {
|
|
41893
|
-
return
|
|
42200
|
+
return join56(voiceDir(), "luxtts-infer.py");
|
|
41894
42201
|
}
|
|
41895
42202
|
function writeDetectTorchScript(targetPath) {
|
|
41896
|
-
if (
|
|
42203
|
+
if (existsSync40(targetPath))
|
|
41897
42204
|
return;
|
|
41898
42205
|
try {
|
|
41899
|
-
|
|
42206
|
+
mkdirSync16(dirname18(targetPath), { recursive: true });
|
|
41900
42207
|
} catch {
|
|
41901
42208
|
}
|
|
41902
42209
|
const script = `#!/usr/bin/env python3
|
|
@@ -41969,7 +42276,7 @@ def main():
|
|
|
41969
42276
|
if __name__ == "__main__": main()
|
|
41970
42277
|
`;
|
|
41971
42278
|
try {
|
|
41972
|
-
|
|
42279
|
+
writeFileSync17(targetPath, script, { mode: 493 });
|
|
41973
42280
|
} catch {
|
|
41974
42281
|
}
|
|
41975
42282
|
}
|
|
@@ -42779,8 +43086,8 @@ var init_voice = __esm({
|
|
|
42779
43086
|
const refsDir = luxttsCloneRefsDir();
|
|
42780
43087
|
const targets = ["glados", "overwatch"];
|
|
42781
43088
|
for (const modelId of targets) {
|
|
42782
|
-
const refFile =
|
|
42783
|
-
if (
|
|
43089
|
+
const refFile = join56(refsDir, `${modelId}-ref.wav`);
|
|
43090
|
+
if (existsSync40(refFile))
|
|
42784
43091
|
continue;
|
|
42785
43092
|
try {
|
|
42786
43093
|
await this.generateCloneRef(modelId);
|
|
@@ -42859,24 +43166,24 @@ var init_voice = __esm({
|
|
|
42859
43166
|
}
|
|
42860
43167
|
p = p.replace(/\\ /g, " ");
|
|
42861
43168
|
if (p.startsWith("~/") || p === "~") {
|
|
42862
|
-
p =
|
|
43169
|
+
p = join56(homedir13(), p.slice(1));
|
|
42863
43170
|
}
|
|
42864
|
-
if (!
|
|
43171
|
+
if (!existsSync40(p)) {
|
|
42865
43172
|
return `File not found: ${p}
|
|
42866
43173
|
(original input: ${audioPath})`;
|
|
42867
43174
|
}
|
|
42868
43175
|
audioPath = p;
|
|
42869
43176
|
const refsDir = luxttsCloneRefsDir();
|
|
42870
|
-
if (!
|
|
42871
|
-
|
|
43177
|
+
if (!existsSync40(refsDir))
|
|
43178
|
+
mkdirSync16(refsDir, { recursive: true });
|
|
42872
43179
|
const ext = audioPath.split(".").pop() || "wav";
|
|
42873
43180
|
const srcName = (audioPath.split("/").pop() ?? "clone").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
42874
43181
|
const ts = Date.now().toString(36);
|
|
42875
43182
|
const destFilename = `clone-${srcName}-${ts}.${ext}`;
|
|
42876
|
-
const destPath =
|
|
43183
|
+
const destPath = join56(refsDir, destFilename);
|
|
42877
43184
|
try {
|
|
42878
|
-
const data =
|
|
42879
|
-
|
|
43185
|
+
const data = readFileSync29(audioPath);
|
|
43186
|
+
writeFileSync17(destPath, data);
|
|
42880
43187
|
} catch (err) {
|
|
42881
43188
|
return `Failed to copy audio file: ${err instanceof Error ? err.message : String(err)}`;
|
|
42882
43189
|
}
|
|
@@ -42916,9 +43223,9 @@ var init_voice = __esm({
|
|
|
42916
43223
|
return `Failed to synthesize reference audio from ${source.label}.`;
|
|
42917
43224
|
}
|
|
42918
43225
|
const refsDir = luxttsCloneRefsDir();
|
|
42919
|
-
if (!
|
|
42920
|
-
|
|
42921
|
-
const destPath =
|
|
43226
|
+
if (!existsSync40(refsDir))
|
|
43227
|
+
mkdirSync16(refsDir, { recursive: true });
|
|
43228
|
+
const destPath = join56(refsDir, `${sourceModelId}-ref.wav`);
|
|
42922
43229
|
const sampleRate = this.config?.audio?.sample_rate ?? 22050;
|
|
42923
43230
|
this.writeWav(audioData, sampleRate, destPath);
|
|
42924
43231
|
this.luxttsCloneRef = destPath;
|
|
@@ -42934,23 +43241,23 @@ var init_voice = __esm({
|
|
|
42934
43241
|
// -------------------------------------------------------------------------
|
|
42935
43242
|
/** Metadata file for friendly names of clone refs */
|
|
42936
43243
|
static cloneMetaFile() {
|
|
42937
|
-
return
|
|
43244
|
+
return join56(luxttsCloneRefsDir(), "meta.json");
|
|
42938
43245
|
}
|
|
42939
43246
|
loadCloneMeta() {
|
|
42940
43247
|
const p = _VoiceEngine.cloneMetaFile();
|
|
42941
|
-
if (!
|
|
43248
|
+
if (!existsSync40(p))
|
|
42942
43249
|
return {};
|
|
42943
43250
|
try {
|
|
42944
|
-
return JSON.parse(
|
|
43251
|
+
return JSON.parse(readFileSync29(p, "utf8"));
|
|
42945
43252
|
} catch {
|
|
42946
43253
|
return {};
|
|
42947
43254
|
}
|
|
42948
43255
|
}
|
|
42949
43256
|
saveCloneMeta(meta) {
|
|
42950
43257
|
const dir = luxttsCloneRefsDir();
|
|
42951
|
-
if (!
|
|
42952
|
-
|
|
42953
|
-
|
|
43258
|
+
if (!existsSync40(dir))
|
|
43259
|
+
mkdirSync16(dir, { recursive: true });
|
|
43260
|
+
writeFileSync17(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
|
|
42954
43261
|
}
|
|
42955
43262
|
/** Audio file extensions recognized as clone references */
|
|
42956
43263
|
static AUDIO_EXTS = /* @__PURE__ */ new Set(["wav", "mp3", "ogg", "flac", "m4a", "opus", "aac"]);
|
|
@@ -42960,15 +43267,15 @@ var init_voice = __esm({
|
|
|
42960
43267
|
*/
|
|
42961
43268
|
listCloneRefs() {
|
|
42962
43269
|
const dir = luxttsCloneRefsDir();
|
|
42963
|
-
if (!
|
|
43270
|
+
if (!existsSync40(dir))
|
|
42964
43271
|
return [];
|
|
42965
43272
|
const meta = this.loadCloneMeta();
|
|
42966
|
-
const files =
|
|
43273
|
+
const files = readdirSync11(dir).filter((f) => {
|
|
42967
43274
|
const ext = f.split(".").pop()?.toLowerCase() ?? "";
|
|
42968
43275
|
return _VoiceEngine.AUDIO_EXTS.has(ext);
|
|
42969
43276
|
});
|
|
42970
43277
|
return files.map((f) => {
|
|
42971
|
-
const p =
|
|
43278
|
+
const p = join56(dir, f);
|
|
42972
43279
|
let size = 0;
|
|
42973
43280
|
try {
|
|
42974
43281
|
size = statSync13(p).size;
|
|
@@ -42985,11 +43292,11 @@ var init_voice = __esm({
|
|
|
42985
43292
|
}
|
|
42986
43293
|
/** Delete a clone reference file by filename. Returns true if deleted. */
|
|
42987
43294
|
deleteCloneRef(filename) {
|
|
42988
|
-
const p =
|
|
42989
|
-
if (!
|
|
43295
|
+
const p = join56(luxttsCloneRefsDir(), filename);
|
|
43296
|
+
if (!existsSync40(p))
|
|
42990
43297
|
return false;
|
|
42991
43298
|
try {
|
|
42992
|
-
|
|
43299
|
+
unlinkSync9(p);
|
|
42993
43300
|
const meta = this.loadCloneMeta();
|
|
42994
43301
|
delete meta[filename];
|
|
42995
43302
|
this.saveCloneMeta(meta);
|
|
@@ -43010,8 +43317,8 @@ var init_voice = __esm({
|
|
|
43010
43317
|
}
|
|
43011
43318
|
/** Set the active clone reference by filename. */
|
|
43012
43319
|
setActiveCloneRef(filename) {
|
|
43013
|
-
const p =
|
|
43014
|
-
if (!
|
|
43320
|
+
const p = join56(luxttsCloneRefsDir(), filename);
|
|
43321
|
+
if (!existsSync40(p))
|
|
43015
43322
|
return `File not found: ${filename}`;
|
|
43016
43323
|
this.luxttsCloneRef = p;
|
|
43017
43324
|
return `Active clone voice set to: ${filename}`;
|
|
@@ -43267,7 +43574,7 @@ var init_voice = __esm({
|
|
|
43267
43574
|
}
|
|
43268
43575
|
if (prefetchedWav) {
|
|
43269
43576
|
try {
|
|
43270
|
-
|
|
43577
|
+
unlinkSync9(prefetchedWav.path);
|
|
43271
43578
|
} catch {
|
|
43272
43579
|
}
|
|
43273
43580
|
}
|
|
@@ -43336,11 +43643,11 @@ var init_voice = __esm({
|
|
|
43336
43643
|
}
|
|
43337
43644
|
this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
|
|
43338
43645
|
}
|
|
43339
|
-
const wavPath =
|
|
43646
|
+
const wavPath = join56(tmpdir9(), `oa-voice-${Date.now()}.wav`);
|
|
43340
43647
|
this.writeStereoWav(stereo.left, stereo.right, sampleRate, wavPath);
|
|
43341
43648
|
await this.playWav(wavPath);
|
|
43342
43649
|
try {
|
|
43343
|
-
|
|
43650
|
+
unlinkSync9(wavPath);
|
|
43344
43651
|
} catch {
|
|
43345
43652
|
}
|
|
43346
43653
|
}
|
|
@@ -43453,7 +43760,7 @@ var init_voice = __esm({
|
|
|
43453
43760
|
buffer.writeInt16LE(rSample < 0 ? rSample * 32768 : rSample * 32767, pos);
|
|
43454
43761
|
pos += 2;
|
|
43455
43762
|
}
|
|
43456
|
-
|
|
43763
|
+
writeFileSync17(path, buffer);
|
|
43457
43764
|
}
|
|
43458
43765
|
// -------------------------------------------------------------------------
|
|
43459
43766
|
// Phonemization
|
|
@@ -43531,7 +43838,7 @@ var init_voice = __esm({
|
|
|
43531
43838
|
return buffer;
|
|
43532
43839
|
}
|
|
43533
43840
|
writeWav(samples, sampleRate, path) {
|
|
43534
|
-
|
|
43841
|
+
writeFileSync17(path, this.buildWavBuffer(samples, sampleRate));
|
|
43535
43842
|
}
|
|
43536
43843
|
// -------------------------------------------------------------------------
|
|
43537
43844
|
// Audio playback (system default speakers)
|
|
@@ -43581,7 +43888,7 @@ var init_voice = __esm({
|
|
|
43581
43888
|
}
|
|
43582
43889
|
for (const player of ["paplay", "pw-play", "aplay"]) {
|
|
43583
43890
|
try {
|
|
43584
|
-
|
|
43891
|
+
execSync29(`which ${player}`, { stdio: "pipe" });
|
|
43585
43892
|
return [player, path];
|
|
43586
43893
|
} catch {
|
|
43587
43894
|
}
|
|
@@ -43610,7 +43917,7 @@ var init_voice = __esm({
|
|
|
43610
43917
|
return this.python3Path;
|
|
43611
43918
|
for (const bin of ["python3", "python"]) {
|
|
43612
43919
|
try {
|
|
43613
|
-
const path =
|
|
43920
|
+
const path = execSync29(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
|
|
43614
43921
|
if (path) {
|
|
43615
43922
|
this.python3Path = path;
|
|
43616
43923
|
return path;
|
|
@@ -43676,7 +43983,7 @@ var init_voice = __esm({
|
|
|
43676
43983
|
return false;
|
|
43677
43984
|
}
|
|
43678
43985
|
try {
|
|
43679
|
-
|
|
43986
|
+
execSync29(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
|
|
43680
43987
|
this.mlxInstalled = true;
|
|
43681
43988
|
return true;
|
|
43682
43989
|
} catch {
|
|
@@ -43729,7 +44036,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
43729
44036
|
const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
|
|
43730
44037
|
const mlxVoice = model.mlxVoice ?? "af_heart";
|
|
43731
44038
|
const mlxLangCode = model.mlxLangCode ?? "a";
|
|
43732
|
-
const wavPath =
|
|
44039
|
+
const wavPath = join56(tmpdir9(), `oa-mlx-${Date.now()}.wav`);
|
|
43733
44040
|
const pyScript = [
|
|
43734
44041
|
"import sys, json",
|
|
43735
44042
|
"from mlx_audio.tts import generate as tts_gen",
|
|
@@ -43737,20 +44044,20 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
43737
44044
|
`tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
|
|
43738
44045
|
].join("; ");
|
|
43739
44046
|
try {
|
|
43740
|
-
|
|
44047
|
+
execSync29(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
|
|
43741
44048
|
} catch (err) {
|
|
43742
44049
|
try {
|
|
43743
44050
|
const safeText = cleaned.replace(/'/g, "'\\''");
|
|
43744
|
-
|
|
44051
|
+
execSync29(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
|
|
43745
44052
|
} catch (err2) {
|
|
43746
44053
|
return;
|
|
43747
44054
|
}
|
|
43748
44055
|
}
|
|
43749
|
-
if (!
|
|
44056
|
+
if (!existsSync40(wavPath))
|
|
43750
44057
|
return;
|
|
43751
44058
|
if (volume !== 1) {
|
|
43752
44059
|
try {
|
|
43753
|
-
const wavData =
|
|
44060
|
+
const wavData = readFileSync29(wavPath);
|
|
43754
44061
|
if (wavData.length > 44) {
|
|
43755
44062
|
const header = wavData.subarray(0, 44);
|
|
43756
44063
|
const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
|
|
@@ -43758,14 +44065,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
43758
44065
|
samples[i] = Math.round(samples[i] * volume);
|
|
43759
44066
|
}
|
|
43760
44067
|
const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
|
|
43761
|
-
|
|
44068
|
+
writeFileSync17(wavPath, scaled);
|
|
43762
44069
|
}
|
|
43763
44070
|
} catch {
|
|
43764
44071
|
}
|
|
43765
44072
|
}
|
|
43766
44073
|
if (this.onPCMOutput) {
|
|
43767
44074
|
try {
|
|
43768
|
-
const wavData =
|
|
44075
|
+
const wavData = readFileSync29(wavPath);
|
|
43769
44076
|
if (wavData.length > 44) {
|
|
43770
44077
|
const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
|
|
43771
44078
|
const sampleRate = wavData.readUInt32LE(24);
|
|
@@ -43776,7 +44083,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
43776
44083
|
}
|
|
43777
44084
|
await this.playWav(wavPath);
|
|
43778
44085
|
try {
|
|
43779
|
-
|
|
44086
|
+
unlinkSync9(wavPath);
|
|
43780
44087
|
} catch {
|
|
43781
44088
|
}
|
|
43782
44089
|
}
|
|
@@ -43797,7 +44104,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
43797
44104
|
const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
|
|
43798
44105
|
const mlxVoice = model.mlxVoice ?? "af_heart";
|
|
43799
44106
|
const mlxLangCode = model.mlxLangCode ?? "a";
|
|
43800
|
-
const wavPath =
|
|
44107
|
+
const wavPath = join56(tmpdir9(), `oa-mlx-buf-${Date.now()}.wav`);
|
|
43801
44108
|
const pyScript = [
|
|
43802
44109
|
"import sys, json",
|
|
43803
44110
|
"from mlx_audio.tts import generate as tts_gen",
|
|
@@ -43805,20 +44112,20 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
43805
44112
|
`tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
|
|
43806
44113
|
].join("; ");
|
|
43807
44114
|
try {
|
|
43808
|
-
|
|
44115
|
+
execSync29(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
|
|
43809
44116
|
} catch {
|
|
43810
44117
|
try {
|
|
43811
44118
|
const safeText = cleaned.replace(/'/g, "'\\''");
|
|
43812
|
-
|
|
44119
|
+
execSync29(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
|
|
43813
44120
|
} catch {
|
|
43814
44121
|
return null;
|
|
43815
44122
|
}
|
|
43816
44123
|
}
|
|
43817
|
-
if (!
|
|
44124
|
+
if (!existsSync40(wavPath))
|
|
43818
44125
|
return null;
|
|
43819
44126
|
try {
|
|
43820
|
-
const data =
|
|
43821
|
-
|
|
44127
|
+
const data = readFileSync29(wavPath);
|
|
44128
|
+
unlinkSync9(wavPath);
|
|
43822
44129
|
return data;
|
|
43823
44130
|
} catch {
|
|
43824
44131
|
return null;
|
|
@@ -43840,7 +44147,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
43840
44147
|
}
|
|
43841
44148
|
const venvDir = luxttsVenvDir();
|
|
43842
44149
|
const venvPy = luxttsVenvPy();
|
|
43843
|
-
if (
|
|
44150
|
+
if (existsSync40(venvPy)) {
|
|
43844
44151
|
try {
|
|
43845
44152
|
await this.asyncShell(`${venvPy} -c "import sys; sys.path.insert(0, '${luxttsRepoDir()}'); from zipvoice.luxvoice import LuxTTS; print('ok')"`, 3e4);
|
|
43846
44153
|
let hasCudaSys = false;
|
|
@@ -43854,7 +44161,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
43854
44161
|
if (torchCheck === "cpu") {
|
|
43855
44162
|
renderWarning("GPU detected but PyTorch is CPU-only. Reinstalling with CUDA support in background...");
|
|
43856
44163
|
try {
|
|
43857
|
-
const detectScript =
|
|
44164
|
+
const detectScript = join56(voiceDir(), "detect-torch.py");
|
|
43858
44165
|
writeDetectTorchScript(detectScript);
|
|
43859
44166
|
let pipArgs = `torch torchaudio --index-url https://download.pytorch.org/whl/cu124`;
|
|
43860
44167
|
try {
|
|
@@ -43879,7 +44186,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
43879
44186
|
}
|
|
43880
44187
|
}
|
|
43881
44188
|
renderInfo("Setting up LuxTTS voice cloning (first-time setup, this takes several minutes)...");
|
|
43882
|
-
if (!
|
|
44189
|
+
if (!existsSync40(venvDir)) {
|
|
43883
44190
|
renderInfo(" Creating Python virtual environment...");
|
|
43884
44191
|
try {
|
|
43885
44192
|
await this.asyncShell(`${py} -m venv ${JSON.stringify(venvDir)}`, 6e4);
|
|
@@ -43888,7 +44195,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
43888
44195
|
}
|
|
43889
44196
|
}
|
|
43890
44197
|
{
|
|
43891
|
-
const detectScript =
|
|
44198
|
+
const detectScript = join56(voiceDir(), "detect-torch.py");
|
|
43892
44199
|
writeDetectTorchScript(detectScript);
|
|
43893
44200
|
let pipArgsStr = "torch torchaudio";
|
|
43894
44201
|
let torchDesc = "unknown platform";
|
|
@@ -43925,10 +44232,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
43925
44232
|
}
|
|
43926
44233
|
}
|
|
43927
44234
|
const repoDir = luxttsRepoDir();
|
|
43928
|
-
if (!
|
|
44235
|
+
if (!existsSync40(join56(repoDir, "zipvoice", "luxvoice.py"))) {
|
|
43929
44236
|
renderInfo(" Cloning LuxTTS repository...");
|
|
43930
44237
|
try {
|
|
43931
|
-
if (
|
|
44238
|
+
if (existsSync40(repoDir)) {
|
|
43932
44239
|
const rmCmd = process.platform === "win32" ? `rmdir /s /q ${JSON.stringify(repoDir)}` : `rm -rf ${JSON.stringify(repoDir)}`;
|
|
43933
44240
|
await this.asyncShell(rmCmd, 3e4);
|
|
43934
44241
|
}
|
|
@@ -43967,7 +44274,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
43967
44274
|
renderWarning(` Could not install system build deps: ${err instanceof Error ? err.message : String(err)}`);
|
|
43968
44275
|
}
|
|
43969
44276
|
}
|
|
43970
|
-
const isJetson = isArm && (
|
|
44277
|
+
const isJetson = isArm && (existsSync40("/etc/nv_tegra_release") || existsSync40("/usr/local/cuda/targets/aarch64-linux") || (process.env.JETSON_L4T_VERSION ?? "") !== "");
|
|
43971
44278
|
const installSteps = isArm ? [
|
|
43972
44279
|
// ARM: install individually so we get clear error messages per package.
|
|
43973
44280
|
// ALL are fatal because LuxTTS hard-imports them (no lazy/optional imports).
|
|
@@ -44035,14 +44342,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
44035
44342
|
}
|
|
44036
44343
|
/** Auto-detect an existing clone reference in the refs directory */
|
|
44037
44344
|
autoDetectCloneRef() {
|
|
44038
|
-
if (this.luxttsCloneRef &&
|
|
44345
|
+
if (this.luxttsCloneRef && existsSync40(this.luxttsCloneRef))
|
|
44039
44346
|
return;
|
|
44040
44347
|
const refsDir = luxttsCloneRefsDir();
|
|
44041
|
-
if (!
|
|
44348
|
+
if (!existsSync40(refsDir))
|
|
44042
44349
|
return;
|
|
44043
44350
|
for (const name of ["custom-clone.wav", "custom-clone.mp3", "glados-ref.wav", "overwatch-ref.wav"]) {
|
|
44044
|
-
const p =
|
|
44045
|
-
if (
|
|
44351
|
+
const p = join56(refsDir, name);
|
|
44352
|
+
if (existsSync40(p)) {
|
|
44046
44353
|
this.luxttsCloneRef = p;
|
|
44047
44354
|
return;
|
|
44048
44355
|
}
|
|
@@ -44142,15 +44449,15 @@ if __name__ == '__main__':
|
|
|
44142
44449
|
main()
|
|
44143
44450
|
`;
|
|
44144
44451
|
const scriptPath2 = luxttsInferScript();
|
|
44145
|
-
|
|
44146
|
-
|
|
44452
|
+
mkdirSync16(voiceDir(), { recursive: true });
|
|
44453
|
+
writeFileSync17(scriptPath2, script);
|
|
44147
44454
|
}
|
|
44148
44455
|
/** Ensure the LuxTTS daemon is running, spawn if needed */
|
|
44149
44456
|
async ensureLuxttsDaemon() {
|
|
44150
44457
|
if (this._luxttsDaemon && !this._luxttsDaemon.killed)
|
|
44151
44458
|
return true;
|
|
44152
44459
|
const venvPy = luxttsVenvPy();
|
|
44153
|
-
if (!
|
|
44460
|
+
if (!existsSync40(venvPy))
|
|
44154
44461
|
return false;
|
|
44155
44462
|
return new Promise((resolve34) => {
|
|
44156
44463
|
const env = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
|
|
@@ -44234,7 +44541,7 @@ if __name__ == '__main__':
|
|
|
44234
44541
|
* Used by drainQueue's pre-fetch pipeline for gapless back-to-back playback.
|
|
44235
44542
|
*/
|
|
44236
44543
|
async synthesizeLuxttsWav(text, speedFactor = 1) {
|
|
44237
|
-
if (!this.luxttsCloneRef || !
|
|
44544
|
+
if (!this.luxttsCloneRef || !existsSync40(this.luxttsCloneRef))
|
|
44238
44545
|
return null;
|
|
44239
44546
|
const cleaned = text.replace(/\*/g, "").trim();
|
|
44240
44547
|
if (!cleaned)
|
|
@@ -44242,7 +44549,7 @@ if __name__ == '__main__':
|
|
|
44242
44549
|
const ready = await this.ensureLuxttsDaemon();
|
|
44243
44550
|
if (!ready)
|
|
44244
44551
|
return null;
|
|
44245
|
-
const wavPath =
|
|
44552
|
+
const wavPath = join56(tmpdir9(), `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
|
|
44246
44553
|
try {
|
|
44247
44554
|
await this.luxttsRequest({
|
|
44248
44555
|
action: "synthesize",
|
|
@@ -44254,17 +44561,17 @@ if __name__ == '__main__':
|
|
|
44254
44561
|
} catch {
|
|
44255
44562
|
return null;
|
|
44256
44563
|
}
|
|
44257
|
-
return
|
|
44564
|
+
return existsSync40(wavPath) ? wavPath : null;
|
|
44258
44565
|
}
|
|
44259
44566
|
/**
|
|
44260
44567
|
* Post-process (fade-in, volume, pitch, stereo) and play a LuxTTS WAV file.
|
|
44261
44568
|
* Cleans up the WAV file after playback.
|
|
44262
44569
|
*/
|
|
44263
44570
|
async postProcessAndPlayLuxtts(wavPath, volume = 1, pitchFactor = 1, stereoDelayMs = 0.6) {
|
|
44264
|
-
if (!
|
|
44571
|
+
if (!existsSync40(wavPath))
|
|
44265
44572
|
return;
|
|
44266
44573
|
try {
|
|
44267
|
-
const wavData =
|
|
44574
|
+
const wavData = readFileSync29(wavPath);
|
|
44268
44575
|
if (wavData.length > 44) {
|
|
44269
44576
|
const sampleRate = wavData.readUInt32LE(24);
|
|
44270
44577
|
const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
|
|
@@ -44279,13 +44586,13 @@ if __name__ == '__main__':
|
|
|
44279
44586
|
}
|
|
44280
44587
|
const header = wavData.subarray(0, 44);
|
|
44281
44588
|
const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
|
|
44282
|
-
|
|
44589
|
+
writeFileSync17(wavPath, scaled);
|
|
44283
44590
|
}
|
|
44284
44591
|
} catch {
|
|
44285
44592
|
}
|
|
44286
44593
|
if (pitchFactor !== 1) {
|
|
44287
44594
|
try {
|
|
44288
|
-
const wavData =
|
|
44595
|
+
const wavData = readFileSync29(wavPath);
|
|
44289
44596
|
if (wavData.length > 44) {
|
|
44290
44597
|
const int16 = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
|
|
44291
44598
|
const float32 = new Float32Array(int16.length);
|
|
@@ -44300,7 +44607,7 @@ if __name__ == '__main__':
|
|
|
44300
44607
|
}
|
|
44301
44608
|
if (this.onPCMOutput) {
|
|
44302
44609
|
try {
|
|
44303
|
-
const wavData =
|
|
44610
|
+
const wavData = readFileSync29(wavPath);
|
|
44304
44611
|
if (wavData.length > 44) {
|
|
44305
44612
|
const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
|
|
44306
44613
|
const sampleRate = wavData.readUInt32LE(24);
|
|
@@ -44311,7 +44618,7 @@ if __name__ == '__main__':
|
|
|
44311
44618
|
}
|
|
44312
44619
|
if (stereoDelayMs > 0) {
|
|
44313
44620
|
try {
|
|
44314
|
-
const wavData =
|
|
44621
|
+
const wavData = readFileSync29(wavPath);
|
|
44315
44622
|
if (wavData.length > 44) {
|
|
44316
44623
|
const sampleRate = wavData.readUInt32LE(24);
|
|
44317
44624
|
const numChannels = wavData.readUInt16LE(22);
|
|
@@ -44331,7 +44638,7 @@ if __name__ == '__main__':
|
|
|
44331
44638
|
await this.playWav(wavPath);
|
|
44332
44639
|
await this.sleep(150);
|
|
44333
44640
|
try {
|
|
44334
|
-
|
|
44641
|
+
unlinkSync9(wavPath);
|
|
44335
44642
|
} catch {
|
|
44336
44643
|
}
|
|
44337
44644
|
}
|
|
@@ -44347,7 +44654,7 @@ if __name__ == '__main__':
|
|
|
44347
44654
|
* Used for Telegram voice messages and WebSocket streaming.
|
|
44348
44655
|
*/
|
|
44349
44656
|
async synthesizeLuxttsToBuffer(text) {
|
|
44350
|
-
if (!this.luxttsCloneRef || !
|
|
44657
|
+
if (!this.luxttsCloneRef || !existsSync40(this.luxttsCloneRef))
|
|
44351
44658
|
return null;
|
|
44352
44659
|
const cleaned = text.replace(/\*/g, "").trim();
|
|
44353
44660
|
if (!cleaned)
|
|
@@ -44355,7 +44662,7 @@ if __name__ == '__main__':
|
|
|
44355
44662
|
const ready = await this.ensureLuxttsDaemon();
|
|
44356
44663
|
if (!ready)
|
|
44357
44664
|
return null;
|
|
44358
|
-
const wavPath =
|
|
44665
|
+
const wavPath = join56(tmpdir9(), `oa-luxtts-buf-${Date.now()}.wav`);
|
|
44359
44666
|
try {
|
|
44360
44667
|
await this.luxttsRequest({
|
|
44361
44668
|
action: "synthesize",
|
|
@@ -44367,11 +44674,11 @@ if __name__ == '__main__':
|
|
|
44367
44674
|
} catch {
|
|
44368
44675
|
return null;
|
|
44369
44676
|
}
|
|
44370
|
-
if (!
|
|
44677
|
+
if (!existsSync40(wavPath))
|
|
44371
44678
|
return null;
|
|
44372
44679
|
try {
|
|
44373
|
-
const data =
|
|
44374
|
-
|
|
44680
|
+
const data = readFileSync29(wavPath);
|
|
44681
|
+
unlinkSync9(wavPath);
|
|
44375
44682
|
return data;
|
|
44376
44683
|
} catch {
|
|
44377
44684
|
return null;
|
|
@@ -44384,40 +44691,40 @@ if __name__ == '__main__':
|
|
|
44384
44691
|
if (this.ort)
|
|
44385
44692
|
return;
|
|
44386
44693
|
const arch2 = process.arch;
|
|
44387
|
-
|
|
44388
|
-
const pkgPath =
|
|
44694
|
+
mkdirSync16(voiceDir(), { recursive: true });
|
|
44695
|
+
const pkgPath = join56(voiceDir(), "package.json");
|
|
44389
44696
|
const expectedDeps = {
|
|
44390
44697
|
"onnxruntime-node": "^1.21.0",
|
|
44391
44698
|
"phonemizer": "^1.2.1"
|
|
44392
44699
|
};
|
|
44393
|
-
if (
|
|
44700
|
+
if (existsSync40(pkgPath)) {
|
|
44394
44701
|
try {
|
|
44395
|
-
const existing = JSON.parse(
|
|
44702
|
+
const existing = JSON.parse(readFileSync29(pkgPath, "utf8"));
|
|
44396
44703
|
if (!existing.dependencies?.["phonemizer"]) {
|
|
44397
44704
|
existing.dependencies = { ...existing.dependencies, ...expectedDeps };
|
|
44398
|
-
|
|
44705
|
+
writeFileSync17(pkgPath, JSON.stringify(existing, null, 2));
|
|
44399
44706
|
}
|
|
44400
44707
|
} catch {
|
|
44401
44708
|
}
|
|
44402
44709
|
}
|
|
44403
|
-
if (!
|
|
44404
|
-
|
|
44710
|
+
if (!existsSync40(pkgPath)) {
|
|
44711
|
+
writeFileSync17(pkgPath, JSON.stringify({
|
|
44405
44712
|
name: "open-agents-voice",
|
|
44406
44713
|
private: true,
|
|
44407
44714
|
dependencies: expectedDeps
|
|
44408
44715
|
}, null, 2));
|
|
44409
44716
|
}
|
|
44410
|
-
const voiceRequire = createRequire(
|
|
44717
|
+
const voiceRequire = createRequire(join56(voiceDir(), "index.js"));
|
|
44411
44718
|
const probeOnnx = async () => {
|
|
44412
44719
|
try {
|
|
44413
|
-
const output = await this.asyncShell(`NODE_PATH="${
|
|
44720
|
+
const output = await this.asyncShell(`NODE_PATH="${join56(voiceDir(), "node_modules")}" node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, 15e3);
|
|
44414
44721
|
return output.trim() === "OK";
|
|
44415
44722
|
} catch {
|
|
44416
44723
|
return false;
|
|
44417
44724
|
}
|
|
44418
44725
|
};
|
|
44419
|
-
const onnxNodeModules =
|
|
44420
|
-
const onnxInstalled =
|
|
44726
|
+
const onnxNodeModules = join56(voiceDir(), "node_modules", "onnxruntime-node");
|
|
44727
|
+
const onnxInstalled = existsSync40(onnxNodeModules);
|
|
44421
44728
|
if (onnxInstalled && !await probeOnnx()) {
|
|
44422
44729
|
throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch2}). 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.`);
|
|
44423
44730
|
}
|
|
@@ -44467,18 +44774,18 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
44467
44774
|
const dir = modelDir(id);
|
|
44468
44775
|
const onnxPath = modelOnnxPath(id);
|
|
44469
44776
|
const configPath = modelConfigPath(id);
|
|
44470
|
-
if (
|
|
44777
|
+
if (existsSync40(onnxPath) && existsSync40(configPath))
|
|
44471
44778
|
return;
|
|
44472
|
-
|
|
44473
|
-
if (!
|
|
44779
|
+
mkdirSync16(dir, { recursive: true });
|
|
44780
|
+
if (!existsSync40(configPath)) {
|
|
44474
44781
|
renderInfo(`Downloading ${model.label} voice config...`);
|
|
44475
44782
|
const configResp = await fetch(model.configUrl);
|
|
44476
44783
|
if (!configResp.ok)
|
|
44477
44784
|
throw new Error(`Failed to download config: HTTP ${configResp.status}`);
|
|
44478
44785
|
const configText = await configResp.text();
|
|
44479
|
-
|
|
44786
|
+
writeFileSync17(configPath, configText);
|
|
44480
44787
|
}
|
|
44481
|
-
if (!
|
|
44788
|
+
if (!existsSync40(onnxPath)) {
|
|
44482
44789
|
renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
|
|
44483
44790
|
const onnxResp = await fetch(model.onnxUrl);
|
|
44484
44791
|
if (!onnxResp.ok)
|
|
@@ -44503,7 +44810,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
44503
44810
|
}
|
|
44504
44811
|
}
|
|
44505
44812
|
const fullBuffer = Buffer.concat(chunks);
|
|
44506
|
-
|
|
44813
|
+
writeFileSync17(onnxPath, fullBuffer);
|
|
44507
44814
|
renderInfo(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
|
|
44508
44815
|
}
|
|
44509
44816
|
}
|
|
@@ -44515,10 +44822,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
44515
44822
|
throw new Error("ONNX runtime not loaded");
|
|
44516
44823
|
const onnxPath = modelOnnxPath(this.modelId);
|
|
44517
44824
|
const configPath = modelConfigPath(this.modelId);
|
|
44518
|
-
if (!
|
|
44825
|
+
if (!existsSync40(onnxPath) || !existsSync40(configPath)) {
|
|
44519
44826
|
throw new Error(`Model files not found for ${this.modelId}`);
|
|
44520
44827
|
}
|
|
44521
|
-
this.config = JSON.parse(
|
|
44828
|
+
this.config = JSON.parse(readFileSync29(configPath, "utf8"));
|
|
44522
44829
|
this.session = await this.ort.InferenceSession.create(onnxPath, {
|
|
44523
44830
|
executionProviders: ["cpu"],
|
|
44524
44831
|
graphOptimizationLevel: "all"
|
|
@@ -44545,8 +44852,8 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
44545
44852
|
// packages/cli/dist/tui/commands.js
|
|
44546
44853
|
import * as nodeOs from "node:os";
|
|
44547
44854
|
import { execSync as nodeExecSync } from "node:child_process";
|
|
44548
|
-
import { existsSync as
|
|
44549
|
-
import { join as
|
|
44855
|
+
import { existsSync as existsSync41, readFileSync as readFileSync30, writeFileSync as writeFileSync18, mkdirSync as mkdirSync17, readdirSync as readdirSync12, statSync as statSync14, rmSync } from "node:fs";
|
|
44856
|
+
import { join as join57 } from "node:path";
|
|
44550
44857
|
function safeLog(text) {
|
|
44551
44858
|
if (isNeovimActive()) {
|
|
44552
44859
|
writeToNeovimOutput(text + "\n");
|
|
@@ -45155,22 +45462,22 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45155
45462
|
let content = "";
|
|
45156
45463
|
let metadata = {};
|
|
45157
45464
|
if (shareType === "tool") {
|
|
45158
|
-
const toolDir =
|
|
45159
|
-
const toolFile =
|
|
45160
|
-
if (!
|
|
45465
|
+
const toolDir = join57(ctx.repoRoot, ".oa", "tools");
|
|
45466
|
+
const toolFile = join57(toolDir, shareName.endsWith(".json") ? shareName : `${shareName}.json`);
|
|
45467
|
+
if (!existsSync41(toolFile)) {
|
|
45161
45468
|
renderWarning(`Tool not found: ${toolFile}`);
|
|
45162
45469
|
return "handled";
|
|
45163
45470
|
}
|
|
45164
|
-
content =
|
|
45471
|
+
content = readFileSync30(toolFile, "utf8");
|
|
45165
45472
|
metadata = { type: "tool", name: shareName };
|
|
45166
45473
|
} else if (shareType === "skill") {
|
|
45167
|
-
const skillDir =
|
|
45168
|
-
const skillFile =
|
|
45169
|
-
if (!
|
|
45474
|
+
const skillDir = join57(ctx.repoRoot, ".oa", "skills", shareName);
|
|
45475
|
+
const skillFile = join57(skillDir, "SKILL.md");
|
|
45476
|
+
if (!existsSync41(skillFile)) {
|
|
45170
45477
|
renderWarning(`Skill not found: ${skillFile}`);
|
|
45171
45478
|
return "handled";
|
|
45172
45479
|
}
|
|
45173
|
-
content =
|
|
45480
|
+
content = readFileSync30(skillFile, "utf8");
|
|
45174
45481
|
metadata = { type: "skill", name: shareName };
|
|
45175
45482
|
} else {
|
|
45176
45483
|
renderWarning(`Unknown share type: ${shareType}. Use 'tool' or 'skill'.`);
|
|
@@ -45209,9 +45516,9 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45209
45516
|
const { NexusTool: NexusTool2 } = __require("@open-agents/execution");
|
|
45210
45517
|
const nexus = new NexusTool2(ctx.repoRoot);
|
|
45211
45518
|
await nexus.execute({ action: "ipfs_pin", cid: importCid, source: "import" });
|
|
45212
|
-
const regFile =
|
|
45213
|
-
if (
|
|
45214
|
-
const reg = JSON.parse(
|
|
45519
|
+
const regFile = join57(ctx.repoRoot, ".oa", "nexus", "ipfs", "cid-registry", "learning-cids.json");
|
|
45520
|
+
if (existsSync41(regFile)) {
|
|
45521
|
+
const reg = JSON.parse(readFileSync30(regFile, "utf8"));
|
|
45215
45522
|
const pinned = Object.values(reg).some((e) => e.cid === importCid && e.pinned);
|
|
45216
45523
|
if (pinned) {
|
|
45217
45524
|
renderInfo(`CID ${importCid.slice(0, 20)}... pinned successfully.`);
|
|
@@ -45264,33 +45571,33 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45264
45571
|
lines.push(`
|
|
45265
45572
|
${c2.bold("IPFS / Helia Status")}
|
|
45266
45573
|
`);
|
|
45267
|
-
const ipfsDir =
|
|
45268
|
-
const ipfsLocalDir =
|
|
45574
|
+
const ipfsDir = join57(ctx.repoRoot, ".oa", "ipfs");
|
|
45575
|
+
const ipfsLocalDir = join57(ipfsDir, "local");
|
|
45269
45576
|
let ipfsFiles = 0;
|
|
45270
45577
|
let ipfsBytes = 0;
|
|
45271
45578
|
let heliaBlocks = 0;
|
|
45272
45579
|
let heliaBytes = 0;
|
|
45273
45580
|
try {
|
|
45274
|
-
if (
|
|
45275
|
-
const files =
|
|
45581
|
+
if (existsSync41(ipfsLocalDir)) {
|
|
45582
|
+
const files = readdirSync12(ipfsLocalDir).filter((f) => f.endsWith(".json"));
|
|
45276
45583
|
ipfsFiles = files.length;
|
|
45277
45584
|
for (const f of files) {
|
|
45278
45585
|
try {
|
|
45279
|
-
ipfsBytes += statSync14(
|
|
45586
|
+
ipfsBytes += statSync14(join57(ipfsLocalDir, f)).size;
|
|
45280
45587
|
} catch {
|
|
45281
45588
|
}
|
|
45282
45589
|
}
|
|
45283
45590
|
}
|
|
45284
|
-
const heliaBlockDir =
|
|
45285
|
-
if (
|
|
45591
|
+
const heliaBlockDir = join57(ipfsDir, "blocks");
|
|
45592
|
+
if (existsSync41(heliaBlockDir)) {
|
|
45286
45593
|
const walkDir = (dir) => {
|
|
45287
|
-
for (const entry of
|
|
45594
|
+
for (const entry of readdirSync12(dir, { withFileTypes: true })) {
|
|
45288
45595
|
if (entry.isDirectory())
|
|
45289
|
-
walkDir(
|
|
45596
|
+
walkDir(join57(dir, entry.name));
|
|
45290
45597
|
else {
|
|
45291
45598
|
heliaBlocks++;
|
|
45292
45599
|
try {
|
|
45293
|
-
heliaBytes += statSync14(
|
|
45600
|
+
heliaBytes += statSync14(join57(dir, entry.name)).size;
|
|
45294
45601
|
} catch {
|
|
45295
45602
|
}
|
|
45296
45603
|
}
|
|
@@ -45306,9 +45613,9 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45306
45613
|
lines.push(` Blocks: ${c2.bold(String(heliaBlocks))} Size: ${c2.bold(formatFileSize(heliaBytes))}`);
|
|
45307
45614
|
lines.push(` Backend: ${heliaBlocks > 0 ? c2.green("helia-ipfs") : c2.yellow("sha256-local (Helia not initialized)")}`);
|
|
45308
45615
|
try {
|
|
45309
|
-
const statusFile =
|
|
45310
|
-
if (
|
|
45311
|
-
const status = JSON.parse(
|
|
45616
|
+
const statusFile = join57(ctx.repoRoot, ".oa", "nexus", "status.json");
|
|
45617
|
+
if (existsSync41(statusFile)) {
|
|
45618
|
+
const status = JSON.parse(readFileSync30(statusFile, "utf8"));
|
|
45312
45619
|
if (status.peerId) {
|
|
45313
45620
|
lines.push(`
|
|
45314
45621
|
${c2.bold("Peer Info")}`);
|
|
@@ -45327,11 +45634,11 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45327
45634
|
${c2.dim("Commands: /ipfs pin <CID> /ipfs publish /ipfs cids")}`);
|
|
45328
45635
|
lines.push(`
|
|
45329
45636
|
${c2.bold("Identity Kernel")}`);
|
|
45330
|
-
const idDir =
|
|
45637
|
+
const idDir = join57(ctx.repoRoot, ".oa", "identity");
|
|
45331
45638
|
try {
|
|
45332
|
-
const stateFile =
|
|
45333
|
-
if (
|
|
45334
|
-
const state = JSON.parse(
|
|
45639
|
+
const stateFile = join57(idDir, "self-state.json");
|
|
45640
|
+
if (existsSync41(stateFile)) {
|
|
45641
|
+
const state = JSON.parse(readFileSync30(stateFile, "utf8"));
|
|
45335
45642
|
lines.push(` Version: ${c2.bold("v" + (state.version ?? "?"))} Sessions: ${c2.bold(String(state.session_count ?? 0))}`);
|
|
45336
45643
|
if (state.narrative_summary) {
|
|
45337
45644
|
lines.push(` Narrative: ${c2.dim(state.narrative_summary.slice(0, 60))}${state.narrative_summary.length > 60 ? "..." : ""}`);
|
|
@@ -45340,9 +45647,9 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45340
45647
|
const traits = typeof state.personality_traits === "object" ? Object.entries(state.personality_traits).map(([k, v]) => `${k}:${v}`).join(", ") : String(state.personality_traits);
|
|
45341
45648
|
lines.push(` Traits: ${c2.dim(traits.slice(0, 60))}`);
|
|
45342
45649
|
}
|
|
45343
|
-
const cidFile =
|
|
45344
|
-
if (
|
|
45345
|
-
const cids = JSON.parse(
|
|
45650
|
+
const cidFile = join57(idDir, "cids.json");
|
|
45651
|
+
if (existsSync41(cidFile)) {
|
|
45652
|
+
const cids = JSON.parse(readFileSync30(cidFile, "utf8"));
|
|
45346
45653
|
const lastCid = Array.isArray(cids) ? cids[cids.length - 1] : cids.latest;
|
|
45347
45654
|
if (lastCid)
|
|
45348
45655
|
lines.push(` Last CID: ${c2.dim(String(lastCid).slice(0, 50))}`);
|
|
@@ -45355,9 +45662,9 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45355
45662
|
lines.push(`
|
|
45356
45663
|
${c2.bold("Memory Sentiment")}`);
|
|
45357
45664
|
try {
|
|
45358
|
-
const metaFile =
|
|
45359
|
-
if (
|
|
45360
|
-
const store = JSON.parse(
|
|
45665
|
+
const metaFile = join57(ctx.repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
45666
|
+
if (existsSync41(metaFile)) {
|
|
45667
|
+
const store = JSON.parse(readFileSync30(metaFile, "utf8"));
|
|
45361
45668
|
const active = store.filter((m) => m.type !== "quarantine");
|
|
45362
45669
|
const recoveries = active.filter((m) => m.content?.startsWith("[recovery]")).length;
|
|
45363
45670
|
const strategies = active.filter((m) => m.content?.startsWith("[strategy]")).length;
|
|
@@ -45375,8 +45682,8 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45375
45682
|
} catch {
|
|
45376
45683
|
}
|
|
45377
45684
|
try {
|
|
45378
|
-
const dbPath =
|
|
45379
|
-
if (
|
|
45685
|
+
const dbPath = join57(ctx.repoRoot, ".oa", "memory", "structured.db");
|
|
45686
|
+
if (existsSync41(dbPath)) {
|
|
45380
45687
|
const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
|
|
45381
45688
|
const db = initDb2(dbPath);
|
|
45382
45689
|
const memStore = new ProceduralMemoryStore2(db);
|
|
@@ -45397,8 +45704,8 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45397
45704
|
lines.push(`
|
|
45398
45705
|
${c2.bold("Storage Overview")}
|
|
45399
45706
|
`);
|
|
45400
|
-
const oaDir =
|
|
45401
|
-
if (!
|
|
45707
|
+
const oaDir = join57(ctx.repoRoot, ".oa");
|
|
45708
|
+
if (!existsSync41(oaDir)) {
|
|
45402
45709
|
lines.push(` ${c2.dim("No .oa/ directory found.")}`);
|
|
45403
45710
|
safeLog(lines.join("\n") + "\n");
|
|
45404
45711
|
return "handled";
|
|
@@ -45407,8 +45714,8 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45407
45714
|
const categories = {};
|
|
45408
45715
|
const walkStorage = (dir, category) => {
|
|
45409
45716
|
try {
|
|
45410
|
-
for (const entry of
|
|
45411
|
-
const full =
|
|
45717
|
+
for (const entry of readdirSync12(dir, { withFileTypes: true })) {
|
|
45718
|
+
const full = join57(dir, entry.name);
|
|
45412
45719
|
if (entry.isDirectory()) {
|
|
45413
45720
|
const subCat = category || entry.name;
|
|
45414
45721
|
walkStorage(full, subCat);
|
|
@@ -45441,13 +45748,13 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45441
45748
|
const sensitiveFound = [];
|
|
45442
45749
|
const checkSensitive = (dir) => {
|
|
45443
45750
|
try {
|
|
45444
|
-
for (const entry of
|
|
45751
|
+
for (const entry of readdirSync12(dir, { withFileTypes: true })) {
|
|
45445
45752
|
const name = entry.name.toLowerCase();
|
|
45446
45753
|
if (sensitivePatterns.some((p) => name.includes(p))) {
|
|
45447
|
-
sensitiveFound.push(
|
|
45754
|
+
sensitiveFound.push(join57(dir, entry.name).replace(oaDir + "/", ""));
|
|
45448
45755
|
}
|
|
45449
45756
|
if (entry.isDirectory())
|
|
45450
|
-
checkSensitive(
|
|
45757
|
+
checkSensitive(join57(dir, entry.name));
|
|
45451
45758
|
}
|
|
45452
45759
|
} catch {
|
|
45453
45760
|
}
|
|
@@ -45475,8 +45782,8 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45475
45782
|
renderInfo("Supported: .wav .mp3 .flac .ogg (audio\u2192transcribe) | .pdf .txt .md (text\u2192chunk)");
|
|
45476
45783
|
return "handled";
|
|
45477
45784
|
}
|
|
45478
|
-
const resolvedPath =
|
|
45479
|
-
if (!
|
|
45785
|
+
const resolvedPath = join57(ctx.repoRoot, filePath);
|
|
45786
|
+
if (!existsSync41(resolvedPath)) {
|
|
45480
45787
|
renderWarning(`File not found: ${resolvedPath}`);
|
|
45481
45788
|
return "handled";
|
|
45482
45789
|
}
|
|
@@ -45492,9 +45799,9 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45492
45799
|
}
|
|
45493
45800
|
try {
|
|
45494
45801
|
const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
|
|
45495
|
-
const dbDir =
|
|
45496
|
-
|
|
45497
|
-
const db = initDb2(
|
|
45802
|
+
const dbDir = join57(ctx.repoRoot, ".oa", "memory");
|
|
45803
|
+
mkdirSync17(dbDir, { recursive: true });
|
|
45804
|
+
const db = initDb2(join57(dbDir, "structured.db"));
|
|
45498
45805
|
const memStore = new ProceduralMemoryStore2(db);
|
|
45499
45806
|
if (isAudio) {
|
|
45500
45807
|
renderInfo(`Transcribing: ${filePath}...`);
|
|
@@ -45535,7 +45842,7 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45535
45842
|
return "handled";
|
|
45536
45843
|
}
|
|
45537
45844
|
} else {
|
|
45538
|
-
content =
|
|
45845
|
+
content = readFileSync30(resolvedPath, "utf8");
|
|
45539
45846
|
}
|
|
45540
45847
|
if (!content.trim()) {
|
|
45541
45848
|
renderWarning("No content extracted.");
|
|
@@ -45574,9 +45881,9 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45574
45881
|
}
|
|
45575
45882
|
case "fortemi": {
|
|
45576
45883
|
const fortemiSubCmd = (arg || "").trim().toLowerCase();
|
|
45577
|
-
const fortemiDir =
|
|
45578
|
-
const altFortemiDir =
|
|
45579
|
-
const fDir =
|
|
45884
|
+
const fortemiDir = join57(ctx.repoRoot, "..", "fortemi-react");
|
|
45885
|
+
const altFortemiDir = join57(nodeOs.homedir(), "fortemi-react");
|
|
45886
|
+
const fDir = existsSync41(fortemiDir) ? fortemiDir : existsSync41(altFortemiDir) ? altFortemiDir : null;
|
|
45580
45887
|
if (fortemiSubCmd === "start" || fortemiSubCmd === "") {
|
|
45581
45888
|
if (!fDir) {
|
|
45582
45889
|
renderWarning("fortemi-react not found adjacent or in home directory.");
|
|
@@ -45591,14 +45898,14 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45591
45898
|
// 24h
|
|
45592
45899
|
nonce: Math.random().toString(36).slice(2, 10)
|
|
45593
45900
|
};
|
|
45594
|
-
const jwtFile =
|
|
45595
|
-
|
|
45596
|
-
|
|
45901
|
+
const jwtFile = join57(ctx.repoRoot, ".oa", "fortemi-jwt.json");
|
|
45902
|
+
mkdirSync17(join57(ctx.repoRoot, ".oa"), { recursive: true });
|
|
45903
|
+
writeFileSync18(jwtFile, JSON.stringify(jwtPayload, null, 2));
|
|
45597
45904
|
renderInfo(`Launching fortemi-react from ${fDir}...`);
|
|
45598
45905
|
try {
|
|
45599
45906
|
const { spawn: spawn21 } = __require("node:child_process");
|
|
45600
45907
|
const child = spawn21("npx", ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"], {
|
|
45601
|
-
cwd:
|
|
45908
|
+
cwd: join57(fDir, "apps", "standalone"),
|
|
45602
45909
|
stdio: "ignore",
|
|
45603
45910
|
detached: true,
|
|
45604
45911
|
env: { ...process.env, OA_JWT: JSON.stringify(jwtPayload) }
|
|
@@ -45607,8 +45914,8 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45607
45914
|
renderInfo("Fortemi-React starting on http://localhost:3000");
|
|
45608
45915
|
renderInfo(`JWT saved to ${jwtFile}`);
|
|
45609
45916
|
renderInfo("Memory operations will proxy to fortemi when available.");
|
|
45610
|
-
const bridgeFile =
|
|
45611
|
-
|
|
45917
|
+
const bridgeFile = join57(ctx.repoRoot, ".oa", "fortemi-bridge.json");
|
|
45918
|
+
writeFileSync18(bridgeFile, JSON.stringify({
|
|
45612
45919
|
url: "http://localhost:3000",
|
|
45613
45920
|
pid: child.pid,
|
|
45614
45921
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -45620,12 +45927,12 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45620
45927
|
return "handled";
|
|
45621
45928
|
}
|
|
45622
45929
|
if (fortemiSubCmd === "status") {
|
|
45623
|
-
const bridgeFile =
|
|
45624
|
-
if (!
|
|
45930
|
+
const bridgeFile = join57(ctx.repoRoot, ".oa", "fortemi-bridge.json");
|
|
45931
|
+
if (!existsSync41(bridgeFile)) {
|
|
45625
45932
|
renderInfo("Fortemi bridge: not connected. Run /fortemi start");
|
|
45626
45933
|
return "handled";
|
|
45627
45934
|
}
|
|
45628
|
-
const bridge = JSON.parse(
|
|
45935
|
+
const bridge = JSON.parse(readFileSync30(bridgeFile, "utf8"));
|
|
45629
45936
|
let alive = false;
|
|
45630
45937
|
try {
|
|
45631
45938
|
process.kill(bridge.pid, 0);
|
|
@@ -45645,15 +45952,15 @@ async function handleSlashCommand(input, ctx) {
|
|
|
45645
45952
|
lines.push(` Process: ${alive ? c2.green("running") : c2.yellow("not running")} (PID ${bridge.pid})`);
|
|
45646
45953
|
lines.push(` HTTP: ${httpOk ? c2.green("connected") : c2.yellow("unreachable")}`);
|
|
45647
45954
|
lines.push(` Started: ${bridge.startedAt}`);
|
|
45648
|
-
lines.push(` JWT: ${
|
|
45955
|
+
lines.push(` JWT: ${existsSync41(bridge.jwtFile) ? c2.green("valid") : c2.yellow("missing")}`);
|
|
45649
45956
|
lines.push("");
|
|
45650
45957
|
safeLog(lines.join("\n"));
|
|
45651
45958
|
return "handled";
|
|
45652
45959
|
}
|
|
45653
45960
|
if (fortemiSubCmd === "stop") {
|
|
45654
|
-
const bridgeFile =
|
|
45655
|
-
if (
|
|
45656
|
-
const bridge = JSON.parse(
|
|
45961
|
+
const bridgeFile = join57(ctx.repoRoot, ".oa", "fortemi-bridge.json");
|
|
45962
|
+
if (existsSync41(bridgeFile)) {
|
|
45963
|
+
const bridge = JSON.parse(readFileSync30(bridgeFile, "utf8"));
|
|
45657
45964
|
try {
|
|
45658
45965
|
process.kill(bridge.pid, "SIGTERM");
|
|
45659
45966
|
} catch {
|
|
@@ -47032,13 +47339,13 @@ async function showCohereDashboard(ctx) {
|
|
|
47032
47339
|
} else if (idResult.key === "view") {
|
|
47033
47340
|
await ik.execute({ operation: "hydrate" });
|
|
47034
47341
|
} else if (idResult.key === "history") {
|
|
47035
|
-
const snapDir =
|
|
47036
|
-
if (
|
|
47037
|
-
const snaps =
|
|
47342
|
+
const snapDir = join57(ctx.repoRoot, ".oa", "identity", "snapshots");
|
|
47343
|
+
if (existsSync41(snapDir)) {
|
|
47344
|
+
const snaps = readdirSync12(snapDir).filter((f) => f.endsWith(".json")).sort().reverse();
|
|
47038
47345
|
const snapItems = snaps.slice(0, 20).map((f) => ({
|
|
47039
47346
|
key: f,
|
|
47040
47347
|
label: f.replace(".json", ""),
|
|
47041
|
-
detail: `${formatFileSize(statSync14(
|
|
47348
|
+
detail: `${formatFileSize(statSync14(join57(snapDir, f)).size)}`
|
|
47042
47349
|
}));
|
|
47043
47350
|
if (snapItems.length > 0) {
|
|
47044
47351
|
await tuiSelect({
|
|
@@ -47353,13 +47660,13 @@ async function handleVoiceMenu(ctx, save, hasLocal) {
|
|
|
47353
47660
|
if (!jsonDrop.confirmed || !jsonDrop.path) {
|
|
47354
47661
|
continue;
|
|
47355
47662
|
}
|
|
47356
|
-
const { basename:
|
|
47357
|
-
const { copyFileSync: copyFileSync2, mkdirSync:
|
|
47663
|
+
const { basename: basename18, join: pathJoin } = await import("node:path");
|
|
47664
|
+
const { copyFileSync: copyFileSync2, mkdirSync: mkdirSync25, existsSync: exists } = await import("node:fs");
|
|
47358
47665
|
const { homedir: homedir18 } = await import("node:os");
|
|
47359
|
-
const modelName =
|
|
47666
|
+
const modelName = basename18(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
47360
47667
|
const destDir = pathJoin(homedir18(), ".open-agents", "voice", "models", modelName);
|
|
47361
47668
|
if (!exists(destDir))
|
|
47362
|
-
|
|
47669
|
+
mkdirSync25(destDir, { recursive: true });
|
|
47363
47670
|
copyFileSync2(onnxDrop.path, pathJoin(destDir, "model.onnx"));
|
|
47364
47671
|
copyFileSync2(jsonDrop.path, pathJoin(destDir, "config.json"));
|
|
47365
47672
|
const { registerCustomOnnxModel: registerCustomOnnxModel2 } = await Promise.resolve().then(() => (init_voice(), voice_exports));
|
|
@@ -47504,7 +47811,7 @@ async function handleVoiceList(ctx, focusFilename) {
|
|
|
47504
47811
|
const src = srcPath.trim();
|
|
47505
47812
|
try {
|
|
47506
47813
|
const { existsSync: fe, copyFileSync: cpf, mkdirSync: mkd } = __require("node:fs");
|
|
47507
|
-
const { basename:
|
|
47814
|
+
const { basename: basename18, join: pjoin } = __require("node:path");
|
|
47508
47815
|
if (!fe(src)) {
|
|
47509
47816
|
renderError(`File not found: ${src}`);
|
|
47510
47817
|
helpers.render();
|
|
@@ -47512,7 +47819,7 @@ async function handleVoiceList(ctx, focusFilename) {
|
|
|
47512
47819
|
}
|
|
47513
47820
|
const refsDir = pjoin(__require("node:os").homedir(), ".open-agents", "voice", "clone-refs");
|
|
47514
47821
|
mkd(refsDir, { recursive: true });
|
|
47515
|
-
const destName =
|
|
47822
|
+
const destName = basename18(src);
|
|
47516
47823
|
const dest = pjoin(refsDir, destName);
|
|
47517
47824
|
cpf(src, dest);
|
|
47518
47825
|
renderInfo(`Imported "${destName}" \u2192 ${dest}`);
|
|
@@ -47851,11 +48158,11 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
|
|
|
47851
48158
|
const models = await fetchModels(peerUrl, authKey);
|
|
47852
48159
|
if (models.length > 0) {
|
|
47853
48160
|
try {
|
|
47854
|
-
const { writeFileSync:
|
|
47855
|
-
const { join:
|
|
47856
|
-
const cachePath =
|
|
47857
|
-
|
|
47858
|
-
|
|
48161
|
+
const { writeFileSync: writeFileSync24, mkdirSync: mkdirSync25 } = await import("node:fs");
|
|
48162
|
+
const { join: join71, dirname: dirname22 } = await import("node:path");
|
|
48163
|
+
const cachePath = join71(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
|
|
48164
|
+
mkdirSync25(dirname22(cachePath), { recursive: true });
|
|
48165
|
+
writeFileSync24(cachePath, JSON.stringify({
|
|
47859
48166
|
peerId,
|
|
47860
48167
|
cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
47861
48168
|
models: models.map((m) => ({ name: m.name, size: m.size, parameterSize: m.parameterSize }))
|
|
@@ -47904,7 +48211,7 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
|
|
|
47904
48211
|
}
|
|
47905
48212
|
}
|
|
47906
48213
|
async function handleParallel(arg, ctx) {
|
|
47907
|
-
const { execSync:
|
|
48214
|
+
const { execSync: execSync34 } = await import("node:child_process");
|
|
47908
48215
|
const baseUrl = ctx.config.backendUrl || "http://localhost:11434";
|
|
47909
48216
|
const isRemote = ctx.config.backendType === "nexus";
|
|
47910
48217
|
if (isRemote) {
|
|
@@ -47928,7 +48235,7 @@ async function handleParallel(arg, ctx) {
|
|
|
47928
48235
|
}
|
|
47929
48236
|
let systemdVal = "";
|
|
47930
48237
|
try {
|
|
47931
|
-
const out =
|
|
48238
|
+
const out = execSync34("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
|
|
47932
48239
|
const match = out.match(/OLLAMA_NUM_PARALLEL=(\d+)/);
|
|
47933
48240
|
if (match)
|
|
47934
48241
|
systemdVal = match[1];
|
|
@@ -47957,7 +48264,7 @@ async function handleParallel(arg, ctx) {
|
|
|
47957
48264
|
}
|
|
47958
48265
|
const isSystemd = (() => {
|
|
47959
48266
|
try {
|
|
47960
|
-
const out =
|
|
48267
|
+
const out = execSync34("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
|
|
47961
48268
|
return out === "active" || out === "inactive";
|
|
47962
48269
|
} catch {
|
|
47963
48270
|
return false;
|
|
@@ -47971,10 +48278,10 @@ async function handleParallel(arg, ctx) {
|
|
|
47971
48278
|
const overrideContent = `[Service]
|
|
47972
48279
|
Environment="OLLAMA_NUM_PARALLEL=${n}"
|
|
47973
48280
|
`;
|
|
47974
|
-
|
|
47975
|
-
|
|
47976
|
-
|
|
47977
|
-
|
|
48281
|
+
execSync34(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
|
|
48282
|
+
execSync34(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
|
|
48283
|
+
execSync34("sudo systemctl daemon-reload", { stdio: "pipe" });
|
|
48284
|
+
execSync34("sudo systemctl restart ollama.service", { stdio: "pipe" });
|
|
47978
48285
|
let ready = false;
|
|
47979
48286
|
for (let i = 0; i < 30 && !ready; i++) {
|
|
47980
48287
|
await new Promise((r) => setTimeout(r, 500));
|
|
@@ -48001,7 +48308,7 @@ Environment="OLLAMA_NUM_PARALLEL=${n}"
|
|
|
48001
48308
|
renderInfo(`Setting OLLAMA_NUM_PARALLEL=${n}...`);
|
|
48002
48309
|
try {
|
|
48003
48310
|
try {
|
|
48004
|
-
|
|
48311
|
+
execSync34("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
|
|
48005
48312
|
} catch {
|
|
48006
48313
|
}
|
|
48007
48314
|
await new Promise((r) => setTimeout(r, 1e3));
|
|
@@ -48054,17 +48361,17 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
48054
48361
|
try {
|
|
48055
48362
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
48056
48363
|
const { fileURLToPath: fileURLToPath14 } = await import("node:url");
|
|
48057
|
-
const { dirname: dirname22, join:
|
|
48058
|
-
const { existsSync:
|
|
48364
|
+
const { dirname: dirname22, join: join71 } = await import("node:path");
|
|
48365
|
+
const { existsSync: existsSync51 } = await import("node:fs");
|
|
48059
48366
|
const req = createRequire4(import.meta.url);
|
|
48060
48367
|
const thisDir = dirname22(fileURLToPath14(import.meta.url));
|
|
48061
48368
|
const candidates = [
|
|
48062
|
-
|
|
48063
|
-
|
|
48064
|
-
|
|
48369
|
+
join71(thisDir, "..", "package.json"),
|
|
48370
|
+
join71(thisDir, "..", "..", "package.json"),
|
|
48371
|
+
join71(thisDir, "..", "..", "..", "package.json")
|
|
48065
48372
|
];
|
|
48066
48373
|
for (const pkgPath of candidates) {
|
|
48067
|
-
if (
|
|
48374
|
+
if (existsSync51(pkgPath)) {
|
|
48068
48375
|
const pkg = req(pkgPath);
|
|
48069
48376
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
48070
48377
|
currentVersion = pkg.version ?? "0.0.0";
|
|
@@ -48804,18 +49111,18 @@ async function showExposeDashboard(gateway, rl, ctx) {
|
|
|
48804
49111
|
const cmd = `/endpoint ${id} --auth ${gateway.authKey ?? ""}`;
|
|
48805
49112
|
let copied = false;
|
|
48806
49113
|
try {
|
|
48807
|
-
const { execSync:
|
|
49114
|
+
const { execSync: execSync34 } = __require("node:child_process");
|
|
48808
49115
|
const platform6 = process.platform;
|
|
48809
49116
|
if (platform6 === "darwin") {
|
|
48810
|
-
|
|
49117
|
+
execSync34("pbcopy", { input: cmd, timeout: 3e3 });
|
|
48811
49118
|
copied = true;
|
|
48812
49119
|
} else if (platform6 === "win32") {
|
|
48813
|
-
|
|
49120
|
+
execSync34("clip", { input: cmd, timeout: 3e3 });
|
|
48814
49121
|
copied = true;
|
|
48815
49122
|
} else {
|
|
48816
49123
|
for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
|
|
48817
49124
|
try {
|
|
48818
|
-
|
|
49125
|
+
execSync34(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
|
|
48819
49126
|
copied = true;
|
|
48820
49127
|
break;
|
|
48821
49128
|
} catch {
|
|
@@ -48902,9 +49209,9 @@ var init_commands = __esm({
|
|
|
48902
49209
|
});
|
|
48903
49210
|
|
|
48904
49211
|
// packages/cli/dist/tui/project-context.js
|
|
48905
|
-
import { existsSync as
|
|
48906
|
-
import { join as
|
|
48907
|
-
import { execSync as
|
|
49212
|
+
import { existsSync as existsSync42, readFileSync as readFileSync31, readdirSync as readdirSync13 } from "node:fs";
|
|
49213
|
+
import { join as join58, basename as basename12 } from "node:path";
|
|
49214
|
+
import { execSync as execSync30 } from "node:child_process";
|
|
48908
49215
|
import { homedir as homedir15, platform as platform4, release } from "node:os";
|
|
48909
49216
|
function getModelTier(modelName) {
|
|
48910
49217
|
const m = modelName.toLowerCase();
|
|
@@ -48938,10 +49245,10 @@ function loadProjectMap(repoRoot) {
|
|
|
48938
49245
|
if (!hasOaDirectory(repoRoot)) {
|
|
48939
49246
|
initOaDirectory(repoRoot);
|
|
48940
49247
|
}
|
|
48941
|
-
const mapPath2 =
|
|
48942
|
-
if (
|
|
49248
|
+
const mapPath2 = join58(repoRoot, OA_DIR, "context", "project-map.md");
|
|
49249
|
+
if (existsSync42(mapPath2)) {
|
|
48943
49250
|
try {
|
|
48944
|
-
const content =
|
|
49251
|
+
const content = readFileSync31(mapPath2, "utf-8");
|
|
48945
49252
|
return content;
|
|
48946
49253
|
} catch {
|
|
48947
49254
|
}
|
|
@@ -48950,19 +49257,19 @@ function loadProjectMap(repoRoot) {
|
|
|
48950
49257
|
}
|
|
48951
49258
|
function getGitInfo(repoRoot) {
|
|
48952
49259
|
try {
|
|
48953
|
-
|
|
49260
|
+
execSync30("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
|
|
48954
49261
|
} catch {
|
|
48955
49262
|
return "";
|
|
48956
49263
|
}
|
|
48957
49264
|
const lines = [];
|
|
48958
49265
|
try {
|
|
48959
|
-
const branch =
|
|
49266
|
+
const branch = execSync30("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
48960
49267
|
if (branch)
|
|
48961
49268
|
lines.push(`Branch: ${branch}`);
|
|
48962
49269
|
} catch {
|
|
48963
49270
|
}
|
|
48964
49271
|
try {
|
|
48965
|
-
const status =
|
|
49272
|
+
const status = execSync30("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
48966
49273
|
if (status) {
|
|
48967
49274
|
const changed = status.split("\n").length;
|
|
48968
49275
|
lines.push(`Working tree: ${changed} changed file(s)`);
|
|
@@ -48972,7 +49279,7 @@ function getGitInfo(repoRoot) {
|
|
|
48972
49279
|
} catch {
|
|
48973
49280
|
}
|
|
48974
49281
|
try {
|
|
48975
|
-
const log =
|
|
49282
|
+
const log = execSync30("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
48976
49283
|
if (log)
|
|
48977
49284
|
lines.push(`Recent commits:
|
|
48978
49285
|
${log}`);
|
|
@@ -48982,33 +49289,33 @@ ${log}`);
|
|
|
48982
49289
|
}
|
|
48983
49290
|
function loadMemoryContext(repoRoot) {
|
|
48984
49291
|
const sections = [];
|
|
48985
|
-
const oaMemDir =
|
|
49292
|
+
const oaMemDir = join58(repoRoot, OA_DIR, "memory");
|
|
48986
49293
|
const oaEntries = loadMemoryDir(oaMemDir, "project");
|
|
48987
49294
|
if (oaEntries)
|
|
48988
49295
|
sections.push(oaEntries);
|
|
48989
|
-
const legacyMemDir =
|
|
48990
|
-
if (legacyMemDir !== oaMemDir &&
|
|
49296
|
+
const legacyMemDir = join58(repoRoot, ".open-agents", "memory");
|
|
49297
|
+
if (legacyMemDir !== oaMemDir && existsSync42(legacyMemDir)) {
|
|
48991
49298
|
const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
|
|
48992
49299
|
if (legacyEntries)
|
|
48993
49300
|
sections.push(legacyEntries);
|
|
48994
49301
|
}
|
|
48995
|
-
const globalMemDir =
|
|
49302
|
+
const globalMemDir = join58(homedir15(), ".open-agents", "memory");
|
|
48996
49303
|
const globalEntries = loadMemoryDir(globalMemDir, "global");
|
|
48997
49304
|
if (globalEntries)
|
|
48998
49305
|
sections.push(globalEntries);
|
|
48999
49306
|
return sections.join("\n\n");
|
|
49000
49307
|
}
|
|
49001
49308
|
function loadMemoryDir(memDir, scope) {
|
|
49002
|
-
if (!
|
|
49309
|
+
if (!existsSync42(memDir))
|
|
49003
49310
|
return "";
|
|
49004
49311
|
const lines = [];
|
|
49005
49312
|
try {
|
|
49006
|
-
const files =
|
|
49313
|
+
const files = readdirSync13(memDir).filter((f) => f.endsWith(".json"));
|
|
49007
49314
|
for (const file of files.slice(0, 10)) {
|
|
49008
49315
|
try {
|
|
49009
|
-
const raw =
|
|
49316
|
+
const raw = readFileSync31(join58(memDir, file), "utf-8");
|
|
49010
49317
|
const entries = JSON.parse(raw);
|
|
49011
|
-
const topic =
|
|
49318
|
+
const topic = basename12(file, ".json");
|
|
49012
49319
|
const keys = Object.keys(entries);
|
|
49013
49320
|
if (keys.length === 0)
|
|
49014
49321
|
continue;
|
|
@@ -50525,22 +50832,22 @@ var init_banner = __esm({
|
|
|
50525
50832
|
});
|
|
50526
50833
|
|
|
50527
50834
|
// packages/cli/dist/tui/carousel-descriptors.js
|
|
50528
|
-
import { existsSync as
|
|
50529
|
-
import { join as
|
|
50835
|
+
import { existsSync as existsSync43, readFileSync as readFileSync32, writeFileSync as writeFileSync19, mkdirSync as mkdirSync18, readdirSync as readdirSync14 } from "node:fs";
|
|
50836
|
+
import { join as join59, basename as basename13 } from "node:path";
|
|
50530
50837
|
function loadToolProfile(repoRoot) {
|
|
50531
|
-
const filePath =
|
|
50838
|
+
const filePath = join59(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
|
|
50532
50839
|
try {
|
|
50533
|
-
if (!
|
|
50840
|
+
if (!existsSync43(filePath))
|
|
50534
50841
|
return null;
|
|
50535
|
-
return JSON.parse(
|
|
50842
|
+
return JSON.parse(readFileSync32(filePath, "utf-8"));
|
|
50536
50843
|
} catch {
|
|
50537
50844
|
return null;
|
|
50538
50845
|
}
|
|
50539
50846
|
}
|
|
50540
50847
|
function saveToolProfile(repoRoot, profile) {
|
|
50541
|
-
const contextDir =
|
|
50542
|
-
|
|
50543
|
-
|
|
50848
|
+
const contextDir = join59(repoRoot, OA_DIR, "context");
|
|
50849
|
+
mkdirSync18(contextDir, { recursive: true });
|
|
50850
|
+
writeFileSync19(join59(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
|
|
50544
50851
|
}
|
|
50545
50852
|
function categorizeToolCall(toolName) {
|
|
50546
50853
|
for (const cat of TOOL_CATEGORIES) {
|
|
@@ -50598,25 +50905,25 @@ function weightedColor(profile) {
|
|
|
50598
50905
|
return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
|
|
50599
50906
|
}
|
|
50600
50907
|
function loadCachedDescriptors(repoRoot) {
|
|
50601
|
-
const filePath =
|
|
50908
|
+
const filePath = join59(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
|
|
50602
50909
|
try {
|
|
50603
|
-
if (!
|
|
50910
|
+
if (!existsSync43(filePath))
|
|
50604
50911
|
return null;
|
|
50605
|
-
const cached = JSON.parse(
|
|
50912
|
+
const cached = JSON.parse(readFileSync32(filePath, "utf-8"));
|
|
50606
50913
|
return cached.phrases.length > 0 ? cached.phrases : null;
|
|
50607
50914
|
} catch {
|
|
50608
50915
|
return null;
|
|
50609
50916
|
}
|
|
50610
50917
|
}
|
|
50611
50918
|
function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
|
|
50612
|
-
const contextDir =
|
|
50613
|
-
|
|
50919
|
+
const contextDir = join59(repoRoot, OA_DIR, "context");
|
|
50920
|
+
mkdirSync18(contextDir, { recursive: true });
|
|
50614
50921
|
const cached = {
|
|
50615
50922
|
phrases,
|
|
50616
50923
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
50617
50924
|
sourceHash
|
|
50618
50925
|
};
|
|
50619
|
-
|
|
50926
|
+
writeFileSync19(join59(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
|
|
50620
50927
|
}
|
|
50621
50928
|
function generateDescriptors(repoRoot) {
|
|
50622
50929
|
const profile = loadToolProfile(repoRoot);
|
|
@@ -50627,7 +50934,7 @@ function generateDescriptors(repoRoot) {
|
|
|
50627
50934
|
extractFromSessions(repoRoot, tags);
|
|
50628
50935
|
extractFromMemory(repoRoot, tags);
|
|
50629
50936
|
extractFromToolProfile(profile, tags);
|
|
50630
|
-
const repoName2 =
|
|
50937
|
+
const repoName2 = basename13(repoRoot);
|
|
50631
50938
|
if (repoName2 && !tags.includes(repoName2)) {
|
|
50632
50939
|
tags.push(repoName2);
|
|
50633
50940
|
}
|
|
@@ -50664,11 +50971,11 @@ function generateDescriptors(repoRoot) {
|
|
|
50664
50971
|
return phrases;
|
|
50665
50972
|
}
|
|
50666
50973
|
function extractFromPackageJson(repoRoot, tags) {
|
|
50667
|
-
const pkgPath =
|
|
50974
|
+
const pkgPath = join59(repoRoot, "package.json");
|
|
50668
50975
|
try {
|
|
50669
|
-
if (!
|
|
50976
|
+
if (!existsSync43(pkgPath))
|
|
50670
50977
|
return;
|
|
50671
|
-
const pkg = JSON.parse(
|
|
50978
|
+
const pkg = JSON.parse(readFileSync32(pkgPath, "utf-8"));
|
|
50672
50979
|
if (pkg.name && typeof pkg.name === "string") {
|
|
50673
50980
|
const parts = pkg.name.replace(/^@/, "").split("/");
|
|
50674
50981
|
for (const p of parts)
|
|
@@ -50712,7 +51019,7 @@ function extractFromManifests(repoRoot, tags) {
|
|
|
50712
51019
|
{ file: ".github/workflows", tag: "ci/cd" }
|
|
50713
51020
|
];
|
|
50714
51021
|
for (const check of manifestChecks) {
|
|
50715
|
-
if (
|
|
51022
|
+
if (existsSync43(join59(repoRoot, check.file))) {
|
|
50716
51023
|
tags.push(check.tag);
|
|
50717
51024
|
}
|
|
50718
51025
|
}
|
|
@@ -50734,16 +51041,16 @@ function extractFromSessions(repoRoot, tags) {
|
|
|
50734
51041
|
}
|
|
50735
51042
|
}
|
|
50736
51043
|
function extractFromMemory(repoRoot, tags) {
|
|
50737
|
-
const memoryDir =
|
|
51044
|
+
const memoryDir = join59(repoRoot, OA_DIR, "memory");
|
|
50738
51045
|
try {
|
|
50739
|
-
if (!
|
|
51046
|
+
if (!existsSync43(memoryDir))
|
|
50740
51047
|
return;
|
|
50741
|
-
const files =
|
|
51048
|
+
const files = readdirSync14(memoryDir).filter((f) => f.endsWith(".json"));
|
|
50742
51049
|
for (const file of files) {
|
|
50743
51050
|
const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
|
|
50744
51051
|
tags.push(topic);
|
|
50745
51052
|
try {
|
|
50746
|
-
const data = JSON.parse(
|
|
51053
|
+
const data = JSON.parse(readFileSync32(join59(memoryDir, file), "utf-8"));
|
|
50747
51054
|
if (data && typeof data === "object") {
|
|
50748
51055
|
const keys = Object.keys(data).slice(0, 3);
|
|
50749
51056
|
for (const key of keys) {
|
|
@@ -51376,13 +51683,13 @@ var init_stream_renderer = __esm({
|
|
|
51376
51683
|
});
|
|
51377
51684
|
|
|
51378
51685
|
// packages/cli/dist/tui/edit-history.js
|
|
51379
|
-
import { appendFileSync as appendFileSync3, mkdirSync as
|
|
51380
|
-
import { join as
|
|
51686
|
+
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync19 } from "node:fs";
|
|
51687
|
+
import { join as join60 } from "node:path";
|
|
51381
51688
|
function createEditHistoryLogger(repoRoot, sessionId) {
|
|
51382
|
-
const historyDir =
|
|
51383
|
-
const logPath2 =
|
|
51689
|
+
const historyDir = join60(repoRoot, ".oa", "history");
|
|
51690
|
+
const logPath2 = join60(historyDir, "edits.jsonl");
|
|
51384
51691
|
try {
|
|
51385
|
-
|
|
51692
|
+
mkdirSync19(historyDir, { recursive: true });
|
|
51386
51693
|
} catch {
|
|
51387
51694
|
}
|
|
51388
51695
|
function logToolCall(toolName, toolArgs, success) {
|
|
@@ -51491,17 +51798,17 @@ var init_edit_history = __esm({
|
|
|
51491
51798
|
});
|
|
51492
51799
|
|
|
51493
51800
|
// packages/cli/dist/tui/promptLoader.js
|
|
51494
|
-
import { readFileSync as
|
|
51495
|
-
import { join as
|
|
51801
|
+
import { readFileSync as readFileSync33, existsSync as existsSync44 } from "node:fs";
|
|
51802
|
+
import { join as join61, dirname as dirname19 } from "node:path";
|
|
51496
51803
|
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
51497
51804
|
function loadPrompt3(promptPath, vars) {
|
|
51498
51805
|
let content = cache3.get(promptPath);
|
|
51499
51806
|
if (content === void 0) {
|
|
51500
|
-
const fullPath =
|
|
51501
|
-
if (!
|
|
51807
|
+
const fullPath = join61(PROMPTS_DIR3, promptPath);
|
|
51808
|
+
if (!existsSync44(fullPath)) {
|
|
51502
51809
|
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
51503
51810
|
}
|
|
51504
|
-
content =
|
|
51811
|
+
content = readFileSync33(fullPath, "utf-8");
|
|
51505
51812
|
cache3.set(promptPath, content);
|
|
51506
51813
|
}
|
|
51507
51814
|
if (!vars)
|
|
@@ -51514,23 +51821,23 @@ var init_promptLoader3 = __esm({
|
|
|
51514
51821
|
"use strict";
|
|
51515
51822
|
__filename3 = fileURLToPath11(import.meta.url);
|
|
51516
51823
|
__dirname6 = dirname19(__filename3);
|
|
51517
|
-
devPath2 =
|
|
51518
|
-
publishedPath2 =
|
|
51519
|
-
PROMPTS_DIR3 =
|
|
51824
|
+
devPath2 = join61(__dirname6, "..", "..", "prompts");
|
|
51825
|
+
publishedPath2 = join61(__dirname6, "..", "prompts");
|
|
51826
|
+
PROMPTS_DIR3 = existsSync44(devPath2) ? devPath2 : publishedPath2;
|
|
51520
51827
|
cache3 = /* @__PURE__ */ new Map();
|
|
51521
51828
|
}
|
|
51522
51829
|
});
|
|
51523
51830
|
|
|
51524
51831
|
// packages/cli/dist/tui/dream-engine.js
|
|
51525
|
-
import { mkdirSync as
|
|
51526
|
-
import { join as
|
|
51527
|
-
import { execSync as
|
|
51832
|
+
import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync20, readFileSync as readFileSync34, existsSync as existsSync45, cpSync, rmSync as rmSync2, readdirSync as readdirSync15 } from "node:fs";
|
|
51833
|
+
import { join as join62, basename as basename14 } from "node:path";
|
|
51834
|
+
import { execSync as execSync31 } from "node:child_process";
|
|
51528
51835
|
function loadAutoresearchMemory(repoRoot) {
|
|
51529
|
-
const memoryPath =
|
|
51530
|
-
if (!
|
|
51836
|
+
const memoryPath = join62(repoRoot, ".oa", "memory", "autoresearch.json");
|
|
51837
|
+
if (!existsSync45(memoryPath))
|
|
51531
51838
|
return "";
|
|
51532
51839
|
try {
|
|
51533
|
-
const raw =
|
|
51840
|
+
const raw = readFileSync34(memoryPath, "utf-8");
|
|
51534
51841
|
const data = JSON.parse(raw);
|
|
51535
51842
|
const sections = [];
|
|
51536
51843
|
for (const key of AUTORESEARCH_MEMORY_KEYS) {
|
|
@@ -51720,14 +52027,14 @@ var init_dream_engine = __esm({
|
|
|
51720
52027
|
const content = String(args["content"] ?? "");
|
|
51721
52028
|
if (!rawPath)
|
|
51722
52029
|
return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
|
|
51723
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ?
|
|
52030
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join62(this.autoresearchDir, basename14(rawPath)) : join62(this.autoresearchDir, rawPath);
|
|
51724
52031
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
51725
52032
|
return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
|
|
51726
52033
|
}
|
|
51727
52034
|
try {
|
|
51728
|
-
const dir =
|
|
51729
|
-
|
|
51730
|
-
|
|
52035
|
+
const dir = join62(targetPath, "..");
|
|
52036
|
+
mkdirSync20(dir, { recursive: true });
|
|
52037
|
+
writeFileSync20(targetPath, content, "utf-8");
|
|
51731
52038
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
|
|
51732
52039
|
} catch (err) {
|
|
51733
52040
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -51755,20 +52062,20 @@ var init_dream_engine = __esm({
|
|
|
51755
52062
|
const rawPath = String(args["path"] ?? "");
|
|
51756
52063
|
const oldStr = String(args["old_string"] ?? "");
|
|
51757
52064
|
const newStr = String(args["new_string"] ?? "");
|
|
51758
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ?
|
|
52065
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join62(this.autoresearchDir, basename14(rawPath)) : join62(this.autoresearchDir, rawPath);
|
|
51759
52066
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
51760
52067
|
return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
|
|
51761
52068
|
}
|
|
51762
52069
|
try {
|
|
51763
|
-
if (!
|
|
52070
|
+
if (!existsSync45(targetPath)) {
|
|
51764
52071
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
|
|
51765
52072
|
}
|
|
51766
|
-
let content =
|
|
52073
|
+
let content = readFileSync34(targetPath, "utf-8");
|
|
51767
52074
|
if (!content.includes(oldStr)) {
|
|
51768
52075
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
|
|
51769
52076
|
}
|
|
51770
52077
|
content = content.replace(oldStr, newStr);
|
|
51771
|
-
|
|
52078
|
+
writeFileSync20(targetPath, content, "utf-8");
|
|
51772
52079
|
return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
|
|
51773
52080
|
} catch (err) {
|
|
51774
52081
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -51809,14 +52116,14 @@ var init_dream_engine = __esm({
|
|
|
51809
52116
|
const content = String(args["content"] ?? "");
|
|
51810
52117
|
if (!rawPath)
|
|
51811
52118
|
return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
|
|
51812
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
52119
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join62(this.dreamsDir, basename14(rawPath)) : join62(this.dreamsDir, rawPath);
|
|
51813
52120
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
51814
52121
|
return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
51815
52122
|
}
|
|
51816
52123
|
try {
|
|
51817
|
-
const dir =
|
|
51818
|
-
|
|
51819
|
-
|
|
52124
|
+
const dir = join62(targetPath, "..");
|
|
52125
|
+
mkdirSync20(dir, { recursive: true });
|
|
52126
|
+
writeFileSync20(targetPath, content, "utf-8");
|
|
51820
52127
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
|
|
51821
52128
|
} catch (err) {
|
|
51822
52129
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -51844,20 +52151,20 @@ var init_dream_engine = __esm({
|
|
|
51844
52151
|
const rawPath = String(args["path"] ?? "");
|
|
51845
52152
|
const oldStr = String(args["old_string"] ?? "");
|
|
51846
52153
|
const newStr = String(args["new_string"] ?? "");
|
|
51847
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
52154
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join62(this.dreamsDir, basename14(rawPath)) : join62(this.dreamsDir, rawPath);
|
|
51848
52155
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
51849
52156
|
return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
51850
52157
|
}
|
|
51851
52158
|
try {
|
|
51852
|
-
if (!
|
|
52159
|
+
if (!existsSync45(targetPath)) {
|
|
51853
52160
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
|
|
51854
52161
|
}
|
|
51855
|
-
let content =
|
|
52162
|
+
let content = readFileSync34(targetPath, "utf-8");
|
|
51856
52163
|
if (!content.includes(oldStr)) {
|
|
51857
52164
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
|
|
51858
52165
|
}
|
|
51859
52166
|
content = content.replace(oldStr, newStr);
|
|
51860
|
-
|
|
52167
|
+
writeFileSync20(targetPath, content, "utf-8");
|
|
51861
52168
|
return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
|
|
51862
52169
|
} catch (err) {
|
|
51863
52170
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -51888,7 +52195,7 @@ var init_dream_engine = __esm({
|
|
|
51888
52195
|
}
|
|
51889
52196
|
}
|
|
51890
52197
|
try {
|
|
51891
|
-
const output =
|
|
52198
|
+
const output = execSync31(cmd, {
|
|
51892
52199
|
cwd: this.repoRoot,
|
|
51893
52200
|
timeout: 3e4,
|
|
51894
52201
|
encoding: "utf-8",
|
|
@@ -51911,7 +52218,7 @@ var init_dream_engine = __esm({
|
|
|
51911
52218
|
constructor(config, repoRoot) {
|
|
51912
52219
|
this.config = config;
|
|
51913
52220
|
this.repoRoot = repoRoot;
|
|
51914
|
-
this.dreamsDir =
|
|
52221
|
+
this.dreamsDir = join62(repoRoot, ".oa", "dreams");
|
|
51915
52222
|
this.state = {
|
|
51916
52223
|
mode: "default",
|
|
51917
52224
|
active: false,
|
|
@@ -51942,7 +52249,7 @@ var init_dream_engine = __esm({
|
|
|
51942
52249
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
51943
52250
|
results: []
|
|
51944
52251
|
};
|
|
51945
|
-
|
|
52252
|
+
mkdirSync20(this.dreamsDir, { recursive: true });
|
|
51946
52253
|
this.saveDreamState();
|
|
51947
52254
|
try {
|
|
51948
52255
|
for (let cycle = 1; cycle <= totalCycles; cycle++) {
|
|
@@ -51995,8 +52302,8 @@ ${result.summary}`;
|
|
|
51995
52302
|
if (mode !== "default" || cycle === totalCycles) {
|
|
51996
52303
|
renderDreamContraction(cycle);
|
|
51997
52304
|
const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
|
|
51998
|
-
const summaryPath =
|
|
51999
|
-
|
|
52305
|
+
const summaryPath = join62(this.dreamsDir, `cycle-${cycle}-summary.md`);
|
|
52306
|
+
writeFileSync20(summaryPath, cycleSummary, "utf-8");
|
|
52000
52307
|
}
|
|
52001
52308
|
if (mode === "lucid" && !this.abortController.signal.aborted) {
|
|
52002
52309
|
this.saveVersionCheckpoint(cycle);
|
|
@@ -52208,7 +52515,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
|
|
|
52208
52515
|
}
|
|
52209
52516
|
/** Build role-specific tool sets for swarm agents */
|
|
52210
52517
|
buildSwarmTools(role, _workspace) {
|
|
52211
|
-
const autoresearchDir =
|
|
52518
|
+
const autoresearchDir = join62(this.repoRoot, ".oa", "autoresearch");
|
|
52212
52519
|
const taskComplete = this.createSwarmTaskCompleteTool(role);
|
|
52213
52520
|
switch (role) {
|
|
52214
52521
|
case "researcher": {
|
|
@@ -52572,7 +52879,7 @@ INSTRUCTIONS:
|
|
|
52572
52879
|
2. Summarize the key learnings and next steps
|
|
52573
52880
|
|
|
52574
52881
|
Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
|
|
52575
|
-
const reportPath =
|
|
52882
|
+
const reportPath = join62(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
|
|
52576
52883
|
const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
|
|
52577
52884
|
|
|
52578
52885
|
**Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
@@ -52594,8 +52901,8 @@ ${summaryResult}
|
|
|
52594
52901
|
*Generated by open-agents autoresearch swarm*
|
|
52595
52902
|
`;
|
|
52596
52903
|
try {
|
|
52597
|
-
|
|
52598
|
-
|
|
52904
|
+
mkdirSync20(this.dreamsDir, { recursive: true });
|
|
52905
|
+
writeFileSync20(reportPath, report, "utf-8");
|
|
52599
52906
|
} catch {
|
|
52600
52907
|
}
|
|
52601
52908
|
renderSwarmComplete(workspace);
|
|
@@ -52661,29 +52968,29 @@ ${summaryResult}
|
|
|
52661
52968
|
}
|
|
52662
52969
|
/** Save workspace backup for lucid mode */
|
|
52663
52970
|
saveVersionCheckpoint(cycle) {
|
|
52664
|
-
const checkpointDir =
|
|
52971
|
+
const checkpointDir = join62(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
|
|
52665
52972
|
try {
|
|
52666
|
-
|
|
52973
|
+
mkdirSync20(checkpointDir, { recursive: true });
|
|
52667
52974
|
try {
|
|
52668
|
-
const gitStatus =
|
|
52975
|
+
const gitStatus = execSync31("git status --porcelain", {
|
|
52669
52976
|
cwd: this.repoRoot,
|
|
52670
52977
|
encoding: "utf-8",
|
|
52671
52978
|
timeout: 1e4
|
|
52672
52979
|
});
|
|
52673
|
-
const gitDiff =
|
|
52980
|
+
const gitDiff = execSync31("git diff", {
|
|
52674
52981
|
cwd: this.repoRoot,
|
|
52675
52982
|
encoding: "utf-8",
|
|
52676
52983
|
timeout: 1e4
|
|
52677
52984
|
});
|
|
52678
|
-
const gitHash =
|
|
52985
|
+
const gitHash = execSync31("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
|
|
52679
52986
|
cwd: this.repoRoot,
|
|
52680
52987
|
encoding: "utf-8",
|
|
52681
52988
|
timeout: 5e3
|
|
52682
52989
|
}).trim();
|
|
52683
|
-
|
|
52684
|
-
|
|
52685
|
-
|
|
52686
|
-
|
|
52990
|
+
writeFileSync20(join62(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
|
|
52991
|
+
writeFileSync20(join62(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
|
|
52992
|
+
writeFileSync20(join62(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
|
|
52993
|
+
writeFileSync20(join62(checkpointDir, "checkpoint.json"), JSON.stringify({
|
|
52687
52994
|
cycle,
|
|
52688
52995
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
52689
52996
|
gitHash,
|
|
@@ -52691,7 +52998,7 @@ ${summaryResult}
|
|
|
52691
52998
|
}, null, 2), "utf-8");
|
|
52692
52999
|
renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
|
|
52693
53000
|
} catch {
|
|
52694
|
-
|
|
53001
|
+
writeFileSync20(join62(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
|
|
52695
53002
|
renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
|
|
52696
53003
|
}
|
|
52697
53004
|
} catch (err) {
|
|
@@ -52728,7 +53035,7 @@ Each proposal includes implementation entrypoints and estimated effort.
|
|
|
52728
53035
|
/** Update the master proposal index */
|
|
52729
53036
|
updateProposalIndex() {
|
|
52730
53037
|
try {
|
|
52731
|
-
const files =
|
|
53038
|
+
const files = readdirSync15(this.dreamsDir).filter((f) => f.endsWith(".md") && f !== "PROPOSAL-INDEX.md" && f !== "dream-state.json").sort();
|
|
52732
53039
|
const index = `# Dream Proposals Index
|
|
52733
53040
|
|
|
52734
53041
|
**Last updated**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
@@ -52749,14 +53056,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
|
|
|
52749
53056
|
---
|
|
52750
53057
|
*Auto-generated by open-agents dream engine*
|
|
52751
53058
|
`;
|
|
52752
|
-
|
|
53059
|
+
writeFileSync20(join62(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
|
|
52753
53060
|
} catch {
|
|
52754
53061
|
}
|
|
52755
53062
|
}
|
|
52756
53063
|
/** Save dream state for resume/inspection */
|
|
52757
53064
|
saveDreamState() {
|
|
52758
53065
|
try {
|
|
52759
|
-
|
|
53066
|
+
writeFileSync20(join62(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
|
|
52760
53067
|
} catch {
|
|
52761
53068
|
}
|
|
52762
53069
|
}
|
|
@@ -53130,8 +53437,8 @@ var init_bless_engine = __esm({
|
|
|
53130
53437
|
});
|
|
53131
53438
|
|
|
53132
53439
|
// packages/cli/dist/tui/dmn-engine.js
|
|
53133
|
-
import { existsSync as
|
|
53134
|
-
import { join as
|
|
53440
|
+
import { existsSync as existsSync46, readFileSync as readFileSync35, writeFileSync as writeFileSync21, mkdirSync as mkdirSync21, readdirSync as readdirSync16, unlinkSync as unlinkSync10 } from "node:fs";
|
|
53441
|
+
import { join as join63, basename as basename15 } from "node:path";
|
|
53135
53442
|
function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
|
|
53136
53443
|
const competenceReport = competence.length > 0 ? competence.map((c3) => {
|
|
53137
53444
|
const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
|
|
@@ -53251,9 +53558,9 @@ var init_dmn_engine = __esm({
|
|
|
53251
53558
|
constructor(config, repoRoot) {
|
|
53252
53559
|
this.config = config;
|
|
53253
53560
|
this.repoRoot = repoRoot;
|
|
53254
|
-
this.stateDir =
|
|
53255
|
-
this.historyDir =
|
|
53256
|
-
|
|
53561
|
+
this.stateDir = join63(repoRoot, ".oa", "dmn");
|
|
53562
|
+
this.historyDir = join63(repoRoot, ".oa", "dmn", "cycles");
|
|
53563
|
+
mkdirSync21(this.historyDir, { recursive: true });
|
|
53257
53564
|
this.loadState();
|
|
53258
53565
|
}
|
|
53259
53566
|
get stats() {
|
|
@@ -53842,16 +54149,16 @@ OUTPUT: Call task_complete with JSON:
|
|
|
53842
54149
|
async gatherMemoryTopics() {
|
|
53843
54150
|
const topics = [];
|
|
53844
54151
|
const dirs = [
|
|
53845
|
-
|
|
53846
|
-
|
|
54152
|
+
join63(this.repoRoot, ".oa", "memory"),
|
|
54153
|
+
join63(this.repoRoot, ".open-agents", "memory")
|
|
53847
54154
|
];
|
|
53848
54155
|
for (const dir of dirs) {
|
|
53849
|
-
if (!
|
|
54156
|
+
if (!existsSync46(dir))
|
|
53850
54157
|
continue;
|
|
53851
54158
|
try {
|
|
53852
|
-
const files =
|
|
54159
|
+
const files = readdirSync16(dir).filter((f) => f.endsWith(".json"));
|
|
53853
54160
|
for (const f of files) {
|
|
53854
|
-
const topic =
|
|
54161
|
+
const topic = basename15(f, ".json");
|
|
53855
54162
|
if (!topics.includes(topic))
|
|
53856
54163
|
topics.push(topic);
|
|
53857
54164
|
}
|
|
@@ -53862,29 +54169,29 @@ OUTPUT: Call task_complete with JSON:
|
|
|
53862
54169
|
}
|
|
53863
54170
|
// ── State persistence ─────────────────────────────────────────────────
|
|
53864
54171
|
loadState() {
|
|
53865
|
-
const path =
|
|
53866
|
-
if (
|
|
54172
|
+
const path = join63(this.stateDir, "state.json");
|
|
54173
|
+
if (existsSync46(path)) {
|
|
53867
54174
|
try {
|
|
53868
|
-
this.state = JSON.parse(
|
|
54175
|
+
this.state = JSON.parse(readFileSync35(path, "utf-8"));
|
|
53869
54176
|
} catch {
|
|
53870
54177
|
}
|
|
53871
54178
|
}
|
|
53872
54179
|
}
|
|
53873
54180
|
saveState() {
|
|
53874
54181
|
try {
|
|
53875
|
-
|
|
54182
|
+
writeFileSync21(join63(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
|
|
53876
54183
|
} catch {
|
|
53877
54184
|
}
|
|
53878
54185
|
}
|
|
53879
54186
|
saveCycleResult(result) {
|
|
53880
54187
|
try {
|
|
53881
54188
|
const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
|
|
53882
|
-
|
|
53883
|
-
const files =
|
|
54189
|
+
writeFileSync21(join63(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
|
|
54190
|
+
const files = readdirSync16(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
|
|
53884
54191
|
if (files.length > 50) {
|
|
53885
54192
|
for (const old of files.slice(0, files.length - 50)) {
|
|
53886
54193
|
try {
|
|
53887
|
-
|
|
54194
|
+
unlinkSync10(join63(this.historyDir, old));
|
|
53888
54195
|
} catch {
|
|
53889
54196
|
}
|
|
53890
54197
|
}
|
|
@@ -53897,8 +54204,8 @@ OUTPUT: Call task_complete with JSON:
|
|
|
53897
54204
|
});
|
|
53898
54205
|
|
|
53899
54206
|
// packages/cli/dist/tui/snr-engine.js
|
|
53900
|
-
import { existsSync as
|
|
53901
|
-
import { join as
|
|
54207
|
+
import { existsSync as existsSync47, readdirSync as readdirSync17, readFileSync as readFileSync36 } from "node:fs";
|
|
54208
|
+
import { join as join64, basename as basename16 } from "node:path";
|
|
53902
54209
|
function computeDPrime(signalScores, noiseScores) {
|
|
53903
54210
|
if (signalScores.length === 0 || noiseScores.length === 0)
|
|
53904
54211
|
return 0;
|
|
@@ -54138,20 +54445,20 @@ Call task_complete with the JSON array when done.`, onEvent)
|
|
|
54138
54445
|
loadMemoryEntries(topics) {
|
|
54139
54446
|
const entries = [];
|
|
54140
54447
|
const dirs = [
|
|
54141
|
-
|
|
54142
|
-
|
|
54448
|
+
join64(this.repoRoot, ".oa", "memory"),
|
|
54449
|
+
join64(this.repoRoot, ".open-agents", "memory")
|
|
54143
54450
|
];
|
|
54144
54451
|
for (const dir of dirs) {
|
|
54145
|
-
if (!
|
|
54452
|
+
if (!existsSync47(dir))
|
|
54146
54453
|
continue;
|
|
54147
54454
|
try {
|
|
54148
|
-
const files =
|
|
54455
|
+
const files = readdirSync17(dir).filter((f) => f.endsWith(".json"));
|
|
54149
54456
|
for (const f of files) {
|
|
54150
|
-
const topic =
|
|
54457
|
+
const topic = basename16(f, ".json");
|
|
54151
54458
|
if (topics.length > 0 && !topics.includes(topic))
|
|
54152
54459
|
continue;
|
|
54153
54460
|
try {
|
|
54154
|
-
const data = JSON.parse(
|
|
54461
|
+
const data = JSON.parse(readFileSync36(join64(dir, f), "utf-8"));
|
|
54155
54462
|
for (const [key, val] of Object.entries(data)) {
|
|
54156
54463
|
const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
54157
54464
|
entries.push({ topic, key, value });
|
|
@@ -54718,8 +55025,8 @@ var init_tool_policy = __esm({
|
|
|
54718
55025
|
});
|
|
54719
55026
|
|
|
54720
55027
|
// packages/cli/dist/tui/telegram-bridge.js
|
|
54721
|
-
import { mkdirSync as
|
|
54722
|
-
import { join as
|
|
55028
|
+
import { mkdirSync as mkdirSync22, existsSync as existsSync48, unlinkSync as unlinkSync11, readdirSync as readdirSync18, statSync as statSync15 } from "node:fs";
|
|
55029
|
+
import { join as join65, resolve as resolve30 } from "node:path";
|
|
54723
55030
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
54724
55031
|
function convertMarkdownToTelegramHTML(md) {
|
|
54725
55032
|
let html = md;
|
|
@@ -55047,7 +55354,7 @@ with summary "no_reply" to silently skip without responding.
|
|
|
55047
55354
|
this.polling = true;
|
|
55048
55355
|
this.abortController = new AbortController();
|
|
55049
55356
|
try {
|
|
55050
|
-
|
|
55357
|
+
mkdirSync22(this.mediaCacheDir, { recursive: true });
|
|
55051
55358
|
} catch {
|
|
55052
55359
|
}
|
|
55053
55360
|
this.mediaCacheCleanupTimer = setInterval(() => this.cleanupMediaCache(), 5 * 60 * 1e3);
|
|
@@ -55484,7 +55791,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
|
|
|
55484
55791
|
return null;
|
|
55485
55792
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
55486
55793
|
const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
|
|
55487
|
-
const localPath =
|
|
55794
|
+
const localPath = join65(this.mediaCacheDir, fileName);
|
|
55488
55795
|
await writeFileAsync(localPath, buffer);
|
|
55489
55796
|
return localPath;
|
|
55490
55797
|
} catch {
|
|
@@ -55572,7 +55879,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
|
|
|
55572
55879
|
for (const [key, entry] of this.mediaCache) {
|
|
55573
55880
|
if (now - entry.cachedAt > MEDIA_CACHE_TTL_MS) {
|
|
55574
55881
|
try {
|
|
55575
|
-
|
|
55882
|
+
unlinkSync11(entry.localPath);
|
|
55576
55883
|
} catch {
|
|
55577
55884
|
}
|
|
55578
55885
|
this.mediaCache.delete(key);
|
|
@@ -56500,7 +56807,7 @@ __export(text_selection_exports, {
|
|
|
56500
56807
|
stripAnsi: () => stripAnsi3,
|
|
56501
56808
|
visibleLength: () => visibleLength
|
|
56502
56809
|
});
|
|
56503
|
-
import { execSync as
|
|
56810
|
+
import { execSync as execSync32 } from "node:child_process";
|
|
56504
56811
|
function stripAnsi3(s) {
|
|
56505
56812
|
return s.replace(/\x1B\[[0-9;]*[A-Za-z]|\x1B\].*?(?:\x07|\x1B\\)/g, "");
|
|
56506
56813
|
}
|
|
@@ -56511,16 +56818,16 @@ function copyText(text) {
|
|
|
56511
56818
|
try {
|
|
56512
56819
|
const platform6 = process.platform;
|
|
56513
56820
|
if (platform6 === "darwin") {
|
|
56514
|
-
|
|
56821
|
+
execSync32("pbcopy", { input: text, timeout: 3e3 });
|
|
56515
56822
|
return true;
|
|
56516
56823
|
}
|
|
56517
56824
|
if (platform6 === "win32") {
|
|
56518
|
-
|
|
56825
|
+
execSync32("clip", { input: text, timeout: 3e3 });
|
|
56519
56826
|
return true;
|
|
56520
56827
|
}
|
|
56521
56828
|
for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
|
|
56522
56829
|
try {
|
|
56523
|
-
|
|
56830
|
+
execSync32(tool, { input: text, timeout: 3e3 });
|
|
56524
56831
|
return true;
|
|
56525
56832
|
} catch {
|
|
56526
56833
|
continue;
|
|
@@ -56529,10 +56836,10 @@ function copyText(text) {
|
|
|
56529
56836
|
if (!_clipboardAutoInstallAttempted) {
|
|
56530
56837
|
_clipboardAutoInstallAttempted = true;
|
|
56531
56838
|
try {
|
|
56532
|
-
|
|
56839
|
+
execSync32("which apt-get", { timeout: 2e3, stdio: "pipe" });
|
|
56533
56840
|
try {
|
|
56534
|
-
|
|
56535
|
-
|
|
56841
|
+
execSync32("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
|
|
56842
|
+
execSync32("xclip -selection clipboard", { input: text, timeout: 3e3 });
|
|
56536
56843
|
return true;
|
|
56537
56844
|
} catch {
|
|
56538
56845
|
}
|
|
@@ -56840,7 +57147,7 @@ var init_text_selection = __esm({
|
|
|
56840
57147
|
});
|
|
56841
57148
|
|
|
56842
57149
|
// packages/cli/dist/tui/status-bar.js
|
|
56843
|
-
import { readFileSync as
|
|
57150
|
+
import { readFileSync as readFileSync37 } from "node:fs";
|
|
56844
57151
|
function setTerminalTitle(task, version) {
|
|
56845
57152
|
if (!process.stdout.isTTY)
|
|
56846
57153
|
return;
|
|
@@ -57522,7 +57829,7 @@ var init_status_bar = __esm({
|
|
|
57522
57829
|
if (nexusDir) {
|
|
57523
57830
|
try {
|
|
57524
57831
|
const metricsPath = nexusDir + "/remote-metrics.json";
|
|
57525
|
-
const raw =
|
|
57832
|
+
const raw = readFileSync37(metricsPath, "utf8");
|
|
57526
57833
|
const cached = JSON.parse(raw);
|
|
57527
57834
|
if (cached && cached.ts && Date.now() - cached.ts < 6e4) {
|
|
57528
57835
|
const m = cached.data;
|
|
@@ -59121,12 +59428,12 @@ var init_mouse_filter = __esm({
|
|
|
59121
59428
|
import * as readline2 from "node:readline";
|
|
59122
59429
|
import { Writable } from "node:stream";
|
|
59123
59430
|
import { cwd } from "node:process";
|
|
59124
|
-
import { resolve as resolve31, join as
|
|
59431
|
+
import { resolve as resolve31, join as join66, dirname as dirname20, extname as extname11 } from "node:path";
|
|
59125
59432
|
import { createRequire as createRequire2 } from "node:module";
|
|
59126
59433
|
import { fileURLToPath as fileURLToPath12 } from "node:url";
|
|
59127
|
-
import { readFileSync as
|
|
59128
|
-
import { existsSync as
|
|
59129
|
-
import { execSync as
|
|
59434
|
+
import { readFileSync as readFileSync38, writeFileSync as writeFileSync22, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync19, mkdirSync as mkdirSync23 } from "node:fs";
|
|
59435
|
+
import { existsSync as existsSync49 } from "node:fs";
|
|
59436
|
+
import { execSync as execSync33 } from "node:child_process";
|
|
59130
59437
|
import { homedir as homedir16 } from "node:os";
|
|
59131
59438
|
function formatTimeAgo(date) {
|
|
59132
59439
|
const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
|
|
@@ -59146,12 +59453,12 @@ function getVersion3() {
|
|
|
59146
59453
|
const require2 = createRequire2(import.meta.url);
|
|
59147
59454
|
const thisDir = dirname20(fileURLToPath12(import.meta.url));
|
|
59148
59455
|
const candidates = [
|
|
59149
|
-
|
|
59150
|
-
|
|
59151
|
-
|
|
59456
|
+
join66(thisDir, "..", "package.json"),
|
|
59457
|
+
join66(thisDir, "..", "..", "package.json"),
|
|
59458
|
+
join66(thisDir, "..", "..", "..", "package.json")
|
|
59152
59459
|
];
|
|
59153
59460
|
for (const pkgPath of candidates) {
|
|
59154
|
-
if (
|
|
59461
|
+
if (existsSync49(pkgPath)) {
|
|
59155
59462
|
const pkg = require2(pkgPath);
|
|
59156
59463
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
59157
59464
|
return pkg.version ?? "0.0.0";
|
|
@@ -59284,6 +59591,7 @@ function buildTools(repoRoot, config, contextWindowSize) {
|
|
|
59284
59591
|
new SemanticMapTool(repoRoot),
|
|
59285
59592
|
new RepoMapTool(repoRoot),
|
|
59286
59593
|
new ProcessHealthTool(),
|
|
59594
|
+
new VideoUnderstandTool(repoRoot),
|
|
59287
59595
|
// Full OA sub-process — callbacks wired after runner + statusBar created
|
|
59288
59596
|
(() => {
|
|
59289
59597
|
_fullSubAgentToolRef = new FullSubAgentTool(repoRoot, config.model, config.backendUrl);
|
|
@@ -59385,15 +59693,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
|
|
|
59385
59693
|
function gatherMemorySnippets(root) {
|
|
59386
59694
|
const snippets = [];
|
|
59387
59695
|
const dirs = [
|
|
59388
|
-
|
|
59389
|
-
|
|
59696
|
+
join66(root, ".oa", "memory"),
|
|
59697
|
+
join66(root, ".open-agents", "memory")
|
|
59390
59698
|
];
|
|
59391
59699
|
for (const dir of dirs) {
|
|
59392
|
-
if (!
|
|
59700
|
+
if (!existsSync49(dir))
|
|
59393
59701
|
continue;
|
|
59394
59702
|
try {
|
|
59395
|
-
for (const f of
|
|
59396
|
-
const data = JSON.parse(
|
|
59703
|
+
for (const f of readdirSync19(dir).filter((f2) => f2.endsWith(".json"))) {
|
|
59704
|
+
const data = JSON.parse(readFileSync38(join66(dir, f), "utf-8"));
|
|
59397
59705
|
for (const val of Object.values(data)) {
|
|
59398
59706
|
const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
59399
59707
|
if (v.length > 10)
|
|
@@ -59550,9 +59858,9 @@ ${metabolismMemories}
|
|
|
59550
59858
|
} catch {
|
|
59551
59859
|
}
|
|
59552
59860
|
try {
|
|
59553
|
-
const archeFile =
|
|
59554
|
-
if (
|
|
59555
|
-
const variants = JSON.parse(
|
|
59861
|
+
const archeFile = join66(repoRoot, ".oa", "arche", "variants.json");
|
|
59862
|
+
if (existsSync49(archeFile)) {
|
|
59863
|
+
const variants = JSON.parse(readFileSync38(archeFile, "utf8"));
|
|
59556
59864
|
if (variants.length > 0) {
|
|
59557
59865
|
let filtered = variants;
|
|
59558
59866
|
if (taskType) {
|
|
@@ -59689,9 +59997,9 @@ ${lines.join("\n")}
|
|
|
59689
59997
|
const compactionThreshold = modelTier === "small" ? 12e3 : modelTier === "medium" ? 24e3 : 4e4;
|
|
59690
59998
|
let identityInjection = "";
|
|
59691
59999
|
try {
|
|
59692
|
-
const ikStateFile =
|
|
59693
|
-
if (
|
|
59694
|
-
const selfState = JSON.parse(
|
|
60000
|
+
const ikStateFile = join66(repoRoot, ".oa", "identity", "self-state.json");
|
|
60001
|
+
if (existsSync49(ikStateFile)) {
|
|
60002
|
+
const selfState = JSON.parse(readFileSync38(ikStateFile, "utf8"));
|
|
59695
60003
|
const lines = [
|
|
59696
60004
|
`[Identity State v${selfState.version}]`,
|
|
59697
60005
|
`Self: ${selfState.narrative_summary}`,
|
|
@@ -60330,13 +60638,13 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
60330
60638
|
});
|
|
60331
60639
|
}
|
|
60332
60640
|
try {
|
|
60333
|
-
const ikDir =
|
|
60334
|
-
const ikFile =
|
|
60641
|
+
const ikDir = join66(repoRoot, ".oa", "identity");
|
|
60642
|
+
const ikFile = join66(ikDir, "self-state.json");
|
|
60335
60643
|
let ikState;
|
|
60336
|
-
if (
|
|
60337
|
-
ikState = JSON.parse(
|
|
60644
|
+
if (existsSync49(ikFile)) {
|
|
60645
|
+
ikState = JSON.parse(readFileSync38(ikFile, "utf8"));
|
|
60338
60646
|
} else {
|
|
60339
|
-
|
|
60647
|
+
mkdirSync23(ikDir, { recursive: true });
|
|
60340
60648
|
const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
|
|
60341
60649
|
ikState = {
|
|
60342
60650
|
self_id: `oa-${machineId}`,
|
|
@@ -60362,7 +60670,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
60362
60670
|
}
|
|
60363
60671
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
60364
60672
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
60365
|
-
|
|
60673
|
+
writeFileSync22(ikFile, JSON.stringify(ikState, null, 2));
|
|
60366
60674
|
} catch (ikErr) {
|
|
60367
60675
|
try {
|
|
60368
60676
|
console.error("[IK-OBSERVE]", ikErr);
|
|
@@ -60377,14 +60685,14 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
60377
60685
|
} else {
|
|
60378
60686
|
renderTaskIncomplete(result.turns, result.toolCalls, result.durationMs, tokens);
|
|
60379
60687
|
try {
|
|
60380
|
-
const ikFile =
|
|
60381
|
-
if (
|
|
60382
|
-
const ikState = JSON.parse(
|
|
60688
|
+
const ikFile = join66(repoRoot, ".oa", "identity", "self-state.json");
|
|
60689
|
+
if (existsSync49(ikFile)) {
|
|
60690
|
+
const ikState = JSON.parse(readFileSync38(ikFile, "utf8"));
|
|
60383
60691
|
ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
|
|
60384
60692
|
ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
|
|
60385
60693
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
60386
60694
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
60387
|
-
|
|
60695
|
+
writeFileSync22(ikFile, JSON.stringify(ikState, null, 2));
|
|
60388
60696
|
}
|
|
60389
60697
|
} catch {
|
|
60390
60698
|
}
|
|
@@ -60727,7 +61035,7 @@ Review its full output in the [${id}] tab or via full_sub_agent(action='output',
|
|
|
60727
61035
|
let p2pGateway = null;
|
|
60728
61036
|
let peerMesh = null;
|
|
60729
61037
|
let inferenceRouter = null;
|
|
60730
|
-
const secretVault = new SecretVault(
|
|
61038
|
+
const secretVault = new SecretVault(join66(repoRoot, ".oa", "vault.enc"));
|
|
60731
61039
|
let adminSessionKey = null;
|
|
60732
61040
|
const callSubAgents = /* @__PURE__ */ new Map();
|
|
60733
61041
|
const streamRenderer = new StreamRenderer();
|
|
@@ -60947,13 +61255,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
60947
61255
|
const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
|
|
60948
61256
|
return [hits, line];
|
|
60949
61257
|
}
|
|
60950
|
-
const HISTORY_DIR =
|
|
60951
|
-
const HISTORY_FILE =
|
|
61258
|
+
const HISTORY_DIR = join66(homedir16(), ".open-agents");
|
|
61259
|
+
const HISTORY_FILE = join66(HISTORY_DIR, "repl-history");
|
|
60952
61260
|
const MAX_HISTORY_LINES = 500;
|
|
60953
61261
|
let savedHistory = [];
|
|
60954
61262
|
try {
|
|
60955
|
-
if (
|
|
60956
|
-
const raw =
|
|
61263
|
+
if (existsSync49(HISTORY_FILE)) {
|
|
61264
|
+
const raw = readFileSync38(HISTORY_FILE, "utf8").trim();
|
|
60957
61265
|
if (raw)
|
|
60958
61266
|
savedHistory = raw.split("\n").reverse();
|
|
60959
61267
|
}
|
|
@@ -61033,12 +61341,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
61033
61341
|
if (!line.trim())
|
|
61034
61342
|
return;
|
|
61035
61343
|
try {
|
|
61036
|
-
|
|
61344
|
+
mkdirSync23(HISTORY_DIR, { recursive: true });
|
|
61037
61345
|
appendFileSync4(HISTORY_FILE, line + "\n", "utf8");
|
|
61038
61346
|
if (Math.random() < 0.02) {
|
|
61039
|
-
const all =
|
|
61347
|
+
const all = readFileSync38(HISTORY_FILE, "utf8").trim().split("\n");
|
|
61040
61348
|
if (all.length > MAX_HISTORY_LINES) {
|
|
61041
|
-
|
|
61349
|
+
writeFileSync22(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
|
|
61042
61350
|
}
|
|
61043
61351
|
}
|
|
61044
61352
|
} catch {
|
|
@@ -61214,7 +61522,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
61214
61522
|
} catch {
|
|
61215
61523
|
}
|
|
61216
61524
|
try {
|
|
61217
|
-
const oaDir =
|
|
61525
|
+
const oaDir = join66(repoRoot, ".oa");
|
|
61218
61526
|
const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
|
|
61219
61527
|
onInfo: (msg) => writeContent(() => renderInfo(msg)),
|
|
61220
61528
|
onError: (msg) => writeContent(() => renderWarning(msg))
|
|
@@ -61237,7 +61545,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
61237
61545
|
} catch {
|
|
61238
61546
|
}
|
|
61239
61547
|
try {
|
|
61240
|
-
const oaDir =
|
|
61548
|
+
const oaDir = join66(repoRoot, ".oa");
|
|
61241
61549
|
const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
|
|
61242
61550
|
onInfo: (msg) => writeContent(() => renderInfo(msg)),
|
|
61243
61551
|
onError: (msg) => writeContent(() => renderWarning(msg))
|
|
@@ -62121,7 +62429,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
62121
62429
|
kind,
|
|
62122
62430
|
targetUrl,
|
|
62123
62431
|
authKey,
|
|
62124
|
-
stateDir:
|
|
62432
|
+
stateDir: join66(repoRoot, ".oa"),
|
|
62125
62433
|
passthrough: passthrough ?? false,
|
|
62126
62434
|
loadbalance: loadbalance ?? false,
|
|
62127
62435
|
endpointAuth: passthrough ? currentConfig.apiKey : void 0,
|
|
@@ -62169,7 +62477,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
62169
62477
|
await tunnelGateway.stop();
|
|
62170
62478
|
tunnelGateway = null;
|
|
62171
62479
|
}
|
|
62172
|
-
const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir:
|
|
62480
|
+
const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join66(repoRoot, ".oa") });
|
|
62173
62481
|
newTunnel.on("stats", (stats) => {
|
|
62174
62482
|
statusBar.setExposeStatus({
|
|
62175
62483
|
status: stats.status,
|
|
@@ -62438,15 +62746,15 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
62438
62746
|
writeContent(() => renderInfo(`Killed ${bgKilled} background task(s).`));
|
|
62439
62747
|
}
|
|
62440
62748
|
try {
|
|
62441
|
-
const nexusDir =
|
|
62442
|
-
const pidFile =
|
|
62443
|
-
if (
|
|
62444
|
-
const pid = parseInt(
|
|
62749
|
+
const nexusDir = join66(repoRoot, OA_DIR, "nexus");
|
|
62750
|
+
const pidFile = join66(nexusDir, "daemon.pid");
|
|
62751
|
+
if (existsSync49(pidFile)) {
|
|
62752
|
+
const pid = parseInt(readFileSync38(pidFile, "utf8").trim(), 10);
|
|
62445
62753
|
if (pid > 0) {
|
|
62446
62754
|
try {
|
|
62447
62755
|
if (process.platform === "win32") {
|
|
62448
62756
|
try {
|
|
62449
|
-
|
|
62757
|
+
execSync33(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
|
|
62450
62758
|
} catch {
|
|
62451
62759
|
}
|
|
62452
62760
|
} else {
|
|
@@ -62463,17 +62771,17 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
62463
62771
|
} catch {
|
|
62464
62772
|
}
|
|
62465
62773
|
try {
|
|
62466
|
-
const voiceDir2 =
|
|
62774
|
+
const voiceDir2 = join66(homedir16(), ".open-agents", "voice");
|
|
62467
62775
|
const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
|
|
62468
62776
|
for (const pf of voicePidFiles) {
|
|
62469
|
-
const pidPath =
|
|
62470
|
-
if (
|
|
62777
|
+
const pidPath = join66(voiceDir2, pf);
|
|
62778
|
+
if (existsSync49(pidPath)) {
|
|
62471
62779
|
try {
|
|
62472
|
-
const pid = parseInt(
|
|
62780
|
+
const pid = parseInt(readFileSync38(pidPath, "utf8").trim(), 10);
|
|
62473
62781
|
if (pid > 0) {
|
|
62474
62782
|
if (process.platform === "win32") {
|
|
62475
62783
|
try {
|
|
62476
|
-
|
|
62784
|
+
execSync33(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
|
|
62477
62785
|
} catch {
|
|
62478
62786
|
}
|
|
62479
62787
|
} else {
|
|
@@ -62490,11 +62798,11 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
62490
62798
|
} catch {
|
|
62491
62799
|
}
|
|
62492
62800
|
try {
|
|
62493
|
-
|
|
62801
|
+
execSync33(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
|
|
62494
62802
|
} catch {
|
|
62495
62803
|
}
|
|
62496
|
-
const oaPath =
|
|
62497
|
-
if (
|
|
62804
|
+
const oaPath = join66(repoRoot, OA_DIR);
|
|
62805
|
+
if (existsSync49(oaPath)) {
|
|
62498
62806
|
let deleted = false;
|
|
62499
62807
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
62500
62808
|
try {
|
|
@@ -62504,14 +62812,14 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
62504
62812
|
} catch (err) {
|
|
62505
62813
|
if (attempt < 2) {
|
|
62506
62814
|
try {
|
|
62507
|
-
|
|
62815
|
+
execSync33(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
|
|
62508
62816
|
} catch {
|
|
62509
62817
|
}
|
|
62510
62818
|
} else {
|
|
62511
62819
|
writeContent(() => renderWarning(`Could not fully remove ${OA_DIR}/: ${err instanceof Error ? err.message : String(err)}`));
|
|
62512
62820
|
if (process.platform === "win32") {
|
|
62513
62821
|
try {
|
|
62514
|
-
|
|
62822
|
+
execSync33(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
|
|
62515
62823
|
deleted = true;
|
|
62516
62824
|
} catch {
|
|
62517
62825
|
}
|
|
@@ -62866,8 +63174,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
62866
63174
|
}
|
|
62867
63175
|
}
|
|
62868
63176
|
const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
|
|
62869
|
-
const isImage = isImagePath(cleanPath) &&
|
|
62870
|
-
const isMedia = !isImage && isTranscribablePath(cleanPath) &&
|
|
63177
|
+
const isImage = isImagePath(cleanPath) && existsSync49(resolve31(repoRoot, cleanPath));
|
|
63178
|
+
const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync49(resolve31(repoRoot, cleanPath));
|
|
62871
63179
|
if (activeTask) {
|
|
62872
63180
|
if (activeTask.runner.isPaused) {
|
|
62873
63181
|
activeTask.runner.resume();
|
|
@@ -62876,7 +63184,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
62876
63184
|
if (isImage) {
|
|
62877
63185
|
try {
|
|
62878
63186
|
const imgPath = resolve31(repoRoot, cleanPath);
|
|
62879
|
-
const imgBuffer =
|
|
63187
|
+
const imgBuffer = readFileSync38(imgPath);
|
|
62880
63188
|
const base64 = imgBuffer.toString("base64");
|
|
62881
63189
|
const ext = extname11(cleanPath).toLowerCase();
|
|
62882
63190
|
const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
|
|
@@ -63113,13 +63421,13 @@ NEW TASK: ${fullInput}`;
|
|
|
63113
63421
|
writeContent(() => renderError(errMsg));
|
|
63114
63422
|
if (failureStore) {
|
|
63115
63423
|
try {
|
|
63116
|
-
const { createHash:
|
|
63424
|
+
const { createHash: createHash6 } = await import("node:crypto");
|
|
63117
63425
|
failureStore.insert({
|
|
63118
63426
|
taskId: "",
|
|
63119
63427
|
sessionId: `${Date.now()}`,
|
|
63120
63428
|
repoRoot,
|
|
63121
63429
|
failureType: "runtime-error",
|
|
63122
|
-
fingerprint:
|
|
63430
|
+
fingerprint: createHash6("sha256").update(errMsg.slice(0, 200)).digest("hex").slice(0, 16),
|
|
63123
63431
|
filePath: null,
|
|
63124
63432
|
errorMessage: errMsg.slice(0, 500),
|
|
63125
63433
|
context: null,
|
|
@@ -63375,13 +63683,13 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
63375
63683
|
const handle = startTask(task, config, repoRoot);
|
|
63376
63684
|
await handle.promise;
|
|
63377
63685
|
try {
|
|
63378
|
-
const ikDir =
|
|
63379
|
-
const ikFile =
|
|
63686
|
+
const ikDir = join66(repoRoot, ".oa", "identity");
|
|
63687
|
+
const ikFile = join66(ikDir, "self-state.json");
|
|
63380
63688
|
let ikState;
|
|
63381
|
-
if (
|
|
63382
|
-
ikState = JSON.parse(
|
|
63689
|
+
if (existsSync49(ikFile)) {
|
|
63690
|
+
ikState = JSON.parse(readFileSync38(ikFile, "utf8"));
|
|
63383
63691
|
} else {
|
|
63384
|
-
|
|
63692
|
+
mkdirSync23(ikDir, { recursive: true });
|
|
63385
63693
|
ikState = {
|
|
63386
63694
|
self_id: `oa-${Date.now().toString(36)}`,
|
|
63387
63695
|
version: 1,
|
|
@@ -63403,7 +63711,7 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
63403
63711
|
ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
|
|
63404
63712
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
63405
63713
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
63406
|
-
|
|
63714
|
+
writeFileSync22(ikFile, JSON.stringify(ikState, null, 2));
|
|
63407
63715
|
} catch (ikErr) {
|
|
63408
63716
|
}
|
|
63409
63717
|
try {
|
|
@@ -63412,12 +63720,12 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
63412
63720
|
ec.archiveVariantSync(`Task: ${task.slice(0, 200)}`, "success \u2014 completed", ["general"]);
|
|
63413
63721
|
} catch {
|
|
63414
63722
|
try {
|
|
63415
|
-
const archeDir =
|
|
63416
|
-
const archeFile =
|
|
63723
|
+
const archeDir = join66(repoRoot, ".oa", "arche");
|
|
63724
|
+
const archeFile = join66(archeDir, "variants.json");
|
|
63417
63725
|
let variants = [];
|
|
63418
63726
|
try {
|
|
63419
|
-
if (
|
|
63420
|
-
variants = JSON.parse(
|
|
63727
|
+
if (existsSync49(archeFile))
|
|
63728
|
+
variants = JSON.parse(readFileSync38(archeFile, "utf8"));
|
|
63421
63729
|
} catch {
|
|
63422
63730
|
}
|
|
63423
63731
|
variants.push({
|
|
@@ -63432,15 +63740,15 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
63432
63740
|
});
|
|
63433
63741
|
if (variants.length > 50)
|
|
63434
63742
|
variants = variants.slice(-50);
|
|
63435
|
-
|
|
63436
|
-
|
|
63743
|
+
mkdirSync23(archeDir, { recursive: true });
|
|
63744
|
+
writeFileSync22(archeFile, JSON.stringify(variants, null, 2));
|
|
63437
63745
|
} catch {
|
|
63438
63746
|
}
|
|
63439
63747
|
}
|
|
63440
63748
|
try {
|
|
63441
|
-
const metaFile =
|
|
63442
|
-
if (
|
|
63443
|
-
const store = JSON.parse(
|
|
63749
|
+
const metaFile = join66(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
63750
|
+
if (existsSync49(metaFile)) {
|
|
63751
|
+
const store = JSON.parse(readFileSync38(metaFile, "utf8"));
|
|
63444
63752
|
const surfaced = store.filter((m) => m.type !== "quarantine" && m.scores?.confidence > 0.15).sort((a, b) => b.scores.utility * b.scores.confidence - a.scores.utility * a.scores.confidence).slice(0, 5);
|
|
63445
63753
|
let updated = false;
|
|
63446
63754
|
for (const item of surfaced) {
|
|
@@ -63451,7 +63759,7 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
63451
63759
|
updated = true;
|
|
63452
63760
|
}
|
|
63453
63761
|
if (updated) {
|
|
63454
|
-
|
|
63762
|
+
writeFileSync22(metaFile, JSON.stringify(store, null, 2));
|
|
63455
63763
|
}
|
|
63456
63764
|
}
|
|
63457
63765
|
} catch {
|
|
@@ -63504,9 +63812,9 @@ Rules:
|
|
|
63504
63812
|
try {
|
|
63505
63813
|
const { initDb: initDb2 } = __require("@open-agents/memory");
|
|
63506
63814
|
const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
|
|
63507
|
-
const dbDir =
|
|
63508
|
-
|
|
63509
|
-
const db = initDb2(
|
|
63815
|
+
const dbDir = join66(repoRoot, ".oa", "memory");
|
|
63816
|
+
mkdirSync23(dbDir, { recursive: true });
|
|
63817
|
+
const db = initDb2(join66(dbDir, "structured.db"));
|
|
63510
63818
|
const memStore = new ProceduralMemoryStore2(db);
|
|
63511
63819
|
memStore.createWithEmbedding({
|
|
63512
63820
|
content: content.slice(0, 600),
|
|
@@ -63521,12 +63829,12 @@ Rules:
|
|
|
63521
63829
|
db.close();
|
|
63522
63830
|
} catch {
|
|
63523
63831
|
}
|
|
63524
|
-
const metaDir =
|
|
63525
|
-
const storeFile =
|
|
63832
|
+
const metaDir = join66(repoRoot, ".oa", "memory", "metabolism");
|
|
63833
|
+
const storeFile = join66(metaDir, "store.json");
|
|
63526
63834
|
let store = [];
|
|
63527
63835
|
try {
|
|
63528
|
-
if (
|
|
63529
|
-
store = JSON.parse(
|
|
63836
|
+
if (existsSync49(storeFile))
|
|
63837
|
+
store = JSON.parse(readFileSync38(storeFile, "utf8"));
|
|
63530
63838
|
} catch {
|
|
63531
63839
|
}
|
|
63532
63840
|
store.push({
|
|
@@ -63542,26 +63850,26 @@ Rules:
|
|
|
63542
63850
|
});
|
|
63543
63851
|
if (store.length > 100)
|
|
63544
63852
|
store = store.slice(-100);
|
|
63545
|
-
|
|
63546
|
-
|
|
63853
|
+
mkdirSync23(metaDir, { recursive: true });
|
|
63854
|
+
writeFileSync22(storeFile, JSON.stringify(store, null, 2));
|
|
63547
63855
|
}
|
|
63548
63856
|
}
|
|
63549
63857
|
} catch {
|
|
63550
63858
|
}
|
|
63551
63859
|
try {
|
|
63552
|
-
const cohereSettingsFile =
|
|
63860
|
+
const cohereSettingsFile = join66(repoRoot, ".oa", "settings.json");
|
|
63553
63861
|
let cohereActive = false;
|
|
63554
63862
|
try {
|
|
63555
|
-
if (
|
|
63556
|
-
const settings = JSON.parse(
|
|
63863
|
+
if (existsSync49(cohereSettingsFile)) {
|
|
63864
|
+
const settings = JSON.parse(readFileSync38(cohereSettingsFile, "utf8"));
|
|
63557
63865
|
cohereActive = settings.cohere === true;
|
|
63558
63866
|
}
|
|
63559
63867
|
} catch {
|
|
63560
63868
|
}
|
|
63561
63869
|
if (cohereActive) {
|
|
63562
|
-
const metaFile =
|
|
63563
|
-
if (
|
|
63564
|
-
const store = JSON.parse(
|
|
63870
|
+
const metaFile = join66(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
63871
|
+
if (existsSync49(metaFile)) {
|
|
63872
|
+
const store = JSON.parse(readFileSync38(metaFile, "utf8"));
|
|
63565
63873
|
const latest = store.filter((m) => m.sourceTrace === "trajectory-extraction" || m.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
|
|
63566
63874
|
if (latest && latest.scores?.confidence >= 0.6) {
|
|
63567
63875
|
try {
|
|
@@ -63586,18 +63894,18 @@ Rules:
|
|
|
63586
63894
|
}
|
|
63587
63895
|
} catch (err) {
|
|
63588
63896
|
try {
|
|
63589
|
-
const ikFile =
|
|
63590
|
-
if (
|
|
63591
|
-
const ikState = JSON.parse(
|
|
63897
|
+
const ikFile = join66(repoRoot, ".oa", "identity", "self-state.json");
|
|
63898
|
+
if (existsSync49(ikFile)) {
|
|
63899
|
+
const ikState = JSON.parse(readFileSync38(ikFile, "utf8"));
|
|
63592
63900
|
ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
|
|
63593
63901
|
ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
|
|
63594
63902
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
63595
63903
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
63596
|
-
|
|
63904
|
+
writeFileSync22(ikFile, JSON.stringify(ikState, null, 2));
|
|
63597
63905
|
}
|
|
63598
|
-
const metaFile =
|
|
63599
|
-
if (
|
|
63600
|
-
const store = JSON.parse(
|
|
63906
|
+
const metaFile = join66(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
63907
|
+
if (existsSync49(metaFile)) {
|
|
63908
|
+
const store = JSON.parse(readFileSync38(metaFile, "utf8"));
|
|
63601
63909
|
const surfaced = store.filter((m) => m.type !== "quarantine" && m.scores?.confidence > 0.15).sort((a, b) => b.scores.utility * b.scores.confidence - a.scores.utility * a.scores.confidence).slice(0, 5);
|
|
63602
63910
|
for (const item of surfaced) {
|
|
63603
63911
|
item.accessCount = (item.accessCount || 0) + 1;
|
|
@@ -63605,15 +63913,15 @@ Rules:
|
|
|
63605
63913
|
item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
|
|
63606
63914
|
item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
|
|
63607
63915
|
}
|
|
63608
|
-
|
|
63916
|
+
writeFileSync22(metaFile, JSON.stringify(store, null, 2));
|
|
63609
63917
|
}
|
|
63610
63918
|
try {
|
|
63611
|
-
const archeDir =
|
|
63612
|
-
const archeFile =
|
|
63919
|
+
const archeDir = join66(repoRoot, ".oa", "arche");
|
|
63920
|
+
const archeFile = join66(archeDir, "variants.json");
|
|
63613
63921
|
let variants = [];
|
|
63614
63922
|
try {
|
|
63615
|
-
if (
|
|
63616
|
-
variants = JSON.parse(
|
|
63923
|
+
if (existsSync49(archeFile))
|
|
63924
|
+
variants = JSON.parse(readFileSync38(archeFile, "utf8"));
|
|
63617
63925
|
} catch {
|
|
63618
63926
|
}
|
|
63619
63927
|
variants.push({
|
|
@@ -63628,8 +63936,8 @@ Rules:
|
|
|
63628
63936
|
});
|
|
63629
63937
|
if (variants.length > 50)
|
|
63630
63938
|
variants = variants.slice(-50);
|
|
63631
|
-
|
|
63632
|
-
|
|
63939
|
+
mkdirSync23(archeDir, { recursive: true });
|
|
63940
|
+
writeFileSync22(archeFile, JSON.stringify(variants, null, 2));
|
|
63633
63941
|
} catch {
|
|
63634
63942
|
}
|
|
63635
63943
|
} catch {
|
|
@@ -63717,8 +64025,8 @@ var init_run = __esm({
|
|
|
63717
64025
|
import { glob } from "glob";
|
|
63718
64026
|
import ignore from "ignore";
|
|
63719
64027
|
import { readFile as readFile23, stat as stat4 } from "node:fs/promises";
|
|
63720
|
-
import { createHash as
|
|
63721
|
-
import { join as
|
|
64028
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
64029
|
+
import { join as join67, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
|
|
63722
64030
|
var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
|
|
63723
64031
|
var init_codebase_indexer = __esm({
|
|
63724
64032
|
"packages/indexer/dist/codebase-indexer.js"() {
|
|
@@ -63762,7 +64070,7 @@ var init_codebase_indexer = __esm({
|
|
|
63762
64070
|
const ig = ignore.default();
|
|
63763
64071
|
if (this.config.respectGitignore) {
|
|
63764
64072
|
try {
|
|
63765
|
-
const gitignoreContent = await readFile23(
|
|
64073
|
+
const gitignoreContent = await readFile23(join67(this.config.rootDir, ".gitignore"), "utf-8");
|
|
63766
64074
|
ig.add(gitignoreContent);
|
|
63767
64075
|
} catch {
|
|
63768
64076
|
}
|
|
@@ -63777,13 +64085,13 @@ var init_codebase_indexer = __esm({
|
|
|
63777
64085
|
for (const relativePath of files) {
|
|
63778
64086
|
if (ig.ignores(relativePath))
|
|
63779
64087
|
continue;
|
|
63780
|
-
const fullPath =
|
|
64088
|
+
const fullPath = join67(this.config.rootDir, relativePath);
|
|
63781
64089
|
try {
|
|
63782
64090
|
const fileStat = await stat4(fullPath);
|
|
63783
64091
|
if (fileStat.size > this.config.maxFileSize)
|
|
63784
64092
|
continue;
|
|
63785
64093
|
const content = await readFile23(fullPath);
|
|
63786
|
-
const hash =
|
|
64094
|
+
const hash = createHash5("sha256").update(content).digest("hex");
|
|
63787
64095
|
const ext = extname12(relativePath);
|
|
63788
64096
|
indexed.push({
|
|
63789
64097
|
path: fullPath,
|
|
@@ -63800,7 +64108,7 @@ var init_codebase_indexer = __esm({
|
|
|
63800
64108
|
}
|
|
63801
64109
|
buildTree(files) {
|
|
63802
64110
|
const root = {
|
|
63803
|
-
name:
|
|
64111
|
+
name: basename17(this.config.rootDir),
|
|
63804
64112
|
path: this.config.rootDir,
|
|
63805
64113
|
type: "directory",
|
|
63806
64114
|
children: []
|
|
@@ -63823,7 +64131,7 @@ var init_codebase_indexer = __esm({
|
|
|
63823
64131
|
if (!child) {
|
|
63824
64132
|
child = {
|
|
63825
64133
|
name: part,
|
|
63826
|
-
path:
|
|
64134
|
+
path: join67(current.path, part),
|
|
63827
64135
|
type: "directory",
|
|
63828
64136
|
children: []
|
|
63829
64137
|
};
|
|
@@ -63906,13 +64214,13 @@ __export(index_repo_exports, {
|
|
|
63906
64214
|
indexRepoCommand: () => indexRepoCommand
|
|
63907
64215
|
});
|
|
63908
64216
|
import { resolve as resolve32 } from "node:path";
|
|
63909
|
-
import { existsSync as
|
|
64217
|
+
import { existsSync as existsSync50, statSync as statSync16 } from "node:fs";
|
|
63910
64218
|
import { cwd as cwd2 } from "node:process";
|
|
63911
64219
|
async function indexRepoCommand(opts, _config) {
|
|
63912
64220
|
const repoRoot = resolve32(opts.repoPath ?? cwd2());
|
|
63913
64221
|
printHeader("Index Repository");
|
|
63914
64222
|
printInfo(`Indexing: ${repoRoot}`);
|
|
63915
|
-
if (!
|
|
64223
|
+
if (!existsSync50(repoRoot)) {
|
|
63916
64224
|
printError(`Path does not exist: ${repoRoot}`);
|
|
63917
64225
|
process.exit(1);
|
|
63918
64226
|
}
|
|
@@ -64164,7 +64472,7 @@ var config_exports = {};
|
|
|
64164
64472
|
__export(config_exports, {
|
|
64165
64473
|
configCommand: () => configCommand
|
|
64166
64474
|
});
|
|
64167
|
-
import { join as
|
|
64475
|
+
import { join as join68, resolve as resolve33 } from "node:path";
|
|
64168
64476
|
import { homedir as homedir17 } from "node:os";
|
|
64169
64477
|
import { cwd as cwd3 } from "node:process";
|
|
64170
64478
|
function redactIfSensitive(key, value) {
|
|
@@ -64247,7 +64555,7 @@ function handleShow(opts, config) {
|
|
|
64247
64555
|
}
|
|
64248
64556
|
}
|
|
64249
64557
|
printSection("Config File");
|
|
64250
|
-
printInfo(`~/.open-agents/config.json (${
|
|
64558
|
+
printInfo(`~/.open-agents/config.json (${join68(homedir17(), ".open-agents", "config.json")})`);
|
|
64251
64559
|
printSection("Priority Chain");
|
|
64252
64560
|
printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
|
|
64253
64561
|
printInfo(" 2. Project .oa/settings.json (--local)");
|
|
@@ -64286,7 +64594,7 @@ function handleSet(opts, _config) {
|
|
|
64286
64594
|
const coerced = coerceForSettings(key, value);
|
|
64287
64595
|
saveProjectSettings(repoRoot, { [key]: coerced });
|
|
64288
64596
|
printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
|
|
64289
|
-
printInfo(`Saved to ${
|
|
64597
|
+
printInfo(`Saved to ${join68(repoRoot, ".oa", "settings.json")}`);
|
|
64290
64598
|
printInfo("This override applies only when running in this workspace.");
|
|
64291
64599
|
} catch (err) {
|
|
64292
64600
|
printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -64544,8 +64852,8 @@ __export(eval_exports, {
|
|
|
64544
64852
|
evalCommand: () => evalCommand
|
|
64545
64853
|
});
|
|
64546
64854
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
64547
|
-
import { mkdirSync as
|
|
64548
|
-
import { join as
|
|
64855
|
+
import { mkdirSync as mkdirSync24, writeFileSync as writeFileSync23 } from "node:fs";
|
|
64856
|
+
import { join as join69 } from "node:path";
|
|
64549
64857
|
async function evalCommand(opts, config) {
|
|
64550
64858
|
const suiteName = opts.suite ?? "basic";
|
|
64551
64859
|
const suite = SUITES[suiteName];
|
|
@@ -64670,9 +64978,9 @@ async function evalCommand(opts, config) {
|
|
|
64670
64978
|
process.exit(failed > 0 ? 1 : 0);
|
|
64671
64979
|
}
|
|
64672
64980
|
function createTempEvalRepo() {
|
|
64673
|
-
const dir =
|
|
64674
|
-
|
|
64675
|
-
|
|
64981
|
+
const dir = join69(tmpdir10(), `open-agents-eval-${Date.now()}`);
|
|
64982
|
+
mkdirSync24(dir, { recursive: true });
|
|
64983
|
+
writeFileSync23(join69(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
|
|
64676
64984
|
return dir;
|
|
64677
64985
|
}
|
|
64678
64986
|
var BASIC_SUITE, FULL_SUITE, SUITES;
|
|
@@ -64732,7 +65040,7 @@ init_updater();
|
|
|
64732
65040
|
import { parseArgs as nodeParseArgs2 } from "node:util";
|
|
64733
65041
|
import { createRequire as createRequire3 } from "node:module";
|
|
64734
65042
|
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
64735
|
-
import { dirname as dirname21, join as
|
|
65043
|
+
import { dirname as dirname21, join as join70 } from "node:path";
|
|
64736
65044
|
|
|
64737
65045
|
// packages/cli/dist/cli.js
|
|
64738
65046
|
import { createInterface } from "node:readline";
|
|
@@ -64839,7 +65147,7 @@ init_output();
|
|
|
64839
65147
|
function getVersion4() {
|
|
64840
65148
|
try {
|
|
64841
65149
|
const require2 = createRequire3(import.meta.url);
|
|
64842
|
-
const pkgPath =
|
|
65150
|
+
const pkgPath = join70(dirname21(fileURLToPath13(import.meta.url)), "..", "package.json");
|
|
64843
65151
|
const pkg = require2(pkgPath);
|
|
64844
65152
|
return pkg.version;
|
|
64845
65153
|
} catch {
|