@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,144 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * auth-errors.ts — 统一错误类型定义。
6
+ *
7
+ * 所有与认证/授权/scope 相关的错误类型集中在此文件,
8
+ * 解除 tool-client ↔ app-scope-checker 循环依赖。
9
+ *
10
+ * 其他模块应直接 import 此文件,或通过 tool-client / uat-client 的 re-export 使用。
11
+ */
12
+ /** 飞书 OAPI 错误码常量,替代各处硬编码的 magic number。 */
13
+ export declare const LARK_ERROR: {
14
+ /** 应用 scope 不足(租户维度) */
15
+ readonly APP_SCOPE_MISSING: 99991672;
16
+ /** 用户 token scope 不足 */
17
+ readonly USER_SCOPE_INSUFFICIENT: 99991679;
18
+ /** access_token 无效 */
19
+ readonly TOKEN_INVALID: 99991668;
20
+ /** access_token 已过期 */
21
+ readonly TOKEN_EXPIRED: 99991677;
22
+ /** refresh_token 本身无效(格式非法或来自 v1 API) */
23
+ readonly REFRESH_TOKEN_INVALID: 20026;
24
+ /** refresh_token 已过期(超过 365 天) */
25
+ readonly REFRESH_TOKEN_EXPIRED: 20037;
26
+ /** refresh_token 已被吊销 */
27
+ readonly REFRESH_TOKEN_REVOKED: 20064;
28
+ /** refresh_token 已被使用(单次消费,rotation 场景) */
29
+ readonly REFRESH_TOKEN_ALREADY_USED: 20073;
30
+ /** refresh token 端点服务端内部错误,可重试 */
31
+ readonly REFRESH_SERVER_ERROR: 20050;
32
+ /** 消息已被撤回 */
33
+ readonly MESSAGE_RECALLED: 230011;
34
+ /** 消息已被删除 */
35
+ readonly MESSAGE_DELETED: 231003;
36
+ };
37
+ /** refresh token 端点可重试的错误码集合(服务端瞬时故障)。遇到后重试一次,仍失败则清 token。 */
38
+ export declare const REFRESH_TOKEN_RETRYABLE: ReadonlySet<number>;
39
+ /** 消息终止错误码集合(撤回/删除),遇到后应停止对该消息的后续操作。 */
40
+ export declare const MESSAGE_TERMINAL_CODES: ReadonlySet<number>;
41
+ /** access_token 失效相关的错误码集合,遇到后可尝试刷新重试。 */
42
+ export declare const TOKEN_RETRY_CODES: ReadonlySet<number>;
43
+ /** invoke() 错误共享的 scope 信息。 */
44
+ export interface ScopeErrorInfo {
45
+ apiName: string;
46
+ scopes: string[];
47
+ /** 应用 scope 是否已验证通过。false 表示 app scope 检查失败,scope 信息可能不准确。 */
48
+ appScopeVerified?: boolean;
49
+ /** 应用 ID,用于生成开放平台权限管理链接。 */
50
+ appId?: string;
51
+ }
52
+ /** OAuth 授权提示信息,与 handleInvokeError 返回的结构一致。 */
53
+ export interface AuthHint {
54
+ error: string;
55
+ api: string;
56
+ required_scope: string;
57
+ user_open_id: string;
58
+ message: string;
59
+ next_tool_call: {
60
+ tool: 'feishu_oauth';
61
+ params: {
62
+ action: 'authorize';
63
+ scope: string;
64
+ };
65
+ };
66
+ }
67
+ /** tryInvoke 返回值的判别联合体。 */
68
+ export type TryInvokeResult<T> = {
69
+ ok: true;
70
+ data: T;
71
+ } | {
72
+ ok: false;
73
+ error: string;
74
+ authHint: AuthHint;
75
+ } | {
76
+ ok: false;
77
+ error: string;
78
+ authHint?: undefined;
79
+ };
80
+ /**
81
+ * Thrown when no valid UAT exists and the user needs to (re-)authorise.
82
+ * Callers should catch this and trigger the OAuth flow.
83
+ */
84
+ export declare class NeedAuthorizationError extends Error {
85
+ readonly userOpenId: string;
86
+ constructor(userOpenId: string);
87
+ }
88
+ /**
89
+ * 应用缺少 application:application:self_manage 权限,无法查询应用权限配置。
90
+ *
91
+ * 需要管理员在飞书开放平台开通 application:application:self_manage 权限。
92
+ */
93
+ export declare class AppScopeCheckFailedError extends Error {
94
+ /** 应用 ID,用于生成开放平台权限管理链接。 */
95
+ readonly appId?: string;
96
+ constructor(appId?: string);
97
+ }
98
+ /**
99
+ * 应用未开通 OAPI 所需 scope。
100
+ *
101
+ * 需要管理员在飞书开放平台开通权限。
102
+ */
103
+ export declare class AppScopeMissingError extends Error {
104
+ readonly apiName: string;
105
+ /** OAPI 需要但 APP 未开通的 scope 列表。 */
106
+ readonly missingScopes: string[];
107
+ /** 工具的全部所需 scope(含已开通的),用于应用权限完成后一次性发起用户授权。 */
108
+ readonly allRequiredScopes?: string[];
109
+ /** 应用 ID,用于生成开放平台权限管理链接。 */
110
+ readonly appId?: string;
111
+ readonly scopeNeedType?: 'one' | 'all';
112
+ /** 触发此错误时使用的 token 类型,用于保持 card action 二次校验一致。 */
113
+ readonly tokenType?: 'user' | 'tenant';
114
+ constructor(info: ScopeErrorInfo, scopeNeedType?: 'one' | 'all', tokenType?: 'user' | 'tenant', allRequiredScopes?: string[]);
115
+ }
116
+ /**
117
+ * 用户未授权或 scope 不足,需要发起 OAuth 授权。
118
+ *
119
+ * `requiredScopes` 为 APP∩OAPI 的有效 scope,可直接传给
120
+ * `feishu_oauth authorize --scope`。
121
+ */
122
+ export declare class UserAuthRequiredError extends Error {
123
+ readonly userOpenId: string;
124
+ readonly apiName: string;
125
+ /** APP∩OAPI 交集 scope,传给 OAuth authorize。 */
126
+ readonly requiredScopes: string[];
127
+ /** 应用 scope 是否已验证通过。false 时 requiredScopes 可能不准确。 */
128
+ readonly appScopeVerified: boolean;
129
+ /** 应用 ID,用于生成开放平台权限管理链接。 */
130
+ readonly appId?: string;
131
+ constructor(userOpenId: string, info: ScopeErrorInfo);
132
+ }
133
+ /**
134
+ * 服务端报 99991679 — 用户 token 的 scope 不足。
135
+ *
136
+ * 需要增量授权:用缺失的 scope 发起新 Device Flow。
137
+ */
138
+ export declare class UserScopeInsufficientError extends Error {
139
+ readonly userOpenId: string;
140
+ readonly apiName: string;
141
+ /** 缺失的 scope 列表。 */
142
+ readonly missingScopes: string[];
143
+ constructor(userOpenId: string, info: ScopeErrorInfo);
144
+ }
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * auth-errors.ts — 统一错误类型定义。
7
+ *
8
+ * 所有与认证/授权/scope 相关的错误类型集中在此文件,
9
+ * 解除 tool-client ↔ app-scope-checker 循环依赖。
10
+ *
11
+ * 其他模块应直接 import 此文件,或通过 tool-client / uat-client 的 re-export 使用。
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.UserScopeInsufficientError = exports.UserAuthRequiredError = exports.AppScopeMissingError = exports.AppScopeCheckFailedError = exports.NeedAuthorizationError = exports.TOKEN_RETRY_CODES = exports.MESSAGE_TERMINAL_CODES = exports.REFRESH_TOKEN_RETRYABLE = exports.LARK_ERROR = void 0;
15
+ // ---------------------------------------------------------------------------
16
+ // Feishu error code constants
17
+ // ---------------------------------------------------------------------------
18
+ /** 飞书 OAPI 错误码常量,替代各处硬编码的 magic number。 */
19
+ exports.LARK_ERROR = {
20
+ /** 应用 scope 不足(租户维度) */
21
+ APP_SCOPE_MISSING: 99991672,
22
+ /** 用户 token scope 不足 */
23
+ USER_SCOPE_INSUFFICIENT: 99991679,
24
+ /** access_token 无效 */
25
+ TOKEN_INVALID: 99991668,
26
+ /** access_token 已过期 */
27
+ TOKEN_EXPIRED: 99991677,
28
+ /** refresh_token 本身无效(格式非法或来自 v1 API) */
29
+ REFRESH_TOKEN_INVALID: 20026,
30
+ /** refresh_token 已过期(超过 365 天) */
31
+ REFRESH_TOKEN_EXPIRED: 20037,
32
+ /** refresh_token 已被吊销 */
33
+ REFRESH_TOKEN_REVOKED: 20064,
34
+ /** refresh_token 已被使用(单次消费,rotation 场景) */
35
+ REFRESH_TOKEN_ALREADY_USED: 20073,
36
+ /** refresh token 端点服务端内部错误,可重试 */
37
+ REFRESH_SERVER_ERROR: 20050,
38
+ /** 消息已被撤回 */
39
+ MESSAGE_RECALLED: 230011,
40
+ /** 消息已被删除 */
41
+ MESSAGE_DELETED: 231003,
42
+ };
43
+ /** refresh token 端点可重试的错误码集合(服务端瞬时故障)。遇到后重试一次,仍失败则清 token。 */
44
+ exports.REFRESH_TOKEN_RETRYABLE = new Set([exports.LARK_ERROR.REFRESH_SERVER_ERROR]);
45
+ /** 消息终止错误码集合(撤回/删除),遇到后应停止对该消息的后续操作。 */
46
+ exports.MESSAGE_TERMINAL_CODES = new Set([
47
+ exports.LARK_ERROR.MESSAGE_RECALLED,
48
+ exports.LARK_ERROR.MESSAGE_DELETED,
49
+ ]);
50
+ /** access_token 失效相关的错误码集合,遇到后可尝试刷新重试。 */
51
+ exports.TOKEN_RETRY_CODES = new Set([exports.LARK_ERROR.TOKEN_INVALID, exports.LARK_ERROR.TOKEN_EXPIRED]);
52
+ // ---------------------------------------------------------------------------
53
+ // Error classes
54
+ // ---------------------------------------------------------------------------
55
+ /**
56
+ * Thrown when no valid UAT exists and the user needs to (re-)authorise.
57
+ * Callers should catch this and trigger the OAuth flow.
58
+ */
59
+ class NeedAuthorizationError extends Error {
60
+ userOpenId;
61
+ constructor(userOpenId) {
62
+ super('need_user_authorization');
63
+ this.name = 'NeedAuthorizationError';
64
+ this.userOpenId = userOpenId;
65
+ }
66
+ }
67
+ exports.NeedAuthorizationError = NeedAuthorizationError;
68
+ /**
69
+ * 应用缺少 application:application:self_manage 权限,无法查询应用权限配置。
70
+ *
71
+ * 需要管理员在飞书开放平台开通 application:application:self_manage 权限。
72
+ */
73
+ class AppScopeCheckFailedError extends Error {
74
+ /** 应用 ID,用于生成开放平台权限管理链接。 */
75
+ appId;
76
+ constructor(appId) {
77
+ super('应用缺少 application:application:self_manage 权限,无法查询应用权限配置。请管理员在开放平台开通该权限。');
78
+ this.name = 'AppScopeCheckFailedError';
79
+ this.appId = appId;
80
+ }
81
+ }
82
+ exports.AppScopeCheckFailedError = AppScopeCheckFailedError;
83
+ /**
84
+ * 应用未开通 OAPI 所需 scope。
85
+ *
86
+ * 需要管理员在飞书开放平台开通权限。
87
+ */
88
+ class AppScopeMissingError extends Error {
89
+ apiName;
90
+ /** OAPI 需要但 APP 未开通的 scope 列表。 */
91
+ missingScopes;
92
+ /** 工具的全部所需 scope(含已开通的),用于应用权限完成后一次性发起用户授权。 */
93
+ allRequiredScopes;
94
+ /** 应用 ID,用于生成开放平台权限管理链接。 */
95
+ appId;
96
+ scopeNeedType;
97
+ /** 触发此错误时使用的 token 类型,用于保持 card action 二次校验一致。 */
98
+ tokenType;
99
+ constructor(info, scopeNeedType, tokenType, allRequiredScopes) {
100
+ if (scopeNeedType === 'one') {
101
+ super(`应用缺少权限 [${info.scopes.join(', ')}](开启任一权限即可),请管理员在开放平台开通。`);
102
+ }
103
+ else {
104
+ super(`应用缺少权限 [${info.scopes.join(', ')}],请管理员在开放平台开通。`);
105
+ }
106
+ this.name = 'AppScopeMissingError';
107
+ this.apiName = info.apiName;
108
+ this.missingScopes = info.scopes;
109
+ this.allRequiredScopes = allRequiredScopes;
110
+ this.appId = info.appId;
111
+ this.scopeNeedType = scopeNeedType;
112
+ this.tokenType = tokenType;
113
+ }
114
+ }
115
+ exports.AppScopeMissingError = AppScopeMissingError;
116
+ /**
117
+ * 用户未授权或 scope 不足,需要发起 OAuth 授权。
118
+ *
119
+ * `requiredScopes` 为 APP∩OAPI 的有效 scope,可直接传给
120
+ * `feishu_oauth authorize --scope`。
121
+ */
122
+ class UserAuthRequiredError extends Error {
123
+ userOpenId;
124
+ apiName;
125
+ /** APP∩OAPI 交集 scope,传给 OAuth authorize。 */
126
+ requiredScopes;
127
+ /** 应用 scope 是否已验证通过。false 时 requiredScopes 可能不准确。 */
128
+ appScopeVerified;
129
+ /** 应用 ID,用于生成开放平台权限管理链接。 */
130
+ appId;
131
+ constructor(userOpenId, info) {
132
+ super('need_user_authorization');
133
+ this.name = 'UserAuthRequiredError';
134
+ this.userOpenId = userOpenId;
135
+ this.apiName = info.apiName;
136
+ this.requiredScopes = info.scopes;
137
+ this.appId = info.appId;
138
+ this.appScopeVerified = info.appScopeVerified ?? true;
139
+ }
140
+ }
141
+ exports.UserAuthRequiredError = UserAuthRequiredError;
142
+ /**
143
+ * 服务端报 99991679 — 用户 token 的 scope 不足。
144
+ *
145
+ * 需要增量授权:用缺失的 scope 发起新 Device Flow。
146
+ */
147
+ class UserScopeInsufficientError extends Error {
148
+ userOpenId;
149
+ apiName;
150
+ /** 缺失的 scope 列表。 */
151
+ missingScopes;
152
+ constructor(userOpenId, info) {
153
+ super('user_scope_insufficient');
154
+ this.name = 'UserScopeInsufficientError';
155
+ this.userOpenId = userOpenId;
156
+ this.apiName = info.apiName;
157
+ this.missingScopes = info.scopes;
158
+ }
159
+ }
160
+ exports.UserScopeInsufficientError = UserScopeInsufficientError;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Card callback operator identity extraction.
6
+ *
7
+ * Feishu Schema 2 card callbacks may carry the operator identity under
8
+ * either `operator.open_id` (Schema 1 / default) or `operator.user_id`
9
+ * (Schema 2 when the user has no open_id in the app's tenant).
10
+ *
11
+ * This helper provides a single, consistent extraction point so that
12
+ * every card callback handler resolves the operator identity the same
13
+ * way. See openclaw/openclaw#71670 for the upstream Schema 2 change.
14
+ */
15
+ /**
16
+ * Minimal shape of the `operator` object in a Feishu card callback event.
17
+ * Both fields are optional because Schema 2 may omit `open_id` entirely.
18
+ */
19
+ export interface CardCallbackOperator {
20
+ open_id?: string;
21
+ user_id?: string;
22
+ }
23
+ /**
24
+ * Extract the operator's identity from a Feishu card callback event.
25
+ *
26
+ * Prefers `open_id` (the stable per-app user identifier) and falls back
27
+ * to `user_id` when `open_id` is absent or empty — this is the Schema 2 path.
28
+ *
29
+ * @param operator - The `operator` field from the card callback payload.
30
+ * @returns The resolved operator identifier, or `undefined` when neither
31
+ * field is present.
32
+ */
33
+ export declare function resolveCardCallbackOperatorId(operator: CardCallbackOperator | undefined): string | undefined;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Card callback operator identity extraction.
7
+ *
8
+ * Feishu Schema 2 card callbacks may carry the operator identity under
9
+ * either `operator.open_id` (Schema 1 / default) or `operator.user_id`
10
+ * (Schema 2 when the user has no open_id in the app's tenant).
11
+ *
12
+ * This helper provides a single, consistent extraction point so that
13
+ * every card callback handler resolves the operator identity the same
14
+ * way. See openclaw/openclaw#71670 for the upstream Schema 2 change.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.resolveCardCallbackOperatorId = resolveCardCallbackOperatorId;
18
+ /**
19
+ * Extract the operator's identity from a Feishu card callback event.
20
+ *
21
+ * Prefers `open_id` (the stable per-app user identifier) and falls back
22
+ * to `user_id` when `open_id` is absent or empty — this is the Schema 2 path.
23
+ *
24
+ * @param operator - The `operator` field from the card callback payload.
25
+ * @returns The resolved operator identifier, or `undefined` when neither
26
+ * field is present.
27
+ */
28
+ function resolveCardCallbackOperatorId(operator) {
29
+ return operator?.open_id || operator?.user_id;
30
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Account-scoped LRU cache for Feishu group/chat metadata.
6
+ *
7
+ * Caches the result of `im.chat.get` (chat_mode, group_message_type, etc.)
8
+ * to avoid repeated OAPI calls for every inbound message.
9
+ *
10
+ * Key fields cached:
11
+ * - `chat_mode`: "group" | "topic" | "p2p"
12
+ * - `group_message_type`: "chat" | "thread" (only for chat_mode=group)
13
+ */
14
+ import type * as Lark from '@larksuiteoapi/node-sdk';
15
+ import type { ClawdbotConfig } from 'openclaw/plugin-sdk';
16
+ /** Minimal structural type for LarkClient class (avoids circular import). */
17
+ interface LarkClientStatic {
18
+ fromCfg(cfg: ClawdbotConfig, accountId?: string): {
19
+ sdk: Lark.Client;
20
+ };
21
+ }
22
+ /** @internal Called by lark-client.ts at module init time. */
23
+ export declare function injectLarkClient(cls: LarkClientStatic): void;
24
+ export interface ChatInfo {
25
+ chatMode: 'group' | 'topic' | 'p2p';
26
+ groupMessageType?: 'chat' | 'thread';
27
+ }
28
+ /** Clear chat-info caches (called from LarkClient.clearCache). */
29
+ export declare function clearChatInfoCache(accountId?: string): void;
30
+ /**
31
+ * Determine whether a group supports thread sessions.
32
+ *
33
+ * Returns `true` when the group is a topic group (`chat_mode=topic`) or
34
+ * a normal group with thread message mode (`group_message_type=thread`).
35
+ *
36
+ * Results are cached per-account with a 1-hour TTL to minimise OAPI calls.
37
+ */
38
+ export declare function isThreadCapableGroup(params: {
39
+ cfg: ClawdbotConfig;
40
+ chatId: string;
41
+ accountId?: string;
42
+ }): Promise<boolean>;
43
+ /**
44
+ * Fetch (or read from cache) the chat metadata for a given chat ID.
45
+ *
46
+ * Returns `undefined` when the API call fails (best-effort).
47
+ */
48
+ export declare function getChatInfo(params: {
49
+ cfg: ClawdbotConfig;
50
+ chatId: string;
51
+ accountId?: string;
52
+ }): Promise<ChatInfo | undefined>;
53
+ /**
54
+ * Determine the chat type (p2p or group) for a given chat ID.
55
+ *
56
+ * Delegates to the shared {@link getChatInfo} cache (account-scoped LRU with
57
+ * 1-hour TTL) so that chat metadata is fetched at most once across all
58
+ * call-sites (dispatch, reaction handler, etc.).
59
+ *
60
+ * Falls back to "p2p" if the API call fails.
61
+ */
62
+ export declare function getChatTypeFeishu(params: {
63
+ cfg: ClawdbotConfig;
64
+ chatId: string;
65
+ accountId?: string;
66
+ }): Promise<'p2p' | 'group'>;
67
+ export {};
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Account-scoped LRU cache for Feishu group/chat metadata.
7
+ *
8
+ * Caches the result of `im.chat.get` (chat_mode, group_message_type, etc.)
9
+ * to avoid repeated OAPI calls for every inbound message.
10
+ *
11
+ * Key fields cached:
12
+ * - `chat_mode`: "group" | "topic" | "p2p"
13
+ * - `group_message_type`: "chat" | "thread" (only for chat_mode=group)
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.injectLarkClient = injectLarkClient;
17
+ exports.clearChatInfoCache = clearChatInfoCache;
18
+ exports.isThreadCapableGroup = isThreadCapableGroup;
19
+ exports.getChatInfo = getChatInfo;
20
+ exports.getChatTypeFeishu = getChatTypeFeishu;
21
+ const lark_logger_1 = require("./lark-logger.js");
22
+ let _LarkClient = null;
23
+ /** @internal Called by lark-client.ts at module init time. */
24
+ function injectLarkClient(cls) {
25
+ _LarkClient = cls;
26
+ }
27
+ const log = (0, lark_logger_1.larkLogger)('core/chat-info-cache');
28
+ // ---------------------------------------------------------------------------
29
+ // Cache implementation
30
+ // ---------------------------------------------------------------------------
31
+ const DEFAULT_MAX_SIZE = 500;
32
+ const DEFAULT_TTL_MS = 60 * 60 * 1000; // 1 hour
33
+ class ChatInfoCache {
34
+ map = new Map();
35
+ maxSize;
36
+ ttlMs;
37
+ constructor(maxSize = DEFAULT_MAX_SIZE, ttlMs = DEFAULT_TTL_MS) {
38
+ this.maxSize = maxSize;
39
+ this.ttlMs = ttlMs;
40
+ }
41
+ get(chatId) {
42
+ const entry = this.map.get(chatId);
43
+ if (!entry)
44
+ return undefined;
45
+ if (entry.expireAt <= Date.now()) {
46
+ this.map.delete(chatId);
47
+ return undefined;
48
+ }
49
+ // LRU refresh
50
+ this.map.delete(chatId);
51
+ this.map.set(chatId, entry);
52
+ return entry.info;
53
+ }
54
+ set(chatId, info) {
55
+ this.map.delete(chatId);
56
+ this.map.set(chatId, { info, expireAt: Date.now() + this.ttlMs });
57
+ this.evict();
58
+ }
59
+ clear() {
60
+ this.map.clear();
61
+ }
62
+ evict() {
63
+ while (this.map.size > this.maxSize) {
64
+ const oldest = this.map.keys().next().value;
65
+ if (oldest !== undefined)
66
+ this.map.delete(oldest);
67
+ }
68
+ }
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // Account-scoped singleton registry
72
+ // ---------------------------------------------------------------------------
73
+ const registry = new Map();
74
+ function getChatInfoCache(accountId) {
75
+ let c = registry.get(accountId);
76
+ if (!c) {
77
+ c = new ChatInfoCache();
78
+ registry.set(accountId, c);
79
+ }
80
+ return c;
81
+ }
82
+ /** Clear chat-info caches (called from LarkClient.clearCache). */
83
+ function clearChatInfoCache(accountId) {
84
+ if (accountId !== undefined) {
85
+ registry.get(accountId)?.clear();
86
+ registry.delete(accountId);
87
+ }
88
+ else {
89
+ for (const c of registry.values())
90
+ c.clear();
91
+ registry.clear();
92
+ }
93
+ }
94
+ // ---------------------------------------------------------------------------
95
+ // Public API
96
+ // ---------------------------------------------------------------------------
97
+ /**
98
+ * Determine whether a group supports thread sessions.
99
+ *
100
+ * Returns `true` when the group is a topic group (`chat_mode=topic`) or
101
+ * a normal group with thread message mode (`group_message_type=thread`).
102
+ *
103
+ * Results are cached per-account with a 1-hour TTL to minimise OAPI calls.
104
+ */
105
+ async function isThreadCapableGroup(params) {
106
+ const { cfg, chatId, accountId } = params;
107
+ const info = await getChatInfo({ cfg, chatId, accountId });
108
+ if (!info)
109
+ return false;
110
+ return info.chatMode === 'topic' || info.groupMessageType === 'thread';
111
+ }
112
+ /**
113
+ * Fetch (or read from cache) the chat metadata for a given chat ID.
114
+ *
115
+ * Returns `undefined` when the API call fails (best-effort).
116
+ */
117
+ async function getChatInfo(params) {
118
+ const { cfg, chatId, accountId } = params;
119
+ const effectiveAccountId = accountId ?? 'default';
120
+ const cache = getChatInfoCache(effectiveAccountId);
121
+ const cached = cache.get(chatId);
122
+ if (cached)
123
+ return cached;
124
+ try {
125
+ if (!_LarkClient)
126
+ throw new Error('LarkClient not injected — circular dependency broken?');
127
+ const sdk = _LarkClient.fromCfg(cfg, accountId).sdk;
128
+ const response = await sdk.im.chat.get({
129
+ path: { chat_id: chatId },
130
+ });
131
+ const data = response?.data;
132
+ const chatMode = data?.chat_mode ?? 'group';
133
+ const groupMessageType = data?.group_message_type;
134
+ const info = {
135
+ chatMode: chatMode,
136
+ groupMessageType: groupMessageType,
137
+ };
138
+ cache.set(chatId, info);
139
+ log.info(`resolved ${chatId} → chat_mode=${chatMode}, group_message_type=${groupMessageType ?? 'N/A'}`);
140
+ return info;
141
+ }
142
+ catch (err) {
143
+ log.error(`failed to get chat info for ${chatId}: ${String(err)}`);
144
+ return undefined;
145
+ }
146
+ }
147
+ // ---------------------------------------------------------------------------
148
+ // getChatTypeFeishu
149
+ // ---------------------------------------------------------------------------
150
+ /**
151
+ * Determine the chat type (p2p or group) for a given chat ID.
152
+ *
153
+ * Delegates to the shared {@link getChatInfo} cache (account-scoped LRU with
154
+ * 1-hour TTL) so that chat metadata is fetched at most once across all
155
+ * call-sites (dispatch, reaction handler, etc.).
156
+ *
157
+ * Falls back to "p2p" if the API call fails.
158
+ */
159
+ async function getChatTypeFeishu(params) {
160
+ const { cfg, chatId, accountId } = params;
161
+ const info = await getChatInfo({ cfg, chatId, accountId });
162
+ if (!info)
163
+ return 'p2p';
164
+ return info.chatMode === 'group' || info.chatMode === 'topic' ? 'group' : 'p2p';
165
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Feishu Drive comment target ID parsing and formatting utilities.
6
+ *
7
+ * Comment targets use one of these formats:
8
+ * - `comment:<fileType>:<fileToken>:<commentId>` (legacy/default reply mode)
9
+ * - `comment:<deliveryMode>:<fileType>:<fileToken>:<commentId>`
10
+ *
11
+ * This enables the outbound routing layer to distinguish comment-thread
12
+ * replies from normal IM messages and route them through the Drive
13
+ * comment API instead.
14
+ */
15
+ /** Document types that support Drive comments. */
16
+ export type CommentFileType = 'doc' | 'docx' | 'file' | 'sheet' | 'slides';
17
+ /** Delivery mode for a comment target. */
18
+ export type CommentDeliveryMode = 'reply' | 'create_whole';
19
+ /** Parsed comment target components. */
20
+ export interface CommentTarget {
21
+ deliveryMode: CommentDeliveryMode;
22
+ fileType: CommentFileType;
23
+ fileToken: string;
24
+ commentId: string;
25
+ }
26
+ /**
27
+ * Construct a comment target string from its components.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * buildFeishuCommentTarget({ fileType: 'docx', fileToken: 'abc123', commentId: '789' })
32
+ * // => 'comment:docx:abc123:789'
33
+ *
34
+ * buildFeishuCommentTarget({ deliveryMode: 'create_whole', fileType: 'docx', fileToken: 'abc123', commentId: '789' })
35
+ * // => 'comment:create_whole:docx:abc123:789'
36
+ * ```
37
+ */
38
+ export declare function buildFeishuCommentTarget(params: {
39
+ deliveryMode?: CommentDeliveryMode;
40
+ fileType: CommentFileType;
41
+ fileToken: string;
42
+ commentId: string;
43
+ }): string;
44
+ /**
45
+ * Parse a comment target string into its components.
46
+ *
47
+ * Returns `null` when the string is not a valid comment target.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * parseFeishuCommentTarget('comment:docx:abc123:789')
52
+ * // => { deliveryMode: 'reply', fileType: 'docx', fileToken: 'abc123', commentId: '789' }
53
+ *
54
+ * parseFeishuCommentTarget('comment:create_whole:docx:abc123:789')
55
+ * // => { deliveryMode: 'create_whole', fileType: 'docx', fileToken: 'abc123', commentId: '789' }
56
+ *
57
+ * parseFeishuCommentTarget('oc_xxx')
58
+ * // => null
59
+ * ```
60
+ */
61
+ export declare function parseFeishuCommentTarget(target: string): CommentTarget | null;
62
+ /**
63
+ * Return `true` when a target string looks like a comment target.
64
+ */
65
+ export declare function isCommentTarget(target: string): boolean;