@gguf/claw 2026.2.9 → 2026.2.13

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 (715) hide show
  1. package/CHANGELOG.md +159 -0
  2. package/LICENSE +1 -1
  3. package/dist/{accounts-MyAvfCVH.js → accounts-54zZMYCo.js} +5 -2
  4. package/dist/{accounts-DbzMEfKN.js → accounts-Bvh0DFxS.js} +5 -2
  5. package/dist/{acp-cli-MZ3h1E1n.js → acp-cli-BslcOPdx.js} +146 -25
  6. package/dist/{acp-cli-DKJRTfwB.js → acp-cli-D6rk5cOh.js} +145 -24
  7. package/dist/{agent-whSJT2Lk.js → agent-C0yL70cy.js} +26 -20
  8. package/dist/{agent-c1QNeDmV.js → agent-DjZxytiC.js} +26 -20
  9. package/dist/{agent-scope-D3me2AZa.js → agent-scope-Bkr9fZtl.js} +31 -14
  10. package/dist/{agent-scope-Dp8sREli.js → agent-scope-DASgjz2_.js} +199 -14
  11. package/dist/{agent-scope-DnyDZ5RH.js → agent-scope-GYIs5dyU.js} +30 -13
  12. package/dist/{agent-scope-Dpav7C-i.js → agent-scope-okUOVjE5.js} +32 -11
  13. package/dist/audio-preflight-B0kLz-Ma.js +60 -0
  14. package/dist/audio-preflight-BCs_J33s.js +60 -0
  15. package/dist/audio-preflight-CTl2RCyF.js +71 -0
  16. package/dist/audio-preflight-MhF6YlAY.js +74 -0
  17. package/dist/{audit-BFYy1qSw.js → audit-BYfhZ7LA.js} +454 -31
  18. package/dist/{audit-Dn2cBl2x.js → audit-CfPZ_5Id.js} +452 -29
  19. package/dist/auth-9nTeB2Je.js +602 -0
  20. package/dist/auth-CLhyWwAU.js +593 -0
  21. package/dist/{auth-health-Cx5exPMV.js → auth-health-CWiLyzSr.js} +1 -1
  22. package/dist/{auth-health-DjT4fUpw.js → auth-health-qD4RND47.js} +1 -1
  23. package/dist/{auth-profiles-FJ3VY25a.js → auth-profiles-Cp9MtUdM.js} +353 -33
  24. package/dist/build-info.json +2 -2
  25. package/dist/bundled/boot-md/handler.js +33 -25
  26. package/dist/bundled/session-memory/handler.js +33 -22
  27. package/dist/{call-CD2IZCHT.js → call-CjEdFGAf.js} +7 -7
  28. package/dist/{call-CM25qgxz.js → call-DAfkvtVq.js} +6 -6
  29. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  30. package/dist/canvas-host/a2ui/a2ui.bundle.js +7 -1
  31. package/dist/{channel-options-CremuJyh.js → channel-options-B8dPzlyO.js} +4 -4
  32. package/dist/{channel-options-D-JnJ4Ft.js → channel-options-Bq5IC5Tv.js} +12 -7
  33. package/dist/{channel-selection-DAHCVAX4.js → channel-selection-BaW1xXEa.js} +2 -2
  34. package/dist/{channel-selection-DPV9hvY8.js → channel-selection-dR0jCgTn.js} +2 -2
  35. package/dist/{channels-cli-6deHFr9t.js → channels-cli-hPo28hWS.js} +61 -56
  36. package/dist/{channels-cli-D3tKmhlt.js → channels-cli-zi3rO0jq.js} +62 -57
  37. package/dist/{channels-status-issues-BN1ICfdy.js → channels-status-issues-kb-M2Fi0.js} +1 -1
  38. package/dist/{channels-status-issues-DFhI_u0p.js → channels-status-issues-ketdwZun.js} +1 -1
  39. package/dist/{chrome-B2UjqY-9.js → chrome--Fe8F5Kf.js} +24 -12
  40. package/dist/{chrome-COabMr6f.js → chrome-BWeMtFGf.js} +24 -12
  41. package/dist/{chrome-CQd_MVOA.js → chrome-Bx24uq7B.js} +27 -15
  42. package/dist/{chrome-CxRJz4ZD.js → chrome-n_3rtK2c.js} +22 -11
  43. package/dist/{clack-prompter-BkNZ4Xdw.js → clack-prompter-B-tJmODa.js} +5 -5
  44. package/dist/{clack-prompter-DuBVnTKy.js → clack-prompter-DpuKn_Uy.js} +5 -5
  45. package/dist/cli/daemon-cli.js +8 -1
  46. package/dist/cli-9lwO6Ttx.js +94 -0
  47. package/dist/cli-CNNdyxPO.js +91 -0
  48. package/dist/{client-DMloFP_O.js → client-BhZjzrH2.js} +73 -9
  49. package/dist/{client-C0gQ7hrj.js → client-DyAxKXKY.js} +73 -9
  50. package/dist/{command-format-ayFsmwwz.js → command-format-Bxe0mWee.js} +1 -1
  51. package/dist/{command-options-BQdH6qnK.js → command-options-BDV7Xgs-.js} +9 -4
  52. package/dist/{commands-BWHYcc83.js → commands-gOiRcfoU.js} +4 -4
  53. package/dist/{tui-formatters-BDP_71Xt.js → commands-registry-6NUFrejL.js} +6 -114
  54. package/dist/{tui-formatters-CIx4sCQO.js → commands-registry-DGgkLQ7A.js} +6 -114
  55. package/dist/{completion-cli-DEJia0V1.js → completion-cli-B1kHKJZX.js} +30 -30
  56. package/dist/{completion-cli-D_0fx2O6.js → completion-cli-Drks7xRK.js} +3 -3
  57. package/dist/{config-CQt4vGxI.js → config-7NCznPmF.js} +336 -97
  58. package/dist/{config-fCnPoWjU.js → config-B8v0zg48.js} +295 -99
  59. package/dist/{config-Bj2eDa02.js → config-CeWMHOiQ.js} +295 -99
  60. package/dist/{config-ethqi73X.js → config-D8pgDSNo.js} +358 -99
  61. package/dist/{config-guard-BJuqQvng.js → config-guard-RbHxYc9j.js} +212 -63
  62. package/dist/{configure-skrLiSwW.js → configure-DLp2Xz7L.js} +59 -40
  63. package/dist/{configure-C-pYuYg_.js → configure-Su1S0gi-.js} +58 -39
  64. package/dist/control-auth-BlWU-jBl.js +54 -0
  65. package/dist/control-auth-C8rIqEdA.js +54 -0
  66. package/dist/{control-service-BDgF-FZ0.js → control-service-BNDthc1N.js} +11 -5
  67. package/dist/{control-service-Djd_WI3_.js → control-service-COF59GQe.js} +10 -4
  68. package/dist/control-ui/assets/{index-CnB9IO4a.js → index-BECn2L1T.js} +369 -368
  69. package/dist/control-ui/assets/index-BECn2L1T.js.map +1 -0
  70. package/dist/control-ui/assets/index-DRPcd1Z4.css +1 -0
  71. package/dist/control-ui/index.html +2 -2
  72. package/dist/{cron-cli-CB6CufAb.js → cron-cli-CSy4-JGS.js} +20 -20
  73. package/dist/{cron-cli-Db6fardJ.js → cron-cli-Db3uCDIT.js} +21 -21
  74. package/dist/{daemon-cli-Xe22v7lZ.js → daemon-cli-BLbzcTuD.js} +61 -22
  75. package/dist/{daemon-cli-BlHK0ly2.js → daemon-cli-DR0D35MO.js} +60 -21
  76. package/dist/{daemon-runtime-CMqH8BUE.js → daemon-runtime-ZWXvLDxx.js} +3 -3
  77. package/dist/{daemon-runtime-DwQFvDXZ.js → daemon-runtime-pVcZ2KDE.js} +3 -3
  78. package/dist/{deliver-CD7-BhYD.js → deliver-BHNoC9Yk.js} +396 -290
  79. package/dist/{deliver-BdGjIcTC.js → deliver-C_5eGQrX.js} +392 -286
  80. package/dist/{deliver-nTKaXF--.js → deliver-DPHZlWgr.js} +392 -287
  81. package/dist/{deliver-CDMGxRoW.js → deliver-geVWJ52I.js} +394 -288
  82. package/dist/{deps-BDQ_K8zf.js → deps-CP0dcOgD.js} +2 -2
  83. package/dist/{deps-D60FbgTP.js → deps-DW5r2IEk.js} +2 -2
  84. package/dist/{devices-cli-N559801X.js → devices-cli-BViqX5pl.js} +15 -15
  85. package/dist/{devices-cli-IxmPLIk8.js → devices-cli-DpYaY-iM.js} +14 -14
  86. package/dist/{directory-cli-Caq-OYk8.js → directory-cli-BWD1DdKf.js} +16 -16
  87. package/dist/{directory-cli-ClrdmQL-.js → directory-cli-BcvZfkfo.js} +17 -17
  88. package/dist/{dispatcher-BfXtm4Dl.js → dispatcher-4Qn951N3.js} +5 -3
  89. package/dist/{dns-cli-DgVO0Pkw.js → dns-cli-_Ych2tu9.js} +12 -12
  90. package/dist/{dns-cli-BTNZkWHs.js → dns-cli-gQCxUXgU.js} +13 -13
  91. package/dist/{docs-cli-9Xan7C6D.js → docs-cli-Bseiau7J.js} +7 -7
  92. package/dist/{docs-cli-DZULc91f.js → docs-cli-DzBTlWQE.js} +8 -8
  93. package/dist/{doctor-D39rZvNH.js → doctor-BNkYYahD.js} +37 -36
  94. package/dist/{doctor-Dq1YeYdH.js → doctor-DzIgdPx1.js} +37 -36
  95. package/dist/entry.js +77 -21
  96. package/dist/{env-B5YXooWp.js → env-BUuSkE19.js} +1 -1
  97. package/dist/{exec-DFOtZbI0.js → exec-BPQSKwGa.js} +5 -3
  98. package/dist/{exec-B8JKbXKW.js → exec-DqZFMawz.js} +5 -3
  99. package/dist/{exec-Bas1hoSJ.js → exec-EKUaAU91.js} +57 -18
  100. package/dist/{exec-CiH_vkWn.js → exec-_PSUrMP8.js} +528 -19
  101. package/dist/{exec-approvals-DGPTjO0N.js → exec-approvals-Bqk-tIxY.js} +134 -51
  102. package/dist/{exec-approvals-C9InMoAB.js → exec-approvals-C67V-ljH.js} +134 -51
  103. package/dist/{exec-approvals-cli-EASbqFd-.js → exec-approvals-cli-D6vfSqQu.js} +22 -22
  104. package/dist/{exec-approvals-cli-DPHItoxG.js → exec-approvals-cli-DAdoki_R.js} +21 -21
  105. package/dist/extensionAPI.js +8518 -9140
  106. package/dist/fetch-Bz1WxfzV.js +285 -0
  107. package/dist/fetch-D2O8s8I1.js +285 -0
  108. package/dist/fetch-Dm-nCwa_.js +285 -0
  109. package/dist/fetch-wuOZDzdT.js +285 -0
  110. package/dist/{gateway-cli-BFqUIif8.js → gateway-cli-C-k7JPlr.js} +1868 -1072
  111. package/dist/{gateway-cli-v4kSPsLE.js → gateway-cli-DIIJ9Z0Y.js} +1870 -1074
  112. package/dist/{gateway-rpc-D6LrkcSA.js → gateway-rpc-D6jLh81b.js} +3 -3
  113. package/dist/{gateway-rpc-dHFK02Kk.js → gateway-rpc-aqysUyf5.js} +3 -3
  114. package/dist/{github-copilot-auth-CQIWc0hC.js → github-copilot-auth-BUqfX7hG.js} +316 -52
  115. package/dist/{github-copilot-auth-D2jfnapd.js → github-copilot-auth-By-nyRb6.js} +316 -52
  116. package/dist/{github-copilot-token-SLWintYd.js → github-copilot-token-C9W4SY9o.js} +7 -4
  117. package/dist/{github-copilot-token-BW-SEg7E.js → github-copilot-token-CiF5Iyi2.js} +6 -3
  118. package/dist/{github-copilot-token-C9IJh2Pn.js → github-copilot-token-DatTe1w-.js} +6 -3
  119. package/dist/{github-copilot-token-wCk9Fg_E.js → github-copilot-token-c9Igt3ZH.js} +6 -3
  120. package/dist/{gmail-setup-utils-CVNgLkXL.js → gmail-setup-utils-HvKMdooP.js} +4 -4
  121. package/dist/{gmail-setup-utils-CAM1vbUS.js → gmail-setup-utils-c-iF00aL.js} +3 -3
  122. package/dist/{health-format-C77hrjEQ.js → health-format-BORnJOeS.js} +106 -44
  123. package/dist/{health-format-DDYtlkB9.js → health-format-Nd0jcoqM.js} +105 -43
  124. package/dist/{help-format-CUnac_bT.js → help-format-Cd5PLwXe.js} +1 -1
  125. package/dist/{help-format-aiW76js8.js → help-format-DYBEvMOX.js} +1 -1
  126. package/dist/{hooks-cli-DsflBRxX.js → hooks-cli-3KdsbdRi.js} +53 -47
  127. package/dist/{hooks-cli-C7kctMuZ.js → hooks-cli-BThja6wK.js} +53 -47
  128. package/dist/{hooks-status-DRAVHSPg.js → hooks-status-BbIz0zmm.js} +6 -5
  129. package/dist/{hooks-status-lHWrY64E.js → hooks-status-DPJORMB6.js} +6 -5
  130. package/dist/{image--gbzucyh.js → image-BaJKrmCs.js} +12 -8
  131. package/dist/{image-ORs4LLwg.js → image-D-5pUELC.js} +13 -9
  132. package/dist/{image-DMnjYGdA.js → image-TvL5YI_W.js} +13 -9
  133. package/dist/{image-BVNytEIn.js → image-bodq5cUH.js} +13 -9
  134. package/dist/index.js +261 -109
  135. package/dist/{installs-CXGV291R.js → installs-BrOMqREO.js} +7 -6
  136. package/dist/{installs-89zeUsVn.js → installs-z69au9Te.js} +7 -6
  137. package/dist/{links-Dg90NTyF.js → links-AVB88xxH.js} +1 -1
  138. package/dist/{links-7M-j83As.js → links-DpxpaKe1.js} +1 -1
  139. package/dist/llm-slug-generator.js +18 -19
  140. package/dist/{loader-BnzQyT31.js → loader-CS-5lMQa.js} +3694 -4531
  141. package/dist/{logging-DuK6YXuK.js → logging-B3KnAryz.js} +2 -2
  142. package/dist/{logging-CNq0UUgf.js → logging-DEPo2hji.js} +1 -1
  143. package/dist/{login-qr-CJ__cE3-.js → login-qr--28WL1TN.js} +11 -5
  144. package/dist/{login-qr-BVeOFfNW.js → login-qr-4o2aC2UE.js} +9 -4
  145. package/dist/{login-qr-BJChByHH.js → login-qr-BUdeu1Sl.js} +8 -2
  146. package/dist/{login-qr-KUOtNJaQ.js → login-qr-BsYM2E1y.js} +12 -6
  147. package/dist/{logs-cli-Cm7AiarR.js → logs-cli-DDMD5w5_.js} +38 -22
  148. package/dist/{logs-cli-BWmtAsjp.js → logs-cli-DvPoVKCN.js} +38 -22
  149. package/dist/{manager-C-jXr9ks.js → manager-CXo1uqmO.js} +102 -86
  150. package/dist/{manager-CMFBuvVd.js → manager-ChW0jk7T.js} +101 -85
  151. package/dist/{manager-D2Ndphg3.js → manager-DUOe7ud6.js} +100 -85
  152. package/dist/{manager-BsdlwsL5.js → manager-PoxUqdN_.js} +98 -82
  153. package/dist/{manifest-registry-D5SiA3xq.js → manifest-registry-CVsqjgX0.js} +40 -2
  154. package/dist/{manifest-registry-DyMRD3rY.js → manifest-registry-jeAPx6AW.js} +40 -2
  155. package/dist/{message-channel-CHRYQtAM.js → message-channel-CTtrEkmW.js} +1 -1
  156. package/dist/{message-channel-BlgPSDAh.js → message-channel-DWcu72r7.js} +1 -1
  157. package/dist/{model-auth-BqjMkNFs.js → model-auth-BvODRbV0.js} +362 -35
  158. package/dist/{model-selection-DbsbOAoh.js → model-selection-B53OvWCf.js} +353 -33
  159. package/dist/{model-selection-DlV6wnTr.js → model-selection-vC82fEiP.js} +331 -30
  160. package/dist/{models-cli-DIFBrK4W.js → models-cli-DqsKsOgd.js} +66 -55
  161. package/dist/{models-cli-0XhQQbMW.js → models-cli-NV0bnh8l.js} +66 -55
  162. package/dist/{node-cli-BMUfVCSq.js → node-cli-C7YleuBk.js} +54 -44
  163. package/dist/{node-cli-DY4lzhDA.js → node-cli-CxwoHnZ6.js} +54 -44
  164. package/dist/{node-service-DQ-tiSie.js → node-service-C7f_uvx9.js} +2 -2
  165. package/dist/{node-service-u8g85nD3.js → node-service-De_WkxJe.js} +2 -2
  166. package/dist/{nodes-cli-BX6oWnLC.js → nodes-cli-BxrMVI9V.js} +25 -23
  167. package/dist/{nodes-cli-CVHzcQo2.js → nodes-cli-Clb0ocwB.js} +24 -22
  168. package/dist/{nodes-screen-DGlNPbk4.js → nodes-screen-CVL9363A.js} +48 -6
  169. package/dist/{nodes-screen-lykd2cny.js → nodes-screen-DsHJIN2I.js} +47 -5
  170. package/dist/{note-Ci08TSbV.js → note-Duiadw1g.js} +1 -1
  171. package/dist/{note-DVO1KLaW.js → note-uC6iDp4y.js} +2 -2
  172. package/dist/{onboard-channels-DTkFFbzS.js → onboard-channels-C5Iaafwb.js} +10 -10
  173. package/dist/{onboard-channels-CtDnwaF5.js → onboard-channels-C5uL3i8d.js} +11 -11
  174. package/dist/{onboard-skills-BnAcpzfX.js → onboard-skills-BFxdI1Y1.js} +1143 -112
  175. package/dist/{onboard-skills-DuoDzEmI.js → onboard-skills-DUG8Y0se.js} +1142 -111
  176. package/dist/{onboarding-DvhiiHh0.js → onboarding-ClzElK4D.js} +56 -48
  177. package/dist/{openclaw-root-93W6UrUK.js → openclaw-root-BKsZvO6K.js} +6 -2
  178. package/dist/{openclaw-root-9ILYSmJ9.js → openclaw-root-CEnmuBUN.js} +6 -2
  179. package/dist/{pairing-cli-BKJHBxwT.js → pairing-cli-BWWFZF7Q.js} +16 -16
  180. package/dist/{pairing-cli-DJHjPBwu.js → pairing-cli-BrFLxnug.js} +16 -16
  181. package/dist/{pairing-labels-xImhiJax.js → pairing-labels-C8KULWNH.js} +1 -1
  182. package/dist/{pairing-labels-CHxlh3tT.js → pairing-labels-Dt2vXyI7.js} +1 -1
  183. package/dist/{pairing-store-CO6umWFP.js → pairing-store-Dz-ArTQS.js} +3 -3
  184. package/dist/{pairing-store-BpPUNzmB.js → pairing-store-gQdv7Ruh.js} +2 -2
  185. package/dist/{path-env-Nq83EHH9.js → path-env-BRKerjt1.js} +2 -2
  186. package/dist/{path-env-CXWUFfFv.js → path-env-OJAyUeWW.js} +1 -1
  187. package/dist/paths-BZK4Ct0I.js +81 -0
  188. package/dist/paths-DWYi0R_2.js +78 -0
  189. package/dist/{paths-Bkhd_qY8.js → paths-DdKf4lHp.js} +35 -5
  190. package/dist/paths-SFzVNGbc.js +78 -0
  191. package/dist/pi-auth-json-D7hGObyW.js +12 -0
  192. package/dist/pi-auth-json-DgvHjfJy.js +8 -0
  193. package/dist/pi-auth-json-la6lnAzY.js +79 -0
  194. package/dist/pi-auth-json-p3vsMR7W.js +79 -0
  195. package/dist/{pi-embedded-C1qKCgDT.js → pi-embedded-De6SeAPs.js} +9518 -9968
  196. package/dist/{pi-embedded-helpers-DtPn5RC8.js → pi-embedded-helpers-BrUBxrE2.js} +70 -10
  197. package/dist/{pi-embedded-helpers-DhEkdWB1.js → pi-embedded-helpers-D0mqOwwq.js} +821 -128
  198. package/dist/{pi-embedded-helpers-7AjuNiiJ.js → pi-embedded-helpers-DpJb0kUk.js} +69 -9
  199. package/dist/{pi-embedded-helpers-BTkXgwJ7.js → pi-embedded-helpers-ZI1UCSRM.js} +927 -136
  200. package/dist/{pi-tools.policy-gG96mWwA.js → pi-tools.policy-z5Wd_2WN.js} +4 -4
  201. package/dist/{plugin-auto-enable-D5ye7QnB.js → plugin-auto-enable-B8mX3rX3.js} +14 -5
  202. package/dist/{plugin-auto-enable-BROgMZcf.js → plugin-auto-enable-OO0eDINB.js} +14 -5
  203. package/dist/plugin-sdk/agents/apply-patch-update.d.ts +3 -1
  204. package/dist/plugin-sdk/agents/apply-patch.d.ts +11 -3
  205. package/dist/plugin-sdk/agents/auth-profiles/profiles.d.ts +5 -0
  206. package/dist/plugin-sdk/agents/auth-profiles.d.ts +1 -1
  207. package/dist/plugin-sdk/agents/bash-process-registry.d.ts +1 -0
  208. package/dist/plugin-sdk/agents/bash-tools.exec.d.ts +26 -0
  209. package/dist/plugin-sdk/agents/current-time.d.ts +17 -0
  210. package/dist/plugin-sdk/agents/huggingface-models.d.ts +17 -0
  211. package/dist/plugin-sdk/agents/models-config.providers.d.ts +10 -0
  212. package/dist/plugin-sdk/agents/openclaw-tools.d.ts +2 -0
  213. package/dist/plugin-sdk/agents/pi-auth-json.d.ts +14 -0
  214. package/dist/plugin-sdk/agents/pi-embedded-helpers/errors.d.ts +5 -1
  215. package/dist/plugin-sdk/agents/pi-embedded-helpers.d.ts +1 -1
  216. package/dist/plugin-sdk/agents/pi-embedded-runner/google.d.ts +1 -0
  217. package/dist/plugin-sdk/agents/pi-embedded-runner/run/images.d.ts +9 -4
  218. package/dist/plugin-sdk/agents/pi-embedded-runner/run/params.d.ts +2 -0
  219. package/dist/plugin-sdk/agents/pi-embedded-runner/run/payloads.d.ts +1 -0
  220. package/dist/plugin-sdk/agents/pi-embedded-runner/run/types.d.ts +2 -0
  221. package/dist/plugin-sdk/agents/pi-embedded-runner/types.d.ts +15 -0
  222. package/dist/plugin-sdk/agents/pi-embedded-subscribe.handlers.tools.d.ts +1 -1
  223. package/dist/plugin-sdk/agents/pi-embedded-subscribe.handlers.types.d.ts +2 -0
  224. package/dist/plugin-sdk/agents/pi-embedded-subscribe.types.d.ts +2 -0
  225. package/dist/plugin-sdk/agents/pi-tools.read.d.ts +8 -3
  226. package/dist/plugin-sdk/agents/sandbox/constants.d.ts +1 -1
  227. package/dist/plugin-sdk/agents/sandbox/docker.d.ts +14 -3
  228. package/dist/plugin-sdk/agents/sandbox/fs-bridge.d.ts +56 -0
  229. package/dist/plugin-sdk/agents/sandbox/types.d.ts +2 -0
  230. package/dist/plugin-sdk/agents/session-tool-result-guard-wrapper.d.ts +2 -0
  231. package/dist/plugin-sdk/agents/session-tool-result-guard.d.ts +4 -0
  232. package/dist/plugin-sdk/agents/subagent-registry.d.ts +3 -1
  233. package/dist/plugin-sdk/agents/tools/agent-step.d.ts +3 -0
  234. package/dist/plugin-sdk/agents/tools/browser-tool.schema.d.ts +2 -2
  235. package/dist/plugin-sdk/agents/tools/common.d.ts +4 -0
  236. package/dist/plugin-sdk/agents/tools/image-tool.d.ts +9 -1
  237. package/dist/plugin-sdk/agents/tools/web-search.d.ts +10 -1
  238. package/dist/plugin-sdk/agents/usage.d.ts +1 -0
  239. package/dist/plugin-sdk/auto-reply/reply/commands-status.d.ts +1 -0
  240. package/dist/plugin-sdk/auto-reply/reply/get-reply-directives.d.ts +1 -0
  241. package/dist/plugin-sdk/auto-reply/reply/memory-flush.d.ts +2 -2
  242. package/dist/plugin-sdk/auto-reply/reply/mentions.d.ts +1 -0
  243. package/dist/plugin-sdk/auto-reply/reply/model-selection.d.ts +3 -0
  244. package/dist/plugin-sdk/auto-reply/reply/reply-reference.d.ts +1 -1
  245. package/dist/plugin-sdk/auto-reply/reply/session-run-accounting.d.ts +11 -0
  246. package/dist/plugin-sdk/auto-reply/reply/session-usage.d.ts +8 -0
  247. package/dist/plugin-sdk/auto-reply/status.d.ts +2 -0
  248. package/dist/plugin-sdk/auto-reply/templating.d.ts +3 -0
  249. package/dist/plugin-sdk/auto-reply/thinking.d.ts +1 -1
  250. package/dist/plugin-sdk/auto-reply/types.d.ts +2 -0
  251. package/dist/plugin-sdk/browser/cdp.helpers.d.ts +2 -1
  252. package/dist/plugin-sdk/browser/client-actions-core.d.ts +1 -0
  253. package/dist/plugin-sdk/browser/control-auth.d.ts +13 -0
  254. package/dist/plugin-sdk/browser/pw-ai.d.ts +1 -1
  255. package/dist/plugin-sdk/browser/pw-session.d.ts +25 -0
  256. package/dist/plugin-sdk/browser/pw-tools-core.interactions.d.ts +2 -0
  257. package/dist/plugin-sdk/browser/routes/dispatcher.d.ts +1 -0
  258. package/dist/plugin-sdk/browser/routes/types.d.ts +5 -0
  259. package/dist/plugin-sdk/channels/plugins/onboarding/signal.d.ts +1 -0
  260. package/dist/plugin-sdk/channels/registry.d.ts +2 -2
  261. package/dist/plugin-sdk/cli/nodes-camera.d.ts +8 -2
  262. package/dist/plugin-sdk/cli/prompt.d.ts +1 -0
  263. package/dist/plugin-sdk/commands/agent/types.d.ts +2 -0
  264. package/dist/plugin-sdk/commands/onboard-helpers.d.ts +1 -0
  265. package/dist/plugin-sdk/commands/onboard-types.d.ts +9 -1
  266. package/dist/plugin-sdk/commands/signal-install.d.ts +20 -0
  267. package/dist/plugin-sdk/config/config.d.ts +1 -1
  268. package/dist/plugin-sdk/config/group-policy.d.ts +3 -0
  269. package/dist/plugin-sdk/config/merge-patch.d.ts +1 -0
  270. package/dist/plugin-sdk/config/sessions/paths.d.ts +14 -4
  271. package/dist/plugin-sdk/config/sessions/store.d.ts +8 -0
  272. package/dist/plugin-sdk/config/sessions/types.d.ts +8 -0
  273. package/dist/plugin-sdk/config/types.agents.d.ts +2 -0
  274. package/dist/plugin-sdk/config/types.channels.d.ts +2 -0
  275. package/dist/plugin-sdk/config/types.d.ts +1 -0
  276. package/dist/plugin-sdk/config/types.discord.d.ts +5 -0
  277. package/dist/plugin-sdk/config/types.gateway.d.ts +35 -0
  278. package/dist/plugin-sdk/config/types.hooks.d.ts +23 -1
  279. package/dist/plugin-sdk/config/types.irc.d.ts +96 -0
  280. package/dist/plugin-sdk/config/types.memory.d.ts +2 -0
  281. package/dist/plugin-sdk/config/types.openclaw.d.ts +6 -0
  282. package/dist/plugin-sdk/config/types.queue.d.ts +1 -0
  283. package/dist/plugin-sdk/config/types.slack.d.ts +2 -0
  284. package/dist/plugin-sdk/config/types.telegram.d.ts +2 -0
  285. package/dist/plugin-sdk/config/validation.d.ts +20 -0
  286. package/dist/plugin-sdk/config/zod-schema.agents.d.ts +1 -0
  287. package/dist/plugin-sdk/config/zod-schema.core.d.ts +2 -0
  288. package/dist/plugin-sdk/config/zod-schema.d.ts +193 -2
  289. package/dist/plugin-sdk/config/zod-schema.hooks.d.ts +3 -2
  290. package/dist/plugin-sdk/config/zod-schema.providers-core.d.ts +378 -0
  291. package/dist/plugin-sdk/config/zod-schema.providers.d.ts +176 -0
  292. package/dist/plugin-sdk/config/zod-schema.sensitive.d.ts +2 -0
  293. package/dist/plugin-sdk/config/zod-schema.session.d.ts +1 -0
  294. package/dist/plugin-sdk/cron/service/jobs.d.ts +8 -0
  295. package/dist/plugin-sdk/cron/service/state.d.ts +1 -0
  296. package/dist/plugin-sdk/cron/types.d.ts +2 -0
  297. package/dist/plugin-sdk/discord/monitor/allow-list.d.ts +15 -0
  298. package/dist/plugin-sdk/discord/send.types.d.ts +5 -0
  299. package/dist/plugin-sdk/gateway/auth-rate-limit.d.ts +59 -0
  300. package/dist/plugin-sdk/gateway/auth.d.ts +47 -0
  301. package/dist/plugin-sdk/gateway/net.d.ts +5 -0
  302. package/dist/plugin-sdk/gateway/protocol/index.d.ts +7 -7
  303. package/dist/plugin-sdk/gateway/protocol/schema/agent.d.ts +7 -1
  304. package/dist/plugin-sdk/gateway/protocol/schema/channels.d.ts +21 -0
  305. package/dist/plugin-sdk/gateway/protocol/schema/types.d.ts +3 -1
  306. package/dist/plugin-sdk/gateway/session-utils.fs.d.ts +3 -1
  307. package/dist/plugin-sdk/gateway/session-utils.types.d.ts +1 -0
  308. package/dist/plugin-sdk/imessage/send.d.ts +12 -0
  309. package/dist/plugin-sdk/index.js +2147 -900
  310. package/dist/plugin-sdk/infra/binaries.d.ts +3 -0
  311. package/dist/plugin-sdk/infra/brew.d.ts +8 -0
  312. package/dist/plugin-sdk/infra/heartbeat-active-hours.d.ts +5 -0
  313. package/dist/plugin-sdk/infra/heartbeat-runner.d.ts +1 -0
  314. package/dist/plugin-sdk/infra/heartbeat-wake.d.ts +8 -1
  315. package/dist/plugin-sdk/infra/net/fetch-guard.d.ts +1 -0
  316. package/dist/plugin-sdk/infra/net/ssrf.d.ts +1 -0
  317. package/dist/plugin-sdk/infra/outbound/message.d.ts +2 -0
  318. package/dist/plugin-sdk/infra/outbound/outbound-send-service.d.ts +2 -0
  319. package/dist/plugin-sdk/infra/session-cost-usage.d.ts +3 -0
  320. package/dist/plugin-sdk/infra/tailscale.d.ts +34 -0
  321. package/dist/plugin-sdk/infra/tmp-openclaw-dir.d.ts +10 -0
  322. package/dist/plugin-sdk/logging/console.d.ts +4 -0
  323. package/dist/plugin-sdk/logging/logger.d.ts +1 -1
  324. package/dist/plugin-sdk/logging/state.d.ts +1 -0
  325. package/dist/plugin-sdk/logging.d.ts +2 -2
  326. package/dist/plugin-sdk/markdown/ir.d.ts +1 -1
  327. package/dist/plugin-sdk/markdown/whatsapp.d.ts +14 -0
  328. package/dist/plugin-sdk/media/input-files.d.ts +5 -0
  329. package/dist/plugin-sdk/media/store.d.ts +10 -0
  330. package/dist/plugin-sdk/media-understanding/audio-preflight.d.ts +16 -0
  331. package/dist/plugin-sdk/media-understanding/types.d.ts +1 -0
  332. package/dist/plugin-sdk/memory/backend-config.d.ts +2 -1
  333. package/dist/plugin-sdk/memory/embedding-chunk-limits.d.ts +3 -0
  334. package/dist/plugin-sdk/memory/embedding-input-limits.d.ts +2 -0
  335. package/dist/plugin-sdk/memory/embedding-model-limits.d.ts +2 -0
  336. package/dist/plugin-sdk/memory/embeddings.d.ts +1 -0
  337. package/dist/plugin-sdk/memory/internal.d.ts +11 -0
  338. package/dist/plugin-sdk/memory/manager.d.ts +0 -6
  339. package/dist/plugin-sdk/memory/qmd-manager.d.ts +2 -0
  340. package/dist/plugin-sdk/memory/qmd-query-parser.d.ts +8 -0
  341. package/dist/plugin-sdk/memory/session-files.d.ts +2 -0
  342. package/dist/plugin-sdk/process/command-queue.d.ts +16 -0
  343. package/dist/plugin-sdk/providers/github-copilot-token.d.ts +3 -0
  344. package/dist/plugin-sdk/routing/resolve-route.d.ts +3 -1
  345. package/dist/plugin-sdk/security/external-content.d.ts +1 -1
  346. package/dist/plugin-sdk/security/secret-equal.d.ts +1 -0
  347. package/dist/plugin-sdk/sessions/input-provenance.d.ts +16 -0
  348. package/dist/plugin-sdk/signal/monitor/event-handler.types.d.ts +8 -0
  349. package/dist/plugin-sdk/signal/monitor/mentions.d.ts +2 -0
  350. package/dist/plugin-sdk/slack/monitor/commands.d.ts +5 -0
  351. package/dist/plugin-sdk/slack/monitor/media.d.ts +21 -0
  352. package/dist/plugin-sdk/slack/types.d.ts +1 -0
  353. package/dist/plugin-sdk/telegram/bot-message-context.d.ts +2 -1
  354. package/dist/plugin-sdk/telegram/fetch.d.ts +1 -0
  355. package/dist/plugin-sdk/telegram/monitor.d.ts +1 -0
  356. package/dist/plugin-sdk/telegram/send.d.ts +3 -0
  357. package/dist/plugin-sdk/tts/tts.d.ts +2 -2
  358. package/dist/plugin-sdk/utils/fetch-timeout.d.ts +2 -0
  359. package/dist/plugin-sdk/web/media.d.ts +12 -2
  360. package/dist/{plugins-CQw3z3Nw.js → plugins-CTjLu-z-.js} +4 -4
  361. package/dist/{plugins-B7F0Ly9G.js → plugins-CxrdL_IZ.js} +3 -3
  362. package/dist/{plugins-cli-CJ74eHvr.js → plugins-cli-CbX97Kvt.js} +259 -49
  363. package/dist/{plugins-cli-ubDwUAzK.js → plugins-cli-Dn9OeO53.js} +257 -47
  364. package/dist/{ports-kYsTYQdA.js → ports-C8YYHVlc.js} +2 -2
  365. package/dist/{program-1bQ15ivo.js → program-D-mNC0It.js} +86 -83
  366. package/dist/{progress-Da1ehW-x.js → progress-COHv-uNT.js} +1 -1
  367. package/dist/{progress-COzt9PNY.js → progress-DZb6yPcJ.js} +1 -1
  368. package/dist/{prompt-style-Dc0C5HC9.js → prompt-style-Cf1r1L6k.js} +1 -1
  369. package/dist/{prompt-style-DjZDxcFg.js → prompt-style-lSlXMhsd.js} +1 -1
  370. package/dist/{pw-ai-CQ4-gUNR.js → pw-ai-6GzTgK5g.js} +205 -32
  371. package/dist/{pw-ai-1NN0FrJb.js → pw-ai-C8YhJRaI.js} +207 -32
  372. package/dist/{pw-ai-qEMUq5Mt.js → pw-ai-CKGenizV.js} +203 -29
  373. package/dist/{pw-ai-IOqEXO1O.js → pw-ai-D7devT89.js} +206 -32
  374. package/dist/{qmd-manager-CEwp3el1.js → qmd-manager-CQzWovq-.js} +71 -90
  375. package/dist/{qmd-manager-D6N3qvQ5.js → qmd-manager-Cs8RJVQp.js} +73 -90
  376. package/dist/{qmd-manager-C48QzrRe.js → qmd-manager-DdgrQ2kc.js} +71 -88
  377. package/dist/{qmd-manager-DaUqCKB_.js → qmd-manager-dyIoOvKl.js} +73 -90
  378. package/dist/{register.subclis-Cm-VJ5nP.js → register.subclis-ifHtmF3e.js} +29 -29
  379. package/dist/{reply-CBs4e9Rm.js → reply-VIHqsQ-k.js} +7906 -8743
  380. package/dist/{routes-9ygR0GOk.js → routes-CaCvio4Q.js} +36 -15
  381. package/dist/{routes-BrWrBk2R.js → routes-Cpfxk96k.js} +36 -14
  382. package/dist/{rpc-Cjuz2Gv1.js → rpc-BhB01Bhj.js} +3 -3
  383. package/dist/{rpc-DhkLVY5H.js → rpc-C5WsS_Ne.js} +3 -3
  384. package/dist/{run-main-BlZ5l-X9.js → run-main-DVy6KJTe.js} +88 -85
  385. package/dist/runner-B7CKBC80.js +1800 -0
  386. package/dist/runner-BEy5ZGFv.js +1901 -0
  387. package/dist/runner-Bv0BmJPF.js +1800 -0
  388. package/dist/runner-ChqVEgPx.js +1901 -0
  389. package/dist/{sandbox-qt49csTr.js → sandbox-BAChxjC5.js} +627 -157
  390. package/dist/{sandbox-CPZiaKcS.js → sandbox-DNHDwHw8.js} +628 -158
  391. package/dist/{sandbox-cli-C6_iNuqO.js → sandbox-cli-9oq67QEg.js} +22 -22
  392. package/dist/{sandbox-cli-C_wK-KAE.js → sandbox-cli-BiNq9yUe.js} +22 -22
  393. package/dist/{security-cli-CTTD1vms.js → security-cli-CRg03hvq.js} +28 -28
  394. package/dist/{security-cli-DRpGF2Yc.js → security-cli-LmBBHnmh.js} +28 -28
  395. package/dist/{server-context-lyNcqJYD.js → server-context-FwqBRH3K.js} +10 -10
  396. package/dist/{server-context-39mkstUs.js → server-context-RY7lRaxl.js} +9 -9
  397. package/dist/{server-node-events-V_G9BRRw.js → server-node-events-BbHOZX3O.js} +48 -43
  398. package/dist/{server-node-events-o9G18PaE.js → server-node-events-CngNLVL-.js} +50 -45
  399. package/dist/{service-DOlJdIqe.js → service-BnqdBTAK.js} +8 -4
  400. package/dist/{service-DDPRbf8a.js → service-DZN7KRok.js} +8 -4
  401. package/dist/{service-audit-VDRrWefh.js → service-audit-0Eil3ISN.js} +4 -4
  402. package/dist/{service-audit-CVy00Ze_.js → service-audit-B8KIOe8A.js} +4 -4
  403. package/dist/{session-cost-usage-CcCEQNuc.js → session-cost-usage-B-tyjp76.js} +14 -14
  404. package/dist/{session-cost-usage-PvyVZz-g.js → session-cost-usage-BYUb7fov.js} +14 -14
  405. package/dist/{shared-BnpC3wMU.js → shared-BCdNboU1.js} +3 -3
  406. package/dist/{shared-CagUDdmp.js → shared-CsAwU6-q.js} +3 -3
  407. package/dist/{shared-BDk_zC9p.js → shared-Csn6DLBA.js} +5 -5
  408. package/dist/{shared-C92wo-6f.js → shared-DEanAgja.js} +4 -4
  409. package/dist/{skill-scanner-C_fQzVDu.js → skill-scanner-BrGkh5K7.js} +1 -1
  410. package/dist/{skill-scanner-DrVEHfC6.js → skill-scanner-CucvxYhu.js} +1 -1
  411. package/dist/{skills-Ccsv3IQq.js → skills-CE7by2IF.js} +151 -8
  412. package/dist/{skills-_eKGrw9z.js → skills-Dz15dAM4.js} +152 -9
  413. package/dist/{skills-cli-DqvLjooh.js → skills-cli-B5b75pDK.js} +13 -13
  414. package/dist/{skills-cli-DUncybht.js → skills-cli-CbCDrYwp.js} +13 -13
  415. package/dist/{skills-status-Cp2ZFhIx.js → skills-status-B99Us6yS.js} +2 -2
  416. package/dist/{skills-status-Ck0CCFZG.js → skills-status-ChM7JE47.js} +3 -3
  417. package/dist/{sqlite-DODNHWJb.js → sqlite-2UsPaJz5.js} +97 -2
  418. package/dist/{sqlite-cSdsHVEw.js → sqlite-CASnHrgX.js} +97 -1
  419. package/dist/{sqlite-Bwo2rASR.js → sqlite-CVWiMkGu.js} +97 -1
  420. package/dist/{sqlite-CpqIbY4-.js → sqlite-CcIWkGaM.js} +97 -1
  421. package/dist/{status-Bmx9_1C7.js → status-CKuX1-zb.js} +3 -3
  422. package/dist/{status-CBGgwlTW.js → status-Cm4q6o-I.js} +57 -49
  423. package/dist/{status-DkJgtvSz.js → status-DD2iqGc9.js} +4 -4
  424. package/dist/{subsystem-DPnkvS73.js → subsystem-DHfJG4gk.js} +73 -20
  425. package/dist/{system-cli-9fQ1uLiz.js → system-cli-BVJDR474.js} +87 -15
  426. package/dist/{system-cli-Gq8OWHFg.js → system-cli-C3Y_9VpI.js} +88 -16
  427. package/dist/{systemd-Pa7LURHB.js → systemd-DxddcFsa.js} +3 -3
  428. package/dist/{systemd-hints-zi4ohCOY.js → systemd-hints-BVLopJ9O.js} +1 -1
  429. package/dist/{systemd-linger-CDo2UbHM.js → systemd-linger-BThjV1Sr.js} +2 -2
  430. package/dist/{systemd-linger-6_naJcJp.js → systemd-linger-D3Va1Cv7.js} +2 -2
  431. package/dist/{systemd-BEWwfwn0.js → systemd-s3S2HVog.js} +3 -3
  432. package/dist/{table-Bb9gAVIp.js → table-BIk8Aan_.js} +2 -2
  433. package/dist/{table-cCoGqLsk.js → table-Bvka_vkc.js} +1 -1
  434. package/dist/{tool-display-DUVhO36P.js → tool-display-DbdMQFZx.js} +2 -2
  435. package/dist/{tool-display-DNOVCI6J.js → tool-display-kpW5Hg2z.js} +2 -2
  436. package/dist/{tui-DDVqLwqT.js → tui-B40Z2jMa.js} +120 -14
  437. package/dist/{tui-cli-CurbazQf.js → tui-cli-Bwa6K7xR.js} +28 -28
  438. package/dist/{tui-cli-BeN2K38I.js → tui-cli-DD6g7uZb.js} +27 -27
  439. package/dist/{tui-B9zLJxf6.js → tui-lFMZUnx6.js} +121 -13
  440. package/dist/{update-Ct9sqJC_.js → update-Bos8PPCG.js} +3 -3
  441. package/dist/{update--i077azM.js → update-Cg8MtrEr.js} +3 -3
  442. package/dist/{update-cli-CT5W0kpw.js → update-cli-CC-wTeje.js} +92 -73
  443. package/dist/{update-cli-C87lNK1S.js → update-cli-CULnXFL_.js} +91 -72
  444. package/dist/{update-runner-BIttRDyV.js → update-runner-BaLsla0c.js} +11 -11
  445. package/dist/{update-runner-xbeVkAD9.js → update-runner-Dbsdl5AU.js} +10 -10
  446. package/dist/{utils-Dk86IbEs.js → utils-BLJAc3ZV.js} +1 -1
  447. package/dist/{utils-BTaR--Ln.js → utils-BtIMES3N.js} +1 -1
  448. package/dist/{webhooks-cli-Db3zyJaw.js → webhooks-cli-ClHLUu_j.js} +21 -13
  449. package/dist/{webhooks-cli-DUUa8gVY.js → webhooks-cli-DVXr2uyN.js} +21 -13
  450. package/dist/{widearea-dns-BgYasW6m.js → widearea-dns-C4RnIR9O.js} +3 -3
  451. package/dist/{widearea-dns-CMIG6-74.js → widearea-dns-Ypwgjpsr.js} +3 -3
  452. package/dist/{ws-C0k_dhCP.js → ws-BcJt4pcg.js} +24 -2
  453. package/dist/{ws-DtDKpbLR.js → ws-MC-rTJLe.js} +24 -2
  454. package/dist/{ws-log-cMNgAyLy.js → ws-log-WrJ4QYu7.js} +1 -1
  455. package/dist/{ws-log-C6vm_XMA.js → ws-log-lip4ETlm.js} +2 -2
  456. package/dist/{wsl-rfIr_Sde.js → wsl-BvTIzy-8.js} +5 -3
  457. package/docs/assets/install-script.svg +1 -0
  458. package/docs/automation/hooks.md +1 -38
  459. package/docs/automation/webhook.md +52 -2
  460. package/docs/channels/discord.md +389 -381
  461. package/docs/channels/grammy.md +1 -1
  462. package/docs/channels/imessage.md +229 -218
  463. package/docs/channels/index.md +1 -0
  464. package/docs/channels/irc.md +234 -0
  465. package/docs/channels/msteams.md +2 -0
  466. package/docs/channels/pairing.md +1 -1
  467. package/docs/channels/slack.md +295 -415
  468. package/docs/channels/telegram.md +397 -460
  469. package/docs/channels/whatsapp.md +338 -310
  470. package/docs/ci.md +0 -12
  471. package/docs/cli/hooks.md +1 -14
  472. package/docs/cli/index.md +6 -1
  473. package/docs/cli/logs.md +4 -0
  474. package/docs/cli/onboard.md +33 -0
  475. package/docs/cli/plugins.md +20 -1
  476. package/docs/cli/security.md +2 -0
  477. package/docs/concepts/architecture.md +0 -16
  478. package/docs/concepts/memory.md +7 -4
  479. package/docs/concepts/model-providers.md +27 -0
  480. package/docs/concepts/session-tool.md +1 -0
  481. package/docs/concepts/system-prompt.md +13 -0
  482. package/docs/docs.json +18 -12
  483. package/docs/experiments/plans/browser-evaluate-cdp-refactor.md +229 -0
  484. package/docs/gateway/configuration-examples.md +9 -2
  485. package/docs/gateway/configuration-reference.md +2345 -0
  486. package/docs/gateway/configuration.md +338 -3297
  487. package/docs/gateway/index.md +162 -238
  488. package/docs/gateway/openai-http-api.md +1 -0
  489. package/docs/gateway/openresponses-http-api.md +16 -0
  490. package/docs/gateway/remote-gateway-readme.md +0 -16
  491. package/docs/gateway/security/index.md +4 -16
  492. package/docs/gateway/tools-invoke-http-api.md +26 -1
  493. package/docs/help/faq.md +9 -0
  494. package/docs/help/testing.md +11 -0
  495. package/docs/install/docker.md +18 -0
  496. package/docs/install/hetzner.md +21 -0
  497. package/docs/install/installer.md +20 -0
  498. package/docs/nodes/audio.md +19 -0
  499. package/docs/platforms/mac/release.md +7 -7
  500. package/docs/providers/glm.md +3 -3
  501. package/docs/providers/huggingface.md +209 -0
  502. package/docs/providers/index.md +3 -0
  503. package/docs/providers/litellm.md +153 -0
  504. package/docs/providers/together.md +2 -2
  505. package/docs/providers/vllm.md +92 -0
  506. package/docs/providers/zai.md +2 -2
  507. package/docs/reference/credits.md +4 -28
  508. package/docs/reference/test.md +2 -1
  509. package/docs/reference/token-use.md +1 -1
  510. package/docs/reference/transcript-hygiene.md +18 -0
  511. package/docs/start/getting-started.md +5 -0
  512. package/docs/start/onboarding-overview.md +51 -0
  513. package/docs/start/onboarding.md +1 -0
  514. package/docs/start/openclaw.md +0 -16
  515. package/docs/start/wizard-cli-automation.md +17 -0
  516. package/docs/start/wizard-cli-reference.md +12 -0
  517. package/docs/start/wizard.md +3 -1
  518. package/docs/tools/browser.md +6 -0
  519. package/docs/zh-CN/automation/hooks.md +1 -38
  520. package/docs/zh-CN/cli/hooks.md +1 -14
  521. package/extensions/bluebubbles/package.json +1 -1
  522. package/extensions/bluebubbles/src/monitor.test.ts +40 -28
  523. package/extensions/bluebubbles/src/monitor.ts +0 -4
  524. package/extensions/copilot-proxy/package.json +1 -1
  525. package/extensions/diagnostics-otel/package.json +10 -10
  526. package/extensions/discord/package.json +1 -1
  527. package/extensions/feishu/package.json +2 -5
  528. package/extensions/feishu/src/bot.checkBotMentioned.test.ts +64 -0
  529. package/extensions/feishu/src/bot.test.ts +265 -0
  530. package/extensions/feishu/src/bot.ts +73 -18
  531. package/extensions/feishu/src/channel.test.ts +48 -0
  532. package/extensions/feishu/src/channel.ts +1 -3
  533. package/extensions/feishu/src/config-schema.ts +6 -0
  534. package/extensions/feishu/src/docx.ts +14 -4
  535. package/extensions/feishu/src/media.test.ts +151 -0
  536. package/extensions/feishu/src/media.ts +27 -13
  537. package/extensions/feishu/src/reply-dispatcher.test.ts +116 -0
  538. package/extensions/feishu/src/reply-dispatcher.ts +124 -67
  539. package/extensions/feishu/src/streaming-card.ts +223 -0
  540. package/extensions/feishu/src/targets.test.ts +16 -0
  541. package/extensions/feishu/src/targets.ts +1 -1
  542. package/extensions/google-antigravity-auth/package.json +1 -1
  543. package/extensions/google-gemini-cli-auth/oauth.test.ts +4 -1
  544. package/extensions/google-gemini-cli-auth/package.json +1 -1
  545. package/extensions/googlechat/package.json +1 -1
  546. package/extensions/googlechat/src/channel.ts +3 -20
  547. package/extensions/googlechat/src/resolve-target.test.ts +138 -0
  548. package/extensions/imessage/package.json +1 -1
  549. package/extensions/irc/index.ts +17 -0
  550. package/extensions/irc/openclaw.plugin.json +9 -0
  551. package/extensions/irc/package.json +14 -0
  552. package/extensions/irc/src/accounts.ts +268 -0
  553. package/extensions/irc/src/channel.ts +367 -0
  554. package/extensions/irc/src/client.test.ts +43 -0
  555. package/extensions/irc/src/client.ts +439 -0
  556. package/extensions/irc/src/config-schema.test.ts +27 -0
  557. package/extensions/irc/src/config-schema.ts +97 -0
  558. package/extensions/irc/src/control-chars.ts +22 -0
  559. package/extensions/irc/src/inbound.ts +334 -0
  560. package/extensions/irc/src/monitor.test.ts +43 -0
  561. package/extensions/irc/src/monitor.ts +158 -0
  562. package/extensions/irc/src/normalize.test.ts +46 -0
  563. package/extensions/irc/src/normalize.ts +117 -0
  564. package/extensions/irc/src/onboarding.test.ts +118 -0
  565. package/extensions/irc/src/onboarding.ts +479 -0
  566. package/extensions/irc/src/policy.test.ts +132 -0
  567. package/extensions/irc/src/policy.ts +157 -0
  568. package/extensions/irc/src/probe.ts +64 -0
  569. package/extensions/irc/src/protocol.test.ts +44 -0
  570. package/extensions/irc/src/protocol.ts +169 -0
  571. package/extensions/irc/src/runtime.ts +14 -0
  572. package/extensions/irc/src/send.ts +99 -0
  573. package/extensions/irc/src/types.ts +94 -0
  574. package/extensions/line/package.json +1 -1
  575. package/extensions/llm-task/package.json +1 -1
  576. package/extensions/lobster/package.json +1 -1
  577. package/extensions/matrix/CHANGELOG.md +6 -0
  578. package/extensions/matrix/node_modules/.bin/markdown-it +2 -2
  579. package/extensions/matrix/node_modules/.bin/markdown-it.CMD +2 -2
  580. package/extensions/matrix/node_modules/.bin/markdown-it.ps1 +2 -2
  581. package/extensions/matrix/package.json +2 -2
  582. package/extensions/matrix/src/matrix/monitor/media.ts +4 -2
  583. package/extensions/mattermost/package.json +1 -1
  584. package/extensions/memory-core/package.json +1 -1
  585. package/extensions/memory-lancedb/index.ts +6 -2
  586. package/extensions/memory-lancedb/node_modules/.bin/openai +2 -2
  587. package/extensions/memory-lancedb/node_modules/.bin/openai.CMD +2 -2
  588. package/extensions/memory-lancedb/node_modules/.bin/openai.ps1 +2 -2
  589. package/extensions/memory-lancedb/package.json +2 -2
  590. package/extensions/minimax-portal-auth/index.ts +7 -5
  591. package/extensions/minimax-portal-auth/package.json +1 -1
  592. package/extensions/msteams/CHANGELOG.md +6 -0
  593. package/extensions/msteams/package.json +1 -1
  594. package/extensions/msteams/src/media-helpers.test.ts +9 -0
  595. package/extensions/msteams/src/media-helpers.ts +15 -1
  596. package/extensions/msteams/src/mentions.test.ts +235 -0
  597. package/extensions/msteams/src/mentions.ts +114 -0
  598. package/extensions/msteams/src/messenger.test.ts +81 -1
  599. package/extensions/msteams/src/messenger.ts +11 -2
  600. package/extensions/nextcloud-talk/package.json +1 -1
  601. package/extensions/nostr/CHANGELOG.md +6 -0
  602. package/extensions/nostr/package.json +2 -2
  603. package/extensions/open-prose/package.json +1 -1
  604. package/extensions/signal/package.json +1 -1
  605. package/extensions/slack/package.json +1 -1
  606. package/extensions/telegram/package.json +1 -1
  607. package/extensions/telegram/src/channel.ts +1 -0
  608. package/extensions/tlon/package.json +1 -1
  609. package/extensions/twitch/CHANGELOG.md +6 -0
  610. package/extensions/twitch/package.json +1 -1
  611. package/extensions/twitch/src/onboarding.test.ts +5 -0
  612. package/extensions/twitch/src/outbound.test.ts +17 -6
  613. package/extensions/twitch/src/outbound.ts +12 -10
  614. package/extensions/voice-call/CHANGELOG.md +6 -0
  615. package/extensions/voice-call/package.json +1 -1
  616. package/extensions/voice-call/src/media-stream.ts +7 -1
  617. package/extensions/voice-call/src/providers/twilio.test.ts +5 -3
  618. package/extensions/voice-call/src/providers/twilio.ts +12 -1
  619. package/extensions/whatsapp/package.json +1 -1
  620. package/extensions/whatsapp/src/channel.ts +6 -16
  621. package/extensions/whatsapp/src/resolve-target.test.ts +154 -0
  622. package/extensions/zalo/CHANGELOG.md +6 -0
  623. package/extensions/zalo/package.json +1 -1
  624. package/extensions/zalouser/CHANGELOG.md +6 -0
  625. package/extensions/zalouser/package.json +1 -1
  626. package/package.json +26 -22
  627. package/dist/auth-BcNHFK-i.js +0 -184
  628. package/dist/auth-DkjJ3pm-.js +0 -184
  629. package/dist/boolean-M-esQJt6.js +0 -30
  630. package/dist/bundled/soul-evil/HOOK.md +0 -71
  631. package/dist/bundled/soul-evil/handler.js +0 -194
  632. package/dist/cli-B631__JU.js +0 -89
  633. package/dist/cli-DVhCVZZ6.js +0 -86
  634. package/dist/config-CI7EpvlP.js +0 -15
  635. package/dist/constants-DuoCkWRh.js +0 -65
  636. package/dist/control-ui/assets/index-CnB9IO4a.js.map +0 -1
  637. package/dist/control-ui/assets/index-DWhx-9JL.css +0 -1
  638. package/dist/date-time-c6HTX6IW.js +0 -187
  639. package/dist/frontmatter-xwTm0734.js +0 -105
  640. package/dist/parse-DqAvJRIf.js +0 -23
  641. package/dist/parse-duration-De_tAQSe.js +0 -24
  642. package/dist/parse-timeout-DV8NQQWk.js +0 -16
  643. package/dist/paths-IivnSNkP.js +0 -51
  644. package/dist/paths-MnZaxqPw.js +0 -48
  645. package/dist/paths-uoGO2aiO.js +0 -48
  646. package/dist/pi-model-discovery-DzFOAbQt.js +0 -20
  647. package/dist/plugin-sdk/tui/tui-formatters.d.ts +0 -31
  648. package/dist/session-key-nXYQSv-a.js +0 -167
  649. package/dist/tailscale-DU6DgqVy.js +0 -225
  650. package/dist/tailscale-DzJUWmKf.js +0 -252
  651. package/dist/utils-dp_OM900.js +0 -476
  652. package/docs/hooks/soul-evil.md +0 -69
  653. package/docs/zh-CN/hooks/soul-evil.md +0 -72
  654. package/skills/local-places/SERVER_README.md +0 -101
  655. package/skills/local-places/SKILL.md +0 -102
  656. package/skills/local-places/pyproject.toml +0 -21
  657. package/skills/local-places/src/local_places/__init__.py +0 -2
  658. package/skills/local-places/src/local_places/google_places.py +0 -314
  659. package/skills/local-places/src/local_places/main.py +0 -65
  660. package/skills/local-places/src/local_places/schemas.py +0 -107
  661. /package/dist/{archive-CXhvR9nU.js → archive-aSMUcOc6.js} +0 -0
  662. /package/dist/{archive-D0z3LZDK.js → archive-beaSfAzA.js} +0 -0
  663. /package/dist/{brew-BIrWdDps.js → brew-DlQQMJ3n.js} +0 -0
  664. /package/dist/{brew-B7YK4ZoL.js → brew-ROHf0-Xp.js} +0 -0
  665. /package/dist/{cli-utils-PlLcDZlM.js → cli-utils-CRhVAaLV.js} +0 -0
  666. /package/dist/{cli-utils-R-ECs5cY.js → cli-utils-CodyYLHe.js} +0 -0
  667. /package/dist/{command-format-BUxhT1xL.js → command-format-qUVxzqYm.js} +0 -0
  668. /package/dist/{constants-CNTiY-ZN.js → constants-BvQ6S8j5.js} +0 -0
  669. /package/dist/{errors-D3tYRJWG.js → errors-B91HIDPD.js} +0 -0
  670. /package/dist/{errors-B0eT3jVv.js → errors-Bv81hF2P.js} +0 -0
  671. /package/dist/{errors-x4NYs-1P.js → errors-Cojm0Kl7.js} +0 -0
  672. /package/dist/{format-CaxeRcue.js → format-CL8VOhxX.js} +0 -0
  673. /package/dist/{format-DLOJPZmo.js → format-DcfK-dwd.js} +0 -0
  674. /package/dist/{format-duration-CEmFWLyX.js → format-duration--hQihAvf.js} +0 -0
  675. /package/dist/{format-duration-DCXJx2ba.js → format-duration-84n6_DgO.js} +0 -0
  676. /package/dist/{format-relative-79_Y1n2Y.js → format-relative-Cywx6ldk.js} +0 -0
  677. /package/dist/{format-relative-Db7eqEu8.js → format-relative-cegC_FF5.js} +0 -0
  678. /package/dist/{helpers-CQI-5xS9.js → helpers-8O7IVGO-.js} +0 -0
  679. /package/dist/{helpers-DdwqKAAS.js → helpers-ByYj2Aq5.js} +0 -0
  680. /package/dist/{helpers-CRzoyyXS.js → helpers-CUVSCDJV.js} +0 -0
  681. /package/dist/{helpers-C89IG08W.js → helpers-HyeZXsnu.js} +0 -0
  682. /package/dist/{is-main-qJ675wPV.js → is-main-B9A8S9YC.js} +0 -0
  683. /package/dist/{is-main-WWuz28Ip.js → is-main-BWoXGz7p.js} +0 -0
  684. /package/dist/{logging-BzvBIA3Y.js → logging-D-Jq2wIo.js} +0 -0
  685. /package/dist/{logging-CfEk_PnX.js → logging-fywhKCmE.js} +0 -0
  686. /package/dist/{parse-Cjiudy6x.js → parse-Bw0oH-rT.js} +0 -0
  687. /package/dist/{parse-log-line-CUrpqe1w.js → parse-log-line-BuRiE-Ij.js} +0 -0
  688. /package/dist/{parse-log-line-D2UGw0wR.js → parse-log-line-CfVgwy6x.js} +0 -0
  689. /package/dist/{parse-timeout-DFSPLxpY.js → parse-timeout-D1XX_zN_.js} +0 -0
  690. /package/dist/{pi-model-discovery-CV2V1HHz.js → pi-model-discovery-DqgqUyAv.js} +0 -0
  691. /package/dist/{pi-model-discovery-DzEIEgHL.js → pi-model-discovery-EwKVHlZB.js} +0 -0
  692. /package/dist/{prompts--d-6l5Ln.js → prompts-Bg96reub.js} +0 -0
  693. /package/dist/{prompts-CXLLIBwP.js → prompts-Dszjy1n_.js} +0 -0
  694. /package/dist/{redact-BRmQPYDR.js → redact-BIMJ3ntQ.js} +0 -0
  695. /package/dist/{redact-BHmk44DI.js → redact-BRsnXqwD.js} +0 -0
  696. /package/dist/{redact-DAKeu7PA.js → redact-UvkXqguc.js} +0 -0
  697. /package/dist/{status-Cv36yYdi.js → status-C_dMhoE0.js} +0 -0
  698. /package/dist/{status-Drziap9H.js → status-DCkF_L3U.js} +0 -0
  699. /package/dist/{systemd-hints-CH4pbCFD.js → systemd-hints-CXNtLw9Q.js} +0 -0
  700. /package/dist/{tailnet-CL5GtL7t.js → tailnet-DATIFSsY.js} +0 -0
  701. /package/dist/{tailnet-DGRSvYuQ.js → tailnet-uoFvUSsw.js} +0 -0
  702. /package/dist/{transcript-events-BlIONGVn.js → transcript-events-BHS7QoRl.js} +0 -0
  703. /package/dist/{transcript-events-C1hdue6u.js → transcript-events-Bp7fGnwv.js} +0 -0
  704. /package/dist/{transcript-events-CZ8CG4ht.js → transcript-events-Ch7wLX-j.js} +0 -0
  705. /package/dist/{usage-format-6Uar63S0.js → usage-format-Bhl_WCWP.js} +0 -0
  706. /package/dist/{usage-format-hd37en6b.js → usage-format-CpORtVCG.js} +0 -0
  707. /package/extensions/{feishu → irc}/node_modules/.bin/claw +0 -0
  708. /package/extensions/{feishu → irc}/node_modules/.bin/claw.CMD +0 -0
  709. /package/extensions/{feishu → irc}/node_modules/.bin/claw.ps1 +0 -0
  710. /package/extensions/{feishu → irc}/node_modules/.bin/moltbot +0 -0
  711. /package/extensions/{feishu → irc}/node_modules/.bin/moltbot.CMD +0 -0
  712. /package/extensions/{feishu → irc}/node_modules/.bin/moltbot.ps1 +0 -0
  713. /package/extensions/{feishu → irc}/node_modules/.bin/pigbot +0 -0
  714. /package/extensions/{feishu → irc}/node_modules/.bin/pigbot.CMD +0 -0
  715. /package/extensions/{feishu → irc}/node_modules/.bin/pigbot.ps1 +0 -0
