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
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
applyTemplateToAgent,
|
|
5
5
|
readChatSettings,
|
|
6
6
|
writeChatSettings,
|
|
7
|
+
copyAgentSkills,
|
|
7
8
|
} from './workspace.js';
|
|
8
9
|
import { createChat, listChats } from './chats.js';
|
|
9
10
|
|
|
@@ -19,6 +20,15 @@ export async function createAgentWithChat(
|
|
|
19
20
|
await applyTemplateToAgent(agentId, template, agentData, startDir);
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
try {
|
|
24
|
+
await copyAgentSkills(agentId, startDir);
|
|
25
|
+
console.log(`Copied skills to agent ${agentId}.`);
|
|
26
|
+
} catch (err) {
|
|
27
|
+
console.warn(
|
|
28
|
+
`Warning: Failed to copy skills to agent ${agentId}: ${err instanceof Error ? err.message : String(err)}`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
22
32
|
const existingChats = await listChats(startDir);
|
|
23
33
|
if (existingChats.includes(agentId)) {
|
|
24
34
|
console.warn(`Warning: Chat ${agentId} already exists.`);
|
package/src/shared/chats.test.ts
CHANGED
|
@@ -63,9 +63,10 @@ describe('chats utilities', () => {
|
|
|
63
63
|
const msg2: CommandLogMessage = {
|
|
64
64
|
id: 'log-1',
|
|
65
65
|
messageId: 'msg-1',
|
|
66
|
-
role: '
|
|
66
|
+
role: 'command',
|
|
67
67
|
content: 'output',
|
|
68
68
|
stderr: '',
|
|
69
|
+
stdout: '',
|
|
69
70
|
timestamp: new Date().toISOString(),
|
|
70
71
|
command: 'echo output',
|
|
71
72
|
cwd: '/tmp',
|
|
@@ -75,10 +76,10 @@ describe('chats utilities', () => {
|
|
|
75
76
|
const msg3: CommandLogMessage = {
|
|
76
77
|
id: 'log-2',
|
|
77
78
|
messageId: 'msg-1',
|
|
78
|
-
role: '
|
|
79
|
-
source: 'router',
|
|
79
|
+
role: 'command',
|
|
80
80
|
content: 'router modified message',
|
|
81
81
|
stderr: '',
|
|
82
|
+
stdout: '',
|
|
82
83
|
timestamp: new Date().toISOString(),
|
|
83
84
|
command: 'router',
|
|
84
85
|
cwd: '/tmp',
|
|
@@ -99,6 +100,16 @@ describe('chats utilities', () => {
|
|
|
99
100
|
const limited = await getMessages('chat1', 1, TEST_DIR);
|
|
100
101
|
expect(limited.length).toBe(1);
|
|
101
102
|
expect(limited[0]).toEqual(msg3);
|
|
103
|
+
|
|
104
|
+
// Test predicate filtering combined with limit
|
|
105
|
+
const msgSub = { ...msg2, id: 'sub-1', subagentId: 'sub-123' };
|
|
106
|
+
await appendMessage('chat1', msgSub as CommandLogMessage, TEST_DIR);
|
|
107
|
+
|
|
108
|
+
// Total is now 4 messages (3 normal, 1 subagent)
|
|
109
|
+
const withPredicate = await getMessages('chat1', 2, TEST_DIR, (m) => !m.subagentId);
|
|
110
|
+
expect(withPredicate.length).toBe(2);
|
|
111
|
+
expect(withPredicate[0]).toEqual(msg2);
|
|
112
|
+
expect(withPredicate[1]).toEqual(msg3);
|
|
102
113
|
});
|
|
103
114
|
|
|
104
115
|
it('should manage default chat id in settings.json', async () => {
|
|
@@ -109,4 +120,135 @@ describe('chats utilities', () => {
|
|
|
109
120
|
defaultId = await getDefaultChatId(TEST_DIR);
|
|
110
121
|
expect(defaultId).toBe('my-chat');
|
|
111
122
|
});
|
|
123
|
+
|
|
124
|
+
it('should support message pagination with before cursor and limits', async () => {
|
|
125
|
+
await createChat('chat1', TEST_DIR);
|
|
126
|
+
|
|
127
|
+
const msgs: UserMessage[] = Array.from({ length: 5 }, (_, i) => ({
|
|
128
|
+
id: `msg-${i + 1}`,
|
|
129
|
+
role: 'user',
|
|
130
|
+
content: `Message ${i + 1}`,
|
|
131
|
+
timestamp: new Date().toISOString(),
|
|
132
|
+
}));
|
|
133
|
+
|
|
134
|
+
for (const msg of msgs) {
|
|
135
|
+
await appendMessage('chat1', msg, TEST_DIR);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Default limit should be 100, which returns all 5
|
|
139
|
+
const all = await getMessages('chat1', undefined, TEST_DIR);
|
|
140
|
+
expect(all.length).toBe(5);
|
|
141
|
+
|
|
142
|
+
// Limit to 2 should return the last 2
|
|
143
|
+
const lastTwo = await getMessages('chat1', 2, TEST_DIR);
|
|
144
|
+
expect(lastTwo.length).toBe(2);
|
|
145
|
+
expect(lastTwo[0]?.id).toBe('msg-4');
|
|
146
|
+
expect(lastTwo[1]?.id).toBe('msg-5');
|
|
147
|
+
|
|
148
|
+
// Before cursor with limit
|
|
149
|
+
const beforeCursor = await getMessages('chat1', 2, TEST_DIR, undefined, 'msg-4');
|
|
150
|
+
expect(beforeCursor.length).toBe(2);
|
|
151
|
+
expect(beforeCursor[0]?.id).toBe('msg-2');
|
|
152
|
+
expect(beforeCursor[1]?.id).toBe('msg-3');
|
|
153
|
+
|
|
154
|
+
// Before cursor reaching the start
|
|
155
|
+
const beforeCursorStart = await getMessages('chat1', 2, TEST_DIR, undefined, 'msg-2');
|
|
156
|
+
expect(beforeCursorStart.length).toBe(1);
|
|
157
|
+
expect(beforeCursorStart[0]?.id).toBe('msg-1');
|
|
158
|
+
|
|
159
|
+
// Before cursor that doesn't exist returns empty
|
|
160
|
+
const beforeCursorUnknown = await getMessages('chat1', 2, TEST_DIR, undefined, 'msg-unknown');
|
|
161
|
+
expect(beforeCursorUnknown.length).toBe(0);
|
|
162
|
+
|
|
163
|
+
// Limit 0 or negative should read all (Wait, limit 0 reads all?)
|
|
164
|
+
// Our implementation sets default to 100 if undefined. If 0 is explicitly passed, it hits `limit <= 0` and reads all.
|
|
165
|
+
const readAll = await getMessages('chat1', 0, TEST_DIR);
|
|
166
|
+
expect(readAll.length).toBe(5);
|
|
167
|
+
|
|
168
|
+
// Before cursor with limit <= 0
|
|
169
|
+
const readAllBefore = await getMessages('chat1', 0, TEST_DIR, undefined, 'msg-4');
|
|
170
|
+
expect(readAllBefore.length).toBe(3);
|
|
171
|
+
expect(readAllBefore[0]?.id).toBe('msg-1');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should parse legacy log messages gracefully', async () => {
|
|
175
|
+
await createChat('chat1', TEST_DIR);
|
|
176
|
+
|
|
177
|
+
// Old plain log missing messageId
|
|
178
|
+
const oldPlainLog = {
|
|
179
|
+
id: 'log-1',
|
|
180
|
+
role: 'log',
|
|
181
|
+
content: 'legacy content',
|
|
182
|
+
timestamp: new Date().toISOString(),
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// Old command log with legacy properties
|
|
186
|
+
const oldCommandLog = {
|
|
187
|
+
id: 'log-2',
|
|
188
|
+
role: 'log',
|
|
189
|
+
messageId: 'msg-1',
|
|
190
|
+
content: 'output',
|
|
191
|
+
command: 'echo output',
|
|
192
|
+
timestamp: new Date().toISOString(),
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
// New generic log message without legacy properties
|
|
196
|
+
const newLogMsg = {
|
|
197
|
+
id: 'log-3',
|
|
198
|
+
role: 'log',
|
|
199
|
+
messageId: 'msg-1',
|
|
200
|
+
content: 'new log',
|
|
201
|
+
timestamp: new Date().toISOString(),
|
|
202
|
+
type: 'tool',
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const chatFile = path.join(TEST_DIR, '.clawmini', 'chats', 'chat1', 'chat.jsonl');
|
|
206
|
+
await fs.appendFile(chatFile, JSON.stringify(oldPlainLog) + '\n');
|
|
207
|
+
await fs.appendFile(chatFile, JSON.stringify(oldCommandLog) + '\n');
|
|
208
|
+
await fs.appendFile(chatFile, JSON.stringify(newLogMsg) + '\n');
|
|
209
|
+
|
|
210
|
+
const messages = await getMessages('chat1', undefined, TEST_DIR);
|
|
211
|
+
expect(messages.length).toBe(3);
|
|
212
|
+
|
|
213
|
+
// Should map to legacy_log
|
|
214
|
+
expect(messages[0]?.role).toBe('legacy_log');
|
|
215
|
+
expect(messages[1]?.role).toBe('legacy_log');
|
|
216
|
+
expect(messages[2]?.role).toBe('legacy_log');
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('should skip corrupted JSON lines gracefully', async () => {
|
|
220
|
+
await createChat('chat1', TEST_DIR);
|
|
221
|
+
|
|
222
|
+
const validMsg1 = {
|
|
223
|
+
id: 'msg-1',
|
|
224
|
+
role: 'user',
|
|
225
|
+
content: 'Hello',
|
|
226
|
+
timestamp: new Date().toISOString(),
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const validMsg2 = {
|
|
230
|
+
id: 'msg-2',
|
|
231
|
+
role: 'agent',
|
|
232
|
+
content: 'Hi',
|
|
233
|
+
timestamp: new Date().toISOString(),
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const chatFile = path.join(TEST_DIR, '.clawmini', 'chats', 'chat1', 'chat.jsonl');
|
|
237
|
+
await fs.appendFile(chatFile, JSON.stringify(validMsg1) + '\n');
|
|
238
|
+
await fs.appendFile(chatFile, '{ "id": "corrupted", "role": "user" \n'); // Invalid JSON
|
|
239
|
+
await fs.appendFile(chatFile, JSON.stringify(validMsg2) + '\n');
|
|
240
|
+
await fs.appendFile(chatFile, 'This is completely not JSON\n'); // Invalid JSON
|
|
241
|
+
|
|
242
|
+
// Test getMessages with limit > 0
|
|
243
|
+
const limitedMessages = await getMessages('chat1', 10, TEST_DIR);
|
|
244
|
+
expect(limitedMessages.length).toBe(2);
|
|
245
|
+
expect(limitedMessages[0]?.id).toBe('msg-1');
|
|
246
|
+
expect(limitedMessages[1]?.id).toBe('msg-2');
|
|
247
|
+
|
|
248
|
+
// Test getMessages with limit <= 0 (read all)
|
|
249
|
+
const allMessages = await getMessages('chat1', 0, TEST_DIR);
|
|
250
|
+
expect(allMessages.length).toBe(2);
|
|
251
|
+
expect(allMessages[0]?.id).toBe('msg-1');
|
|
252
|
+
expect(allMessages[1]?.id).toBe('msg-2');
|
|
253
|
+
});
|
|
112
254
|
});
|
package/src/shared/chats.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable max-lines */
|
|
1
2
|
import fs from 'node:fs/promises';
|
|
2
3
|
import { existsSync } from 'node:fs';
|
|
3
4
|
import path from 'node:path';
|
|
@@ -6,30 +7,93 @@ import { pathIsInsideDir } from './utils/fs.js';
|
|
|
6
7
|
|
|
7
8
|
export const DEFAULT_CHAT_ID = 'default';
|
|
8
9
|
|
|
9
|
-
export interface
|
|
10
|
+
export interface BaseMessage {
|
|
10
11
|
id: string;
|
|
11
|
-
role:
|
|
12
|
+
role: string;
|
|
13
|
+
displayRole?: 'user' | 'agent';
|
|
12
14
|
content: string;
|
|
13
15
|
timestamp: string;
|
|
16
|
+
subagentId?: string;
|
|
14
17
|
}
|
|
15
18
|
|
|
16
|
-
export interface
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
export interface UserMessage extends BaseMessage {
|
|
20
|
+
role: 'user';
|
|
21
|
+
agentContent?: string;
|
|
22
|
+
files?: string[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface AgentReplyMessage extends BaseMessage {
|
|
26
|
+
role: 'agent';
|
|
27
|
+
files?: string[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface LogMessage extends BaseMessage {
|
|
19
31
|
role: 'log';
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
messageId: string;
|
|
33
|
+
type?: 'tool' | 'unknown';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface CommandLogMessage extends BaseMessage {
|
|
37
|
+
role: 'command';
|
|
38
|
+
messageId: string;
|
|
24
39
|
command: string;
|
|
25
40
|
cwd: string;
|
|
41
|
+
stdout: string;
|
|
42
|
+
stderr: string;
|
|
26
43
|
exitCode: number;
|
|
27
|
-
|
|
44
|
+
retryAttemptIndex?: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface SystemMessage extends BaseMessage {
|
|
48
|
+
role: 'system';
|
|
49
|
+
event: 'cron' | 'policy_approved' | 'policy_rejected' | 'subagent_update' | 'router' | 'other';
|
|
50
|
+
messageId?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface ToolMessage extends BaseMessage {
|
|
54
|
+
role: 'tool';
|
|
55
|
+
messageId: string;
|
|
56
|
+
name: string;
|
|
57
|
+
payload: unknown;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface PolicyRequestMessage extends BaseMessage {
|
|
61
|
+
role: 'policy';
|
|
62
|
+
messageId: string;
|
|
63
|
+
requestId: string;
|
|
64
|
+
commandName: string;
|
|
65
|
+
args: string[];
|
|
66
|
+
status: 'pending' | 'approved' | 'rejected';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface SubagentStatusMessage extends BaseMessage {
|
|
70
|
+
role: 'subagent_status';
|
|
71
|
+
subagentId: string;
|
|
72
|
+
status: 'completed' | 'failed';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface LegacyLogMessage extends BaseMessage {
|
|
76
|
+
role: 'legacy_log';
|
|
77
|
+
messageId?: string;
|
|
78
|
+
source?: string;
|
|
28
79
|
files?: string[];
|
|
29
80
|
level?: 'default' | 'debug' | 'verbose';
|
|
81
|
+
command?: string;
|
|
82
|
+
cwd?: string;
|
|
83
|
+
stdout?: string;
|
|
84
|
+
stderr?: string;
|
|
85
|
+
exitCode?: number;
|
|
30
86
|
}
|
|
31
87
|
|
|
32
|
-
export type ChatMessage =
|
|
88
|
+
export type ChatMessage =
|
|
89
|
+
| UserMessage
|
|
90
|
+
| AgentReplyMessage
|
|
91
|
+
| CommandLogMessage
|
|
92
|
+
| SystemMessage
|
|
93
|
+
| ToolMessage
|
|
94
|
+
| PolicyRequestMessage
|
|
95
|
+
| SubagentStatusMessage
|
|
96
|
+
| LegacyLogMessage;
|
|
33
97
|
|
|
34
98
|
export async function getChatsDir(startDir = process.cwd()): Promise<string> {
|
|
35
99
|
const dir = path.join(getClawminiDir(startDir), 'chats');
|
|
@@ -102,10 +166,71 @@ export async function appendMessage(
|
|
|
102
166
|
await fs.appendFile(chatFile, JSON.stringify(message) + '\n');
|
|
103
167
|
}
|
|
104
168
|
|
|
169
|
+
async function* readLinesBackwards(filePath: string): AsyncGenerator<string, void, unknown> {
|
|
170
|
+
const fd = await fs.open(filePath, 'r');
|
|
171
|
+
try {
|
|
172
|
+
const stats = await fd.stat();
|
|
173
|
+
if (stats.size === 0) return;
|
|
174
|
+
|
|
175
|
+
const chunkSize = 64 * 1024;
|
|
176
|
+
let position = stats.size;
|
|
177
|
+
const buffer = Buffer.alloc(chunkSize);
|
|
178
|
+
let leftoverBuffer = Buffer.alloc(0);
|
|
179
|
+
|
|
180
|
+
while (position > 0) {
|
|
181
|
+
const readSize = Math.min(chunkSize, position);
|
|
182
|
+
position -= readSize;
|
|
183
|
+
|
|
184
|
+
const { bytesRead } = await fd.read(buffer, 0, readSize, position);
|
|
185
|
+
|
|
186
|
+
const currentChunk = buffer.subarray(0, bytesRead);
|
|
187
|
+
let combinedBuffer = Buffer.concat([currentChunk, leftoverBuffer]);
|
|
188
|
+
|
|
189
|
+
let lastNewlineIdx = combinedBuffer.lastIndexOf(0x0a);
|
|
190
|
+
|
|
191
|
+
while (lastNewlineIdx !== -1) {
|
|
192
|
+
const lineBuffer = combinedBuffer.subarray(lastNewlineIdx + 1);
|
|
193
|
+
const line = lineBuffer.toString('utf8').trim();
|
|
194
|
+
|
|
195
|
+
if (line) {
|
|
196
|
+
yield line;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
combinedBuffer = combinedBuffer.subarray(0, lastNewlineIdx);
|
|
200
|
+
lastNewlineIdx = combinedBuffer.lastIndexOf(0x0a);
|
|
201
|
+
}
|
|
202
|
+
leftoverBuffer = combinedBuffer;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (leftoverBuffer.length > 0) {
|
|
206
|
+
const line = leftoverBuffer.toString('utf8').trim();
|
|
207
|
+
if (line) {
|
|
208
|
+
yield line;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
} finally {
|
|
212
|
+
await fd.close();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function parseChatMessage(line: string): ChatMessage | null {
|
|
217
|
+
try {
|
|
218
|
+
const msg = JSON.parse(line);
|
|
219
|
+
if (msg && msg.role === 'log') {
|
|
220
|
+
msg.role = 'legacy_log';
|
|
221
|
+
}
|
|
222
|
+
return msg as ChatMessage;
|
|
223
|
+
} catch {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
105
228
|
export async function getMessages(
|
|
106
229
|
id: string,
|
|
107
230
|
limit?: number,
|
|
108
|
-
startDir = process.cwd()
|
|
231
|
+
startDir = process.cwd(),
|
|
232
|
+
predicate?: (msg: ChatMessage) => boolean,
|
|
233
|
+
before?: string
|
|
109
234
|
): Promise<ChatMessage[]> {
|
|
110
235
|
assertValidChatId(id);
|
|
111
236
|
const chatsDir = await getChatsDir(startDir);
|
|
@@ -113,14 +238,61 @@ export async function getMessages(
|
|
|
113
238
|
if (!existsSync(chatFile)) {
|
|
114
239
|
throw new Error(`Chat directory or file for '${id}' not found.`);
|
|
115
240
|
}
|
|
116
|
-
const content = await fs.readFile(chatFile, 'utf8');
|
|
117
|
-
const lines = content.split('\n').filter((line) => line.trim() !== '');
|
|
118
|
-
const messages = lines.map((line) => JSON.parse(line) as ChatMessage);
|
|
119
241
|
|
|
120
|
-
|
|
121
|
-
|
|
242
|
+
limit = limit ?? 100;
|
|
243
|
+
|
|
244
|
+
if (limit <= 0) {
|
|
245
|
+
const content = await fs.readFile(chatFile, 'utf8');
|
|
246
|
+
const lines = content.split('\n').filter((line) => line.trim() !== '');
|
|
247
|
+
|
|
248
|
+
let messages = lines
|
|
249
|
+
.map((line) => parseChatMessage(line))
|
|
250
|
+
.filter((msg): msg is ChatMessage => msg !== null);
|
|
251
|
+
|
|
252
|
+
if (before) {
|
|
253
|
+
const beforeIndex = messages.findIndex((m) => m.id === before);
|
|
254
|
+
if (beforeIndex !== -1) {
|
|
255
|
+
messages = messages.slice(0, beforeIndex);
|
|
256
|
+
} else {
|
|
257
|
+
messages = [];
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (predicate) {
|
|
262
|
+
messages = messages.filter(predicate);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return messages;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// We have a limit > 0, read backwards to avoid parsing the whole file
|
|
269
|
+
const messages: ChatMessage[] = [];
|
|
270
|
+
let skipping = before !== undefined;
|
|
271
|
+
|
|
272
|
+
for await (const line of readLinesBackwards(chatFile)) {
|
|
273
|
+
try {
|
|
274
|
+
const msg = parseChatMessage(line);
|
|
275
|
+
if (!msg) continue;
|
|
276
|
+
|
|
277
|
+
if (skipping) {
|
|
278
|
+
if (msg.id === before) {
|
|
279
|
+
skipping = false;
|
|
280
|
+
}
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (!predicate || predicate(msg)) {
|
|
285
|
+
messages.push(msg);
|
|
286
|
+
if (messages.length >= limit) {
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
} catch {
|
|
291
|
+
// Ignore invalid JSON lines
|
|
292
|
+
}
|
|
122
293
|
}
|
|
123
|
-
|
|
294
|
+
|
|
295
|
+
return messages.reverse();
|
|
124
296
|
}
|
|
125
297
|
|
|
126
298
|
export async function getDefaultChatId(startDir = process.cwd()): Promise<string> {
|
|
@@ -162,3 +334,28 @@ export async function setDefaultChatId(id: string, startDir = process.cwd()): Pr
|
|
|
162
334
|
|
|
163
335
|
await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
164
336
|
}
|
|
337
|
+
|
|
338
|
+
export async function findLastMessage(
|
|
339
|
+
id: string,
|
|
340
|
+
predicate: (msg: ChatMessage) => boolean,
|
|
341
|
+
startDir = process.cwd()
|
|
342
|
+
): Promise<ChatMessage | null> {
|
|
343
|
+
assertValidChatId(id);
|
|
344
|
+
const chatsDir = await getChatsDir(startDir);
|
|
345
|
+
const chatFile = path.join(chatsDir, id, 'chat.jsonl');
|
|
346
|
+
if (!existsSync(chatFile)) {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
for await (const line of readLinesBackwards(chatFile)) {
|
|
351
|
+
try {
|
|
352
|
+
const msg = parseChatMessage(line);
|
|
353
|
+
if (!msg) continue;
|
|
354
|
+
if (predicate(msg)) return msg;
|
|
355
|
+
} catch {
|
|
356
|
+
// Ignore invalid JSON lines
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return null;
|
|
361
|
+
}
|
package/src/shared/config.ts
CHANGED
|
@@ -23,36 +23,88 @@ export const AgentSchema = z.looseObject({
|
|
|
23
23
|
getMessageContent: z.string().optional(),
|
|
24
24
|
})
|
|
25
25
|
.optional(),
|
|
26
|
+
apiTokenEnvVar: z.string().optional(),
|
|
27
|
+
apiUrlEnvVar: z.string().optional(),
|
|
26
28
|
env: z.record(z.string(), z.union([z.string(), z.boolean()])).optional(),
|
|
29
|
+
subagentEnv: z.record(z.string(), z.union([z.string(), z.boolean()])).optional(),
|
|
27
30
|
directory: z.string().optional(),
|
|
31
|
+
skillsDir: z.string().optional(),
|
|
28
32
|
fallbacks: z.array(FallbackSchema).optional(),
|
|
29
33
|
files: z.string().default('./attachments').optional(),
|
|
30
34
|
});
|
|
31
35
|
|
|
32
36
|
export type Agent = z.infer<typeof AgentSchema>;
|
|
33
37
|
|
|
34
|
-
export
|
|
35
|
-
id:
|
|
36
|
-
createdAt
|
|
37
|
-
message:
|
|
38
|
-
reply
|
|
38
|
+
export type CronJob = {
|
|
39
|
+
id: string;
|
|
40
|
+
createdAt?: string;
|
|
41
|
+
message: string;
|
|
42
|
+
reply?: string;
|
|
43
|
+
agentId?: string;
|
|
44
|
+
env?: Record<string, string | boolean>;
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
|
+
session?: { type: string; [key: string]: any };
|
|
47
|
+
schedule: { cron: string } | { every: string } | { at: string };
|
|
48
|
+
nextSessionId?: string;
|
|
49
|
+
action?: 'stop' | 'interrupt' | 'continue';
|
|
50
|
+
jobs?: {
|
|
51
|
+
add?: CronJob[];
|
|
52
|
+
remove?: string[];
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const CronJobSchema = z.lazy(() =>
|
|
57
|
+
z.looseObject({
|
|
58
|
+
id: z.string().min(1),
|
|
59
|
+
createdAt: z.string().optional(),
|
|
60
|
+
message: z.string().default(''),
|
|
61
|
+
reply: z.string().optional(),
|
|
62
|
+
agentId: z.string().optional(),
|
|
63
|
+
env: z.record(z.string(), z.union([z.string(), z.boolean()])).optional(),
|
|
64
|
+
session: z.looseObject({ type: z.string() }).optional(),
|
|
65
|
+
schedule: z.union([
|
|
66
|
+
z.looseObject({ cron: z.string() }),
|
|
67
|
+
z.looseObject({ every: z.string() }),
|
|
68
|
+
z.looseObject({ at: z.string() }),
|
|
69
|
+
]),
|
|
70
|
+
nextSessionId: z.string().optional(),
|
|
71
|
+
action: z.enum(['stop', 'interrupt', 'continue']).optional(),
|
|
72
|
+
jobs: z
|
|
73
|
+
.looseObject({
|
|
74
|
+
add: z.array(z.lazy(() => CronJobSchema)).optional(),
|
|
75
|
+
remove: z.array(z.string()).optional(),
|
|
76
|
+
})
|
|
77
|
+
.optional(),
|
|
78
|
+
})
|
|
79
|
+
) as z.ZodType<CronJob>;
|
|
80
|
+
|
|
81
|
+
export const RouterConfigSchema = z.union([
|
|
82
|
+
z.string(),
|
|
83
|
+
z.looseObject({
|
|
84
|
+
use: z.string(),
|
|
85
|
+
with: z.record(z.string(), z.any()).optional(),
|
|
86
|
+
}),
|
|
87
|
+
]);
|
|
88
|
+
|
|
89
|
+
export type RouterConfig = z.infer<typeof RouterConfigSchema>;
|
|
90
|
+
|
|
91
|
+
export const SubagentTrackerSchema = z.looseObject({
|
|
92
|
+
id: z.string(),
|
|
39
93
|
agentId: z.string().optional(),
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
z.looseObject({ every: z.string() }),
|
|
45
|
-
z.looseObject({ at: z.string() }),
|
|
46
|
-
]),
|
|
94
|
+
sessionId: z.string().optional(),
|
|
95
|
+
createdAt: z.string(),
|
|
96
|
+
status: z.enum(['active', 'completed', 'failed']),
|
|
97
|
+
parentId: z.string().optional(),
|
|
47
98
|
});
|
|
48
99
|
|
|
49
|
-
export type
|
|
100
|
+
export type SubagentTracker = z.infer<typeof SubagentTrackerSchema>;
|
|
50
101
|
|
|
51
102
|
export const ChatSettingsSchema = z.looseObject({
|
|
52
103
|
defaultAgent: z.string().optional(),
|
|
53
104
|
sessions: z.record(z.string(), z.string()).optional(),
|
|
54
|
-
routers: z.array(
|
|
105
|
+
routers: z.array(RouterConfigSchema).optional(),
|
|
55
106
|
jobs: z.array(CronJobSchema).optional(),
|
|
107
|
+
subagents: z.record(z.string(), SubagentTrackerSchema).optional(),
|
|
56
108
|
});
|
|
57
109
|
|
|
58
110
|
export type ChatSettings = z.infer<typeof ChatSettingsSchema>;
|
|
@@ -83,7 +135,7 @@ export const SettingsSchema = z.looseObject({
|
|
|
83
135
|
.optional(),
|
|
84
136
|
defaultAgent: AgentSchema.optional(),
|
|
85
137
|
environments: z.record(z.string(), z.string()).optional(),
|
|
86
|
-
routers: z.array(
|
|
138
|
+
routers: z.array(RouterConfigSchema).optional(),
|
|
87
139
|
files: z.string().default('./attachments').optional(),
|
|
88
140
|
api: z
|
|
89
141
|
.union([
|
package/src/shared/lite.ts
CHANGED
|
@@ -4,31 +4,35 @@ import { fileURLToPath } from 'node:url';
|
|
|
4
4
|
import { readSettings, readEnvironment, getWorkspaceRoot } from './workspace.js';
|
|
5
5
|
import type { Environment } from './config.js';
|
|
6
6
|
|
|
7
|
-
export async function
|
|
8
|
-
|
|
9
|
-
const
|
|
7
|
+
export async function resolveCompiledScript(scriptName: string, metaUrl: string): Promise<string> {
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(metaUrl));
|
|
9
|
+
const filename = scriptName.endsWith('.mjs') ? scriptName : `${scriptName}.mjs`;
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
const searchPaths = [
|
|
12
|
+
path.resolve(__dirname, `cli/${filename}`), // If bundled in a shared chunk at dist/
|
|
13
|
+
path.resolve(__dirname, filename), // If bundled in dist/cli or dist/daemon and lite is next to it
|
|
14
|
+
path.resolve(__dirname, `../cli/${filename}`), // If bundled in dist/daemon, it might be in ../cli/
|
|
15
|
+
path.resolve(__dirname, `../../dist/cli/${filename}`), // Fallback for development/testing when running from src/shared
|
|
16
|
+
path.resolve(__dirname, `../${filename}`), // Used from src/cli/commands (1 level deep) -> dist/cli
|
|
17
|
+
path.resolve(__dirname, `../../${filename}`), // Used from src/cli/commands -> dist/cli (2 levels deep)
|
|
18
|
+
];
|
|
12
19
|
|
|
13
|
-
|
|
14
|
-
await fs.access(liteScriptPath);
|
|
15
|
-
} catch {
|
|
20
|
+
for (const scriptPath of searchPaths) {
|
|
16
21
|
try {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
await fs.access(liteScriptPath);
|
|
22
|
+
await fs.access(scriptPath);
|
|
23
|
+
return scriptPath;
|
|
20
24
|
} catch {
|
|
21
|
-
|
|
22
|
-
// If bundled in dist/daemon, it might be in ../cli/lite.mjs
|
|
23
|
-
liteScriptPath = path.resolve(__dirname, '../cli/lite.mjs');
|
|
24
|
-
await fs.access(liteScriptPath);
|
|
25
|
-
} catch {
|
|
26
|
-
// Fallback for development/testing when running from src/shared
|
|
27
|
-
liteScriptPath = path.resolve(__dirname, '../../dist/cli/lite.mjs');
|
|
28
|
-
}
|
|
25
|
+
// Continue searching
|
|
29
26
|
}
|
|
30
27
|
}
|
|
31
28
|
|
|
29
|
+
throw new Error(`Could not find compiled script: ${filename}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function getLiteScriptContent(): Promise<string> {
|
|
33
|
+
let liteScriptContent: string;
|
|
34
|
+
const liteScriptPath = await resolveCompiledScript('lite', import.meta.url);
|
|
35
|
+
|
|
32
36
|
liteScriptContent = await fs.readFile(liteScriptPath, 'utf8');
|
|
33
37
|
|
|
34
38
|
// Ensure it has the hashbang (if tsdown stripped it or if missing)
|
package/src/shared/policies.ts
CHANGED
|
@@ -3,6 +3,7 @@ export interface PolicyDefinition {
|
|
|
3
3
|
command: string;
|
|
4
4
|
args?: string[];
|
|
5
5
|
allowHelp?: boolean;
|
|
6
|
+
autoApprove?: boolean;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
export interface PolicyConfig {
|
|
@@ -21,4 +22,10 @@ export interface PolicyRequest {
|
|
|
21
22
|
rejectionReason?: string;
|
|
22
23
|
chatId: string;
|
|
23
24
|
agentId: string;
|
|
25
|
+
subagentId?: string;
|
|
26
|
+
executionResult?: {
|
|
27
|
+
stdout: string;
|
|
28
|
+
stderr: string;
|
|
29
|
+
exitCode: number;
|
|
30
|
+
};
|
|
24
31
|
}
|