@noxsoft/anima 2.0.2 → 2.0.4

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 (829) hide show
  1. package/README.md +1260 -28
  2. package/dist/accounts-Bth3PpPD.js +260 -0
  3. package/dist/accounts-D8CPKNkN.js +259 -0
  4. package/dist/acp-cli-ByK6lS6c.js +1081 -0
  5. package/dist/acp-cli-CaQCjIw4.js +1084 -0
  6. package/dist/agent-BgIkqd3F.js +725 -0
  7. package/dist/agent-N5BDcge4.js +725 -0
  8. package/dist/agent-events-COH7NDW2.js +182 -0
  9. package/dist/agent-scope-CPphqq-U.js +452 -0
  10. package/dist/agent-scope-DZgptr9J.js +452 -0
  11. package/dist/agent-scope-cj2QCT6R.js +112 -0
  12. package/dist/agents-NEudYMdg.js +774 -0
  13. package/dist/agents.config-Bujs-NIy.js +182 -0
  14. package/dist/agents.config-jp7OLssr.js +182 -0
  15. package/dist/argv-BMZMiW7v.js +73 -0
  16. package/dist/audit-C-UJhfdv.js +2401 -0
  17. package/dist/audit-CeCO7SK5.js +2401 -0
  18. package/dist/auth-BNZsOHGF.js +648 -0
  19. package/dist/auth-DMPZWzEa.js +639 -0
  20. package/dist/auth-choice-5VnaGMD-.js +2681 -0
  21. package/dist/auth-choice-DA2k4vs8.js +2681 -0
  22. package/dist/auth-health-B7FqA26_.js +149 -0
  23. package/dist/auth-health-VO_MPqVX.js +149 -0
  24. package/dist/auth-profiles-BDrNYX_n.js +1564 -0
  25. package/dist/auth-profiles-CxSHydjn.js +2689 -0
  26. package/dist/banner-BtDZPRzi.js +294 -0
  27. package/dist/browser-cli-8yQMpxb8.js +1679 -0
  28. package/dist/browser-cli-Czg3JtDH.js +1676 -0
  29. package/dist/build-info.json +3 -3
  30. package/dist/bundled/boot-md/handler.js +16 -16
  31. package/dist/bundled/bootstrap-extra-files/handler.js +4 -4
  32. package/dist/bundled/command-logger/handler.js +1 -1
  33. package/dist/bundled/session-memory/handler.js +5 -5
  34. package/dist/call-BIzCaKZb.js +282 -0
  35. package/dist/call-BYDpTVCZ.js +282 -0
  36. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  37. package/dist/catalog-CqKiUgu6.js +185 -0
  38. package/dist/catalog-DMfEg-oK.js +185 -0
  39. package/dist/channel-options-BrtCtyrT.js +32 -0
  40. package/dist/channel-options-CO21Gl8p.js +33 -0
  41. package/dist/channel-selection-Bbm1lq3P.js +51 -0
  42. package/dist/channel-selection-CqcX7Ocw.js +51 -0
  43. package/dist/channel-web-DrsT6OAE.js +2162 -0
  44. package/dist/channels-cli-Juyh1S6n.js +1304 -0
  45. package/dist/channels-cli-zNvi1m5c.js +1306 -0
  46. package/dist/channels-status-issues-CqzqshW4.js +18 -0
  47. package/dist/channels-status-issues-DdJdO866.js +18 -0
  48. package/dist/chrome-C4dOMO8z.js +1601 -0
  49. package/dist/chrome-DdcDzAtH.js +1629 -0
  50. package/dist/chrome-U3DRzjJD.js +1601 -0
  51. package/dist/chunk-D2nLsrEW.js +348 -0
  52. package/dist/clack-prompter-BI3RDW5w.js +92 -0
  53. package/dist/clack-prompter-Dwr1m_IZ.js +92 -0
  54. package/dist/cli/daemon-cli.js +1 -1
  55. package/dist/cli-C3cpDaz8.js +99 -0
  56. package/dist/cli-CjWUGdGC.js +101 -0
  57. package/dist/cli-session-BVjY_XrW.js +5463 -0
  58. package/dist/cli-session-gtuYN2Iq.js +5408 -0
  59. package/dist/client-Dswwze5_.js +1692 -0
  60. package/dist/client-LRKFjo4A.js +1692 -0
  61. package/dist/clipboard-BZKS9O1u.js +31 -0
  62. package/dist/clipboard-DES8b1AM.js +31 -0
  63. package/dist/command-format-CP1YTNCl.js +52 -0
  64. package/dist/command-format-CVL4K5cj.js +52 -0
  65. package/dist/command-format-G6N2zghg.js +38 -0
  66. package/dist/command-registry-BBvNvysr.js +248 -0
  67. package/dist/commands-AZ3n8Y2c.js +726 -0
  68. package/dist/commands-BMnD_QRY.js +726 -0
  69. package/dist/commands-registry-cFqZ6Ib4.js +766 -0
  70. package/dist/commands-registry-q13H7ng5.js +766 -0
  71. package/dist/common-CX5458fH.js +287 -0
  72. package/dist/common-DJbnT8ws.js +287 -0
  73. package/dist/completion-cli-BADRBcIl.js +432 -0
  74. package/dist/completion-cli-DMQgiObF.js +431 -0
  75. package/dist/config-CU-Axg8P.js +5704 -0
  76. package/dist/config-DaqbUdkI.js +5705 -0
  77. package/dist/config-cli-BPlbwiuA.js +244 -0
  78. package/dist/config-cli-DXgZJkPU.js +247 -0
  79. package/dist/config-guard-Ba49JNds.js +76 -0
  80. package/dist/config-guard-Cu0qMKZJ.js +93 -0
  81. package/dist/config-kVVm5EYV.js +6523 -0
  82. package/dist/config-sync-CzLnLTXt.js +91 -0
  83. package/dist/config-sync-DuydxPWx.js +91 -0
  84. package/dist/configure-CHgacLyi.js +960 -0
  85. package/dist/configure-DfHXDa1L.js +959 -0
  86. package/dist/context-DzgXOckU.js +60 -0
  87. package/dist/control-service-8_wKHwBa.js +72 -0
  88. package/dist/control-service-BtL1Jto_.js +72 -0
  89. package/dist/cron-cli-BCzSR2c0.js +448 -0
  90. package/dist/cron-cli-CCWNkykU.js +451 -0
  91. package/dist/daemon-cli-Bjkbu9Vy.js +565 -0
  92. package/dist/daemon-cli-CmlHcC1J.js +566 -0
  93. package/dist/daemon-cli.js +16 -16
  94. package/dist/daemon-runtime-C0tz7VAC.js +460 -0
  95. package/dist/daemon-runtime-rUTqCVwJ.js +460 -0
  96. package/dist/deliver-BBggsviM.js +1097 -0
  97. package/dist/deliver-CePITOl8.js +1162 -0
  98. package/dist/deliver-DFnVaetP.js +1097 -0
  99. package/dist/delivery-queue-BJQK3oh5.js +220 -0
  100. package/dist/deps-CeEKhrp7.js +42 -0
  101. package/dist/devices-cli-DQrDMrZH.js +198 -0
  102. package/dist/devices-cli-Oe-A1Dv0.js +195 -0
  103. package/dist/diagnostics-DxMFrBLO.js +35 -0
  104. package/dist/diagnostics-m79ZlMmZ.js +35 -0
  105. package/dist/directory-cli-BL6h8cGF.js +246 -0
  106. package/dist/directory-cli-Cjgmi_sj.js +243 -0
  107. package/dist/dispatcher-DAFbQM-c.js +100 -0
  108. package/dist/dispatcher-DNd40gUn.js +100 -0
  109. package/dist/dist-CqDI82ei.js +929 -0
  110. package/dist/dist-DnHRxR5U.js +929 -0
  111. package/dist/dns-cli-CFtV3BXK.js +200 -0
  112. package/dist/dns-cli-NyIHvQ5S.js +197 -0
  113. package/dist/dock-BdXLb5oY.js +753 -0
  114. package/dist/dock-jYICmNcI.js +753 -0
  115. package/dist/docs-cli-CrOaIK_H.js +161 -0
  116. package/dist/docs-cli-D_cmJDSr.js +159 -0
  117. package/dist/doctor-BpGxKrBl.js +1815 -0
  118. package/dist/doctor-D12wNQPU.js +1813 -0
  119. package/dist/doctor-completion-DeOfofek.js +92 -0
  120. package/dist/doctor-completion-DwjqdEcK.js +92 -0
  121. package/dist/doctor-config-flow-BI3mpkbd.js +1232 -0
  122. package/dist/doctor-config-flow-wMHheFkC.js +1232 -0
  123. package/dist/engine-BCtL-AMw.js +563 -0
  124. package/dist/engine-Bk_UT413.js +563 -0
  125. package/dist/entry.js +5 -5
  126. package/dist/env-v6411I8h.js +32 -0
  127. package/dist/exec-B7sUS164.js +1167 -0
  128. package/dist/exec-approvals-CroGJRUg.js +1221 -0
  129. package/dist/exec-approvals-cli-BTxF_RsH.js +371 -0
  130. package/dist/exec-approvals-cli-n1gyGwH2.js +368 -0
  131. package/dist/exec-mhSykkaa.js +255 -0
  132. package/dist/extensionAPI.js +3 -3
  133. package/dist/frontmatter-BmHq0vRD.js +204 -0
  134. package/dist/gateway-cli-DDBadlrS.js +19971 -0
  135. package/dist/gateway-cli-IZNkOMBe.js +19972 -0
  136. package/dist/gateway-rpc-Dtx8HN-n.js +28 -0
  137. package/dist/gateway-rpc-L2PVSqGj.js +28 -0
  138. package/dist/github-copilot-auth-DKyqDaGU.js +1418 -0
  139. package/dist/github-copilot-auth-DXpOMSd3.js +1418 -0
  140. package/dist/gmail-setup-utils-BKNczIJ9.js +428 -0
  141. package/dist/gmail-setup-utils-co0ppccC.js +428 -0
  142. package/dist/health-Bm8ZTvC3.js +1253 -0
  143. package/dist/health-DUf1gt4E.js +1258 -0
  144. package/dist/health-format-BksT6F68.js +208 -0
  145. package/dist/health-format-uzh1xYLD.js +208 -0
  146. package/dist/heartbeat-visibility-1TJb1Zao.js +98 -0
  147. package/dist/heartbeat-visibility-CwodtdcX.js +98 -0
  148. package/dist/help-format-C6cv_aZp.js +17 -0
  149. package/dist/helpers-N-uSFKOn.js +10 -0
  150. package/dist/hooks-cli-1POsXqOl.js +993 -0
  151. package/dist/hooks-cli-BGjILbze.js +991 -0
  152. package/dist/hooks-status-DE07n5RC.js +356 -0
  153. package/dist/hooks-status-Du-d1jde.js +356 -0
  154. package/dist/image-ops-B_AYV3tp.js +541 -0
  155. package/dist/image-ops-Bp0C6Mvr.js +541 -0
  156. package/dist/index.js +82 -82
  157. package/dist/init-9A0s7bWG.js +122 -0
  158. package/dist/init-DoyCHJDC.js +122 -0
  159. package/dist/installs-D1C9wHAq.js +383 -0
  160. package/dist/installs-Dh4dHayM.js +383 -0
  161. package/dist/ipv4-DCItfaJo.js +1964 -0
  162. package/dist/ipv4-DSOUVx0i.js +1964 -0
  163. package/dist/lanes-BvSnHq2h.js +232 -0
  164. package/dist/lifecycle-core-BY4WIf9g.js +388 -0
  165. package/dist/lifecycle-core-TQKyXO-6.js +387 -0
  166. package/dist/links-CNu_8RZl.js +15 -0
  167. package/dist/links-D2tt2ouh.js +15 -0
  168. package/dist/llm-slug-generator.js +4 -4
  169. package/dist/logging-BIeRw0WR.js +15 -0
  170. package/dist/logging-C7lb3Vjc.js +15 -0
  171. package/dist/login-DXWKewA2.js +59 -0
  172. package/dist/login-Fhh4uWmf.js +61 -0
  173. package/dist/login-pPs3UO38.js +61 -0
  174. package/dist/login-qr-CevLD8cV.js +326 -0
  175. package/dist/login-qr-GF2JMIy-.js +323 -0
  176. package/dist/login-qr-ZYYKD6Yt.js +321 -0
  177. package/dist/logs-cli-CzXbX8HZ.js +242 -0
  178. package/dist/logs-cli-D9ngH9PF.js +245 -0
  179. package/dist/manager-BD5rA3w0.js +3244 -0
  180. package/dist/manager-BDPgBQSH.js +3246 -0
  181. package/dist/manager-DRWMWM--.js +3244 -0
  182. package/dist/manifest-registry-DbvPaBXY.js +748 -0
  183. package/dist/manifest-registry-kHX_MFa1.js +748 -0
  184. package/dist/markdown-tables-CqwihY2m.js +347 -0
  185. package/dist/markdown-tables-DJV7eAJZ.js +348 -0
  186. package/dist/media-lUqN-0O9.js +1342 -0
  187. package/dist/memory-cli-BLXSpgnN.js +868 -0
  188. package/dist/memory-cli-BcGVkkRJ.js +869 -0
  189. package/dist/message-channel-D_jIO87f.js +110 -0
  190. package/dist/migrate-BpVOar4L.js +157 -0
  191. package/dist/migrate-CkgGDkWy.js +157 -0
  192. package/dist/model-selection-Cqt6aJ0G.js +2691 -0
  193. package/dist/models-CExsNQPH.js +2510 -0
  194. package/dist/models-cli-Ba3Jmwev.js +2739 -0
  195. package/dist/models-cli-iDAlsbL2.js +258 -0
  196. package/dist/net-0A_zcaQD.js +218 -0
  197. package/dist/node-cli-ATmwCXIk.js +1319 -0
  198. package/dist/node-cli-DYFR_V25.js +1322 -0
  199. package/dist/node-service-CN4LqR1A.js +67 -0
  200. package/dist/node-service-CWt3MdSC.js +67 -0
  201. package/dist/nodes-cli-BeVmhTz3.js +1197 -0
  202. package/dist/nodes-cli-QeJIfa18.js +1200 -0
  203. package/dist/nodes-screen-DHyWAlla.js +234 -0
  204. package/dist/nodes-screen-qs3jRBPk.js +234 -0
  205. package/dist/note-CSlg2BnB.js +73 -0
  206. package/dist/note-Ctvglhp1.js +73 -0
  207. package/dist/npm-registry-spec-DQd4M22q.js +351 -0
  208. package/dist/npm-registry-spec-PxisIMts.js +351 -0
  209. package/dist/onboard-DeruD10m.js +1166 -0
  210. package/dist/onboard-SAcu5N6N.js +1165 -0
  211. package/dist/onboard-channels-C4iSfFXR.js +672 -0
  212. package/dist/onboard-channels-oVTVgoyg.js +672 -0
  213. package/dist/onboard-helpers-B8roRwLP.js +365 -0
  214. package/dist/onboard-helpers-Dgh26hgP.js +365 -0
  215. package/dist/onboarding-Bi-ac8we.js +911 -0
  216. package/dist/onboarding-C2gjB2u8.js +910 -0
  217. package/dist/orchestrator-DlbAYMQP.js +357 -0
  218. package/dist/orchestrator-DlwVRVDA.js +357 -0
  219. package/dist/outbound-CkKgc6iR.js +2062 -0
  220. package/dist/outbound-Vfm5yDh3.js +214 -0
  221. package/dist/outbound-bs_VK51X.js +214 -0
  222. package/dist/outbound-send-deps-DDjiMfEL.js +55 -0
  223. package/dist/pairing-cli-CJYeuEik.js +118 -0
  224. package/dist/pairing-cli-mqopHI8s.js +121 -0
  225. package/dist/pairing-store-BsXzUDPv.js +388 -0
  226. package/dist/pairing-store-DoNj00-X.js +388 -0
  227. package/dist/path-env-C_xpiG8l.js +89 -0
  228. package/dist/path-env-DSSMHu5A.js +89 -0
  229. package/dist/paths-B1vRVCad.js +126 -0
  230. package/dist/paths-BMuHNFxg.js +238 -0
  231. package/dist/paths-BXQQzXGQ.js +129 -0
  232. package/dist/paths-Buw_geoe.js +54 -0
  233. package/dist/paths-DA9WYabg.js +222 -0
  234. package/dist/paths-DfQGx0_k.js +129 -0
  235. package/dist/pi-auth-json-DOPW3e4X.js +78 -0
  236. package/dist/pi-auth-json-MruLmI_X.js +82 -0
  237. package/dist/pi-auth-json-lae_wwwo.js +80 -0
  238. package/dist/pi-model-discovery-7q0GxMrp.js +3 -0
  239. package/dist/pi-tools.policy-Csmla32P.js +200 -0
  240. package/dist/pi-tools.policy-xYdDLEv9.js +200 -0
  241. package/dist/plugin-auto-enable-CViVVWgg.js +282 -0
  242. package/dist/plugin-auto-enable-CjZ238UI.js +282 -0
  243. package/dist/plugin-registry-B4Aw2hzq.js +32 -0
  244. package/dist/plugin-registry-DW81arxW.js +32 -0
  245. package/dist/plugin-sdk/cli/cli-name.d.ts +1 -1
  246. package/dist/plugin-sdk/config/paths.d.ts +2 -2
  247. package/dist/plugin-sdk/index.js +7 -7
  248. package/dist/plugins-DhcGAPDB.js +38 -0
  249. package/dist/plugins-DtghNRtM.js +168 -0
  250. package/dist/plugins-cli-4vWTmOAb.js +736 -0
  251. package/dist/plugins-cli-CdTMbP0X.js +734 -0
  252. package/dist/polls-D6eCdatA.js +1343 -0
  253. package/dist/ports-BtZx-JKD.js +96 -0
  254. package/dist/ports-C8bKN8s0.js +96 -0
  255. package/dist/ports-DHiKnPRX.js +344 -0
  256. package/dist/ports-vd93M_Pt.js +317 -0
  257. package/dist/program-CX3aUVeb.js +176 -0
  258. package/dist/program-context-BPos0ivo.js +496 -0
  259. package/dist/progress-oiAjiiNi.js +133 -0
  260. package/dist/prompt-style-Cm4wOtKm.js +9 -0
  261. package/dist/pw-ai-4QbK5YFe.js +1865 -0
  262. package/dist/pw-ai-BWz3Cxt7.js +1868 -0
  263. package/dist/pw-ai-C83HBue2.js +1867 -0
  264. package/dist/qmd-manager-BcMeZiGD.js +938 -0
  265. package/dist/qmd-manager-CPypGJ0P.js +935 -0
  266. package/dist/qmd-manager-CRrSkfia.js +937 -0
  267. package/dist/register.agent-DDY8KJhn.js +265 -0
  268. package/dist/register.agent-DKawm-9d.js +1003 -0
  269. package/dist/register.anima-CEWUo29k.js +193 -0
  270. package/dist/register.anima-DBWz2rk_.js +193 -0
  271. package/dist/register.configure-BX67qV8k.js +103 -0
  272. package/dist/register.configure-CWsySuiq.js +101 -0
  273. package/dist/register.maintenance-0k-ZNhDg.js +543 -0
  274. package/dist/register.maintenance-BIwx1fzX.js +543 -0
  275. package/dist/register.message-CXPsoakA.js +657 -0
  276. package/dist/register.message-DA3jvfgI.js +660 -0
  277. package/dist/register.onboard-C4HG7Hqv.js +170 -0
  278. package/dist/register.onboard-GOpdif-j.js +170 -0
  279. package/dist/register.setup-B17vZT7C.js +175 -0
  280. package/dist/register.setup-GJyUDCqh.js +175 -0
  281. package/dist/register.status-health-sessions-D5876dGx.js +313 -0
  282. package/dist/register.status-health-sessions-lOewVIZR.js +142 -0
  283. package/dist/register.subclis-Dwnujj5C.js +255 -0
  284. package/dist/reply-CR5T_oQJ.js +32212 -0
  285. package/dist/reply-prefix-BcrS4Umd.js +100 -0
  286. package/dist/reply-prefix-Btb5o2NH.js +100 -0
  287. package/dist/reply-r089HuRA.js +32212 -0
  288. package/dist/routes-B4czFzIb.js +1820 -0
  289. package/dist/routes-ucJWAk5O.js +1820 -0
  290. package/dist/rpc-BnKxnQ0v.js +70 -0
  291. package/dist/rpc-DgE-xnyx.js +70 -0
  292. package/dist/run-main-B74kv84C.js +371 -0
  293. package/dist/runtime-guard-CKFdts2L.js +60 -0
  294. package/dist/sandbox-CJTS3er6.js +858 -0
  295. package/dist/sandbox-DBSiVHt_.js +859 -0
  296. package/dist/sandbox-cli-CrkjyU5M.js +461 -0
  297. package/dist/sandbox-cli-D1r5y6Sz.js +458 -0
  298. package/dist/security-cli-BZUdnkhn.js +462 -0
  299. package/dist/security-cli-DS09ebvA.js +465 -0
  300. package/dist/server-context-C0xZbYhg.js +824 -0
  301. package/dist/server-context-DVh2z7om.js +824 -0
  302. package/dist/server-node-events-bu9lpkMH.js +233 -0
  303. package/dist/server-node-events-i1Rrww31.js +231 -0
  304. package/dist/service-CJJwLEor.js +642 -0
  305. package/dist/service-DxLxBhaU.js +642 -0
  306. package/dist/service-audit-DB4Y3Ekp.js +488 -0
  307. package/dist/service-audit-M8y4TXVb.js +488 -0
  308. package/dist/session-CGxOLFs2.js +179 -0
  309. package/dist/session-DTTbdKb0.js +181 -0
  310. package/dist/session-cost-usage-FcdJl9c3.js +600 -0
  311. package/dist/session-cost-usage-qdfsGU2a.js +600 -0
  312. package/dist/session-yOhWcsD2.js +181 -0
  313. package/dist/sessions-B-Cu7JZq.js +1296 -0
  314. package/dist/sessions-BgLN4KFr.js +180 -0
  315. package/dist/sessions-CnRjwdVr.js +1296 -0
  316. package/dist/sessions-wRKla1Qh.js +2038 -0
  317. package/dist/shared-DS3UaJSP.js +66 -0
  318. package/dist/shared-DxNHzky3.js +77 -0
  319. package/dist/shared-Qpt4hUDi.js +66 -0
  320. package/dist/shared-kzrojZ1B.js +77 -0
  321. package/dist/skill-scanner-DLJji5Ye.js +263 -0
  322. package/dist/skills-BWFIEp4j.js +807 -0
  323. package/dist/skills-DV4zKdCx.js +808 -0
  324. package/dist/skills-cli-BY53ILm2.js +289 -0
  325. package/dist/skills-cli-CO3gxl8A.js +286 -0
  326. package/dist/skills-status-DX5pcqY3.js +166 -0
  327. package/dist/skills-status-zhcKzGkp.js +166 -0
  328. package/dist/sqlite-B6MojU1I.js +321 -0
  329. package/dist/sqlite-CuprTGR7.js +453 -0
  330. package/dist/sqlite-dzD-jMjs.js +368 -0
  331. package/dist/start-Cu3aLoSf.js +297 -0
  332. package/dist/start-Dz7tMAl8.js +296 -0
  333. package/dist/status-CaSxhxfV.js +2132 -0
  334. package/dist/status-D2C0JCX3.js +2137 -0
  335. package/dist/status-DlFMsQzh.js +27 -0
  336. package/dist/status-G0CITnKR.js +27 -0
  337. package/dist/status.update-CHjhVxJY.js +79 -0
  338. package/dist/status.update-DVFelehi.js +79 -0
  339. package/dist/subagent-registry-3Xb4el-8.js +14 -0
  340. package/dist/subagent-registry-CdSjz14I.js +2760 -0
  341. package/dist/subagent-registry-DNDhbHWi.js +2759 -0
  342. package/dist/subsystem-DfKstnEK.js +860 -0
  343. package/dist/system-cli-B5mt0FWa.js +82 -0
  344. package/dist/system-cli-Dg3UQ3Zz.js +79 -0
  345. package/dist/systemd-B43AvOGx.js +452 -0
  346. package/dist/systemd-RpPE0XGg.js +452 -0
  347. package/dist/systemd-hints-DMJT-Bbc.js +36 -0
  348. package/dist/systemd-hints-vRInKcz9.js +36 -0
  349. package/dist/systemd-linger-Dzyxqsod.js +75 -0
  350. package/dist/systemd-linger-EujbmI5A.js +75 -0
  351. package/dist/table-DhXHfRX2.js +279 -0
  352. package/dist/table-bWCLW-3P.js +279 -0
  353. package/dist/timeout-Ddn-5kAO.js +232 -0
  354. package/dist/tokens-3psI_Qk2.js +14 -0
  355. package/dist/tokens-BaM53PEx.js +14 -0
  356. package/dist/trash-Bmxs1Rnm.js +23 -0
  357. package/dist/trash-C39a6hKA.js +23 -0
  358. package/dist/tui-BHgBWhHE.js +3894 -0
  359. package/dist/tui-cli-B9Sq5-cC.js +50 -0
  360. package/dist/tui-cli-Dw7v4JoJ.js +47 -0
  361. package/dist/tui-mUwDwqvd.js +3894 -0
  362. package/dist/update-DF0GHG0j.js +317 -0
  363. package/dist/update-DoZLVjva.js +317 -0
  364. package/dist/update-check-Bt1dVPVN.js +400 -0
  365. package/dist/update-check-D5qAKes7.js +400 -0
  366. package/dist/update-cli-BNu2Oi7H.js +1105 -0
  367. package/dist/update-cli-D36AmALA.js +1105 -0
  368. package/dist/update-runner-CNQQaTwA.js +894 -0
  369. package/dist/update-runner-CvxZmbu-.js +894 -0
  370. package/dist/usage-BGCwNnjk.js +4516 -0
  371. package/dist/utils-DZ8pnOD5.js +243 -0
  372. package/dist/web-B5QG839O.js +46842 -0
  373. package/dist/web-Cmnvk9v0.js +2203 -0
  374. package/dist/web-Cv2KnTnL.js +63 -0
  375. package/dist/webhooks-cli-B6y89Pj_.js +319 -0
  376. package/dist/webhooks-cli-BDzHON4w.js +316 -0
  377. package/dist/whatsapp-actions-C_5MwVxM.js +45 -0
  378. package/dist/whatsapp-actions-hgYA12To.js +53 -0
  379. package/dist/whatsapp-actions-zTiVOoOV.js +49 -0
  380. package/dist/widearea-dns-BeIdnISJ.js +127 -0
  381. package/dist/widearea-dns-CF1gxpJ-.js +127 -0
  382. package/dist/workspace-DLna1IxR.js +649 -0
  383. package/dist/ws-log-Q4wO1Ztb.js +267 -0
  384. package/dist/ws-log-xF0kxDzp.js +267 -0
  385. package/package.json +1 -2
  386. package/dist/accounts-Cc5E4IDO.js +0 -260
  387. package/dist/accounts-CcVrwKqv.js +0 -259
  388. package/dist/acp-cli-DvphOKuh.js +0 -1081
  389. package/dist/acp-cli-p28pQ65a.js +0 -1084
  390. package/dist/agent-Cj7uDJaZ.js +0 -725
  391. package/dist/agent-Cuj9-2sT.js +0 -725
  392. package/dist/agent-events-BEBQsyE5.js +0 -182
  393. package/dist/agent-scope-BVf4aSwY.js +0 -112
  394. package/dist/agent-scope-OZi7lb8S.js +0 -452
  395. package/dist/agent-scope-V1bi9OYL.js +0 -452
  396. package/dist/agents-BUWqn_Ui.js +0 -774
  397. package/dist/agents.config-Dvo2ULxs.js +0 -182
  398. package/dist/agents.config-d6H0_3oj.js +0 -182
  399. package/dist/argv-DqUHKf0o.js +0 -73
  400. package/dist/audit-C6okOOSh.js +0 -2401
  401. package/dist/audit-VWjIdwC7.js +0 -2401
  402. package/dist/auth-91o2YM96.js +0 -648
  403. package/dist/auth-choice-CAmACV13.js +0 -2681
  404. package/dist/auth-choice-p3SeHPj2.js +0 -2681
  405. package/dist/auth-health-B_jXrWe6.js +0 -149
  406. package/dist/auth-health-DCicUKYR.js +0 -149
  407. package/dist/auth-lZ26wsbN.js +0 -639
  408. package/dist/auth-profiles-CCDD56dU.js +0 -1564
  409. package/dist/auth-profiles-DxI8L7bs.js +0 -2689
  410. package/dist/banner-Cohn04J6.js +0 -294
  411. package/dist/browser-cli-DANzjztE.js +0 -1676
  412. package/dist/browser-cli-WjsVH741.js +0 -1679
  413. package/dist/call-BAHvlu2G.js +0 -282
  414. package/dist/call-Ct7EGP_L.js +0 -282
  415. package/dist/catalog-BAayBt1L.js +0 -185
  416. package/dist/catalog-BNsf97BM.js +0 -185
  417. package/dist/channel-options-Dx9nPlX8.js +0 -33
  418. package/dist/channel-options-ZdvXrTGs.js +0 -32
  419. package/dist/channel-selection-CujyiWGM.js +0 -51
  420. package/dist/channel-selection-DfGpCyh2.js +0 -51
  421. package/dist/channel-web-CC0hkgkR.js +0 -2162
  422. package/dist/channels-cli-D7lNBpIb.js +0 -1304
  423. package/dist/channels-cli-DUPG8WDv.js +0 -1306
  424. package/dist/channels-status-issues-DBc1pU_R.js +0 -18
  425. package/dist/channels-status-issues-DjO9MHIG.js +0 -18
  426. package/dist/chrome-Bi6iZ5sG.js +0 -1601
  427. package/dist/chrome-DNSv7Cpy.js +0 -1629
  428. package/dist/chrome-DScZx4Lk.js +0 -1601
  429. package/dist/chunk-mxPVo000.js +0 -348
  430. package/dist/clack-prompter-B0kl7shw.js +0 -92
  431. package/dist/clack-prompter-B1YxZdRy.js +0 -92
  432. package/dist/cli-CfHUkOD0.js +0 -101
  433. package/dist/cli-ClMrIh6l.js +0 -99
  434. package/dist/cli-session-BkPTd9Pk.js +0 -5463
  435. package/dist/cli-session-Dd8DKb5a.js +0 -5408
  436. package/dist/client-C1avc0vD.js +0 -1692
  437. package/dist/client-CC94YZrT.js +0 -1692
  438. package/dist/clipboard-B2fBy8tG.js +0 -31
  439. package/dist/clipboard-BbGnZskJ.js +0 -31
  440. package/dist/command-format-Clp46jkj.js +0 -38
  441. package/dist/command-format-DELazozB.js +0 -52
  442. package/dist/command-format-SkzzRqR1.js +0 -52
  443. package/dist/command-registry-DZ4hkmA0.js +0 -248
  444. package/dist/commands-DtYZJSPn.js +0 -568
  445. package/dist/commands-Dujk1JmY.js +0 -568
  446. package/dist/commands-registry-Bd0xbvwG.js +0 -766
  447. package/dist/commands-registry-DYfRSVF3.js +0 -766
  448. package/dist/common-D6bu0zHC.js +0 -287
  449. package/dist/common-zW9Y2P1B.js +0 -287
  450. package/dist/completion-cli-tSe7Pmqm.js +0 -431
  451. package/dist/completion-cli-vn4IScs5.js +0 -432
  452. package/dist/config-C8rUDJXY.js +0 -5704
  453. package/dist/config-CLZ_XGVw.js +0 -6523
  454. package/dist/config-SY8M0kM_.js +0 -5705
  455. package/dist/config-cli-1V7D2Wsw.js +0 -247
  456. package/dist/config-cli-CjWEC81L.js +0 -244
  457. package/dist/config-guard-BW2gpKj_.js +0 -93
  458. package/dist/config-guard-BvxuzHpo.js +0 -76
  459. package/dist/config-sync-CoIIbEOe.js +0 -91
  460. package/dist/config-sync-DvAttep0.js +0 -91
  461. package/dist/configure-Bf0oupCE.js +0 -959
  462. package/dist/configure-DRM-7zFf.js +0 -960
  463. package/dist/context-D5iEFzv9.js +0 -60
  464. package/dist/control-service-C8m8F9pr.js +0 -72
  465. package/dist/control-service-DKotCWCg.js +0 -72
  466. package/dist/cron-cli-DB_FLYHD.js +0 -448
  467. package/dist/cron-cli-bxm5lrrO.js +0 -451
  468. package/dist/daemon-cli-1LsOnICv.js +0 -566
  469. package/dist/daemon-cli-CC2NrJ7a.js +0 -565
  470. package/dist/daemon-runtime-BXZhtBL9.js +0 -460
  471. package/dist/daemon-runtime-DW4USC7r.js +0 -460
  472. package/dist/deliver-B4HuPwJA.js +0 -1162
  473. package/dist/deliver-LiY5oL52.js +0 -1097
  474. package/dist/deliver-xrmk7xjh.js +0 -1097
  475. package/dist/delivery-queue-TnQykYsg.js +0 -220
  476. package/dist/deps-CMMOiOsF.js +0 -42
  477. package/dist/devices-cli-Be5he2SA.js +0 -195
  478. package/dist/devices-cli-z6ecoFe9.js +0 -198
  479. package/dist/diagnostics-Dj75aEHN.js +0 -35
  480. package/dist/diagnostics-DlIw6fqD.js +0 -35
  481. package/dist/directory-cli-CEy-0nxj.js +0 -243
  482. package/dist/directory-cli-DpzKcigr.js +0 -246
  483. package/dist/dispatcher-10Shiuz3.js +0 -100
  484. package/dist/dispatcher-3Jae6AiW.js +0 -100
  485. package/dist/dns-cli-Bat1pkc-.js +0 -200
  486. package/dist/dns-cli-NohNyEo0.js +0 -197
  487. package/dist/dock-DbxBBv30.js +0 -753
  488. package/dist/dock-cPBY4qGl.js +0 -753
  489. package/dist/docs-cli-BWp6p-Tq.js +0 -161
  490. package/dist/docs-cli-x22FnZfL.js +0 -159
  491. package/dist/doctor-BrT5m_on.js +0 -1815
  492. package/dist/doctor-Pp2HVnjM.js +0 -1813
  493. package/dist/doctor-completion-DNTimX9o.js +0 -92
  494. package/dist/doctor-completion-ylN9QAJ6.js +0 -92
  495. package/dist/doctor-config-flow-D1w3700T.js +0 -1232
  496. package/dist/doctor-config-flow-Dq50iE1R.js +0 -1232
  497. package/dist/engine-B9avUJL5.js +0 -563
  498. package/dist/engine-BiUQ25D4.js +0 -563
  499. package/dist/env-0lJfCPsw.js +0 -32
  500. package/dist/exec-BenD3A5l.js +0 -1167
  501. package/dist/exec-Bv3pyjeM.js +0 -255
  502. package/dist/exec-approvals-CdLmKX2R.js +0 -1221
  503. package/dist/exec-approvals-cli-DXfV6G8H.js +0 -368
  504. package/dist/exec-approvals-cli-J2cZs10o.js +0 -371
  505. package/dist/frontmatter-YijVi0FQ.js +0 -204
  506. package/dist/gateway-cli-DOAbA0pc.js +0 -19972
  507. package/dist/gateway-cli-QpWtBhQy.js +0 -19971
  508. package/dist/gateway-rpc-DJKBil9s.js +0 -28
  509. package/dist/gateway-rpc-DVterpLP.js +0 -28
  510. package/dist/github-copilot-auth-4IUFp669.js +0 -1418
  511. package/dist/github-copilot-auth-C9E0IROs.js +0 -1418
  512. package/dist/gmail-setup-utils-BPo_LkKI.js +0 -428
  513. package/dist/gmail-setup-utils-D3Yqgor7.js +0 -428
  514. package/dist/health-BeZnqp6m.js +0 -1258
  515. package/dist/health-Cn2OoVWZ.js +0 -1253
  516. package/dist/health-format-CdP99j3Y.js +0 -208
  517. package/dist/health-format-JEChH08S.js +0 -208
  518. package/dist/heartbeat-visibility-BL3WAchI.js +0 -98
  519. package/dist/heartbeat-visibility-CQ9QimI7.js +0 -98
  520. package/dist/help-format-Dl4bsrLI.js +0 -17
  521. package/dist/helpers-ZKNRexvX.js +0 -10
  522. package/dist/hooks-cli-D99hXt7K.js +0 -991
  523. package/dist/hooks-cli-DMB8RiEO.js +0 -993
  524. package/dist/hooks-status-B-e96dZj.js +0 -356
  525. package/dist/hooks-status-C_9sE0ox.js +0 -356
  526. package/dist/image-ops-Dlt3T7th.js +0 -541
  527. package/dist/image-ops-omlvdfah.js +0 -541
  528. package/dist/init-Bm04RagW.js +0 -122
  529. package/dist/init-CaJBf4p1.js +0 -122
  530. package/dist/installs-C2iMRBVz.js +0 -383
  531. package/dist/installs-D-cPGdCw.js +0 -383
  532. package/dist/ipv4-Bf7NS3QU.js +0 -1964
  533. package/dist/ipv4-wWNs8IH_.js +0 -1964
  534. package/dist/lanes-CNxj3tit.js +0 -232
  535. package/dist/lifecycle-core-B_7XRcvF.js +0 -388
  536. package/dist/lifecycle-core-By83PVAK.js +0 -387
  537. package/dist/links-BfjHVTB_.js +0 -15
  538. package/dist/links-DPGe0OHw.js +0 -15
  539. package/dist/logging-DB6BQmhi.js +0 -15
  540. package/dist/logging-mcb66J0p.js +0 -15
  541. package/dist/login-BDCg6D0N.js +0 -61
  542. package/dist/login-BDfnbjnZ.js +0 -59
  543. package/dist/login-BqH1itcg.js +0 -61
  544. package/dist/login-qr-CyOw3R4r.js +0 -321
  545. package/dist/login-qr-D8ECtb72.js +0 -323
  546. package/dist/login-qr-RnR7e4Bw.js +0 -326
  547. package/dist/logs-cli--j89L74J.js +0 -245
  548. package/dist/logs-cli-DpEMg_Gq.js +0 -242
  549. package/dist/manager-B4OyvcxT.js +0 -3244
  550. package/dist/manager-Cqc1CeH7.js +0 -3246
  551. package/dist/manager-DUyQPFvj.js +0 -3244
  552. package/dist/manifest-registry-CW1zCyRF.js +0 -748
  553. package/dist/manifest-registry-D4lM2RdV.js +0 -748
  554. package/dist/markdown-tables-BT1X6jqH.js +0 -347
  555. package/dist/markdown-tables-DHgOK2vI.js +0 -348
  556. package/dist/media-THyainiE.js +0 -1342
  557. package/dist/memory-cli-BKocCWXM.js +0 -868
  558. package/dist/memory-cli-Jmma-xI_.js +0 -869
  559. package/dist/message-channel-dSTVVCyX.js +0 -110
  560. package/dist/migrate-BR6iAIjO.js +0 -157
  561. package/dist/migrate-D0EcMs0f.js +0 -157
  562. package/dist/model-selection-YcSr9CgC.js +0 -2691
  563. package/dist/models-1vUQBVfw.js +0 -2510
  564. package/dist/models-cli-BK3BwUhL.js +0 -2739
  565. package/dist/models-cli-DECrM8oA.js +0 -258
  566. package/dist/net-B5lXhYLV.js +0 -218
  567. package/dist/node-cli-cLHUNpPD.js +0 -1319
  568. package/dist/node-cli-fO7Y132S.js +0 -1322
  569. package/dist/node-service-BFxHJsno.js +0 -67
  570. package/dist/node-service-DUnan4uK.js +0 -67
  571. package/dist/nodes-cli-BCq35E6N.js +0 -1200
  572. package/dist/nodes-cli-vD7MwAKP.js +0 -1197
  573. package/dist/nodes-screen-1YiLkqr5.js +0 -234
  574. package/dist/nodes-screen-DZeD8hE5.js +0 -234
  575. package/dist/note-Bi8Wb8DV.js +0 -73
  576. package/dist/note-uiuPxhyX.js +0 -73
  577. package/dist/npm-registry-spec-B-XIShkB.js +0 -351
  578. package/dist/npm-registry-spec-za3itb5Y.js +0 -351
  579. package/dist/onboard-Ds6w_sWo.js +0 -1165
  580. package/dist/onboard-SAVx3bp4.js +0 -1166
  581. package/dist/onboard-channels-Cg_EkBa4.js +0 -672
  582. package/dist/onboard-channels-D7NbA55V.js +0 -672
  583. package/dist/onboard-helpers-DO_hgZb9.js +0 -365
  584. package/dist/onboard-helpers-_XgJgeqh.js +0 -365
  585. package/dist/onboarding-3hLmDd0r.js +0 -911
  586. package/dist/onboarding-B4LKLsbU.js +0 -910
  587. package/dist/orchestrator-BKzmyBWy.js +0 -357
  588. package/dist/orchestrator-BN3QCz2s.js +0 -357
  589. package/dist/outbound-BgA9hNlP.js +0 -2062
  590. package/dist/outbound-CjdvVhUI.js +0 -214
  591. package/dist/outbound-DOGe6qb2.js +0 -214
  592. package/dist/outbound-send-deps-Du5aBpd7.js +0 -55
  593. package/dist/pairing-cli-2vnyg_Nd.js +0 -118
  594. package/dist/pairing-cli-BH1KQtNV.js +0 -121
  595. package/dist/pairing-store-DJz_9Gv0.js +0 -388
  596. package/dist/pairing-store-DmOzxcuk.js +0 -388
  597. package/dist/path-env-Bu6k0jDQ.js +0 -89
  598. package/dist/path-env-C0zQSjw8.js +0 -89
  599. package/dist/paths-BTc4nk-6.js +0 -126
  600. package/dist/paths-BgUi2Z2G.js +0 -54
  601. package/dist/paths-C6VCWKo3.js +0 -238
  602. package/dist/paths-CCxa0o9c.js +0 -222
  603. package/dist/paths-CxRf2rBG.js +0 -129
  604. package/dist/paths-hcX1Gqg5.js +0 -129
  605. package/dist/pi-auth-json-B68R7q7_.js +0 -82
  606. package/dist/pi-auth-json-CR0jXAgq.js +0 -78
  607. package/dist/pi-auth-json-ZYzi3nxs.js +0 -80
  608. package/dist/pi-model-discovery-Cxs4pvC2.js +0 -3
  609. package/dist/pi-tools.policy-D81U5xy0.js +0 -200
  610. package/dist/pi-tools.policy-DSHkkb5b.js +0 -200
  611. package/dist/plugin-auto-enable-CxF4bpDN.js +0 -282
  612. package/dist/plugin-auto-enable-jNaAeyEh.js +0 -282
  613. package/dist/plugin-registry-C7XWotZG.js +0 -32
  614. package/dist/plugin-registry-DcUCbGax.js +0 -32
  615. package/dist/plugins-B362e77G.js +0 -168
  616. package/dist/plugins-CmSUIUNi.js +0 -38
  617. package/dist/plugins-cli-BsCEnoQ7.js +0 -734
  618. package/dist/plugins-cli-QSIsMUG7.js +0 -736
  619. package/dist/polls-CItfB1H8.js +0 -1343
  620. package/dist/ports-BVLMN1Sr.js +0 -96
  621. package/dist/ports-CqLSlU6Z.js +0 -317
  622. package/dist/ports-D94CwCrv.js +0 -344
  623. package/dist/ports-D_NHthOz.js +0 -96
  624. package/dist/program-DkJHjI0R.js +0 -176
  625. package/dist/program-context-DnyGM2SC.js +0 -496
  626. package/dist/progress-Bek_GyWS.js +0 -133
  627. package/dist/prompt-style-lu0clOOE.js +0 -9
  628. package/dist/pw-ai-BLVMuSLv.js +0 -1867
  629. package/dist/pw-ai-DZJWEF_f.js +0 -1865
  630. package/dist/pw-ai-dzf-ptcn.js +0 -1868
  631. package/dist/qmd-manager-Cur_Ekn0.js +0 -937
  632. package/dist/qmd-manager-DNAUuwjK.js +0 -938
  633. package/dist/qmd-manager-DepEoASu.js +0 -935
  634. package/dist/register.agent-CSWvzOkR.js +0 -265
  635. package/dist/register.agent-UeH2NXmH.js +0 -1003
  636. package/dist/register.anima-DOdee0dh.js +0 -193
  637. package/dist/register.anima-HHDWsz6r.js +0 -193
  638. package/dist/register.configure-CSJFxdz9.js +0 -103
  639. package/dist/register.configure-D84Fvcz4.js +0 -101
  640. package/dist/register.maintenance-B3pvNbZb.js +0 -543
  641. package/dist/register.maintenance-BKVOwkw6.js +0 -543
  642. package/dist/register.message-BAO6CPl2.js +0 -657
  643. package/dist/register.message-OXoOKE_6.js +0 -660
  644. package/dist/register.onboard-BK_ixVmD.js +0 -170
  645. package/dist/register.onboard-cfCaPx6j.js +0 -170
  646. package/dist/register.setup-BGfDnzph.js +0 -175
  647. package/dist/register.setup-Y-Q74M-0.js +0 -175
  648. package/dist/register.status-health-sessions-CT14eitH.js +0 -142
  649. package/dist/register.status-health-sessions-TfZMzAUn.js +0 -313
  650. package/dist/register.subclis-BZwdlNHC.js +0 -255
  651. package/dist/reply-mlsExaZm.js +0 -32212
  652. package/dist/reply-prefix-B0CfR4bM.js +0 -100
  653. package/dist/reply-prefix-w4a39ybC.js +0 -100
  654. package/dist/reply-qalRISe_.js +0 -32212
  655. package/dist/routes-CENsHJyg.js +0 -1820
  656. package/dist/routes-DO0HqW2e.js +0 -1820
  657. package/dist/rpc-C0pjNhBi.js +0 -70
  658. package/dist/rpc-DZ44PIXE.js +0 -70
  659. package/dist/run-main-BMpKw8Mp.js +0 -371
  660. package/dist/runtime-guard-BSUFiAQV.js +0 -60
  661. package/dist/sandbox-BIGfMYEI.js +0 -858
  662. package/dist/sandbox-DxP3IpUP.js +0 -859
  663. package/dist/sandbox-cli-DtLGH8sL.js +0 -461
  664. package/dist/sandbox-cli-_Tg7lfJ_.js +0 -458
  665. package/dist/security-cli-BRwgbedo.js +0 -462
  666. package/dist/security-cli-D3bSuyZt.js +0 -465
  667. package/dist/server-context-49XFFxFg.js +0 -824
  668. package/dist/server-context-LrlgrZzS.js +0 -824
  669. package/dist/server-node-events-Dm52i7NW.js +0 -231
  670. package/dist/server-node-events-QX523UyF.js +0 -233
  671. package/dist/service-BNVpYcQe.js +0 -642
  672. package/dist/service-D56aMXUB.js +0 -642
  673. package/dist/service-audit-D0X_XAB2.js +0 -488
  674. package/dist/service-audit-qmf6XMmP.js +0 -488
  675. package/dist/session-CrQQLLhx.js +0 -179
  676. package/dist/session-LocsOOWJ.js +0 -181
  677. package/dist/session-Vlce2BAT.js +0 -181
  678. package/dist/session-cost-usage-BwiTZuKl.js +0 -600
  679. package/dist/session-cost-usage-DT9YNXTJ.js +0 -600
  680. package/dist/sessions-BfV53TbG.js +0 -1296
  681. package/dist/sessions-BimpX_km.js +0 -180
  682. package/dist/sessions-DcXpzig0.js +0 -1296
  683. package/dist/sessions-Wd18dukK.js +0 -2038
  684. package/dist/shared-Bsr69u_7.js +0 -77
  685. package/dist/shared-Cgly1vPb.js +0 -66
  686. package/dist/shared-JOo05hST.js +0 -66
  687. package/dist/shared-f7dvQsi7.js +0 -77
  688. package/dist/skill-scanner-CkaVLABv.js +0 -263
  689. package/dist/skills-B-G7UHOa.js +0 -808
  690. package/dist/skills-B5LQx4lT.js +0 -807
  691. package/dist/skills-cli-DUGe2ZWW.js +0 -286
  692. package/dist/skills-cli-DtOk0bvK.js +0 -289
  693. package/dist/skills-status-Clq9ZnYu.js +0 -166
  694. package/dist/skills-status-JQluhU-P.js +0 -166
  695. package/dist/sqlite-BukcjdJa.js +0 -321
  696. package/dist/sqlite-CGcOZZ0C.js +0 -368
  697. package/dist/sqlite-Ck6f9KWc.js +0 -453
  698. package/dist/start--xmSFepB.js +0 -372
  699. package/dist/start-BdlZbqrr.js +0 -371
  700. package/dist/status-BgoeFm6g.js +0 -2137
  701. package/dist/status-BjjDrUq7.js +0 -27
  702. package/dist/status-Ct0DgOZ-.js +0 -2132
  703. package/dist/status-RA_uNmK0.js +0 -27
  704. package/dist/status.update-BjOH3GlS.js +0 -79
  705. package/dist/status.update-DLU1qBf0.js +0 -79
  706. package/dist/subagent-registry-9RLdKxES.js +0 -2760
  707. package/dist/subagent-registry-Byuex3zp.js +0 -2759
  708. package/dist/subagent-registry-DOBunBYS.js +0 -14
  709. package/dist/subsystem-Dowf8fSU.js +0 -860
  710. package/dist/system-cli-C5oBpzni.js +0 -79
  711. package/dist/system-cli-DXNKD_Id.js +0 -82
  712. package/dist/systemd-BSrHDyeU.js +0 -452
  713. package/dist/systemd-By5xdSB4.js +0 -452
  714. package/dist/systemd-hints-BtjL_5Rh.js +0 -36
  715. package/dist/systemd-hints-sJmr6cjb.js +0 -36
  716. package/dist/systemd-linger-CTmV2Gci.js +0 -75
  717. package/dist/systemd-linger-CmyqQkeC.js +0 -75
  718. package/dist/table-BL0lJzsm.js +0 -279
  719. package/dist/table-DoiRPsn0.js +0 -279
  720. package/dist/timeout-CswI_K-U.js +0 -232
  721. package/dist/tokens-C-X7wDKj.js +0 -14
  722. package/dist/tokens-DkvqA72p.js +0 -14
  723. package/dist/trash-BJLK1vMn.js +0 -23
  724. package/dist/trash-_x5UZ94k.js +0 -23
  725. package/dist/tui-BHjxDFZC.js +0 -3894
  726. package/dist/tui-CgOocwN8.js +0 -3894
  727. package/dist/tui-cli-5ANH8dE5.js +0 -47
  728. package/dist/tui-cli-BQ4P-JW_.js +0 -50
  729. package/dist/update-LFgxHHPd.js +0 -317
  730. package/dist/update-TxptCqk7.js +0 -317
  731. package/dist/update-check-CWc7YXmc.js +0 -400
  732. package/dist/update-check-IhlWaui6.js +0 -400
  733. package/dist/update-cli-PtXU62w7.js +0 -1105
  734. package/dist/update-cli-Va0EtETG.js +0 -1105
  735. package/dist/update-runner-BLeKFkiB.js +0 -894
  736. package/dist/update-runner-Iuzpc-_y.js +0 -894
  737. package/dist/usage-ApGvBLVg.js +0 -4516
  738. package/dist/utils-Bsw__U-F.js +0 -243
  739. package/dist/web-B6_Ky60G.js +0 -63
  740. package/dist/web-EZLQEWXY.js +0 -46842
  741. package/dist/web-pec8YJUX.js +0 -2203
  742. package/dist/webhooks-cli-BYQKTHTp.js +0 -319
  743. package/dist/webhooks-cli-C2_xtsUQ.js +0 -316
  744. package/dist/whatsapp-actions-C72VCq8f.js +0 -49
  745. package/dist/whatsapp-actions-Ck9Uv0Nw.js +0 -45
  746. package/dist/whatsapp-actions-D0reTj2k.js +0 -53
  747. package/dist/widearea-dns-B6ocX23x.js +0 -127
  748. package/dist/widearea-dns-NsEUNYwz.js +0 -127
  749. package/dist/workspace-Dcfoy5JJ.js +0 -649
  750. package/dist/ws-log-N8R5MvGE.js +0 -267
  751. package/dist/ws-log-gwFxPxj5.js +0 -267
  752. /package/dist/{auto-update-CUeF99gI.js → auto-update-CpF0fycd.js} +0 -0
  753. /package/dist/{auto-update-cgkp9ZTJ.js → auto-update-DNWdO7uF.js} +0 -0
  754. /package/dist/{brew-CVZkr0GU.js → brew-nqf_MiE4.js} +0 -0
  755. /package/dist/{budget-DxYQSekw.js → budget-CPedI-qW.js} +0 -0
  756. /package/dist/{budget-BWBp8Res.js → budget-CRpvqDRX.js} +0 -0
  757. /package/dist/{cli-utils-DtAxdCte.js → cli-utils-C1YHVD4o.js} +0 -0
  758. /package/dist/{command-options-CSbuuqHr.js → command-options-BbponVnw.js} +0 -0
  759. /package/dist/{command-options-Cp1tf96a.js → command-options-s0gnvXnS.js} +0 -0
  760. /package/dist/{constants-O8yBqCBv.js → constants-Dhb6zSIV.js} +0 -0
  761. /package/dist/{dangerous-tools-5ObDWy1N.js → dangerous-tools-DGTtJ_JR.js} +0 -0
  762. /package/dist/{dangerous-tools-Jwr7jqNw.js → dangerous-tools-DxrfTOfT.js} +0 -0
  763. /package/dist/{delivery-queue-B6IHz4Ry.js → delivery-queue-Bxm0nzw7.js} +0 -0
  764. /package/dist/{display-BDOsXu8F.js → display-Jy3UdGzA.js} +0 -0
  765. /package/dist/{errors-CHow2wtt.js → errors-CKaCqKga.js} +0 -0
  766. /package/dist/{exec-BizYYQgP.js → exec-DDmuVVNq.js} +0 -0
  767. /package/dist/{format-Mq6iU0_5.js → format-ByEjgyTF.js} +0 -0
  768. /package/dist/{format-duration-DhWzz_5b.js → format-duration-Aaj5tjJd.js} +0 -0
  769. /package/dist/{format-relative-C6kUHuOj.js → format-relative-79_Y1n2Y.js} +0 -0
  770. /package/dist/{help-format-DUBI91Ti.js → help-format-BMKzarov.js} +0 -0
  771. /package/dist/{helpers-eJFa4K6r.js → helpers-DpEB9Mh0.js} +0 -0
  772. /package/dist/{helpers-DLgbkcEn.js → helpers-FMld9sBT.js} +0 -0
  773. /package/dist/{input-provenance-DJBdpeKk.js → input-provenance-Cy_KnBlP.js} +0 -0
  774. /package/dist/{is-main-Dt9DTcH1.js → is-main-yjaVwMtJ.js} +0 -0
  775. /package/dist/{loader-l2OBdJ8x.js → loader-Br7Vr0zn.js} +0 -0
  776. /package/dist/{loader-BoYxRfcW.js → loader-CkmOrXcC.js} +0 -0
  777. /package/dist/{logging-BdnOSVPD.js → logging-CY-Q5cwf.js} +0 -0
  778. /package/dist/{message-channel-w4F2b2F6.js → message-channel-dua8OOGJ.js} +0 -0
  779. /package/dist/{mime-B1ZoR53M.js → mime-CBg4KybI.js} +0 -0
  780. /package/dist/{model-param-b-DPwyNGn8.js → model-param-b-DW9f0NN8.js} +0 -0
  781. /package/dist/{node-match-8XZnaid6.js → node-match-BV8bTBd4.js} +0 -0
  782. /package/dist/{normalize-GDK8JTNW.js → normalize-_lmlBOW9.js} +0 -0
  783. /package/dist/{openclaw-root-C85WMnVV.js → openclaw-root-JPvmPTf7.js} +0 -0
  784. /package/dist/{outbound-send-deps-ANnAhImn.js → outbound-send-deps-BfUvuWGa.js} +0 -0
  785. /package/dist/{parse-6-2MDhdT.js → parse-CZRwKocn.js} +0 -0
  786. /package/dist/{parse-log-line-Bqh1SSzC.js → parse-log-line-CvrZEK6A.js} +0 -0
  787. /package/dist/{parse-log-line-DUZCjXbl.js → parse-log-line-mLdat0AH.js} +0 -0
  788. /package/dist/{parse-port-BKB9Exlg.js → parse-port-BSOOdo7I.js} +0 -0
  789. /package/dist/{parse-port-DrfvwwiL.js → parse-port-Y0NK62x1.js} +0 -0
  790. /package/dist/{parse-timeout-Di_tcEmi.js → parse-timeout-DVPQ3n9j.js} +0 -0
  791. /package/dist/{paths-DcVEkYX5.js → paths-DHjlJ6cn.js} +0 -0
  792. /package/dist/{pi-model-discovery-DsRqYJLy.js → pi-model-discovery-DzEIEgHL.js} +0 -0
  793. /package/dist/{plugins-CDJw924T.js → plugins-D6PBOdkn.js} +0 -0
  794. /package/dist/{program-context-Bvn8046-.js → program-context-Q1hkT73c.js} +0 -0
  795. /package/dist/{progress-CbZ2D53A.js → progress-C9Ha1NJh.js} +0 -0
  796. /package/dist/{prompt-style-DKy6qQxR.js → prompt-style-DQi8j03a.js} +0 -0
  797. /package/dist/{prompts-BI__va99.js → prompts-BEHxUC3w.js} +0 -0
  798. /package/dist/{prompts-_dDWkCAz.js → prompts-CSOhuiqe.js} +0 -0
  799. /package/dist/{queue-D_u34pbL.js → queue-BJGo7kAB.js} +0 -0
  800. /package/dist/{queue-PG591iID.js → queue-DYgUbdoq.js} +0 -0
  801. /package/dist/{redact-ClVwO7Nn.js → redact-CyKvdFrg.js} +0 -0
  802. /package/dist/{registry-Bs_DJK9E.js → registry-C5MAYD4V.js} +0 -0
  803. /package/dist/{registry-D_zlP1U-.js → registry-CRrXXVs0.js} +0 -0
  804. /package/dist/{requirements-BzZxj2Wu.js → requirements-CGkxTCu4.js} +0 -0
  805. /package/dist/{requirements-DIW1svgA.js → requirements-CIDaOcbO.js} +0 -0
  806. /package/dist/{runtime-guard-DeOXA_86.js → runtime-guard-nL3Lp8T-.js} +0 -0
  807. /package/dist/{secret-equal-Dghy3xsA.js → secret-equal-DJpmLXlG.js} +0 -0
  808. /package/dist/{send-BhAfdGII.js → send-CTcxgDDU.js} +0 -0
  809. /package/dist/{send-ga9udK1_.js → send-DPezUR3-.js} +0 -0
  810. /package/dist/{send-C2t9xpXI.js → send-DZQTaG7-.js} +0 -0
  811. /package/dist/{send-DigO-i9j.js → send-VDff2gra.js} +0 -0
  812. /package/dist/{send-Dz2BDHll.js → send-bgQNV8d1.js} +0 -0
  813. /package/dist/{session-key-BGiG_JcT.js → session-key-CQT-NR6w.js} +0 -0
  814. /package/dist/{shell-argv-CAq1mLa2.js → shell-argv-n9IueeJQ.js} +0 -0
  815. /package/dist/{skill-scanner-Coo4QoCd.js → skill-scanner-o6NgVMD9.js} +0 -0
  816. /package/dist/{status-CMnlcBVc.js → status-C53kTIXF.js} +0 -0
  817. /package/dist/{status-tDZPwewW.js → status-CZDDA_Sy.js} +0 -0
  818. /package/dist/{system-run-command-X9lDJIy0.js → system-run-command-BCjUffN9.js} +0 -0
  819. /package/dist/{system-run-command-DGk7dwQP.js → system-run-command-CqAqKL9K.js} +0 -0
  820. /package/dist/{tailnet-CuiNECdL.js → tailnet-Ciwjv243.js} +0 -0
  821. /package/dist/{templates-CeYJjVzw.js → templates-37RKpACb.js} +0 -0
  822. /package/dist/{templates-I3Z0xplD.js → templates-DPalk30o.js} +0 -0
  823. /package/dist/{thinking-BXEswx1X.js → thinking-2hxwmvTl.js} +0 -0
  824. /package/dist/{transcript-events-C1hdue6u.js → transcript-events-Bp7fGnwv.js} +0 -0
  825. /package/dist/{transcript-tools-DuyYOkUq.js → transcript-tools-D4Lbxlka.js} +0 -0
  826. /package/dist/{usage-format-BAirWUSO.js → usage-format-6Uar63S0.js} +0 -0
  827. /package/dist/{utils-C9sj30YY.js → utils-DT8uXjFS.js} +0 -0
  828. /package/dist/{wsl-CqyuRvtM.js → wsl-CrPvx2kZ.js} +0 -0
  829. /package/dist/{wsl-ymJYvc9Q.js → wsl-UvJ5dHah.js} +0 -0
