open-agents-ai 0.104.3 → 0.104.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +721 -303
  2. package/package.json +6 -2
package/dist/index.js CHANGED
@@ -5639,8 +5639,8 @@ function deleteCustomToolDefinition(name, scope, repoRoot) {
5639
5639
  const dir = scope === "project" && repoRoot ? projectToolsDir(repoRoot) : globalToolsDir();
5640
5640
  const filePath = join13(dir, `${name}.json`);
5641
5641
  if (existsSync10(filePath)) {
5642
- const { unlinkSync: unlinkSync8 } = __require("node:fs");
5643
- unlinkSync8(filePath);
5642
+ const { unlinkSync: unlinkSync9 } = __require("node:fs");
5643
+ unlinkSync9(filePath);
5644
5644
  return true;
5645
5645
  }
5646
5646
  return false;
@@ -20060,8 +20060,8 @@ ${marker}` : marker);
20060
20060
  return;
20061
20061
  try {
20062
20062
  const { mkdirSync: mkdirSync21, writeFileSync: writeFileSync19 } = __require("node:fs");
20063
- const { join: join55 } = __require("node:path");
20064
- const sessionDir = join55(this._workingDirectory, ".oa", "session", this._sessionId);
20063
+ const { join: join56 } = __require("node:path");
20064
+ const sessionDir = join56(this._workingDirectory, ".oa", "session", this._sessionId);
20065
20065
  mkdirSync21(sessionDir, { recursive: true });
20066
20066
  const checkpoint = {
20067
20067
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -20074,7 +20074,7 @@ ${marker}` : marker);
20074
20074
  memexEntryCount: this._memexArchive.size,
20075
20075
  fileRegistrySize: this._fileRegistry.size
20076
20076
  };
