centaurus-cli 3.0.1 → 3.1.1

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 (552) hide show
  1. package/dist/ai/types.js +0 -1
  2. package/dist/ai/types.js.map +1 -1
  3. package/dist/cli-adapter.js +5047 -5158
  4. package/dist/cli-adapter.js.map +1 -1
  5. package/dist/commands/CommandParser.js +372 -315
  6. package/dist/commands/CommandParser.js.map +1 -1
  7. package/dist/config/build-config.js +11 -42
  8. package/dist/config/build-config.js.map +1 -1
  9. package/dist/config/defaultConfig.js +94 -82
  10. package/dist/config/defaultConfig.js.map +1 -1
  11. package/dist/config/manager.js +144 -160
  12. package/dist/config/manager.js.map +1 -1
  13. package/dist/config/mcp-config-manager.js +411 -364
  14. package/dist/config/mcp-config-manager.js.map +1 -1
  15. package/dist/config/models.js +118 -185
  16. package/dist/config/models.js.map +1 -1
  17. package/dist/config/slash-commands.js +186 -184
  18. package/dist/config/slash-commands.js.map +1 -1
  19. package/dist/config/types.js +33 -26
  20. package/dist/config/types.js.map +1 -1
  21. package/dist/context/command-detector.js +63 -67
  22. package/dist/context/command-detector.js.map +1 -1
  23. package/dist/context/context-manager.js +533 -518
  24. package/dist/context/context-manager.js.map +1 -1
  25. package/dist/context/handlers/docker-handler.js +518 -576
  26. package/dist/context/handlers/docker-handler.js.map +1 -1
  27. package/dist/context/handlers/ssh-handler.js +1050 -1109
  28. package/dist/context/handlers/ssh-handler.js.map +1 -1
  29. package/dist/context/handlers/wsl-handler.js +558 -630
  30. package/dist/context/handlers/wsl-handler.js.map +1 -1
  31. package/dist/context/index.js +42 -6
  32. package/dist/context/index.js.map +1 -1
  33. package/dist/context/subshell-handler.js +0 -4
  34. package/dist/context/subshell-handler.js.map +1 -1
  35. package/dist/context/types.js +20 -31
  36. package/dist/context/types.js.map +1 -1
  37. package/dist/hooks/useConnectivity.js +13 -10
  38. package/dist/hooks/useConnectivity.js.map +1 -1
  39. package/dist/hooks/useTerminalDimensions.js +67 -79
  40. package/dist/hooks/useTerminalDimensions.js.map +1 -1
  41. package/dist/index.js +228 -251
  42. package/dist/index.js.map +1 -1
  43. package/dist/mcp/mcp-command-handler.js +297 -260
  44. package/dist/mcp/mcp-command-handler.js.map +1 -1
  45. package/dist/mcp/mcp-server-manager.js +139 -155
  46. package/dist/mcp/mcp-server-manager.js.map +1 -1
  47. package/dist/mcp/mcp-tool-wrapper.js +74 -94
  48. package/dist/mcp/mcp-tool-wrapper.js.map +1 -1
  49. package/dist/services/ai-autocomplete-agent.js +169 -181
  50. package/dist/services/ai-autocomplete-agent.js.map +1 -1
  51. package/dist/services/ai-context-injector.js +180 -93
  52. package/dist/services/ai-context-injector.js.map +1 -1
  53. package/dist/services/ai-service-client.js +513 -456
  54. package/dist/services/ai-service-client.js.map +1 -1
  55. package/dist/services/api-client.js +443 -441
  56. package/dist/services/api-client.js.map +1 -1
  57. package/dist/services/auth-handler.js +162 -198
  58. package/dist/services/auth-handler.js.map +1 -1
  59. package/dist/services/background-task-manager.js +258 -282
  60. package/dist/services/background-task-manager.js.map +1 -1
  61. package/dist/services/checkpoint-manager.js +1526 -1512
  62. package/dist/services/checkpoint-manager.js.map +1 -1
  63. package/dist/services/clipboard-service.js +151 -200
  64. package/dist/services/clipboard-service.js.map +1 -1
  65. package/dist/services/connectivity-manager.js +63 -65
  66. package/dist/services/connectivity-manager.js.map +1 -1
  67. package/dist/services/conversation-manager.js +118 -121
  68. package/dist/services/conversation-manager.js.map +1 -1
  69. package/dist/services/environment-context-injector.js +160 -187
  70. package/dist/services/environment-context-injector.js.map +1 -1
  71. package/dist/services/fast-context-agent.js +203 -243
  72. package/dist/services/fast-context-agent.js.map +1 -1
  73. package/dist/services/input-detection-agent.js +190 -202
  74. package/dist/services/input-detection-agent.js.map +1 -1
  75. package/dist/services/input-requirement-detector.js +155 -189
  76. package/dist/services/input-requirement-detector.js.map +1 -1
  77. package/dist/services/local-chat-storage.js +342 -365
  78. package/dist/services/local-chat-storage.js.map +1 -1
  79. package/dist/services/monitored-shell-manager.js +225 -233
  80. package/dist/services/monitored-shell-manager.js.map +1 -1
  81. package/dist/services/ollama-service.js +293 -310
  82. package/dist/services/ollama-service.js.map +1 -1
  83. package/dist/services/rules-storage.js +142 -0
  84. package/dist/services/rules-storage.js.map +1 -0
  85. package/dist/services/session-quota-manager.js +219 -235
  86. package/dist/services/session-quota-manager.js.map +1 -1
  87. package/dist/services/shell-input-agent.js +299 -334
  88. package/dist/services/shell-input-agent.js.map +1 -1
  89. package/dist/services/sub-agent-manager.js +459 -501
  90. package/dist/services/sub-agent-manager.js.map +1 -1
  91. package/dist/services/warpify-detector.js +133 -183
  92. package/dist/services/warpify-detector.js.map +1 -1
  93. package/dist/services/workflow-storage.js +202 -217
  94. package/dist/services/workflow-storage.js.map +1 -1
  95. package/dist/test-ssh-handler.js +148 -193
  96. package/dist/test-ssh-handler.js.map +1 -1
  97. package/dist/tools/add-mcp.js +161 -0
  98. package/dist/tools/add-mcp.js.map +1 -0
  99. package/dist/tools/background-command.js +240 -273
  100. package/dist/tools/background-command.js.map +1 -1
  101. package/dist/tools/command.js +447 -440
  102. package/dist/tools/command.js.map +1 -1
  103. package/dist/tools/create-image.js +172 -202
  104. package/dist/tools/create-image.js.map +1 -1
  105. package/dist/tools/enter-remote-session.js +169 -215
  106. package/dist/tools/enter-remote-session.js.map +1 -1
  107. package/dist/tools/fast-context.js +60 -67
  108. package/dist/tools/fast-context.js.map +1 -1
  109. package/dist/tools/file-ops.js +601 -572
  110. package/dist/tools/file-ops.js.map +1 -1
  111. package/dist/tools/find-files.js +262 -303
  112. package/dist/tools/find-files.js.map +1 -1
  113. package/dist/tools/get-diff.js +423 -406
  114. package/dist/tools/get-diff.js.map +1 -1
  115. package/dist/tools/grep-search.js +966 -948
  116. package/dist/tools/grep-search.js.map +1 -1
  117. package/dist/tools/inspect-symbol.js +308 -323
  118. package/dist/tools/inspect-symbol.js.map +1 -1
  119. package/dist/tools/plan-mode.js +459 -503
  120. package/dist/tools/plan-mode.js.map +1 -1
  121. package/dist/tools/read-binary-file.js +160 -190
  122. package/dist/tools/read-binary-file.js.map +1 -1
  123. package/dist/tools/registry.js +100 -84
  124. package/dist/tools/registry.js.map +1 -1
  125. package/dist/tools/reproduce_issue.js +170 -151
  126. package/dist/tools/reproduce_issue.js.map +1 -1
  127. package/dist/tools/sub-agent.js +223 -228
  128. package/dist/tools/sub-agent.js.map +1 -1
  129. package/dist/tools/task-complete.js +28 -27
  130. package/dist/tools/task-complete.js.map +1 -1
  131. package/dist/tools/types.js +0 -1
  132. package/dist/tools/types.js.map +1 -1
  133. package/dist/tools/validation.js +96 -118
  134. package/dist/tools/validation.js.map +1 -1
  135. package/dist/tools/web-search.js +194 -194
  136. package/dist/tools/web-search.js.map +1 -1
  137. package/dist/tools/workflow-tool.js +77 -82
  138. package/dist/tools/workflow-tool.js.map +1 -1
  139. package/dist/types/index.js +0 -1
  140. package/dist/types/index.js.map +1 -1
  141. package/dist/types/rule.js +1 -0
  142. package/dist/types/rule.js.map +1 -0
  143. package/dist/types/workflow.js +0 -7
  144. package/dist/types/workflow.js.map +1 -1
  145. package/dist/ui/components/AgentTimer.js +24 -25
  146. package/dist/ui/components/AgentTimer.js.map +1 -1
  147. package/dist/ui/components/App.js +3266 -3263
  148. package/dist/ui/components/App.js.map +1 -1
  149. package/dist/ui/components/AuthScreen.js +22 -34
  150. package/dist/ui/components/AuthScreen.js.map +1 -1
  151. package/dist/ui/components/AuthWelcomeScreen.js +30 -24
  152. package/dist/ui/components/AuthWelcomeScreen.js.map +1 -1
  153. package/dist/ui/components/Breadcrumbs.js +53 -82
  154. package/dist/ui/components/Breadcrumbs.js.map +1 -1
  155. package/dist/ui/components/CircularSelectInput.js +59 -67
  156. package/dist/ui/components/CircularSelectInput.js.map +1 -1
  157. package/dist/ui/components/ClipboardFileAutocomplete.js +78 -39
  158. package/dist/ui/components/ClipboardFileAutocomplete.js.map +1 -1
  159. package/dist/ui/components/CodeBlock.js +24 -42
  160. package/dist/ui/components/CodeBlock.js.map +1 -1
  161. package/dist/ui/components/ConfigViewer.js +18 -25
  162. package/dist/ui/components/ConfigViewer.js.map +1 -1
  163. package/dist/ui/components/ConfirmPrompt.js +49 -71
  164. package/dist/ui/components/ConfirmPrompt.js.map +1 -1
  165. package/dist/ui/components/ConnectionStatusMessage.js +32 -83
  166. package/dist/ui/components/ConnectionStatusMessage.js.map +1 -1
  167. package/dist/ui/components/ContextWindowIndicator.js +34 -49
  168. package/dist/ui/components/ContextWindowIndicator.js.map +1 -1
  169. package/dist/ui/components/DetailedPlanReviewScreen.js +104 -106
  170. package/dist/ui/components/DetailedPlanReviewScreen.js.map +1 -1
  171. package/dist/ui/components/DiffViewer.js +68 -121
  172. package/dist/ui/components/DiffViewer.js.map +1 -1
  173. package/dist/ui/components/ErrorBoundary.js +40 -48
  174. package/dist/ui/components/ErrorBoundary.js.map +1 -1
  175. package/dist/ui/components/FileCreationPreview.js +29 -60
  176. package/dist/ui/components/FileCreationPreview.js.map +1 -1
  177. package/dist/ui/components/FileOperation.js +34 -29
  178. package/dist/ui/components/FileOperation.js.map +1 -1
  179. package/dist/ui/components/FileTagAutocomplete.js +55 -25
  180. package/dist/ui/components/FileTagAutocomplete.js.map +1 -1
  181. package/dist/ui/components/FontRecommendation.js.map +1 -1
  182. package/dist/ui/components/GitDiffBreadcrumb.js +29 -0
  183. package/dist/ui/components/GitDiffBreadcrumb.js.map +1 -0
  184. package/dist/ui/components/InputBox.js +1620 -2150
  185. package/dist/ui/components/InputBox.js.map +1 -1
  186. package/dist/ui/components/InteractiveShell.js +234 -352
  187. package/dist/ui/components/InteractiveShell.js.map +1 -1
  188. package/dist/ui/components/KeyboardHelp.js +34 -35
  189. package/dist/ui/components/KeyboardHelp.js.map +1 -1
  190. package/dist/ui/components/LoadingIndicator.js +22 -25
  191. package/dist/ui/components/LoadingIndicator.js.map +1 -1
  192. package/dist/ui/components/MCPAddScreen.js +40 -51
  193. package/dist/ui/components/MCPAddScreen.js.map +1 -1
  194. package/dist/ui/components/MCPListScreen.js +40 -48
  195. package/dist/ui/components/MCPListScreen.js.map +1 -1
  196. package/dist/ui/components/MCPServerListScreen.js +49 -56
  197. package/dist/ui/components/MCPServerListScreen.js.map +1 -1
  198. package/dist/ui/components/MarkdownRenderer.js +69 -96
  199. package/dist/ui/components/MarkdownRenderer.js.map +1 -1
  200. package/dist/ui/components/MessageBox.js +66 -48
  201. package/dist/ui/components/MessageBox.js.map +1 -1
  202. package/dist/ui/components/MessageDisplay.js +150 -142
  203. package/dist/ui/components/MessageDisplay.js.map +1 -1
  204. package/dist/ui/components/MonitorModeAIPanel.js +46 -65
  205. package/dist/ui/components/MonitorModeAIPanel.js.map +1 -1
  206. package/dist/ui/components/MultiLineInput.js +243 -277
  207. package/dist/ui/components/MultiLineInput.js.map +1 -1
  208. package/dist/ui/components/PasswordPrompt.js +37 -18
  209. package/dist/ui/components/PasswordPrompt.js.map +1 -1
  210. package/dist/ui/components/PlanAcceptedMessage.js +27 -38
  211. package/dist/ui/components/PlanAcceptedMessage.js.map +1 -1
  212. package/dist/ui/components/PlanReviewScreen.js +46 -50
  213. package/dist/ui/components/PlanReviewScreen.js.map +1 -1
  214. package/dist/ui/components/RulesEditorScreen.js +81 -0
  215. package/dist/ui/components/RulesEditorScreen.js.map +1 -0
  216. package/dist/ui/components/SelectPrompt.js +19 -8
  217. package/dist/ui/components/SelectPrompt.js.map +1 -1
  218. package/dist/ui/components/ShimmerText.js +44 -0
  219. package/dist/ui/components/ShimmerText.js.map +1 -0
  220. package/dist/ui/components/SlashCommandAutocomplete.js +49 -22
  221. package/dist/ui/components/SlashCommandAutocomplete.js.map +1 -1
  222. package/dist/ui/components/StatusBar.js +56 -87
  223. package/dist/ui/components/StatusBar.js.map +1 -1
  224. package/dist/ui/components/StreamingMessageDisplay.js +116 -99
  225. package/dist/ui/components/StreamingMessageDisplay.js.map +1 -1
  226. package/dist/ui/components/TaskCompletedMessage.js +28 -23
  227. package/dist/ui/components/TaskCompletedMessage.js.map +1 -1
  228. package/dist/ui/components/TaskProgressIndicator.js +44 -70
  229. package/dist/ui/components/TaskProgressIndicator.js.map +1 -1
  230. package/dist/ui/components/ThinkingDisplay.js +44 -41
  231. package/dist/ui/components/ThinkingDisplay.js.map +1 -1
  232. package/dist/ui/components/ToolExecutionMessage.js +772 -1326
  233. package/dist/ui/components/ToolExecutionMessage.js.map +1 -1
  234. package/dist/ui/components/ToolExecutionStatus.js +53 -84
  235. package/dist/ui/components/ToolExecutionStatus.js.map +1 -1
  236. package/dist/ui/components/ToolResult.js +22 -15
  237. package/dist/ui/components/ToolResult.js.map +1 -1
  238. package/dist/ui/components/VersionUpdatePrompt.js +88 -120
  239. package/dist/ui/components/VersionUpdatePrompt.js.map +1 -1
  240. package/dist/ui/components/WelcomeBanner.js +176 -26
  241. package/dist/ui/components/WelcomeBanner.js.map +1 -1
  242. package/dist/ui/components/WorkflowCreatorScreen.js +94 -161
  243. package/dist/ui/components/WorkflowCreatorScreen.js.map +1 -1
  244. package/dist/utils/ansi-encoder.js +30 -61
  245. package/dist/utils/ansi-encoder.js.map +1 -1
  246. package/dist/utils/chat-formatter.js +327 -305
  247. package/dist/utils/chat-formatter.js.map +1 -1
  248. package/dist/utils/command-history.js +152 -174
  249. package/dist/utils/command-history.js.map +1 -1
  250. package/dist/utils/context-sanitizer.js +49 -112
  251. package/dist/utils/context-sanitizer.js.map +1 -1
  252. package/dist/utils/conversation-logger.js +292 -324
  253. package/dist/utils/conversation-logger.js.map +1 -1
  254. package/dist/utils/custom-commands-manager.js +126 -131
  255. package/dist/utils/custom-commands-manager.js.map +1 -1
  256. package/dist/utils/editor-utils.js +732 -837
  257. package/dist/utils/editor-utils.js.map +1 -1
  258. package/dist/utils/file.js +174 -213
  259. package/dist/utils/file.js.map +1 -1
  260. package/dist/utils/git-stats.js +169 -0
  261. package/dist/utils/git-stats.js.map +1 -0
  262. package/dist/utils/input-classifier.js +960 -482
  263. package/dist/utils/input-classifier.js.map +1 -1
  264. package/dist/utils/logger.js +48 -73
  265. package/dist/utils/logger.js.map +1 -1
  266. package/dist/utils/markdown-parser.js +277 -310
  267. package/dist/utils/markdown-parser.js.map +1 -1
  268. package/dist/utils/rule-reference-resolver.js +54 -0
  269. package/dist/utils/rule-reference-resolver.js.map +1 -0
  270. package/dist/utils/shell.js +144 -156
  271. package/dist/utils/shell.js.map +1 -1
  272. package/dist/utils/state.js +23 -22
  273. package/dist/utils/state.js.map +1 -1
  274. package/dist/utils/syntax-checker.js +279 -327
  275. package/dist/utils/syntax-checker.js.map +1 -1
  276. package/dist/utils/terminal-output.js +199 -302
  277. package/dist/utils/terminal-output.js.map +1 -1
  278. package/dist/utils/text-clipboard.js +47 -70
  279. package/dist/utils/text-clipboard.js.map +1 -1
  280. package/dist/utils/unicode-sanitizer.js +134 -197
  281. package/dist/utils/unicode-sanitizer.js.map +1 -1
  282. package/dist/utils/version-checker.js +46 -56
  283. package/dist/utils/version-checker.js.map +1 -1
  284. package/package.json +6 -4
  285. package/dist/ai/types.d.ts +0 -20
  286. package/dist/ai/types.d.ts.map +0 -1
  287. package/dist/cli-adapter.d.ts +0 -514
  288. package/dist/cli-adapter.d.ts.map +0 -1
  289. package/dist/commands/CommandParser.d.ts +0 -27
  290. package/dist/commands/CommandParser.d.ts.map +0 -1
  291. package/dist/config/build-config.d.ts +0 -42
  292. package/dist/config/build-config.d.ts.map +0 -1
  293. package/dist/config/defaultConfig.d.ts +0 -79
  294. package/dist/config/defaultConfig.d.ts.map +0 -1
  295. package/dist/config/manager.d.ts +0 -62
  296. package/dist/config/manager.d.ts.map +0 -1
  297. package/dist/config/mcp-config-manager.d.ts +0 -79
  298. package/dist/config/mcp-config-manager.d.ts.map +0 -1
  299. package/dist/config/models.d.ts +0 -83
  300. package/dist/config/models.d.ts.map +0 -1
  301. package/dist/config/slash-commands.d.ts +0 -23
  302. package/dist/config/slash-commands.d.ts.map +0 -1
  303. package/dist/config/types.d.ts +0 -35
  304. package/dist/config/types.d.ts.map +0 -1
  305. package/dist/context/command-detector.d.ts +0 -50
  306. package/dist/context/command-detector.d.ts.map +0 -1
  307. package/dist/context/context-manager.d.ts +0 -157
  308. package/dist/context/context-manager.d.ts.map +0 -1
  309. package/dist/context/handlers/docker-handler.d.ts +0 -130
  310. package/dist/context/handlers/docker-handler.d.ts.map +0 -1
  311. package/dist/context/handlers/ssh-handler.d.ts +0 -201
  312. package/dist/context/handlers/ssh-handler.d.ts.map +0 -1
  313. package/dist/context/handlers/wsl-handler.d.ts +0 -146
  314. package/dist/context/handlers/wsl-handler.d.ts.map +0 -1
  315. package/dist/context/index.d.ts +0 -8
  316. package/dist/context/index.d.ts.map +0 -1
  317. package/dist/context/subshell-handler.d.ts +0 -165
  318. package/dist/context/subshell-handler.d.ts.map +0 -1
  319. package/dist/context/types.d.ts +0 -70
  320. package/dist/context/types.d.ts.map +0 -1
  321. package/dist/hooks/useConnectivity.d.ts +0 -2
  322. package/dist/hooks/useConnectivity.d.ts.map +0 -1
  323. package/dist/hooks/useTerminalDimensions.d.ts +0 -41
  324. package/dist/hooks/useTerminalDimensions.d.ts.map +0 -1
  325. package/dist/index.d.ts +0 -9
  326. package/dist/index.d.ts.map +0 -1
  327. package/dist/mcp/mcp-command-handler.d.ts +0 -47
  328. package/dist/mcp/mcp-command-handler.d.ts.map +0 -1
  329. package/dist/mcp/mcp-server-manager.d.ts +0 -30
  330. package/dist/mcp/mcp-server-manager.d.ts.map +0 -1
  331. package/dist/mcp/mcp-tool-wrapper.d.ts +0 -12
  332. package/dist/mcp/mcp-tool-wrapper.d.ts.map +0 -1
  333. package/dist/services/ai-autocomplete-agent.d.ts +0 -39
  334. package/dist/services/ai-autocomplete-agent.d.ts.map +0 -1
  335. package/dist/services/ai-context-injector.d.ts +0 -41
  336. package/dist/services/ai-context-injector.d.ts.map +0 -1
  337. package/dist/services/ai-service-client.d.ts +0 -128
  338. package/dist/services/ai-service-client.d.ts.map +0 -1
  339. package/dist/services/api-client.d.ts +0 -353
  340. package/dist/services/api-client.d.ts.map +0 -1
  341. package/dist/services/auth-handler.d.ts +0 -30
  342. package/dist/services/auth-handler.d.ts.map +0 -1
  343. package/dist/services/background-task-manager.d.ts +0 -114
  344. package/dist/services/background-task-manager.d.ts.map +0 -1
  345. package/dist/services/checkpoint-manager.d.ts +0 -204
  346. package/dist/services/checkpoint-manager.d.ts.map +0 -1
  347. package/dist/services/clipboard-service.d.ts +0 -37
  348. package/dist/services/clipboard-service.d.ts.map +0 -1
  349. package/dist/services/connectivity-manager.d.ts +0 -18
  350. package/dist/services/connectivity-manager.d.ts.map +0 -1
  351. package/dist/services/conversation-manager.d.ts +0 -73
  352. package/dist/services/conversation-manager.d.ts.map +0 -1
  353. package/dist/services/environment-context-injector.d.ts +0 -69
  354. package/dist/services/environment-context-injector.d.ts.map +0 -1
  355. package/dist/services/fast-context-agent.d.ts +0 -12
  356. package/dist/services/fast-context-agent.d.ts.map +0 -1
  357. package/dist/services/input-detection-agent.d.ts +0 -40
  358. package/dist/services/input-detection-agent.d.ts.map +0 -1
  359. package/dist/services/input-requirement-detector.d.ts +0 -28
  360. package/dist/services/input-requirement-detector.d.ts.map +0 -1
  361. package/dist/services/local-chat-storage.d.ts +0 -182
  362. package/dist/services/local-chat-storage.d.ts.map +0 -1
  363. package/dist/services/monitored-shell-manager.d.ts +0 -120
  364. package/dist/services/monitored-shell-manager.d.ts.map +0 -1
  365. package/dist/services/ollama-service.d.ts +0 -197
  366. package/dist/services/ollama-service.d.ts.map +0 -1
  367. package/dist/services/session-quota-manager.d.ts +0 -101
  368. package/dist/services/session-quota-manager.d.ts.map +0 -1
  369. package/dist/services/shell-input-agent.d.ts +0 -89
  370. package/dist/services/shell-input-agent.d.ts.map +0 -1
  371. package/dist/services/sub-agent-manager.d.ts +0 -140
  372. package/dist/services/sub-agent-manager.d.ts.map +0 -1
  373. package/dist/services/warpify-detector.d.ts +0 -43
  374. package/dist/services/warpify-detector.d.ts.map +0 -1
  375. package/dist/services/workflow-storage.d.ts +0 -72
  376. package/dist/services/workflow-storage.d.ts.map +0 -1
  377. package/dist/test-ssh-handler.d.ts +0 -8
  378. package/dist/test-ssh-handler.d.ts.map +0 -1
  379. package/dist/tools/background-command.d.ts +0 -11
  380. package/dist/tools/background-command.d.ts.map +0 -1
  381. package/dist/tools/command.d.ts +0 -3
  382. package/dist/tools/command.d.ts.map +0 -1
  383. package/dist/tools/create-image.d.ts +0 -10
  384. package/dist/tools/create-image.d.ts.map +0 -1
  385. package/dist/tools/enter-remote-session.d.ts +0 -48
  386. package/dist/tools/enter-remote-session.d.ts.map +0 -1
  387. package/dist/tools/fast-context.d.ts +0 -3
  388. package/dist/tools/fast-context.d.ts.map +0 -1
  389. package/dist/tools/file-ops.d.ts +0 -7
  390. package/dist/tools/file-ops.d.ts.map +0 -1
  391. package/dist/tools/find-files.d.ts +0 -49
  392. package/dist/tools/find-files.d.ts.map +0 -1
  393. package/dist/tools/get-diff.d.ts +0 -14
  394. package/dist/tools/get-diff.d.ts.map +0 -1
  395. package/dist/tools/grep-search.d.ts +0 -155
  396. package/dist/tools/grep-search.d.ts.map +0 -1
  397. package/dist/tools/inspect-symbol.d.ts +0 -32
  398. package/dist/tools/inspect-symbol.d.ts.map +0 -1
  399. package/dist/tools/plan-mode.d.ts +0 -140
  400. package/dist/tools/plan-mode.d.ts.map +0 -1
  401. package/dist/tools/read-binary-file.d.ts +0 -10
  402. package/dist/tools/read-binary-file.d.ts.map +0 -1
  403. package/dist/tools/registry.d.ts +0 -31
  404. package/dist/tools/registry.d.ts.map +0 -1
  405. package/dist/tools/reproduce_issue.d.ts +0 -2
  406. package/dist/tools/reproduce_issue.d.ts.map +0 -1
  407. package/dist/tools/sub-agent.d.ts +0 -9
  408. package/dist/tools/sub-agent.d.ts.map +0 -1
  409. package/dist/tools/task-complete.d.ts +0 -3
  410. package/dist/tools/task-complete.d.ts.map +0 -1
  411. package/dist/tools/types.d.ts +0 -40
  412. package/dist/tools/types.d.ts.map +0 -1
  413. package/dist/tools/validation.d.ts +0 -47
  414. package/dist/tools/validation.d.ts.map +0 -1
  415. package/dist/tools/web-search.d.ts +0 -24
  416. package/dist/tools/web-search.d.ts.map +0 -1
  417. package/dist/tools/workflow-tool.d.ts +0 -11
  418. package/dist/tools/workflow-tool.d.ts.map +0 -1
  419. package/dist/types/index.d.ts +0 -123
  420. package/dist/types/index.d.ts.map +0 -1
  421. package/dist/types/workflow.d.ts +0 -110
  422. package/dist/types/workflow.d.ts.map +0 -1
  423. package/dist/ui/components/AgentTimer.d.ts +0 -7
  424. package/dist/ui/components/AgentTimer.d.ts.map +0 -1
  425. package/dist/ui/components/App.d.ts +0 -197
  426. package/dist/ui/components/App.d.ts.map +0 -1
  427. package/dist/ui/components/AuthScreen.d.ts +0 -8
  428. package/dist/ui/components/AuthScreen.d.ts.map +0 -1
  429. package/dist/ui/components/AuthWelcomeScreen.d.ts +0 -8
  430. package/dist/ui/components/AuthWelcomeScreen.d.ts.map +0 -1
  431. package/dist/ui/components/Breadcrumbs.d.ts +0 -13
  432. package/dist/ui/components/Breadcrumbs.d.ts.map +0 -1
  433. package/dist/ui/components/CircularSelectInput.d.ts +0 -24
  434. package/dist/ui/components/CircularSelectInput.d.ts.map +0 -1
  435. package/dist/ui/components/ClipboardFileAutocomplete.d.ts +0 -10
  436. package/dist/ui/components/ClipboardFileAutocomplete.d.ts.map +0 -1
  437. package/dist/ui/components/CodeBlock.d.ts +0 -9
  438. package/dist/ui/components/CodeBlock.d.ts.map +0 -1
  439. package/dist/ui/components/ConfigViewer.d.ts +0 -11
  440. package/dist/ui/components/ConfigViewer.d.ts.map +0 -1
  441. package/dist/ui/components/ConfirmPrompt.d.ts +0 -13
  442. package/dist/ui/components/ConfirmPrompt.d.ts.map +0 -1
  443. package/dist/ui/components/ConnectionStatusMessage.d.ts +0 -17
  444. package/dist/ui/components/ConnectionStatusMessage.d.ts.map +0 -1
  445. package/dist/ui/components/ContextWindowIndicator.d.ts +0 -8
  446. package/dist/ui/components/ContextWindowIndicator.d.ts.map +0 -1
  447. package/dist/ui/components/DetailedPlanReviewScreen.d.ts +0 -17
  448. package/dist/ui/components/DetailedPlanReviewScreen.d.ts.map +0 -1
  449. package/dist/ui/components/DiffViewer.d.ts +0 -9
  450. package/dist/ui/components/DiffViewer.d.ts.map +0 -1
  451. package/dist/ui/components/ErrorBoundary.d.ts +0 -17
  452. package/dist/ui/components/ErrorBoundary.d.ts.map +0 -1
  453. package/dist/ui/components/FileCreationPreview.d.ts +0 -8
  454. package/dist/ui/components/FileCreationPreview.d.ts.map +0 -1
  455. package/dist/ui/components/FileOperation.d.ts +0 -10
  456. package/dist/ui/components/FileOperation.d.ts.map +0 -1
  457. package/dist/ui/components/FileTagAutocomplete.d.ts +0 -11
  458. package/dist/ui/components/FileTagAutocomplete.d.ts.map +0 -1
  459. package/dist/ui/components/FontRecommendation.d.ts +0 -1
  460. package/dist/ui/components/FontRecommendation.d.ts.map +0 -1
  461. package/dist/ui/components/InputBox.d.ts +0 -42
  462. package/dist/ui/components/InputBox.d.ts.map +0 -1
  463. package/dist/ui/components/InteractiveShell.d.ts +0 -30
  464. package/dist/ui/components/InteractiveShell.d.ts.map +0 -1
  465. package/dist/ui/components/KeyboardHelp.d.ts +0 -7
  466. package/dist/ui/components/KeyboardHelp.d.ts.map +0 -1
  467. package/dist/ui/components/LoadingIndicator.d.ts +0 -3
  468. package/dist/ui/components/LoadingIndicator.d.ts.map +0 -1
  469. package/dist/ui/components/MCPAddScreen.d.ts +0 -13
  470. package/dist/ui/components/MCPAddScreen.d.ts.map +0 -1
  471. package/dist/ui/components/MCPListScreen.d.ts +0 -17
  472. package/dist/ui/components/MCPListScreen.d.ts.map +0 -1
  473. package/dist/ui/components/MCPServerListScreen.d.ts +0 -16
  474. package/dist/ui/components/MCPServerListScreen.d.ts.map +0 -1
  475. package/dist/ui/components/MarkdownRenderer.d.ts +0 -8
  476. package/dist/ui/components/MarkdownRenderer.d.ts.map +0 -1
  477. package/dist/ui/components/MessageBox.d.ts +0 -10
  478. package/dist/ui/components/MessageBox.d.ts.map +0 -1
  479. package/dist/ui/components/MessageDisplay.d.ts +0 -14
  480. package/dist/ui/components/MessageDisplay.d.ts.map +0 -1
  481. package/dist/ui/components/MonitorModeAIPanel.d.ts +0 -23
  482. package/dist/ui/components/MonitorModeAIPanel.d.ts.map +0 -1
  483. package/dist/ui/components/MultiLineInput.d.ts +0 -13
  484. package/dist/ui/components/MultiLineInput.d.ts.map +0 -1
  485. package/dist/ui/components/PasswordPrompt.d.ts +0 -9
  486. package/dist/ui/components/PasswordPrompt.d.ts.map +0 -1
  487. package/dist/ui/components/PlanAcceptedMessage.d.ts +0 -20
  488. package/dist/ui/components/PlanAcceptedMessage.d.ts.map +0 -1
  489. package/dist/ui/components/PlanReviewScreen.d.ts +0 -14
  490. package/dist/ui/components/PlanReviewScreen.d.ts.map +0 -1
  491. package/dist/ui/components/SelectPrompt.d.ts +0 -12
  492. package/dist/ui/components/SelectPrompt.d.ts.map +0 -1
  493. package/dist/ui/components/SlashCommandAutocomplete.d.ts +0 -13
  494. package/dist/ui/components/SlashCommandAutocomplete.d.ts.map +0 -1
  495. package/dist/ui/components/StatusBar.d.ts +0 -14
  496. package/dist/ui/components/StatusBar.d.ts.map +0 -1
  497. package/dist/ui/components/StreamingMessageDisplay.d.ts +0 -15
  498. package/dist/ui/components/StreamingMessageDisplay.d.ts.map +0 -1
  499. package/dist/ui/components/TaskCompletedMessage.d.ts +0 -14
  500. package/dist/ui/components/TaskCompletedMessage.d.ts.map +0 -1
  501. package/dist/ui/components/TaskProgressIndicator.d.ts +0 -18
  502. package/dist/ui/components/TaskProgressIndicator.d.ts.map +0 -1
  503. package/dist/ui/components/ThinkingDisplay.d.ts +0 -15
  504. package/dist/ui/components/ThinkingDisplay.d.ts.map +0 -1
  505. package/dist/ui/components/ToolExecutionMessage.d.ts +0 -8
  506. package/dist/ui/components/ToolExecutionMessage.d.ts.map +0 -1
  507. package/dist/ui/components/ToolExecutionStatus.d.ts +0 -10
  508. package/dist/ui/components/ToolExecutionStatus.d.ts.map +0 -1
  509. package/dist/ui/components/ToolResult.d.ts +0 -10
  510. package/dist/ui/components/ToolResult.d.ts.map +0 -1
  511. package/dist/ui/components/VersionUpdatePrompt.d.ts +0 -9
  512. package/dist/ui/components/VersionUpdatePrompt.d.ts.map +0 -1
  513. package/dist/ui/components/WelcomeBanner.d.ts +0 -3
  514. package/dist/ui/components/WelcomeBanner.d.ts.map +0 -1
  515. package/dist/ui/components/WorkflowCreatorScreen.d.ts +0 -25
  516. package/dist/ui/components/WorkflowCreatorScreen.d.ts.map +0 -1
  517. package/dist/utils/ansi-encoder.d.ts +0 -7
  518. package/dist/utils/ansi-encoder.d.ts.map +0 -1
  519. package/dist/utils/chat-formatter.d.ts +0 -12
  520. package/dist/utils/chat-formatter.d.ts.map +0 -1
  521. package/dist/utils/command-history.d.ts +0 -24
  522. package/dist/utils/command-history.d.ts.map +0 -1
  523. package/dist/utils/context-sanitizer.d.ts +0 -50
  524. package/dist/utils/context-sanitizer.d.ts.map +0 -1
  525. package/dist/utils/conversation-logger.d.ts +0 -142
  526. package/dist/utils/conversation-logger.d.ts.map +0 -1
  527. package/dist/utils/custom-commands-manager.d.ts +0 -59
  528. package/dist/utils/custom-commands-manager.d.ts.map +0 -1
  529. package/dist/utils/editor-utils.d.ts +0 -101
  530. package/dist/utils/editor-utils.d.ts.map +0 -1
  531. package/dist/utils/file.d.ts +0 -61
  532. package/dist/utils/file.d.ts.map +0 -1
  533. package/dist/utils/input-classifier.d.ts +0 -25
  534. package/dist/utils/input-classifier.d.ts.map +0 -1
  535. package/dist/utils/logger.d.ts +0 -17
  536. package/dist/utils/logger.d.ts.map +0 -1
  537. package/dist/utils/markdown-parser.d.ts +0 -60
  538. package/dist/utils/markdown-parser.d.ts.map +0 -1
  539. package/dist/utils/shell.d.ts +0 -47
  540. package/dist/utils/shell.d.ts.map +0 -1
  541. package/dist/utils/state.d.ts +0 -13
  542. package/dist/utils/state.d.ts.map +0 -1
  543. package/dist/utils/syntax-checker.d.ts +0 -24
  544. package/dist/utils/syntax-checker.d.ts.map +0 -1
  545. package/dist/utils/terminal-output.d.ts +0 -25
  546. package/dist/utils/terminal-output.d.ts.map +0 -1
  547. package/dist/utils/text-clipboard.d.ts +0 -12
  548. package/dist/utils/text-clipboard.d.ts.map +0 -1
  549. package/dist/utils/unicode-sanitizer.d.ts +0 -44
  550. package/dist/utils/unicode-sanitizer.d.ts.map +0 -1
  551. package/dist/utils/version-checker.d.ts +0 -14
  552. package/dist/utils/version-checker.d.ts.map +0 -1
