clawmini 0.0.7 → 0.0.9

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 (367) hide show
  1. package/.changeset/README.md +8 -0
  2. package/.changeset/config.json +14 -0
  3. package/.github/workflows/release.yml +49 -0
  4. package/CHANGELOG.md +36 -0
  5. package/README.md +5 -4
  6. package/dist/adapter-discord/index.d.mts.map +1 -1
  7. package/dist/adapter-discord/index.mjs +465 -282
  8. package/dist/adapter-discord/index.mjs.map +1 -1
  9. package/dist/adapter-google-chat/index.mjs +367 -243
  10. package/dist/adapter-google-chat/index.mjs.map +1 -1
  11. package/dist/cli/index.mjs +684 -24
  12. package/dist/cli/index.mjs.map +1 -1
  13. package/dist/cli/lite.mjs +43 -13
  14. package/dist/cli/lite.mjs.map +1 -1
  15. package/dist/cli/{propose-policy.mjs → manage-policies.mjs} +270 -47
  16. package/dist/cli/manage-policies.mjs.map +1 -0
  17. package/dist/cli/run-host.d.mts +1 -0
  18. package/dist/cli/run-host.mjs +3090 -0
  19. package/dist/cli/run-host.mjs.map +1 -0
  20. package/dist/config-CPFQIGdG.mjs +57 -0
  21. package/dist/config-CPFQIGdG.mjs.map +1 -0
  22. package/dist/config-Dvl-Pov4.mjs +76 -0
  23. package/dist/config-Dvl-Pov4.mjs.map +1 -0
  24. package/dist/daemon/index.d.mts.map +1 -1
  25. package/dist/daemon/index.mjs +970 -332
  26. package/dist/daemon/index.mjs.map +1 -1
  27. package/dist/supervisor-actions-CiW56eLi.mjs +843 -0
  28. package/dist/supervisor-actions-CiW56eLi.mjs.map +1 -0
  29. package/dist/turn-log-buffer-DRgW53gl.mjs +767 -0
  30. package/dist/turn-log-buffer-DRgW53gl.mjs.map +1 -0
  31. package/dist/web/_app/immutable/chunks/{Drm9vgeP.js → 3AZlWB6U.js} +1 -1
  32. package/dist/web/_app/immutable/chunks/BhRSsUCh.js +2 -0
  33. package/dist/web/_app/immutable/chunks/BiLeM2i1.js +1 -0
  34. package/{web/.svelte-kit/output/client/_app/immutable/chunks/CME08kGM.js → dist/web/_app/immutable/chunks/BmBj85Ll.js} +1 -1
  35. package/dist/web/_app/immutable/chunks/BrERcKAH.js +1 -0
  36. package/dist/web/_app/immutable/chunks/Bv9252RM.js +1 -0
  37. package/dist/web/_app/immutable/chunks/CIXNBPKi.js +1 -0
  38. package/dist/web/_app/immutable/chunks/DISKL3GN.js +2 -0
  39. package/dist/web/_app/immutable/chunks/{Zeh-C-mx.js → DcpaLzmX.js} +1 -1
  40. package/dist/web/_app/immutable/chunks/DnQ3vS13.js +1 -0
  41. package/dist/web/_app/immutable/chunks/KsloHTKS.js +1 -0
  42. package/{web/.svelte-kit/output/client/_app/immutable/chunks/Ck-be5J2.js → dist/web/_app/immutable/chunks/RsHsUj-8.js} +2 -2
  43. package/dist/web/_app/immutable/chunks/{G_zz-Gou.js → wpfV79dV.js} +1 -1
  44. package/dist/web/_app/immutable/entry/app.CIw1Qj0n.js +2 -0
  45. package/dist/web/_app/immutable/entry/start.Di0-Jhte.js +1 -0
  46. package/dist/web/_app/immutable/nodes/{0.CYS8iApT.js → 0.DYyUA1au.js} +1 -1
  47. package/dist/web/_app/immutable/nodes/1.D-3QEMMZ.js +1 -0
  48. package/dist/web/_app/immutable/nodes/{2.BnwnD1Ki.js → 2.4olHnH7U.js} +1 -1
  49. package/{web/.svelte-kit/output/client/_app/immutable/nodes/3.Dr0ot9sV.js → dist/web/_app/immutable/nodes/3.4w0bE-m2.js} +3 -3
  50. package/dist/web/_app/immutable/nodes/4.CZvjhVHt.js +60 -0
  51. package/dist/web/_app/immutable/nodes/{5.BBGQ_i84.js → 5.DLbPVJY2.js} +1 -1
  52. package/dist/web/_app/version.json +1 -1
  53. package/dist/web/index.html +12 -12
  54. package/dist/workspace-oWmVh5mi.mjs +1001 -0
  55. package/dist/workspace-oWmVh5mi.mjs.map +1 -0
  56. package/docs/23_adapter_slash_autocomplete/development_log.md +19 -0
  57. package/docs/23_adapter_slash_autocomplete/notes.md +18 -0
  58. package/docs/23_adapter_slash_autocomplete/prd.md +46 -0
  59. package/docs/23_adapter_slash_autocomplete/questions.md +6 -0
  60. package/docs/23_adapter_slash_autocomplete/tickets.md +21 -0
  61. package/docs/24_subagent_job_policy_fixes/development_log.md +22 -0
  62. package/docs/24_subagent_job_policy_fixes/notes.md +28 -0
  63. package/docs/24_subagent_job_policy_fixes/prd.md +59 -0
  64. package/docs/24_subagent_job_policy_fixes/questions.md +3 -0
  65. package/docs/24_subagent_job_policy_fixes/tickets.md +49 -0
  66. package/docs/25_e2e_test_improvements/development_log.md +30 -0
  67. package/docs/25_e2e_test_improvements/notes.md +29 -0
  68. package/docs/25_e2e_test_improvements/prd.md +43 -0
  69. package/docs/25_e2e_test_improvements/questions.md +12 -0
  70. package/docs/25_e2e_test_improvements/tickets-2.md +22 -0
  71. package/docs/25_e2e_test_improvements/tickets.md +22 -0
  72. package/docs/25_policy_cwd/development_log.md +30 -0
  73. package/docs/25_policy_cwd/notes.md +28 -0
  74. package/docs/25_policy_cwd/prd.md +77 -0
  75. package/docs/25_policy_cwd/questions.md +6 -0
  76. package/docs/25_policy_cwd/tickets.md +77 -0
  77. package/docs/CLI_REFERENCE.md +3 -1
  78. package/docs/PHILOSOPHY.md +35 -0
  79. package/docs/adapter-visibility/SPEC.md +461 -0
  80. package/docs/adapter-visibility/SPEC_v2.md +202 -0
  81. package/docs/auto-update/SPEC.md +344 -0
  82. package/docs/backups/SPEC.md +296 -0
  83. package/docs/backups/clawmini.gitignore +69 -0
  84. package/docs/guides/assets/clawmini-avatar.png +0 -0
  85. package/docs/guides/backups.md +332 -0
  86. package/docs/guides/discord_adapter_setup.md +1 -1
  87. package/docs/guides/google_chat_adapter_setup.md +81 -0
  88. package/docs/unified-startup/SPEC.md +203 -0
  89. package/e2e/_helpers/test-environment.test.ts +49 -0
  90. package/e2e/_helpers/test-environment.ts +548 -0
  91. package/e2e/adapters/_google-chat-fixtures.ts +340 -0
  92. package/{src/cli/e2e → e2e/adapters}/adapter-discord.test.ts +22 -23
  93. package/e2e/adapters/adapter-google-chat-downtime.test.ts +157 -0
  94. package/e2e/adapters/adapter-google-chat-inbound.test.ts +697 -0
  95. package/e2e/adapters/adapter-google-chat-outbound.test.ts +297 -0
  96. package/e2e/adapters/adapter-google-chat-roundtrip.test.ts +56 -0
  97. package/e2e/adapters/adapter-google-chat-threads.test.ts +1078 -0
  98. package/e2e/agents/custom-api-env.test.ts +80 -0
  99. package/e2e/agents/export-lite-func.test.ts +104 -0
  100. package/e2e/agents/fallbacks.test.ts +124 -0
  101. package/e2e/agents/interrupt.test.ts +50 -0
  102. package/e2e/agents/no-reply-necessary.test.ts +57 -0
  103. package/e2e/agents/session-timeout-subagents.test.ts +76 -0
  104. package/e2e/agents/subagent-authorization.test.ts +246 -0
  105. package/e2e/agents/subagent-env.test.ts +49 -0
  106. package/e2e/agents/subagent-lifecycle.test.ts +782 -0
  107. package/e2e/agents/subagents-depth.test.ts +47 -0
  108. package/e2e/cli/agents.test.ts +176 -0
  109. package/e2e/cli/auto-update.test.ts +741 -0
  110. package/e2e/cli/basic.test.ts +44 -0
  111. package/{src/cli/e2e → e2e/cli}/export-lite.test.ts +16 -12
  112. package/e2e/cli/init-gitignore.test.ts +86 -0
  113. package/e2e/cli/init.test.ts +76 -0
  114. package/e2e/cli/messages.test.ts +363 -0
  115. package/e2e/cli/serve.test.ts +76 -0
  116. package/{src/cli/e2e → e2e/cli}/skills.test.ts +11 -10
  117. package/{src/cli/e2e → e2e/daemon}/daemon.test.ts +57 -195
  118. package/e2e/jobs/agent-jobs.test.ts +216 -0
  119. package/e2e/jobs/cron.test.ts +64 -0
  120. package/e2e/jobs/restart.test.ts +108 -0
  121. package/e2e/policies/approval-session.test.ts +69 -0
  122. package/e2e/policies/auto-create-policies-file.test.ts +35 -0
  123. package/e2e/policies/builtin-manage-policies.test.ts +184 -0
  124. package/e2e/policies/builtin-run-host.test.ts +180 -0
  125. package/e2e/policies/environment-policies.test.ts +177 -0
  126. package/e2e/policies/manage-policies.test.ts +566 -0
  127. package/e2e/policies/output-size.test.ts +98 -0
  128. package/e2e/policies/policies-context-cwd.test.ts +160 -0
  129. package/e2e/policies/relative-script-path.test.ts +60 -0
  130. package/e2e/policies/requests-show.test.ts +135 -0
  131. package/e2e/policies/requests.test.ts +208 -0
  132. package/e2e/policies/slash-policies.test.ts +308 -0
  133. package/e2e/policies/startup-cleanup.test.ts +48 -0
  134. package/e2e/routers/session-timeout.test.ts +106 -0
  135. package/e2e/routers/slash-model.test.ts +152 -0
  136. package/e2e/routers/slash-new.test.ts +50 -0
  137. package/e2e/routers/slash-restart-adapter.test.ts +96 -0
  138. package/e2e/routers/slash-restart.test.ts +114 -0
  139. package/e2e/routers/slash-shutdown.test.ts +55 -0
  140. package/e2e/routers/slash-stop.test.ts +232 -0
  141. package/e2e/routers/slash-upgrade.test.ts +88 -0
  142. package/{src/cli/e2e → e2e/sandbox}/environments.test.ts +14 -13
  143. package/eslint.config.js +6 -0
  144. package/napkin.md +1 -1
  145. package/package.json +8 -3
  146. package/src/adapter-discord/commands.test.ts +42 -0
  147. package/src/adapter-discord/commands.ts +33 -0
  148. package/src/adapter-discord/config.ts +12 -0
  149. package/src/adapter-discord/forwarder.test.ts +499 -21
  150. package/src/adapter-discord/forwarder.ts +343 -124
  151. package/src/adapter-discord/inbound-cache.test.ts +47 -0
  152. package/src/adapter-discord/inbound-cache.ts +37 -0
  153. package/src/adapter-discord/index.test.ts +67 -2
  154. package/src/adapter-discord/index.ts +84 -216
  155. package/src/adapter-discord/interactions.test.ts +54 -3
  156. package/src/adapter-discord/interactions.ts +97 -53
  157. package/src/adapter-discord/processMessage.ts +239 -0
  158. package/src/adapter-discord/state.ts +1 -0
  159. package/src/adapter-google-chat/auth.test.ts +9 -5
  160. package/src/adapter-google-chat/auth.ts +29 -23
  161. package/src/adapter-google-chat/cards.ts +7 -2
  162. package/src/adapter-google-chat/client.test.ts +37 -2
  163. package/src/adapter-google-chat/client.ts +138 -38
  164. package/src/adapter-google-chat/config.ts +19 -0
  165. package/src/adapter-google-chat/forwarder.test.ts +81 -56
  166. package/src/adapter-google-chat/forwarder.ts +394 -185
  167. package/src/adapter-google-chat/inbound-cache.test.ts +61 -0
  168. package/src/adapter-google-chat/inbound-cache.ts +36 -0
  169. package/src/adapter-google-chat/state.test.ts +1 -0
  170. package/src/adapter-google-chat/state.ts +9 -1
  171. package/src/adapter-google-chat/subscriptions.ts +8 -6
  172. package/src/cli/builtin-policies.ts +44 -0
  173. package/src/cli/commands/agents.ts +59 -5
  174. package/src/cli/commands/down.ts +54 -2
  175. package/src/cli/commands/environments.ts +8 -2
  176. package/src/cli/commands/init.ts +31 -0
  177. package/src/cli/commands/logs.ts +116 -0
  178. package/src/cli/commands/policies.ts +6 -4
  179. package/src/cli/commands/serve.test.ts +67 -0
  180. package/src/cli/commands/serve.ts +284 -0
  181. package/src/cli/commands/up.ts +122 -2
  182. package/src/cli/commands/web-api/agents.ts +3 -2
  183. package/src/cli/index.ts +4 -0
  184. package/src/cli/install-detection.test.ts +72 -0
  185. package/src/cli/install-detection.ts +48 -0
  186. package/src/cli/lite.ts +54 -22
  187. package/src/cli/manage-policies-utils.ts +104 -0
  188. package/src/cli/manage-policies.ts +291 -0
  189. package/src/cli/run-host.ts +45 -0
  190. package/src/cli/supervisor-actions.ts +267 -0
  191. package/src/cli/supervisor-control.test.ts +129 -0
  192. package/src/cli/supervisor-control.ts +155 -0
  193. package/src/cli/supervisor-pid.ts +68 -0
  194. package/src/cli/supervisor.ts +277 -0
  195. package/src/daemon/agent/agent-context.ts +11 -11
  196. package/src/daemon/agent/agent-session.ts +8 -1
  197. package/src/daemon/agent/chat-logger.test.ts +78 -9
  198. package/src/daemon/agent/chat-logger.ts +25 -5
  199. package/src/daemon/agent/turn-registry.test.ts +89 -0
  200. package/src/daemon/agent/turn-registry.ts +94 -0
  201. package/src/daemon/agent/types.ts +2 -0
  202. package/src/daemon/api/agent-policy-endpoints.ts +263 -0
  203. package/src/daemon/api/agent-router.ts +47 -126
  204. package/src/daemon/api/index.test.ts +1 -0
  205. package/src/daemon/api/policy-request.test.ts +7 -5
  206. package/src/daemon/api/router-utils.ts +6 -5
  207. package/src/daemon/api/subagent-router.ts +110 -74
  208. package/src/daemon/api/subagent-utils.test.ts +60 -0
  209. package/src/daemon/api/subagent-utils.ts +113 -87
  210. package/src/daemon/api/user-router.ts +34 -8
  211. package/src/daemon/auth.ts +1 -0
  212. package/src/daemon/cron.test.ts +62 -4
  213. package/src/daemon/cron.ts +42 -16
  214. package/src/daemon/events.ts +65 -0
  215. package/src/daemon/index.ts +24 -1
  216. package/src/daemon/message-interruption.test.ts +1 -0
  217. package/src/daemon/message-jobs.test.ts +1 -0
  218. package/src/daemon/message.ts +78 -14
  219. package/src/daemon/observation.test.ts +26 -18
  220. package/src/daemon/pending-replies.test.ts +112 -0
  221. package/src/daemon/pending-replies.ts +162 -0
  222. package/src/daemon/policy-request-service.ts +3 -1
  223. package/src/daemon/policy-utils.test.ts +66 -1
  224. package/src/daemon/policy-utils.ts +126 -1
  225. package/src/daemon/request-store.ts +31 -0
  226. package/src/daemon/routers/session-timeout.ts +4 -0
  227. package/src/daemon/routers/slash-model.test.ts +344 -0
  228. package/src/daemon/routers/slash-model.ts +207 -0
  229. package/src/daemon/routers/slash-policies.test.ts +38 -32
  230. package/src/daemon/routers/slash-policies.ts +84 -33
  231. package/src/daemon/routers/slash-restart.test.ts +69 -0
  232. package/src/daemon/routers/slash-restart.ts +36 -0
  233. package/src/daemon/routers/slash-shutdown.test.ts +50 -0
  234. package/src/daemon/routers/slash-shutdown.ts +28 -0
  235. package/src/daemon/routers/slash-upgrade.test.ts +116 -0
  236. package/src/daemon/routers/slash-upgrade.ts +76 -0
  237. package/src/daemon/routers/types.ts +7 -0
  238. package/src/daemon/routers.ts +16 -0
  239. package/src/shared/adapters/blockquote.test.ts +28 -0
  240. package/src/shared/adapters/blockquote.ts +20 -0
  241. package/src/shared/adapters/filtering.test.ts +224 -10
  242. package/src/shared/adapters/filtering.ts +95 -7
  243. package/src/shared/adapters/inbound-cache.test.ts +48 -0
  244. package/src/shared/adapters/inbound-cache.ts +54 -0
  245. package/src/shared/adapters/turn-log-buffer.ts +266 -0
  246. package/src/shared/adapters/turn-log.test.ts +389 -0
  247. package/src/shared/adapters/turn-log.ts +357 -0
  248. package/src/shared/agent-utils.ts +12 -5
  249. package/src/shared/chats.test.ts +4 -0
  250. package/src/shared/chats.ts +9 -0
  251. package/src/shared/config.ts +16 -1
  252. package/src/shared/lite.ts +76 -2
  253. package/src/shared/policies.ts +26 -0
  254. package/src/shared/template-manifest.ts +267 -0
  255. package/src/shared/utils/shell.ts +61 -0
  256. package/src/shared/version.ts +34 -0
  257. package/src/shared/workspace.test.ts +217 -0
  258. package/src/shared/workspace.ts +626 -48
  259. package/templates/environments/cladding/allowlist-domain.mjs +125 -0
  260. package/templates/environments/cladding/env.json +21 -1
  261. package/templates/environments/cladding/run-with-network.mjs +54 -0
  262. package/templates/environments/macos-proxy/allowlist-domain.mjs +95 -0
  263. package/templates/environments/macos-proxy/env.json +8 -1
  264. package/templates/environments/macos-proxy/proxy.mjs +42 -13
  265. package/templates/gemini/template.json +5 -0
  266. package/templates/gemini-claw/template.json +13 -0
  267. package/templates/skills/clawmini-requests/SKILL.md +69 -10
  268. package/templates/skills/run-host/SKILL.md +51 -0
  269. package/templates/skills/skill-creator/SKILL.md +4 -3
  270. package/templates/skills/skill-creator/scripts/validate.sh +52 -0
  271. package/tsdown.config.ts +10 -1
  272. package/vitest.config.ts +2 -2
  273. package/web/.svelte-kit/ambient.d.ts +292 -176
  274. package/web/.svelte-kit/generated/server/internal.js +1 -1
  275. package/web/.svelte-kit/output/client/.vite/manifest.json +127 -137
  276. package/web/.svelte-kit/output/client/_app/immutable/chunks/{Drm9vgeP.js → 3AZlWB6U.js} +1 -1
  277. package/web/.svelte-kit/output/client/_app/immutable/chunks/BhRSsUCh.js +2 -0
  278. package/web/.svelte-kit/output/client/_app/immutable/chunks/BiLeM2i1.js +1 -0
  279. package/{dist/web/_app/immutable/chunks/CME08kGM.js → web/.svelte-kit/output/client/_app/immutable/chunks/BmBj85Ll.js} +1 -1
  280. package/web/.svelte-kit/output/client/_app/immutable/chunks/BrERcKAH.js +1 -0
  281. package/web/.svelte-kit/output/client/_app/immutable/chunks/Bv9252RM.js +1 -0
  282. package/web/.svelte-kit/output/client/_app/immutable/chunks/CIXNBPKi.js +1 -0
  283. package/web/.svelte-kit/output/client/_app/immutable/chunks/DISKL3GN.js +2 -0
  284. package/web/.svelte-kit/output/client/_app/immutable/chunks/{Zeh-C-mx.js → DcpaLzmX.js} +1 -1
  285. package/web/.svelte-kit/output/client/_app/immutable/chunks/DnQ3vS13.js +1 -0
  286. package/web/.svelte-kit/output/client/_app/immutable/chunks/KsloHTKS.js +1 -0
  287. package/{dist/web/_app/immutable/chunks/Ck-be5J2.js → web/.svelte-kit/output/client/_app/immutable/chunks/RsHsUj-8.js} +2 -2
  288. package/web/.svelte-kit/output/client/_app/immutable/chunks/{G_zz-Gou.js → wpfV79dV.js} +1 -1
  289. package/web/.svelte-kit/output/client/_app/immutable/entry/app.CIw1Qj0n.js +2 -0
  290. package/web/.svelte-kit/output/client/_app/immutable/entry/start.Di0-Jhte.js +1 -0
  291. package/web/.svelte-kit/output/client/_app/immutable/nodes/{0.CYS8iApT.js → 0.DYyUA1au.js} +1 -1
  292. package/web/.svelte-kit/output/client/_app/immutable/nodes/1.D-3QEMMZ.js +1 -0
  293. package/web/.svelte-kit/output/client/_app/immutable/nodes/{2.BnwnD1Ki.js → 2.4olHnH7U.js} +1 -1
  294. package/{dist/web/_app/immutable/nodes/3.Dr0ot9sV.js → web/.svelte-kit/output/client/_app/immutable/nodes/3.4w0bE-m2.js} +3 -3
  295. package/web/.svelte-kit/output/client/_app/immutable/nodes/4.CZvjhVHt.js +60 -0
  296. package/web/.svelte-kit/output/client/_app/immutable/nodes/{5.BBGQ_i84.js → 5.DLbPVJY2.js} +1 -1
  297. package/web/.svelte-kit/output/client/_app/version.json +1 -1
  298. package/web/.svelte-kit/output/server/.vite/manifest.json +12 -10
  299. package/web/.svelte-kit/output/server/chunks/Icon.js +1 -1
  300. package/web/.svelte-kit/output/server/chunks/client.js +1 -1
  301. package/web/.svelte-kit/output/server/chunks/exports.js +1 -1
  302. package/web/.svelte-kit/output/server/chunks/index-server.js +2 -1
  303. package/web/.svelte-kit/output/server/chunks/internal.js +1 -1
  304. package/web/.svelte-kit/output/server/chunks/render-context.js +77 -0
  305. package/web/.svelte-kit/output/server/chunks/root.js +739 -788
  306. package/web/.svelte-kit/output/server/chunks/shared.js +234 -21
  307. package/web/.svelte-kit/output/server/index.js +126 -90
  308. package/web/.svelte-kit/output/server/manifest-full.js +1 -1
  309. package/web/.svelte-kit/output/server/manifest.js +1 -1
  310. package/web/.svelte-kit/output/server/nodes/0.js +1 -1
  311. package/web/.svelte-kit/output/server/nodes/1.js +1 -1
  312. package/web/.svelte-kit/output/server/nodes/2.js +1 -1
  313. package/web/.svelte-kit/output/server/nodes/3.js +1 -1
  314. package/web/.svelte-kit/output/server/nodes/4.js +1 -1
  315. package/web/.svelte-kit/output/server/nodes/5.js +1 -1
  316. package/web/.svelte-kit/output/server/remote-entry.js +245 -81
  317. package/web/.svelte-kit/tsconfig.json +4 -1
  318. package/dist/cli/propose-policy.mjs.map +0 -1
  319. package/dist/lite-CBxOT1y5.mjs +0 -241
  320. package/dist/lite-CBxOT1y5.mjs.map +0 -1
  321. package/dist/routing-D8rTxtaV.mjs +0 -245
  322. package/dist/routing-D8rTxtaV.mjs.map +0 -1
  323. package/dist/web/_app/immutable/chunks/B6YN0Nuq.js +0 -1
  324. package/dist/web/_app/immutable/chunks/BmRlVmv6.js +0 -1
  325. package/dist/web/_app/immutable/chunks/CK9JZLaG.js +0 -2
  326. package/dist/web/_app/immutable/chunks/Ck3rYNON.js +0 -1
  327. package/dist/web/_app/immutable/chunks/DMtIqaiV.js +0 -2
  328. package/dist/web/_app/immutable/chunks/DhD271EB.js +0 -1
  329. package/dist/web/_app/immutable/chunks/DpuLqk8d.js +0 -1
  330. package/dist/web/_app/immutable/chunks/DsIToJCP.js +0 -1
  331. package/dist/web/_app/immutable/chunks/bBmtyQMj.js +0 -1
  332. package/dist/web/_app/immutable/entry/app.CJmSwntr.js +0 -2
  333. package/dist/web/_app/immutable/entry/start.ZpUrT2ak.js +0 -1
  334. package/dist/web/_app/immutable/nodes/1.Bli0Hqzn.js +0 -1
  335. package/dist/web/_app/immutable/nodes/4.oBhvQhcA.js +0 -60
  336. package/dist/workspace-BJmJBfKi.mjs +0 -456
  337. package/dist/workspace-BJmJBfKi.mjs.map +0 -1
  338. package/src/cli/e2e/agents.test.ts +0 -140
  339. package/src/cli/e2e/basic.test.ts +0 -43
  340. package/src/cli/e2e/cron.test.ts +0 -132
  341. package/src/cli/e2e/export-lite-func.test.ts +0 -206
  342. package/src/cli/e2e/fallbacks.test.ts +0 -175
  343. package/src/cli/e2e/init.test.ts +0 -77
  344. package/src/cli/e2e/messages.test.ts +0 -332
  345. package/src/cli/e2e/propose-policy.test.ts +0 -203
  346. package/src/cli/e2e/requests.test.ts +0 -180
  347. package/src/cli/e2e/session-timeout.test.ts +0 -192
  348. package/src/cli/e2e/slash-new.test.ts +0 -93
  349. package/src/cli/e2e/subagents.test.ts +0 -106
  350. package/src/cli/e2e/utils.ts +0 -66
  351. package/src/cli/propose-policy.ts +0 -91
  352. package/web/.svelte-kit/output/client/_app/immutable/chunks/B6YN0Nuq.js +0 -1
  353. package/web/.svelte-kit/output/client/_app/immutable/chunks/BmRlVmv6.js +0 -1
  354. package/web/.svelte-kit/output/client/_app/immutable/chunks/CK9JZLaG.js +0 -2
  355. package/web/.svelte-kit/output/client/_app/immutable/chunks/Ck3rYNON.js +0 -1
  356. package/web/.svelte-kit/output/client/_app/immutable/chunks/DMtIqaiV.js +0 -2
  357. package/web/.svelte-kit/output/client/_app/immutable/chunks/DhD271EB.js +0 -1
  358. package/web/.svelte-kit/output/client/_app/immutable/chunks/DpuLqk8d.js +0 -1
  359. package/web/.svelte-kit/output/client/_app/immutable/chunks/DsIToJCP.js +0 -1
  360. package/web/.svelte-kit/output/client/_app/immutable/chunks/bBmtyQMj.js +0 -1
  361. package/web/.svelte-kit/output/client/_app/immutable/entry/app.CJmSwntr.js +0 -2
  362. package/web/.svelte-kit/output/client/_app/immutable/entry/start.ZpUrT2ak.js +0 -1
  363. package/web/.svelte-kit/output/client/_app/immutable/nodes/1.Bli0Hqzn.js +0 -1
  364. package/web/.svelte-kit/output/client/_app/immutable/nodes/4.oBhvQhcA.js +0 -60
  365. package/web/.svelte-kit/output/server/chunks/false.js +0 -4
  366. /package/dist/cli/{propose-policy.d.mts → manage-policies.d.mts} +0 -0
  367. /package/{src/cli/e2e → e2e/_helpers}/global-setup.ts +0 -0
