open-agents-ai 0.104.4 → 0.104.6

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 +753 -291
  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,26 +31013,26 @@ 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: readFileSync32 } = 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 status = JSON.parse(readFileSync31(statusPath, "utf8"));
31023
+ const statusPath = join56(nexusDir, "status.json");
31024
+ if (existsSync44(statusPath)) {
31025
+ const status = JSON.parse(readFileSync32(statusPath, "utf8"));
31024
31026
  if (status.peerId === peerId)
31025
31027
  isLocalPeer = true;
31026
31028
  }
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
- const pricing = JSON.parse(readFileSync31(pricingPath, "utf8"));
31035
+ const pricing = JSON.parse(readFileSync32(pricingPath, "utf8"));
31034
31036
  const localModels = (pricing.models || []).map((m) => ({
31035
31037
  name: m.model || "unknown",
31036
31038
  size: m.parameterSize || "",
@@ -31044,10 +31046,10 @@ 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
- const cache4 = JSON.parse(readFileSync31(cachePath, "utf8"));
31052
+ const cache4 = JSON.parse(readFileSync32(cachePath, "utf8"));
31051
31053
  if (cache4.peerId === peerId && cache4.models?.length > 0) {
31052
31054
  const age = Date.now() - new Date(cache4.cachedAt).getTime();
31053
31055
  if (age < 5 * 60 * 1e3) {
@@ -31162,10 +31164,10 @@ 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
- const pricing = JSON.parse(readFileSync31(pricingPath, "utf8"));
31170
+ const pricing = JSON.parse(readFileSync32(pricingPath, "utf8"));
31169
31171
  return (pricing.models || []).map((m) => ({
31170
31172
  name: m.model || "unknown",
31171
31173
  size: m.parameterSize || "",
@@ -32092,7 +32094,7 @@ var init_oa_directory = __esm({
32092
32094
  import * as readline from "node:readline";
32093
32095
  import { execSync as execSync25, spawn as spawn17, exec as exec2 } from "node:child_process";
32094
32096
  import { promisify as promisify5 } from "node:util";
32095
- import { existsSync as existsSync31, writeFileSync as writeFileSync12, mkdirSync as mkdirSync12 } from "node:fs";
32097
+ import { existsSync as existsSync31, writeFileSync as writeFileSync12, readFileSync as readFileSync23, appendFileSync as appendFileSync2, mkdirSync as mkdirSync12 } from "node:fs";
32096
32098
  import { join as join40 } from "node:path";
32097
32099
  import { homedir as homedir10, platform } from "node:os";
32098
32100
  function detectSystemSpecs() {
@@ -33670,6 +33672,105 @@ async function ensureExpandedContext(modelName, backendUrl) {
33670
33672
  }
33671
33673
  return { model: modelName, created: false, contextLabel: ctx.label, numCtx: ctx.numCtx };
33672
33674
  }
33675
+ async function ensureNeovim() {
33676
+ try {
33677
+ const nvimPath = execSync25("which nvim 2>/dev/null || where nvim 2>nul", {
33678
+ encoding: "utf8",
33679
+ stdio: "pipe",
33680
+ timeout: 5e3
33681
+ }).trim();
33682
+ if (nvimPath)
33683
+ return nvimPath;
33684
+ } catch {
33685
+ }
33686
+ const platform5 = process.platform;
33687
+ const arch = process.arch;
33688
+ if (platform5 === "linux") {
33689
+ const binDir = join40(homedir10(), ".local", "bin");
33690
+ const nvimDest = join40(binDir, "nvim");
33691
+ try {
33692
+ mkdirSync12(binDir, { recursive: true });
33693
+ } catch {
33694
+ }
33695
+ const appImageName = arch === "arm64" ? "nvim-linux-arm64.appimage" : "nvim-linux-x86_64.appimage";
33696
+ const url = `https://github.com/neovim/neovim/releases/latest/download/${appImageName}`;
33697
+ console.log(` Downloading Neovim (${appImageName})...`);
33698
+ try {
33699
+ execSync25(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
33700
+ execSync25(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
33701
+ } catch (err) {
33702
+ console.log(` Failed to download Neovim: ${err instanceof Error ? err.message : String(err)}`);
33703
+ return null;
33704
+ }
33705
+ try {
33706
+ const ver = execSync25(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
33707
+ console.log(` Installed: ${ver}`);
33708
+ } catch {
33709
+ console.log(" Warning: nvim binary downloaded but may not work (missing FUSE? Try: nvim --appimage-extract)");
33710
+ }
33711
+ if (!process.env.PATH?.includes(binDir)) {
33712
+ process.env.PATH = `${binDir}:${process.env.PATH}`;
33713
+ }
33714
+ ensurePathInShellRc(binDir);
33715
+ return nvimDest;
33716
+ }
33717
+ if (platform5 === "darwin") {
33718
+ if (hasCmd("brew")) {
33719
+ console.log(" Installing Neovim via Homebrew...");
33720
+ try {
33721
+ execSync25("brew install neovim", { stdio: "inherit", timeout: 12e4 });
33722
+ const nvimPath = execSync25("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
33723
+ return nvimPath || null;
33724
+ } catch {
33725
+ console.log(" brew install neovim failed.");
33726
+ return null;
33727
+ }
33728
+ }
33729
+ console.log(" Homebrew not found. Install Neovim: brew install neovim");
33730
+ return null;
33731
+ }
33732
+ if (platform5 === "win32") {
33733
+ if (hasCmd("choco")) {
33734
+ console.log(" Installing Neovim via Chocolatey...");
33735
+ try {
33736
+ execSync25("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
33737
+ return "nvim";
33738
+ } catch {
33739
+ console.log(" choco install neovim failed.");
33740
+ }
33741
+ }
33742
+ if (hasCmd("winget")) {
33743
+ console.log(" Installing Neovim via winget...");
33744
+ try {
33745
+ execSync25("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
33746
+ stdio: "inherit",
33747
+ timeout: 12e4
33748
+ });
33749
+ return "nvim";
33750
+ } catch {
33751
+ console.log(" winget install neovim failed.");
33752
+ }
33753
+ }
33754
+ console.log(" Install Neovim manually: https://neovim.io");
33755
+ return null;
33756
+ }
33757
+ return null;
33758
+ }
33759
+ function ensurePathInShellRc(binDir) {
33760
+ const shell = process.env.SHELL ?? "";
33761
+ const rcFile = shell.includes("zsh") ? join40(homedir10(), ".zshrc") : join40(homedir10(), ".bashrc");
33762
+ try {
33763
+ const rcContent = existsSync31(rcFile) ? readFileSync23(rcFile, "utf8") : "";
33764
+ if (rcContent.includes(binDir))
33765
+ return;
33766
+ const exportLine = `
33767
+ export PATH="${binDir}:$PATH" # Added by open-agents for nvim
33768
+ `;
33769
+ appendFileSync2(rcFile, exportLine, "utf8");
33770
+ console.log(` Added ${binDir} to ${rcFile}`);
33771
+ } catch {
33772
+ }
33773
+ }
33673
33774
  var execAsync, QWEN_VARIANTS, TOOL_CALLING_MODELS, _cloudflaredInstallPromise;
33674
33775
  var init_setup = __esm({
33675
33776
  "packages/cli/dist/tui/setup.js"() {
@@ -34426,6 +34527,314 @@ var init_drop_panel = __esm({
34426
34527
  }
34427
34528
  });
34428
34529
 
34530
+ // packages/cli/dist/tui/neovim-mode.js
34531
+ import { existsSync as existsSync33, unlinkSync as unlinkSync5 } from "node:fs";
34532
+ import { tmpdir as tmpdir6 } from "node:os";
34533
+ import { join as join41 } from "node:path";
34534
+ import { execSync as execSync26 } from "node:child_process";
34535
+ function isNeovimActive() {
34536
+ return _state !== null && !_state.cleanedUp;
34537
+ }
34538
+ async function startNeovimMode(opts) {
34539
+ if (_state && !_state.cleanedUp) {
34540
+ return "Neovim mode is already active. Use /neovim to exit first.";
34541
+ }
34542
+ let nvimPath;
34543
+ try {
34544
+ nvimPath = execSync26("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
34545
+ if (!nvimPath)
34546
+ throw new Error();
34547
+ } catch {
34548
+ const installed = await ensureNeovim();
34549
+ if (!installed) {
34550
+ return "nvim not found and auto-install failed. Install Neovim: https://neovim.io";
34551
+ }
34552
+ nvimPath = installed;
34553
+ }
34554
+ let ptyMod;
34555
+ try {
34556
+ const ptyModName = "node-pty";
34557
+ ptyMod = await import(
34558
+ /* @vite-ignore */
34559
+ ptyModName
34560
+ );
34561
+ } catch {
34562
+ return "node-pty not available. Install it: npm install node-pty";
34563
+ }
34564
+ let neovimPkg = null;
34565
+ try {
34566
+ const nvimModName = "neovim";
34567
+ neovimPkg = await import(
34568
+ /* @vite-ignore */
34569
+ nvimModName
34570
+ );
34571
+ } catch {
34572
+ }
34573
+ const socketPath = join41(tmpdir6(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
34574
+ try {
34575
+ if (existsSync33(socketPath))
34576
+ unlinkSync5(socketPath);
34577
+ } catch {
34578
+ }
34579
+ const ptyCols = opts.cols;
34580
+ const ptyRows = Math.max(5, opts.contentRows);
34581
+ const nvimArgs = [
34582
+ "--listen",
34583
+ socketPath,
34584
+ "--cmd",
34585
+ "set autoread updatetime=300 signcolumn=no"
34586
+ ];
34587
+ if (opts.initialFile) {
34588
+ nvimArgs.push(opts.initialFile);
34589
+ } else {
34590
+ nvimArgs.push(".");
34591
+ }
34592
+ const nvimPty = ptyMod.spawn(nvimPath, nvimArgs, {
34593
+ name: "xterm-256color",
34594
+ cols: ptyCols,
34595
+ rows: ptyRows,
34596
+ cwd: opts.cwd,
34597
+ env: { ...process.env }
34598
+ });
34599
+ const state = {
34600
+ pty: nvimPty,
34601
+ nvim: null,
34602
+ outputChanId: 0,
34603
+ socketPath,
34604
+ focused: true,
34605
+ opts,
34606
+ stdinHandler: null,
34607
+ savedRlListeners: [],
34608
+ cleanedUp: false
34609
+ };
34610
+ _state = state;
34611
+ nvimPty.onData((data) => {
34612
+ if (state.cleanedUp)
34613
+ return;
34614
+ if (!state.focused) {
34615
+ process.stdout.write("\x1B7" + data + "\x1B8");
34616
+ } else {
34617
+ process.stdout.write(data);
34618
+ }
34619
+ });
34620
+ nvimPty.onExit(() => {
34621
+ if (!state.cleanedUp) {
34622
+ doCleanup(state);
34623
+ }
34624
+ });
34625
+ const stdin = process.stdin;
34626
+ if (opts.rl) {
34627
+ opts.rl.pause();
34628
+ for (const event of ["keypress", "data"]) {
34629
+ const listeners = stdin.listeners(event);
34630
+ for (const fn of listeners) {
34631
+ state.savedRlListeners.push({ event, fn });
34632
+ stdin.removeListener(event, fn);
34633
+ }
34634
+ }
34635
+ }
34636
+ if (typeof stdin.setRawMode === "function") {
34637
+ stdin.setRawMode(true);
34638
+ }
34639
+ stdin.resume();
34640
+ state.stdinHandler = (data) => {
34641
+ if (state.cleanedUp)
34642
+ return;
34643
+ const seq = data.toString("utf8");
34644
+ if (seq === "") {
34645
+ toggleFocus(state);
34646
+ return;
34647
+ }
34648
+ if (state.focused) {
34649
+ nvimPty.write(seq);
34650
+ }
34651
+ };
34652
+ stdin.on("data", state.stdinHandler);
34653
+ if (neovimPkg) {
34654
+ connectRPC(state, neovimPkg, ptyCols).catch(() => {
34655
+ });
34656
+ }
34657
+ return null;
34658
+ }
34659
+ function stopNeovimMode() {
34660
+ if (!_state || _state.cleanedUp)
34661
+ return;
34662
+ try {
34663
+ _state.pty?.write(":qa!\r");
34664
+ } catch {
34665
+ }
34666
+ setTimeout(() => {
34667
+ if (_state && !_state.cleanedUp) {
34668
+ doCleanup(_state);
34669
+ }
34670
+ }, 500);
34671
+ }
34672
+ function writeToNeovimOutput(text) {
34673
+ if (!_state || _state.cleanedUp || !_state.nvim || !_state.outputChanId)
34674
+ return;
34675
+ const normalized = text.replace(/(?<!\r)\n/g, "\r\n");
34676
+ _state.nvim.request("nvim_chan_send", [_state.outputChanId, normalized]).catch(() => {
34677
+ });
34678
+ }
34679
+ async function notifyNeovimFileChange(filePath) {
34680
+ if (!_state || _state.cleanedUp || !_state.nvim)
34681
+ return;
34682
+ try {
34683
+ await _state.nvim.command("checktime");
34684
+ if (filePath) {
34685
+ const escaped = filePath.replace(/'/g, "''");
34686
+ await _state.nvim.command(`if bufexists('${escaped}') | execute 'buffer ' . bufnr('${escaped}') | endif`);
34687
+ }
34688
+ } catch {
34689
+ }
34690
+ }
34691
+ function resizeNeovim(cols, contentRows) {
34692
+ if (!_state || _state.cleanedUp || !_state.pty)
34693
+ return;
34694
+ const rows = Math.max(5, contentRows);
34695
+ try {
34696
+ _state.pty.resize(cols, rows);
34697
+ } catch {
34698
+ }
34699
+ }
34700
+ async function connectRPC(state, neovimPkg, cols) {
34701
+ let attempts = 0;
34702
+ while (!existsSync33(state.socketPath) && attempts < 30) {
34703
+ await new Promise((r) => setTimeout(r, 200));
34704
+ attempts++;
34705
+ if (state.cleanedUp)
34706
+ return;
34707
+ }
34708
+ if (!existsSync33(state.socketPath))
34709
+ return;
34710
+ const nvim = neovimPkg.attach({ socket: state.socketPath });
34711
+ state.nvim = nvim;
34712
+ await new Promise((r) => setTimeout(r, 300));
34713
+ if (state.cleanedUp)
34714
+ return;
34715
+ try {
34716
+ const editorWidth = Math.floor(cols * 0.7);
34717
+ const outputWidth = cols - editorWidth;
34718
+ await nvim.command("botright vsplit");
34719
+ await nvim.command(`vertical resize ${outputWidth}`);
34720
+ const buf = await nvim.createBuffer(false, true);
34721
+ const win = await nvim.window;
34722
+ await nvim.request("nvim_win_set_buf", [win.id, buf.id]);
34723
+ await nvim.request("nvim_buf_set_option", [buf.id, "buftype", "nofile"]);
34724
+ await nvim.request("nvim_buf_set_option", [buf.id, "swapfile", false]);
34725
+ const chanId = await nvim.request("nvim_open_term", [buf.id, {}]);
34726
+ state.outputChanId = chanId;
34727
+ await nvim.request("nvim_chan_send", [
34728
+ chanId,
34729
+ "\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"
34730
+ ]);
34731
+ await nvim.request("nvim_win_set_option", [win.id, "number", false]);
34732
+ await nvim.request("nvim_win_set_option", [win.id, "relativenumber", false]);
34733
+ await nvim.request("nvim_win_set_option", [win.id, "wrap", true]);
34734
+ await nvim.command("wincmd h");
34735
+ await nvim.command("set autoread");
34736
+ await nvim.command("autocmd FocusGained,BufEnter,CursorHold * silent! checktime");
34737
+ } catch {
34738
+ }
34739
+ }
34740
+ function toggleFocus(state) {
34741
+ const stdin = process.stdin;
34742
+ if (state.focused) {
34743
+ state.focused = false;
34744
+ if (state.stdinHandler) {
34745
+ stdin.removeListener("data", state.stdinHandler);
34746
+ }
34747
+ if (typeof stdin.setRawMode === "function") {
34748
+ stdin.setRawMode(false);
34749
+ }
34750
+ for (const { event, fn } of state.savedRlListeners) {
34751
+ stdin.on(event, fn);
34752
+ }
34753
+ if (state.opts.rl) {
34754
+ state.opts.rl.resume();
34755
+ state.opts.rl.prompt(false);
34756
+ }
34757
+ } else {
34758
+ state.focused = true;
34759
+ if (state.opts.rl) {
34760
+ state.opts.rl.pause();
34761
+ }
34762
+ state.savedRlListeners = [];
34763
+ for (const event of ["keypress", "data"]) {
34764
+ const listeners = stdin.listeners(event);
34765
+ for (const fn of listeners) {
34766
+ state.savedRlListeners.push({ event, fn });
34767
+ stdin.removeListener(event, fn);
34768
+ }
34769
+ }
34770
+ if (typeof stdin.setRawMode === "function") {
34771
+ stdin.setRawMode(true);
34772
+ }
34773
+ stdin.resume();
34774
+ if (state.stdinHandler) {
34775
+ stdin.on("data", state.stdinHandler);
34776
+ }
34777
+ if (state.nvim) {
34778
+ state.nvim.command("echo ''").catch(() => {
34779
+ });
34780
+ }
34781
+ }
34782
+ }
34783
+ function doCleanup(state) {
34784
+ if (state.cleanedUp)
34785
+ return;
34786
+ state.cleanedUp = true;
34787
+ const stdin = process.stdin;
34788
+ if (state.nvim) {
34789
+ try {
34790
+ state.nvim.quit();
34791
+ } catch {
34792
+ }
34793
+ state.nvim = null;
34794
+ }
34795
+ if (state.pty) {
34796
+ try {
34797
+ state.pty.kill();
34798
+ } catch {
34799
+ }
34800
+ state.pty = null;
34801
+ }
34802
+ try {
34803
+ if (existsSync33(state.socketPath))
34804
+ unlinkSync5(state.socketPath);
34805
+ } catch {
34806
+ }
34807
+ if (state.stdinHandler) {
34808
+ stdin.removeListener("data", state.stdinHandler);
34809
+ state.stdinHandler = null;
34810
+ }
34811
+ if (typeof stdin.setRawMode === "function") {
34812
+ try {
34813
+ stdin.setRawMode(false);
34814
+ } catch {
34815
+ }
34816
+ }
34817
+ for (const { event, fn } of state.savedRlListeners) {
34818
+ stdin.on(event, fn);
34819
+ }
34820
+ if (state.opts.rl) {
34821
+ state.opts.rl.resume();
34822
+ state.opts.rl.prompt(false);
34823
+ }
34824
+ _state = null;
34825
+ process.stdout.write("\x1B[H\x1B[J");
34826
+ state.opts.onExit?.();
34827
+ }
34828
+ var isTTY5, _state;
34829
+ var init_neovim_mode = __esm({
34830
+ "packages/cli/dist/tui/neovim-mode.js"() {
34831
+ "use strict";
34832
+ init_setup();
34833
+ isTTY5 = process.stdout.isTTY ?? false;
34834
+ _state = null;
34835
+ }
34836
+ });
34837
+
34429
34838
  // packages/cli/dist/tui/voice.js
34430
34839
  var voice_exports = {};
34431
34840
  __export(voice_exports, {
@@ -34438,10 +34847,10 @@ __export(voice_exports, {
34438
34847
  registerCustomOnnxModel: () => registerCustomOnnxModel,
34439
34848
  resetNarrationContext: () => resetNarrationContext
34440
34849
  });
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";
34850
+ import { existsSync as existsSync34, mkdirSync as mkdirSync13, writeFileSync as writeFileSync13, readFileSync as readFileSync24, unlinkSync as unlinkSync6, readdirSync as readdirSync9, renameSync, statSync as statSync10 } from "node:fs";
34851
+ import { join as join42 } from "node:path";
34852
+ import { homedir as homedir11, tmpdir as tmpdir7, platform as platform2 } from "node:os";
34853
+ import { execSync as execSync27, spawn as nodeSpawn } from "node:child_process";
34445
34854
  import { createRequire } from "node:module";
34446
34855
  function registerCustomOnnxModel(id, label) {
34447
34856
  VOICE_MODELS[id] = {
@@ -34461,34 +34870,34 @@ function listVoiceModels() {
34461
34870
  }));
34462
34871
  }
34463
34872
  function voiceDir() {
34464
- return join41(homedir11(), ".open-agents", "voice");
34873
+ return join42(homedir11(), ".open-agents", "voice");
34465
34874
  }
34466
34875
  function modelsDir() {
34467
- return join41(voiceDir(), "models");
34876
+ return join42(voiceDir(), "models");
34468
34877
  }
34469
34878
  function modelDir(id) {
34470
- return join41(modelsDir(), id);
34879
+ return join42(modelsDir(), id);
34471
34880
  }
34472
34881
  function modelOnnxPath(id) {
34473
- return join41(modelDir(id), "model.onnx");
34882
+ return join42(modelDir(id), "model.onnx");
34474
34883
  }
34475
34884
  function modelConfigPath(id) {
34476
- return join41(modelDir(id), "config.json");
34885
+ return join42(modelDir(id), "config.json");
34477
34886
  }
34478
34887
  function luxttsVenvDir() {
34479
- return join41(voiceDir(), "luxtts-venv");
34888
+ return join42(voiceDir(), "luxtts-venv");
34480
34889
  }
34481
34890
  function luxttsVenvPy() {
34482
- return platform2() === "win32" ? join41(luxttsVenvDir(), "Scripts", "python.exe") : join41(luxttsVenvDir(), "bin", "python3");
34891
+ return platform2() === "win32" ? join42(luxttsVenvDir(), "Scripts", "python.exe") : join42(luxttsVenvDir(), "bin", "python3");
34483
34892
  }
34484
34893
  function luxttsRepoDir() {
34485
- return join41(voiceDir(), "LuxTTS");
34894
+ return join42(voiceDir(), "LuxTTS");
34486
34895
  }
34487
34896
  function luxttsCloneRefsDir() {
34488
- return join41(voiceDir(), "clone-refs");
34897
+ return join42(voiceDir(), "clone-refs");
34489
34898
  }
34490
34899
  function luxttsInferScript() {
34491
- return join41(voiceDir(), "luxtts-infer.py");
34900
+ return join42(voiceDir(), "luxtts-infer.py");
34492
34901
  }
34493
34902
  function emotionToPitchBias(emotion, stark = false, autist = false) {
34494
34903
  if (autist)
@@ -35296,8 +35705,8 @@ var init_voice = __esm({
35296
35705
  const refsDir = luxttsCloneRefsDir();
35297
35706
  const targets = ["glados", "overwatch"];
35298
35707
  for (const modelId of targets) {
35299
- const refFile = join41(refsDir, `${modelId}-ref.wav`);
35300
- if (existsSync33(refFile))
35708
+ const refFile = join42(refsDir, `${modelId}-ref.wav`);
35709
+ if (existsSync34(refFile))
35301
35710
  continue;
35302
35711
  try {
35303
35712
  await this.generateCloneRef(modelId);
@@ -35376,23 +35785,23 @@ var init_voice = __esm({
35376
35785
  }
35377
35786
  p = p.replace(/\\ /g, " ");
35378
35787
  if (p.startsWith("~/") || p === "~") {
35379
- p = join41(homedir11(), p.slice(1));
35788
+ p = join42(homedir11(), p.slice(1));
35380
35789
  }
35381
- if (!existsSync33(p)) {
35790
+ if (!existsSync34(p)) {
35382
35791
  return `File not found: ${p}
35383
35792
  (original input: ${audioPath})`;
35384
35793
  }
35385
35794
  audioPath = p;
35386
35795
  const refsDir = luxttsCloneRefsDir();
35387
- if (!existsSync33(refsDir))
35796
+ if (!existsSync34(refsDir))
35388
35797
  mkdirSync13(refsDir, { recursive: true });
35389
35798
  const ext = audioPath.split(".").pop() || "wav";
35390
35799
  const srcName = (audioPath.split("/").pop() ?? "clone").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]/g, "-");
35391
35800
  const ts = Date.now().toString(36);
35392
35801
  const destFilename = `clone-${srcName}-${ts}.${ext}`;
35393
- const destPath = join41(refsDir, destFilename);
35802
+ const destPath = join42(refsDir, destFilename);
35394
35803
  try {
35395
- const data = readFileSync23(audioPath);
35804
+ const data = readFileSync24(audioPath);
35396
35805
  writeFileSync13(destPath, data);
35397
35806
  } catch (err) {
35398
35807
  return `Failed to copy audio file: ${err instanceof Error ? err.message : String(err)}`;
@@ -35433,9 +35842,9 @@ var init_voice = __esm({
35433
35842
  return `Failed to synthesize reference audio from ${source.label}.`;
35434
35843
  }
35435
35844
  const refsDir = luxttsCloneRefsDir();
35436
- if (!existsSync33(refsDir))
35845
+ if (!existsSync34(refsDir))
35437
35846
  mkdirSync13(refsDir, { recursive: true });
35438
- const destPath = join41(refsDir, `${sourceModelId}-ref.wav`);
35847
+ const destPath = join42(refsDir, `${sourceModelId}-ref.wav`);
35439
35848
  const sampleRate = this.config?.audio?.sample_rate ?? 22050;
35440
35849
  this.writeWav(audioData, sampleRate, destPath);
35441
35850
  this.luxttsCloneRef = destPath;
@@ -35451,21 +35860,21 @@ var init_voice = __esm({
35451
35860
  // -------------------------------------------------------------------------
35452
35861
  /** Metadata file for friendly names of clone refs */
35453
35862
  static cloneMetaFile() {
35454
- return join41(luxttsCloneRefsDir(), "meta.json");
35863
+ return join42(luxttsCloneRefsDir(), "meta.json");
35455
35864
  }
35456
35865
  loadCloneMeta() {
35457
35866
  const p = _VoiceEngine.cloneMetaFile();
35458
- if (!existsSync33(p))
35867
+ if (!existsSync34(p))
35459
35868
  return {};
35460
35869
  try {
35461
- return JSON.parse(readFileSync23(p, "utf8"));
35870
+ return JSON.parse(readFileSync24(p, "utf8"));
35462
35871
  } catch {
35463
35872
  return {};
35464
35873
  }
35465
35874
  }
35466
35875
  saveCloneMeta(meta) {
35467
35876
  const dir = luxttsCloneRefsDir();
35468
- if (!existsSync33(dir))
35877
+ if (!existsSync34(dir))
35469
35878
  mkdirSync13(dir, { recursive: true });
35470
35879
  writeFileSync13(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
35471
35880
  }
@@ -35477,7 +35886,7 @@ var init_voice = __esm({
35477
35886
  */
35478
35887
  listCloneRefs() {
35479
35888
  const dir = luxttsCloneRefsDir();
35480
- if (!existsSync33(dir))
35889
+ if (!existsSync34(dir))
35481
35890
  return [];
35482
35891
  const meta = this.loadCloneMeta();
35483
35892
  const files = readdirSync9(dir).filter((f) => {
@@ -35485,7 +35894,7 @@ var init_voice = __esm({
35485
35894
  return _VoiceEngine.AUDIO_EXTS.has(ext);
35486
35895
  });
35487
35896
  return files.map((f) => {
35488
- const p = join41(dir, f);
35897
+ const p = join42(dir, f);
35489
35898
  let size = 0;
35490
35899
  try {
35491
35900
  size = statSync10(p).size;
@@ -35502,11 +35911,11 @@ var init_voice = __esm({
35502
35911
  }
35503
35912
  /** Delete a clone reference file by filename. Returns true if deleted. */
35504
35913
  deleteCloneRef(filename) {
35505
- const p = join41(luxttsCloneRefsDir(), filename);
35506
- if (!existsSync33(p))
35914
+ const p = join42(luxttsCloneRefsDir(), filename);
35915
+ if (!existsSync34(p))
35507
35916
  return false;
35508
35917
  try {
35509
- unlinkSync5(p);
35918
+ unlinkSync6(p);
35510
35919
  const meta = this.loadCloneMeta();
35511
35920
  delete meta[filename];
35512
35921
  this.saveCloneMeta(meta);
@@ -35527,8 +35936,8 @@ var init_voice = __esm({
35527
35936
  }
35528
35937
  /** Set the active clone reference by filename. */
35529
35938
  setActiveCloneRef(filename) {
35530
- const p = join41(luxttsCloneRefsDir(), filename);
35531
- if (!existsSync33(p))
35939
+ const p = join42(luxttsCloneRefsDir(), filename);
35940
+ if (!existsSync34(p))
35532
35941
  return `File not found: ${filename}`;
35533
35942
  this.luxttsCloneRef = p;
35534
35943
  return `Active clone voice set to: ${filename}`;
@@ -35813,11 +36222,11 @@ var init_voice = __esm({
35813
36222
  }
35814
36223
  this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
35815
36224
  }
35816
- const wavPath = join41(tmpdir6(), `oa-voice-${Date.now()}.wav`);
36225
+ const wavPath = join42(tmpdir7(), `oa-voice-${Date.now()}.wav`);
35817
36226
  this.writeWav(audioData, sampleRate, wavPath);
35818
36227
  await this.playWav(wavPath);
35819
36228
  try {
35820
- unlinkSync5(wavPath);
36229
+ unlinkSync6(wavPath);
35821
36230
  } catch {
35822
36231
  }
35823
36232
  }
@@ -36001,7 +36410,7 @@ var init_voice = __esm({
36001
36410
  }
36002
36411
  for (const player of ["paplay", "pw-play", "aplay"]) {
36003
36412
  try {
36004
- execSync26(`which ${player}`, { stdio: "pipe" });
36413
+ execSync27(`which ${player}`, { stdio: "pipe" });
36005
36414
  return [player, path];
36006
36415
  } catch {
36007
36416
  }
@@ -36030,7 +36439,7 @@ var init_voice = __esm({
36030
36439
  return this.python3Path;
36031
36440
  for (const bin of ["python3", "python"]) {
36032
36441
  try {
36033
- const path = execSync26(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
36442
+ const path = execSync27(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
36034
36443
  if (path) {
36035
36444
  this.python3Path = path;
36036
36445
  return path;
@@ -36062,7 +36471,7 @@ var init_voice = __esm({
36062
36471
  return new Promise((resolve32, reject) => {
36063
36472
  const proc = nodeSpawn("sh", ["-c", command], {
36064
36473
  stdio: ["ignore", "pipe", "pipe"],
36065
- cwd: tmpdir6()
36474
+ cwd: tmpdir7()
36066
36475
  });
36067
36476
  let stdout = "";
36068
36477
  let stderr = "";
@@ -36096,7 +36505,7 @@ var init_voice = __esm({
36096
36505
  return false;
36097
36506
  }
36098
36507
  try {
36099
- execSync26(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
36508
+ execSync27(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
36100
36509
  this.mlxInstalled = true;
36101
36510
  return true;
36102
36511
  } catch {
@@ -36120,7 +36529,7 @@ var init_voice = __esm({
36120
36529
  return;
36121
36530
  renderInfo("Installing MLX Audio for voice synthesis (first time setup)...");
36122
36531
  try {
36123
- execSync26(`${py} -m pip install mlx-audio --quiet`, {
36532
+ execSync27(`${py} -m pip install mlx-audio --quiet`, {
36124
36533
  stdio: "pipe",
36125
36534
  timeout: 3e5
36126
36535
  // 5 min — may need to compile
@@ -36128,7 +36537,7 @@ var init_voice = __esm({
36128
36537
  this.mlxInstalled = true;
36129
36538
  } catch (err) {
36130
36539
  try {
36131
- execSync26(`${py} -m pip install mlx-audio --user --quiet`, {
36540
+ execSync27(`${py} -m pip install mlx-audio --user --quiet`, {
36132
36541
  stdio: "pipe",
36133
36542
  timeout: 3e5
36134
36543
  });
@@ -36156,7 +36565,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36156
36565
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
36157
36566
  const mlxVoice = model.mlxVoice ?? "af_heart";
36158
36567
  const mlxLangCode = model.mlxLangCode ?? "a";
36159
- const wavPath = join41(tmpdir6(), `oa-mlx-${Date.now()}.wav`);
36568
+ const wavPath = join42(tmpdir7(), `oa-mlx-${Date.now()}.wav`);
36160
36569
  const pyScript = [
36161
36570
  "import sys, json",
36162
36571
  "from mlx_audio.tts import generate as tts_gen",
@@ -36164,20 +36573,20 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36164
36573
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
36165
36574
  ].join("; ");
36166
36575
  try {
36167
- execSync26(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
36576
+ execSync27(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir7() });
36168
36577
  } catch (err) {
36169
36578
  try {
36170
36579
  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() });
36580
+ 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
36581
  } catch (err2) {
36173
36582
  return;
36174
36583
  }
36175
36584
  }
36176
- if (!existsSync33(wavPath))
36585
+ if (!existsSync34(wavPath))
36177
36586
  return;
36178
36587
  if (volume !== 1) {
36179
36588
  try {
36180
- const wavData = readFileSync23(wavPath);
36589
+ const wavData = readFileSync24(wavPath);
36181
36590
  if (wavData.length > 44) {
36182
36591
  const header = wavData.subarray(0, 44);
36183
36592
  const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
@@ -36192,7 +36601,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36192
36601
  }
36193
36602
  if (this.onPCMOutput) {
36194
36603
  try {
36195
- const wavData = readFileSync23(wavPath);
36604
+ const wavData = readFileSync24(wavPath);
36196
36605
  if (wavData.length > 44) {
36197
36606
  const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
36198
36607
  const sampleRate = wavData.readUInt32LE(24);
@@ -36203,7 +36612,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36203
36612
  }
36204
36613
  await this.playWav(wavPath);
36205
36614
  try {
36206
- unlinkSync5(wavPath);
36615
+ unlinkSync6(wavPath);
36207
36616
  } catch {
36208
36617
  }
36209
36618
  }
@@ -36224,7 +36633,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36224
36633
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
36225
36634
  const mlxVoice = model.mlxVoice ?? "af_heart";
36226
36635
  const mlxLangCode = model.mlxLangCode ?? "a";
36227
- const wavPath = join41(tmpdir6(), `oa-mlx-buf-${Date.now()}.wav`);
36636
+ const wavPath = join42(tmpdir7(), `oa-mlx-buf-${Date.now()}.wav`);
36228
36637
  const pyScript = [
36229
36638
  "import sys, json",
36230
36639
  "from mlx_audio.tts import generate as tts_gen",
@@ -36232,20 +36641,20 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36232
36641
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
36233
36642
  ].join("; ");
36234
36643
  try {
36235
- execSync26(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
36644
+ execSync27(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir7() });
36236
36645
  } catch {
36237
36646
  try {
36238
36647
  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() });
36648
+ 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
36649
  } catch {
36241
36650
  return null;
36242
36651
  }
36243
36652
  }
36244
- if (!existsSync33(wavPath))
36653
+ if (!existsSync34(wavPath))
36245
36654
  return null;
36246
36655
  try {
36247
- const data = readFileSync23(wavPath);
36248
- unlinkSync5(wavPath);
36656
+ const data = readFileSync24(wavPath);
36657
+ unlinkSync6(wavPath);
36249
36658
  return data;
36250
36659
  } catch {
36251
36660
  return null;
@@ -36267,7 +36676,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36267
36676
  }
36268
36677
  const venvDir = luxttsVenvDir();
36269
36678
  const venvPy = luxttsVenvPy();
36270
- if (existsSync33(venvPy)) {
36679
+ if (existsSync34(venvPy)) {
36271
36680
  try {
36272
36681
  await this.asyncShell(`${venvPy} -c "import sys; sys.path.insert(0, '${luxttsRepoDir()}'); from zipvoice.luxvoice import LuxTTS; print('ok')"`, 3e4);
36273
36682
  let hasCudaSys = false;
@@ -36297,7 +36706,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36297
36706
  }
36298
36707
  }
36299
36708
  renderInfo("Setting up LuxTTS voice cloning (first-time setup, this takes several minutes)...");
36300
- if (!existsSync33(venvDir)) {
36709
+ if (!existsSync34(venvDir)) {
36301
36710
  renderInfo(" Creating Python virtual environment...");
36302
36711
  try {
36303
36712
  await this.asyncShell(`${py} -m venv ${JSON.stringify(venvDir)}`, 6e4);
@@ -36335,10 +36744,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36335
36744
  }
36336
36745
  }
36337
36746
  const repoDir = luxttsRepoDir();
36338
- if (!existsSync33(join41(repoDir, "zipvoice", "luxvoice.py"))) {
36747
+ if (!existsSync34(join42(repoDir, "zipvoice", "luxvoice.py"))) {
36339
36748
  renderInfo(" Cloning LuxTTS repository...");
36340
36749
  try {
36341
- if (existsSync33(repoDir)) {
36750
+ if (existsSync34(repoDir)) {
36342
36751
  await this.asyncShell(`rm -rf ${JSON.stringify(repoDir)}`, 3e4);
36343
36752
  }
36344
36753
  await this.asyncShell(`git clone --depth 1 https://github.com/ysharma3501/LuxTTS.git ${JSON.stringify(repoDir)}`, 12e4);
@@ -36378,14 +36787,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36378
36787
  }
36379
36788
  /** Auto-detect an existing clone reference in the refs directory */
36380
36789
  autoDetectCloneRef() {
36381
- if (this.luxttsCloneRef && existsSync33(this.luxttsCloneRef))
36790
+ if (this.luxttsCloneRef && existsSync34(this.luxttsCloneRef))
36382
36791
  return;
36383
36792
  const refsDir = luxttsCloneRefsDir();
36384
- if (!existsSync33(refsDir))
36793
+ if (!existsSync34(refsDir))
36385
36794
  return;
36386
36795
  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)) {
36796
+ const p = join42(refsDir, name);
36797
+ if (existsSync34(p)) {
36389
36798
  this.luxttsCloneRef = p;
36390
36799
  return;
36391
36800
  }
@@ -36493,13 +36902,13 @@ if __name__ == '__main__':
36493
36902
  if (this._luxttsDaemon && !this._luxttsDaemon.killed)
36494
36903
  return true;
36495
36904
  const venvPy = luxttsVenvPy();
36496
- if (!existsSync33(venvPy))
36905
+ if (!existsSync34(venvPy))
36497
36906
  return false;
36498
36907
  return new Promise((resolve32) => {
36499
36908
  const env = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
36500
36909
  const daemon = nodeSpawn(venvPy, [luxttsInferScript()], {
36501
36910
  stdio: ["pipe", "pipe", "pipe"],
36502
- cwd: tmpdir6(),
36911
+ cwd: tmpdir7(),
36503
36912
  env
36504
36913
  });
36505
36914
  this._luxttsDaemon = daemon;
@@ -36572,7 +36981,7 @@ if __name__ == '__main__':
36572
36981
  * Volume is applied via WAV sample scaling.
36573
36982
  */
36574
36983
  async synthesizeWithLuxtts(text, volume = 1, pitchFactor = 1, speedFactor = 1) {
36575
- if (!this.luxttsCloneRef || !existsSync33(this.luxttsCloneRef)) {
36984
+ if (!this.luxttsCloneRef || !existsSync34(this.luxttsCloneRef)) {
36576
36985
  return;
36577
36986
  }
36578
36987
  const cleaned = text.replace(/\*/g, "").trim();
@@ -36581,7 +36990,7 @@ if __name__ == '__main__':
36581
36990
  const ready = await this.ensureLuxttsDaemon();
36582
36991
  if (!ready)
36583
36992
  return;
36584
- const wavPath = join41(tmpdir6(), `oa-luxtts-${Date.now()}.wav`);
36993
+ const wavPath = join42(tmpdir7(), `oa-luxtts-${Date.now()}.wav`);
36585
36994
  try {
36586
36995
  await this.luxttsRequest({
36587
36996
  action: "synthesize",
@@ -36593,11 +37002,11 @@ if __name__ == '__main__':
36593
37002
  } catch {
36594
37003
  return;
36595
37004
  }
36596
- if (!existsSync33(wavPath))
37005
+ if (!existsSync34(wavPath))
36597
37006
  return;
36598
37007
  if (volume !== 1) {
36599
37008
  try {
36600
- const wavData = readFileSync23(wavPath);
37009
+ const wavData = readFileSync24(wavPath);
36601
37010
  if (wavData.length > 44) {
36602
37011
  const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
36603
37012
  for (let i = 0; i < samples.length; i++) {
@@ -36612,7 +37021,7 @@ if __name__ == '__main__':
36612
37021
  }
36613
37022
  if (pitchFactor !== 1) {
36614
37023
  try {
36615
- const wavData = readFileSync23(wavPath);
37024
+ const wavData = readFileSync24(wavPath);
36616
37025
  if (wavData.length > 44) {
36617
37026
  const int16 = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
36618
37027
  const float32 = new Float32Array(int16.length);
@@ -36627,7 +37036,7 @@ if __name__ == '__main__':
36627
37036
  }
36628
37037
  if (this.onPCMOutput) {
36629
37038
  try {
36630
- const wavData = readFileSync23(wavPath);
37039
+ const wavData = readFileSync24(wavPath);
36631
37040
  if (wavData.length > 44) {
36632
37041
  const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
36633
37042
  const sampleRate = wavData.readUInt32LE(24);
@@ -36638,7 +37047,7 @@ if __name__ == '__main__':
36638
37047
  }
36639
37048
  await this.playWav(wavPath);
36640
37049
  try {
36641
- unlinkSync5(wavPath);
37050
+ unlinkSync6(wavPath);
36642
37051
  } catch {
36643
37052
  }
36644
37053
  }
@@ -36647,7 +37056,7 @@ if __name__ == '__main__':
36647
37056
  * Used for Telegram voice messages and WebSocket streaming.
36648
37057
  */
36649
37058
  async synthesizeLuxttsToBuffer(text) {
36650
- if (!this.luxttsCloneRef || !existsSync33(this.luxttsCloneRef))
37059
+ if (!this.luxttsCloneRef || !existsSync34(this.luxttsCloneRef))
36651
37060
  return null;
36652
37061
  const cleaned = text.replace(/\*/g, "").trim();
36653
37062
  if (!cleaned)
@@ -36655,7 +37064,7 @@ if __name__ == '__main__':
36655
37064
  const ready = await this.ensureLuxttsDaemon();
36656
37065
  if (!ready)
36657
37066
  return null;
36658
- const wavPath = join41(tmpdir6(), `oa-luxtts-buf-${Date.now()}.wav`);
37067
+ const wavPath = join42(tmpdir7(), `oa-luxtts-buf-${Date.now()}.wav`);
36659
37068
  try {
36660
37069
  await this.luxttsRequest({
36661
37070
  action: "synthesize",
@@ -36667,11 +37076,11 @@ if __name__ == '__main__':
36667
37076
  } catch {
36668
37077
  return null;
36669
37078
  }
36670
- if (!existsSync33(wavPath))
37079
+ if (!existsSync34(wavPath))
36671
37080
  return null;
36672
37081
  try {
36673
- const data = readFileSync23(wavPath);
36674
- unlinkSync5(wavPath);
37082
+ const data = readFileSync24(wavPath);
37083
+ unlinkSync6(wavPath);
36675
37084
  return data;
36676
37085
  } catch {
36677
37086
  return null;
@@ -36685,14 +37094,14 @@ if __name__ == '__main__':
36685
37094
  return;
36686
37095
  const arch = process.arch;
36687
37096
  mkdirSync13(voiceDir(), { recursive: true });
36688
- const pkgPath = join41(voiceDir(), "package.json");
37097
+ const pkgPath = join42(voiceDir(), "package.json");
36689
37098
  const expectedDeps = {
36690
37099
  "onnxruntime-node": "^1.21.0",
36691
37100
  "phonemizer": "^1.2.1"
36692
37101
  };
36693
- if (existsSync33(pkgPath)) {
37102
+ if (existsSync34(pkgPath)) {
36694
37103
  try {
36695
- const existing = JSON.parse(readFileSync23(pkgPath, "utf8"));
37104
+ const existing = JSON.parse(readFileSync24(pkgPath, "utf8"));
36696
37105
  if (!existing.dependencies?.["phonemizer"]) {
36697
37106
  existing.dependencies = { ...existing.dependencies, ...expectedDeps };
36698
37107
  writeFileSync13(pkgPath, JSON.stringify(existing, null, 2));
@@ -36700,25 +37109,25 @@ if __name__ == '__main__':
36700
37109
  } catch {
36701
37110
  }
36702
37111
  }
36703
- if (!existsSync33(pkgPath)) {
37112
+ if (!existsSync34(pkgPath)) {
36704
37113
  writeFileSync13(pkgPath, JSON.stringify({
36705
37114
  name: "open-agents-voice",
36706
37115
  private: true,
36707
37116
  dependencies: expectedDeps
36708
37117
  }, null, 2));
36709
37118
  }
36710
- const voiceRequire = createRequire(join41(voiceDir(), "index.js"));
37119
+ const voiceRequire = createRequire(join42(voiceDir(), "index.js"));
36711
37120
  const probeOnnx = () => {
36712
37121
  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") } });
37122
+ 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
37123
  const output = result.toString().trim();
36715
37124
  return output === "OK";
36716
37125
  } catch {
36717
37126
  return false;
36718
37127
  }
36719
37128
  };
36720
- const onnxNodeModules = join41(voiceDir(), "node_modules", "onnxruntime-node");
36721
- const onnxInstalled = existsSync33(onnxNodeModules);
37129
+ const onnxNodeModules = join42(voiceDir(), "node_modules", "onnxruntime-node");
37130
+ const onnxInstalled = existsSync34(onnxNodeModules);
36722
37131
  if (onnxInstalled && !probeOnnx()) {
36723
37132
  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
37133
  }
@@ -36727,7 +37136,7 @@ if __name__ == '__main__':
36727
37136
  } catch {
36728
37137
  renderInfo("Installing ONNX runtime for voice synthesis...");
36729
37138
  try {
36730
- execSync26("npm install --no-audit --no-fund", {
37139
+ execSync27("npm install --no-audit --no-fund", {
36731
37140
  cwd: voiceDir(),
36732
37141
  stdio: "pipe",
36733
37142
  timeout: 12e4
@@ -36752,7 +37161,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
36752
37161
  } catch {
36753
37162
  renderInfo("Installing phonemizer for voice synthesis...");
36754
37163
  try {
36755
- execSync26("npm install --no-audit --no-fund", {
37164
+ execSync27("npm install --no-audit --no-fund", {
36756
37165
  cwd: voiceDir(),
36757
37166
  stdio: "pipe",
36758
37167
  timeout: 12e4
@@ -36776,10 +37185,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
36776
37185
  const dir = modelDir(id);
36777
37186
  const onnxPath = modelOnnxPath(id);
36778
37187
  const configPath = modelConfigPath(id);
36779
- if (existsSync33(onnxPath) && existsSync33(configPath))
37188
+ if (existsSync34(onnxPath) && existsSync34(configPath))
36780
37189
  return;
36781
37190
  mkdirSync13(dir, { recursive: true });
36782
- if (!existsSync33(configPath)) {
37191
+ if (!existsSync34(configPath)) {
36783
37192
  renderInfo(`Downloading ${model.label} voice config...`);
36784
37193
  const configResp = await fetch(model.configUrl);
36785
37194
  if (!configResp.ok)
@@ -36787,7 +37196,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
36787
37196
  const configText = await configResp.text();
36788
37197
  writeFileSync13(configPath, configText);
36789
37198
  }
36790
- if (!existsSync33(onnxPath)) {
37199
+ if (!existsSync34(onnxPath)) {
36791
37200
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
36792
37201
  const onnxResp = await fetch(model.onnxUrl);
36793
37202
  if (!onnxResp.ok)
@@ -36824,10 +37233,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
36824
37233
  throw new Error("ONNX runtime not loaded");
36825
37234
  const onnxPath = modelOnnxPath(this.modelId);
36826
37235
  const configPath = modelConfigPath(this.modelId);
36827
- if (!existsSync33(onnxPath) || !existsSync33(configPath)) {
37236
+ if (!existsSync34(onnxPath) || !existsSync34(configPath)) {
36828
37237
  throw new Error(`Model files not found for ${this.modelId}`);
36829
37238
  }
36830
- this.config = JSON.parse(readFileSync23(configPath, "utf8"));
37239
+ this.config = JSON.parse(readFileSync24(configPath, "utf8"));
36831
37240
  this.session = await this.ort.InferenceSession.create(onnxPath, {
36832
37241
  executionProviders: ["cpu"],
36833
37242
  graphOptimizationLevel: "all"
@@ -37498,6 +37907,33 @@ async function handleSlashCommand(input, ctx) {
37498
37907
  }
37499
37908
  return "handled";
37500
37909
  }
37910
+ case "neovim":
37911
+ case "nvim":
37912
+ case "vim": {
37913
+ if (isNeovimActive()) {
37914
+ stopNeovimMode();
37915
+ renderInfo("Neovim mode stopped.");
37916
+ } else {
37917
+ const contentRows = ctx.availableContentRows?.() ?? Math.max(5, (process.stdout.rows ?? 24) - 6);
37918
+ const cols = process.stdout.columns ?? 80;
37919
+ const err = await startNeovimMode({
37920
+ cwd: ctx.repoRoot,
37921
+ contentRows,
37922
+ cols,
37923
+ rl: ctx.rl,
37924
+ initialFile: arg || void 0,
37925
+ onExit: () => {
37926
+ renderInfo("Neovim mode exited.");
37927
+ }
37928
+ });
37929
+ if (err) {
37930
+ renderError(err);
37931
+ } else {
37932
+ renderInfo("Neovim mode started. Ctrl+N toggles focus between editor and input.");
37933
+ }
37934
+ }
37935
+ return "handled";
37936
+ }
37501
37937
  case "dream": {
37502
37938
  if (arg === "stop" || arg === "wake") {
37503
37939
  if (ctx.isDreaming?.()) {
@@ -39020,8 +39456,8 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
39020
39456
  if (models.length > 0) {
39021
39457
  try {
39022
39458
  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");
39459
+ const { join: join56, dirname: dirname20 } = await import("node:path");
39460
+ const cachePath = join56(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
39025
39461
  mkdirSync21(dirname20(cachePath), { recursive: true });
39026
39462
  writeFileSync19(cachePath, JSON.stringify({
39027
39463
  peerId,
@@ -39072,7 +39508,7 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
39072
39508
  }
39073
39509
  }
39074
39510
  async function handleParallel(arg, ctx) {
39075
- const { execSync: execSync29 } = await import("node:child_process");
39511
+ const { execSync: execSync30 } = await import("node:child_process");
39076
39512
  const baseUrl = ctx.config.backendUrl || "http://localhost:11434";
39077
39513
  const isRemote = ctx.config.backendType === "nexus";
39078
39514
  if (isRemote) {
@@ -39096,7 +39532,7 @@ async function handleParallel(arg, ctx) {
39096
39532
  }
39097
39533
  let systemdVal = "";
39098
39534
  try {
39099
- const out = execSync29("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
39535
+ const out = execSync30("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
39100
39536
  const match = out.match(/OLLAMA_NUM_PARALLEL=(\d+)/);
39101
39537
  if (match)
39102
39538
  systemdVal = match[1];
@@ -39125,7 +39561,7 @@ async function handleParallel(arg, ctx) {
39125
39561
  }
39126
39562
  const isSystemd = (() => {
39127
39563
  try {
39128
- const out = execSync29("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
39564
+ const out = execSync30("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
39129
39565
  return out === "active" || out === "inactive";
39130
39566
  } catch {
39131
39567
  return false;
@@ -39139,10 +39575,10 @@ async function handleParallel(arg, ctx) {
39139
39575
  const overrideContent = `[Service]
39140
39576
  Environment="OLLAMA_NUM_PARALLEL=${n}"
39141
39577
  `;
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" });
39578
+ execSync30(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
39579
+ execSync30(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
39580
+ execSync30("sudo systemctl daemon-reload", { stdio: "pipe" });
39581
+ execSync30("sudo systemctl restart ollama.service", { stdio: "pipe" });
39146
39582
  let ready = false;
39147
39583
  for (let i = 0; i < 30 && !ready; i++) {
39148
39584
  await new Promise((r) => setTimeout(r, 500));
@@ -39169,7 +39605,7 @@ Environment="OLLAMA_NUM_PARALLEL=${n}"
39169
39605
  renderInfo(`Setting OLLAMA_NUM_PARALLEL=${n}...`);
39170
39606
  try {
39171
39607
  try {
39172
- execSync29("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
39608
+ execSync30("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
39173
39609
  } catch {
39174
39610
  }
39175
39611
  await new Promise((r) => setTimeout(r, 1e3));
@@ -39222,17 +39658,17 @@ async function handleUpdate(subcommand, ctx) {
39222
39658
  try {
39223
39659
  const { createRequire: createRequire4 } = await import("node:module");
39224
39660
  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");
39661
+ const { dirname: dirname20, join: join56 } = await import("node:path");
39662
+ const { existsSync: existsSync44 } = await import("node:fs");
39227
39663
  const req = createRequire4(import.meta.url);
39228
39664
  const thisDir = dirname20(fileURLToPath14(import.meta.url));
39229
39665
  const candidates = [
39230
- join55(thisDir, "..", "package.json"),
39231
- join55(thisDir, "..", "..", "package.json"),
39232
- join55(thisDir, "..", "..", "..", "package.json")
39666
+ join56(thisDir, "..", "package.json"),
39667
+ join56(thisDir, "..", "..", "package.json"),
39668
+ join56(thisDir, "..", "..", "..", "package.json")
39233
39669
  ];
39234
39670
  for (const pkgPath of candidates) {
39235
- if (existsSync43(pkgPath)) {
39671
+ if (existsSync44(pkgPath)) {
39236
39672
  const pkg = req(pkgPath);
39237
39673
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
39238
39674
  currentVersion = pkg.version ?? "0.0.0";
@@ -39563,8 +39999,8 @@ function getLocalSystemMetrics() {
39563
39999
  vramUtil: 0
39564
40000
  };
39565
40001
  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 });
40002
+ const { execSync: execSync30 } = __require("node:child_process");
40003
+ 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
40004
  const line = smiOut.trim().split("\n")[0];
39569
40005
  if (line) {
39570
40006
  const parts = line.split(",").map((s) => s.trim());
@@ -39790,14 +40226,15 @@ var init_commands = __esm({
39790
40226
  init_dist();
39791
40227
  init_tui_select();
39792
40228
  init_drop_panel();
40229
+ init_neovim_mode();
39793
40230
  DASH_INTERNAL = /* @__PURE__ */ new Set(["system_metrics", "__list_capabilities"]);
39794
40231
  }
39795
40232
  });
39796
40233
 
39797
40234
  // 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";
40235
+ import { existsSync as existsSync35, readFileSync as readFileSync25, readdirSync as readdirSync10 } from "node:fs";
40236
+ import { join as join43, basename as basename10 } from "node:path";
40237
+ import { execSync as execSync28 } from "node:child_process";
39801
40238
  import { homedir as homedir12, platform as platform3, release } from "node:os";
39802
40239
  function getModelTier(modelName) {
39803
40240
  const m = modelName.toLowerCase();
@@ -39831,10 +40268,10 @@ function loadProjectMap(repoRoot) {
39831
40268
  if (!hasOaDirectory(repoRoot)) {
39832
40269
  initOaDirectory(repoRoot);
39833
40270
  }
39834
- const mapPath = join42(repoRoot, OA_DIR, "context", "project-map.md");
39835
- if (existsSync34(mapPath)) {
40271
+ const mapPath = join43(repoRoot, OA_DIR, "context", "project-map.md");
40272
+ if (existsSync35(mapPath)) {
39836
40273
  try {
39837
- const content = readFileSync24(mapPath, "utf-8");
40274
+ const content = readFileSync25(mapPath, "utf-8");
39838
40275
  return content;
39839
40276
  } catch {
39840
40277
  }
@@ -39843,19 +40280,19 @@ function loadProjectMap(repoRoot) {
39843
40280
  }
39844
40281
  function getGitInfo(repoRoot) {
39845
40282
  try {
39846
- execSync27("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
40283
+ execSync28("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
39847
40284
  } catch {
39848
40285
  return "";
39849
40286
  }
39850
40287
  const lines = [];
39851
40288
  try {
39852
- const branch = execSync27("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
40289
+ const branch = execSync28("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
39853
40290
  if (branch)
39854
40291
  lines.push(`Branch: ${branch}`);
39855
40292
  } catch {
39856
40293
  }
39857
40294
  try {
39858
- const status = execSync27("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
40295
+ const status = execSync28("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
39859
40296
  if (status) {
39860
40297
  const changed = status.split("\n").length;
39861
40298
  lines.push(`Working tree: ${changed} changed file(s)`);
@@ -39865,7 +40302,7 @@ function getGitInfo(repoRoot) {
39865
40302
  } catch {
39866
40303
  }
39867
40304
  try {
39868
- const log = execSync27("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
40305
+ const log = execSync28("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
39869
40306
  if (log)
39870
40307
  lines.push(`Recent commits:
39871
40308
  ${log}`);
@@ -39875,31 +40312,31 @@ ${log}`);
39875
40312
  }
39876
40313
  function loadMemoryContext(repoRoot) {
39877
40314
  const sections = [];
39878
- const oaMemDir = join42(repoRoot, OA_DIR, "memory");
40315
+ const oaMemDir = join43(repoRoot, OA_DIR, "memory");
39879
40316
  const oaEntries = loadMemoryDir(oaMemDir, "project");
39880
40317
  if (oaEntries)
39881
40318
  sections.push(oaEntries);
39882
- const legacyMemDir = join42(repoRoot, ".open-agents", "memory");
39883
- if (legacyMemDir !== oaMemDir && existsSync34(legacyMemDir)) {
40319
+ const legacyMemDir = join43(repoRoot, ".open-agents", "memory");
40320
+ if (legacyMemDir !== oaMemDir && existsSync35(legacyMemDir)) {
39884
40321
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
39885
40322
  if (legacyEntries)
39886
40323
  sections.push(legacyEntries);
39887
40324
  }
39888
- const globalMemDir = join42(homedir12(), ".open-agents", "memory");
40325
+ const globalMemDir = join43(homedir12(), ".open-agents", "memory");
39889
40326
  const globalEntries = loadMemoryDir(globalMemDir, "global");
39890
40327
  if (globalEntries)
39891
40328
  sections.push(globalEntries);
39892
40329
  return sections.join("\n\n");
39893
40330
  }
39894
40331
  function loadMemoryDir(memDir, scope) {
39895
- if (!existsSync34(memDir))
40332
+ if (!existsSync35(memDir))
39896
40333
  return "";
39897
40334
  const lines = [];
39898
40335
  try {
39899
40336
  const files = readdirSync10(memDir).filter((f) => f.endsWith(".json"));
39900
40337
  for (const file of files.slice(0, 10)) {
39901
40338
  try {
39902
- const raw = readFileSync24(join42(memDir, file), "utf-8");
40339
+ const raw = readFileSync25(join43(memDir, file), "utf-8");
39903
40340
  const entries = JSON.parse(raw);
39904
40341
  const topic = basename10(file, ".json");
39905
40342
  const keys = Object.keys(entries);
@@ -40640,7 +41077,7 @@ var init_dist7 = __esm({
40640
41077
 
40641
41078
  // packages/cli/dist/tui/carousel.js
40642
41079
  function fg(code, text) {
40643
- return isTTY5 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
41080
+ return isTTY6 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
40644
41081
  }
40645
41082
  function displayWidth(str) {
40646
41083
  let w = 0;
@@ -40678,11 +41115,11 @@ function createRow(phraseIndices, speed, direction, bank) {
40678
41115
  const phrases = phraseIndices.map((i) => bank[i % bank.length]);
40679
41116
  return { phrases, offset: 0, speed, direction, renderedPlain: "" };
40680
41117
  }
40681
- var isTTY5, PHRASES, Carousel;
41118
+ var isTTY6, PHRASES, Carousel;
40682
41119
  var init_carousel = __esm({
40683
41120
  "packages/cli/dist/tui/carousel.js"() {
40684
41121
  "use strict";
40685
- isTTY5 = process.stdout.isTTY ?? false;
41122
+ isTTY6 = process.stdout.isTTY ?? false;
40686
41123
  PHRASES = [
40687
41124
  // English
40688
41125
  { text: "freedom of information", color: 39 },
@@ -40791,7 +41228,7 @@ var init_carousel = __esm({
40791
41228
  * Sets scroll region to row 5+ for all content/readline.
40792
41229
  */
40793
41230
  start() {
40794
- if (!isTTY5)
41231
+ if (!isTTY6)
40795
41232
  return 0;
40796
41233
  this.started = true;
40797
41234
  const termRows = process.stdout.rows ?? 24;
@@ -40823,7 +41260,7 @@ var init_carousel = __esm({
40823
41260
  * Row 4 is left blank as a separator.
40824
41261
  */
40825
41262
  renderFrame() {
40826
- if (!isTTY5)
41263
+ if (!isTTY6)
40827
41264
  return;
40828
41265
  let buf = "\x1B7";
40829
41266
  buf += "\x1B[?7l";
@@ -40903,7 +41340,7 @@ var init_carousel = __esm({
40903
41340
  process.stdout.removeListener("resize", this.resizeHandler);
40904
41341
  this.resizeHandler = null;
40905
41342
  }
40906
- if (!isTTY5 || !this.started)
41343
+ if (!isTTY6 || !this.started)
40907
41344
  return;
40908
41345
  let buf = "\x1B7";
40909
41346
  for (let i = 0; i < this.reservedRows; i++) {
@@ -40922,22 +41359,22 @@ var init_carousel = __esm({
40922
41359
  });
40923
41360
 
40924
41361
  // 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";
41362
+ import { existsSync as existsSync36, readFileSync as readFileSync26, writeFileSync as writeFileSync14, mkdirSync as mkdirSync14, readdirSync as readdirSync11 } from "node:fs";
41363
+ import { join as join44, basename as basename11 } from "node:path";
40927
41364
  function loadToolProfile(repoRoot) {
40928
- const filePath = join43(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
41365
+ const filePath = join44(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
40929
41366
  try {
40930
- if (!existsSync35(filePath))
41367
+ if (!existsSync36(filePath))
40931
41368
  return null;
40932
- return JSON.parse(readFileSync25(filePath, "utf-8"));
41369
+ return JSON.parse(readFileSync26(filePath, "utf-8"));
40933
41370
  } catch {
40934
41371
  return null;
40935
41372
  }
40936
41373
  }
40937
41374
  function saveToolProfile(repoRoot, profile) {
40938
- const contextDir = join43(repoRoot, OA_DIR, "context");
41375
+ const contextDir = join44(repoRoot, OA_DIR, "context");
40939
41376
  mkdirSync14(contextDir, { recursive: true });
40940
- writeFileSync14(join43(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
41377
+ writeFileSync14(join44(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
40941
41378
  }
40942
41379
  function categorizeToolCall(toolName) {
40943
41380
  for (const cat of TOOL_CATEGORIES) {
@@ -40995,25 +41432,25 @@ function weightedColor(profile) {
40995
41432
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
40996
41433
  }
40997
41434
  function loadCachedDescriptors(repoRoot) {
40998
- const filePath = join43(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
41435
+ const filePath = join44(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
40999
41436
  try {
41000
- if (!existsSync35(filePath))
41437
+ if (!existsSync36(filePath))
41001
41438
  return null;
41002
- const cached = JSON.parse(readFileSync25(filePath, "utf-8"));
41439
+ const cached = JSON.parse(readFileSync26(filePath, "utf-8"));
41003
41440
  return cached.phrases.length > 0 ? cached.phrases : null;
41004
41441
  } catch {
41005
41442
  return null;
41006
41443
  }
41007
41444
  }
41008
41445
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
41009
- const contextDir = join43(repoRoot, OA_DIR, "context");
41446
+ const contextDir = join44(repoRoot, OA_DIR, "context");
41010
41447
  mkdirSync14(contextDir, { recursive: true });
41011
41448
  const cached = {
41012
41449
  phrases,
41013
41450
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
41014
41451
  sourceHash
41015
41452
  };
41016
- writeFileSync14(join43(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
41453
+ writeFileSync14(join44(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
41017
41454
  }
41018
41455
  function generateDescriptors(repoRoot) {
41019
41456
  const profile = loadToolProfile(repoRoot);
@@ -41061,11 +41498,11 @@ function generateDescriptors(repoRoot) {
41061
41498
  return phrases;
41062
41499
  }
41063
41500
  function extractFromPackageJson(repoRoot, tags) {
41064
- const pkgPath = join43(repoRoot, "package.json");
41501
+ const pkgPath = join44(repoRoot, "package.json");
41065
41502
  try {
41066
- if (!existsSync35(pkgPath))
41503
+ if (!existsSync36(pkgPath))
41067
41504
  return;
41068
- const pkg = JSON.parse(readFileSync25(pkgPath, "utf-8"));
41505
+ const pkg = JSON.parse(readFileSync26(pkgPath, "utf-8"));
41069
41506
  if (pkg.name && typeof pkg.name === "string") {
41070
41507
  const parts = pkg.name.replace(/^@/, "").split("/");
41071
41508
  for (const p of parts)
@@ -41109,7 +41546,7 @@ function extractFromManifests(repoRoot, tags) {
41109
41546
  { file: ".github/workflows", tag: "ci/cd" }
41110
41547
  ];
41111
41548
  for (const check of manifestChecks) {
41112
- if (existsSync35(join43(repoRoot, check.file))) {
41549
+ if (existsSync36(join44(repoRoot, check.file))) {
41113
41550
  tags.push(check.tag);
41114
41551
  }
41115
41552
  }
@@ -41131,16 +41568,16 @@ function extractFromSessions(repoRoot, tags) {
41131
41568
  }
41132
41569
  }
41133
41570
  function extractFromMemory(repoRoot, tags) {
41134
- const memoryDir = join43(repoRoot, OA_DIR, "memory");
41571
+ const memoryDir = join44(repoRoot, OA_DIR, "memory");
41135
41572
  try {
41136
- if (!existsSync35(memoryDir))
41573
+ if (!existsSync36(memoryDir))
41137
41574
  return;
41138
41575
  const files = readdirSync11(memoryDir).filter((f) => f.endsWith(".json"));
41139
41576
  for (const file of files) {
41140
41577
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
41141
41578
  tags.push(topic);
41142
41579
  try {
41143
- const data = JSON.parse(readFileSync25(join43(memoryDir, file), "utf-8"));
41580
+ const data = JSON.parse(readFileSync26(join44(memoryDir, file), "utf-8"));
41144
41581
  if (data && typeof data === "object") {
41145
41582
  const keys = Object.keys(data).slice(0, 3);
41146
41583
  for (const key of keys) {
@@ -41276,25 +41713,25 @@ var init_carousel_descriptors = __esm({
41276
41713
 
41277
41714
  // packages/cli/dist/tui/stream-renderer.js
41278
41715
  function fg2563(code, text) {
41279
- return isTTY6 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
41716
+ return isTTY7 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
41280
41717
  }
41281
41718
  function dimText(text) {
41282
- return isTTY6 ? `\x1B[2m${text}\x1B[0m` : text;
41719
+ return isTTY7 ? `\x1B[2m${text}\x1B[0m` : text;
41283
41720
  }
41284
41721
  function italicText(text) {
41285
- return isTTY6 ? `\x1B[3m${text}\x1B[0m` : text;
41722
+ return isTTY7 ? `\x1B[3m${text}\x1B[0m` : text;
41286
41723
  }
41287
41724
  function dimItalic(text) {
41288
- return isTTY6 ? `\x1B[2;3m${text}\x1B[0m` : text;
41725
+ return isTTY7 ? `\x1B[2;3m${text}\x1B[0m` : text;
41289
41726
  }
41290
41727
  function boldText(text) {
41291
- return isTTY6 ? `\x1B[1m${text}\x1B[0m` : text;
41728
+ return isTTY7 ? `\x1B[1m${text}\x1B[0m` : text;
41292
41729
  }
41293
- var isTTY6, PASTEL, StreamRenderer;
41730
+ var isTTY7, PASTEL, StreamRenderer;
41294
41731
  var init_stream_renderer = __esm({
41295
41732
  "packages/cli/dist/tui/stream-renderer.js"() {
41296
41733
  "use strict";
41297
- isTTY6 = process.stdout.isTTY ?? false;
41734
+ isTTY7 = process.stdout.isTTY ?? false;
41298
41735
  PASTEL = {
41299
41736
  key: 222,
41300
41737
  // light gold — JSON keys
@@ -41762,11 +42199,11 @@ var init_stream_renderer = __esm({
41762
42199
  });
41763
42200
 
41764
42201
  // packages/cli/dist/tui/edit-history.js
41765
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync15 } from "node:fs";
41766
- import { join as join44 } from "node:path";
42202
+ import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync15 } from "node:fs";
42203
+ import { join as join45 } from "node:path";
41767
42204
  function createEditHistoryLogger(repoRoot, sessionId) {
41768
- const historyDir = join44(repoRoot, ".oa", "history");
41769
- const logPath = join44(historyDir, "edits.jsonl");
42205
+ const historyDir = join45(repoRoot, ".oa", "history");
42206
+ const logPath = join45(historyDir, "edits.jsonl");
41770
42207
  try {
41771
42208
  mkdirSync15(historyDir, { recursive: true });
41772
42209
  } catch {
@@ -41784,7 +42221,7 @@ function createEditHistoryLogger(repoRoot, sessionId) {
41784
42221
  args: sanitizeArgs(toolName, toolArgs)
41785
42222
  };
41786
42223
  try {
41787
- appendFileSync2(logPath, JSON.stringify(entry) + "\n", "utf-8");
42224
+ appendFileSync3(logPath, JSON.stringify(entry) + "\n", "utf-8");
41788
42225
  } catch {
41789
42226
  }
41790
42227
  }
@@ -41877,17 +42314,17 @@ var init_edit_history = __esm({
41877
42314
  });
41878
42315
 
41879
42316
  // 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";
42317
+ import { readFileSync as readFileSync27, existsSync as existsSync37 } from "node:fs";
42318
+ import { join as join46, dirname as dirname17 } from "node:path";
41882
42319
  import { fileURLToPath as fileURLToPath11 } from "node:url";
41883
42320
  function loadPrompt3(promptPath, vars) {
41884
42321
  let content = cache3.get(promptPath);
41885
42322
  if (content === void 0) {
41886
- const fullPath = join45(PROMPTS_DIR3, promptPath);
41887
- if (!existsSync36(fullPath)) {
42323
+ const fullPath = join46(PROMPTS_DIR3, promptPath);
42324
+ if (!existsSync37(fullPath)) {
41888
42325
  throw new Error(`Prompt file not found: ${fullPath}`);
41889
42326
  }
41890
- content = readFileSync26(fullPath, "utf-8");
42327
+ content = readFileSync27(fullPath, "utf-8");
41891
42328
  cache3.set(promptPath, content);
41892
42329
  }
41893
42330
  if (!vars)
@@ -41900,23 +42337,23 @@ var init_promptLoader3 = __esm({
41900
42337
  "use strict";
41901
42338
  __filename3 = fileURLToPath11(import.meta.url);
41902
42339
  __dirname6 = dirname17(__filename3);
41903
- devPath2 = join45(__dirname6, "..", "..", "prompts");
41904
- publishedPath2 = join45(__dirname6, "..", "prompts");
41905
- PROMPTS_DIR3 = existsSync36(devPath2) ? devPath2 : publishedPath2;
42340
+ devPath2 = join46(__dirname6, "..", "..", "prompts");
42341
+ publishedPath2 = join46(__dirname6, "..", "prompts");
42342
+ PROMPTS_DIR3 = existsSync37(devPath2) ? devPath2 : publishedPath2;
41906
42343
  cache3 = /* @__PURE__ */ new Map();
41907
42344
  }
41908
42345
  });
41909
42346
 
41910
42347
  // 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";
42348
+ import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync15, readFileSync as readFileSync28, existsSync as existsSync38, cpSync, rmSync, readdirSync as readdirSync12 } from "node:fs";
42349
+ import { join as join47, basename as basename12 } from "node:path";
42350
+ import { execSync as execSync29 } from "node:child_process";
41914
42351
  function loadAutoresearchMemory(repoRoot) {
41915
- const memoryPath = join46(repoRoot, ".oa", "memory", "autoresearch.json");
41916
- if (!existsSync37(memoryPath))
42352
+ const memoryPath = join47(repoRoot, ".oa", "memory", "autoresearch.json");
42353
+ if (!existsSync38(memoryPath))
41917
42354
  return "";
41918
42355
  try {
41919
- const raw = readFileSync27(memoryPath, "utf-8");
42356
+ const raw = readFileSync28(memoryPath, "utf-8");
41920
42357
  const data = JSON.parse(raw);
41921
42358
  const sections = [];
41922
42359
  for (const key of AUTORESEARCH_MEMORY_KEYS) {
@@ -42106,12 +42543,12 @@ var init_dream_engine = __esm({
42106
42543
  const content = String(args["content"] ?? "");
42107
42544
  if (!rawPath)
42108
42545
  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);
42546
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join47(this.autoresearchDir, basename12(rawPath)) : join47(this.autoresearchDir, rawPath);
42110
42547
  if (!targetPath.startsWith(this.autoresearchDir)) {
42111
42548
  return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
42112
42549
  }
42113
42550
  try {
42114
- const dir = join46(targetPath, "..");
42551
+ const dir = join47(targetPath, "..");
42115
42552
  mkdirSync16(dir, { recursive: true });
42116
42553
  writeFileSync15(targetPath, content, "utf-8");
42117
42554
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
@@ -42141,15 +42578,15 @@ var init_dream_engine = __esm({
42141
42578
  const rawPath = String(args["path"] ?? "");
42142
42579
  const oldStr = String(args["old_string"] ?? "");
42143
42580
  const newStr = String(args["new_string"] ?? "");
42144
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join46(this.autoresearchDir, basename12(rawPath)) : join46(this.autoresearchDir, rawPath);
42581
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join47(this.autoresearchDir, basename12(rawPath)) : join47(this.autoresearchDir, rawPath);
42145
42582
  if (!targetPath.startsWith(this.autoresearchDir)) {
42146
42583
  return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
42147
42584
  }
42148
42585
  try {
42149
- if (!existsSync37(targetPath)) {
42586
+ if (!existsSync38(targetPath)) {
42150
42587
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
42151
42588
  }
42152
- let content = readFileSync27(targetPath, "utf-8");
42589
+ let content = readFileSync28(targetPath, "utf-8");
42153
42590
  if (!content.includes(oldStr)) {
42154
42591
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
42155
42592
  }
@@ -42195,12 +42632,12 @@ var init_dream_engine = __esm({
42195
42632
  const content = String(args["content"] ?? "");
42196
42633
  if (!rawPath)
42197
42634
  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);
42635
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join47(this.dreamsDir, basename12(rawPath)) : join47(this.dreamsDir, rawPath);
42199
42636
  if (!targetPath.startsWith(this.dreamsDir)) {
42200
42637
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
42201
42638
  }
42202
42639
  try {
42203
- const dir = join46(targetPath, "..");
42640
+ const dir = join47(targetPath, "..");
42204
42641
  mkdirSync16(dir, { recursive: true });
42205
42642
  writeFileSync15(targetPath, content, "utf-8");
42206
42643
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
@@ -42230,15 +42667,15 @@ var init_dream_engine = __esm({
42230
42667
  const rawPath = String(args["path"] ?? "");
42231
42668
  const oldStr = String(args["old_string"] ?? "");
42232
42669
  const newStr = String(args["new_string"] ?? "");
42233
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join46(this.dreamsDir, basename12(rawPath)) : join46(this.dreamsDir, rawPath);
42670
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join47(this.dreamsDir, basename12(rawPath)) : join47(this.dreamsDir, rawPath);
42234
42671
  if (!targetPath.startsWith(this.dreamsDir)) {
42235
42672
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
42236
42673
  }
42237
42674
  try {
42238
- if (!existsSync37(targetPath)) {
42675
+ if (!existsSync38(targetPath)) {
42239
42676
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
42240
42677
  }
42241
- let content = readFileSync27(targetPath, "utf-8");
42678
+ let content = readFileSync28(targetPath, "utf-8");
42242
42679
  if (!content.includes(oldStr)) {
42243
42680
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
42244
42681
  }
@@ -42274,7 +42711,7 @@ var init_dream_engine = __esm({
42274
42711
  }
42275
42712
  }
42276
42713
  try {
42277
- const output = execSync28(cmd, {
42714
+ const output = execSync29(cmd, {
42278
42715
  cwd: this.repoRoot,
42279
42716
  timeout: 3e4,
42280
42717
  encoding: "utf-8",
@@ -42297,7 +42734,7 @@ var init_dream_engine = __esm({
42297
42734
  constructor(config, repoRoot) {
42298
42735
  this.config = config;
42299
42736
  this.repoRoot = repoRoot;
42300
- this.dreamsDir = join46(repoRoot, ".oa", "dreams");
42737
+ this.dreamsDir = join47(repoRoot, ".oa", "dreams");
42301
42738
  this.state = {
42302
42739
  mode: "default",
42303
42740
  active: false,
@@ -42381,7 +42818,7 @@ ${result.summary}`;
42381
42818
  if (mode !== "default" || cycle === totalCycles) {
42382
42819
  renderDreamContraction(cycle);
42383
42820
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
42384
- const summaryPath = join46(this.dreamsDir, `cycle-${cycle}-summary.md`);
42821
+ const summaryPath = join47(this.dreamsDir, `cycle-${cycle}-summary.md`);
42385
42822
  writeFileSync15(summaryPath, cycleSummary, "utf-8");
42386
42823
  }
42387
42824
  if (mode === "lucid" && !this.abortController.signal.aborted) {
@@ -42594,7 +43031,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
42594
43031
  }
42595
43032
  /** Build role-specific tool sets for swarm agents */
42596
43033
  buildSwarmTools(role, _workspace) {
42597
- const autoresearchDir = join46(this.repoRoot, ".oa", "autoresearch");
43034
+ const autoresearchDir = join47(this.repoRoot, ".oa", "autoresearch");
42598
43035
  const taskComplete = this.createSwarmTaskCompleteTool(role);
42599
43036
  switch (role) {
42600
43037
  case "researcher": {
@@ -42958,7 +43395,7 @@ INSTRUCTIONS:
42958
43395
  2. Summarize the key learnings and next steps
42959
43396
 
42960
43397
  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`);
43398
+ const reportPath = join47(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
42962
43399
  const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
42963
43400
 
42964
43401
  **Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -43047,29 +43484,29 @@ ${summaryResult}
43047
43484
  }
43048
43485
  /** Save workspace backup for lucid mode */
43049
43486
  saveVersionCheckpoint(cycle) {
43050
- const checkpointDir = join46(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
43487
+ const checkpointDir = join47(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
43051
43488
  try {
43052
43489
  mkdirSync16(checkpointDir, { recursive: true });
43053
43490
  try {
43054
- const gitStatus = execSync28("git status --porcelain", {
43491
+ const gitStatus = execSync29("git status --porcelain", {
43055
43492
  cwd: this.repoRoot,
43056
43493
  encoding: "utf-8",
43057
43494
  timeout: 1e4
43058
43495
  });
43059
- const gitDiff = execSync28("git diff", {
43496
+ const gitDiff = execSync29("git diff", {
43060
43497
  cwd: this.repoRoot,
43061
43498
  encoding: "utf-8",
43062
43499
  timeout: 1e4
43063
43500
  });
43064
- const gitHash = execSync28("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
43501
+ const gitHash = execSync29("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
43065
43502
  cwd: this.repoRoot,
43066
43503
  encoding: "utf-8",
43067
43504
  timeout: 5e3
43068
43505
  }).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({
43506
+ writeFileSync15(join47(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
43507
+ writeFileSync15(join47(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
43508
+ writeFileSync15(join47(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
43509
+ writeFileSync15(join47(checkpointDir, "checkpoint.json"), JSON.stringify({
43073
43510
  cycle,
43074
43511
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
43075
43512
  gitHash,
@@ -43077,7 +43514,7 @@ ${summaryResult}
43077
43514
  }, null, 2), "utf-8");
43078
43515
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
43079
43516
  } catch {
43080
- writeFileSync15(join46(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
43517
+ writeFileSync15(join47(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
43081
43518
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
43082
43519
  }
43083
43520
  } catch (err) {
@@ -43135,14 +43572,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
43135
43572
  ---
43136
43573
  *Auto-generated by open-agents dream engine*
43137
43574
  `;
43138
- writeFileSync15(join46(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
43575
+ writeFileSync15(join47(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
43139
43576
  } catch {
43140
43577
  }
43141
43578
  }
43142
43579
  /** Save dream state for resume/inspection */
43143
43580
  saveDreamState() {
43144
43581
  try {
43145
- writeFileSync15(join46(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
43582
+ writeFileSync15(join47(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
43146
43583
  } catch {
43147
43584
  }
43148
43585
  }
@@ -43516,8 +43953,8 @@ var init_bless_engine = __esm({
43516
43953
  });
43517
43954
 
43518
43955
  // 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";
43956
+ import { existsSync as existsSync39, readFileSync as readFileSync29, writeFileSync as writeFileSync16, mkdirSync as mkdirSync17, readdirSync as readdirSync13, unlinkSync as unlinkSync7 } from "node:fs";
43957
+ import { join as join48, basename as basename13 } from "node:path";
43521
43958
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
43522
43959
  const competenceReport = competence.length > 0 ? competence.map((c3) => {
43523
43960
  const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
@@ -43630,8 +44067,8 @@ var init_dmn_engine = __esm({
43630
44067
  constructor(config, repoRoot) {
43631
44068
  this.config = config;
43632
44069
  this.repoRoot = repoRoot;
43633
- this.stateDir = join47(repoRoot, ".oa", "dmn");
43634
- this.historyDir = join47(repoRoot, ".oa", "dmn", "cycles");
44070
+ this.stateDir = join48(repoRoot, ".oa", "dmn");
44071
+ this.historyDir = join48(repoRoot, ".oa", "dmn", "cycles");
43635
44072
  mkdirSync17(this.historyDir, { recursive: true });
43636
44073
  this.loadState();
43637
44074
  }
@@ -44221,11 +44658,11 @@ OUTPUT: Call task_complete with JSON:
44221
44658
  async gatherMemoryTopics() {
44222
44659
  const topics = [];
44223
44660
  const dirs = [
44224
- join47(this.repoRoot, ".oa", "memory"),
44225
- join47(this.repoRoot, ".open-agents", "memory")
44661
+ join48(this.repoRoot, ".oa", "memory"),
44662
+ join48(this.repoRoot, ".open-agents", "memory")
44226
44663
  ];
44227
44664
  for (const dir of dirs) {
44228
- if (!existsSync38(dir))
44665
+ if (!existsSync39(dir))
44229
44666
  continue;
44230
44667
  try {
44231
44668
  const files = readdirSync13(dir).filter((f) => f.endsWith(".json"));
@@ -44241,29 +44678,29 @@ OUTPUT: Call task_complete with JSON:
44241
44678
  }
44242
44679
  // ── State persistence ─────────────────────────────────────────────────
44243
44680
  loadState() {
44244
- const path = join47(this.stateDir, "state.json");
44245
- if (existsSync38(path)) {
44681
+ const path = join48(this.stateDir, "state.json");
44682
+ if (existsSync39(path)) {
44246
44683
  try {
44247
- this.state = JSON.parse(readFileSync28(path, "utf-8"));
44684
+ this.state = JSON.parse(readFileSync29(path, "utf-8"));
44248
44685
  } catch {
44249
44686
  }
44250
44687
  }
44251
44688
  }
44252
44689
  saveState() {
44253
44690
  try {
44254
- writeFileSync16(join47(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
44691
+ writeFileSync16(join48(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
44255
44692
  } catch {
44256
44693
  }
44257
44694
  }
44258
44695
  saveCycleResult(result) {
44259
44696
  try {
44260
44697
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
44261
- writeFileSync16(join47(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
44698
+ writeFileSync16(join48(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
44262
44699
  const files = readdirSync13(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
44263
44700
  if (files.length > 50) {
44264
44701
  for (const old of files.slice(0, files.length - 50)) {
44265
44702
  try {
44266
- unlinkSync6(join47(this.historyDir, old));
44703
+ unlinkSync7(join48(this.historyDir, old));
44267
44704
  } catch {
44268
44705
  }
44269
44706
  }
@@ -44276,8 +44713,8 @@ OUTPUT: Call task_complete with JSON:
44276
44713
  });
44277
44714
 
44278
44715
  // 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";
44716
+ import { existsSync as existsSync40, readdirSync as readdirSync14, readFileSync as readFileSync30 } from "node:fs";
44717
+ import { join as join49, basename as basename14 } from "node:path";
44281
44718
  function computeDPrime(signalScores, noiseScores) {
44282
44719
  if (signalScores.length === 0 || noiseScores.length === 0)
44283
44720
  return 0;
@@ -44517,11 +44954,11 @@ Call task_complete with the JSON array when done.`, onEvent)
44517
44954
  loadMemoryEntries(topics) {
44518
44955
  const entries = [];
44519
44956
  const dirs = [
44520
- join48(this.repoRoot, ".oa", "memory"),
44521
- join48(this.repoRoot, ".open-agents", "memory")
44957
+ join49(this.repoRoot, ".oa", "memory"),
44958
+ join49(this.repoRoot, ".open-agents", "memory")
44522
44959
  ];
44523
44960
  for (const dir of dirs) {
44524
- if (!existsSync39(dir))
44961
+ if (!existsSync40(dir))
44525
44962
  continue;
44526
44963
  try {
44527
44964
  const files = readdirSync14(dir).filter((f) => f.endsWith(".json"));
@@ -44530,7 +44967,7 @@ Call task_complete with the JSON array when done.`, onEvent)
44530
44967
  if (topics.length > 0 && !topics.includes(topic))
44531
44968
  continue;
44532
44969
  try {
44533
- const data = JSON.parse(readFileSync29(join48(dir, f), "utf-8"));
44970
+ const data = JSON.parse(readFileSync30(join49(dir, f), "utf-8"));
44534
44971
  for (const [key, val] of Object.entries(data)) {
44535
44972
  const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
44536
44973
  entries.push({ topic, key, value });
@@ -45097,8 +45534,8 @@ var init_tool_policy = __esm({
45097
45534
  });
45098
45535
 
45099
45536
  // 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";
45537
+ import { mkdirSync as mkdirSync18, existsSync as existsSync41, unlinkSync as unlinkSync8, readdirSync as readdirSync15, statSync as statSync11 } from "node:fs";
45538
+ import { join as join50, resolve as resolve28 } from "node:path";
45102
45539
  import { writeFile as writeFileAsync } from "node:fs/promises";
45103
45540
  function convertMarkdownToTelegramHTML(md) {
45104
45541
  let html = md;
@@ -45863,7 +46300,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
45863
46300
  return null;
45864
46301
  const buffer = Buffer.from(await res.arrayBuffer());
45865
46302
  const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
45866
- const localPath = join49(this.mediaCacheDir, fileName);
46303
+ const localPath = join50(this.mediaCacheDir, fileName);
45867
46304
  await writeFileAsync(localPath, buffer);
45868
46305
  return localPath;
45869
46306
  } catch {
@@ -45951,7 +46388,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
45951
46388
  for (const [key, entry] of this.mediaCache) {
45952
46389
  if (now - entry.cachedAt > MEDIA_CACHE_TTL_MS) {
45953
46390
  try {
45954
- unlinkSync7(entry.localPath);
46391
+ unlinkSync8(entry.localPath);
45955
46392
  } catch {
45956
46393
  }
45957
46394
  this.mediaCache.delete(key);
@@ -46027,11 +46464,11 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
46027
46464
  let mimeType = "audio/wav";
46028
46465
  try {
46029
46466
  const { execSync: execSyncLocal } = await import("node:child_process");
46030
- const { tmpdir: tmpdir8 } = await import("node:os");
46467
+ const { tmpdir: tmpdir9 } = await import("node:os");
46031
46468
  const { join: joinPath } = await import("node:path");
46032
46469
  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`);
46470
+ const tmpWav = joinPath(tmpdir9(), `oa-tg-voice-${Date.now()}.wav`);
46471
+ const tmpOgg = joinPath(tmpdir9(), `oa-tg-voice-${Date.now()}.ogg`);
46035
46472
  writeFs(tmpWav, wavBuffer);
46036
46473
  execSyncLocal(`ffmpeg -i "${tmpWav}" -c:a libopus -b:a 48k -ar 48000 -ac 1 "${tmpOgg}" -y 2>/dev/null`, {
46037
46474
  timeout: 15e3,
@@ -48208,11 +48645,11 @@ var init_status_bar = __esm({
48208
48645
  import * as readline2 from "node:readline";
48209
48646
  import { Writable } from "node:stream";
48210
48647
  import { cwd } from "node:process";
48211
- import { resolve as resolve29, join as join50, dirname as dirname18, extname as extname10 } from "node:path";
48648
+ import { resolve as resolve29, join as join51, dirname as dirname18, extname as extname10 } from "node:path";
48212
48649
  import { createRequire as createRequire2 } from "node:module";
48213
48650
  import { fileURLToPath as fileURLToPath12 } from "node:url";
48214
- 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";
48651
+ import { readFileSync as readFileSync31, writeFileSync as writeFileSync17, appendFileSync as appendFileSync4, rmSync as rmSync2, readdirSync as readdirSync16, mkdirSync as mkdirSync19 } from "node:fs";
48652
+ import { existsSync as existsSync42 } from "node:fs";
48216
48653
  import { homedir as homedir13 } from "node:os";
48217
48654
  function formatTimeAgo(date) {
48218
48655
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
@@ -48232,12 +48669,12 @@ function getVersion3() {
48232
48669
  const require2 = createRequire2(import.meta.url);
48233
48670
  const thisDir = dirname18(fileURLToPath12(import.meta.url));
48234
48671
  const candidates = [
48235
- join50(thisDir, "..", "package.json"),
48236
- join50(thisDir, "..", "..", "package.json"),
48237
- join50(thisDir, "..", "..", "..", "package.json")
48672
+ join51(thisDir, "..", "package.json"),
48673
+ join51(thisDir, "..", "..", "package.json"),
48674
+ join51(thisDir, "..", "..", "..", "package.json")
48238
48675
  ];
48239
48676
  for (const pkgPath of candidates) {
48240
- if (existsSync41(pkgPath)) {
48677
+ if (existsSync42(pkgPath)) {
48241
48678
  const pkg = require2(pkgPath);
48242
48679
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
48243
48680
  return pkg.version ?? "0.0.0";
@@ -48444,15 +48881,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
48444
48881
  function gatherMemorySnippets(root) {
48445
48882
  const snippets = [];
48446
48883
  const dirs = [
48447
- join50(root, ".oa", "memory"),
48448
- join50(root, ".open-agents", "memory")
48884
+ join51(root, ".oa", "memory"),
48885
+ join51(root, ".open-agents", "memory")
48449
48886
  ];
48450
48887
  for (const dir of dirs) {
48451
- if (!existsSync41(dir))
48888
+ if (!existsSync42(dir))
48452
48889
  continue;
48453
48890
  try {
48454
48891
  for (const f of readdirSync16(dir).filter((f2) => f2.endsWith(".json"))) {
48455
- const data = JSON.parse(readFileSync30(join50(dir, f), "utf-8"));
48892
+ const data = JSON.parse(readFileSync31(join51(dir, f), "utf-8"));
48456
48893
  for (const val of Object.values(data)) {
48457
48894
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
48458
48895
  if (v.length > 10)
@@ -48897,8 +49334,18 @@ ${entry.fullContent}`
48897
49334
  const name = event.toolName ?? "";
48898
49335
  if (name === "file_write" || name === "file_edit" || name === "file_patch" || name === "batch_edit") {
48899
49336
  filesTouched.add(event.toolArgs.path);
49337
+ if (isNeovimActive()) {
49338
+ notifyNeovimFileChange(event.toolArgs.path).catch(() => {
49339
+ });
49340
+ }
48900
49341
  }
48901
49342
  }
49343
+ if (isNeovimActive()) {
49344
+ const toolName = event.toolName ?? "unknown";
49345
+ const argSummary = Object.keys(event.toolArgs ?? {}).join(", ");
49346
+ writeToNeovimOutput(`\x1B[33m\u25B6 ${toolName}\x1B[0m(${argSummary})\r
49347
+ `);
49348
+ }
48902
49349
  getActivityFeed().push({
48903
49350
  ts: Date.now(),
48904
49351
  source: "main",
@@ -48958,6 +49405,13 @@ ${entry.fullContent}`
48958
49405
  }
48959
49406
  }
48960
49407
  });
49408
+ if (isNeovimActive()) {
49409
+ const ok = event.success ?? false;
49410
+ const prefix = ok ? "\x1B[32m\u2713\x1B[0m" : "\x1B[31m\u2717\x1B[0m";
49411
+ const preview = (event.content ?? "").slice(0, 120).replace(/\n/g, " ");
49412
+ writeToNeovimOutput(` ${prefix} ${preview}\r
49413
+ `);
49414
+ }
48961
49415
  break;
48962
49416
  }
48963
49417
  case "model_response":
@@ -48982,6 +49436,9 @@ ${entry.fullContent}`
48982
49436
  if (stream?.enabled) {
48983
49437
  stream.renderer.write(event.content ?? "", event.streamKind ?? "content");
48984
49438
  }
49439
+ if (isNeovimActive() && event.content && (event.streamKind ?? "content") === "content") {
49440
+ writeToNeovimOutput(event.content);
49441
+ }
48985
49442
  if (voice?.enabled && (voice.voiceMode === "chat" || voice.voiceMode === "verbose")) {
48986
49443
  if (event.content && (event.streamKind ?? "content") === "content") {
48987
49444
  streamTextBuffer += event.content;
@@ -49344,7 +49801,7 @@ async function startInteractive(config, repoPath) {
49344
49801
  let p2pGateway = null;
49345
49802
  let peerMesh = null;
49346
49803
  let inferenceRouter = null;
49347
- const secretVault = new SecretVault(join50(repoRoot, ".oa", "vault.enc"));
49804
+ const secretVault = new SecretVault(join51(repoRoot, ".oa", "vault.enc"));
49348
49805
  let adminSessionKey = null;
49349
49806
  const callSubAgents = /* @__PURE__ */ new Map();
49350
49807
  const streamRenderer = new StreamRenderer();
@@ -49553,13 +50010,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
49553
50010
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
49554
50011
  return [hits, line];
49555
50012
  }
49556
- const HISTORY_DIR = join50(homedir13(), ".open-agents");
49557
- const HISTORY_FILE = join50(HISTORY_DIR, "repl-history");
50013
+ const HISTORY_DIR = join51(homedir13(), ".open-agents");
50014
+ const HISTORY_FILE = join51(HISTORY_DIR, "repl-history");
49558
50015
  const MAX_HISTORY_LINES = 500;
49559
50016
  let savedHistory = [];
49560
50017
  try {
49561
- if (existsSync41(HISTORY_FILE)) {
49562
- const raw = readFileSync30(HISTORY_FILE, "utf8").trim();
50018
+ if (existsSync42(HISTORY_FILE)) {
50019
+ const raw = readFileSync31(HISTORY_FILE, "utf8").trim();
49563
50020
  if (raw)
49564
50021
  savedHistory = raw.split("\n").reverse();
49565
50022
  }
@@ -49579,9 +50036,9 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
49579
50036
  return;
49580
50037
  try {
49581
50038
  mkdirSync19(HISTORY_DIR, { recursive: true });
49582
- appendFileSync3(HISTORY_FILE, line + "\n", "utf8");
50039
+ appendFileSync4(HISTORY_FILE, line + "\n", "utf8");
49583
50040
  if (Math.random() < 0.02) {
49584
- const all = readFileSync30(HISTORY_FILE, "utf8").trim().split("\n");
50041
+ const all = readFileSync31(HISTORY_FILE, "utf8").trim().split("\n");
49585
50042
  if (all.length > MAX_HISTORY_LINES) {
49586
50043
  writeFileSync17(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
49587
50044
  }
@@ -49600,6 +50057,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
49600
50057
  }
49601
50058
  process.stdout.on("resize", () => {
49602
50059
  statusBar.handleResize();
50060
+ if (isNeovimActive()) {
50061
+ const contentRows = statusBar.isActive ? statusBar.availableContentRows : Math.max(5, (process.stdout.rows ?? 24) - 6);
50062
+ resizeNeovim(process.stdout.columns ?? 80, contentRows);
50063
+ }
49603
50064
  if (!carouselRetired) {
49604
50065
  const termRows = process.stdout.rows ?? 24;
49605
50066
  const scrollStart = carousel.reservedRows + 1;
@@ -49717,7 +50178,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
49717
50178
  } catch {
49718
50179
  }
49719
50180
  try {
49720
- const oaDir = join50(repoRoot, ".oa");
50181
+ const oaDir = join51(repoRoot, ".oa");
49721
50182
  const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
49722
50183
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
49723
50184
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -49739,7 +50200,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
49739
50200
  } catch {
49740
50201
  }
49741
50202
  try {
49742
- const oaDir = join50(repoRoot, ".oa");
50203
+ const oaDir = join51(repoRoot, ".oa");
49743
50204
  const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
49744
50205
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
49745
50206
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -50539,7 +51000,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
50539
51000
  kind,
50540
51001
  targetUrl,
50541
51002
  authKey,
50542
- stateDir: join50(repoRoot, ".oa"),
51003
+ stateDir: join51(repoRoot, ".oa"),
50543
51004
  passthrough: passthrough ?? false,
50544
51005
  loadbalance: loadbalance ?? false,
50545
51006
  endpointAuth: passthrough ? currentConfig.apiKey : void 0,
@@ -50584,7 +51045,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
50584
51045
  await tunnelGateway.stop();
50585
51046
  tunnelGateway = null;
50586
51047
  }
50587
- const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join50(repoRoot, ".oa") });
51048
+ const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join51(repoRoot, ".oa") });
50588
51049
  newTunnel.on("stats", (stats) => {
50589
51050
  statusBar.setExposeStatus({
50590
51051
  status: stats.status,
@@ -50834,8 +51295,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
50834
51295
  return statusBar.isActive ? statusBar.availableContentRows : Math.max(3, (process.stdout.rows ?? 24) - 6);
50835
51296
  },
50836
51297
  destroyProject() {
50837
- const oaPath = join50(repoRoot, OA_DIR);
50838
- if (existsSync41(oaPath)) {
51298
+ const oaPath = join51(repoRoot, OA_DIR);
51299
+ if (existsSync42(oaPath)) {
50839
51300
  try {
50840
51301
  rmSync2(oaPath, { recursive: true, force: true });
50841
51302
  writeContent(() => renderInfo(`Removed ${OA_DIR}/ directory.`));
@@ -51164,8 +51625,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
51164
51625
  }
51165
51626
  }
51166
51627
  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));
51628
+ const isImage = isImagePath(cleanPath) && existsSync42(resolve29(repoRoot, cleanPath));
51629
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync42(resolve29(repoRoot, cleanPath));
51169
51630
  if (activeTask) {
51170
51631
  if (activeTask.runner.isPaused) {
51171
51632
  activeTask.runner.resume();
@@ -51174,7 +51635,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
51174
51635
  if (isImage) {
51175
51636
  try {
51176
51637
  const imgPath = resolve29(repoRoot, cleanPath);
51177
- const imgBuffer = readFileSync30(imgPath);
51638
+ const imgBuffer = readFileSync31(imgPath);
51178
51639
  const base64 = imgBuffer.toString("base64");
51179
51640
  const ext = extname10(cleanPath).toLowerCase();
51180
51641
  const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
@@ -51711,6 +52172,7 @@ var init_interactive = __esm({
51711
52172
  init_status_bar();
51712
52173
  init_dist6();
51713
52174
  init_overlay_lock();
52175
+ init_neovim_mode();
51714
52176
  taskManager = new BackgroundTaskManager();
51715
52177
  }
51716
52178
  });
@@ -51746,7 +52208,7 @@ import { glob } from "glob";
51746
52208
  import ignore from "ignore";
51747
52209
  import { readFile as readFile17, stat as stat4 } from "node:fs/promises";
51748
52210
  import { createHash as createHash4 } from "node:crypto";
51749
- import { join as join51, relative as relative3, extname as extname11, basename as basename15 } from "node:path";
52211
+ import { join as join52, relative as relative3, extname as extname11, basename as basename15 } from "node:path";
51750
52212
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
51751
52213
  var init_codebase_indexer = __esm({
51752
52214
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -51790,7 +52252,7 @@ var init_codebase_indexer = __esm({
51790
52252
  const ig = ignore.default();
51791
52253
  if (this.config.respectGitignore) {
51792
52254
  try {
51793
- const gitignoreContent = await readFile17(join51(this.config.rootDir, ".gitignore"), "utf-8");
52255
+ const gitignoreContent = await readFile17(join52(this.config.rootDir, ".gitignore"), "utf-8");
51794
52256
  ig.add(gitignoreContent);
51795
52257
  } catch {
51796
52258
  }
@@ -51805,7 +52267,7 @@ var init_codebase_indexer = __esm({
51805
52267
  for (const relativePath of files) {
51806
52268
  if (ig.ignores(relativePath))
51807
52269
  continue;
51808
- const fullPath = join51(this.config.rootDir, relativePath);
52270
+ const fullPath = join52(this.config.rootDir, relativePath);
51809
52271
  try {
51810
52272
  const fileStat = await stat4(fullPath);
51811
52273
  if (fileStat.size > this.config.maxFileSize)
@@ -51851,7 +52313,7 @@ var init_codebase_indexer = __esm({
51851
52313
  if (!child) {
51852
52314
  child = {
51853
52315
  name: part,
51854
- path: join51(current.path, part),
52316
+ path: join52(current.path, part),
51855
52317
  type: "directory",
51856
52318
  children: []
51857
52319
  };
@@ -51934,13 +52396,13 @@ __export(index_repo_exports, {
51934
52396
  indexRepoCommand: () => indexRepoCommand
51935
52397
  });
51936
52398
  import { resolve as resolve30 } from "node:path";
51937
- import { existsSync as existsSync42, statSync as statSync12 } from "node:fs";
52399
+ import { existsSync as existsSync43, statSync as statSync12 } from "node:fs";
51938
52400
  import { cwd as cwd2 } from "node:process";
51939
52401
  async function indexRepoCommand(opts, _config) {
51940
52402
  const repoRoot = resolve30(opts.repoPath ?? cwd2());
51941
52403
  printHeader("Index Repository");
51942
52404
  printInfo(`Indexing: ${repoRoot}`);
51943
- if (!existsSync42(repoRoot)) {
52405
+ if (!existsSync43(repoRoot)) {
51944
52406
  printError(`Path does not exist: ${repoRoot}`);
51945
52407
  process.exit(1);
51946
52408
  }
@@ -52192,7 +52654,7 @@ var config_exports = {};
52192
52654
  __export(config_exports, {
52193
52655
  configCommand: () => configCommand
52194
52656
  });
52195
- import { join as join52, resolve as resolve31 } from "node:path";
52657
+ import { join as join53, resolve as resolve31 } from "node:path";
52196
52658
  import { homedir as homedir14 } from "node:os";
52197
52659
  import { cwd as cwd3 } from "node:process";
52198
52660
  function redactIfSensitive(key, value) {
@@ -52275,7 +52737,7 @@ function handleShow(opts, config) {
52275
52737
  }
52276
52738
  }
52277
52739
  printSection("Config File");
52278
- printInfo(`~/.open-agents/config.json (${join52(homedir14(), ".open-agents", "config.json")})`);
52740
+ printInfo(`~/.open-agents/config.json (${join53(homedir14(), ".open-agents", "config.json")})`);
52279
52741
  printSection("Priority Chain");
52280
52742
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
52281
52743
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -52314,7 +52776,7 @@ function handleSet(opts, _config) {
52314
52776
  const coerced = coerceForSettings(key, value);
52315
52777
  saveProjectSettings(repoRoot, { [key]: coerced });
52316
52778
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
52317
- printInfo(`Saved to ${join52(repoRoot, ".oa", "settings.json")}`);
52779
+ printInfo(`Saved to ${join53(repoRoot, ".oa", "settings.json")}`);
52318
52780
  printInfo("This override applies only when running in this workspace.");
52319
52781
  } catch (err) {
52320
52782
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -52571,9 +53033,9 @@ var eval_exports = {};
52571
53033
  __export(eval_exports, {
52572
53034
  evalCommand: () => evalCommand
52573
53035
  });
52574
- import { tmpdir as tmpdir7 } from "node:os";
53036
+ import { tmpdir as tmpdir8 } from "node:os";
52575
53037
  import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync18 } from "node:fs";
52576
- import { join as join53 } from "node:path";
53038
+ import { join as join54 } from "node:path";
52577
53039
  async function evalCommand(opts, config) {
52578
53040
  const suiteName = opts.suite ?? "basic";
52579
53041
  const suite = SUITES[suiteName];
@@ -52698,9 +53160,9 @@ async function evalCommand(opts, config) {
52698
53160
  process.exit(failed > 0 ? 1 : 0);
52699
53161
  }
52700
53162
  function createTempEvalRepo() {
52701
- const dir = join53(tmpdir7(), `open-agents-eval-${Date.now()}`);
53163
+ const dir = join54(tmpdir8(), `open-agents-eval-${Date.now()}`);
52702
53164
  mkdirSync20(dir, { recursive: true });
52703
- writeFileSync18(join53(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
53165
+ writeFileSync18(join54(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
52704
53166
  return dir;
52705
53167
  }
52706
53168
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -52760,7 +53222,7 @@ init_updater();
52760
53222
  import { parseArgs as nodeParseArgs2 } from "node:util";
52761
53223
  import { createRequire as createRequire3 } from "node:module";
52762
53224
  import { fileURLToPath as fileURLToPath13 } from "node:url";
52763
- import { dirname as dirname19, join as join54 } from "node:path";
53225
+ import { dirname as dirname19, join as join55 } from "node:path";
52764
53226
 
52765
53227
  // packages/cli/dist/cli.js
52766
53228
  import { createInterface } from "node:readline";
@@ -52867,7 +53329,7 @@ init_output();
52867
53329
  function getVersion4() {
52868
53330
  try {
52869
53331
  const require2 = createRequire3(import.meta.url);
52870
- const pkgPath = join54(dirname19(fileURLToPath13(import.meta.url)), "..", "package.json");
53332
+ const pkgPath = join55(dirname19(fileURLToPath13(import.meta.url)), "..", "package.json");
52871
53333
  const pkg = require2(pkgPath);
52872
53334
  return pkg.version;
52873
53335
  } catch {