@@ -0,0 +1,1901 @@
1
+ import { S as logVerbose, T as shouldLogVerbose } from "./entry.js";
2
+ import { A as normalizeProviderId, C as resolveOpenClawAgentDir, W as normalizeGoogleModelId, ct as requireApiKey, lt as resolveApiKeyForProvider } from "./auth-profiles-Cp9MtUdM.js";
3
+ import { n as runExec } from "./exec-DqZFMawz.js";
4
+ import { i as loadConfig } from "./config-B8v0zg48.js";
5
+ import { r as formatUncaughtError, t as extractErrorCode } from "./errors-Cojm0Kl7.js";
6
+ import { _ as normalizeChatType } from "./plugins-CxrdL_IZ.js";
7
+ import { _ as isAudioFileName, h as getFileExtension, p as detectMime, y as kindFromMime } from "./routes-CaCvio4Q.js";
8
+ import { a as fetchWithTimeout, n as fetchRemoteMedia, r as fetchWithSsrFGuard, t as MediaFetchError } from "./fetch-wuOZDzdT.js";
9
+ import { t as describeImageWithModel, y as ensureOpenClawModelsJson } from "./image-D-5pUELC.js";
10
+ import path from "node:path";
11
+ import process$1 from "node:process";
12
+ import os from "node:os";
13
+ import { constants } from "node:fs";
14
+ import fs$1 from "node:fs/promises";
15
+ import { fileURLToPath } from "node:url";
16
+ import crypto from "node:crypto";
17
+
18
+ //#region src/agents/model-catalog.ts
19
+ let modelCatalogPromise = null;
20
+ let hasLoggedModelCatalogError = false;
21
+ const defaultImportPiSdk = () => import("./pi-model-discovery-EhM2JAQo.js").then((n) => n.r);
22
+ let importPiSdk = defaultImportPiSdk;
23
+ const CODEX_PROVIDER = "openai-codex";
24
+ const OPENAI_CODEX_GPT53_MODEL_ID = "gpt-5.3-codex";
25
+ const OPENAI_CODEX_GPT53_SPARK_MODEL_ID = "gpt-5.3-codex-spark";
26
+ function applyOpenAICodexSparkFallback(models) {
27
+ if (models.some((entry) => entry.provider === CODEX_PROVIDER && entry.id.toLowerCase() === OPENAI_CODEX_GPT53_SPARK_MODEL_ID)) return;
28
+ const baseModel = models.find((entry) => entry.provider === CODEX_PROVIDER && entry.id.toLowerCase() === OPENAI_CODEX_GPT53_MODEL_ID);
29
+ if (!baseModel) return;
30
+ models.push({
31
+ ...baseModel,
32
+ id: OPENAI_CODEX_GPT53_SPARK_MODEL_ID,
33
+ name: OPENAI_CODEX_GPT53_SPARK_MODEL_ID
34
+ });
35
+ }
36
+ async function loadModelCatalog(params) {
37
+ if (params?.useCache === false) modelCatalogPromise = null;
38
+ if (modelCatalogPromise) return modelCatalogPromise;
39
+ modelCatalogPromise = (async () => {
40
+ const models = [];
41
+ const sortModels = (entries) => entries.sort((a, b) => {
42
+ const p = a.provider.localeCompare(b.provider);
43
+ if (p !== 0) return p;
44
+ return a.name.localeCompare(b.name);
45
+ });
46
+ try {
47
+ await ensureOpenClawModelsJson(params?.config ?? loadConfig());
48
+ await (await import("./pi-auth-json-DgvHjfJy.js")).ensurePiAuthJsonFromAuthProfiles(resolveOpenClawAgentDir());
49
+ const piSdk = await importPiSdk();
50
+ const agentDir = resolveOpenClawAgentDir();
51
+ const { join } = await import("node:path");
52
+ const authStorage = new piSdk.AuthStorage(join(agentDir, "auth.json"));
53
+ const registry = new piSdk.ModelRegistry(authStorage, join(agentDir, "models.json"));
54
+ const entries = Array.isArray(registry) ? registry : registry.getAll();
55
+ for (const entry of entries) {
56
+ const id = String(entry?.id ?? "").trim();
57
+ if (!id) continue;
58
+ const provider = String(entry?.provider ?? "").trim();
59
+ if (!provider) continue;
60
+ const name = String(entry?.name ?? id).trim() || id;
61
+ const contextWindow = typeof entry?.contextWindow === "number" && entry.contextWindow > 0 ? entry.contextWindow : void 0;
62
+ const reasoning = typeof entry?.reasoning === "boolean" ? entry.reasoning : void 0;
63
+ const input = Array.isArray(entry?.input) ? entry.input : void 0;
64
+ models.push({
65
+ id,
66
+ name,
67
+ provider,
68
+ contextWindow,
69
+ reasoning,
70
+ input
71
+ });
72
+ }
73
+ applyOpenAICodexSparkFallback(models);
74
+ if (models.length === 0) modelCatalogPromise = null;
75
+ return sortModels(models);
76
+ } catch (error) {
77
+ if (!hasLoggedModelCatalogError) {
78
+ hasLoggedModelCatalogError = true;
79
+ console.warn(`[model-catalog] Failed to load model catalog: ${String(error)}`);
80
+ }
81
+ modelCatalogPromise = null;
82
+ if (models.length > 0) return sortModels(models);
83
+ return [];
84
+ }
85
+ })();
86
+ return modelCatalogPromise;
87
+ }
88
+ /**
89
+ * Check if a model supports image input based on its catalog entry.
90
+ */
91
+ function modelSupportsVision(entry) {
92
+ return entry?.input?.includes("image") ?? false;
93
+ }
94
+ /**
95
+ * Find a model in the catalog by provider and model ID.
96
+ */
97
+ function findModelInCatalog(catalog, provider, modelId) {
98
+ const normalizedProvider = provider.toLowerCase().trim();
99
+ const normalizedModelId = modelId.toLowerCase().trim();
100
+ return catalog.find((entry) => entry.provider.toLowerCase() === normalizedProvider && entry.id.toLowerCase() === normalizedModelId);
101
+ }
102
+
103
+ //#endregion
104
+ //#region src/infra/unhandled-rejections.ts
105
+ const handlers = /* @__PURE__ */ new Set();
106
+ const FATAL_ERROR_CODES = new Set([
107
+ "ERR_OUT_OF_MEMORY",
108
+ "ERR_SCRIPT_EXECUTION_TIMEOUT",
109
+ "ERR_WORKER_OUT_OF_MEMORY",
110
+ "ERR_WORKER_UNCAUGHT_EXCEPTION",
111
+ "ERR_WORKER_INITIALIZATION_FAILED"
112
+ ]);
113
+ const CONFIG_ERROR_CODES = new Set([
114
+ "INVALID_CONFIG",
115
+ "MISSING_API_KEY",
116
+ "MISSING_CREDENTIALS"
117
+ ]);
118
+ const TRANSIENT_NETWORK_CODES = new Set([
119
+ "ECONNRESET",
120
+ "ECONNREFUSED",
121
+ "ENOTFOUND",
122
+ "ETIMEDOUT",
123
+ "ESOCKETTIMEDOUT",
124
+ "ECONNABORTED",
125
+ "EPIPE",
126
+ "EHOSTUNREACH",
127
+ "ENETUNREACH",
128
+ "EAI_AGAIN",
129
+ "UND_ERR_CONNECT_TIMEOUT",
130
+ "UND_ERR_DNS_RESOLVE_FAILED",
131
+ "UND_ERR_CONNECT",
132
+ "UND_ERR_SOCKET",
133
+ "UND_ERR_HEADERS_TIMEOUT",
134
+ "UND_ERR_BODY_TIMEOUT"
135
+ ]);
136
+ function getErrorCause(err) {
137
+ if (!err || typeof err !== "object") return;
138
+ return err.cause;
139
+ }
140
+ function extractErrorCodeWithCause(err) {
141
+ const direct = extractErrorCode(err);
142
+ if (direct) return direct;
143
+ return extractErrorCode(getErrorCause(err));
144
+ }
145
+ /**
146
+ * Checks if an error is an AbortError.
147
+ * These are typically intentional cancellations (e.g., during shutdown) and shouldn't crash.
148
+ */
149
+ function isAbortError(err) {
150
+ if (!err || typeof err !== "object") return false;
151
+ if (("name" in err ? String(err.name) : "") === "AbortError") return true;
152
+ if (("message" in err && typeof err.message === "string" ? err.message : "") === "This operation was aborted") return true;
153
+ return false;
154
+ }
155
+ function isFatalError(err) {
156
+ const code = extractErrorCodeWithCause(err);
157
+ return code !== void 0 && FATAL_ERROR_CODES.has(code);
158
+ }
159
+ function isConfigError(err) {
160
+ const code = extractErrorCodeWithCause(err);
161
+ return code !== void 0 && CONFIG_ERROR_CODES.has(code);
162
+ }
163
+ /**
164
+ * Checks if an error is a transient network error that shouldn't crash the gateway.
165
+ * These are typically temporary connectivity issues that will resolve on their own.
166
+ */
167
+ function isTransientNetworkError(err) {
168
+ if (!err) return false;
169
+ const code = extractErrorCodeWithCause(err);
170
+ if (code && TRANSIENT_NETWORK_CODES.has(code)) return true;
171
+ if (err instanceof TypeError && err.message === "fetch failed") {
172
+ const cause = getErrorCause(err);
173
+ if (cause) return isTransientNetworkError(cause);
174
+ return true;
175
+ }
176
+ const cause = getErrorCause(err);
177
+ if (cause && cause !== err) return isTransientNetworkError(cause);
178
+ if (err instanceof AggregateError && err.errors?.length) return err.errors.some((e) => isTransientNetworkError(e));
179
+ return false;
180
+ }
181
+ function registerUnhandledRejectionHandler(handler) {
182
+ handlers.add(handler);
183
+ return () => {
184
+ handlers.delete(handler);
185
+ };
186
+ }
187
+ function isUnhandledRejectionHandled(reason) {
188
+ for (const handler of handlers) try {
189
+ if (handler(reason)) return true;
190
+ } catch (err) {
191
+ console.error("[openclaw] Unhandled rejection handler failed:", err instanceof Error ? err.stack ?? err.message : err);
192
+ }
193
+ return false;
194
+ }
195
+ function installUnhandledRejectionHandler() {
196
+ process$1.on("unhandledRejection", (reason, _promise) => {
197
+ if (isUnhandledRejectionHandled(reason)) return;
198
+ if (isAbortError(reason)) {
199
+ console.warn("[openclaw] Suppressed AbortError:", formatUncaughtError(reason));
200
+ return;
201
+ }
202
+ if (isFatalError(reason)) {
203
+ console.error("[openclaw] FATAL unhandled rejection:", formatUncaughtError(reason));
204
+ process$1.exit(1);
205
+ return;
206
+ }
207
+ if (isConfigError(reason)) {
208
+ console.error("[openclaw] CONFIGURATION ERROR - requires fix:", formatUncaughtError(reason));
209
+ process$1.exit(1);
210
+ return;
211
+ }
212
+ if (isTransientNetworkError(reason)) {
213
+ console.warn("[openclaw] Non-fatal unhandled rejection (continuing):", formatUncaughtError(reason));
214
+ return;
215
+ }
216
+ console.error("[openclaw] Unhandled promise rejection:", formatUncaughtError(reason));
217
+ process$1.exit(1);
218
+ });
219
+ }
220
+
221
+ //#endregion
222
+ //#region src/auto-reply/templating.ts
223
+ function formatTemplateValue(value) {
224
+ if (value == null) return "";
225
+ if (typeof value === "string") return value;
226
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
227
+ if (typeof value === "symbol" || typeof value === "function") return value.toString();
228
+ if (Array.isArray(value)) return value.flatMap((entry) => {
229
+ if (entry == null) return [];
230
+ if (typeof entry === "string") return [entry];
231
+ if (typeof entry === "number" || typeof entry === "boolean" || typeof entry === "bigint") return [String(entry)];
232
+ return [];
233
+ }).join(",");
234
+ if (typeof value === "object") return "";
235
+ return "";
236
+ }
237
+ function applyTemplate(str, ctx) {
238
+ if (!str) return "";
239
+ return str.replace(/{{\s*(\w+)\s*}}/g, (_, key) => {
240
+ const value = ctx[key];
241
+ return formatTemplateValue(value);
242
+ });
243
+ }
244
+
245
+ //#endregion
246
+ //#region src/media-understanding/defaults.ts
247
+ const MB = 1024 * 1024;
248
+ const DEFAULT_MAX_CHARS = 500;
249
+ const DEFAULT_MAX_CHARS_BY_CAPABILITY = {
250
+ image: DEFAULT_MAX_CHARS,
251
+ audio: void 0,
252
+ video: DEFAULT_MAX_CHARS
253
+ };
254
+ const DEFAULT_MAX_BYTES = {
255
+ image: 10 * MB,
256
+ audio: 20 * MB,
257
+ video: 50 * MB
258
+ };
259
+ const DEFAULT_TIMEOUT_SECONDS = {
260
+ image: 60,
261
+ audio: 60,
262
+ video: 120
263
+ };
264
+ const DEFAULT_PROMPT = {
265
+ image: "Describe the image.",
266
+ audio: "Transcribe the audio.",
267
+ video: "Describe the video."
268
+ };
269
+ const DEFAULT_VIDEO_MAX_BASE64_BYTES = 70 * MB;
270
+ const DEFAULT_AUDIO_MODELS = {
271
+ groq: "whisper-large-v3-turbo",
272
+ openai: "gpt-4o-mini-transcribe",
273
+ deepgram: "nova-3"
274
+ };
275
+ const AUTO_AUDIO_KEY_PROVIDERS = [
276
+ "openai",
277
+ "groq",
278
+ "deepgram",
279
+ "google"
280
+ ];
281
+ const AUTO_IMAGE_KEY_PROVIDERS = [
282
+ "openai",
283
+ "anthropic",
284
+ "google",
285
+ "minimax",
286
+ "zai"
287
+ ];
288
+ const AUTO_VIDEO_KEY_PROVIDERS = ["google"];
289
+ const DEFAULT_IMAGE_MODELS = {
290
+ openai: "gpt-5-mini",
291
+ anthropic: "claude-opus-4-6",
292
+ google: "gemini-3-flash-preview",
293
+ minimax: "MiniMax-VL-01",
294
+ zai: "glm-4.6v"
295
+ };
296
+ const CLI_OUTPUT_MAX_BUFFER = 5 * MB;
297
+ const DEFAULT_MEDIA_CONCURRENCY = 2;
298
+
299
+ //#endregion
300
+ //#region src/media-understanding/providers/anthropic/index.ts
301
+ const anthropicProvider = {
302
+ id: "anthropic",
303
+ capabilities: ["image"],
304
+ describeImage: describeImageWithModel
305
+ };
306
+
307
+ //#endregion
308
+ //#region src/media-understanding/providers/shared.ts
309
+ const MAX_ERROR_CHARS = 300;
310
+ function normalizeBaseUrl(baseUrl, fallback) {
311
+ return (baseUrl?.trim() || fallback).replace(/\/+$/, "");
312
+ }
313
+ async function fetchWithTimeoutGuarded(url, init, timeoutMs, fetchFn, options) {
314
+ return await fetchWithSsrFGuard({
315
+ url,
316
+ fetchImpl: fetchFn,
317
+ init,
318
+ timeoutMs,
319
+ policy: options?.ssrfPolicy,
320
+ lookupFn: options?.lookupFn,
321
+ pinDns: options?.pinDns
322
+ });
323
+ }
324
+ async function readErrorResponse(res) {
325
+ try {
326
+ const collapsed = (await res.text()).replace(/\s+/g, " ").trim();
327
+ if (!collapsed) return;
328
+ if (collapsed.length <= MAX_ERROR_CHARS) return collapsed;
329
+ return `${collapsed.slice(0, MAX_ERROR_CHARS)}…`;
330
+ } catch {
331
+ return;
332
+ }
333
+ }
334
+
335
+ //#endregion
336
+ //#region src/media-understanding/providers/deepgram/audio.ts
337
+ const DEFAULT_DEEPGRAM_AUDIO_BASE_URL = "https://api.deepgram.com/v1";
338
+ const DEFAULT_DEEPGRAM_AUDIO_MODEL = "nova-3";
339
+ function resolveModel$3(model) {
340
+ return model?.trim() || DEFAULT_DEEPGRAM_AUDIO_MODEL;
341
+ }
342
+ async function transcribeDeepgramAudio(params) {
343
+ const fetchFn = params.fetchFn ?? fetch;
344
+ const baseUrl = normalizeBaseUrl(params.baseUrl, DEFAULT_DEEPGRAM_AUDIO_BASE_URL);
345
+ const allowPrivate = Boolean(params.baseUrl?.trim());
346
+ const model = resolveModel$3(params.model);
347
+ const url = new URL(`${baseUrl}/listen`);
348
+ url.searchParams.set("model", model);
349
+ if (params.language?.trim()) url.searchParams.set("language", params.language.trim());
350
+ if (params.query) for (const [key, value] of Object.entries(params.query)) {
351
+ if (value === void 0) continue;
352
+ url.searchParams.set(key, String(value));
353
+ }
354
+ const headers = new Headers(params.headers);
355
+ if (!headers.has("authorization")) headers.set("authorization", `Token ${params.apiKey}`);
356
+ if (!headers.has("content-type")) headers.set("content-type", params.mime ?? "application/octet-stream");
357
+ const body = new Uint8Array(params.buffer);
358
+ const { response: res, release } = await fetchWithTimeoutGuarded(url.toString(), {
359
+ method: "POST",
360
+ headers,
361
+ body
362
+ }, params.timeoutMs, fetchFn, allowPrivate ? { ssrfPolicy: { allowPrivateNetwork: true } } : void 0);
363
+ try {
364
+ if (!res.ok) {
365
+ const detail = await readErrorResponse(res);
366
+ const suffix = detail ? `: ${detail}` : "";
367
+ throw new Error(`Audio transcription failed (HTTP ${res.status})${suffix}`);
368
+ }
369
+ const transcript = (await res.json()).results?.channels?.[0]?.alternatives?.[0]?.transcript?.trim();
370
+ if (!transcript) throw new Error("Audio transcription response missing transcript");
371
+ return {
372
+ text: transcript,
373
+ model
374
+ };
375
+ } finally {
376
+ await release();
377
+ }
378
+ }
379
+
380
+ //#endregion
381
+ //#region src/media-understanding/providers/deepgram/index.ts
382
+ const deepgramProvider = {
383
+ id: "deepgram",
384
+ capabilities: ["audio"],
385
+ transcribeAudio: transcribeDeepgramAudio
386
+ };
387
+
388
+ //#endregion
389
+ //#region src/media-understanding/providers/google/audio.ts
390
+ const DEFAULT_GOOGLE_AUDIO_BASE_URL = "https://generativelanguage.googleapis.com/v1beta";
391
+ const DEFAULT_GOOGLE_AUDIO_MODEL = "gemini-3-flash-preview";
392
+ const DEFAULT_GOOGLE_AUDIO_PROMPT = "Transcribe the audio.";
393
+ function resolveModel$2(model) {
394
+ const trimmed = model?.trim();
395
+ if (!trimmed) return DEFAULT_GOOGLE_AUDIO_MODEL;
396
+ return normalizeGoogleModelId(trimmed);
397
+ }
398
+ function resolvePrompt$2(prompt) {
399
+ return prompt?.trim() || DEFAULT_GOOGLE_AUDIO_PROMPT;
400
+ }
401
+ async function transcribeGeminiAudio(params) {
402
+ const fetchFn = params.fetchFn ?? fetch;
403
+ const baseUrl = normalizeBaseUrl(params.baseUrl, DEFAULT_GOOGLE_AUDIO_BASE_URL);
404
+ const allowPrivate = Boolean(params.baseUrl?.trim());
405
+ const model = resolveModel$2(params.model);
406
+ const url = `${baseUrl}/models/${model}:generateContent`;
407
+ const headers = new Headers(params.headers);
408
+ if (!headers.has("content-type")) headers.set("content-type", "application/json");
409
+ if (!headers.has("x-goog-api-key")) headers.set("x-goog-api-key", params.apiKey);
410
+ const body = { contents: [{
411
+ role: "user",
412
+ parts: [{ text: resolvePrompt$2(params.prompt) }, { inline_data: {
413
+ mime_type: params.mime ?? "audio/wav",
414
+ data: params.buffer.toString("base64")
415
+ } }]
416
+ }] };
417
+ const { response: res, release } = await fetchWithTimeoutGuarded(url, {
418
+ method: "POST",
419
+ headers,
420
+ body: JSON.stringify(body)
421
+ }, params.timeoutMs, fetchFn, allowPrivate ? { ssrfPolicy: { allowPrivateNetwork: true } } : void 0);
422
+ try {
423
+ if (!res.ok) {
424
+ const detail = await readErrorResponse(res);
425
+ const suffix = detail ? `: ${detail}` : "";
426
+ throw new Error(`Audio transcription failed (HTTP ${res.status})${suffix}`);
427
+ }
428
+ const text = ((await res.json()).candidates?.[0]?.content?.parts ?? []).map((part) => part?.text?.trim()).filter(Boolean).join("\n");
429
+ if (!text) throw new Error("Audio transcription response missing text");
430
+ return {
431
+ text,
432
+ model
433
+ };
434
+ } finally {
435
+ await release();
436
+ }
437
+ }
438
+
439
+ //#endregion
440
+ //#region src/media-understanding/providers/google/video.ts
441
+ const DEFAULT_GOOGLE_VIDEO_BASE_URL = "https://generativelanguage.googleapis.com/v1beta";
442
+ const DEFAULT_GOOGLE_VIDEO_MODEL = "gemini-3-flash-preview";
443
+ const DEFAULT_GOOGLE_VIDEO_PROMPT = "Describe the video.";
444
+ function resolveModel$1(model) {
445
+ const trimmed = model?.trim();
446
+ if (!trimmed) return DEFAULT_GOOGLE_VIDEO_MODEL;
447
+ return normalizeGoogleModelId(trimmed);
448
+ }
449
+ function resolvePrompt$1(prompt) {
450
+ return prompt?.trim() || DEFAULT_GOOGLE_VIDEO_PROMPT;
451
+ }
452
+ async function describeGeminiVideo(params) {
453
+ const fetchFn = params.fetchFn ?? fetch;
454
+ const baseUrl = normalizeBaseUrl(params.baseUrl, DEFAULT_GOOGLE_VIDEO_BASE_URL);
455
+ const allowPrivate = Boolean(params.baseUrl?.trim());
456
+ const model = resolveModel$1(params.model);
457
+ const url = `${baseUrl}/models/${model}:generateContent`;
458
+ const headers = new Headers(params.headers);
459
+ if (!headers.has("content-type")) headers.set("content-type", "application/json");
460
+ if (!headers.has("x-goog-api-key")) headers.set("x-goog-api-key", params.apiKey);
461
+ const body = { contents: [{
462
+ role: "user",
463
+ parts: [{ text: resolvePrompt$1(params.prompt) }, { inline_data: {
464
+ mime_type: params.mime ?? "video/mp4",
465
+ data: params.buffer.toString("base64")
466
+ } }]
467
+ }] };
468
+ const { response: res, release } = await fetchWithTimeoutGuarded(url, {
469
+ method: "POST",
470
+ headers,
471
+ body: JSON.stringify(body)
472
+ }, params.timeoutMs, fetchFn, allowPrivate ? { ssrfPolicy: { allowPrivateNetwork: true } } : void 0);
473
+ try {
474
+ if (!res.ok) {
475
+ const detail = await readErrorResponse(res);
476
+ const suffix = detail ? `: ${detail}` : "";
477
+ throw new Error(`Video description failed (HTTP ${res.status})${suffix}`);
478
+ }
479
+ const text = ((await res.json()).candidates?.[0]?.content?.parts ?? []).map((part) => part?.text?.trim()).filter(Boolean).join("\n");
480
+ if (!text) throw new Error("Video description response missing text");
481
+ return {
482
+ text,
483
+ model
484
+ };
485
+ } finally {
486
+ await release();
487
+ }
488
+ }
489
+
490
+ //#endregion
491
+ //#region src/media-understanding/providers/google/index.ts
492
+ const googleProvider = {
493
+ id: "google",
494
+ capabilities: [
495
+ "image",
496
+ "audio",
497
+ "video"
498
+ ],
499
+ describeImage: describeImageWithModel,
500
+ transcribeAudio: transcribeGeminiAudio,
501
+ describeVideo: describeGeminiVideo
502
+ };
503
+
504
+ //#endregion
505
+ //#region src/media-understanding/providers/openai/audio.ts
506
+ const DEFAULT_OPENAI_AUDIO_BASE_URL = "https://api.openai.com/v1";
507
+ const DEFAULT_OPENAI_AUDIO_MODEL = "gpt-4o-mini-transcribe";
508
+ function resolveModel(model) {
509
+ return model?.trim() || DEFAULT_OPENAI_AUDIO_MODEL;
510
+ }
511
+ async function transcribeOpenAiCompatibleAudio(params) {
512
+ const fetchFn = params.fetchFn ?? fetch;
513
+ const baseUrl = normalizeBaseUrl(params.baseUrl, DEFAULT_OPENAI_AUDIO_BASE_URL);
514
+ const allowPrivate = Boolean(params.baseUrl?.trim());
515
+ const url = `${baseUrl}/audio/transcriptions`;
516
+ const model = resolveModel(params.model);
517
+ const form = new FormData();
518
+ const fileName = params.fileName?.trim() || path.basename(params.fileName) || "audio";
519
+ const bytes = new Uint8Array(params.buffer);
520
+ const blob = new Blob([bytes], { type: params.mime ?? "application/octet-stream" });
521
+ form.append("file", blob, fileName);
522
+ form.append("model", model);
523
+ if (params.language?.trim()) form.append("language", params.language.trim());
524
+ if (params.prompt?.trim()) form.append("prompt", params.prompt.trim());
525
+ const headers = new Headers(params.headers);
526
+ if (!headers.has("authorization")) headers.set("authorization", `Bearer ${params.apiKey}`);
527
+ const { response: res, release } = await fetchWithTimeoutGuarded(url, {
528
+ method: "POST",
529
+ headers,
530
+ body: form
531
+ }, params.timeoutMs, fetchFn, allowPrivate ? { ssrfPolicy: { allowPrivateNetwork: true } } : void 0);
532
+ try {
533
+ if (!res.ok) {
534
+ const detail = await readErrorResponse(res);
535
+ const suffix = detail ? `: ${detail}` : "";
536
+ throw new Error(`Audio transcription failed (HTTP ${res.status})${suffix}`);
537
+ }
538
+ const text = (await res.json()).text?.trim();
539
+ if (!text) throw new Error("Audio transcription response missing text");
540
+ return {
541
+ text,
542
+ model
543
+ };
544
+ } finally {
545
+ await release();
546
+ }
547
+ }
548
+
549
+ //#endregion
550
+ //#region src/media-understanding/providers/groq/index.ts
551
+ const DEFAULT_GROQ_AUDIO_BASE_URL = "https://api.groq.com/openai/v1";
552
+ const groqProvider = {
553
+ id: "groq",
554
+ capabilities: ["audio"],
555
+ transcribeAudio: (req) => transcribeOpenAiCompatibleAudio({
556
+ ...req,
557
+ baseUrl: req.baseUrl ?? DEFAULT_GROQ_AUDIO_BASE_URL
558
+ })
559
+ };
560
+
561
+ //#endregion
562
+ //#region src/media-understanding/providers/minimax/index.ts
563
+ const minimaxProvider = {
564
+ id: "minimax",
565
+ capabilities: ["image"],
566
+ describeImage: describeImageWithModel
567
+ };
568
+
569
+ //#endregion
570
+ //#region src/media-understanding/providers/openai/index.ts
571
+ const openaiProvider = {
572
+ id: "openai",
573
+ capabilities: ["image"],
574
+ describeImage: describeImageWithModel,
575
+ transcribeAudio: transcribeOpenAiCompatibleAudio
576
+ };
577
+
578
+ //#endregion
579
+ //#region src/media-understanding/providers/zai/index.ts
580
+ const zaiProvider = {
581
+ id: "zai",
582
+ capabilities: ["image"],
583
+ describeImage: describeImageWithModel
584
+ };
585
+
586
+ //#endregion
587
+ //#region src/media-understanding/providers/index.ts
588
+ const PROVIDERS = [
589
+ groqProvider,
590
+ openaiProvider,
591
+ googleProvider,
592
+ anthropicProvider,
593
+ minimaxProvider,
594
+ zaiProvider,
595
+ deepgramProvider
596
+ ];
597
+ function normalizeMediaProviderId(id) {
598
+ const normalized = normalizeProviderId(id);
599
+ if (normalized === "gemini") return "google";
600
+ return normalized;
601
+ }
602
+ function buildMediaUnderstandingRegistry(overrides) {
603
+ const registry = /* @__PURE__ */ new Map();
604
+ for (const provider of PROVIDERS) registry.set(normalizeMediaProviderId(provider.id), provider);
605
+ if (overrides) for (const [key, provider] of Object.entries(overrides)) {
606
+ const normalizedKey = normalizeMediaProviderId(key);
607
+ const existing = registry.get(normalizedKey);
608
+ const merged = existing ? {
609
+ ...existing,
610
+ ...provider,
611
+ capabilities: provider.capabilities ?? existing.capabilities
612
+ } : provider;
613
+ registry.set(normalizedKey, merged);
614
+ }
615
+ return registry;
616
+ }
617
+ function getMediaUnderstandingProvider(id, registry) {
618
+ return registry.get(normalizeMediaProviderId(id));
619
+ }
620
+
621
+ //#endregion
622
+ //#region src/media-understanding/scope.ts
623
+ function normalizeDecision(value) {
624
+ const normalized = value?.trim().toLowerCase();
625
+ if (normalized === "allow") return "allow";
626
+ if (normalized === "deny") return "deny";
627
+ }
628
+ function normalizeMatch(value) {
629
+ return value?.trim().toLowerCase() || void 0;
630
+ }
631
+ function normalizeMediaUnderstandingChatType(raw) {
632
+ return normalizeChatType(raw ?? void 0);
633
+ }
634
+ function resolveMediaUnderstandingScope(params) {
635
+ const scope = params.scope;
636
+ if (!scope) return "allow";
637
+ const channel = normalizeMatch(params.channel);
638
+ const chatType = normalizeMediaUnderstandingChatType(params.chatType);
639
+ const sessionKey = normalizeMatch(params.sessionKey) ?? "";
640
+ for (const rule of scope.rules ?? []) {
641
+ if (!rule) continue;
642
+ const action = normalizeDecision(rule.action) ?? "allow";
643
+ const match = rule.match ?? {};
644
+ const matchChannel = normalizeMatch(match.channel);
645
+ const matchChatType = normalizeMediaUnderstandingChatType(match.chatType);
646
+ const matchPrefix = normalizeMatch(match.keyPrefix);
647
+ if (matchChannel && matchChannel !== channel) continue;
648
+ if (matchChatType && matchChatType !== chatType) continue;
649
+ if (matchPrefix && !sessionKey.startsWith(matchPrefix)) continue;
650
+ return action;
651
+ }
652
+ return normalizeDecision(scope.default) ?? "allow";
653
+ }
654
+
655
+ //#endregion
656
+ //#region src/media-understanding/resolve.ts
657
+ function resolveTimeoutMs(seconds, fallbackSeconds) {
658
+ const value = typeof seconds === "number" && Number.isFinite(seconds) ? seconds : fallbackSeconds;
659
+ return Math.max(1e3, Math.floor(value * 1e3));
660
+ }
661
+ function resolvePrompt(capability, prompt, maxChars) {
662
+ const base = prompt?.trim() || DEFAULT_PROMPT[capability];
663
+ if (!maxChars || capability === "audio") return base;
664
+ return `${base} Respond in at most ${maxChars} characters.`;
665
+ }
666
+ function resolveMaxChars(params) {
667
+ const { capability, entry, cfg } = params;
668
+ const configured = entry.maxChars ?? params.config?.maxChars ?? cfg.tools?.media?.[capability]?.maxChars;
669
+ if (typeof configured === "number") return configured;
670
+ return DEFAULT_MAX_CHARS_BY_CAPABILITY[capability];
671
+ }
672
+ function resolveMaxBytes(params) {
673
+ const configured = params.entry.maxBytes ?? params.config?.maxBytes ?? params.cfg.tools?.media?.[params.capability]?.maxBytes;
674
+ if (typeof configured === "number") return configured;
675
+ return DEFAULT_MAX_BYTES[params.capability];
676
+ }
677
+ function resolveScopeDecision(params) {
678
+ return resolveMediaUnderstandingScope({
679
+ scope: params.scope,
680
+ sessionKey: params.ctx.SessionKey,
681
+ channel: params.ctx.Surface ?? params.ctx.Provider,
682
+ chatType: normalizeMediaUnderstandingChatType(params.ctx.ChatType)
683
+ });
684
+ }
685
+ function resolveEntryCapabilities(params) {
686
+ if ((params.entry.type ?? (params.entry.command ? "cli" : "provider")) === "cli") return;
687
+ const providerId = normalizeMediaProviderId(params.entry.provider ?? "");
688
+ if (!providerId) return;
689
+ return params.providerRegistry.get(providerId)?.capabilities;
690
+ }
691
+ function resolveModelEntries(params) {
692
+ const { cfg, capability, config } = params;
693
+ const sharedModels = cfg.tools?.media?.models ?? [];
694
+ const entries = [...(config?.models ?? []).map((entry) => ({
695
+ entry,
696
+ source: "capability"
697
+ })), ...sharedModels.map((entry) => ({
698
+ entry,
699
+ source: "shared"
700
+ }))];
701
+ if (entries.length === 0) return [];
702
+ return entries.filter(({ entry, source }) => {
703
+ const caps = entry.capabilities && entry.capabilities.length > 0 ? entry.capabilities : source === "shared" ? resolveEntryCapabilities({
704
+ entry,
705
+ providerRegistry: params.providerRegistry
706
+ }) : void 0;
707
+ if (!caps || caps.length === 0) {
708
+ if (source === "shared") {
709
+ if (shouldLogVerbose()) logVerbose(`Skipping shared media model without capabilities: ${entry.provider ?? entry.command ?? "unknown"}`);
710
+ return false;
711
+ }
712
+ return true;
713
+ }
714
+ return caps.includes(capability);
715
+ }).map(({ entry }) => entry);
716
+ }
717
+ function resolveConcurrency(cfg) {
718
+ const configured = cfg.tools?.media?.concurrency;
719
+ if (typeof configured === "number" && Number.isFinite(configured) && configured > 0) return Math.floor(configured);
720
+ return DEFAULT_MEDIA_CONCURRENCY;
721
+ }
722
+
723
+ //#endregion
724
+ //#region src/media-understanding/errors.ts
725
+ var MediaUnderstandingSkipError = class extends Error {
726
+ constructor(reason, message) {
727
+ super(message);
728
+ this.reason = reason;
729
+ this.name = "MediaUnderstandingSkipError";
730
+ }
731
+ };
732
+ function isMediaUnderstandingSkipError(err) {
733
+ return err instanceof MediaUnderstandingSkipError;
734
+ }
735
+
736
+ //#endregion
737
+ //#region src/media-understanding/attachments.ts
738
+ const DEFAULT_MAX_ATTACHMENTS = 1;
739
+ function normalizeAttachmentPath(raw) {
740
+ const value = raw?.trim();
741
+ if (!value) return;
742
+ if (value.startsWith("file://")) try {
743
+ return fileURLToPath(value);
744
+ } catch {
745
+ return;
746
+ }
747
+ return value;
748
+ }
749
+ function normalizeAttachments(ctx) {
750
+ const pathsFromArray = Array.isArray(ctx.MediaPaths) ? ctx.MediaPaths : void 0;
751
+ const urlsFromArray = Array.isArray(ctx.MediaUrls) ? ctx.MediaUrls : void 0;
752
+ const typesFromArray = Array.isArray(ctx.MediaTypes) ? ctx.MediaTypes : void 0;
753
+ const resolveMime = (count, index) => {
754
+ const typeHint = typesFromArray?.[index];
755
+ const trimmed = typeof typeHint === "string" ? typeHint.trim() : "";
756
+ if (trimmed) return trimmed;
757
+ return count === 1 ? ctx.MediaType : void 0;
758
+ };
759
+ if (pathsFromArray && pathsFromArray.length > 0) {
760
+ const count = pathsFromArray.length;
761
+ const urls = urlsFromArray && urlsFromArray.length > 0 ? urlsFromArray : void 0;
762
+ return pathsFromArray.map((value, index) => ({
763
+ path: value?.trim() || void 0,
764
+ url: urls?.[index] ?? ctx.MediaUrl,
765
+ mime: resolveMime(count, index),
766
+ index
767
+ })).filter((entry) => Boolean(entry.path?.trim() || entry.url?.trim()));
768
+ }
769
+ if (urlsFromArray && urlsFromArray.length > 0) {
770
+ const count = urlsFromArray.length;
771
+ return urlsFromArray.map((value, index) => ({
772
+ path: void 0,
773
+ url: value?.trim() || void 0,
774
+ mime: resolveMime(count, index),
775
+ index
776
+ })).filter((entry) => Boolean(entry.url?.trim()));
777
+ }
778
+ const pathValue = ctx.MediaPath?.trim();
779
+ const url = ctx.MediaUrl?.trim();
780
+ if (!pathValue && !url) return [];
781
+ return [{
782
+ path: pathValue || void 0,
783
+ url: url || void 0,
784
+ mime: ctx.MediaType,
785
+ index: 0
786
+ }];
787
+ }
788
+ function resolveAttachmentKind(attachment) {
789
+ const kind = kindFromMime(attachment.mime);
790
+ if (kind === "image" || kind === "audio" || kind === "video") return kind;
791
+ const ext = getFileExtension(attachment.path ?? attachment.url);
792
+ if (!ext) return "unknown";
793
+ if ([
794
+ ".mp4",
795
+ ".mov",
796
+ ".mkv",
797
+ ".webm",
798
+ ".avi",
799
+ ".m4v"
800
+ ].includes(ext)) return "video";
801
+ if (isAudioFileName(attachment.path ?? attachment.url)) return "audio";
802
+ if ([
803
+ ".png",
804
+ ".jpg",
805
+ ".jpeg",
806
+ ".webp",
807
+ ".gif",
808
+ ".bmp",
809
+ ".tiff",
810
+ ".tif"
811
+ ].includes(ext)) return "image";
812
+ return "unknown";
813
+ }
814
+ function isVideoAttachment(attachment) {
815
+ return resolveAttachmentKind(attachment) === "video";
816
+ }
817
+ function isAudioAttachment(attachment) {
818
+ return resolveAttachmentKind(attachment) === "audio";
819
+ }
820
+ function isImageAttachment(attachment) {
821
+ return resolveAttachmentKind(attachment) === "image";
822
+ }
823
+ function resolveRequestUrl(input) {
824
+ if (typeof input === "string") return input;
825
+ if (input instanceof URL) return input.toString();
826
+ return input.url;
827
+ }
828
+ function orderAttachments(attachments, prefer) {
829
+ if (!prefer || prefer === "first") return attachments;
830
+ if (prefer === "last") return [...attachments].toReversed();
831
+ if (prefer === "path") {
832
+ const withPath = attachments.filter((item) => item.path);
833
+ const withoutPath = attachments.filter((item) => !item.path);
834
+ return [...withPath, ...withoutPath];
835
+ }
836
+ if (prefer === "url") {
837
+ const withUrl = attachments.filter((item) => item.url);
838
+ const withoutUrl = attachments.filter((item) => !item.url);
839
+ return [...withUrl, ...withoutUrl];
840
+ }
841
+ return attachments;
842
+ }
843
+ function selectAttachments(params) {
844
+ const { capability, attachments, policy } = params;
845
+ const matches = attachments.filter((item) => {
846
+ if (capability === "audio" && item.alreadyTranscribed) return false;
847
+ if (capability === "image") return isImageAttachment(item);
848
+ if (capability === "audio") return isAudioAttachment(item);
849
+ return isVideoAttachment(item);
850
+ });
851
+ if (matches.length === 0) return [];
852
+ const ordered = orderAttachments(matches, policy?.prefer);
853
+ const mode = policy?.mode ?? "first";
854
+ const maxAttachments = policy?.maxAttachments ?? DEFAULT_MAX_ATTACHMENTS;
855
+ if (mode === "all") return ordered.slice(0, Math.max(1, maxAttachments));
856
+ return ordered.slice(0, 1);
857
+ }
858
+ var MediaAttachmentCache = class {
859
+ constructor(attachments) {
860
+ this.entries = /* @__PURE__ */ new Map();
861
+ this.attachments = attachments;
862
+ for (const attachment of attachments) this.entries.set(attachment.index, { attachment });
863
+ }
864
+ async getBuffer(params) {
865
+ const entry = await this.ensureEntry(params.attachmentIndex);
866
+ if (entry.buffer) {
867
+ if (entry.buffer.length > params.maxBytes) throw new MediaUnderstandingSkipError("maxBytes", `Attachment ${params.attachmentIndex + 1} exceeds maxBytes ${params.maxBytes}`);
868
+ return {
869
+ buffer: entry.buffer,
870
+ mime: entry.bufferMime,
871
+ fileName: entry.bufferFileName ?? `media-${params.attachmentIndex + 1}`,
872
+ size: entry.buffer.length
873
+ };
874
+ }
875
+ if (entry.resolvedPath) {
876
+ const size = await this.ensureLocalStat(entry);
877
+ if (entry.resolvedPath) {
878
+ if (size !== void 0 && size > params.maxBytes) throw new MediaUnderstandingSkipError("maxBytes", `Attachment ${params.attachmentIndex + 1} exceeds maxBytes ${params.maxBytes}`);
879
+ const buffer = await fs$1.readFile(entry.resolvedPath);
880
+ entry.buffer = buffer;
881
+ entry.bufferMime = entry.bufferMime ?? entry.attachment.mime ?? await detectMime({
882
+ buffer,
883
+ filePath: entry.resolvedPath
884
+ });
885
+ entry.bufferFileName = path.basename(entry.resolvedPath) || `media-${params.attachmentIndex + 1}`;
886
+ return {
887
+ buffer,
888
+ mime: entry.bufferMime,
889
+ fileName: entry.bufferFileName,
890
+ size: buffer.length
891
+ };
892
+ }
893
+ }
894
+ const url = entry.attachment.url?.trim();
895
+ if (!url) throw new MediaUnderstandingSkipError("empty", `Attachment ${params.attachmentIndex + 1} has no path or URL.`);
896
+ try {
897
+ const fetchImpl = (input, init) => fetchWithTimeout(resolveRequestUrl(input), init ?? {}, params.timeoutMs, fetch);
898
+ const fetched = await fetchRemoteMedia({
899
+ url,
900
+ fetchImpl,
901
+ maxBytes: params.maxBytes
902
+ });
903
+ entry.buffer = fetched.buffer;
904
+ entry.bufferMime = entry.attachment.mime ?? fetched.contentType ?? await detectMime({
905
+ buffer: fetched.buffer,
906
+ filePath: fetched.fileName ?? url
907
+ });
908
+ entry.bufferFileName = fetched.fileName ?? `media-${params.attachmentIndex + 1}`;
909
+ return {
910
+ buffer: fetched.buffer,
911
+ mime: entry.bufferMime,
912
+ fileName: entry.bufferFileName,
913
+ size: fetched.buffer.length
914
+ };
915
+ } catch (err) {
916
+ if (err instanceof MediaFetchError && err.code === "max_bytes") throw new MediaUnderstandingSkipError("maxBytes", `Attachment ${params.attachmentIndex + 1} exceeds maxBytes ${params.maxBytes}`);
917
+ if (isAbortError(err)) throw new MediaUnderstandingSkipError("timeout", `Attachment ${params.attachmentIndex + 1} timed out while fetching.`);
918
+ throw err;
919
+ }
920
+ }
921
+ async getPath(params) {
922
+ const entry = await this.ensureEntry(params.attachmentIndex);
923
+ if (entry.resolvedPath) {
924
+ if (params.maxBytes) {
925
+ const size = await this.ensureLocalStat(entry);
926
+ if (entry.resolvedPath) {
927
+ if (size !== void 0 && size > params.maxBytes) throw new MediaUnderstandingSkipError("maxBytes", `Attachment ${params.attachmentIndex + 1} exceeds maxBytes ${params.maxBytes}`);
928
+ }
929
+ }
930
+ if (entry.resolvedPath) return { path: entry.resolvedPath };
931
+ }
932
+ if (entry.tempPath) {
933
+ if (params.maxBytes && entry.buffer && entry.buffer.length > params.maxBytes) throw new MediaUnderstandingSkipError("maxBytes", `Attachment ${params.attachmentIndex + 1} exceeds maxBytes ${params.maxBytes}`);
934
+ return {
935
+ path: entry.tempPath,
936
+ cleanup: entry.tempCleanup
937
+ };
938
+ }
939
+ const maxBytes = params.maxBytes ?? Number.POSITIVE_INFINITY;
940
+ const bufferResult = await this.getBuffer({
941
+ attachmentIndex: params.attachmentIndex,
942
+ maxBytes,
943
+ timeoutMs: params.timeoutMs
944
+ });
945
+ const extension = path.extname(bufferResult.fileName || "") || "";
946
+ const tmpPath = path.join(os.tmpdir(), `openclaw-media-${crypto.randomUUID()}${extension}`);
947
+ await fs$1.writeFile(tmpPath, bufferResult.buffer);
948
+ entry.tempPath = tmpPath;
949
+ entry.tempCleanup = async () => {
950
+ await fs$1.unlink(tmpPath).catch(() => {});
951
+ };
952
+ return {
953
+ path: tmpPath,
954
+ cleanup: entry.tempCleanup
955
+ };
956
+ }
957
+ async cleanup() {
958
+ const cleanups = [];
959
+ for (const entry of this.entries.values()) if (entry.tempCleanup) {
960
+ cleanups.push(Promise.resolve(entry.tempCleanup()));
961
+ entry.tempCleanup = void 0;
962
+ }
963
+ await Promise.all(cleanups);
964
+ }
965
+ async ensureEntry(attachmentIndex) {
966
+ const existing = this.entries.get(attachmentIndex);
967
+ if (existing) {
968
+ if (!existing.resolvedPath) existing.resolvedPath = this.resolveLocalPath(existing.attachment);
969
+ return existing;
970
+ }
971
+ const attachment = this.attachments.find((item) => item.index === attachmentIndex) ?? { index: attachmentIndex };
972
+ const entry = {
973
+ attachment,
974
+ resolvedPath: this.resolveLocalPath(attachment)
975
+ };
976
+ this.entries.set(attachmentIndex, entry);
977
+ return entry;
978
+ }
979
+ resolveLocalPath(attachment) {
980
+ const rawPath = normalizeAttachmentPath(attachment.path);
981
+ if (!rawPath) return;
982
+ return path.isAbsolute(rawPath) ? rawPath : path.resolve(rawPath);
983
+ }
984
+ async ensureLocalStat(entry) {
985
+ if (!entry.resolvedPath) return;
986
+ if (entry.statSize !== void 0) return entry.statSize;
987
+ try {
988
+ const stat = await fs$1.stat(entry.resolvedPath);
989
+ if (!stat.isFile()) {
990
+ entry.resolvedPath = void 0;
991
+ return;
992
+ }
993
+ entry.statSize = stat.size;
994
+ return stat.size;
995
+ } catch (err) {
996
+ entry.resolvedPath = void 0;
997
+ if (shouldLogVerbose()) logVerbose(`Failed to read attachment ${entry.attachment.index + 1}: ${String(err)}`);
998
+ return;
999
+ }
1000
+ }
1001
+ };
1002
+
1003
+ //#endregion
1004
+ //#region src/media-understanding/video.ts
1005
+ function estimateBase64Size(bytes) {
1006
+ return Math.ceil(bytes / 3) * 4;
1007
+ }
1008
+ function resolveVideoMaxBase64Bytes(maxBytes) {
1009
+ const expanded = Math.floor(maxBytes * (4 / 3));
1010
+ return Math.min(expanded, DEFAULT_VIDEO_MAX_BASE64_BYTES);
1011
+ }
1012
+
1013
+ //#endregion
1014
+ //#region src/media-understanding/runner.ts
1015
+ function buildProviderRegistry(overrides) {
1016
+ return buildMediaUnderstandingRegistry(overrides);
1017
+ }
1018
+ function normalizeMediaAttachments(ctx) {
1019
+ return normalizeAttachments(ctx);
1020
+ }
1021
+ function createMediaAttachmentCache(attachments) {
1022
+ return new MediaAttachmentCache(attachments);
1023
+ }
1024
+ const binaryCache = /* @__PURE__ */ new Map();
1025
+ const geminiProbeCache = /* @__PURE__ */ new Map();
1026
+ function expandHomeDir(value) {
1027
+ if (!value.startsWith("~")) return value;
1028
+ const home = os.homedir();
1029
+ if (value === "~") return home;
1030
+ if (value.startsWith("~/")) return path.join(home, value.slice(2));
1031
+ return value;
1032
+ }
1033
+ function hasPathSeparator(value) {
1034
+ return value.includes("/") || value.includes("\\");
1035
+ }
1036
+ function candidateBinaryNames(name) {
1037
+ if (process.platform !== "win32") return [name];
1038
+ if (path.extname(name)) return [name];
1039
+ const pathext = (process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";").map((item) => item.trim()).filter(Boolean).map((item) => item.startsWith(".") ? item : `.${item}`);
1040
+ return [name, ...Array.from(new Set(pathext)).map((item) => `${name}${item}`)];
1041
+ }
1042
+ async function isExecutable(filePath) {
1043
+ try {
1044
+ if (!(await fs$1.stat(filePath)).isFile()) return false;
1045
+ if (process.platform === "win32") return true;
1046
+ await fs$1.access(filePath, constants.X_OK);
1047
+ return true;
1048
+ } catch {
1049
+ return false;
1050
+ }
1051
+ }
1052
+ async function findBinary(name) {
1053
+ const cached = binaryCache.get(name);
1054
+ if (cached) return cached;
1055
+ const resolved = (async () => {
1056
+ const direct = expandHomeDir(name.trim());
1057
+ if (direct && hasPathSeparator(direct)) {
1058
+ for (const candidate of candidateBinaryNames(direct)) if (await isExecutable(candidate)) return candidate;
1059
+ }
1060
+ const searchName = name.trim();
1061
+ if (!searchName) return null;
1062
+ const pathEntries = (process.env.PATH ?? "").split(path.delimiter);
1063
+ const candidates = candidateBinaryNames(searchName);
1064
+ for (const entryRaw of pathEntries) {
1065
+ const entry = expandHomeDir(entryRaw.trim().replace(/^"(.*)"$/, "$1"));
1066
+ if (!entry) continue;
1067
+ for (const candidate of candidates) {
1068
+ const fullPath = path.join(entry, candidate);
1069
+ if (await isExecutable(fullPath)) return fullPath;
1070
+ }
1071
+ }
1072
+ return null;
1073
+ })();
1074
+ binaryCache.set(name, resolved);
1075
+ return resolved;
1076
+ }
1077
+ async function hasBinary(name) {
1078
+ return Boolean(await findBinary(name));
1079
+ }
1080
+ async function fileExists(filePath) {
1081
+ if (!filePath) return false;
1082
+ try {
1083
+ await fs$1.stat(filePath);
1084
+ return true;
1085
+ } catch {
1086
+ return false;
1087
+ }
1088
+ }
1089
+ function extractLastJsonObject(raw) {
1090
+ const trimmed = raw.trim();
1091
+ const start = trimmed.lastIndexOf("{");
1092
+ if (start === -1) return null;
1093
+ const slice = trimmed.slice(start);
1094
+ try {
1095
+ return JSON.parse(slice);
1096
+ } catch {
1097
+ return null;
1098
+ }
1099
+ }
1100
+ function extractGeminiResponse(raw) {
1101
+ const payload = extractLastJsonObject(raw);
1102
+ if (!payload || typeof payload !== "object") return null;
1103
+ const response = payload.response;
1104
+ if (typeof response !== "string") return null;
1105
+ return response.trim() || null;
1106
+ }
1107
+ function extractSherpaOnnxText(raw) {
1108
+ const tryParse = (value) => {
1109
+ const trimmed = value.trim();
1110
+ if (!trimmed) return null;
1111
+ const head = trimmed[0];
1112
+ if (head !== "{" && head !== "\"") return null;
1113
+ try {
1114
+ const parsed = JSON.parse(trimmed);
1115
+ if (typeof parsed === "string") return tryParse(parsed);
1116
+ if (parsed && typeof parsed === "object") {
1117
+ const text = parsed.text;
1118
+ if (typeof text === "string" && text.trim()) return text.trim();
1119
+ }
1120
+ } catch {}
1121
+ return null;
1122
+ };
1123
+ const direct = tryParse(raw);
1124
+ if (direct) return direct;
1125
+ const lines = raw.split("\n").map((line) => line.trim()).filter(Boolean);
1126
+ for (let i = lines.length - 1; i >= 0; i -= 1) {
1127
+ const parsed = tryParse(lines[i] ?? "");
1128
+ if (parsed) return parsed;
1129
+ }
1130
+ return null;
1131
+ }
1132
+ async function probeGeminiCli() {
1133
+ const cached = geminiProbeCache.get("gemini");
1134
+ if (cached) return cached;
1135
+ const resolved = (async () => {
1136
+ if (!await hasBinary("gemini")) return false;
1137
+ try {
1138
+ const { stdout } = await runExec("gemini", [
1139
+ "--output-format",
1140
+ "json",
1141
+ "ok"
1142
+ ], { timeoutMs: 8e3 });
1143
+ return Boolean(extractGeminiResponse(stdout) ?? stdout.toLowerCase().includes("ok"));
1144
+ } catch {
1145
+ return false;
1146
+ }
1147
+ })();
1148
+ geminiProbeCache.set("gemini", resolved);
1149
+ return resolved;
1150
+ }
1151
+ async function resolveLocalWhisperCppEntry() {
1152
+ if (!await hasBinary("whisper-cli")) return null;
1153
+ const envModel = process.env.WHISPER_CPP_MODEL?.trim();
1154
+ const modelPath = envModel && await fileExists(envModel) ? envModel : "/opt/homebrew/share/whisper-cpp/for-tests-ggml-tiny.bin";
1155
+ if (!await fileExists(modelPath)) return null;
1156
+ return {
1157
+ type: "cli",
1158
+ command: "whisper-cli",
1159
+ args: [
1160
+ "-m",
1161
+ modelPath,
1162
+ "-otxt",
1163
+ "-of",
1164
+ "{{OutputBase}}",
1165
+ "-np",
1166
+ "-nt",
1167
+ "{{MediaPath}}"
1168
+ ]
1169
+ };
1170
+ }
1171
+ async function resolveLocalWhisperEntry() {
1172
+ if (!await hasBinary("whisper")) return null;
1173
+ return {
1174
+ type: "cli",
1175
+ command: "whisper",
1176
+ args: [
1177
+ "--model",
1178
+ "turbo",
1179
+ "--output_format",
1180
+ "txt",
1181
+ "--output_dir",
1182
+ "{{OutputDir}}",
1183
+ "--verbose",
1184
+ "False",
1185
+ "{{MediaPath}}"
1186
+ ]
1187
+ };
1188
+ }
1189
+ async function resolveSherpaOnnxEntry() {
1190
+ if (!await hasBinary("sherpa-onnx-offline")) return null;
1191
+ const modelDir = process.env.SHERPA_ONNX_MODEL_DIR?.trim();
1192
+ if (!modelDir) return null;
1193
+ const tokens = path.join(modelDir, "tokens.txt");
1194
+ const encoder = path.join(modelDir, "encoder.onnx");
1195
+ const decoder = path.join(modelDir, "decoder.onnx");
1196
+ const joiner = path.join(modelDir, "joiner.onnx");
1197
+ if (!await fileExists(tokens)) return null;
1198
+ if (!await fileExists(encoder)) return null;
1199
+ if (!await fileExists(decoder)) return null;
1200
+ if (!await fileExists(joiner)) return null;
1201
+ return {
1202
+ type: "cli",
1203
+ command: "sherpa-onnx-offline",
1204
+ args: [
1205
+ `--tokens=${tokens}`,
1206
+ `--encoder=${encoder}`,
1207
+ `--decoder=${decoder}`,
1208
+ `--joiner=${joiner}`,
1209
+ "{{MediaPath}}"
1210
+ ]
1211
+ };
1212
+ }
1213
+ async function resolveLocalAudioEntry() {
1214
+ const sherpa = await resolveSherpaOnnxEntry();
1215
+ if (sherpa) return sherpa;
1216
+ const whisperCpp = await resolveLocalWhisperCppEntry();
1217
+ if (whisperCpp) return whisperCpp;
1218
+ return await resolveLocalWhisperEntry();
1219
+ }
1220
+ async function resolveGeminiCliEntry(_capability) {
1221
+ if (!await probeGeminiCli()) return null;
1222
+ return {
1223
+ type: "cli",
1224
+ command: "gemini",
1225
+ args: [
1226
+ "--output-format",
1227
+ "json",
1228
+ "--allowed-tools",
1229
+ "read_many_files",
1230
+ "--include-directories",
1231
+ "{{MediaDir}}",
1232
+ "{{Prompt}}",
1233
+ "Use read_many_files to read {{MediaPath}} and respond with only the text output."
1234
+ ]
1235
+ };
1236
+ }
1237
+ async function resolveKeyEntry(params) {
1238
+ const { cfg, agentDir, providerRegistry, capability } = params;
1239
+ const checkProvider = async (providerId, model) => {
1240
+ const provider = getMediaUnderstandingProvider(providerId, providerRegistry);
1241
+ if (!provider) return null;
1242
+ if (capability === "audio" && !provider.transcribeAudio) return null;
1243
+ if (capability === "image" && !provider.describeImage) return null;
1244
+ if (capability === "video" && !provider.describeVideo) return null;
1245
+ try {
1246
+ await resolveApiKeyForProvider({
1247
+ provider: providerId,
1248
+ cfg,
1249
+ agentDir
1250
+ });
1251
+ return {
1252
+ type: "provider",
1253
+ provider: providerId,
1254
+ model
1255
+ };
1256
+ } catch {
1257
+ return null;
1258
+ }
1259
+ };
1260
+ if (capability === "image") {
1261
+ const activeProvider = params.activeModel?.provider?.trim();
1262
+ if (activeProvider) {
1263
+ const activeEntry = await checkProvider(activeProvider, params.activeModel?.model);
1264
+ if (activeEntry) return activeEntry;
1265
+ }
1266
+ for (const providerId of AUTO_IMAGE_KEY_PROVIDERS) {
1267
+ const model = DEFAULT_IMAGE_MODELS[providerId];
1268
+ const entry = await checkProvider(providerId, model);
1269
+ if (entry) return entry;
1270
+ }
1271
+ return null;
1272
+ }
1273
+ if (capability === "video") {
1274
+ const activeProvider = params.activeModel?.provider?.trim();
1275
+ if (activeProvider) {
1276
+ const activeEntry = await checkProvider(activeProvider, params.activeModel?.model);
1277
+ if (activeEntry) return activeEntry;
1278
+ }
1279
+ for (const providerId of AUTO_VIDEO_KEY_PROVIDERS) {
1280
+ const entry = await checkProvider(providerId, void 0);
1281
+ if (entry) return entry;
1282
+ }
1283
+ return null;
1284
+ }
1285
+ const activeProvider = params.activeModel?.provider?.trim();
1286
+ if (activeProvider) {
1287
+ const activeEntry = await checkProvider(activeProvider, params.activeModel?.model);
1288
+ if (activeEntry) return activeEntry;
1289
+ }
1290
+ for (const providerId of AUTO_AUDIO_KEY_PROVIDERS) {
1291
+ const entry = await checkProvider(providerId, void 0);
1292
+ if (entry) return entry;
1293
+ }
1294
+ return null;
1295
+ }
1296
+ async function resolveAutoEntries(params) {
1297
+ const activeEntry = await resolveActiveModelEntry(params);
1298
+ if (activeEntry) return [activeEntry];
1299
+ if (params.capability === "audio") {
1300
+ const localAudio = await resolveLocalAudioEntry();
1301
+ if (localAudio) return [localAudio];
1302
+ }
1303
+ const gemini = await resolveGeminiCliEntry(params.capability);
1304
+ if (gemini) return [gemini];
1305
+ const keys = await resolveKeyEntry(params);
1306
+ if (keys) return [keys];
1307
+ return [];
1308
+ }
1309
+ async function resolveAutoImageModel(params) {
1310
+ const providerRegistry = buildProviderRegistry();
1311
+ const toActive = (entry) => {
1312
+ if (!entry || entry.type === "cli") return null;
1313
+ const provider = entry.provider;
1314
+ if (!provider) return null;
1315
+ const model = entry.model ?? DEFAULT_IMAGE_MODELS[provider];
1316
+ if (!model) return null;
1317
+ return {
1318
+ provider,
1319
+ model
1320
+ };
1321
+ };
1322
+ const resolvedActive = toActive(await resolveActiveModelEntry({
1323
+ cfg: params.cfg,
1324
+ agentDir: params.agentDir,
1325
+ providerRegistry,
1326
+ capability: "image",
1327
+ activeModel: params.activeModel
1328
+ }));
1329
+ if (resolvedActive) return resolvedActive;
1330
+ return toActive(await resolveKeyEntry({
1331
+ cfg: params.cfg,
1332
+ agentDir: params.agentDir,
1333
+ providerRegistry,
1334
+ capability: "image",
1335
+ activeModel: params.activeModel
1336
+ }));
1337
+ }
1338
+ async function resolveActiveModelEntry(params) {
1339
+ const activeProviderRaw = params.activeModel?.provider?.trim();
1340
+ if (!activeProviderRaw) return null;
1341
+ const providerId = normalizeMediaProviderId(activeProviderRaw);
1342
+ if (!providerId) return null;
1343
+ const provider = getMediaUnderstandingProvider(providerId, params.providerRegistry);
1344
+ if (!provider) return null;
1345
+ if (params.capability === "audio" && !provider.transcribeAudio) return null;
1346
+ if (params.capability === "image" && !provider.describeImage) return null;
1347
+ if (params.capability === "video" && !provider.describeVideo) return null;
1348
+ try {
1349
+ await resolveApiKeyForProvider({
1350
+ provider: providerId,
1351
+ cfg: params.cfg,
1352
+ agentDir: params.agentDir
1353
+ });
1354
+ } catch {
1355
+ return null;
1356
+ }
1357
+ return {
1358
+ type: "provider",
1359
+ provider: providerId,
1360
+ model: params.activeModel?.model
1361
+ };
1362
+ }
1363
+ function trimOutput(text, maxChars) {
1364
+ const trimmed = text.trim();
1365
+ if (!maxChars || trimmed.length <= maxChars) return trimmed;
1366
+ return trimmed.slice(0, maxChars).trim();
1367
+ }
1368
+ function commandBase(command) {
1369
+ return path.parse(command).name;
1370
+ }
1371
+ function findArgValue(args, keys) {
1372
+ for (let i = 0; i < args.length; i += 1) if (keys.includes(args[i] ?? "")) {
1373
+ const value = args[i + 1];
1374
+ if (value) return value;
1375
+ }
1376
+ }
1377
+ function hasArg(args, keys) {
1378
+ return args.some((arg) => keys.includes(arg));
1379
+ }
1380
+ function resolveWhisperOutputPath(args, mediaPath) {
1381
+ const outputDir = findArgValue(args, ["--output_dir", "-o"]);
1382
+ const outputFormat = findArgValue(args, ["--output_format"]);
1383
+ if (!outputDir || !outputFormat) return null;
1384
+ if (!outputFormat.split(",").map((value) => value.trim()).includes("txt")) return null;
1385
+ const base = path.parse(mediaPath).name;
1386
+ return path.join(outputDir, `${base}.txt`);
1387
+ }
1388
+ function resolveWhisperCppOutputPath(args) {
1389
+ if (!hasArg(args, ["-otxt", "--output-txt"])) return null;
1390
+ const outputBase = findArgValue(args, ["-of", "--output-file"]);
1391
+ if (!outputBase) return null;
1392
+ return `${outputBase}.txt`;
1393
+ }
1394
+ async function resolveCliOutput(params) {
1395
+ const commandId = commandBase(params.command);
1396
+ const fileOutput = commandId === "whisper-cli" ? resolveWhisperCppOutputPath(params.args) : commandId === "whisper" ? resolveWhisperOutputPath(params.args, params.mediaPath) : null;
1397
+ if (fileOutput && await fileExists(fileOutput)) try {
1398
+ const content = await fs$1.readFile(fileOutput, "utf8");
1399
+ if (content.trim()) return content.trim();
1400
+ } catch {}
1401
+ if (commandId === "gemini") {
1402
+ const response = extractGeminiResponse(params.stdout);
1403
+ if (response) return response;
1404
+ }
1405
+ if (commandId === "sherpa-onnx-offline") {
1406
+ const response = extractSherpaOnnxText(params.stdout);
1407
+ if (response) return response;
1408
+ }
1409
+ return params.stdout.trim();
1410
+ }
1411
+ function normalizeProviderQuery(options) {
1412
+ if (!options) return;
1413
+ const query = {};
1414
+ for (const [key, value] of Object.entries(options)) {
1415
+ if (value === void 0) continue;
1416
+ query[key] = value;
1417
+ }
1418
+ return Object.keys(query).length > 0 ? query : void 0;
1419
+ }
1420
+ function buildDeepgramCompatQuery(options) {
1421
+ if (!options) return;
1422
+ const query = {};
1423
+ if (typeof options.detectLanguage === "boolean") query.detect_language = options.detectLanguage;
1424
+ if (typeof options.punctuate === "boolean") query.punctuate = options.punctuate;
1425
+ if (typeof options.smartFormat === "boolean") query.smart_format = options.smartFormat;
1426
+ return Object.keys(query).length > 0 ? query : void 0;
1427
+ }
1428
+ function normalizeDeepgramQueryKeys(query) {
1429
+ const normalized = { ...query };
1430
+ if ("detectLanguage" in normalized) {
1431
+ normalized.detect_language = normalized.detectLanguage;
1432
+ delete normalized.detectLanguage;
1433
+ }
1434
+ if ("smartFormat" in normalized) {
1435
+ normalized.smart_format = normalized.smartFormat;
1436
+ delete normalized.smartFormat;
1437
+ }
1438
+ return normalized;
1439
+ }
1440
+ function resolveProviderQuery(params) {
1441
+ const { providerId, config, entry } = params;
1442
+ const mergedOptions = normalizeProviderQuery({
1443
+ ...config?.providerOptions?.[providerId],
1444
+ ...entry.providerOptions?.[providerId]
1445
+ });
1446
+ if (providerId !== "deepgram") return mergedOptions;
1447
+ let query = normalizeDeepgramQueryKeys(mergedOptions ?? {});
1448
+ const compat = buildDeepgramCompatQuery({
1449
+ ...config?.deepgram,
1450
+ ...entry.deepgram
1451
+ });
1452
+ for (const [key, value] of Object.entries(compat ?? {})) if (query[key] === void 0) query[key] = value;
1453
+ return Object.keys(query).length > 0 ? query : void 0;
1454
+ }
1455
+ function buildModelDecision(params) {
1456
+ if (params.entryType === "cli") {
1457
+ const command = params.entry.command?.trim();
1458
+ return {
1459
+ type: "cli",
1460
+ provider: command ?? "cli",
1461
+ model: params.entry.model ?? command,
1462
+ outcome: params.outcome,
1463
+ reason: params.reason
1464
+ };
1465
+ }
1466
+ const providerIdRaw = params.entry.provider?.trim();
1467
+ return {
1468
+ type: "provider",
1469
+ provider: (providerIdRaw ? normalizeMediaProviderId(providerIdRaw) : void 0) ?? providerIdRaw,
1470
+ model: params.entry.model,
1471
+ outcome: params.outcome,
1472
+ reason: params.reason
1473
+ };
1474
+ }
1475
+ function formatDecisionSummary(decision) {
1476
+ const total = decision.attachments.length;
1477
+ const success = decision.attachments.filter((entry) => entry.chosen?.outcome === "success").length;
1478
+ const chosen = decision.attachments.find((entry) => entry.chosen)?.chosen;
1479
+ const provider = chosen?.provider?.trim();
1480
+ const model = chosen?.model?.trim();
1481
+ const modelLabel = provider ? model ? `${provider}/${model}` : provider : void 0;
1482
+ const reason = decision.attachments.flatMap((entry) => entry.attempts.map((attempt) => attempt.reason).filter(Boolean)).find(Boolean);
1483
+ const shortReason = reason ? reason.split(":")[0]?.trim() : void 0;
1484
+ const countLabel = total > 0 ? ` (${success}/${total})` : "";
1485
+ const viaLabel = modelLabel ? ` via ${modelLabel}` : "";
1486
+ const reasonLabel = shortReason ? ` reason=${shortReason}` : "";
1487
+ return `${decision.capability}: ${decision.outcome}${countLabel}${viaLabel}${reasonLabel}`;
1488
+ }
1489
+ async function runProviderEntry(params) {
1490
+ const { entry, capability, cfg } = params;
1491
+ const providerIdRaw = entry.provider?.trim();
1492
+ if (!providerIdRaw) throw new Error(`Provider entry missing provider for ${capability}`);
1493
+ const providerId = normalizeMediaProviderId(providerIdRaw);
1494
+ const maxBytes = resolveMaxBytes({
1495
+ capability,
1496
+ entry,
1497
+ cfg,
1498
+ config: params.config
1499
+ });
1500
+ const maxChars = resolveMaxChars({
1501
+ capability,
1502
+ entry,
1503
+ cfg,
1504
+ config: params.config
1505
+ });
1506
+ const timeoutMs = resolveTimeoutMs(entry.timeoutSeconds ?? params.config?.timeoutSeconds ?? cfg.tools?.media?.[capability]?.timeoutSeconds, DEFAULT_TIMEOUT_SECONDS[capability]);
1507
+ const prompt = resolvePrompt(capability, entry.prompt ?? params.config?.prompt ?? cfg.tools?.media?.[capability]?.prompt, maxChars);
1508
+ if (capability === "image") {
1509
+ if (!params.agentDir) throw new Error("Image understanding requires agentDir");
1510
+ const modelId = entry.model?.trim();
1511
+ if (!modelId) throw new Error("Image understanding requires model id");
1512
+ const media = await params.cache.getBuffer({
1513
+ attachmentIndex: params.attachmentIndex,
1514
+ maxBytes,
1515
+ timeoutMs
1516
+ });
1517
+ const provider = getMediaUnderstandingProvider(providerId, params.providerRegistry);
1518
+ const result = provider?.describeImage ? await provider.describeImage({
1519
+ buffer: media.buffer,
1520
+ fileName: media.fileName,
1521
+ mime: media.mime,
1522
+ model: modelId,
1523
+ provider: providerId,
1524
+ prompt,
1525
+ timeoutMs,
1526
+ profile: entry.profile,
1527
+ preferredProfile: entry.preferredProfile,
1528
+ agentDir: params.agentDir,
1529
+ cfg: params.cfg
1530
+ }) : await describeImageWithModel({
1531
+ buffer: media.buffer,
1532
+ fileName: media.fileName,
1533
+ mime: media.mime,
1534
+ model: modelId,
1535
+ provider: providerId,
1536
+ prompt,
1537
+ timeoutMs,
1538
+ profile: entry.profile,
1539
+ preferredProfile: entry.preferredProfile,
1540
+ agentDir: params.agentDir,
1541
+ cfg: params.cfg
1542
+ });
1543
+ return {
1544
+ kind: "image.description",
1545
+ attachmentIndex: params.attachmentIndex,
1546
+ text: trimOutput(result.text, maxChars),
1547
+ provider: providerId,
1548
+ model: result.model ?? modelId
1549
+ };
1550
+ }
1551
+ const provider = getMediaUnderstandingProvider(providerId, params.providerRegistry);
1552
+ if (!provider) throw new Error(`Media provider not available: ${providerId}`);
1553
+ if (capability === "audio") {
1554
+ if (!provider.transcribeAudio) throw new Error(`Audio transcription provider "${providerId}" not available.`);
1555
+ const media = await params.cache.getBuffer({
1556
+ attachmentIndex: params.attachmentIndex,
1557
+ maxBytes,
1558
+ timeoutMs
1559
+ });
1560
+ const apiKey = requireApiKey(await resolveApiKeyForProvider({
1561
+ provider: providerId,
1562
+ cfg,
1563
+ profileId: entry.profile,
1564
+ preferredProfile: entry.preferredProfile,
1565
+ agentDir: params.agentDir
1566
+ }), providerId);
1567
+ const providerConfig = cfg.models?.providers?.[providerId];
1568
+ const baseUrl = entry.baseUrl ?? params.config?.baseUrl ?? providerConfig?.baseUrl;
1569
+ const mergedHeaders = {
1570
+ ...providerConfig?.headers,
1571
+ ...params.config?.headers,
1572
+ ...entry.headers
1573
+ };
1574
+ const headers = Object.keys(mergedHeaders).length > 0 ? mergedHeaders : void 0;
1575
+ const providerQuery = resolveProviderQuery({
1576
+ providerId,
1577
+ config: params.config,
1578
+ entry
1579
+ });
1580
+ const model = entry.model?.trim() || DEFAULT_AUDIO_MODELS[providerId] || entry.model;
1581
+ const result = await provider.transcribeAudio({
1582
+ buffer: media.buffer,
1583
+ fileName: media.fileName,
1584
+ mime: media.mime,
1585
+ apiKey,
1586
+ baseUrl,
1587
+ headers,
1588
+ model,
1589
+ language: entry.language ?? params.config?.language ?? cfg.tools?.media?.audio?.language,
1590
+ prompt,
1591
+ query: providerQuery,
1592
+ timeoutMs
1593
+ });
1594
+ return {
1595
+ kind: "audio.transcription",
1596
+ attachmentIndex: params.attachmentIndex,
1597
+ text: trimOutput(result.text, maxChars),
1598
+ provider: providerId,
1599
+ model: result.model ?? model
1600
+ };
1601
+ }
1602
+ if (!provider.describeVideo) throw new Error(`Video understanding provider "${providerId}" not available.`);
1603
+ const media = await params.cache.getBuffer({
1604
+ attachmentIndex: params.attachmentIndex,
1605
+ maxBytes,
1606
+ timeoutMs
1607
+ });
1608
+ const estimatedBase64Bytes = estimateBase64Size(media.size);
1609
+ const maxBase64Bytes = resolveVideoMaxBase64Bytes(maxBytes);
1610
+ if (estimatedBase64Bytes > maxBase64Bytes) throw new MediaUnderstandingSkipError("maxBytes", `Video attachment ${params.attachmentIndex + 1} base64 payload ${estimatedBase64Bytes} exceeds ${maxBase64Bytes}`);
1611
+ const apiKey = requireApiKey(await resolveApiKeyForProvider({
1612
+ provider: providerId,
1613
+ cfg,
1614
+ profileId: entry.profile,
1615
+ preferredProfile: entry.preferredProfile,
1616
+ agentDir: params.agentDir
1617
+ }), providerId);
1618
+ const providerConfig = cfg.models?.providers?.[providerId];
1619
+ const result = await provider.describeVideo({
1620
+ buffer: media.buffer,
1621
+ fileName: media.fileName,
1622
+ mime: media.mime,
1623
+ apiKey,
1624
+ baseUrl: providerConfig?.baseUrl,
1625
+ headers: providerConfig?.headers,
1626
+ model: entry.model,
1627
+ prompt,
1628
+ timeoutMs
1629
+ });
1630
+ return {
1631
+ kind: "video.description",
1632
+ attachmentIndex: params.attachmentIndex,
1633
+ text: trimOutput(result.text, maxChars),
1634
+ provider: providerId,
1635
+ model: result.model ?? entry.model
1636
+ };
1637
+ }
1638
+ async function runCliEntry(params) {
1639
+ const { entry, capability, cfg, ctx } = params;
1640
+ const command = entry.command?.trim();
1641
+ const args = entry.args ?? [];
1642
+ if (!command) throw new Error(`CLI entry missing command for ${capability}`);
1643
+ const maxBytes = resolveMaxBytes({
1644
+ capability,
1645
+ entry,
1646
+ cfg,
1647
+ config: params.config
1648
+ });
1649
+ const maxChars = resolveMaxChars({
1650
+ capability,
1651
+ entry,
1652
+ cfg,
1653
+ config: params.config
1654
+ });
1655
+ const timeoutMs = resolveTimeoutMs(entry.timeoutSeconds ?? params.config?.timeoutSeconds ?? cfg.tools?.media?.[capability]?.timeoutSeconds, DEFAULT_TIMEOUT_SECONDS[capability]);
1656
+ const prompt = resolvePrompt(capability, entry.prompt ?? params.config?.prompt ?? cfg.tools?.media?.[capability]?.prompt, maxChars);
1657
+ const pathResult = await params.cache.getPath({
1658
+ attachmentIndex: params.attachmentIndex,
1659
+ maxBytes,
1660
+ timeoutMs
1661
+ });
1662
+ const outputDir = await fs$1.mkdtemp(path.join(os.tmpdir(), "openclaw-media-cli-"));
1663
+ const mediaPath = pathResult.path;
1664
+ const outputBase = path.join(outputDir, path.parse(mediaPath).name);
1665
+ const templCtx = {
1666
+ ...ctx,
1667
+ MediaPath: mediaPath,
1668
+ MediaDir: path.dirname(mediaPath),
1669
+ OutputDir: outputDir,
1670
+ OutputBase: outputBase,
1671
+ Prompt: prompt,
1672
+ MaxChars: maxChars
1673
+ };
1674
+ const argv = [command, ...args].map((part, index) => index === 0 ? part : applyTemplate(part, templCtx));
1675
+ try {
1676
+ if (shouldLogVerbose()) logVerbose(`Media understanding via CLI: ${argv.join(" ")}`);
1677
+ const { stdout } = await runExec(argv[0], argv.slice(1), {
1678
+ timeoutMs,
1679
+ maxBuffer: CLI_OUTPUT_MAX_BUFFER
1680
+ });
1681
+ const text = trimOutput(await resolveCliOutput({
1682
+ command,
1683
+ args: argv.slice(1),
1684
+ stdout,
1685
+ mediaPath
1686
+ }), maxChars);
1687
+ if (!text) return null;
1688
+ return {
1689
+ kind: capability === "audio" ? "audio.transcription" : `${capability}.description`,
1690
+ attachmentIndex: params.attachmentIndex,
1691
+ text,
1692
+ provider: "cli",
1693
+ model: command
1694
+ };
1695
+ } finally {
1696
+ await fs$1.rm(outputDir, {
1697
+ recursive: true,
1698
+ force: true
1699
+ }).catch(() => {});
1700
+ }
1701
+ }
1702
+ async function runAttachmentEntries(params) {
1703
+ const { entries, capability } = params;
1704
+ const attempts = [];
1705
+ for (const entry of entries) {
1706
+ const entryType = entry.type ?? (entry.command ? "cli" : "provider");
1707
+ try {
1708
+ const result = entryType === "cli" ? await runCliEntry({
1709
+ capability,
1710
+ entry,
1711
+ cfg: params.cfg,
1712
+ ctx: params.ctx,
1713
+ attachmentIndex: params.attachmentIndex,
1714
+ cache: params.cache,
1715
+ config: params.config
1716
+ }) : await runProviderEntry({
1717
+ capability,
1718
+ entry,
1719
+ cfg: params.cfg,
1720
+ ctx: params.ctx,
1721
+ attachmentIndex: params.attachmentIndex,
1722
+ cache: params.cache,
1723
+ agentDir: params.agentDir,
1724
+ providerRegistry: params.providerRegistry,
1725
+ config: params.config
1726
+ });
1727
+ if (result) {
1728
+ const decision = buildModelDecision({
1729
+ entry,
1730
+ entryType,
1731
+ outcome: "success"
1732
+ });
1733
+ if (result.provider) decision.provider = result.provider;
1734
+ if (result.model) decision.model = result.model;
1735
+ attempts.push(decision);
1736
+ return {
1737
+ output: result,
1738
+ attempts
1739
+ };
1740
+ }
1741
+ attempts.push(buildModelDecision({
1742
+ entry,
1743
+ entryType,
1744
+ outcome: "skipped",
1745
+ reason: "empty output"
1746
+ }));
1747
+ } catch (err) {
1748
+ if (isMediaUnderstandingSkipError(err)) {
1749
+ attempts.push(buildModelDecision({
1750
+ entry,
1751
+ entryType,
1752
+ outcome: "skipped",
1753
+ reason: `${err.reason}: ${err.message}`
1754
+ }));
1755
+ if (shouldLogVerbose()) logVerbose(`Skipping ${capability} model due to ${err.reason}: ${err.message}`);
1756
+ continue;
1757
+ }
1758
+ attempts.push(buildModelDecision({
1759
+ entry,
1760
+ entryType,
1761
+ outcome: "failed",
1762
+ reason: String(err)
1763
+ }));
1764
+ if (shouldLogVerbose()) logVerbose(`${capability} understanding failed: ${String(err)}`);
1765
+ }
1766
+ }
1767
+ return {
1768
+ output: null,
1769
+ attempts
1770
+ };
1771
+ }
1772
+ async function runCapability(params) {
1773
+ const { capability, cfg, ctx } = params;
1774
+ const config = params.config ?? cfg.tools?.media?.[capability];
1775
+ if (config?.enabled === false) return {
1776
+ outputs: [],
1777
+ decision: {
1778
+ capability,
1779
+ outcome: "disabled",
1780
+ attachments: []
1781
+ }
1782
+ };
1783
+ const attachmentPolicy = config?.attachments;
1784
+ const selected = selectAttachments({
1785
+ capability,
1786
+ attachments: params.media,
1787
+ policy: attachmentPolicy
1788
+ });
1789
+ if (selected.length === 0) return {
1790
+ outputs: [],
1791
+ decision: {
1792
+ capability,
1793
+ outcome: "no-attachment",
1794
+ attachments: []
1795
+ }
1796
+ };
1797
+ if (resolveScopeDecision({
1798
+ scope: config?.scope,
1799
+ ctx
1800
+ }) === "deny") {
1801
+ if (shouldLogVerbose()) logVerbose(`${capability} understanding disabled by scope policy.`);
1802
+ return {
1803
+ outputs: [],
1804
+ decision: {
1805
+ capability,
1806
+ outcome: "scope-deny",
1807
+ attachments: selected.map((item) => ({
1808
+ attachmentIndex: item.index,
1809
+ attempts: []
1810
+ }))
1811
+ }
1812
+ };
1813
+ }
1814
+ const activeProvider = params.activeModel?.provider?.trim();
1815
+ if (capability === "image" && activeProvider) {
1816
+ if (modelSupportsVision(findModelInCatalog(await loadModelCatalog({ config: cfg }), activeProvider, params.activeModel?.model ?? ""))) {
1817
+ if (shouldLogVerbose()) logVerbose("Skipping image understanding: primary model supports vision natively");
1818
+ const model = params.activeModel?.model?.trim();
1819
+ const reason = "primary model supports vision natively";
1820
+ return {
1821
+ outputs: [],
1822
+ decision: {
1823
+ capability,
1824
+ outcome: "skipped",
1825
+ attachments: selected.map((item) => {
1826
+ const attempt = {
1827
+ type: "provider",
1828
+ provider: activeProvider,
1829
+ model: model || void 0,
1830
+ outcome: "skipped",
1831
+ reason
1832
+ };
1833
+ return {
1834
+ attachmentIndex: item.index,
1835
+ attempts: [attempt],
1836
+ chosen: attempt
1837
+ };
1838
+ })
1839
+ }
1840
+ };
1841
+ }
1842
+ }
1843
+ let resolvedEntries = resolveModelEntries({
1844
+ cfg,
1845
+ capability,
1846
+ config,
1847
+ providerRegistry: params.providerRegistry
1848
+ });
1849
+ if (resolvedEntries.length === 0) resolvedEntries = await resolveAutoEntries({
1850
+ cfg,
1851
+ agentDir: params.agentDir,
1852
+ providerRegistry: params.providerRegistry,
1853
+ capability,
1854
+ activeModel: params.activeModel
1855
+ });
1856
+ if (resolvedEntries.length === 0) return {
1857
+ outputs: [],
1858
+ decision: {
1859
+ capability,
1860
+ outcome: "skipped",
1861
+ attachments: selected.map((item) => ({
1862
+ attachmentIndex: item.index,
1863
+ attempts: []
1864
+ }))
1865
+ }
1866
+ };
1867
+ const outputs = [];
1868
+ const attachmentDecisions = [];
1869
+ for (const attachment of selected) {
1870
+ const { output, attempts } = await runAttachmentEntries({
1871
+ capability,
1872
+ cfg,
1873
+ ctx,
1874
+ attachmentIndex: attachment.index,
1875
+ agentDir: params.agentDir,
1876
+ providerRegistry: params.providerRegistry,
1877
+ cache: params.attachments,
1878
+ entries: resolvedEntries,
1879
+ config
1880
+ });
1881
+ if (output) outputs.push(output);
1882
+ attachmentDecisions.push({
1883
+ attachmentIndex: attachment.index,
1884
+ attempts,
1885
+ chosen: attempts.find((attempt) => attempt.outcome === "success")
1886
+ });
1887
+ }
1888
+ const decision = {
1889
+ capability,
1890
+ outcome: outputs.length > 0 ? "success" : "skipped",
1891
+ attachments: attachmentDecisions
1892
+ };
1893
+ if (shouldLogVerbose()) logVerbose(`Media understanding ${formatDecisionSummary(decision)}`);
1894
+ return {
1895
+ outputs,
1896
+ decision
1897
+ };
1898
+ }
1899
+
1900
+ //#endregion
1901
+ export { loadModelCatalog as _, runCapability as a, resolveConcurrency as c, resolveMediaUnderstandingScope as d, CLI_OUTPUT_MAX_BUFFER as f, findModelInCatalog as g, registerUnhandledRejectionHandler as h, resolveAutoImageModel as i, resolveTimeoutMs as l, installUnhandledRejectionHandler as m, createMediaAttachmentCache as n, isAudioAttachment as o, applyTemplate as p, normalizeMediaAttachments as r, resolveAttachmentKind as s, buildProviderRegistry as t, normalizeMediaUnderstandingChatType as u, modelSupportsVision as v };