wave-agent-sdk 0.19.6 → 0.19.8

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 (366) hide show
  1. package/dist/agent.d.ts +16 -14
  2. package/dist/agent.js +58 -56
  3. package/dist/constants/goalPrompts.d.ts +0 -1
  4. package/dist/constants/subagents.d.ts +0 -1
  5. package/dist/constants/toolLimits.d.ts +0 -1
  6. package/dist/constants/tools.d.ts +0 -1
  7. package/dist/core/plugin.d.ts +0 -1
  8. package/dist/core/session.d.ts +0 -1
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.js +1 -0
  11. package/dist/managers/MemoryRuleManager.d.ts +0 -1
  12. package/dist/managers/aiManager.d.ts +2 -1
  13. package/dist/managers/aiManager.js +29 -9
  14. package/dist/managers/backgroundTaskManager.d.ts +0 -2
  15. package/dist/managers/backgroundTaskManager.js +16 -19
  16. package/dist/managers/bangManager.d.ts +0 -1
  17. package/dist/managers/cronManager.d.ts +0 -1
  18. package/dist/managers/foregroundTaskManager.d.ts +0 -1
  19. package/dist/managers/forkedAgentManager.d.ts +0 -1
  20. package/dist/managers/goalManager.d.ts +0 -1
  21. package/dist/managers/hookManager.d.ts +0 -1
  22. package/dist/managers/liveConfigManager.d.ts +0 -1
  23. package/dist/managers/lspManager.d.ts +0 -1
  24. package/dist/managers/mcpManager.d.ts +0 -1
  25. package/dist/managers/messageManager.d.ts +0 -1
  26. package/dist/managers/messageQueue.d.ts +17 -2
  27. package/dist/managers/messageQueue.js +40 -1
  28. package/dist/managers/permissionManager.d.ts +0 -1
  29. package/dist/managers/planManager.d.ts +0 -1
  30. package/dist/managers/pluginManager.d.ts +0 -1
  31. package/dist/managers/pluginScopeManager.d.ts +0 -1
  32. package/dist/managers/reversionManager.d.ts +0 -1
  33. package/dist/managers/skillManager.d.ts +0 -1
  34. package/dist/managers/slashCommandManager.d.ts +0 -1
  35. package/dist/managers/subagentManager.d.ts +0 -3
  36. package/dist/managers/subagentManager.js +14 -13
  37. package/dist/managers/toolManager.d.ts +0 -1
  38. package/dist/managers/workflowManager.d.ts +1 -2
  39. package/dist/managers/workflowManager.js +4 -4
  40. package/dist/prompts/autoMemory.d.ts +0 -1
  41. package/dist/prompts/autoMemoryExtraction.d.ts +0 -1
  42. package/dist/prompts/index.d.ts +0 -1
  43. package/dist/prompts/planModeReminders.d.ts +0 -1
  44. package/dist/services/GitService.d.ts +0 -1
  45. package/dist/services/MarketplaceService.d.ts +0 -1
  46. package/dist/services/MemoryRuleService.d.ts +0 -1
  47. package/dist/services/aiService.d.ts +0 -1
  48. package/dist/services/authService.d.ts +0 -1
  49. package/dist/services/autoMemoryService.d.ts +0 -1
  50. package/dist/services/configurationService.d.ts +6 -1
  51. package/dist/services/configurationService.js +31 -0
  52. package/dist/services/fileWatcher.d.ts +0 -1
  53. package/dist/services/hook.d.ts +0 -1
  54. package/dist/services/initializationService.d.ts +0 -1
  55. package/dist/services/interactionService.d.ts +0 -1
  56. package/dist/services/interactionService.js +10 -0
  57. package/dist/services/jsonlHandler.d.ts +0 -1
  58. package/dist/services/memory.d.ts +0 -1
  59. package/dist/services/pluginLoader.d.ts +0 -1
  60. package/dist/services/remoteSettingsService.d.ts +0 -1
  61. package/dist/services/remoteSettingsService.js +2 -0
  62. package/dist/services/reversionService.d.ts +0 -1
  63. package/dist/services/session.d.ts +0 -1
  64. package/dist/services/taskManager.d.ts +0 -1
  65. package/dist/services/taskManager.js +8 -1
  66. package/dist/telemetry/events.d.ts +0 -1
  67. package/dist/telemetry/instrumentation.d.ts +0 -1
  68. package/dist/telemetry/sessionTracing.d.ts +0 -1
  69. package/dist/tools/agentTool.d.ts +0 -1
  70. package/dist/tools/askUserQuestion.d.ts +0 -1
  71. package/dist/tools/bashTool.d.ts +0 -1
  72. package/dist/tools/buildTool.d.ts +0 -1
  73. package/dist/tools/cronCreateTool.d.ts +0 -1
  74. package/dist/tools/cronDeleteTool.d.ts +0 -1
  75. package/dist/tools/cronListTool.d.ts +0 -1
  76. package/dist/tools/editTool.d.ts +0 -1
  77. package/dist/tools/enterPlanMode.d.ts +0 -1
  78. package/dist/tools/enterWorktreeTool.d.ts +0 -1
  79. package/dist/tools/enterWorktreeTool.js +2 -1
  80. package/dist/tools/exitPlanMode.d.ts +0 -1
  81. package/dist/tools/exitWorktreeTool.d.ts +0 -1
  82. package/dist/tools/globTool.d.ts +0 -1
  83. package/dist/tools/grepTool.d.ts +0 -1
  84. package/dist/tools/lspTool.d.ts +0 -1
  85. package/dist/tools/readTool.d.ts +0 -1
  86. package/dist/tools/skillTool.d.ts +0 -1
  87. package/dist/tools/taskManagementTools.d.ts +0 -1
  88. package/dist/tools/taskStopTool.d.ts +0 -1
  89. package/dist/tools/types.d.ts +0 -1
  90. package/dist/tools/webFetchTool.d.ts +0 -1
  91. package/dist/tools/workflowTool.d.ts +0 -1
  92. package/dist/tools/writeTool.d.ts +0 -1
  93. package/dist/types/agent.d.ts +0 -1
  94. package/dist/types/auth.d.ts +0 -1
  95. package/dist/types/commands.d.ts +0 -1
  96. package/dist/types/config.d.ts +0 -1
  97. package/dist/types/configuration.d.ts +5 -1
  98. package/dist/types/core.d.ts +0 -1
  99. package/dist/types/cron.d.ts +0 -1
  100. package/dist/types/environment.d.ts +0 -1
  101. package/dist/types/fileSearch.d.ts +0 -1
  102. package/dist/types/history.d.ts +0 -1
  103. package/dist/types/hooks.d.ts +0 -1
  104. package/dist/types/index.d.ts +0 -1
  105. package/dist/types/lsp.d.ts +0 -1
  106. package/dist/types/marketplace.d.ts +0 -1
  107. package/dist/types/mcp.d.ts +0 -1
  108. package/dist/types/memoryRule.d.ts +0 -1
  109. package/dist/types/messaging.d.ts +0 -1
  110. package/dist/types/permissions.d.ts +0 -3
  111. package/dist/types/plugins.d.ts +0 -1
  112. package/dist/types/processes.d.ts +27 -1
  113. package/dist/types/reversion.d.ts +0 -1
  114. package/dist/types/session.d.ts +0 -1
  115. package/dist/types/skills.d.ts +0 -1
  116. package/dist/types/tasks.d.ts +0 -1
  117. package/dist/types/telemetry.d.ts +0 -1
  118. package/dist/types/tools.d.ts +0 -1
  119. package/dist/types/workflow.d.ts +1 -2
  120. package/dist/utils/abortUtils.d.ts +0 -1
  121. package/dist/utils/atomicWrite.d.ts +0 -1
  122. package/dist/utils/bashParser.d.ts +0 -1
  123. package/dist/utils/cacheControlUtils.d.ts +0 -1
  124. package/dist/utils/commandArgumentParser.d.ts +0 -1
  125. package/dist/utils/commandPathResolver.d.ts +0 -1
  126. package/dist/utils/configPaths.d.ts +0 -1
  127. package/dist/utils/configValidator.d.ts +0 -1
  128. package/dist/utils/constants.d.ts +0 -1
  129. package/dist/utils/container.d.ts +0 -1
  130. package/dist/utils/containerSetup.d.ts +0 -1
  131. package/dist/utils/containerSetup.js +0 -12
  132. package/dist/utils/convertMessagesForAPI.d.ts +0 -1
  133. package/dist/utils/cronTasks.d.ts +0 -1
  134. package/dist/utils/cronTasksLock.d.ts +0 -1
  135. package/dist/utils/cronToHuman.d.ts +0 -1
  136. package/dist/utils/customCommands.d.ts +0 -1
  137. package/dist/utils/editUtils.d.ts +0 -1
  138. package/dist/utils/fileFormat.d.ts +0 -1
  139. package/dist/utils/fileSearch.d.ts +0 -1
  140. package/dist/utils/fileUtils.d.ts +0 -1
  141. package/dist/utils/gitUtils.d.ts +0 -1
  142. package/dist/utils/globalLogger.d.ts +0 -1
  143. package/dist/utils/groupMessagesByApiRound.d.ts +0 -1
  144. package/dist/utils/hookMatcher.d.ts +0 -1
  145. package/dist/utils/markdownParser.d.ts +0 -1
  146. package/dist/utils/mcpUtils.d.ts +0 -1
  147. package/dist/utils/messageOperations.d.ts +0 -1
  148. package/dist/utils/modelCapabilities.d.ts +0 -1
  149. package/dist/utils/nameGenerator.d.ts +0 -1
  150. package/dist/utils/notificationXml.d.ts +0 -1
  151. package/dist/utils/openaiClient.d.ts +0 -1
  152. package/dist/utils/parseCronExpression.d.ts +0 -1
  153. package/dist/utils/path.d.ts +0 -1
  154. package/dist/utils/pathEncoder.d.ts +0 -1
  155. package/dist/utils/pathSafety.d.ts +0 -1
  156. package/dist/utils/promptHistory.d.ts +0 -1
  157. package/dist/utils/ripgrep.d.ts +0 -1
  158. package/dist/utils/shellResolver.d.ts +0 -1
  159. package/dist/utils/skillParser.d.ts +0 -1
  160. package/dist/utils/stringUtils.d.ts +0 -1
  161. package/dist/utils/subagentParser.d.ts +0 -1
  162. package/dist/utils/taskReminder.d.ts +0 -1
  163. package/dist/utils/tokenCalculation.d.ts +0 -1
  164. package/dist/utils/tokenEstimate.d.ts +0 -1
  165. package/dist/utils/toolResultStorage.d.ts +0 -1
  166. package/dist/utils/worktreeSession.d.ts +1 -2
  167. package/dist/utils/worktreeSession.js +1 -1
  168. package/dist/utils/worktreeUtils.d.ts +7 -2
  169. package/dist/utils/worktreeUtils.js +10 -4
  170. package/dist/workflow/budgetTracker.d.ts +0 -1
  171. package/dist/workflow/concurrencyLimiter.d.ts +0 -1
  172. package/dist/workflow/journal.d.ts +0 -1
  173. package/dist/workflow/progressReporter.d.ts +0 -1
  174. package/dist/workflow/runState.d.ts +0 -1
  175. package/dist/workflow/scriptRuntime.d.ts +0 -1
  176. package/dist/workflow/structuredOutput.d.ts +0 -1
  177. package/dist/workflow/types.d.ts +5 -1
  178. package/dist/workflow/workflowApis.d.ts +0 -1
  179. package/package.json +1 -1
  180. package/src/agent.ts +59 -67
  181. package/src/index.ts +1 -0
  182. package/src/managers/aiManager.ts +34 -10
  183. package/src/managers/backgroundTaskManager.ts +17 -21
  184. package/src/managers/messageQueue.ts +43 -2
  185. package/src/managers/subagentManager.ts +15 -15
  186. package/src/managers/workflowManager.ts +5 -5
  187. package/src/services/configurationService.ts +37 -0
  188. package/src/services/interactionService.ts +11 -0
  189. package/src/services/remoteSettingsService.ts +1 -0
  190. package/src/services/taskManager.ts +8 -1
  191. package/src/tools/enterWorktreeTool.ts +2 -1
  192. package/src/types/configuration.ts +5 -0
  193. package/src/types/permissions.ts +0 -2
  194. package/src/types/processes.ts +29 -0
  195. package/src/types/workflow.ts +1 -0
  196. package/src/utils/containerSetup.ts +0 -15
  197. package/src/utils/worktreeSession.ts +1 -1
  198. package/src/utils/worktreeUtils.ts +14 -4
  199. package/src/workflow/types.ts +6 -0
  200. package/dist/agent.d.ts.map +0 -1
  201. package/dist/constants/goalPrompts.d.ts.map +0 -1
  202. package/dist/constants/subagents.d.ts.map +0 -1
  203. package/dist/constants/toolLimits.d.ts.map +0 -1
  204. package/dist/constants/tools.d.ts.map +0 -1
  205. package/dist/core/plugin.d.ts.map +0 -1
  206. package/dist/core/session.d.ts.map +0 -1
  207. package/dist/index.d.ts.map +0 -1
  208. package/dist/managers/MemoryRuleManager.d.ts.map +0 -1
  209. package/dist/managers/aiManager.d.ts.map +0 -1
  210. package/dist/managers/backgroundTaskManager.d.ts.map +0 -1
  211. package/dist/managers/bangManager.d.ts.map +0 -1
  212. package/dist/managers/cronManager.d.ts.map +0 -1
  213. package/dist/managers/foregroundTaskManager.d.ts.map +0 -1
  214. package/dist/managers/forkedAgentManager.d.ts.map +0 -1
  215. package/dist/managers/goalManager.d.ts.map +0 -1
  216. package/dist/managers/hookManager.d.ts.map +0 -1
  217. package/dist/managers/liveConfigManager.d.ts.map +0 -1
  218. package/dist/managers/lspManager.d.ts.map +0 -1
  219. package/dist/managers/mcpManager.d.ts.map +0 -1
  220. package/dist/managers/messageManager.d.ts.map +0 -1
  221. package/dist/managers/messageQueue.d.ts.map +0 -1
  222. package/dist/managers/notificationQueue.d.ts +0 -8
  223. package/dist/managers/notificationQueue.d.ts.map +0 -1
  224. package/dist/managers/notificationQueue.js +0 -17
  225. package/dist/managers/permissionManager.d.ts.map +0 -1
  226. package/dist/managers/planManager.d.ts.map +0 -1
  227. package/dist/managers/pluginManager.d.ts.map +0 -1
  228. package/dist/managers/pluginScopeManager.d.ts.map +0 -1
  229. package/dist/managers/reversionManager.d.ts.map +0 -1
  230. package/dist/managers/skillManager.d.ts.map +0 -1
  231. package/dist/managers/slashCommandManager.d.ts.map +0 -1
  232. package/dist/managers/subagentManager.d.ts.map +0 -1
  233. package/dist/managers/toolManager.d.ts.map +0 -1
  234. package/dist/managers/workflowManager.d.ts.map +0 -1
  235. package/dist/prompts/autoMemory.d.ts.map +0 -1
  236. package/dist/prompts/autoMemoryExtraction.d.ts.map +0 -1
  237. package/dist/prompts/index.d.ts.map +0 -1
  238. package/dist/prompts/planModeReminders.d.ts.map +0 -1
  239. package/dist/services/GitService.d.ts.map +0 -1
  240. package/dist/services/MarketplaceService.d.ts.map +0 -1
  241. package/dist/services/MemoryRuleService.d.ts.map +0 -1
  242. package/dist/services/aiService.d.ts.map +0 -1
  243. package/dist/services/authService.d.ts.map +0 -1
  244. package/dist/services/autoMemoryService.d.ts.map +0 -1
  245. package/dist/services/configurationService.d.ts.map +0 -1
  246. package/dist/services/fileWatcher.d.ts.map +0 -1
  247. package/dist/services/hook.d.ts.map +0 -1
  248. package/dist/services/initializationService.d.ts.map +0 -1
  249. package/dist/services/interactionService.d.ts.map +0 -1
  250. package/dist/services/jsonlHandler.d.ts.map +0 -1
  251. package/dist/services/memory.d.ts.map +0 -1
  252. package/dist/services/pluginLoader.d.ts.map +0 -1
  253. package/dist/services/remoteSettingsService.d.ts.map +0 -1
  254. package/dist/services/reversionService.d.ts.map +0 -1
  255. package/dist/services/session.d.ts.map +0 -1
  256. package/dist/services/taskManager.d.ts.map +0 -1
  257. package/dist/telemetry/events.d.ts.map +0 -1
  258. package/dist/telemetry/instrumentation.d.ts.map +0 -1
  259. package/dist/telemetry/sessionTracing.d.ts.map +0 -1
  260. package/dist/tools/agentTool.d.ts.map +0 -1
  261. package/dist/tools/askUserQuestion.d.ts.map +0 -1
  262. package/dist/tools/bashTool.d.ts.map +0 -1
  263. package/dist/tools/buildTool.d.ts.map +0 -1
  264. package/dist/tools/cronCreateTool.d.ts.map +0 -1
  265. package/dist/tools/cronDeleteTool.d.ts.map +0 -1
  266. package/dist/tools/cronListTool.d.ts.map +0 -1
  267. package/dist/tools/editTool.d.ts.map +0 -1
  268. package/dist/tools/enterPlanMode.d.ts.map +0 -1
  269. package/dist/tools/enterWorktreeTool.d.ts.map +0 -1
  270. package/dist/tools/exitPlanMode.d.ts.map +0 -1
  271. package/dist/tools/exitWorktreeTool.d.ts.map +0 -1
  272. package/dist/tools/globTool.d.ts.map +0 -1
  273. package/dist/tools/grepTool.d.ts.map +0 -1
  274. package/dist/tools/lspTool.d.ts.map +0 -1
  275. package/dist/tools/readTool.d.ts.map +0 -1
  276. package/dist/tools/skillTool.d.ts.map +0 -1
  277. package/dist/tools/taskManagementTools.d.ts.map +0 -1
  278. package/dist/tools/taskStopTool.d.ts.map +0 -1
  279. package/dist/tools/types.d.ts.map +0 -1
  280. package/dist/tools/webFetchTool.d.ts.map +0 -1
  281. package/dist/tools/workflowTool.d.ts.map +0 -1
  282. package/dist/tools/writeTool.d.ts.map +0 -1
  283. package/dist/types/agent.d.ts.map +0 -1
  284. package/dist/types/auth.d.ts.map +0 -1
  285. package/dist/types/commands.d.ts.map +0 -1
  286. package/dist/types/config.d.ts.map +0 -1
  287. package/dist/types/configuration.d.ts.map +0 -1
  288. package/dist/types/core.d.ts.map +0 -1
  289. package/dist/types/cron.d.ts.map +0 -1
  290. package/dist/types/environment.d.ts.map +0 -1
  291. package/dist/types/fileSearch.d.ts.map +0 -1
  292. package/dist/types/history.d.ts.map +0 -1
  293. package/dist/types/hooks.d.ts.map +0 -1
  294. package/dist/types/index.d.ts.map +0 -1
  295. package/dist/types/lsp.d.ts.map +0 -1
  296. package/dist/types/marketplace.d.ts.map +0 -1
  297. package/dist/types/mcp.d.ts.map +0 -1
  298. package/dist/types/memoryRule.d.ts.map +0 -1
  299. package/dist/types/messaging.d.ts.map +0 -1
  300. package/dist/types/permissions.d.ts.map +0 -1
  301. package/dist/types/plugins.d.ts.map +0 -1
  302. package/dist/types/processes.d.ts.map +0 -1
  303. package/dist/types/reversion.d.ts.map +0 -1
  304. package/dist/types/session.d.ts.map +0 -1
  305. package/dist/types/skills.d.ts.map +0 -1
  306. package/dist/types/tasks.d.ts.map +0 -1
  307. package/dist/types/telemetry.d.ts.map +0 -1
  308. package/dist/types/tools.d.ts.map +0 -1
  309. package/dist/types/workflow.d.ts.map +0 -1
  310. package/dist/utils/abortUtils.d.ts.map +0 -1
  311. package/dist/utils/atomicWrite.d.ts.map +0 -1
  312. package/dist/utils/bashParser.d.ts.map +0 -1
  313. package/dist/utils/cacheControlUtils.d.ts.map +0 -1
  314. package/dist/utils/commandArgumentParser.d.ts.map +0 -1
  315. package/dist/utils/commandPathResolver.d.ts.map +0 -1
  316. package/dist/utils/configPaths.d.ts.map +0 -1
  317. package/dist/utils/configValidator.d.ts.map +0 -1
  318. package/dist/utils/constants.d.ts.map +0 -1
  319. package/dist/utils/container.d.ts.map +0 -1
  320. package/dist/utils/containerSetup.d.ts.map +0 -1
  321. package/dist/utils/convertMessagesForAPI.d.ts.map +0 -1
  322. package/dist/utils/cronTasks.d.ts.map +0 -1
  323. package/dist/utils/cronTasksLock.d.ts.map +0 -1
  324. package/dist/utils/cronToHuman.d.ts.map +0 -1
  325. package/dist/utils/customCommands.d.ts.map +0 -1
  326. package/dist/utils/editUtils.d.ts.map +0 -1
  327. package/dist/utils/fileFormat.d.ts.map +0 -1
  328. package/dist/utils/fileSearch.d.ts.map +0 -1
  329. package/dist/utils/fileUtils.d.ts.map +0 -1
  330. package/dist/utils/gitUtils.d.ts.map +0 -1
  331. package/dist/utils/globalLogger.d.ts.map +0 -1
  332. package/dist/utils/groupMessagesByApiRound.d.ts.map +0 -1
  333. package/dist/utils/hookMatcher.d.ts.map +0 -1
  334. package/dist/utils/markdownParser.d.ts.map +0 -1
  335. package/dist/utils/mcpUtils.d.ts.map +0 -1
  336. package/dist/utils/messageOperations.d.ts.map +0 -1
  337. package/dist/utils/modelCapabilities.d.ts.map +0 -1
  338. package/dist/utils/nameGenerator.d.ts.map +0 -1
  339. package/dist/utils/notificationXml.d.ts.map +0 -1
  340. package/dist/utils/openaiClient.d.ts.map +0 -1
  341. package/dist/utils/parseCronExpression.d.ts.map +0 -1
  342. package/dist/utils/path.d.ts.map +0 -1
  343. package/dist/utils/pathEncoder.d.ts.map +0 -1
  344. package/dist/utils/pathSafety.d.ts.map +0 -1
  345. package/dist/utils/promptHistory.d.ts.map +0 -1
  346. package/dist/utils/ripgrep.d.ts.map +0 -1
  347. package/dist/utils/shellResolver.d.ts.map +0 -1
  348. package/dist/utils/skillParser.d.ts.map +0 -1
  349. package/dist/utils/stringUtils.d.ts.map +0 -1
  350. package/dist/utils/subagentParser.d.ts.map +0 -1
  351. package/dist/utils/taskReminder.d.ts.map +0 -1
  352. package/dist/utils/tokenCalculation.d.ts.map +0 -1
  353. package/dist/utils/tokenEstimate.d.ts.map +0 -1
  354. package/dist/utils/toolResultStorage.d.ts.map +0 -1
  355. package/dist/utils/worktreeSession.d.ts.map +0 -1
  356. package/dist/utils/worktreeUtils.d.ts.map +0 -1
  357. package/dist/workflow/budgetTracker.d.ts.map +0 -1
  358. package/dist/workflow/concurrencyLimiter.d.ts.map +0 -1
  359. package/dist/workflow/journal.d.ts.map +0 -1
  360. package/dist/workflow/progressReporter.d.ts.map +0 -1
  361. package/dist/workflow/runState.d.ts.map +0 -1
  362. package/dist/workflow/scriptRuntime.d.ts.map +0 -1
  363. package/dist/workflow/structuredOutput.d.ts.map +0 -1
  364. package/dist/workflow/types.d.ts.map +0 -1
  365. package/dist/workflow/workflowApis.d.ts.map +0 -1
  366. package/src/managers/notificationQueue.ts +0 -19
