clawmini 0.0.3 → 0.0.5

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 (333) hide show
  1. package/README.md +19 -0
  2. package/dist/adapter-discord/index.d.mts.map +1 -1
  3. package/dist/adapter-discord/index.mjs +398 -193
  4. package/dist/adapter-discord/index.mjs.map +1 -1
  5. package/dist/adapter-google-chat/index.d.mts +5 -0
  6. package/dist/adapter-google-chat/index.d.mts.map +1 -0
  7. package/dist/adapter-google-chat/index.mjs +1077 -0
  8. package/dist/adapter-google-chat/index.mjs.map +1 -0
  9. package/dist/cli/index.mjs +107 -14
  10. package/dist/cli/index.mjs.map +1 -1
  11. package/dist/cli/lite.mjs +175 -16
  12. package/dist/cli/lite.mjs.map +1 -1
  13. package/dist/cli/propose-policy.d.mts +1 -0
  14. package/dist/cli/propose-policy.mjs +7159 -0
  15. package/dist/cli/propose-policy.mjs.map +1 -0
  16. package/dist/daemon/index.d.mts.map +1 -1
  17. package/dist/daemon/index.mjs +1427 -513
  18. package/dist/daemon/index.mjs.map +1 -1
  19. package/dist/{lite-oSYSvaOr.mjs → lite-CBxOT1y5.mjs} +101 -24
  20. package/dist/lite-CBxOT1y5.mjs.map +1 -0
  21. package/dist/routing-D8rTxtaV.mjs +245 -0
  22. package/dist/routing-D8rTxtaV.mjs.map +1 -0
  23. package/dist/web/_app/immutable/assets/0.C-4eziNy.css +1 -0
  24. package/dist/web/_app/immutable/assets/4.Cc_xwLNl.css +1 -0
  25. package/dist/web/_app/immutable/chunks/B6YN0Nuq.js +1 -0
  26. package/dist/web/_app/immutable/chunks/{Dc-UOHw9.js → BmRlVmv6.js} +1 -1
  27. package/{web/.svelte-kit/output/client/_app/immutable/chunks/8YNcRyEk.js → dist/web/_app/immutable/chunks/C20lZMGz.js} +1 -1
  28. package/dist/web/_app/immutable/chunks/C9lbZ-kT.js +1 -0
  29. package/dist/web/_app/immutable/chunks/CK9JZLaG.js +2 -0
  30. package/dist/web/_app/immutable/chunks/CME08kGM.js +1 -0
  31. package/dist/web/_app/immutable/chunks/{BPy8HLo7.js → Ck-be5J2.js} +1 -1
  32. package/dist/web/_app/immutable/chunks/Ck3rYNON.js +1 -0
  33. package/dist/web/_app/immutable/chunks/DMtIqaiV.js +2 -0
  34. package/dist/web/_app/immutable/chunks/{B8yYFADm.js → DhD271EB.js} +1 -1
  35. package/dist/web/_app/immutable/chunks/{DcrmIfTj.js → DpuLqk8d.js} +1 -1
  36. package/dist/web/_app/immutable/chunks/{ZkLyk0mE.js → Drm9vgeP.js} +1 -1
  37. package/dist/web/_app/immutable/chunks/DsIToJCP.js +1 -0
  38. package/dist/web/_app/immutable/chunks/{CyNaE55B.js → Zeh-C-mx.js} +1 -1
  39. package/{web/.svelte-kit/output/client/_app/immutable/entry/app.DO5eYwVz.js → dist/web/_app/immutable/entry/app.BgB5VkRU.js} +2 -2
  40. package/dist/web/_app/immutable/entry/start.DuxJo6av.js +1 -0
  41. package/dist/web/_app/immutable/nodes/0.C9oFZP9h.js +1 -0
  42. package/dist/web/_app/immutable/nodes/1.BON2Wk6k.js +1 -0
  43. package/dist/web/_app/immutable/nodes/{2.CK3CLC0f.js → 2.BnwnD1Ki.js} +1 -1
  44. package/dist/web/_app/immutable/nodes/{3.ncP0xLO6.js → 3.CIs4tjjw.js} +1 -1
  45. package/dist/web/_app/immutable/nodes/4.DLarELN4.js +60 -0
  46. package/dist/web/_app/immutable/nodes/{5.BpJUN6QH.js → 5.CE_QKy_3.js} +1 -1
  47. package/dist/web/_app/version.json +1 -1
  48. package/dist/web/index.html +12 -12
  49. package/dist/{workspace-DjoNjhW0.mjs → workspace-BJmJBfKi.mjs} +103 -11
  50. package/dist/workspace-BJmJBfKi.mjs.map +1 -0
  51. package/docs/14_google_chat_adapter/development_log.md +40 -0
  52. package/docs/14_google_chat_adapter/notes.md +28 -0
  53. package/docs/14_google_chat_adapter/prd.md +35 -0
  54. package/docs/14_google_chat_adapter/questions.md +9 -0
  55. package/docs/14_google_chat_adapter/tickets.md +117 -0
  56. package/docs/15_sandbox_policies/tickets.md +33 -0
  57. package/docs/16_session_timeout/development_log.md +20 -0
  58. package/docs/16_session_timeout/notes.md +44 -0
  59. package/docs/16_session_timeout/prd.md +106 -0
  60. package/docs/16_session_timeout/questions.md +10 -0
  61. package/docs/16_session_timeout/tickets.md +64 -0
  62. package/docs/17_auto_approve_policy/development_log.md +29 -0
  63. package/docs/17_auto_approve_policy/notes.md +25 -0
  64. package/docs/17_auto_approve_policy/prd.md +34 -0
  65. package/docs/17_auto_approve_policy/questions.md +10 -0
  66. package/docs/17_auto_approve_policy/tickets.md +11 -0
  67. package/docs/18_clawmini_skills/development_log.md +36 -0
  68. package/docs/18_clawmini_skills/notes.md +8 -0
  69. package/docs/18_clawmini_skills/prd.md +45 -0
  70. package/docs/18_clawmini_skills/questions.md +10 -0
  71. package/docs/18_clawmini_skills/tickets.md +55 -0
  72. package/docs/19_subagents/development_log.md +69 -0
  73. package/docs/19_subagents/notes.md +18 -0
  74. package/docs/19_subagents/prd.md +156 -0
  75. package/docs/19_subagents/questions.md +13 -0
  76. package/docs/19_subagents/tickets.md +113 -0
  77. package/docs/20_chat_logs_cleanup/development_log.md +50 -0
  78. package/docs/20_chat_logs_cleanup/notes.md +43 -0
  79. package/docs/20_chat_logs_cleanup/prd.md +232 -0
  80. package/docs/20_chat_logs_cleanup/questions.md +2 -0
  81. package/docs/20_chat_logs_cleanup/tickets.md +98 -0
  82. package/docs/20_webui_markdown/development_log.md +36 -0
  83. package/docs/20_webui_markdown/notes.md +23 -0
  84. package/docs/20_webui_markdown/prd.md +49 -0
  85. package/docs/20_webui_markdown/questions.md +10 -0
  86. package/docs/20_webui_markdown/tickets.md +55 -0
  87. package/docs/21_adapter_filtering/development_log.md +29 -0
  88. package/docs/21_adapter_filtering/notes.md +25 -0
  89. package/docs/21_adapter_filtering/prd.md +44 -0
  90. package/docs/21_adapter_filtering/questions.md +12 -0
  91. package/docs/21_adapter_filtering/tickets.md +38 -0
  92. package/docs/21_built_in_routers/development_log.md +17 -0
  93. package/docs/21_built_in_routers/notes.md +27 -0
  94. package/docs/21_built_in_routers/prd.md +34 -0
  95. package/docs/21_built_in_routers/questions.md +4 -0
  96. package/docs/21_built_in_routers/tickets.md +25 -0
  97. package/docs/21_fancy_policies/development_log.md +38 -0
  98. package/docs/21_fancy_policies/notes.md +27 -0
  99. package/docs/21_fancy_policies/prd.md +58 -0
  100. package/docs/21_fancy_policies/questions.md +6 -0
  101. package/docs/21_fancy_policies/tickets.md +48 -0
  102. package/docs/22_adapter_multi_chat/development_log.md +76 -0
  103. package/docs/22_adapter_multi_chat/notes.md +42 -0
  104. package/docs/22_adapter_multi_chat/prd.md +76 -0
  105. package/docs/22_adapter_multi_chat/questions.md +16 -0
  106. package/docs/22_adapter_multi_chat/tickets.md +164 -0
  107. package/docs/23_custom_token_env/development_log.md +31 -0
  108. package/docs/23_custom_token_env/notes.md +16 -0
  109. package/docs/23_custom_token_env/prd.md +42 -0
  110. package/docs/23_custom_token_env/questions.md +8 -0
  111. package/docs/23_custom_token_env/tickets.md +54 -0
  112. package/docs/guides/discord_adapter_setup.md +15 -2
  113. package/docs/guides/google_chat_adapter_setup.md +145 -0
  114. package/napkin.md +5 -0
  115. package/package.json +7 -2
  116. package/src/adapter-discord/config.test.ts +27 -8
  117. package/src/adapter-discord/config.ts +6 -8
  118. package/src/adapter-discord/forwarder.test.ts +307 -114
  119. package/src/adapter-discord/forwarder.ts +260 -75
  120. package/src/adapter-discord/index.test.ts +278 -0
  121. package/src/adapter-discord/index.ts +160 -30
  122. package/src/adapter-discord/interactions.test.ts +96 -0
  123. package/src/adapter-discord/interactions.ts +156 -0
  124. package/src/adapter-discord/state.test.ts +9 -8
  125. package/src/adapter-discord/state.ts +51 -8
  126. package/src/adapter-google-chat/auth.test.ts +87 -0
  127. package/src/adapter-google-chat/auth.ts +132 -0
  128. package/src/adapter-google-chat/cards.ts +71 -0
  129. package/src/adapter-google-chat/client.test.ts +561 -0
  130. package/src/adapter-google-chat/client.ts +430 -0
  131. package/src/adapter-google-chat/config.test.ts +187 -0
  132. package/src/adapter-google-chat/config.ts +82 -0
  133. package/src/adapter-google-chat/cron.test.ts +143 -0
  134. package/src/adapter-google-chat/cron.ts +81 -0
  135. package/src/adapter-google-chat/forwarder.test.ts +537 -0
  136. package/src/adapter-google-chat/forwarder.ts +349 -0
  137. package/src/adapter-google-chat/index.test.ts +62 -0
  138. package/src/adapter-google-chat/index.ts +61 -0
  139. package/src/adapter-google-chat/state.test.ts +96 -0
  140. package/src/adapter-google-chat/state.ts +85 -0
  141. package/src/adapter-google-chat/subscriptions.ts +124 -0
  142. package/src/adapter-google-chat/upload.ts +88 -0
  143. package/src/adapter-google-chat/utils.test.ts +111 -0
  144. package/src/adapter-google-chat/utils.ts +133 -0
  145. package/src/cli/commands/init.ts +0 -7
  146. package/src/cli/commands/messages.ts +18 -3
  147. package/src/cli/commands/policies.ts +70 -0
  148. package/src/cli/commands/skills.ts +71 -0
  149. package/src/cli/commands/web-api/chats.ts +5 -1
  150. package/src/cli/e2e/basic.test.ts +1 -1
  151. package/src/cli/e2e/cron.test.ts +1 -1
  152. package/src/cli/e2e/daemon.test.ts +132 -4
  153. package/src/cli/e2e/export-lite-func.test.ts +54 -31
  154. package/src/cli/e2e/fallbacks.test.ts +8 -6
  155. package/src/cli/e2e/init.test.ts +7 -0
  156. package/src/cli/e2e/messages.test.ts +90 -55
  157. package/src/cli/e2e/propose-policy.test.ts +203 -0
  158. package/src/cli/e2e/requests.test.ts +15 -0
  159. package/src/cli/e2e/session-timeout.test.ts +192 -0
  160. package/src/cli/e2e/skills.test.ts +55 -0
  161. package/src/cli/e2e/slash-new.test.ts +93 -0
  162. package/src/cli/e2e/subagents.test.ts +106 -0
  163. package/src/cli/index.ts +4 -0
  164. package/src/cli/lite.ts +51 -11
  165. package/src/cli/propose-policy.ts +91 -0
  166. package/src/cli/subagent-commands.ts +215 -0
  167. package/src/daemon/agent/agent-context.ts +89 -0
  168. package/src/daemon/agent/agent-extractors.ts +68 -0
  169. package/src/daemon/agent/agent-runner.ts +153 -0
  170. package/src/daemon/agent/agent-session.ts +261 -0
  171. package/src/daemon/agent/chat-logger.test.ts +158 -0
  172. package/src/daemon/agent/chat-logger.ts +188 -0
  173. package/src/daemon/agent/task-scheduler.test.ts +202 -0
  174. package/src/daemon/agent/task-scheduler.ts +276 -0
  175. package/src/daemon/agent/types.ts +84 -0
  176. package/src/daemon/agent/utils.ts +7 -0
  177. package/src/daemon/api/agent-router.ts +166 -18
  178. package/src/daemon/api/index.test.ts +50 -18
  179. package/src/daemon/api/policy-request.test.ts +39 -2
  180. package/src/daemon/api/subagent-router.test.ts +108 -0
  181. package/src/daemon/api/subagent-router.ts +296 -0
  182. package/src/daemon/api/subagent-utils.test.ts +56 -0
  183. package/src/daemon/api/subagent-utils.ts +130 -0
  184. package/src/daemon/api/user-router.ts +30 -13
  185. package/src/daemon/auth.ts +1 -0
  186. package/src/daemon/chats.ts +6 -0
  187. package/src/daemon/cron.test.ts +66 -1
  188. package/src/daemon/cron.ts +35 -8
  189. package/src/daemon/index.ts +23 -0
  190. package/src/daemon/message-agent.test.ts +11 -25
  191. package/src/daemon/message-extraction.test.ts +10 -27
  192. package/src/daemon/message-fallbacks.test.ts +13 -35
  193. package/src/daemon/message-interruption.test.ts +70 -53
  194. package/src/daemon/message-jobs.test.ts +138 -0
  195. package/src/daemon/message-queue.test.ts +30 -43
  196. package/src/daemon/message-router.test.ts +12 -11
  197. package/src/daemon/message-session.test.ts +41 -28
  198. package/src/daemon/message-typing.test.ts +19 -6
  199. package/src/daemon/message.ts +103 -515
  200. package/src/daemon/policy-request-service.ts +8 -3
  201. package/src/daemon/policy-utils.ts +19 -1
  202. package/src/daemon/queue.ts +16 -0
  203. package/src/daemon/request-store.test.ts +4 -0
  204. package/src/daemon/routers/session-timeout.test.ts +122 -0
  205. package/src/daemon/routers/session-timeout.ts +71 -0
  206. package/src/daemon/routers/slash-new.ts +3 -1
  207. package/src/daemon/routers/slash-policies.test.ts +26 -13
  208. package/src/daemon/routers/slash-policies.ts +39 -29
  209. package/src/daemon/routers/types.ts +8 -0
  210. package/src/daemon/routers.ts +64 -2
  211. package/src/daemon/utils/spawn.ts +6 -8
  212. package/src/shared/adapters/commands.test.ts +155 -0
  213. package/src/shared/adapters/commands.ts +125 -0
  214. package/src/shared/adapters/filtering.test.ts +111 -0
  215. package/src/shared/adapters/filtering.ts +57 -0
  216. package/src/shared/adapters/routing.test.ts +144 -0
  217. package/src/shared/adapters/routing.ts +109 -0
  218. package/src/shared/agent-utils.ts +10 -0
  219. package/src/shared/chats.test.ts +145 -3
  220. package/src/shared/chats.ts +215 -18
  221. package/src/shared/config.ts +67 -15
  222. package/src/shared/lite.ts +22 -18
  223. package/src/shared/policies.ts +7 -0
  224. package/src/shared/workspace.test.ts +45 -1
  225. package/src/shared/workspace.ts +119 -6
  226. package/templates/debug/settings.json +5 -2
  227. package/templates/environments/cladding/env.json +2 -2
  228. package/templates/gemini/.gemini/hooks/check-subagents.mjs +23 -0
  229. package/templates/gemini/.gemini/hooks/clawmini-logging.sh +17 -0
  230. package/templates/gemini/.gemini/hooks/insert-pending.sh +9 -0
  231. package/templates/gemini/.gemini/settings.json +50 -0
  232. package/templates/gemini/settings.json +22 -8
  233. package/templates/gemini-claw/.gemini/base-system.md +100 -0
  234. package/templates/gemini-claw/.gemini/hooks/check-subagents.mjs +23 -0
  235. package/templates/gemini-claw/.gemini/hooks/clawmini-logging.sh +1 -1
  236. package/templates/gemini-claw/.gemini/settings.json +13 -0
  237. package/templates/gemini-claw/.gemini/subagent-system.md +7 -0
  238. package/templates/gemini-claw/.gemini/system.md +3 -99
  239. package/templates/gemini-claw/settings.json +27 -22
  240. package/templates/skills/clawmini-requests/SKILL.md +92 -0
  241. package/templates/skills/clawmini-subagents/SKILL.md +79 -0
  242. package/templates/skills/skill-creator/SKILL.md +60 -0
  243. package/tsdown.config.ts +10 -1
  244. package/web/.svelte-kit/generated/server/internal.js +2 -1
  245. package/web/.svelte-kit/non-ambient.d.ts +2 -0
  246. package/web/.svelte-kit/output/client/.vite/manifest.json +141 -138
  247. package/web/.svelte-kit/output/client/_app/immutable/assets/0.C-4eziNy.css +1 -0
  248. package/web/.svelte-kit/output/client/_app/immutable/assets/4.Cc_xwLNl.css +1 -0
  249. package/web/.svelte-kit/output/client/_app/immutable/chunks/B6YN0Nuq.js +1 -0
  250. package/web/.svelte-kit/output/client/_app/immutable/chunks/{Dc-UOHw9.js → BmRlVmv6.js} +1 -1
  251. package/{dist/web/_app/immutable/chunks/8YNcRyEk.js → web/.svelte-kit/output/client/_app/immutable/chunks/C20lZMGz.js} +1 -1
  252. package/web/.svelte-kit/output/client/_app/immutable/chunks/C9lbZ-kT.js +1 -0
  253. package/web/.svelte-kit/output/client/_app/immutable/chunks/CK9JZLaG.js +2 -0
  254. package/web/.svelte-kit/output/client/_app/immutable/chunks/CME08kGM.js +1 -0
  255. package/web/.svelte-kit/output/client/_app/immutable/chunks/{BPy8HLo7.js → Ck-be5J2.js} +1 -1
  256. package/web/.svelte-kit/output/client/_app/immutable/chunks/Ck3rYNON.js +1 -0
  257. package/web/.svelte-kit/output/client/_app/immutable/chunks/DMtIqaiV.js +2 -0
  258. package/web/.svelte-kit/output/client/_app/immutable/chunks/{B8yYFADm.js → DhD271EB.js} +1 -1
  259. package/web/.svelte-kit/output/client/_app/immutable/chunks/{DcrmIfTj.js → DpuLqk8d.js} +1 -1
  260. package/web/.svelte-kit/output/client/_app/immutable/chunks/{ZkLyk0mE.js → Drm9vgeP.js} +1 -1
  261. package/web/.svelte-kit/output/client/_app/immutable/chunks/DsIToJCP.js +1 -0
  262. package/web/.svelte-kit/output/client/_app/immutable/chunks/{CyNaE55B.js → Zeh-C-mx.js} +1 -1
  263. package/{dist/web/_app/immutable/entry/app.DO5eYwVz.js → web/.svelte-kit/output/client/_app/immutable/entry/app.BgB5VkRU.js} +2 -2
  264. package/web/.svelte-kit/output/client/_app/immutable/entry/start.DuxJo6av.js +1 -0
  265. package/web/.svelte-kit/output/client/_app/immutable/nodes/0.C9oFZP9h.js +1 -0
  266. package/web/.svelte-kit/output/client/_app/immutable/nodes/1.BON2Wk6k.js +1 -0
  267. package/web/.svelte-kit/output/client/_app/immutable/nodes/{2.CK3CLC0f.js → 2.BnwnD1Ki.js} +1 -1
  268. package/web/.svelte-kit/output/client/_app/immutable/nodes/{3.ncP0xLO6.js → 3.CIs4tjjw.js} +1 -1
  269. package/web/.svelte-kit/output/client/_app/immutable/nodes/4.DLarELN4.js +60 -0
  270. package/web/.svelte-kit/output/client/_app/immutable/nodes/{5.BpJUN6QH.js → 5.CE_QKy_3.js} +1 -1
  271. package/web/.svelte-kit/output/client/_app/version.json +1 -1
  272. package/web/.svelte-kit/output/server/.vite/manifest.json +12 -3
  273. package/web/.svelte-kit/output/server/_app/immutable/assets/_layout.C-4eziNy.css +1 -0
  274. package/web/.svelte-kit/output/server/_app/immutable/assets/_page.Cc_xwLNl.css +1 -0
  275. package/web/.svelte-kit/output/server/chunks/app-state.svelte.js +5 -0
  276. package/web/.svelte-kit/output/server/chunks/bot.js +4 -4
  277. package/web/.svelte-kit/output/server/chunks/client.js +2 -1
  278. package/web/.svelte-kit/output/server/chunks/exports.js +0 -1
  279. package/web/.svelte-kit/output/server/chunks/internal.js +2 -1
  280. package/web/.svelte-kit/output/server/chunks/root.js +482 -392
  281. package/web/.svelte-kit/output/server/entries/pages/_layout.svelte.js +57 -7
  282. package/web/.svelte-kit/output/server/entries/pages/chats/_id_/_page.svelte.js +234 -9
  283. package/web/.svelte-kit/output/server/index.js +82 -10
  284. package/web/.svelte-kit/output/server/manifest-full.js +1 -1
  285. package/web/.svelte-kit/output/server/manifest.js +1 -1
  286. package/web/.svelte-kit/output/server/nodes/0.js +2 -2
  287. package/web/.svelte-kit/output/server/nodes/1.js +1 -1
  288. package/web/.svelte-kit/output/server/nodes/2.js +1 -1
  289. package/web/.svelte-kit/output/server/nodes/3.js +1 -1
  290. package/web/.svelte-kit/output/server/nodes/4.js +2 -2
  291. package/web/.svelte-kit/output/server/nodes/5.js +1 -1
  292. package/web/.svelte-kit/types/src/routes/$types.d.ts +1 -2
  293. package/web/.svelte-kit/types/src/routes/agents/$types.d.ts +1 -2
  294. package/web/.svelte-kit/types/src/routes/chats/[id]/$types.d.ts +1 -2
  295. package/web/.svelte-kit/types/src/routes/chats/[id]/settings/$types.d.ts +1 -2
  296. package/web/package.json +8 -0
  297. package/web/src/lib/app-state.svelte.ts +5 -1
  298. package/web/src/lib/components/app/markdown-renderer.svelte +56 -0
  299. package/web/src/lib/components/app/markdown-renderer.svelte.spec.ts +44 -0
  300. package/web/src/lib/components/app/message-content.svelte +16 -0
  301. package/web/src/lib/types.ts +67 -3
  302. package/web/src/routes/+layout.svelte +31 -1
  303. package/web/src/routes/chats/[id]/+page.svelte +167 -18
  304. package/web/src/routes/chats/[id]/page.svelte.spec.ts +58 -7
  305. package/dist/lite-oSYSvaOr.mjs.map +0 -1
  306. package/dist/web/_app/immutable/assets/0.GI4C4dpV.css +0 -1
  307. package/dist/web/_app/immutable/chunks/B5abRDXp.js +0 -1
  308. package/dist/web/_app/immutable/chunks/Bi0jeV7Q.js +0 -1
  309. package/dist/web/_app/immutable/chunks/BmUXQ3wy.js +0 -2
  310. package/dist/web/_app/immutable/chunks/C3k55nDF.js +0 -1
  311. package/dist/web/_app/immutable/chunks/CpaGRn9L.js +0 -1
  312. package/dist/web/_app/immutable/chunks/DG5RZBw-.js +0 -2
  313. package/dist/web/_app/immutable/chunks/DQoygso7.js +0 -1
  314. package/dist/web/_app/immutable/entry/start.D48mVn1m.js +0 -1
  315. package/dist/web/_app/immutable/nodes/0.B-0CcADM.js +0 -1
  316. package/dist/web/_app/immutable/nodes/1.FixKgvRO.js +0 -1
  317. package/dist/web/_app/immutable/nodes/4.CQYJEgv8.js +0 -1
  318. package/dist/workspace-DjoNjhW0.mjs.map +0 -1
  319. package/src/daemon/message-verbosity.test.ts +0 -127
  320. package/web/.svelte-kit/output/client/_app/immutable/assets/0.GI4C4dpV.css +0 -1
  321. package/web/.svelte-kit/output/client/_app/immutable/chunks/B5abRDXp.js +0 -1
  322. package/web/.svelte-kit/output/client/_app/immutable/chunks/Bi0jeV7Q.js +0 -1
  323. package/web/.svelte-kit/output/client/_app/immutable/chunks/BmUXQ3wy.js +0 -2
  324. package/web/.svelte-kit/output/client/_app/immutable/chunks/C3k55nDF.js +0 -1
  325. package/web/.svelte-kit/output/client/_app/immutable/chunks/CpaGRn9L.js +0 -1
  326. package/web/.svelte-kit/output/client/_app/immutable/chunks/DG5RZBw-.js +0 -2
  327. package/web/.svelte-kit/output/client/_app/immutable/chunks/DQoygso7.js +0 -1
  328. package/web/.svelte-kit/output/client/_app/immutable/entry/start.D48mVn1m.js +0 -1
  329. package/web/.svelte-kit/output/client/_app/immutable/nodes/0.B-0CcADM.js +0 -1
  330. package/web/.svelte-kit/output/client/_app/immutable/nodes/1.FixKgvRO.js +0 -1
  331. package/web/.svelte-kit/output/client/_app/immutable/nodes/4.CQYJEgv8.js +0 -1
  332. package/web/.svelte-kit/output/server/_app/immutable/assets/_layout.GI4C4dpV.css +0 -1
  333. /package/templates/{gemini-claw/.gemini/skills → skills}/clawmini-jobs/SKILL.md +0 -0
