@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,8 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Converter for "video_chat" message type.
6
+ */
7
+ import type { ContentConverterFn } from './types';
8
+ export declare const convertVideoChat: ContentConverterFn;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Converter for "video_chat" message type.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.convertVideoChat = void 0;
10
+ const utils_1 = require("./utils.js");
11
+ const convertVideoChat = (raw) => {
12
+ const parsed = (0, utils_1.safeParse)(raw);
13
+ const topic = parsed?.topic ?? '';
14
+ const meetingNo = parsed?.meet_number?.trim() ?? '';
15
+ const parts = [];
16
+ if (topic) {
17
+ parts.push(`Topic: ${topic}`);
18
+ }
19
+ if (parsed?.start_time) {
20
+ parts.push(`Start time: ${(0, utils_1.millisToDatetime)(parsed.start_time)}`);
21
+ }
22
+ if (meetingNo) {
23
+ parts.push(`Meeting number: ${meetingNo}`);
24
+ }
25
+ const inner = parts.join('\n') || '[video chat]';
26
+ return {
27
+ content: `<meeting>${inner}</meeting>`,
28
+ resources: [],
29
+ };
30
+ };
31
+ exports.convertVideoChat = convertVideoChat;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Converter for "video" and "media" message types.
6
+ */
7
+ import type { ContentConverterFn } from './types';
8
+ export declare const convertVideo: ContentConverterFn;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Converter for "video" and "media" message types.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.convertVideo = void 0;
10
+ const utils_1 = require("./utils.js");
11
+ const convertVideo = (raw) => {
12
+ const parsed = (0, utils_1.safeParse)(raw);
13
+ const fileKey = parsed?.file_key;
14
+ if (!fileKey) {
15
+ return { content: '[video]', resources: [] };
16
+ }
17
+ const fileName = parsed?.file_name ?? '';
18
+ const duration = parsed?.duration;
19
+ const coverKey = parsed?.image_key;
20
+ const nameAttr = fileName ? ` name="${fileName}"` : '';
21
+ const durationAttr = duration != null ? ` duration="${(0, utils_1.formatDuration)(duration)}"` : '';
22
+ return {
23
+ content: `<video key="${fileKey}"${nameAttr}${durationAttr}/>`,
24
+ resources: [
25
+ {
26
+ type: 'video',
27
+ fileKey,
28
+ fileName: fileName || undefined,
29
+ duration: duration ?? undefined,
30
+ coverImageKey: coverKey ?? undefined,
31
+ },
32
+ ],
33
+ };
34
+ };
35
+ exports.convertVideo = convertVideo;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Converter for "vote" message type.
6
+ */
7
+ import type { ContentConverterFn } from './types';
8
+ export declare const convertVote: ContentConverterFn;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Converter for "vote" message type.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.convertVote = void 0;
10
+ const utils_1 = require("./utils.js");
11
+ const convertVote = (raw) => {
12
+ const parsed = (0, utils_1.safeParse)(raw);
13
+ const topic = parsed?.topic ?? '';
14
+ const options = parsed?.options ?? [];
15
+ const parts = [];
16
+ if (topic) {
17
+ parts.push(topic);
18
+ }
19
+ for (const opt of options) {
20
+ parts.push(`• ${opt}`);
21
+ }
22
+ const inner = parts.join('\n') || '[vote]';
23
+ return {
24
+ content: `<vote>\n${inner}\n</vote>`,
25
+ resources: [],
26
+ };
27
+ };
28
+ exports.convertVote = convertVote;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Reply-routing decisions for the Feishu dispatch path.
6
+ *
7
+ * In bot-to-bot group scenarios, Feishu will pull thread-style replies into
8
+ * a hidden "topic view" that group members cannot see (#32980). The peer bot
9
+ * keeps receiving messages but humans in the chat see nothing — a silent
10
+ * failure mode that turns bot↔bot chat into a black hole.
11
+ *
12
+ * This module centralizes the three signals that decide where a reply lands:
13
+ * 1. isGroup — DMs never have the topic-view trap
14
+ * 2. senderIsBot — only bot→bot triggers it
15
+ * 3. dc.isThread — inbound was a thread reply (also inferred from
16
+ * root_id in topic groups when threadSession=true)
17
+ *
18
+ * Output: a routing object consumed by every outbound call site (main
19
+ * dispatcher + i18n command card + i18n command text fallback), so the
20
+ * three call sites never drift out of sync again.
21
+ */
22
+ import type { MentionInfo } from '../types';
23
+ import type { DispatchContext } from './dispatch-context';
24
+ /** The peer a reply must explicitly @-mention so it actually reaches them. */
25
+ export interface BotPeerTarget {
26
+ peerOpenId: string;
27
+ peerName: string;
28
+ }
29
+ /**
30
+ * Decide which peer (if any) an outbound reply must be guaranteed to
31
+ * @-mention, so the deterministic `ensureMention` backstop can wake them up.
32
+ *
33
+ * Deliberately INDEPENDENT of `suppressForBotPeer` (which only governs
34
+ * thread-vs-main routing): the addressee must be resolvable even on a
35
+ * human-orchestrated kickoff, where the triggering sender is a person but the
36
+ * conversation is meant to continue between bots.
37
+ *
38
+ * 1. Bot sender → @ the sender back, continuing the exchange.
39
+ * 2. Otherwise (e.g. a human kicking off a bot debate) → if the inbound
40
+ * message @-mentions exactly ONE party other than ourselves, treat that
41
+ * party as the designated peer. Zero / multiple non-self mentions are
42
+ * ambiguous, so we add no forced @ (avoids spamming unrelated members).
43
+ *
44
+ * Group-only: bot-at-bot @ delivery semantics don't apply to DMs.
45
+ */
46
+ export declare function resolveBotPeerForMention(params: {
47
+ isGroup: boolean;
48
+ senderIsBot?: boolean;
49
+ senderId?: string;
50
+ senderName?: string;
51
+ mentions: MentionInfo[];
52
+ botOpenId?: string;
53
+ }): BotPeerTarget | undefined;
54
+ export interface FeishuReplyRouting {
55
+ /** Whether to send the reply as a thread-scoped message. */
56
+ replyInThread: boolean;
57
+ /** Effective thread_id when replying in-thread; undefined otherwise. */
58
+ threadId: string | undefined;
59
+ /** True when the peer is a bot in a group chat: suppress thread-mode reply
60
+ * so the message lands in the main chat (avoiding the hidden topic view,
61
+ * #32980). Consumers may also use this signal for additional bot-peer-
62
+ * specific behavior (e.g. ensureMention in outbound-mention). */
63
+ suppressForBotPeer: boolean;
64
+ }
65
+ /**
66
+ * Resolve reply routing for the current dispatch, performing two tasks:
67
+ *
68
+ * 1. **Topic-group thread inference (may mutate `dc`).** In topic groups
69
+ * (chat_mode=topic), reply events may carry `root_id` without
70
+ * `thread_id`. When `threadSession` is enabled and the chat is
71
+ * thread-capable, treat `root_id` as a synthetic `threadId` so replies
72
+ * stay inside the topic instead of creating a new top-level message.
73
+ * This step mutates `dc.isThread` and `dc.ctx.threadId` so subsequent
74
+ * code (session-key resolution, sentinel scoping, history scoping)
75
+ * observes the same routing decision.
76
+ *
77
+ * 2. **Reply routing decision (pure).** Computes `replyInThread` and
78
+ * `suppressForBotPeer` from the post-inference state. In bot→bot group
79
+ * chats `replyInThread` is forced to `false` regardless of the inbound
80
+ * shape, preventing the topic-view trap.
81
+ */
82
+ export declare function resolveFeishuReplyRouting(dc: DispatchContext, opts?: {
83
+ replyInThreadConfig?: boolean;
84
+ }): Promise<FeishuReplyRouting>;
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Reply-routing decisions for the Feishu dispatch path.
7
+ *
8
+ * In bot-to-bot group scenarios, Feishu will pull thread-style replies into
9
+ * a hidden "topic view" that group members cannot see (#32980). The peer bot
10
+ * keeps receiving messages but humans in the chat see nothing — a silent
11
+ * failure mode that turns bot↔bot chat into a black hole.
12
+ *
13
+ * This module centralizes the three signals that decide where a reply lands:
14
+ * 1. isGroup — DMs never have the topic-view trap
15
+ * 2. senderIsBot — only bot→bot triggers it
16
+ * 3. dc.isThread — inbound was a thread reply (also inferred from
17
+ * root_id in topic groups when threadSession=true)
18
+ *
19
+ * Output: a routing object consumed by every outbound call site (main
20
+ * dispatcher + i18n command card + i18n command text fallback), so the
21
+ * three call sites never drift out of sync again.
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.resolveBotPeerForMention = resolveBotPeerForMention;
25
+ exports.resolveFeishuReplyRouting = resolveFeishuReplyRouting;
26
+ const chat_info_cache_1 = require("../../core/chat-info-cache.js");
27
+ const lark_logger_1 = require("../../core/lark-logger.js");
28
+ const log = (0, lark_logger_1.larkLogger)('inbound/bot-content');
29
+ /**
30
+ * Decide which peer (if any) an outbound reply must be guaranteed to
31
+ * @-mention, so the deterministic `ensureMention` backstop can wake them up.
32
+ *
33
+ * Deliberately INDEPENDENT of `suppressForBotPeer` (which only governs
34
+ * thread-vs-main routing): the addressee must be resolvable even on a
35
+ * human-orchestrated kickoff, where the triggering sender is a person but the
36
+ * conversation is meant to continue between bots.
37
+ *
38
+ * 1. Bot sender → @ the sender back, continuing the exchange.
39
+ * 2. Otherwise (e.g. a human kicking off a bot debate) → if the inbound
40
+ * message @-mentions exactly ONE party other than ourselves, treat that
41
+ * party as the designated peer. Zero / multiple non-self mentions are
42
+ * ambiguous, so we add no forced @ (avoids spamming unrelated members).
43
+ *
44
+ * Group-only: bot-at-bot @ delivery semantics don't apply to DMs.
45
+ */
46
+ function resolveBotPeerForMention(params) {
47
+ if (!params.isGroup)
48
+ return undefined;
49
+ // 1. Bot sender → keep the ping-pong going by @-ing them back.
50
+ if (params.senderIsBot && params.senderId) {
51
+ return { peerOpenId: params.senderId, peerName: params.senderName ?? params.senderId };
52
+ }
53
+ // 2. Human-orchestrated kickoff → the single non-self @-mentioned party.
54
+ const seen = new Set();
55
+ const others = [];
56
+ for (const m of params.mentions) {
57
+ if (!m.openId || m.isBot || m.openId === params.botOpenId)
58
+ continue;
59
+ if (seen.has(m.openId))
60
+ continue;
61
+ seen.add(m.openId);
62
+ others.push(m);
63
+ }
64
+ if (others.length === 1) {
65
+ return { peerOpenId: others[0].openId, peerName: others[0].name || others[0].openId };
66
+ }
67
+ return undefined;
68
+ }
69
+ /**
70
+ * Resolve reply routing for the current dispatch, performing two tasks:
71
+ *
72
+ * 1. **Topic-group thread inference (may mutate `dc`).** In topic groups
73
+ * (chat_mode=topic), reply events may carry `root_id` without
74
+ * `thread_id`. When `threadSession` is enabled and the chat is
75
+ * thread-capable, treat `root_id` as a synthetic `threadId` so replies
76
+ * stay inside the topic instead of creating a new top-level message.
77
+ * This step mutates `dc.isThread` and `dc.ctx.threadId` so subsequent
78
+ * code (session-key resolution, sentinel scoping, history scoping)
79
+ * observes the same routing decision.
80
+ *
81
+ * 2. **Reply routing decision (pure).** Computes `replyInThread` and
82
+ * `suppressForBotPeer` from the post-inference state. In bot→bot group
83
+ * chats `replyInThread` is forced to `false` regardless of the inbound
84
+ * shape, preventing the topic-view trap.
85
+ */
86
+ async function resolveFeishuReplyRouting(dc, opts = {}) {
87
+ // Step 1: topic-group thread inference (async + side effects on dc)
88
+ if (!dc.isThread &&
89
+ dc.isGroup &&
90
+ dc.ctx.rootId &&
91
+ dc.account.config?.threadSession === true) {
92
+ const threadCapable = await (0, chat_info_cache_1.isThreadCapableGroup)({
93
+ cfg: dc.accountScopedCfg,
94
+ chatId: dc.ctx.chatId,
95
+ accountId: dc.account.accountId,
96
+ });
97
+ if (threadCapable) {
98
+ log.info(`inferred thread from root_id=${dc.ctx.rootId} in topic group ${dc.ctx.chatId}`);
99
+ dc.isThread = true;
100
+ dc.ctx = { ...dc.ctx, threadId: dc.ctx.rootId };
101
+ }
102
+ }
103
+ // Step 2: bot-peer suppression decision (pure read of dc state).
104
+ //
105
+ // We force a bot→bot reply out of the thread only when it would otherwise
106
+ // snowball an *auto-detected* threadReply into a hidden topic view (#32980).
107
+ // Two escape hatches keep parity with openclaw core (PR #89783):
108
+ // - isTopicSession: a deliberate topic session (threadSession enabled +
109
+ // inbound is in a thread) is human-visible by design — keep it threaded.
110
+ // - replyInThread config: operators can opt in per-group/account.
111
+ const isTopicSession = dc.isThread && dc.account.config?.threadSession === true;
112
+ const configReplyInThread = opts.replyInThreadConfig === true;
113
+ const suppressForBotPeer = dc.isGroup && !!dc.ctx.senderIsBot && !isTopicSession && !configReplyInThread;
114
+ const replyInThread = !suppressForBotPeer && dc.isThread;
115
+ const threadId = replyInThread ? dc.ctx.threadId : undefined;
116
+ return { replyInThread, threadId, suppressForBotPeer };
117
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Cross-bot loop guard for bot-at-bot (ping-pong) conversations.
6
+ *
7
+ * Background: when two different bots @-mention each other in a group, each
8
+ * reply wakes the other, which replies again — an endless debate. The
9
+ * existing self-echo filter only drops a bot's *own* echo; it does nothing
10
+ * for A↔B loops. This module adds a deterministic hard brake: count the
11
+ * consecutive turns whose sender is a bot per (chat, thread), and stop
12
+ * auto-replying once the count exceeds a cap. Any human turn resets the
13
+ * counter, so a new human-driven exchange starts fresh.
14
+ *
15
+ * State is process-local and best-effort (each bot process keeps its own
16
+ * counter for the peer's messages it receives). Idle conversations decay so
17
+ * a long-quiet chat doesn't carry a stale count into a new exchange.
18
+ */
19
+ /** Max consecutive bot-originated turns before auto-reply is suppressed. */
20
+ export declare const MAX_CONSECUTIVE_BOT_TURNS = 10;
21
+ /** Idle window after which a conversation's counter is considered stale. */
22
+ export declare const BOT_LOOP_IDLE_RESET_MS: number;
23
+ export interface BotTurnVerdict {
24
+ /** False once the consecutive bot-turn count exceeds the cap. */
25
+ allowed: boolean;
26
+ /** The current consecutive bot-turn count after this turn. */
27
+ count: number;
28
+ /** The configured cap, for logging. */
29
+ limit: number;
30
+ }
31
+ /**
32
+ * Record one bot-originated turn for the given conversation and decide
33
+ * whether the bot should still auto-reply.
34
+ *
35
+ * Increments the consecutive-bot-turn counter (resetting first if the
36
+ * conversation has been idle past the decay window), then returns
37
+ * `allowed: false` once the count exceeds {@link MAX_CONSECUTIVE_BOT_TURNS}.
38
+ */
39
+ export declare function noteBotTurnAndCheck(chatId: string, threadId?: string, now?: number): BotTurnVerdict;
40
+ /**
41
+ * Reset the consecutive bot-turn counter for a conversation. Called on every
42
+ * human turn so a human stepping in always re-arms the debate budget.
43
+ */
44
+ export declare function resetBotLoop(chatId: string, threadId?: string): void;
45
+ /** Clear all loop state. Intended for tests. */
46
+ export declare function resetAllBotLoops(): void;
47
+ /** Number of tracked conversations. Intended for tests. */
48
+ export declare function botLoopStateSize(): number;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Cross-bot loop guard for bot-at-bot (ping-pong) conversations.
7
+ *
8
+ * Background: when two different bots @-mention each other in a group, each
9
+ * reply wakes the other, which replies again — an endless debate. The
10
+ * existing self-echo filter only drops a bot's *own* echo; it does nothing
11
+ * for A↔B loops. This module adds a deterministic hard brake: count the
12
+ * consecutive turns whose sender is a bot per (chat, thread), and stop
13
+ * auto-replying once the count exceeds a cap. Any human turn resets the
14
+ * counter, so a new human-driven exchange starts fresh.
15
+ *
16
+ * State is process-local and best-effort (each bot process keeps its own
17
+ * counter for the peer's messages it receives). Idle conversations decay so
18
+ * a long-quiet chat doesn't carry a stale count into a new exchange.
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.BOT_LOOP_IDLE_RESET_MS = exports.MAX_CONSECUTIVE_BOT_TURNS = void 0;
22
+ exports.noteBotTurnAndCheck = noteBotTurnAndCheck;
23
+ exports.resetBotLoop = resetBotLoop;
24
+ exports.resetAllBotLoops = resetAllBotLoops;
25
+ exports.botLoopStateSize = botLoopStateSize;
26
+ /** Max consecutive bot-originated turns before auto-reply is suppressed. */
27
+ exports.MAX_CONSECUTIVE_BOT_TURNS = 10;
28
+ /** Idle window after which a conversation's counter is considered stale. */
29
+ exports.BOT_LOOP_IDLE_RESET_MS = 10 * 60 * 1000; // 10 min
30
+ // `${chatId}:${threadId ?? ''}` -> consecutive bot-turn state
31
+ const states = new Map();
32
+ // Timestamp of the last stale-entry sweep, to bound sweep frequency.
33
+ let lastSweepAt = 0;
34
+ function loopKey(chatId, threadId) {
35
+ return `${chatId}:${threadId ?? ''}`;
36
+ }
37
+ /**
38
+ * Evict entries idle past the decay window. Called opportunistically from
39
+ * noteBotTurnAndCheck (at most once per idle window) so the Map can't grow
40
+ * unbounded for bot-only chats that never see a human turn to reset them.
41
+ * Dropping a stale entry is equivalent to leaving it: the next access would
42
+ * reset its count to 1 via the freshness check anyway.
43
+ */
44
+ function sweepStale(now) {
45
+ if (now - lastSweepAt < exports.BOT_LOOP_IDLE_RESET_MS)
46
+ return;
47
+ lastSweepAt = now;
48
+ for (const [key, state] of states) {
49
+ if (now - state.updatedAt > exports.BOT_LOOP_IDLE_RESET_MS)
50
+ states.delete(key);
51
+ }
52
+ }
53
+ /**
54
+ * Record one bot-originated turn for the given conversation and decide
55
+ * whether the bot should still auto-reply.
56
+ *
57
+ * Increments the consecutive-bot-turn counter (resetting first if the
58
+ * conversation has been idle past the decay window), then returns
59
+ * `allowed: false` once the count exceeds {@link MAX_CONSECUTIVE_BOT_TURNS}.
60
+ */
61
+ function noteBotTurnAndCheck(chatId, threadId, now = Date.now()) {
62
+ sweepStale(now);
63
+ const key = loopKey(chatId, threadId);
64
+ const prev = states.get(key);
65
+ const fresh = prev && now - prev.updatedAt <= exports.BOT_LOOP_IDLE_RESET_MS;
66
+ const count = (fresh ? prev.count : 0) + 1;
67
+ states.set(key, { count, updatedAt: now });
68
+ return {
69
+ allowed: count <= exports.MAX_CONSECUTIVE_BOT_TURNS,
70
+ count,
71
+ limit: exports.MAX_CONSECUTIVE_BOT_TURNS,
72
+ };
73
+ }
74
+ /**
75
+ * Reset the consecutive bot-turn counter for a conversation. Called on every
76
+ * human turn so a human stepping in always re-arms the debate budget.
77
+ */
78
+ function resetBotLoop(chatId, threadId) {
79
+ states.delete(loopKey(chatId, threadId));
80
+ }
81
+ /** Clear all loop state. Intended for tests. */
82
+ function resetAllBotLoops() {
83
+ states.clear();
84
+ lastSweepAt = 0;
85
+ }
86
+ /** Number of tracked conversations. Intended for tests. */
87
+ function botLoopStateSize() {
88
+ return states.size;
89
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Drive comment event context resolution.
6
+ *
7
+ * Resolves the full context for a `drive.notice.comment_add_v1` event:
8
+ * document title, comment quoted text, and reply chain.
9
+ */
10
+ import type { ClawdbotConfig } from 'openclaw/plugin-sdk';
11
+ import type { FeishuDriveCommentEvent } from '../types';
12
+ /** Resolved context for a Drive comment event. */
13
+ export interface CommentEventTurn {
14
+ /** Document title (best-effort, may be undefined). */
15
+ docTitle?: string;
16
+ /** File type of the document. */
17
+ fileType: string;
18
+ /** File token of the document. */
19
+ fileToken: string;
20
+ /** Root comment ID. */
21
+ commentId: string;
22
+ /** Reply ID (if this event is a reply). */
23
+ replyId?: string;
24
+ /** Quoted text from the comment (the content being commented on). */
25
+ quotedText?: string;
26
+ /** The text of the triggering comment/reply. */
27
+ commentText?: string;
28
+ /** Reply chain context (previous replies in the thread). */
29
+ replyChainContext?: string;
30
+ /** Whether the bot was @-mentioned. */
31
+ isMentioned?: boolean;
32
+ /** Whether the source comment is a whole-document comment. */
33
+ isWholeComment?: boolean;
34
+ /** Surface prompt for the agent (context + instructions). */
35
+ prompt: string;
36
+ /** Short preview of the prompt. */
37
+ preview: string;
38
+ }
39
+ /**
40
+ * Infer whether a Drive comment thread is a whole-document comment.
41
+ *
42
+ * The explicit `is_whole` flag is authoritative when present. When the API
43
+ * omits it, the root comment's quoted anchor is the best fallback signal:
44
+ * whole-document comments have no quote, while anchored comments do.
45
+ *
46
+ * Note that this inference is about the root thread, so it must behave the
47
+ * same for both root-comment events and reply events.
48
+ */
49
+ export declare function inferIsWholeComment(params: {
50
+ explicitIsWhole?: boolean;
51
+ quotedText?: string;
52
+ }): boolean;
53
+ /**
54
+ * Resolve the full context for a Drive comment event.
55
+ *
56
+ * Fetches document metadata, comment content, and reply chain.
57
+ */
58
+ export declare function resolveDriveCommentEventTurn(params: {
59
+ cfg: ClawdbotConfig;
60
+ event: FeishuDriveCommentEvent;
61
+ accountId?: string;
62
+ }): Promise<CommentEventTurn | null>;
63
+ /**
64
+ * Parse the raw webhook payload for a `drive.notice.comment_add_v1` event.
65
+ *
66
+ * The SDK flattens the v2 envelope, so the event data may be at the
67
+ * top level or nested under `event`. User info and timestamp live inside
68
+ * `notice_meta` in the real event structure, with fallback to top-level
69
+ * fields for compatibility with different SDK flattening styles.
70
+ */
71
+ /**
72
+ * Normalize a Drive comment event into a canonical shape.
73
+ *
74
+ * Real event structures vary:
75
+ * - **notice_meta style**: file_token, file_type, from_user_id, timestamp
76
+ * all live inside `notice_meta`; top-level only has comment_id/reply_id.
77
+ * - **SDK-flattened style**: fields may be hoisted to top level.
78
+ *
79
+ * This parser checks `notice_meta.*` first, then falls back to top-level
80
+ * fields, so the handler can consume a single canonical shape.
81
+ */
82
+ export declare function parseFeishuDriveCommentNoticeEventPayload(data: unknown): FeishuDriveCommentEvent | null;