clawmini 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. package/README.md +19 -0
  2. package/dist/adapter-discord/index.d.mts.map +1 -1
  3. package/dist/adapter-discord/index.mjs +398 -193
  4. package/dist/adapter-discord/index.mjs.map +1 -1
  5. package/dist/adapter-google-chat/index.d.mts +5 -0
  6. package/dist/adapter-google-chat/index.d.mts.map +1 -0
  7. package/dist/adapter-google-chat/index.mjs +1077 -0
  8. package/dist/adapter-google-chat/index.mjs.map +1 -0
  9. package/dist/cli/index.mjs +107 -14
  10. package/dist/cli/index.mjs.map +1 -1
  11. package/dist/cli/lite.mjs +175 -16
  12. package/dist/cli/lite.mjs.map +1 -1
  13. package/dist/cli/propose-policy.d.mts +1 -0
  14. package/dist/cli/propose-policy.mjs +7159 -0
  15. package/dist/cli/propose-policy.mjs.map +1 -0
  16. package/dist/daemon/index.d.mts.map +1 -1
  17. package/dist/daemon/index.mjs +1427 -513
  18. package/dist/daemon/index.mjs.map +1 -1
  19. package/dist/{lite-oSYSvaOr.mjs → lite-CBxOT1y5.mjs} +101 -24
  20. package/dist/lite-CBxOT1y5.mjs.map +1 -0
  21. package/dist/routing-D8rTxtaV.mjs +245 -0
  22. package/dist/routing-D8rTxtaV.mjs.map +1 -0
  23. package/dist/web/_app/immutable/assets/0.C-4eziNy.css +1 -0
  24. package/dist/web/_app/immutable/assets/4.Cc_xwLNl.css +1 -0
  25. package/dist/web/_app/immutable/chunks/B6YN0Nuq.js +1 -0
  26. package/dist/web/_app/immutable/chunks/{Dc-UOHw9.js → BmRlVmv6.js} +1 -1
  27. package/{web/.svelte-kit/output/client/_app/immutable/chunks/8YNcRyEk.js → dist/web/_app/immutable/chunks/C20lZMGz.js} +1 -1
  28. package/dist/web/_app/immutable/chunks/C9lbZ-kT.js +1 -0
  29. package/dist/web/_app/immutable/chunks/CK9JZLaG.js +2 -0
  30. package/dist/web/_app/immutable/chunks/CME08kGM.js +1 -0
  31. package/dist/web/_app/immutable/chunks/{BPy8HLo7.js → Ck-be5J2.js} +1 -1
  32. package/dist/web/_app/immutable/chunks/Ck3rYNON.js +1 -0
  33. package/dist/web/_app/immutable/chunks/DMtIqaiV.js +2 -0
  34. package/dist/web/_app/immutable/chunks/{B8yYFADm.js → DhD271EB.js} +1 -1
  35. package/dist/web/_app/immutable/chunks/{DcrmIfTj.js → DpuLqk8d.js} +1 -1
  36. package/dist/web/_app/immutable/chunks/{ZkLyk0mE.js → Drm9vgeP.js} +1 -1
  37. package/dist/web/_app/immutable/chunks/DsIToJCP.js +1 -0
  38. package/dist/web/_app/immutable/chunks/{CyNaE55B.js → Zeh-C-mx.js} +1 -1
  39. package/{web/.svelte-kit/output/client/_app/immutable/entry/app.DO5eYwVz.js → dist/web/_app/immutable/entry/app.BgB5VkRU.js} +2 -2
  40. package/dist/web/_app/immutable/entry/start.DuxJo6av.js +1 -0
  41. package/dist/web/_app/immutable/nodes/0.C9oFZP9h.js +1 -0
  42. package/dist/web/_app/immutable/nodes/1.BON2Wk6k.js +1 -0
  43. package/dist/web/_app/immutable/nodes/{2.CK3CLC0f.js → 2.BnwnD1Ki.js} +1 -1
  44. package/dist/web/_app/immutable/nodes/{3.ncP0xLO6.js → 3.CIs4tjjw.js} +1 -1
  45. package/dist/web/_app/immutable/nodes/4.DLarELN4.js +60 -0
  46. package/dist/web/_app/immutable/nodes/{5.BpJUN6QH.js → 5.CE_QKy_3.js} +1 -1
  47. package/dist/web/_app/version.json +1 -1
  48. package/dist/web/index.html +12 -12
  49. package/dist/{workspace-DjoNjhW0.mjs → workspace-BJmJBfKi.mjs} +103 -11
  50. package/dist/workspace-BJmJBfKi.mjs.map +1 -0
  51. package/docs/14_google_chat_adapter/development_log.md +40 -0
  52. package/docs/14_google_chat_adapter/notes.md +28 -0
  53. package/docs/14_google_chat_adapter/prd.md +35 -0
  54. package/docs/14_google_chat_adapter/questions.md +9 -0
  55. package/docs/14_google_chat_adapter/tickets.md +117 -0
  56. package/docs/15_sandbox_policies/tickets.md +33 -0
  57. package/docs/16_session_timeout/development_log.md +20 -0
  58. package/docs/16_session_timeout/notes.md +44 -0
  59. package/docs/16_session_timeout/prd.md +106 -0
  60. package/docs/16_session_timeout/questions.md +10 -0
  61. package/docs/16_session_timeout/tickets.md +64 -0
  62. package/docs/17_auto_approve_policy/development_log.md +29 -0
  63. package/docs/17_auto_approve_policy/notes.md +25 -0
  64. package/docs/17_auto_approve_policy/prd.md +34 -0
  65. package/docs/17_auto_approve_policy/questions.md +10 -0
  66. package/docs/17_auto_approve_policy/tickets.md +11 -0
  67. package/docs/18_clawmini_skills/development_log.md +36 -0
  68. package/docs/18_clawmini_skills/notes.md +8 -0
  69. package/docs/18_clawmini_skills/prd.md +45 -0
  70. package/docs/18_clawmini_skills/questions.md +10 -0
  71. package/docs/18_clawmini_skills/tickets.md +55 -0
  72. package/docs/19_subagents/development_log.md +69 -0
  73. package/docs/19_subagents/notes.md +18 -0
  74. package/docs/19_subagents/prd.md +156 -0
  75. package/docs/19_subagents/questions.md +13 -0
  76. package/docs/19_subagents/tickets.md +113 -0
  77. package/docs/20_chat_logs_cleanup/development_log.md +50 -0
  78. package/docs/20_chat_logs_cleanup/notes.md +43 -0
  79. package/docs/20_chat_logs_cleanup/prd.md +232 -0
  80. package/docs/20_chat_logs_cleanup/questions.md +2 -0
  81. package/docs/20_chat_logs_cleanup/tickets.md +98 -0
  82. package/docs/20_webui_markdown/development_log.md +36 -0
  83. package/docs/20_webui_markdown/notes.md +23 -0
  84. package/docs/20_webui_markdown/prd.md +49 -0
  85. package/docs/20_webui_markdown/questions.md +10 -0
  86. package/docs/20_webui_markdown/tickets.md +55 -0
  87. package/docs/21_adapter_filtering/development_log.md +29 -0
  88. package/docs/21_adapter_filtering/notes.md +25 -0
  89. package/docs/21_adapter_filtering/prd.md +44 -0
  90. package/docs/21_adapter_filtering/questions.md +12 -0
  91. package/docs/21_adapter_filtering/tickets.md +38 -0
  92. package/docs/21_built_in_routers/development_log.md +17 -0
  93. package/docs/21_built_in_routers/notes.md +27 -0
  94. package/docs/21_built_in_routers/prd.md +34 -0
  95. package/docs/21_built_in_routers/questions.md +4 -0
  96. package/docs/21_built_in_routers/tickets.md +25 -0
  97. package/docs/21_fancy_policies/development_log.md +38 -0
  98. package/docs/21_fancy_policies/notes.md +27 -0
  99. package/docs/21_fancy_policies/prd.md +58 -0
  100. package/docs/21_fancy_policies/questions.md +6 -0
  101. package/docs/21_fancy_policies/tickets.md +48 -0
  102. package/docs/22_adapter_multi_chat/development_log.md +76 -0
  103. package/docs/22_adapter_multi_chat/notes.md +42 -0
  104. package/docs/22_adapter_multi_chat/prd.md +76 -0
  105. package/docs/22_adapter_multi_chat/questions.md +16 -0
  106. package/docs/22_adapter_multi_chat/tickets.md +164 -0
  107. package/docs/23_custom_token_env/development_log.md +31 -0
  108. package/docs/23_custom_token_env/notes.md +16 -0
  109. package/docs/23_custom_token_env/prd.md +42 -0
  110. package/docs/23_custom_token_env/questions.md +8 -0
  111. package/docs/23_custom_token_env/tickets.md +54 -0
  112. package/docs/guides/discord_adapter_setup.md +15 -2
  113. package/docs/guides/google_chat_adapter_setup.md +145 -0
  114. package/napkin.md +5 -0
  115. package/package.json +7 -2
  116. package/src/adapter-discord/config.test.ts +27 -8
  117. package/src/adapter-discord/config.ts +6 -8
  118. package/src/adapter-discord/forwarder.test.ts +307 -114
  119. package/src/adapter-discord/forwarder.ts +260 -75
  120. package/src/adapter-discord/index.test.ts +278 -0
  121. package/src/adapter-discord/index.ts +160 -30
  122. package/src/adapter-discord/interactions.test.ts +96 -0
  123. package/src/adapter-discord/interactions.ts +156 -0
  124. package/src/adapter-discord/state.test.ts +9 -8
  125. package/src/adapter-discord/state.ts +51 -8
  126. package/src/adapter-google-chat/auth.test.ts +87 -0
  127. package/src/adapter-google-chat/auth.ts +132 -0
  128. package/src/adapter-google-chat/cards.ts +71 -0
  129. package/src/adapter-google-chat/client.test.ts +561 -0
  130. package/src/adapter-google-chat/client.ts +430 -0
  131. package/src/adapter-google-chat/config.test.ts +187 -0
  132. package/src/adapter-google-chat/config.ts +82 -0
  133. package/src/adapter-google-chat/cron.test.ts +143 -0
  134. package/src/adapter-google-chat/cron.ts +81 -0
  135. package/src/adapter-google-chat/forwarder.test.ts +537 -0
  136. package/src/adapter-google-chat/forwarder.ts +349 -0
  137. package/src/adapter-google-chat/index.test.ts +62 -0
  138. package/src/adapter-google-chat/index.ts +61 -0
  139. package/src/adapter-google-chat/state.test.ts +96 -0
  140. package/src/adapter-google-chat/state.ts +85 -0
  141. package/src/adapter-google-chat/subscriptions.ts +124 -0
  142. package/src/adapter-google-chat/upload.ts +88 -0
  143. package/src/adapter-google-chat/utils.test.ts +111 -0
  144. package/src/adapter-google-chat/utils.ts +133 -0
  145. package/src/cli/commands/init.ts +0 -7
  146. package/src/cli/commands/messages.ts +18 -3
  147. package/src/cli/commands/policies.ts +70 -0
  148. package/src/cli/commands/skills.ts +71 -0
  149. package/src/cli/commands/web-api/chats.ts +5 -1
  150. package/src/cli/e2e/basic.test.ts +1 -1
  151. package/src/cli/e2e/cron.test.ts +1 -1
  152. package/src/cli/e2e/daemon.test.ts +132 -4
  153. package/src/cli/e2e/export-lite-func.test.ts +54 -31
  154. package/src/cli/e2e/fallbacks.test.ts +8 -6
  155. package/src/cli/e2e/init.test.ts +7 -0
  156. package/src/cli/e2e/messages.test.ts +90 -55
  157. package/src/cli/e2e/propose-policy.test.ts +203 -0
  158. package/src/cli/e2e/requests.test.ts +15 -0
  159. package/src/cli/e2e/session-timeout.test.ts +192 -0
  160. package/src/cli/e2e/skills.test.ts +55 -0
  161. package/src/cli/e2e/slash-new.test.ts +93 -0
  162. package/src/cli/e2e/subagents.test.ts +106 -0
  163. package/src/cli/index.ts +4 -0
  164. package/src/cli/lite.ts +51 -11
  165. package/src/cli/propose-policy.ts +91 -0
  166. package/src/cli/subagent-commands.ts +215 -0
  167. package/src/daemon/agent/agent-context.ts +89 -0
  168. package/src/daemon/agent/agent-extractors.ts +68 -0
  169. package/src/daemon/agent/agent-runner.ts +153 -0
  170. package/src/daemon/agent/agent-session.ts +261 -0
  171. package/src/daemon/agent/chat-logger.test.ts +158 -0
  172. package/src/daemon/agent/chat-logger.ts +188 -0
  173. package/src/daemon/agent/task-scheduler.test.ts +202 -0
  174. package/src/daemon/agent/task-scheduler.ts +276 -0
  175. package/src/daemon/agent/types.ts +84 -0
  176. package/src/daemon/agent/utils.ts +7 -0
  177. package/src/daemon/api/agent-router.ts +166 -18
  178. package/src/daemon/api/index.test.ts +50 -18
  179. package/src/daemon/api/policy-request.test.ts +39 -2
  180. package/src/daemon/api/subagent-router.test.ts +108 -0
  181. package/src/daemon/api/subagent-router.ts +296 -0
  182. package/src/daemon/api/subagent-utils.test.ts +56 -0
  183. package/src/daemon/api/subagent-utils.ts +130 -0
  184. package/src/daemon/api/user-router.ts +30 -13
  185. package/src/daemon/auth.ts +1 -0
  186. package/src/daemon/chats.ts +6 -0
  187. package/src/daemon/cron.test.ts +66 -1
  188. package/src/daemon/cron.ts +35 -8
  189. package/src/daemon/index.ts +23 -0
  190. package/src/daemon/message-agent.test.ts +11 -25
  191. package/src/daemon/message-extraction.test.ts +10 -27
  192. package/src/daemon/message-fallbacks.test.ts +13 -35
  193. package/src/daemon/message-interruption.test.ts +70 -53
  194. package/src/daemon/message-jobs.test.ts +138 -0
  195. package/src/daemon/message-queue.test.ts +30 -43
  196. package/src/daemon/message-router.test.ts +12 -11
  197. package/src/daemon/message-session.test.ts +41 -28
  198. package/src/daemon/message-typing.test.ts +19 -6
  199. package/src/daemon/message.ts +103 -515
  200. package/src/daemon/policy-request-service.ts +8 -3
  201. package/src/daemon/policy-utils.ts +19 -1
  202. package/src/daemon/queue.ts +16 -0
  203. package/src/daemon/request-store.test.ts +4 -0
  204. package/src/daemon/routers/session-timeout.test.ts +122 -0
  205. package/src/daemon/routers/session-timeout.ts +71 -0
  206. package/src/daemon/routers/slash-new.ts +3 -1
  207. package/src/daemon/routers/slash-policies.test.ts +26 -13
  208. package/src/daemon/routers/slash-policies.ts +39 -29
  209. package/src/daemon/routers/types.ts +8 -0
  210. package/src/daemon/routers.ts +64 -2
  211. package/src/daemon/utils/spawn.ts +6 -8
  212. package/src/shared/adapters/commands.test.ts +155 -0
  213. package/src/shared/adapters/commands.ts +125 -0
  214. package/src/shared/adapters/filtering.test.ts +111 -0
  215. package/src/shared/adapters/filtering.ts +57 -0
  216. package/src/shared/adapters/routing.test.ts +144 -0
  217. package/src/shared/adapters/routing.ts +109 -0
  218. package/src/shared/agent-utils.ts +10 -0
  219. package/src/shared/chats.test.ts +145 -3
  220. package/src/shared/chats.ts +215 -18
  221. package/src/shared/config.ts +67 -15
  222. package/src/shared/lite.ts +22 -18
  223. package/src/shared/policies.ts +7 -0
  224. package/src/shared/workspace.test.ts +45 -1
  225. package/src/shared/workspace.ts +119 -6
  226. package/templates/debug/settings.json +5 -2
  227. package/templates/environments/cladding/env.json +2 -2
  228. package/templates/gemini/.gemini/hooks/check-subagents.mjs +23 -0
  229. package/templates/gemini/.gemini/hooks/clawmini-logging.sh +17 -0
  230. package/templates/gemini/.gemini/hooks/insert-pending.sh +9 -0
  231. package/templates/gemini/.gemini/settings.json +50 -0
  232. package/templates/gemini/settings.json +22 -8
  233. package/templates/gemini-claw/.gemini/base-system.md +100 -0
  234. package/templates/gemini-claw/.gemini/hooks/check-subagents.mjs +23 -0
  235. package/templates/gemini-claw/.gemini/hooks/clawmini-logging.sh +1 -1
  236. package/templates/gemini-claw/.gemini/settings.json +13 -0
  237. package/templates/gemini-claw/.gemini/subagent-system.md +7 -0
  238. package/templates/gemini-claw/.gemini/system.md +3 -99
  239. package/templates/gemini-claw/settings.json +27 -22
  240. package/templates/skills/clawmini-requests/SKILL.md +92 -0
  241. package/templates/skills/clawmini-subagents/SKILL.md +79 -0
  242. package/templates/skills/skill-creator/SKILL.md +60 -0
  243. package/tsdown.config.ts +10 -1
  244. package/web/.svelte-kit/generated/server/internal.js +2 -1
  245. package/web/.svelte-kit/non-ambient.d.ts +2 -0
  246. package/web/.svelte-kit/output/client/.vite/manifest.json +141 -138
  247. package/web/.svelte-kit/output/client/_app/immutable/assets/0.C-4eziNy.css +1 -0
  248. package/web/.svelte-kit/output/client/_app/immutable/assets/4.Cc_xwLNl.css +1 -0
  249. package/web/.svelte-kit/output/client/_app/immutable/chunks/B6YN0Nuq.js +1 -0
  250. package/web/.svelte-kit/output/client/_app/immutable/chunks/{Dc-UOHw9.js → BmRlVmv6.js} +1 -1
  251. package/{dist/web/_app/immutable/chunks/8YNcRyEk.js → web/.svelte-kit/output/client/_app/immutable/chunks/C20lZMGz.js} +1 -1
  252. package/web/.svelte-kit/output/client/_app/immutable/chunks/C9lbZ-kT.js +1 -0
  253. package/web/.svelte-kit/output/client/_app/immutable/chunks/CK9JZLaG.js +2 -0
  254. package/web/.svelte-kit/output/client/_app/immutable/chunks/CME08kGM.js +1 -0
  255. package/web/.svelte-kit/output/client/_app/immutable/chunks/{BPy8HLo7.js → Ck-be5J2.js} +1 -1
  256. package/web/.svelte-kit/output/client/_app/immutable/chunks/Ck3rYNON.js +1 -0
  257. package/web/.svelte-kit/output/client/_app/immutable/chunks/DMtIqaiV.js +2 -0
  258. package/web/.svelte-kit/output/client/_app/immutable/chunks/{B8yYFADm.js → DhD271EB.js} +1 -1
  259. package/web/.svelte-kit/output/client/_app/immutable/chunks/{DcrmIfTj.js → DpuLqk8d.js} +1 -1
  260. package/web/.svelte-kit/output/client/_app/immutable/chunks/{ZkLyk0mE.js → Drm9vgeP.js} +1 -1
  261. package/web/.svelte-kit/output/client/_app/immutable/chunks/DsIToJCP.js +1 -0
  262. package/web/.svelte-kit/output/client/_app/immutable/chunks/{CyNaE55B.js → Zeh-C-mx.js} +1 -1
  263. package/{dist/web/_app/immutable/entry/app.DO5eYwVz.js → web/.svelte-kit/output/client/_app/immutable/entry/app.BgB5VkRU.js} +2 -2
  264. package/web/.svelte-kit/output/client/_app/immutable/entry/start.DuxJo6av.js +1 -0
  265. package/web/.svelte-kit/output/client/_app/immutable/nodes/0.C9oFZP9h.js +1 -0
  266. package/web/.svelte-kit/output/client/_app/immutable/nodes/1.BON2Wk6k.js +1 -0
  267. package/web/.svelte-kit/output/client/_app/immutable/nodes/{2.CK3CLC0f.js → 2.BnwnD1Ki.js} +1 -1
  268. package/web/.svelte-kit/output/client/_app/immutable/nodes/{3.ncP0xLO6.js → 3.CIs4tjjw.js} +1 -1
  269. package/web/.svelte-kit/output/client/_app/immutable/nodes/4.DLarELN4.js +60 -0
  270. package/web/.svelte-kit/output/client/_app/immutable/nodes/{5.BpJUN6QH.js → 5.CE_QKy_3.js} +1 -1
  271. package/web/.svelte-kit/output/client/_app/version.json +1 -1
  272. package/web/.svelte-kit/output/server/.vite/manifest.json +12 -3
  273. package/web/.svelte-kit/output/server/_app/immutable/assets/_layout.C-4eziNy.css +1 -0
  274. package/web/.svelte-kit/output/server/_app/immutable/assets/_page.Cc_xwLNl.css +1 -0
  275. package/web/.svelte-kit/output/server/chunks/app-state.svelte.js +5 -0
  276. package/web/.svelte-kit/output/server/chunks/bot.js +4 -4
  277. package/web/.svelte-kit/output/server/chunks/client.js +2 -1
  278. package/web/.svelte-kit/output/server/chunks/exports.js +0 -1
  279. package/web/.svelte-kit/output/server/chunks/internal.js +2 -1
  280. package/web/.svelte-kit/output/server/chunks/root.js +482 -392
  281. package/web/.svelte-kit/output/server/entries/pages/_layout.svelte.js +57 -7
  282. package/web/.svelte-kit/output/server/entries/pages/chats/_id_/_page.svelte.js +234 -9
  283. package/web/.svelte-kit/output/server/index.js +82 -10
  284. package/web/.svelte-kit/output/server/manifest-full.js +1 -1
  285. package/web/.svelte-kit/output/server/manifest.js +1 -1
  286. package/web/.svelte-kit/output/server/nodes/0.js +2 -2
  287. package/web/.svelte-kit/output/server/nodes/1.js +1 -1
  288. package/web/.svelte-kit/output/server/nodes/2.js +1 -1
  289. package/web/.svelte-kit/output/server/nodes/3.js +1 -1
  290. package/web/.svelte-kit/output/server/nodes/4.js +2 -2
  291. package/web/.svelte-kit/output/server/nodes/5.js +1 -1
  292. package/web/.svelte-kit/types/src/routes/$types.d.ts +1 -2
  293. package/web/.svelte-kit/types/src/routes/agents/$types.d.ts +1 -2
  294. package/web/.svelte-kit/types/src/routes/chats/[id]/$types.d.ts +1 -2
  295. package/web/.svelte-kit/types/src/routes/chats/[id]/settings/$types.d.ts +1 -2
  296. package/web/package.json +8 -0
  297. package/web/src/lib/app-state.svelte.ts +5 -1
  298. package/web/src/lib/components/app/markdown-renderer.svelte +56 -0
  299. package/web/src/lib/components/app/markdown-renderer.svelte.spec.ts +44 -0
  300. package/web/src/lib/components/app/message-content.svelte +16 -0
  301. package/web/src/lib/types.ts +67 -3
  302. package/web/src/routes/+layout.svelte +31 -1
  303. package/web/src/routes/chats/[id]/+page.svelte +167 -18
  304. package/web/src/routes/chats/[id]/page.svelte.spec.ts +58 -7
  305. package/dist/lite-oSYSvaOr.mjs.map +0 -1
  306. package/dist/web/_app/immutable/assets/0.GI4C4dpV.css +0 -1
  307. package/dist/web/_app/immutable/chunks/B5abRDXp.js +0 -1
  308. package/dist/web/_app/immutable/chunks/Bi0jeV7Q.js +0 -1
  309. package/dist/web/_app/immutable/chunks/BmUXQ3wy.js +0 -2
  310. package/dist/web/_app/immutable/chunks/C3k55nDF.js +0 -1
  311. package/dist/web/_app/immutable/chunks/CpaGRn9L.js +0 -1
  312. package/dist/web/_app/immutable/chunks/DG5RZBw-.js +0 -2
  313. package/dist/web/_app/immutable/chunks/DQoygso7.js +0 -1
  314. package/dist/web/_app/immutable/entry/start.D48mVn1m.js +0 -1
  315. package/dist/web/_app/immutable/nodes/0.B-0CcADM.js +0 -1
  316. package/dist/web/_app/immutable/nodes/1.FixKgvRO.js +0 -1
  317. package/dist/web/_app/immutable/nodes/4.CQYJEgv8.js +0 -1
  318. package/dist/workspace-DjoNjhW0.mjs.map +0 -1
  319. package/src/daemon/message-verbosity.test.ts +0 -127
  320. package/web/.svelte-kit/output/client/_app/immutable/assets/0.GI4C4dpV.css +0 -1
  321. package/web/.svelte-kit/output/client/_app/immutable/chunks/B5abRDXp.js +0 -1
  322. package/web/.svelte-kit/output/client/_app/immutable/chunks/Bi0jeV7Q.js +0 -1
  323. package/web/.svelte-kit/output/client/_app/immutable/chunks/BmUXQ3wy.js +0 -2
  324. package/web/.svelte-kit/output/client/_app/immutable/chunks/C3k55nDF.js +0 -1
  325. package/web/.svelte-kit/output/client/_app/immutable/chunks/CpaGRn9L.js +0 -1
  326. package/web/.svelte-kit/output/client/_app/immutable/chunks/DG5RZBw-.js +0 -2
  327. package/web/.svelte-kit/output/client/_app/immutable/chunks/DQoygso7.js +0 -1
  328. package/web/.svelte-kit/output/client/_app/immutable/entry/start.D48mVn1m.js +0 -1
  329. package/web/.svelte-kit/output/client/_app/immutable/nodes/0.B-0CcADM.js +0 -1
  330. package/web/.svelte-kit/output/client/_app/immutable/nodes/1.FixKgvRO.js +0 -1
  331. package/web/.svelte-kit/output/client/_app/immutable/nodes/4.CQYJEgv8.js +0 -1
  332. package/web/.svelte-kit/output/server/_app/immutable/assets/_layout.GI4C4dpV.css +0 -1
  333. /package/templates/{gemini-claw/.gemini/skills → skills}/clawmini-jobs/SKILL.md +0 -0
