@lark-project/openclaw-lark-project 2026.3.131

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 (368) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +80 -0
  3. package/README.zh.md +80 -0
  4. package/dist/index.js +172 -0
  5. package/dist/index.js.map +7 -0
  6. package/dist/skills/feishu-bitable/SKILL.md +248 -0
  7. package/dist/skills/feishu-bitable/references/examples.md +813 -0
  8. package/dist/skills/feishu-bitable/references/field-properties.md +763 -0
  9. package/dist/skills/feishu-bitable/references/record-values.md +911 -0
  10. package/dist/skills/feishu-calendar/SKILL.md +244 -0
  11. package/dist/skills/feishu-channel-rules/SKILL.md +18 -0
  12. package/dist/skills/feishu-channel-rules/references/markdown-syntax.md +138 -0
  13. package/dist/skills/feishu-create-doc/SKILL.md +719 -0
  14. package/dist/skills/feishu-fetch-doc/SKILL.md +93 -0
  15. package/dist/skills/feishu-im-read/SKILL.md +163 -0
  16. package/dist/skills/feishu-project/SKILL.md +122 -0
  17. package/dist/skills/feishu-task/SKILL.md +293 -0
  18. package/dist/skills/feishu-troubleshoot/SKILL.md +70 -0
  19. package/dist/skills/feishu-update-doc/SKILL.md +285 -0
  20. package/dist/src/card/builder.js +293 -0
  21. package/dist/src/card/builder.js.map +7 -0
  22. package/dist/src/card/cardkit.js +126 -0
  23. package/dist/src/card/cardkit.js.map +7 -0
  24. package/dist/src/card/flush-controller.js +107 -0
  25. package/dist/src/card/flush-controller.js.map +7 -0
  26. package/dist/src/card/markdown-style.js +57 -0
  27. package/dist/src/card/markdown-style.js.map +7 -0
  28. package/dist/src/card/reply-dispatcher-types.js +39 -0
  29. package/dist/src/card/reply-dispatcher-types.js.map +7 -0
  30. package/dist/src/card/reply-dispatcher.js +245 -0
  31. package/dist/src/card/reply-dispatcher.js.map +7 -0
  32. package/dist/src/card/reply-mode.js +29 -0
  33. package/dist/src/card/reply-mode.js.map +7 -0
  34. package/dist/src/card/streaming-card-controller.js +653 -0
  35. package/dist/src/card/streaming-card-controller.js.map +7 -0
  36. package/dist/src/card/unavailable-guard.js +76 -0
  37. package/dist/src/card/unavailable-guard.js.map +7 -0
  38. package/dist/src/channel/abort-detect.js +79 -0
  39. package/dist/src/channel/abort-detect.js.map +7 -0
  40. package/dist/src/channel/chat-queue.js +50 -0
  41. package/dist/src/channel/chat-queue.js.map +7 -0
  42. package/dist/src/channel/config-adapter.js +89 -0
  43. package/dist/src/channel/config-adapter.js.map +7 -0
  44. package/dist/src/channel/directory.js +133 -0
  45. package/dist/src/channel/directory.js.map +7 -0
  46. package/dist/src/channel/event-handlers.js +175 -0
  47. package/dist/src/channel/event-handlers.js.map +7 -0
  48. package/dist/src/channel/monitor.js +108 -0
  49. package/dist/src/channel/monitor.js.map +7 -0
  50. package/dist/src/channel/onboarding-config.js +76 -0
  51. package/dist/src/channel/onboarding-config.js.map +7 -0
  52. package/dist/src/channel/onboarding-migrate.js +55 -0
  53. package/dist/src/channel/onboarding-migrate.js.map +7 -0
  54. package/dist/src/channel/onboarding.js +285 -0
  55. package/dist/src/channel/onboarding.js.map +7 -0
  56. package/dist/src/channel/plugin.js +260 -0
  57. package/dist/src/channel/plugin.js.map +7 -0
  58. package/dist/src/channel/probe.js +14 -0
  59. package/dist/src/channel/probe.js.map +7 -0
  60. package/dist/src/channel/types.js +1 -0
  61. package/dist/src/channel/types.js.map +7 -0
  62. package/dist/src/commands/auth.js +73 -0
  63. package/dist/src/commands/auth.js.map +7 -0
  64. package/dist/src/commands/diagnose.js +658 -0
  65. package/dist/src/commands/diagnose.js.map +7 -0
  66. package/dist/src/commands/doctor.js +327 -0
  67. package/dist/src/commands/doctor.js.map +7 -0
  68. package/dist/src/commands/index.js +124 -0
  69. package/dist/src/commands/index.js.map +7 -0
  70. package/dist/src/core/accounts.js +129 -0
  71. package/dist/src/core/accounts.js.map +7 -0
  72. package/dist/src/core/agent-config.js +60 -0
  73. package/dist/src/core/agent-config.js.map +7 -0
  74. package/dist/src/core/api-error.js +55 -0
  75. package/dist/src/core/api-error.js.map +7 -0
  76. package/dist/src/core/app-owner-fallback.js +17 -0
  77. package/dist/src/core/app-owner-fallback.js.map +7 -0
  78. package/dist/src/core/app-scope-checker.js +95 -0
  79. package/dist/src/core/app-scope-checker.js.map +7 -0
  80. package/dist/src/core/auth-errors.js +120 -0
  81. package/dist/src/core/auth-errors.js.map +7 -0
  82. package/dist/src/core/chat-info-cache.js +102 -0
  83. package/dist/src/core/chat-info-cache.js.map +7 -0
  84. package/dist/src/core/config-schema.js +150 -0
  85. package/dist/src/core/config-schema.js.map +7 -0
  86. package/dist/src/core/device-flow.js +174 -0
  87. package/dist/src/core/device-flow.js.map +7 -0
  88. package/dist/src/core/feishu-fetch.js +12 -0
  89. package/dist/src/core/feishu-fetch.js.map +7 -0
  90. package/dist/src/core/footer-config.js +16 -0
  91. package/dist/src/core/footer-config.js.map +7 -0
  92. package/dist/src/core/lark-client.js +322 -0
  93. package/dist/src/core/lark-client.js.map +7 -0
  94. package/dist/src/core/lark-logger.js +92 -0
  95. package/dist/src/core/lark-logger.js.map +7 -0
  96. package/dist/src/core/lark-ticket.js +18 -0
  97. package/dist/src/core/lark-ticket.js.map +7 -0
  98. package/dist/src/core/message-unavailable.js +119 -0
  99. package/dist/src/core/message-unavailable.js.map +7 -0
  100. package/dist/src/core/owner-policy.js +25 -0
  101. package/dist/src/core/owner-policy.js.map +7 -0
  102. package/dist/src/core/permission-url.js +37 -0
  103. package/dist/src/core/permission-url.js.map +7 -0
  104. package/dist/src/core/project-auth.js +177 -0
  105. package/dist/src/core/project-auth.js.map +7 -0
  106. package/dist/src/core/project-oauth-flow.js +124 -0
  107. package/dist/src/core/project-oauth-flow.js.map +7 -0
  108. package/dist/src/core/project-token-store.js +172 -0
  109. package/dist/src/core/project-token-store.js.map +7 -0
  110. package/dist/src/core/raw-request.js +45 -0
  111. package/dist/src/core/raw-request.js.map +7 -0
  112. package/dist/src/core/scope-manager.js +62 -0
  113. package/dist/src/core/scope-manager.js.map +7 -0
  114. package/dist/src/core/security-check.js +118 -0
  115. package/dist/src/core/security-check.js.map +7 -0
  116. package/dist/src/core/shutdown-hooks.js +37 -0
  117. package/dist/src/core/shutdown-hooks.js.map +7 -0
  118. package/dist/src/core/targets.js +55 -0
  119. package/dist/src/core/targets.js.map +7 -0
  120. package/dist/src/core/token-store.js +215 -0
  121. package/dist/src/core/token-store.js.map +7 -0
  122. package/dist/src/core/tool-client.js +335 -0
  123. package/dist/src/core/tool-client.js.map +7 -0
  124. package/dist/src/core/tool-scopes.js +207 -0
  125. package/dist/src/core/tool-scopes.js.map +7 -0
  126. package/dist/src/core/tools-config.js +57 -0
  127. package/dist/src/core/tools-config.js.map +7 -0
  128. package/dist/src/core/types.js +1 -0
  129. package/dist/src/core/types.js.map +7 -0
  130. package/dist/src/core/uat-client.js +124 -0
  131. package/dist/src/core/uat-client.js.map +7 -0
  132. package/dist/src/core/version.js +27 -0
  133. package/dist/src/core/version.js.map +7 -0
  134. package/dist/src/messaging/converters/audio.js +19 -0
  135. package/dist/src/messaging/converters/audio.js.map +7 -0
  136. package/dist/src/messaging/converters/calendar.js +46 -0
  137. package/dist/src/messaging/converters/calendar.js.map +7 -0
  138. package/dist/src/messaging/converters/content-converter.js +61 -0
  139. package/dist/src/messaging/converters/content-converter.js.map +7 -0
  140. package/dist/src/messaging/converters/file.js +18 -0
  141. package/dist/src/messaging/converters/file.js.map +7 -0
  142. package/dist/src/messaging/converters/folder.js +18 -0
  143. package/dist/src/messaging/converters/folder.js.map +7 -0
  144. package/dist/src/messaging/converters/hongbao.js +14 -0
  145. package/dist/src/messaging/converters/hongbao.js.map +7 -0
  146. package/dist/src/messaging/converters/image.js +16 -0
  147. package/dist/src/messaging/converters/image.js.map +7 -0
  148. package/dist/src/messaging/converters/index.js +48 -0
  149. package/dist/src/messaging/converters/index.js.map +7 -0
  150. package/dist/src/messaging/converters/interactive/card-converter.js +1040 -0
  151. package/dist/src/messaging/converters/interactive/card-converter.js.map +7 -0
  152. package/dist/src/messaging/converters/interactive/card-utils.js +36 -0
  153. package/dist/src/messaging/converters/interactive/card-utils.js.map +7 -0
  154. package/dist/src/messaging/converters/interactive/index.js +19 -0
  155. package/dist/src/messaging/converters/interactive/index.js.map +7 -0
  156. package/dist/src/messaging/converters/interactive/legacy.js +53 -0
  157. package/dist/src/messaging/converters/interactive/legacy.js.map +7 -0
  158. package/dist/src/messaging/converters/interactive/types.js +23 -0
  159. package/dist/src/messaging/converters/interactive/types.js.map +7 -0
  160. package/dist/src/messaging/converters/location.js +17 -0
  161. package/dist/src/messaging/converters/location.js.map +7 -0
  162. package/dist/src/messaging/converters/merge-forward.js +143 -0
  163. package/dist/src/messaging/converters/merge-forward.js.map +7 -0
  164. package/dist/src/messaging/converters/post.js +113 -0
  165. package/dist/src/messaging/converters/post.js.map +7 -0
  166. package/dist/src/messaging/converters/share.js +22 -0
  167. package/dist/src/messaging/converters/share.js.map +7 -0
  168. package/dist/src/messaging/converters/sticker.js +16 -0
  169. package/dist/src/messaging/converters/sticker.js.map +7 -0
  170. package/dist/src/messaging/converters/system.js +25 -0
  171. package/dist/src/messaging/converters/system.js.map +7 -0
  172. package/dist/src/messaging/converters/text.js +12 -0
  173. package/dist/src/messaging/converters/text.js.map +7 -0
  174. package/dist/src/messaging/converters/todo.js +37 -0
  175. package/dist/src/messaging/converters/todo.js.map +7 -0
  176. package/dist/src/messaging/converters/types.js +1 -0
  177. package/dist/src/messaging/converters/types.js.map +7 -0
  178. package/dist/src/messaging/converters/unknown.js +13 -0
  179. package/dist/src/messaging/converters/unknown.js.map +7 -0
  180. package/dist/src/messaging/converters/utils.js +35 -0
  181. package/dist/src/messaging/converters/utils.js.map +7 -0
  182. package/dist/src/messaging/converters/video-chat.js +21 -0
  183. package/dist/src/messaging/converters/video-chat.js.map +7 -0
  184. package/dist/src/messaging/converters/video.js +30 -0
  185. package/dist/src/messaging/converters/video.js.map +7 -0
  186. package/dist/src/messaging/converters/vote.js +24 -0
  187. package/dist/src/messaging/converters/vote.js.map +7 -0
  188. package/dist/src/messaging/inbound/dedup.js +82 -0
  189. package/dist/src/messaging/inbound/dedup.js.map +7 -0
  190. package/dist/src/messaging/inbound/dispatch-builders.js +98 -0
  191. package/dist/src/messaging/inbound/dispatch-builders.js.map +7 -0
  192. package/dist/src/messaging/inbound/dispatch-commands.js +94 -0
  193. package/dist/src/messaging/inbound/dispatch-commands.js.map +7 -0
  194. package/dist/src/messaging/inbound/dispatch-context.js +96 -0
  195. package/dist/src/messaging/inbound/dispatch-context.js.map +7 -0
  196. package/dist/src/messaging/inbound/dispatch.js +150 -0
  197. package/dist/src/messaging/inbound/dispatch.js.map +7 -0
  198. package/dist/src/messaging/inbound/enrich.js +137 -0
  199. package/dist/src/messaging/inbound/enrich.js.map +7 -0
  200. package/dist/src/messaging/inbound/gate-effects.js +28 -0
  201. package/dist/src/messaging/inbound/gate-effects.js.map +7 -0
  202. package/dist/src/messaging/inbound/gate.js +163 -0
  203. package/dist/src/messaging/inbound/gate.js.map +7 -0
  204. package/dist/src/messaging/inbound/handler.js +132 -0
  205. package/dist/src/messaging/inbound/handler.js.map +7 -0
  206. package/dist/src/messaging/inbound/media-resolver.js +70 -0
  207. package/dist/src/messaging/inbound/media-resolver.js.map +7 -0
  208. package/dist/src/messaging/inbound/mention.js +50 -0
  209. package/dist/src/messaging/inbound/mention.js.map +7 -0
  210. package/dist/src/messaging/inbound/parse-io.js +41 -0
  211. package/dist/src/messaging/inbound/parse-io.js.map +7 -0
  212. package/dist/src/messaging/inbound/parse.js +79 -0
  213. package/dist/src/messaging/inbound/parse.js.map +7 -0
  214. package/dist/src/messaging/inbound/permission.js +30 -0
  215. package/dist/src/messaging/inbound/permission.js.map +7 -0
  216. package/dist/src/messaging/inbound/policy.js +83 -0
  217. package/dist/src/messaging/inbound/policy.js.map +7 -0
  218. package/dist/src/messaging/inbound/reaction-handler.js +162 -0
  219. package/dist/src/messaging/inbound/reaction-handler.js.map +7 -0
  220. package/dist/src/messaging/inbound/user-name-cache.js +172 -0
  221. package/dist/src/messaging/inbound/user-name-cache.js.map +7 -0
  222. package/dist/src/messaging/outbound/actions.js +239 -0
  223. package/dist/src/messaging/outbound/actions.js.map +7 -0
  224. package/dist/src/messaging/outbound/chat-manage.js +74 -0
  225. package/dist/src/messaging/outbound/chat-manage.js.map +7 -0
  226. package/dist/src/messaging/outbound/deliver.js +162 -0
  227. package/dist/src/messaging/outbound/deliver.js.map +7 -0
  228. package/dist/src/messaging/outbound/fetch.js +7 -0
  229. package/dist/src/messaging/outbound/fetch.js.map +7 -0
  230. package/dist/src/messaging/outbound/forward.js +31 -0
  231. package/dist/src/messaging/outbound/forward.js.map +7 -0
  232. package/dist/src/messaging/outbound/media-url-utils.js +101 -0
  233. package/dist/src/messaging/outbound/media-url-utils.js.map +7 -0
  234. package/dist/src/messaging/outbound/media.js +463 -0
  235. package/dist/src/messaging/outbound/media.js.map +7 -0
  236. package/dist/src/messaging/outbound/outbound.js +95 -0
  237. package/dist/src/messaging/outbound/outbound.js.map +7 -0
  238. package/dist/src/messaging/outbound/reactions.js +312 -0
  239. package/dist/src/messaging/outbound/reactions.js.map +7 -0
  240. package/dist/src/messaging/outbound/send.js +194 -0
  241. package/dist/src/messaging/outbound/send.js.map +7 -0
  242. package/dist/src/messaging/outbound/typing.js +77 -0
  243. package/dist/src/messaging/outbound/typing.js.map +7 -0
  244. package/dist/src/messaging/shared/message-lookup.js +84 -0
  245. package/dist/src/messaging/shared/message-lookup.js.map +7 -0
  246. package/dist/src/messaging/types.js +1 -0
  247. package/dist/src/messaging/types.js.map +7 -0
  248. package/dist/src/tools/auto-auth.js +714 -0
  249. package/dist/src/tools/auto-auth.js.map +7 -0
  250. package/dist/src/tools/helpers.js +133 -0
  251. package/dist/src/tools/helpers.js.map +7 -0
  252. package/dist/src/tools/mcp/doc/create.js +35 -0
  253. package/dist/src/tools/mcp/doc/create.js.map +7 -0
  254. package/dist/src/tools/mcp/doc/fetch.js +33 -0
  255. package/dist/src/tools/mcp/doc/fetch.js.map +7 -0
  256. package/dist/src/tools/mcp/doc/index.js +32 -0
  257. package/dist/src/tools/mcp/doc/index.js.map +7 -0
  258. package/dist/src/tools/mcp/doc/update.js +61 -0
  259. package/dist/src/tools/mcp/doc/update.js.map +7 -0
  260. package/dist/src/tools/mcp/project/endpoint.js +25 -0
  261. package/dist/src/tools/mcp/project/endpoint.js.map +7 -0
  262. package/dist/src/tools/mcp/project/index.js +27 -0
  263. package/dist/src/tools/mcp/project/index.js.map +7 -0
  264. package/dist/src/tools/mcp/project/tools.js +579 -0
  265. package/dist/src/tools/mcp/project/tools.js.map +7 -0
  266. package/dist/src/tools/mcp/shared.js +170 -0
  267. package/dist/src/tools/mcp/shared.js.map +7 -0
  268. package/dist/src/tools/oapi/bitable/app-table-field.js +244 -0
  269. package/dist/src/tools/oapi/bitable/app-table-field.js.map +7 -0
  270. package/dist/src/tools/oapi/bitable/app-table-record.js +501 -0
  271. package/dist/src/tools/oapi/bitable/app-table-record.js.map +7 -0
  272. package/dist/src/tools/oapi/bitable/app-table-view.js +226 -0
  273. package/dist/src/tools/oapi/bitable/app-table-view.js.map +7 -0
  274. package/dist/src/tools/oapi/bitable/app-table.js +278 -0
  275. package/dist/src/tools/oapi/bitable/app-table.js.map +7 -0
  276. package/dist/src/tools/oapi/bitable/app.js +200 -0
  277. package/dist/src/tools/oapi/bitable/app.js.map +7 -0
  278. package/dist/src/tools/oapi/bitable/index.js +13 -0
  279. package/dist/src/tools/oapi/bitable/index.js.map +7 -0
  280. package/dist/src/tools/oapi/calendar/calendar.js +131 -0
  281. package/dist/src/tools/oapi/calendar/calendar.js.map +7 -0
  282. package/dist/src/tools/oapi/calendar/event-attendee.js +301 -0
  283. package/dist/src/tools/oapi/calendar/event-attendee.js.map +7 -0
  284. package/dist/src/tools/oapi/calendar/event.js +834 -0
  285. package/dist/src/tools/oapi/calendar/event.js.map +7 -0
  286. package/dist/src/tools/oapi/calendar/freebusy.js +111 -0
  287. package/dist/src/tools/oapi/calendar/freebusy.js.map +7 -0
  288. package/dist/src/tools/oapi/calendar/index.js +11 -0
  289. package/dist/src/tools/oapi/calendar/index.js.map +7 -0
  290. package/dist/src/tools/oapi/chat/chat.js +132 -0
  291. package/dist/src/tools/oapi/chat/chat.js.map +7 -0
  292. package/dist/src/tools/oapi/chat/index.js +11 -0
  293. package/dist/src/tools/oapi/chat/index.js.map +7 -0
  294. package/dist/src/tools/oapi/chat/members.js +83 -0
  295. package/dist/src/tools/oapi/chat/members.js.map +7 -0
  296. package/dist/src/tools/oapi/common/get-user.js +95 -0
  297. package/dist/src/tools/oapi/common/get-user.js.map +7 -0
  298. package/dist/src/tools/oapi/common/index.js +7 -0
  299. package/dist/src/tools/oapi/common/index.js.map +7 -0
  300. package/dist/src/tools/oapi/common/search-user.js +67 -0
  301. package/dist/src/tools/oapi/common/search-user.js.map +7 -0
  302. package/dist/src/tools/oapi/drive/doc-comments.js +310 -0
  303. package/dist/src/tools/oapi/drive/doc-comments.js.map +7 -0
  304. package/dist/src/tools/oapi/drive/doc-media.js +314 -0
  305. package/dist/src/tools/oapi/drive/doc-media.js.map +7 -0
  306. package/dist/src/tools/oapi/drive/file.js +548 -0
  307. package/dist/src/tools/oapi/drive/file.js.map +7 -0
  308. package/dist/src/tools/oapi/drive/index.js +29 -0
  309. package/dist/src/tools/oapi/drive/index.js.map +7 -0
  310. package/dist/src/tools/oapi/helpers.js +199 -0
  311. package/dist/src/tools/oapi/helpers.js.map +7 -0
  312. package/dist/src/tools/oapi/im/format-messages.js +128 -0
  313. package/dist/src/tools/oapi/im/format-messages.js.map +7 -0
  314. package/dist/src/tools/oapi/im/index.js +15 -0
  315. package/dist/src/tools/oapi/im/index.js.map +7 -0
  316. package/dist/src/tools/oapi/im/message-read.js +404 -0
  317. package/dist/src/tools/oapi/im/message-read.js.map +7 -0
  318. package/dist/src/tools/oapi/im/message.js +179 -0
  319. package/dist/src/tools/oapi/im/message.js.map +7 -0
  320. package/dist/src/tools/oapi/im/resource.js +126 -0
  321. package/dist/src/tools/oapi/im/resource.js.map +7 -0
  322. package/dist/src/tools/oapi/im/time-utils.js +169 -0
  323. package/dist/src/tools/oapi/im/time-utils.js.map +7 -0
  324. package/dist/src/tools/oapi/im/user-name-uat.js +103 -0
  325. package/dist/src/tools/oapi/im/user-name-uat.js.map +7 -0
  326. package/dist/src/tools/oapi/index.js +56 -0
  327. package/dist/src/tools/oapi/index.js.map +7 -0
  328. package/dist/src/tools/oapi/sdk-types.js +1 -0
  329. package/dist/src/tools/oapi/sdk-types.js.map +7 -0
  330. package/dist/src/tools/oapi/search/doc-search.js +215 -0
  331. package/dist/src/tools/oapi/search/doc-search.js.map +7 -0
  332. package/dist/src/tools/oapi/search/index.js +25 -0
  333. package/dist/src/tools/oapi/search/index.js.map +7 -0
  334. package/dist/src/tools/oapi/sheets/index.js +25 -0
  335. package/dist/src/tools/oapi/sheets/index.js.map +7 -0
  336. package/dist/src/tools/oapi/sheets/sheet.js +652 -0
  337. package/dist/src/tools/oapi/sheets/sheet.js.map +7 -0
  338. package/dist/src/tools/oapi/task/comment.js +151 -0
  339. package/dist/src/tools/oapi/task/comment.js.map +7 -0
  340. package/dist/src/tools/oapi/task/index.js +11 -0
  341. package/dist/src/tools/oapi/task/index.js.map +7 -0
  342. package/dist/src/tools/oapi/task/subtask.js +175 -0
  343. package/dist/src/tools/oapi/task/subtask.js.map +7 -0
  344. package/dist/src/tools/oapi/task/task.js +405 -0
  345. package/dist/src/tools/oapi/task/task.js.map +7 -0
  346. package/dist/src/tools/oapi/task/tasklist.js +366 -0
  347. package/dist/src/tools/oapi/task/tasklist.js.map +7 -0
  348. package/dist/src/tools/oapi/wiki/index.js +27 -0
  349. package/dist/src/tools/oapi/wiki/index.js.map +7 -0
  350. package/dist/src/tools/oapi/wiki/space-node.js +311 -0
  351. package/dist/src/tools/oapi/wiki/space-node.js.map +7 -0
  352. package/dist/src/tools/oapi/wiki/space.js +148 -0
  353. package/dist/src/tools/oapi/wiki/space.js.map +7 -0
  354. package/dist/src/tools/oauth-batch-auth.js +125 -0
  355. package/dist/src/tools/oauth-batch-auth.js.map +7 -0
  356. package/dist/src/tools/oauth-cards.js +269 -0
  357. package/dist/src/tools/oauth-cards.js.map +7 -0
  358. package/dist/src/tools/oauth.js +538 -0
  359. package/dist/src/tools/oauth.js.map +7 -0
  360. package/dist/src/tools/onboarding-auth.js +101 -0
  361. package/dist/src/tools/onboarding-auth.js.map +7 -0
  362. package/dist/src/tools/project-oauth.js +305 -0
  363. package/dist/src/tools/project-oauth.js.map +7 -0
  364. package/dist/src/tools/tat/im/index.js +9 -0
  365. package/dist/src/tools/tat/im/index.js.map +7 -0
  366. package/dist/src/tools/tat/im/resource.js +123 -0
  367. package/dist/src/tools/tat/im/resource.js.map +7 -0
  368. package/package.json +64 -0
