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