@within-7/minto 0.1.6 → 0.2.0

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 (487) hide show
  1. package/cli.js +155 -37
  2. package/dist/Tool.js +38 -0
  3. package/dist/Tool.js.map +3 -3
  4. package/dist/commands/agents/AgentsCommand.js +52 -26
  5. package/dist/commands/agents/AgentsCommand.js.map +2 -2
  6. package/dist/commands/agents/constants.js +1 -1
  7. package/dist/commands/agents/constants.js.map +1 -1
  8. package/dist/commands/agents/index.js +1 -1
  9. package/dist/commands/bug.js +74 -7
  10. package/dist/commands/bug.js.map +3 -3
  11. package/dist/commands/clear.js +3 -0
  12. package/dist/commands/clear.js.map +2 -2
  13. package/dist/commands/compact.js +37 -0
  14. package/dist/commands/compact.js.map +2 -2
  15. package/dist/commands/context.js +84 -0
  16. package/dist/commands/context.js.map +7 -0
  17. package/dist/commands/ctx_viz.js +18 -10
  18. package/dist/commands/ctx_viz.js.map +2 -2
  19. package/dist/commands/doctor.js +158 -12
  20. package/dist/commands/doctor.js.map +2 -2
  21. package/dist/commands/export.js +156 -0
  22. package/dist/commands/export.js.map +7 -0
  23. package/dist/commands/mcp-interactive.js +21 -12
  24. package/dist/commands/mcp-interactive.js.map +2 -2
  25. package/dist/commands/model.js +6 -5
  26. package/dist/commands/model.js.map +2 -2
  27. package/dist/commands/permissions.js +86 -0
  28. package/dist/commands/permissions.js.map +7 -0
  29. package/dist/commands/quit.js +3 -1
  30. package/dist/commands/quit.js.map +2 -2
  31. package/dist/commands/sandbox.js +104 -0
  32. package/dist/commands/sandbox.js.map +7 -0
  33. package/dist/commands/status.js +58 -0
  34. package/dist/commands/status.js.map +7 -0
  35. package/dist/commands/tasks.js +108 -0
  36. package/dist/commands/tasks.js.map +7 -0
  37. package/dist/commands/todos.js +123 -0
  38. package/dist/commands/todos.js.map +7 -0
  39. package/dist/commands.js +20 -2
  40. package/dist/commands.js.map +2 -2
  41. package/dist/components/AgentThinkingBlock.js +10 -18
  42. package/dist/components/AgentThinkingBlock.js.map +2 -2
  43. package/dist/components/BackgroundTasksPanel.js +78 -29
  44. package/dist/components/BackgroundTasksPanel.js.map +2 -2
  45. package/dist/components/BashStreamingProgress.js +24 -0
  46. package/dist/components/BashStreamingProgress.js.map +7 -0
  47. package/dist/components/CollapsibleHint.js +14 -0
  48. package/dist/components/CollapsibleHint.js.map +7 -0
  49. package/dist/components/FileEditToolUpdatedMessage.js +1 -1
  50. package/dist/components/FileEditToolUpdatedMessage.js.map +2 -2
  51. package/dist/components/HotkeyHelpPanel.js +137 -0
  52. package/dist/components/HotkeyHelpPanel.js.map +7 -0
  53. package/dist/components/Logo.js +5 -5
  54. package/dist/components/Logo.js.map +2 -2
  55. package/dist/components/Message.js +23 -7
  56. package/dist/components/Message.js.map +3 -3
  57. package/dist/components/ModelConfig.js +16 -3
  58. package/dist/components/ModelConfig.js.map +2 -2
  59. package/dist/components/ModelListManager.js +3 -3
  60. package/dist/components/ModelListManager.js.map +2 -2
  61. package/dist/components/ModelSelector/ModelSelector.js +1 -1
  62. package/dist/components/Onboarding.js +19 -14
  63. package/dist/components/Onboarding.js.map +2 -2
  64. package/dist/components/ProgressBar.js +74 -0
  65. package/dist/components/ProgressBar.js.map +7 -0
  66. package/dist/components/PromptInput.js +156 -46
  67. package/dist/components/PromptInput.js.map +2 -2
  68. package/dist/components/RequestStatusIndicator.js +194 -0
  69. package/dist/components/RequestStatusIndicator.js.map +7 -0
  70. package/dist/components/Spinner.js +92 -27
  71. package/dist/components/Spinner.js.map +2 -2
  72. package/dist/components/SpinnerSymbol.js +21 -27
  73. package/dist/components/SpinnerSymbol.js.map +2 -2
  74. package/dist/components/StreamingBashOutput.js +9 -8
  75. package/dist/components/StreamingBashOutput.js.map +2 -2
  76. package/dist/components/SubagentBlock.js +1 -1
  77. package/dist/components/SubagentBlock.js.map +1 -1
  78. package/dist/components/SubagentProgress.js +10 -11
  79. package/dist/components/SubagentProgress.js.map +2 -2
  80. package/dist/components/TaskCard.js +16 -13
  81. package/dist/components/TaskCard.js.map +2 -2
  82. package/dist/components/TodoChangeBlock.js +1 -1
  83. package/dist/components/TodoChangeBlock.js.map +2 -2
  84. package/dist/components/TodoPanel.js +120 -29
  85. package/dist/components/TodoPanel.js.map +3 -3
  86. package/dist/components/TokenCounter.js +74 -0
  87. package/dist/components/TokenCounter.js.map +7 -0
  88. package/dist/components/TokenWarning.js +2 -1
  89. package/dist/components/TokenWarning.js.map +2 -2
  90. package/dist/components/TreeConnector.js +25 -0
  91. package/dist/components/TreeConnector.js.map +7 -0
  92. package/dist/components/TurnCompletionIndicator.js +18 -0
  93. package/dist/components/TurnCompletionIndicator.js.map +7 -0
  94. package/dist/components/messages/AssistantTextMessage.js +5 -2
  95. package/dist/components/messages/AssistantTextMessage.js.map +2 -2
  96. package/dist/components/messages/AssistantThinkingMessage.js +18 -3
  97. package/dist/components/messages/AssistantThinkingMessage.js.map +2 -2
  98. package/dist/components/messages/AssistantToolUseMessage.js +11 -8
  99. package/dist/components/messages/AssistantToolUseMessage.js.map +2 -2
  100. package/dist/components/messages/GroupRenderer.js +53 -0
  101. package/dist/components/messages/GroupRenderer.js.map +7 -0
  102. package/dist/components/messages/NestedTasksPreview.js +12 -0
  103. package/dist/components/messages/NestedTasksPreview.js.map +7 -0
  104. package/dist/components/messages/ParallelTasksGroupView.js +92 -0
  105. package/dist/components/messages/ParallelTasksGroupView.js.map +7 -0
  106. package/dist/components/messages/TaskInModuleView.js +198 -0
  107. package/dist/components/messages/TaskInModuleView.js.map +7 -0
  108. package/dist/components/messages/TaskOutputContent.js +53 -0
  109. package/dist/components/messages/TaskOutputContent.js.map +7 -0
  110. package/dist/components/messages/UserPromptMessage.js +1 -1
  111. package/dist/components/messages/UserPromptMessage.js.map +2 -2
  112. package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js +2 -3
  113. package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js.map +2 -2
  114. package/dist/components/permissions/FallbackPermissionRequest.js +4 -4
  115. package/dist/components/permissions/FallbackPermissionRequest.js.map +2 -2
  116. package/dist/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js +4 -4
  117. package/dist/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js.map +2 -2
  118. package/dist/constants/colors.js +48 -0
  119. package/dist/constants/colors.js.map +2 -2
  120. package/dist/constants/formatRules.js +102 -0
  121. package/dist/constants/formatRules.js.map +7 -0
  122. package/dist/constants/prompts.js +12 -34
  123. package/dist/constants/prompts.js.map +2 -2
  124. package/dist/constants/symbols.js +64 -6
  125. package/dist/constants/symbols.js.map +2 -2
  126. package/dist/constants/timing.js +5 -0
  127. package/dist/constants/timing.js.map +2 -2
  128. package/dist/core/config/defaults.js +84 -0
  129. package/dist/core/config/defaults.js.map +7 -0
  130. package/dist/core/config/index.js +111 -0
  131. package/dist/core/config/index.js.map +7 -0
  132. package/dist/core/config/loader.js +221 -0
  133. package/dist/core/config/loader.js.map +7 -0
  134. package/dist/core/config/migrations.js +128 -0
  135. package/dist/core/config/migrations.js.map +7 -0
  136. package/dist/core/config/schema.js +178 -0
  137. package/dist/core/config/schema.js.map +7 -0
  138. package/dist/core/costTracker.js +138 -0
  139. package/dist/core/costTracker.js.map +7 -0
  140. package/dist/core/index.js +5 -0
  141. package/dist/core/index.js.map +7 -0
  142. package/dist/core/permissions/auditLog.js +204 -0
  143. package/dist/core/permissions/auditLog.js.map +7 -0
  144. package/dist/core/permissions/engine/index.js +3 -0
  145. package/dist/core/permissions/engine/index.js.map +7 -0
  146. package/dist/core/permissions/engine/permissionEngine.js +106 -0
  147. package/dist/core/permissions/engine/permissionEngine.js.map +7 -0
  148. package/dist/core/permissions/engine/types.js +1 -0
  149. package/dist/core/permissions/engine/types.js.map +7 -0
  150. package/dist/core/permissions/index.js +84 -0
  151. package/dist/core/permissions/index.js.map +7 -0
  152. package/dist/core/permissions/ruleEngine.js +259 -0
  153. package/dist/core/permissions/ruleEngine.js.map +7 -0
  154. package/dist/core/permissions/rules/allowedToolsRule.js +62 -0
  155. package/dist/core/permissions/rules/allowedToolsRule.js.map +7 -0
  156. package/dist/core/permissions/rules/autoEscalationRule.js +291 -0
  157. package/dist/core/permissions/rules/autoEscalationRule.js.map +7 -0
  158. package/dist/core/permissions/rules/index.js +46 -0
  159. package/dist/core/permissions/rules/index.js.map +7 -0
  160. package/dist/core/permissions/rules/planModeRule.js +55 -0
  161. package/dist/core/permissions/rules/planModeRule.js.map +7 -0
  162. package/dist/core/permissions/rules/projectBoundaryRule.js +168 -0
  163. package/dist/core/permissions/rules/projectBoundaryRule.js.map +7 -0
  164. package/dist/core/permissions/rules/safeModeRule.js +65 -0
  165. package/dist/core/permissions/rules/safeModeRule.js.map +7 -0
  166. package/dist/core/permissions/rules/sensitivePathsRule.js +340 -0
  167. package/dist/core/permissions/rules/sensitivePathsRule.js.map +7 -0
  168. package/dist/core/permissions/types.js +127 -0
  169. package/dist/core/permissions/types.js.map +7 -0
  170. package/dist/core/tools/executor.js +143 -0
  171. package/dist/core/tools/executor.js.map +7 -0
  172. package/dist/core/tools/index.js +15 -0
  173. package/dist/core/tools/index.js.map +7 -0
  174. package/dist/core/tools/registry.js +183 -0
  175. package/dist/core/tools/registry.js.map +7 -0
  176. package/dist/core/tools/types.js +1 -0
  177. package/dist/core/tools/types.js.map +7 -0
  178. package/dist/cost-tracker.js +23 -15
  179. package/dist/cost-tracker.js.map +2 -2
  180. package/dist/entrypoints/cli.js +43 -43
  181. package/dist/entrypoints/cli.js.map +2 -2
  182. package/dist/entrypoints/mcp.js +12 -4
  183. package/dist/entrypoints/mcp.js.map +2 -2
  184. package/dist/history.js +14 -3
  185. package/dist/history.js.map +2 -2
  186. package/dist/hooks/useAgentTranscripts.js +116 -0
  187. package/dist/hooks/useAgentTranscripts.js.map +7 -0
  188. package/dist/hooks/useAnimationSync.js +53 -0
  189. package/dist/hooks/useAnimationSync.js.map +7 -0
  190. package/dist/hooks/useArrowKeyHistory.js +4 -2
  191. package/dist/hooks/useArrowKeyHistory.js.map +2 -2
  192. package/dist/hooks/useCanUseTool.js +3 -1
  193. package/dist/hooks/useCanUseTool.js.map +2 -2
  194. package/dist/hooks/useCancelRequest.js +4 -1
  195. package/dist/hooks/useCancelRequest.js.map +2 -2
  196. package/dist/hooks/useExitOnCtrlCD.js +9 -5
  197. package/dist/hooks/useExitOnCtrlCD.js.map +2 -2
  198. package/dist/hooks/useHookStatus.js +40 -0
  199. package/dist/hooks/useHookStatus.js.map +7 -0
  200. package/dist/hooks/useLogMessages.js +17 -1
  201. package/dist/hooks/useLogMessages.js.map +2 -2
  202. package/dist/hooks/useMessageGroups.js +43 -0
  203. package/dist/hooks/useMessageGroups.js.map +7 -0
  204. package/dist/hooks/useTerminalSize.js +62 -6
  205. package/dist/hooks/useTerminalSize.js.map +2 -2
  206. package/dist/hooks/useUnifiedCompletion.js +69 -0
  207. package/dist/hooks/useUnifiedCompletion.js.map +2 -2
  208. package/dist/i18n/index.js +109 -0
  209. package/dist/i18n/index.js.map +7 -0
  210. package/dist/i18n/locales/en.js +347 -0
  211. package/dist/i18n/locales/en.js.map +7 -0
  212. package/dist/i18n/locales/index.js +7 -0
  213. package/dist/i18n/locales/index.js.map +7 -0
  214. package/dist/i18n/locales/zh-CN.js +347 -0
  215. package/dist/i18n/locales/zh-CN.js.map +7 -0
  216. package/dist/i18n/types.js +8 -0
  217. package/dist/i18n/types.js.map +7 -0
  218. package/dist/query.js +175 -17
  219. package/dist/query.js.map +3 -3
  220. package/dist/screens/REPL.js +501 -192
  221. package/dist/screens/REPL.js.map +3 -3
  222. package/dist/services/adapters/chatCompletions.js +3 -1
  223. package/dist/services/adapters/chatCompletions.js.map +2 -2
  224. package/dist/services/adapters/messageNormalizer.js +354 -0
  225. package/dist/services/adapters/messageNormalizer.js.map +7 -0
  226. package/dist/services/adapters/responsesAPI.js +6 -3
  227. package/dist/services/adapters/responsesAPI.js.map +2 -2
  228. package/dist/services/checkpointManager.js +386 -0
  229. package/dist/services/checkpointManager.js.map +7 -0
  230. package/dist/services/claude.js +138 -11
  231. package/dist/services/claude.js.map +3 -3
  232. package/dist/services/compressionService.js +50 -1
  233. package/dist/services/compressionService.js.map +2 -2
  234. package/dist/services/contextMonitor.js +162 -0
  235. package/dist/services/contextMonitor.js.map +7 -0
  236. package/dist/services/customCommands.js +60 -41
  237. package/dist/services/customCommands.js.map +2 -2
  238. package/dist/services/hookExecutor.js +173 -1
  239. package/dist/services/hookExecutor.js.map +2 -2
  240. package/dist/services/intelligentCompactor.js +281 -0
  241. package/dist/services/intelligentCompactor.js.map +7 -0
  242. package/dist/services/lspConfig.js +109 -0
  243. package/dist/services/lspConfig.js.map +7 -0
  244. package/dist/services/mcpClient.js +273 -34
  245. package/dist/services/mcpClient.js.map +2 -2
  246. package/dist/services/modelOrchestrator.js +310 -0
  247. package/dist/services/modelOrchestrator.js.map +7 -0
  248. package/dist/services/openai.js +8 -1
  249. package/dist/services/openai.js.map +2 -2
  250. package/dist/services/outputStyles.js +138 -0
  251. package/dist/services/outputStyles.js.map +7 -0
  252. package/dist/services/plugins/index.js +5 -0
  253. package/dist/services/plugins/index.js.map +7 -0
  254. package/dist/services/plugins/lspServers.js +188 -0
  255. package/dist/services/plugins/lspServers.js.map +7 -0
  256. package/dist/services/plugins/pluginRuntime.js +229 -0
  257. package/dist/services/plugins/pluginRuntime.js.map +7 -0
  258. package/dist/services/plugins/pluginValidation.js +219 -0
  259. package/dist/services/plugins/pluginValidation.js.map +7 -0
  260. package/dist/services/plugins/skillMarketplace.js +556 -0
  261. package/dist/services/plugins/skillMarketplace.js.map +7 -0
  262. package/dist/services/responseStateManager.js +37 -3
  263. package/dist/services/responseStateManager.js.map +2 -2
  264. package/dist/services/sandbox/filesystemBoundary.js +300 -0
  265. package/dist/services/sandbox/filesystemBoundary.js.map +7 -0
  266. package/dist/services/sandbox/index.js +14 -0
  267. package/dist/services/sandbox/index.js.map +7 -0
  268. package/dist/services/sandbox/networkProxy.js +293 -0
  269. package/dist/services/sandbox/networkProxy.js.map +7 -0
  270. package/dist/services/sandbox/sandboxController.js +574 -0
  271. package/dist/services/sandbox/sandboxController.js.map +7 -0
  272. package/dist/services/sandbox/types.js +50 -0
  273. package/dist/services/sandbox/types.js.map +7 -0
  274. package/dist/services/sessionMemory.js +266 -0
  275. package/dist/services/sessionMemory.js.map +7 -0
  276. package/dist/services/taskRouter.js +324 -0
  277. package/dist/services/taskRouter.js.map +7 -0
  278. package/dist/tools/ArchitectTool/ArchitectTool.js +10 -3
  279. package/dist/tools/ArchitectTool/ArchitectTool.js.map +2 -2
  280. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +3 -0
  281. package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +2 -2
  282. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js +8 -1
  283. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js.map +2 -2
  284. package/dist/tools/BaseTool.js +72 -0
  285. package/dist/tools/BaseTool.js.map +7 -0
  286. package/dist/tools/BashOutputTool/BashOutputToolResultMessage.js +3 -0
  287. package/dist/tools/BashOutputTool/BashOutputToolResultMessage.js.map +2 -2
  288. package/dist/tools/BashTool/BashTool.js +60 -3
  289. package/dist/tools/BashTool/BashTool.js.map +2 -2
  290. package/dist/tools/BashTool/BashToolResultMessage.js +3 -0
  291. package/dist/tools/BashTool/BashToolResultMessage.js.map +2 -2
  292. package/dist/tools/BashTool/OutputLine.js +54 -0
  293. package/dist/tools/BashTool/OutputLine.js.map +2 -2
  294. package/dist/tools/BashTool/prompt.js +192 -3
  295. package/dist/tools/BashTool/prompt.js.map +2 -2
  296. package/dist/tools/FileEditTool/FileEditTool.js +29 -4
  297. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  298. package/dist/tools/FileReadTool/FileReadTool.js +23 -4
  299. package/dist/tools/FileReadTool/FileReadTool.js.map +2 -2
  300. package/dist/tools/FileWriteTool/FileWriteTool.js +5 -5
  301. package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
  302. package/dist/tools/GlobTool/GlobTool.js +14 -3
  303. package/dist/tools/GlobTool/GlobTool.js.map +2 -2
  304. package/dist/tools/GrepTool/GrepTool.js +41 -7
  305. package/dist/tools/GrepTool/GrepTool.js.map +2 -2
  306. package/dist/tools/KillShellTool/KillShellToolResultMessage.js +3 -0
  307. package/dist/tools/KillShellTool/KillShellToolResultMessage.js.map +2 -2
  308. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js +109 -0
  309. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +7 -0
  310. package/dist/tools/ListMcpResourcesTool/prompt.js +19 -0
  311. package/dist/tools/ListMcpResourcesTool/prompt.js.map +7 -0
  312. package/dist/tools/LspTool/LspTool.js +664 -0
  313. package/dist/tools/LspTool/LspTool.js.map +7 -0
  314. package/dist/tools/LspTool/prompt.js +27 -0
  315. package/dist/tools/LspTool/prompt.js.map +7 -0
  316. package/dist/tools/MCPTool/MCPTool.js +11 -4
  317. package/dist/tools/MCPTool/MCPTool.js.map +2 -2
  318. package/dist/tools/MemoryReadTool/MemoryReadTool.js +19 -6
  319. package/dist/tools/MemoryReadTool/MemoryReadTool.js.map +2 -2
  320. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js +6 -6
  321. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js.map +2 -2
  322. package/dist/tools/MultiEditTool/MultiEditTool.js +19 -2
  323. package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
  324. package/dist/tools/NotebookEditTool/NotebookEditTool.js +5 -1
  325. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
  326. package/dist/tools/NotebookReadTool/NotebookReadTool.js +8 -4
  327. package/dist/tools/NotebookReadTool/NotebookReadTool.js.map +2 -2
  328. package/dist/tools/PlanModeTool/EnterPlanModeTool.js +74 -0
  329. package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +7 -0
  330. package/dist/tools/PlanModeTool/ExitPlanModeTool.js +108 -0
  331. package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +7 -0
  332. package/dist/tools/PlanModeTool/prompt.js +94 -0
  333. package/dist/tools/PlanModeTool/prompt.js.map +7 -0
  334. package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js +130 -0
  335. package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js.map +7 -0
  336. package/dist/tools/ReadMcpResourceTool/prompt.js +17 -0
  337. package/dist/tools/ReadMcpResourceTool/prompt.js.map +7 -0
  338. package/dist/tools/SkillTool/SkillTool.js +14 -3
  339. package/dist/tools/SkillTool/SkillTool.js.map +2 -2
  340. package/dist/tools/SlashCommandTool/SlashCommandTool.js +260 -0
  341. package/dist/tools/SlashCommandTool/SlashCommandTool.js.map +7 -0
  342. package/dist/tools/SlashCommandTool/prompt.js +35 -0
  343. package/dist/tools/SlashCommandTool/prompt.js.map +7 -0
  344. package/dist/tools/TaskOutputTool/TaskOutputTool.js +189 -0
  345. package/dist/tools/TaskOutputTool/TaskOutputTool.js.map +7 -0
  346. package/dist/tools/TaskOutputTool/prompt.js +15 -0
  347. package/dist/tools/TaskOutputTool/prompt.js.map +7 -0
  348. package/dist/tools/TaskTool/TaskTool.js +321 -146
  349. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  350. package/dist/tools/TaskTool/prompt.js.map +2 -2
  351. package/dist/tools/TodoWriteTool/TodoWriteTool.js +42 -73
  352. package/dist/tools/TodoWriteTool/TodoWriteTool.js.map +2 -2
  353. package/dist/tools/URLFetcherTool/URLFetcherTool.js +7 -1
  354. package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +2 -2
  355. package/dist/tools/URLFetcherTool/cache.js +55 -8
  356. package/dist/tools/URLFetcherTool/cache.js.map +2 -2
  357. package/dist/tools/WebSearchTool/WebSearchTool.js +6 -1
  358. package/dist/tools/WebSearchTool/WebSearchTool.js.map +2 -2
  359. package/dist/tools.js +31 -2
  360. package/dist/tools.js.map +2 -2
  361. package/dist/types/hooks.js +4 -0
  362. package/dist/types/hooks.js.map +2 -2
  363. package/dist/types/marketplace.js.map +2 -2
  364. package/dist/types/messageGroup.js +36 -0
  365. package/dist/types/messageGroup.js.map +7 -0
  366. package/dist/types/plugin.js.map +2 -2
  367. package/dist/types/thinking.js +1 -0
  368. package/dist/types/thinking.js.map +7 -0
  369. package/dist/utils/BackgroundShellManager.js +136 -39
  370. package/dist/utils/BackgroundShellManager.js.map +2 -2
  371. package/dist/utils/MessageBatchBuffer.js +102 -0
  372. package/dist/utils/MessageBatchBuffer.js.map +7 -0
  373. package/dist/utils/PersistentShell.js +151 -1
  374. package/dist/utils/PersistentShell.js.map +2 -2
  375. package/dist/utils/agentLoader.js +1 -23
  376. package/dist/utils/agentLoader.js.map +2 -2
  377. package/dist/utils/agentTranscripts.js +641 -0
  378. package/dist/utils/agentTranscripts.js.map +7 -0
  379. package/dist/utils/animationManager.js +213 -0
  380. package/dist/utils/animationManager.js.map +7 -0
  381. package/dist/utils/animationSync.js +110 -0
  382. package/dist/utils/animationSync.js.map +7 -0
  383. package/dist/utils/asyncFile.js +215 -0
  384. package/dist/utils/asyncFile.js.map +7 -0
  385. package/dist/utils/backgroundAgentManager.js +231 -0
  386. package/dist/utils/backgroundAgentManager.js.map +7 -0
  387. package/dist/utils/config.js +63 -7
  388. package/dist/utils/config.js.map +2 -2
  389. package/dist/utils/conversationRecovery.js +19 -0
  390. package/dist/utils/conversationRecovery.js.map +2 -2
  391. package/dist/utils/exit.js +73 -0
  392. package/dist/utils/exit.js.map +7 -0
  393. package/dist/utils/format.js +73 -5
  394. package/dist/utils/format.js.map +2 -2
  395. package/dist/utils/generators.js +76 -6
  396. package/dist/utils/generators.js.map +2 -2
  397. package/dist/utils/globalErrorHandler.js +149 -0
  398. package/dist/utils/globalErrorHandler.js.map +7 -0
  399. package/dist/utils/groupHandlers/index.js +8 -0
  400. package/dist/utils/groupHandlers/index.js.map +7 -0
  401. package/dist/utils/groupHandlers/parallelTasksHandler.js +140 -0
  402. package/dist/utils/groupHandlers/parallelTasksHandler.js.map +7 -0
  403. package/dist/utils/groupHandlers/taskHandler.js +104 -0
  404. package/dist/utils/groupHandlers/taskHandler.js.map +7 -0
  405. package/dist/utils/groupHandlers/types.js +1 -0
  406. package/dist/utils/groupHandlers/types.js.map +7 -0
  407. package/dist/utils/logRotation.js +224 -0
  408. package/dist/utils/logRotation.js.map +7 -0
  409. package/dist/utils/marketplaceManager.js +3 -5
  410. package/dist/utils/marketplaceManager.js.map +2 -2
  411. package/dist/utils/memSafety.js +264 -0
  412. package/dist/utils/memSafety.js.map +7 -0
  413. package/dist/utils/messageGroupManager.js +274 -0
  414. package/dist/utils/messageGroupManager.js.map +7 -0
  415. package/dist/utils/messages.js +13 -4
  416. package/dist/utils/messages.js.map +2 -2
  417. package/dist/utils/model.js +119 -15
  418. package/dist/utils/model.js.map +3 -3
  419. package/dist/utils/permissions/filesystem.js +157 -5
  420. package/dist/utils/permissions/filesystem.js.map +2 -2
  421. package/dist/utils/plan/planMode.js +143 -0
  422. package/dist/utils/plan/planMode.js.map +7 -0
  423. package/dist/utils/pluginLoader.js +17 -21
  424. package/dist/utils/pluginLoader.js.map +2 -2
  425. package/dist/utils/ripgrep.js +55 -2
  426. package/dist/utils/ripgrep.js.map +2 -2
  427. package/dist/utils/sanitizeInput.js +32 -0
  428. package/dist/utils/sanitizeInput.js.map +7 -0
  429. package/dist/utils/secureKeyStorage.js +312 -0
  430. package/dist/utils/secureKeyStorage.js.map +7 -0
  431. package/dist/utils/session/sessionPlugins.js +67 -0
  432. package/dist/utils/session/sessionPlugins.js.map +7 -0
  433. package/dist/utils/taskDisplayUtils.js +257 -0
  434. package/dist/utils/taskDisplayUtils.js.map +7 -0
  435. package/dist/utils/teamConfig.js +2 -1
  436. package/dist/utils/teamConfig.js.map +2 -2
  437. package/dist/utils/todoStorage.js +92 -2
  438. package/dist/utils/todoStorage.js.map +2 -2
  439. package/dist/utils/toolTimeout.js +136 -0
  440. package/dist/utils/toolTimeout.js.map +7 -0
  441. package/dist/utils/tooling/safeRender.js +115 -0
  442. package/dist/utils/tooling/safeRender.js.map +7 -0
  443. package/dist/utils/userFriendlyError.js +346 -0
  444. package/dist/utils/userFriendlyError.js.map +7 -0
  445. package/dist/utils/vendor/ripgrep/arm64-darwin/rg +0 -0
  446. package/dist/version.js +2 -2
  447. package/dist/version.js.map +1 -1
  448. package/package.json +14 -4
  449. package/scripts/postinstall.js +128 -38
  450. package/dist/commands/agents.js +0 -2086
  451. package/dist/commands/agents.js.map +0 -7
  452. package/dist/commands/build.js +0 -74
  453. package/dist/commands/build.js.map +0 -7
  454. package/dist/commands/compression.js +0 -57
  455. package/dist/commands/compression.js.map +0 -7
  456. package/dist/commands/listen.js +0 -37
  457. package/dist/commands/listen.js.map +0 -7
  458. package/dist/commands/login.js +0 -37
  459. package/dist/commands/login.js.map +0 -7
  460. package/dist/commands/logout.js +0 -33
  461. package/dist/commands/logout.js.map +0 -7
  462. package/dist/commands/mcp.js +0 -40
  463. package/dist/commands/mcp.js.map +0 -7
  464. package/dist/commands/mcp_refresh.js +0 -40
  465. package/dist/commands/mcp_refresh.js.map +0 -7
  466. package/dist/commands/modelstatus.js +0 -21
  467. package/dist/commands/modelstatus.js.map +0 -7
  468. package/dist/commands/onboarding.js +0 -36
  469. package/dist/commands/onboarding.js.map +0 -7
  470. package/dist/commands/plugin-interactive.js +0 -446
  471. package/dist/commands/plugin-interactive.js.map +0 -7
  472. package/dist/commands/pr_comments.js +0 -61
  473. package/dist/commands/pr_comments.js.map +0 -7
  474. package/dist/commands/release-notes.js +0 -30
  475. package/dist/commands/release-notes.js.map +0 -7
  476. package/dist/commands/review.js +0 -51
  477. package/dist/commands/review.js.map +0 -7
  478. package/dist/components/Bug.js +0 -147
  479. package/dist/components/Bug.js.map +0 -7
  480. package/dist/components/ModelSelector.js +0 -2062
  481. package/dist/components/ModelSelector.js.map +0 -7
  482. package/dist/components/ModelStatusDisplay.js +0 -87
  483. package/dist/components/ModelStatusDisplay.js.map +0 -7
  484. package/dist/entrypoints/cli-wrapper.js +0 -61
  485. package/dist/entrypoints/cli-wrapper.js.map +0 -7
  486. package/dist/screens/Doctor.js +0 -22
  487. package/dist/screens/Doctor.js.map +0 -7
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/tools/LspTool/LspTool.tsx"],
4
+ "sourcesContent": ["/**\n * LSP Tool\n *\n * Provides Language Server Protocol operations for code intelligence.\n * Currently supports TypeScript/JavaScript files using the project's TypeScript.\n */\n\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport type { Tool, ToolUseContext } from '@tool'\nimport { getCwd } from '@utils/state'\nimport { existsSync, readFileSync, statSync } from 'fs'\nimport { Box, Text } from 'ink'\nimport { createRequire } from 'node:module'\nimport { extname, join, relative } from 'path'\nimport React from 'react'\nimport { pathToFileURL } from 'url'\nimport { z } from 'zod'\nimport { DESCRIPTION, PROMPT, TOOL_NAME_FOR_PROMPT } from './prompt'\n\ntype TypeScriptModule = typeof import('typescript')\n\ntype Operation =\n | 'goToDefinition'\n | 'findReferences'\n | 'hover'\n | 'documentSymbol'\n | 'workspaceSymbol'\n | 'goToImplementation'\n | 'prepareCallHierarchy'\n | 'incomingCalls'\n | 'outgoingCalls'\n\nconst inputSchema = z.strictObject({\n operation: z\n .enum([\n 'goToDefinition',\n 'findReferences',\n 'hover',\n 'documentSymbol',\n 'workspaceSymbol',\n 'goToImplementation',\n 'prepareCallHierarchy',\n 'incomingCalls',\n 'outgoingCalls',\n ])\n .describe('The LSP operation to perform'),\n filePath: z.string().describe('The absolute or relative path to the file'),\n line: z\n .number()\n .int()\n .positive()\n .describe('The line number (1-based, as shown in editors)'),\n character: z\n .number()\n .int()\n .positive()\n .describe('The character offset (1-based, as shown in editors)'),\n})\n\nconst outputSchema = z.object({\n operation: z\n .enum([\n 'goToDefinition',\n 'findReferences',\n 'hover',\n 'documentSymbol',\n 'workspaceSymbol',\n 'goToImplementation',\n 'prepareCallHierarchy',\n 'incomingCalls',\n 'outgoingCalls',\n ])\n .describe('The LSP operation that was performed'),\n result: z.string().describe('The formatted result of the LSP operation'),\n filePath: z.string().describe('The file path the operation was performed on'),\n resultCount: z\n .number()\n .int()\n .nonnegative()\n .optional()\n .describe('Number of results (definitions, references, symbols)'),\n fileCount: z\n .number()\n .int()\n .nonnegative()\n .optional()\n .describe('Number of files containing results'),\n})\n\ntype Input = z.infer<typeof inputSchema>\ntype Output = z.infer<typeof outputSchema>\n\nconst OPERATION_LABELS: Record<\n Operation,\n { singular: string; plural: string; special?: string }\n> = {\n goToDefinition: { singular: 'definition', plural: 'definitions' },\n findReferences: { singular: 'reference', plural: 'references' },\n documentSymbol: { singular: 'symbol', plural: 'symbols' },\n workspaceSymbol: { singular: 'symbol', plural: 'symbols' },\n hover: { singular: 'hover info', plural: 'hover info', special: 'available' },\n goToImplementation: { singular: 'implementation', plural: 'implementations' },\n prepareCallHierarchy: { singular: 'call item', plural: 'call items' },\n incomingCalls: { singular: 'caller', plural: 'callers' },\n outgoingCalls: { singular: 'callee', plural: 'callees' },\n}\n\nfunction getAbsolutePath(filePath: string): string {\n if (filePath.startsWith('/')) return filePath\n return join(getCwd(), filePath)\n}\n\nfunction toProjectRelativeIfPossible(filePath: string): string {\n const cwd = getCwd()\n try {\n const rel = relative(cwd, filePath)\n if (!rel || rel === '') return filePath\n if (rel.startsWith('..')) return filePath\n return rel\n } catch {\n return filePath\n }\n}\n\nfunction formatLocation(\n fileName: string,\n line0: number,\n character0: number,\n): string {\n return `${toProjectRelativeIfPossible(fileName)}:${line0 + 1}:${character0 + 1}`\n}\n\nfunction formatGoToDefinitionResult(\n locations: Array<{\n fileName: string\n line0: number\n character0: number\n }> | null,\n): { formatted: string; resultCount: number; fileCount: number } {\n if (!locations || locations.length === 0) {\n return {\n formatted:\n 'No definition found. This may occur if the cursor is not on a symbol, or if the definition is in an external library not indexed by the LSP server.',\n resultCount: 0,\n fileCount: 0,\n }\n }\n const fileCount = new Set(locations.map(l => l.fileName)).size\n if (locations.length === 1) {\n const loc = locations[0]\n return {\n formatted: `Defined in ${formatLocation(loc.fileName, loc.line0, loc.character0)}`,\n resultCount: 1,\n fileCount,\n }\n }\n return {\n formatted: `Found ${locations.length} definitions:\\n${locations\n .map(\n loc => ` ${formatLocation(loc.fileName, loc.line0, loc.character0)}`,\n )\n .join('\\n')}`,\n resultCount: locations.length,\n fileCount,\n }\n}\n\nfunction groupLocationsByFile<T extends { fileName: string }>(\n items: T[],\n): Map<string, T[]> {\n const grouped = new Map<string, T[]>()\n for (const item of items) {\n const key = toProjectRelativeIfPossible(item.fileName)\n const existing = grouped.get(key)\n if (existing) existing.push(item)\n else grouped.set(key, [item])\n }\n return grouped\n}\n\nfunction formatFindReferencesResult(\n references: Array<{\n fileName: string\n line0: number\n character0: number\n }> | null,\n): { formatted: string; resultCount: number; fileCount: number } {\n if (!references || references.length === 0) {\n return {\n formatted:\n 'No references found. This may occur if the symbol has no usages, or if the LSP server has not fully indexed the workspace.',\n resultCount: 0,\n fileCount: 0,\n }\n }\n if (references.length === 1) {\n const ref = references[0]\n return {\n formatted: `Found 1 reference:\\n ${formatLocation(ref.fileName, ref.line0, ref.character0)}`,\n resultCount: 1,\n fileCount: 1,\n }\n }\n\n const grouped = groupLocationsByFile(references)\n const lines: string[] = [\n `Found ${references.length} references across ${grouped.size} files:`,\n ]\n for (const [file, refs] of grouped) {\n lines.push(`\\n${file}:`)\n for (const ref of refs) {\n lines.push(` Line ${ref.line0 + 1}:${ref.character0 + 1}`)\n }\n }\n return {\n formatted: lines.join('\\n'),\n resultCount: references.length,\n fileCount: grouped.size,\n }\n}\n\nfunction formatHoverResult(\n hoverText: string | null,\n line0: number,\n character0: number,\n) {\n if (!hoverText || hoverText.trim() === '') {\n return {\n formatted:\n 'No hover information available. This may occur if the cursor is not on a symbol, or if the LSP server has not fully indexed the file.',\n resultCount: 0,\n fileCount: 0,\n }\n }\n return {\n formatted: `Hover info at ${line0 + 1}:${character0 + 1}:\\n\\n${hoverText}`,\n resultCount: 1,\n fileCount: 1,\n }\n}\n\nfunction formatDocumentSymbolsResult(lines: string[], symbolCount: number) {\n if (symbolCount === 0) {\n return {\n formatted:\n 'No symbols found in document. This may occur if the file is empty, not supported by the LSP server, or if the server has not fully indexed the file.',\n resultCount: 0,\n fileCount: 0,\n }\n }\n return {\n formatted: ['Document symbols:', ...lines].join('\\n'),\n resultCount: symbolCount,\n fileCount: 1,\n }\n}\n\n// TypeScript module cache\nlet cachedTypeScript: { cwd: string; module: TypeScriptModule | null } | null =\n null\n\nfunction tryLoadTypeScriptModule(projectCwd: string): TypeScriptModule | null {\n if (cachedTypeScript?.cwd === projectCwd) return cachedTypeScript.module\n\n try {\n const requireFromCwd = createRequire(\n pathToFileURL(join(projectCwd, '__minto_lsp__.js')),\n )\n const mod = requireFromCwd('typescript') as TypeScriptModule\n cachedTypeScript = { cwd: projectCwd, module: mod }\n return mod\n } catch {\n cachedTypeScript = { cwd: projectCwd, module: null }\n return null\n }\n}\n\ntype TsProjectState = {\n ts: TypeScriptModule\n cwd: string\n rootFiles: Set<string>\n compilerOptions: any\n languageService: any\n versions: Map<string, string>\n}\n\nconst projectCache = new Map<string, TsProjectState>()\n\nfunction getOrCreateTsProject(projectCwd: string): TsProjectState | null {\n const ts = tryLoadTypeScriptModule(projectCwd)\n if (!ts) return null\n\n const existing = projectCache.get(projectCwd)\n if (existing) return existing\n\n let compilerOptions: any = {\n allowJs: true,\n checkJs: false,\n jsx: ts.JsxEmit.ReactJSX,\n target: ts.ScriptTarget.ESNext,\n module: ts.ModuleKind.ESNext,\n moduleResolution: ts.ModuleResolutionKind.NodeNext,\n }\n\n let rootFileNames: string[] = []\n try {\n const configPath = ts.findConfigFile(\n projectCwd,\n ts.sys.fileExists,\n 'tsconfig.json',\n )\n if (configPath) {\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile)\n if (!configFile.error) {\n const parsed = ts.parseJsonConfigFileContent(\n configFile.config,\n ts.sys,\n projectCwd,\n )\n compilerOptions = { ...compilerOptions, ...parsed.options }\n rootFileNames = parsed.fileNames\n }\n }\n } catch {\n // Use defaults\n }\n\n const rootFiles = new Set(rootFileNames)\n const versions = new Map<string, string>()\n\n const host: any = {\n getCompilationSettings: () => compilerOptions,\n getScriptFileNames: () => Array.from(rootFiles),\n getScriptVersion: (fileName: string) => {\n try {\n const stat = statSync(fileName)\n const version = String(stat.mtimeMs ?? Date.now())\n versions.set(fileName, version)\n return version\n } catch {\n return versions.get(fileName) ?? '0'\n }\n },\n getScriptSnapshot: (fileName: string) => {\n try {\n if (!ts.sys.fileExists(fileName)) return undefined\n const content = ts.sys.readFile(fileName)\n if (content === undefined) return undefined\n const stat = statSync(fileName)\n versions.set(fileName, String(stat.mtimeMs ?? Date.now()))\n return ts.ScriptSnapshot.fromString(content)\n } catch {\n return undefined\n }\n },\n getCurrentDirectory: () => projectCwd,\n getDefaultLibFileName: (options: any) => ts.getDefaultLibFilePath(options),\n fileExists: ts.sys.fileExists,\n readFile: ts.sys.readFile,\n readDirectory: ts.sys.readDirectory,\n directoryExists: ts.sys.directoryExists,\n getDirectories: ts.sys.getDirectories,\n useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,\n getCanonicalFileName: (fileName: string) =>\n ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),\n getNewLine: () => ts.sys.newLine,\n }\n\n const languageService = ts.createLanguageService(\n host,\n ts.createDocumentRegistry(),\n )\n\n const state: TsProjectState = {\n ts,\n cwd: projectCwd,\n rootFiles,\n compilerOptions,\n languageService,\n versions,\n }\n projectCache.set(projectCwd, state)\n return state\n}\n\nfunction isFileTypeSupportedByTypescriptBackend(filePath: string): boolean {\n const ext = extname(filePath).toLowerCase()\n return (\n ext === '.ts' ||\n ext === '.tsx' ||\n ext === '.js' ||\n ext === '.jsx' ||\n ext === '.mts' ||\n ext === '.cts' ||\n ext === '.mjs' ||\n ext === '.cjs'\n )\n}\n\nfunction summarizeToolResult(\n operation: Operation,\n resultCount: number,\n fileCount: number,\n) {\n const label = OPERATION_LABELS[operation] ?? {\n singular: 'result',\n plural: 'results',\n }\n const noun = resultCount === 1 ? label.singular : label.plural\n if (operation === 'hover' && resultCount > 0 && label.special) {\n return <Text>Hover info {label.special}</Text>\n }\n return (\n <Text>\n Found <Text bold>{resultCount}</Text> {noun}\n {fileCount > 1 ? (\n <>\n {' '}\n across <Text bold>{fileCount}</Text> files\n </>\n ) : null}\n </Text>\n )\n}\n\nexport const LspTool = {\n name: TOOL_NAME_FOR_PROMPT,\n async description() {\n return DESCRIPTION\n },\n async prompt() {\n return PROMPT\n },\n inputSchema,\n userFacingName() {\n return 'LSP'\n },\n async isEnabled() {\n return tryLoadTypeScriptModule(getCwd()) !== null\n },\n isReadOnly() {\n return true\n },\n isConcurrencySafe() {\n return true\n },\n needsPermissions({ filePath }: Input) {\n // LSP operations are read-only, but we check if file exists\n const abs = getAbsolutePath(filePath)\n return !existsSync(abs)\n },\n async validateInput(input: Input) {\n const parsed = inputSchema.safeParse(input)\n if (!parsed.success) {\n return {\n result: false,\n message: `Invalid input: ${parsed.error.message}`,\n errorCode: 3,\n }\n }\n\n const absPath = getAbsolutePath(input.filePath)\n if (!existsSync(absPath)) {\n return {\n result: false,\n message: `File does not exist: ${input.filePath}`,\n errorCode: 1,\n }\n }\n try {\n if (!statSync(absPath).isFile()) {\n return {\n result: false,\n message: `Path is not a file: ${input.filePath}`,\n errorCode: 2,\n }\n }\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err))\n return {\n result: false,\n message: `Cannot access file: ${input.filePath}. ${e.message}`,\n errorCode: 4,\n }\n }\n\n return { result: true }\n },\n renderToolUseMessage(input: Input, { verbose }: { verbose: boolean }) {\n const abs = getAbsolutePath(input.filePath)\n const filePathForDisplay = verbose ? abs : toProjectRelativeIfPossible(abs)\n const parts: string[] = []\n\n parts.push(`operation: \"${input.operation}\"`)\n if (input.filePath) parts.push(`file: \"${filePathForDisplay}\"`)\n if (input.line && input.character) {\n parts.push(`position: ${input.line}:${input.character}`)\n }\n return parts.join(', ')\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(output: Output, { verbose }: { verbose: boolean }) {\n if (!output) {\n return (\n <Box paddingLeft={2}>\n <Text>LSP operation completed</Text>\n </Box>\n )\n }\n\n if (output.resultCount !== undefined && output.fileCount !== undefined) {\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n {summarizeToolResult(\n output.operation,\n output.resultCount,\n output.fileCount,\n )}\n </Box>\n {verbose ? (\n <Box marginLeft={5}>\n <Text>{output.result}</Text>\n </Box>\n ) : null}\n </Box>\n )\n }\n\n return (\n <Box justifyContent=\"space-between\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text>{output.result}</Text>\n </Box>\n </Box>\n )\n },\n renderResultForAssistant(output: Output) {\n return output?.result ?? 'LSP operation completed'\n },\n async *call(input: Input, _context: ToolUseContext) {\n const absPath = getAbsolutePath(input.filePath)\n\n if (!isFileTypeSupportedByTypescriptBackend(absPath)) {\n const ext = extname(absPath)\n const out: Output = {\n operation: input.operation,\n result: `No LSP server available for file type: ${ext}`,\n filePath: input.filePath,\n resultCount: 0,\n fileCount: 0,\n }\n yield { type: 'result', data: out, resultForAssistant: out.result }\n return\n }\n\n const project = getOrCreateTsProject(getCwd())\n if (!project) {\n const out: Output = {\n operation: input.operation,\n result:\n 'TypeScript not found in project. Install typescript to use LSP features: npm install typescript',\n filePath: input.filePath,\n resultCount: 0,\n fileCount: 0,\n }\n yield { type: 'result', data: out, resultForAssistant: out.result }\n return\n }\n\n project.rootFiles.add(absPath)\n\n const ts = project.ts\n const service = project.languageService\n const program = service.getProgram?.()\n if (!program) {\n const out: Output = {\n operation: input.operation,\n result: `Error performing ${input.operation}: TypeScript program not available`,\n filePath: input.filePath,\n resultCount: 0,\n fileCount: 0,\n }\n yield { type: 'result', data: out, resultForAssistant: out.result }\n return\n }\n\n const sourceFile = program.getSourceFile(absPath)\n if (!sourceFile) {\n const out: Output = {\n operation: input.operation,\n result: `Error performing ${input.operation}: File is not part of the TypeScript program`,\n filePath: input.filePath,\n resultCount: 0,\n fileCount: 0,\n }\n yield { type: 'result', data: out, resultForAssistant: out.result }\n return\n }\n\n const pos = ts.getPositionOfLineAndCharacter(\n sourceFile,\n input.line - 1,\n input.character - 1,\n )\n\n try {\n let formatted: string\n let resultCount = 0\n let fileCount = 0\n\n switch (input.operation) {\n case 'goToDefinition': {\n const defs = service.getDefinitionAtPosition?.(absPath, pos) ?? []\n const locations = defs\n .map((d: any) => {\n const defSourceFile = program.getSourceFile(d.fileName)\n if (!defSourceFile) return null\n const lc = ts.getLineAndCharacterOfPosition(\n defSourceFile,\n d.textSpan.start,\n )\n return {\n fileName: d.fileName,\n line0: lc.line,\n character0: lc.character,\n }\n })\n .filter(Boolean) as Array<{\n fileName: string\n line0: number\n character0: number\n }>\n const res = formatGoToDefinitionResult(locations)\n formatted = res.formatted\n resultCount = res.resultCount\n fileCount = res.fileCount\n break\n }\n case 'goToImplementation': {\n const impls =\n service.getImplementationAtPosition?.(absPath, pos) ?? []\n const locations = impls\n .map((d: any) => {\n const defSourceFile = program.getSourceFile(d.fileName)\n if (!defSourceFile) return null\n const lc = ts.getLineAndCharacterOfPosition(\n defSourceFile,\n d.textSpan.start,\n )\n return {\n fileName: d.fileName,\n line0: lc.line,\n character0: lc.character,\n }\n })\n .filter(Boolean) as Array<{\n fileName: string\n line0: number\n character0: number\n }>\n const res = formatGoToDefinitionResult(locations)\n formatted = res.formatted\n resultCount = res.resultCount\n fileCount = res.fileCount\n break\n }\n case 'findReferences': {\n const referencedSymbols = service.findReferences?.(absPath, pos) ?? []\n const refs: Array<{\n fileName: string\n line0: number\n character0: number\n }> = []\n for (const sym of referencedSymbols) {\n for (const ref of sym.references ?? []) {\n const refSource = program.getSourceFile(ref.fileName)\n if (!refSource) continue\n const lc = ts.getLineAndCharacterOfPosition(\n refSource,\n ref.textSpan.start,\n )\n refs.push({\n fileName: ref.fileName,\n line0: lc.line,\n character0: lc.character,\n })\n }\n }\n const res = formatFindReferencesResult(refs)\n formatted = res.formatted\n resultCount = res.resultCount\n fileCount = res.fileCount\n break\n }\n case 'hover': {\n const info = service.getQuickInfoAtPosition?.(absPath, pos)\n let text: string | null = null\n let hoverLine0 = input.line - 1\n let hoverCharacter0 = input.character - 1\n if (info) {\n const parts: string[] = []\n const signature = ts.displayPartsToString(info.displayParts ?? [])\n if (signature) parts.push(signature)\n const doc = ts.displayPartsToString(info.documentation ?? [])\n if (doc) parts.push(doc)\n if (info.tags && info.tags.length > 0) {\n for (const tag of info.tags) {\n const tagText = ts.displayPartsToString(tag.text ?? [])\n parts.push(`@${tag.name}${tagText ? ` ${tagText}` : ''}`)\n }\n }\n text = parts.filter(Boolean).join('\\n\\n')\n const lc = ts.getLineAndCharacterOfPosition(\n sourceFile,\n info.textSpan.start,\n )\n hoverLine0 = lc.line\n hoverCharacter0 = lc.character\n }\n const res = formatHoverResult(text, hoverLine0, hoverCharacter0)\n formatted = res.formatted\n resultCount = res.resultCount\n fileCount = res.fileCount\n break\n }\n case 'documentSymbol': {\n const tree = service.getNavigationTree?.(absPath)\n const lines: string[] = []\n let count = 0\n\n const kindLabel = (kind: string) => {\n const m = {\n class: 'Class',\n interface: 'Interface',\n enum: 'Enum',\n function: 'Function',\n method: 'Method',\n property: 'Property',\n var: 'Variable',\n let: 'Variable',\n const: 'Constant',\n module: 'Module',\n alias: 'Alias',\n type: 'Type',\n } as Record<string, string>\n return (\n m[kind] ??\n (kind ? kind[0].toUpperCase() + kind.slice(1) : 'Unknown')\n )\n }\n\n const walk = (node: any, depth: number) => {\n const children: any[] = node?.childItems ?? []\n for (const child of children) {\n const span = child.spans?.[0]\n if (!span) continue\n const lc = ts.getLineAndCharacterOfPosition(\n sourceFile,\n span.start,\n )\n const indent = ' '.repeat(depth)\n const label = kindLabel(child.kind)\n const detail = child.kindModifiers\n ? ` ${child.kindModifiers}`\n : ''\n lines.push(\n `${indent}${child.text} (${label})${detail} - Line ${lc.line + 1}`,\n )\n count += 1\n if (child.childItems && child.childItems.length > 0) {\n walk(child, depth + 1)\n }\n }\n }\n walk(tree, 0)\n\n const res = formatDocumentSymbolsResult(lines, count)\n formatted = res.formatted\n resultCount = res.resultCount\n fileCount = res.fileCount\n break\n }\n case 'workspaceSymbol': {\n const items =\n service.getNavigateToItems?.('', 100, undefined, true, true) ?? []\n if (!items || items.length === 0) {\n formatted =\n 'No symbols found in workspace. This may occur if the workspace is empty, or if the LSP server has not finished indexing the project.'\n resultCount = 0\n fileCount = 0\n break\n }\n\n const lines: string[] = [\n `Found ${items.length} symbol${items.length === 1 ? '' : 's'} in workspace:`,\n ]\n const grouped = groupLocationsByFile(\n items.map((it: any) => ({\n fileName: it.fileName,\n item: it,\n })),\n )\n for (const [file, itemsInFile] of grouped) {\n lines.push(`\\n${file}:`)\n for (const wrapper of itemsInFile) {\n const it: any = (wrapper as any).item\n const sf = program.getSourceFile(it.fileName)\n if (!sf) continue\n const span = it.textSpan\n const lc = span\n ? ts.getLineAndCharacterOfPosition(sf, span.start)\n : { line: 0, character: 0 }\n const label = it.kind\n ? String(it.kind)[0].toUpperCase() + String(it.kind).slice(1)\n : 'Symbol'\n let line = ` ${it.name} (${label}) - Line ${lc.line + 1}`\n if (it.containerName) line += ` in ${it.containerName}`\n lines.push(line)\n }\n }\n formatted = lines.join('\\n')\n resultCount = items.length\n fileCount = grouped.size\n break\n }\n case 'prepareCallHierarchy':\n case 'incomingCalls':\n case 'outgoingCalls': {\n const opLabel = input.operation\n formatted = `Error performing ${opLabel}: Call hierarchy is not supported by the TypeScript backend`\n resultCount = 0\n fileCount = 0\n break\n }\n default: {\n formatted = `Error performing ${input.operation}: Unsupported operation`\n resultCount = 0\n fileCount = 0\n }\n }\n\n const out: Output = {\n operation: input.operation,\n result: formatted,\n filePath: input.filePath,\n resultCount,\n fileCount,\n }\n yield { type: 'result', data: out, resultForAssistant: out.result }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n const out: Output = {\n operation: input.operation,\n result: `Error performing ${input.operation}: ${message}`,\n filePath: input.filePath,\n }\n yield { type: 'result', data: out, resultForAssistant: out.result }\n }\n },\n} satisfies Tool<typeof inputSchema, Output>\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,27 @@
1
+ const TOOL_NAME_FOR_PROMPT = "LSP";
2
+ const PROMPT = `Interact with Language Server Protocol (LSP) servers to get code intelligence features.
3
+
4
+ Supported operations:
5
+ - goToDefinition: Find where a symbol is defined
6
+ - findReferences: Find all references to a symbol
7
+ - hover: Get hover information (documentation, type info) for a symbol
8
+ - documentSymbol: Get all symbols (functions, classes, variables) in a document
9
+ - workspaceSymbol: Search for symbols across the entire workspace
10
+ - goToImplementation: Find implementations of an interface or abstract method
11
+ - prepareCallHierarchy: Get call hierarchy item at a position (functions/methods)
12
+ - incomingCalls: Find all functions/methods that call the function at a position
13
+ - outgoingCalls: Find all functions/methods called by the function at a position
14
+
15
+ All operations require:
16
+ - filePath: The file to operate on
17
+ - line: The line number (1-based, as shown in editors)
18
+ - character: The character offset (1-based, as shown in editors)
19
+
20
+ Note: LSP servers must be configured for the file type. If no server is available, an error will be returned.`;
21
+ const DESCRIPTION = PROMPT;
22
+ export {
23
+ DESCRIPTION,
24
+ PROMPT,
25
+ TOOL_NAME_FOR_PROMPT
26
+ };
27
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/tools/LspTool/prompt.ts"],
4
+ "sourcesContent": ["export const TOOL_NAME_FOR_PROMPT = 'LSP'\n\nexport const PROMPT = `Interact with Language Server Protocol (LSP) servers to get code intelligence features.\n\nSupported operations:\n- goToDefinition: Find where a symbol is defined\n- findReferences: Find all references to a symbol\n- hover: Get hover information (documentation, type info) for a symbol\n- documentSymbol: Get all symbols (functions, classes, variables) in a document\n- workspaceSymbol: Search for symbols across the entire workspace\n- goToImplementation: Find implementations of an interface or abstract method\n- prepareCallHierarchy: Get call hierarchy item at a position (functions/methods)\n- incomingCalls: Find all functions/methods that call the function at a position\n- outgoingCalls: Find all functions/methods called by the function at a position\n\nAll operations require:\n- filePath: The file to operate on\n- line: The line number (1-based, as shown in editors)\n- character: The character offset (1-based, as shown in editors)\n\nNote: LSP servers must be configured for the file type. If no server is available, an error will be returned.`\n\nexport const DESCRIPTION = PROMPT\n"],
5
+ "mappings": "AAAO,MAAM,uBAAuB;AAE7B,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBf,MAAM,cAAc;",
6
+ "names": []
7
+ }
@@ -48,8 +48,14 @@ const MCPTool = {
48
48
  },
