@openclaw/feishu 2026.9.8 → 2026.10.1-beta.2

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 (225) hide show
  1. package/dist/.setup/{channel-DV4hM2Uf.mjs → channel-CX62T71S.mjs} +146 -245
  2. package/dist/.setup/{channel.runtime-CXQcH5zZ.mjs → channel.runtime-COiaq-Rv.mjs} +6 -12
  3. package/dist/.setup/{chat-D8MlFAZi.mjs → chat-BdyvImsY.mjs} +6 -9
  4. package/dist/.setup/{client-BYG-_IZl.mjs → client-BsBVWJzN.mjs} +1 -1
  5. package/dist/.setup/{doctor-contract-3XC0vbIw.mjs → doctor-contract-B1B9ogdd.mjs} +212 -27
  6. package/dist/.setup/{monitor-D_rsHBZ6.mjs → monitor-7DvwUs4Y.mjs} +5 -6
  7. package/dist/.setup/{monitor.account-DvvY7i6k.mjs → monitor.account-7xVu7XWY.mjs} +190 -393
  8. package/dist/.setup/{probe-_ViqSi0j.mjs → probe-B9o7iey6.mjs} +13 -39
  9. package/dist/.setup/{reply-delivery-result-COAjaukc.mjs → reply-delivery-result-Bt-BWBEA.mjs} +151 -297
  10. package/dist/.setup/{setup-api-C4S5I3ac.mjs → setup-api-DmzX9S01.mjs} +1 -1
  11. package/dist/.setup/{subagent-hooks-BaFoMu8W.mjs → subagent-hooks-CUXg0pC-.mjs} +5 -11
  12. package/dist/.setup/{thread-bindings-EdLXPXzw.mjs → thread-bindings-jW2x5VuN.mjs} +23 -41
  13. package/dist/api.js +234 -297
  14. package/dist/channel-plugin-api.js +1 -1
  15. package/dist/doctor-contract-api.js +2 -2
  16. package/dist/session-binding-contract-api.js +1 -1
  17. package/dist/setup-api.js +1 -1
  18. package/dist/setup-entry.js +1 -1
  19. package/dist/subagent-hooks-api.js +1 -1
  20. package/node_modules/@openclaw/fs-safe/CHANGELOG.md +95 -0
  21. package/node_modules/@openclaw/fs-safe/README.md +70 -379
  22. package/node_modules/@openclaw/fs-safe/dist/absolute-path.js +35 -51
  23. package/node_modules/@openclaw/fs-safe/dist/advanced.d.ts +2 -0
  24. package/node_modules/@openclaw/fs-safe/dist/advanced.js +1 -0
  25. package/node_modules/@openclaw/fs-safe/dist/archive-input.js +2 -0
  26. package/node_modules/@openclaw/fs-safe/dist/archive-parser.wasm +0 -0
  27. package/node_modules/@openclaw/fs-safe/dist/archive-staging.d.ts +1 -1
  28. package/node_modules/@openclaw/fs-safe/dist/archive-staging.js +9 -10
  29. package/node_modules/@openclaw/fs-safe/dist/archive.js +2 -5
  30. package/node_modules/@openclaw/fs-safe/dist/atomic-io.d.ts +51 -0
  31. package/node_modules/@openclaw/fs-safe/dist/atomic-io.js +242 -0
  32. package/node_modules/@openclaw/fs-safe/dist/config.d.ts +1 -1
  33. package/node_modules/@openclaw/fs-safe/dist/config.js +1 -1
  34. package/node_modules/@openclaw/fs-safe/dist/copy-file-input.d.ts +1 -1
  35. package/node_modules/@openclaw/fs-safe/dist/copy-file-input.js +2 -2
  36. package/node_modules/@openclaw/fs-safe/dist/copy-tree-portable.js +2 -0
  37. package/node_modules/@openclaw/fs-safe/dist/create.js +12 -5
  38. package/node_modules/@openclaw/fs-safe/dist/directory-guard.d.ts +11 -0
  39. package/node_modules/@openclaw/fs-safe/dist/directory-guard.js +4 -7
  40. package/node_modules/@openclaw/fs-safe/dist/entry-publication-types.d.ts +55 -0
  41. package/node_modules/@openclaw/fs-safe/dist/entry-publication-types.js +1 -0
  42. package/node_modules/@openclaw/fs-safe/dist/entry-publication.d.ts +8 -0
  43. package/node_modules/@openclaw/fs-safe/dist/entry-publication.js +262 -0
  44. package/node_modules/@openclaw/fs-safe/dist/exclusive-create.d.ts +3 -0
  45. package/node_modules/@openclaw/fs-safe/dist/exclusive-create.js +22 -0
  46. package/node_modules/@openclaw/fs-safe/dist/file-cleanup.d.ts +1 -6
  47. package/node_modules/@openclaw/fs-safe/dist/file-cleanup.js +3 -6
  48. package/node_modules/@openclaw/fs-safe/dist/file-identity.js +3 -6
  49. package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-io.js +2 -2
  50. package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-mutation.js +9 -0
  51. package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root.js +4 -6
  52. package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-stale-admission.js +1 -1
  53. package/node_modules/@openclaw/fs-safe/dist/file-lock-sync.js +8 -0
  54. package/node_modules/@openclaw/fs-safe/dist/file-store-boundary.js +2 -0
  55. package/node_modules/@openclaw/fs-safe/dist/file-store-sync-write.js +20 -18
  56. package/node_modules/@openclaw/fs-safe/dist/file-store.js +4 -10
  57. package/node_modules/@openclaw/fs-safe/dist/fs.d.ts +2 -10
  58. package/node_modules/@openclaw/fs-safe/dist/fs.js +2 -10
  59. package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.d.ts +3 -4
  60. package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.js +6 -18
  61. package/node_modules/@openclaw/fs-safe/dist/guest-dispatch-python.js +1 -1
  62. package/node_modules/@openclaw/fs-safe/dist/guest-native-python.js +0 -2
  63. package/node_modules/@openclaw/fs-safe/dist/guest.js +3 -9
  64. package/node_modules/@openclaw/fs-safe/dist/index.d.ts +1 -1
  65. package/node_modules/@openclaw/fs-safe/dist/index.js +1 -1
  66. package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-directory.js +1 -5
  67. package/node_modules/@openclaw/fs-safe/dist/json.js +19 -37
  68. package/node_modules/@openclaw/fs-safe/dist/move-path.js +2 -0
  69. package/node_modules/@openclaw/fs-safe/dist/mutation-authority.d.ts +1 -0
  70. package/node_modules/@openclaw/fs-safe/dist/mutation-authority.js +9 -1
  71. package/node_modules/@openclaw/fs-safe/dist/native-binding.d.ts +47 -2
  72. package/node_modules/@openclaw/fs-safe/dist/native-config.d.ts +1 -9
  73. package/node_modules/@openclaw/fs-safe/dist/native-config.js +6 -40
  74. package/node_modules/@openclaw/fs-safe/dist/native-parent-admission.d.ts +2 -0
  75. package/node_modules/@openclaw/fs-safe/dist/native-parent-admission.js +5 -2
  76. package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.js +11 -316
  77. package/node_modules/@openclaw/fs-safe/dist/native-policy-parent-windows.d.ts +7 -7
  78. package/node_modules/@openclaw/fs-safe/dist/native-policy-parent-windows.js +28 -175
  79. package/node_modules/@openclaw/fs-safe/dist/native-policy-parent.d.ts +15 -0
  80. package/node_modules/@openclaw/fs-safe/dist/native-policy-parent.js +418 -0
  81. package/node_modules/@openclaw/fs-safe/dist/native-rename-outcome.js +9 -4
  82. package/node_modules/@openclaw/fs-safe/dist/native-staged-file.js +17 -13
  83. package/node_modules/@openclaw/fs-safe/dist/native-staged-symlink.js +6 -24
  84. package/node_modules/@openclaw/fs-safe/dist/native.js +5 -1
  85. package/node_modules/@openclaw/fs-safe/dist/path-case.js +10 -9
  86. package/node_modules/@openclaw/fs-safe/dist/path-scope-lexical.js +4 -1
  87. package/node_modules/@openclaw/fs-safe/dist/path-segment-route.d.ts +1 -0
  88. package/node_modules/@openclaw/fs-safe/dist/path-segment-route.js +3 -0
  89. package/node_modules/@openclaw/fs-safe/dist/path.js +4 -1
  90. package/node_modules/@openclaw/fs-safe/dist/permissions-windows.d.ts +0 -1
  91. package/node_modules/@openclaw/fs-safe/dist/pinned-mutation-admission.js +1 -3
  92. package/node_modules/@openclaw/fs-safe/dist/pinned-write-staged.js +2 -0
  93. package/node_modules/@openclaw/fs-safe/dist/pinned-write.js +9 -10
  94. package/node_modules/@openclaw/fs-safe/dist/private-producer-handoff.js +3 -6
  95. package/node_modules/@openclaw/fs-safe/dist/publish-copy-stage.js +2 -2
  96. package/node_modules/@openclaw/fs-safe/dist/publish-file.js +4 -3
  97. package/node_modules/@openclaw/fs-safe/dist/replace-file-buffer.d.ts +3 -4
  98. package/node_modules/@openclaw/fs-safe/dist/replace-file-buffer.js +18 -32
  99. package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.d.ts +5 -17
  100. package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.js +92 -230
  101. package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.d.ts +4 -15
  102. package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.js +22 -63
  103. package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.d.ts +9 -34
  104. package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.js +78 -83
  105. package/node_modules/@openclaw/fs-safe/dist/replace-file-destination.d.ts +18 -20
  106. package/node_modules/@openclaw/fs-safe/dist/replace-file-destination.js +64 -98
  107. package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.d.ts +16 -33
  108. package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.js +61 -200
  109. package/node_modules/@openclaw/fs-safe/dist/replace-file-types.d.ts +1 -6
  110. package/node_modules/@openclaw/fs-safe/dist/replace-file.js +76 -216
  111. package/node_modules/@openclaw/fs-safe/dist/root-boundary.js +14 -24
  112. package/node_modules/@openclaw/fs-safe/dist/root-context.d.ts +1 -4
  113. package/node_modules/@openclaw/fs-safe/dist/root-context.js +4 -19
  114. package/node_modules/@openclaw/fs-safe/dist/root-create-native.d.ts +52 -0
  115. package/node_modules/@openclaw/fs-safe/dist/root-create-native.js +350 -0
  116. package/node_modules/@openclaw/fs-safe/dist/root-directory-list-types.d.ts +35 -0
  117. package/node_modules/@openclaw/fs-safe/dist/root-directory-list-types.js +1 -0
  118. package/node_modules/@openclaw/fs-safe/dist/root-directory-list.d.ts +2 -27
  119. package/node_modules/@openclaw/fs-safe/dist/root-directory-list.js +31 -28
  120. package/node_modules/@openclaw/fs-safe/dist/root-directory.js +1 -4
  121. package/node_modules/@openclaw/fs-safe/dist/root-errors.js +34 -0
  122. package/node_modules/@openclaw/fs-safe/dist/root-file.js +9 -21
  123. package/node_modules/@openclaw/fs-safe/dist/root-impl.js +105 -37
  124. package/node_modules/@openclaw/fs-safe/dist/root-move-noreplace.d.ts +7 -2
  125. package/node_modules/@openclaw/fs-safe/dist/root-move-noreplace.js +67 -38
  126. package/node_modules/@openclaw/fs-safe/dist/root-observed-path.d.ts +1 -1
  127. package/node_modules/@openclaw/fs-safe/dist/root-observed-path.js +0 -2
  128. package/node_modules/@openclaw/fs-safe/dist/root-options.d.ts +2 -3
  129. package/node_modules/@openclaw/fs-safe/dist/root-path-existing.js +3 -1
  130. package/node_modules/@openclaw/fs-safe/dist/root-path-stat.js +68 -85
  131. package/node_modules/@openclaw/fs-safe/dist/root-path.js +6 -1
  132. package/node_modules/@openclaw/fs-safe/dist/root-paths-lexical.d.ts +4 -0
  133. package/node_modules/@openclaw/fs-safe/dist/root-paths-lexical.js +1 -1
  134. package/node_modules/@openclaw/fs-safe/dist/root-paths.js +4 -9
  135. package/node_modules/@openclaw/fs-safe/dist/root-remove-native.d.ts +4 -0
  136. package/node_modules/@openclaw/fs-safe/dist/root-remove-native.js +311 -0
  137. package/node_modules/@openclaw/fs-safe/dist/root-remove.d.ts +11 -0
  138. package/node_modules/@openclaw/fs-safe/dist/root-remove.js +3 -1
  139. package/node_modules/@openclaw/fs-safe/dist/root-walk.d.ts +2 -2
  140. package/node_modules/@openclaw/fs-safe/dist/root-walk.js +1 -3
  141. package/node_modules/@openclaw/fs-safe/dist/root-write-admission.d.ts +3 -3
  142. package/node_modules/@openclaw/fs-safe/dist/root-write-admission.js +8 -10
  143. package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.d.ts +0 -1
  144. package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.js +0 -4
  145. package/node_modules/@openclaw/fs-safe/dist/secret-file.js +12 -9
  146. package/node_modules/@openclaw/fs-safe/dist/secure-temp-dir.d.ts +0 -2
  147. package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.js +2 -0
  148. package/node_modules/@openclaw/fs-safe/dist/sibling-temp.js +7 -4
  149. package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-acquire.js +13 -6
  150. package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.d.ts +0 -3
  151. package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js +5 -23
  152. package/node_modules/@openclaw/fs-safe/dist/staged-file-settlement.d.ts +2 -1
  153. package/node_modules/@openclaw/fs-safe/dist/staged-file-settlement.js +11 -6
  154. package/node_modules/@openclaw/fs-safe/dist/temp-cleanup.js +1 -8
  155. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-child-admission.d.ts +1 -1
  156. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-child-admission.js +2 -9
  157. package/node_modules/@openclaw/fs-safe/dist/text-atomic.d.ts +1 -6
  158. package/node_modules/@openclaw/fs-safe/dist/trash.js +6 -2
  159. package/node_modules/@openclaw/fs-safe/dist/walk.js +100 -46
  160. package/node_modules/@openclaw/fs-safe/dist/watch-hints.d.ts +7 -0
  161. package/node_modules/@openclaw/fs-safe/dist/watch-hints.js +235 -19
  162. package/node_modules/@openclaw/fs-safe/dist/watch-native.d.ts +21 -2
  163. package/node_modules/@openclaw/fs-safe/dist/watch-native.js +21 -3
  164. package/node_modules/@openclaw/fs-safe/dist/watch-rescan.d.ts +6 -0
  165. package/node_modules/@openclaw/fs-safe/dist/watch-rescan.js +111 -0
  166. package/node_modules/@openclaw/fs-safe/dist/watch-scan.d.ts +13 -0
  167. package/node_modules/@openclaw/fs-safe/dist/watch-scan.js +27 -4
  168. package/node_modules/@openclaw/fs-safe/dist/watch-stream.js +2 -0
  169. package/node_modules/@openclaw/fs-safe/dist/watch.js +131 -40
  170. package/node_modules/@openclaw/fs-safe/dist/windows-path-alias.d.ts +8 -0
  171. package/node_modules/@openclaw/fs-safe/dist/windows-path-alias.js +24 -6
  172. package/node_modules/@openclaw/fs-safe/dist/windows-path-syntax.d.ts +13 -0
  173. package/node_modules/@openclaw/fs-safe/dist/windows-path-syntax.js +51 -0
  174. package/node_modules/@openclaw/fs-safe/docs/advanced.md +4 -0
  175. package/node_modules/@openclaw/fs-safe/docs/atomic.md +4 -1
  176. package/node_modules/@openclaw/fs-safe/docs/config.md +6 -14
  177. package/node_modules/@openclaw/fs-safe/docs/contributing.md +4 -14
  178. package/node_modules/@openclaw/fs-safe/docs/durability.md +6 -29
  179. package/node_modules/@openclaw/fs-safe/docs/entry-publication.md +146 -0
  180. package/node_modules/@openclaw/fs-safe/docs/errors.md +16 -0
  181. package/node_modules/@openclaw/fs-safe/docs/file-store.md +28 -5
  182. package/node_modules/@openclaw/fs-safe/docs/index.md +2 -31
  183. package/node_modules/@openclaw/fs-safe/docs/install.md +10 -31
  184. package/node_modules/@openclaw/fs-safe/docs/json.md +1 -1
  185. package/node_modules/@openclaw/fs-safe/docs/local-roots.md +0 -1
  186. package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.5.md +12 -12
  187. package/node_modules/@openclaw/fs-safe/docs/native-helper.md +35 -96
  188. package/node_modules/@openclaw/fs-safe/docs/native.md +22 -20
  189. package/node_modules/@openclaw/fs-safe/docs/path.md +1 -1
  190. package/node_modules/@openclaw/fs-safe/docs/permissions.md +1 -2
  191. package/node_modules/@openclaw/fs-safe/docs/public-api.md +1 -2
  192. package/node_modules/@openclaw/fs-safe/docs/reading.md +1 -2
  193. package/node_modules/@openclaw/fs-safe/docs/root.md +26 -184
  194. package/node_modules/@openclaw/fs-safe/docs/secret-file.md +1 -1
  195. package/node_modules/@openclaw/fs-safe/docs/security-model.md +115 -3
  196. package/node_modules/@openclaw/fs-safe/docs/store.md +2 -2
  197. package/node_modules/@openclaw/fs-safe/docs/temp.md +29 -65
  198. package/node_modules/@openclaw/fs-safe/docs/testing.md +90 -58
  199. package/node_modules/@openclaw/fs-safe/docs/types.md +3 -16
  200. package/node_modules/@openclaw/fs-safe/docs/walk.md +33 -5
  201. package/node_modules/@openclaw/fs-safe/docs/watch.md +96 -14
  202. package/node_modules/@openclaw/fs-safe/docs/writing.md +172 -16
  203. package/node_modules/@openclaw/fs-safe/package.json +10 -10
  204. package/node_modules/@openclaw/fs-safe-darwin-arm64/fs-safe-native.node +0 -0
  205. package/node_modules/@openclaw/fs-safe-darwin-arm64/package.json +1 -1
  206. package/node_modules/@openclaw/fs-safe-darwin-x64/fs-safe-native.node +0 -0
  207. package/node_modules/@openclaw/fs-safe-darwin-x64/package.json +1 -1
  208. package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/fs-safe-native.node +0 -0
  209. package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/package.json +1 -1
  210. package/node_modules/@openclaw/fs-safe-linux-arm64-musl/fs-safe-native.node +0 -0
  211. package/node_modules/@openclaw/fs-safe-linux-arm64-musl/package.json +1 -1
  212. package/node_modules/@openclaw/fs-safe-linux-x64-gnu/fs-safe-native.node +0 -0
  213. package/node_modules/@openclaw/fs-safe-linux-x64-gnu/package.json +1 -1
  214. package/node_modules/@openclaw/fs-safe-linux-x64-musl/fs-safe-native.node +0 -0
  215. package/node_modules/@openclaw/fs-safe-linux-x64-musl/package.json +1 -1
  216. package/node_modules/@openclaw/fs-safe-win32-x64-msvc/fs-safe-native.node +0 -0
  217. package/node_modules/@openclaw/fs-safe-win32-x64-msvc/package.json +1 -1
  218. package/package.json +5 -5
  219. package/skills/feishu-wiki/SKILL.md +1 -1
  220. package/dist/.setup/accounts-wRqItHug.mjs +0 -206
  221. package/node_modules/@openclaw/fs-safe/dist/watch-alias.d.ts +0 -6
  222. package/node_modules/@openclaw/fs-safe/dist/watch-alias.js +0 -88
  223. package/node_modules/@openclaw/fs-safe/docs/mutation-policy-proof.md +0 -69
  224. package/node_modules/@openclaw/fs-safe/docs/private-file-store.md +0 -68
  225. package/node_modules/@openclaw/fs-safe/docs/test-hooks.md +0 -110
