@vibe-lark/larkpal 0.1.86 → 0.1.87

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 (208) hide show
  1. package/dist/account-id-BM1T6029-BzQ_cMoi.mjs +1 -0
  2. package/dist/activation-context--5yu1dPF-XV0Y0pTy.mjs +1 -0
  3. package/dist/anthropic-CFZUCb1w.mjs +39 -0
  4. package/dist/assistant-visible-text-DuFWokAt-BOJV_zwc.mjs +9 -0
  5. package/dist/azure-openai-responses-BEuiMaF-.mjs +1 -0
  6. package/dist/boundary-file-read-BSd9MXPy-gnNVhPKT.mjs +1 -0
  7. package/dist/browser-lifecycle-cleanup-BdNsMhMD-BM97qA_M.mjs +1 -0
  8. package/dist/build-Bkj0hOS2.mjs +3 -0
  9. package/dist/bundled-compat-BpaDaAAu-DJtrIX6i.mjs +27 -0
  10. package/dist/bundled-dir-U738ay4K-BxbzrJOo.mjs +1 -0
  11. package/dist/call-DimWbpgJ-B4pv55RH.mjs +20 -0
  12. package/dist/channel-bootstrap.runtime-BVclcGv1-CEZ0-JP9.mjs +1 -0
  13. package/dist/channel-bootstrap.runtime-Cwcr38m2-Dt6QlQkX.mjs +1 -0
  14. package/dist/chunk-DHbaKqs-.mjs +1 -0
  15. package/dist/cli.mjs +7 -92
  16. package/dist/command-format-LSnUCVVF-Dn4h9IOh.mjs +16 -0
  17. package/dist/config-Bim2pi8a-03N-28sw.mjs +1 -0
  18. package/dist/delivery-context.shared-j5hC5qb1-BSLQG47q.mjs +1 -0
  19. package/dist/diagnostic-ClMwNnUA-BMKvPQJT.mjs +1 -0
  20. package/dist/dist-J5UB83Ws.mjs +601 -0
  21. package/dist/dist-coestTs9.mjs +5 -0
  22. package/dist/env-api-keys-Cuz5irWW.mjs +1 -0
  23. package/dist/event-stream-B7Ei41Bu.mjs +1 -0
  24. package/dist/facade-loader-DFzIYYt_-4bzFvy-b.mjs +1 -0
  25. package/dist/from-Ba69_5cR.mjs +14 -0
  26. package/dist/gateway-method-policy-C7rf0SeV-CTJcMQCE.mjs +1 -0
  27. package/dist/github-copilot-headers-BfhryVuU.mjs +1 -0
  28. package/dist/google-ABo-1guT.mjs +1 -0
  29. package/dist/google-gemini-cli-CGlN1zUA.mjs +2 -0
  30. package/dist/google-shared-C60sNhwd.mjs +301 -0
  31. package/dist/google-vertex-De0nAItu.mjs +1 -0
  32. package/dist/hash-Dw-N8Y9l.mjs +1 -0
  33. package/dist/headers-Bpsp70B9.mjs +1 -0
  34. package/dist/home-dir-C44RaPME-B5iLWwCq.mjs +1 -0
  35. package/dist/ids-BPsM98Uu-CJBJAeVC.mjs +1 -0
  36. package/dist/image-2w3cApg7-CrpUMCvm.mjs +3 -0
  37. package/dist/interactive-init-C5MFL5MW.mjs +8 -0
  38. package/dist/io-CH2g3vsv-JJtUIa_U.mjs +10 -0
  39. package/dist/jiti-loader-cache-Bat69wam-DNIteTtO.mjs +9 -0
  40. package/dist/json-file-BQRNuxmK-hRjIgOXI.mjs +1 -0
  41. package/dist/json-parse-BESd8UAM.mjs +3 -0
  42. package/dist/jws-YaZ38F_i.mjs +12 -0
  43. package/dist/lark-cli-provider-BLMxH6CN.mjs +4 -0
  44. package/dist/lark-logger-xpMKNNtY.mjs +1 -0
  45. package/dist/live-smoke-DpURW676.mjs +33 -0
  46. package/dist/load-context-mb7uvLSn-3xYwSnOZ.mjs +1 -0
  47. package/dist/loader-708jrx4Y-BbJRXNlQ.mjs +4 -0
  48. package/dist/main.mjs +153 -74571
  49. package/dist/manifest-registry-_hxKCS2K-OL8KK_o4.mjs +15 -0
  50. package/dist/mcp-server.mjs +4 -527
  51. package/dist/message-channel-Bk_YHfQg-n2Hw2Y0L.mjs +1 -0
  52. package/dist/message-channel-core-DTA--Gjh-CIh10vfo.mjs +1 -0
  53. package/dist/message.config.runtime-K-k4XOyq-F_h0Cgkl.mjs +1 -0
  54. package/dist/message.gateway.runtime-DqHOHRTQ-ge4c5p4s.mjs +1 -0
  55. package/dist/mistral-DyL3Zo1b.mjs +7 -0
  56. package/dist/model-auth-env-oyg2Hexc-DJbt9J3o.mjs +1 -0
  57. package/dist/models-config-BmpSQJQF-BL6S5qAo.mjs +1 -0
  58. package/dist/models-config.runtime-SOhLEw-f.mjs +1 -0
  59. package/dist/multipart-parser-B9dwXBqu.mjs +2 -0
  60. package/dist/oauth-25y2wc7K.mjs +75 -0
  61. package/dist/openai-C-rgGb7X.mjs +16 -0
  62. package/dist/openai-codex-responses-BbyAPsP1.mjs +7 -0
  63. package/dist/openai-completions-Bu5qvQzb.mjs +5 -0
  64. package/dist/openai-responses-pIdwQBc4.mjs +1 -0
  65. package/dist/openai-responses-shared-DqW1JSux.mjs +10 -0
  66. package/dist/paths-D6msg0S1-BO4XgM1u.mjs +1 -0
  67. package/dist/paths-D92DjaZ--DdtJ-zYp.mjs +1 -0
  68. package/dist/pi-model-discovery-Bd0TWzo8-DvSM0eWu.mjs +1 -0
  69. package/dist/pi-model-discovery-runtime-PrjWOmsV.mjs +1 -0
  70. package/dist/pi-tools.before-tool-call.runtime-Bn7uqKie-WPxU5oNX.mjs +2 -0
  71. package/dist/plugin-auto-enable-DdH3n9V8-Dr_bUXkG.mjs +1 -0
  72. package/dist/process-scoped-map-B2cWkYET-Co-i-MXA.mjs +1 -0
  73. package/dist/provider-discovery.runtime-DY0VWQ81.mjs +1 -0
  74. package/dist/provider-model-compat-CFqcq0it-BUwZENrz.mjs +1 -0
  75. package/dist/provider-runtime-C8rljsNs-BDvu6FW3.mjs +1 -0
  76. package/dist/provider-runtime-CT50mNIX-DImw7ZZu.mjs +79 -0
  77. package/dist/provider-stream-COLujAAo-Dpq1DSIk.mjs +248 -0
  78. package/dist/providers.runtime-Ba7tOlq7-B4t6ywCr.mjs +1 -0
  79. package/dist/public-surface-loader-BVl0NQAE-TfJ3izj1.mjs +1 -0
  80. package/dist/resolve-C33B7eeu-DZM_z6Wr.mjs +1 -0
  81. package/dist/runtime-Cym-fqI8-1GOIuRRQ.mjs +1 -0
  82. package/dist/runtime-channel-state-CohMybAh-BBzhl07Q.mjs +1 -0
  83. package/dist/runtime-snapshot-C54O1-gI-DxusscPf.mjs +1 -0
  84. package/dist/runtime-state-IBOIXKOx-Cw1GA1td.mjs +1 -0
  85. package/dist/runtime-web-tools-fallback.runtime-Ca-qn1mj-BsYE2gOd.mjs +1 -0
  86. package/dist/runtime-web-tools-manifest.runtime-BgxQTjmq-P6MKP9gQ.mjs +1 -0
  87. package/dist/runtime-web-tools-public-artifacts.runtime-D9qcoWIX-5VoyjouO.mjs +1 -0
  88. package/dist/session-archive.runtime-B52_5vs4-cU2tYbBz.mjs +1 -0
  89. package/dist/session-key-Cn2QoOyX-QZeYmbxd.mjs +1 -0
  90. package/dist/session-transcript-files.fs-DEeFXruQ-CXIAFSsr.mjs +1 -0
  91. package/dist/src-CCDx_C-U.mjs +3 -0
  92. package/dist/src-DACmA9V6.mjs +5 -0
  93. package/dist/subagent-announce-L5WsQatW--rMn240x.mjs +2 -0
  94. package/dist/subagent-announce.registry.runtime-DiqZyeTs-DNfNHsls.mjs +1 -0
  95. package/dist/subagent-registry-steer-runtime-DFgZFC0j-XYS1_qwl.mjs +1 -0
  96. package/dist/subagent-system-prompt-C1qnN--K-CsU4f97T.mjs +23 -0
  97. package/dist/target-parsing-loaded-DKkb6jJY-B830OA1a.mjs +12 -0
  98. package/dist/task-registry-delivery-runtime-Dd1CUkZF-B2Hj2k8C.mjs +16 -0
  99. package/dist/task-registry-delivery-runtime-ragbeVx5-Bdvo2Q5u.mjs +1 -0
  100. package/dist/thinking-Bh-7MqXz-uApNUe6g.mjs +1 -0
  101. package/dist/transcript-E_-ISOkD-VTwb782D.mjs +5 -0
  102. package/dist/transcript.runtime-BqhvZZdl-B4E0TiX5.mjs +1 -0
  103. package/dist/transform-messages-BTA3xbAI.mjs +1 -0
  104. package/dist/web-provider-public-artifacts-BlpRwIUS-DbVhDOrY.mjs +1 -0
  105. package/dist/web-search-providers.runtime--0aUtC3b-Bjh4Bmrz.mjs +1 -0
  106. package/package.json +2 -3
  107. package/dist/account-id-BM1T6029-DYjVxojW.mjs +0 -46
  108. package/dist/activation-context--5yu1dPF-Bwsn3moT.mjs +0 -172
  109. package/dist/anthropic-TH8ERTXK.mjs +0 -5962
  110. package/dist/assistant-visible-text-DuFWokAt-CsbII5KS.mjs +0 -596
  111. package/dist/azure-openai-responses-Bt_Ag9Er.mjs +0 -166
  112. package/dist/boundary-file-read-BSd9MXPy--KThL5e6.mjs +0 -594
  113. package/dist/browser-lifecycle-cleanup-BdNsMhMD-O3tnAM4i.mjs +0 -60
  114. package/dist/build-DgTrEpge.mjs +0 -3333
  115. package/dist/bundled-compat-BpaDaAAu-D7oazKjD.mjs +0 -5216
  116. package/dist/bundled-dir-U738ay4K-DXK0q_TV.mjs +0 -258
  117. package/dist/call-DimWbpgJ-ColD4W-y.mjs +0 -9993
  118. package/dist/channel-bootstrap.runtime-BVclcGv1-DJv_Z-Kr.mjs +0 -2
  119. package/dist/channel-bootstrap.runtime-Cwcr38m2-VRfVCR-i.mjs +0 -33
  120. package/dist/chunk-D6SyT4dJ.mjs +0 -36
  121. package/dist/command-format-LSnUCVVF-BQ2SMKka.mjs +0 -685
  122. package/dist/config-Bim2pi8a-BQUdfiEi.mjs +0 -9
  123. package/dist/delivery-context.shared-j5hC5qb1-CI83RXXZ.mjs +0 -72
  124. package/dist/diagnostic-ClMwNnUA-D6nUtLnb.mjs +0 -140
  125. package/dist/dist-CEGw8-2W.mjs +0 -429
  126. package/dist/dist-DD2aJ2UL.mjs +0 -125135
  127. package/dist/env-api-keys-BVvSg7T2.mjs +0 -68
  128. package/dist/event-stream-xaQWmyas.mjs +0 -15226
  129. package/dist/facade-loader-DFzIYYt_-CIr4HKtE.mjs +0 -194
  130. package/dist/from-DF7cl2wz.mjs +0 -3842
  131. package/dist/gateway-method-policy-C7rf0SeV-CJQMEYIE.mjs +0 -28
  132. package/dist/github-copilot-headers-DjqWtUoP.mjs +0 -22
  133. package/dist/google-C2pVrgBZ.mjs +0 -336
  134. package/dist/google-gemini-cli-BBxgS5Ho.mjs +0 -623
  135. package/dist/google-shared-BsWgwEk1.mjs +0 -22791
  136. package/dist/google-vertex-BsVLJrrC.mjs +0 -358
  137. package/dist/hash-DAFtW_W7.mjs +0 -16
  138. package/dist/headers-R3HdCbAE.mjs +0 -8
  139. package/dist/home-dir-C44RaPME-CBRS4HLP.mjs +0 -93
  140. package/dist/ids-BPsM98Uu-CwuxvUai.mjs +0 -77
  141. package/dist/image-2w3cApg7-CxpHvoB5.mjs +0 -207
  142. package/dist/interactive-init-BXQBalNr.mjs +0 -450
  143. package/dist/io-CH2g3vsv-BOGlLlB8.mjs +0 -26218
  144. package/dist/jiti-loader-cache-Bat69wam-D6hCxboy.mjs +0 -5049
  145. package/dist/json-file-BQRNuxmK-DhJM5NsG.mjs +0 -108
  146. package/dist/json-parse-v_HIJjjI.mjs +0 -381
  147. package/dist/jws-GFcTvvVT.mjs +0 -2291
  148. package/dist/lark-cli-provider-BARgbbmo.mjs +0 -554
  149. package/dist/lark-logger-D7_pEVQc.mjs +0 -143
  150. package/dist/live-smoke-BhkBOcH9.mjs +0 -7135
  151. package/dist/load-context-mb7uvLSn-B10MAi3I.mjs +0 -29
  152. package/dist/loader-708jrx4Y-BOswuvpe.mjs +0 -5053
  153. package/dist/manifest-registry-_hxKCS2K-CZdeyN0f.mjs +0 -3512
  154. package/dist/message-channel-Bk_YHfQg-AeNrPPpp.mjs +0 -50
  155. package/dist/message-channel-core-DTA--Gjh-CY4Tkb7N.mjs +0 -29
  156. package/dist/message.config.runtime-K-k4XOyq-DZTmXomP.mjs +0 -2
  157. package/dist/message.gateway.runtime-DqHOHRTQ-DH4ml0YF.mjs +0 -2
  158. package/dist/mistral-CaR4DiLu.mjs +0 -28657
  159. package/dist/model-auth-env-oyg2Hexc-DU_rOUU5.mjs +0 -1306
  160. package/dist/models-config-BmpSQJQF-Gfvh1n3A.mjs +0 -1282
  161. package/dist/models-config.runtime-BsU_22xk.mjs +0 -2
  162. package/dist/multipart-parser-DedmaB5g.mjs +0 -294
  163. package/dist/oauth-DOJeGfcE.mjs +0 -6392
  164. package/dist/openai-BDtIh3Ja.mjs +0 -6693
  165. package/dist/openai-codex-responses-C5EORu31.mjs +0 -664
  166. package/dist/openai-completions-CR_cS6gX.mjs +0 -669
  167. package/dist/openai-responses-oGxwZyuC.mjs +0 -184
  168. package/dist/openai-responses-shared-BixMSDZE.mjs +0 -398
  169. package/dist/paths-D6msg0S1-C2lYuisN.mjs +0 -189
  170. package/dist/paths-D92DjaZ--CTOESW2b.mjs +0 -192
  171. package/dist/pi-model-discovery-Bd0TWzo8-BFsJmeMb.mjs +0 -227
  172. package/dist/pi-model-discovery-runtime-CCCZxkd8.mjs +0 -2
  173. package/dist/pi-tools.before-tool-call.runtime-Bn7uqKie-C5ewk8kK.mjs +0 -399
  174. package/dist/plugin-auto-enable-DdH3n9V8-DsA1isaF.mjs +0 -1456
  175. package/dist/process-scoped-map-B2cWkYET-CXwUZ8CZ.mjs +0 -61
  176. package/dist/provider-discovery.runtime-BPzz1PFj.mjs +0 -58
  177. package/dist/provider-model-compat-CFqcq0it-BDDuBI3A.mjs +0 -118
  178. package/dist/provider-runtime-C8rljsNs-CIT93zoy.mjs +0 -2
  179. package/dist/provider-runtime-CT50mNIX-BwEV6GyO.mjs +0 -573
  180. package/dist/provider-stream-COLujAAo-CbJPDngm.mjs +0 -35449
  181. package/dist/providers.runtime-Ba7tOlq7-CXkhkzU9.mjs +0 -219
  182. package/dist/public-surface-loader-BVl0NQAE-C0piXtsT.mjs +0 -117
  183. package/dist/resolve-C33B7eeu-BNvYTl6k.mjs +0 -1041
  184. package/dist/runtime-Cym-fqI8-DaSDMH-a.mjs +0 -120
  185. package/dist/runtime-channel-state-CohMybAh-hXR6y5Gx.mjs +0 -19
  186. package/dist/runtime-snapshot-C54O1-gI-40cbyi7P.mjs +0 -677
  187. package/dist/runtime-state-IBOIXKOx-Bf9tcLvc.mjs +0 -10
  188. package/dist/runtime-web-tools-fallback.runtime-Ca-qn1mj-BCVImm7a.mjs +0 -39
  189. package/dist/runtime-web-tools-manifest.runtime-BgxQTjmq-Cb4nJkRT.mjs +0 -2
  190. package/dist/runtime-web-tools-public-artifacts.runtime-D9qcoWIX-BrQdXzOQ.mjs +0 -2
  191. package/dist/session-archive.runtime-B52_5vs4-BG-_IwNJ.mjs +0 -2
  192. package/dist/session-key-Cn2QoOyX-CuHbJMgR.mjs +0 -82
  193. package/dist/session-transcript-files.fs-DEeFXruQ-B1PF6nLy.mjs +0 -147
  194. package/dist/src-BgCX0MLG.mjs +0 -813
  195. package/dist/src-DYbqlAqf.mjs +0 -1177
  196. package/dist/subagent-announce-L5WsQatW-CQWI9GMd.mjs +0 -344
  197. package/dist/subagent-announce.registry.runtime-DiqZyeTs-BKuniyi3.mjs +0 -28
  198. package/dist/subagent-registry-steer-runtime-DFgZFC0j-BhBz0roy.mjs +0 -211
  199. package/dist/subagent-system-prompt-C1qnN--K-DpnTFP47.mjs +0 -3061
  200. package/dist/target-parsing-loaded-DKkb6jJY-BMD4CkpS.mjs +0 -1002
  201. package/dist/task-registry-delivery-runtime-Dd1CUkZF-C8U40a3O.mjs +0 -2950
  202. package/dist/task-registry-delivery-runtime-ragbeVx5-CNbFAkjD.mjs +0 -2
  203. package/dist/thinking-Bh-7MqXz-D3woGbO7.mjs +0 -2
  204. package/dist/transcript-E_-ISOkD-DWCfZP2p.mjs +0 -2019
  205. package/dist/transcript.runtime-BqhvZZdl-BPy42vBP.mjs +0 -2
  206. package/dist/transform-messages-DbhIzTxq.mjs +0 -207
  207. package/dist/web-provider-public-artifacts-BlpRwIUS-CGPSV4W2.mjs +0 -295
  208. package/dist/web-search-providers.runtime--0aUtC3b-DyuhC95V.mjs +0 -200
