open-agents-ai 0.104.14 → 0.104.16

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 +134 -20
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -27085,31 +27085,56 @@ function setContentWriteHook(hook) {
27085
27085
  _contentWriteHook = hook;
27086
27086
  }
27087
27087
  function renderError(message) {
27088
- _contentWriteHook?.begin();
27088
+ const redir = _contentWriteHook?.redirect?.();
27089
27089
  const icon = _emojisEnabled ? c2.red("\u2716") : c2.red("E");
27090
+ if (redir) {
27091
+ redir(`
27092
+ ${icon} ${message}
27093
+ `);
27094
+ return;
27095
+ }
27096
+ _contentWriteHook?.begin();
27090
27097
  process.stdout.write(`
27091
27098
  ${icon} ${message}
27092
27099
  `);
27093
27100
  _contentWriteHook?.end();
27094
27101
  }
27095
27102
  function renderInfo(message) {
27096
- _contentWriteHook?.begin();
27103
+ const redir = _contentWriteHook?.redirect?.();
27097
27104
  const icon = _emojisEnabled ? c2.cyan("\u2139") : c2.cyan("i");
27105
+ if (redir) {
27106
+ redir(`${icon} ${message}
27107
+ `);
27108
+ return;
27109
+ }
27110
+ _contentWriteHook?.begin();
27098
27111
  process.stdout.write(`${icon} ${message}
27099
27112
  `);
27100
27113
  _contentWriteHook?.end();
27101
27114
  }
27102
27115
  function renderWarning(message) {
27103
- _contentWriteHook?.begin();
27116
+ const redir = _contentWriteHook?.redirect?.();
27104
27117
  const icon = _emojisEnabled ? c2.yellow("\u26A0") : c2.yellow("!");
27118
+ if (redir) {
27119
+ redir(`${icon} ${message}
27120
+ `);
27121
+ return;
27122
+ }
27123
+ _contentWriteHook?.begin();
27105
27124
  process.stdout.write(`${icon} ${message}
27106
27125
  `);
27107
27126
  _contentWriteHook?.end();
27108
27127
  }
27109
27128
  function renderVerbose(message) {
27129
+ const redir = _contentWriteHook?.redirect?.();
27130
+ const text = `${c2.dim(` > ${message}`)}
27131
+ `;
27132
+ if (redir) {
27133
+ redir(text);
27134
+ return;
27135
+ }
27110
27136
  _contentWriteHook?.begin();
27111
- process.stdout.write(`${c2.dim(` > ${message}`)}
27112
- `);
27137
+ process.stdout.write(text);
27113
27138
  _contentWriteHook?.end();
27114
27139
  }