@@ -1,21 +1,20 @@
1
- import { a as normalizeFeishuWebhookPath, o as normalizeFeishuExternalKey } from "./doctor-contract-3XC0vbIw.mjs";
2
- import { c as resolveFeishuRuntimeAccount, s as resolveFeishuAccount } from "./accounts-wRqItHug.mjs";
1
+ import { h as resolveFeishuRuntimeAccount, m as resolveFeishuAccount, o as normalizeFeishuWebhookPath, s as normalizeFeishuExternalKey } from "./doctor-contract-B1B9ogdd.mjs";
3
2
  import { o as resolveConfiguredFeishuGroupSessionScope, t as buildFeishuConversationId, u as resolveReceiveIdType } from "./conversation-id-C1ofUfU8.mjs";
4
- import { c as resolveFeishuLegacyWebhookListener, l as gateway_config_runtime_exports, s as describeFeishuWebhookPathConflict } from "./channel-DV4hM2Uf.mjs";
5
- import { A as sendMessageFeishu, B as parsePostContent, D as getMessageFeishu, Dt as resolveFeishuGroupConfig, Et as resolveFeishuDmIngressAccess, F as isFeishuBroadcastMention, Ft as buildFeishuCardActionTextFallback, G as deliverCommentThreadText, H as buildFeishuMediaFallbackText, I as isMentionForwardRequest, It as createFeishuCardInteractionEnvelope, L as isFeishuGroupChatType, Lt as decodeFeishuCardAction, Mt as normalizeFeishuChatType, N as formatFeishuMediaContent, Nt as resolveFeishuChatType, O as listFeishuThreadMessages, Ot as resolveFeishuGroupConversationIngressAccess, P as extractMentionTargets, R as normalizeFeishuEventChatType, S as sendMediaFeishu, T as chunkFeishuCardMarkdown, Tt as normalizeFeishuAllowEntry, U as resolveFeishuIdentityEmoji, a as shouldSendNoVisibleReplyFallback, at as requestFeishuApi, b as withinCardTableLimit, d as consumeFeishuPresentationFallbackMarker, et as createCommentTypingReactionLifecycle, ft as chunkFeishuPostMarkdown, ht as shouldUseFeishuCard, i as noVisibleFeishuReplyDelivery, it as parseCommentContentElements, j as sendStructuredCardFeishu, jt as resolveFeishuReplyPolicy, k as sendCardFeishu, kt as resolveFeishuGroupSenderActivationIngressAccess, n as createFeishuReplyDeliveryResult, nt as extractReplyText, ot as buildFeishuCommentTarget, pt as materializeFeishuPostMarkdownSoftBreaks, r as mergeFeishuReplyDeliveryResults, st as normalizeCommentFileType, t as createFeishuPartialReplyDeliveryError, tt as encodeQuery, u as buildFeishuPresentationFallback, ut as resolveFeishuCardTemplate, v as renderFeishuReplyPayload, w as shouldSuppressFeishuTextForVoiceMedia, wt as hasExplicitFeishuGroupConfig, x as saveMessageResourceFeishu, y as resolveFeishuRichReply, z as parseInteractiveCardContent } from "./reply-delivery-result-COAjaukc.mjs";
3
+ import { c as resolveFeishuLegacyWebhookListener, l as gateway_config_runtime_exports, s as describeFeishuWebhookPathConflict } from "./channel-CX62T71S.mjs";
4
+ import { A as sendMessageFeishu, At as resolveFeishuGroupSenderActivationIngressAccess, B as parsePostContent, D as getMessageFeishu, Dt as resolveFeishuDmIngressAccess, Et as normalizeFeishuAllowEntry, F as isFeishuBroadcastMention, G as deliverCommentThreadText, H as buildFeishuMediaFallbackText, I as isMentionForwardRequest, It as createFeishuCardInteractionEnvelope, L as isFeishuGroupChatType, Lt as decodeFeishuCardAction, Mt as resolveFeishuReplyPolicy, N as formatFeishuMediaContent, Nt as normalizeFeishuChatType, O as listFeishuThreadMessages, Ot as resolveFeishuGroupConfig, P as extractMentionTargets, Pt as resolveFeishuChatType, R as normalizeFeishuEventChatType, S as sendMediaFeishu, T as chunkFeishuCardMarkdown, Tt as hasExplicitFeishuGroupConfig, U as resolveFeishuIdentityEmoji, a as shouldSendNoVisibleReplyFallback, at as requestFeishuApi, b as withinCardTableLimit, d as consumeFeishuPresentationFallbackMarker, et as createCommentTypingReactionLifecycle, ft as chunkFeishuPostMarkdown, ht as shouldUseFeishuCard, i as noVisibleFeishuReplyDelivery, it as parseCommentContentElements, j as sendStructuredCardFeishu, k as sendCardFeishu, kt as resolveFeishuGroupConversationIngressAccess, n as createFeishuReplyDeliveryResult, nt as extractReplyText, ot as buildFeishuCommentTarget, pt as materializeFeishuPostMarkdownSoftBreaks, r as mergeFeishuReplyDeliveryResults, st as normalizeCommentFileType, t as createFeishuPartialReplyDeliveryError, tt as encodeQuery, u as buildFeishuPresentationFallback, ut as resolveFeishuCardTemplate, v as renderFeishuReplyPayload, w as shouldSuppressFeishuTextForVoiceMedia, x as saveMessageResourceFeishu, y as resolveFeishuRichReply, z as parseInteractiveCardContent } from "./reply-delivery-result-Bt-BWBEA.mjs";
6
5
  import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.mjs";
