@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,285 @@
1
+ import { DEFAULT_ACCOUNT_ID, formatDocsLink } from "openclaw/plugin-sdk";
2
+ import { getLarkCredentials } from "../core/accounts";
3
+ import { probeFeishu } from "./probe";
4
+ import {
5
+ setFeishuDmPolicy,
6
+ setFeishuAllowFrom,
7
+ setFeishuGroupPolicy,
8
+ setFeishuGroupAllowFrom,
9
+ parseAllowFromInput
10
+ } from "./onboarding-config";
11
+ import { migrateLegacyGroupAllowFrom } from "./onboarding-migrate";
12
+ const channel = "feishu";
13
+ async function noteFeishuCredentialHelp(prompter) {
14
+ await prompter.note(
15
+ [
16
+ "1) Go to Feishu Open Platform (open.feishu.cn)",
17
+ "2) Create a self-built app",
18
+ "3) Get App ID and App Secret from Credentials page",
19
+ "4) Enable required permissions: im:message, im:chat, contact:user.base:readonly",
20
+ "5) Publish the app or add it to a test group",
21
+ "Tip: you can also set FEISHU_APP_ID / FEISHU_APP_SECRET env vars.",
22
+ `Docs: ${formatDocsLink("/channels/feishu", "feishu")}`
23
+ ].join("\n"),
24
+ "Feishu credentials"
25
+ );
26
+ }
27
+ async function promptFeishuAllowFrom(params) {
28
+ const existing = params.cfg.channels?.feishu?.allowFrom ?? [];
29
+ await params.prompter.note(
30
+ [
31
+ "Allowlist Feishu DMs by open_id or user_id.",
32
+ "You can find user open_id in Feishu admin console or via API.",
33
+ "Examples:",
34
+ "- ou_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
35
+ "- on_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
36
+ ].join("\n"),
37
+ "Feishu allowlist"
38
+ );
39
+ while (true) {
40
+ const entry = await params.prompter.text({
41
+ message: "Feishu allowFrom (user open_ids)",
42
+ placeholder: "ou_xxxxx, ou_yyyyy",
43
+ initialValue: existing[0] ? String(existing[0]) : void 0,
44
+ validate: (value) => String(value ?? "").trim() ? void 0 : "Required"
45
+ });
46
+ const parts = parseAllowFromInput(String(entry));
47
+ if (parts.length === 0) {
48
+ await params.prompter.note("Enter at least one user.", "Feishu allowlist");
49
+ continue;
50
+ }
51
+ const unique = [.../* @__PURE__ */ new Set([...existing.map((v) => String(v).trim()).filter(Boolean), ...parts])];
52
+ return setFeishuAllowFrom(params.cfg, unique);
53
+ }
54
+ }
55
+ async function acquireCredentials(params) {
56
+ const { prompter, feishuCfg } = params;
57
+ let next = params.cfg;
58
+ const hasConfigCreds = Boolean(feishuCfg?.appId?.trim() && feishuCfg?.appSecret?.trim());
59
+ const canUseEnv = Boolean(
60
+ !hasConfigCreds && process.env.FEISHU_APP_ID?.trim() && process.env.FEISHU_APP_SECRET?.trim()
61
+ );
62
+ let appId = null;
63
+ let appSecret = null;
64
+ if (canUseEnv) {
65
+ const keepEnv = await prompter.confirm({
66
+ message: "FEISHU_APP_ID + FEISHU_APP_SECRET detected. Use env vars?",
67
+ initialValue: true
68
+ });
69
+ if (keepEnv) {
70
+ next = {
71
+ ...next,
72
+ channels: {
73
+ ...next.channels,
74
+ feishu: { ...next.channels?.feishu, enabled: true }
75
+ }
76
+ };
77
+ } else {
78
+ appId = String(
79
+ await prompter.text({
80
+ message: "Enter Feishu App ID",
81
+ validate: (value) => value?.trim() ? void 0 : "Required"
82
+ })
83
+ ).trim();
84
+ appSecret = String(
85
+ await prompter.text({
86
+ message: "Enter Feishu App Secret",
87
+ validate: (value) => value?.trim() ? void 0 : "Required"
88
+ })
89
+ ).trim();
90
+ }
91
+ } else if (hasConfigCreds) {
92
+ const keep = await prompter.confirm({
93
+ message: "Feishu credentials already configured. Keep them?",
94
+ initialValue: true
95
+ });
96
+ if (!keep) {
97
+ appId = String(
98
+ await prompter.text({
99
+ message: "Enter Feishu App ID",
100
+ validate: (value) => value?.trim() ? void 0 : "Required"
101
+ })
102
+ ).trim();
103
+ appSecret = String(
104
+ await prompter.text({
105
+ message: "Enter Feishu App Secret",
106
+ validate: (value) => value?.trim() ? void 0 : "Required"
107
+ })
108
+ ).trim();
109
+ }
110
+ } else {
111
+ appId = String(
112
+ await prompter.text({
113
+ message: "Enter Feishu App ID",
114
+ validate: (value) => value?.trim() ? void 0 : "Required"
115
+ })
116
+ ).trim();
117
+ appSecret = String(
118
+ await prompter.text({
119
+ message: "Enter Feishu App Secret",
120
+ validate: (value) => value?.trim() ? void 0 : "Required"
121
+ })
122
+ ).trim();
123
+ }
124
+ return { cfg: next, appId, appSecret };
125
+ }
126
+ const dmPolicy = {
127
+ label: "Feishu",
128
+ channel,
129
+ policyKey: "channels.feishu.dmPolicy",
130
+ allowFromKey: "channels.feishu.allowFrom",
131
+ getCurrent: (cfg) => cfg.channels?.feishu?.dmPolicy ?? "pairing",
132
+ setPolicy: (cfg, policy) => setFeishuDmPolicy(cfg, policy),
133
+ promptAllowFrom: promptFeishuAllowFrom
134
+ };
135
+ const feishuOnboardingAdapter = {
136
+ channel,
137
+ // -----------------------------------------------------------------------
138
+ // getStatus
139
+ // -----------------------------------------------------------------------
140
+ getStatus: async ({ cfg }) => {
141
+ const feishuCfg = cfg.channels?.feishu;
142
+ const configured = Boolean(getLarkCredentials(feishuCfg));
143
+ let probeResult = null;
144
+ if (configured && feishuCfg) {
145
+ try {
146
+ probeResult = await probeFeishu(feishuCfg);
147
+ } catch {
148
+ }
149
+ }
150
+ const statusLines = [];
151
+ if (!configured) {
152
+ statusLines.push("Feishu: needs app credentials");
153
+ } else if (probeResult?.ok) {
154
+ statusLines.push(`Feishu: connected as ${probeResult.botName ?? probeResult.botOpenId ?? "bot"}`);
155
+ } else {
156
+ statusLines.push("Feishu: configured (connection not verified)");
157
+ }
158
+ return {
159
+ channel,
160
+ configured,
161
+ statusLines,
162
+ selectionHint: configured ? "configured" : "needs app creds",
163
+ quickstartScore: configured ? 2 : 0
164
+ };
165
+ },
166
+ // -----------------------------------------------------------------------
167
+ // configure
168
+ // -----------------------------------------------------------------------
169
+ configure: async ({ cfg, prompter }) => {
170
+ const feishuCfg = cfg.channels?.feishu;
171
+ const resolved = getLarkCredentials(feishuCfg);
172
+ let next = cfg;
173
+ if (!resolved) {
174
+ await noteFeishuCredentialHelp(prompter);
175
+ }
176
+ const creds = await acquireCredentials({ cfg: next, prompter, feishuCfg });
177
+ next = creds.cfg;
178
+ if (creds.appId && creds.appSecret) {
179
+ next = {
180
+ ...next,
181
+ channels: {
182
+ ...next.channels,
183
+ feishu: {
184
+ ...next.channels?.feishu,
185
+ enabled: true,
186
+ appId: creds.appId,
187
+ appSecret: creds.appSecret
188
+ }
189
+ }
190
+ };
191
+ const testCfg = next.channels?.feishu;
192
+ try {
193
+ const probe = await probeFeishu(testCfg);
194
+ if (probe.ok) {
195
+ await prompter.note(`Connected as ${probe.botName ?? probe.botOpenId ?? "bot"}`, "Feishu connection test");
196
+ } else {
197
+ await prompter.note(`Connection failed: ${probe.error ?? "unknown error"}`, "Feishu connection test");
198
+ }
199
+ } catch (err) {
200
+ await prompter.note(`Connection test failed: ${String(err)}`, "Feishu connection test");
201
+ }
202
+ }
203
+ const currentDomain = next.channels?.feishu?.domain ?? "feishu";
204
+ const domain = await prompter.select({
205
+ message: "Which Feishu domain?",
206
+ options: [
207
+ { value: "feishu", label: "Feishu (feishu.cn) - China" },
208
+ { value: "lark", label: "Lark (larksuite.com) - International" }
209
+ ],
210
+ initialValue: currentDomain
211
+ });
212
+ if (domain) {
213
+ next = {
214
+ ...next,
215
+ channels: {
216
+ ...next.channels,
217
+ feishu: {
218
+ ...next.channels?.feishu,
219
+ domain
220
+ }
221
+ }
222
+ };
223
+ }
224
+ next = await migrateLegacyGroupAllowFrom({ cfg: next, prompter });
225
+ const groupPolicy = await prompter.select({
226
+ message: "Group chat policy \u2014 which groups can interact with the bot?",
227
+ options: [
228
+ {
229
+ value: "allowlist",
230
+ label: "Allowlist \u2014 only groups listed in `groups` config (default)"
231
+ },
232
+ {
233
+ value: "open",
234
+ label: "Open \u2014 any group (requires @mention)"
235
+ },
236
+ {
237
+ value: "disabled",
238
+ label: "Disabled \u2014 no group interactions"
239
+ }
240
+ ],
241
+ initialValue: next.channels?.feishu?.groupPolicy ?? "allowlist"
242
+ });
243
+ if (groupPolicy) {
244
+ next = setFeishuGroupPolicy(next, groupPolicy);
245
+ }
246
+ if (groupPolicy !== "disabled") {
247
+ const existing = next.channels?.feishu?.groupAllowFrom ?? [];
248
+ const entry = await prompter.text({
249
+ message: "Group sender allowlist \u2014 which users can trigger the bot in allowed groups? (user open_ids)",
250
+ placeholder: "ou_xxxxx, ou_yyyyy",
251
+ initialValue: existing.length > 0 ? existing.map(String).join(", ") : void 0
252
+ });
253
+ if (entry) {
254
+ const parts = parseAllowFromInput(String(entry));
255
+ if (parts.length > 0) {
256
+ next = setFeishuGroupAllowFrom(next, parts);
257
+ }
258
+ } else if (groupPolicy === "allowlist") {
259
+ await prompter.note(
260
+ "Empty sender list + allowlist = nobody can trigger. Use groupPolicy 'open' if you want anyone in allowed groups to trigger.",
261
+ "Note"
262
+ );
263
+ }
264
+ }
265
+ return { cfg: next, accountId: DEFAULT_ACCOUNT_ID };
266
+ },
267
+ // -----------------------------------------------------------------------
268
+ // dmPolicy
269
+ // -----------------------------------------------------------------------
270
+ dmPolicy,
271
+ // -----------------------------------------------------------------------
272
+ // disable
273
+ // -----------------------------------------------------------------------
274
+ disable: (cfg) => ({
275
+ ...cfg,
276
+ channels: {
277
+ ...cfg.channels,
278
+ feishu: { ...cfg.channels?.feishu, enabled: false }
279
+ }
280
+ })
281
+ };
282
+ export {
283
+ feishuOnboardingAdapter
284
+ };
285
+ //# sourceMappingURL=onboarding.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/channel/onboarding.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * Onboarding wizard adapter for the Lark/Feishu channel plugin.\n *\n * Implements the ChannelOnboardingAdapter interface so the `openclaw\n * setup` wizard can configure Feishu credentials, domain, group\n * policies, and DM allowlists interactively.\n */\n\nimport type {\n ChannelOnboardingAdapter,\n ChannelOnboardingDmPolicy,\n ClawdbotConfig,\n WizardPrompter,\n} from 'openclaw/plugin-sdk';\nimport { DEFAULT_ACCOUNT_ID, formatDocsLink } from 'openclaw/plugin-sdk';\nimport type { FeishuConfig } from '../core/types';\nimport { getLarkCredentials } from '../core/accounts';\nimport { probeFeishu } from './probe';\nimport {\n setFeishuDmPolicy,\n setFeishuAllowFrom,\n setFeishuGroupPolicy,\n setFeishuGroupAllowFrom,\n parseAllowFromInput,\n} from './onboarding-config';\nimport { migrateLegacyGroupAllowFrom } from './onboarding-migrate';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst channel = 'feishu' as const;\n\n// ---------------------------------------------------------------------------\n// Prompter helpers\n// ---------------------------------------------------------------------------\n\nasync function noteFeishuCredentialHelp(prompter: WizardPrompter): Promise<void> {\n await prompter.note(\n [\n '1) Go to Feishu Open Platform (open.feishu.cn)',\n '2) Create a self-built app',\n '3) Get App ID and App Secret from Credentials page',\n '4) Enable required permissions: im:message, im:chat, contact:user.base:readonly',\n '5) Publish the app or add it to a test group',\n 'Tip: you can also set FEISHU_APP_ID / FEISHU_APP_SECRET env vars.',\n `Docs: ${formatDocsLink('/channels/feishu', 'feishu')}`,\n ].join('\\n'),\n 'Feishu credentials',\n );\n}\n\nasync function promptFeishuAllowFrom(params: {\n cfg: ClawdbotConfig;\n prompter: WizardPrompter;\n accountId?: string;\n}): Promise<ClawdbotConfig> {\n const existing = params.cfg.channels?.feishu?.allowFrom ?? [];\n\n await params.prompter.note(\n [\n 'Allowlist Feishu DMs by open_id or user_id.',\n 'You can find user open_id in Feishu admin console or via API.',\n 'Examples:',\n '- ou_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',\n '- on_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',\n ].join('\\n'),\n 'Feishu allowlist',\n );\n\n while (true) {\n const entry = await params.prompter.text({\n message: 'Feishu allowFrom (user open_ids)',\n placeholder: 'ou_xxxxx, ou_yyyyy',\n initialValue: existing[0] ? String(existing[0]) : undefined,\n validate: (value) => (String(value ?? '').trim() ? undefined : 'Required'),\n });\n\n const parts = parseAllowFromInput(String(entry));\n if (parts.length === 0) {\n await params.prompter.note('Enter at least one user.', 'Feishu allowlist');\n continue;\n }\n\n const unique = [...new Set([...existing.map((v: string | number) => String(v).trim()).filter(Boolean), ...parts])];\n return setFeishuAllowFrom(params.cfg, unique);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Credential acquisition\n// ---------------------------------------------------------------------------\n\nasync function acquireCredentials(params: {\n cfg: ClawdbotConfig;\n prompter: WizardPrompter;\n feishuCfg: FeishuConfig | undefined;\n}): Promise<{ cfg: ClawdbotConfig; appId: string | null; appSecret: string | null }> {\n const { prompter, feishuCfg } = params;\n let next = params.cfg;\n\n const hasConfigCreds = Boolean(feishuCfg?.appId?.trim() && feishuCfg?.appSecret?.trim());\n const canUseEnv = Boolean(\n !hasConfigCreds && process.env.FEISHU_APP_ID?.trim() && process.env.FEISHU_APP_SECRET?.trim(),\n );\n\n let appId: string | null = null;\n let appSecret: string | null = null;\n\n if (canUseEnv) {\n const keepEnv = await prompter.confirm({\n message: 'FEISHU_APP_ID + FEISHU_APP_SECRET detected. Use env vars?',\n initialValue: true,\n });\n if (keepEnv) {\n next = {\n ...next,\n channels: {\n ...next.channels,\n feishu: { ...next.channels?.feishu, enabled: true },\n },\n };\n } else {\n appId = String(\n await prompter.text({\n message: 'Enter Feishu App ID',\n validate: (value) => (value?.trim() ? undefined : 'Required'),\n }),\n ).trim();\n appSecret = String(\n await prompter.text({\n message: 'Enter Feishu App Secret',\n validate: (value) => (value?.trim() ? undefined : 'Required'),\n }),\n ).trim();\n }\n } else if (hasConfigCreds) {\n const keep = await prompter.confirm({\n message: 'Feishu credentials already configured. Keep them?',\n initialValue: true,\n });\n if (!keep) {\n appId = String(\n await prompter.text({\n message: 'Enter Feishu App ID',\n validate: (value) => (value?.trim() ? undefined : 'Required'),\n }),\n ).trim();\n appSecret = String(\n await prompter.text({\n message: 'Enter Feishu App Secret',\n validate: (value) => (value?.trim() ? undefined : 'Required'),\n }),\n ).trim();\n }\n } else {\n appId = String(\n await prompter.text({\n message: 'Enter Feishu App ID',\n validate: (value) => (value?.trim() ? undefined : 'Required'),\n }),\n ).trim();\n appSecret = String(\n await prompter.text({\n message: 'Enter Feishu App Secret',\n validate: (value) => (value?.trim() ? undefined : 'Required'),\n }),\n ).trim();\n }\n\n return { cfg: next, appId, appSecret };\n}\n\n// ---------------------------------------------------------------------------\n// DM policy\n// ---------------------------------------------------------------------------\n\nconst dmPolicy: ChannelOnboardingDmPolicy = {\n label: 'Feishu',\n channel,\n policyKey: 'channels.feishu.dmPolicy',\n allowFromKey: 'channels.feishu.allowFrom',\n getCurrent: (cfg) => (cfg.channels?.feishu as FeishuConfig | undefined)?.dmPolicy ?? 'pairing',\n setPolicy: (cfg, policy) => setFeishuDmPolicy(cfg, policy),\n promptAllowFrom: promptFeishuAllowFrom,\n};\n\n// ---------------------------------------------------------------------------\n// Adapter\n// ---------------------------------------------------------------------------\n\nexport const feishuOnboardingAdapter: ChannelOnboardingAdapter = {\n channel,\n\n // -----------------------------------------------------------------------\n // getStatus\n // -----------------------------------------------------------------------\n getStatus: async ({ cfg }) => {\n const feishuCfg = cfg.channels?.feishu as FeishuConfig | undefined;\n const configured = Boolean(getLarkCredentials(feishuCfg));\n\n // Attempt a live probe when credentials are present.\n let probeResult = null;\n if (configured && feishuCfg) {\n try {\n probeResult = await probeFeishu(feishuCfg);\n } catch {\n // Ignore probe errors -- status degrades gracefully.\n }\n }\n\n const statusLines: string[] = [];\n if (!configured) {\n statusLines.push('Feishu: needs app credentials');\n } else if (probeResult?.ok) {\n statusLines.push(`Feishu: connected as ${probeResult.botName ?? probeResult.botOpenId ?? 'bot'}`);\n } else {\n statusLines.push('Feishu: configured (connection not verified)');\n }\n\n return {\n channel,\n configured,\n statusLines,\n selectionHint: configured ? 'configured' : 'needs app creds',\n quickstartScore: configured ? 2 : 0,\n };\n },\n\n // -----------------------------------------------------------------------\n // configure\n // -----------------------------------------------------------------------\n configure: async ({ cfg, prompter }) => {\n const feishuCfg = cfg.channels?.feishu as FeishuConfig | undefined;\n const resolved = getLarkCredentials(feishuCfg);\n\n let next = cfg;\n\n // Show credential help if nothing is configured yet.\n if (!resolved) {\n await noteFeishuCredentialHelp(prompter);\n }\n\n // --- Credential acquisition ---\n const creds = await acquireCredentials({ cfg: next, prompter, feishuCfg });\n next = creds.cfg;\n\n // --- Persist and test credentials ---\n if (creds.appId && creds.appSecret) {\n next = {\n ...next,\n channels: {\n ...next.channels,\n feishu: {\n ...next.channels?.feishu,\n enabled: true,\n appId: creds.appId,\n appSecret: creds.appSecret,\n },\n },\n };\n\n const testCfg = next.channels?.feishu as FeishuConfig;\n try {\n const probe = await probeFeishu(testCfg);\n if (probe.ok) {\n await prompter.note(`Connected as ${probe.botName ?? probe.botOpenId ?? 'bot'}`, 'Feishu connection test');\n } else {\n await prompter.note(`Connection failed: ${probe.error ?? 'unknown error'}`, 'Feishu connection test');\n }\n } catch (err) {\n await prompter.note(`Connection test failed: ${String(err)}`, 'Feishu connection test');\n }\n }\n\n // --- Domain selection ---\n const currentDomain = (next.channels?.feishu as FeishuConfig | undefined)?.domain ?? 'feishu';\n const domain = await prompter.select({\n message: 'Which Feishu domain?',\n options: [\n { value: 'feishu', label: 'Feishu (feishu.cn) - China' },\n { value: 'lark', label: 'Lark (larksuite.com) - International' },\n ],\n initialValue: currentDomain,\n });\n if (domain) {\n next = {\n ...next,\n channels: {\n ...next.channels,\n feishu: {\n ...next.channels?.feishu,\n domain: domain as 'feishu' | 'lark',\n },\n },\n };\n }\n\n // --- Legacy migration ---\n next = await migrateLegacyGroupAllowFrom({ cfg: next, prompter });\n\n // --- Group policy ---\n const groupPolicy = await prompter.select({\n message: 'Group chat policy \u2014 which groups can interact with the bot?',\n options: [\n {\n value: 'allowlist',\n label: 'Allowlist \u2014 only groups listed in `groups` config (default)',\n },\n {\n value: 'open',\n label: 'Open \u2014 any group (requires @mention)',\n },\n {\n value: 'disabled',\n label: 'Disabled \u2014 no group interactions',\n },\n ],\n initialValue: (next.channels?.feishu as FeishuConfig | undefined)?.groupPolicy ?? 'allowlist',\n });\n if (groupPolicy) {\n next = setFeishuGroupPolicy(next, groupPolicy as 'open' | 'allowlist' | 'disabled');\n }\n\n // --- Group sender allowlist ---\n if (groupPolicy !== 'disabled') {\n const existing = (next.channels?.feishu as FeishuConfig | undefined)?.groupAllowFrom ?? [];\n const entry = await prompter.text({\n message: 'Group sender allowlist \u2014 which users can trigger the bot in allowed groups? (user open_ids)',\n placeholder: 'ou_xxxxx, ou_yyyyy',\n initialValue: existing.length > 0 ? existing.map(String).join(', ') : undefined,\n });\n if (entry) {\n const parts = parseAllowFromInput(String(entry));\n if (parts.length > 0) {\n next = setFeishuGroupAllowFrom(next, parts);\n }\n } else if (groupPolicy === 'allowlist') {\n await prompter.note(\n 'Empty sender list + allowlist = nobody can trigger. ' +\n \"Use groupPolicy 'open' if you want anyone in allowed groups to trigger.\",\n 'Note',\n );\n }\n }\n\n return { cfg: next, accountId: DEFAULT_ACCOUNT_ID };\n },\n\n // -----------------------------------------------------------------------\n // dmPolicy\n // -----------------------------------------------------------------------\n dmPolicy,\n\n // -----------------------------------------------------------------------\n // disable\n // -----------------------------------------------------------------------\n disable: (cfg) => ({\n ...cfg,\n channels: {\n ...cfg.channels,\n feishu: { ...cfg.channels?.feishu, enabled: false },\n },\n }),\n};\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,260 @@
1
+ import { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk";
2
+ import { getLarkAccount, getLarkAccountIds, getDefaultLarkAccountId } from "../core/accounts";
3
+ import {
4
+ listFeishuDirectoryPeers,
5
+ listFeishuDirectoryGroups,
6
+ listFeishuDirectoryPeersLive,
7
+ listFeishuDirectoryGroupsLive
8
+ } from "./directory";
9
+ import { feishuOnboardingAdapter } from "./onboarding";
10
+ import { feishuOutbound } from "../messaging/outbound/outbound";
11
+ import { feishuMessageActions } from "../messaging/outbound/actions";
12
+ import { resolveFeishuGroupToolPolicy } from "../messaging/inbound/policy";
13
+ import { LarkClient } from "../core/lark-client";
14
+ import { sendMessageFeishu } from "../messaging/outbound/send";
15
+ import { normalizeFeishuTarget, looksLikeFeishuId } from "../core/targets";
16
+ import { triggerOnboarding } from "../tools/onboarding-auth";
17
+ import { setAccountEnabled, applyAccountConfig, deleteAccount, collectFeishuSecurityWarnings } from "./config-adapter";
18
+ import { larkLogger } from "../core/lark-logger";
19
+ import { FEISHU_CONFIG_JSON_SCHEMA } from "../core/config-schema";
20
+ const pluginLog = larkLogger("channel/plugin");
21
+ const PROBE_CACHE_TTL_MS = 10 * 60 * 1e3;
22
+ function adaptDirectoryParams(params) {
23
+ return {
24
+ cfg: params.cfg,
25
+ query: params.query ?? void 0,
26
+ limit: params.limit ?? void 0,
27
+ accountId: params.accountId ?? void 0
28
+ };
29
+ }
30
+ const meta = {
31
+ id: "feishu",
32
+ label: "Feishu",
33
+ selectionLabel: "Lark/Feishu (\u98DE\u4E66)",
34
+ docsPath: "/channels/feishu",
35
+ docsLabel: "feishu",
36
+ blurb: "\u98DE\u4E66/Lark enterprise messaging.",
37
+ aliases: ["lark"],
38
+ order: 70
39
+ };
40
+ const feishuPlugin = {
41
+ id: "feishu",
42
+ meta: {
43
+ ...meta
44
+ },
45
+ // -------------------------------------------------------------------------
46
+ // Pairing
47
+ // -------------------------------------------------------------------------
48
+ pairing: {
49
+ idLabel: "feishuUserId",
50
+ normalizeAllowEntry: (entry) => entry.replace(/^(feishu|user|open_id):/i, ""),
51
+ notifyApproval: async ({ cfg, id }) => {
52
+ const accountId = getDefaultLarkAccountId(cfg);
53
+ pluginLog.info("notifyApproval called", { id, accountId });
54
+ await sendMessageFeishu({
55
+ cfg,
56
+ to: id,
57
+ text: PAIRING_APPROVED_MESSAGE,
58
+ accountId
59
+ });
60
+ try {
61
+ await triggerOnboarding({ cfg, userOpenId: id, accountId });
62
+ pluginLog.info("onboarding completed", { id });
63
+ } catch (err) {
64
+ pluginLog.warn("onboarding failed", { id, error: String(err) });
65
+ }
66
+ }
67
+ },
68
+ // -------------------------------------------------------------------------
69
+ // Capabilities
70
+ // -------------------------------------------------------------------------
71
+ capabilities: {
72
+ chatTypes: ["direct", "group"],
73
+ media: true,
74
+ reactions: true,
75
+ threads: true,
76
+ polls: false,
77
+ nativeCommands: true,
78
+ blockStreaming: true
79
+ },
80
+ // -------------------------------------------------------------------------
81
+ // Agent prompt
82
+ // -------------------------------------------------------------------------
83
+ agentPrompt: {
84
+ messageToolHints: () => [
85
+ "- Feishu targeting: omit `target` to reply to the current conversation (auto-inferred). Explicit targets: `user:open_id` or `chat:chat_id`.",
86
+ "- Feishu supports interactive cards for rich messages.",
87
+ "- Feishu reactions use UPPERCASE emoji type names (e.g. `OK`,`THUMBSUP`,`THANKS`,`MUSCLE`,`FINGERHEART`,`APPLAUSE`,`FISTBUMP`,`JIAYI`,`DONE`,`SMILE`,`BLUSH` ), not Unicode emoji characters.",
88
+ "- Feishu `action=delete`/`action=unsend` only deletes messages sent by the bot. When the user quotes a message and says 'delete this', use the **quoted message's** message_id, not the user's own message_id."
89
+ ]
90
+ },
91
+ // -------------------------------------------------------------------------
92
+ // Groups
93
+ // -------------------------------------------------------------------------
94
+ groups: {
95
+ resolveToolPolicy: resolveFeishuGroupToolPolicy
96
+ },
97
+ // -------------------------------------------------------------------------
98
+ // Reload
99
+ // -------------------------------------------------------------------------
100
+ reload: { configPrefixes: ["channels.feishu"] },
101
+ // -------------------------------------------------------------------------
102
+ // Config schema (JSON Schema)
103
+ // -------------------------------------------------------------------------
104
+ configSchema: {
105
+ schema: FEISHU_CONFIG_JSON_SCHEMA
106
+ },
107
+ // -------------------------------------------------------------------------
108
+ // Config adapter
109
+ // -------------------------------------------------------------------------
110
+ config: {
111
+ listAccountIds: (cfg) => getLarkAccountIds(cfg),
112
+ resolveAccount: (cfg, accountId) => getLarkAccount(cfg, accountId),
113
+ defaultAccountId: (cfg) => getDefaultLarkAccountId(cfg),
114
+ setAccountEnabled: ({ cfg, accountId, enabled }) => {
115
+ return setAccountEnabled(cfg, accountId, enabled);
116
+ },
117
+ deleteAccount: ({ cfg, accountId }) => {
118
+ return deleteAccount(cfg, accountId);
119
+ },
120
+ isConfigured: (account) => account.configured,
121
+ describeAccount: (account) => ({
122
+ accountId: account.accountId,
123
+ enabled: account.enabled,
124
+ configured: account.configured,
125
+ name: account.name,
126
+ appId: account.appId,
127
+ brand: account.brand
128
+ }),
129
+ resolveAllowFrom: ({ cfg, accountId }) => {
130
+ const account = getLarkAccount(cfg, accountId);
131
+ return (account.config?.allowFrom ?? []).map((entry) => String(entry));
132
+ },
133
+ formatAllowFrom: ({ allowFrom }) => allowFrom.map((entry) => String(entry).trim()).filter(Boolean).map((entry) => entry.toLowerCase())
134
+ },
135
+ // -------------------------------------------------------------------------
136
+ // Security
137
+ // -------------------------------------------------------------------------
138
+ security: {
139
+ collectWarnings: ({ cfg, accountId }) => collectFeishuSecurityWarnings({ cfg, accountId: accountId ?? DEFAULT_ACCOUNT_ID })
140
+ },
141
+ // -------------------------------------------------------------------------
142
+ // Setup
143
+ // -------------------------------------------------------------------------
144
+ setup: {
145
+ resolveAccountId: () => DEFAULT_ACCOUNT_ID,
146
+ applyAccountConfig: ({ cfg, accountId }) => {
147
+ return applyAccountConfig(cfg, accountId, { enabled: true });
148
+ }
149
+ },
150
+ // -------------------------------------------------------------------------
151
+ // Onboarding
152
+ // -------------------------------------------------------------------------
153
+ onboarding: feishuOnboardingAdapter,
154
+ // -------------------------------------------------------------------------
155
+ // Messaging
156
+ // -------------------------------------------------------------------------
157
+ messaging: {
158
+ normalizeTarget: (raw) => normalizeFeishuTarget(raw) ?? void 0,
159
+ targetResolver: {
160
+ looksLikeId: looksLikeFeishuId,
161
+ hint: "<chatId|user:openId|chat:chatId>"
162
+ }
163
+ },
164
+ // -------------------------------------------------------------------------
165
+ // Directory
166
+ // -------------------------------------------------------------------------
167
+ directory: {
168
+ self: async () => null,
169
+ listPeers: async (p) => listFeishuDirectoryPeers(adaptDirectoryParams(p)),
170
+ listGroups: async (p) => listFeishuDirectoryGroups(adaptDirectoryParams(p)),
171
+ listPeersLive: async (p) => listFeishuDirectoryPeersLive(adaptDirectoryParams(p)),
172
+ listGroupsLive: async (p) => listFeishuDirectoryGroupsLive(adaptDirectoryParams(p))
173
+ },
174
+ // -------------------------------------------------------------------------
175
+ // Outbound
176
+ // -------------------------------------------------------------------------
177
+ outbound: feishuOutbound,
178
+ // -------------------------------------------------------------------------
179
+ // Threading
180
+ // -------------------------------------------------------------------------
181
+ threading: {
182
+ buildToolContext: ({ context, hasRepliedRef }) => ({
183
+ currentChannelId: normalizeFeishuTarget(context.To ?? "") ?? void 0,
184
+ currentThreadTs: context.MessageThreadId != null ? String(context.MessageThreadId) : void 0,
185
+ currentMessageId: context.CurrentMessageId,
186
+ hasRepliedRef
187
+ })
188
+ },
189
+ // -------------------------------------------------------------------------
190
+ // Actions
191
+ // -------------------------------------------------------------------------
192
+ actions: feishuMessageActions,
193
+ // -------------------------------------------------------------------------
194
+ // Status
195
+ // -------------------------------------------------------------------------
196
+ status: {
197
+ defaultRuntime: {
198
+ accountId: DEFAULT_ACCOUNT_ID,
199
+ running: false,
200
+ lastStartAt: null,
201
+ lastStopAt: null,
202
+ lastError: null,
203
+ port: null
204
+ },
205
+ buildChannelSummary: ({ snapshot }) => ({
206
+ configured: snapshot.configured ?? false,
207
+ running: snapshot.running ?? false,
208
+ lastStartAt: snapshot.lastStartAt ?? null,
209
+ lastStopAt: snapshot.lastStopAt ?? null,
210
+ lastError: snapshot.lastError ?? null,
211
+ port: snapshot.port ?? null,
212
+ probe: snapshot.probe,
213
+ lastProbeAt: snapshot.lastProbeAt ?? null
214
+ }),
215
+ probeAccount: async ({ account }) => {
216
+ return await LarkClient.fromAccount(account).probe({ maxAgeMs: PROBE_CACHE_TTL_MS });
217
+ },
218
+ buildAccountSnapshot: ({ account, runtime, probe }) => ({
219
+ accountId: account.accountId,
220
+ enabled: account.enabled,
221
+ configured: account.configured,
222
+ name: account.name,
223
+ appId: account.appId,
224
+ brand: account.brand,
225
+ running: runtime?.running ?? false,
226
+ lastStartAt: runtime?.lastStartAt ?? null,
227
+ lastStopAt: runtime?.lastStopAt ?? null,
228
+ lastError: runtime?.lastError ?? null,
229
+ port: runtime?.port ?? null,
230
+ probe
231
+ })
232
+ },
233
+ // -------------------------------------------------------------------------
234
+ // Gateway
235
+ // -------------------------------------------------------------------------
236
+ gateway: {
237
+ startAccount: async (ctx) => {
238
+ const { monitorFeishuProvider } = await import("./monitor.js");
239
+ const account = getLarkAccount(ctx.cfg, ctx.accountId);
240
+ const port = account.config?.webhookPort ?? null;
241
+ ctx.setStatus({ accountId: ctx.accountId, port });
242
+ ctx.log?.info(`starting feishu[${ctx.accountId}] (mode: ${account.config?.connectionMode ?? "websocket"})`);
243
+ return monitorFeishuProvider({
244
+ config: ctx.cfg,
245
+ runtime: ctx.runtime,
246
+ abortSignal: ctx.abortSignal,
247
+ accountId: ctx.accountId
248
+ });
249
+ },
250
+ stopAccount: async (ctx) => {
251
+ ctx.log?.info(`stopping feishu[${ctx.accountId}]`);
252
+ LarkClient.clearCache(ctx.accountId);
253
+ ctx.log?.info(`stopped feishu[${ctx.accountId}]`);
254
+ }
255
+ }
256
+ };
257
+ export {
258
+ feishuPlugin
259
+ };
260
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/channel/plugin.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * ChannelPlugin interface implementation for the Lark/Feishu channel.\n *\n * This is the top-level entry point that the OpenClaw plugin system uses to\n * discover capabilities, resolve accounts, obtain outbound adapters, and\n * start the inbound event gateway.\n */\n\nimport type { ChannelMeta, ChannelPlugin, ChannelThreadingToolContext, ClawdbotConfig } from 'openclaw/plugin-sdk';\nimport { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE } from 'openclaw/plugin-sdk';\nimport type { LarkAccount } from '../core/types';\nimport { getLarkAccount, getLarkAccountIds, getDefaultLarkAccountId } from '../core/accounts';\nimport {\n listFeishuDirectoryPeers,\n listFeishuDirectoryGroups,\n listFeishuDirectoryPeersLive,\n listFeishuDirectoryGroupsLive,\n} from './directory';\nimport { feishuOnboardingAdapter } from './onboarding';\nimport { feishuOutbound } from '../messaging/outbound/outbound';\nimport { feishuMessageActions } from '../messaging/outbound/actions';\nimport { resolveFeishuGroupToolPolicy } from '../messaging/inbound/policy';\nimport { LarkClient } from '../core/lark-client';\nimport { sendMessageFeishu } from '../messaging/outbound/send';\nimport { normalizeFeishuTarget, looksLikeFeishuId } from '../core/targets';\nimport { triggerOnboarding } from '../tools/onboarding-auth';\nimport { setAccountEnabled, applyAccountConfig, deleteAccount, collectFeishuSecurityWarnings } from './config-adapter';\nimport { larkLogger } from '../core/lark-logger';\nimport { FEISHU_CONFIG_JSON_SCHEMA } from '../core/config-schema';\n\nconst pluginLog = larkLogger('channel/plugin');\n\n/** \u72B6\u6001\u8F6E\u8BE2\u7684\u63A2\u9488\u7ED3\u679C\u7F13\u5B58\u65F6\u957F\uFF0810 \u5206\u949F\uFF09\u3002 */\nconst PROBE_CACHE_TTL_MS = 10 * 60 * 1000;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Convert nullable SDK params to optional params for directory functions. */\nfunction adaptDirectoryParams(params: {\n cfg: ClawdbotConfig;\n query?: string | null;\n limit?: number | null;\n accountId?: string | null;\n}): { cfg: ClawdbotConfig; query?: string; limit?: number; accountId?: string } {\n return {\n cfg: params.cfg,\n query: params.query ?? undefined,\n limit: params.limit ?? undefined,\n accountId: params.accountId ?? undefined,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Meta\n// ---------------------------------------------------------------------------\n\nconst meta: ChannelMeta = {\n id: 'feishu',\n label: 'Feishu',\n selectionLabel: 'Lark/Feishu (\\u98DE\\u4E66)',\n docsPath: '/channels/feishu',\n docsLabel: 'feishu',\n blurb: '\\u98DE\\u4E66/Lark enterprise messaging.',\n aliases: ['lark'],\n order: 70,\n};\n\n// ---------------------------------------------------------------------------\n// Channel plugin definition\n// ---------------------------------------------------------------------------\n\nexport const feishuPlugin: ChannelPlugin<LarkAccount> = {\n id: 'feishu',\n\n meta: {\n ...meta,\n },\n\n // -------------------------------------------------------------------------\n // Pairing\n // -------------------------------------------------------------------------\n\n pairing: {\n idLabel: 'feishuUserId',\n normalizeAllowEntry: (entry) => entry.replace(/^(feishu|user|open_id):/i, ''),\n notifyApproval: async ({ cfg, id }) => {\n const accountId = getDefaultLarkAccountId(cfg);\n pluginLog.info('notifyApproval called', { id, accountId });\n\n // 1. \u53D1\u9001\u914D\u5BF9\u6210\u529F\u6D88\u606F\uFF08\u4FDD\u6301\u73B0\u6709\u884C\u4E3A\uFF09\n await sendMessageFeishu({\n cfg,\n to: id,\n text: PAIRING_APPROVED_MESSAGE,\n accountId,\n });\n\n // 2. \u89E6\u53D1 onboarding\n try {\n await triggerOnboarding({ cfg, userOpenId: id, accountId });\n pluginLog.info('onboarding completed', { id });\n } catch (err) {\n pluginLog.warn('onboarding failed', { id, error: String(err) });\n }\n },\n },\n\n // -------------------------------------------------------------------------\n // Capabilities\n // -------------------------------------------------------------------------\n\n capabilities: {\n chatTypes: ['direct', 'group'],\n media: true,\n reactions: true,\n threads: true,\n polls: false,\n nativeCommands: true,\n blockStreaming: true,\n },\n\n // -------------------------------------------------------------------------\n // Agent prompt\n // -------------------------------------------------------------------------\n\n agentPrompt: {\n messageToolHints: () => [\n '- Feishu targeting: omit `target` to reply to the current conversation (auto-inferred). Explicit targets: `user:open_id` or `chat:chat_id`.',\n '- Feishu supports interactive cards for rich messages.',\n '- Feishu reactions use UPPERCASE emoji type names (e.g. `OK`,`THUMBSUP`,`THANKS`,`MUSCLE`,`FINGERHEART`,`APPLAUSE`,`FISTBUMP`,`JIAYI`,`DONE`,`SMILE`,`BLUSH` ), not Unicode emoji characters.',\n \"- Feishu `action=delete`/`action=unsend` only deletes messages sent by the bot. When the user quotes a message and says 'delete this', use the **quoted message's** message_id, not the user's own message_id.\",\n ],\n },\n\n // -------------------------------------------------------------------------\n // Groups\n // -------------------------------------------------------------------------\n\n groups: {\n resolveToolPolicy: resolveFeishuGroupToolPolicy,\n },\n\n // -------------------------------------------------------------------------\n // Reload\n // -------------------------------------------------------------------------\n\n reload: { configPrefixes: ['channels.feishu'] },\n\n // -------------------------------------------------------------------------\n // Config schema (JSON Schema)\n // -------------------------------------------------------------------------\n\n configSchema: {\n schema: FEISHU_CONFIG_JSON_SCHEMA,\n },\n\n // -------------------------------------------------------------------------\n // Config adapter\n // -------------------------------------------------------------------------\n\n config: {\n listAccountIds: (cfg) => getLarkAccountIds(cfg),\n resolveAccount: (cfg, accountId) => getLarkAccount(cfg, accountId),\n defaultAccountId: (cfg) => getDefaultLarkAccountId(cfg),\n\n setAccountEnabled: ({ cfg, accountId, enabled }) => {\n return setAccountEnabled(cfg, accountId, enabled);\n },\n\n deleteAccount: ({ cfg, accountId }) => {\n return deleteAccount(cfg, accountId);\n },\n\n isConfigured: (account) => account.configured,\n\n describeAccount: (account) => ({\n accountId: account.accountId,\n enabled: account.enabled,\n configured: account.configured,\n name: account.name,\n appId: account.appId,\n brand: account.brand,\n }),\n\n resolveAllowFrom: ({ cfg, accountId }) => {\n const account = getLarkAccount(cfg, accountId);\n return (account.config?.allowFrom ?? []).map((entry) => String(entry));\n },\n\n formatAllowFrom: ({ allowFrom }) =>\n allowFrom\n .map((entry) => String(entry).trim())\n .filter(Boolean)\n .map((entry) => entry.toLowerCase()),\n },\n\n // -------------------------------------------------------------------------\n // Security\n // -------------------------------------------------------------------------\n\n security: {\n collectWarnings: ({ cfg, accountId }) =>\n collectFeishuSecurityWarnings({ cfg, accountId: accountId ?? DEFAULT_ACCOUNT_ID }),\n },\n\n // -------------------------------------------------------------------------\n // Setup\n // -------------------------------------------------------------------------\n\n setup: {\n resolveAccountId: () => DEFAULT_ACCOUNT_ID,\n applyAccountConfig: ({ cfg, accountId }) => {\n return applyAccountConfig(cfg, accountId, { enabled: true });\n },\n },\n\n // -------------------------------------------------------------------------\n // Onboarding\n // -------------------------------------------------------------------------\n\n onboarding: feishuOnboardingAdapter,\n\n // -------------------------------------------------------------------------\n // Messaging\n // -------------------------------------------------------------------------\n\n messaging: {\n normalizeTarget: (raw) => normalizeFeishuTarget(raw) ?? undefined,\n targetResolver: {\n looksLikeId: looksLikeFeishuId,\n hint: '<chatId|user:openId|chat:chatId>',\n },\n },\n\n // -------------------------------------------------------------------------\n // Directory\n // -------------------------------------------------------------------------\n\n directory: {\n self: async () => null,\n listPeers: async (p) => listFeishuDirectoryPeers(adaptDirectoryParams(p)),\n listGroups: async (p) => listFeishuDirectoryGroups(adaptDirectoryParams(p)),\n listPeersLive: async (p) => listFeishuDirectoryPeersLive(adaptDirectoryParams(p)),\n listGroupsLive: async (p) => listFeishuDirectoryGroupsLive(adaptDirectoryParams(p)),\n },\n\n // -------------------------------------------------------------------------\n // Outbound\n // -------------------------------------------------------------------------\n\n outbound: feishuOutbound,\n\n // -------------------------------------------------------------------------\n // Threading\n // -------------------------------------------------------------------------\n\n threading: {\n buildToolContext: ({ context, hasRepliedRef }): ChannelThreadingToolContext => ({\n currentChannelId: normalizeFeishuTarget(context.To ?? '') ?? undefined,\n currentThreadTs: context.MessageThreadId != null ? String(context.MessageThreadId) : undefined,\n currentMessageId: context.CurrentMessageId,\n hasRepliedRef,\n }),\n },\n\n // -------------------------------------------------------------------------\n // Actions\n // -------------------------------------------------------------------------\n\n actions: feishuMessageActions,\n\n // -------------------------------------------------------------------------\n // Status\n // -------------------------------------------------------------------------\n\n status: {\n defaultRuntime: {\n accountId: DEFAULT_ACCOUNT_ID,\n running: false,\n lastStartAt: null,\n lastStopAt: null,\n lastError: null,\n port: null,\n },\n buildChannelSummary: ({ snapshot }) => ({\n configured: snapshot.configured ?? false,\n running: snapshot.running ?? false,\n lastStartAt: snapshot.lastStartAt ?? null,\n lastStopAt: snapshot.lastStopAt ?? null,\n lastError: snapshot.lastError ?? null,\n port: snapshot.port ?? null,\n probe: snapshot.probe,\n lastProbeAt: snapshot.lastProbeAt ?? null,\n }),\n probeAccount: async ({ account }) => {\n return await LarkClient.fromAccount(account).probe({ maxAgeMs: PROBE_CACHE_TTL_MS });\n },\n buildAccountSnapshot: ({ account, runtime, probe }) => ({\n accountId: account.accountId,\n enabled: account.enabled,\n configured: account.configured,\n name: account.name,\n appId: account.appId,\n brand: account.brand,\n running: runtime?.running ?? false,\n lastStartAt: runtime?.lastStartAt ?? null,\n lastStopAt: runtime?.lastStopAt ?? null,\n lastError: runtime?.lastError ?? null,\n port: runtime?.port ?? null,\n probe,\n }),\n },\n\n // -------------------------------------------------------------------------\n // Gateway\n // -------------------------------------------------------------------------\n\n gateway: {\n startAccount: async (ctx) => {\n const { monitorFeishuProvider } = await import('./monitor.js');\n const account = getLarkAccount(ctx.cfg, ctx.accountId);\n const port = account.config?.webhookPort ?? null;\n ctx.setStatus({ accountId: ctx.accountId, port });\n ctx.log?.info(`starting feishu[${ctx.accountId}] (mode: ${account.config?.connectionMode ?? 'websocket'})`);\n return monitorFeishuProvider({\n config: ctx.cfg,\n runtime: ctx.runtime,\n abortSignal: ctx.abortSignal,\n accountId: ctx.accountId,\n });\n },\n\n stopAccount: async (ctx) => {\n ctx.log?.info(`stopping feishu[${ctx.accountId}]`);\n LarkClient.clearCache(ctx.accountId);\n ctx.log?.info(`stopped feishu[${ctx.accountId}]`);\n },\n },\n};\n"],
5
+ "mappings": "AAYA,SAAS,oBAAoB,gCAAgC;AAE7D,SAAS,gBAAgB,mBAAmB,+BAA+B;AAC3E;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,+BAA+B;AACxC,SAAS,sBAAsB;AAC/B,SAAS,4BAA4B;AACrC,SAAS,oCAAoC;AAC7C,SAAS,kBAAkB;AAC3B,SAAS,yBAAyB;AAClC,SAAS,uBAAuB,yBAAyB;AACzD,SAAS,yBAAyB;AAClC,SAAS,mBAAmB,oBAAoB,eAAe,qCAAqC;AACpG,SAAS,kBAAkB;AAC3B,SAAS,iCAAiC;AAE1C,MAAM,YAAY,WAAW,gBAAgB;AAG7C,MAAM,qBAAqB,KAAK,KAAK;AAOrC,SAAS,qBAAqB,QAKkD;AAC9E,SAAO;AAAA,IACL,KAAK,OAAO;AAAA,IACZ,OAAO,OAAO,SAAS;AAAA,IACvB,OAAO,OAAO,SAAS;AAAA,IACvB,WAAW,OAAO,aAAa;AAAA,EACjC;AACF;AAMA,MAAM,OAAoB;AAAA,EACxB,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS,CAAC,MAAM;AAAA,EAChB,OAAO;AACT;AAMO,MAAM,eAA2C;AAAA,EACtD,IAAI;AAAA,EAEJ,MAAM;AAAA,IACJ,GAAG;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS;AAAA,IACP,SAAS;AAAA,IACT,qBAAqB,CAAC,UAAU,MAAM,QAAQ,4BAA4B,EAAE;AAAA,IAC5E,gBAAgB,OAAO,EAAE,KAAK,GAAG,MAAM;AACrC,YAAM,YAAY,wBAAwB,GAAG;AAC7C,gBAAU,KAAK,yBAAyB,EAAE,IAAI,UAAU,CAAC;AAGzD,YAAM,kBAAkB;AAAA,QACtB;AAAA,QACA,IAAI;AAAA,QACJ,MAAM;AAAA,QACN;AAAA,MACF,CAAC;AAGD,UAAI;AACF,cAAM,kBAAkB,EAAE,KAAK,YAAY,IAAI,UAAU,CAAC;AAC1D,kBAAU,KAAK,wBAAwB,EAAE,GAAG,CAAC;AAAA,MAC/C,SAAS,KAAK;AACZ,kBAAU,KAAK,qBAAqB,EAAE,IAAI,OAAO,OAAO,GAAG,EAAE,CAAC;AAAA,MAChE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc;AAAA,IACZ,WAAW,CAAC,UAAU,OAAO;AAAA,IAC7B,OAAO;AAAA,IACP,WAAW;AAAA,IACX,SAAS;AAAA,IACT,OAAO;AAAA,IACP,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa;AAAA,IACX,kBAAkB,MAAM;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ;AAAA,IACN,mBAAmB;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,EAAE,gBAAgB,CAAC,iBAAiB,EAAE;AAAA;AAAA;AAAA;AAAA,EAM9C,cAAc;AAAA,IACZ,QAAQ;AAAA,EACV;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ;AAAA,IACN,gBAAgB,CAAC,QAAQ,kBAAkB,GAAG;AAAA,IAC9C,gBAAgB,CAAC,KAAK,cAAc,eAAe,KAAK,SAAS;AAAA,IACjE,kBAAkB,CAAC,QAAQ,wBAAwB,GAAG;AAAA,IAEtD,mBAAmB,CAAC,EAAE,KAAK,WAAW,QAAQ,MAAM;AAClD,aAAO,kBAAkB,KAAK,WAAW,OAAO;AAAA,IAClD;AAAA,IAEA,eAAe,CAAC,EAAE,KAAK,UAAU,MAAM;AACrC,aAAO,cAAc,KAAK,SAAS;AAAA,IACrC;AAAA,IAEA,cAAc,CAAC,YAAY,QAAQ;AAAA,IAEnC,iBAAiB,CAAC,aAAa;AAAA,MAC7B,WAAW,QAAQ;AAAA,MACnB,SAAS,QAAQ;AAAA,MACjB,YAAY,QAAQ;AAAA,MACpB,MAAM,QAAQ;AAAA,MACd,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,IACjB;AAAA,IAEA,kBAAkB,CAAC,EAAE,KAAK,UAAU,MAAM;AACxC,YAAM,UAAU,eAAe,KAAK,SAAS;AAC7C,cAAQ,QAAQ,QAAQ,aAAa,CAAC,GAAG,IAAI,CAAC,UAAU,OAAO,KAAK,CAAC;AAAA,IACvE;AAAA,IAEA,iBAAiB,CAAC,EAAE,UAAU,MAC5B,UACG,IAAI,CAAC,UAAU,OAAO,KAAK,EAAE,KAAK,CAAC,EACnC,OAAO,OAAO,EACd,IAAI,CAAC,UAAU,MAAM,YAAY,CAAC;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU;AAAA,IACR,iBAAiB,CAAC,EAAE,KAAK,UAAU,MACjC,8BAA8B,EAAE,KAAK,WAAW,aAAa,mBAAmB,CAAC;AAAA,EACrF;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO;AAAA,IACL,kBAAkB,MAAM;AAAA,IACxB,oBAAoB,CAAC,EAAE,KAAK,UAAU,MAAM;AAC1C,aAAO,mBAAmB,KAAK,WAAW,EAAE,SAAS,KAAK,CAAC;AAAA,IAC7D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY;AAAA;AAAA;AAAA;AAAA,EAMZ,WAAW;AAAA,IACT,iBAAiB,CAAC,QAAQ,sBAAsB,GAAG,KAAK;AAAA,IACxD,gBAAgB;AAAA,MACd,aAAa;AAAA,MACb,MAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW;AAAA,IACT,MAAM,YAAY;AAAA,IAClB,WAAW,OAAO,MAAM,yBAAyB,qBAAqB,CAAC,CAAC;AAAA,IACxE,YAAY,OAAO,MAAM,0BAA0B,qBAAqB,CAAC,CAAC;AAAA,IAC1E,eAAe,OAAO,MAAM,6BAA6B,qBAAqB,CAAC,CAAC;AAAA,IAChF,gBAAgB,OAAO,MAAM,8BAA8B,qBAAqB,CAAC,CAAC;AAAA,EACpF;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU;AAAA;AAAA;AAAA;AAAA,EAMV,WAAW;AAAA,IACT,kBAAkB,CAAC,EAAE,SAAS,cAAc,OAAoC;AAAA,MAC9E,kBAAkB,sBAAsB,QAAQ,MAAM,EAAE,KAAK;AAAA,MAC7D,iBAAiB,QAAQ,mBAAmB,OAAO,OAAO,QAAQ,eAAe,IAAI;AAAA,MACrF,kBAAkB,QAAQ;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS;AAAA;AAAA;AAAA;AAAA,EAMT,QAAQ;AAAA,IACN,gBAAgB;AAAA,MACd,WAAW;AAAA,MACX,SAAS;AAAA,MACT,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,MAAM;AAAA,IACR;AAAA,IACA,qBAAqB,CAAC,EAAE,SAAS,OAAO;AAAA,MACtC,YAAY,SAAS,cAAc;AAAA,MACnC,SAAS,SAAS,WAAW;AAAA,MAC7B,aAAa,SAAS,eAAe;AAAA,MACrC,YAAY,SAAS,cAAc;AAAA,MACnC,WAAW,SAAS,aAAa;AAAA,MACjC,MAAM,SAAS,QAAQ;AAAA,MACvB,OAAO,SAAS;AAAA,MAChB,aAAa,SAAS,eAAe;AAAA,IACvC;AAAA,IACA,cAAc,OAAO,EAAE,QAAQ,MAAM;AACnC,aAAO,MAAM,WAAW,YAAY,OAAO,EAAE,MAAM,EAAE,UAAU,mBAAmB,CAAC;AAAA,IACrF;AAAA,IACA,sBAAsB,CAAC,EAAE,SAAS,SAAS,MAAM,OAAO;AAAA,MACtD,WAAW,QAAQ;AAAA,MACnB,SAAS,QAAQ;AAAA,MACjB,YAAY,QAAQ;AAAA,MACpB,MAAM,QAAQ;AAAA,MACd,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,MACf,SAAS,SAAS,WAAW;AAAA,MAC7B,aAAa,SAAS,eAAe;AAAA,MACrC,YAAY,SAAS,cAAc;AAAA,MACnC,WAAW,SAAS,aAAa;AAAA,MACjC,MAAM,SAAS,QAAQ;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS;AAAA,IACP,cAAc,OAAO,QAAQ;AAC3B,YAAM,EAAE,sBAAsB,IAAI,MAAM,OAAO,cAAc;AAC7D,YAAM,UAAU,eAAe,IAAI,KAAK,IAAI,SAAS;AACrD,YAAM,OAAO,QAAQ,QAAQ,eAAe;AAC5C,UAAI,UAAU,EAAE,WAAW,IAAI,WAAW,KAAK,CAAC;AAChD,UAAI,KAAK,KAAK,mBAAmB,IAAI,SAAS,YAAY,QAAQ,QAAQ,kBAAkB,WAAW,GAAG;AAC1G,aAAO,sBAAsB;AAAA,QAC3B,QAAQ,IAAI;AAAA,QACZ,SAAS,IAAI;AAAA,QACb,aAAa,IAAI;AAAA,QACjB,WAAW,IAAI;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,IAEA,aAAa,OAAO,QAAQ;AAC1B,UAAI,KAAK,KAAK,mBAAmB,IAAI,SAAS,GAAG;AACjD,iBAAW,WAAW,IAAI,SAAS;AACnC,UAAI,KAAK,KAAK,kBAAkB,IAAI,SAAS,GAAG;AAAA,IAClD;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,14 @@
1
+ import { LarkClient } from "../core/lark-client";
2
+ async function probeFeishu(credentials) {
3
+ if (!credentials?.appId || !credentials?.appSecret) {
4
+ return {
5
+ ok: false,
6
+ error: "missing credentials (appId, appSecret)"
7
+ };
8
+ }
9
+ return LarkClient.fromCredentials(credentials).probe();
10
+ }
11
+ export {
12
+ probeFeishu
13
+ };
14
+ //# sourceMappingURL=probe.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/channel/probe.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport type { FeishuProbeResult } from './types';\nimport { LarkClient, type LarkClientCredentials } from '../core/lark-client';\n\n/**\n * Probe the Feishu bot connection by calling the bot/v3/info API.\n *\n * Returns a result indicating whether the bot is reachable and its\n * basic identity (name, open_id). Used by onboarding and status\n * checks to verify credentials before committing them to config.\n */\nexport async function probeFeishu(credentials?: LarkClientCredentials): Promise<FeishuProbeResult> {\n if (!credentials?.appId || !credentials?.appSecret) {\n return {\n ok: false,\n error: 'missing credentials (appId, appSecret)',\n };\n }\n\n return LarkClient.fromCredentials(credentials).probe();\n}\n"],
5
+ "mappings": "AAMA,SAAS,kBAA8C;AASvD,eAAsB,YAAY,aAAiE;AACjG,MAAI,CAAC,aAAa,SAAS,CAAC,aAAa,WAAW;AAClD,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO,WAAW,gBAAgB,WAAW,EAAE,MAAM;AACvD;",
6
+ "names": []
7
+ }
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map