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.
Files changed (2) hide show
  1. package/dist/index.js +1142 -834
  2. 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: unlinkSync11 } = __require("node:fs");
10487
- unlinkSync11(filePath);
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: readdirSync19 } = await import("node:fs");
11663
- for (const ver of readdirSync19(nvmBase)) {
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: createHash5 } = await import("node:crypto");
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 = createHash5("sha256").update(snapshot).digest("hex");
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: createHash5 } = __require("node:crypto");
12856
- const machineId = createHash5("sha256").update(this.cwd).digest("hex").slice(0, 12);
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: mkdirSync24, writeFileSync: writeFileSync23 } = await import("node:fs");
13405
+ const { mkdirSync: mkdirSync25, writeFileSync: writeFileSync24 } = await import("node:fs");
13406
13406
  const sessionDir = join22(this.cwd, ".oa", "rlm");
13407
- mkdirSync24(sessionDir, { recursive: true });
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
- writeFileSync23(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
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: readFileSync38, existsSync: existsSync50 } = await import("node:fs");
13443
+ const { readFileSync: readFileSync39, existsSync: existsSync51 } = await import("node:fs");
13444
13444
  const sessionPath = join22(this.cwd, ".oa", "rlm", "session.json");
13445
- if (!existsSync50(sessionPath))
13445
+ if (!existsSync51(sessionPath))
13446
13446
  return null;
13447
- return JSON.parse(readFileSync38(sessionPath, "utf8"));
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: readdirSync19, readFileSync: readFileSync38 } = await import("node:fs");
13625
- const files = readdirSync19(trajDir).filter((f) => f.endsWith(".jsonl")).sort().reverse().slice(0, 3);
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 = readFileSync38(join23(trajDir, file), "utf8").split("\n").filter((l) => l.trim());
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: readFileSync38, existsSync: existsSync50 } = __require("node:fs");
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 (!existsSync50(storeFile))
14014
+ if (!existsSync51(storeFile))
14015
14015
  return "";
14016
14016
  let store = [];
14017
14017
  try {
14018
- store = JSON.parse(readFileSync38(storeFile, "utf8"));
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: readFileSync38, writeFileSync: writeFileSync23, existsSync: existsSync50, mkdirSync: mkdirSync24 } = __require("node:fs");
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 (!existsSync50(storeFile))
14043
+ if (!existsSync51(storeFile))
14044
14044
  return;
14045
14045
  let store = [];
14046
14046
  try {
14047
- store = JSON.parse(readFileSync38(storeFile, "utf8"));
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
- mkdirSync24(metaDir, { recursive: true });
14072
- writeFileSync23(storeFile, JSON.stringify(store, null, 2));
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: readFileSync38, existsSync: existsSync50 } = __require("node:fs");
14494
+ const { readFileSync: readFileSync39, existsSync: existsSync51 } = __require("node:fs");
14495
14495
  const archiveFile = join25(this.cwd, ".oa", "arche", "variants.json");
14496
- if (!existsSync50(archiveFile))
14496
+ if (!existsSync51(archiveFile))
14497
14497
  return "";
14498
14498
  let variants = [];
14499
14499
  try {
14500
- variants = JSON.parse(readFileSync38(archiveFile, "utf8"));
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: readFileSync38, writeFileSync: writeFileSync23, existsSync: existsSync50, mkdirSync: mkdirSync24 } = __require("node:fs");
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 (existsSync50(archiveFile))
14524
- variants = JSON.parse(readFileSync38(archiveFile, "utf8"));
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
- mkdirSync24(dir, { recursive: true });
14540
- writeFileSync23(archiveFile, JSON.stringify(variants, null, 2));
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 join41 } from "node:path";
21510
+ import { join as join42 } from "node:path";
21206
21511
  function venvPython(venvDir) {
21207
- return isWin ? join41(venvDir, "Scripts", "python.exe") : join41(venvDir, "bin", "python");
21512
+ return isWin ? join42(venvDir, "Scripts", "python.exe") : join42(venvDir, "bin", "python");
21208
21513
  }
21209
21514
  function venvPip(venvDir) {
21210
- return isWin ? join41(venvDir, "Scripts", "pip.exe") : join41(venvDir, "bin", "pip");
21515
+ return isWin ? join42(venvDir, "Scripts", "pip.exe") : join42(venvDir, "bin", "pip");
21211
21516
  }
21212
21517
  function venvBinDir(venvDir) {
21213
- return isWin ? join41(venvDir, "Scripts") : join41(venvDir, "bin");
21518
+ return isWin ? join42(venvDir, "Scripts") : join42(venvDir, "bin");
21214
21519
  }
21215
21520
  function venvExe(venvDir, name) {
21216
- return isWin ? join41(venvDir, "Scripts", `${name}.exe`) : join41(venvDir, "bin", name);
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 existsSync27, readFileSync as readFileSync20 } from "node:fs";
21228
- import { join as join42 } from "node:path";
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 = join42(repoRoot, ".oa", "fortemi-bridge.json");
21231
- if (!existsSync27(bridgeFile))
21535
+ const bridgeFile = join43(repoRoot, ".oa", "fortemi-bridge.json");
21536
+ if (!existsSync28(bridgeFile))
21232
21537
  return null;
21233
21538
  try {
21234
- return JSON.parse(readFileSync20(bridgeFile, "utf8"));
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 readFileSync21, writeFileSync as writeFileSync9, existsSync as existsSync28, mkdirSync as mkdirSync9 } from "node:fs";
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 = readFileSync21(patch.filePath, "utf-8");
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
- writeFileSync9(patch.filePath, updated, "utf-8");
21808
+ writeFileSync10(patch.filePath, updated, "utf-8");
21504
21809
  }
21505
21810
  function applyRewrite(patch) {
21506
- writeFileSync9(patch.filePath, patch.newContent, "utf-8");
21811
+ writeFileSync10(patch.filePath, patch.newContent, "utf-8");
21507
21812
  }
