@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,306 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Account-scoped LRU cache for Feishu user display names.
7
+ *
8
+ * Provides:
9
+ * - `UserNameCache` — per-account LRU Map with TTL
10
+ * - `getUserNameCache(accountId)` — singleton registry
11
+ * - `batchResolveUserNames()` — batch API via `contact/v3/users/batch`
12
+ * - `resolveUserName()` — single-user fallback via `contact.user.get`
13
+ * - `clearUserNameCache()` — teardown hook (called from LarkClient.clearCache)
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.getUserNameCache = exports.clearUserNameCache = exports.UserNameCache = void 0;
17
+ exports.batchResolveUserNames = batchResolveUserNames;
18
+ exports.createBatchResolveNames = createBatchResolveNames;
19
+ exports.resolveBotName = resolveBotName;
20
+ exports.prefetchChatBots = prefetchChatBots;
21
+ exports.prefetchChatMembers = prefetchChatMembers;
22
+ exports.resolveUserName = resolveUserName;
23
+ const lark_client_1 = require("../../core/lark-client.js");
24
+ const user_name_cache_store_1 = require("./user-name-cache-store.js");
25
+ const permission_1 = require("./permission.js");
26
+ var user_name_cache_store_2 = require("./user-name-cache-store.js");
27
+ Object.defineProperty(exports, "UserNameCache", { enumerable: true, get: function () { return user_name_cache_store_2.UserNameCache; } });
28
+ Object.defineProperty(exports, "clearUserNameCache", { enumerable: true, get: function () { return user_name_cache_store_2.clearUserNameCache; } });
29
+ Object.defineProperty(exports, "getUserNameCache", { enumerable: true, get: function () { return user_name_cache_store_2.getUserNameCache; } });
30
+ // ---------------------------------------------------------------------------
31
+ // Batch resolve via contact/v3/users/batch
32
+ // ---------------------------------------------------------------------------
33
+ /** Max user_ids per API call (Feishu limit). */
34
+ const BATCH_SIZE = 50;
35
+ /**
36
+ * Batch-resolve user display names.
37
+ *
38
+ * 1. Check cache → collect misses
39
+ * 2. Deduplicate
40
+ * 3. Call `GET /open-apis/contact/v3/users/batch` in chunks of 50
41
+ * 4. Write results back to cache
42
+ * 5. Return full Map<openId, name> (cache hits + API results)
43
+ *
44
+ * Best-effort: API errors are logged but never thrown.
45
+ */
46
+ async function batchResolveUserNames(params) {
47
+ const { account, openIds, log } = params;
48
+ if (!account.configured || openIds.length === 0) {
49
+ return new Map();
50
+ }
51
+ const cache = (0, user_name_cache_store_1.getUserNameCache)(account.accountId);
52
+ const result = cache.getMany(openIds);
53
+ // Deduplicate missing IDs
54
+ const missing = [...new Set(cache.filterMissing(openIds))];
55
+ if (missing.length === 0)
56
+ return result;
57
+ const client = lark_client_1.LarkClient.fromAccount(account).sdk;
58
+ // Split into chunks of BATCH_SIZE and call SDK method
59
+ for (let i = 0; i < missing.length; i += BATCH_SIZE) {
60
+ const chunk = missing.slice(i, i + BATCH_SIZE);
61
+ try {
62
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
63
+ const res = await client.contact.user.batch({
64
+ params: {
65
+ user_ids: chunk,
66
+ user_id_type: 'open_id',
67
+ },
68
+ });
69
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
70
+ const items = res?.data?.items ?? [];
71
+ const resolved = new Set();
72
+ for (const item of items) {
73
+ const openId = item.open_id;
74
+ if (!openId)
75
+ continue;
76
+ const name = item.name || item.display_name || item.nickname || item.en_name || '';
77
+ cache.setWithKind(openId, name, 'user');
78
+ result.set(openId, name);
79
+ resolved.add(openId);
80
+ }
81
+ // Cache empty names for IDs the API didn't return (no permission, etc.)
82
+ for (const id of chunk) {
83
+ if (!resolved.has(id)) {
84
+ cache.setWithKind(id, '', 'user');
85
+ result.set(id, '');
86
+ }
87
+ }
88
+ }
89
+ catch (err) {
90
+ log(`batchResolveUserNames: failed: ${String(err)}`);
91
+ }
92
+ }
93
+ return result;
94
+ }
95
+ /**
96
+ * Create a `batchResolveNames` callback for use in `ConvertContext`.
97
+ *
98
+ * The returned function calls `batchResolveUserNames` with the given
99
+ * account and log function, populating the TAT user-name cache.
100
+ */
101
+ function createBatchResolveNames(account, log) {
102
+ return async (openIds) => {
103
+ await batchResolveUserNames({ account, openIds, log });
104
+ };
105
+ }
106
+ /**
107
+ * Resolve a single bot's display name via `/open-apis/bot/v3/bots/basic_batch`.
108
+ *
109
+ * Bots are not returned by the contact API, so they have their own endpoint.
110
+ * Names share the same account-scoped cache (keyed by openId) since both
111
+ * bots and users have `ou_` prefixed openIds and a single display name.
112
+ */
113
+ async function resolveBotName(params) {
114
+ const { account, openId, log } = params;
115
+ if (!account.configured || !openId)
116
+ return {};
117
+ const cache = (0, user_name_cache_store_1.getUserNameCache)(account.accountId);
118
+ if (cache.has(openId))
119
+ return { name: cache.get(openId) ?? '' };
120
+ try {
121
+ const client = lark_client_1.LarkClient.fromAccount(account).sdk;
122
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
123
+ const res = await client.request({
124
+ method: 'GET',
125
+ url: '/open-apis/bot/v3/bots/basic_batch',
126
+ params: { bot_ids: [openId] },
127
+ });
128
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
129
+ const bot = res?.data?.bots?.[openId];
130
+ const name = bot?.name || bot?.i18n_names?.zh_cn || bot?.i18n_names?.en_us || '';
131
+ // Cache even empty names to avoid repeated API calls for bots
132
+ // whose names we cannot resolve.
133
+ cache.setWithKind(openId, name, 'bot');
134
+ return { name: name || undefined };
135
+ }
136
+ catch (err) {
137
+ // Bot name resolution is best-effort: missing `bot:basic_info` scope
138
+ // should not surface as a permission notification to the agent. Log
139
+ // and cache an empty name so we don't retry, then fall back to openId.
140
+ const permErr = (0, permission_1.extractPermissionError)(err);
141
+ if (permErr) {
142
+ log(`feishu: permission error resolving bot name (best-effort, ignored): code=${permErr.code}`);
143
+ }
144
+ else {
145
+ log(`feishu: failed to resolve bot name for ${openId}: ${String(err)}`);
146
+ }
147
+ cache.setWithKind(openId, '', 'bot');
148
+ return {};
149
+ }
150
+ }
151
+ // ---------------------------------------------------------------------------
152
+ // Lazy chat-member prefetch
153
+ // ---------------------------------------------------------------------------
154
+ /** Returns the numeric Feishu API error code from a thrown error, or null. */
155
+ function extractApiCode(err) {
156
+ const permErr = (0, permission_1.extractPermissionError)(err);
157
+ if (typeof permErr?.code === 'number')
158
+ return permErr.code;
159
+ if (err && typeof err === 'object') {
160
+ const code = err.response?.data?.code;
161
+ if (typeof code === 'number')
162
+ return code;
163
+ }
164
+ return null;
165
+ }
166
+ /**
167
+ * Runs a chat-member prefetch with shared lifecycle:
168
+ *
169
+ * 1. Skip on unconfigured account or empty chatId.
170
+ * 2. Dedup concurrent calls per (tag, chatId) via `cache.inFlight`.
171
+ * 3. Skip when an in-TTL snapshot already exists.
172
+ * 4. On API error, cache an empty list to short-circuit retries; on
173
+ * transient errors, leave the cache untouched so the next call retries.
174
+ */
175
+ async function runChatPrefetch(spec, account, chatId, log) {
176
+ if (!account.configured || !chatId)
177
+ return;
178
+ const cache = (0, user_name_cache_store_1.getUserNameCache)(account.accountId);
179
+ const key = `${spec.tag}:${chatId}`;
180
+ const existing = cache.getInflight(key);
181
+ if (existing)
182
+ return existing;
183
+ if (spec.isFresh(cache, chatId))
184
+ return;
185
+ const promise = (async () => {
186
+ try {
187
+ const client = lark_client_1.LarkClient.fromAccount(account).sdk;
188
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
189
+ const res = await client.request({
190
+ method: 'GET',
191
+ url: spec.url(chatId),
192
+ params: spec.params,
193
+ });
194
+ const items = res?.data?.items ?? [];
195
+ const members = items.map(spec.parseItem).filter((m) => m !== null);
196
+ spec.record(cache, chatId, members);
197
+ }
198
+ catch (err) {
199
+ const apiCode = extractApiCode(err);
200
+ if (apiCode != null) {
201
+ // Application-level refusal: cache an empty list to short-circuit
202
+ // further retries. Persistent errors (e.g. missing scope) will not
203
+ // resolve within the cache TTL anyway.
204
+ log(`prefetchChat${spec.tag}[${chatId}]: API error code=${apiCode}, caching empty`);
205
+ spec.record(cache, chatId, []);
206
+ }
207
+ else {
208
+ log(`prefetchChat${spec.tag}[${chatId}]: failed: ${String(err)}`);
209
+ }
210
+ }
211
+ finally {
212
+ cache.clearInflight(key);
213
+ }
214
+ })();
215
+ cache.setInflight(key, promise);
216
+ return promise;
217
+ }
218
+ const CHAT_BOTS_SPEC = {
219
+ tag: 'Bots',
220
+ url: (chatId) => `/open-apis/im/v1/chats/${chatId}/members/bots`,
221
+ params: {},
222
+ parseItem: (raw) => {
223
+ const it = raw;
224
+ const openId = String(it.bot_id ?? it.open_id ?? '');
225
+ if (!openId)
226
+ return null;
227
+ return { openId, name: String(it.bot_name ?? it.name ?? '') };
228
+ },
229
+ isFresh: (cache, chatId) => cache.getChatBots(chatId) !== null,
230
+ record: (cache, chatId, members) => cache.recordChatBots(chatId, members),
231
+ };
232
+ function memberTypeToKind(type) {
233
+ return type === 'app' ? 'bot' : 'user';
234
+ }
235
+ const CHAT_MEMBERS_SPEC = {
236
+ tag: 'Members',
237
+ url: (chatId) => `/open-apis/im/v1/chats/${chatId}/members`,
238
+ params: { member_id_type: 'open_id', page_size: 100 },
239
+ parseItem: (raw) => {
240
+ const it = raw;
241
+ const openId = String(it.member_id ?? it.open_id ?? '');
242
+ if (!openId)
243
+ return null;
244
+ return { openId, name: String(it.name ?? ''), kind: memberTypeToKind(it.member_type) };
245
+ },
246
+ isFresh: (cache, chatId) => cache.getChatMembers(chatId) !== null,
247
+ record: (cache, chatId, members) => cache.recordChatMembers(chatId, members),
248
+ };
249
+ /**
250
+ * Fetches the bot members of a chat via
251
+ * `GET /open-apis/im/v1/chats/{chat_id}/members/bots` and writes them
252
+ * to the per-account cache.
253
+ */
254
+ async function prefetchChatBots(account, chatId, log) {
255
+ return runChatPrefetch(CHAT_BOTS_SPEC, account, chatId, log);
256
+ }
257
+ /**
258
+ * Fetches the human members of a chat via
259
+ * `GET /open-apis/im/v1/chats/{chat_id}/members` and writes them to
260
+ * the per-account cache.
261
+ */
262
+ async function prefetchChatMembers(account, chatId, log) {
263
+ return runChatPrefetch(CHAT_MEMBERS_SPEC, account, chatId, log);
264
+ }
265
+ /**
266
+ * Resolve a single user's display name.
267
+ *
268
+ * Checks the account-scoped cache first, then falls back to the
269
+ * `contact.user.get` API (same as the old `resolveFeishuSenderName`).
270
+ */
271
+ async function resolveUserName(params) {
272
+ const { account, openId, log } = params;
273
+ if (!account.configured || !openId)
274
+ return {};
275
+ const cache = (0, user_name_cache_store_1.getUserNameCache)(account.accountId);
276
+ if (cache.has(openId))
277
+ return { name: cache.get(openId) ?? '' };
278
+ try {
279
+ const client = lark_client_1.LarkClient.fromAccount(account).sdk;
280
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
281
+ const res = await client.contact.user.get({
282
+ path: { user_id: openId },
283
+ params: { user_id_type: 'open_id' },
284
+ });
285
+ const name = res?.data?.user?.name ||
286
+ res?.data?.user?.display_name ||
287
+ res?.data?.user?.nickname ||
288
+ res?.data?.user?.en_name ||
289
+ '';
290
+ // Cache even empty names to avoid repeated API calls for users
291
+ // whose names we cannot resolve (e.g. due to permissions).
292
+ cache.setWithKind(openId, name, 'user');
293
+ return { name: name || undefined };
294
+ }
295
+ catch (err) {
296
+ const permErr = (0, permission_1.extractPermissionError)(err);
297
+ if (permErr) {
298
+ log(`feishu: permission error resolving user name: code=${permErr.code}`);
299
+ // Cache empty name so we don't retry a known-failing openId
300
+ cache.setWithKind(openId, '', 'user');
301
+ return { permissionError: permErr };
302
+ }
303
+ log(`feishu: failed to resolve user name for ${openId}: ${String(err)}`);
304
+ return {};
305
+ }
306
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * VC meeting invited event handler for the Lark/Feishu channel plugin.
6
+ *
7
+ * Handles `vc.bot.meeting_invited_v1` by converting the event into a
8
+ * synthetic natural-language inbound and dispatching it through the
9
+ * standard OpenClaw agent pipeline.
10
+ */
11
+ import type { ClawdbotConfig, RuntimeEnv } from 'openclaw/plugin-sdk';
12
+ import type { HistoryEntry } from 'openclaw/plugin-sdk/reply-history';
13
+ import type { FeishuVcMeetingInvitedEvent } from '../types';
14
+ export declare function handleFeishuVcMeetingInvited(params: {
15
+ cfg: ClawdbotConfig;
16
+ event: FeishuVcMeetingInvitedEvent;
17
+ runtime?: RuntimeEnv;
18
+ chatHistories?: Map<string, HistoryEntry[]>;
19
+ accountId?: string;
20
+ }): Promise<void>;
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * VC meeting invited event handler for the Lark/Feishu channel plugin.
7
+ *
8
+ * Handles `vc.bot.meeting_invited_v1` by converting the event into a
9
+ * synthetic natural-language inbound and dispatching it through the
10
+ * standard OpenClaw agent pipeline.
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.handleFeishuVcMeetingInvited = handleFeishuVcMeetingInvited;
47
+ const crypto = __importStar(require("node:crypto"));
48
+ const synthetic_target_1 = require("../../core/synthetic-target.js");
49
+ const accounts_1 = require("../../core/accounts.js");
50
+ const lark_logger_1 = require("../../core/lark-logger.js");
51
+ const dispatch_1 = require("./dispatch.js");
52
+ const gate_effects_1 = require("./gate-effects.js");
53
+ const gate_1 = require("./gate.js");
54
+ const policy_1 = require("./policy.js");
55
+ const vc_sender_1 = require("./vc-sender.js");
56
+ const logger = (0, lark_logger_1.larkLogger)('inbound/vc-meeting-invited-handler');
57
+ function buildSyntheticEvent(event) {
58
+ const meetingNo = event.meeting?.meeting_no?.trim() ?? '';
59
+ // Both meeting_no and inviter identity are required for this event.
60
+ if (!meetingNo) {
61
+ return null;
62
+ }
63
+ const sender = (0, vc_sender_1.resolveVcSender)(event);
64
+ if (!sender.senderId) {
65
+ return null;
66
+ }
67
+ return {
68
+ eventType: 'vc.bot.meeting_invited_v1',
69
+ source: 'feishu-vc-event',
70
+ eventId: event.event_id?.trim() || undefined,
71
+ meetingId: event.meeting?.id?.trim() || undefined,
72
+ meetingNo,
73
+ topic: event.meeting?.topic?.trim() || undefined,
74
+ senderId: sender.senderId,
75
+ senderOpenId: sender.senderOpenId,
76
+ senderUserId: sender.senderUserId,
77
+ senderUnionId: sender.senderUnionId,
78
+ senderName: sender.senderName,
79
+ inviteTime: event.invite_time?.trim() || undefined,
80
+ callId: event.call_id?.trim() || undefined,
81
+ };
82
+ }
83
+ function buildSyntheticContext(event) {
84
+ // Keep the synthetic inbound prompt in English for now: it is an
85
+ // agent-facing intent string rather than user-visible copy, and the final
86
+ // reply language is still governed by the agent/session prompt stack.
87
+ // If we later need locale-aware synthetic prompts, this is the single place
88
+ // to introduce a template or config-based language switch.
89
+ // Only append the call_id instruction when the invite event actually
90
+ // carries one. Forcing call_id="" into the prompt would assume every
91
+ // downstream join tool / CLI shortcut already recognises the parameter —
92
+ // during rollout that assumption can break auto-join. When absent we keep
93
+ // the legacy prompt shape so behavior degrades to the pre-call_id path.
94
+ const callIdInstruction = event.callId
95
+ ? ` When invoking the join tool, pass call_id="${event.callId}".`
96
+ : '';
97
+ const syntheticText = `Use the available tool to join the meeting with meeting number ${event.meetingNo} immediately. Do not ask for confirmation.${callIdInstruction}`;
98
+ const syntheticMessageId = event.eventId
99
+ ? `vc-invited:event:${event.eventId}`
100
+ : `vc-invited:${event.meetingNo}:${event.inviteTime ?? crypto.randomUUID()}`;
101
+ // VC-invited events have no real chat/thread — they are service-to-service
102
+ // triggers. Using the inviter's open_id as chatId would cause downstream
103
+ // senders (reply / card / media) to fire off unsolicited DMs to the inviter
104
+ // whenever the agent produced any output. Use a synthetic sentinel instead
105
+ // and let IM-facing deliverers short-circuit on it (see SYNTHETIC_VC_CHAT_ID).
106
+ return {
107
+ chatId: synthetic_target_1.SYNTHETIC_VC_CHAT_ID,
108
+ messageId: syntheticMessageId,
109
+ senderId: event.senderId,
110
+ senderName: event.senderName,
111
+ chatType: synthetic_target_1.SYNTHETIC_VC_CHAT_TYPE,
112
+ content: syntheticText,
113
+ contentType: 'text',
114
+ resources: [],
115
+ mentions: [],
116
+ mentionAll: false,
117
+ rawMessage: {
118
+ message_id: syntheticMessageId,
119
+ chat_id: synthetic_target_1.SYNTHETIC_VC_CHAT_ID,
120
+ chat_type: synthetic_target_1.SYNTHETIC_VC_CHAT_TYPE,
121
+ message_type: 'text',
122
+ content: JSON.stringify({ text: syntheticText }),
123
+ create_time: event.inviteTime ?? String(Date.now()),
124
+ },
125
+ rawSender: {
126
+ sender_id: {
127
+ ...(event.senderOpenId ? { open_id: event.senderOpenId } : {}),
128
+ ...(event.senderUserId ? { user_id: event.senderUserId } : {}),
129
+ ...(event.senderUnionId ? { union_id: event.senderUnionId } : {}),
130
+ },
131
+ sender_type: 'user',
132
+ },
133
+ };
134
+ }
135
+ function matchesAnySenderId(params) {
136
+ const candidates = [...new Set(params.senderIds.map((id) => id?.trim()).filter(Boolean))];
137
+ return candidates.some((candidate) => (0, policy_1.resolveFeishuAllowlistMatch)({
138
+ allowFrom: params.allowFrom,
139
+ senderId: candidate,
140
+ }).allowed);
141
+ }
142
+ async function handleFeishuVcMeetingInvited(params) {
143
+ const { cfg, event, runtime, chatHistories, accountId } = params;
144
+ const log = runtime?.log ?? ((...args) => logger.info(args.map(String).join(' ')));
145
+ const error = runtime?.error ?? ((...args) => logger.error(args.map(String).join(' ')));
146
+ const syntheticEvent = buildSyntheticEvent(event);
147
+ if (!syntheticEvent) {
148
+ log(`feishu[${accountId}]: vc invited event missing meeting_no or inviter identity, skipping`);
149
+ return;
150
+ }
151
+ const account = (0, accounts_1.getLarkAccount)(cfg, accountId);
152
+ const accountScopedCfg = {
153
+ ...cfg,
154
+ channels: { ...cfg.channels, feishu: account.config },
155
+ };
156
+ const accountFeishuCfg = account.config;
157
+ // ---- Access policy enforcement (DM-style) ----
158
+ // VC invited events are user-triggered service events. Align their access
159
+ // semantics with direct-message/comment flows so unpaired users cannot
160
+ // trigger agent behavior through event ingress.
161
+ const dmPolicy = accountFeishuCfg?.dmPolicy ?? 'pairing';
162
+ if (dmPolicy === 'disabled') {
163
+ log(`feishu[${accountId}]: vc invited event rejected (dmPolicy=disabled)`);
164
+ return;
165
+ }
166
+ if (dmPolicy !== 'open') {
167
+ const configAllowFrom = accountFeishuCfg?.allowFrom ?? [];
168
+ const storeAllowFrom = await (0, gate_1.readFeishuAllowFromStore)(account.accountId).catch(() => []);
169
+ const combinedAllowFrom = [...configAllowFrom, ...storeAllowFrom];
170
+ const allowed = matchesAnySenderId({
171
+ allowFrom: combinedAllowFrom,
172
+ senderIds: [
173
+ syntheticEvent.senderOpenId,
174
+ syntheticEvent.senderUserId,
175
+ syntheticEvent.senderUnionId,
176
+ ],
177
+ });
178
+ if (!allowed) {
179
+ if (dmPolicy === 'pairing') {
180
+ if (syntheticEvent.senderOpenId) {
181
+ log(`feishu[${accountId}]: vc inviter not paired, creating pairing request`);
182
+ try {
183
+ await (0, gate_effects_1.sendPairingReply)({
184
+ senderId: syntheticEvent.senderOpenId,
185
+ chatId: syntheticEvent.senderOpenId,
186
+ accountId: account.accountId,
187
+ accountScopedCfg,
188
+ });
189
+ }
190
+ catch (pairingErr) {
191
+ log(`feishu[${accountId}]: failed to create pairing request for vc inviter: ${String(pairingErr)}`);
192
+ }
193
+ }
194
+ else {
195
+ log(`feishu[${accountId}]: vc inviter not paired and has no open_id for pairing reply, rejecting`);
196
+ }
197
+ }
198
+ else {
199
+ log(`feishu[${accountId}]: vc invited event rejected (dmPolicy=${dmPolicy}, inviter not in allowlist)`);
200
+ }
201
+ return;
202
+ }
203
+ }
204
+ const ctx = buildSyntheticContext(syntheticEvent);
205
+ log(`feishu[${accountId}]: vc meeting invited, dispatching synthetic inbound` +
206
+ ` sender=${syntheticEvent.senderId} meeting_no=${syntheticEvent.meetingNo}`);
207
+ try {
208
+ await (0, dispatch_1.dispatchToAgent)({
209
+ ctx,
210
+ permissionError: undefined,
211
+ mediaPayload: {},
212
+ extraInboundFields: {
213
+ SyntheticEventType: syntheticEvent.eventType,
214
+ VcMeetingId: syntheticEvent.meetingId,
215
+ VcMeetingNo: syntheticEvent.meetingNo,
216
+ VcMeetingTopic: syntheticEvent.topic,
217
+ VcInviterOpenId: syntheticEvent.senderOpenId,
218
+ VcInviteTime: syntheticEvent.inviteTime,
219
+ VcCallId: syntheticEvent.callId,
220
+ },
221
+ quotedContent: undefined,
222
+ account,
223
+ accountScopedCfg,
224
+ runtime,
225
+ chatHistories,
226
+ historyLimit: 0,
227
+ // VC events do not originate from a real IM message.
228
+ replyToMessageId: undefined,
229
+ commandAuthorized: false,
230
+ skipTyping: true,
231
+ });
232
+ }
233
+ catch (err) {
234
+ error(`feishu[${accountId}]: error dispatching vc invited synthetic inbound: ${String(err)}`);
235
+ }
236
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Shared sender-identity resolution for the VC meeting-invited event.
6
+ *
7
+ * Both the raw event handler (for diagnostics / dedup / ownership check)
8
+ * and the synthetic inbound builder (for dispatchToAgent) need a single,
9
+ * deterministic fallback chain. Keeping a dedicated module avoids drift
10
+ * between the two code paths when the event schema changes again.
11
+ */
12
+ import type { FeishuVcMeetingInvitedEvent } from '../types';
13
+ /** Which bucket the final senderId was picked from. */
14
+ export type VcSenderFallback = 'inviter' | 'none';
15
+ export interface ResolvedVcSender {
16
+ /**
17
+ * Final sender id used for logging / extraInboundFields. Sender is defined
18
+ * as the real inviter only; if inviter identity is missing, the event
19
+ * should be skipped instead of degrading to bot/config ids.
20
+ */
21
+ senderId: string;
22
+ /** Raw inviter-level open_id (if present); useful for agent "at inviter" use-cases. */
23
+ senderOpenId?: string;
24
+ /** Raw inviter-level user_id (if present). */
25
+ senderUserId?: string;
26
+ /** Raw inviter-level union_id (if present). */
27
+ senderUnionId?: string;
28
+ /** Human-readable name from inviter.user_name. */
29
+ senderName?: string;
30
+ /** Which bucket the senderId fell back to. */
31
+ fromFallback: VcSenderFallback;
32
+ }
33
+ /**
34
+ * Resolve the effective sender identity for a `vc.bot.meeting_invited_v1`
35
+ * event. See {@link ResolvedVcSender} for the field contract.
36
+ *
37
+ * Sender resolution order (first non-empty wins):
38
+ * 1. inviter.id.open_id → user_id → union_id
39
+ * 2. empty string + fromFallback='none'
40
+ */
41
+ export declare function resolveVcSender(event: FeishuVcMeetingInvitedEvent): ResolvedVcSender;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Shared sender-identity resolution for the VC meeting-invited event.
7
+ *
8
+ * Both the raw event handler (for diagnostics / dedup / ownership check)
9
+ * and the synthetic inbound builder (for dispatchToAgent) need a single,
10
+ * deterministic fallback chain. Keeping a dedicated module avoids drift
11
+ * between the two code paths when the event schema changes again.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.resolveVcSender = resolveVcSender;
15
+ /**
16
+ * Trim a possibly-null identifier and treat the empty string as missing.
17
+ *
18
+ * The event schema marks open_id / user_id / union_id as nullable and we
19
+ * have observed tenants returning empty strings in practice, so `||`/`??`
20
+ * alone are not enough.
21
+ */
22
+ function pickId(value) {
23
+ const trimmed = value?.trim();
24
+ return trimmed && trimmed.length > 0 ? trimmed : undefined;
25
+ }
26
+ /**
27
+ * Resolve the effective sender identity for a `vc.bot.meeting_invited_v1`
28
+ * event. See {@link ResolvedVcSender} for the field contract.
29
+ *
30
+ * Sender resolution order (first non-empty wins):
31
+ * 1. inviter.id.open_id → user_id → union_id
32
+ * 2. empty string + fromFallback='none'
33
+ */
34
+ function resolveVcSender(event) {
35
+ const inviterId = event.inviter?.id;
36
+ const inviterOpenId = pickId(inviterId?.open_id);
37
+ const inviterUserId = pickId(inviterId?.user_id);
38
+ const inviterUnionId = pickId(inviterId?.union_id);
39
+ let senderId = '';
40
+ let fromFallback = 'none';
41
+ if (inviterOpenId ?? inviterUserId ?? inviterUnionId) {
42
+ senderId = inviterOpenId ?? inviterUserId ?? inviterUnionId ?? '';
43
+ fromFallback = 'inviter';
44
+ }
45
+ return {
46
+ senderId,
47
+ senderOpenId: inviterOpenId,
48
+ senderUserId: inviterUserId,
49
+ senderUnionId: inviterUnionId,
50
+ senderName: pickId(event.inviter?.user_name) ?? undefined,
51
+ fromFallback,
52
+ };
53
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * ChannelMessageActionAdapter for the Lark/Feishu channel plugin.
6
+ *
7
+ * Implements the standard message-action interface so the framework's
8
+ * built-in `message` tool can route send, react, delete and other
9
+ * actions to Feishu.
10
+ *
11
+ * The `send` action is the unified entry-point for text, card, media,
12
+ * reply and attachment delivery — matching the Telegram/Discord pattern
13
+ * where a single action handles all outbound message types.
14
+ */
15
+ import type { ChannelMessageActionAdapter } from 'openclaw/plugin-sdk';
16
+ export declare const feishuMessageActions: ChannelMessageActionAdapter;