49
49
  renderToolResultMessage(output) {
50
50
  const verbose = false;
51
+ if (!output) {
52
+ return /* @__PURE__ */ React.createElement(Box, { justifyContent: "space-between", overflowX: "hidden", width: "100%" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React.createElement(Text, { color: getTheme().secondaryText }, "(No content)")));
53
+ }
51
54
  if (Array.isArray(output)) {
52
55
  return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, output.map((item, i) => {
56
+ if (!item) {
57
+ return null;
58
+ }
53
59
  if (item.type === "image") {
54
60
  return /* @__PURE__ */ React.createElement(
55
61
  Box,
@@ -62,20 +68,21 @@ const MCPTool = {
62
68
  /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React.createElement(Text, null, "[Image]"))
63
69
  );
64
70
  }
65
- const lines2 = item.text.split("\n").length;
71
+ const text = item.text || "";
72
+ const lines2 = text.split("\n").length;
66
73
  return /* @__PURE__ */ React.createElement(
67
74
  OutputLine,
68
75
  {
69
76
  key: i,
70
- content: item.text,
77
+ content: text,
71
78
  lines: lines2,
72
79
  verbose
73
80
  }
74
81
  );
75
82
  }));
76
83
  }
77
- if (!output) {
78
- return /* @__PURE__ */ React.createElement(Box, { justifyContent: "space-between", overflowX: "hidden", width: "100%" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React.createElement(Text, { color: getTheme().secondaryText }, "(No content)")));
84
+ if (typeof output !== "string") {
85
+ return /* @__PURE__ */ React.createElement(Box, { justifyContent: "space-between", overflowX: "hidden", width: "100%" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React.createElement(Text, { color: getTheme().secondaryText }, "MCP operation completed")));
79
86
  }
80
87
  const lines = output.split("\n").length;
81
88
  return /* @__PURE__ */ React.createElement(OutputLine, { content: output, lines, verbose });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/tools/MCPTool/MCPTool.tsx"],
4
- "sourcesContent": ["import { Box, Text } from 'ink'\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport { type Tool } from '@tool'\nimport { getTheme } from '@utils/theme'\nimport { DESCRIPTION, PROMPT } from './prompt'\nimport { OutputLine } from '@tools/BashTool/OutputLine'\n\n// Allow any input object since MCP tools define their own schemas\nconst inputSchema = z.object({}).passthrough()\n\nexport const MCPTool = {\n async isEnabled() {\n return true\n },\n isReadOnly() {\n return false\n },\n isConcurrencySafe() {\n return false // MCPTool can modify state through MCP calls, not safe for concurrent execution\n },\n // Overridden in mcpClient.ts\n name: 'mcp',\n // Overridden in mcpClient.ts\n async description() {\n return DESCRIPTION\n },\n // Overridden in mcpClient.ts\n async prompt() {\n return PROMPT\n },\n inputSchema,\n // Overridden in mcpClient.ts\n async *call() {\n yield {\n type: 'result',\n data: '',\n resultForAssistant: '',\n }\n },\n needsPermissions() {\n return true\n },\n renderToolUseMessage(input) {\n return Object.entries(input)\n .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)\n .join(', ')\n },\n // Overridden in mcpClient.ts\n userFacingName: () => 'mcp',\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(output) {\n const verbose = false // Set default value for verbose\n if (Array.isArray(output)) {\n return (\n <Box flexDirection=\"column\">\n {output.map((item, i) => {\n if (item.type === 'image') {\n return (\n <Box\n key={i}\n justifyContent=\"space-between\"\n overflowX=\"hidden\"\n width=\"100%\"\n >\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text>[Image]</Text>\n </Box>\n </Box>\n )\n }\n const lines = item.text.split('\\n').length\n return (\n <OutputLine\n key={i}\n content={item.text}\n lines={lines}\n verbose={verbose}\n />\n )\n })}\n </Box>\n )\n }\n\n if (!output) {\n return (\n <Box justifyContent=\"space-between\" overflowX=\"hidden\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text color={getTheme().secondaryText}>(No content)</Text>\n </Box>\n </Box>\n )\n }\n\n const lines = output.split('\\n').length\n return <OutputLine content={output} lines={lines} verbose={verbose} />\n },\n renderResultForAssistant(content) {\n return content\n },\n} satisfies Tool<typeof inputSchema, string>\n"],
5
- "mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,YAAY,WAAW;AACvB,SAAS,SAAS;AAClB,SAAS,sCAAsC;AAE/C,SAAS,gBAAgB;AACzB,SAAS,aAAa,cAAc;AACpC,SAAS,kBAAkB;AAG3B,MAAM,cAAc,EAAE,OAAO,CAAC,CAAC,EAAE,YAAY;AAEtC,MAAM,UAAU;AAAA,EACrB,MAAM,YAAY;AAChB,WAAO;AAAA,EACT;AAAA,EACA,aAAa;AACX,WAAO;AAAA,EACT;AAAA,EACA,oBAAoB;AAClB,WAAO;AAAA,EACT;AAAA;AAAA,EAEA,MAAM;AAAA;AAAA,EAEN,MAAM,cAAc;AAClB,WAAO;AAAA,EACT;AAAA;AAAA,EAEA,MAAM,SAAS;AACb,WAAO;AAAA,EACT;AAAA,EACA;AAAA;AAAA,EAEA,OAAO,OAAO;AACZ,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,oBAAoB;AAAA,IACtB;AAAA,EACF;AAAA,EACA,mBAAmB;AACjB,WAAO;AAAA,EACT;AAAA,EACA,qBAAqB,OAAO;AAC1B,WAAO,OAAO,QAAQ,KAAK,EACxB,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,GAAG,GAAG,KAAK,KAAK,UAAU,KAAK,CAAC,EAAE,EACxD,KAAK,IAAI;AAAA,EACd;AAAA;AAAA,EAEA,gBAAgB,MAAM;AAAA,EACtB,+BAA+B;AAC7B,WAAO,oCAAC,oCAA+B;AAAA,EACzC;AAAA,EACA,wBAAwB,QAAQ;AAC9B,UAAM,UAAU;AAChB,QAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,aACE,oCAAC,OAAI,eAAc,YAChB,OAAO,IAAI,CAAC,MAAM,MAAM;AACvB,YAAI,KAAK,SAAS,SAAS;AACzB,iBACE;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,gBAAe;AAAA,cACf,WAAU;AAAA,cACV,OAAM;AAAA;AAAA,YAEN,oCAAC,OAAI,eAAc,SACjB,oCAAC,YAAK,qBAAoB,GAC1B,oCAAC,YAAK,SAAO,CACf;AAAA,UACF;AAAA,QAEJ;AACA,cAAMA,SAAQ,KAAK,KAAK,MAAM,IAAI,EAAE;AACpC,eACE;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,SAAS,KAAK;AAAA,YACd,OAAOA;AAAA,YACP;AAAA;AAAA,QACF;AAAA,MAEJ,CAAC,CACH;AAAA,IAEJ;AAEA,QAAI,CAAC,QAAQ;AACX,aACE,oCAAC,OAAI,gBAAe,iBAAgB,WAAU,UAAS,OAAM,UAC3D,oCAAC,OAAI,eAAc,SACjB,oCAAC,YAAK,qBAAoB,GAC1B,oCAAC,QAAK,OAAO,SAAS,EAAE,iBAAe,cAAY,CACrD,CACF;AAAA,IAEJ;AAEA,UAAM,QAAQ,OAAO,MAAM,IAAI,EAAE;AACjC,WAAO,oCAAC,cAAW,SAAS,QAAQ,OAAc,SAAkB;AAAA,EACtE;AAAA,EACA,yBAAyB,SAAS;AAChC,WAAO;AAAA,EACT;AACF;",
4
+ "sourcesContent": ["import { Box, Text } from 'ink'\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport { type Tool } from '@tool'\nimport { getTheme } from '@utils/theme'\nimport { DESCRIPTION, PROMPT } from './prompt'\nimport { OutputLine } from '@tools/BashTool/OutputLine'\n\n// Allow any input object since MCP tools define their own schemas\nconst inputSchema = z.object({}).passthrough()\n\nexport const MCPTool = {\n async isEnabled() {\n return true\n },\n isReadOnly() {\n return false\n },\n isConcurrencySafe() {\n return false // MCPTool can modify state through MCP calls, not safe for concurrent execution\n },\n // Overridden in mcpClient.ts\n name: 'mcp',\n // Overridden in mcpClient.ts\n async description() {\n return DESCRIPTION\n },\n // Overridden in mcpClient.ts\n async prompt() {\n return PROMPT\n },\n inputSchema,\n // Overridden in mcpClient.ts\n async *call() {\n yield {\n type: 'result',\n data: '',\n resultForAssistant: '',\n }\n },\n needsPermissions() {\n return true\n },\n renderToolUseMessage(input) {\n return Object.entries(input)\n .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)\n .join(', ')\n },\n // Overridden in mcpClient.ts\n userFacingName: () => 'mcp',\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(output) {\n const verbose = false // Set default value for verbose\n\n // Guard against undefined or null output\n if (!output) {\n return (\n <Box justifyContent=\"space-between\" overflowX=\"hidden\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text color={getTheme().secondaryText}>(No content)</Text>\n </Box>\n </Box>\n )\n }\n\n if (Array.isArray(output)) {\n return (\n <Box flexDirection=\"column\">\n {output.map((item, i) => {\n // Guard against null/undefined items in array\n if (!item) {\n return null\n }\n if (item.type === 'image') {\n return (\n <Box\n key={i}\n justifyContent=\"space-between\"\n overflowX=\"hidden\"\n width=\"100%\"\n >\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text>[Image]</Text>\n </Box>\n </Box>\n )\n }\n // Guard against missing text property\n const text = item.text || ''\n const lines = text.split('\\n').length\n return (\n <OutputLine\n key={i}\n content={text}\n lines={lines}\n verbose={verbose}\n />\n )\n })}\n </Box>\n )\n }\n\n // Guard against non-string output\n if (typeof output !== 'string') {\n return (\n <Box justifyContent=\"space-between\" overflowX=\"hidden\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text color={getTheme().secondaryText}>\n MCP operation completed\n </Text>\n </Box>\n </Box>\n )\n }\n\n const lines = output.split('\\n').length\n return <OutputLine content={output} lines={lines} verbose={verbose} />\n },\n renderResultForAssistant(content) {\n return content\n },\n} satisfies Tool<typeof inputSchema, string>\n"],
5
+ "mappings": "AAAA,SAAS,KAAK,YAAY;AAC1B,YAAY,WAAW;AACvB,SAAS,SAAS;AAClB,SAAS,sCAAsC;AAE/C,SAAS,gBAAgB;AACzB,SAAS,aAAa,cAAc;AACpC,SAAS,kBAAkB;AAG3B,MAAM,cAAc,EAAE,OAAO,CAAC,CAAC,EAAE,YAAY;AAEtC,MAAM,UAAU;AAAA,EACrB,MAAM,YAAY;AAChB,WAAO;AAAA,EACT;AAAA,EACA,aAAa;AACX,WAAO;AAAA,EACT;AAAA,EACA,oBAAoB;AAClB,WAAO;AAAA,EACT;AAAA;AAAA,EAEA,MAAM;AAAA;AAAA,EAEN,MAAM,cAAc;AAClB,WAAO;AAAA,EACT;AAAA;AAAA,EAEA,MAAM,SAAS;AACb,WAAO;AAAA,EACT;AAAA,EACA;AAAA;AAAA,EAEA,OAAO,OAAO;AACZ,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,oBAAoB;AAAA,IACtB;AAAA,EACF;AAAA,EACA,mBAAmB;AACjB,WAAO;AAAA,EACT;AAAA,EACA,qBAAqB,OAAO;AAC1B,WAAO,OAAO,QAAQ,KAAK,EACxB,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,GAAG,GAAG,KAAK,KAAK,UAAU,KAAK,CAAC,EAAE,EACxD,KAAK,IAAI;AAAA,EACd;AAAA;AAAA,EAEA,gBAAgB,MAAM;AAAA,EACtB,+BAA+B;AAC7B,WAAO,oCAAC,oCAA+B;AAAA,EACzC;AAAA,EACA,wBAAwB,QAAQ;AAC9B,UAAM,UAAU;AAGhB,QAAI,CAAC,QAAQ;AACX,aACE,oCAAC,OAAI,gBAAe,iBAAgB,WAAU,UAAS,OAAM,UAC3D,oCAAC,OAAI,eAAc,SACjB,oCAAC,YAAK,qBAAoB,GAC1B,oCAAC,QAAK,OAAO,SAAS,EAAE,iBAAe,cAAY,CACrD,CACF;AAAA,IAEJ;AAEA,QAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,aACE,oCAAC,OAAI,eAAc,YAChB,OAAO,IAAI,CAAC,MAAM,MAAM;AAEvB,YAAI,CAAC,MAAM;AACT,iBAAO;AAAA,QACT;AACA,YAAI,KAAK,SAAS,SAAS;AACzB,iBACE;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,gBAAe;AAAA,cACf,WAAU;AAAA,cACV,OAAM;AAAA;AAAA,YAEN,oCAAC,OAAI,eAAc,SACjB,oCAAC,YAAK,qBAAoB,GAC1B,oCAAC,YAAK,SAAO,CACf;AAAA,UACF;AAAA,QAEJ;AAEA,cAAM,OAAO,KAAK,QAAQ;AAC1B,cAAMA,SAAQ,KAAK,MAAM,IAAI,EAAE;AAC/B,eACE;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,SAAS;AAAA,YACT,OAAOA;AAAA,YACP;AAAA;AAAA,QACF;AAAA,MAEJ,CAAC,CACH;AAAA,IAEJ;AAGA,QAAI,OAAO,WAAW,UAAU;AAC9B,aACE,oCAAC,OAAI,gBAAe,iBAAgB,WAAU,UAAS,OAAM,UAC3D,oCAAC,OAAI,eAAc,SACjB,oCAAC,YAAK,qBAAoB,GAC1B,oCAAC,QAAK,OAAO,SAAS,EAAE,iBAAe,yBAEvC,CACF,CACF;AAAA,IAEJ;AAEA,UAAM,QAAQ,OAAO,MAAM,IAAI,EAAE;AACjC,WAAO,oCAAC,cAAW,SAAS,QAAQ,OAAc,SAAkB;AAAA,EACtE;AAAA,EACA,yBAAyB,SAAS;AAChC,WAAO;AAAA,EACT;AACF;",
6
6
  "names": ["lines"]
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync } from "fs";
2
2
  import { Box, Text } from "ink";
