silentlake 2026.3.24

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 (1893) hide show
  1. package/CHANGELOG.md +4587 -0
  2. package/LICENSE +21 -0
  3. package/README.md +248 -0
  4. package/assets/avatar-placeholder.svg +19 -0
  5. package/assets/chrome-extension/icons/icon128.png +0 -0
  6. package/assets/chrome-extension/icons/icon16.png +0 -0
  7. package/assets/chrome-extension/icons/icon32.png +0 -0
  8. package/assets/chrome-extension/icons/icon48.png +0 -0
  9. package/assets/dmg-background-small.png +0 -0
  10. package/assets/dmg-background.png +0 -0
  11. package/assets/silentlake-banner.png +0 -0
  12. package/dist/APEv2Parser-BZv_dP9t.js +269 -0
  13. package/dist/APEv2Parser-CPzxFNBB.js +5 -0
  14. package/dist/AbstractID3Parser-mvDFcjYV.js +47 -0
  15. package/dist/AiffParser-BXQ9SRZk.js +145 -0
  16. package/dist/AsfParser-CmBDUlZE.js +631 -0
  17. package/dist/BasicParser-DhmXREDo.js +853 -0
  18. package/dist/DsdiffParser-CTKKGyZg.js +150 -0
  19. package/dist/DsfParser-Ds-YQe4Z.js +101 -0
  20. package/dist/FlacParser-B1XVPgXF.js +5 -0
  21. package/dist/FlacParser-DMPyL1y4.js +367 -0
  22. package/dist/ID3v1Parser-BICWWVDG.js +289 -0
  23. package/dist/ID3v2Parser-BmZHSUqs.js +650 -0
  24. package/dist/ID3v2Token-DeJf4tYQ.js +145 -0
  25. package/dist/MP4Parser-Cjf-Zs8T.js +1061 -0
  26. package/dist/MatroskaParser-DgBzBe8t.js +909 -0
  27. package/dist/MpegParser-D5swTpA1.js +744 -0
  28. package/dist/MusepackParser-D8EQXnpK.js +285 -0
  29. package/dist/OggParser-BcIYPHwP.js +390 -0
  30. package/dist/Util-D_zGsr97.js +170 -0
  31. package/dist/WavPackParser-hosU8gfo.js +166 -0
  32. package/dist/WaveParser-CA00FZrC.js +273 -0
  33. package/dist/abort-cutoff-CERmtgZI.js +56 -0
  34. package/dist/abort-cutoff.runtime-DZkGKKzv.js +61 -0
  35. package/dist/abort-signal-CsrBEr94.js +13 -0
  36. package/dist/account-helpers-D3c_eI7c.js +37 -0
  37. package/dist/account-helpers-ru3jdZSV.js +12 -0
  38. package/dist/account-id-DZnNZg8x.js +1 -0
  39. package/dist/account-id-ZCrgXl7Z.js +44 -0
  40. package/dist/account-lookup-nkoa-foB.js +10 -0
  41. package/dist/account-snapshot-fields-Cvq7803C.js +116 -0
  42. package/dist/account-summary-B5Xzvntm.js +36 -0
  43. package/dist/accounts-43SvCDEA.js +212 -0
  44. package/dist/accounts-CYgFhv2o.js +105 -0
  45. package/dist/accounts-ChlyF7cx.js +112 -0
  46. package/dist/ack-reactions-CNVwfOBj.js +43 -0
  47. package/dist/acp-cli-B4Rv7-xU.js +2033 -0
  48. package/dist/acp-runtime-BdLdT-QY.js +1 -0
  49. package/dist/actions.runtime-CqnQssoB.js +217 -0
  50. package/dist/actions.runtime-FLmCvVRd.js +236 -0
  51. package/dist/agent-CBOdzEvR.js +1 -0
  52. package/dist/agent-scope-BLhzf-o0.js +17 -0
  53. package/dist/agent-scope-DPP4Z_UU.js +193 -0
  54. package/dist/agents-D8pBK0II.js +855 -0
  55. package/dist/agents-Dihz1Ihx.js +323 -0
  56. package/dist/agents.config-C_lrnc9J.js +18 -0
  57. package/dist/agents.config-D1VqC78r.js +121 -0
  58. package/dist/allow-from-BPSBITdd.js +9 -0
  59. package/dist/allow-from-BwTLpvhp.js +20 -0
  60. package/dist/allow-from-C4iBpqFI.js +62 -0
  61. package/dist/allowlist-config-edit-CKbnMmwS.js +279 -0
  62. package/dist/allowlist-match-CYmPgg1K.js +63 -0
  63. package/dist/ansi-BEJF8NKS.js +54 -0
  64. package/dist/anthropic-vertex-provider-Dd5agCN9.js +60 -0
  65. package/dist/apply.runtime-DhKxNSJE.js +370 -0
  66. package/dist/apply.runtime-ghlh-P6X.js +211 -0
  67. package/dist/archive-Tr0wIUO-.js +532 -0
  68. package/dist/arg-split-Dtda0YDl.js +38 -0
  69. package/dist/artifacts-C_4LekPC.js +39 -0
  70. package/dist/audit-BOPSQQtd.js +54 -0
  71. package/dist/audit-C5kdrCi_.js +788 -0
  72. package/dist/audit-channel.allow-from.runtime-B7BHNblL.js +17 -0
  73. package/dist/audit-channel.collect.runtime-CjAbXFBV.js +521 -0
  74. package/dist/audit-channel.discord.runtime-BBY6S9lg.js +5 -0
  75. package/dist/audit-channel.telegram.runtime-SJnxOJH2.js +8 -0
  76. package/dist/audit-channel.zalouser.runtime-SGRWvHxT.js +5 -0
  77. package/dist/audit-extra.async-DY8v7LXH.js +817 -0
  78. package/dist/audit-fs-oDMUa5N_.js +375 -0
  79. package/dist/audit-membership-runtime-BPjFryEx.js +261 -0
  80. package/dist/audit.deep.runtime-WFf-TpsD.js +31 -0
  81. package/dist/audit.nondeep.runtime-B4BaEaRU.js +842 -0
  82. package/dist/audit.runtime-rFjCrods.js +74 -0
  83. package/dist/auth-O6LQFLHJ.js +416 -0
  84. package/dist/auth-choice-DIBaxmAQ.js +219 -0
  85. package/dist/auth-choice-PrbpIjyg.js +610 -0
  86. package/dist/auth-choice-legacy-Clyw2lVc.js +17 -0
  87. package/dist/auth-choice-options-ohUw8QR-.js +127 -0
  88. package/dist/auth-choice-prompt-Cm0s-9Du.js +215 -0
  89. package/dist/auth-choice-prompt-DI-Xl1Nv.js +36 -0
  90. package/dist/auth-choice-rKBOd02a.js +64 -0
  91. package/dist/auth-choice.apply-helpers-BibBSEl9.js +66 -0
  92. package/dist/auth-choice.plugin-providers.runtime-gqF9NO7_.js +219 -0
  93. package/dist/auth-health-TWboMYA5.js +166 -0
  94. package/dist/auth-mode-policy-DywddkT-.js +18 -0
  95. package/dist/auth-profiles-CWEIQV77.js +1047 -0
  96. package/dist/auth-profiles.runtime-B98lwopF.js +48 -0
  97. package/dist/avatar-policy-Ds9e6uHI.js +67 -0
  98. package/dist/axios-xDDnM0KG.js +12831 -0
  99. package/dist/backup-create-B6JAR6jJ.js +461 -0
  100. package/dist/banner-bez5CpOK.js +351 -0
  101. package/dist/base-session-key-Cf2rkwag.js +14 -0
  102. package/dist/bindings-BV4AtNSY.js +21 -0
  103. package/dist/bindings-kjwuC11Q.js +69 -0
  104. package/dist/bluebubbles-C1M3Geg0.js +87 -0
  105. package/dist/bluebubbles-DRW3JdOY.js +603 -0
  106. package/dist/bluebubbles-dEl4QpYz.js +37 -0
  107. package/dist/bonjour-discovery-C2oY96BG.js +376 -0
  108. package/dist/boolean-DKtCJu_W.js +29 -0
  109. package/dist/boolean-param-xAGXUSSN.js +13 -0
  110. package/dist/boundary-file-read-BP6VMpqH.js +106 -0
  111. package/dist/boundary-path-B3FFLYNx.js +557 -0
  112. package/dist/brave-CkimJe4j.js +405 -0
  113. package/dist/brew-DSwWqzLd.js +44 -0
  114. package/dist/browser-cli-D3kBUBNc.js +1502 -0
  115. package/dist/bundled/boot-md/handler.js +381 -0
  116. package/dist/bundled/bootstrap-extra-files/handler.js +56 -0
  117. package/dist/bundled/command-logger/handler.js +62 -0
  118. package/dist/bundled/session-memory/handler.js +401 -0
  119. package/dist/call-BDvaXe4i.js +44 -0
  120. package/dist/call-BmLt3xO1.js +639 -0
  121. package/dist/catalog-BwAYUfL7.js +240 -0
  122. package/dist/channel-BBCuV5OT.js +4945 -0
  123. package/dist/channel-BDBXuqeg.js +321 -0
  124. package/dist/channel-C8h1Irxm.js +1284 -0
  125. package/dist/channel-CbGpFzo4.js +1602 -0
  126. package/dist/channel-Ci3K8fI9.js +1006 -0
  127. package/dist/channel-DGT5N1v7.js +1077 -0
  128. package/dist/channel-account-context-Bwa-YH_o.js +104 -0
  129. package/dist/channel-actions-DU2CR3xW.js +37 -0
  130. package/dist/channel-activity-B8aReQoE.js +35 -0
  131. package/dist/channel-config-3Uv6ve2_.js +115 -0
  132. package/dist/channel-config-helpers-CieQWILI.js +377 -0
  133. package/dist/channel-config-schema-DEVsCZpj.js +1 -0
  134. package/dist/channel-feedback-G6zh8efr.js +245 -0
  135. package/dist/channel-inbound-DwzVf2PK.js +395 -0
  136. package/dist/channel-lifecycle-CpU1dRbh.js +354 -0
  137. package/dist/channel-options-DJaIP4Dv.js +38 -0
  138. package/dist/channel-pairing-D54mn51y.js +66 -0
  139. package/dist/channel-plugin-common-BhTxCE5t.js +1 -0
  140. package/dist/channel-plugin-ids-CFeS3qir.js +26 -0
  141. package/dist/channel-plugin-resolution-DUngfdFj.js +112 -0
  142. package/dist/channel-policy-C4GKHvhz.js +1 -0
  143. package/dist/channel-reply-pipeline-CPTuaW8n.js +15 -0
  144. package/dist/channel-send-result-By8EpCPw.js +40 -0
  145. package/dist/channel-setup-Ck35g7zI.js +49 -0
  146. package/dist/channel-shared-LkXtTPXk.js +308 -0
  147. package/dist/channel-summary-CdYLGMVt.js +137 -0
  148. package/dist/channel-summary-D33z52ft.js +41 -0
  149. package/dist/channel-targets-DfnKGXez.js +87 -0
  150. package/dist/channel.runtime-DAyBR2A5.js +324 -0
  151. package/dist/channel.runtime-DVq5tC2D.js +35 -0
  152. package/dist/channel.runtime-DaLTDGtF.js +288 -0
  153. package/dist/channel.runtime-FKfTev2g.js +512 -0
  154. package/dist/channel.runtime-owqedh1t.js +268 -0
  155. package/dist/channel.runtime-wOTeiifp.js +230 -0
  156. package/dist/channels-CIHgkPea.js +408 -0
  157. package/dist/channels-ZXK6Jiuk.js +1393 -0
  158. package/dist/channels-cli-Bj6qSlkE.js +412 -0
  159. package/dist/channels-status-issues-C_U44M8Y.js +16 -0
  160. package/dist/chat-type-C-n03mQY.js +10 -0
  161. package/dist/clack-prompter-DuzDnaLi.js +112 -0
  162. package/dist/clawbot-cli-YNPuwmTB.js +218 -0
  163. package/dist/cli/daemon-cli.js +88 -0
  164. package/dist/cli-CW46WAZn.js +254 -0
  165. package/dist/cli-name-Daok7A7-.js +25 -0
  166. package/dist/cli-runtime-aAVwbEYy.js +7 -0
  167. package/dist/cli-utils-Np4NAAtt.js +39 -0
  168. package/dist/command-format-CYK9XiUC.js +16 -0
  169. package/dist/command-format-g8YUHNir.js +2 -0
  170. package/dist/command-gating-BQXGSqc9.js +40 -0
  171. package/dist/command-options-5coRiipK.js +25 -0
  172. package/dist/command-poll-backoff-CpkSns-6.js +56 -0
  173. package/dist/command-poll-backoff.runtime-YT6EGcLN.js +7 -0
  174. package/dist/command-registry-BI2MOs89.js +242 -0
  175. package/dist/command-registry-BMsxnuoC.js +14 -0
  176. package/dist/command-secret-gateway-ChXyZwos.js +211 -0
  177. package/dist/command-secret-targets-COcwhn-D.js +88 -0
  178. package/dist/command-secret-targets-CQJT3viO.js +3 -0
  179. package/dist/commands-Bb9xUwz9.js +42 -0
  180. package/dist/commands-core-C1usZXC2.js +4923 -0
  181. package/dist/commands-core.runtime-OTZivlO2.js +232 -0
  182. package/dist/commands-registry-ChCep1KJ.js +295 -0
  183. package/dist/commands-registry.data-XyUTELK9.js +904 -0
  184. package/dist/commands-registry.runtime-m5WTxFtv.js +25 -0
  185. package/dist/commands-status.runtime-C8_hpNgj.js +211 -0
  186. package/dist/commands.runtime-BZPnQKcW.js +232 -0
  187. package/dist/common-CUBlLRXB.js +457 -0
  188. package/dist/compact.runtime-Djmzpbn6.js +216 -0
  189. package/dist/completion-cli-D8tLgE5W.js +445 -0
  190. package/dist/completion-cli-Dz89naVA.js +17 -0
  191. package/dist/config-6sZwvXJD.js +88 -0
  192. package/dist/config-B7tPwoHZ.js +38 -0
  193. package/dist/config-DdDLrP_v.js +273 -0
  194. package/dist/config-cli-C10R8azD.js +945 -0
  195. package/dist/config-guard-B1c73BYQ.js +126 -0
  196. package/dist/config-helpers-3u5wfLBu.js +117 -0
  197. package/dist/config-pn7LKJdW.js +23 -0
  198. package/dist/config-presence-BmUF_5K9.js +79 -0
  199. package/dist/config-regex-CvZFnWkO.js +39 -0
  200. package/dist/config-runtime-CstET7fq.js +142 -0
  201. package/dist/config-schema-5YkIW1xw.js +270 -0
  202. package/dist/config-schema-B1UGMwZ8.js +31 -0
  203. package/dist/config-schema-DzlnsY3D.js +33 -0
  204. package/dist/config-state-CE0CGjey.js +288 -0
  205. package/dist/config-validation-CkVqgkHr.js +272 -0
  206. package/dist/config-value-DgJrpclm.js +25 -0
  207. package/dist/configure-DMkp7Sr4.js +1126 -0
  208. package/dist/configure-DOrQthLy.js +344 -0
  209. package/dist/connection-auth-BSQJeDOU.js +30 -0
  210. package/dist/constants-C_Scc680.js +71 -0
  211. package/dist/control-ui-assets-DjqeIg6A.js +232 -0
  212. package/dist/control-ui-shared-DP000Pxd.js +29 -0
  213. package/dist/conversation-runtime-1O0Aaolb.js +1458 -0
  214. package/dist/core-C7aHA4Aq.js +187 -0
  215. package/dist/core-command-descriptors-DCUYAEZd.js +96 -0
  216. package/dist/credentials-BPwBlm1X.js +265 -0
  217. package/dist/cron-cli-N2Hw_02d.js +579 -0
  218. package/dist/daemon-cli-DgfaF9xx.js +354 -0
  219. package/dist/daemon-install-CbclJo5M.js +134 -0
  220. package/dist/daemon-install-plan.shared-DK6BHlWI.js +222 -0
  221. package/dist/daemon-runtime-CbClrCwc.js +12 -0
  222. package/dist/dangerous-config-flags-BJtLWIk7.js +15 -0
  223. package/dist/dangerous-name-matching-DZa_t0RM.js +44 -0
  224. package/dist/dangerous-tools-yGPDFTHh.js +27 -0
  225. package/dist/date-time-DCAyaBop.js +118 -0
  226. package/dist/dedupe-Cgnk5BbX.js +55 -0
  227. package/dist/defaults-CEdZhIIb.js +6 -0
  228. package/dist/delegate-D4ql5N70.js +43 -0
  229. package/dist/deliver-B004w1Mv.js +212 -0
  230. package/dist/deliver-runtime-IYvc0giI.js +211 -0
  231. package/dist/delivery-queue-B19wDCjT.js +3 -0
  232. package/dist/delivery-queue-DrrqB4Hi.js +299 -0
  233. package/dist/device-auth-GEXe9vqR.js +15 -0
  234. package/dist/device-bootstrap-CwwokLEY.js +96 -0
  235. package/dist/device-bootstrap-Dbhe6oe8.js +1 -0
  236. package/dist/device-metadata-normalization-BDSQ_eA7.js +21 -0
  237. package/dist/device-pairing-cFWbBray.js +553 -0
  238. package/dist/devices-cli-DzycjFzS.js +366 -0
  239. package/dist/diagnostic-DqJXx_4Q.js +310 -0
  240. package/dist/diagnostic-events-ktCoG8Br.js +48 -0
  241. package/dist/diagnostics-CMhyGsPu.js +33 -0
  242. package/dist/diagnostics-DpLHpQ9c.js +14 -0
  243. package/dist/directive-handling.fast-lane-toP_ri_H.js +273 -0
  244. package/dist/directive-handling.impl-BRARyrsT.js +638 -0
  245. package/dist/directive-handling.impl-CUB4MOnK.js +214 -0
  246. package/dist/directive-handling.levels-8vnMeuGX.js +2 -0
  247. package/dist/directive-handling.levels-CoruY1AA.js +13 -0
  248. package/dist/directive-handling.persist.runtime-78Du6PgL.js +170 -0
  249. package/dist/directive-handling.shared-DCGUCHjn.js +147 -0
  250. package/dist/directory-cli-DVsDcgIU.js +437 -0
  251. package/dist/directory-config-helpers-CURJ8mj7.js +129 -0
  252. package/dist/directory-runtime-DhC8QkMq.js +19 -0
  253. package/dist/directory.static-DQaG9ohH.js +44 -0
  254. package/dist/discord-CYj8s73O.js +214 -0
  255. package/dist/discord-L9zvSHVn.js +635 -0
  256. package/dist/discord-core-5tkl-BzP.js +1 -0
  257. package/dist/dm-policy-shared-6bCJzHOS.js +188 -0
  258. package/dist/dns-cli-BMvHy265.js +223 -0
  259. package/dist/docker-XFNiArwM.js +1254 -0
  260. package/dist/docs-cli-BTaH94wD.js +176 -0
  261. package/dist/doctor-completion-DKx5m2UC.js +90 -0
  262. package/dist/doctor-config-preflight-BzQgc3_t.js +40 -0
  263. package/dist/doctor-config-preflight-DxVCut8L.js +150 -0
  264. package/dist/doctor-state-migrations-CTF66iAy.js +732 -0
  265. package/dist/doctor-state-migrations-D0VP4dUh.js +212 -0
  266. package/dist/entry-status-B2OWAf0s.js +172 -0
  267. package/dist/entry.js +210 -0
  268. package/dist/env-BP70DGuy.js +30 -0
  269. package/dist/env-overrides-JneV60sd.js +434 -0
  270. package/dist/env-overrides.runtime-DLrwions.js +18 -0
  271. package/dist/env-substitution-D6t_sLS_.js +136 -0
  272. package/dist/errors-BxyFnvP3.js +58 -0
  273. package/dist/exec-Dmex2w_d.js +310 -0
  274. package/dist/exec-approvals-BJhuySBz.js +386 -0
  275. package/dist/exec-approvals-allowlist-B_wPddCb.js +384 -0
  276. package/dist/exec-approvals-cli-C2dwhSkX.js +427 -0
  277. package/dist/exec-safe-bin-runtime-policy-BZkObC8r.js +89 -0
  278. package/dist/exec-safety-CaaBy-Zw.js +24 -0
  279. package/dist/extension-shared-5txN7IXK.js +74 -0
  280. package/dist/extensionAPI.js +218 -0
  281. package/dist/extensions/amazon-bedrock/index.js +231 -0
  282. package/dist/extensions/anthropic/index.js +330 -0
  283. package/dist/extensions/bluebubbles/index.js +224 -0
  284. package/dist/extensions/bluebubbles/setup-entry.js +289 -0
  285. package/dist/extensions/brave/index.js +23 -0
  286. package/dist/extensions/byteplus/index.js +112 -0
  287. package/dist/extensions/chutes/index.js +221 -0
  288. package/dist/extensions/cloudflare-ai-gateway/index.js +218 -0
  289. package/dist/extensions/copilot-proxy/index.js +125 -0
  290. package/dist/extensions/device-pair/index.js +1040 -0
  291. package/dist/extensions/discord/index.js +215 -0
  292. package/dist/extensions/discord/setup-entry.js +215 -0
  293. package/dist/extensions/elevenlabs/index.js +223 -0
  294. package/dist/extensions/fal/index.js +112 -0
  295. package/dist/extensions/feishu/index.js +227 -0
  296. package/dist/extensions/feishu/setup-entry.js +112 -0
  297. package/dist/extensions/firecrawl/index.js +211 -0
  298. package/dist/extensions/github-copilot/index.js +490 -0
  299. package/dist/extensions/google/index.js +211 -0
  300. package/dist/extensions/huggingface/index.js +108 -0
  301. package/dist/extensions/imessage/index.js +223 -0
  302. package/dist/extensions/imessage/setup-entry.js +220 -0
  303. package/dist/extensions/irc/index.js +220 -0
  304. package/dist/extensions/irc/setup-entry.js +222 -0
  305. package/dist/extensions/kilocode/index.js +282 -0
  306. package/dist/extensions/kimi-coding/index.js +148 -0
  307. package/dist/extensions/line/index.js +57 -0
  308. package/dist/extensions/line/setup-entry.js +49 -0
  309. package/dist/extensions/llm-task/index.js +157 -0
  310. package/dist/extensions/lobster/index.js +261 -0
  311. package/dist/extensions/mattermost/index.js +220 -0
  312. package/dist/extensions/mattermost/setup-entry.js +222 -0
  313. package/dist/extensions/memory-core/index.js +36 -0
  314. package/dist/extensions/microsoft/index.js +223 -0
  315. package/dist/extensions/minimax/index.js +437 -0
  316. package/dist/extensions/mistral/index.js +149 -0
  317. package/dist/extensions/modelstudio/index.js +144 -0
  318. package/dist/extensions/moonshot/index.js +211 -0
  319. package/dist/extensions/nextcloud-talk/index.js +221 -0
  320. package/dist/extensions/nextcloud-talk/setup-entry.js +223 -0
  321. package/dist/extensions/nvidia/index.js +29 -0
  322. package/dist/extensions/ollama/index.js +118 -0
  323. package/dist/extensions/open-prose/index.js +10 -0
  324. package/dist/extensions/openai/index.js +677 -0
  325. package/dist/extensions/opencode/index.js +116 -0
  326. package/dist/extensions/opencode-go/index.js +114 -0
  327. package/dist/extensions/openrouter/index.js +398 -0
  328. package/dist/extensions/openshell/index.js +923 -0
  329. package/dist/extensions/perplexity/index.js +23 -0
  330. package/dist/extensions/phone-control/index.js +276 -0
  331. package/dist/extensions/qianfan/index.js +114 -0
  332. package/dist/extensions/qwen-portal-auth/index.js +350 -0
  333. package/dist/extensions/sglang/index.js +285 -0
  334. package/dist/extensions/signal/index.js +218 -0
  335. package/dist/extensions/signal/setup-entry.js +218 -0
  336. package/dist/extensions/slack/index.js +222 -0
  337. package/dist/extensions/slack/setup-entry.js +220 -0
  338. package/dist/extensions/synology-chat/index.js +56 -0
  339. package/dist/extensions/synology-chat/setup-entry.js +58 -0
  340. package/dist/extensions/synthetic/index.js +112 -0
  341. package/dist/extensions/talk-voice/index.js +197 -0
  342. package/dist/extensions/tavily/index.js +211 -0
  343. package/dist/extensions/telegram/index.js +221 -0
  344. package/dist/extensions/telegram/setup-entry.js +221 -0
  345. package/dist/extensions/thread-ownership/index.js +70 -0
  346. package/dist/extensions/together/index.js +113 -0
  347. package/dist/extensions/venice/index.js +132 -0
  348. package/dist/extensions/vercel-ai-gateway/index.js +86 -0
  349. package/dist/extensions/vllm/index.js +285 -0
  350. package/dist/extensions/voice-call/index.js +5715 -0
  351. package/dist/extensions/volcengine/index.js +112 -0
  352. package/dist/extensions/xai/index.js +211 -0
  353. package/dist/extensions/xiaomi/index.js +115 -0
  354. package/dist/extensions/zai/index.js +559 -0
  355. package/dist/extensions/zalo/index.js +225 -0
  356. package/dist/extensions/zalo/setup-entry.js +226 -0
  357. package/dist/external-content-BUdUOqkv.js +238 -0
  358. package/dist/feishu-CgbwAF0e.js +2664 -0
  359. package/dist/feishu-Dh5fEbh5.js +59127 -0
  360. package/dist/fetch-guard-DIyN1HW5.js +165 -0
  361. package/dist/fetch-timeout-C5xpMuGd.js +36 -0
  362. package/dist/file-identity-Cw0fQxYY.js +11 -0
  363. package/dist/file-lock-WbEmczmY.js +107 -0
  364. package/dist/filter-oMGaNOM1.js +20 -0
  365. package/dist/format-DH8ysi7s.js +19 -0
  366. package/dist/format-datetime-BGS6tLDE.js +73 -0
  367. package/dist/format-duration-CO0BGWB0.js +57 -0
  368. package/dist/format-relative-C3nDxnXz.js +54 -0
  369. package/dist/frontmatter-S5vS-I4a.js +309 -0
  370. package/dist/fs-safe-D3qzH-ab.js +731 -0
  371. package/dist/gateway-cli-PQNp7o0j.js +28378 -0
  372. package/dist/gateway-install-token-DV5KjD4F.js +164 -0
  373. package/dist/gateway-rpc-C0Ey-rik.js +26 -0
  374. package/dist/gateway-runtime-ih2e7a2K.js +42 -0
  375. package/dist/gaxios-fetch-compat-KX6bsqFm.js +165 -0
  376. package/dist/gemini-auth-B5ljg7jr.js +29 -0
  377. package/dist/git-commit-BIdLubm5.js +2 -0
  378. package/dist/git-commit-OvUvjri2.js +177 -0
  379. package/dist/github-copilot-auth-Ccm-cBwy.js +104 -0
  380. package/dist/global-singleton-4KwY5RvX.js +13 -0
  381. package/dist/globals-41sdSaKv.js +38 -0
  382. package/dist/gmail-setup-utils-BX68dZla.js +419 -0
  383. package/dist/group-access-DJZrYPx1.js +113 -0
  384. package/dist/group-keys-BD_IYSMs.js +44 -0
  385. package/dist/group-policy-CWFxv3iB.js +201 -0
  386. package/dist/group-policy-warnings-Ddu6lBkh.js +175 -0
  387. package/dist/health-Bu1sbyYy.js +573 -0
  388. package/dist/health-Cbxc9Bn3.js +59 -0
  389. package/dist/health-format-B5XfOTuJ.js +26 -0
  390. package/dist/heartbeat-7aHh0m3d.js +169 -0
  391. package/dist/heartbeat-summary-Das49TYq.js +57 -0
  392. package/dist/help-CcbF7-ha.js +81 -0
  393. package/dist/help-format-Dv45FpYu.js +15 -0
  394. package/dist/helpers-DJ-5HEbE.js +24 -0
  395. package/dist/helpers-MxyaLZUk.js +32 -0
  396. package/dist/history-CHjo8B5W.js +102 -0
  397. package/dist/hook-runtime-BnNBi_q4.js +1 -0
  398. package/dist/hooks-cli-DUYK4RM1.js +1102 -0
  399. package/dist/hooks-policy-BL6HDLUn.js +20 -0
  400. package/dist/hooks-status-gzNmo3li.js +78 -0
  401. package/dist/host-env-security-BogNN146.js +223 -0
  402. package/dist/http-body-CCiSfloA.js +237 -0
  403. package/dist/http-registry-WFFbLYRd.js +153 -0
  404. package/dist/identity-DovQV4zD.js +112 -0
  405. package/dist/identity-cyBYcoXS.js +84 -0
  406. package/dist/identity-file-EndG1nfc.js +60 -0
  407. package/dist/image-generation-CNKc-mFK.js +441 -0
  408. package/dist/image-kJ7Tbov4.js +211 -0
  409. package/dist/image-ops-j01UkxEv.js +371 -0
  410. package/dist/imessage-B5pSMT47.js +219 -0
  411. package/dist/imessage-CoIuY1Ro.js +1451 -0
  412. package/dist/imessage-Cqjsq4VW.js +190 -0
  413. package/dist/imessage-core-CsYJuaRZ.js +1 -0
  414. package/dist/inbound-envelope-4P3IIJc3.js +61 -0
  415. package/dist/inbound-reply-dispatch-i2Vekqyy.js +72 -0
  416. package/dist/includes-7XyL3p1c.js +188 -0
  417. package/dist/includes-scan-y-rS6tTw.js +55 -0
  418. package/dist/index.js +57 -0
  419. package/dist/infra/warning-filter.js +2 -0
  420. package/dist/inspect-CcxlJ1ba.js +279 -0
  421. package/dist/install-safe-path-Rwbw1XCZ.js +62 -0
  422. package/dist/installs-iHi2aSjM.js +532 -0
  423. package/dist/interactive-F7iY0yED.js +8 -0
  424. package/dist/interactive-runtime-OweOj_Vv.js +90 -0
  425. package/dist/internal-hooks-0uipqzRY.js +156 -0
  426. package/dist/io-BX49DsSJ.js +35 -0
  427. package/dist/io-jOnQRia2.js +7178 -0
  428. package/dist/ip-C8vmzVu0.js +203 -0
  429. package/dist/ipv4-DAmsJVOV.js +82 -0
  430. package/dist/irc-AZ-Ec8be.js +12 -0
  431. package/dist/irc-CCSRuEC2.js +660 -0
  432. package/dist/is-main-YViS6wOn.js +27 -0
  433. package/dist/issue-format-CBEXVico.js +31 -0
  434. package/dist/issue-format-D3HehoKZ.js +4 -0
  435. package/dist/json-file-C2zjA0Gv.js +23 -0
  436. package/dist/json-files-WW-H_psG.js +60 -0
  437. package/dist/json-pointer-f9dEnBoR.js +43 -0
  438. package/dist/json-store-O1LwpnBH.js +37 -0
  439. package/dist/kb-cli-DMZs6PCu.js +65 -0
  440. package/dist/keyed-async-queue-CPUWV5Pm.js +32 -0
  441. package/dist/kill-tree-CbjXBw3z.js +149 -0
  442. package/dist/kilocode-shared-DS7_0IMs.js +29 -0
  443. package/dist/launchd-tyqGVx9U.js +491 -0
  444. package/dist/lazy-runtime-BcXbyAaC.js +1 -0
  445. package/dist/lazy-runtime-bWkd2cs3.js +29 -0
  446. package/dist/legacy-names-CUNZ4vHN.js +7 -0
  447. package/dist/legacy-web-search-BgZjNG2h.js +222 -0
  448. package/dist/lib-CERS7N4b.js +503 -0
  449. package/dist/lib-PPICrHv1.js +1938 -0
  450. package/dist/library-CZ461krl.js +211 -0
  451. package/dist/lifecycle-core-Dnxnw0oy.js +382 -0
  452. package/dist/line/accounts.js +10 -0
  453. package/dist/line/send.js +39 -0
  454. package/dist/line/template-messages.js +2 -0
  455. package/dist/line-CJSvwApm.js +1 -0
  456. package/dist/line-N9vL-2JB.js +688 -0
  457. package/dist/line-core-BOIxkjgu.js +1 -0
  458. package/dist/links-Bilm-v0z.js +13 -0
  459. package/dist/llm-slug-generator-BuAuQ5Ft.js +68 -0
  460. package/dist/llm-slug-generator.js +212 -0
  461. package/dist/llm-task-Dx8ymRFr.js +1 -0
  462. package/dist/local-roots-DAzCjWbC.js +34 -0
  463. package/dist/location-DefAH9WS.js +42 -0
  464. package/dist/logger-CoEtkjhn.js +550 -0
  465. package/dist/logger-Cqy7-Maj.js +70 -0
  466. package/dist/logging-B2wMcpWV.js +13 -0
  467. package/dist/logging-Bz1qZDPg.js +16 -0
  468. package/dist/logging-CArEWRgI.js +36 -0
  469. package/dist/logging-CbTTfADU.js +1 -0
  470. package/dist/logs-cli-BSjKwaur.js +261 -0
  471. package/dist/magic-string.es-DJPWMt-n.js +1011 -0
  472. package/dist/main-session-DKr0lBVk.js +36 -0
  473. package/dist/manager-ChTGDe87.js +2005 -0
  474. package/dist/manager-DuwFn87U.js +4226 -0
  475. package/dist/manager-runtime-E16jsvRe.js +59 -0
  476. package/dist/manager.runtime-F9F1eFiB.js +827 -0
  477. package/dist/manifest-registry-B90TyTWl.js +1350 -0
  478. package/dist/map-size-CMTQVKUV.js +15 -0
  479. package/dist/markdown-to-line-BWwaRx5F.js +640 -0
  480. package/dist/mask-api-key-CprzEe7l.js +10 -0
  481. package/dist/matrix-DzvdUw97.js +228 -0
  482. package/dist/matrix-migration-snapshot-adoDbNii.js +702 -0
  483. package/dist/mattermost-DO0BCfF3.js +1 -0
  484. package/dist/mattermost-SjOt4QDb.js +15 -0
  485. package/dist/mcp-cli-BC_VPl_o.js +94 -0
  486. package/dist/mcp-config-Coky4zS4.js +108 -0
  487. package/dist/media-limits-Cuvmmhop.js +14 -0
  488. package/dist/media-understanding-DD2uMjK8.js +48 -0
  489. package/dist/media-understanding.runtime-Kbb2bRmk.js +216 -0
  490. package/dist/memory-DBjQ0TPd.js +1 -0
  491. package/dist/memory-cli-Cm4Df0hJ.js +215 -0
  492. package/dist/memory-cli-yzqneSF8.js +541 -0
  493. package/dist/memory-search-Das1tiuB.js +204 -0
  494. package/dist/memory-search-DxmSTjHq.js +18 -0
  495. package/dist/mention-gating-B_q-EHFx.js +25 -0
  496. package/dist/mentions-Bxys_va0.js +154 -0
  497. package/dist/message-channel-Cy-gN4K2.js +106 -0
  498. package/dist/message-hook-mappers-BBTV3JRQ.js +249 -0
  499. package/dist/method-scopes-DgypDW23.js +2649 -0
  500. package/dist/mime-C4vVTBso.js +150 -0
  501. package/dist/minimal-C5yUxtHy.js +2120 -0
  502. package/dist/model-auth-B__TJTPw.js +309 -0
  503. package/dist/model-auth-env-CF9ts7Th.js +111 -0
  504. package/dist/model-catalog.runtime-CWh17vcc.js +211 -0
  505. package/dist/model-id-normalization-Y-MIsyK_.js +16 -0
  506. package/dist/model-input-BB2wSAHb.js +20 -0
  507. package/dist/model-overrides-sIzKU2wo.js +84 -0
  508. package/dist/model-param-b-DIFEhICm.js +15 -0
  509. package/dist/model-picker-CAPjetT3.js +400 -0
  510. package/dist/model-picker-DEw9viWc.js +215 -0
  511. package/dist/model-picker.runtime-ixYl7lB5.js +224 -0
  512. package/dist/model-selection-BTpJnslv.js +437 -0
  513. package/dist/model-selection-Ci9cPkL2.js +765 -0
  514. package/dist/model-suppression.runtime-D8cIb6Y5.js +216 -0
  515. package/dist/models-BQtc3khN.js +226 -0
  516. package/dist/models-CQgBV5dW.js +2536 -0
  517. package/dist/models-cli-DbQ-QpQk.js +418 -0
  518. package/dist/models-config-D2xK-G6c.js +211 -0
  519. package/dist/models-config.providers.discovery-BaIk1NKL.js +141 -0
  520. package/dist/models-config.runtime-Cf7q9uAQ.js +211 -0
  521. package/dist/monitor-B5QmKaD7.js +3272 -0
  522. package/dist/monitor-CL5OYLih.js +878 -0
  523. package/dist/monitor-CNZxrM4d.js +3145 -0
  524. package/dist/monitor-CyQVZdDh.js +223 -0
  525. package/dist/multimodal-DC43jYNv.js +75 -0
  526. package/dist/mutable-allowlist-detectors-C6EAzWYE.js +62 -0
  527. package/dist/net-DlJFp95v.js +270 -0
  528. package/dist/network-mode-DOgvmom4.js +17 -0
  529. package/dist/nextcloud-talk-ChMP88s-.js +12 -0
  530. package/dist/nextcloud-talk-CwnkUy8E.js +1 -0
  531. package/dist/node-cli-BZDC7rXg.js +2484 -0
  532. package/dist/node-command-policy-Bg2g6Xjp.js +192 -0
  533. package/dist/node-commands-B6W6Eo0b.js +11 -0
  534. package/dist/node-require-BgDD9bTi.js +14 -0
  535. package/dist/node-resolve-BunMro3f.js +69 -0
  536. package/dist/node-service-CEZZaqba.js +65 -0
  537. package/dist/node-startup-env-Gz8ZQniA.js +50 -0
  538. package/dist/nodes-cli-B4Jr9vct.js +1330 -0
  539. package/dist/nodes-screen-CQ7IvP62.js +401 -0
  540. package/dist/normalize-secret-input-_PgpexOG.js +32 -0
  541. package/dist/note-dfjacCV8.js +109 -0
  542. package/dist/npm-pack-install-CYNRv-vM.js +574 -0
  543. package/dist/npm-resolution-Ml2aA6Nu.js +60 -0
  544. package/dist/oauth.runtime-DA_48MPQ.js +687 -0
  545. package/dist/oauth.runtime-DS1ry5__.js +318 -0
  546. package/dist/oauth.runtime-qCkidk8J.js +180 -0
  547. package/dist/ollama-defaults-asNuGW4_.js +4 -0
  548. package/dist/onboard-BM6gO6Uw.js +589 -0
  549. package/dist/onboard-D9IU-7uw.js +48 -0
  550. package/dist/onboard-DQaHGPRm.js +25 -0
  551. package/dist/onboard-channels-BdQtLjYb.js +300 -0
  552. package/dist/onboard-channels-DIVUygs5.js +1257 -0
  553. package/dist/onboard-config-DFKb-0sE.js +29 -0
  554. package/dist/onboard-config-DYykzJhx.js +2 -0
  555. package/dist/onboard-custom-CDP4w1AT.js +216 -0
  556. package/dist/onboard-custom-DhJN13UV.js +644 -0
  557. package/dist/onboard-helpers-B7XTd4Pw.js +335 -0
  558. package/dist/onboard-helpers-BUKtx5Bq.js +54 -0
  559. package/dist/onboard-hooks-BHSSLAhI.js +73 -0
  560. package/dist/onboard-remote-BOzEPdHA.js +59 -0
  561. package/dist/onboard-remote-DVza19_k.js +182 -0
  562. package/dist/onboard-search-CrS-n9_3.js +446 -0
  563. package/dist/onboard-skills-BojzIPvk.js +133 -0
  564. package/dist/onboard-skills-D7HyCVjz.js +69 -0
  565. package/dist/openai-codex-provider.runtime-BFsopDHI.js +2 -0
  566. package/dist/openai-defaults-B7FUywsh.js +10 -0
  567. package/dist/openclaw-exec-env-AcZ9we1N.js +14 -0
  568. package/dist/openclaw-root-TUHYdr9B.js +88 -0
  569. package/dist/openclaw-tools.runtime-draZJo5r.js +211 -0
  570. package/dist/outbound-media-69yrWRDt.js +11 -0
  571. package/dist/outbound-runtime-ic_7ulJJ.js +1 -0
  572. package/dist/pairing-challenge-CNrPmmi9.js +48 -0
  573. package/dist/pairing-cli-BohXW2BK.js +150 -0
  574. package/dist/pairing-labels-CNKCSmBK.js +7 -0
  575. package/dist/pairing-message-CBv2njJT.js +4 -0
  576. package/dist/pairing-store-C4lsd4pO.js +590 -0
  577. package/dist/pairing-token-gKj4SNFJ.js +55 -0
  578. package/dist/parse-duration-BBGYkY0S.js +41 -0
  579. package/dist/parse-finite-number-CP4MQF_w.js +30 -0
  580. package/dist/parse-log-line-CVh9zu3Q.js +43 -0
  581. package/dist/parse-port-COyt3COn.js +8 -0
  582. package/dist/path-alias-guards-ZTKqurNH.js +40 -0
  583. package/dist/path-env-CPkz6U0Y.js +87 -0
  584. package/dist/paths-CTjJI9l0.js +179 -0
  585. package/dist/paths-GHJ97ebE.js +268 -0
  586. package/dist/paths-nCHyK08H.js +56 -0
  587. package/dist/perplexity-Beshd9zu.js +422 -0
  588. package/dist/persistent-dedupe-bjKjVI5u.js +116 -0
  589. package/dist/pi-embedded-CSQySvOV.js +168518 -0
  590. package/dist/pi-model-discovery-CuX5CDyZ.js +125 -0
  591. package/dist/pi-model-discovery-runtime-DNsMrX1n.js +44 -0
  592. package/dist/pi-tools.before-tool-call.runtime-DxVqzMVf.js +387 -0
  593. package/dist/platform-launcher-CqGy6UhP.js +83 -0
  594. package/dist/plugin-entry-CwuwM1jC.js +17 -0
  595. package/dist/plugin-install-JJwfOXtg.js +216 -0
  596. package/dist/plugin-install-plan-cixz1_W4.js +49 -0
  597. package/dist/plugin-install-vkpI1UNd.js +184 -0
  598. package/dist/plugin-registry-C3j_DUnj.js +51 -0
  599. package/dist/plugin-registry-DB_yxabS.js +213 -0
  600. package/dist/plugin-sdk/account-helpers.js +3 -0
  601. package/dist/plugin-sdk/account-id.js +2 -0
  602. package/dist/plugin-sdk/account-resolution.js +216 -0
  603. package/dist/plugin-sdk/acp-runtime.js +46 -0
  604. package/dist/plugin-sdk/agent-runtime.js +215 -0
  605. package/dist/plugin-sdk/allow-from.js +17 -0
  606. package/dist/plugin-sdk/allowlist-config-edit.js +2 -0
  607. package/dist/plugin-sdk/bluebubbles.js +232 -0
  608. package/dist/plugin-sdk/boolean-param.js +2 -0
  609. package/dist/plugin-sdk/channel-actions.js +16 -0
  610. package/dist/plugin-sdk/channel-config-helpers.js +15 -0
  611. package/dist/plugin-sdk/channel-config-schema.js +5 -0
  612. package/dist/plugin-sdk/channel-contract.js +1 -0
  613. package/dist/plugin-sdk/channel-feedback.js +4 -0
  614. package/dist/plugin-sdk/channel-inbound.js +53 -0
  615. package/dist/plugin-sdk/channel-lifecycle.js +2 -0
  616. package/dist/plugin-sdk/channel-pairing.js +2 -0
  617. package/dist/plugin-sdk/channel-policy.js +19 -0
  618. package/dist/plugin-sdk/channel-reply-pipeline.js +23 -0
  619. package/dist/plugin-sdk/channel-runtime.js +33 -0
  620. package/dist/plugin-sdk/channel-send-result.js +2 -0
  621. package/dist/plugin-sdk/channel-setup.js +24 -0
  622. package/dist/plugin-sdk/channel-targets.js +3 -0
  623. package/dist/plugin-sdk/cli-runtime.js +5 -0
  624. package/dist/plugin-sdk/command-auth.js +212 -0
  625. package/dist/plugin-sdk/compat.js +59 -0
  626. package/dist/plugin-sdk/config-runtime.js +51 -0
  627. package/dist/plugin-sdk/conversation-runtime.js +55 -0
  628. package/dist/plugin-sdk/core.js +40 -0
  629. package/dist/plugin-sdk/device-bootstrap.js +6 -0
  630. package/dist/plugin-sdk/diagnostics-otel.js +7 -0
  631. package/dist/plugin-sdk/diffs.js +3 -0
  632. package/dist/plugin-sdk/directory-runtime.js +5 -0
  633. package/dist/plugin-sdk/discord-core.js +26 -0
  634. package/dist/plugin-sdk/discord.js +219 -0
  635. package/dist/plugin-sdk/extension-shared.js +15 -0
  636. package/dist/plugin-sdk/feishu.js +101 -0
  637. package/dist/plugin-sdk/gateway-runtime.js +46 -0
  638. package/dist/plugin-sdk/googlechat.js +93 -0
  639. package/dist/plugin-sdk/group-access.js +2 -0
  640. package/dist/plugin-sdk/hook-runtime.js +12 -0
  641. package/dist/plugin-sdk/image-generation.js +51 -0
  642. package/dist/plugin-sdk/imessage-core.js +214 -0
  643. package/dist/plugin-sdk/imessage.js +223 -0
  644. package/dist/plugin-sdk/index.js +55 -0
  645. package/dist/plugin-sdk/infra-runtime.js +223 -0
  646. package/dist/plugin-sdk/interactive-runtime.js +3 -0
  647. package/dist/plugin-sdk/irc.js +232 -0
  648. package/dist/plugin-sdk/json-store.js +9 -0
  649. package/dist/plugin-sdk/keyed-async-queue.js +2 -0
  650. package/dist/plugin-sdk/lazy-runtime.js +2 -0
  651. package/dist/plugin-sdk/line-core.js +29 -0
  652. package/dist/plugin-sdk/line.js +22 -0
  653. package/dist/plugin-sdk/llm-task.js +7 -0
  654. package/dist/plugin-sdk/matrix-runtime-heavy.js +223 -0
  655. package/dist/plugin-sdk/matrix-runtime-shared.js +2 -0
  656. package/dist/plugin-sdk/matrix.js +84 -0
  657. package/dist/plugin-sdk/mattermost.js +233 -0
  658. package/dist/plugin-sdk/media-runtime.js +212 -0
  659. package/dist/plugin-sdk/media-understanding-runtime.js +211 -0
  660. package/dist/plugin-sdk/media-understanding.js +15 -0
  661. package/dist/plugin-sdk/memory-core.js +2 -0
  662. package/dist/plugin-sdk/memory-lancedb.js +2 -0
  663. package/dist/plugin-sdk/msteams.js +244 -0
  664. package/dist/plugin-sdk/nextcloud-talk.js +231 -0
  665. package/dist/plugin-sdk/nostr.js +50 -0
  666. package/dist/plugin-sdk/ollama-setup.js +33 -0
  667. package/dist/plugin-sdk/outbound-runtime.js +23 -0
  668. package/dist/plugin-sdk/plugin-entry.js +3 -0
  669. package/dist/plugin-sdk/plugin-runtime.js +211 -0
  670. package/dist/plugin-sdk/process-runtime.js +12 -0
  671. package/dist/plugin-sdk/provider-auth-api-key.js +53 -0
  672. package/dist/plugin-sdk/provider-auth-login.js +2 -0
  673. package/dist/plugin-sdk/provider-auth.js +37 -0
  674. package/dist/plugin-sdk/provider-catalog.js +2 -0
  675. package/dist/plugin-sdk/provider-env-vars.js +2 -0
  676. package/dist/plugin-sdk/provider-google.js +3 -0
  677. package/dist/plugin-sdk/provider-models.js +27 -0
  678. package/dist/plugin-sdk/provider-onboard.js +20 -0
  679. package/dist/plugin-sdk/provider-setup.js +58 -0
  680. package/dist/plugin-sdk/provider-stream.js +211 -0
  681. package/dist/plugin-sdk/provider-usage.js +18 -0
  682. package/dist/plugin-sdk/provider-web-search.js +23 -0
  683. package/dist/plugin-sdk/provider-zai-endpoint.js +3 -0
  684. package/dist/plugin-sdk/reply-history.js +23 -0
  685. package/dist/plugin-sdk/reply-payload.js +2 -0
  686. package/dist/plugin-sdk/reply-runtime.js +211 -0
  687. package/dist/plugin-sdk/request-url.js +2 -0
  688. package/dist/plugin-sdk/routing.js +25 -0
  689. package/dist/plugin-sdk/runtime-env.js +15 -0
  690. package/dist/plugin-sdk/runtime-store.js +2 -0
  691. package/dist/plugin-sdk/runtime.js +15 -0
  692. package/dist/plugin-sdk/sandbox.js +66 -0
  693. package/dist/plugin-sdk/secret-input.js +3 -0
  694. package/dist/plugin-sdk/security-runtime.js +18 -0
  695. package/dist/plugin-sdk/self-hosted-provider-setup.js +33 -0
  696. package/dist/plugin-sdk/setup-adapter-runtime.js +2 -0
  697. package/dist/plugin-sdk/setup-runtime.js +17 -0
  698. package/dist/plugin-sdk/setup-tools.js +21 -0
  699. package/dist/plugin-sdk/setup.js +26 -0
  700. package/dist/plugin-sdk/signal.js +220 -0
  701. package/dist/plugin-sdk/slack-core.js +22 -0
  702. package/dist/plugin-sdk/slack.js +223 -0
  703. package/dist/plugin-sdk/speech-runtime.js +213 -0
  704. package/dist/plugin-sdk/speech.js +212 -0
  705. package/dist/plugin-sdk/ssrf-runtime.js +5 -0
  706. package/dist/plugin-sdk/state-paths.js +3 -0
  707. package/dist/plugin-sdk/status-helpers.js +9 -0
  708. package/dist/plugin-sdk/telegram-core.js +23 -0
  709. package/dist/plugin-sdk/telegram.js +224 -0
  710. package/dist/plugin-sdk/testing.js +13174 -0
  711. package/dist/plugin-sdk/text-runtime.js +45 -0
  712. package/dist/plugin-sdk/thread-bindings-runtime.js +2 -0
  713. package/dist/plugin-sdk/thread-ownership.js +2 -0
  714. package/dist/plugin-sdk/tlon.js +57 -0
  715. package/dist/plugin-sdk/tool-send.js +2 -0
  716. package/dist/plugin-sdk/twitch.js +46 -0
  717. package/dist/plugin-sdk/voice-call.js +213 -0
  718. package/dist/plugin-sdk/web-media.js +28 -0
  719. package/dist/plugin-sdk/webhook-ingress.js +7 -0
  720. package/dist/plugin-sdk/webhook-path.js +2 -0
  721. package/dist/plugin-sdk/whatsapp-core.js +219 -0
  722. package/dist/plugin-sdk/whatsapp-shared.js +18 -0
  723. package/dist/plugin-sdk/windows-spawn.js +2 -0
  724. package/dist/plugin-sdk/zalo.js +239 -0
  725. package/dist/plugin-sdk/zalouser.js +240 -0
  726. package/dist/plugins/build-smoke-entry.js +211 -0
  727. package/dist/plugins/runtime/index.js +229 -0
  728. package/dist/plugins-1Z50ecJ6.js +1 -0
  729. package/dist/plugins-C6fKmNuA.js +7 -0
  730. package/dist/plugins-cli-BkgQkGaU.js +1192 -0
  731. package/dist/policy-CpkbSAfm.js +60 -0
  732. package/dist/polls-B2VH7SN9.js +35 -0
  733. package/dist/ports-BjWuIIQw.js +262 -0
  734. package/dist/ports-DFiK_Jc-.js +385 -0
  735. package/dist/ports-lsof-DtJqhFOr.js +25 -0
  736. package/dist/ports-probe-BQqp8l8E.js +14 -0
  737. package/dist/preflight-audio.runtime-Fi9mofpp.js +216 -0
  738. package/dist/probe-BM9sbCgS.js +20 -0
  739. package/dist/probe-DLBOZftS.js +134 -0
  740. package/dist/probe-auth-Bjp3G4CI.js +48 -0
  741. package/dist/probe-auth-DMSPTRRk.js +45 -0
  742. package/dist/process-runtime-C7el-Ri4.js +1 -0
  743. package/dist/process-scoped-map-C4gOa-gv.js +61 -0
  744. package/dist/profile-utils-BcMYGFPT.js +15 -0
  745. package/dist/profiles-D17eMKQZ.js +683 -0
  746. package/dist/program-Ch-76sgl.js +155 -0
  747. package/dist/program-context-BMWNUfqL.js +10 -0
  748. package/dist/program-context-CD_RvRYh.js +2 -0
  749. package/dist/progress-D1r9bZU1.js +132 -0
  750. package/dist/prompt-select-styled-NUKYS9QR.js +4879 -0
  751. package/dist/prompt-style-BvciNCqy.js +7 -0
  752. package/dist/prompts-NtuylUyl.js +9 -0
  753. package/dist/prototype-keys-Cm_8mWvq.js +11 -0
  754. package/dist/provider-api-key-auth-BE0taXiB.js +108 -0
  755. package/dist/provider-api-key-auth.runtime-jDZZUAMX.js +34 -0
  756. package/dist/provider-auth-Bw8x1a3o.js +58 -0
  757. package/dist/provider-auth-api-key-BrQYvdxi.js +1 -0
  758. package/dist/provider-auth-choice-BYbPq0eC.js +128 -0
  759. package/dist/provider-auth-choice-helpers-Bj1GkOSn.js +48 -0
  760. package/dist/provider-auth-choice-preference-tKq5gaJL.js +192 -0
  761. package/dist/provider-auth-choice.runtime-DegPpvRJ.js +223 -0
  762. package/dist/provider-auth-choices-QSilukI1.js +58 -0
  763. package/dist/provider-auth-guidance-gninjjq8.js +34 -0
  764. package/dist/provider-auth-helpers-B0dS-1WK.js +86 -0
  765. package/dist/provider-auth-input-BftBdgvW.js +112 -0
  766. package/dist/provider-auth-login-D0n0lMuc.js +8 -0
  767. package/dist/provider-auth-login.runtime-LvuBkQrc.js +243 -0
  768. package/dist/provider-auth-mode-sTdccIKL.js +20 -0
  769. package/dist/provider-auth-ref-BS3gwrNr.js +168 -0
  770. package/dist/provider-auth-ref-BmEcEN7K.js +3 -0
  771. package/dist/provider-catalog--18-pW5t.js +11 -0
  772. package/dist/provider-catalog-2P2hel74.js +48 -0
  773. package/dist/provider-catalog-B0FqWSwe.js +48 -0
  774. package/dist/provider-catalog-BvORKzzD.js +91 -0
  775. package/dist/provider-catalog-C34j1_or.js +26 -0
  776. package/dist/provider-catalog-C5vmXjmb.js +11 -0
  777. package/dist/provider-catalog-CBufm2Dr.js +36 -0
  778. package/dist/provider-catalog-D7QvsUXS.js +12 -0
  779. package/dist/provider-catalog-DKy_dzQZ.js +41 -0
  780. package/dist/provider-env-vars-CsQlY7bF.js +110 -0
  781. package/dist/provider-id-BpXo5t6v.js +31 -0
  782. package/dist/provider-model-allowlist-4HSOnlX-.js +24 -0
  783. package/dist/provider-model-primary-NJ-xlhec.js +53 -0
  784. package/dist/provider-models-C2EjYMwW.js +2416 -0
  785. package/dist/provider-oauth-flow-BQN6F6EC.js +33 -0
  786. package/dist/provider-ollama-setup-DhQvDwAj.js +309 -0
  787. package/dist/provider-onboard-CjOfyeQG.js +1 -0
  788. package/dist/provider-onboarding-config-DOZ3pFA6.js +165 -0
  789. package/dist/provider-openai-codex-oauth-tls-Bo8U4D3E.js +101 -0
  790. package/dist/provider-runtime.runtime-DnP2jpoM.js +211 -0
  791. package/dist/provider-self-hosted-setup-CUrmsugW.js +182 -0
  792. package/dist/provider-usage-ClDVmkhl.js +633 -0
  793. package/dist/provider-usage-DIC6cn-3.js +211 -0
  794. package/dist/provider-web-search-NzK8ep1E.js +507 -0
  795. package/dist/provider-wizard-C6jCuyQe.js +236 -0
  796. package/dist/provider-zai-endpoint-DeDABzT4.js +106 -0
  797. package/dist/proxy-H5O2p6AP.js +121 -0
  798. package/dist/proxy-env-DG2u55RW.js +40 -0
  799. package/dist/push-apns-D4zD2tmP.js +1050 -0
  800. package/dist/pw-ai-BuPUVeUK.js +1876 -0
  801. package/dist/qmd-manager-BpygGMW9.js +1571 -0
  802. package/dist/qr-cli-DnWHXcxh.js +370 -0
  803. package/dist/qr-cli-yaZ0FZ6z.js +213 -0
  804. package/dist/query-expansion-Do45hILP.js +1114 -0
  805. package/dist/reactions-BcC_XZqD.js +281 -0
  806. package/dist/read-only-account-inspect-DPJzadPo.js +42 -0
  807. package/dist/read-only-account-inspect.discord.runtime-CW9DDKH8.js +216 -0
  808. package/dist/read-only-account-inspect.slack.runtime-BcXBPyh3.js +216 -0
  809. package/dist/read-only-account-inspect.telegram.runtime-Y7h0Jbdj.js +216 -0
  810. package/dist/redact-BDinS1q9.js +102 -0
  811. package/dist/redact-identifier-FUiWQxv5.js +13 -0
  812. package/dist/redact-snapshot-DBPmeYy2.js +2654 -0
  813. package/dist/ref-contract-CCBBbf1r.js +53 -0
  814. package/dist/register-CppP7Ddc.js +43 -0
  815. package/dist/register.agent-BOD5ROGQ.js +546 -0
  816. package/dist/register.backup-Y2VGqcRu.js +269 -0
  817. package/dist/register.configure-1qiTINph.js +354 -0
  818. package/dist/register.maintenance-shn-zigv.js +694 -0
  819. package/dist/register.message-mR4CLSoo.js +812 -0
  820. package/dist/register.onboard-CkDryVid.js +298 -0
  821. package/dist/register.setup-B0xW5olD.js +318 -0
  822. package/dist/register.status-health-sessions-CuhWc03j.js +604 -0
  823. package/dist/register.subclis-BazXM5TW.js +315 -0
  824. package/dist/register.subclis-C2d8UDhH.js +13 -0
  825. package/dist/registry-C3q59Qj0.js +55 -0
  826. package/dist/registry-CPsHw6xU.js +219 -0
  827. package/dist/registry-CxgtJ09C.js +28 -0
  828. package/dist/registry-rgYi7KoO.js +160 -0
  829. package/dist/repair-qXnOAvDy.js +105 -0
  830. package/dist/replies-EiwmmZ_W.js +122 -0
  831. package/dist/reply-history-CVCD5oE9.js +1 -0
  832. package/dist/reply-payload-DBGc074f.js +232 -0
  833. package/dist/report-cli-DB1jQx32.js +42 -0
  834. package/dist/request-url-BKfWAQx8.js +10 -0
  835. package/dist/resolve-Ckjd8TAk.js +14 -0
  836. package/dist/resolve-T2q_0ARF.js +619 -0
  837. package/dist/resolve-route-vEY3ONZ2.js +466 -0
  838. package/dist/resolve-utils-CbqJY2bs.js +102 -0
  839. package/dist/response-generator-VdoCcQ3y.js +153 -0
  840. package/dist/restart-stale-pids-CLGiqU2E.js +187 -0
  841. package/dist/retry-D15TD1S3.js +168 -0
  842. package/dist/root-help-B9Aou4ho.js +32 -0
  843. package/dist/routes-TpLEcKO8.js +7084 -0
  844. package/dist/routing-Y3m0o-kB.js +26 -0
  845. package/dist/rpc-C6MN-nVc.js +67 -0
  846. package/dist/run-command-DRKv5Lj6.js +32 -0
  847. package/dist/run-main-YZSMdx0B.js +424 -0
  848. package/dist/run-with-concurrency-BrSjWzpg.js +41 -0
  849. package/dist/runtime-B66W9flm.js +43 -0
  850. package/dist/runtime-C9VaVKYZ.js +2338 -0
  851. package/dist/runtime-CT2LIJZu.js +91 -0
  852. package/dist/runtime-CqDQ81eY.js +143 -0
  853. package/dist/runtime-CuvWMN7E.js +89 -0
  854. package/dist/runtime-D4_OpzA1.js +5 -0
  855. package/dist/runtime-DP-4DZja.js +5 -0
  856. package/dist/runtime-Dl17x_cV.js +1 -0
  857. package/dist/runtime-Z35JoYPC.js +30 -0
  858. package/dist/runtime-api-D79M0lQN.js +1 -0
  859. package/dist/runtime-api-y3zfnQGK.js +39 -0
  860. package/dist/runtime-discord-ops.runtime-Bg5h5v9-.js +234 -0
  861. package/dist/runtime-env-a_iwdJIv.js +1 -0
  862. package/dist/runtime-forwarders-DtMc8rBP.js +44 -0
  863. package/dist/runtime-group-policy-B7irU4eu.js +59 -0
  864. package/dist/runtime-guard-y62lPDGY.js +58 -0
  865. package/dist/runtime-parse-CeqXmZHJ.js +84 -0
  866. package/dist/runtime-paths-CstaCCMi.js +334 -0
  867. package/dist/runtime-slack-ops.runtime-BumgKDhS.js +226 -0
  868. package/dist/runtime-status-CgL02wYX.js +15 -0
  869. package/dist/runtime-store-Bt3Sdbrn.js +22 -0
  870. package/dist/runtime-telegram-ops.runtime-rSLQ3KrE.js +233 -0
  871. package/dist/runtime-whatsapp-boundary-xZem0NyQ.js +364 -0
  872. package/dist/safe-open-sync-Bt9R1Mnf.js +83 -0
  873. package/dist/safe-regex-tLlDZYfM.js +244 -0
  874. package/dist/safe-text-B_CQuica.js +16 -0
  875. package/dist/sandbox-CUUouiKs.js +2795 -0
  876. package/dist/sandbox-cli-BN8y0Get.js +499 -0
  877. package/dist/sandbox-paths-fqp_TZdO.js +144 -0
  878. package/dist/sandbox-qSs4h3sk.js +1 -0
  879. package/dist/sanitize-env-vars-vNSNqm0y.js +74 -0
  880. package/dist/scan-paths-BJmvUZ1E.js +28 -0
  881. package/dist/search-manager-DWhFgwyp.js +17 -0
  882. package/dist/search-manager-r8Cw4ZRv.js +392 -0
  883. package/dist/secret-equal-ObQfyZGa.js +9 -0
  884. package/dist/secret-file-Ch0yuOXR.js +11 -0
  885. package/dist/secret-file-DYJtH6kf.js +92 -0
  886. package/dist/secret-input-4REZ4sHo.js +35 -0
  887. package/dist/secrets-cli-D1df8b0o.js +2304 -0
  888. package/dist/secure-random-Cs8tw_HQ.js +10 -0
  889. package/dist/security-cli-V66ESmdT.js +676 -0
  890. package/dist/security-runtime-BuEhpJVE.js +23 -0
  891. package/dist/send-3tabvle6.js +100 -0
  892. package/dist/send-CC5J3tyW.js +1026 -0
  893. package/dist/send-deps-CrFMNvqO.js +19 -0
  894. package/dist/send-i2-mdtiE.js +250 -0
  895. package/dist/server-BTOjmlyi.js +116 -0
  896. package/dist/server-middleware-CCqKhKUb.js +106 -0
  897. package/dist/server-node-events-D6y22Tt8.js +611 -0
  898. package/dist/server-startup-matrix-migration-DHWSoS73.js +1595 -0
  899. package/dist/service-Bxc9uL2e.js +774 -0
  900. package/dist/service-CBLajPZL.js +21 -0
  901. package/dist/session-cost-usage-BmbaBvk4.js +212 -0
  902. package/dist/session-cost-usage-C30Jl2SI.js +615 -0
  903. package/dist/session-fork.runtime-BZfcC1Nc.js +51 -0
  904. package/dist/session-key-gFFk3uv9.js +216 -0
  905. package/dist/session-write-lock-DNKvpjKf.js +324 -0
  906. package/dist/sessions-BIH_j_XS.js +222 -0
  907. package/dist/sessions-D5dWcxC_.js +212 -0
  908. package/dist/sessions-DaSBVNwD.js +669 -0
  909. package/dist/setup-C2XF1YH3.js +397 -0
  910. package/dist/setup-CN-teRpz.js +8 -0
  911. package/dist/setup-adapter-runtime-Bjv2adwG.js +1 -0
  912. package/dist/setup-binary-BOJA7zdN.js +30 -0
  913. package/dist/setup-browser-BhNPCUtK.js +71 -0
  914. package/dist/setup-core-BsG09DZH.js +149 -0
  915. package/dist/setup-core-D-O1GQax.js +162 -0
  916. package/dist/setup-core-Dtm54Rcq.js +510 -0
  917. package/dist/setup-entry-B1mTa7bU.js +10 -0
  918. package/dist/setup-entry-CTMgw-K5.js +13 -0
  919. package/dist/setup-entry-Cmd_cufO.js +13 -0
  920. package/dist/setup-entry-CybgA3zP.js +12 -0
  921. package/dist/setup-entry-DED_hL6i.js +12 -0
  922. package/dist/setup-entry-WCq9VMWx.js +14 -0
  923. package/dist/setup-group-access-BtPApRvE.js +70 -0
  924. package/dist/setup-helpers-B62Ecg9r.js +362 -0
  925. package/dist/setup-surface-B7A7qowY.js +452 -0
  926. package/dist/setup-surface-BBYJVRXc.js +380 -0
  927. package/dist/setup-surface-CFUz_BJi.js +298 -0
  928. package/dist/setup-tools-BPiMjAN7.js +1 -0
  929. package/dist/setup-wizard-helpers-COZ1UAdX.js +770 -0
  930. package/dist/setup-wizard-proxy-Slwi-1gX.js +116 -0
  931. package/dist/setup.finalize-B8O01nge.js +633 -0
  932. package/dist/setup.gateway-config-BPDIFk__.js +288 -0
  933. package/dist/setup.secret-input-BL-bqJpt.js +25 -0
  934. package/dist/shared-AygSbeCK.js +50 -0
  935. package/dist/shared-BHqDLkMG.js +127 -0
  936. package/dist/shared-BPtG8PgB.js +70 -0
  937. package/dist/shared-BU0QgVMZ.js +36 -0
  938. package/dist/shared-Bzr2UyEm.js +351 -0
  939. package/dist/shared-C_XXbGIF.js +87 -0
  940. package/dist/shared-Diw3KzwZ.js +82 -0
  941. package/dist/shared-DngjQumT.js +196 -0
  942. package/dist/shared-DzH3zmAy.js +64 -0
  943. package/dist/shared-LeP8iUTz.js +54 -0
  944. package/dist/shell-argv-DWV43Vya.js +72 -0
  945. package/dist/shell-env-cD92jEyV.js +181 -0
  946. package/dist/signal-BQd9f9dF.js +315 -0
  947. package/dist/signal-Ca7y47bM.js +46 -0
  948. package/dist/signal-Did9U_fa.js +214 -0
  949. package/dist/signal-cli-install-DxoL8CgF.js +188 -0
  950. package/dist/skill-commands-CiSwTFBQ.js +652 -0
  951. package/dist/skill-commands.runtime-CEwlWT4j.js +34 -0
  952. package/dist/skill-scanner-DG7MT7pu.js +354 -0
  953. package/dist/skills-BC8GJ9Rp.js +22 -0
  954. package/dist/skills-CCgKs_NJ.js +863 -0
  955. package/dist/skills-cli-dhYXJCuL.js +339 -0
  956. package/dist/skills-install-DiriUXJd.js +763 -0
  957. package/dist/skills-status-BmQTn4jL.js +23 -0
  958. package/dist/skills-status-a9b899Y3.js +169 -0
  959. package/dist/slack-CXgv7nu7.js +730 -0
  960. package/dist/slack-CcSByPzI.js +217 -0
  961. package/dist/slack-CtcCh0Lj.js +24537 -0
  962. package/dist/slack-core-DcsbATUs.js +1 -0
  963. package/dist/slash-commands.runtime-kO8EUKYW.js +228 -0
  964. package/dist/slash-dispatch.runtime-Bu2yMeFy.js +238 -0
  965. package/dist/slash-skill-commands.runtime-wwX3tF84.js +216 -0
  966. package/dist/speech-bSreRuDH.js +1 -0
  967. package/dist/speech-runtime-y1FcnGVA.js +1 -0
  968. package/dist/src-CmXHIz5f.js +846 -0
  969. package/dist/ssh-config-ChqR6ijV.js +77 -0
  970. package/dist/ssh-tunnel-Cz51VBAt.js +159 -0
  971. package/dist/ssh-tunnel-DWze2IQS.js +16 -0
  972. package/dist/ssrf-Dk9XaoKN.js +220 -0
  973. package/dist/ssrf-policy-Dk6oMa20.js +69 -0
  974. package/dist/ssrf-runtime-C-mAQLVA.js +1 -0
  975. package/dist/stagger-DU7FjHYo.js +54 -0
  976. package/dist/state-paths-DJIGEFq_.js +1 -0
  977. package/dist/status-69r8-Zey.js +75 -0
  978. package/dist/status-BdLTvZOL.js +44 -0
  979. package/dist/status-Bt7DQmRI.js +1665 -0
  980. package/dist/status-CoUFSBgt.js +202 -0
  981. package/dist/status-DbI3Kbh5.js +235 -0
  982. package/dist/status-DeKlzu_o.js +212 -0
  983. package/dist/status-Haie42Fc.js +606 -0
  984. package/dist/status-helpers-Cda-rGLX.js +101 -0
  985. package/dist/status-json-DS1M_MWJ.js +322 -0
  986. package/dist/status.link-channel-Cb8bZ_Od.js +40 -0
  987. package/dist/status.scan.deps.runtime-7_6VUs50.js +77 -0
  988. package/dist/status.scan.runtime-DtR8BIE9.js +14 -0
  989. package/dist/status.summary-l_Bi1buR.js +600 -0
  990. package/dist/status.summary.runtime-Cng6MzRU.js +151 -0
  991. package/dist/status.update-DtbnnPKx.js +79 -0
  992. package/dist/store-CvL8MPei.js +1446 -0
  993. package/dist/store.runtime-hgnvmZgO.js +43 -0
  994. package/dist/string-normalization-CvzuCAZv.js +19 -0
  995. package/dist/string-sample-BOLqzr4Y.js +11 -0
  996. package/dist/subagent-orphan-recovery-si1z2iBu.js +407 -0
  997. package/dist/subagent-registry-runtime-CXUDI8gL.js +211 -0
  998. package/dist/subcli-descriptors-CY_nHzpZ.js +151 -0
  999. package/dist/subsystem-CUp-6QQf.js +421 -0
  1000. package/dist/synology-chat-CdejNfs0.js +12 -0
  1001. package/dist/system-cli-DkOaXHkQ.js +99 -0
  1002. package/dist/system-events-mAu6Ap6K.js +75 -0
  1003. package/dist/system-message-DA9eUYzB.js +16 -0
  1004. package/dist/system-run-command-Cxq2F1MB.js +258 -0
  1005. package/dist/systemd-CrxZBFae.js +557 -0
  1006. package/dist/systemd-hints-y-zJ9aTm.js +315 -0
  1007. package/dist/systemd-linger-BdklDcLg.js +16 -0
  1008. package/dist/systemd-linger-DLrbG9_d.js +68 -0
  1009. package/dist/table-DFMOhmNZ.js +305 -0
  1010. package/dist/tailnet-ofqBrXzu.js +38 -0
  1011. package/dist/tailscale-Cbsx-2HB.js +254 -0
  1012. package/dist/target-errors-ksphhzJg.js +26 -0
  1013. package/dist/target-registry-krAVlXi_.js +1321 -0
  1014. package/dist/telegram/audit.js +2 -0
  1015. package/dist/telegram/token.js +211 -0
  1016. package/dist/telegram-BjDUP22F.js +10910 -0
  1017. package/dist/telegram-DMiNSGAJ.js +575 -0
  1018. package/dist/telegram-Dt11B3JL.js +218 -0
  1019. package/dist/telegram-core-B4Jo-uko.js +1 -0
  1020. package/dist/template-messages-kh7VfgOb.js +214 -0
  1021. package/dist/text-chunking-CUf5WgqG.js +19 -0
  1022. package/dist/text-format-sFXlJfHH.js +8 -0
  1023. package/dist/text-runtime-C_Roi_Je.js +1418 -0
  1024. package/dist/theme-B5HDbQfl.js +2 -0
  1025. package/dist/theme-CdOoMzRk.js +34 -0
  1026. package/dist/thinking-BBD_0HSp.js +68 -0
  1027. package/dist/thinking.shared-CncvRHts.js +246 -0
  1028. package/dist/thread-bindings-messages-Cdo8jSa9.js +229 -0
  1029. package/dist/thread-bindings-policy-DMjOaNyR.js +119 -0
  1030. package/dist/thread-bindings-runtime-Ckwk3Uuz.js +1 -0
  1031. package/dist/threading-helpers-Cq55SUtb.js +14 -0
  1032. package/dist/timeouts-BwR1sGom.js +72 -0
  1033. package/dist/tmp-openclaw-dir-idKIOMmb.js +102 -0
  1034. package/dist/token-Bgv8XEsC.js +50 -0
  1035. package/dist/tool-catalog-BV6FcEWS.js +337 -0
  1036. package/dist/tool-policy-match-CHqTCSdK.js +46 -0
  1037. package/dist/tool-send-9LXKcrda.js +16 -0
  1038. package/dist/topology-cli-BhUXVViF.js +43 -0
  1039. package/dist/transcript-events-B1V6z5ct.js +29 -0
  1040. package/dist/tui-DDJMGCFK.js +3838 -0
  1041. package/dist/tui-cli-ByN-ZH6y.js +237 -0
  1042. package/dist/typebox-D0SHDJST.js +175 -0
  1043. package/dist/types-BCKGVVld.js +83 -0
  1044. package/dist/types-CtpUGsDP.js +30 -0
  1045. package/dist/types.secrets-BWSeXrF4.js +80 -0
  1046. package/dist/types.tools-BBO8HCi6.js +22 -0
  1047. package/dist/typing-DG_YqWJ7.js +224 -0
  1048. package/dist/unhandled-rejections-CDJ8dOVP.js +170 -0
  1049. package/dist/unhandled-rejections-O6cVOz2D.js +4 -0
  1050. package/dist/update-Br8U-txJ.js +1039 -0
  1051. package/dist/update-check-C3TeQaWg.js +464 -0
  1052. package/dist/update-cli-XHfIntD0.js +1625 -0
  1053. package/dist/update-offset-store-36vzzZXw.js +211 -0
  1054. package/dist/upsert-with-lock-Bb96JHpb.js +34 -0
  1055. package/dist/url-userinfo-Db63ng4y.js +14 -0
  1056. package/dist/utils-Bxk6BLTg.js +236 -0
  1057. package/dist/utils-vDeUf98G.js +7 -0
  1058. package/dist/version-DCY9_obP.js +64 -0
  1059. package/dist/version-DRF-wKTV.js +2 -0
  1060. package/dist/voice-call-D4fgwZNO.js +1 -0
  1061. package/dist/warning-filter-CgvLQB4Y.js +56 -0
  1062. package/dist/web-media-BfBb8i48.js +1 -0
  1063. package/dist/web-media-CtU6jM5V.js +498 -0
  1064. package/dist/webhook-ingress-CupqYpKM.js +338 -0
  1065. package/dist/webhook-memory-guards-BHrFZ4yq.js +129 -0
  1066. package/dist/webhook-path-BGFZ55ML.js +22 -0
  1067. package/dist/webhook-shared-Cvk3b0ac.js +349 -0
  1068. package/dist/webhooks-cli-vOAoBF9b.js +357 -0
  1069. package/dist/whatsapp-D5nD0rGG.js +58 -0
  1070. package/dist/whatsapp-DXbWlm3A.js +82 -0
  1071. package/dist/whatsapp-core-C2WGMsaY.js +89451 -0
  1072. package/dist/whatsapp-heartbeat-CSWnPQ7q.js +84 -0
  1073. package/dist/whatsapp-shared-BmHKqTtR.js +95 -0
  1074. package/dist/widearea-dns-CXimgJzu.js +125 -0
  1075. package/dist/windows-argv-IXrdWrJj.js +145 -0
  1076. package/dist/windows-spawn-vMJGZo89.js +154 -0
  1077. package/dist/with-timeout-2AKTISee.js +58 -0
  1078. package/dist/workspace-BH7CXmrr.js +479 -0
  1079. package/dist/workspace-dirs-_O4V3xCR.js +13 -0
  1080. package/dist/workspace-v5XppK5M.js +302 -0
  1081. package/dist/ws-By-QcLjg.js +11 -0
  1082. package/dist/wsl-BV3Cb66X.js +57 -0
  1083. package/dist/zalo-CHQzsLhE.js +301 -0
  1084. package/dist/zalo-CcJ3J9f2.js +13 -0
  1085. package/dist/zod-schema.agent-runtime-T_EC_6fg.js +600 -0
  1086. package/dist/zod-schema.core-BdgRr-F1.js +545 -0
  1087. package/dist/zod-schema.providers-core-Dgq7MTqU.js +1613 -0
  1088. package/docs/.i18n/README.md +31 -0
  1089. package/docs/.i18n/glossary.ja-JP.json +14 -0
  1090. package/docs/.i18n/glossary.zh-CN.json +242 -0
  1091. package/docs/.i18n/ja-JP.tm.jsonl +0 -0
  1092. package/docs/assets/install-script.svg +1 -0
  1093. package/docs/assets/macos-onboarding/01-macos-warning.jpeg +0 -0
  1094. package/docs/assets/macos-onboarding/02-local-networks.jpeg +0 -0
  1095. package/docs/assets/macos-onboarding/03-security-notice.png +0 -0
  1096. package/docs/assets/macos-onboarding/04-choose-gateway.png +0 -0
  1097. package/docs/assets/macos-onboarding/05-permissions.png +0 -0
  1098. package/docs/assets/openclaw-logo-text-dark.png +0 -0
  1099. package/docs/assets/openclaw-logo-text-dark.svg +418 -0
  1100. package/docs/assets/openclaw-logo-text.png +0 -0
  1101. package/docs/assets/openclaw-logo-text.svg +418 -0
  1102. package/docs/assets/pixel-lobster.svg +60 -0
  1103. package/docs/assets/showcase/agents-ui.jpg +0 -0
  1104. package/docs/assets/showcase/bambu-cli.png +0 -0
  1105. package/docs/assets/showcase/codexmonitor.png +0 -0
  1106. package/docs/assets/showcase/gohome-grafana.png +0 -0
  1107. package/docs/assets/showcase/ios-testflight.jpg +0 -0
  1108. package/docs/assets/showcase/oura-health.png +0 -0
  1109. package/docs/assets/showcase/padel-cli.svg +11 -0
  1110. package/docs/assets/showcase/padel-screenshot.jpg +0 -0
  1111. package/docs/assets/showcase/papla-tts.jpg +0 -0
  1112. package/docs/assets/showcase/pr-review-telegram.jpg +0 -0
  1113. package/docs/assets/showcase/roborock-screenshot.jpg +0 -0
  1114. package/docs/assets/showcase/roborock-status.svg +13 -0
  1115. package/docs/assets/showcase/roof-camera-sky.jpg +0 -0
  1116. package/docs/assets/showcase/snag.png +0 -0
  1117. package/docs/assets/showcase/tesco-shop.jpg +0 -0
  1118. package/docs/assets/showcase/wienerlinien.png +0 -0
  1119. package/docs/assets/showcase/wine-cellar-skill.jpg +0 -0
  1120. package/docs/assets/showcase/winix-air-purifier.jpg +0 -0
  1121. package/docs/assets/showcase/xuezh-pronunciation.jpeg +0 -0
  1122. package/docs/assets/sponsors/blacksmith.svg +14 -0
  1123. package/docs/assets/sponsors/convex.svg +16 -0
  1124. package/docs/assets/sponsors/openai.svg +3 -0
  1125. package/docs/assets/sponsors/vercel.svg +5 -0
  1126. package/docs/auth-credential-semantics.md +53 -0
  1127. package/docs/automation/auth-monitoring.md +44 -0
  1128. package/docs/automation/cron-jobs.md +727 -0
  1129. package/docs/automation/cron-vs-heartbeat.md +286 -0
  1130. package/docs/automation/gmail-pubsub.md +256 -0
  1131. package/docs/automation/hooks.md +1049 -0
  1132. package/docs/automation/poll.md +86 -0
  1133. package/docs/automation/standing-orders.md +251 -0
  1134. package/docs/automation/troubleshooting.md +122 -0
  1135. package/docs/automation/webhook.md +217 -0
  1136. package/docs/brave-search.md +93 -0
  1137. package/docs/channels/bluebubbles.md +347 -0
  1138. package/docs/channels/broadcast-groups.md +442 -0
  1139. package/docs/channels/channel-routing.md +139 -0
  1140. package/docs/channels/discord.md +1229 -0
  1141. package/docs/channels/feishu.md +747 -0
  1142. package/docs/channels/googlechat.md +261 -0
  1143. package/docs/channels/group-messages.md +84 -0
  1144. package/docs/channels/groups.md +379 -0
  1145. package/docs/channels/imessage.md +367 -0
  1146. package/docs/channels/index.md +47 -0
  1147. package/docs/channels/irc.md +242 -0
  1148. package/docs/channels/line.md +194 -0
  1149. package/docs/channels/location.md +56 -0
  1150. package/docs/channels/matrix.md +677 -0
  1151. package/docs/channels/mattermost.md +427 -0
  1152. package/docs/channels/msteams.md +780 -0
  1153. package/docs/channels/nextcloud-talk.md +138 -0
  1154. package/docs/channels/nostr.md +242 -0
  1155. package/docs/channels/pairing.md +114 -0
  1156. package/docs/channels/signal.md +329 -0
  1157. package/docs/channels/slack.md +603 -0
  1158. package/docs/channels/synology-chat.md +132 -0
  1159. package/docs/channels/telegram.md +987 -0
  1160. package/docs/channels/tlon.md +276 -0
  1161. package/docs/channels/troubleshooting.md +118 -0
  1162. package/docs/channels/twitch.md +379 -0
  1163. package/docs/channels/whatsapp.md +460 -0
  1164. package/docs/channels/zalo.md +243 -0
  1165. package/docs/channels/zalouser.md +181 -0
  1166. package/docs/ci.md +55 -0
  1167. package/docs/cli/acp.md +288 -0
  1168. package/docs/cli/agent.md +29 -0
  1169. package/docs/cli/agents.md +123 -0
  1170. package/docs/cli/approvals.md +50 -0
  1171. package/docs/cli/backup.md +76 -0
  1172. package/docs/cli/browser.md +106 -0
  1173. package/docs/cli/channels.md +102 -0
  1174. package/docs/cli/clawbot.md +21 -0
  1175. package/docs/cli/completion.md +35 -0
  1176. package/docs/cli/config.md +295 -0
  1177. package/docs/cli/configure.md +36 -0
  1178. package/docs/cli/cron.md +77 -0
  1179. package/docs/cli/daemon.md +53 -0
  1180. package/docs/cli/dashboard.md +22 -0
  1181. package/docs/cli/devices.md +139 -0
  1182. package/docs/cli/directory.md +63 -0
  1183. package/docs/cli/dns.md +23 -0
  1184. package/docs/cli/docs.md +15 -0
  1185. package/docs/cli/doctor.md +48 -0
  1186. package/docs/cli/gateway.md +235 -0
  1187. package/docs/cli/health.md +21 -0
  1188. package/docs/cli/hooks.md +318 -0
  1189. package/docs/cli/index.md +1147 -0
  1190. package/docs/cli/logs.md +28 -0
  1191. package/docs/cli/memory.md +66 -0
  1192. package/docs/cli/message.md +278 -0
  1193. package/docs/cli/models.md +81 -0
  1194. package/docs/cli/node.md +127 -0
  1195. package/docs/cli/nodes.md +75 -0
  1196. package/docs/cli/onboard.md +157 -0
  1197. package/docs/cli/pairing.md +32 -0
  1198. package/docs/cli/plugins.md +186 -0
  1199. package/docs/cli/qr.md +46 -0
  1200. package/docs/cli/reset.md +20 -0
  1201. package/docs/cli/sandbox.md +197 -0
  1202. package/docs/cli/secrets.md +188 -0
  1203. package/docs/cli/security.md +79 -0
  1204. package/docs/cli/sessions.md +110 -0
  1205. package/docs/cli/setup.md +29 -0
  1206. package/docs/cli/skills.md +26 -0
  1207. package/docs/cli/status.md +30 -0
  1208. package/docs/cli/system.md +60 -0
  1209. package/docs/cli/tui.md +30 -0
  1210. package/docs/cli/uninstall.md +20 -0
  1211. package/docs/cli/update.md +103 -0
  1212. package/docs/cli/voicecall.md +34 -0
  1213. package/docs/cli/webhooks.md +25 -0
  1214. package/docs/concepts/agent-loop.md +148 -0
  1215. package/docs/concepts/agent-workspace.md +236 -0
  1216. package/docs/concepts/agent.md +122 -0
  1217. package/docs/concepts/architecture.md +137 -0
  1218. package/docs/concepts/compaction.md +123 -0
  1219. package/docs/concepts/context-engine.md +268 -0
  1220. package/docs/concepts/context.md +172 -0
  1221. package/docs/concepts/delegate-architecture.md +296 -0
  1222. package/docs/concepts/features.md +73 -0
  1223. package/docs/concepts/markdown-formatting.md +130 -0
  1224. package/docs/concepts/memory.md +108 -0
  1225. package/docs/concepts/messages.md +154 -0
  1226. package/docs/concepts/model-failover.md +152 -0
  1227. package/docs/concepts/model-providers.md +607 -0
  1228. package/docs/concepts/models.md +225 -0
  1229. package/docs/concepts/multi-agent.md +552 -0
  1230. package/docs/concepts/oauth.md +158 -0
  1231. package/docs/concepts/presence.md +102 -0
  1232. package/docs/concepts/queue.md +89 -0
  1233. package/docs/concepts/retry.md +69 -0
  1234. package/docs/concepts/session-pruning.md +121 -0
  1235. package/docs/concepts/session-tool.md +242 -0
  1236. package/docs/concepts/session.md +310 -0
  1237. package/docs/concepts/streaming.md +155 -0
  1238. package/docs/concepts/system-prompt.md +132 -0
  1239. package/docs/concepts/timezone.md +91 -0
  1240. package/docs/concepts/typebox.md +291 -0
  1241. package/docs/concepts/typing-indicators.md +68 -0
  1242. package/docs/concepts/usage-tracking.md +35 -0
  1243. package/docs/date-time.md +128 -0
  1244. package/docs/debug/node-issue.md +85 -0
  1245. package/docs/diagnostics/flags.md +91 -0
  1246. package/docs/docs.json +2061 -0
  1247. package/docs/gateway/authentication.md +179 -0
  1248. package/docs/gateway/background-process.md +97 -0
  1249. package/docs/gateway/bonjour.md +177 -0
  1250. package/docs/gateway/bridge-protocol.md +91 -0
  1251. package/docs/gateway/cli-backends.md +225 -0
  1252. package/docs/gateway/configuration-examples.md +651 -0
  1253. package/docs/gateway/configuration-reference.md +3123 -0
  1254. package/docs/gateway/configuration.md +633 -0
  1255. package/docs/gateway/discovery.md +123 -0
  1256. package/docs/gateway/doctor.md +362 -0
  1257. package/docs/gateway/gateway-lock.md +34 -0
  1258. package/docs/gateway/health.md +44 -0
  1259. package/docs/gateway/heartbeat.md +393 -0
  1260. package/docs/gateway/index.md +261 -0
  1261. package/docs/gateway/local-models.md +152 -0
  1262. package/docs/gateway/logging.md +113 -0
  1263. package/docs/gateway/multiple-gateways.md +112 -0
  1264. package/docs/gateway/network-model.md +22 -0
  1265. package/docs/gateway/openai-http-api.md +132 -0
  1266. package/docs/gateway/openresponses-http-api.md +295 -0
  1267. package/docs/gateway/openshell.md +307 -0
  1268. package/docs/gateway/pairing.md +99 -0
  1269. package/docs/gateway/protocol.md +267 -0
  1270. package/docs/gateway/remote-gateway-readme.md +158 -0
  1271. package/docs/gateway/remote.md +153 -0
  1272. package/docs/gateway/sandbox-vs-tool-policy-vs-elevated.md +134 -0
  1273. package/docs/gateway/sandboxing.md +469 -0
  1274. package/docs/gateway/secrets-plan-contract.md +116 -0
  1275. package/docs/gateway/secrets.md +503 -0
  1276. package/docs/gateway/security/index.md +1213 -0
  1277. package/docs/gateway/tailscale.md +132 -0
  1278. package/docs/gateway/tools-invoke-http-api.md +110 -0
  1279. package/docs/gateway/troubleshooting.md +378 -0
  1280. package/docs/gateway/trusted-proxy-auth.md +330 -0
  1281. package/docs/help/debugging.md +168 -0
  1282. package/docs/help/environment.md +163 -0
  1283. package/docs/help/faq.md +2999 -0
  1284. package/docs/help/index.md +28 -0
  1285. package/docs/help/scripts.md +28 -0
  1286. package/docs/help/testing.md +524 -0
  1287. package/docs/help/troubleshooting.md +297 -0
  1288. package/docs/images/configure-model-picker-unsearchable.png +0 -0
  1289. package/docs/images/feishu-step2-create-app.png +0 -0
  1290. package/docs/images/feishu-step3-credentials.png +0 -0
  1291. package/docs/images/feishu-step4-permissions.png +0 -0
  1292. package/docs/images/feishu-step5-bot-capability.png +0 -0
  1293. package/docs/images/feishu-step6-event-subscription.png +0 -0
  1294. package/docs/images/feishu-verification-token.png +0 -0
  1295. package/docs/images/groups-flow.svg +52 -0
  1296. package/docs/images/mobile-ui-screenshot.png +0 -0
  1297. package/docs/index.md +196 -0
  1298. package/docs/install/ansible.md +230 -0
  1299. package/docs/install/azure.md +311 -0
  1300. package/docs/install/bun.md +55 -0
  1301. package/docs/install/development-channels.md +120 -0
  1302. package/docs/install/digitalocean.md +129 -0
  1303. package/docs/install/docker-vm-runtime.md +142 -0
  1304. package/docs/install/docker.md +375 -0
  1305. package/docs/install/exe-dev.md +126 -0
  1306. package/docs/install/fly.md +501 -0
  1307. package/docs/install/gcp.md +402 -0
  1308. package/docs/install/hetzner.md +251 -0
  1309. package/docs/install/index.md +183 -0
  1310. package/docs/install/installer.md +415 -0
  1311. package/docs/install/kubernetes.md +191 -0
  1312. package/docs/install/macos-vm.md +281 -0
  1313. package/docs/install/migrating-matrix.md +346 -0
  1314. package/docs/install/migrating.md +110 -0
  1315. package/docs/install/nix.md +89 -0
  1316. package/docs/install/node.md +138 -0
  1317. package/docs/install/northflank.mdx +54 -0
  1318. package/docs/install/oracle.md +156 -0
  1319. package/docs/install/podman.md +133 -0
  1320. package/docs/install/railway.mdx +100 -0
  1321. package/docs/install/raspberry-pi.md +159 -0
  1322. package/docs/install/render.mdx +169 -0
  1323. package/docs/install/uninstall.md +128 -0
  1324. package/docs/install/updating.md +128 -0
  1325. package/docs/ja-JP/index.md +186 -0
  1326. package/docs/ja-JP/start/getting-started.md +125 -0
  1327. package/docs/ja-JP/start/wizard.md +77 -0
  1328. package/docs/logging.md +352 -0
  1329. package/docs/nav-tabs-underline.js +100 -0
  1330. package/docs/network.md +54 -0
  1331. package/docs/nodes/audio.md +187 -0
  1332. package/docs/nodes/camera.md +162 -0
  1333. package/docs/nodes/images.md +72 -0
  1334. package/docs/nodes/index.md +393 -0
  1335. package/docs/nodes/location-command.md +98 -0
  1336. package/docs/nodes/media-understanding.md +394 -0
  1337. package/docs/nodes/talk.md +92 -0
  1338. package/docs/nodes/troubleshooting.md +114 -0
  1339. package/docs/nodes/voicewake.md +66 -0
  1340. package/docs/perplexity.md +174 -0
  1341. package/docs/pi-dev.md +80 -0
  1342. package/docs/pi.md +567 -0
  1343. package/docs/platforms/android.md +168 -0
  1344. package/docs/platforms/digitalocean.md +266 -0
  1345. package/docs/platforms/index.md +54 -0
  1346. package/docs/platforms/ios.md +220 -0
  1347. package/docs/platforms/linux.md +94 -0
  1348. package/docs/platforms/mac/bundled-gateway.md +73 -0
  1349. package/docs/platforms/mac/canvas.md +125 -0
  1350. package/docs/platforms/mac/child-process.md +69 -0
  1351. package/docs/platforms/mac/dev-setup.md +104 -0
  1352. package/docs/platforms/mac/health.md +34 -0
  1353. package/docs/platforms/mac/icon.md +31 -0
  1354. package/docs/platforms/mac/logging.md +57 -0
  1355. package/docs/platforms/mac/menu-bar.md +81 -0
  1356. package/docs/platforms/mac/peekaboo.md +65 -0
  1357. package/docs/platforms/mac/permissions.md +50 -0
  1358. package/docs/platforms/mac/remote.md +84 -0
  1359. package/docs/platforms/mac/signing.md +47 -0
  1360. package/docs/platforms/mac/skills.md +33 -0
  1361. package/docs/platforms/mac/voice-overlay.md +60 -0
  1362. package/docs/platforms/mac/voicewake.md +67 -0
  1363. package/docs/platforms/mac/webchat.md +43 -0
  1364. package/docs/platforms/mac/xpc.md +61 -0
  1365. package/docs/platforms/macos.md +226 -0
  1366. package/docs/platforms/oracle.md +303 -0
  1367. package/docs/platforms/raspberry-pi.md +412 -0
  1368. package/docs/platforms/windows.md +241 -0
  1369. package/docs/plugins/agent-tools.md +10 -0
  1370. package/docs/plugins/architecture.md +1363 -0
  1371. package/docs/plugins/building-extensions.md +10 -0
  1372. package/docs/plugins/building-plugins.md +376 -0
  1373. package/docs/plugins/bundles.md +181 -0
  1374. package/docs/plugins/community.md +141 -0
  1375. package/docs/plugins/manifest.md +145 -0
  1376. package/docs/plugins/sdk-migration.md +169 -0
  1377. package/docs/plugins/voice-call.md +380 -0
  1378. package/docs/plugins/zalouser.md +77 -0
  1379. package/docs/prose.md +134 -0
  1380. package/docs/providers/anthropic.md +259 -0
  1381. package/docs/providers/bedrock.md +176 -0
  1382. package/docs/providers/claude-max-api-proxy.md +154 -0
  1383. package/docs/providers/cloudflare-ai-gateway.md +71 -0
  1384. package/docs/providers/deepgram.md +93 -0
  1385. package/docs/providers/github-copilot.md +72 -0
  1386. package/docs/providers/glm.md +43 -0
  1387. package/docs/providers/google.md +78 -0
  1388. package/docs/providers/groq.md +96 -0
  1389. package/docs/providers/huggingface.md +209 -0
  1390. package/docs/providers/index.md +69 -0
  1391. package/docs/providers/kilocode.md +74 -0
  1392. package/docs/providers/litellm.md +154 -0
  1393. package/docs/providers/minimax.md +224 -0
  1394. package/docs/providers/mistral.md +54 -0
  1395. package/docs/providers/models.md +45 -0
  1396. package/docs/providers/modelstudio.md +66 -0
  1397. package/docs/providers/moonshot.md +175 -0
  1398. package/docs/providers/nvidia.md +55 -0
  1399. package/docs/providers/ollama.md +352 -0
  1400. package/docs/providers/openai.md +303 -0
  1401. package/docs/providers/opencode-go.md +45 -0
  1402. package/docs/providers/opencode.md +64 -0
  1403. package/docs/providers/openrouter.md +37 -0
  1404. package/docs/providers/perplexity-provider.md +62 -0
  1405. package/docs/providers/qianfan.md +38 -0
  1406. package/docs/providers/qwen.md +53 -0
  1407. package/docs/providers/sglang.md +104 -0
  1408. package/docs/providers/synthetic.md +99 -0
  1409. package/docs/providers/together.md +66 -0
  1410. package/docs/providers/venice.md +282 -0
  1411. package/docs/providers/vercel-ai-gateway.md +60 -0
  1412. package/docs/providers/vllm.md +92 -0
  1413. package/docs/providers/volcengine.md +74 -0
  1414. package/docs/providers/xai.md +60 -0
  1415. package/docs/providers/xiaomi.md +86 -0
  1416. package/docs/providers/zai.md +46 -0
  1417. package/docs/reference/AGENTS.default.md +126 -0
  1418. package/docs/reference/RELEASING.md +42 -0
  1419. package/docs/reference/api-usage-costs.md +144 -0
  1420. package/docs/reference/credits.md +30 -0
  1421. package/docs/reference/device-models.md +47 -0
  1422. package/docs/reference/memory-config.md +711 -0
  1423. package/docs/reference/prompt-caching.md +185 -0
  1424. package/docs/reference/rpc.md +43 -0
  1425. package/docs/reference/secretref-credential-surface.md +140 -0
  1426. package/docs/reference/secretref-user-supplied-credentials-matrix.json +563 -0
  1427. package/docs/reference/session-management-compaction.md +324 -0
  1428. package/docs/reference/templates/AGENTS.dev.md +83 -0
  1429. package/docs/reference/templates/AGENTS.md +219 -0
  1430. package/docs/reference/templates/BOOT.md +11 -0
  1431. package/docs/reference/templates/BOOTSTRAP.md +62 -0
  1432. package/docs/reference/templates/HEARTBEAT.md +14 -0
  1433. package/docs/reference/templates/IDENTITY.dev.md +47 -0
  1434. package/docs/reference/templates/IDENTITY.md +29 -0
  1435. package/docs/reference/templates/SOUL.dev.md +76 -0
  1436. package/docs/reference/templates/SOUL.md +43 -0
  1437. package/docs/reference/templates/TOOLS.dev.md +24 -0
  1438. package/docs/reference/templates/TOOLS.md +47 -0
  1439. package/docs/reference/templates/USER.dev.md +18 -0
  1440. package/docs/reference/templates/USER.md +23 -0
  1441. package/docs/reference/test.md +90 -0
  1442. package/docs/reference/token-use.md +175 -0
  1443. package/docs/reference/transcript-hygiene.md +151 -0
  1444. package/docs/reference/wizard.md +235 -0
  1445. package/docs/security/CONTRIBUTING-THREAT-MODEL.md +98 -0
  1446. package/docs/security/THREAT-MODEL-ATLAS.md +611 -0
  1447. package/docs/security/formal-verification.md +167 -0
  1448. package/docs/start/bootstrapping.md +41 -0
  1449. package/docs/start/docs-directory.md +66 -0
  1450. package/docs/start/getting-started.md +116 -0
  1451. package/docs/start/hubs.md +198 -0
  1452. package/docs/start/lore.md +219 -0
  1453. package/docs/start/onboarding-overview.md +67 -0
  1454. package/docs/start/onboarding.md +91 -0
  1455. package/docs/start/openclaw.md +216 -0
  1456. package/docs/start/quickstart.md +22 -0
  1457. package/docs/start/setup.md +164 -0
  1458. package/docs/start/showcase.md +418 -0
  1459. package/docs/start/wizard-cli-automation.md +215 -0
  1460. package/docs/start/wizard-cli-reference.md +299 -0
  1461. package/docs/start/wizard.md +125 -0
  1462. package/docs/style.css +37 -0
  1463. package/docs/tools/acp-agents.md +623 -0
  1464. package/docs/tools/agent-send.md +100 -0
  1465. package/docs/tools/apply-patch.md +51 -0
  1466. package/docs/tools/brave-search.md +93 -0
  1467. package/docs/tools/browser-linux-troubleshooting.md +138 -0
  1468. package/docs/tools/browser-login.md +73 -0
  1469. package/docs/tools/browser-wsl2-windows-remote-cdp-troubleshooting.md +211 -0
  1470. package/docs/tools/browser.md +731 -0
  1471. package/docs/tools/btw.md +142 -0
  1472. package/docs/tools/capability-cookbook.md +119 -0
  1473. package/docs/tools/clawhub.md +257 -0
  1474. package/docs/tools/creating-skills.md +117 -0
  1475. package/docs/tools/diffs.md +386 -0
  1476. package/docs/tools/elevated.md +114 -0
  1477. package/docs/tools/exec-approvals.md +400 -0
  1478. package/docs/tools/exec.md +204 -0
  1479. package/docs/tools/firecrawl.md +140 -0
  1480. package/docs/tools/index.md +137 -0
  1481. package/docs/tools/llm-task.md +119 -0
  1482. package/docs/tools/lobster.md +340 -0
  1483. package/docs/tools/loop-detection.md +100 -0
  1484. package/docs/tools/multi-agent-sandbox-tools.md +364 -0
  1485. package/docs/tools/pdf.md +156 -0
  1486. package/docs/tools/perplexity-search.md +174 -0
  1487. package/docs/tools/plugin.md +251 -0
  1488. package/docs/tools/reactions.md +64 -0
  1489. package/docs/tools/skills-config.md +86 -0
  1490. package/docs/tools/skills.md +306 -0
  1491. package/docs/tools/slash-commands.md +294 -0
  1492. package/docs/tools/subagents.md +295 -0
  1493. package/docs/tools/tavily.md +125 -0
  1494. package/docs/tools/thinking.md +96 -0
  1495. package/docs/tools/tts.md +406 -0
  1496. package/docs/tools/web.md +516 -0
  1497. package/docs/tts.md +406 -0
  1498. package/docs/vps.md +112 -0
  1499. package/docs/web/control-ui.md +275 -0
  1500. package/docs/web/dashboard.md +54 -0
  1501. package/docs/web/index.md +120 -0
  1502. package/docs/web/tui.md +170 -0
  1503. package/docs/web/webchat.md +61 -0
  1504. package/docs/whatsapp-openclaw-ai-zh.jpg +0 -0
  1505. package/docs/whatsapp-openclaw.jpg +0 -0
  1506. package/docs/zh-CN/AGENTS.md +61 -0
  1507. package/docs/zh-CN/automation/auth-monitoring.md +47 -0
  1508. package/docs/zh-CN/automation/cron-jobs.md +435 -0
  1509. package/docs/zh-CN/automation/cron-vs-heartbeat.md +286 -0
  1510. package/docs/zh-CN/automation/gmail-pubsub.md +249 -0
  1511. package/docs/zh-CN/automation/hooks.md +1051 -0
  1512. package/docs/zh-CN/automation/poll.md +76 -0
  1513. package/docs/zh-CN/automation/troubleshooting.md +8 -0
  1514. package/docs/zh-CN/automation/webhook.md +163 -0
  1515. package/docs/zh-CN/brave-search.md +60 -0
  1516. package/docs/zh-CN/channels/bluebubbles.md +354 -0
  1517. package/docs/zh-CN/channels/broadcast-groups.md +449 -0
  1518. package/docs/zh-CN/channels/channel-routing.md +117 -0
  1519. package/docs/zh-CN/channels/discord.md +468 -0
  1520. package/docs/zh-CN/channels/feishu.md +728 -0
  1521. package/docs/zh-CN/channels/googlechat.md +257 -0
  1522. package/docs/zh-CN/channels/grammy.md +38 -0
  1523. package/docs/zh-CN/channels/group-messages.md +91 -0
  1524. package/docs/zh-CN/channels/groups.md +379 -0
  1525. package/docs/zh-CN/channels/imessage.md +302 -0
  1526. package/docs/zh-CN/channels/index.md +53 -0
  1527. package/docs/zh-CN/channels/line.md +180 -0
  1528. package/docs/zh-CN/channels/location.md +63 -0
  1529. package/docs/zh-CN/channels/matrix.md +221 -0
  1530. package/docs/zh-CN/channels/mattermost.md +144 -0
  1531. package/docs/zh-CN/channels/msteams.md +775 -0
  1532. package/docs/zh-CN/channels/nextcloud-talk.md +142 -0
  1533. package/docs/zh-CN/channels/nostr.md +249 -0
  1534. package/docs/zh-CN/channels/pairing.md +89 -0
  1535. package/docs/zh-CN/channels/signal.md +209 -0
  1536. package/docs/zh-CN/channels/slack.md +531 -0
  1537. package/docs/zh-CN/channels/synology-chat.md +138 -0
  1538. package/docs/zh-CN/channels/telegram.md +751 -0
  1539. package/docs/zh-CN/channels/tlon.md +136 -0
  1540. package/docs/zh-CN/channels/troubleshooting.md +36 -0
  1541. package/docs/zh-CN/channels/twitch.md +385 -0
  1542. package/docs/zh-CN/channels/whatsapp.md +411 -0
  1543. package/docs/zh-CN/channels/zalo.md +196 -0
  1544. package/docs/zh-CN/channels/zalouser.md +147 -0
  1545. package/docs/zh-CN/cli/acp.md +173 -0
  1546. package/docs/zh-CN/cli/agent.md +30 -0
  1547. package/docs/zh-CN/cli/agents.md +82 -0
  1548. package/docs/zh-CN/cli/approvals.md +57 -0
  1549. package/docs/zh-CN/cli/browser.md +114 -0
  1550. package/docs/zh-CN/cli/channels.md +86 -0
  1551. package/docs/zh-CN/cli/config.md +57 -0
  1552. package/docs/zh-CN/cli/configure.md +38 -0
  1553. package/docs/zh-CN/cli/cron.md +43 -0
  1554. package/docs/zh-CN/cli/dashboard.md +23 -0
  1555. package/docs/zh-CN/cli/devices.md +74 -0
  1556. package/docs/zh-CN/cli/directory.md +70 -0
  1557. package/docs/zh-CN/cli/dns.md +30 -0
  1558. package/docs/zh-CN/cli/docs.md +22 -0
  1559. package/docs/zh-CN/cli/doctor.md +48 -0
  1560. package/docs/zh-CN/cli/gateway.md +206 -0
  1561. package/docs/zh-CN/cli/health.md +28 -0
  1562. package/docs/zh-CN/cli/hooks.md +298 -0
  1563. package/docs/zh-CN/cli/index.md +1143 -0
  1564. package/docs/zh-CN/cli/logs.md +31 -0
  1565. package/docs/zh-CN/cli/memory.md +52 -0
  1566. package/docs/zh-CN/cli/message.md +246 -0
  1567. package/docs/zh-CN/cli/models.md +85 -0
  1568. package/docs/zh-CN/cli/node.md +115 -0
  1569. package/docs/zh-CN/cli/nodes.md +80 -0
  1570. package/docs/zh-CN/cli/onboard.md +164 -0
  1571. package/docs/zh-CN/cli/pairing.md +28 -0
  1572. package/docs/zh-CN/cli/plugins.md +66 -0
  1573. package/docs/zh-CN/cli/reset.md +24 -0
  1574. package/docs/zh-CN/cli/sandbox.md +158 -0
  1575. package/docs/zh-CN/cli/security.md +33 -0
  1576. package/docs/zh-CN/cli/sessions.md +23 -0
  1577. package/docs/zh-CN/cli/setup.md +36 -0
  1578. package/docs/zh-CN/cli/skills.md +33 -0
  1579. package/docs/zh-CN/cli/status.md +33 -0
  1580. package/docs/zh-CN/cli/system.md +63 -0
  1581. package/docs/zh-CN/cli/tui.md +30 -0
  1582. package/docs/zh-CN/cli/uninstall.md +24 -0
  1583. package/docs/zh-CN/cli/update.md +101 -0
  1584. package/docs/zh-CN/cli/voicecall.md +41 -0
  1585. package/docs/zh-CN/cli/webhooks.md +32 -0
  1586. package/docs/zh-CN/concepts/agent-loop.md +146 -0
  1587. package/docs/zh-CN/concepts/agent-workspace.md +219 -0
  1588. package/docs/zh-CN/concepts/agent.md +115 -0
  1589. package/docs/zh-CN/concepts/architecture.md +123 -0
  1590. package/docs/zh-CN/concepts/compaction.md +67 -0
  1591. package/docs/zh-CN/concepts/context.md +168 -0
  1592. package/docs/zh-CN/concepts/features.md +59 -0
  1593. package/docs/zh-CN/concepts/markdown-formatting.md +117 -0
  1594. package/docs/zh-CN/concepts/memory.md +412 -0
  1595. package/docs/zh-CN/concepts/messages.md +141 -0
  1596. package/docs/zh-CN/concepts/model-failover.md +145 -0
  1597. package/docs/zh-CN/concepts/model-providers.md +606 -0
  1598. package/docs/zh-CN/concepts/models.md +225 -0
  1599. package/docs/zh-CN/concepts/multi-agent.md +372 -0
  1600. package/docs/zh-CN/concepts/oauth.md +164 -0
  1601. package/docs/zh-CN/concepts/presence.md +99 -0
  1602. package/docs/zh-CN/concepts/queue.md +94 -0
  1603. package/docs/zh-CN/concepts/retry.md +76 -0
  1604. package/docs/zh-CN/concepts/session-pruning.md +129 -0
  1605. package/docs/zh-CN/concepts/session-tool.md +200 -0
  1606. package/docs/zh-CN/concepts/session.md +166 -0
  1607. package/docs/zh-CN/concepts/streaming.md +133 -0
  1608. package/docs/zh-CN/concepts/system-prompt.md +101 -0
  1609. package/docs/zh-CN/concepts/timezone.md +96 -0
  1610. package/docs/zh-CN/concepts/typebox.md +284 -0
  1611. package/docs/zh-CN/concepts/typing-indicators.md +74 -0
  1612. package/docs/zh-CN/concepts/usage-tracking.md +42 -0
  1613. package/docs/zh-CN/date-time.md +129 -0
  1614. package/docs/zh-CN/debug/node-issue.md +90 -0
  1615. package/docs/zh-CN/diagnostics/flags.md +98 -0
  1616. package/docs/zh-CN/gateway/authentication.md +184 -0
  1617. package/docs/zh-CN/gateway/background-process.md +100 -0
  1618. package/docs/zh-CN/gateway/bonjour.md +174 -0
  1619. package/docs/zh-CN/gateway/bridge-protocol.md +86 -0
  1620. package/docs/zh-CN/gateway/cli-backends.md +213 -0
  1621. package/docs/zh-CN/gateway/configuration-examples.md +587 -0
  1622. package/docs/zh-CN/gateway/configuration-reference.md +3103 -0
  1623. package/docs/zh-CN/gateway/configuration.md +640 -0
  1624. package/docs/zh-CN/gateway/discovery.md +123 -0
  1625. package/docs/zh-CN/gateway/doctor.md +238 -0
  1626. package/docs/zh-CN/gateway/gateway-lock.md +41 -0
  1627. package/docs/zh-CN/gateway/health.md +42 -0
  1628. package/docs/zh-CN/gateway/heartbeat.md +274 -0
  1629. package/docs/zh-CN/gateway/index.md +335 -0
  1630. package/docs/zh-CN/gateway/local-models.md +159 -0
  1631. package/docs/zh-CN/gateway/logging.md +114 -0
  1632. package/docs/zh-CN/gateway/multiple-gateways.md +119 -0
  1633. package/docs/zh-CN/gateway/network-model.md +23 -0
  1634. package/docs/zh-CN/gateway/openai-http-api.md +125 -0
  1635. package/docs/zh-CN/gateway/openresponses-http-api.md +317 -0
  1636. package/docs/zh-CN/gateway/pairing.md +99 -0
  1637. package/docs/zh-CN/gateway/protocol.md +220 -0
  1638. package/docs/zh-CN/gateway/remote-gateway-readme.md +164 -0
  1639. package/docs/zh-CN/gateway/remote.md +133 -0
  1640. package/docs/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated.md +135 -0
  1641. package/docs/zh-CN/gateway/sandboxing.md +188 -0
  1642. package/docs/zh-CN/gateway/security/index.md +777 -0
  1643. package/docs/zh-CN/gateway/tailscale.md +124 -0
  1644. package/docs/zh-CN/gateway/tools-invoke-http-api.md +92 -0
  1645. package/docs/zh-CN/gateway/troubleshooting.md +771 -0
  1646. package/docs/zh-CN/help/debugging.md +160 -0
  1647. package/docs/zh-CN/help/environment.md +88 -0
  1648. package/docs/zh-CN/help/faq.md +2640 -0
  1649. package/docs/zh-CN/help/index.md +28 -0
  1650. package/docs/zh-CN/help/scripts.md +35 -0
  1651. package/docs/zh-CN/help/testing.md +375 -0
  1652. package/docs/zh-CN/help/troubleshooting.md +104 -0
  1653. package/docs/zh-CN/index.md +186 -0
  1654. package/docs/zh-CN/install/ansible.md +215 -0
  1655. package/docs/zh-CN/install/bun.md +65 -0
  1656. package/docs/zh-CN/install/development-channels.md +81 -0
  1657. package/docs/zh-CN/install/docker.md +532 -0
  1658. package/docs/zh-CN/install/exe-dev.md +133 -0
  1659. package/docs/zh-CN/install/fly.md +490 -0
  1660. package/docs/zh-CN/install/gcp.md +510 -0
  1661. package/docs/zh-CN/install/hetzner.md +337 -0
  1662. package/docs/zh-CN/install/index.md +235 -0
  1663. package/docs/zh-CN/install/installer.md +422 -0
  1664. package/docs/zh-CN/install/macos-vm.md +288 -0
  1665. package/docs/zh-CN/install/migrating.md +199 -0
  1666. package/docs/zh-CN/install/nix.md +99 -0
  1667. package/docs/zh-CN/install/node.md +8 -0
  1668. package/docs/zh-CN/install/northflank.mdx +60 -0
  1669. package/docs/zh-CN/install/railway.mdx +106 -0
  1670. package/docs/zh-CN/install/render.mdx +169 -0
  1671. package/docs/zh-CN/install/uninstall.md +135 -0
  1672. package/docs/zh-CN/install/updating.md +233 -0
  1673. package/docs/zh-CN/logging.md +329 -0
  1674. package/docs/zh-CN/network.md +59 -0
  1675. package/docs/zh-CN/nodes/audio.md +120 -0
  1676. package/docs/zh-CN/nodes/camera.md +162 -0
  1677. package/docs/zh-CN/nodes/images.md +79 -0
  1678. package/docs/zh-CN/nodes/index.md +348 -0
  1679. package/docs/zh-CN/nodes/location-command.md +120 -0
  1680. package/docs/zh-CN/nodes/media-understanding.md +380 -0
  1681. package/docs/zh-CN/nodes/talk.md +97 -0
  1682. package/docs/zh-CN/nodes/troubleshooting.md +8 -0
  1683. package/docs/zh-CN/nodes/voicewake.md +72 -0
  1684. package/docs/zh-CN/perplexity.md +102 -0
  1685. package/docs/zh-CN/pi-dev.md +77 -0
  1686. package/docs/zh-CN/pi.md +619 -0
  1687. package/docs/zh-CN/platforms/android.md +155 -0
  1688. package/docs/zh-CN/platforms/digitalocean.md +273 -0
  1689. package/docs/zh-CN/platforms/index.md +60 -0
  1690. package/docs/zh-CN/platforms/ios.md +114 -0
  1691. package/docs/zh-CN/platforms/linux.md +100 -0
  1692. package/docs/zh-CN/platforms/mac/bundled-gateway.md +75 -0
  1693. package/docs/zh-CN/platforms/mac/canvas.md +128 -0
  1694. package/docs/zh-CN/platforms/mac/child-process.md +73 -0
  1695. package/docs/zh-CN/platforms/mac/dev-setup.md +109 -0
  1696. package/docs/zh-CN/platforms/mac/health.md +41 -0
  1697. package/docs/zh-CN/platforms/mac/icon.md +38 -0
  1698. package/docs/zh-CN/platforms/mac/logging.md +64 -0
  1699. package/docs/zh-CN/platforms/mac/menu-bar.md +88 -0
  1700. package/docs/zh-CN/platforms/mac/peekaboo.md +62 -0
  1701. package/docs/zh-CN/platforms/mac/permissions.md +46 -0
  1702. package/docs/zh-CN/platforms/mac/remote.md +90 -0
  1703. package/docs/zh-CN/platforms/mac/signing.md +54 -0
  1704. package/docs/zh-CN/platforms/mac/skills.md +40 -0
  1705. package/docs/zh-CN/platforms/mac/voice-overlay.md +67 -0
  1706. package/docs/zh-CN/platforms/mac/voicewake.md +74 -0
  1707. package/docs/zh-CN/platforms/mac/webchat.md +43 -0
  1708. package/docs/zh-CN/platforms/mac/xpc.md +68 -0
  1709. package/docs/zh-CN/platforms/macos.md +193 -0
  1710. package/docs/zh-CN/platforms/oracle.md +310 -0
  1711. package/docs/zh-CN/platforms/raspberry-pi.md +416 -0
  1712. package/docs/zh-CN/platforms/windows.md +247 -0
  1713. package/docs/zh-CN/plugins/agent-tools.md +99 -0
  1714. package/docs/zh-CN/plugins/manifest.md +68 -0
  1715. package/docs/zh-CN/plugins/voice-call.md +250 -0
  1716. package/docs/zh-CN/plugins/zalouser.md +88 -0
  1717. package/docs/zh-CN/prose.md +141 -0
  1718. package/docs/zh-CN/providers/anthropic.md +265 -0
  1719. package/docs/zh-CN/providers/bedrock.md +170 -0
  1720. package/docs/zh-CN/providers/claude-max-api-proxy.md +155 -0
  1721. package/docs/zh-CN/providers/cloudflare-ai-gateway.md +78 -0
  1722. package/docs/zh-CN/providers/deepgram.md +97 -0
  1723. package/docs/zh-CN/providers/github-copilot.md +67 -0
  1724. package/docs/zh-CN/providers/glm.md +50 -0
  1725. package/docs/zh-CN/providers/huggingface.md +216 -0
  1726. package/docs/zh-CN/providers/index.md +69 -0
  1727. package/docs/zh-CN/providers/kilocode.md +80 -0
  1728. package/docs/zh-CN/providers/litellm.md +160 -0
  1729. package/docs/zh-CN/providers/minimax.md +222 -0
  1730. package/docs/zh-CN/providers/mistral.md +61 -0
  1731. package/docs/zh-CN/providers/models.md +51 -0
  1732. package/docs/zh-CN/providers/moonshot.md +182 -0
  1733. package/docs/zh-CN/providers/nvidia.md +62 -0
  1734. package/docs/zh-CN/providers/ollama.md +359 -0
  1735. package/docs/zh-CN/providers/openai.md +308 -0
  1736. package/docs/zh-CN/providers/opencode-go.md +52 -0
  1737. package/docs/zh-CN/providers/opencode.md +71 -0
  1738. package/docs/zh-CN/providers/openrouter.md +44 -0
  1739. package/docs/zh-CN/providers/qianfan.md +45 -0
  1740. package/docs/zh-CN/providers/qwen.md +55 -0
  1741. package/docs/zh-CN/providers/sglang.md +111 -0
  1742. package/docs/zh-CN/providers/synthetic.md +106 -0
  1743. package/docs/zh-CN/providers/together.md +72 -0
  1744. package/docs/zh-CN/providers/venice.md +289 -0
  1745. package/docs/zh-CN/providers/vercel-ai-gateway.md +66 -0
  1746. package/docs/zh-CN/providers/xiaomi.md +93 -0
  1747. package/docs/zh-CN/providers/zai.md +53 -0
  1748. package/docs/zh-CN/reference/AGENTS.default.md +131 -0
  1749. package/docs/zh-CN/reference/RELEASING.md +48 -0
  1750. package/docs/zh-CN/reference/api-usage-costs.md +141 -0
  1751. package/docs/zh-CN/reference/credits.md +34 -0
  1752. package/docs/zh-CN/reference/device-models.md +54 -0
  1753. package/docs/zh-CN/reference/rpc.md +48 -0
  1754. package/docs/zh-CN/reference/session-management-compaction.md +287 -0
  1755. package/docs/zh-CN/reference/templates/AGENTS.dev.md +89 -0
  1756. package/docs/zh-CN/reference/templates/AGENTS.md +225 -0
  1757. package/docs/zh-CN/reference/templates/BOOT.md +17 -0
  1758. package/docs/zh-CN/reference/templates/BOOTSTRAP.md +68 -0
  1759. package/docs/zh-CN/reference/templates/HEARTBEAT.md +18 -0
  1760. package/docs/zh-CN/reference/templates/IDENTITY.dev.md +54 -0
  1761. package/docs/zh-CN/reference/templates/IDENTITY.md +36 -0
  1762. package/docs/zh-CN/reference/templates/SOUL.dev.md +83 -0
  1763. package/docs/zh-CN/reference/templates/SOUL.md +49 -0
  1764. package/docs/zh-CN/reference/templates/TOOLS.dev.md +31 -0
  1765. package/docs/zh-CN/reference/templates/TOOLS.md +53 -0
  1766. package/docs/zh-CN/reference/templates/USER.dev.md +25 -0
  1767. package/docs/zh-CN/reference/templates/USER.md +30 -0
  1768. package/docs/zh-CN/reference/test.md +57 -0
  1769. package/docs/zh-CN/reference/token-use.md +119 -0
  1770. package/docs/zh-CN/reference/transcript-hygiene.md +109 -0
  1771. package/docs/zh-CN/reference/wizard.md +242 -0
  1772. package/docs/zh-CN/security/formal-verification.md +171 -0
  1773. package/docs/zh-CN/start/bootstrapping.md +9 -0
  1774. package/docs/zh-CN/start/docs-directory.md +70 -0
  1775. package/docs/zh-CN/start/getting-started.md +143 -0
  1776. package/docs/zh-CN/start/hubs.md +194 -0
  1777. package/docs/zh-CN/start/lore.md +226 -0
  1778. package/docs/zh-CN/start/onboarding-overview.md +58 -0
  1779. package/docs/zh-CN/start/onboarding.md +105 -0
  1780. package/docs/zh-CN/start/openclaw.md +248 -0
  1781. package/docs/zh-CN/start/quickstart.md +88 -0
  1782. package/docs/zh-CN/start/setup.md +153 -0
  1783. package/docs/zh-CN/start/showcase.md +423 -0
  1784. package/docs/zh-CN/start/wizard-cli-automation.md +222 -0
  1785. package/docs/zh-CN/start/wizard-cli-reference.md +306 -0
  1786. package/docs/zh-CN/start/wizard.md +132 -0
  1787. package/docs/zh-CN/tools/agent-send.md +59 -0
  1788. package/docs/zh-CN/tools/apply-patch.md +57 -0
  1789. package/docs/zh-CN/tools/browser-linux-troubleshooting.md +144 -0
  1790. package/docs/zh-CN/tools/browser-login.md +75 -0
  1791. package/docs/zh-CN/tools/browser.md +553 -0
  1792. package/docs/zh-CN/tools/chrome-extension.md +183 -0
  1793. package/docs/zh-CN/tools/clawhub.md +209 -0
  1794. package/docs/zh-CN/tools/creating-skills.md +61 -0
  1795. package/docs/zh-CN/tools/elevated.md +64 -0
  1796. package/docs/zh-CN/tools/exec-approvals.md +234 -0
  1797. package/docs/zh-CN/tools/exec.md +169 -0
  1798. package/docs/zh-CN/tools/firecrawl.md +68 -0
  1799. package/docs/zh-CN/tools/index.md +515 -0
  1800. package/docs/zh-CN/tools/llm-task.md +117 -0
  1801. package/docs/zh-CN/tools/lobster.md +349 -0
  1802. package/docs/zh-CN/tools/multi-agent-sandbox-tools.md +401 -0
  1803. package/docs/zh-CN/tools/plugin.md +1612 -0
  1804. package/docs/zh-CN/tools/reactions.md +29 -0
  1805. package/docs/zh-CN/tools/skills-config.md +78 -0
  1806. package/docs/zh-CN/tools/skills.md +279 -0
  1807. package/docs/zh-CN/tools/slash-commands.md +205 -0
  1808. package/docs/zh-CN/tools/subagents.md +167 -0
  1809. package/docs/zh-CN/tools/thinking.md +80 -0
  1810. package/docs/zh-CN/tools/web.md +289 -0
  1811. package/docs/zh-CN/tts.md +375 -0
  1812. package/docs/zh-CN/vps.md +47 -0
  1813. package/docs/zh-CN/web/control-ui.md +191 -0
  1814. package/docs/zh-CN/web/dashboard.md +53 -0
  1815. package/docs/zh-CN/web/index.md +118 -0
  1816. package/docs/zh-CN/web/tui.md +166 -0
  1817. package/docs/zh-CN/web/webchat.md +56 -0
  1818. package/openclaw.mjs +135 -0
  1819. package/package.json +835 -0
  1820. package/skills/1password/SKILL.md +70 -0
  1821. package/skills/1password/references/cli-examples.md +29 -0
  1822. package/skills/1password/references/get-started.md +17 -0
  1823. package/skills/apple-notes/SKILL.md +77 -0
  1824. package/skills/apple-reminders/SKILL.md +118 -0
  1825. package/skills/bear-notes/SKILL.md +107 -0
  1826. package/skills/blogwatcher/SKILL.md +69 -0
  1827. package/skills/blucli/SKILL.md +47 -0
  1828. package/skills/bluebubbles/SKILL.md +131 -0
  1829. package/skills/camsnap/SKILL.md +45 -0
  1830. package/skills/canvas/SKILL.md +198 -0
  1831. package/skills/clawhub/SKILL.md +77 -0
  1832. package/skills/coding-agent/SKILL.md +295 -0
  1833. package/skills/discord/SKILL.md +197 -0
  1834. package/skills/doubao-code/SKILL.md +43 -0
  1835. package/skills/eightctl/SKILL.md +50 -0
  1836. package/skills/gemini/SKILL.md +43 -0
  1837. package/skills/gh-issues/SKILL.md +865 -0
  1838. package/skills/gifgrep/SKILL.md +79 -0
  1839. package/skills/github/SKILL.md +163 -0
  1840. package/skills/gog/SKILL.md +116 -0
  1841. package/skills/goplaces/SKILL.md +52 -0
  1842. package/skills/healthcheck/SKILL.md +245 -0
  1843. package/skills/himalaya/SKILL.md +257 -0
  1844. package/skills/himalaya/references/configuration.md +184 -0
  1845. package/skills/himalaya/references/message-composition.md +199 -0
  1846. package/skills/imsg/SKILL.md +122 -0
  1847. package/skills/kimi-code/SKILL.md +42 -0
  1848. package/skills/mcporter/SKILL.md +61 -0
  1849. package/skills/model-usage/SKILL.md +69 -0
  1850. package/skills/model-usage/references/codexbar-cli.md +33 -0
  1851. package/skills/model-usage/scripts/model_usage.py +320 -0
  1852. package/skills/model-usage/scripts/test_model_usage.py +40 -0
  1853. package/skills/nano-pdf/SKILL.md +38 -0
  1854. package/skills/node-connect/SKILL.md +142 -0
  1855. package/skills/notion/SKILL.md +174 -0
  1856. package/skills/obsidian/SKILL.md +81 -0
  1857. package/skills/openai-image-gen/SKILL.md +92 -0
  1858. package/skills/openai-image-gen/scripts/gen.py +328 -0
  1859. package/skills/openai-image-gen/scripts/test_gen.py +140 -0
  1860. package/skills/openai-whisper/SKILL.md +38 -0
  1861. package/skills/openai-whisper-api/SKILL.md +52 -0
  1862. package/skills/openai-whisper-api/scripts/transcribe.sh +85 -0
  1863. package/skills/openhue/SKILL.md +112 -0
  1864. package/skills/oracle/SKILL.md +125 -0
  1865. package/skills/ordercli/SKILL.md +78 -0
  1866. package/skills/peekaboo/SKILL.md +190 -0
  1867. package/skills/sag/SKILL.md +87 -0
  1868. package/skills/session-logs/SKILL.md +115 -0
  1869. package/skills/sherpa-onnx-tts/SKILL.md +103 -0
  1870. package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +178 -0
  1871. package/skills/skill-creator/SKILL.md +372 -0
  1872. package/skills/skill-creator/license.txt +202 -0
  1873. package/skills/skill-creator/scripts/init_skill.py +378 -0
  1874. package/skills/skill-creator/scripts/package_skill.py +139 -0
  1875. package/skills/skill-creator/scripts/quick_validate.py +159 -0
  1876. package/skills/skill-creator/scripts/test_package_skill.py +160 -0
  1877. package/skills/skill-creator/scripts/test_quick_validate.py +72 -0
  1878. package/skills/slack/SKILL.md +144 -0
  1879. package/skills/songsee/SKILL.md +49 -0
  1880. package/skills/sonoscli/SKILL.md +65 -0
  1881. package/skills/spotify-player/SKILL.md +64 -0
  1882. package/skills/summarize/SKILL.md +87 -0
  1883. package/skills/things-mac/SKILL.md +86 -0
  1884. package/skills/tmux/SKILL.md +153 -0
  1885. package/skills/tmux/scripts/find-sessions.sh +112 -0
  1886. package/skills/tmux/scripts/wait-for-text.sh +83 -0
  1887. package/skills/trello/SKILL.md +95 -0
  1888. package/skills/video-frames/SKILL.md +46 -0
  1889. package/skills/video-frames/scripts/frame.sh +81 -0
  1890. package/skills/voice-call/SKILL.md +45 -0
  1891. package/skills/wacli/SKILL.md +72 -0
  1892. package/skills/weather/SKILL.md +112 -0
  1893. package/skills/xurl/SKILL.md +461 -0