@@ -2,12 +2,12 @@
2
2
  import schedule from 'node-schedule';
3
3
  import { listChats } from '../shared/chats.js';
4
4
  import { readChatSettings, writeChatSettings } from '../shared/workspace.js';
5
- import { executeDirectMessage, getInitialRouterState } from './message.js';
5
+ import { executeDirectMessage, getInitialRouterState, applyRouterStateUpdates } from './message.js';
6
+ import { executeRouterPipeline, resolveRouters } from './routers.js';
6
7
  import type { CronJob, Settings } from '../shared/config.js';
7
8
  import fs from 'node:fs/promises';
8
9
  import { getSettingsPath } from '../shared/workspace.js';
9
10
  import { applyEnvOverrides } from '../shared/utils/env.js';
10
- import { runCommand } from './utils/spawn.js';
11
11
 
12
12
  export class CronManager {
13
13
  private jobs = new Map<string, schedule.Job>();
@@ -117,11 +117,12 @@ export class CronManager {
117
117
  globalSettings = undefined;
118
118
  }
119
119
 
120
- const overrideSessionId = job.session?.type === 'new' ? crypto.randomUUID() : undefined;
121
- const routerState = await getInitialRouterState(
120
+ const overrideSessionId = job.session?.type === 'new' ? crypto.randomUUID() : job.session?.id;
121
+ const chatSettings = (await readChatSettings(chatId, process.cwd())) ?? {};
122
+ let routerState = await getInitialRouterState(
122
123
  chatId,
123
124
  job.message,
124
- process.cwd(),
125
+ chatSettings,
125
126
  job.agentId,
126
127
  overrideSessionId
127
128
  );
@@ -130,16 +131,42 @@ export class CronManager {
130
131
  routerState.env = routerState.env || {};
131
132
  applyEnvOverrides(routerState.env, job.env);
132
133
  }
133
- if (job.reply !== undefined) routerState.reply = job.reply;
134
+
135
+ const currentAgentId = job.agentId ?? chatSettings.defaultAgent ?? 'default';
136
+ const currentActiveSession = chatSettings.sessions?.[currentAgentId];
137
+ const isOutdatedSession =
138
+ job.session?.type === 'existing' &&
139
+ currentActiveSession !== undefined &&
140
+ currentActiveSession !== job.session.id;
141
+
142
+ if (job.reply !== undefined && !isOutdatedSession) routerState.reply = job.reply;
143
+ if (job.nextSessionId !== undefined && !isOutdatedSession)
144
+ routerState.nextSessionId = job.nextSessionId;
145
+ if (job.action !== undefined) routerState.action = job.action;
146
+ if (job.jobs !== undefined) routerState.jobs = job.jobs;
147
+
148
+ const routers = chatSettings.routers ?? globalSettings?.routers ?? [];
149
+ const resolvedRouters = resolveRouters(routers, false);
150
+ const initialState = { ...routerState };
151
+ routerState = await executeRouterPipeline(routerState, resolvedRouters);
152
+
153
+ await applyRouterStateUpdates(
154
+ chatId,
155
+ process.cwd(),
156
+ routerState,
157
+ chatSettings,
158
+ initialState.agentId
159
+ );
134
160
 
135
161
  await executeDirectMessage(
136
162
  chatId,
137
163
  routerState,
138
164
  globalSettings,
139
165
  process.cwd(),
140
- runCommand,
141
166
  false,
142
- job.message
167
+ job.message,
168
+ undefined,
169
+ 'cron'
143
170
  );
144
171
 
145
172
  if (isOneOff) {
@@ -12,7 +12,9 @@ import {
12
12
  readEnvironment,
13
13
  getEnvironmentPath,
14
14
  getWorkspaceRoot,
15
+ updateChatSettings,
15
16
  } from '../shared/workspace.js';
17
+ import { listChats } from '../shared/chats.js';
16
18
  import { cronManager } from './cron.js';
17
19
  import { SettingsSchema } from '../shared/config.js';
18
20
  import { validateToken, getApiContext } from './auth.js';
@@ -140,6 +142,27 @@ export async function initDaemon() {
140
142
  });
141
143
  });
