@larksuite/openclaw-lark 2025.7.15-beta.0

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 (426) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +76 -0
  3. package/bin/openclaw-lark.js +39 -0
  4. package/index.d.ts +36 -0
  5. package/index.js +188 -0
  6. package/openclaw.plugin.json +64 -0
  7. package/package.json +63 -0
  8. package/secret-contract-api.d.ts +15 -0
  9. package/secret-contract-api.js +78 -0
  10. package/skills/feishu-bitable/SKILL.md +248 -0
  11. package/skills/feishu-bitable/references/examples.md +813 -0
  12. package/skills/feishu-bitable/references/field-properties.md +763 -0
  13. package/skills/feishu-bitable/references/record-values.md +911 -0
  14. package/skills/feishu-calendar/SKILL.md +242 -0
  15. package/skills/feishu-channel-rules/SKILL.md +18 -0
  16. package/skills/feishu-channel-rules/references/markdown-syntax.md +138 -0
  17. package/skills/feishu-create-doc/SKILL.md +719 -0
  18. package/skills/feishu-fetch-doc/SKILL.md +93 -0
  19. package/skills/feishu-im-read/SKILL.md +163 -0
  20. package/skills/feishu-task/SKILL.md +340 -0
  21. package/skills/feishu-troubleshoot/SKILL.md +70 -0
  22. package/skills/feishu-update-doc/SKILL.md +285 -0
  23. package/src/card/builder.d.ts +152 -0
  24. package/src/card/builder.js +794 -0
  25. package/src/card/card-error.d.ts +91 -0
  26. package/src/card/card-error.js +206 -0
  27. package/src/card/cardkit.d.ts +90 -0
  28. package/src/card/cardkit.js +203 -0
  29. package/src/card/flush-controller.d.ts +45 -0
  30. package/src/card/flush-controller.js +138 -0
  31. package/src/card/image-resolver.d.ts +45 -0
  32. package/src/card/image-resolver.js +116 -0
  33. package/src/card/markdown-style.d.ts +16 -0
  34. package/src/card/markdown-style.js +106 -0
  35. package/src/card/reasoning-utils.d.ts +14 -0
  36. package/src/card/reasoning-utils.js +64 -0
  37. package/src/card/reply-dispatcher-types.d.ts +132 -0
  38. package/src/card/reply-dispatcher-types.js +61 -0
  39. package/src/card/reply-dispatcher.d.ts +15 -0
  40. package/src/card/reply-dispatcher.js +447 -0
  41. package/src/card/reply-mode.d.ts +41 -0
  42. package/src/card/reply-mode.js +70 -0
  43. package/src/card/streaming-card-controller.d.ts +118 -0
  44. package/src/card/streaming-card-controller.js +1045 -0
  45. package/src/card/tool-use-config.d.ts +26 -0
  46. package/src/card/tool-use-config.js +76 -0
  47. package/src/card/tool-use-display.d.ts +37 -0
  48. package/src/card/tool-use-display.js +476 -0
  49. package/src/card/tool-use-trace-store.d.ts +51 -0
  50. package/src/card/tool-use-trace-store.js +271 -0
  51. package/src/card/unavailable-guard.d.ts +35 -0
  52. package/src/card/unavailable-guard.js +87 -0
  53. package/src/channel/abort-detect.d.ts +47 -0
  54. package/src/channel/abort-detect.js +219 -0
  55. package/src/channel/chat-queue.d.ts +41 -0
  56. package/src/channel/chat-queue.js +68 -0
  57. package/src/channel/config-adapter.d.ts +23 -0
  58. package/src/channel/config-adapter.js +107 -0
  59. package/src/channel/directory.d.ts +57 -0
  60. package/src/channel/directory.js +197 -0
  61. package/src/channel/event-handlers.d.ts +17 -0
  62. package/src/channel/event-handlers.js +380 -0
  63. package/src/channel/interactive-dispatch.d.ts +59 -0
  64. package/src/channel/interactive-dispatch.js +195 -0
  65. package/src/channel/monitor.d.ts +17 -0
  66. package/src/channel/monitor.js +140 -0
  67. package/src/channel/onboarding-config.d.ts +18 -0
  68. package/src/channel/onboarding-config.js +96 -0
  69. package/src/channel/onboarding-migrate.d.ts +25 -0
  70. package/src/channel/onboarding-migrate.js +70 -0
  71. package/src/channel/onboarding.d.ts +12 -0
  72. package/src/channel/onboarding.js +300 -0
  73. package/src/channel/plugin.d.ts +13 -0
  74. package/src/channel/plugin.js +310 -0
  75. package/src/channel/probe.d.ts +14 -0
  76. package/src/channel/probe.js +24 -0
  77. package/src/channel/types.d.ts +37 -0
  78. package/src/channel/types.js +8 -0
  79. package/src/commands/auth.d.ts +21 -0
  80. package/src/commands/auth.js +165 -0
  81. package/src/commands/diagnose.d.ts +69 -0
  82. package/src/commands/diagnose.js +848 -0
  83. package/src/commands/doctor.d.ts +27 -0
  84. package/src/commands/doctor.js +588 -0
  85. package/src/commands/index.d.ts +25 -0
  86. package/src/commands/index.js +219 -0
  87. package/src/commands/locale.d.ts +7 -0
  88. package/src/commands/locale.js +8 -0
  89. package/src/core/accounts.d.ts +51 -0
  90. package/src/core/accounts.js +219 -0
  91. package/src/core/agent-config.d.ts +100 -0
  92. package/src/core/agent-config.js +148 -0
  93. package/src/core/api-error.d.ts +48 -0
  94. package/src/core/api-error.js +117 -0
  95. package/src/core/app-owner-fallback.d.ts +22 -0
  96. package/src/core/app-owner-fallback.js +39 -0
  97. package/src/core/app-scope-checker.d.ts +87 -0
  98. package/src/core/app-scope-checker.js +198 -0
  99. package/src/core/auth-errors.d.ts +144 -0
  100. package/src/core/auth-errors.js +160 -0
  101. package/src/core/card-action-operator.d.ts +33 -0
  102. package/src/core/card-action-operator.js +30 -0
  103. package/src/core/chat-info-cache.d.ts +67 -0
  104. package/src/core/chat-info-cache.js +165 -0
  105. package/src/core/comment-target.d.ts +65 -0
  106. package/src/core/comment-target.js +100 -0
  107. package/src/core/config-schema.d.ts +490 -0
  108. package/src/core/config-schema.js +223 -0
  109. package/src/core/device-flow.d.ts +77 -0
  110. package/src/core/device-flow.js +217 -0
  111. package/src/core/domains.d.ts +18 -0
  112. package/src/core/domains.js +34 -0
  113. package/src/core/feishu-fetch.d.ts +18 -0
  114. package/src/core/feishu-fetch.js +28 -0
  115. package/src/core/footer-config.d.ts +24 -0
  116. package/src/core/footer-config.js +51 -0
  117. package/src/core/lark-client.d.ts +125 -0
  118. package/src/core/lark-client.js +468 -0
  119. package/src/core/lark-logger.d.ts +23 -0
  120. package/src/core/lark-logger.js +160 -0
  121. package/src/core/lark-ticket.d.ts +29 -0
  122. package/src/core/lark-ticket.js +40 -0
  123. package/src/core/message-unavailable.d.ts +53 -0
  124. package/src/core/message-unavailable.js +142 -0
  125. package/src/core/owner-policy.d.ts +32 -0
  126. package/src/core/owner-policy.js +55 -0
  127. package/src/core/permission-url.d.ts +22 -0
  128. package/src/core/permission-url.js +76 -0
  129. package/src/core/raw-request.d.ts +27 -0
  130. package/src/core/raw-request.js +90 -0
  131. package/src/core/runtime-store.d.ts +13 -0
  132. package/src/core/runtime-store.js +29 -0
  133. package/src/core/scope-manager.d.ts +168 -0
  134. package/src/core/scope-manager.js +224 -0
  135. package/src/core/sdk-compat.d.ts +20 -0
  136. package/src/core/sdk-compat.js +28 -0
  137. package/src/core/security-check.d.ts +72 -0
  138. package/src/core/security-check.js +184 -0
  139. package/src/core/shutdown-hooks.d.ts +22 -0
  140. package/src/core/shutdown-hooks.js +61 -0
  141. package/src/core/synthetic-target.d.ts +33 -0
  142. package/src/core/synthetic-target.js +40 -0
  143. package/src/core/targets.d.ts +60 -0
  144. package/src/core/targets.js +173 -0
  145. package/src/core/token-store.d.ts +54 -0
  146. package/src/core/token-store.js +326 -0
  147. package/src/core/tool-client.d.ts +176 -0
  148. package/src/core/tool-client.js +426 -0
  149. package/src/core/tool-scopes.d.ts +156 -0
  150. package/src/core/tool-scopes.js +344 -0
  151. package/src/core/tools-config.d.ts +55 -0
  152. package/src/core/tools-config.js +143 -0
  153. package/src/core/types.d.ts +91 -0
  154. package/src/core/types.js +12 -0
  155. package/src/core/uat-client.d.ts +46 -0
  156. package/src/core/uat-client.js +192 -0
  157. package/src/core/version.d.ts +31 -0
  158. package/src/core/version.js +69 -0
  159. package/src/messaging/converters/audio.d.ts +8 -0
  160. package/src/messaging/converters/audio.js +24 -0
  161. package/src/messaging/converters/calendar.d.ts +13 -0
  162. package/src/messaging/converters/calendar.js +56 -0
  163. package/src/messaging/converters/content-converter-helpers.d.ts +30 -0
  164. package/src/messaging/converters/content-converter-helpers.js +82 -0
  165. package/src/messaging/converters/content-converter.d.ts +24 -0
  166. package/src/messaging/converters/content-converter.js +40 -0
  167. package/src/messaging/converters/file.d.ts +8 -0
  168. package/src/messaging/converters/file.js +24 -0
  169. package/src/messaging/converters/folder.d.ts +8 -0
  170. package/src/messaging/converters/folder.js +24 -0
  171. package/src/messaging/converters/hongbao.d.ts +8 -0
  172. package/src/messaging/converters/hongbao.js +20 -0
  173. package/src/messaging/converters/image.d.ts +8 -0
  174. package/src/messaging/converters/image.js +22 -0
  175. package/src/messaging/converters/index.d.ts +8 -0
  176. package/src/messaging/converters/index.js +53 -0
  177. package/src/messaging/converters/interactive/card-converter.d.ts +76 -0
  178. package/src/messaging/converters/interactive/card-converter.js +1177 -0
  179. package/src/messaging/converters/interactive/card-utils.d.ts +9 -0
  180. package/src/messaging/converters/interactive/card-utils.js +47 -0
  181. package/src/messaging/converters/interactive/index.d.ts +8 -0
  182. package/src/messaging/converters/interactive/index.js +25 -0
  183. package/src/messaging/converters/interactive/legacy.d.ts +11 -0
  184. package/src/messaging/converters/interactive/legacy.js +60 -0
  185. package/src/messaging/converters/interactive/types.d.ts +23 -0
  186. package/src/messaging/converters/interactive/types.js +27 -0
  187. package/src/messaging/converters/location.d.ts +8 -0
  188. package/src/messaging/converters/location.js +23 -0
  189. package/src/messaging/converters/merge-forward.d.ts +32 -0
  190. package/src/messaging/converters/merge-forward.js +235 -0
  191. package/src/messaging/converters/post.d.ts +11 -0
  192. package/src/messaging/converters/post.js +235 -0
  193. package/src/messaging/converters/share.d.ts +9 -0
  194. package/src/messaging/converters/share.js +28 -0
  195. package/src/messaging/converters/sticker.d.ts +8 -0
  196. package/src/messaging/converters/sticker.js +22 -0
  197. package/src/messaging/converters/system.d.ts +12 -0
  198. package/src/messaging/converters/system.js +36 -0
  199. package/src/messaging/converters/text.d.ts +8 -0
  200. package/src/messaging/converters/text.js +18 -0
  201. package/src/messaging/converters/todo.d.ts +8 -0
  202. package/src/messaging/converters/todo.js +45 -0
  203. package/src/messaging/converters/types.d.ts +114 -0
  204. package/src/messaging/converters/types.js +8 -0
  205. package/src/messaging/converters/unknown.d.ts +8 -0
  206. package/src/messaging/converters/unknown.js +20 -0
  207. package/src/messaging/converters/utils.d.ts +22 -0
  208. package/src/messaging/converters/utils.js +57 -0
  209. package/src/messaging/converters/video-chat.d.ts +8 -0
  210. package/src/messaging/converters/video-chat.js +31 -0
  211. package/src/messaging/converters/video.d.ts +8 -0
  212. package/src/messaging/converters/video.js +35 -0
  213. package/src/messaging/converters/vote.d.ts +8 -0
  214. package/src/messaging/converters/vote.js +28 -0
  215. package/src/messaging/inbound/bot-content.d.ts +84 -0
  216. package/src/messaging/inbound/bot-content.js +117 -0
  217. package/src/messaging/inbound/bot-loop-guard.d.ts +48 -0
  218. package/src/messaging/inbound/bot-loop-guard.js +89 -0
  219. package/src/messaging/inbound/comment-context.d.ts +82 -0
  220. package/src/messaging/inbound/comment-context.js +353 -0
  221. package/src/messaging/inbound/comment-handler.d.ts +30 -0
  222. package/src/messaging/inbound/comment-handler.js +269 -0
  223. package/src/messaging/inbound/dedup.d.ts +59 -0
  224. package/src/messaging/inbound/dedup.js +121 -0
  225. package/src/messaging/inbound/dispatch-builders.d.ts +104 -0
  226. package/src/messaging/inbound/dispatch-builders.js +241 -0
  227. package/src/messaging/inbound/dispatch-commands.d.ts +22 -0
  228. package/src/messaging/inbound/dispatch-commands.js +131 -0
  229. package/src/messaging/inbound/dispatch-context.d.ts +67 -0
  230. package/src/messaging/inbound/dispatch-context.js +153 -0
  231. package/src/messaging/inbound/dispatch.d.ts +50 -0
  232. package/src/messaging/inbound/dispatch.js +477 -0
  233. package/src/messaging/inbound/enrich.d.ts +102 -0
  234. package/src/messaging/inbound/enrich.js +236 -0
  235. package/src/messaging/inbound/gate-effects.d.ts +23 -0
  236. package/src/messaging/inbound/gate-effects.js +46 -0
  237. package/src/messaging/inbound/gate.d.ts +91 -0
  238. package/src/messaging/inbound/gate.js +342 -0
  239. package/src/messaging/inbound/handler-registry.d.ts +25 -0
  240. package/src/messaging/inbound/handler-registry.js +23 -0
  241. package/src/messaging/inbound/handler.d.ts +37 -0
  242. package/src/messaging/inbound/handler.js +286 -0
  243. package/src/messaging/inbound/media-resolver.d.ts +32 -0
  244. package/src/messaging/inbound/media-resolver.js +91 -0
  245. package/src/messaging/inbound/mention-registry.d.ts +59 -0
  246. package/src/messaging/inbound/mention-registry.js +115 -0
  247. package/src/messaging/inbound/mention.d.ts +48 -0
  248. package/src/messaging/inbound/mention.js +102 -0
  249. package/src/messaging/inbound/parse-io.d.ts +50 -0
  250. package/src/messaging/inbound/parse-io.js +86 -0
  251. package/src/messaging/inbound/parse.d.ts +28 -0
  252. package/src/messaging/inbound/parse.js +128 -0
  253. package/src/messaging/inbound/permission.d.ts +17 -0
  254. package/src/messaging/inbound/permission.js +44 -0
  255. package/src/messaging/inbound/policy.d.ts +95 -0
  256. package/src/messaging/inbound/policy.js +168 -0
  257. package/src/messaging/inbound/reaction-handler.d.ts +62 -0
  258. package/src/messaging/inbound/reaction-handler.js +259 -0
  259. package/src/messaging/inbound/sentinel-store.d.ts +37 -0
  260. package/src/messaging/inbound/sentinel-store.js +98 -0
  261. package/src/messaging/inbound/synthetic-message.d.ts +26 -0
  262. package/src/messaging/inbound/synthetic-message.js +59 -0
  263. package/src/messaging/inbound/user-name-cache-store.d.ts +62 -0
  264. package/src/messaging/inbound/user-name-cache-store.js +236 -0
  265. package/src/messaging/inbound/user-name-cache.d.ts +78 -0
  266. package/src/messaging/inbound/user-name-cache.js +306 -0
  267. package/src/messaging/inbound/vc-meeting-invited-handler.d.ts +20 -0
  268. package/src/messaging/inbound/vc-meeting-invited-handler.js +236 -0
  269. package/src/messaging/inbound/vc-sender.d.ts +41 -0
  270. package/src/messaging/inbound/vc-sender.js +53 -0
  271. package/src/messaging/outbound/actions.d.ts +16 -0
  272. package/src/messaging/outbound/actions.js +329 -0
  273. package/src/messaging/outbound/bot-peer-context.d.ts +42 -0
  274. package/src/messaging/outbound/bot-peer-context.js +40 -0
  275. package/src/messaging/outbound/chat-manage.d.ts +64 -0
  276. package/src/messaging/outbound/chat-manage.js +117 -0
  277. package/src/messaging/outbound/deliver.d.ts +186 -0
  278. package/src/messaging/outbound/deliver.js +410 -0
  279. package/src/messaging/outbound/fetch.d.ts +12 -0
  280. package/src/messaging/outbound/fetch.js +17 -0
  281. package/src/messaging/outbound/forward.d.ts +26 -0
  282. package/src/messaging/outbound/forward.js +51 -0
  283. package/src/messaging/outbound/media-url-utils.d.ts +29 -0
  284. package/src/messaging/outbound/media-url-utils.js +172 -0
  285. package/src/messaging/outbound/media.d.ts +260 -0
  286. package/src/messaging/outbound/media.js +865 -0
  287. package/src/messaging/outbound/normalize-mentions.d.ts +50 -0
  288. package/src/messaging/outbound/normalize-mentions.js +166 -0
  289. package/src/messaging/outbound/outbound-mention.d.ts +41 -0
  290. package/src/messaging/outbound/outbound-mention.js +112 -0
  291. package/src/messaging/outbound/outbound.d.ts +79 -0
  292. package/src/messaging/outbound/outbound.js +195 -0
  293. package/src/messaging/outbound/reactions.d.ts +124 -0
  294. package/src/messaging/outbound/reactions.js +384 -0
  295. package/src/messaging/outbound/send.d.ts +153 -0
  296. package/src/messaging/outbound/send.js +417 -0
  297. package/src/messaging/outbound/typing.d.ts +60 -0
  298. package/src/messaging/outbound/typing.js +139 -0
  299. package/src/messaging/shared/message-lookup.d.ts +54 -0
  300. package/src/messaging/shared/message-lookup.js +120 -0
  301. package/src/messaging/types.d.ts +316 -0
  302. package/src/messaging/types.js +11 -0
  303. package/src/tools/ask-user-question.d.ts +32 -0
  304. package/src/tools/ask-user-question.js +922 -0
  305. package/src/tools/auto-auth.d.ts +57 -0
  306. package/src/tools/auto-auth.js +904 -0
  307. package/src/tools/helpers.d.ts +264 -0
  308. package/src/tools/helpers.js +389 -0
  309. package/src/tools/mcp/doc/create.d.ts +12 -0
  310. package/src/tools/mcp/doc/create.js +47 -0
  311. package/src/tools/mcp/doc/fetch.d.ts +12 -0
  312. package/src/tools/mcp/doc/fetch.js +39 -0
  313. package/src/tools/mcp/doc/index.d.ts +12 -0
  314. package/src/tools/mcp/doc/index.js +50 -0
  315. package/src/tools/mcp/doc/update.d.ts +12 -0
  316. package/src/tools/mcp/doc/update.js +64 -0
  317. package/src/tools/mcp/shared.d.ts +59 -0
  318. package/src/tools/mcp/shared.js +239 -0
  319. package/src/tools/oapi/bitable/app-table-field.d.ts +16 -0
  320. package/src/tools/oapi/bitable/app-table-field.js +225 -0
  321. package/src/tools/oapi/bitable/app-table-record.d.ts +20 -0
  322. package/src/tools/oapi/bitable/app-table-record.js +439 -0
  323. package/src/tools/oapi/bitable/app-table-view.d.ts +16 -0
  324. package/src/tools/oapi/bitable/app-table-view.js +172 -0
  325. package/src/tools/oapi/bitable/app-table.d.ts +17 -0
  326. package/src/tools/oapi/bitable/app-table.js +195 -0
  327. package/src/tools/oapi/bitable/app.d.ts +18 -0
  328. package/src/tools/oapi/bitable/app.js +189 -0
  329. package/src/tools/oapi/bitable/index.d.ts +9 -0
  330. package/src/tools/oapi/bitable/index.js +17 -0
  331. package/src/tools/oapi/calendar/calendar.d.ts +15 -0
  332. package/src/tools/oapi/calendar/calendar.js +125 -0
  333. package/src/tools/oapi/calendar/event-attendee.d.ts +14 -0
  334. package/src/tools/oapi/calendar/event-attendee.js +161 -0
  335. package/src/tools/oapi/calendar/event.d.ts +16 -0
  336. package/src/tools/oapi/calendar/event.js +712 -0
  337. package/src/tools/oapi/calendar/freebusy.d.ts +13 -0
  338. package/src/tools/oapi/calendar/freebusy.js +114 -0
  339. package/src/tools/oapi/calendar/index.d.ts +8 -0
  340. package/src/tools/oapi/calendar/index.js +15 -0
  341. package/src/tools/oapi/chat/chat.d.ts +16 -0
  342. package/src/tools/oapi/chat/chat.js +127 -0
  343. package/src/tools/oapi/chat/index.d.ts +10 -0
  344. package/src/tools/oapi/chat/index.js +23 -0
  345. package/src/tools/oapi/chat/members.d.ts +11 -0
  346. package/src/tools/oapi/chat/members.js +84 -0
  347. package/src/tools/oapi/common/get-user.d.ts +12 -0
  348. package/src/tools/oapi/common/get-user.js +109 -0
  349. package/src/tools/oapi/common/index.d.ts +6 -0
  350. package/src/tools/oapi/common/index.js +11 -0
  351. package/src/tools/oapi/common/search-user.d.ts +11 -0
  352. package/src/tools/oapi/common/search-user.js +76 -0
  353. package/src/tools/oapi/drive/doc-comments.d.ts +15 -0
  354. package/src/tools/oapi/drive/doc-comments.js +351 -0
  355. package/src/tools/oapi/drive/doc-media.d.ts +19 -0
  356. package/src/tools/oapi/drive/doc-media.js +371 -0
  357. package/src/tools/oapi/drive/file.d.ts +19 -0
  358. package/src/tools/oapi/drive/file.js +519 -0
  359. package/src/tools/oapi/drive/index.d.ts +12 -0
  360. package/src/tools/oapi/drive/index.js +45 -0
  361. package/src/tools/oapi/helpers.d.ts +183 -0
  362. package/src/tools/oapi/helpers.js +385 -0
  363. package/src/tools/oapi/im/format-messages.d.ts +50 -0
  364. package/src/tools/oapi/im/format-messages.js +169 -0
  365. package/src/tools/oapi/im/index.d.ts +10 -0
  366. package/src/tools/oapi/im/index.js +25 -0
  367. package/src/tools/oapi/im/message-read.d.ts +13 -0
  368. package/src/tools/oapi/im/message-read.js +419 -0
  369. package/src/tools/oapi/im/message.d.ts +16 -0
  370. package/src/tools/oapi/im/message.js +152 -0
  371. package/src/tools/oapi/im/resource.d.ts +13 -0
  372. package/src/tools/oapi/im/resource.js +186 -0
  373. package/src/tools/oapi/im/time-utils.d.ts +46 -0
  374. package/src/tools/oapi/im/time-utils.js +212 -0
  375. package/src/tools/oapi/im/user-name-uat.d.ts +26 -0
  376. package/src/tools/oapi/im/user-name-uat.js +143 -0
  377. package/src/tools/oapi/index.d.ts +11 -0
  378. package/src/tools/oapi/index.js +64 -0
  379. package/src/tools/oapi/sdk-types.d.ts +96 -0
  380. package/src/tools/oapi/sdk-types.js +13 -0
  381. package/src/tools/oapi/search/doc-search.d.ts +13 -0
  382. package/src/tools/oapi/search/doc-search.js +194 -0
  383. package/src/tools/oapi/search/index.d.ts +12 -0
  384. package/src/tools/oapi/search/index.js +37 -0
  385. package/src/tools/oapi/sheets/index.d.ts +12 -0
  386. package/src/tools/oapi/sheets/index.js +35 -0
  387. package/src/tools/oapi/sheets/sheet.d.ts +16 -0
  388. package/src/tools/oapi/sheets/sheet.js +688 -0
  389. package/src/tools/oapi/task/attachment.d.ts +18 -0
  390. package/src/tools/oapi/task/attachment.js +107 -0
  391. package/src/tools/oapi/task/comment.d.ts +15 -0
  392. package/src/tools/oapi/task/comment.js +149 -0
  393. package/src/tools/oapi/task/index.d.ts +11 -0
  394. package/src/tools/oapi/task/index.js +21 -0
  395. package/src/tools/oapi/task/section.d.ts +17 -0
  396. package/src/tools/oapi/task/section.js +293 -0
  397. package/src/tools/oapi/task/subtask.d.ts +14 -0
  398. package/src/tools/oapi/task/subtask.js +171 -0
  399. package/src/tools/oapi/task/task.d.ts +19 -0
  400. package/src/tools/oapi/task/task.js +512 -0
  401. package/src/tools/oapi/task/task_agent.d.ts +14 -0
  402. package/src/tools/oapi/task/task_agent.js +108 -0
  403. package/src/tools/oapi/task/tasklist.d.ts +19 -0
  404. package/src/tools/oapi/task/tasklist.js +276 -0
  405. package/src/tools/oapi/wiki/index.d.ts +12 -0
  406. package/src/tools/oapi/wiki/index.js +42 -0
  407. package/src/tools/oapi/wiki/space-node.d.ts +17 -0
  408. package/src/tools/oapi/wiki/space-node.js +233 -0
  409. package/src/tools/oapi/wiki/space.d.ts +15 -0
  410. package/src/tools/oapi/wiki/space.js +133 -0
  411. package/src/tools/oauth-batch-auth.d.ts +11 -0
  412. package/src/tools/oauth-batch-auth.js +150 -0
  413. package/src/tools/oauth-cards.d.ts +39 -0
  414. package/src/tools/oauth-cards.js +324 -0
  415. package/src/tools/oauth.d.ts +47 -0
  416. package/src/tools/oauth.js +592 -0
  417. package/src/tools/onboarding-auth.d.ts +27 -0
  418. package/src/tools/onboarding-auth.js +133 -0
  419. package/src/tools/tat/im/index.d.ts +15 -0
  420. package/src/tools/tat/im/index.js +22 -0
  421. package/src/tools/tat/im/resource.d.ts +15 -0
  422. package/src/tools/tat/im/resource.js +192 -0
  423. package/tsdown.config.d.ts +2 -0
  424. package/tsdown.config.js +25 -0
  425. package/vitest.config.d.ts +2 -0
  426. package/vitest.config.js +12 -0
