open-agents-ai 0.104.4 → 0.104.5

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 +617 -259
  2. package/package.json +6 -2
package/dist/index.js CHANGED
@@ -5639,8 +5639,8 @@ function deleteCustomToolDefinition(name, scope, repoRoot) {
5639
5639
  const dir = scope === "project" && repoRoot ? projectToolsDir(repoRoot) : globalToolsDir();
5640
5640
  const filePath = join13(dir, `${name}.json`);
5641
5641
  if (existsSync10(filePath)) {
5642
- const { unlinkSync: unlinkSync8 } = __require("node:fs");
5643
- unlinkSync8(filePath);
5642
+ const { unlinkSync: unlinkSync9 } = __require("node:fs");
5643
+ unlinkSync9(filePath);
5644
5644
  return true;
5645
5645
  }
5646
5646
  return false;
@@ -20060,8 +20060,8 @@ ${marker}` : marker);
20060
20060
  return;
20061
20061
  try {
20062
20062
  const { mkdirSync: mkdirSync21, writeFileSync: writeFileSync19 } = __require("node:fs");
20063
- const { join: join55 } = __require("node:path");
20064
- const sessionDir = join55(this._workingDirectory, ".oa", "session", this._sessionId);
20063
+ const { join: join56 } = __require("node:path");
20064
+ const sessionDir = join56(this._workingDirectory, ".oa", "session", this._sessionId);
20065
20065
  mkdirSync21(sessionDir, { recursive: true });
20066
20066
  const checkpoint = {
20067
20067
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -20074,7 +20074,7 @@ ${marker}` : marker);
20074
20074
  memexEntryCount: this._memexArchive.size,
20075
20075
  fileRegistrySize: this._fileRegistry.size
20076
20076
  };