@@ -0,0 +1,175 @@
1
+ import { handleFeishuMessage } from "../messaging/inbound/handler";
2
+ import { handleFeishuReaction, resolveReactionContext } from "../messaging/inbound/reaction-handler";
3
+ import { isMessageExpired } from "../messaging/inbound/dedup";
4
+ import { withTicket } from "../core/lark-ticket";
5
+ import { larkLogger } from "../core/lark-logger";
6
+ import { handleCardAction } from "../tools/auto-auth";
7
+ import { enqueueFeishuChatTask, buildQueueKey, hasActiveTask, getActiveDispatcher } from "./chat-queue";
8
+ import { extractRawTextFromEvent, isLikelyAbortText } from "./abort-detect";
9
+ const elog = larkLogger("channel/event-handlers");
10
+ function isEventOwnershipValid(ctx, data) {
11
+ const expectedAppId = ctx.lark.account.appId;
12
+ if (!expectedAppId) return true;
13
+ const eventAppId = data.app_id;
14
+ if (eventAppId == null) return true;
15
+ if (eventAppId !== expectedAppId) {
16
+ elog.warn("event app_id mismatch, discarding", {
17
+ accountId: ctx.accountId,
18
+ expected: expectedAppId,
19
+ received: String(eventAppId)
20
+ });
21
+ return false;
22
+ }
23
+ return true;
24
+ }
25
+ async function handleMessageEvent(ctx, data) {
26
+ if (!isEventOwnershipValid(ctx, data)) return;
27
+ const { accountId, log, error } = ctx;
28
+ try {
29
+ const event = data;
30
+ const msgId = event.message?.message_id ?? "unknown";
31
+ const chatId = event.message?.chat_id ?? "";
32
+ const threadId = event.message?.thread_id || void 0;
33
+ if (!ctx.messageDedup.tryRecord(msgId, accountId)) {
34
+ log(`feishu[${accountId}]: duplicate message ${msgId}, skipping`);
35
+ return;
36
+ }
37
+ if (isMessageExpired(event.message?.create_time)) {
38
+ log(`feishu[${accountId}]: message ${msgId} expired, discarding`);
39
+ return;
40
+ }
41
+ const abortText = extractRawTextFromEvent(event);
42
+ if (abortText && isLikelyAbortText(abortText)) {
43
+ const queueKey = buildQueueKey(accountId, chatId, threadId);
44
+ if (hasActiveTask(queueKey)) {
45
+ const active = getActiveDispatcher(queueKey);
46
+ if (active) {
47
+ log(`feishu[${accountId}]: abort fast-path triggered for chat ${chatId} (text="${abortText}")`);
48
+ active.abortController?.abort();
49
+ active.abortCard().catch((err) => {
50
+ error(`feishu[${accountId}]: abort fast-path abortCard failed: ${String(err)}`);
51
+ });
52
+ }
53
+ }
54
+ }
55
+ const { status } = enqueueFeishuChatTask({
56
+ accountId,
57
+ chatId,
58
+ threadId,
59
+ task: async () => {
60
+ try {
61
+ await withTicket(
62
+ {
63
+ messageId: msgId,
64
+ chatId,
65
+ accountId,
66
+ startTime: Date.now(),
67
+ senderOpenId: event.sender?.sender_id?.open_id || "",
68
+ chatType: event.message?.chat_type || void 0,
69
+ threadId
70
+ },
71
+ () => handleFeishuMessage({
72
+ cfg: ctx.cfg,
73
+ event,
74
+ botOpenId: ctx.lark.botOpenId,
75
+ runtime: ctx.runtime,
76
+ chatHistories: ctx.chatHistories,
77
+ accountId
78
+ })
79
+ );
80
+ } catch (err) {
81
+ error(`feishu[${accountId}]: error handling message: ${String(err)}`);
82
+ }
83
+ }
84
+ });
85
+ log(`feishu[${accountId}]: message ${msgId} in chat ${chatId}${threadId ? ` thread ${threadId}` : ""} \u2014 ${status}`);
86
+ } catch (err) {
87
+ error(`feishu[${accountId}]: error handling message: ${String(err)}`);
88
+ }
89
+ }
90
+ async function handleReactionEvent(ctx, data) {
91
+ if (!isEventOwnershipValid(ctx, data)) return;
92
+ const { accountId, log, error } = ctx;
93
+ try {
94
+ const event = data;
95
+ const msgId = event.message_id ?? "unknown";
96
+ log(`feishu[${accountId}]: reaction event on message ${msgId}`);
97
+ const emojiType = event.reaction_type?.emoji_type ?? "";
98
+ const operatorOpenId = event.user_id?.open_id ?? "";
99
+ const dedupKey = `${msgId}:reaction:${emojiType}:${operatorOpenId}`;
100
+ if (!ctx.messageDedup.tryRecord(dedupKey, accountId)) {
101
+ log(`feishu[${accountId}]: duplicate reaction ${dedupKey}, skipping`);
102
+ return;
103
+ }
104
+ if (isMessageExpired(event.action_time)) {
105
+ log(`feishu[${accountId}]: reaction on ${msgId} expired, discarding`);
106
+ return;
107
+ }
108
+ const preResolved = await resolveReactionContext({
109
+ cfg: ctx.cfg,
110
+ event,
111
+ botOpenId: ctx.lark.botOpenId,
112
+ runtime: ctx.runtime,
113
+ accountId
114
+ });
115
+ if (!preResolved) return;
116
+ const { status } = enqueueFeishuChatTask({
117
+ accountId,
118
+ chatId: preResolved.chatId,
119
+ threadId: preResolved.threadId,
120
+ task: async () => {
121
+ try {
122
+ await withTicket(
123
+ {
124
+ messageId: msgId,
125
+ chatId: preResolved.chatId,
126
+ accountId,
127
+ startTime: Date.now(),
128
+ senderOpenId: operatorOpenId,
129
+ chatType: preResolved.chatType,
130
+ threadId: preResolved.threadId
131
+ },
132
+ () => handleFeishuReaction({
133
+ cfg: ctx.cfg,
134
+ event,
135
+ botOpenId: ctx.lark.botOpenId,
136
+ runtime: ctx.runtime,
137
+ chatHistories: ctx.chatHistories,
138
+ accountId,
139
+ preResolved
140
+ })
141
+ );
142
+ } catch (err) {
143
+ error(`feishu[${accountId}]: error handling reaction: ${String(err)}`);
144
+ }
145
+ }
146
+ });
147
+ log(`feishu[${accountId}]: reaction on ${msgId} (chatId=${preResolved.chatId}) \u2014 ${status}`);
148
+ } catch (err) {
149
+ error(`feishu[${accountId}]: error handling reaction event: ${String(err)}`);
150
+ }
151
+ }
152
+ async function handleBotMembershipEvent(ctx, data, action) {
153
+ if (!isEventOwnershipValid(ctx, data)) return;
154
+ const { accountId, log, error } = ctx;
155
+ try {
156
+ const event = data;
157
+ log(`feishu[${accountId}]: bot ${action} ${action === "removed" ? "from" : "to"} chat ${event.chat_id}`);
158
+ } catch (err) {
159
+ error(`feishu[${accountId}]: error handling bot ${action} event: ${String(err)}`);
160
+ }
161
+ }
162
+ async function handleCardActionEvent(ctx, data) {
163
+ try {
164
+ return await handleCardAction(data, ctx.cfg, ctx.accountId);
165
+ } catch (err) {
166
+ elog.warn(`card.action.trigger handler error: ${err}`);
167
+ }
168
+ }
169
+ export {
170
+ handleBotMembershipEvent,
171
+ handleCardActionEvent,
172
+ handleMessageEvent,
173
+ handleReactionEvent
174
+ };
175
+ //# sourceMappingURL=event-handlers.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/channel/event-handlers.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * Event handlers for the Feishu WebSocket monitor.\n *\n * Extracted from monitor.ts to improve testability and reduce\n * function size. Each handler receives a MonitorContext with all\n * dependencies needed to process the event.\n */\n\nimport type { FeishuMessageEvent, FeishuBotAddedEvent, FeishuReactionCreatedEvent } from '../messaging/types';\nimport { handleFeishuMessage } from '../messaging/inbound/handler';\nimport { handleFeishuReaction, resolveReactionContext } from '../messaging/inbound/reaction-handler';\nimport { isMessageExpired } from '../messaging/inbound/dedup';\nimport { withTicket } from '../core/lark-ticket';\nimport { larkLogger } from '../core/lark-logger';\nimport { handleCardAction } from '../tools/auto-auth';\nimport { enqueueFeishuChatTask, buildQueueKey, hasActiveTask, getActiveDispatcher } from './chat-queue';\nimport { extractRawTextFromEvent, isLikelyAbortText } from './abort-detect';\nimport type { MonitorContext } from './types';\n\nconst elog = larkLogger('channel/event-handlers');\n\n// ---------------------------------------------------------------------------\n// Event ownership validation\n// ---------------------------------------------------------------------------\n\n/**\n * Verify that the event's app_id matches the current account.\n *\n * Lark SDK EventDispatcher flattens the v2 envelope header (which\n * contains `app_id`) into the handler `data` object, so `app_id` is\n * available directly on `data`.\n *\n * Returns `false` (discard event) when the app_id does not match.\n */\nfunction isEventOwnershipValid(ctx: MonitorContext, data: unknown): boolean {\n const expectedAppId = ctx.lark.account.appId;\n if (!expectedAppId) return true; // appId not configured \u2014 skip check\n\n const eventAppId = (data as Record<string, unknown>).app_id;\n if (eventAppId == null) return true; // SDK did not provide app_id \u2014 defensive skip\n\n if (eventAppId !== expectedAppId) {\n elog.warn('event app_id mismatch, discarding', {\n accountId: ctx.accountId,\n expected: expectedAppId,\n received: String(eventAppId),\n });\n return false;\n }\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// Message handler\n// ---------------------------------------------------------------------------\n\nexport async function handleMessageEvent(ctx: MonitorContext, data: unknown): Promise<void> {\n if (!isEventOwnershipValid(ctx, data)) return;\n const { accountId, log, error } = ctx;\n try {\n const event = data as FeishuMessageEvent;\n const msgId = event.message?.message_id ?? 'unknown';\n const chatId = event.message?.chat_id ?? '';\n const threadId = event.message?.thread_id || undefined;\n\n // Dedup \u2014 skip duplicate messages (e.g. from WebSocket reconnects).\n if (!ctx.messageDedup.tryRecord(msgId, accountId)) {\n log(`feishu[${accountId}]: duplicate message ${msgId}, skipping`);\n return;\n }\n\n // Expiry \u2014 discard stale messages from reconnect replay.\n if (isMessageExpired(event.message?.create_time)) {\n log(`feishu[${accountId}]: message ${msgId} expired, discarding`);\n return;\n }\n\n // ---- Abort fast-path ----\n // If the message looks like an abort trigger and there is an active\n // reply dispatcher for this chat, fire abortCard() immediately\n // (before the message enters the serial queue) so the streaming\n // card is terminated without waiting for the current task.\n const abortText = extractRawTextFromEvent(event);\n if (abortText && isLikelyAbortText(abortText)) {\n const queueKey = buildQueueKey(accountId, chatId, threadId);\n if (hasActiveTask(queueKey)) {\n const active = getActiveDispatcher(queueKey);\n if (active) {\n log(`feishu[${accountId}]: abort fast-path triggered for chat ${chatId} (text=\"${abortText}\")`);\n active.abortController?.abort();\n active.abortCard().catch((err) => {\n error(`feishu[${accountId}]: abort fast-path abortCard failed: ${String(err)}`);\n });\n }\n }\n }\n\n const { status } = enqueueFeishuChatTask({\n accountId,\n chatId,\n threadId,\n task: async () => {\n try {\n await withTicket(\n {\n messageId: msgId,\n chatId,\n accountId,\n startTime: Date.now(),\n senderOpenId: event.sender?.sender_id?.open_id || '',\n chatType: (event.message?.chat_type as 'p2p' | 'group') || undefined,\n threadId,\n },\n () =>\n handleFeishuMessage({\n cfg: ctx.cfg,\n event,\n botOpenId: ctx.lark.botOpenId,\n runtime: ctx.runtime,\n chatHistories: ctx.chatHistories,\n accountId,\n }),\n );\n } catch (err) {\n error(`feishu[${accountId}]: error handling message: ${String(err)}`);\n }\n },\n });\n log(`feishu[${accountId}]: message ${msgId} in chat ${chatId}${threadId ? ` thread ${threadId}` : ''} \u2014 ${status}`);\n } catch (err) {\n error(`feishu[${accountId}]: error handling message: ${String(err)}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Reaction handler\n// ---------------------------------------------------------------------------\n\nexport async function handleReactionEvent(ctx: MonitorContext, data: unknown): Promise<void> {\n if (!isEventOwnershipValid(ctx, data)) return;\n const { accountId, log, error } = ctx;\n try {\n const event = data as FeishuReactionCreatedEvent;\n const msgId = event.message_id ?? 'unknown';\n\n log(`feishu[${accountId}]: reaction event on message ${msgId}`);\n\n // ---- Dedup: deterministic key based on message + emoji + operator ----\n const emojiType = event.reaction_type?.emoji_type ?? '';\n const operatorOpenId = event.user_id?.open_id ?? '';\n const dedupKey = `${msgId}:reaction:${emojiType}:${operatorOpenId}`;\n if (!ctx.messageDedup.tryRecord(dedupKey, accountId)) {\n log(`feishu[${accountId}]: duplicate reaction ${dedupKey}, skipping`);\n return;\n }\n\n // ---- Expiry: discard stale reaction events ----\n if (isMessageExpired(event.action_time)) {\n log(`feishu[${accountId}]: reaction on ${msgId} expired, discarding`);\n return;\n }\n\n // ---- Pre-resolve real chatId before enqueuing ----\n // The API call (3s timeout) runs outside the queue so it doesn't\n // block the serial chain, and is read-only so ordering is irrelevant.\n const preResolved = await resolveReactionContext({\n cfg: ctx.cfg,\n event,\n botOpenId: ctx.lark.botOpenId,\n runtime: ctx.runtime,\n accountId,\n });\n if (!preResolved) return;\n\n // ---- Enqueue with the real chatId (matches normal message queue key) ----\n const { status } = enqueueFeishuChatTask({\n accountId,\n chatId: preResolved.chatId,\n threadId: preResolved.threadId,\n task: async () => {\n try {\n await withTicket(\n {\n messageId: msgId,\n chatId: preResolved.chatId,\n accountId,\n startTime: Date.now(),\n senderOpenId: operatorOpenId,\n chatType: preResolved.chatType,\n threadId: preResolved.threadId,\n },\n () =>\n handleFeishuReaction({\n cfg: ctx.cfg,\n event,\n botOpenId: ctx.lark.botOpenId,\n runtime: ctx.runtime,\n chatHistories: ctx.chatHistories,\n accountId,\n preResolved,\n }),\n );\n } catch (err) {\n error(`feishu[${accountId}]: error handling reaction: ${String(err)}`);\n }\n },\n });\n log(`feishu[${accountId}]: reaction on ${msgId} (chatId=${preResolved.chatId}) \u2014 ${status}`);\n } catch (err) {\n error(`feishu[${accountId}]: error handling reaction event: ${String(err)}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Bot membership handler\n// ---------------------------------------------------------------------------\n\nexport async function handleBotMembershipEvent(\n ctx: MonitorContext,\n data: unknown,\n action: 'added' | 'removed',\n): Promise<void> {\n if (!isEventOwnershipValid(ctx, data)) return;\n const { accountId, log, error } = ctx;\n try {\n const event = data as FeishuBotAddedEvent;\n log(`feishu[${accountId}]: bot ${action} ${action === 'removed' ? 'from' : 'to'} chat ${event.chat_id}`);\n } catch (err) {\n error(`feishu[${accountId}]: error handling bot ${action} event: ${String(err)}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Card action handler\n// ---------------------------------------------------------------------------\n\nexport async function handleCardActionEvent(ctx: MonitorContext, data: unknown): Promise<unknown> {\n try {\n return await handleCardAction(data, ctx.cfg, ctx.accountId);\n } catch (err) {\n elog.warn(`card.action.trigger handler error: ${err}`);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,108 @@
1
+ import { getLarkAccount, getEnabledLarkAccounts } from "../core/accounts";
2
+ import { LarkClient } from "../core/lark-client";
3
+ import { MessageDedup } from "../messaging/inbound/dedup";
4
+ import { larkLogger } from "../core/lark-logger";
5
+ import { drainShutdownHooks } from "../core/shutdown-hooks";
6
+ import {
7
+ handleMessageEvent,
8
+ handleReactionEvent,
9
+ handleBotMembershipEvent,
10
+ handleCardActionEvent
11
+ } from "./event-handlers";
12
+ const mlog = larkLogger("channel/monitor");
13
+ async function monitorSingleAccount(params) {
14
+ const { account, runtime, abortSignal } = params;
15
+ const { accountId } = account;
16
+ const log = runtime?.log ?? ((...args) => mlog.info(args.map(String).join(" ")));
17
+ const error = runtime?.error ?? ((...args) => mlog.error(args.map(String).join(" ")));
18
+ const connectionMode = account.config.connectionMode ?? "websocket";
19
+ if (connectionMode !== "websocket") {
20
+ log(`feishu[${accountId}]: webhook mode not implemented in monitor`);
21
+ return;
22
+ }
23
+ const dedupCfg = account.config.dedup;
24
+ const messageDedup = new MessageDedup({
25
+ ttlMs: dedupCfg?.ttlMs,
26
+ maxEntries: dedupCfg?.maxEntries
27
+ });
28
+ log(
29
+ `feishu[${accountId}]: message dedup enabled (ttl=${messageDedup["ttlMs"]}ms, max=${messageDedup["maxEntries"]})`
30
+ );
31
+ log(`feishu[${accountId}]: starting WebSocket connection...`);
32
+ const lark = LarkClient.fromAccount(account);
33
+ lark.messageDedup = messageDedup;
34
+ const chatHistories = /* @__PURE__ */ new Map();
35
+ const ctx = {
36
+ get cfg() {
37
+ return LarkClient.runtime.config.loadConfig();
38
+ },
39
+ lark,
40
+ accountId,
41
+ chatHistories,
42
+ messageDedup,
43
+ runtime,
44
+ log,
45
+ error
46
+ };
47
+ await lark.startWS({
48
+ handlers: {
49
+ "im.message.receive_v1": (data) => handleMessageEvent(ctx, data),
50
+ "im.message.message_read_v1": async () => {
51
+ },
52
+ "im.message.reaction.created_v1": (data) => handleReactionEvent(ctx, data),
53
+ "im.chat.member.bot.added_v1": (data) => handleBotMembershipEvent(ctx, data, "added"),
54
+ "im.chat.member.bot.deleted_v1": (data) => handleBotMembershipEvent(ctx, data, "removed"),
55
+ // 飞书 SDK EventDispatcher.register 不支持带返回值的处理器,此处 as any 是 SDK 类型限制的变通
56
+ "card.action.trigger": ((data) => (
57
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
58
+ handleCardActionEvent(ctx, data)
59
+ ))
60
+ },
61
+ abortSignal
62
+ });
63
+ log(`feishu[${accountId}]: bot open_id resolved: ${lark.botOpenId ?? "unknown"}`);
64
+ log(`feishu[${accountId}]: WebSocket client started`);
65
+ mlog.info(`websocket started for account ${accountId}`);
66
+ }
67
+ async function monitorFeishuProvider(opts = {}) {
68
+ const cfg = opts.config;
69
+ if (!cfg) {
70
+ throw new Error("Config is required for Feishu monitor");
71
+ }
72
+ LarkClient.setGlobalConfig(cfg);
73
+ const log = opts.runtime?.log ?? ((...args) => mlog.info(args.map(String).join(" ")));
74
+ if (opts.accountId) {
75
+ const account = getLarkAccount(cfg, opts.accountId);
76
+ if (!account.enabled || !account.configured) {
77
+ throw new Error(`Feishu account "${opts.accountId}" not configured or disabled`);
78
+ }
79
+ await monitorSingleAccount({
80
+ cfg,
81
+ account,
82
+ runtime: opts.runtime,
83
+ abortSignal: opts.abortSignal
84
+ });
85
+ await drainShutdownHooks({ log });
86
+ return;
87
+ }
88
+ const accounts = getEnabledLarkAccounts(cfg);
89
+ if (accounts.length === 0) {
90
+ throw new Error("No enabled Feishu accounts configured");
91
+ }
92
+ log(`feishu: starting ${accounts.length} account(s): ${accounts.map((a) => a.accountId).join(", ")}`);
93
+ await Promise.all(
94
+ accounts.map(
95
+ (account) => monitorSingleAccount({
96
+ cfg,
97
+ account,
98
+ runtime: opts.runtime,
99
+ abortSignal: opts.abortSignal
100
+ })
101
+ )
102
+ );
103
+ await drainShutdownHooks({ log });
104
+ }
105
+ export {
106
+ monitorFeishuProvider
107
+ };
108
+ //# sourceMappingURL=monitor.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/channel/monitor.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * WebSocket monitoring for the Lark/Feishu channel plugin.\n *\n * Manages per-account WSClient connections and routes inbound Feishu\n * events (messages, bot membership changes, read receipts) to the\n * appropriate handlers.\n */\n\nimport type { ClawdbotConfig, RuntimeEnv, HistoryEntry } from 'openclaw/plugin-sdk';\nimport { getLarkAccount, getEnabledLarkAccounts } from '../core/accounts';\nimport { LarkClient } from '../core/lark-client';\nimport { MessageDedup } from '../messaging/inbound/dedup';\nimport { larkLogger } from '../core/lark-logger';\nimport { drainShutdownHooks } from '../core/shutdown-hooks';\nimport type { MonitorFeishuOpts, MonitorContext } from './types';\nimport {\n handleMessageEvent,\n handleReactionEvent,\n handleBotMembershipEvent,\n handleCardActionEvent,\n} from './event-handlers';\n\nconst mlog = larkLogger('channel/monitor');\n\n// Re-export type for backward compatibility\nexport type { MonitorFeishuOpts } from './types';\n\n// ---------------------------------------------------------------------------\n// Single-account monitor\n// ---------------------------------------------------------------------------\n\n/**\n * Start monitoring a single Feishu account.\n *\n * Creates a LarkClient, probes bot identity, registers event handlers,\n * and starts a WebSocket connection. Returns a Promise that resolves\n * when the abort signal fires (or immediately if already aborted).\n */\nasync function monitorSingleAccount(params: {\n cfg: ClawdbotConfig;\n account: ReturnType<typeof getLarkAccount>;\n runtime?: RuntimeEnv;\n abortSignal?: AbortSignal;\n}): Promise<void> {\n const { account, runtime, abortSignal } = params;\n const { accountId } = account;\n const log = runtime?.log ?? ((...args: unknown[]) => mlog.info(args.map(String).join(' ')));\n const error = runtime?.error ?? ((...args: unknown[]) => mlog.error(args.map(String).join(' ')));\n\n // Only websocket mode is supported in the monitor path.\n const connectionMode = account.config.connectionMode ?? 'websocket';\n if (connectionMode !== 'websocket') {\n log(`feishu[${accountId}]: webhook mode not implemented in monitor`);\n return;\n }\n\n // Message dedup \u2014 filters duplicate deliveries from WebSocket reconnects.\n const dedupCfg = account.config.dedup;\n const messageDedup = new MessageDedup({\n ttlMs: dedupCfg?.ttlMs,\n maxEntries: dedupCfg?.maxEntries,\n });\n log(\n `feishu[${accountId}]: message dedup enabled (ttl=${messageDedup['ttlMs']}ms, max=${messageDedup['maxEntries']})`,\n );\n\n log(`feishu[${accountId}]: starting WebSocket connection...`);\n\n // Create LarkClient instance \u2014 manages SDK client, WS, and bot identity.\n const lark = LarkClient.fromAccount(account);\n\n // Attach dedup instance so it is disposed together with the client.\n lark.messageDedup = messageDedup;\n\n /** Per-chat history maps (used for group-chat context window). */\n const chatHistories = new Map<string, HistoryEntry[]>();\n\n const ctx: MonitorContext = {\n get cfg() {\n return LarkClient.runtime.config.loadConfig();\n },\n lark,\n accountId,\n chatHistories,\n messageDedup,\n runtime,\n log,\n error,\n };\n\n await lark.startWS({\n handlers: {\n 'im.message.receive_v1': (data) => handleMessageEvent(ctx, data),\n 'im.message.message_read_v1': async () => {},\n 'im.message.reaction.created_v1': (data) => handleReactionEvent(ctx, data),\n 'im.chat.member.bot.added_v1': (data) => handleBotMembershipEvent(ctx, data, 'added'),\n 'im.chat.member.bot.deleted_v1': (data) => handleBotMembershipEvent(ctx, data, 'removed'),\n // \u98DE\u4E66 SDK EventDispatcher.register \u4E0D\u652F\u6301\u5E26\u8FD4\u56DE\u503C\u7684\u5904\u7406\u5668\uFF0C\u6B64\u5904 as any \u662F SDK \u7C7B\u578B\u9650\u5236\u7684\u53D8\u901A\n 'card.action.trigger': ((data: unknown) =>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handleCardActionEvent(ctx, data)) as any,\n },\n abortSignal,\n });\n\n // startWS resolves when abortSignal fires \u2014 probe result is logged inside startWS.\n log(`feishu[${accountId}]: bot open_id resolved: ${lark.botOpenId ?? 'unknown'}`);\n log(`feishu[${accountId}]: WebSocket client started`);\n mlog.info(`websocket started for account ${accountId}`);\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Start monitoring for all enabled Feishu accounts (or a single\n * account when `opts.accountId` is specified).\n */\nexport async function monitorFeishuProvider(opts: MonitorFeishuOpts = {}): Promise<void> {\n const cfg = opts.config;\n if (!cfg) {\n throw new Error('Config is required for Feishu monitor');\n }\n\n // Store the original global config so plugin commands (doctor, diagnose)\n // can access cross-account information even when running inside an\n // account-scoped config context.\n LarkClient.setGlobalConfig(cfg);\n\n const log = opts.runtime?.log ?? ((...args: unknown[]) => mlog.info(args.map(String).join(' ')));\n\n // Single-account mode.\n if (opts.accountId) {\n const account = getLarkAccount(cfg, opts.accountId);\n if (!account.enabled || !account.configured) {\n throw new Error(`Feishu account \"${opts.accountId}\" not configured or disabled`);\n }\n await monitorSingleAccount({\n cfg,\n account,\n runtime: opts.runtime,\n abortSignal: opts.abortSignal,\n });\n await drainShutdownHooks({ log });\n return;\n }\n\n // Multi-account mode: start all enabled accounts in parallel.\n const accounts = getEnabledLarkAccounts(cfg);\n if (accounts.length === 0) {\n throw new Error('No enabled Feishu accounts configured');\n }\n\n log(`feishu: starting ${accounts.length} account(s): ${accounts.map((a) => a.accountId).join(', ')}`);\n\n await Promise.all(\n accounts.map((account) =>\n monitorSingleAccount({\n cfg,\n account,\n runtime: opts.runtime,\n abortSignal: opts.abortSignal,\n }),\n ),\n );\n await drainShutdownHooks({ log });\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,76 @@
1
+ import { addWildcardAllowFrom } from "openclaw/plugin-sdk";
2
+ function setFeishuDmPolicy(cfg, dmPolicy) {
3
+ const allowFrom = dmPolicy === "open" ? addWildcardAllowFrom(cfg.channels?.feishu?.allowFrom)?.map((entry) => String(entry)) : void 0;
4
+ return {
5
+ ...cfg,
6
+ channels: {
7
+ ...cfg.channels,
8
+ feishu: {
9
+ ...cfg.channels?.feishu,
10
+ dmPolicy,
11
+ ...allowFrom ? { allowFrom } : {}
12
+ }
13
+ }
14
+ };
15
+ }
16
+ function setFeishuAllowFrom(cfg, allowFrom) {
17
+ return {
18
+ ...cfg,
19
+ channels: {
20
+ ...cfg.channels,
21
+ feishu: {
22
+ ...cfg.channels?.feishu,
23
+ allowFrom
24
+ }
25
+ }
26
+ };
27
+ }
28
+ function setFeishuGroupPolicy(cfg, groupPolicy) {
29
+ return {
30
+ ...cfg,
31
+ channels: {
32
+ ...cfg.channels,
33
+ feishu: {
34
+ ...cfg.channels?.feishu,
35
+ enabled: true,
36
+ groupPolicy
37
+ }
38
+ }
39
+ };
40
+ }
41
+ function setFeishuGroupAllowFrom(cfg, groupAllowFrom) {
42
+ return {
43
+ ...cfg,
44
+ channels: {
45
+ ...cfg.channels,
46
+ feishu: {
47
+ ...cfg.channels?.feishu,
48
+ groupAllowFrom
49
+ }
50
+ }
51
+ };
52
+ }
53
+ function setFeishuGroups(cfg, groups) {
54
+ return {
55
+ ...cfg,
56
+ channels: {
57
+ ...cfg.channels,
58
+ feishu: {
59
+ ...cfg.channels?.feishu,
60
+ groups
61
+ }
62
+ }
63
+ };
64
+ }
65
+ function parseAllowFromInput(raw) {
66
+ return raw.split(/[\n,;]+/g).map((entry) => entry.trim()).filter(Boolean);
67
+ }
68
+ export {
69
+ parseAllowFromInput,
70
+ setFeishuAllowFrom,
71
+ setFeishuDmPolicy,
72
+ setFeishuGroupAllowFrom,
73
+ setFeishuGroupPolicy,
74
+ setFeishuGroups
75
+ };
76
+ //# sourceMappingURL=onboarding-config.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/channel/onboarding-config.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * Onboarding configuration mutation helpers.\n *\n * Pure functions that apply Feishu channel configuration changes\n * to a ClawdbotConfig. Extracted from onboarding.ts for reuse\n * in CLI commands and other configuration flows.\n */\n\nimport type { ClawdbotConfig, DmPolicy } from 'openclaw/plugin-sdk';\nimport { addWildcardAllowFrom } from 'openclaw/plugin-sdk';\n\n// ---------------------------------------------------------------------------\n// Config mutation helpers\n// ---------------------------------------------------------------------------\n\nexport function setFeishuDmPolicy(cfg: ClawdbotConfig, dmPolicy: DmPolicy): ClawdbotConfig {\n const allowFrom =\n dmPolicy === 'open'\n ? addWildcardAllowFrom(cfg.channels?.feishu?.allowFrom)?.map((entry) => String(entry))\n : undefined;\n\n return {\n ...cfg,\n channels: {\n ...cfg.channels,\n feishu: {\n ...cfg.channels?.feishu,\n dmPolicy,\n ...(allowFrom ? { allowFrom } : {}),\n },\n },\n };\n}\n\nexport function setFeishuAllowFrom(cfg: ClawdbotConfig, allowFrom: string[]): ClawdbotConfig {\n return {\n ...cfg,\n channels: {\n ...cfg.channels,\n feishu: {\n ...cfg.channels?.feishu,\n allowFrom,\n },\n },\n };\n}\n\nexport function setFeishuGroupPolicy(\n cfg: ClawdbotConfig,\n groupPolicy: 'open' | 'allowlist' | 'disabled',\n): ClawdbotConfig {\n return {\n ...cfg,\n channels: {\n ...cfg.channels,\n feishu: {\n ...cfg.channels?.feishu,\n enabled: true,\n groupPolicy,\n },\n },\n };\n}\n\nexport function setFeishuGroupAllowFrom(cfg: ClawdbotConfig, groupAllowFrom: string[]): ClawdbotConfig {\n return {\n ...cfg,\n channels: {\n ...cfg.channels,\n feishu: {\n ...cfg.channels?.feishu,\n groupAllowFrom,\n },\n },\n };\n}\n\nexport function setFeishuGroups(cfg: ClawdbotConfig, groups: Record<string, object>): ClawdbotConfig {\n return {\n ...cfg,\n channels: {\n ...cfg.channels,\n feishu: {\n ...cfg.channels?.feishu,\n groups,\n },\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Input helpers\n// ---------------------------------------------------------------------------\n\nexport function parseAllowFromInput(raw: string): string[] {\n return raw\n .split(/[\\n,;]+/g)\n .map((entry) => entry.trim())\n .filter(Boolean);\n}\n"],
5
+ "mappings": "AAYA,SAAS,4BAA4B;AAM9B,SAAS,kBAAkB,KAAqB,UAAoC;AACzF,QAAM,YACJ,aAAa,SACT,qBAAqB,IAAI,UAAU,QAAQ,SAAS,GAAG,IAAI,CAAC,UAAU,OAAO,KAAK,CAAC,IACnF;AAEN,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU;AAAA,MACR,GAAG,IAAI;AAAA,MACP,QAAQ;AAAA,QACN,GAAG,IAAI,UAAU;AAAA,QACjB;AAAA,QACA,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,mBAAmB,KAAqB,WAAqC;AAC3F,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU;AAAA,MACR,GAAG,IAAI;AAAA,MACP,QAAQ;AAAA,QACN,GAAG,IAAI,UAAU;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,qBACd,KACA,aACgB;AAChB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU;AAAA,MACR,GAAG,IAAI;AAAA,MACP,QAAQ;AAAA,QACN,GAAG,IAAI,UAAU;AAAA,QACjB,SAAS;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,wBAAwB,KAAqB,gBAA0C;AACrG,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU;AAAA,MACR,GAAG,IAAI;AAAA,MACP,QAAQ;AAAA,QACN,GAAG,IAAI,UAAU;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,gBAAgB,KAAqB,QAAgD;AACnG,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU;AAAA,MACR,GAAG,IAAI;AAAA,MACP,QAAQ;AAAA,QACN,GAAG,IAAI,UAAU;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAMO,SAAS,oBAAoB,KAAuB;AACzD,SAAO,IACJ,MAAM,UAAU,EAChB,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAC3B,OAAO,OAAO;AACnB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,55 @@
1
+ import { setFeishuGroups, setFeishuGroupAllowFrom } from "./onboarding-config";
2
+ async function migrateLegacyGroupAllowFrom(params) {
3
+ let next = params.cfg;
4
+ const { prompter } = params;
5
+ const existingGroupAllowFrom = next.channels?.feishu?.groupAllowFrom ?? [];
6
+ const legacyChatIds = existingGroupAllowFrom.filter((e) => String(e).startsWith("oc_"));
7
+ const senderAllowFrom = existingGroupAllowFrom.filter((e) => !String(e).startsWith("oc_"));
8
+ if (legacyChatIds.length === 0) {
9
+ return next;
10
+ }
11
+ await prompter.note(
12
+ [
13
+ `\u26A0\uFE0F Detected legacy config: groupAllowFrom contains chat_ids (${legacyChatIds.join(", ")})`,
14
+ "",
15
+ "Old semantic: groupAllowFrom controlled which groups could use the bot.",
16
+ "New semantic: groupAllowFrom is for SENDER filtering (open_ids like ou_xxx).",
17
+ "",
18
+ "Recommended migration:",
19
+ ` 1. Move chat_ids (oc_xxx) \u2192 channels.feishu.groups`,
20
+ ` 2. Keep sender IDs (ou_xxx) in groupAllowFrom`
21
+ ].join("\n"),
22
+ "Legacy config detected"
23
+ );
24
+ const migrate = await prompter.confirm({
25
+ message: `Migrate ${legacyChatIds.length} chat_id(s) to groups config?`,
26
+ initialValue: true
27
+ });
28
+ if (migrate) {
29
+ const existingGroups = next.channels?.feishu?.groups ?? {};
30
+ const migratedGroups = {
31
+ ...existingGroups
32
+ };
33
+ for (const chatId of legacyChatIds) {
34
+ if (!migratedGroups[String(chatId)]) {
35
+ migratedGroups[String(chatId)] = {
36
+ enabled: true,
37
+ groupPolicy: "open"
38
+ };
39
+ }
40
+ }
41
+ next = setFeishuGroups(next, migratedGroups);
42
+ next = setFeishuGroupAllowFrom(next, senderAllowFrom);
43
+ await prompter.note(
44
+ `\u2705 Migrated: ${legacyChatIds.length} chat_id(s) moved to groups, ${senderAllowFrom.length} sender(s) kept in groupAllowFrom`,
45
+ "Migration complete"
46
+ );
47
+ } else {
48
+ await prompter.note("Skipped migration. Please update config manually to avoid issues.", "Migration skipped");
49
+ }
50
+ return next;
51
+ }
52
+ export {
53
+ migrateLegacyGroupAllowFrom
54
+ };
55
+ //# sourceMappingURL=onboarding-migrate.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/channel/onboarding-migrate.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * Legacy groupAllowFrom migration for Feishu onboarding.\n *\n * Handles the migration of chat_id entries (oc_xxx) from\n * groupAllowFrom to the groups config, preserving the original\n * semantic of \"allow this group for any sender\".\n */\n\nimport type { ClawdbotConfig, WizardPrompter } from 'openclaw/plugin-sdk';\nimport type { FeishuConfig, FeishuGroupConfig } from '../core/types';\nimport { setFeishuGroups, setFeishuGroupAllowFrom } from './onboarding-config';\n\n/**\n * Detect and migrate legacy chat_id entries in groupAllowFrom.\n *\n * Old semantic: groupAllowFrom contained chat_ids (oc_xxx) to control\n * which groups could use the bot.\n * New semantic: groupAllowFrom is for sender filtering (open_ids like ou_xxx).\n *\n * This function prompts the user and, if confirmed, moves chat_ids\n * to the groups config and keeps only sender IDs in groupAllowFrom.\n */\nexport async function migrateLegacyGroupAllowFrom(params: {\n cfg: ClawdbotConfig;\n prompter: WizardPrompter;\n}): Promise<ClawdbotConfig> {\n let next = params.cfg;\n const { prompter } = params;\n\n const existingGroupAllowFrom = (next.channels?.feishu as FeishuConfig | undefined)?.groupAllowFrom ?? [];\n const legacyChatIds = existingGroupAllowFrom.filter((e) => String(e).startsWith('oc_'));\n const senderAllowFrom = existingGroupAllowFrom.filter((e) => !String(e).startsWith('oc_'));\n\n if (legacyChatIds.length === 0) {\n return next;\n }\n\n await prompter.note(\n [\n `\u26A0\uFE0F Detected legacy config: groupAllowFrom contains chat_ids (${legacyChatIds.join(', ')})`,\n '',\n 'Old semantic: groupAllowFrom controlled which groups could use the bot.',\n 'New semantic: groupAllowFrom is for SENDER filtering (open_ids like ou_xxx).',\n '',\n 'Recommended migration:',\n ` 1. Move chat_ids (oc_xxx) \u2192 channels.feishu.groups`,\n ` 2. Keep sender IDs (ou_xxx) in groupAllowFrom`,\n ].join('\\n'),\n 'Legacy config detected',\n );\n\n const migrate = await prompter.confirm({\n message: `Migrate ${legacyChatIds.length} chat_id(s) to groups config?`,\n initialValue: true,\n });\n\n if (migrate) {\n const existingGroups = (next.channels?.feishu as FeishuConfig | undefined)?.groups ?? {};\n const migratedGroups: Record<string, FeishuGroupConfig> = {\n ...existingGroups,\n };\n for (const chatId of legacyChatIds) {\n if (!migratedGroups[String(chatId)]) {\n migratedGroups[String(chatId)] = {\n enabled: true,\n groupPolicy: 'open',\n } as FeishuGroupConfig;\n }\n }\n next = setFeishuGroups(next, migratedGroups as Record<string, object>);\n\n next = setFeishuGroupAllowFrom(next, senderAllowFrom);\n\n await prompter.note(\n `\u2705 Migrated: ${legacyChatIds.length} chat_id(s) moved to groups, ` +\n `${senderAllowFrom.length} sender(s) kept in groupAllowFrom`,\n 'Migration complete',\n );\n } else {\n await prompter.note('Skipped migration. Please update config manually to avoid issues.', 'Migration skipped');\n }\n\n return next;\n}\n"],
5
+ "mappings": "AAaA,SAAS,iBAAiB,+BAA+B;AAYzD,eAAsB,4BAA4B,QAGtB;AAC1B,MAAI,OAAO,OAAO;AAClB,QAAM,EAAE,SAAS,IAAI;AAErB,QAAM,yBAA0B,KAAK,UAAU,QAAqC,kBAAkB,CAAC;AACvG,QAAM,gBAAgB,uBAAuB,OAAO,CAAC,MAAM,OAAO,CAAC,EAAE,WAAW,KAAK,CAAC;AACtF,QAAM,kBAAkB,uBAAuB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,WAAW,KAAK,CAAC;AAEzF,MAAI,cAAc,WAAW,GAAG;AAC9B,WAAO;AAAA,EACT;AAEA,QAAM,SAAS;AAAA,IACb;AAAA,MACE,2EAAiE,cAAc,KAAK,IAAI,CAAC;AAAA,MACzF;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,IACX;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,SAAS,QAAQ;AAAA,IACrC,SAAS,WAAW,cAAc,MAAM;AAAA,IACxC,cAAc;AAAA,EAChB,CAAC;AAED,MAAI,SAAS;AACX,UAAM,iBAAkB,KAAK,UAAU,QAAqC,UAAU,CAAC;AACvF,UAAM,iBAAoD;AAAA,MACxD,GAAG;AAAA,IACL;AACA,eAAW,UAAU,eAAe;AAClC,UAAI,CAAC,eAAe,OAAO,MAAM,CAAC,GAAG;AACnC,uBAAe,OAAO,MAAM,CAAC,IAAI;AAAA,UAC/B,SAAS;AAAA,UACT,aAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AACA,WAAO,gBAAgB,MAAM,cAAwC;AAErE,WAAO,wBAAwB,MAAM,eAAe;AAEpD,UAAM,SAAS;AAAA,MACb,oBAAe,cAAc,MAAM,gCAC9B,gBAAgB,MAAM;AAAA,MAC3B;AAAA,IACF;AAAA,EACF,OAAO;AACL,UAAM,SAAS,KAAK,qEAAqE,mBAAmB;AAAA,EAC9G;AAEA,SAAO;AACT;",
6
+ "names": []
7
+ }