@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,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* UAT (User Access Token) API call wrapper.
|
|
6
|
+
*
|
|
7
|
+
* Provides a safe, auto-refreshing interface for making Feishu API calls on
|
|
8
|
+
* behalf of a user. Tokens are read from the OS Keychain, refreshed
|
|
9
|
+
* transparently, and **never** exposed to the AI layer.
|
|
10
|
+
*/
|
|
11
|
+
import type { LarkBrand } from './types';
|
|
12
|
+
import { NeedAuthorizationError } from './auth-errors';
|
|
13
|
+
export { NeedAuthorizationError };
|
|
14
|
+
export interface UATCallOptions {
|
|
15
|
+
userOpenId: string;
|
|
16
|
+
appId: string;
|
|
17
|
+
appSecret: string;
|
|
18
|
+
domain: LarkBrand;
|
|
19
|
+
}
|
|
20
|
+
export interface UATStatus {
|
|
21
|
+
authorized: boolean;
|
|
22
|
+
userOpenId: string;
|
|
23
|
+
scope?: string;
|
|
24
|
+
expiresAt?: number;
|
|
25
|
+
refreshExpiresAt?: number;
|
|
26
|
+
grantedAt?: number;
|
|
27
|
+
tokenStatus?: 'valid' | 'needs_refresh' | 'expired';
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Obtain a valid access_token for the given user.
|
|
31
|
+
*
|
|
32
|
+
* - Reads from Keychain.
|
|
33
|
+
* - Refreshes proactively if the token is about to expire.
|
|
34
|
+
* - Throws when no token exists or refresh fails irrecoverably.
|
|
35
|
+
*
|
|
36
|
+
* **The returned token must never be exposed to the AI layer.**
|
|
37
|
+
*/
|
|
38
|
+
export declare function getValidAccessToken(opts: UATCallOptions): Promise<string>;
|
|
39
|
+
/**
|
|
40
|
+
* Execute an API call with a valid UAT, retrying once on token-expiry errors.
|
|
41
|
+
*/
|
|
42
|
+
export declare function callWithUAT<T>(opts: UATCallOptions, apiCall: (accessToken: string) => Promise<T>): Promise<T>;
|
|
43
|
+
/**
|
|
44
|
+
* Revoke a user's UAT by removing it from the Keychain.
|
|
45
|
+
*/
|
|
46
|
+
export declare function revokeUAT(appId: string, userOpenId: string): Promise<void>;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*
|
|
6
|
+
* UAT (User Access Token) API call wrapper.
|
|
7
|
+
*
|
|
8
|
+
* Provides a safe, auto-refreshing interface for making Feishu API calls on
|
|
9
|
+
* behalf of a user. Tokens are read from the OS Keychain, refreshed
|
|
10
|
+
* transparently, and **never** exposed to the AI layer.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.NeedAuthorizationError = void 0;
|
|
14
|
+
exports.getValidAccessToken = getValidAccessToken;
|
|
15
|
+
exports.callWithUAT = callWithUAT;
|
|
16
|
+
exports.revokeUAT = revokeUAT;
|
|
17
|
+
const token_store_1 = require("./token-store.js");
|
|
18
|
+
const device_flow_1 = require("./device-flow.js");
|
|
19
|
+
const lark_logger_1 = require("./lark-logger.js");
|
|
20
|
+
const log = (0, lark_logger_1.larkLogger)('core/uat-client');
|
|
21
|
+
const feishu_fetch_1 = require("./feishu-fetch.js");
|
|
22
|
+
const auth_errors_1 = require("./auth-errors.js");
|
|
23
|
+
Object.defineProperty(exports, "NeedAuthorizationError", { enumerable: true, get: function () { return auth_errors_1.NeedAuthorizationError; } });
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Per-user refresh lock
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
/**
|
|
28
|
+
* Guards against concurrent refresh operations for the same user.
|
|
29
|
+
*
|
|
30
|
+
* refresh_token is single-use: if two requests trigger a refresh
|
|
31
|
+
* simultaneously, the second one would use an already-consumed token and
|
|
32
|
+
* fail. The lock ensures only one refresh runs at a time per user.
|
|
33
|
+
*/
|
|
34
|
+
const refreshLocks = new Map();
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Refresh implementation
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
async function doRefreshToken(opts, stored) {
|
|
39
|
+
// refresh_token already expired → can't refresh, need re-auth.
|
|
40
|
+
if (Date.now() >= stored.refreshExpiresAt) {
|
|
41
|
+
log.info(`refresh_token expired for ${opts.userOpenId}, clearing`);
|
|
42
|
+
await (0, token_store_1.removeStoredToken)(opts.appId, opts.userOpenId);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const endpoints = (0, device_flow_1.resolveOAuthEndpoints)(opts.domain);
|
|
46
|
+
const requestBody = new URLSearchParams({
|
|
47
|
+
grant_type: 'refresh_token',
|
|
48
|
+
refresh_token: stored.refreshToken,
|
|
49
|
+
client_id: opts.appId,
|
|
50
|
+
client_secret: opts.appSecret,
|
|
51
|
+
}).toString();
|
|
52
|
+
const callEndpoint = async () => {
|
|
53
|
+
const resp = await (0, feishu_fetch_1.feishuFetch)(endpoints.token, {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
56
|
+
body: requestBody,
|
|
57
|
+
});
|
|
58
|
+
return (await resp.json());
|
|
59
|
+
};
|
|
60
|
+
let data = await callEndpoint();
|
|
61
|
+
// Feishu v2 token endpoint returns `code: 0` on success.
|
|
62
|
+
// Some responses use `error` field instead (standard OAuth).
|
|
63
|
+
const code = data.code;
|
|
64
|
+
const error = data.error;
|
|
65
|
+
if ((code !== undefined && code !== 0) || error) {
|
|
66
|
+
const errCode = code ?? error;
|
|
67
|
+
// Transient server error: retry once, then clear.
|
|
68
|
+
if (auth_errors_1.REFRESH_TOKEN_RETRYABLE.has(code)) {
|
|
69
|
+
log.warn(`refresh transient error (code=${errCode}) for ${opts.userOpenId}, retrying once`);
|
|
70
|
+
data = await callEndpoint();
|
|
71
|
+
const retryCode = data.code;
|
|
72
|
+
const retryError = data.error;
|
|
73
|
+
if ((retryCode !== undefined && retryCode !== 0) || retryError) {
|
|
74
|
+
const retryErrCode = retryCode ?? retryError;
|
|
75
|
+
log.warn(`refresh failed after retry (code=${retryErrCode}), clearing token for ${opts.userOpenId}`);
|
|
76
|
+
await (0, token_store_1.removeStoredToken)(opts.appId, opts.userOpenId);
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// Any other error (invalid/expired/revoked token, or unknown): clear and force re-auth.
|
|
82
|
+
log.warn(`refresh failed (code=${errCode}), clearing token for ${opts.userOpenId}`);
|
|
83
|
+
await (0, token_store_1.removeStoredToken)(opts.appId, opts.userOpenId);
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (!data.access_token) {
|
|
88
|
+
throw new Error('Token refresh returned no access_token');
|
|
89
|
+
}
|
|
90
|
+
const now = Date.now();
|
|
91
|
+
const updated = {
|
|
92
|
+
userOpenId: stored.userOpenId,
|
|
93
|
+
appId: opts.appId,
|
|
94
|
+
accessToken: data.access_token,
|
|
95
|
+
// refresh_token is rotated – always use the new one.
|
|
96
|
+
refreshToken: data.refresh_token ?? stored.refreshToken,
|
|
97
|
+
expiresAt: now + (data.expires_in ?? 7200) * 1000,
|
|
98
|
+
refreshExpiresAt: data.refresh_token_expires_in
|
|
99
|
+
? now + data.refresh_token_expires_in * 1000
|
|
100
|
+
: stored.refreshExpiresAt,
|
|
101
|
+
scope: data.scope ?? stored.scope,
|
|
102
|
+
grantedAt: stored.grantedAt,
|
|
103
|
+
};
|
|
104
|
+
await (0, token_store_1.setStoredToken)(updated);
|
|
105
|
+
log.info(`refreshed UAT for ${opts.userOpenId} (at:${(0, token_store_1.maskToken)(updated.accessToken)})`);
|
|
106
|
+
return updated;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Refresh with per-user locking.
|
|
110
|
+
*/
|
|
111
|
+
async function refreshWithLock(opts, stored) {
|
|
112
|
+
const key = `${opts.appId}:${opts.userOpenId}`;
|
|
113
|
+
// Another refresh is already in-flight – wait for it and re-read.
|
|
114
|
+
const existing = refreshLocks.get(key);
|
|
115
|
+
if (existing) {
|
|
116
|
+
await existing;
|
|
117
|
+
return (0, token_store_1.getStoredToken)(opts.appId, opts.userOpenId);
|
|
118
|
+
}
|
|
119
|
+
const promise = doRefreshToken(opts, stored);
|
|
120
|
+
refreshLocks.set(key, promise);
|
|
121
|
+
try {
|
|
122
|
+
return await promise;
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
refreshLocks.delete(key);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
// Public API
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
/**
|
|
132
|
+
* Obtain a valid access_token for the given user.
|
|
133
|
+
*
|
|
134
|
+
* - Reads from Keychain.
|
|
135
|
+
* - Refreshes proactively if the token is about to expire.
|
|
136
|
+
* - Throws when no token exists or refresh fails irrecoverably.
|
|
137
|
+
*
|
|
138
|
+
* **The returned token must never be exposed to the AI layer.**
|
|
139
|
+
*/
|
|
140
|
+
async function getValidAccessToken(opts) {
|
|
141
|
+
// Owner 检查已迁移到 owner-policy.ts(由 tool-client.ts 的 invokeAsUser 调用)
|
|
142
|
+
const stored = await (0, token_store_1.getStoredToken)(opts.appId, opts.userOpenId);
|
|
143
|
+
if (!stored) {
|
|
144
|
+
throw new auth_errors_1.NeedAuthorizationError(opts.userOpenId);
|
|
145
|
+
}
|
|
146
|
+
const status = (0, token_store_1.tokenStatus)(stored);
|
|
147
|
+
if (status === 'valid') {
|
|
148
|
+
return stored.accessToken;
|
|
149
|
+
}
|
|
150
|
+
if (status === 'needs_refresh') {
|
|
151
|
+
const refreshed = await refreshWithLock(opts, stored);
|
|
152
|
+
if (!refreshed) {
|
|
153
|
+
throw new auth_errors_1.NeedAuthorizationError(opts.userOpenId);
|
|
154
|
+
}
|
|
155
|
+
return refreshed.accessToken;
|
|
156
|
+
}
|
|
157
|
+
// expired
|
|
158
|
+
await (0, token_store_1.removeStoredToken)(opts.appId, opts.userOpenId);
|
|
159
|
+
throw new auth_errors_1.NeedAuthorizationError(opts.userOpenId);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Execute an API call with a valid UAT, retrying once on token-expiry errors.
|
|
163
|
+
*/
|
|
164
|
+
async function callWithUAT(opts, apiCall) {
|
|
165
|
+
const accessToken = await getValidAccessToken(opts);
|
|
166
|
+
try {
|
|
167
|
+
return await apiCall(accessToken);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
// Retry once if the server reports token invalid/expired.
|
|
171
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
172
|
+
const code = err?.code ?? err?.response?.data?.code;
|
|
173
|
+
if (auth_errors_1.TOKEN_RETRY_CODES.has(code)) {
|
|
174
|
+
log.warn(`API call failed (code=${code}), refreshing and retrying`);
|
|
175
|
+
const stored = await (0, token_store_1.getStoredToken)(opts.appId, opts.userOpenId);
|
|
176
|
+
if (!stored)
|
|
177
|
+
throw new auth_errors_1.NeedAuthorizationError(opts.userOpenId);
|
|
178
|
+
const refreshed = await refreshWithLock(opts, stored);
|
|
179
|
+
if (!refreshed)
|
|
180
|
+
throw new auth_errors_1.NeedAuthorizationError(opts.userOpenId);
|
|
181
|
+
return await apiCall(refreshed.accessToken);
|
|
182
|
+
}
|
|
183
|
+
throw err;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Revoke a user's UAT by removing it from the Keychain.
|
|
188
|
+
*/
|
|
189
|
+
async function revokeUAT(appId, userOpenId) {
|
|
190
|
+
await (0, token_store_1.removeStoredToken)(appId, userOpenId);
|
|
191
|
+
log.info(`revoked UAT for ${userOpenId}`);
|
|
192
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* 插件版本号管理
|
|
6
|
+
*
|
|
7
|
+
* 从 package.json 读取版本号并生成 User-Agent 字符串。
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* 获取插件版本号(从 package.json 读取)
|
|
11
|
+
*
|
|
12
|
+
* @returns 版本号字符串,如 "2026.2.28.5";读取失败返回 "unknown"
|
|
13
|
+
*/
|
|
14
|
+
export declare function getPluginVersion(): string;
|
|
15
|
+
/**
|
|
16
|
+
* 获取当前运行平台名称
|
|
17
|
+
*
|
|
18
|
+
* @returns `mac` | `linux` | `windows`
|
|
19
|
+
*/
|
|
20
|
+
export declare function getPlatform(): string;
|
|
21
|
+
/**
|
|
22
|
+
* 生成 User-Agent 字符串
|
|
23
|
+
*
|
|
24
|
+
* @returns User-Agent 字符串,格式:`openclaw-lark/{version}/{platform}`
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* getUserAgent() // => "openclaw-lark/2026.2.28.5/mac"
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function getUserAgent(): string;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*
|
|
6
|
+
* 插件版本号管理
|
|
7
|
+
*
|
|
8
|
+
* 从 package.json 读取版本号并生成 User-Agent 字符串。
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.getPluginVersion = getPluginVersion;
|
|
12
|
+
exports.getPlatform = getPlatform;
|
|
13
|
+
exports.getUserAgent = getUserAgent;
|
|
14
|
+
const node_url_1 = require("node:url");
|
|
15
|
+
const node_path_1 = require("node:path");
|
|
16
|
+
const node_fs_1 = require("node:fs");
|
|
17
|
+
/** 缓存的版本号 */
|
|
18
|
+
let cachedVersion;
|
|
19
|
+
/**
|
|
20
|
+
* 获取插件版本号(从 package.json 读取)
|
|
21
|
+
*
|
|
22
|
+
* @returns 版本号字符串,如 "2026.2.28.5";读取失败返回 "unknown"
|
|
23
|
+
*/
|
|
24
|
+
function getPluginVersion() {
|
|
25
|
+
if (cachedVersion)
|
|
26
|
+
return cachedVersion;
|
|
27
|
+
try {
|
|
28
|
+
// 当前文件: src/core/version.ts → 向上两级到达项目根目录
|
|
29
|
+
const __filename = (0, node_url_1.fileURLToPath)(import.meta.url);
|
|
30
|
+
const __dirname = (0, node_path_1.dirname)(__filename);
|
|
31
|
+
const packageJsonPath = (0, node_path_1.join)(__dirname, '..', '..', 'package.json');
|
|
32
|
+
const raw = (0, node_fs_1.readFileSync)(packageJsonPath, 'utf8');
|
|
33
|
+
const pkg = JSON.parse(raw);
|
|
34
|
+
cachedVersion = pkg.version ?? 'unknown';
|
|
35
|
+
return cachedVersion;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
cachedVersion = 'unknown';
|
|
39
|
+
return cachedVersion;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 获取当前运行平台名称
|
|
44
|
+
*
|
|
45
|
+
* @returns `mac` | `linux` | `windows`
|
|
46
|
+
*/
|
|
47
|
+
function getPlatform() {
|
|
48
|
+
switch (process.platform) {
|
|
49
|
+
case 'darwin':
|
|
50
|
+
return 'mac';
|
|
51
|
+
case 'win32':
|
|
52
|
+
return 'windows';
|
|
53
|
+
default:
|
|
54
|
+
return 'linux';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 生成 User-Agent 字符串
|
|
59
|
+
*
|
|
60
|
+
* @returns User-Agent 字符串,格式:`openclaw-lark/{version}/{platform}`
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* getUserAgent() // => "openclaw-lark/2026.2.28.5/mac"
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
function getUserAgent() {
|
|
68
|
+
return `openclaw-lark/${getPluginVersion()}/${getPlatform()}`;
|
|
69
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*
|
|
6
|
+
* Converter for "audio" message type.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.convertAudio = void 0;
|
|
10
|
+
const utils_1 = require("./utils.js");
|
|
11
|
+
const convertAudio = (raw) => {
|
|
12
|
+
const parsed = (0, utils_1.safeParse)(raw);
|
|
13
|
+
const fileKey = parsed?.file_key;
|
|
14
|
+
if (!fileKey) {
|
|
15
|
+
return { content: '[audio]', resources: [] };
|
|
16
|
+
}
|
|
17
|
+
const duration = parsed?.duration;
|
|
18
|
+
const durationAttr = duration != null ? ` duration="${(0, utils_1.formatDuration)(duration)}"` : '';
|
|
19
|
+
return {
|
|
20
|
+
content: `<audio key="${fileKey}"${durationAttr}/>`,
|
|
21
|
+
resources: [{ type: 'audio', fileKey, duration: duration ?? undefined }],
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
exports.convertAudio = convertAudio;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* Converters for calendar-related message types:
|
|
6
|
+
* - share_calendar_event
|
|
7
|
+
* - calendar
|
|
8
|
+
* - general_calendar
|
|
9
|
+
*/
|
|
10
|
+
import type { ContentConverterFn } from './types';
|
|
11
|
+
export declare const convertShareCalendarEvent: ContentConverterFn;
|
|
12
|
+
export declare const convertCalendar: ContentConverterFn;
|
|
13
|
+
export declare const convertGeneralCalendar: ContentConverterFn;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*
|
|
6
|
+
* Converters for calendar-related message types:
|
|
7
|
+
* - share_calendar_event
|
|
8
|
+
* - calendar
|
|
9
|
+
* - general_calendar
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.convertGeneralCalendar = exports.convertCalendar = exports.convertShareCalendarEvent = void 0;
|
|
13
|
+
const utils_1 = require("./utils.js");
|
|
14
|
+
function formatCalendarContent(parsed) {
|
|
15
|
+
const summary = parsed?.summary ?? '';
|
|
16
|
+
const parts = [];
|
|
17
|
+
if (summary) {
|
|
18
|
+
parts.push(`📅 ${summary}`);
|
|
19
|
+
}
|
|
20
|
+
const start = parsed?.start_time ? (0, utils_1.millisToDatetime)(parsed.start_time) : '';
|
|
21
|
+
const end = parsed?.end_time ? (0, utils_1.millisToDatetime)(parsed.end_time) : '';
|
|
22
|
+
if (start && end) {
|
|
23
|
+
parts.push(`🕙 ${start} ~ ${end}`);
|
|
24
|
+
}
|
|
25
|
+
else if (start) {
|
|
26
|
+
parts.push(`🕙 ${start}`);
|
|
27
|
+
}
|
|
28
|
+
return parts.join('\n') || '[calendar event]';
|
|
29
|
+
}
|
|
30
|
+
const convertShareCalendarEvent = (raw) => {
|
|
31
|
+
const parsed = (0, utils_1.safeParse)(raw);
|
|
32
|
+
const inner = formatCalendarContent(parsed);
|
|
33
|
+
return {
|
|
34
|
+
content: `<calendar_share>${inner}</calendar_share>`,
|
|
35
|
+
resources: [],
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
exports.convertShareCalendarEvent = convertShareCalendarEvent;
|
|
39
|
+
const convertCalendar = (raw) => {
|
|
40
|
+
const parsed = (0, utils_1.safeParse)(raw);
|
|
41
|
+
const inner = formatCalendarContent(parsed);
|
|
42
|
+
return {
|
|
43
|
+
content: `<calendar_invite>${inner}</calendar_invite>`,
|
|
44
|
+
resources: [],
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
exports.convertCalendar = convertCalendar;
|
|
48
|
+
const convertGeneralCalendar = (raw) => {
|
|
49
|
+
const parsed = (0, utils_1.safeParse)(raw);
|
|
50
|
+
const inner = formatCalendarContent(parsed);
|
|
51
|
+
return {
|
|
52
|
+
content: `<calendar>${inner}</calendar>`,
|
|
53
|
+
resources: [],
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
exports.convertGeneralCalendar = convertGeneralCalendar;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* Shared helper functions for Feishu content converters.
|
|
6
|
+
*/
|
|
7
|
+
import type { ApiMessageItem, ConvertContext } from './types';
|
|
8
|
+
/** 从 mention 的 id 字段提取 open_id(兼容事件推送的对象格式和 API 响应的字符串格式) */
|
|
9
|
+
export declare function extractMentionOpenId(id: unknown): string;
|
|
10
|
+
/**
|
|
11
|
+
* Build a {@link ConvertContext} from a raw Feishu API message item.
|
|
12
|
+
*
|
|
13
|
+
* Extracts the `mentions` array that the IM API returns on each message
|
|
14
|
+
* item and maps it into the key→MentionInfo / openId→MentionInfo
|
|
15
|
+
* structures the converter system expects.
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildConvertContextFromItem(item: ApiMessageItem, fallbackMessageId: string, accountId?: string): ConvertContext;
|
|
18
|
+
/**
|
|
19
|
+
* Resolve mention placeholders in text.
|
|
20
|
+
*
|
|
21
|
+
* - Bot self-mention + stripBotMentions: leading-only strip. When the
|
|
22
|
+
* self-mention sits at the very start of the message, drop it (the
|
|
23
|
+
* `WasMentioned` envelope field already tells the agent "this message
|
|
24
|
+
* was addressed to you", so the anchor is redundant). When it appears
|
|
25
|
+
* mid-text, render it as plain `@Name` so the surrounding context still
|
|
26
|
+
* reads naturally without leaving an inline anchor the LLM might echo
|
|
27
|
+
* back into its reply.
|
|
28
|
+
* - Non-bot mentions: replace the placeholder key with readable `@name`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveMentions(text: string, ctx: ConvertContext): string;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*
|
|
6
|
+
* Shared helper functions for Feishu content converters.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.extractMentionOpenId = extractMentionOpenId;
|
|
10
|
+
exports.buildConvertContextFromItem = buildConvertContextFromItem;
|
|
11
|
+
exports.resolveMentions = resolveMentions;
|
|
12
|
+
const user_name_cache_1 = require("../inbound/user-name-cache.js");
|
|
13
|
+
const utils_1 = require("./utils.js");
|
|
14
|
+
/** 从 mention 的 id 字段提取 open_id(兼容事件推送的对象格式和 API 响应的字符串格式) */
|
|
15
|
+
function extractMentionOpenId(id) {
|
|
16
|
+
if (typeof id === 'string')
|
|
17
|
+
return id;
|
|
18
|
+
if (id != null && typeof id === 'object' && 'open_id' in id) {
|
|
19
|
+
const openId = id.open_id;
|
|
20
|
+
return typeof openId === 'string' ? openId : '';
|
|
21
|
+
}
|
|
22
|
+
return '';
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Build a {@link ConvertContext} from a raw Feishu API message item.
|
|
26
|
+
*
|
|
27
|
+
* Extracts the `mentions` array that the IM API returns on each message
|
|
28
|
+
* item and maps it into the key→MentionInfo / openId→MentionInfo
|
|
29
|
+
* structures the converter system expects.
|
|
30
|
+
*/
|
|
31
|
+
function buildConvertContextFromItem(item, fallbackMessageId, accountId) {
|
|
32
|
+
const mentions = new Map();
|
|
33
|
+
const mentionsByOpenId = new Map();
|
|
34
|
+
for (const m of item.mentions ?? []) {
|
|
35
|
+
const openId = extractMentionOpenId(m.id);
|
|
36
|
+
if (!openId)
|
|
37
|
+
continue;
|
|
38
|
+
const info = {
|
|
39
|
+
key: m.key,
|
|
40
|
+
openId,
|
|
41
|
+
name: m.name ?? '',
|
|
42
|
+
isBot: false,
|
|
43
|
+
};
|
|
44
|
+
mentions.set(m.key, info);
|
|
45
|
+
mentionsByOpenId.set(openId, info);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
mentions,
|
|
49
|
+
mentionsByOpenId,
|
|
50
|
+
messageId: item.message_id ?? fallbackMessageId,
|
|
51
|
+
accountId,
|
|
52
|
+
resolveUserName: accountId ? (openId) => (0, user_name_cache_1.getUserNameCache)(accountId).get(openId) : undefined,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolve mention placeholders in text.
|
|
57
|
+
*
|
|
58
|
+
* - Bot self-mention + stripBotMentions: leading-only strip. When the
|
|
59
|
+
* self-mention sits at the very start of the message, drop it (the
|
|
60
|
+
* `WasMentioned` envelope field already tells the agent "this message
|
|
61
|
+
* was addressed to you", so the anchor is redundant). When it appears
|
|
62
|
+
* mid-text, render it as plain `@Name` so the surrounding context still
|
|
63
|
+
* reads naturally without leaving an inline anchor the LLM might echo
|
|
64
|
+
* back into its reply.
|
|
65
|
+
* - Non-bot mentions: replace the placeholder key with readable `@name`.
|
|
66
|
+
*/
|
|
67
|
+
function resolveMentions(text, ctx) {
|
|
68
|
+
if (ctx.mentions.size === 0)
|
|
69
|
+
return text;
|
|
70
|
+
let result = text;
|
|
71
|
+
for (const [key, info] of ctx.mentions) {
|
|
72
|
+
if (info.isBot && ctx.stripBotMentions) {
|
|
73
|
+
result = result.replace(new RegExp((0, utils_1.escapeRegExp)(key), 'g'), `@${info.name}`);
|
|
74
|
+
const leadingPattern = new RegExp(`^\\s*@${(0, utils_1.escapeRegExp)(info.name)}[\\s,,::]*`);
|
|
75
|
+
result = result.replace(leadingPattern, '').trimStart();
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
result = result.replace(new RegExp((0, utils_1.escapeRegExp)(key), 'g'), `@${info.name}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* Content converter for Feishu messages.
|
|
6
|
+
*
|
|
7
|
+
* Each message type (text, post, image, etc.) has a dedicated converter
|
|
8
|
+
* function that parses raw JSON content into an AI-friendly text
|
|
9
|
+
* representation plus a list of resource descriptors.
|
|
10
|
+
*
|
|
11
|
+
* This module is a general-purpose message parsing utility — usable
|
|
12
|
+
* from inbound handling, outbound formatting, and skills.
|
|
13
|
+
*/
|
|
14
|
+
import type { ConvertContext, ConvertResult } from './types';
|
|
15
|
+
export type { ApiMessageItem, ConvertContext, ConvertResult, ContentConverterFn } from './types';
|
|
16
|
+
export { buildConvertContextFromItem, extractMentionOpenId, resolveMentions } from './content-converter-helpers';
|
|
17
|
+
/**
|
|
18
|
+
* Convert raw message content using the converter for the given message
|
|
19
|
+
* type. Falls back to the "unknown" converter for unrecognised types.
|
|
20
|
+
*
|
|
21
|
+
* Returns a Promise because some converters (e.g. merge_forward) perform
|
|
22
|
+
* async operations. Synchronous converters are awaited transparently.
|
|
23
|
+
*/
|
|
24
|
+
export declare function convertMessageContent(raw: string, messageType: string, ctx: ConvertContext): Promise<ConvertResult>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*
|
|
6
|
+
* Content converter for Feishu messages.
|
|
7
|
+
*
|
|
8
|
+
* Each message type (text, post, image, etc.) has a dedicated converter
|
|
9
|
+
* function that parses raw JSON content into an AI-friendly text
|
|
10
|
+
* representation plus a list of resource descriptors.
|
|
11
|
+
*
|
|
12
|
+
* This module is a general-purpose message parsing utility — usable
|
|
13
|
+
* from inbound handling, outbound formatting, and skills.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.resolveMentions = exports.extractMentionOpenId = exports.buildConvertContextFromItem = void 0;
|
|
17
|
+
exports.convertMessageContent = convertMessageContent;
|
|
18
|
+
const index_1 = require("./index.js");
|
|
19
|
+
var content_converter_helpers_1 = require("./content-converter-helpers.js");
|
|
20
|
+
Object.defineProperty(exports, "buildConvertContextFromItem", { enumerable: true, get: function () { return content_converter_helpers_1.buildConvertContextFromItem; } });
|
|
21
|
+
Object.defineProperty(exports, "extractMentionOpenId", { enumerable: true, get: function () { return content_converter_helpers_1.extractMentionOpenId; } });
|
|
22
|
+
Object.defineProperty(exports, "resolveMentions", { enumerable: true, get: function () { return content_converter_helpers_1.resolveMentions; } });
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Convert
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Convert raw message content using the converter for the given message
|
|
28
|
+
* type. Falls back to the "unknown" converter for unrecognised types.
|
|
29
|
+
*
|
|
30
|
+
* Returns a Promise because some converters (e.g. merge_forward) perform
|
|
31
|
+
* async operations. Synchronous converters are awaited transparently.
|
|
32
|
+
*/
|
|
33
|
+
async function convertMessageContent(raw, messageType, ctx) {
|
|
34
|
+
const fn = index_1.converters.get(messageType) ?? index_1.converters.get('unknown');
|
|
35
|
+
if (!fn) {
|
|
36
|
+
return { content: raw, resources: [] };
|
|
37
|
+
}
|
|
38
|
+
const nextCtx = ctx.convertMessageContent ? ctx : { ...ctx, convertMessageContent };
|
|
39
|
+
return fn(raw, nextCtx);
|
|
40
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*
|
|
6
|
+
* Converter for "file" message type.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.convertFile = void 0;
|
|
10
|
+
const utils_1 = require("./utils.js");
|
|
11
|
+
const convertFile = (raw) => {
|
|
12
|
+
const parsed = (0, utils_1.safeParse)(raw);
|
|
13
|
+
const fileKey = parsed?.file_key;
|
|
14
|
+
if (!fileKey) {
|
|
15
|
+
return { content: '[file]', resources: [] };
|
|
16
|
+
}
|
|
17
|
+
const fileName = parsed?.file_name ?? '';
|
|
18
|
+
const nameAttr = fileName ? ` name="${fileName}"` : '';
|
|
19
|
+
return {
|
|
20
|
+
content: `<file key="${fileKey}"${nameAttr}/>`,
|
|
21
|
+
resources: [{ type: 'file', fileKey, fileName: fileName || undefined }],
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
exports.convertFile = convertFile;
|