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.
Files changed (469) hide show
  1. package/.gemini/settings.json +46 -0
  2. package/.prettierrc +7 -0
  3. package/GEMINI.md +11 -0
  4. package/README.md +137 -0
  5. package/dist/adapter-discord/index.d.mts +5 -0
  6. package/dist/adapter-discord/index.d.mts.map +1 -0
  7. package/dist/adapter-discord/index.mjs +456 -0
  8. package/dist/adapter-discord/index.mjs.map +1 -0
  9. package/dist/chats-DKgTeU7i.mjs +91 -0
  10. package/dist/chats-DKgTeU7i.mjs.map +1 -0
  11. package/dist/chats-Zd_HXDHx.mjs +29 -0
  12. package/dist/chats-Zd_HXDHx.mjs.map +1 -0
  13. package/dist/cli/index.d.mts +1 -0
  14. package/dist/cli/index.mjs +850 -0
  15. package/dist/cli/index.mjs.map +1 -0
  16. package/dist/cli/lite.d.mts +1 -0
  17. package/dist/cli/lite.mjs +4434 -0
  18. package/dist/cli/lite.mjs.map +1 -0
  19. package/dist/daemon/index.d.mts +5 -0
  20. package/dist/daemon/index.d.mts.map +1 -0
  21. package/dist/daemon/index.mjs +1222 -0
  22. package/dist/daemon/index.mjs.map +1 -0
  23. package/dist/fetch-BjZVyU3Z.mjs +37 -0
  24. package/dist/fetch-BjZVyU3Z.mjs.map +1 -0
  25. package/dist/fs-B5wW0oaH.mjs +14 -0
  26. package/dist/fs-B5wW0oaH.mjs.map +1 -0
  27. package/dist/lite-Dl7WXyaH.mjs +80 -0
  28. package/dist/lite-Dl7WXyaH.mjs.map +1 -0
  29. package/dist/rolldown-runtime-95iHPtFO.mjs +18 -0
  30. package/dist/web/_app/env.js +1 -0
  31. package/dist/web/_app/immutable/assets/0.GI4C4dpV.css +1 -0
  32. package/dist/web/_app/immutable/chunks/B5abRDXp.js +1 -0
  33. package/dist/web/_app/immutable/chunks/B8yYFADm.js +1 -0
  34. package/dist/web/_app/immutable/chunks/BPy8HLo7.js +5 -0
  35. package/dist/web/_app/immutable/chunks/Bi0jeV7Q.js +1 -0
  36. package/dist/web/_app/immutable/chunks/BmUXQ3wy.js +2 -0
  37. package/dist/web/_app/immutable/chunks/C3k55nDF.js +1 -0
  38. package/dist/web/_app/immutable/chunks/COekwvP2.js +1 -0
  39. package/dist/web/_app/immutable/chunks/CSvS_NwK.js +1 -0
  40. package/dist/web/_app/immutable/chunks/CpaGRn9L.js +1 -0
  41. package/dist/web/_app/immutable/chunks/CyNaE55B.js +1 -0
  42. package/dist/web/_app/immutable/chunks/DG5RZBw-.js +2 -0
  43. package/dist/web/_app/immutable/chunks/Dc-UOHw9.js +1 -0
  44. package/dist/web/_app/immutable/chunks/DcrmIfTj.js +1 -0
  45. package/dist/web/_app/immutable/chunks/ZkLyk0mE.js +1 -0
  46. package/dist/web/_app/immutable/entry/app.B-vZe7PN.js +2 -0
  47. package/dist/web/_app/immutable/entry/start.oP1AgKhs.js +1 -0
  48. package/dist/web/_app/immutable/nodes/0.B5WFN0zw.js +1 -0
  49. package/dist/web/_app/immutable/nodes/1.D1wtJb2k.js +1 -0
  50. package/dist/web/_app/immutable/nodes/2.CK3CLC0f.js +1 -0
  51. package/dist/web/_app/immutable/nodes/3.BB5wCoBf.js +4 -0
  52. package/dist/web/_app/immutable/nodes/4.Dr2jvAXK.js +1 -0
  53. package/dist/web/_app/immutable/nodes/5.BJl7oM3b.js +1 -0
  54. package/dist/web/_app/version.json +1 -0
  55. package/dist/web/index.html +37 -0
  56. package/dist/web/robots.txt +3 -0
  57. package/dist/workspace-CSgfo_2J.mjs +383 -0
  58. package/dist/workspace-CSgfo_2J.mjs.map +1 -0
  59. package/docs/01_chats/development_log.md +36 -0
  60. package/docs/01_chats/notes.md +27 -0
  61. package/docs/01_chats/prd.md +47 -0
  62. package/docs/01_chats/questions.md +19 -0
  63. package/docs/01_chats/tickets.md +67 -0
  64. package/docs/02_sessions/development_log.md +79 -0
  65. package/docs/02_sessions/notes.md +40 -0
  66. package/docs/02_sessions/prd.md +75 -0
  67. package/docs/02_sessions/questions.md +7 -0
  68. package/docs/02_sessions/tickets.md +68 -0
  69. package/docs/03_web_interface/development_log.md +60 -0
  70. package/docs/03_web_interface/notes.md +29 -0
  71. package/docs/03_web_interface/prd.md +42 -0
  72. package/docs/03_web_interface/questions.md +8 -0
  73. package/docs/03_web_interface/tickets.md +59 -0
  74. package/docs/04_agents/development_log.md +54 -0
  75. package/docs/04_agents/notes.md +45 -0
  76. package/docs/04_agents/prd.md +47 -0
  77. package/docs/04_agents/questions.md +13 -0
  78. package/docs/04_agents/tickets.md +107 -0
  79. package/docs/05_routers/development_log.md +13 -0
  80. package/docs/05_routers/notes.md +40 -0
  81. package/docs/05_routers/prd.md +55 -0
  82. package/docs/05_routers/questions.md +21 -0
  83. package/docs/05_routers/tickets.md +109 -0
  84. package/docs/06_agent_templates/development_log.md +38 -0
  85. package/docs/06_agent_templates/notes.md +25 -0
  86. package/docs/06_agent_templates/prd.md +34 -0
  87. package/docs/06_agent_templates/questions.md +11 -0
  88. package/docs/06_agent_templates/tickets.md +49 -0
  89. package/docs/06_cron/development_log.md +51 -0
  90. package/docs/06_cron/notes.md +14 -0
  91. package/docs/06_cron/prd.md +92 -0
  92. package/docs/06_cron/questions.md +15 -0
  93. package/docs/06_cron/tickets.md +75 -0
  94. package/docs/07_web_chat_ux/development_log.md +30 -0
  95. package/docs/07_web_chat_ux/notes.md +25 -0
  96. package/docs/07_web_chat_ux/prd.md +46 -0
  97. package/docs/07_web_chat_ux/questions.md +7 -0
  98. package/docs/07_web_chat_ux/tickets.md +48 -0
  99. package/docs/08_agent_api/development_log.md +52 -0
  100. package/docs/08_agent_api/notes.md +31 -0
  101. package/docs/08_agent_api/prd.md +56 -0
  102. package/docs/08_agent_api/questions.md +14 -0
  103. package/docs/08_agent_api/tickets.md +104 -0
  104. package/docs/09_agent_fallbacks/development_log.md +52 -0
  105. package/docs/09_agent_fallbacks/notes.md +40 -0
  106. package/docs/09_agent_fallbacks/prd.md +55 -0
  107. package/docs/09_agent_fallbacks/questions.md +10 -0
  108. package/docs/09_agent_fallbacks/tickets.md +88 -0
  109. package/docs/09_discord_adapter/development_log.md +95 -0
  110. package/docs/09_discord_adapter/notes.md +18 -0
  111. package/docs/09_discord_adapter/prd.md +57 -0
  112. package/docs/09_discord_adapter/questions.md +16 -0
  113. package/docs/09_discord_adapter/tickets.md +116 -0
  114. package/docs/10_file_attachments/development_log.md +55 -0
  115. package/docs/10_file_attachments/notes.md +59 -0
  116. package/docs/10_file_attachments/prd.md +73 -0
  117. package/docs/10_file_attachments/questions.md +15 -0
  118. package/docs/10_file_attachments/tickets.md +88 -0
  119. package/docs/11_message_verbosity/development_log.md +43 -0
  120. package/docs/11_message_verbosity/notes.md +26 -0
  121. package/docs/11_message_verbosity/prd.md +44 -0
  122. package/docs/11_message_verbosity/questions.md +8 -0
  123. package/docs/11_message_verbosity/tickets.md +33 -0
  124. package/docs/12_environments/development_log.md +43 -0
  125. package/docs/12_environments/notes.md +45 -0
  126. package/docs/12_environments/prd.md +113 -0
  127. package/docs/12_environments/questions.md +17 -0
  128. package/docs/12_environments/tickets.md +87 -0
  129. package/docs/12_setup_flow_improvements/development_log.md +40 -0
  130. package/docs/12_setup_flow_improvements/notes.md +34 -0
  131. package/docs/12_setup_flow_improvements/prd.md +35 -0
  132. package/docs/12_setup_flow_improvements/questions.md +8 -0
  133. package/docs/12_setup_flow_improvements/tickets.md +122 -0
  134. package/docs/13_discord_typing_indicators/development_log.md +38 -0
  135. package/docs/13_discord_typing_indicators/notes.md +18 -0
  136. package/docs/13_discord_typing_indicators/prd.md +41 -0
  137. package/docs/13_discord_typing_indicators/questions.md +6 -0
  138. package/docs/13_discord_typing_indicators/tickets.md +60 -0
  139. package/docs/14_interruptions/development_log.md +50 -0
  140. package/docs/14_interruptions/notes.md +38 -0
  141. package/docs/14_interruptions/prd.md +46 -0
  142. package/docs/14_interruptions/questions.md +12 -0
  143. package/docs/14_interruptions/tickets.md +69 -0
  144. package/docs/15_sandbox_policies/development_log.md +95 -0
  145. package/docs/15_sandbox_policies/notes.md +33 -0
  146. package/docs/15_sandbox_policies/prd.md +163 -0
  147. package/docs/15_sandbox_policies/questions.md +10 -0
  148. package/docs/15_sandbox_policies/tickets.md +196 -0
  149. package/docs/CHECKS.md +9 -0
  150. package/docs/guides/discord_adapter_setup.md +69 -0
  151. package/docs/guides/sandbox_policies.md +76 -0
  152. package/eslint.config.js +47 -0
  153. package/napkin.md +21 -0
  154. package/package.json +50 -0
  155. package/scripts/create_worktree.sh +49 -0
  156. package/scripts/get_pr_comments.sh +36 -0
  157. package/src/adapter-discord/client.test.ts +65 -0
  158. package/src/adapter-discord/client.ts +41 -0
  159. package/src/adapter-discord/config.test.ts +156 -0
  160. package/src/adapter-discord/config.ts +61 -0
  161. package/src/adapter-discord/forwarder.test.ts +493 -0
  162. package/src/adapter-discord/forwarder.ts +246 -0
  163. package/src/adapter-discord/index.test.ts +399 -0
  164. package/src/adapter-discord/index.ts +147 -0
  165. package/src/adapter-discord/state.test.ts +65 -0
  166. package/src/adapter-discord/state.ts +44 -0
  167. package/src/cli/client.ts +46 -0
  168. package/src/cli/commands/agents.ts +138 -0
  169. package/src/cli/commands/chats.ts +79 -0
  170. package/src/cli/commands/down.ts +32 -0
  171. package/src/cli/commands/environments.ts +39 -0
  172. package/src/cli/commands/export-lite.ts +62 -0
  173. package/src/cli/commands/init.ts +79 -0
  174. package/src/cli/commands/jobs.ts +141 -0
  175. package/src/cli/commands/messages.ts +103 -0
  176. package/src/cli/commands/up.ts +26 -0
  177. package/src/cli/commands/web-api/agents.ts +138 -0
  178. package/src/cli/commands/web-api/chats.ts +213 -0
  179. package/src/cli/commands/web-api/utils.ts +27 -0
  180. package/src/cli/commands/web.ts +105 -0
  181. package/src/cli/e2e/adapter-discord.test.ts +76 -0
  182. package/src/cli/e2e/agents.test.ts +140 -0
  183. package/src/cli/e2e/basic.test.ts +43 -0
  184. package/src/cli/e2e/cron.test.ts +132 -0
  185. package/src/cli/e2e/daemon.test.ts +293 -0
  186. package/src/cli/e2e/environments.test.ts +66 -0
  187. package/src/cli/e2e/export-lite-func.test.ts +155 -0
  188. package/src/cli/e2e/export-lite.test.ts +51 -0
  189. package/src/cli/e2e/fallbacks.test.ts +169 -0
  190. package/src/cli/e2e/global-setup.ts +15 -0
  191. package/src/cli/e2e/init.test.ts +70 -0
  192. package/src/cli/e2e/messages.test.ts +294 -0
  193. package/src/cli/e2e/requests.test.ts +165 -0
  194. package/src/cli/e2e/utils.ts +66 -0
  195. package/src/cli/index.test.ts +7 -0
  196. package/src/cli/index.ts +29 -0
  197. package/src/cli/lite.ts +247 -0
  198. package/src/cli/utils.ts +4 -0
  199. package/src/daemon/auth.test.ts +50 -0
  200. package/src/daemon/auth.ts +69 -0
  201. package/src/daemon/chats.ts +26 -0
  202. package/src/daemon/cron.test.ts +28 -0
  203. package/src/daemon/cron.ts +159 -0
  204. package/src/daemon/events.ts +15 -0
  205. package/src/daemon/index.ts +212 -0
  206. package/src/daemon/message-agent.test.ts +132 -0
  207. package/src/daemon/message-extraction.test.ts +166 -0
  208. package/src/daemon/message-fallbacks.test.ts +313 -0
  209. package/src/daemon/message-interruption.test.ts +125 -0
  210. package/src/daemon/message-queue.test.ts +143 -0
  211. package/src/daemon/message-router.test.ts +106 -0
  212. package/src/daemon/message-session.test.ts +127 -0
  213. package/src/daemon/message-test-utils.ts +41 -0
  214. package/src/daemon/message-typing.test.ts +93 -0
  215. package/src/daemon/message-verbosity.test.ts +127 -0
  216. package/src/daemon/message.ts +600 -0
  217. package/src/daemon/observation.test.ts +118 -0
  218. package/src/daemon/policy-request-service.test.ts +87 -0
  219. package/src/daemon/policy-request-service.ts +62 -0
  220. package/src/daemon/policy-utils.test.ts +138 -0
  221. package/src/daemon/policy-utils.ts +152 -0
  222. package/src/daemon/queue.test.ts +89 -0
  223. package/src/daemon/queue.ts +87 -0
  224. package/src/daemon/request-store.test.ts +103 -0
  225. package/src/daemon/request-store.ts +96 -0
  226. package/src/daemon/router-policy-request.test.ts +99 -0
  227. package/src/daemon/router.test.ts +380 -0
  228. package/src/daemon/router.ts +510 -0
  229. package/src/daemon/routers/slash-command.test.ts +145 -0
  230. package/src/daemon/routers/slash-command.ts +58 -0
  231. package/src/daemon/routers/slash-interrupt.test.ts +30 -0
  232. package/src/daemon/routers/slash-interrupt.ts +7 -0
  233. package/src/daemon/routers/slash-new.test.ts +59 -0
  234. package/src/daemon/routers/slash-new.ts +14 -0
  235. package/src/daemon/routers/slash-policies.test.ts +167 -0
  236. package/src/daemon/routers/slash-policies.ts +131 -0
  237. package/src/daemon/routers/slash-stop.test.ts +30 -0
  238. package/src/daemon/routers/slash-stop.ts +3 -0
  239. package/src/daemon/routers/types.ts +10 -0
  240. package/src/daemon/routers/utils.ts +22 -0
  241. package/src/daemon/routers.test.ts +141 -0
  242. package/src/daemon/routers.ts +115 -0
  243. package/src/daemon/utils/spawn.ts +61 -0
  244. package/src/shared/agent-utils.ts +30 -0
  245. package/src/shared/chats.test.ts +112 -0
  246. package/src/shared/chats.ts +164 -0
  247. package/src/shared/config.test.ts +90 -0
  248. package/src/shared/config.ts +100 -0
  249. package/src/shared/event-source.ts +121 -0
  250. package/src/shared/fetch.ts +45 -0
  251. package/src/shared/lite.ts +129 -0
  252. package/src/shared/policies.ts +24 -0
  253. package/src/shared/utils/env.ts +27 -0
  254. package/src/shared/utils/fs.ts +13 -0
  255. package/src/shared/workspace.test.ts +345 -0
  256. package/src/shared/workspace.ts +500 -0
  257. package/templates/environments/cladding/env.json +7 -0
  258. package/templates/environments/macos/env.json +8 -0
  259. package/templates/environments/macos/sandbox.sb +21 -0
  260. package/templates/environments/macos-proxy/allowlist.txt +1 -0
  261. package/templates/environments/macos-proxy/env.json +14 -0
  262. package/templates/environments/macos-proxy/proxy.mjs +86 -0
  263. package/templates/environments/macos-proxy/sandbox.sb +34 -0
  264. package/templates/gemini/settings.json +11 -0
  265. package/templates/gemini-claw/.gemini/hooks/clawmini-logging.sh +17 -0
  266. package/templates/gemini-claw/.gemini/settings.json +24 -0
  267. package/templates/gemini-claw/.gemini/skills/clawmini-jobs/SKILL.md +40 -0
  268. package/templates/gemini-claw/.gemini/system.md +98 -0
  269. package/templates/gemini-claw/BOOTSTRAP.md +54 -0
  270. package/templates/gemini-claw/GEMINI.md +107 -0
  271. package/templates/gemini-claw/HEARTBEAT.md +3 -0
  272. package/templates/gemini-claw/MEMORY.md +2 -0
  273. package/templates/gemini-claw/SOUL.md +42 -0
  274. package/templates/gemini-claw/TOOLS.md +38 -0
  275. package/templates/gemini-claw/USER.md +15 -0
  276. package/templates/gemini-claw/memory/.gitkeep +0 -0
  277. package/templates/gemini-claw/settings.json +24 -0
  278. package/templates/opencode/settings.json +11 -0
  279. package/tsconfig.json +42 -0
  280. package/tsdown.config.ts +19 -0
  281. package/vitest.config.ts +9 -0
  282. package/web/.svelte-kit/ambient.d.ts +382 -0
  283. package/web/.svelte-kit/generated/client/app.js +35 -0
  284. package/web/.svelte-kit/generated/client/matchers.js +1 -0
  285. package/web/.svelte-kit/generated/client/nodes/0.js +3 -0
  286. package/web/.svelte-kit/generated/client/nodes/1.js +1 -0
  287. package/web/.svelte-kit/generated/client/nodes/2.js +1 -0
  288. package/web/.svelte-kit/generated/client/nodes/3.js +1 -0
  289. package/web/.svelte-kit/generated/client/nodes/4.js +3 -0
  290. package/web/.svelte-kit/generated/client/nodes/5.js +3 -0
  291. package/web/.svelte-kit/generated/client-optimized/app.js +35 -0
  292. package/web/.svelte-kit/generated/client-optimized/matchers.js +1 -0
  293. package/web/.svelte-kit/generated/client-optimized/nodes/0.js +3 -0
  294. package/web/.svelte-kit/generated/client-optimized/nodes/1.js +1 -0
  295. package/web/.svelte-kit/generated/client-optimized/nodes/2.js +1 -0
  296. package/web/.svelte-kit/generated/client-optimized/nodes/3.js +1 -0
  297. package/web/.svelte-kit/generated/client-optimized/nodes/4.js +3 -0
  298. package/web/.svelte-kit/generated/client-optimized/nodes/5.js +3 -0
  299. package/web/.svelte-kit/generated/root.js +3 -0
  300. package/web/.svelte-kit/generated/root.svelte +68 -0
  301. package/web/.svelte-kit/generated/server/internal.js +53 -0
  302. package/web/.svelte-kit/non-ambient.d.ts +46 -0
  303. package/web/.svelte-kit/output/client/.vite/manifest.json +251 -0
  304. package/web/.svelte-kit/output/client/_app/immutable/assets/0.GI4C4dpV.css +1 -0
  305. package/web/.svelte-kit/output/client/_app/immutable/chunks/B5abRDXp.js +1 -0
  306. package/web/.svelte-kit/output/client/_app/immutable/chunks/B8yYFADm.js +1 -0
  307. package/web/.svelte-kit/output/client/_app/immutable/chunks/BPy8HLo7.js +5 -0
  308. package/web/.svelte-kit/output/client/_app/immutable/chunks/Bi0jeV7Q.js +1 -0
  309. package/web/.svelte-kit/output/client/_app/immutable/chunks/BmUXQ3wy.js +2 -0
  310. package/web/.svelte-kit/output/client/_app/immutable/chunks/C3k55nDF.js +1 -0
  311. package/web/.svelte-kit/output/client/_app/immutable/chunks/COekwvP2.js +1 -0
  312. package/web/.svelte-kit/output/client/_app/immutable/chunks/CSvS_NwK.js +1 -0
  313. package/web/.svelte-kit/output/client/_app/immutable/chunks/CpaGRn9L.js +1 -0
  314. package/web/.svelte-kit/output/client/_app/immutable/chunks/CyNaE55B.js +1 -0
  315. package/web/.svelte-kit/output/client/_app/immutable/chunks/DG5RZBw-.js +2 -0
  316. package/web/.svelte-kit/output/client/_app/immutable/chunks/Dc-UOHw9.js +1 -0
  317. package/web/.svelte-kit/output/client/_app/immutable/chunks/DcrmIfTj.js +1 -0
  318. package/web/.svelte-kit/output/client/_app/immutable/chunks/ZkLyk0mE.js +1 -0
  319. package/web/.svelte-kit/output/client/_app/immutable/entry/app.B-vZe7PN.js +2 -0
  320. package/web/.svelte-kit/output/client/_app/immutable/entry/start.oP1AgKhs.js +1 -0
  321. package/web/.svelte-kit/output/client/_app/immutable/nodes/0.B5WFN0zw.js +1 -0
  322. package/web/.svelte-kit/output/client/_app/immutable/nodes/1.D1wtJb2k.js +1 -0
  323. package/web/.svelte-kit/output/client/_app/immutable/nodes/2.CK3CLC0f.js +1 -0
  324. package/web/.svelte-kit/output/client/_app/immutable/nodes/3.BB5wCoBf.js +4 -0
  325. package/web/.svelte-kit/output/client/_app/immutable/nodes/4.Dr2jvAXK.js +1 -0
  326. package/web/.svelte-kit/output/client/_app/immutable/nodes/5.BJl7oM3b.js +1 -0
  327. package/web/.svelte-kit/output/client/_app/version.json +1 -0
  328. package/web/.svelte-kit/output/client/robots.txt +3 -0
  329. package/web/.svelte-kit/output/prerendered/dependencies/_app/env.js +1 -0
  330. package/web/.svelte-kit/output/server/.vite/manifest.json +215 -0
  331. package/web/.svelte-kit/output/server/_app/immutable/assets/_layout.GI4C4dpV.css +1 -0
  332. package/web/.svelte-kit/output/server/chunks/Icon.js +153 -0
  333. package/web/.svelte-kit/output/server/chunks/bot.js +2753 -0
  334. package/web/.svelte-kit/output/server/chunks/client.js +47 -0
  335. package/web/.svelte-kit/output/server/chunks/environment.js +34 -0
  336. package/web/.svelte-kit/output/server/chunks/exports.js +231 -0
  337. package/web/.svelte-kit/output/server/chunks/false.js +4 -0
  338. package/web/.svelte-kit/output/server/chunks/index-server.js +20 -0
  339. package/web/.svelte-kit/output/server/chunks/index.js +24 -0
  340. package/web/.svelte-kit/output/server/chunks/internal.js +133 -0
  341. package/web/.svelte-kit/output/server/chunks/plus.js +81 -0
  342. package/web/.svelte-kit/output/server/chunks/root.js +4076 -0
  343. package/web/.svelte-kit/output/server/chunks/shared.js +789 -0
  344. package/web/.svelte-kit/output/server/chunks/utils.js +43 -0
  345. package/web/.svelte-kit/output/server/entries/fallbacks/error.svelte.js +11 -0
  346. package/web/.svelte-kit/output/server/entries/pages/_layout.svelte.js +3944 -0
  347. package/web/.svelte-kit/output/server/entries/pages/_layout.ts.js +28 -0
  348. package/web/.svelte-kit/output/server/entries/pages/_page.svelte.js +7 -0
  349. package/web/.svelte-kit/output/server/entries/pages/agents/_page.svelte.js +379 -0
  350. package/web/.svelte-kit/output/server/entries/pages/chats/_id_/_page.svelte.js +292 -0
  351. package/web/.svelte-kit/output/server/entries/pages/chats/_id_/_page.ts.js +17 -0
  352. package/web/.svelte-kit/output/server/entries/pages/chats/_id_/settings/_page.svelte.js +259 -0
  353. package/web/.svelte-kit/output/server/entries/pages/chats/_id_/settings/_page.ts.js +17 -0
  354. package/web/.svelte-kit/output/server/index.js +3748 -0
  355. package/web/.svelte-kit/output/server/internal.js +14 -0
  356. package/web/.svelte-kit/output/server/manifest-full.js +63 -0
  357. package/web/.svelte-kit/output/server/manifest.js +63 -0
  358. package/web/.svelte-kit/output/server/nodes/0.js +13 -0
  359. package/web/.svelte-kit/output/server/nodes/1.js +8 -0
  360. package/web/.svelte-kit/output/server/nodes/2.js +8 -0
  361. package/web/.svelte-kit/output/server/nodes/3.js +8 -0
  362. package/web/.svelte-kit/output/server/nodes/4.js +13 -0
  363. package/web/.svelte-kit/output/server/nodes/5.js +13 -0
  364. package/web/.svelte-kit/output/server/remote-entry.js +557 -0
  365. package/web/.svelte-kit/tsconfig.json +67 -0
  366. package/web/.svelte-kit/types/route_meta_data.json +17 -0
  367. package/web/.svelte-kit/types/src/routes/$types.d.ts +26 -0
  368. package/web/.svelte-kit/types/src/routes/agents/$types.d.ts +18 -0
  369. package/web/.svelte-kit/types/src/routes/chats/[id]/$types.d.ts +21 -0
  370. package/web/.svelte-kit/types/src/routes/chats/[id]/proxy+page.ts +20 -0
  371. package/web/.svelte-kit/types/src/routes/chats/[id]/settings/$types.d.ts +21 -0
  372. package/web/.svelte-kit/types/src/routes/chats/[id]/settings/proxy+page.ts +19 -0
  373. package/web/.svelte-kit/types/src/routes/proxy+layout.ts +35 -0
  374. package/web/README.md +42 -0
  375. package/web/components.json +16 -0
  376. package/web/package.json +41 -0
  377. package/web/src/app.css +121 -0
  378. package/web/src/app.d.ts +13 -0
  379. package/web/src/app.html +11 -0
  380. package/web/src/demo.spec.ts +7 -0
  381. package/web/src/lib/app-state.svelte.ts +3 -0
  382. package/web/src/lib/assets/favicon.svg +1 -0
  383. package/web/src/lib/components/app/app-sidebar-test-wrapper.svelte +10 -0
  384. package/web/src/lib/components/app/app-sidebar.svelte +171 -0
  385. package/web/src/lib/components/app/app-sidebar.svelte.spec.ts +13 -0
  386. package/web/src/lib/components/ui/button/button.svelte +82 -0
  387. package/web/src/lib/components/ui/button/index.ts +17 -0
  388. package/web/src/lib/components/ui/dialog/dialog-close.svelte +7 -0
  389. package/web/src/lib/components/ui/dialog/dialog-content.svelte +45 -0
  390. package/web/src/lib/components/ui/dialog/dialog-description.svelte +17 -0
  391. package/web/src/lib/components/ui/dialog/dialog-footer.svelte +20 -0
  392. package/web/src/lib/components/ui/dialog/dialog-header.svelte +20 -0
  393. package/web/src/lib/components/ui/dialog/dialog-overlay.svelte +20 -0
  394. package/web/src/lib/components/ui/dialog/dialog-portal.svelte +7 -0
  395. package/web/src/lib/components/ui/dialog/dialog-title.svelte +17 -0
  396. package/web/src/lib/components/ui/dialog/dialog-trigger.svelte +7 -0
  397. package/web/src/lib/components/ui/dialog/dialog.svelte +7 -0
  398. package/web/src/lib/components/ui/dialog/index.ts +34 -0
  399. package/web/src/lib/components/ui/input/index.ts +7 -0
  400. package/web/src/lib/components/ui/input/input.svelte +52 -0
  401. package/web/src/lib/components/ui/separator/index.ts +7 -0
  402. package/web/src/lib/components/ui/separator/separator.svelte +21 -0
  403. package/web/src/lib/components/ui/sheet/index.ts +34 -0
  404. package/web/src/lib/components/ui/sheet/sheet-close.svelte +7 -0
  405. package/web/src/lib/components/ui/sheet/sheet-content.svelte +60 -0
  406. package/web/src/lib/components/ui/sheet/sheet-description.svelte +17 -0
  407. package/web/src/lib/components/ui/sheet/sheet-footer.svelte +20 -0
  408. package/web/src/lib/components/ui/sheet/sheet-header.svelte +20 -0
  409. package/web/src/lib/components/ui/sheet/sheet-overlay.svelte +20 -0
  410. package/web/src/lib/components/ui/sheet/sheet-portal.svelte +7 -0
  411. package/web/src/lib/components/ui/sheet/sheet-title.svelte +17 -0
  412. package/web/src/lib/components/ui/sheet/sheet-trigger.svelte +7 -0
  413. package/web/src/lib/components/ui/sheet/sheet.svelte +7 -0
  414. package/web/src/lib/components/ui/sidebar/constants.ts +6 -0
  415. package/web/src/lib/components/ui/sidebar/context.svelte.ts +79 -0
  416. package/web/src/lib/components/ui/sidebar/index.ts +75 -0
  417. package/web/src/lib/components/ui/sidebar/sidebar-content.svelte +24 -0
  418. package/web/src/lib/components/ui/sidebar/sidebar-footer.svelte +21 -0
  419. package/web/src/lib/components/ui/sidebar/sidebar-group-action.svelte +36 -0
  420. package/web/src/lib/components/ui/sidebar/sidebar-group-content.svelte +21 -0
  421. package/web/src/lib/components/ui/sidebar/sidebar-group-label.svelte +34 -0
  422. package/web/src/lib/components/ui/sidebar/sidebar-group.svelte +21 -0
  423. package/web/src/lib/components/ui/sidebar/sidebar-header.svelte +21 -0
  424. package/web/src/lib/components/ui/sidebar/sidebar-input.svelte +21 -0
  425. package/web/src/lib/components/ui/sidebar/sidebar-inset.svelte +24 -0
  426. package/web/src/lib/components/ui/sidebar/sidebar-menu-action.svelte +43 -0
  427. package/web/src/lib/components/ui/sidebar/sidebar-menu-badge.svelte +29 -0
  428. package/web/src/lib/components/ui/sidebar/sidebar-menu-button.svelte +103 -0
  429. package/web/src/lib/components/ui/sidebar/sidebar-menu-item.svelte +21 -0
  430. package/web/src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte +36 -0
  431. package/web/src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte +43 -0
  432. package/web/src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte +21 -0
  433. package/web/src/lib/components/ui/sidebar/sidebar-menu-sub.svelte +25 -0
  434. package/web/src/lib/components/ui/sidebar/sidebar-menu.svelte +21 -0
  435. package/web/src/lib/components/ui/sidebar/sidebar-provider.svelte +53 -0
  436. package/web/src/lib/components/ui/sidebar/sidebar-rail.svelte +36 -0
  437. package/web/src/lib/components/ui/sidebar/sidebar-separator.svelte +19 -0
  438. package/web/src/lib/components/ui/sidebar/sidebar-trigger.svelte +35 -0
  439. package/web/src/lib/components/ui/sidebar/sidebar.svelte +104 -0
  440. package/web/src/lib/components/ui/skeleton/index.ts +7 -0
  441. package/web/src/lib/components/ui/skeleton/skeleton.svelte +17 -0
  442. package/web/src/lib/components/ui/switch/index.ts +7 -0
  443. package/web/src/lib/components/ui/switch/switch.svelte +29 -0
  444. package/web/src/lib/components/ui/textarea/index.ts +7 -0
  445. package/web/src/lib/components/ui/textarea/textarea.svelte +23 -0
  446. package/web/src/lib/components/ui/tooltip/index.ts +19 -0
  447. package/web/src/lib/components/ui/tooltip/tooltip-content.svelte +52 -0
  448. package/web/src/lib/components/ui/tooltip/tooltip-portal.svelte +7 -0
  449. package/web/src/lib/components/ui/tooltip/tooltip-provider.svelte +7 -0
  450. package/web/src/lib/components/ui/tooltip/tooltip-trigger.svelte +7 -0
  451. package/web/src/lib/components/ui/tooltip/tooltip.svelte +7 -0
  452. package/web/src/lib/hooks/is-mobile.svelte.ts +9 -0
  453. package/web/src/lib/index.ts +1 -0
  454. package/web/src/lib/types.ts +23 -0
  455. package/web/src/lib/utils.ts +13 -0
  456. package/web/src/routes/+layout.svelte +67 -0
  457. package/web/src/routes/+layout.ts +34 -0
  458. package/web/src/routes/+page.svelte +7 -0
  459. package/web/src/routes/agents/+page.svelte +206 -0
  460. package/web/src/routes/chats/[id]/+page.svelte +406 -0
  461. package/web/src/routes/chats/[id]/+page.ts +19 -0
  462. package/web/src/routes/chats/[id]/page.svelte.spec.ts +102 -0
  463. package/web/src/routes/chats/[id]/settings/+page.svelte +165 -0
  464. package/web/src/routes/chats/[id]/settings/+page.ts +18 -0
  465. package/web/src/routes/page.svelte.spec.ts +13 -0
  466. package/web/static/robots.txt +3 -0
  467. package/web/svelte.config.js +21 -0
  468. package/web/tsconfig.json +20 -0
  469. package/web/vite.config.ts +41 -0
