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