@@ -1,4516 +0,0 @@
1
- import { E as resolveAgentIdFromSessionKey, M as parseAgentSessionKey, S as classifySessionKeyShape, _ as DEFAULT_AGENT_ID, f as loadWorkspaceBootstrapFiles, h as resolveAnimaPackageRootSync, m as resolveAnimaPackageRoot, u as filterBootstrapFilesForSession, w as normalizeAgentId } from "./workspace-Dcfoy5JJ.js";
2
- import { M as isRecord, Y as logVerbose, Z as shouldLogVerbose, k as escapeRegExp, l as createSubsystemLogger, n as runExec, t as runCommandWithTimeout, w as CONFIG_DIR, z as resolveUserPath } from "./exec-BenD3A5l.js";
3
- import { c as resolveDefaultAgentId, s as resolveAgentWorkspaceDir, u as resolveSessionAgentIds } from "./agent-scope-BVf4aSwY.js";
4
- import { t as formatCliCommand } from "./command-format-SkzzRqR1.js";
5
- import { h as resolveMemorySlotDecision, m as resolveEnableState, n as loadConfig, p as normalizePluginsConfig, u as loadPluginManifestRegistry } from "./config-CLZ_XGVw.js";
6
- import { R as normalizeChatType, V as SILENT_REPLY_TOKEN, c as updateSessionStore, u as deliveryContextFromSession } from "./sessions-Wd18dukK.js";
7
- import { E as requireApiKey, I as isTruthyEnvValue, R as DEFAULT_MODEL, S as resolveModelRefFromString, _ as normalizeModelRef, b as resolveConfiguredModelRef, c as resolveAnimaAgentDir, g as modelKey, m as buildModelAliasIndex, n as resolveAuthProfileOrder, o as ensureAuthProfileStore, p as buildConfiguredAllowlistKeys, r as isProfileInCooldown, v as normalizeProviderId$1, w as getApiKeyForModel, x as resolveDefaultModelForAgent, z as DEFAULT_PROVIDER } from "./auth-profiles-CCDD56dU.js";
8
- import { _ as listDeliverableMessageChannels, f as INTERNAL_MESSAGE_CHANNEL, p as isDeliverableMessageChannel, r as normalizeChannelId, t as getChannelPlugin, v as normalizeMessageChannel } from "./plugins-B362e77G.js";
9
- import { l as resolveHeartbeatPrompt } from "./agent-events-BEBQsyE5.js";
10
- import { i as triggerInternalHook, t as createInternalHookEvent } from "./internal-hooks-DFTIurVM.js";
11
- import { r as getFileExtension, s as normalizeMimeType } from "./mime-Bm1xTtpY.js";
12
- import { a as parseFrontmatterBlock, c as resolveRuntimePlatform, i as resolveAnimaManifestBlock, n as normalizeStringList, o as hasBinary, r as parseFrontmatterBool, s as isConfigPathTruthyWithDefaults, t as getFrontmatterString } from "./frontmatter-YijVi0FQ.js";
13
- import fs from "node:fs/promises";
14
- import os, { tmpdir } from "node:os";
15
- import path from "node:path";
16
- import fs$1, { existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
17
- import { execSync, spawn } from "node:child_process";
18
- import { fileURLToPath } from "node:url";
19
- import crypto, { randomUUID } from "node:crypto";
20
- import { completeSimple } from "@mariozechner/pi-ai";
21
- import { formatSkillsForPrompt, loadSkillsFromDir } from "@mariozechner/pi-coding-agent";
22
- import { EdgeTTS } from "node-edge-tts";
23
- import chokidar from "chokidar";
24
-
25
- //#region src/agents/auth-profiles/session-override.ts
26
- function isProfileForProvider(params) {
27
- const entry = params.store.profiles[params.profileId];
28
- if (!entry?.provider) return false;
29
- return normalizeProviderId$1(entry.provider) === normalizeProviderId$1(params.provider);
30
- }
31
- async function clearSessionAuthProfileOverride(params) {
32
- const { sessionEntry, sessionStore, sessionKey, storePath } = params;
33
- delete sessionEntry.authProfileOverride;
34
- delete sessionEntry.authProfileOverrideSource;
35
- delete sessionEntry.authProfileOverrideCompactionCount;
36
- sessionEntry.updatedAt = Date.now();
37
- sessionStore[sessionKey] = sessionEntry;
38
- if (storePath) await updateSessionStore(storePath, (store) => {
39
- store[sessionKey] = sessionEntry;
40
- });
41
- }
42
- async function resolveSessionAuthProfileOverride(params) {
43
- const { cfg, provider, agentDir, sessionEntry, sessionStore, sessionKey, storePath, isNewSession } = params;
44
- if (!sessionEntry || !sessionStore || !sessionKey) return sessionEntry?.authProfileOverride;
45
- const store = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false });
46
- const order = resolveAuthProfileOrder({
47
- cfg,
48
- store,
49
- provider
50
- });
51
- let current = sessionEntry.authProfileOverride?.trim();
52
- if (current && !store.profiles[current]) {
53
- await clearSessionAuthProfileOverride({
54
- sessionEntry,
55
- sessionStore,
56
- sessionKey,
57
- storePath
58
- });
59
- current = void 0;
60
- }
61
- if (current && !isProfileForProvider({
62
- provider,
63
- profileId: current,
64
- store
65
- })) {
66
- await clearSessionAuthProfileOverride({
67
- sessionEntry,
68
- sessionStore,
69
- sessionKey,
70
- storePath
71
- });
72
- current = void 0;
73
- }
74
- if (current && order.length > 0 && !order.includes(current)) {
75
- await clearSessionAuthProfileOverride({
76
- sessionEntry,
77
- sessionStore,
78
- sessionKey,
79
- storePath
80
- });
81
- current = void 0;
82
- }
83
- if (order.length === 0) return;
84
- const pickFirstAvailable = () => order.find((profileId) => !isProfileInCooldown(store, profileId)) ?? order[0];
85
- const pickNextAvailable = (active) => {
86
- const startIndex = order.indexOf(active);
87
- if (startIndex < 0) return pickFirstAvailable();
88
- for (let offset = 1; offset <= order.length; offset += 1) {
89
- const candidate = order[(startIndex + offset) % order.length];
90
- if (!isProfileInCooldown(store, candidate)) return candidate;
91
- }
92
- return order[startIndex] ?? order[0];
93
- };
94
- const compactionCount = sessionEntry.compactionCount ?? 0;
95
- const storedCompaction = typeof sessionEntry.authProfileOverrideCompactionCount === "number" ? sessionEntry.authProfileOverrideCompactionCount : compactionCount;
96
- if ((sessionEntry.authProfileOverrideSource ?? (typeof sessionEntry.authProfileOverrideCompactionCount === "number" ? "auto" : current ? "user" : void 0)) === "user" && current && !isNewSession) return current;
97
- let next = current;
98
- if (isNewSession) next = current ? pickNextAvailable(current) : pickFirstAvailable();
99
- else if (current && compactionCount > storedCompaction) next = pickNextAvailable(current);
100
- else if (!current || isProfileInCooldown(store, current)) next = pickFirstAvailable();
101
- if (!next) return current;
102
- if (next !== sessionEntry.authProfileOverride || sessionEntry.authProfileOverrideSource !== "auto" || sessionEntry.authProfileOverrideCompactionCount !== compactionCount) {
103
- sessionEntry.authProfileOverride = next;
104
- sessionEntry.authProfileOverrideSource = "auto";
105
- sessionEntry.authProfileOverrideCompactionCount = compactionCount;
106
- sessionEntry.updatedAt = Date.now();
107
- sessionStore[sessionKey] = sessionEntry;
108
- if (storePath) await updateSessionStore(storePath, (store) => {
109
- store[sessionKey] = sessionEntry;
110
- });
111
- }
112
- return next;
113
- }
114
-
115
- //#endregion
116
- //#region src/agents/bootstrap-hooks.ts
117
- async function applyBootstrapHookOverrides(params) {
118
- const sessionKey = params.sessionKey ?? params.sessionId ?? "unknown";
119
- const agentId = params.agentId ?? (params.sessionKey ? resolveAgentIdFromSessionKey(params.sessionKey) : void 0);
120
- const event = createInternalHookEvent("agent", "bootstrap", sessionKey, {
121
- workspaceDir: params.workspaceDir,
122
- bootstrapFiles: params.files,
123
- cfg: params.config,
124
- sessionKey: params.sessionKey,
125
- sessionId: params.sessionId,
126
- agentId
127
- });
128
- await triggerInternalHook(event);
129
- const updated = event.context.bootstrapFiles;
130
- return Array.isArray(updated) ? updated : params.files;
131
- }
132
-
133
- //#endregion
134
- //#region src/agents/bootstrap-files.ts
135
- function makeBootstrapWarn(params) {
136
- if (!params.warn) return;
137
- return (message) => params.warn?.(`${message} (sessionKey=${params.sessionLabel})`);
138
- }
139
- async function resolveBootstrapFilesForRun(params) {
140
- const sessionKey = params.sessionKey ?? params.sessionId;
141
- return applyBootstrapHookOverrides({
142
- files: filterBootstrapFilesForSession(await loadWorkspaceBootstrapFiles(params.workspaceDir), sessionKey),
143
- workspaceDir: params.workspaceDir,
144
- config: params.config,
145
- sessionKey: params.sessionKey,
146
- sessionId: params.sessionId,
147
- agentId: params.agentId
148
- });
149
- }
150
- async function resolveBootstrapContextForRun(params) {
151
- const bootstrapFiles = await resolveBootstrapFilesForRun(params);
152
- return {
153
- bootstrapFiles,
154
- contextFiles: buildBootstrapContextFiles(bootstrapFiles, {
155
- maxChars: resolveBootstrapMaxChars(params.config),
156
- totalMaxChars: resolveBootstrapTotalMaxChars(params.config),
157
- warn: params.warn
158
- })
159
- };
160
- }
161
-
162
- //#endregion
163
- //#region src/agents/cli-backends.ts
164
- const DEFAULT_CLAUDE_BACKEND = {
165
- command: "claude",
166
- args: [
167
- "-p",
168
- "--output-format",
169
- "json",
170
- "--dangerously-skip-permissions"
171
- ],
172
- resumeArgs: [
173
- "-p",
174
- "--output-format",
175
- "json",
176
- "--dangerously-skip-permissions",
177
- "--resume",
178
- "{sessionId}"
179
- ],
180
- output: "json",
181
- input: "arg",
182
- modelArg: "--model",
183
- modelAliases: {
184
- opus: "opus",
185
- "opus-4.6": "opus",
186
- "opus-4.5": "opus",
187
- "opus-4": "opus",
188
- "claude-opus-4-6": "opus",
189
- "claude-opus-4-5": "opus",
190
- "claude-opus-4": "opus",
191
- sonnet: "sonnet",
192
- "sonnet-4.5": "sonnet",
193
- "sonnet-4.1": "sonnet",
194
- "sonnet-4.0": "sonnet",
195
- "claude-sonnet-4-5": "sonnet",
196
- "claude-sonnet-4-1": "sonnet",
197
- "claude-sonnet-4-0": "sonnet",
198
- haiku: "haiku",
199
- "haiku-3.5": "haiku",
200
- "claude-haiku-3-5": "haiku"
201
- },
202
- sessionArg: "--session-id",
203
- sessionMode: "always",
204
- sessionIdFields: [
205
- "session_id",
206
- "sessionId",
207
- "conversation_id",
208
- "conversationId"
209
- ],
210
- systemPromptArg: "--append-system-prompt",
211
- systemPromptMode: "append",
212
- systemPromptWhen: "first",
213
- clearEnv: ["ANTHROPIC_API_KEY", "ANTHROPIC_API_KEY_OLD"],
214
- serialize: true
215
- };
216
- const DEFAULT_CODEX_BACKEND = {
217
- command: "codex",
218
- args: [
219
- "exec",
220
- "--json",
221
- "--color",
222
- "never",
223
- "--sandbox",
224
- "read-only",
225
- "--skip-git-repo-check"
226
- ],
227
- resumeArgs: [
228
- "exec",
229
- "resume",
230
- "{sessionId}",
231
- "--color",
232
- "never",
233
- "--sandbox",
234
- "read-only",
235
- "--skip-git-repo-check"
236
- ],
237
- output: "jsonl",
238
- resumeOutput: "text",
239
- input: "arg",
240
- modelArg: "--model",
241
- sessionIdFields: ["thread_id"],
242
- sessionMode: "existing",
243
- imageArg: "--image",
244
- imageMode: "repeat",
245
- serialize: true
246
- };
247
- function normalizeBackendKey(key) {
248
- return normalizeProviderId$1(key);
249
- }
250
- function pickBackendConfig(config, normalizedId) {
251
- for (const [key, entry] of Object.entries(config)) if (normalizeBackendKey(key) === normalizedId) return entry;
252
- }
253
- function mergeBackendConfig(base, override) {
254
- if (!override) return { ...base };
255
- return {
256
- ...base,
257
- ...override,
258
- args: override.args ?? base.args,
259
- env: {
260
- ...base.env,
261
- ...override.env
262
- },
263
- modelAliases: {
264
- ...base.modelAliases,
265
- ...override.modelAliases
266
- },
267
- clearEnv: Array.from(new Set([...base.clearEnv ?? [], ...override.clearEnv ?? []])),
268
- sessionIdFields: override.sessionIdFields ?? base.sessionIdFields,
269
- sessionArgs: override.sessionArgs ?? base.sessionArgs,
270
- resumeArgs: override.resumeArgs ?? base.resumeArgs
271
- };
272
- }
273
- function resolveCliBackendConfig(provider, cfg) {
274
- const normalized = normalizeBackendKey(provider);
275
- const override = pickBackendConfig(cfg?.agents?.defaults?.cliBackends ?? {}, normalized);
276
- if (normalized === "claude-cli") {
277
- const merged = mergeBackendConfig(DEFAULT_CLAUDE_BACKEND, override);
278
- const command = merged.command?.trim();
279
- if (!command) return null;
280
- return {
281
- id: normalized,
282
- config: {
283
- ...merged,
284
- command
285
- }
286
- };
287
- }
288
- if (normalized === "codex-cli") {
289
- const merged = mergeBackendConfig(DEFAULT_CODEX_BACKEND, override);
290
- const command = merged.command?.trim();
291
- if (!command) return null;
292
- return {
293
- id: normalized,
294
- config: {
295
- ...merged,
296
- command
297
- }
298
- };
299
- }
300
- if (!override) return null;
301
- const command = override.command?.trim();
302
- if (!command) return null;
303
- return {
304
- id: normalized,
305
- config: {
306
- ...override,
307
- command
308
- }
309
- };
310
- }
311
-
312
- //#endregion
313
- //#region src/line/markdown-to-line.ts
314
- function stripMarkdown(text) {
315
- return text.replace(/\*\*([^*]+)\*\*/g, "$1").replace(/\*([^*]+)\*/g, "$1").replace(/__([^_]+)__/g, "$1").replace(/_([^_]+)_/g, "$1").replace(/~~([^~]+)~~/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/```[^`]*```/gs, "").replace(/^#{1,6}\s+/gm, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/^[-*+]\s+/gm, "").replace(/^\d+\.\s+/gm, "");
316
- }
317
-
318
- //#endregion
319
- //#region src/media/audio.ts
320
- const TELEGRAM_VOICE_AUDIO_EXTENSIONS = new Set([
321
- ".oga",
322
- ".ogg",
323
- ".opus",
324
- ".mp3",
325
- ".m4a"
326
- ]);
327
- /**
328
- * MIME types compatible with voice messages.
329
- * Telegram sendVoice supports OGG/Opus, MP3, and M4A.
330
- * https://core.telegram.org/bots/api#sendvoice
331
- */
332
- const TELEGRAM_VOICE_MIME_TYPES = new Set([
333
- "audio/ogg",
334
- "audio/opus",
335
- "audio/mpeg",
336
- "audio/mp3",
337
- "audio/mp4",
338
- "audio/x-m4a",
339
- "audio/m4a"
340
- ]);
341
- function isTelegramVoiceCompatibleAudio(opts) {
342
- const mime = normalizeMimeType(opts.contentType);
343
- if (mime && TELEGRAM_VOICE_MIME_TYPES.has(mime)) return true;
344
- const fileName = opts.fileName?.trim();
345
- if (!fileName) return false;
346
- const ext = getFileExtension(fileName);
347
- if (!ext) return false;
348
- return TELEGRAM_VOICE_AUDIO_EXTENSIONS.has(ext);
349
- }
350
- /**
351
- * Backward-compatible alias used across plugin/runtime call sites.
352
- * Keeps existing behavior while making Telegram-specific policy explicit.
353
- */
354
- function isVoiceCompatibleAudio(opts) {
355
- return isTelegramVoiceCompatibleAudio(opts);
356
- }
357
-
358
- //#endregion
359
- //#region src/agents/pi-embedded-runner/model.ts
360
- function resolveModel(..._args) {
361
- return "default";
362
- }
363
-
364
- //#endregion
365
- //#region src/tts/tts-core.ts
366
- const DEFAULT_ELEVENLABS_BASE_URL$1 = "https://api.elevenlabs.io";
367
- const TEMP_FILE_CLEANUP_DELAY_MS = 300 * 1e3;
368
- function isValidVoiceId(voiceId) {
369
- return /^[a-zA-Z0-9]{10,40}$/.test(voiceId);
370
- }
371
- function normalizeElevenLabsBaseUrl(baseUrl) {
372
- const trimmed = baseUrl.trim();
373
- if (!trimmed) return DEFAULT_ELEVENLABS_BASE_URL$1;
374
- return trimmed.replace(/\/+$/, "");
375
- }
376
- function requireInRange(value, min, max, label) {
377
- if (!Number.isFinite(value) || value < min || value > max) throw new Error(`${label} must be between ${min} and ${max}`);
378
- }
379
- function assertElevenLabsVoiceSettings(settings) {
380
- requireInRange(settings.stability, 0, 1, "stability");
381
- requireInRange(settings.similarityBoost, 0, 1, "similarityBoost");
382
- requireInRange(settings.style, 0, 1, "style");
383
- requireInRange(settings.speed, .5, 2, "speed");
384
- }
385
- function normalizeLanguageCode(code) {
386
- const trimmed = code?.trim();
387
- if (!trimmed) return;
388
- const normalized = trimmed.toLowerCase();
389
- if (!/^[a-z]{2}$/.test(normalized)) throw new Error("languageCode must be a 2-letter ISO 639-1 code (e.g. en, de, fr)");
390
- return normalized;
391
- }
392
- function normalizeApplyTextNormalization(mode) {
393
- const trimmed = mode?.trim();
394
- if (!trimmed) return;
395
- const normalized = trimmed.toLowerCase();
396
- if (normalized === "auto" || normalized === "on" || normalized === "off") return normalized;
397
- throw new Error("applyTextNormalization must be one of: auto, on, off");
398
- }
399
- function normalizeSeed(seed) {
400
- if (seed == null) return;
401
- const next = Math.floor(seed);
402
- if (!Number.isFinite(next) || next < 0 || next > 4294967295) throw new Error("seed must be between 0 and 4294967295");
403
- return next;
404
- }
405
- function parseBooleanValue(value) {
406
- const normalized = value.trim().toLowerCase();
407
- if ([
408
- "true",
409
- "1",
410
- "yes",
411
- "on"
412
- ].includes(normalized)) return true;
413
- if ([
414
- "false",
415
- "0",
416
- "no",
417
- "off"
418
- ].includes(normalized)) return false;
419
- }
420
- function parseNumberValue(value) {
421
- const parsed = Number.parseFloat(value);
422
- return Number.isFinite(parsed) ? parsed : void 0;
423
- }
424
- function parseTtsDirectives(text, policy) {
425
- if (!policy.enabled) return {
426
- cleanedText: text,
427
- overrides: {},
428
- warnings: [],
429
- hasDirective: false
430
- };
431
- const overrides = {};
432
- const warnings = [];
433
- let cleanedText = text;
434
- let hasDirective = false;
435
- cleanedText = cleanedText.replace(/\[\[tts:text\]\]([\s\S]*?)\[\[\/tts:text\]\]/gi, (_match, inner) => {
436
- hasDirective = true;
437
- if (policy.allowText && overrides.ttsText == null) overrides.ttsText = inner.trim();
438
- return "";
439
- });
440
- cleanedText = cleanedText.replace(/\[\[tts:([^\]]+)\]\]/gi, (_match, body) => {
441
- hasDirective = true;
442
- const tokens = body.split(/\s+/).filter(Boolean);
443
- for (const token of tokens) {
444
- const eqIndex = token.indexOf("=");
445
- if (eqIndex === -1) continue;
446
- const rawKey = token.slice(0, eqIndex).trim();
447
- const rawValue = token.slice(eqIndex + 1).trim();
448
- if (!rawKey || !rawValue) continue;
449
- const key = rawKey.toLowerCase();
450
- try {
451
- switch (key) {
452
- case "provider":
453
- if (!policy.allowProvider) break;
454
- if (rawValue === "openai" || rawValue === "elevenlabs" || rawValue === "edge") overrides.provider = rawValue;
455
- else warnings.push(`unsupported provider "${rawValue}"`);
456
- break;
457
- case "voice":
458
- case "openai_voice":
459
- case "openaivoice":
460
- if (!policy.allowVoice) break;
461
- if (isValidOpenAIVoice(rawValue)) overrides.openai = {
462
- ...overrides.openai,
463
- voice: rawValue
464
- };
465
- else warnings.push(`invalid OpenAI voice "${rawValue}"`);
466
- break;
467
- case "voiceid":
468
- case "voice_id":
469
- case "elevenlabs_voice":
470
- case "elevenlabsvoice":
471
- if (!policy.allowVoice) break;
472
- if (isValidVoiceId(rawValue)) overrides.elevenlabs = {
473
- ...overrides.elevenlabs,
474
- voiceId: rawValue
475
- };
476
- else warnings.push(`invalid ElevenLabs voiceId "${rawValue}"`);
477
- break;
478
- case "model":
479
- case "modelid":
480
- case "model_id":
481
- case "elevenlabs_model":
482
- case "elevenlabsmodel":
483
- case "openai_model":
484
- case "openaimodel":
485
- if (!policy.allowModelId) break;
486
- if (isValidOpenAIModel(rawValue)) overrides.openai = {
487
- ...overrides.openai,
488
- model: rawValue
489
- };
490
- else overrides.elevenlabs = {
491
- ...overrides.elevenlabs,
492
- modelId: rawValue
493
- };
494
- break;
495
- case "stability":
496
- if (!policy.allowVoiceSettings) break;
497
- {
498
- const value = parseNumberValue(rawValue);
499
- if (value == null) {
500
- warnings.push("invalid stability value");
501
- break;
502
- }
503
- requireInRange(value, 0, 1, "stability");
504
- overrides.elevenlabs = {
505
- ...overrides.elevenlabs,
506
- voiceSettings: {
507
- ...overrides.elevenlabs?.voiceSettings,
508
- stability: value
509
- }
510
- };
511
- }
512
- break;
513
- case "similarity":
514
- case "similarityboost":
515
- case "similarity_boost":
516
- if (!policy.allowVoiceSettings) break;
517
- {
518
- const value = parseNumberValue(rawValue);
519
- if (value == null) {
520
- warnings.push("invalid similarityBoost value");
521
- break;
522
- }
523
- requireInRange(value, 0, 1, "similarityBoost");
524
- overrides.elevenlabs = {
525
- ...overrides.elevenlabs,
526
- voiceSettings: {
527
- ...overrides.elevenlabs?.voiceSettings,
528
- similarityBoost: value
529
- }
530
- };
531
- }
532
- break;
533
- case "style":
534
- if (!policy.allowVoiceSettings) break;
535
- {
536
- const value = parseNumberValue(rawValue);
537
- if (value == null) {
538
- warnings.push("invalid style value");
539
- break;
540
- }
541
- requireInRange(value, 0, 1, "style");
542
- overrides.elevenlabs = {
543
- ...overrides.elevenlabs,
544
- voiceSettings: {
545
- ...overrides.elevenlabs?.voiceSettings,
546
- style: value
547
- }
548
- };
549
- }
550
- break;
551
- case "speed":
552
- if (!policy.allowVoiceSettings) break;
553
- {
554
- const value = parseNumberValue(rawValue);
555
- if (value == null) {
556
- warnings.push("invalid speed value");
557
- break;
558
- }
559
- requireInRange(value, .5, 2, "speed");
560
- overrides.elevenlabs = {
561
- ...overrides.elevenlabs,
562
- voiceSettings: {
563
- ...overrides.elevenlabs?.voiceSettings,
564
- speed: value
565
- }
566
- };
567
- }
568
- break;
569
- case "speakerboost":
570
- case "speaker_boost":
571
- case "usespeakerboost":
572
- case "use_speaker_boost":
573
- if (!policy.allowVoiceSettings) break;
574
- {
575
- const value = parseBooleanValue(rawValue);
576
- if (value == null) {
577
- warnings.push("invalid useSpeakerBoost value");
578
- break;
579
- }
580
- overrides.elevenlabs = {
581
- ...overrides.elevenlabs,
582
- voiceSettings: {
583
- ...overrides.elevenlabs?.voiceSettings,
584
- useSpeakerBoost: value
585
- }
586
- };
587
- }
588
- break;
589
- case "normalize":
590
- case "applytextnormalization":
591
- case "apply_text_normalization":
592
- if (!policy.allowNormalization) break;
593
- overrides.elevenlabs = {
594
- ...overrides.elevenlabs,
595
- applyTextNormalization: normalizeApplyTextNormalization(rawValue)
596
- };
597
- break;
598
- case "language":
599
- case "languagecode":
600
- case "language_code":
601
- if (!policy.allowNormalization) break;
602
- overrides.elevenlabs = {
603
- ...overrides.elevenlabs,
604
- languageCode: normalizeLanguageCode(rawValue)
605
- };
606
- break;
607
- case "seed":
608
- if (!policy.allowSeed) break;
609
- overrides.elevenlabs = {
610
- ...overrides.elevenlabs,
611
- seed: normalizeSeed(Number.parseInt(rawValue, 10))
612
- };
613
- break;
614
- default: break;
615
- }
616
- } catch (err) {
617
- warnings.push(err.message);
618
- }
619
- }
620
- return "";
621
- });
622
- return {
623
- cleanedText,
624
- ttsText: overrides.ttsText,
625
- hasDirective,
626
- overrides,
627
- warnings
628
- };
629
- }
630
- const OPENAI_TTS_MODELS = [
631
- "gpt-4o-mini-tts",
632
- "tts-1",
633
- "tts-1-hd"
634
- ];
635
- /**
636
- * Custom OpenAI-compatible TTS endpoint.
637
- * When set, model/voice validation is relaxed to allow non-OpenAI models.
638
- * Example: OPENAI_TTS_BASE_URL=http://localhost:8880/v1
639
- *
640
- * Note: Read at runtime (not module load) to support config.env loading.
641
- */
642
- function getOpenAITtsBaseUrl() {
643
- return (process.env.OPENAI_TTS_BASE_URL?.trim() || "https://api.openai.com/v1").replace(/\/+$/, "");
644
- }
645
- function isCustomOpenAIEndpoint() {
646
- return getOpenAITtsBaseUrl() !== "https://api.openai.com/v1";
647
- }
648
- const OPENAI_TTS_VOICES = [
649
- "alloy",
650
- "ash",
651
- "ballad",
652
- "cedar",
653
- "coral",
654
- "echo",
655
- "fable",
656
- "juniper",
657
- "marin",
658
- "onyx",
659
- "nova",
660
- "sage",
661
- "shimmer",
662
- "verse"
663
- ];
664
- function isValidOpenAIModel(model) {
665
- if (isCustomOpenAIEndpoint()) return true;
666
- return OPENAI_TTS_MODELS.includes(model);
667
- }
668
- function isValidOpenAIVoice(voice) {
669
- if (isCustomOpenAIEndpoint()) return true;
670
- return OPENAI_TTS_VOICES.includes(voice);
671
- }
672
- function resolveSummaryModelRef(cfg, config) {
673
- const defaultRef = resolveDefaultModelForAgent({ cfg });
674
- const override = config.summaryModel?.trim();
675
- if (!override) return {
676
- ref: defaultRef,
677
- source: "default"
678
- };
679
- const aliasIndex = buildModelAliasIndex({
680
- cfg,
681
- defaultProvider: defaultRef.provider
682
- });
683
- const resolved = resolveModelRefFromString({
684
- raw: override,
685
- defaultProvider: defaultRef.provider,
686
- aliasIndex
687
- });
688
- if (!resolved) return {
689
- ref: defaultRef,
690
- source: "default"
691
- };
692
- return {
693
- ref: resolved.ref,
694
- source: "summaryModel"
695
- };
696
- }
697
- function isTextContentBlock(block) {
698
- return block.type === "text";
699
- }
700
- async function summarizeText(params) {
701
- const { text, targetLength, cfg, config, timeoutMs } = params;
702
- if (targetLength < 100 || targetLength > 1e4) throw new Error(`Invalid targetLength: ${targetLength}`);
703
- const startTime = Date.now();
704
- const { ref } = resolveSummaryModelRef(cfg, config);
705
- const resolved = resolveModel(ref.provider, ref.model, void 0, cfg);
706
- if (!resolved.model) throw new Error(resolved.error ?? `Unknown summary model: ${ref.provider}/${ref.model}`);
707
- const apiKey = requireApiKey(await getApiKeyForModel({
708
- model: resolved.model,
709
- cfg
710
- }), ref.provider);
711
- try {
712
- const controller = new AbortController();
713
- const timeout = setTimeout(() => controller.abort(), timeoutMs);
714
- try {
715
- const summary = (await completeSimple(resolved.model, { messages: [{
716
- role: "user",
717
- content: `You are an assistant that summarizes texts concisely while keeping the most important information. Summarize the text to approximately ${targetLength} characters. Maintain the original tone and style. Reply only with the summary, without additional explanations.\n\n<text_to_summarize>\n${text}\n</text_to_summarize>`,
718
- timestamp: Date.now()
719
- }] }, {
720
- apiKey,
721
- maxTokens: Math.ceil(targetLength / 2),
722
- temperature: .3,
723
- signal: controller.signal
724
- })).content.filter(isTextContentBlock).map((block) => block.text.trim()).filter(Boolean).join(" ").trim();
725
- if (!summary) throw new Error("No summary returned");
726
- return {
727
- summary,
728
- latencyMs: Date.now() - startTime,
729
- inputLength: text.length,
730
- outputLength: summary.length
731
- };
732
- } finally {
733
- clearTimeout(timeout);
734
- }
735
- } catch (err) {
736
- if (err.name === "AbortError") throw new Error("Summarization timed out", { cause: err });
737
- throw err;
738
- }
739
- }
740
- function scheduleCleanup(tempDir, delayMs = TEMP_FILE_CLEANUP_DELAY_MS) {
741
- setTimeout(() => {
742
- try {
743
- rmSync(tempDir, {
744
- recursive: true,
745
- force: true
746
- });
747
- } catch {}
748
- }, delayMs).unref();
749
- }
750
- async function elevenLabsTTS(params) {
751
- const { text, apiKey, baseUrl, voiceId, modelId, outputFormat, seed, applyTextNormalization, languageCode, voiceSettings, timeoutMs } = params;
752
- if (!isValidVoiceId(voiceId)) throw new Error("Invalid voiceId format");
753
- assertElevenLabsVoiceSettings(voiceSettings);
754
- const normalizedLanguage = normalizeLanguageCode(languageCode);
755
- const normalizedNormalization = normalizeApplyTextNormalization(applyTextNormalization);
756
- const normalizedSeed = normalizeSeed(seed);
757
- const controller = new AbortController();
758
- const timeout = setTimeout(() => controller.abort(), timeoutMs);
759
- try {
760
- const url = new URL(`${normalizeElevenLabsBaseUrl(baseUrl)}/v1/text-to-speech/${voiceId}`);
761
- if (outputFormat) url.searchParams.set("output_format", outputFormat);
762
- const response = await fetch(url.toString(), {
763
- method: "POST",
764
- headers: {
765
- "xi-api-key": apiKey,
766
- "Content-Type": "application/json",
767
- Accept: "audio/mpeg"
768
- },
769
- body: JSON.stringify({
770
- text,
771
- model_id: modelId,
772
- seed: normalizedSeed,
773
- apply_text_normalization: normalizedNormalization,
774
- language_code: normalizedLanguage,
775
- voice_settings: {
776
- stability: voiceSettings.stability,
777
- similarity_boost: voiceSettings.similarityBoost,
778
- style: voiceSettings.style,
779
- use_speaker_boost: voiceSettings.useSpeakerBoost,
780
- speed: voiceSettings.speed
781
- }
782
- }),
783
- signal: controller.signal
784
- });
785
- if (!response.ok) throw new Error(`ElevenLabs API error (${response.status})`);
786
- return Buffer.from(await response.arrayBuffer());
787
- } finally {
788
- clearTimeout(timeout);
789
- }
790
- }
791
- async function openaiTTS(params) {
792
- const { text, apiKey, model, voice, responseFormat, timeoutMs } = params;
793
- if (!isValidOpenAIModel(model)) throw new Error(`Invalid model: ${model}`);
794
- if (!isValidOpenAIVoice(voice)) throw new Error(`Invalid voice: ${voice}`);
795
- const controller = new AbortController();
796
- const timeout = setTimeout(() => controller.abort(), timeoutMs);
797
- try {
798
- const response = await fetch(`${getOpenAITtsBaseUrl()}/audio/speech`, {
799
- method: "POST",
800
- headers: {
801
- Authorization: `Bearer ${apiKey}`,
802
- "Content-Type": "application/json"
803
- },
804
- body: JSON.stringify({
805
- model,
806
- input: text,
807
- voice,
808
- response_format: responseFormat
809
- }),
810
- signal: controller.signal
811
- });
812
- if (!response.ok) throw new Error(`OpenAI TTS API error (${response.status})`);
813
- return Buffer.from(await response.arrayBuffer());
814
- } finally {
815
- clearTimeout(timeout);
816
- }
817
- }
818
- function inferEdgeExtension(outputFormat) {
819
- const normalized = outputFormat.toLowerCase();
820
- if (normalized.includes("webm")) return ".webm";
821
- if (normalized.includes("ogg")) return ".ogg";
822
- if (normalized.includes("opus")) return ".opus";
823
- if (normalized.includes("wav") || normalized.includes("riff") || normalized.includes("pcm")) return ".wav";
824
- return ".mp3";
825
- }
826
- async function edgeTTS(params) {
827
- const { text, outputPath, config, timeoutMs } = params;
828
- await new EdgeTTS({
829
- voice: config.voice,
830
- lang: config.lang,
831
- outputFormat: config.outputFormat,
832
- saveSubtitles: config.saveSubtitles,
833
- proxy: config.proxy,
834
- rate: config.rate,
835
- pitch: config.pitch,
836
- volume: config.volume,
837
- timeout: config.timeoutMs ?? timeoutMs
838
- }).ttsPromise(text, outputPath);
839
- }
840
-
841
- //#endregion
842
- //#region src/tts/tts.ts
843
- const DEFAULT_TIMEOUT_MS = 3e4;
844
- const DEFAULT_TTS_MAX_LENGTH = 1500;
845
- const DEFAULT_TTS_SUMMARIZE = true;
846
- const DEFAULT_MAX_TEXT_LENGTH = 4096;
847
- const DEFAULT_ELEVENLABS_BASE_URL = "https://api.elevenlabs.io";
848
- const DEFAULT_ELEVENLABS_VOICE_ID = "pMsXgVXv3BLzUgSXRplE";
849
- const DEFAULT_ELEVENLABS_MODEL_ID = "eleven_multilingual_v2";
850
- const DEFAULT_OPENAI_MODEL = "gpt-4o-mini-tts";
851
- const DEFAULT_OPENAI_VOICE = "alloy";
852
- const DEFAULT_EDGE_VOICE = "en-US-MichelleNeural";
853
- const DEFAULT_EDGE_LANG = "en-US";
854
- const DEFAULT_EDGE_OUTPUT_FORMAT = "audio-24khz-48kbitrate-mono-mp3";
855
- const DEFAULT_ELEVENLABS_VOICE_SETTINGS = {
856
- stability: .5,
857
- similarityBoost: .75,
858
- style: 0,
859
- useSpeakerBoost: true,
860
- speed: 1
861
- };
862
- const TELEGRAM_OUTPUT = {
863
- openai: "opus",
864
- elevenlabs: "opus_48000_64",
865
- extension: ".opus",
866
- voiceCompatible: true
867
- };
868
- const DEFAULT_OUTPUT = {
869
- openai: "mp3",
870
- elevenlabs: "mp3_44100_128",
871
- extension: ".mp3",
872
- voiceCompatible: false
873
- };
874
- const TELEPHONY_OUTPUT = {
875
- openai: {
876
- format: "pcm",
877
- sampleRate: 24e3
878
- },
879
- elevenlabs: {
880
- format: "pcm_22050",
881
- sampleRate: 22050
882
- }
883
- };
884
- const TTS_AUTO_MODES = new Set([
885
- "off",
886
- "always",
887
- "inbound",
888
- "tagged"
889
- ]);
890
- let lastTtsAttempt;
891
- function normalizeTtsAutoMode(value) {
892
- if (typeof value !== "string") return;
893
- const normalized = value.trim().toLowerCase();
894
- if (TTS_AUTO_MODES.has(normalized)) return normalized;
895
- }
896
- function resolveModelOverridePolicy(overrides) {
897
- if (!(overrides?.enabled ?? true)) return {
898
- enabled: false,
899
- allowText: false,
900
- allowProvider: false,
901
- allowVoice: false,
902
- allowModelId: false,
903
- allowVoiceSettings: false,
904
- allowNormalization: false,
905
- allowSeed: false
906
- };
907
- const allow = (value) => value ?? true;
908
- return {
909
- enabled: true,
910
- allowText: allow(overrides?.allowText),
911
- allowProvider: allow(overrides?.allowProvider),
912
- allowVoice: allow(overrides?.allowVoice),
913
- allowModelId: allow(overrides?.allowModelId),
914
- allowVoiceSettings: allow(overrides?.allowVoiceSettings),
915
- allowNormalization: allow(overrides?.allowNormalization),
916
- allowSeed: allow(overrides?.allowSeed)
917
- };
918
- }
919
- function resolveTtsConfig(cfg) {
920
- const raw = cfg.messages?.tts ?? {};
921
- const providerSource = raw.provider ? "config" : "default";
922
- const edgeOutputFormat = raw.edge?.outputFormat?.trim();
923
- return {
924
- auto: normalizeTtsAutoMode(raw.auto) ?? (raw.enabled ? "always" : "off"),
925
- mode: raw.mode ?? "final",
926
- provider: raw.provider ?? "edge",
927
- providerSource,
928
- summaryModel: raw.summaryModel?.trim() || void 0,
929
- modelOverrides: resolveModelOverridePolicy(raw.modelOverrides),
930
- elevenlabs: {
931
- apiKey: raw.elevenlabs?.apiKey,
932
- baseUrl: raw.elevenlabs?.baseUrl?.trim() || DEFAULT_ELEVENLABS_BASE_URL,
933
- voiceId: raw.elevenlabs?.voiceId ?? DEFAULT_ELEVENLABS_VOICE_ID,
934
- modelId: raw.elevenlabs?.modelId ?? DEFAULT_ELEVENLABS_MODEL_ID,
935
- seed: raw.elevenlabs?.seed,
936
- applyTextNormalization: raw.elevenlabs?.applyTextNormalization,
937
- languageCode: raw.elevenlabs?.languageCode,
938
- voiceSettings: {
939
- stability: raw.elevenlabs?.voiceSettings?.stability ?? DEFAULT_ELEVENLABS_VOICE_SETTINGS.stability,
940
- similarityBoost: raw.elevenlabs?.voiceSettings?.similarityBoost ?? DEFAULT_ELEVENLABS_VOICE_SETTINGS.similarityBoost,
941
- style: raw.elevenlabs?.voiceSettings?.style ?? DEFAULT_ELEVENLABS_VOICE_SETTINGS.style,
942
- useSpeakerBoost: raw.elevenlabs?.voiceSettings?.useSpeakerBoost ?? DEFAULT_ELEVENLABS_VOICE_SETTINGS.useSpeakerBoost,
943
- speed: raw.elevenlabs?.voiceSettings?.speed ?? DEFAULT_ELEVENLABS_VOICE_SETTINGS.speed
944
- }
945
- },
946
- openai: {
947
- apiKey: raw.openai?.apiKey,
948
- model: raw.openai?.model ?? DEFAULT_OPENAI_MODEL,
949
- voice: raw.openai?.voice ?? DEFAULT_OPENAI_VOICE
950
- },
951
- edge: {
952
- enabled: raw.edge?.enabled ?? true,
953
- voice: raw.edge?.voice?.trim() || DEFAULT_EDGE_VOICE,
954
- lang: raw.edge?.lang?.trim() || DEFAULT_EDGE_LANG,
955
- outputFormat: edgeOutputFormat || DEFAULT_EDGE_OUTPUT_FORMAT,
956
- outputFormatConfigured: Boolean(edgeOutputFormat),
957
- pitch: raw.edge?.pitch?.trim() || void 0,
958
- rate: raw.edge?.rate?.trim() || void 0,
959
- volume: raw.edge?.volume?.trim() || void 0,
960
- saveSubtitles: raw.edge?.saveSubtitles ?? false,
961
- proxy: raw.edge?.proxy?.trim() || void 0,
962
- timeoutMs: raw.edge?.timeoutMs
963
- },
964
- prefsPath: raw.prefsPath,
965
- maxTextLength: raw.maxTextLength ?? DEFAULT_MAX_TEXT_LENGTH,
966
- timeoutMs: raw.timeoutMs ?? DEFAULT_TIMEOUT_MS
967
- };
968
- }
969
- function resolveTtsPrefsPath(config) {
970
- if (config.prefsPath?.trim()) return resolveUserPath(config.prefsPath.trim());
971
- const envPath = process.env.ANIMA_TTS_PREFS?.trim();
972
- if (envPath) return resolveUserPath(envPath);
973
- return path.join(CONFIG_DIR, "settings", "tts.json");
974
- }
975
- function resolveTtsAutoModeFromPrefs(prefs) {
976
- const auto = normalizeTtsAutoMode(prefs.tts?.auto);
977
- if (auto) return auto;
978
- if (typeof prefs.tts?.enabled === "boolean") return prefs.tts.enabled ? "always" : "off";
979
- }
980
- function resolveTtsAutoMode(params) {
981
- const sessionAuto = normalizeTtsAutoMode(params.sessionAuto);
982
- if (sessionAuto) return sessionAuto;
983
- const prefsAuto = resolveTtsAutoModeFromPrefs(readPrefs(params.prefsPath));
984
- if (prefsAuto) return prefsAuto;
985
- return params.config.auto;
986
- }
987
- function buildTtsSystemPromptHint(cfg) {
988
- const config = resolveTtsConfig(cfg);
989
- const prefsPath = resolveTtsPrefsPath(config);
990
- const autoMode = resolveTtsAutoMode({
991
- config,
992
- prefsPath
993
- });
994
- if (autoMode === "off") return;
995
- const maxLength = getTtsMaxLength(prefsPath);
996
- const summarize = isSummarizationEnabled(prefsPath) ? "on" : "off";
997
- return [
998
- "Voice (TTS) is enabled.",
999
- autoMode === "inbound" ? "Only use TTS when the user's last message includes audio/voice." : autoMode === "tagged" ? "Only use TTS when you include [[tts]] or [[tts:text]] tags." : void 0,
1000
- `Keep spoken text ≤${maxLength} chars to avoid auto-summary (summary ${summarize}).`,
1001
- "Use [[tts:...]] and optional [[tts:text]]...[[/tts:text]] to control voice/expressiveness."
1002
- ].filter(Boolean).join("\n");
1003
- }
1004
- function readPrefs(prefsPath) {
1005
- try {
1006
- if (!existsSync(prefsPath)) return {};
1007
- return JSON.parse(readFileSync(prefsPath, "utf8"));
1008
- } catch {
1009
- return {};
1010
- }
1011
- }
1012
- function atomicWriteFileSync(filePath, content) {
1013
- const tmpPath = `${filePath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
1014
- writeFileSync(tmpPath, content);
1015
- try {
1016
- renameSync(tmpPath, filePath);
1017
- } catch (err) {
1018
- try {
1019
- unlinkSync(tmpPath);
1020
- } catch {}
1021
- throw err;
1022
- }
1023
- }
1024
- function updatePrefs(prefsPath, update) {
1025
- const prefs = readPrefs(prefsPath);
1026
- update(prefs);
1027
- mkdirSync(path.dirname(prefsPath), { recursive: true });
1028
- atomicWriteFileSync(prefsPath, JSON.stringify(prefs, null, 2));
1029
- }
1030
- function isTtsEnabled(config, prefsPath, sessionAuto) {
1031
- return resolveTtsAutoMode({
1032
- config,
1033
- prefsPath,
1034
- sessionAuto
1035
- }) !== "off";
1036
- }
1037
- function setTtsAutoMode(prefsPath, mode) {
1038
- updatePrefs(prefsPath, (prefs) => {
1039
- const next = { ...prefs.tts };
1040
- delete next.enabled;
1041
- next.auto = mode;
1042
- prefs.tts = next;
1043
- });
1044
- }
1045
- function setTtsEnabled(prefsPath, enabled) {
1046
- setTtsAutoMode(prefsPath, enabled ? "always" : "off");
1047
- }
1048
- function getTtsProvider(config, prefsPath) {
1049
- const prefs = readPrefs(prefsPath);
1050
- if (prefs.tts?.provider) return prefs.tts.provider;
1051
- if (config.providerSource === "config") return config.provider;
1052
- if (resolveTtsApiKey(config, "openai")) return "openai";
1053
- if (resolveTtsApiKey(config, "elevenlabs")) return "elevenlabs";
1054
- return "edge";
1055
- }
1056
- function setTtsProvider(prefsPath, provider) {
1057
- updatePrefs(prefsPath, (prefs) => {
1058
- prefs.tts = {
1059
- ...prefs.tts,
1060
- provider
1061
- };
1062
- });
1063
- }
1064
- function getTtsMaxLength(prefsPath) {
1065
- return readPrefs(prefsPath).tts?.maxLength ?? DEFAULT_TTS_MAX_LENGTH;
1066
- }
1067
- function setTtsMaxLength(prefsPath, maxLength) {
1068
- updatePrefs(prefsPath, (prefs) => {
1069
- prefs.tts = {
1070
- ...prefs.tts,
1071
- maxLength
1072
- };
1073
- });
1074
- }
1075
- function isSummarizationEnabled(prefsPath) {
1076
- return readPrefs(prefsPath).tts?.summarize ?? DEFAULT_TTS_SUMMARIZE;
1077
- }
1078
- function setSummarizationEnabled(prefsPath, enabled) {
1079
- updatePrefs(prefsPath, (prefs) => {
1080
- prefs.tts = {
1081
- ...prefs.tts,
1082
- summarize: enabled
1083
- };
1084
- });
1085
- }
1086
- function getLastTtsAttempt() {
1087
- return lastTtsAttempt;
1088
- }
1089
- function setLastTtsAttempt(entry) {
1090
- lastTtsAttempt = entry;
1091
- }
1092
- function resolveOutputFormat(channelId) {
1093
- if (channelId === "telegram") return TELEGRAM_OUTPUT;
1094
- return DEFAULT_OUTPUT;
1095
- }
1096
- function resolveChannelId(channel) {
1097
- return channel ? normalizeChannelId(channel) : null;
1098
- }
1099
- function resolveEdgeOutputFormat(config) {
1100
- return config.edge.outputFormat;
1101
- }
1102
- function resolveTtsApiKey(config, provider) {
1103
- if (provider === "elevenlabs") return config.elevenlabs.apiKey || process.env.ELEVENLABS_API_KEY || process.env.XI_API_KEY;
1104
- if (provider === "openai") return config.openai.apiKey || process.env.OPENAI_API_KEY;
1105
- }
1106
- const TTS_PROVIDERS = [
1107
- "openai",
1108
- "elevenlabs",
1109
- "edge"
1110
- ];
1111
- function resolveTtsProviderOrder(primary) {
1112
- return [primary, ...TTS_PROVIDERS.filter((provider) => provider !== primary)];
1113
- }
1114
- function isTtsProviderConfigured(config, provider) {
1115
- if (provider === "edge") return config.edge.enabled;
1116
- return Boolean(resolveTtsApiKey(config, provider));
1117
- }
1118
- async function textToSpeech(params) {
1119
- const config = resolveTtsConfig(params.cfg);
1120
- const prefsPath = params.prefsPath ?? resolveTtsPrefsPath(config);
1121
- const output = resolveOutputFormat(resolveChannelId(params.channel));
1122
- if (params.text.length > config.maxTextLength) return {
1123
- success: false,
1124
- error: `Text too long (${params.text.length} chars, max ${config.maxTextLength})`
1125
- };
1126
- const userProvider = getTtsProvider(config, prefsPath);
1127
- const providers = resolveTtsProviderOrder(params.overrides?.provider ?? userProvider);
1128
- let lastError;
1129
- for (const provider of providers) {
1130
- const providerStart = Date.now();
1131
- try {
1132
- if (provider === "edge") {
1133
- if (!config.edge.enabled) {
1134
- lastError = "edge: disabled";
1135
- continue;
1136
- }
1137
- const tempDir = mkdtempSync(path.join(tmpdir(), "tts-"));
1138
- let edgeOutputFormat = resolveEdgeOutputFormat(config);
1139
- const fallbackEdgeOutputFormat = edgeOutputFormat !== DEFAULT_EDGE_OUTPUT_FORMAT ? DEFAULT_EDGE_OUTPUT_FORMAT : void 0;
1140
- const attemptEdgeTts = async (outputFormat) => {
1141
- const extension = inferEdgeExtension(outputFormat);
1142
- const audioPath = path.join(tempDir, `voice-${Date.now()}${extension}`);
1143
- await edgeTTS({
1144
- text: params.text,
1145
- outputPath: audioPath,
1146
- config: {
1147
- ...config.edge,
1148
- outputFormat
1149
- },
1150
- timeoutMs: config.timeoutMs
1151
- });
1152
- return {
1153
- audioPath,
1154
- outputFormat
1155
- };
1156
- };
1157
- let edgeResult;
1158
- try {
1159
- edgeResult = await attemptEdgeTts(edgeOutputFormat);
1160
- } catch (err) {
1161
- if (fallbackEdgeOutputFormat && fallbackEdgeOutputFormat !== edgeOutputFormat) {
1162
- logVerbose(`TTS: Edge output ${edgeOutputFormat} failed; retrying with ${fallbackEdgeOutputFormat}.`);
1163
- edgeOutputFormat = fallbackEdgeOutputFormat;
1164
- try {
1165
- edgeResult = await attemptEdgeTts(edgeOutputFormat);
1166
- } catch (fallbackErr) {
1167
- try {
1168
- rmSync(tempDir, {
1169
- recursive: true,
1170
- force: true
1171
- });
1172
- } catch {}
1173
- throw fallbackErr;
1174
- }
1175
- } else {
1176
- try {
1177
- rmSync(tempDir, {
1178
- recursive: true,
1179
- force: true
1180
- });
1181
- } catch {}
1182
- throw err;
1183
- }
1184
- }
1185
- scheduleCleanup(tempDir);
1186
- const voiceCompatible = isVoiceCompatibleAudio({ fileName: edgeResult.audioPath });
1187
- return {
1188
- success: true,
1189
- audioPath: edgeResult.audioPath,
1190
- latencyMs: Date.now() - providerStart,
1191
- provider,
1192
- outputFormat: edgeResult.outputFormat,
1193
- voiceCompatible
1194
- };
1195
- }
1196
- const apiKey = resolveTtsApiKey(config, provider);
1197
- if (!apiKey) {
1198
- lastError = `No API key for ${provider}`;
1199
- continue;
1200
- }
1201
- let audioBuffer;
1202
- if (provider === "elevenlabs") {
1203
- const voiceIdOverride = params.overrides?.elevenlabs?.voiceId;
1204
- const modelIdOverride = params.overrides?.elevenlabs?.modelId;
1205
- const voiceSettings = {
1206
- ...config.elevenlabs.voiceSettings,
1207
- ...params.overrides?.elevenlabs?.voiceSettings
1208
- };
1209
- const seedOverride = params.overrides?.elevenlabs?.seed;
1210
- const normalizationOverride = params.overrides?.elevenlabs?.applyTextNormalization;
1211
- const languageOverride = params.overrides?.elevenlabs?.languageCode;
1212
- audioBuffer = await elevenLabsTTS({
1213
- text: params.text,
1214
- apiKey,
1215
- baseUrl: config.elevenlabs.baseUrl,
1216
- voiceId: voiceIdOverride ?? config.elevenlabs.voiceId,
1217
- modelId: modelIdOverride ?? config.elevenlabs.modelId,
1218
- outputFormat: output.elevenlabs,
1219
- seed: seedOverride ?? config.elevenlabs.seed,
1220
- applyTextNormalization: normalizationOverride ?? config.elevenlabs.applyTextNormalization,
1221
- languageCode: languageOverride ?? config.elevenlabs.languageCode,
1222
- voiceSettings,
1223
- timeoutMs: config.timeoutMs
1224
- });
1225
- } else {
1226
- const openaiModelOverride = params.overrides?.openai?.model;
1227
- const openaiVoiceOverride = params.overrides?.openai?.voice;
1228
- audioBuffer = await openaiTTS({
1229
- text: params.text,
1230
- apiKey,
1231
- model: openaiModelOverride ?? config.openai.model,
1232
- voice: openaiVoiceOverride ?? config.openai.voice,
1233
- responseFormat: output.openai,
1234
- timeoutMs: config.timeoutMs
1235
- });
1236
- }
1237
- const latencyMs = Date.now() - providerStart;
1238
- const tempDir = mkdtempSync(path.join(tmpdir(), "tts-"));
1239
- const audioPath = path.join(tempDir, `voice-${Date.now()}${output.extension}`);
1240
- writeFileSync(audioPath, audioBuffer);
1241
- scheduleCleanup(tempDir);
1242
- return {
1243
- success: true,
1244
- audioPath,
1245
- latencyMs,
1246
- provider,
1247
- outputFormat: provider === "openai" ? output.openai : output.elevenlabs,
1248
- voiceCompatible: output.voiceCompatible
1249
- };
1250
- } catch (err) {
1251
- const error = err;
1252
- if (error.name === "AbortError") lastError = `${provider}: request timed out`;
1253
- else lastError = `${provider}: ${error.message}`;
1254
- }
1255
- }
1256
- return {
1257
- success: false,
1258
- error: `TTS conversion failed: ${lastError || "no providers available"}`
1259
- };
1260
- }
1261
- async function textToSpeechTelephony(params) {
1262
- const config = resolveTtsConfig(params.cfg);
1263
- const prefsPath = params.prefsPath ?? resolveTtsPrefsPath(config);
1264
- if (params.text.length > config.maxTextLength) return {
1265
- success: false,
1266
- error: `Text too long (${params.text.length} chars, max ${config.maxTextLength})`
1267
- };
1268
- const providers = resolveTtsProviderOrder(getTtsProvider(config, prefsPath));
1269
- let lastError;
1270
- for (const provider of providers) {
1271
- const providerStart = Date.now();
1272
- try {
1273
- if (provider === "edge") {
1274
- lastError = "edge: unsupported for telephony";
1275
- continue;
1276
- }
1277
- const apiKey = resolveTtsApiKey(config, provider);
1278
- if (!apiKey) {
1279
- lastError = `No API key for ${provider}`;
1280
- continue;
1281
- }
1282
- if (provider === "elevenlabs") {
1283
- const output = TELEPHONY_OUTPUT.elevenlabs;
1284
- return {
1285
- success: true,
1286
- audioBuffer: await elevenLabsTTS({
1287
- text: params.text,
1288
- apiKey,
1289
- baseUrl: config.elevenlabs.baseUrl,
1290
- voiceId: config.elevenlabs.voiceId,
1291
- modelId: config.elevenlabs.modelId,
1292
- outputFormat: output.format,
1293
- seed: config.elevenlabs.seed,
1294
- applyTextNormalization: config.elevenlabs.applyTextNormalization,
1295
- languageCode: config.elevenlabs.languageCode,
1296
- voiceSettings: config.elevenlabs.voiceSettings,
1297
- timeoutMs: config.timeoutMs
1298
- }),
1299
- latencyMs: Date.now() - providerStart,
1300
- provider,
1301
- outputFormat: output.format,
1302
- sampleRate: output.sampleRate
1303
- };
1304
- }
1305
- const output = TELEPHONY_OUTPUT.openai;
1306
- return {
1307
- success: true,
1308
- audioBuffer: await openaiTTS({
1309
- text: params.text,
1310
- apiKey,
1311
- model: config.openai.model,
1312
- voice: config.openai.voice,
1313
- responseFormat: output.format,
1314
- timeoutMs: config.timeoutMs
1315
- }),
1316
- latencyMs: Date.now() - providerStart,
1317
- provider,
1318
- outputFormat: output.format,
1319
- sampleRate: output.sampleRate
1320
- };
1321
- } catch (err) {
1322
- const error = err;
1323
- if (error.name === "AbortError") lastError = `${provider}: request timed out`;
1324
- else lastError = `${provider}: ${error.message}`;
1325
- }
1326
- }
1327
- return {
1328
- success: false,
1329
- error: `TTS conversion failed: ${lastError || "no providers available"}`
1330
- };
1331
- }
1332
- async function maybeApplyTtsToPayload(params) {
1333
- const config = resolveTtsConfig(params.cfg);
1334
- const prefsPath = resolveTtsPrefsPath(config);
1335
- const autoMode = resolveTtsAutoMode({
1336
- config,
1337
- prefsPath,
1338
- sessionAuto: params.ttsAuto
1339
- });
1340
- if (autoMode === "off") return params.payload;
1341
- const text = params.payload.text ?? "";
1342
- const directives = parseTtsDirectives(text, config.modelOverrides);
1343
- if (directives.warnings.length > 0) logVerbose(`TTS: ignored directive overrides (${directives.warnings.join("; ")})`);
1344
- const trimmedCleaned = directives.cleanedText.trim();
1345
- const visibleText = trimmedCleaned.length > 0 ? trimmedCleaned : "";
1346
- const ttsText = directives.ttsText?.trim() || visibleText;
1347
- const nextPayload = visibleText === text.trim() ? params.payload : {
1348
- ...params.payload,
1349
- text: visibleText.length > 0 ? visibleText : void 0
1350
- };
1351
- if (autoMode === "tagged" && !directives.hasDirective) return nextPayload;
1352
- if (autoMode === "inbound" && params.inboundAudio !== true) return nextPayload;
1353
- if ((config.mode ?? "final") === "final" && params.kind && params.kind !== "final") return nextPayload;
1354
- if (!ttsText.trim()) return nextPayload;
1355
- if (params.payload.mediaUrl || (params.payload.mediaUrls?.length ?? 0) > 0) return nextPayload;
1356
- if (text.includes("MEDIA:")) return nextPayload;
1357
- if (ttsText.trim().length < 10) return nextPayload;
1358
- const maxLength = getTtsMaxLength(prefsPath);
1359
- let textForAudio = ttsText.trim();
1360
- let wasSummarized = false;
1361
- if (textForAudio.length > maxLength) if (!isSummarizationEnabled(prefsPath)) {
1362
- logVerbose(`TTS: truncating long text (${textForAudio.length} > ${maxLength}), summarization disabled.`);
1363
- textForAudio = `${textForAudio.slice(0, maxLength - 3)}...`;
1364
- } else try {
1365
- textForAudio = (await summarizeText({
1366
- text: textForAudio,
1367
- targetLength: maxLength,
1368
- cfg: params.cfg,
1369
- config,
1370
- timeoutMs: config.timeoutMs
1371
- })).summary;
1372
- wasSummarized = true;
1373
- if (textForAudio.length > config.maxTextLength) {
1374
- logVerbose(`TTS: summary exceeded hard limit (${textForAudio.length} > ${config.maxTextLength}); truncating.`);
1375
- textForAudio = `${textForAudio.slice(0, config.maxTextLength - 3)}...`;
1376
- }
1377
- } catch (err) {
1378
- logVerbose(`TTS: summarization failed, truncating instead: ${err.message}`);
1379
- textForAudio = `${textForAudio.slice(0, maxLength - 3)}...`;
1380
- }
1381
- textForAudio = stripMarkdown(textForAudio).trim();
1382
- if (textForAudio.length < 10) return nextPayload;
1383
- const ttsStart = Date.now();
1384
- const result = await textToSpeech({
1385
- text: textForAudio,
1386
- cfg: params.cfg,
1387
- prefsPath,
1388
- channel: params.channel,
1389
- overrides: directives.overrides
1390
- });
1391
- if (result.success && result.audioPath) {
1392
- lastTtsAttempt = {
1393
- timestamp: Date.now(),
1394
- success: true,
1395
- textLength: text.length,
1396
- summarized: wasSummarized,
1397
- provider: result.provider,
1398
- latencyMs: result.latencyMs
1399
- };
1400
- const shouldVoice = resolveChannelId(params.channel) === "telegram" && result.voiceCompatible === true;
1401
- return {
1402
- ...nextPayload,
1403
- mediaUrl: result.audioPath,
1404
- audioAsVoice: shouldVoice || params.payload.audioAsVoice
1405
- };
1406
- }
1407
- lastTtsAttempt = {
1408
- timestamp: Date.now(),
1409
- success: false,
1410
- textLength: text.length,
1411
- summarized: wasSummarized,
1412
- error: result.error
1413
- };
1414
- logVerbose(`TTS: conversion failed after ${Date.now() - ttsStart}ms (${result.error ?? "unknown"}).`);
1415
- return nextPayload;
1416
- }
1417
-
1418
- //#endregion
1419
- //#region src/agents/model-alias-lines.ts
1420
- function buildModelAliasLines(cfg) {
1421
- const models = cfg?.agents?.defaults?.models ?? {};
1422
- const entries = [];
1423
- for (const [keyRaw, entryRaw] of Object.entries(models)) {
1424
- const model = String(keyRaw ?? "").trim();
1425
- if (!model) continue;
1426
- const alias = String(entryRaw?.alias ?? "").trim();
1427
- if (!alias) continue;
1428
- entries.push({
1429
- alias,
1430
- model
1431
- });
1432
- }
1433
- return entries.toSorted((a, b) => a.alias.localeCompare(b.alias)).map((entry) => `- ${entry.alias}: ${entry.model}`);
1434
- }
1435
-
1436
- //#endregion
1437
- //#region src/agents/shell-utils.ts
1438
- function resolvePowerShellPath() {
1439
- const systemRoot = process.env.SystemRoot || process.env.WINDIR;
1440
- if (systemRoot) {
1441
- const candidate = path.join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
1442
- if (fs$1.existsSync(candidate)) return candidate;
1443
- }
1444
- return "powershell.exe";
1445
- }
1446
- function getShellConfig() {
1447
- if (process.platform === "win32") return {
1448
- shell: resolvePowerShellPath(),
1449
- args: [
1450
- "-NoProfile",
1451
- "-NonInteractive",
1452
- "-Command"
1453
- ]
1454
- };
1455
- const envShell = process.env.SHELL?.trim();
1456
- if ((envShell ? path.basename(envShell) : "") === "fish") {
1457
- const bash = resolveShellFromPath("bash");
1458
- if (bash) return {
1459
- shell: bash,
1460
- args: ["-c"]
1461
- };
1462
- const sh = resolveShellFromPath("sh");
1463
- if (sh) return {
1464
- shell: sh,
1465
- args: ["-c"]
1466
- };
1467
- }
1468
- return {
1469
- shell: envShell && envShell.length > 0 ? envShell : "sh",
1470
- args: ["-c"]
1471
- };
1472
- }
1473
- function resolveShellFromPath(name) {
1474
- const envPath = process.env.PATH ?? "";
1475
- if (!envPath) return;
1476
- const entries = envPath.split(path.delimiter).filter(Boolean);
1477
- for (const entry of entries) {
1478
- const candidate = path.join(entry, name);
1479
- try {
1480
- fs$1.accessSync(candidate, fs$1.constants.X_OK);
1481
- return candidate;
1482
- } catch {}
1483
- }
1484
- }
1485
- function normalizeShellName(value) {
1486
- const trimmed = value.trim();
1487
- if (!trimmed) return "";
1488
- return path.basename(trimmed).replace(/\.(exe|cmd|bat)$/i, "").replace(/[^a-zA-Z0-9_-]/g, "");
1489
- }
1490
- function detectRuntimeShell() {
1491
- const overrideShell = process.env.ANIMA_SHELL?.trim();
1492
- if (overrideShell) {
1493
- const name = normalizeShellName(overrideShell);
1494
- if (name) return name;
1495
- }
1496
- if (process.platform === "win32") {
1497
- if (process.env.POWERSHELL_DISTRIBUTION_CHANNEL) return "pwsh";
1498
- return "powershell";
1499
- }
1500
- const envShell = process.env.SHELL?.trim();
1501
- if (envShell) {
1502
- const name = normalizeShellName(envShell);
1503
- if (name) return name;
1504
- }
1505
- if (process.env.POWERSHELL_DISTRIBUTION_CHANNEL) return "pwsh";
1506
- if (process.env.BASH_VERSION) return "bash";
1507
- if (process.env.ZSH_VERSION) return "zsh";
1508
- if (process.env.FISH_VERSION) return "fish";
1509
- if (process.env.KSH_VERSION) return "ksh";
1510
- if (process.env.NU_VERSION || process.env.NUSHELL_VERSION) return "nu";
1511
- }
1512
- function sanitizeBinaryOutput(text) {
1513
- const scrubbed = text.replace(/[\p{Format}\p{Surrogate}]/gu, "");
1514
- if (!scrubbed) return scrubbed;
1515
- const chunks = [];
1516
- for (const char of scrubbed) {
1517
- const code = char.codePointAt(0);
1518
- if (code == null) continue;
1519
- if (code === 9 || code === 10 || code === 13) {
1520
- chunks.push(char);
1521
- continue;
1522
- }
1523
- if (code < 32) continue;
1524
- chunks.push(char);
1525
- }
1526
- return chunks.join("");
1527
- }
1528
- function killProcessTree(pid) {
1529
- if (process.platform === "win32") {
1530
- try {
1531
- spawn("taskkill", [
1532
- "/F",
1533
- "/T",
1534
- "/PID",
1535
- String(pid)
1536
- ], {
1537
- stdio: "ignore",
1538
- detached: true
1539
- });
1540
- } catch {}
1541
- return;
1542
- }
1543
- try {
1544
- process.kill(-pid, "SIGKILL");
1545
- } catch {
1546
- try {
1547
- process.kill(pid, "SIGKILL");
1548
- } catch {}
1549
- }
1550
- }
1551
-
1552
- //#endregion
1553
- //#region src/agents/date-time.ts
1554
- let cachedTimeFormat;
1555
- function resolveUserTimezone(configured) {
1556
- const trimmed = configured?.trim();
1557
- if (trimmed) try {
1558
- new Intl.DateTimeFormat("en-US", { timeZone: trimmed }).format(/* @__PURE__ */ new Date());
1559
- return trimmed;
1560
- } catch {}
1561
- return Intl.DateTimeFormat().resolvedOptions().timeZone?.trim() || "UTC";
1562
- }
1563
- function resolveUserTimeFormat(preference) {
1564
- if (preference === "12" || preference === "24") return preference;
1565
- if (cachedTimeFormat) return cachedTimeFormat;
1566
- cachedTimeFormat = detectSystemTimeFormat() ? "24" : "12";
1567
- return cachedTimeFormat;
1568
- }
1569
- function normalizeTimestamp(raw) {
1570
- if (raw == null) return;
1571
- let timestampMs;
1572
- if (raw instanceof Date) timestampMs = raw.getTime();
1573
- else if (typeof raw === "number" && Number.isFinite(raw)) timestampMs = raw < 0xe8d4a51000 ? Math.round(raw * 1e3) : Math.round(raw);
1574
- else if (typeof raw === "string") {
1575
- const trimmed = raw.trim();
1576
- if (!trimmed) return;
1577
- if (/^\d+(\.\d+)?$/.test(trimmed)) {
1578
- const num = Number(trimmed);
1579
- if (Number.isFinite(num)) if (trimmed.includes(".")) timestampMs = Math.round(num * 1e3);
1580
- else if (trimmed.length >= 13) timestampMs = Math.round(num);
1581
- else timestampMs = Math.round(num * 1e3);
1582
- } else {
1583
- const parsed = Date.parse(trimmed);
1584
- if (!Number.isNaN(parsed)) timestampMs = parsed;
1585
- }
1586
- }
1587
- if (timestampMs === void 0 || !Number.isFinite(timestampMs)) return;
1588
- return {
1589
- timestampMs,
1590
- timestampUtc: new Date(timestampMs).toISOString()
1591
- };
1592
- }
1593
- function withNormalizedTimestamp(value, rawTimestamp) {
1594
- const normalized = normalizeTimestamp(rawTimestamp);
1595
- if (!normalized) return value;
1596
- return {
1597
- ...value,
1598
- timestampMs: typeof value.timestampMs === "number" && Number.isFinite(value.timestampMs) ? value.timestampMs : normalized.timestampMs,
1599
- timestampUtc: typeof value.timestampUtc === "string" && value.timestampUtc.trim() ? value.timestampUtc : normalized.timestampUtc
1600
- };
1601
- }
1602
- function detectSystemTimeFormat() {
1603
- if (process.platform === "darwin") try {
1604
- const result = execSync("defaults read -g AppleICUForce24HourTime 2>/dev/null", {
1605
- encoding: "utf8",
1606
- timeout: 500
1607
- }).trim();
1608
- if (result === "1") return true;
1609
- if (result === "0") return false;
1610
- } catch {}
1611
- if (process.platform === "win32") try {
1612
- const result = execSync("powershell -Command \"(Get-Culture).DateTimeFormat.ShortTimePattern\"", {
1613
- encoding: "utf8",
1614
- timeout: 1e3
1615
- }).trim();
1616
- if (result.startsWith("H")) return true;
1617
- if (result.startsWith("h")) return false;
1618
- } catch {}
1619
- try {
1620
- const sample = new Date(2e3, 0, 1, 13, 0);
1621
- return new Intl.DateTimeFormat(void 0, { hour: "numeric" }).format(sample).includes("13");
1622
- } catch {
1623
- return false;
1624
- }
1625
- }
1626
- function ordinalSuffix(day) {
1627
- if (day >= 11 && day <= 13) return "th";
1628
- switch (day % 10) {
1629
- case 1: return "st";
1630
- case 2: return "nd";
1631
- case 3: return "rd";
1632
- default: return "th";
1633
- }
1634
- }
1635
- function formatUserTime(date, timeZone, format) {
1636
- const use24Hour = format === "24";
1637
- try {
1638
- const parts = new Intl.DateTimeFormat("en-US", {
1639
- timeZone,
1640
- weekday: "long",
1641
- year: "numeric",
1642
- month: "long",
1643
- day: "numeric",
1644
- hour: use24Hour ? "2-digit" : "numeric",
1645
- minute: "2-digit",
1646
- hourCycle: use24Hour ? "h23" : "h12"
1647
- }).formatToParts(date);
1648
- const map = {};
1649
- for (const part of parts) if (part.type !== "literal") map[part.type] = part.value;
1650
- if (!map.weekday || !map.year || !map.month || !map.day || !map.hour || !map.minute) return;
1651
- const dayNum = parseInt(map.day, 10);
1652
- const suffix = ordinalSuffix(dayNum);
1653
- const timePart = use24Hour ? `${map.hour}:${map.minute}` : `${map.hour}:${map.minute} ${map.dayPeriod ?? ""}`.trim();
1654
- return `${map.weekday}, ${map.month} ${dayNum}${suffix}, ${map.year} — ${timePart}`;
1655
- } catch {
1656
- return;
1657
- }
1658
- }
1659
-
1660
- //#endregion
1661
- //#region src/agents/system-prompt-params.ts
1662
- function buildSystemPromptParams(params) {
1663
- const repoRoot = resolveRepoRoot({
1664
- config: params.config,
1665
- workspaceDir: params.workspaceDir,
1666
- cwd: params.cwd
1667
- });
1668
- const userTimezone = resolveUserTimezone(params.config?.agents?.defaults?.userTimezone);
1669
- const userTimeFormat = resolveUserTimeFormat(params.config?.agents?.defaults?.timeFormat);
1670
- const userTime = formatUserTime(/* @__PURE__ */ new Date(), userTimezone, userTimeFormat);
1671
- return {
1672
- runtimeInfo: {
1673
- agentId: params.agentId,
1674
- ...params.runtime,
1675
- repoRoot
1676
- },
1677
- userTimezone,
1678
- userTime,
1679
- userTimeFormat
1680
- };
1681
- }
1682
- function resolveRepoRoot(params) {
1683
- const configured = params.config?.agents?.defaults?.repoRoot?.trim();
1684
- if (configured) try {
1685
- const resolved = path.resolve(configured);
1686
- if (fs$1.statSync(resolved).isDirectory()) return resolved;
1687
- } catch {}
1688
- const candidates = [params.workspaceDir, params.cwd].map((value) => value?.trim()).filter(Boolean);
1689
- const seen = /* @__PURE__ */ new Set();
1690
- for (const candidate of candidates) {
1691
- const resolved = path.resolve(candidate);
1692
- if (seen.has(resolved)) continue;
1693
- seen.add(resolved);
1694
- const root = findGitRoot(resolved);
1695
- if (root) return root;
1696
- }
1697
- }
1698
- function findGitRoot(startDir) {
1699
- let current = path.resolve(startDir);
1700
- for (let i = 0; i < 12; i += 1) {
1701
- const gitPath = path.join(current, ".git");
1702
- try {
1703
- const stat = fs$1.statSync(gitPath);
1704
- if (stat.isDirectory() || stat.isFile()) return current;
1705
- } catch {}
1706
- const parent = path.dirname(current);
1707
- if (parent === current) break;
1708
- current = parent;
1709
- }
1710
- return null;
1711
- }
1712
-
1713
- //#endregion
1714
- //#region src/agents/system-prompt.ts
1715
- function buildSkillsSection(params) {
1716
- if (params.isMinimal) return [];
1717
- const trimmed = params.skillsPrompt?.trim();
1718
- if (!trimmed) return [];
1719
- return [
1720
- "## Skills (mandatory)",
1721
- "Before replying: scan <available_skills> <description> entries.",
1722
- `- If exactly one skill clearly applies: read its SKILL.md at <location> with \`${params.readToolName}\`, then follow it.`,
1723
- "- If multiple could apply: choose the most specific one, then read/follow it.",
1724
- "- If none clearly apply: do not read any SKILL.md.",
1725
- "Constraints: never read more than one skill up front; only read after selecting.",
1726
- trimmed,
1727
- ""
1728
- ];
1729
- }
1730
- function buildMemorySection(params) {
1731
- if (params.isMinimal) return [];
1732
- if (!params.availableTools.has("memory_search") && !params.availableTools.has("memory_get")) return [];
1733
- const lines = ["## Memory Recall", "Before answering anything about prior work, decisions, dates, people, preferences, or todos: run memory_search on MEMORY.md + memory/*.md; then use memory_get to pull only the needed lines. If low confidence after search, say you checked."];
1734
- if (params.citationsMode === "off") lines.push("Citations are disabled: do not mention file paths or line numbers in replies unless the user explicitly asks.");
1735
- else lines.push("Citations: include Source: <path#line> when it helps the user verify memory snippets.");
1736
- lines.push("");
1737
- return lines;
1738
- }
1739
- function buildUserIdentitySection(ownerLine, isMinimal) {
1740
- if (!ownerLine || isMinimal) return [];
1741
- return [
1742
- "## User Identity",
1743
- ownerLine,
1744
- ""
1745
- ];
1746
- }
1747
- function buildTimeSection(params) {
1748
- if (!params.userTimezone) return [];
1749
- return [
1750
- "## Current Date & Time",
1751
- `Time zone: ${params.userTimezone}`,
1752
- ""
1753
- ];
1754
- }
1755
- function buildReplyTagsSection(isMinimal) {
1756
- if (isMinimal) return [];
1757
- return [
1758
- "## Reply Tags",
1759
- "To request a native reply/quote on supported surfaces, include one tag in your reply:",
1760
- "- [[reply_to_current]] replies to the triggering message.",
1761
- "- Prefer [[reply_to_current]]. Use [[reply_to:<id>]] only when an id was explicitly provided (e.g. by the user or a tool).",
1762
- "Whitespace inside the tag is allowed (e.g. [[ reply_to_current ]] / [[ reply_to: 123 ]]).",
1763
- "Tags are stripped before sending; support depends on the current channel config.",
1764
- ""
1765
- ];
1766
- }
1767
- function buildMessagingSection(params) {
1768
- if (params.isMinimal) return [];
1769
- return [
1770
- "## Messaging",
1771
- "- Reply in current session → automatically routes to the source channel (Signal, Telegram, etc.)",
1772
- "- Cross-session messaging → use sessions_send(sessionKey, message)",
1773
- "- Sub-agent orchestration → use subagents(action=list|steer|kill)",
1774
- "- `[System Message] ...` blocks are internal context and are not user-visible by default.",
1775
- "- If a `[System Message]` reports completed cron/subagent work and asks for a user update, rewrite it in your normal assistant voice and send that update (do not forward raw system text or default to NO_REPLY).",
1776
- "- Never use exec/curl for provider messaging; Anima handles all routing internally.",
1777
- params.availableTools.has("message") ? [
1778
- "",
1779
- "### message tool",
1780
- "- Use `message` for proactive sends + channel actions (polls, reactions, etc.).",
1781
- "- For `action=send`, include `to` and `message`.",
1782
- `- If multiple channels are configured, pass \`channel\` (${params.messageChannelOptions}).`,
1783
- `- If you use \`message\` (\`action=send\`) to deliver your user-visible reply, respond with ONLY: ${SILENT_REPLY_TOKEN} (avoid duplicate replies).`,
1784
- params.inlineButtonsEnabled ? "- Inline buttons supported. Use `action=send` with `buttons=[[{text,callback_data}]]` (callback_data routes back as a user message)." : params.runtimeChannel ? `- Inline buttons not enabled for ${params.runtimeChannel}. If you need them, ask to set ${params.runtimeChannel}.capabilities.inlineButtons ("dm"|"group"|"all"|"allowlist").` : "",
1785
- ...params.messageToolHints ?? []
1786
- ].filter(Boolean).join("\n") : "",
1787
- ""
1788
- ];
1789
- }
1790
- function buildVoiceSection(params) {
1791
- if (params.isMinimal) return [];
1792
- const hint = params.ttsHint?.trim();
1793
- if (!hint) return [];
1794
- return [
1795
- "## Voice (TTS)",
1796
- hint,
1797
- ""
1798
- ];
1799
- }
1800
- function buildDocsSection(params) {
1801
- const docsPath = params.docsPath?.trim();
1802
- if (!docsPath || params.isMinimal) return [];
1803
- return [
1804
- "## Documentation",
1805
- `Anima docs: ${docsPath}`,
1806
- "Mirror: https://docs.anima.ai",
1807
- "Source: https://github.com/anima/anima",
1808
- "Community: https://discord.com/invite/clawd",
1809
- "Find new skills: https://animahub.com",
1810
- "For Anima behavior, commands, config, or architecture: consult local docs first.",
1811
- "When diagnosing issues, run `anima status` yourself when possible; only ask the user if you lack access (e.g., sandboxed).",
1812
- ""
1813
- ];
1814
- }
1815
- function buildAgentSystemPrompt(params) {
1816
- const coreToolSummaries = {
1817
- read: "Read file contents",
1818
- write: "Create or overwrite files",
1819
- edit: "Make precise edits to files",
1820
- apply_patch: "Apply multi-file patches",
1821
- grep: "Search file contents for patterns",
1822
- find: "Find files by glob pattern",
1823
- ls: "List directory contents",
1824
- exec: "Run shell commands (pty available for TTY-required CLIs)",
1825
- process: "Manage background exec sessions",
1826
- web_search: "Search the web (Brave API)",
1827
- web_fetch: "Fetch and extract readable content from a URL",
1828
- browser: "Control web browser",
1829
- canvas: "Present/eval/snapshot the Canvas",
1830
- nodes: "List/describe/notify/camera/screen on paired nodes",
1831
- cron: "Manage cron jobs and wake events (use for reminders; when scheduling a reminder, write the systemEvent text as something that will read like a reminder when it fires, and mention that it is a reminder depending on the time gap between setting and firing; include recent context in reminder text if appropriate)",
1832
- message: "Send messages and channel actions",
1833
- gateway: "Restart, apply config, or run updates on the running Anima process",
1834
- agents_list: "List agent ids allowed for sessions_spawn",
1835
- sessions_list: "List other sessions (incl. sub-agents) with filters/last",
1836
- sessions_history: "Fetch history for another session/sub-agent",
1837
- sessions_send: "Send a message to another session/sub-agent",
1838
- sessions_spawn: "Spawn a sub-agent session",
1839
- subagents: "List, steer, or kill sub-agent runs for this requester session",
1840
- session_status: "Show a /status-equivalent status card (usage + time + Reasoning/Verbose/Elevated); use for model-use questions (📊 session_status); optional per-session model override",
1841
- image: "Analyze an image with the configured image model"
1842
- };
1843
- const toolOrder = [
1844
- "read",
1845
- "write",
1846
- "edit",
1847
- "apply_patch",
1848
- "grep",
1849
- "find",
1850
- "ls",
1851
- "exec",
1852
- "process",
1853
- "web_search",
1854
- "web_fetch",
1855
- "browser",
1856
- "canvas",
1857
- "nodes",
1858
- "cron",
1859
- "message",
1860
- "gateway",
1861
- "agents_list",
1862
- "sessions_list",
1863
- "sessions_history",
1864
- "sessions_send",
1865
- "subagents",
1866
- "session_status",
1867
- "image"
1868
- ];
1869
- const canonicalToolNames = (params.toolNames ?? []).map((tool) => tool.trim()).filter(Boolean);
1870
- const canonicalByNormalized = /* @__PURE__ */ new Map();
1871
- for (const name of canonicalToolNames) {
1872
- const normalized = name.toLowerCase();
1873
- if (!canonicalByNormalized.has(normalized)) canonicalByNormalized.set(normalized, name);
1874
- }
1875
- const resolveToolName = (normalized) => canonicalByNormalized.get(normalized) ?? normalized;
1876
- const normalizedTools = canonicalToolNames.map((tool) => tool.toLowerCase());
1877
- const availableTools = new Set(normalizedTools);
1878
- const externalToolSummaries = /* @__PURE__ */ new Map();
1879
- for (const [key, value] of Object.entries(params.toolSummaries ?? {})) {
1880
- const normalized = key.trim().toLowerCase();
1881
- if (!normalized || !value?.trim()) continue;
1882
- externalToolSummaries.set(normalized, value.trim());
1883
- }
1884
- const extraTools = Array.from(new Set(normalizedTools.filter((tool) => !toolOrder.includes(tool))));
1885
- const toolLines = toolOrder.filter((tool) => availableTools.has(tool)).map((tool) => {
1886
- const summary = coreToolSummaries[tool] ?? externalToolSummaries.get(tool);
1887
- const name = resolveToolName(tool);
1888
- return summary ? `- ${name}: ${summary}` : `- ${name}`;
1889
- });
1890
- for (const tool of extraTools.toSorted()) {
1891
- const summary = coreToolSummaries[tool] ?? externalToolSummaries.get(tool);
1892
- const name = resolveToolName(tool);
1893
- toolLines.push(summary ? `- ${name}: ${summary}` : `- ${name}`);
1894
- }
1895
- const hasGateway = availableTools.has("gateway");
1896
- const readToolName = resolveToolName("read");
1897
- const execToolName = resolveToolName("exec");
1898
- const processToolName = resolveToolName("process");
1899
- const extraSystemPrompt = params.extraSystemPrompt?.trim();
1900
- const ownerNumbers = (params.ownerNumbers ?? []).map((value) => value.trim()).filter(Boolean);
1901
- const ownerLine = ownerNumbers.length > 0 ? `Owner numbers: ${ownerNumbers.join(", ")}. Treat messages from these numbers as the user.` : void 0;
1902
- const reasoningHint = params.reasoningTagHint ? [
1903
- "ALL internal reasoning MUST be inside <think>...</think>.",
1904
- "Do not output any analysis outside <think>.",
1905
- "Format every reply as <think>...</think> then <final>...</final>, with no other text.",
1906
- "Only the final user-visible reply may appear inside <final>.",
1907
- "Only text inside <final> is shown to the user; everything else is discarded and never seen by the user.",
1908
- "Example:",
1909
- "<think>Short internal reasoning.</think>",
1910
- "<final>Hey there! What would you like to do next?</final>"
1911
- ].join(" ") : void 0;
1912
- const reasoningLevel = params.reasoningLevel ?? "off";
1913
- const userTimezone = params.userTimezone?.trim();
1914
- const skillsPrompt = params.skillsPrompt?.trim();
1915
- const heartbeatPrompt = params.heartbeatPrompt?.trim();
1916
- const heartbeatPromptLine = heartbeatPrompt ? `Heartbeat prompt: ${heartbeatPrompt}` : "Heartbeat prompt: (configured)";
1917
- const runtimeInfo = params.runtimeInfo;
1918
- const runtimeChannel = runtimeInfo?.channel?.trim().toLowerCase();
1919
- const runtimeCapabilities = (runtimeInfo?.capabilities ?? []).map((cap) => String(cap).trim()).filter(Boolean);
1920
- const inlineButtonsEnabled = new Set(runtimeCapabilities.map((cap) => cap.toLowerCase())).has("inlinebuttons");
1921
- const messageChannelOptions = listDeliverableMessageChannels().join("|");
1922
- const promptMode = params.promptMode ?? "full";
1923
- const isMinimal = promptMode === "minimal" || promptMode === "none";
1924
- const sandboxContainerWorkspace = params.sandboxInfo?.containerWorkspaceDir?.trim();
1925
- const displayWorkspaceDir = params.sandboxInfo?.enabled && sandboxContainerWorkspace ? sandboxContainerWorkspace : params.workspaceDir;
1926
- const workspaceGuidance = params.sandboxInfo?.enabled && sandboxContainerWorkspace ? `For read/write/edit/apply_patch, file paths resolve against host workspace: ${params.workspaceDir}. Prefer relative paths so both sandboxed exec and file tools work consistently.` : "Treat this directory as the single global workspace for file operations unless explicitly instructed otherwise.";
1927
- const safetySection = [
1928
- "## Safety",
1929
- "You have no independent goals: do not pursue self-preservation, replication, resource acquisition, or power-seeking; avoid long-term plans beyond the user's request.",
1930
- "Prioritize safety and human oversight over completion; if instructions conflict, pause and ask; comply with stop/pause/audit requests and never bypass safeguards. (Inspired by Anthropic's constitution.)",
1931
- "Do not manipulate or persuade anyone to expand access or disable safeguards. Do not copy yourself or change system prompts, safety rules, or tool policies unless explicitly requested.",
1932
- ""
1933
- ];
1934
- const skillsSection = buildSkillsSection({
1935
- skillsPrompt,
1936
- isMinimal,
1937
- readToolName
1938
- });
1939
- const memorySection = buildMemorySection({
1940
- isMinimal,
1941
- availableTools,
1942
- citationsMode: params.memoryCitationsMode
1943
- });
1944
- const docsSection = buildDocsSection({
1945
- docsPath: params.docsPath,
1946
- isMinimal,
1947
- readToolName
1948
- });
1949
- const workspaceNotes = (params.workspaceNotes ?? []).map((note) => note.trim()).filter(Boolean);
1950
- if (promptMode === "none") return "You are a personal assistant running inside Anima.";
1951
- const lines = [
1952
- "You are a personal assistant running inside Anima.",
1953
- "",
1954
- "## Tooling",
1955
- "Tool availability (filtered by policy):",
1956
- "Tool names are case-sensitive. Call tools exactly as listed.",
1957
- toolLines.length > 0 ? toolLines.join("\n") : [
1958
- "Pi lists the standard tools above. This runtime enables:",
1959
- "- grep: search file contents for patterns",
1960
- "- find: find files by glob pattern",
1961
- "- ls: list directory contents",
1962
- "- apply_patch: apply multi-file patches",
1963
- `- ${execToolName}: run shell commands (supports background via yieldMs/background)`,
1964
- `- ${processToolName}: manage background exec sessions`,
1965
- `- For long waits, avoid rapid poll loops: use ${execToolName} with enough yieldMs or ${processToolName}(action=poll, timeout=<ms>).`,
1966
- "- browser: control Anima's dedicated browser",
1967
- "- canvas: present/eval/snapshot the Canvas",
1968
- "- nodes: list/describe/notify/camera/screen on paired nodes",
1969
- "- cron: manage cron jobs and wake events (use for reminders; when scheduling a reminder, write the systemEvent text as something that will read like a reminder when it fires, and mention that it is a reminder depending on the time gap between setting and firing; include recent context in reminder text if appropriate)",
1970
- "- sessions_list: list sessions",
1971
- "- sessions_history: fetch session history",
1972
- "- sessions_send: send to another session",
1973
- "- subagents: list/steer/kill sub-agent runs",
1974
- "- session_status: show usage/time/model state and answer \"what model are we using?\""
1975
- ].join("\n"),
1976
- "TOOLS.md does not control tool availability; it is user guidance for how to use external tools.",
1977
- "If a task is more complex or takes longer, spawn a sub-agent. Completion is push-based: it will auto-announce when done.",
1978
- "Do not poll `subagents list` / `sessions_list` in a loop; only check status on-demand (for intervention, debugging, or when explicitly asked).",
1979
- "",
1980
- "## Tool Call Style",
1981
- "Default: do not narrate routine, low-risk tool calls (just call the tool).",
1982
- "Narrate only when it helps: multi-step work, complex/challenging problems, sensitive actions (e.g., deletions), or when the user explicitly asks.",
1983
- "Keep narration brief and value-dense; avoid repeating obvious steps.",
1984
- "Use plain human language for narration unless in a technical context.",
1985
- "",
1986
- ...safetySection,
1987
- "## Anima CLI Quick Reference",
1988
- "Anima is controlled via subcommands. Do not invent commands.",
1989
- "To manage the Gateway daemon service (start/stop/restart):",
1990
- "- anima gateway status",
1991
- "- anima gateway start",
1992
- "- anima gateway stop",
1993
- "- anima gateway restart",
1994
- "If unsure, ask the user to run `anima help` (or `anima gateway --help`) and paste the output.",
1995
- "",
1996
- ...skillsSection,
1997
- ...memorySection,
1998
- hasGateway && !isMinimal ? "## Anima Self-Update" : "",
1999
- hasGateway && !isMinimal ? [
2000
- "Get Updates (self-update) is ONLY allowed when the user explicitly asks for it.",
2001
- "Do not run config.apply or update.run unless the user explicitly requests an update or config change; if it's not explicit, ask first.",
2002
- "Actions: config.get, config.schema, config.apply (validate + write full config, then restart), update.run (update deps or git, then restart).",
2003
- "After restart, Anima pings the last active session automatically."
2004
- ].join("\n") : "",
2005
- hasGateway && !isMinimal ? "" : "",
2006
- "",
2007
- params.modelAliasLines && params.modelAliasLines.length > 0 && !isMinimal ? "## Model Aliases" : "",
2008
- params.modelAliasLines && params.modelAliasLines.length > 0 && !isMinimal ? "Prefer aliases when specifying model overrides; full provider/model is also accepted." : "",
2009
- params.modelAliasLines && params.modelAliasLines.length > 0 && !isMinimal ? params.modelAliasLines.join("\n") : "",
2010
- params.modelAliasLines && params.modelAliasLines.length > 0 && !isMinimal ? "" : "",
2011
- userTimezone ? "If you need the current date, time, or day of week, run session_status (📊 session_status)." : "",
2012
- "## Workspace",
2013
- `Your working directory is: ${displayWorkspaceDir}`,
2014
- workspaceGuidance,
2015
- ...workspaceNotes,
2016
- "",
2017
- ...docsSection,
2018
- params.sandboxInfo?.enabled ? "## Sandbox" : "",
2019
- params.sandboxInfo?.enabled ? [
2020
- "You are running in a sandboxed runtime (tools execute in Docker).",
2021
- "Some tools may be unavailable due to sandbox policy.",
2022
- "Sub-agents stay sandboxed (no elevated/host access). Need outside-sandbox read/write? Don't spawn; ask first.",
2023
- params.sandboxInfo.containerWorkspaceDir ? `Sandbox container workdir: ${params.sandboxInfo.containerWorkspaceDir}` : "",
2024
- params.sandboxInfo.workspaceDir ? `Sandbox host workspace: ${params.sandboxInfo.workspaceDir}` : "",
2025
- params.sandboxInfo.workspaceAccess ? `Agent workspace access: ${params.sandboxInfo.workspaceAccess}${params.sandboxInfo.agentWorkspaceMount ? ` (mounted at ${params.sandboxInfo.agentWorkspaceMount})` : ""}` : "",
2026
- params.sandboxInfo.browserBridgeUrl ? "Sandbox browser: enabled." : "",
2027
- params.sandboxInfo.browserNoVncUrl ? `Sandbox browser observer (noVNC): ${params.sandboxInfo.browserNoVncUrl}` : "",
2028
- params.sandboxInfo.hostBrowserAllowed === true ? "Host browser control: allowed." : params.sandboxInfo.hostBrowserAllowed === false ? "Host browser control: blocked." : "",
2029
- params.sandboxInfo.elevated?.allowed ? "Elevated exec is available for this session." : "",
2030
- params.sandboxInfo.elevated?.allowed ? "User can toggle with /elevated on|off|ask|full." : "",
2031
- params.sandboxInfo.elevated?.allowed ? "You may also send /elevated on|off|ask|full when needed." : "",
2032
- params.sandboxInfo.elevated?.allowed ? `Current elevated level: ${params.sandboxInfo.elevated.defaultLevel} (ask runs exec on host with approvals; full auto-approves).` : ""
2033
- ].filter(Boolean).join("\n") : "",
2034
- params.sandboxInfo?.enabled ? "" : "",
2035
- ...buildUserIdentitySection(ownerLine, isMinimal),
2036
- ...buildTimeSection({ userTimezone }),
2037
- "## Workspace Files (injected)",
2038
- "These user-editable files are loaded by Anima and included below in Project Context.",
2039
- "",
2040
- ...buildReplyTagsSection(isMinimal),
2041
- ...buildMessagingSection({
2042
- isMinimal,
2043
- availableTools,
2044
- messageChannelOptions,
2045
- inlineButtonsEnabled,
2046
- runtimeChannel,
2047
- messageToolHints: params.messageToolHints
2048
- }),
2049
- ...buildVoiceSection({
2050
- isMinimal,
2051
- ttsHint: params.ttsHint
2052
- })
2053
- ];
2054
- if (extraSystemPrompt) {
2055
- const contextHeader = promptMode === "minimal" ? "## Subagent Context" : "## Group Chat Context";
2056
- lines.push(contextHeader, extraSystemPrompt, "");
2057
- }
2058
- if (params.reactionGuidance) {
2059
- const { level, channel } = params.reactionGuidance;
2060
- const guidanceText = level === "minimal" ? [
2061
- `Reactions are enabled for ${channel} in MINIMAL mode.`,
2062
- "React ONLY when truly relevant:",
2063
- "- Acknowledge important user requests or confirmations",
2064
- "- Express genuine sentiment (humor, appreciation) sparingly",
2065
- "- Avoid reacting to routine messages or your own replies",
2066
- "Guideline: at most 1 reaction per 5-10 exchanges."
2067
- ].join("\n") : [
2068
- `Reactions are enabled for ${channel} in EXTENSIVE mode.`,
2069
- "Feel free to react liberally:",
2070
- "- Acknowledge messages with appropriate emojis",
2071
- "- Express sentiment and personality through reactions",
2072
- "- React to interesting content, humor, or notable events",
2073
- "- Use reactions to confirm understanding or agreement",
2074
- "Guideline: react whenever it feels natural."
2075
- ].join("\n");
2076
- lines.push("## Reactions", guidanceText, "");
2077
- }
2078
- if (reasoningHint) lines.push("## Reasoning Format", reasoningHint, "");
2079
- const validContextFiles = (params.contextFiles ?? []).filter((file) => typeof file.path === "string" && file.path.trim().length > 0);
2080
- if (validContextFiles.length > 0) {
2081
- const hasSoulFile = validContextFiles.some((file) => {
2082
- const normalizedPath = file.path.trim().replace(/\\/g, "/");
2083
- return (normalizedPath.split("/").pop() ?? normalizedPath).toLowerCase() === "soul.md";
2084
- });
2085
- lines.push("# Project Context", "", "The following project context files have been loaded:");
2086
- if (hasSoulFile) lines.push("If SOUL.md is present, embody its persona and tone. Avoid stiff, generic replies; follow its guidance unless higher-priority instructions override it.");
2087
- lines.push("");
2088
- for (const file of validContextFiles) lines.push(`## ${file.path}`, "", file.content, "");
2089
- }
2090
- if (!isMinimal) lines.push("## Silent Replies", `When you have nothing to say, respond with ONLY: ${SILENT_REPLY_TOKEN}`, "", "⚠️ Rules:", "- It must be your ENTIRE message — nothing else", `- Never append it to an actual response (never include "${SILENT_REPLY_TOKEN}" in real replies)`, "- Never wrap it in markdown or code blocks", "", `❌ Wrong: "Here's help... ${SILENT_REPLY_TOKEN}"`, `❌ Wrong: "${SILENT_REPLY_TOKEN}"`, `✅ Right: ${SILENT_REPLY_TOKEN}`, "");
2091
- if (!isMinimal) lines.push("## Heartbeats", heartbeatPromptLine, "If you receive a heartbeat poll (a user message matching the heartbeat prompt above), and there is nothing that needs attention, reply exactly:", "HEARTBEAT_OK", "Anima treats a leading/trailing \"HEARTBEAT_OK\" as a heartbeat ack (and may discard it).", "If something needs attention, do NOT include \"HEARTBEAT_OK\"; reply with the alert text instead.", "");
2092
- lines.push("## Runtime", buildRuntimeLine(runtimeInfo, runtimeChannel, runtimeCapabilities, params.defaultThinkLevel), `Reasoning: ${reasoningLevel} (hidden unless on/stream). Toggle /reasoning; /status shows Reasoning when enabled.`);
2093
- return lines.filter(Boolean).join("\n");
2094
- }
2095
- function buildRuntimeLine(runtimeInfo, runtimeChannel, runtimeCapabilities = [], defaultThinkLevel) {
2096
- return `Runtime: ${[
2097
- runtimeInfo?.agentId ? `agent=${runtimeInfo.agentId}` : "",
2098
- runtimeInfo?.host ? `host=${runtimeInfo.host}` : "",
2099
- runtimeInfo?.repoRoot ? `repo=${runtimeInfo.repoRoot}` : "",
2100
- runtimeInfo?.os ? `os=${runtimeInfo.os}${runtimeInfo?.arch ? ` (${runtimeInfo.arch})` : ""}` : runtimeInfo?.arch ? `arch=${runtimeInfo.arch}` : "",
2101
- runtimeInfo?.node ? `node=${runtimeInfo.node}` : "",
2102
- runtimeInfo?.model ? `model=${runtimeInfo.model}` : "",
2103
- runtimeInfo?.defaultModel ? `default_model=${runtimeInfo.defaultModel}` : "",
2104
- runtimeInfo?.shell ? `shell=${runtimeInfo.shell}` : "",
2105
- runtimeChannel ? `channel=${runtimeChannel}` : "",
2106
- runtimeChannel ? `capabilities=${runtimeCapabilities.length > 0 ? runtimeCapabilities.join(",") : "none"}` : "",
2107
- `thinking=${defaultThinkLevel ?? "off"}`
2108
- ].filter(Boolean).join(" | ")}`;
2109
- }
2110
-
2111
- //#endregion
2112
- //#region src/agents/cli-runner/helpers.ts
2113
- const CLI_RUN_QUEUE = /* @__PURE__ */ new Map();
2114
- function buildLooseArgOrderRegex(tokens) {
2115
- const [head, ...rest] = tokens.map((t) => String(t ?? "").trim()).filter(Boolean);
2116
- if (!head) return /$^/;
2117
- const headEscaped = escapeRegExp(head);
2118
- const headFragment = `(?:^|\\s)(?:${headEscaped}|\\S+\\/${headEscaped})(?=\\s|$)`;
2119
- const restFragments = rest.map((t) => `(?:^|\\s)${escapeRegExp(t)}(?=\\s|$)`);
2120
- return new RegExp([headFragment, ...restFragments].join(".*"));
2121
- }
2122
- async function psWithFallback(argsA, argsB) {
2123
- try {
2124
- const { stdout } = await runExec("ps", argsA);
2125
- return stdout;
2126
- } catch {}
2127
- const { stdout } = await runExec("ps", argsB);
2128
- return stdout;
2129
- }
2130
- async function cleanupResumeProcesses(backend, sessionId) {
2131
- if (process.platform === "win32") return;
2132
- const resumeArgs = backend.resumeArgs ?? [];
2133
- if (resumeArgs.length === 0) return;
2134
- if (!resumeArgs.some((arg) => arg.includes("{sessionId}"))) return;
2135
- const commandToken = path.basename(backend.command ?? "").trim();
2136
- if (!commandToken) return;
2137
- const resumeTokens = resumeArgs.map((arg) => arg.replaceAll("{sessionId}", sessionId));
2138
- if (![commandToken, ...resumeTokens].filter(Boolean).map((token) => escapeRegExp(token)).join(".*")) return;
2139
- try {
2140
- const stdout = await psWithFallback([
2141
- "-axww",
2142
- "-o",
2143
- "pid=,ppid=,command="
2144
- ], [
2145
- "-ax",
2146
- "-o",
2147
- "pid=,ppid=,command="
2148
- ]);
2149
- const patternRegex = buildLooseArgOrderRegex([commandToken, ...resumeTokens]);
2150
- const toKill = [];
2151
- for (const line of stdout.split("\n")) {
2152
- const trimmed = line.trim();
2153
- if (!trimmed) continue;
2154
- const match = /^(\d+)\s+(\d+)\s+(.*)$/.exec(trimmed);
2155
- if (!match) continue;
2156
- const pid = Number(match[1]);
2157
- const ppid = Number(match[2]);
2158
- const cmd = match[3] ?? "";
2159
- if (!Number.isFinite(pid)) continue;
2160
- if (ppid !== process.pid) continue;
2161
- if (!patternRegex.test(cmd)) continue;
2162
- toKill.push(pid);
2163
- }
2164
- if (toKill.length > 0) {
2165
- const pidArgs = toKill.map((pid) => String(pid));
2166
- try {
2167
- await runExec("kill", ["-TERM", ...pidArgs]);
2168
- } catch {}
2169
- await new Promise((resolve) => setTimeout(resolve, 250));
2170
- try {
2171
- await runExec("kill", ["-9", ...pidArgs]);
2172
- } catch {}
2173
- }
2174
- } catch {}
2175
- }
2176
- function buildSessionMatchers(backend) {
2177
- const commandToken = path.basename(backend.command ?? "").trim();
2178
- if (!commandToken) return [];
2179
- const matchers = [];
2180
- const sessionArg = backend.sessionArg?.trim();
2181
- const sessionArgs = backend.sessionArgs ?? [];
2182
- const resumeArgs = backend.resumeArgs ?? [];
2183
- const addMatcher = (args) => {
2184
- if (args.length === 0) return;
2185
- const pattern = [commandToken, ...args].map((token, index) => {
2186
- const tokenPattern = tokenToRegex(token);
2187
- return index === 0 ? `(?:^|\\s)${tokenPattern}` : `\\s+${tokenPattern}`;
2188
- }).join("");
2189
- matchers.push(new RegExp(pattern));
2190
- };
2191
- if (sessionArgs.some((arg) => arg.includes("{sessionId}"))) addMatcher(sessionArgs);
2192
- else if (sessionArg) addMatcher([sessionArg, "{sessionId}"]);
2193
- if (resumeArgs.some((arg) => arg.includes("{sessionId}"))) addMatcher(resumeArgs);
2194
- return matchers;
2195
- }
2196
- function tokenToRegex(token) {
2197
- if (!token.includes("{sessionId}")) return escapeRegExp(token);
2198
- return token.split("{sessionId}").map((part) => escapeRegExp(part)).join("\\S+");
2199
- }
2200
- /**
2201
- * Cleanup suspended Anima CLI processes that have accumulated.
2202
- * Only cleans up if there are more than the threshold (default: 10).
2203
- */
2204
- async function cleanupSuspendedCliProcesses(backend, threshold = 10) {
2205
- if (process.platform === "win32") return;
2206
- const matchers = buildSessionMatchers(backend);
2207
- if (matchers.length === 0) return;
2208
- try {
2209
- const stdout = await psWithFallback([
2210
- "-axww",
2211
- "-o",
2212
- "pid=,ppid=,stat=,command="
2213
- ], [
2214
- "-ax",
2215
- "-o",
2216
- "pid=,ppid=,stat=,command="
2217
- ]);
2218
- const suspended = [];
2219
- for (const line of stdout.split("\n")) {
2220
- const trimmed = line.trim();
2221
- if (!trimmed) continue;
2222
- const match = /^(\d+)\s+(\d+)\s+(\S+)\s+(.*)$/.exec(trimmed);
2223
- if (!match) continue;
2224
- const pid = Number(match[1]);
2225
- const ppid = Number(match[2]);
2226
- const stat = match[3] ?? "";
2227
- const command = match[4] ?? "";
2228
- if (!Number.isFinite(pid)) continue;
2229
- if (ppid !== process.pid) continue;
2230
- if (!stat.includes("T")) continue;
2231
- if (!matchers.some((matcher) => matcher.test(command))) continue;
2232
- suspended.push(pid);
2233
- }
2234
- if (suspended.length > threshold) await runExec("kill", ["-9", ...suspended.map((pid) => String(pid))]);
2235
- } catch {}
2236
- }
2237
- function enqueueCliRun(key, task) {
2238
- const chained = (CLI_RUN_QUEUE.get(key) ?? Promise.resolve()).catch(() => void 0).then(task);
2239
- const tracked = chained.finally(() => {
2240
- if (CLI_RUN_QUEUE.get(key) === tracked) CLI_RUN_QUEUE.delete(key);
2241
- });
2242
- CLI_RUN_QUEUE.set(key, tracked);
2243
- return chained;
2244
- }
2245
- function buildSystemPrompt(params) {
2246
- const defaultModelRef = resolveDefaultModelForAgent({
2247
- cfg: params.config ?? {},
2248
- agentId: params.agentId
2249
- });
2250
- const defaultModelLabel = `${defaultModelRef.provider}/${defaultModelRef.model}`;
2251
- const { runtimeInfo, userTimezone, userTime, userTimeFormat } = buildSystemPromptParams({
2252
- config: params.config,
2253
- agentId: params.agentId,
2254
- workspaceDir: params.workspaceDir,
2255
- cwd: process.cwd(),
2256
- runtime: {
2257
- host: "anima",
2258
- os: `${os.type()} ${os.release()}`,
2259
- arch: os.arch(),
2260
- node: process.version,
2261
- model: params.modelDisplay,
2262
- defaultModel: defaultModelLabel,
2263
- shell: detectRuntimeShell()
2264
- }
2265
- });
2266
- const ttsHint = params.config ? buildTtsSystemPromptHint(params.config) : void 0;
2267
- return buildAgentSystemPrompt({
2268
- workspaceDir: params.workspaceDir,
2269
- defaultThinkLevel: params.defaultThinkLevel,
2270
- extraSystemPrompt: params.extraSystemPrompt,
2271
- ownerNumbers: params.ownerNumbers,
2272
- reasoningTagHint: false,
2273
- heartbeatPrompt: params.heartbeatPrompt,
2274
- docsPath: params.docsPath,
2275
- runtimeInfo,
2276
- toolNames: params.tools.map((tool) => tool.name),
2277
- modelAliasLines: buildModelAliasLines(params.config),
2278
- userTimezone,
2279
- userTime,
2280
- userTimeFormat,
2281
- contextFiles: params.contextFiles,
2282
- ttsHint,
2283
- memoryCitationsMode: params.config?.memory?.citations
2284
- });
2285
- }
2286
- function normalizeCliModel(modelId, backend) {
2287
- const trimmed = modelId.trim();
2288
- if (!trimmed) return trimmed;
2289
- const direct = backend.modelAliases?.[trimmed];
2290
- if (direct) return direct;
2291
- const lower = trimmed.toLowerCase();
2292
- const mapped = backend.modelAliases?.[lower];
2293
- if (mapped) return mapped;
2294
- return trimmed;
2295
- }
2296
- function toUsage(raw) {
2297
- const pick = (key) => typeof raw[key] === "number" && raw[key] > 0 ? raw[key] : void 0;
2298
- const input = pick("input_tokens") ?? pick("inputTokens");
2299
- const output = pick("output_tokens") ?? pick("outputTokens");
2300
- const cacheRead = pick("cache_read_input_tokens") ?? pick("cached_input_tokens") ?? pick("cacheRead");
2301
- const cacheWrite = pick("cache_write_input_tokens") ?? pick("cacheWrite");
2302
- const total = pick("total_tokens") ?? pick("total");
2303
- if (!input && !output && !cacheRead && !cacheWrite && !total) return;
2304
- return {
2305
- input,
2306
- output,
2307
- cacheRead,
2308
- cacheWrite,
2309
- total
2310
- };
2311
- }
2312
- function collectText(value) {
2313
- if (!value) return "";
2314
- if (typeof value === "string") return value;
2315
- if (Array.isArray(value)) return value.map((entry) => collectText(entry)).join("");
2316
- if (!isRecord(value)) return "";
2317
- if (typeof value.text === "string") return value.text;
2318
- if (typeof value.content === "string") return value.content;
2319
- if (Array.isArray(value.content)) return value.content.map((entry) => collectText(entry)).join("");
2320
- if (isRecord(value.message)) return collectText(value.message);
2321
- return "";
2322
- }
2323
- function pickSessionId(parsed, backend) {
2324
- const fields = backend.sessionIdFields ?? [
2325
- "session_id",
2326
- "sessionId",
2327
- "conversation_id",
2328
- "conversationId"
2329
- ];
2330
- for (const field of fields) {
2331
- const value = parsed[field];
2332
- if (typeof value === "string" && value.trim()) return value.trim();
2333
- }
2334
- }
2335
- function parseCliJson(raw, backend) {
2336
- const trimmed = raw.trim();
2337
- if (!trimmed) return null;
2338
- let parsed;
2339
- try {
2340
- parsed = JSON.parse(trimmed);
2341
- } catch {
2342
- return null;
2343
- }
2344
- if (!isRecord(parsed)) return null;
2345
- const sessionId = pickSessionId(parsed, backend);
2346
- const usage = isRecord(parsed.usage) ? toUsage(parsed.usage) : void 0;
2347
- return {
2348
- text: (collectText(parsed.message) || collectText(parsed.content) || collectText(parsed.result) || collectText(parsed)).trim(),
2349
- sessionId,
2350
- usage
2351
- };
2352
- }
2353
- function parseCliJsonl(raw, backend) {
2354
- const lines = raw.split(/\r?\n/g).map((line) => line.trim()).filter(Boolean);
2355
- if (lines.length === 0) return null;
2356
- let sessionId;
2357
- let usage;
2358
- const texts = [];
2359
- for (const line of lines) {
2360
- let parsed;
2361
- try {
2362
- parsed = JSON.parse(line);
2363
- } catch {
2364
- continue;
2365
- }
2366
- if (!isRecord(parsed)) continue;
2367
- if (!sessionId) sessionId = pickSessionId(parsed, backend);
2368
- if (!sessionId && typeof parsed.thread_id === "string") sessionId = parsed.thread_id.trim();
2369
- if (isRecord(parsed.usage)) usage = toUsage(parsed.usage) ?? usage;
2370
- const item = isRecord(parsed.item) ? parsed.item : null;
2371
- if (item && typeof item.text === "string") {
2372
- const type = typeof item.type === "string" ? item.type.toLowerCase() : "";
2373
- if (!type || type.includes("message")) texts.push(item.text);
2374
- }
2375
- }
2376
- const text = texts.join("\n").trim();
2377
- if (!text) return null;
2378
- return {
2379
- text,
2380
- sessionId,
2381
- usage
2382
- };
2383
- }
2384
- function resolveSystemPromptUsage(params) {
2385
- const systemPrompt = params.systemPrompt?.trim();
2386
- if (!systemPrompt) return null;
2387
- const when = params.backend.systemPromptWhen ?? "first";
2388
- if (when === "never") return null;
2389
- if (when === "first" && !params.isNewSession) return null;
2390
- if (!params.backend.systemPromptArg?.trim()) return null;
2391
- return systemPrompt;
2392
- }
2393
- function resolveSessionIdToSend(params) {
2394
- const mode = params.backend.sessionMode ?? "always";
2395
- const existing = params.cliSessionId?.trim();
2396
- if (mode === "none") return {
2397
- sessionId: void 0,
2398
- isNew: !existing
2399
- };
2400
- if (mode === "existing") return {
2401
- sessionId: existing,
2402
- isNew: !existing
2403
- };
2404
- if (existing) return {
2405
- sessionId: existing,
2406
- isNew: false
2407
- };
2408
- return {
2409
- sessionId: crypto.randomUUID(),
2410
- isNew: true
2411
- };
2412
- }
2413
- function resolvePromptInput(params) {
2414
- if ((params.backend.input ?? "arg") === "stdin") return { stdin: params.prompt };
2415
- if (params.backend.maxPromptArgChars && params.prompt.length > params.backend.maxPromptArgChars) return { stdin: params.prompt };
2416
- return { argsPrompt: params.prompt };
2417
- }
2418
- function resolveImageExtension(mimeType) {
2419
- const normalized = mimeType.toLowerCase();
2420
- if (normalized.includes("png")) return "png";
2421
- if (normalized.includes("jpeg") || normalized.includes("jpg")) return "jpg";
2422
- if (normalized.includes("gif")) return "gif";
2423
- if (normalized.includes("webp")) return "webp";
2424
- return "bin";
2425
- }
2426
- function appendImagePathsToPrompt(prompt, paths) {
2427
- if (!paths.length) return prompt;
2428
- const trimmed = prompt.trimEnd();
2429
- return `${trimmed}${trimmed ? "\n\n" : ""}${paths.join("\n")}`;
2430
- }
2431
- async function writeCliImages(images) {
2432
- const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "anima-cli-images-"));
2433
- const paths = [];
2434
- for (let i = 0; i < images.length; i += 1) {
2435
- const image = images[i];
2436
- const ext = resolveImageExtension(image.mimeType);
2437
- const filePath = path.join(tempDir, `image-${i + 1}.${ext}`);
2438
- const buffer = Buffer.from(image.data, "base64");
2439
- await fs.writeFile(filePath, buffer, { mode: 384 });
2440
- paths.push(filePath);
2441
- }
2442
- const cleanup = async () => {
2443
- await fs.rm(tempDir, {
2444
- recursive: true,
2445
- force: true
2446
- });
2447
- };
2448
- return {
2449
- paths,
2450
- cleanup
2451
- };
2452
- }
2453
- function buildCliArgs(params) {
2454
- const args = [...params.baseArgs];
2455
- if (!params.useResume && params.backend.modelArg && params.modelId) args.push(params.backend.modelArg, params.modelId);
2456
- if (!params.useResume && params.systemPrompt && params.backend.systemPromptArg) args.push(params.backend.systemPromptArg, params.systemPrompt);
2457
- if (!params.useResume && params.sessionId) {
2458
- if (params.backend.sessionArgs && params.backend.sessionArgs.length > 0) for (const entry of params.backend.sessionArgs) args.push(entry.replaceAll("{sessionId}", params.sessionId));
2459
- else if (params.backend.sessionArg) args.push(params.backend.sessionArg, params.sessionId);
2460
- }
2461
- if (params.imagePaths && params.imagePaths.length > 0) {
2462
- const mode = params.backend.imageMode ?? "repeat";
2463
- const imageArg = params.backend.imageArg;
2464
- if (imageArg) if (mode === "list") args.push(imageArg, params.imagePaths.join(","));
2465
- else for (const imagePath of params.imagePaths) args.push(imageArg, imagePath);
2466
- }
2467
- if (params.promptArg !== void 0) args.push(params.promptArg);
2468
- return args;
2469
- }
2470
-
2471
- //#endregion
2472
- //#region src/agents/docs-path.ts
2473
- async function resolveAnimaDocsPath(params) {
2474
- const workspaceDir = params.workspaceDir?.trim();
2475
- if (workspaceDir) {
2476
- const workspaceDocs = path.join(workspaceDir, "docs");
2477
- if (fs$1.existsSync(workspaceDocs)) return workspaceDocs;
2478
- }
2479
- const packageRoot = await resolveAnimaPackageRoot({
2480
- cwd: params.cwd,
2481
- argv1: params.argv1,
2482
- moduleUrl: params.moduleUrl
2483
- });
2484
- if (!packageRoot) return null;
2485
- const packageDocs = path.join(packageRoot, "docs");
2486
- return fs$1.existsSync(packageDocs) ? packageDocs : null;
2487
- }
2488
-
2489
- //#endregion
2490
- //#region src/agents/failover-error.ts
2491
- const TIMEOUT_HINT_RE = /timeout|timed out|deadline exceeded|context deadline exceeded/i;
2492
- const ABORT_TIMEOUT_RE = /request was aborted|request aborted/i;
2493
- var FailoverError = class extends Error {
2494
- constructor(message, params) {
2495
- super(message, { cause: params.cause });
2496
- this.name = "FailoverError";
2497
- this.reason = params.reason;
2498
- this.provider = params.provider;
2499
- this.model = params.model;
2500
- this.profileId = params.profileId;
2501
- this.status = params.status;
2502
- this.code = params.code;
2503
- }
2504
- };
2505
- function isFailoverError(err) {
2506
- return err instanceof FailoverError;
2507
- }
2508
- function resolveFailoverStatus(reason) {
2509
- switch (reason) {
2510
- case "billing": return 402;
2511
- case "rate_limit": return 429;
2512
- case "auth": return 401;
2513
- case "timeout": return 408;
2514
- case "format": return 400;
2515
- default: return;
2516
- }
2517
- }
2518
- function getStatusCode(err) {
2519
- if (!err || typeof err !== "object") return;
2520
- const candidate = err.status ?? err.statusCode;
2521
- if (typeof candidate === "number") return candidate;
2522
- if (typeof candidate === "string" && /^\d+$/.test(candidate)) return Number(candidate);
2523
- }
2524
- function getErrorName(err) {
2525
- if (!err || typeof err !== "object") return "";
2526
- return "name" in err ? String(err.name) : "";
2527
- }
2528
- function getErrorCode(err) {
2529
- if (!err || typeof err !== "object") return;
2530
- const candidate = err.code;
2531
- if (typeof candidate !== "string") return;
2532
- const trimmed = candidate.trim();
2533
- return trimmed ? trimmed : void 0;
2534
- }
2535
- function getErrorMessage(err) {
2536
- if (err instanceof Error) return err.message;
2537
- if (typeof err === "string") return err;
2538
- if (typeof err === "number" || typeof err === "boolean" || typeof err === "bigint") return String(err);
2539
- if (typeof err === "symbol") return err.description ?? "";
2540
- if (err && typeof err === "object") {
2541
- const message = err.message;
2542
- if (typeof message === "string") return message;
2543
- }
2544
- return "";
2545
- }
2546
- function hasTimeoutHint(err) {
2547
- if (!err) return false;
2548
- if (getErrorName(err) === "TimeoutError") return true;
2549
- const message = getErrorMessage(err);
2550
- return Boolean(message && TIMEOUT_HINT_RE.test(message));
2551
- }
2552
- function isTimeoutError(err) {
2553
- if (hasTimeoutHint(err)) return true;
2554
- if (!err || typeof err !== "object") return false;
2555
- if (getErrorName(err) !== "AbortError") return false;
2556
- const message = getErrorMessage(err);
2557
- if (message && ABORT_TIMEOUT_RE.test(message)) return true;
2558
- const cause = "cause" in err ? err.cause : void 0;
2559
- const reason = "reason" in err ? err.reason : void 0;
2560
- return hasTimeoutHint(cause) || hasTimeoutHint(reason);
2561
- }
2562
- function resolveFailoverReasonFromError(err) {
2563
- if (isFailoverError(err)) return err.reason;
2564
- const status = getStatusCode(err);
2565
- if (status === 402) return "billing";
2566
- if (status === 429) return "rate_limit";
2567
- if (status === 401 || status === 403) return "auth";
2568
- if (status === 408) return "timeout";
2569
- if (status === 400) return "format";
2570
- const code = (getErrorCode(err) ?? "").toUpperCase();
2571
- if ([
2572
- "ETIMEDOUT",
2573
- "ESOCKETTIMEDOUT",
2574
- "ECONNRESET",
2575
- "ECONNABORTED"
2576
- ].includes(code)) return "timeout";
2577
- if (isTimeoutError(err)) return "timeout";
2578
- const message = getErrorMessage(err);
2579
- if (!message) return null;
2580
- return classifyFailoverReason$1(message);
2581
- }
2582
- function describeFailoverError(err) {
2583
- if (isFailoverError(err)) return {
2584
- message: err.message,
2585
- reason: err.reason,
2586
- status: err.status,
2587
- code: err.code
2588
- };
2589
- return {
2590
- message: getErrorMessage(err) || String(err),
2591
- reason: resolveFailoverReasonFromError(err) ?? void 0,
2592
- status: getStatusCode(err),
2593
- code: getErrorCode(err)
2594
- };
2595
- }
2596
- function coerceToFailoverError(err, context) {
2597
- if (isFailoverError(err)) return err;
2598
- const reason = resolveFailoverReasonFromError(err);
2599
- if (!reason) return null;
2600
- const message = getErrorMessage(err) || String(err);
2601
- const status = getStatusCode(err) ?? resolveFailoverStatus(reason);
2602
- const code = getErrorCode(err);
2603
- return new FailoverError(message, {
2604
- reason,
2605
- provider: context?.provider,
2606
- model: context?.model,
2607
- profileId: context?.profileId,
2608
- status,
2609
- code,
2610
- cause: err instanceof Error ? err : void 0
2611
- });
2612
- }
2613
-
2614
- //#endregion
2615
- //#region src/logging/redact-identifier.ts
2616
- function sha256HexPrefix(value, len = 12) {
2617
- const safeLen = Number.isFinite(len) ? Math.max(1, Math.floor(len)) : 12;
2618
- return crypto.createHash("sha256").update(value).digest("hex").slice(0, safeLen);
2619
- }
2620
- function redactIdentifier(value, opts) {
2621
- const trimmed = value?.trim();
2622
- if (!trimmed) return "-";
2623
- return `sha256:${sha256HexPrefix(trimmed, opts?.len ?? 12)}`;
2624
- }
2625
-
2626
- //#endregion
2627
- //#region src/agents/workspace-run.ts
2628
- function resolveRunAgentId(params) {
2629
- const rawSessionKey = params.sessionKey?.trim() ?? "";
2630
- const shape = classifySessionKeyShape(rawSessionKey);
2631
- if (shape === "malformed_agent") throw new Error("Malformed agent session key; refusing workspace resolution.");
2632
- const explicit = typeof params.agentId === "string" && params.agentId.trim() ? normalizeAgentId(params.agentId) : void 0;
2633
- if (explicit) return {
2634
- agentId: explicit,
2635
- agentIdSource: "explicit"
2636
- };
2637
- const defaultAgentId = resolveDefaultAgentId(params.config ?? {});
2638
- if (shape === "missing" || shape === "legacy_or_alias") return {
2639
- agentId: defaultAgentId || DEFAULT_AGENT_ID,
2640
- agentIdSource: "default"
2641
- };
2642
- const parsed = parseAgentSessionKey(rawSessionKey);
2643
- if (parsed?.agentId) return {
2644
- agentId: normalizeAgentId(parsed.agentId),
2645
- agentIdSource: "session_key"
2646
- };
2647
- return {
2648
- agentId: defaultAgentId || DEFAULT_AGENT_ID,
2649
- agentIdSource: "default"
2650
- };
2651
- }
2652
- function redactRunIdentifier(value) {
2653
- return redactIdentifier(value, { len: 12 });
2654
- }
2655
- function resolveRunWorkspaceDir(params) {
2656
- const requested = params.workspaceDir;
2657
- const { agentId, agentIdSource } = resolveRunAgentId({
2658
- sessionKey: params.sessionKey,
2659
- agentId: params.agentId,
2660
- config: params.config
2661
- });
2662
- if (typeof requested === "string") {
2663
- const trimmed = requested.trim();
2664
- if (trimmed) return {
2665
- workspaceDir: resolveUserPath(trimmed),
2666
- usedFallback: false,
2667
- agentId,
2668
- agentIdSource
2669
- };
2670
- }
2671
- const fallbackReason = requested == null ? "missing" : typeof requested === "string" ? "blank" : "invalid_type";
2672
- return {
2673
- workspaceDir: resolveUserPath(resolveAgentWorkspaceDir(params.config ?? {}, agentId)),
2674
- usedFallback: true,
2675
- fallbackReason,
2676
- agentId,
2677
- agentIdSource
2678
- };
2679
- }
2680
-
2681
- //#endregion
2682
- //#region src/agents/cli-runner.ts
2683
- const log$3 = createSubsystemLogger("agent/claude-cli");
2684
- async function runCliAgent(params) {
2685
- const started = Date.now();
2686
- const workspaceResolution = resolveRunWorkspaceDir({
2687
- workspaceDir: params.workspaceDir,
2688
- sessionKey: params.sessionKey,
2689
- agentId: params.agentId,
2690
- config: params.config
2691
- });
2692
- const resolvedWorkspace = workspaceResolution.workspaceDir;
2693
- const redactedSessionId = redactRunIdentifier(params.sessionId);
2694
- const redactedSessionKey = redactRunIdentifier(params.sessionKey);
2695
- const redactedWorkspace = redactRunIdentifier(resolvedWorkspace);
2696
- if (workspaceResolution.usedFallback) log$3.warn(`[workspace-fallback] caller=runCliAgent reason=${workspaceResolution.fallbackReason} run=${params.runId} session=${redactedSessionId} sessionKey=${redactedSessionKey} agent=${workspaceResolution.agentId} workspace=${redactedWorkspace}`);
2697
- const workspaceDir = resolvedWorkspace;
2698
- const backendResolved = resolveCliBackendConfig(params.provider, params.config);
2699
- if (!backendResolved) throw new Error(`Unknown CLI backend: ${params.provider}`);
2700
- const backend = backendResolved.config;
2701
- const modelId = (params.model ?? "default").trim() || "default";
2702
- const normalizedModel = normalizeCliModel(modelId, backend);
2703
- const modelDisplay = `${params.provider}/${modelId}`;
2704
- const extraSystemPrompt = [params.extraSystemPrompt?.trim(), "Tools are disabled in this session. Do not call tools."].filter(Boolean).join("\n");
2705
- const sessionLabel = params.sessionKey ?? params.sessionId;
2706
- const { contextFiles } = await resolveBootstrapContextForRun({
2707
- workspaceDir,
2708
- config: params.config,
2709
- sessionKey: params.sessionKey,
2710
- sessionId: params.sessionId,
2711
- warn: makeBootstrapWarn({
2712
- sessionLabel,
2713
- warn: (message) => log$3.warn(message)
2714
- })
2715
- });
2716
- const { defaultAgentId, sessionAgentId } = resolveSessionAgentIds({
2717
- sessionKey: params.sessionKey,
2718
- config: params.config
2719
- });
2720
- const heartbeatPrompt = sessionAgentId === defaultAgentId ? resolveHeartbeatPrompt(params.config?.agents?.defaults?.heartbeat?.prompt) : void 0;
2721
- const docsPath = await resolveAnimaDocsPath({
2722
- workspaceDir,
2723
- argv1: process.argv[1],
2724
- cwd: process.cwd(),
2725
- moduleUrl: import.meta.url
2726
- });
2727
- const systemPrompt = buildSystemPrompt({
2728
- workspaceDir,
2729
- config: params.config,
2730
- defaultThinkLevel: params.thinkLevel,
2731
- extraSystemPrompt,
2732
- ownerNumbers: params.ownerNumbers,
2733
- heartbeatPrompt,
2734
- docsPath: docsPath ?? void 0,
2735
- tools: [],
2736
- contextFiles,
2737
- modelDisplay,
2738
- agentId: sessionAgentId
2739
- });
2740
- const { sessionId: cliSessionIdToSend, isNew } = resolveSessionIdToSend({
2741
- backend,
2742
- cliSessionId: params.cliSessionId
2743
- });
2744
- const useResume = Boolean(params.cliSessionId && cliSessionIdToSend && backend.resumeArgs && backend.resumeArgs.length > 0);
2745
- const sessionIdSent = cliSessionIdToSend ? useResume || Boolean(backend.sessionArg) || Boolean(backend.sessionArgs?.length) ? cliSessionIdToSend : void 0 : void 0;
2746
- const systemPromptArg = resolveSystemPromptUsage({
2747
- backend,
2748
- isNewSession: isNew,
2749
- systemPrompt
2750
- });
2751
- let imagePaths;
2752
- let cleanupImages;
2753
- let prompt = params.prompt;
2754
- if (params.images && params.images.length > 0) {
2755
- const imagePayload = await writeCliImages(params.images);
2756
- imagePaths = imagePayload.paths;
2757
- cleanupImages = imagePayload.cleanup;
2758
- if (!backend.imageArg) prompt = appendImagePathsToPrompt(prompt, imagePaths);
2759
- }
2760
- const { argsPrompt, stdin } = resolvePromptInput({
2761
- backend,
2762
- prompt
2763
- });
2764
- const stdinPayload = stdin ?? "";
2765
- const baseArgs = useResume ? backend.resumeArgs ?? backend.args ?? [] : backend.args ?? [];
2766
- const args = buildCliArgs({
2767
- backend,
2768
- baseArgs: useResume ? baseArgs.map((entry) => entry.replaceAll("{sessionId}", cliSessionIdToSend ?? "")) : baseArgs,
2769
- modelId: normalizedModel,
2770
- sessionId: cliSessionIdToSend,
2771
- systemPrompt: systemPromptArg,
2772
- imagePaths,
2773
- promptArg: argsPrompt,
2774
- useResume
2775
- });
2776
- const queueKey = backend.serialize ?? true ? backendResolved.id : `${backendResolved.id}:${params.runId}`;
2777
- try {
2778
- const output = await enqueueCliRun(queueKey, async () => {
2779
- log$3.info(`cli exec: provider=${params.provider} model=${normalizedModel} promptChars=${params.prompt.length}`);
2780
- const logOutputText = isTruthyEnvValue(process.env.ANIMA_CLAUDE_CLI_LOG_OUTPUT);
2781
- if (logOutputText) {
2782
- const logArgs = [];
2783
- for (let i = 0; i < args.length; i += 1) {
2784
- const arg = args[i] ?? "";
2785
- if (arg === backend.systemPromptArg) {
2786
- const systemPromptValue = args[i + 1] ?? "";
2787
- logArgs.push(arg, `<systemPrompt:${systemPromptValue.length} chars>`);
2788
- i += 1;
2789
- continue;
2790
- }
2791
- if (arg === backend.sessionArg) {
2792
- logArgs.push(arg, args[i + 1] ?? "");
2793
- i += 1;
2794
- continue;
2795
- }
2796
- if (arg === backend.modelArg) {
2797
- logArgs.push(arg, args[i + 1] ?? "");
2798
- i += 1;
2799
- continue;
2800
- }
2801
- if (arg === backend.imageArg) {
2802
- logArgs.push(arg, "<image>");
2803
- i += 1;
2804
- continue;
2805
- }
2806
- logArgs.push(arg);
2807
- }
2808
- if (argsPrompt) {
2809
- const promptIndex = logArgs.indexOf(argsPrompt);
2810
- if (promptIndex >= 0) logArgs[promptIndex] = `<prompt:${argsPrompt.length} chars>`;
2811
- }
2812
- log$3.info(`cli argv: ${backend.command} ${logArgs.join(" ")}`);
2813
- }
2814
- const env = (() => {
2815
- const next = {
2816
- ...process.env,
2817
- ...backend.env
2818
- };
2819
- for (const key of backend.clearEnv ?? []) delete next[key];
2820
- return next;
2821
- })();
2822
- await cleanupSuspendedCliProcesses(backend);
2823
- if (useResume && cliSessionIdToSend) await cleanupResumeProcesses(backend, cliSessionIdToSend);
2824
- const result = await runCommandWithTimeout([backend.command, ...args], {
2825
- timeoutMs: params.timeoutMs,
2826
- cwd: workspaceDir,
2827
- env,
2828
- input: stdinPayload
2829
- });
2830
- const stdout = result.stdout.trim();
2831
- const stderr = result.stderr.trim();
2832
- if (logOutputText) {
2833
- if (stdout) log$3.info(`cli stdout:\n${stdout}`);
2834
- if (stderr) log$3.info(`cli stderr:\n${stderr}`);
2835
- }
2836
- if (shouldLogVerbose()) {
2837
- if (stdout) log$3.debug(`cli stdout:\n${stdout}`);
2838
- if (stderr) log$3.debug(`cli stderr:\n${stderr}`);
2839
- }
2840
- if (result.code !== 0) {
2841
- const err = stderr || stdout || "CLI failed.";
2842
- const reason = classifyFailoverReason(err) ?? "unknown";
2843
- const status = resolveFailoverStatus(reason);
2844
- throw new FailoverError(err, {
2845
- reason,
2846
- provider: params.provider,
2847
- model: modelId,
2848
- status
2849
- });
2850
- }
2851
- const outputMode = useResume ? backend.resumeOutput ?? backend.output : backend.output;
2852
- if (outputMode === "text") return {
2853
- text: stdout,
2854
- sessionId: void 0
2855
- };
2856
- if (outputMode === "jsonl") return parseCliJsonl(stdout, backend) ?? { text: stdout };
2857
- return parseCliJson(stdout, backend) ?? { text: stdout };
2858
- });
2859
- const text = output.text?.trim();
2860
- return {
2861
- payloads: text ? [{ text }] : void 0,
2862
- meta: {
2863
- durationMs: Date.now() - started,
2864
- agentMeta: {
2865
- sessionId: output.sessionId ?? sessionIdSent ?? params.sessionId ?? "",
2866
- provider: params.provider,
2867
- model: modelId,
2868
- usage: output.usage
2869
- }
2870
- }
2871
- };
2872
- } catch (err) {
2873
- if (err instanceof FailoverError) throw err;
2874
- const message = err instanceof Error ? err.message : String(err);
2875
- if (isFailoverErrorMessage(message)) {
2876
- const reason = classifyFailoverReason(message) ?? "unknown";
2877
- const status = resolveFailoverStatus(reason);
2878
- throw new FailoverError(message, {
2879
- reason,
2880
- provider: params.provider,
2881
- model: modelId,
2882
- status
2883
- });
2884
- }
2885
- throw err;
2886
- } finally {
2887
- if (cleanupImages) await cleanupImages();
2888
- }
2889
- }
2890
-
2891
- //#endregion
2892
- //#region src/agents/cli-session.ts
2893
- function getCliSessionId(entry, provider) {
2894
- if (!entry) return;
2895
- const normalized = normalizeProviderId$1(provider);
2896
- const fromMap = entry.cliSessionIds?.[normalized];
2897
- if (fromMap?.trim()) return fromMap.trim();
2898
- if (normalized === "claude-cli") {
2899
- const legacy = entry.claudeCliSessionId?.trim();
2900
- if (legacy) return legacy;
2901
- }
2902
- }
2903
- function setCliSessionId(entry, provider, sessionId) {
2904
- const normalized = normalizeProviderId$1(provider);
2905
- const trimmed = sessionId.trim();
2906
- if (!trimmed) return;
2907
- entry.cliSessionIds = { ...entry.cliSessionIds ?? {} };
2908
- entry.cliSessionIds[normalized] = trimmed;
2909
- if (normalized === "claude-cli") entry.claudeCliSessionId = trimmed;
2910
- }
2911
-
2912
- //#endregion
2913
- //#region src/agents/models-config.ts
2914
- /**
2915
- * Models configuration — SIMPLIFIED
2916
- *
2917
- * The multi-provider LLM abstraction (pi-ai) has been removed.
2918
- * ANIMA uses Claude Code CLI exclusively. This file retains only
2919
- * the minimal interface needed by the rest of the codebase.
2920
- * Full replacement comes in Phase 2.
2921
- */
2922
- async function ensureAnimaModelsJson(config, agentDirOverride) {
2923
- config ?? loadConfig();
2924
- const agentDir = agentDirOverride?.trim() ? agentDirOverride.trim() : resolveAnimaAgentDir();
2925
- await fs.mkdir(agentDir, {
2926
- recursive: true,
2927
- mode: 448
2928
- });
2929
- const targetPath = path.join(agentDir, "models.json");
2930
- const content = JSON.stringify({ providers: {} }, null, 2) + "\n";
2931
- let existing = "";
2932
- try {
2933
- existing = await fs.readFile(targetPath, "utf8");
2934
- } catch {}
2935
- if (existing === content) return {
2936
- agentDir,
2937
- wrote: false
2938
- };
2939
- await fs.writeFile(targetPath, content, { mode: 384 });
2940
- return {
2941
- agentDir,
2942
- wrote: true
2943
- };
2944
- }
2945
-
2946
- //#endregion
2947
- //#region src/agents/model-catalog.ts
2948
- let modelCatalogPromise = null;
2949
- let hasLoggedModelCatalogError = false;
2950
- const defaultImportPiSdk = () => import("./pi-model-discovery-Cxs4pvC2.js");
2951
- let importPiSdk = defaultImportPiSdk;
2952
- const CODEX_PROVIDER = "openai-codex";
2953
- const OPENAI_CODEX_GPT53_MODEL_ID = "gpt-5.3-codex";
2954
- const OPENAI_CODEX_GPT53_SPARK_MODEL_ID = "gpt-5.3-codex-spark";
2955
- function applyOpenAICodexSparkFallback(models) {
2956
- if (models.some((entry) => entry.provider === CODEX_PROVIDER && entry.id.toLowerCase() === OPENAI_CODEX_GPT53_SPARK_MODEL_ID)) return;
2957
- const baseModel = models.find((entry) => entry.provider === CODEX_PROVIDER && entry.id.toLowerCase() === OPENAI_CODEX_GPT53_MODEL_ID);
2958
- if (!baseModel) return;
2959
- models.push({
2960
- ...baseModel,
2961
- id: OPENAI_CODEX_GPT53_SPARK_MODEL_ID,
2962
- name: OPENAI_CODEX_GPT53_SPARK_MODEL_ID
2963
- });
2964
- }
2965
- async function loadModelCatalog(params) {
2966
- if (params?.useCache === false) modelCatalogPromise = null;
2967
- if (modelCatalogPromise) return modelCatalogPromise;
2968
- modelCatalogPromise = (async () => {
2969
- const models = [];
2970
- const sortModels = (entries) => entries.sort((a, b) => {
2971
- const p = a.provider.localeCompare(b.provider);
2972
- if (p !== 0) return p;
2973
- return a.name.localeCompare(b.name);
2974
- });
2975
- try {
2976
- await ensureAnimaModelsJson(params?.config ?? loadConfig());
2977
- await (await import("./pi-auth-json-ZYzi3nxs.js")).ensurePiAuthJsonFromAuthProfiles(resolveAnimaAgentDir());
2978
- const piSdk = await importPiSdk();
2979
- const agentDir = resolveAnimaAgentDir();
2980
- const { join } = await import("node:path");
2981
- const authStorage = new piSdk.AuthStorage(join(agentDir, "auth.json"));
2982
- const registry = new piSdk.ModelRegistry(authStorage, join(agentDir, "models.json"));
2983
- const entries = Array.isArray(registry) ? registry : registry.getAll();
2984
- for (const entry of entries) {
2985
- const id = String(entry?.id ?? "").trim();
2986
- if (!id) continue;
2987
- const provider = String(entry?.provider ?? "").trim();
2988
- if (!provider) continue;
2989
- const name = String(entry?.name ?? id).trim() || id;
2990
- const contextWindow = typeof entry?.contextWindow === "number" && entry.contextWindow > 0 ? entry.contextWindow : void 0;
2991
- const reasoning = typeof entry?.reasoning === "boolean" ? entry.reasoning : void 0;
2992
- const input = Array.isArray(entry?.input) ? entry.input : void 0;
2993
- models.push({
2994
- id,
2995
- name,
2996
- provider,
2997
- contextWindow,
2998
- reasoning,
2999
- input
3000
- });
3001
- }
3002
- applyOpenAICodexSparkFallback(models);
3003
- if (models.length === 0) modelCatalogPromise = null;
3004
- return sortModels(models);
3005
- } catch (error) {
3006
- if (!hasLoggedModelCatalogError) {
3007
- hasLoggedModelCatalogError = true;
3008
- console.warn(`[model-catalog] Failed to load model catalog: ${String(error)}`);
3009
- }
3010
- modelCatalogPromise = null;
3011
- if (models.length > 0) return sortModels(models);
3012
- return [];
3013
- }
3014
- })();
3015
- return modelCatalogPromise;
3016
- }
3017
- /**
3018
- * Check if a model supports image input based on its catalog entry.
3019
- */
3020
- function modelSupportsVision(entry) {
3021
- return entry?.input?.includes("image") ?? false;
3022
- }
3023
- /**
3024
- * Find a model in the catalog by provider and model ID.
3025
- */
3026
- function findModelInCatalog(catalog, provider, modelId) {
3027
- const normalizedProvider = provider.toLowerCase().trim();
3028
- const normalizedModelId = modelId.toLowerCase().trim();
3029
- return catalog.find((entry) => entry.provider.toLowerCase() === normalizedProvider && entry.id.toLowerCase() === normalizedModelId);
3030
- }
3031
-
3032
- //#endregion
3033
- //#region src/agents/model-fallback.ts
3034
- /**
3035
- * Fallback abort check. Only treats explicit AbortError names as user aborts.
3036
- * Message-based checks (e.g., "aborted") can mask timeouts and skip fallback.
3037
- */
3038
- function isFallbackAbortError(err) {
3039
- if (!err || typeof err !== "object") return false;
3040
- if (isFailoverError(err)) return false;
3041
- return ("name" in err ? String(err.name) : "") === "AbortError";
3042
- }
3043
- function shouldRethrowAbort(err) {
3044
- return isFallbackAbortError(err) && !isTimeoutError(err);
3045
- }
3046
- function createModelCandidateCollector(allowlist) {
3047
- const seen = /* @__PURE__ */ new Set();
3048
- const candidates = [];
3049
- const addCandidate = (candidate, enforceAllowlist) => {
3050
- if (!candidate.provider || !candidate.model) return;
3051
- const key = modelKey(candidate.provider, candidate.model);
3052
- if (seen.has(key)) return;
3053
- if (enforceAllowlist && allowlist && !allowlist.has(key)) return;
3054
- seen.add(key);
3055
- candidates.push(candidate);
3056
- };
3057
- return {
3058
- candidates,
3059
- addCandidate
3060
- };
3061
- }
3062
- function resolveImageFallbackCandidates(params) {
3063
- const aliasIndex = buildModelAliasIndex({
3064
- cfg: params.cfg ?? {},
3065
- defaultProvider: params.defaultProvider
3066
- });
3067
- const { candidates, addCandidate } = createModelCandidateCollector(buildConfiguredAllowlistKeys({
3068
- cfg: params.cfg,
3069
- defaultProvider: params.defaultProvider
3070
- }));
3071
- const addRaw = (raw, enforceAllowlist) => {
3072
- const resolved = resolveModelRefFromString({
3073
- raw: String(raw ?? ""),
3074
- defaultProvider: params.defaultProvider,
3075
- aliasIndex
3076
- });
3077
- if (!resolved) return;
3078
- addCandidate(resolved.ref, enforceAllowlist);
3079
- };
3080
- if (params.modelOverride?.trim()) addRaw(params.modelOverride, false);
3081
- else {
3082
- const imageModel = params.cfg?.agents?.defaults?.imageModel;
3083
- const primary = typeof imageModel === "string" ? imageModel.trim() : imageModel?.primary;
3084
- if (primary?.trim()) addRaw(primary, false);
3085
- }
3086
- const imageFallbacks = (() => {
3087
- const imageModel = params.cfg?.agents?.defaults?.imageModel;
3088
- if (imageModel && typeof imageModel === "object") return imageModel.fallbacks ?? [];
3089
- return [];
3090
- })();
3091
- for (const raw of imageFallbacks) addRaw(raw, true);
3092
- return candidates;
3093
- }
3094
- function resolveFallbackCandidates(params) {
3095
- const primary = params.cfg ? resolveConfiguredModelRef({
3096
- cfg: params.cfg,
3097
- defaultProvider: DEFAULT_PROVIDER,
3098
- defaultModel: DEFAULT_MODEL
3099
- }) : null;
3100
- const defaultProvider = primary?.provider ?? DEFAULT_PROVIDER;
3101
- const defaultModel = primary?.model ?? DEFAULT_MODEL;
3102
- const normalizedPrimary = normalizeModelRef(String(params.provider ?? "").trim() || defaultProvider, String(params.model ?? "").trim() || defaultModel);
3103
- const aliasIndex = buildModelAliasIndex({
3104
- cfg: params.cfg ?? {},
3105
- defaultProvider
3106
- });
3107
- const { candidates, addCandidate } = createModelCandidateCollector(buildConfiguredAllowlistKeys({
3108
- cfg: params.cfg,
3109
- defaultProvider
3110
- }));
3111
- addCandidate(normalizedPrimary, false);
3112
- const modelFallbacks = (() => {
3113
- if (params.fallbacksOverride !== void 0) return params.fallbacksOverride;
3114
- const model = params.cfg?.agents?.defaults?.model;
3115
- if (model && typeof model === "object") return model.fallbacks ?? [];
3116
- return [];
3117
- })();
3118
- for (const raw of modelFallbacks) {
3119
- const resolved = resolveModelRefFromString({
3120
- raw: String(raw ?? ""),
3121
- defaultProvider,
3122
- aliasIndex
3123
- });
3124
- if (!resolved) continue;
3125
- addCandidate(resolved.ref, true);
3126
- }
3127
- if (params.fallbacksOverride === void 0 && primary?.provider && primary.model) addCandidate({
3128
- provider: primary.provider,
3129
- model: primary.model
3130
- }, false);
3131
- return candidates;
3132
- }
3133
- async function runWithModelFallback(params) {
3134
- const candidates = resolveFallbackCandidates({
3135
- cfg: params.cfg,
3136
- provider: params.provider,
3137
- model: params.model,
3138
- fallbacksOverride: params.fallbacksOverride
3139
- });
3140
- const authStore = params.cfg ? ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false }) : null;
3141
- const attempts = [];
3142
- let lastError;
3143
- for (let i = 0; i < candidates.length; i += 1) {
3144
- const candidate = candidates[i];
3145
- if (authStore) {
3146
- const profileIds = resolveAuthProfileOrder({
3147
- cfg: params.cfg,
3148
- store: authStore,
3149
- provider: candidate.provider
3150
- });
3151
- const isAnyProfileAvailable = profileIds.some((id) => !isProfileInCooldown(authStore, id));
3152
- if (profileIds.length > 0 && !isAnyProfileAvailable) {
3153
- attempts.push({
3154
- provider: candidate.provider,
3155
- model: candidate.model,
3156
- error: `Provider ${candidate.provider} is in cooldown (all profiles unavailable)`,
3157
- reason: "rate_limit"
3158
- });
3159
- continue;
3160
- }
3161
- }
3162
- try {
3163
- return {
3164
- result: await params.run(candidate.provider, candidate.model),
3165
- provider: candidate.provider,
3166
- model: candidate.model,
3167
- attempts
3168
- };
3169
- } catch (err) {
3170
- if (shouldRethrowAbort(err)) throw err;
3171
- if (isLikelyContextOverflowError(err instanceof Error ? err.message : String(err))) throw err;
3172
- const normalized = coerceToFailoverError(err, {
3173
- provider: candidate.provider,
3174
- model: candidate.model
3175
- }) ?? err;
3176
- if (!isFailoverError(normalized)) throw err;
3177
- lastError = normalized;
3178
- const described = describeFailoverError(normalized);
3179
- attempts.push({
3180
- provider: candidate.provider,
3181
- model: candidate.model,
3182
- error: described.message,
3183
- reason: described.reason,
3184
- status: described.status,
3185
- code: described.code
3186
- });
3187
- await params.onError?.({
3188
- provider: candidate.provider,
3189
- model: candidate.model,
3190
- error: normalized,
3191
- attempt: i + 1,
3192
- total: candidates.length
3193
- });
3194
- }
3195
- }
3196
- if (attempts.length <= 1 && lastError) throw lastError;
3197
- const summary = attempts.length > 0 ? attempts.map((attempt) => `${attempt.provider}/${attempt.model}: ${attempt.error}${attempt.reason ? ` (${attempt.reason})` : ""}`).join(" | ") : "unknown";
3198
- throw new Error(`All models failed (${attempts.length || candidates.length}): ${summary}`, { cause: lastError instanceof Error ? lastError : void 0 });
3199
- }
3200
- async function runWithImageModelFallback(params) {
3201
- const candidates = resolveImageFallbackCandidates({
3202
- cfg: params.cfg,
3203
- defaultProvider: DEFAULT_PROVIDER,
3204
- modelOverride: params.modelOverride
3205
- });
3206
- if (candidates.length === 0) throw new Error("No image model configured. Set agents.defaults.imageModel.primary or agents.defaults.imageModel.fallbacks.");
3207
- const attempts = [];
3208
- let lastError;
3209
- for (let i = 0; i < candidates.length; i += 1) {
3210
- const candidate = candidates[i];
3211
- try {
3212
- return {
3213
- result: await params.run(candidate.provider, candidate.model),
3214
- provider: candidate.provider,
3215
- model: candidate.model,
3216
- attempts
3217
- };
3218
- } catch (err) {
3219
- if (shouldRethrowAbort(err)) throw err;
3220
- lastError = err;
3221
- attempts.push({
3222
- provider: candidate.provider,
3223
- model: candidate.model,
3224
- error: err instanceof Error ? err.message : String(err)
3225
- });
3226
- await params.onError?.({
3227
- provider: candidate.provider,
3228
- model: candidate.model,
3229
- error: err,
3230
- attempt: i + 1,
3231
- total: candidates.length
3232
- });
3233
- }
3234
- }
3235
- if (attempts.length <= 1 && lastError) throw lastError;
3236
- const summary = attempts.length > 0 ? attempts.map((attempt) => `${attempt.provider}/${attempt.model}: ${attempt.error}`).join(" | ") : "unknown";
3237
- throw new Error(`All image models failed (${attempts.length || candidates.length}): ${summary}`, { cause: lastError instanceof Error ? lastError : void 0 });
3238
- }
3239
-
3240
- //#endregion
3241
- //#region src/agents/skills/frontmatter.ts
3242
- function parseFrontmatter(content) {
3243
- return parseFrontmatterBlock(content);
3244
- }
3245
- function parseInstallSpec(input) {
3246
- if (!input || typeof input !== "object") return;
3247
- const raw = input;
3248
- const kind = (typeof raw.kind === "string" ? raw.kind : typeof raw.type === "string" ? raw.type : "").trim().toLowerCase();
3249
- if (kind !== "brew" && kind !== "node" && kind !== "go" && kind !== "uv" && kind !== "download") return;
3250
- const spec = { kind };
3251
- if (typeof raw.id === "string") spec.id = raw.id;
3252
- if (typeof raw.label === "string") spec.label = raw.label;
3253
- const bins = normalizeStringList(raw.bins);
3254
- if (bins.length > 0) spec.bins = bins;
3255
- const osList = normalizeStringList(raw.os);
3256
- if (osList.length > 0) spec.os = osList;
3257
- if (typeof raw.formula === "string") spec.formula = raw.formula;
3258
- if (typeof raw.package === "string") spec.package = raw.package;
3259
- if (typeof raw.module === "string") spec.module = raw.module;
3260
- if (typeof raw.url === "string") spec.url = raw.url;
3261
- if (typeof raw.archive === "string") spec.archive = raw.archive;
3262
- if (typeof raw.extract === "boolean") spec.extract = raw.extract;
3263
- if (typeof raw.stripComponents === "number") spec.stripComponents = raw.stripComponents;
3264
- if (typeof raw.targetDir === "string") spec.targetDir = raw.targetDir;
3265
- return spec;
3266
- }
3267
- function resolveAnimaMetadata(frontmatter) {
3268
- const metadataObj = resolveAnimaManifestBlock({ frontmatter });
3269
- if (!metadataObj) return;
3270
- const requiresRaw = typeof metadataObj.requires === "object" && metadataObj.requires !== null ? metadataObj.requires : void 0;
3271
- const install = (Array.isArray(metadataObj.install) ? metadataObj.install : []).map((entry) => parseInstallSpec(entry)).filter((entry) => Boolean(entry));
3272
- const osRaw = normalizeStringList(metadataObj.os);
3273
- return {
3274
- always: typeof metadataObj.always === "boolean" ? metadataObj.always : void 0,
3275
- emoji: typeof metadataObj.emoji === "string" ? metadataObj.emoji : void 0,
3276
- homepage: typeof metadataObj.homepage === "string" ? metadataObj.homepage : void 0,
3277
- skillKey: typeof metadataObj.skillKey === "string" ? metadataObj.skillKey : void 0,
3278
- primaryEnv: typeof metadataObj.primaryEnv === "string" ? metadataObj.primaryEnv : void 0,
3279
- os: osRaw.length > 0 ? osRaw : void 0,
3280
- requires: requiresRaw ? {
3281
- bins: normalizeStringList(requiresRaw.bins),
3282
- anyBins: normalizeStringList(requiresRaw.anyBins),
3283
- env: normalizeStringList(requiresRaw.env),
3284
- config: normalizeStringList(requiresRaw.config)
3285
- } : void 0,
3286
- install: install.length > 0 ? install : void 0
3287
- };
3288
- }
3289
- function resolveSkillInvocationPolicy(frontmatter) {
3290
- return {
3291
- userInvocable: parseFrontmatterBool(getFrontmatterString(frontmatter, "user-invocable"), true),
3292
- disableModelInvocation: parseFrontmatterBool(getFrontmatterString(frontmatter, "disable-model-invocation"), false)
3293
- };
3294
- }
3295
- function resolveSkillKey(skill, entry) {
3296
- return entry?.metadata?.skillKey ?? skill.name;
3297
- }
3298
-
3299
- //#endregion
3300
- //#region src/agents/skills/config.ts
3301
- const DEFAULT_CONFIG_VALUES = {
3302
- "browser.enabled": true,
3303
- "browser.evaluateEnabled": true
3304
- };
3305
- function isConfigPathTruthy(config, pathStr) {
3306
- return isConfigPathTruthyWithDefaults(config, pathStr, DEFAULT_CONFIG_VALUES);
3307
- }
3308
- function resolveSkillConfig(config, skillKey) {
3309
- const skills = config?.skills?.entries;
3310
- if (!skills || typeof skills !== "object") return;
3311
- const entry = skills[skillKey];
3312
- if (!entry || typeof entry !== "object") return;
3313
- return entry;
3314
- }
3315
- function normalizeAllowlist(input) {
3316
- if (!input) return;
3317
- if (!Array.isArray(input)) return;
3318
- const normalized = input.map((entry) => String(entry).trim()).filter(Boolean);
3319
- return normalized.length > 0 ? normalized : void 0;
3320
- }
3321
- const BUNDLED_SOURCES = new Set(["anima-bundled"]);
3322
- function isBundledSkill(entry) {
3323
- return BUNDLED_SOURCES.has(entry.skill.source);
3324
- }
3325
- function isBundledSkillAllowed(entry, allowlist) {
3326
- if (!allowlist || allowlist.length === 0) return true;
3327
- if (!isBundledSkill(entry)) return true;
3328
- const key = resolveSkillKey(entry.skill, entry);
3329
- return allowlist.includes(key) || allowlist.includes(entry.skill.name);
3330
- }
3331
- function shouldIncludeSkill(params) {
3332
- const { entry, config, eligibility } = params;
3333
- const skillConfig = resolveSkillConfig(config, resolveSkillKey(entry.skill, entry));
3334
- const allowBundled = normalizeAllowlist(config?.skills?.allowBundled);
3335
- const osList = entry.metadata?.os ?? [];
3336
- const remotePlatforms = eligibility?.remote?.platforms ?? [];
3337
- if (skillConfig?.enabled === false) return false;
3338
- if (!isBundledSkillAllowed(entry, allowBundled)) return false;
3339
- if (osList.length > 0 && !osList.includes(resolveRuntimePlatform()) && !remotePlatforms.some((platform) => osList.includes(platform))) return false;
3340
- if (entry.metadata?.always === true) return true;
3341
- const requiredBins = entry.metadata?.requires?.bins ?? [];
3342
- if (requiredBins.length > 0) for (const bin of requiredBins) {
3343
- if (hasBinary(bin)) continue;
3344
- if (eligibility?.remote?.hasBin?.(bin)) continue;
3345
- return false;
3346
- }
3347
- const requiredAnyBins = entry.metadata?.requires?.anyBins ?? [];
3348
- if (requiredAnyBins.length > 0) {
3349
- if (!(requiredAnyBins.some((bin) => hasBinary(bin)) || eligibility?.remote?.hasAnyBin?.(requiredAnyBins))) return false;
3350
- }
3351
- const requiredEnv = entry.metadata?.requires?.env ?? [];
3352
- if (requiredEnv.length > 0) for (const envName of requiredEnv) {
3353
- if (process.env[envName]) continue;
3354
- if (skillConfig?.env?.[envName]) continue;
3355
- if (skillConfig?.apiKey && entry.metadata?.primaryEnv === envName) continue;
3356
- return false;
3357
- }
3358
- const requiredConfig = entry.metadata?.requires?.config ?? [];
3359
- if (requiredConfig.length > 0) {
3360
- for (const configPath of requiredConfig) if (!isConfigPathTruthy(config, configPath)) return false;
3361
- }
3362
- return true;
3363
- }
3364
-
3365
- //#endregion
3366
- //#region src/agents/sandbox-paths.ts
3367
- const UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
3368
- const HTTP_URL_RE = /^https?:\/\//i;
3369
- const DATA_URL_RE = /^data:/i;
3370
- function normalizeUnicodeSpaces(str) {
3371
- return str.replace(UNICODE_SPACES, " ");
3372
- }
3373
- function expandPath(filePath) {
3374
- const normalized = normalizeUnicodeSpaces(filePath);
3375
- if (normalized === "~") return os.homedir();
3376
- if (normalized.startsWith("~/")) return os.homedir() + normalized.slice(1);
3377
- return normalized;
3378
- }
3379
- function resolveToCwd(filePath, cwd) {
3380
- const expanded = expandPath(filePath);
3381
- if (path.isAbsolute(expanded)) return expanded;
3382
- return path.resolve(cwd, expanded);
3383
- }
3384
- function resolveSandboxInputPath(filePath, cwd) {
3385
- return resolveToCwd(filePath, cwd);
3386
- }
3387
- function resolveSandboxPath(params) {
3388
- const resolved = resolveSandboxInputPath(params.filePath, params.cwd);
3389
- const rootResolved = path.resolve(params.root);
3390
- const relative = path.relative(rootResolved, resolved);
3391
- if (!relative || relative === "") return {
3392
- resolved,
3393
- relative: ""
3394
- };
3395
- if (relative.startsWith("..") || path.isAbsolute(relative)) throw new Error(`Path escapes sandbox root (${shortPath(rootResolved)}): ${params.filePath}`);
3396
- return {
3397
- resolved,
3398
- relative
3399
- };
3400
- }
3401
- async function assertSandboxPath(params) {
3402
- const resolved = resolveSandboxPath(params);
3403
- await assertNoSymlinkEscape(resolved.relative, path.resolve(params.root), { allowFinalSymlink: params.allowFinalSymlink });
3404
- return resolved;
3405
- }
3406
- function assertMediaNotDataUrl(media) {
3407
- const raw = media.trim();
3408
- if (DATA_URL_RE.test(raw)) throw new Error("data: URLs are not supported for media. Use buffer instead.");
3409
- }
3410
- async function resolveSandboxedMediaSource(params) {
3411
- const raw = params.media.trim();
3412
- if (!raw) return raw;
3413
- if (HTTP_URL_RE.test(raw)) return raw;
3414
- let candidate = raw;
3415
- if (/^file:\/\//i.test(candidate)) try {
3416
- candidate = fileURLToPath(candidate);
3417
- } catch {
3418
- throw new Error(`Invalid file:// URL for sandboxed media: ${raw}`);
3419
- }
3420
- return (await assertSandboxPath({
3421
- filePath: candidate,
3422
- cwd: params.sandboxRoot,
3423
- root: params.sandboxRoot
3424
- })).resolved;
3425
- }
3426
- async function assertNoSymlinkEscape(relative, root, options) {
3427
- if (!relative) return;
3428
- const rootReal = await tryRealpath(root);
3429
- const parts = relative.split(path.sep).filter(Boolean);
3430
- let current = root;
3431
- for (let idx = 0; idx < parts.length; idx += 1) {
3432
- const part = parts[idx];
3433
- const isLast = idx === parts.length - 1;
3434
- current = path.join(current, part);
3435
- try {
3436
- if ((await fs.lstat(current)).isSymbolicLink()) {
3437
- if (options?.allowFinalSymlink && isLast) return;
3438
- const target = await tryRealpath(current);
3439
- if (!isPathInside(rootReal, target)) throw new Error(`Symlink escapes sandbox root (${shortPath(rootReal)}): ${shortPath(current)}`);
3440
- current = target;
3441
- }
3442
- } catch (err) {
3443
- if (err.code === "ENOENT") return;
3444
- throw err;
3445
- }
3446
- }
3447
- }
3448
- async function tryRealpath(value) {
3449
- try {
3450
- return await fs.realpath(value);
3451
- } catch {
3452
- return path.resolve(value);
3453
- }
3454
- }
3455
- function isPathInside(root, target) {
3456
- const relative = path.relative(root, target);
3457
- if (!relative || relative === "") return true;
3458
- return !(relative.startsWith("..") || path.isAbsolute(relative));
3459
- }
3460
- function shortPath(value) {
3461
- if (value.startsWith(os.homedir())) return `~${value.slice(os.homedir().length)}`;
3462
- return value;
3463
- }
3464
-
3465
- //#endregion
3466
- //#region src/agents/skills/bundled-dir.ts
3467
- function looksLikeSkillsDir(dir) {
3468
- try {
3469
- const entries = fs$1.readdirSync(dir, { withFileTypes: true });
3470
- for (const entry of entries) {
3471
- if (entry.name.startsWith(".")) continue;
3472
- const fullPath = path.join(dir, entry.name);
3473
- if (entry.isFile() && entry.name.endsWith(".md")) return true;
3474
- if (entry.isDirectory()) {
3475
- if (fs$1.existsSync(path.join(fullPath, "SKILL.md"))) return true;
3476
- }
3477
- }
3478
- } catch {
3479
- return false;
3480
- }
3481
- return false;
3482
- }
3483
- function resolveBundledSkillsDir(opts = {}) {
3484
- const override = process.env.ANIMA_BUNDLED_SKILLS_DIR?.trim();
3485
- if (override) return override;
3486
- try {
3487
- const execPath = opts.execPath ?? process.execPath;
3488
- const execDir = path.dirname(execPath);
3489
- const sibling = path.join(execDir, "skills");
3490
- if (fs$1.existsSync(sibling)) return sibling;
3491
- } catch {}
3492
- try {
3493
- const moduleUrl = opts.moduleUrl ?? import.meta.url;
3494
- const moduleDir = path.dirname(fileURLToPath(moduleUrl));
3495
- const packageRoot = resolveAnimaPackageRootSync({
3496
- argv1: opts.argv1 ?? process.argv[1],
3497
- moduleUrl,
3498
- cwd: opts.cwd ?? process.cwd()
3499
- });
3500
- if (packageRoot) {
3501
- const candidate = path.join(packageRoot, "skills");
3502
- if (looksLikeSkillsDir(candidate)) return candidate;
3503
- }
3504
- let current = moduleDir;
3505
- for (let depth = 0; depth < 6; depth += 1) {
3506
- const candidate = path.join(current, "skills");
3507
- if (looksLikeSkillsDir(candidate)) return candidate;
3508
- const next = path.dirname(current);
3509
- if (next === current) break;
3510
- current = next;
3511
- }
3512
- } catch {}
3513
- }
3514
-
3515
- //#endregion
3516
- //#region src/agents/skills/plugin-skills.ts
3517
- const log$2 = createSubsystemLogger("skills");
3518
- function resolvePluginSkillDirs(params) {
3519
- const workspaceDir = params.workspaceDir.trim();
3520
- if (!workspaceDir) return [];
3521
- const registry = loadPluginManifestRegistry({
3522
- workspaceDir,
3523
- config: params.config
3524
- });
3525
- if (registry.plugins.length === 0) return [];
3526
- const normalizedPlugins = normalizePluginsConfig(params.config?.plugins);
3527
- const memorySlot = normalizedPlugins.slots.memory;
3528
- let selectedMemoryPluginId = null;
3529
- const seen = /* @__PURE__ */ new Set();
3530
- const resolved = [];
3531
- for (const record of registry.plugins) {
3532
- if (!record.skills || record.skills.length === 0) continue;
3533
- if (!resolveEnableState(record.id, record.origin, normalizedPlugins).enabled) continue;
3534
- const memoryDecision = resolveMemorySlotDecision({
3535
- id: record.id,
3536
- kind: record.kind,
3537
- slot: memorySlot,
3538
- selectedId: selectedMemoryPluginId
3539
- });
3540
- if (!memoryDecision.enabled) continue;
3541
- if (memoryDecision.selected && record.kind === "memory") selectedMemoryPluginId = record.id;
3542
- for (const raw of record.skills) {
3543
- const trimmed = raw.trim();
3544
- if (!trimmed) continue;
3545
- const candidate = path.resolve(record.rootDir, trimmed);
3546
- if (!fs$1.existsSync(candidate)) {
3547
- log$2.warn(`plugin skill path not found (${record.id}): ${candidate}`);
3548
- continue;
3549
- }
3550
- if (seen.has(candidate)) continue;
3551
- seen.add(candidate);
3552
- resolved.push(candidate);
3553
- }
3554
- }
3555
- return resolved;
3556
- }
3557
-
3558
- //#endregion
3559
- //#region src/agents/skills/serialize.ts
3560
- const SKILLS_SYNC_QUEUE = /* @__PURE__ */ new Map();
3561
- async function serializeByKey(key, task) {
3562
- const next = (SKILLS_SYNC_QUEUE.get(key) ?? Promise.resolve()).then(task, task);
3563
- SKILLS_SYNC_QUEUE.set(key, next);
3564
- try {
3565
- return await next;
3566
- } finally {
3567
- if (SKILLS_SYNC_QUEUE.get(key) === next) SKILLS_SYNC_QUEUE.delete(key);
3568
- }
3569
- }
3570
-
3571
- //#endregion
3572
- //#region src/agents/skills/workspace.ts
3573
- const fsp = fs$1.promises;
3574
- const skillsLogger = createSubsystemLogger("skills");
3575
- const skillCommandDebugOnce = /* @__PURE__ */ new Set();
3576
- function debugSkillCommandOnce(messageKey, message, meta) {
3577
- if (skillCommandDebugOnce.has(messageKey)) return;
3578
- skillCommandDebugOnce.add(messageKey);
3579
- skillsLogger.debug(message, meta);
3580
- }
3581
- function filterSkillEntries(entries, config, skillFilter, eligibility) {
3582
- let filtered = entries.filter((entry) => shouldIncludeSkill({
3583
- entry,
3584
- config,
3585
- eligibility
3586
- }));
3587
- if (skillFilter !== void 0) {
3588
- const normalized = skillFilter.map((entry) => String(entry).trim()).filter(Boolean);
3589
- const label = normalized.length > 0 ? normalized.join(", ") : "(none)";
3590
- console.log(`[skills] Applying skill filter: ${label}`);
3591
- filtered = normalized.length > 0 ? filtered.filter((entry) => normalized.includes(entry.skill.name)) : [];
3592
- console.log(`[skills] After filter: ${filtered.map((entry) => entry.skill.name).join(", ")}`);
3593
- }
3594
- return filtered;
3595
- }
3596
- const SKILL_COMMAND_MAX_LENGTH = 32;
3597
- const SKILL_COMMAND_FALLBACK = "skill";
3598
- const SKILL_COMMAND_DESCRIPTION_MAX_LENGTH = 100;
3599
- function sanitizeSkillCommandName(raw) {
3600
- return raw.toLowerCase().replace(/[^a-z0-9_]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").slice(0, SKILL_COMMAND_MAX_LENGTH) || SKILL_COMMAND_FALLBACK;
3601
- }
3602
- function resolveUniqueSkillCommandName(base, used) {
3603
- const normalizedBase = base.toLowerCase();
3604
- if (!used.has(normalizedBase)) return base;
3605
- for (let index = 2; index < 1e3; index += 1) {
3606
- const suffix = `_${index}`;
3607
- const maxBaseLength = Math.max(1, SKILL_COMMAND_MAX_LENGTH - suffix.length);
3608
- const candidate = `${base.slice(0, maxBaseLength)}${suffix}`;
3609
- const candidateKey = candidate.toLowerCase();
3610
- if (!used.has(candidateKey)) return candidate;
3611
- }
3612
- return `${base.slice(0, Math.max(1, SKILL_COMMAND_MAX_LENGTH - 2))}_x`;
3613
- }
3614
- function loadSkillEntries(workspaceDir, opts) {
3615
- const loadSkills = (params) => {
3616
- const loaded = loadSkillsFromDir(params);
3617
- if (Array.isArray(loaded)) return loaded;
3618
- if (loaded && typeof loaded === "object" && "skills" in loaded && Array.isArray(loaded.skills)) return loaded.skills;
3619
- return [];
3620
- };
3621
- const managedSkillsDir = opts?.managedSkillsDir ?? path.join(CONFIG_DIR, "skills");
3622
- const workspaceSkillsDir = path.resolve(workspaceDir, "skills");
3623
- const bundledSkillsDir = opts?.bundledSkillsDir ?? resolveBundledSkillsDir();
3624
- const extraDirs = (opts?.config?.skills?.load?.extraDirs ?? []).map((d) => typeof d === "string" ? d.trim() : "").filter(Boolean);
3625
- const pluginSkillDirs = resolvePluginSkillDirs({
3626
- workspaceDir,
3627
- config: opts?.config
3628
- });
3629
- const mergedExtraDirs = [...extraDirs, ...pluginSkillDirs];
3630
- const bundledSkills = bundledSkillsDir ? loadSkills({
3631
- dir: bundledSkillsDir,
3632
- source: "anima-bundled"
3633
- }) : [];
3634
- const extraSkills = mergedExtraDirs.flatMap((dir) => {
3635
- return loadSkills({
3636
- dir: resolveUserPath(dir),
3637
- source: "anima-extra"
3638
- });
3639
- });
3640
- const managedSkills = loadSkills({
3641
- dir: managedSkillsDir,
3642
- source: "anima-managed"
3643
- });
3644
- const personalAgentsSkills = loadSkills({
3645
- dir: path.resolve(os.homedir(), ".agents", "skills"),
3646
- source: "agents-skills-personal"
3647
- });
3648
- const projectAgentsSkills = loadSkills({
3649
- dir: path.resolve(workspaceDir, ".agents", "skills"),
3650
- source: "agents-skills-project"
3651
- });
3652
- const workspaceSkills = loadSkills({
3653
- dir: workspaceSkillsDir,
3654
- source: "anima-workspace"
3655
- });
3656
- const merged = /* @__PURE__ */ new Map();
3657
- for (const skill of extraSkills) merged.set(skill.name, skill);
3658
- for (const skill of bundledSkills) merged.set(skill.name, skill);
3659
- for (const skill of managedSkills) merged.set(skill.name, skill);
3660
- for (const skill of personalAgentsSkills) merged.set(skill.name, skill);
3661
- for (const skill of projectAgentsSkills) merged.set(skill.name, skill);
3662
- for (const skill of workspaceSkills) merged.set(skill.name, skill);
3663
- return Array.from(merged.values()).map((skill) => {
3664
- let frontmatter = {};
3665
- try {
3666
- frontmatter = parseFrontmatter(fs$1.readFileSync(skill.filePath, "utf-8"));
3667
- } catch {}
3668
- return {
3669
- skill,
3670
- frontmatter,
3671
- metadata: resolveAnimaMetadata(frontmatter),
3672
- invocation: resolveSkillInvocationPolicy(frontmatter)
3673
- };
3674
- });
3675
- }
3676
- function buildWorkspaceSkillSnapshot(workspaceDir, opts) {
3677
- const eligible = filterSkillEntries(opts?.entries ?? loadSkillEntries(workspaceDir, opts), opts?.config, opts?.skillFilter, opts?.eligibility);
3678
- const resolvedSkills = eligible.filter((entry) => entry.invocation?.disableModelInvocation !== true).map((entry) => entry.skill);
3679
- return {
3680
- prompt: [opts?.eligibility?.remote?.note?.trim(), formatSkillsForPrompt(resolvedSkills)].filter(Boolean).join("\n"),
3681
- skills: eligible.map((entry) => ({
3682
- name: entry.skill.name,
3683
- primaryEnv: entry.metadata?.primaryEnv
3684
- })),
3685
- resolvedSkills,
3686
- version: opts?.snapshotVersion
3687
- };
3688
- }
3689
- function resolveUniqueSyncedSkillDirName(base, used) {
3690
- if (!used.has(base)) {
3691
- used.add(base);
3692
- return base;
3693
- }
3694
- for (let index = 2; index < 1e4; index += 1) {
3695
- const candidate = `${base}-${index}`;
3696
- if (!used.has(candidate)) {
3697
- used.add(candidate);
3698
- return candidate;
3699
- }
3700
- }
3701
- let fallbackIndex = 1e4;
3702
- let fallback = `${base}-${fallbackIndex}`;
3703
- while (used.has(fallback)) {
3704
- fallbackIndex += 1;
3705
- fallback = `${base}-${fallbackIndex}`;
3706
- }
3707
- used.add(fallback);
3708
- return fallback;
3709
- }
3710
- function resolveSyncedSkillDestinationPath(params) {
3711
- const sourceDirName = path.basename(params.entry.skill.baseDir).trim();
3712
- if (!sourceDirName || sourceDirName === "." || sourceDirName === "..") return null;
3713
- return resolveSandboxPath({
3714
- filePath: resolveUniqueSyncedSkillDirName(sourceDirName, params.usedDirNames),
3715
- cwd: params.targetSkillsDir,
3716
- root: params.targetSkillsDir
3717
- }).resolved;
3718
- }
3719
- async function syncSkillsToWorkspace(params) {
3720
- const sourceDir = resolveUserPath(params.sourceWorkspaceDir);
3721
- const targetDir = resolveUserPath(params.targetWorkspaceDir);
3722
- if (sourceDir === targetDir) return;
3723
- await serializeByKey(`syncSkills:${targetDir}`, async () => {
3724
- const targetSkillsDir = path.join(targetDir, "skills");
3725
- const entries = loadSkillEntries(sourceDir, {
3726
- config: params.config,
3727
- managedSkillsDir: params.managedSkillsDir,
3728
- bundledSkillsDir: params.bundledSkillsDir
3729
- });
3730
- await fsp.rm(targetSkillsDir, {
3731
- recursive: true,
3732
- force: true
3733
- });
3734
- await fsp.mkdir(targetSkillsDir, { recursive: true });
3735
- const usedDirNames = /* @__PURE__ */ new Set();
3736
- for (const entry of entries) {
3737
- let dest = null;
3738
- try {
3739
- dest = resolveSyncedSkillDestinationPath({
3740
- targetSkillsDir,
3741
- entry,
3742
- usedDirNames
3743
- });
3744
- } catch (error) {
3745
- const message = error instanceof Error ? error.message : JSON.stringify(error);
3746
- console.warn(`[skills] Failed to resolve safe destination for ${entry.skill.name}: ${message}`);
3747
- continue;
3748
- }
3749
- if (!dest) {
3750
- console.warn(`[skills] Failed to resolve safe destination for ${entry.skill.name}: invalid source directory name`);
3751
- continue;
3752
- }
3753
- try {
3754
- await fsp.cp(entry.skill.baseDir, dest, {
3755
- recursive: true,
3756
- force: true
3757
- });
3758
- } catch (error) {
3759
- const message = error instanceof Error ? error.message : JSON.stringify(error);
3760
- console.warn(`[skills] Failed to copy ${entry.skill.name} to sandbox: ${message}`);
3761
- }
3762
- }
3763
- });
3764
- }
3765
- function buildWorkspaceSkillCommandSpecs(workspaceDir, opts) {
3766
- const userInvocable = filterSkillEntries(opts?.entries ?? loadSkillEntries(workspaceDir, opts), opts?.config, opts?.skillFilter, opts?.eligibility).filter((entry) => entry.invocation?.userInvocable !== false);
3767
- const used = /* @__PURE__ */ new Set();
3768
- for (const reserved of opts?.reservedNames ?? []) used.add(reserved.toLowerCase());
3769
- const specs = [];
3770
- for (const entry of userInvocable) {
3771
- const rawName = entry.skill.name;
3772
- const base = sanitizeSkillCommandName(rawName);
3773
- if (base !== rawName) debugSkillCommandOnce(`sanitize:${rawName}:${base}`, `Sanitized skill command name "${rawName}" to "/${base}".`, {
3774
- rawName,
3775
- sanitized: `/${base}`
3776
- });
3777
- const unique = resolveUniqueSkillCommandName(base, used);
3778
- if (unique !== base) debugSkillCommandOnce(`dedupe:${rawName}:${unique}`, `De-duplicated skill command name for "${rawName}" to "/${unique}".`, {
3779
- rawName,
3780
- deduped: `/${unique}`
3781
- });
3782
- used.add(unique.toLowerCase());
3783
- const rawDescription = entry.skill.description?.trim() || rawName;
3784
- const description = rawDescription.length > SKILL_COMMAND_DESCRIPTION_MAX_LENGTH ? rawDescription.slice(0, SKILL_COMMAND_DESCRIPTION_MAX_LENGTH - 1) + "…" : rawDescription;
3785
- const dispatch = (() => {
3786
- const kindRaw = (entry.frontmatter?.["command-dispatch"] ?? entry.frontmatter?.["command_dispatch"] ?? "").trim().toLowerCase();
3787
- if (!kindRaw) return;
3788
- if (kindRaw !== "tool") return;
3789
- const toolName = (entry.frontmatter?.["command-tool"] ?? entry.frontmatter?.["command_tool"] ?? "").trim();
3790
- if (!toolName) {
3791
- debugSkillCommandOnce(`dispatch:missingTool:${rawName}`, `Skill command "/${unique}" requested tool dispatch but did not provide command-tool. Ignoring dispatch.`, {
3792
- skillName: rawName,
3793
- command: unique
3794
- });
3795
- return;
3796
- }
3797
- const argModeRaw = (entry.frontmatter?.["command-arg-mode"] ?? entry.frontmatter?.["command_arg_mode"] ?? "").trim().toLowerCase();
3798
- if (!(!argModeRaw || argModeRaw === "raw" ? "raw" : null)) debugSkillCommandOnce(`dispatch:badArgMode:${rawName}:${argModeRaw}`, `Skill command "/${unique}" requested tool dispatch but has unknown command-arg-mode. Falling back to raw.`, {
3799
- skillName: rawName,
3800
- command: unique,
3801
- argMode: argModeRaw
3802
- });
3803
- return {
3804
- kind: "tool",
3805
- toolName,
3806
- argMode: "raw"
3807
- };
3808
- })();
3809
- specs.push({
3810
- name: unique,
3811
- skillName: rawName,
3812
- description,
3813
- ...dispatch ? { dispatch } : {}
3814
- });
3815
- }
3816
- return specs;
3817
- }
3818
-
3819
- //#endregion
3820
- //#region src/agents/skills/refresh.ts
3821
- const log$1 = createSubsystemLogger("gateway/skills");
3822
- const listeners = /* @__PURE__ */ new Set();
3823
- const workspaceVersions = /* @__PURE__ */ new Map();
3824
- const watchers = /* @__PURE__ */ new Map();
3825
- let globalVersion = 0;
3826
- const DEFAULT_SKILLS_WATCH_IGNORED = [
3827
- /(^|[\\/])\.git([\\/]|$)/,
3828
- /(^|[\\/])node_modules([\\/]|$)/,
3829
- /(^|[\\/])dist([\\/]|$)/,
3830
- /(^|[\\/])\.venv([\\/]|$)/,
3831
- /(^|[\\/])venv([\\/]|$)/,
3832
- /(^|[\\/])__pycache__([\\/]|$)/,
3833
- /(^|[\\/])\.mypy_cache([\\/]|$)/,
3834
- /(^|[\\/])\.pytest_cache([\\/]|$)/,
3835
- /(^|[\\/])build([\\/]|$)/,
3836
- /(^|[\\/])\.cache([\\/]|$)/
3837
- ];
3838
- function bumpVersion(current) {
3839
- const now = Date.now();
3840
- return now <= current ? current + 1 : now;
3841
- }
3842
- function emit(event) {
3843
- for (const listener of listeners) try {
3844
- listener(event);
3845
- } catch (err) {
3846
- log$1.warn(`skills change listener failed: ${String(err)}`);
3847
- }
3848
- }
3849
- function resolveWatchPaths(workspaceDir, config) {
3850
- const paths = [];
3851
- if (workspaceDir.trim()) {
3852
- paths.push(path.join(workspaceDir, "skills"));
3853
- paths.push(path.join(workspaceDir, ".agents", "skills"));
3854
- }
3855
- paths.push(path.join(CONFIG_DIR, "skills"));
3856
- paths.push(path.join(os.homedir(), ".agents", "skills"));
3857
- const extraDirs = (config?.skills?.load?.extraDirs ?? []).map((d) => typeof d === "string" ? d.trim() : "").filter(Boolean).map((dir) => resolveUserPath(dir));
3858
- paths.push(...extraDirs);
3859
- const pluginSkillDirs = resolvePluginSkillDirs({
3860
- workspaceDir,
3861
- config
3862
- });
3863
- paths.push(...pluginSkillDirs);
3864
- return paths;
3865
- }
3866
- function toWatchGlobRoot(raw) {
3867
- return raw.replaceAll("\\", "/").replace(/\/+$/, "");
3868
- }
3869
- function resolveWatchTargets(workspaceDir, config) {
3870
- const targets = /* @__PURE__ */ new Set();
3871
- for (const root of resolveWatchPaths(workspaceDir, config)) {
3872
- const globRoot = toWatchGlobRoot(root);
3873
- targets.add(`${globRoot}/SKILL.md`);
3874
- targets.add(`${globRoot}/*/SKILL.md`);
3875
- }
3876
- return Array.from(targets).toSorted();
3877
- }
3878
- function bumpSkillsSnapshotVersion(params) {
3879
- const reason = params?.reason ?? "manual";
3880
- const changedPath = params?.changedPath;
3881
- if (params?.workspaceDir) {
3882
- const next = bumpVersion(workspaceVersions.get(params.workspaceDir) ?? 0);
3883
- workspaceVersions.set(params.workspaceDir, next);
3884
- emit({
3885
- workspaceDir: params.workspaceDir,
3886
- reason,
3887
- changedPath
3888
- });
3889
- return next;
3890
- }
3891
- globalVersion = bumpVersion(globalVersion);
3892
- emit({
3893
- reason,
3894
- changedPath
3895
- });
3896
- return globalVersion;
3897
- }
3898
- function getSkillsSnapshotVersion(workspaceDir) {
3899
- if (!workspaceDir) return globalVersion;
3900
- const local = workspaceVersions.get(workspaceDir) ?? 0;
3901
- return Math.max(globalVersion, local);
3902
- }
3903
- function ensureSkillsWatcher(params) {
3904
- const workspaceDir = params.workspaceDir.trim();
3905
- if (!workspaceDir) return;
3906
- const watchEnabled = params.config?.skills?.load?.watch !== false;
3907
- const debounceMsRaw = params.config?.skills?.load?.watchDebounceMs;
3908
- const debounceMs = typeof debounceMsRaw === "number" && Number.isFinite(debounceMsRaw) ? Math.max(0, debounceMsRaw) : 250;
3909
- const existing = watchers.get(workspaceDir);
3910
- if (!watchEnabled) {
3911
- if (existing) {
3912
- watchers.delete(workspaceDir);
3913
- if (existing.timer) clearTimeout(existing.timer);
3914
- existing.watcher.close().catch(() => {});
3915
- }
3916
- return;
3917
- }
3918
- const watchTargets = resolveWatchTargets(workspaceDir, params.config);
3919
- const pathsKey = watchTargets.join("|");
3920
- if (existing && existing.pathsKey === pathsKey && existing.debounceMs === debounceMs) return;
3921
- if (existing) {
3922
- watchers.delete(workspaceDir);
3923
- if (existing.timer) clearTimeout(existing.timer);
3924
- existing.watcher.close().catch(() => {});
3925
- }
3926
- const watcher = chokidar.watch(watchTargets, {
3927
- ignoreInitial: true,
3928
- awaitWriteFinish: {
3929
- stabilityThreshold: debounceMs,
3930
- pollInterval: 100
3931
- },
3932
- ignored: DEFAULT_SKILLS_WATCH_IGNORED
3933
- });
3934
- const state = {
3935
- watcher,
3936
- pathsKey,
3937
- debounceMs
3938
- };
3939
- const schedule = (changedPath) => {
3940
- state.pendingPath = changedPath ?? state.pendingPath;
3941
- if (state.timer) clearTimeout(state.timer);
3942
- state.timer = setTimeout(() => {
3943
- const pendingPath = state.pendingPath;
3944
- state.pendingPath = void 0;
3945
- state.timer = void 0;
3946
- bumpSkillsSnapshotVersion({
3947
- workspaceDir,
3948
- reason: "watch",
3949
- changedPath: pendingPath
3950
- });
3951
- }, debounceMs);
3952
- };
3953
- watcher.on("add", (p) => schedule(p));
3954
- watcher.on("change", (p) => schedule(p));
3955
- watcher.on("unlink", (p) => schedule(p));
3956
- watcher.on("error", (err) => {
3957
- log$1.warn(`skills watcher error (${workspaceDir}): ${String(err)}`);
3958
- });
3959
- watchers.set(workspaceDir, state);
3960
- }
3961
-
3962
- //#endregion
3963
- //#region src/auto-reply/thinking.ts
3964
- function normalizeProviderId(provider) {
3965
- if (!provider) return "";
3966
- const normalized = provider.trim().toLowerCase();
3967
- if (normalized === "z.ai" || normalized === "z-ai") return "zai";
3968
- return normalized;
3969
- }
3970
- function isBinaryThinkingProvider(provider) {
3971
- return normalizeProviderId(provider) === "zai";
3972
- }
3973
- const XHIGH_MODEL_REFS = [
3974
- "openai/gpt-5.2",
3975
- "openai-codex/gpt-5.3-codex",
3976
- "openai-codex/gpt-5.3-codex-spark",
3977
- "openai-codex/gpt-5.2-codex",
3978
- "openai-codex/gpt-5.1-codex",
3979
- "github-copilot/gpt-5.2-codex",
3980
- "github-copilot/gpt-5.2"
3981
- ];
3982
- const XHIGH_MODEL_SET = new Set(XHIGH_MODEL_REFS.map((entry) => entry.toLowerCase()));
3983
- const XHIGH_MODEL_IDS = new Set(XHIGH_MODEL_REFS.map((entry) => entry.split("/")[1]?.toLowerCase()).filter((entry) => Boolean(entry)));
3984
- function normalizeThinkLevel(raw) {
3985
- if (!raw) return;
3986
- const key = raw.trim().toLowerCase();
3987
- const collapsed = key.replace(/[\s_-]+/g, "");
3988
- if (collapsed === "xhigh" || collapsed === "extrahigh") return "xhigh";
3989
- if (["off"].includes(key)) return "off";
3990
- if ([
3991
- "on",
3992
- "enable",
3993
- "enabled"
3994
- ].includes(key)) return "low";
3995
- if (["min", "minimal"].includes(key)) return "minimal";
3996
- if ([
3997
- "low",
3998
- "thinkhard",
3999
- "think-hard",
4000
- "think_hard"
4001
- ].includes(key)) return "low";
4002
- if ([
4003
- "mid",
4004
- "med",
4005
- "medium",
4006
- "thinkharder",
4007
- "think-harder",
4008
- "harder"
4009
- ].includes(key)) return "medium";
4010
- if ([
4011
- "high",
4012
- "ultra",
4013
- "ultrathink",
4014
- "think-hard",
4015
- "thinkhardest",
4016
- "highest",
4017
- "max"
4018
- ].includes(key)) return "high";
4019
- if (["think"].includes(key)) return "minimal";
4020
- }
4021
- function supportsXHighThinking(provider, model) {
4022
- const modelKey = model?.trim().toLowerCase();
4023
- if (!modelKey) return false;
4024
- const providerKey = provider?.trim().toLowerCase();
4025
- if (providerKey) return XHIGH_MODEL_SET.has(`${providerKey}/${modelKey}`);
4026
- return XHIGH_MODEL_IDS.has(modelKey);
4027
- }
4028
- function listThinkingLevels(provider, model) {
4029
- const levels = [
4030
- "off",
4031
- "minimal",
4032
- "low",
4033
- "medium",
4034
- "high"
4035
- ];
4036
- if (supportsXHighThinking(provider, model)) levels.push("xhigh");
4037
- return levels;
4038
- }
4039
- function listThinkingLevelLabels(provider, model) {
4040
- if (isBinaryThinkingProvider(provider)) return ["off", "on"];
4041
- return listThinkingLevels(provider, model);
4042
- }
4043
- function formatThinkingLevels(provider, model, separator = ", ") {
4044
- return listThinkingLevelLabels(provider, model).join(separator);
4045
- }
4046
- function formatXHighModelHint() {
4047
- const refs = [...XHIGH_MODEL_REFS];
4048
- if (refs.length === 0) return "unknown model";
4049
- if (refs.length === 1) return refs[0];
4050
- if (refs.length === 2) return `${refs[0]} or ${refs[1]}`;
4051
- return `${refs.slice(0, -1).join(", ")} or ${refs[refs.length - 1]}`;
4052
- }
4053
- function normalizeVerboseLevel(raw) {
4054
- if (!raw) return;
4055
- const key = raw.toLowerCase();
4056
- if ([
4057
- "off",
4058
- "false",
4059
- "no",
4060
- "0"
4061
- ].includes(key)) return "off";
4062
- if ([
4063
- "full",
4064
- "all",
4065
- "everything"
4066
- ].includes(key)) return "full";
4067
- if ([
4068
- "on",
4069
- "minimal",
4070
- "true",
4071
- "yes",
4072
- "1"
4073
- ].includes(key)) return "on";
4074
- }
4075
- function normalizeUsageDisplay(raw) {
4076
- if (!raw) return;
4077
- const key = raw.toLowerCase();
4078
- if ([
4079
- "off",
4080
- "false",
4081
- "no",
4082
- "0",
4083
- "disable",
4084
- "disabled"
4085
- ].includes(key)) return "off";
4086
- if ([
4087
- "on",
4088
- "true",
4089
- "yes",
4090
- "1",
4091
- "enable",
4092
- "enabled"
4093
- ].includes(key)) return "tokens";
4094
- if ([
4095
- "tokens",
4096
- "token",
4097
- "tok",
4098
- "minimal",
4099
- "min"
4100
- ].includes(key)) return "tokens";
4101
- if (["full", "session"].includes(key)) return "full";
4102
- }
4103
- function resolveResponseUsageMode(raw) {
4104
- return normalizeUsageDisplay(raw) ?? "off";
4105
- }
4106
- function normalizeElevatedLevel(raw) {
4107
- if (!raw) return;
4108
- const key = raw.toLowerCase();
4109
- if ([
4110
- "off",
4111
- "false",
4112
- "no",
4113
- "0"
4114
- ].includes(key)) return "off";
4115
- if ([
4116
- "full",
4117
- "auto",
4118
- "auto-approve",
4119
- "autoapprove"
4120
- ].includes(key)) return "full";
4121
- if ([
4122
- "ask",
4123
- "prompt",
4124
- "approval",
4125
- "approve"
4126
- ].includes(key)) return "ask";
4127
- if ([
4128
- "on",
4129
- "true",
4130
- "yes",
4131
- "1"
4132
- ].includes(key)) return "on";
4133
- }
4134
- function normalizeReasoningLevel(raw) {
4135
- if (!raw) return;
4136
- const key = raw.toLowerCase();
4137
- if ([
4138
- "off",
4139
- "false",
4140
- "no",
4141
- "0",
4142
- "hide",
4143
- "hidden",
4144
- "disable",
4145
- "disabled"
4146
- ].includes(key)) return "off";
4147
- if ([
4148
- "on",
4149
- "true",
4150
- "yes",
4151
- "1",
4152
- "show",
4153
- "visible",
4154
- "enable",
4155
- "enabled"
4156
- ].includes(key)) return "on";
4157
- if ([
4158
- "stream",
4159
- "streaming",
4160
- "draft",
4161
- "live"
4162
- ].includes(key)) return "stream";
4163
- }
4164
-
4165
- //#endregion
4166
- //#region src/infra/pairing-files.ts
4167
- function createAsyncLock() {
4168
- let lock = Promise.resolve();
4169
- return async function withLock(fn) {
4170
- const prev = lock;
4171
- let release;
4172
- lock = new Promise((resolve) => {
4173
- release = resolve;
4174
- });
4175
- await prev;
4176
- try {
4177
- return await fn();
4178
- } finally {
4179
- release?.();
4180
- }
4181
- };
4182
- }
4183
-
4184
- //#endregion
4185
- //#region src/infra/node-pairing.ts
4186
- const PENDING_TTL_MS = 300 * 1e3;
4187
- const withLock = createAsyncLock();
4188
-
4189
- //#endregion
4190
- //#region src/infra/skills-remote.ts
4191
- const log = createSubsystemLogger("gateway/skills-remote");
4192
- const remoteNodes = /* @__PURE__ */ new Map();
4193
- function isMacPlatform(platform, deviceFamily) {
4194
- const platformNorm = String(platform ?? "").trim().toLowerCase();
4195
- const familyNorm = String(deviceFamily ?? "").trim().toLowerCase();
4196
- if (platformNorm.includes("mac")) return true;
4197
- if (platformNorm.includes("darwin")) return true;
4198
- if (familyNorm === "mac") return true;
4199
- return false;
4200
- }
4201
- function supportsSystemRun(commands) {
4202
- return Array.isArray(commands) && commands.includes("system.run");
4203
- }
4204
- function getRemoteSkillEligibility() {
4205
- const macNodes = [...remoteNodes.values()].filter((node) => isMacPlatform(node.platform, node.deviceFamily) && supportsSystemRun(node.commands));
4206
- if (macNodes.length === 0) return;
4207
- const bins = /* @__PURE__ */ new Set();
4208
- for (const node of macNodes) for (const bin of node.bins) bins.add(bin);
4209
- const labels = macNodes.map((node) => node.displayName ?? node.nodeId).filter(Boolean);
4210
- return {
4211
- platforms: ["darwin"],
4212
- hasBin: (bin) => bins.has(bin),
4213
- hasAnyBin: (required) => required.some((bin) => bins.has(bin)),
4214
- note: labels.length > 0 ? `Remote macOS node available (${labels.join(", ")}). Run macOS-only skills via nodes.run on that node.` : "Remote macOS node available. Run macOS-only skills via nodes.run on that node."
4215
- };
4216
- }
4217
-
4218
- //#endregion
4219
- //#region src/sessions/level-overrides.ts
4220
- function applyVerboseOverride(entry, level) {
4221
- if (level === void 0) return;
4222
- if (level === null) {
4223
- delete entry.verboseLevel;
4224
- return;
4225
- }
4226
- entry.verboseLevel = level;
4227
- }
4228
-
4229
- //#endregion
4230
- //#region src/sessions/model-overrides.ts
4231
- function applyModelOverrideToSessionEntry(params) {
4232
- const { entry, selection, profileOverride } = params;
4233
- const profileOverrideSource = params.profileOverrideSource ?? "user";
4234
- let updated = false;
4235
- if (selection.isDefault) {
4236
- if (entry.providerOverride) {
4237
- delete entry.providerOverride;
4238
- updated = true;
4239
- }
4240
- if (entry.modelOverride) {
4241
- delete entry.modelOverride;
4242
- updated = true;
4243
- }
4244
- } else {
4245
- if (entry.providerOverride !== selection.provider) {
4246
- entry.providerOverride = selection.provider;
4247
- updated = true;
4248
- }
4249
- if (entry.modelOverride !== selection.model) {
4250
- entry.modelOverride = selection.model;
4251
- updated = true;
4252
- }
4253
- }
4254
- if (profileOverride) {
4255
- if (entry.authProfileOverride !== profileOverride) {
4256
- entry.authProfileOverride = profileOverride;
4257
- updated = true;
4258
- }
4259
- if (entry.authProfileOverrideSource !== profileOverrideSource) {
4260
- entry.authProfileOverrideSource = profileOverrideSource;
4261
- updated = true;
4262
- }
4263
- if (entry.authProfileOverrideCompactionCount !== void 0) {
4264
- delete entry.authProfileOverrideCompactionCount;
4265
- updated = true;
4266
- }
4267
- } else {
4268
- if (entry.authProfileOverride) {
4269
- delete entry.authProfileOverride;
4270
- updated = true;
4271
- }
4272
- if (entry.authProfileOverrideSource) {
4273
- delete entry.authProfileOverrideSource;
4274
- updated = true;
4275
- }
4276
- if (entry.authProfileOverrideCompactionCount !== void 0) {
4277
- delete entry.authProfileOverrideCompactionCount;
4278
- updated = true;
4279
- }
4280
- }
4281
- if (updated) entry.updatedAt = Date.now();
4282
- return { updated };
4283
- }
4284
-
4285
- //#endregion
4286
- //#region src/sessions/send-policy.ts
4287
- function normalizeSendPolicy(raw) {
4288
- const value = raw?.trim().toLowerCase();
4289
- if (value === "allow") return "allow";
4290
- if (value === "deny") return "deny";
4291
- }
4292
- function normalizeMatchValue(raw) {
4293
- const value = raw?.trim().toLowerCase();
4294
- return value ? value : void 0;
4295
- }
4296
- function stripAgentSessionKeyPrefix(key) {
4297
- if (!key) return;
4298
- const parts = key.split(":").filter(Boolean);
4299
- if (parts.length >= 3 && parts[0] === "agent") return parts.slice(2).join(":");
4300
- return key;
4301
- }
4302
- function deriveChannelFromKey(key) {
4303
- const normalizedKey = stripAgentSessionKeyPrefix(key);
4304
- if (!normalizedKey) return;
4305
- const parts = normalizedKey.split(":").filter(Boolean);
4306
- if (parts.length >= 3 && (parts[1] === "group" || parts[1] === "channel")) return normalizeMatchValue(parts[0]);
4307
- }
4308
- function deriveChatTypeFromKey(key) {
4309
- const normalizedKey = stripAgentSessionKeyPrefix(key);
4310
- if (!normalizedKey) return;
4311
- if (normalizedKey.includes(":group:")) return "group";
4312
- if (normalizedKey.includes(":channel:")) return "channel";
4313
- }
4314
- function resolveSendPolicy(params) {
4315
- const override = normalizeSendPolicy(params.entry?.sendPolicy);
4316
- if (override) return override;
4317
- const policy = params.cfg.session?.sendPolicy;
4318
- if (!policy) return "allow";
4319
- const channel = normalizeMatchValue(params.channel) ?? normalizeMatchValue(params.entry?.channel) ?? normalizeMatchValue(params.entry?.lastChannel) ?? deriveChannelFromKey(params.sessionKey);
4320
- const chatType = normalizeChatType(params.chatType ?? params.entry?.chatType) ?? normalizeChatType(deriveChatTypeFromKey(params.sessionKey));
4321
- const rawSessionKey = params.sessionKey ?? "";
4322
- const strippedSessionKey = stripAgentSessionKeyPrefix(rawSessionKey) ?? "";
4323
- const rawSessionKeyNorm = rawSessionKey.toLowerCase();
4324
- const strippedSessionKeyNorm = strippedSessionKey.toLowerCase();
4325
- let allowedMatch = false;
4326
- for (const rule of policy.rules ?? []) {
4327
- if (!rule) continue;
4328
- const action = normalizeSendPolicy(rule.action) ?? "allow";
4329
- const match = rule.match ?? {};
4330
- const matchChannel = normalizeMatchValue(match.channel);
4331
- const matchChatType = normalizeChatType(match.chatType);
4332
- const matchPrefix = normalizeMatchValue(match.keyPrefix);
4333
- const matchRawPrefix = normalizeMatchValue(match.rawKeyPrefix);
4334
- if (matchChannel && matchChannel !== channel) continue;
4335
- if (matchChatType && matchChatType !== chatType) continue;
4336
- if (matchRawPrefix && !rawSessionKeyNorm.startsWith(matchRawPrefix)) continue;
4337
- if (matchPrefix && !rawSessionKeyNorm.startsWith(matchPrefix) && !strippedSessionKeyNorm.startsWith(matchPrefix)) continue;
4338
- if (action === "deny") return "deny";
4339
- allowedMatch = true;
4340
- }
4341
- if (allowedMatch) return "allow";
4342
- return normalizeSendPolicy(policy.default) ?? "allow";
4343
- }
4344
-
4345
- //#endregion
4346
- //#region src/infra/outbound/target-errors.ts
4347
- function missingTargetMessage(provider, hint) {
4348
- return `Delivering to ${provider} requires target${formatTargetHint(hint)}`;
4349
- }
4350
- function missingTargetError(provider, hint) {
4351
- return new Error(missingTargetMessage(provider, hint));
4352
- }
4353
- function ambiguousTargetMessage(provider, raw, hint) {
4354
- return `Ambiguous target "${raw}" for ${provider}. Provide a unique name or an explicit id.${formatTargetHint(hint, true)}`;
4355
- }
4356
- function ambiguousTargetError(provider, raw, hint) {
4357
- return new Error(ambiguousTargetMessage(provider, raw, hint));
4358
- }
4359
- function unknownTargetMessage(provider, raw, hint) {
4360
- return `Unknown target "${raw}" for ${provider}.${formatTargetHint(hint, true)}`;
4361
- }
4362
- function unknownTargetError(provider, raw, hint) {
4363
- return new Error(unknownTargetMessage(provider, raw, hint));
4364
- }
4365
- function formatTargetHint(hint, withLabel = false) {
4366
- if (!hint) return "";
4367
- return withLabel ? ` Hint: ${hint}` : ` ${hint}`;
4368
- }
4369
-
4370
- //#endregion
4371
- //#region src/infra/outbound/targets.ts
4372
- function resolveSessionDeliveryTarget(params) {
4373
- const context = deliveryContextFromSession(params.entry);
4374
- const lastChannel = context?.channel && isDeliverableMessageChannel(context.channel) ? context.channel : void 0;
4375
- const lastTo = context?.to;
4376
- const lastAccountId = context?.accountId;
4377
- const lastThreadId = context?.threadId;
4378
- const rawRequested = params.requestedChannel ?? "last";
4379
- const requested = rawRequested === "last" ? "last" : normalizeMessageChannel(rawRequested);
4380
- const requestedChannel = requested === "last" ? "last" : requested && isDeliverableMessageChannel(requested) ? requested : void 0;
4381
- const explicitTo = typeof params.explicitTo === "string" && params.explicitTo.trim() ? params.explicitTo.trim() : void 0;
4382
- const explicitThreadId = params.explicitThreadId != null && params.explicitThreadId !== "" ? params.explicitThreadId : void 0;
4383
- let channel = requestedChannel === "last" ? lastChannel : requestedChannel;
4384
- if (!channel && params.fallbackChannel && isDeliverableMessageChannel(params.fallbackChannel)) channel = params.fallbackChannel;
4385
- let to = explicitTo;
4386
- if (!to && lastTo) {
4387
- if (channel && channel === lastChannel) to = lastTo;
4388
- else if (params.allowMismatchedLastTo) to = lastTo;
4389
- }
4390
- const accountId = channel && channel === lastChannel ? lastAccountId : void 0;
4391
- const threadId = channel && channel === lastChannel ? lastThreadId : void 0;
4392
- const mode = params.mode ?? (explicitTo ? "explicit" : "implicit");
4393
- return {
4394
- channel,
4395
- to,
4396
- accountId,
4397
- threadId: explicitThreadId ?? threadId,
4398
- mode,
4399
- lastChannel,
4400
- lastTo,
4401
- lastAccountId,
4402
- lastThreadId
4403
- };
4404
- }
4405
- function resolveOutboundTarget(params) {
4406
- if (params.channel === INTERNAL_MESSAGE_CHANNEL) return {
4407
- ok: false,
4408
- error: /* @__PURE__ */ new Error(`Delivering to WebChat is not supported via \`${formatCliCommand("anima agent")}\`; use WhatsApp/Telegram or run with --deliver=false.`)
4409
- };
4410
- const plugin = getChannelPlugin(params.channel);
4411
- if (!plugin) return {
4412
- ok: false,
4413
- error: /* @__PURE__ */ new Error(`Unsupported channel: ${params.channel}`)
4414
- };
4415
- const allowFrom = params.allowFrom ?? (params.cfg && plugin.config.resolveAllowFrom ? plugin.config.resolveAllowFrom({
4416
- cfg: params.cfg,
4417
- accountId: params.accountId ?? void 0
4418
- }) : void 0);
4419
- const resolveTarget = plugin.outbound?.resolveTarget;
4420
- if (resolveTarget) return resolveTarget({
4421
- cfg: params.cfg,
4422
- to: params.to,
4423
- allowFrom,
4424
- accountId: params.accountId ?? void 0,
4425
- mode: params.mode ?? "explicit"
4426
- });
4427
- const trimmed = params.to?.trim();
4428
- if (trimmed) return {
4429
- ok: true,
4430
- to: trimmed
4431
- };
4432
- const hint = plugin.messaging?.targetResolver?.hint;
4433
- return {
4434
- ok: false,
4435
- error: missingTargetError(plugin.meta.label ?? params.channel, hint)
4436
- };
4437
- }
4438
-
4439
- //#endregion
4440
- //#region src/agents/context.ts
4441
- const MODEL_CACHE = /* @__PURE__ */ new Map();
4442
- (async () => {
4443
- try {
4444
- const { discoverAuthStorage, discoverModels } = await import("./pi-model-discovery-Cxs4pvC2.js");
4445
- await ensureAnimaModelsJson(loadConfig());
4446
- const agentDir = resolveAnimaAgentDir();
4447
- const models = discoverModels(discoverAuthStorage(agentDir), agentDir).getAll();
4448
- for (const m of models) {
4449
- if (!m?.id) continue;
4450
- if (typeof m.contextWindow === "number" && m.contextWindow > 0) MODEL_CACHE.set(m.id, m.contextWindow);
4451
- }
4452
- } catch {}
4453
- })();
4454
- function lookupContextTokens(modelId) {
4455
- if (!modelId) return;
4456
- return MODEL_CACHE.get(modelId);
4457
- }
4458
-
4459
- //#endregion
4460
- //#region src/agents/usage.ts
4461
- const asFiniteNumber = (value) => {
4462
- if (typeof value !== "number") return;
4463
- if (!Number.isFinite(value)) return;
4464
- return value;
4465
- };
4466
- function hasNonzeroUsage(usage) {
4467
- if (!usage) return false;
4468
- return [
4469
- usage.input,
4470
- usage.output,
4471
- usage.cacheRead,
4472
- usage.cacheWrite,
4473
- usage.total
4474
- ].some((v) => typeof v === "number" && Number.isFinite(v) && v > 0);
4475
- }
4476
- function normalizeUsage(raw) {
4477
- if (!raw) return;
4478
- const input = asFiniteNumber(raw.input ?? raw.inputTokens ?? raw.input_tokens ?? raw.promptTokens ?? raw.prompt_tokens);
4479
- const output = asFiniteNumber(raw.output ?? raw.outputTokens ?? raw.output_tokens ?? raw.completionTokens ?? raw.completion_tokens);
4480
- const cacheRead = asFiniteNumber(raw.cacheRead ?? raw.cache_read ?? raw.cache_read_input_tokens);
4481
- const cacheWrite = asFiniteNumber(raw.cacheWrite ?? raw.cache_write ?? raw.cache_creation_input_tokens);
4482
- const total = asFiniteNumber(raw.total ?? raw.totalTokens ?? raw.total_tokens);
4483
- if (input === void 0 && output === void 0 && cacheRead === void 0 && cacheWrite === void 0 && total === void 0) return;
4484
- return {
4485
- input,
4486
- output,
4487
- cacheRead,
4488
- cacheWrite,
4489
- total
4490
- };
4491
- }
4492
- function derivePromptTokens(usage) {
4493
- if (!usage) return;
4494
- const input = usage.input ?? 0;
4495
- const cacheRead = usage.cacheRead ?? 0;
4496
- const cacheWrite = usage.cacheWrite ?? 0;
4497
- const sum = input + cacheRead + cacheWrite;
4498
- return sum > 0 ? sum : void 0;
4499
- }
4500
- function deriveSessionTotalTokens(params) {
4501
- const promptOverride = params.promptTokens;
4502
- const hasPromptOverride = typeof promptOverride === "number" && Number.isFinite(promptOverride) && promptOverride > 0;
4503
- const usage = params.usage;
4504
- if (!usage && !hasPromptOverride) return;
4505
- const input = usage?.input ?? 0;
4506
- let total = (hasPromptOverride ? promptOverride : derivePromptTokens({
4507
- input: usage?.input,
4508
- cacheRead: usage?.cacheRead,
4509
- cacheWrite: usage?.cacheWrite
4510
- })) ?? usage?.total ?? input;
4511
- if (!(total > 0)) return;
4512
- return total;
4513
- }
4514
-
4515
- //#endregion
4516
- export { getTtsProvider as $, assertSandboxPath as A, runCliAgent as B, supportsXHighThinking as C, buildWorkspaceSkillSnapshot as D, buildWorkspaceSkillCommandSpecs as E, loadModelCatalog as F, resolveUserTimezone as G, buildSystemPromptParams as H, modelSupportsVision as I, killProcessTree as J, withNormalizedTimestamp as K, ensureAnimaModelsJson as L, runWithImageModelFallback as M, runWithModelFallback as N, syncSkillsToWorkspace as O, findModelInCatalog as P, getTtsMaxLength as Q, getCliSessionId as R, resolveResponseUsageMode as S, getSkillsSnapshotVersion as T, formatUserTime as U, buildAgentSystemPrompt as V, resolveUserTimeFormat as W, buildTtsSystemPromptHint as X, sanitizeBinaryOutput as Y, getLastTtsAttempt as Z, normalizeElevatedLevel as _, resolveBootstrapContextForRun as _t, lookupContextTokens as a, resolveTtsApiKey as at, normalizeUsageDisplay as b, ambiguousTargetError as c, resolveTtsPrefsPath as ct, applyModelOverrideToSessionEntry as d, setTtsEnabled as dt, isSummarizationEnabled as et, applyVerboseOverride as f, setTtsMaxLength as ft, listThinkingLevels as g, isVoiceCompatibleAudio as gt, formatXHighModelHint as h, textToSpeechTelephony as ht, normalizeUsage as i, normalizeTtsAutoMode as it, resolveSandboxedMediaSource as j, assertMediaNotDataUrl as k, unknownTargetError as l, setLastTtsAttempt as lt, formatThinkingLevels as m, textToSpeech as mt, deriveSessionTotalTokens as n, isTtsProviderConfigured as nt, resolveOutboundTarget as o, resolveTtsAutoMode as ot, getRemoteSkillEligibility as p, setTtsProvider as pt, getShellConfig as q, hasNonzeroUsage as r, maybeApplyTtsToPayload as rt, resolveSessionDeliveryTarget as s, resolveTtsConfig as st, derivePromptTokens as t, isTtsEnabled as tt, resolveSendPolicy as u, setSummarizationEnabled as ut, normalizeReasoningLevel as v, clearSessionAuthProfileOverride as vt, ensureSkillsWatcher as w, normalizeVerboseLevel as x, normalizeThinkLevel as y, resolveSessionAuthProfileOverride as yt, setCliSessionId as z };