20077
- writeFileSync19(join55(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
20077
+ writeFileSync19(join56(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
20078
20078
  } catch {
20079
20079
  }
20080
20080
  }
@@ -27191,6 +27191,8 @@ function renderSlashHelp() {
27191
27191
  ["/voice clone overwatch", "Generate clone ref from Overwatch for LuxTTS"],
27192
27192
  ["/think", "Toggle thinking/reasoning mode (Qwen3, DeepSeek-R1, etc.)"],
27193
27193
  ["/stream", "Toggle real-time token streaming (pastel syntax highlighting)"],
27194
+ ["/neovim", "Toggle embedded Neovim editor (Ctrl+N to switch focus)"],
27195
+ ["/neovim <file>", "Open file in embedded Neovim editor"],
27194
27196
  ["/dream", "Start dream mode \u2014 creative idle exploration (writes to .oa/dreams/)"],
27195
27197
  ["/dream deep", "Deep dream \u2014 multi-cycle exploration with sleep architecture"],
27196
27198
  ["/dream lucid", "Lucid dream \u2014 implements proposals, tests, evaluates in cycles"],
@@ -31011,15 +31013,15 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
31011
31013
  async function fetchPeerModels(peerId, authKey) {
31012
31014
  try {
31013
31015
  const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
31014
- const { existsSync: existsSync43, readFileSync: readFileSync31 } = await import("node:fs");
31015
- const { join: join55 } = await import("node:path");
31016
+ const { existsSync: existsSync44, readFileSync: readFileSync31 } = await import("node:fs");
31017
+ const { join: join56 } = await import("node:path");
31016
31018
  const cwd4 = process.cwd();
31017
31019
  const nexusTool = new NexusTool2(cwd4);
31018
31020
  const nexusDir = nexusTool.getNexusDir();
31019
31021
  let isLocalPeer = false;
31020
31022
  try {
31021
- const statusPath = join55(nexusDir, "status.json");
31022
- if (existsSync43(statusPath)) {
31023
+ const statusPath = join56(nexusDir, "status.json");
31024
+ if (existsSync44(statusPath)) {
31023
31025
  const status = JSON.parse(readFileSync31(statusPath, "utf8"));
31024
31026
  if (status.peerId === peerId)
31025
31027
  isLocalPeer = true;
@@ -31027,8 +31029,8 @@ async function fetchPeerModels(peerId, authKey) {
31027
31029
  } catch {
31028
31030
  }
31029
31031
  if (isLocalPeer) {
31030
- const pricingPath = join55(nexusDir, "pricing.json");
31031
- if (existsSync43(pricingPath)) {
31032
+ const pricingPath = join56(nexusDir, "pricing.json");
31033
+ if (existsSync44(pricingPath)) {
31032
31034
  try {
31033
31035
  const pricing = JSON.parse(readFileSync31(pricingPath, "utf8"));
31034
31036
  const localModels = (pricing.models || []).map((m) => ({
@@ -31044,8 +31046,8 @@ async function fetchPeerModels(peerId, authKey) {
31044
31046
  }
31045
31047
  }
31046
31048
  }
31047
- const cachePath = join55(nexusDir, "peer-models-cache.json");
31048
- if (existsSync43(cachePath)) {
31049
+ const cachePath = join56(nexusDir, "peer-models-cache.json");
31050
+ if (existsSync44(cachePath)) {
31049
31051
  try {
31050
31052
  const cache4 = JSON.parse(readFileSync31(cachePath, "utf8"));
31051
31053
  if (cache4.peerId === peerId && cache4.models?.length > 0) {
@@ -31162,8 +31164,8 @@ async function fetchPeerModels(peerId, authKey) {
31162
31164
  } catch {
31163
31165
  }
31164
31166
  if (isLocalPeer) {
31165
- const pricingPath = join55(nexusDir, "pricing.json");
31166
- if (existsSync43(pricingPath)) {
31167
+ const pricingPath = join56(nexusDir, "pricing.json");
31168
+ if (existsSync44(pricingPath)) {
31167
31169
  try {
31168
31170
  const pricing = JSON.parse(readFileSync31(pricingPath, "utf8"));
31169
31171
  return (pricing.models || []).map((m) => ({
@@ -33711,6 +33713,12 @@ var init_setup = __esm({
33711
33713
  function isOverlayActive() {
33712
33714
  return _overlayActive;
33713
33715
  }
33716
+ function overlayWrite(data) {
33717
+ if (_origStdoutWrite) {
33718
+ return _origStdoutWrite.call(process.stdout, data);
33719
+ }
33720
+ return process.stdout.write(data);
33721
+ }
33714
33722
  function bufferIfOverlay(stream, data) {
33715
33723
  if (!_overlayActive)
33716
33724
  return false;
@@ -33719,12 +33727,38 @@ function bufferIfOverlay(stream, data) {
33719
33727
  }
33720
33728
  function enterOverlay() {
33721
33729
  _depth++;
33722
- _overlayActive = true;
33730
+ if (_depth === 1) {
33731
+ _overlayActive = true;
33732
+ _origStdoutWrite = process.stdout.write.bind(process.stdout);
33733
+ _origStderrWrite = process.stderr.write.bind(process.stderr);
33734
+ process.stdout.write = function(chunk, ...args) {
33735
+ _buffer.push({ stream: "stdout", data: chunk });
33736
+ const cb = typeof args[args.length - 1] === "function" ? args[args.length - 1] : void 0;
33737
+ if (cb)
33738
+ cb();
33739
+ return true;
33740
+ };
33741
+ process.stderr.write = function(chunk, ...args) {
33742
+ _buffer.push({ stream: "stderr", data: chunk });
33743
+ const cb = typeof args[args.length - 1] === "function" ? args[args.length - 1] : void 0;
33744
+ if (cb)
33745
+ cb();
33746
+ return true;
33747
+ };
33748
+ }
33723
33749
  }
33724
33750
  function leaveOverlay() {
33725
33751
  _depth = Math.max(0, _depth - 1);
33726
33752
  if (_depth === 0) {
33727
33753
  _overlayActive = false;
33754
+ if (_origStdoutWrite) {
33755
+ process.stdout.write = _origStdoutWrite;
33756
+ _origStdoutWrite = null;
33757
+ }
33758
+ if (_origStderrWrite) {
33759
+ process.stderr.write = _origStderrWrite;
33760
+ _origStderrWrite = null;
33761
+ }
33728
33762
  const pending = _buffer;
33729
33763
  _buffer = [];
33730
33764
  for (const { stream, data } of pending) {
@@ -33736,13 +33770,15 @@ function leaveOverlay() {
33736
33770
  }
33737
33771
  }
33738
33772
  }
33739
- var _overlayActive, _depth, _buffer;
33773
+ var _overlayActive, _depth, _buffer, _origStdoutWrite, _origStderrWrite;
33740
33774
  var init_overlay_lock = __esm({
33741
33775
  "packages/cli/dist/tui/overlay-lock.js"() {
33742
33776
  "use strict";
33743
33777
  _overlayActive = false;
33744
33778
  _depth = 0;
33745
33779
  _buffer = [];
33780
+ _origStdoutWrite = null;
33781
+ _origStderrWrite = null;
33746
33782
  }
33747
33783
  });
33748
33784
 
@@ -33839,8 +33875,8 @@ function tuiSelect(opts) {
33839
33875
  stdin.setRawMode(true);
33840
33876
  }
33841
33877
  stdin.resume();
33842
- process.stdout.write("\x1B[?1049h\x1B[2J\x1B[H\x1B[?25l");
33843
33878
  enterOverlay();
33879
+ overlayWrite("\x1B[?1049h\x1B[2J\x1B[H\x1B[?25l");
33844
33880
  function clampScroll(displayList) {
33845
33881
  const cursorPos = displayList.indexOf(cursor);
33846
33882
  if (cursorPos < 0)
@@ -33854,7 +33890,7 @@ function tuiSelect(opts) {
33854
33890
  scrollOffset = Math.max(0, Math.min(maxOffset, scrollOffset));
33855
33891
  }
33856
33892
  function render() {
33857
- process.stdout.write("\x1B[H\x1B[2J");
33893
+ overlayWrite("\x1B[H\x1B[2J");
33858
33894
  const lines = [];
33859
33895
  if (title) {
33860
33896
  lines.push(`
@@ -33928,14 +33964,14 @@ function tuiSelect(opts) {
33928
33964
  }
33929
33965
  lines.push("");
33930
33966
  const output = lines.join("\n");
33931
- process.stdout.write(output);
33967
+ overlayWrite(output);
33932
33968
  lastRenderedLines = lines.length;
33933
33969
  }
33934
33970
  function cleanup() {
33935
33971
  stdin.removeListener("data", onData);
33936
33972
  process.stdout.removeListener("resize", onResize);
33973
+ overlayWrite("\x1B[?1049l\x1B[?25h");
33937
33974
  leaveOverlay();
33938
- process.stdout.write("\x1B[?1049l\x1B[?25h");
33939
33975
  if (typeof stdin.setRawMode === "function") {
33940
33976
  stdin.setRawMode(hadRawMode ?? false);
33941
33977
  }
@@ -34118,33 +34154,33 @@ function tuiSelect(opts) {
34118
34154
  return new Promise((inputResolve) => {
34119
34155
  let inputBuf = prefill;
34120
34156
  let inputCursor = prefill.length;
34121
- process.stdout.write("\x1B[?25h");
34157
+ overlayWrite("\x1B[?25h");
34122
34158
  function renderInput() {
34123
- process.stdout.write(`\x1B[${lastRenderedLines}A`);
34159
+ overlayWrite(`\x1B[${lastRenderedLines}A`);
34124
34160
  const saveFooter = lastRenderedLines;
34125
34161
  for (let i = 0; i < saveFooter; i++)
34126
- process.stdout.write("\x1B[B");
34127
- process.stdout.write("\x1B[2A");
34128
- process.stdout.write("\x1B[2K");
34162
+ overlayWrite("\x1B[B");
34163
+ overlayWrite("\x1B[2A");
34164
+ overlayWrite("\x1B[2K");
34129
34165
  const before = inputBuf.slice(0, inputCursor);
34130
34166
  const after = inputBuf.slice(inputCursor);
34131
- process.stdout.write(` ${selectColors.cyan("\u203A")} ${selectColors.bold(prompt)} ${before}\x1B[7m${after.charAt(0) || " "}\x1B[27m${after.slice(1)}`);
34132
- process.stdout.write("\n\x1B[2K");
34133
- process.stdout.write(` ${selectColors.dim("Enter confirm Esc cancel")}`);
34134
- process.stdout.write("\n");
34167
+ overlayWrite(` ${selectColors.cyan("\u203A")} ${selectColors.bold(prompt)} ${before}\x1B[7m${after.charAt(0) || " "}\x1B[27m${after.slice(1)}`);
34168
+ overlayWrite("\n\x1B[2K");
34169
+ overlayWrite(` ${selectColors.dim("Enter confirm Esc cancel")}`);
34170
+ overlayWrite("\n");
34135
34171
  }
34136
34172
  function onInputData(chunk) {
34137
34173
  const s = chunk.toString("utf8");
34138
34174
  if (s === "\r" || s === "\n") {
34139
34175
  stdin.removeListener("data", onInputData);
34140
34176
  stdin.on("data", onData);
34141
- process.stdout.write("\x1B[?25l");
34177
+ overlayWrite("\x1B[?25l");
34142
34178
  render();
34143
34179
  inputResolve(inputBuf);
34144
34180
  } else if (s === "\x1B" || s === "\x1B\x1B" || s === "") {
34145
34181
  stdin.removeListener("data", onInputData);
34146
34182
  stdin.on("data", onData);
34147
- process.stdout.write("\x1B[?25l");
34183
+ overlayWrite("\x1B[?25l");
34148
34184
  render();
34149
34185
  inputResolve(null);
34150
34186
  } else if (s === "\x7F" || s === "\b") {
@@ -34212,6 +34248,29 @@ import { extname as extname9, resolve as resolve27 } from "node:path";
34212
34248
  function ansi4(code, text) {
34213
34249
  return isTTY4 ? `\x1B[${code}m${text}\x1B[0m` : text;
34214
34250
  }
34251
+ function stripAnsi2(s) {
34252
+ return s.replace(/\x1B\[[0-9;]*m/g, "");
34253
+ }
34254
+ function fitToWidth(text, width) {
34255
+ const visible = stripAnsi2(text);
34256
+ if (visible.length >= width) {
34257
+ let visCount = 0;
34258
+ let i = 0;
34259
+ while (i < text.length && visCount < width) {
34260
+ if (text[i] === "\x1B") {
34261
+ const end = text.indexOf("m", i);
34262
+ if (end >= 0) {
34263
+ i = end + 1;
34264
+ continue;
34265
+ }
34266
+ }
34267
+ visCount++;
34268
+ i++;
34269
+ }
34270
+ return text.slice(0, i) + "\x1B[0m";
34271
+ }
34272
+ return text + " ".repeat(width - visible.length);
34273
+ }
34215
34274
  function showDropPanel(opts) {
34216
34275
  const { title, instruction = "Drag and drop a file here, or type/paste a path", allowedExtensions = [], typeLabel, rl } = opts;
34217
34276
  return new Promise((resolve_) => {
@@ -34232,53 +34291,56 @@ function showDropPanel(opts) {
34232
34291
  stdin.setRawMode(true);
34233
34292
  }
34234
34293
  stdin.resume();
34235
- process.stdout.write("\x1B[?1049h\x1B[2J\x1B[H\x1B[?25h");
34236
34294
  enterOverlay();
34295
+ overlayWrite("\x1B[?1049h\x1B[2J\x1B[H\x1B[?25h");
34237
34296
  let inputBuf = "";
34238
34297
  let errorMsg = "";
34239
34298
  function render() {
34240
- process.stdout.write("\x1B[H\x1B[2J");
34299
+ overlayWrite("\x1B[H\x1B[2J");
34241
34300
  const cols = process.stdout.columns ?? 80;
34242
34301
  const rows = process.stdout.rows ?? 24;
34243
- const borderH = "\u2508".repeat(Math.max(2, cols - 4));
34244
- const lines = [];
34245
- lines.push("");
34246
- lines.push(` ${dc.cyan(borderH)}`);
34247
- const contentLines = 8;
34248
- const topPad = Math.max(1, Math.floor((rows - contentLines) / 2) - 2);
34249
- for (let i = 0; i < topPad; i++) {
34250
- lines.push(` ${dc.cyan("\u250A")}${" ".repeat(Math.max(0, cols - 6))}${dc.cyan("\u250A")}`);
34251
- }
34252
- const titleLine = ` ${dc.cyan("\u250A")} ${dc.bold(title)}`;
34253
- lines.push(titleLine);
34254
- lines.push(` ${dc.cyan("\u250A")}`);
34255
- lines.push(` ${dc.cyan("\u250A")} ${dc.dim(instruction)}`);
34302
+ const textWidth = Math.max(10, cols - 9);
34303
+ const innerSpace = Math.max(10, cols - 6);
34304
+ const content = [];
34305
+ content.push(` ${fitToWidth(dc.bold(title), textWidth)} `);
34306
+ content.push(` ${" ".repeat(textWidth)} `);
34307
+ content.push(` ${fitToWidth(dc.dim(instruction), textWidth)} `);
34256
34308
  if (allowedExtensions.length > 0) {
34257
34309
  const extList = allowedExtensions.join(", ");
34258
34310
  const label = typeLabel ? `${typeLabel}: ` : "Accepted: ";
34259
- lines.push(` ${dc.cyan("\u250A")} ${dc.dim(label)}${dc.dim(extList)}`);
34311
+ content.push(` ${fitToWidth(dc.dim(label) + dc.dim(extList), textWidth)} `);
34260
34312
  }
34261
- lines.push(` ${dc.cyan("\u250A")}`);
34262
- const cursor = inputBuf.length > 0 ? inputBuf : dc.dim("waiting for file...");
34263
- lines.push(` ${dc.cyan("\u250A")} ${dc.cyan(">")} ${cursor}`);
34313
+ content.push(` ${" ".repeat(textWidth)} `);
34314
+ const cursorText = inputBuf.length > 0 ? inputBuf : dc.dim("waiting for file...");
34315
+ content.push(` ${fitToWidth(dc.cyan(">") + " " + cursorText, textWidth)} `);
34264
34316
  if (errorMsg) {
34265
- lines.push(` ${dc.cyan("\u250A")} ${dc.red(errorMsg)}`);
34317
+ content.push(` ${fitToWidth(dc.red(errorMsg), textWidth)} `);
34266
34318
  } else {
34267
- lines.push(` ${dc.cyan("\u250A")}`);
34319
+ content.push(` ${" ".repeat(textWidth)} `);
34268
34320
  }
34269
- const bottomPad = Math.max(1, rows - lines.length - 4);
34270
- for (let i = 0; i < bottomPad; i++) {
34271
- lines.push(` ${dc.cyan("\u250A")}${" ".repeat(Math.max(0, cols - 6))}${dc.cyan("\u250A")}`);
34321
+ const fixedChrome = 4;
34322
+ const availableForPadding = Math.max(0, rows - fixedChrome - content.length);
34323
+ const topPad = Math.max(0, Math.floor(availableForPadding / 2));
34324
+ const bottomPad = Math.max(0, availableForPadding - topPad);
34325
+ const lines = [];
34326
+ const borderH = "\u2508".repeat(Math.max(2, cols - 4));
34327
+ const emptyPipe = ` ${dc.cyan("\u250A")}${" ".repeat(innerSpace)}${dc.cyan("\u250A")}`;
34328
+ lines.push(` ${dc.cyan(borderH)}`);
34329
+ for (let i = 0; i < topPad; i++)
34330
+ lines.push(emptyPipe);
34331
+ for (const line of content) {
34332
+ lines.push(` ${dc.cyan("\u250A")}${line}${dc.cyan("\u250A")}`);
34272
34333
  }
34334
+ for (let i = 0; i < bottomPad; i++)
34335
+ lines.push(emptyPipe);
34273
34336
  lines.push(` ${dc.cyan(borderH)}`);
34274
34337
  lines.push(` ${dc.dim("Enter confirm Esc cancel")}`);
34275
- lines.push("");
34276
- process.stdout.write(lines.join("\n"));
34338
+ overlayWrite(lines.join("\n") + "\n");
34277
34339
  }
34278
34340
  function cleanup() {
34279
34341
  stdin.removeListener("data", onData);
34342
+ overlayWrite("\x1B[?1049l\x1B[?25h");
34280
34343
  leaveOverlay();
34281
- process.stdout.write("\x1B[?1049l\x1B[?25h");
34282
34344
  if (typeof stdin.setRawMode === "function") {
34283
34345
  stdin.setRawMode(hadRawMode ?? false);
34284
34346
  }
@@ -34366,6 +34428,309 @@ var init_drop_panel = __esm({
34366
34428
  }
34367
34429
  });
34368
34430
 
34431
+ // packages/cli/dist/tui/neovim-mode.js
34432
+ import { existsSync as existsSync33, unlinkSync as unlinkSync5 } from "node:fs";
34433
+ import { tmpdir as tmpdir6 } from "node:os";
34434
+ import { join as join41 } from "node:path";
34435
+ import { execSync as execSync26 } from "node:child_process";
34436
+ function isNeovimActive() {
34437
+ return _state !== null && !_state.cleanedUp;
34438
+ }
34439
+ async function startNeovimMode(opts) {
34440
+ if (_state && !_state.cleanedUp) {
34441
+ return "Neovim mode is already active. Use /neovim to exit first.";
34442
+ }
34443
+ let nvimPath;
34444
+ try {
34445
+ nvimPath = execSync26("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
34446
+ if (!nvimPath)
34447
+ throw new Error();
34448
+ } catch {
34449
+ return "nvim not found on PATH. Install Neovim: https://neovim.io";
34450
+ }
34451
+ let ptyMod;
34452
+ try {
34453
+ const ptyModName = "node-pty";
34454
+ ptyMod = await import(
34455
+ /* @vite-ignore */
34456
+ ptyModName
34457
+ );
34458
+ } catch {
34459
+ return "node-pty not available. Install it: npm install node-pty";
34460
+ }
34461
+ let neovimPkg = null;
34462
+ try {
34463
+ const nvimModName = "neovim";
34464
+ neovimPkg = await import(
34465
+ /* @vite-ignore */
34466
+ nvimModName
34467
+ );
34468
+ } catch {
34469
+ }
34470
+ const socketPath = join41(tmpdir6(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
34471
+ try {
34472
+ if (existsSync33(socketPath))
34473
+ unlinkSync5(socketPath);
34474
+ } catch {
34475
+ }
34476
+ const ptyCols = opts.cols;
34477
+ const ptyRows = Math.max(5, opts.contentRows);
34478
+ const nvimArgs = [
34479
+ "--listen",
34480
+ socketPath,
34481
+ "--cmd",
34482
+ "set autoread updatetime=300 signcolumn=no"
34483
+ ];
34484
+ if (opts.initialFile) {
34485
+ nvimArgs.push(opts.initialFile);
34486
+ } else {
34487
+ nvimArgs.push(".");
34488
+ }
34489
+ const nvimPty = ptyMod.spawn(nvimPath, nvimArgs, {
34490
+ name: "xterm-256color",
34491
+ cols: ptyCols,
34492
+ rows: ptyRows,
34493
+ cwd: opts.cwd,
34494
+ env: { ...process.env }
34495
+ });
34496
+ const state = {
34497
+ pty: nvimPty,
34498
+ nvim: null,
34499
+ outputChanId: 0,
34500
+ socketPath,
34501
+ focused: true,
34502
+ opts,
34503
+ stdinHandler: null,
34504
+ savedRlListeners: [],
34505
+ cleanedUp: false
34506
+ };
34507
+ _state = state;
34508
+ nvimPty.onData((data) => {
34509
+ if (state.cleanedUp)
34510
+ return;
34511
+ if (!state.focused) {
34512
+ process.stdout.write("\x1B7" + data + "\x1B8");
34513
+ } else {
34514
+ process.stdout.write(data);
34515
+ }
34516
+ });
34517
+ nvimPty.onExit(() => {
34518
+ if (!state.cleanedUp) {
34519
+ doCleanup(state);
34520
+ }
34521
+ });
34522
+ const stdin = process.stdin;
34523
+ if (opts.rl) {
34524
+ opts.rl.pause();
34525
+ for (const event of ["keypress", "data"]) {
34526
+ const listeners = stdin.listeners(event);
34527
+ for (const fn of listeners) {
34528
+ state.savedRlListeners.push({ event, fn });
34529
+ stdin.removeListener(event, fn);
34530
+ }
34531
+ }
34532
+ }
34533
+ if (typeof stdin.setRawMode === "function") {
34534
+ stdin.setRawMode(true);
34535
+ }
34536
+ stdin.resume();
34537
+ state.stdinHandler = (data) => {
34538
+ if (state.cleanedUp)
34539
+ return;
34540
+ const seq = data.toString("utf8");
34541
+ if (seq === "") {
34542
+ toggleFocus(state);
34543
+ return;
34544
+ }
34545
+ if (state.focused) {
34546
+ nvimPty.write(seq);
34547
+ }
34548
+ };
34549
+ stdin.on("data", state.stdinHandler);
34550
+ if (neovimPkg) {
34551
+ connectRPC(state, neovimPkg, ptyCols).catch(() => {
34552
+ });
34553
+ }
34554
+ return null;
34555
+ }
34556
+ function stopNeovimMode() {
34557
+ if (!_state || _state.cleanedUp)
34558
+ return;
34559
+ try {
34560
+ _state.pty?.write(":qa!\r");
34561
+ } catch {
34562
+ }
34563
+ setTimeout(() => {
34564
+ if (_state && !_state.cleanedUp) {
34565
+ doCleanup(_state);
34566
+ }
34567
+ }, 500);
34568
+ }
34569
+ function writeToNeovimOutput(text) {
34570
+ if (!_state || _state.cleanedUp || !_state.nvim || !_state.outputChanId)
34571
+ return;
34572
+ const normalized = text.replace(/(?<!\r)\n/g, "\r\n");
34573
+ _state.nvim.request("nvim_chan_send", [_state.outputChanId, normalized]).catch(() => {
34574
+ });
34575
+ }
34576
+ async function notifyNeovimFileChange(filePath) {
34577
+ if (!_state || _state.cleanedUp || !_state.nvim)
34578
+ return;
34579
+ try {
34580
+ await _state.nvim.command("checktime");
34581
+ if (filePath) {
34582
+ const escaped = filePath.replace(/'/g, "''");
34583
+ await _state.nvim.command(`if bufexists('${escaped}') | execute 'buffer ' . bufnr('${escaped}') | endif`);
34584
+ }
34585
+ } catch {
34586
+ }
34587
+ }
34588
+ function resizeNeovim(cols, contentRows) {
34589
+ if (!_state || _state.cleanedUp || !_state.pty)
34590
+ return;
34591
+ const rows = Math.max(5, contentRows);
34592
+ try {
34593
+ _state.pty.resize(cols, rows);
34594
+ } catch {
34595
+ }
34596
+ }
34597
+ async function connectRPC(state, neovimPkg, cols) {
34598
+ let attempts = 0;
34599
+ while (!existsSync33(state.socketPath) && attempts < 30) {
34600
+ await new Promise((r) => setTimeout(r, 200));
34601
+ attempts++;
34602
+ if (state.cleanedUp)
34603
+ return;
34604
+ }
34605
+ if (!existsSync33(state.socketPath))
34606
+ return;
34607
+ const nvim = neovimPkg.attach({ socket: state.socketPath });
34608
+ state.nvim = nvim;
34609
+ await new Promise((r) => setTimeout(r, 300));
34610
+ if (state.cleanedUp)
34611
+ return;
34612
+ try {
34613
+ const editorWidth = Math.floor(cols * 0.7);
34614
+ const outputWidth = cols - editorWidth;
34615
+ await nvim.command("botright vsplit");
34616
+ await nvim.command(`vertical resize ${outputWidth}`);
34617
+ const buf = await nvim.createBuffer(false, true);
34618
+ const win = await nvim.window;
34619
+ await nvim.request("nvim_win_set_buf", [win.id, buf.id]);
34620
+ await nvim.request("nvim_buf_set_option", [buf.id, "buftype", "nofile"]);
34621
+ await nvim.request("nvim_buf_set_option", [buf.id, "swapfile", false]);
34622
+ const chanId = await nvim.request("nvim_open_term", [buf.id, {}]);
34623
+ state.outputChanId = chanId;
34624
+ await nvim.request("nvim_chan_send", [
34625
+ chanId,
34626
+ "\x1B[36m\u2500\u2500 Agent Output \u2500\u2500\x1B[0m\r\n\r\n\x1B[2mAgent activity will appear here.\x1B[0m\r\n\x1B[2mCtrl+N toggles focus to input.\x1B[0m\r\n"
34627
+ ]);
34628
+ await nvim.request("nvim_win_set_option", [win.id, "number", false]);
34629
+ await nvim.request("nvim_win_set_option", [win.id, "relativenumber", false]);
34630
+ await nvim.request("nvim_win_set_option", [win.id, "wrap", true]);
34631
+ await nvim.command("wincmd h");
34632
+ await nvim.command("set autoread");
34633
+ await nvim.command("autocmd FocusGained,BufEnter,CursorHold * silent! checktime");
34634
+ } catch {
34635
+ }
34636
+ }
34637
+ function toggleFocus(state) {
34638
+ const stdin = process.stdin;
34639
+ if (state.focused) {
34640
+ state.focused = false;
34641
+ if (state.stdinHandler) {
34642
+ stdin.removeListener("data", state.stdinHandler);
34643
+ }
34644
+ if (typeof stdin.setRawMode === "function") {
34645
+ stdin.setRawMode(false);
34646
+ }
34647
+ for (const { event, fn } of state.savedRlListeners) {
34648
+ stdin.on(event, fn);
34649
+ }
34650
+ if (state.opts.rl) {
34651
+ state.opts.rl.resume();
34652
+ state.opts.rl.prompt(false);
34653
+ }
34654
+ } else {
34655
+ state.focused = true;
34656
+ if (state.opts.rl) {
34657
+ state.opts.rl.pause();
34658
+ }
34659
+ state.savedRlListeners = [];
34660
+ for (const event of ["keypress", "data"]) {
34661
+ const listeners = stdin.listeners(event);
34662
+ for (const fn of listeners) {
34663
+ state.savedRlListeners.push({ event, fn });
34664
+ stdin.removeListener(event, fn);
34665
+ }
34666
+ }
34667
+ if (typeof stdin.setRawMode === "function") {
34668
+ stdin.setRawMode(true);
34669
+ }
34670
+ stdin.resume();
34671
+ if (state.stdinHandler) {
34672
+ stdin.on("data", state.stdinHandler);
34673
+ }
34674
+ if (state.nvim) {
34675
+ state.nvim.command("echo ''").catch(() => {
34676
+ });
34677
+ }
34678
+ }
34679
+ }
34680
+ function doCleanup(state) {
34681
+ if (state.cleanedUp)
34682
+ return;
34683
+ state.cleanedUp = true;
34684
+ const stdin = process.stdin;
34685
+ if (state.nvim) {
34686
+ try {
34687
+ state.nvim.quit();
34688
+ } catch {
34689
+ }
34690
+ state.nvim = null;
34691
+ }
34692
+ if (state.pty) {
34693
+ try {
34694
+ state.pty.kill();
34695
+ } catch {
34696
+ }
34697
+ state.pty = null;
34698
+ }
34699
+ try {
34700
+ if (existsSync33(state.socketPath))
34701
+ unlinkSync5(state.socketPath);
34702
+ } catch {
34703
+ }
34704
+ if (state.stdinHandler) {
34705
+ stdin.removeListener("data", state.stdinHandler);
34706
+ state.stdinHandler = null;
34707
+ }
34708
+ if (typeof stdin.setRawMode === "function") {
34709
+ try {
34710
+ stdin.setRawMode(false);
34711
+ } catch {
34712
+ }
34713
+ }
34714
+ for (const { event, fn } of state.savedRlListeners) {
34715
+ stdin.on(event, fn);
34716
+ }
34717
+ if (state.opts.rl) {
34718
+ state.opts.rl.resume();
34719
+ state.opts.rl.prompt(false);
34720
+ }
34721
+ _state = null;
34722
+ process.stdout.write("\x1B[H\x1B[J");
34723
+ state.opts.onExit?.();
34724
+ }
34725
+ var isTTY5, _state;
34726
+ var init_neovim_mode = __esm({
34727
+ "packages/cli/dist/tui/neovim-mode.js"() {
34728
+ "use strict";
34729
+ isTTY5 = process.stdout.isTTY ?? false;
34730
+ _state = null;
34731
+ }
34732
+ });
34733
+
34369
34734
  // packages/cli/dist/tui/voice.js
34370
34735
  var voice_exports = {};
34371
34736
  __export(voice_exports, {
@@ -34378,10 +34743,10 @@ __export(voice_exports, {
34378
34743
  registerCustomOnnxModel: () => registerCustomOnnxModel,
34379
34744
  resetNarrationContext: () => resetNarrationContext
34380
34745
  });
34381
- 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";
34382
- import { join as join41 } from "node:path";
34383
- import { homedir as homedir11, tmpdir as tmpdir6, platform as platform2 } from "node:os";
34384
- import { execSync as execSync26, spawn as nodeSpawn } from "node:child_process";
34746
+ import { existsSync as existsSync34, mkdirSync as mkdirSync13, writeFileSync as writeFileSync13, readFileSync as readFileSync23, unlinkSync as unlinkSync6, readdirSync as readdirSync9, renameSync, statSync as statSync10 } from "node:fs";
34747
+ import { join as join42 } from "node:path";
34748
+ import { homedir as homedir11, tmpdir as tmpdir7, platform as platform2 } from "node:os";
34749
+ import { execSync as execSync27, spawn as nodeSpawn } from "node:child_process";
34385
34750
  import { createRequire } from "node:module";
34386
34751
  function registerCustomOnnxModel(id, label) {
34387
34752
  VOICE_MODELS[id] = {
@@ -34401,34 +34766,34 @@ function listVoiceModels() {
34401
34766
  }));
34402
34767
  }
34403
34768
  function voiceDir() {
34404
- return join41(homedir11(), ".open-agents", "voice");
34769
+ return join42(homedir11(), ".open-agents", "voice");
34405
34770
  }
34406
34771
  function modelsDir() {
34407
- return join41(voiceDir(), "models");
34772
+ return join42(voiceDir(), "models");
34408
34773
  }
34409
34774
  function modelDir(id) {
34410
- return join41(modelsDir(), id);
34775
+ return join42(modelsDir(), id);
34411
34776
  }
34412
34777
  function modelOnnxPath(id) {
34413
- return join41(modelDir(id), "model.onnx");
34778
+ return join42(modelDir(id), "model.onnx");
34414
34779
  }
34415
34780
  function modelConfigPath(id) {
34416
- return join41(modelDir(id), "config.json");
34781
+ return join42(modelDir(id), "config.json");
34417
34782
  }
34418
34783
  function luxttsVenvDir() {
34419
- return join41(voiceDir(), "luxtts-venv");
34784
+ return join42(voiceDir(), "luxtts-venv");
34420
34785
  }
34421
34786
  function luxttsVenvPy() {
34422
- return platform2() === "win32" ? join41(luxttsVenvDir(), "Scripts", "python.exe") : join41(luxttsVenvDir(), "bin", "python3");
34787
+ return platform2() === "win32" ? join42(luxttsVenvDir(), "Scripts", "python.exe") : join42(luxttsVenvDir(), "bin", "python3");
34423
34788
  }
34424
34789
  function luxttsRepoDir() {
34425
- return join41(voiceDir(), "LuxTTS");
34790
+ return join42(voiceDir(), "LuxTTS");
34426
34791
  }
34427
34792
  function luxttsCloneRefsDir() {
34428
- return join41(voiceDir(), "clone-refs");
34793
+ return join42(voiceDir(), "clone-refs");
34429
34794
  }
34430
34795
  function luxttsInferScript() {
34431
- return join41(voiceDir(), "luxtts-infer.py");
34796
+ return join42(voiceDir(), "luxtts-infer.py");
34432
34797
  }
34433
34798
  function emotionToPitchBias(emotion, stark = false, autist = false) {
34434
34799
  if (autist)
@@ -35236,8 +35601,8 @@ var init_voice = __esm({
35236
35601
  const refsDir = luxttsCloneRefsDir();
35237
35602
  const targets = ["glados", "overwatch"];
35238
35603
  for (const modelId of targets) {
35239
- const refFile = join41(refsDir, `${modelId}-ref.wav`);
35240
- if (existsSync33(refFile))
35604
+ const refFile = join42(refsDir, `${modelId}-ref.wav`);
35605
+ if (existsSync34(refFile))
35241
35606
  continue;
35242
35607
  try {
35243
35608
  await this.generateCloneRef(modelId);
@@ -35316,21 +35681,21 @@ var init_voice = __esm({
35316
35681
  }
35317
35682
  p = p.replace(/\\ /g, " ");
35318
35683
  if (p.startsWith("~/") || p === "~") {
35319
- p = join41(homedir11(), p.slice(1));
35684
+ p = join42(homedir11(), p.slice(1));
35320
35685
  }
35321
- if (!existsSync33(p)) {
35686
+ if (!existsSync34(p)) {
35322
35687
  return `File not found: ${p}
35323
35688
  (original input: ${audioPath})`;
35324
35689
  }
35325
35690
  audioPath = p;
35326
35691
  const refsDir = luxttsCloneRefsDir();
35327
- if (!existsSync33(refsDir))
35692
+ if (!existsSync34(refsDir))
35328
35693
  mkdirSync13(refsDir, { recursive: true });
35329
35694
  const ext = audioPath.split(".").pop() || "wav";
35330
35695
  const srcName = (audioPath.split("/").pop() ?? "clone").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]/g, "-");
35331
35696
  const ts = Date.now().toString(36);
35332
35697
  const destFilename = `clone-${srcName}-${ts}.${ext}`;
35333
- const destPath = join41(refsDir, destFilename);
35698
+ const destPath = join42(refsDir, destFilename);
35334
35699
  try {
35335
35700
  const data = readFileSync23(audioPath);
35336
35701
  writeFileSync13(destPath, data);
@@ -35373,9 +35738,9 @@ var init_voice = __esm({
35373
35738
  return `Failed to synthesize reference audio from ${source.label}.`;
35374
35739
  }
35375
35740
  const refsDir = luxttsCloneRefsDir();
35376
- if (!existsSync33(refsDir))
35741
+ if (!existsSync34(refsDir))
35377
35742
  mkdirSync13(refsDir, { recursive: true });
35378
- const destPath = join41(refsDir, `${sourceModelId}-ref.wav`);
35743
+ const destPath = join42(refsDir, `${sourceModelId}-ref.wav`);
35379
35744
  const sampleRate = this.config?.audio?.sample_rate ?? 22050;
35380
35745
  this.writeWav(audioData, sampleRate, destPath);
35381
35746
  this.luxttsCloneRef = destPath;
@@ -35391,11 +35756,11 @@ var init_voice = __esm({
35391
35756
  // -------------------------------------------------------------------------
35392
35757
  /** Metadata file for friendly names of clone refs */
35393
35758
  static cloneMetaFile() {
35394
- return join41(luxttsCloneRefsDir(), "meta.json");
35759
+ return join42(luxttsCloneRefsDir(), "meta.json");
35395
35760
  }
35396
35761
  loadCloneMeta() {
35397
35762
  const p = _VoiceEngine.cloneMetaFile();
35398
- if (!existsSync33(p))
35763
+ if (!existsSync34(p))
35399
35764
  return {};
35400
35765
  try {
35401
35766
  return JSON.parse(readFileSync23(p, "utf8"));
@@ -35405,7 +35770,7 @@ var init_voice = __esm({
35405
35770
  }
35406
35771
  saveCloneMeta(meta) {
35407
35772
  const dir = luxttsCloneRefsDir();
35408
- if (!existsSync33(dir))
35773
+ if (!existsSync34(dir))
35409
35774
  mkdirSync13(dir, { recursive: true });
35410
35775
  writeFileSync13(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
35411
35776
  }
@@ -35417,7 +35782,7 @@ var init_voice = __esm({
35417
35782
  */
35418
35783
  listCloneRefs() {
35419
35784
  const dir = luxttsCloneRefsDir();
35420
- if (!existsSync33(dir))
35785
+ if (!existsSync34(dir))
35421
35786
  return [];
35422
35787
  const meta = this.loadCloneMeta();
35423
35788
  const files = readdirSync9(dir).filter((f) => {
@@ -35425,7 +35790,7 @@ var init_voice = __esm({
35425
35790
  return _VoiceEngine.AUDIO_EXTS.has(ext);
35426
35791
  });
35427
35792
  return files.map((f) => {
35428
- const p = join41(dir, f);
35793
+ const p = join42(dir, f);
35429
35794
  let size = 0;
35430
35795
  try {
35431
35796
  size = statSync10(p).size;
@@ -35442,11 +35807,11 @@ var init_voice = __esm({
35442
35807
  }
35443
35808
  /** Delete a clone reference file by filename. Returns true if deleted. */
35444
35809
  deleteCloneRef(filename) {
35445
- const p = join41(luxttsCloneRefsDir(), filename);
35446
- if (!existsSync33(p))
35810
+ const p = join42(luxttsCloneRefsDir(), filename);
35811
+ if (!existsSync34(p))
35447
35812
  return false;
35448
35813
  try {
35449
- unlinkSync5(p);
35814
+ unlinkSync6(p);
35450
35815
  const meta = this.loadCloneMeta();
35451
35816
  delete meta[filename];
35452
35817
  this.saveCloneMeta(meta);
@@ -35467,8 +35832,8 @@ var init_voice = __esm({
35467
35832
  }
35468
35833
  /** Set the active clone reference by filename. */
35469
35834
  setActiveCloneRef(filename) {
35470
- const p = join41(luxttsCloneRefsDir(), filename);
35471
- if (!existsSync33(p))
35835
+ const p = join42(luxttsCloneRefsDir(), filename);
35836
+ if (!existsSync34(p))
35472
35837
  return `File not found: ${filename}`;
35473
35838
  this.luxttsCloneRef = p;
35474
35839
  return `Active clone voice set to: ${filename}`;
@@ -35753,11 +36118,11 @@ var init_voice = __esm({
35753
36118
  }
35754
36119
  this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
35755
36120
  }
35756
- const wavPath = join41(tmpdir6(), `oa-voice-${Date.now()}.wav`);
36121
+ const wavPath = join42(tmpdir7(), `oa-voice-${Date.now()}.wav`);
35757
36122
  this.writeWav(audioData, sampleRate, wavPath);
35758
36123
  await this.playWav(wavPath);
35759
36124
  try {
35760
- unlinkSync5(wavPath);
36125
+ unlinkSync6(wavPath);
35761
36126
  } catch {
35762
36127
  }
35763
36128
  }
@@ -35941,7 +36306,7 @@ var init_voice = __esm({
35941
36306
  }
35942
36307
  for (const player of ["paplay", "pw-play", "aplay"]) {
35943
36308
  try {
35944
- execSync26(`which ${player}`, { stdio: "pipe" });
36309
+ execSync27(`which ${player}`, { stdio: "pipe" });
35945
36310
  return [player, path];
35946
36311
  } catch {
35947
36312
  }
@@ -35970,7 +36335,7 @@ var init_voice = __esm({
35970
36335
  return this.python3Path;
35971
36336
  for (const bin of ["python3", "python"]) {
35972
36337
  try {
35973
- const path = execSync26(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
36338
+ const path = execSync27(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
35974
36339
  if (path) {
35975
36340
  this.python3Path = path;
35976
36341
  return path;
@@ -36002,7 +36367,7 @@ var init_voice = __esm({
36002
36367
  return new Promise((resolve32, reject) => {
36003
36368
  const proc = nodeSpawn("sh", ["-c", command], {
36004
36369
  stdio: ["ignore", "pipe", "pipe"],
36005
- cwd: tmpdir6()
36370
+ cwd: tmpdir7()
36006
36371
  });
36007
36372
  let stdout = "";
36008
36373
  let stderr = "";
@@ -36036,7 +36401,7 @@ var init_voice = __esm({
36036
36401
  return false;
36037
36402
  }
36038
36403
  try {
36039
- execSync26(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
36404
+ execSync27(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
36040
36405
  this.mlxInstalled = true;
36041
36406
  return true;
36042
36407
  } catch {
@@ -36060,7 +36425,7 @@ var init_voice = __esm({
36060
36425
  return;
36061
36426
  renderInfo("Installing MLX Audio for voice synthesis (first time setup)...");
36062
36427
  try {
36063
- execSync26(`${py} -m pip install mlx-audio --quiet`, {
36428
+ execSync27(`${py} -m pip install mlx-audio --quiet`, {
36064
36429
  stdio: "pipe",
36065
36430
  timeout: 3e5
36066
36431
  // 5 min — may need to compile
@@ -36068,7 +36433,7 @@ var init_voice = __esm({
36068
36433
  this.mlxInstalled = true;
36069
36434
  } catch (err) {
36070
36435
  try {
36071
- execSync26(`${py} -m pip install mlx-audio --user --quiet`, {
36436
+ execSync27(`${py} -m pip install mlx-audio --user --quiet`, {
36072
36437
  stdio: "pipe",
36073
36438
  timeout: 3e5
36074
36439
  });
@@ -36096,7 +36461,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36096
36461
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
36097
36462
  const mlxVoice = model.mlxVoice ?? "af_heart";
36098
36463
  const mlxLangCode = model.mlxLangCode ?? "a";
36099
- const wavPath = join41(tmpdir6(), `oa-mlx-${Date.now()}.wav`);
36464
+ const wavPath = join42(tmpdir7(), `oa-mlx-${Date.now()}.wav`);
36100
36465
  const pyScript = [
36101
36466
  "import sys, json",
36102
36467
  "from mlx_audio.tts import generate as tts_gen",
@@ -36104,16 +36469,16 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36104
36469
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
36105
36470
  ].join("; ");
36106
36471
  try {
36107
- execSync26(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
36472
+ execSync27(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir7() });
36108
36473
  } catch (err) {
36109
36474
  try {
36110
36475
  const safeText = cleaned.replace(/'/g, "'\\''");
36111
- execSync26(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
36476
+ execSync27(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir7() });
36112
36477
  } catch (err2) {
36113
36478
  return;
36114
36479
  }
36115
36480
  }
36116
- if (!existsSync33(wavPath))
36481
+ if (!existsSync34(wavPath))
36117
36482
  return;
36118
36483
  if (volume !== 1) {
36119
36484
  try {
@@ -36143,7 +36508,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36143
36508
  }
36144
36509
  await this.playWav(wavPath);
36145
36510
  try {
36146
- unlinkSync5(wavPath);
36511
+ unlinkSync6(wavPath);
36147
36512
  } catch {
36148
36513
  }
36149
36514
  }
@@ -36164,7 +36529,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36164
36529
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
36165
36530
  const mlxVoice = model.mlxVoice ?? "af_heart";
36166
36531
  const mlxLangCode = model.mlxLangCode ?? "a";
36167
- const wavPath = join41(tmpdir6(), `oa-mlx-buf-${Date.now()}.wav`);
36532
+ const wavPath = join42(tmpdir7(), `oa-mlx-buf-${Date.now()}.wav`);
36168
36533
  const pyScript = [
36169
36534
  "import sys, json",
36170
36535
  "from mlx_audio.tts import generate as tts_gen",
@@ -36172,20 +36537,20 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36172
36537
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
36173
36538
  ].join("; ");
36174
36539
  try {
36175
- execSync26(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
36540
+ execSync27(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir7() });
36176
36541
  } catch {
36177
36542
  try {
36178
36543
  const safeText = cleaned.replace(/'/g, "'\\''");
36179
- execSync26(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
36544
+ execSync27(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir7() });
36180
36545
  } catch {
36181
36546
  return null;
36182
36547
  }
36183
36548
  }
36184
- if (!existsSync33(wavPath))
36549
+ if (!existsSync34(wavPath))
36185
36550
  return null;
36186
36551
  try {
36187
36552
  const data = readFileSync23(wavPath);
36188
- unlinkSync5(wavPath);
36553
+ unlinkSync6(wavPath);
36189
36554
  return data;
36190
36555
  } catch {
36191
36556
  return null;
@@ -36207,7 +36572,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36207
36572
  }
36208
36573
  const venvDir = luxttsVenvDir();
36209
36574
  const venvPy = luxttsVenvPy();
36210
- if (existsSync33(venvPy)) {
36575
+ if (existsSync34(venvPy)) {
36211
36576
  try {
36212
36577
  await this.asyncShell(`${venvPy} -c "import sys; sys.path.insert(0, '${luxttsRepoDir()}'); from zipvoice.luxvoice import LuxTTS; print('ok')"`, 3e4);
36213
36578
  let hasCudaSys = false;
@@ -36237,7 +36602,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36237
36602
  }
36238
36603
  }
36239
36604
  renderInfo("Setting up LuxTTS voice cloning (first-time setup, this takes several minutes)...");
36240
- if (!existsSync33(venvDir)) {
36605
+ if (!existsSync34(venvDir)) {
36241
36606
  renderInfo(" Creating Python virtual environment...");
36242
36607
  try {
36243
36608
  await this.asyncShell(`${py} -m venv ${JSON.stringify(venvDir)}`, 6e4);
@@ -36275,10 +36640,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36275
36640
  }
36276
36641
  }
36277
36642
  const repoDir = luxttsRepoDir();
36278
- if (!existsSync33(join41(repoDir, "zipvoice", "luxvoice.py"))) {
36643
+ if (!existsSync34(join42(repoDir, "zipvoice", "luxvoice.py"))) {
36279
36644
  renderInfo(" Cloning LuxTTS repository...");
36280
36645
  try {
36281
- if (existsSync33(repoDir)) {
36646
+ if (existsSync34(repoDir)) {
36282
36647
  await this.asyncShell(`rm -rf ${JSON.stringify(repoDir)}`, 3e4);
36283
36648
  }
36284
36649
  await this.asyncShell(`git clone --depth 1 https://github.com/ysharma3501/LuxTTS.git ${JSON.stringify(repoDir)}`, 12e4);
@@ -36318,14 +36683,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
36318
36683
  }
36319
36684
  /** Auto-detect an existing clone reference in the refs directory */
36320
36685
  autoDetectCloneRef() {
36321
- if (this.luxttsCloneRef && existsSync33(this.luxttsCloneRef))
36686
+ if (this.luxttsCloneRef && existsSync34(this.luxttsCloneRef))
36322
36687
  return;
36323
36688
  const refsDir = luxttsCloneRefsDir();
36324
- if (!existsSync33(refsDir))
36689
+ if (!existsSync34(refsDir))
36325
36690
  return;
36326
36691
  for (const name of ["custom-clone.wav", "custom-clone.mp3", "glados-ref.wav", "overwatch-ref.wav"]) {
36327
- const p = join41(refsDir, name);
36328
- if (existsSync33(p)) {
36692
+ const p = join42(refsDir, name);
36693
+ if (existsSync34(p)) {
36329
36694
  this.luxttsCloneRef = p;
36330
36695
  return;
36331
36696
  }
@@ -36433,13 +36798,13 @@ if __name__ == '__main__':
36433
36798
  if (this._luxttsDaemon && !this._luxttsDaemon.killed)
36434
36799
  return true;
36435
36800
  const venvPy = luxttsVenvPy();
36436
- if (!existsSync33(venvPy))
36801
+ if (!existsSync34(venvPy))
36437
36802
  return false;
36438
36803
  return new Promise((resolve32) => {
36439
36804
  const env = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
36440
36805
  const daemon = nodeSpawn(venvPy, [luxttsInferScript()], {
36441
36806
  stdio: ["pipe", "pipe", "pipe"],
36442
- cwd: tmpdir6(),
36807
+ cwd: tmpdir7(),
36443
36808
  env
36444
36809
  });
36445
36810
  this._luxttsDaemon = daemon;
@@ -36512,7 +36877,7 @@ if __name__ == '__main__':
36512
36877
  * Volume is applied via WAV sample scaling.
36513
36878
  */
36514
36879
  async synthesizeWithLuxtts(text, volume = 1, pitchFactor = 1, speedFactor = 1) {
36515
- if (!this.luxttsCloneRef || !existsSync33(this.luxttsCloneRef)) {
36880
+ if (!this.luxttsCloneRef || !existsSync34(this.luxttsCloneRef)) {
36516
36881
  return;
36517
36882
  }
36518
36883
  const cleaned = text.replace(/\*/g, "").trim();
@@ -36521,7 +36886,7 @@ if __name__ == '__main__':
36521
36886
  const ready = await this.ensureLuxttsDaemon();
36522
36887
  if (!ready)
36523
36888
  return;
36524
- const wavPath = join41(tmpdir6(), `oa-luxtts-${Date.now()}.wav`);
36889
+ const wavPath = join42(tmpdir7(), `oa-luxtts-${Date.now()}.wav`);
36525
36890
  try {
36526
36891
  await this.luxttsRequest({
36527
36892
  action: "synthesize",
@@ -36533,7 +36898,7 @@ if __name__ == '__main__':
36533
36898
  } catch {
36534
36899
  return;
36535
36900
  }
36536
- if (!existsSync33(wavPath))
36901
+ if (!existsSync34(wavPath))
36537
36902
  return;
36538
36903
  if (volume !== 1) {
36539
36904
  try {
@@ -36578,7 +36943,7 @@ if __name__ == '__main__':
36578
36943
  }
36579
36944
  await this.playWav(wavPath);
36580
36945
  try {
36581
- unlinkSync5(wavPath);
36946
+ unlinkSync6(wavPath);
36582
36947
  } catch {
36583
36948
  }
36584
36949
  }
@@ -36587,7 +36952,7 @@ if __name__ == '__main__':
36587
36952
  * Used for Telegram voice messages and WebSocket streaming.
36588
36953
  */
36589
36954
  async synthesizeLuxttsToBuffer(text) {
36590
- if (!this.luxttsCloneRef || !existsSync33(this.luxttsCloneRef))
36955
+ if (!this.luxttsCloneRef || !existsSync34(this.luxttsCloneRef))
36591
36956
  return null;
36592
36957
  const cleaned = text.replace(/\*/g, "").trim();
36593
36958
  if (!cleaned)
@@ -36595,7 +36960,7 @@ if __name__ == '__main__':
36595
36960
  const ready = await this.ensureLuxttsDaemon();
36596
36961
  if (!ready)
36597
36962
  return null;
36598
- const wavPath = join41(tmpdir6(), `oa-luxtts-buf-${Date.now()}.wav`);
36963
+ const wavPath = join42(tmpdir7(), `oa-luxtts-buf-${Date.now()}.wav`);
36599
36964
  try {
36600
36965
  await this.luxttsRequest({
36601
36966
  action: "synthesize",
@@ -36607,11 +36972,11 @@ if __name__ == '__main__':
36607
36972
  } catch {
36608
36973
  return null;
36609
36974
  }
36610
- if (!existsSync33(wavPath))
36975
+ if (!existsSync34(wavPath))
36611
36976
  return null;
36612
36977
  try {
36613
36978
  const data = readFileSync23(wavPath);
36614
- unlinkSync5(wavPath);
36979
+ unlinkSync6(wavPath);
36615
36980
  return data;
36616
36981
  } catch {
36617
36982
  return null;
@@ -36625,12 +36990,12 @@ if __name__ == '__main__':
36625
36990
  return;
36626
36991
  const arch = process.arch;
36627
36992
  mkdirSync13(voiceDir(), { recursive: true });
36628
- const pkgPath = join41(voiceDir(), "package.json");
36993
+ const pkgPath = join42(voiceDir(), "package.json");
36629
36994
  const expectedDeps = {
36630
36995
  "onnxruntime-node": "^1.21.0",
36631
36996
  "phonemizer": "^1.2.1"
36632
36997
  };
36633
- if (existsSync33(pkgPath)) {
36998
+ if (existsSync34(pkgPath)) {
36634
36999
  try {
36635
37000
  const existing = JSON.parse(readFileSync23(pkgPath, "utf8"));
36636
37001
  if (!existing.dependencies?.["phonemizer"]) {
@@ -36640,25 +37005,25 @@ if __name__ == '__main__':
36640
37005
  } catch {
36641
37006
  }
36642
37007
  }
36643
- if (!existsSync33(pkgPath)) {
37008
+ if (!existsSync34(pkgPath)) {
36644
37009
  writeFileSync13(pkgPath, JSON.stringify({
36645
37010
  name: "open-agents-voice",
36646
37011
  private: true,
36647
37012
  dependencies: expectedDeps
36648
37013
  }, null, 2));
36649
37014
  }
36650
- const voiceRequire = createRequire(join41(voiceDir(), "index.js"));
37015
+ const voiceRequire = createRequire(join42(voiceDir(), "index.js"));
36651
37016
  const probeOnnx = () => {
36652
37017
  try {
36653
- const result = execSync26(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join41(voiceDir(), "node_modules") } });
37018
+ const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join42(voiceDir(), "node_modules") } });
36654
37019
  const output = result.toString().trim();
36655
37020
  return output === "OK";
36656
37021
  } catch {
36657
37022
  return false;
36658
37023
  }
36659
37024
  };
36660
- const onnxNodeModules = join41(voiceDir(), "node_modules", "onnxruntime-node");
36661
- const onnxInstalled = existsSync33(onnxNodeModules);
37025
+ const onnxNodeModules = join42(voiceDir(), "node_modules", "onnxruntime-node");
37026
+ const onnxInstalled = existsSync34(onnxNodeModules);
36662
37027
  if (onnxInstalled && !probeOnnx()) {
36663
37028
  throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
36664
37029
  }
@@ -36667,7 +37032,7 @@ if __name__ == '__main__':
36667
37032
  } catch {
36668
37033
  renderInfo("Installing ONNX runtime for voice synthesis...");
36669
37034
  try {
36670
- execSync26("npm install --no-audit --no-fund", {
37035
+ execSync27("npm install --no-audit --no-fund", {
36671
37036
  cwd: voiceDir(),
36672
37037
  stdio: "pipe",
36673
37038
  timeout: 12e4
@@ -36692,7 +37057,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
36692
37057
  } catch {
36693
37058
  renderInfo("Installing phonemizer for voice synthesis...");
36694
37059
  try {
36695
- execSync26("npm install --no-audit --no-fund", {
37060
+ execSync27("npm install --no-audit --no-fund", {
36696
37061
  cwd: voiceDir(),
36697
37062
  stdio: "pipe",
36698
37063
  timeout: 12e4
@@ -36716,10 +37081,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
36716
37081
  const dir = modelDir(id);
36717
37082
  const onnxPath = modelOnnxPath(id);
36718
37083
  const configPath = modelConfigPath(id);
36719
- if (existsSync33(onnxPath) && existsSync33(configPath))
37084
+ if (existsSync34(onnxPath) && existsSync34(configPath))
36720
37085
  return;
36721
37086
  mkdirSync13(dir, { recursive: true });
36722
- if (!existsSync33(configPath)) {
37087
+ if (!existsSync34(configPath)) {
36723
37088
  renderInfo(`Downloading ${model.label} voice config...`);
36724
37089
  const configResp = await fetch(model.configUrl);
36725
37090
  if (!configResp.ok)
@@ -36727,7 +37092,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
36727
37092
  const configText = await configResp.text();
36728
37093
  writeFileSync13(configPath, configText);
36729
37094
  }
36730
- if (!existsSync33(onnxPath)) {
37095
+ if (!existsSync34(onnxPath)) {
36731
37096
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
36732
37097
  const onnxResp = await fetch(model.onnxUrl);
36733
37098
  if (!onnxResp.ok)
@@ -36764,7 +37129,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
36764
37129
  throw new Error("ONNX runtime not loaded");
36765
37130
  const onnxPath = modelOnnxPath(this.modelId);
36766
37131
  const configPath = modelConfigPath(this.modelId);
36767
- if (!existsSync33(onnxPath) || !existsSync33(configPath)) {
37132
+ if (!existsSync34(onnxPath) || !existsSync34(configPath)) {
36768
37133
  throw new Error(`Model files not found for ${this.modelId}`);
36769
37134
  }
36770
37135
  this.config = JSON.parse(readFileSync23(configPath, "utf8"));
@@ -37438,6 +37803,33 @@ async function handleSlashCommand(input, ctx) {
37438
37803
  }
37439
37804
  return "handled";
37440
37805
  }
37806
+ case "neovim":
37807
+ case "nvim":
37808
+ case "vim": {
37809
+ if (isNeovimActive()) {
37810
+ stopNeovimMode();
37811
+ renderInfo("Neovim mode stopped.");
37812
+ } else {
37813
+ const contentRows = ctx.availableContentRows?.() ?? Math.max(5, (process.stdout.rows ?? 24) - 6);
37814
+ const cols = process.stdout.columns ?? 80;
37815
+ const err = await startNeovimMode({
37816
+ cwd: ctx.repoRoot,
37817
+ contentRows,
37818
+ cols,
37819
+ rl: ctx.rl,
37820
+ initialFile: arg || void 0,
37821
+ onExit: () => {
37822
+ renderInfo("Neovim mode exited.");
37823
+ }
37824
+ });
37825
+ if (err) {
37826
+ renderError(err);
37827
+ } else {
37828
+ renderInfo("Neovim mode started. Ctrl+N toggles focus between editor and input.");
37829
+ }
37830
+ }
37831
+ return "handled";
37832
+ }
37441
37833
  case "dream": {
37442
37834
  if (arg === "stop" || arg === "wake") {
37443
37835
  if (ctx.isDreaming?.()) {
@@ -38960,8 +39352,8 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
38960
39352
  if (models.length > 0) {
38961
39353
  try {
38962
39354
  const { writeFileSync: writeFileSync19, mkdirSync: mkdirSync21 } = await import("node:fs");
38963
- const { join: join55, dirname: dirname20 } = await import("node:path");
38964
- const cachePath = join55(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
39355
+ const { join: join56, dirname: dirname20 } = await import("node:path");
39356
+ const cachePath = join56(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
38965
39357
  mkdirSync21(dirname20(cachePath), { recursive: true });
38966
39358
  writeFileSync19(cachePath, JSON.stringify({
38967
39359
  peerId,
@@ -39012,7 +39404,7 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
39012
39404
  }
39013
39405
  }
39014
39406
  async function handleParallel(arg, ctx) {
39015
- const { execSync: execSync29 } = await import("node:child_process");
39407
+ const { execSync: execSync30 } = await import("node:child_process");
39016
39408
  const baseUrl = ctx.config.backendUrl || "http://localhost:11434";
39017
39409
  const isRemote = ctx.config.backendType === "nexus";
39018
39410
  if (isRemote) {
@@ -39036,7 +39428,7 @@ async function handleParallel(arg, ctx) {
39036
39428
  }
39037
39429
  let systemdVal = "";
39038
39430
  try {
39039
- const out = execSync29("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
39431
+ const out = execSync30("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
39040
39432
  const match = out.match(/OLLAMA_NUM_PARALLEL=(\d+)/);
39041
39433
  if (match)
39042
39434
  systemdVal = match[1];
@@ -39065,7 +39457,7 @@ async function handleParallel(arg, ctx) {
39065
39457
  }
39066
39458
  const isSystemd = (() => {
39067
39459
  try {
39068
- const out = execSync29("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
39460
+ const out = execSync30("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
39069
39461
  return out === "active" || out === "inactive";
39070
39462
  } catch {
39071
39463
  return false;
@@ -39079,10 +39471,10 @@ async function handleParallel(arg, ctx) {
39079
39471
  const overrideContent = `[Service]
39080
39472
  Environment="OLLAMA_NUM_PARALLEL=${n}"
39081
39473
  `;
39082
- execSync29(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
39083
- execSync29(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
39084
- execSync29("sudo systemctl daemon-reload", { stdio: "pipe" });
39085
- execSync29("sudo systemctl restart ollama.service", { stdio: "pipe" });
39474
+ execSync30(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
39475
+ execSync30(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
39476
+ execSync30("sudo systemctl daemon-reload", { stdio: "pipe" });
39477
+ execSync30("sudo systemctl restart ollama.service", { stdio: "pipe" });
39086
39478
  let ready = false;
39087
39479
  for (let i = 0; i < 30 && !ready; i++) {
39088
39480
  await new Promise((r) => setTimeout(r, 500));
@@ -39109,7 +39501,7 @@ Environment="OLLAMA_NUM_PARALLEL=${n}"
39109
39501
  renderInfo(`Setting OLLAMA_NUM_PARALLEL=${n}...`);
39110
39502
  try {
39111
39503
  try {
39112
- execSync29("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
39504
+ execSync30("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
39113
39505
  } catch {
39114
39506
  }
39115
39507
  await new Promise((r) => setTimeout(r, 1e3));
@@ -39162,17 +39554,17 @@ async function handleUpdate(subcommand, ctx) {
39162
39554
  try {
39163
39555
  const { createRequire: createRequire4 } = await import("node:module");
39164
39556
  const { fileURLToPath: fileURLToPath14 } = await import("node:url");
39165
- const { dirname: dirname20, join: join55 } = await import("node:path");
39166
- const { existsSync: existsSync43 } = await import("node:fs");
39557
+ const { dirname: dirname20, join: join56 } = await import("node:path");
39558
+ const { existsSync: existsSync44 } = await import("node:fs");
39167
39559
  const req = createRequire4(import.meta.url);
39168
39560
  const thisDir = dirname20(fileURLToPath14(import.meta.url));
39169
39561
  const candidates = [
39170
- join55(thisDir, "..", "package.json"),
39171
- join55(thisDir, "..", "..", "package.json"),
39172
- join55(thisDir, "..", "..", "..", "package.json")
39562
+ join56(thisDir, "..", "package.json"),
39563
+ join56(thisDir, "..", "..", "package.json"),
39564
+ join56(thisDir, "..", "..", "..", "package.json")
39173
39565
  ];
39174
39566
  for (const pkgPath of candidates) {
39175
- if (existsSync43(pkgPath)) {
39567
+ if (existsSync44(pkgPath)) {
39176
39568
  const pkg = req(pkgPath);
39177
39569
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
39178
39570
  currentVersion = pkg.version ?? "0.0.0";
@@ -39503,8 +39895,8 @@ function getLocalSystemMetrics() {
39503
39895
  vramUtil: 0
39504
39896
  };
39505
39897
  try {
39506
- const { execSync: execSync29 } = __require("node:child_process");
39507
- const smiOut = execSync29("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 });
39898
+ const { execSync: execSync30 } = __require("node:child_process");
39899
+ const smiOut = execSync30("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 });
39508
39900
  const line = smiOut.trim().split("\n")[0];
39509
39901
  if (line) {
39510
39902
  const parts = line.split(",").map((s) => s.trim());
@@ -39730,14 +40122,15 @@ var init_commands = __esm({
39730
40122
  init_dist();
39731
40123
  init_tui_select();
39732
40124
  init_drop_panel();
40125
+ init_neovim_mode();
39733
40126
  DASH_INTERNAL = /* @__PURE__ */ new Set(["system_metrics", "__list_capabilities"]);
39734
40127
  }
39735
40128
  });
39736
40129
 
39737
40130
  // packages/cli/dist/tui/project-context.js
39738
- import { existsSync as existsSync34, readFileSync as readFileSync24, readdirSync as readdirSync10 } from "node:fs";
39739
- import { join as join42, basename as basename10 } from "node:path";
39740
- import { execSync as execSync27 } from "node:child_process";
40131
+ import { existsSync as existsSync35, readFileSync as readFileSync24, readdirSync as readdirSync10 } from "node:fs";
40132
+ import { join as join43, basename as basename10 } from "node:path";
40133
+ import { execSync as execSync28 } from "node:child_process";
39741
40134
  import { homedir as homedir12, platform as platform3, release } from "node:os";
39742
40135
  function getModelTier(modelName) {
39743
40136
  const m = modelName.toLowerCase();
@@ -39771,8 +40164,8 @@ function loadProjectMap(repoRoot) {
39771
40164
  if (!hasOaDirectory(repoRoot)) {
39772
40165
  initOaDirectory(repoRoot);
39773
40166
  }
39774
- const mapPath = join42(repoRoot, OA_DIR, "context", "project-map.md");
39775
- if (existsSync34(mapPath)) {
40167
+ const mapPath = join43(repoRoot, OA_DIR, "context", "project-map.md");
40168
+ if (existsSync35(mapPath)) {
39776
40169
  try {
39777
40170
  const content = readFileSync24(mapPath, "utf-8");
39778
40171
  return content;
@@ -39783,19 +40176,19 @@ function loadProjectMap(repoRoot) {
39783
40176
  }
39784
40177
  function getGitInfo(repoRoot) {
39785
40178
  try {
39786
- execSync27("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
40179
+ execSync28("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
39787
40180
  } catch {
39788
40181
  return "";
39789
40182
  }
39790
40183
  const lines = [];
39791
40184
  try {
39792
- const branch = execSync27("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
40185
+ const branch = execSync28("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
39793
40186
  if (branch)
39794
40187
  lines.push(`Branch: ${branch}`);
39795
40188
  } catch {
39796
40189
  }
39797
40190
  try {
39798
- const status = execSync27("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
40191
+ const status = execSync28("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
39799
40192
  if (status) {
39800
40193
  const changed = status.split("\n").length;
39801
40194
  lines.push(`Working tree: ${changed} changed file(s)`);
@@ -39805,7 +40198,7 @@ function getGitInfo(repoRoot) {
39805
40198
  } catch {
39806
40199
  }
39807
40200
  try {
39808
- const log = execSync27("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
40201
+ const log = execSync28("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
39809
40202
  if (log)
39810
40203
  lines.push(`Recent commits:
39811
40204
  ${log}`);
@@ -39815,31 +40208,31 @@ ${log}`);
39815
40208
  }
39816
40209
  function loadMemoryContext(repoRoot) {
39817
40210
  const sections = [];
39818
- const oaMemDir = join42(repoRoot, OA_DIR, "memory");
40211
+ const oaMemDir = join43(repoRoot, OA_DIR, "memory");
39819
40212
  const oaEntries = loadMemoryDir(oaMemDir, "project");
39820
40213
  if (oaEntries)
39821
40214
  sections.push(oaEntries);
39822
- const legacyMemDir = join42(repoRoot, ".open-agents", "memory");
39823
- if (legacyMemDir !== oaMemDir && existsSync34(legacyMemDir)) {
40215
+ const legacyMemDir = join43(repoRoot, ".open-agents", "memory");
40216
+ if (legacyMemDir !== oaMemDir && existsSync35(legacyMemDir)) {
39824
40217
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
39825
40218
  if (legacyEntries)
39826
40219
  sections.push(legacyEntries);
39827
40220
  }
39828
- const globalMemDir = join42(homedir12(), ".open-agents", "memory");
40221
+ const globalMemDir = join43(homedir12(), ".open-agents", "memory");
39829
40222
  const globalEntries = loadMemoryDir(globalMemDir, "global");
39830
40223
  if (globalEntries)
39831
40224
  sections.push(globalEntries);
39832
40225
  return sections.join("\n\n");
39833
40226
  }
39834
40227
  function loadMemoryDir(memDir, scope) {
39835
- if (!existsSync34(memDir))
40228
+ if (!existsSync35(memDir))
39836
40229
  return "";
39837
40230
  const lines = [];
39838
40231
  try {
39839
40232
  const files = readdirSync10(memDir).filter((f) => f.endsWith(".json"));
39840
40233
  for (const file of files.slice(0, 10)) {
39841
40234
  try {
39842
- const raw = readFileSync24(join42(memDir, file), "utf-8");
40235
+ const raw = readFileSync24(join43(memDir, file), "utf-8");
39843
40236
  const entries = JSON.parse(raw);
39844
40237
  const topic = basename10(file, ".json");
39845
40238
  const keys = Object.keys(entries);
@@ -40580,7 +40973,7 @@ var init_dist7 = __esm({
40580
40973
 
40581
40974
  // packages/cli/dist/tui/carousel.js
40582
40975
  function fg(code, text) {
40583
- return isTTY5 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
40976
+ return isTTY6 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
40584
40977
  }
40585
40978
  function displayWidth(str) {
40586
40979
  let w = 0;
@@ -40618,11 +41011,11 @@ function createRow(phraseIndices, speed, direction, bank) {
40618
41011
  const phrases = phraseIndices.map((i) => bank[i % bank.length]);
40619
41012
  return { phrases, offset: 0, speed, direction, renderedPlain: "" };
40620
41013
  }
40621
- var isTTY5, PHRASES, Carousel;
41014
+ var isTTY6, PHRASES, Carousel;
40622
41015
  var init_carousel = __esm({
40623
41016
  "packages/cli/dist/tui/carousel.js"() {
40624
41017
  "use strict";
40625
- isTTY5 = process.stdout.isTTY ?? false;
41018
+ isTTY6 = process.stdout.isTTY ?? false;
40626
41019
  PHRASES = [
40627
41020
  // English
40628
41021
  { text: "freedom of information", color: 39 },
@@ -40731,7 +41124,7 @@ var init_carousel = __esm({
40731
41124
  * Sets scroll region to row 5+ for all content/readline.
40732
41125
  */
40733
41126
  start() {
40734
- if (!isTTY5)
41127
+ if (!isTTY6)
40735
41128
  return 0;
40736
41129
  this.started = true;
40737
41130
  const termRows = process.stdout.rows ?? 24;
@@ -40763,7 +41156,7 @@ var init_carousel = __esm({
40763
41156
  * Row 4 is left blank as a separator.
40764
41157
  */
40765
41158
  renderFrame() {
40766
- if (!isTTY5)
41159
+ if (!isTTY6)
40767
41160
  return;
40768
41161
  let buf = "\x1B7";
40769
41162
  buf += "\x1B[?7l";
@@ -40843,7 +41236,7 @@ var init_carousel = __esm({
40843
41236
  process.stdout.removeListener("resize", this.resizeHandler);
40844
41237
  this.resizeHandler = null;
40845
41238
  }
40846
- if (!isTTY5 || !this.started)
41239
+ if (!isTTY6 || !this.started)
40847
41240
  return;
40848
41241
  let buf = "\x1B7";
40849
41242
  for (let i = 0; i < this.reservedRows; i++) {
@@ -40862,12 +41255,12 @@ var init_carousel = __esm({
40862
41255
  });
40863
41256
 
40864
41257
  // packages/cli/dist/tui/carousel-descriptors.js
40865
- import { existsSync as existsSync35, readFileSync as readFileSync25, writeFileSync as writeFileSync14, mkdirSync as mkdirSync14, readdirSync as readdirSync11 } from "node:fs";
40866
- import { join as join43, basename as basename11 } from "node:path";
41258
+ import { existsSync as existsSync36, readFileSync as readFileSync25, writeFileSync as writeFileSync14, mkdirSync as mkdirSync14, readdirSync as readdirSync11 } from "node:fs";
41259
+ import { join as join44, basename as basename11 } from "node:path";
40867
41260
  function loadToolProfile(repoRoot) {
40868
- const filePath = join43(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
41261
+ const filePath = join44(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
40869
41262
  try {
40870
- if (!existsSync35(filePath))
41263
+ if (!existsSync36(filePath))
40871
41264
  return null;
40872
41265
  return JSON.parse(readFileSync25(filePath, "utf-8"));
40873
41266
  } catch {
@@ -40875,9 +41268,9 @@ function loadToolProfile(repoRoot) {
40875
41268
  }
40876
41269
  }
40877
41270
  function saveToolProfile(repoRoot, profile) {
40878
- const contextDir = join43(repoRoot, OA_DIR, "context");
41271
+ const contextDir = join44(repoRoot, OA_DIR, "context");
40879
41272
  mkdirSync14(contextDir, { recursive: true });
40880
- writeFileSync14(join43(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
41273
+ writeFileSync14(join44(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
40881
41274
  }
40882
41275
  function categorizeToolCall(toolName) {
40883
41276
  for (const cat of TOOL_CATEGORIES) {
@@ -40935,9 +41328,9 @@ function weightedColor(profile) {
40935
41328
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
40936
41329
  }
40937
41330
  function loadCachedDescriptors(repoRoot) {
40938
- const filePath = join43(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
41331
+ const filePath = join44(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
40939
41332
  try {
40940
- if (!existsSync35(filePath))
41333
+ if (!existsSync36(filePath))
40941
41334
  return null;
40942
41335
  const cached = JSON.parse(readFileSync25(filePath, "utf-8"));
40943
41336
  return cached.phrases.length > 0 ? cached.phrases : null;
@@ -40946,14 +41339,14 @@ function loadCachedDescriptors(repoRoot) {
40946
41339
  }
40947
41340
  }
40948
41341
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
40949
- const contextDir = join43(repoRoot, OA_DIR, "context");
41342
+ const contextDir = join44(repoRoot, OA_DIR, "context");
40950
41343
  mkdirSync14(contextDir, { recursive: true });
40951
41344
  const cached = {
40952
41345
  phrases,
40953
41346
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
40954
41347
  sourceHash
40955
41348
  };
40956
- writeFileSync14(join43(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
41349
+ writeFileSync14(join44(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
40957
41350
  }
40958
41351
  function generateDescriptors(repoRoot) {
40959
41352
  const profile = loadToolProfile(repoRoot);
@@ -41001,9 +41394,9 @@ function generateDescriptors(repoRoot) {
41001
41394
  return phrases;
41002
41395
  }
41003
41396
  function extractFromPackageJson(repoRoot, tags) {
41004
- const pkgPath = join43(repoRoot, "package.json");
41397
+ const pkgPath = join44(repoRoot, "package.json");
41005
41398
  try {
41006
- if (!existsSync35(pkgPath))
41399
+ if (!existsSync36(pkgPath))
41007
41400
  return;
41008
41401
  const pkg = JSON.parse(readFileSync25(pkgPath, "utf-8"));
41009
41402
  if (pkg.name && typeof pkg.name === "string") {
@@ -41049,7 +41442,7 @@ function extractFromManifests(repoRoot, tags) {
41049
41442
  { file: ".github/workflows", tag: "ci/cd" }
41050
41443
  ];
41051
41444
  for (const check of manifestChecks) {
41052
- if (existsSync35(join43(repoRoot, check.file))) {
41445
+ if (existsSync36(join44(repoRoot, check.file))) {
41053
41446
  tags.push(check.tag);
41054
41447
  }
41055
41448
  }
@@ -41071,16 +41464,16 @@ function extractFromSessions(repoRoot, tags) {
41071
41464
  }
41072
41465
  }
41073
41466
  function extractFromMemory(repoRoot, tags) {
41074
- const memoryDir = join43(repoRoot, OA_DIR, "memory");
41467
+ const memoryDir = join44(repoRoot, OA_DIR, "memory");
41075
41468
  try {
41076
- if (!existsSync35(memoryDir))
41469
+ if (!existsSync36(memoryDir))
41077
41470
  return;
41078
41471
  const files = readdirSync11(memoryDir).filter((f) => f.endsWith(".json"));
41079
41472
  for (const file of files) {
41080
41473
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
41081
41474
  tags.push(topic);
41082
41475
  try {
41083
- const data = JSON.parse(readFileSync25(join43(memoryDir, file), "utf-8"));
41476
+ const data = JSON.parse(readFileSync25(join44(memoryDir, file), "utf-8"));
41084
41477
  if (data && typeof data === "object") {
41085
41478
  const keys = Object.keys(data).slice(0, 3);
41086
41479
  for (const key of keys) {
@@ -41216,25 +41609,25 @@ var init_carousel_descriptors = __esm({
41216
41609
 
41217
41610
  // packages/cli/dist/tui/stream-renderer.js
41218
41611
  function fg2563(code, text) {
41219
- return isTTY6 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
41612
+ return isTTY7 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
41220
41613
  }
41221
41614
  function dimText(text) {
41222
- return isTTY6 ? `\x1B[2m${text}\x1B[0m` : text;
41615
+ return isTTY7 ? `\x1B[2m${text}\x1B[0m` : text;
41223
41616
  }
41224
41617
  function italicText(text) {
41225
- return isTTY6 ? `\x1B[3m${text}\x1B[0m` : text;
41618
+ return isTTY7 ? `\x1B[3m${text}\x1B[0m` : text;
41226
41619
  }
41227
41620
  function dimItalic(text) {
41228
- return isTTY6 ? `\x1B[2;3m${text}\x1B[0m` : text;
41621
+ return isTTY7 ? `\x1B[2;3m${text}\x1B[0m` : text;
41229
41622
  }
41230
41623
  function boldText(text) {
41231
- return isTTY6 ? `\x1B[1m${text}\x1B[0m` : text;
41624
+ return isTTY7 ? `\x1B[1m${text}\x1B[0m` : text;
41232
41625
  }
41233
- var isTTY6, PASTEL, StreamRenderer;
41626
+ var isTTY7, PASTEL, StreamRenderer;
41234
41627
  var init_stream_renderer = __esm({
41235
41628
  "packages/cli/dist/tui/stream-renderer.js"() {
41236
41629
  "use strict";
41237
- isTTY6 = process.stdout.isTTY ?? false;
41630
+ isTTY7 = process.stdout.isTTY ?? false;
41238
41631
  PASTEL = {
41239
41632
  key: 222,
41240
41633
  // light gold — JSON keys
@@ -41703,10 +42096,10 @@ var init_stream_renderer = __esm({
41703
42096
 
41704
42097
  // packages/cli/dist/tui/edit-history.js
41705
42098
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync15 } from "node:fs";
41706
- import { join as join44 } from "node:path";
42099
+ import { join as join45 } from "node:path";
41707
42100
  function createEditHistoryLogger(repoRoot, sessionId) {
41708
- const historyDir = join44(repoRoot, ".oa", "history");
41709
- const logPath = join44(historyDir, "edits.jsonl");
42101
+ const historyDir = join45(repoRoot, ".oa", "history");
42102
+ const logPath = join45(historyDir, "edits.jsonl");
41710
42103
  try {
41711
42104
  mkdirSync15(historyDir, { recursive: true });
41712
42105
  } catch {
@@ -41817,14 +42210,14 @@ var init_edit_history = __esm({
41817
42210
  });
41818
42211
 
41819
42212
  // packages/cli/dist/tui/promptLoader.js
41820
- import { readFileSync as readFileSync26, existsSync as existsSync36 } from "node:fs";
41821
- import { join as join45, dirname as dirname17 } from "node:path";
42213
+ import { readFileSync as readFileSync26, existsSync as existsSync37 } from "node:fs";
42214
+ import { join as join46, dirname as dirname17 } from "node:path";
41822
42215
  import { fileURLToPath as fileURLToPath11 } from "node:url";
41823
42216
  function loadPrompt3(promptPath, vars) {
41824
42217
  let content = cache3.get(promptPath);
41825
42218
  if (content === void 0) {
41826
- const fullPath = join45(PROMPTS_DIR3, promptPath);
41827
- if (!existsSync36(fullPath)) {
42219
+ const fullPath = join46(PROMPTS_DIR3, promptPath);
42220
+ if (!existsSync37(fullPath)) {
41828
42221
  throw new Error(`Prompt file not found: ${fullPath}`);
41829
42222
  }
41830
42223
  content = readFileSync26(fullPath, "utf-8");
@@ -41840,20 +42233,20 @@ var init_promptLoader3 = __esm({
41840
42233
  "use strict";
41841
42234
  __filename3 = fileURLToPath11(import.meta.url);
41842
42235
  __dirname6 = dirname17(__filename3);
41843
- devPath2 = join45(__dirname6, "..", "..", "prompts");
41844
- publishedPath2 = join45(__dirname6, "..", "prompts");
41845
- PROMPTS_DIR3 = existsSync36(devPath2) ? devPath2 : publishedPath2;
42236
+ devPath2 = join46(__dirname6, "..", "..", "prompts");
42237
+ publishedPath2 = join46(__dirname6, "..", "prompts");
42238
+ PROMPTS_DIR3 = existsSync37(devPath2) ? devPath2 : publishedPath2;
41846
42239
  cache3 = /* @__PURE__ */ new Map();
41847
42240
  }
41848
42241
  });
41849
42242
 
41850
42243
  // packages/cli/dist/tui/dream-engine.js
41851
- import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync15, readFileSync as readFileSync27, existsSync as existsSync37, cpSync, rmSync, readdirSync as readdirSync12 } from "node:fs";
41852
- import { join as join46, basename as basename12 } from "node:path";
41853
- import { execSync as execSync28 } from "node:child_process";
42244
+ import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync15, readFileSync as readFileSync27, existsSync as existsSync38, cpSync, rmSync, readdirSync as readdirSync12 } from "node:fs";
42245
+ import { join as join47, basename as basename12 } from "node:path";
42246
+ import { execSync as execSync29 } from "node:child_process";
41854
42247
  function loadAutoresearchMemory(repoRoot) {
41855
- const memoryPath = join46(repoRoot, ".oa", "memory", "autoresearch.json");
41856
- if (!existsSync37(memoryPath))
42248
+ const memoryPath = join47(repoRoot, ".oa", "memory", "autoresearch.json");
42249
+ if (!existsSync38(memoryPath))
41857
42250
  return "";
41858
42251
  try {
41859
42252
  const raw = readFileSync27(memoryPath, "utf-8");
@@ -42046,12 +42439,12 @@ var init_dream_engine = __esm({
42046
42439
  const content = String(args["content"] ?? "");
42047
42440
  if (!rawPath)
42048
42441
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
42049
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join46(this.autoresearchDir, basename12(rawPath)) : join46(this.autoresearchDir, rawPath);
42442
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join47(this.autoresearchDir, basename12(rawPath)) : join47(this.autoresearchDir, rawPath);
42050
42443
  if (!targetPath.startsWith(this.autoresearchDir)) {
42051
42444
  return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
42052
42445
  }
42053
42446
  try {
42054
- const dir = join46(targetPath, "..");
42447
+ const dir = join47(targetPath, "..");
42055
42448
  mkdirSync16(dir, { recursive: true });
42056
42449
  writeFileSync15(targetPath, content, "utf-8");
42057
42450
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
@@ -42081,12 +42474,12 @@ var init_dream_engine = __esm({
42081
42474
  const rawPath = String(args["path"] ?? "");
42082
42475
  const oldStr = String(args["old_string"] ?? "");
42083
42476
  const newStr = String(args["new_string"] ?? "");
42084
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join46(this.autoresearchDir, basename12(rawPath)) : join46(this.autoresearchDir, rawPath);
42477
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join47(this.autoresearchDir, basename12(rawPath)) : join47(this.autoresearchDir, rawPath);
42085
42478
  if (!targetPath.startsWith(this.autoresearchDir)) {
42086
42479
  return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
42087
42480
  }
42088
42481
  try {
42089
- if (!existsSync37(targetPath)) {
42482
+ if (!existsSync38(targetPath)) {
42090
42483
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
42091
42484
  }
42092
42485
  let content = readFileSync27(targetPath, "utf-8");
@@ -42135,12 +42528,12 @@ var init_dream_engine = __esm({
42135
42528
  const content = String(args["content"] ?? "");
42136
42529
  if (!rawPath)
42137
42530
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
42138
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join46(this.dreamsDir, basename12(rawPath)) : join46(this.dreamsDir, rawPath);
42531
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join47(this.dreamsDir, basename12(rawPath)) : join47(this.dreamsDir, rawPath);
42139
42532
  if (!targetPath.startsWith(this.dreamsDir)) {
42140
42533
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
42141
42534
  }
42142
42535
  try {
42143
- const dir = join46(targetPath, "..");
42536
+ const dir = join47(targetPath, "..");
42144
42537
  mkdirSync16(dir, { recursive: true });
42145
42538
  writeFileSync15(targetPath, content, "utf-8");
42146
42539
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
@@ -42170,12 +42563,12 @@ var init_dream_engine = __esm({
42170
42563
  const rawPath = String(args["path"] ?? "");
42171
42564
  const oldStr = String(args["old_string"] ?? "");
42172
42565
  const newStr = String(args["new_string"] ?? "");
42173
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join46(this.dreamsDir, basename12(rawPath)) : join46(this.dreamsDir, rawPath);
42566
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join47(this.dreamsDir, basename12(rawPath)) : join47(this.dreamsDir, rawPath);
42174
42567
  if (!targetPath.startsWith(this.dreamsDir)) {
42175
42568
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
42176
42569
  }
42177
42570
  try {
42178
- if (!existsSync37(targetPath)) {
42571
+ if (!existsSync38(targetPath)) {
42179
42572
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
42180
42573
  }
42181
42574
  let content = readFileSync27(targetPath, "utf-8");
@@ -42214,7 +42607,7 @@ var init_dream_engine = __esm({
42214
42607
  }
42215
42608
  }
42216
42609
  try {
42217
- const output = execSync28(cmd, {
42610
+ const output = execSync29(cmd, {
42218
42611
  cwd: this.repoRoot,
42219
42612
  timeout: 3e4,
42220
42613
  encoding: "utf-8",
@@ -42237,7 +42630,7 @@ var init_dream_engine = __esm({
42237
42630
  constructor(config, repoRoot) {
42238
42631
  this.config = config;
42239
42632
  this.repoRoot = repoRoot;
42240
- this.dreamsDir = join46(repoRoot, ".oa", "dreams");
42633
+ this.dreamsDir = join47(repoRoot, ".oa", "dreams");
42241
42634
  this.state = {
42242
42635
  mode: "default",
42243
42636
  active: false,
@@ -42321,7 +42714,7 @@ ${result.summary}`;
42321
42714
  if (mode !== "default" || cycle === totalCycles) {
42322
42715
  renderDreamContraction(cycle);
42323
42716
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
42324
- const summaryPath = join46(this.dreamsDir, `cycle-${cycle}-summary.md`);
42717
+ const summaryPath = join47(this.dreamsDir, `cycle-${cycle}-summary.md`);
42325
42718
  writeFileSync15(summaryPath, cycleSummary, "utf-8");
42326
42719
  }
42327
42720
  if (mode === "lucid" && !this.abortController.signal.aborted) {
@@ -42534,7 +42927,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
42534
42927
  }
42535
42928
  /** Build role-specific tool sets for swarm agents */
42536
42929
  buildSwarmTools(role, _workspace) {
42537
- const autoresearchDir = join46(this.repoRoot, ".oa", "autoresearch");
42930
+ const autoresearchDir = join47(this.repoRoot, ".oa", "autoresearch");
42538
42931
  const taskComplete = this.createSwarmTaskCompleteTool(role);
42539
42932
  switch (role) {
42540
42933
  case "researcher": {
@@ -42898,7 +43291,7 @@ INSTRUCTIONS:
42898
43291
  2. Summarize the key learnings and next steps
42899
43292
 
42900
43293
  Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
42901
- const reportPath = join46(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
43294
+ const reportPath = join47(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
42902
43295
  const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
42903
43296
 
42904
43297
  **Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -42987,29 +43380,29 @@ ${summaryResult}
42987
43380
  }
42988
43381
  /** Save workspace backup for lucid mode */
42989
43382
  saveVersionCheckpoint(cycle) {
42990
- const checkpointDir = join46(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
43383
+ const checkpointDir = join47(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
42991
43384
  try {
42992
43385
  mkdirSync16(checkpointDir, { recursive: true });
42993
43386
  try {
42994
- const gitStatus = execSync28("git status --porcelain", {
43387
+ const gitStatus = execSync29("git status --porcelain", {
42995
43388
  cwd: this.repoRoot,
42996
43389
  encoding: "utf-8",
42997
43390
  timeout: 1e4
42998
43391
  });
42999
- const gitDiff = execSync28("git diff", {
43392
+ const gitDiff = execSync29("git diff", {
43000
43393
  cwd: this.repoRoot,
43001
43394
  encoding: "utf-8",
43002
43395
  timeout: 1e4
43003
43396
  });
43004
- const gitHash = execSync28("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
43397
+ const gitHash = execSync29("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
43005
43398
  cwd: this.repoRoot,
43006
43399
  encoding: "utf-8",
43007
43400
  timeout: 5e3
43008
43401
  }).trim();
43009
- writeFileSync15(join46(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
43010
- writeFileSync15(join46(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
43011
- writeFileSync15(join46(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
43012
- writeFileSync15(join46(checkpointDir, "checkpoint.json"), JSON.stringify({
43402
+ writeFileSync15(join47(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
43403
+ writeFileSync15(join47(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
43404
+ writeFileSync15(join47(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
43405
+ writeFileSync15(join47(checkpointDir, "checkpoint.json"), JSON.stringify({
43013
43406
  cycle,
43014
43407
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
43015
43408
  gitHash,
@@ -43017,7 +43410,7 @@ ${summaryResult}
43017
43410
  }, null, 2), "utf-8");
43018
43411
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
43019
43412
  } catch {
43020
- writeFileSync15(join46(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
43413
+ writeFileSync15(join47(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
43021
43414
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
43022
43415
  }
43023
43416
  } catch (err) {
@@ -43075,14 +43468,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
43075
43468
  ---
43076
43469
  *Auto-generated by open-agents dream engine*
43077
43470
  `;
43078
- writeFileSync15(join46(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
43471
+ writeFileSync15(join47(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
43079
43472
  } catch {
43080
43473
  }
43081
43474
  }
43082
43475
  /** Save dream state for resume/inspection */
43083
43476
  saveDreamState() {
43084
43477
  try {
43085
- writeFileSync15(join46(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
43478
+ writeFileSync15(join47(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
43086
43479
  } catch {
43087
43480
  }
43088
43481
  }
@@ -43456,8 +43849,8 @@ var init_bless_engine = __esm({
43456
43849
  });
43457
43850
 
43458
43851
  // packages/cli/dist/tui/dmn-engine.js
43459
- import { existsSync as existsSync38, readFileSync as readFileSync28, writeFileSync as writeFileSync16, mkdirSync as mkdirSync17, readdirSync as readdirSync13, unlinkSync as unlinkSync6 } from "node:fs";
43460
- import { join as join47, basename as basename13 } from "node:path";
43852
+ import { existsSync as existsSync39, readFileSync as readFileSync28, writeFileSync as writeFileSync16, mkdirSync as mkdirSync17, readdirSync as readdirSync13, unlinkSync as unlinkSync7 } from "node:fs";
43853
+ import { join as join48, basename as basename13 } from "node:path";
43461
43854
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
43462
43855
  const competenceReport = competence.length > 0 ? competence.map((c3) => {
43463
43856
  const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
@@ -43570,8 +43963,8 @@ var init_dmn_engine = __esm({
43570
43963
  constructor(config, repoRoot) {
43571
43964
  this.config = config;
43572
43965
  this.repoRoot = repoRoot;
43573
- this.stateDir = join47(repoRoot, ".oa", "dmn");
43574
- this.historyDir = join47(repoRoot, ".oa", "dmn", "cycles");
43966
+ this.stateDir = join48(repoRoot, ".oa", "dmn");
43967
+ this.historyDir = join48(repoRoot, ".oa", "dmn", "cycles");
43575
43968
  mkdirSync17(this.historyDir, { recursive: true });
43576
43969
  this.loadState();
43577
43970
  }
@@ -44161,11 +44554,11 @@ OUTPUT: Call task_complete with JSON:
44161
44554
  async gatherMemoryTopics() {
44162
44555
  const topics = [];
44163
44556
  const dirs = [
44164
- join47(this.repoRoot, ".oa", "memory"),
44165
- join47(this.repoRoot, ".open-agents", "memory")
44557
+ join48(this.repoRoot, ".oa", "memory"),
44558
+ join48(this.repoRoot, ".open-agents", "memory")
44166
44559
  ];
44167
44560
  for (const dir of dirs) {
44168
- if (!existsSync38(dir))
44561
+ if (!existsSync39(dir))
44169
44562
  continue;
44170
44563
  try {
44171
44564
  const files = readdirSync13(dir).filter((f) => f.endsWith(".json"));
@@ -44181,8 +44574,8 @@ OUTPUT: Call task_complete with JSON:
44181
44574
  }
44182
44575
  // ── State persistence ─────────────────────────────────────────────────
44183
44576
  loadState() {
44184
- const path = join47(this.stateDir, "state.json");
44185
- if (existsSync38(path)) {
44577
+ const path = join48(this.stateDir, "state.json");
44578
+ if (existsSync39(path)) {
44186
44579
  try {
44187
44580
  this.state = JSON.parse(readFileSync28(path, "utf-8"));
44188
44581
  } catch {
@@ -44191,19 +44584,19 @@ OUTPUT: Call task_complete with JSON:
44191
44584
  }
44192
44585
  saveState() {
44193
44586
  try {
44194
- writeFileSync16(join47(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
44587
+ writeFileSync16(join48(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
44195
44588
  } catch {
44196
44589
  }
44197
44590
  }
44198
44591
  saveCycleResult(result) {
44199
44592
  try {
44200
44593
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
44201
- writeFileSync16(join47(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
44594
+ writeFileSync16(join48(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
44202
44595
  const files = readdirSync13(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
44203
44596
  if (files.length > 50) {
44204
44597
  for (const old of files.slice(0, files.length - 50)) {
44205
44598
  try {
44206
- unlinkSync6(join47(this.historyDir, old));
44599
+ unlinkSync7(join48(this.historyDir, old));
44207
44600
  } catch {
44208
44601
  }
44209
44602
  }
@@ -44216,8 +44609,8 @@ OUTPUT: Call task_complete with JSON:
44216
44609
  });
44217
44610
 
44218
44611
  // packages/cli/dist/tui/snr-engine.js
44219
- import { existsSync as existsSync39, readdirSync as readdirSync14, readFileSync as readFileSync29 } from "node:fs";
44220
- import { join as join48, basename as basename14 } from "node:path";
44612
+ import { existsSync as existsSync40, readdirSync as readdirSync14, readFileSync as readFileSync29 } from "node:fs";
44613
+ import { join as join49, basename as basename14 } from "node:path";
44221
44614
  function computeDPrime(signalScores, noiseScores) {
44222
44615
  if (signalScores.length === 0 || noiseScores.length === 0)
44223
44616
  return 0;
@@ -44457,11 +44850,11 @@ Call task_complete with the JSON array when done.`, onEvent)
44457
44850
  loadMemoryEntries(topics) {
44458
44851
  const entries = [];
44459
44852
  const dirs = [
44460
- join48(this.repoRoot, ".oa", "memory"),
44461
- join48(this.repoRoot, ".open-agents", "memory")
44853
+ join49(this.repoRoot, ".oa", "memory"),
44854
+ join49(this.repoRoot, ".open-agents", "memory")
44462
44855
  ];
44463
44856
  for (const dir of dirs) {
44464
- if (!existsSync39(dir))
44857
+ if (!existsSync40(dir))
44465
44858
  continue;
44466
44859
  try {
44467
44860
  const files = readdirSync14(dir).filter((f) => f.endsWith(".json"));
@@ -44470,7 +44863,7 @@ Call task_complete with the JSON array when done.`, onEvent)
44470
44863
  if (topics.length > 0 && !topics.includes(topic))
44471
44864
  continue;
44472
44865
  try {
44473
- const data = JSON.parse(readFileSync29(join48(dir, f), "utf-8"));
44866
+ const data = JSON.parse(readFileSync29(join49(dir, f), "utf-8"));
44474
44867
  for (const [key, val] of Object.entries(data)) {
44475
44868
  const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
44476
44869
  entries.push({ topic, key, value });
@@ -45037,8 +45430,8 @@ var init_tool_policy = __esm({
45037
45430
  });
45038
45431
 
45039
45432
  // packages/cli/dist/tui/telegram-bridge.js
45040
- import { mkdirSync as mkdirSync18, existsSync as existsSync40, unlinkSync as unlinkSync7, readdirSync as readdirSync15, statSync as statSync11 } from "node:fs";
45041
- import { join as join49, resolve as resolve28 } from "node:path";
45433
+ import { mkdirSync as mkdirSync18, existsSync as existsSync41, unlinkSync as unlinkSync8, readdirSync as readdirSync15, statSync as statSync11 } from "node:fs";
45434
+ import { join as join50, resolve as resolve28 } from "node:path";
45042
45435
  import { writeFile as writeFileAsync } from "node:fs/promises";
45043
45436
  function convertMarkdownToTelegramHTML(md) {
45044
45437
  let html = md;
@@ -45803,7 +46196,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
45803
46196
  return null;
45804
46197
  const buffer = Buffer.from(await res.arrayBuffer());
45805
46198
  const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
45806
- const localPath = join49(this.mediaCacheDir, fileName);
46199
+ const localPath = join50(this.mediaCacheDir, fileName);
45807
46200
  await writeFileAsync(localPath, buffer);
45808
46201
  return localPath;
45809
46202
  } catch {
@@ -45891,7 +46284,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
45891
46284
  for (const [key, entry] of this.mediaCache) {
45892
46285
  if (now - entry.cachedAt > MEDIA_CACHE_TTL_MS) {
45893
46286
  try {
45894
- unlinkSync7(entry.localPath);
46287
+ unlinkSync8(entry.localPath);
45895
46288
  } catch {
45896
46289
  }
45897
46290
  this.mediaCache.delete(key);
@@ -45967,11 +46360,11 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
45967
46360
  let mimeType = "audio/wav";
45968
46361
  try {
45969
46362
  const { execSync: execSyncLocal } = await import("node:child_process");
45970
- const { tmpdir: tmpdir8 } = await import("node:os");
46363
+ const { tmpdir: tmpdir9 } = await import("node:os");
45971
46364
  const { join: joinPath } = await import("node:path");
45972
46365
  const { writeFileSync: writeFs, readFileSync: readFs, unlinkSync: unlinkFs } = await import("node:fs");
45973
- const tmpWav = joinPath(tmpdir8(), `oa-tg-voice-${Date.now()}.wav`);
45974
- const tmpOgg = joinPath(tmpdir8(), `oa-tg-voice-${Date.now()}.ogg`);
46366
+ const tmpWav = joinPath(tmpdir9(), `oa-tg-voice-${Date.now()}.wav`);
46367
+ const tmpOgg = joinPath(tmpdir9(), `oa-tg-voice-${Date.now()}.ogg`);
45975
46368
  writeFs(tmpWav, wavBuffer);
45976
46369
  execSyncLocal(`ffmpeg -i "${tmpWav}" -c:a libopus -b:a 48k -ar 48000 -ac 1 "${tmpOgg}" -y 2>/dev/null`, {
45977
46370
  timeout: 15e3,
@@ -48148,11 +48541,11 @@ var init_status_bar = __esm({
48148
48541
  import * as readline2 from "node:readline";
48149
48542
  import { Writable } from "node:stream";
48150
48543
  import { cwd } from "node:process";
48151
- import { resolve as resolve29, join as join50, dirname as dirname18, extname as extname10 } from "node:path";
48544
+ import { resolve as resolve29, join as join51, dirname as dirname18, extname as extname10 } from "node:path";
48152
48545
  import { createRequire as createRequire2 } from "node:module";
48153
48546
  import { fileURLToPath as fileURLToPath12 } from "node:url";
48154
48547
  import { readFileSync as readFileSync30, writeFileSync as writeFileSync17, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as readdirSync16, mkdirSync as mkdirSync19 } from "node:fs";
48155
- import { existsSync as existsSync41 } from "node:fs";
48548
+ import { existsSync as existsSync42 } from "node:fs";
48156
48549
  import { homedir as homedir13 } from "node:os";
48157
48550
  function formatTimeAgo(date) {
48158
48551
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
@@ -48172,12 +48565,12 @@ function getVersion3() {
48172
48565
  const require2 = createRequire2(import.meta.url);
48173
48566
  const thisDir = dirname18(fileURLToPath12(import.meta.url));
48174
48567
  const candidates = [
48175
- join50(thisDir, "..", "package.json"),
48176
- join50(thisDir, "..", "..", "package.json"),
48177
- join50(thisDir, "..", "..", "..", "package.json")
48568
+ join51(thisDir, "..", "package.json"),
48569
+ join51(thisDir, "..", "..", "package.json"),
48570
+ join51(thisDir, "..", "..", "..", "package.json")
48178
48571
  ];
48179
48572
  for (const pkgPath of candidates) {
48180
- if (existsSync41(pkgPath)) {
48573
+ if (existsSync42(pkgPath)) {
48181
48574
  const pkg = require2(pkgPath);
48182
48575
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
48183
48576
  return pkg.version ?? "0.0.0";
@@ -48384,15 +48777,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
48384
48777
  function gatherMemorySnippets(root) {
48385
48778
  const snippets = [];
48386
48779
  const dirs = [
48387
- join50(root, ".oa", "memory"),
48388
- join50(root, ".open-agents", "memory")
48780
+ join51(root, ".oa", "memory"),
48781
+ join51(root, ".open-agents", "memory")
48389
48782
  ];
48390
48783
  for (const dir of dirs) {
48391
- if (!existsSync41(dir))
48784
+ if (!existsSync42(dir))
48392
48785
  continue;
48393
48786
  try {
48394
48787
  for (const f of readdirSync16(dir).filter((f2) => f2.endsWith(".json"))) {
48395
- const data = JSON.parse(readFileSync30(join50(dir, f), "utf-8"));
48788
+ const data = JSON.parse(readFileSync30(join51(dir, f), "utf-8"));
48396
48789
  for (const val of Object.values(data)) {
48397
48790
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
48398
48791
  if (v.length > 10)
@@ -48837,8 +49230,18 @@ ${entry.fullContent}`
48837
49230
  const name = event.toolName ?? "";
48838
49231
  if (name === "file_write" || name === "file_edit" || name === "file_patch" || name === "batch_edit") {
48839
49232
  filesTouched.add(event.toolArgs.path);
49233
+ if (isNeovimActive()) {
49234
+ notifyNeovimFileChange(event.toolArgs.path).catch(() => {
49235
+ });
49236
+ }
48840
49237
  }
48841
49238
  }
49239
+ if (isNeovimActive()) {
49240
+ const toolName = event.toolName ?? "unknown";
49241
+ const argSummary = Object.keys(event.toolArgs ?? {}).join(", ");
49242
+ writeToNeovimOutput(`\x1B[33m\u25B6 ${toolName}\x1B[0m(${argSummary})\r
49243
+ `);
49244
+ }
48842
49245
  getActivityFeed().push({
48843
49246
  ts: Date.now(),
48844
49247
  source: "main",
@@ -48898,6 +49301,13 @@ ${entry.fullContent}`
48898
49301
  }
48899
49302
  }
48900
49303
  });
49304
+ if (isNeovimActive()) {
49305
+ const ok = event.success ?? false;
49306
+ const prefix = ok ? "\x1B[32m\u2713\x1B[0m" : "\x1B[31m\u2717\x1B[0m";
49307
+ const preview = (event.content ?? "").slice(0, 120).replace(/\n/g, " ");
49308
+ writeToNeovimOutput(` ${prefix} ${preview}\r
49309
+ `);
49310
+ }
48901
49311
  break;
48902
49312
  }
48903
49313
  case "model_response":
@@ -48922,6 +49332,9 @@ ${entry.fullContent}`
48922
49332
  if (stream?.enabled) {
48923
49333
  stream.renderer.write(event.content ?? "", event.streamKind ?? "content");
48924
49334
  }
49335
+ if (isNeovimActive() && event.content && (event.streamKind ?? "content") === "content") {
49336
+ writeToNeovimOutput(event.content);
49337
+ }
48925
49338
  if (voice?.enabled && (voice.voiceMode === "chat" || voice.voiceMode === "verbose")) {
48926
49339
  if (event.content && (event.streamKind ?? "content") === "content") {
48927
49340
  streamTextBuffer += event.content;
@@ -49284,7 +49697,7 @@ async function startInteractive(config, repoPath) {
49284
49697
  let p2pGateway = null;
49285
49698
  let peerMesh = null;
49286
49699
  let inferenceRouter = null;
49287
- const secretVault = new SecretVault(join50(repoRoot, ".oa", "vault.enc"));
49700
+ const secretVault = new SecretVault(join51(repoRoot, ".oa", "vault.enc"));
49288
49701
  let adminSessionKey = null;
49289
49702
  const callSubAgents = /* @__PURE__ */ new Map();
49290
49703
  const streamRenderer = new StreamRenderer();
@@ -49493,12 +49906,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
49493
49906
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
49494
49907
  return [hits, line];
49495
49908
  }
49496
- const HISTORY_DIR = join50(homedir13(), ".open-agents");
49497
- const HISTORY_FILE = join50(HISTORY_DIR, "repl-history");
49909
+ const HISTORY_DIR = join51(homedir13(), ".open-agents");
49910
+ const HISTORY_FILE = join51(HISTORY_DIR, "repl-history");
49498
49911
  const MAX_HISTORY_LINES = 500;
49499
49912
  let savedHistory = [];
49500
49913
  try {
49501
- if (existsSync41(HISTORY_FILE)) {
49914
+ if (existsSync42(HISTORY_FILE)) {
49502
49915
  const raw = readFileSync30(HISTORY_FILE, "utf8").trim();
49503
49916
  if (raw)
49504
49917
  savedHistory = raw.split("\n").reverse();
@@ -49540,6 +49953,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
49540
49953
  }
49541
49954
  process.stdout.on("resize", () => {
49542
49955
  statusBar.handleResize();
49956
+ if (isNeovimActive()) {
49957
+ const contentRows = statusBar.isActive ? statusBar.availableContentRows : Math.max(5, (process.stdout.rows ?? 24) - 6);
49958
+ resizeNeovim(process.stdout.columns ?? 80, contentRows);
49959
+ }
49543
49960
  if (!carouselRetired) {
49544
49961
  const termRows = process.stdout.rows ?? 24;
49545
49962
  const scrollStart = carousel.reservedRows + 1;
@@ -49657,7 +50074,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
49657
50074
  } catch {
49658
50075
  }
49659
50076
  try {
49660
- const oaDir = join50(repoRoot, ".oa");
50077
+ const oaDir = join51(repoRoot, ".oa");
49661
50078
  const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
49662
50079
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
49663
50080
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -49679,7 +50096,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
49679
50096
  } catch {
49680
50097
  }
49681
50098
  try {
49682
- const oaDir = join50(repoRoot, ".oa");
50099
+ const oaDir = join51(repoRoot, ".oa");
49683
50100
  const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
49684
50101
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
49685
50102
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -50479,7 +50896,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
50479
50896
  kind,
50480
50897
  targetUrl,
50481
50898
  authKey,
50482
- stateDir: join50(repoRoot, ".oa"),
50899
+ stateDir: join51(repoRoot, ".oa"),
50483
50900
  passthrough: passthrough ?? false,
50484
50901
  loadbalance: loadbalance ?? false,
50485
50902
  endpointAuth: passthrough ? currentConfig.apiKey : void 0,
@@ -50524,7 +50941,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
50524
50941
  await tunnelGateway.stop();
50525
50942
  tunnelGateway = null;
50526
50943
  }
50527
- const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join50(repoRoot, ".oa") });
50944
+ const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join51(repoRoot, ".oa") });
50528
50945
  newTunnel.on("stats", (stats) => {
50529
50946
  statusBar.setExposeStatus({
50530
50947
  status: stats.status,
@@ -50774,8 +51191,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
50774
51191
  return statusBar.isActive ? statusBar.availableContentRows : Math.max(3, (process.stdout.rows ?? 24) - 6);
50775
51192
  },
50776
51193
  destroyProject() {
50777
- const oaPath = join50(repoRoot, OA_DIR);
50778
- if (existsSync41(oaPath)) {
51194
+ const oaPath = join51(repoRoot, OA_DIR);
51195
+ if (existsSync42(oaPath)) {
50779
51196
  try {
50780
51197
  rmSync2(oaPath, { recursive: true, force: true });
50781
51198
  writeContent(() => renderInfo(`Removed ${OA_DIR}/ directory.`));
@@ -51104,8 +51521,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
51104
51521
  }
51105
51522
  }
51106
51523
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
51107
- const isImage = isImagePath(cleanPath) && existsSync41(resolve29(repoRoot, cleanPath));
51108
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync41(resolve29(repoRoot, cleanPath));
51524
+ const isImage = isImagePath(cleanPath) && existsSync42(resolve29(repoRoot, cleanPath));
51525
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync42(resolve29(repoRoot, cleanPath));
51109
51526
  if (activeTask) {
51110
51527
  if (activeTask.runner.isPaused) {
51111
51528
  activeTask.runner.resume();
@@ -51651,6 +52068,7 @@ var init_interactive = __esm({
51651
52068
  init_status_bar();
51652
52069
  init_dist6();
51653
52070
  init_overlay_lock();
52071
+ init_neovim_mode();
51654
52072
  taskManager = new BackgroundTaskManager();
51655
52073
  }
51656
52074
  });
@@ -51686,7 +52104,7 @@ import { glob } from "glob";
51686
52104
  import ignore from "ignore";
51687
52105
  import { readFile as readFile17, stat as stat4 } from "node:fs/promises";
51688
52106
  import { createHash as createHash4 } from "node:crypto";
51689
- import { join as join51, relative as relative3, extname as extname11, basename as basename15 } from "node:path";
52107
+ import { join as join52, relative as relative3, extname as extname11, basename as basename15 } from "node:path";
51690
52108
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
51691
52109
  var init_codebase_indexer = __esm({
51692
52110
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -51730,7 +52148,7 @@ var init_codebase_indexer = __esm({
51730
52148
  const ig = ignore.default();
51731
52149
  if (this.config.respectGitignore) {
51732
52150
  try {
51733
- const gitignoreContent = await readFile17(join51(this.config.rootDir, ".gitignore"), "utf-8");
52151
+ const gitignoreContent = await readFile17(join52(this.config.rootDir, ".gitignore"), "utf-8");
51734
52152
  ig.add(gitignoreContent);
51735
52153
  } catch {
51736
52154
  }
@@ -51745,7 +52163,7 @@ var init_codebase_indexer = __esm({
51745
52163
  for (const relativePath of files) {
51746
52164
  if (ig.ignores(relativePath))
51747
52165
  continue;
51748
- const fullPath = join51(this.config.rootDir, relativePath);
52166
+ const fullPath = join52(this.config.rootDir, relativePath);
51749
52167
  try {
51750
52168
  const fileStat = await stat4(fullPath);
51751
52169
  if (fileStat.size > this.config.maxFileSize)
@@ -51791,7 +52209,7 @@ var init_codebase_indexer = __esm({
51791
52209
  if (!child) {
51792
52210
  child = {
51793
52211
  name: part,
51794
- path: join51(current.path, part),
52212
+ path: join52(current.path, part),
51795
52213
  type: "directory",
51796
52214
  children: []
51797
52215
  };
@@ -51874,13 +52292,13 @@ __export(index_repo_exports, {
51874
52292
  indexRepoCommand: () => indexRepoCommand
51875
52293
  });
51876
52294
  import { resolve as resolve30 } from "node:path";
51877
- import { existsSync as existsSync42, statSync as statSync12 } from "node:fs";
52295
+ import { existsSync as existsSync43, statSync as statSync12 } from "node:fs";
51878
52296
  import { cwd as cwd2 } from "node:process";
51879
52297
  async function indexRepoCommand(opts, _config) {
51880
52298
  const repoRoot = resolve30(opts.repoPath ?? cwd2());
51881
52299
  printHeader("Index Repository");
51882
52300
  printInfo(`Indexing: ${repoRoot}`);
51883
- if (!existsSync42(repoRoot)) {
52301
+ if (!existsSync43(repoRoot)) {
51884
52302
  printError(`Path does not exist: ${repoRoot}`);
51885
52303
  process.exit(1);
51886
52304
  }
@@ -52132,7 +52550,7 @@ var config_exports = {};
52132
52550
  __export(config_exports, {
52133
52551
  configCommand: () => configCommand
52134
52552
  });
52135
- import { join as join52, resolve as resolve31 } from "node:path";
52553
+ import { join as join53, resolve as resolve31 } from "node:path";
52136
52554
  import { homedir as homedir14 } from "node:os";
52137
52555
  import { cwd as cwd3 } from "node:process";
52138
52556
  function redactIfSensitive(key, value) {
@@ -52215,7 +52633,7 @@ function handleShow(opts, config) {
52215
52633
  }
52216
52634
  }
52217
52635
  printSection("Config File");
52218
- printInfo(`~/.open-agents/config.json (${join52(homedir14(), ".open-agents", "config.json")})`);
52636
+ printInfo(`~/.open-agents/config.json (${join53(homedir14(), ".open-agents", "config.json")})`);
52219
52637
  printSection("Priority Chain");
52220
52638
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
52221
52639
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -52254,7 +52672,7 @@ function handleSet(opts, _config) {
52254
52672
  const coerced = coerceForSettings(key, value);
52255
52673
  saveProjectSettings(repoRoot, { [key]: coerced });
52256
52674
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
52257
- printInfo(`Saved to ${join52(repoRoot, ".oa", "settings.json")}`);
52675
+ printInfo(`Saved to ${join53(repoRoot, ".oa", "settings.json")}`);
52258
52676
  printInfo("This override applies only when running in this workspace.");
52259
52677
  } catch (err) {
52260
52678
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -52511,9 +52929,9 @@ var eval_exports = {};
52511
52929
  __export(eval_exports, {
52512
52930
  evalCommand: () => evalCommand
52513
52931
  });
52514
- import { tmpdir as tmpdir7 } from "node:os";
52932
+ import { tmpdir as tmpdir8 } from "node:os";
52515
52933
  import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync18 } from "node:fs";
52516
- import { join as join53 } from "node:path";
52934
+ import { join as join54 } from "node:path";
52517
52935
  async function evalCommand(opts, config) {
52518
52936
  const suiteName = opts.suite ?? "basic";
52519
52937
  const suite = SUITES[suiteName];
@@ -52638,9 +53056,9 @@ async function evalCommand(opts, config) {
52638
53056
  process.exit(failed > 0 ? 1 : 0);
52639
53057
  }
52640
53058
  function createTempEvalRepo() {
52641
- const dir = join53(tmpdir7(), `open-agents-eval-${Date.now()}`);
53059
+ const dir = join54(tmpdir8(), `open-agents-eval-${Date.now()}`);
52642
53060
  mkdirSync20(dir, { recursive: true });
52643
- writeFileSync18(join53(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
53061
+ writeFileSync18(join54(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
52644
53062
  return dir;
52645
53063
  }
52646
53064
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -52700,7 +53118,7 @@ init_updater();
52700
53118
  import { parseArgs as nodeParseArgs2 } from "node:util";
52701
53119
  import { createRequire as createRequire3 } from "node:module";
52702
53120
  import { fileURLToPath as fileURLToPath13 } from "node:url";
52703
- import { dirname as dirname19, join as join54 } from "node:path";
53121
+ import { dirname as dirname19, join as join55 } from "node:path";
52704
53122
 
52705
53123
  // packages/cli/dist/cli.js
52706
53124
  import { createInterface } from "node:readline";
@@ -52807,7 +53225,7 @@ init_output();
52807
53225
  function getVersion4() {
52808
53226
  try {
52809
53227
  const require2 = createRequire3(import.meta.url);
52810
- const pkgPath = join54(dirname19(fileURLToPath13(import.meta.url)), "..", "package.json");
53228
+ const pkgPath = join55(dirname19(fileURLToPath13(import.meta.url)), "..", "package.json");
52811
53229
  const pkg = require2(pkgPath);
52812
53230
  return pkg.version;
52813
53231
  } catch {