@@ -0,0 +1,843 @@
1
+ import { C as readSettings, F as pathIsInsideDir, g as getWorkspaceRoot, m as getSettingsPath, u as getClawminiDir, x as readEnvironment } from "./workspace-oWmVh5mi.mjs";
2
+ import fs, { existsSync } from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { execFileSync, spawn } from "node:child_process";
6
+ import { createHash, randomUUID } from "node:crypto";
7
+ import fsPromises from "node:fs/promises";
8
+ import net from "node:net";
9
+ import { EventEmitter } from "node:events";
10
+
11
+ //#region src/shared/chats.ts
12
+ const DEFAULT_CHAT_ID = "default";
13
+ async function getChatsDir(startDir = process.cwd()) {
14
+ const dir = path.join(getClawminiDir(startDir), "chats");
15
+ if (!existsSync(dir)) await fsPromises.mkdir(dir, { recursive: true });
16
+ return dir;
17
+ }
18
+ function isValidChatId(chatId) {
19
+ if (!chatId || chatId.length === 0) return false;
20
+ return /^[a-zA-Z0-9_-]+$/.test(chatId);
21
+ }
22
+ function assertValidChatId(id) {
23
+ if (!isValidChatId(id)) throw new Error(`Invalid chat ID: ${id}`);
24
+ }
25
+ async function createChat(id, startDir = process.cwd()) {
26
+ assertValidChatId(id);
27
+ const chatsDir = await getChatsDir(startDir);
28
+ const chatDir = path.join(chatsDir, id);
29
+ if (!existsSync(chatDir)) await fsPromises.mkdir(chatDir, { recursive: true });
30
+ const chatFile = path.join(chatDir, "chat.jsonl");
31
+ if (!existsSync(chatFile)) await fsPromises.writeFile(chatFile, "");
32
+ }
33
+ async function listChats(startDir = process.cwd()) {
34
+ const chatsDir = await getChatsDir(startDir);
35
+ try {
36
+ return (await fsPromises.readdir(chatsDir, { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name);
37
+ } catch {
38
+ return [];
39
+ }
40
+ }
41
+ async function deleteChat(id, startDir = process.cwd()) {
42
+ assertValidChatId(id);
43
+ const chatsDir = await getChatsDir(startDir);
44
+ const chatDir = path.join(chatsDir, id);
45
+ if (!pathIsInsideDir(chatDir, chatsDir)) throw new Error(`Security Error: Cannot delete chat directory outside of ${chatsDir}`);
46
+ if (existsSync(chatDir)) await fsPromises.rm(chatDir, {
47
+ recursive: true,
48
+ force: true
49
+ });
50
+ }
51
+ async function appendMessage$1(id, message, startDir = process.cwd()) {
52
+ assertValidChatId(id);
53
+ const chatsDir = await getChatsDir(startDir);
54
+ const chatDir = path.join(chatsDir, id);
55
+ if (!existsSync(chatDir)) await createChat(id, startDir);
56
+ const chatFile = path.join(chatDir, "chat.jsonl");
57
+ await fsPromises.appendFile(chatFile, JSON.stringify(message) + "\n");
58
+ }
59
+ async function* readLinesBackwards(filePath) {
60
+ const fd = await fsPromises.open(filePath, "r");
61
+ try {
62
+ const stats = await fd.stat();
63
+ if (stats.size === 0) return;
64
+ const chunkSize = 64 * 1024;
65
+ let position = stats.size;
66
+ const buffer = Buffer.alloc(chunkSize);
67
+ let leftoverBuffer = Buffer.alloc(0);
68
+ while (position > 0) {
69
+ const readSize = Math.min(chunkSize, position);
70
+ position -= readSize;
71
+ const { bytesRead } = await fd.read(buffer, 0, readSize, position);
72
+ const currentChunk = buffer.subarray(0, bytesRead);
73
+ let combinedBuffer = Buffer.concat([currentChunk, leftoverBuffer]);
74
+ let lastNewlineIdx = combinedBuffer.lastIndexOf(10);
75
+ while (lastNewlineIdx !== -1) {
76
+ const line = combinedBuffer.subarray(lastNewlineIdx + 1).toString("utf8").trim();
77
+ if (line) yield line;
78
+ combinedBuffer = combinedBuffer.subarray(0, lastNewlineIdx);
79
+ lastNewlineIdx = combinedBuffer.lastIndexOf(10);
80
+ }
81
+ leftoverBuffer = combinedBuffer;
82
+ }
83
+ if (leftoverBuffer.length > 0) {
84
+ const line = leftoverBuffer.toString("utf8").trim();
85
+ if (line) yield line;
86
+ }
87
+ } finally {
88
+ await fd.close();
89
+ }
90
+ }
91
+ function parseChatMessage(line) {
92
+ try {
93
+ const msg = JSON.parse(line);
94
+ if (msg && msg.role === "log") msg.role = "legacy_log";
95
+ return msg;
96
+ } catch {
97
+ return null;
98
+ }
99
+ }
100
+ async function getMessages(id, limit, startDir = process.cwd(), predicate, before) {
101
+ assertValidChatId(id);
102
+ const chatsDir = await getChatsDir(startDir);
103
+ const chatFile = path.join(chatsDir, id, "chat.jsonl");
104
+ if (!existsSync(chatFile)) throw new Error(`Chat directory or file for '${id}' not found.`);
105
+ limit = limit ?? 100;
106
+ if (limit <= 0) {
107
+ let messages = (await fsPromises.readFile(chatFile, "utf8")).split("\n").filter((line) => line.trim() !== "").map((line) => parseChatMessage(line)).filter((msg) => msg !== null);
108
+ if (before) {
109
+ const beforeIndex = messages.findIndex((m) => m.id === before);
110
+ if (beforeIndex !== -1) messages = messages.slice(0, beforeIndex);
111
+ else messages = [];
112
+ }
113
+ if (predicate) messages = messages.filter(predicate);
114
+ return messages;
115
+ }
116
+ const messages = [];
117
+ let skipping = before !== void 0;
118
+ for await (const line of readLinesBackwards(chatFile)) try {
119
+ const msg = parseChatMessage(line);
120
+ if (!msg) continue;
121
+ if (skipping) {
122
+ if (msg.id === before) skipping = false;
123
+ continue;
124
+ }
125
+ if (!predicate || predicate(msg)) {
126
+ messages.push(msg);
127
+ if (messages.length >= limit) break;
128
+ }
129
+ } catch {}
130
+ return messages.reverse();
131
+ }
132
+ async function getDefaultChatId(startDir = process.cwd()) {
133
+ const settingsPath = getSettingsPath(startDir);
134
+ if (!existsSync(settingsPath)) return DEFAULT_CHAT_ID;
135
+ try {
136
+ const content = await fsPromises.readFile(settingsPath, "utf8");
137
+ return JSON.parse(content).chats?.defaultId || DEFAULT_CHAT_ID;
138
+ } catch {
139
+ return DEFAULT_CHAT_ID;
140
+ }
141
+ }
142
+ async function setDefaultChatId(id, startDir = process.cwd()) {
143
+ assertValidChatId(id);
144
+ const settingsPath = getSettingsPath(startDir);
145
+ let settings = {};
146
+ if (existsSync(settingsPath)) try {
147
+ const content = await fsPromises.readFile(settingsPath, "utf8");
148
+ settings = JSON.parse(content);
149
+ } catch {}
150
+ if (!settings.chats) settings.chats = {};
151
+ settings.chats.defaultId = id;
152
+ const clawminiDir = getClawminiDir(startDir);
153
+ if (!existsSync(clawminiDir)) await fsPromises.mkdir(clawminiDir, { recursive: true });
154
+ await fsPromises.writeFile(settingsPath, JSON.stringify(settings, null, 2));
155
+ }
156
+ async function findLastMessage(id, predicate, startDir = process.cwd()) {
157
+ assertValidChatId(id);
158
+ const chatsDir = await getChatsDir(startDir);
159
+ const chatFile = path.join(chatsDir, id, "chat.jsonl");
160
+ if (!existsSync(chatFile)) return null;
161
+ for await (const line of readLinesBackwards(chatFile)) try {
162
+ const msg = parseChatMessage(line);
163
+ if (!msg) continue;
164
+ if (predicate(msg)) return msg;
165
+ } catch {}
166
+ return null;
167
+ }
168
+
169
+ //#endregion
170
+ //#region src/shared/lite.ts
171
+ const LITE_MARKER = "clawmini-lite";
172
+ function sha256(content) {
173
+ return createHash("sha256").update(content).digest("hex");
174
+ }
175
+ function looksLikeLiteScript(content) {
176
+ return content.startsWith("#!") && content.includes(LITE_MARKER);
177
+ }
178
+ async function resolveCompiledScript(scriptName, metaUrl) {
179
+ const __dirname = path.dirname(fileURLToPath(metaUrl));
180
+ const filename = scriptName.endsWith(".mjs") ? scriptName : `${scriptName}.mjs`;
181
+ const searchPaths = [
182
+ path.resolve(__dirname, `cli/${filename}`),
183
+ path.resolve(__dirname, filename),
184
+ path.resolve(__dirname, `../cli/${filename}`),
185
+ path.resolve(__dirname, `../../dist/cli/${filename}`),
186
+ path.resolve(__dirname, `../${filename}`),
187
+ path.resolve(__dirname, `../../${filename}`)
188
+ ];
189
+ for (const scriptPath of searchPaths) try {
190
+ await fsPromises.access(scriptPath);
191
+ return scriptPath;
192
+ } catch {}
193
+ throw new Error(`Could not find compiled script: ${filename}`);
194
+ }
195
+ async function getLiteScriptContent() {
196
+ let liteScriptContent;
197
+ const liteScriptPath = await resolveCompiledScript("lite", import.meta.url);
198
+ liteScriptContent = await fsPromises.readFile(liteScriptPath, "utf8");
199
+ if (!liteScriptContent.startsWith("#!")) liteScriptContent = "#!/usr/bin/env node\n" + liteScriptContent;
200
+ return liteScriptContent;
201
+ }
202
+ async function writeLiteScript(outPath) {
203
+ const content = await getLiteScriptContent();
204
+ let finalPath = outPath;
205
+ const isDir = finalPath.endsWith(path.sep) || !(path.extname(finalPath) === ".js" || path.extname(finalPath) === ".mjs" || path.basename(finalPath) === "clawmini-lite");
206
+ try {
207
+ if ((await fsPromises.stat(finalPath)).isDirectory()) finalPath = path.join(finalPath, "clawmini-lite.js");
208
+ } catch {
209
+ if (isDir && !path.extname(finalPath) && !finalPath.endsWith("clawmini-lite") && !finalPath.endsWith("clawmini-lite.js")) {
210
+ await fsPromises.mkdir(finalPath, { recursive: true });
211
+ finalPath = path.join(finalPath, "clawmini-lite.js");
212
+ }
213
+ }
214
+ const dir = path.dirname(finalPath);
215
+ await fsPromises.mkdir(dir, { recursive: true });
216
+ await fsPromises.writeFile(finalPath, content, { mode: 493 });
217
+ return finalPath;
218
+ }
219
+ async function resolveLiteTargetPath(outPath) {
220
+ const isProbablyFile = path.extname(outPath) === ".js" || path.extname(outPath) === ".mjs" || path.basename(outPath) === "clawmini-lite";
221
+ try {
222
+ if ((await fsPromises.stat(outPath)).isDirectory()) return path.join(outPath, "clawmini-lite.js");
223
+ return outPath;
224
+ } catch {
225
+ if (isProbablyFile) return outPath;
226
+ return path.join(outPath, "clawmini-lite.js");
227
+ }
228
+ }
229
+ async function refreshLiteAt(outPath, opts = {}) {
230
+ const content = await getLiteScriptContent();
231
+ const finalPath = await resolveLiteTargetPath(outPath);
232
+ let existing = null;
233
+ try {
234
+ existing = await fsPromises.readFile(finalPath, "utf8");
235
+ } catch {}
236
+ if (existing !== null) {
237
+ if (sha256(existing) === sha256(content)) return {
238
+ status: "unchanged",
239
+ path: finalPath
240
+ };
241
+ if (!looksLikeLiteScript(existing)) {
242
+ const label = opts.label ? ` (${opts.label})` : "";
243
+ console.warn(`Refusing to overwrite ${finalPath}${label}: existing file is not a clawmini-lite script`);
244
+ return {
245
+ status: "refused",
246
+ path: finalPath
247
+ };
248
+ }
249
+ }
250
+ const dir = path.dirname(finalPath);
251
+ await fsPromises.mkdir(dir, { recursive: true });
252
+ await fsPromises.writeFile(finalPath, content, { mode: 493 });
253
+ return {
254
+ status: "written",
255
+ path: finalPath
256
+ };
257
+ }
258
+ async function exportLiteToEnvironment(envName, envConfig, affectedDir) {
259
+ if (!envConfig?.exportLiteTo) return false;
260
+ const finalExportPath = path.resolve(affectedDir, envConfig.exportLiteTo);
261
+ if (!finalExportPath.startsWith(affectedDir + path.sep) && finalExportPath !== affectedDir && !finalExportPath.startsWith(affectedDir + "/")) {
262
+ console.warn(`Skipping export for environment '${envName}': exportLiteTo path '${envConfig.exportLiteTo}' escapes the environment target directory '${affectedDir}'`);
263
+ return false;
264
+ }
265
+ try {
266
+ const result = await refreshLiteAt(finalExportPath, { label: `Environment: ${envName}` });
267
+ if (result.status === "written") console.log(`Successfully exported clawmini-lite to ${result.path} (Environment: ${envName})`);
268
+ else if (result.status === "refused") return false;
269
+ return true;
270
+ } catch (err) {
271
+ console.error(`Failed to export clawmini-lite to ${finalExportPath} (Environment: ${envName}): ${err instanceof Error ? err.message : String(err)}`);
272
+ return false;
273
+ }
274
+ }
275
+ async function exportLiteToAllEnvironments(startDir = process.cwd()) {
276
+ let exportedToEnvironments = false;
277
+ try {
278
+ const workspaceRoot = getWorkspaceRoot(startDir);
279
+ const settings = await readSettings(workspaceRoot);
280
+ if (settings?.environments) for (const [envPath, envName] of Object.entries(settings.environments)) {
281
+ const envConfig = await readEnvironment(envName, workspaceRoot);
282
+ if (envConfig) {
283
+ if (await exportLiteToEnvironment(envName, envConfig, path.resolve(workspaceRoot, envPath))) exportedToEnvironments = true;
284
+ }
285
+ }
286
+ } catch {}
287
+ return exportedToEnvironments;
288
+ }
289
+
290
+ //#endregion
291
+ //#region src/cli/supervisor-pid.ts
292
+ function getSupervisorPidPath(startDir = process.cwd()) {
293
+ return path.join(getClawminiDir(startDir), "supervisor.pid");
294
+ }
295
+ function getProcessStartTime(pid) {
296
+ try {
297
+ const trimmed = execFileSync("ps", [
298
+ "-p",
299
+ String(pid),
300
+ "-o",
301
+ "lstart="
302
+ ], {
303
+ encoding: "utf-8",
304
+ stdio: [
305
+ "ignore",
306
+ "pipe",
307
+ "ignore"
308
+ ]
309
+ }).trim();
310
+ return trimmed.length > 0 ? trimmed : null;
311
+ } catch {
312
+ return null;
313
+ }
314
+ }
315
+ function readSupervisorPid(startDir = process.cwd()) {
316
+ const p = getSupervisorPidPath(startDir);
317
+ if (!fs.existsSync(p)) return null;
318
+ const content = fs.readFileSync(p, "utf-8").trim();
319
+ const sep = content.indexOf(":");
320
+ if (sep <= 0) return null;
321
+ const pid = parseInt(content.slice(0, sep), 10);
322
+ const storedStart = content.slice(sep + 1).trim();
323
+ if (!Number.isFinite(pid) || pid <= 0 || storedStart.length === 0) return null;
324
+ try {
325
+ process.kill(pid, 0);
326
+ } catch {
327
+ return null;
328
+ }
329
+ const currentStart = getProcessStartTime(pid);
330
+ if (currentStart === null || currentStart !== storedStart) return null;
331
+ return pid;
332
+ }
333
+ function writeSupervisorPid(pid, startDir = process.cwd()) {
334
+ const startTime = getProcessStartTime(pid);
335
+ if (!startTime) throw new Error(`Cannot read start time for pid ${pid}; refusing to write supervisor.pid`);
336
+ fs.writeFileSync(getSupervisorPidPath(startDir), `${pid}:${startTime}`);
337
+ }
338
+ function removeSupervisorPid(startDir = process.cwd()) {
339
+ const p = getSupervisorPidPath(startDir);
340
+ if (fs.existsSync(p)) try {
341
+ fs.unlinkSync(p);
342
+ } catch {}
343
+ }
344
+
345
+ //#endregion
346
+ //#region src/cli/install-detection.ts
347
+ function realpathOrNull(p) {
348
+ try {
349
+ return fs.realpathSync(p);
350
+ } catch {
351
+ return null;
352
+ }
353
+ }
354
+ function getNpmRootGlobal() {
355
+ try {
356
+ return execFileSync("npm", ["root", "-g"], {
357
+ encoding: "utf-8",
358
+ stdio: [
359
+ "ignore",
360
+ "pipe",
361
+ "ignore"
362
+ ]
363
+ }).trim() || null;
364
+ } catch {
365
+ return null;
366
+ }
367
+ }
368
+ function detectInstall(entryPath = process.argv[1] ?? "") {
369
+ const entryRealPath = realpathOrNull(entryPath) ?? entryPath;
370
+ const npmRoot = getNpmRootGlobal();
371
+ const npmRootRealPath = npmRoot ? realpathOrNull(npmRoot) ?? npmRoot : null;
372
+ let isNpmGlobal = false;
373
+ if (npmRootRealPath) {
374
+ const rootWithSep = npmRootRealPath.endsWith(path.sep) ? npmRootRealPath : npmRootRealPath + path.sep;
375
+ isNpmGlobal = entryRealPath === npmRootRealPath || entryRealPath.startsWith(rootWithSep);
376
+ }
377
+ return {
378
+ isNpmGlobal,
379
+ entryRealPath,
380
+ npmRootRealPath
381
+ };
382
+ }
383
+
384
+ //#endregion
385
+ //#region src/cli/supervisor-control.ts
386
+ function getControlSocketPath(startDir = process.cwd()) {
387
+ return path.join(getClawminiDir(startDir), "super.sock");
388
+ }
389
+ function startControlServer(handlers, socketPath = getControlSocketPath()) {
390
+ if (fs.existsSync(socketPath)) try {
391
+ fs.unlinkSync(socketPath);
392
+ } catch {}
393
+ const server = net.createServer((socket) => {
394
+ let buf = "";
395
+ let handled = false;
396
+ const respond = (res) => {
397
+ if (handled) return;
398
+ handled = true;
399
+ socket.end(JSON.stringify(res) + "\n");
400
+ };
401
+ socket.on("data", (chunk) => {
402
+ if (handled) return;
403
+ buf += chunk.toString();
404
+ const idx = buf.indexOf("\n");
405
+ if (idx === -1) return;
406
+ const line = buf.slice(0, idx);
407
+ let req;
408
+ try {
409
+ req = JSON.parse(line);
410
+ } catch {
411
+ respond({
412
+ ok: false,
413
+ error: "invalid request"
414
+ });
415
+ return;
416
+ }
417
+ const handler = handlers[req.action];
418
+ if (!handler) {
419
+ respond({
420
+ ok: false,
421
+ error: `unknown action: ${req.action}`
422
+ });
423
+ return;
424
+ }
425
+ Promise.resolve().then(() => handler(req)).then((res) => respond(res), (err) => respond({
426
+ ok: false,
427
+ error: err instanceof Error ? err.message : String(err)
428
+ }));
429
+ });
430
+ socket.on("error", () => {});
431
+ });
432
+ server.listen(socketPath, () => {
433
+ try {
434
+ fs.chmodSync(socketPath, 384);
435
+ } catch {}
436
+ });
437
+ return server;
438
+ }
439
+ function sendControlRequest(req, socketPath = getControlSocketPath(), timeoutMs = 5e3) {
440
+ return new Promise((resolve, reject) => {
441
+ const socket = net.createConnection({ path: socketPath });
442
+ let buf = "";
443
+ let settled = false;
444
+ const finish = (fn) => {
445
+ if (settled) return;
446
+ settled = true;
447
+ try {
448
+ socket.destroy();
449
+ } catch {}
450
+ fn();
451
+ };
452
+ const timer = setTimeout(() => {
453
+ finish(() => reject(/* @__PURE__ */ new Error(`Control request timed out after ${timeoutMs}ms`)));
454
+ }, timeoutMs);
455
+ socket.on("connect", () => {
456
+ socket.write(JSON.stringify(req) + "\n");
457
+ });
458
+ socket.on("data", (chunk) => {
459
+ buf += chunk.toString();
460
+ const idx = buf.indexOf("\n");
461
+ if (idx !== -1) {
462
+ const line = buf.slice(0, idx);
463
+ clearTimeout(timer);
464
+ try {
465
+ const res = JSON.parse(line);
466
+ finish(() => resolve(res));
467
+ } catch (err) {
468
+ finish(() => reject(err instanceof Error ? err : new Error(String(err))));
469
+ }
470
+ }
471
+ });
472
+ socket.on("error", (err) => {
473
+ clearTimeout(timer);
474
+ finish(() => reject(err));
475
+ });
476
+ socket.on("end", () => {
477
+ if (!settled) {
478
+ clearTimeout(timer);
479
+ finish(() => reject(/* @__PURE__ */ new Error("Control server closed connection without responding")));
480
+ }
481
+ });
482
+ });
483
+ }
484
+
485
+ //#endregion
486
+ //#region src/daemon/events.ts
487
+ const daemonEvents = new EventEmitter();
488
+ const DAEMON_EVENT_MESSAGE_APPENDED = "message-appended";
489
+ const DAEMON_EVENT_TYPING = "typing";
490
+ const DAEMON_EVENT_TURN_STARTED = "turn-started";
491
+ const DAEMON_EVENT_TURN_ENDED = "turn-ended";
492
+ /**
493
+ * Unified event carrying both `ChatMessage` appends and turn lifecycle
494
+ * events so a single `waitForMessages` subscription can interleave them
495
+ * in emission order (no merge logic or messageQueue on the consumer side).
496
+ */
497
+ const DAEMON_EVENT_CHAT_STREAM = "chat-stream";
498
+ function emitMessageAppended(chatId, message) {
499
+ daemonEvents.emit(DAEMON_EVENT_MESSAGE_APPENDED, {
500
+ chatId,
501
+ message
502
+ });
503
+ const envelope = {
504
+ chatId,
505
+ item: {
506
+ kind: "message",
507
+ message
508
+ }
509
+ };
510
+ daemonEvents.emit(DAEMON_EVENT_CHAT_STREAM, envelope);
511
+ }
512
+ function emitTyping(chatId) {
513
+ daemonEvents.emit(DAEMON_EVENT_TYPING, { chatId });
514
+ }
515
+ function emitTurnStarted(event) {
516
+ daemonEvents.emit(DAEMON_EVENT_TURN_STARTED, event);
517
+ const lifecycle = {
518
+ type: "started",
519
+ turnId: event.turnId,
520
+ rootMessageId: event.rootMessageId,
521
+ ...event.externalRef ? { externalRef: event.externalRef } : {}
522
+ };
523
+ const envelope = {
524
+ chatId: event.chatId,
525
+ item: {
526
+ kind: "turn",
527
+ event: lifecycle
528
+ }
529
+ };
530
+ daemonEvents.emit(DAEMON_EVENT_CHAT_STREAM, envelope);
531
+ }
532
+ function emitTurnEnded(event) {
533
+ daemonEvents.emit(DAEMON_EVENT_TURN_ENDED, event);
534
+ const lifecycle = {
535
+ type: "ended",
536
+ turnId: event.turnId,
537
+ outcome: event.outcome
538
+ };
539
+ const envelope = {
540
+ chatId: event.chatId,
541
+ item: {
542
+ kind: "turn",
543
+ event: lifecycle
544
+ }
545
+ };
546
+ daemonEvents.emit(DAEMON_EVENT_CHAT_STREAM, envelope);
547
+ }
548
+
549
+ //#endregion
550
+ //#region src/daemon/chats.ts
551
+ async function appendMessage(id, message, startDir = process.cwd()) {
552
+ await appendMessage$1(id, message, startDir);
553
+ emitMessageAppended(id, message);
554
+ }
555
+
556
+ //#endregion
557
+ //#region src/daemon/pending-replies.ts
558
+ function getPendingRepliesPath(startDir = process.cwd()) {
559
+ return path.join(getClawminiDir(startDir), "pending-replies.json");
560
+ }
561
+ function readFileSafe(filePath) {
562
+ if (!fs.existsSync(filePath)) return null;
563
+ try {
564
+ const raw = fs.readFileSync(filePath, "utf-8");
565
+ const parsed = JSON.parse(raw);
566
+ if (!parsed || parsed.version !== 1 || !Array.isArray(parsed.entries)) return null;
567
+ return parsed;
568
+ } catch {
569
+ return null;
570
+ }
571
+ }
572
+ function writeAtomic(filePath, data) {
573
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
574
+ const tmpPath = `${filePath}.${process.pid}.tmp`;
575
+ fs.writeFileSync(tmpPath, JSON.stringify(data, null, 2));
576
+ fs.renameSync(tmpPath, filePath);
577
+ }
578
+ function tryUnlink(filePath) {
579
+ if (!fs.existsSync(filePath)) return;
580
+ try {
581
+ fs.unlinkSync(filePath);
582
+ } catch {}
583
+ }
584
+ function enqueuePendingReply(entry, startDir = process.cwd()) {
585
+ const filePath = getPendingRepliesPath(startDir);
586
+ const entries = readFileSafe(filePath)?.entries ?? [];
587
+ entries.push(entry);
588
+ writeAtomic(filePath, {
589
+ version: 1,
590
+ entries
591
+ });
592
+ }
593
+ /**
594
+ * Remove the first entry that matches the predicate. Used to roll back an
595
+ * enqueued entry when the supervisor reports the action could not be started.
596
+ */
597
+ function dequeuePendingReply(predicate, startDir = process.cwd()) {
598
+ const filePath = getPendingRepliesPath(startDir);
599
+ const existing = readFileSafe(filePath);
600
+ if (!existing) return false;
601
+ const idx = existing.entries.findIndex(predicate);
602
+ if (idx === -1) return false;
603
+ existing.entries.splice(idx, 1);
604
+ if (existing.entries.length === 0) tryUnlink(filePath);
605
+ else writeAtomic(filePath, existing);
606
+ return true;
607
+ }
608
+ function renderMessage(entry, runtimeVersion) {
609
+ switch (entry.kind) {
610
+ case "restart-complete": return `Clawmini restarted (v${runtimeVersion}).`;
611
+ case "upgrade-complete": return `Clawmini upgraded to v${runtimeVersion}.`;
612
+ case "upgrade-failed": return `Clawmini upgrade${entry.requestedVersion ? ` to v${entry.requestedVersion}` : ""} failed${entry.reason ? `: ${entry.reason}` : "."}`;
613
+ }
614
+ }
615
+ /**
616
+ * Append a SystemMessage for each pending reply. Called from the daemon
617
+ * startup path so adapters (which reconnect via tRPC subscription with
618
+ * lastMessageId) replay the message after the daemon comes back online.
619
+ *
620
+ * Crash-safe: each entry is consumed only after its SystemMessage is
621
+ * appended. A crash mid-loop leaves the un-delivered entries on disk for the
622
+ * next daemon start to drain.
623
+ */
624
+ async function drainPendingReplies(runtimeVersion, startDir = process.cwd()) {
625
+ const filePath = getPendingRepliesPath(startDir);
626
+ const data = readFileSafe(filePath);
627
+ if (!data) {
628
+ tryUnlink(filePath);
629
+ return;
630
+ }
631
+ const remaining = [...data.entries];
632
+ while (remaining.length > 0) {
633
+ const entry = remaining[0];
634
+ const sysMsg = {
635
+ id: randomUUID(),
636
+ role: "system",
637
+ content: renderMessage(entry, runtimeVersion),
638
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
639
+ sessionId: void 0,
640
+ event: "router",
641
+ displayRole: "agent",
642
+ ...entry.messageId ? { messageId: entry.messageId } : {}
643
+ };
644
+ try {
645
+ await appendMessage(entry.chatId, sysMsg, startDir);
646
+ } catch (err) {
647
+ console.error(`Failed to deliver pending reply to chat ${entry.chatId}:`, err instanceof Error ? err.message : err);
648
+ }
649
+ remaining.shift();
650
+ if (remaining.length === 0) tryUnlink(filePath);
651
+ else writeAtomic(filePath, {
652
+ version: 1,
653
+ entries: remaining
654
+ });
655
+ }
656
+ }
657
+
658
+ //#endregion
659
+ //#region src/cli/supervisor-actions.ts
660
+ const ACTION_GRACE_MS = 1e3;
661
+ /**
662
+ * Wire up the supervisor control socket so the daemon can request
663
+ * /restart, /shutdown, and /upgrade out-of-band.
664
+ */
665
+ function startSupervisorControl(supervisor) {
666
+ startControlServer({
667
+ restart: async (req) => {
668
+ if (req.chatId) enqueuePendingReply({
669
+ chatId: req.chatId,
670
+ kind: "restart-complete",
671
+ ...req.messageId ? { messageId: req.messageId } : {}
672
+ });
673
+ setTimeout(() => {
674
+ supervisor.restartAll().catch((err) => {
675
+ process.stderr.write(`[supervisor] /restart failed: ${err instanceof Error ? err.message : String(err)}\n`);
676
+ if (req.chatId && req.messageId) dequeuePendingReply((e) => e.kind === "restart-complete" && e.messageId === req.messageId);
677
+ });
678
+ }, ACTION_GRACE_MS);
679
+ return { ok: true };
680
+ },
681
+ shutdown: async () => {
682
+ setTimeout(() => void supervisor.shutdown(0), ACTION_GRACE_MS);
683
+ return { ok: true };
684
+ },
685
+ upgrade: async (req) => {
686
+ const info = detectInstall();
687
+ if (!info.isNpmGlobal) return {
688
+ ok: false,
689
+ error: `not installed via npm install -g (running from ${info.entryRealPath})`
690
+ };
691
+ const version = req.version?.trim();
692
+ if (!version) return {
693
+ ok: false,
694
+ error: "missing target version"
695
+ };
696
+ if (!isAcceptableVersion(version)) return {
697
+ ok: false,
698
+ error: `invalid version: ${version}`
699
+ };
700
+ setTimeout(() => {
701
+ runUpgrade(supervisor, version, req.chatId, req.messageId).catch((err) => {
702
+ process.stderr.write(`[supervisor] /upgrade encountered an unexpected error: ${err instanceof Error ? err.message : String(err)}\n`);
703
+ });
704
+ }, ACTION_GRACE_MS);
705
+ return { ok: true };
706
+ }
707
+ });
708
+ }
709
+ function isAcceptableVersion(version) {
710
+ return /^[a-zA-Z0-9][a-zA-Z0-9._+-]{0,63}$/.test(version);
711
+ }
712
+ /**
713
+ * In-place upgrade. Order:
714
+ * 1. `npm install -g clawmini@<version>` (services kept running so the
715
+ * user isn't left in the dark if the install fails).
716
+ * 2. Resolve the freshly-installed binary by absolute path. Bail out with
717
+ * an upgrade-failed reply if it's missing.
718
+ * 3. Enqueue the upgrade-complete reply.
719
+ * 4. Stop all children, spawn the replacement supervisor, exit.
720
+ *
721
+ * Any failure path enqueues an upgrade-failed reply (so the user gets visible
722
+ * feedback) and restarts the daemon to drain it, rather than silently exiting.
723
+ */
724
+ async function runUpgrade(supervisor, version, chatId, messageId) {
725
+ const info = detectInstall();
726
+ if (!info.isNpmGlobal || !info.npmRootRealPath) {
727
+ process.stderr.write(`[supervisor] /upgrade aborted: clawmini is not installed via npm install -g (running from ${info.entryRealPath}).\n`);
728
+ return;
729
+ }
730
+ const installErr = await runNpmInstall(version);
731
+ if (installErr) {
732
+ process.stderr.write(`[supervisor] /upgrade failed: ${installErr}\n`);
733
+ if (chatId) {
734
+ enqueuePendingReply({
735
+ chatId,
736
+ kind: "upgrade-failed",
737
+ ...messageId ? { messageId } : {},
738
+ requestedVersion: version,
739
+ reason: installErr
740
+ });
741
+ await supervisor.restartAll().catch((err) => {
742
+ process.stderr.write(`[supervisor] additionally failed to restart services to surface the failure: ${err instanceof Error ? err.message : String(err)}\n`);
743
+ });
744
+ }
745
+ return;
746
+ }
747
+ const newCli = path.join(info.npmRootRealPath, "clawmini", "dist", "cli", "index.mjs");
748
+ if (!fs.existsSync(newCli)) {
749
+ const reason = `npm install reported success but ${newCli} is missing`;
750
+ process.stderr.write(`[supervisor] /upgrade aborted: ${reason}\n`);
751
+ if (chatId) {
752
+ enqueuePendingReply({
753
+ chatId,
754
+ kind: "upgrade-failed",
755
+ ...messageId ? { messageId } : {},
756
+ requestedVersion: version,
757
+ reason
758
+ });
759
+ await supervisor.restartAll().catch(() => {});
760
+ }
761
+ return;
762
+ }
763
+ if (chatId) enqueuePendingReply({
764
+ chatId,
765
+ kind: "upgrade-complete",
766
+ ...messageId ? { messageId } : {},
767
+ requestedVersion: version
768
+ });
769
+ process.stderr.write("[supervisor] /upgrade: stopping all services...\n");
770
+ await supervisor.stopAllChildren();
771
+ process.stderr.write(`[supervisor] /upgrade: relaunching ${newCli} serve --detach...\n`);
772
+ removeSupervisorPid();
773
+ const replacement = spawn(process.execPath, [
774
+ newCli,
775
+ "serve",
776
+ "--detach"
777
+ ], {
778
+ detached: true,
779
+ stdio: "ignore",
780
+ cwd: process.cwd(),
781
+ env: process.env
782
+ });
783
+ if (!await waitForSpawn(replacement)) {
784
+ process.stderr.write(`[supervisor] /upgrade: replacement supervisor failed to spawn — restarting in place\n`);
785
+ if (chatId) {
786
+ dequeuePendingReply((e) => e.kind === "upgrade-complete" && e.messageId === messageId && e.requestedVersion === version);
787
+ enqueuePendingReply({
788
+ chatId,
789
+ kind: "upgrade-failed",
790
+ ...messageId ? { messageId } : {},
791
+ requestedVersion: version,
792
+ reason: "replacement supervisor failed to spawn"
793
+ });
794
+ }
795
+ try {
796
+ await supervisor.restartAll();
797
+ } catch (err) {
798
+ process.stderr.write(`[supervisor] additionally failed to restart services after spawn failure: ${err instanceof Error ? err.message : String(err)}\n`);
799
+ }
800
+ return;
801
+ }
802
+ replacement.unref();
803
+ process.exit(0);
804
+ }
805
+ function runNpmInstall(version) {
806
+ return new Promise((resolve) => {
807
+ const child = spawn("npm", [
808
+ "install",
809
+ "-g",
810
+ `clawmini@${version}`
811
+ ], {
812
+ stdio: "inherit",
813
+ env: process.env
814
+ });
815
+ child.on("exit", (code) => {
816
+ if (code === 0) resolve(null);
817
+ else resolve(`npm install -g exited with code ${code}`);
818
+ });
819
+ child.on("error", (err) => {
820
+ resolve(err instanceof Error ? err.message : String(err));
821
+ });
822
+ });
823
+ }
824
+ function waitForSpawn(child, timeoutMs = 5e3) {
825
+ return new Promise((resolve) => {
826
+ let settled = false;
827
+ const settle = (ok) => {
828
+ if (settled) return;
829
+ settled = true;
830
+ resolve(ok);
831
+ };
832
+ child.once("spawn", () => settle(true));
833
+ child.once("error", (err) => {
834
+ process.stderr.write(`[supervisor] replacement spawn error: ${err.message}\n`);
835
+ settle(false);
836
+ });
837
+ setTimeout(() => settle(true), timeoutMs);
838
+ });
839
+ }
840
+
841
+ //#endregion
842
+ export { getMessages as A, writeLiteScript as C, findLastMessage as D, deleteChat as E, listChats as M, setDefaultChatId as N, getChatsDir as O, resolveCompiledScript as S, createChat as T, removeSupervisorPid as _, DAEMON_EVENT_CHAT_STREAM as a, exportLiteToEnvironment as b, daemonEvents as c, emitTyping as d, getControlSocketPath as f, readSupervisorPid as g, getSupervisorPidPath as h, appendMessage as i, isValidChatId as j, getDefaultChatId as k, emitTurnEnded as l, detectInstall as m, startSupervisorControl as n, DAEMON_EVENT_MESSAGE_APPENDED as o, sendControlRequest as p, drainPendingReplies as r, DAEMON_EVENT_TYPING as s, isAcceptableVersion as t, emitTurnStarted as u, writeSupervisorPid as v, DEFAULT_CHAT_ID as w, getLiteScriptContent as x, exportLiteToAllEnvironments as y };
843
+ //# sourceMappingURL=supervisor-actions-CiW56eLi.mjs.map