@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.
- package/LICENSE +21 -0
- package/README.md +76 -0
- package/bin/openclaw-lark.js +39 -0
- package/index.d.ts +36 -0
- package/index.js +188 -0
- package/openclaw.plugin.json +64 -0
- package/package.json +63 -0
- package/secret-contract-api.d.ts +15 -0
- package/secret-contract-api.js +78 -0
- package/skills/feishu-bitable/SKILL.md +248 -0
- package/skills/feishu-bitable/references/examples.md +813 -0
- package/skills/feishu-bitable/references/field-properties.md +763 -0
- package/skills/feishu-bitable/references/record-values.md +911 -0
- package/skills/feishu-calendar/SKILL.md +242 -0
- package/skills/feishu-channel-rules/SKILL.md +18 -0
- package/skills/feishu-channel-rules/references/markdown-syntax.md +138 -0
- package/skills/feishu-create-doc/SKILL.md +719 -0
- package/skills/feishu-fetch-doc/SKILL.md +93 -0
- package/skills/feishu-im-read/SKILL.md +163 -0
- package/skills/feishu-task/SKILL.md +340 -0
- package/skills/feishu-troubleshoot/SKILL.md +70 -0
- package/skills/feishu-update-doc/SKILL.md +285 -0
- package/src/card/builder.d.ts +152 -0
- package/src/card/builder.js +794 -0
- package/src/card/card-error.d.ts +91 -0
- package/src/card/card-error.js +206 -0
- package/src/card/cardkit.d.ts +90 -0
- package/src/card/cardkit.js +203 -0
- package/src/card/flush-controller.d.ts +45 -0
- package/src/card/flush-controller.js +138 -0
- package/src/card/image-resolver.d.ts +45 -0
- package/src/card/image-resolver.js +116 -0
- package/src/card/markdown-style.d.ts +16 -0
- package/src/card/markdown-style.js +106 -0
- package/src/card/reasoning-utils.d.ts +14 -0
- package/src/card/reasoning-utils.js +64 -0
- package/src/card/reply-dispatcher-types.d.ts +132 -0
- package/src/card/reply-dispatcher-types.js +61 -0
- package/src/card/reply-dispatcher.d.ts +15 -0
- package/src/card/reply-dispatcher.js +447 -0
- package/src/card/reply-mode.d.ts +41 -0
- package/src/card/reply-mode.js +70 -0
- package/src/card/streaming-card-controller.d.ts +118 -0
- package/src/card/streaming-card-controller.js +1045 -0
- package/src/card/tool-use-config.d.ts +26 -0
- package/src/card/tool-use-config.js +76 -0
- package/src/card/tool-use-display.d.ts +37 -0
- package/src/card/tool-use-display.js +476 -0
- package/src/card/tool-use-trace-store.d.ts +51 -0
- package/src/card/tool-use-trace-store.js +271 -0
- package/src/card/unavailable-guard.d.ts +35 -0
- package/src/card/unavailable-guard.js +87 -0
- package/src/channel/abort-detect.d.ts +47 -0
- package/src/channel/abort-detect.js +219 -0
- package/src/channel/chat-queue.d.ts +41 -0
- package/src/channel/chat-queue.js +68 -0
- package/src/channel/config-adapter.d.ts +23 -0
- package/src/channel/config-adapter.js +107 -0
- package/src/channel/directory.d.ts +57 -0
- package/src/channel/directory.js +197 -0
- package/src/channel/event-handlers.d.ts +17 -0
- package/src/channel/event-handlers.js +380 -0
- package/src/channel/interactive-dispatch.d.ts +59 -0
- package/src/channel/interactive-dispatch.js +195 -0
- package/src/channel/monitor.d.ts +17 -0
- package/src/channel/monitor.js +140 -0
- package/src/channel/onboarding-config.d.ts +18 -0
- package/src/channel/onboarding-config.js +96 -0
- package/src/channel/onboarding-migrate.d.ts +25 -0
- package/src/channel/onboarding-migrate.js +70 -0
- package/src/channel/onboarding.d.ts +12 -0
- package/src/channel/onboarding.js +300 -0
- package/src/channel/plugin.d.ts +13 -0
- package/src/channel/plugin.js +310 -0
- package/src/channel/probe.d.ts +14 -0
- package/src/channel/probe.js +24 -0
- package/src/channel/types.d.ts +37 -0
- package/src/channel/types.js +8 -0
- package/src/commands/auth.d.ts +21 -0
- package/src/commands/auth.js +165 -0
- package/src/commands/diagnose.d.ts +69 -0
- package/src/commands/diagnose.js +848 -0
- package/src/commands/doctor.d.ts +27 -0
- package/src/commands/doctor.js +588 -0
- package/src/commands/index.d.ts +25 -0
- package/src/commands/index.js +219 -0
- package/src/commands/locale.d.ts +7 -0
- package/src/commands/locale.js +8 -0
- package/src/core/accounts.d.ts +51 -0
- package/src/core/accounts.js +219 -0
- package/src/core/agent-config.d.ts +100 -0
- package/src/core/agent-config.js +148 -0
- package/src/core/api-error.d.ts +48 -0
- package/src/core/api-error.js +117 -0
- package/src/core/app-owner-fallback.d.ts +22 -0
- package/src/core/app-owner-fallback.js +39 -0
- package/src/core/app-scope-checker.d.ts +87 -0
- package/src/core/app-scope-checker.js +198 -0
- package/src/core/auth-errors.d.ts +144 -0
- package/src/core/auth-errors.js +160 -0
- package/src/core/card-action-operator.d.ts +33 -0
- package/src/core/card-action-operator.js +30 -0
- package/src/core/chat-info-cache.d.ts +67 -0
- package/src/core/chat-info-cache.js +165 -0
- package/src/core/comment-target.d.ts +65 -0
- package/src/core/comment-target.js +100 -0
- package/src/core/config-schema.d.ts +490 -0
- package/src/core/config-schema.js +223 -0
- package/src/core/device-flow.d.ts +77 -0
- package/src/core/device-flow.js +217 -0
- package/src/core/domains.d.ts +18 -0
- package/src/core/domains.js +34 -0
- package/src/core/feishu-fetch.d.ts +18 -0
- package/src/core/feishu-fetch.js +28 -0
- package/src/core/footer-config.d.ts +24 -0
- package/src/core/footer-config.js +51 -0
- package/src/core/lark-client.d.ts +125 -0
- package/src/core/lark-client.js +468 -0
- package/src/core/lark-logger.d.ts +23 -0
- package/src/core/lark-logger.js +160 -0
- package/src/core/lark-ticket.d.ts +29 -0
- package/src/core/lark-ticket.js +40 -0
- package/src/core/message-unavailable.d.ts +53 -0
- package/src/core/message-unavailable.js +142 -0
- package/src/core/owner-policy.d.ts +32 -0
- package/src/core/owner-policy.js +55 -0
- package/src/core/permission-url.d.ts +22 -0
- package/src/core/permission-url.js +76 -0
- package/src/core/raw-request.d.ts +27 -0
- package/src/core/raw-request.js +90 -0
- package/src/core/runtime-store.d.ts +13 -0
- package/src/core/runtime-store.js +29 -0
- package/src/core/scope-manager.d.ts +168 -0
- package/src/core/scope-manager.js +224 -0
- package/src/core/sdk-compat.d.ts +20 -0
- package/src/core/sdk-compat.js +28 -0
- package/src/core/security-check.d.ts +72 -0
- package/src/core/security-check.js +184 -0
- package/src/core/shutdown-hooks.d.ts +22 -0
- package/src/core/shutdown-hooks.js +61 -0
- package/src/core/synthetic-target.d.ts +33 -0
- package/src/core/synthetic-target.js +40 -0
- package/src/core/targets.d.ts +60 -0
- package/src/core/targets.js +173 -0
- package/src/core/token-store.d.ts +54 -0
- package/src/core/token-store.js +326 -0
- package/src/core/tool-client.d.ts +176 -0
- package/src/core/tool-client.js +426 -0
- package/src/core/tool-scopes.d.ts +156 -0
- package/src/core/tool-scopes.js +344 -0
- package/src/core/tools-config.d.ts +55 -0
- package/src/core/tools-config.js +143 -0
- package/src/core/types.d.ts +91 -0
- package/src/core/types.js +12 -0
- package/src/core/uat-client.d.ts +46 -0
- package/src/core/uat-client.js +192 -0
- package/src/core/version.d.ts +31 -0
- package/src/core/version.js +69 -0
- package/src/messaging/converters/audio.d.ts +8 -0
- package/src/messaging/converters/audio.js +24 -0
- package/src/messaging/converters/calendar.d.ts +13 -0
- package/src/messaging/converters/calendar.js +56 -0
- package/src/messaging/converters/content-converter-helpers.d.ts +30 -0
- package/src/messaging/converters/content-converter-helpers.js +82 -0
- package/src/messaging/converters/content-converter.d.ts +24 -0
- package/src/messaging/converters/content-converter.js +40 -0
- package/src/messaging/converters/file.d.ts +8 -0
- package/src/messaging/converters/file.js +24 -0
- package/src/messaging/converters/folder.d.ts +8 -0
- package/src/messaging/converters/folder.js +24 -0
- package/src/messaging/converters/hongbao.d.ts +8 -0
- package/src/messaging/converters/hongbao.js +20 -0
- package/src/messaging/converters/image.d.ts +8 -0
- package/src/messaging/converters/image.js +22 -0
- package/src/messaging/converters/index.d.ts +8 -0
- package/src/messaging/converters/index.js +53 -0
- package/src/messaging/converters/interactive/card-converter.d.ts +76 -0
- package/src/messaging/converters/interactive/card-converter.js +1177 -0
- package/src/messaging/converters/interactive/card-utils.d.ts +9 -0
- package/src/messaging/converters/interactive/card-utils.js +47 -0
- package/src/messaging/converters/interactive/index.d.ts +8 -0
- package/src/messaging/converters/interactive/index.js +25 -0
- package/src/messaging/converters/interactive/legacy.d.ts +11 -0
- package/src/messaging/converters/interactive/legacy.js +60 -0
- package/src/messaging/converters/interactive/types.d.ts +23 -0
- package/src/messaging/converters/interactive/types.js +27 -0
- package/src/messaging/converters/location.d.ts +8 -0
- package/src/messaging/converters/location.js +23 -0
- package/src/messaging/converters/merge-forward.d.ts +32 -0
- package/src/messaging/converters/merge-forward.js +235 -0
- package/src/messaging/converters/post.d.ts +11 -0
- package/src/messaging/converters/post.js +235 -0
- package/src/messaging/converters/share.d.ts +9 -0
- package/src/messaging/converters/share.js +28 -0
- package/src/messaging/converters/sticker.d.ts +8 -0
- package/src/messaging/converters/sticker.js +22 -0
- package/src/messaging/converters/system.d.ts +12 -0
- package/src/messaging/converters/system.js +36 -0
- package/src/messaging/converters/text.d.ts +8 -0
- package/src/messaging/converters/text.js +18 -0
- package/src/messaging/converters/todo.d.ts +8 -0
- package/src/messaging/converters/todo.js +45 -0
- package/src/messaging/converters/types.d.ts +114 -0
- package/src/messaging/converters/types.js +8 -0
- package/src/messaging/converters/unknown.d.ts +8 -0
- package/src/messaging/converters/unknown.js +20 -0
- package/src/messaging/converters/utils.d.ts +22 -0
- package/src/messaging/converters/utils.js +57 -0
- package/src/messaging/converters/video-chat.d.ts +8 -0
- package/src/messaging/converters/video-chat.js +31 -0
- package/src/messaging/converters/video.d.ts +8 -0
- package/src/messaging/converters/video.js +35 -0
- package/src/messaging/converters/vote.d.ts +8 -0
- package/src/messaging/converters/vote.js +28 -0
- package/src/messaging/inbound/bot-content.d.ts +84 -0
- package/src/messaging/inbound/bot-content.js +117 -0
- package/src/messaging/inbound/bot-loop-guard.d.ts +48 -0
- package/src/messaging/inbound/bot-loop-guard.js +89 -0
- package/src/messaging/inbound/comment-context.d.ts +82 -0
- package/src/messaging/inbound/comment-context.js +353 -0
- package/src/messaging/inbound/comment-handler.d.ts +30 -0
- package/src/messaging/inbound/comment-handler.js +269 -0
- package/src/messaging/inbound/dedup.d.ts +59 -0
- package/src/messaging/inbound/dedup.js +121 -0
- package/src/messaging/inbound/dispatch-builders.d.ts +104 -0
- package/src/messaging/inbound/dispatch-builders.js +241 -0
- package/src/messaging/inbound/dispatch-commands.d.ts +22 -0
- package/src/messaging/inbound/dispatch-commands.js +131 -0
- package/src/messaging/inbound/dispatch-context.d.ts +67 -0
- package/src/messaging/inbound/dispatch-context.js +153 -0
- package/src/messaging/inbound/dispatch.d.ts +50 -0
- package/src/messaging/inbound/dispatch.js +477 -0
- package/src/messaging/inbound/enrich.d.ts +102 -0
- package/src/messaging/inbound/enrich.js +236 -0
- package/src/messaging/inbound/gate-effects.d.ts +23 -0
- package/src/messaging/inbound/gate-effects.js +46 -0
- package/src/messaging/inbound/gate.d.ts +91 -0
- package/src/messaging/inbound/gate.js +342 -0
- package/src/messaging/inbound/handler-registry.d.ts +25 -0
- package/src/messaging/inbound/handler-registry.js +23 -0
- package/src/messaging/inbound/handler.d.ts +37 -0
- package/src/messaging/inbound/handler.js +286 -0
- package/src/messaging/inbound/media-resolver.d.ts +32 -0
- package/src/messaging/inbound/media-resolver.js +91 -0
- package/src/messaging/inbound/mention-registry.d.ts +59 -0
- package/src/messaging/inbound/mention-registry.js +115 -0
- package/src/messaging/inbound/mention.d.ts +48 -0
- package/src/messaging/inbound/mention.js +102 -0
- package/src/messaging/inbound/parse-io.d.ts +50 -0
- package/src/messaging/inbound/parse-io.js +86 -0
- package/src/messaging/inbound/parse.d.ts +28 -0
- package/src/messaging/inbound/parse.js +128 -0
- package/src/messaging/inbound/permission.d.ts +17 -0
- package/src/messaging/inbound/permission.js +44 -0
- package/src/messaging/inbound/policy.d.ts +95 -0
- package/src/messaging/inbound/policy.js +168 -0
- package/src/messaging/inbound/reaction-handler.d.ts +62 -0
- package/src/messaging/inbound/reaction-handler.js +259 -0
- package/src/messaging/inbound/sentinel-store.d.ts +37 -0
- package/src/messaging/inbound/sentinel-store.js +98 -0
- package/src/messaging/inbound/synthetic-message.d.ts +26 -0
- package/src/messaging/inbound/synthetic-message.js +59 -0
- package/src/messaging/inbound/user-name-cache-store.d.ts +62 -0
- package/src/messaging/inbound/user-name-cache-store.js +236 -0
- package/src/messaging/inbound/user-name-cache.d.ts +78 -0
- package/src/messaging/inbound/user-name-cache.js +306 -0
- package/src/messaging/inbound/vc-meeting-invited-handler.d.ts +20 -0
- package/src/messaging/inbound/vc-meeting-invited-handler.js +236 -0
- package/src/messaging/inbound/vc-sender.d.ts +41 -0
- package/src/messaging/inbound/vc-sender.js +53 -0
- package/src/messaging/outbound/actions.d.ts +16 -0
- package/src/messaging/outbound/actions.js +329 -0
- package/src/messaging/outbound/bot-peer-context.d.ts +42 -0
- package/src/messaging/outbound/bot-peer-context.js +40 -0
- package/src/messaging/outbound/chat-manage.d.ts +64 -0
- package/src/messaging/outbound/chat-manage.js +117 -0
- package/src/messaging/outbound/deliver.d.ts +186 -0
- package/src/messaging/outbound/deliver.js +410 -0
- package/src/messaging/outbound/fetch.d.ts +12 -0
- package/src/messaging/outbound/fetch.js +17 -0
- package/src/messaging/outbound/forward.d.ts +26 -0
- package/src/messaging/outbound/forward.js +51 -0
- package/src/messaging/outbound/media-url-utils.d.ts +29 -0
- package/src/messaging/outbound/media-url-utils.js +172 -0
- package/src/messaging/outbound/media.d.ts +260 -0
- package/src/messaging/outbound/media.js +865 -0
- package/src/messaging/outbound/normalize-mentions.d.ts +50 -0
- package/src/messaging/outbound/normalize-mentions.js +166 -0
- package/src/messaging/outbound/outbound-mention.d.ts +41 -0
- package/src/messaging/outbound/outbound-mention.js +112 -0
- package/src/messaging/outbound/outbound.d.ts +79 -0
- package/src/messaging/outbound/outbound.js +195 -0
- package/src/messaging/outbound/reactions.d.ts +124 -0
- package/src/messaging/outbound/reactions.js +384 -0
- package/src/messaging/outbound/send.d.ts +153 -0
- package/src/messaging/outbound/send.js +417 -0
- package/src/messaging/outbound/typing.d.ts +60 -0
- package/src/messaging/outbound/typing.js +139 -0
- package/src/messaging/shared/message-lookup.d.ts +54 -0
- package/src/messaging/shared/message-lookup.js +120 -0
- package/src/messaging/types.d.ts +316 -0
- package/src/messaging/types.js +11 -0
- package/src/tools/ask-user-question.d.ts +32 -0
- package/src/tools/ask-user-question.js +922 -0
- package/src/tools/auto-auth.d.ts +57 -0
- package/src/tools/auto-auth.js +904 -0
- package/src/tools/helpers.d.ts +264 -0
- package/src/tools/helpers.js +389 -0
- package/src/tools/mcp/doc/create.d.ts +12 -0
- package/src/tools/mcp/doc/create.js +47 -0
- package/src/tools/mcp/doc/fetch.d.ts +12 -0
- package/src/tools/mcp/doc/fetch.js +39 -0
- package/src/tools/mcp/doc/index.d.ts +12 -0
- package/src/tools/mcp/doc/index.js +50 -0
- package/src/tools/mcp/doc/update.d.ts +12 -0
- package/src/tools/mcp/doc/update.js +64 -0
- package/src/tools/mcp/shared.d.ts +59 -0
- package/src/tools/mcp/shared.js +239 -0
- package/src/tools/oapi/bitable/app-table-field.d.ts +16 -0
- package/src/tools/oapi/bitable/app-table-field.js +225 -0
- package/src/tools/oapi/bitable/app-table-record.d.ts +20 -0
- package/src/tools/oapi/bitable/app-table-record.js +439 -0
- package/src/tools/oapi/bitable/app-table-view.d.ts +16 -0
- package/src/tools/oapi/bitable/app-table-view.js +172 -0
- package/src/tools/oapi/bitable/app-table.d.ts +17 -0
- package/src/tools/oapi/bitable/app-table.js +195 -0
- package/src/tools/oapi/bitable/app.d.ts +18 -0
- package/src/tools/oapi/bitable/app.js +189 -0
- package/src/tools/oapi/bitable/index.d.ts +9 -0
- package/src/tools/oapi/bitable/index.js +17 -0
- package/src/tools/oapi/calendar/calendar.d.ts +15 -0
- package/src/tools/oapi/calendar/calendar.js +125 -0
- package/src/tools/oapi/calendar/event-attendee.d.ts +14 -0
- package/src/tools/oapi/calendar/event-attendee.js +161 -0
- package/src/tools/oapi/calendar/event.d.ts +16 -0
- package/src/tools/oapi/calendar/event.js +712 -0
- package/src/tools/oapi/calendar/freebusy.d.ts +13 -0
- package/src/tools/oapi/calendar/freebusy.js +114 -0
- package/src/tools/oapi/calendar/index.d.ts +8 -0
- package/src/tools/oapi/calendar/index.js +15 -0
- package/src/tools/oapi/chat/chat.d.ts +16 -0
- package/src/tools/oapi/chat/chat.js +127 -0
- package/src/tools/oapi/chat/index.d.ts +10 -0
- package/src/tools/oapi/chat/index.js +23 -0
- package/src/tools/oapi/chat/members.d.ts +11 -0
- package/src/tools/oapi/chat/members.js +84 -0
- package/src/tools/oapi/common/get-user.d.ts +12 -0
- package/src/tools/oapi/common/get-user.js +109 -0
- package/src/tools/oapi/common/index.d.ts +6 -0
- package/src/tools/oapi/common/index.js +11 -0
- package/src/tools/oapi/common/search-user.d.ts +11 -0
- package/src/tools/oapi/common/search-user.js +76 -0
- package/src/tools/oapi/drive/doc-comments.d.ts +15 -0
- package/src/tools/oapi/drive/doc-comments.js +351 -0
- package/src/tools/oapi/drive/doc-media.d.ts +19 -0
- package/src/tools/oapi/drive/doc-media.js +371 -0
- package/src/tools/oapi/drive/file.d.ts +19 -0
- package/src/tools/oapi/drive/file.js +519 -0
- package/src/tools/oapi/drive/index.d.ts +12 -0
- package/src/tools/oapi/drive/index.js +45 -0
- package/src/tools/oapi/helpers.d.ts +183 -0
- package/src/tools/oapi/helpers.js +385 -0
- package/src/tools/oapi/im/format-messages.d.ts +50 -0
- package/src/tools/oapi/im/format-messages.js +169 -0
- package/src/tools/oapi/im/index.d.ts +10 -0
- package/src/tools/oapi/im/index.js +25 -0
- package/src/tools/oapi/im/message-read.d.ts +13 -0
- package/src/tools/oapi/im/message-read.js +419 -0
- package/src/tools/oapi/im/message.d.ts +16 -0
- package/src/tools/oapi/im/message.js +152 -0
- package/src/tools/oapi/im/resource.d.ts +13 -0
- package/src/tools/oapi/im/resource.js +186 -0
- package/src/tools/oapi/im/time-utils.d.ts +46 -0
- package/src/tools/oapi/im/time-utils.js +212 -0
- package/src/tools/oapi/im/user-name-uat.d.ts +26 -0
- package/src/tools/oapi/im/user-name-uat.js +143 -0
- package/src/tools/oapi/index.d.ts +11 -0
- package/src/tools/oapi/index.js +64 -0
- package/src/tools/oapi/sdk-types.d.ts +96 -0
- package/src/tools/oapi/sdk-types.js +13 -0
- package/src/tools/oapi/search/doc-search.d.ts +13 -0
- package/src/tools/oapi/search/doc-search.js +194 -0
- package/src/tools/oapi/search/index.d.ts +12 -0
- package/src/tools/oapi/search/index.js +37 -0
- package/src/tools/oapi/sheets/index.d.ts +12 -0
- package/src/tools/oapi/sheets/index.js +35 -0
- package/src/tools/oapi/sheets/sheet.d.ts +16 -0
- package/src/tools/oapi/sheets/sheet.js +688 -0
- package/src/tools/oapi/task/attachment.d.ts +18 -0
- package/src/tools/oapi/task/attachment.js +107 -0
- package/src/tools/oapi/task/comment.d.ts +15 -0
- package/src/tools/oapi/task/comment.js +149 -0
- package/src/tools/oapi/task/index.d.ts +11 -0
- package/src/tools/oapi/task/index.js +21 -0
- package/src/tools/oapi/task/section.d.ts +17 -0
- package/src/tools/oapi/task/section.js +293 -0
- package/src/tools/oapi/task/subtask.d.ts +14 -0
- package/src/tools/oapi/task/subtask.js +171 -0
- package/src/tools/oapi/task/task.d.ts +19 -0
- package/src/tools/oapi/task/task.js +512 -0
- package/src/tools/oapi/task/task_agent.d.ts +14 -0
- package/src/tools/oapi/task/task_agent.js +108 -0
- package/src/tools/oapi/task/tasklist.d.ts +19 -0
- package/src/tools/oapi/task/tasklist.js +276 -0
- package/src/tools/oapi/wiki/index.d.ts +12 -0
- package/src/tools/oapi/wiki/index.js +42 -0
- package/src/tools/oapi/wiki/space-node.d.ts +17 -0
- package/src/tools/oapi/wiki/space-node.js +233 -0
- package/src/tools/oapi/wiki/space.d.ts +15 -0
- package/src/tools/oapi/wiki/space.js +133 -0
- package/src/tools/oauth-batch-auth.d.ts +11 -0
- package/src/tools/oauth-batch-auth.js +150 -0
- package/src/tools/oauth-cards.d.ts +39 -0
- package/src/tools/oauth-cards.js +324 -0
- package/src/tools/oauth.d.ts +47 -0
- package/src/tools/oauth.js +592 -0
- package/src/tools/onboarding-auth.d.ts +27 -0
- package/src/tools/onboarding-auth.js +133 -0
- package/src/tools/tat/im/index.d.ts +15 -0
- package/src/tools/tat/im/index.js +22 -0
- package/src/tools/tat/im/resource.d.ts +15 -0
- package/src/tools/tat/im/resource.js +192 -0
- package/tsdown.config.d.ts +2 -0
- package/tsdown.config.js +25 -0
- package/vitest.config.d.ts +2 -0
- package/vitest.config.js +12 -0
|
@@ -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,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;
|