@@ -5,7 +5,7 @@
5
5
  * "WorktreeSession" container slot registered in containerSetup.ts and accessed via
6
6
  * AIManager.getWorktreeSession()/setWorktreeSession()). This keeps worktree state
7
7
  * isolated per session in stdio multi-agent mode — a process-level singleton would
8
- * leak state across concurrent sessions (see specs/047-worktree.md FR-042).
8
+ * leak state across concurrent sessions (see docs/specs/multi-agent/worktree.md FR-042).
9
9
  */
10
10
  export interface WorktreeSession {
11
11
  /** The working directory the session was in before EnterWorktree */
@@ -23,4 +23,3 @@ export interface WorktreeSession {
23
23
  /** The HEAD commit of the original branch at worktree creation time */
24
24
  originalHeadCommit?: string;
25
25
  }
26
- //# sourceMappingURL=worktreeSession.d.ts.map
@@ -5,6 +5,6 @@
5
5
  * "WorktreeSession" container slot registered in containerSetup.ts and accessed via
6
6
  * AIManager.getWorktreeSession()/setWorktreeSession()). This keeps worktree state
7
7
  * isolated per session in stdio multi-agent mode — a process-level singleton would
8
- * leak state across concurrent sessions (see specs/047-worktree.md FR-042).
8
+ * leak state across concurrent sessions (see docs/specs/multi-agent/worktree.md FR-042).
9
9
  */
