@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,271 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Runtime store for structured tool-use steps.
7
+ *
8
+ * The Feishu card renderer reads from this store by session key so it can
9
+ * render observable, replayable tool execution without relying purely on
10
+ * reply payload text.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.startToolUseTraceRun = startToolUseTraceRun;
14
+ exports.clearToolUseTraceRun = clearToolUseTraceRun;
15
+ exports.hasToolUseTraceRun = hasToolUseTraceRun;
16
+ exports.recordToolUseStart = recordToolUseStart;
17
+ exports.recordToolUseEnd = recordToolUseEnd;
18
+ exports.getToolUseTraceSteps = getToolUseTraceSteps;
19
+ exports.sanitizeTraceValue = sanitizeTraceValue;
20
+ exports._resetForTesting = _resetForTesting;
21
+ const reasoning_utils_1 = require("./reasoning-utils.js");
22
+ const TRACE_TTL_MS = 30 * 60 * 1000;
23
+ const MAX_SESSION_TRACES = 128;
24
+ const MAX_STEPS_PER_SESSION = 256;
25
+ const STEP_RUNNING_TIMEOUT_MS = 5 * 60 * 1000;
26
+ const GENERIC_STRING_LIMIT = 512;
27
+ const RESULT_STRING_LIMIT = 1024;
28
+ const COMMAND_STRING_LIMIT = 4096;
29
+ const PATH_STRING_LIMIT = 2048;
30
+ const sessionTraces = new Map();
31
+ function startToolUseTraceRun(sessionKey) {
32
+ if (!sessionKey)
33
+ return;
34
+ pruneTraceStore();
35
+ sessionTraces.set(sessionKey, {
36
+ nextSeq: 1,
37
+ updatedAt: Date.now(),
38
+ steps: [],
39
+ currentRunId: undefined,
40
+ });
41
+ }
42
+ function clearToolUseTraceRun(sessionKey) {
43
+ if (!sessionKey)
44
+ return;
45
+ sessionTraces.delete(sessionKey);
46
+ }
47
+ function hasToolUseTraceRun(sessionKey) {
48
+ if (!sessionKey)
49
+ return false;
50
+ return sessionTraces.has(sessionKey);
51
+ }
52
+ function recordToolUseStart(params) {
53
+ const { sessionKey, toolName, toolParams, toolCallId, runId } = params;
54
+ if (!sessionKey || !toolName)
55
+ return;
56
+ const state = sessionTraces.get(sessionKey);
57
+ if (!state)
58
+ return;
59
+ if (runId) {
60
+ if (state.currentRunId === undefined) {
61
+ state.currentRunId = runId;
62
+ }
63
+ else if (state.currentRunId !== runId) {
64
+ return;
65
+ }
66
+ }
67
+ const now = Date.now();
68
+ if (state.steps.length >= MAX_STEPS_PER_SESSION) {
69
+ state.steps.splice(0, state.steps.length - MAX_STEPS_PER_SESSION + 1);
70
+ }
71
+ state.steps.push({
72
+ id: `${state.nextSeq}`,
73
+ seq: state.nextSeq,
74
+ toolName,
75
+ toolCallId: toolCallId || undefined,
76
+ runId: runId || undefined,
77
+ params: sanitizeTraceValue(toolParams, 0, { source: 'params' }),
78
+ status: 'running',
79
+ startedAt: now,
80
+ });
81
+ state.nextSeq += 1;
82
+ state.updatedAt = now;
83
+ }
84
+ function recordToolUseEnd(params) {
85
+ const { sessionKey, toolName, toolParams, toolCallId, runId, result, error, durationMs } = params;
86
+ if (!sessionKey || !toolName)
87
+ return;
88
+ const state = sessionTraces.get(sessionKey);
89
+ if (!state)
90
+ return;
91
+ if (runId && state.currentRunId !== undefined && state.currentRunId !== runId) {
92
+ return;
93
+ }
94
+ const now = Date.now();
95
+ const sanitizedParams = sanitizeTraceValue(toolParams, 0, { source: 'params' });
96
+ const pendingIndex = findPendingStepIndex(state.steps, toolName, sanitizedParams, toolCallId);
97
+ if (pendingIndex >= 0) {
98
+ const step = state.steps[pendingIndex];
99
+ if (!step)
100
+ return;
101
+ step.status = error ? 'error' : 'success';
102
+ step.result = sanitizeTraceValue(result, 0, { source: 'result' });
103
+ step.error = error ? (0, reasoning_utils_1.truncateText)(error, 160) : undefined;
104
+ step.durationMs = durationMs;
105
+ step.finishedAt = now;
106
+ if (!step.params && sanitizedParams) {
107
+ step.params = sanitizedParams;
108
+ }
109
+ state.updatedAt = now;
110
+ return;
111
+ }
112
+ state.steps.push({
113
+ id: `${state.nextSeq}`,
114
+ seq: state.nextSeq,
115
+ toolName,
116
+ toolCallId: toolCallId || undefined,
117
+ runId: runId || undefined,
118
+ params: sanitizedParams,
119
+ result: sanitizeTraceValue(result, 0, { source: 'result' }),
120
+ error: error ? (0, reasoning_utils_1.truncateText)(error, 160) : undefined,
121
+ durationMs,
122
+ status: error ? 'error' : 'success',
123
+ startedAt: now,
124
+ finishedAt: now,
125
+ });
126
+ state.nextSeq += 1;
127
+ state.updatedAt = now;
128
+ }
129
+ function getToolUseTraceSteps(sessionKey) {
130
+ if (!sessionKey)
131
+ return [];
132
+ const state = sessionTraces.get(sessionKey);
133
+ if (!state)
134
+ return [];
135
+ if (Date.now() - state.updatedAt > TRACE_TTL_MS) {
136
+ sessionTraces.delete(sessionKey);
137
+ return [];
138
+ }
139
+ const now = Date.now();
140
+ return state.steps.map((step) => {
141
+ if (step.status === 'running' && now - step.startedAt > STEP_RUNNING_TIMEOUT_MS) {
142
+ return { ...step, status: 'error', error: 'timed out', finishedAt: now };
143
+ }
144
+ return { ...step };
145
+ });
146
+ }
147
+ function findPendingStepIndex(steps, toolName, params, toolCallId) {
148
+ if (toolCallId) {
149
+ for (let index = steps.length - 1; index >= 0; index -= 1) {
150
+ const step = steps[index];
151
+ if (!step || step.status !== 'running')
152
+ continue;
153
+ if (step.toolCallId === toolCallId)
154
+ return index;
155
+ }
156
+ }
157
+ const normalizedToolName = (0, reasoning_utils_1.normalizeToolName)(toolName);
158
+ const paramsKey = fingerprintTraceValue(params);
159
+ for (let index = steps.length - 1; index >= 0; index -= 1) {
160
+ const step = steps[index];
161
+ if (!step || step.status !== 'running')
162
+ continue;
163
+ if ((0, reasoning_utils_1.normalizeToolName)(step.toolName) !== normalizedToolName)
164
+ continue;
165
+ if (fingerprintTraceValue(step.params) !== paramsKey)
166
+ continue;
167
+ return index;
168
+ }
169
+ for (let index = steps.length - 1; index >= 0; index -= 1) {
170
+ const step = steps[index];
171
+ if (!step || step.status !== 'running')
172
+ continue;
173
+ if ((0, reasoning_utils_1.normalizeToolName)(step.toolName) !== normalizedToolName)
174
+ continue;
175
+ return index;
176
+ }
177
+ return -1;
178
+ }
179
+ function pruneTraceStore() {
180
+ const now = Date.now();
181
+ for (const [sessionKey, state] of sessionTraces) {
182
+ if (now - state.updatedAt > TRACE_TTL_MS) {
183
+ sessionTraces.delete(sessionKey);
184
+ }
185
+ }
186
+ if (sessionTraces.size <= MAX_SESSION_TRACES)
187
+ return;
188
+ const overflow = sessionTraces.size - MAX_SESSION_TRACES;
189
+ const entries = [...sessionTraces.entries()].sort((a, b) => a[1].updatedAt - b[1].updatedAt);
190
+ for (const [sessionKey] of entries.slice(0, overflow)) {
191
+ sessionTraces.delete(sessionKey);
192
+ }
193
+ }
194
+ function sanitizeTraceValue(value, depth = 0, context = {}) {
195
+ if (value == null)
196
+ return undefined;
197
+ if (typeof value === 'string') {
198
+ const limit = resolveStringLimit(context);
199
+ return (0, reasoning_utils_1.truncateText)(sanitizeTraceString(value, context), limit);
200
+ }
201
+ if (typeof value === 'number' || typeof value === 'boolean')
202
+ return value;
203
+ if (depth >= 2)
204
+ return '[truncated]';
205
+ if (Array.isArray(value)) {
206
+ return value.slice(0, 8).map((item) => sanitizeTraceValue(item, depth + 1, { source: context.source }));
207
+ }
208
+ if (typeof value === 'object') {
209
+ const input = value;
210
+ const output = {};
211
+ for (const [key, entryValue] of Object.entries(input).slice(0, 12)) {
212
+ output[key] = isSensitiveKey(key)
213
+ ? '[redacted]'
214
+ : sanitizeTraceValue(entryValue, depth + 1, { source: context.source, key });
215
+ }
216
+ return output;
217
+ }
218
+ return (0, reasoning_utils_1.truncateText)(String(value), 180);
219
+ }
220
+ function sanitizeTraceString(value, context) {
221
+ const redactedUrl = redactUrlParams(value);
222
+ if (isCommandLikeKey(context.key)) {
223
+ return (0, reasoning_utils_1.redactInlineSecrets)(redactedUrl);
224
+ }
225
+ return redactedUrl;
226
+ }
227
+ function resolveStringLimit(context) {
228
+ const key = context.key?.toLowerCase() ?? '';
229
+ if (/(?:^|_)(?:command|script|description|prompt|task)(?:$|_)/.test(key)) {
230
+ return COMMAND_STRING_LIMIT;
231
+ }
232
+ if (/(?:^|_)(?:path|file|url|uri|cwd|folder|dir)(?:$|_)/.test(key)) {
233
+ return PATH_STRING_LIMIT;
234
+ }
235
+ if (context.source === 'result') {
236
+ return RESULT_STRING_LIMIT;
237
+ }
238
+ return GENERIC_STRING_LIMIT;
239
+ }
240
+ function isCommandLikeKey(key) {
241
+ const normalized = key?.toLowerCase() ?? '';
242
+ return /(?:^|_)(?:command|script)(?:$|_)/.test(normalized);
243
+ }
244
+ const SENSITIVE_KEY_RE = /secret|token|password|authorization|cookie|api[-_]?key|credential|private[-_]?key|access[-_]?key|database[-_]?url|connection[-_]?string|bearer|signing[-_]?key|encryption[-_]?key|session[-_]?id|client[-_]?secret|auth[-_]?token/i;
245
+ function isSensitiveKey(key) {
246
+ return SENSITIVE_KEY_RE.test(key);
247
+ }
248
+ function redactUrlParams(url) {
249
+ return url.replace(/([?&])(api_key|token|secret|key)=[^&]*/gi, '$1$2=[redacted]');
250
+ }
251
+ function fingerprintTraceValue(value) {
252
+ if (value == null)
253
+ return '';
254
+ if (typeof value !== 'object')
255
+ return String(value);
256
+ return JSON.stringify(sortTraceValue(value));
257
+ }
258
+ function sortTraceValue(value) {
259
+ if (Array.isArray(value))
260
+ return value.map((item) => sortTraceValue(item));
261
+ if (value && typeof value === 'object') {
262
+ return Object.fromEntries(Object.entries(value)
263
+ .sort(([left], [right]) => left.localeCompare(right))
264
+ .map(([key, entryValue]) => [key, sortTraceValue(entryValue)]));
265
+ }
266
+ return value;
267
+ }
268
+ /** @internal — test-only helper to reset module-level state between test cases. */
269
+ function _resetForTesting() {
270
+ sessionTraces.clear();
271
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Guard against operating on unavailable (deleted/recalled) messages.
6
+ *
7
+ * Encapsulates the terminateDueToUnavailable / shouldSkipForUnavailable
8
+ * logic previously scattered as closures in reply-dispatcher.ts.
9
+ */
10
+ export interface UnavailableGuardParams {
11
+ replyToMessageId: string | undefined;
12
+ getCardMessageId: () => string | null;
13
+ onTerminate: () => void;
14
+ }
15
+ export declare class UnavailableGuard {
16
+ private terminated;
17
+ private readonly replyToMessageId;
18
+ private readonly getCardMessageId;
19
+ private readonly onTerminate;
20
+ constructor(params: UnavailableGuardParams);
21
+ get isTerminated(): boolean;
22
+ /**
23
+ * Check whether the reply pipeline should skip further operations.
24
+ * Returns true if the message is already known to be unavailable.
25
+ */
26
+ shouldSkip(source: string): boolean;
27
+ /**
28
+ * Attempt to terminate the reply pipeline due to an unavailable message.
29
+ *
30
+ * @param source - Descriptive label for the caller (for logging).
31
+ * @param err - Optional error that triggered the check.
32
+ * @returns true if the pipeline was (or already had been) terminated.
33
+ */
34
+ terminate(source: string, err?: unknown): boolean;
35
+ }
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Guard against operating on unavailable (deleted/recalled) messages.
7
+ *
8
+ * Encapsulates the terminateDueToUnavailable / shouldSkipForUnavailable
9
+ * logic previously scattered as closures in reply-dispatcher.ts.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.UnavailableGuard = void 0;
13
+ const lark_logger_1 = require("../core/lark-logger.js");
14
+ const api_error_1 = require("../core/api-error.js");
15
+ const message_unavailable_1 = require("../core/message-unavailable.js");
16
+ const log = (0, lark_logger_1.larkLogger)('card/unavailable-guard');
17
+ // ---------------------------------------------------------------------------
18
+ // UnavailableGuard
19
+ // ---------------------------------------------------------------------------
20
+ class UnavailableGuard {
21
+ terminated = false;
22
+ replyToMessageId;
23
+ getCardMessageId;
24
+ onTerminate;
25
+ constructor(params) {
26
+ this.replyToMessageId = params.replyToMessageId;
27
+ this.getCardMessageId = params.getCardMessageId;
28
+ this.onTerminate = params.onTerminate;
29
+ }
30
+ get isTerminated() {
31
+ return this.terminated;
32
+ }
33
+ /**
34
+ * Check whether the reply pipeline should skip further operations.
35
+ * Returns true if the message is already known to be unavailable.
36
+ */
37
+ shouldSkip(source) {
38
+ if (this.terminated)
39
+ return true;
40
+ if (!this.replyToMessageId)
41
+ return false;
42
+ if (!(0, message_unavailable_1.isMessageUnavailable)(this.replyToMessageId))
43
+ return false;
44
+ return this.terminate(source);
45
+ }
46
+ /**
47
+ * Attempt to terminate the reply pipeline due to an unavailable message.
48
+ *
49
+ * @param source - Descriptive label for the caller (for logging).
50
+ * @param err - Optional error that triggered the check.
51
+ * @returns true if the pipeline was (or already had been) terminated.
52
+ */
53
+ terminate(source, err) {
54
+ if (this.terminated)
55
+ return true;
56
+ const fromError = (0, message_unavailable_1.isMessageUnavailableError)(err) ? err : undefined;
57
+ const cardMessageId = this.getCardMessageId();
58
+ const state = (0, message_unavailable_1.getMessageUnavailableState)(this.replyToMessageId) ?? (0, message_unavailable_1.getMessageUnavailableState)(cardMessageId ?? undefined);
59
+ let apiCode = fromError?.apiCode ?? state?.apiCode;
60
+ if (!apiCode && err) {
61
+ const detectedCode = (0, api_error_1.extractLarkApiCode)(err);
62
+ if ((0, message_unavailable_1.isTerminalMessageApiCode)(detectedCode)) {
63
+ const fallbackMessageId = this.replyToMessageId ?? cardMessageId ?? undefined;
64
+ if (fallbackMessageId) {
65
+ (0, message_unavailable_1.markMessageUnavailable)({
66
+ messageId: fallbackMessageId,
67
+ apiCode: detectedCode,
68
+ operation: source,
69
+ });
70
+ }
71
+ apiCode = detectedCode;
72
+ }
73
+ }
74
+ if (!apiCode)
75
+ return false;
76
+ this.terminated = true;
77
+ this.onTerminate();
78
+ const affectedMessageId = fromError?.messageId ?? this.replyToMessageId ?? cardMessageId ?? 'unknown';
79
+ log.warn('reply pipeline terminated by unavailable message', {
80
+ source,
81
+ apiCode,
82
+ messageId: affectedMessageId,
83
+ });
84
+ return true;
85
+ }
86
+ }
87
+ exports.UnavailableGuard = UnavailableGuard;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Abort trigger detection for the Lark/Feishu channel plugin.
6
+ *
7
+ * Provides a fast-path check to determine whether an inbound message is
8
+ * an abort/stop command *before* it enters the per-chat serial queue.
9
+ *
10
+ * The trigger word list and normalisation logic are copied from the
11
+ * OpenClaw core (`src/auto-reply/reply/abort.ts`) so the plugin can
12
+ * make a lightweight decision without importing the full reply pipeline.
13
+ * The message still flows through `tryFastAbortFromMessage()` for
14
+ * authoritative handling.
15
+ */
16
+ import type { FeishuMessageEvent } from '../messaging/types';
17
+ /** Exact trigger-word match (same logic as OpenClaw core `isAbortTrigger`). */
18
+ export declare function isAbortTrigger(text: string): boolean;
19
+ /**
20
+ * Extended abort detection: matches both bare trigger words and the
21
+ * `/stop` command form. Used by the monitor fast-path.
22
+ */
23
+ export declare function isLikelyAbortText(text: string): boolean;
24
+ /**
25
+ * Whether an inbound message expresses intent to stop / interrupt the ongoing
26
+ * (bot-to-bot) exchange. Superset of {@link isLikelyAbortText} plus the
27
+ * conversational phrases above.
28
+ *
29
+ * Two consumers: (1) suppress the deterministic peer-@ backstop so a stop
30
+ * acknowledgement doesn't re-wake the peer bot; (2) mute an active bot loop so
31
+ * the in-flight ping-pong drains instead of being re-armed. Substring match —
32
+ * keep the list distinctive (no bare "停"/"stop") to limit false positives;
33
+ * the worst case is a missed forced-@ or a self-healing mute (any normal
34
+ * message lifts it).
35
+ */
36
+ export declare function isConversationStopIntent(text: string): boolean;
37
+ /**
38
+ * Extract the raw text payload from a Feishu message event.
39
+ *
40
+ * Only handles `text` type messages. The `message.content` field is a
41
+ * JSON string like `{"text":"hello"}`. Returns `undefined` for
42
+ * non-text messages or parse failures.
43
+ *
44
+ * In group chats, bot mention placeholders (`@_user_N`) are stripped so
45
+ * a message like `@Bot stop` is detected as `stop`.
46
+ */
47
+ export declare function extractRawTextFromEvent(event: FeishuMessageEvent): string | undefined;
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Abort trigger detection for the Lark/Feishu channel plugin.
7
+ *
8
+ * Provides a fast-path check to determine whether an inbound message is
9
+ * an abort/stop command *before* it enters the per-chat serial queue.
10
+ *
11
+ * The trigger word list and normalisation logic are copied from the
12
+ * OpenClaw core (`src/auto-reply/reply/abort.ts`) so the plugin can
13
+ * make a lightweight decision without importing the full reply pipeline.
14
+ * The message still flows through `tryFastAbortFromMessage()` for
15
+ * authoritative handling.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.isAbortTrigger = isAbortTrigger;
19
+ exports.isLikelyAbortText = isLikelyAbortText;
20
+ exports.isConversationStopIntent = isConversationStopIntent;
21
+ exports.extractRawTextFromEvent = extractRawTextFromEvent;
22
+ // ---------------------------------------------------------------------------
23
+ // Trigger word list (synced with OpenClaw core abort.ts)
24
+ // ---------------------------------------------------------------------------
25
+ const ABORT_TRIGGERS = new Set([
26
+ 'stop',
27
+ 'esc',
28
+ 'abort',
29
+ 'wait',
30
+ 'exit',
31
+ 'interrupt',
32
+ 'detente',
33
+ 'deten',
34
+ 'detén',
35
+ 'arrete',
36
+ 'arrête',
37
+ '停止',
38
+ 'やめて',
39
+ '止めて',
40
+ 'रुको',
41
+ 'توقف',
42
+ 'стоп',
43
+ 'остановись',
44
+ 'останови',
45
+ 'остановить',
46
+ 'прекрати',
47
+ 'halt',
48
+ 'anhalten',
49
+ 'aufhören',
50
+ 'hoer auf',
51
+ 'stopp',
52
+ 'pare',
53
+ 'stop openclaw',
54
+ 'openclaw stop',
55
+ 'stop action',
56
+ 'stop current action',
57
+ 'stop run',
58
+ 'stop current run',
59
+ 'stop agent',
60
+ 'stop the agent',
61
+ "stop don't do anything",
62
+ 'stop dont do anything',
63
+ 'stop do not do anything',
64
+ 'stop doing anything',
65
+ 'do not do that',
66
+ 'please stop',
67
+ 'stop please',
68
+ ]);
69
+ // ---------------------------------------------------------------------------
70
+ // Normalisation helpers
71
+ // ---------------------------------------------------------------------------
72
+ const TRAILING_ABORT_PUNCTUATION_RE = /[.!?…,,。;;::'"'")\]}]+$/u;
73
+ function normalizeAbortTriggerText(text) {
74
+ return text
75
+ .trim()
76
+ .toLowerCase()
77
+ .replace(/['`]/g, "'")
78
+ .replace(/\s+/g, ' ')
79
+ .replace(TRAILING_ABORT_PUNCTUATION_RE, '')
80
+ .trim();
81
+ }
82
+ // ---------------------------------------------------------------------------
83
+ // Public API
84
+ // ---------------------------------------------------------------------------
85
+ /** Exact trigger-word match (same logic as OpenClaw core `isAbortTrigger`). */
86
+ function isAbortTrigger(text) {
87
+ if (!text)
88
+ return false;
89
+ const normalized = normalizeAbortTriggerText(text);
90
+ return ABORT_TRIGGERS.has(normalized);
91
+ }
92
+ /**
93
+ * Extended abort detection: matches both bare trigger words and the
94
+ * `/stop` command form. Used by the monitor fast-path.
95
+ */
96
+ function isLikelyAbortText(text) {
97
+ if (!text)
98
+ return false;
99
+ const trimmed = text.trim().toLowerCase();
100
+ if (trimmed === '/stop')
101
+ return true;
102
+ return isAbortTrigger(trimmed);
103
+ }
104
+ // ---------------------------------------------------------------------------
105
+ // Conversation stop-intent (broader than the exact abort triggers)
106
+ // ---------------------------------------------------------------------------
107
+ /**
108
+ * Conversational "please stop / interrupt this exchange" phrases.
109
+ *
110
+ * Deliberately SEPARATE from {@link ABORT_TRIGGERS} (which is synced word-for-
111
+ * word with OpenClaw core and matched by exact equality, e.g. `/stop`). These
112
+ * are matched by substring so natural phrasings like "中断对话" or "stop
113
+ * talking" are caught. The list is intentionally distinctive to avoid false
114
+ * positives — a false positive only means we skip the deterministic peer-@
115
+ * backstop for that turn (the model can still @ on its own), which is mild.
116
+ */
117
+ const STOP_INTENT_PHRASES = [
118
+ // zh — stop / terminate / pause
119
+ '中断',
120
+ '中止',
121
+ '终止',
122
+ '停止',
123
+ '停下',
124
+ '停一下',
125
+ '暂停',
126
+ '打住',
127
+ '停手',
128
+ '收手',
129
+ // zh — "don't keep going / replying"
130
+ '别聊',
131
+ '别说了',
132
+ '别回复',
133
+ '别继续',
134
+ '别再聊',
135
+ '别再说',
136
+ '别吵',
137
+ '别争',
138
+ '不要回复',
139
+ '不要继续',
140
+ '不用回复',
141
+ '不用继续',
142
+ // zh — "wrap up / be quiet"
143
+ '结束对话',
144
+ '结束讨论',
145
+ '结束辩论',
146
+ '到此为止',
147
+ '闭嘴',
148
+ // en
149
+ 'stop talking',
150
+ 'stop chatting',
151
+ 'stop debating',
152
+ 'stop the debate',
153
+ 'stop the conversation',
154
+ 'stop this conversation',
155
+ 'stop responding',
156
+ 'stop replying',
157
+ 'end the conversation',
158
+ 'end conversation',
159
+ 'end the debate',
160
+ 'shut up',
161
+ 'be quiet',
162
+ 'cut it out',
163
+ 'knock it off',
164
+ 'wrap it up',
165
+ 'stand down',
166
+ ];
167
+ /**
168
+ * Whether an inbound message expresses intent to stop / interrupt the ongoing
169
+ * (bot-to-bot) exchange. Superset of {@link isLikelyAbortText} plus the
170
+ * conversational phrases above.
171
+ *
172
+ * Two consumers: (1) suppress the deterministic peer-@ backstop so a stop
173
+ * acknowledgement doesn't re-wake the peer bot; (2) mute an active bot loop so
174
+ * the in-flight ping-pong drains instead of being re-armed. Substring match —
175
+ * keep the list distinctive (no bare "停"/"stop") to limit false positives;
176
+ * the worst case is a missed forced-@ or a self-healing mute (any normal
177
+ * message lifts it).
178
+ */
179
+ function isConversationStopIntent(text) {
180
+ if (!text)
181
+ return false;
182
+ // Drop bot mention placeholders so "@Bot 中断对话" → "中断对话".
183
+ const normalized = text
184
+ .replace(/@_user_\d+/g, '')
185
+ .trim()
186
+ .toLowerCase();
187
+ if (!normalized)
188
+ return false;
189
+ if (isLikelyAbortText(normalized))
190
+ return true;
191
+ return STOP_INTENT_PHRASES.some((p) => normalized.includes(p));
192
+ }
193
+ /**
194
+ * Extract the raw text payload from a Feishu message event.
195
+ *
196
+ * Only handles `text` type messages. The `message.content` field is a
197
+ * JSON string like `{"text":"hello"}`. Returns `undefined` for
198
+ * non-text messages or parse failures.
199
+ *
200
+ * In group chats, bot mention placeholders (`@_user_N`) are stripped so
201
+ * a message like `@Bot stop` is detected as `stop`.
202
+ */
203
+ function extractRawTextFromEvent(event) {
204
+ if (!event.message || event.message.message_type !== 'text') {
205
+ return undefined;
206
+ }
207
+ try {
208
+ const parsed = JSON.parse(event.message.content);
209
+ let text = parsed?.text;
210
+ if (typeof text !== 'string')
211
+ return undefined;
212
+ // Strip bot mention placeholders (@_user_1, @_user_2, etc.)
213
+ text = text.replace(/@_user_\d+/g, '').trim();
214
+ return text || undefined;
215
+ }
216
+ catch {
217
+ return undefined;
218
+ }
219
+ }