@@ -0,0 +1,153 @@
1
+ import { emitTyping } from '../events.js';
2
+ import type { ExecutionResponse, Message, RunCommandFn } from './types.js';
3
+ import { type Fallback } from './agent-context.js';
4
+ import { extractMessageContent, extractSessionId } from './agent-extractors.js';
5
+ import type { AgentSession } from './agent-session.js';
6
+ import { isNewSession } from './utils.js';
7
+
8
+ export function calculateDelay(
9
+ attempt: number,
10
+ baseDelayMs: number,
11
+ isFallback: boolean = false
12
+ ): number {
13
+ const effectiveAttempt = isFallback ? attempt + 1 : attempt;
14
+ if (effectiveAttempt <= 0) return 0;
15
+ const delay = baseDelayMs * Math.pow(2, effectiveAttempt - 1);
16
+ return Math.min(delay, 15000);
17
+ }
18
+
19
+ const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
20
+
21
+ export class AgentRunner {
22
+ constructor(
23
+ private readonly session: AgentSession,
24
+ private readonly runCommand: RunCommandFn
25
+ ) {}
26
+
27
+ private async withTypingIndicator<T>(fn: () => Promise<T>): Promise<T> {
28
+ const interval = setInterval(() => emitTyping(this.session.chatId), 5000);
29
+ try {
30
+ return await fn();
31
+ } finally {
32
+ clearInterval(interval);
33
+ }
34
+ }
35
+
36
+ private *getExecutionAttempts() {
37
+ const fallbacks = this.session.settings.fallbacks || [];
38
+ const executionConfigs = [
39
+ { fallback: undefined, retries: 0, delayMs: 1000 },
40
+ ...fallbacks.map((f) => ({ fallback: f, retries: f.retries, delayMs: f.delayMs })),
41
+ ];
42
+
43
+ for (let configIdx = 0; configIdx < executionConfigs.length; configIdx++) {
44
+ const config = executionConfigs[configIdx]!;
45
+ const isFallbackConfig = configIdx > 0;
46
+
47
+ for (let attempt = 0; attempt <= config.retries; attempt++) {
48
+ yield {
49
+ fallback: config.fallback,
50
+ delay: calculateDelay(attempt, config.delayMs, isFallbackConfig),
51
+ };
52
+ }
53
+ }
54
+ }
55
+
56
+ private async executeSingleAttempt(
57
+ message: Message,
58
+ fallback?: Fallback | undefined,
59
+ signal?: AbortSignal | undefined
60
+ ): Promise<{ success: boolean; response?: ExecutionResponse }> {
61
+ const context = await this.session.buildExecutionContext(
62
+ message.content,
63
+ message.env,
64
+ fallback
65
+ );
66
+
67
+ if (!context) return { success: false };
68
+
69
+ const mainResult = await this.withTypingIndicator(() =>
70
+ this.runCommand({
71
+ command: context.command,
72
+ cwd: this.session.workDirectory,
73
+ env: context.env,
74
+ signal,
75
+ })
76
+ );
77
+
78
+ let success = mainResult.exitCode === 0;
79
+ let finalContent = mainResult.stdout.trim();
80
+ const additonalErrors = [];
81
+
82
+ if (success && context.currentAgent.commands?.getMessageContent) {
83
+ const extraction = await extractMessageContent(
84
+ context,
85
+ mainResult,
86
+ this.runCommand,
87
+ this.session.workDirectory,
88
+ signal
89
+ );
90
+ if (extraction.error) additonalErrors.push(extraction.error);
91
+ if (extraction.result !== undefined) finalContent = extraction.result.trim();
92
+ if (!finalContent) success = false;
93
+ }
94
+
95
+ let extractedSessionId: string | undefined;
96
+
97
+ if (success && isNewSession(message.env) && context.currentAgent.commands?.getSessionId) {
98
+ const extraction = await extractSessionId(
99
+ context,
100
+ mainResult,
101
+ this.runCommand,
102
+ this.session.workDirectory,
103
+ signal
104
+ );
105
+ if (extraction.error) additonalErrors.push(extraction.error);
106
+ if (extraction.result) {
107
+ extractedSessionId = extraction.result;
108
+ }
109
+ }
110
+
111
+ return {
112
+ success,
113
+ response: {
114
+ messageId: message.id,
115
+ content: finalContent,
116
+ command: context.command,
117
+ cwd: this.session.workDirectory,
118
+ extractedSessionId,
119
+ result: {
120
+ ...mainResult,
121
+ stderr: [mainResult.stderr, ...additonalErrors].join('\n\n'),
122
+ },
123
+ },
124
+ };
125
+ }
126
+
127
+ async executeWithFallbacks(
128
+ message: Message,
129
+ signal?: AbortSignal | undefined
130
+ ): Promise<ExecutionResponse | undefined> {
131
+ let lastResponse: ExecutionResponse | undefined;
132
+
133
+ for (const attempt of this.getExecutionAttempts()) {
134
+ if (attempt.delay > 0) {
135
+ await this.session.logger.logCommandRetry({
136
+ messageId: message.id,
137
+ content: `Error running agent, retrying in ${Math.round(attempt.delay / 1000)} seconds...`,
138
+ cwd: this.session.workDirectory,
139
+ });
140
+ await sleep(attempt.delay);
141
+ }
142
+
143
+ const attemptResult = await this.executeSingleAttempt(message, attempt.fallback, signal);
144
+
145
+ lastResponse = attemptResult.response || lastResponse;
146
+ if (attemptResult.success) {
147
+ return lastResponse;
148
+ }
149
+ }
150
+
151
+ return lastResponse;
152
+ }
153
+ }
@@ -0,0 +1,261 @@
1
+ import type { Agent, Settings } from '../../shared/config.js';
2
+ import { AgentRunner } from './agent-runner.js';
3
+ import type { Logger, Message } from './types.js';
4
+ import { runCommand } from '../utils/spawn.js';
5
+ import {
6
+ getAgent,
7
+ getWorkspaceRoot,
8
+ readAgentSessionSettings,
9
+ writeAgentSessionSettings,
10
+ readSettings,
11
+ resolveAgentWorkDir,
12
+ } from '../../shared/workspace.js';
13
+ import { formatPendingMessages, isNewSession } from './utils.js';
14
+ import { createChatLogger } from './chat-logger.js';
15
+ import { sandboxExecutionContext, type Fallback } from './agent-context.js';
16
+ import { applyEnvOverrides, getActiveEnvKeys } from '../../shared/utils/env.js';
17
+ import { getApiContext, generateToken } from '../auth.js';
18
+ import { taskScheduler } from './task-scheduler.js';
19
+ import { randomUUID } from 'node:crypto';
20
+
21
+ export class AgentSession {
22
+ public readonly agentId: string;
23
+ public readonly sessionId: string;
24
+ public readonly chatId: string;
25
+ public readonly subagentId: string | undefined;
26
+ public readonly settings: Agent;
27
+ public readonly workspaceRoot: string;
28
+ public readonly globalSettings: Settings | undefined;
29
+ public readonly logger: Logger;
30
+
31
+ constructor(config: {
32
+ agentId: string;
33
+ sessionId: string;
34
+ chatId: string;
35
+ subagentId?: string;
36
+ settings: Agent;
37
+ workspaceRoot: string;
38
+ globalSettings: Settings | undefined;
39
+ logger?: Logger;
40
+ }) {
41
+ this.agentId = config.agentId;
42
+ this.sessionId = config.sessionId;
43
+ this.chatId = config.chatId;
44
+ this.subagentId = config.subagentId;
45
+ this.settings = config.settings;
46
+ this.workspaceRoot = config.workspaceRoot;
47
+ this.globalSettings = config.globalSettings;
48
+
49
+ this.logger = config.logger ?? createChatLogger(this.chatId, this.subagentId);
50
+ }
51
+
52
+ async buildExecutionContext(
53
+ messageContent: string,
54
+ routerEnv: Record<string, string>,
55
+ fallback?: Fallback
56
+ ): Promise<{ command: string; env: Record<string, string>; currentAgent: Agent } | null> {
57
+ const currentAgent: Agent = {
58
+ ...this.settings,
59
+ commands: {
60
+ ...this.settings.commands,
61
+ ...(fallback?.commands || {}),
62
+ },
63
+ env: {
64
+ ...this.settings.env,
65
+ ...(this.subagentId && this.settings.subagentEnv ? this.settings.subagentEnv : {}),
66
+ ...(fallback?.env || {}),
67
+ },
68
+ };
69
+
70
+ let initialCommand = currentAgent.commands?.new ?? '';
71
+ const env = {
72
+ ...process.env,
73
+ CLAW_CLI_MESSAGE: messageContent,
74
+ } as Record<string, string>;
75
+
76
+ applyEnvOverrides(env, currentAgent.env);
77
+
78
+ if (!isNewSession(routerEnv) && currentAgent.commands?.append) {
79
+ initialCommand = currentAgent.commands.append;
80
+ }
81
+
82
+ if (!initialCommand) {
83
+ return null;
84
+ }
85
+
86
+ const agentSpecificEnvKeys = getActiveEnvKeys(currentAgent.env);
87
+ agentSpecificEnvKeys.add('CLAW_CLI_MESSAGE');
88
+
89
+ Object.assign(env, routerEnv);
90
+ Object.keys(routerEnv).forEach((k) => agentSpecificEnvKeys.add(k));
91
+
92
+ const apiCtx = getApiContext(this.globalSettings);
93
+ if (apiCtx) {
94
+ const proxyUrl = apiCtx.proxy_host
95
+ ? `${apiCtx.proxy_host}:${apiCtx.port}`
96
+ : `http://${apiCtx.host}:${apiCtx.port}`;
97
+
98
+ if (currentAgent.apiUrlEnvVar) {
99
+ env[currentAgent.apiUrlEnvVar] = proxyUrl;
100
+ agentSpecificEnvKeys.add(currentAgent.apiUrlEnvVar);
101
+ env['CLAW_LITE_URL_VAR'] = currentAgent.apiUrlEnvVar;
102
+ agentSpecificEnvKeys.add('CLAW_LITE_URL_VAR');
103
+ } else {
104
+ env['CLAW_API_URL'] = proxyUrl;
105
+ agentSpecificEnvKeys.add('CLAW_API_URL');
106
+ }
107
+
108
+ const token = generateToken({
109
+ chatId: this.chatId,
110
+ agentId: this.agentId,
111
+ sessionId: this.sessionId,
112
+ ...(this.subagentId ? { subagentId: this.subagentId } : {}),
113
+ timestamp: Date.now(),
114
+ });
115
+
116
+ if (currentAgent.apiTokenEnvVar) {
117
+ env[currentAgent.apiTokenEnvVar] = token;
118
+ agentSpecificEnvKeys.add(currentAgent.apiTokenEnvVar);
119
+ env['CLAW_LITE_API_VAR'] = currentAgent.apiTokenEnvVar;
120
+ agentSpecificEnvKeys.add('CLAW_LITE_API_VAR');
121
+ } else {
122
+ env['CLAW_API_TOKEN'] = token;
123
+ agentSpecificEnvKeys.add('CLAW_API_TOKEN');
124
+ }
125
+ }
126
+
127
+ let command = initialCommand;
128
+ command = await sandboxExecutionContext(
129
+ command,
130
+ env,
131
+ agentSpecificEnvKeys,
132
+ this.workDirectory,
133
+ this.workspaceRoot
134
+ );
135
+
136
+ return { command, env, currentAgent };
137
+ }
138
+
139
+ createRunner(): AgentRunner {
140
+ return new AgentRunner(this, runCommand);
141
+ }
142
+
143
+ get workDirectory(): string {
144
+ return resolveAgentWorkDir(this.agentId, this.settings.directory, this.workspaceRoot);
145
+ }
146
+
147
+ stop() {
148
+ taskScheduler.abortTasks(this.sessionId);
149
+ }
150
+
151
+ interrupt(message: Message): Message {
152
+ const payloads = taskScheduler.interruptTasks(this.sessionId);
153
+
154
+ if (payloads.length > 0) {
155
+ // TODO: Figure out how to handle merging payloads when they have different env settings or other config.
156
+ // Currently, we only preserve the text content and drop any specific configuration attached to individual messages.
157
+ const pendingText = formatPendingMessages(payloads);
158
+ return {
159
+ ...message,
160
+ content: `${pendingText}\n\n<message>\n${message.content}\n</message>`.trim(),
161
+ };
162
+ }
163
+ return message;
164
+ }
165
+
166
+ async handleMessage(message: Message): Promise<void> {
167
+ if (!message.content.trim()) {
168
+ return;
169
+ }
170
+
171
+ await taskScheduler.schedule({
172
+ id: `task-${this.agentId}-${randomUUID()}`,
173
+ rootChatId: this.chatId,
174
+ dirPath: this.workDirectory,
175
+ sessionId: this.sessionId,
176
+ text: message.content,
177
+ execute: async (signal) => {
178
+ // Refresh sessionSettings immediately before execution
179
+ const sessionSettings = await readAgentSessionSettings(
180
+ this.agentId,
181
+ this.sessionId,
182
+ this.workspaceRoot
183
+ );
184
+ // TODO: create a copy of the message first
185
+ applyEnvOverrides(message.env, sessionSettings?.env);
186
+
187
+ const runner = this.createRunner();
188
+ const result = await runner.executeWithFallbacks(message, signal);
189
+ if (!result) {
190
+ // TODO: throw an error? Log an error?
191
+ return;
192
+ }
193
+
194
+ if (result.extractedSessionId) {
195
+ await writeAgentSessionSettings(
196
+ this.agentId,
197
+ this.sessionId,
198
+ { env: { SESSION_ID: result.extractedSessionId } },
199
+ this.workspaceRoot
200
+ );
201
+ }
202
+
203
+ await this.logger.logCommandResult(result);
204
+
205
+ if (!result.content.includes('NO_REPLY_NECESSARY')) {
206
+ await this.logger.logAgentReply({ content: result.content });
207
+ }
208
+ },
209
+ });
210
+ }
211
+ }
212
+
213
+ export async function createAgentSession(options: {
214
+ chatId: string;
215
+ agentId: string;
216
+ sessionId: string;
217
+ subagentId?: string;
218
+ cwd: string;
219
+ settings?: Settings | undefined;
220
+ logger?: Logger;
221
+ }) {
222
+ // TODO: make it so that readSettings returns Settings|undefined
223
+ const settings = options.settings ?? (await readSettings(options.cwd)) ?? undefined;
224
+ const mergedAgent = await resolveMergedAgent(options.agentId, settings, options.cwd);
225
+ const workspaceRoot = getWorkspaceRoot(options.cwd);
226
+
227
+ return new AgentSession({
228
+ agentId: options.agentId,
229
+ sessionId: options.sessionId,
230
+ chatId: options.chatId,
231
+ ...(options.subagentId ? { subagentId: options.subagentId } : {}),
232
+ settings: mergedAgent,
233
+ workspaceRoot,
234
+ globalSettings: settings,
235
+ ...(options.logger ? { logger: options.logger } : {}),
236
+ });
237
+ }
238
+
239
+ async function resolveMergedAgent(
240
+ agentId: string,
241
+ settings: Settings | undefined,
242
+ cwd: string
243
+ ): Promise<Agent> {
244
+ let mergedAgent: Agent = settings?.defaultAgent || {};
245
+ if (agentId !== 'default') {
246
+ try {
247
+ const customAgent = await getAgent(agentId, cwd);
248
+ if (customAgent) {
249
+ mergedAgent = {
250
+ ...mergedAgent,
251
+ ...customAgent,
252
+ commands: { ...mergedAgent.commands, ...customAgent.commands },
253
+ env: { ...mergedAgent.env, ...customAgent.env },
254
+ };
255
+ }
256
+ } catch {
257
+ // Fall back to default if agent not found
258
+ }
259
+ }
260
+ return mergedAgent;
261
+ }
@@ -0,0 +1,158 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { createChatLogger } from './chat-logger.js';
3
+ import * as daemonChats from '../chats.js';
4
+ import { type ChatMessage } from '../chats.js';
5
+
6
+ vi.mock('../chats.js', async () => {
7
+ const actual = await vi.importActual('../chats.js');
8
+ return {
9
+ ...actual,
10
+ appendMessage: vi.fn(),
11
+ getMessages: vi.fn(),
12
+ };
13
+ });
14
+
15
+ describe('ChatLogger', () => {
16
+ beforeEach(() => {
17
+ vi.clearAllMocks();
18
+ });
19
+
20
+ describe('createChatLogger', () => {
21
+ it('should create a standard logger without subagentId', async () => {
22
+ const logger = createChatLogger('chat-1');
23
+ await logger.logUserMessage('hello');
24
+
25
+ expect(daemonChats.appendMessage).toHaveBeenCalledWith(
26
+ 'chat-1',
27
+ expect.objectContaining({ role: 'user', content: 'hello' })
28
+ );
29
+ });
30
+
31
+ it('should inject subagentId into outgoing messages', async () => {
32
+ const logger = createChatLogger('chat-1', 'sub-1');
33
+ await logger.logUserMessage('hello subagent');
34
+
35
+ expect(daemonChats.appendMessage).toHaveBeenCalledWith(
36
+ 'chat-1',
37
+ expect.objectContaining({ role: 'user', content: 'hello subagent', subagentId: 'sub-1' })
38
+ );
39
+ });
40
+
41
+ it('should filter incoming logs for the subagent', async () => {
42
+ const mockMessages: ChatMessage[] = [
43
+ { id: '1', role: 'user', content: 'root msg', timestamp: '1' },
44
+ { id: '2', role: 'user', content: 'sub msg', timestamp: '2', subagentId: 'sub-1' },
45
+ { id: '3', role: 'user', content: 'other sub', timestamp: '3', subagentId: 'sub-2' },
46
+ ];
47
+ vi.mocked(daemonChats.getMessages).mockResolvedValue(mockMessages);
48
+
49
+ const logger = createChatLogger('chat-1', 'sub-1');
50
+ const filtered = await logger.getMessages();
51
+
52
+ expect(filtered).toHaveLength(1);
53
+ expect(filtered[0]!.id).toBe('2');
54
+ expect(daemonChats.getMessages).toHaveBeenCalledWith('chat-1');
55
+ });
56
+
57
+ it('should limit messages after filtering', async () => {
58
+ const mockMessages: ChatMessage[] = [
59
+ { id: '1', role: 'user', content: 'root msg', timestamp: '1' },
60
+ { id: '2', role: 'user', content: 'sub msg 1', timestamp: '2', subagentId: 'sub-1' },
61
+ { id: '3', role: 'user', content: 'other sub', timestamp: '3', subagentId: 'sub-2' },
62
+ { id: '4', role: 'user', content: 'sub msg 2', timestamp: '4', subagentId: 'sub-1' },
63
+ ];
64
+ vi.mocked(daemonChats.getMessages).mockResolvedValue(mockMessages);
65
+
66
+ const logger = createChatLogger('chat-1', 'sub-1');
67
+ const filtered = await logger.getMessages(1);
68
+
69
+ expect(filtered).toHaveLength(1);
70
+ expect(filtered[0]!.id).toBe('4');
71
+ });
72
+
73
+ it('should not return subagent messages if no subagentId', async () => {
74
+ const mockMessages: ChatMessage[] = [
75
+ { id: '1', role: 'user', content: 'root msg', timestamp: '1' },
76
+ { id: '2', role: 'user', content: 'sub msg 1', timestamp: '2', subagentId: 'sub-1' },
77
+ ];
78
+ vi.mocked(daemonChats.getMessages).mockResolvedValue(mockMessages);
79
+
80
+ const logger = createChatLogger('chat-1');
81
+ const filtered = await logger.getMessages();
82
+
83
+ expect(filtered).toHaveLength(1);
84
+ expect(filtered[0]!.id).toBe('1');
85
+ });
86
+
87
+ it('should log system message correctly', async () => {
88
+ const logger = createChatLogger('chat-1');
89
+ await logger.logSystemMessage({ content: 'test', event: 'cron', messageId: 'msg-1' });
90
+
91
+ expect(daemonChats.appendMessage).toHaveBeenCalledWith(
92
+ 'chat-1',
93
+ expect.objectContaining({
94
+ role: 'system',
95
+ content: 'test',
96
+ event: 'cron',
97
+ messageId: 'msg-1',
98
+ })
99
+ );
100
+ });
101
+
102
+ it('should log agent reply correctly', async () => {
103
+ const logger = createChatLogger('chat-1');
104
+ await logger.logAgentReply({ content: 'reply', files: ['test.txt'] });
105
+
106
+ expect(daemonChats.appendMessage).toHaveBeenCalledWith(
107
+ 'chat-1',
108
+ expect.objectContaining({ role: 'agent', content: 'reply', files: ['test.txt'] })
109
+ );
110
+ });
111
+
112
+ it('should log tool message correctly', async () => {
113
+ const logger = createChatLogger('chat-1');
114
+ await logger.logToolMessage({
115
+ content: 'tool content',
116
+ messageId: 'msg-1',
117
+ name: 'myTool',
118
+ payload: { a: 1 },
119
+ });
120
+
121
+ expect(daemonChats.appendMessage).toHaveBeenCalledWith(
122
+ 'chat-1',
123
+ expect.objectContaining({
124
+ role: 'tool',
125
+ content: 'tool content',
126
+ messageId: 'msg-1',
127
+ name: 'myTool',
128
+ payload: { a: 1 },
129
+ })
130
+ );
131
+ });
132
+
133
+ it('should log policy request correctly', async () => {
134
+ const logger = createChatLogger('chat-1');
135
+ await logger.logPolicyRequestMessage({
136
+ content: 'please allow',
137
+ messageId: 'msg-1',
138
+ requestId: 'req-1',
139
+ commandName: 'ls',
140
+ args: ['-la'],
141
+ status: 'pending',
142
+ });
143
+
144
+ expect(daemonChats.appendMessage).toHaveBeenCalledWith(
145
+ 'chat-1',
146
+ expect.objectContaining({
147
+ role: 'policy',
148
+ content: 'please allow',
149
+ messageId: 'msg-1',
150
+ requestId: 'req-1',
151
+ commandName: 'ls',
152
+ args: ['-la'],
153
+ status: 'pending',
154
+ })
155
+ );
156
+ });
157
+ });
158
+ });