@travisennis/acai 0.0.11 → 0.0.13

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 (292) hide show
  1. package/README.md +5 -5
  2. package/dist/agent/index.d.ts.map +1 -1
  3. package/dist/agent/index.js +2 -5
  4. package/dist/commands/history/types.d.ts +3 -2
  5. package/dist/commands/history/types.d.ts.map +1 -1
  6. package/dist/commands/init-project/utils.d.ts +0 -1
  7. package/dist/commands/init-project/utils.d.ts.map +1 -1
  8. package/dist/commands/init-project/utils.js +1 -12
  9. package/dist/commands/manager.d.ts.map +1 -1
  10. package/dist/commands/manager.js +6 -19
  11. package/dist/commands/resources/index.d.ts.map +1 -1
  12. package/dist/commands/resources/index.js +4 -1
  13. package/dist/commands/session/index.d.ts.map +1 -1
  14. package/dist/commands/session/index.js +6 -0
  15. package/dist/commands/session/types.d.ts +1 -0
  16. package/dist/commands/session/types.d.ts.map +1 -1
  17. package/dist/commands/share/html-renderer.d.ts.map +1 -1
  18. package/dist/commands/share/html-renderer.js +54 -48
  19. package/dist/commands/tools/index.d.ts +3 -0
  20. package/dist/commands/tools/index.d.ts.map +1 -0
  21. package/dist/commands/tools/index.js +191 -0
  22. package/dist/commands/tools/templates.d.ts +6 -0
  23. package/dist/commands/tools/templates.d.ts.map +1 -0
  24. package/dist/commands/tools/templates.js +97 -0
  25. package/dist/config/index.d.ts +5 -2
  26. package/dist/config/index.d.ts.map +1 -1
  27. package/dist/config/index.js +42 -6
  28. package/dist/index.d.ts +14 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +98 -68
  31. package/dist/models/anthropic-provider.d.ts +1 -1
  32. package/dist/models/deepseek-provider.d.ts +3 -3
  33. package/dist/models/deepseek-provider.js +17 -17
  34. package/dist/models/google-provider.d.ts +2 -4
  35. package/dist/models/google-provider.d.ts.map +1 -1
  36. package/dist/models/google-provider.js +2 -17
  37. package/dist/models/groq-provider.d.ts +2 -4
  38. package/dist/models/groq-provider.d.ts.map +1 -1
  39. package/dist/models/groq-provider.js +3 -21
  40. package/dist/models/manager.d.ts +1 -10
  41. package/dist/models/manager.d.ts.map +1 -1
  42. package/dist/models/manager.js +2 -2
  43. package/dist/models/opencode-go-provider.d.ts +11 -1
  44. package/dist/models/opencode-go-provider.d.ts.map +1 -1
  45. package/dist/models/opencode-go-provider.js +130 -0
  46. package/dist/models/opencode-zen-provider.d.ts +3 -3
  47. package/dist/models/opencode-zen-provider.d.ts.map +1 -1
  48. package/dist/models/opencode-zen-provider.js +26 -32
  49. package/dist/models/openrouter-provider.d.ts +4 -15
  50. package/dist/models/openrouter-provider.d.ts.map +1 -1
  51. package/dist/models/openrouter-provider.js +26 -169
  52. package/dist/models/providers.d.ts +1 -1
  53. package/dist/models/providers.d.ts.map +1 -1
  54. package/dist/models/xai-provider.d.ts +1 -2
  55. package/dist/models/xai-provider.d.ts.map +1 -1
  56. package/dist/models/xai-provider.js +0 -13
  57. package/dist/prompts/manager.d.ts.map +1 -1
  58. package/dist/prompts/manager.js +5 -1
  59. package/dist/prompts/system-prompt.d.ts +1 -2
  60. package/dist/prompts/system-prompt.d.ts.map +1 -1
  61. package/dist/prompts/system-prompt.js +26 -15
  62. package/dist/repl/index.d.ts +28 -13
  63. package/dist/repl/index.d.ts.map +1 -1
  64. package/dist/repl/index.js +242 -305
  65. package/dist/skills/activated-tracker.d.ts +11 -0
  66. package/dist/skills/activated-tracker.d.ts.map +1 -0
  67. package/dist/skills/activated-tracker.js +16 -0
  68. package/dist/skills/index.d.ts +12 -2
  69. package/dist/skills/index.d.ts.map +1 -1
  70. package/dist/skills/index.js +127 -71
  71. package/dist/terminal/control.d.ts +1 -21
  72. package/dist/terminal/control.d.ts.map +1 -1
  73. package/dist/terminal/control.js +1 -32
  74. package/dist/terminal/formatting.d.ts +0 -33
  75. package/dist/terminal/formatting.d.ts.map +1 -1
  76. package/dist/terminal/formatting.js +0 -91
  77. package/dist/terminal/highlight/theme.d.ts +0 -37
  78. package/dist/terminal/highlight/theme.d.ts.map +1 -1
  79. package/dist/terminal/highlight/theme.js +1 -79
  80. package/dist/terminal/keys.d.ts +0 -97
  81. package/dist/terminal/keys.d.ts.map +1 -1
  82. package/dist/terminal/keys.js +0 -194
  83. package/dist/terminal/select-prompt.d.ts.map +1 -1
  84. package/dist/terminal/select-prompt.js +65 -51
  85. package/dist/terminal/style.d.ts +1 -1
  86. package/dist/terminal/style.d.ts.map +1 -1
  87. package/dist/terminal/supports-color.d.ts.map +1 -1
  88. package/dist/terminal/supports-color.js +38 -20
  89. package/dist/terminal/supports-hyperlinks.d.ts +3 -0
  90. package/dist/terminal/supports-hyperlinks.d.ts.map +1 -1
  91. package/dist/terminal/supports-hyperlinks.js +72 -31
  92. package/dist/terminal/table/layout-manager.d.ts +0 -20
  93. package/dist/terminal/table/layout-manager.d.ts.map +1 -1
  94. package/dist/terminal/table/layout-manager.js +68 -44
  95. package/dist/terminal/table/utils.d.ts +0 -1
  96. package/dist/terminal/table/utils.d.ts.map +1 -1
  97. package/dist/terminal/table/utils.js +2 -4
  98. package/dist/tools/apply-patch.d.ts +5 -3
  99. package/dist/tools/apply-patch.d.ts.map +1 -1
  100. package/dist/tools/apply-patch.js +154 -123
  101. package/dist/tools/bash.d.ts +4 -4
  102. package/dist/tools/bash.d.ts.map +1 -1
  103. package/dist/tools/bash.js +27 -13
  104. package/dist/tools/dynamic-tool-loader.d.ts +17 -3
  105. package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
  106. package/dist/tools/dynamic-tool-loader.js +360 -81
  107. package/dist/tools/edit-file.d.ts +2 -2
  108. package/dist/tools/index.d.ts +27 -151
  109. package/dist/tools/index.d.ts.map +1 -1
  110. package/dist/tools/index.js +16 -21
  111. package/dist/tools/read-file.d.ts +8 -8
  112. package/dist/tools/read-file.d.ts.map +1 -1
  113. package/dist/tools/read-file.js +32 -13
  114. package/dist/tools/save-file.d.ts +4 -4
  115. package/dist/tools/skill.d.ts +2 -1
  116. package/dist/tools/skill.d.ts.map +1 -1
  117. package/dist/tools/skill.js +64 -14
  118. package/dist/tools/types.d.ts +8 -2
  119. package/dist/tools/types.d.ts.map +1 -1
  120. package/dist/tools/web-fetch.d.ts +8 -12
  121. package/dist/tools/web-fetch.d.ts.map +1 -1
  122. package/dist/tools/web-fetch.js +86 -44
  123. package/dist/tools/web-search.d.ts +4 -8
  124. package/dist/tools/web-search.d.ts.map +1 -1
  125. package/dist/tools/web-search.js +41 -33
  126. package/dist/tui/autocomplete/utils.d.ts +0 -15
  127. package/dist/tui/autocomplete/utils.d.ts.map +1 -1
  128. package/dist/tui/autocomplete/utils.js +0 -85
  129. package/dist/tui/autocomplete.d.ts +1 -1
  130. package/dist/tui/autocomplete.d.ts.map +1 -1
  131. package/dist/tui/autocomplete.js +1 -1
  132. package/dist/tui/components/editor.d.ts +12 -0
  133. package/dist/tui/components/editor.d.ts.map +1 -1
  134. package/dist/tui/components/editor.js +181 -195
  135. package/dist/tui/components/footer.d.ts +0 -2
  136. package/dist/tui/components/footer.d.ts.map +1 -1
  137. package/dist/tui/components/footer.js +1 -17
  138. package/dist/tui/components/input.d.ts +4 -0
  139. package/dist/tui/components/input.d.ts.map +1 -1
  140. package/dist/tui/components/input.js +33 -31
  141. package/dist/tui/components/markdown.d.ts +30 -0
  142. package/dist/tui/components/markdown.d.ts.map +1 -1
  143. package/dist/tui/components/markdown.js +274 -242
  144. package/dist/tui/components/modal.d.ts.map +1 -1
  145. package/dist/tui/components/modal.js +11 -11
  146. package/dist/tui/components/select-list.d.ts +5 -0
  147. package/dist/tui/components/select-list.d.ts.map +1 -1
  148. package/dist/tui/components/select-list.js +69 -98
  149. package/dist/tui/components/table.d.ts +6 -0
  150. package/dist/tui/components/table.d.ts.map +1 -1
  151. package/dist/tui/components/table.js +61 -52
  152. package/dist/tui/index.d.ts +1 -8
  153. package/dist/tui/index.d.ts.map +1 -1
  154. package/dist/tui/index.js +0 -8
  155. package/dist/tui/tui.d.ts +9 -0
  156. package/dist/tui/tui.d.ts.map +1 -1
  157. package/dist/tui/tui.js +78 -48
  158. package/dist/tui/utils.d.ts +7 -0
  159. package/dist/tui/utils.d.ts.map +1 -1
  160. package/dist/tui/utils.js +117 -53
  161. package/dist/utils/bash.d.ts.map +1 -1
  162. package/dist/utils/bash.js +121 -104
  163. package/dist/utils/binary-output.d.ts +32 -0
  164. package/dist/utils/binary-output.d.ts.map +1 -0
  165. package/dist/utils/binary-output.js +127 -0
  166. package/dist/utils/command-protection.d.ts +3 -2
  167. package/dist/utils/command-protection.d.ts.map +1 -1
  168. package/dist/utils/command-protection.js +121 -29
  169. package/dist/utils/filesystem/operations.d.ts +0 -15
  170. package/dist/utils/filesystem/operations.d.ts.map +1 -1
  171. package/dist/utils/filesystem/operations.js +1 -38
  172. package/dist/utils/filesystem/security.d.ts.map +1 -1
  173. package/dist/utils/filesystem/security.js +22 -15
  174. package/dist/utils/filetype-detection.d.ts +0 -1
  175. package/dist/utils/filetype-detection.d.ts.map +1 -1
  176. package/dist/utils/filetype-detection.js +0 -12
  177. package/dist/utils/formatting.d.ts +0 -30
  178. package/dist/utils/formatting.d.ts.map +1 -1
  179. package/dist/utils/formatting.js +0 -44
  180. package/dist/utils/git.d.ts +4 -6
  181. package/dist/utils/git.d.ts.map +1 -1
  182. package/dist/utils/git.js +36 -46
  183. package/dist/utils/ignore.d.ts +1 -1
  184. package/dist/utils/ignore.d.ts.map +1 -1
  185. package/dist/utils/ignore.js +1 -1
  186. package/dist/utils/parsing.d.ts +1 -1
  187. package/dist/utils/parsing.d.ts.map +1 -1
  188. package/dist/utils/process.d.ts.map +1 -1
  189. package/dist/utils/process.js +77 -79
  190. package/dist/utils/yaml.d.ts +0 -1
  191. package/dist/utils/yaml.d.ts.map +1 -1
  192. package/dist/utils/yaml.js +80 -89
  193. package/dist/utils/zod.d.ts +0 -3
  194. package/dist/utils/zod.d.ts.map +1 -1
  195. package/dist/utils/zod.js +0 -7
  196. package/package.json +32 -29
  197. package/dist/agent/sub-agent.d.ts +0 -23
  198. package/dist/agent/sub-agent.d.ts.map +0 -1
  199. package/dist/agent/sub-agent.js +0 -109
  200. package/dist/commands/add-directory/index.d.ts +0 -3
  201. package/dist/commands/add-directory/index.d.ts.map +0 -1
  202. package/dist/commands/add-directory/index.js +0 -50
  203. package/dist/commands/add-directory/utils.d.ts +0 -3
  204. package/dist/commands/add-directory/utils.d.ts.map +0 -1
  205. package/dist/commands/add-directory/utils.js +0 -15
  206. package/dist/commands/clear/index.d.ts +0 -3
  207. package/dist/commands/clear/index.d.ts.map +0 -1
  208. package/dist/commands/clear/index.js +0 -13
  209. package/dist/commands/generate-rules/index.d.ts +0 -3
  210. package/dist/commands/generate-rules/index.d.ts.map +0 -1
  211. package/dist/commands/generate-rules/index.js +0 -206
  212. package/dist/commands/generate-rules/service.d.ts +0 -22
  213. package/dist/commands/generate-rules/service.d.ts.map +0 -1
  214. package/dist/commands/generate-rules/service.js +0 -103
  215. package/dist/commands/generate-rules/utils.d.ts +0 -5
  216. package/dist/commands/generate-rules/utils.d.ts.map +0 -1
  217. package/dist/commands/generate-rules/utils.js +0 -25
  218. package/dist/commands/handoff/index.d.ts +0 -3
  219. package/dist/commands/handoff/index.d.ts.map +0 -1
  220. package/dist/commands/handoff/index.js +0 -97
  221. package/dist/commands/handoff/utils.d.ts +0 -4
  222. package/dist/commands/handoff/utils.d.ts.map +0 -1
  223. package/dist/commands/handoff/utils.js +0 -123
  224. package/dist/commands/list-directories/index.d.ts +0 -3
  225. package/dist/commands/list-directories/index.d.ts.map +0 -1
  226. package/dist/commands/list-directories/index.js +0 -35
  227. package/dist/commands/pickup/index.d.ts +0 -3
  228. package/dist/commands/pickup/index.d.ts.map +0 -1
  229. package/dist/commands/pickup/index.js +0 -141
  230. package/dist/commands/pickup/types.d.ts +0 -6
  231. package/dist/commands/pickup/types.d.ts.map +0 -1
  232. package/dist/commands/pickup/types.js +0 -1
  233. package/dist/commands/pickup/utils.d.ts +0 -7
  234. package/dist/commands/pickup/utils.d.ts.map +0 -1
  235. package/dist/commands/pickup/utils.js +0 -56
  236. package/dist/commands/remove-directory/index.d.ts +0 -3
  237. package/dist/commands/remove-directory/index.d.ts.map +0 -1
  238. package/dist/commands/remove-directory/index.js +0 -55
  239. package/dist/commands/review/index.d.ts +0 -3
  240. package/dist/commands/review/index.d.ts.map +0 -1
  241. package/dist/commands/review/index.js +0 -12
  242. package/dist/commands/review/review-panel.d.ts +0 -3
  243. package/dist/commands/review/review-panel.d.ts.map +0 -1
  244. package/dist/commands/review/review-panel.js +0 -186
  245. package/dist/commands/review/utils.d.ts +0 -18
  246. package/dist/commands/review/utils.d.ts.map +0 -1
  247. package/dist/commands/review/utils.js +0 -146
  248. package/dist/commands/shell/index.d.ts +0 -3
  249. package/dist/commands/shell/index.d.ts.map +0 -1
  250. package/dist/commands/shell/index.js +0 -96
  251. package/dist/modes/manager.d.ts +0 -24
  252. package/dist/modes/manager.d.ts.map +0 -1
  253. package/dist/modes/manager.js +0 -77
  254. package/dist/modes/prompts.d.ts +0 -2
  255. package/dist/modes/prompts.d.ts.map +0 -1
  256. package/dist/modes/prompts.js +0 -142
  257. package/dist/subagents/index.d.ts +0 -16
  258. package/dist/subagents/index.d.ts.map +0 -1
  259. package/dist/subagents/index.js +0 -231
  260. package/dist/terminal/index.d.ts +0 -9
  261. package/dist/terminal/index.d.ts.map +0 -1
  262. package/dist/terminal/index.js +0 -8
  263. package/dist/tools/agent.d.ts +0 -27
  264. package/dist/tools/agent.d.ts.map +0 -1
  265. package/dist/tools/agent.js +0 -81
  266. package/dist/tools/directory-tree.d.ts +0 -28
  267. package/dist/tools/directory-tree.d.ts.map +0 -1
  268. package/dist/tools/directory-tree.js +0 -152
  269. package/dist/tools/glob.d.ts +0 -35
  270. package/dist/tools/glob.d.ts.map +0 -1
  271. package/dist/tools/glob.js +0 -159
  272. package/dist/tools/grep.d.ts +0 -100
  273. package/dist/tools/grep.d.ts.map +0 -1
  274. package/dist/tools/grep.js +0 -601
  275. package/dist/tools/ls.d.ts +0 -26
  276. package/dist/tools/ls.d.ts.map +0 -1
  277. package/dist/tools/ls.js +0 -82
  278. package/dist/tui/components/header.d.ts +0 -21
  279. package/dist/tui/components/header.d.ts.map +0 -1
  280. package/dist/tui/components/header.js +0 -63
  281. package/dist/utils/bash/parse.d.ts +0 -19
  282. package/dist/utils/bash/parse.d.ts.map +0 -1
  283. package/dist/utils/bash/parse.js +0 -223
  284. package/dist/utils/bash/quote.d.ts +0 -6
  285. package/dist/utils/bash/quote.d.ts.map +0 -1
  286. package/dist/utils/bash/quote.js +0 -23
  287. package/dist/utils/generators.d.ts +0 -3
  288. package/dist/utils/generators.d.ts.map +0 -1
  289. package/dist/utils/generators.js +0 -25
  290. package/dist/utils/glob.d.ts +0 -52
  291. package/dist/utils/glob.d.ts.map +0 -1
  292. package/dist/utils/glob.js +0 -376