7
- import { a as getFeishuUserAgent, f as resolveConfiguredHttpTimeoutMs, i as createFeishuWSClient, n as createEventDispatcher, r as createFeishuClient } from "./client-BYG-_IZl.mjs";
8
- import { r as getChatInfo } from "./chat-D8MlFAZi.mjs";
9
- import { t as createFeishuThreadBindingManager } from "./thread-bindings-EdLXPXzw.mjs";
6
+ import { a as getFeishuUserAgent, f as resolveConfiguredHttpTimeoutMs, i as createFeishuWSClient, n as createEventDispatcher, r as createFeishuClient } from "./client-BsBVWJzN.mjs";
7
+ import { r as getChatInfo } from "./chat-BdyvImsY.mjs";
8
+ import { t as createFeishuThreadBindingManager } from "./thread-bindings-jW2x5VuN.mjs";
10
9
  import { evaluateSupplementalContextVisibility, normalizeAgentId as normalizeAgentId$1, resolveChannelContextVisibilityMode } from "../runtime-api.js";
11
10
  import { t as readFeishuJsonResponse } from "./json-response-DXajw_FU.mjs";
12
- import { a as waitForAbortableDelay, i as raceWithTimeoutAndAbort } from "./probe-_ViqSi0j.mjs";
13
- import { t as fetchBotIdentityForMonitor } from "./monitor-D_rsHBZ6.mjs";
11
+ import { a as waitForAbortableDelay, i as raceWithTimeoutAndAbort } from "./probe-B9o7iey6.mjs";
12
+ import { t as fetchBotIdentityForMonitor } from "./monitor-7DvwUs4Y.mjs";
14
13
  import { resolveAgentConfig } from "openclaw/plugin-sdk/agent-scope-runtime";
15
14
  import { DEFAULT_INGRESS_ADOPTION_STALL_MS, bindIngressLifecycleToReplyOptions, createChannelIngressError, createChannelIngressMonitor, createChannelMessageReplyPipeline, createReplyPrefixContext, formatChannelProgressDraftLineForEntry, resolveAgentOutboundIdentity, resolveChannelPreviewStreamMode, resolveChannelStreamingBlockEnabled, waitUntilAbort } from "openclaw/plugin-sdk/channel-outbound";
16
15
  import { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing";
17
16
  import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute } from "openclaw/plugin-sdk/conversation-runtime";
