@umsai/ums-code 0.3.0-v2 → 0.5.0-v1

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 (294) hide show
  1. package/dist/package.json +4 -4
  2. package/dist/src/{zed-integration → acp-integration}/acp.d.ts +7 -0
  3. package/dist/src/{zed-integration → acp-integration}/acp.js +25 -0
  4. package/dist/src/acp-integration/acp.js.map +1 -0
  5. package/dist/src/acp-integration/acpAgent.d.ts +10 -0
  6. package/dist/src/acp-integration/acpAgent.js +238 -0
  7. package/dist/src/acp-integration/acpAgent.js.map +1 -0
  8. package/dist/src/{zed-integration → acp-integration}/schema.d.ts +1030 -43
  9. package/dist/src/{zed-integration → acp-integration}/schema.js +81 -2
  10. package/dist/src/acp-integration/schema.js.map +1 -0
  11. package/dist/src/{zed-integration/fileSystemService.d.ts → acp-integration/service/filesystem.d.ts} +1 -1
  12. package/dist/src/{zed-integration/fileSystemService.js → acp-integration/service/filesystem.js} +14 -1
  13. package/dist/src/acp-integration/service/filesystem.js.map +1 -0
  14. package/dist/src/acp-integration/service/filesystem.test.d.ts +6 -0
  15. package/dist/src/acp-integration/service/filesystem.test.js +39 -0
  16. package/dist/src/acp-integration/service/filesystem.test.js.map +1 -0
  17. package/dist/src/acp-integration/session/HistoryReplayer.d.ts +51 -0
  18. package/dist/src/acp-integration/session/HistoryReplayer.js +164 -0
  19. package/dist/src/acp-integration/session/HistoryReplayer.js.map +1 -0
  20. package/dist/src/acp-integration/session/HistoryReplayer.test.d.ts +6 -0
  21. package/dist/src/acp-integration/session/HistoryReplayer.test.js +374 -0
  22. package/dist/src/acp-integration/session/HistoryReplayer.test.js.map +1 -0
  23. package/dist/src/acp-integration/session/Session.d.ts +66 -0
  24. package/dist/src/acp-integration/session/Session.js +760 -0
  25. package/dist/src/acp-integration/session/Session.js.map +1 -0
  26. package/dist/src/acp-integration/session/SubAgentTracker.d.ts +51 -0
  27. package/dist/src/acp-integration/session/SubAgentTracker.js +257 -0
  28. package/dist/src/acp-integration/session/SubAgentTracker.js.map +1 -0
  29. package/dist/src/acp-integration/session/SubAgentTracker.test.d.ts +6 -0
  30. package/dist/src/acp-integration/session/SubAgentTracker.test.js +369 -0
  31. package/dist/src/acp-integration/session/SubAgentTracker.test.js.map +1 -0
  32. package/dist/src/acp-integration/session/emitters/BaseEmitter.d.ts +27 -0
  33. package/dist/src/acp-integration/session/emitters/BaseEmitter.js +34 -0
  34. package/dist/src/acp-integration/session/emitters/BaseEmitter.js.map +1 -0
  35. package/dist/src/acp-integration/session/emitters/MessageEmitter.d.ts +41 -0
  36. package/dist/src/acp-integration/session/emitters/MessageEmitter.js +77 -0
  37. package/dist/src/acp-integration/session/emitters/MessageEmitter.js.map +1 -0
  38. package/dist/src/acp-integration/session/emitters/MessageEmitter.test.d.ts +6 -0
  39. package/dist/src/acp-integration/session/emitters/MessageEmitter.test.js +174 -0
  40. package/dist/src/acp-integration/session/emitters/MessageEmitter.test.js.map +1 -0
  41. package/dist/src/acp-integration/session/emitters/PlanEmitter.d.ts +39 -0
  42. package/dist/src/acp-integration/session/emitters/PlanEmitter.js +83 -0
  43. package/dist/src/acp-integration/session/emitters/PlanEmitter.js.map +1 -0
  44. package/dist/src/acp-integration/session/emitters/PlanEmitter.test.d.ts +6 -0
  45. package/dist/src/acp-integration/session/emitters/PlanEmitter.test.js +176 -0
  46. package/dist/src/acp-integration/session/emitters/PlanEmitter.test.js.map +1 -0
  47. package/dist/src/acp-integration/session/emitters/ToolCallEmitter.d.ts +80 -0
  48. package/dist/src/acp-integration/session/emitters/ToolCallEmitter.js +248 -0
  49. package/dist/src/acp-integration/session/emitters/ToolCallEmitter.js.map +1 -0
  50. package/dist/src/acp-integration/session/emitters/ToolCallEmitter.test.d.ts +6 -0
  51. package/dist/src/acp-integration/session/emitters/ToolCallEmitter.test.js +561 -0
  52. package/dist/src/acp-integration/session/emitters/ToolCallEmitter.test.js.map +1 -0
  53. package/dist/src/acp-integration/session/emitters/index.d.ts +9 -0
  54. package/dist/src/acp-integration/session/emitters/index.js +10 -0
  55. package/dist/src/acp-integration/session/emitters/index.js.map +1 -0
  56. package/dist/src/acp-integration/session/index.d.ts +24 -0
  57. package/dist/src/acp-integration/session/index.js +16 -0
  58. package/dist/src/acp-integration/session/index.js.map +1 -0
  59. package/dist/src/acp-integration/session/types.d.ts +71 -0
  60. package/dist/src/acp-integration/session/types.js +7 -0
  61. package/dist/src/acp-integration/session/types.js.map +1 -0
  62. package/dist/src/config/auth.d.ts +1 -0
  63. package/dist/src/config/auth.js +3 -0
  64. package/dist/src/config/auth.js.map +1 -1
  65. package/dist/src/config/config.d.ts +11 -3
  66. package/dist/src/config/config.js +84 -8
  67. package/dist/src/config/config.js.map +1 -1
  68. package/dist/src/config/extension.js +0 -2
  69. package/dist/src/config/extension.js.map +1 -1
  70. package/dist/src/config/settingsSchema.d.ts +12 -0
  71. package/dist/src/config/settingsSchema.js +10 -0
  72. package/dist/src/config/settingsSchema.js.map +1 -1
  73. package/dist/src/core/auth.d.ts +1 -1
  74. package/dist/src/core/auth.js +3 -2
  75. package/dist/src/core/auth.js.map +1 -1
  76. package/dist/src/gemini.js +38 -18
  77. package/dist/src/gemini.js.map +1 -1
  78. package/dist/src/gemini.test.js +7 -0
  79. package/dist/src/gemini.test.js.map +1 -1
  80. package/dist/src/generated/git-commit.d.ts +2 -2
  81. package/dist/src/generated/git-commit.js +2 -2
  82. package/dist/src/i18n/index.d.ts +1 -1
  83. package/dist/src/i18n/index.js +4 -0
  84. package/dist/src/i18n/index.js.map +1 -1
  85. package/dist/src/i18n/locales/en.js +1 -13
  86. package/dist/src/i18n/locales/ru.js +1121 -0
  87. package/dist/src/i18n/locales/zh.js +1 -10
  88. package/dist/src/nonInteractive/control/ControlDispatcher.d.ts +24 -1
  89. package/dist/src/nonInteractive/control/ControlDispatcher.js +46 -17
  90. package/dist/src/nonInteractive/control/ControlDispatcher.js.map +1 -1
  91. package/dist/src/nonInteractive/control/ControlService.d.ts +2 -1
  92. package/dist/src/nonInteractive/control/ControlService.js +22 -37
  93. package/dist/src/nonInteractive/control/ControlService.js.map +1 -1
  94. package/dist/src/nonInteractive/control/controllers/baseController.d.ts +2 -1
  95. package/dist/src/nonInteractive/control/controllers/baseController.js +38 -5
  96. package/dist/src/nonInteractive/control/controllers/baseController.js.map +1 -1
  97. package/dist/src/nonInteractive/control/controllers/permissionController.d.ts +1 -22
  98. package/dist/src/nonInteractive/control/controllers/permissionController.js +38 -38
  99. package/dist/src/nonInteractive/control/controllers/permissionController.js.map +1 -1
  100. package/dist/src/nonInteractive/control/controllers/sdkMcpController.d.ts +54 -0
  101. package/dist/src/nonInteractive/control/controllers/sdkMcpController.js +84 -0
  102. package/dist/src/nonInteractive/control/controllers/sdkMcpController.js.map +1 -0
  103. package/dist/src/nonInteractive/control/controllers/systemController.d.ts +16 -6
  104. package/dist/src/nonInteractive/control/controllers/systemController.js +189 -44
  105. package/dist/src/nonInteractive/control/controllers/systemController.js.map +1 -1
  106. package/dist/src/nonInteractive/control/types/serviceAPIs.d.ts +1 -16
  107. package/dist/src/nonInteractive/io/BaseJsonOutputAdapter.d.ts +11 -0
  108. package/dist/src/nonInteractive/io/BaseJsonOutputAdapter.js +54 -2
  109. package/dist/src/nonInteractive/io/BaseJsonOutputAdapter.js.map +1 -1
  110. package/dist/src/nonInteractive/session.d.ts +0 -16
  111. package/dist/src/nonInteractive/session.js +317 -321
  112. package/dist/src/nonInteractive/session.js.map +1 -1
  113. package/dist/src/nonInteractive/session.test.js +6 -0
  114. package/dist/src/nonInteractive/session.test.js.map +1 -1
  115. package/dist/src/nonInteractive/types.d.ts +57 -3
  116. package/dist/src/nonInteractive/types.js +0 -1
  117. package/dist/src/nonInteractive/types.js.map +1 -1
  118. package/dist/src/nonInteractiveCli.js +25 -46
  119. package/dist/src/nonInteractiveCli.js.map +1 -1
  120. package/dist/src/services/BuiltinCommandLoader.js +5 -6
  121. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  122. package/dist/src/services/BuiltinCommandLoader.test.js +0 -3
  123. package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
  124. package/dist/src/test-utils/mockCommandContext.js +11 -2
  125. package/dist/src/test-utils/mockCommandContext.js.map +1 -1
  126. package/dist/src/ui/AppContainer.js +39 -36
  127. package/dist/src/ui/AppContainer.js.map +1 -1
  128. package/dist/src/ui/auth/useAuth.js +20 -1
  129. package/dist/src/ui/auth/useAuth.js.map +1 -1
  130. package/dist/src/ui/commands/clearCommand.js +22 -10
  131. package/dist/src/ui/commands/clearCommand.js.map +1 -1
  132. package/dist/src/ui/commands/languageCommand.js +41 -8
  133. package/dist/src/ui/commands/languageCommand.js.map +1 -1
  134. package/dist/src/ui/commands/languageCommand.test.d.ts +6 -0
  135. package/dist/src/ui/commands/languageCommand.test.js +463 -0
  136. package/dist/src/ui/commands/languageCommand.test.js.map +1 -0
  137. package/dist/src/ui/commands/modelCommand.js +4 -2
  138. package/dist/src/ui/commands/modelCommand.js.map +1 -1
  139. package/dist/src/ui/commands/quitCommand.d.ts +0 -1
  140. package/dist/src/ui/commands/quitCommand.js +0 -27
  141. package/dist/src/ui/commands/quitCommand.js.map +1 -1
  142. package/dist/src/ui/commands/reviewCommand.d.ts +9 -0
  143. package/dist/src/ui/commands/reviewCommand.js +1267 -0
  144. package/dist/src/ui/commands/reviewCommand.js.map +1 -0
  145. package/dist/src/ui/commands/reviewCommand.test.d.ts +6 -0
  146. package/dist/src/ui/commands/reviewCommand.test.js +545 -0
  147. package/dist/src/ui/commands/reviewCommand.test.js.map +1 -0
  148. package/dist/src/ui/commands/setupGithubCommand.js +11 -10
  149. package/dist/src/ui/commands/setupGithubCommand.js.map +1 -1
  150. package/dist/src/ui/commands/setupGithubCommand.test.js +14 -14
  151. package/dist/src/ui/commands/setupGithubCommand.test.js.map +1 -1
  152. package/dist/src/ui/commands/types.d.ts +4 -9
  153. package/dist/src/ui/commands/types.js.map +1 -1
  154. package/dist/src/ui/commands/ums/unittestCommand.d.ts +9 -0
  155. package/dist/src/ui/commands/ums/unittestCommand.js +387 -0
  156. package/dist/src/ui/commands/ums/unittestCommand.js.map +1 -0
  157. package/dist/src/ui/components/Composer.test.js +1 -2
  158. package/dist/src/ui/components/Composer.test.js.map +1 -1
  159. package/dist/src/ui/components/ContextUsageDisplay.d.ts +3 -2
  160. package/dist/src/ui/components/ContextUsageDisplay.js +8 -2
  161. package/dist/src/ui/components/ContextUsageDisplay.js.map +1 -1
  162. package/dist/src/ui/components/DialogManager.js +3 -19
  163. package/dist/src/ui/components/DialogManager.js.map +1 -1
  164. package/dist/src/ui/components/Footer.js +2 -3
  165. package/dist/src/ui/components/Footer.js.map +1 -1
  166. package/dist/src/ui/components/Help.js +13 -2
  167. package/dist/src/ui/components/Help.js.map +1 -1
  168. package/dist/src/ui/components/Help.test.js +6 -0
  169. package/dist/src/ui/components/Help.test.js.map +1 -1
  170. package/dist/src/ui/components/HistoryItemDisplay.js +3 -1
  171. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  172. package/dist/src/ui/components/InputPrompt.js +6 -4
  173. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  174. package/dist/src/ui/components/ModelDialog.d.ts +3 -1
  175. package/dist/src/ui/components/ModelDialog.js +25 -5
  176. package/dist/src/ui/components/ModelDialog.js.map +1 -1
  177. package/dist/src/ui/components/OpenAIKeyPrompt.d.ts +3 -0
  178. package/dist/src/ui/components/OpenAIKeyPrompt.js +1 -0
  179. package/dist/src/ui/components/OpenAIKeyPrompt.js.map +1 -1
  180. package/dist/src/ui/components/ResumeSessionPicker.d.ts +10 -0
  181. package/dist/src/ui/components/ResumeSessionPicker.js +249 -0
  182. package/dist/src/ui/components/ResumeSessionPicker.js.map +1 -0
  183. package/dist/src/ui/components/SessionSummaryDisplay.js +10 -2
  184. package/dist/src/ui/components/SessionSummaryDisplay.js.map +1 -1
  185. package/dist/src/ui/components/SettingsDialog.test.js +2 -2
  186. package/dist/src/ui/components/SuggestionsDisplay.js +3 -2
  187. package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
  188. package/dist/src/ui/components/messages/GeminiThoughtMessage.d.ts +18 -0
  189. package/dist/src/ui/components/messages/GeminiThoughtMessage.js +14 -0
  190. package/dist/src/ui/components/messages/GeminiThoughtMessage.js.map +1 -0
  191. package/dist/src/ui/components/messages/GeminiThoughtMessageContent.d.ts +18 -0
  192. package/dist/src/ui/components/messages/GeminiThoughtMessageContent.js +14 -0
  193. package/dist/src/ui/components/messages/GeminiThoughtMessageContent.js.map +1 -0
  194. package/dist/src/ui/components/subagents/manage/AgentEditStep.js +4 -1
  195. package/dist/src/ui/components/subagents/manage/AgentEditStep.js.map +1 -1
  196. package/dist/src/ui/components/subagents/manage/AgentSelectionStep.js +2 -2
  197. package/dist/src/ui/components/subagents/manage/AgentSelectionStep.js.map +1 -1
  198. package/dist/src/ui/components/ums/UMSKeyPrompt.d.ts +1 -1
  199. package/dist/src/ui/components/ums/UMSKeyPrompt.js +23 -3
  200. package/dist/src/ui/components/ums/UMSKeyPrompt.js.map +1 -1
  201. package/dist/src/ui/components/ums/umsStartupWarnings.d.ts +6 -0
  202. package/dist/src/ui/components/ums/umsStartupWarnings.js +47 -0
  203. package/dist/src/ui/components/ums/umsStartupWarnings.js.map +1 -0
  204. package/dist/src/ui/contexts/SessionContext.d.ts +2 -0
  205. package/dist/src/ui/contexts/SessionContext.js +18 -10
  206. package/dist/src/ui/contexts/SessionContext.js.map +1 -1
  207. package/dist/src/ui/contexts/UIStateContext.d.ts +1 -3
  208. package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
  209. package/dist/src/ui/hooks/slashCommandProcessor.d.ts +2 -8
  210. package/dist/src/ui/hooks/slashCommandProcessor.js +68 -101
  211. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  212. package/dist/src/ui/hooks/useAttentionNotifications.d.ts +3 -1
  213. package/dist/src/ui/hooks/useAttentionNotifications.js +10 -5
  214. package/dist/src/ui/hooks/useAttentionNotifications.js.map +1 -1
  215. package/dist/src/ui/hooks/useAttentionNotifications.test.js +39 -2
  216. package/dist/src/ui/hooks/useAttentionNotifications.test.js.map +1 -1
  217. package/dist/src/ui/hooks/useDialogClose.d.ts +0 -3
  218. package/dist/src/ui/hooks/useDialogClose.js +0 -2
  219. package/dist/src/ui/hooks/useDialogClose.js.map +1 -1
  220. package/dist/src/ui/hooks/useGeminiStream.js +49 -9
  221. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  222. package/dist/src/ui/hooks/useLogger.d.ts +1 -1
  223. package/dist/src/ui/hooks/useLogger.js +6 -3
  224. package/dist/src/ui/hooks/useLogger.js.map +1 -1
  225. package/dist/src/ui/hooks/useReactToolScheduler.js +2 -2
  226. package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
  227. package/dist/src/ui/hooks/useSlashCompletion.js +9 -1
  228. package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
  229. package/dist/src/ui/hooks/useSlashCompletion.test.js +36 -31
  230. package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
  231. package/dist/src/ui/hooks/useToolScheduler.test.js +1 -0
  232. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
  233. package/dist/src/ui/models/availableModels.d.ts +8 -2
  234. package/dist/src/ui/models/availableModels.js +24 -35
  235. package/dist/src/ui/models/availableModels.js.map +1 -1
  236. package/dist/src/ui/noninteractive/nonInteractiveUi.js +0 -1
  237. package/dist/src/ui/noninteractive/nonInteractiveUi.js.map +1 -1
  238. package/dist/src/ui/types.d.ts +9 -14
  239. package/dist/src/ui/types.js +0 -1
  240. package/dist/src/ui/types.js.map +1 -1
  241. package/dist/src/ui/utils/InlineMarkdownRenderer.d.ts +1 -0
  242. package/dist/src/ui/utils/InlineMarkdownRenderer.js +2 -2
  243. package/dist/src/ui/utils/InlineMarkdownRenderer.js.map +1 -1
  244. package/dist/src/ui/utils/MarkdownDisplay.d.ts +1 -0
  245. package/dist/src/ui/utils/MarkdownDisplay.js +13 -13
  246. package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
  247. package/dist/src/ui/utils/formatters.d.ts +6 -0
  248. package/dist/src/ui/utils/formatters.js +31 -0
  249. package/dist/src/ui/utils/formatters.js.map +1 -1
  250. package/dist/src/ui/utils/formatters.test.js +51 -2
  251. package/dist/src/ui/utils/formatters.test.js.map +1 -1
  252. package/dist/src/ui/utils/resumeHistoryUtils.d.ts +19 -0
  253. package/dist/src/ui/utils/resumeHistoryUtils.js +263 -0
  254. package/dist/src/ui/utils/resumeHistoryUtils.js.map +1 -0
  255. package/dist/src/ui/utils/resumeHistoryUtils.test.d.ts +6 -0
  256. package/dist/src/ui/utils/resumeHistoryUtils.test.js +248 -0
  257. package/dist/src/ui/utils/resumeHistoryUtils.test.js.map +1 -0
  258. package/dist/src/utils/attentionNotification.d.ts +1 -0
  259. package/dist/src/utils/attentionNotification.js +4 -0
  260. package/dist/src/utils/attentionNotification.js.map +1 -1
  261. package/dist/src/utils/gitUtils.js +3 -3
  262. package/dist/src/utils/gitUtils.js.map +1 -1
  263. package/dist/src/utils/nonInteractiveHelpers.js +1 -1
  264. package/dist/src/utils/nonInteractiveHelpers.js.map +1 -1
  265. package/dist/src/utils/nonInteractiveHelpers.test.js +1 -1
  266. package/dist/src/utils/nonInteractiveHelpers.test.js.map +1 -1
  267. package/dist/src/validateNonInterActiveAuth.js +1 -1
  268. package/dist/src/validateNonInterActiveAuth.js.map +1 -1
  269. package/dist/tsconfig.tsbuildinfo +1 -1
  270. package/package.json +5 -5
  271. package/dist/src/nonInteractive/control/controllers/mcpController.d.ts +0 -42
  272. package/dist/src/nonInteractive/control/controllers/mcpController.js +0 -205
  273. package/dist/src/nonInteractive/control/controllers/mcpController.js.map +0 -1
  274. package/dist/src/ui/commands/chatCommand.d.ts +0 -9
  275. package/dist/src/ui/commands/chatCommand.js +0 -351
  276. package/dist/src/ui/commands/chatCommand.js.map +0 -1
  277. package/dist/src/ui/commands/corgiCommand.d.ts +0 -7
  278. package/dist/src/ui/commands/corgiCommand.js +0 -16
  279. package/dist/src/ui/commands/corgiCommand.js.map +0 -1
  280. package/dist/src/ui/components/QuitConfirmationDialog.d.ts +0 -17
  281. package/dist/src/ui/components/QuitConfirmationDialog.js +0 -49
  282. package/dist/src/ui/components/QuitConfirmationDialog.js.map +0 -1
  283. package/dist/src/ui/hooks/usePromptCompletion.d.ts +0 -23
  284. package/dist/src/ui/hooks/usePromptCompletion.js +0 -177
  285. package/dist/src/ui/hooks/usePromptCompletion.js.map +0 -1
  286. package/dist/src/ui/hooks/useQuitConfirmation.d.ts +0 -14
  287. package/dist/src/ui/hooks/useQuitConfirmation.js +0 -36
  288. package/dist/src/ui/hooks/useQuitConfirmation.js.map +0 -1
  289. package/dist/src/zed-integration/acp.js.map +0 -1
  290. package/dist/src/zed-integration/fileSystemService.js.map +0 -1
  291. package/dist/src/zed-integration/schema.js.map +0 -1
  292. package/dist/src/zed-integration/zedIntegration.d.ts +0 -17
  293. package/dist/src/zed-integration/zedIntegration.js +0 -1135
  294. package/dist/src/zed-integration/zedIntegration.js.map +0 -1
