@travisennis/acai 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. package/README.md +4 -2
  2. package/dist/agent/index.d.ts +119 -0
  3. package/dist/agent/index.d.ts.map +1 -0
  4. package/dist/agent/index.js +406 -0
  5. package/dist/agent/manual-loop.d.ts +41 -0
  6. package/dist/agent/manual-loop.d.ts.map +1 -0
  7. package/dist/agent/manual-loop.js +278 -0
  8. package/dist/cli.d.ts +2 -0
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/cli.js +27 -33
  11. package/dist/commands/add-directory-command.d.ts +3 -0
  12. package/dist/commands/add-directory-command.d.ts.map +1 -0
  13. package/dist/commands/add-directory-command.js +85 -0
  14. package/dist/commands/application-log-command.d.ts.map +1 -1
  15. package/dist/commands/application-log-command.js +34 -0
  16. package/dist/commands/clear-command.d.ts.map +1 -1
  17. package/dist/commands/clear-command.js +8 -0
  18. package/dist/commands/compact-command.d.ts.map +1 -1
  19. package/dist/commands/compact-command.js +15 -2
  20. package/dist/commands/context-command.d.ts +3 -0
  21. package/dist/commands/context-command.d.ts.map +1 -0
  22. package/dist/commands/context-command.js +183 -0
  23. package/dist/commands/copy-command.d.ts.map +1 -1
  24. package/dist/commands/copy-command.js +28 -0
  25. package/dist/commands/edit-command.d.ts.map +1 -1
  26. package/dist/commands/edit-command.js +33 -0
  27. package/dist/commands/edit-prompt-command.d.ts.map +1 -1
  28. package/dist/commands/edit-prompt-command.js +28 -0
  29. package/dist/commands/exit-command.d.ts.map +1 -1
  30. package/dist/commands/exit-command.js +20 -0
  31. package/dist/commands/files-command.d.ts.map +1 -1
  32. package/dist/commands/files-command.js +57 -0
  33. package/dist/commands/generate-rules-command.d.ts.map +1 -1
  34. package/dist/commands/generate-rules-command.js +311 -1
  35. package/dist/commands/handoff-command.d.ts +3 -0
  36. package/dist/commands/handoff-command.d.ts.map +1 -0
  37. package/dist/commands/handoff-command.js +202 -0
  38. package/dist/commands/health-command.d.ts.map +1 -1
  39. package/dist/commands/health-command.js +119 -2
  40. package/dist/commands/help-command.d.ts.map +1 -1
  41. package/dist/commands/help-command.js +28 -0
  42. package/dist/commands/history-command.d.ts +3 -0
  43. package/dist/commands/history-command.d.ts.map +1 -0
  44. package/dist/commands/history-command.js +534 -0
  45. package/dist/commands/init-command.d.ts +1 -1
  46. package/dist/commands/init-command.d.ts.map +1 -1
  47. package/dist/commands/init-command.js +55 -18
  48. package/dist/commands/last-log-command.d.ts.map +1 -1
  49. package/dist/commands/last-log-command.js +27 -0
  50. package/dist/commands/list-directories-command.d.ts +3 -0
  51. package/dist/commands/list-directories-command.d.ts.map +1 -0
  52. package/dist/commands/list-directories-command.js +48 -0
  53. package/dist/commands/list-tools-command.d.ts.map +1 -1
  54. package/dist/commands/list-tools-command.js +66 -3
  55. package/dist/commands/manager.d.ts +15 -3
  56. package/dist/commands/manager.d.ts.map +1 -1
  57. package/dist/commands/manager.js +86 -26
  58. package/dist/commands/model-command.d.ts +22 -0
  59. package/dist/commands/model-command.d.ts.map +1 -1
  60. package/dist/commands/model-command.js +256 -0
  61. package/dist/commands/paste-command.d.ts.map +1 -1
  62. package/dist/commands/paste-command.js +92 -0
  63. package/dist/commands/pickup-command.d.ts +3 -0
  64. package/dist/commands/pickup-command.d.ts.map +1 -0
  65. package/dist/commands/pickup-command.js +161 -0
  66. package/dist/commands/prompt-command.d.ts +1 -1
  67. package/dist/commands/prompt-command.d.ts.map +1 -1
  68. package/dist/commands/prompt-command.js +117 -2
  69. package/dist/commands/remove-directory-command.d.ts +3 -0
  70. package/dist/commands/remove-directory-command.d.ts.map +1 -0
  71. package/dist/commands/remove-directory-command.js +87 -0
  72. package/dist/commands/reset-command.d.ts +1 -1
  73. package/dist/commands/reset-command.d.ts.map +1 -1
  74. package/dist/commands/reset-command.js +13 -2
  75. package/dist/commands/rules-command.d.ts.map +1 -1
  76. package/dist/commands/rules-command.js +65 -0
  77. package/dist/commands/save-command.d.ts.map +1 -1
  78. package/dist/commands/save-command.js +12 -0
  79. package/dist/commands/shell-command.d.ts.map +1 -1
  80. package/dist/commands/shell-command.js +68 -0
  81. package/dist/commands/types.d.ts +9 -4
  82. package/dist/commands/types.d.ts.map +1 -1
  83. package/dist/commands/usage-command.d.ts.map +1 -1
  84. package/dist/commands/usage-command.js +22 -0
  85. package/dist/config.d.ts +6 -7
  86. package/dist/config.d.ts.map +1 -1
  87. package/dist/config.js +23 -29
  88. package/dist/formatting.d.ts +108 -0
  89. package/dist/formatting.d.ts.map +1 -1
  90. package/dist/formatting.js +147 -0
  91. package/dist/index.d.ts +7 -2
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +140 -38
  94. package/dist/logger.d.ts.map +1 -1
  95. package/dist/logger.js +47 -18
  96. package/dist/mentions.d.ts +2 -1
  97. package/dist/mentions.d.ts.map +1 -1
  98. package/dist/mentions.js +16 -1
  99. package/dist/messages.d.ts +8 -0
  100. package/dist/messages.d.ts.map +1 -1
  101. package/dist/messages.js +56 -19
  102. package/dist/middleware/cache.d.ts +3 -0
  103. package/dist/middleware/cache.d.ts.map +1 -0
  104. package/dist/middleware/cache.js +53 -0
  105. package/dist/middleware/index.d.ts +1 -0
  106. package/dist/middleware/index.d.ts.map +1 -1
  107. package/dist/middleware/index.js +1 -0
  108. package/dist/models/ai-config.d.ts +4 -2
  109. package/dist/models/ai-config.d.ts.map +1 -1
  110. package/dist/models/ai-config.js +12 -2
  111. package/dist/models/anthropic-provider.d.ts.map +1 -1
  112. package/dist/models/anthropic-provider.js +3 -60
  113. package/dist/models/manager.d.ts +2 -1
  114. package/dist/models/manager.d.ts.map +1 -1
  115. package/dist/models/manager.js +26 -2
  116. package/dist/models/openrouter-provider.d.ts +7 -14
  117. package/dist/models/openrouter-provider.d.ts.map +1 -1
  118. package/dist/models/openrouter-provider.js +114 -169
  119. package/dist/models/providers.d.ts +1 -1
  120. package/dist/models/providers.d.ts.map +1 -1
  121. package/dist/prompts.d.ts +1 -0
  122. package/dist/prompts.d.ts.map +1 -1
  123. package/dist/prompts.js +53 -4
  124. package/dist/repl/display-tool-messages.d.ts +1 -1
  125. package/dist/repl/display-tool-messages.d.ts.map +1 -1
  126. package/dist/repl/display-tool-messages.js +47 -44
  127. package/dist/repl/get-prompt-header.d.ts.map +1 -1
  128. package/dist/repl/get-prompt-header.js +1 -30
  129. package/dist/repl/project-status-line.d.ts +2 -0
  130. package/dist/repl/project-status-line.d.ts.map +1 -0
  131. package/dist/repl/project-status-line.js +31 -0
  132. package/dist/repl/prompt.d.ts +21 -0
  133. package/dist/repl/prompt.d.ts.map +1 -0
  134. package/dist/{repl-prompt.js → repl/prompt.js} +119 -22
  135. package/dist/repl/tool-call-repair.d.ts.map +1 -1
  136. package/dist/repl/tool-call-repair.js +8 -4
  137. package/dist/repl-new.d.ts +53 -0
  138. package/dist/repl-new.d.ts.map +1 -0
  139. package/dist/repl-new.js +374 -0
  140. package/dist/repl.d.ts +3 -5
  141. package/dist/repl.d.ts.map +1 -1
  142. package/dist/repl.js +74 -166
  143. package/dist/terminal/checkbox-prompt.d.ts.map +1 -1
  144. package/dist/terminal/checkbox-prompt.js +10 -4
  145. package/dist/terminal/index.d.ts +7 -0
  146. package/dist/terminal/index.d.ts.map +1 -1
  147. package/dist/terminal/index.js +94 -0
  148. package/dist/terminal/input-prompt.d.ts +2 -1
  149. package/dist/terminal/input-prompt.d.ts.map +1 -1
  150. package/dist/terminal/markdown.js +3 -0
  151. package/dist/terminal/search-prompt.d.ts.map +1 -1
  152. package/dist/terminal/search-prompt.js +11 -10
  153. package/dist/terminal/select-prompt.d.ts +2 -2
  154. package/dist/terminal/select-prompt.d.ts.map +1 -1
  155. package/dist/terminal/select-prompt.js +47 -39
  156. package/dist/tokens/threshold.d.ts +35 -0
  157. package/dist/tokens/threshold.d.ts.map +1 -0
  158. package/dist/tokens/threshold.js +85 -0
  159. package/dist/tools/advanced-edit-file.d.ts +69 -0
  160. package/dist/tools/advanced-edit-file.d.ts.map +1 -0
  161. package/dist/tools/advanced-edit-file.js +281 -0
  162. package/dist/tools/agent.d.ts +16 -5
  163. package/dist/tools/agent.d.ts.map +1 -1
  164. package/dist/tools/agent.js +71 -58
  165. package/dist/tools/bash-utils.d.ts +1 -1
  166. package/dist/tools/bash-utils.d.ts.map +1 -1
  167. package/dist/tools/bash-utils.js +14 -6
  168. package/dist/tools/bash.d.ts +21 -12
  169. package/dist/tools/bash.d.ts.map +1 -1
  170. package/dist/tools/bash.js +88 -135
  171. package/dist/tools/code-interpreter.d.ts +21 -9
  172. package/dist/tools/code-interpreter.d.ts.map +1 -1
  173. package/dist/tools/code-interpreter.js +138 -137
  174. package/dist/tools/delete-file.d.ts +17 -10
  175. package/dist/tools/delete-file.d.ts.map +1 -1
  176. package/dist/tools/delete-file.js +51 -95
  177. package/dist/tools/directory-tree.d.ts +17 -6
  178. package/dist/tools/directory-tree.d.ts.map +1 -1
  179. package/dist/tools/directory-tree.js +47 -49
  180. package/dist/tools/dynamic-tool-loader.d.ts +18 -8
  181. package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
  182. package/dist/tools/dynamic-tool-loader.js +121 -129
  183. package/dist/tools/dynamic-tool-parser.d.ts +1 -0
  184. package/dist/tools/dynamic-tool-parser.d.ts.map +1 -1
  185. package/dist/tools/dynamic-tool-parser.js +1 -0
  186. package/dist/tools/edit-file.d.ts +35 -15
  187. package/dist/tools/edit-file.d.ts.map +1 -1
  188. package/dist/tools/edit-file.js +112 -112
  189. package/dist/tools/filesystem-utils.d.ts +2 -1
  190. package/dist/tools/filesystem-utils.d.ts.map +1 -1
  191. package/dist/tools/filesystem-utils.js +31 -17
  192. package/dist/tools/glob.d.ts +36 -0
  193. package/dist/tools/glob.d.ts.map +1 -0
  194. package/dist/tools/glob.js +143 -0
  195. package/dist/tools/grep.d.ts +73 -12
  196. package/dist/tools/grep.d.ts.map +1 -1
  197. package/dist/tools/grep.js +413 -168
  198. package/dist/tools/index.d.ts +204 -124
  199. package/dist/tools/index.d.ts.map +1 -1
  200. package/dist/tools/index.js +242 -135
  201. package/dist/tools/llm-edit-fixer.d.ts +25 -0
  202. package/dist/tools/llm-edit-fixer.d.ts.map +1 -0
  203. package/dist/tools/llm-edit-fixer.js +150 -0
  204. package/dist/tools/move-file.d.ts +19 -7
  205. package/dist/tools/move-file.d.ts.map +1 -1
  206. package/dist/tools/move-file.js +40 -33
  207. package/dist/tools/read-file.d.ts +47 -9
  208. package/dist/tools/read-file.d.ts.map +1 -1
  209. package/dist/tools/read-file.js +74 -69
  210. package/dist/tools/read-multiple-files.d.ts +17 -6
  211. package/dist/tools/read-multiple-files.d.ts.map +1 -1
  212. package/dist/tools/read-multiple-files.js +76 -73
  213. package/dist/tools/save-file.d.ts +45 -12
  214. package/dist/tools/save-file.d.ts.map +1 -1
  215. package/dist/tools/save-file.js +58 -101
  216. package/dist/tools/think.d.ts +15 -7
  217. package/dist/tools/think.d.ts.map +1 -1
  218. package/dist/tools/think.js +30 -22
  219. package/dist/tools/types.d.ts +4 -10
  220. package/dist/tools/types.d.ts.map +1 -1
  221. package/dist/tools/types.js +9 -0
  222. package/dist/tools/utils.d.ts +14 -0
  223. package/dist/tools/utils.d.ts.map +1 -0
  224. package/dist/tools/utils.js +16 -0
  225. package/dist/tools/web-fetch.d.ts +11 -4
  226. package/dist/tools/web-fetch.d.ts.map +1 -1
  227. package/dist/tools/web-fetch.js +39 -38
  228. package/dist/tools/web-search.d.ts +15 -6
  229. package/dist/tools/web-search.d.ts.map +1 -1
  230. package/dist/tools/web-search.js +50 -32
  231. package/dist/tui/autocomplete.d.ts +44 -0
  232. package/dist/tui/autocomplete.d.ts.map +1 -0
  233. package/dist/tui/autocomplete.js +466 -0
  234. package/dist/tui/components/assistant-message.d.ts +18 -0
  235. package/dist/tui/components/assistant-message.d.ts.map +1 -0
  236. package/dist/tui/components/assistant-message.js +29 -0
  237. package/dist/tui/components/editor.d.ts +51 -0
  238. package/dist/tui/components/editor.d.ts.map +1 -0
  239. package/dist/tui/components/editor.js +758 -0
  240. package/dist/tui/components/footer.d.ts +24 -0
  241. package/dist/tui/components/footer.d.ts.map +1 -0
  242. package/dist/tui/components/footer.js +197 -0
  243. package/dist/tui/components/input.d.ts +14 -0
  244. package/dist/tui/components/input.d.ts.map +1 -0
  245. package/dist/tui/components/input.js +122 -0
  246. package/dist/tui/components/loader.d.ts +19 -0
  247. package/dist/tui/components/loader.d.ts.map +1 -0
  248. package/dist/tui/components/loader.js +45 -0
  249. package/dist/tui/components/markdown.d.ts +103 -0
  250. package/dist/tui/components/markdown.d.ts.map +1 -0
  251. package/dist/tui/components/markdown.js +533 -0
  252. package/dist/tui/components/modal.d.ts +40 -0
  253. package/dist/tui/components/modal.d.ts.map +1 -0
  254. package/dist/tui/components/modal.js +292 -0
  255. package/dist/tui/components/prompt-status.d.ts +16 -0
  256. package/dist/tui/components/prompt-status.d.ts.map +1 -0
  257. package/dist/tui/components/prompt-status.js +21 -0
  258. package/dist/tui/components/select-list.d.ts +22 -0
  259. package/dist/tui/components/select-list.d.ts.map +1 -0
  260. package/dist/tui/components/select-list.js +143 -0
  261. package/dist/tui/components/spacer.d.ts +16 -0
  262. package/dist/tui/components/spacer.d.ts.map +1 -0
  263. package/dist/tui/components/spacer.js +27 -0
  264. package/dist/tui/components/text.d.ts +26 -0
  265. package/dist/tui/components/text.d.ts.map +1 -0
  266. package/dist/tui/components/text.js +143 -0
  267. package/dist/tui/components/thinking-block.d.ts +14 -0
  268. package/dist/tui/components/thinking-block.d.ts.map +1 -0
  269. package/dist/tui/components/thinking-block.js +30 -0
  270. package/dist/tui/components/tool-execution.d.ts +17 -0
  271. package/dist/tui/components/tool-execution.d.ts.map +1 -0
  272. package/dist/tui/components/tool-execution.js +153 -0
  273. package/dist/tui/components/user-message.d.ts +9 -0
  274. package/dist/tui/components/user-message.d.ts.map +1 -0
  275. package/dist/tui/components/user-message.js +21 -0
  276. package/dist/tui/components/welcome.d.ts +6 -0
  277. package/dist/tui/components/welcome.d.ts.map +1 -0
  278. package/dist/tui/components/welcome.js +30 -0
  279. package/dist/tui/index.d.ts +14 -0
  280. package/dist/tui/index.d.ts.map +1 -0
  281. package/dist/tui/index.js +18 -0
  282. package/dist/tui/terminal.d.ts +37 -0
  283. package/dist/tui/terminal.d.ts.map +1 -0
  284. package/dist/tui/terminal.js +104 -0
  285. package/dist/tui/tui.d.ts +67 -0
  286. package/dist/tui/tui.d.ts.map +1 -0
  287. package/dist/tui/tui.js +184 -0
  288. package/dist/tui/utils.d.ts +19 -0
  289. package/dist/tui/utils.d.ts.map +1 -0
  290. package/dist/tui/utils.js +31 -0
  291. package/dist/utils/generators.d.ts +3 -0
  292. package/dist/utils/generators.d.ts.map +1 -0
  293. package/dist/utils/generators.js +25 -0
  294. package/dist/utils/iterables.d.ts +2 -0
  295. package/dist/utils/iterables.d.ts.map +1 -0
  296. package/dist/utils/iterables.js +6 -0
  297. package/package.json +16 -16
  298. package/dist/conversation-analyzer.d.ts +0 -11
  299. package/dist/conversation-analyzer.d.ts.map +0 -1
  300. package/dist/conversation-analyzer.js +0 -88
  301. package/dist/repl-prompt.d.ts +0 -15
  302. package/dist/repl-prompt.d.ts.map +0 -1
  303. package/dist/tokens/manage-output.d.ts +0 -34
  304. package/dist/tokens/manage-output.d.ts.map +0 -1
  305. package/dist/tokens/manage-output.js +0 -44
  306. package/dist/tool-executor.d.ts +0 -28
  307. package/dist/tool-executor.d.ts.map +0 -1
  308. package/dist/tool-executor.js +0 -74
  309. package/dist/tools/file-editing-utils.d.ts +0 -2
  310. package/dist/tools/file-editing-utils.d.ts.map +0 -1
  311. package/dist/tools/file-editing-utils.js +0 -135