10
10
  export {};
@@ -25,8 +25,14 @@ export declare function generateWorktreeName(): string;
25
25
  export declare function getHeadCommit(cwd: string): string;
26
26
  /**
27
27
  * Create a git worktree for use during a session.
28
+ * @param name Worktree name
29
+ * @param cwd Current working directory (will be resolved to main repo root)
30
+ * @param options Optional creation options
31
+ * @param options.baseRef "fresh" (default, origin/<default-branch>) | "head" (local HEAD)
28
32
  */
29
- export declare function createWorktree(name: string, cwd: string): WorktreeInfo;
33
+ export declare function createWorktree(name: string, cwd: string, options?: {
34
+ baseRef?: "fresh" | "head";
35
+ }): WorktreeInfo;
30
36
  /**
31
37
  * Remove a git worktree and its branch.
32
38
  */
@@ -39,4 +45,3 @@ export declare function countWorktreeChanges(worktreePath: string, originalHeadC
39
45
  changedFiles: number;
40
46
  commits: number;
41
47
  } | null;
42
- //# sourceMappingURL=worktreeUtils.d.ts.map
@@ -68,8 +68,12 @@ export function getHeadCommit(cwd) {
68
68
  }
69
69
  /**
70
70
  * Create a git worktree for use during a session.
71
+ * @param name Worktree name
72
+ * @param cwd Current working directory (will be resolved to main repo root)
73
+ * @param options Optional creation options
74
+ * @param options.baseRef "fresh" (default, origin/<default-branch>) | "head" (local HEAD)
71
75
  */