142
144
 
145
+ const cleanOrphanedSubagents = async () => {
146
+ try {
147
+ const chats = await listChats();
148
+ for (const chatId of chats) {
149
+ await updateChatSettings(chatId, (settings) => {
150
+ if (settings.subagents) {
151
+ for (const subagent of Object.values(settings.subagents)) {
152
+ if (subagent.status === 'active') {
153
+ subagent.status = 'failed';
154
+ }
155
+ }
156
+ }
157
+ return settings;
158
+ });
159
+ }
160
+ } catch (err) {
161
+ console.warn('Failed to clean orphaned subagents:', err);
162
+ }
163
+ };
164
+ await cleanOrphanedSubagents();
165
+
143
166
  await runHooks('up');
144
167
 
145
168
  isReady = true;
@@ -3,14 +3,21 @@ import { describe, it, expect, vi, beforeEach } from 'vitest';
3
3
  import { handleUserMessage } from './message.js';
4
4
  import * as workspace from '../shared/workspace.js';
5
5
  import { spawn } from 'node:child_process';
6
- import { runCommandCallback, createAutoFinishMockSpawn } from './message-test-utils.js';
6
+ import { createAutoFinishMockSpawn } from './message-test-utils.js';
7
7
 
8
8
  vi.mock('node:child_process', () => ({ spawn: vi.fn() }));
