remoteclaw 0.1.0-next.2abd2fa → 0.1.0-next.2e9a6cd

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 (1052) hide show
  1. package/README.md +9 -7
  2. package/dist/accounts-A8jZK_v9.js +272 -0
  3. package/dist/accounts-BegPt5VR.js +36 -0
  4. package/dist/accounts-BmiimLpP.js +47 -0
  5. package/dist/accounts-Bomfgw0M.js +32 -0
  6. package/dist/accounts-Bpk-loA6.js +47 -0
  7. package/dist/accounts-DAdUdbPk.js +36 -0
  8. package/dist/accounts-WYyfAiie.js +270 -0
  9. package/dist/ack-reactions-CMDRj7fJ.js +446 -0
  10. package/dist/ack-reactions-D7VScSny.js +446 -0
  11. package/dist/acp-cli-BpMS0SsZ.js +1323 -0
  12. package/dist/acp-cli-DkXTlCpF.js +1317 -0
  13. package/dist/active-listener--FT8ewxl.js +37 -0
  14. package/dist/active-listener-C1StcdIA.js +37 -0
  15. package/dist/agent-C76P7tEr.js +703 -0
  16. package/dist/agent-helpers-CK3Obbsi.js +400 -0
  17. package/dist/agent-helpers-KHUla1K7.js +400 -0
  18. package/dist/agent-scope-BrDeaWWf.js +116 -0
  19. package/dist/agent-scope-DxqtYjuJ.js +114 -0
  20. package/dist/agent-ue8p9AIv.js +704 -0
  21. package/dist/agents--24oKN80.js +788 -0
  22. package/dist/agents.config-CWAUoPzG.js +116 -0
  23. package/dist/agents.config-Ck45E_ce.js +116 -0
  24. package/dist/audio-B85HoT7E.js +43 -0
  25. package/dist/audio-BbCUzndz.js +43 -0
  26. package/dist/audio-preflight-B3f0x3zu.js +69 -0
  27. package/dist/audio-preflight-Dv76vFTu.js +64 -0
  28. package/dist/audit-BAbBf2MU.js +3149 -0
  29. package/dist/audit-g55SYz1m.js +3149 -0
  30. package/dist/auth-Bq44qPUd.js +448 -0
  31. package/dist/auth-CVfoI--S.js +281 -0
  32. package/dist/auth-DTWpZJ1a.js +279 -0
  33. package/dist/auth-VItd2pwK.js +448 -0
  34. package/dist/banner-CyPQJybO.js +294 -0
  35. package/dist/binaries-DbgLoSWv.js +13 -0
  36. package/dist/bindings-6KojDoIi.js +69 -0
  37. package/dist/bindings-B6icMMUx.js +69 -0
  38. package/dist/bonjour-discovery-CQU4QbLK.js +378 -0
  39. package/dist/bonjour-discovery-D8aOnk3M.js +378 -0
  40. package/dist/boot/handler.js +42 -69
  41. package/dist/browser-cli-BH41geGr.js +1693 -0
  42. package/dist/browser-cli-u4nrjp1h.js +1688 -0
  43. package/dist/build-info.json +3 -3
  44. package/dist/call-CMDcRlGW.js +2826 -0
  45. package/dist/call-D5YKTYSM.js +2827 -0
  46. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  47. package/dist/catalog-CUY_iTaG.js +185 -0
  48. package/dist/catalog-p6W09S2j.js +185 -0
  49. package/dist/channel-account-context-CA2m93Kt.js +550 -0
  50. package/dist/channel-account-context-Las-t6RP.js +550 -0
  51. package/dist/channel-activity-BD603ehL.js +94 -0
  52. package/dist/channel-activity-CwiF_QMr.js +94 -0
  53. package/dist/channel-activity-daCpxHdT.js +292 -0
  54. package/dist/channel-options-CAlClffy.js +33 -0
  55. package/dist/channel-options-Hl_ep3UG.js +32 -0
  56. package/dist/channel-selection-CHJ7TumC.js +51 -0
  57. package/dist/channel-selection-DR7eW8UG.js +51 -0
  58. package/dist/channel-web-B79j9fSC.js +2134 -0
  59. package/dist/channel-web-DHTTcipm.js +2136 -0
  60. package/dist/channels-cli-DeZ95hcx.js +1427 -0
  61. package/dist/channels-cli-eUCi6jXk.js +1422 -0
  62. package/dist/channels-status-issues-By77REbh.js +18 -0
  63. package/dist/channels-status-issues-DXyOO-KH.js +18 -0
  64. package/dist/chat-envelope-BEDutlnF.js +248 -0
  65. package/dist/chat-envelope-vJJUdDE7.js +248 -0
  66. package/dist/chrome-BuAi16Rq.js +1732 -0
  67. package/dist/chrome-IR-2ukph.js +1733 -0
  68. package/dist/chunk-C1mQSjas.js +341 -0
  69. package/dist/chunk-D7VX4pmT.js +341 -0
  70. package/dist/clack-prompter-BX8SVxtP.js +122 -0
  71. package/dist/clack-prompter-D6HhVlZW.js +121 -0
  72. package/dist/cleanup-utils-DNd0wdKZ.js +94 -0
  73. package/dist/cli/daemon-cli.js +1 -1
  74. package/dist/cli-CK4Y43rx.js +131 -0
  75. package/dist/cli-Cha5Uk29.js +126 -0
  76. package/dist/clipboard-Cbj3McM_.js +31 -0
  77. package/dist/clipboard-Ne8gaWea.js +31 -0
  78. package/dist/command-format-D0vKipG9.js +32 -0
  79. package/dist/command-format-KkslAzwV.js +18 -0
  80. package/dist/command-logger/handler.js +3 -3
  81. package/dist/command-registry-07zlvSN8.js +215 -0
  82. package/dist/commands-DChC3pIF.js +41 -0
  83. package/dist/commands-DFHMoQgH.js +41 -0
  84. package/dist/commands-registry-BN04GIlJ.js +891 -0
  85. package/dist/commands-registry-DbS9NHeX.js +892 -0
  86. package/dist/common-DHHHAcmR.js +156 -0
  87. package/dist/common-De-Lakuh.js +156 -0
  88. package/dist/completion-cli--Jcg794c.js +452 -0
  89. package/dist/completion-cli-B8n7umme.js +452 -0
  90. package/dist/config-BupC6eiJ.js +4223 -0
  91. package/dist/config-CHDaGquZ.js +4225 -0
  92. package/dist/config-cli-Cu79BThx.js +242 -0
  93. package/dist/config-cli-DrJtiyW-.js +247 -0
  94. package/dist/config-guard-BLsqW1qt.js +98 -0
  95. package/dist/config-guard-NQ7jaYM4.js +75 -0
  96. package/dist/config-validation-BLllMW0t.js +18 -0
  97. package/dist/config-validation-DT29VEco.js +18 -0
  98. package/dist/configure-B25UEQnQ.js +889 -0
  99. package/dist/configure-CqMUE4Zw.js +891 -0
  100. package/dist/constants-BbAEYzFC.js +70 -0
  101. package/dist/constants-tLOgmZZ1.js +70 -0
  102. package/dist/control-auth-BFbDXKLK.js +397 -0
  103. package/dist/control-auth-BiiO-FNy.js +397 -0
  104. package/dist/control-ui/assets/index-CuY3pfh1.js +7716 -0
  105. package/dist/control-ui/assets/index-CuY3pfh1.js.map +1 -0
  106. package/dist/control-ui/assets/index-D_fjkN3g.css +1 -0
  107. package/dist/control-ui/index.html +2 -2
  108. package/dist/control-ui-assets-BlpSXjlT.js +186 -0
  109. package/dist/control-ui-assets-eJU2-yvs.js +186 -0
  110. package/dist/conversation-label-Bn5j3lUT.js +36 -0
  111. package/dist/conversation-label-L0QTtKji.js +36 -0
  112. package/dist/cron-cli-BV1o0UgM.js +491 -0
  113. package/dist/cron-cli-C8j-P8GF.js +496 -0
  114. package/dist/daemon-cli-BDvU0Xv6.js +1199 -0
  115. package/dist/daemon-cli-CoNl2Ugf.js +1197 -0
  116. package/dist/daemon-cli.js +53 -97
  117. package/dist/daemon-install-BMEnzWwq.js +60 -0
  118. package/dist/daemon-install-BkUJbdPC.js +55 -0
  119. package/dist/daemon-install-helpers-B9kMxC1v.js +462 -0
  120. package/dist/daemon-install-helpers-DoYR5z4H.js +462 -0
  121. package/dist/deliver-D8P9_nk-.js +481 -0
  122. package/dist/deliver-F9ed3dhp.js +481 -0
  123. package/dist/delivery-queue-B6TuHppj.js +244 -0
  124. package/dist/delivery-queue-BZc3AiGu.js +244 -0
  125. package/dist/devices-cli-DZgxMNLD.js +322 -0
  126. package/dist/devices-cli-DlG9ehK0.js +317 -0
  127. package/dist/diagnostics-CK2HGAFw.js +46 -0
  128. package/dist/diagnostics-G-C-IuxO.js +46 -0
  129. package/dist/directory-cli-CY6tHRIZ.js +218 -0
  130. package/dist/directory-cli-HyvRJ1Ua.js +223 -0
  131. package/dist/dm-policy-shared-1FdjwGtJ.js +22 -0
  132. package/dist/dm-policy-shared-CT3er5HI.js +22 -0
  133. package/dist/dns-cli-Cu-wYvll.js +203 -0
  134. package/dist/dns-cli-DQdnNJh4.js +198 -0
  135. package/dist/dock-D038fZZl.js +929 -0
  136. package/dist/dock-D5pZ3a44.js +928 -0
  137. package/dist/doctor-completion-BrHnayfU.js +92 -0
  138. package/dist/doctor-completion-CoZP2KiR.js +92 -0
  139. package/dist/doctor-config-flow-DJ1nWCTZ.js +1935 -0
  140. package/dist/doctor-config-flow-DYhXUwEq.js +1934 -0
  141. package/dist/enable-B5dIjgnm.js +59 -0
  142. package/dist/enable-FmiEY4ng.js +59 -0
  143. package/dist/entry.js +14 -16
  144. package/dist/env-DUb5GiQe.js +60 -0
  145. package/dist/env-vars-C8WMB8Ix.js +93 -0
  146. package/dist/errors-CdmXrBic.js +35 -0
  147. package/dist/errors-DdLfwEVi.js +35 -0
  148. package/dist/exec-BhkXWg7V.js +164 -0
  149. package/dist/exec-ClUTXFZ9.js +164 -0
  150. package/dist/export-html/template.css +0 -36
  151. package/dist/export-html/template.js +1 -32
  152. package/dist/extensionAPI.js +1015 -142
  153. package/dist/fetch-CCuD0LYV.js +67 -0
  154. package/dist/fetch-JBWLkOpL.js +67 -0
  155. package/dist/fetch-oku6r8tJ.js +67 -0
  156. package/dist/file-lock-6NXMPZTT.js +107 -0
  157. package/dist/file-lock-Ks-RPU6W.js +107 -0
  158. package/dist/fs-safe-93aDW4mH.js +98 -0
  159. package/dist/fs-safe-ACrBwOF5.js +88 -0
  160. package/dist/gateway-cli-CJs4Mxlv.js +23730 -0
  161. package/dist/gateway-cli-gUVR20v7.js +23725 -0
  162. package/dist/gateway-rpc-CSdrtPzg.js +28 -0
  163. package/dist/gateway-rpc-PNA_wUoe.js +28 -0
  164. package/dist/gmail-setup-utils-DNZEf6T0.js +422 -0
  165. package/dist/gmail-setup-utils-KPAKWwGy.js +423 -0
  166. package/dist/health-BCidscV-.js +1417 -0
  167. package/dist/health-Cw2dr19V.js +1414 -0
  168. package/dist/health-format-DOhfU1rY.js +28 -0
  169. package/dist/heartbeat-visibility-C5Vxudi9.js +125 -0
  170. package/dist/heartbeat-visibility-DHeZ-ko1.js +125 -0
  171. package/dist/help-format-Ch0EWh7N.js +17 -0
  172. package/dist/helpers-B4NWktS8.js +10 -0
  173. package/dist/hook-runner-global-Vj-YQxeR.js +527 -0
  174. package/dist/hooks-cli---vy0V0j.js +1218 -0
  175. package/dist/hooks-cli-CX-JUHdJ.js +1223 -0
  176. package/dist/image-ops-DMl7j7f4.js +354 -0
  177. package/dist/image-ops-DpkTOzhI.js +354 -0
  178. package/dist/import-DIjlFm_Y.js +493 -0
  179. package/dist/import-DdQvVR-_.js +495 -0
  180. package/dist/inbound-context-CmmmT8IP.js +68 -0
  181. package/dist/inbound-context-oxIWzEgc.js +68 -0
  182. package/dist/inbound-path-policy-BdmTOUka.js +90 -0
  183. package/dist/inbound-path-policy-DYTLjca8.js +90 -0
  184. package/dist/index.js +106 -105
  185. package/dist/inspect-C9d1V-lI.js +559 -0
  186. package/dist/inspect-rHjRqr3W.js +559 -0
  187. package/dist/installs-QUjSL2ZA.js +325 -0
  188. package/dist/installs-vT5wnxC4.js +325 -0
  189. package/dist/ipv4-DdcyK1aU.js +46 -0
  190. package/dist/ipv4-OHvujh00.js +46 -0
  191. package/dist/ir-CnMQRFBu.js +940 -0
  192. package/dist/json-files-BiA_B-xm.js +46 -0
  193. package/dist/links-CIHbVNO_.js +15 -0
  194. package/dist/loader-CYigLbch.js +22404 -0
  195. package/dist/loader-ElWX62xE.js +22401 -0
  196. package/dist/local-roots-B0QcJDJI.js +313 -0
  197. package/dist/local-roots-BfXsZRkm.js +314 -0
  198. package/dist/logger-BtwpYD7c.js +49 -0
  199. package/dist/logging-CLc3Umm0.js +20 -0
  200. package/dist/login-C8jHYLxN.js +61 -0
  201. package/dist/login-D__FYZX9.js +62 -0
  202. package/dist/login-qr-C0Gd6ybl.js +323 -0
  203. package/dist/login-qr-D7dw54Yp.js +328 -0
  204. package/dist/logs-cli-CFOVARdJ.js +234 -0
  205. package/dist/logs-cli-DtAR__VH.js +239 -0
  206. package/dist/markdown-tables-ChBqQA_Q.js +29 -0
  207. package/dist/markdown-tables-xMuH3QnS.js +29 -0
  208. package/dist/media-CmiNXiOZ.js +10453 -0
  209. package/dist/media-DYopaoc0.js +940 -0
  210. package/dist/message-action-names-CACBi-HB.js +2521 -0
  211. package/dist/message-action-names-CFwlz01T.js +2521 -0
  212. package/dist/message-channel-DF4I2vOK.js +91 -0
  213. package/dist/net-COL170MG.js +225 -0
  214. package/dist/net-QZ8IHNXc.js +225 -0
  215. package/dist/node-cli-CW8jOcHO.js +24 -0
  216. package/dist/nodes-cli-B4lvU9N5.js +1349 -0
  217. package/dist/nodes-cli-B8iTBsI6.js +1344 -0
  218. package/dist/nodes-screen-CZCXHrWB.js +250 -0
  219. package/dist/nodes-screen-C_K1vcS5.js +250 -0
  220. package/dist/note-BVerR3D5.js +92 -0
  221. package/dist/note-Dk8-EaJg.js +92 -0
  222. package/dist/npm-registry-spec-Dma0KHft.js +786 -0
  223. package/dist/npm-registry-spec-vYkxZb6u.js +786 -0
  224. package/dist/npm-resolution-CcZYnzrL.js +86 -0
  225. package/dist/npm-resolution-DsATEEGx.js +86 -0
  226. package/dist/onboard-Csm4bDd_.js +438 -0
  227. package/dist/onboard-D1b535pC.js +436 -0
  228. package/dist/onboard-channels-5EIXyDZh.js +2547 -0
  229. package/dist/onboard-channels-bedB47Hs.js +2548 -0
  230. package/dist/onboard-config-CcPV3Cqz.js +39 -0
  231. package/dist/onboard-config-DcTaxmuf.js +39 -0
  232. package/dist/onboard-helpers-BHNXyhA4.js +364 -0
  233. package/dist/onboard-helpers-eTUU00t8.js +363 -0
  234. package/dist/onboard-remote-DwDKQk1K.js +127 -0
  235. package/dist/onboard-remote-TPbiye5m.js +127 -0
  236. package/dist/onboarding-D0YGZ_Ux.js +588 -0
  237. package/dist/onboarding-DCfmKzl2.js +586 -0
  238. package/dist/onboarding.finalize-BhpsVwME.js +399 -0
  239. package/dist/onboarding.finalize-CY8vgmi9.js +402 -0
  240. package/dist/onboarding.gateway-config-C_eqpJ7D.js +192 -0
  241. package/dist/onboarding.gateway-config-DR1ey6tU.js +199 -0
  242. package/dist/outbound-Be4BgVqF.js +220 -0
  243. package/dist/outbound-CXJLn8kn.js +221 -0
  244. package/dist/outbound-attachment-CbNLn0lk.js +18 -0
  245. package/dist/outbound-attachment-DNCMF74c.js +18 -0
  246. package/dist/outbound-attachment-DaStRTGv.js +18 -0
  247. package/dist/pairing-cli-CxGDUsLT.js +128 -0
  248. package/dist/pairing-cli-D83T3PG9.js +123 -0
  249. package/dist/pairing-labels-6f8FqSS5.js +9 -0
  250. package/dist/pairing-labels-CI5j-OUT.js +9 -0
  251. package/dist/pairing-store-DnTHRcnO.js +459 -0
  252. package/dist/pairing-store-ONzqxcNb.js +460 -0
  253. package/dist/path-env-D7VB7sOO.js +89 -0
  254. package/dist/path-env-DFiYvvI-.js +89 -0
  255. package/dist/path-safety-BshBsw4P.js +14 -0
  256. package/dist/path-safety-CZbhQciI.js +14 -0
  257. package/dist/plugin-auto-enable-BnCQKkIK.js +302 -0
  258. package/dist/plugin-auto-enable-CFRs-pcA.js +301 -0
  259. package/dist/plugin-registry-CV5pfXOU.js +33 -0
  260. package/dist/plugin-registry-CmG34W0u.js +33 -0
  261. package/dist/plugin-sdk/agents/agent-helpers.d.ts +0 -1
  262. package/dist/plugin-sdk/agents/agent-scope.d.ts +10 -0
  263. package/dist/plugin-sdk/agents/agent-types.d.ts +1 -6
  264. package/dist/plugin-sdk/agents/agent-utils.d.ts +0 -14
  265. package/dist/plugin-sdk/agents/provider-utils.d.ts +0 -1
  266. package/dist/plugin-sdk/agents/subagent-spawn.d.ts +0 -1
  267. package/dist/plugin-sdk/agents/tools/sessions-helpers.d.ts +0 -1
  268. package/dist/plugin-sdk/auth/constants.d.ts +16 -0
  269. package/dist/plugin-sdk/auth/display.d.ts +7 -0
  270. package/dist/plugin-sdk/auth/doctor.d.ts +8 -0
  271. package/dist/plugin-sdk/auth/env-injection.d.ts +41 -0
  272. package/dist/plugin-sdk/auth/index.d.ts +8 -0
  273. package/dist/plugin-sdk/auth/oauth.d.ts +14 -0
  274. package/dist/plugin-sdk/auth/provider-auth.d.ts +40 -0
  275. package/dist/plugin-sdk/auth/session-override.d.ts +18 -0
  276. package/dist/plugin-sdk/auto-reply/reply/agent-runner-execution.d.ts +0 -1
  277. package/dist/plugin-sdk/auto-reply/reply/agent-runner-utils.d.ts +0 -2
  278. package/dist/plugin-sdk/auto-reply/reply/commands-status.d.ts +1 -4
  279. package/dist/plugin-sdk/auto-reply/reply/commands-types.d.ts +1 -4
  280. package/dist/plugin-sdk/auto-reply/reply/directive-handling.levels.d.ts +1 -7
  281. package/dist/plugin-sdk/auto-reply/reply/directive-handling.params.d.ts +1 -4
  282. package/dist/plugin-sdk/auto-reply/reply/directive-handling.parse.d.ts +1 -7
  283. package/dist/plugin-sdk/auto-reply/reply/directive-handling.shared.d.ts +1 -4
  284. package/dist/plugin-sdk/auto-reply/reply/directives.d.ts +3 -15
  285. package/dist/plugin-sdk/auto-reply/reply/get-reply-directives.d.ts +1 -5
  286. package/dist/plugin-sdk/auto-reply/reply/get-reply-inline-actions.d.ts +1 -5
  287. package/dist/plugin-sdk/auto-reply/reply/get-reply-run.d.ts +1 -5
  288. package/dist/plugin-sdk/auto-reply/reply/queue/types.d.ts +1 -3
  289. package/dist/plugin-sdk/auto-reply/reply/response-prefix-template.d.ts +4 -6
  290. package/dist/plugin-sdk/auto-reply/reply/session-run-accounting.d.ts +0 -7
  291. package/dist/plugin-sdk/auto-reply/reply/session-updates.d.ts +0 -10
  292. package/dist/plugin-sdk/auto-reply/reply.d.ts +1 -1
  293. package/dist/plugin-sdk/auto-reply/status.d.ts +2 -6
  294. package/dist/plugin-sdk/auto-reply/thinking.d.ts +0 -11
  295. package/dist/plugin-sdk/auto-reply/types.d.ts +1 -2
  296. package/dist/plugin-sdk/commands/agent/session.d.ts +1 -2
  297. package/dist/plugin-sdk/config/defaults.d.ts +0 -1
  298. package/dist/plugin-sdk/config/sessions/types.d.ts +0 -8
  299. package/dist/plugin-sdk/config/types.agent-defaults.d.ts +28 -112
  300. package/dist/plugin-sdk/config/types.agents.d.ts +8 -0
  301. package/dist/plugin-sdk/config/types.messages.d.ts +1 -2
  302. package/dist/plugin-sdk/config/types.tools.d.ts +1 -1
  303. package/dist/plugin-sdk/config/zod-schema.agent-defaults.d.ts +9 -66
  304. package/dist/plugin-sdk/config/zod-schema.agent-runtime.d.ts +5 -13
  305. package/dist/plugin-sdk/config/zod-schema.agents.d.ts +12 -76
  306. package/dist/plugin-sdk/config/zod-schema.d.ts +12 -76
  307. package/dist/plugin-sdk/daemon/constants.d.ts +2 -2
  308. package/dist/plugin-sdk/gateway/protocol/index.d.ts +1 -3
  309. package/dist/plugin-sdk/gateway/protocol/schema/sessions.d.ts +0 -2
  310. package/dist/plugin-sdk/gateway/session-utils.types.d.ts +0 -2
  311. package/dist/plugin-sdk/index.js +108 -134
  312. package/dist/plugin-sdk/middleware/auth-key-retry.d.ts +32 -0
  313. package/dist/plugin-sdk/middleware/channel-bridge.d.ts +4 -0
  314. package/dist/plugin-sdk/middleware/error-classifier.d.ts +5 -0
  315. package/dist/plugin-sdk/middleware/media-resolver.d.ts +12 -0
  316. package/dist/plugin-sdk/middleware/runtime-factory.d.ts +42 -0
  317. package/dist/plugin-sdk/middleware/types.d.ts +33 -1
  318. package/dist/plugin-sdk/plugins/types.d.ts +1 -1
  319. package/dist/plugin-sdk/terminal/palette.d.ts +2 -2
  320. package/dist/plugins-B4waLB_f.js +453 -0
  321. package/dist/plugins-D6-JJ1il.js +455 -0
  322. package/dist/plugins-cli-DG2zHgdP.js +799 -0
  323. package/dist/plugins-cli-DZvQzkWd.js +794 -0
  324. package/dist/ports-BcTKFlWl.js +96 -0
  325. package/dist/ports-DAc2AlZE.js +316 -0
  326. package/dist/ports-HiuYk3bt.js +96 -0
  327. package/dist/ports-dEePqmCq.js +370 -0
  328. package/dist/program-CX-EtQ9W.js +245 -0
  329. package/dist/program-context-R3wsjl2f.js +474 -0
  330. package/dist/progress-DQ1drugY.js +124 -0
  331. package/dist/prompt-edYTUtju.js +21 -0
  332. package/dist/prompt-select-styled-BzL7v1zQ.js +1647 -0
  333. package/dist/prompt-select-styled-g5q4srtu.js +1650 -0
  334. package/dist/prompt-style-CYEpbwXH.js +9 -0
  335. package/dist/provider-dispatcher-D7qFGoUR.js +660 -0
  336. package/dist/provider-dispatcher-dB_rm6tV.js +659 -0
  337. package/dist/push-apns-DQwR-i4_.js +713 -0
  338. package/dist/push-apns-Dj5RApCY.js +711 -0
  339. package/dist/pw-ai-DOQMJFB-.js +1911 -0
  340. package/dist/pw-ai-oqtYDmjQ.js +1907 -0
  341. package/dist/qr-cli-CBGm_Cik.js +353 -0
  342. package/dist/qr-cli-D2jZPdW9.js +348 -0
  343. package/dist/redact-gXuh8MFk.js +191 -0
  344. package/dist/redact-snapshot-B-2V56Yb.js +2016 -0
  345. package/dist/redact-snapshot-CD36XSYE.js +2016 -0
  346. package/dist/register.agent-DLSuiqWE.js +287 -0
  347. package/dist/register.agent-DcvEt3hG.js +1044 -0
  348. package/dist/register.configure-3edoYZai.js +131 -0
  349. package/dist/register.configure-CyOJCmnY.js +125 -0
  350. package/dist/register.import-Cku0T-PA.js +31 -0
  351. package/dist/register.import-Dr8TiUVx.js +28 -0
  352. package/dist/register.maintenance-5aaPQbJk.js +495 -0
  353. package/dist/register.maintenance-DPSswZDJ.js +498 -0
  354. package/dist/register.message-BaSVFv92.js +682 -0
  355. package/dist/register.message-FEI0RiNN.js +687 -0
  356. package/dist/register.onboard-CO1UZL-9.js +258 -0
  357. package/dist/register.onboard-DuLKxjXl.js +263 -0
  358. package/dist/register.setup-CFYYd_Ev.js +115 -0
  359. package/dist/register.setup-P0UHDBMS.js +110 -0
  360. package/dist/register.status-health-sessions-D_3vm2yw.js +424 -0
  361. package/dist/register.status-health-sessions-z9x79dmg.js +665 -0
  362. package/dist/register.subclis-B-d970d6.js +267 -0
  363. package/dist/replies-BvarRpHb.js +136 -0
  364. package/dist/replies-CSzm5168.js +136 -0
  365. package/dist/reply-CTgksTO1.js +13695 -0
  366. package/dist/reply-CUyafs4J.js +13692 -0
  367. package/dist/reply-directives-Caq4zVTg.js +182 -0
  368. package/dist/reply-directives-D91fapDF.js +182 -0
  369. package/dist/reply-payloads-te0YnESs.js +527 -0
  370. package/dist/reply-prefix-Bv8Mv9q8.js +37 -0
  371. package/dist/reply-prefix-Rk_UEaJa.js +37 -0
  372. package/dist/resolve-route-BPa6q23t.js +249 -0
  373. package/dist/resolve-route-CN9BEALz.js +249 -0
  374. package/dist/response-prefix-template-D-ptXREi.js +134 -0
  375. package/dist/response-prefix-template-Dckjdftg.js +134 -0
  376. package/dist/retry-BcZuGfnV.js +77 -0
  377. package/dist/retry-BzWBtFpP.js +77 -0
  378. package/dist/run-main-BugUkGES.js +303 -0
  379. package/dist/runner-CVMXkHe9.js +2295 -0
  380. package/dist/runner-DOWTBU0-.js +2295 -0
  381. package/dist/runtime-guard-CXt4yzo-.js +60 -0
  382. package/dist/secure-random-CBwDBdj1.js +44 -0
  383. package/dist/security-cli-BQzdzJUp.js +479 -0
  384. package/dist/security-cli-D2d8RvsT.js +485 -0
  385. package/dist/send-B3G3I3II.js +349 -0
  386. package/dist/send-B6IB6ELR.js +547 -0
  387. package/dist/send-BT8XEvZB.js +332 -0
  388. package/dist/send-BTupAHVX.js +2245 -0
  389. package/dist/send-BZCfto_I.js +1174 -0
  390. package/dist/send-C5EDjThR.js +492 -0
  391. package/dist/send-CBM54hgN.js +349 -0
  392. package/dist/send-CPBd6ItT.js +29 -0
  393. package/dist/send-CzYm7ULP.js +2245 -0
  394. package/dist/send-D2m_x8xM.js +374 -0
  395. package/dist/send-DmEBPE2S.js +1779 -0
  396. package/dist/send-Dt4iCx61.js +426 -0
  397. package/dist/send-MWjpLHEV.js +11 -0
  398. package/dist/send-qpwqt34s.js +547 -0
  399. package/dist/send-rW25uKNz.js +1776 -0
  400. package/dist/send-uqa6CNuP.js +492 -0
  401. package/dist/server-BhmYVCED.js +201 -0
  402. package/dist/server-DaUw1o2B.js +206 -0
  403. package/dist/server-lifecycle-BeZsBQwF.js +2437 -0
  404. package/dist/server-lifecycle-C2F1_TE2.js +2437 -0
  405. package/dist/server-node-events-DoRFbKCT.js +390 -0
  406. package/dist/server-node-events-jbbbt-4R.js +395 -0
  407. package/dist/service-BDt-zUvV.js +670 -0
  408. package/dist/service-Os7W1F2S.js +670 -0
  409. package/dist/session-B9KGKVrY.js +170 -0
  410. package/dist/session-DzAupDyj.js +170 -0
  411. package/dist/session-cost-usage-BYCI739a.js +627 -0
  412. package/dist/session-cost-usage-DGsPcuMj.js +627 -0
  413. package/dist/session-dirs-BIg5RHAh.js +947 -0
  414. package/dist/session-dirs-DwDxjK1p.js +947 -0
  415. package/dist/session-utils-BgWDCbyx.js +622 -0
  416. package/dist/session-utils-CxxOeC1M.js +622 -0
  417. package/dist/sessions-Bwu0l_CG.js +2569 -0
  418. package/dist/sessions-CiuFFCnt.js +247 -0
  419. package/dist/shell-env-CsV_IkJj.js +163 -0
  420. package/dist/shell-env-hZW9j-Uc.js +163 -0
  421. package/dist/ssrf-B-rF_tZB.js +183 -0
  422. package/dist/ssrf-D6fl_7ww.js +183 -0
  423. package/dist/status-BOFm7iyj.js +2065 -0
  424. package/dist/status-RI2y_M21.js +2061 -0
  425. package/dist/status.update-DbO7izip.js +79 -0
  426. package/dist/status.update-wXyvcztI.js +79 -0
  427. package/dist/store-BLGrRL_E.js +64 -0
  428. package/dist/store-BYhcsOLr.js +64 -0
  429. package/dist/store-Dv76bGHg.js +2571 -0
  430. package/dist/store-Dw93tSB-.js +53 -0
  431. package/dist/subagent-registry-DWL-tayF.js +4856 -0
  432. package/dist/subagent-registry-HjR1tO3-.js +4854 -0
  433. package/dist/subsystem-BCkt9Ocb.js +1079 -0
  434. package/dist/subsystem-BgxIzx7w.js +1137 -0
  435. package/dist/system-cli-DtrDDmCt.js +71 -0
  436. package/dist/system-cli-xDr_Yyaa.js +76 -0
  437. package/dist/systemd-BlbIQ1PV.js +547 -0
  438. package/dist/systemd-DzXePo7r.js +547 -0
  439. package/dist/systemd-linger-mLbBF4pa.js +75 -0
  440. package/dist/systemd-linger-qlGGW2JB.js +75 -0
  441. package/dist/table-V_9n7CjP.js +279 -0
  442. package/dist/tables-Cy3gObW7.js +55 -0
  443. package/dist/tables-DAuk-Y6F.js +55 -0
  444. package/dist/tables-DRh09aPZ.js +55 -0
  445. package/dist/tailnet-BoTa0e2q.js +40 -0
  446. package/dist/tailnet-Cy0Q27lj.js +40 -0
  447. package/dist/tailscale-CiWkh0vS.js +230 -0
  448. package/dist/tailscale-Driw3j8E.js +230 -0
  449. package/dist/targets-3hewwPvM.js +120 -0
  450. package/dist/targets-Bkw_co-B.js +220 -0
  451. package/dist/targets-C1Tt0ZWd.js +2406 -0
  452. package/dist/targets-CsrqF2M4.js +650 -0
  453. package/dist/targets-DKriCISG.js +53 -0
  454. package/dist/targets-DTM2OPnS.js +650 -0
  455. package/dist/targets-DhhaK2xG.js +53 -0
  456. package/dist/targets-tDrl_ioQ.js +46 -0
  457. package/dist/targets-yq1kGK1_.js +2407 -0
  458. package/dist/thinking-XA5P_zFw.js +88 -0
  459. package/dist/thinking-l-rrvZwu.js +88 -0
  460. package/dist/tokens-7ZtWRjA3.js +21 -0
  461. package/dist/tool-display-AxpSXZVq.js +785 -0
  462. package/dist/tool-display-D6GD-41Y.js +785 -0
  463. package/dist/tool-images-D16vIWPg.js +263 -0
  464. package/dist/tool-images-IVIZ29ID.js +263 -0
  465. package/dist/trash--8b4GDyV.js +125 -0
  466. package/dist/trash-ivbG2QWV.js +125 -0
  467. package/dist/tui-Cbe1EW-B.js +3319 -0
  468. package/dist/tui-Dj3XrTCV.js +3319 -0
  469. package/dist/tui-cli-EGqEcdfE.js +64 -0
  470. package/dist/tui-cli-KKmqnNs2.js +59 -0
  471. package/dist/update-DruVguh4.js +349 -0
  472. package/dist/update-cli-C5tdQeGG.js +1371 -0
  473. package/dist/update-cli-Canq11sh.js +1374 -0
  474. package/dist/update-y8nz-3OC.js +349 -0
  475. package/dist/usage-CAuX4vsd.js +5384 -0
  476. package/dist/utils-C5daYcFn.js +631 -0
  477. package/dist/web-B9gR_cGR.js +3071 -0
  478. package/dist/web-DZ8ahrhK.js +77 -0
  479. package/dist/web-DkYPsnyd.js +71 -0
  480. package/dist/webhooks-cli-DFqGwW1f.js +329 -0
  481. package/dist/webhooks-cli-y-E-q0Xo.js +334 -0
  482. package/dist/whatsapp-actions-BXIe-Uei.js +123 -0
  483. package/dist/whatsapp-actions-BictxOCB.js +129 -0
  484. package/dist/widearea-dns-fHQt5-Q3.js +127 -0
  485. package/dist/workspace-DvbSDgO_.js +449 -0
  486. package/dist/workspace-zLfKNRwR.js +447 -0
  487. package/dist/zod-schema-B9RGngMW.js +2696 -0
  488. package/dist/zod-schema-D3hQ5SKe.js +2696 -0
  489. package/extensions/matrix/src/matrix/monitor/replies.ts +0 -24
  490. package/extensions/mattermost/src/mattermost/monitor-helpers.ts +0 -1
  491. package/package.json +3 -3
  492. package/dist/accounts-BFy_Z3od.js +0 -272
  493. package/dist/accounts-BTXSfPWi.js +0 -270
  494. package/dist/accounts-BxGS70Do.js +0 -36
  495. package/dist/accounts-CNY1TGj1.js +0 -47
  496. package/dist/accounts-DBohBlww.js +0 -32
  497. package/dist/accounts-DqRQ75w3.js +0 -36
  498. package/dist/accounts-iODF3SK2.js +0 -47
  499. package/dist/ack-reactions-B11TAC2D.js +0 -446
  500. package/dist/ack-reactions-BWVjL4H6.js +0 -446
  501. package/dist/acp-cli-CA1xMmVo.js +0 -1320
  502. package/dist/acp-cli-CGo6fJVZ.js +0 -1326
  503. package/dist/active-listener-VzhWW8W6.js +0 -37
  504. package/dist/active-listener-z0qVEcom.js +0 -37
  505. package/dist/agent-CTizRPIJ.js +0 -732
  506. package/dist/agent-D2RVoS5g.js +0 -731
  507. package/dist/agent-helpers-B6VfZ9_u.js +0 -606
  508. package/dist/agent-helpers-CTx5KKJu.js +0 -606
  509. package/dist/agent-scope-BGYzhtWQ.js +0 -121
  510. package/dist/agent-scope-C50VuLKh.js +0 -119
  511. package/dist/agents-BuYn-obw.js +0 -788
  512. package/dist/agents.config-BSTxuTVd.js +0 -116
  513. package/dist/agents.config-p3V3b9u6.js +0 -116
  514. package/dist/audio-DPOuhNq7.js +0 -43
  515. package/dist/audio-VBcVDa08.js +0 -43
  516. package/dist/audio-preflight-BwmCYeuM.js +0 -64
  517. package/dist/audio-preflight-co8gjlPX.js +0 -69
  518. package/dist/audit-oH4urD3G.js +0 -3138
  519. package/dist/audit-qgtCT3ik.js +0 -3138
  520. package/dist/auth-CAczFgAO.js +0 -448
  521. package/dist/auth-Deh9i9Eg.js +0 -448
  522. package/dist/auth-profiles-BquJGKLC.js +0 -279
  523. package/dist/auth-profiles-D8vKiBPq.js +0 -281
  524. package/dist/banner-Cf978khN.js +0 -294
  525. package/dist/binaries-DXW6oATV.js +0 -13
  526. package/dist/bindings-CRU_udk8.js +0 -69
  527. package/dist/bindings-DQZAu8Wv.js +0 -69
  528. package/dist/bonjour-discovery-DdAk1VyO.js +0 -378
  529. package/dist/bonjour-discovery-DuhiIZZx.js +0 -378
  530. package/dist/browser-cli-CZC4h5V4.js +0 -1687
  531. package/dist/browser-cli-DAgi_aQk.js +0 -1692
  532. package/dist/call-BbwtB9Y-.js +0 -2828
  533. package/dist/call-PivL7Uex.js +0 -2829
  534. package/dist/catalog-BqO6yem_.js +0 -185
  535. package/dist/catalog-DFmaYwfk.js +0 -185
  536. package/dist/channel-account-context-CvIDAtHS.js +0 -550
  537. package/dist/channel-account-context-q-o0pG1A.js +0 -550
  538. package/dist/channel-activity-BaCNOZpP.js +0 -94
  539. package/dist/channel-activity-C-G4n9BK.js +0 -292
  540. package/dist/channel-activity-DTKGf3j5.js +0 -94
  541. package/dist/channel-options-Cyappik_.js +0 -32
  542. package/dist/channel-options-DFnypY5S.js +0 -33
  543. package/dist/channel-selection-BGl53D5K.js +0 -51
  544. package/dist/channel-selection-NNPbxnyZ.js +0 -51
  545. package/dist/channel-web-DmhVkWbP.js +0 -2134
  546. package/dist/channel-web-kRC3UYBJ.js +0 -2136
  547. package/dist/channels-cli-C5XRkPJl.js +0 -1421
  548. package/dist/channels-cli-D6TqCI0m.js +0 -1426
  549. package/dist/channels-status-issues-CUc9mpeW.js +0 -18
  550. package/dist/channels-status-issues-DwRDzwrV.js +0 -18
  551. package/dist/chat-envelope-DEZ-5RY8.js +0 -248
  552. package/dist/chat-envelope-el7Uo-Fe.js +0 -248
  553. package/dist/chrome-0QaGKb3L.js +0 -1732
  554. package/dist/chrome-CFeWdP0Y.js +0 -1733
  555. package/dist/chunk-CSQfUhgF.js +0 -341
  556. package/dist/chunk-D0Y_w4oX.js +0 -341
  557. package/dist/clack-prompter-B7tOxhJd.js +0 -122
  558. package/dist/clack-prompter-CCFnKP_1.js +0 -121
  559. package/dist/cleanup-utils-CqAVZz2b.js +0 -94
  560. package/dist/cli-BR2J3c4l.js +0 -125
  561. package/dist/cli-C1q1vSmN.js +0 -130
  562. package/dist/clipboard-D7_SKHPK.js +0 -31
  563. package/dist/clipboard-Dzkx6Q2K.js +0 -31
  564. package/dist/command-format-CVfo8I5f.js +0 -18
  565. package/dist/command-format-DgXcqxBt.js +0 -32
  566. package/dist/command-registry-CYjvOp8W.js +0 -215
  567. package/dist/commands-CDonBOrw.js +0 -41
  568. package/dist/commands-D_-bgTlO.js +0 -41
  569. package/dist/commands-registry-CWJv6xe2.js +0 -892
  570. package/dist/commands-registry-Ci8_cFk9.js +0 -893
  571. package/dist/common-CMI-qsF8.js +0 -156
  572. package/dist/common-DSVmydhm.js +0 -156
  573. package/dist/completion-cli-8iZJqfmX.js +0 -452
  574. package/dist/completion-cli-CYDjEZSt.js +0 -452
  575. package/dist/config-D5XU45KD.js +0 -6953
  576. package/dist/config-FHu9Bn4R.js +0 -6951
  577. package/dist/config-cli-Gehy4sav.js +0 -241
  578. package/dist/config-cli-RC9qMgJq.js +0 -246
  579. package/dist/config-guard-J-Q_DFWk.js +0 -97
  580. package/dist/config-guard-cB5a_ANg.js +0 -75
  581. package/dist/config-validation-BPNyd9_3.js +0 -18
  582. package/dist/config-validation-BPWuvhVe.js +0 -18
  583. package/dist/configure-CC2XdRRm.js +0 -891
  584. package/dist/configure-DxFBJuhZ.js +0 -889
  585. package/dist/constants-BmRFoHl0.js +0 -67
  586. package/dist/constants-C9WPAluB.js +0 -67
  587. package/dist/control-auth-D0tpV3ts.js +0 -397
  588. package/dist/control-auth-_-0PGRUs.js +0 -397
  589. package/dist/control-ui/assets/index-B4ZM1lW1.js +0 -7738
  590. package/dist/control-ui/assets/index-B4ZM1lW1.js.map +0 -1
  591. package/dist/control-ui/assets/index-PED72sKF.css +0 -1
  592. package/dist/control-ui-assets-Cx_mw4D0.js +0 -186
  593. package/dist/control-ui-assets-W1AUuGrO.js +0 -186
  594. package/dist/conversation-label-C4SDz4sT.js +0 -36
  595. package/dist/conversation-label-D1frnvYe.js +0 -36
  596. package/dist/cron-cli-BzERxhr5.js +0 -495
  597. package/dist/cron-cli-C8j_uslU.js +0 -490
  598. package/dist/daemon-cli-C95XNbX0.js +0 -1199
  599. package/dist/daemon-cli-e6sURMqd.js +0 -1197
  600. package/dist/daemon-install-CcohRvKV.js +0 -55
  601. package/dist/daemon-install-DDshfT0J.js +0 -60
  602. package/dist/daemon-install-helpers-CFGAfRlj.js +0 -462
  603. package/dist/daemon-install-helpers-DIUzSFG1.js +0 -462
  604. package/dist/defaults-B5KStIBg.js +0 -7
  605. package/dist/defaults-xUAL2Z-F.js +0 -7
  606. package/dist/deliver-912khjLK.js +0 -481
  607. package/dist/deliver-D56J4-1F.js +0 -481
  608. package/dist/delivery-queue-Cfa9Wmxp.js +0 -244
  609. package/dist/delivery-queue-CxVRi4tw.js +0 -244
  610. package/dist/devices-cli-0qDhTgZR.js +0 -316
  611. package/dist/devices-cli-6SKMR2bV.js +0 -321
  612. package/dist/diagnostics-99iCgBUh.js +0 -46
  613. package/dist/diagnostics-VC0cz7kX.js +0 -46
  614. package/dist/directory-cli-5YXdoVdn.js +0 -217
  615. package/dist/directory-cli-D3IKCHmn.js +0 -222
  616. package/dist/dm-policy-shared-4rkjhcrM.js +0 -22
  617. package/dist/dm-policy-shared-D8lgnmrC.js +0 -22
  618. package/dist/dns-cli-11CtErVU.js +0 -197
  619. package/dist/dns-cli-SiEd_1Lq.js +0 -202
  620. package/dist/dock-BqNINg7k.js +0 -928
  621. package/dist/dock-CQuu41bw.js +0 -929
  622. package/dist/doctor-completion-BR1SlAT3.js +0 -92
  623. package/dist/doctor-completion-CZwpEhIK.js +0 -92
  624. package/dist/doctor-config-flow-BVkHcvoj.js +0 -1933
  625. package/dist/doctor-config-flow-DVYRn0An.js +0 -1934
  626. package/dist/enable-DcJnkzfz.js +0 -59
  627. package/dist/enable-ibNq4UWy.js +0 -59
  628. package/dist/env-DeF64iu0.js +0 -60
  629. package/dist/env-vars-7aZqKPhk.js +0 -93
  630. package/dist/errors-8F-77i6m.js +0 -35
  631. package/dist/errors-DZ199hOo.js +0 -35
  632. package/dist/exec-DbKuYyM1.js +0 -164
  633. package/dist/exec-DkFE7lqU.js +0 -164
  634. package/dist/fetch-BFSBLBkA.js +0 -67
  635. package/dist/fetch-C6XKGA11.js +0 -67
  636. package/dist/fetch-CEDsOiql.js +0 -67
  637. package/dist/file-lock-CIvloidc.js +0 -107
  638. package/dist/file-lock-CzBL_VIx.js +0 -107
  639. package/dist/fs-safe-DSwT85uK.js +0 -88
  640. package/dist/fs-safe-DkBhNAc3.js +0 -98
  641. package/dist/gateway-cli-BEEZhCHv.js +0 -23747
  642. package/dist/gateway-cli-Nob0g_4y.js +0 -23742
  643. package/dist/gateway-rpc-CksB-N83.js +0 -28
  644. package/dist/gateway-rpc-Dq44SkOv.js +0 -28
  645. package/dist/gmail-setup-utils-Cnx8A5pW.js +0 -422
  646. package/dist/gmail-setup-utils-nkabbKOE.js +0 -423
  647. package/dist/health-RT-F3hzT.js +0 -1423
  648. package/dist/health-SOuaKNRa.js +0 -1420
  649. package/dist/health-format-BG95OE6N.js +0 -28
  650. package/dist/heartbeat-visibility-BxkZjE5m.js +0 -125
  651. package/dist/heartbeat-visibility-CGG-G7px.js +0 -125
  652. package/dist/help-format-DAxf0l_h.js +0 -17
  653. package/dist/helpers-kkeXif0Q.js +0 -10
  654. package/dist/hook-runner-global-DJ14gXFP.js +0 -527
  655. package/dist/hooks-cli-DyEKryW8.js +0 -1217
  656. package/dist/hooks-cli-RuEn0-oy.js +0 -1222
  657. package/dist/image-ops-Bi6JPSkD.js +0 -354
  658. package/dist/image-ops-DWytvdh_.js +0 -354
  659. package/dist/import-D8BBZQgl.js +0 -170
  660. package/dist/import-DQ6NI4Fz.js +0 -168
  661. package/dist/inbound-context-CPkkQW0i.js +0 -68
  662. package/dist/inbound-context-DS_kpIYI.js +0 -68
  663. package/dist/inbound-path-policy-Bg4gZBx-.js +0 -250
  664. package/dist/inbound-path-policy-sdr5Ji0k.js +0 -250
  665. package/dist/inspect-Dt8hogS3.js +0 -559
  666. package/dist/inspect-vYIL1oA0.js +0 -559
  667. package/dist/installs-aM5dWAyn.js +0 -325
  668. package/dist/installs-pWdqG8HL.js +0 -325
  669. package/dist/ipv4--2WXMVtE.js +0 -46
  670. package/dist/ipv4-CDQpx1A7.js +0 -46
  671. package/dist/ir-BpaAMTfW.js +0 -940
  672. package/dist/json-files-DzpTak5i.js +0 -46
  673. package/dist/links-C3soDNDH.js +0 -15
  674. package/dist/loader-Ccwsh8Sh.js +0 -22624
  675. package/dist/loader-y9MhJewT.js +0 -22621
  676. package/dist/local-roots-BrH0Q63K.js +0 -313
  677. package/dist/local-roots-nImrw2WR.js +0 -314
  678. package/dist/logger-Bw3cFE5t.js +0 -49
  679. package/dist/logging-C-nxX2fn.js +0 -20
  680. package/dist/login-C_Kt57nO.js +0 -62
  681. package/dist/login-DOmWDMeP.js +0 -61
  682. package/dist/login-qr-CXU0wC5K.js +0 -322
  683. package/dist/login-qr-D0u6fdeO.js +0 -327
  684. package/dist/logs-cli-CschwP4d.js +0 -238
  685. package/dist/logs-cli-D7ayUvz_.js +0 -233
  686. package/dist/markdown-tables-CrmghPAr.js +0 -29
  687. package/dist/markdown-tables-jrnSPvZ6.js +0 -29
  688. package/dist/media-CojxZ45J.js +0 -10492
  689. package/dist/media-DN7yRfrH.js +0 -940
  690. package/dist/message-action-names-CtEZcmlU.js +0 -2521
  691. package/dist/message-action-names-WglOO_DT.js +0 -2521
  692. package/dist/message-channel-DzJqHVZD.js +0 -91
  693. package/dist/net-Cg8AQeke.js +0 -225
  694. package/dist/net-D6D0wgcF.js +0 -225
  695. package/dist/node-cli-Q2-n3Fgv.js +0 -24
  696. package/dist/nodes-cli-C2SoKfCv.js +0 -1343
  697. package/dist/nodes-cli-CQmlfx0K.js +0 -1348
  698. package/dist/nodes-screen-BR9sYoPa.js +0 -250
  699. package/dist/nodes-screen-Cw7Hv7M2.js +0 -250
  700. package/dist/note-Dlv4NmlQ.js +0 -92
  701. package/dist/note-kvWV4xtw.js +0 -92
  702. package/dist/npm-registry-spec-0qiKawvv.js +0 -786
  703. package/dist/npm-registry-spec-COvUzy5J.js +0 -786
  704. package/dist/npm-resolution-6v_Zm-9G.js +0 -86
  705. package/dist/npm-resolution-BFz7LeoN.js +0 -86
  706. package/dist/onboard-CgyU-mDL.js +0 -407
  707. package/dist/onboard-RI4vNTZd.js +0 -405
  708. package/dist/onboard-channels-DN5JoKPd.js +0 -2548
  709. package/dist/onboard-channels-DyAd1OZr.js +0 -2547
  710. package/dist/onboard-config-BCTthQ7J.js +0 -24
  711. package/dist/onboard-config-y-2cgT0V.js +0 -24
  712. package/dist/onboard-helpers-BCzZUD0z.js +0 -363
  713. package/dist/onboard-helpers-sDc2Ky6H.js +0 -362
  714. package/dist/onboard-remote-CJrMtttl.js +0 -127
  715. package/dist/onboard-remote-hyQIBguz.js +0 -127
  716. package/dist/onboarding-DCu1iBTV.js +0 -541
  717. package/dist/onboarding-zKMitzpb.js +0 -543
  718. package/dist/onboarding.finalize-ClHhYE2E.js +0 -401
  719. package/dist/onboarding.finalize-D5JkVJgg.js +0 -398
  720. package/dist/onboarding.gateway-config-DFh71Ndn.js +0 -198
  721. package/dist/onboarding.gateway-config-VBk6AP9U.js +0 -191
  722. package/dist/outbound-BYlZshIw.js +0 -221
  723. package/dist/outbound-CFfJC1j5.js +0 -220
  724. package/dist/outbound-attachment-BCNs1u1F.js +0 -18
  725. package/dist/outbound-attachment-B_0D60Yr.js +0 -18
  726. package/dist/outbound-attachment-o0seS0CP.js +0 -18
  727. package/dist/pairing-cli-BeydfoF9.js +0 -122
  728. package/dist/pairing-cli-DWzX866x.js +0 -127
  729. package/dist/pairing-labels-B-N8S5Fc.js +0 -9
  730. package/dist/pairing-labels-B_53dY5L.js +0 -9
  731. package/dist/pairing-store-BxdqFZGK.js +0 -460
  732. package/dist/pairing-store-CTkD51uW.js +0 -459
  733. package/dist/path-env-DR5vn3QL.js +0 -89
  734. package/dist/path-env-qRJbjJzj.js +0 -89
  735. package/dist/path-safety-DkT9RmTG.js +0 -14
  736. package/dist/path-safety-juI2XbO1.js +0 -14
  737. package/dist/plugin-auto-enable-D23gv7Aw.js +0 -302
  738. package/dist/plugin-auto-enable-DuPS9XiJ.js +0 -301
  739. package/dist/plugin-registry-CNu_1KZz.js +0 -33
  740. package/dist/plugin-registry-DeHwd2jk.js +0 -33
  741. package/dist/plugin-sdk/agents/agent-helpers/thinking.d.ts +0 -5
  742. package/dist/plugin-sdk/agents/auth-profiles/constants.d.ts +0 -16
  743. package/dist/plugin-sdk/agents/auth-profiles/display.d.ts +0 -7
  744. package/dist/plugin-sdk/agents/auth-profiles/doctor.d.ts +0 -8
  745. package/dist/plugin-sdk/agents/auth-profiles/oauth.d.ts +0 -14
  746. package/dist/plugin-sdk/agents/auth-profiles/session-override.d.ts +0 -18
  747. package/dist/plugin-sdk/agents/auth-profiles.d.ts +0 -8
  748. package/dist/plugin-sdk/agents/defaults.d.ts +0 -3
  749. package/dist/plugin-sdk/agents/provider-auth.d.ts +0 -40
  750. package/dist/plugin-sdk/auto-reply/model-runtime.d.ts +0 -17
  751. package/dist/plugin-sdk/config/model-input.d.ts +0 -9
  752. package/dist/plugin-sdk/config/zod-schema.agent-model.d.ts +0 -5
  753. package/dist/plugin-sdk/sessions/model-overrides.d.ts +0 -14
  754. package/dist/plugin-sdk/telegram/reasoning-lane-coordinator.d.ts +0 -18
  755. package/dist/plugins-BflZz0sp.js +0 -453
  756. package/dist/plugins-cli-DV82scUw.js +0 -798
  757. package/dist/plugins-cli-Qj1UyIZO.js +0 -793
  758. package/dist/plugins-woGRXMzU.js +0 -455
  759. package/dist/ports-DrruB2fK.js +0 -370
  760. package/dist/ports-GT1yV-Tg.js +0 -96
  761. package/dist/ports-NPqtlfp0.js +0 -316
  762. package/dist/ports-QMI4-F9m.js +0 -96
  763. package/dist/program-CQmIaRUI.js +0 -244
  764. package/dist/program-context-DEU6ACnL.js +0 -474
  765. package/dist/progress-CBkSaM6z.js +0 -124
  766. package/dist/prompt-Bllj1dhc.js +0 -21
  767. package/dist/prompt-select-styled-BhTN6zE2.js +0 -1650
  768. package/dist/prompt-select-styled-WopXnjIy.js +0 -1647
  769. package/dist/prompt-style-DVEm3BZW.js +0 -9
  770. package/dist/provider-dispatcher-B4QMe-I6.js +0 -659
  771. package/dist/provider-dispatcher-Bfauw6zz.js +0 -660
  772. package/dist/push-apns-C0LyG-WB.js +0 -713
  773. package/dist/push-apns-DuG95AKC.js +0 -711
  774. package/dist/pw-ai-D9n6-Wa6.js +0 -1906
  775. package/dist/pw-ai-T280E6Mn.js +0 -1910
  776. package/dist/qr-cli-DVECWTHN.js +0 -352
  777. package/dist/qr-cli-hSLixZCe.js +0 -347
  778. package/dist/redact-eZq1uwNK.js +0 -191
  779. package/dist/redact-snapshot-BZYLIqe-.js +0 -2028
  780. package/dist/redact-snapshot-C6hVx_9I.js +0 -2028
  781. package/dist/register.agent-Dmj-sgEl.js +0 -1043
  782. package/dist/register.agent-IspcBFeD.js +0 -286
  783. package/dist/register.configure-BqJEqyGL.js +0 -130
  784. package/dist/register.configure-PPkU_4Ea.js +0 -124
  785. package/dist/register.import-Bs-UkOs-.js +0 -27
  786. package/dist/register.import-DLng8g-e.js +0 -30
  787. package/dist/register.maintenance-BbpkJil3.js +0 -497
  788. package/dist/register.maintenance-C5nkOQxa.js +0 -494
  789. package/dist/register.message-C83Hi1b3.js +0 -681
  790. package/dist/register.message-D16isu4u.js +0 -686
  791. package/dist/register.onboard-B8EzX3wY.js +0 -257
  792. package/dist/register.onboard-CyRbr_0V.js +0 -262
  793. package/dist/register.setup-DWyoowAz.js +0 -109
  794. package/dist/register.setup-Dz6GwMnu.js +0 -114
  795. package/dist/register.status-health-sessions-CbQOfycz.js +0 -423
  796. package/dist/register.status-health-sessions-DXIWG47y.js +0 -669
  797. package/dist/register.subclis-DeGP5UPU.js +0 -267
  798. package/dist/replies-BKrzM0QI.js +0 -136
  799. package/dist/replies-Cl2gYBVt.js +0 -136
  800. package/dist/reply-CCu_DY64.js +0 -13900
  801. package/dist/reply-DSKC8kyS.js +0 -13897
  802. package/dist/reply-directives-BHJKp1Du.js +0 -182
  803. package/dist/reply-directives-CD2WycBM.js +0 -182
  804. package/dist/reply-payloads-D_BM1Anb.js +0 -527
  805. package/dist/reply-prefix-DBLCYiup.js +0 -38
  806. package/dist/reply-prefix-Q4DOJSn_.js +0 -38
  807. package/dist/resolve-route-CBVbY0xS.js +0 -249
  808. package/dist/resolve-route-DGEgTEif.js +0 -249
  809. package/dist/response-prefix-template-rVZQOViK.js +0 -136
  810. package/dist/response-prefix-template-up4REfuR.js +0 -136
  811. package/dist/retry-BhuXOEVR.js +0 -77
  812. package/dist/retry-DUjAzOBy.js +0 -77
  813. package/dist/run-main-Um5xhxla.js +0 -320
  814. package/dist/runner-yVJ4HB2K.js +0 -2294
  815. package/dist/runner-z92MWZ3m.js +0 -2294
  816. package/dist/runtime-guard-DZ_xuCc4.js +0 -60
  817. package/dist/secure-random-Pl9rPl0l.js +0 -44
  818. package/dist/security-cli-CdwbWZUj.js +0 -484
  819. package/dist/security-cli-DP5QJpa5.js +0 -478
  820. package/dist/send-B1_Ymjb9.js +0 -1778
  821. package/dist/send-B84axiIa.js +0 -29
  822. package/dist/send-BN_zYVlx.js +0 -547
  823. package/dist/send-BqVOxAmK.js +0 -1174
  824. package/dist/send-Bx9bUGav.js +0 -492
  825. package/dist/send-C3pdJ6p-.js +0 -2245
  826. package/dist/send-CBGSXjfD.js +0 -2245
  827. package/dist/send-CGXyTF22.js +0 -426
  828. package/dist/send-CKavrhXj.js +0 -11
  829. package/dist/send-D08Je6DL.js +0 -374
  830. package/dist/send-D1aYEG-k.js +0 -332
  831. package/dist/send-DHldI3gf.js +0 -492
  832. package/dist/send-D_DUQJ6H.js +0 -349
  833. package/dist/send-Ds63eF4a.js +0 -349
  834. package/dist/send-YRVDWfSs.js +0 -547
  835. package/dist/send-xnwty9cY.js +0 -1775
  836. package/dist/server-BQFoyCRR.js +0 -200
  837. package/dist/server-DhXw25Jq.js +0 -205
  838. package/dist/server-lifecycle-BjCCyD3w.js +0 -2437
  839. package/dist/server-lifecycle-Coyr6Lda.js +0 -2437
  840. package/dist/server-node-events-De4WZQQD.js +0 -393
  841. package/dist/server-node-events-dXXayuqY.js +0 -398
  842. package/dist/service-Bjqii5nW.js +0 -670
  843. package/dist/service-fp29z5Ww.js +0 -670
  844. package/dist/session-DBL5nHDy.js +0 -170
  845. package/dist/session-cost-usage-DX09eTPU.js +0 -627
  846. package/dist/session-cost-usage-yYi525j3.js +0 -627
  847. package/dist/session-dirs-Cj5xi7zX.js +0 -947
  848. package/dist/session-dirs-DdF6TDsE.js +0 -947
  849. package/dist/session-utils-CEtEq6bi.js +0 -625
  850. package/dist/session-utils-WmlWAs1r.js +0 -625
  851. package/dist/session-xKIW6gL2.js +0 -170
  852. package/dist/sessions--PykPynp.js +0 -2593
  853. package/dist/sessions-Bw4LRnSr.js +0 -252
  854. package/dist/ssrf-Ck9HDZpv.js +0 -183
  855. package/dist/ssrf-m7kFIobZ.js +0 -183
  856. package/dist/status-CtzYFLLF.js +0 -2072
  857. package/dist/status-DiN1cq2p.js +0 -2068
  858. package/dist/status.update-C55QM2xs.js +0 -79
  859. package/dist/status.update-CBmPXwYN.js +0 -79
  860. package/dist/store-C3tOpizT.js +0 -64
  861. package/dist/store-CPJXuhvQ.js +0 -53
  862. package/dist/store-SusmIfz7.js +0 -2595
  863. package/dist/store-v3P-OWhi.js +0 -64
  864. package/dist/subagent-registry-Db4Ho_2Y.js +0 -4858
  865. package/dist/subagent-registry-Du_j0Fnt.js +0 -4860
  866. package/dist/subsystem-BUXAJwPD.js +0 -1079
  867. package/dist/subsystem-COd61u0P.js +0 -1139
  868. package/dist/system-cli-DYCpLO3T.js +0 -75
  869. package/dist/system-cli-eAk5wVbP.js +0 -70
  870. package/dist/systemd-DSnlM3jX.js +0 -547
  871. package/dist/systemd-TfK8GuTx.js +0 -547
  872. package/dist/systemd-linger-Axnc1xCb.js +0 -75
  873. package/dist/systemd-linger-_0_-RY4v.js +0 -75
  874. package/dist/table-DPTzZyhu.js +0 -279
  875. package/dist/tables-DI5LGEr1.js +0 -55
  876. package/dist/tables-PxcSPSO0.js +0 -55
  877. package/dist/tables-TWiml6b1.js +0 -55
  878. package/dist/tailnet-CEudzG0i.js +0 -40
  879. package/dist/tailnet-PnMrjwGT.js +0 -40
  880. package/dist/tailscale-DTATQxAG.js +0 -230
  881. package/dist/tailscale-Dbyahx0J.js +0 -230
  882. package/dist/targets-C1NeMn2J.js +0 -220
  883. package/dist/targets-CcTME3bp.js +0 -46
  884. package/dist/targets-CmC5m7Ey.js +0 -53
  885. package/dist/targets-D-u6Kyio.js +0 -650
  886. package/dist/targets-D7OKVXMI.js +0 -650
  887. package/dist/targets-DB4vBpIQ.js +0 -2172
  888. package/dist/targets-DfqPGOmM.js +0 -2173
  889. package/dist/targets-DyybKefq.js +0 -53
  890. package/dist/targets-JCISV-hS.js +0 -120
  891. package/dist/tokens-DzFOtLlW.js +0 -21
  892. package/dist/tool-display-Br6mwaJc.js +0 -785
  893. package/dist/tool-display-sgNwLOBj.js +0 -785
  894. package/dist/tool-images-BNfIJ_Kj.js +0 -263
  895. package/dist/tool-images-kloBqxqK.js +0 -263
  896. package/dist/trash-DPi0aCCQ.js +0 -125
  897. package/dist/trash-D_Jd_yQZ.js +0 -125
  898. package/dist/tui-CHc0EfJO.js +0 -3392
  899. package/dist/tui-CyHwc2uX.js +0 -3392
  900. package/dist/tui-cli-BvwbrIYO.js +0 -63
  901. package/dist/tui-cli-C9I18SfW.js +0 -58
  902. package/dist/update-DxyjwCL2.js +0 -349
  903. package/dist/update-IX7vdqA8.js +0 -349
  904. package/dist/update-cli-CBeXUSzq.js +0 -1373
  905. package/dist/update-cli-DkAWmUrp.js +0 -1370
  906. package/dist/usage-CYlQW4M2.js +0 -5279
  907. package/dist/utils-LBKvDoPx.js +0 -631
  908. package/dist/web-BUYUdnRH.js +0 -3065
  909. package/dist/web-Dquzwqf4.js +0 -70
  910. package/dist/web-tS8diboh.js +0 -76
  911. package/dist/webhooks-cli-B7Vw3CMz.js +0 -333
  912. package/dist/webhooks-cli-BpZHQlVd.js +0 -328
  913. package/dist/whatsapp-actions-D5HXezjp.js +0 -128
  914. package/dist/whatsapp-actions-DaA291Ya.js +0 -122
  915. package/dist/widearea-dns-DSoaA-eH.js +0 -127
  916. package/dist/workspace-B4ZvVYT9.js +0 -447
  917. package/dist/workspace-B8PA8oxJ.js +0 -449
  918. /package/dist/{account-lookup-0KDSp5Mj.js → account-lookup-BOCzCnir.js} +0 -0
  919. /package/dist/{account-lookup-zvANGr2x.js → account-lookup-DGscKBsr.js} +0 -0
  920. /package/dist/{ansi-D04X81yq.js → ansi-aRwLYlzD.js} +0 -0
  921. /package/dist/{api-BeQMq2iS.js → api-BDff51CS.js} +0 -0
  922. /package/dist/{api-CxX8-gGz.js → api-qWSMsT8m.js} +0 -0
  923. /package/dist/{argv-Co-b9Zsc.js → argv-neJY_Hxm.js} +0 -0
  924. /package/dist/{brew-C4zKZsHX.js → brew-ByYl36Mt.js} +0 -0
  925. /package/dist/{brew-DbSbN8sD.js → brew-CMSQ5Fek.js} +0 -0
  926. /package/dist/{chat-type-CYPyHAj-.js → chat-type-BKe459rw.js} +0 -0
  927. /package/dist/{chat-type-DKb2TlGZ.js → chat-type-DyovJwCt.js} +0 -0
  928. /package/dist/{cleanup-utils-CwQvD73q.js → cleanup-utils-S_P5Jebv.js} +0 -0
  929. /package/dist/{cli-name-BicfmwQX.js → cli-name-CRLBidNP.js} +0 -0
  930. /package/dist/{cli-name-C6rJGl18.js → cli-name-Yv30OygA.js} +0 -0
  931. /package/dist/{cli-utils-BhXbz2UF.js → cli-utils-C5nQDfa6.js} +0 -0
  932. /package/dist/{cli-utils-DZe_rVkZ.js → cli-utils-KcEwAsuZ.js} +0 -0
  933. /package/dist/{client-C61M8zI3.js → client-C7B0uFB0.js} +0 -0
  934. /package/dist/{client-DdpmATKq.js → client-Cd2HNUX0.js} +0 -0
  935. /package/dist/{command-options-C4paWSGf.js → command-options-1bi44p_B.js} +0 -0
  936. /package/dist/{command-options-CA30lfLK.js → command-options-7y5Zrv4M.js} +0 -0
  937. /package/dist/{config-eval-CjGZtLwx.js → config-eval-CJtk3Msr.js} +0 -0
  938. /package/dist/{config-eval-H_wlEYIG.js → config-eval-DQIwdWg7.js} +0 -0
  939. /package/dist/{constants-ChptG3d7.js → constants--3PuQVaS.js} +0 -0
  940. /package/dist/{constants-DY6b-_Wl.js → constants-DNWjlxZ5.js} +0 -0
  941. /package/dist/{credentials-BHWUBHMd.js → credentials-BhnauW0K.js} +0 -0
  942. /package/dist/{credentials-DFsi1_e8.js → credentials-eZcqWNG_.js} +0 -0
  943. /package/dist/{daemon-runtime-CMnbwryP.js → daemon-runtime-99xh1fGv.js} +0 -0
  944. /package/dist/{daemon-runtime-CvqE4ysg.js → daemon-runtime-BOcdJaFy.js} +0 -0
  945. /package/dist/{dangerous-name-matching-BzmiLXmA.js → dangerous-name-matching-YeatnYIA.js} +0 -0
  946. /package/dist/{dangerous-name-matching-DaVRgwer.js → dangerous-name-matching-oVb1EqYT.js} +0 -0
  947. /package/dist/{dangerous-tools-BOLoCRv4.js → dangerous-tools-BMt8-6jE.js} +0 -0
  948. /package/dist/{dangerous-tools-Baq7Q-i6.js → dangerous-tools-CripTfYv.js} +0 -0
  949. /package/dist/{fetch-timeout-DTIN7CGM.js → fetch-timeout-Db3da8yR.js} +0 -0
  950. /package/dist/{fetch-timeout-DoySHqfO.js → fetch-timeout-l_6RdoMw.js} +0 -0
  951. /package/dist/{file-identity-BxlKD8Ys.js → file-identity-Bs9zZOi2.js} +0 -0
  952. /package/dist/{format-duration-CqUERz51.js → format-duration-Bo-Mxi3E.js} +0 -0
  953. /package/dist/{format-duration-Ct-yiwkS.js → format-duration-CfrJ5T8k.js} +0 -0
  954. /package/dist/{format-relative-79_Y1n2Y.js → format-relative-8cNYQsqb.js} +0 -0
  955. /package/dist/{format-relative-CxLpEQOX.js → format-relative-CZOlQ2pA.js} +0 -0
  956. /package/dist/{health-format-B_QRD8Si.js → health-format-WMRp1BbP.js} +0 -0
  957. /package/dist/{heartbeat-wake-LGEgcXjs.js → heartbeat-wake-BtRrOB-t.js} +0 -0
  958. /package/dist/{heartbeat-wake-Y97geucO.js → heartbeat-wake-eRINROYK.js} +0 -0
  959. /package/dist/{help-format-NNm_Ov4H.js → help-format-BEb0SPHF.js} +0 -0
  960. /package/dist/{helpers-BAsMXprO.js → helpers-BJtPtu_2.js} +0 -0
  961. /package/dist/{helpers-DLgbkcEn.js → helpers-Cj6f8SPZ.js} +0 -0
  962. /package/dist/{helpers-R7bU5IBz.js → helpers-ryxLx-aM.js} +0 -0
  963. /package/dist/{host-env-security-szwfmhC4.js → host-env-security-CbiODGvQ.js} +0 -0
  964. /package/dist/{input-provenance-Bn6thJNm.js → input-provenance-CPhdY-0F.js} +0 -0
  965. /package/dist/{input-provenance-xUsSMOsz.js → input-provenance-DUNEQoFM.js} +0 -0
  966. /package/dist/{ip-C9q3Oq20.js → ip-BAhS4rY2.js} +0 -0
  967. /package/dist/{ip-D0zgNmBV.js → ip-BcdPcLiP.js} +0 -0
  968. /package/dist/{is-main-DN8-sNR5.js → is-main-KcWqINzy.js} +0 -0
  969. /package/dist/{json-file-ChO_R9yh.js → json-file-BVvmrQG3.js} +0 -0
  970. /package/dist/{json-file-B7l5-Xhr.js → json-file-Dbg7nZg1.js} +0 -0
  971. /package/dist/{json-files-CmpYSF4G.js → json-files-DSKEdz7x.js} +0 -0
  972. /package/dist/{lanes-ByWMUgrz.js → lanes-Brd-nf-Z.js} +0 -0
  973. /package/dist/{lanes-cHJ5arWg.js → lanes-COs3zODW.js} +0 -0
  974. /package/dist/{links-Bz4V7R_p.js → links-gse8sWn-.js} +0 -0
  975. /package/dist/{location-DBWCGNLq.js → location-D1FM_C63.js} +0 -0
  976. /package/dist/{location-GbZ0bBRU.js → location-LuzkqHGi.js} +0 -0
  977. /package/dist/{logger-DyL5G2DO.js → logger-BMP_j_Lx.js} +0 -0
  978. /package/dist/{logger-BWMPnILd.js → logger-DWbwXLjl.js} +0 -0
  979. /package/dist/{logger-GvipVDfh.js → logger-DXCDb7qu.js} +0 -0
  980. /package/dist/{logging-D8-Kozjc.js → logging-CAgCb3n3.js} +0 -0
  981. /package/dist/{message-channel-uWMAiywE.js → message-channel-D72Bc6Tb.js} +0 -0
  982. /package/dist/{mime-BS3jhcZE.js → mime-Cqg1jjia.js} +0 -0
  983. /package/dist/{mime-Cxh_64P6.js → mime-D4bQLMJL.js} +0 -0
  984. /package/dist/{mutable-allowlist-detectors-DiZDtmlZ.js → mutable-allowlist-detectors-NtI6s4TE.js} +0 -0
  985. /package/dist/{mutable-allowlist-detectors-U5ThQr9V.js → mutable-allowlist-detectors-nAmo9v5u.js} +0 -0
  986. /package/dist/{node-cli-Uf6lAntf.js → node-cli-bNJbha3z.js} +0 -0
  987. /package/dist/{parse-log-line-enq8pduH.js → parse-log-line-BY9Vz72K.js} +0 -0
  988. /package/dist/{parse-log-line-mz9TG6ig.js → parse-log-line-BrrE4onI.js} +0 -0
  989. /package/dist/{parse-timeout-BMP8a0_a.js → parse-timeout-Dfyln-4M.js} +0 -0
  990. /package/dist/{path-guards-CIx4hURU.js → path-guards-D9LU0y9L.js} +0 -0
  991. /package/dist/{path-guards-CrQOUlsq.js → path-guards-crZaTVvq.js} +0 -0
  992. /package/dist/plugin-sdk/{agents → auth}/api-key-rotation.d.ts +0 -0
  993. /package/dist/plugin-sdk/{agents/auth-profiles → auth}/paths.d.ts +0 -0
  994. /package/dist/plugin-sdk/{agents/auth-profiles → auth}/profiles.d.ts +0 -0
  995. /package/dist/plugin-sdk/{agents/auth-profiles → auth}/store.d.ts +0 -0
  996. /package/dist/plugin-sdk/{agents/auth-profiles → auth}/types.d.ts +0 -0
  997. /package/dist/{plugins-allowlist-BbTQ5Z2k.js → plugins-allowlist-CD4oIJNk.js} +0 -0
  998. /package/dist/{plugins-allowlist-C20oaESO.js → plugins-allowlist-CUhk3GDh.js} +0 -0
  999. /package/dist/{polls-B0CCBDeR.js → polls-ChvH1OIW.js} +0 -0
  1000. /package/dist/{polls-CwwHzYBM.js → polls-Dn1C2d1-.js} +0 -0
  1001. /package/dist/{ports-lsof-Wteul3ju.js → ports-lsof-BDQWExpn.js} +0 -0
  1002. /package/dist/{process-scoped-map-CV9kDvfG.js → process-scoped-map-BwUkYFQV.js} +0 -0
  1003. /package/dist/{process-scoped-map-PEvnG75N.js → process-scoped-map-CBWcUvTa.js} +0 -0
  1004. /package/dist/{program-context-jqeI5alP.js → program-context-DtsEOsdM.js} +0 -0
  1005. /package/dist/{progress-C1kUfYL-.js → progress-BjGCAXH7.js} +0 -0
  1006. /package/dist/{prompt-Yn2yClg1.js → prompt-FIISMuNm.js} +0 -0
  1007. /package/dist/{prompt-style-DjEYC_s-.js → prompt-style-DL64_X-p.js} +0 -0
  1008. /package/dist/{provider-utils-3JTMJroG.js → provider-utils-DiLhkKQp.js} +0 -0
  1009. /package/dist/{proxy-DL3MD6-P.js → proxy-DUTF0OYE.js} +0 -0
  1010. /package/dist/{proxy-DpNv2cSV.js → proxy-Dv0sbx6A.js} +0 -0
  1011. /package/dist/{pw-ai-state-CGfLv6nV.js → pw-ai-state-DKhOTqDv.js} +0 -0
  1012. /package/dist/{pw-ai-state-Dynx20hr.js → pw-ai-state-kkp06zyZ.js} +0 -0
  1013. /package/dist/{redact-Dx1Fue21.js → redact-BTeK8lMZ.js} +0 -0
  1014. /package/dist/{redact-identifier-BTIWtaa-.js → redact-identifier-F6t5pklx.js} +0 -0
  1015. /package/dist/{redact-identifier-CAagcfWA.js → redact-identifier-VdOrq-IK.js} +0 -0
  1016. /package/dist/{remoteclaw-root-C2HV2VeC.js → remoteclaw-root-DF8m3X4C.js} +0 -0
  1017. /package/dist/{remoteclaw-root-DybYl8PL.js → remoteclaw-root-rJHOCwzo.js} +0 -0
  1018. /package/dist/{render-CCLsW6Lz.js → render-e7fENCYH.js} +0 -0
  1019. /package/dist/{render-uf6PvGMV.js → render-qcqmrHse.js} +0 -0
  1020. /package/dist/{retry-DnqPAqWp.js → retry-CwZiwLDN.js} +0 -0
  1021. /package/dist/{runtime-DJNp29jv.js → runtime-Ds3E9SqF.js} +0 -0
  1022. /package/dist/{runtime-guard-U-ewY_QH.js → runtime-guard-CdJVmJc0.js} +0 -0
  1023. /package/dist/{secret-equal-BbHdTtqY.js → secret-equal-CDUVxXmp.js} +0 -0
  1024. /package/dist/{secret-equal-CXJEZiWb.js → secret-equal-d3sEnK98.js} +0 -0
  1025. /package/dist/{secure-random-CS2mSdTn.js → secure-random-CJtykx_p.js} +0 -0
  1026. /package/dist/{secure-random-_dzDDlFo.js → secure-random-y6N6Gted.js} +0 -0
  1027. /package/dist/{session-key-5YLnn_qf.js → session-key-BF-9YzxC.js} +0 -0
  1028. /package/dist/{stagger-BXv_apuy.js → stagger-B-_Wnofy.js} +0 -0
  1029. /package/dist/{stagger-MI9gd2rQ.js → stagger-CjkdqPuN.js} +0 -0
  1030. /package/dist/{status-BmtCS3T1.js → status-BFmH9Uge.js} +0 -0
  1031. /package/dist/{status-BrwHRn2B.js → status-BIupzBh9.js} +0 -0
  1032. /package/dist/{strip-inbound-meta-DjKcSFaW.js → strip-inbound-meta-BNXRYvmY.js} +0 -0
  1033. /package/dist/{strip-inbound-meta-jy3bkUab.js → strip-inbound-meta-BtNFmc6V.js} +0 -0
  1034. /package/dist/{table-C1rdyYl9.js → table-Au5EeKD6.js} +0 -0
  1035. /package/dist/{target-errors-BDpPcwh5.js → target-errors-B6YON-5k.js} +0 -0
  1036. /package/dist/{target-errors-DdIAPcMM.js → target-errors-sPHoHj73.js} +0 -0
  1037. /package/dist/{targets-D-qLBpTA.js → targets-BtGRUQMa.js} +0 -0
  1038. /package/dist/{targets-BMenhVHg.js → targets-D3r6Zgic.js} +0 -0
  1039. /package/dist/{targets-C-2xwh9f.js → targets-DDdPVd12.js} +0 -0
  1040. /package/dist/{targets-UncQvCVs.js → targets-Ds5eT_RZ.js} +0 -0
  1041. /package/dist/{targets-D7PT_rdO.js → targets-DtvPW-B8.js} +0 -0
  1042. /package/dist/{text-format-BQ3z_OXA.js → text-format-CFm4X8Ze.js} +0 -0
  1043. /package/dist/{text-format-oWqzVmah.js → text-format-KHU3KzvQ.js} +0 -0
  1044. /package/dist/{tokens-B-jmvNR9.js → tokens-BGw4xHhW.js} +0 -0
  1045. /package/dist/{usage-BdhBT0Vz.js → usage-BEjWlD9A.js} +0 -0
  1046. /package/dist/{usage-format-C3mNLfhI.js → usage-format-Cx3JveFn.js} +0 -0
  1047. /package/dist/{usage-format-DAaPzr_z.js → usage-format-D-ZaYT_e.js} +0 -0
  1048. /package/dist/{usage-BtQcAnf6.js → usage-o8O_TxA-.js} +0 -0
  1049. /package/dist/{widearea-dns-CsmBVbez.js → widearea-dns-DUDYT3z2.js} +0 -0
  1050. /package/dist/{workspace-BzPeZDew.js → workspace-9__vtmnA.js} +0 -0
  1051. /package/dist/{wsl-B_sPlzWw.js → wsl-BLrG__iS.js} +0 -0
  1052. /package/dist/{wsl-BCnYV9O0.js → wsl-C2dudsWt.js} +0 -0
