@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,426 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*
|
|
6
|
+
* ToolClient — 工具层统一客户端。
|
|
7
|
+
*
|
|
8
|
+
* 专为 `src/tools/` 下的工具设计,封装 account 解析、SDK 管理、
|
|
9
|
+
* TAT/UAT 自动切换和 scope 预检。工具代码只需声明 API 名称和调用逻辑,
|
|
10
|
+
* 身份选择/scope 校验/token 管理全部由 `invoke()` 内聚处理。
|
|
11
|
+
*
|
|
12
|
+
* 用法:
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const client = createToolClient(config);
|
|
15
|
+
*
|
|
16
|
+
* // UAT 调用 — 通过 { as: "user" } 指定用户身份
|
|
17
|
+
* const res = await client.invoke(
|
|
18
|
+
* "calendar.v4.calendarEvent.create",
|
|
19
|
+
* (sdk, opts) => sdk.calendar.calendarEvent.create(payload, opts),
|
|
20
|
+
* { as: "user" },
|
|
21
|
+
* );
|
|
22
|
+
*
|
|
23
|
+
* // TAT 调用 — 默认走应用身份
|
|
24
|
+
* const res = await client.invoke(
|
|
25
|
+
* "calendar.v4.calendar.list",
|
|
26
|
+
* (sdk) => sdk.calendar.calendar.list(payload),
|
|
27
|
+
* { as: "tenant" },
|
|
28
|
+
* );
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
32
|
+
if (k2 === undefined) k2 = k;
|
|
33
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
34
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
35
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
36
|
+
}
|
|
37
|
+
Object.defineProperty(o, k2, desc);
|
|
38
|
+
}) : (function(o, m, k, k2) {
|
|
39
|
+
if (k2 === undefined) k2 = k;
|
|
40
|
+
o[k2] = m[k];
|
|
41
|
+
}));
|
|
42
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
43
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
44
|
+
}) : function(o, v) {
|
|
45
|
+
o["default"] = v;
|
|
46
|
+
});
|
|
47
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
48
|
+
var ownKeys = function(o) {
|
|
49
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
50
|
+
var ar = [];
|
|
51
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
52
|
+
return ar;
|
|
53
|
+
};
|
|
54
|
+
return ownKeys(o);
|
|
55
|
+
};
|
|
56
|
+
return function (mod) {
|
|
57
|
+
if (mod && mod.__esModule) return mod;
|
|
58
|
+
var result = {};
|
|
59
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
60
|
+
__setModuleDefault(result, mod);
|
|
61
|
+
return result;
|
|
62
|
+
};
|
|
63
|
+
})();
|
|
64
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
65
|
+
exports.ToolClient = exports.UserScopeInsufficientError = exports.UserAuthRequiredError = exports.AppScopeMissingError = exports.AppScopeCheckFailedError = exports.NeedAuthorizationError = exports.LARK_ERROR = void 0;
|
|
66
|
+
exports.createToolClient = createToolClient;
|
|
67
|
+
const Lark = __importStar(require("@larksuiteoapi/node-sdk"));
|
|
68
|
+
const accounts_1 = require("./accounts.js");
|
|
69
|
+
const lark_client_1 = require("./lark-client.js");
|
|
70
|
+
const lark_ticket_1 = require("./lark-ticket.js");
|
|
71
|
+
const uat_client_1 = require("./uat-client.js");
|
|
72
|
+
const token_store_1 = require("./token-store.js");
|
|
73
|
+
const app_scope_checker_1 = require("./app-scope-checker.js");
|
|
74
|
+
const app_owner_fallback_1 = require("./app-owner-fallback.js");
|
|
75
|
+
const lark_logger_1 = require("./lark-logger.js");
|
|
76
|
+
const scope_manager_1 = require("./scope-manager.js");
|
|
77
|
+
const raw_request_1 = require("./raw-request.js");
|
|
78
|
+
const owner_policy_1 = require("./owner-policy.js");
|
|
79
|
+
const auth_errors_1 = require("./auth-errors.js");
|
|
80
|
+
Object.defineProperty(exports, "AppScopeCheckFailedError", { enumerable: true, get: function () { return auth_errors_1.AppScopeCheckFailedError; } });
|
|
81
|
+
Object.defineProperty(exports, "AppScopeMissingError", { enumerable: true, get: function () { return auth_errors_1.AppScopeMissingError; } });
|
|
82
|
+
Object.defineProperty(exports, "LARK_ERROR", { enumerable: true, get: function () { return auth_errors_1.LARK_ERROR; } });
|
|
83
|
+
Object.defineProperty(exports, "NeedAuthorizationError", { enumerable: true, get: function () { return auth_errors_1.NeedAuthorizationError; } });
|
|
84
|
+
Object.defineProperty(exports, "UserAuthRequiredError", { enumerable: true, get: function () { return auth_errors_1.UserAuthRequiredError; } });
|
|
85
|
+
Object.defineProperty(exports, "UserScopeInsufficientError", { enumerable: true, get: function () { return auth_errors_1.UserScopeInsufficientError; } });
|
|
86
|
+
const tcLog = (0, lark_logger_1.larkLogger)('core/tool-client');
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
// ToolClient
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
class ToolClient {
|
|
91
|
+
config;
|
|
92
|
+
/** 当前解析的账号信息(appId、appSecret 保证存在)。 */
|
|
93
|
+
account;
|
|
94
|
+
/** 当前请求的用户 open_id(来自 LarkTicket,可能为 undefined)。 */
|
|
95
|
+
senderOpenId;
|
|
96
|
+
/** Lark SDK 实例(TAT 身份),直接调用即可。 */
|
|
97
|
+
sdk;
|
|
98
|
+
constructor(params) {
|
|
99
|
+
this.account = params.account;
|
|
100
|
+
this.senderOpenId = params.senderOpenId;
|
|
101
|
+
this.sdk = params.sdk;
|
|
102
|
+
this.config = params.config;
|
|
103
|
+
}
|
|
104
|
+
// -------------------------------------------------------------------------
|
|
105
|
+
// invoke() — 统一 API 调用入口
|
|
106
|
+
// -------------------------------------------------------------------------
|
|
107
|
+
/**
|
|
108
|
+
* 统一 API 调用入口。
|
|
109
|
+
*
|
|
110
|
+
* 自动处理:
|
|
111
|
+
* - 根据 API meta 选择 UAT / TAT
|
|
112
|
+
* - 严格模式:检查应用和用户是否拥有所有 API 要求的 scope
|
|
113
|
+
* - 无 token 或 scope 不足时抛出结构化错误
|
|
114
|
+
* - UAT 模式下复用 callWithUAT 的 refresh + retry
|
|
115
|
+
*
|
|
116
|
+
* @param apiName - meta.json 中的 toolName,如 `"calendar.v4.calendarEvent.create"`
|
|
117
|
+
* @param fn - API 调用逻辑。UAT 时 opts 已注入 token,TAT 时 opts 为 undefined。
|
|
118
|
+
* @param options - 可选配置:
|
|
119
|
+
* - `as`: 指定 UAT/TAT
|
|
120
|
+
* - `userOpenId`: 覆盖用户 ID
|
|
121
|
+
*
|
|
122
|
+
* @throws {@link AppScopeMissingError} 应用未开通 API 所需 scope
|
|
123
|
+
* @throws {@link UserAuthRequiredError} 用户未授权或 scope 不足
|
|
124
|
+
* @throws {@link UserScopeInsufficientError} 服务端报用户 scope 不足
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* // UAT 调用 — 通过 { as: "user" } 指定
|
|
128
|
+
* const res = await client.invoke(
|
|
129
|
+
* "calendar.v4.calendarEvent.create",
|
|
130
|
+
* (sdk, opts) => sdk.calendar.calendarEvent.create(payload, opts),
|
|
131
|
+
* { as: "user" },
|
|
132
|
+
* );
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* // TAT 调用
|
|
136
|
+
* const res = await client.invoke(
|
|
137
|
+
* "calendar.v4.calendar.list",
|
|
138
|
+
* (sdk) => sdk.calendar.calendar.list(payload),
|
|
139
|
+
* { as: "tenant" },
|
|
140
|
+
* );
|
|
141
|
+
*
|
|
142
|
+
*/
|
|
143
|
+
async invoke(toolAction, fn, options) {
|
|
144
|
+
return this._invokeInternal(toolAction, fn, options);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* 内部 invoke 实现,只支持 ToolActionKey(严格类型检查)
|
|
148
|
+
*/
|
|
149
|
+
async _invokeInternal(toolAction, fn, options) {
|
|
150
|
+
// 检查旧版插件是否已禁用 (error)
|
|
151
|
+
const feishuEntry = this.config.plugins?.entries?.feishu;
|
|
152
|
+
if (feishuEntry && feishuEntry.enabled !== false) {
|
|
153
|
+
throw new Error('❌ 检测到旧版插件未禁用。\n' +
|
|
154
|
+
'👉 请依次运行命令:\n' +
|
|
155
|
+
'```\n' +
|
|
156
|
+
'openclaw config set plugins.entries.feishu.enabled false --json\n' +
|
|
157
|
+
'openclaw gateway restart\n' +
|
|
158
|
+
'```');
|
|
159
|
+
}
|
|
160
|
+
// 2. 从 scope.ts 查询 API 需要的 scopes(Required Scopes)
|
|
161
|
+
const requiredScopes = (0, scope_manager_1.getRequiredScopes)(toolAction);
|
|
162
|
+
// 3. 决定 token 类型(默认 user,用户可通过 options.as 覆盖)
|
|
163
|
+
const tokenType = options?.as ?? 'user';
|
|
164
|
+
// ---- App Granted Scopes 检查(应用已开通的权限)----
|
|
165
|
+
// UAT 调用额外检查 offline_access(OAuth Device Flow 的前提权限),
|
|
166
|
+
// 但不加入 requiredScopes(避免阻断业务 scope 进入用户授权流程)。
|
|
167
|
+
const appCheckScopes = tokenType === 'user' ? [...new Set([...requiredScopes, 'offline_access'])] : requiredScopes;
|
|
168
|
+
let appScopeVerified = true;
|
|
169
|
+
if (appCheckScopes.length > 0) {
|
|
170
|
+
const appGrantedScopes = await (0, app_scope_checker_1.getAppGrantedScopes)(this.sdk, this.account.appId, tokenType);
|
|
171
|
+
if (appGrantedScopes.length > 0) {
|
|
172
|
+
// 严格模式:应用必须开通所有 Required Scopes(+ offline_access)
|
|
173
|
+
const missingAppScopes = (0, app_scope_checker_1.missingScopes)(appGrantedScopes, appCheckScopes);
|
|
174
|
+
if (missingAppScopes.length > 0) {
|
|
175
|
+
throw new auth_errors_1.AppScopeMissingError({ apiName: toolAction, scopes: missingAppScopes, appId: this.account.appId }, 'all', tokenType, requiredScopes);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
// 查询失败(返回空数组)→ 标记 appScopeVerified=false,跳过本地 scope 预检,
|
|
180
|
+
// 让服务端来判断是应用缺权限还是用户缺授权。
|
|
181
|
+
appScopeVerified = false;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// 5. 执行调用
|
|
185
|
+
if (tokenType === 'tenant') {
|
|
186
|
+
return this.invokeAsTenant(toolAction, fn, requiredScopes);
|
|
187
|
+
}
|
|
188
|
+
// 5.1 获取 userOpenId,支持兜底逻辑
|
|
189
|
+
let userOpenId = options?.userOpenId ?? this.senderOpenId;
|
|
190
|
+
// 5.2 兜底逻辑:如果没有 senderOpenId,尝试使用应用所有者
|
|
191
|
+
if (!userOpenId) {
|
|
192
|
+
const fallbackUserId = await (0, app_owner_fallback_1.getAppOwnerFallback)(this.account, this.sdk);
|
|
193
|
+
if (fallbackUserId) {
|
|
194
|
+
userOpenId = fallbackUserId;
|
|
195
|
+
tcLog.info(`Using app owner as fallback user`, {
|
|
196
|
+
toolAction,
|
|
197
|
+
appId: this.account.appId,
|
|
198
|
+
ownerId: fallbackUserId,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return this.invokeAsUser(toolAction, fn, requiredScopes, userOpenId, appScopeVerified);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* invoke() 的非抛出包装,适用于"允许失败"的子操作。
|
|
206
|
+
*
|
|
207
|
+
* - 成功 → `{ ok: true, data }`
|
|
208
|
+
* - 用户授权错误(可通过 OAuth 恢复)→ `{ ok: false, authHint }`
|
|
209
|
+
* - 应用权限缺失 / appScopeVerified=false → **仍然 throw**(需管理员操作)
|
|
210
|
+
* - 其他错误 → `{ ok: false, error }`
|
|
211
|
+
*/
|
|
212
|
+
// -------------------------------------------------------------------------
|
|
213
|
+
// invokeByPath() — SDK 未覆盖的 API 调用入口
|
|
214
|
+
// -------------------------------------------------------------------------
|
|
215
|
+
/**
|
|
216
|
+
* 对 SDK 未覆盖的飞书 API 发起 raw HTTP 请求,同时复用 invoke() 的
|
|
217
|
+
* auth/scope/refresh 全链路。
|
|
218
|
+
*
|
|
219
|
+
* @param apiName - 逻辑 API 名称(用于日志和错误信息),如 `"im.v1.chatP2p.batchQuery"`
|
|
220
|
+
* @param path - API 路径(以 `/open-apis/` 开头),如 `"/open-apis/im/v1/chat_p2p/batch_query"`
|
|
221
|
+
* @param options - HTTP 方法、body、query 及 InvokeOptions(as、userOpenId 等)
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```typescript
|
|
225
|
+
* const res = await client.invokeByPath<{ data: { items: Array<{ chat_id: string }> } }>(
|
|
226
|
+
* "im.v1.chatP2p.batchQuery",
|
|
227
|
+
* "/open-apis/im/v1/chat_p2p/batch_query",
|
|
228
|
+
* {
|
|
229
|
+
* method: "POST",
|
|
230
|
+
* body: { chatter_ids: [openId] },
|
|
231
|
+
* as: "user",
|
|
232
|
+
* },
|
|
233
|
+
* );
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
237
|
+
async invokeByPath(toolAction, path, options) {
|
|
238
|
+
const fn = async (_sdk, _opts, uat) => {
|
|
239
|
+
return this.rawRequest(path, {
|
|
240
|
+
method: options?.method,
|
|
241
|
+
body: options?.body,
|
|
242
|
+
query: options?.query,
|
|
243
|
+
headers: options?.headers,
|
|
244
|
+
accessToken: uat,
|
|
245
|
+
});
|
|
246
|
+
};
|
|
247
|
+
return this._invokeInternal(toolAction, fn, options);
|
|
248
|
+
}
|
|
249
|
+
// -------------------------------------------------------------------------
|
|
250
|
+
// Private: TAT path
|
|
251
|
+
// -------------------------------------------------------------------------
|
|
252
|
+
async invokeAsTenant(toolAction, fn, requiredScopes) {
|
|
253
|
+
try {
|
|
254
|
+
return await fn(this.sdk);
|
|
255
|
+
}
|
|
256
|
+
catch (err) {
|
|
257
|
+
this.rethrowStructuredError(err, toolAction, requiredScopes, undefined, 'tenant');
|
|
258
|
+
throw err;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
// -------------------------------------------------------------------------
|
|
262
|
+
// Private: UAT path
|
|
263
|
+
// -------------------------------------------------------------------------
|
|
264
|
+
async invokeAsUser(toolAction, fn, requiredScopes, userOpenId, appScopeVerified) {
|
|
265
|
+
if (!userOpenId) {
|
|
266
|
+
throw new auth_errors_1.UserAuthRequiredError('unknown', {
|
|
267
|
+
apiName: toolAction,
|
|
268
|
+
scopes: requiredScopes,
|
|
269
|
+
appScopeVerified,
|
|
270
|
+
appId: this.account.appId,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
// Owner 检查:非 owner 用户直接拒绝(从 uat-client.ts 迁移至此)
|
|
274
|
+
await (0, owner_policy_1.assertOwnerAccessStrict)(this.account, this.sdk, userOpenId);
|
|
275
|
+
// 预检:是否有已存储的 token
|
|
276
|
+
const stored = await (0, token_store_1.getStoredToken)(this.account.appId, userOpenId);
|
|
277
|
+
if (!stored) {
|
|
278
|
+
throw new auth_errors_1.UserAuthRequiredError(userOpenId, {
|
|
279
|
+
apiName: toolAction,
|
|
280
|
+
scopes: requiredScopes,
|
|
281
|
+
appScopeVerified,
|
|
282
|
+
appId: this.account.appId,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
// 预检:token 的 scope 是否满足 API 要求
|
|
286
|
+
// ---- User Granted Scopes 检查(用户授权的权限)----
|
|
287
|
+
// 仅在 App Granted Scopes 检查成功时进行本地预检。
|
|
288
|
+
// 当 App Scope 检查失败时(appScopeVerified=false),跳过预检,
|
|
289
|
+
// 让请求走到服务端 — 服务端会返回准确的错误码:
|
|
290
|
+
// LARK_ERROR.APP_SCOPE_MISSING (99991672) → App Granted Scopes 缺失(管理员需在开放平台开通)
|
|
291
|
+
// LARK_ERROR.USER_SCOPE_INSUFFICIENT (99991679) → User Granted Scopes 缺失(需引导用户 OAuth 授权)
|
|
292
|
+
if (appScopeVerified && stored.scope && requiredScopes.length > 0) {
|
|
293
|
+
// 检查用户是否授权了所有 Required Scopes
|
|
294
|
+
const userGrantedScopes = new Set(stored.scope.split(/\s+/).filter(Boolean));
|
|
295
|
+
const missingUserScopes = requiredScopes.filter((s) => !userGrantedScopes.has(s));
|
|
296
|
+
if (missingUserScopes.length > 0) {
|
|
297
|
+
throw new auth_errors_1.UserAuthRequiredError(userOpenId, {
|
|
298
|
+
apiName: toolAction,
|
|
299
|
+
scopes: missingUserScopes,
|
|
300
|
+
appScopeVerified,
|
|
301
|
+
appId: this.account.appId,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
// 通过 callWithUAT 执行(自动 refresh + retry)
|
|
306
|
+
try {
|
|
307
|
+
return await (0, uat_client_1.callWithUAT)({
|
|
308
|
+
userOpenId,
|
|
309
|
+
appId: this.account.appId,
|
|
310
|
+
appSecret: this.account.appSecret,
|
|
311
|
+
domain: this.account.brand,
|
|
312
|
+
}, (accessToken) => fn(this.sdk, Lark.withUserAccessToken(accessToken), accessToken));
|
|
313
|
+
}
|
|
314
|
+
catch (err) {
|
|
315
|
+
if (err instanceof auth_errors_1.NeedAuthorizationError) {
|
|
316
|
+
throw new auth_errors_1.UserAuthRequiredError(userOpenId, {
|
|
317
|
+
apiName: toolAction,
|
|
318
|
+
scopes: requiredScopes,
|
|
319
|
+
appScopeVerified,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
this.rethrowStructuredError(err, toolAction, requiredScopes, userOpenId, 'user');
|
|
323
|
+
throw err;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
// -------------------------------------------------------------------------
|
|
327
|
+
// Private: raw HTTP request
|
|
328
|
+
// -------------------------------------------------------------------------
|
|
329
|
+
/**
|
|
330
|
+
* 发起 raw HTTP 请求到飞书 API,委托 rawLarkRequest 处理。
|
|
331
|
+
*/
|
|
332
|
+
async rawRequest(path, options) {
|
|
333
|
+
return (0, raw_request_1.rawLarkRequest)({
|
|
334
|
+
brand: this.account.brand,
|
|
335
|
+
path,
|
|
336
|
+
...options,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
// -------------------------------------------------------------------------
|
|
340
|
+
// Private: structured error detection
|
|
341
|
+
// -------------------------------------------------------------------------
|
|
342
|
+
/**
|
|
343
|
+
* 识别飞书服务端错误码并转换为结构化错误。
|
|
344
|
+
*
|
|
345
|
+
* - LARK_ERROR.APP_SCOPE_MISSING (99991672) → AppScopeMissingError(清缓存后抛出)
|
|
346
|
+
* - LARK_ERROR.USER_SCOPE_INSUFFICIENT (99991679) → UserScopeInsufficientError
|
|
347
|
+
*/
|
|
348
|
+
rethrowStructuredError(err, apiName, effectiveScopes, userOpenId, tokenType) {
|
|
349
|
+
const code =
|
|
350
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
351
|
+
err?.code ?? err?.response?.data?.code;
|
|
352
|
+
if (code === auth_errors_1.LARK_ERROR.APP_SCOPE_MISSING) {
|
|
353
|
+
// 应用 scope 不足 — 清缓存(管理员可能刚开通)
|
|
354
|
+
(0, app_scope_checker_1.invalidateAppScopeCache)(this.account.appId);
|
|
355
|
+
throw new auth_errors_1.AppScopeMissingError({
|
|
356
|
+
apiName,
|
|
357
|
+
scopes: effectiveScopes,
|
|
358
|
+
appId: this.account.appId,
|
|
359
|
+
}, 'all', tokenType);
|
|
360
|
+
}
|
|
361
|
+
if (code === auth_errors_1.LARK_ERROR.USER_SCOPE_INSUFFICIENT && userOpenId) {
|
|
362
|
+
throw new auth_errors_1.UserScopeInsufficientError(userOpenId, {
|
|
363
|
+
apiName,
|
|
364
|
+
scopes: effectiveScopes,
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
exports.ToolClient = ToolClient;
|
|
370
|
+
// ---------------------------------------------------------------------------
|
|
371
|
+
// Factory
|
|
372
|
+
// ---------------------------------------------------------------------------
|
|
373
|
+
/**
|
|
374
|
+
* 从配置创建 {@link ToolClient}。
|
|
375
|
+
*
|
|
376
|
+
* 自动从当前 {@link LarkTicket} 解析 accountId 和 senderOpenId。
|
|
377
|
+
* 如果 LarkTicket 不可用(如非消息场景),回退到 `accountIndex`
|
|
378
|
+
* 指定的账号。
|
|
379
|
+
*
|
|
380
|
+
* @param config - OpenClaw 配置对象
|
|
381
|
+
* @param accountIndex - 回退账号索引(默认 0)
|
|
382
|
+
*/
|
|
383
|
+
function createToolClient(config, accountIndex = 0) {
|
|
384
|
+
const ticket = (0, lark_ticket_1.getTicket)();
|
|
385
|
+
// 1. 解析账号
|
|
386
|
+
//
|
|
387
|
+
// `config` is the closure-captured snapshot from plugin registration and may be
|
|
388
|
+
// stale after a hot-reload. Use getResolvedConfig() to always get the live config.
|
|
389
|
+
const resolveConfig = (0, lark_client_1.getResolvedConfig)(config);
|
|
390
|
+
let account;
|
|
391
|
+
if (ticket?.accountId) {
|
|
392
|
+
const resolved = (0, accounts_1.getLarkAccount)(resolveConfig, ticket.accountId);
|
|
393
|
+
if (!resolved.configured) {
|
|
394
|
+
throw new Error(`Feishu account "${ticket.accountId}" is not configured (missing appId or appSecret). ` +
|
|
395
|
+
`Please check channels.feishu.accounts.${ticket.accountId} in your config.`);
|
|
396
|
+
}
|
|
397
|
+
if (!resolved.enabled) {
|
|
398
|
+
throw new Error(`Feishu account "${ticket.accountId}" is disabled. ` +
|
|
399
|
+
`Set channels.feishu.accounts.${ticket.accountId}.enabled to true, or remove it to use defaults.`);
|
|
400
|
+
}
|
|
401
|
+
account = resolved;
|
|
402
|
+
}
|
|
403
|
+
if (!account) {
|
|
404
|
+
const accounts = (0, accounts_1.getEnabledLarkAccounts)(resolveConfig);
|
|
405
|
+
if (accounts.length === 0) {
|
|
406
|
+
throw new Error('No enabled Feishu accounts configured. ' + 'Please add appId and appSecret in config under channels.feishu');
|
|
407
|
+
}
|
|
408
|
+
if (accountIndex >= accounts.length) {
|
|
409
|
+
throw new Error(`Requested account index ${accountIndex} but only ${accounts.length} accounts available`);
|
|
410
|
+
}
|
|
411
|
+
const fallback = accounts[accountIndex];
|
|
412
|
+
if (!fallback.configured) {
|
|
413
|
+
throw new Error(`Account at index ${accountIndex} is not fully configured (missing appId or appSecret)`);
|
|
414
|
+
}
|
|
415
|
+
account = fallback;
|
|
416
|
+
}
|
|
417
|
+
// 2. 获取 SDK 实例(复用 LarkClient 的缓存)
|
|
418
|
+
const larkClient = lark_client_1.LarkClient.fromAccount(account);
|
|
419
|
+
// 3. 组装 ToolClient
|
|
420
|
+
return new ToolClient({
|
|
421
|
+
account,
|
|
422
|
+
senderOpenId: ticket?.senderOpenId,
|
|
423
|
+
sdk: larkClient.sdk,
|
|
424
|
+
config,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* Tool Scopes 配置
|
|
6
|
+
*
|
|
7
|
+
* 定义所有工具动作所需的飞书权限映射。
|
|
8
|
+
*
|
|
9
|
+
* ## 维护方式
|
|
10
|
+
*
|
|
11
|
+
* ⚠️ 此文件采用**手动维护**,新增或修改工具时需同步更新。
|
|
12
|
+
*
|
|
13
|
+
* ### 新增工具动作
|
|
14
|
+
*
|
|
15
|
+
* 1. 在 `ToolActionKey` 类型中添加新键:
|
|
16
|
+
* ```typescript
|
|
17
|
+
* export type ToolActionKey =
|
|
18
|
+
* | "feishu_calendar_event.create"
|
|
19
|
+
* | "feishu_new_tool.action" // 新增
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* 2. 在 `TOOL_SCOPES` 对象中添加对应配置:
|
|
23
|
+
* ```typescript
|
|
24
|
+
* export const TOOL_SCOPES: ToolScopeMapping = {
|
|
25
|
+
* "feishu_new_tool.action": [
|
|
26
|
+
* "required:scope:here"
|
|
27
|
+
* ],
|
|
28
|
+
* };
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* 3. 运行 TypeScript 类型检查验证一致性:
|
|
32
|
+
* ```bash
|
|
33
|
+
* cd openclaw/feishu && npx tsc --noEmit
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* ### 如何确定所需 Scope
|
|
37
|
+
*
|
|
38
|
+
* 1. **查阅飞书开放平台 API 文档**:https://open.feishu.cn/document
|
|
39
|
+
* 2. **使用 feishu-oapi-search skill**:在 Claude Code 中搜索 API 文档
|
|
40
|
+
* 3. **参考类似工具**:查看功能相近的工具的 scope 配置
|
|
41
|
+
* 4. **实际测试**:观察 API 调用的错误码(LARK_ERROR.APP_SCOPE_MISSING/99991672=应用缺权限,LARK_ERROR.USER_SCOPE_INSUFFICIENT/99991679=用户缺授权)
|
|
42
|
+
*
|
|
43
|
+
* 最后更新: 2026-03-03
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* 所有可用的工具动作键
|
|
47
|
+
*
|
|
48
|
+
* 格式:{tool_name}.{action_name}
|
|
49
|
+
*
|
|
50
|
+
* 示例:
|
|
51
|
+
* - "feishu_calendar_event.create"
|
|
52
|
+
* - "feishu_bitable_app_table_record.update"
|
|
53
|
+
*
|
|
54
|
+
* 总计:96 个工具动作
|
|
55
|
+
*/
|
|
56
|
+
export type ToolActionKey = 'feishu_bitable_app.copy' | 'feishu_bitable_app.create' | 'feishu_bitable_app.get' | 'feishu_bitable_app.list' | 'feishu_bitable_app.patch' | 'feishu_bitable_app_table.batch_create' | 'feishu_bitable_app_table.create' | 'feishu_bitable_app_table.list' | 'feishu_bitable_app_table.patch' | 'feishu_bitable_app_table_field.create' | 'feishu_bitable_app_table_field.delete' | 'feishu_bitable_app_table_field.list' | 'feishu_bitable_app_table_field.update' | 'feishu_bitable_app_table_record.batch_create' | 'feishu_bitable_app_table_record.batch_delete' | 'feishu_bitable_app_table_record.batch_update' | 'feishu_bitable_app_table_record.create' | 'feishu_bitable_app_table_record.delete' | 'feishu_bitable_app_table_record.list' | 'feishu_bitable_app_table_record.update' | 'feishu_bitable_app_table_view.create' | 'feishu_bitable_app_table_view.get' | 'feishu_bitable_app_table_view.list' | 'feishu_bitable_app_table_view.patch' | 'feishu_calendar_calendar.get' | 'feishu_calendar_calendar.list' | 'feishu_calendar_calendar.primary' | 'feishu_calendar_event.create' | 'feishu_calendar_event.delete' | 'feishu_calendar_event.get' | 'feishu_calendar_event.instance_view' | 'feishu_calendar_event.instances' | 'feishu_calendar_event.list' | 'feishu_calendar_event.patch' | 'feishu_calendar_event.reply' | 'feishu_calendar_event.search' | 'feishu_calendar_event_attendee.create' | 'feishu_calendar_event_attendee.list' | 'feishu_calendar_freebusy.list' | 'feishu_chat.get' | 'feishu_chat.search' | 'feishu_chat_members.default' | 'feishu_create_doc.default' | 'feishu_doc_comments.create' | 'feishu_doc_comments.list' | 'feishu_doc_comments.list_replies' | 'feishu_doc_comments.patch' | 'feishu_doc_comments.reply' | 'feishu_doc_media.download' | 'feishu_doc_media.insert' | 'feishu_drive_file.copy' | 'feishu_drive_file.delete' | 'feishu_drive_file.download' | 'feishu_drive_file.get_meta' | 'feishu_drive_file.list' | 'feishu_drive_file.move' | 'feishu_drive_file.upload' | 'feishu_fetch_doc.default' | 'feishu_get_user.basic_batch' | 'feishu_get_user.default' | 'feishu_im_user_fetch_resource.default' | 'feishu_im_user_get_messages.default' | 'feishu_im_user_message.reply' | 'feishu_im_user_message.send' | 'feishu_im_user_search_messages.default' | 'feishu_search_doc_wiki.search' | 'feishu_search_user.default' | 'feishu_task_attachment.upload' | 'feishu_task_comment.create' | 'feishu_task_comment.get' | 'feishu_task_comment.list' | 'feishu_task_section.create' | 'feishu_task_section.get' | 'feishu_task_section.list' | 'feishu_task_section.patch' | 'feishu_task_section.tasks' | 'feishu_task_subtask.create' | 'feishu_task_subtask.list' | 'feishu_task_task.create' | 'feishu_task_task.get' | 'feishu_task_task.list' | 'feishu_task_task.patch' | 'feishu_task_task.add_members' | 'feishu_task_task.append_steps' | 'feishu_task_tasklist.add_members' | 'feishu_task_tasklist.create' | 'feishu_task_tasklist.get' | 'feishu_task_tasklist.list' | 'feishu_task_tasklist.patch' | 'feishu_task_tasklist.tasks' | 'feishu_task_agent.register' | 'feishu_task_agent.update_profile' | 'feishu_update_doc.default' | 'feishu_wiki_space.create' | 'feishu_wiki_space.get' | 'feishu_wiki_space.list' | 'feishu_wiki_space_node.copy' | 'feishu_wiki_space_node.create' | 'feishu_wiki_space_node.get' | 'feishu_wiki_space_node.list' | 'feishu_wiki_space_node.move' | 'feishu_sheet.info' | 'feishu_sheet.read' | 'feishu_sheet.write' | 'feishu_sheet.append' | 'feishu_sheet.find' | 'feishu_sheet.create' | 'feishu_sheet.export';
|
|
57
|
+
/**
|
|
58
|
+
* Tool Scope 映射类型
|
|
59
|
+
*
|
|
60
|
+
* 将每个 ToolActionKey 映射到其所需的 scope 数组
|
|
61
|
+
*/
|
|
62
|
+
export type ToolScopeMapping = Record<ToolActionKey, string[]>;
|
|
63
|
+
/**
|
|
64
|
+
* Tool Scope 数据
|
|
65
|
+
*
|
|
66
|
+
* 每个工具动作所需的飞书权限列表(Required Scopes)
|
|
67
|
+
*
|
|
68
|
+
* ## 数据说明
|
|
69
|
+
*
|
|
70
|
+
* - 空数组 `[]` 表示该工具动作不需要任何权限
|
|
71
|
+
* - 多个权限表示需要同时拥有所有权限(AND 关系)
|
|
72
|
+
* - 所有 scope 都是 user scopes(用户级权限)
|
|
73
|
+
*
|
|
74
|
+
* ## 示例
|
|
75
|
+
*
|
|
76
|
+
* ```typescript
|
|
77
|
+
* TOOL_SCOPES["feishu_calendar_event.create"]
|
|
78
|
+
* // 返回: ["calendar:calendar.event:create", "calendar:calendar.event:update"]
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* @see {@link ToolActionKey} 所有可用的工具动作键
|
|
82
|
+
*/
|
|
83
|
+
export declare const TOOL_SCOPES: ToolScopeMapping;
|
|
84
|
+
/**
|
|
85
|
+
* 飞书插件运行必须开通的应用身份权限清单
|
|
86
|
+
*
|
|
87
|
+
* 这些权限是插件基础功能(消息接收、卡片交互、基本信息查询等)所必需的,
|
|
88
|
+
* 如果缺失这些权限,插件将无法正常工作。
|
|
89
|
+
*
|
|
90
|
+
* 权限分类:
|
|
91
|
+
* - im:message.* - 消息接收和发送
|
|
92
|
+
* - im:chat.* - 群聊管理
|
|
93
|
+
* - im:resource - 消息资源(图片、文件等)
|
|
94
|
+
* - cardkit:card.* - 卡片交互
|
|
95
|
+
* - application:application:self_manage - 应用自身权限查询(权限检查基础)
|
|
96
|
+
* - contact:contact.base:readonly - 通讯录基础信息
|
|
97
|
+
* - docx:document:readonly - 文档基础只读(文档链接预览等)
|
|
98
|
+
*
|
|
99
|
+
* 最后更新: 2026-03-03
|
|
100
|
+
*/
|
|
101
|
+
export declare const REQUIRED_APP_SCOPES: readonly ["contact:contact.base:readonly", "docx:document:readonly", "im:chat:read", "im:chat:update", "im:message.group_at_msg:readonly", "im:message.p2p_msg:readonly", "im:message.pins:read", "im:message.pins:write_only", "im:message.reactions:read", "im:message.reactions:write_only", "im:message:readonly", "im:message:recall", "im:message:send_as_bot", "im:message:send_multi_users", "im:message:send_sys_msg", "im:message:update", "im:resource", "application:application:self_manage", "cardkit:card:write", "cardkit:card:read"];
|
|
102
|
+
/**
|
|
103
|
+
* 必需应用权限类型
|
|
104
|
+
*/
|
|
105
|
+
export type RequiredAppScope = (typeof REQUIRED_APP_SCOPES)[number];
|
|
106
|
+
/**
|
|
107
|
+
* 必需权限用途说明
|
|
108
|
+
*
|
|
109
|
+
* 描述每个必需权限的具体用途,帮助管理员理解为什么需要开通该权限。
|
|
110
|
+
*/
|
|
111
|
+
export declare const REQUIRED_SCOPE_DESCRIPTIONS: Record<RequiredAppScope, string>;
|
|
112
|
+
/**
|
|
113
|
+
* 高敏感权限清单
|
|
114
|
+
*
|
|
115
|
+
* 这些权限具有较高的敏感度,不应在批量授权时自动申请。
|
|
116
|
+
* 用户需要明确知晓这些权限的影响后,才能手动授权。
|
|
117
|
+
*
|
|
118
|
+
* 权限说明:
|
|
119
|
+
* - im:message.send_as_user - 以用户身份发送消息(高风险,可能被滥用发送钓鱼或垃圾消息)
|
|
120
|
+
* - space:document:delete - 删除云文档
|
|
121
|
+
* - calendar:calendar.event:delete - 删除日程
|
|
122
|
+
* - base:table:delete - 删除多维表格数据表
|
|
123
|
+
*
|
|
124
|
+
* 使用场景:
|
|
125
|
+
* - 批量授权时会自动过滤掉这些权限
|
|
126
|
+
* - 需要这些权限的功能会单独提示用户授权
|
|
127
|
+
*
|
|
128
|
+
* 最后更新: 2026-03-17
|
|
129
|
+
*/
|
|
130
|
+
export declare const SENSITIVE_SCOPES: readonly ["im:message.send_as_user", "space:document:delete", "calendar:calendar.event:delete", "base:table:delete"];
|
|
131
|
+
/**
|
|
132
|
+
* 高敏感权限类型
|
|
133
|
+
*/
|
|
134
|
+
export type SensitiveScope = (typeof SENSITIVE_SCOPES)[number];
|
|
135
|
+
/**
|
|
136
|
+
* 过滤掉高敏感权限
|
|
137
|
+
*
|
|
138
|
+
* 用于批量授权时排除高敏感权限,这些权限需要用户明确授权。
|
|
139
|
+
*
|
|
140
|
+
* @param scopes - 原始权限列表
|
|
141
|
+
* @returns 过滤后的权限列表(不包含高敏感权限)
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```typescript
|
|
145
|
+
* const allScopes = ["im:message", "im:message.send_as_user", "calendar:calendar:read"];
|
|
146
|
+
* const safeScopes = filterSensitiveScopes(allScopes);
|
|
147
|
+
* // 返回: ["im:message", "calendar:calendar:read"]
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
export declare function filterSensitiveScopes(scopes: string[]): string[];
|
|
151
|
+
/**
|
|
152
|
+
* 工具动作总数: 96
|
|
153
|
+
* 唯一 scope 总数: 74
|
|
154
|
+
* 必需应用权限总数: 20
|
|
155
|
+
* 高敏感权限总数: 4
|
|
156
|
+
*/
|