clawmini 0.0.1
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/.gemini/settings.json +46 -0
- package/.prettierrc +7 -0
- package/GEMINI.md +11 -0
- package/README.md +137 -0
- package/dist/adapter-discord/index.d.mts +5 -0
- package/dist/adapter-discord/index.d.mts.map +1 -0
- package/dist/adapter-discord/index.mjs +456 -0
- package/dist/adapter-discord/index.mjs.map +1 -0
- package/dist/chats-DKgTeU7i.mjs +91 -0
- package/dist/chats-DKgTeU7i.mjs.map +1 -0
- package/dist/chats-Zd_HXDHx.mjs +29 -0
- package/dist/chats-Zd_HXDHx.mjs.map +1 -0
- package/dist/cli/index.d.mts +1 -0
- package/dist/cli/index.mjs +850 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/cli/lite.d.mts +1 -0
- package/dist/cli/lite.mjs +4434 -0
- package/dist/cli/lite.mjs.map +1 -0
- package/dist/daemon/index.d.mts +5 -0
- package/dist/daemon/index.d.mts.map +1 -0
- package/dist/daemon/index.mjs +1222 -0
- package/dist/daemon/index.mjs.map +1 -0
- package/dist/fetch-BjZVyU3Z.mjs +37 -0
- package/dist/fetch-BjZVyU3Z.mjs.map +1 -0
- package/dist/fs-B5wW0oaH.mjs +14 -0
- package/dist/fs-B5wW0oaH.mjs.map +1 -0
- package/dist/lite-Dl7WXyaH.mjs +80 -0
- package/dist/lite-Dl7WXyaH.mjs.map +1 -0
- package/dist/rolldown-runtime-95iHPtFO.mjs +18 -0
- package/dist/web/_app/env.js +1 -0
- package/dist/web/_app/immutable/assets/0.GI4C4dpV.css +1 -0
- package/dist/web/_app/immutable/chunks/B5abRDXp.js +1 -0
- package/dist/web/_app/immutable/chunks/B8yYFADm.js +1 -0
- package/dist/web/_app/immutable/chunks/BPy8HLo7.js +5 -0
- package/dist/web/_app/immutable/chunks/Bi0jeV7Q.js +1 -0
- package/dist/web/_app/immutable/chunks/BmUXQ3wy.js +2 -0
- package/dist/web/_app/immutable/chunks/C3k55nDF.js +1 -0
- package/dist/web/_app/immutable/chunks/COekwvP2.js +1 -0
- package/dist/web/_app/immutable/chunks/CSvS_NwK.js +1 -0
- package/dist/web/_app/immutable/chunks/CpaGRn9L.js +1 -0
- package/dist/web/_app/immutable/chunks/CyNaE55B.js +1 -0
- package/dist/web/_app/immutable/chunks/DG5RZBw-.js +2 -0
- package/dist/web/_app/immutable/chunks/Dc-UOHw9.js +1 -0
- package/dist/web/_app/immutable/chunks/DcrmIfTj.js +1 -0
- package/dist/web/_app/immutable/chunks/ZkLyk0mE.js +1 -0
- package/dist/web/_app/immutable/entry/app.B-vZe7PN.js +2 -0
- package/dist/web/_app/immutable/entry/start.oP1AgKhs.js +1 -0
- package/dist/web/_app/immutable/nodes/0.B5WFN0zw.js +1 -0
- package/dist/web/_app/immutable/nodes/1.D1wtJb2k.js +1 -0
- package/dist/web/_app/immutable/nodes/2.CK3CLC0f.js +1 -0
- package/dist/web/_app/immutable/nodes/3.BB5wCoBf.js +4 -0
- package/dist/web/_app/immutable/nodes/4.Dr2jvAXK.js +1 -0
- package/dist/web/_app/immutable/nodes/5.BJl7oM3b.js +1 -0
- package/dist/web/_app/version.json +1 -0
- package/dist/web/index.html +37 -0
- package/dist/web/robots.txt +3 -0
- package/dist/workspace-CSgfo_2J.mjs +383 -0
- package/dist/workspace-CSgfo_2J.mjs.map +1 -0
- package/docs/01_chats/development_log.md +36 -0
- package/docs/01_chats/notes.md +27 -0
- package/docs/01_chats/prd.md +47 -0
- package/docs/01_chats/questions.md +19 -0
- package/docs/01_chats/tickets.md +67 -0
- package/docs/02_sessions/development_log.md +79 -0
- package/docs/02_sessions/notes.md +40 -0
- package/docs/02_sessions/prd.md +75 -0
- package/docs/02_sessions/questions.md +7 -0
- package/docs/02_sessions/tickets.md +68 -0
- package/docs/03_web_interface/development_log.md +60 -0
- package/docs/03_web_interface/notes.md +29 -0
- package/docs/03_web_interface/prd.md +42 -0
- package/docs/03_web_interface/questions.md +8 -0
- package/docs/03_web_interface/tickets.md +59 -0
- package/docs/04_agents/development_log.md +54 -0
- package/docs/04_agents/notes.md +45 -0
- package/docs/04_agents/prd.md +47 -0
- package/docs/04_agents/questions.md +13 -0
- package/docs/04_agents/tickets.md +107 -0
- package/docs/05_routers/development_log.md +13 -0
- package/docs/05_routers/notes.md +40 -0
- package/docs/05_routers/prd.md +55 -0
- package/docs/05_routers/questions.md +21 -0
- package/docs/05_routers/tickets.md +109 -0
- package/docs/06_agent_templates/development_log.md +38 -0
- package/docs/06_agent_templates/notes.md +25 -0
- package/docs/06_agent_templates/prd.md +34 -0
- package/docs/06_agent_templates/questions.md +11 -0
- package/docs/06_agent_templates/tickets.md +49 -0
- package/docs/06_cron/development_log.md +51 -0
- package/docs/06_cron/notes.md +14 -0
- package/docs/06_cron/prd.md +92 -0
- package/docs/06_cron/questions.md +15 -0
- package/docs/06_cron/tickets.md +75 -0
- package/docs/07_web_chat_ux/development_log.md +30 -0
- package/docs/07_web_chat_ux/notes.md +25 -0
- package/docs/07_web_chat_ux/prd.md +46 -0
- package/docs/07_web_chat_ux/questions.md +7 -0
- package/docs/07_web_chat_ux/tickets.md +48 -0
- package/docs/08_agent_api/development_log.md +52 -0
- package/docs/08_agent_api/notes.md +31 -0
- package/docs/08_agent_api/prd.md +56 -0
- package/docs/08_agent_api/questions.md +14 -0
- package/docs/08_agent_api/tickets.md +104 -0
- package/docs/09_agent_fallbacks/development_log.md +52 -0
- package/docs/09_agent_fallbacks/notes.md +40 -0
- package/docs/09_agent_fallbacks/prd.md +55 -0
- package/docs/09_agent_fallbacks/questions.md +10 -0
- package/docs/09_agent_fallbacks/tickets.md +88 -0
- package/docs/09_discord_adapter/development_log.md +95 -0
- package/docs/09_discord_adapter/notes.md +18 -0
- package/docs/09_discord_adapter/prd.md +57 -0
- package/docs/09_discord_adapter/questions.md +16 -0
- package/docs/09_discord_adapter/tickets.md +116 -0
- package/docs/10_file_attachments/development_log.md +55 -0
- package/docs/10_file_attachments/notes.md +59 -0
- package/docs/10_file_attachments/prd.md +73 -0
- package/docs/10_file_attachments/questions.md +15 -0
- package/docs/10_file_attachments/tickets.md +88 -0
- package/docs/11_message_verbosity/development_log.md +43 -0
- package/docs/11_message_verbosity/notes.md +26 -0
- package/docs/11_message_verbosity/prd.md +44 -0
- package/docs/11_message_verbosity/questions.md +8 -0
- package/docs/11_message_verbosity/tickets.md +33 -0
- package/docs/12_environments/development_log.md +43 -0
- package/docs/12_environments/notes.md +45 -0
- package/docs/12_environments/prd.md +113 -0
- package/docs/12_environments/questions.md +17 -0
- package/docs/12_environments/tickets.md +87 -0
- package/docs/12_setup_flow_improvements/development_log.md +40 -0
- package/docs/12_setup_flow_improvements/notes.md +34 -0
- package/docs/12_setup_flow_improvements/prd.md +35 -0
- package/docs/12_setup_flow_improvements/questions.md +8 -0
- package/docs/12_setup_flow_improvements/tickets.md +122 -0
- package/docs/13_discord_typing_indicators/development_log.md +38 -0
- package/docs/13_discord_typing_indicators/notes.md +18 -0
- package/docs/13_discord_typing_indicators/prd.md +41 -0
- package/docs/13_discord_typing_indicators/questions.md +6 -0
- package/docs/13_discord_typing_indicators/tickets.md +60 -0
- package/docs/14_interruptions/development_log.md +50 -0
- package/docs/14_interruptions/notes.md +38 -0
- package/docs/14_interruptions/prd.md +46 -0
- package/docs/14_interruptions/questions.md +12 -0
- package/docs/14_interruptions/tickets.md +69 -0
- package/docs/15_sandbox_policies/development_log.md +95 -0
- package/docs/15_sandbox_policies/notes.md +33 -0
- package/docs/15_sandbox_policies/prd.md +163 -0
- package/docs/15_sandbox_policies/questions.md +10 -0
- package/docs/15_sandbox_policies/tickets.md +196 -0
- package/docs/CHECKS.md +9 -0
- package/docs/guides/discord_adapter_setup.md +69 -0
- package/docs/guides/sandbox_policies.md +76 -0
- package/eslint.config.js +47 -0
- package/napkin.md +21 -0
- package/package.json +50 -0
- package/scripts/create_worktree.sh +49 -0
- package/scripts/get_pr_comments.sh +36 -0
- package/src/adapter-discord/client.test.ts +65 -0
- package/src/adapter-discord/client.ts +41 -0
- package/src/adapter-discord/config.test.ts +156 -0
- package/src/adapter-discord/config.ts +61 -0
- package/src/adapter-discord/forwarder.test.ts +493 -0
- package/src/adapter-discord/forwarder.ts +246 -0
- package/src/adapter-discord/index.test.ts +399 -0
- package/src/adapter-discord/index.ts +147 -0
- package/src/adapter-discord/state.test.ts +65 -0
- package/src/adapter-discord/state.ts +44 -0
- package/src/cli/client.ts +46 -0
- package/src/cli/commands/agents.ts +138 -0
- package/src/cli/commands/chats.ts +79 -0
- package/src/cli/commands/down.ts +32 -0
- package/src/cli/commands/environments.ts +39 -0
- package/src/cli/commands/export-lite.ts +62 -0
- package/src/cli/commands/init.ts +79 -0
- package/src/cli/commands/jobs.ts +141 -0
- package/src/cli/commands/messages.ts +103 -0
- package/src/cli/commands/up.ts +26 -0
- package/src/cli/commands/web-api/agents.ts +138 -0
- package/src/cli/commands/web-api/chats.ts +213 -0
- package/src/cli/commands/web-api/utils.ts +27 -0
- package/src/cli/commands/web.ts +105 -0
- package/src/cli/e2e/adapter-discord.test.ts +76 -0
- package/src/cli/e2e/agents.test.ts +140 -0
- package/src/cli/e2e/basic.test.ts +43 -0
- package/src/cli/e2e/cron.test.ts +132 -0
- package/src/cli/e2e/daemon.test.ts +293 -0
- package/src/cli/e2e/environments.test.ts +66 -0
- package/src/cli/e2e/export-lite-func.test.ts +155 -0
- package/src/cli/e2e/export-lite.test.ts +51 -0
- package/src/cli/e2e/fallbacks.test.ts +169 -0
- package/src/cli/e2e/global-setup.ts +15 -0
- package/src/cli/e2e/init.test.ts +70 -0
- package/src/cli/e2e/messages.test.ts +294 -0
- package/src/cli/e2e/requests.test.ts +165 -0
- package/src/cli/e2e/utils.ts +66 -0
- package/src/cli/index.test.ts +7 -0
- package/src/cli/index.ts +29 -0
- package/src/cli/lite.ts +247 -0
- package/src/cli/utils.ts +4 -0
- package/src/daemon/auth.test.ts +50 -0
- package/src/daemon/auth.ts +69 -0
- package/src/daemon/chats.ts +26 -0
- package/src/daemon/cron.test.ts +28 -0
- package/src/daemon/cron.ts +159 -0
- package/src/daemon/events.ts +15 -0
- package/src/daemon/index.ts +212 -0
- package/src/daemon/message-agent.test.ts +132 -0
- package/src/daemon/message-extraction.test.ts +166 -0
- package/src/daemon/message-fallbacks.test.ts +313 -0
- package/src/daemon/message-interruption.test.ts +125 -0
- package/src/daemon/message-queue.test.ts +143 -0
- package/src/daemon/message-router.test.ts +106 -0
- package/src/daemon/message-session.test.ts +127 -0
- package/src/daemon/message-test-utils.ts +41 -0
- package/src/daemon/message-typing.test.ts +93 -0
- package/src/daemon/message-verbosity.test.ts +127 -0
- package/src/daemon/message.ts +600 -0
- package/src/daemon/observation.test.ts +118 -0
- package/src/daemon/policy-request-service.test.ts +87 -0
- package/src/daemon/policy-request-service.ts +62 -0
- package/src/daemon/policy-utils.test.ts +138 -0
- package/src/daemon/policy-utils.ts +152 -0
- package/src/daemon/queue.test.ts +89 -0
- package/src/daemon/queue.ts +87 -0
- package/src/daemon/request-store.test.ts +103 -0
- package/src/daemon/request-store.ts +96 -0
- package/src/daemon/router-policy-request.test.ts +99 -0
- package/src/daemon/router.test.ts +380 -0
- package/src/daemon/router.ts +510 -0
- package/src/daemon/routers/slash-command.test.ts +145 -0
- package/src/daemon/routers/slash-command.ts +58 -0
- package/src/daemon/routers/slash-interrupt.test.ts +30 -0
- package/src/daemon/routers/slash-interrupt.ts +7 -0
- package/src/daemon/routers/slash-new.test.ts +59 -0
- package/src/daemon/routers/slash-new.ts +14 -0
- package/src/daemon/routers/slash-policies.test.ts +167 -0
- package/src/daemon/routers/slash-policies.ts +131 -0
- package/src/daemon/routers/slash-stop.test.ts +30 -0
- package/src/daemon/routers/slash-stop.ts +3 -0
- package/src/daemon/routers/types.ts +10 -0
- package/src/daemon/routers/utils.ts +22 -0
- package/src/daemon/routers.test.ts +141 -0
- package/src/daemon/routers.ts +115 -0
- package/src/daemon/utils/spawn.ts +61 -0
- package/src/shared/agent-utils.ts +30 -0
- package/src/shared/chats.test.ts +112 -0
- package/src/shared/chats.ts +164 -0
- package/src/shared/config.test.ts +90 -0
- package/src/shared/config.ts +100 -0
- package/src/shared/event-source.ts +121 -0
- package/src/shared/fetch.ts +45 -0
- package/src/shared/lite.ts +129 -0
- package/src/shared/policies.ts +24 -0
- package/src/shared/utils/env.ts +27 -0
- package/src/shared/utils/fs.ts +13 -0
- package/src/shared/workspace.test.ts +345 -0
- package/src/shared/workspace.ts +500 -0
- package/templates/environments/cladding/env.json +7 -0
- package/templates/environments/macos/env.json +8 -0
- package/templates/environments/macos/sandbox.sb +21 -0
- package/templates/environments/macos-proxy/allowlist.txt +1 -0
- package/templates/environments/macos-proxy/env.json +14 -0
- package/templates/environments/macos-proxy/proxy.mjs +86 -0
- package/templates/environments/macos-proxy/sandbox.sb +34 -0
- package/templates/gemini/settings.json +11 -0
- package/templates/gemini-claw/.gemini/hooks/clawmini-logging.sh +17 -0
- package/templates/gemini-claw/.gemini/settings.json +24 -0
- package/templates/gemini-claw/.gemini/skills/clawmini-jobs/SKILL.md +40 -0
- package/templates/gemini-claw/.gemini/system.md +98 -0
- package/templates/gemini-claw/BOOTSTRAP.md +54 -0
- package/templates/gemini-claw/GEMINI.md +107 -0
- package/templates/gemini-claw/HEARTBEAT.md +3 -0
- package/templates/gemini-claw/MEMORY.md +2 -0
- package/templates/gemini-claw/SOUL.md +42 -0
- package/templates/gemini-claw/TOOLS.md +38 -0
- package/templates/gemini-claw/USER.md +15 -0
- package/templates/gemini-claw/memory/.gitkeep +0 -0
- package/templates/gemini-claw/settings.json +24 -0
- package/templates/opencode/settings.json +11 -0
- package/tsconfig.json +42 -0
- package/tsdown.config.ts +19 -0
- package/vitest.config.ts +9 -0
- package/web/.svelte-kit/ambient.d.ts +382 -0
- package/web/.svelte-kit/generated/client/app.js +35 -0
- package/web/.svelte-kit/generated/client/matchers.js +1 -0
- package/web/.svelte-kit/generated/client/nodes/0.js +3 -0
- package/web/.svelte-kit/generated/client/nodes/1.js +1 -0
- package/web/.svelte-kit/generated/client/nodes/2.js +1 -0
- package/web/.svelte-kit/generated/client/nodes/3.js +1 -0
- package/web/.svelte-kit/generated/client/nodes/4.js +3 -0
- package/web/.svelte-kit/generated/client/nodes/5.js +3 -0
- package/web/.svelte-kit/generated/client-optimized/app.js +35 -0
- package/web/.svelte-kit/generated/client-optimized/matchers.js +1 -0
- package/web/.svelte-kit/generated/client-optimized/nodes/0.js +3 -0
- package/web/.svelte-kit/generated/client-optimized/nodes/1.js +1 -0
- package/web/.svelte-kit/generated/client-optimized/nodes/2.js +1 -0
- package/web/.svelte-kit/generated/client-optimized/nodes/3.js +1 -0
- package/web/.svelte-kit/generated/client-optimized/nodes/4.js +3 -0
- package/web/.svelte-kit/generated/client-optimized/nodes/5.js +3 -0
- package/web/.svelte-kit/generated/root.js +3 -0
- package/web/.svelte-kit/generated/root.svelte +68 -0
- package/web/.svelte-kit/generated/server/internal.js +53 -0
- package/web/.svelte-kit/non-ambient.d.ts +46 -0
- package/web/.svelte-kit/output/client/.vite/manifest.json +251 -0
- package/web/.svelte-kit/output/client/_app/immutable/assets/0.GI4C4dpV.css +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/B5abRDXp.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/B8yYFADm.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/BPy8HLo7.js +5 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/Bi0jeV7Q.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/BmUXQ3wy.js +2 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/C3k55nDF.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/COekwvP2.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/CSvS_NwK.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/CpaGRn9L.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/CyNaE55B.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/DG5RZBw-.js +2 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/Dc-UOHw9.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/DcrmIfTj.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/chunks/ZkLyk0mE.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/entry/app.B-vZe7PN.js +2 -0
- package/web/.svelte-kit/output/client/_app/immutable/entry/start.oP1AgKhs.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/0.B5WFN0zw.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/1.D1wtJb2k.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/2.CK3CLC0f.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/3.BB5wCoBf.js +4 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/4.Dr2jvAXK.js +1 -0
- package/web/.svelte-kit/output/client/_app/immutable/nodes/5.BJl7oM3b.js +1 -0
- package/web/.svelte-kit/output/client/_app/version.json +1 -0
- package/web/.svelte-kit/output/client/robots.txt +3 -0
- package/web/.svelte-kit/output/prerendered/dependencies/_app/env.js +1 -0
- package/web/.svelte-kit/output/server/.vite/manifest.json +215 -0
- package/web/.svelte-kit/output/server/_app/immutable/assets/_layout.GI4C4dpV.css +1 -0
- package/web/.svelte-kit/output/server/chunks/Icon.js +153 -0
- package/web/.svelte-kit/output/server/chunks/bot.js +2753 -0
- package/web/.svelte-kit/output/server/chunks/client.js +47 -0
- package/web/.svelte-kit/output/server/chunks/environment.js +34 -0
- package/web/.svelte-kit/output/server/chunks/exports.js +231 -0
- package/web/.svelte-kit/output/server/chunks/false.js +4 -0
- package/web/.svelte-kit/output/server/chunks/index-server.js +20 -0
- package/web/.svelte-kit/output/server/chunks/index.js +24 -0
- package/web/.svelte-kit/output/server/chunks/internal.js +133 -0
- package/web/.svelte-kit/output/server/chunks/plus.js +81 -0
- package/web/.svelte-kit/output/server/chunks/root.js +4076 -0
- package/web/.svelte-kit/output/server/chunks/shared.js +789 -0
- package/web/.svelte-kit/output/server/chunks/utils.js +43 -0
- package/web/.svelte-kit/output/server/entries/fallbacks/error.svelte.js +11 -0
- package/web/.svelte-kit/output/server/entries/pages/_layout.svelte.js +3944 -0
- package/web/.svelte-kit/output/server/entries/pages/_layout.ts.js +28 -0
- package/web/.svelte-kit/output/server/entries/pages/_page.svelte.js +7 -0
- package/web/.svelte-kit/output/server/entries/pages/agents/_page.svelte.js +379 -0
- package/web/.svelte-kit/output/server/entries/pages/chats/_id_/_page.svelte.js +292 -0
- package/web/.svelte-kit/output/server/entries/pages/chats/_id_/_page.ts.js +17 -0
- package/web/.svelte-kit/output/server/entries/pages/chats/_id_/settings/_page.svelte.js +259 -0
- package/web/.svelte-kit/output/server/entries/pages/chats/_id_/settings/_page.ts.js +17 -0
- package/web/.svelte-kit/output/server/index.js +3748 -0
- package/web/.svelte-kit/output/server/internal.js +14 -0
- package/web/.svelte-kit/output/server/manifest-full.js +63 -0
- package/web/.svelte-kit/output/server/manifest.js +63 -0
- package/web/.svelte-kit/output/server/nodes/0.js +13 -0
- package/web/.svelte-kit/output/server/nodes/1.js +8 -0
- package/web/.svelte-kit/output/server/nodes/2.js +8 -0
- package/web/.svelte-kit/output/server/nodes/3.js +8 -0
- package/web/.svelte-kit/output/server/nodes/4.js +13 -0
- package/web/.svelte-kit/output/server/nodes/5.js +13 -0
- package/web/.svelte-kit/output/server/remote-entry.js +557 -0
- package/web/.svelte-kit/tsconfig.json +67 -0
- package/web/.svelte-kit/types/route_meta_data.json +17 -0
- package/web/.svelte-kit/types/src/routes/$types.d.ts +26 -0
- package/web/.svelte-kit/types/src/routes/agents/$types.d.ts +18 -0
- package/web/.svelte-kit/types/src/routes/chats/[id]/$types.d.ts +21 -0
- package/web/.svelte-kit/types/src/routes/chats/[id]/proxy+page.ts +20 -0
- package/web/.svelte-kit/types/src/routes/chats/[id]/settings/$types.d.ts +21 -0
- package/web/.svelte-kit/types/src/routes/chats/[id]/settings/proxy+page.ts +19 -0
- package/web/.svelte-kit/types/src/routes/proxy+layout.ts +35 -0
- package/web/README.md +42 -0
- package/web/components.json +16 -0
- package/web/package.json +41 -0
- package/web/src/app.css +121 -0
- package/web/src/app.d.ts +13 -0
- package/web/src/app.html +11 -0
- package/web/src/demo.spec.ts +7 -0
- package/web/src/lib/app-state.svelte.ts +3 -0
- package/web/src/lib/assets/favicon.svg +1 -0
- package/web/src/lib/components/app/app-sidebar-test-wrapper.svelte +10 -0
- package/web/src/lib/components/app/app-sidebar.svelte +171 -0
- package/web/src/lib/components/app/app-sidebar.svelte.spec.ts +13 -0
- package/web/src/lib/components/ui/button/button.svelte +82 -0
- package/web/src/lib/components/ui/button/index.ts +17 -0
- package/web/src/lib/components/ui/dialog/dialog-close.svelte +7 -0
- package/web/src/lib/components/ui/dialog/dialog-content.svelte +45 -0
- package/web/src/lib/components/ui/dialog/dialog-description.svelte +17 -0
- package/web/src/lib/components/ui/dialog/dialog-footer.svelte +20 -0
- package/web/src/lib/components/ui/dialog/dialog-header.svelte +20 -0
- package/web/src/lib/components/ui/dialog/dialog-overlay.svelte +20 -0
- package/web/src/lib/components/ui/dialog/dialog-portal.svelte +7 -0
- package/web/src/lib/components/ui/dialog/dialog-title.svelte +17 -0
- package/web/src/lib/components/ui/dialog/dialog-trigger.svelte +7 -0
- package/web/src/lib/components/ui/dialog/dialog.svelte +7 -0
- package/web/src/lib/components/ui/dialog/index.ts +34 -0
- package/web/src/lib/components/ui/input/index.ts +7 -0
- package/web/src/lib/components/ui/input/input.svelte +52 -0
- package/web/src/lib/components/ui/separator/index.ts +7 -0
- package/web/src/lib/components/ui/separator/separator.svelte +21 -0
- package/web/src/lib/components/ui/sheet/index.ts +34 -0
- package/web/src/lib/components/ui/sheet/sheet-close.svelte +7 -0
- package/web/src/lib/components/ui/sheet/sheet-content.svelte +60 -0
- package/web/src/lib/components/ui/sheet/sheet-description.svelte +17 -0
- package/web/src/lib/components/ui/sheet/sheet-footer.svelte +20 -0
- package/web/src/lib/components/ui/sheet/sheet-header.svelte +20 -0
- package/web/src/lib/components/ui/sheet/sheet-overlay.svelte +20 -0
- package/web/src/lib/components/ui/sheet/sheet-portal.svelte +7 -0
- package/web/src/lib/components/ui/sheet/sheet-title.svelte +17 -0
- package/web/src/lib/components/ui/sheet/sheet-trigger.svelte +7 -0
- package/web/src/lib/components/ui/sheet/sheet.svelte +7 -0
- package/web/src/lib/components/ui/sidebar/constants.ts +6 -0
- package/web/src/lib/components/ui/sidebar/context.svelte.ts +79 -0
- package/web/src/lib/components/ui/sidebar/index.ts +75 -0
- package/web/src/lib/components/ui/sidebar/sidebar-content.svelte +24 -0
- package/web/src/lib/components/ui/sidebar/sidebar-footer.svelte +21 -0
- package/web/src/lib/components/ui/sidebar/sidebar-group-action.svelte +36 -0
- package/web/src/lib/components/ui/sidebar/sidebar-group-content.svelte +21 -0
- package/web/src/lib/components/ui/sidebar/sidebar-group-label.svelte +34 -0
- package/web/src/lib/components/ui/sidebar/sidebar-group.svelte +21 -0
- package/web/src/lib/components/ui/sidebar/sidebar-header.svelte +21 -0
- package/web/src/lib/components/ui/sidebar/sidebar-input.svelte +21 -0
- package/web/src/lib/components/ui/sidebar/sidebar-inset.svelte +24 -0
- package/web/src/lib/components/ui/sidebar/sidebar-menu-action.svelte +43 -0
- package/web/src/lib/components/ui/sidebar/sidebar-menu-badge.svelte +29 -0
- package/web/src/lib/components/ui/sidebar/sidebar-menu-button.svelte +103 -0
- package/web/src/lib/components/ui/sidebar/sidebar-menu-item.svelte +21 -0
- package/web/src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte +36 -0
- package/web/src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte +43 -0
- package/web/src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte +21 -0
- package/web/src/lib/components/ui/sidebar/sidebar-menu-sub.svelte +25 -0
- package/web/src/lib/components/ui/sidebar/sidebar-menu.svelte +21 -0
- package/web/src/lib/components/ui/sidebar/sidebar-provider.svelte +53 -0
- package/web/src/lib/components/ui/sidebar/sidebar-rail.svelte +36 -0
- package/web/src/lib/components/ui/sidebar/sidebar-separator.svelte +19 -0
- package/web/src/lib/components/ui/sidebar/sidebar-trigger.svelte +35 -0
- package/web/src/lib/components/ui/sidebar/sidebar.svelte +104 -0
- package/web/src/lib/components/ui/skeleton/index.ts +7 -0
- package/web/src/lib/components/ui/skeleton/skeleton.svelte +17 -0
- package/web/src/lib/components/ui/switch/index.ts +7 -0
- package/web/src/lib/components/ui/switch/switch.svelte +29 -0
- package/web/src/lib/components/ui/textarea/index.ts +7 -0
- package/web/src/lib/components/ui/textarea/textarea.svelte +23 -0
- package/web/src/lib/components/ui/tooltip/index.ts +19 -0
- package/web/src/lib/components/ui/tooltip/tooltip-content.svelte +52 -0
- package/web/src/lib/components/ui/tooltip/tooltip-portal.svelte +7 -0
- package/web/src/lib/components/ui/tooltip/tooltip-provider.svelte +7 -0
- package/web/src/lib/components/ui/tooltip/tooltip-trigger.svelte +7 -0
- package/web/src/lib/components/ui/tooltip/tooltip.svelte +7 -0
- package/web/src/lib/hooks/is-mobile.svelte.ts +9 -0
- package/web/src/lib/index.ts +1 -0
- package/web/src/lib/types.ts +23 -0
- package/web/src/lib/utils.ts +13 -0
- package/web/src/routes/+layout.svelte +67 -0
- package/web/src/routes/+layout.ts +34 -0
- package/web/src/routes/+page.svelte +7 -0
- package/web/src/routes/agents/+page.svelte +206 -0
- package/web/src/routes/chats/[id]/+page.svelte +406 -0
- package/web/src/routes/chats/[id]/+page.ts +19 -0
- package/web/src/routes/chats/[id]/page.svelte.spec.ts +102 -0
- package/web/src/routes/chats/[id]/settings/+page.svelte +165 -0
- package/web/src/routes/chats/[id]/settings/+page.ts +18 -0
- package/web/src/routes/page.svelte.spec.ts +13 -0
- package/web/static/robots.txt +3 -0
- package/web/svelte.config.js +21 -0
- package/web/tsconfig.json +20 -0
- package/web/vite.config.ts +41 -0
|
@@ -0,0 +1,850 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { a as getAgent, b as writeChatSettings, d as isValidAgentId, f as listAgents, g as readSettings, l as getSocketPath, m as readChatSettings, n as deleteAgent, o as getClawminiDir, r as enableEnvironment, t as applyTemplateToAgent, x as writeSettings, y as writeAgentSettings } from "../workspace-CSgfo_2J.mjs";
|
|
3
|
+
import { n as pathIsInsideDir } from "../fs-B5wW0oaH.mjs";
|
|
4
|
+
import { a as getChatsDir, c as isValidChatId, i as deleteChat, l as listChats, o as getDefaultChatId, r as createChat, s as getMessages, t as DEFAULT_CHAT_ID, u as setDefaultChatId } from "../chats-DKgTeU7i.mjs";
|
|
5
|
+
import { t as createUnixSocketFetch } from "../fetch-BjZVyU3Z.mjs";
|
|
6
|
+
import { i as writeLiteScript, r as getLiteScriptContent, t as exportLiteToAllEnvironments } from "../lite-Dl7WXyaH.mjs";
|
|
7
|
+
import { Command } from "commander";
|
|
8
|
+
import fs from "node:fs";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import { spawn } from "node:child_process";
|
|
11
|
+
import * as fs$2 from "node:fs/promises";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
import { createTRPCClient, httpLink } from "@trpc/client";
|
|
15
|
+
import http from "node:http";
|
|
16
|
+
|
|
17
|
+
//#region src/shared/agent-utils.ts
|
|
18
|
+
async function createAgentWithChat(agentId, agentData, template, startDir = process.cwd()) {
|
|
19
|
+
await writeAgentSettings(agentId, agentData, startDir);
|
|
20
|
+
if (template) await applyTemplateToAgent(agentId, template, agentData, startDir);
|
|
21
|
+
if ((await listChats(startDir)).includes(agentId)) console.warn(`Warning: Chat ${agentId} already exists.`);
|
|
22
|
+
else {
|
|
23
|
+
await createChat(agentId, startDir);
|
|
24
|
+
await writeChatSettings(agentId, {
|
|
25
|
+
...await readChatSettings(agentId, startDir) || {},
|
|
26
|
+
defaultAgent: agentId
|
|
27
|
+
}, startDir);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/cli/utils.ts
|
|
33
|
+
function handleError$1(action, err) {
|
|
34
|
+
console.error(`Failed to ${action}:`, err instanceof Error ? err.message : String(err));
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/cli/commands/init.ts
|
|
40
|
+
const initCmd = new Command("init").description("Initialize a new .clawmini settings folder").option("--agent <name>", "Initialize with a specific agent").option("--agent-template <name>", "Template to use for the agent").option("--environment <name>", "Enable a specific environment").action(async (options) => {
|
|
41
|
+
if (options.agentTemplate && !options.agent) handleError$1("initialize", /* @__PURE__ */ new Error("--agent-template cannot be used without --agent"));
|
|
42
|
+
if (options.agent && !isValidAgentId(options.agent)) handleError$1("initialize", /* @__PURE__ */ new Error(`Invalid agent ID: ${options.agent}`));
|
|
43
|
+
const cwd = process.cwd();
|
|
44
|
+
const dirPath = path.join(cwd, ".clawmini");
|
|
45
|
+
const settingsPath = path.join(dirPath, "settings.json");
|
|
46
|
+
if (fs.existsSync(settingsPath)) {
|
|
47
|
+
console.log(".clawmini already initialized");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const defaultSettings = {
|
|
51
|
+
defaultAgent: {
|
|
52
|
+
commands: { new: "echo $CLAW_CLI_MESSAGE" },
|
|
53
|
+
env: {}
|
|
54
|
+
},
|
|
55
|
+
routers: [
|
|
56
|
+
"@clawmini/slash-new",
|
|
57
|
+
"@clawmini/slash-stop",
|
|
58
|
+
"@clawmini/slash-interrupt",
|
|
59
|
+
"@clawmini/slash-command"
|
|
60
|
+
],
|
|
61
|
+
api: true
|
|
62
|
+
};
|
|
63
|
+
if (!fs.existsSync(dirPath)) fs.mkdirSync(dirPath, { recursive: true });
|
|
64
|
+
fs.writeFileSync(settingsPath, JSON.stringify(defaultSettings, null, 2));
|
|
65
|
+
console.log("Initialized .clawmini/settings.json");
|
|
66
|
+
if (options.agent) try {
|
|
67
|
+
const agentId = options.agent;
|
|
68
|
+
await createAgentWithChat(agentId, {}, options.agentTemplate);
|
|
69
|
+
console.log(`Agent ${agentId} created successfully.`);
|
|
70
|
+
await setDefaultChatId(agentId);
|
|
71
|
+
console.log(`Default chat set to ${agentId}.`);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
handleError$1("create agent", err);
|
|
74
|
+
}
|
|
75
|
+
if (options.environment) try {
|
|
76
|
+
await enableEnvironment(options.environment);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
handleError$1("enable environment", err);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/cli/client.ts
|
|
84
|
+
async function getDaemonClient(options = {}) {
|
|
85
|
+
const { autoStart = true } = options;
|
|
86
|
+
const socketPath = getSocketPath();
|
|
87
|
+
if (!fs.existsSync(socketPath)) {
|
|
88
|
+
if (!autoStart) throw new Error("Daemon not running.");
|
|
89
|
+
console.log("Daemon not running. Starting daemon...");
|
|
90
|
+
const daemonPath = new URL("../daemon/index.mjs", import.meta.url).pathname;
|
|
91
|
+
const logFile = fs.openSync(path.join(getClawminiDir(), "daemon.log"), "a");
|
|
92
|
+
spawn(process.execPath, [daemonPath], {
|
|
93
|
+
detached: true,
|
|
94
|
+
stdio: [
|
|
95
|
+
"ignore",
|
|
96
|
+
logFile,
|
|
97
|
+
logFile
|
|
98
|
+
]
|
|
99
|
+
}).unref();
|
|
100
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
101
|
+
if (!fs.existsSync(socketPath)) throw new Error("Failed to start daemon.");
|
|
102
|
+
}
|
|
103
|
+
return createTRPCClient({ links: [httpLink({
|
|
104
|
+
url: "http://localhost",
|
|
105
|
+
fetch: createUnixSocketFetch(socketPath)
|
|
106
|
+
})] });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/cli/commands/messages.ts
|
|
111
|
+
const messagesCmd = new Command("messages").description("Manage messages");
|
|
112
|
+
messagesCmd.command("send <message>").description("Send a new message").option("-c, --chat <id>", "Specific chat to send the message to").option("-s, --session <id>", "Specific session to send the message to").option("-a, --agent <name>", "Specific agent to use for this message").option("--no-wait", "Return immediately after the server queues the message").option("-f, --file <path>", "File to attach", (val, prev) => prev.concat([val]), []).action(async (message, options) => {
|
|
113
|
+
try {
|
|
114
|
+
if (options.agent) {
|
|
115
|
+
if (!isValidAgentId(options.agent)) {
|
|
116
|
+
console.error(`Error: Invalid agent ID '${options.agent}'.`);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
if (options.agent !== "default") {
|
|
120
|
+
if (!await getAgent(options.agent)) {
|
|
121
|
+
console.error(`Error: Agent '${options.agent}' not found.`);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
let finalFiles = void 0;
|
|
127
|
+
if (options.file && options.file.length > 0) {
|
|
128
|
+
finalFiles = [];
|
|
129
|
+
const tmpDir = path.join(getClawminiDir(process.cwd()), "tmp");
|
|
130
|
+
await fs$2.mkdir(tmpDir, { recursive: true });
|
|
131
|
+
for (const f of options.file) {
|
|
132
|
+
const dest = path.join(tmpDir, `cli-${Date.now()}-${Math.random().toString(36).substring(2, 7)}-${path.basename(f)}`);
|
|
133
|
+
await fs$2.copyFile(path.resolve(process.cwd(), f), dest);
|
|
134
|
+
finalFiles.push(dest);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
await (await getDaemonClient()).sendMessage.mutate({
|
|
138
|
+
type: "send-message",
|
|
139
|
+
client: "cli",
|
|
140
|
+
data: {
|
|
141
|
+
message,
|
|
142
|
+
chatId: options.chat,
|
|
143
|
+
sessionId: options.session,
|
|
144
|
+
agentId: options.agent,
|
|
145
|
+
noWait: !options.wait,
|
|
146
|
+
files: finalFiles
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
console.log("Message sent successfully.");
|
|
150
|
+
} catch (err) {
|
|
151
|
+
console.error("Failed to send message:", err instanceof Error ? err.message : String(err));
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
messagesCmd.command("tail").description("View message history").option("-n, --lines <number>", "Number of messages to show", parseInt).option("--json", "Output raw JSONL format").option("-c, --chat <id>", "Specific chat to view").action(async (options) => {
|
|
156
|
+
try {
|
|
157
|
+
const messages = await getMessages(options.chat ?? await getDefaultChatId(), options.lines);
|
|
158
|
+
if (options.json) messages.forEach((msg) => console.log(JSON.stringify(msg)));
|
|
159
|
+
else messages.forEach((msg) => {
|
|
160
|
+
if (msg.role === "user") console.log(`[USER] ${msg.content}`);
|
|
161
|
+
else if (msg.role === "log") {
|
|
162
|
+
if (msg.content) console.log(`[LOG] ${msg.content.trim()}`);
|
|
163
|
+
else if (msg.stderr) console.error(`[STDERR] ${msg.stderr.trim()}`);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
} catch (err) {
|
|
167
|
+
console.error("Failed to retrieve messages:", err instanceof Error ? err.message : String(err));
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region src/cli/commands/chats.ts
|
|
174
|
+
const chatsCmd = new Command("chats").description("Manage chat sessions");
|
|
175
|
+
chatsCmd.command("list").description("Display existing chats").action(async () => {
|
|
176
|
+
try {
|
|
177
|
+
const chats = await listChats();
|
|
178
|
+
const defaultId = await getDefaultChatId();
|
|
179
|
+
if (chats.length === 0) {
|
|
180
|
+
console.log("No chats found.");
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
for (const id of chats) {
|
|
184
|
+
const marker = id === defaultId ? " *" : "";
|
|
185
|
+
console.log(`- ${id}${marker}`);
|
|
186
|
+
}
|
|
187
|
+
} catch (err) {
|
|
188
|
+
console.error("Failed to list chats:", err instanceof Error ? err.message : String(err));
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
chatsCmd.command("add <id>").description("Initialize a new chat").action(async (id) => {
|
|
193
|
+
try {
|
|
194
|
+
await createChat(id);
|
|
195
|
+
console.log(`Chat ${id} created successfully.`);
|
|
196
|
+
} catch (err) {
|
|
197
|
+
console.error("Failed to create chat:", err instanceof Error ? err.message : String(err));
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
chatsCmd.command("delete <id>").description("Remove a chat").action(async (id) => {
|
|
202
|
+
try {
|
|
203
|
+
const defaultId = await getDefaultChatId();
|
|
204
|
+
await deleteChat(id);
|
|
205
|
+
console.log(`Chat ${id} deleted successfully.`);
|
|
206
|
+
if (id === defaultId) {
|
|
207
|
+
await setDefaultChatId(DEFAULT_CHAT_ID);
|
|
208
|
+
console.log(`Default chat reset to default.`);
|
|
209
|
+
}
|
|
210
|
+
} catch (err) {
|
|
211
|
+
console.error("Failed to delete chat:", err instanceof Error ? err.message : String(err));
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
chatsCmd.command("set-default <id>").description("Update the workspace default chat").action(async (id) => {
|
|
216
|
+
try {
|
|
217
|
+
await setDefaultChatId(id);
|
|
218
|
+
console.log(`Default chat set to ${id}.`);
|
|
219
|
+
} catch (err) {
|
|
220
|
+
console.error("Failed to set default chat:", err instanceof Error ? err.message : String(err));
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
//#endregion
|
|
226
|
+
//#region src/cli/commands/agents.ts
|
|
227
|
+
const agentsCmd = new Command("agents").description("Manage agents");
|
|
228
|
+
function parseEnv(envArray) {
|
|
229
|
+
if (!envArray || envArray.length === 0) return void 0;
|
|
230
|
+
const env = {};
|
|
231
|
+
for (const e of envArray) {
|
|
232
|
+
const [key, ...rest] = e.split("=");
|
|
233
|
+
if (key && rest.length >= 0) env[key] = rest.join("=");
|
|
234
|
+
}
|
|
235
|
+
return env;
|
|
236
|
+
}
|
|
237
|
+
function assertValidAgentId(id) {
|
|
238
|
+
if (!isValidAgentId(id)) throw new Error(`Invalid agent ID: ${id}`);
|
|
239
|
+
}
|
|
240
|
+
agentsCmd.command("list").description("Display existing agents").action(async () => {
|
|
241
|
+
try {
|
|
242
|
+
const agents = await listAgents();
|
|
243
|
+
if (agents.length === 0) {
|
|
244
|
+
console.log("No agents found.");
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
for (const id of agents) console.log(`- ${id}`);
|
|
248
|
+
} catch (err) {
|
|
249
|
+
handleError$1("list agents", err);
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
agentsCmd.command("add <id>").description("Create a new agent").option("-d, --directory <dir>", "Working directory for the agent").option("-t, --template <name>", "Template to use for the agent").option("-e, --env <env...>", "Environment variables in KEY=VALUE format (can be specified multiple times)").action(async (id, options) => {
|
|
253
|
+
try {
|
|
254
|
+
assertValidAgentId(id);
|
|
255
|
+
if (await getAgent(id)) throw new Error(`Agent ${id} already exists.`);
|
|
256
|
+
const agentData = {};
|
|
257
|
+
if (options.directory) agentData.directory = options.directory;
|
|
258
|
+
const env = parseEnv(options.env);
|
|
259
|
+
if (env) agentData.env = {
|
|
260
|
+
...agentData.env || {},
|
|
261
|
+
...env
|
|
262
|
+
};
|
|
263
|
+
await createAgentWithChat(id, agentData, options.template);
|
|
264
|
+
console.log(`Agent ${id} created successfully.`);
|
|
265
|
+
} catch (err) {
|
|
266
|
+
handleError$1("create agent", err);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
agentsCmd.command("update <id>").description("Update an existing agent").option("-d, --directory <dir>", "Working directory for the agent").option("-e, --env <env...>", "Environment variables in KEY=VALUE format (can be specified multiple times)").action(async (id, options) => {
|
|
270
|
+
try {
|
|
271
|
+
assertValidAgentId(id);
|
|
272
|
+
const existing = await getAgent(id);
|
|
273
|
+
if (!existing) throw new Error(`Agent ${id} does not exist.`);
|
|
274
|
+
const agentData = { ...existing };
|
|
275
|
+
if (options.directory !== void 0) agentData.directory = options.directory;
|
|
276
|
+
const env = parseEnv(options.env);
|
|
277
|
+
if (env) agentData.env = {
|
|
278
|
+
...agentData.env || {},
|
|
279
|
+
...env
|
|
280
|
+
};
|
|
281
|
+
await writeAgentSettings(id, agentData);
|
|
282
|
+
console.log(`Agent ${id} updated successfully.`);
|
|
283
|
+
} catch (err) {
|
|
284
|
+
handleError$1("update agent", err);
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
agentsCmd.command("delete <id>").description("Remove an agent").action(async (id) => {
|
|
288
|
+
try {
|
|
289
|
+
assertValidAgentId(id);
|
|
290
|
+
if (!await getAgent(id)) throw new Error(`Agent ${id} does not exist.`);
|
|
291
|
+
await deleteAgent(id);
|
|
292
|
+
console.log(`Agent ${id} deleted successfully.`);
|
|
293
|
+
} catch (err) {
|
|
294
|
+
handleError$1("delete agent", err);
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
//#endregion
|
|
299
|
+
//#region src/cli/commands/down.ts
|
|
300
|
+
const downCmd = new Command("down").description("Stop the local clawmini daemon server").action(async () => {
|
|
301
|
+
try {
|
|
302
|
+
const client = await getDaemonClient({ autoStart: false });
|
|
303
|
+
process.stdout.write("Shutting down clawmini daemon...");
|
|
304
|
+
await client.shutdown.mutate();
|
|
305
|
+
const socketPath = getSocketPath();
|
|
306
|
+
while (fs.existsSync(socketPath)) {
|
|
307
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
308
|
+
process.stdout.write(".");
|
|
309
|
+
}
|
|
310
|
+
console.log("\nSuccessfully shut down clawmini daemon.");
|
|
311
|
+
} catch (err) {
|
|
312
|
+
if (err instanceof Error && err.message === "Daemon not running.") console.log("Daemon is not running.");
|
|
313
|
+
else {
|
|
314
|
+
console.error("\nFailed to shut down daemon:", err instanceof Error ? err.message : String(err));
|
|
315
|
+
process.exit(1);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
//#endregion
|
|
321
|
+
//#region src/cli/commands/up.ts
|
|
322
|
+
const upCmd = new Command("up").description("Start the local clawmini daemon server").action(async () => {
|
|
323
|
+
try {
|
|
324
|
+
const socketPath = getSocketPath();
|
|
325
|
+
const wasRunning = fs.existsSync(socketPath);
|
|
326
|
+
await (await getDaemonClient({ autoStart: true })).ping.query();
|
|
327
|
+
if (wasRunning) console.log("Daemon is already running.");
|
|
328
|
+
else console.log("Successfully started clawmini daemon.");
|
|
329
|
+
} catch (err) {
|
|
330
|
+
console.error("Failed to start daemon:", err instanceof Error ? err.message : String(err));
|
|
331
|
+
process.exit(1);
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
//#endregion
|
|
336
|
+
//#region src/cli/commands/web-api/utils.ts
|
|
337
|
+
async function parseJsonBody(req, schema) {
|
|
338
|
+
if (req.headers["content-type"] !== "application/json") throw new Error("Invalid Content-Type");
|
|
339
|
+
let bodyStr = "";
|
|
340
|
+
for await (const chunk of req) bodyStr += chunk;
|
|
341
|
+
const rawBody = JSON.parse(bodyStr);
|
|
342
|
+
if (schema) return schema.parse(rawBody);
|
|
343
|
+
return rawBody;
|
|
344
|
+
}
|
|
345
|
+
function sendJsonResponse(res, statusCode, data) {
|
|
346
|
+
res.writeHead(statusCode, { "Content-Type": "application/json" });
|
|
347
|
+
res.end(JSON.stringify(data));
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
//#endregion
|
|
351
|
+
//#region src/cli/commands/web-api/agents.ts
|
|
352
|
+
async function handleApiAgents(req, res, urlPath) {
|
|
353
|
+
if (req.method === "GET" && urlPath === "/api/agents") {
|
|
354
|
+
const agentIds = await listAgents();
|
|
355
|
+
const agents = [];
|
|
356
|
+
for (const id of agentIds) try {
|
|
357
|
+
const agent = await getAgent(id);
|
|
358
|
+
if (agent) agents.push({
|
|
359
|
+
id,
|
|
360
|
+
...agent
|
|
361
|
+
});
|
|
362
|
+
} catch (err) {
|
|
363
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
364
|
+
console.error(`Failed to load agent ${id}: ${errorMessage}`);
|
|
365
|
+
agents.push({
|
|
366
|
+
id,
|
|
367
|
+
error: errorMessage
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
sendJsonResponse(res, 200, agents);
|
|
371
|
+
return true;
|
|
372
|
+
}
|
|
373
|
+
if (req.method === "POST" && urlPath === "/api/agents") {
|
|
374
|
+
try {
|
|
375
|
+
const body = await parseJsonBody(req, z.object({
|
|
376
|
+
id: z.string().refine(isValidAgentId, { message: "Invalid agent ID" }),
|
|
377
|
+
directory: z.string().optional(),
|
|
378
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
379
|
+
commands: z.record(z.string(), z.string()).optional()
|
|
380
|
+
}));
|
|
381
|
+
if (await getAgent(body.id)) {
|
|
382
|
+
sendJsonResponse(res, 409, { error: "Agent already exists" });
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
const newAgent = {
|
|
386
|
+
directory: body.directory,
|
|
387
|
+
env: body.env || {},
|
|
388
|
+
commands: body.commands || {}
|
|
389
|
+
};
|
|
390
|
+
try {
|
|
391
|
+
await writeAgentSettings(body.id, newAgent);
|
|
392
|
+
} catch (err) {
|
|
393
|
+
sendJsonResponse(res, 400, { error: err instanceof Error ? err.message : "Invalid agent directory" });
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
sendJsonResponse(res, 201, {
|
|
397
|
+
id: body.id,
|
|
398
|
+
...newAgent
|
|
399
|
+
});
|
|
400
|
+
} catch {
|
|
401
|
+
sendJsonResponse(res, 500, { error: "Failed to create agent" });
|
|
402
|
+
}
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
const agentMatch = urlPath.match(/^\/api\/agents\/([^/]+)$/);
|
|
406
|
+
if (agentMatch && agentMatch[1]) {
|
|
407
|
+
const agentId = agentMatch[1];
|
|
408
|
+
if (!isValidAgentId(agentId)) {
|
|
409
|
+
sendJsonResponse(res, 400, { error: "Invalid agent ID" });
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
if (req.method === "GET") {
|
|
413
|
+
try {
|
|
414
|
+
const agent = await getAgent(agentId);
|
|
415
|
+
if (!agent) {
|
|
416
|
+
sendJsonResponse(res, 404, { error: "Agent not found" });
|
|
417
|
+
return true;
|
|
418
|
+
}
|
|
419
|
+
sendJsonResponse(res, 200, {
|
|
420
|
+
id: agentId,
|
|
421
|
+
...agent
|
|
422
|
+
});
|
|
423
|
+
} catch (err) {
|
|
424
|
+
sendJsonResponse(res, 500, { error: err instanceof Error ? err.message : String(err) });
|
|
425
|
+
}
|
|
426
|
+
return true;
|
|
427
|
+
}
|
|
428
|
+
if (req.method === "PUT" || req.method === "POST") {
|
|
429
|
+
try {
|
|
430
|
+
const body = await parseJsonBody(req, z.object({
|
|
431
|
+
directory: z.string().optional(),
|
|
432
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
433
|
+
commands: z.record(z.string(), z.string()).optional()
|
|
434
|
+
}));
|
|
435
|
+
const agent = await getAgent(agentId) || {};
|
|
436
|
+
if (body.directory !== void 0) agent.directory = body.directory;
|
|
437
|
+
if (body.env !== void 0) agent.env = body.env;
|
|
438
|
+
if (body.commands !== void 0) agent.commands = body.commands;
|
|
439
|
+
try {
|
|
440
|
+
await writeAgentSettings(agentId, agent);
|
|
441
|
+
} catch (err) {
|
|
442
|
+
sendJsonResponse(res, 400, { error: err instanceof Error ? err.message : "Invalid agent directory" });
|
|
443
|
+
return true;
|
|
444
|
+
}
|
|
445
|
+
sendJsonResponse(res, 200, {
|
|
446
|
+
id: agentId,
|
|
447
|
+
...agent
|
|
448
|
+
});
|
|
449
|
+
} catch {
|
|
450
|
+
sendJsonResponse(res, 500, { error: "Failed to update agent" });
|
|
451
|
+
}
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
if (req.method === "DELETE") {
|
|
455
|
+
await deleteAgent(agentId);
|
|
456
|
+
sendJsonResponse(res, 200, { success: true });
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
//#endregion
|
|
464
|
+
//#region src/cli/commands/web-api/chats.ts
|
|
465
|
+
async function handleApiChats(req, res, urlPath) {
|
|
466
|
+
if (req.method === "GET" && urlPath === "/api/chats") {
|
|
467
|
+
sendJsonResponse(res, 200, await listChats());
|
|
468
|
+
return true;
|
|
469
|
+
}
|
|
470
|
+
if (req.method === "POST" && urlPath === "/api/chats") {
|
|
471
|
+
try {
|
|
472
|
+
const body = await parseJsonBody(req, z.object({
|
|
473
|
+
id: z.string().refine(isValidChatId, { message: "Invalid chat ID. Must be alphanumeric with dashes or underscores." }),
|
|
474
|
+
agent: z.string().optional()
|
|
475
|
+
}));
|
|
476
|
+
await createChat(body.id);
|
|
477
|
+
if (body.agent) await writeChatSettings(body.id, { defaultAgent: body.agent });
|
|
478
|
+
sendJsonResponse(res, 201, {
|
|
479
|
+
id: body.id,
|
|
480
|
+
agent: body.agent
|
|
481
|
+
});
|
|
482
|
+
} catch {
|
|
483
|
+
sendJsonResponse(res, 500, { error: "Failed to create chat" });
|
|
484
|
+
}
|
|
485
|
+
return true;
|
|
486
|
+
}
|
|
487
|
+
const chatMatch = urlPath.match(/^\/api\/chats\/([^/]+)$/);
|
|
488
|
+
if (req.method === "GET" && chatMatch && chatMatch[1]) {
|
|
489
|
+
const chatId = chatMatch[1];
|
|
490
|
+
try {
|
|
491
|
+
const since = new URL(req.url || "", `http://${req.headers.host}`).searchParams.get("since");
|
|
492
|
+
let messages = await getMessages(chatId);
|
|
493
|
+
if (since) {
|
|
494
|
+
const sinceIndex = messages.findIndex((m) => m.id === since);
|
|
495
|
+
if (sinceIndex !== -1) messages = messages.slice(sinceIndex + 1);
|
|
496
|
+
}
|
|
497
|
+
sendJsonResponse(res, 200, messages);
|
|
498
|
+
} catch {
|
|
499
|
+
sendJsonResponse(res, 404, { error: "Chat not found" });
|
|
500
|
+
}
|
|
501
|
+
return true;
|
|
502
|
+
}
|
|
503
|
+
const streamMatch = urlPath.match(/^\/api\/chats\/([^/]+)\/stream$/);
|
|
504
|
+
if (req.method === "GET" && streamMatch && streamMatch[1]) {
|
|
505
|
+
const chatId = streamMatch[1];
|
|
506
|
+
res.setHeader("Content-Type", "text/event-stream");
|
|
507
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
508
|
+
res.setHeader("Connection", "keep-alive");
|
|
509
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
510
|
+
res.flushHeaders();
|
|
511
|
+
const chatsDir = await getChatsDir();
|
|
512
|
+
const chatFile = path.join(chatsDir, chatId, "chat.jsonl");
|
|
513
|
+
if (!fs.existsSync(chatFile)) await createChat(chatId);
|
|
514
|
+
let currentSize = fs.statSync(chatFile).size;
|
|
515
|
+
const watcher = fs.watch(chatFile, (eventType) => {
|
|
516
|
+
if (eventType === "change") try {
|
|
517
|
+
const stat = fs.statSync(chatFile);
|
|
518
|
+
if (stat.size > currentSize) {
|
|
519
|
+
const stream = fs.createReadStream(chatFile, {
|
|
520
|
+
start: currentSize,
|
|
521
|
+
end: stat.size - 1
|
|
522
|
+
});
|
|
523
|
+
currentSize = stat.size;
|
|
524
|
+
let buffer = "";
|
|
525
|
+
stream.on("data", (chunk) => {
|
|
526
|
+
buffer += chunk.toString();
|
|
527
|
+
const parts = buffer.split("\n");
|
|
528
|
+
buffer = parts.pop() || "";
|
|
529
|
+
for (const line of parts) if (line.trim()) res.write(`data: ${line}\n\n`);
|
|
530
|
+
});
|
|
531
|
+
stream.on("end", () => {
|
|
532
|
+
if (buffer.trim()) res.write(`data: ${buffer}\n\n`);
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
} catch {}
|
|
536
|
+
});
|
|
537
|
+
req.on("close", () => {
|
|
538
|
+
watcher.close();
|
|
539
|
+
});
|
|
540
|
+
res.write(": connected\n\n");
|
|
541
|
+
return true;
|
|
542
|
+
}
|
|
543
|
+
const messageMatch = urlPath.match(/^\/api\/chats\/([^/]+)\/messages$/);
|
|
544
|
+
if (req.method === "POST" && messageMatch && messageMatch[1]) {
|
|
545
|
+
const chatId = messageMatch[1];
|
|
546
|
+
const schema = z.object({ message: z.string().min(1, "Missing or invalid \"message\" field") });
|
|
547
|
+
let body;
|
|
548
|
+
try {
|
|
549
|
+
body = await parseJsonBody(req, schema);
|
|
550
|
+
} catch (err) {
|
|
551
|
+
sendJsonResponse(res, 400, { error: err instanceof Error ? err.message : "Invalid request" });
|
|
552
|
+
return true;
|
|
553
|
+
}
|
|
554
|
+
try {
|
|
555
|
+
await (await getDaemonClient()).sendMessage.mutate({
|
|
556
|
+
type: "send-message",
|
|
557
|
+
client: "cli",
|
|
558
|
+
data: {
|
|
559
|
+
message: body.message,
|
|
560
|
+
chatId,
|
|
561
|
+
noWait: true
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
sendJsonResponse(res, 200, { success: true });
|
|
565
|
+
} catch (err) {
|
|
566
|
+
sendJsonResponse(res, 500, { error: (err instanceof Error ? err.message : "Unknown error") || "Internal Server Error" });
|
|
567
|
+
}
|
|
568
|
+
return true;
|
|
569
|
+
}
|
|
570
|
+
const cronMatch = urlPath.match(/^\/api\/chats\/([^/]+)\/cron(?:\/([^/]+))?$/);
|
|
571
|
+
if (cronMatch && cronMatch[1]) {
|
|
572
|
+
const chatId = cronMatch[1];
|
|
573
|
+
const jobId = cronMatch[2];
|
|
574
|
+
if (req.method === "GET") {
|
|
575
|
+
try {
|
|
576
|
+
sendJsonResponse(res, 200, await (await getDaemonClient()).listCronJobs.query({ chatId }));
|
|
577
|
+
} catch {
|
|
578
|
+
sendJsonResponse(res, 500, { error: "Failed to list cron jobs" });
|
|
579
|
+
}
|
|
580
|
+
return true;
|
|
581
|
+
}
|
|
582
|
+
if (req.method === "POST") {
|
|
583
|
+
try {
|
|
584
|
+
const client = await getDaemonClient();
|
|
585
|
+
const body = await parseJsonBody(req);
|
|
586
|
+
await client.addCronJob.mutate({
|
|
587
|
+
chatId,
|
|
588
|
+
job: body
|
|
589
|
+
});
|
|
590
|
+
sendJsonResponse(res, 201, { success: true });
|
|
591
|
+
} catch (err) {
|
|
592
|
+
sendJsonResponse(res, 500, { error: (err instanceof Error ? err.message : "Unknown error") || "Failed to add cron job" });
|
|
593
|
+
}
|
|
594
|
+
return true;
|
|
595
|
+
}
|
|
596
|
+
if (req.method === "DELETE" && jobId) {
|
|
597
|
+
try {
|
|
598
|
+
await (await getDaemonClient()).deleteCronJob.mutate({
|
|
599
|
+
chatId,
|
|
600
|
+
id: jobId
|
|
601
|
+
});
|
|
602
|
+
sendJsonResponse(res, 200, { success: true });
|
|
603
|
+
} catch {
|
|
604
|
+
sendJsonResponse(res, 500, { error: "Failed to delete cron job" });
|
|
605
|
+
}
|
|
606
|
+
return true;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
return false;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
//#endregion
|
|
613
|
+
//#region src/cli/commands/web.ts
|
|
614
|
+
const mimeTypes = {
|
|
615
|
+
".html": "text/html",
|
|
616
|
+
".js": "text/javascript",
|
|
617
|
+
".mjs": "text/javascript",
|
|
618
|
+
".css": "text/css",
|
|
619
|
+
".json": "application/json",
|
|
620
|
+
".png": "image/png",
|
|
621
|
+
".jpg": "image/jpeg",
|
|
622
|
+
".gif": "image/gif",
|
|
623
|
+
".svg": "image/svg+xml",
|
|
624
|
+
".ico": "image/x-icon",
|
|
625
|
+
".woff": "font/woff",
|
|
626
|
+
".woff2": "font/woff2"
|
|
627
|
+
};
|
|
628
|
+
const webCmd = new Command("web").description("Start the local clawmini web interface").option("-p, --port <number>", "Port to bind the server to", "8080").option("-H, --host <string>", "Host to bind the server to", "127.0.0.1").action((options) => {
|
|
629
|
+
const port = parseInt(options.port, 10);
|
|
630
|
+
if (isNaN(port)) {
|
|
631
|
+
console.error("Invalid port number.");
|
|
632
|
+
process.exit(1);
|
|
633
|
+
}
|
|
634
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
635
|
+
const __dirname = path.dirname(__filename);
|
|
636
|
+
const webDir = path.resolve(__dirname, "../web");
|
|
637
|
+
http.createServer(async (req, res) => {
|
|
638
|
+
try {
|
|
639
|
+
const urlPath = req.url === "/" ? "/index.html" : req.url?.split("?")[0] || "/";
|
|
640
|
+
if (urlPath.startsWith("/api/")) {
|
|
641
|
+
res.setHeader("Content-Type", "application/json");
|
|
642
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
643
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
|
644
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
645
|
+
if (req.method === "OPTIONS") {
|
|
646
|
+
res.writeHead(204);
|
|
647
|
+
res.end();
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
if (urlPath.startsWith("/api/agents") && await handleApiAgents(req, res, urlPath)) return;
|
|
651
|
+
if (urlPath.startsWith("/api/chats") && await handleApiChats(req, res, urlPath)) return;
|
|
652
|
+
sendJsonResponse(res, 404, { error: "Not Found" });
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
let filePath = path.join(webDir, urlPath);
|
|
656
|
+
if (!pathIsInsideDir(filePath, webDir)) {
|
|
657
|
+
res.writeHead(403);
|
|
658
|
+
res.end("Forbidden");
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
if (!fs.existsSync(filePath) || fs.statSync(filePath).isDirectory()) {
|
|
662
|
+
filePath = path.join(webDir, "index.html");
|
|
663
|
+
if (!fs.existsSync(filePath)) {
|
|
664
|
+
res.writeHead(404);
|
|
665
|
+
res.end("Not Found");
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
const contentType = mimeTypes[path.extname(filePath).toLowerCase()] || "application/octet-stream";
|
|
670
|
+
res.writeHead(200, { "Content-Type": contentType });
|
|
671
|
+
fs.createReadStream(filePath).pipe(res);
|
|
672
|
+
} catch (err) {
|
|
673
|
+
console.error("Error serving request:", err);
|
|
674
|
+
res.writeHead(500);
|
|
675
|
+
res.end("Internal Server Error");
|
|
676
|
+
}
|
|
677
|
+
}).listen(port, options.host, () => {
|
|
678
|
+
console.log(`Clawmini web interface running at http://${options.host}:${port}/`);
|
|
679
|
+
});
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
//#endregion
|
|
683
|
+
//#region src/cli/commands/jobs.ts
|
|
684
|
+
const jobsCmd = new Command("jobs").description("Manage background jobs");
|
|
685
|
+
function parseKeyValueArray(arr) {
|
|
686
|
+
if (!arr || arr.length === 0) return void 0;
|
|
687
|
+
const result = {};
|
|
688
|
+
for (const item of arr) {
|
|
689
|
+
const [key, ...rest] = item.split("=");
|
|
690
|
+
if (key && rest.length >= 0) result[key] = rest.join("=");
|
|
691
|
+
}
|
|
692
|
+
return result;
|
|
693
|
+
}
|
|
694
|
+
function handleError(action, err) {
|
|
695
|
+
console.error(`Failed to ${action}:`, err instanceof Error ? err.message : String(err));
|
|
696
|
+
process.exit(1);
|
|
697
|
+
}
|
|
698
|
+
jobsCmd.command("list").description("Display existing jobs").option("-c, --chat <id>", "Specific chat to list jobs from").option("--json", "Output full JSON for each job").action(async (options) => {
|
|
699
|
+
try {
|
|
700
|
+
let jobs = await (await getDaemonClient()).listCronJobs.query({ chatId: options.chat });
|
|
701
|
+
jobs = jobs.sort((a, b) => {
|
|
702
|
+
return (a.createdAt ? new Date(a.createdAt).getTime() : 0) - (b.createdAt ? new Date(b.createdAt).getTime() : 0);
|
|
703
|
+
});
|
|
704
|
+
if (options.json) {
|
|
705
|
+
console.log(JSON.stringify(jobs, null, 2));
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
if (jobs.length === 0) {
|
|
709
|
+
console.log("No jobs found.");
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
for (const job of jobs) {
|
|
713
|
+
let schedule = "";
|
|
714
|
+
if ("cron" in job.schedule) schedule = `cron: ${job.schedule.cron}`;
|
|
715
|
+
else if ("every" in job.schedule) schedule = `every: ${job.schedule.every}`;
|
|
716
|
+
else if ("at" in job.schedule) schedule = `at: ${job.schedule.at}`;
|
|
717
|
+
console.log(`- ${job.id} (${schedule})`);
|
|
718
|
+
}
|
|
719
|
+
} catch (err) {
|
|
720
|
+
handleError("list jobs", err);
|
|
721
|
+
}
|
|
722
|
+
});
|
|
723
|
+
jobsCmd.command("add <name>").description("Create a new job").option("-m, --message <text>", "The message to send", "").option("-r, --reply <text>", "An immediate reply to append").option("--at <time-or-interval>", "Execute once at this UTC time or after an interval (e.g., 2m, 4h)").option("--every <duration>", "Execute repeatedly at this interval (e.g., 20m, 4h)").option("--cron <expression>", "Execute according to the crontab expression").option("-a, --agent <agentid>", "Agent to use").option("-e, --env <env...>", "Environment variables in KEY=VALUE format (can be specified multiple times)").option("-s, --session <type>", "Session type (e.g. new)").option("-c, --chat <chatid>", "Specify the chat").action(async (name, options) => {
|
|
724
|
+
try {
|
|
725
|
+
const schedules = [
|
|
726
|
+
options.at,
|
|
727
|
+
options.every,
|
|
728
|
+
options.cron
|
|
729
|
+
].filter(Boolean);
|
|
730
|
+
if (schedules.length > 1) throw new Error("More than one schedule flag was set. Please use only one of --at, --every, or --cron.");
|
|
731
|
+
if (schedules.length === 0) throw new Error("A schedule must be specified (--at, --every, or --cron).");
|
|
732
|
+
let schedule;
|
|
733
|
+
if (options.at) schedule = { at: options.at };
|
|
734
|
+
else if (options.every) schedule = { every: options.every };
|
|
735
|
+
else schedule = { cron: options.cron };
|
|
736
|
+
const job = {
|
|
737
|
+
id: name,
|
|
738
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
739
|
+
message: options.message,
|
|
740
|
+
schedule
|
|
741
|
+
};
|
|
742
|
+
if (options.reply) job.reply = options.reply;
|
|
743
|
+
if (options.agent) job.agentId = options.agent;
|
|
744
|
+
const env = parseKeyValueArray(options.env);
|
|
745
|
+
if (env) job.env = env;
|
|
746
|
+
if (options.session) {
|
|
747
|
+
if (options.session !== "new") throw new Error("Only the \"new\" session type is supported.");
|
|
748
|
+
job.session = { type: options.session };
|
|
749
|
+
}
|
|
750
|
+
await (await getDaemonClient()).addCronJob.mutate({
|
|
751
|
+
chatId: options.chat,
|
|
752
|
+
job
|
|
753
|
+
});
|
|
754
|
+
console.log(`Job '${name}' created successfully.`);
|
|
755
|
+
} catch (err) {
|
|
756
|
+
handleError("create job", err);
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
jobsCmd.command("delete <name>").description("Remove a job").option("-c, --chat <chatid>", "Specify the chat").action(async (name, options) => {
|
|
760
|
+
try {
|
|
761
|
+
if ((await (await getDaemonClient()).deleteCronJob.mutate({
|
|
762
|
+
chatId: options.chat,
|
|
763
|
+
id: name
|
|
764
|
+
})).deleted) console.log(`Job '${name}' deleted successfully.`);
|
|
765
|
+
else console.log(`Job '${name}' not found.`);
|
|
766
|
+
} catch (err) {
|
|
767
|
+
handleError("delete job", err);
|
|
768
|
+
}
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
//#endregion
|
|
772
|
+
//#region src/cli/commands/export-lite.ts
|
|
773
|
+
const exportLiteCmd = new Command("export-lite").description("Export the standalone clawmini-lite client script").option("-o, --out <path>", "Output path or directory for the script (defaults to current directory)").option("--stdout", "Output the script to stdout instead of a file").action(async (options) => {
|
|
774
|
+
let liteScriptContent = "";
|
|
775
|
+
try {
|
|
776
|
+
liteScriptContent = await getLiteScriptContent();
|
|
777
|
+
} catch (err) {
|
|
778
|
+
console.error(`Failed to read compiled clawmini-lite script. Ensure you have built the project (npm run build). Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
779
|
+
process.exit(1);
|
|
780
|
+
}
|
|
781
|
+
if (options.stdout) {
|
|
782
|
+
process.stdout.write(liteScriptContent);
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
let finalPath = path.resolve(process.cwd(), "clawmini-lite.js");
|
|
786
|
+
if (options.out) {
|
|
787
|
+
finalPath = path.resolve(process.cwd(), options.out);
|
|
788
|
+
try {
|
|
789
|
+
const writtenPath = await writeLiteScript(finalPath);
|
|
790
|
+
console.log(`Successfully exported clawmini-lite to ${writtenPath}`);
|
|
791
|
+
} catch (err) {
|
|
792
|
+
console.error(`Failed to export script: ${err instanceof Error ? err.message : String(err)}`);
|
|
793
|
+
process.exit(1);
|
|
794
|
+
}
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
if (!await exportLiteToAllEnvironments(process.cwd())) try {
|
|
798
|
+
const writtenPath = await writeLiteScript(finalPath);
|
|
799
|
+
console.log(`Successfully exported clawmini-lite to ${writtenPath}`);
|
|
800
|
+
} catch (err) {
|
|
801
|
+
console.error(`Failed to export script: ${err instanceof Error ? err.message : String(err)}`);
|
|
802
|
+
process.exit(1);
|
|
803
|
+
}
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
//#endregion
|
|
807
|
+
//#region src/cli/commands/environments.ts
|
|
808
|
+
const environmentsCmd = new Command("environments").description("Manage environments");
|
|
809
|
+
environmentsCmd.command("enable <name>").description("Enable an environment for a path in the workspace").option("-p, --path <subpath>", "Path to apply the environment to", "./").action(async (name, options) => {
|
|
810
|
+
try {
|
|
811
|
+
await enableEnvironment(name, options.path);
|
|
812
|
+
} catch (err) {
|
|
813
|
+
handleError$1("enable environment", err);
|
|
814
|
+
}
|
|
815
|
+
});
|
|
816
|
+
environmentsCmd.command("disable").description("Disable an environment mapping").option("-p, --path <subpath>", "Path to remove the environment from", "./").action(async (options) => {
|
|
817
|
+
try {
|
|
818
|
+
const settings = await readSettings();
|
|
819
|
+
if (!settings?.environments || !settings.environments[options.path]) {
|
|
820
|
+
console.log(`No environment mapping found for path '${options.path}'.`);
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
const name = settings.environments[options.path];
|
|
824
|
+
delete settings.environments[options.path];
|
|
825
|
+
await writeSettings(settings);
|
|
826
|
+
console.log(`Disabled environment '${name}' for path '${options.path}'.`);
|
|
827
|
+
} catch (err) {
|
|
828
|
+
handleError$1("disable environment", err);
|
|
829
|
+
}
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
//#endregion
|
|
833
|
+
//#region src/cli/index.ts
|
|
834
|
+
const program = new Command();
|
|
835
|
+
program.name("clawmini").description("Clawmini CLI").version("0.0.1");
|
|
836
|
+
program.addCommand(initCmd);
|
|
837
|
+
program.addCommand(messagesCmd);
|
|
838
|
+
program.addCommand(chatsCmd);
|
|
839
|
+
program.addCommand(agentsCmd);
|
|
840
|
+
program.addCommand(environmentsCmd);
|
|
841
|
+
program.addCommand(downCmd);
|
|
842
|
+
program.addCommand(upCmd);
|
|
843
|
+
program.addCommand(webCmd);
|
|
844
|
+
program.addCommand(jobsCmd);
|
|
845
|
+
program.addCommand(exportLiteCmd);
|
|
846
|
+
program.parse();
|
|
847
|
+
|
|
848
|
+
//#endregion
|
|
849
|
+
export { };
|
|
850
|
+
//# sourceMappingURL=index.mjs.map
|