@larksuite/openclaw-lark 2025.7.15-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (426) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +76 -0
  3. package/bin/openclaw-lark.js +39 -0
  4. package/index.d.ts +36 -0
  5. package/index.js +188 -0
  6. package/openclaw.plugin.json +64 -0
  7. package/package.json +63 -0
  8. package/secret-contract-api.d.ts +15 -0
  9. package/secret-contract-api.js +78 -0
  10. package/skills/feishu-bitable/SKILL.md +248 -0
  11. package/skills/feishu-bitable/references/examples.md +813 -0
  12. package/skills/feishu-bitable/references/field-properties.md +763 -0
  13. package/skills/feishu-bitable/references/record-values.md +911 -0
  14. package/skills/feishu-calendar/SKILL.md +242 -0
  15. package/skills/feishu-channel-rules/SKILL.md +18 -0
  16. package/skills/feishu-channel-rules/references/markdown-syntax.md +138 -0
  17. package/skills/feishu-create-doc/SKILL.md +719 -0
  18. package/skills/feishu-fetch-doc/SKILL.md +93 -0
  19. package/skills/feishu-im-read/SKILL.md +163 -0
  20. package/skills/feishu-task/SKILL.md +340 -0
  21. package/skills/feishu-troubleshoot/SKILL.md +70 -0
  22. package/skills/feishu-update-doc/SKILL.md +285 -0
  23. package/src/card/builder.d.ts +152 -0
  24. package/src/card/builder.js +794 -0
  25. package/src/card/card-error.d.ts +91 -0
  26. package/src/card/card-error.js +206 -0
  27. package/src/card/cardkit.d.ts +90 -0
  28. package/src/card/cardkit.js +203 -0
  29. package/src/card/flush-controller.d.ts +45 -0
  30. package/src/card/flush-controller.js +138 -0
  31. package/src/card/image-resolver.d.ts +45 -0
  32. package/src/card/image-resolver.js +116 -0
  33. package/src/card/markdown-style.d.ts +16 -0
  34. package/src/card/markdown-style.js +106 -0
  35. package/src/card/reasoning-utils.d.ts +14 -0
  36. package/src/card/reasoning-utils.js +64 -0
  37. package/src/card/reply-dispatcher-types.d.ts +132 -0
  38. package/src/card/reply-dispatcher-types.js +61 -0
  39. package/src/card/reply-dispatcher.d.ts +15 -0
  40. package/src/card/reply-dispatcher.js +447 -0
  41. package/src/card/reply-mode.d.ts +41 -0
  42. package/src/card/reply-mode.js +70 -0
  43. package/src/card/streaming-card-controller.d.ts +118 -0
  44. package/src/card/streaming-card-controller.js +1045 -0
  45. package/src/card/tool-use-config.d.ts +26 -0
  46. package/src/card/tool-use-config.js +76 -0
  47. package/src/card/tool-use-display.d.ts +37 -0
  48. package/src/card/tool-use-display.js +476 -0
  49. package/src/card/tool-use-trace-store.d.ts +51 -0
  50. package/src/card/tool-use-trace-store.js +271 -0
  51. package/src/card/unavailable-guard.d.ts +35 -0
  52. package/src/card/unavailable-guard.js +87 -0
  53. package/src/channel/abort-detect.d.ts +47 -0
  54. package/src/channel/abort-detect.js +219 -0
  55. package/src/channel/chat-queue.d.ts +41 -0
  56. package/src/channel/chat-queue.js +68 -0
  57. package/src/channel/config-adapter.d.ts +23 -0
  58. package/src/channel/config-adapter.js +107 -0
  59. package/src/channel/directory.d.ts +57 -0
  60. package/src/channel/directory.js +197 -0
  61. package/src/channel/event-handlers.d.ts +17 -0
  62. package/src/channel/event-handlers.js +380 -0
  63. package/src/channel/interactive-dispatch.d.ts +59 -0
  64. package/src/channel/interactive-dispatch.js +195 -0
  65. package/src/channel/monitor.d.ts +17 -0
  66. package/src/channel/monitor.js +140 -0
  67. package/src/channel/onboarding-config.d.ts +18 -0
  68. package/src/channel/onboarding-config.js +96 -0
  69. package/src/channel/onboarding-migrate.d.ts +25 -0
  70. package/src/channel/onboarding-migrate.js +70 -0
  71. package/src/channel/onboarding.d.ts +12 -0
  72. package/src/channel/onboarding.js +300 -0
  73. package/src/channel/plugin.d.ts +13 -0
  74. package/src/channel/plugin.js +310 -0
  75. package/src/channel/probe.d.ts +14 -0
  76. package/src/channel/probe.js +24 -0
  77. package/src/channel/types.d.ts +37 -0
  78. package/src/channel/types.js +8 -0
  79. package/src/commands/auth.d.ts +21 -0
  80. package/src/commands/auth.js +165 -0
  81. package/src/commands/diagnose.d.ts +69 -0
  82. package/src/commands/diagnose.js +848 -0
  83. package/src/commands/doctor.d.ts +27 -0
  84. package/src/commands/doctor.js +588 -0
  85. package/src/commands/index.d.ts +25 -0
  86. package/src/commands/index.js +219 -0
  87. package/src/commands/locale.d.ts +7 -0
  88. package/src/commands/locale.js +8 -0
  89. package/src/core/accounts.d.ts +51 -0
  90. package/src/core/accounts.js +219 -0
  91. package/src/core/agent-config.d.ts +100 -0
  92. package/src/core/agent-config.js +148 -0
  93. package/src/core/api-error.d.ts +48 -0
  94. package/src/core/api-error.js +117 -0
  95. package/src/core/app-owner-fallback.d.ts +22 -0
  96. package/src/core/app-owner-fallback.js +39 -0
  97. package/src/core/app-scope-checker.d.ts +87 -0
  98. package/src/core/app-scope-checker.js +198 -0
  99. package/src/core/auth-errors.d.ts +144 -0
  100. package/src/core/auth-errors.js +160 -0
  101. package/src/core/card-action-operator.d.ts +33 -0
  102. package/src/core/card-action-operator.js +30 -0
  103. package/src/core/chat-info-cache.d.ts +67 -0
  104. package/src/core/chat-info-cache.js +165 -0
  105. package/src/core/comment-target.d.ts +65 -0
  106. package/src/core/comment-target.js +100 -0
  107. package/src/core/config-schema.d.ts +490 -0
  108. package/src/core/config-schema.js +223 -0
  109. package/src/core/device-flow.d.ts +77 -0
  110. package/src/core/device-flow.js +217 -0
  111. package/src/core/domains.d.ts +18 -0
  112. package/src/core/domains.js +34 -0
  113. package/src/core/feishu-fetch.d.ts +18 -0
  114. package/src/core/feishu-fetch.js +28 -0
  115. package/src/core/footer-config.d.ts +24 -0
  116. package/src/core/footer-config.js +51 -0
  117. package/src/core/lark-client.d.ts +125 -0
  118. package/src/core/lark-client.js +468 -0
  119. package/src/core/lark-logger.d.ts +23 -0
  120. package/src/core/lark-logger.js +160 -0
  121. package/src/core/lark-ticket.d.ts +29 -0
  122. package/src/core/lark-ticket.js +40 -0
  123. package/src/core/message-unavailable.d.ts +53 -0
  124. package/src/core/message-unavailable.js +142 -0
  125. package/src/core/owner-policy.d.ts +32 -0
  126. package/src/core/owner-policy.js +55 -0
  127. package/src/core/permission-url.d.ts +22 -0
  128. package/src/core/permission-url.js +76 -0
  129. package/src/core/raw-request.d.ts +27 -0
  130. package/src/core/raw-request.js +90 -0
  131. package/src/core/runtime-store.d.ts +13 -0
  132. package/src/core/runtime-store.js +29 -0
  133. package/src/core/scope-manager.d.ts +168 -0
  134. package/src/core/scope-manager.js +224 -0
  135. package/src/core/sdk-compat.d.ts +20 -0
  136. package/src/core/sdk-compat.js +28 -0
  137. package/src/core/security-check.d.ts +72 -0
  138. package/src/core/security-check.js +184 -0
  139. package/src/core/shutdown-hooks.d.ts +22 -0
  140. package/src/core/shutdown-hooks.js +61 -0
  141. package/src/core/synthetic-target.d.ts +33 -0
  142. package/src/core/synthetic-target.js +40 -0
  143. package/src/core/targets.d.ts +60 -0
  144. package/src/core/targets.js +173 -0
  145. package/src/core/token-store.d.ts +54 -0
  146. package/src/core/token-store.js +326 -0
  147. package/src/core/tool-client.d.ts +176 -0
  148. package/src/core/tool-client.js +426 -0
  149. package/src/core/tool-scopes.d.ts +156 -0
  150. package/src/core/tool-scopes.js +344 -0
  151. package/src/core/tools-config.d.ts +55 -0
  152. package/src/core/tools-config.js +143 -0
  153. package/src/core/types.d.ts +91 -0
  154. package/src/core/types.js +12 -0
  155. package/src/core/uat-client.d.ts +46 -0
  156. package/src/core/uat-client.js +192 -0
  157. package/src/core/version.d.ts +31 -0
  158. package/src/core/version.js +69 -0
  159. package/src/messaging/converters/audio.d.ts +8 -0
  160. package/src/messaging/converters/audio.js +24 -0
  161. package/src/messaging/converters/calendar.d.ts +13 -0
  162. package/src/messaging/converters/calendar.js +56 -0
  163. package/src/messaging/converters/content-converter-helpers.d.ts +30 -0
  164. package/src/messaging/converters/content-converter-helpers.js +82 -0
  165. package/src/messaging/converters/content-converter.d.ts +24 -0
  166. package/src/messaging/converters/content-converter.js +40 -0
  167. package/src/messaging/converters/file.d.ts +8 -0
  168. package/src/messaging/converters/file.js +24 -0
  169. package/src/messaging/converters/folder.d.ts +8 -0
  170. package/src/messaging/converters/folder.js +24 -0
  171. package/src/messaging/converters/hongbao.d.ts +8 -0
  172. package/src/messaging/converters/hongbao.js +20 -0
  173. package/src/messaging/converters/image.d.ts +8 -0
  174. package/src/messaging/converters/image.js +22 -0
  175. package/src/messaging/converters/index.d.ts +8 -0
  176. package/src/messaging/converters/index.js +53 -0
  177. package/src/messaging/converters/interactive/card-converter.d.ts +76 -0
  178. package/src/messaging/converters/interactive/card-converter.js +1177 -0
  179. package/src/messaging/converters/interactive/card-utils.d.ts +9 -0
  180. package/src/messaging/converters/interactive/card-utils.js +47 -0
  181. package/src/messaging/converters/interactive/index.d.ts +8 -0
  182. package/src/messaging/converters/interactive/index.js +25 -0
  183. package/src/messaging/converters/interactive/legacy.d.ts +11 -0
  184. package/src/messaging/converters/interactive/legacy.js +60 -0
  185. package/src/messaging/converters/interactive/types.d.ts +23 -0
  186. package/src/messaging/converters/interactive/types.js +27 -0
  187. package/src/messaging/converters/location.d.ts +8 -0
  188. package/src/messaging/converters/location.js +23 -0
  189. package/src/messaging/converters/merge-forward.d.ts +32 -0
  190. package/src/messaging/converters/merge-forward.js +235 -0
  191. package/src/messaging/converters/post.d.ts +11 -0
  192. package/src/messaging/converters/post.js +235 -0
  193. package/src/messaging/converters/share.d.ts +9 -0
  194. package/src/messaging/converters/share.js +28 -0
  195. package/src/messaging/converters/sticker.d.ts +8 -0
  196. package/src/messaging/converters/sticker.js +22 -0
  197. package/src/messaging/converters/system.d.ts +12 -0
  198. package/src/messaging/converters/system.js +36 -0
  199. package/src/messaging/converters/text.d.ts +8 -0
  200. package/src/messaging/converters/text.js +18 -0
  201. package/src/messaging/converters/todo.d.ts +8 -0
  202. package/src/messaging/converters/todo.js +45 -0
  203. package/src/messaging/converters/types.d.ts +114 -0
  204. package/src/messaging/converters/types.js +8 -0
  205. package/src/messaging/converters/unknown.d.ts +8 -0
  206. package/src/messaging/converters/unknown.js +20 -0
  207. package/src/messaging/converters/utils.d.ts +22 -0
  208. package/src/messaging/converters/utils.js +57 -0
  209. package/src/messaging/converters/video-chat.d.ts +8 -0
  210. package/src/messaging/converters/video-chat.js +31 -0
  211. package/src/messaging/converters/video.d.ts +8 -0
  212. package/src/messaging/converters/video.js +35 -0
  213. package/src/messaging/converters/vote.d.ts +8 -0
  214. package/src/messaging/converters/vote.js +28 -0
  215. package/src/messaging/inbound/bot-content.d.ts +84 -0
  216. package/src/messaging/inbound/bot-content.js +117 -0
  217. package/src/messaging/inbound/bot-loop-guard.d.ts +48 -0
  218. package/src/messaging/inbound/bot-loop-guard.js +89 -0
  219. package/src/messaging/inbound/comment-context.d.ts +82 -0
  220. package/src/messaging/inbound/comment-context.js +353 -0
  221. package/src/messaging/inbound/comment-handler.d.ts +30 -0
  222. package/src/messaging/inbound/comment-handler.js +269 -0
  223. package/src/messaging/inbound/dedup.d.ts +59 -0
  224. package/src/messaging/inbound/dedup.js +121 -0
  225. package/src/messaging/inbound/dispatch-builders.d.ts +104 -0
  226. package/src/messaging/inbound/dispatch-builders.js +241 -0
  227. package/src/messaging/inbound/dispatch-commands.d.ts +22 -0
  228. package/src/messaging/inbound/dispatch-commands.js +131 -0
  229. package/src/messaging/inbound/dispatch-context.d.ts +67 -0
  230. package/src/messaging/inbound/dispatch-context.js +153 -0
  231. package/src/messaging/inbound/dispatch.d.ts +50 -0
  232. package/src/messaging/inbound/dispatch.js +477 -0
  233. package/src/messaging/inbound/enrich.d.ts +102 -0
  234. package/src/messaging/inbound/enrich.js +236 -0
  235. package/src/messaging/inbound/gate-effects.d.ts +23 -0
  236. package/src/messaging/inbound/gate-effects.js +46 -0
  237. package/src/messaging/inbound/gate.d.ts +91 -0
  238. package/src/messaging/inbound/gate.js +342 -0
  239. package/src/messaging/inbound/handler-registry.d.ts +25 -0
  240. package/src/messaging/inbound/handler-registry.js +23 -0
  241. package/src/messaging/inbound/handler.d.ts +37 -0
  242. package/src/messaging/inbound/handler.js +286 -0
  243. package/src/messaging/inbound/media-resolver.d.ts +32 -0
  244. package/src/messaging/inbound/media-resolver.js +91 -0
  245. package/src/messaging/inbound/mention-registry.d.ts +59 -0
  246. package/src/messaging/inbound/mention-registry.js +115 -0
  247. package/src/messaging/inbound/mention.d.ts +48 -0
  248. package/src/messaging/inbound/mention.js +102 -0
  249. package/src/messaging/inbound/parse-io.d.ts +50 -0
  250. package/src/messaging/inbound/parse-io.js +86 -0
  251. package/src/messaging/inbound/parse.d.ts +28 -0
  252. package/src/messaging/inbound/parse.js +128 -0
  253. package/src/messaging/inbound/permission.d.ts +17 -0
  254. package/src/messaging/inbound/permission.js +44 -0
  255. package/src/messaging/inbound/policy.d.ts +95 -0
  256. package/src/messaging/inbound/policy.js +168 -0
  257. package/src/messaging/inbound/reaction-handler.d.ts +62 -0
  258. package/src/messaging/inbound/reaction-handler.js +259 -0
  259. package/src/messaging/inbound/sentinel-store.d.ts +37 -0
  260. package/src/messaging/inbound/sentinel-store.js +98 -0
  261. package/src/messaging/inbound/synthetic-message.d.ts +26 -0
  262. package/src/messaging/inbound/synthetic-message.js +59 -0
  263. package/src/messaging/inbound/user-name-cache-store.d.ts +62 -0
  264. package/src/messaging/inbound/user-name-cache-store.js +236 -0
  265. package/src/messaging/inbound/user-name-cache.d.ts +78 -0
  266. package/src/messaging/inbound/user-name-cache.js +306 -0
  267. package/src/messaging/inbound/vc-meeting-invited-handler.d.ts +20 -0
  268. package/src/messaging/inbound/vc-meeting-invited-handler.js +236 -0
  269. package/src/messaging/inbound/vc-sender.d.ts +41 -0
  270. package/src/messaging/inbound/vc-sender.js +53 -0
  271. package/src/messaging/outbound/actions.d.ts +16 -0
  272. package/src/messaging/outbound/actions.js +329 -0
  273. package/src/messaging/outbound/bot-peer-context.d.ts +42 -0
  274. package/src/messaging/outbound/bot-peer-context.js +40 -0
  275. package/src/messaging/outbound/chat-manage.d.ts +64 -0
  276. package/src/messaging/outbound/chat-manage.js +117 -0
  277. package/src/messaging/outbound/deliver.d.ts +186 -0
  278. package/src/messaging/outbound/deliver.js +410 -0
  279. package/src/messaging/outbound/fetch.d.ts +12 -0
  280. package/src/messaging/outbound/fetch.js +17 -0
  281. package/src/messaging/outbound/forward.d.ts +26 -0
  282. package/src/messaging/outbound/forward.js +51 -0
  283. package/src/messaging/outbound/media-url-utils.d.ts +29 -0
  284. package/src/messaging/outbound/media-url-utils.js +172 -0
  285. package/src/messaging/outbound/media.d.ts +260 -0
  286. package/src/messaging/outbound/media.js +865 -0
  287. package/src/messaging/outbound/normalize-mentions.d.ts +50 -0
  288. package/src/messaging/outbound/normalize-mentions.js +166 -0
  289. package/src/messaging/outbound/outbound-mention.d.ts +41 -0
  290. package/src/messaging/outbound/outbound-mention.js +112 -0
  291. package/src/messaging/outbound/outbound.d.ts +79 -0
  292. package/src/messaging/outbound/outbound.js +195 -0
  293. package/src/messaging/outbound/reactions.d.ts +124 -0
  294. package/src/messaging/outbound/reactions.js +384 -0
  295. package/src/messaging/outbound/send.d.ts +153 -0
  296. package/src/messaging/outbound/send.js +417 -0
  297. package/src/messaging/outbound/typing.d.ts +60 -0
  298. package/src/messaging/outbound/typing.js +139 -0
  299. package/src/messaging/shared/message-lookup.d.ts +54 -0
  300. package/src/messaging/shared/message-lookup.js +120 -0
  301. package/src/messaging/types.d.ts +316 -0
  302. package/src/messaging/types.js +11 -0
  303. package/src/tools/ask-user-question.d.ts +32 -0
  304. package/src/tools/ask-user-question.js +922 -0
  305. package/src/tools/auto-auth.d.ts +57 -0
  306. package/src/tools/auto-auth.js +904 -0
  307. package/src/tools/helpers.d.ts +264 -0
  308. package/src/tools/helpers.js +389 -0
  309. package/src/tools/mcp/doc/create.d.ts +12 -0
  310. package/src/tools/mcp/doc/create.js +47 -0
  311. package/src/tools/mcp/doc/fetch.d.ts +12 -0
  312. package/src/tools/mcp/doc/fetch.js +39 -0
  313. package/src/tools/mcp/doc/index.d.ts +12 -0
  314. package/src/tools/mcp/doc/index.js +50 -0
  315. package/src/tools/mcp/doc/update.d.ts +12 -0
  316. package/src/tools/mcp/doc/update.js +64 -0
  317. package/src/tools/mcp/shared.d.ts +59 -0
  318. package/src/tools/mcp/shared.js +239 -0
  319. package/src/tools/oapi/bitable/app-table-field.d.ts +16 -0
  320. package/src/tools/oapi/bitable/app-table-field.js +225 -0
  321. package/src/tools/oapi/bitable/app-table-record.d.ts +20 -0
  322. package/src/tools/oapi/bitable/app-table-record.js +439 -0
  323. package/src/tools/oapi/bitable/app-table-view.d.ts +16 -0
  324. package/src/tools/oapi/bitable/app-table-view.js +172 -0
  325. package/src/tools/oapi/bitable/app-table.d.ts +17 -0
  326. package/src/tools/oapi/bitable/app-table.js +195 -0
  327. package/src/tools/oapi/bitable/app.d.ts +18 -0
  328. package/src/tools/oapi/bitable/app.js +189 -0
  329. package/src/tools/oapi/bitable/index.d.ts +9 -0
  330. package/src/tools/oapi/bitable/index.js +17 -0
  331. package/src/tools/oapi/calendar/calendar.d.ts +15 -0
  332. package/src/tools/oapi/calendar/calendar.js +125 -0
  333. package/src/tools/oapi/calendar/event-attendee.d.ts +14 -0
  334. package/src/tools/oapi/calendar/event-attendee.js +161 -0
  335. package/src/tools/oapi/calendar/event.d.ts +16 -0
  336. package/src/tools/oapi/calendar/event.js +712 -0
  337. package/src/tools/oapi/calendar/freebusy.d.ts +13 -0
  338. package/src/tools/oapi/calendar/freebusy.js +114 -0
  339. package/src/tools/oapi/calendar/index.d.ts +8 -0
  340. package/src/tools/oapi/calendar/index.js +15 -0
  341. package/src/tools/oapi/chat/chat.d.ts +16 -0
  342. package/src/tools/oapi/chat/chat.js +127 -0
  343. package/src/tools/oapi/chat/index.d.ts +10 -0
  344. package/src/tools/oapi/chat/index.js +23 -0
  345. package/src/tools/oapi/chat/members.d.ts +11 -0
  346. package/src/tools/oapi/chat/members.js +84 -0
  347. package/src/tools/oapi/common/get-user.d.ts +12 -0
  348. package/src/tools/oapi/common/get-user.js +109 -0
  349. package/src/tools/oapi/common/index.d.ts +6 -0
  350. package/src/tools/oapi/common/index.js +11 -0
  351. package/src/tools/oapi/common/search-user.d.ts +11 -0
  352. package/src/tools/oapi/common/search-user.js +76 -0
  353. package/src/tools/oapi/drive/doc-comments.d.ts +15 -0
  354. package/src/tools/oapi/drive/doc-comments.js +351 -0
  355. package/src/tools/oapi/drive/doc-media.d.ts +19 -0
  356. package/src/tools/oapi/drive/doc-media.js +371 -0
  357. package/src/tools/oapi/drive/file.d.ts +19 -0
  358. package/src/tools/oapi/drive/file.js +519 -0
  359. package/src/tools/oapi/drive/index.d.ts +12 -0
  360. package/src/tools/oapi/drive/index.js +45 -0
  361. package/src/tools/oapi/helpers.d.ts +183 -0
  362. package/src/tools/oapi/helpers.js +385 -0
  363. package/src/tools/oapi/im/format-messages.d.ts +50 -0
  364. package/src/tools/oapi/im/format-messages.js +169 -0
  365. package/src/tools/oapi/im/index.d.ts +10 -0
  366. package/src/tools/oapi/im/index.js +25 -0
  367. package/src/tools/oapi/im/message-read.d.ts +13 -0
  368. package/src/tools/oapi/im/message-read.js +419 -0
  369. package/src/tools/oapi/im/message.d.ts +16 -0
  370. package/src/tools/oapi/im/message.js +152 -0
  371. package/src/tools/oapi/im/resource.d.ts +13 -0
  372. package/src/tools/oapi/im/resource.js +186 -0
  373. package/src/tools/oapi/im/time-utils.d.ts +46 -0
  374. package/src/tools/oapi/im/time-utils.js +212 -0
  375. package/src/tools/oapi/im/user-name-uat.d.ts +26 -0
  376. package/src/tools/oapi/im/user-name-uat.js +143 -0
  377. package/src/tools/oapi/index.d.ts +11 -0
  378. package/src/tools/oapi/index.js +64 -0
  379. package/src/tools/oapi/sdk-types.d.ts +96 -0
  380. package/src/tools/oapi/sdk-types.js +13 -0
  381. package/src/tools/oapi/search/doc-search.d.ts +13 -0
  382. package/src/tools/oapi/search/doc-search.js +194 -0
  383. package/src/tools/oapi/search/index.d.ts +12 -0
  384. package/src/tools/oapi/search/index.js +37 -0
  385. package/src/tools/oapi/sheets/index.d.ts +12 -0
  386. package/src/tools/oapi/sheets/index.js +35 -0
  387. package/src/tools/oapi/sheets/sheet.d.ts +16 -0
  388. package/src/tools/oapi/sheets/sheet.js +688 -0
  389. package/src/tools/oapi/task/attachment.d.ts +18 -0
  390. package/src/tools/oapi/task/attachment.js +107 -0
  391. package/src/tools/oapi/task/comment.d.ts +15 -0
  392. package/src/tools/oapi/task/comment.js +149 -0
  393. package/src/tools/oapi/task/index.d.ts +11 -0
  394. package/src/tools/oapi/task/index.js +21 -0
  395. package/src/tools/oapi/task/section.d.ts +17 -0
  396. package/src/tools/oapi/task/section.js +293 -0
  397. package/src/tools/oapi/task/subtask.d.ts +14 -0
  398. package/src/tools/oapi/task/subtask.js +171 -0
  399. package/src/tools/oapi/task/task.d.ts +19 -0
  400. package/src/tools/oapi/task/task.js +512 -0
  401. package/src/tools/oapi/task/task_agent.d.ts +14 -0
  402. package/src/tools/oapi/task/task_agent.js +108 -0
  403. package/src/tools/oapi/task/tasklist.d.ts +19 -0
  404. package/src/tools/oapi/task/tasklist.js +276 -0
  405. package/src/tools/oapi/wiki/index.d.ts +12 -0
  406. package/src/tools/oapi/wiki/index.js +42 -0
  407. package/src/tools/oapi/wiki/space-node.d.ts +17 -0
  408. package/src/tools/oapi/wiki/space-node.js +233 -0
  409. package/src/tools/oapi/wiki/space.d.ts +15 -0
  410. package/src/tools/oapi/wiki/space.js +133 -0
  411. package/src/tools/oauth-batch-auth.d.ts +11 -0
  412. package/src/tools/oauth-batch-auth.js +150 -0
  413. package/src/tools/oauth-cards.d.ts +39 -0
  414. package/src/tools/oauth-cards.js +324 -0
  415. package/src/tools/oauth.d.ts +47 -0
  416. package/src/tools/oauth.js +592 -0
  417. package/src/tools/onboarding-auth.d.ts +27 -0
  418. package/src/tools/onboarding-auth.js +133 -0
  419. package/src/tools/tat/im/index.d.ts +15 -0
  420. package/src/tools/tat/im/index.js +22 -0
  421. package/src/tools/tat/im/resource.d.ts +15 -0
  422. package/src/tools/tat/im/resource.js +192 -0
  423. package/tsdown.config.d.ts +2 -0
  424. package/tsdown.config.js +25 -0
  425. package/vitest.config.d.ts +2 -0
  426. package/vitest.config.js +12 -0
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * feishu-doctor 诊断报告 Markdown 格式化(完全重构版)
6
+ *
7
+ * 直接生成 Markdown 诊断报告,不依赖 diagnose.ts 的任何架构和代码。
8
+ * 按照 doctor_template.md 的格式规范实现。
9
+ */
10
+ import type { OpenClawConfig } from 'openclaw/plugin-sdk';
11
+ export type { FeishuLocale } from './locale';
12
+ import type { FeishuLocale } from './locale';
13
+ /** @deprecated Use FeishuLocale instead */
14
+ export type DoctorLocale = FeishuLocale;
15
+ /**
16
+ * 运行飞书插件诊断,生成 Markdown 格式报告。
17
+ *
18
+ * @param config - OpenClaw 配置
19
+ * @param currentAccountId - 当前发送命令的机器人账号 ID(若有则只诊断该账号)
20
+ * @param locale - 输出语言,默认 zh_cn
21
+ */
22
+ export declare function runFeishuDoctor(config: OpenClawConfig, currentAccountId?: string, locale?: DoctorLocale): Promise<string>;
23
+ /**
24
+ * 运行飞书插件诊断,同时生成中英双语 Markdown 报告。
25
+ * 用于飞书 channel 的多语言 post 发送。
26
+ */
27
+ export declare function runFeishuDoctorI18n(config: OpenClawConfig, currentAccountId?: string): Promise<Record<DoctorLocale, string>>;
@@ -0,0 +1,588 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * feishu-doctor 诊断报告 Markdown 格式化(完全重构版)
7
+ *
8
+ * 直接生成 Markdown 诊断报告,不依赖 diagnose.ts 的任何架构和代码。
9
+ * 按照 doctor_template.md 的格式规范实现。
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.runFeishuDoctor = runFeishuDoctor;
13
+ exports.runFeishuDoctorI18n = runFeishuDoctorI18n;
14
+ const accounts_1 = require("../core/accounts.js");
15
+ const lark_client_1 = require("../core/lark-client.js");
16
+ /**
17
+ * Resolve the global config for cross-account operations.
18
+ *
19
+ * Plugin commands receive an account-scoped config where `channels.feishu`
20
+ * has been replaced with the merged per-account config (the `accounts` map
21
+ * is stripped by `baseConfig()`). Commands that enumerate all accounts
22
+ * need the original global config to see the full `accounts` map.
23
+ */
24
+ function resolveGlobalConfig(config) {
25
+ return lark_client_1.LarkClient.globalConfig ?? config;
26
+ }
27
+ const app_scope_checker_1 = require("../core/app-scope-checker.js");
28
+ const app_owner_fallback_1 = require("../core/app-owner-fallback.js");
29
+ const token_store_1 = require("../core/token-store.js");
30
+ const tool_scopes_1 = require("../core/tool-scopes.js");
31
+ const probe_1 = require("../channel/probe.js");
32
+ const tool_client_1 = require("../core/tool-client.js");
33
+ const version_1 = require("../core/version.js");
34
+ const domains_1 = require("../core/domains.js");
35
+ // ---------------------------------------------------------------------------
36
+ // I18n text map
37
+ // ---------------------------------------------------------------------------
38
+ const T = {
39
+ zh_cn: {
40
+ notSet: '(未设置)',
41
+ legacyNotDisabled: '❌ **旧版插件**: 检测到旧版官方插件未禁用\n' +
42
+ '👉 请依次运行命令:\n' +
43
+ '```\n' +
44
+ 'openclaw config set plugins.entries.feishu.enabled false --json\n' +
45
+ 'openclaw gateway restart\n' +
46
+ '```',
47
+ legacyRunCmds: '👉 请依次运行命令:',
48
+ legacyDisabled: '✅ **旧版插件**: 已禁用',
49
+ credentials: '✅ **凭证完整性**',
50
+ accountEnabled: '✅ **账户启用**: 已启用',
51
+ apiOk: '✅ **API 连通性**: 连接成功',
52
+ apiFail: '❌ **API 连通性**: 连接失败',
53
+ apiError: '❌ **API 连通性**: 探测异常',
54
+ toolsOk: '✅ 飞书工具加载暂未发现异常',
55
+ toolsWarnProfile: (profile) => `⚠️ **工具基础允许列表**: 当前为 \`${profile}\`,飞书工具可能无法加载。可以按需修改配置:`,
56
+ toolsDocRef: '📖 参考文档',
57
+ allPermsGranted: (count) => `全部 ${count} 个必需权限已开通`,
58
+ missingPermsPrefix: '缺少',
59
+ missingPermsSuffix: '个必需权限。需应用管理员申请开通',
60
+ cannotQueryPerms: '无法查询应用权限状态。原因:未开通 application:application:self_manage 权限',
61
+ cannotQueryPermsGeneric: '无法查询应用权限状态。',
62
+ suggestCheckPerm: '建议检查 application:application:self_manage 权限',
63
+ adminApply: '需应用管理员申请开通',
64
+ apply: '申请',
65
+ permTableHeader: '| 权限名称 | 应用已开通 | 用户已授权 |',
66
+ authStatusLabel: '**授权状态**',
67
+ userTotal: '共 1 个用户',
68
+ valid: '有效',
69
+ needRefresh: '需刷新',
70
+ expired: '已过期',
71
+ tokenRefreshLabel: '**Token 自动刷新**',
72
+ tokenRefreshOn: '✓ 已开启自动刷新 (1/1 个用户)',
73
+ tokenRefreshOff: '✗ 未开启自动刷新,Token 将在 2 小时后过期',
74
+ noUserAuth: '⚠️ **暂无用户授权**',
75
+ noUserAuthDesc: '尚未有用户通过 OAuth 授权。用户首次使用需以用户身份的功能时,会自动触发授权流程。',
76
+ permCompareLabel: '**权限对照**',
77
+ permInsufficient: '**用户身份权限不足**',
78
+ userCountLabel: '已授权',
79
+ noAuthLabel: '暂无授权',
80
+ appMissingUserPerms: (count) => `💡 应用缺少 ${count} 个用户身份权限。需应用管理员申请开通`,
81
+ permCompareSummary: (appCount, total, userPart) => `应用 **${appCount}/${total}** 已开通,用户 **${userPart}**`,
82
+ userReauth: '💡 用户需要重新授权以获得完整权限,可以向机器人发送消息 "**/feishu auth**"',
83
+ userNeedsOAuth: '💡 用户需要进行 OAuth 授权,可以向机器人发送消息 "**/feishu auth**"',
84
+ userPermFailed: '用户权限检查失败',
85
+ userPermFailedNoSelfManage: '用户权限检查失败:无法查询应用权限。原因:未开通 application:application:self_manage 权限',
86
+ reportTitle: '### 飞书插件诊断',
87
+ pluginVersionLabel: '插件版本',
88
+ diagTimeLabel: '诊断时间',
89
+ noAccounts: '❌ **错误**: 未找到已启用的飞书账户\n\n请在 OpenClaw 配置文件中配置飞书账户并启用。',
90
+ accountNotFoundPrefix: '❌ **错误**: 未找到账户',
91
+ enabledAccountsLabel: '当前已启用的账户',
92
+ toolsCheckPass: '#### ✅ 工具配置检查通过',
93
+ toolsCheckWarn: '#### ⚠️ 工具配置检查异常',
94
+ accountPrefix: '### 账户',
95
+ envCheckPass: '#### ✅ 环境信息检查通过',
96
+ envCheckFail: '#### ❌ 环境信息检查未通过',
97
+ appPermPass: '#### ✅ 应用身份权限检查通过',
98
+ appPermFail: '#### ❌ 应用身份权限检查未通过',
99
+ userPermPass: '#### ✅ 用户身份权限检查通过',
100
+ userPermFail: '#### ❌ 用户身份权限检查未通过',
101
+ },
102
+ en_us: {
103
+ notSet: '(not set)',
104
+ legacyNotDisabled: '❌ **Legacy Plugin**: Legacy official plugin is not disabled\n' +
105
+ '👉 Please run the following commands:\n' +
106
+ '```\n' +
107
+ 'openclaw config set plugins.entries.feishu.enabled false --json\n' +
108
+ 'openclaw gateway restart\n' +
109
+ '```',
110
+ legacyRunCmds: '👉 Please run the following commands:',
111
+ legacyDisabled: '✅ **Legacy Plugin**: Disabled',
112
+ credentials: '✅ **Credentials**',
113
+ accountEnabled: '✅ **Account**: Enabled',
114
+ apiOk: '✅ **API Connectivity**: Connected',
115
+ apiFail: '❌ **API Connectivity**: Connection failed',
116
+ apiError: '❌ **API Connectivity**: Probe error',
117
+ toolsOk: '✅ Feishu tools loading: No issues found',
118
+ toolsWarnProfile: (profile) => `⚠️ **Tool Allowlist**: Currently set to \`${profile}\`. Feishu tools may not load properly. Update configuration as needed:`,
119
+ toolsDocRef: '📖 Documentation',
120
+ allPermsGranted: (count) => `All ${count} required permissions granted`,
121
+ missingPermsPrefix: 'Missing',
122
+ missingPermsSuffix: 'required permissions. Admin needs to apply',
123
+ cannotQueryPerms: 'Unable to query app permissions. Reason: Missing application:application:self_manage permission',
124
+ cannotQueryPermsGeneric: 'Unable to query app permissions.',
125
+ suggestCheckPerm: 'Please check application:application:self_manage permission',
126
+ adminApply: 'Admin needs to apply',
127
+ apply: 'Apply',
128
+ permTableHeader: '| Permission | App Granted | User Authorized |',
129
+ authStatusLabel: '**Auth Status**',
130
+ userTotal: '1 user total',
131
+ valid: 'Valid',
132
+ needRefresh: 'Needs refresh',
133
+ expired: 'Expired',
134
+ tokenRefreshLabel: '**Token Auto-Refresh**',
135
+ tokenRefreshOn: '✓ Auto-refresh enabled (1/1 users)',
136
+ tokenRefreshOff: '✗ Auto-refresh not enabled. Token will expire in 2 hours',
137
+ noUserAuth: '⚠️ **No User Authorization**',
138
+ noUserAuthDesc: 'No user has authorized via OAuth yet. The authorization flow will be triggered automatically when a user first uses a feature requiring user identity.',
139
+ permCompareLabel: '**Permission Comparison**',
140
+ permInsufficient: '**Insufficient User Permissions**',
141
+ userCountLabel: 'authorized',
142
+ noAuthLabel: 'not authorized',
143
+ appMissingUserPerms: (count) => `💡 App is missing ${count} user-identity permissions. Admin needs to apply`,
144
+ permCompareSummary: (appCount, total, userPart) => `App **${appCount}/${total}** granted, User **${userPart}**`,
145
+ userReauth: '💡 User needs to re-authorize for full permissions. Send message to bot: "**/feishu auth**"',
146
+ userNeedsOAuth: '💡 User needs OAuth authorization. Send message to bot: "**/feishu auth**"',
147
+ userPermFailed: 'User permission check failed',
148
+ userPermFailedNoSelfManage: 'User permission check failed: Unable to query app permissions. Reason: Missing application:application:self_manage permission',
149
+ reportTitle: '### Feishu Plugin Diagnostics',
150
+ pluginVersionLabel: 'Plugin version',
151
+ diagTimeLabel: 'Diagnosis time',
152
+ noAccounts: '❌ **Error**: No enabled Feishu accounts found\n\nPlease configure and enable a Feishu account in the OpenClaw configuration.',
153
+ accountNotFoundPrefix: '❌ **Error**: Account not found',
154
+ enabledAccountsLabel: 'Currently enabled accounts',
155
+ toolsCheckPass: '#### ✅ Tool Configuration Check Passed',
156
+ toolsCheckWarn: '#### ⚠️ Tool Configuration Check Warning',
157
+ accountPrefix: '### Account',
158
+ envCheckPass: '#### ✅ Environment Check Passed',
159
+ envCheckFail: '#### ❌ Environment Check Failed',
160
+ appPermPass: '#### ✅ App Permission Check Passed',
161
+ appPermFail: '#### ❌ App Permission Check Failed',
162
+ userPermPass: '#### ✅ User Permission Check Passed',
163
+ userPermFail: '#### ❌ User Permission Check Failed',
164
+ },
165
+ };
166
+ // ---------------------------------------------------------------------------
167
+ // Helpers
168
+ // ---------------------------------------------------------------------------
169
+ /**
170
+ * 格式化时间戳为 "YYYY-MM-DD HH:mm:ss"
171
+ */
172
+ function formatTimestamp(date) {
173
+ return date.toLocaleString('sv-SE', { timeZone: 'Asia/Shanghai' }).replace('T', ' ');
174
+ }
175
+ /**
176
+ * 获取所有工具动作需要的唯一 scope 列表(从 diagnose.ts 复制)
177
+ */
178
+ function getAllToolScopes() {
179
+ const scopesSet = new Set();
180
+ for (const scopes of Object.values(tool_scopes_1.TOOL_SCOPES)) {
181
+ for (const scope of scopes) {
182
+ scopesSet.add(scope);
183
+ }
184
+ }
185
+ return Array.from(scopesSet).sort();
186
+ }
187
+ // ---------------------------------------------------------------------------
188
+ // 基础信息检查
189
+ // ---------------------------------------------------------------------------
190
+ /**
191
+ * 掩码敏感信息(appSecret)
192
+ */
193
+ function maskSecret(secret, locale) {
194
+ if (!secret)
195
+ return T[locale].notSet;
196
+ if (secret.length <= 4)
197
+ return '****';
198
+ return secret.slice(0, 4) + '****';
199
+ }
200
+ /**
201
+ * 检查基础信息和账号状态
202
+ */
203
+ async function checkBasicInfo(account, config, locale) {
204
+ const t = T[locale];
205
+ const lines = [];
206
+ let status = 'pass';
207
+ // 旧版官方插件是否已禁用
208
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
209
+ const feishuEntry = config.plugins?.entries?.feishu;
210
+ if (feishuEntry && feishuEntry.enabled !== false) {
211
+ status = 'fail';
212
+ lines.push(t.legacyNotDisabled);
213
+ }
214
+ else {
215
+ lines.push(t.legacyDisabled);
216
+ }
217
+ lines.push(`${t.credentials}: appId: ${account.appId}, appSecret: ${maskSecret(account.appSecret, locale)}`);
218
+ lines.push(t.accountEnabled);
219
+ // API 连通性
220
+ try {
221
+ const probeResult = await (0, probe_1.probeFeishu)({
222
+ accountId: account.accountId,
223
+ appId: account.appId,
224
+ appSecret: account.appSecret,
225
+ brand: account.brand,
226
+ });
227
+ if (probeResult.ok) {
228
+ lines.push(t.apiOk);
229
+ }
230
+ else {
231
+ status = 'fail';
232
+ lines.push(`${t.apiFail} - ${probeResult.error}`);
233
+ }
234
+ }
235
+ catch (err) {
236
+ status = 'fail';
237
+ lines.push(`${t.apiError} - ${err instanceof Error ? err.message : String(err)}`);
238
+ }
239
+ return {
240
+ status,
241
+ markdown: lines.join('\n'),
242
+ };
243
+ }
244
+ // ---------------------------------------------------------------------------
245
+ // 工具配置检查
246
+ // ---------------------------------------------------------------------------
247
+ const INCOMPLETE_PROFILES = new Set(['minimal', 'coding', 'messaging']);
248
+ function checkToolsProfile(config, locale) {
249
+ const t = T[locale];
250
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
251
+ const tools = config.tools;
252
+ const profile = tools?.profile;
253
+ if (!profile) {
254
+ return {
255
+ status: 'pass',
256
+ markdown: t.toolsOk,
257
+ };
258
+ }
259
+ if (INCOMPLETE_PROFILES.has(profile)) {
260
+ return {
261
+ status: 'warn',
262
+ markdown: `${t.toolsWarnProfile(profile)}\n` +
263
+ '```\n' +
264
+ 'openclaw config set tools.profile "full"\n' +
265
+ 'openclaw gateway restart\n' +
266
+ '```\n' +
267
+ `${t.toolsDocRef}: https://docs.openclaw.ai/zh-CN/tools`,
268
+ };
269
+ }
270
+ // profile === "full" 或其他未知值
271
+ return {
272
+ status: 'pass',
273
+ markdown: t.toolsOk,
274
+ };
275
+ }
276
+ // ---------------------------------------------------------------------------
277
+ // 应用权限检查
278
+ // ---------------------------------------------------------------------------
279
+ /**
280
+ * 检查应用权限状态
281
+ */
282
+ async function checkAppPermissions(account, sdk, locale) {
283
+ const t = T[locale];
284
+ const { appId } = account;
285
+ const openDomain = (0, domains_1.openPlatformDomain)(account.brand);
286
+ try {
287
+ // 获取应用已开通的权限(tenant token)
288
+ const grantedScopes = await (0, app_scope_checker_1.getAppGrantedScopes)(sdk, appId, 'tenant');
289
+ // 计算缺失的必需权限
290
+ const requiredMissing = (0, app_scope_checker_1.missingScopes)(grantedScopes, Array.from(tool_scopes_1.REQUIRED_APP_SCOPES));
291
+ if (requiredMissing.length === 0) {
292
+ // 全部权限已开通
293
+ return {
294
+ status: 'pass',
295
+ markdown: t.allPermsGranted(tool_scopes_1.REQUIRED_APP_SCOPES.length),
296
+ missingScopes: [],
297
+ };
298
+ }
299
+ // 缺少必需权限
300
+ const lines = [];
301
+ let applyUrl = `${openDomain}/app/${appId}/auth?op_from=feishu-openclaw&token_type=tenant`;
302
+ if (requiredMissing.length < 20) {
303
+ applyUrl = `${openDomain}/app/${appId}/auth?q=${encodeURIComponent(requiredMissing.join(','))}&op_from=feishu-openclaw&token_type=tenant`;
304
+ }
305
+ lines.push(`${t.missingPermsPrefix} ${requiredMissing.length} ${t.missingPermsSuffix} [${t.apply}](${applyUrl})`);
306
+ lines.push('');
307
+ for (const scope of requiredMissing) {
308
+ lines.push(`- ${scope}`);
309
+ }
310
+ return {
311
+ status: 'fail',
312
+ markdown: lines.join('\n'),
313
+ missingScopes: requiredMissing,
314
+ };
315
+ }
316
+ catch (err) {
317
+ // API 调用失败(通常是缺少 application:application:self_manage 权限)
318
+ const applyUrl = `${openDomain}/app/${appId}/auth?q=application:application:self_manage&op_from=feishu-openclaw&token_type=tenant`;
319
+ if (err instanceof tool_client_1.AppScopeCheckFailedError) {
320
+ return {
321
+ status: 'fail',
322
+ markdown: `${t.cannotQueryPerms}\n\n${t.adminApply} [${t.apply}](${applyUrl})`,
323
+ missingScopes: [],
324
+ };
325
+ }
326
+ return {
327
+ status: 'fail',
328
+ markdown: `${t.cannotQueryPermsGeneric}${err instanceof Error ? err.message : String(err)}\n\n${t.suggestCheckPerm} [${t.apply}](${applyUrl})`,
329
+ missingScopes: [],
330
+ };
331
+ }
332
+ }
333
+ // ---------------------------------------------------------------------------
334
+ // 用户权限检查
335
+ // ---------------------------------------------------------------------------
336
+ /**
337
+ * 生成权限对照表
338
+ */
339
+ function generatePermissionTable(appGrantedScopes, userGrantedScopes, hasValidUser, locale) {
340
+ let allScopes = getAllToolScopes();
341
+ allScopes = (0, tool_scopes_1.filterSensitiveScopes)(allScopes);
342
+ const appSet = new Set(appGrantedScopes);
343
+ const userSet = new Set(userGrantedScopes);
344
+ const lines = [];
345
+ lines.push(T[locale].permTableHeader);
346
+ lines.push('|----------|-----------|-----------|');
347
+ for (const scope of allScopes) {
348
+ const appGranted = appSet.has(scope) ? '✅' : '❌';
349
+ // 如果没有有效用户,显示 ➖;否则根据授权情况显示 ✅ 或 ❌
350
+ const userGranted = !hasValidUser ? '➖' : userSet.has(scope) ? '✅' : '❌';
351
+ lines.push(`| ${scope} | ${appGranted} | ${userGranted} |`);
352
+ }
353
+ return lines.join('\n');
354
+ }
355
+ /**
356
+ * 检查用户权限状态
357
+ */
358
+ async function checkUserPermissions(account, sdk, locale) {
359
+ const t = T[locale];
360
+ const { appId } = account;
361
+ const openDomain = (0, domains_1.openPlatformDomain)(account.brand);
362
+ const lines = [];
363
+ try {
364
+ // 1. 获取应用所有者
365
+ const ownerId = await (0, app_owner_fallback_1.getAppOwnerFallback)(account, sdk);
366
+ // 2. 读取 token
367
+ const token = ownerId ? await (0, token_store_1.getStoredToken)(appId, ownerId) : null;
368
+ // 判断是否有有效的用户授权
369
+ const hasUserAuth = !!token;
370
+ // 变量初始化
371
+ let authStatus = 'warn';
372
+ let refreshStatus = 'warn';
373
+ let validCount = 0;
374
+ let scopes = [];
375
+ let userTokenStatus = 'expired';
376
+ let userMissing = [];
377
+ // 获取应用开通的支持 user token 的权限
378
+ const appUserScopes = await (0, app_scope_checker_1.getAppGrantedScopes)(sdk, appId, 'user');
379
+ let allScopes = getAllToolScopes();
380
+ allScopes = (0, tool_scopes_1.filterSensitiveScopes)(allScopes);
381
+ const appGrantedCount = appUserScopes.filter((s) => allScopes.includes(s)).length;
382
+ if (hasUserAuth) {
383
+ // 有用户授权 - 检查授权状态
384
+ const status = (0, token_store_1.tokenStatus)(token);
385
+ userTokenStatus = status;
386
+ scopes = token.scope.split(' ').filter(Boolean);
387
+ validCount = status === 'valid' ? 1 : 0;
388
+ const needsRefreshCount = status === 'needs_refresh' ? 1 : 0;
389
+ const expiredCount = status === 'expired' ? 1 : 0;
390
+ authStatus = expiredCount > 0 ? 'warn' : validCount === 1 ? 'pass' : 'warn';
391
+ const authEmoji = authStatus === 'pass' ? '✅' : '⚠️';
392
+ lines.push(`${authEmoji} ${t.authStatusLabel}: ${t.userTotal} | ✓ ${t.valid}: ${validCount}, ⟳ ${t.needRefresh}: ${needsRefreshCount}, ✗ ${t.expired}: ${expiredCount}`);
393
+ // Token 自动刷新检查
394
+ const hasOfflineAccess = scopes.includes('offline_access');
395
+ refreshStatus = hasOfflineAccess ? 'pass' : 'warn';
396
+ const refreshEmoji = refreshStatus === 'pass' ? '✅' : '⚠️';
397
+ lines.push(`${refreshEmoji} ${t.tokenRefreshLabel}: ${hasOfflineAccess ? t.tokenRefreshOn : t.tokenRefreshOff}`);
398
+ }
399
+ else {
400
+ // 没有用户授权
401
+ lines.push(t.noUserAuth);
402
+ lines.push('');
403
+ lines.push(t.noUserAuthDesc);
404
+ lines.push('');
405
+ }
406
+ // 计算用户已授权权限数
407
+ const userGrantedCount = validCount === 1 ? scopes.filter((s) => allScopes.includes(s)).length : 0;
408
+ // 计算用户缺失的权限
409
+ if (hasUserAuth && validCount === 1) {
410
+ const scopeSet = new Set(scopes);
411
+ userMissing = allScopes.filter((s) => !scopeSet.has(s));
412
+ }
413
+ // 权限对照统计
414
+ const tableStatus = appGrantedCount < allScopes.length || userGrantedCount < allScopes.length
415
+ ? appGrantedCount < allScopes.length
416
+ ? 'fail'
417
+ : 'warn'
418
+ : 'pass';
419
+ const tableEmoji = tableStatus === 'pass' ? '✅' : tableStatus === 'warn' ? '⚠️' : '❌';
420
+ if (validCount === 0) {
421
+ lines.push(`${t.permCompareLabel}: ${t.permCompareSummary(appGrantedCount, allScopes.length, t.noAuthLabel)}`);
422
+ }
423
+ else if (userGrantedCount < allScopes.length) {
424
+ lines.push(`${tableEmoji} ${t.permInsufficient}: ${t.permCompareSummary(appGrantedCount, allScopes.length, `${userGrantedCount}/${allScopes.length} ${t.userCountLabel}`)}`);
425
+ }
426
+ else {
427
+ lines.push(`${tableEmoji} ${t.permCompareLabel}: ${t.permCompareSummary(appGrantedCount, allScopes.length, `${userGrantedCount}/${allScopes.length} ${t.userCountLabel}`)}`);
428
+ }
429
+ lines.push('');
430
+ // 添加指引信息
431
+ if (appGrantedCount < allScopes.length) {
432
+ // 计算缺失的应用权限
433
+ const appMissingScopes = allScopes.filter((s) => !appUserScopes.includes(s));
434
+ let appApplyUrl = `${openDomain}/app/${appId}/auth?op_from=feishu-openclaw&token_type=user`;
435
+ if (appMissingScopes.length < 20) {
436
+ appApplyUrl = `${openDomain}/app/${appId}/auth?q=${encodeURIComponent(appMissingScopes.join(','))}&op_from=feishu-openclaw&token_type=user`;
437
+ }
438
+ lines.push(`${t.appMissingUserPerms(appMissingScopes.length)} [${t.apply}](${appApplyUrl})`);
439
+ }
440
+ if (userGrantedCount < allScopes.length && validCount > 0) {
441
+ lines.push(t.userReauth);
442
+ lines.push('');
443
+ }
444
+ else if (!hasUserAuth) {
445
+ lines.push(t.userNeedsOAuth);
446
+ lines.push('');
447
+ }
448
+ // 生成详细权限对照表
449
+ const table = generatePermissionTable(appUserScopes, validCount === 1 ? scopes : [], validCount === 1, locale);
450
+ lines.push(table);
451
+ // 计算总体状态
452
+ const overallStatus = tableStatus === 'fail'
453
+ ? 'fail'
454
+ : authStatus === 'warn' || refreshStatus === 'warn' || tableStatus === 'warn'
455
+ ? 'warn'
456
+ : 'pass';
457
+ return {
458
+ status: overallStatus,
459
+ markdown: lines.join('\n'),
460
+ hasAuth: hasUserAuth,
461
+ tokenExpired: userTokenStatus === 'expired',
462
+ missingUserScopes: userMissing,
463
+ };
464
+ }
465
+ catch (err) {
466
+ const applyUrl = `${openDomain}/app/${appId}/auth?q=application:application:self_manage&op_from=feishu-openclaw&token_type=tenant`;
467
+ if (err instanceof tool_client_1.AppScopeCheckFailedError) {
468
+ return {
469
+ status: 'warn',
470
+ markdown: `${t.userPermFailedNoSelfManage}\n\n${t.adminApply} [${t.apply}](${applyUrl})`,
471
+ hasAuth: false,
472
+ tokenExpired: false,
473
+ missingUserScopes: [],
474
+ };
475
+ }
476
+ return {
477
+ status: 'warn',
478
+ markdown: `${t.userPermFailed}: ${err instanceof Error ? err.message : String(err)}`,
479
+ hasAuth: false,
480
+ tokenExpired: false,
481
+ missingUserScopes: [],
482
+ };
483
+ }
484
+ }
485
+ // ---------------------------------------------------------------------------
486
+ // 主函数
487
+ // ---------------------------------------------------------------------------
488
+ /**
489
+ * 运行飞书插件诊断,生成 Markdown 格式报告。
490
+ *
491
+ * @param config - OpenClaw 配置
492
+ * @param currentAccountId - 当前发送命令的机器人账号 ID(若有则只诊断该账号)
493
+ * @param locale - 输出语言,默认 zh_cn
494
+ */
495
+ async function runFeishuDoctor(config, currentAccountId, locale = 'zh_cn') {
496
+ const t = T[locale];
497
+ const lines = [];
498
+ // 1. 获取目标账户
499
+ // Use the global config to enumerate all accounts — the passed-in
500
+ // config may be account-scoped (accounts map stripped).
501
+ const globalCfg = resolveGlobalConfig(config);
502
+ const allAccounts = (0, accounts_1.getEnabledLarkAccounts)(globalCfg);
503
+ if (allAccounts.length === 0) {
504
+ return t.noAccounts;
505
+ }
506
+ // 若指定了 accountId,只诊断该账号
507
+ const accounts = currentAccountId ? allAccounts.filter((a) => a.accountId === currentAccountId) : allAccounts;
508
+ if (accounts.length === 0) {
509
+ return `${t.accountNotFoundPrefix} "${currentAccountId}"\n\n${t.enabledAccountsLabel}: ${allAccounts.map((a) => a.accountId).join(', ')}`;
510
+ }
511
+ // 2. 生成报告头部
512
+ lines.push(t.reportTitle);
513
+ lines.push('');
514
+ lines.push(`${t.pluginVersionLabel}: ${(0, version_1.getPluginVersion)()} | ${t.diagTimeLabel}: ${formatTimestamp(new Date())}`);
515
+ lines.push('');
516
+ lines.push('---');
517
+ lines.push('');
518
+ // 3. 工具配置(全局,不区分账户)
519
+ const toolsResult = checkToolsProfile(config, locale);
520
+ const toolsTitle = toolsResult.status === 'pass' ? t.toolsCheckPass : t.toolsCheckWarn;
521
+ lines.push(toolsTitle);
522
+ lines.push('');
523
+ lines.push(toolsResult.markdown);
524
+ lines.push('');
525
+ lines.push('---');
526
+ lines.push('');
527
+ // 3.5 多账号隔离检查(全局问题,始终展示)
528
+ // TODO: 暂时注释掉,等产品策略明确后再放开
529
+ // const isolationStatus = checkMultiAccountIsolation(config);
530
+ // const isolationWarning = formatIsolationWarning(isolationStatus, config);
531
+ // if (isolationWarning) {
532
+ // lines.push(isolationWarning);
533
+ // lines.push("");
534
+ // lines.push("---");
535
+ // lines.push("");
536
+ // }
537
+ // 4. 逐账户诊断(仅目标账户)
538
+ for (let i = 0; i < accounts.length; i++) {
539
+ const account = accounts[i];
540
+ const sdk = lark_client_1.LarkClient.fromAccount(account).sdk;
541
+ const accountLabel = account.accountId || account.appId;
542
+ if (accounts.length > 1) {
543
+ lines.push(`${t.accountPrefix} ${i + 1}: ${accountLabel}`);
544
+ lines.push('');
545
+ }
546
+ // 4a. 环境信息
547
+ const basicInfoResult = await checkBasicInfo(account, config, locale);
548
+ const basicTitle = basicInfoResult.status === 'pass' ? t.envCheckPass : t.envCheckFail;
549
+ lines.push(basicTitle);
550
+ lines.push('');
551
+ lines.push(basicInfoResult.markdown);
552
+ lines.push('');
553
+ lines.push('---');
554
+ lines.push('');
555
+ // 4b. 应用权限
556
+ const appResult = await checkAppPermissions(account, sdk, locale);
557
+ const appTitle = appResult.status === 'pass' ? t.appPermPass : t.appPermFail;
558
+ lines.push(appTitle);
559
+ lines.push('');
560
+ lines.push(appResult.markdown);
561
+ lines.push('');
562
+ lines.push('---');
563
+ lines.push('');
564
+ // 4c. 用户权限
565
+ const userResult = await checkUserPermissions(account, sdk, locale);
566
+ const userTitle = userResult.status === 'pass' ? t.userPermPass : t.userPermFail;
567
+ lines.push(userTitle);
568
+ lines.push('');
569
+ lines.push(userResult.markdown);
570
+ lines.push('');
571
+ if (i < accounts.length - 1) {
572
+ lines.push('---');
573
+ lines.push('');
574
+ }
575
+ }
576
+ return lines.join('\n');
577
+ }
578
+ /**
579
+ * 运行飞书插件诊断,同时生成中英双语 Markdown 报告。
580
+ * 用于飞书 channel 的多语言 post 发送。
581
+ */
582
+ async function runFeishuDoctorI18n(config, currentAccountId) {
583
+ const [zh_cn, en_us] = await Promise.all([
584
+ runFeishuDoctor(config, currentAccountId, 'zh_cn'),
585
+ runFeishuDoctor(config, currentAccountId, 'en_us'),
586
+ ]);
587
+ return { zh_cn, en_us };
588
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Register all chat commands (/feishu_diagnose, /feishu_doctor, /feishu_auth, /feishu).
6
+ */
7
+ import type { OpenClawConfig, OpenClawPluginApi } from 'openclaw/plugin-sdk';
8
+ import type { FeishuLocale } from './locale';
9
+ /**
10
+ * 运行 /feishu start 校验,返回 Markdown 格式结果。
11
+ */
12
+ export declare function runFeishuStart(config: OpenClawConfig, locale?: FeishuLocale): string;
13
+ /**
14
+ * 运行 /feishu start,同时生成中英双语结果。
15
+ */
16
+ export declare function runFeishuStartI18n(config: OpenClawConfig): Record<FeishuLocale, string>;
17
+ /**
18
+ * 生成 /feishu help 帮助文本。
19
+ */
20
+ export declare function getFeishuHelp(locale?: FeishuLocale): string;
21
+ /**
22
+ * 生成 /feishu help,同时生成中英双语结果。
23
+ */
24
+ export declare function getFeishuHelpI18n(): Record<FeishuLocale, string>;
25
+ export declare function registerCommands(api: OpenClawPluginApi): void;