@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,794 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Interactive card building for Lark/Feishu.
7
+ *
8
+ * Provides utilities to construct Feishu Interactive Message Cards for
9
+ * different agent response states (thinking, streaming, complete, confirm).
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.REASONING_ELEMENT_ID = exports.STREAMING_ELEMENT_ID = void 0;
13
+ exports.splitReasoningText = splitReasoningText;
14
+ exports.stripReasoningTags = stripReasoningTags;
15
+ exports.formatReasoningDuration = formatReasoningDuration;
16
+ exports.formatToolUseDuration = formatToolUseDuration;
17
+ exports.formatElapsed = formatElapsed;
18
+ exports.compactNumber = compactNumber;
19
+ exports.formatFooterRuntimeSegments = formatFooterRuntimeSegments;
20
+ exports.buildCardContent = buildCardContent;
21
+ exports.buildStreamingThinkingCard = buildStreamingThinkingCard;
22
+ exports.buildStreamingPreAnswerCard = buildStreamingPreAnswerCard;
23
+ exports.toCardKit2 = toCardKit2;
24
+ const markdown_style_1 = require("./markdown-style.js");
25
+ const tool_use_display_1 = require("./tool-use-display.js");
26
+ // ---------------------------------------------------------------------------
27
+ // Constants
28
+ // ---------------------------------------------------------------------------
29
+ /**
30
+ * Element ID used for the streaming text area in cards. The CardKit
31
+ * `cardElement.content()` API targets this element for typewriter-effect
32
+ * streaming updates.
33
+ */
34
+ exports.STREAMING_ELEMENT_ID = 'streaming_content';
35
+ exports.REASONING_ELEMENT_ID = 'reasoning_content';
36
+ const TOOL_USE_STEP_CONTENT_INDENT = '0px 0px 0px 22px';
37
+ // ---------------------------------------------------------------------------
38
+ // Helpers
39
+ // ---------------------------------------------------------------------------
40
+ // ---- Reasoning text utilities ----
41
+ // Mirrors the logic in the framework's `splitTelegramReasoningText` and
42
+ // related helpers from `plugin-sdk/telegram/reasoning-lane-coordinator`.
43
+ // Those are not exported from the public plugin-sdk entry, so we replicate
44
+ // the same detection/splitting logic here.
45
+ const REASONING_PREFIX = 'Reasoning:\n';
46
+ /**
47
+ * Split a payload text into optional `reasoningText` and `answerText`.
48
+ *
49
+ * Handles two formats produced by the framework:
50
+ * 1. "Reasoning:\n_italic line_\n…" prefix (from `formatReasoningMessage`)
51
+ * 2. `<think>…</think>` / `<thinking>…</thinking>` XML tags
52
+ *
53
+ * Equivalent to the framework's `splitTelegramReasoningText()`.
54
+ */
55
+ function splitReasoningText(text) {
56
+ if (typeof text !== 'string' || !text.trim())
57
+ return {};
58
+ const trimmed = text.trim();
59
+ // Case 1: "Reasoning:\n..." prefix — the entire payload is reasoning
60
+ if (trimmed.startsWith(REASONING_PREFIX) && trimmed.length > REASONING_PREFIX.length) {
61
+ return { reasoningText: cleanReasoningPrefix(trimmed) };
62
+ }
63
+ // Case 2: XML thinking tags — extract content and strip from answer
64
+ const taggedReasoning = extractThinkingContent(text);
65
+ const strippedAnswer = stripReasoningTags(text);
66
+ if (!taggedReasoning && strippedAnswer === text) {
67
+ return { answerText: text };
68
+ }
69
+ return {
70
+ reasoningText: taggedReasoning || undefined,
71
+ answerText: strippedAnswer || undefined,
72
+ };
73
+ }
74
+ /**
75
+ * Extract content from `<think>`, `<thinking>`, `<thought>` blocks.
76
+ * Handles both closed and unclosed (streaming) tags.
77
+ */
78
+ function extractThinkingContent(text) {
79
+ if (!text)
80
+ return '';
81
+ const scanRe = /<\s*(\/?)\s*(?:think(?:ing)?|thought|antthinking)\s*>/gi;
82
+ let result = '';
83
+ let lastIndex = 0;
84
+ let inThinking = false;
85
+ for (const match of text.matchAll(scanRe)) {
86
+ const idx = match.index ?? 0;
87
+ if (inThinking) {
88
+ result += text.slice(lastIndex, idx);
89
+ }
90
+ inThinking = match[1] !== '/';
91
+ lastIndex = idx + match[0].length;
92
+ }
93
+ // Handle unclosed tag (still streaming)
94
+ if (inThinking) {
95
+ result += text.slice(lastIndex);
96
+ }
97
+ return result.trim();
98
+ }
99
+ /**
100
+ * Strip reasoning blocks — both XML tags with their content and any
101
+ * "Reasoning:\n" prefixed content.
102
+ */
103
+ function stripReasoningTags(text) {
104
+ // Strip complete XML blocks
105
+ let result = text.replace(/<\s*(?:think(?:ing)?|thought|antthinking)\s*>[\s\S]*?<\s*\/\s*(?:think(?:ing)?|thought|antthinking)\s*>/gi, '');
106
+ // Strip unclosed tag at end (streaming)
107
+ result = result.replace(/<\s*(?:think(?:ing)?|thought|antthinking)\s*>[\s\S]*$/gi, '');
108
+ // Strip orphaned closing tags
109
+ result = result.replace(/<\s*\/\s*(?:think(?:ing)?|thought|antthinking)\s*>/gi, '');
110
+ return result.trim();
111
+ }
112
+ /**
113
+ * Clean a "Reasoning:\n_italic_" formatted message back to plain text.
114
+ * Strips the prefix and per-line italic markdown wrappers.
115
+ */
116
+ function cleanReasoningPrefix(text) {
117
+ let cleaned = text.replace(/^Reasoning:\s*/i, '');
118
+ cleaned = cleaned
119
+ .split('\n')
120
+ .map((line) => line.replace(/^_(.+)_$/, '$1'))
121
+ .join('\n');
122
+ return cleaned.trim();
123
+ }
124
+ /**
125
+ * Format reasoning duration into a human-readable i18n pair.
126
+ * e.g. { zh: "思考了 3.2s", en: "Thought for 3.2s" }
127
+ */
128
+ function formatReasoningDuration(ms) {
129
+ const d = formatElapsed(ms);
130
+ return { zh: `思考了 ${d}`, en: `Thought for ${d}` };
131
+ }
132
+ /**
133
+ * Format tool-use duration into a human-readable i18n pair.
134
+ */
135
+ function formatToolUseDuration(ms) {
136
+ const d = formatElapsed(ms);
137
+ return { zh: `执行耗时 ${d}`, en: `Tool use for ${d}` };
138
+ }
139
+ /**
140
+ * Format milliseconds into a human-readable duration string.
141
+ */
142
+ function formatElapsed(ms) {
143
+ const seconds = ms / 1000;
144
+ return seconds < 60 ? `${seconds.toFixed(1)}s` : `${Math.floor(seconds / 60)}m ${Math.round(seconds % 60)}s`;
145
+ }
146
+ /**
147
+ * Build footer meta-info: notation-sized text with i18n support.
148
+ * Error text is rendered in red; normal text uses default grey (notation).
149
+ */
150
+ function buildFooter(zhText, enText, isError) {
151
+ const zhContent = isError ? `<font color='red'>${zhText}</font>` : zhText;
152
+ const enContent = isError ? `<font color='red'>${enText}</font>` : enText;
153
+ return [
154
+ {
155
+ tag: 'markdown',
156
+ content: enContent,
157
+ i18n_content: { zh_cn: zhContent, en_us: enContent },
158
+ text_size: 'notation',
159
+ },
160
+ ];
161
+ }
162
+ function compactNumber(value) {
163
+ const abs = Math.abs(value);
164
+ if (abs >= 1_000_000) {
165
+ const m = value / 1_000_000;
166
+ return Math.abs(m) >= 100 ? `${Math.round(m)}m` : `${m.toFixed(1)}m`;
167
+ }
168
+ if (abs >= 1_000) {
169
+ const k = value / 1_000;
170
+ return Math.abs(k) >= 100 ? `${Math.round(k)}k` : `${k.toFixed(1)}k`;
171
+ }
172
+ return `${Math.round(value)}`;
173
+ }
174
+ function formatFooterRuntimeSegments(params) {
175
+ const { footer, metrics, elapsedMs, isError, isAborted } = params;
176
+ const primaryZh = [];
177
+ const primaryEn = [];
178
+ const detailZh = [];
179
+ const detailEn = [];
180
+ // --- Primary line: status, elapsed, model ---
181
+ if (footer?.status) {
182
+ if (isError) {
183
+ primaryZh.push('出错');
184
+ primaryEn.push('Error');
185
+ }
186
+ else if (isAborted) {
187
+ primaryZh.push('已停止');
188
+ primaryEn.push('Stopped');
189
+ }
190
+ else {
191
+ primaryZh.push('已完成');
192
+ primaryEn.push('Completed');
193
+ }
194
+ }
195
+ if (footer?.elapsed && elapsedMs != null) {
196
+ const d = formatElapsed(elapsedMs);
197
+ primaryZh.push(`耗时 ${d}`);
198
+ primaryEn.push(`Elapsed ${d}`);
199
+ }
200
+ if (footer?.model && metrics?.model) {
201
+ const model = metrics.model.trim();
202
+ if (model) {
203
+ primaryZh.push(model);
204
+ primaryEn.push(model);
205
+ }
206
+ }
207
+ // --- Detail line: tokens, cache, context ---
208
+ if (footer?.tokens && metrics) {
209
+ const inTokens = typeof metrics.inputTokens === 'number' ? Math.max(0, metrics.inputTokens) : undefined;
210
+ const outTokens = typeof metrics.outputTokens === 'number' ? Math.max(0, metrics.outputTokens) : undefined;
211
+ if (inTokens != null && outTokens != null) {
212
+ const inLabel = compactNumber(inTokens);
213
+ const outLabel = compactNumber(outTokens);
214
+ detailZh.push(`↑ ${inLabel} ↓ ${outLabel}`);
215
+ detailEn.push(`↑ ${inLabel} ↓ ${outLabel}`);
216
+ }
217
+ }
218
+ if (footer?.cache && metrics) {
219
+ const read = typeof metrics.cacheRead === 'number' ? Math.max(0, metrics.cacheRead) : undefined;
220
+ const write = typeof metrics.cacheWrite === 'number' ? Math.max(0, metrics.cacheWrite) : undefined;
221
+ const inputVal = typeof metrics.inputTokens === 'number' ? Math.max(0, metrics.inputTokens) : undefined;
222
+ if (read != null && write != null && inputVal != null) {
223
+ const total = read + write + inputVal;
224
+ const hit = total > 0 ? Math.round((read / total) * 100) : 0;
225
+ const left = compactNumber(read);
226
+ const right = compactNumber(write);
227
+ detailZh.push(`缓存 ${left}/${right} (${hit}%)`);
228
+ detailEn.push(`Cache ${left}/${right} (${hit}%)`);
229
+ }
230
+ }
231
+ if (footer?.context && metrics) {
232
+ const freshTotal = metrics.totalTokensFresh === false ? undefined : metrics.totalTokens;
233
+ const total = typeof freshTotal === 'number' ? Math.max(0, freshTotal) : undefined;
234
+ const ctx = typeof metrics.contextTokens === 'number' ? Math.max(0, metrics.contextTokens) : undefined;
235
+ if (total != null && ctx != null) {
236
+ const totalLabel = compactNumber(total);
237
+ const ctxLabel = compactNumber(ctx);
238
+ const pct = ctx > 0 ? Math.round((total / ctx) * 100) : 0;
239
+ const pctLabel = `${pct}%`;
240
+ detailZh.push(`上下文 ${totalLabel}/${ctxLabel} (${pctLabel})`);
241
+ detailEn.push(`Context ${totalLabel}/${ctxLabel} (${pctLabel})`);
242
+ }
243
+ }
244
+ return { primaryZh, primaryEn, detailZh, detailEn };
245
+ }
246
+ // ---------------------------------------------------------------------------
247
+ // buildCardContent
248
+ // ---------------------------------------------------------------------------
249
+ /**
250
+ * Build a full Feishu Interactive Message Card JSON object for the
251
+ * given state.
252
+ */
253
+ function buildCardContent(state, data = {}) {
254
+ switch (state) {
255
+ case 'thinking':
256
+ return buildThinkingCard();
257
+ case 'streaming':
258
+ return buildStreamingCard(data.text ?? '', {
259
+ reasoningText: data.reasoningText,
260
+ showToolUse: data.showToolUse,
261
+ toolUseSteps: data.toolUseSteps,
262
+ toolUseTitleSuffix: data.toolUseTitleSuffix,
263
+ });
264
+ case 'complete':
265
+ return buildCompleteCard({
266
+ text: data.text ?? '',
267
+ elapsedMs: data.elapsedMs,
268
+ isError: data.isError,
269
+ reasoningText: data.reasoningText,
270
+ reasoningElapsedMs: data.reasoningElapsedMs,
271
+ toolUseSteps: data.toolUseSteps,
272
+ toolUseTitleSuffix: data.toolUseTitleSuffix,
273
+ toolUseElapsedMs: data.toolUseElapsedMs,
274
+ showToolUse: data.showToolUse,
275
+ isAborted: data.isAborted,
276
+ footer: data.footer,
277
+ footerMetrics: data.footerMetrics,
278
+ });
279
+ case 'confirm':
280
+ return buildConfirmCard(data.confirmData);
281
+ default:
282
+ throw new Error(`Unknown card state: ${state}`);
283
+ }
284
+ }
285
+ // ---------------------------------------------------------------------------
286
+ // Private card builders
287
+ // ---------------------------------------------------------------------------
288
+ function buildThinkingCard() {
289
+ return {
290
+ config: { wide_screen_mode: true, update_multi: true, locales: ['zh_cn', 'en_us'] },
291
+ elements: [
292
+ {
293
+ tag: 'markdown',
294
+ content: 'Thinking...',
295
+ i18n_content: { zh_cn: '思考中...', en_us: 'Thinking...' },
296
+ },
297
+ ],
298
+ };
299
+ }
300
+ function buildStreamingCard(partialText, params = {}) {
301
+ const { showToolUse = true, toolUseSteps, toolUseTitleSuffix, reasoningText } = params;
302
+ const elements = [];
303
+ const hasToolUse = Boolean(toolUseSteps?.length);
304
+ if (showToolUse) {
305
+ elements.push(hasToolUse
306
+ ? buildToolUsePanel({
307
+ toolUseSteps,
308
+ titleSuffix: toolUseTitleSuffix,
309
+ })
310
+ : buildStreamingToolUsePendingPanel());
311
+ }
312
+ if (!partialText && reasoningText) {
313
+ // Reasoning phase: show reasoning content in notation style
314
+ elements.push({
315
+ tag: 'markdown',
316
+ content: `💭 **Thinking...**\n\n${reasoningText}`,
317
+ i18n_content: {
318
+ zh_cn: `💭 **思考中...**\n\n${reasoningText}`,
319
+ en_us: `💭 **Thinking...**\n\n${reasoningText}`,
320
+ },
321
+ text_size: 'notation',
322
+ });
323
+ }
324
+ else if (partialText) {
325
+ // Answer phase: show answer content only
326
+ elements.push({
327
+ tag: 'markdown',
328
+ content: (0, markdown_style_1.optimizeMarkdownStyle)(partialText),
329
+ });
330
+ }
331
+ return {
332
+ config: { wide_screen_mode: true, update_multi: true, locales: ['zh_cn', 'en_us'] },
333
+ elements,
334
+ };
335
+ }
336
+ function buildCompleteCard(params) {
337
+ const { text, elapsedMs, isError, reasoningText, reasoningElapsedMs, toolUseSteps, toolUseTitleSuffix, toolUseElapsedMs, showToolUse = true, isAborted, footer, footerMetrics, } = params;
338
+ const elements = [];
339
+ if (showToolUse) {
340
+ elements.push(buildToolUsePanel({
341
+ toolUseSteps,
342
+ toolUseElapsedMs,
343
+ titleSuffix: toolUseTitleSuffix,
344
+ }));
345
+ }
346
+ // Collapsible reasoning panel (before main content)
347
+ if (reasoningText) {
348
+ const dur = reasoningElapsedMs ? formatReasoningDuration(reasoningElapsedMs) : null;
349
+ const zhLabel = dur ? dur.zh : '思考';
350
+ const enLabel = dur ? dur.en : 'Thought';
351
+ elements.push({
352
+ tag: 'collapsible_panel',
353
+ expanded: false,
354
+ header: {
355
+ title: {
356
+ tag: 'markdown',
357
+ content: `💭 ${enLabel}`,
358
+ i18n_content: {
359
+ zh_cn: `💭 ${zhLabel}`,
360
+ en_us: `💭 ${enLabel}`,
361
+ },
362
+ },
363
+ vertical_align: 'center',
364
+ icon: {
365
+ tag: 'standard_icon',
366
+ token: 'down-small-ccm_outlined',
367
+ size: '16px 16px',
368
+ },
369
+ icon_position: 'follow_text',
370
+ icon_expanded_angle: -180,
371
+ },
372
+ border: { color: 'grey', corner_radius: '5px' },
373
+ vertical_spacing: '8px',
374
+ padding: '8px 8px 8px 8px',
375
+ elements: [
376
+ {
377
+ tag: 'markdown',
378
+ content: reasoningText,
379
+ text_size: 'notation',
380
+ },
381
+ ],
382
+ });
383
+ }
384
+ // Full text content
385
+ elements.push({
386
+ tag: 'markdown',
387
+ content: (0, markdown_style_1.optimizeMarkdownStyle)(text),
388
+ });
389
+ // Footer meta-info: split into two lines for readability.
390
+ // Line 1 (primary): status · elapsed · model
391
+ // Line 2 (detail): tokens · cache · context
392
+ const fp = formatFooterRuntimeSegments({
393
+ footer,
394
+ metrics: footerMetrics,
395
+ elapsedMs,
396
+ isError,
397
+ isAborted,
398
+ });
399
+ const footerZhLines = [];
400
+ const footerEnLines = [];
401
+ if (fp.primaryZh.length > 0) {
402
+ footerZhLines.push(fp.primaryZh.join(' · '));
403
+ footerEnLines.push(fp.primaryEn.join(' · '));
404
+ }
405
+ if (fp.detailZh.length > 0) {
406
+ footerZhLines.push(fp.detailZh.join(' · '));
407
+ footerEnLines.push(fp.detailEn.join(' · '));
408
+ }
409
+ if (footerZhLines.length > 0) {
410
+ elements.push(...buildFooter(footerZhLines.join('\n'), footerEnLines.join('\n'), isError));
411
+ }
412
+ // Use the answer text as the feed preview summary.
413
+ // Strip markdown syntax so the preview reads as plain text.
414
+ const summaryText = text.replace(/[*_`#>[\]()~]/g, '').trim();
415
+ const summary = summaryText ? { content: summaryText.slice(0, 120) } : undefined;
416
+ return {
417
+ config: { wide_screen_mode: true, update_multi: true, locales: ['zh_cn', 'en_us'], summary },
418
+ elements,
419
+ };
420
+ }
421
+ function buildConfirmCard(confirmData) {
422
+ const elements = [];
423
+ // Operation description
424
+ elements.push({
425
+ tag: 'div',
426
+ text: {
427
+ tag: 'lark_md',
428
+ content: confirmData.operationDescription,
429
+ },
430
+ });
431
+ // Preview (if available)
432
+ if (confirmData.preview) {
433
+ elements.push({ tag: 'hr' });
434
+ elements.push({
435
+ tag: 'div',
436
+ text: {
437
+ tag: 'lark_md',
438
+ content: `**Preview:**\n${confirmData.preview}`,
439
+ },
440
+ });
441
+ }
442
+ // Confirm / Reject / Preview buttons
443
+ elements.push({ tag: 'hr' });
444
+ elements.push({
445
+ tag: 'action',
446
+ actions: [
447
+ {
448
+ tag: 'button',
449
+ text: { tag: 'plain_text', content: 'Confirm' },
450
+ type: 'primary',
451
+ value: {
452
+ action: 'confirm_write',
453
+ operation_id: confirmData.pendingOperationId,
454
+ },
455
+ },
456
+ {
457
+ tag: 'button',
458
+ text: { tag: 'plain_text', content: 'Reject' },
459
+ type: 'danger',
460
+ value: {
461
+ action: 'reject_write',
462
+ operation_id: confirmData.pendingOperationId,
463
+ },
464
+ },
465
+ ...(confirmData.preview
466
+ ? []
467
+ : [
468
+ {
469
+ tag: 'button',
470
+ text: {
471
+ tag: 'plain_text',
472
+ content: 'Preview',
473
+ },
474
+ type: 'default',
475
+ value: {
476
+ action: 'preview_write',
477
+ operation_id: confirmData.pendingOperationId,
478
+ },
479
+ },
480
+ ]),
481
+ ],
482
+ });
483
+ return {
484
+ config: { wide_screen_mode: true, update_multi: true },
485
+ header: {
486
+ title: {
487
+ tag: 'plain_text',
488
+ content: '\ud83d\udd12 Confirmation Required',
489
+ },
490
+ template: 'orange',
491
+ },
492
+ elements,
493
+ };
494
+ }
495
+ // ---------------------------------------------------------------------------
496
+ // toCardKit2
497
+ // ---------------------------------------------------------------------------
498
+ /**
499
+ * Convert an old-format FeishuCard to CardKit JSON 2.0 format.
500
+ * JSON 2.0 uses `body.elements` instead of top-level `elements`.
501
+ */
502
+ /**
503
+ * Build the initial CardKit 2.0 streaming card with a loading icon.
504
+ * Optionally includes a tool-use pending panel above the streaming area.
505
+ */
506
+ function buildStreamingThinkingCard(showToolUse = true) {
507
+ return buildStreamingPreAnswerCard({ showToolUse });
508
+ }
509
+ /**
510
+ * Build a CardKit 2.0 card for the pre-answer streaming phase.
511
+ * Used both for the initial card and for live updates during tool calls.
512
+ */
513
+ function buildStreamingPreAnswerCard(params) {
514
+ const { steps, elapsedMs, showToolUse = true } = params;
515
+ const hasSteps = Boolean(steps?.length);
516
+ const elements = [];
517
+ if (showToolUse) {
518
+ elements.push(hasSteps ? buildStreamingToolUseActivePanel({ steps: steps, elapsedMs }) : buildStreamingToolUsePendingPanel());
519
+ }
520
+ elements.push({
521
+ tag: 'markdown',
522
+ content: '',
523
+ text_align: 'left',
524
+ text_size: 'normal_v2',
525
+ margin: '0px 0px 0px 0px',
526
+ element_id: exports.STREAMING_ELEMENT_ID,
527
+ });
528
+ elements.push({
529
+ tag: 'markdown',
530
+ content: ' ',
531
+ icon: {
532
+ tag: 'custom_icon',
533
+ img_key: 'img_v3_02vb_496bec09-4b43-4773-ad6b-0cdd103cd2bg',
534
+ size: '16px 16px',
535
+ },
536
+ element_id: 'loading_icon',
537
+ });
538
+ return {
539
+ schema: '2.0',
540
+ config: {
541
+ streaming_mode: true,
542
+ locales: ['zh_cn', 'en_us'],
543
+ summary: {
544
+ content: 'Processing...',
545
+ i18n_content: { zh_cn: '处理中...', en_us: 'Processing...' },
546
+ },
547
+ },
548
+ body: { elements },
549
+ };
550
+ }
551
+ /**
552
+ * Build the collapsible panel for the active pre-answer phase.
553
+ * Used by buildStreamingPreAnswerCard when at least one step exists.
554
+ */
555
+ function buildStreamingToolUseActivePanel(params) {
556
+ const { steps, elapsedMs } = params;
557
+ const enParts = ['Tool use'];
558
+ const zhParts = ['工具执行'];
559
+ if (steps.length > 0) {
560
+ enParts.push(`${steps.length} step${steps.length === 1 ? '' : 's'}`);
561
+ zhParts.push(`${steps.length} 步`);
562
+ }
563
+ if (elapsedMs != null && elapsedMs > 0) {
564
+ const d = formatElapsed(elapsedMs);
565
+ enParts.push(`(${d})`);
566
+ zhParts.push(`(${d})`);
567
+ }
568
+ return {
569
+ tag: 'collapsible_panel',
570
+ expanded: true,
571
+ header: {
572
+ title: {
573
+ tag: 'plain_text',
574
+ content: `🛠️ ${enParts.join(' · ')}`,
575
+ i18n_content: {
576
+ zh_cn: `🛠️ ${zhParts.join(' · ')}`,
577
+ en_us: `🛠️ ${enParts.join(' · ')}`,
578
+ },
579
+ text_color: 'grey',
580
+ text_size: 'notation',
581
+ },
582
+ vertical_align: 'center',
583
+ icon: {
584
+ tag: 'standard_icon',
585
+ token: 'down-small-ccm_outlined',
586
+ color: 'grey',
587
+ size: '16px 16px',
588
+ },
589
+ icon_position: 'right',
590
+ icon_expanded_angle: -180,
591
+ },
592
+ border: { color: 'grey', corner_radius: '5px' },
593
+ vertical_spacing: '4px',
594
+ padding: '8px 8px 8px 8px',
595
+ elements: steps.flatMap((step) => buildToolUseStepElements(step)),
596
+ };
597
+ }
598
+ function toCardKit2(card) {
599
+ const result = {
600
+ schema: '2.0',
601
+ config: card.config,
602
+ body: { elements: card.elements },
603
+ };
604
+ if (card.header)
605
+ result.header = card.header;
606
+ return result;
607
+ }
608
+ function buildStreamingToolUsePendingPanel() {
609
+ return {
610
+ tag: 'collapsible_panel',
611
+ expanded: false,
612
+ header: {
613
+ title: {
614
+ tag: 'plain_text',
615
+ content: '🛠️ Tool use pending',
616
+ i18n_content: {
617
+ zh_cn: '🛠️ 等待工具执行',
618
+ en_us: '🛠️ Tool use pending',
619
+ },
620
+ text_color: 'grey',
621
+ text_size: 'notation',
622
+ },
623
+ vertical_align: 'center',
624
+ icon: {
625
+ tag: 'standard_icon',
626
+ token: 'down-small-ccm_outlined',
627
+ color: 'grey',
628
+ size: '16px 16px',
629
+ },
630
+ icon_position: 'right',
631
+ icon_expanded_angle: -180,
632
+ },
633
+ border: { color: 'grey', corner_radius: '5px' },
634
+ vertical_spacing: '4px',
635
+ padding: '8px 8px 8px 8px',
636
+ elements: [],
637
+ };
638
+ }
639
+ function buildToolUsePanel(params) {
640
+ const { toolUseSteps = [], toolUseElapsedMs, titleSuffix } = params;
641
+ const duration = toolUseElapsedMs ? formatToolUseDuration(toolUseElapsedMs) : null;
642
+ const zhTitleParts = [duration?.zh ?? '工具执行'];
643
+ const enTitleParts = [duration?.en ?? 'Tool use'];
644
+ if (titleSuffix) {
645
+ zhTitleParts.push(titleSuffix.zh);
646
+ enTitleParts.push(titleSuffix.en);
647
+ }
648
+ const stepElements = toolUseSteps.length > 0
649
+ ? toolUseSteps.flatMap((step) => buildToolUseStepElements(step))
650
+ : [buildToolUsePlaceholder()];
651
+ return {
652
+ tag: 'collapsible_panel',
653
+ expanded: false,
654
+ header: {
655
+ title: {
656
+ tag: 'plain_text',
657
+ content: `🛠️ ${enTitleParts.join(' · ')}`,
658
+ i18n_content: {
659
+ zh_cn: `🛠️ ${zhTitleParts.join(' · ')}`,
660
+ en_us: `🛠️ ${enTitleParts.join(' · ')}`,
661
+ },
662
+ text_color: 'grey',
663
+ text_size: 'notation',
664
+ },
665
+ vertical_align: 'center',
666
+ icon: {
667
+ tag: 'standard_icon',
668
+ token: 'down-small-ccm_outlined',
669
+ color: 'grey',
670
+ size: '16px 16px',
671
+ },
672
+ icon_position: 'right',
673
+ icon_expanded_angle: -180,
674
+ },
675
+ border: { color: 'grey', corner_radius: '5px' },
676
+ vertical_spacing: '4px',
677
+ padding: '8px 8px 8px 8px',
678
+ elements: stepElements,
679
+ };
680
+ }
681
+ function buildToolUseStepElements(step) {
682
+ const elements = [buildToolUseStepTitleElement(step)];
683
+ const detailElement = buildToolUseStepDetailElement(step);
684
+ if (detailElement) {
685
+ elements.push(detailElement);
686
+ }
687
+ const outputElement = buildToolUseStepOutputElement(step);
688
+ if (outputElement) {
689
+ elements.push(outputElement);
690
+ }
691
+ return elements;
692
+ }
693
+ function buildToolUsePlaceholder(labels) {
694
+ const zh = labels?.zh ?? '暂无工具步骤';
695
+ const en = labels?.en ?? tool_use_display_1.EMPTY_TOOL_USE_PLACEHOLDER;
696
+ return {
697
+ tag: 'div',
698
+ text: {
699
+ tag: 'plain_text',
700
+ content: en,
701
+ i18n_content: {
702
+ zh_cn: zh,
703
+ en_us: en,
704
+ },
705
+ text_color: 'grey',
706
+ text_size: 'notation',
707
+ },
708
+ };
709
+ }
710
+ function buildToolUseStepTitleElement(step) {
711
+ return {
712
+ tag: 'div',
713
+ icon: {
714
+ tag: 'standard_icon',
715
+ token: step.iconToken,
716
+ color: 'grey',
717
+ },
718
+ text: {
719
+ tag: 'lark_md',
720
+ content: buildToolUseStepTitleMarkdown(step),
721
+ text_size: 'notation',
722
+ },
723
+ };
724
+ }
725
+ function buildToolUseStepTitleMarkdown(step) {
726
+ const status = formatToolUseStepStatus(step.status);
727
+ return (0, markdown_style_1.optimizeMarkdownStyle)(`**${escapeToolUseMarkdownText(step.title)}** · <font color='${status.color}'>${status.label}</font>`, 1);
728
+ }
729
+ function buildToolUseStepDetailElement(step) {
730
+ const detail = step.detail?.trim();
731
+ if (!detail)
732
+ return undefined;
733
+ return {
734
+ tag: 'div',
735
+ margin: TOOL_USE_STEP_CONTENT_INDENT,
736
+ text: {
737
+ tag: 'plain_text',
738
+ content: detail,
739
+ text_color: 'grey',
740
+ text_size: 'notation',
741
+ },
742
+ };
743
+ }
744
+ function buildToolUseStepOutputElement(step) {
745
+ const content = buildToolUseStepOutputMarkdown(step);
746
+ if (!content)
747
+ return undefined;
748
+ return {
749
+ tag: 'div',
750
+ margin: TOOL_USE_STEP_CONTENT_INDENT,
751
+ text: {
752
+ tag: 'lark_md',
753
+ content,
754
+ text_size: 'notation',
755
+ },
756
+ };
757
+ }
758
+ function buildToolUseStepOutputMarkdown(step) {
759
+ const lines = [];
760
+ if (step.errorBlock) {
761
+ lines.push('**Error**');
762
+ lines.push(formatToolUseCodeBlock(step.errorBlock.content, step.errorBlock.language));
763
+ }
764
+ else if (step.resultBlock) {
765
+ lines.push('**Result**');
766
+ lines.push(formatToolUseCodeBlock(step.resultBlock.content, step.resultBlock.language));
767
+ }
768
+ if (lines.length === 0)
769
+ return undefined;
770
+ return (0, markdown_style_1.optimizeMarkdownStyle)(lines.join('\n'), 1);
771
+ }
772
+ function formatToolUseStepStatus(status) {
773
+ switch (status) {
774
+ case 'running':
775
+ return { label: 'Running', color: 'turquoise' };
776
+ case 'error':
777
+ return { label: 'Failed', color: 'red' };
778
+ case 'success':
779
+ default:
780
+ return { label: 'Succeeded', color: 'green' };
781
+ }
782
+ }
783
+ function formatToolUseCodeBlock(content, language) {
784
+ const normalized = content.replace(/\r\n/g, '\n').trim();
785
+ const fence = '`'.repeat(Math.max(3, longestBacktickRun(normalized) + 1));
786
+ return `${fence}${language}\n${normalized}\n${fence}`;
787
+ }
788
+ function longestBacktickRun(value) {
789
+ const matches = value.match(/`+/g) ?? [];
790
+ return matches.reduce((max, run) => Math.max(max, run.length), 0);
791
+ }
792
+ function escapeToolUseMarkdownText(value) {
793
+ return value.replace(/\\/g, '\\\\').replace(/([`*_{}[\]<>])/g, '\\$1');
794
+ }