27115
27140
  function renderRichHeader(opts) {
@@ -34535,6 +34560,14 @@ import { execSync as execSync26 } from "node:child_process";
34535
34560
  function isNeovimActive() {
34536
34561
  return _state !== null && !_state.cleanedUp;
34537
34562
  }
34563
+ function isNeovimFocused() {
34564
+ return _state?.focused ?? false;
34565
+ }
34566
+ function refocusNeovim() {
34567
+ if (!_state || _state.cleanedUp || _state.focused)
34568
+ return;
34569
+ toggleFocus(_state);
34570
+ }
34538
34571
  async function startNeovimMode(opts) {
34539
34572
  if (_state && !_state.cleanedUp) {
34540
34573
  return "Neovim mode is already active. Use /neovim to exit first.";
@@ -34583,7 +34616,7 @@ async function startNeovimMode(opts) {
34583
34616
  'local lp = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"',
34584
34617
  'if not vim.loop.fs_stat(lp) then pcall(vim.fn.system, {"git", "clone", "--filter=blob:none", "--depth=1", "https://github.com/folke/lazy.nvim.git", "--branch=stable", lp}) end',
34585
34618
  "vim.opt.rtp:prepend(lp)",
34586
- 'pcall(function() require("lazy").setup({{"nvim-neo-tree/neo-tree.nvim", branch="v3.x", dependencies={"nvim-lua/plenary.nvim","MunifTanjim/nui.nvim"},config=function() require("neo-tree").setup({close_if_last_window=true,filesystem={follow_current_file={enabled=true},use_libuv_file_watcher=true,hijack_netrw_behavior="disabled"},window={position="left",width=30}}) end}},{install={colorscheme={}},checker={enabled=false}}) end)',
34619
+ 'pcall(function() require("lazy").setup({{"nvim-neo-tree/neo-tree.nvim", branch="v3.x", lazy=false, dependencies={"nvim-lua/plenary.nvim","MunifTanjim/nui.nvim","nvim-tree/nvim-web-devicons"},config=function() require("neo-tree").setup({close_if_last_window=true,enable_git_status=true,filesystem={follow_current_file={enabled=true},use_libuv_file_watcher=true,hijack_netrw_behavior="open_default",filtered_items={hide_dotfiles=false,hide_gitignored=false}},window={position="left",width=30}}) end}},{install={colorscheme={}},checker={enabled=false}}) end)',
34587
34620
  // Open neo-tree sidebar after lazy.nvim finishes loading (needs short defer).
34588
34621
  // Uses pcall so a missing/broken neo-tree doesn't block the editor.
34589
34622
  'vim.defer_fn(function() pcall(vim.cmd, "Neotree show") end, 300)'
@@ -34810,10 +34843,10 @@ function toggleFocus(state) {
34810
34843
  if (state.opts.rl) {
34811
34844
  try {
34812
34845
  state.opts.rl.resume();
34813
- state.opts.rl.prompt(false);
34814
34846
  } catch {
34815
34847
  }
34816
34848
  }
34849
+ state.opts.onFocusToTUI?.();
34817
34850
  } else {
34818
34851
  state.focused = true;
34819
34852
  if (state.opts.rl) {
@@ -37983,6 +38016,7 @@ async function handleSlashCommand(input, ctx) {
37983
38016
  ctx.clearScreen();
37984
38017
  renderInfo("Neovim mode stopped. Main waterfall restored.");
37985
38018
  } else {
38019
+ ctx.retireCarousel?.();
37986
38020
  const contentRows = ctx.availableContentRows?.() ?? Math.max(5, (process.stdout.rows ?? 24) - 6);
37987
38021
  const cols = process.stdout.columns ?? 80;
37988
38022
  const err = await startNeovimMode({
@@ -37993,12 +38027,11 @@ async function handleSlashCommand(input, ctx) {
37993
38027
  initialFile: arg || void 0,
37994
38028
  onExit: () => {
37995
38029
  renderInfo("Neovim mode exited.");
37996
- }
38030
+ },
38031
+ onFocusToTUI: ctx.showPrompt
37997
38032
  });
37998
38033
  if (err) {
37999
38034
  renderError(err);
38000
- } else {
38001
- renderInfo("Neovim mode started. Ctrl+N toggles focus between editor and input.");
38002
38035
  }
38003
38036
  }
38004
38037
  return "handled";
@@ -49367,6 +49400,22 @@ ${entry.fullContent}`
49367
49400
  let streamStartMs = 0;
49368
49401
  let streamTextBuffer = "";
49369
49402
  const contentWrite = (fn) => {
49403
+ if (isNeovimActive()) {
49404
+ const origWrite = process.stdout.write;
49405
+ let captured = "";
49406
+ process.stdout.write = ((chunk) => {
49407
+ captured += typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString() : "";
49408
+ return true;
49409
+ });
49410
+ try {
49411
+ fn();
49412
+ } finally {
49413
+ process.stdout.write = origWrite;
49414
+ }
49415
+ if (captured)
49416
+ writeToNeovimOutput(captured);
49417
+ return;
49418
+ }
49370
49419
  if (isOverlayActive()) {
49371
49420
  const origWrite = process.stdout.write;
49372
49421
  const chunks = [];
@@ -49791,7 +49840,10 @@ async function startInteractive(config, repoPath) {
49791
49840
  statusBar.activate(scrollTop);
49792
49841
  setContentWriteHook({
49793
49842
  begin: () => statusBar.beginContentWrite(),
49794
- end: () => statusBar.endContentWrite()
49843
+ end: () => statusBar.endContentWrite(),
49844
+ // When neovim is active, redirect all render output to the Agent Output
49845
+ // pane instead of writing to stdout (which would push the PTY upward).
49846
+ redirect: () => isNeovimActive() ? writeToNeovimOutput : null
49795
49847
  });
49796
49848
  }
49797
49849
  let resolvedContextWindowSize = 0;
@@ -50183,6 +50235,22 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
50183
50235
  }
50184
50236
  }
50185
50237
  function writeContent(fn) {
50238
+ if (isNeovimActive()) {
50239
+ const origWrite = process.stdout.write;
50240
+ let captured = "";
50241
+ process.stdout.write = ((chunk) => {
50242
+ captured += typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString() : "";
50243
+ return true;
50244
+ });
50245
+ try {
50246
+ fn();
50247
+ } finally {
50248
+ process.stdout.write = origWrite;
50249
+ }
50250
+ if (captured)
50251
+ writeToNeovimOutput(captured);
50252
+ return;
50253
+ }
50186
50254
  if (isOverlayActive()) {
50187
50255
  const origWrite = process.stdout.write;
50188
50256
  const chunks = [];
@@ -50338,7 +50406,11 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
50338
50406
  }
50339
50407
  sudoPromptPending = true;
50340
50408
  const sudoPromptStr = ` ${c2.bold(c2.yellow("\u{1F511} Password:"))} `;
50341
- process.stdout.write(sudoPromptStr);
50409
+ if (isNeovimActive()) {
50410
+ writeToNeovimOutput(sudoPromptStr);
50411
+ } else {
50412
+ process.stdout.write(sudoPromptStr);
50413
+ }
50342
50414
  }
50343
50415
  async function handleAskUser(question, options, allowMultiple) {
50344
50416
  if (statusBar?.isActive)
@@ -51087,7 +51159,12 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
51087
51159
  const exposeFrames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
51088
51160
  let exposeFrame = 0;
51089
51161
  const exposeSpinner = setInterval(() => {
51090
- process.stdout.write(`\r ${c2.cyan(exposeFrames[exposeFrame % exposeFrames.length])} ${c2.dim(exposeSpinnerMsg)}`);
51162
+ if (isNeovimActive()) {
51163
+ writeToNeovimOutput(`${c2.cyan(exposeFrames[exposeFrame % exposeFrames.length])} ${c2.dim(exposeSpinnerMsg)}\r
51164
+ `);
51165
+ } else {
51166
+ process.stdout.write(`\r ${c2.cyan(exposeFrames[exposeFrame % exposeFrames.length])} ${c2.dim(exposeSpinnerMsg)}`);
51167
+ }
51091
51168
  exposeFrame++;
51092
51169
  }, 80);
51093
51170
  const newP2P = new ExposeP2PGateway({
@@ -51116,7 +51193,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
51116
51193
  try {
51117
51194
  const peerId = await newP2P.start();
51118
51195
  clearInterval(exposeSpinner);
51119
- process.stdout.write(`\r\x1B[2K`);
51196
+ if (!isNeovimActive())
51197
+ process.stdout.write(`\r\x1B[2K`);
51120
51198
  p2pGateway = newP2P;
51121
51199
  writeContent(() => {
51122
51200
  process.stdout.write("\n" + newP2P.formatConnectionInfo() + "\n\n");
@@ -51124,7 +51202,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
51124
51202
  return peerId;
51125
51203
  } catch (err) {
51126
51204
  clearInterval(exposeSpinner);
51127
- process.stdout.write(`\r\x1B[2K`);
51205
+ if (!isNeovimActive())
51206
+ process.stdout.write(`\r\x1B[2K`);
51128
51207
  if (!transport) {
51129
51208
  writeContent(() => {
51130
51209
  renderWarning(`libp2p expose failed: ${err instanceof Error ? err.message : String(err)}`);
@@ -51388,6 +51467,17 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
51388
51467
  availableContentRows() {
51389
51468
  return statusBar.isActive ? statusBar.availableContentRows : Math.max(3, (process.stdout.rows ?? 24) - 6);
51390
51469
  },
51470
+ showPrompt() {
51471
+ showPrompt();
51472
+ },
51473
+ retireCarousel() {
51474
+ if (!carouselRetired && carousel.isRunning) {
51475
+ carousel.stop();
51476
+ carouselRetired = true;
51477
+ if (statusBar.isActive)
51478
+ statusBar.setScrollRegionTop(1);
51479
+ }
51480
+ },
51391
51481
  destroyProject() {
51392
51482
  const oaPath = join51(repoRoot, OA_DIR);
51393
51483
  if (existsSync42(oaPath)) {
@@ -51562,7 +51652,12 @@ ${sessionCtx}` : "",
51562
51652
  function showPasteIndicator() {
51563
51653
  const count = pasteBuffer.length;
51564
51654
  const label = ` ${c2.dim("[")}${c2.bold(c2.cyan(String(count)))}${c2.dim(" pasted line" + (count !== 1 ? "s" : "") + " \u2014 press Enter to submit]")}`;
51565
- process.stdout.write(`\r\x1B[K${label}`);
51655
+ if (isNeovimActive()) {
51656
+ writeToNeovimOutput(`${label}\r
51657
+ `);
51658
+ } else {
51659
+ process.stdout.write(`\r\x1B[K${label}`);
51660
+ }
51566
51661
  pasteIndicatorShown = true;
51567
51662
  }
51568
51663
  const buildSlashCommandHandler = () => {
@@ -51627,8 +51722,13 @@ ${result.content.slice(0, 2e3)}${result.content.length > 2e3 ? "\n[truncated]" :
51627
51722
  async function processLine(input) {
51628
51723
  if (depSudoPromptPending && depSudoResolver) {
51629
51724
  const pw = input.trim();
51630
- process.stdout.write(`\r\x1B[K ${c2.dim("\u{1F511} Password received")}
51631
- `);
51725
+ const pwRecvMsg = `\r\x1B[K ${c2.dim("\u{1F511} Password received")}
51726
+ `;
51727
+ if (isNeovimActive()) {
51728
+ writeToNeovimOutput(pwRecvMsg);
51729
+ } else {
51730
+ process.stdout.write(pwRecvMsg);
51731
+ }
51632
51732
  depSudoResolver(pw || null);
51633
51733
  showPrompt();
51634
51734
  return;
@@ -51637,8 +51737,13 @@ ${result.content.slice(0, 2e3)}${result.content.length > 2e3 ? "\n[truncated]" :
51637
51737
  sudoPromptPending = false;
51638
51738
  sessionSudoPassword = input;
51639
51739
  activeTask.runner.setSudoPassword(input);
51640
- process.stdout.write(`\r\x1B[K ${c2.dim("\u{1F511} Password received")}
51641
- `);
51740
+ const pwRecvMsg2 = `\r\x1B[K ${c2.dim("\u{1F511} Password received")}
51741
+ `;
51742
+ if (isNeovimActive()) {
51743
+ writeToNeovimOutput(pwRecvMsg2);
51744
+ } else {
51745
+ process.stdout.write(pwRecvMsg2);
51746
+ }
51642
51747
  showPrompt();
51643
51748
  return;
51644
51749
  }
@@ -51707,6 +51812,9 @@ Execute this skill now. Follow the behavioral guidance above.`;
51707
51812
  }, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler(), thinkingEnabled, handleAskUser);
51708
51813
  activeTask = task;
51709
51814
  showPrompt();
51815
+ if (isNeovimActive() && !isNeovimFocused()) {
51816
+ refocusNeovim();
51817
+ }
51710
51818
  await task.promise;
51711
51819
  } catch (err) {
51712
51820
  const errMsg = err instanceof Error ? err.message : String(err);
@@ -51767,6 +51875,9 @@ ${result.text}`;
51767
51875
  } else {
51768
51876
  writeContent(() => renderUserInterrupt(input));
51769
51877
  }
51878
+ if (isNeovimActive() && !isNeovimFocused()) {
51879
+ refocusNeovim();
51880
+ }
51770
51881
  const steerRunner = activeTask.runner;
51771
51882
  const steerTaskGoal = lastSubmittedPrompt;
51772
51883
  const steerFeed = getActivityFeed();
@@ -51951,6 +52062,9 @@ NEW TASK: ${fullInput}`;
51951
52062
  }, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler(), thinkingEnabled, handleAskUser);
51952
52063
  activeTask = task;
51953
52064
  showPrompt();
52065
+ if (isNeovimActive() && !isNeovimFocused()) {
52066
+ refocusNeovim();
52067
+ }
51954
52068
  await task.promise;
51955
52069
  } catch (err) {
51956
52070
  const errMsg = err instanceof Error ? err.message : String(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.104.14",
3
+ "version": "0.104.16",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",