21508
21813
  function applyNewFile(patch) {
21509
- if (existsSync28(patch.filePath)) {
21814
+ if (existsSync29(patch.filePath)) {
21510
21815
  throw new Error(`Cannot create new file: "${patch.filePath}" already exists.`);
21511
21816
  }
21512
- mkdirSync9(dirname12(patch.filePath), { recursive: true });
21513
- writeFileSync9(patch.filePath, patch.newContent, "utf-8");
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 readFileSync22, existsSync as existsSync29 } from "node:fs";
22866
- import { join as join43, dirname as dirname13 } from "node:path";
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 = join43(PROMPTS_DIR, promptPath);
22872
- if (!existsSync29(fullPath)) {
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 = readFileSync22(fullPath, "utf-8");
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 = join43(__dirname4, "..", "prompts");
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 join44, extname as extname8 } from "node:path";
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 = join44(dir, entry.name);
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 join45 } from "node:path";
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 : join45(repoRoot, 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: mkdirSync24, writeFileSync: writeFileSync23 } = __require("node:fs");
26477
- const { join: join70 } = __require("node:path");
26478
- const sessionDir = join70(this._workingDirectory, ".oa", "session", this._sessionId);
26479
- mkdirSync24(sessionDir, { recursive: true });
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
- writeFileSync23(join70(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
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 existsSync30, statSync as statSync10, openSync, readSync, closeSync, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "node:fs";
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 join46 } from "node:path";
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 = join46(tmpdir7(), `nexus-stream-${randomBytes11(6).toString("hex")}.jsonl`);
27975
- writeFileSync10(streamFile, "", "utf8");
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
- unlinkSync4(streamFile);
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
- unlinkSync4(streamFile);
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
- unlinkSync4(streamFile);
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 execSync24 } from "node:child_process";
29010
- import { existsSync as existsSync31, mkdirSync as mkdirSync10, writeFileSync as writeFileSync11, readdirSync as readdirSync7 } from "node:fs";
29011
- import { join as join47, dirname as dirname14 } from "node:path";
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
- execSync24("which arecord", { stdio: "pipe" });
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
- execSync24("which sox", { stdio: "pipe" });
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
- execSync24("which ffmpeg", { stdio: "pipe" });
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
- join47(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
29098
- join47(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
29099
- join47(thisDir, "../../execution/scripts/live-whisper.py"),
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
- join47(thisDir, "../scripts/live-whisper.py"),
29102
- join47(thisDir, "../../scripts/live-whisper.py")
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 (existsSync31(p))
29412
+ if (existsSync32(p))
29106
29413
  return p;
29107
29414
  }
29108
29415
  try {
29109
- const globalRoot = execSync24("npm root -g", {
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
- join47(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
29116
- join47(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
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 (existsSync31(p))
29426
+ if (existsSync32(p))
29120
29427
  return p;
29121
29428
  }
29122
29429
  } catch {
29123
29430
  }
29124
- const nvmBase = join47(homedir10(), ".nvm", "versions", "node");
29125
- if (existsSync31(nvmBase)) {
29431
+ const nvmBase = join48(homedir10(), ".nvm", "versions", "node");
29432
+ if (existsSync32(nvmBase)) {
29126
29433
  try {
29127
- for (const ver of readdirSync7(nvmBase)) {
29128
- const p = join47(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
29129
- if (existsSync31(p))
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 = execSync24("npm root -g", {
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 (existsSync31(join47(globalRoot, "transcribe-cli", "dist", "index.js"))) {
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
- execSync24("which transcribe-cli", { stdio: "pipe" });
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 = execSync24("npm root -g", {
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 = join47(globalRoot, "transcribe-cli");
29371
- if (existsSync31(join47(tcPath, "dist", "index.js"))) {
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(join47(tcPath, "dist", "index.js"));
29681
+ return req(join48(tcPath, "dist", "index.js"));
29375
29682
  }
29376
29683
  } catch {
29377
29684
  }
29378
- const nvmBase = join47(homedir10(), ".nvm", "versions", "node");
29379
- if (existsSync31(nvmBase)) {
29685
+ const nvmBase = join48(homedir10(), ".nvm", "versions", "node");
29686
+ if (existsSync32(nvmBase)) {
29380
29687
  try {
29381
- const { readdirSync: readdirSync19 } = await import("node:fs");
29382
- for (const ver of readdirSync19(nvmBase)) {
29383
- const tcPath = join47(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
29384
- if (existsSync31(join47(tcPath, "dist", "index.js"))) {
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(join47(tcPath, "dist", "index.js"));
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
- execSync24("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
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
- execSync24("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
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
- execSync24("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
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: basename17 } = await import("node:path");
29669
- const transcriptDir = join47(outputDir, ".oa", "transcripts");
29670
- mkdirSync10(transcriptDir, { recursive: true });
29671
- const outFile = join47(transcriptDir, `${basename17(filePath)}.txt`);
29672
- writeFileSync11(outFile, result.text, "utf-8");
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: createHash5 } = __require("crypto");
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 = createHash5("sha1").update(key + GUID).digest("base64");
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: createHash5 } = __require("crypto");
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 = createHash5("sha1").update(key + GUID).digest("base64");
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 execSync25 } from "node:child_process";
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 existsSync32, readFileSync as readFileSync23, writeFileSync as writeFileSync12, unlinkSync as unlinkSync5, mkdirSync as mkdirSync11, readdirSync as readdirSync8, statSync as statSync11 } from "node:fs";
34893
- import { join as join48 } from "node:path";
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 = join48(stateDir, STATE_FILE_NAME);
34922
- if (!existsSync32(path))
35228
+ const path = join49(stateDir, STATE_FILE_NAME);
35229
+ if (!existsSync33(path))
34923
35230
  return null;
34924
- const raw = readFileSync23(path, "utf8");
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
- mkdirSync11(stateDir, { recursive: true });
34936
- writeFileSync12(join48(stateDir, STATE_FILE_NAME), JSON.stringify(state, null, 2));
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
- unlinkSync5(join48(stateDir, STATE_FILE_NAME));
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 = join48(stateDir, P2P_STATE_FILE_NAME);
35032
- if (!existsSync32(path))
35338
+ const path = join49(stateDir, P2P_STATE_FILE_NAME);
35339
+ if (!existsSync33(path))
35033
35340
  return null;
35034
- const raw = readFileSync23(path, "utf8");
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
- mkdirSync11(stateDir, { recursive: true });
35046
- writeFileSync12(join48(stateDir, P2P_STATE_FILE_NAME), JSON.stringify(state, null, 2));
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
- unlinkSync5(join48(stateDir, P2P_STATE_FILE_NAME));
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 = join48(nexusDir, "status.json");
36207
+ const statusPath = join49(nexusDir, "status.json");
35901
36208
  for (let i = 0; i < 80; i++) {
35902
36209
  try {
35903
- const raw = readFileSync23(statusPath, "utf8");
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 = join48(nexusDir, "invocations");
35935
- if (existsSync32(invocDir)) {
35936
- this._prevInvocCount = readdirSync8(invocDir).filter((f) => f.endsWith(".json")).length;
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 = join48(nexusDir, "status.json");
36271
+ const statusPath = join49(nexusDir, "status.json");
35965
36272
  try {
35966
- if (!existsSync32(statusPath)) {
36273
+ if (!existsSync33(statusPath)) {
35967
36274
  removeP2PExposeState(stateDir);
35968
36275
  return null;
35969
36276
  }
35970
- const status = JSON.parse(readFileSync23(statusPath, "utf8"));
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 = join48(nexusDir, "invocations");
36024
- if (!existsSync32(invocDir))
36330
+ const invocDir = join49(nexusDir, "invocations");
36331
+ if (!existsSync33(invocDir))
36025
36332
  return;
36026
- const files = readdirSync8(invocDir).filter((f) => f.endsWith(".json"));
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(join48(invocDir, f));
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 = join48(nexusDir, "metering.jsonl");
36352
+ const meteringFile = join49(nexusDir, "metering.jsonl");
36046
36353
  let meteringLines = lastMeteringLineCount;
36047
36354
  try {
36048
- if (existsSync32(meteringFile)) {
36049
- const content = readFileSync23(meteringFile, "utf8");
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 = join48(nexusDir, "status.json");
36076
- if (existsSync32(statusPath)) {
36077
- const status = JSON.parse(readFileSync23(statusPath, "utf8"));
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 = join48(nexusDir, "invocations");
36087
- if (existsSync32(invocDir)) {
36088
- const files = readdirSync8(invocDir);
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 = join48(nexusDir, "metering.jsonl");
36099
- if (existsSync32(meteringFile)) {
36100
- const content = readFileSync23(meteringFile, "utf8");
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 createHash2 } from "node:crypto";
36309
- import { readFileSync as readFileSync24, writeFileSync as writeFileSync13, existsSync as existsSync33, mkdirSync as mkdirSync12 } from "node:fs";
36310
- import { join as join49, dirname as dirname15 } from "node:path";
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 (!existsSync33(dir))
36523
- mkdirSync12(dir, { recursive: true });
36524
- writeFileSync13(this.storePath, blob, { mode: 384 });
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 || !existsSync33(this.storePath))
36838
+ if (!this.storePath || !existsSync34(this.storePath))
36532
36839
  return 0;
36533
- const blob = readFileSync24(this.storePath);
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 = createHash2("sha256");
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 createHash3, generateKeyPairSync } from "node:crypto";
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 = createHash3("sha256").update(this.publicKey).digest("base64url").slice(0, 22);
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: existsSync50, readFileSync: readFileSync38 } = await import("node:fs");
37655
- const { join: join70 } = await import("node:path");
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 = join70(nexusDir, "status.json");
37662
- if (existsSync50(statusPath)) {
37663
- const status = JSON.parse(readFileSync38(statusPath, "utf8"));
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 = join70(nexusDir, "pricing.json");
37671
- if (existsSync50(pricingPath)) {
37977
+ const pricingPath = join71(nexusDir, "pricing.json");
37978
+ if (existsSync51(pricingPath)) {
37672
37979
  try {
37673
- const pricing = JSON.parse(readFileSync38(pricingPath, "utf8"));
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 = join70(nexusDir, "peer-models-cache.json");
37688
- if (existsSync50(cachePath)) {
37994
+ const cachePath = join71(nexusDir, "peer-models-cache.json");
37995
+ if (existsSync51(cachePath)) {
37689
37996
  try {
37690
- const cache4 = JSON.parse(readFileSync38(cachePath, "utf8"));
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 = join70(nexusDir, "pricing.json");
37806
- if (existsSync50(pricingPath)) {
38112
+ const pricingPath = join71(nexusDir, "pricing.json");
38113
+ if (existsSync51(pricingPath)) {
37807
38114
  try {
37808
- const pricing = JSON.parse(readFileSync38(pricingPath, "utf8"));
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 readFileSync25, existsSync as existsSync34 } from "node:fs";
38089
- import { join as join50, dirname as dirname16 } from "node:path";
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 = join50(PROMPTS_DIR2, promptPath);
38095
- if (!existsSync34(fullPath)) {
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 = readFileSync25(fullPath, "utf-8");
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 = join50(__dirname5, "..", "templates");
38112
- publishedPath = join50(__dirname5, "..", "prompts", "templates");
38113
- PROMPTS_DIR2 = existsSync34(devPath) ? devPath : publishedPath;
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 join51, dirname as dirname17 } from "node:path";
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 = join51(_dir, "..");
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 existsSync35, mkdirSync as mkdirSync13, readFileSync as readFileSync26, writeFileSync as writeFileSync14, readdirSync as readdirSync9, statSync as statSync12, unlinkSync as unlinkSync6 } from "node:fs";
38269
- import { join as join52, relative as relative3, basename as basename10, extname as extname9 } from "node:path";
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 = join52(repoRoot, OA_DIR);
38579
+ const oaPath = join53(repoRoot, OA_DIR);
38273
38580
  for (const sub of SUBDIRS) {
38274
- mkdirSync13(join52(oaPath, sub), { recursive: true });
38581
+ mkdirSync14(join53(oaPath, sub), { recursive: true });
38275
38582
  }
38276
38583
  try {
38277
- const gitignorePath = join52(repoRoot, ".gitignore");
38584
+ const gitignorePath = join53(repoRoot, ".gitignore");
38278
38585
  const settingsPattern = ".oa/settings.json";
38279
- if (existsSync35(gitignorePath)) {
38280
- const content = readFileSync26(gitignorePath, "utf-8");
38586
+ if (existsSync36(gitignorePath)) {
38587
+ const content = readFileSync27(gitignorePath, "utf-8");
38281
38588
  if (!content.includes(settingsPattern)) {
38282
- writeFileSync14(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
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 existsSync35(join52(repoRoot, OA_DIR, "index"));
38597
+ return existsSync36(join53(repoRoot, OA_DIR, "index"));
38291
38598
  }
38292
38599
  function loadProjectSettings(repoRoot) {
38293
- const settingsPath = join52(repoRoot, OA_DIR, "settings.json");
38600
+ const settingsPath = join53(repoRoot, OA_DIR, "settings.json");
38294
38601
  try {
38295
- if (existsSync35(settingsPath)) {
38296
- return JSON.parse(readFileSync26(settingsPath, "utf-8"));
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 = join52(repoRoot, OA_DIR);
38304
- mkdirSync13(oaPath, { recursive: true });
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
- writeFileSync14(join52(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
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 = join52(homedir11(), ".open-agents", "settings.json");
38617
+ const settingsPath = join53(homedir11(), ".open-agents", "settings.json");
38311
38618
  try {
38312
- if (existsSync35(settingsPath)) {
38313
- return JSON.parse(readFileSync26(settingsPath, "utf-8"));
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 = join52(homedir11(), ".open-agents");
38321
- mkdirSync13(dir, { recursive: true });
38627
+ const dir = join53(homedir11(), ".open-agents");
38628
+ mkdirSync14(dir, { recursive: true });
38322
38629
  const existing = loadGlobalSettings();
38323
38630
  const merged = { ...existing, ...settings };
38324
- writeFileSync14(join52(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
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 = join52(dir, name);
38646
+ const filePath = join53(dir, name);
38340
38647
  const normalizedName = name.toLowerCase();
38341
- if (existsSync35(filePath) && !seen.has(filePath)) {
38648
+ if (existsSync36(filePath) && !seen.has(filePath)) {
38342
38649
  seen.add(filePath);
38343
38650
  try {
38344
- let content = readFileSync26(filePath, "utf-8");
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 = join52(dir, OA_DIR, "context", "project-map.md");
38359
- if (existsSync35(projectMap) && !seen.has(projectMap)) {
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 = readFileSync26(projectMap, "utf-8");
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 = join52(dir, "..");
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 = join52(repoRoot, OA_DIR, "index", "meta.json");
38699
+ const metaPath = join53(repoRoot, OA_DIR, "index", "meta.json");
38393
38700
  try {
38394
- return JSON.parse(readFileSync26(metaPath, "utf-8"));
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 = join52(repoRoot, OA_DIR, "index", "meta.json");
38401
- mkdirSync13(join52(repoRoot, OA_DIR, "index"), { recursive: true });
38402
- writeFileSync14(metaPath, JSON.stringify(meta, null, 2), "utf-8");
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 = join52(repoRoot, OA_DIR, "index", filename);
38712
+ const filePath = join53(repoRoot, OA_DIR, "index", filename);
38406
38713
  try {
38407
- return JSON.parse(readFileSync26(filePath, "utf-8"));
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 = join52(repoRoot, OA_DIR, "index", filename);
38414
- mkdirSync13(join52(repoRoot, OA_DIR, "index"), { recursive: true });
38415
- writeFileSync14(filePath, JSON.stringify(data, null, 2), "utf-8");
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 = basename10(repoRoot);
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 = join52(repoRoot, OA_DIR, "context");
38464
- mkdirSync13(contextDir, { recursive: true });
38465
- writeFileSync14(join52(contextDir, "project-map.md"), content, "utf-8");
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 = join52(repoRoot, OA_DIR, "history");
38470
- mkdirSync13(historyDir, { recursive: true });
38471
- writeFileSync14(join52(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
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 = join52(repoRoot, OA_DIR, "history");
38475
- if (!existsSync35(historyDir))
38781
+ const historyDir = join53(repoRoot, OA_DIR, "history");
38782
+ if (!existsSync36(historyDir))
38476
38783
  return [];
38477
38784
  try {
38478
- const files = readdirSync9(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
38479
- const stat5 = statSync12(join52(historyDir, f));
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(readFileSync26(join52(historyDir, f.file), "utf-8"));
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 = join52(repoRoot, OA_DIR, "history");
38495
- mkdirSync13(historyDir, { recursive: true });
38496
- writeFileSync14(join52(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
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 = join52(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
38806
+ const filePath = join53(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
38500
38807
  try {
38501
- if (!existsSync35(filePath))
38808
+ if (!existsSync36(filePath))
38502
38809
  return null;
38503
- const data = JSON.parse(readFileSync26(filePath, "utf-8"));
38810
+ const data = JSON.parse(readFileSync27(filePath, "utf-8"));
38504
38811
  try {
38505
- unlinkSync6(filePath);
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 = join52(repoRoot, OA_DIR, "context");
38515
- mkdirSync13(contextDir, { recursive: true });
38516
- const filePath = join52(contextDir, CONTEXT_SAVE_FILE);
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 (existsSync35(filePath)) {
38520
- ctx = JSON.parse(readFileSync26(filePath, "utf-8"));
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
- writeFileSync14(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
38839
+ writeFileSync15(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
38533
38840
  }
38534
38841
  function loadSessionContext(repoRoot) {
38535
- const filePath = join52(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
38842
+ const filePath = join53(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
38536
38843
  try {
38537
- if (!existsSync35(filePath))
38844
+ if (!existsSync36(filePath))
38538
38845
  return null;
38539
- return JSON.parse(readFileSync26(filePath, "utf-8"));
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 = join52(repoRoot, check.file);
38586
- if (existsSync35(filePath)) {
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(readFileSync26(filePath, "utf-8"));
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 (existsSync35(join52(repoRoot, check.pattern))) {
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 = readdirSync9(root, { withFileTypes: true }).filter((e) => !e.name.startsWith(".") || e.name === ".github").filter((e) => !SKIP_DIRS.has(e.name)).sort((a, b) => {
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 = readdirSync9(join52(root, entry.name)).filter((f) => !f.startsWith(".")).length;
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(join52(root, entry.name), maxDepth, childPrefix, depth + 1);
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 (existsSync35(filePath)) {
38663
- return JSON.parse(readFileSync26(filePath, "utf-8"));
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 = join52(filePath, "..");
38671
- mkdirSync13(dir, { recursive: true });
38672
- writeFileSync14(filePath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
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(join52(homedir11(), ".open-agents", USAGE_HISTORY_FILE));
39007
+ update(join53(homedir11(), ".open-agents", USAGE_HISTORY_FILE));
38701
39008
  if (opts?.repoRoot) {
38702
- update(join52(opts.repoRoot, OA_DIR, USAGE_HISTORY_FILE));
39009
+ update(join53(opts.repoRoot, OA_DIR, USAGE_HISTORY_FILE));
38703
39010
  }
38704
39011
  }
38705
39012
  function loadUsageHistory(kind, repoRoot) {
38706
- const globalPath = join52(homedir11(), ".open-agents", USAGE_HISTORY_FILE);
39013
+ const globalPath = join53(homedir11(), ".open-agents", USAGE_HISTORY_FILE);
38707
39014
  const globalData = loadUsageFile(globalPath);
38708
- const localData = repoRoot ? loadUsageFile(join52(repoRoot, OA_DIR, USAGE_HISTORY_FILE)) : { records: [] };
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(join52(homedir11(), ".open-agents", USAGE_HISTORY_FILE));
39046
+ remove(join53(homedir11(), ".open-agents", USAGE_HISTORY_FILE));
38740
39047
  if (repoRoot) {
38741
- remove(join52(repoRoot, OA_DIR, USAGE_HISTORY_FILE));
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 execSync26, spawn as spawn19, exec as exec2 } from "node:child_process";
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 existsSync36, writeFileSync as writeFileSync15, readFileSync as readFileSync27, appendFileSync as appendFileSync2, mkdirSync as mkdirSync14 } from "node:fs";
38792
- import { join as join53 } from "node:path";
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 = execSync26("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
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 = execSync26("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
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
- execSync26(s.install, { stdio: "inherit", timeout: 12e4 });
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
- execSync26("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
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
- execSync26("curl -fsSL https://ollama.com/install.sh | sh", {
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
- execSync26('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
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 = existsSync36("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
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
- execSync26("brew install ollama", {
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
- execSync26('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
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
- execSync26(`ollama pull ${tag}`, {
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
- execSync26("curl -fsSL https://ollama.com/install.sh | sh", {
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
- execSync26(`ollama pull ${tag}`, {
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
- execSync26("brew install python3", { stdio: "inherit", timeout: 3e5 });
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
- execSync26(s.install, { stdio: "inherit", timeout: 12e4 });
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
- execSync26("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
39686
+ execSync27("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
39380
39687
  return true;
39381
39688
  } catch {
39382
39689
  try {
39383
- execSync26("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
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
- execSync26(s.install, { stdio: "inherit", timeout: 12e4 });
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 = join53(homedir12(), ".open-agents", "models");
39834
- mkdirSync14(modelDir2, { recursive: true });
39835
- const modelfilePath = join53(modelDir2, `Modelfile.${customName}`);
39836
- writeFileSync15(modelfilePath, modelfileContent + "\n", "utf8");
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
- execSync26(`ollama create ${customName} -f ${modelfilePath}`, {
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 !existsSync36(join53(homedir12(), ".open-agents", "config.json"));
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
- execSync26(whichCmd, { stdio: "pipe", timeout: 3e3 });
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 join53(homedir12(), ".open-agents", "venv");
40225
+ return join54(homedir12(), ".open-agents", "venv");
39919
40226
  }
39920
40227
  function hasVenvModule() {
39921
40228
  try {
39922
- execSync26("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
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 ? join53(venvDir, "Scripts", "pip.exe") : join53(venvDir, "bin", "pip");
40238
+ const pipPath = isWin2 ? join54(venvDir, "Scripts", "pip.exe") : join54(venvDir, "bin", "pip");
39932
40239
  const pythonCmd = isWin2 ? "python" : "python3";
39933
- if (existsSync36(pipPath))
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
- mkdirSync14(join53(homedir12(), ".open-agents"), { recursive: true });
40252
+ mkdirSync15(join54(homedir12(), ".open-agents"), { recursive: true });
39946
40253
  const pyCmd = hasCmd(pythonCmd) ? pythonCmd : "python3";
39947
- execSync26(`${pyCmd} -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
39948
- execSync26(`"${pipPath}" install --upgrade pip`, {
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
- execSync26(`sudo -n ${cmd}`, {
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
- execSync26(`sudo -S bash -c '${escaped}'`, {
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
- execSync26(batchCmd, { stdio: "pipe", timeout: 18e4 });
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 = execSync26(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
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 = join53(venvDir, "bin");
40140
- const venvMoondream = join53(venvBin, "moondream-station");
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") && !existsSync36(venvMoondream)) {
40143
- const venvPip2 = join53(venvBin, "pip");
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
- execSync26(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
40147
- if (existsSync36(venvMoondream)) {
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 = execSync26(`"${venvPip2}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
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 = join53(venvBin, "python");
40165
- const venvPip2 = join53(venvBin, "pip");
40471
+ const venvPython2 = join54(venvBin, "python");
40472
+ const venvPip2 = join54(venvBin, "pip");
40166
40473
  let ocrStackInstalled = false;
40167
40474
  try {
40168
- execSync26(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
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
- execSync26(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
40483
+ execSync27(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
40177
40484
  try {
40178
- execSync26(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
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
- execSync26(`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 });
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
- execSync26(`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 });
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
- execSync26("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
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 = join53(homedir12(), ".open-agents", "models");
40310
- mkdirSync14(modelDir2, { recursive: true });
40311
- const modelfilePath = join53(modelDir2, `Modelfile.${customName}`);
40312
- writeFileSync15(modelfilePath, modelfileContent + "\n", "utf8");
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 = execSync26("which nvim 2>/dev/null || where nvim 2>nul", {
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 = join53(homedir12(), ".local", "bin");
40387
- const nvimDest = join53(binDir, "nvim");
40693
+ const binDir = join54(homedir12(), ".local", "bin");
40694
+ const nvimDest = join54(binDir, "nvim");
40388
40695
  try {
40389
- mkdirSync14(binDir, { recursive: true });
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
- execSync26(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
40397
- execSync26(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
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 = execSync26(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
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
- execSync26("brew install neovim", { stdio: "inherit", timeout: 12e4 });
40419
- const nvimPath = execSync26("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
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
- execSync26("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
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
- execSync26("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
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") ? join53(homedir12(), ".zshrc") : join53(homedir12(), ".bashrc");
40765
+ const rcFile = shell.includes("zsh") ? join54(homedir12(), ".zshrc") : join54(homedir12(), ".bashrc");
40459
40766
  try {
40460
- const rcContent = existsSync36(rcFile) ? readFileSync27(rcFile, "utf8") : "";
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 existsSync37 } from "node:fs";
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 (!existsSync37(filePath)) {
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 existsSync38, unlinkSync as unlinkSync7 } from "node:fs";
41668
+ import { existsSync as existsSync39, unlinkSync as unlinkSync8 } from "node:fs";
41362
41669
  import { tmpdir as tmpdir8 } from "node:os";
41363
- import { join as join54 } from "node:path";
41364
- import { execSync as execSync27 } from "node:child_process";
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 = execSync27("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
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 = join54(tmpdir8(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
41718
+ const socketPath = join55(tmpdir8(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
41412
41719
  try {
41413
- if (existsSync38(socketPath))
41414
- unlinkSync7(socketPath);
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 (!existsSync38(state.socketPath) && attempts < 30) {
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 (!existsSync38(state.socketPath))
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 (existsSync38(state.socketPath))
41784
- unlinkSync7(state.socketPath);
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 existsSync39, mkdirSync as mkdirSync15, writeFileSync as writeFileSync16, readFileSync as readFileSync28, unlinkSync as unlinkSync8, readdirSync as readdirSync10, renameSync, statSync as statSync13 } from "node:fs";
41841
- import { join as join55, dirname as dirname18 } from "node:path";
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 execSync28, spawn as nodeSpawn } from "node:child_process";
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 join55(homedir13(), ".open-agents", "voice");
42173
+ return join56(homedir13(), ".open-agents", "voice");
41867
42174
  }
41868
42175
  function modelsDir() {
41869
- return join55(voiceDir(), "models");
42176
+ return join56(voiceDir(), "models");
41870
42177
  }
41871
42178
  function modelDir(id) {
41872
- return join55(modelsDir(), id);
42179
+ return join56(modelsDir(), id);
41873
42180
  }
41874
42181
  function modelOnnxPath(id) {
41875
- return join55(modelDir(id), "model.onnx");
42182
+ return join56(modelDir(id), "model.onnx");
41876
42183
  }
41877
42184
  function modelConfigPath(id) {
41878
- return join55(modelDir(id), "config.json");
42185
+ return join56(modelDir(id), "config.json");
41879
42186
  }
41880
42187
  function luxttsVenvDir() {
41881
- return join55(voiceDir(), "luxtts-venv");
42188
+ return join56(voiceDir(), "luxtts-venv");
41882
42189
  }
41883
42190
  function luxttsVenvPy() {
41884
- return platform3() === "win32" ? join55(luxttsVenvDir(), "Scripts", "python.exe") : join55(luxttsVenvDir(), "bin", "python3");
42191
+ return platform3() === "win32" ? join56(luxttsVenvDir(), "Scripts", "python.exe") : join56(luxttsVenvDir(), "bin", "python3");
41885
42192
  }
41886
42193
  function luxttsRepoDir() {
41887
- return join55(voiceDir(), "LuxTTS");
42194
+ return join56(voiceDir(), "LuxTTS");
41888
42195
  }
41889
42196
  function luxttsCloneRefsDir() {
41890
- return join55(voiceDir(), "clone-refs");
42197
+ return join56(voiceDir(), "clone-refs");
41891
42198
  }
41892
42199
  function luxttsInferScript() {
41893
- return join55(voiceDir(), "luxtts-infer.py");
42200
+ return join56(voiceDir(), "luxtts-infer.py");
41894
42201
  }
41895
42202
  function writeDetectTorchScript(targetPath) {
41896
- if (existsSync39(targetPath))
42203
+ if (existsSync40(targetPath))
41897
42204
  return;
41898
42205
  try {
41899
- mkdirSync15(dirname18(targetPath), { recursive: true });
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
- writeFileSync16(targetPath, script, { mode: 493 });
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 = join55(refsDir, `${modelId}-ref.wav`);
42783
- if (existsSync39(refFile))
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 = join55(homedir13(), p.slice(1));
43169
+ p = join56(homedir13(), p.slice(1));
42863
43170
  }
42864
- if (!existsSync39(p)) {
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 (!existsSync39(refsDir))
42871
- mkdirSync15(refsDir, { recursive: true });
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 = join55(refsDir, destFilename);
43183
+ const destPath = join56(refsDir, destFilename);
42877
43184
  try {
42878
- const data = readFileSync28(audioPath);
42879
- writeFileSync16(destPath, data);
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 (!existsSync39(refsDir))
42920
- mkdirSync15(refsDir, { recursive: true });
42921
- const destPath = join55(refsDir, `${sourceModelId}-ref.wav`);
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 join55(luxttsCloneRefsDir(), "meta.json");
43244
+ return join56(luxttsCloneRefsDir(), "meta.json");
42938
43245
  }
42939
43246
  loadCloneMeta() {
42940
43247
  const p = _VoiceEngine.cloneMetaFile();
42941
- if (!existsSync39(p))
43248
+ if (!existsSync40(p))
42942
43249
  return {};
42943
43250
  try {
42944
- return JSON.parse(readFileSync28(p, "utf8"));
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 (!existsSync39(dir))
42952
- mkdirSync15(dir, { recursive: true });
42953
- writeFileSync16(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
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 (!existsSync39(dir))
43270
+ if (!existsSync40(dir))
42964
43271
  return [];
42965
43272
  const meta = this.loadCloneMeta();
42966
- const files = readdirSync10(dir).filter((f) => {
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 = join55(dir, f);
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 = join55(luxttsCloneRefsDir(), filename);
42989
- if (!existsSync39(p))
43295
+ const p = join56(luxttsCloneRefsDir(), filename);
43296
+ if (!existsSync40(p))
42990
43297
  return false;
42991
43298
  try {
42992
- unlinkSync8(p);
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 = join55(luxttsCloneRefsDir(), filename);
43014
- if (!existsSync39(p))
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
- unlinkSync8(prefetchedWav.path);
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 = join55(tmpdir9(), `oa-voice-${Date.now()}.wav`);
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
- unlinkSync8(wavPath);
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
- writeFileSync16(path, buffer);
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
- writeFileSync16(path, this.buildWavBuffer(samples, sampleRate));
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
- execSync28(`which ${player}`, { stdio: "pipe" });
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 = execSync28(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
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
- execSync28(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
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 = join55(tmpdir9(), `oa-mlx-${Date.now()}.wav`);
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
- execSync28(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
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
- execSync28(`${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() });
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 (!existsSync39(wavPath))
44056
+ if (!existsSync40(wavPath))
43750
44057
  return;
43751
44058
  if (volume !== 1) {
43752
44059
  try {
43753
- const wavData = readFileSync28(wavPath);
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
- writeFileSync16(wavPath, scaled);
44068
+ writeFileSync17(wavPath, scaled);
43762
44069
  }
43763
44070
  } catch {
43764
44071
  }
43765
44072
  }
43766
44073
  if (this.onPCMOutput) {
43767
44074
  try {
43768
- const wavData = readFileSync28(wavPath);
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
- unlinkSync8(wavPath);
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 = join55(tmpdir9(), `oa-mlx-buf-${Date.now()}.wav`);
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
- execSync28(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
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
- execSync28(`${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() });
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 (!existsSync39(wavPath))
44124
+ if (!existsSync40(wavPath))
43818
44125
  return null;
43819
44126
  try {
43820
- const data = readFileSync28(wavPath);
43821
- unlinkSync8(wavPath);
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 (existsSync39(venvPy)) {
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 = join55(voiceDir(), "detect-torch.py");
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 (!existsSync39(venvDir)) {
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 = join55(voiceDir(), "detect-torch.py");
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 (!existsSync39(join55(repoDir, "zipvoice", "luxvoice.py"))) {
44235
+ if (!existsSync40(join56(repoDir, "zipvoice", "luxvoice.py"))) {
43929
44236
  renderInfo(" Cloning LuxTTS repository...");
43930
44237
  try {
43931
- if (existsSync39(repoDir)) {
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 && (existsSync39("/etc/nv_tegra_release") || existsSync39("/usr/local/cuda/targets/aarch64-linux") || (process.env.JETSON_L4T_VERSION ?? "") !== "");
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 && existsSync39(this.luxttsCloneRef))
44345
+ if (this.luxttsCloneRef && existsSync40(this.luxttsCloneRef))
44039
44346
  return;
44040
44347
  const refsDir = luxttsCloneRefsDir();
44041
- if (!existsSync39(refsDir))
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 = join55(refsDir, name);
44045
- if (existsSync39(p)) {
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
- mkdirSync15(voiceDir(), { recursive: true });
44146
- writeFileSync16(scriptPath2, script);
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 (!existsSync39(venvPy))
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 || !existsSync39(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 = join55(tmpdir9(), `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
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 existsSync39(wavPath) ? wavPath : null;
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 (!existsSync39(wavPath))
44571
+ if (!existsSync40(wavPath))
44265
44572
  return;
44266
44573
  try {
44267
- const wavData = readFileSync28(wavPath);
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
- writeFileSync16(wavPath, scaled);
44589
+ writeFileSync17(wavPath, scaled);
44283
44590
  }
44284
44591
  } catch {
44285
44592
  }
44286
44593
  if (pitchFactor !== 1) {
44287
44594
  try {
44288
- const wavData = readFileSync28(wavPath);
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 = readFileSync28(wavPath);
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 = readFileSync28(wavPath);
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
- unlinkSync8(wavPath);
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 || !existsSync39(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 = join55(tmpdir9(), `oa-luxtts-buf-${Date.now()}.wav`);
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 (!existsSync39(wavPath))
44677
+ if (!existsSync40(wavPath))
44371
44678
  return null;
44372
44679
  try {
44373
- const data = readFileSync28(wavPath);
44374
- unlinkSync8(wavPath);
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
- mkdirSync15(voiceDir(), { recursive: true });
44388
- const pkgPath = join55(voiceDir(), "package.json");
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 (existsSync39(pkgPath)) {
44700
+ if (existsSync40(pkgPath)) {
44394
44701
  try {
44395
- const existing = JSON.parse(readFileSync28(pkgPath, "utf8"));
44702
+ const existing = JSON.parse(readFileSync29(pkgPath, "utf8"));
44396
44703
  if (!existing.dependencies?.["phonemizer"]) {
44397
44704
  existing.dependencies = { ...existing.dependencies, ...expectedDeps };
44398
- writeFileSync16(pkgPath, JSON.stringify(existing, null, 2));
44705
+ writeFileSync17(pkgPath, JSON.stringify(existing, null, 2));
44399
44706
  }
44400
44707
  } catch {
44401
44708
  }
44402
44709
  }
44403
- if (!existsSync39(pkgPath)) {
44404
- writeFileSync16(pkgPath, JSON.stringify({
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(join55(voiceDir(), "index.js"));
44717
+ const voiceRequire = createRequire(join56(voiceDir(), "index.js"));
44411
44718
  const probeOnnx = async () => {
44412
44719
  try {
44413
- const output = await this.asyncShell(`NODE_PATH="${join55(voiceDir(), "node_modules")}" node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, 15e3);
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 = join55(voiceDir(), "node_modules", "onnxruntime-node");
44420
- const onnxInstalled = existsSync39(onnxNodeModules);
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 (existsSync39(onnxPath) && existsSync39(configPath))
44777
+ if (existsSync40(onnxPath) && existsSync40(configPath))
44471
44778
  return;
44472
- mkdirSync15(dir, { recursive: true });
44473
- if (!existsSync39(configPath)) {
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
- writeFileSync16(configPath, configText);
44786
+ writeFileSync17(configPath, configText);
44480
44787
  }
44481
- if (!existsSync39(onnxPath)) {
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
- writeFileSync16(onnxPath, fullBuffer);
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 (!existsSync39(onnxPath) || !existsSync39(configPath)) {
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(readFileSync28(configPath, "utf8"));
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 existsSync40, readFileSync as readFileSync29, writeFileSync as writeFileSync17, mkdirSync as mkdirSync16, readdirSync as readdirSync11, statSync as statSync14, rmSync } from "node:fs";
44549
- import { join as join56 } from "node:path";
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 = join56(ctx.repoRoot, ".oa", "tools");
45159
- const toolFile = join56(toolDir, shareName.endsWith(".json") ? shareName : `${shareName}.json`);
45160
- if (!existsSync40(toolFile)) {
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 = readFileSync29(toolFile, "utf8");
45471
+ content = readFileSync30(toolFile, "utf8");
45165
45472
  metadata = { type: "tool", name: shareName };
45166
45473
  } else if (shareType === "skill") {
45167
- const skillDir = join56(ctx.repoRoot, ".oa", "skills", shareName);
45168
- const skillFile = join56(skillDir, "SKILL.md");
45169
- if (!existsSync40(skillFile)) {
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 = readFileSync29(skillFile, "utf8");
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 = join56(ctx.repoRoot, ".oa", "nexus", "ipfs", "cid-registry", "learning-cids.json");
45213
- if (existsSync40(regFile)) {
45214
- const reg = JSON.parse(readFileSync29(regFile, "utf8"));
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 = join56(ctx.repoRoot, ".oa", "ipfs");
45268
- const ipfsLocalDir = join56(ipfsDir, "local");
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 (existsSync40(ipfsLocalDir)) {
45275
- const files = readdirSync11(ipfsLocalDir).filter((f) => f.endsWith(".json"));
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(join56(ipfsLocalDir, f)).size;
45586
+ ipfsBytes += statSync14(join57(ipfsLocalDir, f)).size;
45280
45587
  } catch {
45281
45588
  }
45282
45589
  }
45283
45590
  }
45284
- const heliaBlockDir = join56(ipfsDir, "blocks");
45285
- if (existsSync40(heliaBlockDir)) {
45591
+ const heliaBlockDir = join57(ipfsDir, "blocks");
45592
+ if (existsSync41(heliaBlockDir)) {
45286
45593
  const walkDir = (dir) => {
45287
- for (const entry of readdirSync11(dir, { withFileTypes: true })) {
45594
+ for (const entry of readdirSync12(dir, { withFileTypes: true })) {
45288
45595
  if (entry.isDirectory())
45289
- walkDir(join56(dir, entry.name));
45596
+ walkDir(join57(dir, entry.name));
45290
45597
  else {
45291
45598
  heliaBlocks++;
45292
45599
  try {
45293
- heliaBytes += statSync14(join56(dir, entry.name)).size;
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 = join56(ctx.repoRoot, ".oa", "nexus", "status.json");
45310
- if (existsSync40(statusFile)) {
45311
- const status = JSON.parse(readFileSync29(statusFile, "utf8"));
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 = join56(ctx.repoRoot, ".oa", "identity");
45637
+ const idDir = join57(ctx.repoRoot, ".oa", "identity");
45331
45638
  try {
45332
- const stateFile = join56(idDir, "self-state.json");
45333
- if (existsSync40(stateFile)) {
45334
- const state = JSON.parse(readFileSync29(stateFile, "utf8"));
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 = join56(idDir, "cids.json");
45344
- if (existsSync40(cidFile)) {
45345
- const cids = JSON.parse(readFileSync29(cidFile, "utf8"));
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 = join56(ctx.repoRoot, ".oa", "memory", "metabolism", "store.json");
45359
- if (existsSync40(metaFile)) {
45360
- const store = JSON.parse(readFileSync29(metaFile, "utf8"));
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 = join56(ctx.repoRoot, ".oa", "memory", "structured.db");
45379
- if (existsSync40(dbPath)) {
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 = join56(ctx.repoRoot, ".oa");
45401
- if (!existsSync40(oaDir)) {
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 readdirSync11(dir, { withFileTypes: true })) {
45411
- const full = join56(dir, entry.name);
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 readdirSync11(dir, { withFileTypes: true })) {
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(join56(dir, entry.name).replace(oaDir + "/", ""));
45754
+ sensitiveFound.push(join57(dir, entry.name).replace(oaDir + "/", ""));
45448
45755
  }
45449
45756
  if (entry.isDirectory())
45450
- checkSensitive(join56(dir, entry.name));
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 = join56(ctx.repoRoot, filePath);
45479
- if (!existsSync40(resolvedPath)) {
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 = join56(ctx.repoRoot, ".oa", "memory");
45496
- mkdirSync16(dbDir, { recursive: true });
45497
- const db = initDb2(join56(dbDir, "structured.db"));
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 = readFileSync29(resolvedPath, "utf8");
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 = join56(ctx.repoRoot, "..", "fortemi-react");
45578
- const altFortemiDir = join56(nodeOs.homedir(), "fortemi-react");
45579
- const fDir = existsSync40(fortemiDir) ? fortemiDir : existsSync40(altFortemiDir) ? altFortemiDir : null;
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 = join56(ctx.repoRoot, ".oa", "fortemi-jwt.json");
45595
- mkdirSync16(join56(ctx.repoRoot, ".oa"), { recursive: true });
45596
- writeFileSync17(jwtFile, JSON.stringify(jwtPayload, null, 2));
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: join56(fDir, "apps", "standalone"),
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 = join56(ctx.repoRoot, ".oa", "fortemi-bridge.json");
45611
- writeFileSync17(bridgeFile, JSON.stringify({
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 = join56(ctx.repoRoot, ".oa", "fortemi-bridge.json");
45624
- if (!existsSync40(bridgeFile)) {
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(readFileSync29(bridgeFile, "utf8"));
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: ${existsSync40(bridge.jwtFile) ? c2.green("valid") : c2.yellow("missing")}`);
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 = join56(ctx.repoRoot, ".oa", "fortemi-bridge.json");
45655
- if (existsSync40(bridgeFile)) {
45656
- const bridge = JSON.parse(readFileSync29(bridgeFile, "utf8"));
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 = join56(ctx.repoRoot, ".oa", "identity", "snapshots");
47036
- if (existsSync40(snapDir)) {
47037
- const snaps = readdirSync11(snapDir).filter((f) => f.endsWith(".json")).sort().reverse();
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(join56(snapDir, f)).size)}`
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: basename17, join: pathJoin } = await import("node:path");
47357
- const { copyFileSync: copyFileSync2, mkdirSync: mkdirSync24, existsSync: exists } = await import("node:fs");
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 = basename17(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
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
- mkdirSync24(destDir, { recursive: true });
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: basename17, join: pjoin } = __require("node:path");
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 = basename17(src);
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: writeFileSync23, mkdirSync: mkdirSync24 } = await import("node:fs");
47855
- const { join: join70, dirname: dirname22 } = await import("node:path");
47856
- const cachePath = join70(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
47857
- mkdirSync24(dirname22(cachePath), { recursive: true });
47858
- writeFileSync23(cachePath, JSON.stringify({
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: execSync33 } = await import("node:child_process");
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 = execSync33("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
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 = execSync33("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
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
- execSync33(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
47975
- execSync33(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
47976
- execSync33("sudo systemctl daemon-reload", { stdio: "pipe" });
47977
- execSync33("sudo systemctl restart ollama.service", { stdio: "pipe" });
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
- execSync33("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
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: join70 } = await import("node:path");
48058
- const { existsSync: existsSync50 } = await import("node:fs");
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
- join70(thisDir, "..", "package.json"),
48063
- join70(thisDir, "..", "..", "package.json"),
48064
- join70(thisDir, "..", "..", "..", "package.json")
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 (existsSync50(pkgPath)) {
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: execSync33 } = __require("node:child_process");
49114
+ const { execSync: execSync34 } = __require("node:child_process");
48808
49115
  const platform6 = process.platform;
48809
49116
  if (platform6 === "darwin") {
48810
- execSync33("pbcopy", { input: cmd, timeout: 3e3 });
49117
+ execSync34("pbcopy", { input: cmd, timeout: 3e3 });
48811
49118
  copied = true;
48812
49119
  } else if (platform6 === "win32") {
48813
- execSync33("clip", { input: cmd, timeout: 3e3 });
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
- execSync33(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
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 existsSync41, readFileSync as readFileSync30, readdirSync as readdirSync12 } from "node:fs";
48906
- import { join as join57, basename as basename11 } from "node:path";
48907
- import { execSync as execSync29 } from "node:child_process";
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 = join57(repoRoot, OA_DIR, "context", "project-map.md");
48942
- if (existsSync41(mapPath2)) {
49248
+ const mapPath2 = join58(repoRoot, OA_DIR, "context", "project-map.md");
49249
+ if (existsSync42(mapPath2)) {
48943
49250
  try {
48944
- const content = readFileSync30(mapPath2, "utf-8");
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
- execSync29("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
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 = execSync29("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
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 = execSync29("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
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 = execSync29("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
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 = join57(repoRoot, OA_DIR, "memory");
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 = join57(repoRoot, ".open-agents", "memory");
48990
- if (legacyMemDir !== oaMemDir && existsSync41(legacyMemDir)) {
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 = join57(homedir15(), ".open-agents", "memory");
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 (!existsSync41(memDir))
49309
+ if (!existsSync42(memDir))
49003
49310
  return "";
49004
49311
  const lines = [];
49005
49312
  try {
49006
- const files = readdirSync12(memDir).filter((f) => f.endsWith(".json"));
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 = readFileSync30(join57(memDir, file), "utf-8");
49316
+ const raw = readFileSync31(join58(memDir, file), "utf-8");
49010
49317
  const entries = JSON.parse(raw);
49011
- const topic = basename11(file, ".json");
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 existsSync42, readFileSync as readFileSync31, writeFileSync as writeFileSync18, mkdirSync as mkdirSync17, readdirSync as readdirSync13 } from "node:fs";
50529
- import { join as join58, basename as basename12 } from "node:path";
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 = join58(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
50838
+ const filePath = join59(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
50532
50839
  try {
50533
- if (!existsSync42(filePath))
50840
+ if (!existsSync43(filePath))
50534
50841
  return null;
50535
- return JSON.parse(readFileSync31(filePath, "utf-8"));
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 = join58(repoRoot, OA_DIR, "context");
50542
- mkdirSync17(contextDir, { recursive: true });
50543
- writeFileSync18(join58(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
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 = join58(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
50908
+ const filePath = join59(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
50602
50909
  try {
50603
- if (!existsSync42(filePath))
50910
+ if (!existsSync43(filePath))
50604
50911
  return null;
50605
- const cached = JSON.parse(readFileSync31(filePath, "utf-8"));
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 = join58(repoRoot, OA_DIR, "context");
50613
- mkdirSync17(contextDir, { recursive: true });
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
- writeFileSync18(join58(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
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 = basename12(repoRoot);
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 = join58(repoRoot, "package.json");
50974
+ const pkgPath = join59(repoRoot, "package.json");
50668
50975
  try {
50669
- if (!existsSync42(pkgPath))
50976
+ if (!existsSync43(pkgPath))
50670
50977
  return;
50671
- const pkg = JSON.parse(readFileSync31(pkgPath, "utf-8"));
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 (existsSync42(join58(repoRoot, check.file))) {
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 = join58(repoRoot, OA_DIR, "memory");
51044
+ const memoryDir = join59(repoRoot, OA_DIR, "memory");
50738
51045
  try {
50739
- if (!existsSync42(memoryDir))
51046
+ if (!existsSync43(memoryDir))
50740
51047
  return;
50741
- const files = readdirSync13(memoryDir).filter((f) => f.endsWith(".json"));
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(readFileSync31(join58(memoryDir, file), "utf-8"));
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 mkdirSync18 } from "node:fs";
51380
- import { join as join59 } from "node:path";
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 = join59(repoRoot, ".oa", "history");
51383
- const logPath2 = join59(historyDir, "edits.jsonl");
51689
+ const historyDir = join60(repoRoot, ".oa", "history");
51690
+ const logPath2 = join60(historyDir, "edits.jsonl");
51384
51691
  try {
51385
- mkdirSync18(historyDir, { recursive: true });
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 readFileSync32, existsSync as existsSync43 } from "node:fs";
51495
- import { join as join60, dirname as dirname19 } from "node:path";
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 = join60(PROMPTS_DIR3, promptPath);
51501
- if (!existsSync43(fullPath)) {
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 = readFileSync32(fullPath, "utf-8");
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 = join60(__dirname6, "..", "..", "prompts");
51518
- publishedPath2 = join60(__dirname6, "..", "prompts");
51519
- PROMPTS_DIR3 = existsSync43(devPath2) ? devPath2 : publishedPath2;
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 mkdirSync19, writeFileSync as writeFileSync19, readFileSync as readFileSync33, existsSync as existsSync44, cpSync, rmSync as rmSync2, readdirSync as readdirSync14 } from "node:fs";
51526
- import { join as join61, basename as basename13 } from "node:path";
51527
- import { execSync as execSync30 } from "node:child_process";
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 = join61(repoRoot, ".oa", "memory", "autoresearch.json");
51530
- if (!existsSync44(memoryPath))
51836
+ const memoryPath = join62(repoRoot, ".oa", "memory", "autoresearch.json");
51837
+ if (!existsSync45(memoryPath))
51531
51838
  return "";
51532
51839
  try {
51533
- const raw = readFileSync33(memoryPath, "utf-8");
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") ? join61(this.autoresearchDir, basename13(rawPath)) : join61(this.autoresearchDir, rawPath);
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 = join61(targetPath, "..");
51729
- mkdirSync19(dir, { recursive: true });
51730
- writeFileSync19(targetPath, content, "utf-8");
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") ? join61(this.autoresearchDir, basename13(rawPath)) : join61(this.autoresearchDir, rawPath);
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 (!existsSync44(targetPath)) {
52070
+ if (!existsSync45(targetPath)) {
51764
52071
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
51765
52072
  }
51766
- let content = readFileSync33(targetPath, "utf-8");
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
- writeFileSync19(targetPath, content, "utf-8");
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") ? join61(this.dreamsDir, basename13(rawPath)) : join61(this.dreamsDir, rawPath);
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 = join61(targetPath, "..");
51818
- mkdirSync19(dir, { recursive: true });
51819
- writeFileSync19(targetPath, content, "utf-8");
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") ? join61(this.dreamsDir, basename13(rawPath)) : join61(this.dreamsDir, rawPath);
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 (!existsSync44(targetPath)) {
52159
+ if (!existsSync45(targetPath)) {
51853
52160
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
51854
52161
  }
51855
- let content = readFileSync33(targetPath, "utf-8");
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
- writeFileSync19(targetPath, content, "utf-8");
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 = execSync30(cmd, {
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 = join61(repoRoot, ".oa", "dreams");
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
- mkdirSync19(this.dreamsDir, { recursive: true });
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 = join61(this.dreamsDir, `cycle-${cycle}-summary.md`);
51999
- writeFileSync19(summaryPath, cycleSummary, "utf-8");
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 = join61(this.repoRoot, ".oa", "autoresearch");
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 = join61(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
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
- mkdirSync19(this.dreamsDir, { recursive: true });
52598
- writeFileSync19(reportPath, report, "utf-8");
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 = join61(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
52971
+ const checkpointDir = join62(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
52665
52972
  try {
52666
- mkdirSync19(checkpointDir, { recursive: true });
52973
+ mkdirSync20(checkpointDir, { recursive: true });
52667
52974
  try {
52668
- const gitStatus = execSync30("git status --porcelain", {
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 = execSync30("git diff", {
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 = execSync30("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
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
- writeFileSync19(join61(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
52684
- writeFileSync19(join61(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
52685
- writeFileSync19(join61(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
52686
- writeFileSync19(join61(checkpointDir, "checkpoint.json"), JSON.stringify({
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
- writeFileSync19(join61(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
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 = readdirSync14(this.dreamsDir).filter((f) => f.endsWith(".md") && f !== "PROPOSAL-INDEX.md" && f !== "dream-state.json").sort();
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
- writeFileSync19(join61(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
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
- writeFileSync19(join61(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
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 existsSync45, readFileSync as readFileSync34, writeFileSync as writeFileSync20, mkdirSync as mkdirSync20, readdirSync as readdirSync15, unlinkSync as unlinkSync9 } from "node:fs";
53134
- import { join as join62, basename as basename14 } from "node:path";
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 = join62(repoRoot, ".oa", "dmn");
53255
- this.historyDir = join62(repoRoot, ".oa", "dmn", "cycles");
53256
- mkdirSync20(this.historyDir, { recursive: true });
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
- join62(this.repoRoot, ".oa", "memory"),
53846
- join62(this.repoRoot, ".open-agents", "memory")
54152
+ join63(this.repoRoot, ".oa", "memory"),
54153
+ join63(this.repoRoot, ".open-agents", "memory")
53847
54154
  ];
53848
54155
  for (const dir of dirs) {
53849
- if (!existsSync45(dir))
54156
+ if (!existsSync46(dir))
53850
54157
  continue;
53851
54158
  try {
53852
- const files = readdirSync15(dir).filter((f) => f.endsWith(".json"));
54159
+ const files = readdirSync16(dir).filter((f) => f.endsWith(".json"));
53853
54160
  for (const f of files) {
53854
- const topic = basename14(f, ".json");
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 = join62(this.stateDir, "state.json");
53866
- if (existsSync45(path)) {
54172
+ const path = join63(this.stateDir, "state.json");
54173
+ if (existsSync46(path)) {
53867
54174
  try {
53868
- this.state = JSON.parse(readFileSync34(path, "utf-8"));
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
- writeFileSync20(join62(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
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
- writeFileSync20(join62(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
53883
- const files = readdirSync15(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
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
- unlinkSync9(join62(this.historyDir, old));
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 existsSync46, readdirSync as readdirSync16, readFileSync as readFileSync35 } from "node:fs";
53901
- import { join as join63, basename as basename15 } from "node:path";
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
- join63(this.repoRoot, ".oa", "memory"),
54142
- join63(this.repoRoot, ".open-agents", "memory")
54448
+ join64(this.repoRoot, ".oa", "memory"),
54449
+ join64(this.repoRoot, ".open-agents", "memory")
54143
54450
  ];
54144
54451
  for (const dir of dirs) {
54145
- if (!existsSync46(dir))
54452
+ if (!existsSync47(dir))
54146
54453
  continue;
54147
54454
  try {
54148
- const files = readdirSync16(dir).filter((f) => f.endsWith(".json"));
54455
+ const files = readdirSync17(dir).filter((f) => f.endsWith(".json"));
54149
54456
  for (const f of files) {
54150
- const topic = basename15(f, ".json");
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(readFileSync35(join63(dir, f), "utf-8"));
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 mkdirSync21, existsSync as existsSync47, unlinkSync as unlinkSync10, readdirSync as readdirSync17, statSync as statSync15 } from "node:fs";
54722
- import { join as join64, resolve as resolve30 } from "node:path";
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
- mkdirSync21(this.mediaCacheDir, { recursive: true });
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 = join64(this.mediaCacheDir, fileName);
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
- unlinkSync10(entry.localPath);
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 execSync31 } from "node:child_process";
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
- execSync31("pbcopy", { input: text, timeout: 3e3 });
56821
+ execSync32("pbcopy", { input: text, timeout: 3e3 });
56515
56822
  return true;
56516
56823
  }
56517
56824
  if (platform6 === "win32") {
56518
- execSync31("clip", { input: text, timeout: 3e3 });
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
- execSync31(tool, { input: text, timeout: 3e3 });
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
- execSync31("which apt-get", { timeout: 2e3, stdio: "pipe" });
56839
+ execSync32("which apt-get", { timeout: 2e3, stdio: "pipe" });
56533
56840
  try {
56534
- execSync31("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
56535
- execSync31("xclip -selection clipboard", { input: text, timeout: 3e3 });
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 readFileSync36 } from "node:fs";
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 = readFileSync36(metricsPath, "utf8");
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 join65, dirname as dirname20, extname as extname11 } from "node:path";
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 readFileSync37, writeFileSync as writeFileSync21, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync18, mkdirSync as mkdirSync22 } from "node:fs";
59128
- import { existsSync as existsSync48 } from "node:fs";
59129
- import { execSync as execSync32 } from "node:child_process";
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
- join65(thisDir, "..", "package.json"),
59150
- join65(thisDir, "..", "..", "package.json"),
59151
- join65(thisDir, "..", "..", "..", "package.json")
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 (existsSync48(pkgPath)) {
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
- join65(root, ".oa", "memory"),
59389
- join65(root, ".open-agents", "memory")
59696
+ join66(root, ".oa", "memory"),
59697
+ join66(root, ".open-agents", "memory")
59390
59698
  ];
59391
59699
  for (const dir of dirs) {
59392
- if (!existsSync48(dir))
59700
+ if (!existsSync49(dir))
59393
59701
  continue;
59394
59702
  try {
59395
- for (const f of readdirSync18(dir).filter((f2) => f2.endsWith(".json"))) {
59396
- const data = JSON.parse(readFileSync37(join65(dir, f), "utf-8"));
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 = join65(repoRoot, ".oa", "arche", "variants.json");
59554
- if (existsSync48(archeFile)) {
59555
- const variants = JSON.parse(readFileSync37(archeFile, "utf8"));
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 = join65(repoRoot, ".oa", "identity", "self-state.json");
59693
- if (existsSync48(ikStateFile)) {
59694
- const selfState = JSON.parse(readFileSync37(ikStateFile, "utf8"));
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 = join65(repoRoot, ".oa", "identity");
60334
- const ikFile = join65(ikDir, "self-state.json");
60641
+ const ikDir = join66(repoRoot, ".oa", "identity");
60642
+ const ikFile = join66(ikDir, "self-state.json");
60335
60643
  let ikState;
60336
- if (existsSync48(ikFile)) {
60337
- ikState = JSON.parse(readFileSync37(ikFile, "utf8"));
60644
+ if (existsSync49(ikFile)) {
60645
+ ikState = JSON.parse(readFileSync38(ikFile, "utf8"));
60338
60646
  } else {
60339
- mkdirSync22(ikDir, { recursive: true });
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
- writeFileSync21(ikFile, JSON.stringify(ikState, null, 2));
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 = join65(repoRoot, ".oa", "identity", "self-state.json");
60381
- if (existsSync48(ikFile)) {
60382
- const ikState = JSON.parse(readFileSync37(ikFile, "utf8"));
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
- writeFileSync21(ikFile, JSON.stringify(ikState, null, 2));
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(join65(repoRoot, ".oa", "vault.enc"));
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 = join65(homedir16(), ".open-agents");
60951
- const HISTORY_FILE = join65(HISTORY_DIR, "repl-history");
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 (existsSync48(HISTORY_FILE)) {
60956
- const raw = readFileSync37(HISTORY_FILE, "utf8").trim();
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
- mkdirSync22(HISTORY_DIR, { recursive: true });
61344
+ mkdirSync23(HISTORY_DIR, { recursive: true });
61037
61345
  appendFileSync4(HISTORY_FILE, line + "\n", "utf8");
61038
61346
  if (Math.random() < 0.02) {
61039
- const all = readFileSync37(HISTORY_FILE, "utf8").trim().split("\n");
61347
+ const all = readFileSync38(HISTORY_FILE, "utf8").trim().split("\n");
61040
61348
  if (all.length > MAX_HISTORY_LINES) {
61041
- writeFileSync21(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
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 = join65(repoRoot, ".oa");
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 = join65(repoRoot, ".oa");
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: join65(repoRoot, ".oa"),
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: join65(repoRoot, ".oa") });
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 = join65(repoRoot, OA_DIR, "nexus");
62442
- const pidFile = join65(nexusDir, "daemon.pid");
62443
- if (existsSync48(pidFile)) {
62444
- const pid = parseInt(readFileSync37(pidFile, "utf8").trim(), 10);
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
- execSync32(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
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 = join65(homedir16(), ".open-agents", "voice");
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 = join65(voiceDir2, pf);
62470
- if (existsSync48(pidPath)) {
62777
+ const pidPath = join66(voiceDir2, pf);
62778
+ if (existsSync49(pidPath)) {
62471
62779
  try {
62472
- const pid = parseInt(readFileSync37(pidPath, "utf8").trim(), 10);
62780
+ const pid = parseInt(readFileSync38(pidPath, "utf8").trim(), 10);
62473
62781
  if (pid > 0) {
62474
62782
  if (process.platform === "win32") {
62475
62783
  try {
62476
- execSync32(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
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
- execSync32(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
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 = join65(repoRoot, OA_DIR);
62497
- if (existsSync48(oaPath)) {
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
- execSync32(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
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
- execSync32(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
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) && existsSync48(resolve31(repoRoot, cleanPath));
62870
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync48(resolve31(repoRoot, 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 = readFileSync37(imgPath);
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: createHash5 } = await import("node:crypto");
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: createHash5("sha256").update(errMsg.slice(0, 200)).digest("hex").slice(0, 16),
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 = join65(repoRoot, ".oa", "identity");
63379
- const ikFile = join65(ikDir, "self-state.json");
63686
+ const ikDir = join66(repoRoot, ".oa", "identity");
63687
+ const ikFile = join66(ikDir, "self-state.json");
63380
63688
  let ikState;
63381
- if (existsSync48(ikFile)) {
63382
- ikState = JSON.parse(readFileSync37(ikFile, "utf8"));
63689
+ if (existsSync49(ikFile)) {
63690
+ ikState = JSON.parse(readFileSync38(ikFile, "utf8"));
63383
63691
  } else {
63384
- mkdirSync22(ikDir, { recursive: true });
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
- writeFileSync21(ikFile, JSON.stringify(ikState, null, 2));
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 = join65(repoRoot, ".oa", "arche");
63416
- const archeFile = join65(archeDir, "variants.json");
63723
+ const archeDir = join66(repoRoot, ".oa", "arche");
63724
+ const archeFile = join66(archeDir, "variants.json");
63417
63725
  let variants = [];
63418
63726
  try {
63419
- if (existsSync48(archeFile))
63420
- variants = JSON.parse(readFileSync37(archeFile, "utf8"));
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
- mkdirSync22(archeDir, { recursive: true });
63436
- writeFileSync21(archeFile, JSON.stringify(variants, null, 2));
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 = join65(repoRoot, ".oa", "memory", "metabolism", "store.json");
63442
- if (existsSync48(metaFile)) {
63443
- const store = JSON.parse(readFileSync37(metaFile, "utf8"));
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
- writeFileSync21(metaFile, JSON.stringify(store, null, 2));
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 = join65(repoRoot, ".oa", "memory");
63508
- mkdirSync22(dbDir, { recursive: true });
63509
- const db = initDb2(join65(dbDir, "structured.db"));
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 = join65(repoRoot, ".oa", "memory", "metabolism");
63525
- const storeFile = join65(metaDir, "store.json");
63832
+ const metaDir = join66(repoRoot, ".oa", "memory", "metabolism");
63833
+ const storeFile = join66(metaDir, "store.json");
63526
63834
  let store = [];
63527
63835
  try {
63528
- if (existsSync48(storeFile))
63529
- store = JSON.parse(readFileSync37(storeFile, "utf8"));
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
- mkdirSync22(metaDir, { recursive: true });
63546
- writeFileSync21(storeFile, JSON.stringify(store, null, 2));
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 = join65(repoRoot, ".oa", "settings.json");
63860
+ const cohereSettingsFile = join66(repoRoot, ".oa", "settings.json");
63553
63861
  let cohereActive = false;
63554
63862
  try {
63555
- if (existsSync48(cohereSettingsFile)) {
63556
- const settings = JSON.parse(readFileSync37(cohereSettingsFile, "utf8"));
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 = join65(repoRoot, ".oa", "memory", "metabolism", "store.json");
63563
- if (existsSync48(metaFile)) {
63564
- const store = JSON.parse(readFileSync37(metaFile, "utf8"));
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 = join65(repoRoot, ".oa", "identity", "self-state.json");
63590
- if (existsSync48(ikFile)) {
63591
- const ikState = JSON.parse(readFileSync37(ikFile, "utf8"));
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
- writeFileSync21(ikFile, JSON.stringify(ikState, null, 2));
63904
+ writeFileSync22(ikFile, JSON.stringify(ikState, null, 2));
63597
63905
  }
63598
- const metaFile = join65(repoRoot, ".oa", "memory", "metabolism", "store.json");
63599
- if (existsSync48(metaFile)) {
63600
- const store = JSON.parse(readFileSync37(metaFile, "utf8"));
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
- writeFileSync21(metaFile, JSON.stringify(store, null, 2));
63916
+ writeFileSync22(metaFile, JSON.stringify(store, null, 2));
63609
63917
  }
63610
63918
  try {
63611
- const archeDir = join65(repoRoot, ".oa", "arche");
63612
- const archeFile = join65(archeDir, "variants.json");
63919
+ const archeDir = join66(repoRoot, ".oa", "arche");
63920
+ const archeFile = join66(archeDir, "variants.json");
63613
63921
  let variants = [];
63614
63922
  try {
63615
- if (existsSync48(archeFile))
63616
- variants = JSON.parse(readFileSync37(archeFile, "utf8"));
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
- mkdirSync22(archeDir, { recursive: true });
63632
- writeFileSync21(archeFile, JSON.stringify(variants, null, 2));
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 createHash4 } from "node:crypto";
63721
- import { join as join66, relative as relative4, extname as extname12, basename as basename16 } from "node:path";
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(join66(this.config.rootDir, ".gitignore"), "utf-8");
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 = join66(this.config.rootDir, relativePath);
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 = createHash4("sha256").update(content).digest("hex");
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: basename16(this.config.rootDir),
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: join66(current.path, part),
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 existsSync49, statSync as statSync16 } from "node:fs";
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 (!existsSync49(repoRoot)) {
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 join67, resolve as resolve33 } from "node:path";
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 (${join67(homedir17(), ".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 ${join67(repoRoot, ".oa", "settings.json")}`);
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 mkdirSync23, writeFileSync as writeFileSync22 } from "node:fs";
64548
- import { join as join68 } from "node:path";
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 = join68(tmpdir10(), `open-agents-eval-${Date.now()}`);
64674
- mkdirSync23(dir, { recursive: true });
64675
- writeFileSync22(join68(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
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 join69 } from "node:path";
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 = join69(dirname21(fileURLToPath13(import.meta.url)), "..", "package.json");
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 {