@@ -1,602 +1,631 @@
1
- import * as path from 'path';
2
- import * as fs from 'fs';
3
- import * as fileUtils from '../utils/file.js';
4
- import * as Diff from 'diff';
5
- import { ToolValidator } from './validation.js';
6
- import { checkSyntax, formatSyntaxCheckResult } from '../utils/syntax-checker.js';
7
- import { logWarning } from '../utils/logger.js';
8
- /**
9
- * Helper: back up a file before the AI modifies it (for checkpoint revert).
10
- * Non-critical — if backup fails, the file operation proceeds anyway.
11
- */
1
+ import * as path from "path";
2
+ import * as fs from "fs";
3
+ import * as fileUtils from "../utils/file.js";
4
+ import * as Diff from "diff";
5
+ import { ToolValidator } from "./validation.js";
6
+ import { checkSyntax, formatSyntaxCheckResult } from "../utils/syntax-checker.js";
7
+ import { logWarning } from "../utils/logger.js";
12
8
  async function backupBeforeChange(context, absoluteFilePath) {
13
- if (!context.checkpointManager || !context.currentCheckpointId)
14
- return;
15
- try {
16
- // Determine remote handler if in remote context
17
- let remoteHandler;
18
- if (context.contextManager) {
19
- const currentCtx = context.contextManager.getCurrentContext();
20
- if (currentCtx.type !== 'local' && currentCtx.handler) {
21
- const h = currentCtx.handler;
22
- if (typeof h.readFile === 'function' && typeof h.writeFile === 'function' &&
23
- typeof h.executeCommand === 'function' && typeof h.isConnected === 'function') {
24
- remoteHandler = h;
25
- }
26
- }
9
+ if (!context.checkpointManager || !context.currentCheckpointId) return;
10
+ try {
11
+ let remoteHandler;
12
+ if (context.contextManager) {
13
+ const currentCtx = context.contextManager.getCurrentContext();
14
+ if (currentCtx.type !== "local" && currentCtx.handler) {
15
+ const h = currentCtx.handler;
16
+ if (typeof h.readFile === "function" && typeof h.writeFile === "function" && typeof h.executeCommand === "function" && typeof h.isConnected === "function") {
17
+ remoteHandler = h;
27
18
  }
28
- await context.checkpointManager.backupFileBeforeChange(context.currentCheckpointId, absoluteFilePath, context.cwd, remoteHandler);
29
- }
30
- catch (err) {
31
- logWarning(`Checkpoint backup before change failed (non-critical): ${err.message}`);
19
+ }
32
20
  }
21
+ await context.checkpointManager.backupFileBeforeChange(
22
+ context.currentCheckpointId,
23
+ absoluteFilePath,
24
+ context.cwd,
25
+ remoteHandler
26
+ );
27
+ } catch (err) {
28
+ logWarning(`Checkpoint backup before change failed (non-critical): ${err.message}`);
29
+ }
33
30
  }
34
- export const viewFileTool = {
35
- schema: {
36
- name: 'view_file',
37
- description: `View the contents of a file from the local filesystem. This tool supports some binary files such as images and videos.
38
- Text file usage:
39
- - The lines of the file are 1-indexed
40
- - If you do not provide StartLine/EndLine, the tool will read the ENTIRE file.
41
- - WARNING: If the file is >500 lines, output will be TRUNCATED to the first 500 lines.
42
- - You will be told the total line count and must use targeted reads (StartLine/EndLine) for the rest.
43
- - PREFER TARGETED READS: Use 'grep_search' to find line numbers, then read specific ranges.
44
- - You can view at most 500 lines at a time to prevent context explosion.
45
- Binary file usage:
46
- - Do not provide StartLine or EndLine arguments, this tool always returns the entire file
31
+ const viewFileTool = {
32
+ schema: {
33
+ name: "view_file",
34
+ description: `View the contents of a file from the local filesystem. This tool supports some binary files such as images and videos.
35
+ Text file usage:
36
+ - The lines of the file are 1-indexed
37
+ - If you do not provide StartLine/EndLine, the tool will read the ENTIRE file.
38
+ - WARNING: If the file is >500 lines, output will be TRUNCATED to the first 500 lines.
39
+ - You will be told the total line count and must use targeted reads (StartLine/EndLine) for the rest.
40
+ - PREFER TARGETED READS: Use 'grep_search' to find line numbers, then read specific ranges.
41
+ - You can view at most 500 lines at a time to prevent context explosion.
42
+ Binary file usage:
43
+ - Do not provide StartLine or EndLine arguments, this tool always returns the entire file
47
44
  - The output includes line numbers (e.g., "1: code") for reference. DO NOT include these line numbers in your search_pattern when editing.`,
48
- parameters: {
49
- type: 'object',
50
- properties: {
51
- reason_text: {
52
- type: 'string',
53
- description: 'REQUIRED: A brief explanation of why you are reading this file and what you are looking for. This will be shown to the user. Example: "Reading package.json to check the current version number"',
54
- },
55
- AbsolutePath: {
56
- type: 'string',
57
- description: 'Path to file to view. Must be an absolute path.',
58
- },
59
- StartLine: {
60
- type: 'integer',
61
- description: 'Optional. Startline to view, 1-indexed as usual, inclusive. This value must be less than or equal to EndLine.',
62
- },
63
- EndLine: {
64
- type: 'integer',
65
- description: 'Optional. Endline to view, 1-indexed as usual, inclusive. This value must be greater than or equal to StartLine.',
66
- },
67
- },
68
- required: ['reason_text', 'AbsolutePath'],
45
+ parameters: {
46
+ type: "object",
47
+ properties: {
48
+ reason_text: {
49
+ type: "string",
50
+ description: 'REQUIRED: A brief explanation of why you are reading this file and what you are looking for. This will be shown to the user. Example: "Reading package.json to check the current version number"'
69
51
  },
70
- },
71
- async execute(args, context) {
72
- const { AbsolutePath, StartLine, EndLine } = args;
73
- const file_path = AbsolutePath; // Map to internal variable
74
- const contextManager = context.contextManager;
75
- const currentContext = contextManager.getCurrentContext();
76
- // Use Context Manager for file operations
77
- let content;
78
- let fullPath;
79
- if (currentContext.type === 'local') {
80
- // Since AbsolutePath is required to be absolute, we might need to handle relative paths gracefully or enforce absolute
81
- // The tool description says "Must be an absolute path", but for usability we can resolve it
82
- fullPath = path.isAbsolute(file_path) ? file_path : path.resolve(context.cwd, file_path);
83
- if (!fs.existsSync(fullPath)) {
84
- throw new Error(`File not found: ${file_path}\n\nAction: Verify the file path using 'list_directory'.`);
85
- }
86
- // If user specifically requested lines, respect that lookup
87
- // Otherwise read whole file first to check length
88
- if (StartLine !== undefined || EndLine !== undefined) {
89
- content = fileUtils.readFile(fullPath, StartLine, EndLine);
90
- }
91
- else {
92
- // Read full file to check length
93
- content = fs.readFileSync(fullPath, 'utf-8');
94
- }
95
- }
96
- else {
97
- // Read from subshell
98
- content = await contextManager.readFile(file_path);
99
- // Apply line range if logic requires it (for explicit range requests)
100
- if (StartLine !== undefined || EndLine !== undefined) {
101
- const lines = content.split('\n');
102
- const start = StartLine ? StartLine - 1 : 0;
103
- const end = EndLine ? EndLine : lines.length;
104
- content = lines.slice(start, end).join('\n');
105
- }
106
- }
107
- // Process content (add line numbers, handle truncation)
108
- const lines = content.split('\n');
109
- let displayedLines = lines;
110
- let truncationMsg = '';
111
- const startNum = StartLine || 1;
112
- // TRUNCATION LOGIC:
113
- // Only apply if NO range was specified (viewing "whole" file) AND file is too long
114
- if (StartLine === undefined && EndLine === undefined && lines.length > 500) {
115
- displayedLines = lines.slice(0, 500);
116
- truncationMsg = `\n\n... [File truncated. Total lines: ${lines.length}. Showing first 500 lines only.]\n[Action: Use StartLine/EndLine parameters to view specific sections of the rest of the file.]`;
52
+ AbsolutePath: {
53
+ type: "string",
54
+ description: "Path to file to view. Must be an absolute path."
55
+ },
56
+ StartLine: {
57
+ type: "integer",
58
+ description: "Optional. Startline to view, 1-indexed as usual, inclusive. This value must be less than or equal to EndLine."
59
+ },
60
+ EndLine: {
61
+ type: "integer",
62
+ description: "Optional. Endline to view, 1-indexed as usual, inclusive. This value must be greater than or equal to StartLine."
117
63
  }
118
- const numberedContent = displayedLines.map((line, idx) => `${startNum + idx}: ${line}`).join('\n');
119
- return `File: ${file_path}\nLines: ${StartLine === undefined && EndLine === undefined ? lines.length : displayedLines.length} ${truncationMsg ? '(Truncated)' : ''}\n\n${numberedContent}${truncationMsg}`;
120
- },
64
+ },
65
+ required: ["reason_text", "AbsolutePath"]
66
+ }
67
+ },
68
+ async execute(args, context) {
69
+ const { AbsolutePath, StartLine, EndLine } = args;
70
+ const file_path = AbsolutePath;
71
+ const contextManager = context.contextManager;
72
+ const currentContext = contextManager.getCurrentContext();
73
+ let content;
74
+ let fullPath;
75
+ if (currentContext.type === "local") {
76
+ fullPath = path.isAbsolute(file_path) ? file_path : path.resolve(context.cwd, file_path);
77
+ if (!fs.existsSync(fullPath)) {
78
+ throw new Error(`File not found: ${file_path}
79
+
80
+ Action: Verify the file path using 'list_directory'.`);
81
+ }
82
+ if (StartLine !== void 0 || EndLine !== void 0) {
83
+ content = fileUtils.readFile(fullPath, StartLine, EndLine);
84
+ } else {
85
+ content = fs.readFileSync(fullPath, "utf-8");
86
+ }
87
+ } else {
88
+ content = await contextManager.readFile(file_path);
89
+ if (StartLine !== void 0 || EndLine !== void 0) {
90
+ const lines2 = content.split("\n");
91
+ const start = StartLine ? StartLine - 1 : 0;
92
+ const end = EndLine ? EndLine : lines2.length;
93
+ content = lines2.slice(start, end).join("\n");
94
+ }
95
+ }
96
+ const lines = content.split("\n");
97
+ let displayedLines = lines;
98
+ let truncationMsg = "";
99
+ const startNum = StartLine || 1;
100
+ if (StartLine === void 0 && EndLine === void 0 && lines.length > 500) {
101
+ displayedLines = lines.slice(0, 500);
102
+ truncationMsg = `
103
+
104
+ ... [File truncated. Total lines: ${lines.length}. Showing first 500 lines only.]
105
+ [Action: Use StartLine/EndLine parameters to view specific sections of the rest of the file.]`;
106
+ }
107
+ const numberedContent = displayedLines.map((line, idx) => `${startNum + idx}: ${line}`).join("\n");
108
+ return `File: ${file_path}
109
+ Lines: ${StartLine === void 0 && EndLine === void 0 ? lines.length : displayedLines.length} ${truncationMsg ? "(Truncated)" : ""}
110
+
111
+ ${numberedContent}${truncationMsg}`;
112
+ }
121
113
  };
122
- export const writeToFileTool = {
123
- schema: {
124
- name: 'write_to_file',
125
- description: `Use this tool to create new files. The file and any parent directories will be created for you if they do not already exist.
126
- Follow these instructions:
127
- 1. By default this tool will error if TargetFile already exists. To overwrite an existing file, set Overwrite to true.
128
- 2. You MUST specify TargetFile as the FIRST argument. Please specify the full TargetFile before any of the code contents.
114
+ const writeToFileTool = {
115
+ schema: {
116
+ name: "write_to_file",
117
+ description: `Use this tool to create new files. The file and any parent directories will be created for you if they do not already exist.
118
+ Follow these instructions:
119
+ 1. By default this tool will error if TargetFile already exists. To overwrite an existing file, set Overwrite to true.
120
+ 2. You MUST specify TargetFile as the FIRST argument. Please specify the full TargetFile before any of the code contents.
129
121
  IMPORTANT: You must generate the following arguments first, before any others: [TargetFile, Overwrite]`,
130
- parameters: {
131
- type: 'object',
132
- properties: {
133
- reason_text: {
134
- type: 'string',
135
- description: 'REQUIRED: A brief explanation of why you are creating/writing this file. This will be shown to the user. Example: "Creating a new configuration file for the database connection"',
136
- },
137
- TargetFile: {
138
- type: 'string',
139
- description: 'The target file to create and write code to.',
140
- },
141
- CodeContent: {
142
- type: 'string',
143
- description: 'The code contents to write to the file.',
144
- },
145
- Overwrite: {
146
- type: 'boolean',
147
- description: 'Set this to true to overwrite an existing file. WARNING: This will replace the entire file contents. Only use when you explicitly intend to overwrite. Otherwise, use a code edit tool to modify existing files.',
148
- },
149
- EmptyFile: {
150
- type: 'boolean',
151
- description: 'Set this to true to create an empty file.',
152
- },
153
- Description: {
154
- type: 'string',
155
- description: 'Brief, user-facing explanation of what this change did. Focus on non-obvious rationale, design decisions, or important context. Don\'t just restate what the code does.',
156
- },
157
- Complexity: {
158
- type: 'integer',
159
- description: 'A 1-10 rating of how important it is for the user to review this change. Rate based on: 1-3 (routine/obvious), 4-6 (worth noting), 7-10 (critical or subtle and warrants explanation).',
160
- },
161
- },
162
- required: ['reason_text', 'TargetFile', 'Overwrite', 'CodeContent', 'EmptyFile', 'Description', 'Complexity'],
122
+ parameters: {
123
+ type: "object",
124
+ properties: {
125
+ reason_text: {
126
+ type: "string",
127
+ description: 'REQUIRED: A brief explanation of why you are creating/writing this file. This will be shown to the user. Example: "Creating a new configuration file for the database connection"'
163
128
  },
164
- },
165
- async execute(args, context) {
166
- const { TargetFile, CodeContent, Overwrite, EmptyFile } = args;
167
- const file_path = TargetFile; // Map to internal variable
168
- const content = EmptyFile ? '' : CodeContent;
169
- const contextManager = context.contextManager;
170
- const currentContext = contextManager.getCurrentContext();
171
- if (currentContext.type === 'local') {
172
- const fullPath = path.resolve(context.cwd, file_path);
173
- // Ask for approval if file exists
174
- if (fs.existsSync(fullPath)) {
175
- if (!Overwrite) {
176
- throw new Error(`File ${file_path} already exists. Set Overwrite to true if you intend to replace it.`);
177
- }
178
- // Show preview of new content for overwrite
179
- const language = file_path.split('.').pop() || 'text';
180
- const result = await context.requireApproval(`File ${fullPath} already exists. Overwrite it?`, true, {
181
- type: 'code',
182
- content,
183
- language
184
- }, 'write_to_file', { file_path: fullPath, operation: 'overwrite' });
185
- if (typeof result === 'object' && 'feedback' in result) {
186
- // User provided feedback - throw special error with feedback
187
- throw new Error(`USER_FEEDBACK: ${result.feedback}`);
188
- }
189
- if (!result) {
190
- throw new Error('Operation cancelled by user.');
191
- }
192
- }
193
- else {
194
- // Ask for approval to create new file with code preview
195
- const language = file_path.split('.').pop() || 'text';
196
- const result = await context.requireApproval(`Create new file ${fullPath}?`, false, {
197
- type: 'code',
198
- content: content,
199
- language
200
- }, 'write_to_file', { file_path: fullPath, operation: 'create' });
201
- if (typeof result === 'object' && 'feedback' in result) {
202
- // User provided feedback - throw special error with feedback
203
- throw new Error(`USER_FEEDBACK: ${result.feedback}`);
204
- }
205
- if (!result) {
206
- throw new Error('Operation cancelled by user.');
207
- }
208
- }
209
- // Backup file before modification (for checkpoint revert)
210
- await backupBeforeChange(context, fullPath);
211
- fileUtils.writeFile(fullPath, content);
212
- // Run syntax check on the written file
213
- const syntaxResult = await checkSyntax(fullPath, content);
214
- const syntaxFeedback = formatSyntaxCheckResult(syntaxResult);
215
- return `Successfully wrote ${content.length} characters to ${file_path}\n${syntaxFeedback}`;
216
- }
217
- else {
218
- // Write to subshell - always ask for approval
219
- const language = file_path.split('.').pop() || 'text';
220
- const result = await context.requireApproval(`Write file ${file_path} in ${currentContext.type} environment?`, true, {
221
- type: 'code',
222
- content,
223
- language
224
- }, 'write_to_file', { file_path, operation: 'write_remote' });
225
- if (typeof result === 'object' && 'feedback' in result) {
226
- throw new Error(`USER_FEEDBACK: ${result.feedback}`);
227
- }
228
- if (!result) {
229
- throw new Error('Operation cancelled by user.');
230
- }
231
- // Backup remote file before modification (for checkpoint revert)
232
- await backupBeforeChange(context, file_path);
233
- await contextManager.writeFile(file_path, content);
234
- // Note: Syntax check skipped for remote files (would need to read back)
235
- return `Successfully wrote ${content.length} characters to ${file_path} in ${currentContext.type} environment\n(Syntax check skipped for remote files)`;
236
- }
237
- },
238
- };
239
- export const editFileTool = {
240
- schema: {
241
- name: 'edit_file',
242
- description: `Search for a specific pattern in a file and replace it with new content. Shows a diff preview before applying.
243
-
244
- IMPORTANT: You MUST provide a reason_text parameter explaining what change you are making and why. This will be shown to the user before the edit is applied.
245
-
246
- CRITICAL REQUIREMENTS:
247
- - 'search_pattern' must match the file content's meaningful tokens exactly.
248
- - Leading and trailing whitespace/indentation around the pattern will be ignored for the match.
249
- - You must still provide the full code block, but do not worry about exact indentation.
250
- - The pattern must be UNIQUE in the file (appear exactly once).
251
- - You MUST have read the file in a previous turn to know the exact content.
252
- - Include surrounding context (2-3 lines) to ensure uniqueness.
253
-
254
- COMMON MISTAKES TO AVOID:
255
- - Using patterns that appear multiple times
256
- - Not including enough context for uniqueness
257
- - Modifying the internal tokens of the code (variable names, strings, etc.)
258
- - Including the line numbers (e.g., "1: ") in the search_pattern. Copy ONLY the code.`,
259
- parameters: {
260
- type: 'object',
261
- properties: {
262
- reason_text: {
263
- type: 'string',
264
- description: 'REQUIRED: A brief explanation of what change you are making and why. This will be shown to the user. Example: "Updating the port number from 3000 to 8080 to match the production configuration"',
265
- },
266
- file_path: {
267
- type: 'string',
268
- description: 'The path to the file to edit (relative to current working directory)',
269
- },
270
- search_pattern: {
271
- type: 'string',
272
- description: `The EXACT block of text to replace. Must match character-for-character (ignoring whitespace differences).
273
- Copy this directly from a recent view_file output.`,
274
- },
275
- replacement: {
276
- type: 'string',
277
- description: 'The new text to insert in place of search_pattern. Use the same indentation style as the surrounding code.',
278
- },
279
- },
280
- required: ['reason_text', 'file_path', 'search_pattern', 'replacement'],
129
+ TargetFile: {
130
+ type: "string",
131
+ description: "The target file to create and write code to."
281
132
  },
282
- },
283
- async execute(args, context) {
284
- const { file_path, search_pattern, replacement } = args;
285
- const contextManager = context.contextManager;
286
- const currentContext = contextManager.getCurrentContext();
287
- // Validate edit operation for local files
288
- if (currentContext.type === 'local') {
289
- const validator = new ToolValidator();
290
- const validationResult = await validator.validateEditFile(file_path, search_pattern, replacement, context.cwd);
291
- if (!validationResult.valid) {
292
- const errorMessage = [
293
- validationResult.error,
294
- validationResult.suggestion ? `\nSuggestion: ${validationResult.suggestion}` : '',
295
- ].join('');
296
- throw new Error(errorMessage);
297
- }
298
- }
299
- // Read the current content
300
- let oldContent;
301
- // Compute the full path for local files
302
- const fullPath = currentContext.type === 'local' ? path.resolve(context.cwd, file_path) : file_path;
303
- if (currentContext.type === 'local') {
304
- if (!fs.existsSync(fullPath)) {
305
- throw new Error(`File not found: ${file_path}\n\nAction: Verify the file path using 'list_directory'.`);
306
- }
307
- oldContent = fs.readFileSync(fullPath, 'utf-8');
133
+ CodeContent: {
134
+ type: "string",
135
+ description: "The code contents to write to the file."
136
+ },
137
+ Overwrite: {
138
+ type: "boolean",
139
+ description: "Set this to true to overwrite an existing file. WARNING: This will replace the entire file contents. Only use when you explicitly intend to overwrite. Otherwise, use a code edit tool to modify existing files."
140
+ },
141
+ EmptyFile: {
142
+ type: "boolean",
143
+ description: "Set this to true to create an empty file."
144
+ },
145
+ Description: {
146
+ type: "string",
147
+ description: "Brief, user-facing explanation of what this change did. Focus on non-obvious rationale, design decisions, or important context. Don't just restate what the code does."
148
+ },
149
+ Complexity: {
150
+ type: "integer",
151
+ description: "A 1-10 rating of how important it is for the user to review this change. Rate based on: 1-3 (routine/obvious), 4-6 (worth noting), 7-10 (critical or subtle and warrants explanation)."
308
152
  }
309
- else {
310
- oldContent = await contextManager.readFile(file_path);
153
+ },
154
+ required: ["reason_text", "TargetFile", "Overwrite", "CodeContent", "EmptyFile", "Description", "Complexity"]
155
+ }
156
+ },
157
+ async execute(args, context) {
158
+ const { TargetFile, CodeContent, Overwrite, EmptyFile } = args;
159
+ const file_path = TargetFile;
160
+ const content = EmptyFile ? "" : CodeContent;
161
+ const contextManager = context.contextManager;
162
+ const currentContext = contextManager.getCurrentContext();
163
+ if (currentContext.type === "local") {
164
+ const fullPath = path.resolve(context.cwd, file_path);
165
+ if (fs.existsSync(fullPath)) {
166
+ if (!Overwrite) {
167
+ throw new Error(`File ${file_path} already exists. Set Overwrite to true if you intend to replace it.`);
311
168
  }
312
- // Create flexible regex for matching and replacement
313
- const { createFlexibleRegex } = await import('./validation.js');
314
- const regex = createFlexibleRegex(search_pattern);
315
- // SAFETY CHECK: Ensure we don't accidentally match 0 times or >1 times
316
- // (In case file changed between validation and execution)
317
- const matches = oldContent.match(regex);
318
- if (!matches || matches.length === 0) {
319
- throw new Error(`Pattern not found in file (even with flexible whitespace).`);
169
+ const language = file_path.split(".").pop() || "text";
170
+ const result = await context.requireApproval(
171
+ `File ${fullPath} already exists. Overwrite it?`,
172
+ true,
173
+ {
174
+ type: "code",
175
+ content,
176
+ language
177
+ },
178
+ "write_to_file",
179
+ { file_path: fullPath, operation: "overwrite" }
180
+ );
181
+ if (typeof result === "object" && "feedback" in result) {
182
+ throw new Error(`USER_FEEDBACK: ${result.feedback}`);
320
183
  }
321
- if (matches.length > 1) {
322
- throw new Error(`Pattern matches ${matches.length} times. Search pattern must be unique.`);
184
+ if (!result) {
185
+ throw new Error("Operation cancelled by user.");
323
186
  }
324
- // APPLY REPLACEMENT
325
- // We use the regex to replace.
326
- // Since we validated count === 1, the global 'g' flag is safe/necessary.
327
- const newContent = oldContent.replace(regex, replacement);
328
- // Build unified diff text for preview
329
- const patch = Diff.createTwoFilesPatch(file_path, file_path, oldContent, newContent, '', '');
330
- // Generate full diff with infinite context for "Full File" view
331
- const fullDiff = Diff.createTwoFilesPatch(file_path, file_path, oldContent, newContent, '', '', { context: Number.MAX_SAFE_INTEGER });
332
- // Ask for approval with diff preview
333
- const approved = await context.requireApproval(`Apply these changes to ${fullPath}${currentContext.type !== 'local' ? ` in ${currentContext.type} environment` : ''}?`, false, {
334
- type: 'diff',
335
- content: patch,
336
- fullDiff: fullDiff
337
- }, 'edit_file', { file_path: fullPath });
338
- if (!approved) {
339
- throw new Error('Operation cancelled by user.');
187
+ } else {
188
+ const language = file_path.split(".").pop() || "text";
189
+ const result = await context.requireApproval(
190
+ `Create new file ${fullPath}?`,
191
+ false,
192
+ {
193
+ type: "code",
194
+ content,
195
+ language
196
+ },
197
+ "write_to_file",
198
+ { file_path: fullPath, operation: "create" }
199
+ );
200
+ if (typeof result === "object" && "feedback" in result) {
201
+ throw new Error(`USER_FEEDBACK: ${result.feedback}`);
340
202
  }
341
- // Apply the changes
342
- if (currentContext.type === 'local') {
343
- // Backup file before modification (for checkpoint revert)
344
- await backupBeforeChange(context, fullPath);
345
- fs.writeFileSync(fullPath, newContent, 'utf-8');
346
- // Run syntax check on the edited file
347
- const syntaxResult = await checkSyntax(fullPath, newContent);
348
- const syntaxFeedback = formatSyntaxCheckResult(syntaxResult);
349
- return `Successfully replaced pattern in ${file_path}\n${syntaxFeedback}`;
203
+ if (!result) {
204
+ throw new Error("Operation cancelled by user.");
350
205
  }
351
- else {
352
- // Backup remote file before modification (for checkpoint revert)
353
- await backupBeforeChange(context, fullPath);
354
- await contextManager.writeFile(file_path, newContent);
355
- // Note: Syntax check skipped for remote files
356
- return `Successfully replaced pattern in ${file_path} (${currentContext.type} environment)\n(Syntax check skipped for remote files)`;
206
+ }
207
+ await backupBeforeChange(context, fullPath);
208
+ fileUtils.writeFile(fullPath, content);
209
+ const syntaxResult = await checkSyntax(fullPath, content);
210
+ const syntaxFeedback = formatSyntaxCheckResult(syntaxResult);
211
+ return `Successfully wrote ${content.length} characters to ${file_path}
212
+ ${syntaxFeedback}`;
213
+ } else {
214
+ const language = file_path.split(".").pop() || "text";
215
+ const result = await context.requireApproval(
216
+ `Write file ${file_path} in ${currentContext.type} environment?`,
217
+ true,
218
+ {
219
+ type: "code",
220
+ content,
221
+ language
222
+ },
223
+ "write_to_file",
224
+ { file_path, operation: "write_remote" }
225
+ );
226
+ if (typeof result === "object" && "feedback" in result) {
227
+ throw new Error(`USER_FEEDBACK: ${result.feedback}`);
228
+ }
229
+ if (!result) {
230
+ throw new Error("Operation cancelled by user.");
231
+ }
232
+ await backupBeforeChange(context, file_path);
233
+ await contextManager.writeFile(file_path, content);
234
+ return `Successfully wrote ${content.length} characters to ${file_path} in ${currentContext.type} environment
235
+ (Syntax check skipped for remote files)`;
236
+ }
237
+ }
238
+ };
239
+ const editFileTool = {
240
+ schema: {
241
+ name: "edit_file",
242
+ description: `Search for a specific pattern in a file and replace it with new content. Shows a diff preview before applying.
243
+
244
+ IMPORTANT: You MUST provide a reason_text parameter explaining what change you are making and why. This will be shown to the user before the edit is applied.
245
+
246
+ CRITICAL REQUIREMENTS:
247
+ - 'search_pattern' must match the file content's meaningful tokens exactly.
248
+ - Leading and trailing whitespace/indentation around the pattern will be ignored for the match.
249
+ - You must still provide the full code block, but do not worry about exact indentation.
250
+ - The pattern must be UNIQUE in the file (appear exactly once).
251
+ - You MUST have read the file in a previous turn to know the exact content.
252
+ - Include surrounding context (2-3 lines) to ensure uniqueness.
253
+
254
+ COMMON MISTAKES TO AVOID:
255
+ - Using patterns that appear multiple times
256
+ - Not including enough context for uniqueness
257
+ - Modifying the internal tokens of the code (variable names, strings, etc.)
258
+ - Including the line numbers (e.g., "1: ") in the search_pattern. Copy ONLY the code.`,
259
+ parameters: {
260
+ type: "object",
261
+ properties: {
262
+ reason_text: {
263
+ type: "string",
264
+ description: 'REQUIRED: A brief explanation of what change you are making and why. This will be shown to the user. Example: "Updating the port number from 3000 to 8080 to match the production configuration"'
265
+ },
266
+ file_path: {
267
+ type: "string",
268
+ description: "The path to the file to edit (relative to current working directory)"
269
+ },
270
+ search_pattern: {
271
+ type: "string",
272
+ description: `The EXACT block of text to replace. Must match character-for-character (ignoring whitespace differences).
273
+ Copy this directly from a recent view_file output.`
274
+ },
275
+ replacement: {
276
+ type: "string",
277
+ description: "The new text to insert in place of search_pattern. Use the same indentation style as the surrounding code."
357
278
  }
358
- },
279
+ },
280
+ required: ["reason_text", "file_path", "search_pattern", "replacement"]
281
+ }
282
+ },
283
+ async execute(args, context) {
284
+ const { file_path, search_pattern, replacement } = args;
285
+ const contextManager = context.contextManager;
286
+ const currentContext = contextManager.getCurrentContext();
287
+ if (currentContext.type === "local") {
288
+ const validator = new ToolValidator();
289
+ const validationResult = await validator.validateEditFile(
290
+ file_path,
291
+ search_pattern,
292
+ replacement,
293
+ context.cwd
294
+ );
295
+ if (!validationResult.valid) {
296
+ const errorMessage = [
297
+ validationResult.error,
298
+ validationResult.suggestion ? `
299
+ Suggestion: ${validationResult.suggestion}` : ""
300
+ ].join("");
301
+ throw new Error(errorMessage);
302
+ }
303
+ }
304
+ let oldContent;
305
+ const fullPath = currentContext.type === "local" ? path.resolve(context.cwd, file_path) : file_path;
306
+ if (currentContext.type === "local") {
307
+ if (!fs.existsSync(fullPath)) {
308
+ throw new Error(`File not found: ${file_path}
309
+
310
+ Action: Verify the file path using 'list_directory'.`);
311
+ }
312
+ oldContent = fs.readFileSync(fullPath, "utf-8");
313
+ } else {
314
+ oldContent = await contextManager.readFile(file_path);
315
+ }
316
+ const { createFlexibleRegex } = await import("./validation.js");
317
+ const regex = createFlexibleRegex(search_pattern);
318
+ const matches = oldContent.match(regex);
319
+ if (!matches || matches.length === 0) {
320
+ throw new Error(`Pattern not found in file (even with flexible whitespace).`);
321
+ }
322
+ if (matches.length > 1) {
323
+ throw new Error(`Pattern matches ${matches.length} times. Search pattern must be unique.`);
324
+ }
325
+ const newContent = oldContent.replace(regex, replacement);
326
+ const patch = Diff.createTwoFilesPatch(
327
+ file_path,
328
+ file_path,
329
+ oldContent,
330
+ newContent,
331
+ "",
332
+ ""
333
+ );
334
+ const fullDiff = Diff.createTwoFilesPatch(
335
+ file_path,
336
+ file_path,
337
+ oldContent,
338
+ newContent,
339
+ "",
340
+ "",
341
+ { context: Number.MAX_SAFE_INTEGER }
342
+ );
343
+ const approved = await context.requireApproval(
344
+ `Apply these changes to ${fullPath}${currentContext.type !== "local" ? ` in ${currentContext.type} environment` : ""}?`,
345
+ false,
346
+ {
347
+ type: "diff",
348
+ content: patch,
349
+ fullDiff
350
+ },
351
+ "edit_file",
352
+ { file_path: fullPath }
353
+ );
354
+ if (!approved) {
355
+ throw new Error("Operation cancelled by user.");
356
+ }
357
+ if (currentContext.type === "local") {
358
+ await backupBeforeChange(context, fullPath);
359
+ fs.writeFileSync(fullPath, newContent, "utf-8");
360
+ const syntaxResult = await checkSyntax(fullPath, newContent);
361
+ const syntaxFeedback = formatSyntaxCheckResult(syntaxResult);
362
+ return `Successfully replaced pattern in ${file_path}
363
+ ${syntaxFeedback}`;
364
+ } else {
365
+ await backupBeforeChange(context, fullPath);
366
+ await contextManager.writeFile(file_path, newContent);
367
+ return `Successfully replaced pattern in ${file_path} (${currentContext.type} environment)
368
+ (Syntax check skipped for remote files)`;
369
+ }
370
+ }
359
371
  };
360
- export const multiEditFileTool = {
361
- schema: {
362
- name: 'multi_edit_file',
363
- description: `Apply MULTIPLE search-and-replace edits to a SINGLE file in ONE tool call.
364
-
365
- Use this instead of calling edit_file multiple times on the same file. This is more efficient and ensures all edits are applied atomically.
366
-
367
- WHEN TO USE:
368
- - You need to make 2+ edits to the same file
369
- - You want to batch changes to avoid multiple tool calls
370
- - The edits are independent (don't overlap)
371
-
372
- CRITICAL REQUIREMENTS:
373
- - Each edit's 'search_pattern' must be UNIQUE in the file
374
- - Edits are applied in order - earlier edits can affect line positions
375
- - All patterns must exist in the file or the entire operation fails
372
+ const multiEditFileTool = {
373
+ schema: {
374
+ name: "multi_edit_file",
375
+ description: `Apply MULTIPLE search-and-replace edits to a SINGLE file in ONE tool call.
376
+
377
+ Use this instead of calling edit_file multiple times on the same file. This is more efficient and ensures all edits are applied atomically.
378
+
379
+ WHEN TO USE:
380
+ - You need to make 2+ edits to the same file
381
+ - You want to batch changes to avoid multiple tool calls
382
+ - The edits are independent (don't overlap)
383
+
384
+ CRITICAL REQUIREMENTS:
385
+ - Each edit's 'search_pattern' must be UNIQUE in the file
386
+ - Edits are applied in order - earlier edits can affect line positions
387
+ - All patterns must exist in the file or the entire operation fails
376
388
  - You MUST have read the file first to know exact content`,
377
- parameters: {
378
- type: 'object',
389
+ parameters: {
390
+ type: "object",
391
+ properties: {
392
+ reason_text: {
393
+ type: "string",
394
+ description: "REQUIRED: A brief explanation of what changes you are making and why."
395
+ },
396
+ file_path: {
397
+ type: "string",
398
+ description: "The path to the file to edit"
399
+ },
400
+ edits: {
401
+ type: "array",
402
+ description: "Array of edit operations to apply, in order",
403
+ items: {
404
+ type: "object",
379
405
  properties: {
380
- reason_text: {
381
- type: 'string',
382
- description: 'REQUIRED: A brief explanation of what changes you are making and why.',
383
- },
384
- file_path: {
385
- type: 'string',
386
- description: 'The path to the file to edit',
387
- },
388
- edits: {
389
- type: 'array',
390
- description: 'Array of edit operations to apply, in order',
391
- items: {
392
- type: 'object',
393
- properties: {
394
- search_pattern: {
395
- type: 'string',
396
- description: 'The EXACT block of text to replace. Must be unique in the file.',
397
- },
398
- replacement: {
399
- type: 'string',
400
- description: 'The new text to insert in place of search_pattern.',
401
- },
402
- description: {
403
- type: 'string',
404
- description: 'Brief description of this specific edit',
405
- },
406
- },
407
- required: ['search_pattern', 'replacement'],
408
- },
409
- },
406
+ search_pattern: {
407
+ type: "string",
408
+ description: "The EXACT block of text to replace. Must be unique in the file."
409
+ },
410
+ replacement: {
411
+ type: "string",
412
+ description: "The new text to insert in place of search_pattern."
413
+ },
414
+ description: {
415
+ type: "string",
416
+ description: "Brief description of this specific edit"
417
+ }
410
418
  },
411
- required: ['reason_text', 'file_path', 'edits'],
412
- },
413
- },
414
- async execute(args, context) {
415
- const { file_path, edits } = args;
416
- const contextManager = context.contextManager;
417
- const currentContext = contextManager.getCurrentContext();
418
- if (!edits || !Array.isArray(edits) || edits.length === 0) {
419
- throw new Error('No edits provided. The edits array must contain at least one edit operation.');
420
- }
421
- // Read the current content
422
- let content;
423
- // Compute the full path for local files
424
- const fullPath = currentContext.type === 'local' ? path.resolve(context.cwd, file_path) : file_path;
425
- if (currentContext.type === 'local') {
426
- if (!fs.existsSync(fullPath)) {
427
- throw new Error(`File not found: ${file_path}`);
428
- }
429
- content = fs.readFileSync(fullPath, 'utf-8');
419
+ required: ["search_pattern", "replacement"]
420
+ }
430
421
  }
431
- else {
432
- content = await contextManager.readFile(file_path);
433
- }
434
- const originalContent = content;
435
- const { createFlexibleRegex } = await import('./validation.js');
436
- const appliedEdits = [];
437
- const errors = [];
438
- // Validate all patterns exist before applying any
439
- for (let i = 0; i < edits.length; i++) {
440
- const edit = edits[i];
441
- const regex = createFlexibleRegex(edit.search_pattern);
442
- const matches = content.match(regex);
443
- if (!matches || matches.length === 0) {
444
- errors.push(`Edit ${i + 1}: Pattern not found in file`);
445
- }
446
- else if (matches.length > 1) {
447
- errors.push(`Edit ${i + 1}: Pattern matches ${matches.length} times (must be unique)`);
448
- }
449
- }
450
- if (errors.length > 0) {
451
- throw new Error(`Validation failed:\n${errors.join('\n')}\n\nNo changes were made.`);
452
- }
453
- // Apply edits in order
454
- for (let i = 0; i < edits.length; i++) {
455
- const edit = edits[i];
456
- const regex = createFlexibleRegex(edit.search_pattern);
457
- // Re-check match after previous edits
458
- const matches = content.match(regex);
459
- if (!matches || matches.length === 0) {
460
- errors.push(`Edit ${i + 1}: Pattern no longer found after previous edits`);
461
- continue;
462
- }
463
- content = content.replace(regex, edit.replacement);
464
- appliedEdits.push(edit.description || `Edit ${i + 1}`);
465
- }
466
- // Generate combined diff
467
- const patch = Diff.createTwoFilesPatch(file_path, file_path, originalContent, content, '', '');
468
- const fullDiff = Diff.createTwoFilesPatch(file_path, file_path, originalContent, content, '', '', { context: Number.MAX_SAFE_INTEGER });
469
- // Ask for approval
470
- const approved = await context.requireApproval(`Apply ${edits.length} edits to ${fullPath}?`, false, {
471
- type: 'diff',
472
- content: patch,
473
- fullDiff: fullDiff
474
- }, 'multi_edit_file', { file_path: fullPath, editCount: edits.length });
475
- if (!approved) {
476
- throw new Error('Operation cancelled by user.');
477
- }
478
- // Write changes
479
- if (currentContext.type === 'local') {
480
- // Backup file before modification (for checkpoint revert)
481
- await backupBeforeChange(context, fullPath);
482
- fs.writeFileSync(fullPath, content, 'utf-8');
483
- const syntaxResult = await checkSyntax(fullPath, content);
484
- const syntaxFeedback = formatSyntaxCheckResult(syntaxResult);
485
- return `Successfully applied ${appliedEdits.length} edits to ${file_path}:\n${appliedEdits.map((e, i) => ` ${i + 1}. ${e}`).join('\n')}\n${syntaxFeedback}`;
486
- }
487
- else {
488
- // Backup remote file before modification (for checkpoint revert)
489
- await backupBeforeChange(context, fullPath);
490
- await contextManager.writeFile(file_path, content);
491
- return `Successfully applied ${appliedEdits.length} edits to ${file_path} (${currentContext.type} environment)`;
492
- }
493
- },
422
+ },
423
+ required: ["reason_text", "file_path", "edits"]
424
+ }
425
+ },
426
+ async execute(args, context) {
427
+ const { file_path, edits } = args;
428
+ const contextManager = context.contextManager;
429
+ const currentContext = contextManager.getCurrentContext();
430
+ if (!edits || !Array.isArray(edits) || edits.length === 0) {
431
+ throw new Error("No edits provided. The edits array must contain at least one edit operation.");
432
+ }
433
+ let content;
434
+ const fullPath = currentContext.type === "local" ? path.resolve(context.cwd, file_path) : file_path;
435
+ if (currentContext.type === "local") {
436
+ if (!fs.existsSync(fullPath)) {
437
+ throw new Error(`File not found: ${file_path}`);
438
+ }
439
+ content = fs.readFileSync(fullPath, "utf-8");
440
+ } else {
441
+ content = await contextManager.readFile(file_path);
442
+ }
443
+ const originalContent = content;
444
+ const { createFlexibleRegex } = await import("./validation.js");
445
+ const appliedEdits = [];
446
+ const errors = [];
447
+ for (let i = 0; i < edits.length; i++) {
448
+ const edit = edits[i];
449
+ const regex = createFlexibleRegex(edit.search_pattern);
450
+ const matches = content.match(regex);
451
+ if (!matches || matches.length === 0) {
452
+ errors.push(`Edit ${i + 1}: Pattern not found in file`);
453
+ } else if (matches.length > 1) {
454
+ errors.push(`Edit ${i + 1}: Pattern matches ${matches.length} times (must be unique)`);
455
+ }
456
+ }
457
+ if (errors.length > 0) {
458
+ throw new Error(`Validation failed:
459
+ ${errors.join("\n")}
460
+
461
+ No changes were made.`);
462
+ }
463
+ for (let i = 0; i < edits.length; i++) {
464
+ const edit = edits[i];
465
+ const regex = createFlexibleRegex(edit.search_pattern);
466
+ const matches = content.match(regex);
467
+ if (!matches || matches.length === 0) {
468
+ errors.push(`Edit ${i + 1}: Pattern no longer found after previous edits`);
469
+ continue;
470
+ }
471
+ content = content.replace(regex, edit.replacement);
472
+ appliedEdits.push(edit.description || `Edit ${i + 1}`);
473
+ }
474
+ const patch = Diff.createTwoFilesPatch(
475
+ file_path,
476
+ file_path,
477
+ originalContent,
478
+ content,
479
+ "",
480
+ ""
481
+ );
482
+ const fullDiff = Diff.createTwoFilesPatch(
483
+ file_path,
484
+ file_path,
485
+ originalContent,
486
+ content,
487
+ "",
488
+ "",
489
+ { context: Number.MAX_SAFE_INTEGER }
490
+ );
491
+ const approved = await context.requireApproval(
492
+ `Apply ${edits.length} edits to ${fullPath}?`,
493
+ false,
494
+ {
495
+ type: "diff",
496
+ content: patch,
497
+ fullDiff
498
+ },
499
+ "multi_edit_file",
500
+ { file_path: fullPath, editCount: edits.length }
501
+ );
502
+ if (!approved) {
503
+ throw new Error("Operation cancelled by user.");
504
+ }
505
+ if (currentContext.type === "local") {
506
+ await backupBeforeChange(context, fullPath);
507
+ fs.writeFileSync(fullPath, content, "utf-8");
508
+ const syntaxResult = await checkSyntax(fullPath, content);
509
+ const syntaxFeedback = formatSyntaxCheckResult(syntaxResult);
510
+ return `Successfully applied ${appliedEdits.length} edits to ${file_path}:
511
+ ${appliedEdits.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}
512
+ ${syntaxFeedback}`;
513
+ } else {
514
+ await backupBeforeChange(context, fullPath);
515
+ await contextManager.writeFile(file_path, content);
516
+ return `Successfully applied ${appliedEdits.length} edits to ${file_path} (${currentContext.type} environment)`;
517
+ }
518
+ }
494
519
  };
495
- export const listDirTool = {
496
- schema: {
497
- name: 'list_dir',
498
- description: `List the contents of a directory with statistics and smart limiting.
499
-
500
- For each directory child, output includes:
501
- - Directories: name and item count (sorted by size, largest first)
502
- - Files: name and size in KB (limited to 100 by default)
503
-
504
- SMART LIMITING:
505
- - Shows all directories (up to 50) - navigation is critical
506
- - Limits files to 100 - prevents context explosion
507
- - Always shows complete statistics (total dirs, files, items)
508
- - Highlights large directories (>100 items) for awareness
509
-
520
+ const listDirTool = {
521
+ schema: {
522
+ name: "list_dir",
523
+ description: `List the contents of a directory with statistics and smart limiting.
524
+
525
+ For each directory child, output includes:
526
+ - Directories: name and item count (sorted by size, largest first)
527
+ - Files: name and size in KB (limited to 100 by default)
528
+
529
+ SMART LIMITING:
530
+ - Shows all directories (up to 50) - navigation is critical
531
+ - Limits files to 100 - prevents context explosion
532
+ - Always shows complete statistics (total dirs, files, items)
533
+ - Highlights large directories (>100 items) for awareness
534
+
510
535
  IMPORTANT: You MUST provide a reason_text parameter explaining why you are listing this directory.`,
511
- parameters: {
512
- type: 'object',
513
- properties: {
514
- reason_text: {
515
- type: 'string',
516
- description: 'REQUIRED: A brief explanation of why you are listing this directory.',
517
- },
518
- DirectoryPath: {
519
- type: 'string',
520
- description: 'Path to list contents of, should be absolute path to a directory',
521
- },
522
- fileLimit: {
523
- type: 'integer',
524
- description: 'Optional: Maximum number of files to show (default: 100)',
525
- },
526
- showHidden: {
527
- type: 'boolean',
528
- description: 'Optional: Whether to show hidden files (dotfiles). Defaults to true.',
529
- },
530
- },
531
- required: ['reason_text', 'DirectoryPath'],
536
+ parameters: {
537
+ type: "object",
538
+ properties: {
539
+ reason_text: {
540
+ type: "string",
541
+ description: "REQUIRED: A brief explanation of why you are listing this directory."
542
+ },
543
+ DirectoryPath: {
544
+ type: "string",
545
+ description: "Path to list contents of, should be absolute path to a directory"
532
546
  },
533
- },
534
- async execute(args, context) {
535
- const { DirectoryPath, fileLimit = 100, showHidden = true } = args;
536
- const directory_path = DirectoryPath;
537
- const contextManager = context.contextManager;
538
- const currentContext = contextManager.getCurrentContext();
539
- if (currentContext.type === 'local') {
540
- const fullPath = path.isAbsolute(directory_path) ? directory_path : path.resolve(context.cwd, directory_path);
541
- if (!fs.existsSync(fullPath)) {
542
- throw new Error(`Directory not found: ${directory_path}\n\nAction: Check the path or use 'find_files' to locate the directory.`);
543
- }
544
- if (!fs.statSync(fullPath).isDirectory()) {
545
- throw new Error(`Path is not a directory: ${directory_path}\n\nAction: Verify the path points to a directory, not a file.`);
546
- }
547
- // Use enhanced listing
548
- const listing = fileUtils.listDirectoryEnhanced(fullPath, {
549
- fileLimit: fileLimit,
550
- dirLimit: 50,
551
- showHidden: showHidden,
552
- largeThreshold: 100
553
- });
554
- return fileUtils.formatDirectoryListing(directory_path, listing);
547
+ fileLimit: {
548
+ type: "integer",
549
+ description: "Optional: Maximum number of files to show (default: 100)"
550
+ },
551
+ showHidden: {
552
+ type: "boolean",
553
+ description: "Optional: Whether to show hidden files (dotfiles). Defaults to true."
554
+ }
555
+ },
556
+ required: ["reason_text", "DirectoryPath"]
557
+ }
558
+ },
559
+ async execute(args, context) {
560
+ const { DirectoryPath, fileLimit = 100, showHidden = true } = args;
561
+ const directory_path = DirectoryPath;
562
+ const contextManager = context.contextManager;
563
+ const currentContext = contextManager.getCurrentContext();
564
+ if (currentContext.type === "local") {
565
+ const fullPath = path.isAbsolute(directory_path) ? directory_path : path.resolve(context.cwd, directory_path);
566
+ if (!fs.existsSync(fullPath)) {
567
+ throw new Error(`Directory not found: ${directory_path}
568
+
569
+ Action: Check the path or use 'find_files' to locate the directory.`);
570
+ }
571
+ if (!fs.statSync(fullPath).isDirectory()) {
572
+ throw new Error(`Path is not a directory: ${directory_path}
573
+
574
+ Action: Verify the path points to a directory, not a file.`);
575
+ }
576
+ const listing = fileUtils.listDirectoryEnhanced(fullPath, {
577
+ fileLimit,
578
+ dirLimit: 50,
579
+ showHidden,
580
+ largeThreshold: 100
581
+ });
582
+ return fileUtils.formatDirectoryListing(directory_path, listing);
583
+ } else {
584
+ const entries = await contextManager.listDirectory(directory_path);
585
+ const directories = [];
586
+ const files = [];
587
+ for (const entry of entries) {
588
+ if (entry.type === "directory") {
589
+ directories.push(` ${entry.name}/`);
590
+ } else {
591
+ files.push(` ${entry.name}`);
592
+ }
593
+ }
594
+ const lines = [
595
+ `\u{1F4C1} Directory: ${directory_path} (${currentContext.type} environment)`,
596
+ "\u2550".repeat(50),
597
+ `Total: ${directories.length} directories, ${files.length} files, ${entries.length} items`,
598
+ ""
599
+ ];
600
+ if (directories.length > 0) {
601
+ lines.push("\u{1F4C2} Directories:");
602
+ lines.push(...directories.slice(0, 50));
603
+ if (directories.length > 50) {
604
+ lines.push(` ... and ${directories.length - 50} more directories`);
555
605
  }
556
- else {
557
- // For subshell contexts, use existing simple format
558
- // (enhanced format would require additional subshell handler changes)
559
- const entries = await contextManager.listDirectory(directory_path);
560
- const directories = [];
561
- const files = [];
562
- for (const entry of entries) {
563
- if (entry.type === 'directory') {
564
- directories.push(` ${entry.name}/`);
565
- }
566
- else {
567
- files.push(` ${entry.name}`);
568
- }
569
- }
570
- const lines = [
571
- `📁 Directory: ${directory_path} (${currentContext.type} environment)`,
572
- '═'.repeat(50),
573
- `Total: ${directories.length} directories, ${files.length} files, ${entries.length} items`,
574
- ''
575
- ];
576
- if (directories.length > 0) {
577
- lines.push('📂 Directories:');
578
- lines.push(...directories.slice(0, 50));
579
- if (directories.length > 50) {
580
- lines.push(` ... and ${directories.length - 50} more directories`);
581
- }
582
- lines.push('');
583
- }
584
- if (files.length > 0) {
585
- const fileLimit = 100;
586
- const shownFiles = files.slice(0, fileLimit);
587
- const hiddenCount = Math.max(0, files.length - fileLimit);
588
- lines.push(hiddenCount > 0
589
- ? `📄 Files (${shownFiles.length} of ${files.length} shown):`
590
- : '📄 Files:');
591
- lines.push(...shownFiles);
592
- if (hiddenCount > 0) {
593
- lines.push(` ... and ${hiddenCount} more files`);
594
- lines.push('');
595
- lines.push('💡 To see more: List subdirectories individually or use find_files to search');
596
- }
597
- }
598
- return lines.join('\n');
606
+ lines.push("");
607
+ }
608
+ if (files.length > 0) {
609
+ const fileLimit2 = 100;
610
+ const shownFiles = files.slice(0, fileLimit2);
611
+ const hiddenCount = Math.max(0, files.length - fileLimit2);
612
+ lines.push(hiddenCount > 0 ? `\u{1F4C4} Files (${shownFiles.length} of ${files.length} shown):` : "\u{1F4C4} Files:");
613
+ lines.push(...shownFiles);
614
+ if (hiddenCount > 0) {
615
+ lines.push(` ... and ${hiddenCount} more files`);
616
+ lines.push("");
617
+ lines.push("\u{1F4A1} To see more: List subdirectories individually or use find_files to search");
599
618
  }
600
- },
619
+ }
620
+ return lines.join("\n");
621
+ }
622
+ }
623
+ };
624
+ export {
625
+ editFileTool,
626
+ listDirTool,
627
+ multiEditFileTool,
628
+ viewFileTool,
629
+ writeToFileTool
601
630
  };
602
631
  //# sourceMappingURL=file-ops.js.map