@@ -0,0 +1,4223 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js";
2
+ import { A as normalizeChatChannelId, Bt as resolveDefaultConfigCandidates, Ft as STATE_DIR, Gt as resolveNewStateDir, Ht as resolveGatewayPort, It as isNixMode, Kt as resolveOAuthDir, Lt as resolveCanonicalConfigPath, Nt as CONFIG_PATH, Pt as DEFAULT_GATEWAY_PORT, Rt as resolveConfigPath, S as CHANNEL_IDS, Ut as resolveIsNixMode, Vt as resolveGatewayLockDir, Wt as resolveLegacyStateDirs, Y as isRecord, dn as resolveRequiredHomeDir, et as resolveConfigDir, qt as resolveStateDir, rt as resolveUserPath, ut as isPlainObject$2, zt as resolveConfigPathCandidate } from "./entry.js";
3
+ import { a as shouldEnableShellEnvFallback, i as shouldDeferShellEnvFallback, n as loadShellEnvFallback, r as resolveShellEnvFallbackTimeoutMs } from "./shell-env-hZW9j-Uc.js";
4
+ import { r as VERSION, t as applyConfigEnvVars } from "./env-vars-C8WMB8Ix.js";
5
+ import { _ as isBlockedObjectKey, s as normalizeAgentId, t as DEFAULT_AGENT_ID } from "./session-key-BF-9YzxC.js";
6
+ import { o as parseModelRef } from "./provider-utils-DiLhkKQp.js";
7
+ import { d as resolveDiscordPreviewStreamMode, f as resolveSlackNativeStreaming, l as isSafeExecutableValue, m as resolveTelegramPreviewStreamMode, p as resolveSlackStreamingMode, t as RemoteClawSchema } from "./zod-schema-B9RGngMW.js";
8
+ import { c as resolveDefaultAgentId, s as resolveAgentWorkspaceDirOrNull } from "./agent-scope-DxqtYjuJ.js";
9
+ import { d as TOOLS_BY_SENDER_KEY_TYPES, f as parseToolsBySenderTypedKey } from "./dock-D5pZ3a44.js";
10
+ import { fileURLToPath } from "node:url";
11
+ import os from "node:os";
12
+ import path from "node:path";
13
+ import fs from "node:fs";
14
+ import JSON5 from "json5";
15
+ import { isDeepStrictEqual } from "node:util";
16
+ import crypto from "node:crypto";
17
+ import dotenv from "dotenv";
18
+ import AjvPkg from "ajv";
19
+
20
+ //#region src/agents/owner-display.ts
21
+ function trimToUndefined(value) {
22
+ const trimmed = value?.trim();
23
+ return trimmed ? trimmed : void 0;
24
+ }
25
+ /**
26
+ * Resolve owner display settings for prompt rendering.
27
+ * Keep auth secrets decoupled from owner hash secrets.
28
+ */
29
+ function resolveOwnerDisplaySetting(config) {
30
+ const ownerDisplay = config?.commands?.ownerDisplay;
31
+ if (ownerDisplay !== "hash") return {
32
+ ownerDisplay,
33
+ ownerDisplaySecret: void 0
34
+ };
35
+ return {
36
+ ownerDisplay: "hash",
37
+ ownerDisplaySecret: trimToUndefined(config?.commands?.ownerDisplaySecret)
38
+ };
39
+ }
40
+ /**
41
+ * Ensure hash mode has a dedicated secret.
42
+ * Returns updated config and generated secret when autofill was needed.
43
+ */
44
+ function ensureOwnerDisplaySecret(config, generateSecret = () => crypto.randomBytes(32).toString("hex")) {
45
+ const settings = resolveOwnerDisplaySetting(config);
46
+ if (settings.ownerDisplay !== "hash" || settings.ownerDisplaySecret) return { config };
47
+ const generatedSecret = generateSecret();
48
+ return {
49
+ config: {
50
+ ...config,
51
+ commands: {
52
+ ...config.commands,
53
+ ownerDisplay: "hash",
54
+ ownerDisplaySecret: generatedSecret
55
+ }
56
+ },
57
+ generatedSecret
58
+ };
59
+ }
60
+
61
+ //#endregion
62
+ //#region src/infra/dotenv.ts
63
+ function loadDotEnv(opts) {
64
+ const quiet = opts?.quiet ?? true;
65
+ dotenv.config({ quiet });
66
+ const globalEnvPath = path.join(resolveConfigDir(process.env), ".env");
67
+ if (!fs.existsSync(globalEnvPath)) return;
68
+ dotenv.config({
69
+ quiet,
70
+ path: globalEnvPath,
71
+ override: false
72
+ });
73
+ }
74
+
75
+ //#endregion
76
+ //#region src/config/agent-dirs.ts
77
+ var DuplicateAgentDirError = class extends Error {
78
+ constructor(duplicates) {
79
+ super(formatDuplicateAgentDirError(duplicates));
80
+ this.name = "DuplicateAgentDirError";
81
+ this.duplicates = duplicates;
82
+ }
83
+ };
84
+ function canonicalizeAgentDir(agentDir) {
85
+ const resolved = path.resolve(agentDir);
86
+ if (process.platform === "darwin" || process.platform === "win32") return resolved.toLowerCase();
87
+ return resolved;
88
+ }
89
+ function collectReferencedAgentIds(cfg) {
90
+ const ids = /* @__PURE__ */ new Set();
91
+ const agents = Array.isArray(cfg.agents?.list) ? cfg.agents?.list : [];
92
+ const defaultAgentId = agents.find((agent) => agent?.default)?.id ?? agents[0]?.id ?? DEFAULT_AGENT_ID;
93
+ ids.add(normalizeAgentId(defaultAgentId));
94
+ for (const entry of agents) if (entry?.id) ids.add(normalizeAgentId(entry.id));
95
+ const bindings = cfg.bindings;
96
+ if (Array.isArray(bindings)) for (const binding of bindings) {
97
+ const id = binding?.agentId;
98
+ if (typeof id === "string" && id.trim()) ids.add(normalizeAgentId(id));
99
+ }
100
+ return [...ids];
101
+ }
102
+ function resolveEffectiveAgentDir(cfg, agentId, deps) {
103
+ const id = normalizeAgentId(agentId);
104
+ const trimmed = (Array.isArray(cfg.agents?.list) ? cfg.agents?.list.find((agent) => normalizeAgentId(agent.id) === id)?.agentDir : void 0)?.trim();
105
+ if (trimmed) return resolveUserPath(trimmed);
106
+ const env = deps?.env ?? process.env;
107
+ const root = resolveStateDir(env, deps?.homedir ?? (() => resolveRequiredHomeDir(env, os.homedir)));
108
+ return path.join(root, "agents", id, "agent");
109
+ }
110
+ function findDuplicateAgentDirs(cfg, deps) {
111
+ const byDir = /* @__PURE__ */ new Map();
112
+ for (const agentId of collectReferencedAgentIds(cfg)) {
113
+ const agentDir = resolveEffectiveAgentDir(cfg, agentId, deps);
114
+ const key = canonicalizeAgentDir(agentDir);
115
+ const entry = byDir.get(key);
116
+ if (entry) entry.agentIds.push(agentId);
117
+ else byDir.set(key, {
118
+ agentDir,
119
+ agentIds: [agentId]
120
+ });
121
+ }
122
+ return [...byDir.values()].filter((v) => v.agentIds.length > 1);
123
+ }
124
+ function formatDuplicateAgentDirError(dups) {
125
+ return [
126
+ "Duplicate agentDir detected (multi-agent config).",
127
+ "Each agent must have a unique agentDir; sharing it causes auth/session state collisions and token invalidation.",
128
+ "",
129
+ "Conflicts:",
130
+ ...dups.map((d) => `- ${d.agentDir}: ${d.agentIds.map((id) => `"${id}"`).join(", ")}`),
131
+ "",
132
+ "Fix: remove the shared agents.list[].agentDir override (or give each agent its own directory).",
133
+ "If you want to share credentials, copy auth-profiles.json instead of sharing the entire agentDir."
134
+ ].join("\n");
135
+ }
136
+
137
+ //#endregion
138
+ //#region src/config/backup-rotation.ts
139
+ const CONFIG_BACKUP_COUNT = 5;
140
+ async function rotateConfigBackups(configPath, ioFs) {
141
+ if (CONFIG_BACKUP_COUNT <= 1) return;
142
+ const backupBase = `${configPath}.bak`;
143
+ const maxIndex = CONFIG_BACKUP_COUNT - 1;
144
+ await ioFs.unlink(`${backupBase}.${maxIndex}`).catch(() => {});
145
+ for (let index = maxIndex - 1; index >= 1; index -= 1) await ioFs.rename(`${backupBase}.${index}`, `${backupBase}.${index + 1}`).catch(() => {});
146
+ await ioFs.rename(backupBase, `${backupBase}.1`).catch(() => {});
147
+ }
148
+
149
+ //#endregion
150
+ //#region src/config/agent-limits.ts
151
+ const DEFAULT_AGENT_MAX_CONCURRENT = 4;
152
+ const DEFAULT_SUBAGENT_MAX_CONCURRENT = 8;
153
+ const DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH = 1;
154
+ function resolveAgentMaxConcurrent(cfg) {
155
+ const raw = cfg?.agents?.defaults?.maxConcurrent;
156
+ if (typeof raw === "number" && Number.isFinite(raw)) return Math.max(1, Math.floor(raw));
157
+ return DEFAULT_AGENT_MAX_CONCURRENT;
158
+ }
159
+ function resolveSubagentMaxConcurrent(cfg) {
160
+ const raw = cfg?.agents?.defaults?.subagents?.maxConcurrent;
161
+ if (typeof raw === "number" && Number.isFinite(raw)) return Math.max(1, Math.floor(raw));
162
+ return DEFAULT_SUBAGENT_MAX_CONCURRENT;
163
+ }
164
+
165
+ //#endregion
166
+ //#region src/config/talk.ts
167
+ const DEFAULT_TALK_PROVIDER = "elevenlabs";
168
+ function isPlainObject$1(value) {
169
+ return typeof value === "object" && value !== null && !Array.isArray(value);
170
+ }
171
+ function normalizeString(value) {
172
+ if (typeof value !== "string") return;
173
+ const trimmed = value.trim();
174
+ return trimmed.length > 0 ? trimmed : void 0;
175
+ }
176
+ function normalizeVoiceAliases(value) {
177
+ if (!isPlainObject$1(value)) return;
178
+ const aliases = {};
179
+ for (const [alias, rawId] of Object.entries(value)) {
180
+ if (typeof rawId !== "string") continue;
181
+ aliases[alias] = rawId;
182
+ }
183
+ return Object.keys(aliases).length > 0 ? aliases : void 0;
184
+ }
185
+ function normalizeTalkProviderConfig(value) {
186
+ if (!isPlainObject$1(value)) return;
187
+ const provider = {};
188
+ for (const [key, raw] of Object.entries(value)) {
189
+ if (raw === void 0) continue;
190
+ if (key === "voiceAliases") {
191
+ const aliases = normalizeVoiceAliases(raw);
192
+ if (aliases) provider.voiceAliases = aliases;
193
+ continue;
194
+ }
195
+ if (key === "voiceId" || key === "modelId" || key === "outputFormat" || key === "apiKey") {
196
+ const normalized = normalizeString(raw);
197
+ if (normalized) provider[key] = normalized;
198
+ continue;
199
+ }
200
+ provider[key] = raw;
201
+ }
202
+ return Object.keys(provider).length > 0 ? provider : void 0;
203
+ }
204
+ function normalizeTalkProviders(value) {
205
+ if (!isPlainObject$1(value)) return;
206
+ const providers = {};
207
+ for (const [rawProviderId, providerConfig] of Object.entries(value)) {
208
+ const providerId = normalizeString(rawProviderId);
209
+ if (!providerId) continue;
210
+ const normalizedProvider = normalizeTalkProviderConfig(providerConfig);
211
+ if (!normalizedProvider) continue;
212
+ providers[providerId] = normalizedProvider;
213
+ }
214
+ return Object.keys(providers).length > 0 ? providers : void 0;
215
+ }
216
+ function normalizedLegacyTalkFields(source) {
217
+ const legacy = {};
218
+ const voiceId = normalizeString(source.voiceId);
219
+ if (voiceId) legacy.voiceId = voiceId;
220
+ const voiceAliases = normalizeVoiceAliases(source.voiceAliases);
221
+ if (voiceAliases) legacy.voiceAliases = voiceAliases;
222
+ const modelId = normalizeString(source.modelId);
223
+ if (modelId) legacy.modelId = modelId;
224
+ const outputFormat = normalizeString(source.outputFormat);
225
+ if (outputFormat) legacy.outputFormat = outputFormat;
226
+ const apiKey = normalizeString(source.apiKey);
227
+ if (apiKey) legacy.apiKey = apiKey;
228
+ return legacy;
229
+ }
230
+ function legacyProviderConfigFromTalk(source) {
231
+ return normalizeTalkProviderConfig({
232
+ voiceId: source.voiceId,
233
+ voiceAliases: source.voiceAliases,
234
+ modelId: source.modelId,
235
+ outputFormat: source.outputFormat,
236
+ apiKey: source.apiKey
237
+ });
238
+ }
239
+ function activeProviderFromTalk(talk) {
240
+ const provider = normalizeString(talk.provider);
241
+ if (provider) return provider;
242
+ const providerIds = talk.providers ? Object.keys(talk.providers) : [];
243
+ return providerIds.length === 1 ? providerIds[0] : void 0;
244
+ }
245
+ function legacyTalkFieldsFromProviderConfig(config) {
246
+ if (!config) return {};
247
+ const legacy = {};
248
+ if (typeof config.voiceId === "string") legacy.voiceId = config.voiceId;
249
+ if (config.voiceAliases && typeof config.voiceAliases === "object" && !Array.isArray(config.voiceAliases)) {
250
+ const aliases = normalizeVoiceAliases(config.voiceAliases);
251
+ if (aliases) legacy.voiceAliases = aliases;
252
+ }
253
+ if (typeof config.modelId === "string") legacy.modelId = config.modelId;
254
+ if (typeof config.outputFormat === "string") legacy.outputFormat = config.outputFormat;
255
+ if (typeof config.apiKey === "string") legacy.apiKey = config.apiKey;
256
+ return legacy;
257
+ }
258
+ function normalizeTalkSection(value) {
259
+ if (!isPlainObject$1(value)) return;
260
+ const source = value;
261
+ const hasNormalizedShape = typeof source.provider === "string" || isPlainObject$1(source.providers);
262
+ const normalized = {};
263
+ const legacy = normalizedLegacyTalkFields(source);
264
+ if (Object.keys(legacy).length > 0) Object.assign(normalized, legacy);
265
+ if (typeof source.interruptOnSpeech === "boolean") normalized.interruptOnSpeech = source.interruptOnSpeech;
266
+ if (hasNormalizedShape) {
267
+ const providers = normalizeTalkProviders(source.providers);
268
+ const provider = normalizeString(source.provider);
269
+ if (providers) normalized.providers = providers;
270
+ if (provider) normalized.provider = provider;
271
+ else if (providers) {
272
+ const ids = Object.keys(providers);
273
+ if (ids.length === 1) normalized.provider = ids[0];
274
+ }
275
+ return Object.keys(normalized).length > 0 ? normalized : void 0;
276
+ }
277
+ const legacyProviderConfig = legacyProviderConfigFromTalk(source);
278
+ if (legacyProviderConfig) {
279
+ normalized.provider = DEFAULT_TALK_PROVIDER;
280
+ normalized.providers = { [DEFAULT_TALK_PROVIDER]: legacyProviderConfig };
281
+ }
282
+ return Object.keys(normalized).length > 0 ? normalized : void 0;
283
+ }
284
+ function normalizeTalkConfig(config) {
285
+ if (!config.talk) return config;
286
+ const normalizedTalk = normalizeTalkSection(config.talk);
287
+ if (!normalizedTalk) return config;
288
+ return {
289
+ ...config,
290
+ talk: normalizedTalk
291
+ };
292
+ }
293
+ function resolveActiveTalkProviderConfig(talk) {
294
+ const normalizedTalk = normalizeTalkSection(talk);
295
+ if (!normalizedTalk) return {};
296
+ const provider = activeProviderFromTalk(normalizedTalk);
297
+ if (!provider) return {};
298
+ return {
299
+ provider,
300
+ config: normalizedTalk.providers?.[provider]
301
+ };
302
+ }
303
+ function buildTalkConfigResponse(value) {
304
+ if (!isPlainObject$1(value)) return;
305
+ const normalized = normalizeTalkSection(value);
306
+ if (!normalized) return;
307
+ const payload = {};
308
+ if (typeof normalized.interruptOnSpeech === "boolean") payload.interruptOnSpeech = normalized.interruptOnSpeech;
309
+ if (normalized.providers && Object.keys(normalized.providers).length > 0) payload.providers = normalized.providers;
310
+ if (typeof normalized.provider === "string") payload.provider = normalized.provider;
311
+ const activeProvider = activeProviderFromTalk(normalized);
312
+ const providerCompatibilityLegacy = legacyTalkFieldsFromProviderConfig(activeProvider ? normalized.providers?.[activeProvider] : void 0);
313
+ const compatibilityLegacy = Object.keys(providerCompatibilityLegacy).length > 0 ? providerCompatibilityLegacy : normalizedLegacyTalkFields(normalized);
314
+ Object.assign(payload, compatibilityLegacy);
315
+ return Object.keys(payload).length > 0 ? payload : void 0;
316
+ }
317
+ function readTalkApiKeyFromProfile(deps = {}) {
318
+ const fsImpl = deps.fs ?? fs;
319
+ const osImpl = deps.os ?? os;
320
+ const pathImpl = deps.path ?? path;
321
+ const home = osImpl.homedir();
322
+ const candidates = [
323
+ ".profile",
324
+ ".zprofile",
325
+ ".zshrc",
326
+ ".bashrc"
327
+ ].map((name) => pathImpl.join(home, name));
328
+ for (const candidate of candidates) {
329
+ if (!fsImpl.existsSync(candidate)) continue;
330
+ try {
331
+ const value = fsImpl.readFileSync(candidate, "utf-8").match(/(?:^|\n)\s*(?:export\s+)?ELEVENLABS_API_KEY\s*=\s*["']?([^\n"']+)["']?/)?.[1]?.trim();
332
+ if (value) return value;
333
+ } catch {}
334
+ }
335
+ return null;
336
+ }
337
+ function resolveTalkApiKey(env = process.env, deps = {}) {
338
+ const envValue = (env.ELEVENLABS_API_KEY ?? "").trim();
339
+ if (envValue) return envValue;
340
+ return readTalkApiKeyFromProfile(deps);
341
+ }
342
+
343
+ //#endregion
344
+ //#region src/config/defaults.ts
345
+ let defaultWarnState = { warned: false };
346
+ const DEFAULT_MODEL_ALIASES = {
347
+ opus: "anthropic/claude-opus-4-6",
348
+ sonnet: "anthropic/claude-sonnet-4-6",
349
+ gpt: "openai/gpt-5.2",
350
+ "gpt-mini": "openai/gpt-5-mini",
351
+ gemini: "google/gemini-3-pro-preview",
352
+ "gemini-flash": "google/gemini-3-flash-preview"
353
+ };
354
+ function resolveAnthropicDefaultAuthMode(cfg) {
355
+ const profiles = cfg.auth?.profiles ?? {};
356
+ const anthropicProfiles = Object.entries(profiles).filter(([, profile]) => profile?.provider === "anthropic");
357
+ const order = cfg.auth?.order?.anthropic ?? [];
358
+ for (const profileId of order) {
359
+ const entry = profiles[profileId];
360
+ if (!entry || entry.provider !== "anthropic") continue;
361
+ if (entry.mode === "api_key") return "api_key";
362
+ if (entry.mode === "oauth" || entry.mode === "token") return "oauth";
363
+ }
364
+ const hasApiKey = anthropicProfiles.some(([, profile]) => profile?.mode === "api_key");
365
+ const hasOauth = anthropicProfiles.some(([, profile]) => profile?.mode === "oauth" || profile?.mode === "token");
366
+ if (hasApiKey && !hasOauth) return "api_key";
367
+ if (hasOauth && !hasApiKey) return "oauth";
368
+ if (process.env.ANTHROPIC_OAUTH_TOKEN?.trim()) return "oauth";
369
+ if (process.env.ANTHROPIC_API_KEY?.trim()) return "api_key";
370
+ return null;
371
+ }
372
+ function resolvePrimaryModelRef(raw) {
373
+ if (!raw || typeof raw !== "string") return null;
374
+ const trimmed = raw.trim();
375
+ if (!trimmed) return null;
376
+ return DEFAULT_MODEL_ALIASES[trimmed.toLowerCase()] ?? trimmed;
377
+ }
378
+ function applyMessageDefaults(cfg) {
379
+ const messages = cfg.messages;
380
+ if (messages?.ackReactionScope !== void 0) return cfg;
381
+ const nextMessages = messages ? { ...messages } : {};
382
+ nextMessages.ackReactionScope = "group-mentions";
383
+ return {
384
+ ...cfg,
385
+ messages: nextMessages
386
+ };
387
+ }
388
+ function applySessionDefaults(cfg, options = {}) {
389
+ const session = cfg.session;
390
+ if (!session || session.mainKey === void 0) return cfg;
391
+ const trimmed = session.mainKey.trim();
392
+ const warn = options.warn ?? console.warn;
393
+ const warnState = options.warnState ?? defaultWarnState;
394
+ const next = {
395
+ ...cfg,
396
+ session: {
397
+ ...session,
398
+ mainKey: "main"
399
+ }
400
+ };
401
+ if (trimmed && trimmed !== "main" && !warnState.warned) {
402
+ warnState.warned = true;
403
+ warn("session.mainKey is ignored; main session is always \"main\".");
404
+ }
405
+ return next;
406
+ }
407
+ function applyTalkApiKey(config) {
408
+ const normalized = normalizeTalkConfig(config);
409
+ const resolved = resolveTalkApiKey();
410
+ if (!resolved) return normalized;
411
+ const talk = normalized.talk;
412
+ const active = resolveActiveTalkProviderConfig(talk);
413
+ if (active.provider && active.provider !== DEFAULT_TALK_PROVIDER) return normalized;
414
+ const existingProviderApiKey = typeof active.config?.apiKey === "string" ? active.config.apiKey.trim() : "";
415
+ const existingLegacyApiKey = typeof talk?.apiKey === "string" ? talk.apiKey.trim() : "";
416
+ if (existingProviderApiKey || existingLegacyApiKey) return normalized;
417
+ const providerId = active.provider ?? DEFAULT_TALK_PROVIDER;
418
+ const providers = { ...talk?.providers };
419
+ providers[providerId] = {
420
+ ...providers[providerId],
421
+ apiKey: resolved
422
+ };
423
+ const nextTalk = {
424
+ ...talk,
425
+ provider: talk?.provider ?? providerId,
426
+ providers,
427
+ apiKey: resolved
428
+ };
429
+ return {
430
+ ...normalized,
431
+ talk: nextTalk
432
+ };
433
+ }
434
+ function applyTalkConfigNormalization(config) {
435
+ return normalizeTalkConfig(config);
436
+ }
437
+ function applyModelDefaults(cfg) {
438
+ const existingAgent = cfg.agents?.defaults;
439
+ if (!existingAgent) return cfg;
440
+ const existingModels = existingAgent.models ?? {};
441
+ if (Object.keys(existingModels).length === 0) return cfg;
442
+ const nextModels = { ...existingModels };
443
+ let mutated = false;
444
+ for (const [alias, target] of Object.entries(DEFAULT_MODEL_ALIASES)) {
445
+ const entry = nextModels[target];
446
+ if (!entry) continue;
447
+ if (entry.alias !== void 0) continue;
448
+ nextModels[target] = {
449
+ ...entry,
450
+ alias
451
+ };
452
+ mutated = true;
453
+ }
454
+ if (!mutated) return cfg;
455
+ return {
456
+ ...cfg,
457
+ agents: {
458
+ ...cfg.agents,
459
+ defaults: {
460
+ ...existingAgent,
461
+ models: nextModels
462
+ }
463
+ }
464
+ };
465
+ }
466
+ function applyAgentDefaults(cfg) {
467
+ const agents = cfg.agents;
468
+ const defaults = agents?.defaults;
469
+ const hasMax = typeof defaults?.maxConcurrent === "number" && Number.isFinite(defaults.maxConcurrent);
470
+ const hasSubMax = typeof defaults?.subagents?.maxConcurrent === "number" && Number.isFinite(defaults.subagents.maxConcurrent);
471
+ if (hasMax && hasSubMax) return cfg;
472
+ let mutated = false;
473
+ const nextDefaults = defaults ? { ...defaults } : {};
474
+ if (!hasMax) {
475
+ nextDefaults.maxConcurrent = DEFAULT_AGENT_MAX_CONCURRENT;
476
+ mutated = true;
477
+ }
478
+ const nextSubagents = defaults?.subagents ? { ...defaults.subagents } : {};
479
+ if (!hasSubMax) {
480
+ nextSubagents.maxConcurrent = DEFAULT_SUBAGENT_MAX_CONCURRENT;
481
+ mutated = true;
482
+ }
483
+ if (!mutated) return cfg;
484
+ return {
485
+ ...cfg,
486
+ agents: {
487
+ ...agents,
488
+ defaults: {
489
+ ...nextDefaults,
490
+ subagents: nextSubagents
491
+ }
492
+ }
493
+ };
494
+ }
495
+ function applyLoggingDefaults(cfg) {
496
+ const logging = cfg.logging;
497
+ if (!logging) return cfg;
498
+ if (logging.redactSensitive) return cfg;
499
+ return {
500
+ ...cfg,
501
+ logging: {
502
+ ...logging,
503
+ redactSensitive: "tools"
504
+ }
505
+ };
506
+ }
507
+ function applyContextPruningDefaults(cfg) {
508
+ const defaults = cfg.agents?.defaults;
509
+ if (!defaults) return cfg;
510
+ const authMode = resolveAnthropicDefaultAuthMode(cfg);
511
+ if (!authMode) return cfg;
512
+ let mutated = false;
513
+ const nextDefaults = { ...defaults };
514
+ const contextPruning = defaults.contextPruning ?? {};
515
+ const heartbeat = defaults.heartbeat ?? {};
516
+ if (defaults.contextPruning?.mode === void 0) {
517
+ nextDefaults.contextPruning = {
518
+ ...contextPruning,
519
+ mode: "cache-ttl",
520
+ ttl: defaults.contextPruning?.ttl ?? "1h"
521
+ };
522
+ mutated = true;
523
+ }
524
+ if (defaults.heartbeat?.every === void 0) {
525
+ nextDefaults.heartbeat = {
526
+ ...heartbeat,
527
+ every: authMode === "oauth" ? "1h" : "30m"
528
+ };
529
+ mutated = true;
530
+ }
531
+ if (authMode === "api_key") {
532
+ const nextModels = defaults.models ? { ...defaults.models } : {};
533
+ let modelsMutated = false;
534
+ const isAnthropicCacheRetentionTarget = (parsed) => Boolean(parsed && (parsed.provider === "anthropic" || parsed.provider === "amazon-bedrock" && parsed.model.toLowerCase().includes("anthropic.claude")));
535
+ for (const [key, entry] of Object.entries(nextModels)) {
536
+ if (!isAnthropicCacheRetentionTarget(parseModelRef(key, "anthropic"))) continue;
537
+ const current = entry ?? {};
538
+ const params = current.params ?? {};
539
+ if (typeof params.cacheRetention === "string") continue;
540
+ nextModels[key] = {
541
+ ...current,
542
+ params: {
543
+ ...params,
544
+ cacheRetention: "short"
545
+ }
546
+ };
547
+ modelsMutated = true;
548
+ }
549
+ const rawModel = defaults.model;
550
+ const rawPrimary = typeof rawModel === "string" ? rawModel : rawModel?.primary;
551
+ const primary = resolvePrimaryModelRef(typeof rawPrimary === "string" ? rawPrimary : void 0);
552
+ if (primary) {
553
+ const parsedPrimary = parseModelRef(primary, "anthropic");
554
+ if (isAnthropicCacheRetentionTarget(parsedPrimary)) {
555
+ const key = `${parsedPrimary.provider}/${parsedPrimary.model}`;
556
+ const current = nextModels[key] ?? {};
557
+ const params = current.params ?? {};
558
+ if (typeof params.cacheRetention !== "string") {
559
+ nextModels[key] = {
560
+ ...current,
561
+ params: {
562
+ ...params,
563
+ cacheRetention: "short"
564
+ }
565
+ };
566
+ modelsMutated = true;
567
+ }
568
+ }
569
+ }
570
+ if (modelsMutated) {
571
+ nextDefaults.models = nextModels;
572
+ mutated = true;
573
+ }
574
+ }
575
+ if (!mutated) return cfg;
576
+ return {
577
+ ...cfg,
578
+ agents: {
579
+ ...cfg.agents,
580
+ defaults: nextDefaults
581
+ }
582
+ };
583
+ }
584
+
585
+ //#endregion
586
+ //#region src/config/env-preserve.ts
587
+ /**
588
+ * Preserves `${VAR}` environment variable references during config write-back.
589
+ *
590
+ * When config is read, `${VAR}` references are resolved to their values.
591
+ * When writing back, callers pass the resolved config. This module detects
592
+ * values that match what a `${VAR}` reference would resolve to and restores
593
+ * the original reference, so env var references survive config round-trips.
594
+ *
595
+ * A value is restored only if:
596
+ * 1. The pre-substitution value contained a `${VAR}` pattern
597
+ * 2. Resolving that pattern with current env vars produces the incoming value
598
+ *
599
+ * If a caller intentionally set a new value (different from what the env var
600
+ * resolves to), the new value is kept as-is.
601
+ */
602
+ const ENV_VAR_PATTERN = /\$\{[A-Z_][A-Z0-9_]*\}/;
603
+ /**
604
+ * Check if a string contains any `${VAR}` env var references.
605
+ */
606
+ function hasEnvVarRef(value) {
607
+ return ENV_VAR_PATTERN.test(value);
608
+ }
609
+ /**
610
+ * Resolve `${VAR}` references in a single string using the given env.
611
+ * Returns null if any referenced var is missing (instead of throwing).
612
+ *
613
+ * Mirrors the substitution semantics of `substituteString` in env-substitution.ts:
614
+ * - `${VAR}` → env value (returns null if missing)
615
+ * - `$${VAR}` → literal `${VAR}` (escape sequence)
616
+ */
617
+ function tryResolveString(template, env) {
618
+ const ENV_VAR_NAME = /^[A-Z_][A-Z0-9_]*$/;
619
+ const chunks = [];
620
+ for (let i = 0; i < template.length; i++) {
621
+ if (template[i] === "$") {
622
+ if (template[i + 1] === "$" && template[i + 2] === "{") {
623
+ const start = i + 3;
624
+ const end = template.indexOf("}", start);
625
+ if (end !== -1) {
626
+ const name = template.slice(start, end);
627
+ if (ENV_VAR_NAME.test(name)) {
628
+ chunks.push(`\${${name}}`);
629
+ i = end;
630
+ continue;
631
+ }
632
+ }
633
+ }
634
+ if (template[i + 1] === "{") {
635
+ const start = i + 2;
636
+ const end = template.indexOf("}", start);
637
+ if (end !== -1) {
638
+ const name = template.slice(start, end);
639
+ if (ENV_VAR_NAME.test(name)) {
640
+ const val = env[name];
641
+ if (val === void 0 || val === "") return null;
642
+ chunks.push(val);
643
+ i = end;
644
+ continue;
645
+ }
646
+ }
647
+ }
648
+ }
649
+ chunks.push(template[i]);
650
+ }
651
+ return chunks.join("");
652
+ }
653
+ /**
654
+ * Deep-walk the incoming config and restore `${VAR}` references from the
655
+ * pre-substitution parsed config wherever the resolved value matches.
656
+ *
657
+ * @param incoming - The resolved config about to be written
658
+ * @param parsed - The pre-substitution parsed config (from the current file on disk)
659
+ * @param env - Environment variables for verification
660
+ * @returns A new config object with env var references restored where appropriate
661
+ */
662
+ function restoreEnvVarRefs(incoming, parsed, env = process.env) {
663
+ if (parsed === null || parsed === void 0) return incoming;
664
+ if (typeof incoming === "string" && typeof parsed === "string") {
665
+ if (hasEnvVarRef(parsed)) {
666
+ if (tryResolveString(parsed, env) === incoming) return parsed;
667
+ }
668
+ return incoming;
669
+ }
670
+ if (Array.isArray(incoming) && Array.isArray(parsed)) return incoming.map((item, i) => i < parsed.length ? restoreEnvVarRefs(item, parsed[i], env) : item);
671
+ if (isPlainObject$2(incoming) && isPlainObject$2(parsed)) {
672
+ const result = {};
673
+ for (const [key, value] of Object.entries(incoming)) if (key in parsed) result[key] = restoreEnvVarRefs(value, parsed[key], env);
674
+ else result[key] = value;
675
+ return result;
676
+ }
677
+ return incoming;
678
+ }
679
+
680
+ //#endregion
681
+ //#region src/config/env-substitution.ts
682
+ /**
683
+ * Environment variable substitution for config values.
684
+ *
685
+ * Supports `${VAR_NAME}` syntax in string values, substituted at config load time.
686
+ * - Only uppercase env vars are matched: `[A-Z_][A-Z0-9_]*`
687
+ * - Escape with `$${}` to output literal `${}`
688
+ * - Missing env vars throw `MissingEnvVarError` with context
689
+ *
690
+ * @example
691
+ * ```json5
692
+ * {
693
+ * models: {
694
+ * providers: {
695
+ * "vercel-gateway": {
696
+ * apiKey: "${VERCEL_GATEWAY_API_KEY}"
697
+ * }
698
+ * }
699
+ * }
700
+ * }
701
+ * ```
702
+ */
703
+ const ENV_VAR_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
704
+ var MissingEnvVarError = class extends Error {
705
+ constructor(varName, configPath) {
706
+ super(`Missing env var "${varName}" referenced at config path: ${configPath}`);
707
+ this.varName = varName;
708
+ this.configPath = configPath;
709
+ this.name = "MissingEnvVarError";
710
+ }
711
+ };
712
+ function parseEnvTokenAt(value, index) {
713
+ if (value[index] !== "$") return null;
714
+ const next = value[index + 1];
715
+ const afterNext = value[index + 2];
716
+ if (next === "$" && afterNext === "{") {
717
+ const start = index + 3;
718
+ const end = value.indexOf("}", start);
719
+ if (end !== -1) {
720
+ const name = value.slice(start, end);
721
+ if (ENV_VAR_NAME_PATTERN.test(name)) return {
722
+ kind: "escaped",
723
+ name,
724
+ end
725
+ };
726
+ }
727
+ }
728
+ if (next === "{") {
729
+ const start = index + 2;
730
+ const end = value.indexOf("}", start);
731
+ if (end !== -1) {
732
+ const name = value.slice(start, end);
733
+ if (ENV_VAR_NAME_PATTERN.test(name)) return {
734
+ kind: "substitution",
735
+ name,
736
+ end
737
+ };
738
+ }
739
+ }
740
+ return null;
741
+ }
742
+ function substituteString(value, env, configPath) {
743
+ if (!value.includes("$")) return value;
744
+ const chunks = [];
745
+ for (let i = 0; i < value.length; i += 1) {
746
+ const char = value[i];
747
+ if (char !== "$") {
748
+ chunks.push(char);
749
+ continue;
750
+ }
751
+ const token = parseEnvTokenAt(value, i);
752
+ if (token?.kind === "escaped") {
753
+ chunks.push(`\${${token.name}}`);
754
+ i = token.end;
755
+ continue;
756
+ }
757
+ if (token?.kind === "substitution") {
758
+ const envValue = env[token.name];
759
+ if (envValue === void 0 || envValue === "") throw new MissingEnvVarError(token.name, configPath);
760
+ chunks.push(envValue);
761
+ i = token.end;
762
+ continue;
763
+ }
764
+ chunks.push(char);
765
+ }
766
+ return chunks.join("");
767
+ }
768
+ function containsEnvVarReference(value) {
769
+ if (!value.includes("$")) return false;
770
+ for (let i = 0; i < value.length; i += 1) {
771
+ if (value[i] !== "$") continue;
772
+ const token = parseEnvTokenAt(value, i);
773
+ if (token?.kind === "escaped") {
774
+ i = token.end;
775
+ continue;
776
+ }
777
+ if (token?.kind === "substitution") return true;
778
+ }
779
+ return false;
780
+ }
781
+ function substituteAny(value, env, path) {
782
+ if (typeof value === "string") return substituteString(value, env, path);
783
+ if (Array.isArray(value)) return value.map((item, index) => substituteAny(item, env, `${path}[${index}]`));
784
+ if (isPlainObject$2(value)) {
785
+ const result = {};
786
+ for (const [key, val] of Object.entries(value)) result[key] = substituteAny(val, env, path ? `${path}.${key}` : key);
787
+ return result;
788
+ }
789
+ return value;
790
+ }
791
+ /**
792
+ * Resolves `${VAR_NAME}` environment variable references in config values.
793
+ *
794
+ * @param obj - The parsed config object (after JSON5 parse and $include resolution)
795
+ * @param env - Environment variables to use for substitution (defaults to process.env)
796
+ * @returns The config object with env vars substituted
797
+ * @throws {MissingEnvVarError} If a referenced env var is not set or empty
798
+ */
799
+ function resolveConfigEnvVars(obj, env = process.env) {
800
+ return substituteAny(obj, env, "");
801
+ }
802
+
803
+ //#endregion
804
+ //#region src/security/scan-paths.ts
805
+ function isPathInside$1(basePath, candidatePath) {
806
+ const base = path.resolve(basePath);
807
+ const candidate = path.resolve(candidatePath);
808
+ const rel = path.relative(base, candidate);
809
+ return rel === "" || !rel.startsWith(`..${path.sep}`) && rel !== ".." && !path.isAbsolute(rel);
810
+ }
811
+ function safeRealpathSync$1(filePath) {
812
+ try {
813
+ return fs.realpathSync(filePath);
814
+ } catch {
815
+ return null;
816
+ }
817
+ }
818
+ function isPathInsideWithRealpath(basePath, candidatePath, opts) {
819
+ if (!isPathInside$1(basePath, candidatePath)) return false;
820
+ const baseReal = safeRealpathSync$1(basePath);
821
+ const candidateReal = safeRealpathSync$1(candidatePath);
822
+ if (!baseReal || !candidateReal) return opts?.requireRealpath !== true;
823
+ return isPathInside$1(baseReal, candidateReal);
824
+ }
825
+ function extensionUsesSkippedScannerPath(entry) {
826
+ return entry.split(/[\\/]+/).filter(Boolean).some((segment) => segment === "node_modules" || segment.startsWith(".") && segment !== "." && segment !== "..");
827
+ }
828
+
829
+ //#endregion
830
+ //#region src/config/includes.ts
831
+ /**
832
+ * Config includes: $include directive for modular configs
833
+ *
834
+ * @example
835
+ * ```json5
836
+ * {
837
+ * "$include": "./base.json5", // single file
838
+ * "$include": ["./a.json5", "./b.json5"] // merge multiple
839
+ * }
840
+ * ```
841
+ */
842
+ const INCLUDE_KEY = "$include";
843
+ const MAX_INCLUDE_DEPTH = 10;
844
+ var ConfigIncludeError = class extends Error {
845
+ constructor(message, includePath, cause) {
846
+ super(message);
847
+ this.includePath = includePath;
848
+ this.cause = cause;
849
+ this.name = "ConfigIncludeError";
850
+ }
851
+ };
852
+ var CircularIncludeError = class extends ConfigIncludeError {
853
+ constructor(chain) {
854
+ super(`Circular include detected: ${chain.join(" -> ")}`, chain[chain.length - 1]);
855
+ this.chain = chain;
856
+ this.name = "CircularIncludeError";
857
+ }
858
+ };
859
+ /** Deep merge: arrays concatenate, objects merge recursively, primitives: source wins */
860
+ function deepMerge(target, source) {
861
+ if (Array.isArray(target) && Array.isArray(source)) return [...target, ...source];
862
+ if (isPlainObject$2(target) && isPlainObject$2(source)) {
863
+ const result = { ...target };
864
+ for (const key of Object.keys(source)) {
865
+ if (isBlockedObjectKey(key)) continue;
866
+ result[key] = key in result ? deepMerge(result[key], source[key]) : source[key];
867
+ }
868
+ return result;
869
+ }
870
+ return source;
871
+ }
872
+ var IncludeProcessor = class IncludeProcessor {
873
+ constructor(basePath, resolver, rootDir) {
874
+ this.basePath = basePath;
875
+ this.resolver = resolver;
876
+ this.visited = /* @__PURE__ */ new Set();
877
+ this.depth = 0;
878
+ this.visited.add(path.normalize(basePath));
879
+ this.rootDir = path.normalize(rootDir ?? path.dirname(basePath));
880
+ this.rootRealDir = path.normalize(safeRealpath(this.rootDir));
881
+ }
882
+ process(obj) {
883
+ if (Array.isArray(obj)) return obj.map((item) => this.process(item));
884
+ if (!isPlainObject$2(obj)) return obj;
885
+ if (!(INCLUDE_KEY in obj)) return this.processObject(obj);
886
+ return this.processInclude(obj);
887
+ }
888
+ processObject(obj) {
889
+ const result = {};
890
+ for (const [key, value] of Object.entries(obj)) result[key] = this.process(value);
891
+ return result;
892
+ }
893
+ processInclude(obj) {
894
+ const includeValue = obj[INCLUDE_KEY];
895
+ const otherKeys = Object.keys(obj).filter((k) => k !== INCLUDE_KEY);
896
+ const included = this.resolveInclude(includeValue);
897
+ if (otherKeys.length === 0) return included;
898
+ if (!isPlainObject$2(included)) throw new ConfigIncludeError("Sibling keys require included content to be an object", typeof includeValue === "string" ? includeValue : INCLUDE_KEY);
899
+ const rest = {};
900
+ for (const key of otherKeys) rest[key] = this.process(obj[key]);
901
+ return deepMerge(included, rest);
902
+ }
903
+ resolveInclude(value) {
904
+ if (typeof value === "string") return this.loadFile(value);
905
+ if (Array.isArray(value)) return value.reduce((merged, item) => {
906
+ if (typeof item !== "string") throw new ConfigIncludeError(`Invalid $include array item: expected string, got ${typeof item}`, String(item));
907
+ return deepMerge(merged, this.loadFile(item));
908
+ }, {});
909
+ throw new ConfigIncludeError(`Invalid $include value: expected string or array of strings, got ${typeof value}`, String(value));
910
+ }
911
+ loadFile(includePath) {
912
+ const resolvedPath = this.resolvePath(includePath);
913
+ this.checkCircular(resolvedPath);
914
+ this.checkDepth(includePath);
915
+ const raw = this.readFile(includePath, resolvedPath);
916
+ const parsed = this.parseFile(includePath, resolvedPath, raw);
917
+ return this.processNested(resolvedPath, parsed);
918
+ }
919
+ resolvePath(includePath) {
920
+ const configDir = path.dirname(this.basePath);
921
+ const resolved = path.isAbsolute(includePath) ? includePath : path.resolve(configDir, includePath);
922
+ const normalized = path.normalize(resolved);
923
+ if (!isPathInside$1(this.rootDir, normalized)) throw new ConfigIncludeError(`Include path escapes config directory: ${includePath} (root: ${this.rootDir})`, includePath);
924
+ try {
925
+ const real = fs.realpathSync(normalized);
926
+ if (!isPathInside$1(this.rootRealDir, real)) throw new ConfigIncludeError(`Include path resolves outside config directory (symlink): ${includePath} (root: ${this.rootDir})`, includePath);
927
+ } catch (err) {
928
+ if (err instanceof ConfigIncludeError) throw err;
929
+ }
930
+ return normalized;
931
+ }
932
+ checkCircular(resolvedPath) {
933
+ if (this.visited.has(resolvedPath)) throw new CircularIncludeError([...this.visited, resolvedPath]);
934
+ }
935
+ checkDepth(includePath) {
936
+ if (this.depth >= MAX_INCLUDE_DEPTH) throw new ConfigIncludeError(`Maximum include depth (${MAX_INCLUDE_DEPTH}) exceeded at: ${includePath}`, includePath);
937
+ }
938
+ readFile(includePath, resolvedPath) {
939
+ try {
940
+ return this.resolver.readFile(resolvedPath);
941
+ } catch (err) {
942
+ throw new ConfigIncludeError(`Failed to read include file: ${includePath} (resolved: ${resolvedPath})`, includePath, err instanceof Error ? err : void 0);
943
+ }
944
+ }
945
+ parseFile(includePath, resolvedPath, raw) {
946
+ try {
947
+ return this.resolver.parseJson(raw);
948
+ } catch (err) {
949
+ throw new ConfigIncludeError(`Failed to parse include file: ${includePath} (resolved: ${resolvedPath})`, includePath, err instanceof Error ? err : void 0);
950
+ }
951
+ }
952
+ processNested(resolvedPath, parsed) {
953
+ const nested = new IncludeProcessor(resolvedPath, this.resolver, this.rootDir);
954
+ nested.visited = new Set([...this.visited, resolvedPath]);
955
+ nested.depth = this.depth + 1;
956
+ return nested.process(parsed);
957
+ }
958
+ };
959
+ function safeRealpath(target) {
960
+ try {
961
+ return fs.realpathSync(target);
962
+ } catch {
963
+ return target;
964
+ }
965
+ }
966
+ const defaultResolver = {
967
+ readFile: (p) => fs.readFileSync(p, "utf-8"),
968
+ parseJson: (raw) => JSON5.parse(raw)
969
+ };
970
+ /**
971
+ * Resolves all $include directives in a parsed config object.
972
+ */
973
+ function resolveConfigIncludes(obj, configPath, resolver = defaultResolver) {
974
+ return new IncludeProcessor(configPath, resolver).process(obj);
975
+ }
976
+
977
+ //#endregion
978
+ //#region src/config/legacy.shared.ts
979
+ const getRecord = (value) => isRecord(value) ? value : null;
980
+ const ensureRecord = (root, key) => {
981
+ const existing = root[key];
982
+ if (isRecord(existing)) return existing;
983
+ const next = {};
984
+ root[key] = next;
985
+ return next;
986
+ };
987
+ const mergeMissing = (target, source) => {
988
+ for (const [key, value] of Object.entries(source)) {
989
+ if (value === void 0 || isBlockedObjectKey(key)) continue;
990
+ const existing = target[key];
991
+ if (existing === void 0) {
992
+ target[key] = value;
993
+ continue;
994
+ }
995
+ if (isRecord(existing) && isRecord(value)) mergeMissing(existing, value);
996
+ }
997
+ };
998
+ const mapLegacyAudioTranscription = (value) => {
999
+ const transcriber = getRecord(value);
1000
+ const command = Array.isArray(transcriber?.command) ? transcriber?.command : null;
1001
+ if (!command || command.length === 0) return null;
1002
+ if (typeof command[0] !== "string") return null;
1003
+ if (!command.every((part) => typeof part === "string")) return null;
1004
+ const rawExecutable = command[0].trim();
1005
+ if (!rawExecutable) return null;
1006
+ if (!isSafeExecutableValue(rawExecutable)) return null;
1007
+ const args = command.slice(1);
1008
+ const timeoutSeconds = typeof transcriber?.timeoutSeconds === "number" ? transcriber?.timeoutSeconds : void 0;
1009
+ const result = {
1010
+ command: rawExecutable,
1011
+ type: "cli"
1012
+ };
1013
+ if (args.length > 0) result.args = args;
1014
+ if (timeoutSeconds !== void 0) result.timeoutSeconds = timeoutSeconds;
1015
+ return result;
1016
+ };
1017
+ const getAgentsList = (agents) => {
1018
+ const list = agents?.list;
1019
+ return Array.isArray(list) ? list : [];
1020
+ };
1021
+ const resolveDefaultAgentIdFromRaw = (raw) => {
1022
+ const list = getAgentsList(getRecord(raw.agents));
1023
+ const defaultEntry = list.find((entry) => isRecord(entry) && entry.default === true && typeof entry.id === "string" && entry.id.trim() !== "");
1024
+ if (defaultEntry) return defaultEntry.id.trim();
1025
+ const routing = getRecord(raw.routing);
1026
+ const routingDefault = typeof routing?.defaultAgentId === "string" ? routing.defaultAgentId.trim() : "";
1027
+ if (routingDefault) return routingDefault;
1028
+ const firstEntry = list.find((entry) => isRecord(entry) && typeof entry.id === "string" && entry.id.trim() !== "");
1029
+ if (firstEntry) return firstEntry.id.trim();
1030
+ return "main";
1031
+ };
1032
+ const ensureAgentEntry = (list, id) => {
1033
+ const normalized = id.trim();
1034
+ const existing = list.find((entry) => isRecord(entry) && typeof entry.id === "string" && entry.id.trim() === normalized);
1035
+ if (existing) return existing;
1036
+ const created = { id: normalized };
1037
+ list.push(created);
1038
+ return created;
1039
+ };
1040
+
1041
+ //#endregion
1042
+ //#region src/config/legacy.migrations.part-1.ts
1043
+ function migrateBindings(raw, changes, changeNote, mutator) {
1044
+ const bindings = Array.isArray(raw.bindings) ? raw.bindings : null;
1045
+ if (!bindings) return;
1046
+ let touched = false;
1047
+ for (const entry of bindings) {
1048
+ if (!isRecord(entry)) continue;
1049
+ const match = getRecord(entry.match);
1050
+ if (!match) continue;
1051
+ if (!mutator(match)) continue;
1052
+ entry.match = match;
1053
+ touched = true;
1054
+ }
1055
+ if (touched) {
1056
+ raw.bindings = bindings;
1057
+ changes.push(changeNote);
1058
+ }
1059
+ }
1060
+ function ensureDefaultGroupEntry(section) {
1061
+ const groups = isRecord(section.groups) ? section.groups : {};
1062
+ const defaultKey = "*";
1063
+ return {
1064
+ groups,
1065
+ entry: isRecord(groups[defaultKey]) ? groups[defaultKey] : {}
1066
+ };
1067
+ }
1068
+ const LEGACY_CONFIG_MIGRATIONS_PART_1 = [
1069
+ {
1070
+ id: "bindings.match.provider->bindings.match.channel",
1071
+ describe: "Move bindings[].match.provider to bindings[].match.channel",
1072
+ apply: (raw, changes) => {
1073
+ migrateBindings(raw, changes, "Moved bindings[].match.provider → bindings[].match.channel.", (match) => {
1074
+ if (typeof match.channel === "string" && match.channel.trim()) return false;
1075
+ const provider = typeof match.provider === "string" ? match.provider.trim() : "";
1076
+ if (!provider) return false;
1077
+ match.channel = provider;
1078
+ delete match.provider;
1079
+ return true;
1080
+ });
1081
+ }
1082
+ },
1083
+ {
1084
+ id: "bindings.match.accountID->bindings.match.accountId",
1085
+ describe: "Move bindings[].match.accountID to bindings[].match.accountId",
1086
+ apply: (raw, changes) => {
1087
+ migrateBindings(raw, changes, "Moved bindings[].match.accountID → bindings[].match.accountId.", (match) => {
1088
+ if (match.accountId !== void 0) return false;
1089
+ const accountID = typeof match.accountID === "string" ? match.accountID.trim() : match.accountID;
1090
+ if (!accountID) return false;
1091
+ match.accountId = accountID;
1092
+ delete match.accountID;
1093
+ return true;
1094
+ });
1095
+ }
1096
+ },
1097
+ {
1098
+ id: "session.sendPolicy.rules.match.provider->match.channel",
1099
+ describe: "Move session.sendPolicy.rules[].match.provider to match.channel",
1100
+ apply: (raw, changes) => {
1101
+ const session = getRecord(raw.session);
1102
+ if (!session) return;
1103
+ const sendPolicy = getRecord(session.sendPolicy);
1104
+ if (!sendPolicy) return;
1105
+ const rules = Array.isArray(sendPolicy.rules) ? sendPolicy.rules : null;
1106
+ if (!rules) return;
1107
+ let touched = false;
1108
+ for (const rule of rules) {
1109
+ if (!isRecord(rule)) continue;
1110
+ const match = getRecord(rule.match);
1111
+ if (!match) continue;
1112
+ if (typeof match.channel === "string" && match.channel.trim()) continue;
1113
+ const provider = typeof match.provider === "string" ? match.provider.trim() : "";
1114
+ if (!provider) continue;
1115
+ match.channel = provider;
1116
+ delete match.provider;
1117
+ rule.match = match;
1118
+ touched = true;
1119
+ }
1120
+ if (touched) {
1121
+ sendPolicy.rules = rules;
1122
+ session.sendPolicy = sendPolicy;
1123
+ raw.session = session;
1124
+ changes.push("Moved session.sendPolicy.rules[].match.provider → match.channel.");
1125
+ }
1126
+ }
1127
+ },
1128
+ {
1129
+ id: "messages.queue.byProvider->byChannel",
1130
+ describe: "Move messages.queue.byProvider to messages.queue.byChannel",
1131
+ apply: (raw, changes) => {
1132
+ const messages = getRecord(raw.messages);
1133
+ if (!messages) return;
1134
+ const queue = getRecord(messages.queue);
1135
+ if (!queue) return;
1136
+ if (queue.byProvider === void 0) return;
1137
+ if (queue.byChannel === void 0) {
1138
+ queue.byChannel = queue.byProvider;
1139
+ changes.push("Moved messages.queue.byProvider → messages.queue.byChannel.");
1140
+ } else changes.push("Removed messages.queue.byProvider (messages.queue.byChannel already set).");
1141
+ delete queue.byProvider;
1142
+ messages.queue = queue;
1143
+ raw.messages = messages;
1144
+ }
1145
+ },
1146
+ {
1147
+ id: "providers->channels",
1148
+ describe: "Move provider config sections to channels.*",
1149
+ apply: (raw, changes) => {
1150
+ const legacyEntries = [
1151
+ "whatsapp",
1152
+ "telegram",
1153
+ "discord",
1154
+ "slack",
1155
+ "signal",
1156
+ "imessage",
1157
+ "msteams"
1158
+ ].filter((key) => isRecord(raw[key]));
1159
+ if (legacyEntries.length === 0) return;
1160
+ const channels = ensureRecord(raw, "channels");
1161
+ for (const key of legacyEntries) {
1162
+ const legacy = getRecord(raw[key]);
1163
+ if (!legacy) continue;
1164
+ const channelEntry = ensureRecord(channels, key);
1165
+ const hadEntries = Object.keys(channelEntry).length > 0;
1166
+ mergeMissing(channelEntry, legacy);
1167
+ channels[key] = channelEntry;
1168
+ delete raw[key];
1169
+ changes.push(hadEntries ? `Merged ${key} → channels.${key}.` : `Moved ${key} → channels.${key}.`);
1170
+ }
1171
+ raw.channels = channels;
1172
+ }
1173
+ },
1174
+ {
1175
+ id: "channels.streaming-keys->channels.streaming",
1176
+ describe: "Normalize legacy streaming keys to channels.<provider>.streaming (Telegram/Discord/Slack)",
1177
+ apply: (raw, changes) => {
1178
+ const channels = getRecord(raw.channels);
1179
+ if (!channels) return;
1180
+ const migrateProviderEntry = (params) => {
1181
+ const migrateCommonStreamingMode = (resolveMode) => {
1182
+ const hasLegacyStreamMode = params.entry.streamMode !== void 0;
1183
+ const legacyStreaming = params.entry.streaming;
1184
+ if (!hasLegacyStreamMode && typeof legacyStreaming !== "boolean") return false;
1185
+ const resolved = resolveMode(params.entry);
1186
+ params.entry.streaming = resolved;
1187
+ if (hasLegacyStreamMode) {
1188
+ delete params.entry.streamMode;
1189
+ changes.push(`Moved ${params.pathPrefix}.streamMode → ${params.pathPrefix}.streaming (${resolved}).`);
1190
+ }
1191
+ if (typeof legacyStreaming === "boolean") changes.push(`Normalized ${params.pathPrefix}.streaming boolean → enum (${resolved}).`);
1192
+ return true;
1193
+ };
1194
+ const hasLegacyStreamMode = params.entry.streamMode !== void 0;
1195
+ const legacyStreaming = params.entry.streaming;
1196
+ const legacyNativeStreaming = params.entry.nativeStreaming;
1197
+ if (params.provider === "telegram") {
1198
+ migrateCommonStreamingMode(resolveTelegramPreviewStreamMode);
1199
+ return;
1200
+ }
1201
+ if (params.provider === "discord") {
1202
+ migrateCommonStreamingMode(resolveDiscordPreviewStreamMode);
1203
+ return;
1204
+ }
1205
+ if (!hasLegacyStreamMode && typeof legacyStreaming !== "boolean") return;
1206
+ const resolvedStreaming = resolveSlackStreamingMode(params.entry);
1207
+ const resolvedNativeStreaming = resolveSlackNativeStreaming(params.entry);
1208
+ params.entry.streaming = resolvedStreaming;
1209
+ params.entry.nativeStreaming = resolvedNativeStreaming;
1210
+ if (hasLegacyStreamMode) {
1211
+ delete params.entry.streamMode;
1212
+ changes.push(`Moved ${params.pathPrefix}.streamMode → ${params.pathPrefix}.streaming (${resolvedStreaming}).`);
1213
+ }
1214
+ if (typeof legacyStreaming === "boolean") changes.push(`Moved ${params.pathPrefix}.streaming (boolean) → ${params.pathPrefix}.nativeStreaming (${resolvedNativeStreaming}).`);
1215
+ else if (typeof legacyNativeStreaming !== "boolean" && hasLegacyStreamMode) changes.push(`Set ${params.pathPrefix}.nativeStreaming → ${resolvedNativeStreaming}.`);
1216
+ };
1217
+ const migrateProvider = (provider) => {
1218
+ const providerEntry = getRecord(channels[provider]);
1219
+ if (!providerEntry) return;
1220
+ migrateProviderEntry({
1221
+ provider,
1222
+ entry: providerEntry,
1223
+ pathPrefix: `channels.${provider}`
1224
+ });
1225
+ const accounts = getRecord(providerEntry.accounts);
1226
+ if (!accounts) return;
1227
+ for (const [accountId, accountValue] of Object.entries(accounts)) {
1228
+ const account = getRecord(accountValue);
1229
+ if (!account) continue;
1230
+ migrateProviderEntry({
1231
+ provider,
1232
+ entry: account,
1233
+ pathPrefix: `channels.${provider}.accounts.${accountId}`
1234
+ });
1235
+ }
1236
+ };
1237
+ migrateProvider("telegram");
1238
+ migrateProvider("discord");
1239
+ migrateProvider("slack");
1240
+ }
1241
+ },
1242
+ {
1243
+ id: "routing.allowFrom->channels.whatsapp.allowFrom",
1244
+ describe: "Move routing.allowFrom to channels.whatsapp.allowFrom",
1245
+ apply: (raw, changes) => {
1246
+ const routing = raw.routing;
1247
+ if (!routing || typeof routing !== "object") return;
1248
+ const allowFrom = routing.allowFrom;
1249
+ if (allowFrom === void 0) return;
1250
+ const channels = getRecord(raw.channels);
1251
+ const whatsapp = channels ? getRecord(channels.whatsapp) : null;
1252
+ if (!whatsapp) {
1253
+ delete routing.allowFrom;
1254
+ if (Object.keys(routing).length === 0) delete raw.routing;
1255
+ changes.push("Removed routing.allowFrom (channels.whatsapp not configured).");
1256
+ return;
1257
+ }
1258
+ if (whatsapp.allowFrom === void 0) {
1259
+ whatsapp.allowFrom = allowFrom;
1260
+ changes.push("Moved routing.allowFrom → channels.whatsapp.allowFrom.");
1261
+ } else changes.push("Removed routing.allowFrom (channels.whatsapp.allowFrom already set).");
1262
+ delete routing.allowFrom;
1263
+ if (Object.keys(routing).length === 0) delete raw.routing;
1264
+ channels.whatsapp = whatsapp;
1265
+ raw.channels = channels;
1266
+ }
1267
+ },
1268
+ {
1269
+ id: "routing.groupChat.requireMention->groups.*.requireMention",
1270
+ describe: "Move routing.groupChat.requireMention to channels.whatsapp/telegram/imessage groups",
1271
+ apply: (raw, changes) => {
1272
+ const routing = raw.routing;
1273
+ if (!routing || typeof routing !== "object") return;
1274
+ const groupChat = routing.groupChat && typeof routing.groupChat === "object" ? routing.groupChat : null;
1275
+ if (!groupChat) return;
1276
+ const requireMention = groupChat.requireMention;
1277
+ if (requireMention === void 0) return;
1278
+ const channels = ensureRecord(raw, "channels");
1279
+ const applyTo = (key, options) => {
1280
+ if (options?.requireExisting && !isRecord(channels[key])) return;
1281
+ const section = channels[key] && typeof channels[key] === "object" ? channels[key] : {};
1282
+ const { groups, entry } = ensureDefaultGroupEntry(section);
1283
+ const defaultKey = "*";
1284
+ if (entry.requireMention === void 0) {
1285
+ entry.requireMention = requireMention;
1286
+ groups[defaultKey] = entry;
1287
+ section.groups = groups;
1288
+ channels[key] = section;
1289
+ changes.push(`Moved routing.groupChat.requireMention → channels.${key}.groups."*".requireMention.`);
1290
+ } else changes.push(`Removed routing.groupChat.requireMention (channels.${key}.groups."*" already set).`);
1291
+ };
1292
+ applyTo("whatsapp", { requireExisting: true });
1293
+ applyTo("telegram");
1294
+ applyTo("imessage");
1295
+ delete groupChat.requireMention;
1296
+ if (Object.keys(groupChat).length === 0) delete routing.groupChat;
1297
+ if (Object.keys(routing).length === 0) delete raw.routing;
1298
+ raw.channels = channels;
1299
+ }
1300
+ },
1301
+ {
1302
+ id: "gateway.token->gateway.auth.token",
1303
+ describe: "Move gateway.token to gateway.auth.token",
1304
+ apply: (raw, changes) => {
1305
+ const gateway = raw.gateway;
1306
+ if (!gateway || typeof gateway !== "object") return;
1307
+ const token = gateway.token;
1308
+ if (token === void 0) return;
1309
+ const gatewayObj = gateway;
1310
+ const auth = gatewayObj.auth && typeof gatewayObj.auth === "object" ? gatewayObj.auth : {};
1311
+ if (auth.token === void 0) {
1312
+ auth.token = token;
1313
+ if (!auth.mode) auth.mode = "token";
1314
+ changes.push("Moved gateway.token → gateway.auth.token.");
1315
+ } else changes.push("Removed gateway.token (gateway.auth.token already set).");
1316
+ delete gatewayObj.token;
1317
+ if (Object.keys(auth).length > 0) gatewayObj.auth = auth;
1318
+ raw.gateway = gatewayObj;
1319
+ }
1320
+ },
1321
+ {
1322
+ id: "telegram.requireMention->channels.telegram.groups.*.requireMention",
1323
+ describe: "Move telegram.requireMention to channels.telegram.groups.*.requireMention",
1324
+ apply: (raw, changes) => {
1325
+ const channels = ensureRecord(raw, "channels");
1326
+ const telegram = channels.telegram;
1327
+ if (!telegram || typeof telegram !== "object") return;
1328
+ const requireMention = telegram.requireMention;
1329
+ if (requireMention === void 0) return;
1330
+ const { groups, entry } = ensureDefaultGroupEntry(telegram);
1331
+ const defaultKey = "*";
1332
+ if (entry.requireMention === void 0) {
1333
+ entry.requireMention = requireMention;
1334
+ groups[defaultKey] = entry;
1335
+ telegram.groups = groups;
1336
+ changes.push("Moved telegram.requireMention → channels.telegram.groups.\"*\".requireMention.");
1337
+ } else changes.push("Removed telegram.requireMention (channels.telegram.groups.\"*\" already set).");
1338
+ delete telegram.requireMention;
1339
+ channels.telegram = telegram;
1340
+ raw.channels = channels;
1341
+ }
1342
+ }
1343
+ ];
1344
+
1345
+ //#endregion
1346
+ //#region src/config/legacy.migrations.part-2.ts
1347
+ function applyLegacyAudioTranscriptionModel(params) {
1348
+ const mapped = mapLegacyAudioTranscription(params.source);
1349
+ if (!mapped) {
1350
+ params.changes.push(params.invalidMessage);
1351
+ return;
1352
+ }
1353
+ const mediaAudio = ensureRecord(ensureRecord(ensureRecord(params.raw, "tools"), "media"), "audio");
1354
+ if ((Array.isArray(mediaAudio.models) ? mediaAudio.models : []).length === 0) {
1355
+ mediaAudio.enabled = true;
1356
+ mediaAudio.models = [mapped];
1357
+ params.changes.push(params.movedMessage);
1358
+ return;
1359
+ }
1360
+ params.changes.push(params.alreadySetMessage);
1361
+ }
1362
+ const LEGACY_CONFIG_MIGRATIONS_PART_2 = [
1363
+ {
1364
+ id: "agent.model-config-v2",
1365
+ describe: "Migrate legacy agent.model/allowedModels/modelAliases/modelFallbacks/imageModelFallbacks to agent.models + model lists",
1366
+ apply: (raw, changes) => {
1367
+ const agentRoot = getRecord(raw.agent);
1368
+ const defaults = getRecord(getRecord(raw.agents)?.defaults);
1369
+ const agent = agentRoot ?? defaults;
1370
+ if (!agent) return;
1371
+ const label = agentRoot ? "agent" : "agents.defaults";
1372
+ const legacyModel = typeof agent.model === "string" ? String(agent.model) : void 0;
1373
+ const legacyImageModel = typeof agent.imageModel === "string" ? String(agent.imageModel) : void 0;
1374
+ const legacyAllowed = Array.isArray(agent.allowedModels) ? agent.allowedModels.map(String) : [];
1375
+ const legacyModelFallbacks = Array.isArray(agent.modelFallbacks) ? agent.modelFallbacks.map(String) : [];
1376
+ const legacyImageModelFallbacks = Array.isArray(agent.imageModelFallbacks) ? agent.imageModelFallbacks.map(String) : [];
1377
+ const legacyAliases = agent.modelAliases && typeof agent.modelAliases === "object" ? agent.modelAliases : {};
1378
+ if (!(legacyModel || legacyImageModel || legacyAllowed.length > 0 || legacyModelFallbacks.length > 0 || legacyImageModelFallbacks.length > 0 || Object.keys(legacyAliases).length > 0)) return;
1379
+ const models = agent.models && typeof agent.models === "object" ? agent.models : {};
1380
+ const ensureModel = (rawKey) => {
1381
+ if (typeof rawKey !== "string") return;
1382
+ const key = rawKey.trim();
1383
+ if (!key) return;
1384
+ if (!models[key]) models[key] = {};
1385
+ };
1386
+ ensureModel(legacyModel);
1387
+ ensureModel(legacyImageModel);
1388
+ for (const key of legacyAllowed) ensureModel(key);
1389
+ for (const key of legacyModelFallbacks) ensureModel(key);
1390
+ for (const key of legacyImageModelFallbacks) ensureModel(key);
1391
+ for (const target of Object.values(legacyAliases)) {
1392
+ if (typeof target !== "string") continue;
1393
+ ensureModel(target);
1394
+ }
1395
+ for (const [alias, targetRaw] of Object.entries(legacyAliases)) {
1396
+ if (typeof targetRaw !== "string") continue;
1397
+ const target = targetRaw.trim();
1398
+ if (!target) continue;
1399
+ const entry = models[target] && typeof models[target] === "object" ? models[target] : {};
1400
+ if (!("alias" in entry)) {
1401
+ entry.alias = alias;
1402
+ models[target] = entry;
1403
+ }
1404
+ }
1405
+ const currentModel = agent.model && typeof agent.model === "object" ? agent.model : null;
1406
+ if (currentModel) {
1407
+ if (!currentModel.primary && legacyModel) currentModel.primary = legacyModel;
1408
+ if (legacyModelFallbacks.length > 0 && (!Array.isArray(currentModel.fallbacks) || currentModel.fallbacks.length === 0)) currentModel.fallbacks = legacyModelFallbacks;
1409
+ agent.model = currentModel;
1410
+ } else if (legacyModel || legacyModelFallbacks.length > 0) agent.model = {
1411
+ primary: legacyModel,
1412
+ fallbacks: legacyModelFallbacks.length ? legacyModelFallbacks : []
1413
+ };
1414
+ const currentImageModel = agent.imageModel && typeof agent.imageModel === "object" ? agent.imageModel : null;
1415
+ if (currentImageModel) {
1416
+ if (!currentImageModel.primary && legacyImageModel) currentImageModel.primary = legacyImageModel;
1417
+ if (legacyImageModelFallbacks.length > 0 && (!Array.isArray(currentImageModel.fallbacks) || currentImageModel.fallbacks.length === 0)) currentImageModel.fallbacks = legacyImageModelFallbacks;
1418
+ agent.imageModel = currentImageModel;
1419
+ } else if (legacyImageModel || legacyImageModelFallbacks.length > 0) agent.imageModel = {
1420
+ primary: legacyImageModel,
1421
+ fallbacks: legacyImageModelFallbacks.length ? legacyImageModelFallbacks : []
1422
+ };
1423
+ agent.models = models;
1424
+ if (legacyModel !== void 0) changes.push(`Migrated ${label}.model string → ${label}.model.primary.`);
1425
+ if (legacyModelFallbacks.length > 0) changes.push(`Migrated ${label}.modelFallbacks → ${label}.model.fallbacks.`);
1426
+ if (legacyImageModel !== void 0) changes.push(`Migrated ${label}.imageModel string → ${label}.imageModel.primary.`);
1427
+ if (legacyImageModelFallbacks.length > 0) changes.push(`Migrated ${label}.imageModelFallbacks → ${label}.imageModel.fallbacks.`);
1428
+ if (legacyAllowed.length > 0) changes.push(`Migrated ${label}.allowedModels → ${label}.models.`);
1429
+ if (Object.keys(legacyAliases).length > 0) changes.push(`Migrated ${label}.modelAliases → ${label}.models.*.alias.`);
1430
+ delete agent.allowedModels;
1431
+ delete agent.modelAliases;
1432
+ delete agent.modelFallbacks;
1433
+ delete agent.imageModelFallbacks;
1434
+ }
1435
+ },
1436
+ {
1437
+ id: "routing.agents-v2",
1438
+ describe: "Move routing.agents/defaultAgentId to agents.list",
1439
+ apply: (raw, changes) => {
1440
+ const routing = getRecord(raw.routing);
1441
+ if (!routing) return;
1442
+ const routingAgents = getRecord(routing.agents);
1443
+ const agents = ensureRecord(raw, "agents");
1444
+ const list = getAgentsList(agents);
1445
+ if (routingAgents) {
1446
+ for (const [rawId, entryRaw] of Object.entries(routingAgents)) {
1447
+ const agentId = String(rawId ?? "").trim();
1448
+ const entry = getRecord(entryRaw);
1449
+ if (!agentId || !entry) continue;
1450
+ const target = ensureAgentEntry(list, agentId);
1451
+ const entryCopy = { ...entry };
1452
+ if ("mentionPatterns" in entryCopy) {
1453
+ const mentionPatterns = entryCopy.mentionPatterns;
1454
+ const groupChat = ensureRecord(target, "groupChat");
1455
+ if (groupChat.mentionPatterns === void 0) {
1456
+ groupChat.mentionPatterns = mentionPatterns;
1457
+ changes.push(`Moved routing.agents.${agentId}.mentionPatterns → agents.list (id "${agentId}").groupChat.mentionPatterns.`);
1458
+ } else changes.push(`Removed routing.agents.${agentId}.mentionPatterns (agents.list groupChat mentionPatterns already set).`);
1459
+ delete entryCopy.mentionPatterns;
1460
+ }
1461
+ const legacyGroupChat = getRecord(entryCopy.groupChat);
1462
+ if (legacyGroupChat) {
1463
+ mergeMissing(ensureRecord(target, "groupChat"), legacyGroupChat);
1464
+ delete entryCopy.groupChat;
1465
+ }
1466
+ const legacySandbox = getRecord(entryCopy.sandbox);
1467
+ if (legacySandbox) {
1468
+ const sandboxTools = getRecord(legacySandbox.tools);
1469
+ if (sandboxTools) {
1470
+ mergeMissing(ensureRecord(ensureRecord(ensureRecord(target, "tools"), "sandbox"), "tools"), sandboxTools);
1471
+ delete legacySandbox.tools;
1472
+ changes.push(`Moved routing.agents.${agentId}.sandbox.tools → agents.list (id "${agentId}").tools.sandbox.tools.`);
1473
+ }
1474
+ entryCopy.sandbox = legacySandbox;
1475
+ }
1476
+ mergeMissing(target, entryCopy);
1477
+ }
1478
+ delete routing.agents;
1479
+ changes.push("Moved routing.agents → agents.list.");
1480
+ }
1481
+ const defaultAgentId = typeof routing.defaultAgentId === "string" ? routing.defaultAgentId.trim() : "";
1482
+ if (defaultAgentId) {
1483
+ if (!list.some((entry) => isRecord(entry) && entry.default === true)) {
1484
+ const entry = ensureAgentEntry(list, defaultAgentId);
1485
+ entry.default = true;
1486
+ changes.push(`Moved routing.defaultAgentId → agents.list (id "${defaultAgentId}").default.`);
1487
+ } else changes.push("Removed routing.defaultAgentId (agents.list default already set).");
1488
+ delete routing.defaultAgentId;
1489
+ }
1490
+ if (list.length > 0) agents.list = list;
1491
+ if (Object.keys(routing).length === 0) delete raw.routing;
1492
+ }
1493
+ },
1494
+ {
1495
+ id: "routing.config-v2",
1496
+ describe: "Move routing bindings/groupChat/queue/agentToAgent/transcribeAudio",
1497
+ apply: (raw, changes) => {
1498
+ const routing = getRecord(raw.routing);
1499
+ if (!routing) return;
1500
+ if (routing.bindings !== void 0) {
1501
+ if (raw.bindings === void 0) {
1502
+ raw.bindings = routing.bindings;
1503
+ changes.push("Moved routing.bindings → bindings.");
1504
+ } else changes.push("Removed routing.bindings (bindings already set).");
1505
+ delete routing.bindings;
1506
+ }
1507
+ if (routing.agentToAgent !== void 0) {
1508
+ const tools = ensureRecord(raw, "tools");
1509
+ if (tools.agentToAgent === void 0) {
1510
+ tools.agentToAgent = routing.agentToAgent;
1511
+ changes.push("Moved routing.agentToAgent → tools.agentToAgent.");
1512
+ } else changes.push("Removed routing.agentToAgent (tools.agentToAgent already set).");
1513
+ delete routing.agentToAgent;
1514
+ }
1515
+ if (routing.queue !== void 0) {
1516
+ const messages = ensureRecord(raw, "messages");
1517
+ if (messages.queue === void 0) {
1518
+ messages.queue = routing.queue;
1519
+ changes.push("Moved routing.queue → messages.queue.");
1520
+ } else changes.push("Removed routing.queue (messages.queue already set).");
1521
+ delete routing.queue;
1522
+ }
1523
+ const groupChat = getRecord(routing.groupChat);
1524
+ if (groupChat) {
1525
+ const historyLimit = groupChat.historyLimit;
1526
+ if (historyLimit !== void 0) {
1527
+ const messagesGroup = ensureRecord(ensureRecord(raw, "messages"), "groupChat");
1528
+ if (messagesGroup.historyLimit === void 0) {
1529
+ messagesGroup.historyLimit = historyLimit;
1530
+ changes.push("Moved routing.groupChat.historyLimit → messages.groupChat.historyLimit.");
1531
+ } else changes.push("Removed routing.groupChat.historyLimit (messages.groupChat.historyLimit already set).");
1532
+ delete groupChat.historyLimit;
1533
+ }
1534
+ const mentionPatterns = groupChat.mentionPatterns;
1535
+ if (mentionPatterns !== void 0) {
1536
+ const messagesGroup = ensureRecord(ensureRecord(raw, "messages"), "groupChat");
1537
+ if (messagesGroup.mentionPatterns === void 0) {
1538
+ messagesGroup.mentionPatterns = mentionPatterns;
1539
+ changes.push("Moved routing.groupChat.mentionPatterns → messages.groupChat.mentionPatterns.");
1540
+ } else changes.push("Removed routing.groupChat.mentionPatterns (messages.groupChat.mentionPatterns already set).");
1541
+ delete groupChat.mentionPatterns;
1542
+ }
1543
+ if (Object.keys(groupChat).length === 0) delete routing.groupChat;
1544
+ else routing.groupChat = groupChat;
1545
+ }
1546
+ if (routing.transcribeAudio !== void 0) {
1547
+ applyLegacyAudioTranscriptionModel({
1548
+ raw,
1549
+ source: routing.transcribeAudio,
1550
+ changes,
1551
+ movedMessage: "Moved routing.transcribeAudio → tools.media.audio.models.",
1552
+ alreadySetMessage: "Removed routing.transcribeAudio (tools.media.audio.models already set).",
1553
+ invalidMessage: "Removed routing.transcribeAudio (invalid or empty command)."
1554
+ });
1555
+ delete routing.transcribeAudio;
1556
+ }
1557
+ if (Object.keys(routing).length === 0) delete raw.routing;
1558
+ }
1559
+ },
1560
+ {
1561
+ id: "audio.transcription-v2",
1562
+ describe: "Move audio.transcription to tools.media.audio.models",
1563
+ apply: (raw, changes) => {
1564
+ const audio = getRecord(raw.audio);
1565
+ if (audio?.transcription === void 0) return;
1566
+ applyLegacyAudioTranscriptionModel({
1567
+ raw,
1568
+ source: audio.transcription,
1569
+ changes,
1570
+ movedMessage: "Moved audio.transcription → tools.media.audio.models.",
1571
+ alreadySetMessage: "Removed audio.transcription (tools.media.audio.models already set).",
1572
+ invalidMessage: "Removed audio.transcription (invalid or empty command)."
1573
+ });
1574
+ delete audio.transcription;
1575
+ if (Object.keys(audio).length === 0) delete raw.audio;
1576
+ else raw.audio = audio;
1577
+ }
1578
+ }
1579
+ ];
1580
+
1581
+ //#endregion
1582
+ //#region src/config/legacy.migrations.part-3.ts
1583
+ const LEGACY_CONFIG_MIGRATIONS_PART_3 = [
1584
+ {
1585
+ id: "auth.anthropic-claude-cli-mode-oauth",
1586
+ describe: "Switch anthropic:claude-cli auth profile mode to oauth",
1587
+ apply: (raw, changes) => {
1588
+ const profiles = getRecord(getRecord(raw.auth)?.profiles);
1589
+ if (!profiles) return;
1590
+ const claudeCli = getRecord(profiles["anthropic:claude-cli"]);
1591
+ if (!claudeCli) return;
1592
+ if (claudeCli.mode !== "token") return;
1593
+ claudeCli.mode = "oauth";
1594
+ changes.push("Updated auth.profiles[\"anthropic:claude-cli\"].mode → \"oauth\".");
1595
+ }
1596
+ },
1597
+ {
1598
+ id: "tools.bash->tools.exec",
1599
+ describe: "Move tools.bash to tools.exec",
1600
+ apply: (raw, changes) => {
1601
+ const tools = ensureRecord(raw, "tools");
1602
+ const bash = getRecord(tools.bash);
1603
+ if (!bash) return;
1604
+ if (tools.exec === void 0) {
1605
+ tools.exec = bash;
1606
+ changes.push("Moved tools.bash → tools.exec.");
1607
+ } else changes.push("Removed tools.bash (tools.exec already set).");
1608
+ delete tools.bash;
1609
+ }
1610
+ },
1611
+ {
1612
+ id: "messages.tts.enabled->auto",
1613
+ describe: "Move messages.tts.enabled to messages.tts.auto",
1614
+ apply: (raw, changes) => {
1615
+ const tts = getRecord(getRecord(raw.messages)?.tts);
1616
+ if (!tts) return;
1617
+ if (tts.auto !== void 0) {
1618
+ if ("enabled" in tts) {
1619
+ delete tts.enabled;
1620
+ changes.push("Removed messages.tts.enabled (messages.tts.auto already set).");
1621
+ }
1622
+ return;
1623
+ }
1624
+ if (typeof tts.enabled !== "boolean") return;
1625
+ tts.auto = tts.enabled ? "always" : "off";
1626
+ delete tts.enabled;
1627
+ changes.push(`Moved messages.tts.enabled → messages.tts.auto (${String(tts.auto)}).`);
1628
+ }
1629
+ },
1630
+ {
1631
+ id: "agent.defaults-v2",
1632
+ describe: "Move agent config to agents.defaults and tools",
1633
+ apply: (raw, changes) => {
1634
+ const agent = getRecord(raw.agent);
1635
+ if (!agent) return;
1636
+ const agents = ensureRecord(raw, "agents");
1637
+ const defaults = getRecord(agents.defaults) ?? {};
1638
+ const tools = ensureRecord(raw, "tools");
1639
+ const agentTools = getRecord(agent.tools);
1640
+ if (agentTools) {
1641
+ if (tools.allow === void 0 && agentTools.allow !== void 0) {
1642
+ tools.allow = agentTools.allow;
1643
+ changes.push("Moved agent.tools.allow → tools.allow.");
1644
+ }
1645
+ if (tools.deny === void 0 && agentTools.deny !== void 0) {
1646
+ tools.deny = agentTools.deny;
1647
+ changes.push("Moved agent.tools.deny → tools.deny.");
1648
+ }
1649
+ }
1650
+ const elevated = getRecord(agent.elevated);
1651
+ if (elevated) if (tools.elevated === void 0) {
1652
+ tools.elevated = elevated;
1653
+ changes.push("Moved agent.elevated → tools.elevated.");
1654
+ } else changes.push("Removed agent.elevated (tools.elevated already set).");
1655
+ const bash = getRecord(agent.bash);
1656
+ if (bash) if (tools.exec === void 0) {
1657
+ tools.exec = bash;
1658
+ changes.push("Moved agent.bash → tools.exec.");
1659
+ } else changes.push("Removed agent.bash (tools.exec already set).");
1660
+ const sandbox = getRecord(agent.sandbox);
1661
+ if (sandbox) {
1662
+ const sandboxTools = getRecord(sandbox.tools);
1663
+ if (sandboxTools) {
1664
+ mergeMissing(ensureRecord(ensureRecord(tools, "sandbox"), "tools"), sandboxTools);
1665
+ delete sandbox.tools;
1666
+ changes.push("Moved agent.sandbox.tools → tools.sandbox.tools.");
1667
+ }
1668
+ }
1669
+ const subagents = getRecord(agent.subagents);
1670
+ if (subagents) {
1671
+ const subagentTools = getRecord(subagents.tools);
1672
+ if (subagentTools) {
1673
+ mergeMissing(ensureRecord(ensureRecord(tools, "subagents"), "tools"), subagentTools);
1674
+ delete subagents.tools;
1675
+ changes.push("Moved agent.subagents.tools → tools.subagents.tools.");
1676
+ }
1677
+ }
1678
+ const agentCopy = structuredClone(agent);
1679
+ delete agentCopy.tools;
1680
+ delete agentCopy.elevated;
1681
+ delete agentCopy.bash;
1682
+ if (isRecord(agentCopy.sandbox)) delete agentCopy.sandbox.tools;
1683
+ if (isRecord(agentCopy.subagents)) delete agentCopy.subagents.tools;
1684
+ mergeMissing(defaults, agentCopy);
1685
+ agents.defaults = defaults;
1686
+ raw.agents = agents;
1687
+ delete raw.agent;
1688
+ changes.push("Moved agent → agents.defaults.");
1689
+ }
1690
+ },
1691
+ {
1692
+ id: "identity->agents.list",
1693
+ describe: "Move identity to agents.list[].identity",
1694
+ apply: (raw, changes) => {
1695
+ const identity = getRecord(raw.identity);
1696
+ if (!identity) return;
1697
+ const agents = ensureRecord(raw, "agents");
1698
+ const list = getAgentsList(agents);
1699
+ const defaultId = resolveDefaultAgentIdFromRaw(raw);
1700
+ const entry = ensureAgentEntry(list, defaultId);
1701
+ if (entry.identity === void 0) {
1702
+ entry.identity = identity;
1703
+ changes.push(`Moved identity → agents.list (id "${defaultId}").identity.`);
1704
+ } else changes.push("Removed identity (agents.list identity already set).");
1705
+ agents.list = list;
1706
+ raw.agents = agents;
1707
+ delete raw.identity;
1708
+ }
1709
+ }
1710
+ ];
1711
+
1712
+ //#endregion
1713
+ //#region src/config/legacy.migrations.ts
1714
+ const LEGACY_CONFIG_MIGRATIONS = [
1715
+ ...LEGACY_CONFIG_MIGRATIONS_PART_1,
1716
+ ...LEGACY_CONFIG_MIGRATIONS_PART_2,
1717
+ ...LEGACY_CONFIG_MIGRATIONS_PART_3
1718
+ ];
1719
+
1720
+ //#endregion
1721
+ //#region src/config/legacy.rules.ts
1722
+ const LEGACY_CONFIG_RULES = [
1723
+ {
1724
+ path: ["whatsapp"],
1725
+ message: "whatsapp config moved to channels.whatsapp (auto-migrated on load)."
1726
+ },
1727
+ {
1728
+ path: ["telegram"],
1729
+ message: "telegram config moved to channels.telegram (auto-migrated on load)."
1730
+ },
1731
+ {
1732
+ path: ["discord"],
1733
+ message: "discord config moved to channels.discord (auto-migrated on load)."
1734
+ },
1735
+ {
1736
+ path: ["slack"],
1737
+ message: "slack config moved to channels.slack (auto-migrated on load)."
1738
+ },
1739
+ {
1740
+ path: ["signal"],
1741
+ message: "signal config moved to channels.signal (auto-migrated on load)."
1742
+ },
1743
+ {
1744
+ path: ["imessage"],
1745
+ message: "imessage config moved to channels.imessage (auto-migrated on load)."
1746
+ },
1747
+ {
1748
+ path: ["msteams"],
1749
+ message: "msteams config moved to channels.msteams (auto-migrated on load)."
1750
+ },
1751
+ {
1752
+ path: ["routing", "allowFrom"],
1753
+ message: "routing.allowFrom was removed; use channels.whatsapp.allowFrom instead (auto-migrated on load)."
1754
+ },
1755
+ {
1756
+ path: ["routing", "bindings"],
1757
+ message: "routing.bindings was moved; use top-level bindings instead (auto-migrated on load)."
1758
+ },
1759
+ {
1760
+ path: ["routing", "agents"],
1761
+ message: "routing.agents was moved; use agents.list instead (auto-migrated on load)."
1762
+ },
1763
+ {
1764
+ path: ["routing", "defaultAgentId"],
1765
+ message: "routing.defaultAgentId was moved; use agents.list[].default instead (auto-migrated on load)."
1766
+ },
1767
+ {
1768
+ path: ["routing", "agentToAgent"],
1769
+ message: "routing.agentToAgent was moved; use tools.agentToAgent instead (auto-migrated on load)."
1770
+ },
1771
+ {
1772
+ path: [
1773
+ "routing",
1774
+ "groupChat",
1775
+ "requireMention"
1776
+ ],
1777
+ message: "routing.groupChat.requireMention was removed; use channels.whatsapp/telegram/imessage groups defaults (e.g. channels.whatsapp.groups.\"*\".requireMention) instead (auto-migrated on load)."
1778
+ },
1779
+ {
1780
+ path: [
1781
+ "routing",
1782
+ "groupChat",
1783
+ "mentionPatterns"
1784
+ ],
1785
+ message: "routing.groupChat.mentionPatterns was moved; use agents.list[].groupChat.mentionPatterns or messages.groupChat.mentionPatterns instead (auto-migrated on load)."
1786
+ },
1787
+ {
1788
+ path: ["routing", "queue"],
1789
+ message: "routing.queue was moved; use messages.queue instead (auto-migrated on load)."
1790
+ },
1791
+ {
1792
+ path: ["routing", "transcribeAudio"],
1793
+ message: "routing.transcribeAudio was moved; use tools.media.audio.models instead (auto-migrated on load)."
1794
+ },
1795
+ {
1796
+ path: ["telegram", "requireMention"],
1797
+ message: "telegram.requireMention was removed; use channels.telegram.groups.\"*\".requireMention instead (auto-migrated on load)."
1798
+ },
1799
+ {
1800
+ path: ["identity"],
1801
+ message: "identity was moved; use agents.list[].identity instead (auto-migrated on load)."
1802
+ },
1803
+ {
1804
+ path: ["agent"],
1805
+ message: "agent.* was moved; use agents.defaults (and tools.* for tool/elevated/exec settings) instead (auto-migrated on load)."
1806
+ },
1807
+ {
1808
+ path: ["tools", "bash"],
1809
+ message: "tools.bash was removed; use tools.exec instead (auto-migrated on load)."
1810
+ },
1811
+ {
1812
+ path: ["agent", "model"],
1813
+ message: "agent.model string was replaced by agents.defaults.model.primary/fallbacks and agents.defaults.models (auto-migrated on load).",
1814
+ match: (value) => typeof value === "string"
1815
+ },
1816
+ {
1817
+ path: ["agent", "imageModel"],
1818
+ message: "agent.imageModel string was replaced by agents.defaults.imageModel.primary/fallbacks (auto-migrated on load).",
1819
+ match: (value) => typeof value === "string"
1820
+ },
1821
+ {
1822
+ path: ["agent", "allowedModels"],
1823
+ message: "agent.allowedModels was replaced by agents.defaults.models (auto-migrated on load)."
1824
+ },
1825
+ {
1826
+ path: ["agent", "modelAliases"],
1827
+ message: "agent.modelAliases was replaced by agents.defaults.models.*.alias (auto-migrated on load)."
1828
+ },
1829
+ {
1830
+ path: ["agent", "modelFallbacks"],
1831
+ message: "agent.modelFallbacks was replaced by agents.defaults.model.fallbacks (auto-migrated on load)."
1832
+ },
1833
+ {
1834
+ path: ["agent", "imageModelFallbacks"],
1835
+ message: "agent.imageModelFallbacks was replaced by agents.defaults.imageModel.fallbacks (auto-migrated on load)."
1836
+ },
1837
+ {
1838
+ path: [
1839
+ "messages",
1840
+ "tts",
1841
+ "enabled"
1842
+ ],
1843
+ message: "messages.tts.enabled was replaced by messages.tts.auto (auto-migrated on load)."
1844
+ },
1845
+ {
1846
+ path: ["gateway", "token"],
1847
+ message: "gateway.token is ignored; use gateway.auth.token instead (auto-migrated on load)."
1848
+ }
1849
+ ];
1850
+
1851
+ //#endregion
1852
+ //#region src/config/legacy.ts
1853
+ function findLegacyConfigIssues(raw) {
1854
+ if (!raw || typeof raw !== "object") return [];
1855
+ const root = raw;
1856
+ const issues = [];
1857
+ for (const rule of LEGACY_CONFIG_RULES) {
1858
+ let cursor = root;
1859
+ for (const key of rule.path) {
1860
+ if (!cursor || typeof cursor !== "object") {
1861
+ cursor = void 0;
1862
+ break;
1863
+ }
1864
+ cursor = cursor[key];
1865
+ }
1866
+ if (cursor !== void 0 && (!rule.match || rule.match(cursor, root))) issues.push({
1867
+ path: rule.path.join("."),
1868
+ message: rule.message
1869
+ });
1870
+ }
1871
+ return issues;
1872
+ }
1873
+ function applyLegacyMigrations(raw) {
1874
+ if (!raw || typeof raw !== "object") return {
1875
+ next: null,
1876
+ changes: []
1877
+ };
1878
+ const next = structuredClone(raw);
1879
+ const changes = [];
1880
+ for (const migration of LEGACY_CONFIG_MIGRATIONS) migration.apply(next, changes);
1881
+ if (changes.length === 0) return {
1882
+ next: null,
1883
+ changes: []
1884
+ };
1885
+ return {
1886
+ next,
1887
+ changes
1888
+ };
1889
+ }
1890
+
1891
+ //#endregion
1892
+ //#region src/config/merge-patch.ts
1893
+ function isObjectWithStringId(value) {
1894
+ if (!isPlainObject$2(value)) return false;
1895
+ return typeof value.id === "string" && value.id.length > 0;
1896
+ }
1897
+ /**
1898
+ * Merge arrays of object-like entries keyed by `id`.
1899
+ *
1900
+ * Contract:
1901
+ * - Base array must be fully id-keyed; otherwise return undefined (caller should replace).
1902
+ * - Patch entries with valid id merge by id (or append when the id is new).
1903
+ * - Patch entries without valid id append as-is, avoiding destructive full-array replacement.
1904
+ */
1905
+ function mergeObjectArraysById(base, patch, options) {
1906
+ if (!base.every(isObjectWithStringId)) return;
1907
+ const merged = [...base];
1908
+ const indexById = /* @__PURE__ */ new Map();
1909
+ for (const [index, entry] of merged.entries()) {
1910
+ if (!isObjectWithStringId(entry)) return;
1911
+ indexById.set(entry.id, index);
1912
+ }
1913
+ for (const patchEntry of patch) {
1914
+ if (!isObjectWithStringId(patchEntry)) {
1915
+ merged.push(structuredClone(patchEntry));
1916
+ continue;
1917
+ }
1918
+ const existingIndex = indexById.get(patchEntry.id);
1919
+ if (existingIndex === void 0) {
1920
+ merged.push(structuredClone(patchEntry));
1921
+ indexById.set(patchEntry.id, merged.length - 1);
1922
+ continue;
1923
+ }
1924
+ merged[existingIndex] = applyMergePatch(merged[existingIndex], patchEntry, options);
1925
+ }
1926
+ return merged;
1927
+ }
1928
+ function applyMergePatch(base, patch, options = {}) {
1929
+ if (!isPlainObject$2(patch)) return patch;
1930
+ const result = isPlainObject$2(base) ? { ...base } : {};
1931
+ for (const [key, value] of Object.entries(patch)) {
1932
+ if (isBlockedObjectKey(key)) continue;
1933
+ if (value === null) {
1934
+ delete result[key];
1935
+ continue;
1936
+ }
1937
+ if (options.mergeObjectArraysById && Array.isArray(result[key]) && Array.isArray(value)) {
1938
+ const mergedArray = mergeObjectArraysById(result[key], value, options);
1939
+ if (mergedArray) {
1940
+ result[key] = mergedArray;
1941
+ continue;
1942
+ }
1943
+ }
1944
+ if (isPlainObject$2(value)) {
1945
+ const baseValue = result[key];
1946
+ result[key] = applyMergePatch(isPlainObject$2(baseValue) ? baseValue : {}, value, options);
1947
+ continue;
1948
+ }
1949
+ result[key] = value;
1950
+ }
1951
+ return result;
1952
+ }
1953
+
1954
+ //#endregion
1955
+ //#region src/config/normalize-paths.ts
1956
+ const PATH_VALUE_RE = /^~(?=$|[\\/])/;
1957
+ const PATH_KEY_RE = /(dir|path|paths|file|root|workspace)$/i;
1958
+ const PATH_LIST_KEYS = new Set(["paths", "pathPrepend"]);
1959
+ function normalizeStringValue(key, value) {
1960
+ if (!PATH_VALUE_RE.test(value.trim())) return value;
1961
+ if (!key) return value;
1962
+ if (PATH_KEY_RE.test(key) || PATH_LIST_KEYS.has(key)) return resolveUserPath(value);
1963
+ return value;
1964
+ }
1965
+ function normalizeAny(key, value) {
1966
+ if (typeof value === "string") return normalizeStringValue(key, value);
1967
+ if (Array.isArray(value)) {
1968
+ const normalizeChildren = Boolean(key && PATH_LIST_KEYS.has(key));
1969
+ return value.map((entry) => {
1970
+ if (typeof entry === "string") return normalizeChildren ? normalizeStringValue(key, entry) : entry;
1971
+ if (Array.isArray(entry)) return normalizeAny(void 0, entry);
1972
+ if (isPlainObject$2(entry)) return normalizeAny(void 0, entry);
1973
+ return entry;
1974
+ });
1975
+ }
1976
+ if (!isPlainObject$2(value)) return value;
1977
+ for (const [childKey, childValue] of Object.entries(value)) {
1978
+ const next = normalizeAny(childKey, childValue);
1979
+ if (next !== childValue) value[childKey] = next;
1980
+ }
1981
+ return value;
1982
+ }
1983
+ /**
1984
+ * Normalize "~" paths in path-ish config fields.
1985
+ *
1986
+ * Goal: accept `~/...` consistently across config file + env overrides, while
1987
+ * keeping the surface area small and predictable.
1988
+ */
1989
+ function normalizeConfigPaths(cfg) {
1990
+ if (!cfg || typeof cfg !== "object") return cfg;
1991
+ normalizeAny(void 0, cfg);
1992
+ return cfg;
1993
+ }
1994
+
1995
+ //#endregion
1996
+ //#region src/config/config-paths.ts
1997
+ function parseConfigPath(raw) {
1998
+ const trimmed = raw.trim();
1999
+ if (!trimmed) return {
2000
+ ok: false,
2001
+ error: "Invalid path. Use dot notation (e.g. foo.bar)."
2002
+ };
2003
+ const parts = trimmed.split(".").map((part) => part.trim());
2004
+ if (parts.some((part) => !part)) return {
2005
+ ok: false,
2006
+ error: "Invalid path. Use dot notation (e.g. foo.bar)."
2007
+ };
2008
+ if (parts.some((part) => isBlockedObjectKey(part))) return {
2009
+ ok: false,
2010
+ error: "Invalid path segment."
2011
+ };
2012
+ return {
2013
+ ok: true,
2014
+ path: parts
2015
+ };
2016
+ }
2017
+ function setConfigValueAtPath(root, path, value) {
2018
+ let cursor = root;
2019
+ for (let idx = 0; idx < path.length - 1; idx += 1) {
2020
+ const key = path[idx];
2021
+ const next = cursor[key];
2022
+ if (!isPlainObject$2(next)) cursor[key] = {};
2023
+ cursor = cursor[key];
2024
+ }
2025
+ cursor[path[path.length - 1]] = value;
2026
+ }
2027
+ function unsetConfigValueAtPath(root, path) {
2028
+ const stack = [];
2029
+ let cursor = root;
2030
+ for (let idx = 0; idx < path.length - 1; idx += 1) {
2031
+ const key = path[idx];
2032
+ const next = cursor[key];
2033
+ if (!isPlainObject$2(next)) return false;
2034
+ stack.push({
2035
+ node: cursor,
2036
+ key
2037
+ });
2038
+ cursor = next;
2039
+ }
2040
+ const leafKey = path[path.length - 1];
2041
+ if (!(leafKey in cursor)) return false;
2042
+ delete cursor[leafKey];
2043
+ for (let idx = stack.length - 1; idx >= 0; idx -= 1) {
2044
+ const { node, key } = stack[idx];
2045
+ const child = node[key];
2046
+ if (isPlainObject$2(child) && Object.keys(child).length === 0) delete node[key];
2047
+ else break;
2048
+ }
2049
+ return true;
2050
+ }
2051
+ function getConfigValueAtPath(root, path) {
2052
+ let cursor = root;
2053
+ for (const key of path) {
2054
+ if (!isPlainObject$2(cursor)) return;
2055
+ cursor = cursor[key];
2056
+ }
2057
+ return cursor;
2058
+ }
2059
+
2060
+ //#endregion
2061
+ //#region src/config/runtime-overrides.ts
2062
+ let overrides = {};
2063
+ function sanitizeOverrideValue(value, seen = /* @__PURE__ */ new WeakSet()) {
2064
+ if (Array.isArray(value)) return value.map((entry) => sanitizeOverrideValue(entry, seen));
2065
+ if (!isPlainObject$2(value)) return value;
2066
+ if (seen.has(value)) return {};
2067
+ seen.add(value);
2068
+ const sanitized = {};
2069
+ for (const [key, entry] of Object.entries(value)) {
2070
+ if (entry === void 0 || isBlockedObjectKey(key)) continue;
2071
+ sanitized[key] = sanitizeOverrideValue(entry, seen);
2072
+ }
2073
+ seen.delete(value);
2074
+ return sanitized;
2075
+ }
2076
+ function mergeOverrides(base, override) {
2077
+ if (!isPlainObject$2(base) || !isPlainObject$2(override)) return override;
2078
+ const next = { ...base };
2079
+ for (const [key, value] of Object.entries(override)) {
2080
+ if (value === void 0 || isBlockedObjectKey(key)) continue;
2081
+ next[key] = mergeOverrides(base[key], value);
2082
+ }
2083
+ return next;
2084
+ }
2085
+ function getConfigOverrides() {
2086
+ return overrides;
2087
+ }
2088
+ function resetConfigOverrides() {
2089
+ overrides = {};
2090
+ }
2091
+ function setConfigOverride(pathRaw, value) {
2092
+ const parsed = parseConfigPath(pathRaw);
2093
+ if (!parsed.ok || !parsed.path) return {
2094
+ ok: false,
2095
+ error: parsed.error ?? "Invalid path."
2096
+ };
2097
+ setConfigValueAtPath(overrides, parsed.path, sanitizeOverrideValue(value));
2098
+ return { ok: true };
2099
+ }
2100
+ function unsetConfigOverride(pathRaw) {
2101
+ const parsed = parseConfigPath(pathRaw);
2102
+ if (!parsed.ok || !parsed.path) return {
2103
+ ok: false,
2104
+ removed: false,
2105
+ error: parsed.error ?? "Invalid path."
2106
+ };
2107
+ return {
2108
+ ok: true,
2109
+ removed: unsetConfigValueAtPath(overrides, parsed.path)
2110
+ };
2111
+ }
2112
+ function applyConfigOverrides(cfg) {
2113
+ if (!overrides || Object.keys(overrides).length === 0) return cfg;
2114
+ return mergeOverrides(cfg, overrides);
2115
+ }
2116
+
2117
+ //#endregion
2118
+ //#region src/plugins/config-state.ts
2119
+ const BUNDLED_ENABLED_BY_DEFAULT = new Set([
2120
+ "device-pair",
2121
+ "phone-control",
2122
+ "talk-voice"
2123
+ ]);
2124
+ const normalizeList = (value) => {
2125
+ if (!Array.isArray(value)) return [];
2126
+ return value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter(Boolean);
2127
+ };
2128
+ const normalizePluginEntries = (entries) => {
2129
+ if (!entries || typeof entries !== "object" || Array.isArray(entries)) return {};
2130
+ const normalized = {};
2131
+ for (const [key, value] of Object.entries(entries)) {
2132
+ if (!key.trim()) continue;
2133
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
2134
+ normalized[key] = {};
2135
+ continue;
2136
+ }
2137
+ const entry = value;
2138
+ normalized[key] = {
2139
+ enabled: typeof entry.enabled === "boolean" ? entry.enabled : void 0,
2140
+ config: "config" in entry ? entry.config : void 0
2141
+ };
2142
+ }
2143
+ return normalized;
2144
+ };
2145
+ const normalizePluginsConfig = (config) => {
2146
+ return {
2147
+ enabled: config?.enabled !== false,
2148
+ allow: normalizeList(config?.allow),
2149
+ deny: normalizeList(config?.deny),
2150
+ loadPaths: normalizeList(config?.load?.paths),
2151
+ slots: {},
2152
+ entries: normalizePluginEntries(config?.entries)
2153
+ };
2154
+ };
2155
+ const hasExplicitPluginConfig = (plugins) => {
2156
+ if (!plugins) return false;
2157
+ if (typeof plugins.enabled === "boolean") return true;
2158
+ if (Array.isArray(plugins.allow) && plugins.allow.length > 0) return true;
2159
+ if (Array.isArray(plugins.deny) && plugins.deny.length > 0) return true;
2160
+ if (plugins.load?.paths && Array.isArray(plugins.load.paths) && plugins.load.paths.length > 0) return true;
2161
+ if (plugins.slots && Object.keys(plugins.slots).length > 0) return true;
2162
+ if (plugins.entries && Object.keys(plugins.entries).length > 0) return true;
2163
+ return false;
2164
+ };
2165
+ function applyTestPluginDefaults(cfg, env = process.env) {
2166
+ if (!env.VITEST) return cfg;
2167
+ const plugins = cfg.plugins;
2168
+ if (hasExplicitPluginConfig(plugins)) return cfg;
2169
+ return {
2170
+ ...cfg,
2171
+ plugins: {
2172
+ ...plugins,
2173
+ enabled: false
2174
+ }
2175
+ };
2176
+ }
2177
+ function resolveEnableState(id, origin, config) {
2178
+ if (!config.enabled) return {
2179
+ enabled: false,
2180
+ reason: "plugins disabled"
2181
+ };
2182
+ if (config.deny.includes(id)) return {
2183
+ enabled: false,
2184
+ reason: "blocked by denylist"
2185
+ };
2186
+ if (config.allow.length > 0 && !config.allow.includes(id)) return {
2187
+ enabled: false,
2188
+ reason: "not in allowlist"
2189
+ };
2190
+ const entry = config.entries[id];
2191
+ if (entry?.enabled === true) return { enabled: true };
2192
+ if (entry?.enabled === false) return {
2193
+ enabled: false,
2194
+ reason: "disabled in config"
2195
+ };
2196
+ if (origin === "bundled" && BUNDLED_ENABLED_BY_DEFAULT.has(id)) return { enabled: true };
2197
+ if (origin === "bundled") return {
2198
+ enabled: false,
2199
+ reason: "bundled (disabled by default)"
2200
+ };
2201
+ return { enabled: true };
2202
+ }
2203
+ function isBundledChannelEnabledByChannelConfig(cfg, pluginId) {
2204
+ if (!cfg) return false;
2205
+ const channelId = normalizeChatChannelId(pluginId);
2206
+ if (!channelId) return false;
2207
+ const entry = cfg.channels?.[channelId];
2208
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) return false;
2209
+ return entry.enabled === true;
2210
+ }
2211
+ function resolveEffectiveEnableState(params) {
2212
+ const base = resolveEnableState(params.id, params.origin, params.config);
2213
+ if (!base.enabled && base.reason === "bundled (disabled by default)" && isBundledChannelEnabledByChannelConfig(params.rootConfig, params.id)) return { enabled: true };
2214
+ return base;
2215
+ }
2216
+
2217
+ //#endregion
2218
+ //#region src/plugins/bundled-dir.ts
2219
+ function resolveBundledPluginsDir() {
2220
+ const override = process.env.REMOTECLAW_BUNDLED_PLUGINS_DIR?.trim();
2221
+ if (override) return override;
2222
+ try {
2223
+ const execDir = path.dirname(process.execPath);
2224
+ const sibling = path.join(execDir, "extensions");
2225
+ if (fs.existsSync(sibling)) return sibling;
2226
+ } catch {}
2227
+ try {
2228
+ let cursor = path.dirname(fileURLToPath(import.meta.url));
2229
+ for (let i = 0; i < 6; i += 1) {
2230
+ const candidate = path.join(cursor, "extensions");
2231
+ if (fs.existsSync(candidate)) return candidate;
2232
+ const parent = path.dirname(cursor);
2233
+ if (parent === cursor) break;
2234
+ cursor = parent;
2235
+ }
2236
+ } catch {}
2237
+ }
2238
+
2239
+ //#endregion
2240
+ //#region src/compat/legacy-names.ts
2241
+ const PROJECT_NAME = "remoteclaw";
2242
+ const LEGACY_PROJECT_NAMES = [];
2243
+ const MANIFEST_KEY = PROJECT_NAME;
2244
+ const LEGACY_MANIFEST_KEYS = LEGACY_PROJECT_NAMES;
2245
+ const LEGACY_PLUGIN_MANIFEST_FILENAMES = [];
2246
+
2247
+ //#endregion
2248
+ //#region src/plugins/manifest.ts
2249
+ const PLUGIN_MANIFEST_FILENAME = "remoteclaw.plugin.json";
2250
+ const PLUGIN_MANIFEST_FILENAMES = [PLUGIN_MANIFEST_FILENAME, ...LEGACY_PLUGIN_MANIFEST_FILENAMES];
2251
+ function normalizeStringList(value) {
2252
+ if (!Array.isArray(value)) return [];
2253
+ return value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter(Boolean);
2254
+ }
2255
+ function resolvePluginManifestPath(rootDir) {
2256
+ for (const filename of PLUGIN_MANIFEST_FILENAMES) {
2257
+ const candidate = path.join(rootDir, filename);
2258
+ if (fs.existsSync(candidate)) return candidate;
2259
+ }
2260
+ return path.join(rootDir, PLUGIN_MANIFEST_FILENAME);
2261
+ }
2262
+ function loadPluginManifest(rootDir) {
2263
+ const manifestPath = resolvePluginManifestPath(rootDir);
2264
+ if (!fs.existsSync(manifestPath)) return {
2265
+ ok: false,
2266
+ error: `plugin manifest not found: ${manifestPath}`,
2267
+ manifestPath
2268
+ };
2269
+ let raw;
2270
+ try {
2271
+ raw = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
2272
+ } catch (err) {
2273
+ return {
2274
+ ok: false,
2275
+ error: `failed to parse plugin manifest: ${String(err)}`,
2276
+ manifestPath
2277
+ };
2278
+ }
2279
+ if (!isRecord(raw)) return {
2280
+ ok: false,
2281
+ error: "plugin manifest must be an object",
2282
+ manifestPath
2283
+ };
2284
+ const id = typeof raw.id === "string" ? raw.id.trim() : "";
2285
+ if (!id) return {
2286
+ ok: false,
2287
+ error: "plugin manifest requires id",
2288
+ manifestPath
2289
+ };
2290
+ const configSchema = isRecord(raw.configSchema) ? raw.configSchema : null;
2291
+ if (!configSchema) return {
2292
+ ok: false,
2293
+ error: "plugin manifest requires configSchema",
2294
+ manifestPath
2295
+ };
2296
+ const kind = typeof raw.kind === "string" ? raw.kind : void 0;
2297
+ const name = typeof raw.name === "string" ? raw.name.trim() : void 0;
2298
+ const description = typeof raw.description === "string" ? raw.description.trim() : void 0;
2299
+ const version = typeof raw.version === "string" ? raw.version.trim() : void 0;
2300
+ const channels = normalizeStringList(raw.channels);
2301
+ const providers = normalizeStringList(raw.providers);
2302
+ const skills = normalizeStringList(raw.skills);
2303
+ let uiHints;
2304
+ if (isRecord(raw.uiHints)) uiHints = raw.uiHints;
2305
+ return {
2306
+ ok: true,
2307
+ manifest: {
2308
+ id,
2309
+ configSchema,
2310
+ kind,
2311
+ channels,
2312
+ providers,
2313
+ skills,
2314
+ name,
2315
+ description,
2316
+ version,
2317
+ uiHints
2318
+ },
2319
+ manifestPath
2320
+ };
2321
+ }
2322
+ function getPackageManifestMetadata(manifest) {
2323
+ if (!manifest) return;
2324
+ const current = manifest[MANIFEST_KEY];
2325
+ if (current) return current;
2326
+ for (const key of LEGACY_MANIFEST_KEYS) {
2327
+ const legacy = manifest[key];
2328
+ if (legacy) return legacy;
2329
+ }
2330
+ }
2331
+
2332
+ //#endregion
2333
+ //#region src/plugins/path-safety.ts
2334
+ function isPathInside(baseDir, targetPath) {
2335
+ const rel = path.relative(baseDir, targetPath);
2336
+ if (!rel) return true;
2337
+ return !rel.startsWith("..") && !path.isAbsolute(rel);
2338
+ }
2339
+ function safeRealpathSync(targetPath, cache) {
2340
+ const cached = cache?.get(targetPath);
2341
+ if (cached) return cached;
2342
+ try {
2343
+ const resolved = fs.realpathSync(targetPath);
2344
+ cache?.set(targetPath, resolved);
2345
+ return resolved;
2346
+ } catch {
2347
+ return null;
2348
+ }
2349
+ }
2350
+ function safeStatSync(targetPath) {
2351
+ try {
2352
+ return fs.statSync(targetPath);
2353
+ } catch {
2354
+ return null;
2355
+ }
2356
+ }
2357
+ function formatPosixMode(mode) {
2358
+ return (mode & 511).toString(8).padStart(3, "0");
2359
+ }
2360
+
2361
+ //#endregion
2362
+ //#region src/plugins/discovery.ts
2363
+ const EXTENSION_EXTS = new Set([
2364
+ ".ts",
2365
+ ".js",
2366
+ ".mts",
2367
+ ".cts",
2368
+ ".mjs",
2369
+ ".cjs"
2370
+ ]);
2371
+ function currentUid(overrideUid) {
2372
+ if (overrideUid !== void 0) return overrideUid;
2373
+ if (process.platform === "win32") return null;
2374
+ if (typeof process.getuid !== "function") return null;
2375
+ return process.getuid();
2376
+ }
2377
+ function checkSourceEscapesRoot(params) {
2378
+ const sourceRealPath = safeRealpathSync(params.source);
2379
+ const rootRealPath = safeRealpathSync(params.rootDir);
2380
+ if (!sourceRealPath || !rootRealPath) return null;
2381
+ if (isPathInside(rootRealPath, sourceRealPath)) return null;
2382
+ return {
2383
+ reason: "source_escapes_root",
2384
+ sourcePath: params.source,
2385
+ rootPath: params.rootDir,
2386
+ targetPath: params.source,
2387
+ sourceRealPath,
2388
+ rootRealPath
2389
+ };
2390
+ }
2391
+ function checkPathStatAndPermissions(params) {
2392
+ if (process.platform === "win32") return null;
2393
+ const pathsToCheck = [params.rootDir, params.source];
2394
+ const seen = /* @__PURE__ */ new Set();
2395
+ for (const targetPath of pathsToCheck) {
2396
+ const normalized = path.resolve(targetPath);
2397
+ if (seen.has(normalized)) continue;
2398
+ seen.add(normalized);
2399
+ const stat = safeStatSync(targetPath);
2400
+ if (!stat) return {
2401
+ reason: "path_stat_failed",
2402
+ sourcePath: params.source,
2403
+ rootPath: params.rootDir,
2404
+ targetPath
2405
+ };
2406
+ const modeBits = stat.mode & 511;
2407
+ if ((modeBits & 2) !== 0) return {
2408
+ reason: "path_world_writable",
2409
+ sourcePath: params.source,
2410
+ rootPath: params.rootDir,
2411
+ targetPath,
2412
+ modeBits
2413
+ };
2414
+ if (params.origin !== "bundled" && params.uid !== null && typeof stat.uid === "number" && stat.uid !== params.uid && stat.uid !== 0) return {
2415
+ reason: "path_suspicious_ownership",
2416
+ sourcePath: params.source,
2417
+ rootPath: params.rootDir,
2418
+ targetPath,
2419
+ foundUid: stat.uid,
2420
+ expectedUid: params.uid
2421
+ };
2422
+ }
2423
+ return null;
2424
+ }
2425
+ function findCandidateBlockIssue(params) {
2426
+ const escaped = checkSourceEscapesRoot({
2427
+ source: params.source,
2428
+ rootDir: params.rootDir
2429
+ });
2430
+ if (escaped) return escaped;
2431
+ return checkPathStatAndPermissions({
2432
+ source: params.source,
2433
+ rootDir: params.rootDir,
2434
+ origin: params.origin,
2435
+ uid: currentUid(params.ownershipUid)
2436
+ });
2437
+ }
2438
+ function formatCandidateBlockMessage(issue) {
2439
+ if (issue.reason === "source_escapes_root") return `blocked plugin candidate: source escapes plugin root (${issue.sourcePath} -> ${issue.sourceRealPath}; root=${issue.rootRealPath})`;
2440
+ if (issue.reason === "path_stat_failed") return `blocked plugin candidate: cannot stat path (${issue.targetPath})`;
2441
+ if (issue.reason === "path_world_writable") return `blocked plugin candidate: world-writable path (${issue.targetPath}, mode=${formatPosixMode(issue.modeBits ?? 0)})`;
2442
+ return `blocked plugin candidate: suspicious ownership (${issue.targetPath}, uid=${issue.foundUid}, expected uid=${issue.expectedUid} or root)`;
2443
+ }
2444
+ function isUnsafePluginCandidate(params) {
2445
+ const issue = findCandidateBlockIssue({
2446
+ source: params.source,
2447
+ rootDir: params.rootDir,
2448
+ origin: params.origin,
2449
+ ownershipUid: params.ownershipUid
2450
+ });
2451
+ if (!issue) return false;
2452
+ params.diagnostics.push({
2453
+ level: "warn",
2454
+ source: issue.targetPath,
2455
+ message: formatCandidateBlockMessage(issue)
2456
+ });
2457
+ return true;
2458
+ }
2459
+ function isExtensionFile(filePath) {
2460
+ const ext = path.extname(filePath);
2461
+ if (!EXTENSION_EXTS.has(ext)) return false;
2462
+ return !filePath.endsWith(".d.ts");
2463
+ }
2464
+ function shouldIgnoreScannedDirectory(dirName) {
2465
+ const normalized = dirName.trim().toLowerCase();
2466
+ if (!normalized) return true;
2467
+ if (normalized.endsWith(".bak")) return true;
2468
+ if (normalized.includes(".backup-")) return true;
2469
+ if (normalized.includes(".disabled")) return true;
2470
+ return false;
2471
+ }
2472
+ function readPackageManifest(dir) {
2473
+ const manifestPath = path.join(dir, "package.json");
2474
+ if (!fs.existsSync(manifestPath)) return null;
2475
+ try {
2476
+ const raw = fs.readFileSync(manifestPath, "utf-8");
2477
+ return JSON.parse(raw);
2478
+ } catch {
2479
+ return null;
2480
+ }
2481
+ }
2482
+ function resolvePackageExtensions(manifest) {
2483
+ const raw = getPackageManifestMetadata(manifest)?.extensions;
2484
+ if (!Array.isArray(raw)) return [];
2485
+ return raw.map((entry) => typeof entry === "string" ? entry.trim() : "").filter(Boolean);
2486
+ }
2487
+ function deriveIdHint(params) {
2488
+ const base = path.basename(params.filePath, path.extname(params.filePath));
2489
+ const rawPackageName = params.packageName?.trim();
2490
+ if (!rawPackageName) return base;
2491
+ const unscoped = rawPackageName.includes("/") ? rawPackageName.split("/").pop() ?? rawPackageName : rawPackageName;
2492
+ if (!params.hasMultipleExtensions) return unscoped;
2493
+ return `${unscoped}/${base}`;
2494
+ }
2495
+ function addCandidate(params) {
2496
+ const resolved = path.resolve(params.source);
2497
+ if (params.seen.has(resolved)) return;
2498
+ const resolvedRoot = path.resolve(params.rootDir);
2499
+ if (isUnsafePluginCandidate({
2500
+ source: resolved,
2501
+ rootDir: resolvedRoot,
2502
+ origin: params.origin,
2503
+ diagnostics: params.diagnostics,
2504
+ ownershipUid: params.ownershipUid
2505
+ })) return;
2506
+ params.seen.add(resolved);
2507
+ const manifest = params.manifest ?? null;
2508
+ params.candidates.push({
2509
+ idHint: params.idHint,
2510
+ source: resolved,
2511
+ rootDir: resolvedRoot,
2512
+ origin: params.origin,
2513
+ workspaceDir: params.workspaceDir,
2514
+ packageName: manifest?.name?.trim() || void 0,
2515
+ packageVersion: manifest?.version?.trim() || void 0,
2516
+ packageDescription: manifest?.description?.trim() || void 0,
2517
+ packageDir: params.packageDir,
2518
+ packageManifest: getPackageManifestMetadata(manifest ?? void 0)
2519
+ });
2520
+ }
2521
+ function resolvePackageEntrySource(params) {
2522
+ const source = path.resolve(params.packageDir, params.entryPath);
2523
+ if (!isPathInsideWithRealpath(params.packageDir, source, { requireRealpath: true })) {
2524
+ params.diagnostics.push({
2525
+ level: "error",
2526
+ message: `extension entry escapes package directory: ${params.entryPath}`,
2527
+ source: params.sourceLabel
2528
+ });
2529
+ return null;
2530
+ }
2531
+ return source;
2532
+ }
2533
+ function discoverInDirectory(params) {
2534
+ if (!fs.existsSync(params.dir)) return;
2535
+ let entries = [];
2536
+ try {
2537
+ entries = fs.readdirSync(params.dir, { withFileTypes: true });
2538
+ } catch (err) {
2539
+ params.diagnostics.push({
2540
+ level: "warn",
2541
+ message: `failed to read extensions dir: ${params.dir} (${String(err)})`,
2542
+ source: params.dir
2543
+ });
2544
+ return;
2545
+ }
2546
+ for (const entry of entries) {
2547
+ const fullPath = path.join(params.dir, entry.name);
2548
+ if (entry.isFile()) {
2549
+ if (!isExtensionFile(fullPath)) continue;
2550
+ addCandidate({
2551
+ candidates: params.candidates,
2552
+ diagnostics: params.diagnostics,
2553
+ seen: params.seen,
2554
+ idHint: path.basename(entry.name, path.extname(entry.name)),
2555
+ source: fullPath,
2556
+ rootDir: path.dirname(fullPath),
2557
+ origin: params.origin,
2558
+ ownershipUid: params.ownershipUid,
2559
+ workspaceDir: params.workspaceDir
2560
+ });
2561
+ }
2562
+ if (!entry.isDirectory()) continue;
2563
+ if (shouldIgnoreScannedDirectory(entry.name)) continue;
2564
+ const manifest = readPackageManifest(fullPath);
2565
+ const extensions = manifest ? resolvePackageExtensions(manifest) : [];
2566
+ if (extensions.length > 0) {
2567
+ for (const extPath of extensions) {
2568
+ const resolved = resolvePackageEntrySource({
2569
+ packageDir: fullPath,
2570
+ entryPath: extPath,
2571
+ sourceLabel: fullPath,
2572
+ diagnostics: params.diagnostics
2573
+ });
2574
+ if (!resolved) continue;
2575
+ addCandidate({
2576
+ candidates: params.candidates,
2577
+ diagnostics: params.diagnostics,
2578
+ seen: params.seen,
2579
+ idHint: deriveIdHint({
2580
+ filePath: resolved,
2581
+ packageName: manifest?.name,
2582
+ hasMultipleExtensions: extensions.length > 1
2583
+ }),
2584
+ source: resolved,
2585
+ rootDir: fullPath,
2586
+ origin: params.origin,
2587
+ ownershipUid: params.ownershipUid,
2588
+ workspaceDir: params.workspaceDir,
2589
+ manifest,
2590
+ packageDir: fullPath
2591
+ });
2592
+ }
2593
+ continue;
2594
+ }
2595
+ const indexFile = [
2596
+ "index.ts",
2597
+ "index.js",
2598
+ "index.mjs",
2599
+ "index.cjs"
2600
+ ].map((candidate) => path.join(fullPath, candidate)).find((candidate) => fs.existsSync(candidate));
2601
+ if (indexFile && isExtensionFile(indexFile)) addCandidate({
2602
+ candidates: params.candidates,
2603
+ diagnostics: params.diagnostics,
2604
+ seen: params.seen,
2605
+ idHint: entry.name,
2606
+ source: indexFile,
2607
+ rootDir: fullPath,
2608
+ origin: params.origin,
2609
+ ownershipUid: params.ownershipUid,
2610
+ workspaceDir: params.workspaceDir,
2611
+ manifest,
2612
+ packageDir: fullPath
2613
+ });
2614
+ }
2615
+ }
2616
+ function discoverFromPath(params) {
2617
+ const resolved = resolveUserPath(params.rawPath);
2618
+ if (!fs.existsSync(resolved)) {
2619
+ params.diagnostics.push({
2620
+ level: "error",
2621
+ message: `plugin path not found: ${resolved}`,
2622
+ source: resolved
2623
+ });
2624
+ return;
2625
+ }
2626
+ const stat = fs.statSync(resolved);
2627
+ if (stat.isFile()) {
2628
+ if (!isExtensionFile(resolved)) {
2629
+ params.diagnostics.push({
2630
+ level: "error",
2631
+ message: `plugin path is not a supported file: ${resolved}`,
2632
+ source: resolved
2633
+ });
2634
+ return;
2635
+ }
2636
+ addCandidate({
2637
+ candidates: params.candidates,
2638
+ diagnostics: params.diagnostics,
2639
+ seen: params.seen,
2640
+ idHint: path.basename(resolved, path.extname(resolved)),
2641
+ source: resolved,
2642
+ rootDir: path.dirname(resolved),
2643
+ origin: params.origin,
2644
+ ownershipUid: params.ownershipUid,
2645
+ workspaceDir: params.workspaceDir
2646
+ });
2647
+ return;
2648
+ }
2649
+ if (stat.isDirectory()) {
2650
+ const manifest = readPackageManifest(resolved);
2651
+ const extensions = manifest ? resolvePackageExtensions(manifest) : [];
2652
+ if (extensions.length > 0) {
2653
+ for (const extPath of extensions) {
2654
+ const source = resolvePackageEntrySource({
2655
+ packageDir: resolved,
2656
+ entryPath: extPath,
2657
+ sourceLabel: resolved,
2658
+ diagnostics: params.diagnostics
2659
+ });
2660
+ if (!source) continue;
2661
+ addCandidate({
2662
+ candidates: params.candidates,
2663
+ diagnostics: params.diagnostics,
2664
+ seen: params.seen,
2665
+ idHint: deriveIdHint({
2666
+ filePath: source,
2667
+ packageName: manifest?.name,
2668
+ hasMultipleExtensions: extensions.length > 1
2669
+ }),
2670
+ source,
2671
+ rootDir: resolved,
2672
+ origin: params.origin,
2673
+ ownershipUid: params.ownershipUid,
2674
+ workspaceDir: params.workspaceDir,
2675
+ manifest,
2676
+ packageDir: resolved
2677
+ });
2678
+ }
2679
+ return;
2680
+ }
2681
+ const indexFile = [
2682
+ "index.ts",
2683
+ "index.js",
2684
+ "index.mjs",
2685
+ "index.cjs"
2686
+ ].map((candidate) => path.join(resolved, candidate)).find((candidate) => fs.existsSync(candidate));
2687
+ if (indexFile && isExtensionFile(indexFile)) {
2688
+ addCandidate({
2689
+ candidates: params.candidates,
2690
+ diagnostics: params.diagnostics,
2691
+ seen: params.seen,
2692
+ idHint: path.basename(resolved),
2693
+ source: indexFile,
2694
+ rootDir: resolved,
2695
+ origin: params.origin,
2696
+ ownershipUid: params.ownershipUid,
2697
+ workspaceDir: params.workspaceDir,
2698
+ manifest,
2699
+ packageDir: resolved
2700
+ });
2701
+ return;
2702
+ }
2703
+ discoverInDirectory({
2704
+ dir: resolved,
2705
+ origin: params.origin,
2706
+ ownershipUid: params.ownershipUid,
2707
+ workspaceDir: params.workspaceDir,
2708
+ candidates: params.candidates,
2709
+ diagnostics: params.diagnostics,
2710
+ seen: params.seen
2711
+ });
2712
+ return;
2713
+ }
2714
+ }
2715
+ function discoverRemoteClawPlugins(params) {
2716
+ const candidates = [];
2717
+ const diagnostics = [];
2718
+ const seen = /* @__PURE__ */ new Set();
2719
+ const workspaceDir = params.workspaceDir?.trim();
2720
+ const extra = params.extraPaths ?? [];
2721
+ for (const extraPath of extra) {
2722
+ if (typeof extraPath !== "string") continue;
2723
+ const trimmed = extraPath.trim();
2724
+ if (!trimmed) continue;
2725
+ discoverFromPath({
2726
+ rawPath: trimmed,
2727
+ origin: "config",
2728
+ ownershipUid: params.ownershipUid,
2729
+ workspaceDir: workspaceDir?.trim() || void 0,
2730
+ candidates,
2731
+ diagnostics,
2732
+ seen
2733
+ });
2734
+ }
2735
+ if (workspaceDir) {
2736
+ const workspaceRoot = resolveUserPath(workspaceDir);
2737
+ const workspaceExtDirs = [path.join(workspaceRoot, ".remoteclaw", "extensions")];
2738
+ for (const dir of workspaceExtDirs) discoverInDirectory({
2739
+ dir,
2740
+ origin: "workspace",
2741
+ ownershipUid: params.ownershipUid,
2742
+ workspaceDir: workspaceRoot,
2743
+ candidates,
2744
+ diagnostics,
2745
+ seen
2746
+ });
2747
+ }
2748
+ discoverInDirectory({
2749
+ dir: path.join(resolveConfigDir(), "extensions"),
2750
+ origin: "global",
2751
+ ownershipUid: params.ownershipUid,
2752
+ candidates,
2753
+ diagnostics,
2754
+ seen
2755
+ });
2756
+ const bundledDir = resolveBundledPluginsDir();
2757
+ if (bundledDir) discoverInDirectory({
2758
+ dir: bundledDir,
2759
+ origin: "bundled",
2760
+ ownershipUid: params.ownershipUid,
2761
+ candidates,
2762
+ diagnostics,
2763
+ seen
2764
+ });
2765
+ return {
2766
+ candidates,
2767
+ diagnostics
2768
+ };
2769
+ }
2770
+
2771
+ //#endregion
2772
+ //#region src/plugins/manifest-registry.ts
2773
+ const PLUGIN_ORIGIN_RANK = {
2774
+ config: 0,
2775
+ workspace: 1,
2776
+ global: 2,
2777
+ bundled: 3
2778
+ };
2779
+ const registryCache = /* @__PURE__ */ new Map();
2780
+ const DEFAULT_MANIFEST_CACHE_MS = 200;
2781
+ function clearPluginManifestRegistryCache() {
2782
+ registryCache.clear();
2783
+ }
2784
+ function resolveManifestCacheMs(env) {
2785
+ const raw = env.REMOTECLAW_PLUGIN_MANIFEST_CACHE_MS?.trim();
2786
+ if (raw === "" || raw === "0") return 0;
2787
+ if (!raw) return DEFAULT_MANIFEST_CACHE_MS;
2788
+ const parsed = Number.parseInt(raw, 10);
2789
+ if (!Number.isFinite(parsed)) return DEFAULT_MANIFEST_CACHE_MS;
2790
+ return Math.max(0, parsed);
2791
+ }
2792
+ function shouldUseManifestCache(env) {
2793
+ if (env.REMOTECLAW_DISABLE_PLUGIN_MANIFEST_CACHE?.trim()) return false;
2794
+ return resolveManifestCacheMs(env) > 0;
2795
+ }
2796
+ function buildCacheKey(params) {
2797
+ const workspaceKey = params.workspaceDir ? resolveUserPath(params.workspaceDir) : "";
2798
+ const loadPaths = params.plugins.loadPaths.map((p) => resolveUserPath(p)).map((p) => p.trim()).filter(Boolean).toSorted();
2799
+ return `${workspaceKey}::${JSON.stringify(loadPaths)}`;
2800
+ }
2801
+ function safeStatMtimeMs(filePath) {
2802
+ try {
2803
+ return fs.statSync(filePath).mtimeMs;
2804
+ } catch {
2805
+ return null;
2806
+ }
2807
+ }
2808
+ function normalizeManifestLabel(raw) {
2809
+ const trimmed = raw?.trim();
2810
+ return trimmed ? trimmed : void 0;
2811
+ }
2812
+ function buildRecord(params) {
2813
+ return {
2814
+ id: params.manifest.id,
2815
+ name: normalizeManifestLabel(params.manifest.name) ?? params.candidate.packageName,
2816
+ description: normalizeManifestLabel(params.manifest.description) ?? params.candidate.packageDescription,
2817
+ version: normalizeManifestLabel(params.manifest.version) ?? params.candidate.packageVersion,
2818
+ kind: params.manifest.kind,
2819
+ channels: params.manifest.channels ?? [],
2820
+ providers: params.manifest.providers ?? [],
2821
+ skills: params.manifest.skills ?? [],
2822
+ origin: params.candidate.origin,
2823
+ workspaceDir: params.candidate.workspaceDir,
2824
+ rootDir: params.candidate.rootDir,
2825
+ source: params.candidate.source,
2826
+ manifestPath: params.manifestPath,
2827
+ schemaCacheKey: params.schemaCacheKey,
2828
+ configSchema: params.configSchema,
2829
+ configUiHints: params.manifest.uiHints
2830
+ };
2831
+ }
2832
+ function loadPluginManifestRegistry(params) {
2833
+ const normalized = normalizePluginsConfig((params.config ?? {}).plugins);
2834
+ const cacheKey = buildCacheKey({
2835
+ workspaceDir: params.workspaceDir,
2836
+ plugins: normalized
2837
+ });
2838
+ const env = params.env ?? process.env;
2839
+ const cacheEnabled = params.cache !== false && shouldUseManifestCache(env);
2840
+ if (cacheEnabled) {
2841
+ const cached = registryCache.get(cacheKey);
2842
+ if (cached && cached.expiresAt > Date.now()) return cached.registry;
2843
+ }
2844
+ const discovery = params.candidates ? {
2845
+ candidates: params.candidates,
2846
+ diagnostics: params.diagnostics ?? []
2847
+ } : discoverRemoteClawPlugins({
2848
+ workspaceDir: params.workspaceDir,
2849
+ extraPaths: normalized.loadPaths
2850
+ });
2851
+ const diagnostics = [...discovery.diagnostics];
2852
+ const candidates = discovery.candidates;
2853
+ const records = [];
2854
+ const seenIds = /* @__PURE__ */ new Map();
2855
+ const realpathCache = /* @__PURE__ */ new Map();
2856
+ for (const candidate of candidates) {
2857
+ const manifestRes = loadPluginManifest(candidate.rootDir);
2858
+ if (!manifestRes.ok) {
2859
+ diagnostics.push({
2860
+ level: "error",
2861
+ message: manifestRes.error,
2862
+ source: manifestRes.manifestPath
2863
+ });
2864
+ continue;
2865
+ }
2866
+ const manifest = manifestRes.manifest;
2867
+ if (candidate.idHint && candidate.idHint !== manifest.id) diagnostics.push({
2868
+ level: "warn",
2869
+ pluginId: manifest.id,
2870
+ source: candidate.source,
2871
+ message: `plugin id mismatch (manifest uses "${manifest.id}", entry hints "${candidate.idHint}")`
2872
+ });
2873
+ const configSchema = manifest.configSchema;
2874
+ const manifestMtime = safeStatMtimeMs(manifestRes.manifestPath);
2875
+ const schemaCacheKey = manifestMtime ? `${manifestRes.manifestPath}:${manifestMtime}` : manifestRes.manifestPath;
2876
+ const existing = seenIds.get(manifest.id);
2877
+ if (existing) {
2878
+ const existingReal = safeRealpathSync(existing.candidate.rootDir, realpathCache);
2879
+ const candidateReal = safeRealpathSync(candidate.rootDir, realpathCache);
2880
+ if (Boolean(existingReal && candidateReal && existingReal === candidateReal)) {
2881
+ if (PLUGIN_ORIGIN_RANK[candidate.origin] < PLUGIN_ORIGIN_RANK[existing.candidate.origin]) {
2882
+ records[existing.recordIndex] = buildRecord({
2883
+ manifest,
2884
+ candidate,
2885
+ manifestPath: manifestRes.manifestPath,
2886
+ schemaCacheKey,
2887
+ configSchema
2888
+ });
2889
+ seenIds.set(manifest.id, {
2890
+ candidate,
2891
+ recordIndex: existing.recordIndex
2892
+ });
2893
+ }
2894
+ continue;
2895
+ }
2896
+ diagnostics.push({
2897
+ level: "warn",
2898
+ pluginId: manifest.id,
2899
+ source: candidate.source,
2900
+ message: `duplicate plugin id detected; later plugin may be overridden (${candidate.source})`
2901
+ });
2902
+ } else seenIds.set(manifest.id, {
2903
+ candidate,
2904
+ recordIndex: records.length
2905
+ });
2906
+ records.push(buildRecord({
2907
+ manifest,
2908
+ candidate,
2909
+ manifestPath: manifestRes.manifestPath,
2910
+ schemaCacheKey,
2911
+ configSchema
2912
+ }));
2913
+ }
2914
+ const registry = {
2915
+ plugins: records,
2916
+ diagnostics
2917
+ };
2918
+ if (cacheEnabled) {
2919
+ const ttl = resolveManifestCacheMs(env);
2920
+ if (ttl > 0) registryCache.set(cacheKey, {
2921
+ expiresAt: Date.now() + ttl,
2922
+ registry
2923
+ });
2924
+ }
2925
+ return registry;
2926
+ }
2927
+
2928
+ //#endregion
2929
+ //#region src/plugins/schema-validator.ts
2930
+ const ajv = new AjvPkg({
2931
+ allErrors: true,
2932
+ strict: false,
2933
+ removeAdditional: false
2934
+ });
2935
+ const schemaCache = /* @__PURE__ */ new Map();
2936
+ function formatAjvErrors(errors) {
2937
+ if (!errors || errors.length === 0) return ["invalid config"];
2938
+ return errors.map((error) => {
2939
+ return `${error.instancePath?.replace(/^\//, "").replace(/\//g, ".") || "<root>"}: ${error.message ?? "invalid"}`;
2940
+ });
2941
+ }
2942
+ function validateJsonSchemaValue(params) {
2943
+ let cached = schemaCache.get(params.cacheKey);
2944
+ if (!cached || cached.schema !== params.schema) {
2945
+ cached = {
2946
+ validate: ajv.compile(params.schema),
2947
+ schema: params.schema
2948
+ };
2949
+ schemaCache.set(params.cacheKey, cached);
2950
+ }
2951
+ if (cached.validate(params.value)) return { ok: true };
2952
+ return {
2953
+ ok: false,
2954
+ errors: formatAjvErrors(cached.validate.errors)
2955
+ };
2956
+ }
2957
+
2958
+ //#endregion
2959
+ //#region src/shared/avatar-policy.ts
2960
+ const AVATAR_MAX_BYTES = 2 * 1024 * 1024;
2961
+ const LOCAL_AVATAR_EXTENSIONS = new Set([
2962
+ ".png",
2963
+ ".jpg",
2964
+ ".jpeg",
2965
+ ".gif",
2966
+ ".webp",
2967
+ ".svg"
2968
+ ]);
2969
+ const AVATAR_MIME_BY_EXT = {
2970
+ ".png": "image/png",
2971
+ ".jpg": "image/jpeg",
2972
+ ".jpeg": "image/jpeg",
2973
+ ".webp": "image/webp",
2974
+ ".gif": "image/gif",
2975
+ ".svg": "image/svg+xml",
2976
+ ".bmp": "image/bmp",
2977
+ ".tif": "image/tiff",
2978
+ ".tiff": "image/tiff"
2979
+ };
2980
+ const AVATAR_DATA_RE = /^data:/i;
2981
+ const AVATAR_IMAGE_DATA_RE = /^data:image\//i;
2982
+ const AVATAR_HTTP_RE = /^https?:\/\//i;
2983
+ const AVATAR_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;
2984
+ const WINDOWS_ABS_RE = /^[a-zA-Z]:[\\/]/;
2985
+ const AVATAR_PATH_EXT_RE = /\.(png|jpe?g|gif|webp|svg|ico)$/i;
2986
+ function resolveAvatarMime(filePath) {
2987
+ return AVATAR_MIME_BY_EXT[path.extname(filePath).toLowerCase()] ?? "application/octet-stream";
2988
+ }
2989
+ function isAvatarDataUrl(value) {
2990
+ return AVATAR_DATA_RE.test(value);
2991
+ }
2992
+ function isAvatarImageDataUrl(value) {
2993
+ return AVATAR_IMAGE_DATA_RE.test(value);
2994
+ }
2995
+ function isAvatarHttpUrl(value) {
2996
+ return AVATAR_HTTP_RE.test(value);
2997
+ }
2998
+ function hasAvatarUriScheme(value) {
2999
+ return AVATAR_SCHEME_RE.test(value);
3000
+ }
3001
+ function isWindowsAbsolutePath(value) {
3002
+ return WINDOWS_ABS_RE.test(value);
3003
+ }
3004
+ function isWorkspaceRelativeAvatarPath(value) {
3005
+ if (!value) return false;
3006
+ if (value.startsWith("~")) return false;
3007
+ if (hasAvatarUriScheme(value) && !isWindowsAbsolutePath(value)) return false;
3008
+ return true;
3009
+ }
3010
+ function isPathWithinRoot(rootDir, targetPath) {
3011
+ const relative = path.relative(rootDir, targetPath);
3012
+ if (relative === "") return true;
3013
+ return !relative.startsWith("..") && !path.isAbsolute(relative);
3014
+ }
3015
+ function looksLikeAvatarPath(value) {
3016
+ if (/[\\/]/.test(value)) return true;
3017
+ return AVATAR_PATH_EXT_RE.test(value);
3018
+ }
3019
+ function isSupportedLocalAvatarExtension(filePath) {
3020
+ const ext = path.extname(filePath).toLowerCase();
3021
+ return LOCAL_AVATAR_EXTENSIONS.has(ext);
3022
+ }
3023
+
3024
+ //#endregion
3025
+ //#region src/config/validation.ts
3026
+ const LEGACY_REMOVED_PLUGIN_IDS = new Set(["google-antigravity-auth"]);
3027
+ function isWorkspaceAvatarPath(value, workspaceDir) {
3028
+ const workspaceRoot = path.resolve(workspaceDir);
3029
+ return isPathWithinRoot(workspaceRoot, path.resolve(workspaceRoot, value));
3030
+ }
3031
+ function validateIdentityAvatar(config) {
3032
+ const agents = config.agents?.list;
3033
+ if (!Array.isArray(agents) || agents.length === 0) return [];
3034
+ const issues = [];
3035
+ for (const [index, entry] of agents.entries()) {
3036
+ if (!entry || typeof entry !== "object") continue;
3037
+ const avatarRaw = entry.identity?.avatar;
3038
+ if (typeof avatarRaw !== "string") continue;
3039
+ const avatar = avatarRaw.trim();
3040
+ if (!avatar) continue;
3041
+ if (isAvatarDataUrl(avatar) || isAvatarHttpUrl(avatar)) continue;
3042
+ if (avatar.startsWith("~")) {
3043
+ issues.push({
3044
+ path: `agents.list.${index}.identity.avatar`,
3045
+ message: "identity.avatar must be a workspace-relative path, http(s) URL, or data URI."
3046
+ });
3047
+ continue;
3048
+ }
3049
+ if (hasAvatarUriScheme(avatar) && !isWindowsAbsolutePath(avatar)) {
3050
+ issues.push({
3051
+ path: `agents.list.${index}.identity.avatar`,
3052
+ message: "identity.avatar must be a workspace-relative path, http(s) URL, or data URI."
3053
+ });
3054
+ continue;
3055
+ }
3056
+ const workspaceDir = resolveAgentWorkspaceDirOrNull(config, entry.id ?? resolveDefaultAgentId(config));
3057
+ if (workspaceDir != null && !isWorkspaceAvatarPath(avatar, workspaceDir)) issues.push({
3058
+ path: `agents.list.${index}.identity.avatar`,
3059
+ message: "identity.avatar must stay within the agent workspace."
3060
+ });
3061
+ }
3062
+ return issues;
3063
+ }
3064
+ /**
3065
+ * Validates config without applying runtime defaults.
3066
+ * Use this when you need the raw validated config (e.g., for writing back to file).
3067
+ */
3068
+ function validateConfigObjectRaw(raw) {
3069
+ const legacyIssues = findLegacyConfigIssues(raw);
3070
+ if (legacyIssues.length > 0) return {
3071
+ ok: false,
3072
+ issues: legacyIssues.map((iss) => ({
3073
+ path: iss.path,
3074
+ message: iss.message
3075
+ }))
3076
+ };
3077
+ const validated = RemoteClawSchema.safeParse(raw);
3078
+ if (!validated.success) return {
3079
+ ok: false,
3080
+ issues: validated.error.issues.map((iss) => ({
3081
+ path: iss.path.join("."),
3082
+ message: iss.message
3083
+ }))
3084
+ };
3085
+ const duplicates = findDuplicateAgentDirs(validated.data);
3086
+ if (duplicates.length > 0) return {
3087
+ ok: false,
3088
+ issues: [{
3089
+ path: "agents.list",
3090
+ message: formatDuplicateAgentDirError(duplicates)
3091
+ }]
3092
+ };
3093
+ const avatarIssues = validateIdentityAvatar(validated.data);
3094
+ if (avatarIssues.length > 0) return {
3095
+ ok: false,
3096
+ issues: avatarIssues
3097
+ };
3098
+ return {
3099
+ ok: true,
3100
+ config: validated.data
3101
+ };
3102
+ }
3103
+ function validateConfigObject(raw) {
3104
+ const result = validateConfigObjectRaw(raw);
3105
+ if (!result.ok) return result;
3106
+ return {
3107
+ ok: true,
3108
+ config: applyModelDefaults(applyAgentDefaults(applySessionDefaults(result.config)))
3109
+ };
3110
+ }
3111
+ function validateConfigObjectWithPlugins(raw) {
3112
+ return validateConfigObjectWithPluginsBase(raw, { applyDefaults: true });
3113
+ }
3114
+ function validateConfigObjectRawWithPlugins(raw) {
3115
+ return validateConfigObjectWithPluginsBase(raw, { applyDefaults: false });
3116
+ }
3117
+ function validateConfigObjectWithPluginsBase(raw, opts) {
3118
+ const base = opts.applyDefaults ? validateConfigObject(raw) : validateConfigObjectRaw(raw);
3119
+ if (!base.ok) return {
3120
+ ok: false,
3121
+ issues: base.issues,
3122
+ warnings: []
3123
+ };
3124
+ const config = base.config;
3125
+ const issues = [];
3126
+ const warnings = [];
3127
+ const hasExplicitPluginsConfig = isRecord(raw) && Object.prototype.hasOwnProperty.call(raw, "plugins");
3128
+ let registryInfo = null;
3129
+ const ensureRegistry = () => {
3130
+ if (registryInfo) return registryInfo;
3131
+ const registry = loadPluginManifestRegistry({
3132
+ config,
3133
+ workspaceDir: resolveAgentWorkspaceDirOrNull(config, resolveDefaultAgentId(config)) ?? void 0
3134
+ });
3135
+ const knownIds = new Set(registry.plugins.map((record) => record.id));
3136
+ const normalizedPlugins = normalizePluginsConfig(config.plugins);
3137
+ for (const diag of registry.diagnostics) {
3138
+ let path = diag.pluginId ? `plugins.entries.${diag.pluginId}` : "plugins";
3139
+ if (!diag.pluginId && diag.message.includes("plugin path not found")) path = "plugins.load.paths";
3140
+ const message = `${diag.pluginId ? `plugin ${diag.pluginId}` : "plugin"}: ${diag.message}`;
3141
+ if (diag.level === "error") issues.push({
3142
+ path,
3143
+ message
3144
+ });
3145
+ else warnings.push({
3146
+ path,
3147
+ message
3148
+ });
3149
+ }
3150
+ registryInfo = {
3151
+ registry,
3152
+ knownIds,
3153
+ normalizedPlugins
3154
+ };
3155
+ return registryInfo;
3156
+ };
3157
+ const allowedChannels = new Set([
3158
+ "defaults",
3159
+ "modelByChannel",
3160
+ ...CHANNEL_IDS
3161
+ ]);
3162
+ if (config.channels && isRecord(config.channels)) for (const key of Object.keys(config.channels)) {
3163
+ const trimmed = key.trim();
3164
+ if (!trimmed) continue;
3165
+ if (!allowedChannels.has(trimmed)) {
3166
+ const { registry } = ensureRegistry();
3167
+ for (const record of registry.plugins) for (const channelId of record.channels) allowedChannels.add(channelId);
3168
+ }
3169
+ if (!allowedChannels.has(trimmed)) issues.push({
3170
+ path: `channels.${trimmed}`,
3171
+ message: `unknown channel id: ${trimmed}`
3172
+ });
3173
+ }
3174
+ const heartbeatChannelIds = /* @__PURE__ */ new Set();
3175
+ for (const channelId of CHANNEL_IDS) heartbeatChannelIds.add(channelId.toLowerCase());
3176
+ const validateHeartbeatTarget = (target, path) => {
3177
+ if (typeof target !== "string") return;
3178
+ const trimmed = target.trim();
3179
+ if (!trimmed) {
3180
+ issues.push({
3181
+ path,
3182
+ message: "heartbeat target must not be empty"
3183
+ });
3184
+ return;
3185
+ }
3186
+ const normalized = trimmed.toLowerCase();
3187
+ if (normalized === "last" || normalized === "none") return;
3188
+ if (normalizeChatChannelId(trimmed)) return;
3189
+ if (!heartbeatChannelIds.has(normalized)) {
3190
+ const { registry } = ensureRegistry();
3191
+ for (const record of registry.plugins) for (const channelId of record.channels) {
3192
+ const pluginChannel = channelId.trim();
3193
+ if (pluginChannel) heartbeatChannelIds.add(pluginChannel.toLowerCase());
3194
+ }
3195
+ }
3196
+ if (heartbeatChannelIds.has(normalized)) return;
3197
+ issues.push({
3198
+ path,
3199
+ message: `unknown heartbeat target: ${target}`
3200
+ });
3201
+ };
3202
+ validateHeartbeatTarget(config.agents?.defaults?.heartbeat?.target, "agents.defaults.heartbeat.target");
3203
+ if (Array.isArray(config.agents?.list)) for (const [index, entry] of config.agents.list.entries()) validateHeartbeatTarget(entry?.heartbeat?.target, `agents.list.${index}.heartbeat.target`);
3204
+ if (!hasExplicitPluginsConfig) {
3205
+ if (issues.length > 0) return {
3206
+ ok: false,
3207
+ issues,
3208
+ warnings
3209
+ };
3210
+ return {
3211
+ ok: true,
3212
+ config,
3213
+ warnings
3214
+ };
3215
+ }
3216
+ const { registry, knownIds, normalizedPlugins } = ensureRegistry();
3217
+ const pushMissingPluginIssue = (path, pluginId) => {
3218
+ if (LEGACY_REMOVED_PLUGIN_IDS.has(pluginId)) {
3219
+ warnings.push({
3220
+ path,
3221
+ message: `plugin removed: ${pluginId} (stale config entry ignored; remove it from plugins config)`
3222
+ });
3223
+ return;
3224
+ }
3225
+ issues.push({
3226
+ path,
3227
+ message: `plugin not found: ${pluginId}`
3228
+ });
3229
+ };
3230
+ const pluginsConfig = config.plugins;
3231
+ const entries = pluginsConfig?.entries;
3232
+ if (entries && isRecord(entries)) {
3233
+ for (const pluginId of Object.keys(entries)) if (!knownIds.has(pluginId)) pushMissingPluginIssue(`plugins.entries.${pluginId}`, pluginId);
3234
+ }
3235
+ const allow = pluginsConfig?.allow ?? [];
3236
+ for (const pluginId of allow) {
3237
+ if (typeof pluginId !== "string" || !pluginId.trim()) continue;
3238
+ if (!knownIds.has(pluginId)) pushMissingPluginIssue("plugins.allow", pluginId);
3239
+ }
3240
+ const deny = pluginsConfig?.deny ?? [];
3241
+ for (const pluginId of deny) {
3242
+ if (typeof pluginId !== "string" || !pluginId.trim()) continue;
3243
+ if (!knownIds.has(pluginId)) pushMissingPluginIssue("plugins.deny", pluginId);
3244
+ }
3245
+ const seenPlugins = /* @__PURE__ */ new Set();
3246
+ for (const record of registry.plugins) {
3247
+ const pluginId = record.id;
3248
+ if (seenPlugins.has(pluginId)) continue;
3249
+ seenPlugins.add(pluginId);
3250
+ const entry = normalizedPlugins.entries[pluginId];
3251
+ const entryHasConfig = Boolean(entry?.config);
3252
+ const enableState = resolveEffectiveEnableState({
3253
+ id: pluginId,
3254
+ origin: record.origin,
3255
+ config: normalizedPlugins,
3256
+ rootConfig: config
3257
+ });
3258
+ let enabled = enableState.enabled;
3259
+ let reason = enableState.reason;
3260
+ if (enabled || entryHasConfig) if (record.configSchema) {
3261
+ const res = validateJsonSchemaValue({
3262
+ schema: record.configSchema,
3263
+ cacheKey: record.schemaCacheKey ?? record.manifestPath ?? pluginId,
3264
+ value: entry?.config ?? {}
3265
+ });
3266
+ if (!res.ok) for (const error of res.errors) issues.push({
3267
+ path: `plugins.entries.${pluginId}.config`,
3268
+ message: `invalid config: ${error}`
3269
+ });
3270
+ } else issues.push({
3271
+ path: `plugins.entries.${pluginId}`,
3272
+ message: `plugin schema missing for ${pluginId}`
3273
+ });
3274
+ if (!enabled && entryHasConfig) warnings.push({
3275
+ path: `plugins.entries.${pluginId}`,
3276
+ message: `plugin disabled (${reason ?? "disabled"}) but config is present`
3277
+ });
3278
+ }
3279
+ if (issues.length > 0) return {
3280
+ ok: false,
3281
+ issues,
3282
+ warnings
3283
+ };
3284
+ return {
3285
+ ok: true,
3286
+ config,
3287
+ warnings
3288
+ };
3289
+ }
3290
+
3291
+ //#endregion
3292
+ //#region src/config/version.ts
3293
+ const VERSION_RE = /^v?(\d+)\.(\d+)\.(\d+)(?:-(\d+))?/;
3294
+ function parseRemoteClawVersion(raw) {
3295
+ if (!raw) return null;
3296
+ const match = raw.trim().match(VERSION_RE);
3297
+ if (!match) return null;
3298
+ const [, major, minor, patch, revision] = match;
3299
+ return {
3300
+ major: Number.parseInt(major, 10),
3301
+ minor: Number.parseInt(minor, 10),
3302
+ patch: Number.parseInt(patch, 10),
3303
+ revision: revision ? Number.parseInt(revision, 10) : 0
3304
+ };
3305
+ }
3306
+ function compareRemoteClawVersions(a, b) {
3307
+ const parsedA = parseRemoteClawVersion(a);
3308
+ const parsedB = parseRemoteClawVersion(b);
3309
+ if (!parsedA || !parsedB) return null;
3310
+ if (parsedA.major !== parsedB.major) return parsedA.major < parsedB.major ? -1 : 1;
3311
+ if (parsedA.minor !== parsedB.minor) return parsedA.minor < parsedB.minor ? -1 : 1;
3312
+ if (parsedA.patch !== parsedB.patch) return parsedA.patch < parsedB.patch ? -1 : 1;
3313
+ if (parsedA.revision !== parsedB.revision) return parsedA.revision < parsedB.revision ? -1 : 1;
3314
+ return 0;
3315
+ }
3316
+
3317
+ //#endregion
3318
+ //#region src/config/io.ts
3319
+ const SHELL_ENV_EXPECTED_KEYS = [
3320
+ "OPENAI_API_KEY",
3321
+ "ANTHROPIC_API_KEY",
3322
+ "ANTHROPIC_OAUTH_TOKEN",
3323
+ "GEMINI_API_KEY",
3324
+ "ZAI_API_KEY",
3325
+ "OPENROUTER_API_KEY",
3326
+ "AI_GATEWAY_API_KEY",
3327
+ "MINIMAX_API_KEY",
3328
+ "SYNTHETIC_API_KEY",
3329
+ "KILOCODE_API_KEY",
3330
+ "ELEVENLABS_API_KEY",
3331
+ "TELEGRAM_BOT_TOKEN",
3332
+ "DISCORD_BOT_TOKEN",
3333
+ "SLACK_BOT_TOKEN",
3334
+ "SLACK_APP_TOKEN",
3335
+ "REMOTECLAW_GATEWAY_TOKEN",
3336
+ "REMOTECLAW_GATEWAY_PASSWORD"
3337
+ ];
3338
+ const OPEN_DM_POLICY_ALLOW_FROM_RE = /^(?<policyPath>[a-z0-9_.-]+)\s*=\s*"open"\s+requires\s+(?<allowPath>[a-z0-9_.-]+)(?:\s+\(or\s+[a-z0-9_.-]+\))?\s+to include "\*"$/i;
3339
+ const CONFIG_AUDIT_LOG_FILENAME = "config-audit.jsonl";
3340
+ const loggedInvalidConfigs = /* @__PURE__ */ new Set();
3341
+ function hashConfigRaw(raw) {
3342
+ return crypto.createHash("sha256").update(raw ?? "").digest("hex");
3343
+ }
3344
+ function formatConfigValidationFailure(pathLabel, issueMessage) {
3345
+ const match = issueMessage.match(OPEN_DM_POLICY_ALLOW_FROM_RE);
3346
+ const policyPath = match?.groups?.policyPath?.trim();
3347
+ const allowPath = match?.groups?.allowPath?.trim();
3348
+ if (!policyPath || !allowPath) return `Config validation failed: ${pathLabel}: ${issueMessage}`;
3349
+ return [
3350
+ `Config validation failed: ${pathLabel}`,
3351
+ "",
3352
+ `Configuration mismatch: ${policyPath} is "open", but ${allowPath} does not include "*".`,
3353
+ "",
3354
+ "Fix with:",
3355
+ ` remoteclaw config set ${allowPath} '["*"]'`,
3356
+ "",
3357
+ "Or switch policy:",
3358
+ ` remoteclaw config set ${policyPath} "pairing"`
3359
+ ].join("\n");
3360
+ }
3361
+ function isNumericPathSegment(raw) {
3362
+ return /^[0-9]+$/.test(raw);
3363
+ }
3364
+ function isWritePlainObject(value) {
3365
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3366
+ }
3367
+ function hasOwnObjectKey(value, key) {
3368
+ return Object.prototype.hasOwnProperty.call(value, key);
3369
+ }
3370
+ const WRITE_PRUNED_OBJECT = Symbol("write-pruned-object");
3371
+ function unsetPathForWriteAt(value, pathSegments, depth) {
3372
+ if (depth >= pathSegments.length) return {
3373
+ changed: false,
3374
+ value
3375
+ };
3376
+ const segment = pathSegments[depth];
3377
+ const isLeaf = depth === pathSegments.length - 1;
3378
+ if (Array.isArray(value)) {
3379
+ if (!isNumericPathSegment(segment)) return {
3380
+ changed: false,
3381
+ value
3382
+ };
3383
+ const index = Number.parseInt(segment, 10);
3384
+ if (!Number.isFinite(index) || index < 0 || index >= value.length) return {
3385
+ changed: false,
3386
+ value
3387
+ };
3388
+ if (isLeaf) {
3389
+ const next = value.slice();
3390
+ next.splice(index, 1);
3391
+ return {
3392
+ changed: true,
3393
+ value: next
3394
+ };
3395
+ }
3396
+ const child = unsetPathForWriteAt(value[index], pathSegments, depth + 1);
3397
+ if (!child.changed) return {
3398
+ changed: false,
3399
+ value
3400
+ };
3401
+ const next = value.slice();
3402
+ if (child.value === WRITE_PRUNED_OBJECT) next.splice(index, 1);
3403
+ else next[index] = child.value;
3404
+ return {
3405
+ changed: true,
3406
+ value: next
3407
+ };
3408
+ }
3409
+ if (isBlockedObjectKey(segment) || !isWritePlainObject(value) || !hasOwnObjectKey(value, segment)) return {
3410
+ changed: false,
3411
+ value
3412
+ };
3413
+ if (isLeaf) {
3414
+ const next = { ...value };
3415
+ delete next[segment];
3416
+ return {
3417
+ changed: true,
3418
+ value: Object.keys(next).length === 0 ? WRITE_PRUNED_OBJECT : next
3419
+ };
3420
+ }
3421
+ const child = unsetPathForWriteAt(value[segment], pathSegments, depth + 1);
3422
+ if (!child.changed) return {
3423
+ changed: false,
3424
+ value
3425
+ };
3426
+ const next = { ...value };
3427
+ if (child.value === WRITE_PRUNED_OBJECT) delete next[segment];
3428
+ else next[segment] = child.value;
3429
+ return {
3430
+ changed: true,
3431
+ value: Object.keys(next).length === 0 ? WRITE_PRUNED_OBJECT : next
3432
+ };
3433
+ }
3434
+ function unsetPathForWrite(root, pathSegments) {
3435
+ if (pathSegments.length === 0) return {
3436
+ changed: false,
3437
+ next: root
3438
+ };
3439
+ const result = unsetPathForWriteAt(root, pathSegments, 0);
3440
+ if (!result.changed) return {
3441
+ changed: false,
3442
+ next: root
3443
+ };
3444
+ if (result.value === WRITE_PRUNED_OBJECT) return {
3445
+ changed: true,
3446
+ next: {}
3447
+ };
3448
+ if (isWritePlainObject(result.value)) return {
3449
+ changed: true,
3450
+ next: coerceConfig(result.value)
3451
+ };
3452
+ return {
3453
+ changed: false,
3454
+ next: root
3455
+ };
3456
+ }
3457
+ function resolveConfigSnapshotHash(snapshot) {
3458
+ if (typeof snapshot.hash === "string") {
3459
+ const trimmed = snapshot.hash.trim();
3460
+ if (trimmed) return trimmed;
3461
+ }
3462
+ if (typeof snapshot.raw !== "string") return null;
3463
+ return hashConfigRaw(snapshot.raw);
3464
+ }
3465
+ function coerceConfig(value) {
3466
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
3467
+ return value;
3468
+ }
3469
+ function isPlainObject(value) {
3470
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3471
+ }
3472
+ function hasConfigMeta(value) {
3473
+ if (!isPlainObject(value)) return false;
3474
+ const meta = value.meta;
3475
+ return isPlainObject(meta);
3476
+ }
3477
+ function resolveGatewayMode(value) {
3478
+ if (!isPlainObject(value)) return null;
3479
+ const gateway = value.gateway;
3480
+ if (!isPlainObject(gateway) || typeof gateway.mode !== "string") return null;
3481
+ const trimmed = gateway.mode.trim();
3482
+ return trimmed.length > 0 ? trimmed : null;
3483
+ }
3484
+ function cloneUnknown(value) {
3485
+ return structuredClone(value);
3486
+ }
3487
+ function createMergePatch(base, target) {
3488
+ if (!isPlainObject(base) || !isPlainObject(target)) return cloneUnknown(target);
3489
+ const patch = {};
3490
+ const keys = new Set([...Object.keys(base), ...Object.keys(target)]);
3491
+ for (const key of keys) {
3492
+ const hasBase = key in base;
3493
+ if (!(key in target)) {
3494
+ patch[key] = null;
3495
+ continue;
3496
+ }
3497
+ const targetValue = target[key];
3498
+ if (!hasBase) {
3499
+ patch[key] = cloneUnknown(targetValue);
3500
+ continue;
3501
+ }
3502
+ const baseValue = base[key];
3503
+ if (isPlainObject(baseValue) && isPlainObject(targetValue)) {
3504
+ const childPatch = createMergePatch(baseValue, targetValue);
3505
+ if (isPlainObject(childPatch) && Object.keys(childPatch).length === 0) continue;
3506
+ patch[key] = childPatch;
3507
+ continue;
3508
+ }
3509
+ if (!isDeepStrictEqual(baseValue, targetValue)) patch[key] = cloneUnknown(targetValue);
3510
+ }
3511
+ return patch;
3512
+ }
3513
+ function collectEnvRefPaths(value, path, output) {
3514
+ if (typeof value === "string") {
3515
+ if (containsEnvVarReference(value)) output.set(path, value);
3516
+ return;
3517
+ }
3518
+ if (Array.isArray(value)) {
3519
+ value.forEach((item, index) => {
3520
+ collectEnvRefPaths(item, `${path}[${index}]`, output);
3521
+ });
3522
+ return;
3523
+ }
3524
+ if (isPlainObject(value)) for (const [key, child] of Object.entries(value)) collectEnvRefPaths(child, path ? `${path}.${key}` : key, output);
3525
+ }
3526
+ function collectChangedPaths(base, target, path, output) {
3527
+ if (Array.isArray(base) && Array.isArray(target)) {
3528
+ const max = Math.max(base.length, target.length);
3529
+ for (let index = 0; index < max; index += 1) {
3530
+ const childPath = path ? `${path}[${index}]` : `[${index}]`;
3531
+ if (index >= base.length || index >= target.length) {
3532
+ output.add(childPath);
3533
+ continue;
3534
+ }
3535
+ collectChangedPaths(base[index], target[index], childPath, output);
3536
+ }
3537
+ return;
3538
+ }
3539
+ if (isPlainObject(base) && isPlainObject(target)) {
3540
+ const keys = new Set([...Object.keys(base), ...Object.keys(target)]);
3541
+ for (const key of keys) {
3542
+ const childPath = path ? `${path}.${key}` : key;
3543
+ const hasBase = key in base;
3544
+ if (!(key in target) || !hasBase) {
3545
+ output.add(childPath);
3546
+ continue;
3547
+ }
3548
+ collectChangedPaths(base[key], target[key], childPath, output);
3549
+ }
3550
+ return;
3551
+ }
3552
+ if (!isDeepStrictEqual(base, target)) output.add(path);
3553
+ }
3554
+ function parentPath(value) {
3555
+ if (!value) return "";
3556
+ if (value.endsWith("]")) {
3557
+ const index = value.lastIndexOf("[");
3558
+ return index > 0 ? value.slice(0, index) : "";
3559
+ }
3560
+ const index = value.lastIndexOf(".");
3561
+ return index >= 0 ? value.slice(0, index) : "";
3562
+ }
3563
+ function isPathChanged(path, changedPaths) {
3564
+ if (changedPaths.has(path)) return true;
3565
+ let current = parentPath(path);
3566
+ while (current) {
3567
+ if (changedPaths.has(current)) return true;
3568
+ current = parentPath(current);
3569
+ }
3570
+ return changedPaths.has("");
3571
+ }
3572
+ function restoreEnvRefsFromMap(value, path, envRefMap, changedPaths) {
3573
+ if (typeof value === "string") {
3574
+ if (!isPathChanged(path, changedPaths)) {
3575
+ const original = envRefMap.get(path);
3576
+ if (original !== void 0) return original;
3577
+ }
3578
+ return value;
3579
+ }
3580
+ if (Array.isArray(value)) {
3581
+ let changed = false;
3582
+ const next = value.map((item, index) => {
3583
+ const updated = restoreEnvRefsFromMap(item, `${path}[${index}]`, envRefMap, changedPaths);
3584
+ if (updated !== item) changed = true;
3585
+ return updated;
3586
+ });
3587
+ return changed ? next : value;
3588
+ }
3589
+ if (isPlainObject(value)) {
3590
+ let changed = false;
3591
+ const next = {};
3592
+ for (const [key, child] of Object.entries(value)) {
3593
+ const updated = restoreEnvRefsFromMap(child, path ? `${path}.${key}` : key, envRefMap, changedPaths);
3594
+ if (updated !== child) changed = true;
3595
+ next[key] = updated;
3596
+ }
3597
+ return changed ? next : value;
3598
+ }
3599
+ return value;
3600
+ }
3601
+ function resolveConfigAuditLogPath(env, homedir) {
3602
+ return path.join(resolveStateDir(env, homedir), "logs", CONFIG_AUDIT_LOG_FILENAME);
3603
+ }
3604
+ function resolveConfigWriteSuspiciousReasons(params) {
3605
+ const reasons = [];
3606
+ if (!params.existsBefore) return reasons;
3607
+ if (typeof params.previousBytes === "number" && typeof params.nextBytes === "number" && params.previousBytes >= 512 && params.nextBytes < Math.floor(params.previousBytes * .5)) reasons.push(`size-drop:${params.previousBytes}->${params.nextBytes}`);
3608
+ if (!params.hasMetaBefore) reasons.push("missing-meta-before-write");
3609
+ if (params.gatewayModeBefore && !params.gatewayModeAfter) reasons.push("gateway-mode-removed");
3610
+ return reasons;
3611
+ }
3612
+ async function appendConfigWriteAuditRecord(deps, record) {
3613
+ try {
3614
+ const auditPath = resolveConfigAuditLogPath(deps.env, deps.homedir);
3615
+ await deps.fs.promises.mkdir(path.dirname(auditPath), {
3616
+ recursive: true,
3617
+ mode: 448
3618
+ });
3619
+ await deps.fs.promises.appendFile(auditPath, `${JSON.stringify(record)}\n`, {
3620
+ encoding: "utf-8",
3621
+ mode: 384
3622
+ });
3623
+ } catch {}
3624
+ }
3625
+ function warnOnConfigMiskeys(raw, logger) {
3626
+ if (!raw || typeof raw !== "object") return;
3627
+ const gateway = raw.gateway;
3628
+ if (!gateway || typeof gateway !== "object") return;
3629
+ if ("token" in gateway) logger.warn("Config uses \"gateway.token\". This key is ignored; use \"gateway.auth.token\" instead.");
3630
+ }
3631
+ function stampConfigVersion(cfg) {
3632
+ const now = (/* @__PURE__ */ new Date()).toISOString();
3633
+ return {
3634
+ ...cfg,
3635
+ meta: {
3636
+ ...cfg.meta,
3637
+ lastTouchedVersion: VERSION,
3638
+ lastTouchedAt: now
3639
+ }
3640
+ };
3641
+ }
3642
+ function warnIfConfigFromFuture(cfg, logger) {
3643
+ const touched = cfg.meta?.lastTouchedVersion;
3644
+ if (!touched) return;
3645
+ const cmp = compareRemoteClawVersions(VERSION, touched);
3646
+ if (cmp === null) return;
3647
+ if (cmp < 0) logger.warn(`Config was last written by a newer RemoteClaw (${touched}); current version is ${VERSION}.`);
3648
+ }
3649
+ function resolveConfigPathForDeps(deps) {
3650
+ if (deps.configPath) return deps.configPath;
3651
+ return resolveConfigPath(deps.env, resolveStateDir(deps.env, deps.homedir));
3652
+ }
3653
+ function normalizeDeps(overrides = {}) {
3654
+ return {
3655
+ fs: overrides.fs ?? fs,
3656
+ json5: overrides.json5 ?? JSON5,
3657
+ env: overrides.env ?? process.env,
3658
+ homedir: overrides.homedir ?? (() => resolveRequiredHomeDir(overrides.env ?? process.env, os.homedir)),
3659
+ configPath: overrides.configPath ?? "",
3660
+ logger: overrides.logger ?? console
3661
+ };
3662
+ }
3663
+ function maybeLoadDotEnvForConfig(env) {
3664
+ if (env !== process.env) return;
3665
+ loadDotEnv({ quiet: true });
3666
+ }
3667
+ function parseConfigJson5(raw, json5 = JSON5) {
3668
+ try {
3669
+ return {
3670
+ ok: true,
3671
+ parsed: json5.parse(raw)
3672
+ };
3673
+ } catch (err) {
3674
+ return {
3675
+ ok: false,
3676
+ error: String(err)
3677
+ };
3678
+ }
3679
+ }
3680
+ function resolveConfigIncludesForRead(parsed, configPath, deps) {
3681
+ return resolveConfigIncludes(parsed, configPath, {
3682
+ readFile: (candidate) => deps.fs.readFileSync(candidate, "utf-8"),
3683
+ parseJson: (raw) => deps.json5.parse(raw)
3684
+ });
3685
+ }
3686
+ function resolveConfigForRead(resolvedIncludes, env) {
3687
+ if (resolvedIncludes && typeof resolvedIncludes === "object" && "env" in resolvedIncludes) applyConfigEnvVars(resolvedIncludes, env);
3688
+ return {
3689
+ resolvedConfigRaw: resolveConfigEnvVars(resolvedIncludes, env),
3690
+ envSnapshotForRestore: { ...env }
3691
+ };
3692
+ }
3693
+ function createConfigIO(overrides = {}) {
3694
+ const deps = normalizeDeps(overrides);
3695
+ const requestedConfigPath = resolveConfigPathForDeps(deps);
3696
+ const configPath = (deps.configPath ? [requestedConfigPath] : resolveDefaultConfigCandidates(deps.env, deps.homedir)).find((candidate) => deps.fs.existsSync(candidate)) ?? requestedConfigPath;
3697
+ function loadConfig() {
3698
+ try {
3699
+ maybeLoadDotEnvForConfig(deps.env);
3700
+ if (!deps.fs.existsSync(configPath)) {
3701
+ if (shouldEnableShellEnvFallback(deps.env) && !shouldDeferShellEnvFallback(deps.env)) loadShellEnvFallback({
3702
+ enabled: true,
3703
+ env: deps.env,
3704
+ expectedKeys: SHELL_ENV_EXPECTED_KEYS,
3705
+ logger: deps.logger,
3706
+ timeoutMs: resolveShellEnvFallbackTimeoutMs(deps.env)
3707
+ });
3708
+ return {};
3709
+ }
3710
+ const raw = deps.fs.readFileSync(configPath, "utf-8");
3711
+ const { resolvedConfigRaw: resolvedConfig } = resolveConfigForRead(resolveConfigIncludesForRead(deps.json5.parse(raw), configPath, deps), deps.env);
3712
+ warnOnConfigMiskeys(resolvedConfig, deps.logger);
3713
+ if (typeof resolvedConfig !== "object" || resolvedConfig === null) return {};
3714
+ const preValidationDuplicates = findDuplicateAgentDirs(resolvedConfig, {
3715
+ env: deps.env,
3716
+ homedir: deps.homedir
3717
+ });
3718
+ if (preValidationDuplicates.length > 0) throw new DuplicateAgentDirError(preValidationDuplicates);
3719
+ const validated = validateConfigObjectWithPlugins(resolvedConfig);
3720
+ if (!validated.ok) {
3721
+ const details = validated.issues.map((iss) => `- ${iss.path || "<root>"}: ${iss.message}`).join("\n");
3722
+ if (!loggedInvalidConfigs.has(configPath)) {
3723
+ loggedInvalidConfigs.add(configPath);
3724
+ deps.logger.error(`Invalid config at ${configPath}:\\n${details}`);
3725
+ }
3726
+ const error = /* @__PURE__ */ new Error("Invalid config");
3727
+ error.code = "INVALID_CONFIG";
3728
+ error.details = details;
3729
+ throw error;
3730
+ }
3731
+ if (validated.warnings.length > 0) {
3732
+ const details = validated.warnings.map((iss) => `- ${iss.path || "<root>"}: ${iss.message}`).join("\n");
3733
+ deps.logger.warn(`Config warnings:\\n${details}`);
3734
+ }
3735
+ warnIfConfigFromFuture(validated.config, deps.logger);
3736
+ const cfg = applyTalkConfigNormalization(applyModelDefaults(applyContextPruningDefaults(applyAgentDefaults(applySessionDefaults(applyLoggingDefaults(applyMessageDefaults(validated.config)))))));
3737
+ normalizeConfigPaths(cfg);
3738
+ const duplicates = findDuplicateAgentDirs(cfg, {
3739
+ env: deps.env,
3740
+ homedir: deps.homedir
3741
+ });
3742
+ if (duplicates.length > 0) throw new DuplicateAgentDirError(duplicates);
3743
+ applyConfigEnvVars(cfg, deps.env);
3744
+ if ((shouldEnableShellEnvFallback(deps.env) || cfg.env?.shellEnv?.enabled === true) && !shouldDeferShellEnvFallback(deps.env)) loadShellEnvFallback({
3745
+ enabled: true,
3746
+ env: deps.env,
3747
+ expectedKeys: SHELL_ENV_EXPECTED_KEYS,
3748
+ logger: deps.logger,
3749
+ timeoutMs: cfg.env?.shellEnv?.timeoutMs ?? resolveShellEnvFallbackTimeoutMs(deps.env)
3750
+ });
3751
+ const pendingSecret = AUTO_OWNER_DISPLAY_SECRET_BY_PATH.get(configPath);
3752
+ const ownerDisplaySecretResolution = ensureOwnerDisplaySecret(cfg, () => pendingSecret ?? crypto.randomBytes(32).toString("hex"));
3753
+ const cfgWithOwnerDisplaySecret = ownerDisplaySecretResolution.config;
3754
+ if (ownerDisplaySecretResolution.generatedSecret) {
3755
+ AUTO_OWNER_DISPLAY_SECRET_BY_PATH.set(configPath, ownerDisplaySecretResolution.generatedSecret);
3756
+ if (!AUTO_OWNER_DISPLAY_SECRET_PERSIST_IN_FLIGHT.has(configPath)) {
3757
+ AUTO_OWNER_DISPLAY_SECRET_PERSIST_IN_FLIGHT.add(configPath);
3758
+ writeConfigFile(cfgWithOwnerDisplaySecret, { expectedConfigPath: configPath }).then(() => {
3759
+ AUTO_OWNER_DISPLAY_SECRET_BY_PATH.delete(configPath);
3760
+ AUTO_OWNER_DISPLAY_SECRET_PERSIST_WARNED.delete(configPath);
3761
+ }).catch((err) => {
3762
+ if (!AUTO_OWNER_DISPLAY_SECRET_PERSIST_WARNED.has(configPath)) {
3763
+ AUTO_OWNER_DISPLAY_SECRET_PERSIST_WARNED.add(configPath);
3764
+ deps.logger.warn(`Failed to persist auto-generated commands.ownerDisplaySecret at ${configPath}: ${String(err)}`);
3765
+ }
3766
+ }).finally(() => {
3767
+ AUTO_OWNER_DISPLAY_SECRET_PERSIST_IN_FLIGHT.delete(configPath);
3768
+ });
3769
+ }
3770
+ } else {
3771
+ AUTO_OWNER_DISPLAY_SECRET_BY_PATH.delete(configPath);
3772
+ AUTO_OWNER_DISPLAY_SECRET_PERSIST_WARNED.delete(configPath);
3773
+ }
3774
+ return applyConfigOverrides(cfgWithOwnerDisplaySecret);
3775
+ } catch (err) {
3776
+ if (err instanceof DuplicateAgentDirError) {
3777
+ deps.logger.error(err.message);
3778
+ throw err;
3779
+ }
3780
+ if (err?.code === "INVALID_CONFIG") return {};
3781
+ deps.logger.error(`Failed to read config at ${configPath}`, err);
3782
+ return {};
3783
+ }
3784
+ }
3785
+ async function readConfigFileSnapshotInternal() {
3786
+ maybeLoadDotEnvForConfig(deps.env);
3787
+ if (!deps.fs.existsSync(configPath)) {
3788
+ const hash = hashConfigRaw(null);
3789
+ return { snapshot: {
3790
+ path: configPath,
3791
+ exists: false,
3792
+ raw: null,
3793
+ parsed: {},
3794
+ resolved: {},
3795
+ valid: true,
3796
+ config: applyTalkApiKey(applyTalkConfigNormalization(applyModelDefaults(applyContextPruningDefaults(applyAgentDefaults(applySessionDefaults(applyMessageDefaults({}))))))),
3797
+ hash,
3798
+ issues: [],
3799
+ warnings: [],
3800
+ legacyIssues: []
3801
+ } };
3802
+ }
3803
+ try {
3804
+ const raw = deps.fs.readFileSync(configPath, "utf-8");
3805
+ const hash = hashConfigRaw(raw);
3806
+ const parsedRes = parseConfigJson5(raw, deps.json5);
3807
+ if (!parsedRes.ok) return { snapshot: {
3808
+ path: configPath,
3809
+ exists: true,
3810
+ raw,
3811
+ parsed: {},
3812
+ resolved: {},
3813
+ valid: false,
3814
+ config: {},
3815
+ hash,
3816
+ issues: [{
3817
+ path: "",
3818
+ message: `JSON5 parse failed: ${parsedRes.error}`
3819
+ }],
3820
+ warnings: [],
3821
+ legacyIssues: []
3822
+ } };
3823
+ let resolved;
3824
+ try {
3825
+ resolved = resolveConfigIncludesForRead(parsedRes.parsed, configPath, deps);
3826
+ } catch (err) {
3827
+ const message = err instanceof ConfigIncludeError ? err.message : `Include resolution failed: ${String(err)}`;
3828
+ return { snapshot: {
3829
+ path: configPath,
3830
+ exists: true,
3831
+ raw,
3832
+ parsed: parsedRes.parsed,
3833
+ resolved: coerceConfig(parsedRes.parsed),
3834
+ valid: false,
3835
+ config: coerceConfig(parsedRes.parsed),
3836
+ hash,
3837
+ issues: [{
3838
+ path: "",
3839
+ message
3840
+ }],
3841
+ warnings: [],
3842
+ legacyIssues: []
3843
+ } };
3844
+ }
3845
+ let readResolution;
3846
+ try {
3847
+ readResolution = resolveConfigForRead(resolved, deps.env);
3848
+ } catch (err) {
3849
+ const message = err instanceof MissingEnvVarError ? err.message : `Env var substitution failed: ${String(err)}`;
3850
+ return { snapshot: {
3851
+ path: configPath,
3852
+ exists: true,
3853
+ raw,
3854
+ parsed: parsedRes.parsed,
3855
+ resolved: coerceConfig(resolved),
3856
+ valid: false,
3857
+ config: coerceConfig(resolved),
3858
+ hash,
3859
+ issues: [{
3860
+ path: "",
3861
+ message
3862
+ }],
3863
+ warnings: [],
3864
+ legacyIssues: []
3865
+ } };
3866
+ }
3867
+ const resolvedConfigRaw = readResolution.resolvedConfigRaw;
3868
+ const legacyIssues = findLegacyConfigIssues(resolvedConfigRaw);
3869
+ const validated = validateConfigObjectWithPlugins(resolvedConfigRaw);
3870
+ if (!validated.ok) return { snapshot: {
3871
+ path: configPath,
3872
+ exists: true,
3873
+ raw,
3874
+ parsed: parsedRes.parsed,
3875
+ resolved: coerceConfig(resolvedConfigRaw),
3876
+ valid: false,
3877
+ config: coerceConfig(resolvedConfigRaw),
3878
+ hash,
3879
+ issues: validated.issues,
3880
+ warnings: validated.warnings,
3881
+ legacyIssues
3882
+ } };
3883
+ warnIfConfigFromFuture(validated.config, deps.logger);
3884
+ const snapshotConfig = normalizeConfigPaths(applyTalkApiKey(applyTalkConfigNormalization(applyModelDefaults(applyAgentDefaults(applySessionDefaults(applyLoggingDefaults(applyMessageDefaults(validated.config))))))));
3885
+ return {
3886
+ snapshot: {
3887
+ path: configPath,
3888
+ exists: true,
3889
+ raw,
3890
+ parsed: parsedRes.parsed,
3891
+ resolved: coerceConfig(resolvedConfigRaw),
3892
+ valid: true,
3893
+ config: snapshotConfig,
3894
+ hash,
3895
+ issues: [],
3896
+ warnings: validated.warnings,
3897
+ legacyIssues
3898
+ },
3899
+ envSnapshotForRestore: readResolution.envSnapshotForRestore
3900
+ };
3901
+ } catch (err) {
3902
+ const nodeErr = err;
3903
+ let message;
3904
+ if (nodeErr?.code === "EACCES") {
3905
+ const uid = process.getuid?.();
3906
+ const uidHint = typeof uid === "number" ? String(uid) : "$(id -u)";
3907
+ message = [
3908
+ `read failed: ${String(err)}`,
3909
+ ``,
3910
+ `Config file is not readable by the current process. If running in a container`,
3911
+ `or 1-click deployment, fix ownership with:`,
3912
+ ` chown ${uidHint} "${configPath}"`,
3913
+ `Then restart the gateway.`
3914
+ ].join("\n");
3915
+ deps.logger.error(message);
3916
+ } else message = `read failed: ${String(err)}`;
3917
+ return { snapshot: {
3918
+ path: configPath,
3919
+ exists: true,
3920
+ raw: null,
3921
+ parsed: {},
3922
+ resolved: {},
3923
+ valid: false,
3924
+ config: {},
3925
+ hash: hashConfigRaw(null),
3926
+ issues: [{
3927
+ path: "",
3928
+ message
3929
+ }],
3930
+ warnings: [],
3931
+ legacyIssues: []
3932
+ } };
3933
+ }
3934
+ }
3935
+ async function readConfigFileSnapshot() {
3936
+ return (await readConfigFileSnapshotInternal()).snapshot;
3937
+ }
3938
+ async function readConfigFileSnapshotForWrite() {
3939
+ const result = await readConfigFileSnapshotInternal();
3940
+ return {
3941
+ snapshot: result.snapshot,
3942
+ writeOptions: {
3943
+ envSnapshotForRestore: result.envSnapshotForRestore,
3944
+ expectedConfigPath: configPath
3945
+ }
3946
+ };
3947
+ }
3948
+ async function writeConfigFile(cfg, options = {}) {
3949
+ clearConfigCache();
3950
+ let persistCandidate = cfg;
3951
+ const { snapshot } = await readConfigFileSnapshotInternal();
3952
+ let envRefMap = null;
3953
+ let changedPaths = null;
3954
+ if (snapshot.valid && snapshot.exists) {
3955
+ const patch = createMergePatch(snapshot.config, cfg);
3956
+ persistCandidate = applyMergePatch(snapshot.resolved, patch);
3957
+ try {
3958
+ const resolvedIncludes = resolveConfigIncludes(snapshot.parsed, configPath, {
3959
+ readFile: (candidate) => deps.fs.readFileSync(candidate, "utf-8"),
3960
+ parseJson: (raw) => deps.json5.parse(raw)
3961
+ });
3962
+ const collected = /* @__PURE__ */ new Map();
3963
+ collectEnvRefPaths(resolvedIncludes, "", collected);
3964
+ if (collected.size > 0) {
3965
+ envRefMap = collected;
3966
+ changedPaths = /* @__PURE__ */ new Set();
3967
+ collectChangedPaths(snapshot.config, cfg, "", changedPaths);
3968
+ }
3969
+ } catch {
3970
+ envRefMap = null;
3971
+ }
3972
+ }
3973
+ const validated = validateConfigObjectRawWithPlugins(persistCandidate);
3974
+ if (!validated.ok) {
3975
+ const issue = validated.issues[0];
3976
+ const pathLabel = issue?.path ? issue.path : "<root>";
3977
+ const issueMessage = issue?.message ?? "invalid";
3978
+ throw new Error(formatConfigValidationFailure(pathLabel, issueMessage));
3979
+ }
3980
+ if (validated.warnings.length > 0) {
3981
+ const details = validated.warnings.map((warning) => `- ${warning.path}: ${warning.message}`).join("\n");
3982
+ deps.logger.warn(`Config warnings:\n${details}`);
3983
+ }
3984
+ let cfgToWrite = validated.config;
3985
+ try {
3986
+ if (deps.fs.existsSync(configPath)) {
3987
+ const parsedRes = parseConfigJson5(await deps.fs.promises.readFile(configPath, "utf-8"), deps.json5);
3988
+ if (parsedRes.ok) {
3989
+ const envForRestore = options.envSnapshotForRestore ?? deps.env;
3990
+ cfgToWrite = restoreEnvVarRefs(cfgToWrite, parsedRes.parsed, envForRestore);
3991
+ }
3992
+ }
3993
+ } catch {}
3994
+ const dir = path.dirname(configPath);
3995
+ await deps.fs.promises.mkdir(dir, {
3996
+ recursive: true,
3997
+ mode: 448
3998
+ });
3999
+ let outputConfig = envRefMap && changedPaths ? restoreEnvRefsFromMap(cfgToWrite, "", envRefMap, changedPaths) : cfgToWrite;
4000
+ if (options.unsetPaths?.length) for (const unsetPath of options.unsetPaths) {
4001
+ if (!Array.isArray(unsetPath) || unsetPath.length === 0) continue;
4002
+ const unsetResult = unsetPathForWrite(outputConfig, unsetPath);
4003
+ if (unsetResult.changed) outputConfig = unsetResult.next;
4004
+ }
4005
+ const stampedOutputConfig = stampConfigVersion(outputConfig);
4006
+ const json = JSON.stringify(stampedOutputConfig, null, 2).trimEnd().concat("\n");
4007
+ const nextHash = hashConfigRaw(json);
4008
+ const previousHash = resolveConfigSnapshotHash(snapshot);
4009
+ const changedPathCount = changedPaths?.size;
4010
+ const previousBytes = typeof snapshot.raw === "string" ? Buffer.byteLength(snapshot.raw, "utf-8") : null;
4011
+ const nextBytes = Buffer.byteLength(json, "utf-8");
4012
+ const hasMetaBefore = hasConfigMeta(snapshot.parsed);
4013
+ const hasMetaAfter = hasConfigMeta(stampedOutputConfig);
4014
+ const gatewayModeBefore = resolveGatewayMode(snapshot.resolved);
4015
+ const gatewayModeAfter = resolveGatewayMode(stampedOutputConfig);
4016
+ const suspiciousReasons = resolveConfigWriteSuspiciousReasons({
4017
+ existsBefore: snapshot.exists,
4018
+ previousBytes,
4019
+ nextBytes,
4020
+ hasMetaBefore,
4021
+ gatewayModeBefore,
4022
+ gatewayModeAfter
4023
+ });
4024
+ const logConfigOverwrite = () => {
4025
+ if (!snapshot.exists) return;
4026
+ const isVitest = deps.env.VITEST === "true";
4027
+ const shouldLogInVitest = deps.env.REMOTECLAW_TEST_CONFIG_OVERWRITE_LOG === "1";
4028
+ if (isVitest && !shouldLogInVitest) return;
4029
+ const changeSummary = typeof changedPathCount === "number" ? `, changedPaths=${changedPathCount}` : "";
4030
+ deps.logger.warn(`Config overwrite: ${configPath} (sha256 ${previousHash ?? "unknown"} -> ${nextHash}, backup=${configPath}.bak${changeSummary})`);
4031
+ };
4032
+ const logConfigWriteAnomalies = () => {
4033
+ if (suspiciousReasons.length === 0) return;
4034
+ const isVitest = deps.env.VITEST === "true";
4035
+ const shouldLogInVitest = deps.env.REMOTECLAW_TEST_CONFIG_WRITE_ANOMALY_LOG === "1";
4036
+ if (isVitest && !shouldLogInVitest) return;
4037
+ deps.logger.warn(`Config write anomaly: ${configPath} (${suspiciousReasons.join(", ")})`);
4038
+ };
4039
+ const auditRecordBase = {
4040
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
4041
+ source: "config-io",
4042
+ event: "config.write",
4043
+ configPath,
4044
+ pid: process.pid,
4045
+ ppid: process.ppid,
4046
+ cwd: process.cwd(),
4047
+ argv: process.argv.slice(0, 8),
4048
+ execArgv: process.execArgv.slice(0, 8),
4049
+ watchMode: deps.env.REMOTECLAW_WATCH_MODE === "1",
4050
+ watchSession: typeof deps.env.REMOTECLAW_WATCH_SESSION === "string" && deps.env.REMOTECLAW_WATCH_SESSION.trim().length > 0 ? deps.env.REMOTECLAW_WATCH_SESSION.trim() : null,
4051
+ watchCommand: typeof deps.env.REMOTECLAW_WATCH_COMMAND === "string" && deps.env.REMOTECLAW_WATCH_COMMAND.trim().length > 0 ? deps.env.REMOTECLAW_WATCH_COMMAND.trim() : null,
4052
+ existsBefore: snapshot.exists,
4053
+ previousHash: previousHash ?? null,
4054
+ nextHash,
4055
+ previousBytes,
4056
+ nextBytes,
4057
+ changedPathCount: typeof changedPathCount === "number" ? changedPathCount : null,
4058
+ hasMetaBefore,
4059
+ hasMetaAfter,
4060
+ gatewayModeBefore,
4061
+ gatewayModeAfter,
4062
+ suspicious: suspiciousReasons
4063
+ };
4064
+ const appendWriteAudit = async (result, err) => {
4065
+ const errorCode = err && typeof err === "object" && "code" in err && typeof err.code === "string" ? err.code : void 0;
4066
+ const errorMessage = err && typeof err === "object" && "message" in err && typeof err.message === "string" ? err.message : void 0;
4067
+ await appendConfigWriteAuditRecord(deps, {
4068
+ ...auditRecordBase,
4069
+ result,
4070
+ nextHash: result === "failed" ? null : auditRecordBase.nextHash,
4071
+ nextBytes: result === "failed" ? null : auditRecordBase.nextBytes,
4072
+ errorCode,
4073
+ errorMessage
4074
+ });
4075
+ };
4076
+ const tmp = path.join(dir, `${path.basename(configPath)}.${process.pid}.${crypto.randomUUID()}.tmp`);
4077
+ try {
4078
+ await deps.fs.promises.writeFile(tmp, json, {
4079
+ encoding: "utf-8",
4080
+ mode: 384
4081
+ });
4082
+ if (deps.fs.existsSync(configPath)) {
4083
+ await rotateConfigBackups(configPath, deps.fs.promises);
4084
+ await deps.fs.promises.copyFile(configPath, `${configPath}.bak`).catch(() => {});
4085
+ }
4086
+ try {
4087
+ await deps.fs.promises.rename(tmp, configPath);
4088
+ } catch (err) {
4089
+ const code = err.code;
4090
+ if (code === "EPERM" || code === "EEXIST") {
4091
+ await deps.fs.promises.copyFile(tmp, configPath);
4092
+ await deps.fs.promises.chmod(configPath, 384).catch(() => {});
4093
+ await deps.fs.promises.unlink(tmp).catch(() => {});
4094
+ logConfigOverwrite();
4095
+ logConfigWriteAnomalies();
4096
+ await appendWriteAudit("copy-fallback");
4097
+ return;
4098
+ }
4099
+ await deps.fs.promises.unlink(tmp).catch(() => {});
4100
+ throw err;
4101
+ }
4102
+ logConfigOverwrite();
4103
+ logConfigWriteAnomalies();
4104
+ await appendWriteAudit("rename");
4105
+ } catch (err) {
4106
+ await appendWriteAudit("failed", err);
4107
+ throw err;
4108
+ }
4109
+ }
4110
+ return {
4111
+ configPath,
4112
+ loadConfig,
4113
+ readConfigFileSnapshot,
4114
+ readConfigFileSnapshotForWrite,
4115
+ writeConfigFile
4116
+ };
4117
+ }
4118
+ const DEFAULT_CONFIG_CACHE_MS = 200;
4119
+ const AUTO_OWNER_DISPLAY_SECRET_BY_PATH = /* @__PURE__ */ new Map();
4120
+ const AUTO_OWNER_DISPLAY_SECRET_PERSIST_IN_FLIGHT = /* @__PURE__ */ new Set();
4121
+ const AUTO_OWNER_DISPLAY_SECRET_PERSIST_WARNED = /* @__PURE__ */ new Set();
4122
+ let configCache = null;
4123
+ function resolveConfigCacheMs(env) {
4124
+ const raw = env.REMOTECLAW_CONFIG_CACHE_MS?.trim();
4125
+ if (raw === "" || raw === "0") return 0;
4126
+ if (!raw) return DEFAULT_CONFIG_CACHE_MS;
4127
+ const parsed = Number.parseInt(raw, 10);
4128
+ if (!Number.isFinite(parsed)) return DEFAULT_CONFIG_CACHE_MS;
4129
+ return Math.max(0, parsed);
4130
+ }
4131
+ function shouldUseConfigCache(env) {
4132
+ if (env.REMOTECLAW_DISABLE_CONFIG_CACHE?.trim()) return false;
4133
+ return resolveConfigCacheMs(env) > 0;
4134
+ }
4135
+ function clearConfigCache() {
4136
+ configCache = null;
4137
+ }
4138
+ function loadConfig() {
4139
+ const io = createConfigIO();
4140
+ const configPath = io.configPath;
4141
+ const now = Date.now();
4142
+ if (shouldUseConfigCache(process.env)) {
4143
+ const cached = configCache;
4144
+ if (cached && cached.configPath === configPath && cached.expiresAt > now) return cached.config;
4145
+ }
4146
+ const config = io.loadConfig();
4147
+ if (shouldUseConfigCache(process.env)) {
4148
+ const cacheMs = resolveConfigCacheMs(process.env);
4149
+ if (cacheMs > 0) configCache = {
4150
+ configPath,
4151
+ expiresAt: now + cacheMs,
4152
+ config
4153
+ };
4154
+ }
4155
+ return config;
4156
+ }
4157
+ async function readConfigFileSnapshot() {
4158
+ return await createConfigIO().readConfigFileSnapshot();
4159
+ }
4160
+ async function readConfigFileSnapshotForWrite() {
4161
+ return await createConfigIO().readConfigFileSnapshotForWrite();
4162
+ }
4163
+ async function writeConfigFile(cfg, options = {}) {
4164
+ const io = createConfigIO();
4165
+ const sameConfigPath = options.expectedConfigPath === void 0 || options.expectedConfigPath === io.configPath;
4166
+ await io.writeConfigFile(cfg, {
4167
+ envSnapshotForRestore: sameConfigPath ? options.envSnapshotForRestore : void 0,
4168
+ unsetPaths: options.unsetPaths
4169
+ });
4170
+ }
4171
+
4172
+ //#endregion
4173
+ //#region src/config/legacy-migrate.ts
4174
+ function migrateLegacyConfig(raw) {
4175
+ const { next, changes } = applyLegacyMigrations(raw);
4176
+ if (!next) return {
4177
+ config: null,
4178
+ changes: []
4179
+ };
4180
+ const validated = validateConfigObjectWithPlugins(next);
4181
+ if (!validated.ok) {
4182
+ changes.push("Migration applied, but config still invalid; fix remaining issues manually.");
4183
+ return {
4184
+ config: null,
4185
+ changes
4186
+ };
4187
+ }
4188
+ return {
4189
+ config: validated.config,
4190
+ changes
4191
+ };
4192
+ }
4193
+
4194
+ //#endregion
4195
+ //#region src/config/config.ts
4196
+ var config_exports = /* @__PURE__ */ __exportAll({
4197
+ CONFIG_PATH: () => CONFIG_PATH,
4198
+ DEFAULT_GATEWAY_PORT: () => DEFAULT_GATEWAY_PORT,
4199
+ STATE_DIR: () => STATE_DIR,
4200
+ TOOLS_BY_SENDER_KEY_TYPES: () => TOOLS_BY_SENDER_KEY_TYPES,
4201
+ applyConfigOverrides: () => applyConfigOverrides,
4202
+ getConfigOverrides: () => getConfigOverrides,
4203
+ isNixMode: () => isNixMode,
4204
+ loadConfig: () => loadConfig,
4205
+ parseToolsBySenderTypedKey: () => parseToolsBySenderTypedKey,
4206
+ resetConfigOverrides: () => resetConfigOverrides,
4207
+ resolveCanonicalConfigPath: () => resolveCanonicalConfigPath,
4208
+ resolveConfigPath: () => resolveConfigPath,
4209
+ resolveConfigPathCandidate: () => resolveConfigPathCandidate,
4210
+ resolveDefaultConfigCandidates: () => resolveDefaultConfigCandidates,
4211
+ resolveGatewayLockDir: () => resolveGatewayLockDir,
4212
+ resolveGatewayPort: () => resolveGatewayPort,
4213
+ resolveIsNixMode: () => resolveIsNixMode,
4214
+ resolveLegacyStateDirs: () => resolveLegacyStateDirs,
4215
+ resolveNewStateDir: () => resolveNewStateDir,
4216
+ resolveOAuthDir: () => resolveOAuthDir,
4217
+ resolveStateDir: () => resolveStateDir,
4218
+ setConfigOverride: () => setConfigOverride,
4219
+ unsetConfigOverride: () => unsetConfigOverride
4220
+ });
4221
+
4222
+ //#endregion
4223
+ export { applyTestPluginDefaults as A, unsetConfigValueAtPath as B, discoverRemoteClawPlugins as C, LEGACY_MANIFEST_KEYS as D, loadPluginManifest as E, setConfigOverride as F, extensionUsesSkippedScannerPath as G, applyLegacyMigrations as H, unsetConfigOverride as I, buildTalkConfigResponse as J, isPathInside$1 as K, getConfigValueAtPath as L, resolveEffectiveEnableState as M, getConfigOverrides as N, MANIFEST_KEY as O, resetConfigOverrides as P, loadDotEnv as Q, parseConfigPath as R, loadPluginManifestRegistry as S, safeStatSync as T, INCLUDE_KEY as U, applyMergePatch as V, MAX_INCLUDE_DEPTH as W, resolveAgentMaxConcurrent as X, DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH as Y, resolveSubagentMaxConcurrent as Z, isWorkspaceRelativeAvatarPath as _, parseConfigJson5 as a, validateJsonSchemaValue as b, resolveConfigSnapshotHash as c, AVATAR_MAX_BYTES as d, isAvatarDataUrl as f, isSupportedLocalAvatarExtension as g, isPathWithinRoot as h, loadConfig as i, normalizePluginsConfig as j, resolveBundledPluginsDir as k, writeConfigFile as l, isAvatarImageDataUrl as m, migrateLegacyConfig as n, readConfigFileSnapshot as o, isAvatarHttpUrl as p, isPathInsideWithRealpath as q, createConfigIO as r, readConfigFileSnapshotForWrite as s, config_exports as t, validateConfigObjectWithPlugins as u, looksLikeAvatarPath as v, isPathInside as w, clearPluginManifestRegistryCache as x, resolveAvatarMime as y, setConfigValueAtPath as z };