@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,61 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Type definitions for the Feishu reply dispatcher subsystem.
7
+ *
8
+ * Consolidates all interfaces, state shapes, and constants used across
9
+ * reply-dispatcher.ts, streaming-card-controller.ts, flush-controller.ts,
10
+ * and unavailable-guard.ts.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.EMPTY_REPLY_FALLBACK_TEXT = exports.THROTTLE_CONSTANTS = exports.PHASE_TRANSITIONS = exports.TERMINAL_PHASES = exports.CARD_PHASES = void 0;
14
+ // ---------------------------------------------------------------------------
15
+ // CardPhase — explicit state machine replacing boolean flags
16
+ // ---------------------------------------------------------------------------
17
+ exports.CARD_PHASES = {
18
+ idle: 'idle',
19
+ creating: 'creating',
20
+ streaming: 'streaming',
21
+ completed: 'completed',
22
+ aborted: 'aborted',
23
+ terminated: 'terminated',
24
+ creation_failed: 'creation_failed',
25
+ };
26
+ exports.TERMINAL_PHASES = new Set([
27
+ 'completed',
28
+ 'aborted',
29
+ 'terminated',
30
+ 'creation_failed',
31
+ ]);
32
+ exports.PHASE_TRANSITIONS = {
33
+ idle: new Set(['creating', 'aborted', 'terminated']),
34
+ creating: new Set(['streaming', 'creation_failed', 'aborted', 'terminated']),
35
+ streaming: new Set(['completed', 'aborted', 'terminated']),
36
+ completed: new Set(),
37
+ aborted: new Set(),
38
+ terminated: new Set(),
39
+ creation_failed: new Set(),
40
+ };
41
+ // ---------------------------------------------------------------------------
42
+ // Throttle constants
43
+ // ---------------------------------------------------------------------------
44
+ /**
45
+ * Throttle intervals for card updates.
46
+ *
47
+ * - `CARDKIT_MS`: CardKit `cardElement.content()` — designed for streaming,
48
+ * low throttle is fine.
49
+ * - `PATCH_MS`: `im.message.patch` — strict rate limits (code 230020).
50
+ * - `LONG_GAP_THRESHOLD_MS`: After a long idle gap (tool call / LLM thinking),
51
+ * defer the first flush briefly.
52
+ * - `BATCH_AFTER_GAP_MS`: Batching window after a long gap.
53
+ */
54
+ exports.THROTTLE_CONSTANTS = {
55
+ CARDKIT_MS: 100,
56
+ PATCH_MS: 1500,
57
+ LONG_GAP_THRESHOLD_MS: 2000,
58
+ BATCH_AFTER_GAP_MS: 300,
59
+ REASONING_STATUS_MS: 1500,
60
+ };
61
+ exports.EMPTY_REPLY_FALLBACK_TEXT = 'Done.';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Reply dispatcher factory for the Lark/Feishu channel plugin.
6
+ *
7
+ * Thin factory function that:
8
+ * 1. Resolves account, reply mode, and typing indicator config
9
+ * 2. In streaming mode, delegates to StreamingCardController
10
+ * 3. In static mode, delivers via sendMessageFeishu / sendMarkdownCardFeishu
11
+ * 4. Assembles and returns FeishuReplyDispatcherResult
12
+ */
13
+ import type { CreateFeishuReplyDispatcherParams, FeishuReplyDispatcherResult } from './reply-dispatcher-types';
14
+ export type { CreateFeishuReplyDispatcherParams } from './reply-dispatcher-types';
15
+ export declare function createFeishuReplyDispatcher(params: CreateFeishuReplyDispatcherParams): FeishuReplyDispatcherResult;
@@ -0,0 +1,447 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Reply dispatcher factory for the Lark/Feishu channel plugin.
7
+ *
8
+ * Thin factory function that:
9
+ * 1. Resolves account, reply mode, and typing indicator config
10
+ * 2. In streaming mode, delegates to StreamingCardController
11
+ * 3. In static mode, delivers via sendMessageFeishu / sendMarkdownCardFeishu
12
+ * 4. Assembles and returns FeishuReplyDispatcherResult
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.createFeishuReplyDispatcher = createFeishuReplyDispatcher;
16
+ const channel_runtime_1 = require("openclaw/plugin-sdk/channel-runtime");
17
+ const channel_feedback_1 = require("openclaw/plugin-sdk/channel-feedback");
18
+ const accounts_1 = require("../core/accounts.js");
19
+ const footer_config_1 = require("../core/footer-config.js");
20
+ const lark_client_1 = require("../core/lark-client.js");
21
+ const lark_logger_1 = require("../core/lark-logger.js");
22
+ const deliver_1 = require("../messaging/outbound/deliver.js");
23
+ const send_1 = require("../messaging/outbound/send.js");
24
+ const typing_1 = require("../messaging/outbound/typing.js");
25
+ const builder_1 = require("./builder.js");
26
+ const card_error_1 = require("./card-error.js");
27
+ const reply_mode_1 = require("./reply-mode.js");
28
+ const streaming_card_controller_1 = require("./streaming-card-controller.js");
29
+ const unavailable_guard_1 = require("./unavailable-guard.js");
30
+ const log = (0, lark_logger_1.larkLogger)('card/reply-dispatcher');
31
+ // ---------------------------------------------------------------------------
32
+ // Public API
33
+ // ---------------------------------------------------------------------------
34
+ function createFeishuReplyDispatcher(params) {
35
+ const core = lark_client_1.LarkClient.runtime;
36
+ const { cfg, agentId, chatId, sessionKey, replyToMessageId, accountId, replyInThread, threadId } = params;
37
+ // Resolve account so we can read per-account config (e.g. replyMode)
38
+ const account = (0, accounts_1.getLarkAccount)(cfg, accountId);
39
+ const feishuCfg = account.config;
40
+ const prefixContext = (0, channel_runtime_1.createReplyPrefixContext)({ cfg, agentId });
41
+ // ---- Reply mode resolution ----
42
+ const chatType = params.chatType;
43
+ const effectiveReplyMode = (0, reply_mode_1.resolveReplyMode)({ feishuCfg, chatType });
44
+ const replyMode = (0, reply_mode_1.expandAutoMode)({
45
+ mode: effectiveReplyMode,
46
+ streaming: feishuCfg?.streaming,
47
+ chatType,
48
+ });
49
+ const useStreamingCards = replyMode === 'streaming';
50
+ // ---- Block streaming for static mode ----
51
+ const enableBlockStreaming = feishuCfg?.blockStreaming === true && !useStreamingCards;
52
+ const { toolUseDisplay } = params;
53
+ const resolvedFooter = (0, footer_config_1.resolveFooterConfig)(feishuCfg?.footer);
54
+ log.info('reply mode resolved', {
55
+ effectiveReplyMode,
56
+ replyMode,
57
+ chatType,
58
+ });
59
+ log.info('footer config resolved', {
60
+ accountId: account.accountId,
61
+ sessionKey,
62
+ chatType,
63
+ useStreamingCards,
64
+ rawFooter: feishuCfg?.footer ?? null,
65
+ resolvedFooter,
66
+ });
67
+ // ---- Chunk & render settings (static mode only) ----
68
+ const textChunkLimit = core.channel.text.resolveTextChunkLimit(cfg, 'feishu', accountId, { fallbackLimit: 4000 });
69
+ const chunkMode = core.channel.text.resolveChunkMode(cfg, 'feishu');
70
+ // ---- Streaming card controller (instantiated only when needed) ----
71
+ const controller = useStreamingCards
72
+ ? new streaming_card_controller_1.StreamingCardController({
73
+ cfg,
74
+ agentId,
75
+ sessionKey,
76
+ accountId,
77
+ chatId,
78
+ replyToMessageId,
79
+ replyInThread,
80
+ toolUseDisplay,
81
+ resolvedFooter,
82
+ })
83
+ : null;
84
+ // ---- Static mode unavailable guard ----
85
+ // In streaming mode the controller owns its own guard; in static mode
86
+ // we still need unavailable-message detection for typing and deliver.
87
+ let staticAborted = false;
88
+ const staticGuard = controller
89
+ ? null
90
+ : new unavailable_guard_1.UnavailableGuard({
91
+ replyToMessageId,
92
+ getCardMessageId: () => null,
93
+ onTerminate: () => {
94
+ staticAborted = true;
95
+ },
96
+ });
97
+ const shouldSkip = (source) => {
98
+ if (controller)
99
+ return controller.shouldSkipForUnavailable(source);
100
+ return staticGuard?.shouldSkip(source) ?? false;
101
+ };
102
+ const isTerminated = () => {
103
+ if (controller)
104
+ return controller.isTerminated;
105
+ return staticGuard?.isTerminated ?? false;
106
+ };
107
+ // ---- Typing indicator (reaction-based) ----
108
+ let typingState = null;
109
+ let typingStopped = false;
110
+ const typingCallbacks = (0, channel_runtime_1.createTypingCallbacks)({
111
+ keepaliveIntervalMs: 0,
112
+ start: async () => {
113
+ if (shouldSkip('typing.start.precheck'))
114
+ return;
115
+ if (!replyToMessageId || typingStopped || params.skipTyping)
116
+ return;
117
+ if (typingState?.reactionId)
118
+ return;
119
+ typingState = await (0, typing_1.addTypingIndicator)({
120
+ cfg,
121
+ messageId: replyToMessageId,
122
+ accountId,
123
+ });
124
+ if (shouldSkip('typing.start.postcheck'))
125
+ return;
126
+ if (typingStopped && typingState) {
127
+ await (0, typing_1.removeTypingIndicator)({ cfg, state: typingState, accountId });
128
+ typingState = null;
129
+ log.info('removed typing indicator (raced with stop)');
130
+ return;
131
+ }
132
+ log.info('added typing indicator reaction');
133
+ },
134
+ stop: async () => {
135
+ typingStopped = true;
136
+ if (!typingState)
137
+ return;
138
+ await (0, typing_1.removeTypingIndicator)({ cfg, state: typingState, accountId });
139
+ typingState = null;
140
+ log.info('removed typing indicator reaction');
141
+ },
142
+ onStartError: (err) => {
143
+ (0, channel_feedback_1.logTypingFailure)({
144
+ log: (message) => log.warn(message),
145
+ channel: 'feishu',
146
+ action: 'start',
147
+ error: err,
148
+ });
149
+ },
150
+ onStopError: (err) => {
151
+ (0, channel_feedback_1.logTypingFailure)({
152
+ log: (message) => log.warn(message),
153
+ channel: 'feishu',
154
+ action: 'stop',
155
+ error: err,
156
+ });
157
+ },
158
+ });
159
+ // ---- dispatchFullyComplete flag (static mode) ----
160
+ let dispatchFullyComplete = false;
161
+ // ---- Build dispatcher ----
162
+ const { dispatcher, replyOptions, markDispatchIdle } = core.channel.reply.createReplyDispatcherWithTyping({
163
+ responsePrefix: prefixContext.responsePrefix,
164
+ responsePrefixContextProvider: prefixContext.responsePrefixContextProvider,
165
+ humanDelay: core.channel.reply.resolveHumanDelayConfig(cfg, agentId),
166
+ onReplyStart: async () => {
167
+ if (shouldSkip('onReplyStart'))
168
+ return;
169
+ await typingCallbacks.onReplyStart?.();
170
+ },
171
+ deliver: async (payload, meta) => {
172
+ log.debug('deliver called', {
173
+ textPreview: payload.text?.slice(0, 100),
174
+ kind: meta?.kind,
175
+ });
176
+ if (shouldSkip('deliver.entry'))
177
+ return;
178
+ // ---- Abort guard ----
179
+ // Only check aborted (not isTerminalPhase) so that
180
+ // creation_failed can still fallthrough to static delivery.
181
+ if (staticAborted || controller?.isTerminated || controller?.isAborted) {
182
+ log.debug('deliver: skipped (aborted)');
183
+ return;
184
+ }
185
+ // ---- Post-dispatch guard ----
186
+ if (dispatchFullyComplete) {
187
+ log.debug('deliver: skipped (dispatch already complete)');
188
+ return;
189
+ }
190
+ // 提取文本和媒体 URL
191
+ const text = getVisiblePayloadText(payload);
192
+ const reasoningText = payload.isReasoning === true ? (payload.text ?? '') : '';
193
+ const payloadMediaUrls = payload.mediaUrls?.length
194
+ ? payload.mediaUrls
195
+ : payload.mediaUrl
196
+ ? [payload.mediaUrl]
197
+ : [];
198
+ if (!text.trim() && !reasoningText.trim() && payloadMediaUrls.length === 0) {
199
+ log.debug('deliver: empty text and no media, skipping');
200
+ return;
201
+ }
202
+ // ---- Streaming card mode ----
203
+ if (controller) {
204
+ if (meta?.kind === 'tool' && shouldRouteToolPayloadToCard(payload, toolUseDisplay.showToolUse)) {
205
+ await controller.onToolPayload(payload);
206
+ return;
207
+ }
208
+ const controllerText = reasoningText.trim() ? reasoningText : text;
209
+ if (controllerText.trim()) {
210
+ await controller.ensureCardCreated();
211
+ if (controller.isTerminated)
212
+ return;
213
+ if (controller.cardMessageId) {
214
+ if (payload.isReasoning === true) {
215
+ await controller.onReasoningStream({ ...payload, text: controllerText });
216
+ return;
217
+ }
218
+ await controller.onDeliver({ ...payload, text: controllerText });
219
+ return;
220
+ }
221
+ // Card creation failed — fall through to static delivery
222
+ log.warn('deliver: card creation failed, falling back to static delivery');
223
+ }
224
+ }
225
+ // ---- Static text delivery ----
226
+ if (text.trim()) {
227
+ if ((0, reply_mode_1.shouldUseCard)(text)) {
228
+ const chunks = core.channel.text.chunkTextWithMode(text, textChunkLimit, chunkMode);
229
+ log.info('deliver: sending card chunks', {
230
+ count: chunks.length,
231
+ chatId,
232
+ });
233
+ // Runtime fallback: shouldUseCard() 通过但 API 仍拒绝(表格数超限)
234
+ let cardTableLimitHit = false;
235
+ for (const chunk of chunks) {
236
+ if (cardTableLimitHit) {
237
+ // 已触发降级,后续 chunk 直接走纯文本
238
+ try {
239
+ await (0, send_1.sendMessageFeishu)({
240
+ cfg,
241
+ to: chatId,
242
+ text: chunk,
243
+ replyToMessageId,
244
+ replyInThread,
245
+ accountId,
246
+ threadId,
247
+ });
248
+ }
249
+ catch (fallbackErr) {
250
+ if (staticGuard?.terminate('deliver.textFallback', fallbackErr))
251
+ return;
252
+ throw fallbackErr;
253
+ }
254
+ continue;
255
+ }
256
+ try {
257
+ await (0, send_1.sendMarkdownCardFeishu)({
258
+ cfg,
259
+ to: chatId,
260
+ text: chunk,
261
+ replyToMessageId,
262
+ replyInThread,
263
+ accountId,
264
+ });
265
+ }
266
+ catch (err) {
267
+ if (staticGuard?.terminate('deliver.cardChunk', err))
268
+ return;
269
+ // 卡片表格数超出飞书限制 — 降级为纯文本
270
+ if ((0, card_error_1.isCardTableLimitError)(err)) {
271
+ log.warn('card table limit exceeded (230099/11310), falling back to text', { chatId });
272
+ cardTableLimitHit = true;
273
+ try {
274
+ await (0, send_1.sendMessageFeishu)({
275
+ cfg,
276
+ to: chatId,
277
+ text: chunk,
278
+ replyToMessageId,
279
+ replyInThread,
280
+ accountId,
281
+ threadId,
282
+ });
283
+ }
284
+ catch (fallbackErr) {
285
+ if (staticGuard?.terminate('deliver.textFallback', fallbackErr))
286
+ return;
287
+ throw fallbackErr;
288
+ }
289
+ continue;
290
+ }
291
+ throw err;
292
+ }
293
+ }
294
+ }
295
+ else {
296
+ const chunks = core.channel.text.chunkTextWithMode(text, textChunkLimit, chunkMode);
297
+ log.info('deliver: sending text chunks', {
298
+ count: chunks.length,
299
+ chatId,
300
+ });
301
+ for (const chunk of chunks) {
302
+ try {
303
+ await (0, send_1.sendMessageFeishu)({
304
+ cfg,
305
+ to: chatId,
306
+ text: chunk,
307
+ replyToMessageId,
308
+ replyInThread,
309
+ accountId,
310
+ threadId,
311
+ });
312
+ }
313
+ catch (err) {
314
+ if (staticGuard?.terminate('deliver.textChunk', err))
315
+ return;
316
+ throw err;
317
+ }
318
+ }
319
+ }
320
+ }
321
+ // ---- Static media delivery ----
322
+ for (const mediaUrl of payloadMediaUrls) {
323
+ if (!mediaUrl?.trim())
324
+ continue;
325
+ try {
326
+ log.info('deliver: sending media via static path', {
327
+ mediaUrl: mediaUrl.slice(0, 80),
328
+ });
329
+ await (0, deliver_1.sendMediaLark)({
330
+ cfg,
331
+ to: chatId,
332
+ mediaUrl,
333
+ accountId,
334
+ replyToMessageId,
335
+ replyInThread,
336
+ });
337
+ }
338
+ catch (mediaErr) {
339
+ if (staticGuard?.terminate('deliver.media', mediaErr))
340
+ return;
341
+ log.error('deliver: static media send failed', {
342
+ error: String(mediaErr),
343
+ });
344
+ }
345
+ }
346
+ },
347
+ onError: async (err, info) => {
348
+ if (controller) {
349
+ if (controller.terminateIfUnavailable('onError', err)) {
350
+ typingCallbacks.onIdle?.();
351
+ return;
352
+ }
353
+ await controller.onError(err, info);
354
+ typingCallbacks.onIdle?.();
355
+ return;
356
+ }
357
+ // Static mode error handling
358
+ if (staticGuard?.terminate('onError', err)) {
359
+ typingCallbacks.onIdle?.();
360
+ return;
361
+ }
362
+ log.error(`${info.kind} reply failed`, { error: String(err) });
363
+ typingCallbacks.onIdle?.();
364
+ },
365
+ onIdle: async () => {
366
+ if (isTerminated() || shouldSkip('onIdle')) {
367
+ typingCallbacks.onIdle?.();
368
+ return;
369
+ }
370
+ if (!dispatchFullyComplete) {
371
+ typingCallbacks.onIdle?.();
372
+ return;
373
+ }
374
+ if (controller) {
375
+ await controller.onIdle();
376
+ }
377
+ typingCallbacks.onIdle?.();
378
+ },
379
+ onCleanup: async () => {
380
+ typingCallbacks.onCleanup?.();
381
+ },
382
+ });
383
+ // ---- Abort card (delegates to controller or no-op for static) ----
384
+ const abortCard = controller ? () => controller.abortCard() : async () => { };
385
+ return {
386
+ dispatcher,
387
+ replyOptions: {
388
+ ...replyOptions,
389
+ ...(controller
390
+ ? {
391
+ shouldEmitToolResult: () => false,
392
+ shouldEmitToolOutput: () => false,
393
+ }
394
+ : {}),
395
+ onModelSelected: (ctx) => {
396
+ prefixContext.onModelSelected(ctx);
397
+ },
398
+ disableBlockStreaming: !enableBlockStreaming,
399
+ ...(controller
400
+ ? {
401
+ onReasoningStream: (payload) => controller.onReasoningStream(payload),
402
+ onPartialReply: (payload) => controller.onPartialReply(payload),
403
+ onToolStart: (payload) => controller.onToolStart(payload),
404
+ }
405
+ : {}),
406
+ },
407
+ markDispatchIdle,
408
+ markFullyComplete: () => {
409
+ dispatchFullyComplete = true;
410
+ controller?.markFullyComplete();
411
+ },
412
+ abortCard,
413
+ };
414
+ }
415
+ function getVisiblePayloadText(payload) {
416
+ if (payload.isReasoning === true)
417
+ return '';
418
+ const rawText = payload.text ?? '';
419
+ if (!rawText)
420
+ return '';
421
+ const split = (0, builder_1.splitReasoningText)(rawText);
422
+ if (split.answerText != null) {
423
+ return split.answerText;
424
+ }
425
+ return (0, builder_1.stripReasoningTags)(rawText);
426
+ }
427
+ function shouldRouteToolPayloadToCard(payload, showToolUse) {
428
+ if (!showToolUse)
429
+ return false;
430
+ if (!getVisiblePayloadText(payload).trim())
431
+ return false;
432
+ if (payload.interactive)
433
+ return false;
434
+ if (payload.btw)
435
+ return false;
436
+ if (payload.audioAsVoice)
437
+ return false;
438
+ if (payload.mediaUrl || (payload.mediaUrls?.length ?? 0) > 0)
439
+ return false;
440
+ const execApproval = payload.channelData && typeof payload.channelData === 'object' && !Array.isArray(payload.channelData)
441
+ ? payload.channelData.execApproval
442
+ : undefined;
443
+ if (execApproval && typeof execApproval === 'object' && !Array.isArray(execApproval)) {
444
+ return false;
445
+ }
446
+ return true;
447
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Pure functions for resolving the Feishu reply mode.
6
+ *
7
+ * Extracted from reply-dispatcher.ts to enable independent testing
8
+ * and eliminate `as any` casts on FeishuConfig.
9
+ */
10
+ import type { FeishuConfig } from '../core/types';
11
+ type ReplyModeValue = 'auto' | 'static' | 'streaming';
12
+ /**
13
+ * Resolve the effective reply mode based on configuration and chat type.
14
+ *
15
+ * Priority: replyMode.{scene} > replyMode.default > replyMode (string) > "auto"
16
+ */
17
+ export declare function resolveReplyMode(params: {
18
+ feishuCfg: FeishuConfig | undefined;
19
+ chatType?: 'p2p' | 'group';
20
+ }): ReplyModeValue;
21
+ /**
22
+ * Expand "auto" mode to a concrete mode based on streaming flag and chat type.
23
+ *
24
+ * When streaming === true: group → static, direct → streaming (legacy behavior).
25
+ * When streaming is unset: always static (new default).
26
+ */
27
+ export declare function expandAutoMode(params: {
28
+ mode: ReplyModeValue;
29
+ streaming: boolean | undefined;
30
+ chatType?: 'p2p' | 'group';
31
+ }): 'static' | 'streaming';
32
+ /**
33
+ * scope A: rich text now renders natively as post(`tag:md`); we never force a
34
+ * card for code blocks OR tables anymore. Native rendering also keeps bot-at-bot
35
+ * @ delivery working — wrapping a reply in a card breaks it (cards have limited
36
+ * @ support). The only remaining card-path guard is the table-count hard limit,
37
+ * retained for the runtime fallback in reply-dispatcher (card rejected by
38
+ * Feishu → plain text).
39
+ */
40
+ export declare function shouldUseCard(text: string): boolean;
41
+ export {};
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Pure functions for resolving the Feishu reply mode.
7
+ *
8
+ * Extracted from reply-dispatcher.ts to enable independent testing
9
+ * and eliminate `as any` casts on FeishuConfig.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.resolveReplyMode = resolveReplyMode;
13
+ exports.expandAutoMode = expandAutoMode;
14
+ exports.shouldUseCard = shouldUseCard;
15
+ const card_error_1 = require("./card-error.js");
16
+ // ---------------------------------------------------------------------------
17
+ // resolveReplyMode
18
+ // ---------------------------------------------------------------------------
19
+ /**
20
+ * Resolve the effective reply mode based on configuration and chat type.
21
+ *
22
+ * Priority: replyMode.{scene} > replyMode.default > replyMode (string) > "auto"
23
+ */
24
+ function resolveReplyMode(params) {
25
+ const { feishuCfg, chatType } = params;
26
+ // streaming 布尔总开关:仅 true 时允许流式,未设置或 false 一律 static
27
+ if (feishuCfg?.streaming !== true)
28
+ return 'static';
29
+ const replyMode = feishuCfg?.replyMode;
30
+ if (!replyMode)
31
+ return 'auto';
32
+ if (typeof replyMode === 'string')
33
+ return replyMode;
34
+ // Object form: pick scene-specific value
35
+ const sceneMode = chatType === 'group' ? replyMode.group : chatType === 'p2p' ? replyMode.direct : undefined;
36
+ return sceneMode ?? replyMode.default ?? 'auto';
37
+ }
38
+ // ---------------------------------------------------------------------------
39
+ // expandAutoMode
40
+ // ---------------------------------------------------------------------------
41
+ /**
42
+ * Expand "auto" mode to a concrete mode based on streaming flag and chat type.
43
+ *
44
+ * When streaming === true: group → static, direct → streaming (legacy behavior).
45
+ * When streaming is unset: always static (new default).
46
+ */
47
+ function expandAutoMode(params) {
48
+ const { mode, streaming, chatType } = params;
49
+ if (mode !== 'auto')
50
+ return mode;
51
+ return streaming === true ? (chatType === 'group' ? 'static' : 'streaming') : 'static';
52
+ }
53
+ // ---------------------------------------------------------------------------
54
+ // shouldUseCard
55
+ // ---------------------------------------------------------------------------
56
+ /**
57
+ * scope A: rich text now renders natively as post(`tag:md`); we never force a
58
+ * card for code blocks OR tables anymore. Native rendering also keeps bot-at-bot
59
+ * @ delivery working — wrapping a reply in a card breaks it (cards have limited
60
+ * @ support). The only remaining card-path guard is the table-count hard limit,
61
+ * retained for the runtime fallback in reply-dispatcher (card rejected by
62
+ * Feishu → plain text).
63
+ */
64
+ function shouldUseCard(text) {
65
+ const tableMatches = (0, card_error_1.findMarkdownTablesOutsideCodeBlocks)(text);
66
+ if (tableMatches.length > card_error_1.FEISHU_CARD_TABLE_LIMIT) {
67
+ return false;
68
+ }
69
+ return false;
70
+ }