@@ -0,0 +1,380 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Event handlers for the Feishu WebSocket monitor.
7
+ *
8
+ * Extracted from monitor.ts to improve testability and reduce
9
+ * function size. Each handler receives a MonitorContext with all
10
+ * dependencies needed to process the event.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.handleMessageEvent = handleMessageEvent;
14
+ exports.handleReactionEvent = handleReactionEvent;
15
+ exports.handleBotMembershipEvent = handleBotMembershipEvent;
16
+ exports.handleVcMeetingInvitedEvent = handleVcMeetingInvitedEvent;
17
+ exports.handleCommentEvent = handleCommentEvent;
18
+ exports.handleCardActionEvent = handleCardActionEvent;
19
+ const handler_1 = require("../messaging/inbound/handler.js");
20
+ const reaction_handler_1 = require("../messaging/inbound/reaction-handler.js");
21
+ const comment_handler_1 = require("../messaging/inbound/comment-handler.js");
22
+ const vc_meeting_invited_handler_1 = require("../messaging/inbound/vc-meeting-invited-handler.js");
23
+ const vc_sender_1 = require("../messaging/inbound/vc-sender.js");
24
+ const comment_context_1 = require("../messaging/inbound/comment-context.js");
25
+ const dedup_1 = require("../messaging/inbound/dedup.js");
26
+ const lark_ticket_1 = require("../core/lark-ticket.js");
27
+ const lark_logger_1 = require("../core/lark-logger.js");
28
+ const auto_auth_1 = require("../tools/auto-auth.js");
29
+ const ask_user_question_1 = require("../tools/ask-user-question.js");
30
+ const chat_queue_1 = require("./chat-queue.js");
31
+ const abort_detect_1 = require("./abort-detect.js");
32
+ const interactive_dispatch_1 = require("./interactive-dispatch.js");
33
+ const elog = (0, lark_logger_1.larkLogger)('channel/event-handlers');
34
+ // ---------------------------------------------------------------------------
35
+ // Event ownership validation
36
+ // ---------------------------------------------------------------------------
37
+ /**
38
+ * Verify that the event's app_id matches the current account.
39
+ *
40
+ * Lark SDK EventDispatcher flattens the v2 envelope header (which
41
+ * contains `app_id`) into the handler `data` object, so `app_id` is
42
+ * available directly on `data`.
43
+ *
44
+ * Returns `false` (discard event) when the app_id does not match.
45
+ */
46
+ function isEventOwnershipValid(ctx, data) {
47
+ const expectedAppId = ctx.lark.account.appId;
48
+ if (!expectedAppId)
49
+ return true; // appId not configured — skip check
50
+ const eventAppId = data.app_id;
51
+ if (eventAppId == null)
52
+ return true; // SDK did not provide app_id — defensive skip
53
+ if (eventAppId !== expectedAppId) {
54
+ elog.warn('event app_id mismatch, discarding', {
55
+ accountId: ctx.accountId,
56
+ expected: expectedAppId,
57
+ received: String(eventAppId),
58
+ });
59
+ return false;
60
+ }
61
+ return true;
62
+ }
63
+ // ---------------------------------------------------------------------------
64
+ // Message handler
65
+ // ---------------------------------------------------------------------------
66
+ async function handleMessageEvent(ctx, data) {
67
+ if (!isEventOwnershipValid(ctx, data))
68
+ return;
69
+ const { accountId, log, error } = ctx;
70
+ try {
71
+ const event = data;
72
+ // Self-echo hard filter — drop messages authored by this very bot before
73
+ // dedup and enqueue. Prevents self-reply loops; the primary guardrail
74
+ // against bot-to-bot ping-pong.
75
+ //
76
+ // NOTE: if botOpenId is not yet populated (startup race before probe
77
+ // resolves), this filter is skipped. The downstream bot-sender gate
78
+ // (checkBotSenderGate) acts as fallback — bot messages default to
79
+ // `allowBots='mentions'`, so in groups they require an explicit @-mention
80
+ // of this bot to pass; DMs are pass-through under the default.
81
+ const senderOpenId = event.sender?.sender_id?.open_id;
82
+ const botOpenId = ctx.lark.botOpenId;
83
+ if (botOpenId && senderOpenId && senderOpenId === botOpenId) {
84
+ log(`feishu[${accountId}]: drop self-echo message ${event.message?.message_id ?? 'unknown'}`);
85
+ return;
86
+ }
87
+ const msgId = event.message?.message_id ?? 'unknown';
88
+ const chatId = event.message?.chat_id ?? '';
89
+ // In topic groups, reply events carry root_id but not thread_id.
90
+ // Use root_id as fallback so different topics get separate queue keys
91
+ // and can be processed in parallel.
92
+ const threadId = event.message?.thread_id || event.message?.root_id || undefined;
93
+ // Dedup — skip duplicate messages (e.g. from WebSocket reconnects).
94
+ if (!ctx.messageDedup.tryRecord(msgId, accountId)) {
95
+ log(`feishu[${accountId}]: duplicate message ${msgId}, skipping`);
96
+ return;
97
+ }
98
+ // Expiry — discard stale messages from reconnect replay.
99
+ if ((0, dedup_1.isMessageExpired)(event.message?.create_time)) {
100
+ log(`feishu[${accountId}]: message ${msgId} expired, discarding`);
101
+ return;
102
+ }
103
+ // ---- Abort fast-path ----
104
+ // If the message looks like an abort trigger and there is an active
105
+ // reply dispatcher for this chat, fire abortCard() immediately
106
+ // (before the message enters the serial queue) so the streaming
107
+ // card is terminated without waiting for the current task.
108
+ const abortText = (0, abort_detect_1.extractRawTextFromEvent)(event);
109
+ if (abortText && (0, abort_detect_1.isLikelyAbortText)(abortText)) {
110
+ const queueKey = (0, chat_queue_1.buildQueueKey)(accountId, chatId, threadId);
111
+ if ((0, chat_queue_1.hasActiveTask)(queueKey)) {
112
+ const active = (0, chat_queue_1.getActiveDispatcher)(queueKey);
113
+ if (active) {
114
+ log(`feishu[${accountId}]: abort fast-path triggered for chat ${chatId} (text="${abortText}")`);
115
+ active.abortController?.abort();
116
+ active.abortCard().catch((err) => {
117
+ error(`feishu[${accountId}]: abort fast-path abortCard failed: ${String(err)}`);
118
+ });
119
+ }
120
+ }
121
+ }
122
+ const { status } = (0, chat_queue_1.enqueueFeishuChatTask)({
123
+ accountId,
124
+ chatId,
125
+ threadId,
126
+ task: async () => {
127
+ try {
128
+ await (0, lark_ticket_1.withTicket)({
129
+ messageId: msgId,
130
+ chatId,
131
+ accountId,
132
+ startTime: Date.now(),
133
+ senderOpenId: event.sender?.sender_id?.open_id || '',
134
+ chatType: event.message?.chat_type || undefined,
135
+ threadId,
136
+ }, () => (0, handler_1.handleFeishuMessage)({
137
+ cfg: ctx.cfg,
138
+ event,
139
+ botOpenId: ctx.lark.botOpenId,
140
+ runtime: ctx.runtime,
141
+ chatHistories: ctx.chatHistories,
142
+ accountId,
143
+ }));
144
+ }
145
+ catch (err) {
146
+ error(`feishu[${accountId}]: error handling message: ${String(err)}`);
147
+ }
148
+ },
149
+ });
150
+ log(`feishu[${accountId}]: message ${msgId} in chat ${chatId}${threadId ? ` thread ${threadId}` : ''} — ${status}`);
151
+ }
152
+ catch (err) {
153
+ error(`feishu[${accountId}]: error handling message: ${String(err)}`);
154
+ }
155
+ }
156
+ // ---------------------------------------------------------------------------
157
+ // Reaction handler
158
+ // ---------------------------------------------------------------------------
159
+ async function handleReactionEvent(ctx, data) {
160
+ if (!isEventOwnershipValid(ctx, data))
161
+ return;
162
+ const { accountId, log, error } = ctx;
163
+ try {
164
+ const event = data;
165
+ const msgId = event.message_id ?? 'unknown';
166
+ log(`feishu[${accountId}]: reaction event on message ${msgId}`);
167
+ // ---- Dedup: deterministic key based on message + emoji + operator ----
168
+ const emojiType = event.reaction_type?.emoji_type ?? '';
169
+ const operatorOpenId = event.user_id?.open_id ?? '';
170
+ const dedupKey = `${msgId}:reaction:${emojiType}:${operatorOpenId}`;
171
+ if (!ctx.messageDedup.tryRecord(dedupKey, accountId)) {
172
+ log(`feishu[${accountId}]: duplicate reaction ${dedupKey}, skipping`);
173
+ return;
174
+ }
175
+ // ---- Expiry: discard stale reaction events ----
176
+ if ((0, dedup_1.isMessageExpired)(event.action_time)) {
177
+ log(`feishu[${accountId}]: reaction on ${msgId} expired, discarding`);
178
+ return;
179
+ }
180
+ // ---- Pre-resolve real chatId before enqueuing ----
181
+ // The API call (3s timeout) runs outside the queue so it doesn't
182
+ // block the serial chain, and is read-only so ordering is irrelevant.
183
+ const preResolved = await (0, reaction_handler_1.resolveReactionContext)({
184
+ cfg: ctx.cfg,
185
+ event,
186
+ botOpenId: ctx.lark.botOpenId,
187
+ runtime: ctx.runtime,
188
+ accountId,
189
+ });
190
+ if (!preResolved)
191
+ return;
192
+ // ---- Enqueue with the real chatId (matches normal message queue key) ----
193
+ const { status } = (0, chat_queue_1.enqueueFeishuChatTask)({
194
+ accountId,
195
+ chatId: preResolved.chatId,
196
+ threadId: preResolved.threadId,
197
+ task: async () => {
198
+ try {
199
+ await (0, lark_ticket_1.withTicket)({
200
+ messageId: msgId,
201
+ chatId: preResolved.chatId,
202
+ accountId,
203
+ startTime: Date.now(),
204
+ senderOpenId: operatorOpenId,
205
+ chatType: preResolved.chatType,
206
+ threadId: preResolved.threadId,
207
+ }, () => (0, reaction_handler_1.handleFeishuReaction)({
208
+ cfg: ctx.cfg,
209
+ event,
210
+ botOpenId: ctx.lark.botOpenId,
211
+ runtime: ctx.runtime,
212
+ chatHistories: ctx.chatHistories,
213
+ accountId,
214
+ preResolved,
215
+ }));
216
+ }
217
+ catch (err) {
218
+ error(`feishu[${accountId}]: error handling reaction: ${String(err)}`);
219
+ }
220
+ },
221
+ });
222
+ log(`feishu[${accountId}]: reaction on ${msgId} (chatId=${preResolved.chatId}) — ${status}`);
223
+ }
224
+ catch (err) {
225
+ error(`feishu[${accountId}]: error handling reaction event: ${String(err)}`);
226
+ }
227
+ }
228
+ // ---------------------------------------------------------------------------
229
+ // Bot membership handler
230
+ // ---------------------------------------------------------------------------
231
+ async function handleBotMembershipEvent(ctx, data, action) {
232
+ if (!isEventOwnershipValid(ctx, data))
233
+ return;
234
+ const { accountId, log, error } = ctx;
235
+ try {
236
+ const event = data;
237
+ log(`feishu[${accountId}]: bot ${action} ${action === 'removed' ? 'from' : 'to'} chat ${event.chat_id}`);
238
+ }
239
+ catch (err) {
240
+ error(`feishu[${accountId}]: error handling bot ${action} event: ${String(err)}`);
241
+ }
242
+ }
243
+ // ---------------------------------------------------------------------------
244
+ // VC meeting invited handler
245
+ // ---------------------------------------------------------------------------
246
+ async function handleVcMeetingInvitedEvent(ctx, data) {
247
+ if (!isEventOwnershipValid(ctx, data))
248
+ return;
249
+ const { accountId, log, error } = ctx;
250
+ try {
251
+ const event = data;
252
+ const meetingNo = event.meeting?.meeting_no?.trim() ?? '';
253
+ const eventId = event.event_id?.trim() ?? '';
254
+ // Resolve the inviter identity through the shared helper so the
255
+ // diagnostics log and the dispatch handler always agree on the
256
+ // same sender semantics.
257
+ const sender = (0, vc_sender_1.resolveVcSender)(event);
258
+ const senderId = sender.senderId;
259
+ const invitedBotOpenId = event.bot?.id?.open_id?.trim() ?? '';
260
+ // VC invited origin/ownership diagnostics:
261
+ // - This handler is only reachable from the WebSocket monitor path.
262
+ // - We still log app_id/bot_open_id so operators can confirm the event
263
+ // is delivered to the expected bot/account, and see which required
264
+ // fields are missing when we skip.
265
+ const expectedAppId = ctx.lark.account.appId ?? '';
266
+ const eventAppId = event.app_id?.trim() ?? '';
267
+ log(`feishu[${accountId}]: vc invited event received (ingress=websocket)` +
268
+ `${eventId ? ` event_id=${eventId}` : ''}` +
269
+ `${eventAppId ? ` app_id=${eventAppId}` : ' app_id=<missing>'}` +
270
+ `${expectedAppId ? ` expected_app_id=${expectedAppId}` : ''}` +
271
+ `${invitedBotOpenId ? ` bot_open_id=${invitedBotOpenId}` : ' bot_open_id=<missing>'}` +
272
+ `${ctx.lark.botOpenId ? ` expected_bot_open_id=${ctx.lark.botOpenId}` : ''}` +
273
+ `${event.invite_time ? ` invite_time=${event.invite_time}` : ''}` +
274
+ ` meeting_no_present=${meetingNo ? 'true' : 'false'}` +
275
+ ` sender_present=${senderId ? 'true' : 'false'}` +
276
+ ` sender_from=${sender.fromFallback}`);
277
+ if (!meetingNo) {
278
+ log(`feishu[${accountId}]: vc invited event missing meeting_no, skipping`);
279
+ return;
280
+ }
281
+ if (!senderId) {
282
+ log(`feishu[${accountId}]: vc invited event missing inviter identity, skipping`);
283
+ return;
284
+ }
285
+ if (ctx.lark.botOpenId && invitedBotOpenId && invitedBotOpenId !== ctx.lark.botOpenId) {
286
+ log(`feishu[${accountId}]: vc invited event for another bot, expected=${ctx.lark.botOpenId}, got=${invitedBotOpenId}, skipping`);
287
+ return;
288
+ }
289
+ // Prefer event_id when the SDK exposes it: historical raw payload logs
290
+ // show WebSocket reconnect replays reuse the same event_id, while a real
291
+ // second invitation yields a new event_id even for the same meeting/bot.
292
+ // Fallback to (meeting_no, bot) only when event_id is absent so older
293
+ // payload shapes still remain deduplicated.
294
+ const dedupBotKey = ctx.lark.botOpenId ?? invitedBotOpenId ?? 'no-bot';
295
+ const dedupKey = eventId ? `vc-invited:by-event:${eventId}` : `vc-invited:by-meeting:${meetingNo}:${dedupBotKey}`;
296
+ if (!ctx.messageDedup.tryRecord(dedupKey, accountId)) {
297
+ log(`feishu[${accountId}]: duplicate vc invited event detected, skipping`);
298
+ return;
299
+ }
300
+ log(`feishu[${accountId}]: vc invited event accepted for synthetic dispatch`);
301
+ await (0, vc_meeting_invited_handler_1.handleFeishuVcMeetingInvited)({
302
+ cfg: ctx.cfg,
303
+ event,
304
+ runtime: ctx.runtime,
305
+ chatHistories: ctx.chatHistories,
306
+ accountId,
307
+ });
308
+ }
309
+ catch (err) {
310
+ error(`feishu[${accountId}]: error handling vc invited event: ${String(err)}`);
311
+ }
312
+ }
313
+ // ---------------------------------------------------------------------------
314
+ // Drive comment handler
315
+ // ---------------------------------------------------------------------------
316
+ async function handleCommentEvent(ctx, data) {
317
+ if (!isEventOwnershipValid(ctx, data))
318
+ return;
319
+ const { accountId, log, error } = ctx;
320
+ try {
321
+ const parsed = (0, comment_context_1.parseFeishuDriveCommentNoticeEventPayload)(data);
322
+ if (!parsed) {
323
+ log(`feishu[${accountId}]: invalid comment event payload, skipping`);
324
+ return;
325
+ }
326
+ const commentId = parsed.comment_id ?? '';
327
+ const replyId = parsed.reply_id ?? '';
328
+ // Parser has normalized notice_meta fields into canonical top-level fields
329
+ const _senderOpenId = parsed.user_id?.open_id ?? '';
330
+ const isMentioned = parsed.is_mention ?? false;
331
+ const eventTimestamp = parsed.action_time;
332
+ log(`feishu[${accountId}]: drive comment event: ` +
333
+ `type=${parsed.file_type}, comment=${commentId}` +
334
+ `${replyId ? `, reply=${replyId}` : ''}` +
335
+ `${isMentioned ? ', @bot' : ''}`);
336
+ // Dedup: build a deterministic key from the comment/reply IDs
337
+ const dedupKey = replyId ? `comment:${commentId}:reply:${replyId}` : `comment:${commentId}`;
338
+ if (!ctx.messageDedup.tryRecord(dedupKey, accountId)) {
339
+ log(`feishu[${accountId}]: duplicate comment event ${dedupKey}, skipping`);
340
+ return;
341
+ }
342
+ // Expiry check
343
+ if ((0, dedup_1.isMessageExpired)(eventTimestamp)) {
344
+ log(`feishu[${accountId}]: comment event expired, discarding`);
345
+ return;
346
+ }
347
+ // Dispatch the comment event (no queue serialization needed for comment threads)
348
+ await (0, comment_handler_1.handleFeishuCommentEvent)({
349
+ cfg: ctx.cfg,
350
+ event: parsed,
351
+ botOpenId: ctx.lark.botOpenId,
352
+ runtime: ctx.runtime,
353
+ chatHistories: ctx.chatHistories,
354
+ accountId,
355
+ });
356
+ }
357
+ catch (err) {
358
+ error(`feishu[${accountId}]: error handling comment event: ${String(err)}`);
359
+ }
360
+ }
361
+ // ---------------------------------------------------------------------------
362
+ // Card action handler
363
+ // ---------------------------------------------------------------------------
364
+ async function handleCardActionEvent(ctx, data) {
365
+ try {
366
+ // AskUserQuestion:表单卡片交互(宿主内建能力优先)
367
+ const askResult = (0, ask_user_question_1.handleAskUserAction)(data, ctx.cfg, ctx.accountId);
368
+ if (askResult !== undefined)
369
+ return askResult;
370
+ // auto-auth:授权/权限引导相关卡片交互(宿主内建能力优先)
371
+ const authResult = await (0, auto_auth_1.handleCardAction)(data, ctx.cfg, ctx.accountId);
372
+ if (authResult !== undefined)
373
+ return authResult;
374
+ // 业务自定义卡片交互:使用 SDK 标准 interactive dispatch 管道转发给业务插件。
375
+ return await (0, interactive_dispatch_1.dispatchFeishuPluginInteractiveHandler)({ cfg: ctx.cfg, accountId: ctx.accountId, data });
376
+ }
377
+ catch (err) {
378
+ elog.warn(`card.action.trigger handler error: ${err}`);
379
+ }
380
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Feishu interactive dispatch wrapper.
6
+ *
7
+ * This module adapts Feishu `card.action.trigger` events into OpenClaw's
8
+ * standard interactive dispatch pipeline:
9
+ * - Plugins register via `api.registerInteractiveHandler({ channel, namespace, handler })`
10
+ * - Channel forwards via `dispatchPluginInteractiveHandler()`
11
+ *
12
+ * We intentionally do NOT maintain any channel-local global registry here.
13
+ */
14
+ import type { ClawdbotConfig } from 'openclaw/plugin-sdk';
15
+ export type FeishuInteractiveHandlerResponse = unknown;
16
+ export interface FeishuInteractiveHandlerContext {
17
+ channel: 'feishu';
18
+ accountId: string;
19
+ senderId?: string;
20
+ conversationId?: string;
21
+ messageId?: string;
22
+ namespace: string;
23
+ payload: string;
24
+ action: string;
25
+ rawEvent: unknown;
26
+ respond: {
27
+ reply: (args: {
28
+ text: string;
29
+ }) => Promise<void>;
30
+ followUp: (args: {
31
+ text: string;
32
+ }) => Promise<void>;
33
+ /**
34
+ * Best-effort "edit current message" mapping.
35
+ * In Feishu, we prefer updating the original interactive card when possible.
36
+ */
37
+ editMessage: (args: {
38
+ text?: string;
39
+ blocks?: unknown[];
40
+ }) => Promise<void>;
41
+ };
42
+ }
43
+ /**
44
+ * Dispatch a Feishu interactive card action to business plugins through
45
+ * the OpenClaw SDK's standard interactive dispatch pipeline.
46
+ *
47
+ * Returns `undefined` when:
48
+ * - the event does not look like an interactive action we can route, or
49
+ * - no plugin handler is registered for the derived namespace.
50
+ *
51
+ * @param params.cfg - OpenClaw config snapshot.
52
+ * @param params.accountId - Current Feishu account id.
53
+ * @param params.data - Raw `card.action.trigger` event payload.
54
+ */
55
+ export declare function dispatchFeishuPluginInteractiveHandler(params: {
56
+ cfg: ClawdbotConfig;
57
+ accountId: string;
58
+ data: unknown;
59
+ }): Promise<unknown | undefined>;
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Feishu interactive dispatch wrapper.
7
+ *
8
+ * This module adapts Feishu `card.action.trigger` events into OpenClaw's
9
+ * standard interactive dispatch pipeline:
10
+ * - Plugins register via `api.registerInteractiveHandler({ channel, namespace, handler })`
11
+ * - Channel forwards via `dispatchPluginInteractiveHandler()`
12
+ *
13
+ * We intentionally do NOT maintain any channel-local global registry here.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.dispatchFeishuPluginInteractiveHandler = dispatchFeishuPluginInteractiveHandler;
17
+ // NOTE: This is the SDK-standard interactive pipeline.
18
+ const plugin_runtime_1 = require("openclaw/plugin-sdk/plugin-runtime");
19
+ const card_action_operator_1 = require("../core/card-action-operator.js");
20
+ const lark_logger_1 = require("../core/lark-logger.js");
21
+ const send_1 = require("../messaging/outbound/send.js");
22
+ const log = (0, lark_logger_1.larkLogger)('channel/interactive-dispatch');
23
+ function extractBasics(data) {
24
+ try {
25
+ const ev = data;
26
+ const action = ev.action?.value?.action ?? ev.action?.name ?? formSubmitActionName(ev);
27
+ if (!action || typeof action !== 'string')
28
+ return null;
29
+ const openChatId = ev.open_chat_id ?? ev.context?.open_chat_id;
30
+ const openMessageId = ev.open_message_id ?? ev.context?.open_message_id;
31
+ return {
32
+ action: action.trim(),
33
+ senderOpenId: (0, card_action_operator_1.resolveCardCallbackOperatorId)(ev.operator),
34
+ openChatId,
35
+ openMessageId,
36
+ };
37
+ }
38
+ catch {
39
+ return null;
40
+ }
41
+ }
42
+ function formSubmitActionName(ev) {
43
+ const tag = ev.action?.tag;
44
+ if (tag !== 'form_submit')
45
+ return undefined;
46
+ return ev.action?.form_name;
47
+ }
48
+ function buildMarkdownCard(text) {
49
+ return {
50
+ schema: '2.0',
51
+ body: {
52
+ elements: [
53
+ {
54
+ tag: 'markdown',
55
+ content: text,
56
+ },
57
+ ],
58
+ },
59
+ };
60
+ }
61
+ /**
62
+ * Dispatch a Feishu interactive card action to business plugins through
63
+ * the OpenClaw SDK's standard interactive dispatch pipeline.
64
+ *
65
+ * Returns `undefined` when:
66
+ * - the event does not look like an interactive action we can route, or
67
+ * - no plugin handler is registered for the derived namespace.
68
+ *
69
+ * @param params.cfg - OpenClaw config snapshot.
70
+ * @param params.accountId - Current Feishu account id.
71
+ * @param params.data - Raw `card.action.trigger` event payload.
72
+ */
73
+ async function dispatchFeishuPluginInteractiveHandler(params) {
74
+ const basics = extractBasics(params.data);
75
+ if (!basics)
76
+ return undefined;
77
+ if (!basics.action)
78
+ return undefined;
79
+ const respond = {
80
+ reply: async (args) => {
81
+ if (!basics.openChatId || !String(args?.text || '').trim())
82
+ return;
83
+ await (0, send_1.sendMessageFeishu)({
84
+ cfg: params.cfg,
85
+ to: basics.openChatId,
86
+ text: String(args?.text || ''),
87
+ replyToMessageId: basics.openMessageId,
88
+ accountId: params.accountId,
89
+ replyInThread: false,
90
+ });
91
+ },
92
+ followUp: async (args) => {
93
+ if (!basics.openChatId || !String(args?.text || '').trim())
94
+ return;
95
+ await (0, send_1.sendMessageFeishu)({
96
+ cfg: params.cfg,
97
+ to: basics.openChatId,
98
+ text: String(args?.text || ''),
99
+ replyToMessageId: basics.openMessageId,
100
+ accountId: params.accountId,
101
+ replyInThread: false,
102
+ });
103
+ },
104
+ editMessage: async (args) => {
105
+ if (!basics.openMessageId) {
106
+ if (Array.isArray(args?.blocks) && args.blocks.length && basics.openChatId) {
107
+ await (0, send_1.sendCardFeishu)({
108
+ cfg: params.cfg,
109
+ to: basics.openChatId,
110
+ card: { schema: '2.0', body: { elements: args.blocks } },
111
+ replyToMessageId: basics.openMessageId,
112
+ accountId: params.accountId,
113
+ replyInThread: false,
114
+ });
115
+ return;
116
+ }
117
+ if (typeof args?.text === 'string' && args.text.trim() && basics.openChatId) {
118
+ await (0, send_1.sendMessageFeishu)({
119
+ cfg: params.cfg,
120
+ to: basics.openChatId,
121
+ text: args.text,
122
+ replyToMessageId: basics.openMessageId,
123
+ accountId: params.accountId,
124
+ replyInThread: false,
125
+ });
126
+ }
127
+ return;
128
+ }
129
+ if (Array.isArray(args?.blocks) && args.blocks.length) {
130
+ await (0, send_1.updateCardFeishu)({
131
+ cfg: params.cfg,
132
+ messageId: basics.openMessageId,
133
+ card: { schema: '2.0', body: { elements: args.blocks } },
134
+ accountId: params.accountId,
135
+ });
136
+ return;
137
+ }
138
+ if (typeof args?.text === 'string' && args.text.trim()) {
139
+ await (0, send_1.updateCardFeishu)({
140
+ cfg: params.cfg,
141
+ messageId: basics.openMessageId,
142
+ card: buildMarkdownCard(args.text),
143
+ accountId: params.accountId,
144
+ });
145
+ return;
146
+ }
147
+ await (0, send_1.updateCardFeishu)({
148
+ cfg: params.cfg,
149
+ messageId: basics.openMessageId,
150
+ card: { schema: '2.0', body: { elements: [] } },
151
+ accountId: params.accountId,
152
+ });
153
+ },
154
+ };
155
+ try {
156
+ const dedupeId = `feishu:${params.accountId}:${basics.openChatId ?? '-'}:${basics.openMessageId ?? '-'}:${basics.senderOpenId ?? '-'}:${basics.action}`;
157
+ let cardResponse;
158
+ const result = await (0, plugin_runtime_1.dispatchPluginInteractiveHandler)({
159
+ channel: 'feishu',
160
+ data: basics.action,
161
+ dedupeId,
162
+ invoke: async (match) => {
163
+ const { registration, namespace, payload } = match;
164
+ const handlerCtx = {
165
+ channel: 'feishu',
166
+ accountId: params.accountId,
167
+ senderId: basics.senderOpenId,
168
+ conversationId: basics.openChatId,
169
+ messageId: basics.openMessageId,
170
+ namespace,
171
+ payload,
172
+ action: basics.action,
173
+ rawEvent: params.data,
174
+ respond,
175
+ };
176
+ cardResponse = await registration.handler(handlerCtx);
177
+ // If the handler returns a card response, treat it as handled.
178
+ return { handled: cardResponse !== undefined };
179
+ },
180
+ });
181
+ log.debug(`interactive dispatch result: action=${basics.action}, matched=${result.matched}, handled=${result.handled}`);
182
+ if (!result.matched)
183
+ return undefined;
184
+ return cardResponse;
185
+ }
186
+ catch (err) {
187
+ log.warn(`interactive dispatch failed: ${String(err)}`);
188
+ return {
189
+ toast: {
190
+ type: 'error',
191
+ content: '交互处理失败,请稍后重试',
192
+ },
193
+ };
194
+ }
195
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * WebSocket monitoring for the Lark/Feishu channel plugin.
6
+ *
7
+ * Manages per-account WSClient connections and routes inbound Feishu
8
+ * events (messages, bot membership changes, read receipts) to the
9
+ * appropriate handlers.
10
+ */
11
+ import type { MonitorFeishuOpts } from './types';
12
+ export type { MonitorFeishuOpts } from './types';
13
+ /**
14
+ * Start monitoring for all enabled Feishu accounts (or a single
15
+ * account when `opts.accountId` is specified).
16
+ */
17
+ export declare function monitorFeishuProvider(opts?: MonitorFeishuOpts): Promise<void>;