3
- import { join } from "path";
3
+ import { join, resolve } from "path";
4
4
  import * as React from "react";
5
5
  import { z } from "zod";
6
6
  import { FallbackToolUseRejectedMessage } from "../../components/FallbackToolUseRejectedMessage.js";
@@ -44,28 +44,41 @@ const MemoryReadTool = {
44
44
  return /* @__PURE__ */ React.createElement(FallbackToolUseRejectedMessage, null);
45
45
  },
46
46
  renderToolResultMessage(output) {
47
+ if (!output) {
48
+ return /* @__PURE__ */ React.createElement(Box, { justifyContent: "space-between", overflowX: "hidden", width: "100%" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React.createElement(Text, null, "(No memory content)")));
49
+ }
47
50
  return /* @__PURE__ */ React.createElement(Box, { justifyContent: "space-between", overflowX: "hidden", width: "100%" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React.createElement(Text, null, output.content)));
48
51
  },
49
52
  async validateInput({ file_path }, context) {
50
53
  const agentId = resolveAgentId(context?.agentId);
51
- const agentMemoryDir = join(MEMORY_DIR, "agents", agentId);
54
+ const agentMemoryDir = resolve(MEMORY_DIR, "agents", agentId);
52
55
  if (file_path) {
53
- const fullPath = join(agentMemoryDir, file_path);
54
- if (!fullPath.startsWith(agentMemoryDir)) {
56
+ const fullPath = resolve(agentMemoryDir, file_path);
57
+ if (!fullPath.startsWith(agentMemoryDir + "/") && fullPath !== agentMemoryDir) {
55
58
  return { result: false, message: "Invalid memory file path" };
56
59
  }
57
60
  if (!existsSync(fullPath)) {
58
61
  return { result: false, message: "Memory file does not exist" };
59
62
  }
63
+ try {
64
+ const stat = lstatSync(fullPath);
65
+ if (stat.isSymbolicLink()) {
66
+ return {
67
+ result: false,
68
+ message: "Symbolic links are not allowed in memory paths"
69
+ };
70
+ }
71
+ } catch {
72
+ }
60
73
  }
61
74
  return { result: true };
62
75
  },
63
76
  async *call({ file_path }, context) {
64
77
  const agentId = resolveAgentId(context?.agentId);
65
- const agentMemoryDir = join(MEMORY_DIR, "agents", agentId);
78
+ const agentMemoryDir = resolve(MEMORY_DIR, "agents", agentId);
66
79
  mkdirSync(agentMemoryDir, { recursive: true });
67
80
  if (file_path) {
68
- const fullPath = join(agentMemoryDir, file_path);
81
+ const fullPath = resolve(agentMemoryDir, file_path);
69
82
  if (!existsSync(fullPath)) {
70
83
  throw new Error("Memory file does not exist");
71
84
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/tools/MemoryReadTool/MemoryReadTool.tsx"],
4
- "sourcesContent": ["import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync } from 'fs'\nimport { Box, Text } from 'ink'\nimport { join } from 'path'\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport { Tool } from '@tool'\nimport { MEMORY_DIR } from '@utils/env'\nimport { resolveAgentId } from '@utils/agentStorage'\nimport { DESCRIPTION, PROMPT } from './prompt'\n\nconst inputSchema = z.strictObject({\n file_path: z\n .string()\n .optional()\n .describe('Optional path to a specific memory file to read'),\n})\n\nexport const MemoryReadTool = {\n name: 'MemoryRead',\n async description() {\n return DESCRIPTION\n },\n async prompt() {\n return PROMPT\n },\n inputSchema,\n userFacingName() {\n return 'Read Memory'\n },\n async isEnabled() {\n // TODO: Gate with a setting or feature flag\n return false\n },\n isReadOnly() {\n return true\n },\n isConcurrencySafe() {\n return true // MemoryRead is read-only, safe for concurrent execution\n },\n needsPermissions() {\n return false\n },\n renderResultForAssistant({ content }) {\n return content\n },\n renderToolUseMessage(input) {\n return Object.entries(input)\n .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)\n .join(', ')\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(output) {\n return (\n <Box justifyContent=\"space-between\" overflowX=\"hidden\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text>{output.content}</Text>\n </Box>\n </Box>\n )\n },\n async validateInput({ file_path }, context) {\n const agentId = resolveAgentId(context?.agentId)\n const agentMemoryDir = join(MEMORY_DIR, 'agents', agentId)\n\n if (file_path) {\n const fullPath = join(agentMemoryDir, file_path)\n if (!fullPath.startsWith(agentMemoryDir)) {\n return { result: false, message: 'Invalid memory file path' }\n }\n if (!existsSync(fullPath)) {\n return { result: false, message: 'Memory file does not exist' }\n }\n }\n return { result: true }\n },\n async *call({ file_path }, context) {\n const agentId = resolveAgentId(context?.agentId)\n const agentMemoryDir = join(MEMORY_DIR, 'agents', agentId)\n mkdirSync(agentMemoryDir, { recursive: true })\n\n // If a specific file is requested, return its contents\n if (file_path) {\n const fullPath = join(agentMemoryDir, file_path)\n if (!existsSync(fullPath)) {\n throw new Error('Memory file does not exist')\n }\n const content = readFileSync(fullPath, 'utf-8')\n yield {\n type: 'result',\n data: {\n content,\n },\n resultForAssistant: this.renderResultForAssistant({ content }),\n }\n return\n }\n\n // Otherwise return the index and file list for this agent\n const files = readdirSync(agentMemoryDir, { recursive: true })\n .map(f => join(agentMemoryDir, f.toString()))\n .filter(f => !lstatSync(f).isDirectory())\n .map(f => `- ${f}`)\n .join('\\n')\n\n const indexPath = join(agentMemoryDir, 'index.md')\n const index = existsSync(indexPath) ? readFileSync(indexPath, 'utf-8') : ''\n\n const quotes = \"'''\"\n const content = `Here are the contents of the agent memory file, \\`${indexPath}\\`:\n${quotes}\n${index}\n${quotes}\n\nFiles in the agent memory directory:\n${files}`\n yield {\n type: 'result',\n data: { content },\n resultForAssistant: this.renderResultForAssistant({ content }),\n }\n },\n} satisfies Tool<typeof inputSchema, { content: string }>\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync } from 'fs'\nimport { Box, Text } from 'ink'\nimport { join, resolve } from 'path'\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport { Tool } from '@tool'\nimport { MEMORY_DIR } from '@utils/env'\nimport { resolveAgentId } from '@utils/agentStorage'\nimport { DESCRIPTION, PROMPT } from './prompt'\n\nconst inputSchema = z.strictObject({\n file_path: z\n .string()\n .optional()\n .describe('Optional path to a specific memory file to read'),\n})\n\nexport const MemoryReadTool = {\n name: 'MemoryRead',\n async description() {\n return DESCRIPTION\n },\n async prompt() {\n return PROMPT\n },\n inputSchema,\n userFacingName() {\n return 'Read Memory'\n },\n async isEnabled() {\n // Memory tools are currently disabled pending:\n // 1. User-facing configuration UI for enabling/disabling\n // 2. Security review of path traversal handling\n // 3. Documentation of memory storage format and lifecycle\n // These tools are for agent-level persistent memory across sessions\n return false\n },\n isReadOnly() {\n return true\n },\n isConcurrencySafe() {\n return true // MemoryRead is read-only, safe for concurrent execution\n },\n needsPermissions() {\n return false\n },\n renderResultForAssistant({ content }) {\n return content\n },\n renderToolUseMessage(input) {\n return Object.entries(input)\n .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)\n .join(', ')\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(output) {\n // Guard against undefined or null output\n if (!output) {\n return (\n <Box justifyContent=\"space-between\" overflowX=\"hidden\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text>(No memory content)</Text>\n </Box>\n </Box>\n )\n }\n\n return (\n <Box justifyContent=\"space-between\" overflowX=\"hidden\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text>{output.content}</Text>\n </Box>\n </Box>\n )\n },\n async validateInput({ file_path }, context) {\n const agentId = resolveAgentId(context?.agentId)\n const agentMemoryDir = resolve(MEMORY_DIR, 'agents', agentId)\n\n if (file_path) {\n // Use resolve() to normalize paths and prevent path traversal attacks\n // join() alone doesn't protect against \"../\" sequences\n const fullPath = resolve(agentMemoryDir, file_path)\n if (\n !fullPath.startsWith(agentMemoryDir + '/') &&\n fullPath !== agentMemoryDir\n ) {\n return { result: false, message: 'Invalid memory file path' }\n }\n if (!existsSync(fullPath)) {\n return { result: false, message: 'Memory file does not exist' }\n }\n // Check for symlinks that could escape the directory\n try {\n const stat = lstatSync(fullPath)\n if (stat.isSymbolicLink()) {\n return {\n result: false,\n message: 'Symbolic links are not allowed in memory paths',\n }\n }\n } catch {\n // File doesn't exist or can't be accessed, will be caught above\n }\n }\n return { result: true }\n },\n async *call({ file_path }, context) {\n const agentId = resolveAgentId(context?.agentId)\n const agentMemoryDir = resolve(MEMORY_DIR, 'agents', agentId)\n mkdirSync(agentMemoryDir, { recursive: true })\n\n // If a specific file is requested, return its contents\n if (file_path) {\n const fullPath = resolve(agentMemoryDir, file_path)\n if (!existsSync(fullPath)) {\n throw new Error('Memory file does not exist')\n }\n const content = readFileSync(fullPath, 'utf-8')\n yield {\n type: 'result',\n data: {\n content,\n },\n resultForAssistant: this.renderResultForAssistant({ content }),\n }\n return\n }\n\n // Otherwise return the index and file list for this agent\n const files = readdirSync(agentMemoryDir, { recursive: true })\n .map(f => join(agentMemoryDir, f.toString()))\n .filter(f => !lstatSync(f).isDirectory())\n .map(f => `- ${f}`)\n .join('\\n')\n\n const indexPath = join(agentMemoryDir, 'index.md')\n const index = existsSync(indexPath) ? readFileSync(indexPath, 'utf-8') : ''\n\n const quotes = \"'''\"\n const content = `Here are the contents of the agent memory file, \\`${indexPath}\\`:\n${quotes}\n${index}\n${quotes}\n\nFiles in the agent memory directory:\n${files}`\n yield {\n type: 'result',\n data: { content },\n resultForAssistant: this.renderResultForAssistant({ content }),\n }\n },\n} satisfies Tool<typeof inputSchema, { content: string }>\n"],
5
+ "mappings": "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",
6
6
  "names": ["content"]
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import { mkdirSync, writeFileSync } from "fs";
2
2
  import { Box, Text } from "ink";
3
- import { dirname, join } from "path";
3
+ import { dirname, resolve } from "path";
4
4
  import * as React from "react";
5
5
  import { z } from "zod";
6
6
  import { FallbackToolUseRejectedMessage } from "../../components/FallbackToolUseRejectedMessage.js";
@@ -50,17 +50,17 @@ const MemoryWriteTool = {
50
50
  },
51
51
  async validateInput({ file_path }, context) {
52
52
  const agentId = resolveAgentId(context?.agentId);
53
- const agentMemoryDir = join(MEMORY_DIR, "agents", agentId);
54
- const fullPath = join(agentMemoryDir, file_path);
55
- if (!fullPath.startsWith(agentMemoryDir)) {
53
+ const agentMemoryDir = resolve(MEMORY_DIR, "agents", agentId);
54
+ const fullPath = resolve(agentMemoryDir, file_path);
55
+ if (!fullPath.startsWith(agentMemoryDir + "/") && fullPath !== agentMemoryDir) {
56
56
  return { result: false, message: "Invalid memory file path" };
57
57
  }
58
58
  return { result: true };
59
59
  },
60
60
  async *call({ file_path, content }, context) {
61
61
  const agentId = resolveAgentId(context?.agentId);
62
- const agentMemoryDir = join(MEMORY_DIR, "agents", agentId);
63
- const fullPath = join(agentMemoryDir, file_path);
62
+ const agentMemoryDir = resolve(MEMORY_DIR, "agents", agentId);
63
+ const fullPath = resolve(agentMemoryDir, file_path);
64
64
  mkdirSync(dirname(fullPath), { recursive: true });
65
65
  writeFileSync(fullPath, content, "utf-8");
66
66
  recordFileEdit(fullPath, content);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/tools/MemoryWriteTool/MemoryWriteTool.tsx"],
4
- "sourcesContent": ["import { mkdirSync, writeFileSync } from 'fs'\nimport { Box, Text } from 'ink'\nimport { dirname, join } from 'path'\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport { Tool } from '@tool'\nimport { MEMORY_DIR } from '@utils/env'\nimport { resolveAgentId } from '@utils/agentStorage'\nimport { recordFileEdit } from '@services/fileFreshness'\nimport { DESCRIPTION, PROMPT } from './prompt'\n\nconst inputSchema = z.strictObject({\n file_path: z.string().describe('Path to the memory file to write'),\n content: z.string().describe('Content to write to the file'),\n})\n\nexport const MemoryWriteTool = {\n name: 'MemoryWrite',\n async description() {\n return DESCRIPTION\n },\n async prompt() {\n return PROMPT\n },\n inputSchema,\n userFacingName() {\n return 'Write Memory'\n },\n async isEnabled() {\n // TODO: Gate with a setting or feature flag\n return false\n },\n isReadOnly() {\n return false\n },\n isConcurrencySafe() {\n return false // MemoryWrite modifies state, not safe for concurrent execution\n },\n needsPermissions() {\n return false\n },\n renderResultForAssistant(content) {\n return content\n },\n renderToolUseMessage(input) {\n return Object.entries(input)\n .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)\n .join(', ')\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage() {\n return (\n <Box justifyContent=\"space-between\" overflowX=\"hidden\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text>{' '}\u23BF Updated memory</Text>\n </Box>\n </Box>\n )\n },\n async validateInput({ file_path }, context) {\n const agentId = resolveAgentId(context?.agentId)\n const agentMemoryDir = join(MEMORY_DIR, 'agents', agentId)\n const fullPath = join(agentMemoryDir, file_path)\n if (!fullPath.startsWith(agentMemoryDir)) {\n return { result: false, message: 'Invalid memory file path' }\n }\n return { result: true }\n },\n async *call({ file_path, content }, context) {\n const agentId = resolveAgentId(context?.agentId)\n const agentMemoryDir = join(MEMORY_DIR, 'agents', agentId)\n const fullPath = join(agentMemoryDir, file_path)\n mkdirSync(dirname(fullPath), { recursive: true })\n writeFileSync(fullPath, content, 'utf-8')\n\n // Record Agent edit operation for file freshness tracking\n recordFileEdit(fullPath, content)\n\n yield {\n type: 'result',\n data: 'Saved',\n resultForAssistant: 'Saved',\n }\n },\n} satisfies Tool<typeof inputSchema, string>\n"],
5
- "mappings": "AAAA,SAAS,WAAW,qBAAqB;AACzC,SAAS,KAAK,YAAY;AAC1B,SAAS,SAAS,YAAY;AAC9B,YAAY,WAAW;AACvB,SAAS,SAAS;AAClB,SAAS,sCAAsC;AAE/C,SAAS,kBAAkB;AAC3B,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,aAAa,cAAc;AAEpC,MAAM,cAAc,EAAE,aAAa;AAAA,EACjC,WAAW,EAAE,OAAO,EAAE,SAAS,kCAAkC;AAAA,EACjE,SAAS,EAAE,OAAO,EAAE,SAAS,8BAA8B;AAC7D,CAAC;AAEM,MAAM,kBAAkB;AAAA,EAC7B,MAAM;AAAA,EACN,MAAM,cAAc;AAClB,WAAO;AAAA,EACT;AAAA,EACA,MAAM,SAAS;AACb,WAAO;AAAA,EACT;AAAA,EACA;AAAA,EACA,iBAAiB;AACf,WAAO;AAAA,EACT;AAAA,EACA,MAAM,YAAY;AAEhB,WAAO;AAAA,EACT;AAAA,EACA,aAAa;AACX,WAAO;AAAA,EACT;AAAA,EACA,oBAAoB;AAClB,WAAO;AAAA,EACT;AAAA,EACA,mBAAmB;AACjB,WAAO;AAAA,EACT;AAAA,EACA,yBAAyB,SAAS;AAChC,WAAO;AAAA,EACT;AAAA,EACA,qBAAqB,OAAO;AAC1B,WAAO,OAAO,QAAQ,KAAK,EACxB,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,GAAG,GAAG,KAAK,KAAK,UAAU,KAAK,CAAC,EAAE,EACxD,KAAK,IAAI;AAAA,EACd;AAAA,EACA,+BAA+B;AAC7B,WAAO,oCAAC,oCAA+B;AAAA,EACzC;AAAA,EACA,0BAA0B;AACxB,WACE,oCAAC,OAAI,gBAAe,iBAAgB,WAAU,UAAS,OAAM,UAC3D,oCAAC,OAAI,eAAc,SACjB,oCAAC,YAAM,MAAK,uBAAgB,CAC9B,CACF;AAAA,EAEJ;AAAA,EACA,MAAM,cAAc,EAAE,UAAU,GAAG,SAAS;AAC1C,UAAM,UAAU,eAAe,SAAS,OAAO;AAC/C,UAAM,iBAAiB,KAAK,YAAY,UAAU,OAAO;AACzD,UAAM,WAAW,KAAK,gBAAgB,SAAS;AAC/C,QAAI,CAAC,SAAS,WAAW,cAAc,GAAG;AACxC,aAAO,EAAE,QAAQ,OAAO,SAAS,2BAA2B;AAAA,IAC9D;AACA,WAAO,EAAE,QAAQ,KAAK;AAAA,EACxB;AAAA,EACA,OAAO,KAAK,EAAE,WAAW,QAAQ,GAAG,SAAS;AAC3C,UAAM,UAAU,eAAe,SAAS,OAAO;AAC/C,UAAM,iBAAiB,KAAK,YAAY,UAAU,OAAO;AACzD,UAAM,WAAW,KAAK,gBAAgB,SAAS;AAC/C,cAAU,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAChD,kBAAc,UAAU,SAAS,OAAO;AAGxC,mBAAe,UAAU,OAAO;AAEhC,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,oBAAoB;AAAA,IACtB;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import { mkdirSync, writeFileSync } from 'fs'\nimport { Box, Text } from 'ink'\nimport { dirname, join, resolve } from 'path'\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport { Tool } from '@tool'\nimport { MEMORY_DIR } from '@utils/env'\nimport { resolveAgentId } from '@utils/agentStorage'\nimport { recordFileEdit } from '@services/fileFreshness'\nimport { DESCRIPTION, PROMPT } from './prompt'\n\nconst inputSchema = z.strictObject({\n file_path: z.string().describe('Path to the memory file to write'),\n content: z.string().describe('Content to write to the file'),\n})\n\nexport const MemoryWriteTool = {\n name: 'MemoryWrite',\n async description() {\n return DESCRIPTION\n },\n async prompt() {\n return PROMPT\n },\n inputSchema,\n userFacingName() {\n return 'Write Memory'\n },\n async isEnabled() {\n // Memory tools are currently disabled pending:\n // 1. User-facing configuration UI for enabling/disabling\n // 2. Security review of path traversal handling\n // 3. Documentation of memory storage format and lifecycle\n // These tools are for agent-level persistent memory across sessions\n return false\n },\n isReadOnly() {\n return false\n },\n isConcurrencySafe() {\n return false // MemoryWrite modifies state, not safe for concurrent execution\n },\n needsPermissions() {\n return false\n },\n renderResultForAssistant(content) {\n return content\n },\n renderToolUseMessage(input) {\n return Object.entries(input)\n .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)\n .join(', ')\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage() {\n return (\n <Box justifyContent=\"space-between\" overflowX=\"hidden\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text>{' '}\u23BF Updated memory</Text>\n </Box>\n </Box>\n )\n },\n async validateInput({ file_path }, context) {\n const agentId = resolveAgentId(context?.agentId)\n const agentMemoryDir = resolve(MEMORY_DIR, 'agents', agentId)\n // Use resolve() to normalize paths and prevent path traversal attacks\n // join() alone doesn't protect against \"../\" sequences\n const fullPath = resolve(agentMemoryDir, file_path)\n if (\n !fullPath.startsWith(agentMemoryDir + '/') &&\n fullPath !== agentMemoryDir\n ) {\n return { result: false, message: 'Invalid memory file path' }\n }\n return { result: true }\n },\n async *call({ file_path, content }, context) {\n const agentId = resolveAgentId(context?.agentId)\n const agentMemoryDir = resolve(MEMORY_DIR, 'agents', agentId)\n const fullPath = resolve(agentMemoryDir, file_path)\n mkdirSync(dirname(fullPath), { recursive: true })\n writeFileSync(fullPath, content, 'utf-8')\n\n // Record Agent edit operation for file freshness tracking\n recordFileEdit(fullPath, content)\n\n yield {\n type: 'result',\n data: 'Saved',\n resultForAssistant: 'Saved',\n }\n },\n} satisfies Tool<typeof inputSchema, string>\n"],
5
+ "mappings": "AAAA,SAAS,WAAW,qBAAqB;AACzC,SAAS,KAAK,YAAY;AAC1B,SAAS,SAAe,eAAe;AACvC,YAAY,WAAW;AACvB,SAAS,SAAS;AAClB,SAAS,sCAAsC;AAE/C,SAAS,kBAAkB;AAC3B,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,aAAa,cAAc;AAEpC,MAAM,cAAc,EAAE,aAAa;AAAA,EACjC,WAAW,EAAE,OAAO,EAAE,SAAS,kCAAkC;AAAA,EACjE,SAAS,EAAE,OAAO,EAAE,SAAS,8BAA8B;AAC7D,CAAC;AAEM,MAAM,kBAAkB;AAAA,EAC7B,MAAM;AAAA,EACN,MAAM,cAAc;AAClB,WAAO;AAAA,EACT;AAAA,EACA,MAAM,SAAS;AACb,WAAO;AAAA,EACT;AAAA,EACA;AAAA,EACA,iBAAiB;AACf,WAAO;AAAA,EACT;AAAA,EACA,MAAM,YAAY;AAMhB,WAAO;AAAA,EACT;AAAA,EACA,aAAa;AACX,WAAO;AAAA,EACT;AAAA,EACA,oBAAoB;AAClB,WAAO;AAAA,EACT;AAAA,EACA,mBAAmB;AACjB,WAAO;AAAA,EACT;AAAA,EACA,yBAAyB,SAAS;AAChC,WAAO;AAAA,EACT;AAAA,EACA,qBAAqB,OAAO;AAC1B,WAAO,OAAO,QAAQ,KAAK,EACxB,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,GAAG,GAAG,KAAK,KAAK,UAAU,KAAK,CAAC,EAAE,EACxD,KAAK,IAAI;AAAA,EACd;AAAA,EACA,+BAA+B;AAC7B,WAAO,oCAAC,oCAA+B;AAAA,EACzC;AAAA,EACA,0BAA0B;AACxB,WACE,oCAAC,OAAI,gBAAe,iBAAgB,WAAU,UAAS,OAAM,UAC3D,oCAAC,OAAI,eAAc,SACjB,oCAAC,YAAM,MAAK,uBAAgB,CAC9B,CACF;AAAA,EAEJ;AAAA,EACA,MAAM,cAAc,EAAE,UAAU,GAAG,SAAS;AAC1C,UAAM,UAAU,eAAe,SAAS,OAAO;AAC/C,UAAM,iBAAiB,QAAQ,YAAY,UAAU,OAAO;AAG5D,UAAM,WAAW,QAAQ,gBAAgB,SAAS;AAClD,QACE,CAAC,SAAS,WAAW,iBAAiB,GAAG,KACzC,aAAa,gBACb;AACA,aAAO,EAAE,QAAQ,OAAO,SAAS,2BAA2B;AAAA,IAC9D;AACA,WAAO,EAAE,QAAQ,KAAK;AAAA,EACxB;AAAA,EACA,OAAO,KAAK,EAAE,WAAW,QAAQ,GAAG,SAAS;AAC3C,UAAM,UAAU,eAAe,SAAS,OAAO;AAC/C,UAAM,iBAAiB,QAAQ,YAAY,UAAU,OAAO;AAC5D,UAAM,WAAW,QAAQ,gBAAgB,SAAS;AAClD,cAAU,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAChD,kBAAc,UAAU,SAAS,OAAO;AAGxC,mBAAe,UAAU,OAAO;AAEhC,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,oBAAoB;AAAA,IACtB;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -91,7 +91,11 @@ ${editSummary}`;
91
91
  renderToolUseRejectedMessage() {
92
92
  return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: getTheme().error }, "\u26A0 Edit request rejected"));
93
93
  },
94
- renderToolResultMessage(output) {
94
+ renderToolResultMessage(output, options) {
95
+ const verbose = options?.verbose ?? false;
96
+ if (!output) {
97
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: getTheme().secondaryText }, "Multi-edit completed"));
98
+ }
95
99
  if (typeof output === "string") {
96
100
  const isError = output.includes("Error:");
97
101
  return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: isError ? getTheme().error : getTheme().success }, output));