72
- export function createWorktree(name, cwd) {
76
+ export function createWorktree(name, cwd, options) {
73
77
  const repoRoot = getGitMainRepoRoot(cwd);
74
78
  if (!repoRoot) {
75
79
  throw new Error("Cannot create a worktree: not in a git repository. Configure WorktreeCreate and WorktreeRemove hooks in settings.json to use worktree isolation with other VCS systems.");
@@ -78,7 +82,8 @@ export function createWorktree(name, cwd) {
78
82
  const originalHeadCommit = getHeadCommit(cwd);
79
83
  const worktreePath = path.join(repoRoot, ".wave", "worktrees", name);
80
84
  const branchName = `worktree-${name}`;
81
- const baseBranch = getDefaultRemoteBranch(cwd);
85
+ const useHead = options?.baseRef === "head";
86
+ const baseBranch = useHead ? "HEAD" : getDefaultRemoteBranch(cwd);
82
87
  // Ensure Wave runtime files are git-excluded in this repo
83
88
  ensureWaveRuntimeFilesExcluded(cwd);
84
89
  // Ensure parent directory exists
@@ -144,8 +149,9 @@ export function createWorktree(name, cwd) {
144
149
  throw new Error(`Failed to add worktree: ${innerError.message}`);
145
150
  }
146
151
  }
147
- if (stderr.includes("not a valid object name") ||
148
- stderr.includes("unknown revision")) {
152
+ if (!useHead &&
153
+ (stderr.includes("not a valid object name") ||
154
+ stderr.includes("unknown revision"))) {
149
155
  // Base branch not fetched yet — try fetching then retrying
150
156
  const branchNameOnly = baseBranch.split("/").pop();
151
157
  try {
@@ -9,4 +9,3 @@ export declare class BudgetTracker {
9
9
  get total(): number | null;
10
10
  toBudgetInfo(): import("./types.js").BudgetInfo;
11
11
  }
12
- //# sourceMappingURL=budgetTracker.d.ts.map
@@ -11,4 +11,3 @@ export declare class ConcurrencyLimiter {
11
11
  get activeCount(): number;
12
12
  get pendingCount(): number;
13
13
  }
14
- //# sourceMappingURL=concurrencyLimiter.d.ts.map
@@ -16,4 +16,3 @@ export declare class Journal {
16
16
  close(): Promise<void>;
17
17
  static load(filePath: string): Promise<Journal>;
18
18
  }
19
- //# sourceMappingURL=journal.d.ts.map
@@ -18,4 +18,3 @@ export declare class ProgressReporter {
18
18
  onEvent(listener: (event: WorkflowProgressEvent) => void): void;
19
19
  private emit;
20
20
  }
21
- //# sourceMappingURL=progressReporter.d.ts.map
@@ -13,4 +13,3 @@ export declare class RunStateStore {
13
13
  /** List all persisted run IDs */
14
14
  listRuns(): Promise<string[]>;
15
15
  }
16
- //# sourceMappingURL=runState.d.ts.map
@@ -32,4 +32,3 @@ export declare function executeScript(script: string, apis: {
32
32
  meta: WorkflowMeta;
33
33
  result: unknown;
34
34
  }>;
35
- //# sourceMappingURL=scriptRuntime.d.ts.map
@@ -24,4 +24,3 @@ export declare function extractStructuredResult(messages: Array<{
24
24
  }>;
25
25
  }>, schema: object): unknown | null;
26
26
  export { STRUCTURED_OUTPUT_TOOL_NAME };
27
- //# sourceMappingURL=structuredOutput.d.ts.map
@@ -38,6 +38,11 @@ export interface WorkflowRun {
38
38
  /** Error message from the failed agent */
39
39
  failedAgentError?: string;
40
40
  }
41
+ /**
42
+ * Serializable workflow run for stdio transport, with the non-serializable
43
+ * `completionPromise` stripped. Returned by the `getWorkflowRuns` RPC.
44
+ */
45
+ export type SerializableWorkflowRun = Omit<WorkflowRun, "completionPromise">;
41
46
  export interface JournalEntry {
42
47
  agentIndex: number;
43
48
  prompt: string;
@@ -78,4 +83,3 @@ export interface WorkflowProgressEvent {
78
83
  agentIndex?: number;
79
84
  timestamp: number;
80
85
  }
81
- //# sourceMappingURL=types.d.ts.map
@@ -41,4 +41,3 @@ export interface WorkflowApis {
41
41
  }
42
42
  export declare function createWorkflowApis(ctx: WorkflowApiContext): WorkflowApis;
43
43
  export {};
44
- //# sourceMappingURL=workflowApis.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-agent-sdk",
3
- "version": "0.19.6",
3
+ "version": "0.19.8",
4
4
  "description": "SDK for building AI-powered development tools and agents",
5
5
  "keywords": [
6
6
  "ai",
package/src/agent.ts CHANGED
@@ -10,7 +10,6 @@ import { BangManager } from "./managers/bangManager.js";
10
10
  import { CronManager } from "./managers/cronManager.js";
11
11
  import { GoalManager } from "./managers/goalManager.js";
12
12
  import { BackgroundTaskManager } from "./managers/backgroundTaskManager.js";
13
- import { NotificationQueue } from "./managers/notificationQueue.js";
14
13
  import { MessageQueue, type QueuedMessage } from "./managers/messageQueue.js";
15
14
  import { SlashCommandManager } from "./managers/slashCommandManager.js";
16
15
  import { PluginManager } from "./managers/pluginManager.js";
@@ -77,9 +76,8 @@ export class Agent {
77
76
  private goalManager: GoalManager; // Add goal manager instance
78
77
  private hookManager: HookManager; // Add hooks manager instance
79
78
  private reversionManager: ReversionManager;
80
- private notificationQueue: NotificationQueue; // Add notification queue instance
81
- private messageQueue: MessageQueue; // Add message queue instance
82
- private pendingNotificationPromises: Promise<void>[] = []; // Track pending notification processing
79
+ private messageQueue: MessageQueue; // Unified queue for messages, bang commands, and notifications
80
+ private dispatchPromise: Promise<void> | null = null; // Track current dispatch for teardown
83
81
  private memoryRuleManager: MemoryRuleManager; // Add memory rule manager instance
84
82
  private liveConfigManager: LiveConfigManager; // Add live configuration manager
85
83
  private taskManager: TaskManager;
@@ -207,25 +205,8 @@ export class Agent {
207
205
  this.bangManager = this.container.get("BangManager")!;
208
206
  this.cronManager = this.container.get("CronManager")!;
209
207
  this.goalManager = this.container.get("GoalManager")!;
210
- this.notificationQueue = this.container.get("NotificationQueue")!;
211
208
  this.messageQueue = this.container.get("MessageQueue")!;
212
209
 
213
- // Wire up notification queue to trigger AI when notifications arrive while idle
214
- this.notificationQueue.onNotificationsEnqueued = () => {
215
- // If the AI is NOT loading (idle), trigger a new AI cycle to process notifications
216
- if (!this.aiManager.isLoading) {
217
- const pendingPromise = this.processPendingNotifications().catch(
218
- (error) => {
219
- this.logger?.error(
220
- "Failed to process pending notifications:",
221
- error,
222
- );
223
- },
224
- );
225
- this.pendingNotificationPromises.push(pendingPromise);
226
- }
227
- };
228
-
229
210
  // Wire up CWD change callback from AIManager to sync Agent's workdir
230
211
  this.aiManager.setOnCwdChange((newCwd) => {
231
212
  this.workdir = newCwd;
@@ -233,18 +214,20 @@ export class Agent {
233
214
  this.options.callbacks?.onWorkdirChange?.(newCwd);
234
215
  });
235
216
 
236
- // Wire up message queue to process when agent becomes idle
237
- this.messageQueue.onMessageEnqueued = () => this.tryDequeue();
217
+ // Wire up message queue to process when agent becomes idle.
218
+ // Both user messages and background task notifications enqueue here,
219
+ // unified through a single dispatch path (tryDispatch).
220
+ this.messageQueue.onMessageEnqueued = () => this.tryDispatch();
238
221
 
239
222
  // Wire up AI loading changes to process queue when AI becomes idle
240
223
  this.aiManager.onLoadingChange = (loading: boolean) => {
241
- if (!loading) this.tryDequeue();
224
+ if (!loading) this.tryDispatch();
242
225
  };
243
226
 
244
227
  // Wire up bang manager callback for command running changes
245
228
  this.bangManager.onCommandRunningChange = (running: boolean) => {
246
229
  this.options.callbacks?.onCommandRunningChange?.(running);
247
- if (!running) this.tryDequeue();
230
+ if (!running) this.tryDispatch();
248
231
  };
249
232
 
250
233
  // Set initial permission mode if provided
@@ -346,9 +329,11 @@ export class Agent {
346
329
  return this.bangManager?.isCommandRunning ?? false;
347
330
  }
348
331
 
349
- /** Get queued messages */
332
+ /** Get queued user-facing messages (excludes background notifications) */
350
333
  public get queuedMessages(): QueuedMessage[] {
351
- return this.messageQueue.getQueue();
334
+ return this.messageQueue
335
+ .getQueue()
336
+ .filter((m) => m.type !== "notification");
352
337
  }
353
338
 
354
339
  /** Get goal status string */
@@ -421,28 +406,31 @@ export class Agent {
421
406
  }
422
407
 
423
408
  /**
424
- * Unified dequeue trigger — checks state machine before processing.
425
- * Called from onMessageEnqueued, onLoadingChange(false), and
426
- * onCommandRunningChange(false).
409
+ * Unified dispatch trigger — checks state machine before processing.
410
+ * Handles user messages, bang commands, and background task notifications
411
+ * through a single serialized path. Called from onMessageEnqueued,
412
+ * onLoadingChange(false), and onCommandRunningChange(false).
427
413
  */
428
- private tryDequeue(): void {
414
+ private tryDispatch(): void {
429
415
  if (this.messageQueue.state !== "idle") return;
430
416
  if (!this.messageQueue.hasPending()) return;
431
417
  if (this.aiManager.isLoading || this.isCommandRunning) return;
432
418
 
433
419
  this.messageQueue.transitionTo("dispatching");
434
- this.processQueuedMessage()
420
+ this.dispatchPromise = this.processQueuedMessage()
435
421
  .catch((error) => {
436
422
  this.logger?.error("Failed to process queued message:", error);
437
423
  })
438
424
  .finally(() => {
439
425
  this.messageQueue.transitionTo("idle");
440
- this.tryDequeue(); // Re-check after processing
426
+ this.dispatchPromise = null;
427
+ this.tryDispatch(); // Re-check after processing
441
428
  });
442
429
  }
443
430
 
444
431
  /**
445
- * Process the next queued message when the agent becomes idle.
432
+ * Process the next queued item when the agent becomes idle.
433
+ * Handles three item types: user messages, bang commands, and notifications.
446
434
  */
447
435
  private async processQueuedMessage(): Promise<void> {
448
436
  const next = this.messageQueue.dequeue();
@@ -454,6 +442,25 @@ export class Agent {
454
442
  if (next.type === "bang") {
455
443
  await this.bangManager?.executeCommand(next.content);
456
444
  await this.messageManager.saveSession();
445
+ } else if (next.type === "notification") {
446
+ // Drain all pending notifications and batch them into a single AI turn
447
+ const allNotifications = [
448
+ next.content,
449
+ ...this.messageQueue.drainNotifications(),
450
+ ];
451
+ for (const xml of allNotifications) {
452
+ const block = parseTaskNotificationXml(xml);
453
+ if (block) {
454
+ this.messageManager.addNotificationMessage({
455
+ taskId: block.taskId,
456
+ taskType: block.taskType,
457
+ status: block.status,
458
+ summary: block.summary,
459
+ outputFile: block.outputFile,
460
+ });
461
+ }
462
+ }
463
+ await this.aiManager.sendAIMessage({ recursionDepth: 0 });
457
464
  } else {
458
465
  await this.sendMessage(next.content, next.images);
459
466
  }
@@ -681,31 +688,6 @@ export class Agent {
681
688
  this.aiManager.abortAIMessage();
682
689
  }
683
690
 
684
- /**
685
- * Process pending background task notifications by injecting them as user messages
686
- * and triggering a new AI response cycle.
687
- */
688
- private async processPendingNotifications(): Promise<void> {
689
- const notifications = this.notificationQueue.dequeueAll();
690
- if (notifications.length === 0) return;
691
-
692
- for (const notification of notifications) {
693
- const block = parseTaskNotificationXml(notification);
694
- if (block) {
695
- this.messageManager.addNotificationMessage({
696
- taskId: block.taskId,
697
- taskType: block.taskType,
698
- status: block.status,
699
- summary: block.summary,
700
- outputFile: block.outputFile,
701
- });
702
- }
703
- }
704
-
705
- // Trigger AI to process the notifications
706
- await this.aiManager.sendAIMessage({ recursionDepth: 0 });
707
- }
708
-
709
691
  /** Execute bash command (bang command) */
710
692
  public async bang(command: string): Promise<void> {
711
693
  // If the agent is busy, enqueue the bang command
@@ -866,8 +848,9 @@ export class Agent {
866
848
  /** Unified interrupt method, interrupts both AI messages and command execution */
867
849
  public abortMessage(): void {
868
850
  if (this.aiManager.isLoading || this.isCommandRunning) {
869
- // Clear queue first to prevent processQueuedMessage from dequeuing
870
- // when abortAIMessage triggers onLoadingChange(false)
851
+ // Clear user-facing queue items first to prevent processQueuedMessage
852
+ // from dequeuing when abortAIMessage triggers onLoadingChange(false).
853
+ // Notifications are preserved so background task results aren't lost.
871
854
  this.messageQueue.clear();
872
855
  this.options.callbacks?.onQueuedMessagesChange?.(this.queuedMessages);
873
856
  }
@@ -957,15 +940,14 @@ export class Agent {
957
940
  }).catch(() => {});
958
941
  await shutdownTelemetry();
959
942
 
960
- // Clear notification callback first to prevent any late triggers from
943
+ // Clear message queue callback first to prevent any late triggers from
961
944
  // starting async work during teardown
962
- this.notificationQueue.onNotificationsEnqueued = undefined;
945
+ this.messageQueue.onMessageEnqueued = undefined;
963
946
 
964
- // Await any pending notification processing to prevent race conditions
947
+ // Await any pending dispatch to prevent race conditions
965
948
  // with test teardown (e.g., V8 coverage stream cleanup)
966
- if (this.pendingNotificationPromises.length > 0) {
967
- await Promise.allSettled(this.pendingNotificationPromises);
968
- this.pendingNotificationPromises = [];
949
+ if (this.dispatchPromise) {
950
+ await this.dispatchPromise.catch(() => {});
969
951
  }
970
952
 
971
953
  // Fire SessionEnd hooks (fire-and-forget, don't block shutdown)
@@ -1284,4 +1266,14 @@ export class Agent {
1284
1266
  this.subagentManager.getActiveInstances().length > 0;
1285
1267
  return runningTasks || activeSubagents;
1286
1268
  }
1269
+
1270
+ /**
1271
+ * Check if there are pending items (messages, bang commands, or background
1272
+ * task notifications) in the message queue. Background task completion
1273
+ * notifications are enqueued before the main agent's dispatch consumes them,
1274
+ * so callers waiting for the agent to fully settle must also wait on this.
1275
+ */
1276
+ public get hasPendingMessages(): boolean {
1277
+ return this.messageQueue.hasPending();
1278
+ }
1287
1279
  }
package/src/index.ts CHANGED
@@ -29,6 +29,7 @@ export * from "./utils/tokenCalculation.js";
29
29
  export * from "./utils/gitUtils.js";
30
30
  export * from "./utils/nameGenerator.js";
31
31
  export * from "./utils/worktreeSession.js";
32
+ export { loadMergedWaveConfig } from "./services/configurationService.js";
32
33
  export * from "./types/index.js";
33
34
 
34
35
  // Export tool building utilities
@@ -41,7 +41,7 @@ import { Container } from "../utils/container.js";
41
41
  import type { WorktreeSession } from "../utils/worktreeSession.js";
42
42
  import { recoverTruncatedJson } from "../utils/stringUtils.js";
43
43
  import { ConfigurationService } from "../services/configurationService.js";
44
- import type { NotificationQueue } from "./notificationQueue.js";
44
+ import type { MessageQueue } from "./messageQueue.js";
45
45
 
46
46
  import { logger } from "../utils/globalLogger.js";
47
47
  import {
@@ -115,6 +115,7 @@ export interface AIManagerOptions {
115
115
 
116
116
  export class AIManager {
117
117
  public isLoading: boolean = false;
118
+ private turnGeneration = 0; // Guards against concurrent sendAIMessage turns
118
119
  private abortController: AbortController | null = null;
119
120
  onLoadingChange?: (loading: boolean) => void;
120
121
  private toolAbortController: AbortController | null = null;
@@ -251,6 +252,10 @@ export class AIManager {
251
252
  return this.configurationService.resolveAutoMemoryEnabled();
252
253
  }
253
254
 
255
+ public getWorktreeBaseRef(): "fresh" | "head" {
256
+ return this.configurationService.resolveWorktreeBaseRef();
257
+ }
258
+
254
259
  public getWorkdir(): string {
255
260
  return this.container.get<string>("Workdir") ?? process.cwd();
256
261
  }
@@ -397,6 +402,10 @@ export class AIManager {
397
402
  }
398
403
 
399
404
  public abortAIMessage(): void {
405
+ // Bump generation so the in-flight turn's end-of-turn setIsLoading(false)
406
+ // is skipped (generation mismatch), preventing it from racing with this abort.
407
+ this.turnGeneration++;
408
+
400
409
  // Interrupt AI service
401
410
  if (this.abortController) {
402
411
  try {
@@ -818,6 +827,15 @@ export class AIManager {
818
827
  const { recursionDepth = 0, model, allowedRules, maxTokens } = options;
819
828
  let turnOffset = recursionDepth;
820
829
 
830
+ // Reserve this turn synchronously before any async work. Bumping the
831
+ // generation invalidates any in-flight turn's end-of-turn cleanup, and
832
+ // recording myGeneration lets us skip cleanup if a newer turn (or abort)
833
+ // has superseded us. setIsLoading(true) here also closes the "idle but
834
+ // previous turn not finished" race window by marking us busy immediately.
835
+ this.turnGeneration++;
836
+ const myGeneration = this.turnGeneration;
837
+ this.setIsLoading(true);
838
+
821
839
  outer: while (true) {
822
840
  let shouldRestart = false;
823
841
 
@@ -839,9 +857,8 @@ export class AIManager {
839
857
  }).catch(() => {}); // Non-blocking
840
858
  }
841
859
 
842
- // Set loading state early for the initial call, before any async work
860
+ // Apply allowed rules for the initial call
843
861
  if (turnOffset === 0) {
844
- this.setIsLoading(true);
845
862
  if (allowedRules && allowedRules.length > 0) {
846
863
  this.permissionManager?.addTemporaryRules(allowedRules);
847
864
  }
@@ -1375,8 +1392,6 @@ export class AIManager {
1375
1392
 
1376
1393
  // Save session in each iteration to ensure message persistence
1377
1394
  await this.messageManager.saveSession();
1378
- // Set loading to false first
1379
- this.setIsLoading(false);
1380
1395
 
1381
1396
  // Clear temporary rules
1382
1397
  this.permissionManager?.clearTemporaryRules();
@@ -1475,11 +1490,11 @@ export class AIManager {
1475
1490
 
1476
1491
  // Inject pending notifications from background tasks (after Stop hooks,
1477
1492
  // aligned with Claude Code which fires Stop hooks unconditionally)
1478
- const notificationQueue = this.container.has("NotificationQueue")
1479
- ? this.container.get<NotificationQueue>("NotificationQueue")
1493
+ const messageQueue = this.container.has("MessageQueue")
1494
+ ? this.container.get<MessageQueue>("MessageQueue")
1480
1495
  : undefined;
1481
- if (notificationQueue && notificationQueue.hasPending()) {
1482
- const notifications = notificationQueue.dequeueAll();
1496
+ if (messageQueue && messageQueue.hasNotifications()) {
1497
+ const notifications = messageQueue.drainNotifications();
1483
1498
  for (const notification of notifications) {
1484
1499
  const block = parseTaskNotificationXml(notification);
1485
1500
  if (block) {
@@ -1498,7 +1513,16 @@ export class AIManager {
1498
1513
  }
1499
1514
  }
1500
1515
 
1501
- if (!shouldRestart) break outer;
1516
+ if (!shouldRestart) {
1517
+ // Release loading state only after ALL cleanup is done (session save,
1518
+ // Stop hooks, notification injection). Generation check ensures a
1519
+ // superseded (aborted or newer) turn doesn't clobber the current
1520
+ // loading state.
1521
+ if (myGeneration === this.turnGeneration) {
1522
+ this.setIsLoading(false);
1523
+ }
1524
+ break outer;
1525
+ }
1502
1526
  }
1503
1527
  }
1504
1528
 
@@ -6,7 +6,7 @@ import { BackgroundTask, BackgroundShell } from "../types/processes.js";
6
6
  import { stripAnsiColors } from "../utils/stringUtils.js";
7
7
  import { logger } from "../utils/globalLogger.js";
8
8
  import { Container } from "../utils/container.js";
9
- import { NotificationQueue } from "./notificationQueue.js";
9
+ import { MessageQueue } from "./messageQueue.js";
10
10
  import { resolveShellPath } from "../utils/shellResolver.js";
11
11
 
12
12
  export interface BackgroundTaskManagerCallbacks {
@@ -32,10 +32,6 @@ export class BackgroundTaskManager {
32
32
  this.workdir = options.workdir;
33
33
  }
34
34
 
35
- private get notificationQueue(): NotificationQueue {
36
- return this.container.get<NotificationQueue>("NotificationQueue")!;
37
- }
38
-
39
35
  /**
40
36
  * Fire the onBackgroundTasksChange callback so UI consumers refresh.
41
37
  * Public so other managers (e.g. WorkflowManager) can trigger a refresh
@@ -178,13 +174,13 @@ export class BackgroundTaskManager {
178
174
 
179
175
  // Skip notification if task was manually killed (user/agent-initiated stop)
180
176
  if (!wasKilled) {
181
- const notificationQueue = this.container.has("NotificationQueue")
182
- ? this.container.get<NotificationQueue>("NotificationQueue")
177
+ const messageQueue = this.container.has("MessageQueue")
178
+ ? this.container.get<MessageQueue>("MessageQueue")
183
179
  : undefined;
184
- if (notificationQueue) {
180
+ if (messageQueue) {
185
181
  const statusStr = shell.status;
186
182
  const summary = `Command "${command}" ${statusStr} with exit code ${code ?? 0}`;
187
- notificationQueue.enqueue(
183
+ messageQueue.enqueueNotification(
188
184
  `<task-notification>\n<task-id>${id}</task-id>\n<task-type>shell</task-type>\n<output-file>${logPath}</output-file>\n<status>${statusStr}</status>\n<summary>${summary}</summary>\n</task-notification>`,
189
185
  );
190
186
  }
@@ -208,12 +204,12 @@ export class BackgroundTaskManager {
208
204
  this.notifyTasksChange();
209
205
 
210
206
  // Enqueue error notification
211
- const notificationQueue = this.container.has("NotificationQueue")
212
- ? this.container.get<NotificationQueue>("NotificationQueue")
207
+ const messageQueue = this.container.has("MessageQueue")
208
+ ? this.container.get<MessageQueue>("MessageQueue")
213
209
  : undefined;
214
- if (notificationQueue) {
210
+ if (messageQueue) {
215
211
  const summary = `Command "${command}" failed with error: ${stripAnsiColors(error.message)}`;
216
- notificationQueue.enqueue(
212
+ messageQueue.enqueueNotification(
217
213
  `<task-notification>\n<task-id>${id}</task-id>\n<task-type>shell</task-type>\n<output-file>${logPath}</output-file>\n<status>failed</status>\n<summary>${summary}</summary>\n</task-notification>`,
218
214
  );
219
215
  }
@@ -337,13 +333,13 @@ export class BackgroundTaskManager {
337
333
 
338
334
  // Skip notification if task was manually killed (user/agent-initiated stop)
339
335
  if (!wasKilled) {
340
- const notificationQueue = this.container.has("NotificationQueue")
341
- ? this.container.get<NotificationQueue>("NotificationQueue")
336
+ const messageQueue = this.container.has("MessageQueue")
337
+ ? this.container.get<MessageQueue>("MessageQueue")
342
338
  : undefined;
343
- if (notificationQueue) {
339
+ if (messageQueue) {
344
340
  const statusStr = shell.status;
345
341
  const summary = `Command "${command}" ${statusStr} with exit code ${code ?? 0}`;
346
- notificationQueue.enqueue(
342
+ messageQueue.enqueueNotification(
347
343
  `<task-notification>\n<task-id>${id}</task-id>\n<task-type>shell</task-type>\n<output-file>${logPath}</output-file>\n<status>${statusStr}</status>\n<summary>${summary}</summary>\n</task-notification>`,
348
344
  );
349
345
  }
@@ -364,12 +360,12 @@ export class BackgroundTaskManager {
364
360
  this.notifyTasksChange();
365
361
 
366
362
  // Enqueue error notification
367
- const notificationQueue = this.container.has("NotificationQueue")
368
- ? this.container.get<NotificationQueue>("NotificationQueue")
363
+ const messageQueue = this.container.has("MessageQueue")
364
+ ? this.container.get<MessageQueue>("MessageQueue")
369
365
  : undefined;
370
- if (notificationQueue) {
366
+ if (messageQueue) {
371
367
  const summary = `Command "${command}" failed with error: ${stripAnsiColors(error.message)}`;
372
- notificationQueue.enqueue(
368
+ messageQueue.enqueueNotification(
373
369
  `<task-notification>\n<task-id>${id}</task-id>\n<task-type>shell</task-type>\n<output-file>${logPath}</output-file>\n<status>failed</status>\n<summary>${summary}</summary>\n</task-notification>`,
374
370
  );
375
371
  }
@@ -2,7 +2,7 @@ export type QueueState = "idle" | "dispatching" | "running";
2
2
 
3
3
  export interface QueuedMessage {
4
4
  id?: string;
5
- type?: "message" | "bang";
5
+ type?: "message" | "bang" | "notification";
6
6
  content: string;
7
7
  images?: Array<{ path: string; mimeType: string }>;
8
8
  longTextMap?: Record<string, string>;
@@ -44,8 +44,12 @@ export class MessageQueue {
44
44
  return this.queue.shift() ?? null;
45
45
  }
46
46
 
47
+ /**
48
+ * Clear user-facing items (messages, bang commands) but preserve pending
49
+ * notifications so background task results are not lost on abort.
50
+ */
47
51
  clear(): void {
48
- this.queue = [];
52
+ this.queue = this.queue.filter((m) => m.type === "notification");
49
53
  this._state = "idle";
50
54
  }
51
55
 
@@ -113,4 +117,41 @@ export class MessageQueue {
113
117
  this.queue = remaining;
114
118
  return editable;
115
119
  }
120
+
121
+ /**
122
+ * Enqueue a background task notification (XML string). Notifications are
123
+ * not user-editable and not surfaced in the queued-messages UI.
124
+ */
125
+ enqueueNotification(xml: string): void {
126
+ this.queue.push({
127
+ id: `mq-${this.nextId++}`,
128
+ type: "notification",
129
+ content: xml,
130
+ editable: false,
131
+ });
132
+ this.onMessageEnqueued?.();
133
+ }
134
+
135
+ /** Whether any notification items are pending. */
136
+ hasNotifications(): boolean {
137
+ return this.queue.some((m) => m.type === "notification");
138
+ }
139
+
140
+ /**
141
+ * Drain all notification items, returning their XML content. Non-notification
142
+ * items (messages, bang commands) are preserved in the queue.
143
+ */
144
+ drainNotifications(): string[] {
145
+ const notifications: string[] = [];
146
+ const remaining: QueuedMessage[] = [];
147
+ for (const msg of this.queue) {
148
+ if (msg.type === "notification") {
149
+ notifications.push(msg.content);
150
+ } else {
151
+ remaining.push(msg);
152
+ }
153
+ }
154
+ this.queue = remaining;
155
+ return notifications;
156
+ }
116
157
  }