@@ -0,0 +1,27 @@
1
+ import http from 'node:http';
2
+ import { type ZodType } from 'zod';
3
+
4
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
+ export async function parseJsonBody<T = any>(
6
+ req: http.IncomingMessage,
7
+ schema?: ZodType<T>
8
+ ): Promise<T> {
9
+ if (req.headers['content-type'] !== 'application/json') {
10
+ throw new Error('Invalid Content-Type');
11
+ }
12
+ let bodyStr = '';
13
+ for await (const chunk of req) {
14
+ bodyStr += chunk;
15
+ }
16
+ const rawBody = JSON.parse(bodyStr);
17
+ if (schema) {
18
+ return schema.parse(rawBody);
19
+ }
20
+ return rawBody as T;
21
+ }
22
+
23
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
+ export function sendJsonResponse(res: http.ServerResponse, statusCode: number, data: any) {
25
+ res.writeHead(statusCode, { 'Content-Type': 'application/json' });
26
+ res.end(JSON.stringify(data));
27
+ }
@@ -0,0 +1,105 @@
1
+ import { Command } from 'commander';
2
+ import http from 'node:http';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ import { pathIsInsideDir } from '../../shared/utils/fs.js';
8
+ import { sendJsonResponse } from './web-api/utils.js';
9
+ import { handleApiAgents } from './web-api/agents.js';
10
+ import { handleApiChats } from './web-api/chats.js';
11
+
12
+ const mimeTypes: Record<string, string> = {
13
+ '.html': 'text/html',
14
+ '.js': 'text/javascript',
15
+ '.mjs': 'text/javascript',
16
+ '.css': 'text/css',
17
+ '.json': 'application/json',
18
+ '.png': 'image/png',
19
+ '.jpg': 'image/jpeg',
20
+ '.gif': 'image/gif',
21
+ '.svg': 'image/svg+xml',
22
+ '.ico': 'image/x-icon',
23
+ '.woff': 'font/woff',
24
+ '.woff2': 'font/woff2',
25
+ };
26
+
27
+ export const webCmd = new Command('web')
28
+ .description('Start the local clawmini web interface')
29
+ .option('-p, --port <number>', 'Port to bind the server to', '8080')
30
+ .option('-H, --host <string>', 'Host to bind the server to', '127.0.0.1')
31
+ .action((options) => {
32
+ const port = parseInt(options.port, 10);
33
+ if (isNaN(port)) {
34
+ console.error('Invalid port number.');
35
+ process.exit(1);
36
+ }
37
+
38
+ // When bundled into dist/cli/index.mjs, import.meta.url resolves to that file.
39
+ // So __dirname will be dist/cli, and webDir will be dist/web.
40
+ const __filename = fileURLToPath(import.meta.url);
41
+ const __dirname = path.dirname(__filename);
42
+ const webDir = path.resolve(__dirname, '../web');
43
+
44
+ const server = http.createServer(async (req, res) => {
45
+ try {
46
+ const urlPath = req.url === '/' ? '/index.html' : req.url?.split('?')[0] || '/';
47
+
48
+ // API Routes
49
+ if (urlPath.startsWith('/api/')) {
50
+ res.setHeader('Content-Type', 'application/json');
51
+ res.setHeader('Access-Control-Allow-Origin', '*');
52
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
53
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
54
+
55
+ if (req.method === 'OPTIONS') {
56
+ res.writeHead(204);
57
+ res.end();
58
+ return;
59
+ }
60
+
61
+ if (urlPath.startsWith('/api/agents') && (await handleApiAgents(req, res, urlPath)))
62
+ return;
63
+ if (urlPath.startsWith('/api/chats') && (await handleApiChats(req, res, urlPath))) return;
64
+
65
+ sendJsonResponse(res, 404, { error: 'Not Found' });
66
+ return;
67
+ }
68
+
69
+ // Static Files
70
+ let filePath = path.join(webDir, urlPath);
71
+
72
+ // Prevent directory traversal
73
+ if (!pathIsInsideDir(filePath, webDir)) {
74
+ res.writeHead(403);
75
+ res.end('Forbidden');
76
+ return;
77
+ }
78
+
79
+ if (!fs.existsSync(filePath) || fs.statSync(filePath).isDirectory()) {
80
+ // SPA fallback to index.html
81
+ filePath = path.join(webDir, 'index.html');
82
+ if (!fs.existsSync(filePath)) {
83
+ res.writeHead(404);
84
+ res.end('Not Found');
85
+ return;
86
+ }
87
+ }
88
+
89
+ const extname = path.extname(filePath).toLowerCase();
90
+ const contentType = mimeTypes[extname] || 'application/octet-stream';
91
+
92
+ res.writeHead(200, { 'Content-Type': contentType });
93
+ const readStream = fs.createReadStream(filePath);
94
+ readStream.pipe(res);
95
+ } catch (err) {
96
+ console.error('Error serving request:', err);
97
+ res.writeHead(500);
98
+ res.end('Internal Server Error');
99
+ }
100
+ });
101
+
102
+ server.listen(port, options.host, () => {
103
+ console.log(`Clawmini web interface running at http://${options.host}:${port}/`);
104
+ });
105
+ });
@@ -0,0 +1,76 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
+ import path from 'node:path';
3
+ import { createE2EContext } from './utils.js';
4
+ import { getTRPCClient } from '../../adapter-discord/client.js';
5
+
6
+ const { runCli, e2eDir, setupE2E, teardownE2E } = createE2EContext('e2e-discord');
7
+ describe('Discord Adapter Client E2E', () => {
8
+ beforeAll(async () => {
9
+ await setupE2E();
10
+ await runCli(['init']);
11
+ await runCli(['up']);
12
+ }, 30000);
13
+
14
+ afterAll(async () => {
15
+ await runCli(['down']);
16
+ await teardownE2E();
17
+ }, 30000);
18
+
19
+ it('should successfully connect to the daemon and subscribe to messages', async () => {
20
+ const socketPath = path.join(e2eDir, '.clawmini', 'server.sock');
21
+ const trpc = getTRPCClient({ socketPath });
22
+
23
+ const pingResult = await trpc.ping.query();
24
+ expect(pingResult).toEqual({ status: 'ok' });
25
+
26
+ await runCli(['chats', 'add', 'discord-chat']);
27
+
28
+ let subscription: { unsubscribe: () => void } | undefined;
29
+ const messages: Record<string, unknown>[] = [];
30
+
31
+ await new Promise<void>((resolve, reject) => {
32
+ subscription = trpc.waitForMessages.subscribe(
33
+ { chatId: 'discord-chat' },
34
+ {
35
+ onData: (data) => {
36
+ messages.push(...(data as Record<string, unknown>[]));
37
+ if (messages.some((m) => m.content === 'hello from adapter e2e test')) {
38
+ resolve();
39
+ }
40
+ },
41
+ onError: (err) => {
42
+ reject(err);
43
+ },
44
+ }
45
+ );
46
+
47
+ // Wait a brief moment to ensure subscription is established before sending a message
48
+ setTimeout(async () => {
49
+ try {
50
+ await runCli([
51
+ 'messages',
52
+ 'send',
53
+ 'hello from adapter e2e test',
54
+ '--chat',
55
+ 'discord-chat',
56
+ '--no-wait',
57
+ ]);
58
+ } catch (e) {
59
+ reject(e);
60
+ }
61
+ }, 500);
62
+
63
+ // Safety timeout
64
+ setTimeout(() => reject(new Error('Timeout waiting for message')), 5000);
65
+ });
66
+
67
+ if (subscription) {
68
+ subscription.unsubscribe();
69
+ }
70
+
71
+ expect(messages.length).toBeGreaterThan(0);
72
+ const found = messages.find((m) => m.content === 'hello from adapter e2e test');
73
+ expect(found).toBeDefined();
74
+ expect(found!.role).toBe('user');
75
+ });
76
+ });
@@ -0,0 +1,140 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
+ import path from 'node:path';
3
+ import fs from 'node:fs';
4
+ import { createE2EContext } from './utils.js';
5
+
6
+ const { runCli, e2eDir, setupE2E, teardownE2E } = createE2EContext('e2e-tmp-agents');
7
+
8
+ describe('E2E Agents Tests', () => {
9
+ beforeAll(async () => {
10
+ await setupE2E();
11
+ await runCli(['init']);
12
+ }, 30000);
13
+
14
+ afterAll(teardownE2E, 30000);
15
+
16
+ it('should create, list, update and delete agents', async () => {
17
+ const { stdout: stdoutAdd, code: codeAdd } = await runCli([
18
+ 'agents',
19
+ 'add',
20
+ 'test-agent',
21
+ '--directory',
22
+ './test-agent-dir',
23
+ '--env',
24
+ 'FOO=BAR',
25
+ '--env',
26
+ 'BAZ=QUX',
27
+ ]);
28
+ expect(codeAdd).toBe(0);
29
+ expect(stdoutAdd).toContain('Agent test-agent created successfully.');
30
+
31
+ const chatSettingsPath = path.resolve(e2eDir, '.clawmini/chats/test-agent/settings.json');
32
+ expect(fs.existsSync(chatSettingsPath)).toBe(true);
33
+ const chatData = JSON.parse(fs.readFileSync(chatSettingsPath, 'utf8'));
34
+ expect(chatData.defaultAgent).toBe('test-agent');
35
+
36
+ const agentSettingsPath = path.resolve(e2eDir, '.clawmini/agents/test-agent/settings.json');
37
+ expect(fs.existsSync(agentSettingsPath)).toBe(true);
38
+ const agentData = JSON.parse(fs.readFileSync(agentSettingsPath, 'utf8'));
39
+ expect(agentData.directory).toBe('./test-agent-dir');
40
+ expect(agentData.env?.FOO).toBe('BAR');
41
+ expect(agentData.env?.BAZ).toBe('QUX');
42
+
43
+ const { stdout: stdoutList1 } = await runCli(['agents', 'list']);
44
+ expect(stdoutList1).toContain('- test-agent');
45
+
46
+ const { stdout: stdoutUpdate, code: codeUpdate } = await runCli([
47
+ 'agents',
48
+ 'update',
49
+ 'test-agent',
50
+ '--directory',
51
+ './new-dir',
52
+ '--env',
53
+ 'FOO=NEW_BAR',
54
+ ]);
55
+ expect(codeUpdate).toBe(0);
56
+ expect(stdoutUpdate).toContain('Agent test-agent updated successfully.');
57
+
58
+ const updatedAgentData = JSON.parse(fs.readFileSync(agentSettingsPath, 'utf8'));
59
+ expect(updatedAgentData.directory).toBe('./new-dir');
60
+ expect(updatedAgentData.env?.FOO).toBe('NEW_BAR');
61
+ expect(updatedAgentData.env?.BAZ).toBe('QUX');
62
+
63
+ const { stdout: stdoutDelete, code: codeDelete } = await runCli([
64
+ 'agents',
65
+ 'delete',
66
+ 'test-agent',
67
+ ]);
68
+ expect(codeDelete).toBe(0);
69
+ expect(stdoutDelete).toContain('Agent test-agent deleted successfully.');
70
+ expect(fs.existsSync(agentSettingsPath)).toBe(false);
71
+ });
72
+
73
+ it('should output a warning if chat already exists when adding an agent', async () => {
74
+ // First, manually create a chat directory
75
+ const chatDir = path.resolve(e2eDir, '.clawmini/chats/existing-chat');
76
+ fs.mkdirSync(chatDir, { recursive: true });
77
+
78
+ const { stdout, stderr, code } = await runCli(['agents', 'add', 'existing-chat']);
79
+
80
+ expect(code).toBe(0);
81
+ expect(stderr).toContain('Warning: Chat existing-chat already exists.');
82
+ expect(stdout).toContain('Agent existing-chat created successfully.');
83
+ });
84
+
85
+ it('should create an agent using a template and merge settings correctly', async () => {
86
+ // Create a local template
87
+ const templateDir = path.resolve(e2eDir, '.clawmini/templates/test-template');
88
+ fs.mkdirSync(templateDir, { recursive: true });
89
+
90
+ // Create some template files
91
+ fs.writeFileSync(path.join(templateDir, 'hello.txt'), 'Hello Template!');
92
+
93
+ // Create a settings.json that should be merged/overridden
94
+ const templateSettings = {
95
+ directory: './should-be-ignored',
96
+ env: {
97
+ TEMPLATE_VAR: 'template_value',
98
+ FOO: 'WILL_BE_OVERRIDDEN',
99
+ },
100
+ };
101
+ fs.writeFileSync(path.join(templateDir, 'settings.json'), JSON.stringify(templateSettings));
102
+
103
+ const { stdout, stderr, code } = await runCli([
104
+ 'agents',
105
+ 'add',
106
+ 'test-template-agent',
107
+ '--template',
108
+ 'test-template',
109
+ '--directory',
110
+ './custom-agent-dir',
111
+ '--env',
112
+ 'FOO=BAR',
113
+ ]);
114
+
115
+ expect(code).toBe(0);
116
+ expect(stderr).toContain("Warning: Ignoring 'directory' field from template settings.json");
117
+ expect(stdout).toContain('Agent test-template-agent created successfully.');
118
+ const agentSettingsPath = path.resolve(
119
+ e2eDir,
120
+ '.clawmini/agents/test-template-agent/settings.json'
121
+ );
122
+ expect(fs.existsSync(agentSettingsPath)).toBe(true);
123
+
124
+ const agentData = JSON.parse(fs.readFileSync(agentSettingsPath, 'utf8'));
125
+
126
+ // Verify directory override
127
+ expect(agentData.directory).toBe('./custom-agent-dir');
128
+
129
+ // Verify env merge
130
+ expect(agentData.env?.TEMPLATE_VAR).toBe('template_value');
131
+ expect(agentData.env?.FOO).toBe('BAR');
132
+
133
+ // Verify template files were copied
134
+ const customDir = path.resolve(e2eDir, 'custom-agent-dir');
135
+ expect(fs.existsSync(path.join(customDir, 'hello.txt'))).toBe(true);
136
+
137
+ // Verify settings.json was deleted from the agent working dir
138
+ expect(fs.existsSync(path.join(customDir, 'settings.json'))).toBe(false);
139
+ });
140
+ });
@@ -0,0 +1,43 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
+ import path from 'node:path';
3
+ import fs from 'node:fs';
4
+ import { createE2EContext } from './utils.js';
5
+
6
+ const { runCli, e2eDir, setupE2E, teardownE2E } = createE2EContext('e2e-tmp-basic');
7
+
8
+ describe('E2E Basic Tests', () => {
9
+ beforeAll(setupE2E, 30000);
10
+ afterAll(teardownE2E, 30000);
11
+
12
+ it('should run init and initialize settings', async () => {
13
+ const { stdout, code } = await runCli(['init']);
14
+
15
+ expect(code).toBe(0);
16
+ expect(stdout).toContain('Initialized .clawmini/settings.json');
17
+
18
+ const clawminiDir = path.resolve(e2eDir, '.clawmini');
19
+ expect(fs.existsSync(path.join(clawminiDir, 'settings.json'))).toBe(true);
20
+ });
21
+
22
+ it('should create, list, set-default and delete chats', async () => {
23
+ const { stdout: stdoutAdd, code: codeAdd } = await runCli(['chats', 'add', 'test-chat']);
24
+ expect(codeAdd).toBe(0);
25
+ expect(stdoutAdd).toContain('Chat test-chat created successfully.');
26
+
27
+ const chatsDir = path.resolve(e2eDir, '.clawmini/chats');
28
+ expect(fs.existsSync(path.join(chatsDir, 'test-chat', 'chat.jsonl'))).toBe(true);
29
+
30
+ const { stdout: stdoutList1 } = await runCli(['chats', 'list']);
31
+ expect(stdoutList1).toContain('- test-chat');
32
+
33
+ const { stdout: stdoutSetDefault } = await runCli(['chats', 'set-default', 'test-chat']);
34
+ expect(stdoutSetDefault).toContain('Default chat set to test-chat.');
35
+
36
+ const { stdout: stdoutList2 } = await runCli(['chats', 'list']);
37
+ expect(stdoutList2).toContain('- test-chat *');
38
+
39
+ const { stdout: stdoutDelete } = await runCli(['chats', 'delete', 'test-chat']);
40
+ expect(stdoutDelete).toContain('Chat test-chat deleted successfully.');
41
+ expect(fs.existsSync(path.join(chatsDir, 'test-chat'))).toBe(false);
42
+ });
43
+ });
@@ -0,0 +1,132 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
+ import { createE2EContext } from './utils.js';
3
+
4
+ const { runCli, e2eDir, setupE2E, teardownE2E } = createE2EContext('e2e-tmp-cron');
5
+
6
+ describe('E2E Cron Tests', () => {
7
+ beforeAll(async () => {
8
+ await setupE2E();
9
+ await runCli(['init']);
10
+ }, 30000);
11
+
12
+ afterAll(async () => {
13
+ await teardownE2E();
14
+ }, 30000);
15
+
16
+ it('should add, list, and delete jobs', async () => {
17
+ // 1. Add a job
18
+ const { stdout: stdoutAdd, code: codeAdd } = await runCli([
19
+ 'jobs',
20
+ 'add',
21
+ 'test-job-1',
22
+ '--message',
23
+ 'hello world',
24
+ '--every',
25
+ '10m',
26
+ '--agent',
27
+ 'my-agent',
28
+ '--env',
29
+ 'FOO=BAR',
30
+ '--session',
31
+ 'new',
32
+ ]);
33
+ expect(codeAdd).toBe(0);
34
+ expect(stdoutAdd).toContain("Job 'test-job-1' created successfully.");
35
+
36
+ // 2. List jobs
37
+ const { stdout: stdoutList1, code: codeList1 } = await runCli(['jobs', 'list']);
38
+ expect(codeList1).toBe(0);
39
+ expect(stdoutList1).toContain('- test-job-1 (every: 10m)');
40
+
41
+ // 3. Add a second job using cron expression
42
+ const { stdout: stdoutAdd2, code: codeAdd2 } = await runCli([
43
+ 'jobs',
44
+ 'add',
45
+ 'test-job-2',
46
+ '--cron',
47
+ '* * * * *',
48
+ ]);
49
+ expect(codeAdd2).toBe(0);
50
+ expect(stdoutAdd2).toContain("Job 'test-job-2' created successfully.");
51
+
52
+ const { stdout: stdoutList2 } = await runCli(['jobs', 'list']);
53
+ expect(stdoutList2).toContain('- test-job-1 (every: 10m)');
54
+ expect(stdoutList2).toContain('- test-job-2 (cron: * * * * *)');
55
+
56
+ // 4. Delete the first job
57
+ const { stdout: stdoutDelete, code: codeDelete } = await runCli([
58
+ 'jobs',
59
+ 'delete',
60
+ 'test-job-1',
61
+ ]);
62
+ expect(codeDelete).toBe(0);
63
+ expect(stdoutDelete).toContain("Job 'test-job-1' deleted successfully.");
64
+
65
+ const { stdout: stdoutList3 } = await runCli(['jobs', 'list']);
66
+ expect(stdoutList3).not.toContain('test-job-1');
67
+ expect(stdoutList3).toContain('- test-job-2 (cron: * * * * *)');
68
+ });
69
+
70
+ it('should execute a job and inherit chat default agent and session', async () => {
71
+ // 1. Create a specific agent for this chat
72
+ await runCli(['agents', 'add', 'cron-exec-agent']);
73
+ const fs = await import('node:fs');
74
+ const path = await import('node:path');
75
+ const agentPath = path.resolve(e2eDir, '.clawmini/agents/cron-exec-agent/settings.json');
76
+ const agentData = JSON.parse(fs.readFileSync(agentPath, 'utf8'));
77
+ agentData.commands = { new: 'echo "executed with $SESSION_ID and msg: $CLAW_CLI_MESSAGE"' };
78
+ fs.writeFileSync(agentPath, JSON.stringify(agentData));
79
+
80
+ // 2. Setup the chat with this agent and get a session ID
81
+ await runCli(['chats', 'add', 'cron-chat']);
82
+ const { code: codeSetup, stderr: stderrSetup } = await runCli([
83
+ 'messages',
84
+ 'send',
85
+ 'setup session',
86
+ '-c',
87
+ 'cron-chat',
88
+ '-a',
89
+ 'cron-exec-agent',
90
+ ]);
91
+ if (codeSetup !== 0) console.error(stderrSetup);
92
+ expect(codeSetup).toBe(0);
93
+
94
+ // 3. Schedule a job for 2 seconds in the future
95
+ const futureTime = new Date(Date.now() + 2000).toISOString();
96
+ const { stdout: stdoutAdd, code: codeAdd } = await runCli([
97
+ 'jobs',
98
+ 'add',
99
+ 'test-exec-job',
100
+ '-c',
101
+ 'cron-chat',
102
+ '--at',
103
+ futureTime,
104
+ '--message',
105
+ 'hello from future',
106
+ ]);
107
+ expect(codeAdd).toBe(0);
108
+ expect(stdoutAdd).toContain("Job 'test-exec-job' created successfully.");
109
+
110
+ // 4. Wait for job to execute (approx 3 seconds)
111
+ await new Promise((resolve) => setTimeout(resolve, 3000));
112
+
113
+ // 5. Check if the message was sent and properly inherited the agent and session
114
+
115
+ // Fallback if e2e test uses a different dir, get it from the e2eDir context
116
+ // Actually createE2EContext returns e2eDir, but it's not exported from the setup block directly if not destructured.
117
+ // wait, I can just use `runCli(['messages', 'tail', '-c', 'cron-chat', '--json'])`
118
+ const { stdout: stdoutHistory } = await runCli(['messages', 'tail', '-c', 'cron-chat']);
119
+
120
+ // It should have executed the cron job
121
+ expect(stdoutHistory).toContain('hello from future');
122
+ // It should have used cron-exec-agent, not default
123
+ expect(stdoutHistory).toContain('msg: hello from future');
124
+ // Session ID should not be empty or undefined, it should have been set by the previous message
125
+ }, 10000);
126
+
127
+ it('should reject jobs with invalid --at date format', async () => {
128
+ const { stderr, code } = await runCli(['jobs', 'add', 'invalid-job', '--at', 'invalid-date']);
129
+ expect(code).not.toBe(0);
130
+ expect(stderr).toContain("Invalid date format for 'at' schedule: invalid-date");
131
+ });
132
+ });