@@ -38,47 +38,53 @@ function parsePatchHeader(lines, startIdx) {
38
38
  }
39
39
  return null;
40
40
  }
41
+ function parseOneChunk(lines, startIdx) {
42
+ const contextLine = lines[startIdx].substring(2).trim();
43
+ let i = startIdx + 1;
44
+ const oldLines = [];
45
+ const newLines = [];
46
+ let isEndOfFile = false;
47
+ while (i < lines.length && !lines[i].startsWith("@@")) {
48
+ const changeLine = lines[i];
49
+ if (changeLine === "*** End of File") {
50
+ isEndOfFile = true;
51
+ i++;
52
+ break;
53
+ }
54
+ if (changeLine.startsWith("***")) {
55
+ break;
56
+ }
57
+ if (changeLine.startsWith(" ")) {
58
+ const content = changeLine.substring(1);
59
+ oldLines.push(content);
60
+ newLines.push(content);
61
+ }
62
+ else if (changeLine.startsWith("-")) {
63
+ oldLines.push(changeLine.substring(1));
64
+ }
65
+ else if (changeLine.startsWith("+")) {
66
+ newLines.push(changeLine.substring(1));
67
+ }
68
+ i++;
69
+ }
70
+ return {
71
+ chunk: {
72
+ oldLines,
73
+ newLines,
74
+ changeContext: contextLine || undefined,
75
+ isEndOfFile: isEndOfFile || undefined,
76
+ },
77
+ nextIdx: i,
78
+ };
79
+ }
41
80
  function parseUpdateFileChunks(lines, startIdx) {
42
81
  const chunks = [];
43
82
  let i = startIdx;
44
83
  while (i < lines.length && !lines[i].startsWith("***")) {
45
84
  if (lines[i].startsWith("@@")) {
46
- const contextLine = lines[i].substring(2).trim();
47
- i++;
48
- const oldLines = [];
49
- const newLines = [];
50
- let isEndOfFile = false;
51
- while (i < lines.length && !lines[i].startsWith("@@")) {
52
- const changeLine = lines[i];
53
- // Check for end of file marker first (before general *** check)
54
- if (changeLine === "*** End of File") {
55
- isEndOfFile = true;
56
- i++;
57
- break;
58
- }
59
- // Check for other *** markers (new file operations)
60
- if (changeLine.startsWith("***")) {
61
- break;
62
- }
63
- if (changeLine.startsWith(" ")) {
64
- const content = changeLine.substring(1);
65
- oldLines.push(content);
66
- newLines.push(content);
67
- }
68
- else if (changeLine.startsWith("-")) {
69
- oldLines.push(changeLine.substring(1));
70
- }
71
- else if (changeLine.startsWith("+")) {
72
- newLines.push(changeLine.substring(1));
73
- }
74
- i++;
75
- }
76
- chunks.push({
77
- oldLines,
78
- newLines,
79
- changeContext: contextLine || undefined,
80
- isEndOfFile: isEndOfFile || undefined,
81
- });
85
+ const { chunk, nextIdx } = parseOneChunk(lines, i);
86
+ chunks.push(chunk);
87
+ i = nextIdx;
82
88
  }
83
89
  else {
84
90
  i++;
@@ -175,36 +181,50 @@ function applyReplacements(lines, replacements) {
175
181
  }
176
182
  return result;
177
183
  }
178
- function computeReplacements(originalLines, filePath, chunks) {
184
+ function findContextLine(originalLines, changeContext, lineIndex, filePath) {
185
+ const contextIdx = seekSequence(originalLines, [changeContext], lineIndex);
186
+ if (contextIdx === -1) {
187
+ throw new Error(`Failed to find context '${changeContext}' in ${filePath}`);
188
+ }
189
+ return contextIdx + 1;
190
+ }
191
+ function computeInsertionIndex(originalLines) {
192
+ return originalLines.length > 0 &&
193
+ originalLines[originalLines.length - 1] === ""
194
+ ? originalLines.length - 1
195
+ : originalLines.length;
196
+ }
197
+ function findPatternWithFallback(originalLines, oldLines, newLines, lineIndex) {
198
+ let pattern = oldLines;
199
+ let newSlice = newLines;
200
+ let found = seekSequence(originalLines, pattern, lineIndex);
201
+ if (found === -1 &&
202
+ pattern.length > 0 &&
203
+ pattern[pattern.length - 1] === "") {
204
+ pattern = pattern.slice(0, -1);
205
+ if (newSlice.length > 0 && newSlice[newSlice.length - 1] === "") {
206
+ newSlice = newSlice.slice(0, -1);
207
+ }
208
+ found = seekSequence(originalLines, pattern, lineIndex);
209
+ }
210
+ return { pattern, newSlice, found };
211
+ }
212
+ export function computeReplacements(originalLines, filePath, chunks) {
179
213
  const replacements = [];
180
214
  let lineIndex = 0;
181
215
  for (const chunk of chunks) {
182
216
  if (chunk.changeContext) {
183
- const contextIdx = seekSequence(originalLines, [chunk.changeContext], lineIndex);
184
- if (contextIdx === -1) {
185
- throw new Error(`Failed to find context '${chunk.changeContext}' in ${filePath}`);
186
- }
187
- lineIndex = contextIdx + 1;
217
+ lineIndex = findContextLine(originalLines, chunk.changeContext, lineIndex, filePath);
188
218
  }
189
219
  if (chunk.oldLines.length === 0) {
190
- const insertionIdx = originalLines.length > 0 &&
191
- originalLines[originalLines.length - 1] === ""
192
- ? originalLines.length - 1
193
- : originalLines.length;
194
- replacements.push([insertionIdx, 0, chunk.newLines]);
220
+ replacements.push([
221
+ computeInsertionIndex(originalLines),
222
+ 0,
223
+ chunk.newLines,
224
+ ]);
195
225
  continue;
196
226
  }
197
- let pattern = chunk.oldLines;
198
- let newSlice = chunk.newLines;
199
- let found = seekSequence(originalLines, pattern, lineIndex);
200
- if (found === -1 &&
201
- pattern.length > 0 &&
202
- pattern[pattern.length - 1] === "") {
203
- pattern = pattern.slice(0, -1);
204
- if (newSlice.length > 0 && newSlice[newSlice.length - 1] === "")
205
- newSlice = newSlice.slice(0, -1);
206
- found = seekSequence(originalLines, pattern, lineIndex);
207
- }
227
+ const { pattern, newSlice, found } = findPatternWithFallback(originalLines, chunk.oldLines, chunk.newLines, lineIndex);
208
228
  if (found !== -1) {
209
229
  replacements.push([found, pattern.length, newSlice]);
210
230
  lineIndex = found + pattern.length;
@@ -242,39 +262,91 @@ function deriveNewContentsFromChunks(fileAbsPath, chunks) {
242
262
  content: newContent,
243
263
  };
244
264
  }
245
- async function applyChanges(changes, signal) {
265
+ async function applyAddChange(change, changed) {
266
+ const dir = path.dirname(change.path);
267
+ if (dir !== "." && dir !== "/")
268
+ await fsp.mkdir(dir, { recursive: true });
269
+ await fsp.writeFile(change.path, change.content, "utf-8");
270
+ changed.push(change.path);
271
+ }
272
+ async function applyDeleteChange(change, changed) {
273
+ await fsp.unlink(change.path).catch(() => { });
274
+ changed.push(change.path);
275
+ }
276
+ async function applyUpdateChange(change, changed) {
277
+ if (change.movePath) {
278
+ const dir = path.dirname(change.movePath);
279
+ if (dir !== "." && dir !== "/")
280
+ await fsp.mkdir(dir, { recursive: true });
281
+ await fsp.writeFile(change.movePath, change.newContent, "utf-8");
282
+ await fsp.unlink(change.path).catch(() => { });
283
+ changed.push(change.movePath);
284
+ return;
285
+ }
286
+ await fsp.writeFile(change.path, change.newContent, "utf-8");
287
+ changed.push(change.path);
288
+ }
289
+ export async function applyChanges(changes, signal) {
246
290
  const changed = [];
247
291
  for (const change of changes) {
248
292
  if (signal?.aborted)
249
293
  throw new Error("Cancelled");
250
294
  if (change.type === "add") {
251
- const dir = path.dirname(change.path);
252
- if (dir !== "." && dir !== "/")
253
- await fsp.mkdir(dir, { recursive: true });
254
- await fsp.writeFile(change.path, change.content, "utf-8");
255
- changed.push(change.path);
295
+ await applyAddChange(change, changed);
256
296
  continue;
257
297
  }
258
298
  if (change.type === "delete") {
259
- await fsp.unlink(change.path).catch(() => { });
260
- changed.push(change.path);
261
- continue;
262
- }
263
- // update
264
- if (change.movePath) {
265
- const dir = path.dirname(change.movePath);
266
- if (dir !== "." && dir !== "/")
267
- await fsp.mkdir(dir, { recursive: true });
268
- await fsp.writeFile(change.movePath, change.newContent, "utf-8");
269
- await fsp.unlink(change.path).catch(() => { });
270
- changed.push(change.movePath);
299
+ await applyDeleteChange(change, changed);
271
300
  continue;
272
301
  }
273
- await fsp.writeFile(change.path, change.newContent, "utf-8");
274
- changed.push(change.path);
302
+ await applyUpdateChange(change, changed);
275
303
  }
276
304
  return changed;
277
305
  }
306
+ async function processHunk(hunk, root, allowedDirectories, projectConfig, primaryDir, abortSignal) {
307
+ if (abortSignal?.aborted) {
308
+ throw new Error("Cancelled");
309
+ }
310
+ const p = resolvePathInRoot(root, hunk.path);
311
+ const validPath = await validatePath(p.abs, allowedDirectories, {
312
+ requireExistence: hunk.type !== "add",
313
+ abortSignal,
314
+ });
315
+ if (hunk.type === "add") {
316
+ return {
317
+ change: { type: "add", path: validPath, content: hunk.contents },
318
+ };
319
+ }
320
+ if (hunk.type === "delete") {
321
+ validateFileNotReadOnly(validPath, projectConfig, primaryDir);
322
+ return { change: { type: "delete", path: validPath } };
323
+ }
324
+ // update
325
+ validateFileNotReadOnly(validPath, projectConfig, primaryDir);
326
+ let moveAbs;
327
+ if (hunk.movePath) {
328
+ const moveP = resolvePathInRoot(root, hunk.movePath);
329
+ moveAbs = await validatePath(moveP.abs, allowedDirectories, {
330
+ requireExistence: false,
331
+ abortSignal,
332
+ });
333
+ }
334
+ const upd = deriveNewContentsFromChunks(validPath, hunk.chunks);
335
+ const change = {
336
+ type: "update",
337
+ path: validPath,
338
+ movePath: moveAbs,
339
+ newContent: upd.content,
340
+ unifiedDiff: upd.unifiedDiff,
341
+ };
342
+ if (upd.unifiedDiff) {
343
+ return {
344
+ change,
345
+ diffLine: `*** Update File: ${path.relative(root, moveAbs ?? validPath)}\n${upd.unifiedDiff}\n`,
346
+ };
347
+ }
348
+ return { change };
349
+ }
278
350
  export const createApplyPatchTool = async (options) => {
279
351
  const { primaryDir, allowedDirs } = options.workspace;
280
352
  const allowedDirectories = allowedDirs ?? [primaryDir];
@@ -316,56 +388,15 @@ export const createApplyPatchTool = async (options) => {
316
388
  if (hunks.length === 0) {
317
389
  return "No changes found in patch.";
318
390
  }
319
- // Build a list of resolved file changes (absolute paths), and a diff preview.
320
391
  const changes = [];
321
392
  let diffOutput = "";
322
393
  for (const hunk of hunks) {
323
- if (abortSignal?.aborted)
324
- throw new Error("Cancelled");
325
- const p = resolvePathInRoot(root, hunk.path);
326
- // Validate path is within allowed directories
327
- const validPath = await validatePath(p.abs, allowedDirectories, {
328
- requireExistence: hunk.type !== "add",
329
- abortSignal,
330
- });
331
- if (hunk.type === "add") {
332
- changes.push({
333
- type: "add",
334
- path: validPath,
335
- content: hunk.contents,
336
- });
337
- continue;
338
- }
339
- if (hunk.type === "delete") {
340
- // Validate file is not read-only before deletion
341
- validateFileNotReadOnly(validPath, projectConfig, primaryDir);
342
- changes.push({ type: "delete", path: validPath });
343
- continue;
344
- }
345
- // update - validate file is not read-only
346
- validateFileNotReadOnly(validPath, projectConfig, primaryDir);
347
- let moveAbs;
348
- if (hunk.movePath) {
349
- const moveP = resolvePathInRoot(root, hunk.movePath);
350
- moveAbs = await validatePath(moveP.abs, allowedDirectories, {
351
- requireExistence: false,
352
- abortSignal,
353
- });
354
- }
355
- const upd = deriveNewContentsFromChunks(validPath, hunk.chunks);
356
- changes.push({
357
- type: "update",
358
- path: validPath,
359
- movePath: moveAbs,
360
- newContent: upd.content,
361
- unifiedDiff: upd.unifiedDiff,
362
- });
363
- if (upd.unifiedDiff) {
364
- diffOutput += `*** Update File: ${path.relative(root, moveAbs ?? validPath)}\n`;
365
- diffOutput += `${upd.unifiedDiff}\n`;
394
+ const { change, diffLine } = await processHunk(hunk, root, allowedDirectories, projectConfig, primaryDir, abortSignal);
395
+ changes.push(change);
396
+ if (diffLine) {
397
+ diffOutput += diffLine;
366
398
  }
367
399
  }
368
- // Apply changes
369
400
  const changedAbs = await applyChanges(changes, abortSignal);
370
401
  const changedRel = changedAbs.map((p) => path.relative(root, p));
371
402
  clearProjectStatusCache();
@@ -6,8 +6,8 @@ export declare const BashTool: {
6
6
  };
7
7
  declare const inputSchema: z.ZodObject<{
8
8
  command: z.ZodString;
9
- cwd: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNullable<z.ZodString>>;
10
- timeout: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
9
+ cwd: z.ZodPreprocess<z.ZodNullable<z.ZodString>>;
10
+ timeout: z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
11
11
  background: z.ZodOptional<z.ZodBoolean>;
12
12
  }, z.core.$strip>;
13
13
  type BashInputSchema = z.infer<typeof inputSchema>;
@@ -19,8 +19,8 @@ export declare const createBashTool: (options: {
19
19
  description: string;
20
20
  inputSchema: z.ZodObject<{
21
21
  command: z.ZodString;
22
- cwd: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNullable<z.ZodString>>;
23
- timeout: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
22
+ cwd: z.ZodPreprocess<z.ZodNullable<z.ZodString>>;
23
+ timeout: z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
24
24
  background: z.ZodOptional<z.ZodBoolean>;
25
25
  }, z.core.$strip>;
26
26
  };
@@ -1 +1 @@
1
- {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../source/tools/bash.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAUpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA0CvD,eAAO,MAAM,QAAQ;;CAEpB,CAAC;AA4MF,QAAA,MAAM,WAAW;;;;;iBAkBf,CAAC;AAEH,KAAK,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEnD,eAAO,MAAM,cAAc,GAAU,SAAS;IAC5C,SAAS,EAAE,gBAAgB,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;;;;;;;;;;yBA2FwB,eAAe;mDAIK,eAAe,mBACrC,oBAAoB,GACpC,OAAO,CAAC,MAAM,CAAC;EA6BrB,CAAC"}
1
+ {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../source/tools/bash.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAepD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA0CvD,eAAO,MAAM,QAAQ;;CAEpB,CAAC;AAkNF,QAAA,MAAM,WAAW;;;;;iBAkBf,CAAC;AAEH,KAAK,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEnD,eAAO,MAAM,cAAc,GAAU,SAAS;IAC5C,SAAS,EAAE,gBAAgB,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;;;;;;;;;;yBA8GwB,eAAe;mDAIK,eAAe,mBACrC,oBAAoB,GACpC,OAAO,CAAC,MAAM,CAAC;EA6BrB,CAAC"}
@@ -1,4 +1,3 @@
1
- // import { execSync } from "node:child_process";
2
1
  import { randomBytes } from "node:crypto";
3
2
  import { mkdirSync, writeFileSync } from "node:fs";
4
3
  import { dirname } from "node:path";
@@ -6,6 +5,7 @@ import { z } from "zod";
6
5
  import { initExecutionEnvironment } from "../execution/index.js";
7
6
  import style from "../terminal/style.js";
8
7
  import { resolveCwd, validatePaths } from "../utils/bash.js";
8
+ import { formatBinaryMessage, isBinaryOutput, saveBinaryOutput, } from "../utils/binary-output.js";
9
9
  import { detectDestructiveCommand, formatBlockedCommandMessage, } from "../utils/command-protection.js";
10
10
  import { expandEnvVars } from "../utils/env-expand.js";
11
11
  import { logger } from "../utils/logger.js";
@@ -206,7 +206,7 @@ export const BashTool = {
206
206
  // }
207
207
  // Tools available:
208
208
  // ${installedTools}`;
209
- const simpleDescription = "Run terminal commands.";
209
+ const simpleDescription = "Run terminal commands. When you need to run multiple independent commands (e.g. `git status`, `git diff`, `git log`; or several `rg`/`grep` searches with different patterns), ALWAYS issue multiple Bash tool calls in the same assistant message rather than running one, waiting for the result, then running the next. The runtime executes parallel tool calls concurrently, so batching independent commands is several times faster than serial calls. Only sequence commands when one truly depends on the output of another.";
210
210
  // Command execution timeout in milliseconds
211
211
  const DEFAULT_TIMEOUT = 1.5 * 60 * 1000; // 1.5 minutes
212
212
  // Maximum output size in bytes (50KB) to prevent context window exhaustion
@@ -214,15 +214,19 @@ const MAX_OUTPUT_SIZE = 50 * 1024;
214
214
  /**
215
215
  * Truncates output if it exceeds MAX_OUTPUT_SIZE and adds a clear message.
216
216
  * This prevents extremely large outputs from exhausting the context window.
217
+ * The footer is always appended at the end, even when output is truncated.
217
218
  */
218
- function truncateOutput(output) {
219
+ function truncateOutput(output, footer) {
220
+ if (output.length === 0) {
221
+ return footer;
222
+ }
219
223
  if (output.length <= MAX_OUTPUT_SIZE) {
220
- return output;
224
+ return `${output}\n${footer}`;
221
225
  }
222
226
  const truncatedLength = MAX_OUTPUT_SIZE;
223
227
  const originalLength = output.length;
224
228
  const truncated = output.slice(0, truncatedLength);
225
- return `${truncated}\n\n[OUTPUT TRUNCATED: ${originalLength.toLocaleString()} characters total, showing first ${truncatedLength.toLocaleString()} characters. The output was too large and was truncated to prevent context window exhaustion. Consider using commands that produce smaller output (e.g., head, tail with line limits, or redirecting to a file).]`;
229
+ return `${truncated}\n\n[OUTPUT TRUNCATED: ${originalLength.toLocaleString()} characters total, showing first ${truncatedLength.toLocaleString()} characters. The output was too large and was truncated to prevent context window exhaustion. Consider using commands that produce smaller output (e.g., head, tail with line limits, or redirecting to a file).]\n${footer}`;
226
230
  }
227
231
  const inputSchema = z.object({
228
232
  command: z.string().describe("Full CLI command to execute."),
@@ -283,6 +287,7 @@ export const createBashTool = async (options) => {
283
287
  return `Background process started with PID: ${proc.pid}`;
284
288
  }
285
289
  async function executeSync(cmd, cwd, timeout, signal) {
290
+ const startTime = Date.now();
286
291
  const { output, exitCode, error } = await execEnv.executeCommand(cmd, {
287
292
  cwd,
288
293
  timeout,
@@ -291,16 +296,25 @@ export const createBashTool = async (options) => {
291
296
  captureStderr: true,
292
297
  throwOnError: false,
293
298
  });
299
+ const elapsedMs = Date.now() - startTime;
300
+ const timeStr = elapsedMs < 1000 ? `${elapsedMs}ms` : `${(elapsedMs / 1000).toFixed(1)}s`;
301
+ const metadataFooter = `[exit:${exitCode} | ${timeStr}]`;
294
302
  if (exitCode !== 0) {
295
- const errorMessage = error
296
- ? error.message
297
- : `Command exited with code ${exitCode}`;
298
- const combinedOutput = output
299
- ? `${errorMessage}\n${output}`
300
- : errorMessage;
301
- throw new Error(truncateOutput(combinedOutput));
303
+ const execError = error;
304
+ const wasKilled = execError?.killed === true || execError?.signal != null;
305
+ if (wasKilled) {
306
+ const timeoutOutput = output || `Command timed out after ${timeout.toLocaleString()}ms`;
307
+ return truncateOutput(timeoutOutput, metadataFooter);
308
+ }
309
+ return truncateOutput(output, metadataFooter);
310
+ }
311
+ // Check for binary output and handle specially
312
+ if (isBinaryOutput(output)) {
313
+ const saveResult = saveBinaryOutput(output);
314
+ const binaryMessage = formatBinaryMessage(saveResult);
315
+ return `${binaryMessage}\n${metadataFooter}`;
302
316
  }
303
- return truncateOutput(output);
317
+ return truncateOutput(output, metadataFooter);
304
318
  }
305
319
  return {
306
320
  toolDef: {
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import type { ToolExecutionOptions } from "./types.ts";
2
+ import type { SessionContext, ToolExecutionOptions } from "./types.ts";
3
3
  declare const toolMetadataSchema: z.ZodObject<{
4
4
  name: z.ZodString;
5
5
  description: z.ZodString;
@@ -17,7 +17,20 @@ declare const toolMetadataSchema: z.ZodObject<{
17
17
  needsApproval: z.ZodDefault<z.ZodBoolean>;
18
18
  }, z.core.$strip>;
19
19
  type ToolMetadata = z.infer<typeof toolMetadataSchema>;
20
- export declare function parseToolMetadata(output: string): ToolMetadata;
20
+ interface InterpreterResult {
21
+ command: string;
22
+ args: string[];
23
+ }
24
+ export declare function getShebang(scriptPath: string): string | null;
25
+ export declare function parseShebang(shebang: string, scriptPath: string): InterpreterResult;
26
+ export declare function resolveToolInterpreter(scriptPath: string): InterpreterResult | null;
27
+ export declare function parseTextSchema(content: string): ToolMetadata | null;
28
+ /**
29
+ * Processes child process stdout/stderr into a result string.
30
+ * Trims, truncates oversized output, falls back to stderr or a placeholder,
31
+ * and attempts JSON parsing for structured output.
32
+ */
33
+ export declare function processChildOutput(stdout: string, stderr: string): string;
21
34
  interface DynamicToolObject {
22
35
  toolDef: {
23
36
  description: string;
@@ -25,9 +38,10 @@ interface DynamicToolObject {
25
38
  };
26
39
  execute: (input: Record<string, unknown>, options: ToolExecutionOptions) => Promise<string>;
27
40
  }
28
- export declare function loadDynamicTools({ baseDir, existingToolNames, }: {
41
+ export declare function loadDynamicTools({ baseDir, existingToolNames, sessionContext, }: {
29
42
  baseDir: string;
30
43
  existingToolNames?: string[];
44
+ sessionContext?: SessionContext;
31
45
  }): Promise<Record<string, DynamicToolObject>>;
32
46
  export {};
33
47
  //# sourceMappingURL=dynamic-tool-loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-tool-loader.d.ts","sourceRoot":"","sources":["../../source/tools/dynamic-tool-loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGvD,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;iBAatB,CAAC;AAEH,KAAK,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEvD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAS9D;AA2LD,UAAU,iBAAiB;IACzB,OAAO,EAAE;QACP,WAAW,EAAE,MAAM,CAAC;QAEpB,WAAW,EAAE,GAAG,CAAC;KAClB,CAAC;IACF,OAAO,EAAE,CACP,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,EAAE,oBAAoB,KAC1B,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB;AAwCD,wBAAsB,gBAAgB,CAAC,EACrC,OAAO,EACP,iBAAsB,GACvB,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B,8CA2FA"}
1
+ {"version":3,"file":"dynamic-tool-loader.d.ts","sourceRoot":"","sources":["../../source/tools/dynamic-tool-loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGvE,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;iBAatB,CAAC;AAEH,KAAK,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAMvD,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAyBD,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAc5D;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,iBAAiB,CAUnB;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,GACjB,iBAAiB,GAAG,IAAI,CA0B1B;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CA4CpE;AA4LD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CA4BzE;AAoFD,UAAU,iBAAiB;IACzB,OAAO,EAAE;QACP,WAAW,EAAE,MAAM,CAAC;QAEpB,WAAW,EAAE,GAAG,CAAC;KAClB,CAAC;IACF,OAAO,EAAE,CACP,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,EAAE,oBAAoB,KAC1B,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB;AAwED,wBAAsB,gBAAgB,CAAC,EACrC,OAAO,EACP,iBAAsB,EACtB,cAAc,GACf,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC,8CAiKA"}