@@ -101,7 +105,7 @@ ${editSummary}`;
101
105
  {
102
106
  filePath: output.filePath,
103
107
  structuredPatch: output.structuredPatch,
104
- verbose: false
108
+ verbose
105
109
  }
106
110
  );
107
111
  },
@@ -221,9 +225,22 @@ ${editSummary}`;
221
225
  }
222
226
  let modifiedContent = currentContent;
223
227
  const appliedEdits = [];
228
+ const totalEdits = edits.length;
224
229
  for (let i = 0; i < edits.length; i++) {
225
230
  const edit = edits[i];
226
231
  const { old_string, new_string, replace_all } = edit;
232
+ if (totalEdits > 1) {
233
+ yield {
234
+ type: "progress",
235
+ content: {
236
+ type: "streaming",
237
+ toolName: "Multi-Edit",
238
+ stdout: `Applying edit ${i + 1}/${totalEdits}...`,
239
+ stderr: "",
240
+ isStreaming: true
241
+ }
242
+ };
243
+ }
227
244
  try {
228
245
  const result = applyContentEdit(
229
246
  modifiedContent,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/tools/MultiEditTool/MultiEditTool.tsx"],
4
- "sourcesContent": ["import { existsSync, mkdirSync, readFileSync, statSync } from 'fs'\nimport { Box, Text } from 'ink'\nimport { dirname, isAbsolute, relative, resolve, sep } from 'path'\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { FileEditToolUpdatedMessage } from '@components/FileEditToolUpdatedMessage'\nimport { StructuredDiff } from '@components/StructuredDiff'\nimport { Tool, ValidationResult } from '@tool'\nimport { intersperse } from '@utils/array'\nimport {\n addLineNumbers,\n detectFileEncoding,\n detectLineEndings,\n findSimilarFile,\n writeTextContent,\n} from '@utils/file'\nimport { logError } from '@utils/log'\nimport { getCwd } from '@utils/state'\nimport { getTheme } from '@utils/theme'\nimport { NotebookEditTool } from '@tools/NotebookEditTool/NotebookEditTool'\n// Local content-based edit function for MultiEditTool\nfunction applyContentEdit(\n content: string,\n oldString: string,\n newString: string,\n replaceAll: boolean = false,\n): { newContent: string; occurrences: number } {\n if (replaceAll) {\n const regex = new RegExp(\n oldString.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'),\n 'g',\n )\n const matches = content.match(regex)\n const occurrences = matches ? matches.length : 0\n const newContent = content.replace(regex, newString)\n return { newContent, occurrences }\n } else {\n if (content.includes(oldString)) {\n const newContent = content.replace(oldString, newString)\n return { newContent, occurrences: 1 }\n } else {\n throw new Error(`String not found: ${oldString.substring(0, 50)}...`)\n }\n }\n}\nimport { hasWritePermission } from '@utils/permissions/filesystem'\nimport { PROJECT_FILE } from '@constants/product'\nimport { DESCRIPTION, PROMPT } from './prompt'\nimport { emitReminderEvent } from '@services/systemReminder'\nimport { recordFileEdit } from '@services/fileFreshness'\nimport { getPatch } from '@utils/diff'\n\nconst EditSchema = z.object({\n old_string: z.string().describe('The text to replace'),\n new_string: z.string().describe('The text to replace it with'),\n replace_all: z\n .boolean()\n .optional()\n .default(false)\n .describe('Replace all occurences of old_string (default false)'),\n})\n\nconst inputSchema = z.strictObject({\n file_path: z.string().describe('The absolute path to the file to modify'),\n edits: z\n .array(EditSchema)\n .min(1)\n .describe('Array of edit operations to perform sequentially on the file'),\n})\n\nexport type In = typeof inputSchema\n\n// Number of lines of context to include before/after the change in our result message\nconst N_LINES_SNIPPET = 4\n\nexport const MultiEditTool = {\n name: 'MultiEdit',\n async description() {\n return 'A tool for making multiple edits to a single file atomically'\n },\n async prompt() {\n return PROMPT\n },\n inputSchema,\n userFacingName() {\n return 'Multi-Edit'\n },\n async isEnabled() {\n return true\n },\n isReadOnly() {\n return false\n },\n isConcurrencySafe() {\n return false // MultiEdit modifies files, not safe for concurrent execution\n },\n needsPermissions(input?: z.infer<typeof inputSchema>) {\n if (!input) return true\n return !hasWritePermission(input.file_path)\n },\n renderResultForAssistant(content) {\n return content\n },\n renderToolUseMessage(input, { verbose }) {\n const { file_path, edits } = input\n const workingDir = getCwd()\n const relativePath = isAbsolute(file_path)\n ? relative(workingDir, file_path)\n : file_path\n\n if (verbose) {\n const editSummary = edits\n .map(\n (edit, index) =>\n `${index + 1}. Replace \"${edit.old_string.substring(0, 50)}${edit.old_string.length > 50 ? '...' : ''}\" with \"${edit.new_string.substring(0, 50)}${edit.new_string.length > 50 ? '...' : ''}\"`,\n )\n .join('\\n')\n return `Multiple edits to ${relativePath}:\\n${editSummary}`\n }\n\n return `Making ${edits.length} edits to ${relativePath}`\n },\n renderToolUseRejectedMessage() {\n return (\n <Box>\n <Text color={getTheme().error}>\u26A0 Edit request rejected</Text>\n </Box>\n )\n },\n renderToolResultMessage(output) {\n if (typeof output === 'string') {\n const isError = output.includes('Error:')\n return (\n <Box flexDirection=\"column\">\n <Text color={isError ? getTheme().error : getTheme().success}>\n {output}\n </Text>\n </Box>\n )\n }\n\n return (\n <FileEditToolUpdatedMessage\n filePath={output.filePath}\n structuredPatch={output.structuredPatch}\n verbose={false}\n />\n )\n },\n async validateInput(\n { file_path, edits }: z.infer<typeof inputSchema>,\n context?: { readFileTimestamps?: Record<string, number> },\n ): Promise<ValidationResult> {\n const workingDir = getCwd()\n const normalizedPath = isAbsolute(file_path)\n ? resolve(file_path)\n : resolve(workingDir, file_path)\n\n // Check if it's a notebook file\n if (normalizedPath.endsWith('.ipynb')) {\n return {\n result: false,\n errorCode: 1,\n message: `For Jupyter notebooks (.ipynb files), use the ${NotebookEditTool.name} tool instead.`,\n }\n }\n\n // For new files, check parent directory exists\n if (!existsSync(normalizedPath)) {\n const parentDir = dirname(normalizedPath)\n if (!existsSync(parentDir)) {\n return {\n result: false,\n errorCode: 2,\n message: `Parent directory does not exist: ${parentDir}`,\n }\n }\n\n // For new files, ensure first edit creates the file (empty old_string)\n if (edits.length === 0 || edits[0].old_string !== '') {\n return {\n result: false,\n errorCode: 6,\n message:\n 'For new files, the first edit must have an empty old_string to create the file content.',\n }\n }\n } else {\n // For existing files, apply file protection mechanisms\n const readFileTimestamps = context?.readFileTimestamps || {}\n const readTimestamp = readFileTimestamps[normalizedPath]\n\n if (!readTimestamp) {\n return {\n result: false,\n errorCode: 7,\n message:\n 'File has not been read yet. Read it first before editing it.',\n meta: {\n filePath: normalizedPath,\n isFilePathAbsolute: String(isAbsolute(file_path)),\n },\n }\n }\n\n // Check if file has been modified since last read\n const stats = statSync(normalizedPath)\n const lastWriteTime = stats.mtimeMs\n if (lastWriteTime > readTimestamp) {\n return {\n result: false,\n errorCode: 8,\n message:\n 'File has been modified since read, either by the user or by a linter. Read it again before attempting to edit it.',\n meta: {\n filePath: normalizedPath,\n lastWriteTime,\n readTimestamp,\n },\n }\n }\n\n // Pre-validate that all old_strings exist in the file\n const encoding = detectFileEncoding(normalizedPath)\n if (encoding === 'binary') {\n return {\n result: false,\n errorCode: 9,\n message: 'Cannot edit binary files.',\n }\n }\n\n const currentContent = readFileSync(normalizedPath, 'utf-8')\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i]\n if (\n edit.old_string !== '' &&\n !currentContent.includes(edit.old_string)\n ) {\n return {\n result: false,\n errorCode: 10,\n message: `Edit ${i + 1}: String to replace not found in file: \"${edit.old_string.substring(0, 100)}${edit.old_string.length > 100 ? '...' : ''}\"`,\n meta: {\n editIndex: i + 1,\n oldString: edit.old_string.substring(0, 200),\n },\n }\n }\n }\n }\n\n // Validate each edit\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i]\n if (edit.old_string === edit.new_string) {\n return {\n result: false,\n errorCode: 3,\n message: `Edit ${i + 1}: old_string and new_string cannot be the same`,\n }\n }\n }\n\n return { result: true }\n },\n async *call({ file_path, edits }, { readFileTimestamps }) {\n const startTime = Date.now()\n const workingDir = getCwd()\n const filePath = isAbsolute(file_path)\n ? resolve(file_path)\n : resolve(workingDir, file_path)\n\n try {\n // Read current file content (or empty for new files)\n let currentContent = ''\n let fileExists = existsSync(filePath)\n\n if (fileExists) {\n const encoding = detectFileEncoding(filePath)\n if (encoding === 'binary') {\n yield {\n type: 'result',\n data: 'Error: Cannot edit binary files',\n resultForAssistant: 'Error: Cannot edit binary files',\n }\n return\n }\n currentContent = readFileSync(filePath, 'utf-8')\n } else {\n // For new files, ensure parent directory exists\n const parentDir = dirname(filePath)\n if (!existsSync(parentDir)) {\n mkdirSync(parentDir, { recursive: true })\n }\n }\n\n // Apply all edits sequentially\n let modifiedContent = currentContent\n const appliedEdits = []\n\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i]\n const { old_string, new_string, replace_all } = edit\n\n try {\n const result = applyContentEdit(\n modifiedContent,\n old_string,\n new_string,\n replace_all,\n )\n modifiedContent = result.newContent\n appliedEdits.push({\n editIndex: i + 1,\n success: true,\n old_string: old_string.substring(0, 100),\n new_string: new_string.substring(0, 100),\n occurrences: result.occurrences,\n })\n } catch (error) {\n // If any edit fails, abort the entire operation\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error'\n yield {\n type: 'result',\n data: `Error in edit ${i + 1}: ${errorMessage}`,\n resultForAssistant: `Error in edit ${i + 1}: ${errorMessage}`,\n }\n return\n }\n }\n\n // Write the modified content\n const lineEndings = fileExists ? detectLineEndings(currentContent) : 'LF'\n const encoding = fileExists ? detectFileEncoding(filePath) : 'utf8'\n writeTextContent(filePath, modifiedContent, encoding, lineEndings)\n\n // Record Agent edit operation for file freshness tracking\n recordFileEdit(filePath, modifiedContent)\n\n // Update readFileTimestamps to prevent stale file warnings\n readFileTimestamps[filePath] = Date.now()\n\n // Emit file edited event for system reminders\n emitReminderEvent('file:edited', {\n filePath,\n edits: edits.map(e => ({\n oldString: e.old_string,\n newString: e.new_string,\n })),\n originalContent: currentContent,\n newContent: modifiedContent,\n timestamp: Date.now(),\n operation: fileExists ? 'update' : 'create',\n })\n\n // Generate result data\n const relativePath = relative(workingDir, filePath)\n const summary = `Successfully applied ${edits.length} edits to ${relativePath}`\n\n const structuredPatch = getPatch({\n filePath: file_path,\n fileContents: currentContent,\n oldStr: currentContent,\n newStr: modifiedContent,\n })\n\n const resultData = {\n filePath: file_path,\n wasNewFile: !fileExists,\n editsApplied: appliedEdits,\n totalEdits: edits.length,\n summary,\n structuredPatch,\n }\n\n // Log the operation\n\n yield {\n type: 'result',\n data: resultData,\n resultForAssistant: summary,\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error occurred'\n const errorResult = `Error applying multi-edit: ${errorMessage}`\n\n logError(error)\n\n yield {\n type: 'result',\n data: errorResult,\n resultForAssistant: errorResult,\n }\n }\n },\n} satisfies Tool<typeof inputSchema, any>\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { existsSync, mkdirSync, readFileSync, statSync } from 'fs'\nimport { Box, Text } from 'ink'\nimport { dirname, isAbsolute, relative, resolve, sep } from 'path'\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { FileEditToolUpdatedMessage } from '@components/FileEditToolUpdatedMessage'\nimport { StructuredDiff } from '@components/StructuredDiff'\nimport { Tool, ValidationResult } from '@tool'\nimport { intersperse } from '@utils/array'\nimport {\n addLineNumbers,\n detectFileEncoding,\n detectLineEndings,\n findSimilarFile,\n writeTextContent,\n} from '@utils/file'\nimport { logError } from '@utils/log'\nimport { getCwd } from '@utils/state'\nimport { getTheme } from '@utils/theme'\nimport { NotebookEditTool } from '@tools/NotebookEditTool/NotebookEditTool'\n// Local content-based edit function for MultiEditTool\nfunction applyContentEdit(\n content: string,\n oldString: string,\n newString: string,\n replaceAll: boolean = false,\n): { newContent: string; occurrences: number } {\n if (replaceAll) {\n const regex = new RegExp(\n oldString.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'),\n 'g',\n )\n const matches = content.match(regex)\n const occurrences = matches ? matches.length : 0\n const newContent = content.replace(regex, newString)\n return { newContent, occurrences }\n } else {\n if (content.includes(oldString)) {\n const newContent = content.replace(oldString, newString)\n return { newContent, occurrences: 1 }\n } else {\n throw new Error(`String not found: ${oldString.substring(0, 50)}...`)\n }\n }\n}\nimport { hasWritePermission } from '@utils/permissions/filesystem'\nimport { PROJECT_FILE } from '@constants/product'\nimport { DESCRIPTION, PROMPT } from './prompt'\nimport { emitReminderEvent } from '@services/systemReminder'\nimport { recordFileEdit } from '@services/fileFreshness'\nimport { getPatch } from '@utils/diff'\n\nconst EditSchema = z.object({\n old_string: z.string().describe('The text to replace'),\n new_string: z.string().describe('The text to replace it with'),\n replace_all: z\n .boolean()\n .optional()\n .default(false)\n .describe('Replace all occurences of old_string (default false)'),\n})\n\nconst inputSchema = z.strictObject({\n file_path: z.string().describe('The absolute path to the file to modify'),\n edits: z\n .array(EditSchema)\n .min(1)\n .describe('Array of edit operations to perform sequentially on the file'),\n})\n\nexport type In = typeof inputSchema\n\n// Number of lines of context to include before/after the change in our result message\nconst N_LINES_SNIPPET = 4\n\nexport const MultiEditTool = {\n name: 'MultiEdit',\n async description() {\n return 'A tool for making multiple edits to a single file atomically'\n },\n async prompt() {\n return PROMPT\n },\n inputSchema,\n userFacingName() {\n return 'Multi-Edit'\n },\n async isEnabled() {\n return true\n },\n isReadOnly() {\n return false\n },\n isConcurrencySafe() {\n return false // MultiEdit modifies files, not safe for concurrent execution\n },\n needsPermissions(input?: z.infer<typeof inputSchema>) {\n if (!input) return true\n return !hasWritePermission(input.file_path)\n },\n renderResultForAssistant(content) {\n return content\n },\n renderToolUseMessage(input, { verbose }) {\n const { file_path, edits } = input\n const workingDir = getCwd()\n const relativePath = isAbsolute(file_path)\n ? relative(workingDir, file_path)\n : file_path\n\n if (verbose) {\n const editSummary = edits\n .map(\n (edit, index) =>\n `${index + 1}. Replace \"${edit.old_string.substring(0, 50)}${edit.old_string.length > 50 ? '...' : ''}\" with \"${edit.new_string.substring(0, 50)}${edit.new_string.length > 50 ? '...' : ''}\"`,\n )\n .join('\\n')\n return `Multiple edits to ${relativePath}:\\n${editSummary}`\n }\n\n return `Making ${edits.length} edits to ${relativePath}`\n },\n renderToolUseRejectedMessage() {\n return (\n <Box>\n <Text color={getTheme().error}>\u26A0 Edit request rejected</Text>\n </Box>\n )\n },\n renderToolResultMessage(output, options?: { verbose?: boolean }) {\n const verbose = options?.verbose ?? false\n\n // Guard against undefined or null output\n if (!output) {\n return (\n <Box flexDirection=\"column\">\n <Text color={getTheme().secondaryText}>Multi-edit completed</Text>\n </Box>\n )\n }\n\n if (typeof output === 'string') {\n const isError = output.includes('Error:')\n return (\n <Box flexDirection=\"column\">\n <Text color={isError ? getTheme().error : getTheme().success}>\n {output}\n </Text>\n </Box>\n )\n }\n\n return (\n <FileEditToolUpdatedMessage\n filePath={output.filePath}\n structuredPatch={output.structuredPatch}\n verbose={verbose}\n />\n )\n },\n async validateInput(\n { file_path, edits }: z.infer<typeof inputSchema>,\n context?: { readFileTimestamps?: Record<string, number> },\n ): Promise<ValidationResult> {\n const workingDir = getCwd()\n const normalizedPath = isAbsolute(file_path)\n ? resolve(file_path)\n : resolve(workingDir, file_path)\n\n // Check if it's a notebook file\n if (normalizedPath.endsWith('.ipynb')) {\n return {\n result: false,\n errorCode: 1,\n message: `For Jupyter notebooks (.ipynb files), use the ${NotebookEditTool.name} tool instead.`,\n }\n }\n\n // For new files, check parent directory exists\n if (!existsSync(normalizedPath)) {\n const parentDir = dirname(normalizedPath)\n if (!existsSync(parentDir)) {\n return {\n result: false,\n errorCode: 2,\n message: `Parent directory does not exist: ${parentDir}`,\n }\n }\n\n // For new files, ensure first edit creates the file (empty old_string)\n if (edits.length === 0 || edits[0].old_string !== '') {\n return {\n result: false,\n errorCode: 6,\n message:\n 'For new files, the first edit must have an empty old_string to create the file content.',\n }\n }\n } else {\n // For existing files, apply file protection mechanisms\n const readFileTimestamps = context?.readFileTimestamps || {}\n const readTimestamp = readFileTimestamps[normalizedPath]\n\n if (!readTimestamp) {\n return {\n result: false,\n errorCode: 7,\n message:\n 'File has not been read yet. Read it first before editing it.',\n meta: {\n filePath: normalizedPath,\n isFilePathAbsolute: String(isAbsolute(file_path)),\n },\n }\n }\n\n // Check if file has been modified since last read\n const stats = statSync(normalizedPath)\n const lastWriteTime = stats.mtimeMs\n if (lastWriteTime > readTimestamp) {\n return {\n result: false,\n errorCode: 8,\n message:\n 'File has been modified since read, either by the user or by a linter. Read it again before attempting to edit it.',\n meta: {\n filePath: normalizedPath,\n lastWriteTime,\n readTimestamp,\n },\n }\n }\n\n // Pre-validate that all old_strings exist in the file\n const encoding = detectFileEncoding(normalizedPath)\n if (encoding === 'binary') {\n return {\n result: false,\n errorCode: 9,\n message: 'Cannot edit binary files.',\n }\n }\n\n const currentContent = readFileSync(normalizedPath, 'utf-8')\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i]\n if (\n edit.old_string !== '' &&\n !currentContent.includes(edit.old_string)\n ) {\n return {\n result: false,\n errorCode: 10,\n message: `Edit ${i + 1}: String to replace not found in file: \"${edit.old_string.substring(0, 100)}${edit.old_string.length > 100 ? '...' : ''}\"`,\n meta: {\n editIndex: i + 1,\n oldString: edit.old_string.substring(0, 200),\n },\n }\n }\n }\n }\n\n // Validate each edit\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i]\n if (edit.old_string === edit.new_string) {\n return {\n result: false,\n errorCode: 3,\n message: `Edit ${i + 1}: old_string and new_string cannot be the same`,\n }\n }\n }\n\n return { result: true }\n },\n async *call({ file_path, edits }, { readFileTimestamps }) {\n const startTime = Date.now()\n const workingDir = getCwd()\n const filePath = isAbsolute(file_path)\n ? resolve(file_path)\n : resolve(workingDir, file_path)\n\n try {\n // Read current file content (or empty for new files)\n let currentContent = ''\n let fileExists = existsSync(filePath)\n\n if (fileExists) {\n const encoding = detectFileEncoding(filePath)\n if (encoding === 'binary') {\n yield {\n type: 'result',\n data: 'Error: Cannot edit binary files',\n resultForAssistant: 'Error: Cannot edit binary files',\n }\n return\n }\n currentContent = readFileSync(filePath, 'utf-8')\n } else {\n // For new files, ensure parent directory exists\n const parentDir = dirname(filePath)\n if (!existsSync(parentDir)) {\n mkdirSync(parentDir, { recursive: true })\n }\n }\n\n // Apply all edits sequentially with progress updates\n let modifiedContent = currentContent\n const appliedEdits = []\n const totalEdits = edits.length\n\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i]\n const { old_string, new_string, replace_all } = edit\n\n // Yield progress update for multi-edit operations\n if (totalEdits > 1) {\n yield {\n type: 'progress',\n content: {\n type: 'streaming',\n toolName: 'Multi-Edit',\n stdout: `Applying edit ${i + 1}/${totalEdits}...`,\n stderr: '',\n isStreaming: true,\n },\n }\n }\n\n try {\n const result = applyContentEdit(\n modifiedContent,\n old_string,\n new_string,\n replace_all,\n )\n modifiedContent = result.newContent\n appliedEdits.push({\n editIndex: i + 1,\n success: true,\n old_string: old_string.substring(0, 100),\n new_string: new_string.substring(0, 100),\n occurrences: result.occurrences,\n })\n } catch (error) {\n // If any edit fails, abort the entire operation\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error'\n yield {\n type: 'result',\n data: `Error in edit ${i + 1}: ${errorMessage}`,\n resultForAssistant: `Error in edit ${i + 1}: ${errorMessage}`,\n }\n return\n }\n }\n\n // Write the modified content\n const lineEndings = fileExists ? detectLineEndings(currentContent) : 'LF'\n const encoding = fileExists ? detectFileEncoding(filePath) : 'utf8'\n writeTextContent(filePath, modifiedContent, encoding, lineEndings)\n\n // Record Agent edit operation for file freshness tracking\n recordFileEdit(filePath, modifiedContent)\n\n // Update readFileTimestamps to prevent stale file warnings\n readFileTimestamps[filePath] = Date.now()\n\n // Emit file edited event for system reminders\n emitReminderEvent('file:edited', {\n filePath,\n edits: edits.map(e => ({\n oldString: e.old_string,\n newString: e.new_string,\n })),\n originalContent: currentContent,\n newContent: modifiedContent,\n timestamp: Date.now(),\n operation: fileExists ? 'update' : 'create',\n })\n\n // Generate result data\n const relativePath = relative(workingDir, filePath)\n const summary = `Successfully applied ${edits.length} edits to ${relativePath}`\n\n const structuredPatch = getPatch({\n filePath: file_path,\n fileContents: currentContent,\n oldStr: currentContent,\n newStr: modifiedContent,\n })\n\n const resultData = {\n filePath: file_path,\n wasNewFile: !fileExists,\n editsApplied: appliedEdits,\n totalEdits: edits.length,\n summary,\n structuredPatch,\n }\n\n // Log the operation\n\n yield {\n type: 'result',\n data: resultData,\n resultForAssistant: summary,\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error occurred'\n const errorResult = `Error applying multi-edit: ${errorMessage}`\n\n logError(error)\n\n yield {\n type: 'result',\n data: errorResult,\n resultForAssistant: errorResult,\n }\n }\n },\n} satisfies Tool<typeof inputSchema, any>\n"],
5
+ "mappings": "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",
6
6
  "names": ["encoding"]
7
7
  }
@@ -72,7 +72,11 @@ const NotebookEditTool = {
72
72
  renderToolUseRejectedMessage() {
73
73
  return /* @__PURE__ */ React.createElement(FallbackToolUseRejectedMessage, null);
74
74
  },
75
- renderToolResultMessage({ cell_number, new_source, language, error }) {
75
+ renderToolResultMessage(output) {
76
+ if (!output) {
77
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, null, "Notebook cell updated"));
78
+ }
79
+ const { cell_number, new_source, language, error } = output;
76
80
  if (error) {
77
81
  return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, error));
78
82
  }