20077
- writeFileSync19(join55(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
20077
+ writeFileSync19(join56(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
20078
20078
  } catch {
20079
20079
  }
20080
20080
  }
@@ -27191,6 +27191,8 @@ function renderSlashHelp() {
27191
27191
  ["/voice clone overwatch", "Generate clone ref from Overwatch for LuxTTS"],
27192
27192
  ["/think", "Toggle thinking/reasoning mode (Qwen3, DeepSeek-R1, etc.)"],
27193
27193
  ["/stream", "Toggle real-time token streaming (pastel syntax highlighting)"],
27194
+ ["/neovim", "Toggle embedded Neovim editor (Ctrl+N to switch focus)"],
27195
+ ["/neovim <file>", "Open file in embedded Neovim editor"],
27194
27196
  ["/dream", "Start dream mode \u2014 creative idle exploration (writes to .oa/dreams/)"],
27195
27197
  ["/dream deep", "Deep dream \u2014 multi-cycle exploration with sleep architecture"],
27196
27198
  ["/dream lucid", "Lucid dream \u2014 implements proposals, tests, evaluates in cycles"],
@@ -31011,15 +31013,15 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
31011
31013
  async function fetchPeerModels(peerId, authKey) {
31012
31014
  try {
31013
31015
  const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
31014
- const { existsSync: existsSync43, readFileSync: readFileSync31 } = await import("node:fs");
31015
- const { join: join55 } = await import("node:path");
31016
+ const { existsSync: existsSync44, readFileSync: readFileSync31 } = await import("node:fs");
31017
+ const { join: join56 } = await import("node:path");
31016
31018
  const cwd4 = process.cwd();
31017
31019
  const nexusTool = new NexusTool2(cwd4);
31018
31020
  const nexusDir = nexusTool.getNexusDir();
31019
31021
  let isLocalPeer = false;
31020
31022
  try {
31021
- const statusPath = join55(nexusDir, "status.json");
31022
- if (existsSync43(statusPath)) {
31023
+ const statusPath = join56(nexusDir, "status.json");
31024
+ if (existsSync44(statusPath)) {
31023
31025
  const status = JSON.parse(readFileSync31(statusPath, "utf8"));
31024
31026
  if (status.peerId === peerId)
31025
31027
  isLocalPeer = true;
@@ -31027,8 +31029,8 @@ async function fetchPeerModels(peerId, authKey) {
31027
31029
  } catch {
31028
31030
  }
31029
31031
  if (isLocalPeer) {
31030
- const pricingPath = join55(nexusDir, "pricing.json");
31031
- if (existsSync43(pricingPath)) {
31032
+ const pricingPath = join56(nexusDir, "pricing.json");
31033
+ if (existsSync44(pricingPath)) {
31032
31034
  try {
31033
31035
  const pricing = JSON.parse(readFileSync31(pricingPath, "utf8"));
31034
31036
  const localModels = (pricing.models || []).map((m) => ({
@@ -31044,8 +31046,8 @@ async function fetchPeerModels(peerId, authKey) {
31044
31046
  }
31045
31047
  }
31046
31048
  }
31047
- const cachePath = join55(nexusDir, "peer-models-cache.json");
31048
- if (existsSync43(cachePath)) {
31049
+ const cachePath = join56(nexusDir, "peer-models-cache.json");
31050
+ if (existsSync44(cachePath)) {
31049
31051
  try {
31050
31052
  const cache4 = JSON.parse(readFileSync31(cachePath, "utf8"));
31051
31053
  if (cache4.peerId === peerId && cache4.models?.length > 0) {
@@ -31162,8 +31164,8 @@ async function fetchPeerModels(peerId, authKey) {
31162
31164
  } catch {
31163
31165
  }
31164
31166
  if (isLocalPeer) {
31165
- const pricingPath = join55(nexusDir, "pricing.json");
31166
- if (existsSync43(pricingPath)) {
31167
+ const pricingPath = join56(nexusDir, "pricing.json");
31168
+ if (existsSync44(pricingPath)) {
31167
31169
  try {
31168
31170
  const pricing = JSON.parse(readFileSync31(pricingPath, "utf8"));
31169
31171
  return (pricing.models || []).map((m) => ({
@@ -34426,6 +34428,309 @@ var init_drop_panel = __esm({
34426
34428
  }
34427
34429
  });
34428
34430
 
34431
+ // packages/cli/dist/tui/neovim-mode.js
34432
+ import { existsSync as existsSync33, unlinkSync as unlinkSync5 } from "node:fs";
34433
+ import { tmpdir as tmpdir6 } from "node:os";
34434
+ import { join as join41 } from "node:path";
34435
+ import { execSync as execSync26 } from "node:child_process";
34436
+ function isNeovimActive() {
34437
+ return _state !== null && !_state.cleanedUp;
34438
+ }
34439
+ async function startNeovimMode(opts) {
34440
+ if (_state && !_state.cleanedUp) {
34441
+ return "Neovim mode is already active. Use /neovim to exit first.";
34442
+ }
34443
+ let nvimPath;
34444
+ try {
34445
+ nvimPath = execSync26("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
34446
+ if (!nvimPath)
34447
+ throw new Error();
34448
+ } catch {
34449
+ return "nvim not found on PATH. Install Neovim: https://neovim.io";
34450
+ }
34451
+ let ptyMod;
34452
+ try {
34453
+ const ptyModName = "node-pty";
34454
+ ptyMod = await import(
34455
+ /* @vite-ignore */
34456
+ ptyModName
34457
+ );
34458
+ } catch {
34459
+ return "node-pty not available. Install it: npm install node-pty";
34460
+ }
34461
+ let neovimPkg = null;
34462
+ try {
34463
+ const nvimModName = "neovim";
34464
+ neovimPkg = await import(
34465
+ /* @vite-ignore */
34466
+ nvimModName
34467
+ );
34468
+ } catch {
34469
+ }
34470
+ const socketPath = join41(tmpdir6(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
34471
+ try {
34472
+ if (existsSync33(socketPath))
34473
+ unlinkSync5(socketPath);
34474
+ } catch {
34475
+ }
34476
+ const ptyCols = opts.cols;
34477
+ const ptyRows = Math.max(5, opts.contentRows);
34478
+ const nvimArgs = [
34479
+ "--listen",
34480
+ socketPath,
34481
+ "--cmd",
34482
+ "set autoread updatetime=300 signcolumn=no"
34483
+ ];
34484
+ if (opts.initialFile) {
34485
+ nvimArgs.push(opts.initialFile);
34486
+ } else {
34487
+ nvimArgs.push(".");
34488
+ }
34489
+ const nvimPty = ptyMod.spawn(nvimPath, nvimArgs, {
34490
+ name: "xterm-256color",
34491
+ cols: ptyCols,
34492
+ rows: ptyRows,
34493
+ cwd: opts.cwd,
34494
+ env: { ...process.env }
34495
+ });
34496
+ const state = {
34497
+ pty: nvimPty,
34498
+ nvim: null,
34499
+ outputChanId: 0,
34500
+ socketPath,
34501
+ focused: true,
34502
+ opts,
34503
+ stdinHandler: null,
34504
+ savedRlListeners: [],
34505
+ cleanedUp: false
34506
+ };
34507
+ _state = state;
34508
+ nvimPty.onData((data) => {
34509
+ if (state.cleanedUp)
34510
+ return;
34511
+ if (!state.focused) {
34512
+ process.stdout.write("\x1B7" + data + "\x1B8");
34513
+ } else {
34514
+ process.stdout.write(data);
34515
+ }
34516
+ });
34517
+ nvimPty.onExit(() => {
34518
+ if (!state.cleanedUp) {
34519
+ doCleanup(state);
34520
+ }
34521
+ });
34522
+ const stdin = process.stdin;
34523
+ if (opts.rl) {
34524
+ opts.rl.pause();
34525
+ for (const event of ["keypress", "data"]) {
34526
+ const listeners = stdin.listeners(event);
34527
+ for (const fn of listeners) {
34528
+ state.savedRlListeners.push({ event, fn });
34529
+ stdin.removeListener(event, fn);
34530
+ }
34531
+ }
34532
+ }
34533
+ if (typeof stdin.setRawMode === "function") {
34534
+ stdin.setRawMode(true);
34535
+ }
34536
+ stdin.resume();
34537
+ state.stdinHandler = (data) => {
34538
+ if (state.cleanedUp)
34539
+ return;
34540
+ const seq = data.toString("utf8");
34541
+ if (seq === "") {
34542
+ toggleFocus(state);
34543
+ return;
34544
+ }
34545
+ if (state.focused) {
34546
+ nvimPty.write(seq);
34547
+ }
34548
+ };
34549
+ stdin.on("data", state.stdinHandler);
34550
+ if (neovimPkg) {
34551
+ connectRPC(state, neovimPkg, ptyCols).catch(() => {
34552
+ });
34553
+ }
34554
+ return null;
34555
+ }
34556
+ function stopNeovimMode() {
34557
+ if (!_state || _state.cleanedUp)
34558
+ return;
34559
+ try {
34560
+ _state.pty?.write(":qa!\r");
34561
+ } catch {
34562
+ }
34563
+ setTimeout(() => {
34564
+ if (_state && !_state.cleanedUp) {
34565
+ doCleanup(_state);
34566
+ }
34567
+ }, 500);
34568
+ }
34569
+ function writeToNeovimOutput(text) {
34570
+ if (!_state || _state.cleanedUp || !_state.nvim || !_state.outputChanId)
34571
+ return;
34572
+ const normalized = text.replace(/(?<!\r)\n/g, "\r\n");
34573
+ _state.nvim.request("nvim_chan_send", [_state.outputChanId, normalized]).catch(() => {
34574
+ });
34575
+ }
34576
+ async function notifyNeovimFileChange(filePath) {
34577
+ if (!_state || _state.cleanedUp || !_state.nvim)
34578
+ return;
34579
+ try {
34580
+ await _state.nvim.command("checktime");
34581
+ if (filePath) {
34582
+ const escaped = filePath.replace(/'/g, "''");
34583
+ await _state.nvim.command(`if bufexists('${escaped}') | execute 'buffer ' . bufnr('${escaped}') | endif`);
34584
+ }
34585
+ } catch {
34586
+ }
34587
+ }
34588
+ function resizeNeovim(cols, contentRows) {
34589
+ if (!_state || _state.cleanedUp || !_state.pty)
34590
+ return;
34591
+ const rows = Math.max(5, contentRows);
34592
+ try {
34593
+ _state.pty.resize(cols, rows);
34594
+ } catch {
34595
+ }
34596
+ }
34597
+ async function connectRPC(state, neovimPkg, cols) {
34598
+ let attempts = 0;
34599
+ while (!existsSync33(state.socketPath) && attempts < 30) {
34600
+ await new Promise((r) => setTimeout(r, 200));
34601
+ attempts++;
34602
+ if (state.cleanedUp)
34603
+ return;
34604
+ }
34605
+ if (!existsSync33(state.socketPath))
34606
+ return;
34607
+ const nvim = neovimPkg.attach({ socket: state.socketPath });
34608
+ state.nvim = nvim;
34609
+ await new Promise((r) => setTimeout(r, 300));
34610
+ if (state.cleanedUp)
34611
+ return;
34612
+ try {
34613
+ const editorWidth = Math.floor(cols * 0.7);
34614
+ const outputWidth = cols - editorWidth;
34615
+ await nvim.command("botright vsplit");
34616
+ await nvim.command(`vertical resize ${outputWidth}`);
34617
+ const buf = await nvim.createBuffer(false, true);
34618
+ const win = await nvim.window;
34619
+ await nvim.request("nvim_win_set_buf", [win.id, buf.id]);
34620
+ await nvim.request("nvim_buf_set_option", [buf.id, "buftype", "nofile"]);
34621
+ await nvim.request("nvim_buf_set_option", [buf.id, "swapfile", false]);
34622
+ const chanId = await nvim.request("nvim_open_term", [buf.id, {}]);
34623
+ state.outputChanId = chanId;
34624
+ await nvim.request("nvim_chan_send", [
34625
+ chanId,
34626
+ "\x1B[36m\u2500\u2500 Agent Output \u2500\u2500\x1B[0m\r\n\r\n\x1B[2mAgent activity will appear here.\x1B[0m\r\n\x1B[2mCtrl+N toggles focus to input.\x1B[0m\r\n"
34627
+ ]);
34628
+ await nvim.request("nvim_win_set_option", [win.id, "number", false]);
34629
+ await nvim.request("nvim_win_set_option", [win.id, "relativenumber", false]);
34630
+ await nvim.request("nvim_win_set_option", [win.id, "wrap", true]);
34631
+ await nvim.command("wincmd h");
34632
+ await nvim.command("set autoread");
34633
+ await nvim.command("autocmd FocusGained,BufEnter,CursorHold * silent! checktime");
34634
+ } catch {
34635
+ }
34636
+ }
34637
+ function toggleFocus(state) {
34638
+ const stdin = process.stdin;
34639
+ if (state.focused) {
34640
+ state.focused = false;
34641
+ if (state.stdinHandler) {
34642
+ stdin.removeListener("data", state.stdinHandler);
34643
+ }
34644
+ if (typeof stdin.setRawMode === "function") {
34645
+ stdin.setRawMode(false);
34646
+ }
34647
+ for (const { event, fn } of state.savedRlListeners) {
34648
+ stdin.on(event, fn);
34649
+ }
34650
+ if (state.opts.rl) {
34651
+ state.opts.rl.resume();
34652
+ state.opts.rl.prompt(false);
34653
+ }
34654
+ } else {
34655
+ state.focused = true;
34656
+ if (state.opts.rl) {
34657
+ state.opts.rl.pause();
34658
+ }
34659
+ state.savedRlListeners = [];
34660
+ for (const event of ["keypress", "data"]) {
34661
+ const listeners = stdin.listeners(event);
34662
+ for (const fn of listeners) {
34663
+ state.savedRlListeners.push({ event, fn });
34664
+ stdin.removeListener(event, fn);
34665
+ }
34666
+ }
34667
+ if (typeof stdin.setRawMode === "function") {
34668
+ stdin.setRawMode(true);
34669
+ }
34670
+ stdin.resume();
34671
+ if (state.stdinHandler) {
34672
+ stdin.on("data", state.stdinHandler);
34673
+ }
34674
+ if (state.nvim) {
34675
+ state.nvim.command("echo ''").catch(() => {
34676
+ });
34677
+ }
34678
+ }
34679
+ }
34680
+ function doCleanup(state) {
34681
+ if (state.cleanedUp)
34682
+ return;
34683
+ state.cleanedUp = true;
34684
+ const stdin = process.stdin;
34685
+ if (state.nvim) {
34686
+ try {
34687
+ state.nvim.quit();
34688
+ } catch {
34689
+ }
34690
+ state.nvim = null;
34691
+ }
34692
+ if (state.pty) {
34693
+ try {
34694
+ state.pty.kill();
34695
+ } catch {
34696
+ }
34697
+ state.pty = null;
34698
+ }
34699
+ try {
34700
+ if (existsSync33(state.socketPath))
34701
+ unlinkSync5(state.socketPath);
34702
+ } catch {
34703
+ }
34704
+ if (state.stdinHandler) {
34705
+ stdin.removeListener("data", state.stdinHandler);
34706
+ state.stdinHandler = null;
34707
+ }
34708
+ if (typeof stdin.setRawMode === "function") {
34709
+ try {
34710
+ stdin.setRawMode(false);
34711
+ } catch {
34712
+ }
34713
+ }
34714
+ for (const { event, fn } of state.savedRlListeners) {
34715
+ stdin.on(event, fn);
34716
+ }
34717
+ if (state.opts.rl) {
34718
+ state.opts.rl.resume();
34719
+ state.opts.rl.prompt(false);
34720
+ }
34721
+ _state = null;
34722
+ process.stdout.write("\x1B[H\x1B[J");
34723
+ state.opts.onExit?.();
34724
+ }
34725
+ var isTTY5, _state;
34726
+ var init_neovim_mode = __esm({
34727
+ "packages/cli/dist/tui/neovim-mode.js"() {
34728
+ "use strict";
34729
+ isTTY5 = process.stdout.isTTY ?? false;
34730
+ _state = null;
34731
+ }
34732
+ });
34733
+
34429
34734
  // packages/cli/dist/tui/voice.js
34430
34735
  var voice_exports = {};
34431
34736
  __export(voice_exports, {
@@ -34438,10 +34743,10 @@ __export(voice_exports, {
34438
34743
  registerCustomOnnxModel: () => registerCustomOnnxModel,
34439
34744
  resetNarrationContext: () => resetNarrationContext
34440
34745
  });
34441
- import { existsSync as existsSync33, mkdirSync as mkdirSync13, writeFileSync as writeFileSync13, readFileSync as readFileSync23, unlinkSync as unlinkSync5, readdirSync as readdirSync9, renameSync, statSync as statSync10 } from "node:fs";
34442
- import { join as join41 } from "node:path";
34443
- import { homedir as homedir11, tmpdir as tmpdir6, platform as platform2 } from "node:os";
34444
- import { execSync as execSync26, spawn as nodeSpawn } from "node:child_process";
34746
+ import { existsSync as existsSync34, mkdirSync as mkdirSync13, writeFileSync as writeFileSync13, readFileSync as readFileSync23, unlinkSync as unlinkSync6, readdirSync as readdirSync9, renameSync, statSync as statSync10 } from "node:fs";
34747
+ import { join as join42 } from "node:path";
34748
+ import { homedir as homedir11, tmpdir as tmpdir7, platform as platform2 } from "node:os";
34749
+ import { execSync as execSync27, spawn as nodeSpawn } from "node:child_process";
34445
34750
  import { createRequire } from "node:module";
34446
34751
  function registerCustomOnnxModel(id, label) {
34447
34752
  VOICE_MODELS[id] = {
@@ -34461,34 +34766,34 @@ function listVoiceModels() {
34461
34766
  }));
34462
34767
  }
34463
34768
  function voiceDir() {
34464
- return join41(homedir11(), ".open-agents", "voice");
34769
+ return join42(homedir11(), ".open-agents", "voice");
34465
34770
  }
34466
34771
  function modelsDir() {
34467
- return join41(voiceDir(), "models");
34772
+ return join42(voiceDir(), "models");
34468
34773
  }
34469
34774
  function modelDir(id) {
34470
- return join41(modelsDir(), id);
34775
+ return join42(modelsDir(), id);
34471
34776
  }
34472
34777
  function modelOnnxPath(id) {
34473
- return join41(modelDir(id), "model.onnx");
34778
+ return join42(modelDir(id), "model.onnx");
34474
34779
  }
34475
34780
  function modelConfigPath(id) {
34476
- return join41(modelDir(id), "config.json");
34781
+ return join42(modelDir(id), "config.json");
34477
34782
  }
34478
34783
  function luxttsVenvDir() {
34479
- return join41(voiceDir(), "luxtts-venv");
34784
+ return join42(voiceDir(), "luxtts-venv");
34480
34785
  }
34481
34786
  function luxttsVenvPy() {
34482
- return platform2() === "win32" ? join41(luxttsVenvDir(), "Scripts", "python.exe") : join41(luxttsVenvDir(), "bin", "python3");
34787
+ return platform2() === "win32" ? join42(luxttsVenvDir(), "Scripts", "python.exe") : join42(luxttsVenvDir(), "bin", "python3");
34483
34788
  }
34484
34789
  function luxttsRepoDir() {
34485
- return join41(voiceDir(), "LuxTTS");
34790
+ return join42(voiceDir(), "LuxTTS");
34486
34791
  }
34487
34792
  function luxttsCloneRefsDir() {
34488
- return join41(voiceDir(), "clone-refs");
34793
+ return join42(voiceDir(), "clone-refs");
34489
34794
  }
34490
34795
  function luxttsInferScript() {
34491
- return join41(voiceDir(), "luxtts-infer.py");
34796
+ return join42(voiceDir(), "luxtts-infer.py");
34492
34797
  }
34493
34798
  function emotionToPitchBias(emotion, stark = false, autist = false) {
34494
34799
  if (autist)
@@ -35296,8 +35601,8 @@ var init_voice = __esm({
35296
35601
  const refsDir = luxttsCloneRefsDir();
35297
35602
  const targets = ["glados", "overwatch"];
35298
35603
  for (const modelId of targets) {
35299
- const refFile = join41(refsDir, `${modelId}-ref.wav`);
35300
- if (existsSync33(refFile))
35604
+ const refFile = join42(refsDir, `${modelId}-ref.wav`);
35605
+ if (existsSync34(refFile))
35301
35606
  continue;
35302
35607
  try {
35303
35608
  await this.generateCloneRef(modelId);
@@ -35376,21 +35681,21 @@ var init_voice = __esm({
35376
35681
  }
35377
35682
  p = p.replace(/\\ /g, " ");
35378
35683
  if (p.startsWith("~/") || p === "~") {
35379
- p = join41(homedir11(), p.slice(1));
35684
+ p = join42(homedir11(), p.slice(1));
35380
35685
  }
35381
- if (!existsSync33(p)) {
35686
+ if (!existsSync34(p)) {
35382
35687
  return `File not found: ${p}
35383
35688
  (original input: ${audioPath})`;
35384
35689
  }
35385
35690
  audioPath = p;
35386
35691
  const refsDir = luxttsCloneRefsDir();
35387
- if (!existsSync33(refsDir))
35692
+ if (!existsSync34(refsDir))
35388
35693
  mkdirSync13(refsDir, { recursive: true });
35389
35694
  const ext = audioPath.split(".").pop() || "wav";
35390
35695
  const srcName = (audioPath.split("/").pop() ?? "clone").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]/g, "-");
35391
35696
  const ts = Date.now().toString(36);
35392
35697
  const destFilename = `clone-${srcName}-${ts}.${ext}`;
35393
- const destPath = join41(refsDir, destFilename);
35698
+ const destPath = join42(refsDir, destFilename);
35394
35699
  try {
35395
35700
  const data = readFileSync23(audioPath);
35396
35701
  writeFileSync13(destPath, data);
@@ -35433,9 +35738,9 @@ var init_voice = __esm({
35433
35738
  return `Failed to synthesize reference audio from ${source.label}.`;
35434
35739
  }
35435
35740
  const refsDir = luxttsCloneRefsDir();
35436
- if (!existsSync33(refsDir))
35741
+ if (!existsSync34(refsDir))
35437
35742
  mkdirSync13(refsDir, { recursive: true });
35438
- const destPath = join41(refsDir, `${sourceModelId}-ref.wav`);
35743
+ const destPath = join42(refsDir, `${sourceModelId}-ref.wav`);
35439
35744
  const sampleRate = this.config?.audio?.sample_rate ?? 22050;
35440
35745
  this.writeWav(audioData, sampleRate, destPath);
35441
35746
  this.luxttsCloneRef = destPath;
@@ -35451,11 +35756,11 @@ var init_voice = __esm({
35451
35756
  // -------------------------------------------------------------------------
35452
35757
  /** Metadata file for friendly names of clone refs */
35453
35758
  static cloneMetaFile() {
35454
- return join41(luxttsCloneRefsDir(), "meta.json");
35759
+ return join42(luxttsCloneRefsDir(), "meta.json");
35455
35760
  }
35456
35761
  loadCloneMeta() {
35457
35762
  const p = _VoiceEngine.cloneMetaFile();
35458
- if (!existsSync33(p))
35763
+ if (!existsSync34(p))
35459
35764
  return {};
35460
35765
  try {
35461
35766
  return JSON.parse(readFileSync23(p, "utf8"));
@@ -35465,7 +35770,7 @@ var init_voice = __esm({
35465
35770
  }
35466
35771
  saveCloneMeta(meta) {
35467
35772
  const dir = luxttsCloneRefsDir();
35468
- if (!existsSync33(dir))
35773
+ if (!existsSync34(dir))
35469
35774
  mkdirSync13(dir, { recursive: true });
35470
35775
  writeFileSync13(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
35471
35776
  }
@@ -35477,7 +35782,7 @@ var init_voice = __esm({
35477
35782
  */
35478
35783
  listCloneRefs() {
35479
35784
  const dir = luxttsCloneRefsDir();
35480
- if (!existsSync33(dir))
35785
+ if (!existsSync34(dir))
35481
35786
  return [];
35482
35787
  const meta = this.loadCloneMeta();
35483
35788
  const files = readdirSync9(dir).filter((f) => {
@@ -35485,7 +35790,7 @@ var init_voice = __esm({
35485
35790
  return _VoiceEngine.AUDIO_EXTS.has(ext);
35486
35791
  });
35487
35792
  return files.map((f) => {
35488
- const p = join41(dir, f);
35793
+ const p = join42(dir, f);
35489
35794
  let size = 0;
35490
35795
  try {
35491
35796
  size = statSync10(p).size;
@@ -35502,11 +35807,11 @@ var init_voice = __esm({
35502
35807
  }
35503
35808
  /** Delete a clone reference file by filename. Returns true if deleted. */
35504
35809
  deleteCloneRef(filename) {
35505
- const p = join41(luxttsCloneRefsDir(), filename);
35506
- if (!existsSync33(p))
35810
+ const p = join42(luxttsCloneRefsDir(), filename);
35811
+ if (!existsSync34(p))
35507
35812
  return false;
35508
35813
  try {
35509
- unlinkSync5(p);
35814
+ unlinkSync6(p);
35510
35815
  const meta = this.loadCloneMeta();
35511
35816
  delete meta[filename];
35512
35817
  this.saveCloneMeta(meta);
@@ -35527,8 +35832,8 @@ var init_voice = __esm({
35527
35832
  }
35528
35833
  /** Set the active clone reference by filename. */
35529
35834
  setActiveCloneRef(filename) {
35530
- const p = join41(luxttsCloneRefsDir(), filename);
35531
- if (!existsSync33(p))
35835
+ const p = join42(luxttsCloneRefsDir(), filename);
35836
+ if (!existsSync34(p))
35532
35837
  return `File not found: ${filename}`;
35533
35838
  this.luxttsCloneRef = p;
35534
35839
  return `Active clone voice set to: ${filename}`;
@@ -35813,11 +36118,11 @@ var init_voice = __esm({
35813
36118
  }
35814
36119
  this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
35815
36120
  }
35816
- const wavPath = join41(tmpdir6(), `oa-voice-${Date.now()}.wav`);
36121
+ const wavPath = join42(tmpdir7(), `oa-voice-${Date.now()}.wav`);
35817
36122
  this.writeWav(audioData, sampleRate, wavPath);
35818
36123
  await this.playWav(wavPath);
35819
36124
  try {
35820
- unlinkSync5(wavPath);
36125
+ unlinkSync6(wavPath);
35821
36126
  } catch {
35822
36127
  }
35823
36128
  }
@@ -36001,7 +36306,7 @@ var init_voice = __esm({
36001
36306
  }
36002
36307
  for (const player of ["paplay", "pw-play", "aplay"]) {
36003
36308
  try {
36004
- execSync26(`which ${player}`, { stdio: "pipe" });
36309
+ execSync27(`which ${player}`, { stdio: "pipe" });
36005
36310
  return [player, path];
36006
36311
  } catch {
36007
36312
  }
@@ -36030,7 +36335,7 @@ var init_voice = __esm({
36030
36335
  return this.python3Path;
36031
36336
  for (const bin of ["python3", "python"]) {
36032
36337
  try {
36033
- const path = execSync26(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
36338
+ const path = execSync27(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
36034
36339
  if (path) {
36035
36340
  this.python3Path = path;
36036
36341
  return path;
@@ -36062,7 +36367,7 @@ var init_voice = __esm({
36062
36367
  return new Promise((resolve32, reject) => {
36063
36368
  const proc = nodeSpawn("sh", ["-c", command], {
36064
36369
  stdio: ["ignore", "pipe", "pipe"],
36065
- cwd: tmpdir6()
36370
+ cwd: tmpdir7()
36066
36371
  });
36067
36372
  let stdout = "";
36068
36373
  let stderr = "";
@@ -36096,7 +36401,7 @@ var init_voice = __esm({
36096
36401
  return false;
36097
36402
  }
36098
36403
  try {
36099
- execSync26(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
36404
+ execSync27(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
36100
36405
  this.mlxInstalled = true;
36101
36406
  return true;
36102
36407
  } catch {
@@ -36120,7 +36425,7 @@ var init_voice = __esm({
36120
36425
  return;
36121
36426
  renderInfo("Installing MLX Audio for voice synthesis (first time setup)...");
36122
36427
  try {
36123
- execSync26(`${py} -m pip install mlx-audio --quiet`, {
36428
+ execSync27(`${py} -m pip install mlx-audio --quiet`, {
36124
36429
  stdio: "pipe",
36125
36430
  timeout: 3e5
36126
36431
  // 5 min — may need to compile
@@ -36128,7 +36433,7 @@ var init_voice = __esm({
36128
36433
  this.mlxInstalled = true;
36129
36434
  } catch (err) {
36130
36435
  try {
36131
- execSync26(`${py} -m pip install mlx-audio --user --quiet`, {
36436
+ execSync27(`${py} -m pip install mlx-audio --user --quiet`, {
36132
36437
  stdio: "pipe",
36133
36438
  timeout: 3e5
36134
36439
  });
@@ -36156,7 +36461,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36156
36461
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
36157
36462
  const mlxVoice = model.mlxVoice ?? "af_heart";
36158
36463
  const mlxLangCode = model.mlxLangCode ?? "a";
36159
- const wavPath = join41(tmpdir6(), `oa-mlx-${Date.now()}.wav`);
36464
+ const wavPath = join42(tmpdir7(), `oa-mlx-${Date.now()}.wav`);
36160
36465
  const pyScript = [
36161
36466
  "import sys, json",
36162
36467
  "from mlx_audio.tts import generate as tts_gen",
@@ -36164,16 +36469,16 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36164
36469
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
36165
36470
  ].join("; ");
36166
36471
  try {
36167
- execSync26(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
36472
+ execSync27(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir7() });
36168
36473
  } catch (err) {
36169
36474
  try {
36170
36475
  const safeText = cleaned.replace(/'/g, "'\\''");
36171
- execSync26(`${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: tmpdir6() });
36476
+ execSync27(`${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: tmpdir7() });
36172
36477
  } catch (err2) {
36173
36478
  return;
36174
36479
  }
36175
36480
  }
36176
- if (!existsSync33(wavPath))
36481
+ if (!existsSync34(wavPath))
36177
36482
  return;
36178
36483
  if (volume !== 1) {
36179
36484
  try {
@@ -36203,7 +36508,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36203
36508
  }
36204
36509
  await this.playWav(wavPath);
36205
36510
  try {
36206
- unlinkSync5(wavPath);
36511
+ unlinkSync6(wavPath);
36207
36512
  } catch {
36208
36513
  }
36209
36514
  }
@@ -36224,7 +36529,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36224
36529
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
36225
36530
  const mlxVoice = model.mlxVoice ?? "af_heart";
36226
36531
  const mlxLangCode = model.mlxLangCode ?? "a";
36227
- const wavPath = join41(tmpdir6(), `oa-mlx-buf-${Date.now()}.wav`);
36532
+ const wavPath = join42(tmpdir7(), `oa-mlx-buf-${Date.now()}.wav`);
36228
36533
  const pyScript = [
36229
36534
  "import sys, json",
36230
36535
  "from mlx_audio.tts import generate as tts_gen",
@@ -36232,20 +36537,20 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36232
36537
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
36233
36538
  ].join("; ");
36234
36539
  try {
36235
- execSync26(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
36540
+ execSync27(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir7() });
36236
36541
  } catch {
36237
36542
  try {
36238
36543
  const safeText = cleaned.replace(/'/g, "'\\''");
36239
- execSync26(`${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: tmpdir6() });
36544
+ execSync27(`${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: tmpdir7() });
36240
36545
  } catch {
36241
36546
  return null;
36242
36547
  }
36243
36548
  }
36244
- if (!existsSync33(wavPath))
36549
+ if (!existsSync34(wavPath))
36245
36550
  return null;
36246
36551
  try {
36247
36552
  const data = readFileSync23(wavPath);
36248
- unlinkSync5(wavPath);
36553
+ unlinkSync6(wavPath);
36249
36554
  return data;
36250
36555
  } catch {
36251
36556
  return null;
@@ -36267,7 +36572,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36267
36572
  }
36268
36573
  const venvDir = luxttsVenvDir();
36269
36574
  const venvPy = luxttsVenvPy();
36270
- if (existsSync33(venvPy)) {
36575
+ if (existsSync34(venvPy)) {
36271
36576
  try {
36272
36577
  await this.asyncShell(`${venvPy} -c "import sys; sys.path.insert(0, '${luxttsRepoDir()}'); from zipvoice.luxvoice import LuxTTS; print('ok')"`, 3e4);
36273
36578
  let hasCudaSys = false;
@@ -36297,7 +36602,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36297
36602
  }
36298
36603
  }
36299
36604
  renderInfo("Setting up LuxTTS voice cloning (first-time setup, this takes several minutes)...");
36300
- if (!existsSync33(venvDir)) {
36605
+ if (!existsSync34(venvDir)) {
36301
36606
  renderInfo(" Creating Python virtual environment...");
36302
36607
  try {
36303
36608
  await this.asyncShell(`${py} -m venv ${JSON.stringify(venvDir)}`, 6e4);
@@ -36335,10 +36640,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36335
36640
  }
36336
36641
  }
36337
36642
  const repoDir = luxttsRepoDir();
36338
- if (!existsSync33(join41(repoDir, "zipvoice", "luxvoice.py"))) {
36643
+ if (!existsSync34(join42(repoDir, "zipvoice", "luxvoice.py"))) {
36339
36644
  renderInfo(" Cloning LuxTTS repository...");
36340
36645
  try {
36341
- if (existsSync33(repoDir)) {
36646
+ if (existsSync34(repoDir)) {
36342
36647
  await this.asyncShell(`rm -rf ${JSON.stringify(repoDir)}`, 3e4);
36343
36648
  }
36344
36649
  await this.asyncShell(`git clone --depth 1 https://github.com/ysharma3501/LuxTTS.git ${JSON.stringify(repoDir)}`, 12e4);
@@ -36378,14 +36683,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36378
36683
  }
36379
36684
  /** Auto-detect an existing clone reference in the refs directory */
36380
36685
  autoDetectCloneRef() {
36381
- if (this.luxttsCloneRef && existsSync33(this.luxttsCloneRef))
36686
+ if (this.luxttsCloneRef && existsSync34(this.luxttsCloneRef))
36382
36687
  return;
36383
36688
  const refsDir = luxttsCloneRefsDir();
36384
- if (!existsSync33(refsDir))
36689
+ if (!existsSync34(refsDir))
36385
36690
  return;
36386
36691
  for (const name of ["custom-clone.wav", "custom-clone.mp3", "glados-ref.wav", "overwatch-ref.wav"]) {
36387
- const p = join41(refsDir, name);
36388
- if (existsSync33(p)) {
36692
+ const p = join42(refsDir, name);
36693
+ if (existsSync34(p)) {
36389
36694
  this.luxttsCloneRef = p;
36390
36695
  return;
36391
36696
  }
@@ -36493,13 +36798,13 @@ if __name__ == '__main__':
36493
36798
  if (this._luxttsDaemon && !this._luxttsDaemon.killed)
36494
36799
  return true;
36495
36800
  const venvPy = luxttsVenvPy();
36496
- if (!existsSync33(venvPy))
36801
+ if (!existsSync34(venvPy))
36497
36802
  return false;
36498
36803
  return new Promise((resolve32) => {
36499
36804
  const env = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
36500
36805
  const daemon = nodeSpawn(venvPy, [luxttsInferScript()], {
36501
36806
  stdio: ["pipe", "pipe", "pipe"],
36502
- cwd: tmpdir6(),
36807
+ cwd: tmpdir7(),
36503
36808
  env
36504
36809
  });
36505
36810
  this._luxttsDaemon = daemon;
@@ -36572,7 +36877,7 @@ if __name__ == '__main__':
36572
36877
  * Volume is applied via WAV sample scaling.
36573
36878
  */
36574
36879
  async synthesizeWithLuxtts(text, volume = 1, pitchFactor = 1, speedFactor = 1) {
36575
- if (!this.luxttsCloneRef || !existsSync33(this.luxttsCloneRef)) {
36880
+ if (!this.luxttsCloneRef || !existsSync34(this.luxttsCloneRef)) {
36576
36881
  return;
36577
36882
  }
36578
36883
  const cleaned = text.replace(/\*/g, "").trim();
@@ -36581,7 +36886,7 @@ if __name__ == '__main__':
36581
36886
  const ready = await this.ensureLuxttsDaemon();
36582
36887
  if (!ready)
36583
36888
  return;
36584
- const wavPath = join41(tmpdir6(), `oa-luxtts-${Date.now()}.wav`);
36889
+ const wavPath = join42(tmpdir7(), `oa-luxtts-${Date.now()}.wav`);
36585
36890
  try {
36586
36891
  await this.luxttsRequest({
36587
36892
  action: "synthesize",
@@ -36593,7 +36898,7 @@ if __name__ == '__main__':
36593
36898
  } catch {
36594
36899
  return;
36595
36900
  }
36596
- if (!existsSync33(wavPath))
36901
+ if (!existsSync34(wavPath))
36597
36902
  return;
36598
36903
  if (volume !== 1) {
36599
36904
  try {
@@ -36638,7 +36943,7 @@ if __name__ == '__main__':
36638
36943
  }
36639
36944
  await this.playWav(wavPath);
36640
36945
  try {
36641
- unlinkSync5(wavPath);
36946
+ unlinkSync6(wavPath);
36642
36947
  } catch {
36643
36948
  }
36644
36949
  }
@@ -36647,7 +36952,7 @@ if __name__ == '__main__':
36647
36952
  * Used for Telegram voice messages and WebSocket streaming.
36648
36953
  */
36649
36954
  async synthesizeLuxttsToBuffer(text) {
36650
- if (!this.luxttsCloneRef || !existsSync33(this.luxttsCloneRef))
36955
+ if (!this.luxttsCloneRef || !existsSync34(this.luxttsCloneRef))
36651
36956
  return null;
36652
36957
  const cleaned = text.replace(/\*/g, "").trim();
36653
36958
  if (!cleaned)
@@ -36655,7 +36960,7 @@ if __name__ == '__main__':
36655
36960
  const ready = await this.ensureLuxttsDaemon();
36656
36961
  if (!ready)
36657
36962
  return null;
36658
- const wavPath = join41(tmpdir6(), `oa-luxtts-buf-${Date.now()}.wav`);
36963
+ const wavPath = join42(tmpdir7(), `oa-luxtts-buf-${Date.now()}.wav`);
36659
36964
  try {
36660
36965
  await this.luxttsRequest({
36661
36966
  action: "synthesize",
@@ -36667,11 +36972,11 @@ if __name__ == '__main__':
36667
36972
  } catch {
36668
36973
  return null;
36669
36974
  }
36670
- if (!existsSync33(wavPath))
36975
+ if (!existsSync34(wavPath))
36671
36976
  return null;
36672
36977
  try {
36673
36978
  const data = readFileSync23(wavPath);
36674
- unlinkSync5(wavPath);
36979
+ unlinkSync6(wavPath);
36675
36980
  return data;
36676
36981
  } catch {
36677
36982
  return null;
@@ -36685,12 +36990,12 @@ if __name__ == '__main__':
36685
36990
  return;
36686
36991
  const arch = process.arch;
36687
36992
  mkdirSync13(voiceDir(), { recursive: true });
36688
- const pkgPath = join41(voiceDir(), "package.json");
36993
+ const pkgPath = join42(voiceDir(), "package.json");
36689
36994
  const expectedDeps = {
36690
36995
  "onnxruntime-node": "^1.21.0",
36691
36996
  "phonemizer": "^1.2.1"
36692
36997
  };
36693
- if (existsSync33(pkgPath)) {
36998
+ if (existsSync34(pkgPath)) {
36694
36999
  try {
36695
37000
  const existing = JSON.parse(readFileSync23(pkgPath, "utf8"));
36696
37001
  if (!existing.dependencies?.["phonemizer"]) {
@@ -36700,25 +37005,25 @@ if __name__ == '__main__':
36700
37005
  } catch {
36701
37006
  }
36702
37007
  }
36703
- if (!existsSync33(pkgPath)) {
37008
+ if (!existsSync34(pkgPath)) {
36704
37009
  writeFileSync13(pkgPath, JSON.stringify({
36705
37010
  name: "open-agents-voice",
36706
37011
  private: true,
36707
37012
  dependencies: expectedDeps
36708
37013
  }, null, 2));
36709
37014
  }
36710
- const voiceRequire = createRequire(join41(voiceDir(), "index.js"));
37015
+ const voiceRequire = createRequire(join42(voiceDir(), "index.js"));
36711
37016
  const probeOnnx = () => {
36712
37017
  try {
36713
- const result = execSync26(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join41(voiceDir(), "node_modules") } });
37018
+ const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join42(voiceDir(), "node_modules") } });
36714
37019
  const output = result.toString().trim();
36715
37020
  return output === "OK";
36716
37021
  } catch {
36717
37022
  return false;
36718
37023
  }
36719
37024
  };
36720
- const onnxNodeModules = join41(voiceDir(), "node_modules", "onnxruntime-node");
36721
- const onnxInstalled = existsSync33(onnxNodeModules);
37025
+ const onnxNodeModules = join42(voiceDir(), "node_modules", "onnxruntime-node");
37026
+ const onnxInstalled = existsSync34(onnxNodeModules);
36722
37027
  if (onnxInstalled && !probeOnnx()) {
36723
37028
  throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
36724
37029
  }
@@ -36727,7 +37032,7 @@ if __name__ == '__main__':
36727
37032
  } catch {
36728
37033
  renderInfo("Installing ONNX runtime for voice synthesis...");
36729
37034
  try {
36730
- execSync26("npm install --no-audit --no-fund", {
37035
+ execSync27("npm install --no-audit --no-fund", {
36731
37036
  cwd: voiceDir(),
36732
37037
  stdio: "pipe",
36733
37038
  timeout: 12e4
@@ -36752,7 +37057,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
36752
37057
  } catch {
36753
37058
  renderInfo("Installing phonemizer for voice synthesis...");
36754
37059
  try {
36755
- execSync26("npm install --no-audit --no-fund", {
37060
+ execSync27("npm install --no-audit --no-fund", {
36756
37061
  cwd: voiceDir(),
36757
37062
  stdio: "pipe",
36758
37063
  timeout: 12e4
@@ -36776,10 +37081,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
36776
37081
  const dir = modelDir(id);
36777
37082
  const onnxPath = modelOnnxPath(id);
36778
37083
  const configPath = modelConfigPath(id);
36779
- if (existsSync33(onnxPath) && existsSync33(configPath))
37084
+ if (existsSync34(onnxPath) && existsSync34(configPath))
36780
37085
  return;
36781
37086
  mkdirSync13(dir, { recursive: true });
36782
- if (!existsSync33(configPath)) {
37087
+ if (!existsSync34(configPath)) {
36783
37088
  renderInfo(`Downloading ${model.label} voice config...`);
36784
37089
  const configResp = await fetch(model.configUrl);
36785
37090
  if (!configResp.ok)
@@ -36787,7 +37092,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
36787
37092
  const configText = await configResp.text();
36788
37093
  writeFileSync13(configPath, configText);
36789
37094
  }
36790
- if (!existsSync33(onnxPath)) {
37095
+ if (!existsSync34(onnxPath)) {
36791
37096
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
36792
37097
  const onnxResp = await fetch(model.onnxUrl);
36793
37098
  if (!onnxResp.ok)
@@ -36824,7 +37129,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
36824
37129
  throw new Error("ONNX runtime not loaded");
36825
37130
  const onnxPath = modelOnnxPath(this.modelId);
36826
37131
  const configPath = modelConfigPath(this.modelId);
36827
- if (!existsSync33(onnxPath) || !existsSync33(configPath)) {
37132
+ if (!existsSync34(onnxPath) || !existsSync34(configPath)) {
36828
37133
  throw new Error(`Model files not found for ${this.modelId}`);
36829
37134
  }
36830
37135
  this.config = JSON.parse(readFileSync23(configPath, "utf8"));
@@ -37498,6 +37803,33 @@ async function handleSlashCommand(input, ctx) {
37498
37803
  }
37499
37804
  return "handled";
37500
37805
  }
37806
+ case "neovim":
37807
+ case "nvim":
37808
+ case "vim": {
37809
+ if (isNeovimActive()) {
37810
+ stopNeovimMode();
37811
+ renderInfo("Neovim mode stopped.");
37812
+ } else {
37813
+ const contentRows = ctx.availableContentRows?.() ?? Math.max(5, (process.stdout.rows ?? 24) - 6);
37814
+ const cols = process.stdout.columns ?? 80;
37815
+ const err = await startNeovimMode({
37816
+ cwd: ctx.repoRoot,
37817
+ contentRows,
37818
+ cols,
37819
+ rl: ctx.rl,
37820
+ initialFile: arg || void 0,
37821
+ onExit: () => {
37822
+ renderInfo("Neovim mode exited.");
37823
+ }
37824
+ });
37825
+ if (err) {
37826
+ renderError(err);
37827
+ } else {
37828
+ renderInfo("Neovim mode started. Ctrl+N toggles focus between editor and input.");
37829
+ }
37830
+ }
37831
+ return "handled";
37832
+ }
37501
37833
  case "dream": {
37502
37834
  if (arg === "stop" || arg === "wake") {
37503
37835
  if (ctx.isDreaming?.()) {
@@ -39020,8 +39352,8 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
39020
39352
  if (models.length > 0) {
39021
39353
  try {
39022
39354
  const { writeFileSync: writeFileSync19, mkdirSync: mkdirSync21 } = await import("node:fs");
39023
- const { join: join55, dirname: dirname20 } = await import("node:path");
39024
- const cachePath = join55(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
39355
+ const { join: join56, dirname: dirname20 } = await import("node:path");
39356
+ const cachePath = join56(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
39025
39357
  mkdirSync21(dirname20(cachePath), { recursive: true });
39026
39358
  writeFileSync19(cachePath, JSON.stringify({
39027
39359
  peerId,
@@ -39072,7 +39404,7 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
39072
39404
  }
39073
39405
  }
39074
39406
  async function handleParallel(arg, ctx) {
39075
- const { execSync: execSync29 } = await import("node:child_process");
39407
+ const { execSync: execSync30 } = await import("node:child_process");
39076
39408
  const baseUrl = ctx.config.backendUrl || "http://localhost:11434";
39077
39409
  const isRemote = ctx.config.backendType === "nexus";
39078
39410
  if (isRemote) {
@@ -39096,7 +39428,7 @@ async function handleParallel(arg, ctx) {
39096
39428
  }
39097
39429
  let systemdVal = "";
39098
39430
  try {
39099
- const out = execSync29("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
39431
+ const out = execSync30("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
39100
39432
  const match = out.match(/OLLAMA_NUM_PARALLEL=(\d+)/);
39101
39433
  if (match)
39102
39434
  systemdVal = match[1];
@@ -39125,7 +39457,7 @@ async function handleParallel(arg, ctx) {
39125
39457
  }
39126
39458
  const isSystemd = (() => {
39127
39459
  try {
39128
- const out = execSync29("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
39460
+ const out = execSync30("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
39129
39461
  return out === "active" || out === "inactive";
39130
39462
  } catch {
39131
39463
  return false;
@@ -39139,10 +39471,10 @@ async function handleParallel(arg, ctx) {
39139
39471
  const overrideContent = `[Service]
39140
39472
  Environment="OLLAMA_NUM_PARALLEL=${n}"
39141
39473
  `;
39142
- execSync29(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
39143
- execSync29(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
39144
- execSync29("sudo systemctl daemon-reload", { stdio: "pipe" });
39145
- execSync29("sudo systemctl restart ollama.service", { stdio: "pipe" });
39474
+ execSync30(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
39475
+ execSync30(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
39476
+ execSync30("sudo systemctl daemon-reload", { stdio: "pipe" });
39477
+ execSync30("sudo systemctl restart ollama.service", { stdio: "pipe" });
39146
39478
  let ready = false;
39147
39479
  for (let i = 0; i < 30 && !ready; i++) {
39148
39480
  await new Promise((r) => setTimeout(r, 500));
@@ -39169,7 +39501,7 @@ Environment="OLLAMA_NUM_PARALLEL=${n}"
39169
39501
  renderInfo(`Setting OLLAMA_NUM_PARALLEL=${n}...`);
39170
39502
  try {
39171
39503
  try {
39172
- execSync29("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
39504
+ execSync30("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
39173
39505
  } catch {
39174
39506
  }
39175
39507
  await new Promise((r) => setTimeout(r, 1e3));
@@ -39222,17 +39554,17 @@ async function handleUpdate(subcommand, ctx) {
39222
39554
  try {
39223
39555
  const { createRequire: createRequire4 } = await import("node:module");
39224
39556
  const { fileURLToPath: fileURLToPath14 } = await import("node:url");
39225
- const { dirname: dirname20, join: join55 } = await import("node:path");
39226
- const { existsSync: existsSync43 } = await import("node:fs");
39557
+ const { dirname: dirname20, join: join56 } = await import("node:path");
39558
+ const { existsSync: existsSync44 } = await import("node:fs");
39227
39559
  const req = createRequire4(import.meta.url);
39228
39560
  const thisDir = dirname20(fileURLToPath14(import.meta.url));
39229
39561
  const candidates = [
39230
- join55(thisDir, "..", "package.json"),
39231
- join55(thisDir, "..", "..", "package.json"),
39232
- join55(thisDir, "..", "..", "..", "package.json")
39562
+ join56(thisDir, "..", "package.json"),
39563
+ join56(thisDir, "..", "..", "package.json"),
39564
+ join56(thisDir, "..", "..", "..", "package.json")
39233
39565
  ];
39234
39566
  for (const pkgPath of candidates) {
39235
- if (existsSync43(pkgPath)) {
39567
+ if (existsSync44(pkgPath)) {
39236
39568
  const pkg = req(pkgPath);
39237
39569
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
39238
39570
  currentVersion = pkg.version ?? "0.0.0";
@@ -39563,8 +39895,8 @@ function getLocalSystemMetrics() {
39563
39895
  vramUtil: 0
39564
39896
  };
39565
39897
  try {
39566
- const { execSync: execSync29 } = __require("node:child_process");
39567
- const smiOut = execSync29("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 });
39898
+ const { execSync: execSync30 } = __require("node:child_process");
39899
+ const smiOut = execSync30("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 });
39568
39900
  const line = smiOut.trim().split("\n")[0];
39569
39901
  if (line) {
39570
39902
  const parts = line.split(",").map((s) => s.trim());
@@ -39790,14 +40122,15 @@ var init_commands = __esm({
39790
40122
  init_dist();
39791
40123
  init_tui_select();
39792
40124
  init_drop_panel();
40125
+ init_neovim_mode();
39793
40126
  DASH_INTERNAL = /* @__PURE__ */ new Set(["system_metrics", "__list_capabilities"]);
39794
40127
  }
39795
40128
  });
39796
40129
 
39797
40130
  // packages/cli/dist/tui/project-context.js
39798
- import { existsSync as existsSync34, readFileSync as readFileSync24, readdirSync as readdirSync10 } from "node:fs";
39799
- import { join as join42, basename as basename10 } from "node:path";
39800
- import { execSync as execSync27 } from "node:child_process";
40131
+ import { existsSync as existsSync35, readFileSync as readFileSync24, readdirSync as readdirSync10 } from "node:fs";
40132
+ import { join as join43, basename as basename10 } from "node:path";
40133
+ import { execSync as execSync28 } from "node:child_process";
39801
40134
  import { homedir as homedir12, platform as platform3, release } from "node:os";
39802
40135
  function getModelTier(modelName) {
39803
40136
  const m = modelName.toLowerCase();
@@ -39831,8 +40164,8 @@ function loadProjectMap(repoRoot) {
39831
40164
  if (!hasOaDirectory(repoRoot)) {
39832
40165
  initOaDirectory(repoRoot);
39833
40166
  }
39834
- const mapPath = join42(repoRoot, OA_DIR, "context", "project-map.md");
39835
- if (existsSync34(mapPath)) {
40167
+ const mapPath = join43(repoRoot, OA_DIR, "context", "project-map.md");
40168
+ if (existsSync35(mapPath)) {
39836
40169
  try {
39837
40170
  const content = readFileSync24(mapPath, "utf-8");
39838
40171
  return content;
@@ -39843,19 +40176,19 @@ function loadProjectMap(repoRoot) {
39843
40176
  }
39844
40177
  function getGitInfo(repoRoot) {
39845
40178
  try {
39846
- execSync27("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
40179
+ execSync28("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
39847
40180
  } catch {
39848
40181
  return "";
39849
40182
  }
39850
40183
  const lines = [];
39851
40184
  try {
39852
- const branch = execSync27("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
40185
+ const branch = execSync28("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
39853
40186
  if (branch)
39854
40187
  lines.push(`Branch: ${branch}`);
39855
40188
  } catch {
39856
40189
  }
39857
40190
  try {
39858
- const status = execSync27("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
40191
+ const status = execSync28("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
39859
40192
  if (status) {
39860
40193
  const changed = status.split("\n").length;
39861
40194
  lines.push(`Working tree: ${changed} changed file(s)`);
@@ -39865,7 +40198,7 @@ function getGitInfo(repoRoot) {
39865
40198
  } catch {
39866
40199
  }
39867
40200
  try {
39868
- const log = execSync27("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
40201
+ const log = execSync28("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
39869
40202
  if (log)
39870
40203
  lines.push(`Recent commits:
39871
40204
  ${log}`);
@@ -39875,31 +40208,31 @@ ${log}`);
39875
40208
  }
39876
40209
  function loadMemoryContext(repoRoot) {
39877
40210
  const sections = [];
39878
- const oaMemDir = join42(repoRoot, OA_DIR, "memory");
40211
+ const oaMemDir = join43(repoRoot, OA_DIR, "memory");
39879
40212
  const oaEntries = loadMemoryDir(oaMemDir, "project");
39880
40213
  if (oaEntries)
39881
40214
  sections.push(oaEntries);
39882
- const legacyMemDir = join42(repoRoot, ".open-agents", "memory");
39883
- if (legacyMemDir !== oaMemDir && existsSync34(legacyMemDir)) {
40215
+ const legacyMemDir = join43(repoRoot, ".open-agents", "memory");
40216
+ if (legacyMemDir !== oaMemDir && existsSync35(legacyMemDir)) {
39884
40217
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
39885
40218
  if (legacyEntries)
39886
40219
  sections.push(legacyEntries);
39887
40220
  }
39888
- const globalMemDir = join42(homedir12(), ".open-agents", "memory");
40221
+ const globalMemDir = join43(homedir12(), ".open-agents", "memory");
39889
40222
  const globalEntries = loadMemoryDir(globalMemDir, "global");
39890
40223
  if (globalEntries)
39891
40224
  sections.push(globalEntries);
39892
40225
  return sections.join("\n\n");
39893
40226
  }
39894
40227
  function loadMemoryDir(memDir, scope) {
39895
- if (!existsSync34(memDir))
40228
+ if (!existsSync35(memDir))
39896
40229
  return "";
39897
40230
  const lines = [];
39898
40231
  try {
39899
40232
  const files = readdirSync10(memDir).filter((f) => f.endsWith(".json"));
39900
40233
  for (const file of files.slice(0, 10)) {
39901
40234
  try {
39902
- const raw = readFileSync24(join42(memDir, file), "utf-8");
40235
+ const raw = readFileSync24(join43(memDir, file), "utf-8");
39903
40236
  const entries = JSON.parse(raw);
39904
40237
  const topic = basename10(file, ".json");
39905
40238
  const keys = Object.keys(entries);
@@ -40640,7 +40973,7 @@ var init_dist7 = __esm({
40640
40973
 
40641
40974
  // packages/cli/dist/tui/carousel.js
40642
40975
  function fg(code, text) {
40643
- return isTTY5 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
40976
+ return isTTY6 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
40644
40977
  }
40645
40978
  function displayWidth(str) {
40646
40979
  let w = 0;
@@ -40678,11 +41011,11 @@ function createRow(phraseIndices, speed, direction, bank) {
40678
41011
  const phrases = phraseIndices.map((i) => bank[i % bank.length]);
40679
41012
  return { phrases, offset: 0, speed, direction, renderedPlain: "" };
40680
41013
  }
40681
- var isTTY5, PHRASES, Carousel;
41014
+ var isTTY6, PHRASES, Carousel;
40682
41015
  var init_carousel = __esm({
40683
41016
  "packages/cli/dist/tui/carousel.js"() {
40684
41017
  "use strict";
40685
- isTTY5 = process.stdout.isTTY ?? false;
41018
+ isTTY6 = process.stdout.isTTY ?? false;
40686
41019
  PHRASES = [
40687
41020
  // English
40688
41021
  { text: "freedom of information", color: 39 },
@@ -40791,7 +41124,7 @@ var init_carousel = __esm({
40791
41124
  * Sets scroll region to row 5+ for all content/readline.
40792
41125
  */
40793
41126
  start() {
40794
- if (!isTTY5)
41127
+ if (!isTTY6)
40795
41128
  return 0;
40796
41129
  this.started = true;
40797
41130
  const termRows = process.stdout.rows ?? 24;
@@ -40823,7 +41156,7 @@ var init_carousel = __esm({
40823
41156
  * Row 4 is left blank as a separator.
40824
41157
  */
40825
41158
  renderFrame() {
40826
- if (!isTTY5)
41159
+ if (!isTTY6)
40827
41160
  return;
40828
41161
  let buf = "\x1B7";
40829
41162
  buf += "\x1B[?7l";
@@ -40903,7 +41236,7 @@ var init_carousel = __esm({
40903
41236
  process.stdout.removeListener("resize", this.resizeHandler);
40904
41237
  this.resizeHandler = null;
40905
41238
  }
40906
- if (!isTTY5 || !this.started)
41239
+ if (!isTTY6 || !this.started)
40907
41240
  return;
40908
41241
  let buf = "\x1B7";
40909
41242
  for (let i = 0; i < this.reservedRows; i++) {
@@ -40922,12 +41255,12 @@ var init_carousel = __esm({
40922
41255
  });
40923
41256
 
40924
41257
  // packages/cli/dist/tui/carousel-descriptors.js
40925
- import { existsSync as existsSync35, readFileSync as readFileSync25, writeFileSync as writeFileSync14, mkdirSync as mkdirSync14, readdirSync as readdirSync11 } from "node:fs";
40926
- import { join as join43, basename as basename11 } from "node:path";
41258
+ import { existsSync as existsSync36, readFileSync as readFileSync25, writeFileSync as writeFileSync14, mkdirSync as mkdirSync14, readdirSync as readdirSync11 } from "node:fs";
41259
+ import { join as join44, basename as basename11 } from "node:path";
40927
41260
  function loadToolProfile(repoRoot) {
40928
- const filePath = join43(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
41261
+ const filePath = join44(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
40929
41262
  try {
40930
- if (!existsSync35(filePath))
41263
+ if (!existsSync36(filePath))
40931
41264
  return null;
40932
41265
  return JSON.parse(readFileSync25(filePath, "utf-8"));
40933
41266
  } catch {
@@ -40935,9 +41268,9 @@ function loadToolProfile(repoRoot) {
40935
41268
  }
40936
41269
  }
40937
41270
  function saveToolProfile(repoRoot, profile) {
40938
- const contextDir = join43(repoRoot, OA_DIR, "context");
41271
+ const contextDir = join44(repoRoot, OA_DIR, "context");
40939
41272
  mkdirSync14(contextDir, { recursive: true });
40940
- writeFileSync14(join43(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
41273
+ writeFileSync14(join44(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
40941
41274
  }
40942
41275
  function categorizeToolCall(toolName) {
40943
41276
  for (const cat of TOOL_CATEGORIES) {
@@ -40995,9 +41328,9 @@ function weightedColor(profile) {
40995
41328
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
40996
41329
  }
40997
41330
  function loadCachedDescriptors(repoRoot) {
40998
- const filePath = join43(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
41331
+ const filePath = join44(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
40999
41332
  try {
41000
- if (!existsSync35(filePath))
41333
+ if (!existsSync36(filePath))
41001
41334
  return null;
41002
41335
  const cached = JSON.parse(readFileSync25(filePath, "utf-8"));
41003
41336
  return cached.phrases.length > 0 ? cached.phrases : null;
@@ -41006,14 +41339,14 @@ function loadCachedDescriptors(repoRoot) {
41006
41339
  }
41007
41340
  }
41008
41341
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
41009
- const contextDir = join43(repoRoot, OA_DIR, "context");
41342
+ const contextDir = join44(repoRoot, OA_DIR, "context");
41010
41343
  mkdirSync14(contextDir, { recursive: true });
41011
41344
  const cached = {
41012
41345
  phrases,
41013
41346
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
41014
41347
  sourceHash
41015
41348
  };
41016
- writeFileSync14(join43(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
41349
+ writeFileSync14(join44(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
41017
41350
  }
41018
41351
  function generateDescriptors(repoRoot) {
41019
41352
  const profile = loadToolProfile(repoRoot);
@@ -41061,9 +41394,9 @@ function generateDescriptors(repoRoot) {
41061
41394
  return phrases;
41062
41395
  }
41063
41396
  function extractFromPackageJson(repoRoot, tags) {
41064
- const pkgPath = join43(repoRoot, "package.json");
41397
+ const pkgPath = join44(repoRoot, "package.json");
41065
41398
  try {
41066
- if (!existsSync35(pkgPath))
41399
+ if (!existsSync36(pkgPath))
41067
41400
  return;
41068
41401
  const pkg = JSON.parse(readFileSync25(pkgPath, "utf-8"));
41069
41402
  if (pkg.name && typeof pkg.name === "string") {
@@ -41109,7 +41442,7 @@ function extractFromManifests(repoRoot, tags) {
41109
41442
  { file: ".github/workflows", tag: "ci/cd" }
41110
41443
  ];
41111
41444
  for (const check of manifestChecks) {
41112
- if (existsSync35(join43(repoRoot, check.file))) {
41445
+ if (existsSync36(join44(repoRoot, check.file))) {
41113
41446
  tags.push(check.tag);
41114
41447
  }
41115
41448
  }
@@ -41131,16 +41464,16 @@ function extractFromSessions(repoRoot, tags) {
41131
41464
  }
41132
41465
  }
41133
41466
  function extractFromMemory(repoRoot, tags) {
41134
- const memoryDir = join43(repoRoot, OA_DIR, "memory");
41467
+ const memoryDir = join44(repoRoot, OA_DIR, "memory");
41135
41468
  try {
41136
- if (!existsSync35(memoryDir))
41469
+ if (!existsSync36(memoryDir))
41137
41470
  return;
41138
41471
  const files = readdirSync11(memoryDir).filter((f) => f.endsWith(".json"));
41139
41472
  for (const file of files) {
41140
41473
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
41141
41474
  tags.push(topic);
41142
41475
  try {
41143
- const data = JSON.parse(readFileSync25(join43(memoryDir, file), "utf-8"));
41476
+ const data = JSON.parse(readFileSync25(join44(memoryDir, file), "utf-8"));
41144
41477
  if (data && typeof data === "object") {
41145
41478
  const keys = Object.keys(data).slice(0, 3);
41146
41479
  for (const key of keys) {
@@ -41276,25 +41609,25 @@ var init_carousel_descriptors = __esm({
41276
41609
 
41277
41610
  // packages/cli/dist/tui/stream-renderer.js
41278
41611
  function fg2563(code, text) {
41279
- return isTTY6 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
41612
+ return isTTY7 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
41280
41613
  }
41281
41614
  function dimText(text) {
41282
- return isTTY6 ? `\x1B[2m${text}\x1B[0m` : text;
41615
+ return isTTY7 ? `\x1B[2m${text}\x1B[0m` : text;
41283
41616
  }
41284
41617
  function italicText(text) {
41285
- return isTTY6 ? `\x1B[3m${text}\x1B[0m` : text;
41618
+ return isTTY7 ? `\x1B[3m${text}\x1B[0m` : text;
41286
41619
  }
41287
41620
  function dimItalic(text) {
41288
- return isTTY6 ? `\x1B[2;3m${text}\x1B[0m` : text;
41621
+ return isTTY7 ? `\x1B[2;3m${text}\x1B[0m` : text;
41289
41622
  }
41290
41623
  function boldText(text) {
41291
- return isTTY6 ? `\x1B[1m${text}\x1B[0m` : text;
41624
+ return isTTY7 ? `\x1B[1m${text}\x1B[0m` : text;
41292
41625
  }
41293
- var isTTY6, PASTEL, StreamRenderer;
41626
+ var isTTY7, PASTEL, StreamRenderer;
41294
41627
  var init_stream_renderer = __esm({
41295
41628
  "packages/cli/dist/tui/stream-renderer.js"() {
41296
41629
  "use strict";
41297
- isTTY6 = process.stdout.isTTY ?? false;
41630
+ isTTY7 = process.stdout.isTTY ?? false;
41298
41631
  PASTEL = {
41299
41632
  key: 222,
41300
41633
  // light gold — JSON keys
@@ -41763,10 +42096,10 @@ var init_stream_renderer = __esm({
41763
42096
 
41764
42097
  // packages/cli/dist/tui/edit-history.js
41765
42098
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync15 } from "node:fs";
41766
- import { join as join44 } from "node:path";
42099
+ import { join as join45 } from "node:path";
41767
42100
  function createEditHistoryLogger(repoRoot, sessionId) {
41768
- const historyDir = join44(repoRoot, ".oa", "history");
41769
- const logPath = join44(historyDir, "edits.jsonl");
42101
+ const historyDir = join45(repoRoot, ".oa", "history");
42102
+ const logPath = join45(historyDir, "edits.jsonl");
41770
42103
  try {
41771
42104
  mkdirSync15(historyDir, { recursive: true });
41772
42105
  } catch {
@@ -41877,14 +42210,14 @@ var init_edit_history = __esm({
41877
42210
  });
41878
42211
 
41879
42212
  // packages/cli/dist/tui/promptLoader.js
41880
- import { readFileSync as readFileSync26, existsSync as existsSync36 } from "node:fs";
41881
- import { join as join45, dirname as dirname17 } from "node:path";
42213
+ import { readFileSync as readFileSync26, existsSync as existsSync37 } from "node:fs";
42214
+ import { join as join46, dirname as dirname17 } from "node:path";
41882
42215
  import { fileURLToPath as fileURLToPath11 } from "node:url";
41883
42216
  function loadPrompt3(promptPath, vars) {
41884
42217
  let content = cache3.get(promptPath);
41885
42218
  if (content === void 0) {
41886
- const fullPath = join45(PROMPTS_DIR3, promptPath);
41887
- if (!existsSync36(fullPath)) {
42219
+ const fullPath = join46(PROMPTS_DIR3, promptPath);
42220
+ if (!existsSync37(fullPath)) {
41888
42221
  throw new Error(`Prompt file not found: ${fullPath}`);
41889
42222
  }
41890
42223
  content = readFileSync26(fullPath, "utf-8");
@@ -41900,20 +42233,20 @@ var init_promptLoader3 = __esm({
41900
42233
  "use strict";
41901
42234
  __filename3 = fileURLToPath11(import.meta.url);
41902
42235
  __dirname6 = dirname17(__filename3);
41903
- devPath2 = join45(__dirname6, "..", "..", "prompts");
41904
- publishedPath2 = join45(__dirname6, "..", "prompts");
41905
- PROMPTS_DIR3 = existsSync36(devPath2) ? devPath2 : publishedPath2;
42236
+ devPath2 = join46(__dirname6, "..", "..", "prompts");
42237
+ publishedPath2 = join46(__dirname6, "..", "prompts");
42238
+ PROMPTS_DIR3 = existsSync37(devPath2) ? devPath2 : publishedPath2;
41906
42239
  cache3 = /* @__PURE__ */ new Map();
41907
42240
  }
41908
42241
  });
41909
42242
 
41910
42243
  // packages/cli/dist/tui/dream-engine.js
41911
- import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync15, readFileSync as readFileSync27, existsSync as existsSync37, cpSync, rmSync, readdirSync as readdirSync12 } from "node:fs";
41912
- import { join as join46, basename as basename12 } from "node:path";
41913
- import { execSync as execSync28 } from "node:child_process";
42244
+ import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync15, readFileSync as readFileSync27, existsSync as existsSync38, cpSync, rmSync, readdirSync as readdirSync12 } from "node:fs";
42245
+ import { join as join47, basename as basename12 } from "node:path";
42246
+ import { execSync as execSync29 } from "node:child_process";
41914
42247
  function loadAutoresearchMemory(repoRoot) {
41915
- const memoryPath = join46(repoRoot, ".oa", "memory", "autoresearch.json");
41916
- if (!existsSync37(memoryPath))
42248
+ const memoryPath = join47(repoRoot, ".oa", "memory", "autoresearch.json");
42249
+ if (!existsSync38(memoryPath))
41917
42250
  return "";
41918
42251
  try {
41919
42252
  const raw = readFileSync27(memoryPath, "utf-8");
@@ -42106,12 +42439,12 @@ var init_dream_engine = __esm({
42106
42439
  const content = String(args["content"] ?? "");
42107
42440
  if (!rawPath)
42108
42441
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
42109
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join46(this.autoresearchDir, basename12(rawPath)) : join46(this.autoresearchDir, rawPath);
42442
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join47(this.autoresearchDir, basename12(rawPath)) : join47(this.autoresearchDir, rawPath);
42110
42443
  if (!targetPath.startsWith(this.autoresearchDir)) {
42111
42444
  return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
42112
42445
  }
42113
42446
  try {
42114
- const dir = join46(targetPath, "..");
42447
+ const dir = join47(targetPath, "..");
42115
42448
  mkdirSync16(dir, { recursive: true });
42116
42449
  writeFileSync15(targetPath, content, "utf-8");
42117
42450
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
@@ -42141,12 +42474,12 @@ var init_dream_engine = __esm({
42141
42474
  const rawPath = String(args["path"] ?? "");
42142
42475
  const oldStr = String(args["old_string"] ?? "");
42143
42476
  const newStr = String(args["new_string"] ?? "");
42144
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join46(this.autoresearchDir, basename12(rawPath)) : join46(this.autoresearchDir, rawPath);
42477
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join47(this.autoresearchDir, basename12(rawPath)) : join47(this.autoresearchDir, rawPath);
42145
42478
  if (!targetPath.startsWith(this.autoresearchDir)) {
42146
42479
  return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
42147
42480
  }
42148
42481
  try {
42149
- if (!existsSync37(targetPath)) {
42482
+ if (!existsSync38(targetPath)) {
42150
42483
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
42151
42484
  }
42152
42485
  let content = readFileSync27(targetPath, "utf-8");
@@ -42195,12 +42528,12 @@ var init_dream_engine = __esm({
42195
42528
  const content = String(args["content"] ?? "");
42196
42529
  if (!rawPath)
42197
42530
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
42198
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join46(this.dreamsDir, basename12(rawPath)) : join46(this.dreamsDir, rawPath);
42531
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join47(this.dreamsDir, basename12(rawPath)) : join47(this.dreamsDir, rawPath);
42199
42532
  if (!targetPath.startsWith(this.dreamsDir)) {
42200
42533
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
42201
42534
  }
42202
42535
  try {
42203
- const dir = join46(targetPath, "..");
42536
+ const dir = join47(targetPath, "..");
42204
42537
  mkdirSync16(dir, { recursive: true });
42205
42538
  writeFileSync15(targetPath, content, "utf-8");
42206
42539
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
@@ -42230,12 +42563,12 @@ var init_dream_engine = __esm({
42230
42563
  const rawPath = String(args["path"] ?? "");
42231
42564
  const oldStr = String(args["old_string"] ?? "");
42232
42565
  const newStr = String(args["new_string"] ?? "");
42233
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join46(this.dreamsDir, basename12(rawPath)) : join46(this.dreamsDir, rawPath);
42566
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join47(this.dreamsDir, basename12(rawPath)) : join47(this.dreamsDir, rawPath);
42234
42567
  if (!targetPath.startsWith(this.dreamsDir)) {
42235
42568
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
42236
42569
  }
42237
42570
  try {
42238
- if (!existsSync37(targetPath)) {
42571
+ if (!existsSync38(targetPath)) {
42239
42572
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
42240
42573
  }
42241
42574
  let content = readFileSync27(targetPath, "utf-8");
@@ -42274,7 +42607,7 @@ var init_dream_engine = __esm({
42274
42607
  }
42275
42608
  }
42276
42609
  try {
42277
- const output = execSync28(cmd, {
42610
+ const output = execSync29(cmd, {
42278
42611
  cwd: this.repoRoot,
42279
42612
  timeout: 3e4,
42280
42613
  encoding: "utf-8",
@@ -42297,7 +42630,7 @@ var init_dream_engine = __esm({
42297
42630
  constructor(config, repoRoot) {
42298
42631
  this.config = config;
42299
42632
  this.repoRoot = repoRoot;
42300
- this.dreamsDir = join46(repoRoot, ".oa", "dreams");
42633
+ this.dreamsDir = join47(repoRoot, ".oa", "dreams");
42301
42634
  this.state = {
42302
42635
  mode: "default",
42303
42636
  active: false,
@@ -42381,7 +42714,7 @@ ${result.summary}`;
42381
42714
  if (mode !== "default" || cycle === totalCycles) {
42382
42715
  renderDreamContraction(cycle);
42383
42716
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
42384
- const summaryPath = join46(this.dreamsDir, `cycle-${cycle}-summary.md`);
42717
+ const summaryPath = join47(this.dreamsDir, `cycle-${cycle}-summary.md`);
42385
42718
  writeFileSync15(summaryPath, cycleSummary, "utf-8");
42386
42719
  }
42387
42720
  if (mode === "lucid" && !this.abortController.signal.aborted) {
@@ -42594,7 +42927,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
42594
42927
  }
42595
42928
  /** Build role-specific tool sets for swarm agents */
42596
42929
  buildSwarmTools(role, _workspace) {
42597
- const autoresearchDir = join46(this.repoRoot, ".oa", "autoresearch");
42930
+ const autoresearchDir = join47(this.repoRoot, ".oa", "autoresearch");
42598
42931
  const taskComplete = this.createSwarmTaskCompleteTool(role);
42599
42932
  switch (role) {
42600
42933
  case "researcher": {
@@ -42958,7 +43291,7 @@ INSTRUCTIONS:
42958
43291
  2. Summarize the key learnings and next steps
42959
43292
 
42960
43293
  Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
42961
- const reportPath = join46(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
43294
+ const reportPath = join47(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
42962
43295
  const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
42963
43296
 
42964
43297
  **Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -43047,29 +43380,29 @@ ${summaryResult}
43047
43380
  }
43048
43381
  /** Save workspace backup for lucid mode */
43049
43382
  saveVersionCheckpoint(cycle) {
43050
- const checkpointDir = join46(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
43383
+ const checkpointDir = join47(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
43051
43384
  try {
43052
43385
  mkdirSync16(checkpointDir, { recursive: true });
43053
43386
  try {
43054
- const gitStatus = execSync28("git status --porcelain", {
43387
+ const gitStatus = execSync29("git status --porcelain", {
43055
43388
  cwd: this.repoRoot,
43056
43389
  encoding: "utf-8",
43057
43390
  timeout: 1e4
43058
43391
  });
43059
- const gitDiff = execSync28("git diff", {
43392
+ const gitDiff = execSync29("git diff", {
43060
43393
  cwd: this.repoRoot,
43061
43394
  encoding: "utf-8",
43062
43395
  timeout: 1e4
43063
43396
  });
43064
- const gitHash = execSync28("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
43397
+ const gitHash = execSync29("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
43065
43398
  cwd: this.repoRoot,
43066
43399
  encoding: "utf-8",
43067
43400
  timeout: 5e3
43068
43401
  }).trim();
43069
- writeFileSync15(join46(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
43070
- writeFileSync15(join46(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
43071
- writeFileSync15(join46(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
43072
- writeFileSync15(join46(checkpointDir, "checkpoint.json"), JSON.stringify({
43402
+ writeFileSync15(join47(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
43403
+ writeFileSync15(join47(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
43404
+ writeFileSync15(join47(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
43405
+ writeFileSync15(join47(checkpointDir, "checkpoint.json"), JSON.stringify({
43073
43406
  cycle,
43074
43407
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
43075
43408
  gitHash,
@@ -43077,7 +43410,7 @@ ${summaryResult}
43077
43410
  }, null, 2), "utf-8");
43078
43411
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
43079
43412
  } catch {
43080
- writeFileSync15(join46(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
43413
+ writeFileSync15(join47(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
43081
43414
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
43082
43415
  }
43083
43416
  } catch (err) {
@@ -43135,14 +43468,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
43135
43468
  ---
43136
43469
  *Auto-generated by open-agents dream engine*
43137
43470
  `;
43138
- writeFileSync15(join46(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
43471
+ writeFileSync15(join47(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
43139
43472
  } catch {
43140
43473
  }
43141
43474
  }
43142
43475
  /** Save dream state for resume/inspection */
43143
43476
  saveDreamState() {
43144
43477
  try {
43145
- writeFileSync15(join46(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
43478
+ writeFileSync15(join47(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
43146
43479
  } catch {
43147
43480
  }
43148
43481
  }
@@ -43516,8 +43849,8 @@ var init_bless_engine = __esm({
43516
43849
  });
43517
43850
 
43518
43851
  // packages/cli/dist/tui/dmn-engine.js
43519
- import { existsSync as existsSync38, readFileSync as readFileSync28, writeFileSync as writeFileSync16, mkdirSync as mkdirSync17, readdirSync as readdirSync13, unlinkSync as unlinkSync6 } from "node:fs";
43520
- import { join as join47, basename as basename13 } from "node:path";
43852
+ import { existsSync as existsSync39, readFileSync as readFileSync28, writeFileSync as writeFileSync16, mkdirSync as mkdirSync17, readdirSync as readdirSync13, unlinkSync as unlinkSync7 } from "node:fs";
43853
+ import { join as join48, basename as basename13 } from "node:path";
43521
43854
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
43522
43855
  const competenceReport = competence.length > 0 ? competence.map((c3) => {
43523
43856
  const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
@@ -43630,8 +43963,8 @@ var init_dmn_engine = __esm({
43630
43963
  constructor(config, repoRoot) {
43631
43964
  this.config = config;
43632
43965
  this.repoRoot = repoRoot;
43633
- this.stateDir = join47(repoRoot, ".oa", "dmn");
43634
- this.historyDir = join47(repoRoot, ".oa", "dmn", "cycles");
43966
+ this.stateDir = join48(repoRoot, ".oa", "dmn");
43967
+ this.historyDir = join48(repoRoot, ".oa", "dmn", "cycles");
43635
43968
  mkdirSync17(this.historyDir, { recursive: true });
43636
43969
  this.loadState();
43637
43970
  }
@@ -44221,11 +44554,11 @@ OUTPUT: Call task_complete with JSON:
44221
44554
  async gatherMemoryTopics() {
44222
44555
  const topics = [];
44223
44556
  const dirs = [
44224
- join47(this.repoRoot, ".oa", "memory"),
44225
- join47(this.repoRoot, ".open-agents", "memory")
44557
+ join48(this.repoRoot, ".oa", "memory"),
44558
+ join48(this.repoRoot, ".open-agents", "memory")
44226
44559
  ];
44227
44560
  for (const dir of dirs) {
44228
- if (!existsSync38(dir))
44561
+ if (!existsSync39(dir))
44229
44562
  continue;
44230
44563
  try {
44231
44564
  const files = readdirSync13(dir).filter((f) => f.endsWith(".json"));
@@ -44241,8 +44574,8 @@ OUTPUT: Call task_complete with JSON:
44241
44574
  }
44242
44575
  // ── State persistence ─────────────────────────────────────────────────
44243
44576
  loadState() {
44244
- const path = join47(this.stateDir, "state.json");
44245
- if (existsSync38(path)) {
44577
+ const path = join48(this.stateDir, "state.json");
44578
+ if (existsSync39(path)) {
44246
44579
  try {
44247
44580
  this.state = JSON.parse(readFileSync28(path, "utf-8"));
44248
44581
  } catch {
@@ -44251,19 +44584,19 @@ OUTPUT: Call task_complete with JSON:
44251
44584
  }
44252
44585
  saveState() {
44253
44586
  try {
44254
- writeFileSync16(join47(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
44587
+ writeFileSync16(join48(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
44255
44588
  } catch {
44256
44589
  }
44257
44590
  }
44258
44591
  saveCycleResult(result) {
44259
44592
  try {
44260
44593
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
44261
- writeFileSync16(join47(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
44594
+ writeFileSync16(join48(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
44262
44595
  const files = readdirSync13(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
44263
44596
  if (files.length > 50) {
44264
44597
  for (const old of files.slice(0, files.length - 50)) {
44265
44598
  try {
44266
- unlinkSync6(join47(this.historyDir, old));
44599
+ unlinkSync7(join48(this.historyDir, old));
44267
44600
  } catch {
44268
44601
  }
44269
44602
  }
@@ -44276,8 +44609,8 @@ OUTPUT: Call task_complete with JSON:
44276
44609
  });
44277
44610
 
44278
44611
  // packages/cli/dist/tui/snr-engine.js
44279
- import { existsSync as existsSync39, readdirSync as readdirSync14, readFileSync as readFileSync29 } from "node:fs";
44280
- import { join as join48, basename as basename14 } from "node:path";
44612
+ import { existsSync as existsSync40, readdirSync as readdirSync14, readFileSync as readFileSync29 } from "node:fs";
44613
+ import { join as join49, basename as basename14 } from "node:path";
44281
44614
  function computeDPrime(signalScores, noiseScores) {
44282
44615
  if (signalScores.length === 0 || noiseScores.length === 0)
44283
44616
  return 0;
@@ -44517,11 +44850,11 @@ Call task_complete with the JSON array when done.`, onEvent)
44517
44850
  loadMemoryEntries(topics) {
44518
44851
  const entries = [];
44519
44852
  const dirs = [
44520
- join48(this.repoRoot, ".oa", "memory"),
44521
- join48(this.repoRoot, ".open-agents", "memory")
44853
+ join49(this.repoRoot, ".oa", "memory"),
44854
+ join49(this.repoRoot, ".open-agents", "memory")
44522
44855
  ];
44523
44856
  for (const dir of dirs) {
44524
- if (!existsSync39(dir))
44857
+ if (!existsSync40(dir))
44525
44858
  continue;
44526
44859
  try {
44527
44860
  const files = readdirSync14(dir).filter((f) => f.endsWith(".json"));
@@ -44530,7 +44863,7 @@ Call task_complete with the JSON array when done.`, onEvent)
44530
44863
  if (topics.length > 0 && !topics.includes(topic))
44531
44864
  continue;
44532
44865
  try {
44533
- const data = JSON.parse(readFileSync29(join48(dir, f), "utf-8"));
44866
+ const data = JSON.parse(readFileSync29(join49(dir, f), "utf-8"));
44534
44867
  for (const [key, val] of Object.entries(data)) {
44535
44868
  const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
44536
44869
  entries.push({ topic, key, value });
@@ -45097,8 +45430,8 @@ var init_tool_policy = __esm({
45097
45430
  });
45098
45431
 
45099
45432
  // packages/cli/dist/tui/telegram-bridge.js
45100
- import { mkdirSync as mkdirSync18, existsSync as existsSync40, unlinkSync as unlinkSync7, readdirSync as readdirSync15, statSync as statSync11 } from "node:fs";
45101
- import { join as join49, resolve as resolve28 } from "node:path";
45433
+ import { mkdirSync as mkdirSync18, existsSync as existsSync41, unlinkSync as unlinkSync8, readdirSync as readdirSync15, statSync as statSync11 } from "node:fs";
45434
+ import { join as join50, resolve as resolve28 } from "node:path";
45102
45435
  import { writeFile as writeFileAsync } from "node:fs/promises";
45103
45436
  function convertMarkdownToTelegramHTML(md) {
45104
45437
  let html = md;
@@ -45863,7 +46196,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
45863
46196
  return null;
45864
46197
  const buffer = Buffer.from(await res.arrayBuffer());
45865
46198
  const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
45866
- const localPath = join49(this.mediaCacheDir, fileName);
46199
+ const localPath = join50(this.mediaCacheDir, fileName);
45867
46200
  await writeFileAsync(localPath, buffer);
45868
46201
  return localPath;
45869
46202
  } catch {
@@ -45951,7 +46284,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
45951
46284
  for (const [key, entry] of this.mediaCache) {
45952
46285
  if (now - entry.cachedAt > MEDIA_CACHE_TTL_MS) {
45953
46286
  try {
45954
- unlinkSync7(entry.localPath);
46287
+ unlinkSync8(entry.localPath);
45955
46288
  } catch {
45956
46289
  }
45957
46290
  this.mediaCache.delete(key);
@@ -46027,11 +46360,11 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
46027
46360
  let mimeType = "audio/wav";
46028
46361
  try {
46029
46362
  const { execSync: execSyncLocal } = await import("node:child_process");
46030
- const { tmpdir: tmpdir8 } = await import("node:os");
46363
+ const { tmpdir: tmpdir9 } = await import("node:os");
46031
46364
  const { join: joinPath } = await import("node:path");
46032
46365
  const { writeFileSync: writeFs, readFileSync: readFs, unlinkSync: unlinkFs } = await import("node:fs");
46033
- const tmpWav = joinPath(tmpdir8(), `oa-tg-voice-${Date.now()}.wav`);
46034
- const tmpOgg = joinPath(tmpdir8(), `oa-tg-voice-${Date.now()}.ogg`);
46366
+ const tmpWav = joinPath(tmpdir9(), `oa-tg-voice-${Date.now()}.wav`);
46367
+ const tmpOgg = joinPath(tmpdir9(), `oa-tg-voice-${Date.now()}.ogg`);
46035
46368
  writeFs(tmpWav, wavBuffer);
46036
46369
  execSyncLocal(`ffmpeg -i "${tmpWav}" -c:a libopus -b:a 48k -ar 48000 -ac 1 "${tmpOgg}" -y 2>/dev/null`, {
46037
46370
  timeout: 15e3,
@@ -48208,11 +48541,11 @@ var init_status_bar = __esm({
48208
48541
  import * as readline2 from "node:readline";
48209
48542
  import { Writable } from "node:stream";
48210
48543
  import { cwd } from "node:process";
48211
- import { resolve as resolve29, join as join50, dirname as dirname18, extname as extname10 } from "node:path";
48544
+ import { resolve as resolve29, join as join51, dirname as dirname18, extname as extname10 } from "node:path";
48212
48545
  import { createRequire as createRequire2 } from "node:module";
48213
48546
  import { fileURLToPath as fileURLToPath12 } from "node:url";
48214
48547
  import { readFileSync as readFileSync30, writeFileSync as writeFileSync17, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as readdirSync16, mkdirSync as mkdirSync19 } from "node:fs";
48215
- import { existsSync as existsSync41 } from "node:fs";
48548
+ import { existsSync as existsSync42 } from "node:fs";
48216
48549
  import { homedir as homedir13 } from "node:os";
48217
48550
  function formatTimeAgo(date) {
48218
48551
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
@@ -48232,12 +48565,12 @@ function getVersion3() {
48232
48565
  const require2 = createRequire2(import.meta.url);
48233
48566
  const thisDir = dirname18(fileURLToPath12(import.meta.url));
48234
48567
  const candidates = [
48235
- join50(thisDir, "..", "package.json"),
48236
- join50(thisDir, "..", "..", "package.json"),
48237
- join50(thisDir, "..", "..", "..", "package.json")
48568
+ join51(thisDir, "..", "package.json"),
48569
+ join51(thisDir, "..", "..", "package.json"),
48570
+ join51(thisDir, "..", "..", "..", "package.json")
48238
48571
  ];
48239
48572
  for (const pkgPath of candidates) {
48240
- if (existsSync41(pkgPath)) {
48573
+ if (existsSync42(pkgPath)) {
48241
48574
  const pkg = require2(pkgPath);
48242
48575
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
48243
48576
  return pkg.version ?? "0.0.0";
@@ -48444,15 +48777,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
48444
48777
  function gatherMemorySnippets(root) {
48445
48778
  const snippets = [];
48446
48779
  const dirs = [
48447
- join50(root, ".oa", "memory"),
48448
- join50(root, ".open-agents", "memory")
48780
+ join51(root, ".oa", "memory"),
48781
+ join51(root, ".open-agents", "memory")
48449
48782
  ];
48450
48783
  for (const dir of dirs) {
48451
- if (!existsSync41(dir))
48784
+ if (!existsSync42(dir))
48452
48785
  continue;
48453
48786
  try {
48454
48787
  for (const f of readdirSync16(dir).filter((f2) => f2.endsWith(".json"))) {
48455
- const data = JSON.parse(readFileSync30(join50(dir, f), "utf-8"));
48788
+ const data = JSON.parse(readFileSync30(join51(dir, f), "utf-8"));
48456
48789
  for (const val of Object.values(data)) {
48457
48790
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
48458
48791
  if (v.length > 10)
@@ -48897,8 +49230,18 @@ ${entry.fullContent}`
48897
49230
  const name = event.toolName ?? "";
48898
49231
  if (name === "file_write" || name === "file_edit" || name === "file_patch" || name === "batch_edit") {
48899
49232
  filesTouched.add(event.toolArgs.path);
49233
+ if (isNeovimActive()) {
49234
+ notifyNeovimFileChange(event.toolArgs.path).catch(() => {
49235
+ });
49236
+ }
48900
49237
  }
48901
49238
  }
49239
+ if (isNeovimActive()) {
49240
+ const toolName = event.toolName ?? "unknown";
49241
+ const argSummary = Object.keys(event.toolArgs ?? {}).join(", ");
49242
+ writeToNeovimOutput(`\x1B[33m\u25B6 ${toolName}\x1B[0m(${argSummary})\r
49243
+ `);
49244
+ }
48902
49245
  getActivityFeed().push({
48903
49246
  ts: Date.now(),
48904
49247
  source: "main",
@@ -48958,6 +49301,13 @@ ${entry.fullContent}`
48958
49301
  }
48959
49302
  }
48960
49303
  });
49304
+ if (isNeovimActive()) {
49305
+ const ok = event.success ?? false;
49306
+ const prefix = ok ? "\x1B[32m\u2713\x1B[0m" : "\x1B[31m\u2717\x1B[0m";
49307
+ const preview = (event.content ?? "").slice(0, 120).replace(/\n/g, " ");
49308
+ writeToNeovimOutput(` ${prefix} ${preview}\r
49309
+ `);
49310
+ }
48961
49311
  break;
48962
49312
  }
48963
49313
  case "model_response":
@@ -48982,6 +49332,9 @@ ${entry.fullContent}`
48982
49332
  if (stream?.enabled) {
48983
49333
  stream.renderer.write(event.content ?? "", event.streamKind ?? "content");
48984
49334
  }
49335
+ if (isNeovimActive() && event.content && (event.streamKind ?? "content") === "content") {
49336
+ writeToNeovimOutput(event.content);
49337
+ }
48985
49338
  if (voice?.enabled && (voice.voiceMode === "chat" || voice.voiceMode === "verbose")) {
48986
49339
  if (event.content && (event.streamKind ?? "content") === "content") {
48987
49340
  streamTextBuffer += event.content;
@@ -49344,7 +49697,7 @@ async function startInteractive(config, repoPath) {
49344
49697
  let p2pGateway = null;
49345
49698
  let peerMesh = null;
49346
49699
  let inferenceRouter = null;
49347
- const secretVault = new SecretVault(join50(repoRoot, ".oa", "vault.enc"));
49700
+ const secretVault = new SecretVault(join51(repoRoot, ".oa", "vault.enc"));
49348
49701
  let adminSessionKey = null;
49349
49702
  const callSubAgents = /* @__PURE__ */ new Map();
49350
49703
  const streamRenderer = new StreamRenderer();
@@ -49553,12 +49906,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
49553
49906
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
49554
49907
  return [hits, line];
49555
49908
  }
49556
- const HISTORY_DIR = join50(homedir13(), ".open-agents");
49557
- const HISTORY_FILE = join50(HISTORY_DIR, "repl-history");
49909
+ const HISTORY_DIR = join51(homedir13(), ".open-agents");
49910
+ const HISTORY_FILE = join51(HISTORY_DIR, "repl-history");
49558
49911
  const MAX_HISTORY_LINES = 500;
49559
49912
  let savedHistory = [];
49560
49913
  try {
49561
- if (existsSync41(HISTORY_FILE)) {
49914
+ if (existsSync42(HISTORY_FILE)) {
49562
49915
  const raw = readFileSync30(HISTORY_FILE, "utf8").trim();
49563
49916
  if (raw)
49564
49917
  savedHistory = raw.split("\n").reverse();
@@ -49600,6 +49953,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
49600
49953
  }
49601
49954
  process.stdout.on("resize", () => {
49602
49955
  statusBar.handleResize();
49956
+ if (isNeovimActive()) {
49957
+ const contentRows = statusBar.isActive ? statusBar.availableContentRows : Math.max(5, (process.stdout.rows ?? 24) - 6);
49958
+ resizeNeovim(process.stdout.columns ?? 80, contentRows);
49959
+ }
49603
49960
  if (!carouselRetired) {
49604
49961
  const termRows = process.stdout.rows ?? 24;
49605
49962
  const scrollStart = carousel.reservedRows + 1;
@@ -49717,7 +50074,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
49717
50074
  } catch {
49718
50075
  }
49719
50076
  try {
49720
- const oaDir = join50(repoRoot, ".oa");
50077
+ const oaDir = join51(repoRoot, ".oa");
49721
50078
  const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
49722
50079
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
49723
50080
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -49739,7 +50096,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
49739
50096
  } catch {
49740
50097
  }
49741
50098
  try {
49742
- const oaDir = join50(repoRoot, ".oa");
50099
+ const oaDir = join51(repoRoot, ".oa");
49743
50100
  const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
49744
50101
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
49745
50102
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -50539,7 +50896,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
50539
50896
  kind,
50540
50897
  targetUrl,
50541
50898
  authKey,
50542
- stateDir: join50(repoRoot, ".oa"),
50899
+ stateDir: join51(repoRoot, ".oa"),
50543
50900
  passthrough: passthrough ?? false,
50544
50901
  loadbalance: loadbalance ?? false,
50545
50902
  endpointAuth: passthrough ? currentConfig.apiKey : void 0,
@@ -50584,7 +50941,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
50584
50941
  await tunnelGateway.stop();
50585
50942
  tunnelGateway = null;
50586
50943
  }
50587
- const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join50(repoRoot, ".oa") });
50944
+ const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join51(repoRoot, ".oa") });
50588
50945
  newTunnel.on("stats", (stats) => {
50589
50946
  statusBar.setExposeStatus({
50590
50947
  status: stats.status,
@@ -50834,8 +51191,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
50834
51191
  return statusBar.isActive ? statusBar.availableContentRows : Math.max(3, (process.stdout.rows ?? 24) - 6);
50835
51192
  },
50836
51193
  destroyProject() {
50837
- const oaPath = join50(repoRoot, OA_DIR);
50838
- if (existsSync41(oaPath)) {
51194
+ const oaPath = join51(repoRoot, OA_DIR);
51195
+ if (existsSync42(oaPath)) {
50839
51196
  try {
50840
51197
  rmSync2(oaPath, { recursive: true, force: true });
50841
51198
  writeContent(() => renderInfo(`Removed ${OA_DIR}/ directory.`));
@@ -51164,8 +51521,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
51164
51521
  }
51165
51522
  }
51166
51523
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
51167
- const isImage = isImagePath(cleanPath) && existsSync41(resolve29(repoRoot, cleanPath));
51168
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync41(resolve29(repoRoot, cleanPath));
51524
+ const isImage = isImagePath(cleanPath) && existsSync42(resolve29(repoRoot, cleanPath));
51525
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync42(resolve29(repoRoot, cleanPath));
51169
51526
  if (activeTask) {
51170
51527
  if (activeTask.runner.isPaused) {
51171
51528
  activeTask.runner.resume();
@@ -51711,6 +52068,7 @@ var init_interactive = __esm({
51711
52068
  init_status_bar();
51712
52069
  init_dist6();
51713
52070
  init_overlay_lock();
52071
+ init_neovim_mode();
51714
52072
  taskManager = new BackgroundTaskManager();
51715
52073
  }
51716
52074
  });
@@ -51746,7 +52104,7 @@ import { glob } from "glob";
51746
52104
  import ignore from "ignore";
51747
52105
  import { readFile as readFile17, stat as stat4 } from "node:fs/promises";
51748
52106
  import { createHash as createHash4 } from "node:crypto";
51749
- import { join as join51, relative as relative3, extname as extname11, basename as basename15 } from "node:path";
52107
+ import { join as join52, relative as relative3, extname as extname11, basename as basename15 } from "node:path";
51750
52108
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
51751
52109
  var init_codebase_indexer = __esm({
51752
52110
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -51790,7 +52148,7 @@ var init_codebase_indexer = __esm({
51790
52148
  const ig = ignore.default();
51791
52149
  if (this.config.respectGitignore) {
51792
52150
  try {
51793
- const gitignoreContent = await readFile17(join51(this.config.rootDir, ".gitignore"), "utf-8");
52151
+ const gitignoreContent = await readFile17(join52(this.config.rootDir, ".gitignore"), "utf-8");
51794
52152
  ig.add(gitignoreContent);
51795
52153
  } catch {
51796
52154
  }
@@ -51805,7 +52163,7 @@ var init_codebase_indexer = __esm({
51805
52163
  for (const relativePath of files) {
51806
52164
  if (ig.ignores(relativePath))
51807
52165
  continue;
51808
- const fullPath = join51(this.config.rootDir, relativePath);
52166
+ const fullPath = join52(this.config.rootDir, relativePath);
51809
52167
  try {
51810
52168
  const fileStat = await stat4(fullPath);
51811
52169
  if (fileStat.size > this.config.maxFileSize)
@@ -51851,7 +52209,7 @@ var init_codebase_indexer = __esm({
51851
52209
  if (!child) {
51852
52210
  child = {
51853
52211
  name: part,
51854
- path: join51(current.path, part),
52212
+ path: join52(current.path, part),
51855
52213
  type: "directory",
51856
52214
  children: []
51857
52215
  };
@@ -51934,13 +52292,13 @@ __export(index_repo_exports, {
51934
52292
  indexRepoCommand: () => indexRepoCommand
51935
52293
  });
51936
52294
  import { resolve as resolve30 } from "node:path";
51937
- import { existsSync as existsSync42, statSync as statSync12 } from "node:fs";
52295
+ import { existsSync as existsSync43, statSync as statSync12 } from "node:fs";
51938
52296
  import { cwd as cwd2 } from "node:process";
51939
52297
  async function indexRepoCommand(opts, _config) {
51940
52298
  const repoRoot = resolve30(opts.repoPath ?? cwd2());
51941
52299
  printHeader("Index Repository");
51942
52300
  printInfo(`Indexing: ${repoRoot}`);
51943
- if (!existsSync42(repoRoot)) {
52301
+ if (!existsSync43(repoRoot)) {
51944
52302
  printError(`Path does not exist: ${repoRoot}`);
51945
52303
  process.exit(1);
51946
52304
  }
@@ -52192,7 +52550,7 @@ var config_exports = {};
52192
52550
  __export(config_exports, {
52193
52551
  configCommand: () => configCommand
52194
52552
  });
52195
- import { join as join52, resolve as resolve31 } from "node:path";
52553
+ import { join as join53, resolve as resolve31 } from "node:path";
52196
52554
  import { homedir as homedir14 } from "node:os";
52197
52555
  import { cwd as cwd3 } from "node:process";
52198
52556
  function redactIfSensitive(key, value) {
@@ -52275,7 +52633,7 @@ function handleShow(opts, config) {
52275
52633
  }
52276
52634
  }
52277
52635
  printSection("Config File");
52278
- printInfo(`~/.open-agents/config.json (${join52(homedir14(), ".open-agents", "config.json")})`);
52636
+ printInfo(`~/.open-agents/config.json (${join53(homedir14(), ".open-agents", "config.json")})`);
52279
52637
  printSection("Priority Chain");
52280
52638
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
52281
52639
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -52314,7 +52672,7 @@ function handleSet(opts, _config) {
52314
52672
  const coerced = coerceForSettings(key, value);
52315
52673
  saveProjectSettings(repoRoot, { [key]: coerced });
52316
52674
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
52317
- printInfo(`Saved to ${join52(repoRoot, ".oa", "settings.json")}`);
52675
+ printInfo(`Saved to ${join53(repoRoot, ".oa", "settings.json")}`);
52318
52676
  printInfo("This override applies only when running in this workspace.");
52319
52677
  } catch (err) {
52320
52678
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -52571,9 +52929,9 @@ var eval_exports = {};
52571
52929
  __export(eval_exports, {
52572
52930
  evalCommand: () => evalCommand
52573
52931
  });
52574
- import { tmpdir as tmpdir7 } from "node:os";
52932
+ import { tmpdir as tmpdir8 } from "node:os";
52575
52933
  import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync18 } from "node:fs";
52576
- import { join as join53 } from "node:path";
52934
+ import { join as join54 } from "node:path";
52577
52935
  async function evalCommand(opts, config) {
52578
52936
  const suiteName = opts.suite ?? "basic";
52579
52937
  const suite = SUITES[suiteName];
@@ -52698,9 +53056,9 @@ async function evalCommand(opts, config) {
52698
53056
  process.exit(failed > 0 ? 1 : 0);
52699
53057
  }
52700
53058
  function createTempEvalRepo() {
52701
- const dir = join53(tmpdir7(), `open-agents-eval-${Date.now()}`);
53059
+ const dir = join54(tmpdir8(), `open-agents-eval-${Date.now()}`);
52702
53060
  mkdirSync20(dir, { recursive: true });
52703
- writeFileSync18(join53(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
53061
+ writeFileSync18(join54(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
52704
53062
  return dir;
52705
53063
  }
52706
53064
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -52760,7 +53118,7 @@ init_updater();
52760
53118
  import { parseArgs as nodeParseArgs2 } from "node:util";
52761
53119
  import { createRequire as createRequire3 } from "node:module";
52762
53120
  import { fileURLToPath as fileURLToPath13 } from "node:url";
52763
- import { dirname as dirname19, join as join54 } from "node:path";
53121
+ import { dirname as dirname19, join as join55 } from "node:path";
52764
53122
 
52765
53123
  // packages/cli/dist/cli.js
52766
53124
  import { createInterface } from "node:readline";
@@ -52867,7 +53225,7 @@ init_output();
52867
53225
  function getVersion4() {
52868
53226
  try {
52869
53227
  const require2 = createRequire3(import.meta.url);
52870
- const pkgPath = join54(dirname19(fileURLToPath13(import.meta.url)), "..", "package.json");
53228
+ const pkgPath = join55(dirname19(fileURLToPath13(import.meta.url)), "..", "package.json");
52871
53229
  const pkg = require2(pkgPath);
52872
53230
  return pkg.version;
52873
53231
  } catch {