@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,46 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * UAT (User Access Token) API call wrapper.
6
+ *
7
+ * Provides a safe, auto-refreshing interface for making Feishu API calls on
8
+ * behalf of a user. Tokens are read from the OS Keychain, refreshed
9
+ * transparently, and **never** exposed to the AI layer.
10
+ */
11
+ import type { LarkBrand } from './types';
12
+ import { NeedAuthorizationError } from './auth-errors';
13
+ export { NeedAuthorizationError };
14
+ export interface UATCallOptions {
15
+ userOpenId: string;
16
+ appId: string;
17
+ appSecret: string;
18
+ domain: LarkBrand;
19
+ }
20
+ export interface UATStatus {
21
+ authorized: boolean;
22
+ userOpenId: string;
23
+ scope?: string;
24
+ expiresAt?: number;
25
+ refreshExpiresAt?: number;
26
+ grantedAt?: number;
27
+ tokenStatus?: 'valid' | 'needs_refresh' | 'expired';
28
+ }
29
+ /**
30
+ * Obtain a valid access_token for the given user.
31
+ *
32
+ * - Reads from Keychain.
33
+ * - Refreshes proactively if the token is about to expire.
34
+ * - Throws when no token exists or refresh fails irrecoverably.
35
+ *
36
+ * **The returned token must never be exposed to the AI layer.**
37
+ */
38
+ export declare function getValidAccessToken(opts: UATCallOptions): Promise<string>;
39
+ /**
40
+ * Execute an API call with a valid UAT, retrying once on token-expiry errors.
41
+ */
42
+ export declare function callWithUAT<T>(opts: UATCallOptions, apiCall: (accessToken: string) => Promise<T>): Promise<T>;
43
+ /**
44
+ * Revoke a user's UAT by removing it from the Keychain.
45
+ */
46
+ export declare function revokeUAT(appId: string, userOpenId: string): Promise<void>;
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * UAT (User Access Token) API call wrapper.
7
+ *
8
+ * Provides a safe, auto-refreshing interface for making Feishu API calls on
9
+ * behalf of a user. Tokens are read from the OS Keychain, refreshed
10
+ * transparently, and **never** exposed to the AI layer.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.NeedAuthorizationError = void 0;
14
+ exports.getValidAccessToken = getValidAccessToken;
15
+ exports.callWithUAT = callWithUAT;
16
+ exports.revokeUAT = revokeUAT;
17
+ const token_store_1 = require("./token-store.js");
18
+ const device_flow_1 = require("./device-flow.js");
19
+ const lark_logger_1 = require("./lark-logger.js");
20
+ const log = (0, lark_logger_1.larkLogger)('core/uat-client');
21
+ const feishu_fetch_1 = require("./feishu-fetch.js");
22
+ const auth_errors_1 = require("./auth-errors.js");
23
+ Object.defineProperty(exports, "NeedAuthorizationError", { enumerable: true, get: function () { return auth_errors_1.NeedAuthorizationError; } });
24
+ // ---------------------------------------------------------------------------
25
+ // Per-user refresh lock
26
+ // ---------------------------------------------------------------------------
27
+ /**
28
+ * Guards against concurrent refresh operations for the same user.
29
+ *
30
+ * refresh_token is single-use: if two requests trigger a refresh
31
+ * simultaneously, the second one would use an already-consumed token and
32
+ * fail. The lock ensures only one refresh runs at a time per user.
33
+ */
34
+ const refreshLocks = new Map();
35
+ // ---------------------------------------------------------------------------
36
+ // Refresh implementation
37
+ // ---------------------------------------------------------------------------
38
+ async function doRefreshToken(opts, stored) {
39
+ // refresh_token already expired → can't refresh, need re-auth.
40
+ if (Date.now() >= stored.refreshExpiresAt) {
41
+ log.info(`refresh_token expired for ${opts.userOpenId}, clearing`);
42
+ await (0, token_store_1.removeStoredToken)(opts.appId, opts.userOpenId);
43
+ return null;
44
+ }
45
+ const endpoints = (0, device_flow_1.resolveOAuthEndpoints)(opts.domain);
46
+ const requestBody = new URLSearchParams({
47
+ grant_type: 'refresh_token',
48
+ refresh_token: stored.refreshToken,
49
+ client_id: opts.appId,
50
+ client_secret: opts.appSecret,
51
+ }).toString();
52
+ const callEndpoint = async () => {
53
+ const resp = await (0, feishu_fetch_1.feishuFetch)(endpoints.token, {
54
+ method: 'POST',
55
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
56
+ body: requestBody,
57
+ });
58
+ return (await resp.json());
59
+ };
60
+ let data = await callEndpoint();
61
+ // Feishu v2 token endpoint returns `code: 0` on success.
62
+ // Some responses use `error` field instead (standard OAuth).
63
+ const code = data.code;
64
+ const error = data.error;
65
+ if ((code !== undefined && code !== 0) || error) {
66
+ const errCode = code ?? error;
67
+ // Transient server error: retry once, then clear.
68
+ if (auth_errors_1.REFRESH_TOKEN_RETRYABLE.has(code)) {
69
+ log.warn(`refresh transient error (code=${errCode}) for ${opts.userOpenId}, retrying once`);
70
+ data = await callEndpoint();
71
+ const retryCode = data.code;
72
+ const retryError = data.error;
73
+ if ((retryCode !== undefined && retryCode !== 0) || retryError) {
74
+ const retryErrCode = retryCode ?? retryError;
75
+ log.warn(`refresh failed after retry (code=${retryErrCode}), clearing token for ${opts.userOpenId}`);
76
+ await (0, token_store_1.removeStoredToken)(opts.appId, opts.userOpenId);
77
+ return null;
78
+ }
79
+ }
80
+ else {
81
+ // Any other error (invalid/expired/revoked token, or unknown): clear and force re-auth.
82
+ log.warn(`refresh failed (code=${errCode}), clearing token for ${opts.userOpenId}`);
83
+ await (0, token_store_1.removeStoredToken)(opts.appId, opts.userOpenId);
84
+ return null;
85
+ }
86
+ }
87
+ if (!data.access_token) {
88
+ throw new Error('Token refresh returned no access_token');
89
+ }
90
+ const now = Date.now();
91
+ const updated = {
92
+ userOpenId: stored.userOpenId,
93
+ appId: opts.appId,
94
+ accessToken: data.access_token,
95
+ // refresh_token is rotated – always use the new one.
96
+ refreshToken: data.refresh_token ?? stored.refreshToken,
97
+ expiresAt: now + (data.expires_in ?? 7200) * 1000,
98
+ refreshExpiresAt: data.refresh_token_expires_in
99
+ ? now + data.refresh_token_expires_in * 1000
100
+ : stored.refreshExpiresAt,
101
+ scope: data.scope ?? stored.scope,
102
+ grantedAt: stored.grantedAt,
103
+ };
104
+ await (0, token_store_1.setStoredToken)(updated);
105
+ log.info(`refreshed UAT for ${opts.userOpenId} (at:${(0, token_store_1.maskToken)(updated.accessToken)})`);
106
+ return updated;
107
+ }
108
+ /**
109
+ * Refresh with per-user locking.
110
+ */
111
+ async function refreshWithLock(opts, stored) {
112
+ const key = `${opts.appId}:${opts.userOpenId}`;
113
+ // Another refresh is already in-flight – wait for it and re-read.
114
+ const existing = refreshLocks.get(key);
115
+ if (existing) {
116
+ await existing;
117
+ return (0, token_store_1.getStoredToken)(opts.appId, opts.userOpenId);
118
+ }
119
+ const promise = doRefreshToken(opts, stored);
120
+ refreshLocks.set(key, promise);
121
+ try {
122
+ return await promise;
123
+ }
124
+ finally {
125
+ refreshLocks.delete(key);
126
+ }
127
+ }
128
+ // ---------------------------------------------------------------------------
129
+ // Public API
130
+ // ---------------------------------------------------------------------------
131
+ /**
132
+ * Obtain a valid access_token for the given user.
133
+ *
134
+ * - Reads from Keychain.
135
+ * - Refreshes proactively if the token is about to expire.
136
+ * - Throws when no token exists or refresh fails irrecoverably.
137
+ *
138
+ * **The returned token must never be exposed to the AI layer.**
139
+ */
140
+ async function getValidAccessToken(opts) {
141
+ // Owner 检查已迁移到 owner-policy.ts(由 tool-client.ts 的 invokeAsUser 调用)
142
+ const stored = await (0, token_store_1.getStoredToken)(opts.appId, opts.userOpenId);
143
+ if (!stored) {
144
+ throw new auth_errors_1.NeedAuthorizationError(opts.userOpenId);
145
+ }
146
+ const status = (0, token_store_1.tokenStatus)(stored);
147
+ if (status === 'valid') {
148
+ return stored.accessToken;
149
+ }
150
+ if (status === 'needs_refresh') {
151
+ const refreshed = await refreshWithLock(opts, stored);
152
+ if (!refreshed) {
153
+ throw new auth_errors_1.NeedAuthorizationError(opts.userOpenId);
154
+ }
155
+ return refreshed.accessToken;
156
+ }
157
+ // expired
158
+ await (0, token_store_1.removeStoredToken)(opts.appId, opts.userOpenId);
159
+ throw new auth_errors_1.NeedAuthorizationError(opts.userOpenId);
160
+ }
161
+ /**
162
+ * Execute an API call with a valid UAT, retrying once on token-expiry errors.
163
+ */
164
+ async function callWithUAT(opts, apiCall) {
165
+ const accessToken = await getValidAccessToken(opts);
166
+ try {
167
+ return await apiCall(accessToken);
168
+ }
169
+ catch (err) {
170
+ // Retry once if the server reports token invalid/expired.
171
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
172
+ const code = err?.code ?? err?.response?.data?.code;
173
+ if (auth_errors_1.TOKEN_RETRY_CODES.has(code)) {
174
+ log.warn(`API call failed (code=${code}), refreshing and retrying`);
175
+ const stored = await (0, token_store_1.getStoredToken)(opts.appId, opts.userOpenId);
176
+ if (!stored)
177
+ throw new auth_errors_1.NeedAuthorizationError(opts.userOpenId);
178
+ const refreshed = await refreshWithLock(opts, stored);
179
+ if (!refreshed)
180
+ throw new auth_errors_1.NeedAuthorizationError(opts.userOpenId);
181
+ return await apiCall(refreshed.accessToken);
182
+ }
183
+ throw err;
184
+ }
185
+ }
186
+ /**
187
+ * Revoke a user's UAT by removing it from the Keychain.
188
+ */
189
+ async function revokeUAT(appId, userOpenId) {
190
+ await (0, token_store_1.removeStoredToken)(appId, userOpenId);
191
+ log.info(`revoked UAT for ${userOpenId}`);
192
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * 插件版本号管理
6
+ *
7
+ * 从 package.json 读取版本号并生成 User-Agent 字符串。
8
+ */
9
+ /**
10
+ * 获取插件版本号(从 package.json 读取)
11
+ *
12
+ * @returns 版本号字符串,如 "2026.2.28.5";读取失败返回 "unknown"
13
+ */
14
+ export declare function getPluginVersion(): string;
15
+ /**
16
+ * 获取当前运行平台名称
17
+ *
18
+ * @returns `mac` | `linux` | `windows`
19
+ */
20
+ export declare function getPlatform(): string;
21
+ /**
22
+ * 生成 User-Agent 字符串
23
+ *
24
+ * @returns User-Agent 字符串,格式:`openclaw-lark/{version}/{platform}`
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * getUserAgent() // => "openclaw-lark/2026.2.28.5/mac"
29
+ * ```
30
+ */
31
+ export declare function getUserAgent(): string;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * 插件版本号管理
7
+ *
8
+ * 从 package.json 读取版本号并生成 User-Agent 字符串。
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.getPluginVersion = getPluginVersion;
12
+ exports.getPlatform = getPlatform;
13
+ exports.getUserAgent = getUserAgent;
14
+ const node_url_1 = require("node:url");
15
+ const node_path_1 = require("node:path");
16
+ const node_fs_1 = require("node:fs");
17
+ /** 缓存的版本号 */
18
+ let cachedVersion;
19
+ /**
20
+ * 获取插件版本号(从 package.json 读取)
21
+ *
22
+ * @returns 版本号字符串,如 "2026.2.28.5";读取失败返回 "unknown"
23
+ */
24
+ function getPluginVersion() {
25
+ if (cachedVersion)
26
+ return cachedVersion;
27
+ try {
28
+ // 当前文件: src/core/version.ts → 向上两级到达项目根目录
29
+ const __filename = (0, node_url_1.fileURLToPath)(import.meta.url);
30
+ const __dirname = (0, node_path_1.dirname)(__filename);
31
+ const packageJsonPath = (0, node_path_1.join)(__dirname, '..', '..', 'package.json');
32
+ const raw = (0, node_fs_1.readFileSync)(packageJsonPath, 'utf8');
33
+ const pkg = JSON.parse(raw);
34
+ cachedVersion = pkg.version ?? 'unknown';
35
+ return cachedVersion;
36
+ }
37
+ catch {
38
+ cachedVersion = 'unknown';
39
+ return cachedVersion;
40
+ }
41
+ }
42
+ /**
43
+ * 获取当前运行平台名称
44
+ *
45
+ * @returns `mac` | `linux` | `windows`
46
+ */
47
+ function getPlatform() {
48
+ switch (process.platform) {
49
+ case 'darwin':
50
+ return 'mac';
51
+ case 'win32':
52
+ return 'windows';
53
+ default:
54
+ return 'linux';
55
+ }
56
+ }
57
+ /**
58
+ * 生成 User-Agent 字符串
59
+ *
60
+ * @returns User-Agent 字符串,格式:`openclaw-lark/{version}/{platform}`
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * getUserAgent() // => "openclaw-lark/2026.2.28.5/mac"
65
+ * ```
66
+ */
67
+ function getUserAgent() {
68
+ return `openclaw-lark/${getPluginVersion()}/${getPlatform()}`;
69
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Converter for "audio" message type.
6
+ */
7
+ import type { ContentConverterFn } from './types';
8
+ export declare const convertAudio: ContentConverterFn;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Converter for "audio" message type.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.convertAudio = void 0;
10
+ const utils_1 = require("./utils.js");
11
+ const convertAudio = (raw) => {
12
+ const parsed = (0, utils_1.safeParse)(raw);
13
+ const fileKey = parsed?.file_key;
14
+ if (!fileKey) {
15
+ return { content: '[audio]', resources: [] };
16
+ }
17
+ const duration = parsed?.duration;
18
+ const durationAttr = duration != null ? ` duration="${(0, utils_1.formatDuration)(duration)}"` : '';
19
+ return {
20
+ content: `<audio key="${fileKey}"${durationAttr}/>`,
21
+ resources: [{ type: 'audio', fileKey, duration: duration ?? undefined }],
22
+ };
23
+ };
24
+ exports.convertAudio = convertAudio;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Converters for calendar-related message types:
6
+ * - share_calendar_event
7
+ * - calendar
8
+ * - general_calendar
9
+ */
10
+ import type { ContentConverterFn } from './types';
11
+ export declare const convertShareCalendarEvent: ContentConverterFn;
12
+ export declare const convertCalendar: ContentConverterFn;
13
+ export declare const convertGeneralCalendar: ContentConverterFn;
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Converters for calendar-related message types:
7
+ * - share_calendar_event
8
+ * - calendar
9
+ * - general_calendar
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.convertGeneralCalendar = exports.convertCalendar = exports.convertShareCalendarEvent = void 0;
13
+ const utils_1 = require("./utils.js");
14
+ function formatCalendarContent(parsed) {
15
+ const summary = parsed?.summary ?? '';
16
+ const parts = [];
17
+ if (summary) {
18
+ parts.push(`📅 ${summary}`);
19
+ }
20
+ const start = parsed?.start_time ? (0, utils_1.millisToDatetime)(parsed.start_time) : '';
21
+ const end = parsed?.end_time ? (0, utils_1.millisToDatetime)(parsed.end_time) : '';
22
+ if (start && end) {
23
+ parts.push(`🕙 ${start} ~ ${end}`);
24
+ }
25
+ else if (start) {
26
+ parts.push(`🕙 ${start}`);
27
+ }
28
+ return parts.join('\n') || '[calendar event]';
29
+ }
30
+ const convertShareCalendarEvent = (raw) => {
31
+ const parsed = (0, utils_1.safeParse)(raw);
32
+ const inner = formatCalendarContent(parsed);
33
+ return {
34
+ content: `<calendar_share>${inner}</calendar_share>`,
35
+ resources: [],
36
+ };
37
+ };
38
+ exports.convertShareCalendarEvent = convertShareCalendarEvent;
39
+ const convertCalendar = (raw) => {
40
+ const parsed = (0, utils_1.safeParse)(raw);
41
+ const inner = formatCalendarContent(parsed);
42
+ return {
43
+ content: `<calendar_invite>${inner}</calendar_invite>`,
44
+ resources: [],
45
+ };
46
+ };
47
+ exports.convertCalendar = convertCalendar;
48
+ const convertGeneralCalendar = (raw) => {
49
+ const parsed = (0, utils_1.safeParse)(raw);
50
+ const inner = formatCalendarContent(parsed);
51
+ return {
52
+ content: `<calendar>${inner}</calendar>`,
53
+ resources: [],
54
+ };
55
+ };
56
+ exports.convertGeneralCalendar = convertGeneralCalendar;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Shared helper functions for Feishu content converters.
6
+ */
7
+ import type { ApiMessageItem, ConvertContext } from './types';
8
+ /** 从 mention 的 id 字段提取 open_id(兼容事件推送的对象格式和 API 响应的字符串格式) */
9
+ export declare function extractMentionOpenId(id: unknown): string;
10
+ /**
11
+ * Build a {@link ConvertContext} from a raw Feishu API message item.
12
+ *
13
+ * Extracts the `mentions` array that the IM API returns on each message
14
+ * item and maps it into the key→MentionInfo / openId→MentionInfo
15
+ * structures the converter system expects.
16
+ */
17
+ export declare function buildConvertContextFromItem(item: ApiMessageItem, fallbackMessageId: string, accountId?: string): ConvertContext;
18
+ /**
19
+ * Resolve mention placeholders in text.
20
+ *
21
+ * - Bot self-mention + stripBotMentions: leading-only strip. When the
22
+ * self-mention sits at the very start of the message, drop it (the
23
+ * `WasMentioned` envelope field already tells the agent "this message
24
+ * was addressed to you", so the anchor is redundant). When it appears
25
+ * mid-text, render it as plain `@Name` so the surrounding context still
26
+ * reads naturally without leaving an inline anchor the LLM might echo
27
+ * back into its reply.
28
+ * - Non-bot mentions: replace the placeholder key with readable `@name`.
29
+ */
30
+ export declare function resolveMentions(text: string, ctx: ConvertContext): string;
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Shared helper functions for Feishu content converters.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.extractMentionOpenId = extractMentionOpenId;
10
+ exports.buildConvertContextFromItem = buildConvertContextFromItem;
11
+ exports.resolveMentions = resolveMentions;
12
+ const user_name_cache_1 = require("../inbound/user-name-cache.js");
13
+ const utils_1 = require("./utils.js");
14
+ /** 从 mention 的 id 字段提取 open_id(兼容事件推送的对象格式和 API 响应的字符串格式) */
15
+ function extractMentionOpenId(id) {
16
+ if (typeof id === 'string')
17
+ return id;
18
+ if (id != null && typeof id === 'object' && 'open_id' in id) {
19
+ const openId = id.open_id;
20
+ return typeof openId === 'string' ? openId : '';
21
+ }
22
+ return '';
23
+ }
24
+ /**
25
+ * Build a {@link ConvertContext} from a raw Feishu API message item.
26
+ *
27
+ * Extracts the `mentions` array that the IM API returns on each message
28
+ * item and maps it into the key→MentionInfo / openId→MentionInfo
29
+ * structures the converter system expects.
30
+ */
31
+ function buildConvertContextFromItem(item, fallbackMessageId, accountId) {
32
+ const mentions = new Map();
33
+ const mentionsByOpenId = new Map();
34
+ for (const m of item.mentions ?? []) {
35
+ const openId = extractMentionOpenId(m.id);
36
+ if (!openId)
37
+ continue;
38
+ const info = {
39
+ key: m.key,
40
+ openId,
41
+ name: m.name ?? '',
42
+ isBot: false,
43
+ };
44
+ mentions.set(m.key, info);
45
+ mentionsByOpenId.set(openId, info);
46
+ }
47
+ return {
48
+ mentions,
49
+ mentionsByOpenId,
50
+ messageId: item.message_id ?? fallbackMessageId,
51
+ accountId,
52
+ resolveUserName: accountId ? (openId) => (0, user_name_cache_1.getUserNameCache)(accountId).get(openId) : undefined,
53
+ };
54
+ }
55
+ /**
56
+ * Resolve mention placeholders in text.
57
+ *
58
+ * - Bot self-mention + stripBotMentions: leading-only strip. When the
59
+ * self-mention sits at the very start of the message, drop it (the
60
+ * `WasMentioned` envelope field already tells the agent "this message
61
+ * was addressed to you", so the anchor is redundant). When it appears
62
+ * mid-text, render it as plain `@Name` so the surrounding context still
63
+ * reads naturally without leaving an inline anchor the LLM might echo
64
+ * back into its reply.
65
+ * - Non-bot mentions: replace the placeholder key with readable `@name`.
66
+ */
67
+ function resolveMentions(text, ctx) {
68
+ if (ctx.mentions.size === 0)
69
+ return text;
70
+ let result = text;
71
+ for (const [key, info] of ctx.mentions) {
72
+ if (info.isBot && ctx.stripBotMentions) {
73
+ result = result.replace(new RegExp((0, utils_1.escapeRegExp)(key), 'g'), `@${info.name}`);
74
+ const leadingPattern = new RegExp(`^\\s*@${(0, utils_1.escapeRegExp)(info.name)}[\\s,,::]*`);
75
+ result = result.replace(leadingPattern, '').trimStart();
76
+ }
77
+ else {
78
+ result = result.replace(new RegExp((0, utils_1.escapeRegExp)(key), 'g'), `@${info.name}`);
79
+ }
80
+ }
81
+ return result;
82
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Content converter for Feishu messages.
6
+ *
7
+ * Each message type (text, post, image, etc.) has a dedicated converter
8
+ * function that parses raw JSON content into an AI-friendly text
9
+ * representation plus a list of resource descriptors.
10
+ *
11
+ * This module is a general-purpose message parsing utility — usable
12
+ * from inbound handling, outbound formatting, and skills.
13
+ */
14
+ import type { ConvertContext, ConvertResult } from './types';
15
+ export type { ApiMessageItem, ConvertContext, ConvertResult, ContentConverterFn } from './types';
16
+ export { buildConvertContextFromItem, extractMentionOpenId, resolveMentions } from './content-converter-helpers';
17
+ /**
18
+ * Convert raw message content using the converter for the given message
19
+ * type. Falls back to the "unknown" converter for unrecognised types.
20
+ *
21
+ * Returns a Promise because some converters (e.g. merge_forward) perform
22
+ * async operations. Synchronous converters are awaited transparently.
23
+ */
24
+ export declare function convertMessageContent(raw: string, messageType: string, ctx: ConvertContext): Promise<ConvertResult>;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Content converter for Feishu messages.
7
+ *
8
+ * Each message type (text, post, image, etc.) has a dedicated converter
9
+ * function that parses raw JSON content into an AI-friendly text
10
+ * representation plus a list of resource descriptors.
11
+ *
12
+ * This module is a general-purpose message parsing utility — usable
13
+ * from inbound handling, outbound formatting, and skills.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.resolveMentions = exports.extractMentionOpenId = exports.buildConvertContextFromItem = void 0;
17
+ exports.convertMessageContent = convertMessageContent;
18
+ const index_1 = require("./index.js");
19
+ var content_converter_helpers_1 = require("./content-converter-helpers.js");
20
+ Object.defineProperty(exports, "buildConvertContextFromItem", { enumerable: true, get: function () { return content_converter_helpers_1.buildConvertContextFromItem; } });
21
+ Object.defineProperty(exports, "extractMentionOpenId", { enumerable: true, get: function () { return content_converter_helpers_1.extractMentionOpenId; } });
22
+ Object.defineProperty(exports, "resolveMentions", { enumerable: true, get: function () { return content_converter_helpers_1.resolveMentions; } });
23
+ // ---------------------------------------------------------------------------
24
+ // Convert
25
+ // ---------------------------------------------------------------------------
26
+ /**
27
+ * Convert raw message content using the converter for the given message
28
+ * type. Falls back to the "unknown" converter for unrecognised types.
29
+ *
30
+ * Returns a Promise because some converters (e.g. merge_forward) perform
31
+ * async operations. Synchronous converters are awaited transparently.
32
+ */
33
+ async function convertMessageContent(raw, messageType, ctx) {
34
+ const fn = index_1.converters.get(messageType) ?? index_1.converters.get('unknown');
35
+ if (!fn) {
36
+ return { content: raw, resources: [] };
37
+ }
38
+ const nextCtx = ctx.convertMessageContent ? ctx : { ...ctx, convertMessageContent };
39
+ return fn(raw, nextCtx);
40
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Converter for "file" message type.
6
+ */
7
+ import type { ContentConverterFn } from './types';
8
+ export declare const convertFile: ContentConverterFn;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Converter for "file" message type.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.convertFile = void 0;
10
+ const utils_1 = require("./utils.js");
11
+ const convertFile = (raw) => {
12
+ const parsed = (0, utils_1.safeParse)(raw);
13
+ const fileKey = parsed?.file_key;
14
+ if (!fileKey) {
15
+ return { content: '[file]', resources: [] };
16
+ }
17
+ const fileName = parsed?.file_name ?? '';
18
+ const nameAttr = fileName ? ` name="${fileName}"` : '';
19
+ return {
20
+ content: `<file key="${fileKey}"${nameAttr}/>`,
21
+ resources: [{ type: 'file', fileKey, fileName: fileName || undefined }],
22
+ };
23
+ };
24
+ exports.convertFile = convertFile;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Converter for "folder" message type.
6
+ */
7
+ import type { ContentConverterFn } from './types';
8
+ export declare const convertFolder: ContentConverterFn;