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.
- package/README.md +19 -0
- package/dist/adapter-discord/index.d.mts.map +1 -1
- package/dist/adapter-discord/index.mjs +398 -193
- package/dist/adapter-discord/index.mjs.map +1 -1
- package/dist/adapter-google-chat/index.d.mts +5 -0
- package/dist/adapter-google-chat/index.d.mts.map +1 -0
- package/dist/adapter-google-chat/index.mjs +1077 -0
- package/dist/adapter-google-chat/index.mjs.map +1 -0
- package/dist/cli/index.mjs +107 -14
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lite.mjs +175 -16
- package/dist/cli/lite.mjs.map +1 -1
- package/dist/cli/propose-policy.d.mts +1 -0
- package/dist/cli/propose-policy.mjs +7159 -0
- package/dist/cli/propose-policy.mjs.map +1 -0
- package/dist/daemon/index.d.mts.map +1 -1
- package/dist/daemon/index.mjs +1427 -513
- package/dist/daemon/index.mjs.map +1 -1
- package/dist/{lite-oSYSvaOr.mjs → lite-CBxOT1y5.mjs} +101 -24
- package/dist/lite-CBxOT1y5.mjs.map +1 -0
- package/dist/routing-D8rTxtaV.mjs +245 -0
- package/dist/routing-D8rTxtaV.mjs.map +1 -0
- package/dist/web/_app/immutable/assets/0.C-4eziNy.css +1 -0
- package/dist/web/_app/immutable/assets/4.Cc_xwLNl.css +1 -0
- package/dist/web/_app/immutable/chunks/B6YN0Nuq.js +1 -0
- package/dist/web/_app/immutable/chunks/{Dc-UOHw9.js → BmRlVmv6.js} +1 -1
- package/{web/.svelte-kit/output/client/_app/immutable/chunks/8YNcRyEk.js → dist/web/_app/immutable/chunks/C20lZMGz.js} +1 -1
- package/dist/web/_app/immutable/chunks/C9lbZ-kT.js +1 -0
- package/dist/web/_app/immutable/chunks/CK9JZLaG.js +2 -0
- package/dist/web/_app/immutable/chunks/CME08kGM.js +1 -0
- package/dist/web/_app/immutable/chunks/{BPy8HLo7.js → Ck-be5J2.js} +1 -1
- package/dist/web/_app/immutable/chunks/Ck3rYNON.js +1 -0
- package/dist/web/_app/immutable/chunks/DMtIqaiV.js +2 -0
- package/dist/web/_app/immutable/chunks/{B8yYFADm.js → DhD271EB.js} +1 -1
- package/dist/web/_app/immutable/chunks/{DcrmIfTj.js → DpuLqk8d.js} +1 -1
- package/dist/web/_app/immutable/chunks/{ZkLyk0mE.js → Drm9vgeP.js} +1 -1
- package/dist/web/_app/immutable/chunks/DsIToJCP.js +1 -0
- package/dist/web/_app/immutable/chunks/{CyNaE55B.js → Zeh-C-mx.js} +1 -1
- package/{web/.svelte-kit/output/client/_app/immutable/entry/app.DO5eYwVz.js → dist/web/_app/immutable/entry/app.BgB5VkRU.js} +2 -2
- package/dist/web/_app/immutable/entry/start.DuxJo6av.js +1 -0
- package/dist/web/_app/immutable/nodes/0.C9oFZP9h.js +1 -0
- package/dist/web/_app/immutable/nodes/1.BON2Wk6k.js +1 -0
- package/dist/web/_app/immutable/nodes/{2.CK3CLC0f.js → 2.BnwnD1Ki.js} +1 -1
- package/dist/web/_app/immutable/nodes/{3.ncP0xLO6.js → 3.CIs4tjjw.js} +1 -1
- package/dist/web/_app/immutable/nodes/4.DLarELN4.js +60 -0
- package/dist/web/_app/immutable/nodes/{5.BpJUN6QH.js → 5.CE_QKy_3.js} +1 -1
- package/dist/web/_app/version.json +1 -1
- package/dist/web/index.html +12 -12
- package/dist/{workspace-DjoNjhW0.mjs → workspace-BJmJBfKi.mjs} +103 -11
- package/dist/workspace-BJmJBfKi.mjs.map +1 -0
- package/docs/14_google_chat_adapter/development_log.md +40 -0
- package/docs/14_google_chat_adapter/notes.md +28 -0
- package/docs/14_google_chat_adapter/prd.md +35 -0
- package/docs/14_google_chat_adapter/questions.md +9 -0
- package/docs/14_google_chat_adapter/tickets.md +117 -0
- package/docs/15_sandbox_policies/tickets.md +33 -0
- package/docs/16_session_timeout/development_log.md +20 -0
- package/docs/16_session_timeout/notes.md +44 -0
- package/docs/16_session_timeout/prd.md +106 -0
- package/docs/16_session_timeout/questions.md +10 -0
- package/docs/16_session_timeout/tickets.md +64 -0
- package/docs/17_auto_approve_policy/development_log.md +29 -0
- package/docs/17_auto_approve_policy/notes.md +25 -0
- package/docs/17_auto_approve_policy/prd.md +34 -0
- package/docs/17_auto_approve_policy/questions.md +10 -0
- package/docs/17_auto_approve_policy/tickets.md +11 -0
- package/docs/18_clawmini_skills/development_log.md +36 -0
- package/docs/18_clawmini_skills/notes.md +8 -0
- package/docs/18_clawmini_skills/prd.md +45 -0
- package/docs/18_clawmini_skills/questions.md +10 -0
- package/docs/18_clawmini_skills/tickets.md +55 -0
- package/docs/19_subagents/development_log.md +69 -0
- package/docs/19_subagents/notes.md +18 -0
- package/docs/19_subagents/prd.md +156 -0
- package/docs/19_subagents/questions.md +13 -0
- package/docs/19_subagents/tickets.md +113 -0
- package/docs/20_chat_logs_cleanup/development_log.md +50 -0
- package/docs/20_chat_logs_cleanup/notes.md +43 -0
- package/docs/20_chat_logs_cleanup/prd.md +232 -0
- package/docs/20_chat_logs_cleanup/questions.md +2 -0
- package/docs/20_chat_logs_cleanup/tickets.md +98 -0
- package/docs/20_webui_markdown/development_log.md +36 -0
- package/docs/20_webui_markdown/notes.md +23 -0
- package/docs/20_webui_markdown/prd.md +49 -0
- package/docs/20_webui_markdown/questions.md +10 -0
- package/docs/20_webui_markdown/tickets.md +55 -0
- package/docs/21_adapter_filtering/development_log.md +29 -0
- package/docs/21_adapter_filtering/notes.md +25 -0
- package/docs/21_adapter_filtering/prd.md +44 -0
- package/docs/21_adapter_filtering/questions.md +12 -0
- package/docs/21_adapter_filtering/tickets.md +38 -0
- package/docs/21_built_in_routers/development_log.md +17 -0
- package/docs/21_built_in_routers/notes.md +27 -0
- package/docs/21_built_in_routers/prd.md +34 -0
- package/docs/21_built_in_routers/questions.md +4 -0
- package/docs/21_built_in_routers/tickets.md +25 -0
- package/docs/21_fancy_policies/development_log.md +38 -0
- package/docs/21_fancy_policies/notes.md +27 -0
- package/docs/21_fancy_policies/prd.md +58 -0
- package/docs/21_fancy_policies/questions.md +6 -0
- package/docs/21_fancy_policies/tickets.md +48 -0
- package/docs/22_adapter_multi_chat/development_log.md +76 -0
- package/docs/22_adapter_multi_chat/notes.md +42 -0
- package/docs/22_adapter_multi_chat/prd.md +76 -0
- package/docs/22_adapter_multi_chat/questions.md +16 -0
- package/docs/22_adapter_multi_chat/tickets.md +164 -0
- package/docs/23_custom_token_env/development_log.md +31 -0
- package/docs/23_custom_token_env/notes.md +16 -0
- package/docs/23_custom_token_env/prd.md +42 -0
- package/docs/23_custom_token_env/questions.md +8 -0
- package/docs/23_custom_token_env/tickets.md +54 -0
- package/docs/guides/discord_adapter_setup.md +15 -2
- package/docs/guides/google_chat_adapter_setup.md +145 -0
- package/napkin.md +5 -0
- package/package.json +7 -2
- package/src/adapter-discord/config.test.ts +27 -8
- package/src/adapter-discord/config.ts +6 -8
- package/src/adapter-discord/forwarder.test.ts +307 -114
- package/src/adapter-discord/forwarder.ts +260 -75
- package/src/adapter-discord/index.test.ts +278 -0
- package/src/adapter-discord/index.ts +160 -30
- package/src/adapter-discord/interactions.test.ts +96 -0
- package/src/adapter-discord/interactions.ts +156 -0
- package/src/adapter-discord/state.test.ts +9 -8
- package/src/adapter-discord/state.ts +51 -8
- package/src/adapter-google-chat/auth.test.ts +87 -0
- package/src/adapter-google-chat/auth.ts +132 -0
- package/src/adapter-google-chat/cards.ts +71 -0
- package/src/adapter-google-chat/client.test.ts +561 -0
- package/src/adapter-google-chat/client.ts +430 -0
- package/src/adapter-google-chat/config.test.ts +187 -0
- package/src/adapter-google-chat/config.ts +82 -0
- package/src/adapter-google-chat/cron.test.ts +143 -0
- package/src/adapter-google-chat/cron.ts +81 -0
- package/src/adapter-google-chat/forwarder.test.ts +537 -0
- package/src/adapter-google-chat/forwarder.ts +349 -0
- package/src/adapter-google-chat/index.test.ts +62 -0
- package/src/adapter-google-chat/index.ts +61 -0
- package/src/adapter-google-chat/state.test.ts +96 -0
- package/src/adapter-google-chat/state.ts +85 -0
- package/src/adapter-google-chat/subscriptions.ts +124 -0
- package/src/adapter-google-chat/upload.ts +88 -0
- package/src/adapter-google-chat/utils.test.ts +111 -0
- package/src/adapter-google-chat/utils.ts +133 -0
- package/src/cli/commands/init.ts +0 -7
- package/src/cli/commands/messages.ts +18 -3
- package/src/cli/commands/policies.ts +70 -0
- package/src/cli/commands/skills.ts +71 -0
- package/src/cli/commands/web-api/chats.ts +5 -1
- package/src/cli/e2e/basic.test.ts +1 -1
- package/src/cli/e2e/cron.test.ts +1 -1
- package/src/cli/e2e/daemon.test.ts +132 -4
- package/src/cli/e2e/export-lite-func.test.ts +54 -31
- package/src/cli/e2e/fallbacks.test.ts +8 -6
- package/src/cli/e2e/init.test.ts +7 -0
- package/src/cli/e2e/messages.test.ts +90 -55
- package/src/cli/e2e/propose-policy.test.ts +203 -0
- package/src/cli/e2e/requests.test.ts +15 -0
- package/src/cli/e2e/session-timeout.test.ts +192 -0
- package/src/cli/e2e/skills.test.ts +55 -0
- package/src/cli/e2e/slash-new.test.ts +93 -0
- package/src/cli/e2e/subagents.test.ts +106 -0
- package/src/cli/index.ts +4 -0
- package/src/cli/lite.ts +51 -11
- package/src/cli/propose-policy.ts +91 -0
- package/src/cli/subagent-commands.ts +215 -0
- package/src/daemon/agent/agent-context.ts +89 -0
- package/src/daemon/agent/agent-extractors.ts +68 -0
- package/src/daemon/agent/agent-runner.ts +153 -0
- package/src/daemon/agent/agent-session.ts +261 -0
- package/src/daemon/agent/chat-logger.test.ts +158 -0
- package/src/daemon/agent/chat-logger.ts +188 -0
- package/src/daemon/agent/task-scheduler.test.ts +202 -0
- package/src/daemon/agent/task-scheduler.ts +276 -0
- package/src/daemon/agent/types.ts +84 -0
- package/src/daemon/agent/utils.ts +7 -0
- package/src/daemon/api/agent-router.ts +166 -18
- package/src/daemon/api/index.test.ts +50 -18
- package/src/daemon/api/policy-request.test.ts +39 -2
- package/src/daemon/api/subagent-router.test.ts +108 -0
- package/src/daemon/api/subagent-router.ts +296 -0
- package/src/daemon/api/subagent-utils.test.ts +56 -0
- package/src/daemon/api/subagent-utils.ts +130 -0
- package/src/daemon/api/user-router.ts +30 -13
- package/src/daemon/auth.ts +1 -0
- package/src/daemon/chats.ts +6 -0
- package/src/daemon/cron.test.ts +66 -1
- package/src/daemon/cron.ts +35 -8
- package/src/daemon/index.ts +23 -0
- package/src/daemon/message-agent.test.ts +11 -25
- package/src/daemon/message-extraction.test.ts +10 -27
- package/src/daemon/message-fallbacks.test.ts +13 -35
- package/src/daemon/message-interruption.test.ts +70 -53
- package/src/daemon/message-jobs.test.ts +138 -0
- package/src/daemon/message-queue.test.ts +30 -43
- package/src/daemon/message-router.test.ts +12 -11
- package/src/daemon/message-session.test.ts +41 -28
- package/src/daemon/message-typing.test.ts +19 -6
- package/src/daemon/message.ts +103 -515
- package/src/daemon/policy-request-service.ts +8 -3
- package/src/daemon/policy-utils.ts +19 -1
- package/src/daemon/queue.ts +16 -0
- package/src/daemon/request-store.test.ts +4 -0
- package/src/daemon/routers/session-timeout.test.ts +122 -0
- package/src/daemon/routers/session-timeout.ts +71 -0
- package/src/daemon/routers/slash-new.ts +3 -1
- package/src/daemon/routers/slash-policies.test.ts +26 -13
- package/src/daemon/routers/slash-policies.ts +39 -29
- package/src/daemon/routers/types.ts +8 -0
- package/src/daemon/routers.ts +64 -2
- package/src/daemon/utils/spawn.ts +6 -8
- package/src/shared/adapters/commands.test.ts +155 -0
- package/src/shared/adapters/commands.ts +125 -0
- package/src/shared/adapters/filtering.test.ts +111 -0
- package/src/shared/adapters/filtering.ts +57 -0
- package/src/shared/adapters/routing.test.ts +144 -0
- package/src/shared/adapters/routing.ts +109 -0
- package/src/shared/agent-utils.ts +10 -0
- package/src/shared/chats.test.ts +145 -3
- package/src/shared/chats.ts +215 -18
- package/src/shared/config.ts +67 -15
- package/src/shared/lite.ts +22 -18
- package/src/shared/policies.ts +7 -0
- package/src/shared/workspace.test.ts +45 -1
- package/src/shared/workspace.ts +119 -6
- package/templates/debug/settings.json +5 -2
- package/templates/environments/cladding/env.json +2 -2
- package/templates/gemini/.gemini/hooks/check-subagents.mjs +23 -0
- package/templates/gemini/.gemini/hooks/clawmini-logging.sh +17 -0
- package/templates/gemini/.gemini/hooks/insert-pending.sh +9 -0
- package/templates/gemini/.gemini/settings.json +50 -0
- package/templates/gemini/settings.json +22 -8
- package/templates/gemini-claw/.gemini/base-system.md +100 -0
- package/templates/gemini-claw/.gemini/hooks/check-subagents.mjs +23 -0
- package/templates/gemini-claw/.gemini/hooks/clawmini-logging.sh +1 -1
- package/templates/gemini-claw/.gemini/settings.json +13 -0
- package/templates/gemini-claw/.gemini/subagent-system.md +7 -0
- package/templates/gemini-claw/.gemini/system.md +3 -99
- package/templates/gemini-claw/settings.json +27 -22
- package/templates/skills/clawmini-requests/SKILL.md +92 -0
- package/templates/skills/clawmini-subagents/SKILL.md +79 -0
- package/templates/skills/skill-creator/SKILL.md +60 -0
- package/tsdown.config.ts +10 -1
- package/web/.svelte-kit/generated/server/internal.js +2 -1
- package/web/.svelte-kit/non-ambient.d.ts +2 -0
- package/web/.svelte-kit/output/client/.vite/manifest.json +141 -138
- package/web/.svelte-kit/output/client/_app/immutable/assets/0.C-4eziNy.css +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/assets/4.Cc_xwLNl.css +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/B6YN0Nuq.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/{Dc-UOHw9.js → BmRlVmv6.js} +1 -1
- package/{dist/web/_app/immutable/chunks/8YNcRyEk.js → web/.svelte-kit/output/client/_app/immutable/chunks/C20lZMGz.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/C9lbZ-kT.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/CK9JZLaG.js +2 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/CME08kGM.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/{BPy8HLo7.js → Ck-be5J2.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/Ck3rYNON.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/DMtIqaiV.js +2 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/{B8yYFADm.js → DhD271EB.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/{DcrmIfTj.js → DpuLqk8d.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/{ZkLyk0mE.js → Drm9vgeP.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/DsIToJCP.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/{CyNaE55B.js → Zeh-C-mx.js} +1 -1
- package/{dist/web/_app/immutable/entry/app.DO5eYwVz.js → web/.svelte-kit/output/client/_app/immutable/entry/app.BgB5VkRU.js} +2 -2
- package/web/.svelte-kit/output/client/_app/immutable/entry/start.DuxJo6av.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/0.C9oFZP9h.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/1.BON2Wk6k.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{2.CK3CLC0f.js → 2.BnwnD1Ki.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{3.ncP0xLO6.js → 3.CIs4tjjw.js} +1 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/4.DLarELN4.js +60 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/{5.BpJUN6QH.js → 5.CE_QKy_3.js} +1 -1
- package/web/.svelte-kit/output/client/_app/version.json +1 -1
- package/web/.svelte-kit/output/server/.vite/manifest.json +12 -3
- package/web/.svelte-kit/output/server/_app/immutable/assets/_layout.C-4eziNy.css +1 -0
- package/web/.svelte-kit/output/server/_app/immutable/assets/_page.Cc_xwLNl.css +1 -0
- package/web/.svelte-kit/output/server/chunks/app-state.svelte.js +5 -0
- package/web/.svelte-kit/output/server/chunks/bot.js +4 -4
- package/web/.svelte-kit/output/server/chunks/client.js +2 -1
- package/web/.svelte-kit/output/server/chunks/exports.js +0 -1
- package/web/.svelte-kit/output/server/chunks/internal.js +2 -1
- package/web/.svelte-kit/output/server/chunks/root.js +482 -392
- package/web/.svelte-kit/output/server/entries/pages/_layout.svelte.js +57 -7
- package/web/.svelte-kit/output/server/entries/pages/chats/_id_/_page.svelte.js +234 -9
- package/web/.svelte-kit/output/server/index.js +82 -10
- package/web/.svelte-kit/output/server/manifest-full.js +1 -1
- package/web/.svelte-kit/output/server/manifest.js +1 -1
- package/web/.svelte-kit/output/server/nodes/0.js +2 -2
- package/web/.svelte-kit/output/server/nodes/1.js +1 -1
- package/web/.svelte-kit/output/server/nodes/2.js +1 -1
- package/web/.svelte-kit/output/server/nodes/3.js +1 -1
- package/web/.svelte-kit/output/server/nodes/4.js +2 -2
- package/web/.svelte-kit/output/server/nodes/5.js +1 -1
- package/web/.svelte-kit/types/src/routes/$types.d.ts +1 -2
- package/web/.svelte-kit/types/src/routes/agents/$types.d.ts +1 -2
- package/web/.svelte-kit/types/src/routes/chats/[id]/$types.d.ts +1 -2
- package/web/.svelte-kit/types/src/routes/chats/[id]/settings/$types.d.ts +1 -2
- package/web/package.json +8 -0
- package/web/src/lib/app-state.svelte.ts +5 -1
- package/web/src/lib/components/app/markdown-renderer.svelte +56 -0
- package/web/src/lib/components/app/markdown-renderer.svelte.spec.ts +44 -0
- package/web/src/lib/components/app/message-content.svelte +16 -0
- package/web/src/lib/types.ts +67 -3
- package/web/src/routes/+layout.svelte +31 -1
- package/web/src/routes/chats/[id]/+page.svelte +167 -18
- package/web/src/routes/chats/[id]/page.svelte.spec.ts +58 -7
- package/dist/lite-oSYSvaOr.mjs.map +0 -1
- package/dist/web/_app/immutable/assets/0.GI4C4dpV.css +0 -1
- package/dist/web/_app/immutable/chunks/B5abRDXp.js +0 -1
- package/dist/web/_app/immutable/chunks/Bi0jeV7Q.js +0 -1
- package/dist/web/_app/immutable/chunks/BmUXQ3wy.js +0 -2
- package/dist/web/_app/immutable/chunks/C3k55nDF.js +0 -1
- package/dist/web/_app/immutable/chunks/CpaGRn9L.js +0 -1
- package/dist/web/_app/immutable/chunks/DG5RZBw-.js +0 -2
- package/dist/web/_app/immutable/chunks/DQoygso7.js +0 -1
- package/dist/web/_app/immutable/entry/start.D48mVn1m.js +0 -1
- package/dist/web/_app/immutable/nodes/0.B-0CcADM.js +0 -1
- package/dist/web/_app/immutable/nodes/1.FixKgvRO.js +0 -1
- package/dist/web/_app/immutable/nodes/4.CQYJEgv8.js +0 -1
- package/dist/workspace-DjoNjhW0.mjs.map +0 -1
- package/src/daemon/message-verbosity.test.ts +0 -127
- package/web/.svelte-kit/output/client/_app/immutable/assets/0.GI4C4dpV.css +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/B5abRDXp.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/Bi0jeV7Q.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/BmUXQ3wy.js +0 -2
- package/web/.svelte-kit/output/client/_app/immutable/chunks/C3k55nDF.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/CpaGRn9L.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/chunks/DG5RZBw-.js +0 -2
- package/web/.svelte-kit/output/client/_app/immutable/chunks/DQoygso7.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/entry/start.D48mVn1m.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/0.B-0CcADM.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/1.FixKgvRO.js +0 -1
- package/web/.svelte-kit/output/client/_app/immutable/nodes/4.CQYJEgv8.js +0 -1
- package/web/.svelte-kit/output/server/_app/immutable/assets/_layout.GI4C4dpV.css +0 -1
- /package/templates/{gemini-claw/.gemini/skills → skills}/clawmini-jobs/SKILL.md +0 -0
package/src/daemon/cron.ts
CHANGED
|
@@ -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() :
|
|
121
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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) {
|
package/src/daemon/index.ts
CHANGED
|
@@ -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 {
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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 {
|
|
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
|
|
29
|
-
|
|
30
|
-
const
|
|
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
|
-
|
|
40
|
-
await executeDirectMessage('chat1', state, undefined, '/test-interrupt-stop',
|
|
50
|
+
vi.mocked(runCommand).mockResolvedValue({ stdout: '', stderr: '', exitCode: 0 });
|
|
51
|
+
await executeDirectMessage('chat1', state, undefined, '/test-interrupt-stop', true);
|
|
41
52
|
|
|
42
|
-
expect(abortSpy).
|
|
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
|
-
|
|
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
|
|
52
|
-
|
|
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
|
-
|
|
56
|
-
.
|
|
57
|
-
|
|
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
|
-
|
|
63
|
-
.
|
|
64
|
-
|
|
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
|
-
|
|
68
|
-
)
|
|
90
|
+
})
|
|
69
91
|
.catch(() => {});
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
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
|
|
111
|
+
sessionId,
|
|
85
112
|
};
|
|
86
113
|
|
|
87
|
-
|
|
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
|
-
|
|
116
|
+
await executeDirectMessage('chat1', state, undefined, '/test-interrupt-batch', true);
|
|
99
117
|
|
|
100
|
-
|
|
101
|
-
// and enqueued it.
|
|
118
|
+
expect(interruptSpy).toHaveBeenCalledWith(sessionId);
|
|
102
119
|
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
145
|
+
const queueKey = `chat1:${sessionId}`;
|
|
146
|
+
const queuedForSession = taskScheduler['queues'].get(queueKey)?.['queue'] || [];
|
|
147
|
+
expect(queuedForSession.length).toBe(0);
|
|
131
148
|
});
|
|
132
149
|
});
|