@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
@@ -12,19 +12,7 @@ import { isCLIUserMessage, isCLIAssistantMessage, isCLISystemMessage, isCLIResul
12
12
  import { createMinimalSettings } from '../config/settings.js';
13
13
  import { runNonInteractive } from '../nonInteractiveCli.js';
14
14
  import { ConsolePatcher } from '../ui/utils/ConsolePatcher.js';
15
- const SESSION_STATE = {
16
- INITIALIZING: 'initializing',
17
- IDLE: 'idle',
18
- PROCESSING_QUERY: 'processing_query',
19
- SHUTTING_DOWN: 'shutting_down',
20
- };
21
- /**
22
- * Session Manager
23
- *
24
- * Manages the session lifecycle and message processing state machine.
25
- */
26
- class SessionManager {
27
- state = SESSION_STATE.INITIALIZING;
15
+ class Session {
28
16
  userMessageQueue = [];
29
17
  abortController;
30
18
  config;
@@ -39,6 +27,14 @@ class SessionManager {
39
27
  debugMode;
40
28
  shutdownHandler = null;
41
29
  initialPrompt = null;
30
+ processingPromise = null;
31
+ isShuttingDown = false;
32
+ configInitialized = false;
33
+ // Single initialization promise that resolves when session is ready for user messages.
34
+ // Created lazily once initialization actually starts.
35
+ initializationPromise = null;
36
+ initializationResolve = null;
37
+ initializationReject = null;
42
38
  constructor(config, initialPrompt) {
43
39
  this.config = config;
44
40
  this.sessionId = config.getSessionId();
@@ -47,135 +43,86 @@ class SessionManager {
47
43
  this.initialPrompt = initialPrompt ?? null;
48
44
  this.inputReader = new StreamJsonInputReader();
49
45
  this.outputAdapter = new StreamJsonOutputAdapter(config, config.getIncludePartialMessages());
50
- // Setup signal handlers for graceful shutdown
51
46
  this.setupSignalHandlers();
52
47
  }
53
- /**
54
- * Get next prompt ID
55
- */
48
+ ensureInitializationPromise() {
49
+ if (this.initializationPromise) {
50
+ return;
51
+ }
52
+ this.initializationPromise = new Promise((resolve, reject) => {
53
+ this.initializationResolve = () => {
54
+ resolve();
55
+ this.initializationResolve = null;
56
+ this.initializationReject = null;
57
+ };
58
+ this.initializationReject = (error) => {
59
+ reject(error);
60
+ this.initializationResolve = null;
61
+ this.initializationReject = null;
62
+ };
63
+ });
64
+ }
56
65
  getNextPromptId() {
57
66
  this.promptIdCounter++;
58
67
  return `${this.sessionId}########${this.promptIdCounter}`;
59
68
  }
60
- /**
61
- * Route a message to the appropriate handler based on its type
62
- *
63
- * Classifies incoming messages and routes them to appropriate handlers.
64
- */
65
- route(message) {
66
- // Check control messages first
67
- if (isControlRequest(message)) {
68
- return { type: 'control_request', message };
69
- }
70
- if (isControlResponse(message)) {
71
- return { type: 'control_response', message };
72
- }
73
- if (isControlCancel(message)) {
74
- return { type: 'control_cancel', message };
75
- }
76
- // Check data messages
77
- if (isCLIUserMessage(message)) {
78
- return { type: 'user', message };
79
- }
80
- if (isCLIAssistantMessage(message)) {
81
- return { type: 'assistant', message };
82
- }
83
- if (isCLISystemMessage(message)) {
84
- return { type: 'system', message };
69
+ async ensureConfigInitialized(options) {
70
+ if (this.configInitialized) {
71
+ return;
85
72
  }
86
- if (isCLIResultMessage(message)) {
87
- return { type: 'result', message };
73
+ if (this.debugMode) {
74
+ console.error('[Session] Initializing config');
88
75
  }
89
- if (isCLIPartialAssistantMessage(message)) {
90
- return { type: 'stream_event', message };
76
+ try {
77
+ await this.config.initialize(options);
78
+ this.configInitialized = true;
91
79
  }
92
- // Unknown message type
93
- if (this.debugMode) {
94
- console.error('[SessionManager] Unknown message type:', JSON.stringify(message, null, 2));
80
+ catch (error) {
81
+ if (this.debugMode) {
82
+ console.error('[Session] Failed to initialize config:', error);
83
+ }
84
+ throw error;
95
85
  }
96
- return { type: 'unknown', message };
97
86
  }
98
87
  /**
99
- * Process a single message with unified logic for both initial prompt and stream messages.
100
- *
101
- * Handles:
102
- * - Abort check
103
- * - First message detection and handling
104
- * - Normal message processing
105
- * - Shutdown state checks
106
- *
107
- * @param message - Message to process
108
- * @returns true if the calling code should exit (break/return), false to continue
88
+ * Mark initialization as complete
109
89
  */
110
- async processSingleMessage(message) {
111
- // Check for abort
112
- if (this.abortController.signal.aborted) {
113
- return true;
114
- }
115
- // Handle first message if control system not yet initialized
116
- if (this.controlSystemEnabled === null) {
117
- const handled = await this.handleFirstMessage(message);
118
- if (handled) {
119
- // If handled, check if we should shutdown
120
- return this.state === SESSION_STATE.SHUTTING_DOWN;
90
+ completeInitialization() {
91
+ if (this.initializationResolve) {
92
+ if (this.debugMode) {
93
+ console.error('[Session] Initialization complete');
121
94
  }
122
- // If not handled, fall through to normal processing
95
+ this.initializationResolve();
96
+ this.initializationResolve = null;
97
+ this.initializationReject = null;
123
98
  }
124
- // Process message normally
125
- await this.processMessage(message);
126
- // Check for shutdown after processing
127
- return this.state === SESSION_STATE.SHUTTING_DOWN;
128
99
  }
129
100
  /**
130
- * Main entry point - run the session
101
+ * Mark initialization as failed
131
102
  */
132
- async run() {
133
- try {
134
- if (this.debugMode) {
135
- console.error('[SessionManager] Starting session', this.sessionId);
136
- }
137
- // Process initial prompt if provided
138
- if (this.initialPrompt !== null) {
139
- const shouldExit = await this.processSingleMessage(this.initialPrompt);
140
- if (shouldExit) {
141
- await this.shutdown();
142
- return;
143
- }
144
- }
145
- // Process messages from stream
146
- for await (const message of this.inputReader.read()) {
147
- const shouldExit = await this.processSingleMessage(message);
148
- if (shouldExit) {
149
- break;
150
- }
151
- }
152
- // Stream closed, shutdown
153
- await this.shutdown();
154
- }
155
- catch (error) {
103
+ failInitialization(error) {
104
+ if (this.initializationReject) {
156
105
  if (this.debugMode) {
157
- console.error('[SessionManager] Error:', error);
106
+ console.error('[Session] Initialization failed:', error);
158
107
  }
159
- await this.shutdown();
160
- throw error;
108
+ this.initializationReject(error);
109
+ this.initializationResolve = null;
110
+ this.initializationReject = null;
161
111
  }
162
- finally {
163
- // Ensure signal handlers are always cleaned up even if shutdown wasn't called
164
- this.cleanupSignalHandlers();
112
+ }
113
+ /**
114
+ * Wait for session to be ready for user messages
115
+ */
116
+ async waitForInitialization() {
117
+ if (!this.initializationPromise) {
118
+ return;
165
119
  }
120
+ await this.initializationPromise;
166
121
  }
167
122
  ensureControlSystem() {
168
123
  if (this.controlContext && this.dispatcher && this.controlService) {
169
124
  return;
170
125
  }
171
- // The control system follows a strict three-layer architecture:
172
- // 1. ControlContext (shared session state)
173
- // 2. ControlDispatcher (protocol routing SDK ↔ CLI)
174
- // 3. ControlService (programmatic API for CLI runtime)
175
- //
176
- // Application code MUST interact with the control plane exclusively through
177
- // ControlService. ControlDispatcher is reserved for protocol-level message
178
- // routing and should never be used directly outside of this file.
179
126
  this.controlContext = new ControlContext({
180
127
  config: this.config,
181
128
  streamJson: this.outputAdapter,
@@ -196,224 +143,133 @@ class SessionManager {
196
143
  }
197
144
  return this.dispatcher;
198
145
  }
199
- async handleFirstMessage(message) {
200
- const routed = this.route(message);
201
- if (routed.type === 'control_request') {
202
- const request = routed.message;
146
+ /**
147
+ * Handle the first message to determine session mode (SDK vs direct).
148
+ * This is synchronous from the message loop's perspective - it starts
149
+ * async work but does not return a promise that the loop awaits.
150
+ *
151
+ * The initialization completes asynchronously and resolves initializationPromise
152
+ * when ready for user messages.
153
+ */
154
+ handleFirstMessage(message) {
155
+ if (isControlRequest(message)) {
156
+ const request = message;
203
157
  this.controlSystemEnabled = true;
204
158
  this.ensureControlSystem();
205
159
  if (request.request.subtype === 'initialize') {
206
- await this.dispatcher?.dispatch(request);
207
- this.state = SESSION_STATE.IDLE;
208
- return true;
160
+ // Start SDK mode initialization (fire-and-forget from loop perspective)
161
+ void this.initializeSdkMode(request);
162
+ return;
209
163
  }
210
- return false;
164
+ if (this.debugMode) {
165
+ console.error('[Session] Ignoring non-initialize control request during initialization');
166
+ }
167
+ return;
211
168
  }
212
- if (routed.type === 'user') {
169
+ if (isCLIUserMessage(message)) {
213
170
  this.controlSystemEnabled = false;
214
- this.state = SESSION_STATE.PROCESSING_QUERY;
215
- this.userMessageQueue.push(routed.message);
216
- await this.processUserMessageQueue();
217
- return true;
171
+ // Start direct mode initialization (fire-and-forget from loop perspective)
172
+ void this.initializeDirectMode(message);
173
+ return;
218
174
  }
219
175
  this.controlSystemEnabled = false;
220
- return false;
221
- }
222
- /**
223
- * Process a single message from the stream
224
- */
225
- async processMessage(message) {
226
- const routed = this.route(message);
227
- if (this.debugMode) {
228
- console.error(`[SessionManager] State: ${this.state}, Message type: ${routed.type}`);
229
- }
230
- switch (this.state) {
231
- case SESSION_STATE.INITIALIZING:
232
- await this.handleInitializingState(routed);
233
- break;
234
- case SESSION_STATE.IDLE:
235
- await this.handleIdleState(routed);
236
- break;
237
- case SESSION_STATE.PROCESSING_QUERY:
238
- await this.handleProcessingState(routed);
239
- break;
240
- case SESSION_STATE.SHUTTING_DOWN:
241
- // Ignore all messages during shutdown
242
- break;
243
- default: {
244
- // Exhaustive check
245
- const _exhaustiveCheck = this.state;
246
- if (this.debugMode) {
247
- console.error('[SessionManager] Unknown state:', _exhaustiveCheck);
248
- }
249
- break;
250
- }
251
- }
252
176
  }
253
177
  /**
254
- * Handle messages in initializing state
178
+ * SDK mode initialization flow
179
+ * Dispatches initialize request and initializes config with MCP support
255
180
  */
256
- async handleInitializingState(routed) {
257
- if (routed.type === 'control_request') {
258
- const request = routed.message;
259
- const dispatcher = this.getDispatcher();
260
- if (!dispatcher) {
261
- if (this.debugMode) {
262
- console.error('[SessionManager] Control request received before control system initialization');
263
- }
264
- return;
265
- }
266
- if (request.request.subtype === 'initialize') {
267
- await dispatcher.dispatch(request);
268
- this.state = SESSION_STATE.IDLE;
269
- if (this.debugMode) {
270
- console.error('[SessionManager] Initialized, transitioning to idle');
271
- }
272
- }
273
- else {
274
- if (this.debugMode) {
275
- console.error('[SessionManager] Ignoring non-initialize control request during initialization');
276
- }
277
- }
181
+ async initializeSdkMode(request) {
182
+ this.ensureInitializationPromise();
183
+ try {
184
+ // Dispatch the initialize request first
185
+ // This registers SDK MCP servers in the control context
186
+ await this.dispatcher?.dispatch(request);
187
+ // Get sendSdkMcpMessage callback from SdkMcpController
188
+ // This callback is used by McpClientManager to send MCP messages
189
+ // from CLI MCP clients to SDK MCP servers via the control plane
190
+ const sendSdkMcpMessage = this.dispatcher?.sdkMcpController.createSendSdkMcpMessage();
191
+ // Initialize config with SDK MCP message support
192
+ await this.ensureConfigInitialized({ sendSdkMcpMessage });
193
+ // Initialization complete!
194
+ this.completeInitialization();
278
195
  }
279
- else {
196
+ catch (error) {
280
197
  if (this.debugMode) {
281
- console.error('[SessionManager] Ignoring non-control message during initialization');
198
+ console.error('[Session] SDK mode initialization failed:', error);
282
199
  }
200
+ this.failInitialization(error instanceof Error ? error : new Error(String(error)));
283
201
  }
284
202
  }
285
203
  /**
286
- * Handle messages in idle state
204
+ * Direct mode initialization flow
205
+ * Initializes config and enqueues the first user message
287
206
  */
288
- async handleIdleState(routed) {
289
- const dispatcher = this.getDispatcher();
290
- if (routed.type === 'control_request') {
291
- if (!dispatcher) {
292
- if (this.debugMode) {
293
- console.error('[SessionManager] Ignoring control request (disabled)');
294
- }
295
- return;
296
- }
297
- const request = routed.message;
298
- await dispatcher.dispatch(request);
299
- // Stay in idle state
300
- }
301
- else if (routed.type === 'control_response') {
302
- if (!dispatcher) {
303
- return;
304
- }
305
- const response = routed.message;
306
- dispatcher.handleControlResponse(response);
307
- // Stay in idle state
308
- }
309
- else if (routed.type === 'control_cancel') {
310
- if (!dispatcher) {
311
- return;
312
- }
313
- const cancelRequest = routed.message;
314
- dispatcher.handleCancel(cancelRequest.request_id);
315
- }
316
- else if (routed.type === 'user') {
317
- const userMessage = routed.message;
318
- this.userMessageQueue.push(userMessage);
319
- // Start processing queue
320
- await this.processUserMessageQueue();
207
+ async initializeDirectMode(userMessage) {
208
+ this.ensureInitializationPromise();
209
+ try {
210
+ // Initialize config
211
+ await this.ensureConfigInitialized();
212
+ // Initialization complete!
213
+ this.completeInitialization();
214
+ // Enqueue the first user message for processing
215
+ this.enqueueUserMessage(userMessage);
321
216
  }
322
- else {
217
+ catch (error) {
323
218
  if (this.debugMode) {
324
- console.error('[SessionManager] Ignoring message type in idle state:', routed.type);
219
+ console.error('[Session] Direct mode initialization failed:', error);
325
220
  }
221
+ this.failInitialization(error instanceof Error ? error : new Error(String(error)));
326
222
  }
327
223
  }
328
224
  /**
329
- * Handle messages in processing state
225
+ * Handle control request asynchronously (fire-and-forget from main loop).
226
+ * Errors are handled internally and responses sent by dispatcher.
330
227
  */
331
- async handleProcessingState(routed) {
228
+ handleControlRequestAsync(request) {
332
229
  const dispatcher = this.getDispatcher();
333
- if (routed.type === 'control_request') {
334
- if (!dispatcher) {
335
- if (this.debugMode) {
336
- console.error('[SessionManager] Control request ignored during processing (disabled)');
337
- }
338
- return;
339
- }
340
- const request = routed.message;
341
- await dispatcher.dispatch(request);
342
- // Continue processing
343
- }
344
- else if (routed.type === 'control_response') {
345
- if (!dispatcher) {
346
- return;
347
- }
348
- const response = routed.message;
349
- dispatcher.handleControlResponse(response);
350
- // Continue processing
351
- }
352
- else if (routed.type === 'user') {
353
- // Enqueue for later
354
- const userMessage = routed.message;
355
- this.userMessageQueue.push(userMessage);
230
+ if (!dispatcher) {
356
231
  if (this.debugMode) {
357
- console.error('[SessionManager] Enqueued user message during processing');
232
+ console.error('[Session] Control system not enabled');
358
233
  }
234
+ return;
359
235
  }
360
- else {
236
+ // Fire-and-forget: dispatch runs concurrently
237
+ // The dispatcher's pendingIncomingRequests tracks completion
238
+ void dispatcher.dispatch(request).catch((error) => {
361
239
  if (this.debugMode) {
362
- console.error('[SessionManager] Ignoring message type during processing:', routed.type);
240
+ console.error('[Session] Control request dispatch error:', error);
363
241
  }
364
- }
242
+ // Error response is already sent by dispatcher.dispatch()
243
+ });
365
244
  }
366
245
  /**
367
- * Process user message queue (FIFO)
246
+ * Handle control response - MUST be synchronous
247
+ * This resolves pending outgoing requests, breaking the deadlock cycle.
368
248
  */
369
- async processUserMessageQueue() {
370
- while (this.userMessageQueue.length > 0 &&
371
- !this.abortController.signal.aborted) {
372
- this.state = SESSION_STATE.PROCESSING_QUERY;
373
- const userMessage = this.userMessageQueue.shift();
374
- try {
375
- await this.processUserMessage(userMessage);
376
- }
377
- catch (error) {
378
- if (this.debugMode) {
379
- console.error('[SessionManager] Error processing user message:', error);
380
- }
381
- // Send error result
382
- this.emitErrorResult(error);
383
- }
384
- }
385
- // If control system is disabled (single-query mode) and queue is empty,
386
- // automatically shutdown instead of returning to idle
387
- if (!this.abortController.signal.aborted &&
388
- this.state === SESSION_STATE.PROCESSING_QUERY &&
389
- this.controlSystemEnabled === false &&
390
- this.userMessageQueue.length === 0) {
391
- if (this.debugMode) {
392
- console.error('[SessionManager] Single-query mode: queue processed, shutting down');
393
- }
394
- this.state = SESSION_STATE.SHUTTING_DOWN;
249
+ handleControlResponse(response) {
250
+ const dispatcher = this.getDispatcher();
251
+ if (!dispatcher) {
395
252
  return;
396
253
  }
397
- // Return to idle after processing queue (for multi-query mode with control system)
398
- if (!this.abortController.signal.aborted &&
399
- this.state === SESSION_STATE.PROCESSING_QUERY) {
400
- this.state = SESSION_STATE.IDLE;
401
- if (this.debugMode) {
402
- console.error('[SessionManager] Queue processed, returning to idle');
403
- }
254
+ dispatcher.handleControlResponse(response);
255
+ }
256
+ handleControlCancel(cancelRequest) {
257
+ const dispatcher = this.getDispatcher();
258
+ if (!dispatcher) {
259
+ return;
404
260
  }
261
+ dispatcher.handleCancel(cancelRequest.request_id);
405
262
  }
406
- /**
407
- * Process a single user message
408
- */
409
263
  async processUserMessage(userMessage) {
410
264
  const input = extractUserMessageText(userMessage);
411
265
  if (!input) {
412
266
  if (this.debugMode) {
413
- console.error('[SessionManager] No text content in user message');
267
+ console.error('[Session] No text content in user message');
414
268
  }
415
269
  return;
416
270
  }
271
+ // Wait for initialization to complete before processing user messages
272
+ await this.waitForInitialization();
417
273
  const promptId = this.getNextPromptId();
418
274
  try {
419
275
  await runNonInteractive(this.config, createMinimalSettings(), input, promptId, {
@@ -423,15 +279,47 @@ class SessionManager {
423
279
  });
424
280
  }
425
281
  catch (error) {
426
- // Error already handled by runNonInteractive via adapter.emitResult
427
282
  if (this.debugMode) {
428
- console.error('[SessionManager] Query execution error:', error);
283
+ console.error('[Session] Query execution error:', error);
429
284
  }
430
285
  }
431
286
  }
432
- /**
433
- * Send tool results as user message
434
- */
287
+ async processUserMessageQueue() {
288
+ if (this.isShuttingDown || this.abortController.signal.aborted) {
289
+ return;
290
+ }
291
+ while (this.userMessageQueue.length > 0 &&
292
+ !this.isShuttingDown &&
293
+ !this.abortController.signal.aborted) {
294
+ const userMessage = this.userMessageQueue.shift();
295
+ try {
296
+ await this.processUserMessage(userMessage);
297
+ }
298
+ catch (error) {
299
+ if (this.debugMode) {
300
+ console.error('[Session] Error processing user message:', error);
301
+ }
302
+ this.emitErrorResult(error);
303
+ }
304
+ }
305
+ }
306
+ enqueueUserMessage(userMessage) {
307
+ this.userMessageQueue.push(userMessage);
308
+ this.ensureProcessingStarted();
309
+ }
310
+ ensureProcessingStarted() {
311
+ if (this.processingPromise) {
312
+ return;
313
+ }
314
+ this.processingPromise = this.processUserMessageQueue().finally(() => {
315
+ this.processingPromise = null;
316
+ if (this.userMessageQueue.length > 0 &&
317
+ !this.isShuttingDown &&
318
+ !this.abortController.signal.aborted) {
319
+ this.ensureProcessingStarted();
320
+ }
321
+ });
322
+ }
435
323
  emitErrorResult(error, numTurns = 0, durationMs = 0, apiDurationMs = 0) {
436
324
  const message = error instanceof Error ? error.message : String(error);
437
325
  this.outputAdapter.emitResult({
@@ -443,47 +331,70 @@ class SessionManager {
443
331
  usage: undefined,
444
332
  });
445
333
  }
446
- /**
447
- * Handle interrupt control request
448
- */
449
334
  handleInterrupt() {
450
335
  if (this.debugMode) {
451
- console.error('[SessionManager] Interrupt requested');
452
- }
453
- // Abort current query if processing
454
- if (this.state === SESSION_STATE.PROCESSING_QUERY) {
455
- this.abortController.abort();
456
- this.abortController = new AbortController(); // Create new controller for next query
336
+ console.error('[Session] Interrupt requested');
457
337
  }
338
+ this.abortController.abort();
339
+ this.abortController = new AbortController();
458
340
  }
459
- /**
460
- * Setup signal handlers for graceful shutdown
461
- */
462
341
  setupSignalHandlers() {
463
342
  this.shutdownHandler = () => {
464
343
  if (this.debugMode) {
465
- console.error('[SessionManager] Shutdown signal received');
344
+ console.error('[Session] Shutdown signal received');
466
345
  }
346
+ this.isShuttingDown = true;
467
347
  this.abortController.abort();
468
- this.state = SESSION_STATE.SHUTTING_DOWN;
469
348
  };
470
349
  process.on('SIGINT', this.shutdownHandler);
471
350
  process.on('SIGTERM', this.shutdownHandler);
472
351
  }
473
352
  /**
474
- * Shutdown session and cleanup resources
353
+ * Wait for all pending work to complete before shutdown
475
354
  */
355
+ async waitForAllPendingWork() {
356
+ // 1. Wait for initialization to complete (or fail)
357
+ try {
358
+ await this.waitForInitialization();
359
+ }
360
+ catch (error) {
361
+ if (this.debugMode) {
362
+ console.error('[Session] Initialization error during shutdown:', error);
363
+ }
364
+ }
365
+ // 2. Wait for all control request handlers using dispatcher's tracking
366
+ if (this.dispatcher) {
367
+ const pendingCount = this.dispatcher.getPendingIncomingRequestCount();
368
+ if (pendingCount > 0 && this.debugMode) {
369
+ console.error(`[Session] Waiting for ${pendingCount} pending control request handlers`);
370
+ }
371
+ await this.dispatcher.waitForPendingIncomingRequests();
372
+ }
373
+ // 3. Wait for user message processing queue
374
+ while (this.processingPromise) {
375
+ if (this.debugMode) {
376
+ console.error('[Session] Waiting for user message processing');
377
+ }
378
+ try {
379
+ await this.processingPromise;
380
+ }
381
+ catch (error) {
382
+ if (this.debugMode) {
383
+ console.error('[Session] Error in user message processing:', error);
384
+ }
385
+ }
386
+ }
387
+ }
476
388
  async shutdown() {
477
389
  if (this.debugMode) {
478
- console.error('[SessionManager] Shutting down');
390
+ console.error('[Session] Shutting down');
479
391
  }
480
- this.state = SESSION_STATE.SHUTTING_DOWN;
392
+ this.isShuttingDown = true;
393
+ // Wait for all pending work
394
+ await this.waitForAllPendingWork();
481
395
  this.dispatcher?.shutdown();
482
396
  this.cleanupSignalHandlers();
483
397
  }
484
- /**
485
- * Remove signal handlers to prevent memory leaks
486
- */
487
398
  cleanupSignalHandlers() {
488
399
  if (this.shutdownHandler) {
489
400
  process.removeListener('SIGINT', this.shutdownHandler);
@@ -491,6 +402,98 @@ class SessionManager {
491
402
  this.shutdownHandler = null;
492
403
  }
493
404
  }
405
+ /**
406
+ * Main message processing loop
407
+ *
408
+ * CRITICAL: This loop must NEVER await handlers that might need to
409
+ * send control requests and wait for responses. Such handlers must
410
+ * be started in fire-and-forget mode, allowing the loop to continue
411
+ * reading responses that resolve pending requests.
412
+ *
413
+ * Message handling order:
414
+ * 1. control_response - FIRST, synchronously resolves pending requests
415
+ * 2. First message - determines mode, starts async initialization
416
+ * 3. control_request - fire-and-forget, tracked by dispatcher
417
+ * 4. control_cancel - synchronous
418
+ * 5. user_message - enqueued for processing
419
+ */
420
+ async run() {
421
+ try {
422
+ if (this.debugMode) {
423
+ console.error('[Session] Starting session', this.sessionId);
424
+ }
425
+ // Handle initial prompt if provided (fire-and-forget)
426
+ if (this.initialPrompt !== null) {
427
+ this.handleFirstMessage(this.initialPrompt);
428
+ }
429
+ try {
430
+ for await (const message of this.inputReader.read()) {
431
+ if (this.abortController.signal.aborted) {
432
+ break;
433
+ }
434
+ // ============================================================
435
+ // CRITICAL: Handle control_response FIRST and SYNCHRONOUSLY
436
+ // This resolves pending outgoing requests, breaking deadlock.
437
+ // ============================================================
438
+ if (isControlResponse(message)) {
439
+ this.handleControlResponse(message);
440
+ continue;
441
+ }
442
+ // Handle first message to determine session mode
443
+ if (this.controlSystemEnabled === null) {
444
+ this.handleFirstMessage(message);
445
+ continue;
446
+ }
447
+ // ============================================================
448
+ // CRITICAL: Handle control_request in FIRE-AND-FORGET mode
449
+ // DON'T await - let handler run concurrently while loop continues
450
+ // Dispatcher's pendingIncomingRequests tracks completion
451
+ // ============================================================
452
+ if (isControlRequest(message)) {
453
+ this.handleControlRequestAsync(message);
454
+ }
455
+ else if (isControlCancel(message)) {
456
+ // Cancel is synchronous - OK to handle inline
457
+ this.handleControlCancel(message);
458
+ }
459
+ else if (isCLIUserMessage(message)) {
460
+ // User messages are enqueued, processing runs separately
461
+ this.enqueueUserMessage(message);
462
+ }
463
+ else if (this.debugMode) {
464
+ if (!isCLIAssistantMessage(message) &&
465
+ !isCLISystemMessage(message) &&
466
+ !isCLIResultMessage(message) &&
467
+ !isCLIPartialAssistantMessage(message)) {
468
+ console.error('[Session] Unknown message type:', JSON.stringify(message, null, 2));
469
+ }
470
+ }
471
+ if (this.isShuttingDown) {
472
+ break;
473
+ }
474
+ }
475
+ }
476
+ catch (streamError) {
477
+ if (this.debugMode) {
478
+ console.error('[Session] Stream reading error:', streamError);
479
+ }
480
+ throw streamError;
481
+ }
482
+ // Stream ended - wait for all pending work before shutdown
483
+ await this.waitForAllPendingWork();
484
+ await this.shutdown();
485
+ }
486
+ catch (error) {
487
+ if (this.debugMode) {
488
+ console.error('[Session] Error:', error);
489
+ }
490
+ await this.shutdown();
491
+ throw error;
492
+ }
493
+ finally {
494
+ this.cleanupSignalHandlers();
495
+ }
496
+ }
494
497
  }
495
498
  function extractUserMessageText(message) {
496
499
  const content = message.message.content;
@@ -513,19 +516,12 @@ function extractUserMessageText(message) {
513
516
  }
514
517
  return null;
515
518
  }
516
- /**
517
- * Entry point for stream-json mode
518
- *
519
- * @param config - Configuration object
520
- * @param input - Optional initial prompt input to process before reading from stream
521
- */
522
519
  export async function runNonInteractiveStreamJson(config, input) {
523
520
  const consolePatcher = new ConsolePatcher({
524
521
  debugMode: config.getDebugMode(),
525
522
  });
526
523
  consolePatcher.patch();
527
524
  try {
528
- // Create initial user message from prompt input if provided
529
525
  let initialPrompt = undefined;
530
526
  if (input && input.trim().length > 0) {
531
527
  const sessionId = config.getSessionId();
@@ -539,7 +535,7 @@ export async function runNonInteractiveStreamJson(config, input) {
539
535
  parent_tool_use_id: null,
540
536
  };
541
537
  }
542
- const manager = new SessionManager(config, initialPrompt);
538
+ const manager = new Session(config, initialPrompt);
543
539
  await manager.run();
544
540
  }
545
541
  finally {