@colinlu50/openclaw-lark-stream 2026.3.17

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 (361) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +141 -0
  3. package/README.zh.md +70 -0
  4. package/bin/openclaw-lark.js +48 -0
  5. package/index.d.ts +36 -0
  6. package/index.js +118 -0
  7. package/openclaw.plugin.json +10 -0
  8. package/package.json +66 -0
  9. package/skills/feishu-bitable/SKILL.md +248 -0
  10. package/skills/feishu-bitable/references/examples.md +813 -0
  11. package/skills/feishu-bitable/references/field-properties.md +763 -0
  12. package/skills/feishu-bitable/references/record-values.md +911 -0
  13. package/skills/feishu-calendar/SKILL.md +244 -0
  14. package/skills/feishu-channel-rules/SKILL.md +24 -0
  15. package/skills/feishu-channel-rules/references/markdown-syntax.md +138 -0
  16. package/skills/feishu-create-doc/SKILL.md +719 -0
  17. package/skills/feishu-fetch-doc/SKILL.md +93 -0
  18. package/skills/feishu-im-read/SKILL.md +163 -0
  19. package/skills/feishu-task/SKILL.md +293 -0
  20. package/skills/feishu-troubleshoot/SKILL.md +70 -0
  21. package/skills/feishu-update-doc/SKILL.md +285 -0
  22. package/src/card/builder.d.ts +106 -0
  23. package/src/card/builder.js +443 -0
  24. package/src/card/cardkit.d.ts +90 -0
  25. package/src/card/cardkit.js +181 -0
  26. package/src/card/flush-controller.d.ts +45 -0
  27. package/src/card/flush-controller.js +134 -0
  28. package/src/card/image-resolver.d.ts +45 -0
  29. package/src/card/image-resolver.js +112 -0
  30. package/src/card/markdown-style.d.ts +16 -0
  31. package/src/card/markdown-style.js +97 -0
  32. package/src/card/reply-dispatcher-types.d.ts +120 -0
  33. package/src/card/reply-dispatcher-types.js +57 -0
  34. package/src/card/reply-dispatcher.d.ts +15 -0
  35. package/src/card/reply-dispatcher.js +299 -0
  36. package/src/card/reply-mode.d.ts +38 -0
  37. package/src/card/reply-mode.js +65 -0
  38. package/src/card/streaming-card-controller.d.ts +101 -0
  39. package/src/card/streaming-card-controller.js +810 -0
  40. package/src/card/unavailable-guard.d.ts +35 -0
  41. package/src/card/unavailable-guard.js +83 -0
  42. package/src/channel/abort-detect.d.ts +34 -0
  43. package/src/channel/abort-detect.js +124 -0
  44. package/src/channel/chat-queue.d.ts +41 -0
  45. package/src/channel/chat-queue.js +58 -0
  46. package/src/channel/config-adapter.d.ts +23 -0
  47. package/src/channel/config-adapter.js +101 -0
  48. package/src/channel/directory.d.ts +57 -0
  49. package/src/channel/directory.js +191 -0
  50. package/src/channel/event-handlers.d.ts +15 -0
  51. package/src/channel/event-handlers.js +221 -0
  52. package/src/channel/monitor.d.ts +17 -0
  53. package/src/channel/monitor.js +129 -0
  54. package/src/channel/onboarding-config.d.ts +17 -0
  55. package/src/channel/onboarding-config.js +88 -0
  56. package/src/channel/onboarding-migrate.d.ts +25 -0
  57. package/src/channel/onboarding-migrate.js +67 -0
  58. package/src/channel/onboarding.d.ts +12 -0
  59. package/src/channel/onboarding.js +296 -0
  60. package/src/channel/plugin.d.ts +13 -0
  61. package/src/channel/plugin.js +278 -0
  62. package/src/channel/probe.d.ts +14 -0
  63. package/src/channel/probe.js +21 -0
  64. package/src/channel/types.d.ts +36 -0
  65. package/src/channel/types.js +7 -0
  66. package/src/commands/auth.d.ts +21 -0
  67. package/src/commands/auth.js +161 -0
  68. package/src/commands/diagnose.d.ts +69 -0
  69. package/src/commands/diagnose.js +807 -0
  70. package/src/commands/doctor.d.ts +26 -0
  71. package/src/commands/doctor.js +584 -0
  72. package/src/commands/index.d.ts +25 -0
  73. package/src/commands/index.js +212 -0
  74. package/src/commands/locale.d.ts +7 -0
  75. package/src/commands/locale.js +7 -0
  76. package/src/core/accounts.d.ts +37 -0
  77. package/src/core/accounts.js +163 -0
  78. package/src/core/agent-config.d.ts +100 -0
  79. package/src/core/agent-config.js +139 -0
  80. package/src/core/api-error.d.ts +48 -0
  81. package/src/core/api-error.js +112 -0
  82. package/src/core/app-owner-fallback.d.ts +21 -0
  83. package/src/core/app-owner-fallback.js +38 -0
  84. package/src/core/app-scope-checker.d.ts +87 -0
  85. package/src/core/app-scope-checker.js +190 -0
  86. package/src/core/auth-errors.d.ts +144 -0
  87. package/src/core/auth-errors.js +154 -0
  88. package/src/core/chat-info-cache.d.ts +57 -0
  89. package/src/core/chat-info-cache.js +152 -0
  90. package/src/core/config-schema.d.ts +448 -0
  91. package/src/core/config-schema.js +200 -0
  92. package/src/core/device-flow.d.ts +77 -0
  93. package/src/core/device-flow.js +212 -0
  94. package/src/core/domains.d.ts +18 -0
  95. package/src/core/domains.js +28 -0
  96. package/src/core/feishu-fetch.d.ts +18 -0
  97. package/src/core/feishu-fetch.js +25 -0
  98. package/src/core/footer-config.d.ts +24 -0
  99. package/src/core/footer-config.js +39 -0
  100. package/src/core/lark-client.d.ts +108 -0
  101. package/src/core/lark-client.js +353 -0
  102. package/src/core/lark-logger.d.ts +23 -0
  103. package/src/core/lark-logger.js +154 -0
  104. package/src/core/lark-ticket.d.ts +29 -0
  105. package/src/core/lark-ticket.js +35 -0
  106. package/src/core/message-unavailable.d.ts +53 -0
  107. package/src/core/message-unavailable.js +130 -0
  108. package/src/core/owner-policy.d.ts +31 -0
  109. package/src/core/owner-policy.js +52 -0
  110. package/src/core/permission-url.d.ts +22 -0
  111. package/src/core/permission-url.js +72 -0
  112. package/src/core/raw-request.d.ts +27 -0
  113. package/src/core/raw-request.js +62 -0
  114. package/src/core/scope-manager.d.ts +168 -0
  115. package/src/core/scope-manager.js +213 -0
  116. package/src/core/security-check.d.ts +72 -0
  117. package/src/core/security-check.js +174 -0
  118. package/src/core/shutdown-hooks.d.ts +22 -0
  119. package/src/core/shutdown-hooks.js +56 -0
  120. package/src/core/targets.d.ts +60 -0
  121. package/src/core/targets.js +164 -0
  122. package/src/core/token-store.d.ts +54 -0
  123. package/src/core/token-store.js +314 -0
  124. package/src/core/tool-client.d.ts +176 -0
  125. package/src/core/tool-client.js +380 -0
  126. package/src/core/tool-scopes.d.ts +153 -0
  127. package/src/core/tool-scopes.js +326 -0
  128. package/src/core/tools-config.d.ts +55 -0
  129. package/src/core/tools-config.js +137 -0
  130. package/src/core/types.d.ts +87 -0
  131. package/src/core/types.js +11 -0
  132. package/src/core/uat-client.d.ts +46 -0
  133. package/src/core/uat-client.js +187 -0
  134. package/src/core/version.d.ts +25 -0
  135. package/src/core/version.js +49 -0
  136. package/src/messaging/converters/audio.d.ts +8 -0
  137. package/src/messaging/converters/audio.js +21 -0
  138. package/src/messaging/converters/calendar.d.ts +13 -0
  139. package/src/messaging/converters/calendar.js +50 -0
  140. package/src/messaging/converters/content-converter.d.ts +41 -0
  141. package/src/messaging/converters/content-converter.js +106 -0
  142. package/src/messaging/converters/file.d.ts +8 -0
  143. package/src/messaging/converters/file.js +20 -0
  144. package/src/messaging/converters/folder.d.ts +8 -0
  145. package/src/messaging/converters/folder.js +20 -0
  146. package/src/messaging/converters/hongbao.d.ts +8 -0
  147. package/src/messaging/converters/hongbao.js +16 -0
  148. package/src/messaging/converters/image.d.ts +8 -0
  149. package/src/messaging/converters/image.js +18 -0
  150. package/src/messaging/converters/index.d.ts +8 -0
  151. package/src/messaging/converters/index.js +50 -0
  152. package/src/messaging/converters/interactive/card-converter.d.ts +76 -0
  153. package/src/messaging/converters/interactive/card-converter.js +1173 -0
  154. package/src/messaging/converters/interactive/card-utils.d.ts +9 -0
  155. package/src/messaging/converters/interactive/card-utils.js +42 -0
  156. package/src/messaging/converters/interactive/index.d.ts +8 -0
  157. package/src/messaging/converters/interactive/index.js +21 -0
  158. package/src/messaging/converters/interactive/legacy.d.ts +11 -0
  159. package/src/messaging/converters/interactive/legacy.js +57 -0
  160. package/src/messaging/converters/interactive/types.d.ts +23 -0
  161. package/src/messaging/converters/interactive/types.js +24 -0
  162. package/src/messaging/converters/location.d.ts +8 -0
  163. package/src/messaging/converters/location.js +19 -0
  164. package/src/messaging/converters/merge-forward.d.ts +32 -0
  165. package/src/messaging/converters/merge-forward.js +225 -0
  166. package/src/messaging/converters/post.d.ts +11 -0
  167. package/src/messaging/converters/post.js +135 -0
  168. package/src/messaging/converters/share.d.ts +9 -0
  169. package/src/messaging/converters/share.js +23 -0
  170. package/src/messaging/converters/sticker.d.ts +8 -0
  171. package/src/messaging/converters/sticker.js +18 -0
  172. package/src/messaging/converters/system.d.ts +12 -0
  173. package/src/messaging/converters/system.js +32 -0
  174. package/src/messaging/converters/text.d.ts +8 -0
  175. package/src/messaging/converters/text.js +14 -0
  176. package/src/messaging/converters/todo.d.ts +8 -0
  177. package/src/messaging/converters/todo.js +41 -0
  178. package/src/messaging/converters/types.d.ts +107 -0
  179. package/src/messaging/converters/types.js +7 -0
  180. package/src/messaging/converters/unknown.d.ts +8 -0
  181. package/src/messaging/converters/unknown.js +16 -0
  182. package/src/messaging/converters/utils.d.ts +22 -0
  183. package/src/messaging/converters/utils.js +51 -0
  184. package/src/messaging/converters/video-chat.d.ts +8 -0
  185. package/src/messaging/converters/video-chat.js +23 -0
  186. package/src/messaging/converters/video.d.ts +8 -0
  187. package/src/messaging/converters/video.js +32 -0
  188. package/src/messaging/converters/vote.d.ts +8 -0
  189. package/src/messaging/converters/vote.js +24 -0
  190. package/src/messaging/inbound/dedup.d.ts +59 -0
  191. package/src/messaging/inbound/dedup.js +116 -0
  192. package/src/messaging/inbound/dispatch-builders.d.ts +84 -0
  193. package/src/messaging/inbound/dispatch-builders.js +152 -0
  194. package/src/messaging/inbound/dispatch-commands.d.ts +27 -0
  195. package/src/messaging/inbound/dispatch-commands.js +112 -0
  196. package/src/messaging/inbound/dispatch-context.d.ts +67 -0
  197. package/src/messaging/inbound/dispatch-context.js +136 -0
  198. package/src/messaging/inbound/dispatch.d.ts +47 -0
  199. package/src/messaging/inbound/dispatch.js +264 -0
  200. package/src/messaging/inbound/enrich.d.ts +102 -0
  201. package/src/messaging/inbound/enrich.js +227 -0
  202. package/src/messaging/inbound/gate-effects.d.ts +23 -0
  203. package/src/messaging/inbound/gate-effects.js +43 -0
  204. package/src/messaging/inbound/gate.d.ts +60 -0
  205. package/src/messaging/inbound/gate.js +233 -0
  206. package/src/messaging/inbound/handler.d.ts +35 -0
  207. package/src/messaging/inbound/handler.js +173 -0
  208. package/src/messaging/inbound/media-resolver.d.ts +32 -0
  209. package/src/messaging/inbound/media-resolver.js +87 -0
  210. package/src/messaging/inbound/mention.d.ts +39 -0
  211. package/src/messaging/inbound/mention.js +81 -0
  212. package/src/messaging/inbound/parse-io.d.ts +50 -0
  213. package/src/messaging/inbound/parse-io.js +81 -0
  214. package/src/messaging/inbound/parse.d.ts +28 -0
  215. package/src/messaging/inbound/parse.js +106 -0
  216. package/src/messaging/inbound/permission.d.ts +17 -0
  217. package/src/messaging/inbound/permission.js +40 -0
  218. package/src/messaging/inbound/policy.d.ts +94 -0
  219. package/src/messaging/inbound/policy.js +160 -0
  220. package/src/messaging/inbound/reaction-handler.d.ts +61 -0
  221. package/src/messaging/inbound/reaction-handler.js +221 -0
  222. package/src/messaging/inbound/user-name-cache.d.ts +82 -0
  223. package/src/messaging/inbound/user-name-cache.js +241 -0
  224. package/src/messaging/outbound/actions.d.ts +16 -0
  225. package/src/messaging/outbound/actions.js +309 -0
  226. package/src/messaging/outbound/chat-manage.d.ts +64 -0
  227. package/src/messaging/outbound/chat-manage.js +111 -0
  228. package/src/messaging/outbound/deliver.d.ts +155 -0
  229. package/src/messaging/outbound/deliver.js +298 -0
  230. package/src/messaging/outbound/fetch.d.ts +12 -0
  231. package/src/messaging/outbound/fetch.js +12 -0
  232. package/src/messaging/outbound/forward.d.ts +26 -0
  233. package/src/messaging/outbound/forward.js +48 -0
  234. package/src/messaging/outbound/media-url-utils.d.ts +29 -0
  235. package/src/messaging/outbound/media-url-utils.js +130 -0
  236. package/src/messaging/outbound/media.d.ts +260 -0
  237. package/src/messaging/outbound/media.js +758 -0
  238. package/src/messaging/outbound/outbound.d.ts +89 -0
  239. package/src/messaging/outbound/outbound.js +121 -0
  240. package/src/messaging/outbound/reactions.d.ts +124 -0
  241. package/src/messaging/outbound/reactions.js +378 -0
  242. package/src/messaging/outbound/send.d.ts +152 -0
  243. package/src/messaging/outbound/send.js +355 -0
  244. package/src/messaging/outbound/typing.d.ts +71 -0
  245. package/src/messaging/outbound/typing.js +179 -0
  246. package/src/messaging/shared/message-lookup.d.ts +54 -0
  247. package/src/messaging/shared/message-lookup.js +117 -0
  248. package/src/messaging/types.d.ts +176 -0
  249. package/src/messaging/types.js +10 -0
  250. package/src/tools/auto-auth.d.ts +56 -0
  251. package/src/tools/auto-auth.js +919 -0
  252. package/src/tools/helpers.d.ts +260 -0
  253. package/src/tools/helpers.js +364 -0
  254. package/src/tools/mcp/doc/create.d.ts +12 -0
  255. package/src/tools/mcp/doc/create.js +44 -0
  256. package/src/tools/mcp/doc/fetch.d.ts +12 -0
  257. package/src/tools/mcp/doc/fetch.js +36 -0
  258. package/src/tools/mcp/doc/index.d.ts +12 -0
  259. package/src/tools/mcp/doc/index.js +41 -0
  260. package/src/tools/mcp/doc/update.d.ts +12 -0
  261. package/src/tools/mcp/doc/update.js +61 -0
  262. package/src/tools/mcp/shared.d.ts +59 -0
  263. package/src/tools/mcp/shared.js +226 -0
  264. package/src/tools/oapi/bitable/app-table-field.d.ts +16 -0
  265. package/src/tools/oapi/bitable/app-table-field.js +222 -0
  266. package/src/tools/oapi/bitable/app-table-record.d.ts +20 -0
  267. package/src/tools/oapi/bitable/app-table-record.js +436 -0
  268. package/src/tools/oapi/bitable/app-table-view.d.ts +17 -0
  269. package/src/tools/oapi/bitable/app-table-view.js +195 -0
  270. package/src/tools/oapi/bitable/app-table.d.ts +19 -0
  271. package/src/tools/oapi/bitable/app-table.js +247 -0
  272. package/src/tools/oapi/bitable/app.d.ts +18 -0
  273. package/src/tools/oapi/bitable/app.js +186 -0
  274. package/src/tools/oapi/bitable/index.d.ts +9 -0
  275. package/src/tools/oapi/bitable/index.js +9 -0
  276. package/src/tools/oapi/calendar/calendar.d.ts +15 -0
  277. package/src/tools/oapi/calendar/calendar.js +122 -0
  278. package/src/tools/oapi/calendar/event-attendee.d.ts +16 -0
  279. package/src/tools/oapi/calendar/event-attendee.js +263 -0
  280. package/src/tools/oapi/calendar/event.d.ts +16 -0
  281. package/src/tools/oapi/calendar/event.js +709 -0
  282. package/src/tools/oapi/calendar/freebusy.d.ts +13 -0
  283. package/src/tools/oapi/calendar/freebusy.js +111 -0
  284. package/src/tools/oapi/calendar/index.d.ts +8 -0
  285. package/src/tools/oapi/calendar/index.js +8 -0
  286. package/src/tools/oapi/chat/chat.d.ts +16 -0
  287. package/src/tools/oapi/chat/chat.js +124 -0
  288. package/src/tools/oapi/chat/index.d.ts +10 -0
  289. package/src/tools/oapi/chat/index.js +15 -0
  290. package/src/tools/oapi/chat/members.d.ts +11 -0
  291. package/src/tools/oapi/chat/members.js +81 -0
  292. package/src/tools/oapi/common/get-user.d.ts +12 -0
  293. package/src/tools/oapi/common/get-user.js +106 -0
  294. package/src/tools/oapi/common/index.d.ts +6 -0
  295. package/src/tools/oapi/common/index.js +6 -0
  296. package/src/tools/oapi/common/search-user.d.ts +11 -0
  297. package/src/tools/oapi/common/search-user.js +73 -0
  298. package/src/tools/oapi/drive/doc-comments.d.ts +15 -0
  299. package/src/tools/oapi/drive/doc-comments.js +279 -0
  300. package/src/tools/oapi/drive/doc-media.d.ts +19 -0
  301. package/src/tools/oapi/drive/doc-media.js +335 -0
  302. package/src/tools/oapi/drive/file.d.ts +19 -0
  303. package/src/tools/oapi/drive/file.js +483 -0
  304. package/src/tools/oapi/drive/index.d.ts +12 -0
  305. package/src/tools/oapi/drive/index.js +36 -0
  306. package/src/tools/oapi/helpers.d.ts +182 -0
  307. package/src/tools/oapi/helpers.js +354 -0
  308. package/src/tools/oapi/im/format-messages.d.ts +50 -0
  309. package/src/tools/oapi/im/format-messages.js +165 -0
  310. package/src/tools/oapi/im/index.d.ts +10 -0
  311. package/src/tools/oapi/im/index.js +17 -0
  312. package/src/tools/oapi/im/message-read.d.ts +13 -0
  313. package/src/tools/oapi/im/message-read.js +411 -0
  314. package/src/tools/oapi/im/message.d.ts +16 -0
  315. package/src/tools/oapi/im/message.js +149 -0
  316. package/src/tools/oapi/im/resource.d.ts +13 -0
  317. package/src/tools/oapi/im/resource.js +150 -0
  318. package/src/tools/oapi/im/time-utils.d.ts +46 -0
  319. package/src/tools/oapi/im/time-utils.js +201 -0
  320. package/src/tools/oapi/im/user-name-uat.d.ts +26 -0
  321. package/src/tools/oapi/im/user-name-uat.js +140 -0
  322. package/src/tools/oapi/index.d.ts +11 -0
  323. package/src/tools/oapi/index.js +58 -0
  324. package/src/tools/oapi/sdk-types.d.ts +96 -0
  325. package/src/tools/oapi/sdk-types.js +12 -0
  326. package/src/tools/oapi/search/doc-search.d.ts +13 -0
  327. package/src/tools/oapi/search/doc-search.js +191 -0
  328. package/src/tools/oapi/search/index.d.ts +12 -0
  329. package/src/tools/oapi/search/index.js +33 -0
  330. package/src/tools/oapi/sheets/index.d.ts +12 -0
  331. package/src/tools/oapi/sheets/index.js +31 -0
  332. package/src/tools/oapi/sheets/sheet.d.ts +16 -0
  333. package/src/tools/oapi/sheets/sheet.js +652 -0
  334. package/src/tools/oapi/task/comment.d.ts +15 -0
  335. package/src/tools/oapi/task/comment.js +140 -0
  336. package/src/tools/oapi/task/index.d.ts +8 -0
  337. package/src/tools/oapi/task/index.js +8 -0
  338. package/src/tools/oapi/task/subtask.d.ts +14 -0
  339. package/src/tools/oapi/task/subtask.js +162 -0
  340. package/src/tools/oapi/task/task.d.ts +16 -0
  341. package/src/tools/oapi/task/task.js +344 -0
  342. package/src/tools/oapi/task/tasklist.d.ts +21 -0
  343. package/src/tools/oapi/task/tasklist.js +321 -0
  344. package/src/tools/oapi/wiki/index.d.ts +12 -0
  345. package/src/tools/oapi/wiki/index.js +34 -0
  346. package/src/tools/oapi/wiki/space-node.d.ts +17 -0
  347. package/src/tools/oapi/wiki/space-node.js +230 -0
  348. package/src/tools/oapi/wiki/space.d.ts +15 -0
  349. package/src/tools/oapi/wiki/space.js +130 -0
  350. package/src/tools/oauth-batch-auth.d.ts +11 -0
  351. package/src/tools/oauth-batch-auth.js +142 -0
  352. package/src/tools/oauth-cards.d.ts +39 -0
  353. package/src/tools/oauth-cards.js +315 -0
  354. package/src/tools/oauth.d.ts +47 -0
  355. package/src/tools/oauth.js +620 -0
  356. package/src/tools/onboarding-auth.d.ts +27 -0
  357. package/src/tools/onboarding-auth.js +130 -0
  358. package/src/tools/tat/im/index.d.ts +15 -0
  359. package/src/tools/tat/im/index.js +18 -0
  360. package/src/tools/tat/im/resource.d.ts +15 -0
  361. package/src/tools/tat/im/resource.js +157 -0
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Onboarding 预授权模块。
6
+ *
7
+ * 配对后自动发起 OAuth Device Flow,引导应用 owner 完成用户授权。
8
+ * 仅当配对用户 === 应用 owner 时触发。
9
+ *
10
+ * 飞书限制:单次 OAuth 最多 50 个 scope。
11
+ * 超过 50 个时自动分批处理,每批授权完成后自动发起下一批(链式触发)。
12
+ */
13
+ import type { ClawdbotConfig } from 'openclaw/plugin-sdk';
14
+ /**
15
+ * 配对后触发 onboarding OAuth 授权。
16
+ *
17
+ * 流程:
18
+ * 1. 检查 userOpenId === 应用 owner,不匹配则静默跳过
19
+ * 2. 读取 onboarding-scopes.json 中的 user scope 列表
20
+ * 3. 分批处理(每批最多 50 个),第一批直接发起 OAuth Device Flow
21
+ * 4. 每批授权完成后通过 onAuthComplete 回调自动发起下一批
22
+ */
23
+ export declare function triggerOnboarding(params: {
24
+ cfg: ClawdbotConfig;
25
+ userOpenId: string;
26
+ accountId: string;
27
+ }): Promise<void>;
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Onboarding 预授权模块。
6
+ *
7
+ * 配对后自动发起 OAuth Device Flow,引导应用 owner 完成用户授权。
8
+ * 仅当配对用户 === 应用 owner 时触发。
9
+ *
10
+ * 飞书限制:单次 OAuth 最多 50 个 scope。
11
+ * 超过 50 个时自动分批处理,每批授权完成后自动发起下一批(链式触发)。
12
+ */
13
+ import { getLarkAccount } from '../core/accounts';
14
+ import { LarkClient } from '../core/lark-client';
15
+ import { getAppGrantedScopes } from '../core/app-scope-checker';
16
+ import { getAppOwnerFallback } from '../core/app-owner-fallback';
17
+ import { executeAuthorize } from './oauth';
18
+ import { larkLogger } from '../core/lark-logger';
19
+ import { filterSensitiveScopes } from '../core/tool-scopes';
20
+ const log = larkLogger('tools/onboarding-auth');
21
+ // ---------------------------------------------------------------------------
22
+ // Constants
23
+ // ---------------------------------------------------------------------------
24
+ const MAX_SCOPES_PER_BATCH = 100;
25
+ // ---------------------------------------------------------------------------
26
+ // Trigger onboarding
27
+ // ---------------------------------------------------------------------------
28
+ /**
29
+ * 配对后触发 onboarding OAuth 授权。
30
+ *
31
+ * 流程:
32
+ * 1. 检查 userOpenId === 应用 owner,不匹配则静默跳过
33
+ * 2. 读取 onboarding-scopes.json 中的 user scope 列表
34
+ * 3. 分批处理(每批最多 50 个),第一批直接发起 OAuth Device Flow
35
+ * 4. 每批授权完成后通过 onAuthComplete 回调自动发起下一批
36
+ */
37
+ export async function triggerOnboarding(params) {
38
+ const { cfg, userOpenId, accountId } = params;
39
+ const acct = getLarkAccount(cfg, accountId);
40
+ if (!acct.configured) {
41
+ log.warn(`account ${accountId} not configured, skipping`);
42
+ return;
43
+ }
44
+ const sdk = LarkClient.fromAccount(acct).sdk;
45
+ const { appId } = acct;
46
+ // 1. 检查 userOpenId === 应用 owner(统一走 getAppOwnerFallback)
47
+ const ownerOpenId = await getAppOwnerFallback(acct, sdk);
48
+ if (!ownerOpenId) {
49
+ log.info(`app ${appId} has no owner info, skipping`);
50
+ return;
51
+ }
52
+ if (userOpenId !== ownerOpenId) {
53
+ log.info(`user ${userOpenId} is not app owner (${ownerOpenId}), skipping`);
54
+ return;
55
+ }
56
+ log.info(`user ${userOpenId} is app owner, starting OAuth`);
57
+ // 3. 动态获取应用已开通的 user scope 列表
58
+ let allUserScopes;
59
+ try {
60
+ allUserScopes = await getAppGrantedScopes(sdk, appId, 'user');
61
+ }
62
+ catch (err) {
63
+ log.warn(`failed to get app granted scopes: ${err}`);
64
+ return;
65
+ }
66
+ // 过滤掉敏感 scope
67
+ allUserScopes = filterSensitiveScopes(allUserScopes);
68
+ if (allUserScopes.length === 0) {
69
+ log.info('no user scopes configured, skipping');
70
+ return;
71
+ }
72
+ // 4. 分批
73
+ const batches = [];
74
+ for (let i = 0; i < allUserScopes.length; i += MAX_SCOPES_PER_BATCH) {
75
+ batches.push(allUserScopes.slice(i, i + MAX_SCOPES_PER_BATCH));
76
+ }
77
+ log.info(`${allUserScopes.length} user scopes, ${batches.length} batch(es)`);
78
+ // 5. 链式发起授权(第一批同步发起,后续批次由 onAuthComplete 回调触发)
79
+ const startBatch = async (batchIndex) => {
80
+ if (batchIndex >= batches.length) {
81
+ log.info('all batches completed');
82
+ return;
83
+ }
84
+ const batch = batches[batchIndex];
85
+ const scope = batch.join(' ');
86
+ let batchInfo = '';
87
+ if (batches.length > 1) {
88
+ batchInfo =
89
+ `\n\n📋 授权进度:第 ${batchIndex + 1}/${batches.length} 批` +
90
+ `(本批 ${batch.length} 个权限,共 ${allUserScopes.length} 个)`;
91
+ if (batchIndex < batches.length - 1) {
92
+ batchInfo += `\n授权完成后将自动发起下一批。`;
93
+ }
94
+ else {
95
+ batchInfo += `\n这是最后一批,授权完成后即可使用所有功能。`;
96
+ }
97
+ }
98
+ const ticket = {
99
+ messageId: `onboarding:${Date.now()}`,
100
+ chatId: userOpenId,
101
+ accountId,
102
+ startTime: Date.now(),
103
+ senderOpenId: userOpenId,
104
+ chatType: 'p2p',
105
+ };
106
+ log.info(`starting batch ${batchIndex + 1}/${batches.length}, scopes=${batch.length}`);
107
+ try {
108
+ await executeAuthorize({
109
+ account: acct,
110
+ senderOpenId: userOpenId,
111
+ scope,
112
+ isBatchAuth: true,
113
+ totalAppScopes: allUserScopes.length,
114
+ alreadyGranted: batchIndex * MAX_SCOPES_PER_BATCH,
115
+ batchInfo,
116
+ skipSyntheticMessage: true,
117
+ cfg,
118
+ ticket,
119
+ onAuthComplete: async () => {
120
+ log.info(`batch ${batchIndex + 1}/${batches.length} auth completed`);
121
+ await startBatch(batchIndex + 1);
122
+ },
123
+ });
124
+ }
125
+ catch (err) {
126
+ log.error(`batch ${batchIndex + 1} failed: ${err}`);
127
+ }
128
+ };
129
+ await startBatch(0);
130
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * IM 工具集
6
+ * 统一导出所有即时通讯相关工具的注册函数
7
+ */
8
+ import type { OpenClawPluginApi } from 'openclaw/plugin-sdk';
9
+ /**
10
+ * 注册所有 IM 工具
11
+ *
12
+ * Note: feishu_im_message_reaction 和 feishu_im_message_recall 已移除,
13
+ * 其功能由 ChannelMessageActionAdapter (actions.ts) 的 react/delete action 统一覆盖。
14
+ */
15
+ export declare function registerFeishuImTools(api: OpenClawPluginApi): void;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * IM 工具集
6
+ * 统一导出所有即时通讯相关工具的注册函数
7
+ */
8
+ import { registerFeishuImBotImageTool } from './resource';
9
+ /**
10
+ * 注册所有 IM 工具
11
+ *
12
+ * Note: feishu_im_message_reaction 和 feishu_im_message_recall 已移除,
13
+ * 其功能由 ChannelMessageActionAdapter (actions.ts) 的 react/delete action 统一覆盖。
14
+ */
15
+ export function registerFeishuImTools(api) {
16
+ registerFeishuImBotImageTool(api);
17
+ api.logger.info?.('feishu_im: Registered feishu_im_bot_image');
18
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * feishu_im_bot_image 工具
6
+ *
7
+ * 以机器人身份下载飞书 IM 消息中的图片/文件资源到本地。
8
+ *
9
+ * 飞书 API:
10
+ * - 下载资源: GET /open-apis/im/v1/messages/:message_id/resources/:file_key
11
+ * 权限: im:resource
12
+ * 凭证: tenant_access_token
13
+ */
14
+ import type { OpenClawPluginApi } from 'openclaw/plugin-sdk';
15
+ export declare function registerFeishuImBotImageTool(api: OpenClawPluginApi): void;
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * feishu_im_bot_image 工具
6
+ *
7
+ * 以机器人身份下载飞书 IM 消息中的图片/文件资源到本地。
8
+ *
9
+ * 飞书 API:
10
+ * - 下载资源: GET /open-apis/im/v1/messages/:message_id/resources/:file_key
11
+ * 权限: im:resource
12
+ * 凭证: tenant_access_token
13
+ */
14
+ import { buildRandomTempFilePath } from 'openclaw/plugin-sdk';
15
+ import { Type } from '@sinclair/typebox';
16
+ import { json, createToolContext, formatLarkError, registerTool, StringEnum } from '../../oapi/helpers';
17
+ import * as fsPromises from 'node:fs/promises';
18
+ import * as path from 'node:path';
19
+ // ===========================================================================
20
+ // Shared constants
21
+ // ===========================================================================
22
+ /** MIME type → 文件扩展名(下载时使用) */
23
+ const MIME_TO_EXT = {
24
+ 'image/png': '.png',
25
+ 'image/jpeg': '.jpg',
26
+ 'image/jpg': '.jpg',
27
+ 'image/gif': '.gif',
28
+ 'image/webp': '.webp',
29
+ 'image/svg+xml': '.svg',
30
+ 'image/bmp': '.bmp',
31
+ 'image/tiff': '.tiff',
32
+ 'video/mp4': '.mp4',
33
+ 'video/mpeg': '.mpeg',
34
+ 'video/quicktime': '.mov',
35
+ 'video/x-msvideo': '.avi',
36
+ 'video/webm': '.webm',
37
+ 'audio/mpeg': '.mp3',
38
+ 'audio/wav': '.wav',
39
+ 'audio/ogg': '.ogg',
40
+ 'audio/mp4': '.m4a',
41
+ 'application/pdf': '.pdf',
42
+ 'application/msword': '.doc',
43
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx',
44
+ 'application/vnd.ms-excel': '.xls',
45
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': '.xlsx',
46
+ 'application/vnd.ms-powerpoint': '.ppt',
47
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation': '.pptx',
48
+ 'application/zip': '.zip',
49
+ 'application/x-rar-compressed': '.rar',
50
+ 'text/plain': '.txt',
51
+ 'application/json': '.json',
52
+ };
53
+ // ===========================================================================
54
+ // Shared helpers
55
+ // ===========================================================================
56
+ /**
57
+ * 从二进制响应中提取 Buffer、Content-Type。
58
+ * SDK 的二进制响应可能有 getReadableStream(),也可能直接是 Buffer 等格式。
59
+ */
60
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
+ async function extractBuffer(res) {
62
+ let chunks;
63
+ if (typeof res.getReadableStream === 'function') {
64
+ const stream = res.getReadableStream();
65
+ chunks = [];
66
+ for await (const chunk of stream) {
67
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
68
+ }
69
+ }
70
+ else if (Buffer.isBuffer(res)) {
71
+ chunks = [res];
72
+ }
73
+ else if (Buffer.isBuffer(res?.data)) {
74
+ chunks = [res.data];
75
+ }
76
+ else {
77
+ throw new Error('无法从响应中提取二进制数据');
78
+ }
79
+ const buffer = Buffer.concat(chunks);
80
+ const contentType = res.headers?.['content-type'] ?? '';
81
+ return { buffer, contentType };
82
+ }
83
+ /**
84
+ * 将 buffer 保存到临时文件,返回路径。
85
+ */
86
+ async function saveToTempFile(buffer, contentType, prefix) {
87
+ const mimeType = contentType ? contentType.split(';')[0].trim() : '';
88
+ const mimeExt = mimeType ? MIME_TO_EXT[mimeType] : undefined;
89
+ const filePath = buildRandomTempFilePath({
90
+ prefix,
91
+ extension: mimeExt,
92
+ });
93
+ await fsPromises.mkdir(path.dirname(filePath), { recursive: true });
94
+ await fsPromises.writeFile(filePath, buffer);
95
+ return filePath;
96
+ }
97
+ // ===========================================================================
98
+ // Download tool — feishu_im_bot_image
99
+ // ===========================================================================
100
+ const FeishuImBotImageSchema = Type.Object({
101
+ message_id: Type.String({
102
+ description: '消息 ID(om_xxx 格式),引用消息可从上下文中的 [message_id=om_xxx] 提取',
103
+ }),
104
+ file_key: Type.String({
105
+ description: '资源 Key,图片消息的 image_key(img_xxx)或文件消息的 file_key(file_xxx)',
106
+ }),
107
+ type: StringEnum(['image', 'file'], {
108
+ description: '资源类型:image(图片消息中的图片)、file(文件/音频/视频消息中的文件)',
109
+ }),
110
+ });
111
+ export function registerFeishuImBotImageTool(api) {
112
+ if (!api.config)
113
+ return;
114
+ const { getClient, log } = createToolContext(api, 'feishu_im_bot_image');
115
+ registerTool(api, {
116
+ name: 'feishu_im_bot_image',
117
+ label: 'Feishu: IM Bot Image Download',
118
+ description: '【以机器人身份】下载飞书 IM 消息中的图片或文件资源到本地。' +
119
+ '\n\n适用场景:用户直接发送给机器人的消息、用户引用的消息、机器人收到的群聊消息中的图片/文件。' +
120
+ '即当前对话上下文中出现的 message_id 和 image_key/file_key,应使用本工具下载。' +
121
+ '\n引用消息的 message_id 可从上下文中的 [message_id=om_xxx] 提取,无需向用户询问。' +
122
+ '\n\n文件自动保存到 /tmp/openclaw/ 下,返回值中的 saved_path 为实际保存路径。',
123
+ parameters: FeishuImBotImageSchema,
124
+ async execute(_toolCallId, params) {
125
+ const p = params;
126
+ try {
127
+ const client = getClient();
128
+ log.info(`download: message_id="${p.message_id}", file_key="${p.file_key}", type="${p.type}"`);
129
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
130
+ const res = await client.im.messageResource.get({
131
+ path: {
132
+ message_id: p.message_id,
133
+ file_key: p.file_key,
134
+ },
135
+ params: { type: p.type },
136
+ });
137
+ const { buffer, contentType } = await extractBuffer(res);
138
+ log.info(`download: ${buffer.length} bytes, content-type=${contentType}`);
139
+ const savedPath = await saveToTempFile(buffer, contentType, 'bot-resource');
140
+ log.info(`download: saved to ${savedPath}`);
141
+ return json({
142
+ message_id: p.message_id,
143
+ file_key: p.file_key,
144
+ type: p.type,
145
+ size_bytes: buffer.length,
146
+ content_type: contentType,
147
+ saved_path: savedPath,
148
+ });
149
+ }
150
+ catch (err) {
151
+ log.error(`Error: ${formatLarkError(err)}`);
152
+ return json({ error: formatLarkError(err) });
153
+ }
154
+ },
155
+ }, { name: 'feishu_im_bot_image' });
156
+ api.logger.info?.('feishu_im_bot_image: Registered feishu_im_bot_image tool');
157
+ }