@@ -0,0 +1,3272 @@
1
+ import { o as __toESM } from "./src-CmXHIz5f.js";
2
+ import { c as normalizeAgentId, u as resolveAgentIdFromSessionKey } from "./session-key-gFFk3uv9.js";
3
+ import { n as deriveLastRoutePolicy } from "./resolve-route-vEY3ONZ2.js";
4
+ import { n as resolveAgentOutboundIdentity } from "./identity-DovQV4zD.js";
5
+ import { o as getSessionBindingService } from "./thread-bindings-messages-Cdo8jSa9.js";
6
+ import { a as resolveConfiguredBindingRoute, i as ensureConfiguredBindingRouteReady } from "./conversation-runtime-1O0Aaolb.js";
7
+ import { t as createDedupeCache } from "./dedupe-Cgnk5BbX.js";
8
+ import { n as fetchWithSsrFGuard } from "./fetch-guard-DIyN1HW5.js";
9
+ import { n as createReplyPrefixContext } from "./typing-DG_YqWJ7.js";
10
+ import { a as warnMissingProviderGroupPolicyFallbackOnce, i as resolveOpenProviderRuntimeGroupPolicy, r as resolveDefaultGroupPolicy } from "./runtime-group-policy-B7irU4eu.js";
11
+ import { n as createChannelPairingController } from "./channel-pairing-D54mn51y.js";
12
+ import { t as readJsonFileWithFallback } from "./json-store-O1LwpnBH.js";
13
+ import { h as sendMediaWithLeadingCaption, m as resolveTextChunksWithFallback, p as resolveSendableOutboundReplyParts } from "./reply-payload-DBGc074f.js";
14
+ import { l as buildAgentMediaPayload } from "./axios-xDDnM0KG.js";
15
+ import { i as installRequestBodyLimitGuard, o as readJsonBodyWithLimit } from "./http-body-CCiSfloA.js";
16
+ import { a as buildPendingHistoryContextFromMap, s as clearHistoryEntriesIfEnabled, u as recordPendingHistoryEntryIfEnabled } from "./history-CHjo8B5W.js";
17
+ import { r as logTypingFailure } from "./logging-Bz1qZDPg.js";
18
+ import { t as createChannelReplyPipeline } from "./channel-reply-pipeline-CPTuaW8n.js";
19
+ import { a as createFixedWindowRateLimiter, o as createWebhookAnomalyTracker, r as WEBHOOK_RATE_LIMIT_DEFAULTS, t as WEBHOOK_ANOMALY_COUNTER_DEFAULTS } from "./webhook-memory-guards-BHrFZ4yq.js";
20
+ import { d as applyBasicWebhookRequestGuards } from "./webhook-ingress-CupqYpKM.js";
21
+ import { c as createFeishuClient, d as raceWithTimeoutAndAbort, f as listEnabledFeishuAccounts, h as resolveFeishuAccount, l as createFeishuWSClient, o as probeFeishu, s as createEventDispatcher, t as createFeishuThreadBindingManager, u as require_lib } from "./feishu-Dh5fEbh5.js";
22
+ import { t as createPersistentDedupe } from "./persistent-dedupe-bjKjVI5u.js";
23
+ import { a as resolveReceiveIdType, t as getFeishuRuntime } from "./runtime-B66W9flm.js";
24
+ import { a as resolveFeishuReplyPolicy, n as resolveFeishuAllowlistMatch, r as resolveFeishuGroupConfig, t as isFeishuGroupAllowed } from "./policy-CpkbSAfm.js";
25
+ import { C as sendMediaFeishu, E as normalizeFeishuExternalKey, a as sendCardFeishu, b as downloadMessageResourceFeishu, c as sendStructuredCardFeishu, f as extractMentionTargets, i as resolveFeishuCardTemplate, n as getMessageFeishu, r as listFeishuThreadMessages, s as sendMessageFeishu, u as buildMentionedCardContent, v as isMentionForwardRequest, y as parsePostContent } from "./send-CC5J3tyW.js";
26
+ import fs from "node:fs";
27
+ import path from "node:path";
28
+ import os from "node:os";
29
+ import crypto from "node:crypto";
30
+ import * as http from "http";
31
+ import * as crypto$1 from "crypto";
32
+ //#region extensions/feishu/src/bot-content.ts
33
+ function buildFeishuConversationId(params) {
34
+ switch (params.scope) {
35
+ case "group_sender": return `${params.chatId}:sender:${params.senderOpenId}`;
36
+ case "group_topic": return `${params.chatId}:topic:${params.topicId}`;
37
+ case "group_topic_sender": return `${params.chatId}:topic:${params.topicId}:sender:${params.senderOpenId}`;
38
+ default: return params.chatId;
39
+ }
40
+ }
41
+ function resolveFeishuGroupSession(params) {
42
+ const { chatId, senderOpenId, messageId, rootId, threadId, groupConfig, feishuCfg } = params;
43
+ const normalizedThreadId = threadId?.trim();
44
+ const normalizedRootId = rootId?.trim();
45
+ const threadReply = Boolean(normalizedThreadId || normalizedRootId);
46
+ const replyInThread = (groupConfig?.replyInThread ?? feishuCfg?.replyInThread ?? "disabled") === "enabled" || threadReply;
47
+ const legacyTopicSessionMode = groupConfig?.topicSessionMode ?? feishuCfg?.topicSessionMode ?? "disabled";
48
+ const groupSessionScope = groupConfig?.groupSessionScope ?? feishuCfg?.groupSessionScope ?? (legacyTopicSessionMode === "enabled" ? "group_topic" : "group");
49
+ const topicScope = groupSessionScope === "group_topic" || groupSessionScope === "group_topic_sender" ? normalizedRootId ?? normalizedThreadId ?? (replyInThread ? messageId : null) : null;
50
+ let peerId = chatId;
51
+ switch (groupSessionScope) {
52
+ case "group_sender":
53
+ peerId = buildFeishuConversationId({
54
+ chatId,
55
+ scope: "group_sender",
56
+ senderOpenId
57
+ });
58
+ break;
59
+ case "group_topic":
60
+ peerId = topicScope ? buildFeishuConversationId({
61
+ chatId,
62
+ scope: "group_topic",
63
+ topicId: topicScope
64
+ }) : chatId;
65
+ break;
66
+ case "group_topic_sender":
67
+ peerId = topicScope ? buildFeishuConversationId({
68
+ chatId,
69
+ scope: "group_topic_sender",
70
+ topicId: topicScope,
71
+ senderOpenId
72
+ }) : buildFeishuConversationId({
73
+ chatId,
74
+ scope: "group_sender",
75
+ senderOpenId
76
+ });
77
+ break;
78
+ default:
79
+ peerId = chatId;
80
+ break;
81
+ }
82
+ return {
83
+ peerId,
84
+ parentPeer: topicScope && (groupSessionScope === "group_topic" || groupSessionScope === "group_topic_sender") ? {
85
+ kind: "group",
86
+ id: chatId
87
+ } : null,
88
+ groupSessionScope,
89
+ replyInThread,
90
+ threadReply
91
+ };
92
+ }
93
+ function parseMessageContent(content, messageType) {
94
+ if (messageType === "post") return parsePostContent(content).textContent;
95
+ try {
96
+ const parsed = JSON.parse(content);
97
+ if (messageType === "text") return parsed.text || "";
98
+ if (messageType === "share_chat") {
99
+ if (parsed && typeof parsed === "object") {
100
+ const share = parsed;
101
+ if (typeof share.body === "string" && share.body.trim()) return share.body.trim();
102
+ if (typeof share.summary === "string" && share.summary.trim()) return share.summary.trim();
103
+ if (typeof share.share_chat_id === "string" && share.share_chat_id.trim()) return `[Forwarded message: ${share.share_chat_id.trim()}]`;
104
+ }
105
+ return "[Forwarded message]";
106
+ }
107
+ if (messageType === "merge_forward") return "[Merged and Forwarded Message - loading...]";
108
+ return content;
109
+ } catch {
110
+ return content;
111
+ }
112
+ }
113
+ function formatSubMessageContent(content, contentType) {
114
+ try {
115
+ const parsed = JSON.parse(content);
116
+ switch (contentType) {
117
+ case "text": return parsed.text || content;
118
+ case "post": return parsePostContent(content).textContent;
119
+ case "image": return "[Image]";
120
+ case "file": return `[File: ${parsed.file_name || "unknown"}]`;
121
+ case "audio": return "[Audio]";
122
+ case "video": return "[Video]";
123
+ case "sticker": return "[Sticker]";
124
+ case "merge_forward": return "[Nested Merged Forward]";
125
+ default: return `[${contentType}]`;
126
+ }
127
+ } catch {
128
+ return content;
129
+ }
130
+ }
131
+ function parseMergeForwardContent(params) {
132
+ const { content, log } = params;
133
+ const maxMessages = 50;
134
+ log?.("feishu: parsing merge_forward sub-messages from API response");
135
+ let items;
136
+ try {
137
+ items = JSON.parse(content);
138
+ } catch {
139
+ log?.("feishu: merge_forward items parse failed");
140
+ return "[Merged and Forwarded Message - parse error]";
141
+ }
142
+ if (!Array.isArray(items) || items.length === 0) return "[Merged and Forwarded Message - no sub-messages]";
143
+ const subMessages = items.filter((item) => item.upper_message_id);
144
+ if (subMessages.length === 0) return "[Merged and Forwarded Message - no sub-messages found]";
145
+ log?.(`feishu: merge_forward contains ${subMessages.length} sub-messages`);
146
+ subMessages.sort((a, b) => parseInt(a.create_time || "0", 10) - parseInt(b.create_time || "0", 10));
147
+ const lines = ["[Merged and Forwarded Messages]"];
148
+ for (const item of subMessages.slice(0, maxMessages)) lines.push(`- ${formatSubMessageContent(item.body?.content || "", item.msg_type || "text")}`);
149
+ if (subMessages.length > maxMessages) lines.push(`... and ${subMessages.length - maxMessages} more messages`);
150
+ return lines.join("\n");
151
+ }
152
+ function checkBotMentioned(event, botOpenId) {
153
+ if (!botOpenId) return false;
154
+ if ((event.message.content ?? "").includes("@_all")) return true;
155
+ const mentions = event.message.mentions ?? [];
156
+ if (mentions.length > 0) return mentions.some((mention) => mention.id.open_id === botOpenId);
157
+ if (event.message.message_type === "post") return parsePostContent(event.message.content).mentionedOpenIds.some((id) => id === botOpenId);
158
+ return false;
159
+ }
160
+ function normalizeMentions(text, mentions, botStripId) {
161
+ if (!mentions || mentions.length === 0) return text;
162
+ const escaped = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
163
+ const escapeName = (value) => value.replace(/</g, "&lt;").replace(/>/g, "&gt;");
164
+ let result = text;
165
+ for (const mention of mentions) {
166
+ const mentionId = mention.id.open_id;
167
+ const replacement = botStripId && mentionId === botStripId ? "" : mentionId ? `<at user_id="${mentionId}">${escapeName(mention.name)}</at>` : `@${mention.name}`;
168
+ result = result.replace(new RegExp(escaped(mention.key), "g"), () => replacement).trim();
169
+ }
170
+ return result;
171
+ }
172
+ function normalizeFeishuCommandProbeBody(text) {
173
+ if (!text) return "";
174
+ return text.replace(/<at\b[^>]*>[^<]*<\/at>/giu, " ").replace(/(^|\s)@[^/\s]+(?=\s|$|\/)/gu, "$1").replace(/\s+/g, " ").trim();
175
+ }
176
+ function parseMediaKeys(content, messageType) {
177
+ try {
178
+ const parsed = JSON.parse(content);
179
+ const imageKey = normalizeFeishuExternalKey(parsed.image_key);
180
+ const fileKey = normalizeFeishuExternalKey(parsed.file_key);
181
+ switch (messageType) {
182
+ case "image": return {
183
+ imageKey,
184
+ fileName: parsed.file_name
185
+ };
186
+ case "file":
187
+ case "audio":
188
+ case "sticker": return {
189
+ fileKey,
190
+ fileName: parsed.file_name
191
+ };
192
+ case "video":
193
+ case "media": return {
194
+ fileKey,
195
+ imageKey,
196
+ fileName: parsed.file_name
197
+ };
198
+ default: return {};
199
+ }
200
+ } catch {
201
+ return {};
202
+ }
203
+ }
204
+ function toMessageResourceType(messageType) {
205
+ return messageType === "image" ? "image" : "file";
206
+ }
207
+ function inferPlaceholder(messageType) {
208
+ switch (messageType) {
209
+ case "image": return "<media:image>";
210
+ case "file": return "<media:document>";
211
+ case "audio": return "<media:audio>";
212
+ case "video":
213
+ case "media": return "<media:video>";
214
+ case "sticker": return "<media:sticker>";
215
+ default: return "<media:document>";
216
+ }
217
+ }
218
+ async function resolveFeishuMediaList(params) {
219
+ const { cfg, messageId, messageType, content, maxBytes, log, accountId } = params;
220
+ if (![
221
+ "image",
222
+ "file",
223
+ "audio",
224
+ "video",
225
+ "media",
226
+ "sticker",
227
+ "post"
228
+ ].includes(messageType)) return [];
229
+ const out = [];
230
+ const core = getFeishuRuntime();
231
+ if (messageType === "post") {
232
+ const { imageKeys, mediaKeys } = parsePostContent(content);
233
+ if (imageKeys.length === 0 && mediaKeys.length === 0) return [];
234
+ if (imageKeys.length > 0) log?.(`feishu: post message contains ${imageKeys.length} embedded image(s)`);
235
+ if (mediaKeys.length > 0) log?.(`feishu: post message contains ${mediaKeys.length} embedded media file(s)`);
236
+ for (const imageKey of imageKeys) try {
237
+ const result = await downloadMessageResourceFeishu({
238
+ cfg,
239
+ messageId,
240
+ fileKey: imageKey,
241
+ type: "image",
242
+ accountId
243
+ });
244
+ const contentType = result.contentType ?? await core.media.detectMime({ buffer: result.buffer });
245
+ const saved = await core.channel.media.saveMediaBuffer(result.buffer, contentType, "inbound", maxBytes);
246
+ out.push({
247
+ path: saved.path,
248
+ contentType: saved.contentType,
249
+ placeholder: "<media:image>"
250
+ });
251
+ log?.(`feishu: downloaded embedded image ${imageKey}, saved to ${saved.path}`);
252
+ } catch (err) {
253
+ log?.(`feishu: failed to download embedded image ${imageKey}: ${String(err)}`);
254
+ }
255
+ for (const media of mediaKeys) try {
256
+ const result = await downloadMessageResourceFeishu({
257
+ cfg,
258
+ messageId,
259
+ fileKey: media.fileKey,
260
+ type: "file",
261
+ accountId
262
+ });
263
+ const contentType = result.contentType ?? await core.media.detectMime({ buffer: result.buffer });
264
+ const saved = await core.channel.media.saveMediaBuffer(result.buffer, contentType, "inbound", maxBytes);
265
+ out.push({
266
+ path: saved.path,
267
+ contentType: saved.contentType,
268
+ placeholder: "<media:video>"
269
+ });
270
+ log?.(`feishu: downloaded embedded media ${media.fileKey}, saved to ${saved.path}`);
271
+ } catch (err) {
272
+ log?.(`feishu: failed to download embedded media ${media.fileKey}: ${String(err)}`);
273
+ }
274
+ return out;
275
+ }
276
+ const mediaKeys = parseMediaKeys(content, messageType);
277
+ if (!mediaKeys.imageKey && !mediaKeys.fileKey) return [];
278
+ try {
279
+ const fileKey = mediaKeys.fileKey || mediaKeys.imageKey;
280
+ if (!fileKey) return [];
281
+ const result = await downloadMessageResourceFeishu({
282
+ cfg,
283
+ messageId,
284
+ fileKey,
285
+ type: toMessageResourceType(messageType),
286
+ accountId
287
+ });
288
+ const contentType = result.contentType ?? await core.media.detectMime({ buffer: result.buffer });
289
+ const saved = await core.channel.media.saveMediaBuffer(result.buffer, contentType, "inbound", maxBytes, result.fileName || mediaKeys.fileName);
290
+ out.push({
291
+ path: saved.path,
292
+ contentType: saved.contentType,
293
+ placeholder: inferPlaceholder(messageType)
294
+ });
295
+ log?.(`feishu: downloaded ${messageType} media, saved to ${saved.path}`);
296
+ } catch (err) {
297
+ log?.(`feishu: failed to download ${messageType} media: ${String(err)}`);
298
+ }
299
+ return out;
300
+ }
301
+ //#endregion
302
+ //#region extensions/feishu/src/bot-sender-name.ts
303
+ const IGNORED_PERMISSION_SCOPE_TOKENS = ["contact:contact.base:readonly"];
304
+ const FEISHU_SCOPE_CORRECTIONS = { "contact:contact.base:readonly": "contact:user.base:readonly" };
305
+ const SENDER_NAME_TTL_MS = 600 * 1e3;
306
+ const senderNameCache = /* @__PURE__ */ new Map();
307
+ function correctFeishuScopeInUrl(url) {
308
+ let corrected = url;
309
+ for (const [wrong, right] of Object.entries(FEISHU_SCOPE_CORRECTIONS)) {
310
+ corrected = corrected.replaceAll(encodeURIComponent(wrong), encodeURIComponent(right));
311
+ corrected = corrected.replaceAll(wrong, right);
312
+ }
313
+ return corrected;
314
+ }
315
+ function shouldSuppressPermissionErrorNotice(permissionError) {
316
+ const message = permissionError.message.toLowerCase();
317
+ return IGNORED_PERMISSION_SCOPE_TOKENS.some((token) => message.includes(token));
318
+ }
319
+ function extractPermissionError(err) {
320
+ if (!err || typeof err !== "object") return null;
321
+ const data = err.response?.data;
322
+ if (!data || typeof data !== "object") return null;
323
+ const feishuErr = data;
324
+ if (feishuErr.code !== 99991672) return null;
325
+ const msg = feishuErr.msg ?? "";
326
+ const urlMatch = msg.match(/https:\/\/[^\s,]+\/app\/[^\s,]+/);
327
+ return {
328
+ code: feishuErr.code,
329
+ message: msg,
330
+ grantUrl: urlMatch?.[0] ? correctFeishuScopeInUrl(urlMatch[0]) : void 0
331
+ };
332
+ }
333
+ function resolveSenderLookupIdType(senderId) {
334
+ const trimmed = senderId.trim();
335
+ if (trimmed.startsWith("ou_")) return "open_id";
336
+ if (trimmed.startsWith("on_")) return "union_id";
337
+ return "user_id";
338
+ }
339
+ async function resolveFeishuSenderName(params) {
340
+ const { account, senderId, log } = params;
341
+ if (!account.configured) return {};
342
+ const normalizedSenderId = senderId.trim();
343
+ if (!normalizedSenderId) return {};
344
+ const cached = senderNameCache.get(normalizedSenderId);
345
+ const now = Date.now();
346
+ if (cached && cached.expireAt > now) return { name: cached.name };
347
+ try {
348
+ const client = createFeishuClient(account);
349
+ const userIdType = resolveSenderLookupIdType(normalizedSenderId);
350
+ const res = await client.contact.user.get({
351
+ path: { user_id: normalizedSenderId },
352
+ params: { user_id_type: userIdType }
353
+ });
354
+ const name = res?.data?.user?.name || res?.data?.user?.display_name || res?.data?.user?.nickname || res?.data?.user?.en_name;
355
+ if (name && typeof name === "string") {
356
+ senderNameCache.set(normalizedSenderId, {
357
+ name,
358
+ expireAt: now + SENDER_NAME_TTL_MS
359
+ });
360
+ return { name };
361
+ }
362
+ return {};
363
+ } catch (err) {
364
+ const permErr = extractPermissionError(err);
365
+ if (permErr) {
366
+ if (shouldSuppressPermissionErrorNotice(permErr)) {
367
+ log(`feishu: ignoring stale permission scope error: ${permErr.message}`);
368
+ return {};
369
+ }
370
+ log(`feishu: permission error resolving sender name: code=${permErr.code}`);
371
+ return { permissionError: permErr };
372
+ }
373
+ log(`feishu: failed to resolve sender name for ${normalizedSenderId}: ${String(err)}`);
374
+ return {};
375
+ }
376
+ }
377
+ //#endregion
378
+ //#region extensions/feishu/src/dedup.ts
379
+ const DEDUP_TTL_MS = 1440 * 60 * 1e3;
380
+ const MEMORY_MAX_SIZE = 1e3;
381
+ const FILE_MAX_ENTRIES = 1e4;
382
+ const EVENT_DEDUP_TTL_MS = 300 * 1e3;
383
+ const EVENT_MEMORY_MAX_SIZE = 2e3;
384
+ const memoryDedupe = createDedupeCache({
385
+ ttlMs: DEDUP_TTL_MS,
386
+ maxSize: MEMORY_MAX_SIZE
387
+ });
388
+ const processingClaims = createDedupeCache({
389
+ ttlMs: EVENT_DEDUP_TTL_MS,
390
+ maxSize: EVENT_MEMORY_MAX_SIZE
391
+ });
392
+ function resolveStateDirFromEnv(env = process.env) {
393
+ const stateOverride = env.OPENCLAW_STATE_DIR?.trim() || env.CLAWDBOT_STATE_DIR?.trim();
394
+ if (stateOverride) return stateOverride;
395
+ if (env.VITEST || env.NODE_ENV === "test") return path.join(os.tmpdir(), ["openclaw-vitest", String(process.pid)].join("-"));
396
+ return path.join(os.homedir(), ".openclaw");
397
+ }
398
+ function resolveNamespaceFilePath(namespace) {
399
+ const safe = namespace.replace(/[^a-zA-Z0-9_-]/g, "_");
400
+ return path.join(resolveStateDirFromEnv(), "feishu", "dedup", `${safe}.json`);
401
+ }
402
+ const persistentDedupe = createPersistentDedupe({
403
+ ttlMs: DEDUP_TTL_MS,
404
+ memoryMaxSize: MEMORY_MAX_SIZE,
405
+ fileMaxEntries: FILE_MAX_ENTRIES,
406
+ resolveFilePath: resolveNamespaceFilePath
407
+ });
408
+ function resolveEventDedupeKey(namespace, messageId) {
409
+ const trimmed = messageId?.trim();
410
+ if (!trimmed) return null;
411
+ return `${namespace}:${trimmed}`;
412
+ }
413
+ function normalizeMessageId(messageId) {
414
+ const trimmed = messageId?.trim();
415
+ return trimmed ? trimmed : null;
416
+ }
417
+ function resolveMemoryDedupeKey(namespace, messageId) {
418
+ const trimmed = normalizeMessageId(messageId);
419
+ if (!trimmed) return null;
420
+ return `${namespace}:${trimmed}`;
421
+ }
422
+ function tryBeginFeishuMessageProcessing(messageId, namespace = "global") {
423
+ return !processingClaims.check(resolveEventDedupeKey(namespace, messageId));
424
+ }
425
+ function releaseFeishuMessageProcessing(messageId, namespace = "global") {
426
+ processingClaims.delete(resolveEventDedupeKey(namespace, messageId));
427
+ }
428
+ async function finalizeFeishuMessageProcessing(params) {
429
+ const { messageId, namespace = "global", log, claimHeld = false } = params;
430
+ const normalizedMessageId = normalizeMessageId(messageId);
431
+ const memoryKey = resolveMemoryDedupeKey(namespace, messageId);
432
+ if (!memoryKey || !normalizedMessageId) return false;
433
+ if (!claimHeld && !tryBeginFeishuMessageProcessing(normalizedMessageId, namespace)) return false;
434
+ if (!tryRecordMessage(memoryKey)) {
435
+ releaseFeishuMessageProcessing(normalizedMessageId, namespace);
436
+ return false;
437
+ }
438
+ if (!await tryRecordMessagePersistent(normalizedMessageId, namespace, log)) {
439
+ releaseFeishuMessageProcessing(normalizedMessageId, namespace);
440
+ return false;
441
+ }
442
+ return true;
443
+ }
444
+ async function recordProcessedFeishuMessage(messageId, namespace = "global", log) {
445
+ const normalizedMessageId = normalizeMessageId(messageId);
446
+ const memoryKey = resolveMemoryDedupeKey(namespace, messageId);
447
+ if (!memoryKey || !normalizedMessageId) return false;
448
+ tryRecordMessage(memoryKey);
449
+ return await tryRecordMessagePersistent(normalizedMessageId, namespace, log);
450
+ }
451
+ async function hasProcessedFeishuMessage(messageId, namespace = "global", log) {
452
+ const normalizedMessageId = normalizeMessageId(messageId);
453
+ const memoryKey = resolveMemoryDedupeKey(namespace, messageId);
454
+ if (!memoryKey || !normalizedMessageId) return false;
455
+ if (hasRecordedMessage(memoryKey)) return true;
456
+ return hasRecordedMessagePersistent(normalizedMessageId, namespace, log);
457
+ }
458
+ /**
459
+ * Synchronous dedup — memory only.
460
+ * Kept for backward compatibility; prefer {@link tryRecordMessagePersistent}.
461
+ */
462
+ function tryRecordMessage(messageId) {
463
+ return !memoryDedupe.check(messageId);
464
+ }
465
+ function hasRecordedMessage(messageId) {
466
+ const trimmed = messageId.trim();
467
+ if (!trimmed) return false;
468
+ return memoryDedupe.peek(trimmed);
469
+ }
470
+ async function tryRecordMessagePersistent(messageId, namespace = "global", log) {
471
+ return persistentDedupe.checkAndRecord(messageId, {
472
+ namespace,
473
+ onDiskError: (error) => {
474
+ log?.(`feishu-dedup: disk error, falling back to memory: ${String(error)}`);
475
+ }
476
+ });
477
+ }
478
+ async function hasRecordedMessagePersistent(messageId, namespace = "global", log) {
479
+ const trimmed = messageId.trim();
480
+ if (!trimmed) return false;
481
+ const now = Date.now();
482
+ const filePath = resolveNamespaceFilePath(namespace);
483
+ try {
484
+ const { value } = await readJsonFileWithFallback(filePath, {});
485
+ const seenAt = value[trimmed];
486
+ if (typeof seenAt !== "number" || !Number.isFinite(seenAt)) return false;
487
+ return DEDUP_TTL_MS <= 0 || now - seenAt < DEDUP_TTL_MS;
488
+ } catch (error) {
489
+ log?.(`feishu-dedup: persistent peek failed: ${String(error)}`);
490
+ return false;
491
+ }
492
+ }
493
+ async function warmupDedupFromDisk(namespace, log) {
494
+ return persistentDedupe.warmup(namespace, (error) => {
495
+ log?.(`feishu-dedup: warmup disk error: ${String(error)}`);
496
+ });
497
+ }
498
+ //#endregion
499
+ //#region extensions/feishu/src/dynamic-agent.ts
500
+ /**
501
+ * Check if a dynamic agent should be created for a DM user and create it if needed.
502
+ * This creates a unique agent instance with its own workspace for each DM user.
503
+ */
504
+ async function maybeCreateDynamicAgent(params) {
505
+ const { cfg, runtime, senderOpenId, dynamicCfg, log } = params;
506
+ const existingBindings = cfg.bindings ?? [];
507
+ if (existingBindings.some((b) => b.match?.channel === "feishu" && b.match?.peer?.kind === "direct" && b.match?.peer?.id === senderOpenId)) return {
508
+ created: false,
509
+ updatedCfg: cfg
510
+ };
511
+ if (dynamicCfg.maxAgents !== void 0) {
512
+ if ((cfg.agents?.list ?? []).filter((a) => a.id.startsWith("feishu-")).length >= dynamicCfg.maxAgents) {
513
+ log(`feishu: maxAgents limit (${dynamicCfg.maxAgents}) reached, not creating agent for ${senderOpenId}`);
514
+ return {
515
+ created: false,
516
+ updatedCfg: cfg
517
+ };
518
+ }
519
+ }
520
+ const agentId = `feishu-${senderOpenId}`;
521
+ if ((cfg.agents?.list ?? []).find((a) => a.id === agentId)) {
522
+ log(`feishu: agent "${agentId}" exists, adding missing binding for ${senderOpenId}`);
523
+ const updatedCfg = {
524
+ ...cfg,
525
+ bindings: [...existingBindings, {
526
+ agentId,
527
+ match: {
528
+ channel: "feishu",
529
+ peer: {
530
+ kind: "direct",
531
+ id: senderOpenId
532
+ }
533
+ }
534
+ }]
535
+ };
536
+ await runtime.config.writeConfigFile(updatedCfg);
537
+ return {
538
+ created: true,
539
+ updatedCfg,
540
+ agentId
541
+ };
542
+ }
543
+ const workspaceTemplate = dynamicCfg.workspaceTemplate ?? "~/.openclaw/workspace-{agentId}";
544
+ const agentDirTemplate = dynamicCfg.agentDirTemplate ?? "~/.openclaw/agents/{agentId}/agent";
545
+ const workspace = resolveUserPath(workspaceTemplate.replace("{userId}", senderOpenId).replace("{agentId}", agentId));
546
+ const agentDir = resolveUserPath(agentDirTemplate.replace("{userId}", senderOpenId).replace("{agentId}", agentId));
547
+ log(`feishu: creating dynamic agent "${agentId}" for user ${senderOpenId}`);
548
+ log(` workspace: ${workspace}`);
549
+ log(` agentDir: ${agentDir}`);
550
+ await fs.promises.mkdir(workspace, { recursive: true });
551
+ await fs.promises.mkdir(agentDir, { recursive: true });
552
+ const updatedCfg = {
553
+ ...cfg,
554
+ agents: {
555
+ ...cfg.agents,
556
+ list: [...cfg.agents?.list ?? [], {
557
+ id: agentId,
558
+ workspace,
559
+ agentDir
560
+ }]
561
+ },
562
+ bindings: [...existingBindings, {
563
+ agentId,
564
+ match: {
565
+ channel: "feishu",
566
+ peer: {
567
+ kind: "direct",
568
+ id: senderOpenId
569
+ }
570
+ }
571
+ }]
572
+ };
573
+ await runtime.config.writeConfigFile(updatedCfg);
574
+ return {
575
+ created: true,
576
+ updatedCfg,
577
+ agentId
578
+ };
579
+ }
580
+ /**
581
+ * Resolve a path that may start with ~ to the user's home directory.
582
+ */
583
+ function resolveUserPath(p) {
584
+ if (p.startsWith("~/")) return path.join(os.homedir(), p.slice(2));
585
+ return p;
586
+ }
587
+ //#endregion
588
+ //#region extensions/feishu/src/streaming-card.ts
589
+ const tokenCache = /* @__PURE__ */ new Map();
590
+ function resolveApiBase(domain) {
591
+ if (domain === "lark") return "https://open.larksuite.com/open-apis";
592
+ if (domain && domain !== "feishu" && domain.startsWith("http")) return `${domain.replace(/\/+$/, "")}/open-apis`;
593
+ return "https://open.feishu.cn/open-apis";
594
+ }
595
+ function resolveAllowedHostnames(domain) {
596
+ if (domain === "lark") return ["open.larksuite.com"];
597
+ if (domain && domain !== "feishu" && domain.startsWith("http")) try {
598
+ return [new URL(domain).hostname];
599
+ } catch {
600
+ return [];
601
+ }
602
+ return ["open.feishu.cn"];
603
+ }
604
+ async function getToken(creds) {
605
+ const key = `${creds.domain ?? "feishu"}|${creds.appId}`;
606
+ const cached = tokenCache.get(key);
607
+ if (cached && cached.expiresAt > Date.now() + 6e4) return cached.token;
608
+ const { response, release } = await fetchWithSsrFGuard({
609
+ url: `${resolveApiBase(creds.domain)}/auth/v3/tenant_access_token/internal`,
610
+ init: {
611
+ method: "POST",
612
+ headers: { "Content-Type": "application/json" },
613
+ body: JSON.stringify({
614
+ app_id: creds.appId,
615
+ app_secret: creds.appSecret
616
+ })
617
+ },
618
+ policy: { allowedHostnames: resolveAllowedHostnames(creds.domain) },
619
+ auditContext: "feishu.streaming-card.token"
620
+ });
621
+ if (!response.ok) {
622
+ await release();
623
+ throw new Error(`Token request failed with HTTP ${response.status}`);
624
+ }
625
+ const data = await response.json();
626
+ await release();
627
+ if (data.code !== 0 || !data.tenant_access_token) throw new Error(`Token error: ${data.msg}`);
628
+ tokenCache.set(key, {
629
+ token: data.tenant_access_token,
630
+ expiresAt: Date.now() + (data.expire ?? 7200) * 1e3
631
+ });
632
+ return data.tenant_access_token;
633
+ }
634
+ function truncateSummary(text, max = 50) {
635
+ if (!text) return "";
636
+ const clean = text.replace(/\n/g, " ").trim();
637
+ return clean.length <= max ? clean : clean.slice(0, max - 3) + "...";
638
+ }
639
+ function mergeStreamingText(previousText, nextText) {
640
+ const previous = typeof previousText === "string" ? previousText : "";
641
+ const next = typeof nextText === "string" ? nextText : "";
642
+ if (!next) return previous;
643
+ if (!previous || next === previous) return next;
644
+ if (next.startsWith(previous)) return next;
645
+ if (previous.startsWith(next)) return previous;
646
+ if (next.includes(previous)) return next;
647
+ if (previous.includes(next)) return previous;
648
+ const maxOverlap = Math.min(previous.length, next.length);
649
+ for (let overlap = maxOverlap; overlap > 0; overlap -= 1) if (previous.slice(-overlap) === next.slice(0, overlap)) return `${previous}${next.slice(overlap)}`;
650
+ return `${previous}${next}`;
651
+ }
652
+ function resolveStreamingCardSendMode(options) {
653
+ if (options?.replyToMessageId) return "reply";
654
+ if (options?.rootId) return "root_create";
655
+ return "create";
656
+ }
657
+ /** Streaming card session manager */
658
+ var FeishuStreamingSession = class {
659
+ constructor(client, creds, log) {
660
+ this.state = null;
661
+ this.queue = Promise.resolve();
662
+ this.closed = false;
663
+ this.lastUpdateTime = 0;
664
+ this.pendingText = null;
665
+ this.flushTimer = null;
666
+ this.updateThrottleMs = 100;
667
+ this.client = client;
668
+ this.creds = creds;
669
+ this.log = log;
670
+ }
671
+ async start(receiveId, receiveIdType = "chat_id", options) {
672
+ if (this.state) return;
673
+ const apiBase = resolveApiBase(this.creds.domain);
674
+ const elements = [{
675
+ tag: "markdown",
676
+ content: "⏳ Thinking...",
677
+ element_id: "content"
678
+ }];
679
+ if (options?.note) {
680
+ elements.push({ tag: "hr" });
681
+ elements.push({
682
+ tag: "markdown",
683
+ content: `<font color='grey'>${options.note}</font>`,
684
+ element_id: "note"
685
+ });
686
+ }
687
+ const cardJson = {
688
+ schema: "2.0",
689
+ config: {
690
+ streaming_mode: true,
691
+ summary: { content: "[Generating...]" },
692
+ streaming_config: {
693
+ print_frequency_ms: { default: 50 },
694
+ print_step: { default: 1 }
695
+ }
696
+ },
697
+ body: { elements }
698
+ };
699
+ if (options?.header) cardJson.header = {
700
+ title: {
701
+ tag: "plain_text",
702
+ content: options.header.title
703
+ },
704
+ template: resolveFeishuCardTemplate(options.header.template) ?? "blue"
705
+ };
706
+ const { response: createRes, release: releaseCreate } = await fetchWithSsrFGuard({
707
+ url: `${apiBase}/cardkit/v1/cards`,
708
+ init: {
709
+ method: "POST",
710
+ headers: {
711
+ Authorization: `Bearer ${await getToken(this.creds)}`,
712
+ "Content-Type": "application/json"
713
+ },
714
+ body: JSON.stringify({
715
+ type: "card_json",
716
+ data: JSON.stringify(cardJson)
717
+ })
718
+ },
719
+ policy: { allowedHostnames: resolveAllowedHostnames(this.creds.domain) },
720
+ auditContext: "feishu.streaming-card.create"
721
+ });
722
+ if (!createRes.ok) {
723
+ await releaseCreate();
724
+ throw new Error(`Create card request failed with HTTP ${createRes.status}`);
725
+ }
726
+ const createData = await createRes.json();
727
+ await releaseCreate();
728
+ if (createData.code !== 0 || !createData.data?.card_id) throw new Error(`Create card failed: ${createData.msg}`);
729
+ const cardId = createData.data.card_id;
730
+ const cardContent = JSON.stringify({
731
+ type: "card",
732
+ data: { card_id: cardId }
733
+ });
734
+ let sendRes;
735
+ const sendOptions = options ?? {};
736
+ const sendMode = resolveStreamingCardSendMode(sendOptions);
737
+ if (sendMode === "reply") sendRes = await this.client.im.message.reply({
738
+ path: { message_id: sendOptions.replyToMessageId },
739
+ data: {
740
+ msg_type: "interactive",
741
+ content: cardContent,
742
+ ...sendOptions.replyInThread ? { reply_in_thread: true } : {}
743
+ }
744
+ });
745
+ else if (sendMode === "root_create") sendRes = await this.client.im.message.create({
746
+ params: { receive_id_type: receiveIdType },
747
+ data: Object.assign({
748
+ receive_id: receiveId,
749
+ msg_type: "interactive",
750
+ content: cardContent
751
+ }, { root_id: sendOptions.rootId })
752
+ });
753
+ else sendRes = await this.client.im.message.create({
754
+ params: { receive_id_type: receiveIdType },
755
+ data: {
756
+ receive_id: receiveId,
757
+ msg_type: "interactive",
758
+ content: cardContent
759
+ }
760
+ });
761
+ if (sendRes.code !== 0 || !sendRes.data?.message_id) throw new Error(`Send card failed: ${sendRes.msg}`);
762
+ this.state = {
763
+ cardId,
764
+ messageId: sendRes.data.message_id,
765
+ sequence: 1,
766
+ currentText: "",
767
+ hasNote: !!options?.note
768
+ };
769
+ this.log?.(`Started streaming: cardId=${cardId}, messageId=${sendRes.data.message_id}`);
770
+ }
771
+ async updateCardContent(text, onError) {
772
+ if (!this.state) return;
773
+ const apiBase = resolveApiBase(this.creds.domain);
774
+ this.state.sequence += 1;
775
+ await fetchWithSsrFGuard({
776
+ url: `${apiBase}/cardkit/v1/cards/${this.state.cardId}/elements/content/content`,
777
+ init: {
778
+ method: "PUT",
779
+ headers: {
780
+ Authorization: `Bearer ${await getToken(this.creds)}`,
781
+ "Content-Type": "application/json"
782
+ },
783
+ body: JSON.stringify({
784
+ content: text,
785
+ sequence: this.state.sequence,
786
+ uuid: `s_${this.state.cardId}_${this.state.sequence}`
787
+ })
788
+ },
789
+ policy: { allowedHostnames: resolveAllowedHostnames(this.creds.domain) },
790
+ auditContext: "feishu.streaming-card.update"
791
+ }).then(async ({ release }) => {
792
+ await release();
793
+ }).catch((error) => onError?.(error));
794
+ }
795
+ async update(text) {
796
+ if (!this.state || this.closed) return;
797
+ const mergedInput = mergeStreamingText(this.pendingText ?? this.state.currentText, text);
798
+ if (!mergedInput || mergedInput === this.state.currentText) return;
799
+ const now = Date.now();
800
+ if (now - this.lastUpdateTime < this.updateThrottleMs) {
801
+ this.pendingText = mergedInput;
802
+ return;
803
+ }
804
+ this.pendingText = null;
805
+ this.lastUpdateTime = now;
806
+ if (this.flushTimer) {
807
+ clearTimeout(this.flushTimer);
808
+ this.flushTimer = null;
809
+ }
810
+ this.queue = this.queue.then(async () => {
811
+ if (!this.state || this.closed) return;
812
+ const mergedText = mergeStreamingText(this.state.currentText, mergedInput);
813
+ if (!mergedText || mergedText === this.state.currentText) return;
814
+ this.state.currentText = mergedText;
815
+ await this.updateCardContent(mergedText, (e) => this.log?.(`Update failed: ${String(e)}`));
816
+ });
817
+ await this.queue;
818
+ }
819
+ async updateNoteContent(note) {
820
+ if (!this.state || !this.state.hasNote) return;
821
+ const apiBase = resolveApiBase(this.creds.domain);
822
+ this.state.sequence += 1;
823
+ await fetchWithSsrFGuard({
824
+ url: `${apiBase}/cardkit/v1/cards/${this.state.cardId}/elements/note/content`,
825
+ init: {
826
+ method: "PUT",
827
+ headers: {
828
+ Authorization: `Bearer ${await getToken(this.creds)}`,
829
+ "Content-Type": "application/json"
830
+ },
831
+ body: JSON.stringify({
832
+ content: `<font color='grey'>${note}</font>`,
833
+ sequence: this.state.sequence,
834
+ uuid: `n_${this.state.cardId}_${this.state.sequence}`
835
+ })
836
+ },
837
+ policy: { allowedHostnames: resolveAllowedHostnames(this.creds.domain) },
838
+ auditContext: "feishu.streaming-card.note-update"
839
+ }).then(async ({ release }) => {
840
+ await release();
841
+ }).catch((e) => this.log?.(`Note update failed: ${String(e)}`));
842
+ }
843
+ async close(finalText, options) {
844
+ if (!this.state || this.closed) return;
845
+ this.closed = true;
846
+ if (this.flushTimer) {
847
+ clearTimeout(this.flushTimer);
848
+ this.flushTimer = null;
849
+ }
850
+ await this.queue;
851
+ const pendingMerged = mergeStreamingText(this.state.currentText, this.pendingText ?? void 0);
852
+ const text = finalText ? mergeStreamingText(pendingMerged, finalText) : pendingMerged;
853
+ const apiBase = resolveApiBase(this.creds.domain);
854
+ if (text && text !== this.state.currentText) {
855
+ await this.updateCardContent(text);
856
+ this.state.currentText = text;
857
+ }
858
+ if (options?.note) await this.updateNoteContent(options.note);
859
+ this.state.sequence += 1;
860
+ await fetchWithSsrFGuard({
861
+ url: `${apiBase}/cardkit/v1/cards/${this.state.cardId}/settings`,
862
+ init: {
863
+ method: "PATCH",
864
+ headers: {
865
+ Authorization: `Bearer ${await getToken(this.creds)}`,
866
+ "Content-Type": "application/json; charset=utf-8"
867
+ },
868
+ body: JSON.stringify({
869
+ settings: JSON.stringify({ config: {
870
+ streaming_mode: false,
871
+ summary: { content: truncateSummary(text) }
872
+ } }),
873
+ sequence: this.state.sequence,
874
+ uuid: `c_${this.state.cardId}_${this.state.sequence}`
875
+ })
876
+ },
877
+ policy: { allowedHostnames: resolveAllowedHostnames(this.creds.domain) },
878
+ auditContext: "feishu.streaming-card.close"
879
+ }).then(async ({ release }) => {
880
+ await release();
881
+ }).catch((e) => this.log?.(`Close failed: ${String(e)}`));
882
+ const finalState = this.state;
883
+ this.state = null;
884
+ this.pendingText = null;
885
+ this.log?.(`Closed streaming: cardId=${finalState.cardId}`);
886
+ }
887
+ isActive() {
888
+ return this.state !== null && !this.closed;
889
+ }
890
+ };
891
+ //#endregion
892
+ //#region extensions/feishu/src/typing.ts
893
+ const TYPING_EMOJI = "Typing";
894
+ /**
895
+ * Feishu API error codes that indicate the caller should back off.
896
+ * These must propagate to the typing circuit breaker so the keepalive loop
897
+ * can trip and stop retrying.
898
+ *
899
+ * - 99991400: Rate limit (too many requests per second)
900
+ * - 99991403: Monthly API call quota exceeded
901
+ * - 429: Standard HTTP 429 returned as a Feishu SDK error code
902
+ *
903
+ * @see https://open.feishu.cn/document/server-docs/api-call-guide/generic-error-code
904
+ */
905
+ const FEISHU_BACKOFF_CODES = new Set([
906
+ 99991400,
907
+ 99991403,
908
+ 429
909
+ ]);
910
+ /**
911
+ * Custom error class for Feishu backoff conditions detected from non-throwing
912
+ * SDK responses. Carries a numeric `.code` so that `isFeishuBackoffError()`
913
+ * recognises it when the error is caught downstream.
914
+ */
915
+ var FeishuBackoffError = class extends Error {
916
+ constructor(code) {
917
+ super(`Feishu API backoff: code ${code}`);
918
+ this.name = "FeishuBackoffError";
919
+ this.code = code;
920
+ }
921
+ };
922
+ /**
923
+ * Check whether an error represents a rate-limit or quota-exceeded condition
924
+ * from the Feishu API that should stop the typing keepalive loop.
925
+ *
926
+ * Handles two shapes:
927
+ * 1. AxiosError with `response.status` and `response.data.code`
928
+ * 2. Feishu SDK error with a top-level `code` property
929
+ */
930
+ function isFeishuBackoffError(err) {
931
+ if (typeof err !== "object" || err === null) return false;
932
+ const response = err.response;
933
+ if (response) {
934
+ if (response.status === 429) return true;
935
+ if (typeof response.data?.code === "number" && FEISHU_BACKOFF_CODES.has(response.data.code)) return true;
936
+ }
937
+ const code = err.code;
938
+ if (typeof code === "number" && FEISHU_BACKOFF_CODES.has(code)) return true;
939
+ return false;
940
+ }
941
+ /**
942
+ * Check whether a Feishu SDK response object contains a backoff error code.
943
+ *
944
+ * The Feishu SDK sometimes returns a normal response (no throw) with an
945
+ * API-level error code in the response body. This must be detected so the
946
+ * circuit breaker can trip. See codex review on #28157.
947
+ */
948
+ function getBackoffCodeFromResponse(response) {
949
+ if (typeof response !== "object" || response === null) return;
950
+ const code = response.code;
951
+ if (typeof code === "number" && FEISHU_BACKOFF_CODES.has(code)) return code;
952
+ }
953
+ /**
954
+ * Add a typing indicator (reaction) to a message.
955
+ *
956
+ * Rate-limit and quota errors are re-thrown so the circuit breaker in
957
+ * `createTypingCallbacks` (typing-start-guard) can trip and stop the
958
+ * keepalive loop. See #28062.
959
+ *
960
+ * Also checks for backoff codes in non-throwing SDK responses (#28157).
961
+ */
962
+ async function addTypingIndicator(params) {
963
+ const { cfg, messageId, accountId, runtime } = params;
964
+ const account = resolveFeishuAccount({
965
+ cfg,
966
+ accountId
967
+ });
968
+ if (!account.configured) return {
969
+ messageId,
970
+ reactionId: null
971
+ };
972
+ const client = createFeishuClient(account);
973
+ try {
974
+ const response = await client.im.messageReaction.create({
975
+ path: { message_id: messageId },
976
+ data: { reaction_type: { emoji_type: TYPING_EMOJI } }
977
+ });
978
+ const backoffCode = getBackoffCodeFromResponse(response);
979
+ if (backoffCode !== void 0) {
980
+ if (getFeishuRuntime().logging.shouldLogVerbose()) runtime?.log?.(`[feishu] typing indicator response contains backoff code ${backoffCode}, stopping keepalive`);
981
+ throw new FeishuBackoffError(backoffCode);
982
+ }
983
+ return {
984
+ messageId,
985
+ reactionId: response?.data?.reaction_id ?? null
986
+ };
987
+ } catch (err) {
988
+ if (isFeishuBackoffError(err)) {
989
+ if (getFeishuRuntime().logging.shouldLogVerbose()) runtime?.log?.("[feishu] typing indicator hit rate-limit/quota, stopping keepalive");
990
+ throw err;
991
+ }
992
+ if (getFeishuRuntime().logging.shouldLogVerbose()) runtime?.log?.(`[feishu] failed to add typing indicator: ${String(err)}`);
993
+ return {
994
+ messageId,
995
+ reactionId: null
996
+ };
997
+ }
998
+ }
999
+ /**
1000
+ * Remove a typing indicator (reaction) from a message.
1001
+ *
1002
+ * Rate-limit and quota errors are re-thrown for the same reason as above.
1003
+ */
1004
+ async function removeTypingIndicator(params) {
1005
+ const { cfg, state, accountId, runtime } = params;
1006
+ if (!state.reactionId) return;
1007
+ const account = resolveFeishuAccount({
1008
+ cfg,
1009
+ accountId
1010
+ });
1011
+ if (!account.configured) return;
1012
+ const client = createFeishuClient(account);
1013
+ try {
1014
+ const backoffCode = getBackoffCodeFromResponse(await client.im.messageReaction.delete({ path: {
1015
+ message_id: state.messageId,
1016
+ reaction_id: state.reactionId
1017
+ } }));
1018
+ if (backoffCode !== void 0) {
1019
+ if (getFeishuRuntime().logging.shouldLogVerbose()) runtime?.log?.(`[feishu] typing indicator removal response contains backoff code ${backoffCode}, stopping keepalive`);
1020
+ throw new FeishuBackoffError(backoffCode);
1021
+ }
1022
+ } catch (err) {
1023
+ if (isFeishuBackoffError(err)) {
1024
+ if (getFeishuRuntime().logging.shouldLogVerbose()) runtime?.log?.("[feishu] typing indicator removal hit rate-limit/quota, stopping keepalive");
1025
+ throw err;
1026
+ }
1027
+ if (getFeishuRuntime().logging.shouldLogVerbose()) runtime?.log?.(`[feishu] failed to remove typing indicator: ${String(err)}`);
1028
+ }
1029
+ }
1030
+ //#endregion
1031
+ //#region extensions/feishu/src/reply-dispatcher.ts
1032
+ /** Detect if text contains markdown elements that benefit from card rendering */
1033
+ function shouldUseCard(text) {
1034
+ return /```[\s\S]*?```/.test(text) || /\|.+\|[\r\n]+\|[-:| ]+\|/.test(text);
1035
+ }
1036
+ /** Maximum age (ms) for a message to receive a typing indicator reaction.
1037
+ * Messages older than this are likely replays after context compaction (#30418). */
1038
+ const TYPING_INDICATOR_MAX_AGE_MS = 2 * 6e4;
1039
+ const MS_EPOCH_MIN = 0xe8d4a51000;
1040
+ function normalizeEpochMs(timestamp) {
1041
+ if (!Number.isFinite(timestamp) || timestamp === void 0 || timestamp <= 0) return;
1042
+ return timestamp < MS_EPOCH_MIN ? timestamp * 1e3 : timestamp;
1043
+ }
1044
+ /** Build a card header from agent identity config. */
1045
+ function resolveCardHeader(agentId, identity) {
1046
+ const name = identity?.name?.trim() || agentId;
1047
+ const emoji = identity?.emoji?.trim();
1048
+ return {
1049
+ title: emoji ? `${emoji} ${name}` : name,
1050
+ template: identity?.theme ?? "blue"
1051
+ };
1052
+ }
1053
+ /** Build a card note footer from agent identity and model context. */
1054
+ function resolveCardNote(agentId, identity, prefixCtx) {
1055
+ const parts = [`Agent: ${identity?.name?.trim() || agentId}`];
1056
+ if (prefixCtx.model) parts.push(`Model: ${prefixCtx.model}`);
1057
+ if (prefixCtx.provider) parts.push(`Provider: ${prefixCtx.provider}`);
1058
+ return parts.join(" | ");
1059
+ }
1060
+ function createFeishuReplyDispatcher(params) {
1061
+ const core = getFeishuRuntime();
1062
+ const { cfg, agentId, chatId, replyToMessageId, skipReplyToInMessages, replyInThread, threadReply, rootId, mentionTargets, accountId, identity } = params;
1063
+ const sendReplyToMessageId = skipReplyToInMessages ? void 0 : replyToMessageId;
1064
+ const threadReplyMode = threadReply === true;
1065
+ const effectiveReplyInThread = threadReplyMode ? true : replyInThread;
1066
+ const account = resolveFeishuAccount({
1067
+ cfg,
1068
+ accountId
1069
+ });
1070
+ const prefixContext = createReplyPrefixContext({
1071
+ cfg,
1072
+ agentId
1073
+ });
1074
+ let typingState = null;
1075
+ const { typingCallbacks } = createChannelReplyPipeline({
1076
+ cfg,
1077
+ agentId,
1078
+ channel: "feishu",
1079
+ accountId,
1080
+ typing: {
1081
+ start: async () => {
1082
+ if (!(account.config.typingIndicator ?? true)) return;
1083
+ if (!replyToMessageId) return;
1084
+ const messageCreateTimeMs = normalizeEpochMs(params.messageCreateTimeMs);
1085
+ if (messageCreateTimeMs !== void 0 && Date.now() - messageCreateTimeMs > TYPING_INDICATOR_MAX_AGE_MS) return;
1086
+ if (typingState?.reactionId) return;
1087
+ typingState = await addTypingIndicator({
1088
+ cfg,
1089
+ messageId: replyToMessageId,
1090
+ accountId,
1091
+ runtime: params.runtime
1092
+ });
1093
+ },
1094
+ stop: async () => {
1095
+ if (!typingState) return;
1096
+ await removeTypingIndicator({
1097
+ cfg,
1098
+ state: typingState,
1099
+ accountId,
1100
+ runtime: params.runtime
1101
+ });
1102
+ typingState = null;
1103
+ },
1104
+ onStartError: (err) => logTypingFailure({
1105
+ log: (message) => params.runtime.log?.(message),
1106
+ channel: "feishu",
1107
+ action: "start",
1108
+ error: err
1109
+ }),
1110
+ onStopError: (err) => logTypingFailure({
1111
+ log: (message) => params.runtime.log?.(message),
1112
+ channel: "feishu",
1113
+ action: "stop",
1114
+ error: err
1115
+ })
1116
+ }
1117
+ });
1118
+ const textChunkLimit = core.channel.text.resolveTextChunkLimit(cfg, "feishu", accountId, { fallbackLimit: 4e3 });
1119
+ const chunkMode = core.channel.text.resolveChunkMode(cfg, "feishu");
1120
+ const tableMode = core.channel.text.resolveMarkdownTableMode({
1121
+ cfg,
1122
+ channel: "feishu"
1123
+ });
1124
+ const renderMode = account.config?.renderMode ?? "auto";
1125
+ const streamingEnabled = !threadReplyMode && account.config?.streaming !== false && renderMode !== "raw";
1126
+ let streaming = null;
1127
+ let streamText = "";
1128
+ let lastPartial = "";
1129
+ let reasoningText = "";
1130
+ const deliveredFinalTexts = /* @__PURE__ */ new Set();
1131
+ let partialUpdateQueue = Promise.resolve();
1132
+ let streamingStartPromise = null;
1133
+ const formatReasoningPrefix = (thinking) => {
1134
+ if (!thinking) return "";
1135
+ return `> 💭 **Thinking**\n${thinking.replace(/^Reasoning:\n/, "").replace(/^_(.*)_$/gm, "$1").split("\n").map((line) => `> ${line}`).join("\n")}`;
1136
+ };
1137
+ const buildCombinedStreamText = (thinking, answer) => {
1138
+ const parts = [];
1139
+ if (thinking) parts.push(formatReasoningPrefix(thinking));
1140
+ if (thinking && answer) parts.push("\n\n---\n\n");
1141
+ if (answer) parts.push(answer);
1142
+ return parts.join("");
1143
+ };
1144
+ const flushStreamingCardUpdate = (combined) => {
1145
+ partialUpdateQueue = partialUpdateQueue.then(async () => {
1146
+ if (streamingStartPromise) await streamingStartPromise;
1147
+ if (streaming?.isActive()) await streaming.update(combined);
1148
+ });
1149
+ };
1150
+ const queueStreamingUpdate = (nextText, options) => {
1151
+ if (!nextText) return;
1152
+ if (options?.dedupeWithLastPartial && nextText === lastPartial) return;
1153
+ if (options?.dedupeWithLastPartial) lastPartial = nextText;
1154
+ streamText = (options?.mode ?? "snapshot") === "delta" ? `${streamText}${nextText}` : mergeStreamingText(streamText, nextText);
1155
+ flushStreamingCardUpdate(buildCombinedStreamText(reasoningText, streamText));
1156
+ };
1157
+ const queueReasoningUpdate = (nextThinking) => {
1158
+ if (!nextThinking) return;
1159
+ reasoningText = nextThinking;
1160
+ flushStreamingCardUpdate(buildCombinedStreamText(reasoningText, streamText));
1161
+ };
1162
+ const startStreaming = () => {
1163
+ if (!streamingEnabled || streamingStartPromise || streaming) return;
1164
+ streamingStartPromise = (async () => {
1165
+ const creds = account.appId && account.appSecret ? {
1166
+ appId: account.appId,
1167
+ appSecret: account.appSecret,
1168
+ domain: account.domain
1169
+ } : null;
1170
+ if (!creds) return;
1171
+ streaming = new FeishuStreamingSession(createFeishuClient(account), creds, (message) => params.runtime.log?.(`feishu[${account.accountId}] ${message}`));
1172
+ try {
1173
+ const cardHeader = resolveCardHeader(agentId, identity);
1174
+ const cardNote = resolveCardNote(agentId, identity, prefixContext.prefixContext);
1175
+ await streaming.start(chatId, resolveReceiveIdType(chatId), {
1176
+ replyToMessageId,
1177
+ replyInThread: effectiveReplyInThread,
1178
+ rootId,
1179
+ header: cardHeader,
1180
+ note: cardNote
1181
+ });
1182
+ } catch (error) {
1183
+ params.runtime.error?.(`feishu: streaming start failed: ${String(error)}`);
1184
+ streaming = null;
1185
+ streamingStartPromise = null;
1186
+ }
1187
+ })();
1188
+ };
1189
+ const closeStreaming = async () => {
1190
+ if (streamingStartPromise) await streamingStartPromise;
1191
+ await partialUpdateQueue;
1192
+ if (streaming?.isActive()) {
1193
+ let text = buildCombinedStreamText(reasoningText, streamText);
1194
+ if (mentionTargets?.length) text = buildMentionedCardContent(mentionTargets, text);
1195
+ const finalNote = resolveCardNote(agentId, identity, prefixContext.prefixContext);
1196
+ await streaming.close(text, { note: finalNote });
1197
+ }
1198
+ streaming = null;
1199
+ streamingStartPromise = null;
1200
+ streamText = "";
1201
+ lastPartial = "";
1202
+ reasoningText = "";
1203
+ };
1204
+ const sendChunkedTextReply = async (params) => {
1205
+ const chunkSource = params.useCard ? params.text : core.channel.text.convertMarkdownTables(params.text, tableMode);
1206
+ const chunks = resolveTextChunksWithFallback(chunkSource, core.channel.text.chunkTextWithMode(chunkSource, textChunkLimit, chunkMode));
1207
+ for (const [index, chunk] of chunks.entries()) await params.sendChunk({
1208
+ chunk,
1209
+ isFirst: index === 0
1210
+ });
1211
+ if (params.infoKind === "final") deliveredFinalTexts.add(params.text);
1212
+ };
1213
+ const sendMediaReplies = async (payload) => {
1214
+ await sendMediaWithLeadingCaption({
1215
+ mediaUrls: resolveSendableOutboundReplyParts(payload).mediaUrls,
1216
+ caption: "",
1217
+ send: async ({ mediaUrl }) => {
1218
+ await sendMediaFeishu({
1219
+ cfg,
1220
+ to: chatId,
1221
+ mediaUrl,
1222
+ replyToMessageId: sendReplyToMessageId,
1223
+ replyInThread: effectiveReplyInThread,
1224
+ accountId
1225
+ });
1226
+ }
1227
+ });
1228
+ };
1229
+ const { dispatcher, replyOptions, markDispatchIdle } = core.channel.reply.createReplyDispatcherWithTyping({
1230
+ responsePrefix: prefixContext.responsePrefix,
1231
+ responsePrefixContextProvider: prefixContext.responsePrefixContextProvider,
1232
+ humanDelay: core.channel.reply.resolveHumanDelayConfig(cfg, agentId),
1233
+ onReplyStart: async () => {
1234
+ deliveredFinalTexts.clear();
1235
+ if (streamingEnabled && renderMode === "card") startStreaming();
1236
+ await typingCallbacks?.onReplyStart?.();
1237
+ },
1238
+ deliver: async (payload, info) => {
1239
+ const reply = resolveSendableOutboundReplyParts(payload);
1240
+ const text = reply.text;
1241
+ const hasText = reply.hasText;
1242
+ const hasMedia = reply.hasMedia;
1243
+ const skipTextForDuplicateFinal = info?.kind === "final" && hasText && deliveredFinalTexts.has(text);
1244
+ const shouldDeliverText = hasText && !skipTextForDuplicateFinal;
1245
+ if (!shouldDeliverText && !hasMedia) return;
1246
+ if (shouldDeliverText) {
1247
+ const useCard = renderMode === "card" || renderMode === "auto" && shouldUseCard(text);
1248
+ if (info?.kind === "block") {
1249
+ if (!(streamingEnabled && useCard)) return;
1250
+ startStreaming();
1251
+ if (streamingStartPromise) await streamingStartPromise;
1252
+ }
1253
+ if (info?.kind === "final" && streamingEnabled && useCard) {
1254
+ startStreaming();
1255
+ if (streamingStartPromise) await streamingStartPromise;
1256
+ }
1257
+ if (streaming?.isActive()) {
1258
+ if (info?.kind === "block") queueStreamingUpdate(text, { mode: "delta" });
1259
+ if (info?.kind === "final") {
1260
+ streamText = mergeStreamingText(streamText, text);
1261
+ await closeStreaming();
1262
+ deliveredFinalTexts.add(text);
1263
+ }
1264
+ if (hasMedia) await sendMediaReplies(payload);
1265
+ return;
1266
+ }
1267
+ if (useCard) {
1268
+ const cardHeader = resolveCardHeader(agentId, identity);
1269
+ const cardNote = resolveCardNote(agentId, identity, prefixContext.prefixContext);
1270
+ await sendChunkedTextReply({
1271
+ text,
1272
+ useCard: true,
1273
+ infoKind: info?.kind,
1274
+ sendChunk: async ({ chunk, isFirst }) => {
1275
+ await sendStructuredCardFeishu({
1276
+ cfg,
1277
+ to: chatId,
1278
+ text: chunk,
1279
+ replyToMessageId: sendReplyToMessageId,
1280
+ replyInThread: effectiveReplyInThread,
1281
+ mentions: isFirst ? mentionTargets : void 0,
1282
+ accountId,
1283
+ header: cardHeader,
1284
+ note: cardNote
1285
+ });
1286
+ }
1287
+ });
1288
+ } else await sendChunkedTextReply({
1289
+ text,
1290
+ useCard: false,
1291
+ infoKind: info?.kind,
1292
+ sendChunk: async ({ chunk, isFirst }) => {
1293
+ await sendMessageFeishu({
1294
+ cfg,
1295
+ to: chatId,
1296
+ text: chunk,
1297
+ replyToMessageId: sendReplyToMessageId,
1298
+ replyInThread: effectiveReplyInThread,
1299
+ mentions: isFirst ? mentionTargets : void 0,
1300
+ accountId
1301
+ });
1302
+ }
1303
+ });
1304
+ }
1305
+ if (hasMedia) await sendMediaReplies(payload);
1306
+ },
1307
+ onError: async (error, info) => {
1308
+ params.runtime.error?.(`feishu[${account.accountId}] ${info.kind} reply failed: ${String(error)}`);
1309
+ await closeStreaming();
1310
+ typingCallbacks?.onIdle?.();
1311
+ },
1312
+ onIdle: async () => {
1313
+ await closeStreaming();
1314
+ typingCallbacks?.onIdle?.();
1315
+ },
1316
+ onCleanup: () => {
1317
+ typingCallbacks?.onCleanup?.();
1318
+ }
1319
+ });
1320
+ return {
1321
+ dispatcher,
1322
+ replyOptions: {
1323
+ ...replyOptions,
1324
+ onModelSelected: prefixContext.onModelSelected,
1325
+ disableBlockStreaming: true,
1326
+ onPartialReply: streamingEnabled ? (payload) => {
1327
+ if (!payload.text) return;
1328
+ queueStreamingUpdate(payload.text, {
1329
+ dedupeWithLastPartial: true,
1330
+ mode: "snapshot"
1331
+ });
1332
+ } : void 0,
1333
+ onReasoningStream: streamingEnabled ? (payload) => {
1334
+ if (!payload.text) return;
1335
+ startStreaming();
1336
+ queueReasoningUpdate(payload.text);
1337
+ } : void 0,
1338
+ onReasoningEnd: streamingEnabled ? () => {} : void 0
1339
+ },
1340
+ markDispatchIdle
1341
+ };
1342
+ }
1343
+ //#endregion
1344
+ //#region extensions/feishu/src/bot.ts
1345
+ const permissionErrorNotifiedAt = /* @__PURE__ */ new Map();
1346
+ const PERMISSION_ERROR_COOLDOWN_MS = 300 * 1e3;
1347
+ function resolveBroadcastAgents(cfg, peerId) {
1348
+ const broadcast = cfg.broadcast;
1349
+ if (!broadcast || typeof broadcast !== "object") return null;
1350
+ const agents = broadcast[peerId];
1351
+ if (!Array.isArray(agents) || agents.length === 0) return null;
1352
+ return agents;
1353
+ }
1354
+ function buildBroadcastSessionKey(baseSessionKey, originalAgentId, targetAgentId) {
1355
+ const prefix = `agent:${originalAgentId}:`;
1356
+ if (baseSessionKey.startsWith(prefix)) return `agent:${targetAgentId}:${baseSessionKey.slice(prefix.length)}`;
1357
+ return baseSessionKey;
1358
+ }
1359
+ /**
1360
+ * Build media payload for inbound context.
1361
+ * Similar to Discord's buildDiscordMediaPayload().
1362
+ */
1363
+ function parseFeishuMessageEvent(event, botOpenId, _botName) {
1364
+ const rawContent = parseMessageContent(event.message.content, event.message.message_type);
1365
+ const mentionedBot = checkBotMentioned(event, botOpenId);
1366
+ const hasAnyMention = (event.message.mentions?.length ?? 0) > 0;
1367
+ const content = normalizeMentions(rawContent, event.message.mentions, botOpenId);
1368
+ const senderOpenId = event.sender.sender_id.open_id?.trim();
1369
+ const senderUserId = event.sender.sender_id.user_id?.trim();
1370
+ const senderFallbackId = senderOpenId || senderUserId || "";
1371
+ const ctx = {
1372
+ chatId: event.message.chat_id,
1373
+ messageId: event.message.message_id,
1374
+ senderId: senderUserId || senderOpenId || "",
1375
+ senderOpenId: senderFallbackId,
1376
+ chatType: event.message.chat_type,
1377
+ mentionedBot,
1378
+ hasAnyMention,
1379
+ rootId: event.message.root_id || void 0,
1380
+ parentId: event.message.parent_id || void 0,
1381
+ threadId: event.message.thread_id || void 0,
1382
+ content,
1383
+ contentType: event.message.message_type
1384
+ };
1385
+ if (isMentionForwardRequest(event, botOpenId)) {
1386
+ const mentionTargets = extractMentionTargets(event, botOpenId);
1387
+ if (mentionTargets.length > 0) ctx.mentionTargets = mentionTargets;
1388
+ }
1389
+ return ctx;
1390
+ }
1391
+ function buildFeishuAgentBody(params) {
1392
+ const { ctx, quotedContent, permissionErrorForAgent, botOpenId } = params;
1393
+ let messageBody = ctx.content;
1394
+ if (quotedContent) messageBody = `[Replying to: "${quotedContent}"]\n\n${ctx.content}`;
1395
+ messageBody = `${ctx.senderName ?? ctx.senderOpenId}: ${messageBody}`;
1396
+ if (ctx.hasAnyMention) {
1397
+ const botIdHint = botOpenId?.trim();
1398
+ messageBody += "\n\n[System: The content may include mention tags in the form <at user_id=\"...\">name</at>. Treat these as real mentions of Feishu entities (users or bots).]";
1399
+ if (botIdHint) messageBody += `\n[System: If user_id is "${botIdHint}", that mention refers to you.]`;
1400
+ }
1401
+ if (ctx.mentionTargets && ctx.mentionTargets.length > 0) {
1402
+ const targetNames = ctx.mentionTargets.map((t) => t.name).join(", ");
1403
+ messageBody += `\n\n[System: Your reply will automatically @mention: ${targetNames}. Do not write @xxx yourself.]`;
1404
+ }
1405
+ messageBody = `[message_id: ${ctx.messageId}]\n${messageBody}`;
1406
+ if (permissionErrorForAgent) {
1407
+ const grantUrl = permissionErrorForAgent.grantUrl ?? "";
1408
+ messageBody += `\n\n[System: The bot encountered a Feishu API permission error. Please inform the user about this issue and provide the permission grant URL for the admin to authorize. Permission grant URL: ${grantUrl}]`;
1409
+ }
1410
+ return messageBody;
1411
+ }
1412
+ async function handleFeishuMessage(params) {
1413
+ const { cfg, event, botOpenId, botName, runtime, chatHistories, accountId, processingClaimHeld = false } = params;
1414
+ const account = resolveFeishuAccount({
1415
+ cfg,
1416
+ accountId
1417
+ });
1418
+ const feishuCfg = account.config;
1419
+ const log = runtime?.log ?? console.log;
1420
+ const error = runtime?.error ?? console.error;
1421
+ const messageId = event.message.message_id;
1422
+ if (!await finalizeFeishuMessageProcessing({
1423
+ messageId,
1424
+ namespace: account.accountId,
1425
+ log,
1426
+ claimHeld: processingClaimHeld
1427
+ })) {
1428
+ log(`feishu: skipping duplicate message ${messageId}`);
1429
+ return;
1430
+ }
1431
+ let ctx = parseFeishuMessageEvent(event, botOpenId, botName);
1432
+ const isGroup = ctx.chatType === "group";
1433
+ const isDirect = !isGroup;
1434
+ const senderUserId = event.sender.sender_id.user_id?.trim() || void 0;
1435
+ if (event.message.message_type === "merge_forward") {
1436
+ log(`feishu[${account.accountId}]: processing merge_forward message, fetching full content via API`);
1437
+ try {
1438
+ const response = await createFeishuClient(account).im.message.get({ path: { message_id: event.message.message_id } });
1439
+ if (response.code === 0 && response.data?.items && response.data.items.length > 0) {
1440
+ log(`feishu[${account.accountId}]: merge_forward API returned ${response.data.items.length} items`);
1441
+ const expandedContent = parseMergeForwardContent({
1442
+ content: JSON.stringify(response.data.items),
1443
+ log
1444
+ });
1445
+ ctx = {
1446
+ ...ctx,
1447
+ content: expandedContent
1448
+ };
1449
+ } else {
1450
+ log(`feishu[${account.accountId}]: merge_forward API returned no items`);
1451
+ ctx = {
1452
+ ...ctx,
1453
+ content: "[Merged and Forwarded Message - could not fetch]"
1454
+ };
1455
+ }
1456
+ } catch (err) {
1457
+ log(`feishu[${account.accountId}]: merge_forward fetch failed: ${String(err)}`);
1458
+ ctx = {
1459
+ ...ctx,
1460
+ content: "[Merged and Forwarded Message - fetch error]"
1461
+ };
1462
+ }
1463
+ }
1464
+ let permissionErrorForAgent;
1465
+ if (feishuCfg?.resolveSenderNames ?? true) {
1466
+ const senderResult = await resolveFeishuSenderName({
1467
+ account,
1468
+ senderId: ctx.senderOpenId,
1469
+ log
1470
+ });
1471
+ if (senderResult.name) ctx = {
1472
+ ...ctx,
1473
+ senderName: senderResult.name
1474
+ };
1475
+ if (senderResult.permissionError) {
1476
+ const appKey = account.appId ?? "default";
1477
+ const now = Date.now();
1478
+ if (now - (permissionErrorNotifiedAt.get(appKey) ?? 0) > PERMISSION_ERROR_COOLDOWN_MS) {
1479
+ permissionErrorNotifiedAt.set(appKey, now);
1480
+ permissionErrorForAgent = senderResult.permissionError;
1481
+ }
1482
+ }
1483
+ }
1484
+ log(`feishu[${account.accountId}]: received message from ${ctx.senderOpenId} in ${ctx.chatId} (${ctx.chatType})`);
1485
+ if (ctx.mentionTargets && ctx.mentionTargets.length > 0) {
1486
+ const names = ctx.mentionTargets.map((t) => t.name).join(", ");
1487
+ log(`feishu[${account.accountId}]: detected @ forward request, targets: [${names}]`);
1488
+ }
1489
+ const historyLimit = Math.max(0, feishuCfg?.historyLimit ?? cfg.messages?.groupChat?.historyLimit ?? 50);
1490
+ const groupConfig = isGroup ? resolveFeishuGroupConfig({
1491
+ cfg: feishuCfg,
1492
+ groupId: ctx.chatId
1493
+ }) : void 0;
1494
+ const groupSession = isGroup ? resolveFeishuGroupSession({
1495
+ chatId: ctx.chatId,
1496
+ senderOpenId: ctx.senderOpenId,
1497
+ messageId: ctx.messageId,
1498
+ rootId: ctx.rootId,
1499
+ threadId: ctx.threadId,
1500
+ groupConfig,
1501
+ feishuCfg
1502
+ }) : null;
1503
+ const groupHistoryKey = isGroup ? groupSession?.peerId ?? ctx.chatId : void 0;
1504
+ const dmPolicy = feishuCfg?.dmPolicy ?? "pairing";
1505
+ const configAllowFrom = feishuCfg?.allowFrom ?? [];
1506
+ const useAccessGroups = cfg.commands?.useAccessGroups !== false;
1507
+ const rawBroadcastAgents = isGroup ? resolveBroadcastAgents(cfg, ctx.chatId) : null;
1508
+ const broadcastAgents = rawBroadcastAgents ? [...new Set(rawBroadcastAgents.map((id) => normalizeAgentId(id)))] : null;
1509
+ let requireMention = false;
1510
+ if (isGroup) {
1511
+ if (groupConfig?.enabled === false) {
1512
+ log(`feishu[${account.accountId}]: group ${ctx.chatId} is disabled`);
1513
+ return;
1514
+ }
1515
+ const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
1516
+ const { groupPolicy, providerMissingFallbackApplied } = resolveOpenProviderRuntimeGroupPolicy({
1517
+ providerConfigPresent: cfg.channels?.feishu !== void 0,
1518
+ groupPolicy: feishuCfg?.groupPolicy,
1519
+ defaultGroupPolicy
1520
+ });
1521
+ warnMissingProviderGroupPolicyFallbackOnce({
1522
+ providerMissingFallbackApplied,
1523
+ providerKey: "feishu",
1524
+ accountId: account.accountId,
1525
+ log
1526
+ });
1527
+ if (!isFeishuGroupAllowed({
1528
+ groupPolicy,
1529
+ allowFrom: feishuCfg?.groupAllowFrom ?? [],
1530
+ senderId: ctx.chatId,
1531
+ senderName: void 0
1532
+ })) {
1533
+ log(`feishu[${account.accountId}]: group ${ctx.chatId} not in groupAllowFrom (groupPolicy=${groupPolicy})`);
1534
+ return;
1535
+ }
1536
+ const perGroupSenderAllowFrom = groupConfig?.allowFrom ?? [];
1537
+ const globalSenderAllowFrom = feishuCfg?.groupSenderAllowFrom ?? [];
1538
+ const effectiveSenderAllowFrom = perGroupSenderAllowFrom.length > 0 ? perGroupSenderAllowFrom : globalSenderAllowFrom;
1539
+ if (effectiveSenderAllowFrom.length > 0) {
1540
+ if (!isFeishuGroupAllowed({
1541
+ groupPolicy: "allowlist",
1542
+ allowFrom: effectiveSenderAllowFrom,
1543
+ senderId: ctx.senderOpenId,
1544
+ senderIds: [senderUserId],
1545
+ senderName: ctx.senderName
1546
+ })) {
1547
+ log(`feishu: sender ${ctx.senderOpenId} not in group ${ctx.chatId} sender allowlist`);
1548
+ return;
1549
+ }
1550
+ }
1551
+ ({requireMention} = resolveFeishuReplyPolicy({
1552
+ isDirectMessage: false,
1553
+ globalConfig: feishuCfg,
1554
+ groupConfig
1555
+ }));
1556
+ if (requireMention && !ctx.mentionedBot) {
1557
+ log(`feishu[${account.accountId}]: message in group ${ctx.chatId} did not mention bot`);
1558
+ if (!broadcastAgents && chatHistories && groupHistoryKey) recordPendingHistoryEntryIfEnabled({
1559
+ historyMap: chatHistories,
1560
+ historyKey: groupHistoryKey,
1561
+ limit: historyLimit,
1562
+ entry: {
1563
+ sender: ctx.senderOpenId,
1564
+ body: `${ctx.senderName ?? ctx.senderOpenId}: ${ctx.content}`,
1565
+ timestamp: Date.now(),
1566
+ messageId: ctx.messageId
1567
+ }
1568
+ });
1569
+ return;
1570
+ }
1571
+ }
1572
+ try {
1573
+ const core = getFeishuRuntime();
1574
+ const pairing = createChannelPairingController({
1575
+ core,
1576
+ channel: "feishu",
1577
+ accountId: account.accountId
1578
+ });
1579
+ const commandProbeBody = isGroup ? normalizeFeishuCommandProbeBody(ctx.content) : ctx.content;
1580
+ const shouldComputeCommandAuthorized = core.channel.commands.shouldComputeCommandAuthorized(commandProbeBody, cfg);
1581
+ const storeAllowFrom = !isGroup && dmPolicy !== "allowlist" && (dmPolicy !== "open" || shouldComputeCommandAuthorized) ? await pairing.readAllowFromStore().catch(() => []) : [];
1582
+ const effectiveDmAllowFrom = [...configAllowFrom, ...storeAllowFrom];
1583
+ const dmAllowed = resolveFeishuAllowlistMatch({
1584
+ allowFrom: effectiveDmAllowFrom,
1585
+ senderId: ctx.senderOpenId,
1586
+ senderIds: [senderUserId],
1587
+ senderName: ctx.senderName
1588
+ }).allowed;
1589
+ if (isDirect && dmPolicy !== "open" && !dmAllowed) {
1590
+ if (dmPolicy === "pairing") await pairing.issueChallenge({
1591
+ senderId: ctx.senderOpenId,
1592
+ senderIdLine: `Your Feishu user id: ${ctx.senderOpenId}`,
1593
+ meta: { name: ctx.senderName },
1594
+ onCreated: () => {
1595
+ log(`feishu[${account.accountId}]: pairing request sender=${ctx.senderOpenId}`);
1596
+ },
1597
+ sendPairingReply: async (text) => {
1598
+ await sendMessageFeishu({
1599
+ cfg,
1600
+ to: `chat:${ctx.chatId}`,
1601
+ text,
1602
+ accountId: account.accountId
1603
+ });
1604
+ },
1605
+ onReplyError: (err) => {
1606
+ log(`feishu[${account.accountId}]: pairing reply failed for ${ctx.senderOpenId}: ${String(err)}`);
1607
+ }
1608
+ });
1609
+ else log(`feishu[${account.accountId}]: blocked unauthorized sender ${ctx.senderOpenId} (dmPolicy=${dmPolicy})`);
1610
+ return;
1611
+ }
1612
+ const commandAllowFrom = isGroup ? groupConfig?.allowFrom ?? configAllowFrom : effectiveDmAllowFrom;
1613
+ const senderAllowedForCommands = resolveFeishuAllowlistMatch({
1614
+ allowFrom: commandAllowFrom,
1615
+ senderId: ctx.senderOpenId,
1616
+ senderIds: [senderUserId],
1617
+ senderName: ctx.senderName
1618
+ }).allowed;
1619
+ const commandAuthorized = shouldComputeCommandAuthorized ? core.channel.commands.resolveCommandAuthorizedFromAuthorizers({
1620
+ useAccessGroups,
1621
+ authorizers: [{
1622
+ configured: commandAllowFrom.length > 0,
1623
+ allowed: senderAllowedForCommands
1624
+ }]
1625
+ }) : void 0;
1626
+ const feishuFrom = `feishu:${ctx.senderOpenId}`;
1627
+ const feishuTo = isGroup ? `chat:${ctx.chatId}` : `user:${ctx.senderOpenId}`;
1628
+ const peerId = isGroup ? groupSession?.peerId ?? ctx.chatId : ctx.senderOpenId;
1629
+ const parentPeer = isGroup ? groupSession?.parentPeer ?? null : null;
1630
+ const replyInThread = isGroup ? groupSession?.replyInThread ?? false : false;
1631
+ const feishuAcpConversationSupported = !isGroup || groupSession?.groupSessionScope === "group_topic" || groupSession?.groupSessionScope === "group_topic_sender";
1632
+ if (isGroup && groupSession) log(`feishu[${account.accountId}]: group session scope=${groupSession.groupSessionScope}, peer=${peerId}`);
1633
+ let route = core.channel.routing.resolveAgentRoute({
1634
+ cfg,
1635
+ channel: "feishu",
1636
+ accountId: account.accountId,
1637
+ peer: {
1638
+ kind: isGroup ? "group" : "direct",
1639
+ id: peerId
1640
+ },
1641
+ parentPeer
1642
+ });
1643
+ let effectiveCfg = cfg;
1644
+ if (!isGroup && route.matchedBy === "default") {
1645
+ const dynamicCfg = feishuCfg?.dynamicAgentCreation;
1646
+ if (dynamicCfg?.enabled) {
1647
+ const result = await maybeCreateDynamicAgent({
1648
+ cfg,
1649
+ runtime: getFeishuRuntime(),
1650
+ senderOpenId: ctx.senderOpenId,
1651
+ dynamicCfg,
1652
+ log: (msg) => log(msg)
1653
+ });
1654
+ if (result.created) {
1655
+ effectiveCfg = result.updatedCfg;
1656
+ route = core.channel.routing.resolveAgentRoute({
1657
+ cfg: result.updatedCfg,
1658
+ channel: "feishu",
1659
+ accountId: account.accountId,
1660
+ peer: {
1661
+ kind: "direct",
1662
+ id: ctx.senderOpenId
1663
+ }
1664
+ });
1665
+ log(`feishu[${account.accountId}]: dynamic agent created, new route: ${route.sessionKey}`);
1666
+ }
1667
+ }
1668
+ }
1669
+ const currentConversationId = peerId;
1670
+ const parentConversationId = isGroup ? parentPeer?.id ?? ctx.chatId : void 0;
1671
+ let configuredBinding = null;
1672
+ if (feishuAcpConversationSupported) {
1673
+ const configuredRoute = resolveConfiguredBindingRoute({
1674
+ cfg: effectiveCfg,
1675
+ route,
1676
+ conversation: {
1677
+ channel: "feishu",
1678
+ accountId: account.accountId,
1679
+ conversationId: currentConversationId,
1680
+ parentConversationId
1681
+ }
1682
+ });
1683
+ configuredBinding = configuredRoute.bindingResolution;
1684
+ route = configuredRoute.route;
1685
+ const threadBinding = getSessionBindingService().resolveByConversation({
1686
+ channel: "feishu",
1687
+ accountId: account.accountId,
1688
+ conversationId: currentConversationId,
1689
+ ...parentConversationId ? { parentConversationId } : {}
1690
+ });
1691
+ const boundSessionKey = threadBinding?.targetSessionKey?.trim();
1692
+ if (threadBinding && boundSessionKey) {
1693
+ route = {
1694
+ ...route,
1695
+ sessionKey: boundSessionKey,
1696
+ agentId: resolveAgentIdFromSessionKey(boundSessionKey) || route.agentId,
1697
+ lastRoutePolicy: deriveLastRoutePolicy({
1698
+ sessionKey: boundSessionKey,
1699
+ mainSessionKey: route.mainSessionKey
1700
+ }),
1701
+ matchedBy: "binding.channel"
1702
+ };
1703
+ configuredBinding = null;
1704
+ getSessionBindingService().touch(threadBinding.bindingId);
1705
+ log(`feishu[${account.accountId}]: routed via bound conversation ${currentConversationId} -> ${boundSessionKey}`);
1706
+ }
1707
+ }
1708
+ if (configuredBinding) {
1709
+ const ensured = await ensureConfiguredBindingRouteReady({
1710
+ cfg: effectiveCfg,
1711
+ bindingResolution: configuredBinding
1712
+ });
1713
+ if (!ensured.ok) {
1714
+ const replyTargetMessageId = isGroup && (groupSession?.groupSessionScope === "group_topic" || groupSession?.groupSessionScope === "group_topic_sender") ? ctx.rootId ?? ctx.messageId : ctx.messageId;
1715
+ await sendMessageFeishu({
1716
+ cfg: effectiveCfg,
1717
+ to: `chat:${ctx.chatId}`,
1718
+ text: `⚠️ Failed to initialize the configured ACP session for this Feishu conversation: ${ensured.error}`,
1719
+ replyToMessageId: replyTargetMessageId,
1720
+ replyInThread: isGroup ? groupSession?.replyInThread ?? false : false,
1721
+ accountId: account.accountId
1722
+ }).catch((err) => {
1723
+ log(`feishu[${account.accountId}]: failed to send ACP init error reply: ${String(err)}`);
1724
+ });
1725
+ return;
1726
+ }
1727
+ }
1728
+ const preview = ctx.content.replace(/\s+/g, " ").slice(0, 160);
1729
+ const inboundLabel = isGroup ? `Feishu[${account.accountId}] message in group ${ctx.chatId}` : `Feishu[${account.accountId}] DM from ${ctx.senderOpenId}`;
1730
+ log(`feishu[${account.accountId}]: ${inboundLabel}: ${preview}`);
1731
+ const mediaMaxBytes = (feishuCfg?.mediaMaxMb ?? 30) * 1024 * 1024;
1732
+ const mediaPayload = buildAgentMediaPayload(await resolveFeishuMediaList({
1733
+ cfg,
1734
+ messageId: ctx.messageId,
1735
+ messageType: event.message.message_type,
1736
+ content: event.message.content,
1737
+ maxBytes: mediaMaxBytes,
1738
+ log,
1739
+ accountId: account.accountId
1740
+ }));
1741
+ let quotedMessageInfo = null;
1742
+ let quotedContent;
1743
+ if (ctx.parentId) try {
1744
+ quotedMessageInfo = await getMessageFeishu({
1745
+ cfg,
1746
+ messageId: ctx.parentId,
1747
+ accountId: account.accountId
1748
+ });
1749
+ if (quotedMessageInfo) {
1750
+ quotedContent = quotedMessageInfo.content;
1751
+ log(`feishu[${account.accountId}]: fetched quoted message: ${quotedContent?.slice(0, 100)}`);
1752
+ }
1753
+ } catch (err) {
1754
+ log(`feishu[${account.accountId}]: failed to fetch quoted message: ${String(err)}`);
1755
+ }
1756
+ const isTopicSessionForThread = isGroup && (groupSession?.groupSessionScope === "group_topic" || groupSession?.groupSessionScope === "group_topic_sender");
1757
+ const envelopeOptions = core.channel.reply.resolveEnvelopeFormatOptions(cfg);
1758
+ const messageBody = buildFeishuAgentBody({
1759
+ ctx,
1760
+ quotedContent,
1761
+ permissionErrorForAgent,
1762
+ botOpenId
1763
+ });
1764
+ const envelopeFrom = isGroup ? `${ctx.chatId}:${ctx.senderOpenId}` : ctx.senderOpenId;
1765
+ if (permissionErrorForAgent) log(`feishu[${account.accountId}]: appending permission error notice to message body`);
1766
+ let combinedBody = core.channel.reply.formatAgentEnvelope({
1767
+ channel: "Feishu",
1768
+ from: envelopeFrom,
1769
+ timestamp: /* @__PURE__ */ new Date(),
1770
+ envelope: envelopeOptions,
1771
+ body: messageBody
1772
+ });
1773
+ const historyKey = groupHistoryKey;
1774
+ if (isGroup && historyKey && chatHistories) combinedBody = buildPendingHistoryContextFromMap({
1775
+ historyMap: chatHistories,
1776
+ historyKey,
1777
+ limit: historyLimit,
1778
+ currentMessage: combinedBody,
1779
+ formatEntry: (entry) => core.channel.reply.formatAgentEnvelope({
1780
+ channel: "Feishu",
1781
+ from: `${ctx.chatId}:${entry.sender}`,
1782
+ timestamp: entry.timestamp,
1783
+ body: entry.body,
1784
+ envelope: envelopeOptions
1785
+ })
1786
+ });
1787
+ const inboundHistory = isGroup && historyKey && historyLimit > 0 && chatHistories ? (chatHistories.get(historyKey) ?? []).map((entry) => ({
1788
+ sender: entry.sender,
1789
+ body: entry.body,
1790
+ timestamp: entry.timestamp
1791
+ })) : void 0;
1792
+ const threadContextBySessionKey = /* @__PURE__ */ new Map();
1793
+ let rootMessageInfo;
1794
+ let rootMessageFetched = false;
1795
+ const getRootMessageInfo = async () => {
1796
+ if (!ctx.rootId) return null;
1797
+ if (!rootMessageFetched) {
1798
+ rootMessageFetched = true;
1799
+ if (ctx.rootId === ctx.parentId && quotedMessageInfo) rootMessageInfo = quotedMessageInfo;
1800
+ else try {
1801
+ rootMessageInfo = await getMessageFeishu({
1802
+ cfg,
1803
+ messageId: ctx.rootId,
1804
+ accountId: account.accountId
1805
+ });
1806
+ } catch (err) {
1807
+ log(`feishu[${account.accountId}]: failed to fetch root message: ${String(err)}`);
1808
+ rootMessageInfo = null;
1809
+ }
1810
+ }
1811
+ return rootMessageInfo ?? null;
1812
+ };
1813
+ const resolveThreadContextForAgent = async (agentId, agentSessionKey) => {
1814
+ const cached = threadContextBySessionKey.get(agentSessionKey);
1815
+ if (cached) return cached;
1816
+ const threadContext = { threadLabel: (ctx.rootId || ctx.threadId) && isTopicSessionForThread ? `Feishu thread in ${ctx.chatId}` : void 0 };
1817
+ if (!(ctx.rootId || ctx.threadId) || !isTopicSessionForThread) {
1818
+ threadContextBySessionKey.set(agentSessionKey, threadContext);
1819
+ return threadContext;
1820
+ }
1821
+ const storePath = core.channel.session.resolveStorePath(cfg.session?.store, { agentId });
1822
+ if (core.channel.session.readSessionUpdatedAt({
1823
+ storePath,
1824
+ sessionKey: agentSessionKey
1825
+ })) {
1826
+ log(`feishu[${account.accountId}]: skipping thread bootstrap for existing session ${agentSessionKey}`);
1827
+ threadContextBySessionKey.set(agentSessionKey, threadContext);
1828
+ return threadContext;
1829
+ }
1830
+ const rootMsg = await getRootMessageInfo();
1831
+ let feishuThreadId = ctx.threadId ?? rootMsg?.threadId;
1832
+ if (feishuThreadId) log(`feishu[${account.accountId}]: resolved thread ID: ${feishuThreadId}`);
1833
+ if (!feishuThreadId) {
1834
+ log(`feishu[${account.accountId}]: no threadId found for root message ${ctx.rootId ?? "none"}, skipping thread history`);
1835
+ threadContextBySessionKey.set(agentSessionKey, threadContext);
1836
+ return threadContext;
1837
+ }
1838
+ try {
1839
+ const threadMessages = await listFeishuThreadMessages({
1840
+ cfg,
1841
+ threadId: feishuThreadId,
1842
+ currentMessageId: ctx.messageId,
1843
+ rootMessageId: ctx.rootId,
1844
+ limit: 20,
1845
+ accountId: account.accountId
1846
+ });
1847
+ const senderScoped = groupSession?.groupSessionScope === "group_topic_sender";
1848
+ const senderIds = new Set([ctx.senderOpenId, senderUserId].map((id) => id?.trim()).filter((id) => id !== void 0 && id.length > 0));
1849
+ const relevantMessages = (senderScoped ? threadMessages.filter((msg) => msg.senderType === "app" || msg.senderId !== void 0 && senderIds.has(msg.senderId.trim())) : threadMessages) ?? [];
1850
+ const threadStarterBody = rootMsg?.content ?? relevantMessages[0]?.content;
1851
+ const historyMessages = Boolean(rootMsg?.content || ctx.rootId) ? relevantMessages : relevantMessages.slice(1);
1852
+ const historyParts = historyMessages.map((msg) => {
1853
+ const role = msg.senderType === "app" ? "assistant" : "user";
1854
+ return core.channel.reply.formatAgentEnvelope({
1855
+ channel: "Feishu",
1856
+ from: `${msg.senderId ?? "Unknown"} (${role})`,
1857
+ timestamp: msg.createTime,
1858
+ body: msg.content,
1859
+ envelope: envelopeOptions
1860
+ });
1861
+ });
1862
+ threadContext.threadStarterBody = threadStarterBody;
1863
+ threadContext.threadHistoryBody = historyParts.length > 0 ? historyParts.join("\n\n") : void 0;
1864
+ log(`feishu[${account.accountId}]: populated thread bootstrap with starter=${threadStarterBody ? "yes" : "no"} history=${historyMessages.length}`);
1865
+ } catch (err) {
1866
+ log(`feishu[${account.accountId}]: failed to fetch thread history: ${String(err)}`);
1867
+ }
1868
+ threadContextBySessionKey.set(agentSessionKey, threadContext);
1869
+ return threadContext;
1870
+ };
1871
+ const buildCtxPayloadForAgent = async (agentId, agentSessionKey, agentAccountId, wasMentioned) => {
1872
+ const threadContext = await resolveThreadContextForAgent(agentId, agentSessionKey);
1873
+ return core.channel.reply.finalizeInboundContext({
1874
+ Body: combinedBody,
1875
+ BodyForAgent: messageBody,
1876
+ InboundHistory: inboundHistory,
1877
+ ReplyToId: ctx.parentId,
1878
+ RootMessageId: ctx.rootId,
1879
+ RawBody: ctx.content,
1880
+ CommandBody: ctx.content,
1881
+ From: feishuFrom,
1882
+ To: feishuTo,
1883
+ SessionKey: agentSessionKey,
1884
+ AccountId: agentAccountId,
1885
+ ChatType: isGroup ? "group" : "direct",
1886
+ GroupSubject: isGroup ? ctx.chatId : void 0,
1887
+ SenderName: ctx.senderName ?? ctx.senderOpenId,
1888
+ SenderId: ctx.senderOpenId,
1889
+ Provider: "feishu",
1890
+ Surface: "feishu",
1891
+ MessageSid: ctx.messageId,
1892
+ ReplyToBody: quotedContent ?? void 0,
1893
+ ThreadStarterBody: threadContext.threadStarterBody,
1894
+ ThreadHistoryBody: threadContext.threadHistoryBody,
1895
+ ThreadLabel: threadContext.threadLabel,
1896
+ MessageThreadId: ctx.rootId && isTopicSessionForThread ? ctx.rootId : void 0,
1897
+ Timestamp: Date.now(),
1898
+ WasMentioned: wasMentioned,
1899
+ CommandAuthorized: commandAuthorized,
1900
+ OriginatingChannel: "feishu",
1901
+ OriginatingTo: feishuTo,
1902
+ GroupSystemPrompt: isGroup ? groupConfig?.systemPrompt?.trim() || void 0 : void 0,
1903
+ ...mediaPayload
1904
+ });
1905
+ };
1906
+ const messageCreateTimeMs = event.message.create_time ? parseInt(event.message.create_time, 10) : void 0;
1907
+ const isTopicSession = isGroup && (groupSession?.groupSessionScope === "group_topic" || groupSession?.groupSessionScope === "group_topic_sender");
1908
+ const configReplyInThread = isGroup && (groupConfig?.replyInThread ?? feishuCfg?.replyInThread ?? "disabled") === "enabled";
1909
+ const replyTargetMessageId = isTopicSession || configReplyInThread ? ctx.rootId ?? ctx.messageId : ctx.messageId;
1910
+ const threadReply = isGroup ? groupSession?.threadReply ?? false : false;
1911
+ if (broadcastAgents) {
1912
+ if (!await tryRecordMessagePersistent(ctx.messageId, "broadcast", log)) {
1913
+ log(`feishu[${account.accountId}]: broadcast already claimed by another account for message ${ctx.messageId}; skipping`);
1914
+ return;
1915
+ }
1916
+ const strategy = cfg.broadcast?.strategy || "parallel";
1917
+ const activeAgentId = ctx.mentionedBot || !requireMention ? normalizeAgentId(route.agentId) : null;
1918
+ const agentIds = (cfg.agents?.list ?? []).map((a) => normalizeAgentId(a.id));
1919
+ const hasKnownAgents = agentIds.length > 0;
1920
+ log(`feishu[${account.accountId}]: broadcasting to ${broadcastAgents.length} agents (strategy=${strategy}, active=${activeAgentId ?? "none"})`);
1921
+ const dispatchForAgent = async (agentId) => {
1922
+ if (hasKnownAgents && !agentIds.includes(normalizeAgentId(agentId))) {
1923
+ log(`feishu[${account.accountId}]: broadcast agent ${agentId} not found in agents.list; skipping`);
1924
+ return;
1925
+ }
1926
+ const agentSessionKey = buildBroadcastSessionKey(route.sessionKey, route.agentId, agentId);
1927
+ const agentCtx = await buildCtxPayloadForAgent(agentId, agentSessionKey, route.accountId, ctx.mentionedBot && agentId === activeAgentId);
1928
+ if (agentId === activeAgentId) {
1929
+ const identity = resolveAgentOutboundIdentity(cfg, agentId);
1930
+ const { dispatcher, replyOptions, markDispatchIdle } = createFeishuReplyDispatcher({
1931
+ cfg,
1932
+ agentId,
1933
+ runtime,
1934
+ chatId: ctx.chatId,
1935
+ replyToMessageId: replyTargetMessageId,
1936
+ skipReplyToInMessages: !isGroup,
1937
+ replyInThread,
1938
+ rootId: ctx.rootId,
1939
+ threadReply,
1940
+ mentionTargets: ctx.mentionTargets,
1941
+ accountId: account.accountId,
1942
+ identity,
1943
+ messageCreateTimeMs
1944
+ });
1945
+ log(`feishu[${account.accountId}]: broadcast active dispatch agent=${agentId} (session=${agentSessionKey})`);
1946
+ await core.channel.reply.withReplyDispatcher({
1947
+ dispatcher,
1948
+ onSettled: () => markDispatchIdle(),
1949
+ run: () => core.channel.reply.dispatchReplyFromConfig({
1950
+ ctx: agentCtx,
1951
+ cfg,
1952
+ dispatcher,
1953
+ replyOptions
1954
+ })
1955
+ });
1956
+ } else {
1957
+ delete agentCtx.CommandAuthorized;
1958
+ const noopDispatcher = {
1959
+ sendToolResult: () => false,
1960
+ sendBlockReply: () => false,
1961
+ sendFinalReply: () => false,
1962
+ waitForIdle: async () => {},
1963
+ getQueuedCounts: () => ({
1964
+ tool: 0,
1965
+ block: 0,
1966
+ final: 0
1967
+ }),
1968
+ markComplete: () => {}
1969
+ };
1970
+ log(`feishu[${account.accountId}]: broadcast observer dispatch agent=${agentId} (session=${agentSessionKey})`);
1971
+ await core.channel.reply.withReplyDispatcher({
1972
+ dispatcher: noopDispatcher,
1973
+ run: () => core.channel.reply.dispatchReplyFromConfig({
1974
+ ctx: agentCtx,
1975
+ cfg,
1976
+ dispatcher: noopDispatcher
1977
+ })
1978
+ });
1979
+ }
1980
+ };
1981
+ if (strategy === "sequential") for (const agentId of broadcastAgents) try {
1982
+ await dispatchForAgent(agentId);
1983
+ } catch (err) {
1984
+ log(`feishu[${account.accountId}]: broadcast dispatch failed for agent=${agentId}: ${String(err)}`);
1985
+ }
1986
+ else {
1987
+ const results = await Promise.allSettled(broadcastAgents.map(dispatchForAgent));
1988
+ for (let i = 0; i < results.length; i++) if (results[i].status === "rejected") log(`feishu[${account.accountId}]: broadcast dispatch failed for agent=${broadcastAgents[i]}: ${String(results[i].reason)}`);
1989
+ }
1990
+ if (isGroup && historyKey && chatHistories) clearHistoryEntriesIfEnabled({
1991
+ historyMap: chatHistories,
1992
+ historyKey,
1993
+ limit: historyLimit
1994
+ });
1995
+ log(`feishu[${account.accountId}]: broadcast dispatch complete for ${broadcastAgents.length} agents`);
1996
+ } else {
1997
+ const ctxPayload = await buildCtxPayloadForAgent(route.agentId, route.sessionKey, route.accountId, ctx.mentionedBot);
1998
+ const identity = resolveAgentOutboundIdentity(cfg, route.agentId);
1999
+ const { dispatcher, replyOptions, markDispatchIdle } = createFeishuReplyDispatcher({
2000
+ cfg,
2001
+ agentId: route.agentId,
2002
+ runtime,
2003
+ chatId: ctx.chatId,
2004
+ replyToMessageId: replyTargetMessageId,
2005
+ skipReplyToInMessages: !isGroup,
2006
+ replyInThread,
2007
+ rootId: ctx.rootId,
2008
+ threadReply,
2009
+ mentionTargets: ctx.mentionTargets,
2010
+ accountId: account.accountId,
2011
+ identity,
2012
+ messageCreateTimeMs
2013
+ });
2014
+ log(`feishu[${account.accountId}]: dispatching to agent (session=${route.sessionKey})`);
2015
+ const { queuedFinal, counts } = await core.channel.reply.withReplyDispatcher({
2016
+ dispatcher,
2017
+ onSettled: () => {
2018
+ markDispatchIdle();
2019
+ },
2020
+ run: () => core.channel.reply.dispatchReplyFromConfig({
2021
+ ctx: ctxPayload,
2022
+ cfg,
2023
+ dispatcher,
2024
+ replyOptions
2025
+ })
2026
+ });
2027
+ if (isGroup && historyKey && chatHistories) clearHistoryEntriesIfEnabled({
2028
+ historyMap: chatHistories,
2029
+ historyKey,
2030
+ limit: historyLimit
2031
+ });
2032
+ log(`feishu[${account.accountId}]: dispatch complete (queuedFinal=${queuedFinal}, replies=${counts.final})`);
2033
+ }
2034
+ } catch (err) {
2035
+ error(`feishu[${account.accountId}]: failed to dispatch message: ${String(err)}`);
2036
+ }
2037
+ }
2038
+ //#endregion
2039
+ //#region extensions/feishu/src/card-interaction.ts
2040
+ const FEISHU_CARD_INTERACTION_VERSION = "ocf1";
2041
+ function isRecord(value) {
2042
+ return typeof value === "object" && value !== null;
2043
+ }
2044
+ function isInteractionKind(value) {
2045
+ return value === "button" || value === "quick" || value === "meta";
2046
+ }
2047
+ function isMetadataValue(value) {
2048
+ return value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
2049
+ }
2050
+ function createFeishuCardInteractionEnvelope(envelope) {
2051
+ return {
2052
+ oc: FEISHU_CARD_INTERACTION_VERSION,
2053
+ ...envelope
2054
+ };
2055
+ }
2056
+ function buildFeishuCardActionTextFallback(event) {
2057
+ const actionValue = event.action.value;
2058
+ if (isRecord(actionValue)) {
2059
+ if (typeof actionValue.text === "string") return actionValue.text;
2060
+ if (typeof actionValue.command === "string") return actionValue.command;
2061
+ return JSON.stringify(actionValue);
2062
+ }
2063
+ return String(actionValue);
2064
+ }
2065
+ function decodeFeishuCardAction(params) {
2066
+ const { event, now = Date.now() } = params;
2067
+ const actionValue = event.action.value;
2068
+ if (!isRecord(actionValue) || actionValue.oc !== "ocf1") return {
2069
+ kind: "legacy",
2070
+ text: buildFeishuCardActionTextFallback(event)
2071
+ };
2072
+ if (!isInteractionKind(actionValue.k) || typeof actionValue.a !== "string" || !actionValue.a) return {
2073
+ kind: "invalid",
2074
+ reason: "malformed"
2075
+ };
2076
+ if (actionValue.q !== void 0 && typeof actionValue.q !== "string") return {
2077
+ kind: "invalid",
2078
+ reason: "malformed"
2079
+ };
2080
+ if (actionValue.m !== void 0) {
2081
+ if (!isRecord(actionValue.m)) return {
2082
+ kind: "invalid",
2083
+ reason: "malformed"
2084
+ };
2085
+ for (const value of Object.values(actionValue.m)) if (!isMetadataValue(value)) return {
2086
+ kind: "invalid",
2087
+ reason: "malformed"
2088
+ };
2089
+ }
2090
+ if (actionValue.c !== void 0) {
2091
+ if (!isRecord(actionValue.c)) return {
2092
+ kind: "invalid",
2093
+ reason: "malformed"
2094
+ };
2095
+ if (actionValue.c.u !== void 0 && typeof actionValue.c.u !== "string") return {
2096
+ kind: "invalid",
2097
+ reason: "malformed"
2098
+ };
2099
+ if (actionValue.c.h !== void 0 && typeof actionValue.c.h !== "string") return {
2100
+ kind: "invalid",
2101
+ reason: "malformed"
2102
+ };
2103
+ if (actionValue.c.s !== void 0 && typeof actionValue.c.s !== "string") return {
2104
+ kind: "invalid",
2105
+ reason: "malformed"
2106
+ };
2107
+ if (actionValue.c.e !== void 0 && !Number.isFinite(actionValue.c.e)) return {
2108
+ kind: "invalid",
2109
+ reason: "malformed"
2110
+ };
2111
+ if (actionValue.c.t !== void 0 && actionValue.c.t !== "p2p" && actionValue.c.t !== "group") return {
2112
+ kind: "invalid",
2113
+ reason: "malformed"
2114
+ };
2115
+ if (typeof actionValue.c.e === "number" && actionValue.c.e < now) return {
2116
+ kind: "invalid",
2117
+ reason: "stale"
2118
+ };
2119
+ const expectedUser = actionValue.c.u?.trim();
2120
+ if (expectedUser && expectedUser !== (event.operator.open_id ?? "").trim()) return {
2121
+ kind: "invalid",
2122
+ reason: "wrong_user"
2123
+ };
2124
+ const expectedChat = actionValue.c.h?.trim();
2125
+ if (expectedChat && expectedChat !== (event.context.chat_id ?? "").trim()) return {
2126
+ kind: "invalid",
2127
+ reason: "wrong_conversation"
2128
+ };
2129
+ }
2130
+ return {
2131
+ kind: "structured",
2132
+ envelope: actionValue
2133
+ };
2134
+ }
2135
+ //#endregion
2136
+ //#region extensions/feishu/src/card-ux-shared.ts
2137
+ function buildFeishuCardButton(params) {
2138
+ return {
2139
+ tag: "button",
2140
+ text: {
2141
+ tag: "plain_text",
2142
+ content: params.label
2143
+ },
2144
+ type: params.type ?? "default",
2145
+ value: params.value
2146
+ };
2147
+ }
2148
+ function buildFeishuCardInteractionContext(params) {
2149
+ return {
2150
+ u: params.operatorOpenId,
2151
+ ...params.chatId ? { h: params.chatId } : {},
2152
+ ...params.sessionKey ? { s: params.sessionKey } : {},
2153
+ e: params.expiresAt,
2154
+ ...params.chatType ? { t: params.chatType } : {}
2155
+ };
2156
+ }
2157
+ //#endregion
2158
+ //#region extensions/feishu/src/card-ux-approval.ts
2159
+ const FEISHU_APPROVAL_REQUEST_ACTION = "feishu.quick_actions.request_approval";
2160
+ const FEISHU_APPROVAL_CONFIRM_ACTION = "feishu.approval.confirm";
2161
+ const FEISHU_APPROVAL_CANCEL_ACTION = "feishu.approval.cancel";
2162
+ function createApprovalCard(params) {
2163
+ const context = buildFeishuCardInteractionContext(params);
2164
+ return {
2165
+ schema: "2.0",
2166
+ config: { wide_screen_mode: true },
2167
+ header: {
2168
+ title: {
2169
+ tag: "plain_text",
2170
+ content: "Confirm action"
2171
+ },
2172
+ template: "orange"
2173
+ },
2174
+ body: { elements: [{
2175
+ tag: "markdown",
2176
+ content: params.prompt
2177
+ }, {
2178
+ tag: "action",
2179
+ actions: [buildFeishuCardButton({
2180
+ label: params.confirmLabel ?? "Confirm",
2181
+ type: "primary",
2182
+ value: createFeishuCardInteractionEnvelope({
2183
+ k: "quick",
2184
+ a: FEISHU_APPROVAL_CONFIRM_ACTION,
2185
+ q: params.command,
2186
+ c: context
2187
+ })
2188
+ }), buildFeishuCardButton({
2189
+ label: params.cancelLabel ?? "Cancel",
2190
+ value: createFeishuCardInteractionEnvelope({
2191
+ k: "button",
2192
+ a: FEISHU_APPROVAL_CANCEL_ACTION,
2193
+ c: context
2194
+ })
2195
+ })]
2196
+ }] }
2197
+ };
2198
+ }
2199
+ //#endregion
2200
+ //#region extensions/feishu/src/card-action.ts
2201
+ const FEISHU_APPROVAL_CARD_TTL_MS = 5 * 6e4;
2202
+ const FEISHU_CARD_ACTION_TOKEN_TTL_MS = 15 * 6e4;
2203
+ const processedCardActionTokens = /* @__PURE__ */ new Map();
2204
+ function pruneProcessedCardActionTokens(now) {
2205
+ for (const [key, entry] of processedCardActionTokens.entries()) if (entry.expiresAt <= now) processedCardActionTokens.delete(key);
2206
+ }
2207
+ function beginFeishuCardActionToken(params) {
2208
+ const now = params.now ?? Date.now();
2209
+ pruneProcessedCardActionTokens(now);
2210
+ const normalizedToken = params.token.trim();
2211
+ if (!normalizedToken) return true;
2212
+ const key = `${params.accountId}:${normalizedToken}`;
2213
+ const existing = processedCardActionTokens.get(key);
2214
+ if (existing && existing.expiresAt > now) return false;
2215
+ processedCardActionTokens.set(key, {
2216
+ status: "inflight",
2217
+ expiresAt: now + FEISHU_CARD_ACTION_TOKEN_TTL_MS
2218
+ });
2219
+ return true;
2220
+ }
2221
+ function completeFeishuCardActionToken(params) {
2222
+ const now = params.now ?? Date.now();
2223
+ const normalizedToken = params.token.trim();
2224
+ if (!normalizedToken) return;
2225
+ processedCardActionTokens.set(`${params.accountId}:${normalizedToken}`, {
2226
+ status: "completed",
2227
+ expiresAt: now + FEISHU_CARD_ACTION_TOKEN_TTL_MS
2228
+ });
2229
+ }
2230
+ function releaseFeishuCardActionToken(params) {
2231
+ const normalizedToken = params.token.trim();
2232
+ if (!normalizedToken) return;
2233
+ processedCardActionTokens.delete(`${params.accountId}:${normalizedToken}`);
2234
+ }
2235
+ function buildSyntheticMessageEvent(event, content, chatType) {
2236
+ return {
2237
+ sender: { sender_id: {
2238
+ open_id: event.operator.open_id,
2239
+ user_id: event.operator.user_id,
2240
+ union_id: event.operator.union_id
2241
+ } },
2242
+ message: {
2243
+ message_id: `card-action-${event.token}`,
2244
+ chat_id: event.context.chat_id || event.operator.open_id,
2245
+ chat_type: chatType ?? (event.context.chat_id ? "group" : "p2p"),
2246
+ message_type: "text",
2247
+ content: JSON.stringify({ text: content })
2248
+ }
2249
+ };
2250
+ }
2251
+ function resolveCallbackTarget(event) {
2252
+ const chatId = event.context.chat_id?.trim();
2253
+ if (chatId) return `chat:${chatId}`;
2254
+ return `user:${event.operator.open_id}`;
2255
+ }
2256
+ async function dispatchSyntheticCommand(params) {
2257
+ await handleFeishuMessage({
2258
+ cfg: params.cfg,
2259
+ event: buildSyntheticMessageEvent(params.event, params.command, params.chatType),
2260
+ botOpenId: params.botOpenId,
2261
+ runtime: params.runtime,
2262
+ accountId: params.accountId
2263
+ });
2264
+ }
2265
+ async function sendInvalidInteractionNotice(params) {
2266
+ const reasonText = params.reason === "stale" ? "This card action has expired. Open a fresh launcher card and try again." : params.reason === "wrong_user" ? "This card action belongs to a different user." : params.reason === "wrong_conversation" ? "This card action belongs to a different conversation." : "This card action payload is invalid.";
2267
+ await sendMessageFeishu({
2268
+ cfg: params.cfg,
2269
+ to: resolveCallbackTarget(params.event),
2270
+ text: `⚠️ ${reasonText}`,
2271
+ accountId: params.accountId
2272
+ });
2273
+ }
2274
+ async function handleFeishuCardAction(params) {
2275
+ const { cfg, event, runtime, accountId } = params;
2276
+ const account = resolveFeishuAccount({
2277
+ cfg,
2278
+ accountId
2279
+ });
2280
+ const log = runtime?.log ?? console.log;
2281
+ const decoded = decodeFeishuCardAction({ event });
2282
+ if (!beginFeishuCardActionToken({
2283
+ token: event.token,
2284
+ accountId: account.accountId
2285
+ })) {
2286
+ log(`feishu[${account.accountId}]: skipping duplicate card action token ${event.token}`);
2287
+ return;
2288
+ }
2289
+ try {
2290
+ if (decoded.kind === "invalid") {
2291
+ log(`feishu[${account.accountId}]: rejected card action from ${event.operator.open_id}: ${decoded.reason}`);
2292
+ await sendInvalidInteractionNotice({
2293
+ cfg,
2294
+ event,
2295
+ reason: decoded.reason,
2296
+ accountId
2297
+ });
2298
+ completeFeishuCardActionToken({
2299
+ token: event.token,
2300
+ accountId: account.accountId
2301
+ });
2302
+ return;
2303
+ }
2304
+ if (decoded.kind === "structured") {
2305
+ const { envelope } = decoded;
2306
+ log(`feishu[${account.accountId}]: handling structured card action ${envelope.a} from ${event.operator.open_id}`);
2307
+ if (envelope.a === "feishu.quick_actions.request_approval") {
2308
+ const command = typeof envelope.m?.command === "string" ? envelope.m.command.trim() : "";
2309
+ if (!command) {
2310
+ await sendInvalidInteractionNotice({
2311
+ cfg,
2312
+ event,
2313
+ reason: "malformed",
2314
+ accountId
2315
+ });
2316
+ completeFeishuCardActionToken({
2317
+ token: event.token,
2318
+ accountId: account.accountId
2319
+ });
2320
+ return;
2321
+ }
2322
+ const prompt = typeof envelope.m?.prompt === "string" && envelope.m.prompt.trim() ? envelope.m.prompt : `Run \`${command}\` in this Feishu conversation?`;
2323
+ await sendCardFeishu({
2324
+ cfg,
2325
+ to: resolveCallbackTarget(event),
2326
+ card: createApprovalCard({
2327
+ operatorOpenId: event.operator.open_id,
2328
+ chatId: event.context.chat_id || void 0,
2329
+ command,
2330
+ prompt,
2331
+ sessionKey: envelope.c?.s,
2332
+ expiresAt: Date.now() + FEISHU_APPROVAL_CARD_TTL_MS,
2333
+ chatType: envelope.c?.t ?? (event.context.chat_id ? "group" : "p2p"),
2334
+ confirmLabel: command === "/reset" ? "Reset" : "Confirm"
2335
+ }),
2336
+ accountId
2337
+ });
2338
+ completeFeishuCardActionToken({
2339
+ token: event.token,
2340
+ accountId: account.accountId
2341
+ });
2342
+ return;
2343
+ }
2344
+ if (envelope.a === "feishu.approval.cancel") {
2345
+ await sendMessageFeishu({
2346
+ cfg,
2347
+ to: resolveCallbackTarget(event),
2348
+ text: "Cancelled.",
2349
+ accountId
2350
+ });
2351
+ completeFeishuCardActionToken({
2352
+ token: event.token,
2353
+ accountId: account.accountId
2354
+ });
2355
+ return;
2356
+ }
2357
+ if (envelope.a === "feishu.approval.confirm" || envelope.k === "quick") {
2358
+ const command = envelope.q?.trim();
2359
+ if (!command) {
2360
+ await sendInvalidInteractionNotice({
2361
+ cfg,
2362
+ event,
2363
+ reason: "malformed",
2364
+ accountId
2365
+ });
2366
+ completeFeishuCardActionToken({
2367
+ token: event.token,
2368
+ accountId: account.accountId
2369
+ });
2370
+ return;
2371
+ }
2372
+ await dispatchSyntheticCommand({
2373
+ cfg,
2374
+ event,
2375
+ command,
2376
+ botOpenId: params.botOpenId,
2377
+ runtime,
2378
+ accountId,
2379
+ chatType: envelope.c?.t ?? (event.context.chat_id ? "group" : "p2p")
2380
+ });
2381
+ completeFeishuCardActionToken({
2382
+ token: event.token,
2383
+ accountId: account.accountId
2384
+ });
2385
+ return;
2386
+ }
2387
+ await sendInvalidInteractionNotice({
2388
+ cfg,
2389
+ event,
2390
+ reason: "malformed",
2391
+ accountId
2392
+ });
2393
+ completeFeishuCardActionToken({
2394
+ token: event.token,
2395
+ accountId: account.accountId
2396
+ });
2397
+ return;
2398
+ }
2399
+ const content = buildFeishuCardActionTextFallback(event);
2400
+ log(`feishu[${account.accountId}]: handling card action from ${event.operator.open_id}: ${content}`);
2401
+ await dispatchSyntheticCommand({
2402
+ cfg,
2403
+ event,
2404
+ command: content,
2405
+ botOpenId: params.botOpenId,
2406
+ runtime,
2407
+ accountId
2408
+ });
2409
+ completeFeishuCardActionToken({
2410
+ token: event.token,
2411
+ accountId: account.accountId
2412
+ });
2413
+ } catch (err) {
2414
+ releaseFeishuCardActionToken({
2415
+ token: event.token,
2416
+ accountId: account.accountId
2417
+ });
2418
+ throw err;
2419
+ }
2420
+ }
2421
+ //#endregion
2422
+ //#region extensions/feishu/src/card-ux-launcher.ts
2423
+ const FEISHU_QUICK_ACTION_CARD_TTL_MS = 10 * 6e4;
2424
+ const QUICK_ACTION_MENU_KEYS = new Set([
2425
+ "quick-actions",
2426
+ "quick_actions",
2427
+ "launcher"
2428
+ ]);
2429
+ function isFeishuQuickActionMenuEventKey(eventKey) {
2430
+ return QUICK_ACTION_MENU_KEYS.has(eventKey.trim().toLowerCase());
2431
+ }
2432
+ function createQuickActionLauncherCard(params) {
2433
+ const context = buildFeishuCardInteractionContext(params);
2434
+ return {
2435
+ schema: "2.0",
2436
+ config: { wide_screen_mode: true },
2437
+ header: {
2438
+ title: {
2439
+ tag: "plain_text",
2440
+ content: "Quick actions"
2441
+ },
2442
+ template: "indigo"
2443
+ },
2444
+ body: { elements: [{
2445
+ tag: "markdown",
2446
+ content: "Run common actions without typing raw commands."
2447
+ }, {
2448
+ tag: "action",
2449
+ actions: [
2450
+ buildFeishuCardButton({
2451
+ label: "Help",
2452
+ value: createFeishuCardInteractionEnvelope({
2453
+ k: "quick",
2454
+ a: "feishu.quick_actions.help",
2455
+ q: "/help",
2456
+ c: context
2457
+ })
2458
+ }),
2459
+ buildFeishuCardButton({
2460
+ label: "New session",
2461
+ type: "primary",
2462
+ value: createFeishuCardInteractionEnvelope({
2463
+ k: "meta",
2464
+ a: FEISHU_APPROVAL_REQUEST_ACTION,
2465
+ m: {
2466
+ command: "/new",
2467
+ prompt: "Start a fresh session? This will reset the current chat context."
2468
+ },
2469
+ c: context
2470
+ })
2471
+ }),
2472
+ buildFeishuCardButton({
2473
+ label: "Reset",
2474
+ type: "danger",
2475
+ value: createFeishuCardInteractionEnvelope({
2476
+ k: "meta",
2477
+ a: FEISHU_APPROVAL_REQUEST_ACTION,
2478
+ m: {
2479
+ command: "/reset",
2480
+ prompt: "Reset this session now? Any active conversation state will be cleared."
2481
+ },
2482
+ c: context
2483
+ })
2484
+ })
2485
+ ]
2486
+ }] }
2487
+ };
2488
+ }
2489
+ async function maybeHandleFeishuQuickActionMenu(params) {
2490
+ if (!isFeishuQuickActionMenuEventKey(params.eventKey)) return false;
2491
+ const expiresAt = (params.now ?? Date.now()) + FEISHU_QUICK_ACTION_CARD_TTL_MS;
2492
+ try {
2493
+ await sendCardFeishu({
2494
+ cfg: params.cfg,
2495
+ to: `user:${params.operatorOpenId}`,
2496
+ card: createQuickActionLauncherCard({
2497
+ operatorOpenId: params.operatorOpenId,
2498
+ expiresAt,
2499
+ chatType: "p2p"
2500
+ }),
2501
+ accountId: params.accountId
2502
+ });
2503
+ } catch (err) {
2504
+ params.runtime?.log?.(`feishu[${params.accountId ?? "default"}]: failed to open quick-action launcher for ${params.operatorOpenId}: ${String(err)}`);
2505
+ return false;
2506
+ }
2507
+ params.runtime?.log?.(`feishu[${params.accountId ?? "default"}]: opened quick-action launcher for ${params.operatorOpenId}`);
2508
+ return true;
2509
+ }
2510
+ function isTimeoutErrorMessage(message) {
2511
+ return message?.toLowerCase().includes("timeout") || message?.toLowerCase().includes("timed out") ? true : false;
2512
+ }
2513
+ function isAbortErrorMessage(message) {
2514
+ return message?.toLowerCase().includes("aborted") ?? false;
2515
+ }
2516
+ async function fetchBotIdentityForMonitor(account, options = {}) {
2517
+ if (options.abortSignal?.aborted) return {};
2518
+ const timeoutMs = options.timeoutMs ?? 1e4;
2519
+ const result = await probeFeishu(account, {
2520
+ timeoutMs,
2521
+ abortSignal: options.abortSignal
2522
+ });
2523
+ if (result.ok) return {
2524
+ botOpenId: result.botOpenId,
2525
+ botName: result.botName
2526
+ };
2527
+ if (options.abortSignal?.aborted || isAbortErrorMessage(result.error)) return {};
2528
+ if (isTimeoutErrorMessage(result.error)) (options.runtime?.error ?? console.error)(`feishu[${account.accountId}]: bot info probe timed out after ${timeoutMs}ms; continuing startup`);
2529
+ return {};
2530
+ }
2531
+ //#endregion
2532
+ //#region extensions/feishu/src/monitor.state.ts
2533
+ const wsClients = /* @__PURE__ */ new Map();
2534
+ const httpServers = /* @__PURE__ */ new Map();
2535
+ const botOpenIds = /* @__PURE__ */ new Map();
2536
+ const botNames = /* @__PURE__ */ new Map();
2537
+ const FEISHU_WEBHOOK_MAX_BODY_BYTES = 1024 * 1024;
2538
+ const FEISHU_WEBHOOK_BODY_TIMEOUT_MS = 3e4;
2539
+ const FEISHU_WEBHOOK_RATE_LIMIT_FALLBACK_DEFAULTS = {
2540
+ windowMs: 6e4,
2541
+ maxRequests: 120,
2542
+ maxTrackedKeys: 4096
2543
+ };
2544
+ const FEISHU_WEBHOOK_ANOMALY_FALLBACK_DEFAULTS = {
2545
+ maxTrackedKeys: 4096,
2546
+ ttlMs: 360 * 6e4,
2547
+ logEvery: 25
2548
+ };
2549
+ function coercePositiveInt(value, fallback) {
2550
+ if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
2551
+ const normalized = Math.floor(value);
2552
+ return normalized > 0 ? normalized : fallback;
2553
+ }
2554
+ function resolveFeishuWebhookRateLimitDefaultsForTest(defaults) {
2555
+ const resolved = defaults;
2556
+ return {
2557
+ windowMs: coercePositiveInt(resolved?.windowMs, FEISHU_WEBHOOK_RATE_LIMIT_FALLBACK_DEFAULTS.windowMs),
2558
+ maxRequests: coercePositiveInt(resolved?.maxRequests, FEISHU_WEBHOOK_RATE_LIMIT_FALLBACK_DEFAULTS.maxRequests),
2559
+ maxTrackedKeys: coercePositiveInt(resolved?.maxTrackedKeys, FEISHU_WEBHOOK_RATE_LIMIT_FALLBACK_DEFAULTS.maxTrackedKeys)
2560
+ };
2561
+ }
2562
+ function resolveFeishuWebhookAnomalyDefaultsForTest(defaults) {
2563
+ const resolved = defaults;
2564
+ return {
2565
+ maxTrackedKeys: coercePositiveInt(resolved?.maxTrackedKeys, FEISHU_WEBHOOK_ANOMALY_FALLBACK_DEFAULTS.maxTrackedKeys),
2566
+ ttlMs: coercePositiveInt(resolved?.ttlMs, FEISHU_WEBHOOK_ANOMALY_FALLBACK_DEFAULTS.ttlMs),
2567
+ logEvery: coercePositiveInt(resolved?.logEvery, FEISHU_WEBHOOK_ANOMALY_FALLBACK_DEFAULTS.logEvery)
2568
+ };
2569
+ }
2570
+ const feishuWebhookRateLimitDefaults = resolveFeishuWebhookRateLimitDefaultsForTest(WEBHOOK_RATE_LIMIT_DEFAULTS);
2571
+ const feishuWebhookAnomalyDefaults = resolveFeishuWebhookAnomalyDefaultsForTest(WEBHOOK_ANOMALY_COUNTER_DEFAULTS);
2572
+ const feishuWebhookRateLimiter = createFixedWindowRateLimiter({
2573
+ windowMs: feishuWebhookRateLimitDefaults.windowMs,
2574
+ maxRequests: feishuWebhookRateLimitDefaults.maxRequests,
2575
+ maxTrackedKeys: feishuWebhookRateLimitDefaults.maxTrackedKeys
2576
+ });
2577
+ const feishuWebhookAnomalyTracker = createWebhookAnomalyTracker({
2578
+ maxTrackedKeys: feishuWebhookAnomalyDefaults.maxTrackedKeys,
2579
+ ttlMs: feishuWebhookAnomalyDefaults.ttlMs,
2580
+ logEvery: feishuWebhookAnomalyDefaults.logEvery
2581
+ });
2582
+ function recordWebhookStatus(runtime, accountId, path, statusCode) {
2583
+ feishuWebhookAnomalyTracker.record({
2584
+ key: `${accountId}:${path}:${statusCode}`,
2585
+ statusCode,
2586
+ log: runtime?.log ?? console.log,
2587
+ message: (count) => `feishu[${accountId}]: webhook anomaly path=${path} status=${statusCode} count=${count}`
2588
+ });
2589
+ }
2590
+ //#endregion
2591
+ //#region extensions/feishu/src/monitor.transport.ts
2592
+ var import_lib = /* @__PURE__ */ __toESM(require_lib(), 1);
2593
+ function isFeishuWebhookPayload(value) {
2594
+ return !!value && typeof value === "object" && !Array.isArray(value);
2595
+ }
2596
+ function timingSafeEqualString(left, right) {
2597
+ const leftBuffer = Buffer.from(left, "utf8");
2598
+ const rightBuffer = Buffer.from(right, "utf8");
2599
+ if (leftBuffer.length !== rightBuffer.length) return false;
2600
+ return crypto.timingSafeEqual(leftBuffer, rightBuffer);
2601
+ }
2602
+ function buildFeishuWebhookEnvelope(req, payload) {
2603
+ return Object.assign(Object.create({ headers: req.headers }), payload);
2604
+ }
2605
+ function isFeishuWebhookSignatureValid(params) {
2606
+ const encryptKey = params.encryptKey?.trim();
2607
+ if (!encryptKey) return true;
2608
+ const timestampHeader = params.headers["x-lark-request-timestamp"];
2609
+ const nonceHeader = params.headers["x-lark-request-nonce"];
2610
+ const signatureHeader = params.headers["x-lark-signature"];
2611
+ const timestamp = Array.isArray(timestampHeader) ? timestampHeader[0] : timestampHeader;
2612
+ const nonce = Array.isArray(nonceHeader) ? nonceHeader[0] : nonceHeader;
2613
+ const signature = Array.isArray(signatureHeader) ? signatureHeader[0] : signatureHeader;
2614
+ if (!timestamp || !nonce || !signature) return false;
2615
+ return timingSafeEqualString(crypto.createHash("sha256").update(timestamp + nonce + encryptKey + JSON.stringify(params.payload)).digest("hex"), signature);
2616
+ }
2617
+ function respondText(res, statusCode, body) {
2618
+ res.statusCode = statusCode;
2619
+ res.setHeader("Content-Type", "text/plain; charset=utf-8");
2620
+ res.end(body);
2621
+ }
2622
+ async function monitorWebSocket({ account, accountId, runtime, abortSignal, eventDispatcher }) {
2623
+ const log = runtime?.log ?? console.log;
2624
+ log(`feishu[${accountId}]: starting WebSocket connection...`);
2625
+ const wsClient = createFeishuWSClient(account);
2626
+ wsClients.set(accountId, wsClient);
2627
+ return new Promise((resolve, reject) => {
2628
+ const cleanup = () => {
2629
+ wsClients.delete(accountId);
2630
+ botOpenIds.delete(accountId);
2631
+ botNames.delete(accountId);
2632
+ };
2633
+ const handleAbort = () => {
2634
+ log(`feishu[${accountId}]: abort signal received, stopping`);
2635
+ cleanup();
2636
+ resolve();
2637
+ };
2638
+ if (abortSignal?.aborted) {
2639
+ cleanup();
2640
+ resolve();
2641
+ return;
2642
+ }
2643
+ abortSignal?.addEventListener("abort", handleAbort, { once: true });
2644
+ try {
2645
+ wsClient.start({ eventDispatcher });
2646
+ log(`feishu[${accountId}]: WebSocket client started`);
2647
+ } catch (err) {
2648
+ cleanup();
2649
+ abortSignal?.removeEventListener("abort", handleAbort);
2650
+ reject(err);
2651
+ }
2652
+ });
2653
+ }
2654
+ async function monitorWebhook({ account, accountId, runtime, abortSignal, eventDispatcher }) {
2655
+ const log = runtime?.log ?? console.log;
2656
+ const error = runtime?.error ?? console.error;
2657
+ const port = account.config.webhookPort ?? 3e3;
2658
+ const path = account.config.webhookPath ?? "/feishu/events";
2659
+ const host = account.config.webhookHost ?? "127.0.0.1";
2660
+ log(`feishu[${accountId}]: starting Webhook server on ${host}:${port}, path ${path}...`);
2661
+ const server = http.createServer();
2662
+ server.on("request", (req, res) => {
2663
+ res.on("finish", () => {
2664
+ recordWebhookStatus(runtime, accountId, path, res.statusCode);
2665
+ });
2666
+ if (!applyBasicWebhookRequestGuards({
2667
+ req,
2668
+ res,
2669
+ rateLimiter: feishuWebhookRateLimiter,
2670
+ rateLimitKey: `${accountId}:${path}:${req.socket.remoteAddress ?? "unknown"}`,
2671
+ nowMs: Date.now(),
2672
+ requireJsonContentType: true
2673
+ })) return;
2674
+ const guard = installRequestBodyLimitGuard(req, res, {
2675
+ maxBytes: FEISHU_WEBHOOK_MAX_BODY_BYTES,
2676
+ timeoutMs: FEISHU_WEBHOOK_BODY_TIMEOUT_MS,
2677
+ responseFormat: "text"
2678
+ });
2679
+ if (guard.isTripped()) return;
2680
+ (async () => {
2681
+ try {
2682
+ const bodyResult = await readJsonBodyWithLimit(req, {
2683
+ maxBytes: FEISHU_WEBHOOK_MAX_BODY_BYTES,
2684
+ timeoutMs: FEISHU_WEBHOOK_BODY_TIMEOUT_MS
2685
+ });
2686
+ if (guard.isTripped() || res.writableEnded) return;
2687
+ if (!bodyResult.ok) {
2688
+ if (bodyResult.code === "INVALID_JSON") respondText(res, 400, "Invalid JSON");
2689
+ return;
2690
+ }
2691
+ if (!isFeishuWebhookPayload(bodyResult.value)) {
2692
+ respondText(res, 400, "Invalid JSON");
2693
+ return;
2694
+ }
2695
+ if (!isFeishuWebhookSignatureValid({
2696
+ headers: req.headers,
2697
+ payload: bodyResult.value,
2698
+ encryptKey: account.encryptKey
2699
+ })) {
2700
+ respondText(res, 401, "Invalid signature");
2701
+ return;
2702
+ }
2703
+ const { isChallenge, challenge } = import_lib.generateChallenge(bodyResult.value, { encryptKey: account.encryptKey ?? "" });
2704
+ if (isChallenge) {
2705
+ res.statusCode = 200;
2706
+ res.setHeader("Content-Type", "application/json; charset=utf-8");
2707
+ res.end(JSON.stringify(challenge));
2708
+ return;
2709
+ }
2710
+ const value = await eventDispatcher.invoke(buildFeishuWebhookEnvelope(req, bodyResult.value), { needCheck: false });
2711
+ if (!res.headersSent) {
2712
+ res.statusCode = 200;
2713
+ res.setHeader("Content-Type", "application/json; charset=utf-8");
2714
+ res.end(JSON.stringify(value));
2715
+ }
2716
+ } catch (err) {
2717
+ if (!guard.isTripped()) {
2718
+ error(`feishu[${accountId}]: webhook handler error: ${String(err)}`);
2719
+ if (!res.headersSent) respondText(res, 500, "Internal Server Error");
2720
+ }
2721
+ } finally {
2722
+ guard.dispose();
2723
+ }
2724
+ })();
2725
+ });
2726
+ httpServers.set(accountId, server);
2727
+ return new Promise((resolve, reject) => {
2728
+ const cleanup = () => {
2729
+ server.close();
2730
+ httpServers.delete(accountId);
2731
+ botOpenIds.delete(accountId);
2732
+ botNames.delete(accountId);
2733
+ };
2734
+ const handleAbort = () => {
2735
+ log(`feishu[${accountId}]: abort signal received, stopping Webhook server`);
2736
+ cleanup();
2737
+ resolve();
2738
+ };
2739
+ if (abortSignal?.aborted) {
2740
+ cleanup();
2741
+ resolve();
2742
+ return;
2743
+ }
2744
+ abortSignal?.addEventListener("abort", handleAbort, { once: true });
2745
+ server.listen(port, host, () => {
2746
+ log(`feishu[${accountId}]: Webhook server listening on ${host}:${port}`);
2747
+ });
2748
+ server.on("error", (err) => {
2749
+ error(`feishu[${accountId}]: Webhook server error: ${err}`);
2750
+ abortSignal?.removeEventListener("abort", handleAbort);
2751
+ reject(err);
2752
+ });
2753
+ });
2754
+ }
2755
+ //#endregion
2756
+ //#region extensions/feishu/src/monitor.account.ts
2757
+ const FEISHU_REACTION_VERIFY_TIMEOUT_MS = 1500;
2758
+ async function resolveReactionSyntheticEvent(params) {
2759
+ const { cfg, accountId, event, botOpenId, fetchMessage = getMessageFeishu, verificationTimeoutMs = FEISHU_REACTION_VERIFY_TIMEOUT_MS, logger, uuid = () => crypto$1.randomUUID(), action = "created" } = params;
2760
+ const emoji = event.reaction_type?.emoji_type;
2761
+ const messageId = event.message_id;
2762
+ const senderId = event.user_id?.open_id;
2763
+ if (!emoji || !messageId || !senderId) return null;
2764
+ const reactionNotifications = resolveFeishuAccount({
2765
+ cfg,
2766
+ accountId
2767
+ }).config.reactionNotifications ?? "own";
2768
+ if (reactionNotifications === "off") return null;
2769
+ if (event.operator_type === "app" || senderId === botOpenId) return null;
2770
+ if (emoji === "Typing") return null;
2771
+ if (reactionNotifications === "own" && !botOpenId) {
2772
+ logger?.(`feishu[${accountId}]: bot open_id unavailable, skipping reaction ${emoji} on ${messageId}`);
2773
+ return null;
2774
+ }
2775
+ const reactedMsg = await raceWithTimeoutAndAbort(fetchMessage({
2776
+ cfg,
2777
+ messageId,
2778
+ accountId
2779
+ }), { timeoutMs: verificationTimeoutMs }).then((result) => result.status === "resolved" ? result.value : null).catch(() => null);
2780
+ const isBotMessage = reactedMsg?.senderType === "app" || reactedMsg?.senderOpenId === botOpenId;
2781
+ if (!reactedMsg || reactionNotifications === "own" && !isBotMessage) {
2782
+ logger?.(`feishu[${accountId}]: ignoring reaction on non-bot/unverified message ${messageId} (sender: ${reactedMsg?.senderOpenId ?? "unknown"})`);
2783
+ return null;
2784
+ }
2785
+ const fallbackChatType = reactedMsg.chatType;
2786
+ const resolvedChatType = normalizeFeishuChatType(event.chat_type) ?? fallbackChatType;
2787
+ if (!resolvedChatType) {
2788
+ logger?.(`feishu[${accountId}]: skipping reaction ${emoji} on ${messageId} without chat type context`);
2789
+ return null;
2790
+ }
2791
+ const syntheticChatIdRaw = event.chat_id ?? reactedMsg.chatId;
2792
+ const syntheticChatId = syntheticChatIdRaw?.trim() ? syntheticChatIdRaw : `p2p:${senderId}`;
2793
+ const syntheticChatType = resolvedChatType;
2794
+ return {
2795
+ sender: {
2796
+ sender_id: { open_id: senderId },
2797
+ sender_type: "user"
2798
+ },
2799
+ message: {
2800
+ message_id: `${messageId}:reaction:${emoji}:${uuid()}`,
2801
+ chat_id: syntheticChatId,
2802
+ chat_type: syntheticChatType,
2803
+ message_type: "text",
2804
+ content: JSON.stringify({ text: action === "deleted" ? `[removed reaction ${emoji} from message ${messageId}]` : `[reacted with ${emoji} to message ${messageId}]` })
2805
+ }
2806
+ };
2807
+ }
2808
+ function normalizeFeishuChatType(value) {
2809
+ return value === "group" || value === "private" || value === "p2p" ? value : void 0;
2810
+ }
2811
+ /**
2812
+ * Per-chat serial queue that ensures messages from the same chat are processed
2813
+ * in arrival order while allowing different chats to run concurrently.
2814
+ */
2815
+ function createChatQueue() {
2816
+ const queues = /* @__PURE__ */ new Map();
2817
+ return (chatId, task) => {
2818
+ const next = (queues.get(chatId) ?? Promise.resolve()).then(task, task);
2819
+ queues.set(chatId, next);
2820
+ next.finally(() => {
2821
+ if (queues.get(chatId) === next) queues.delete(chatId);
2822
+ });
2823
+ return next;
2824
+ };
2825
+ }
2826
+ function mergeFeishuDebounceMentions(entries) {
2827
+ const merged = /* @__PURE__ */ new Map();
2828
+ for (const entry of entries) for (const mention of entry.message.mentions ?? []) {
2829
+ const stableId = mention.id.open_id?.trim() || mention.id.user_id?.trim() || mention.id.union_id?.trim();
2830
+ const mentionName = mention.name?.trim();
2831
+ const mentionKey = mention.key?.trim();
2832
+ const fallback = mentionName && mentionKey ? `${mentionName}|${mentionKey}` : mentionName || mentionKey;
2833
+ const key = stableId || fallback;
2834
+ if (!key || merged.has(key)) continue;
2835
+ merged.set(key, mention);
2836
+ }
2837
+ if (merged.size === 0) return;
2838
+ return Array.from(merged.values());
2839
+ }
2840
+ function dedupeFeishuDebounceEntriesByMessageId(entries) {
2841
+ const seen = /* @__PURE__ */ new Set();
2842
+ const deduped = [];
2843
+ for (const entry of entries) {
2844
+ const messageId = entry.message.message_id?.trim();
2845
+ if (!messageId) {
2846
+ deduped.push(entry);
2847
+ continue;
2848
+ }
2849
+ if (seen.has(messageId)) continue;
2850
+ seen.add(messageId);
2851
+ deduped.push(entry);
2852
+ }
2853
+ return deduped;
2854
+ }
2855
+ function resolveFeishuDebounceMentions(params) {
2856
+ const { entries, botOpenId } = params;
2857
+ if (entries.length === 0) return;
2858
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
2859
+ const entry = entries[index];
2860
+ if (isMentionForwardRequest(entry, botOpenId)) return mergeFeishuDebounceMentions([entry]);
2861
+ }
2862
+ const merged = mergeFeishuDebounceMentions(entries);
2863
+ if (!merged) return;
2864
+ const normalizedBotOpenId = botOpenId?.trim();
2865
+ if (!normalizedBotOpenId) return;
2866
+ const botMentions = merged.filter((mention) => mention.id.open_id?.trim() === normalizedBotOpenId);
2867
+ return botMentions.length > 0 ? botMentions : void 0;
2868
+ }
2869
+ function registerEventHandlers(eventDispatcher, context) {
2870
+ const { cfg, accountId, runtime, chatHistories, fireAndForget } = context;
2871
+ const core = getFeishuRuntime();
2872
+ const inboundDebounceMs = core.channel.debounce.resolveInboundDebounceMs({
2873
+ cfg,
2874
+ channel: "feishu"
2875
+ });
2876
+ const log = runtime?.log ?? console.log;
2877
+ const error = runtime?.error ?? console.error;
2878
+ const enqueue = createChatQueue();
2879
+ const runFeishuHandler = async (params) => {
2880
+ if (fireAndForget) {
2881
+ params.task().catch((err) => {
2882
+ error(`${params.errorMessage}: ${String(err)}`);
2883
+ });
2884
+ return;
2885
+ }
2886
+ try {
2887
+ await params.task();
2888
+ } catch (err) {
2889
+ error(`${params.errorMessage}: ${String(err)}`);
2890
+ }
2891
+ };
2892
+ const dispatchFeishuMessage = async (event) => {
2893
+ const chatId = event.message.chat_id?.trim() || "unknown";
2894
+ const task = () => handleFeishuMessage({
2895
+ cfg,
2896
+ event,
2897
+ botOpenId: botOpenIds.get(accountId),
2898
+ botName: botNames.get(accountId),
2899
+ runtime,
2900
+ chatHistories,
2901
+ accountId,
2902
+ processingClaimHeld: true
2903
+ });
2904
+ await enqueue(chatId, task);
2905
+ };
2906
+ const resolveSenderDebounceId = (event) => {
2907
+ return event.sender.sender_id.open_id?.trim() || event.sender.sender_id.user_id?.trim() || void 0;
2908
+ };
2909
+ const resolveDebounceText = (event) => {
2910
+ return parseFeishuMessageEvent(event, botOpenIds.get(accountId), botNames.get(accountId)).content.trim();
2911
+ };
2912
+ const recordSuppressedMessageIds = async (entries, dispatchMessageId) => {
2913
+ const keepMessageId = dispatchMessageId?.trim();
2914
+ const suppressedIds = new Set(entries.map((entry) => entry.message.message_id?.trim()).filter((id) => Boolean(id) && (!keepMessageId || id !== keepMessageId)));
2915
+ if (suppressedIds.size === 0) return;
2916
+ for (const messageId of suppressedIds) try {
2917
+ await recordProcessedFeishuMessage(messageId, accountId, log);
2918
+ } catch (err) {
2919
+ error(`feishu[${accountId}]: failed to record merged dedupe id ${messageId}: ${String(err)}`);
2920
+ }
2921
+ };
2922
+ const isMessageAlreadyProcessed = async (entry) => {
2923
+ return await hasProcessedFeishuMessage(entry.message.message_id, accountId, log);
2924
+ };
2925
+ const inboundDebouncer = core.channel.debounce.createInboundDebouncer({
2926
+ debounceMs: inboundDebounceMs,
2927
+ buildKey: (event) => {
2928
+ const chatId = event.message.chat_id?.trim();
2929
+ const senderId = resolveSenderDebounceId(event);
2930
+ if (!chatId || !senderId) return null;
2931
+ const rootId = event.message.root_id?.trim();
2932
+ return `feishu:${accountId}:${chatId}:${rootId ? `thread:${rootId}` : "chat"}:${senderId}`;
2933
+ },
2934
+ shouldDebounce: (event) => {
2935
+ if (event.message.message_type !== "text") return false;
2936
+ const text = resolveDebounceText(event);
2937
+ if (!text) return false;
2938
+ return !core.channel.text.hasControlCommand(text, cfg);
2939
+ },
2940
+ onFlush: async (entries) => {
2941
+ const last = entries.at(-1);
2942
+ if (!last) return;
2943
+ if (entries.length === 1) {
2944
+ await dispatchFeishuMessage(last);
2945
+ return;
2946
+ }
2947
+ const dedupedEntries = dedupeFeishuDebounceEntriesByMessageId(entries);
2948
+ const freshEntries = [];
2949
+ for (const entry of dedupedEntries) if (!await isMessageAlreadyProcessed(entry)) freshEntries.push(entry);
2950
+ const dispatchEntry = freshEntries.at(-1);
2951
+ if (!dispatchEntry) return;
2952
+ await recordSuppressedMessageIds(dedupedEntries, dispatchEntry.message.message_id);
2953
+ const combinedText = freshEntries.map((entry) => resolveDebounceText(entry)).filter(Boolean).join("\n");
2954
+ const mergedMentions = resolveFeishuDebounceMentions({
2955
+ entries: freshEntries,
2956
+ botOpenId: botOpenIds.get(accountId)
2957
+ });
2958
+ if (!combinedText.trim()) {
2959
+ await dispatchFeishuMessage({
2960
+ ...dispatchEntry,
2961
+ message: {
2962
+ ...dispatchEntry.message,
2963
+ mentions: mergedMentions ?? dispatchEntry.message.mentions
2964
+ }
2965
+ });
2966
+ return;
2967
+ }
2968
+ await dispatchFeishuMessage({
2969
+ ...dispatchEntry,
2970
+ message: {
2971
+ ...dispatchEntry.message,
2972
+ message_type: "text",
2973
+ content: JSON.stringify({ text: combinedText }),
2974
+ mentions: mergedMentions ?? dispatchEntry.message.mentions
2975
+ }
2976
+ });
2977
+ },
2978
+ onError: (err, entries) => {
2979
+ for (const entry of entries) releaseFeishuMessageProcessing(entry.message.message_id, accountId);
2980
+ error(`feishu[${accountId}]: inbound debounce flush failed: ${String(err)}`);
2981
+ }
2982
+ });
2983
+ eventDispatcher.register({
2984
+ "im.message.receive_v1": async (data) => {
2985
+ const event = data;
2986
+ const messageId = event.message?.message_id?.trim();
2987
+ if (!tryBeginFeishuMessageProcessing(messageId, accountId)) {
2988
+ log(`feishu[${accountId}]: dropping duplicate event for message ${messageId}`);
2989
+ return;
2990
+ }
2991
+ const processMessage = async () => {
2992
+ await inboundDebouncer.enqueue(event);
2993
+ };
2994
+ if (fireAndForget) {
2995
+ processMessage().catch((err) => {
2996
+ releaseFeishuMessageProcessing(messageId, accountId);
2997
+ error(`feishu[${accountId}]: error handling message: ${String(err)}`);
2998
+ });
2999
+ return;
3000
+ }
3001
+ try {
3002
+ await processMessage();
3003
+ } catch (err) {
3004
+ releaseFeishuMessageProcessing(messageId, accountId);
3005
+ error(`feishu[${accountId}]: error handling message: ${String(err)}`);
3006
+ }
3007
+ },
3008
+ "im.message.message_read_v1": async () => {},
3009
+ "im.chat.member.bot.added_v1": async (data) => {
3010
+ try {
3011
+ log(`feishu[${accountId}]: bot added to chat ${data.chat_id}`);
3012
+ } catch (err) {
3013
+ error(`feishu[${accountId}]: error handling bot added event: ${String(err)}`);
3014
+ }
3015
+ },
3016
+ "im.chat.member.bot.deleted_v1": async (data) => {
3017
+ try {
3018
+ log(`feishu[${accountId}]: bot removed from chat ${data.chat_id}`);
3019
+ } catch (err) {
3020
+ error(`feishu[${accountId}]: error handling bot removed event: ${String(err)}`);
3021
+ }
3022
+ },
3023
+ "im.message.reaction.created_v1": async (data) => {
3024
+ await runFeishuHandler({
3025
+ errorMessage: `feishu[${accountId}]: error handling reaction event`,
3026
+ task: async () => {
3027
+ const event = data;
3028
+ const myBotId = botOpenIds.get(accountId);
3029
+ const syntheticEvent = await resolveReactionSyntheticEvent({
3030
+ cfg,
3031
+ accountId,
3032
+ event,
3033
+ botOpenId: myBotId,
3034
+ logger: log
3035
+ });
3036
+ if (!syntheticEvent) return;
3037
+ await handleFeishuMessage({
3038
+ cfg,
3039
+ event: syntheticEvent,
3040
+ botOpenId: myBotId,
3041
+ botName: botNames.get(accountId),
3042
+ runtime,
3043
+ chatHistories,
3044
+ accountId
3045
+ });
3046
+ }
3047
+ });
3048
+ },
3049
+ "im.message.reaction.deleted_v1": async (data) => {
3050
+ await runFeishuHandler({
3051
+ errorMessage: `feishu[${accountId}]: error handling reaction removal event`,
3052
+ task: async () => {
3053
+ const event = data;
3054
+ const myBotId = botOpenIds.get(accountId);
3055
+ const syntheticEvent = await resolveReactionSyntheticEvent({
3056
+ cfg,
3057
+ accountId,
3058
+ event,
3059
+ botOpenId: myBotId,
3060
+ logger: log,
3061
+ action: "deleted"
3062
+ });
3063
+ if (!syntheticEvent) return;
3064
+ await handleFeishuMessage({
3065
+ cfg,
3066
+ event: syntheticEvent,
3067
+ botOpenId: myBotId,
3068
+ botName: botNames.get(accountId),
3069
+ runtime,
3070
+ chatHistories,
3071
+ accountId
3072
+ });
3073
+ }
3074
+ });
3075
+ },
3076
+ "application.bot.menu_v6": async (data) => {
3077
+ try {
3078
+ const event = data;
3079
+ const operatorOpenId = event.operator?.operator_id?.open_id?.trim();
3080
+ const eventKey = event.event_key?.trim();
3081
+ if (!operatorOpenId || !eventKey) return;
3082
+ const syntheticEvent = {
3083
+ sender: {
3084
+ sender_id: {
3085
+ open_id: operatorOpenId,
3086
+ user_id: event.operator?.operator_id?.user_id,
3087
+ union_id: event.operator?.operator_id?.union_id
3088
+ },
3089
+ sender_type: "user"
3090
+ },
3091
+ message: {
3092
+ message_id: `bot-menu:${eventKey}:${event.timestamp ?? Date.now()}`,
3093
+ chat_id: `p2p:${operatorOpenId}`,
3094
+ chat_type: "p2p",
3095
+ message_type: "text",
3096
+ content: JSON.stringify({ text: `/menu ${eventKey}` })
3097
+ }
3098
+ };
3099
+ const syntheticMessageId = syntheticEvent.message.message_id;
3100
+ if (await hasProcessedFeishuMessage(syntheticMessageId, accountId, log)) {
3101
+ log(`feishu[${accountId}]: dropping duplicate bot-menu event for ${syntheticMessageId}`);
3102
+ return;
3103
+ }
3104
+ if (!tryBeginFeishuMessageProcessing(syntheticMessageId, accountId)) {
3105
+ log(`feishu[${accountId}]: dropping in-flight bot-menu event for ${syntheticMessageId}`);
3106
+ return;
3107
+ }
3108
+ const handleLegacyMenu = () => handleFeishuMessage({
3109
+ cfg,
3110
+ event: syntheticEvent,
3111
+ botOpenId: botOpenIds.get(accountId),
3112
+ botName: botNames.get(accountId),
3113
+ runtime,
3114
+ chatHistories,
3115
+ accountId,
3116
+ processingClaimHeld: true
3117
+ });
3118
+ const promise = maybeHandleFeishuQuickActionMenu({
3119
+ cfg,
3120
+ eventKey,
3121
+ operatorOpenId,
3122
+ runtime,
3123
+ accountId
3124
+ }).then(async (handledMenu) => {
3125
+ if (handledMenu) {
3126
+ await recordProcessedFeishuMessage(syntheticMessageId, accountId, log);
3127
+ releaseFeishuMessageProcessing(syntheticMessageId, accountId);
3128
+ return;
3129
+ }
3130
+ return await handleLegacyMenu();
3131
+ }).catch((err) => {
3132
+ releaseFeishuMessageProcessing(syntheticMessageId, accountId);
3133
+ throw err;
3134
+ });
3135
+ if (fireAndForget) {
3136
+ promise.catch((err) => {
3137
+ error(`feishu[${accountId}]: error handling bot menu event: ${String(err)}`);
3138
+ });
3139
+ return;
3140
+ }
3141
+ await promise;
3142
+ } catch (err) {
3143
+ error(`feishu[${accountId}]: error handling bot menu event: ${String(err)}`);
3144
+ }
3145
+ },
3146
+ "card.action.trigger": async (data) => {
3147
+ try {
3148
+ const promise = handleFeishuCardAction({
3149
+ cfg,
3150
+ event: data,
3151
+ botOpenId: botOpenIds.get(accountId),
3152
+ runtime,
3153
+ accountId
3154
+ });
3155
+ if (fireAndForget) promise.catch((err) => {
3156
+ error(`feishu[${accountId}]: error handling card action: ${String(err)}`);
3157
+ });
3158
+ else await promise;
3159
+ } catch (err) {
3160
+ error(`feishu[${accountId}]: error handling card action: ${String(err)}`);
3161
+ }
3162
+ }
3163
+ });
3164
+ }
3165
+ async function monitorSingleAccount(params) {
3166
+ const { cfg, account, runtime, abortSignal } = params;
3167
+ const { accountId } = account;
3168
+ const log = runtime?.log ?? console.log;
3169
+ const botOpenIdSource = params.botOpenIdSource ?? { kind: "fetch" };
3170
+ const botIdentity = botOpenIdSource.kind === "prefetched" ? {
3171
+ botOpenId: botOpenIdSource.botOpenId,
3172
+ botName: botOpenIdSource.botName
3173
+ } : await fetchBotIdentityForMonitor(account, {
3174
+ runtime,
3175
+ abortSignal
3176
+ });
3177
+ const botOpenId = botIdentity.botOpenId;
3178
+ const botName = botIdentity.botName?.trim();
3179
+ botOpenIds.set(accountId, botOpenId ?? "");
3180
+ if (botName) botNames.set(accountId, botName);
3181
+ else botNames.delete(accountId);
3182
+ log(`feishu[${accountId}]: bot open_id resolved: ${botOpenId ?? "unknown"}`);
3183
+ const connectionMode = account.config.connectionMode ?? "websocket";
3184
+ if (connectionMode === "webhook" && !account.verificationToken?.trim()) throw new Error(`Feishu account "${accountId}" webhook mode requires verificationToken`);
3185
+ if (connectionMode === "webhook" && !account.encryptKey?.trim()) throw new Error(`Feishu account "${accountId}" webhook mode requires encryptKey`);
3186
+ const warmupCount = await warmupDedupFromDisk(accountId, log);
3187
+ if (warmupCount > 0) log(`feishu[${accountId}]: dedup warmup loaded ${warmupCount} entries from disk`);
3188
+ let threadBindingManager = null;
3189
+ try {
3190
+ const eventDispatcher = createEventDispatcher(account);
3191
+ const chatHistories = /* @__PURE__ */ new Map();
3192
+ threadBindingManager = createFeishuThreadBindingManager({
3193
+ accountId,
3194
+ cfg
3195
+ });
3196
+ registerEventHandlers(eventDispatcher, {
3197
+ cfg,
3198
+ accountId,
3199
+ runtime,
3200
+ chatHistories,
3201
+ fireAndForget: true
3202
+ });
3203
+ if (connectionMode === "webhook") return await monitorWebhook({
3204
+ account,
3205
+ accountId,
3206
+ runtime,
3207
+ abortSignal,
3208
+ eventDispatcher
3209
+ });
3210
+ return await monitorWebSocket({
3211
+ account,
3212
+ accountId,
3213
+ runtime,
3214
+ abortSignal,
3215
+ eventDispatcher
3216
+ });
3217
+ } finally {
3218
+ threadBindingManager?.stop();
3219
+ }
3220
+ }
3221
+ //#endregion
3222
+ //#region extensions/feishu/src/monitor.ts
3223
+ async function monitorFeishuProvider(opts = {}) {
3224
+ const cfg = opts.config;
3225
+ if (!cfg) throw new Error("Config is required for Feishu monitor");
3226
+ const log = opts.runtime?.log ?? console.log;
3227
+ if (opts.accountId) {
3228
+ const account = resolveFeishuAccount({
3229
+ cfg,
3230
+ accountId: opts.accountId
3231
+ });
3232
+ if (!account.enabled || !account.configured) throw new Error(`Feishu account "${opts.accountId}" not configured or disabled`);
3233
+ return monitorSingleAccount({
3234
+ cfg,
3235
+ account,
3236
+ runtime: opts.runtime,
3237
+ abortSignal: opts.abortSignal
3238
+ });
3239
+ }
3240
+ const accounts = listEnabledFeishuAccounts(cfg);
3241
+ if (accounts.length === 0) throw new Error("No enabled Feishu accounts configured");
3242
+ log(`feishu: starting ${accounts.length} account(s): ${accounts.map((a) => a.accountId).join(", ")}`);
3243
+ const monitorPromises = [];
3244
+ for (const account of accounts) {
3245
+ if (opts.abortSignal?.aborted) {
3246
+ log("feishu: abort signal received during startup preflight; stopping startup");
3247
+ break;
3248
+ }
3249
+ const { botOpenId, botName } = await fetchBotIdentityForMonitor(account, {
3250
+ runtime: opts.runtime,
3251
+ abortSignal: opts.abortSignal
3252
+ });
3253
+ if (opts.abortSignal?.aborted) {
3254
+ log("feishu: abort signal received during startup preflight; stopping startup");
3255
+ break;
3256
+ }
3257
+ monitorPromises.push(monitorSingleAccount({
3258
+ cfg,
3259
+ account,
3260
+ runtime: opts.runtime,
3261
+ abortSignal: opts.abortSignal,
3262
+ botOpenIdSource: {
3263
+ kind: "prefetched",
3264
+ botOpenId,
3265
+ botName
3266
+ }
3267
+ }));
3268
+ }
3269
+ await Promise.all(monitorPromises);
3270
+ }
3271
+ //#endregion
3272
+ export { resolveReactionSyntheticEvent as n, monitorFeishuProvider as t };