@@ -67,10 +67,14 @@ function findLastEnabledIndex(choices) {
67
67
  }
68
68
  return choices.length - 1;
69
69
  }
70
- function render(choices, pointerIndex, pageStart, pageSize, prompt, typed) {
70
+ function render(choices, pointerIndex, pageStart, pageSize, prompt, typed, totalChoices) {
71
71
  const visible = choices.slice(pageStart, pageStart + pageSize);
72
72
  const lines = [];
73
- lines.push(`${prompt}${typed ? ` (search: ${typed})` : ""}`);
73
+ const searchInfo = typed ? ` (search: ${typed})` : "";
74
+ const filterInfo = typed && choices.length !== totalChoices
75
+ ? ` [${choices.length}/${totalChoices}]`
76
+ : "";
77
+ lines.push(`${prompt}${searchInfo}${filterInfo}`);
74
78
  for (let i = 0; i < visible.length; i++) {
75
79
  const actualIndex = pageStart + i;
76
80
  const ch = visible[i];
@@ -110,13 +114,20 @@ export async function select({ message = "Select", choices, initial = 0, pageSiz
110
114
  if (!stdin.isTTY)
111
115
  throw new Error("TTY required");
112
116
  let searchBuffer = "";
113
- let searchTimer = null;
114
- const resetSearchBuffer = () => {
117
+ const searchTimer = null;
118
+ let filteredChoices = [...normalized];
119
+ const clearSearchBuffer = () => {
120
+ searchBuffer = "";
121
+ filteredChoices = [...normalized];
122
+ // Reset pointer to first enabled choice when clearing search
123
+ pointer = findFirstEnabledIndex(filteredChoices);
124
+ pageStart = updatePageStart(pointer, pageSize, filteredChoices.length);
125
+ renderToScreen();
126
+ };
127
+ const resetSearchTimer = () => {
115
128
  if (searchTimer)
116
129
  clearTimeout(searchTimer);
117
- searchTimer = setTimeout(() => {
118
- searchBuffer = "";
119
- }, 800);
130
+ // Don't auto-clear the search buffer - let user clear it explicitly
120
131
  };
121
132
  let previousOutputLines = 0;
122
133
  function clearPreviousOutput(lineCount) {
@@ -129,30 +140,26 @@ export async function select({ message = "Select", choices, initial = 0, pageSiz
129
140
  stdout.write(ANSI.moveToStart);
130
141
  stdout.write(ANSI.clearFromCursor);
131
142
  clearPreviousOutput(previousOutputLines);
132
- const out = render(normalized, pointer, pageStart, pageSize, message, searchBuffer);
143
+ const out = render(filteredChoices, pointer, pageStart, pageSize, message, searchBuffer, normalized.length);
133
144
  previousOutputLines = out.split("\n").length;
134
145
  stdout.write(`${out}\n`);
135
146
  }
136
147
  function move(delta) {
137
- pointer = findNextEnabledIndex(normalized, pointer, delta);
138
- pageStart = updatePageStart(pointer, pageSize, normalized.length);
148
+ pointer = findNextEnabledIndex(filteredChoices, pointer, delta);
149
+ pageStart = updatePageStart(pointer, pageSize, filteredChoices.length);
139
150
  renderToScreen();
140
151
  }
141
- function jumpToIndexStartingWith(prefix) {
142
- const start = (pointer + 1) % normalized.length;
143
- const lowerPref = prefix.toLowerCase();
144
- for (let i = 0; i < normalized.length; i++) {
145
- const idx = (start + i) % normalized.length;
146
- if (normalized[idx].disabled)
147
- continue;
148
- if (normalized[idx].name.toLowerCase().startsWith(lowerPref)) {
149
- pointer = idx;
150
- pageStart = updatePageStart(pointer, pageSize, normalized.length);
151
- renderToScreen();
152
- return true;
153
- }
152
+ function filterChoices(search) {
153
+ if (!search) {
154
+ filteredChoices = [...normalized];
154
155
  }
155
- return false;
156
+ else {
157
+ const lowerSearch = search.toLowerCase();
158
+ filteredChoices = normalized.filter((choice) => choice.name.toLowerCase().includes(lowerSearch));
159
+ }
160
+ // Reset pointer to first enabled choice
161
+ pointer = findFirstEnabledIndex(filteredChoices);
162
+ pageStart = updatePageStart(pointer, pageSize, filteredChoices.length);
156
163
  }
157
164
  return new Promise((resolve, reject) => {
158
165
  let resolved = false;
@@ -192,7 +199,7 @@ export async function select({ message = "Select", choices, initial = 0, pageSiz
192
199
  }
193
200
  if (key === Keys.enter || key === Keys.newline) {
194
201
  cleanup();
195
- const chosen = normalized[pointer];
202
+ const chosen = filteredChoices[pointer];
196
203
  stdout.write("\n");
197
204
  resolve(chosen.value);
198
205
  return;
@@ -206,35 +213,34 @@ export async function select({ message = "Select", choices, initial = 0, pageSiz
206
213
  return;
207
214
  }
208
215
  if (key === Keys.home || key === Keys.homeAlt) {
209
- pointer = findFirstEnabledIndex(normalized);
210
- pageStart = updatePageStart(pointer, pageSize, normalized.length);
216
+ pointer = findFirstEnabledIndex(filteredChoices);
217
+ pageStart = updatePageStart(pointer, pageSize, filteredChoices.length);
211
218
  renderToScreen();
212
219
  return;
213
220
  }
214
221
  if (key === Keys.end || key === Keys.endAlt) {
215
- pointer = findLastEnabledIndex(normalized);
216
- pageStart = updatePageStart(pointer, pageSize, normalized.length);
222
+ pointer = findLastEnabledIndex(filteredChoices);
223
+ pageStart = updatePageStart(pointer, pageSize, filteredChoices.length);
217
224
  renderToScreen();
218
225
  return;
219
226
  }
220
227
  if (key === Keys.backspace || key === Keys.backspaceAlt) {
221
228
  if (searchBuffer.length > 0) {
222
229
  searchBuffer = searchBuffer.slice(0, -1);
223
- if (searchBuffer.length === 0)
224
- resetSearchBuffer();
225
- renderToScreen();
230
+ if (searchBuffer.length === 0) {
231
+ clearSearchBuffer();
232
+ }
233
+ else {
234
+ filterChoices(searchBuffer);
235
+ renderToScreen();
236
+ }
226
237
  }
227
238
  return;
228
239
  }
229
240
  if (key && key >= " " && key <= "~") {
230
241
  searchBuffer += key;
231
- resetSearchBuffer();
232
- const found = jumpToIndexStartingWith(searchBuffer);
233
- if (!found) {
234
- searchBuffer = key;
235
- resetSearchBuffer();
236
- jumpToIndexStartingWith(searchBuffer);
237
- }
242
+ resetSearchTimer();
243
+ filterChoices(searchBuffer);
238
244
  renderToScreen();
239
245
  return;
240
246
  }
@@ -244,6 +250,8 @@ export async function select({ message = "Select", choices, initial = 0, pageSiz
244
250
  stdin.resume();
245
251
  stdin.setEncoding("utf8");
246
252
  stdout.write(ANSI.hideCursor);
253
+ // Reset previous output lines counter to ensure clean start
254
+ previousOutputLines = 0;
247
255
  renderToScreen();
248
256
  stdin.on("data", onData);
249
257
  const exitHandler = () => {
@@ -0,0 +1,35 @@
1
+ import type { TokenCounter } from "./counter.ts";
2
+ export declare function clearTokenCache(): void;
3
+ /**
4
+ * Standardized result when token limit is exceeded
5
+ */
6
+ interface TokenLimitResult {
7
+ content: string;
8
+ tokenCount: number;
9
+ truncated: boolean;
10
+ }
11
+ /**
12
+ * Generates a standardized token limit message for LLM tools
13
+ * @param toolName - Name of the tool (e.g., "ReadFile", "Bash")
14
+ * @param tokenCount - Actual token count of content
15
+ * @param maxTokens - Maximum allowed tokens
16
+ * @param additionalGuidance - Optional specific guidance for this tool
17
+ * @returns TokenLimitResult with message and metadata
18
+ */
19
+ export declare function createTokenLimitResult(toolName: string, tokenCount: number, additionalGuidance?: string): TokenLimitResult;
20
+ /**
21
+ * Check if content should be truncated and return appropriate result
22
+ * @param content - The content to check
23
+ * @param tokenCounter - Token counter instance
24
+ * @param toolName - Name of the tool for messages
25
+ * @param additionalGuidance - Optional tool-specific guidance
26
+ * @param encoding - Optional encoding type for non-text file handling
27
+ * @returns Either the original content or token limit message
28
+ */
29
+ export declare function manageTokenLimit<T extends string>(content: T, tokenCounter: TokenCounter, toolName: string, additionalGuidance?: string, encoding?: string): Promise<{
30
+ content: T | string;
31
+ tokenCount: number;
32
+ truncated: boolean;
33
+ }>;
34
+ export {};
35
+ //# sourceMappingURL=threshold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"threshold.d.ts","sourceRoot":"","sources":["../../source/tokens/threshold.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAQjD,wBAAgB,eAAe,SAG9B;AAyBD;;GAEG;AACH,UAAU,gBAAgB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,kBAAkB,CAAC,EAAE,MAAM,GAC1B,gBAAgB,CAgBlB;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,SAAS,MAAM,EACrD,OAAO,EAAE,CAAC,EACV,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,MAAM,EAChB,kBAAkB,CAAC,EAAE,MAAM,EAC3B,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CA+B1E"}
@@ -0,0 +1,85 @@
1
+ import { config } from "../config.js";
2
+ // Cache for maxTokens config to avoid repeated async calls
3
+ let maxTokensCache = null;
4
+ let cacheExpiry = 0;
5
+ const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
6
+ // Export cache management for testing
7
+ export function clearTokenCache() {
8
+ maxTokensCache = null;
9
+ cacheExpiry = 0;
10
+ }
11
+ /**
12
+ * Get maxTokens from config with caching
13
+ */
14
+ async function getMaxTokens() {
15
+ const now = Date.now();
16
+ if (maxTokensCache !== null && now < cacheExpiry) {
17
+ return maxTokensCache;
18
+ }
19
+ try {
20
+ const projectConfig = await config.readProjectConfig();
21
+ maxTokensCache = projectConfig.tools.maxTokens;
22
+ cacheExpiry = now + CACHE_DURATION;
23
+ return maxTokensCache;
24
+ }
25
+ catch (error) {
26
+ console.info("Failed to read config for maxTokens, using default:", error);
27
+ maxTokensCache = 8000; // Default fallback
28
+ cacheExpiry = now + CACHE_DURATION;
29
+ return maxTokensCache;
30
+ }
31
+ }
32
+ /**
33
+ * Generates a standardized token limit message for LLM tools
34
+ * @param toolName - Name of the tool (e.g., "ReadFile", "Bash")
35
+ * @param tokenCount - Actual token count of content
36
+ * @param maxTokens - Maximum allowed tokens
37
+ * @param additionalGuidance - Optional specific guidance for this tool
38
+ * @returns TokenLimitResult with message and metadata
39
+ */
40
+ export function createTokenLimitResult(toolName, tokenCount, additionalGuidance) {
41
+ const truncated = true;
42
+ const baseMessage = `${toolName}: Content (${tokenCount} tokens) exceeds maximum allowed tokens`;
43
+ const guidance = additionalGuidance ??
44
+ "Please adjust your parameters to reduce content size";
45
+ const content = `${baseMessage}. ${guidance}`;
46
+ return {
47
+ content,
48
+ tokenCount,
49
+ truncated,
50
+ };
51
+ }
52
+ /**
53
+ * Check if content should be truncated and return appropriate result
54
+ * @param content - The content to check
55
+ * @param tokenCounter - Token counter instance
56
+ * @param toolName - Name of the tool for messages
57
+ * @param additionalGuidance - Optional tool-specific guidance
58
+ * @param encoding - Optional encoding type for non-text file handling
59
+ * @returns Either the original content or token limit message
60
+ */
61
+ export async function manageTokenLimit(content, tokenCounter, toolName, additionalGuidance, encoding) {
62
+ // For non-text files, return content directly without token management
63
+ if (encoding && !encoding.startsWith("utf")) {
64
+ return { content, tokenCount: 0, truncated: false };
65
+ }
66
+ let tokenCount = 0;
67
+ try {
68
+ tokenCount = tokenCounter.count(content);
69
+ }
70
+ catch (tokenError) {
71
+ console.info("Error calculating token count:", tokenError);
72
+ // Return content if token counting fails
73
+ return { content, tokenCount: 0, truncated: false };
74
+ }
75
+ const maxTokens = await getMaxTokens();
76
+ if (tokenCount <= maxTokens) {
77
+ return { content, tokenCount, truncated: false };
78
+ }
79
+ const limitResult = createTokenLimitResult(toolName, tokenCount, additionalGuidance);
80
+ return {
81
+ content: limitResult.content,
82
+ tokenCount,
83
+ truncated: true,
84
+ };
85
+ }
@@ -0,0 +1,69 @@
1
+ import type { ToolCallOptions } from "ai";
2
+ import { z } from "zod";
3
+ import type { ToolResult } from "./types.ts";
4
+ export declare const AdvancedEditFileTool: {
5
+ name: "advancedEditFile";
6
+ };
7
+ declare const inputSchema: z.ZodObject<{
8
+ path: z.ZodString;
9
+ mode: z.ZodDefault<z.ZodEnum<{
10
+ exact: "exact";
11
+ regex: "regex";
12
+ ast: "ast";
13
+ }>>;
14
+ operations: z.ZodArray<z.ZodObject<{
15
+ type: z.ZodEnum<{
16
+ replace: "replace";
17
+ "insert-before": "insert-before";
18
+ "insert-after": "insert-after";
19
+ delete: "delete";
20
+ }>;
21
+ pattern: z.ZodString;
22
+ replacement: z.ZodOptional<z.ZodString>;
23
+ flags: z.ZodOptional<z.ZodString>;
24
+ }, z.core.$strip>>;
25
+ astPattern: z.ZodOptional<z.ZodString>;
26
+ astReplacement: z.ZodOptional<z.ZodString>;
27
+ dryRun: z.ZodDefault<z.ZodBoolean>;
28
+ }, z.core.$strip>;
29
+ type AdvancedEditFileInputSchema = z.infer<typeof inputSchema>;
30
+ interface FileOperation {
31
+ type: "replace" | "insert-before" | "insert-after" | "delete";
32
+ pattern: string;
33
+ replacement?: string;
34
+ flags?: string;
35
+ }
36
+ export declare const createAdvancedEditFileTool: ({ workingDir, allowedDirs, }: {
37
+ workingDir: string;
38
+ allowedDirs?: string[];
39
+ }) => Promise<{
40
+ toolDef: {
41
+ description: string;
42
+ inputSchema: z.ZodObject<{
43
+ path: z.ZodString;
44
+ mode: z.ZodDefault<z.ZodEnum<{
45
+ exact: "exact";
46
+ regex: "regex";
47
+ ast: "ast";
48
+ }>>;
49
+ operations: z.ZodArray<z.ZodObject<{
50
+ type: z.ZodEnum<{
51
+ replace: "replace";
52
+ "insert-before": "insert-before";
53
+ "insert-after": "insert-after";
54
+ delete: "delete";
55
+ }>;
56
+ pattern: z.ZodString;
57
+ replacement: z.ZodOptional<z.ZodString>;
58
+ flags: z.ZodOptional<z.ZodString>;
59
+ }, z.core.$strip>>;
60
+ astPattern: z.ZodOptional<z.ZodString>;
61
+ astReplacement: z.ZodOptional<z.ZodString>;
62
+ dryRun: z.ZodDefault<z.ZodBoolean>;
63
+ }, z.core.$strip>;
64
+ };
65
+ execute({ path, mode, operations, astPattern, astReplacement, dryRun, }: AdvancedEditFileInputSchema, { toolCallId, abortSignal }: ToolCallOptions): AsyncGenerator<ToolResult>;
66
+ }>;
67
+ export declare function applyAdvancedFileEdits(filePath: string, mode: "exact" | "regex" | "ast", operations: FileOperation[], astPattern?: string, astReplacement?: string, dryRun?: boolean, abortSignal?: AbortSignal): Promise<string>;
68
+ export {};
69
+ //# sourceMappingURL=advanced-edit-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advanced-edit-file.d.ts","sourceRoot":"","sources":["../../source/tools/advanced-edit-file.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAE1C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,eAAO,MAAM,oBAAoB;;CAEhC,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;iBAuCf,CAAC;AAEH,KAAK,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAE/D,UAAU,aAAa;IACrB,IAAI,EAAE,SAAS,GAAG,eAAe,GAAG,cAAc,GAAG,QAAQ,CAAC;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,0BAA0B,GAAU,8BAG9C;IACD,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;;;;;;;;;;;;;;;;;;;;;;;;;;6EAiBQ,2BAA2B,+BACD,eAAe,GAC3C,cAAc,CAAC,UAAU,CAAC;EAgDhC,CAAC;AA2MF,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,EAC/B,UAAU,EAAE,aAAa,EAAE,EAC3B,UAAU,CAAC,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,MAAM,EACvB,MAAM,UAAQ,EACd,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,MAAM,CAAC,CAyEjB"}
@@ -0,0 +1,281 @@
1
+ import { execSync } from "node:child_process";
2
+ import { readFile, writeFile } from "node:fs/promises";
3
+ import { createTwoFilesPatch } from "diff";
4
+ import { z } from "zod";
5
+ import style from "../terminal/style.js";
6
+ import { joinWorkingDir, validatePath } from "./filesystem-utils.js";
7
+ export const AdvancedEditFileTool = {
8
+ name: "advancedEditFile",
9
+ };
10
+ const inputSchema = z.object({
11
+ path: z.string().describe("The path of the file to edit."),
12
+ mode: z
13
+ .enum(["exact", "regex", "ast"])
14
+ .default("exact")
15
+ .describe("Editing mode: exact (literal text), regex (pattern matching), or ast (AST-aware)"),
16
+ operations: z.array(z.object({
17
+ type: z
18
+ .enum(["replace", "insert-before", "insert-after", "delete"])
19
+ .describe("Type of operation to perform"),
20
+ pattern: z
21
+ .string()
22
+ .describe("Pattern to match (text, regex, or AST pattern depending on mode)"),
23
+ replacement: z
24
+ .string()
25
+ .optional()
26
+ .describe("Replacement text (required for replace operations)"),
27
+ flags: z
28
+ .string()
29
+ .optional()
30
+ .describe("Regex flags for regex mode (e.g., 'g', 'i', 'm')"),
31
+ })),
32
+ astPattern: z
33
+ .string()
34
+ .optional()
35
+ .describe("AST-grep search pattern for AST mode (e.g., 'var $V = $VAL')"),
36
+ astReplacement: z
37
+ .string()
38
+ .optional()
39
+ .describe("AST-grep replacement pattern for AST mode (e.g., 'let $V = $VAL')"),
40
+ dryRun: z.boolean().default(false).describe("Show changes without writing"),
41
+ });
42
+ export const createAdvancedEditFileTool = async ({ workingDir, allowedDirs, }) => {
43
+ const allowedDirectory = allowedDirs ?? [workingDir];
44
+ return {
45
+ toolDef: {
46
+ description: "Advanced file editing with multiple modes: exact text matching, regex pattern matching, and AST-aware editing. " +
47
+ "Supports replace, insert-before, insert-after, and delete operations. AST mode requires ast-grep to be installed.",
48
+ inputSchema,
49
+ },
50
+ async *execute({ path, mode, operations, astPattern, astReplacement, dryRun, }, { toolCallId, abortSignal }) {
51
+ try {
52
+ if (abortSignal?.aborted) {
53
+ throw new Error("File editing aborted");
54
+ }
55
+ yield {
56
+ name: AdvancedEditFileTool.name,
57
+ id: toolCallId,
58
+ event: "tool-init",
59
+ data: `${style.cyan(path)} (mode: ${mode})`,
60
+ };
61
+ const validPath = await validatePath(joinWorkingDir(path, workingDir), allowedDirectory, { abortSignal });
62
+ const result = await applyAdvancedFileEdits(validPath, mode, operations, astPattern, astReplacement, dryRun, abortSignal);
63
+ yield {
64
+ name: AdvancedEditFileTool.name,
65
+ id: toolCallId,
66
+ event: "tool-completion",
67
+ data: `Applied ${operations.length} edits`,
68
+ };
69
+ yield result;
70
+ }
71
+ catch (error) {
72
+ yield {
73
+ name: AdvancedEditFileTool.name,
74
+ event: "tool-error",
75
+ id: toolCallId,
76
+ data: error.message,
77
+ };
78
+ yield `Failed to edit file: ${error.message}`;
79
+ }
80
+ },
81
+ };
82
+ };
83
+ // file editing and diffing utilities
84
+ function normalizeLineEndings(text) {
85
+ return text.replace(/\r\n/g, "\n");
86
+ }
87
+ function createUnifiedDiff(originalContent, newContent, filepath = "file") {
88
+ // Ensure consistent line endings for diff
89
+ const normalizedOriginal = normalizeLineEndings(originalContent);
90
+ const normalizedNew = normalizeLineEndings(newContent);
91
+ return createTwoFilesPatch(filepath, filepath, normalizedOriginal, normalizedNew, "original", "modified");
92
+ }
93
+ function applyExactModeEdits(content, operations) {
94
+ let modifiedContent = content;
95
+ for (const op of operations) {
96
+ switch (op.type) {
97
+ case "replace": {
98
+ if (!op.replacement) {
99
+ throw new Error("Replacement text required for replace operation");
100
+ }
101
+ // Exact text replacement (global)
102
+ let currentIndex = 0;
103
+ let matchCount = 0;
104
+ while (currentIndex < modifiedContent.length) {
105
+ const matchIndex = modifiedContent.indexOf(op.pattern, currentIndex);
106
+ if (matchIndex === -1) {
107
+ break;
108
+ }
109
+ matchCount++;
110
+ modifiedContent =
111
+ modifiedContent.slice(0, matchIndex) +
112
+ op.replacement +
113
+ modifiedContent.slice(matchIndex + op.pattern.length);
114
+ currentIndex = matchIndex + op.replacement.length;
115
+ }
116
+ if (matchCount === 0) {
117
+ throw new Error(`Pattern not found in content: ${op.pattern}`);
118
+ }
119
+ break;
120
+ }
121
+ case "insert-before": {
122
+ if (!op.replacement) {
123
+ throw new Error("Replacement text required for insert-before operation");
124
+ }
125
+ const beforeIndex = modifiedContent.indexOf(op.pattern);
126
+ if (beforeIndex === -1) {
127
+ throw new Error(`Pattern not found for insert-before: ${op.pattern}`);
128
+ }
129
+ modifiedContent =
130
+ modifiedContent.slice(0, beforeIndex) +
131
+ op.replacement +
132
+ "\n" +
133
+ modifiedContent.slice(beforeIndex);
134
+ break;
135
+ }
136
+ case "insert-after": {
137
+ if (!op.replacement) {
138
+ throw new Error("Replacement text required for insert-after operation");
139
+ }
140
+ const afterIndex = modifiedContent.indexOf(op.pattern);
141
+ if (afterIndex === -1) {
142
+ throw new Error(`Pattern not found for insert-after: ${op.pattern}`);
143
+ }
144
+ const insertPosition = afterIndex + op.pattern.length;
145
+ modifiedContent =
146
+ modifiedContent.slice(0, insertPosition) +
147
+ "\n" +
148
+ op.replacement +
149
+ modifiedContent.slice(insertPosition);
150
+ break;
151
+ }
152
+ case "delete": {
153
+ // For delete operations, use line-based approach to handle newlines properly
154
+ const lines = modifiedContent.split("\n");
155
+ const filteredLines = lines.filter((line) => !line.includes(op.pattern));
156
+ if (filteredLines.length === lines.length) {
157
+ throw new Error(`Pattern not found for delete: ${op.pattern}`);
158
+ }
159
+ modifiedContent = filteredLines.join("\n");
160
+ break;
161
+ }
162
+ }
163
+ }
164
+ return modifiedContent;
165
+ }
166
+ function applyRegexModeEdits(content, operations) {
167
+ let modifiedContent = content;
168
+ for (const op of operations) {
169
+ const flags = op.flags || "g";
170
+ const regex = new RegExp(op.pattern, flags);
171
+ switch (op.type) {
172
+ case "replace":
173
+ if (!op.replacement) {
174
+ throw new Error("Replacement text required for replace operation");
175
+ }
176
+ modifiedContent = modifiedContent.replace(regex, op.replacement);
177
+ break;
178
+ case "insert-before":
179
+ if (!op.replacement) {
180
+ throw new Error("Replacement text required for insert-before operation");
181
+ }
182
+ modifiedContent = modifiedContent.replace(regex, `${op.replacement}\n$&`);
183
+ break;
184
+ case "insert-after":
185
+ if (!op.replacement) {
186
+ throw new Error("Replacement text required for insert-after operation");
187
+ }
188
+ modifiedContent = modifiedContent.replace(regex, `$&\n${op.replacement}`);
189
+ break;
190
+ case "delete":
191
+ modifiedContent = modifiedContent.replace(regex, "");
192
+ break;
193
+ }
194
+ }
195
+ return modifiedContent;
196
+ }
197
+ function applyAstModeEdits(filePath, astPattern, astReplacement, dryRun) {
198
+ if (!astPattern || !astReplacement) {
199
+ throw new Error("AST mode requires both astPattern and astReplacement");
200
+ }
201
+ try {
202
+ const cmd = [
203
+ "ast-grep",
204
+ "--pattern",
205
+ `"${astPattern}"`,
206
+ "--rewrite",
207
+ `"${astReplacement}"`,
208
+ dryRun ? "--dry-run" : "--write",
209
+ filePath,
210
+ ].join(" ");
211
+ if (dryRun) {
212
+ const output = execSync(cmd, { encoding: "utf-8" });
213
+ return `AST edit preview:\n${output}`;
214
+ }
215
+ execSync(cmd, { stdio: "inherit" });
216
+ return `AST edit applied to ${filePath}`;
217
+ }
218
+ catch (err) {
219
+ throw new Error(`AST edit failed: ${err.message}`);
220
+ }
221
+ }
222
+ export async function applyAdvancedFileEdits(filePath, mode, operations, astPattern, astReplacement, dryRun = false, abortSignal) {
223
+ if (abortSignal?.aborted) {
224
+ throw new Error("File edit operation aborted");
225
+ }
226
+ // Read file content literally with signal
227
+ const originalContent = await readFile(filePath, {
228
+ encoding: "utf-8",
229
+ signal: abortSignal,
230
+ });
231
+ let modifiedContent = originalContent;
232
+ let resultMessage = "";
233
+ if (mode === "ast") {
234
+ // AST mode uses external ast-grep tool
235
+ if (!astPattern || !astReplacement) {
236
+ throw new Error("AST mode requires both astPattern and astReplacement");
237
+ }
238
+ resultMessage = applyAstModeEdits(filePath, astPattern, astReplacement, dryRun);
239
+ if (dryRun) {
240
+ return resultMessage;
241
+ }
242
+ // For actual AST edits, read the modified content back
243
+ modifiedContent = await readFile(filePath, {
244
+ encoding: "utf-8",
245
+ signal: abortSignal,
246
+ });
247
+ }
248
+ else {
249
+ // Text-based modes (exact and regex)
250
+ if (operations.length === 0) {
251
+ throw new Error("No operations specified for text-based editing mode");
252
+ }
253
+ switch (mode) {
254
+ case "exact":
255
+ modifiedContent = applyExactModeEdits(originalContent, operations);
256
+ break;
257
+ case "regex":
258
+ modifiedContent = applyRegexModeEdits(originalContent, operations);
259
+ break;
260
+ }
261
+ // Create unified diff
262
+ const diff = createUnifiedDiff(originalContent, modifiedContent, filePath);
263
+ // Format diff with appropriate number of backticks
264
+ let numBackticks = 3;
265
+ while (diff.includes("`".repeat(numBackticks))) {
266
+ numBackticks++;
267
+ }
268
+ resultMessage = `${"`".repeat(numBackticks)}diff\n${diff}${"`".repeat(numBackticks)}\n\n`;
269
+ if (!dryRun) {
270
+ if (abortSignal?.aborted) {
271
+ throw new Error("File edit operation aborted before writing");
272
+ }
273
+ // Write the modified content with signal
274
+ await writeFile(filePath, modifiedContent, {
275
+ encoding: "utf-8",
276
+ signal: abortSignal,
277
+ });
278
+ }
279
+ }
280
+ return resultMessage;
281
+ }
@@ -1,18 +1,29 @@
1
+ import { type ToolCallOptions } from "ai";
2
+ import { z } from "zod";
3
+ import type { WorkspaceContext } from "../index.ts";
1
4
  import type { ModelManager } from "../models/manager.ts";
2
5
  import type { TokenCounter } from "../tokens/counter.ts";
3
6
  import type { TokenTracker } from "../tokens/tracker.ts";
4
- import type { SendData } from "./types.ts";
7
+ import type { ToolResult } from "./types.ts";
5
8
  export declare const AgentTool: {
6
9
  name: "agent";
7
10
  };
11
+ declare const inputSchema: z.ZodObject<{
12
+ prompt: z.ZodString;
13
+ }, z.core.$strip>;
8
14
  export declare const createAgentTools: (options: {
9
15
  modelManager: ModelManager;
10
16
  tokenTracker: TokenTracker;
11
17
  tokenCounter: TokenCounter;
12
- sendData?: SendData | undefined;
18
+ workspace: WorkspaceContext;
13
19
  }) => {
14
- agent: import("ai").Tool<{
15
- prompt: string;
16
- }, string>;
20
+ toolDef: {
21
+ description: string;
22
+ inputSchema: z.ZodObject<{
23
+ prompt: z.ZodString;
24
+ }, z.core.$strip>;
25
+ };
26
+ execute: ({ prompt }: z.infer<typeof inputSchema>, { toolCallId, abortSignal }: ToolCallOptions) => AsyncGenerator<ToolResult>;
17
27
  };
28
+ export {};
18
29
  //# sourceMappingURL=agent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../source/tools/agent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAOzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,eAAO,MAAM,SAAS;;CAErB,CAAC;AA+BF,eAAO,MAAM,gBAAgB,GAAI,SAAS;IACxC,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;CACjC;;;;CAyDA,CAAC"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../source/tools/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,eAAe,EAAE,MAAM,IAAI,CAAC;AACrE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAOzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,eAAO,MAAM,SAAS;;CAErB,CAAC;AAiCF,QAAA,MAAM,WAAW;;iBAEf,CAAC;AAEH,eAAO,MAAM,gBAAgB,GAAI,SAAS;IACxC,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,SAAS,EAAE,gBAAgB,CAAC;CAC7B;;;;;;;0BASe,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,+BACV,eAAe,KAC3C,cAAc,CAAC,UAAU,CAAC;CA8D9B,CAAC"}