9
9
  vi.mock('../shared/chats.js', () => ({ appendMessage: vi.fn().mockResolvedValue(undefined) }));
10
10
  vi.mock('./routers.js', () => ({
11
+ resolveRouters: vi.fn((routers) => routers),
11
12
  executeRouterPipeline: vi.fn().mockImplementation((state) => Promise.resolve(state)),
12
13
  }));
13
14
  vi.mock('../shared/workspace.js', () => ({
15
+ resolveAgentWorkDir: vi
16
+ .fn()
17
+ .mockImplementation((id, dir, root) => (dir ? `${root}/${dir}` : `${root}/${id}`)),
18
+
19
+ readSettings: vi.fn().mockResolvedValue(null),
20
+
14
21
  readChatSettings: vi.fn().mockResolvedValue(null),
15
22
  writeChatSettings: vi.fn().mockResolvedValue(undefined),
16
23
  readAgentSessionSettings: vi.fn().mockResolvedValue(null),
@@ -50,14 +57,7 @@ describe('Agent Configuration & Execution CWD', () => {
50
57
  },
51
58
  };
52
59
 
53
- await handleUserMessage(
54
- 'chat-custom',
55
- 'hello',
56
- settings as any,
57
- '/dir',
58
- false,
59
- runCommandCallback
60
- );
60
+ await handleUserMessage('chat-custom', 'hello', settings as any, '/dir', false);
61
61
 
62
62
  expect(workspace.getAgent).toHaveBeenCalledWith('custom-agent', '/dir');
63
63
  expect(mockSpawn).toHaveBeenCalledWith(
@@ -83,14 +83,7 @@ describe('Agent Configuration & Execution CWD', () => {
83
83
 
84
84
  const settings = { defaultAgent: { commands: { new: 'echo main' } } };
85
85
 
86
- await handleUserMessage(
87
- 'chat-dir-1',
88
- 'hi',
89
- settings as any,
90
- '/base/workspace',
91
- false,
92
- runCommandCallback
93
- );
86
+ await handleUserMessage('chat-dir-1', 'hi', settings as any, '/base/workspace', false);
94
87
 
95
88
  expect(mockSpawn).toHaveBeenCalledWith(
96
89
  'echo agent-dir',
@@ -113,14 +106,7 @@ describe('Agent Configuration & Execution CWD', () => {
113
106
 
114
107
  const settings = { defaultAgent: { commands: { new: 'echo main' } } };
115
108
 
116
- await handleUserMessage(
117
- 'chat-dir-2',
118
- 'hi',
119
- settings as any,
120
- '/base/workspace',
121
- false,
122
- runCommandCallback
123
- );
109
+ await handleUserMessage('chat-dir-2', 'hi', settings as any, '/base/workspace', false);
124
110
 
125
111
  expect(mockSpawn).toHaveBeenCalledWith(
126
112
  'echo my-dir',
@@ -4,15 +4,21 @@ import { handleUserMessage } from './message.js';
4
4
  import * as workspace from '../shared/workspace.js';
5
5
  import * as chats from './chats.js';
6
6
  import { spawn } from 'node:child_process';
7
- import { runCommandCallback } from './message-test-utils.js';
8
7
  import { EventEmitter } from 'node:events';
9
8
 
10
9
  vi.mock('node:child_process', () => ({ spawn: vi.fn() }));
11
10
  vi.mock('./chats.js', () => ({ appendMessage: vi.fn().mockResolvedValue(undefined) }));
12
11
  vi.mock('./routers.js', () => ({
12
+ resolveRouters: vi.fn((routers) => routers),
13
13
  executeRouterPipeline: vi.fn().mockImplementation((state) => Promise.resolve(state)),
14
14
  }));
15
15
  vi.mock('../shared/workspace.js', () => ({
16
+ resolveAgentWorkDir: vi
17
+ .fn()
18
+ .mockImplementation((id, dir, root) => (dir ? `${root}/${dir}` : `${root}/${id}`)),
19
+
20
+ readSettings: vi.fn().mockResolvedValue(null),
21
+
16
22
  readChatSettings: vi.fn().mockResolvedValue(null),
17
23
  writeChatSettings: vi.fn().mockResolvedValue(undefined),
18
24
  readAgentSessionSettings: vi.fn().mockResolvedValue(null),
@@ -68,14 +74,7 @@ describe('Extraction Logic', () => {
68
74
  },
69
75
  };
70
76
 
71
- await handleUserMessage(
72
- 'chat1',
73
- 'hello',
74
- settings as any,
75
- '/dir-extract-1',
76
- false,
77
- runCommandCallback
78
- );
77
+ await handleUserMessage('chat1', 'hello', settings as any, '/dir-extract-1', false);
79
78
 
80
79
  // Verify spawn was called twice
81
80
  expect(mockSpawn).toHaveBeenCalledTimes(2);
@@ -84,15 +83,6 @@ describe('Extraction Logic', () => {
84
83
  expect(mockSpawn).toHaveBeenNthCalledWith(2, 'echo getSessionId', expect.anything());
85
84
 
86
85
  // Verify state files were updated
87
- expect(workspace.writeChatSettings).toHaveBeenCalledWith(
88
- 'chat1',
89
- expect.objectContaining({
90
- defaultAgent: 'my-agent',
91
- sessions: { 'my-agent': 'default' },
92
- }),
93
- '/dir-extract-1'
94
- );
95
-
96
86
  expect(workspace.writeAgentSessionSettings).toHaveBeenCalledWith(
97
87
  'my-agent',
98
88
  'default',
@@ -141,14 +131,7 @@ describe('Extraction Logic', () => {
141
131
  },
142
132
  };
143
133
 
144
- await handleUserMessage(
145
- 'chat1',
146
- 'hello',
147
- settings as any,
148
- '/dir-extract-2',
149
- false,
150
- runCommandCallback
151
- );
134
+ await handleUserMessage('chat1', 'hello', settings as any, '/dir-extract-2', false);
152
135
 
153
136
  expect(mockSpawn).toHaveBeenCalledTimes(2);
154
137
  expect(mockSpawn).toHaveBeenNthCalledWith(2, 'echo getMessageContent', expect.anything());
@@ -157,7 +140,7 @@ describe('Extraction Logic', () => {
157
140
  expect(chats.appendMessage).toHaveBeenCalledWith(
158
141
  'chat1',
159
142
  expect.objectContaining({
160
- role: 'log',
143
+ role: 'command',
161
144
  content: 'extracted message content',
162
145
  stdout: 'main_output',
163
146
  })
@@ -2,15 +2,21 @@
2
2
  import { describe, it, expect, vi, beforeEach } from 'vitest';
3
3
  import { handleUserMessage, calculateDelay } from './message.js';
4
4
  import { spawn } from 'node:child_process';
5
- import { runCommandCallback } from './message-test-utils.js';
6
5
  import * as chats from '../shared/chats.js';
7
6
 
8
7
  vi.mock('node:child_process', () => ({ spawn: vi.fn() }));
9
8
  vi.mock('../shared/chats.js', () => ({ appendMessage: vi.fn().mockResolvedValue(undefined) }));
10
9
  vi.mock('./routers.js', () => ({
10
+ resolveRouters: vi.fn((routers) => routers),
11
11
  executeRouterPipeline: vi.fn().mockImplementation((state) => Promise.resolve(state)),
12
12
  }));
13
13
  vi.mock('../shared/workspace.js', () => ({
14
+ resolveAgentWorkDir: vi
15
+ .fn()
16
+ .mockImplementation((id, dir, root) => (dir ? `${root}/${dir}` : `${root}/${id}`)),
17
+
18
+ readSettings: vi.fn().mockResolvedValue(null),
19
+
14
20
  readChatSettings: vi.fn().mockResolvedValue(null),
15
21
  writeChatSettings: vi.fn().mockResolvedValue(undefined),
16
22
  readAgentSessionSettings: vi.fn().mockResolvedValue(null),
@@ -109,14 +115,7 @@ describe('Message Fallbacks & Retries', () => {
109
115
  },
110
116
  };
111
117
 
112
- await handleUserMessage(
113
- 'chat-fallback',
114
- 'hello',
115
- settings as any,
116
- '/dir',
117
- false,
118
- runCommandCallback
119
- );
118
+ await handleUserMessage('chat-fallback', 'hello', settings as any, '/dir', false);
120
119
 
121
120
  // Should call base once, then fallback once
122
121
  expect(mockSpawn).toHaveBeenCalledTimes(2);
@@ -127,7 +126,7 @@ describe('Message Fallbacks & Retries', () => {
127
126
  expect(chats.appendMessage).toHaveBeenCalledWith(
128
127
  'chat-fallback',
129
128
  expect.objectContaining({
130
- role: 'log',
129
+ role: 'command',
131
130
  content: 'output 2',
132
131
  exitCode: 0,
133
132
  }),
@@ -175,14 +174,7 @@ describe('Message Fallbacks & Retries', () => {
175
174
  },
176
175
  };
177
176
 
178
- await handleUserMessage(
179
- 'chat-empty',
180
- 'hello',
181
- settings as any,
182
- '/dir',
183
- false,
184
- runCommandCallback
185
- );
177
+ await handleUserMessage('chat-empty', 'hello', settings as any, '/dir', false);
186
178
 
187
179
  // Call 1: base (success)
188
180
  // Call 2: getMessageContent (returns empty -> failure)
@@ -233,14 +225,7 @@ describe('Message Fallbacks & Retries', () => {
233
225
  },
234
226
  };
235
227
 
236
- await handleUserMessage(
237
- 'chat-retries',
238
- 'hello',
239
- settings as any,
240
- '/dir',
241
- false,
242
- runCommandCallback
243
- );
228
+ await handleUserMessage('chat-retries', 'hello', settings as any, '/dir', false);
244
229
 
245
230
  // Call 1: base (fail)
246
231
  // Call 2: fallback attempt 0 (fail)
@@ -290,20 +275,13 @@ describe('Message Fallbacks & Retries', () => {
290
275
  },
291
276
  };
292
277
 
293
- await handleUserMessage(
294
- 'chat-log-retry',
295
- 'hello',
296
- settings as any,
297
- '/dir',
298
- false,
299
- runCommandCallback
300
- );
278
+ await handleUserMessage('chat-log-retry', 'hello', settings as any, '/dir', false);
301
279
 
302
280
  // Should find the retry log message
303
281
  expect(chats.appendMessage).toHaveBeenCalledWith(
304
282
  'chat-log-retry',
305
283
  expect.objectContaining({
306
- role: 'log',
284
+ role: 'command',
307
285
  content: 'Error running agent, retrying in 1 seconds...',
308
286
  command: 'retry-delay',
309
287
  }),
@@ -1,12 +1,22 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
2
  import { executeDirectMessage } from './message.js';
3
- import { getMessageQueue } from './queue.js';
3
+ import { taskScheduler } from './agent/task-scheduler.js';
4
4
  import type { RouterState } from './routers/types.js';
5
+ import { runCommand } from './utils/spawn.js';
6
+ import { randomUUID } from 'node:crypto';
7
+
8
+ vi.mock('./utils/spawn.js', () => ({ runCommand: vi.fn() }));
5
9
 
6
10
  vi.mock('./chats.js', () => ({
7
11
  appendMessage: vi.fn().mockResolvedValue(undefined),
8
12
  }));
9
13
  vi.mock('../shared/workspace.js', () => ({
14
+ resolveAgentWorkDir: vi
15
+ .fn()
16
+ .mockImplementation((id, dir, root) => (dir ? `${root}/${dir}` : `${root}/${id}`)),
17
+
18
+ readSettings: vi.fn().mockResolvedValue(null),
19
+
10
20
  readChatSettings: vi.fn().mockResolvedValue(null),
11
21
  writeChatSettings: vi.fn().mockResolvedValue(undefined),
12
22
  readAgentSessionSettings: vi.fn().mockResolvedValue(null),
@@ -25,55 +35,72 @@ describe('Interruption flow in message handler', () => {
25
35
  });
26
36
 
27
37
  it('stops execution and clears queue when action is stop', async () => {
28
- const queue = getMessageQueue('/test-interrupt-stop');
29
- const abortSpy = vi.spyOn(queue, 'abortCurrent');
30
- const clearSpy = vi.spyOn(queue, 'clear');
38
+ const sessionId = 'test-interrupt-stop';
39
+ taskScheduler.abortTasks(sessionId);
40
+ const abortSpy = vi.spyOn(taskScheduler, 'abortTasks');
31
41
 
32
42
  const state: RouterState = {
33
43
  message: 'stop everything',
34
44
  messageId: 'mock-msg-id',
35
45
  chatId: 'chat1',
36
46
  action: 'stop',
47
+ sessionId,
37
48
  };
38
49
 
39
- const runCommand = vi.fn();
40
- await executeDirectMessage('chat1', state, undefined, '/test-interrupt-stop', runCommand, true);
50
+ vi.mocked(runCommand).mockResolvedValue({ stdout: '', stderr: '', exitCode: 0 });
51
+ await executeDirectMessage('chat1', state, undefined, '/test-interrupt-stop', true);
41
52
 
42
- expect(abortSpy).toHaveBeenCalled();
43
- expect(clearSpy).toHaveBeenCalled();
53
+ expect(abortSpy).toHaveBeenCalledWith(sessionId);
44
54
  expect(runCommand).not.toHaveBeenCalled();
45
55
 
46
56
  // We expect it NOT to enqueue because it returns early
47
- expect(queue['pending'].length).toBe(0);
57
+ const key = `chat1:${sessionId}`;
58
+ expect(taskScheduler['queues'].get(key)?.['queue'].length ?? 0).toBe(0);
48
59
  });
49
60
 
50
61
  it('interrupts execution and batches pending tasks when action is interrupt', async () => {
51
- const queue = getMessageQueue('/test-interrupt-batch');
52
- const abortSpy = vi.spyOn(queue, 'abortCurrent');
62
+ const sessionId = 'test-interrupt-batch';
63
+ taskScheduler.abortTasks(sessionId);
64
+ const interruptSpy = vi.spyOn(taskScheduler, 'interruptTasks');
53
65
 
54
66
  // Block the queue with a running task so subsequent ones stay pending
55
- queue
56
- .enqueue(async () => {
57
- await new Promise((r) => setTimeout(r, 500));
67
+ taskScheduler
68
+ .schedule({
69
+ id: randomUUID(),
70
+ rootChatId: 'chat1',
71
+ dirPath: 'dir1',
72
+ sessionId,
73
+ execute: async () => {
74
+ await new Promise((r) => setTimeout(r, 500));
75
+ },
58
76
  })
59
77
  .catch(() => {});
60
78
 
61
79
  // Enqueue some dummy tasks with payloads
62
- queue
63
- .enqueue(
64
- async () => {
80
+ taskScheduler
81
+ .schedule({
82
+ id: randomUUID(),
83
+ rootChatId: 'chat1',
84
+ dirPath: 'dir1',
85
+ sessionId,
86
+ text: 'pending 1',
87
+ execute: async () => {
65
88
  await new Promise((r) => setTimeout(r, 100));
66
89
  },
67
- { text: 'pending 1', sessionId: 'test-session' }
68
- )
90
+ })
69
91
  .catch(() => {});
70
- queue
71
- .enqueue(
72
- async () => {
92
+
93
+ taskScheduler
94
+ .schedule({
95
+ id: randomUUID(),
96
+ rootChatId: 'chat1',
97
+ dirPath: 'dir1',
98
+ sessionId,
99
+ text: 'pending 2',
100
+ execute: async () => {
73
101
  await new Promise((r) => setTimeout(r, 100));
74
102
  },
75
- { text: 'pending 2', sessionId: 'test-session' }
76
- )
103
+ })
77
104
  .catch(() => {});
78
105
 
79
106
  const state: RouterState = {
@@ -81,52 +108,42 @@ describe('Interruption flow in message handler', () => {
81
108
  messageId: 'mock-msg-id',
82
109
  chatId: 'chat1',
83
110
  action: 'interrupt',
84
- sessionId: 'test-session',
111
+ sessionId,
85
112
  };
86
113
 
87
- const runCommand = vi.fn().mockResolvedValue({ stdout: 'done', stderr: '', exitCode: 0 });
88
-
89
- await executeDirectMessage(
90
- 'chat1',
91
- state,
92
- undefined,
93
- '/test-interrupt-batch',
94
- runCommand,
95
- true
96
- );
114
+ vi.mocked(runCommand).mockResolvedValue({ stdout: 'done', stderr: '', exitCode: 0 });
97
115
 
98
- expect(abortSpy).toHaveBeenCalled();
116
+ await executeDirectMessage('chat1', state, undefined, '/test-interrupt-batch', true);
99
117
 
100
- // Should have concatenated the pending tasks with the new message
101
- // and enqueued it.
118
+ expect(interruptSpy).toHaveBeenCalledWith(sessionId);
102
119
 
103
- // In our executeDirectMessage, the state.message gets mutated.
104
- // However, it's easier to verify what was enqueued by extracting pending again,
105
- // or by checking state.message.
106
- expect(state.message).toBe(
120
+ // Verify that the new task enqueued contains the merged payload
121
+ const queueKey = `chat1:${sessionId}`;
122
+ const queueItems = taskScheduler['queues'].get(queueKey)?.['queue'] || [];
123
+ const newlyEnqueued = queueItems.find((t) => t.task.sessionId === sessionId);
124
+ expect(newlyEnqueued).toBeDefined();
125
+ expect(newlyEnqueued?.task.text).toBe(
107
126
  '<message>\npending 1\n</message>\n\n<message>\npending 2\n</message>\n\n<message>\nnew urgent task\n</message>'
108
127
  );
109
128
  });
110
129
 
111
130
  it('returns early when message is empty and no action is specified', async () => {
112
- const queue = getMessageQueue('/test-interrupt-empty');
131
+ const sessionId = 'test-interrupt-empty';
132
+ taskScheduler.abortTasks(sessionId);
133
+
113
134
  const state: RouterState = {
114
135
  message: ' ',
115
136
  messageId: 'mock-msg-id',
116
137
  chatId: 'chat1',
138
+ sessionId,
117
139
  };
118
140
 
119
- const runCommand = vi.fn();
120
- await executeDirectMessage(
121
- 'chat1',
122
- state,
123
- undefined,
124
- '/test-interrupt-empty',
125
- runCommand,
126
- true
127
- );
141
+ vi.mocked(runCommand).mockResolvedValue({ stdout: '', stderr: '', exitCode: 0 });
142
+ await executeDirectMessage('chat1', state, undefined, '/test-interrupt-empty', true);
128
143
 
129
144
  expect(runCommand).not.toHaveBeenCalled();
130
- expect(queue['pending'].length).toBe(0);
145
+ const queueKey = `chat1:${sessionId}`;
146
+ const queuedForSession = taskScheduler['queues'].get(queueKey)?.['queue'] || [];
147
+ expect(queuedForSession.length).toBe(0);
131
148
  });
132
149
  });