@@ -0,0 +1,760 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Qwen
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { ApprovalMode, convertToFunctionResponse, DiscoveredMCPTool, StreamEventType, ToolConfirmationOutcome, logToolCall, logUserPrompt, getErrorStatus, isWithinRoot, isNodeError, TaskTool, UserPromptEvent, TodoWriteTool, ExitPlanModeTool, } from '@umsai/ums-code-core';
7
+ import * as acp from '../acp.js';
8
+ import * as fs from 'node:fs/promises';
9
+ import * as path from 'node:path';
10
+ import { z } from 'zod';
11
+ import { getErrorMessage } from '../../utils/errors.js';
12
+ import { handleSlashCommand, getAvailableCommands, } from '../../nonInteractiveCliCommands.js';
13
+ import { isSlashCommand } from '../../ui/utils/commandUtils.js';
14
+ import { HistoryReplayer } from './HistoryReplayer.js';
15
+ import { ToolCallEmitter } from './emitters/ToolCallEmitter.js';
16
+ import { PlanEmitter } from './emitters/PlanEmitter.js';
17
+ import { MessageEmitter } from './emitters/MessageEmitter.js';
18
+ import { SubAgentTracker } from './SubAgentTracker.js';
19
+ /**
20
+ * Built-in commands that are allowed in ACP integration mode.
21
+ * Only safe, read-only commands that don't require interactive UI.
22
+ */
23
+ export const ALLOWED_BUILTIN_COMMANDS_FOR_ACP = ['init'];
24
+ /**
25
+ * Session represents an active conversation session with the AI model.
26
+ * It uses modular components for consistent event emission:
27
+ * - HistoryReplayer for replaying past conversations
28
+ * - ToolCallEmitter for tool-related session updates
29
+ * - PlanEmitter for todo/plan updates
30
+ * - SubAgentTracker for tracking sub-agent tool calls
31
+ */
32
+ export class Session {
33
+ chat;
34
+ config;
35
+ client;
36
+ settings;
37
+ pendingPrompt = null;
38
+ turn = 0;
39
+ // Modular components
40
+ historyReplayer;
41
+ toolCallEmitter;
42
+ planEmitter;
43
+ messageEmitter;
44
+ // Implement SessionContext interface
45
+ sessionId;
46
+ constructor(id, chat, config, client, settings) {
47
+ this.chat = chat;
48
+ this.config = config;
49
+ this.client = client;
50
+ this.settings = settings;
51
+ this.sessionId = id;
52
+ // Initialize modular components with this session as context
53
+ this.toolCallEmitter = new ToolCallEmitter(this);
54
+ this.planEmitter = new PlanEmitter(this);
55
+ this.historyReplayer = new HistoryReplayer(this);
56
+ this.messageEmitter = new MessageEmitter(this);
57
+ }
58
+ getId() {
59
+ return this.sessionId;
60
+ }
61
+ getConfig() {
62
+ return this.config;
63
+ }
64
+ /**
65
+ * Replays conversation history to the client using modular components.
66
+ * Delegates to HistoryReplayer for consistent event emission.
67
+ */
68
+ async replayHistory(records) {
69
+ await this.historyReplayer.replay(records);
70
+ }
71
+ async cancelPendingPrompt() {
72
+ if (!this.pendingPrompt) {
73
+ throw new Error('Not currently generating');
74
+ }
75
+ this.pendingPrompt.abort();
76
+ this.pendingPrompt = null;
77
+ }
78
+ async prompt(params) {
79
+ this.pendingPrompt?.abort();
80
+ const pendingSend = new AbortController();
81
+ this.pendingPrompt = pendingSend;
82
+ // Increment turn counter for each user prompt
83
+ this.turn += 1;
84
+ const chat = this.chat;
85
+ const promptId = this.config.getSessionId() + '########' + this.turn;
86
+ // Extract text from all text blocks to construct the full prompt text for logging
87
+ const promptText = params.prompt
88
+ .filter((block) => block.type === 'text')
89
+ .map((block) => (block.type === 'text' ? block.text : ''))
90
+ .join(' ');
91
+ // Log user prompt
92
+ logUserPrompt(this.config, new UserPromptEvent(promptText.length, promptId, this.config.getContentGeneratorConfig()?.authType, promptText));
93
+ // record user message for session management
94
+ this.config.getChatRecordingService()?.recordUserMessage(promptText);
95
+ // Check if the input contains a slash command
96
+ // Extract text from the first text block if present
97
+ const firstTextBlock = params.prompt.find((block) => block.type === 'text');
98
+ const inputText = firstTextBlock?.text || '';
99
+ let parts;
100
+ if (isSlashCommand(inputText)) {
101
+ // Handle slash command - allow specific built-in commands for ACP integration
102
+ const slashCommandResult = await handleSlashCommand(inputText, pendingSend, this.config, this.settings, ALLOWED_BUILTIN_COMMANDS_FOR_ACP);
103
+ if (slashCommandResult) {
104
+ // Use the result from the slash command
105
+ parts = slashCommandResult;
106
+ }
107
+ else {
108
+ // Slash command didn't return a prompt, continue with normal processing
109
+ parts = await this.#resolvePrompt(params.prompt, pendingSend.signal);
110
+ }
111
+ }
112
+ else {
113
+ // Normal processing for non-slash commands
114
+ parts = await this.#resolvePrompt(params.prompt, pendingSend.signal);
115
+ }
116
+ let nextMessage = { role: 'user', parts };
117
+ while (nextMessage !== null) {
118
+ if (pendingSend.signal.aborted) {
119
+ chat.addHistory(nextMessage);
120
+ return { stopReason: 'cancelled' };
121
+ }
122
+ const functionCalls = [];
123
+ let usageMetadata = null;
124
+ const streamStartTime = Date.now();
125
+ try {
126
+ const responseStream = await chat.sendMessageStream(this.config.getModel(), {
127
+ message: nextMessage?.parts ?? [],
128
+ config: {
129
+ abortSignal: pendingSend.signal,
130
+ },
131
+ }, promptId);
132
+ nextMessage = null;
133
+ for await (const resp of responseStream) {
134
+ if (pendingSend.signal.aborted) {
135
+ return { stopReason: 'cancelled' };
136
+ }
137
+ if (resp.type === StreamEventType.CHUNK &&
138
+ resp.value.candidates &&
139
+ resp.value.candidates.length > 0) {
140
+ const candidate = resp.value.candidates[0];
141
+ for (const part of candidate.content?.parts ?? []) {
142
+ if (!part.text) {
143
+ continue;
144
+ }
145
+ this.messageEmitter.emitMessage(part.text, 'assistant', part.thought);
146
+ }
147
+ }
148
+ if (resp.type === StreamEventType.CHUNK && resp.value.usageMetadata) {
149
+ usageMetadata = resp.value.usageMetadata;
150
+ }
151
+ if (resp.type === StreamEventType.CHUNK && resp.value.functionCalls) {
152
+ functionCalls.push(...resp.value.functionCalls);
153
+ }
154
+ }
155
+ }
156
+ catch (error) {
157
+ if (getErrorStatus(error) === 429) {
158
+ throw new acp.RequestError(429, 'Rate limit exceeded. Try again later.');
159
+ }
160
+ throw error;
161
+ }
162
+ if (usageMetadata) {
163
+ const durationMs = Date.now() - streamStartTime;
164
+ await this.messageEmitter.emitUsageMetadata(usageMetadata, '', durationMs);
165
+ }
166
+ if (functionCalls.length > 0) {
167
+ const toolResponseParts = [];
168
+ for (const fc of functionCalls) {
169
+ const response = await this.runTool(pendingSend.signal, promptId, fc);
170
+ toolResponseParts.push(...response);
171
+ }
172
+ nextMessage = { role: 'user', parts: toolResponseParts };
173
+ }
174
+ }
175
+ return { stopReason: 'end_turn' };
176
+ }
177
+ async sendUpdate(update) {
178
+ const params = {
179
+ sessionId: this.sessionId,
180
+ update,
181
+ };
182
+ await this.client.sessionUpdate(params);
183
+ }
184
+ async sendAvailableCommandsUpdate() {
185
+ const abortController = new AbortController();
186
+ try {
187
+ const slashCommands = await getAvailableCommands(this.config, this.settings, abortController.signal, ALLOWED_BUILTIN_COMMANDS_FOR_ACP);
188
+ // Convert SlashCommand[] to AvailableCommand[] format for ACP protocol
189
+ const availableCommands = slashCommands.map((cmd) => ({
190
+ name: cmd.name,
191
+ description: cmd.description,
192
+ input: null,
193
+ }));
194
+ const update = {
195
+ sessionUpdate: 'available_commands_update',
196
+ availableCommands,
197
+ };
198
+ await this.sendUpdate(update);
199
+ }
200
+ catch (error) {
201
+ // Log error but don't fail session creation
202
+ console.error('Error sending available commands update:', error);
203
+ }
204
+ }
205
+ /**
206
+ * Requests permission from the client for a tool call.
207
+ * Used by SubAgentTracker for sub-agent approval requests.
208
+ */
209
+ async requestPermission(params) {
210
+ return this.client.requestPermission(params);
211
+ }
212
+ /**
213
+ * Sets the approval mode for the current session.
214
+ * Maps ACP approval mode values to core ApprovalMode enum.
215
+ */
216
+ async setMode(params) {
217
+ const modeMap = {
218
+ plan: ApprovalMode.PLAN,
219
+ default: ApprovalMode.DEFAULT,
220
+ 'auto-edit': ApprovalMode.AUTO_EDIT,
221
+ yolo: ApprovalMode.YOLO,
222
+ };
223
+ const approvalMode = modeMap[params.modeId];
224
+ this.config.setApprovalMode(approvalMode);
225
+ return { modeId: params.modeId };
226
+ }
227
+ /**
228
+ * Sends a current_mode_update notification to the client.
229
+ * Called after the agent switches modes (e.g., from exit_plan_mode tool).
230
+ */
231
+ async sendCurrentModeUpdateNotification(outcome) {
232
+ // Determine the new mode based on the approval outcome
233
+ // This mirrors the logic in ExitPlanModeTool.onConfirm
234
+ let newModeId;
235
+ switch (outcome) {
236
+ case ToolConfirmationOutcome.ProceedAlways:
237
+ newModeId = 'auto-edit';
238
+ break;
239
+ case ToolConfirmationOutcome.ProceedOnce:
240
+ default:
241
+ newModeId = 'default';
242
+ break;
243
+ }
244
+ const update = {
245
+ sessionUpdate: 'current_mode_update',
246
+ modeId: newModeId,
247
+ };
248
+ await this.sendUpdate(update);
249
+ }
250
+ async runTool(abortSignal, promptId, fc) {
251
+ const callId = fc.id ?? `${fc.name}-${Date.now()}`;
252
+ const args = (fc.args ?? {});
253
+ const startTime = Date.now();
254
+ const errorResponse = (error) => {
255
+ const durationMs = Date.now() - startTime;
256
+ logToolCall(this.config, {
257
+ 'event.name': 'tool_call',
258
+ 'event.timestamp': new Date().toISOString(),
259
+ prompt_id: promptId,
260
+ function_name: fc.name ?? '',
261
+ function_args: args,
262
+ duration_ms: durationMs,
263
+ status: 'error',
264
+ success: false,
265
+ error: error.message,
266
+ tool_type: typeof tool !== 'undefined' && tool instanceof DiscoveredMCPTool
267
+ ? 'mcp'
268
+ : 'native',
269
+ });
270
+ return [
271
+ {
272
+ functionResponse: {
273
+ id: callId,
274
+ name: fc.name ?? '',
275
+ response: { error: error.message },
276
+ },
277
+ },
278
+ ];
279
+ };
280
+ if (!fc.name) {
281
+ return errorResponse(new Error('Missing function name'));
282
+ }
283
+ const toolRegistry = this.config.getToolRegistry();
284
+ const tool = toolRegistry.getTool(fc.name);
285
+ if (!tool) {
286
+ return errorResponse(new Error(`Tool "${fc.name}" not found in registry.`));
287
+ }
288
+ // Detect TodoWriteTool early - route to plan updates instead of tool_call events
289
+ const isTodoWriteTool = tool.name === TodoWriteTool.Name;
290
+ const isTaskTool = tool.name === TaskTool.Name;
291
+ const isExitPlanModeTool = tool.name === ExitPlanModeTool.Name;
292
+ // Track cleanup functions for sub-agent event listeners
293
+ let subAgentCleanupFunctions = [];
294
+ try {
295
+ const invocation = tool.build(args);
296
+ if (isTaskTool && 'eventEmitter' in invocation) {
297
+ // Access eventEmitter from TaskTool invocation
298
+ const taskEventEmitter = invocation.eventEmitter;
299
+ // Create a SubAgentTracker for this tool execution
300
+ const subAgentTracker = new SubAgentTracker(this, this.client);
301
+ // Set up sub-agent tool tracking
302
+ subAgentCleanupFunctions = subAgentTracker.setup(taskEventEmitter, abortSignal);
303
+ }
304
+ const confirmationDetails = this.config.getApprovalMode() !== ApprovalMode.YOLO
305
+ ? await invocation.shouldConfirmExecute(abortSignal)
306
+ : false;
307
+ if (confirmationDetails) {
308
+ const content = [];
309
+ if (confirmationDetails.type === 'edit') {
310
+ content.push({
311
+ type: 'diff',
312
+ path: confirmationDetails.fileName,
313
+ oldText: confirmationDetails.originalContent,
314
+ newText: confirmationDetails.newContent,
315
+ });
316
+ }
317
+ // Add plan content for exit_plan_mode
318
+ if (confirmationDetails.type === 'plan') {
319
+ content.push({
320
+ type: 'content',
321
+ content: {
322
+ type: 'text',
323
+ text: confirmationDetails.plan,
324
+ },
325
+ });
326
+ }
327
+ // Map tool kind, using switch_mode for exit_plan_mode per ACP spec
328
+ const mappedKind = this.toolCallEmitter.mapToolKind(tool.kind, fc.name);
329
+ const params = {
330
+ sessionId: this.sessionId,
331
+ options: toPermissionOptions(confirmationDetails),
332
+ toolCall: {
333
+ toolCallId: callId,
334
+ status: 'pending',
335
+ title: invocation.getDescription(),
336
+ content,
337
+ locations: invocation.toolLocations(),
338
+ kind: mappedKind,
339
+ },
340
+ };
341
+ const output = await this.client.requestPermission(params);
342
+ const outcome = output.outcome.outcome === 'cancelled'
343
+ ? ToolConfirmationOutcome.Cancel
344
+ : z
345
+ .nativeEnum(ToolConfirmationOutcome)
346
+ .parse(output.outcome.optionId);
347
+ await confirmationDetails.onConfirm(outcome);
348
+ // After exit_plan_mode confirmation, send current_mode_update notification
349
+ if (isExitPlanModeTool && outcome !== ToolConfirmationOutcome.Cancel) {
350
+ await this.sendCurrentModeUpdateNotification(outcome);
351
+ }
352
+ switch (outcome) {
353
+ case ToolConfirmationOutcome.Cancel:
354
+ return errorResponse(new Error(`Tool "${fc.name}" was canceled by the user.`));
355
+ case ToolConfirmationOutcome.ProceedOnce:
356
+ case ToolConfirmationOutcome.ProceedAlways:
357
+ case ToolConfirmationOutcome.ProceedAlwaysServer:
358
+ case ToolConfirmationOutcome.ProceedAlwaysTool:
359
+ case ToolConfirmationOutcome.ModifyWithEditor:
360
+ break;
361
+ default: {
362
+ const resultOutcome = outcome;
363
+ throw new Error(`Unexpected: ${resultOutcome}`);
364
+ }
365
+ }
366
+ }
367
+ else if (!isTodoWriteTool) {
368
+ // Skip tool_call event for TodoWriteTool - use ToolCallEmitter
369
+ const startParams = {
370
+ callId,
371
+ toolName: fc.name,
372
+ args,
373
+ status: 'in_progress',
374
+ };
375
+ await this.toolCallEmitter.emitStart(startParams);
376
+ }
377
+ const toolResult = await invocation.execute(abortSignal);
378
+ // Clean up event listeners
379
+ subAgentCleanupFunctions.forEach((cleanup) => cleanup());
380
+ // Create response parts first (needed for emitResult and recordToolResult)
381
+ const responseParts = convertToFunctionResponse(fc.name, callId, toolResult.llmContent);
382
+ // Handle TodoWriteTool: extract todos and send plan update
383
+ if (isTodoWriteTool) {
384
+ const todos = this.planEmitter.extractTodos(toolResult.returnDisplay, args);
385
+ // Match original logic: emit plan if todos.length > 0 OR if args had todos
386
+ if ((todos && todos.length > 0) || Array.isArray(args['todos'])) {
387
+ await this.planEmitter.emitPlan(todos ?? []);
388
+ }
389
+ // Skip tool_call_update event for TodoWriteTool
390
+ // Still log and return function response for LLM
391
+ }
392
+ else {
393
+ // Normal tool handling: emit result using ToolCallEmitter
394
+ // Convert toolResult.error to Error type if present
395
+ const error = toolResult.error
396
+ ? new Error(toolResult.error.message)
397
+ : undefined;
398
+ await this.toolCallEmitter.emitResult({
399
+ callId,
400
+ toolName: fc.name,
401
+ args,
402
+ message: responseParts,
403
+ resultDisplay: toolResult.returnDisplay,
404
+ error,
405
+ success: !toolResult.error,
406
+ });
407
+ }
408
+ const durationMs = Date.now() - startTime;
409
+ logToolCall(this.config, {
410
+ 'event.name': 'tool_call',
411
+ 'event.timestamp': new Date().toISOString(),
412
+ function_name: fc.name,
413
+ function_args: args,
414
+ duration_ms: durationMs,
415
+ status: 'success',
416
+ success: true,
417
+ prompt_id: promptId,
418
+ tool_type: typeof tool !== 'undefined' && tool instanceof DiscoveredMCPTool
419
+ ? 'mcp'
420
+ : 'native',
421
+ });
422
+ // Record tool result for session management
423
+ this.config.getChatRecordingService()?.recordToolResult(responseParts, {
424
+ callId,
425
+ status: 'success',
426
+ resultDisplay: toolResult.returnDisplay,
427
+ error: undefined,
428
+ errorType: undefined,
429
+ });
430
+ return responseParts;
431
+ }
432
+ catch (e) {
433
+ // Ensure cleanup on error
434
+ subAgentCleanupFunctions.forEach((cleanup) => cleanup());
435
+ const error = e instanceof Error ? e : new Error(String(e));
436
+ // Use ToolCallEmitter for error handling
437
+ await this.toolCallEmitter.emitError(callId, error);
438
+ // Record tool error for session management
439
+ const errorParts = [
440
+ {
441
+ functionResponse: {
442
+ id: callId,
443
+ name: fc.name ?? '',
444
+ response: { error: error.message },
445
+ },
446
+ },
447
+ ];
448
+ this.config.getChatRecordingService()?.recordToolResult(errorParts, {
449
+ callId,
450
+ status: 'error',
451
+ resultDisplay: undefined,
452
+ error,
453
+ errorType: undefined,
454
+ });
455
+ return errorResponse(error);
456
+ }
457
+ }
458
+ async #resolvePrompt(message, abortSignal) {
459
+ const FILE_URI_SCHEME = 'file://';
460
+ const embeddedContext = [];
461
+ const parts = message.map((part) => {
462
+ switch (part.type) {
463
+ case 'text':
464
+ return { text: part.text };
465
+ case 'image':
466
+ case 'audio':
467
+ return {
468
+ inlineData: {
469
+ mimeType: part.mimeType,
470
+ data: part.data,
471
+ },
472
+ };
473
+ case 'resource_link': {
474
+ if (part.uri.startsWith(FILE_URI_SCHEME)) {
475
+ return {
476
+ fileData: {
477
+ mimeData: part.mimeType,
478
+ name: part.name,
479
+ fileUri: part.uri.slice(FILE_URI_SCHEME.length),
480
+ },
481
+ };
482
+ }
483
+ else {
484
+ return { text: `@${part.uri}` };
485
+ }
486
+ }
487
+ case 'resource': {
488
+ embeddedContext.push(part.resource);
489
+ return { text: `@${part.resource.uri}` };
490
+ }
491
+ default: {
492
+ const unreachable = part;
493
+ throw new Error(`Unexpected chunk type: '${unreachable}'`);
494
+ }
495
+ }
496
+ });
497
+ const atPathCommandParts = parts.filter((part) => 'fileData' in part);
498
+ if (atPathCommandParts.length === 0 && embeddedContext.length === 0) {
499
+ return parts;
500
+ }
501
+ const atPathToResolvedSpecMap = new Map();
502
+ // Get centralized file discovery service
503
+ const fileDiscovery = this.config.getFileService();
504
+ const respectGitIgnore = this.config.getFileFilteringRespectGitIgnore();
505
+ const pathSpecsToRead = [];
506
+ const contentLabelsForDisplay = [];
507
+ const ignoredPaths = [];
508
+ const toolRegistry = this.config.getToolRegistry();
509
+ const readManyFilesTool = toolRegistry.getTool('read_many_files');
510
+ const globTool = toolRegistry.getTool('glob');
511
+ if (!readManyFilesTool) {
512
+ throw new Error('Error: read_many_files tool not found.');
513
+ }
514
+ for (const atPathPart of atPathCommandParts) {
515
+ const pathName = atPathPart.fileData.fileUri;
516
+ // Check if path should be ignored by git
517
+ if (fileDiscovery.shouldGitIgnoreFile(pathName)) {
518
+ ignoredPaths.push(pathName);
519
+ const reason = respectGitIgnore
520
+ ? 'git-ignored and will be skipped'
521
+ : 'ignored by custom patterns';
522
+ console.warn(`Path ${pathName} is ${reason}.`);
523
+ continue;
524
+ }
525
+ let currentPathSpec = pathName;
526
+ let resolvedSuccessfully = false;
527
+ try {
528
+ const absolutePath = path.resolve(this.config.getTargetDir(), pathName);
529
+ if (isWithinRoot(absolutePath, this.config.getTargetDir())) {
530
+ const stats = await fs.stat(absolutePath);
531
+ if (stats.isDirectory()) {
532
+ currentPathSpec = pathName.endsWith('/')
533
+ ? `${pathName}**`
534
+ : `${pathName}/**`;
535
+ this.debug(`Path ${pathName} resolved to directory, using glob: ${currentPathSpec}`);
536
+ }
537
+ else {
538
+ this.debug(`Path ${pathName} resolved to file: ${currentPathSpec}`);
539
+ }
540
+ resolvedSuccessfully = true;
541
+ }
542
+ else {
543
+ this.debug(`Path ${pathName} is outside the project directory. Skipping.`);
544
+ }
545
+ }
546
+ catch (error) {
547
+ if (isNodeError(error) && error.code === 'ENOENT') {
548
+ if (this.config.getEnableRecursiveFileSearch() && globTool) {
549
+ this.debug(`Path ${pathName} not found directly, attempting glob search.`);
550
+ try {
551
+ const globResult = await globTool.buildAndExecute({
552
+ pattern: `**/*${pathName}*`,
553
+ path: this.config.getTargetDir(),
554
+ }, abortSignal);
555
+ if (globResult.llmContent &&
556
+ typeof globResult.llmContent === 'string' &&
557
+ !globResult.llmContent.startsWith('No files found') &&
558
+ !globResult.llmContent.startsWith('Error:')) {
559
+ const lines = globResult.llmContent.split('\n');
560
+ if (lines.length > 1 && lines[1]) {
561
+ const firstMatchAbsolute = lines[1].trim();
562
+ currentPathSpec = path.relative(this.config.getTargetDir(), firstMatchAbsolute);
563
+ this.debug(`Glob search for ${pathName} found ${firstMatchAbsolute}, using relative path: ${currentPathSpec}`);
564
+ resolvedSuccessfully = true;
565
+ }
566
+ else {
567
+ this.debug(`Glob search for '**/*${pathName}*' did not return a usable path. Path ${pathName} will be skipped.`);
568
+ }
569
+ }
570
+ else {
571
+ this.debug(`Glob search for '**/*${pathName}*' found no files or an error. Path ${pathName} will be skipped.`);
572
+ }
573
+ }
574
+ catch (globError) {
575
+ console.error(`Error during glob search for ${pathName}: ${getErrorMessage(globError)}`);
576
+ }
577
+ }
578
+ else {
579
+ this.debug(`Glob tool not found. Path ${pathName} will be skipped.`);
580
+ }
581
+ }
582
+ else {
583
+ console.error(`Error stating path ${pathName}. Path ${pathName} will be skipped.`);
584
+ }
585
+ }
586
+ if (resolvedSuccessfully) {
587
+ pathSpecsToRead.push(currentPathSpec);
588
+ atPathToResolvedSpecMap.set(pathName, currentPathSpec);
589
+ contentLabelsForDisplay.push(pathName);
590
+ }
591
+ }
592
+ // Construct the initial part of the query for the LLM
593
+ let initialQueryText = '';
594
+ for (let i = 0; i < parts.length; i++) {
595
+ const chunk = parts[i];
596
+ if ('text' in chunk) {
597
+ initialQueryText += chunk.text;
598
+ }
599
+ else {
600
+ // type === 'atPath'
601
+ const resolvedSpec = chunk.fileData && atPathToResolvedSpecMap.get(chunk.fileData.fileUri);
602
+ if (i > 0 &&
603
+ initialQueryText.length > 0 &&
604
+ !initialQueryText.endsWith(' ') &&
605
+ resolvedSpec) {
606
+ // Add space if previous part was text and didn't end with space, or if previous was @path
607
+ const prevPart = parts[i - 1];
608
+ if ('text' in prevPart ||
609
+ ('fileData' in prevPart &&
610
+ atPathToResolvedSpecMap.has(prevPart.fileData.fileUri))) {
611
+ initialQueryText += ' ';
612
+ }
613
+ }
614
+ // Append the resolved path spec for display purposes
615
+ if (resolvedSpec) {
616
+ initialQueryText += `@${resolvedSpec}`;
617
+ }
618
+ }
619
+ }
620
+ // Handle ignored paths message
621
+ let ignoredPathsMessage = '';
622
+ if (ignoredPaths.length > 0) {
623
+ const pathList = ignoredPaths.map((p) => `- ${p}`).join('\n');
624
+ ignoredPathsMessage = `Note: The following paths were skipped because they are ignored:\n${pathList}\n\n`;
625
+ }
626
+ const processedQueryParts = [];
627
+ // Read files using read_many_files tool
628
+ if (pathSpecsToRead.length > 0) {
629
+ const readResult = await readManyFilesTool.buildAndExecute({
630
+ paths_with_line_ranges: pathSpecsToRead,
631
+ }, abortSignal);
632
+ const contentForLlm = typeof readResult.llmContent === 'string'
633
+ ? readResult.llmContent
634
+ : JSON.stringify(readResult.llmContent);
635
+ // Combine content label, ignored paths message, file content, and user query
636
+ const combinedText = `${ignoredPathsMessage}${contentForLlm}`.trim();
637
+ processedQueryParts.push({ text: combinedText });
638
+ processedQueryParts.push({ text: initialQueryText });
639
+ }
640
+ else if (embeddedContext.length > 0) {
641
+ // No @path files to read, but we have embedded context
642
+ processedQueryParts.push({
643
+ text: `${ignoredPathsMessage}${initialQueryText}`.trim(),
644
+ });
645
+ }
646
+ else {
647
+ // No @path files found or resolved
648
+ processedQueryParts.push({
649
+ text: `${ignoredPathsMessage}${initialQueryText}`.trim(),
650
+ });
651
+ }
652
+ // Process embedded context from resource blocks
653
+ for (const contextPart of embeddedContext) {
654
+ // Type guard for text resources
655
+ if ('text' in contextPart && contextPart.text) {
656
+ processedQueryParts.push({
657
+ text: `File: ${contextPart.uri}\n${contextPart.text}`,
658
+ });
659
+ }
660
+ // Type guard for blob resources
661
+ if ('blob' in contextPart && contextPart.blob) {
662
+ processedQueryParts.push({
663
+ inlineData: {
664
+ mimeType: contextPart.mimeType ?? 'application/octet-stream',
665
+ data: contextPart.blob,
666
+ },
667
+ });
668
+ }
669
+ }
670
+ return processedQueryParts;
671
+ }
672
+ debug(msg) {
673
+ if (this.config.getDebugMode()) {
674
+ console.warn(msg);
675
+ }
676
+ }
677
+ }
678
+ // ============================================================================
679
+ // Helper functions
680
+ // ============================================================================
681
+ const basicPermissionOptions = [
682
+ {
683
+ optionId: ToolConfirmationOutcome.ProceedOnce,
684
+ name: 'Allow',
685
+ kind: 'allow_once',
686
+ },
687
+ {
688
+ optionId: ToolConfirmationOutcome.Cancel,
689
+ name: 'Reject',
690
+ kind: 'reject_once',
691
+ },
692
+ ];
693
+ function toPermissionOptions(confirmation) {
694
+ switch (confirmation.type) {
695
+ case 'edit':
696
+ return [
697
+ {
698
+ optionId: ToolConfirmationOutcome.ProceedAlways,
699
+ name: 'Allow All Edits',
700
+ kind: 'allow_always',
701
+ },
702
+ ...basicPermissionOptions,
703
+ ];
704
+ case 'exec':
705
+ return [
706
+ {
707
+ optionId: ToolConfirmationOutcome.ProceedAlways,
708
+ name: `Always Allow ${confirmation.rootCommand}`,
709
+ kind: 'allow_always',
710
+ },
711
+ ...basicPermissionOptions,
712
+ ];
713
+ case 'mcp':
714
+ return [
715
+ {
716
+ optionId: ToolConfirmationOutcome.ProceedAlwaysServer,
717
+ name: `Always Allow ${confirmation.serverName}`,
718
+ kind: 'allow_always',
719
+ },
720
+ {
721
+ optionId: ToolConfirmationOutcome.ProceedAlwaysTool,
722
+ name: `Always Allow ${confirmation.toolName}`,
723
+ kind: 'allow_always',
724
+ },
725
+ ...basicPermissionOptions,
726
+ ];
727
+ case 'info':
728
+ return [
729
+ {
730
+ optionId: ToolConfirmationOutcome.ProceedAlways,
731
+ name: `Always Allow`,
732
+ kind: 'allow_always',
733
+ },
734
+ ...basicPermissionOptions,
735
+ ];
736
+ case 'plan':
737
+ return [
738
+ {
739
+ optionId: ToolConfirmationOutcome.ProceedAlways,
740
+ name: `Yes, and auto-accept edits`,
741
+ kind: 'allow_always',
742
+ },
743
+ {
744
+ optionId: ToolConfirmationOutcome.ProceedOnce,
745
+ name: `Yes, and manually approve edits`,
746
+ kind: 'allow_once',
747
+ },
748
+ {
749
+ optionId: ToolConfirmationOutcome.Cancel,
750
+ name: `No, keep planning (esc)`,
751
+ kind: 'reject_once',
752
+ },
753
+ ];
754
+ default: {
755
+ const unreachable = confirmation;
756
+ throw new Error(`Unexpected: ${unreachable}`);
757
+ }
758
+ }
759
+ }
760
+ //# sourceMappingURL=Session.js.map