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