18
- import { collectErrorGraphCandidates, extractErrorCode, formatErrorMessage, toStringifiedError } from "openclaw/plugin-sdk/error-runtime";
17
+ import { collectErrorGraphCandidates, formatErrorMessage, toStringifiedError } from "openclaw/plugin-sdk/error-runtime";
19
18
  import { asDateTimestampMs, isFutureDateTimestampMs, parseStrictNonNegativeInteger, resolveDateTimestampMs, resolveExpiresAtMsFromDurationMs, resolveExpiresAtMsFromDurationSeconds, resolvePromptHistoryLimit, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
20
19
  import { asBoolean, asNullableRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeNullableString, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeTrimmedStringList, readStringValue, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
21
20
  import { stripReasoningTagsFromText } from "openclaw/plugin-sdk/text-chunking";
@@ -37,20 +36,19 @@ import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
37
36
  import { escapeRegExp, sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
38
37
  import * as crypto$1 from "node:crypto";
39
38
  import crypto, { createHash } from "node:crypto";
40
- import { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
41
39
  import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
40
+ import { raceWithTimeout } from "openclaw/plugin-sdk/time-runtime";
41
+ import { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
42
42
  import { createChannelReplayGuard } from "openclaw/plugin-sdk/persistent-dedupe";
43
43
  import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-writes";
44
44
  import { formatReasoningMessage, resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
45
45
  import { logTypingFailure } from "openclaw/plugin-sdk/channel-feedback";
46
46
  import { getGlobalHookRunner } from "openclaw/plugin-sdk/plugin-runtime";
47
- import * as webhookIngressSdk from "openclaw/plugin-sdk/webhook-ingress";
48
- import { WEBHOOK_RATE_LIMIT_DEFAULTS, applyBasicWebhookRequestGuards, createFixedWindowRateLimiter, createWebhookAnomalyTracker, resolveRequestClientIp } from "openclaw/plugin-sdk/webhook-ingress";
47
+ import { WEBHOOK_RATE_LIMIT_DEFAULTS, applyBasicWebhookRequestGuards, createFixedWindowRateLimiter, createWebhookAnomalyTracker, getWebhookLegacyListener, resolveRequestClientIp } from "openclaw/plugin-sdk/webhook-ingress";
49
48
  import { createRuntimeConfigReader } from "openclaw/plugin-sdk/runtime-config-snapshot";
50
49
  import { channelBlockedPatch, channelReadyPatch } from "openclaw/plugin-sdk/gateway-runtime";
51
50
  import { createWebhookInFlightLimiter, readWebhookBodyOrReject, sendHttpRequestRejection } from "openclaw/plugin-sdk/webhook-request-guards";
52
51
  import { canonicalizeWebhookRouteKey, registerPluginHttpRoute, registerWebhookTarget, resolveSingleWebhookTarget } from "openclaw/plugin-sdk/webhook-targets";
53
- import { createServer } from "node:http";
54
52
  import { isAbortRequestText, isBtwRequestText } from "openclaw/plugin-sdk/command-primitives-runtime";
55
53
  //#region src/channels/mention-gating.ts
56
54
  function resolveBotThreadMentionPolicy(params) {
@@ -199,9 +197,6 @@ function createFeishuBroadcastIngressSettlement(params) {
199
197
  status: "pending"
200
198
  };
201
199
  lanes.add(lane);
202
- const releaseLane = (error) => {
203
- lane.replayClaim?.release({ error });
204
- };
205
200
  return {
206
201
  lifecycle: {
207
202
  abortSignal: params.lifecycle?.abortSignal ?? fallbackAbort.signal,
@@ -234,7 +229,7 @@ function createFeishuBroadcastIngressSettlement(params) {
234
229
  onAbandoned: async () => {
235
230
  if (lane.status === "completed" || lane.status === "failed" || lane.status === "abandoned") return;
236
231
  lane.status = "abandoned";
237
- releaseLane(/* @__PURE__ */ new Error("feishu-broadcast-turn-abandoned"));
232
+ lane.replayClaim?.release({ error: /* @__PURE__ */ new Error("feishu-broadcast-turn-abandoned") });
238
233
  await maybeSettle();
239
234
  }
240
235
  },
@@ -243,13 +238,13 @@ function createFeishuBroadcastIngressSettlement(params) {
243
238
  const error = /* @__PURE__ */ new Error(dispatched ? "feishu broadcast dispatch returned before turn adoption" : "feishu broadcast lane was not dispatched");
244
239
  lane.status = "failed";
245
240
  failures.push(error);
246
- releaseLane(error);
241
+ lane.replayClaim?.release({ error });
247
242
  },
248
243
  onDispatchFailed: async (error) => {
249
244
  failures.push(error);
250
245
  if (lane.status !== "completed") {
251
246
  lane.status = "failed";
252
- releaseLane(error);
247
+ lane.replayClaim?.release({ error });
253
248
  }
254
249
  await maybeSettle();
255
250
  }
@@ -343,9 +338,10 @@ function parseMessageContent(content, messageType) {
343
338
  if (messageType === "share_chat") {
344
339
  if (parsed && typeof parsed === "object") {
345
340
  const share = parsed;
346
- if (typeof share.body === "string" && share.body.trim()) return share.body.trim();
347
- if (typeof share.summary === "string" && share.summary.trim()) return share.summary.trim();
348
- if (typeof share.share_chat_id === "string" && share.share_chat_id.trim()) return `[Forwarded message: ${share.share_chat_id.trim()}]`;
341
+ const text = normalizeOptionalString(share.body) ?? normalizeOptionalString(share.summary);
342
+ if (text) return text;
343
+ const sharedChatId = normalizeOptionalString(share.share_chat_id);
344
+ if (sharedChatId) return `[Forwarded message: ${sharedChatId}]`;
349
345
  }
350
346
  return "[Forwarded message]";
351
347
  }
@@ -447,7 +443,7 @@ async function resolveFeishuMediaList(params) {
447
443
  key: attachment.key,
448
444
  type: attachment.kind,
449
445
  fileName: attachment.kind === "file" ? attachment.fileName : void 0,
450
- kind: attachment.kind === "image" ? "image" : "video",
446
+ kind: attachment.kind === "image" ? "image" : attachment.origin === "top-level" ? "document" : "video",
451
447
  label: `embedded ${attachment.kind} ${attachment.key}`
452
448
  });
453
449
  }
@@ -897,7 +893,7 @@ function parseContentRecord(content) {
897
893
  }
898
894
  }
899
895
  function resolvePostMediaParts(content) {
900
- const { attachments } = parsePostContent(content);
896
+ const { attachments } = parsePostContent(content, { includeTopLevelFiles: false });
901
897
  return ["image", "file"].flatMap((kind) => attachments.filter((attachment) => attachment.kind === kind).map((attachment) => `${kind}_key:${attachment.key}`));
902
898
  }
903
899
  function resolveMessageMediaParts(messageType, content) {
@@ -974,7 +970,7 @@ function resolveDynamicAgentConfig(cfg, accountId) {
974
970
  }
975
971
  function isAtDynamicAgentLimit(cfg, dynamicCfg) {
976
972
  if (dynamicCfg.maxAgents === void 0) return false;
977
- return (cfg.agents?.list ?? []).filter((agent) => agent.id.startsWith("feishu-")).length >= dynamicCfg.maxAgents;
973
+ return Object.keys(cfg.agents?.entries ?? {}).filter((id) => id.startsWith("feishu-")).length >= dynamicCfg.maxAgents;
978
974
  }
979
975
  function resolveDynamicAgentId(accountId, senderOpenId) {
980
976
  if (accountId === "default") return `feishu-${senderOpenId}`;
@@ -1014,7 +1010,7 @@ async function maybeCreateDynamicAgent(params) {
1014
1010
  };
1015
1011
  }
1016
1012
  const agentId = resolveDynamicAgentId(accountId, senderOpenId);
1017
- if (!(currentCfg.agents?.list ?? []).some((agent) => agent.id === agentId) && isAtDynamicAgentLimit(currentCfg, currentDynamicCfg)) {
1013
+ if (!Object.hasOwn(currentCfg.agents?.entries ?? {}, agentId) && isAtDynamicAgentLimit(currentCfg, currentDynamicCfg)) {
1018
1014
  log(`feishu: maxAgents limit (${currentDynamicCfg.maxAgents}) reached, not creating agent for ${senderOpenId}`);
1019
1015
  return {
1020
1016
  created: false,
@@ -1037,7 +1033,7 @@ async function maybeCreateDynamicAgent(params) {
1037
1033
  channelId: "feishu",
1038
1034
  accountId
1039
1035
  })) throw new DynamicAgentMutationSkipped(draft);
1040
- const agentExists = (draft.agents?.list ?? []).some((agent) => agent.id === agentId);
1036
+ const agentExists = Object.hasOwn(draft.agents?.entries ?? {}, agentId);
1041
1037
  if (!agentExists && isAtDynamicAgentLimit(draft, dynamicCfg)) {
1042
1038
  log(`feishu: maxAgents limit (${dynamicCfg.maxAgents}) reached, not creating agent for ${senderOpenId}`);
1043
1039
  throw new DynamicAgentMutationSkipped(draft);
@@ -1055,11 +1051,13 @@ async function maybeCreateDynamicAgent(params) {
1055
1051
  await fs.promises.mkdir(agentDir, { recursive: true });
1056
1052
  draft.agents = {
1057
1053
  ...draft.agents,
1058
- list: [...draft.agents?.list ?? [], {
1059
- id: agentId,
1060
- workspace,
1061
- agentDir
1062
- }]
1054
+ entries: {
1055
+ ...draft.agents?.entries,
1056
+ [agentId]: {
1057
+ workspace,
1058
+ agentDir
1059
+ }
1060
+ }
1063
1061
  };
1064
1062
  } else log(`feishu: agent "${agentId}" exists, adding missing binding for ${senderOpenId}`);
1065
1063
  draft.bindings = [...draft.bindings ?? [], {
@@ -1095,22 +1093,14 @@ async function maybeCreateDynamicAgent(params) {
1095
1093
  agentId: committed.result?.agentId
1096
1094
  };
1097
1095
  }
1098
- /**
1099
- * Resolve a path that may start with ~ to the user's home directory.
1100
- */
1101
1096
  function resolveUserPath(p) {
1102
1097
  if (p.startsWith("~/")) return path.join(os.homedir(), p.slice(2));
1103
1098
  return p;
1104
1099
  }
1105
1100
  //#endregion
1106
- //#region extensions/feishu/src/agent-config.ts
1107
- function resolveFeishuConfigReasoningDefault(cfg, agentId) {
1108
- return resolveAgentConfig(cfg, agentId)?.reasoningDefault ?? cfg.agents?.defaults?.reasoningDefault ?? "off";
1109
- }
1110
- //#endregion
1111
1101
  //#region extensions/feishu/src/reasoning-preview.ts
1112
1102
  function resolveFeishuReasoningPreviewEnabled(params) {
1113
- const configDefault = resolveFeishuConfigReasoningDefault(params.cfg, params.agentId);
1103
+ const configDefault = resolveAgentConfig(params.cfg, params.agentId)?.reasoningDefault ?? params.cfg.agents?.defaults?.reasoningDefault ?? "off";
1114
1104
  if (!params.sessionKey) return configDefault === "stream";
1115
1105
  try {
1116
1106
  const level = getSessionEntry({
@@ -1128,13 +1118,6 @@ function resolveFeishuReasoningPreviewEnabled(params) {
1128
1118
  //#region extensions/feishu/src/reply-dispatcher-state.ts
1129
1119
  const streamingStartBackoffUntilByAccount = /* @__PURE__ */ new Map();
1130
1120
  //#endregion
1131
- //#region extensions/feishu/src/streaming-card-send-mode.ts
1132
- function resolveStreamingCardSendMode(options) {
1133
- if (options?.replyToMessageId) return "reply";
1134
- if (options?.rootId) return "root_create";
1135
- return "create";
1136
- }
1137
- //#endregion
1138
1121
  //#region extensions/feishu/src/streaming-card.ts
1139
1122
  /** Provider finalization failed after a streaming card may already be visible. */
1140
1123
  var FeishuStreamingFinalizationError = class extends Error {
@@ -1223,7 +1206,6 @@ async function getToken(creds, deps) {
1223
1206
  return data.tenant_access_token;
1224
1207
  }
1225
1208
  function truncateSummary(text, max = 50) {
1226
- if (!text) return "";
1227
1209
  const clean = text.replace(/\n/g, " ").trim();
1228
1210
  return clean.length <= max ? clean : sliceUtf16Safe(clean, 0, max - 3) + "...";
1229
1211
  }
@@ -1242,7 +1224,6 @@ function mergeStreamingText(previousText, nextText) {
1242
1224
  for (let overlap = maxOverlap; overlap > 0; overlap -= 1) if (previous.slice(-overlap) === next.slice(0, overlap)) return `${previous}${next.slice(overlap)}`;
1243
1225
  return `${previous}${next}`;
1244
1226
  }
1245
- /** Streaming card session manager */
1246
1227
  var FeishuStreamingSession = class {
1247
1228
  constructor(client, creds, log, deps) {
1248
1229
  this.state = null;
@@ -1336,24 +1317,21 @@ var FeishuStreamingSession = class {
1336
1317
  type: "card",
1337
1318
  data: { card_id: cardId }
1338
1319
  });
1339
- let sendRes;
1340
1320
  const sendOptions = options ?? {};
1341
- const sendMode = resolveStreamingCardSendMode(sendOptions);
1342
- if (sendMode === "reply") sendRes = await requestFeishuApi(() => this.client.im.message.reply({
1321
+ const sendRes = await requestFeishuApi(() => sendOptions.replyToMessageId ? this.client.im.message.reply({
1343
1322
  path: { message_id: sendOptions.replyToMessageId },
1344
1323
  data: {
1345
1324
  msg_type: "interactive",
1346
1325
  content: cardContent,
1347
1326
  ...sendOptions.replyInThread ? { reply_in_thread: true } : {}
1348
1327
  }
1349
- }), "Send card failed");
1350
- else sendRes = await requestFeishuApi(() => this.client.im.message.create({
1328
+ }) : this.client.im.message.create({
1351
1329
  params: { receive_id_type: receiveIdType },
1352
1330
  data: {
1353
1331
  receive_id: receiveId,
1354
1332
  msg_type: "interactive",
1355
1333
  content: cardContent,
1356
- ...sendMode === "root_create" ? { root_id: sendOptions.rootId } : {}
1334
+ ...sendOptions.rootId ? { root_id: sendOptions.rootId } : {}
1357
1335
  }
1358
1336
  }), "Send card failed");
1359
1337
  if (sendRes.code !== 0) throw new Error(`Send card failed: ${sendRes.msg}`);
@@ -1535,10 +1513,9 @@ function isFeishuBackoffError(err) {
1535
1513
  const response = err.response;
1536
1514
  if (response) {
1537
1515
  if (response.status === 429) return true;
1538
- if (typeof response.data?.code === "number" && FEISHU_BACKOFF_CODES.has(response.data.code)) return true;
1516
+ if (getBackoffCodeFromResponse(response.data) !== void 0) return true;
1539
1517
  }
1540
- const code = err.code;
1541
- return typeof code === "number" && FEISHU_BACKOFF_CODES.has(code);
1518
+ return getBackoffCodeFromResponse(err) !== void 0;
1542
1519
  }
1543
1520
  function getBackoffCodeFromResponse(response) {
1544
1521
  if (typeof response !== "object" || response === null) return;
@@ -1628,8 +1605,7 @@ async function removeTypingIndicator(params) {
1628
1605
  //#endregion
1629
1606
  //#region extensions/feishu/src/reply-dispatcher.ts
1630
1607
  function mergeStreamingFinalText(previousText, nextText, appendError) {
1631
- if (!appendError || !previousText) return nextText;
1632
- if (nextText.startsWith(previousText)) return nextText;
1608
+ if (!appendError || !previousText || nextText.startsWith(previousText)) return nextText;
1633
1609
  if (previousText.endsWith(`\n\n${nextText}`)) return previousText;
1634
1610
  return `${previousText}\n\n${nextText}`;
1635
1611
  }
@@ -1656,7 +1632,6 @@ function normalizeEpochMs(timestamp) {
1656
1632
  if (!Number.isFinite(timestamp) || timestamp === void 0 || timestamp <= 0) return;
1657
1633
  return timestamp < MS_EPOCH_MIN ? timestamp * 1e3 : timestamp;
1658
1634
  }
1659
- /** Build a card header from agent identity config. */
1660
1635
  function resolveCardHeader(agentId, identity) {
1661
1636
  const name = identity?.name?.trim() || (agentId === "main" ? "" : agentId);
1662
1637
  const emoji = resolveFeishuIdentityEmoji(identity?.emoji);
@@ -1667,7 +1642,6 @@ function resolveCardHeader(agentId, identity) {
1667
1642
  template: identity?.theme ?? "blue"
1668
1643
  };
1669
1644
  }
1670
- /** Build a card note footer from agent identity and model context. */
1671
1645
  function resolveCardNote(agentId, identity, prefixCtx) {
1672
1646
  const parts = [`Agent: ${identity?.name?.trim() || agentId}`];
1673
1647
  if (prefixCtx.model) parts.push(`Model: ${prefixCtx.model}`);
@@ -1774,20 +1748,12 @@ function createFeishuReplyDispatcher(params) {
1774
1748
  let idleRequestedForReply = false;
1775
1749
  let replyLifecycleStateInitialized = false;
1776
1750
  const pendingStreamingDeliveries = [];
1777
- const markVisibleReplySent = () => {
1778
- visibleReplySent = true;
1779
- };
1780
1751
  const formatReasoningPrefix = (thinking) => {
1781
1752
  if (!thinking) return "";
1782
1753
  return `> 💭 **Thinking**\n${thinking.replace(/^(?:Reasoning:|Thinking\.{0,3})\s*/u, "").replace(/^_(.*)_$/gm, "$1").split("\n").map((line) => `> ${line}`).join("\n")}`;
1783
1754
  };
1784
1755
  const buildCombinedStreamText = (thinking, answer) => {
1785
- const parts = [];
1786
- if (thinking) parts.push(formatReasoningPrefix(thinking));
1787
- if (thinking && answer) parts.push("\n\n---\n\n");
1788
- if (answer) parts.push(answer);
1789
- if (statusLine) parts.push(parts.length > 0 ? `\n\n${statusLine}` : statusLine);
1790
- return parts.join("");
1756
+ return [[thinking ? formatReasoningPrefix(thinking) : "", answer].filter(Boolean).join("\n\n---\n\n"), statusLine].filter(Boolean).join("\n\n");
1791
1757
  };
1792
1758
  const flushStreamingCardUpdate = (combined) => {
1793
1759
  const session = streaming;
@@ -1915,7 +1881,7 @@ function createFeishuReplyDispatcher(params) {
1915
1881
  content: closed.content,
1916
1882
  kind: "card"
1917
1883
  });
1918
- if (result.visibleReplySent) markVisibleReplySent();
1884
+ if (result.visibleReplySent) visibleReplySent = true;
1919
1885
  if (disposition === "closed" && result.visibleReplySent && finalizedAnswerText && (finalizationError === void 0 || result.content === text)) deliveredFinalTexts.add(finalizedAnswerText);
1920
1886
  if (finalizationError instanceof FeishuStreamingFinalizationError && result.visibleReplySent) finalizationError = createFeishuPartialReplyDeliveryError(finalizationError.cause ?? finalizationError, result);
1921
1887
  }
@@ -1959,18 +1925,13 @@ function createFeishuReplyDispatcher(params) {
1959
1925
  return closePromise;
1960
1926
  };
1961
1927
  const deferStreamingDelivery = (result, infoKind, ownerGeneration) => {
1962
- let resolveFinalization;
1963
- let rejectFinalization;
1964
- const finalization = new Promise((resolve, reject) => {
1965
- resolveFinalization = resolve;
1966
- rejectFinalization = reject;
1967
- });
1928
+ const { promise: finalization, resolve, reject } = createDeferred();
1968
1929
  pendingStreamingDeliveries.push({
1969
1930
  result,
1970
1931
  ...infoKind ? { infoKind } : {},
1971
1932
  ...ownerGeneration === void 0 ? {} : { streamingGeneration: ownerGeneration },
1972
- resolve: resolveFinalization,
1973
- reject: rejectFinalization
1933
+ resolve,
1934
+ reject
1974
1935
  });
1975
1936
  if (idleRequestedForReply) queueIdleSideEffects().catch((error) => params.runtime.error?.(`feishu[${account.accountId}] late reply finalization failed: ${String(error)}`));
1976
1937
  return {
@@ -2031,12 +1992,12 @@ function createFeishuReplyDispatcher(params) {
2031
1992
  });
2032
1993
  results.push(result);
2033
1994
  acceptedChunks.push(chunk);
2034
- markVisibleReplySent();
1995
+ visibleReplySent = true;
2035
1996
  } catch (error) {
2036
1997
  const acceptedChunk = isChannelPartialDeliveryError(error) ? error.deliveryResult : void 0;
2037
1998
  if (acceptedChunk) {
2038
1999
  acceptedChunks.push(acceptedChunk.content ?? chunk);
2039
- markVisibleReplySent();
2000
+ visibleReplySent = true;
2040
2001
  }
2041
2002
  throw createFeishuPartialReplyDeliveryError(error, {
2042
2003
  ...acceptedChunk,
@@ -2083,12 +2044,12 @@ function createFeishuReplyDispatcher(params) {
2083
2044
  visibleReplySent: true,
2084
2045
  kind: result?.voiceIntentDegradedToFile ? "media" : void 0
2085
2046
  }));
2086
- markVisibleReplySent();
2047
+ visibleReplySent = true;
2087
2048
  if (result?.voiceIntentDegradedToFile && options?.fallbackText && !sentFallbackText) degradedVoiceFallbackText = options.fallbackText;
2088
2049
  },
2089
2050
  onError: options?.fallbackText === void 0 ? void 0 : async ({ error, mediaUrl }) => {
2090
2051
  if (isChannelPartialDeliveryError(error)) {
2091
- markVisibleReplySent();
2052
+ visibleReplySent = true;
2092
2053
  throw toStringifiedError(error);
2093
2054
  }
2094
2055
  const fallbackText = await buildFeishuMediaFallbackText({
@@ -2099,13 +2060,10 @@ function createFeishuReplyDispatcher(params) {
2099
2060
  results.push(await sendPostReply(fallbackText, "final"));
2100
2061
  }
2101
2062
  });
2102
- if (degradedVoiceFallbackText && !sentFallbackText) {
2103
- sentFallbackText = true;
2104
- results.push(await sendPostReply(degradedVoiceFallbackText, "final"));
2105
- }
2063
+ if (degradedVoiceFallbackText && !sentFallbackText) results.push(await sendPostReply(degradedVoiceFallbackText, "final"));
2106
2064
  } catch (error) {
2107
2065
  const partial = isChannelPartialDeliveryError(error) ? error.deliveryResult : void 0;
2108
- if (partial) markVisibleReplySent();
2066
+ if (partial) visibleReplySent = true;
2109
2067
  throw createFeishuPartialReplyDeliveryError(error, mergeFeishuReplyDeliveryResults([...results, ...partial ? [partial] : []]));
2110
2068
  }
2111
2069
  return mergeFeishuReplyDeliveryResults(results);
@@ -2122,7 +2080,7 @@ function createFeishuReplyDispatcher(params) {
2122
2080
  text: NO_VISIBLE_REPLY_FALLBACK_TEXT,
2123
2081
  ...requiredMentionTargets?.length ? { mentions: requiredMentionTargets } : {}
2124
2082
  });
2125
- markVisibleReplySent();
2083
+ visibleReplySent = true;
2126
2084
  params.runtime.error?.(`feishu[${account.accountId}]: sent no-visible-reply fallback (${reason})`);
2127
2085
  return true;
2128
2086
  };
@@ -2139,12 +2097,6 @@ function createFeishuReplyDispatcher(params) {
2139
2097
  if (result) result.contentClaimed = true;
2140
2098
  return result;
2141
2099
  };
2142
- const markClosedStreamingContentClaimed = (generation) => {
2143
- if (generation !== void 0) {
2144
- const settlement = closedStreamingSettlements.get(generation);
2145
- if (settlement) settlement.contentClaimed = true;
2146
- }
2147
- };
2148
2100
  const ensureVisibleStreamingDelivery = async (result, content, infoKind) => {
2149
2101
  if (result?.visibleReplySent === true || !content?.trim()) return result;
2150
2102
  return sendChunkedTextReply({
@@ -2164,7 +2116,7 @@ function createFeishuReplyDispatcher(params) {
2164
2116
  const closeOutcome = await closeStreaming();
2165
2117
  const finalized = closeOutcome.result;
2166
2118
  const ownsCurrentClose = (completion) => closeOutcome.generation !== void 0 && completion.streamingGeneration === closeOutcome.generation;
2167
- if (completions.some((completion) => ownsCurrentClose(completion))) markClosedStreamingContentClaimed(closeOutcome.generation);
2119
+ if (completions.some((completion) => ownsCurrentClose(completion))) claimClosedStreamingResult(closeOutcome.generation, void 0);
2168
2120
  for (const completion of completions) {
2169
2121
  const claimedSettlement = ownsCurrentClose(completion) ? {
2170
2122
  disposition: closeOutcome.disposition,
@@ -2192,7 +2144,7 @@ function createFeishuReplyDispatcher(params) {
2192
2144
  continue;
2193
2145
  }
2194
2146
  const settledResult = mergeFeishuReplyDeliveryResults([...providerFinalized ? [providerFinalized] : [], completion.result], deliveryError === void 0 ? completion.result.content ?? providerFinalized?.content : providerFinalized?.content ?? completion.result.content);
2195
- if (deliveryError !== void 0) completion.reject(createFeishuPartialReplyDeliveryError(isChannelPartialDeliveryError(deliveryError) && deliveryError instanceof Error ? deliveryError.cause ?? deliveryError : deliveryError instanceof FeishuStreamingFinalizationError ? deliveryError.cause ?? deliveryError : deliveryError, settledResult));
2147
+ if (deliveryError !== void 0) completion.reject(createFeishuPartialReplyDeliveryError(isChannelPartialDeliveryError(deliveryError) && deliveryError instanceof Error || deliveryError instanceof FeishuStreamingFinalizationError ? deliveryError.cause ?? deliveryError : deliveryError, settledResult));
2196
2148
  else completion.resolve(settledResult);
2197
2149
  }
2198
2150
  if (closeOutcome.error !== void 0) throw toStringifiedError(closeOutcome.error);
@@ -2280,7 +2232,7 @@ function createFeishuReplyDispatcher(params) {
2280
2232
  };
2281
2233
  const handleDeliveryError = async (error, info) => {
2282
2234
  if (info.kind === "final") replyOutcome = { kind: "failed" };
2283
- if (isChannelPartialDeliveryError(error)) markVisibleReplySent();
2235
+ if (isChannelPartialDeliveryError(error)) visibleReplySent = true;
2284
2236
  params.runtime.error?.(`feishu[${account.accountId}] ${info.kind} reply failed: ${String(error)}`);
2285
2237
  await queueIdleSideEffects().catch((cleanupError) => params.runtime.error?.(`feishu[${account.accountId}] reply error cleanup failed: ${String(cleanupError)}`));
2286
2238
  };
@@ -2290,7 +2242,7 @@ function createFeishuReplyDispatcher(params) {
2290
2242
  observeMessageSent: true,
2291
2243
  onDelivered: (_payload, info, result) => {
2292
2244
  if (result?.visibleReplySent) {
2293
- markVisibleReplySent();
2245
+ visibleReplySent = true;
2294
2246
  if (info.kind === "final") replyOutcome = void 0;
2295
2247
  return;
2296
2248
  }
@@ -2367,7 +2319,7 @@ function createFeishuReplyDispatcher(params) {
2367
2319
  content: resolvedText,
2368
2320
  kind: "card"
2369
2321
  })), resolvedText);
2370
- markVisibleReplySent();
2322
+ visibleReplySent = true;
2371
2323
  return mergeFeishuReplyDeliveryResults(deliveredResults, resolvedText);
2372
2324
  }
2373
2325
  if (shouldDeliverText) {
@@ -2470,11 +2422,7 @@ function createFeishuReplyDispatcher(params) {
2470
2422
  onCompactionStart: previewStreamingEnabled ? () => updateStreamingStatusLine("📦 **Compacting context...**") : void 0,
2471
2423
  onCompactionEnd: previewStreamingEnabled ? () => updateStreamingStatusLine("") : void 0
2472
2424
  },
2473
- ensureNoVisibleReplyFallback,
2474
- getVisibleReplyState: () => ({
2475
- visibleReplySent,
2476
- skippedFinalReason: replyOutcome?.kind === "skipped" || replyOutcome?.kind === "suppressed" ? replyOutcome.reason : null
2477
- })
2425
+ ensureNoVisibleReplyFallback
2478
2426
  };
2479
2427
  }
2480
2428
  //#endregion
@@ -2514,7 +2462,7 @@ async function resolveFeishuAudioTranscript(params) {
2514
2462
  return;
2515
2463
  }
2516
2464
  }
2517
- function parseFeishuMessageEvent(event, botOpenId, _botName, preparedContent) {
2465
+ function parseFeishuMessageEvent(event, botOpenId, preparedContent) {
2518
2466
  const mentionedBot = checkBotMentioned(event, botOpenId);
2519
2467
  const hasAnyMention = (event.message.mentions?.length ?? 0) > 0;
2520
2468
  const content = preparedContent ?? normalizeMentions(parseMessageContent(event.message.content, event.message.message_type), event.message.mentions, botOpenId);
@@ -2573,7 +2521,7 @@ async function filterFetchedGroupContextMessages(messages, params) {
2573
2521
  }) ? message : void 0))).filter((message) => message !== void 0);
2574
2522
  }
2575
2523
  async function handleFeishuMessage(params) {
2576
- const { event, preparedContent, botOpenId, botName, runtime, channelRuntime, chatHistories, accountId, processingClaim, messageDedupeKey: messageDedupeKeyOverride, turnAdoptionLifecycle } = params;
2524
+ const { event, preparedContent, botOpenId, runtime, channelRuntime, chatHistories, accountId, processingClaim, messageDedupeKey: messageDedupeKeyOverride, turnAdoptionLifecycle } = params;
2577
2525
  let cfg = getFeishuRuntime().config.current();
2578
2526
  let account = resolveFeishuRuntimeAccount({
2579
2527
  cfg,
@@ -2593,7 +2541,7 @@ async function handleFeishuMessage(params) {
2593
2541
  log(`feishu: skipping duplicate message ${messageId}`);
2594
2542
  return;
2595
2543
  }
2596
- let ctx = parseFeishuMessageEvent(event, botOpenId, botName, preparedContent);
2544
+ let ctx = parseFeishuMessageEvent(event, botOpenId, preparedContent);
2597
2545
  const isGroup = isFeishuGroupChatType(ctx.chatType);
2598
2546
  const isDirect = !isGroup;
2599
2547
  const directPreDispatchTarget = isDirect ? getFeishuSyntheticDirectPreDispatchTarget(event) : void 0;
@@ -2643,7 +2591,7 @@ async function handleFeishuMessage(params) {
2643
2591
  log(`feishu[${account.accountId}]: dropping bot message ${ctx.messageId} (local mention not verifiable)`);
2644
2592
  return;
2645
2593
  }
2646
- const deliveredCtx = parseFeishuMessageEvent(verifiedEvent, localBotOpenId, botName, preparedContent);
2594
+ const deliveredCtx = parseFeishuMessageEvent(verifiedEvent, localBotOpenId, preparedContent);
2647
2595
  ctx = {
2648
2596
  ...deliveredCtx,
2649
2597
  mentionedBot: true,
@@ -3457,13 +3405,13 @@ async function handleFeishuMessage(params) {
3457
3405
  };
3458
3406
  const strategy = cfg.broadcast?.strategy === "sequential" ? "sequential" : "parallel";
3459
3407
  const activeAgentId = ctx.mentionedBot || !requireMention ? normalizeAgentId$1(route.agentId) : null;
3460
- const agentIds = (cfg.agents?.list ?? []).map((a) => normalizeAgentId$1(a.id));
3408
+ const agentIds = Object.keys(cfg.agents?.entries ?? {}).map((id) => normalizeAgentId$1(id));
3461
3409
  const hasKnownAgents = agentIds.length > 0;
3462
3410
  log(`feishu[${account.accountId}]: broadcasting to ${broadcastAgents.length} agents (strategy=${strategy}, active=${activeAgentId ?? "none"})`);
3463
3411
  const dispatchForAgent = async (agentId) => {
3464
3412
  const normalizedAgentId = normalizeAgentId$1(agentId);
3465
3413
  if (hasKnownAgents && !agentIds.includes(normalizedAgentId)) {
3466
- log(`feishu[${account.accountId}]: broadcast agent ${agentId} not found in agents.list; skipping`);
3414
+ log(`feishu[${account.accountId}]: broadcast agent ${agentId} not found in agents.entries; skipping`);
3467
3415
  return;
3468
3416
  }
3469
3417
  let agentClaim;
@@ -3684,6 +3632,26 @@ const processedCardActions = /* @__PURE__ */ new Map();
3684
3632
  const resolvedCardActionChatTypes = /* @__PURE__ */ new Map();
3685
3633
  //#endregion
3686
3634
  //#region extensions/feishu/src/card-ux-shared.ts
3635
+ function buildFeishuActionCard(params) {
3636
+ return {
3637
+ schema: "2.0",
3638
+ config: { width_mode: "fill" },
3639
+ header: {
3640
+ title: {
3641
+ tag: "plain_text",
3642
+ content: params.title
3643
+ },
3644
+ template: params.template
3645
+ },
3646
+ body: { elements: [{
3647
+ tag: "markdown",
3648
+ content: params.content
3649
+ }, {
3650
+ tag: "action",
3651
+ actions: params.actions
3652
+ }] }
3653
+ };
3654
+ }
3687
3655
  function buildFeishuCardButton(params) {
3688
3656
  return {
3689
3657
  tag: "button",
@@ -3711,56 +3679,44 @@ const FEISHU_APPROVAL_CONFIRM_ACTION = "feishu.approval.confirm";
3711
3679
  const FEISHU_APPROVAL_CANCEL_ACTION = "feishu.approval.cancel";
3712
3680
  function createApprovalCard(params) {
3713
3681
  const context = buildFeishuCardInteractionContext(params);
3714
- return {
3715
- schema: "2.0",
3716
- config: { width_mode: "fill" },
3717
- header: {
3718
- title: {
3719
- tag: "plain_text",
3720
- content: "Confirm action"
3721
- },
3722
- template: "orange"
3723
- },
3724
- body: { elements: [{
3725
- tag: "markdown",
3726
- content: params.prompt
3727
- }, {
3728
- tag: "action",
3729
- actions: [buildFeishuCardButton({
3730
- label: params.confirmLabel ?? "Confirm",
3731
- type: "primary",
3732
- value: createFeishuCardInteractionEnvelope({
3733
- k: "quick",
3734
- a: FEISHU_APPROVAL_CONFIRM_ACTION,
3735
- q: params.command,
3736
- c: context
3737
- })
3738
- }), buildFeishuCardButton({
3739
- label: params.cancelLabel ?? "Cancel",
3740
- value: createFeishuCardInteractionEnvelope({
3741
- k: "button",
3742
- a: FEISHU_APPROVAL_CANCEL_ACTION,
3743
- c: context
3744
- })
3745
- })]
3746
- }] }
3747
- };
3682
+ return buildFeishuActionCard({
3683
+ title: "Confirm action",
3684
+ template: "orange",
3685
+ content: params.prompt,
3686
+ actions: [buildFeishuCardButton({
3687
+ label: params.confirmLabel ?? "Confirm",
3688
+ type: "primary",
3689
+ value: createFeishuCardInteractionEnvelope({
3690
+ k: "quick",
3691
+ a: FEISHU_APPROVAL_CONFIRM_ACTION,
3692
+ q: params.command,
3693
+ c: context
3694
+ })
3695
+ }), buildFeishuCardButton({
3696
+ label: params.cancelLabel ?? "Cancel",
3697
+ value: createFeishuCardInteractionEnvelope({
3698
+ k: "button",
3699
+ a: FEISHU_APPROVAL_CANCEL_ACTION,
3700
+ c: context
3701
+ })
3702
+ })]
3703
+ });
3748
3704
  }
3749
3705
  //#endregion
3750
3706
  //#region extensions/feishu/src/card-action.ts
3751
3707
  const FEISHU_APPROVAL_CARD_TTL_MS = 3e5;
3752
3708
  const FEISHU_CARD_ACTION_TOKEN_TTL_MS = 9e5;
3753
- function pruneProcessedCardActionTokens(now) {
3709
+ function pruneExpiredCardEntries(cache, now) {
3754
3710
  const validNow = asDateTimestampMs(now);
3755
3711
  if (validNow === void 0) {
3756
- processedCardActions.clear();
3712
+ cache.clear();
3757
3713
  return;
3758
3714
  }
3759
- for (const [key, entry] of processedCardActions.entries()) if (!isFutureDateTimestampMs(entry.expiresAt, { nowMs: validNow })) processedCardActions.delete(key);
3715
+ for (const [key, entry] of cache) if (!isFutureDateTimestampMs(entry.expiresAt, { nowMs: validNow })) cache.delete(key);
3760
3716
  }
3761
3717
  function beginFeishuCardActionToken(params) {
3762
3718
  const now = params.now ?? Date.now();
3763
- pruneProcessedCardActionTokens(now);
3719
+ pruneExpiredCardEntries(processedCardActions, now);
3764
3720
  const normalizedToken = params.token.trim();
3765
3721
  if (!normalizedToken) return false;
3766
3722
  const key = `${params.accountId}:${normalizedToken}`;
@@ -3838,28 +3794,15 @@ async function dispatchSyntheticCommand(params) {
3838
3794
  accountId: params.accountId
3839
3795
  });
3840
3796
  }
3841
- const resolvedChatTypeCache = resolvedCardActionChatTypes;
3842
3797
  const CHAT_TYPE_CACHE_TTL_MS = 18e5;
3843
3798
  const CHAT_TYPE_CACHE_MAX_SIZE = 5e3;
3844
- function pruneChatTypeCache(now) {
3845
- const validNow = asDateTimestampMs(now);
3846
- if (validNow === void 0) {
3847
- resolvedChatTypeCache.clear();
3848
- return;
3849
- }
3850
- for (const [key, entry] of resolvedChatTypeCache.entries()) {
3851
- const expiresAt = asDateTimestampMs(entry.expiresAt);
3852
- if (expiresAt === void 0 || expiresAt <= validNow) resolvedChatTypeCache.delete(key);
3853
- }
3854
- pruneMapToMaxSize(resolvedChatTypeCache, CHAT_TYPE_CACHE_MAX_SIZE);
3855
- }
3856
3799
  function sanitizeLogValue(v) {
3857
3800
  return truncateUtf16Safe(v.replace(/[\r\n]/g, " "), 500);
3858
3801
  }
3859
3802
  function cacheResolvedCardActionChatType(cacheKey, value, now) {
3860
3803
  const expiresAt = resolveExpiresAtMsFromDurationMs(CHAT_TYPE_CACHE_TTL_MS, { nowMs: now });
3861
- resolvedChatTypeCache.delete(cacheKey);
3862
- if (expiresAt !== void 0) resolvedChatTypeCache.set(cacheKey, {
3804
+ resolvedCardActionChatTypes.delete(cacheKey);
3805
+ if (expiresAt !== void 0) resolvedCardActionChatTypes.set(cacheKey, {
3863
3806
  value,
3864
3807
  expiresAt
3865
3808
  });
@@ -3871,8 +3814,9 @@ async function resolveCardActionChatType(params) {
3871
3814
  if (!chatId) return "p2p";
3872
3815
  const cacheKey = `${params.account.accountId}:${chatId}`;
3873
3816
  const now = Date.now();
3874
- pruneChatTypeCache(now);
3875
- const cached = resolvedChatTypeCache.get(cacheKey);
3817
+ pruneExpiredCardEntries(resolvedCardActionChatTypes, now);
3818
+ pruneMapToMaxSize(resolvedCardActionChatTypes, CHAT_TYPE_CACHE_MAX_SIZE);
3819
+ const cached = resolvedCardActionChatTypes.get(cacheKey);
3876
3820
  if (cached) return cached.value;
3877
3821
  try {
3878
3822
  const response = await createFeishuClient(params.account).im.chat.get({ path: { chat_id: chatId } });
@@ -3987,7 +3931,7 @@ async function handleFeishuCardAction(params) {
3987
3931
  await sendInvalidInteractionNotice("malformed");
3988
3932
  return;
3989
3933
  }
3990
- const content = buildFeishuCardActionTextFallback(event);
3934
+ const content = decoded.text;
3991
3935
  log(`feishu[${account.accountId}]: handling card action from ${event.operator.open_id}: ${content}`);
3992
3936
  await dispatchSyntheticCommand({
3993
3937
  ...params,
@@ -4223,7 +4167,6 @@ function createFeishuDurableIngress(options) {
4223
4167
  const abandonHandlers = /* @__PURE__ */ new Set();
4224
4168
  const wrappedLifecycle = {
4225
4169
  ...lifecycle,
4226
- onAdopted: lifecycle.onAdopted,
4227
4170
  onAbandoned: async () => {
4228
4171
  await Promise.allSettled([...abandonHandlers].map(async (handler) => await handler()));
4229
4172
  await lifecycle.onAbandoned();
@@ -4311,7 +4254,6 @@ function createFeishuDurableIngress(options) {
4311
4254
  //#region extensions/feishu/src/monitor.state.ts
4312
4255
  const wsClients = /* @__PURE__ */ new Map();
4313
4256
  const botOpenIds = /* @__PURE__ */ new Map();
4314
- const botNames = /* @__PURE__ */ new Map();
4315
4257
  const botIdentityRevisions = /* @__PURE__ */ new Map();
4316
4258
  const FEISHU_WEBHOOK_MAX_BODY_BYTES = 65536;
4317
4259
  const FEISHU_WEBHOOK_BODY_TIMEOUT_MS = 5e3;
@@ -4323,15 +4265,12 @@ function readFeishuBotIdentityRevision(accountId) {
4323
4265
  function bumpBotIdentityRevision(accountId) {
4324
4266
  botIdentityRevisions.set(accountId, readFeishuBotIdentityRevision(accountId) + 1);
4325
4267
  }
4326
- function setFeishuBotIdentityState(accountId, identity) {
4327
- botOpenIds.set(accountId, identity.botOpenId);
4328
- if (identity.botName) botNames.set(accountId, identity.botName);
4329
- else botNames.delete(accountId);
4268
+ function setFeishuBotIdentityState(accountId, botOpenId) {
4269
+ botOpenIds.set(accountId, botOpenId);
4330
4270
  bumpBotIdentityRevision(accountId);
4331
4271
  }
4332
4272
  function clearFeishuBotIdentityState(accountId) {
4333
4273
  botOpenIds.delete(accountId);
4334
- botNames.delete(accountId);
4335
4274
  bumpBotIdentityRevision(accountId);
4336
4275
  }
4337
4276
  function recordWebhookStatus(runtime, accountId, path, statusCode) {
@@ -4354,16 +4293,8 @@ const BOT_IDENTITY_RETRY_DELAYS_MS = [
4354
4293
  ];
4355
4294
  function applyBotIdentityState(accountId, identity) {
4356
4295
  const botOpenId = normalizeOptionalString(identity.botOpenId);
4357
- const botName = normalizeOptionalString(identity.botName);
4358
- setFeishuBotIdentityState(accountId, {
4359
- botOpenId: botOpenId ?? "",
4360
- botName
4361
- });
4362
- return {
4363
- botOpenId,
4364
- botName,
4365
- source: botOpenId ? identity.source : void 0
4366
- };
4296
+ setFeishuBotIdentityState(accountId, botOpenId ?? "");
4297
+ return botOpenId;
4367
4298
  }
4368
4299
  async function retryBotIdentityProbe(account, accountId, runtime, abortSignal) {
4369
4300
  const log = runtime?.log ?? console.log;
@@ -4377,7 +4308,7 @@ async function retryBotIdentityProbe(account, accountId, runtime, abortSignal) {
4377
4308
  allowCachedFallback: false
4378
4309
  });
4379
4310
  if (normalizeOptionalString(identity.botOpenId) && identity.source === "provider") {
4380
- log(`feishu[${accountId}]: bot open_id recovered via background retry: ${applyBotIdentityState(accountId, identity).botOpenId}`);
4311
+ log(`feishu[${accountId}]: bot open_id recovered via background retry: ${applyBotIdentityState(accountId, identity)}`);
4381
4312
  return;
4382
4313
  }
4383
4314
  const nextDelay = BOT_IDENTITY_RETRY_DELAYS_MS[i + 1];
@@ -4402,68 +4333,53 @@ const QUICK_ACTION_MENU_KEYS = /* @__PURE__ */ new Set([
4402
4333
  "quick_actions",
4403
4334
  "launcher"
4404
4335
  ]);
4405
- function isFeishuQuickActionMenuEventKey(eventKey) {
4406
- return QUICK_ACTION_MENU_KEYS.has(normalizeOptionalLowercaseString(eventKey) ?? "");
4407
- }
4408
4336
  function createQuickActionLauncherCard(params) {
4409
4337
  const context = buildFeishuCardInteractionContext(params);
4410
- return {
4411
- schema: "2.0",
4412
- config: { width_mode: "fill" },
4413
- header: {
4414
- title: {
4415
- tag: "plain_text",
4416
- content: "Quick actions"
4417
- },
4418
- template: "indigo"
4419
- },
4420
- body: { elements: [{
4421
- tag: "markdown",
4422
- content: "Run common actions without typing raw commands."
4423
- }, {
4424
- tag: "action",
4425
- actions: [
4426
- buildFeishuCardButton({
4427
- label: "Help",
4428
- value: createFeishuCardInteractionEnvelope({
4429
- k: "quick",
4430
- a: "feishu.quick_actions.help",
4431
- q: "/help",
4432
- c: context
4433
- })
4434
- }),
4435
- buildFeishuCardButton({
4436
- label: "New session",
4437
- type: "primary",
4438
- value: createFeishuCardInteractionEnvelope({
4439
- k: "meta",
4440
- a: FEISHU_APPROVAL_REQUEST_ACTION,
4441
- m: {
4442
- command: "/new",
4443
- prompt: "Start a fresh session? This will reset the current chat context."
4444
- },
4445
- c: context
4446
- })
4447
- }),
4448
- buildFeishuCardButton({
4449
- label: "Reset",
4450
- type: "danger",
4451
- value: createFeishuCardInteractionEnvelope({
4452
- k: "meta",
4453
- a: FEISHU_APPROVAL_REQUEST_ACTION,
4454
- m: {
4455
- command: "/reset",
4456
- prompt: "Reset this session now? Any active conversation state will be cleared."
4457
- },
4458
- c: context
4459
- })
4338
+ return buildFeishuActionCard({
4339
+ title: "Quick actions",
4340
+ template: "indigo",
4341
+ content: "Run common actions without typing raw commands.",
4342
+ actions: [
4343
+ buildFeishuCardButton({
4344
+ label: "Help",
4345
+ value: createFeishuCardInteractionEnvelope({
4346
+ k: "quick",
4347
+ a: "feishu.quick_actions.help",
4348
+ q: "/help",
4349
+ c: context
4460
4350
  })
4461
- ]
4462
- }] }
4463
- };
4351
+ }),
4352
+ buildFeishuCardButton({
4353
+ label: "New session",
4354
+ type: "primary",
4355
+ value: createFeishuCardInteractionEnvelope({
4356
+ k: "meta",
4357
+ a: FEISHU_APPROVAL_REQUEST_ACTION,
4358
+ m: {
4359
+ command: "/new",
4360
+ prompt: "Start a fresh session? This will reset the current chat context."
4361
+ },
4362
+ c: context
4363
+ })
4364
+ }),
4365
+ buildFeishuCardButton({
4366
+ label: "Reset",
4367
+ type: "danger",
4368
+ value: createFeishuCardInteractionEnvelope({
4369
+ k: "meta",
4370
+ a: FEISHU_APPROVAL_REQUEST_ACTION,
4371
+ m: {
4372
+ command: "/reset",
4373
+ prompt: "Reset this session now? Any active conversation state will be cleared."
4374
+ },
4375
+ c: context
4376
+ })
4377
+ })
4378
+ ]
4379
+ });
4464
4380
  }
4465
4381
  async function maybeHandleFeishuQuickActionMenu(params) {
4466
- if (!isFeishuQuickActionMenuEventKey(params.eventKey)) return false;
4382
+ if (!QUICK_ACTION_MENU_KEYS.has(normalizeOptionalLowercaseString(params.eventKey) ?? "")) return false;
4467
4383
  const now = asDateTimestampMs(params.now ?? Date.now());
4468
4384
  const expiresAt = now === void 0 ? void 0 : resolveExpiresAtMsFromDurationMs(FEISHU_QUICK_ACTION_CARD_TTL_MS, { nowMs: now });
4469
4385
  if (expiresAt === void 0) {
@@ -4526,7 +4442,6 @@ function createFeishuBotMenuHandler(params) {
4526
4442
  const log = runtime?.log ?? console.log;
4527
4443
  const error = runtime?.error ?? console.error;
4528
4444
  const getBotOpenId = params.getBotOpenId ?? ((id) => botOpenIds.get(id));
4529
- const getBotName = params.getBotName ?? ((id) => botNames.get(id));
4530
4445
  const isActive = params.isAccountActive ?? (() => true);
4531
4446
  const handle = async (data) => {
4532
4447
  try {
@@ -4577,7 +4492,6 @@ function createFeishuBotMenuHandler(params) {
4577
4492
  cfg,
4578
4493
  event: syntheticEvent,
4579
4494
  botOpenId: getBotOpenId(accountId),
4580
- botName: getBotName(accountId),
4581
4495
  runtime,
4582
4496
  channelRuntime: params.channelRuntime,
4583
4497
  chatHistories,
@@ -5172,7 +5086,7 @@ async function resolveDriveCommentEventTurn(params) {
5172
5086
  return null;
5173
5087
  }
5174
5088
  const context = await fetchDriveCommentContext({
5175
- client: createClient ? createClient(account ?? { accountId }) : createFeishuClient((await import("./accounts-wRqItHug.mjs").then((n) => n.t)).resolveFeishuAccount({
5089
+ client: createClient ? createClient(account ?? { accountId }) : createFeishuClient((await import("./doctor-contract-B1B9ogdd.mjs").then((n) => n.c)).resolveFeishuAccount({
5176
5090
  cfg,
5177
5091
  accountId
5178
5092
  })),
@@ -5516,20 +5430,11 @@ function createSequentialQueue(options = {}) {
5516
5430
  async function boundedRun(key, task, timeoutMs, onTaskTimeout) {
5517
5431
  if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) return task();
5518
5432
  const resolvedTimeoutMs = resolveTimerTimeoutMs(timeoutMs, DEFAULT_TASK_TIMEOUT_MS);
5519
- let timeoutHandle;
5520
- const timeoutPromise = new Promise((resolve) => {
5521
- timeoutHandle = setTimeout(() => {
5522
- try {
5523
- onTaskTimeout?.(key, resolvedTimeoutMs);
5524
- } catch {}
5525
- resolve();
5526
- }, resolvedTimeoutMs);
5433
+ await raceWithTimeout(task, resolvedTimeoutMs, () => {
5434
+ try {
5435
+ onTaskTimeout?.(key, resolvedTimeoutMs);
5436
+ } catch {}
5527
5437
  });
5528
- try {
5529
- await Promise.race([task(), timeoutPromise]);
5530
- } finally {
5531
- if (timeoutHandle) clearTimeout(timeoutHandle);
5532
- }
5533
5438
  }
5534
5439
  //#endregion
5535
5440
  //#region extensions/feishu/src/monitor.comment-notice-handler.ts
@@ -5638,7 +5543,7 @@ function resolveFeishuDebounceMentions(params) {
5638
5543
  const botMentions = merged.filter((mention) => mention.id.open_id?.trim() === normalizedBotOpenId);
5639
5544
  return botMentions.length > 0 ? botMentions : void 0;
5640
5545
  }
5641
- function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, runtime, chatHistories, fireAndForget, isAccountActive = () => true, trackTask, handleMessage, resolveDebounceText: resolveText, hasProcessedMessage, getBotOpenId = () => void 0, getBotName = () => void 0, resolveSequentialKey = ({ accountId: accountIdLocal, event }) => `feishu:${accountIdLocal}:${event.message.chat_id?.trim() || "unknown"}`, statusSink, resolveIngressLifecycle }) {
5546
+ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, runtime, chatHistories, fireAndForget, isAccountActive = () => true, trackTask, handleMessage, resolveDebounceText: resolveText, hasProcessedMessage, getBotOpenId = () => void 0, resolveSequentialKey = ({ accountId: accountIdLocal, event }) => `feishu:${accountIdLocal}:${event.message.chat_id?.trim() || "unknown"}`, statusSink, resolveIngressLifecycle }) {
5642
5547
  const readConfig = createRuntimeConfigReader(cfg);
5643
5548
  const resolveDebounceMs = () => channelRuntime.debounce.resolveInboundDebounceMs({
5644
5549
  cfg: readConfig(),
@@ -5654,8 +5559,7 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
5654
5559
  accountId,
5655
5560
  event,
5656
5561
  preparedContent,
5657
- botOpenId: getBotOpenId(accountId),
5658
- botName: getBotName(accountId)
5562
+ botOpenId: getBotOpenId(accountId)
5659
5563
  });
5660
5564
  const task = async () => {
5661
5565
  if (turnAdoptionLifecycle?.abortSignal.aborted) {
@@ -5668,7 +5572,6 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
5668
5572
  event,
5669
5573
  preparedContent,
5670
5574
  botOpenId: getBotOpenId(accountId),
5671
- botName: getBotName(accountId),
5672
5575
  runtime,
5673
5576
  channelRuntime,
5674
5577
  chatHistories,
@@ -5682,14 +5585,10 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
5682
5585
  };
5683
5586
  await enqueue(sequentialKey, task);
5684
5587
  };
5685
- const resolveSenderDebounceId = (event) => {
5686
- return event.sender.sender_id.open_id?.trim() || event.sender.sender_id.user_id?.trim() || void 0;
5687
- };
5688
5588
  const resolveDebounceText = (event) => {
5689
5589
  return resolveText({
5690
5590
  event,
5691
- botOpenId: getBotOpenId(accountId),
5692
- botName: getBotName(accountId)
5591
+ botOpenId: getBotOpenId(accountId)
5693
5592
  }).trim();
5694
5593
  };
5695
5594
  const recordSuppressedMessageIds = async (entries, dispatchDedupeKey) => {
@@ -5708,7 +5607,7 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
5708
5607
  resolveDebounceMs,
5709
5608
  buildKey: ({ event }) => {
5710
5609
  const chatId = event.message.chat_id?.trim();
5711
- const senderId = resolveSenderDebounceId(event);
5610
+ const senderId = event.sender.sender_id.open_id?.trim() || event.sender.sender_id.user_id?.trim();
5712
5611
  if (!chatId || !senderId) return null;
5713
5612
  const threadId = event.message.root_id?.trim() || event.message.thread_id?.trim();
5714
5613
  return `feishu:${accountId}:${chatId}:${threadId ? `thread:${threadId}` : "chat"}:${senderId}`;
@@ -5813,7 +5712,7 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
5813
5712
  return;
5814
5713
  }
5815
5714
  const messageDedupeKey = resolveFeishuMessageDedupeKey(event);
5816
- if (event.message.message_type.trim() === "post" && messageDedupeKey !== messageId && await hasProcessedMessage(messageId, accountId, log) && parsePostContent(event.message.content).attachments.length === 0) {
5715
+ if (event.message.message_type.trim() === "post" && messageDedupeKey !== messageId && await hasProcessedMessage(messageId, accountId, log) && parsePostContent(event.message.content, { includeTopLevelFiles: false }).attachments.length === 0) {
5817
5716
  log(`feishu[${accountId}]: dropping duplicate event for message ${messageId}`);
5818
5717
  await completeSuppressedIngress();
5819
5718
  return;
@@ -5847,11 +5746,8 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
5847
5746
  debounceEntry.abandoned = true;
5848
5747
  claim.handle.release({ error: /* @__PURE__ */ new Error("feishu-ingress-abandoned-before-flush") });
5849
5748
  });
5850
- const processMessage = async () => {
5851
- await inboundDebouncer.enqueue(debounceEntry);
5852
- };
5853
5749
  if (turnAdoptionLifecycle) try {
5854
- await processMessage();
5750
+ await inboundDebouncer.enqueue(debounceEntry);
5855
5751
  return { kind: "deferred" };
5856
5752
  } catch (err) {
5857
5753
  if (claim.kind === "claimed") claim.handle.release({ error: err });
@@ -5860,7 +5756,7 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
5860
5756
  error: err
5861
5757
  };
5862
5758
  }
5863
- const processing = processMessage().catch((err) => {
5759
+ const processing = inboundDebouncer.enqueue(debounceEntry).catch((err) => {
5864
5760
  if (claim.kind === "claimed") claim.handle.release({ error: err });
5865
5761
  error(`feishu[${accountId}]: error handling message: ${String(err)}`);
5866
5762
  });
@@ -5878,54 +5774,6 @@ function buildFeishuWebhookRateLimitKey(params) {
5878
5774
  return `${params.accountId === void 0 ? params.path : `${params.accountId}:${params.path}`}:${normalizeFeishuWebhookRateLimitClient(params.clientIp)}`;
5879
5775
  }
5880
5776
  //#endregion
5881
- //#region extensions/feishu/src/monitor.webhook-legacy.ts
5882
- const feishuWebhookHost = webhookIngressSdk;
5883
- async function startFeishuLegacyWebhookListener(params) {
5884
- const server = createServer((req, res) => {
5885
- params.handleRequest(req, res).catch((error) => {
5886
- params.onRequestError(error);
5887
- if (!res.headersSent) res.statusCode = 500;
5888
- res.end();
5889
- });
5890
- });
5891
- let closing;
5892
- const stopAccepting = () => {
5893
- closing ??= new Promise((resolve, reject) => {
5894
- server.close((error) => {
5895
- if (error && extractErrorCode(error) !== "ERR_SERVER_NOT_RUNNING") reject(error);
5896
- else resolve();
5897
- });
5898
- });
5899
- closing.catch(() => {});
5900
- };
5901
- const close = async () => {
5902
- stopAccepting();
5903
- server.closeAllConnections();
5904
- try {
5905
- await closing;
5906
- } finally {
5907
- server.off("error", params.onFailure);
5908
- }
5909
- };
5910
- server.on("error", params.onFailure);
5911
- try {
5912
- await new Promise((resolve, reject) => {
5913
- server.once("error", reject);
5914
- server.listen(params.endpoint.port, params.endpoint.host, () => {
5915
- server.off("error", reject);
5916
- resolve();
5917
- });
5918
- });
5919
- } catch (error) {
5920
- await close();
5921
- throw error;
5922
- }
5923
- return {
5924
- stopAccepting,
5925
- close
5926
- };
5927
- }
5928
- //#endregion
5929
5777
  //#region extensions/feishu/src/monitor.transport.ts
5930
5778
  const FEISHU_WEBHOOK_ACCEPTED_HEADER = "x-openclaw-delivery-accepted";
5931
5779
  const FEISHU_WEBHOOK_ACCEPTED_VALUE = "durable";
@@ -6006,25 +5854,6 @@ function cleanupFeishuWsClient(params) {
6006
5854
  wsClients.delete(accountId);
6007
5855
  if (clearIdentity) clearFeishuBotIdentityState(accountId);
6008
5856
  }
6009
- function waitForFeishuWsCycleEnd(params) {
6010
- if (params.abortSignal?.aborted) return Promise.resolve("abort");
6011
- return new Promise((resolve) => {
6012
- let settled = false;
6013
- const finish = (result) => {
6014
- if (settled) return;
6015
- settled = true;
6016
- if (handleAbort) params.abortSignal?.removeEventListener("abort", handleAbort);
6017
- resolve(result);
6018
- };
6019
- const handleAbort = () => finish("abort");
6020
- params.abortSignal?.addEventListener("abort", handleAbort, { once: true });
6021
- if (params.abortSignal?.aborted) {
6022
- finish("abort");
6023
- return;
6024
- }
6025
- params.terminalError.then(finish);
6026
- });
6027
- }
6028
5857
  async function monitorWebSocket({ account, accountId, runtime, abortSignal, eventDispatcher, setSocketTerminator, statusSink }) {
6029
5858
  const log = runtime?.log ?? console.log;
6030
5859
  const error = runtime?.error ?? console.error;
@@ -6033,10 +5862,7 @@ async function monitorWebSocket({ account, accountId, runtime, abortSignal, even
6033
5862
  if (abortSignal?.aborted) break;
6034
5863
  let wsClient;
6035
5864
  try {
6036
- let reportTerminalError = () => {};
6037
- const terminalError = new Promise((resolve) => {
6038
- reportTerminalError = resolve;
6039
- });
5865
+ const { promise: terminalError, resolve: reportTerminalError } = createDeferred();
6040
5866
  const handleWsError = (err) => {
6041
5867
  if (isFeishuWsTerminalError(err)) {
6042
5868
  reportTerminalError(err);
@@ -6079,11 +5905,8 @@ async function monitorWebSocket({ account, accountId, runtime, abortSignal, even
6079
5905
  await wsClient.start({ eventDispatcher });
6080
5906
  attempt = 0;
6081
5907
  log(`feishu[${accountId}]: WebSocket client started`);
6082
- const cycleEnd = await waitForFeishuWsCycleEnd({
6083
- abortSignal,
6084
- terminalError
6085
- });
6086
- if (cycleEnd === "abort") {
5908
+ const cycleEnd = await raceWithTimeoutAndAbort(terminalError, { abortSignal });
5909
+ if (cycleEnd.status !== "resolved") {
6087
5910
  log(`feishu[${accountId}]: abort signal received, stopping`);
6088
5911
  cleanupFeishuWsClient({
6089
5912
  accountId,
@@ -6103,13 +5926,13 @@ async function monitorWebSocket({ account, accountId, runtime, abortSignal, even
6103
5926
  setSocketTerminator?.(void 0);
6104
5927
  if (abortSignal?.aborted) break;
6105
5928
  const disconnectedAt = Date.now();
6106
- statusSink?.(channelBlockedPatch(formatFeishuWsErrorForLog(cycleEnd), {
5929
+ statusSink?.(channelBlockedPatch(formatFeishuWsErrorForLog(cycleEnd.value), {
6107
5930
  connected: false,
6108
5931
  lastEventAt: disconnectedAt
6109
5932
  }));
6110
5933
  attempt += 1;
6111
5934
  const delayMs = getFeishuWsReconnectDelayMs(attempt);
6112
- error(`feishu[${accountId}]: WebSocket connection ended, recreating client in ${delayMs}ms: ${formatFeishuWsErrorForLog(cycleEnd)}`);
5935
+ error(`feishu[${accountId}]: WebSocket connection ended, recreating client in ${delayMs}ms: ${formatFeishuWsErrorForLog(cycleEnd.value)}`);
6113
5936
  if (!await waitForAbortableDelay(delayMs, abortSignal)) break;
6114
5937
  } catch (err) {
6115
5938
  cleanupFeishuWsClient({
@@ -6147,7 +5970,8 @@ const webhookTargetsStore = createPluginRuntimeStore({
6147
5970
  key: "feishu:webhook-targets",
6148
5971
  errorMessage: "Feishu webhook routes are not registered"
6149
5972
  });
6150
- async function handleFeishuWebhook(req, res, webhookTargets, legacyListener = feishuWebhookHost.getWebhookLegacyListener?.(req)) {
5973
+ async function handleFeishuWebhook(req, res, webhookTargets) {
5974
+ const legacyListener = getWebhookLegacyListener(req);
6151
5975
  const requestUrl = req.url ?? "/";
6152
5976
  const requestPath = requestUrl.split("?", 1)[0];
6153
5977
  const targets = (webhookTargets.get(canonicalizeWebhookRouteKey(requestPath ?? "/")) ?? []).filter((target) => (!legacyListener || target.legacyListener?.port === legacyListener.port && target.legacyListener.host === legacyListener.host) && (target.rawPath.includes("?") ? requestUrl : requestPath) === target.rawPath);
@@ -6274,7 +6098,6 @@ async function monitorWebhook(params) {
6274
6098
  const stopped = new AbortController();
6275
6099
  const abortSignal = params.abortSignal ? AbortSignal.any([params.abortSignal, stopped.signal]) : stopped.signal;
6276
6100
  const legacyListener = resolveFeishuLegacyWebhookListener(account.config);
6277
- const gatewayOwnsLegacyListeners = feishuWebhookHost.getWebhookLegacyListener !== void 0;
6278
6101
  const encryptKey = account.encryptKey?.trim();
6279
6102
  if (!encryptKey) throw new Error(`Feishu account "${accountId}" webhook mode requires encryptKey`);
6280
6103
  const rawPath = account.config.webhookPath ?? "/feishu/events";
@@ -6299,15 +6122,12 @@ async function monitorWebhook(params) {
6299
6122
  pendingResponses: /* @__PURE__ */ new Map()
6300
6123
  });
6301
6124
  let unregisterRoute;
6302
- let ownedListener;
6303
- let listenerError;
6304
6125
  let cleanupStarted = false;
6305
6126
  let pendingDrain;
6306
6127
  const cleanup = () => {
6307
6128
  if (cleanupStarted) return pendingDrain;
6308
6129
  cleanupStarted = true;
6309
6130
  stopped.abort();
6310
- ownedListener?.stopAccepting();
6311
6131
  const identityRevision = readFeishuBotIdentityRevision(accountId);
6312
6132
  pendingDrain = (async () => {
6313
6133
  const pendingResponses = registration.target.pendingResponses;
@@ -6315,12 +6135,8 @@ async function monitorWebhook(params) {
6315
6135
  if ((await raceWithTimeoutAndAbort(Promise.all(pendingResponses.values()), { timeoutMs: FEISHU_WEBHOOK_CLOSE_TIMEOUT_MS })).status === "timeout") for (const response of pendingResponses.keys()) response.destroy();
6316
6136
  }
6317
6137
  if (readFeishuBotIdentityRevision(accountId) === identityRevision && ![...webhookTargets.values()].some((targets) => targets.some((target) => target !== registration.target && target.accountId === accountId && !target.abortSignal?.aborted))) clearFeishuBotIdentityState(accountId);
6318
- try {
6319
- registration.unregister();
6320
- unregisterRoute?.();
6321
- } finally {
6322
- await ownedListener?.close();
6323
- }
6138
+ registration.unregister();
6139
+ unregisterRoute?.();
6324
6140
  })();
6325
6141
  return pendingDrain;
6326
6142
  };
@@ -6338,33 +6154,17 @@ async function monitorWebhook(params) {
6338
6154
  handler: (req, res) => handleFeishuWebhook(req, res, webhookTargets),
6339
6155
  reuseExistingSameOwner: true,
6340
6156
  throwOnFailure: true,
6341
- legacyListener: gatewayOwnsLegacyListeners ? legacyListener : void 0,
6157
+ legacyListener,
6342
6158
  log: runtime?.log
6343
6159
  });
6344
- if (!gatewayOwnsLegacyListeners && legacyListener && !abortSignal.aborted) {
6345
- const accountTargets = /* @__PURE__ */ new Map([[path, [registration.target]]]);
6346
- ownedListener = await startFeishuLegacyWebhookListener({
6347
- endpoint: legacyListener,
6348
- handleRequest: (req, res) => handleFeishuWebhook(req, res, accountTargets, legacyListener),
6349
- onFailure: (error) => {
6350
- listenerError = error;
6351
- stopped.abort(error);
6352
- },
6353
- onRequestError: (error) => (runtime?.error ?? console.error)(`feishu[${accountId}]: legacy webhook request failed: ${formatFeishuWsErrorForLog(error)}`)
6354
- });
6355
- }
6356
- if (abortSignal.aborted) {
6357
- if (listenerError) throw listenerError;
6358
- return;
6359
- }
6160
+ if (abortSignal.aborted) return;
6360
6161
  const connectedAt = Date.now();
6361
6162
  statusSink?.(channelReadyPatch({
6362
6163
  lastConnectedAt: connectedAt,
6363
6164
  lastEventAt: connectedAt
6364
6165
  }));
6365
- runtime?.log?.(ownedListener ? `feishu[${accountId}]: 2026.9.6 compatibility listener ${legacyListener?.host}:${legacyListener?.port} serves this account directly. This host requires distinct legacy endpoints for separate accounts; set legacyWebhook:false after verifying delivery on the Gateway route.` : pathConflict ? `feishu[${accountId}]: ${pathConflict} The legacy listener keeps the old path working; move the path and callback before setting legacyWebhook:false.` : `feishu[${accountId}]: webhook registered on Gateway port ${params.gatewayPort ?? 18789} at ${rawPath}; point the Feishu callback URL or reverse-proxy upstream to this Gateway route. ${legacyListener ? `The legacy listener on ${legacyListener.host}:${legacyListener.port} forwards here; set legacyWebhook:false after verifying delivery through the Gateway to disable legacy forwarding for this account.` : "legacyWebhook:false disables legacy forwarding for this account."}`);
6166
+ runtime?.log?.(pathConflict ? `feishu[${accountId}]: ${pathConflict} The legacy listener keeps the old path working; move the path and callback before removing the legacyWebhook pin.` : `feishu[${accountId}]: webhook registered on Gateway port ${params.gatewayPort ?? 18789} at ${rawPath}; point the Feishu callback URL or reverse-proxy upstream to this Gateway route. ${legacyListener ? `The legacy listener on ${legacyListener.host}:${legacyListener.port} forwards here; remove the legacyWebhook pin after verifying delivery through the Gateway, or use legacyWebhook:false to override an inherited endpoint.` : "No legacy listener is configured."}`);
6366
6167
  await waitUntilAbort(abortSignal, cleanup);
6367
- if (listenerError) throw listenerError;
6368
6168
  } finally {
6369
6169
  await cleanup();
6370
6170
  }
@@ -6552,9 +6352,9 @@ function createFeishuVcMeetingInvitedHandler(params) {
6552
6352
  //#endregion
6553
6353
  //#region extensions/feishu/src/sequential-key.ts
6554
6354
  function getFeishuSequentialKey(params) {
6555
- const { accountId, event, botOpenId, botName, preparedContent } = params;
6355
+ const { accountId, event, botOpenId, preparedContent } = params;
6556
6356
  const baseKey = `feishu:${accountId}:${event.message.chat_id?.trim() || "unknown"}`;
6557
- const text = (preparedContent ?? parseFeishuMessageEvent(event, botOpenId, botName).content).trim();
6357
+ const text = (preparedContent ?? parseFeishuMessageEvent(event, botOpenId).content).trim();
6558
6358
  if (isAbortRequestText(text)) return `${baseKey}:control`;
6559
6359
  if (isBtwRequestText(text)) return `${baseKey}:btw`;
6560
6360
  return baseKey;
@@ -6570,7 +6370,7 @@ async function resolveReactionSyntheticEvent(params) {
6570
6370
  const senderUserId = event.user_id?.user_id?.trim();
6571
6371
  const senderId = senderOpenId || senderUserId;
6572
6372
  if (!emoji || !messageId || !senderId) return null;
6573
- const { resolveFeishuAccount } = await import("./accounts-wRqItHug.mjs").then((n) => n.t);
6373
+ const { resolveFeishuAccount } = await import("./doctor-contract-B1B9ogdd.mjs").then((n) => n.c);
6574
6374
  const reactionNotifications = resolveFeishuAccount({
6575
6375
  cfg,
6576
6376
  accountId
@@ -6703,7 +6503,6 @@ function registerEventHandlers(eventDispatcher, context) {
6703
6503
  cfg,
6704
6504
  event: syntheticEvent,
6705
6505
  botOpenId: myBotId,
6706
- botName: botNames.get(accountId),
6707
6506
  runtime,
6708
6507
  channelRuntime,
6709
6508
  chatHistories,
@@ -6722,10 +6521,9 @@ function registerEventHandlers(eventDispatcher, context) {
6722
6521
  isAccountActive: context.isAccountActive,
6723
6522
  trackTask: context.trackTask,
6724
6523
  handleMessage: handleFeishuMessage,
6725
- resolveDebounceText: ({ event, botOpenId, botName }) => parseFeishuMessageEvent(event, botOpenId, botName).content,
6524
+ resolveDebounceText: ({ event, botOpenId }) => parseFeishuMessageEvent(event, botOpenId).content,
6726
6525
  hasProcessedMessage: hasProcessedFeishuMessage,
6727
6526
  getBotOpenId: (id) => botOpenIds.get(id),
6728
- getBotName: (id) => botNames.get(id),
6729
6527
  resolveSequentialKey: getFeishuSequentialKey,
6730
6528
  resolveIngressLifecycle: context.resolveIngressLifecycle,
6731
6529
  ...context.statusSink ? { statusSink: context.statusSink } : {}
@@ -6811,13 +6609,12 @@ async function monitorSingleAccount(params) {
6811
6609
  const botOpenIdSource = params.botOpenIdSource ?? { kind: "fetch" };
6812
6610
  const botIdentity = botOpenIdSource.kind === "prefetched" ? {
6813
6611
  botOpenId: botOpenIdSource.botOpenId,
6814
- botName: botOpenIdSource.botName,
6815
6612
  source: botOpenIdSource.source
6816
6613
  } : await fetchBotIdentityForMonitor(account, {
6817
6614
  runtime,
6818
6615
  abortSignal
6819
6616
  });
6820
- const { botOpenId } = applyBotIdentityState(accountId, botIdentity);
6617
+ const botOpenId = applyBotIdentityState(accountId, botIdentity);
6821
6618
  log(`feishu[${accountId}]: bot open_id resolved: ${botOpenId ?? "unknown"}`);
6822
6619
  if ((!botOpenId || botIdentity.source === "cache") && !abortSignal?.aborted) startBotIdentityRecovery({
6823
6620
  account,