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,147 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Client, Events, GatewayIntentBits, Partials } from 'discord.js';
|
|
4
|
+
import { readDiscordConfig, isAuthorized, initDiscordConfig } from './config.js';
|
|
5
|
+
import { getTRPCClient } from './client.js';
|
|
6
|
+
import { startDaemonToDiscordForwarder } from './forwarder.js';
|
|
7
|
+
import fs from 'node:fs/promises';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
|
|
10
|
+
export async function main() {
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
|
|
13
|
+
if (args[0] === 'init') {
|
|
14
|
+
await initDiscordConfig();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
console.log('Discord Adapter starting...');
|
|
19
|
+
|
|
20
|
+
const config = await readDiscordConfig();
|
|
21
|
+
if (!config) {
|
|
22
|
+
console.error(
|
|
23
|
+
'Failed to load Discord configuration. Please ensure .clawmini/adapters/discord/config.json exists and is valid.'
|
|
24
|
+
);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const trpc = getTRPCClient();
|
|
29
|
+
|
|
30
|
+
const client = new Client({
|
|
31
|
+
intents: [GatewayIntentBits.DirectMessages, GatewayIntentBits.MessageContent],
|
|
32
|
+
partials: [Partials.Channel],
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
client.once(Events.ClientReady, (readyClient) => {
|
|
36
|
+
console.log(`Ready! Logged in as ${readyClient.user.tag}`);
|
|
37
|
+
|
|
38
|
+
// Start forwarding from daemon to Discord
|
|
39
|
+
startDaemonToDiscordForwarder(readyClient, trpc, config.authorizedUserId, config.chatId).catch(
|
|
40
|
+
(error) => {
|
|
41
|
+
console.error('Error in daemon-to-discord forwarder:', error);
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
client.on(Events.MessageCreate, async (message) => {
|
|
47
|
+
// Ignore messages from the bot itself
|
|
48
|
+
if (message.author.id === client.user?.id) return;
|
|
49
|
+
|
|
50
|
+
// Only handle DM messages
|
|
51
|
+
if (message.guild) return;
|
|
52
|
+
|
|
53
|
+
// Check if the user is authorized
|
|
54
|
+
if (!isAuthorized(message.author.id, config.authorizedUserId)) {
|
|
55
|
+
console.log(
|
|
56
|
+
`Unauthorized message from ${message.author.tag} (${message.author.id}) ignored.`
|
|
57
|
+
);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log(`Received message from ${message.author.tag}: ${message.content}`);
|
|
62
|
+
|
|
63
|
+
const downloadedFiles: string[] = [];
|
|
64
|
+
if (message.attachments.size > 0) {
|
|
65
|
+
const { getClawminiDir } = await import('../shared/workspace.js');
|
|
66
|
+
const tmpDir = path.join(getClawminiDir(process.cwd()), 'tmp', 'discord');
|
|
67
|
+
await fs.mkdir(tmpDir, { recursive: true });
|
|
68
|
+
const maxSizeMB = config.maxAttachmentSizeMB ?? 25;
|
|
69
|
+
const maxSizeBytes = maxSizeMB * 1024 * 1024;
|
|
70
|
+
|
|
71
|
+
for (const attachment of message.attachments.values()) {
|
|
72
|
+
if (attachment.size > maxSizeBytes) {
|
|
73
|
+
console.warn(
|
|
74
|
+
`Attachment ${attachment.name} exceeds size limit (${maxSizeMB}MB). Ignoring.`
|
|
75
|
+
);
|
|
76
|
+
await message.reply(
|
|
77
|
+
`Warning: Attachment ${attachment.name} exceeds the size limit of ${maxSizeMB}MB and was ignored.`
|
|
78
|
+
);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
const res = await fetch(attachment.url);
|
|
84
|
+
if (!res.ok) {
|
|
85
|
+
console.error(`Failed to download attachment ${attachment.name}`);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const uniqueName = `${Date.now()}-${attachment.name}`;
|
|
90
|
+
const filePath = path.join(tmpDir, uniqueName);
|
|
91
|
+
const arrayBuffer = await res.arrayBuffer();
|
|
92
|
+
await fs.writeFile(filePath, Buffer.from(arrayBuffer));
|
|
93
|
+
downloadedFiles.push(filePath);
|
|
94
|
+
} catch (err) {
|
|
95
|
+
console.error(`Error downloading attachment ${attachment.name}:`, err);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let finalContent = message.content;
|
|
101
|
+
|
|
102
|
+
if (message.reference && message.reference.messageId) {
|
|
103
|
+
try {
|
|
104
|
+
const referencedMessage = await message.fetchReference();
|
|
105
|
+
if (referencedMessage && referencedMessage.content) {
|
|
106
|
+
const quotedContent = referencedMessage.content
|
|
107
|
+
.split('\n')
|
|
108
|
+
.map((line) => `> ${line}`)
|
|
109
|
+
.join('\n');
|
|
110
|
+
finalContent = `${quotedContent}\n${finalContent}`;
|
|
111
|
+
}
|
|
112
|
+
} catch (err) {
|
|
113
|
+
console.error('Failed to fetch referenced message:', err);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
console.log(`Forwarding message to daemon: ${finalContent}`);
|
|
118
|
+
try {
|
|
119
|
+
await trpc.sendMessage.mutate({
|
|
120
|
+
type: 'send-message',
|
|
121
|
+
client: 'cli',
|
|
122
|
+
data: {
|
|
123
|
+
message: finalContent,
|
|
124
|
+
chatId: config.chatId,
|
|
125
|
+
files: downloadedFiles.length > 0 ? downloadedFiles : undefined,
|
|
126
|
+
adapter: 'discord',
|
|
127
|
+
noWait: true,
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
console.log('Message forwarded to daemon successfully.');
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.error('Failed to forward message to daemon:', error);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
await client.login(config.botToken);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error('Failed to login to Discord:', error);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
main().catch((error) => {
|
|
145
|
+
console.error('Unhandled error in Discord Adapter:', error);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import fsPromises from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { readDiscordState, writeDiscordState, getDiscordStatePath } from './state.js';
|
|
5
|
+
|
|
6
|
+
vi.mock('node:fs/promises');
|
|
7
|
+
vi.mock('../shared/workspace.js', () => ({
|
|
8
|
+
getClawminiDir: vi.fn(() => '/mock/clawmini'),
|
|
9
|
+
getWorkspaceRoot: vi.fn(() => '/mock/workspace'),
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
describe('Discord State Management', () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
vi.clearAllMocks();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should return default state if file does not exist', async () => {
|
|
18
|
+
vi.mocked(fsPromises.readFile).mockRejectedValue(new Error('File not found'));
|
|
19
|
+
|
|
20
|
+
const state = await readDiscordState();
|
|
21
|
+
expect(state).toEqual({ lastSyncedMessageId: undefined });
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should read state from file', async () => {
|
|
25
|
+
const mockState = { lastSyncedMessageId: '12345' };
|
|
26
|
+
vi.mocked(fsPromises.readFile).mockResolvedValue(JSON.stringify(mockState));
|
|
27
|
+
|
|
28
|
+
const state = await readDiscordState();
|
|
29
|
+
expect(state).toEqual(mockState);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should return default state if file contains invalid JSON', async () => {
|
|
33
|
+
vi.mocked(fsPromises.readFile).mockResolvedValue('invalid-json');
|
|
34
|
+
|
|
35
|
+
const state = await readDiscordState();
|
|
36
|
+
expect(state).toEqual({ lastSyncedMessageId: undefined });
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should write state to file', async () => {
|
|
40
|
+
const mockState = { lastSyncedMessageId: '67890' };
|
|
41
|
+
const statePath = getDiscordStatePath();
|
|
42
|
+
|
|
43
|
+
await writeDiscordState(mockState);
|
|
44
|
+
|
|
45
|
+
expect(fsPromises.mkdir).toHaveBeenCalledWith(path.dirname(statePath), { recursive: true });
|
|
46
|
+
expect(fsPromises.writeFile).toHaveBeenCalledWith(
|
|
47
|
+
statePath,
|
|
48
|
+
JSON.stringify(mockState, null, 2),
|
|
49
|
+
'utf-8'
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should handle errors when writing state', async () => {
|
|
54
|
+
vi.mocked(fsPromises.writeFile).mockRejectedValue(new Error('Permission denied'));
|
|
55
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
56
|
+
|
|
57
|
+
await writeDiscordState({ lastSyncedMessageId: '123' });
|
|
58
|
+
|
|
59
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
60
|
+
expect.stringContaining('Failed to write Discord state'),
|
|
61
|
+
expect.any(Error)
|
|
62
|
+
);
|
|
63
|
+
consoleSpy.mockRestore();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import fsPromises from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { getClawminiDir } from '../shared/workspace.js';
|
|
5
|
+
|
|
6
|
+
export const DiscordStateSchema = z.object({
|
|
7
|
+
lastSyncedMessageId: z.string().optional(),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export type DiscordState = z.infer<typeof DiscordStateSchema>;
|
|
11
|
+
|
|
12
|
+
export function getDiscordStatePath(startDir = process.cwd()): string {
|
|
13
|
+
return path.join(getClawminiDir(startDir), 'adapters', 'discord', 'state.json');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function readDiscordState(startDir = process.cwd()): Promise<DiscordState> {
|
|
17
|
+
const statePath = getDiscordStatePath(startDir);
|
|
18
|
+
try {
|
|
19
|
+
const data = await fsPromises.readFile(statePath, 'utf-8');
|
|
20
|
+
const parsed = JSON.parse(data);
|
|
21
|
+
const result = DiscordStateSchema.safeParse(parsed);
|
|
22
|
+
if (!result.success) {
|
|
23
|
+
return { lastSyncedMessageId: undefined };
|
|
24
|
+
}
|
|
25
|
+
return result.data;
|
|
26
|
+
} catch {
|
|
27
|
+
// Return default state if file doesn't exist or is invalid JSON
|
|
28
|
+
return { lastSyncedMessageId: undefined };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function writeDiscordState(
|
|
33
|
+
state: DiscordState,
|
|
34
|
+
startDir = process.cwd()
|
|
35
|
+
): Promise<void> {
|
|
36
|
+
const statePath = getDiscordStatePath(startDir);
|
|
37
|
+
const dir = path.dirname(statePath);
|
|
38
|
+
try {
|
|
39
|
+
await fsPromises.mkdir(dir, { recursive: true });
|
|
40
|
+
await fsPromises.writeFile(statePath, JSON.stringify(state, null, 2), 'utf-8');
|
|
41
|
+
} catch (err) {
|
|
42
|
+
console.error(`Failed to write Discord state to ${statePath}:`, err);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createTRPCClient, httpLink } from '@trpc/client';
|
|
2
|
+
import type { AppRouter } from '../daemon/router.js';
|
|
3
|
+
import { getSocketPath, getClawminiDir } from '../shared/workspace.js';
|
|
4
|
+
import { createUnixSocketFetch } from '../shared/fetch.js';
|
|
5
|
+
import { spawn } from 'node:child_process';
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
|
|
9
|
+
export async function getDaemonClient(options: { autoStart?: boolean } = {}) {
|
|
10
|
+
const { autoStart = true } = options;
|
|
11
|
+
const socketPath = getSocketPath();
|
|
12
|
+
|
|
13
|
+
// Check if server is running by verifying socket exists
|
|
14
|
+
// (A better check would be to ping it, but this is a start)
|
|
15
|
+
if (!fs.existsSync(socketPath)) {
|
|
16
|
+
if (!autoStart) {
|
|
17
|
+
throw new Error('Daemon not running.');
|
|
18
|
+
}
|
|
19
|
+
console.log('Daemon not running. Starting daemon...');
|
|
20
|
+
|
|
21
|
+
// Start daemon in the background
|
|
22
|
+
const daemonPath = new URL('../daemon/index.mjs', import.meta.url).pathname;
|
|
23
|
+
const logFile = fs.openSync(path.join(getClawminiDir(), 'daemon.log'), 'a');
|
|
24
|
+
const child = spawn(process.execPath, [daemonPath], {
|
|
25
|
+
detached: true,
|
|
26
|
+
stdio: ['ignore', logFile, logFile],
|
|
27
|
+
});
|
|
28
|
+
child.unref();
|
|
29
|
+
|
|
30
|
+
// Wait a moment for the daemon to start and create the socket
|
|
31
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
32
|
+
|
|
33
|
+
if (!fs.existsSync(socketPath)) {
|
|
34
|
+
throw new Error('Failed to start daemon.');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return createTRPCClient<AppRouter>({
|
|
39
|
+
links: [
|
|
40
|
+
httpLink({
|
|
41
|
+
url: 'http://localhost',
|
|
42
|
+
fetch: createUnixSocketFetch(socketPath),
|
|
43
|
+
}),
|
|
44
|
+
],
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import {
|
|
3
|
+
listAgents,
|
|
4
|
+
getAgent,
|
|
5
|
+
writeAgentSettings,
|
|
6
|
+
deleteAgent,
|
|
7
|
+
isValidAgentId,
|
|
8
|
+
} from '../../shared/workspace.js';
|
|
9
|
+
import { type Agent } from '../../shared/config.js';
|
|
10
|
+
import { createAgentWithChat } from '../../shared/agent-utils.js';
|
|
11
|
+
import { handleError } from '../utils.js';
|
|
12
|
+
|
|
13
|
+
export const agentsCmd = new Command('agents').description('Manage agents');
|
|
14
|
+
|
|
15
|
+
function parseEnv(envArray: string[] | undefined): Record<string, string> | undefined {
|
|
16
|
+
if (!envArray || envArray.length === 0) return undefined;
|
|
17
|
+
const env: Record<string, string> = {};
|
|
18
|
+
for (const e of envArray) {
|
|
19
|
+
const [key, ...rest] = e.split('=');
|
|
20
|
+
if (key && rest.length >= 0) {
|
|
21
|
+
env[key] = rest.join('=');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return env;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function assertValidAgentId(id: string): void {
|
|
28
|
+
if (!isValidAgentId(id)) {
|
|
29
|
+
throw new Error(`Invalid agent ID: ${id}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
agentsCmd
|
|
34
|
+
.command('list')
|
|
35
|
+
.description('Display existing agents')
|
|
36
|
+
.action(async () => {
|
|
37
|
+
try {
|
|
38
|
+
const agents = await listAgents();
|
|
39
|
+
if (agents.length === 0) {
|
|
40
|
+
console.log('No agents found.');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
for (const id of agents) {
|
|
44
|
+
console.log(`- ${id}`);
|
|
45
|
+
}
|
|
46
|
+
} catch (err) {
|
|
47
|
+
handleError('list agents', err);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
agentsCmd
|
|
52
|
+
.command('add <id>')
|
|
53
|
+
.description('Create a new agent')
|
|
54
|
+
.option('-d, --directory <dir>', 'Working directory for the agent')
|
|
55
|
+
.option('-t, --template <name>', 'Template to use for the agent')
|
|
56
|
+
.option(
|
|
57
|
+
'-e, --env <env...>',
|
|
58
|
+
'Environment variables in KEY=VALUE format (can be specified multiple times)'
|
|
59
|
+
)
|
|
60
|
+
.action(
|
|
61
|
+
async (id: string, options: { directory?: string; template?: string; env?: string[] }) => {
|
|
62
|
+
try {
|
|
63
|
+
assertValidAgentId(id);
|
|
64
|
+
const existing = await getAgent(id);
|
|
65
|
+
if (existing) {
|
|
66
|
+
throw new Error(`Agent ${id} already exists.`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const agentData: Agent = {};
|
|
70
|
+
|
|
71
|
+
if (options.directory) {
|
|
72
|
+
agentData.directory = options.directory;
|
|
73
|
+
}
|
|
74
|
+
const env = parseEnv(options.env);
|
|
75
|
+
if (env) {
|
|
76
|
+
agentData.env = { ...(agentData.env || {}), ...env };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
await createAgentWithChat(id, agentData, options.template);
|
|
80
|
+
|
|
81
|
+
console.log(`Agent ${id} created successfully.`);
|
|
82
|
+
} catch (err) {
|
|
83
|
+
handleError('create agent', err);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
agentsCmd
|
|
89
|
+
.command('update <id>')
|
|
90
|
+
.description('Update an existing agent')
|
|
91
|
+
.option('-d, --directory <dir>', 'Working directory for the agent')
|
|
92
|
+
.option(
|
|
93
|
+
'-e, --env <env...>',
|
|
94
|
+
'Environment variables in KEY=VALUE format (can be specified multiple times)'
|
|
95
|
+
)
|
|
96
|
+
.action(async (id: string, options: { directory?: string; env?: string[] }) => {
|
|
97
|
+
try {
|
|
98
|
+
assertValidAgentId(id);
|
|
99
|
+
const existing = await getAgent(id);
|
|
100
|
+
if (!existing) {
|
|
101
|
+
throw new Error(`Agent ${id} does not exist.`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const agentData: Agent = { ...existing };
|
|
105
|
+
|
|
106
|
+
if (options.directory !== undefined) {
|
|
107
|
+
agentData.directory = options.directory;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const env = parseEnv(options.env);
|
|
111
|
+
if (env) {
|
|
112
|
+
agentData.env = { ...(agentData.env || {}), ...env };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
await writeAgentSettings(id, agentData);
|
|
116
|
+
console.log(`Agent ${id} updated successfully.`);
|
|
117
|
+
} catch (err) {
|
|
118
|
+
handleError('update agent', err);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
agentsCmd
|
|
123
|
+
.command('delete <id>')
|
|
124
|
+
.description('Remove an agent')
|
|
125
|
+
.action(async (id: string) => {
|
|
126
|
+
try {
|
|
127
|
+
assertValidAgentId(id);
|
|
128
|
+
const existing = await getAgent(id);
|
|
129
|
+
if (!existing) {
|
|
130
|
+
throw new Error(`Agent ${id} does not exist.`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
await deleteAgent(id);
|
|
134
|
+
console.log(`Agent ${id} deleted successfully.`);
|
|
135
|
+
} catch (err) {
|
|
136
|
+
handleError('delete agent', err);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import {
|
|
3
|
+
listChats,
|
|
4
|
+
createChat,
|
|
5
|
+
deleteChat,
|
|
6
|
+
setDefaultChatId,
|
|
7
|
+
getDefaultChatId,
|
|
8
|
+
DEFAULT_CHAT_ID,
|
|
9
|
+
} from '../../shared/chats.js';
|
|
10
|
+
|
|
11
|
+
export const chatsCmd = new Command('chats').description('Manage chat sessions');
|
|
12
|
+
|
|
13
|
+
chatsCmd
|
|
14
|
+
.command('list')
|
|
15
|
+
.description('Display existing chats')
|
|
16
|
+
.action(async () => {
|
|
17
|
+
try {
|
|
18
|
+
const chats = await listChats();
|
|
19
|
+
const defaultId = await getDefaultChatId();
|
|
20
|
+
if (chats.length === 0) {
|
|
21
|
+
console.log('No chats found.');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
for (const id of chats) {
|
|
25
|
+
const marker = id === defaultId ? ' *' : '';
|
|
26
|
+
console.log(`- ${id}${marker}`);
|
|
27
|
+
}
|
|
28
|
+
} catch (err) {
|
|
29
|
+
console.error('Failed to list chats:', err instanceof Error ? err.message : String(err));
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
chatsCmd
|
|
35
|
+
.command('add <id>')
|
|
36
|
+
.description('Initialize a new chat')
|
|
37
|
+
.action(async (id: string) => {
|
|
38
|
+
try {
|
|
39
|
+
await createChat(id);
|
|
40
|
+
console.log(`Chat ${id} created successfully.`);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
console.error('Failed to create chat:', err instanceof Error ? err.message : String(err));
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
chatsCmd
|
|
48
|
+
.command('delete <id>')
|
|
49
|
+
.description('Remove a chat')
|
|
50
|
+
.action(async (id: string) => {
|
|
51
|
+
try {
|
|
52
|
+
const defaultId = await getDefaultChatId();
|
|
53
|
+
await deleteChat(id);
|
|
54
|
+
console.log(`Chat ${id} deleted successfully.`);
|
|
55
|
+
if (id === defaultId) {
|
|
56
|
+
await setDefaultChatId(DEFAULT_CHAT_ID);
|
|
57
|
+
console.log(`Default chat reset to default.`);
|
|
58
|
+
}
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error('Failed to delete chat:', err instanceof Error ? err.message : String(err));
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
chatsCmd
|
|
66
|
+
.command('set-default <id>')
|
|
67
|
+
.description('Update the workspace default chat')
|
|
68
|
+
.action(async (id: string) => {
|
|
69
|
+
try {
|
|
70
|
+
await setDefaultChatId(id);
|
|
71
|
+
console.log(`Default chat set to ${id}.`);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
console.error(
|
|
74
|
+
'Failed to set default chat:',
|
|
75
|
+
err instanceof Error ? err.message : String(err)
|
|
76
|
+
);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { getDaemonClient } from '../client.js';
|
|
3
|
+
import { getSocketPath } from '../../shared/workspace.js';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
|
|
6
|
+
export const downCmd = new Command('down')
|
|
7
|
+
.description('Stop the local clawmini daemon server')
|
|
8
|
+
.action(async () => {
|
|
9
|
+
try {
|
|
10
|
+
const client = await getDaemonClient({ autoStart: false });
|
|
11
|
+
process.stdout.write('Shutting down clawmini daemon...');
|
|
12
|
+
await client.shutdown.mutate();
|
|
13
|
+
|
|
14
|
+
const socketPath = getSocketPath();
|
|
15
|
+
// Wait for the socket file to be removed by the daemon's exit handler
|
|
16
|
+
while (fs.existsSync(socketPath)) {
|
|
17
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
18
|
+
process.stdout.write('.');
|
|
19
|
+
}
|
|
20
|
+
console.log('\nSuccessfully shut down clawmini daemon.');
|
|
21
|
+
} catch (err: unknown) {
|
|
22
|
+
if (err instanceof Error && err.message === 'Daemon not running.') {
|
|
23
|
+
console.log('Daemon is not running.');
|
|
24
|
+
} else {
|
|
25
|
+
console.error(
|
|
26
|
+
'\nFailed to shut down daemon:',
|
|
27
|
+
err instanceof Error ? err.message : String(err)
|
|
28
|
+
);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { readSettings, writeSettings, enableEnvironment } from '../../shared/workspace.js';
|
|
3
|
+
import { handleError } from '../utils.js';
|
|
4
|
+
|
|
5
|
+
export const environmentsCmd = new Command('environments').description('Manage environments');
|
|
6
|
+
|
|
7
|
+
environmentsCmd
|
|
8
|
+
.command('enable <name>')
|
|
9
|
+
.description('Enable an environment for a path in the workspace')
|
|
10
|
+
.option('-p, --path <subpath>', 'Path to apply the environment to', './')
|
|
11
|
+
.action(async (name: string, options: { path: string }) => {
|
|
12
|
+
try {
|
|
13
|
+
await enableEnvironment(name, options.path);
|
|
14
|
+
} catch (err) {
|
|
15
|
+
handleError('enable environment', err);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
environmentsCmd
|
|
20
|
+
.command('disable')
|
|
21
|
+
.description('Disable an environment mapping')
|
|
22
|
+
.option('-p, --path <subpath>', 'Path to remove the environment from', './')
|
|
23
|
+
.action(async (options: { path: string }) => {
|
|
24
|
+
try {
|
|
25
|
+
const settings = await readSettings();
|
|
26
|
+
if (!settings?.environments || !settings.environments[options.path]) {
|
|
27
|
+
console.log(`No environment mapping found for path '${options.path}'.`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const name = settings.environments[options.path];
|
|
32
|
+
delete settings.environments[options.path];
|
|
33
|
+
await writeSettings(settings);
|
|
34
|
+
|
|
35
|
+
console.log(`Disabled environment '${name}' for path '${options.path}'.`);
|
|
36
|
+
} catch (err) {
|
|
37
|
+
handleError('disable environment', err);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import {
|
|
4
|
+
getLiteScriptContent,
|
|
5
|
+
writeLiteScript,
|
|
6
|
+
exportLiteToAllEnvironments,
|
|
7
|
+
} from '../../shared/lite.js';
|
|
8
|
+
|
|
9
|
+
export const exportLiteCmd = new Command('export-lite')
|
|
10
|
+
.description('Export the standalone clawmini-lite client script')
|
|
11
|
+
.option(
|
|
12
|
+
'-o, --out <path>',
|
|
13
|
+
'Output path or directory for the script (defaults to current directory)'
|
|
14
|
+
)
|
|
15
|
+
.option('--stdout', 'Output the script to stdout instead of a file')
|
|
16
|
+
.action(async (options: { out?: string; stdout?: boolean }) => {
|
|
17
|
+
let liteScriptContent = '';
|
|
18
|
+
try {
|
|
19
|
+
liteScriptContent = await getLiteScriptContent();
|
|
20
|
+
} catch (err) {
|
|
21
|
+
console.error(
|
|
22
|
+
`Failed to read compiled clawmini-lite script. Ensure you have built the project (npm run build). Error: ${err instanceof Error ? err.message : String(err)}`
|
|
23
|
+
);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (options.stdout) {
|
|
28
|
+
process.stdout.write(liteScriptContent);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const defaultFilename = 'clawmini-lite.js';
|
|
33
|
+
let finalPath = path.resolve(process.cwd(), defaultFilename);
|
|
34
|
+
|
|
35
|
+
if (options.out) {
|
|
36
|
+
finalPath = path.resolve(process.cwd(), options.out);
|
|
37
|
+
try {
|
|
38
|
+
const writtenPath = await writeLiteScript(finalPath);
|
|
39
|
+
console.log(`Successfully exported clawmini-lite to ${writtenPath}`);
|
|
40
|
+
} catch (err) {
|
|
41
|
+
console.error(
|
|
42
|
+
`Failed to export script: ${err instanceof Error ? err.message : String(err)}`
|
|
43
|
+
);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const exportedToEnvironments = await exportLiteToAllEnvironments(process.cwd());
|
|
50
|
+
|
|
51
|
+
if (!exportedToEnvironments) {
|
|
52
|
+
try {
|
|
53
|
+
const writtenPath = await writeLiteScript(finalPath);
|
|
54
|
+
console.log(`Successfully exported clawmini-lite to ${writtenPath}`);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
console.error(
|
|
57
|
+
`Failed to export script: ${err instanceof Error ? err.message : String(err)}`
|
|
58
|
+
);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|