@@ -1,2950 +0,0 @@
1
- import { c as normalizeOptionalString, o as normalizeLowercaseStringOrEmpty } from "./home-dir-C44RaPME-CBRS4HLP.mjs";
2
- import { o as resolveStateDir } from "./paths-D92DjaZ--CTOESW2b.mjs";
3
- import { n as normalizeAccountId } from "./account-id-BM1T6029-DYjVxojW.mjs";
4
- import { c as resolveConfigDir, l as resolveUserPath } from "./bundled-dir-U738ay4K-DXK0q_TV.mjs";
5
- import { S as resolveSilentReplySettings, _ as hasReplyChannelData, a as shouldSuppressReasoningPayload, b as renderMessagePresentationFallbackText, c as compileGlobPatterns, d as mergeAlsoAllowPolicy, f as normalizeToolName, g as hasMessagePresentationBlocks, h as hasInteractiveReplyBlocks, i as isRenderablePayload, l as matchesAnyGlobPattern, o as parseInlineDirectives, p as resolveToolProfilePolicy, r as formatBtwTextForExternalDelivery, s as buildOutboundSessionContext, u as expandToolGroups, v as hasReplyPayloadContent, w as isSilentReplyPayloadText, x as resolveSilentReplyRewriteText, y as normalizeMessagePresentation } from "./target-parsing-loaded-DKkb6jJY-BMD4CkpS.mjs";
6
- import { D as resolveAccountEntry } from "./io-CH2g3vsv-BOGlLlB8.mjs";
7
- import { Mt as formatErrorMessage, St as createSubsystemLogger, jt as resolvePreferredOpenClawTmpDir } from "./bundled-compat-BpaDaAAu-D7oazKjD.mjs";
8
- import "./message-channel-core-DTA--Gjh-CY4Tkb7N.mjs";
9
- import { c as normalizeMessageChannel, i as isDeliverableMessageChannel, n as GATEWAY_CLIENT_MODES, r as GATEWAY_CLIENT_NAMES, s as listDeliverableMessageChannels } from "./message-channel-Bk_YHfQg-AeNrPPpp.mjs";
10
- import { P as defaultRuntime } from "./manifest-registry-_hxKCS2K-CZdeyN0f.mjs";
11
- import { a as hasNodeErrorCode, c as isSymlinkOpenError, i as sameFileIdentity, o as isNotFoundPathError } from "./boundary-file-read-BSd9MXPy--KThL5e6.mjs";
12
- import { S as listChannelPlugins, b as getChannelPlugin, d as resolveAgentWorkspaceDir, u as resolveAgentConfig, x as getLoadedChannelPlugin, y as logVerbose } from "./runtime-snapshot-C54O1-gI-40cbyi7P.mjs";
13
- import { r as getActivePluginRegistry, t as getActivePluginChannelRegistry } from "./runtime-Cym-fqI8-DaSDMH-a.mjs";
14
- import { c as createInternalHookEvent, d as getGlobalHookRunner, l as triggerInternalHook } from "./loader-708jrx4Y-BOswuvpe.mjs";
15
- import { c as parseThreadSessionSuffix, s as parseRawSessionConversationRef } from "./session-key-Cn2QoOyX-CuHbJMgR.mjs";
16
- import "./paths-D6msg0S1-C2lYuisN.mjs";
17
- import { i as resolveSessionConversation, r as resolveMirroredTranscriptText } from "./transcript-E_-ISOkD-DWCfZP2p.mjs";
18
- import "./delivery-context.shared-j5hC5qb1-CI83RXXZ.mjs";
19
- import { t as formatCliCommand } from "./command-format-LSnUCVVF-BQ2SMKka.mjs";
20
- import { t as bootstrapOutboundChannelPlugin } from "./channel-bootstrap.runtime-Cwcr38m2-VRfVCR-i.mjs";
21
- import fs, { constants } from "node:fs";
22
- import path from "node:path";
23
- import { URL, fileURLToPath } from "node:url";
24
- import fs$1 from "node:fs/promises";
25
- import os from "node:os";
26
- import "node:child_process";
27
- import { createHash, randomUUID } from "node:crypto";
28
- import "node:stream/promises";
29
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/fences-CcpA8d2y.js
30
- function parseFenceSpans(buffer) {
31
- const spans = [];
32
- let open;
33
- let offset = 0;
34
- while (offset <= buffer.length) {
35
- const nextNewline = buffer.indexOf("\n", offset);
36
- const lineEnd = nextNewline === -1 ? buffer.length : nextNewline;
37
- const line = buffer.slice(offset, lineEnd);
38
- const match = line.match(/^( {0,3})(`{3,}|~{3,})(.*)$/);
39
- if (match) {
40
- const indent = match[1];
41
- const marker = match[2];
42
- const markerChar = marker[0];
43
- const markerLen = marker.length;
44
- if (!open) open = {
45
- start: offset,
46
- markerChar,
47
- markerLen,
48
- openLine: line,
49
- marker,
50
- indent
51
- };
52
- else if (open.markerChar === markerChar && markerLen >= open.markerLen) {
53
- const end = lineEnd;
54
- spans.push({
55
- start: open.start,
56
- end,
57
- openLine: open.openLine,
58
- marker: open.marker,
59
- indent: open.indent
60
- });
61
- open = void 0;
62
- }
63
- }
64
- if (nextNewline === -1) break;
65
- offset = nextNewline + 1;
66
- }
67
- if (open) spans.push({
68
- start: open.start,
69
- end: buffer.length,
70
- openLine: open.openLine,
71
- marker: open.marker,
72
- indent: open.indent
73
- });
74
- return spans;
75
- }
76
- function findFenceSpanAt(spans, index) {
77
- let low = 0;
78
- let high = spans.length - 1;
79
- while (low <= high) {
80
- const mid = Math.floor((low + high) / 2);
81
- const span = spans[mid];
82
- if (!span) break;
83
- if (index <= span.start) {
84
- high = mid - 1;
85
- continue;
86
- }
87
- if (index >= span.end) {
88
- low = mid + 1;
89
- continue;
90
- }
91
- return span;
92
- }
93
- }
94
- function isSafeFenceBreak(spans, index) {
95
- return !findFenceSpanAt(spans, index);
96
- }
97
- //#endregion
98
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/channel-streaming-Be5llNGp.js
99
- function asObjectRecord(value) {
100
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
101
- }
102
- function asTextChunkMode(value) {
103
- return value === "length" || value === "newline" ? value : void 0;
104
- }
105
- function getChannelStreamingConfigObject(entry) {
106
- const streaming = asObjectRecord(entry?.streaming);
107
- return streaming ? streaming : void 0;
108
- }
109
- function resolveChannelStreamingChunkMode(entry) {
110
- return asTextChunkMode(getChannelStreamingConfigObject(entry)?.chunkMode) ?? asTextChunkMode(entry?.chunkMode);
111
- }
112
- //#endregion
113
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/text-chunking-RDGPC8zE.js
114
- function chunkTextByBreakResolver(text, limit, resolveBreakIndex) {
115
- if (!text) return [];
116
- if (limit <= 0 || text.length <= limit) return [text];
117
- const chunks = [];
118
- let remaining = text;
119
- while (remaining.length > limit) {
120
- const candidateBreak = resolveBreakIndex(remaining.slice(0, limit));
121
- const breakIdx = Number.isFinite(candidateBreak) && candidateBreak > 0 && candidateBreak <= limit ? candidateBreak : limit;
122
- const chunk = remaining.slice(0, breakIdx).trimEnd();
123
- if (chunk.length > 0) chunks.push(chunk);
124
- const brokeOnSeparator = breakIdx < remaining.length && /\s/.test(remaining[breakIdx]);
125
- const nextStart = Math.min(remaining.length, breakIdx + (brokeOnSeparator ? 1 : 0));
126
- remaining = remaining.slice(nextStart).trimStart();
127
- }
128
- if (remaining.length) chunks.push(remaining);
129
- return chunks;
130
- }
131
- //#endregion
132
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/chunk-CReBKZas.js
133
- const DEFAULT_CHUNK_LIMIT = 4e3;
134
- const DEFAULT_CHUNK_MODE = "length";
135
- function resolveChunkLimitForProvider(cfgSection, accountId) {
136
- if (!cfgSection) return;
137
- const normalizedAccountId = normalizeAccountId(accountId);
138
- const accounts = cfgSection.accounts;
139
- if (accounts && typeof accounts === "object") {
140
- const direct = resolveAccountEntry(accounts, normalizedAccountId);
141
- if (typeof direct?.textChunkLimit === "number") return direct.textChunkLimit;
142
- }
143
- return cfgSection.textChunkLimit;
144
- }
145
- function resolveTextChunkLimit(cfg, provider, accountId, opts) {
146
- const fallback = typeof opts?.fallbackLimit === "number" && opts.fallbackLimit > 0 ? opts.fallbackLimit : DEFAULT_CHUNK_LIMIT;
147
- const providerOverride = (() => {
148
- if (!provider || provider === "webchat") return;
149
- return resolveChunkLimitForProvider((cfg?.channels)?.[provider] ?? cfg?.[provider], accountId);
150
- })();
151
- if (typeof providerOverride === "number" && providerOverride > 0) return providerOverride;
152
- return fallback;
153
- }
154
- function resolveChunkModeForProvider(cfgSection, accountId) {
155
- if (!cfgSection) return;
156
- const normalizedAccountId = normalizeAccountId(accountId);
157
- const accounts = cfgSection.accounts;
158
- if (accounts && typeof accounts === "object") {
159
- const directMode = resolveChannelStreamingChunkMode(resolveAccountEntry(accounts, normalizedAccountId));
160
- if (directMode) return directMode;
161
- }
162
- return resolveChannelStreamingChunkMode(cfgSection) ?? cfgSection.chunkMode;
163
- }
164
- function resolveChunkMode(cfg, provider, accountId) {
165
- if (!provider || provider === "webchat") return DEFAULT_CHUNK_MODE;
166
- return resolveChunkModeForProvider((cfg?.channels)?.[provider] ?? cfg?.[provider], accountId) ?? DEFAULT_CHUNK_MODE;
167
- }
168
- /**
169
- * Split text into chunks on paragraph boundaries (blank lines), preserving lists and
170
- * single-newline line wraps inside paragraphs.
171
- *
172
- * - Only breaks at paragraph separators ("\n\n" or more, allowing whitespace on blank lines)
173
- * - Packs multiple paragraphs into a single chunk up to `limit`
174
- * - Falls back to length-based splitting when a single paragraph exceeds `limit`
175
- * (unless `splitLongParagraphs` is disabled)
176
- */
177
- function chunkByParagraph(text, limit, opts) {
178
- if (!text) return [];
179
- if (limit <= 0) return [text];
180
- const splitLongParagraphs = opts?.splitLongParagraphs !== false;
181
- const normalized = text.replace(/\r\n?/g, "\n");
182
- if (!/\n[\t ]*\n+/.test(normalized)) {
183
- if (normalized.length <= limit) return [normalized];
184
- if (!splitLongParagraphs) return [normalized];
185
- return chunkText(normalized, limit);
186
- }
187
- const spans = parseFenceSpans(normalized);
188
- const parts = [];
189
- const re = /\n[\t ]*\n+/g;
190
- let lastIndex = 0;
191
- for (const match of normalized.matchAll(re)) {
192
- const idx = match.index ?? 0;
193
- if (!isSafeFenceBreak(spans, idx)) continue;
194
- parts.push(normalized.slice(lastIndex, idx));
195
- lastIndex = idx + match[0].length;
196
- }
197
- parts.push(normalized.slice(lastIndex));
198
- const chunks = [];
199
- for (const part of parts) {
200
- const paragraph = part.replace(/\s+$/g, "");
201
- if (!paragraph.trim()) continue;
202
- if (paragraph.length <= limit) chunks.push(paragraph);
203
- else if (!splitLongParagraphs) chunks.push(paragraph);
204
- else chunks.push(...chunkText(paragraph, limit));
205
- }
206
- return chunks;
207
- }
208
- function chunkMarkdownTextWithMode(text, limit, mode) {
209
- if (mode === "newline") {
210
- const paragraphChunks = chunkByParagraph(text, limit, { splitLongParagraphs: false });
211
- const out = [];
212
- for (const chunk of paragraphChunks) {
213
- const nested = chunkMarkdownText(chunk, limit);
214
- if (!nested.length && chunk) out.push(chunk);
215
- else out.push(...nested);
216
- }
217
- return out;
218
- }
219
- return chunkMarkdownText(text, limit);
220
- }
221
- function resolveChunkEarlyReturn(text, limit) {
222
- if (!text) return [];
223
- if (limit <= 0) return [text];
224
- if (text.length <= limit) return [text];
225
- }
226
- function chunkText(text, limit) {
227
- const early = resolveChunkEarlyReturn(text, limit);
228
- if (early) return early;
229
- return chunkTextByBreakResolver(text, limit, (window) => {
230
- const { lastNewline, lastWhitespace } = scanParenAwareBreakpoints(window, 0, window.length);
231
- return lastNewline > 0 ? lastNewline : lastWhitespace;
232
- });
233
- }
234
- function chunkMarkdownText(text, limit) {
235
- const early = resolveChunkEarlyReturn(text, limit);
236
- if (early) return early;
237
- const chunks = [];
238
- const spans = parseFenceSpans(text);
239
- let start = 0;
240
- let reopenFence;
241
- while (start < text.length) {
242
- const reopenPrefix = reopenFence ? `${reopenFence.openLine}\n` : "";
243
- const contentLimit = Math.max(1, limit - reopenPrefix.length);
244
- if (text.length - start <= contentLimit) {
245
- const finalChunk = `${reopenPrefix}${text.slice(start)}`;
246
- if (finalChunk.length > 0) chunks.push(finalChunk);
247
- break;
248
- }
249
- const windowEnd = Math.min(text.length, start + contentLimit);
250
- const softBreak = pickSafeBreakIndex(text, start, windowEnd, spans);
251
- let breakIdx = softBreak > start ? softBreak : windowEnd;
252
- const initialFence = isSafeFenceBreak(spans, breakIdx) ? void 0 : findFenceSpanAt(spans, breakIdx);
253
- let fenceToSplit = initialFence;
254
- if (initialFence) {
255
- const closeLine = `${initialFence.indent}${initialFence.marker}`;
256
- const maxIdxIfNeedNewline = start + (contentLimit - (closeLine.length + 1));
257
- if (maxIdxIfNeedNewline <= start) {
258
- fenceToSplit = void 0;
259
- breakIdx = windowEnd;
260
- } else {
261
- const minProgressIdx = Math.min(text.length, Math.max(start + 1, initialFence.start + initialFence.openLine.length + 2));
262
- const maxIdxIfAlreadyNewline = start + (contentLimit - closeLine.length);
263
- let pickedNewline = false;
264
- let lastNewline = text.lastIndexOf("\n", Math.max(start, maxIdxIfAlreadyNewline - 1));
265
- while (lastNewline >= start) {
266
- const candidateBreak = lastNewline + 1;
267
- if (candidateBreak < minProgressIdx) break;
268
- const candidateFence = findFenceSpanAt(spans, candidateBreak);
269
- if (candidateFence && candidateFence.start === initialFence.start) {
270
- breakIdx = candidateBreak;
271
- pickedNewline = true;
272
- break;
273
- }
274
- lastNewline = text.lastIndexOf("\n", lastNewline - 1);
275
- }
276
- if (!pickedNewline) if (minProgressIdx > maxIdxIfAlreadyNewline) {
277
- fenceToSplit = void 0;
278
- breakIdx = windowEnd;
279
- } else breakIdx = Math.max(minProgressIdx, maxIdxIfNeedNewline);
280
- }
281
- const fenceAtBreak = findFenceSpanAt(spans, breakIdx);
282
- fenceToSplit = fenceAtBreak && fenceAtBreak.start === initialFence.start ? fenceAtBreak : void 0;
283
- }
284
- const rawContent = text.slice(start, breakIdx);
285
- if (!rawContent) break;
286
- let rawChunk = `${reopenPrefix}${rawContent}`;
287
- const brokeOnSeparator = breakIdx < text.length && /\s/.test(text[breakIdx]);
288
- let nextStart = Math.min(text.length, breakIdx + (brokeOnSeparator ? 1 : 0));
289
- if (fenceToSplit) {
290
- const closeLine = `${fenceToSplit.indent}${fenceToSplit.marker}`;
291
- rawChunk = rawChunk.endsWith("\n") ? `${rawChunk}${closeLine}` : `${rawChunk}\n${closeLine}`;
292
- reopenFence = fenceToSplit;
293
- } else {
294
- nextStart = skipLeadingNewlines(text, nextStart);
295
- reopenFence = void 0;
296
- }
297
- chunks.push(rawChunk);
298
- start = nextStart;
299
- }
300
- return chunks;
301
- }
302
- function skipLeadingNewlines(value, start = 0) {
303
- let i = start;
304
- while (i < value.length && value[i] === "\n") i++;
305
- return i;
306
- }
307
- function pickSafeBreakIndex(text, start, end, spans) {
308
- const { lastNewline, lastWhitespace } = scanParenAwareBreakpoints(text, start, end, (index) => isSafeFenceBreak(spans, index));
309
- if (lastNewline > start) return lastNewline;
310
- if (lastWhitespace > start) return lastWhitespace;
311
- return -1;
312
- }
313
- function scanParenAwareBreakpoints(text, start, end, isAllowed = () => true) {
314
- let lastNewline = -1;
315
- let lastWhitespace = -1;
316
- let depth = 0;
317
- for (let i = start; i < end; i++) {
318
- if (!isAllowed(i)) continue;
319
- const char = text[i];
320
- if (char === "(") {
321
- depth += 1;
322
- continue;
323
- }
324
- if (char === ")" && depth > 0) {
325
- depth -= 1;
326
- continue;
327
- }
328
- if (depth !== 0) continue;
329
- if (char === "\n") lastNewline = i;
330
- else if (/\s/.test(char)) lastWhitespace = i;
331
- }
332
- return {
333
- lastNewline,
334
- lastWhitespace
335
- };
336
- }
337
- //#endregion
338
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/reply-payload-BeHzA2Kn.js
339
- /** Prefer multi-attachment payloads, then fall back to the legacy single-media field. */
340
- function resolveOutboundMediaUrls(payload) {
341
- if (payload.mediaUrls?.length) return payload.mediaUrls;
342
- if (payload.mediaUrl) return [payload.mediaUrl];
343
- return [];
344
- }
345
- /** Normalize reply payload text/media into a trimmed, sendable shape for delivery paths. */
346
- function resolveSendableOutboundReplyParts(payload, options) {
347
- const text = options?.text ?? payload.text ?? "";
348
- const trimmedText = text.trim();
349
- const mediaUrls = resolveOutboundMediaUrls(payload).map((entry) => entry.trim()).filter(Boolean);
350
- const mediaCount = mediaUrls.length;
351
- const hasText = Boolean(trimmedText);
352
- const hasMedia = mediaCount > 0;
353
- return {
354
- text,
355
- trimmedText,
356
- mediaUrls,
357
- mediaCount,
358
- hasText,
359
- hasMedia,
360
- hasContent: hasText || hasMedia
361
- };
362
- }
363
- /** Send a caption with only the first media item, mirroring caption-limited channel transports. */
364
- async function sendMediaWithLeadingCaption(params) {
365
- if (params.mediaUrls.length === 0) return false;
366
- for (const [index, mediaUrl] of params.mediaUrls.entries()) {
367
- const isFirst = index === 0;
368
- const caption = isFirst ? params.caption : void 0;
369
- try {
370
- await params.send({
371
- mediaUrl,
372
- caption
373
- });
374
- } catch (error) {
375
- if (params.onError) {
376
- await params.onError({
377
- error,
378
- mediaUrl,
379
- caption,
380
- index,
381
- isFirst
382
- });
383
- continue;
384
- }
385
- throw error;
386
- }
387
- }
388
- return true;
389
- }
390
- //#endregion
391
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/message-hook-mappers-BvKyVtNo.js
392
- function fireAndForgetHook(task, label, logger = logVerbose) {
393
- task.catch((err) => {
394
- logger(`${label}: ${String(err)}`);
395
- });
396
- }
397
- function buildCanonicalSentMessageHookContext(params) {
398
- return {
399
- to: params.to,
400
- content: params.content,
401
- success: params.success,
402
- error: params.error,
403
- channelId: params.channelId,
404
- accountId: params.accountId,
405
- conversationId: params.conversationId ?? params.to,
406
- messageId: params.messageId,
407
- isGroup: params.isGroup,
408
- groupId: params.groupId
409
- };
410
- }
411
- function toPluginMessageContext(canonical) {
412
- return {
413
- channelId: canonical.channelId,
414
- accountId: canonical.accountId,
415
- conversationId: canonical.conversationId
416
- };
417
- }
418
- function toPluginMessageSentEvent(canonical) {
419
- return {
420
- to: canonical.to,
421
- content: canonical.content,
422
- success: canonical.success,
423
- ...canonical.error ? { error: canonical.error } : {}
424
- };
425
- }
426
- function toInternalMessageSentContext(canonical) {
427
- return {
428
- to: canonical.to,
429
- content: canonical.content,
430
- success: canonical.success,
431
- ...canonical.error ? { error: canonical.error } : {},
432
- channelId: canonical.channelId,
433
- accountId: canonical.accountId,
434
- conversationId: canonical.conversationId,
435
- messageId: canonical.messageId,
436
- ...canonical.isGroup != null ? { isGroup: canonical.isGroup } : {},
437
- ...canonical.groupId ? { groupId: canonical.groupId } : {}
438
- };
439
- }
440
- //#endregion
441
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/secure-random-DblRPRKa.js
442
- function generateSecureUuid() {
443
- return randomUUID();
444
- }
445
- //#endregion
446
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/types.tools-BT2DX6OI.js
447
- const TOOLS_BY_SENDER_KEY_TYPES = [
448
- "id",
449
- "e164",
450
- "username",
451
- "name"
452
- ];
453
- function parseToolsBySenderTypedKey(rawKey) {
454
- const trimmed = rawKey.trim();
455
- if (!trimmed) return;
456
- const lowered = normalizeLowercaseStringOrEmpty(trimmed);
457
- for (const type of TOOLS_BY_SENDER_KEY_TYPES) {
458
- const prefix = `${type}:`;
459
- if (!lowered.startsWith(prefix)) continue;
460
- return {
461
- type,
462
- value: trimmed.slice(prefix.length)
463
- };
464
- }
465
- }
466
- //#endregion
467
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/group-policy-M4aSFsZ5.js
468
- function resolveChannelGroupConfig(groups, groupId, caseInsensitive = false) {
469
- if (!groups) return;
470
- const direct = groups[groupId];
471
- if (direct) return direct;
472
- if (!caseInsensitive) return;
473
- const target = normalizeLowercaseStringOrEmpty(groupId);
474
- const matchedKey = Object.keys(groups).find((key) => key !== "*" && normalizeLowercaseStringOrEmpty(key) === target);
475
- if (!matchedKey) return;
476
- return groups[matchedKey];
477
- }
478
- const warnedLegacyToolsBySenderKeys = /* @__PURE__ */ new Set();
479
- const compiledToolsBySenderCache = /* @__PURE__ */ new WeakMap();
480
- function normalizeSenderKey(value, options = {}) {
481
- const trimmed = value.trim();
482
- if (!trimmed) return "";
483
- return normalizeLowercaseStringOrEmpty(options.stripLeadingAt && trimmed.startsWith("@") ? trimmed.slice(1) : trimmed);
484
- }
485
- function normalizeTypedSenderKey(value, type) {
486
- return normalizeSenderKey(value, { stripLeadingAt: type === "username" });
487
- }
488
- function normalizeLegacySenderKey(value) {
489
- return normalizeSenderKey(value, { stripLeadingAt: true });
490
- }
491
- function warnLegacyToolsBySenderKey(rawKey) {
492
- const trimmed = rawKey.trim();
493
- if (!trimmed || warnedLegacyToolsBySenderKeys.has(trimmed)) return;
494
- warnedLegacyToolsBySenderKeys.add(trimmed);
495
- process.emitWarning(`toolsBySender key "${trimmed}" is deprecated. Use explicit prefixes (id:, e164:, username:, name:). Legacy unprefixed keys are matched as id only.`, {
496
- type: "DeprecationWarning",
497
- code: "OPENCLAW_TOOLS_BY_SENDER_UNTYPED_KEY"
498
- });
499
- }
500
- function parseSenderPolicyKey(rawKey) {
501
- const trimmed = rawKey.trim();
502
- if (!trimmed) return;
503
- if (trimmed === "*") return { kind: "wildcard" };
504
- const typed = parseToolsBySenderTypedKey(trimmed);
505
- if (typed) {
506
- const key = normalizeTypedSenderKey(typed.value, typed.type);
507
- if (!key) return;
508
- return {
509
- kind: "typed",
510
- type: typed.type,
511
- key
512
- };
513
- }
514
- warnLegacyToolsBySenderKey(trimmed);
515
- const key = normalizeLegacySenderKey(trimmed);
516
- if (!key) return;
517
- return {
518
- kind: "typed",
519
- type: "id",
520
- key
521
- };
522
- }
523
- function createSenderPolicyBuckets() {
524
- return {
525
- id: /* @__PURE__ */ new Map(),
526
- e164: /* @__PURE__ */ new Map(),
527
- username: /* @__PURE__ */ new Map(),
528
- name: /* @__PURE__ */ new Map()
529
- };
530
- }
531
- function compileToolsBySenderPolicy(toolsBySender) {
532
- const entries = Object.entries(toolsBySender);
533
- if (entries.length === 0) return;
534
- const buckets = createSenderPolicyBuckets();
535
- let wildcard;
536
- for (const [rawKey, policy] of entries) {
537
- if (!policy) continue;
538
- const parsed = parseSenderPolicyKey(rawKey);
539
- if (!parsed) continue;
540
- if (parsed.kind === "wildcard") {
541
- wildcard = policy;
542
- continue;
543
- }
544
- const bucket = buckets[parsed.type];
545
- if (!bucket.has(parsed.key)) bucket.set(parsed.key, policy);
546
- }
547
- return {
548
- buckets,
549
- wildcard
550
- };
551
- }
552
- function resolveCompiledToolsBySenderPolicy(toolsBySender) {
553
- const cached = compiledToolsBySenderCache.get(toolsBySender);
554
- if (cached) return cached;
555
- const compiled = compileToolsBySenderPolicy(toolsBySender);
556
- if (!compiled) return;
557
- compiledToolsBySenderCache.set(toolsBySender, compiled);
558
- return compiled;
559
- }
560
- function normalizeCandidate(value, type) {
561
- const trimmed = normalizeOptionalString(value);
562
- if (!trimmed) return "";
563
- return normalizeTypedSenderKey(trimmed, type);
564
- }
565
- function normalizeSenderIdCandidates(value) {
566
- const trimmed = normalizeOptionalString(value);
567
- if (!trimmed) return [];
568
- const typed = normalizeTypedSenderKey(trimmed, "id");
569
- const legacy = normalizeLegacySenderKey(trimmed);
570
- if (!typed) return legacy ? [legacy] : [];
571
- if (!legacy || legacy === typed) return [typed];
572
- return [typed, legacy];
573
- }
574
- function matchToolsBySenderPolicy(compiled, params) {
575
- for (const senderIdCandidate of normalizeSenderIdCandidates(params.senderId)) {
576
- const match = compiled.buckets.id.get(senderIdCandidate);
577
- if (match) return match;
578
- }
579
- const senderE164 = normalizeCandidate(params.senderE164, "e164");
580
- if (senderE164) {
581
- const match = compiled.buckets.e164.get(senderE164);
582
- if (match) return match;
583
- }
584
- const senderUsername = normalizeCandidate(params.senderUsername, "username");
585
- if (senderUsername) {
586
- const match = compiled.buckets.username.get(senderUsername);
587
- if (match) return match;
588
- }
589
- const senderName = normalizeCandidate(params.senderName, "name");
590
- if (senderName) {
591
- const match = compiled.buckets.name.get(senderName);
592
- if (match) return match;
593
- }
594
- return compiled.wildcard;
595
- }
596
- function resolveToolsBySender(params) {
597
- const toolsBySender = params.toolsBySender;
598
- if (!toolsBySender) return;
599
- const compiled = resolveCompiledToolsBySenderPolicy(toolsBySender);
600
- if (!compiled) return;
601
- return matchToolsBySenderPolicy(compiled, params);
602
- }
603
- function resolveChannelGroups(cfg, channel, accountId) {
604
- const normalizedAccountId = normalizeAccountId(accountId);
605
- const channelConfig = cfg.channels?.[channel];
606
- if (!channelConfig) return;
607
- return resolveAccountEntry(channelConfig.accounts, normalizedAccountId)?.groups ?? channelConfig.groups;
608
- }
609
- function resolveChannelGroupToolsPolicy(params) {
610
- const groups = resolveChannelGroups(params.cfg, params.channel, params.accountId);
611
- const groupIds = [params.groupId, ...Array.isArray(params.groupIdCandidates) ? params.groupIdCandidates : []];
612
- let groupConfig;
613
- for (const rawGroupId of groupIds) {
614
- const groupId = rawGroupId?.trim();
615
- if (!groupId) continue;
616
- groupConfig = resolveChannelGroupConfig(groups, groupId, params.groupIdCaseInsensitive);
617
- if (groupConfig) break;
618
- }
619
- const defaultConfig = groups?.["*"];
620
- const groupSenderPolicy = resolveToolsBySender({
621
- toolsBySender: groupConfig?.toolsBySender,
622
- senderId: params.senderId,
623
- senderName: params.senderName,
624
- senderUsername: params.senderUsername,
625
- senderE164: params.senderE164
626
- });
627
- if (groupSenderPolicy) return groupSenderPolicy;
628
- if (groupConfig?.tools) return groupConfig.tools;
629
- const defaultSenderPolicy = resolveToolsBySender({
630
- toolsBySender: defaultConfig?.toolsBySender,
631
- senderId: params.senderId,
632
- senderName: params.senderName,
633
- senderUsername: params.senderUsername,
634
- senderE164: params.senderE164
635
- });
636
- if (defaultSenderPolicy) return defaultSenderPolicy;
637
- if (defaultConfig?.tools) return defaultConfig.tools;
638
- }
639
- //#endregion
640
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/parse-Bxp0CbaB.js
641
- /**
642
- * Extract audio mode tag from text.
643
- * Supports [[audio_as_voice]] to send audio as voice message instead of file.
644
- * Default is file (preserves backward compatibility).
645
- */
646
- function parseAudioTag(text) {
647
- const result = parseInlineDirectives(text, { stripReplyTags: false });
648
- return {
649
- text: result.text,
650
- audioAsVoice: result.audioAsVoice,
651
- hadTag: result.hasAudioTag
652
- };
653
- }
654
- const MEDIA_TOKEN_RE = /\bMEDIA:\s*`?([^\n]+)`?/gi;
655
- function normalizeMediaSource(src) {
656
- return src.startsWith("file://") ? src.replace("file://", "") : src;
657
- }
658
- function cleanCandidate(raw) {
659
- return raw.replace(/^[`"'[{(]+/, "").replace(/[`"'\\})\],]+$/, "");
660
- }
661
- const WINDOWS_DRIVE_RE$1 = /^[a-zA-Z]:[\\/]/;
662
- const SCHEME_RE = /^[a-zA-Z][a-zA-Z0-9+.-]*:/;
663
- const HAS_FILE_EXT = /\.\w{1,10}$/;
664
- const TRAVERSAL_SEGMENT_RE = /(?:^|[/\\])\.\.(?:[/\\]|$)/;
665
- function hasTraversalOrHomeDirPrefix(candidate) {
666
- return candidate.startsWith("../") || candidate === ".." || candidate.startsWith("~") || TRAVERSAL_SEGMENT_RE.test(candidate);
667
- }
668
- function looksLikeLocalFilePath(candidate) {
669
- return candidate.startsWith("/") || candidate.startsWith("./") || candidate.startsWith("../") || candidate.startsWith("~") || WINDOWS_DRIVE_RE$1.test(candidate) || candidate.startsWith("\\\\") || !SCHEME_RE.test(candidate) && (candidate.includes("/") || candidate.includes("\\"));
670
- }
671
- function isLikelyLocalPath(candidate) {
672
- if (hasTraversalOrHomeDirPrefix(candidate)) return false;
673
- return candidate.startsWith("/") || candidate.startsWith("./") || WINDOWS_DRIVE_RE$1.test(candidate) || candidate.startsWith("\\\\") || !SCHEME_RE.test(candidate) && (candidate.includes("/") || candidate.includes("\\"));
674
- }
675
- function isValidMedia(candidate, opts) {
676
- if (!candidate) return false;
677
- if (candidate.length > 4096) return false;
678
- if (!opts?.allowSpaces && /\s/.test(candidate)) return false;
679
- if (/^https?:\/\//i.test(candidate)) return true;
680
- if (isLikelyLocalPath(candidate)) return true;
681
- if (hasTraversalOrHomeDirPrefix(candidate)) return false;
682
- if (opts?.allowBareFilename && !SCHEME_RE.test(candidate) && HAS_FILE_EXT.test(candidate)) return true;
683
- return false;
684
- }
685
- function unwrapQuoted(value) {
686
- const trimmed = value.trim();
687
- if (trimmed.length < 2) return;
688
- const first = trimmed[0];
689
- if (first !== trimmed[trimmed.length - 1]) return;
690
- if (first !== `"` && first !== "'" && first !== "`") return;
691
- return trimmed.slice(1, -1).trim();
692
- }
693
- function mayContainFenceMarkers(input) {
694
- return input.includes("```") || input.includes("~~~");
695
- }
696
- function isInsideFence(fenceSpans, offset) {
697
- return fenceSpans.some((span) => offset >= span.start && offset < span.end);
698
- }
699
- function splitMediaFromOutput(raw) {
700
- const trimmedRaw = raw.trimEnd();
701
- if (!trimmedRaw.trim()) return { text: "" };
702
- const mayContainMediaToken = /media:/i.test(trimmedRaw);
703
- const mayContainAudioTag = trimmedRaw.includes("[[");
704
- if (!mayContainMediaToken && !mayContainAudioTag) return { text: trimmedRaw };
705
- const media = [];
706
- let foundMediaToken = false;
707
- const segments = [];
708
- const pushTextSegment = (text) => {
709
- if (!text) return;
710
- const last = segments[segments.length - 1];
711
- if (last?.type === "text") {
712
- last.text = `${last.text}\n${text}`;
713
- return;
714
- }
715
- segments.push({
716
- type: "text",
717
- text
718
- });
719
- };
720
- const hasFenceMarkers = mayContainFenceMarkers(trimmedRaw);
721
- const fenceSpans = hasFenceMarkers ? parseFenceSpans(trimmedRaw) : [];
722
- const lines = trimmedRaw.split("\n");
723
- const keptLines = [];
724
- let lineOffset = 0;
725
- for (const line of lines) {
726
- if (hasFenceMarkers && isInsideFence(fenceSpans, lineOffset)) {
727
- keptLines.push(line);
728
- pushTextSegment(line);
729
- lineOffset += line.length + 1;
730
- continue;
731
- }
732
- if (!line.trimStart().toUpperCase().startsWith("MEDIA:")) {
733
- keptLines.push(line);
734
- pushTextSegment(line);
735
- lineOffset += line.length + 1;
736
- continue;
737
- }
738
- const matches = Array.from(line.matchAll(MEDIA_TOKEN_RE));
739
- if (matches.length === 0) {
740
- keptLines.push(line);
741
- pushTextSegment(line);
742
- lineOffset += line.length + 1;
743
- continue;
744
- }
745
- const pieces = [];
746
- const lineSegments = [];
747
- let cursor = 0;
748
- for (const match of matches) {
749
- const start = match.index ?? 0;
750
- pieces.push(line.slice(cursor, start));
751
- const payload = match[1];
752
- const unwrapped = unwrapQuoted(payload);
753
- const payloadValue = unwrapped ?? payload;
754
- const parts = unwrapped ? [unwrapped] : payload.split(/\s+/).filter(Boolean);
755
- const mediaStartIndex = media.length;
756
- let validCount = 0;
757
- const invalidParts = [];
758
- let hasValidMedia = false;
759
- for (const part of parts) {
760
- const candidate = normalizeMediaSource(cleanCandidate(part));
761
- if (isValidMedia(candidate, unwrapped ? { allowSpaces: true } : void 0)) {
762
- media.push(candidate);
763
- hasValidMedia = true;
764
- foundMediaToken = true;
765
- validCount += 1;
766
- } else invalidParts.push(part);
767
- }
768
- const trimmedPayload = payloadValue.trim();
769
- const looksLikeLocalPath = looksLikeLocalFilePath(trimmedPayload) || trimmedPayload.startsWith("file://");
770
- if (!unwrapped && validCount === 1 && invalidParts.length > 0 && /\s/.test(payloadValue) && looksLikeLocalPath) {
771
- const fallback = normalizeMediaSource(cleanCandidate(payloadValue));
772
- if (isValidMedia(fallback, { allowSpaces: true })) {
773
- media.splice(mediaStartIndex, media.length - mediaStartIndex, fallback);
774
- hasValidMedia = true;
775
- foundMediaToken = true;
776
- validCount = 1;
777
- invalidParts.length = 0;
778
- }
779
- }
780
- if (!hasValidMedia && !unwrapped && /\s/.test(payloadValue)) {
781
- const spacedFallback = normalizeMediaSource(cleanCandidate(payloadValue));
782
- if (isValidMedia(spacedFallback, {
783
- allowSpaces: true,
784
- allowBareFilename: true
785
- })) {
786
- media.splice(mediaStartIndex, media.length - mediaStartIndex, spacedFallback);
787
- hasValidMedia = true;
788
- foundMediaToken = true;
789
- validCount = 1;
790
- invalidParts.length = 0;
791
- }
792
- }
793
- if (!hasValidMedia) {
794
- const fallback = normalizeMediaSource(cleanCandidate(payloadValue));
795
- if (isValidMedia(fallback, {
796
- allowSpaces: true,
797
- allowBareFilename: true
798
- })) {
799
- media.push(fallback);
800
- hasValidMedia = true;
801
- foundMediaToken = true;
802
- invalidParts.length = 0;
803
- }
804
- }
805
- if (hasValidMedia) {
806
- const beforeText = pieces.join("").replace(/[ \t]{2,}/g, " ").trim();
807
- if (beforeText) lineSegments.push({
808
- type: "text",
809
- text: beforeText
810
- });
811
- pieces.length = 0;
812
- for (const url of media.slice(mediaStartIndex, mediaStartIndex + validCount)) lineSegments.push({
813
- type: "media",
814
- url
815
- });
816
- if (invalidParts.length > 0) pieces.push(invalidParts.join(" "));
817
- } else if (looksLikeLocalPath) foundMediaToken = true;
818
- else pieces.push(match[0]);
819
- cursor = start + match[0].length;
820
- }
821
- pieces.push(line.slice(cursor));
822
- const cleanedLine = pieces.join("").replace(/[ \t]{2,}/g, " ").trim();
823
- if (cleanedLine) {
824
- keptLines.push(cleanedLine);
825
- lineSegments.push({
826
- type: "text",
827
- text: cleanedLine
828
- });
829
- }
830
- for (const segment of lineSegments) {
831
- if (segment.type === "text") {
832
- pushTextSegment(segment.text);
833
- continue;
834
- }
835
- segments.push(segment);
836
- }
837
- lineOffset += line.length + 1;
838
- }
839
- let cleanedText = keptLines.join("\n").replace(/[ \t]+\n/g, "\n").replace(/[ \t]{2,}/g, " ").replace(/\n{2,}/g, "\n").trim();
840
- const audioTagResult = parseAudioTag(cleanedText);
841
- const hasAudioAsVoice = audioTagResult.audioAsVoice;
842
- if (audioTagResult.hadTag) cleanedText = audioTagResult.text.replace(/\n{2,}/g, "\n").trim();
843
- if (media.length === 0) {
844
- const parsedText = foundMediaToken || hasAudioAsVoice ? cleanedText : trimmedRaw;
845
- const result = {
846
- text: parsedText,
847
- segments: parsedText ? [{
848
- type: "text",
849
- text: parsedText
850
- }] : []
851
- };
852
- if (hasAudioAsVoice) result.audioAsVoice = true;
853
- return result;
854
- }
855
- return {
856
- text: cleanedText,
857
- mediaUrls: media,
858
- mediaUrl: media[0],
859
- segments: segments.length > 0 ? segments : [{
860
- type: "text",
861
- text: cleanedText
862
- }],
863
- ...hasAudioAsVoice ? { audioAsVoice: true } : {}
864
- };
865
- }
866
- //#endregion
867
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/pending-spawn-query-DuWwnOBt.js
868
- const log$1 = createSubsystemLogger("outbound/pending-spawn");
869
- const THROW_LOG_INTERVAL_MS = 6e4;
870
- let lastThrowLogAt = 0;
871
- let pendingSpawnedChildrenQuery;
872
- function registerPendingSpawnedChildrenQuery(query) {
873
- const previous = pendingSpawnedChildrenQuery;
874
- pendingSpawnedChildrenQuery = query;
875
- return previous;
876
- }
877
- function summarizeError(err) {
878
- if (err instanceof Error) return {
879
- name: err.name,
880
- message: err.message
881
- };
882
- return {
883
- name: "Unknown",
884
- message: typeof err === "string" ? err : "non-error throw"
885
- };
886
- }
887
- function hashSessionKey(key) {
888
- const trimmed = key?.trim();
889
- if (!trimmed) return;
890
- return createHash("sha256").update(trimmed).digest("hex").slice(0, 12);
891
- }
892
- function resolvePendingSpawnedChildren(sessionKey) {
893
- if (!pendingSpawnedChildrenQuery) return false;
894
- try {
895
- return pendingSpawnedChildrenQuery(sessionKey);
896
- } catch (err) {
897
- const now = Date.now();
898
- if (now - lastThrowLogAt >= THROW_LOG_INTERVAL_MS) {
899
- lastThrowLogAt = now;
900
- log$1.warn("pending-spawn query threw; defaulting to false", {
901
- err: summarizeError(err),
902
- sessionKeyHash: hashSessionKey(sessionKey)
903
- });
904
- }
905
- return false;
906
- }
907
- }
908
- //#endregion
909
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/payloads-D1t_UbQs.js
910
- function parseReplyDirectives(raw, options = {}) {
911
- const split = splitMediaFromOutput(raw);
912
- let text = split.text ?? "";
913
- const replyParsed = parseInlineDirectives(text, {
914
- currentMessageId: options.currentMessageId,
915
- stripAudioTag: false,
916
- stripReplyTags: true
917
- });
918
- if (replyParsed.hasReplyTag) text = replyParsed.text;
919
- const silentToken = options.silentToken ?? "NO_REPLY";
920
- const isSilent = isSilentReplyPayloadText(text, silentToken);
921
- if (isSilent) text = "";
922
- return {
923
- text,
924
- mediaUrls: split.mediaUrls,
925
- mediaUrl: split.mediaUrl,
926
- replyToId: replyParsed.replyToId,
927
- replyToCurrent: replyParsed.replyToCurrent || void 0,
928
- replyToTag: replyParsed.hasReplyTag,
929
- audioAsVoice: split.audioAsVoice,
930
- isSilent
931
- };
932
- }
933
- function isSuppressedRelayStatusText(text) {
934
- const normalized = text.trim();
935
- if (!normalized) return false;
936
- if (/^no channel reply\.?$/i.test(normalized)) return true;
937
- if (/^replied in-thread\.?$/i.test(normalized)) return true;
938
- if (/^replied in #[-\w]+\.?$/i.test(normalized)) return true;
939
- if (/^updated\s+\[[^\]]*wiki\/[^\]]+\](?:\([^)]+\))?(?:\s+with\b[\s\S]*)?(?:\.\s*)?(?:no channel reply\.?)?$/i.test(normalized)) return true;
940
- return false;
941
- }
942
- function mergeMediaUrls(...lists) {
943
- const seen = /* @__PURE__ */ new Set();
944
- const merged = [];
945
- for (const list of lists) {
946
- if (!list) continue;
947
- for (const entry of list) {
948
- const trimmed = entry?.trim();
949
- if (!trimmed) continue;
950
- if (seen.has(trimmed)) continue;
951
- seen.add(trimmed);
952
- merged.push(trimmed);
953
- }
954
- }
955
- return merged;
956
- }
957
- function createOutboundPayloadPlanEntry(payload) {
958
- if (shouldSuppressReasoningPayload(payload)) return null;
959
- const parsed = parseReplyDirectives(payload.text ?? "");
960
- const explicitMediaUrls = payload.mediaUrls ?? parsed.mediaUrls;
961
- const explicitMediaUrl = payload.mediaUrl ?? parsed.mediaUrl;
962
- const mergedMedia = mergeMediaUrls(explicitMediaUrls, explicitMediaUrl ? [explicitMediaUrl] : void 0);
963
- const parsedText = parsed.text ?? "";
964
- if (isSuppressedRelayStatusText(parsedText) && mergedMedia.length === 0) return null;
965
- const isSilent = parsed.isSilent && mergedMedia.length === 0;
966
- const resolvedMediaUrl = (explicitMediaUrls?.length ?? 0) > 1 ? void 0 : explicitMediaUrl;
967
- const normalizedPayload = {
968
- ...payload,
969
- text: formatBtwTextForExternalDelivery({
970
- ...payload,
971
- text: parsedText
972
- }) ?? "",
973
- mediaUrls: mergedMedia.length ? mergedMedia : void 0,
974
- mediaUrl: resolvedMediaUrl,
975
- replyToId: payload.replyToId ?? parsed.replyToId,
976
- replyToTag: payload.replyToTag || parsed.replyToTag,
977
- replyToCurrent: payload.replyToCurrent || parsed.replyToCurrent,
978
- audioAsVoice: Boolean(payload.audioAsVoice || parsed.audioAsVoice)
979
- };
980
- if (!isRenderablePayload(normalizedPayload) && !isSilent) return null;
981
- const hasChannelData = hasReplyChannelData(normalizedPayload.channelData);
982
- return {
983
- payload: normalizedPayload,
984
- hasPresentation: hasMessagePresentationBlocks(normalizedPayload.presentation),
985
- hasInteractive: hasInteractiveReplyBlocks(normalizedPayload.interactive),
986
- hasChannelData,
987
- isSilent
988
- };
989
- }
990
- function createOutboundPayloadPlan(payloads, context = {}) {
991
- const resolvedSilentReplySettings = resolveSilentReplySettings({
992
- cfg: context.cfg,
993
- sessionKey: context.sessionKey,
994
- surface: context.surface,
995
- conversationType: context.conversationType
996
- });
997
- const hasPendingSpawnedChildren = context.hasPendingSpawnedChildren ?? resolvePendingSpawnedChildren(context.sessionKey);
998
- const prepared = [];
999
- for (const payload of payloads) {
1000
- const entry = createOutboundPayloadPlanEntry(payload);
1001
- if (!entry) continue;
1002
- prepared.push(entry);
1003
- }
1004
- const hasVisibleNonSilentContent = prepared.some((entry) => {
1005
- if (entry.isSilent) return false;
1006
- const parts = resolveSendableOutboundReplyParts(entry.payload);
1007
- return hasReplyPayloadContent({
1008
- ...entry.payload,
1009
- text: parts.text,
1010
- mediaUrls: parts.mediaUrls
1011
- }, { hasChannelData: entry.hasChannelData });
1012
- });
1013
- const plan = [];
1014
- for (const entry of prepared) {
1015
- if (!entry.isSilent) {
1016
- plan.push({
1017
- payload: entry.payload,
1018
- parts: resolveSendableOutboundReplyParts(entry.payload),
1019
- hasPresentation: entry.hasPresentation,
1020
- hasInteractive: entry.hasInteractive,
1021
- hasChannelData: entry.hasChannelData
1022
- });
1023
- continue;
1024
- }
1025
- if (hasVisibleNonSilentContent || resolvedSilentReplySettings.policy === "allow" || hasPendingSpawnedChildren) continue;
1026
- if (!resolvedSilentReplySettings.rewrite) {
1027
- const visibleSilentPayload = {
1028
- ...entry.payload,
1029
- text: entry.payload.text?.trim() || "NO_REPLY"
1030
- };
1031
- if (!isRenderablePayload(visibleSilentPayload)) continue;
1032
- plan.push({
1033
- payload: visibleSilentPayload,
1034
- parts: resolveSendableOutboundReplyParts(visibleSilentPayload),
1035
- hasPresentation: entry.hasPresentation,
1036
- hasInteractive: entry.hasInteractive,
1037
- hasChannelData: entry.hasChannelData
1038
- });
1039
- continue;
1040
- }
1041
- const rewrittenPayload = {
1042
- ...entry.payload,
1043
- text: resolveSilentReplyRewriteText({ seed: `${context.sessionKey ?? context.surface ?? "silent-reply"}:${entry.payload.text ?? ""}` })
1044
- };
1045
- if (!isRenderablePayload(rewrittenPayload)) continue;
1046
- plan.push({
1047
- payload: rewrittenPayload,
1048
- parts: resolveSendableOutboundReplyParts(rewrittenPayload),
1049
- hasPresentation: entry.hasPresentation,
1050
- hasInteractive: entry.hasInteractive,
1051
- hasChannelData: entry.hasChannelData
1052
- });
1053
- }
1054
- return plan;
1055
- }
1056
- function projectOutboundPayloadPlanForDelivery(plan) {
1057
- return plan.map((entry) => entry.payload);
1058
- }
1059
- function projectOutboundPayloadPlanForMirror(plan) {
1060
- return {
1061
- text: plan.map((entry) => entry.payload.text).filter((text) => Boolean(text)).join("\n"),
1062
- mediaUrls: plan.flatMap((entry) => entry.parts.mediaUrls)
1063
- };
1064
- }
1065
- function summarizeOutboundPayloadForTransport(payload) {
1066
- const parts = resolveSendableOutboundReplyParts(payload);
1067
- return {
1068
- text: parts.text,
1069
- mediaUrls: parts.mediaUrls,
1070
- audioAsVoice: payload.audioAsVoice === true ? true : void 0,
1071
- presentation: payload.presentation,
1072
- delivery: payload.delivery,
1073
- interactive: payload.interactive,
1074
- channelData: payload.channelData
1075
- };
1076
- }
1077
- [
1078
- "import errno",
1079
- "import os",
1080
- "import stat",
1081
- "import sys",
1082
- "",
1083
- "operation = sys.argv[1]",
1084
- "root_path = sys.argv[2]",
1085
- "relative_path = sys.argv[3]",
1086
- "",
1087
- "DIR_FLAGS = os.O_RDONLY",
1088
- "if hasattr(os, 'O_DIRECTORY'):",
1089
- " DIR_FLAGS |= os.O_DIRECTORY",
1090
- "if hasattr(os, 'O_NOFOLLOW'):",
1091
- " DIR_FLAGS |= os.O_NOFOLLOW",
1092
- "",
1093
- "def open_dir(path_value, dir_fd=None):",
1094
- " return os.open(path_value, DIR_FLAGS, dir_fd=dir_fd)",
1095
- "",
1096
- "def split_segments(relative_path):",
1097
- " return [part for part in relative_path.split('/') if part and part != '.']",
1098
- "",
1099
- "def validate_segment(segment):",
1100
- " if segment == '..':",
1101
- " raise OSError(errno.EPERM, 'path traversal is not allowed', segment)",
1102
- "",
1103
- "def walk_existing_path(root_fd, segments):",
1104
- " current_fd = os.dup(root_fd)",
1105
- " try:",
1106
- " for segment in segments:",
1107
- " validate_segment(segment)",
1108
- " next_fd = open_dir(segment, dir_fd=current_fd)",
1109
- " os.close(current_fd)",
1110
- " current_fd = next_fd",
1111
- " return current_fd",
1112
- " except Exception:",
1113
- " os.close(current_fd)",
1114
- " raise",
1115
- "",
1116
- "def mkdirp_within_root(root_fd, segments):",
1117
- " current_fd = os.dup(root_fd)",
1118
- " try:",
1119
- " for segment in segments:",
1120
- " validate_segment(segment)",
1121
- " try:",
1122
- " next_fd = open_dir(segment, dir_fd=current_fd)",
1123
- " except FileNotFoundError:",
1124
- " os.mkdir(segment, 0o777, dir_fd=current_fd)",
1125
- " next_fd = open_dir(segment, dir_fd=current_fd)",
1126
- " os.close(current_fd)",
1127
- " current_fd = next_fd",
1128
- " finally:",
1129
- " os.close(current_fd)",
1130
- "",
1131
- "def remove_within_root(root_fd, segments):",
1132
- " if not segments:",
1133
- " raise OSError(errno.EPERM, 'refusing to remove root path')",
1134
- " parent_segments = segments[:-1]",
1135
- " basename = segments[-1]",
1136
- " validate_segment(basename)",
1137
- " parent_fd = walk_existing_path(root_fd, parent_segments)",
1138
- " try:",
1139
- " target_stat = os.lstat(basename, dir_fd=parent_fd)",
1140
- " if stat.S_ISDIR(target_stat.st_mode) and not stat.S_ISLNK(target_stat.st_mode):",
1141
- " os.rmdir(basename, dir_fd=parent_fd)",
1142
- " else:",
1143
- " os.unlink(basename, dir_fd=parent_fd)",
1144
- " finally:",
1145
- " os.close(parent_fd)",
1146
- "",
1147
- "root_fd = open_dir(root_path)",
1148
- "try:",
1149
- " segments = split_segments(relative_path)",
1150
- " if operation == 'mkdirp':",
1151
- " mkdirp_within_root(root_fd, segments)",
1152
- " elif operation == 'remove':",
1153
- " remove_within_root(root_fd, segments)",
1154
- " else:",
1155
- " raise RuntimeError(f'unknown pinned path operation: {operation}')",
1156
- "finally:",
1157
- " os.close(root_fd)"
1158
- ].join("\n");
1159
- [
1160
- process.env.OPENCLAW_PINNED_PYTHON,
1161
- process.env.OPENCLAW_PINNED_WRITE_PYTHON,
1162
- "/usr/bin/python3",
1163
- "/opt/homebrew/bin/python3",
1164
- "/usr/local/bin/python3"
1165
- ].filter((value) => Boolean(value));
1166
- [
1167
- "import errno",
1168
- "import os",
1169
- "import secrets",
1170
- "import stat",
1171
- "import sys",
1172
- "",
1173
- "root_path = sys.argv[1]",
1174
- "relative_parent = sys.argv[2]",
1175
- "basename = sys.argv[3]",
1176
- "mkdir_enabled = sys.argv[4] == \"1\"",
1177
- "file_mode = int(sys.argv[5], 8)",
1178
- "",
1179
- "DIR_FLAGS = os.O_RDONLY",
1180
- "if hasattr(os, 'O_DIRECTORY'):",
1181
- " DIR_FLAGS |= os.O_DIRECTORY",
1182
- "if hasattr(os, 'O_NOFOLLOW'):",
1183
- " DIR_FLAGS |= os.O_NOFOLLOW",
1184
- "",
1185
- "WRITE_FLAGS = os.O_WRONLY | os.O_CREAT | os.O_EXCL",
1186
- "if hasattr(os, 'O_NOFOLLOW'):",
1187
- " WRITE_FLAGS |= os.O_NOFOLLOW",
1188
- "",
1189
- "def open_dir(path_value, dir_fd=None):",
1190
- " return os.open(path_value, DIR_FLAGS, dir_fd=dir_fd)",
1191
- "",
1192
- "def walk_parent(root_fd, rel_parent, mkdir_enabled):",
1193
- " current_fd = os.dup(root_fd)",
1194
- " try:",
1195
- " for segment in [part for part in rel_parent.split('/') if part and part != '.']:",
1196
- " if segment == '..':",
1197
- " raise OSError(errno.EPERM, 'path traversal is not allowed', segment)",
1198
- " try:",
1199
- " next_fd = open_dir(segment, dir_fd=current_fd)",
1200
- " except FileNotFoundError:",
1201
- " if not mkdir_enabled:",
1202
- " raise",
1203
- " os.mkdir(segment, 0o777, dir_fd=current_fd)",
1204
- " next_fd = open_dir(segment, dir_fd=current_fd)",
1205
- " os.close(current_fd)",
1206
- " current_fd = next_fd",
1207
- " return current_fd",
1208
- " except Exception:",
1209
- " os.close(current_fd)",
1210
- " raise",
1211
- "",
1212
- "def create_temp_file(parent_fd, basename, mode):",
1213
- " prefix = '.' + basename + '.'",
1214
- " for _ in range(128):",
1215
- " candidate = prefix + secrets.token_hex(6) + '.tmp'",
1216
- " try:",
1217
- " fd = os.open(candidate, WRITE_FLAGS, mode, dir_fd=parent_fd)",
1218
- " return candidate, fd",
1219
- " except FileExistsError:",
1220
- " continue",
1221
- " raise RuntimeError('failed to allocate pinned temp file')",
1222
- "",
1223
- "root_fd = open_dir(root_path)",
1224
- "parent_fd = None",
1225
- "temp_fd = None",
1226
- "temp_name = None",
1227
- "try:",
1228
- " parent_fd = walk_parent(root_fd, relative_parent, mkdir_enabled)",
1229
- " temp_name, temp_fd = create_temp_file(parent_fd, basename, file_mode)",
1230
- " while True:",
1231
- " chunk = sys.stdin.buffer.read(65536)",
1232
- " if not chunk:",
1233
- " break",
1234
- " os.write(temp_fd, chunk)",
1235
- " os.fsync(temp_fd)",
1236
- " os.close(temp_fd)",
1237
- " temp_fd = None",
1238
- " os.replace(temp_name, basename, src_dir_fd=parent_fd, dst_dir_fd=parent_fd)",
1239
- " temp_name = None",
1240
- " os.fsync(parent_fd)",
1241
- " result_stat = os.stat(basename, dir_fd=parent_fd, follow_symlinks=False)",
1242
- " print(f'{result_stat.st_dev}|{result_stat.st_ino}')",
1243
- "finally:",
1244
- " if temp_fd is not None:",
1245
- " os.close(temp_fd)",
1246
- " if temp_name is not None and parent_fd is not None:",
1247
- " try:",
1248
- " os.unlink(temp_name, dir_fd=parent_fd)",
1249
- " except FileNotFoundError:",
1250
- " pass",
1251
- " if parent_fd is not None:",
1252
- " os.close(parent_fd)",
1253
- " os.close(root_fd)"
1254
- ].join("\n");
1255
- [
1256
- process.env.OPENCLAW_PINNED_WRITE_PYTHON,
1257
- "/usr/bin/python3",
1258
- "/opt/homebrew/bin/python3",
1259
- "/usr/local/bin/python3"
1260
- ].filter((value) => Boolean(value));
1261
- var SafeOpenError = class extends Error {
1262
- constructor(code, message, options) {
1263
- super(message, options);
1264
- this.code = code;
1265
- this.name = "SafeOpenError";
1266
- }
1267
- };
1268
- let fsSafeTestHooks;
1269
- const SUPPORTS_NOFOLLOW = process.platform !== "win32" && "O_NOFOLLOW" in constants;
1270
- const NONBLOCK_OPEN_FLAG = "O_NONBLOCK" in constants ? constants.O_NONBLOCK : 0;
1271
- const OPEN_READ_FLAGS = constants.O_RDONLY | (SUPPORTS_NOFOLLOW ? constants.O_NOFOLLOW : 0);
1272
- const OPEN_READ_NONBLOCK_FLAGS = OPEN_READ_FLAGS | NONBLOCK_OPEN_FLAG;
1273
- const OPEN_READ_FOLLOW_FLAGS = constants.O_RDONLY;
1274
- const OPEN_READ_FOLLOW_NONBLOCK_FLAGS = OPEN_READ_FOLLOW_FLAGS | NONBLOCK_OPEN_FLAG;
1275
- constants.O_WRONLY | (SUPPORTS_NOFOLLOW ? constants.O_NOFOLLOW : 0);
1276
- constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (SUPPORTS_NOFOLLOW ? constants.O_NOFOLLOW : 0);
1277
- constants.O_RDWR | constants.O_APPEND | (SUPPORTS_NOFOLLOW ? constants.O_NOFOLLOW : 0);
1278
- constants.O_RDWR | constants.O_APPEND | constants.O_CREAT | constants.O_EXCL | (SUPPORTS_NOFOLLOW ? constants.O_NOFOLLOW : 0);
1279
- async function openVerifiedLocalFile(filePath, options) {
1280
- try {
1281
- if ((await fs$1.lstat(filePath)).isDirectory()) throw new SafeOpenError("not-file", "not a file");
1282
- await fsSafeTestHooks?.afterPreOpenLstat?.(filePath);
1283
- } catch (err) {
1284
- if (err instanceof SafeOpenError) throw err;
1285
- }
1286
- let handle;
1287
- try {
1288
- const openFlags = options?.allowSymlinkTargetWithinRoot ? options?.nonBlockingRead ? OPEN_READ_FOLLOW_NONBLOCK_FLAGS : OPEN_READ_FOLLOW_FLAGS : options?.nonBlockingRead ? OPEN_READ_NONBLOCK_FLAGS : OPEN_READ_FLAGS;
1289
- await fsSafeTestHooks?.beforeOpen?.(filePath, openFlags);
1290
- handle = await fs$1.open(filePath, openFlags);
1291
- try {
1292
- await fsSafeTestHooks?.afterOpen?.(filePath, handle);
1293
- } catch (err) {
1294
- await handle.close().catch(() => {});
1295
- throw err;
1296
- }
1297
- } catch (err) {
1298
- if (isNotFoundPathError(err)) throw new SafeOpenError("not-found", "file not found");
1299
- if (isSymlinkOpenError(err)) throw new SafeOpenError("symlink", "symlink open blocked", { cause: err });
1300
- if (hasNodeErrorCode(err, "EISDIR")) throw new SafeOpenError("not-file", "not a file");
1301
- throw err;
1302
- }
1303
- try {
1304
- const stat = await handle.stat();
1305
- if (!stat.isFile()) throw new SafeOpenError("not-file", "not a file");
1306
- if (options?.rejectHardlinks && stat.nlink > 1) throw new SafeOpenError("invalid-path", "hardlinked path not allowed");
1307
- if (options?.allowSymlinkTargetWithinRoot) {
1308
- if (!sameFileIdentity(stat, await fs$1.stat(filePath))) throw new SafeOpenError("path-mismatch", "path changed during read");
1309
- } else {
1310
- const pathStat = await fs$1.lstat(filePath);
1311
- if (pathStat.isSymbolicLink()) throw new SafeOpenError("symlink", "symlink not allowed");
1312
- if (!sameFileIdentity(stat, pathStat)) throw new SafeOpenError("path-mismatch", "path changed during read");
1313
- }
1314
- const realPath = await resolveOpenedFileRealPathForHandle(handle, filePath);
1315
- const realStat = await fs$1.stat(realPath);
1316
- if (options?.rejectHardlinks && realStat.nlink > 1) throw new SafeOpenError("invalid-path", "hardlinked path not allowed");
1317
- if (!sameFileIdentity(stat, realStat)) throw new SafeOpenError("path-mismatch", "path mismatch");
1318
- return {
1319
- handle,
1320
- realPath,
1321
- stat
1322
- };
1323
- } catch (err) {
1324
- await handle.close().catch(() => {});
1325
- if (err instanceof SafeOpenError) throw err;
1326
- if (isNotFoundPathError(err)) throw new SafeOpenError("not-found", "file not found");
1327
- throw err;
1328
- }
1329
- }
1330
- async function readLocalFileSafely(params) {
1331
- const opened = await openLocalFileSafely({ filePath: params.filePath });
1332
- try {
1333
- return await readOpenedFileSafely({
1334
- opened,
1335
- maxBytes: params.maxBytes
1336
- });
1337
- } finally {
1338
- await opened.handle.close().catch(() => {});
1339
- }
1340
- }
1341
- async function openLocalFileSafely(params) {
1342
- return await openVerifiedLocalFile(params.filePath);
1343
- }
1344
- async function readOpenedFileSafely(params) {
1345
- if (params.maxBytes !== void 0 && params.opened.stat.size > params.maxBytes) throw new SafeOpenError("too-large", `file exceeds limit of ${params.maxBytes} bytes (got ${params.opened.stat.size})`);
1346
- return {
1347
- buffer: await params.opened.handle.readFile(),
1348
- realPath: params.opened.realPath,
1349
- stat: params.opened.stat
1350
- };
1351
- }
1352
- async function resolveOpenedFileRealPathForHandle(handle, ioPath) {
1353
- const handleStat = await handle.stat();
1354
- const fdCandidates = process.platform === "linux" ? [`/proc/self/fd/${handle.fd}`, `/dev/fd/${handle.fd}`] : process.platform === "win32" ? [] : [`/dev/fd/${handle.fd}`];
1355
- for (const fdPath of fdCandidates) try {
1356
- const fdRealPath = await fs$1.realpath(fdPath);
1357
- if (sameFileIdentity(handleStat, await fs$1.stat(fdRealPath))) return fdRealPath;
1358
- } catch {}
1359
- try {
1360
- const ioRealPath = await fs$1.realpath(ioPath);
1361
- if (sameFileIdentity(handleStat, await fs$1.stat(ioRealPath))) return ioRealPath;
1362
- } catch (err) {
1363
- if (!isNotFoundPathError(err)) throw err;
1364
- }
1365
- const parentResolved = await resolveOpenedFileRealPathFromParent(handleStat, ioPath);
1366
- if (parentResolved) return parentResolved;
1367
- throw new SafeOpenError("path-mismatch", "unable to resolve opened file path");
1368
- }
1369
- async function resolveOpenedFileRealPathFromParent(handleStat, ioPath) {
1370
- let parentReal;
1371
- try {
1372
- parentReal = await fs$1.realpath(path.dirname(ioPath));
1373
- } catch (err) {
1374
- if (isNotFoundPathError(err)) return null;
1375
- throw err;
1376
- }
1377
- let entries;
1378
- try {
1379
- entries = await fs$1.readdir(parentReal);
1380
- } catch (err) {
1381
- if (isNotFoundPathError(err)) return null;
1382
- throw err;
1383
- }
1384
- for (const entry of entries.toSorted()) {
1385
- const candidatePath = path.join(parentReal, entry);
1386
- try {
1387
- const candidateStat = await fs$1.lstat(candidatePath);
1388
- if (candidateStat.isFile() && sameFileIdentity(handleStat, candidateStat)) return await fs$1.realpath(candidatePath);
1389
- } catch (err) {
1390
- if (!isNotFoundPathError(err)) throw err;
1391
- }
1392
- }
1393
- return null;
1394
- }
1395
- //#endregion
1396
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/archive-path-DQosmKv_.js
1397
- function isWindowsDrivePath(value) {
1398
- return /^[a-zA-Z]:[\\/]/.test(value);
1399
- }
1400
- //#endregion
1401
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/local-file-access-BpdUv1jJ.js
1402
- const ENCODED_FILE_URL_SEPARATOR_RE = /%(?:2f|5c)/i;
1403
- function isLocalFileUrlHost(hostname) {
1404
- const normalized = normalizeLowercaseStringOrEmpty(hostname);
1405
- return normalized === "" || normalized === "localhost";
1406
- }
1407
- function hasEncodedFileUrlSeparator(pathname) {
1408
- return ENCODED_FILE_URL_SEPARATOR_RE.test(pathname);
1409
- }
1410
- function isWindowsNetworkPath(filePath) {
1411
- if (process.platform !== "win32") return false;
1412
- const normalized = filePath.replace(/\//g, "\\");
1413
- return normalized.startsWith("\\\\?\\UNC\\") || normalized.startsWith("\\\\");
1414
- }
1415
- function assertNoWindowsNetworkPath(filePath, label = "Path") {
1416
- if (isWindowsNetworkPath(filePath)) throw new Error(`${label} cannot use Windows network paths: ${filePath}`);
1417
- }
1418
- function safeFileURLToPath(fileUrl) {
1419
- let parsed;
1420
- try {
1421
- parsed = new URL(fileUrl);
1422
- } catch {
1423
- throw new Error(`Invalid file:// URL: ${fileUrl}`);
1424
- }
1425
- if (parsed.protocol !== "file:") throw new Error(`Invalid file:// URL: ${fileUrl}`);
1426
- if (!isLocalFileUrlHost(parsed.hostname)) throw new Error(`file:// URLs with remote hosts are not allowed: ${fileUrl}`);
1427
- if (hasEncodedFileUrlSeparator(parsed.pathname)) throw new Error(`file:// URLs cannot encode path separators: ${fileUrl}`);
1428
- const filePath = fileURLToPath(parsed);
1429
- assertNoWindowsNetworkPath(filePath, "Local file URL");
1430
- return filePath;
1431
- }
1432
- //#endregion
1433
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/media-source-url-DLCfXDgg.js
1434
- const HTTP_URL_RE = /^https?:\/\//i;
1435
- const MXC_URL_RE = /^mxc:\/\//i;
1436
- function isPassThroughRemoteMediaSource(value) {
1437
- const normalized = value?.trim() ?? "";
1438
- return Boolean(normalized) && (HTTP_URL_RE.test(normalized) || MXC_URL_RE.test(normalized));
1439
- }
1440
- //#endregion
1441
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/sandbox-paths-OtvpaIO7.js
1442
- const UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
1443
- function normalizeUnicodeSpaces(str) {
1444
- return str.replace(UNICODE_SPACES, " ");
1445
- }
1446
- function normalizeAtPrefix(filePath) {
1447
- return filePath.startsWith("@") ? filePath.slice(1) : filePath;
1448
- }
1449
- function expandPath(filePath) {
1450
- const normalized = normalizeUnicodeSpaces(normalizeAtPrefix(filePath));
1451
- if (normalized === "~") return os.homedir();
1452
- if (normalized.startsWith("~/")) return os.homedir() + normalized.slice(1);
1453
- return normalized;
1454
- }
1455
- function resolveToCwd(filePath, cwd) {
1456
- const expanded = expandPath(filePath);
1457
- if (isWindowsDrivePath(expanded)) return path.win32.normalize(expanded);
1458
- if (path.isAbsolute(expanded)) return expanded;
1459
- return path.resolve(cwd, expanded);
1460
- }
1461
- function resolveSandboxInputPath(filePath, cwd) {
1462
- return resolveToCwd(filePath, cwd);
1463
- }
1464
- //#endregion
1465
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/sandbox-tool-policy-CQSRiUbA.js
1466
- function unionAllow(base, extra) {
1467
- if (!Array.isArray(extra) || extra.length === 0) return base;
1468
- if (!Array.isArray(base)) return Array.from(new Set(["*", ...extra]));
1469
- if (base.length === 0) return Array.from(new Set(["*", ...extra]));
1470
- return Array.from(new Set([...base, ...extra]));
1471
- }
1472
- function pickSandboxToolPolicy(config) {
1473
- if (!config) return;
1474
- const allow = Array.isArray(config.allow) ? unionAllow(config.allow, config.alsoAllow) : Array.isArray(config.alsoAllow) && config.alsoAllow.length > 0 ? unionAllow(void 0, config.alsoAllow) : void 0;
1475
- const deny = Array.isArray(config.deny) ? config.deny : void 0;
1476
- if (!allow && !deny) return;
1477
- return {
1478
- allow,
1479
- deny
1480
- };
1481
- }
1482
- //#endregion
1483
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/tool-policy-match-DCu-CJil.js
1484
- function makeToolPolicyMatcher(policy) {
1485
- const deny = compileGlobPatterns({
1486
- raw: expandToolGroups(policy.deny ?? []),
1487
- normalize: normalizeToolName
1488
- });
1489
- const allow = compileGlobPatterns({
1490
- raw: expandToolGroups(policy.allow ?? []),
1491
- normalize: normalizeToolName
1492
- });
1493
- return (name) => {
1494
- const normalized = normalizeToolName(name);
1495
- if (matchesAnyGlobPattern(normalized, deny)) return false;
1496
- if (normalized === "apply_patch" && matchesAnyGlobPattern("write", deny)) return false;
1497
- if (allow.length === 0) return true;
1498
- if (matchesAnyGlobPattern(normalized, allow)) return true;
1499
- if (normalized === "apply_patch" && matchesAnyGlobPattern("write", allow)) return true;
1500
- return false;
1501
- };
1502
- }
1503
- function isToolAllowedByPolicyName(name, policy) {
1504
- if (!policy) return true;
1505
- return makeToolPolicyMatcher(policy)(name);
1506
- }
1507
- function isToolAllowedByPolicies(name, policies) {
1508
- return policies.every((policy) => isToolAllowedByPolicyName(name, policy));
1509
- }
1510
- //#endregion
1511
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/local-roots-B40QFFFV.js
1512
- function resolveToolFsConfig(params) {
1513
- const cfg = params.cfg;
1514
- const globalFs = cfg?.tools?.fs;
1515
- return { workspaceOnly: (cfg && params.agentId ? resolveAgentConfig(cfg, params.agentId)?.tools?.fs : void 0)?.workspaceOnly ?? globalFs?.workspaceOnly };
1516
- }
1517
- function resolveEffectiveToolFsWorkspaceOnly(params) {
1518
- return resolveToolFsConfig(params).workspaceOnly === true;
1519
- }
1520
- function resolveEffectiveToolFsRootExpansionAllowed(params) {
1521
- const cfg = params.cfg;
1522
- if (!cfg) return true;
1523
- const agentTools = params.agentId ? resolveAgentConfig(cfg, params.agentId)?.tools : void 0;
1524
- const globalTools = cfg.tools;
1525
- const profile = agentTools?.profile ?? globalTools?.profile;
1526
- const profileAlsoAllow = new Set(agentTools?.alsoAllow ?? globalTools?.alsoAllow ?? []);
1527
- const fsConfig = resolveToolFsConfig(params);
1528
- const hasExplicitFsConfig = agentTools?.fs !== void 0 || globalTools?.fs !== void 0;
1529
- if (fsConfig.workspaceOnly === true) return false;
1530
- if (hasExplicitFsConfig) {
1531
- profileAlsoAllow.add("read");
1532
- profileAlsoAllow.add("write");
1533
- profileAlsoAllow.add("edit");
1534
- }
1535
- return isToolAllowedByPolicies("read", [
1536
- mergeAlsoAllowPolicy(resolveToolProfilePolicy(profile), profileAlsoAllow.size > 0 ? Array.from(profileAlsoAllow) : void 0),
1537
- pickSandboxToolPolicy(globalTools),
1538
- pickSandboxToolPolicy(agentTools)
1539
- ]);
1540
- }
1541
- let cachedPreferredTmpDir;
1542
- const DATA_URL_RE = /^data:/i;
1543
- const WINDOWS_DRIVE_RE = /^[A-Za-z]:[\\/]/;
1544
- function resolveCachedPreferredTmpDir() {
1545
- if (!cachedPreferredTmpDir) cachedPreferredTmpDir = resolvePreferredOpenClawTmpDir();
1546
- return cachedPreferredTmpDir;
1547
- }
1548
- function buildMediaLocalRoots(stateDir, configDir, options = {}) {
1549
- const resolvedStateDir = path.resolve(stateDir);
1550
- const resolvedConfigDir = path.resolve(configDir);
1551
- const preferredTmpDir = options.preferredTmpDir ?? resolveCachedPreferredTmpDir();
1552
- return Array.from(new Set([
1553
- preferredTmpDir,
1554
- path.join(resolvedConfigDir, "media"),
1555
- path.join(resolvedStateDir, "media"),
1556
- path.join(resolvedStateDir, "canvas"),
1557
- path.join(resolvedStateDir, "workspace"),
1558
- path.join(resolvedStateDir, "sandboxes")
1559
- ]));
1560
- }
1561
- function getAgentScopedMediaLocalRoots(cfg, agentId) {
1562
- const roots = buildMediaLocalRoots(resolveStateDir(), resolveConfigDir());
1563
- const normalizedAgentId = normalizeOptionalString(agentId);
1564
- if (!normalizedAgentId) return roots;
1565
- const workspaceDir = resolveAgentWorkspaceDir(cfg, normalizedAgentId);
1566
- if (!workspaceDir) return roots;
1567
- const normalizedWorkspaceDir = path.resolve(workspaceDir);
1568
- if (!roots.includes(normalizedWorkspaceDir)) roots.push(normalizedWorkspaceDir);
1569
- return roots;
1570
- }
1571
- function resolveLocalMediaPath(source) {
1572
- const trimmed = source.trim();
1573
- if (!trimmed || isPassThroughRemoteMediaSource(trimmed) || DATA_URL_RE.test(trimmed)) return;
1574
- if (trimmed.startsWith("file://")) try {
1575
- return safeFileURLToPath(trimmed);
1576
- } catch {
1577
- return;
1578
- }
1579
- if (trimmed.startsWith("~")) return resolveUserPath(trimmed);
1580
- if (path.isAbsolute(trimmed) || WINDOWS_DRIVE_RE.test(trimmed)) return path.resolve(trimmed);
1581
- }
1582
- function appendLocalMediaParentRoots(roots, mediaSources) {
1583
- const appended = Array.from(new Set(roots.map((root) => path.resolve(root))));
1584
- for (const source of mediaSources ?? []) {
1585
- const localPath = resolveLocalMediaPath(source);
1586
- if (!localPath) continue;
1587
- const parentDir = path.dirname(localPath);
1588
- if (parentDir === path.parse(parentDir).root) continue;
1589
- const normalizedParent = path.resolve(parentDir);
1590
- if (!appended.includes(normalizedParent)) appended.push(normalizedParent);
1591
- }
1592
- return appended;
1593
- }
1594
- function getAgentScopedMediaLocalRootsForSources(params) {
1595
- const roots = getAgentScopedMediaLocalRoots(params.cfg, params.agentId);
1596
- if (resolveEffectiveToolFsWorkspaceOnly({
1597
- cfg: params.cfg,
1598
- agentId: params.agentId
1599
- })) return roots;
1600
- if (!resolveEffectiveToolFsRootExpansionAllowed({
1601
- cfg: params.cfg,
1602
- agentId: params.agentId
1603
- })) return roots;
1604
- return appendLocalMediaParentRoots(roots, params.mediaSources);
1605
- }
1606
- //#endregion
1607
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/read-capability-B_d5F-j4.js
1608
- function resolvePathFromInput(filePath, cwd) {
1609
- return path.normalize(resolveSandboxInputPath(filePath, cwd));
1610
- }
1611
- function normalizeWorkspaceDir(workspaceDir) {
1612
- const trimmed = workspaceDir?.trim();
1613
- if (!trimmed) return null;
1614
- const expanded = trimmed.startsWith("~") ? resolveUserPath(trimmed) : trimmed;
1615
- const resolved = path.resolve(expanded);
1616
- if (resolved === path.parse(resolved).root) return null;
1617
- return resolved;
1618
- }
1619
- function resolveWorkspaceRoot(workspaceDir) {
1620
- return normalizeWorkspaceDir(workspaceDir) ?? process.cwd();
1621
- }
1622
- function collectUniqueStrings(values) {
1623
- const seen = /* @__PURE__ */ new Set();
1624
- const resolved = [];
1625
- for (const value of values) {
1626
- const trimmed = value?.trim();
1627
- if (!trimmed || seen.has(trimmed)) continue;
1628
- seen.add(trimmed);
1629
- resolved.push(trimmed);
1630
- }
1631
- return resolved;
1632
- }
1633
- function buildScopedGroupIdCandidates(groupId) {
1634
- const raw = groupId?.trim();
1635
- if (!raw) return [];
1636
- const topicSenderMatch = raw.match(/^(.+):topic:([^:]+):sender:([^:]+)$/i);
1637
- if (topicSenderMatch) {
1638
- const [, chatId, topicId] = topicSenderMatch;
1639
- return collectUniqueStrings([
1640
- raw,
1641
- `${chatId}:topic:${topicId}`,
1642
- chatId
1643
- ]);
1644
- }
1645
- const topicMatch = raw.match(/^(.+):topic:([^:]+)$/i);
1646
- if (topicMatch) {
1647
- const [, chatId, topicId] = topicMatch;
1648
- return collectUniqueStrings([`${chatId}:topic:${topicId}`, chatId]);
1649
- }
1650
- const senderMatch = raw.match(/^(.+):sender:([^:]+)$/i);
1651
- if (senderMatch) {
1652
- const [, chatId] = senderMatch;
1653
- return collectUniqueStrings([raw, chatId]);
1654
- }
1655
- return [raw];
1656
- }
1657
- function resolveGroupContextFromSessionKey(sessionKey) {
1658
- const raw = (sessionKey ?? "").trim();
1659
- if (!raw) return {};
1660
- const { baseSessionKey, threadId } = parseThreadSessionSuffix(raw);
1661
- const conversationKey = threadId ? baseSessionKey : raw;
1662
- const conversation = parseRawSessionConversationRef(conversationKey);
1663
- if (conversation) {
1664
- const resolvedConversation = /:(?:sender|thread|topic):/iu.test(conversation.rawId) ? resolveSessionConversation({
1665
- channel: conversation.channel,
1666
- kind: conversation.kind,
1667
- rawId: conversation.rawId
1668
- }) : null;
1669
- return {
1670
- channel: conversation.channel,
1671
- groupIds: collectUniqueStrings([
1672
- ...buildScopedGroupIdCandidates(conversation.rawId),
1673
- resolvedConversation?.id,
1674
- resolvedConversation?.baseConversationId,
1675
- ...resolvedConversation?.parentConversationCandidates ?? []
1676
- ])
1677
- };
1678
- }
1679
- const parts = (conversationKey ?? raw).split(":").filter(Boolean);
1680
- let body = parts[0] === "agent" ? parts.slice(2) : parts;
1681
- if (body[0] === "subagent") body = body.slice(1);
1682
- if (body.length < 3) return {};
1683
- const [channel, kind, ...rest] = body;
1684
- if (kind !== "group" && kind !== "channel") return {};
1685
- const groupId = rest.join(":").trim();
1686
- if (!groupId) return {};
1687
- return {
1688
- channel: normalizeLowercaseStringOrEmpty(channel),
1689
- groupIds: buildScopedGroupIdCandidates(groupId)
1690
- };
1691
- }
1692
- function resolveGroupToolPolicy(params) {
1693
- if (!params.config) return;
1694
- const sessionContext = resolveGroupContextFromSessionKey(params.sessionKey);
1695
- const spawnedContext = resolveGroupContextFromSessionKey(params.spawnedBy);
1696
- const groupIds = collectUniqueStrings([
1697
- ...buildScopedGroupIdCandidates(params.groupId),
1698
- ...sessionContext.groupIds ?? [],
1699
- ...spawnedContext.groupIds ?? []
1700
- ]);
1701
- if (groupIds.length === 0) return;
1702
- const channel = normalizeMessageChannel(params.messageProvider ?? sessionContext.channel ?? spawnedContext.channel);
1703
- if (!channel) return;
1704
- let plugin;
1705
- try {
1706
- plugin = getLoadedChannelPlugin(channel);
1707
- } catch {
1708
- plugin = void 0;
1709
- }
1710
- for (const groupId of groupIds) {
1711
- const toolsConfig = plugin?.groups?.resolveToolPolicy?.({
1712
- cfg: params.config,
1713
- groupId,
1714
- groupChannel: params.groupChannel,
1715
- groupSpace: params.groupSpace,
1716
- accountId: params.accountId,
1717
- senderId: params.senderId,
1718
- senderName: params.senderName,
1719
- senderUsername: params.senderUsername,
1720
- senderE164: params.senderE164
1721
- });
1722
- const policy = pickSandboxToolPolicy(toolsConfig);
1723
- if (policy) return policy;
1724
- }
1725
- return pickSandboxToolPolicy(resolveChannelGroupToolsPolicy({
1726
- cfg: params.config,
1727
- channel,
1728
- groupId: groupIds[0],
1729
- groupIdCandidates: groupIds.slice(1),
1730
- accountId: params.accountId,
1731
- senderId: params.senderId,
1732
- senderName: params.senderName,
1733
- senderUsername: params.senderUsername,
1734
- senderE164: params.senderE164
1735
- }));
1736
- }
1737
- function isAgentScopedHostMediaReadAllowed(params) {
1738
- if (!resolveEffectiveToolFsRootExpansionAllowed({
1739
- cfg: params.cfg,
1740
- agentId: params.agentId
1741
- })) return false;
1742
- const groupPolicy = resolveGroupToolPolicy({
1743
- config: params.cfg,
1744
- sessionKey: params.sessionKey,
1745
- messageProvider: params.messageProvider,
1746
- groupId: params.groupId,
1747
- groupChannel: params.groupChannel,
1748
- groupSpace: params.groupSpace,
1749
- accountId: params.accountId,
1750
- senderId: normalizeOptionalString(params.requesterSenderId),
1751
- senderName: normalizeOptionalString(params.requesterSenderName),
1752
- senderUsername: normalizeOptionalString(params.requesterSenderUsername),
1753
- senderE164: normalizeOptionalString(params.requesterSenderE164)
1754
- });
1755
- if (groupPolicy && !isToolAllowedByPolicies("read", [groupPolicy])) return false;
1756
- return true;
1757
- }
1758
- function createAgentScopedHostMediaReadFile(params) {
1759
- if (!isAgentScopedHostMediaReadAllowed(params)) return;
1760
- const workspaceRoot = resolveWorkspaceRoot(params.workspaceDir ?? (params.agentId ? resolveAgentWorkspaceDir(params.cfg, params.agentId) : void 0));
1761
- return async (filePath) => {
1762
- return (await readLocalFileSafely({ filePath: resolvePathFromInput(filePath, workspaceRoot) })).buffer;
1763
- };
1764
- }
1765
- function resolveAgentScopedOutboundMediaAccess(params) {
1766
- const hostMediaReadAllowed = isAgentScopedHostMediaReadAllowed(params);
1767
- const localRoots = params.mediaAccess?.localRoots ?? (hostMediaReadAllowed ? getAgentScopedMediaLocalRootsForSources({
1768
- cfg: params.cfg,
1769
- agentId: params.agentId,
1770
- mediaSources: params.mediaSources
1771
- }) : getAgentScopedMediaLocalRoots(params.cfg, params.agentId));
1772
- const resolvedWorkspaceDir = params.workspaceDir ?? params.mediaAccess?.workspaceDir ?? (params.agentId ? resolveAgentWorkspaceDir(params.cfg, params.agentId) : void 0);
1773
- const readFile = params.mediaAccess?.readFile ?? params.mediaReadFile ?? (hostMediaReadAllowed ? createAgentScopedHostMediaReadFile({
1774
- cfg: params.cfg,
1775
- agentId: params.agentId,
1776
- workspaceDir: resolvedWorkspaceDir,
1777
- sessionKey: params.sessionKey,
1778
- messageProvider: params.messageProvider,
1779
- groupId: params.groupId,
1780
- groupChannel: params.groupChannel,
1781
- groupSpace: params.groupSpace,
1782
- accountId: params.accountId,
1783
- requesterSenderId: params.requesterSenderId,
1784
- requesterSenderName: params.requesterSenderName,
1785
- requesterSenderUsername: params.requesterSenderUsername,
1786
- requesterSenderE164: params.requesterSenderE164
1787
- }) : void 0);
1788
- return {
1789
- ...localRoots?.length ? { localRoots } : {},
1790
- ...readFile ? { readFile } : {},
1791
- ...resolvedWorkspaceDir ? { workspaceDir: resolvedWorkspaceDir } : {}
1792
- };
1793
- }
1794
- //#endregion
1795
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/load-UwglZn5K.js
1796
- function createChannelRegistryLoader(resolveValue) {
1797
- const cache = /* @__PURE__ */ new Map();
1798
- let lastRegistry = null;
1799
- return async (id) => {
1800
- const registry = getActivePluginChannelRegistry();
1801
- if (registry !== lastRegistry) {
1802
- cache.clear();
1803
- lastRegistry = registry;
1804
- }
1805
- const cached = cache.get(id);
1806
- if (cached) return cached;
1807
- const pluginEntry = registry?.channels.find((entry) => entry.plugin.id === id);
1808
- if (!pluginEntry) return;
1809
- const resolved = resolveValue(pluginEntry);
1810
- if (resolved) cache.set(id, resolved);
1811
- return resolved;
1812
- };
1813
- }
1814
- const loadOutboundAdapterFromRegistry = createChannelRegistryLoader((entry) => entry.plugin.outbound);
1815
- async function loadChannelOutboundAdapter(id) {
1816
- return loadOutboundAdapterFromRegistry(id);
1817
- }
1818
- //#endregion
1819
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/delivery-queue-Ds-NSzJi.js
1820
- const QUEUE_DIRNAME = "delivery-queue";
1821
- const FAILED_DIRNAME = "failed";
1822
- function resolveQueueDir(stateDir) {
1823
- const base = stateDir ?? resolveStateDir();
1824
- return path.join(base, QUEUE_DIRNAME);
1825
- }
1826
- function resolveFailedDir(stateDir) {
1827
- return path.join(resolveQueueDir(stateDir), FAILED_DIRNAME);
1828
- }
1829
- function resolveQueueEntryPaths(id, stateDir) {
1830
- const queueDir = resolveQueueDir(stateDir);
1831
- return {
1832
- jsonPath: path.join(queueDir, `${id}.json`),
1833
- deliveredPath: path.join(queueDir, `${id}.delivered`)
1834
- };
1835
- }
1836
- function getErrnoCode$1(err) {
1837
- return err && typeof err === "object" && "code" in err ? String(err.code) : null;
1838
- }
1839
- async function unlinkBestEffort(filePath) {
1840
- try {
1841
- await fs.promises.unlink(filePath);
1842
- } catch {}
1843
- }
1844
- async function writeQueueEntry(filePath, entry) {
1845
- const tmp = `${filePath}.${process.pid}.tmp`;
1846
- await fs.promises.writeFile(tmp, JSON.stringify(entry, null, 2), {
1847
- encoding: "utf-8",
1848
- mode: 384
1849
- });
1850
- await fs.promises.rename(tmp, filePath);
1851
- }
1852
- async function readQueueEntry(filePath) {
1853
- return JSON.parse(await fs.promises.readFile(filePath, "utf-8"));
1854
- }
1855
- /** Ensure the queue directory (and failed/ subdirectory) exist. */
1856
- async function ensureQueueDir(stateDir) {
1857
- const queueDir = resolveQueueDir(stateDir);
1858
- await fs.promises.mkdir(queueDir, {
1859
- recursive: true,
1860
- mode: 448
1861
- });
1862
- await fs.promises.mkdir(resolveFailedDir(stateDir), {
1863
- recursive: true,
1864
- mode: 448
1865
- });
1866
- return queueDir;
1867
- }
1868
- /** Persist a delivery entry to disk before attempting send. Returns the entry ID. */
1869
- async function enqueueDelivery(params, stateDir) {
1870
- const queueDir = await ensureQueueDir(stateDir);
1871
- const id = generateSecureUuid();
1872
- await writeQueueEntry(path.join(queueDir, `${id}.json`), {
1873
- id,
1874
- enqueuedAt: Date.now(),
1875
- channel: params.channel,
1876
- to: params.to,
1877
- accountId: params.accountId,
1878
- payloads: params.payloads,
1879
- threadId: params.threadId,
1880
- replyToId: params.replyToId,
1881
- bestEffort: params.bestEffort,
1882
- gifPlayback: params.gifPlayback,
1883
- forceDocument: params.forceDocument,
1884
- silent: params.silent,
1885
- mirror: params.mirror,
1886
- session: params.session,
1887
- gatewayClientScopes: params.gatewayClientScopes,
1888
- retryCount: 0
1889
- });
1890
- return id;
1891
- }
1892
- /** Remove a successfully delivered entry from the queue.
1893
- *
1894
- * Uses a two-phase approach so that a crash between delivery and cleanup
1895
- * does not cause the message to be replayed on the next recovery scan:
1896
- * Phase 1: atomic rename {id}.json → {id}.delivered
1897
- * Phase 2: unlink the .delivered marker
1898
- * If the process dies between phase 1 and phase 2 the marker is cleaned up
1899
- * by {@link loadPendingDeliveries} on the next startup without re-sending.
1900
- */
1901
- async function ackDelivery(id, stateDir) {
1902
- const { jsonPath, deliveredPath } = resolveQueueEntryPaths(id, stateDir);
1903
- try {
1904
- await fs.promises.rename(jsonPath, deliveredPath);
1905
- } catch (err) {
1906
- if (getErrnoCode$1(err) === "ENOENT") {
1907
- await unlinkBestEffort(deliveredPath);
1908
- return;
1909
- }
1910
- throw err;
1911
- }
1912
- await unlinkBestEffort(deliveredPath);
1913
- }
1914
- /** Update a queue entry after a failed delivery attempt. */
1915
- async function failDelivery(id, error, stateDir) {
1916
- const filePath = path.join(resolveQueueDir(stateDir), `${id}.json`);
1917
- const entry = await readQueueEntry(filePath);
1918
- entry.retryCount += 1;
1919
- entry.lastAttemptAt = Date.now();
1920
- entry.lastError = error;
1921
- await writeQueueEntry(filePath, entry);
1922
- }
1923
- const entriesInProgress = /* @__PURE__ */ new Set();
1924
- function claimRecoveryEntry(entryId) {
1925
- if (entriesInProgress.has(entryId)) return false;
1926
- entriesInProgress.add(entryId);
1927
- return true;
1928
- }
1929
- function releaseRecoveryEntry(entryId) {
1930
- entriesInProgress.delete(entryId);
1931
- }
1932
- async function withActiveDeliveryClaim(entryId, fn) {
1933
- if (!claimRecoveryEntry(entryId)) return { status: "claimed-by-other-owner" };
1934
- try {
1935
- return {
1936
- status: "claimed",
1937
- value: await fn()
1938
- };
1939
- } finally {
1940
- releaseRecoveryEntry(entryId);
1941
- }
1942
- }
1943
- //#endregion
1944
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/deliver-C6YJ_kD0.js
1945
- /**
1946
- * Utility for checking AbortSignal state and throwing a standard AbortError.
1947
- */
1948
- /**
1949
- * Throws an AbortError if the given signal has been aborted.
1950
- * Use at async checkpoints to support cancellation.
1951
- */
1952
- function throwIfAborted(abortSignal) {
1953
- if (abortSignal?.aborted) {
1954
- const err = /* @__PURE__ */ new Error("Operation aborted");
1955
- err.name = "AbortError";
1956
- throw err;
1957
- }
1958
- }
1959
- const log = createSubsystemLogger("outbound/deliver");
1960
- let transcriptRuntimePromise;
1961
- async function loadTranscriptRuntime() {
1962
- transcriptRuntimePromise ??= import("./transcript.runtime-BqhvZZdl-BPy42vBP.mjs");
1963
- return await transcriptRuntimePromise;
1964
- }
1965
- let channelBootstrapRuntimePromise;
1966
- async function loadChannelBootstrapRuntime() {
1967
- channelBootstrapRuntimePromise ??= import("./channel-bootstrap.runtime-BVclcGv1-DJv_Z-Kr.mjs");
1968
- return await channelBootstrapRuntimePromise;
1969
- }
1970
- async function createChannelHandler(params) {
1971
- let outbound = await loadChannelOutboundAdapter(params.channel);
1972
- if (!outbound) {
1973
- const { bootstrapOutboundChannelPlugin } = await loadChannelBootstrapRuntime();
1974
- bootstrapOutboundChannelPlugin({
1975
- channel: params.channel,
1976
- cfg: params.cfg
1977
- });
1978
- outbound = await loadChannelOutboundAdapter(params.channel);
1979
- }
1980
- const handler = createPluginHandler({
1981
- ...params,
1982
- outbound
1983
- });
1984
- if (!handler) throw new Error(`Outbound not configured for channel: ${params.channel}`);
1985
- return handler;
1986
- }
1987
- function createPluginHandler(params) {
1988
- const outbound = params.outbound;
1989
- if (!outbound?.sendText) return null;
1990
- const baseCtx = createChannelOutboundContextBase(params);
1991
- const sendText = outbound.sendText;
1992
- const sendMedia = outbound.sendMedia;
1993
- const chunker = outbound.chunker ?? null;
1994
- const chunkerMode = outbound.chunkerMode;
1995
- const resolveCtx = (overrides) => ({
1996
- ...baseCtx,
1997
- replyToId: overrides?.replyToId ?? baseCtx.replyToId,
1998
- threadId: overrides?.threadId ?? baseCtx.threadId,
1999
- audioAsVoice: overrides?.audioAsVoice
2000
- });
2001
- const buildTargetRef = (overrides) => ({
2002
- channel: params.channel,
2003
- to: params.to,
2004
- accountId: params.accountId ?? void 0,
2005
- threadId: overrides?.threadId ?? baseCtx.threadId
2006
- });
2007
- return {
2008
- chunker,
2009
- chunkerMode,
2010
- textChunkLimit: outbound.textChunkLimit,
2011
- supportsMedia: Boolean(sendMedia),
2012
- sanitizeText: outbound.sanitizeText ? (payload) => outbound.sanitizeText({
2013
- text: payload.text ?? "",
2014
- payload
2015
- }) : void 0,
2016
- normalizePayload: outbound.normalizePayload ? (payload) => outbound.normalizePayload({ payload }) : void 0,
2017
- renderPresentation: outbound.renderPresentation ? async (payload) => {
2018
- const presentation = normalizeMessagePresentation(payload.presentation);
2019
- if (!presentation) return payload;
2020
- const ctx = {
2021
- ...resolveCtx({
2022
- replyToId: payload.replyToId ?? baseCtx.replyToId,
2023
- threadId: baseCtx.threadId,
2024
- audioAsVoice: payload.audioAsVoice
2025
- }),
2026
- text: payload.text ?? "",
2027
- mediaUrl: payload.mediaUrl,
2028
- payload
2029
- };
2030
- return await outbound.renderPresentation({
2031
- payload,
2032
- presentation,
2033
- ctx
2034
- });
2035
- } : void 0,
2036
- pinDeliveredMessage: outbound.pinDeliveredMessage ? async ({ target, messageId, pin }) => outbound.pinDeliveredMessage({
2037
- cfg: params.cfg,
2038
- target,
2039
- messageId,
2040
- pin
2041
- }) : void 0,
2042
- shouldSkipPlainTextSanitization: outbound.shouldSkipPlainTextSanitization ? (payload) => outbound.shouldSkipPlainTextSanitization({ payload }) : void 0,
2043
- resolveEffectiveTextChunkLimit: outbound.resolveEffectiveTextChunkLimit ? (fallbackLimit) => outbound.resolveEffectiveTextChunkLimit({
2044
- cfg: params.cfg,
2045
- accountId: params.accountId ?? void 0,
2046
- fallbackLimit
2047
- }) : void 0,
2048
- sendPayload: outbound.sendPayload ? async (payload, overrides) => outbound.sendPayload({
2049
- ...resolveCtx(overrides),
2050
- text: payload.text ?? "",
2051
- mediaUrl: payload.mediaUrl,
2052
- payload
2053
- }) : void 0,
2054
- sendFormattedText: outbound.sendFormattedText ? async (text, overrides) => outbound.sendFormattedText({
2055
- ...resolveCtx(overrides),
2056
- text
2057
- }) : void 0,
2058
- sendFormattedMedia: outbound.sendFormattedMedia ? async (caption, mediaUrl, overrides) => outbound.sendFormattedMedia({
2059
- ...resolveCtx(overrides),
2060
- text: caption,
2061
- mediaUrl
2062
- }) : void 0,
2063
- sendText: async (text, overrides) => sendText({
2064
- ...resolveCtx(overrides),
2065
- text
2066
- }),
2067
- buildTargetRef,
2068
- sendMedia: async (caption, mediaUrl, overrides) => {
2069
- if (sendMedia) return sendMedia({
2070
- ...resolveCtx(overrides),
2071
- text: caption,
2072
- mediaUrl
2073
- });
2074
- return sendText({
2075
- ...resolveCtx(overrides),
2076
- text: caption
2077
- });
2078
- }
2079
- };
2080
- }
2081
- function createChannelOutboundContextBase(params) {
2082
- return {
2083
- cfg: params.cfg,
2084
- to: params.to,
2085
- accountId: params.accountId,
2086
- replyToId: params.replyToId,
2087
- threadId: params.threadId,
2088
- identity: params.identity,
2089
- gifPlayback: params.gifPlayback,
2090
- forceDocument: params.forceDocument,
2091
- deps: params.deps,
2092
- silent: params.silent,
2093
- mediaAccess: params.mediaAccess,
2094
- mediaLocalRoots: params.mediaAccess?.localRoots,
2095
- mediaReadFile: params.mediaAccess?.readFile,
2096
- gatewayClientScopes: params.gatewayClientScopes
2097
- };
2098
- }
2099
- const isAbortError = (err) => err instanceof Error && err.name === "AbortError";
2100
- function collectPayloadMediaSources(plan) {
2101
- return plan.flatMap((entry) => entry.parts.mediaUrls);
2102
- }
2103
- function normalizeEmptyPayloadForDelivery(payload) {
2104
- const text = typeof payload.text === "string" ? payload.text : "";
2105
- if (!text.trim()) {
2106
- if (!hasReplyPayloadContent({
2107
- ...payload,
2108
- text
2109
- })) return null;
2110
- if (text) return {
2111
- ...payload,
2112
- text: ""
2113
- };
2114
- }
2115
- return payload;
2116
- }
2117
- function normalizePayloadsForChannelDelivery(plan, handler) {
2118
- const normalizedPayloads = [];
2119
- for (const payload of projectOutboundPayloadPlanForDelivery(plan)) {
2120
- let sanitizedPayload = payload;
2121
- if (handler.sanitizeText && sanitizedPayload.text) {
2122
- if (!handler.shouldSkipPlainTextSanitization?.(sanitizedPayload)) sanitizedPayload = {
2123
- ...sanitizedPayload,
2124
- text: handler.sanitizeText(sanitizedPayload)
2125
- };
2126
- }
2127
- const normalizedPayload = handler.normalizePayload ? handler.normalizePayload(sanitizedPayload) : sanitizedPayload;
2128
- const normalized = normalizedPayload ? normalizeEmptyPayloadForDelivery(normalizedPayload) : null;
2129
- if (normalized) normalizedPayloads.push(normalized);
2130
- }
2131
- return normalizedPayloads;
2132
- }
2133
- function buildPayloadSummary(payload) {
2134
- return summarizeOutboundPayloadForTransport(payload);
2135
- }
2136
- function normalizeDeliveryPin(payload) {
2137
- const pin = payload.delivery?.pin;
2138
- if (pin === true) return { enabled: true };
2139
- if (!pin || typeof pin !== "object" || Array.isArray(pin)) return;
2140
- if (!pin.enabled) return;
2141
- const normalized = { enabled: true };
2142
- if (pin.notify === true) normalized.notify = true;
2143
- if (pin.required === true) normalized.required = true;
2144
- return normalized;
2145
- }
2146
- async function maybePinDeliveredMessage(params) {
2147
- const pin = normalizeDeliveryPin(params.payload);
2148
- if (!pin) return;
2149
- if (!params.messageId) {
2150
- if (pin.required) throw new Error("Delivery pin requested, but no delivered message id was returned.");
2151
- log.warn("Delivery pin requested, but no delivered message id was returned.", {
2152
- channel: params.target.channel,
2153
- to: params.target.to
2154
- });
2155
- return;
2156
- }
2157
- if (!params.handler.pinDeliveredMessage) {
2158
- if (pin.required) throw new Error(`Delivery pin is not supported by channel: ${params.target.channel}`);
2159
- log.warn("Delivery pin requested, but channel does not support pinning delivered messages.", {
2160
- channel: params.target.channel,
2161
- to: params.target.to
2162
- });
2163
- return;
2164
- }
2165
- try {
2166
- await params.handler.pinDeliveredMessage({
2167
- target: params.target,
2168
- messageId: params.messageId,
2169
- pin
2170
- });
2171
- } catch (err) {
2172
- if (pin.required) throw err;
2173
- log.warn("Delivery pin requested, but channel failed to pin delivered message.", {
2174
- channel: params.target.channel,
2175
- to: params.target.to,
2176
- messageId: params.messageId,
2177
- error: formatErrorMessage(err)
2178
- });
2179
- }
2180
- }
2181
- async function renderPresentationForDelivery(handler, payload) {
2182
- const presentation = normalizeMessagePresentation(payload.presentation);
2183
- if (!presentation) return payload;
2184
- const rendered = handler.renderPresentation ? await handler.renderPresentation(payload) : null;
2185
- if (rendered) {
2186
- const { presentation: _presentation, ...withoutPresentation } = rendered;
2187
- return withoutPresentation;
2188
- }
2189
- const { presentation: _presentation, ...withoutPresentation } = payload;
2190
- return {
2191
- ...withoutPresentation,
2192
- text: renderMessagePresentationFallbackText({
2193
- text: payload.text,
2194
- presentation
2195
- })
2196
- };
2197
- }
2198
- function createMessageSentEmitter(params) {
2199
- const hasMessageSentHooks = params.hookRunner?.hasHooks("message_sent") ?? false;
2200
- const canEmitInternalHook = Boolean(params.sessionKeyForInternalHooks);
2201
- const emitMessageSent = (event) => {
2202
- if (!hasMessageSentHooks && !canEmitInternalHook) return;
2203
- const canonical = buildCanonicalSentMessageHookContext({
2204
- to: params.to,
2205
- content: event.content,
2206
- success: event.success,
2207
- error: event.error,
2208
- channelId: params.channel,
2209
- accountId: params.accountId ?? void 0,
2210
- conversationId: params.to,
2211
- messageId: event.messageId,
2212
- isGroup: params.mirrorIsGroup,
2213
- groupId: params.mirrorGroupId
2214
- });
2215
- if (hasMessageSentHooks) fireAndForgetHook(params.hookRunner.runMessageSent(toPluginMessageSentEvent(canonical), toPluginMessageContext(canonical)), "deliverOutboundPayloads: message_sent plugin hook failed", (message) => {
2216
- log.warn(message);
2217
- });
2218
- if (!canEmitInternalHook) return;
2219
- fireAndForgetHook(triggerInternalHook(createInternalHookEvent("message", "sent", params.sessionKeyForInternalHooks, toInternalMessageSentContext(canonical))), "deliverOutboundPayloads: message:sent internal hook failed", (message) => {
2220
- log.warn(message);
2221
- });
2222
- };
2223
- return {
2224
- emitMessageSent,
2225
- hasMessageSentHooks
2226
- };
2227
- }
2228
- async function applyMessageSendingHook(params) {
2229
- if (!params.enabled) return {
2230
- cancelled: false,
2231
- payload: params.payload,
2232
- payloadSummary: params.payloadSummary
2233
- };
2234
- try {
2235
- const sendingResult = await params.hookRunner.runMessageSending({
2236
- to: params.to,
2237
- content: params.payloadSummary.text,
2238
- replyToId: params.payload.replyToId ?? params.replyToId ?? void 0,
2239
- threadId: params.threadId ?? void 0,
2240
- metadata: {
2241
- channel: params.channel,
2242
- accountId: params.accountId,
2243
- mediaUrls: params.payloadSummary.mediaUrls
2244
- }
2245
- }, {
2246
- channelId: params.channel,
2247
- accountId: params.accountId ?? void 0,
2248
- conversationId: params.to
2249
- });
2250
- if (sendingResult?.cancel) return {
2251
- cancelled: true,
2252
- payload: params.payload,
2253
- payloadSummary: params.payloadSummary
2254
- };
2255
- if (sendingResult?.content == null) return {
2256
- cancelled: false,
2257
- payload: params.payload,
2258
- payloadSummary: params.payloadSummary
2259
- };
2260
- return {
2261
- cancelled: false,
2262
- payload: {
2263
- ...params.payload,
2264
- text: sendingResult.content
2265
- },
2266
- payloadSummary: {
2267
- ...params.payloadSummary,
2268
- text: sendingResult.content
2269
- }
2270
- };
2271
- } catch {
2272
- return {
2273
- cancelled: false,
2274
- payload: params.payload,
2275
- payloadSummary: params.payloadSummary
2276
- };
2277
- }
2278
- }
2279
- async function deliverOutboundPayloads(params) {
2280
- const { channel, to, payloads } = params;
2281
- const queueId = params.skipQueue ? null : await enqueueDelivery({
2282
- channel,
2283
- to,
2284
- accountId: params.accountId,
2285
- payloads,
2286
- threadId: params.threadId,
2287
- replyToId: params.replyToId,
2288
- bestEffort: params.bestEffort,
2289
- gifPlayback: params.gifPlayback,
2290
- forceDocument: params.forceDocument,
2291
- silent: params.silent,
2292
- mirror: params.mirror,
2293
- session: params.session,
2294
- gatewayClientScopes: params.gatewayClientScopes
2295
- }).catch(() => null);
2296
- if (!queueId) return await deliverOutboundPayloadsWithQueueCleanup(params, null);
2297
- const claimResult = await withActiveDeliveryClaim(queueId, () => deliverOutboundPayloadsWithQueueCleanup(params, queueId));
2298
- if (claimResult.status === "claimed-by-other-owner") return [];
2299
- return claimResult.value;
2300
- }
2301
- async function deliverOutboundPayloadsWithQueueCleanup(params, queueId) {
2302
- let hadPartialFailure = false;
2303
- const wrappedParams = params.onError ? {
2304
- ...params,
2305
- onError: (err, payload) => {
2306
- hadPartialFailure = true;
2307
- params.onError(err, payload);
2308
- }
2309
- } : params;
2310
- try {
2311
- const results = await deliverOutboundPayloadsCore(wrappedParams);
2312
- if (queueId) if (hadPartialFailure) await failDelivery(queueId, "partial delivery failure (bestEffort)").catch(() => {});
2313
- else await ackDelivery(queueId).catch(() => {});
2314
- return results;
2315
- } catch (err) {
2316
- if (queueId) if (isAbortError(err)) await ackDelivery(queueId).catch(() => {});
2317
- else await failDelivery(queueId, formatErrorMessage(err)).catch(() => {});
2318
- throw err;
2319
- }
2320
- }
2321
- /** Core delivery logic (extracted for queue wrapper). */
2322
- async function deliverOutboundPayloadsCore(params) {
2323
- const { cfg, channel, to, payloads } = params;
2324
- const outboundPayloadPlan = createOutboundPayloadPlan(payloads, {
2325
- cfg,
2326
- sessionKey: params.session?.policyKey ?? params.session?.key,
2327
- surface: channel
2328
- });
2329
- const accountId = params.accountId;
2330
- const deps = params.deps;
2331
- const abortSignal = params.abortSignal;
2332
- const mediaSources = collectPayloadMediaSources(outboundPayloadPlan);
2333
- const mediaAccess = mediaSources.length > 0 ? resolveAgentScopedOutboundMediaAccess({
2334
- cfg,
2335
- agentId: params.session?.agentId ?? params.mirror?.agentId,
2336
- mediaSources,
2337
- sessionKey: params.session?.key,
2338
- messageProvider: params.session?.key ? void 0 : channel,
2339
- accountId: params.session?.requesterAccountId ?? accountId,
2340
- requesterSenderId: params.session?.requesterSenderId,
2341
- requesterSenderName: params.session?.requesterSenderName,
2342
- requesterSenderUsername: params.session?.requesterSenderUsername,
2343
- requesterSenderE164: params.session?.requesterSenderE164
2344
- }) : {};
2345
- const results = [];
2346
- const handler = await createChannelHandler({
2347
- cfg,
2348
- channel,
2349
- to,
2350
- deps,
2351
- accountId,
2352
- replyToId: params.replyToId,
2353
- threadId: params.threadId,
2354
- identity: params.identity,
2355
- gifPlayback: params.gifPlayback,
2356
- forceDocument: params.forceDocument,
2357
- silent: params.silent,
2358
- mediaAccess,
2359
- gatewayClientScopes: params.gatewayClientScopes
2360
- });
2361
- const configuredTextLimit = handler.chunker ? resolveTextChunkLimit(cfg, channel, accountId, { fallbackLimit: handler.textChunkLimit }) : void 0;
2362
- const textLimit = handler.resolveEffectiveTextChunkLimit ? handler.resolveEffectiveTextChunkLimit(configuredTextLimit) : configuredTextLimit;
2363
- const chunkMode = handler.chunker ? resolveChunkMode(cfg, channel, accountId) : "length";
2364
- const sendTextChunks = async (text, overrides) => {
2365
- throwIfAborted(abortSignal);
2366
- if (!handler.chunker || textLimit === void 0) {
2367
- results.push(await handler.sendText(text, overrides));
2368
- return;
2369
- }
2370
- if (chunkMode === "newline") {
2371
- const blockChunks = (handler.chunkerMode ?? "text") === "markdown" ? chunkMarkdownTextWithMode(text, textLimit, "newline") : chunkByParagraph(text, textLimit);
2372
- if (!blockChunks.length && text) blockChunks.push(text);
2373
- for (const blockChunk of blockChunks) {
2374
- const chunks = handler.chunker(blockChunk, textLimit);
2375
- if (!chunks.length && blockChunk) chunks.push(blockChunk);
2376
- for (const chunk of chunks) {
2377
- throwIfAborted(abortSignal);
2378
- results.push(await handler.sendText(chunk, overrides));
2379
- }
2380
- }
2381
- return;
2382
- }
2383
- const chunks = handler.chunker(text, textLimit);
2384
- for (const chunk of chunks) {
2385
- throwIfAborted(abortSignal);
2386
- results.push(await handler.sendText(chunk, overrides));
2387
- }
2388
- };
2389
- const normalizedPayloads = normalizePayloadsForChannelDelivery(outboundPayloadPlan, handler);
2390
- const hookRunner = getGlobalHookRunner();
2391
- const sessionKeyForInternalHooks = params.mirror?.sessionKey ?? params.session?.key;
2392
- const mirrorIsGroup = params.mirror?.isGroup;
2393
- const mirrorGroupId = params.mirror?.groupId;
2394
- const { emitMessageSent, hasMessageSentHooks } = createMessageSentEmitter({
2395
- hookRunner,
2396
- channel,
2397
- to,
2398
- accountId,
2399
- sessionKeyForInternalHooks,
2400
- mirrorIsGroup,
2401
- mirrorGroupId
2402
- });
2403
- const hasMessageSendingHooks = hookRunner?.hasHooks("message_sending") ?? false;
2404
- if (hasMessageSentHooks && params.session?.agentId && !sessionKeyForInternalHooks) log.warn("deliverOutboundPayloads: session.agentId present without session key; internal message:sent hook will be skipped", {
2405
- channel,
2406
- to,
2407
- agentId: params.session.agentId
2408
- });
2409
- for (const payload of normalizedPayloads) {
2410
- let payloadSummary = buildPayloadSummary(payload);
2411
- try {
2412
- throwIfAborted(abortSignal);
2413
- const hookResult = await applyMessageSendingHook({
2414
- hookRunner,
2415
- enabled: hasMessageSendingHooks,
2416
- payload,
2417
- payloadSummary,
2418
- to,
2419
- channel,
2420
- accountId,
2421
- replyToId: params.replyToId,
2422
- threadId: params.threadId
2423
- });
2424
- if (hookResult.cancelled) continue;
2425
- const effectivePayload = await renderPresentationForDelivery(handler, hookResult.payload);
2426
- payloadSummary = buildPayloadSummary(effectivePayload);
2427
- params.onPayload?.(payloadSummary);
2428
- const sendOverrides = {
2429
- replyToId: effectivePayload.replyToId ?? params.replyToId ?? void 0,
2430
- threadId: params.threadId ?? void 0,
2431
- audioAsVoice: effectivePayload.audioAsVoice === true ? true : void 0,
2432
- forceDocument: params.forceDocument
2433
- };
2434
- const deliveryTarget = handler.buildTargetRef({ threadId: sendOverrides.threadId });
2435
- if (handler.sendPayload && hasReplyPayloadContent({
2436
- presentation: effectivePayload.presentation,
2437
- interactive: effectivePayload.interactive,
2438
- channelData: effectivePayload.channelData
2439
- })) {
2440
- const delivery = await handler.sendPayload(effectivePayload, sendOverrides);
2441
- results.push(delivery);
2442
- await maybePinDeliveredMessage({
2443
- handler,
2444
- payload: effectivePayload,
2445
- target: deliveryTarget,
2446
- messageId: delivery.messageId
2447
- });
2448
- emitMessageSent({
2449
- success: true,
2450
- content: payloadSummary.text,
2451
- messageId: delivery.messageId
2452
- });
2453
- continue;
2454
- }
2455
- if (payloadSummary.mediaUrls.length === 0) {
2456
- const beforeCount = results.length;
2457
- if (handler.sendFormattedText) results.push(...await handler.sendFormattedText(payloadSummary.text, sendOverrides));
2458
- else await sendTextChunks(payloadSummary.text, sendOverrides);
2459
- const deliveredResults = results.slice(beforeCount);
2460
- const messageId = results.at(-1)?.messageId;
2461
- const pinMessageId = deliveredResults.find((entry) => entry.messageId)?.messageId;
2462
- await maybePinDeliveredMessage({
2463
- handler,
2464
- payload: effectivePayload,
2465
- target: deliveryTarget,
2466
- messageId: pinMessageId
2467
- });
2468
- emitMessageSent({
2469
- success: results.length > beforeCount,
2470
- content: payloadSummary.text,
2471
- messageId
2472
- });
2473
- continue;
2474
- }
2475
- if (!handler.supportsMedia) {
2476
- log.warn("Plugin outbound adapter does not implement sendMedia; media URLs will be dropped and text fallback will be used", {
2477
- channel,
2478
- to,
2479
- mediaCount: payloadSummary.mediaUrls.length
2480
- });
2481
- const fallbackText = payloadSummary.text.trim();
2482
- if (!fallbackText) throw new Error("Plugin outbound adapter does not implement sendMedia and no text fallback is available for media payload");
2483
- const beforeCount = results.length;
2484
- await sendTextChunks(fallbackText, sendOverrides);
2485
- const deliveredResults = results.slice(beforeCount);
2486
- const messageId = results.at(-1)?.messageId;
2487
- const pinMessageId = deliveredResults.find((entry) => entry.messageId)?.messageId;
2488
- await maybePinDeliveredMessage({
2489
- handler,
2490
- payload: effectivePayload,
2491
- target: deliveryTarget,
2492
- messageId: pinMessageId
2493
- });
2494
- emitMessageSent({
2495
- success: results.length > beforeCount,
2496
- content: payloadSummary.text,
2497
- messageId
2498
- });
2499
- continue;
2500
- }
2501
- let firstMessageId;
2502
- let lastMessageId;
2503
- await sendMediaWithLeadingCaption({
2504
- mediaUrls: payloadSummary.mediaUrls,
2505
- caption: payloadSummary.text,
2506
- send: async ({ mediaUrl, caption }) => {
2507
- throwIfAborted(abortSignal);
2508
- if (handler.sendFormattedMedia) {
2509
- const delivery = await handler.sendFormattedMedia(caption ?? "", mediaUrl, sendOverrides);
2510
- results.push(delivery);
2511
- firstMessageId ??= delivery.messageId;
2512
- lastMessageId = delivery.messageId;
2513
- return;
2514
- }
2515
- const delivery = await handler.sendMedia(caption ?? "", mediaUrl, sendOverrides);
2516
- results.push(delivery);
2517
- firstMessageId ??= delivery.messageId;
2518
- lastMessageId = delivery.messageId;
2519
- }
2520
- });
2521
- await maybePinDeliveredMessage({
2522
- handler,
2523
- payload: effectivePayload,
2524
- target: deliveryTarget,
2525
- messageId: firstMessageId
2526
- });
2527
- emitMessageSent({
2528
- success: true,
2529
- content: payloadSummary.text,
2530
- messageId: lastMessageId
2531
- });
2532
- } catch (err) {
2533
- emitMessageSent({
2534
- success: false,
2535
- content: payloadSummary.text,
2536
- error: formatErrorMessage(err)
2537
- });
2538
- if (!params.bestEffort) throw err;
2539
- params.onError?.(err, payloadSummary);
2540
- }
2541
- }
2542
- if (params.mirror && results.length > 0) {
2543
- const mirrorText = resolveMirroredTranscriptText({
2544
- text: params.mirror.text,
2545
- mediaUrls: params.mirror.mediaUrls
2546
- });
2547
- if (mirrorText) {
2548
- const { appendAssistantMessageToSessionTranscript } = await loadTranscriptRuntime();
2549
- await appendAssistantMessageToSessionTranscript({
2550
- agentId: params.mirror.agentId,
2551
- sessionKey: params.mirror.sessionKey,
2552
- text: mirrorText,
2553
- idempotencyKey: params.mirror.idempotencyKey
2554
- });
2555
- }
2556
- }
2557
- return results;
2558
- }
2559
- //#endregion
2560
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/channel-resolution-Bpi0M4FM.js
2561
- function normalizeDeliverableOutboundChannel(raw) {
2562
- const normalized = normalizeMessageChannel(raw);
2563
- if (!normalized || !isDeliverableMessageChannel(normalized)) return;
2564
- return normalized;
2565
- }
2566
- function maybeBootstrapChannelPlugin(params) {
2567
- bootstrapOutboundChannelPlugin(params);
2568
- }
2569
- function resolveDirectFromActiveRegistry(channel) {
2570
- const activeRegistry = getActivePluginRegistry();
2571
- if (!activeRegistry) return;
2572
- for (const entry of activeRegistry.channels) {
2573
- const plugin = entry?.plugin;
2574
- if (plugin?.id === channel) return plugin;
2575
- }
2576
- }
2577
- function resolveOutboundChannelPlugin(params) {
2578
- const normalized = normalizeDeliverableOutboundChannel(params.channel);
2579
- if (!normalized) return;
2580
- const resolveLoaded = () => getLoadedChannelPlugin(normalized);
2581
- const resolve = () => getChannelPlugin(normalized);
2582
- const current = resolveLoaded();
2583
- if (current) return current;
2584
- const directCurrent = resolveDirectFromActiveRegistry(normalized);
2585
- if (directCurrent) return directCurrent;
2586
- maybeBootstrapChannelPlugin({
2587
- channel: normalized,
2588
- cfg: params.cfg
2589
- });
2590
- return resolveLoaded() ?? resolveDirectFromActiveRegistry(normalized) ?? resolve();
2591
- }
2592
- //#endregion
2593
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/channel-selection-uZ6StxpE.js
2594
- const getMessageChannels = () => listDeliverableMessageChannels();
2595
- function isKnownChannel(value) {
2596
- return getMessageChannels().includes(value);
2597
- }
2598
- function resolveKnownChannel(value) {
2599
- const normalized = normalizeMessageChannel(value);
2600
- if (!normalized) return;
2601
- if (!isDeliverableMessageChannel(normalized)) return;
2602
- if (!isKnownChannel(normalized)) return;
2603
- return normalized;
2604
- }
2605
- function resolveAvailableKnownChannel(params) {
2606
- const normalized = resolveKnownChannel(params.value);
2607
- if (!normalized) return;
2608
- return resolveOutboundChannelPlugin({
2609
- channel: normalized,
2610
- cfg: params.cfg
2611
- }) ? normalized : void 0;
2612
- }
2613
- function isAccountEnabled(account) {
2614
- if (!account || typeof account !== "object") return true;
2615
- return account.enabled !== false;
2616
- }
2617
- const loggedChannelSelectionErrors = /* @__PURE__ */ new Set();
2618
- function logChannelSelectionError(params) {
2619
- const message = formatErrorMessage(params.error);
2620
- const key = `${params.pluginId}:${params.accountId}:${params.operation}:${message}`;
2621
- if (loggedChannelSelectionErrors.has(key)) return;
2622
- loggedChannelSelectionErrors.add(key);
2623
- defaultRuntime.error?.(`[channel-selection] ${params.pluginId}(${params.accountId}) ${params.operation} failed: ${message}`);
2624
- }
2625
- async function isPluginConfigured(plugin, cfg) {
2626
- const accountIds = plugin.config.listAccountIds(cfg);
2627
- if (accountIds.length === 0) return false;
2628
- for (const accountId of accountIds) {
2629
- let account;
2630
- try {
2631
- account = plugin.config.resolveAccount(cfg, accountId);
2632
- } catch (error) {
2633
- logChannelSelectionError({
2634
- pluginId: plugin.id,
2635
- accountId,
2636
- operation: "resolveAccount",
2637
- error
2638
- });
2639
- continue;
2640
- }
2641
- if (!(plugin.config.isEnabled ? plugin.config.isEnabled(account, cfg) : isAccountEnabled(account))) continue;
2642
- if (!plugin.config.isConfigured) return true;
2643
- let configured = false;
2644
- try {
2645
- configured = await plugin.config.isConfigured(account, cfg);
2646
- } catch (error) {
2647
- logChannelSelectionError({
2648
- pluginId: plugin.id,
2649
- accountId,
2650
- operation: "isConfigured",
2651
- error
2652
- });
2653
- continue;
2654
- }
2655
- if (configured) return true;
2656
- }
2657
- return false;
2658
- }
2659
- async function listConfiguredMessageChannels(cfg) {
2660
- const channels = [];
2661
- for (const plugin of listChannelPlugins()) {
2662
- if (!isKnownChannel(plugin.id)) continue;
2663
- if (await isPluginConfigured(plugin, cfg)) channels.push(plugin.id);
2664
- }
2665
- return channels;
2666
- }
2667
- async function resolveMessageChannelSelection(params) {
2668
- const normalized = normalizeMessageChannel(params.channel);
2669
- if (normalized) {
2670
- const availableExplicit = resolveAvailableKnownChannel({
2671
- cfg: params.cfg,
2672
- value: normalized
2673
- });
2674
- if (!availableExplicit) {
2675
- const fallback = resolveAvailableKnownChannel({
2676
- cfg: params.cfg,
2677
- value: params.fallbackChannel
2678
- });
2679
- if (fallback) return {
2680
- channel: fallback,
2681
- configured: [],
2682
- source: "tool-context-fallback"
2683
- };
2684
- if (!isKnownChannel(normalized)) throw new Error(`Unknown channel: ${normalized}`);
2685
- throw new Error(`Channel is unavailable: ${normalized}`);
2686
- }
2687
- return {
2688
- channel: availableExplicit,
2689
- configured: [],
2690
- source: "explicit"
2691
- };
2692
- }
2693
- const fallback = resolveAvailableKnownChannel({
2694
- cfg: params.cfg,
2695
- value: params.fallbackChannel
2696
- });
2697
- if (fallback) return {
2698
- channel: fallback,
2699
- configured: [],
2700
- source: "tool-context-fallback"
2701
- };
2702
- const configured = await listConfiguredMessageChannels(params.cfg);
2703
- if (configured.length === 1) return {
2704
- channel: configured[0],
2705
- configured,
2706
- source: "single-configured"
2707
- };
2708
- if (configured.length === 0) throw new Error("Channel is required (no configured channels detected).");
2709
- throw new Error(`Channel is required when multiple channels are configured: ${configured.join(", ")}`);
2710
- }
2711
- //#endregion
2712
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/target-errors-DWCwFi1f.js
2713
- function missingTargetMessage(provider, hint) {
2714
- return `Delivering to ${provider} requires target${formatTargetHint(hint)}`;
2715
- }
2716
- function missingTargetError(provider, hint) {
2717
- return new Error(missingTargetMessage(provider, hint));
2718
- }
2719
- function formatTargetHint(hint, withLabel = false) {
2720
- const normalized = hint?.trim();
2721
- if (!normalized) return "";
2722
- return withLabel ? ` Hint: ${normalized}` : ` ${normalized}`;
2723
- }
2724
- //#endregion
2725
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/channel-config-helpers-DprVFCfq.js
2726
- /** Coerce mixed allowlist config values into plain strings without trimming or deduping. */
2727
- function mapAllowFromEntries(allowFrom) {
2728
- return (allowFrom ?? []).map((entry) => String(entry));
2729
- }
2730
- //#endregion
2731
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/targets-session-CrpEdT9S.js
2732
- function buildWebChatDeliveryError() {
2733
- return /* @__PURE__ */ new Error(`Delivering to WebChat is not supported via \`${formatCliCommand("openclaw agent")}\`; use WhatsApp/Telegram or run with --deliver=false.`);
2734
- }
2735
- function resolveOutboundTargetWithPlugin(params) {
2736
- if (params.target.channel === "webchat") return {
2737
- ok: false,
2738
- error: buildWebChatDeliveryError()
2739
- };
2740
- const plugin = params.plugin;
2741
- if (!plugin) return params.onMissingPlugin?.();
2742
- const allowFromRaw = params.target.allowFrom ?? (params.target.cfg && plugin.config.resolveAllowFrom ? plugin.config.resolveAllowFrom({
2743
- cfg: params.target.cfg,
2744
- accountId: params.target.accountId ?? void 0
2745
- }) : void 0);
2746
- const allowFrom = allowFromRaw ? mapAllowFromEntries(allowFromRaw) : void 0;
2747
- const effectiveTo = params.target.to?.trim() || (params.target.cfg && plugin.config.resolveDefaultTo ? plugin.config.resolveDefaultTo({
2748
- cfg: params.target.cfg,
2749
- accountId: params.target.accountId ?? void 0
2750
- }) : void 0);
2751
- const resolveTarget = plugin.outbound?.resolveTarget;
2752
- if (resolveTarget) return resolveTarget({
2753
- cfg: params.target.cfg,
2754
- to: effectiveTo,
2755
- allowFrom,
2756
- accountId: params.target.accountId ?? void 0,
2757
- mode: params.target.mode ?? "explicit"
2758
- });
2759
- if (effectiveTo) return {
2760
- ok: true,
2761
- to: effectiveTo
2762
- };
2763
- const hint = plugin.messaging?.targetResolver?.hint;
2764
- return {
2765
- ok: false,
2766
- error: missingTargetError(plugin.meta.label ?? params.target.channel, hint)
2767
- };
2768
- }
2769
- //#endregion
2770
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/targets-DMtF6TU_.js
2771
- function resolveOutboundTarget(params) {
2772
- return resolveOutboundTargetWithPlugin({
2773
- plugin: resolveOutboundChannelPlugin({
2774
- channel: params.channel,
2775
- cfg: params.cfg
2776
- }),
2777
- target: params,
2778
- onMissingPlugin: () => params.channel === "webchat" ? void 0 : {
2779
- ok: false,
2780
- error: /* @__PURE__ */ new Error(`Unsupported channel: ${params.channel}`)
2781
- }
2782
- }) ?? {
2783
- ok: false,
2784
- error: /* @__PURE__ */ new Error(`Unsupported channel: ${params.channel}`)
2785
- };
2786
- }
2787
- //#endregion
2788
- //#region node_modules/.pnpm/openclaw@2026.4.22_@napi-rs+canvas@0.1.99/node_modules/openclaw/dist/message-ClDCyV3_.js
2789
- let messageConfigRuntimePromise = null;
2790
- let messageGatewayRuntimePromise = null;
2791
- function loadMessageConfigRuntime() {
2792
- messageConfigRuntimePromise ??= import("./message.config.runtime-K-k4XOyq-DZTmXomP.mjs");
2793
- return messageConfigRuntimePromise;
2794
- }
2795
- function loadMessageGatewayRuntime() {
2796
- messageGatewayRuntimePromise ??= import("./message.gateway.runtime-DqHOHRTQ-DH4ml0YF.mjs");
2797
- return messageGatewayRuntimePromise;
2798
- }
2799
- async function resolveRequiredChannel(params) {
2800
- return (await resolveMessageChannelSelection({
2801
- cfg: params.cfg,
2802
- channel: params.channel
2803
- })).channel;
2804
- }
2805
- function resolveRequiredPlugin(channel, cfg) {
2806
- const plugin = resolveOutboundChannelPlugin({
2807
- channel,
2808
- cfg
2809
- });
2810
- if (!plugin) throw new Error(`Unknown channel: ${channel}`);
2811
- return plugin;
2812
- }
2813
- function resolveGatewayOptions(opts) {
2814
- return {
2815
- url: opts?.mode === GATEWAY_CLIENT_MODES.BACKEND || opts?.clientName === GATEWAY_CLIENT_NAMES.GATEWAY_CLIENT ? void 0 : opts?.url,
2816
- token: opts?.token,
2817
- timeoutMs: typeof opts?.timeoutMs === "number" && Number.isFinite(opts.timeoutMs) ? Math.max(1, Math.floor(opts.timeoutMs)) : 1e4,
2818
- clientName: opts?.clientName ?? GATEWAY_CLIENT_NAMES.CLI,
2819
- clientDisplayName: opts?.clientDisplayName,
2820
- mode: opts?.mode ?? GATEWAY_CLIENT_MODES.CLI
2821
- };
2822
- }
2823
- async function callMessageGateway(params) {
2824
- const { callGatewayLeastPrivilege } = await loadMessageGatewayRuntime();
2825
- const gateway = resolveGatewayOptions(params.gateway);
2826
- return await callGatewayLeastPrivilege({
2827
- url: gateway.url,
2828
- token: gateway.token,
2829
- method: params.method,
2830
- params: params.params,
2831
- timeoutMs: gateway.timeoutMs,
2832
- clientName: gateway.clientName,
2833
- clientDisplayName: gateway.clientDisplayName,
2834
- mode: gateway.mode
2835
- });
2836
- }
2837
- async function resolveMessageConfig(cfg) {
2838
- if (cfg) return cfg;
2839
- const { loadConfig } = await loadMessageConfigRuntime();
2840
- return loadConfig();
2841
- }
2842
- async function resolveGatewayIdempotencyKey(idempotencyKey) {
2843
- if (idempotencyKey) return idempotencyKey;
2844
- const { randomIdempotencyKey } = await loadMessageGatewayRuntime();
2845
- return randomIdempotencyKey();
2846
- }
2847
- async function sendMessage(params) {
2848
- const cfg = await resolveMessageConfig(params.cfg);
2849
- const channel = await resolveRequiredChannel({
2850
- cfg,
2851
- channel: params.channel
2852
- });
2853
- const deliveryMode = resolveRequiredPlugin(channel, cfg).outbound?.deliveryMode ?? "direct";
2854
- const outboundPlan = createOutboundPayloadPlan([{
2855
- text: params.content,
2856
- mediaUrl: params.mediaUrl,
2857
- mediaUrls: params.mediaUrls
2858
- }]);
2859
- const normalizedPayloads = projectOutboundPayloadPlanForDelivery(outboundPlan);
2860
- const mirrorProjection = projectOutboundPayloadPlanForMirror(outboundPlan);
2861
- const mirrorText = mirrorProjection.text;
2862
- const mirrorMediaUrls = mirrorProjection.mediaUrls;
2863
- const primaryMediaUrl = mirrorMediaUrls[0] ?? params.mediaUrl ?? null;
2864
- if (params.dryRun) return {
2865
- channel,
2866
- to: params.to,
2867
- via: deliveryMode === "gateway" ? "gateway" : "direct",
2868
- mediaUrl: primaryMediaUrl,
2869
- mediaUrls: mirrorMediaUrls.length ? mirrorMediaUrls : void 0,
2870
- dryRun: true
2871
- };
2872
- if (deliveryMode !== "gateway") {
2873
- const outboundChannel = channel;
2874
- const resolvedTarget = resolveOutboundTarget({
2875
- channel: outboundChannel,
2876
- to: params.to,
2877
- cfg,
2878
- accountId: params.accountId,
2879
- mode: "explicit"
2880
- });
2881
- if (!resolvedTarget.ok) throw resolvedTarget.error;
2882
- const outboundSession = buildOutboundSessionContext({
2883
- cfg,
2884
- agentId: params.agentId,
2885
- sessionKey: params.requesterSessionKey ?? params.mirror?.sessionKey,
2886
- requesterAccountId: params.requesterAccountId ?? params.accountId,
2887
- requesterSenderId: params.requesterSenderId,
2888
- requesterSenderName: params.requesterSenderName,
2889
- requesterSenderUsername: params.requesterSenderUsername,
2890
- requesterSenderE164: params.requesterSenderE164
2891
- });
2892
- const results = await deliverOutboundPayloads({
2893
- cfg,
2894
- channel: outboundChannel,
2895
- to: resolvedTarget.to,
2896
- session: outboundSession,
2897
- accountId: params.accountId,
2898
- payloads: normalizedPayloads,
2899
- replyToId: params.replyToId,
2900
- threadId: params.threadId,
2901
- gifPlayback: params.gifPlayback,
2902
- forceDocument: params.forceDocument,
2903
- deps: params.deps,
2904
- bestEffort: params.bestEffort,
2905
- abortSignal: params.abortSignal,
2906
- silent: params.silent,
2907
- mirror: params.mirror ? {
2908
- ...params.mirror,
2909
- text: mirrorText || params.content,
2910
- mediaUrls: mirrorMediaUrls.length ? mirrorMediaUrls : void 0,
2911
- idempotencyKey: params.mirror.idempotencyKey ?? params.idempotencyKey
2912
- } : void 0
2913
- });
2914
- return {
2915
- channel,
2916
- to: params.to,
2917
- via: "direct",
2918
- mediaUrl: primaryMediaUrl,
2919
- mediaUrls: mirrorMediaUrls.length ? mirrorMediaUrls : void 0,
2920
- result: results.at(-1)
2921
- };
2922
- }
2923
- const result = await callMessageGateway({
2924
- gateway: params.gateway,
2925
- method: "send",
2926
- params: {
2927
- to: params.to,
2928
- message: params.content,
2929
- mediaUrl: params.mediaUrl,
2930
- mediaUrls: mirrorMediaUrls.length ? mirrorMediaUrls : params.mediaUrls,
2931
- gifPlayback: params.gifPlayback,
2932
- accountId: params.accountId,
2933
- agentId: params.agentId,
2934
- channel,
2935
- replyToId: params.replyToId,
2936
- sessionKey: params.mirror?.sessionKey,
2937
- idempotencyKey: await resolveGatewayIdempotencyKey(params.idempotencyKey)
2938
- }
2939
- });
2940
- return {
2941
- channel,
2942
- to: params.to,
2943
- via: "gateway",
2944
- mediaUrl: primaryMediaUrl,
2945
- mediaUrls: mirrorMediaUrls.length ? mirrorMediaUrls : void 0,
2946
- result
2947
- };
2948
- }
2949
- //#endregion
2950
- export { parseReplyDirectives as n, registerPendingSpawnedChildrenQuery as r, sendMessage as t };