@lark-project/openclaw-lark-project 2026.3.131
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 +80 -0
- package/README.zh.md +80 -0
- package/dist/index.js +172 -0
- package/dist/index.js.map +7 -0
- package/dist/skills/feishu-bitable/SKILL.md +248 -0
- package/dist/skills/feishu-bitable/references/examples.md +813 -0
- package/dist/skills/feishu-bitable/references/field-properties.md +763 -0
- package/dist/skills/feishu-bitable/references/record-values.md +911 -0
- package/dist/skills/feishu-calendar/SKILL.md +244 -0
- package/dist/skills/feishu-channel-rules/SKILL.md +18 -0
- package/dist/skills/feishu-channel-rules/references/markdown-syntax.md +138 -0
- package/dist/skills/feishu-create-doc/SKILL.md +719 -0
- package/dist/skills/feishu-fetch-doc/SKILL.md +93 -0
- package/dist/skills/feishu-im-read/SKILL.md +163 -0
- package/dist/skills/feishu-project/SKILL.md +122 -0
- package/dist/skills/feishu-task/SKILL.md +293 -0
- package/dist/skills/feishu-troubleshoot/SKILL.md +70 -0
- package/dist/skills/feishu-update-doc/SKILL.md +285 -0
- package/dist/src/card/builder.js +293 -0
- package/dist/src/card/builder.js.map +7 -0
- package/dist/src/card/cardkit.js +126 -0
- package/dist/src/card/cardkit.js.map +7 -0
- package/dist/src/card/flush-controller.js +107 -0
- package/dist/src/card/flush-controller.js.map +7 -0
- package/dist/src/card/markdown-style.js +57 -0
- package/dist/src/card/markdown-style.js.map +7 -0
- package/dist/src/card/reply-dispatcher-types.js +39 -0
- package/dist/src/card/reply-dispatcher-types.js.map +7 -0
- package/dist/src/card/reply-dispatcher.js +245 -0
- package/dist/src/card/reply-dispatcher.js.map +7 -0
- package/dist/src/card/reply-mode.js +29 -0
- package/dist/src/card/reply-mode.js.map +7 -0
- package/dist/src/card/streaming-card-controller.js +653 -0
- package/dist/src/card/streaming-card-controller.js.map +7 -0
- package/dist/src/card/unavailable-guard.js +76 -0
- package/dist/src/card/unavailable-guard.js.map +7 -0
- package/dist/src/channel/abort-detect.js +79 -0
- package/dist/src/channel/abort-detect.js.map +7 -0
- package/dist/src/channel/chat-queue.js +50 -0
- package/dist/src/channel/chat-queue.js.map +7 -0
- package/dist/src/channel/config-adapter.js +89 -0
- package/dist/src/channel/config-adapter.js.map +7 -0
- package/dist/src/channel/directory.js +133 -0
- package/dist/src/channel/directory.js.map +7 -0
- package/dist/src/channel/event-handlers.js +175 -0
- package/dist/src/channel/event-handlers.js.map +7 -0
- package/dist/src/channel/monitor.js +108 -0
- package/dist/src/channel/monitor.js.map +7 -0
- package/dist/src/channel/onboarding-config.js +76 -0
- package/dist/src/channel/onboarding-config.js.map +7 -0
- package/dist/src/channel/onboarding-migrate.js +55 -0
- package/dist/src/channel/onboarding-migrate.js.map +7 -0
- package/dist/src/channel/onboarding.js +285 -0
- package/dist/src/channel/onboarding.js.map +7 -0
- package/dist/src/channel/plugin.js +260 -0
- package/dist/src/channel/plugin.js.map +7 -0
- package/dist/src/channel/probe.js +14 -0
- package/dist/src/channel/probe.js.map +7 -0
- package/dist/src/channel/types.js +1 -0
- package/dist/src/channel/types.js.map +7 -0
- package/dist/src/commands/auth.js +73 -0
- package/dist/src/commands/auth.js.map +7 -0
- package/dist/src/commands/diagnose.js +658 -0
- package/dist/src/commands/diagnose.js.map +7 -0
- package/dist/src/commands/doctor.js +327 -0
- package/dist/src/commands/doctor.js.map +7 -0
- package/dist/src/commands/index.js +124 -0
- package/dist/src/commands/index.js.map +7 -0
- package/dist/src/core/accounts.js +129 -0
- package/dist/src/core/accounts.js.map +7 -0
- package/dist/src/core/agent-config.js +60 -0
- package/dist/src/core/agent-config.js.map +7 -0
- package/dist/src/core/api-error.js +55 -0
- package/dist/src/core/api-error.js.map +7 -0
- package/dist/src/core/app-owner-fallback.js +17 -0
- package/dist/src/core/app-owner-fallback.js.map +7 -0
- package/dist/src/core/app-scope-checker.js +95 -0
- package/dist/src/core/app-scope-checker.js.map +7 -0
- package/dist/src/core/auth-errors.js +120 -0
- package/dist/src/core/auth-errors.js.map +7 -0
- package/dist/src/core/chat-info-cache.js +102 -0
- package/dist/src/core/chat-info-cache.js.map +7 -0
- package/dist/src/core/config-schema.js +150 -0
- package/dist/src/core/config-schema.js.map +7 -0
- package/dist/src/core/device-flow.js +174 -0
- package/dist/src/core/device-flow.js.map +7 -0
- package/dist/src/core/feishu-fetch.js +12 -0
- package/dist/src/core/feishu-fetch.js.map +7 -0
- package/dist/src/core/footer-config.js +16 -0
- package/dist/src/core/footer-config.js.map +7 -0
- package/dist/src/core/lark-client.js +322 -0
- package/dist/src/core/lark-client.js.map +7 -0
- package/dist/src/core/lark-logger.js +92 -0
- package/dist/src/core/lark-logger.js.map +7 -0
- package/dist/src/core/lark-ticket.js +18 -0
- package/dist/src/core/lark-ticket.js.map +7 -0
- package/dist/src/core/message-unavailable.js +119 -0
- package/dist/src/core/message-unavailable.js.map +7 -0
- package/dist/src/core/owner-policy.js +25 -0
- package/dist/src/core/owner-policy.js.map +7 -0
- package/dist/src/core/permission-url.js +37 -0
- package/dist/src/core/permission-url.js.map +7 -0
- package/dist/src/core/project-auth.js +177 -0
- package/dist/src/core/project-auth.js.map +7 -0
- package/dist/src/core/project-oauth-flow.js +124 -0
- package/dist/src/core/project-oauth-flow.js.map +7 -0
- package/dist/src/core/project-token-store.js +172 -0
- package/dist/src/core/project-token-store.js.map +7 -0
- package/dist/src/core/raw-request.js +45 -0
- package/dist/src/core/raw-request.js.map +7 -0
- package/dist/src/core/scope-manager.js +62 -0
- package/dist/src/core/scope-manager.js.map +7 -0
- package/dist/src/core/security-check.js +118 -0
- package/dist/src/core/security-check.js.map +7 -0
- package/dist/src/core/shutdown-hooks.js +37 -0
- package/dist/src/core/shutdown-hooks.js.map +7 -0
- package/dist/src/core/targets.js +55 -0
- package/dist/src/core/targets.js.map +7 -0
- package/dist/src/core/token-store.js +215 -0
- package/dist/src/core/token-store.js.map +7 -0
- package/dist/src/core/tool-client.js +335 -0
- package/dist/src/core/tool-client.js.map +7 -0
- package/dist/src/core/tool-scopes.js +207 -0
- package/dist/src/core/tool-scopes.js.map +7 -0
- package/dist/src/core/tools-config.js +57 -0
- package/dist/src/core/tools-config.js.map +7 -0
- package/dist/src/core/types.js +1 -0
- package/dist/src/core/types.js.map +7 -0
- package/dist/src/core/uat-client.js +124 -0
- package/dist/src/core/uat-client.js.map +7 -0
- package/dist/src/core/version.js +27 -0
- package/dist/src/core/version.js.map +7 -0
- package/dist/src/messaging/converters/audio.js +19 -0
- package/dist/src/messaging/converters/audio.js.map +7 -0
- package/dist/src/messaging/converters/calendar.js +46 -0
- package/dist/src/messaging/converters/calendar.js.map +7 -0
- package/dist/src/messaging/converters/content-converter.js +61 -0
- package/dist/src/messaging/converters/content-converter.js.map +7 -0
- package/dist/src/messaging/converters/file.js +18 -0
- package/dist/src/messaging/converters/file.js.map +7 -0
- package/dist/src/messaging/converters/folder.js +18 -0
- package/dist/src/messaging/converters/folder.js.map +7 -0
- package/dist/src/messaging/converters/hongbao.js +14 -0
- package/dist/src/messaging/converters/hongbao.js.map +7 -0
- package/dist/src/messaging/converters/image.js +16 -0
- package/dist/src/messaging/converters/image.js.map +7 -0
- package/dist/src/messaging/converters/index.js +48 -0
- package/dist/src/messaging/converters/index.js.map +7 -0
- package/dist/src/messaging/converters/interactive/card-converter.js +1040 -0
- package/dist/src/messaging/converters/interactive/card-converter.js.map +7 -0
- package/dist/src/messaging/converters/interactive/card-utils.js +36 -0
- package/dist/src/messaging/converters/interactive/card-utils.js.map +7 -0
- package/dist/src/messaging/converters/interactive/index.js +19 -0
- package/dist/src/messaging/converters/interactive/index.js.map +7 -0
- package/dist/src/messaging/converters/interactive/legacy.js +53 -0
- package/dist/src/messaging/converters/interactive/legacy.js.map +7 -0
- package/dist/src/messaging/converters/interactive/types.js +23 -0
- package/dist/src/messaging/converters/interactive/types.js.map +7 -0
- package/dist/src/messaging/converters/location.js +17 -0
- package/dist/src/messaging/converters/location.js.map +7 -0
- package/dist/src/messaging/converters/merge-forward.js +143 -0
- package/dist/src/messaging/converters/merge-forward.js.map +7 -0
- package/dist/src/messaging/converters/post.js +113 -0
- package/dist/src/messaging/converters/post.js.map +7 -0
- package/dist/src/messaging/converters/share.js +22 -0
- package/dist/src/messaging/converters/share.js.map +7 -0
- package/dist/src/messaging/converters/sticker.js +16 -0
- package/dist/src/messaging/converters/sticker.js.map +7 -0
- package/dist/src/messaging/converters/system.js +25 -0
- package/dist/src/messaging/converters/system.js.map +7 -0
- package/dist/src/messaging/converters/text.js +12 -0
- package/dist/src/messaging/converters/text.js.map +7 -0
- package/dist/src/messaging/converters/todo.js +37 -0
- package/dist/src/messaging/converters/todo.js.map +7 -0
- package/dist/src/messaging/converters/types.js +1 -0
- package/dist/src/messaging/converters/types.js.map +7 -0
- package/dist/src/messaging/converters/unknown.js +13 -0
- package/dist/src/messaging/converters/unknown.js.map +7 -0
- package/dist/src/messaging/converters/utils.js +35 -0
- package/dist/src/messaging/converters/utils.js.map +7 -0
- package/dist/src/messaging/converters/video-chat.js +21 -0
- package/dist/src/messaging/converters/video-chat.js.map +7 -0
- package/dist/src/messaging/converters/video.js +30 -0
- package/dist/src/messaging/converters/video.js.map +7 -0
- package/dist/src/messaging/converters/vote.js +24 -0
- package/dist/src/messaging/converters/vote.js.map +7 -0
- package/dist/src/messaging/inbound/dedup.js +82 -0
- package/dist/src/messaging/inbound/dedup.js.map +7 -0
- package/dist/src/messaging/inbound/dispatch-builders.js +98 -0
- package/dist/src/messaging/inbound/dispatch-builders.js.map +7 -0
- package/dist/src/messaging/inbound/dispatch-commands.js +94 -0
- package/dist/src/messaging/inbound/dispatch-commands.js.map +7 -0
- package/dist/src/messaging/inbound/dispatch-context.js +96 -0
- package/dist/src/messaging/inbound/dispatch-context.js.map +7 -0
- package/dist/src/messaging/inbound/dispatch.js +150 -0
- package/dist/src/messaging/inbound/dispatch.js.map +7 -0
- package/dist/src/messaging/inbound/enrich.js +137 -0
- package/dist/src/messaging/inbound/enrich.js.map +7 -0
- package/dist/src/messaging/inbound/gate-effects.js +28 -0
- package/dist/src/messaging/inbound/gate-effects.js.map +7 -0
- package/dist/src/messaging/inbound/gate.js +163 -0
- package/dist/src/messaging/inbound/gate.js.map +7 -0
- package/dist/src/messaging/inbound/handler.js +132 -0
- package/dist/src/messaging/inbound/handler.js.map +7 -0
- package/dist/src/messaging/inbound/media-resolver.js +70 -0
- package/dist/src/messaging/inbound/media-resolver.js.map +7 -0
- package/dist/src/messaging/inbound/mention.js +50 -0
- package/dist/src/messaging/inbound/mention.js.map +7 -0
- package/dist/src/messaging/inbound/parse-io.js +41 -0
- package/dist/src/messaging/inbound/parse-io.js.map +7 -0
- package/dist/src/messaging/inbound/parse.js +79 -0
- package/dist/src/messaging/inbound/parse.js.map +7 -0
- package/dist/src/messaging/inbound/permission.js +30 -0
- package/dist/src/messaging/inbound/permission.js.map +7 -0
- package/dist/src/messaging/inbound/policy.js +83 -0
- package/dist/src/messaging/inbound/policy.js.map +7 -0
- package/dist/src/messaging/inbound/reaction-handler.js +162 -0
- package/dist/src/messaging/inbound/reaction-handler.js.map +7 -0
- package/dist/src/messaging/inbound/user-name-cache.js +172 -0
- package/dist/src/messaging/inbound/user-name-cache.js.map +7 -0
- package/dist/src/messaging/outbound/actions.js +239 -0
- package/dist/src/messaging/outbound/actions.js.map +7 -0
- package/dist/src/messaging/outbound/chat-manage.js +74 -0
- package/dist/src/messaging/outbound/chat-manage.js.map +7 -0
- package/dist/src/messaging/outbound/deliver.js +162 -0
- package/dist/src/messaging/outbound/deliver.js.map +7 -0
- package/dist/src/messaging/outbound/fetch.js +7 -0
- package/dist/src/messaging/outbound/fetch.js.map +7 -0
- package/dist/src/messaging/outbound/forward.js +31 -0
- package/dist/src/messaging/outbound/forward.js.map +7 -0
- package/dist/src/messaging/outbound/media-url-utils.js +101 -0
- package/dist/src/messaging/outbound/media-url-utils.js.map +7 -0
- package/dist/src/messaging/outbound/media.js +463 -0
- package/dist/src/messaging/outbound/media.js.map +7 -0
- package/dist/src/messaging/outbound/outbound.js +95 -0
- package/dist/src/messaging/outbound/outbound.js.map +7 -0
- package/dist/src/messaging/outbound/reactions.js +312 -0
- package/dist/src/messaging/outbound/reactions.js.map +7 -0
- package/dist/src/messaging/outbound/send.js +194 -0
- package/dist/src/messaging/outbound/send.js.map +7 -0
- package/dist/src/messaging/outbound/typing.js +77 -0
- package/dist/src/messaging/outbound/typing.js.map +7 -0
- package/dist/src/messaging/shared/message-lookup.js +84 -0
- package/dist/src/messaging/shared/message-lookup.js.map +7 -0
- package/dist/src/messaging/types.js +1 -0
- package/dist/src/messaging/types.js.map +7 -0
- package/dist/src/tools/auto-auth.js +714 -0
- package/dist/src/tools/auto-auth.js.map +7 -0
- package/dist/src/tools/helpers.js +133 -0
- package/dist/src/tools/helpers.js.map +7 -0
- package/dist/src/tools/mcp/doc/create.js +35 -0
- package/dist/src/tools/mcp/doc/create.js.map +7 -0
- package/dist/src/tools/mcp/doc/fetch.js +33 -0
- package/dist/src/tools/mcp/doc/fetch.js.map +7 -0
- package/dist/src/tools/mcp/doc/index.js +32 -0
- package/dist/src/tools/mcp/doc/index.js.map +7 -0
- package/dist/src/tools/mcp/doc/update.js +61 -0
- package/dist/src/tools/mcp/doc/update.js.map +7 -0
- package/dist/src/tools/mcp/project/endpoint.js +25 -0
- package/dist/src/tools/mcp/project/endpoint.js.map +7 -0
- package/dist/src/tools/mcp/project/index.js +27 -0
- package/dist/src/tools/mcp/project/index.js.map +7 -0
- package/dist/src/tools/mcp/project/tools.js +579 -0
- package/dist/src/tools/mcp/project/tools.js.map +7 -0
- package/dist/src/tools/mcp/shared.js +170 -0
- package/dist/src/tools/mcp/shared.js.map +7 -0
- package/dist/src/tools/oapi/bitable/app-table-field.js +244 -0
- package/dist/src/tools/oapi/bitable/app-table-field.js.map +7 -0
- package/dist/src/tools/oapi/bitable/app-table-record.js +501 -0
- package/dist/src/tools/oapi/bitable/app-table-record.js.map +7 -0
- package/dist/src/tools/oapi/bitable/app-table-view.js +226 -0
- package/dist/src/tools/oapi/bitable/app-table-view.js.map +7 -0
- package/dist/src/tools/oapi/bitable/app-table.js +278 -0
- package/dist/src/tools/oapi/bitable/app-table.js.map +7 -0
- package/dist/src/tools/oapi/bitable/app.js +200 -0
- package/dist/src/tools/oapi/bitable/app.js.map +7 -0
- package/dist/src/tools/oapi/bitable/index.js +13 -0
- package/dist/src/tools/oapi/bitable/index.js.map +7 -0
- package/dist/src/tools/oapi/calendar/calendar.js +131 -0
- package/dist/src/tools/oapi/calendar/calendar.js.map +7 -0
- package/dist/src/tools/oapi/calendar/event-attendee.js +301 -0
- package/dist/src/tools/oapi/calendar/event-attendee.js.map +7 -0
- package/dist/src/tools/oapi/calendar/event.js +834 -0
- package/dist/src/tools/oapi/calendar/event.js.map +7 -0
- package/dist/src/tools/oapi/calendar/freebusy.js +111 -0
- package/dist/src/tools/oapi/calendar/freebusy.js.map +7 -0
- package/dist/src/tools/oapi/calendar/index.js +11 -0
- package/dist/src/tools/oapi/calendar/index.js.map +7 -0
- package/dist/src/tools/oapi/chat/chat.js +132 -0
- package/dist/src/tools/oapi/chat/chat.js.map +7 -0
- package/dist/src/tools/oapi/chat/index.js +11 -0
- package/dist/src/tools/oapi/chat/index.js.map +7 -0
- package/dist/src/tools/oapi/chat/members.js +83 -0
- package/dist/src/tools/oapi/chat/members.js.map +7 -0
- package/dist/src/tools/oapi/common/get-user.js +95 -0
- package/dist/src/tools/oapi/common/get-user.js.map +7 -0
- package/dist/src/tools/oapi/common/index.js +7 -0
- package/dist/src/tools/oapi/common/index.js.map +7 -0
- package/dist/src/tools/oapi/common/search-user.js +67 -0
- package/dist/src/tools/oapi/common/search-user.js.map +7 -0
- package/dist/src/tools/oapi/drive/doc-comments.js +310 -0
- package/dist/src/tools/oapi/drive/doc-comments.js.map +7 -0
- package/dist/src/tools/oapi/drive/doc-media.js +314 -0
- package/dist/src/tools/oapi/drive/doc-media.js.map +7 -0
- package/dist/src/tools/oapi/drive/file.js +548 -0
- package/dist/src/tools/oapi/drive/file.js.map +7 -0
- package/dist/src/tools/oapi/drive/index.js +29 -0
- package/dist/src/tools/oapi/drive/index.js.map +7 -0
- package/dist/src/tools/oapi/helpers.js +199 -0
- package/dist/src/tools/oapi/helpers.js.map +7 -0
- package/dist/src/tools/oapi/im/format-messages.js +128 -0
- package/dist/src/tools/oapi/im/format-messages.js.map +7 -0
- package/dist/src/tools/oapi/im/index.js +15 -0
- package/dist/src/tools/oapi/im/index.js.map +7 -0
- package/dist/src/tools/oapi/im/message-read.js +404 -0
- package/dist/src/tools/oapi/im/message-read.js.map +7 -0
- package/dist/src/tools/oapi/im/message.js +179 -0
- package/dist/src/tools/oapi/im/message.js.map +7 -0
- package/dist/src/tools/oapi/im/resource.js +126 -0
- package/dist/src/tools/oapi/im/resource.js.map +7 -0
- package/dist/src/tools/oapi/im/time-utils.js +169 -0
- package/dist/src/tools/oapi/im/time-utils.js.map +7 -0
- package/dist/src/tools/oapi/im/user-name-uat.js +103 -0
- package/dist/src/tools/oapi/im/user-name-uat.js.map +7 -0
- package/dist/src/tools/oapi/index.js +56 -0
- package/dist/src/tools/oapi/index.js.map +7 -0
- package/dist/src/tools/oapi/sdk-types.js +1 -0
- package/dist/src/tools/oapi/sdk-types.js.map +7 -0
- package/dist/src/tools/oapi/search/doc-search.js +215 -0
- package/dist/src/tools/oapi/search/doc-search.js.map +7 -0
- package/dist/src/tools/oapi/search/index.js +25 -0
- package/dist/src/tools/oapi/search/index.js.map +7 -0
- package/dist/src/tools/oapi/sheets/index.js +25 -0
- package/dist/src/tools/oapi/sheets/index.js.map +7 -0
- package/dist/src/tools/oapi/sheets/sheet.js +652 -0
- package/dist/src/tools/oapi/sheets/sheet.js.map +7 -0
- package/dist/src/tools/oapi/task/comment.js +151 -0
- package/dist/src/tools/oapi/task/comment.js.map +7 -0
- package/dist/src/tools/oapi/task/index.js +11 -0
- package/dist/src/tools/oapi/task/index.js.map +7 -0
- package/dist/src/tools/oapi/task/subtask.js +175 -0
- package/dist/src/tools/oapi/task/subtask.js.map +7 -0
- package/dist/src/tools/oapi/task/task.js +405 -0
- package/dist/src/tools/oapi/task/task.js.map +7 -0
- package/dist/src/tools/oapi/task/tasklist.js +366 -0
- package/dist/src/tools/oapi/task/tasklist.js.map +7 -0
- package/dist/src/tools/oapi/wiki/index.js +27 -0
- package/dist/src/tools/oapi/wiki/index.js.map +7 -0
- package/dist/src/tools/oapi/wiki/space-node.js +311 -0
- package/dist/src/tools/oapi/wiki/space-node.js.map +7 -0
- package/dist/src/tools/oapi/wiki/space.js +148 -0
- package/dist/src/tools/oapi/wiki/space.js.map +7 -0
- package/dist/src/tools/oauth-batch-auth.js +125 -0
- package/dist/src/tools/oauth-batch-auth.js.map +7 -0
- package/dist/src/tools/oauth-cards.js +269 -0
- package/dist/src/tools/oauth-cards.js.map +7 -0
- package/dist/src/tools/oauth.js +538 -0
- package/dist/src/tools/oauth.js.map +7 -0
- package/dist/src/tools/onboarding-auth.js +101 -0
- package/dist/src/tools/onboarding-auth.js.map +7 -0
- package/dist/src/tools/project-oauth.js +305 -0
- package/dist/src/tools/project-oauth.js.map +7 -0
- package/dist/src/tools/tat/im/index.js +9 -0
- package/dist/src/tools/tat/im/index.js.map +7 -0
- package/dist/src/tools/tat/im/resource.js +123 -0
- package/dist/src/tools/tat/im/resource.js.map +7 -0
- package/package.json +64 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/tools/oapi/calendar/event.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * feishu_calendar_event tool -- Manage Feishu calendar events.\n *\n * P0 Actions: create, list, get\n *\n * Uses the Feishu Calendar API:\n * - create: POST /open-apis/calendar/v4/calendars/:calendar_id/events\n * POST /open-apis/calendar/v4/calendars/:calendar_id/events/:event_id/attendees/batch_create\n * - list: GET /open-apis/calendar/v4/calendars/:calendar_id/events/instance_view\n * - get: GET /open-apis/calendar/v4/calendars/:calendar_id/events/:event_id\n */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { OpenClawPluginApi } from 'openclaw/plugin-sdk';\nimport { Type } from '@sinclair/typebox';\nimport {\n json,\n createToolContext,\n parseTimeToTimestamp,\n assertLarkOk,\n handleInvokeErrorWithAutoAuth,\n formatLarkError,\n unixTimestampToISO8601,\n} from '../helpers';\nimport type { CalendarPrimaryData, PaginatedData } from '../sdk-types';\n\n// ---------------------------------------------------------------------------\n// Schema\n// ---------------------------------------------------------------------------\n\nconst FeishuCalendarEventSchema = Type.Union([\n // CREATE\n Type.Object({\n action: Type.Literal('create'),\n start_time: Type.String({\n description: \"\u5F00\u59CB\u65F6\u95F4\uFF08\u5FC5\u586B\uFF09\u3002ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\",\n }),\n end_time: Type.String({\n description: '\u7ED3\u675F\u65F6\u95F4\uFF08\u5FC5\u586B\uFF09\u3002\u683C\u5F0F\u540C start_time\u3002\u5982\u679C\u7528\u6237\u672A\u6307\u5B9A\u65F6\u957F\uFF0C\u9ED8\u8BA4\u4E3A\u5F00\u59CB\u65F6\u95F4\u540E1\u5C0F\u65F6\u3002',\n }),\n summary: Type.Optional(\n Type.String({\n description: '\u65E5\u7A0B\u6807\u9898\uFF08\u53EF\u9009\uFF0C\u4F46\u5F3A\u70C8\u5EFA\u8BAE\u63D0\u4F9B\uFF09',\n }),\n ),\n user_open_id: Type.Optional(\n Type.String({\n description:\n '\u5F53\u524D\u8BF7\u6C42\u7528\u6237\u7684 open_id\uFF08\u53EF\u9009\uFF0C\u4F46\u5F3A\u70C8\u5EFA\u8BAE\u63D0\u4F9B\uFF09\u3002\u4ECE\u6D88\u606F\u4E0A\u4E0B\u6587\u7684 SenderId \u5B57\u6BB5\u83B7\u53D6\uFF0C\u683C\u5F0F\u4E3A ou_xxx\u3002\u65E5\u7A0B\u521B\u5EFA\u5728\u5E94\u7528\u65E5\u5386\u4E0A\uFF0C\u5FC5\u987B\u901A\u8FC7\u6B64\u53C2\u6570\u5C06\u7528\u6237\u52A0\u4E3A\u53C2\u4F1A\u4EBA\uFF0C\u65E5\u7A0B\u624D\u4F1A\u51FA\u73B0\u5728\u7528\u6237\u7684\u98DE\u4E66\u65E5\u5386\u4E2D\u3002',\n }),\n ),\n calendar_id: Type.Optional(\n Type.String({\n description: 'Calendar ID (optional; primary calendar used if omitted)',\n }),\n ),\n description: Type.Optional(\n Type.String({\n description: '\u65E5\u7A0B\u63CF\u8FF0',\n }),\n ),\n attendees: Type.Optional(\n Type.Array(\n Type.Object({\n type: Type.Union([\n Type.Literal('user'),\n Type.Literal('chat'),\n Type.Literal('resource'),\n Type.Literal('third_party'),\n ]),\n id: Type.String({\n description: 'Attendee open_id, chat_id, resource_id, or email',\n }),\n }),\n {\n description:\n \"\u53C2\u4F1A\u4EBA\u5217\u8868\uFF08\u5F3A\u70C8\u5EFA\u8BAE\u63D0\u4F9B\uFF0C\u5426\u5219\u65E5\u7A0B\u53EA\u5728\u5E94\u7528\u65E5\u5386\u4E0A\uFF0C\u7528\u6237\u770B\u4E0D\u5230\uFF09\u3002type='user' \u65F6 id \u586B open_id\uFF0Ctype='third_party' \u65F6 id \u586B\u90AE\u7BB1\u3002\",\n },\n ),\n ),\n vchat: Type.Optional(\n Type.Object(\n {\n vc_type: Type.Optional(\n Type.Union([Type.Literal('vc'), Type.Literal('third_party'), Type.Literal('no_meeting')], {\n description:\n '\u89C6\u9891\u4F1A\u8BAE\u7C7B\u578B\uFF1Avc\uFF08\u98DE\u4E66\u89C6\u9891\u4F1A\u8BAE\uFF09\u3001third_party\uFF08\u7B2C\u4E09\u65B9\u94FE\u63A5\uFF09\u3001no_meeting\uFF08\u65E0\u89C6\u9891\u4F1A\u8BAE\uFF09\u3002\u9ED8\u8BA4\u4E3A\u7A7A\uFF0C\u9996\u6B21\u6DFB\u52A0\u53C2\u4E0E\u4EBA\u65F6\u81EA\u52A8\u751F\u6210\u98DE\u4E66\u89C6\u9891\u4F1A\u8BAE\u3002',\n }),\n ),\n icon_type: Type.Optional(\n Type.Union([Type.Literal('vc'), Type.Literal('live'), Type.Literal('default')], {\n description: '\u7B2C\u4E09\u65B9\u89C6\u9891\u4F1A\u8BAE icon \u7C7B\u578B\uFF08\u4EC5 vc_type=third_party \u65F6\u6709\u6548\uFF09\u3002',\n }),\n ),\n description: Type.Optional(\n Type.String({\n description: '\u7B2C\u4E09\u65B9\u89C6\u9891\u4F1A\u8BAE\u6587\u6848\uFF08\u4EC5 vc_type=third_party \u65F6\u6709\u6548\uFF09\u3002',\n }),\n ),\n meeting_url: Type.Optional(\n Type.String({\n description: '\u7B2C\u4E09\u65B9\u89C6\u9891\u4F1A\u8BAE\u94FE\u63A5\uFF08\u4EC5 vc_type=third_party \u65F6\u6709\u6548\uFF09\u3002',\n }),\n ),\n },\n {\n description: '\u89C6\u9891\u4F1A\u8BAE\u4FE1\u606F\u3002\u4E0D\u4F20\u5219\u9ED8\u8BA4\u5728\u9996\u6B21\u6DFB\u52A0\u53C2\u4E0E\u4EBA\u65F6\u81EA\u52A8\u751F\u6210\u98DE\u4E66\u89C6\u9891\u4F1A\u8BAE\u3002',\n },\n ),\n ),\n visibility: Type.Optional(\n Type.Union([Type.Literal('default'), Type.Literal('public'), Type.Literal('private')], {\n description:\n '\u65E5\u7A0B\u516C\u5F00\u8303\u56F4\u3002default\uFF08\u9ED8\u8BA4\uFF0C\u8DDF\u968F\u65E5\u5386\u6743\u9650\uFF09\u3001public\uFF08\u516C\u5F00\u8BE6\u60C5\uFF09\u3001private\uFF08\u79C1\u5BC6\uFF0C\u4EC5\u81EA\u5DF1\u53EF\u89C1\uFF09\u3002\u9ED8\u8BA4\u503C\uFF1Adefault\u3002',\n }),\n ),\n attendee_ability: Type.Optional(\n Type.Union(\n [\n Type.Literal('none'),\n Type.Literal('can_see_others'),\n Type.Literal('can_invite_others'),\n Type.Literal('can_modify_event'),\n ],\n {\n description:\n '\u53C2\u4E0E\u4EBA\u6743\u9650\u3002none\uFF08\u65E0\u6CD5\u7F16\u8F91\u3001\u9080\u8BF7\u3001\u67E5\u770B\uFF09\u3001can_see_others\uFF08\u53EF\u67E5\u770B\u53C2\u4E0E\u4EBA\u5217\u8868\uFF09\u3001can_invite_others\uFF08\u53EF\u9080\u8BF7\u5176\u4ED6\u4EBA\uFF09\u3001can_modify_event\uFF08\u53EF\u7F16\u8F91\u65E5\u7A0B\uFF09\u3002\u9ED8\u8BA4\u503C\uFF1Anone\u3002',\n },\n ),\n ),\n free_busy_status: Type.Optional(\n Type.Union([Type.Literal('busy'), Type.Literal('free')], {\n description: '\u65E5\u7A0B\u5360\u7528\u7684\u5FD9\u95F2\u72B6\u6001\u3002busy\uFF08\u5FD9\u788C\uFF09\u3001free\uFF08\u7A7A\u95F2\uFF09\u3002\u9ED8\u8BA4\u503C\uFF1Abusy\u3002',\n }),\n ),\n location: Type.Optional(\n Type.Object(\n {\n name: Type.Optional(\n Type.String({\n description: '\u5730\u70B9\u540D\u79F0',\n }),\n ),\n address: Type.Optional(\n Type.String({\n description: '\u5730\u70B9\u5730\u5740',\n }),\n ),\n latitude: Type.Optional(\n Type.Number({\n description: '\u5730\u70B9\u5750\u6807\u7EAC\u5EA6\uFF08\u56FD\u5185\u91C7\u7528 GCJ-02 \u6807\u51C6\uFF0C\u6D77\u5916\u91C7\u7528 WGS84 \u6807\u51C6\uFF09',\n }),\n ),\n longitude: Type.Optional(\n Type.Number({\n description: '\u5730\u70B9\u5750\u6807\u7ECF\u5EA6\uFF08\u56FD\u5185\u91C7\u7528 GCJ-02 \u6807\u51C6\uFF0C\u6D77\u5916\u91C7\u7528 WGS84 \u6807\u51C6\uFF09',\n }),\n ),\n },\n {\n description: '\u65E5\u7A0B\u5730\u70B9\u4FE1\u606F',\n },\n ),\n ),\n reminders: Type.Optional(\n Type.Array(\n Type.Object({\n minutes: Type.Number({\n description:\n '\u65E5\u7A0B\u63D0\u9192\u65F6\u95F4\u7684\u504F\u79FB\u91CF\uFF08\u5206\u949F\uFF09\u3002\u6B63\u6570\u8868\u793A\u5728\u65E5\u7A0B\u5F00\u59CB\u524D\u63D0\u9192\uFF0C\u8D1F\u6570\u8868\u793A\u5728\u65E5\u7A0B\u5F00\u59CB\u540E\u63D0\u9192\u3002\u8303\u56F4\uFF1A-20160 ~ 20160\u3002',\n }),\n }),\n {\n description: '\u65E5\u7A0B\u63D0\u9192\u5217\u8868',\n },\n ),\n ),\n recurrence: Type.Optional(\n Type.String({\n description: \"\u91CD\u590D\u65E5\u7A0B\u7684\u91CD\u590D\u6027\u89C4\u5219\uFF08RFC5545 RRULE \u683C\u5F0F\uFF09\u3002\u4F8B\u5982\uFF1A'FREQ=DAILY;INTERVAL=1' \u8868\u793A\u6BCF\u5929\u91CD\u590D\u3002\",\n }),\n ),\n }),\n\n // LIST (\u4F7F\u7528 instance_view \u63A5\u53E3)\n Type.Object({\n action: Type.Literal('list'),\n start_time: Type.String({\n description:\n \"\u5F00\u59CB\u65F6\u95F4\u3002ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\u3002\u6CE8\u610F\uFF1Astart_time \u4E0E end_time \u4E4B\u95F4\u7684\u65F6\u95F4\u533A\u95F4\u9700\u8981\u5C0F\u4E8E 40 \u5929\u3002\",\n }),\n end_time: Type.String({\n description: '\u7ED3\u675F\u65F6\u95F4\u3002\u683C\u5F0F\u540C start_time\u3002\u6CE8\u610F\uFF1Astart_time \u4E0E end_time \u4E4B\u95F4\u7684\u65F6\u95F4\u533A\u95F4\u9700\u8981\u5C0F\u4E8E 40 \u5929\u3002',\n }),\n calendar_id: Type.Optional(\n Type.String({\n description: 'Calendar ID (optional; primary calendar used if omitted)',\n }),\n ),\n }),\n\n // GET\n Type.Object({\n action: Type.Literal('get'),\n event_id: Type.String({\n description: 'Event ID',\n }),\n calendar_id: Type.Optional(\n Type.String({\n description: 'Calendar ID (optional; primary calendar used if omitted)',\n }),\n ),\n }),\n\n // PATCH (P1)\n Type.Object({\n action: Type.Literal('patch'),\n event_id: Type.String({\n description: 'Event ID',\n }),\n calendar_id: Type.Optional(\n Type.String({\n description: 'Calendar ID (optional; primary calendar used if omitted)',\n }),\n ),\n summary: Type.Optional(\n Type.String({\n description: '\u65B0\u7684\u65E5\u7A0B\u6807\u9898',\n }),\n ),\n description: Type.Optional(\n Type.String({\n description: '\u65B0\u7684\u65E5\u7A0B\u63CF\u8FF0',\n }),\n ),\n start_time: Type.Optional(\n Type.String({\n description: \"\u65B0\u7684\u5F00\u59CB\u65F6\u95F4\uFF08ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\uFF09\",\n }),\n ),\n end_time: Type.Optional(\n Type.String({\n description: \"\u65B0\u7684\u7ED3\u675F\u65F6\u95F4\uFF08ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\uFF09\",\n }),\n ),\n location: Type.Optional(\n Type.String({\n description: '\u65B0\u7684\u5730\u70B9',\n }),\n ),\n }),\n\n // DELETE (P1)\n Type.Object({\n action: Type.Literal('delete'),\n event_id: Type.String({\n description: 'Event ID',\n }),\n calendar_id: Type.Optional(\n Type.String({\n description: 'Calendar ID (optional; primary calendar used if omitted)',\n }),\n ),\n need_notification: Type.Optional(\n Type.Boolean({\n description: '\u662F\u5426\u901A\u77E5\u53C2\u4F1A\u4EBA\uFF08\u9ED8\u8BA4 true\uFF09',\n }),\n ),\n }),\n\n // SEARCH (P1)\n Type.Object({\n action: Type.Literal('search'),\n query: Type.String({\n description: '\u641C\u7D22\u5173\u952E\u8BCD',\n }),\n calendar_id: Type.Optional(\n Type.String({\n description: 'Calendar ID (optional; primary calendar used if omitted)',\n }),\n ),\n page_size: Type.Optional(\n Type.Number({\n description: '\u6BCF\u9875\u6570\u91CF',\n }),\n ),\n page_token: Type.Optional(\n Type.String({\n description: '\u5206\u9875\u6807\u8BB0',\n }),\n ),\n }),\n\n // REPLY (P1)\n Type.Object({\n action: Type.Literal('reply'),\n event_id: Type.String({\n description: 'Event ID',\n }),\n calendar_id: Type.Optional(\n Type.String({\n description: 'Calendar ID (optional; primary calendar used if omitted)',\n }),\n ),\n rsvp_status: Type.Union([Type.Literal('accept'), Type.Literal('decline'), Type.Literal('tentative')]),\n }),\n\n // INSTANCES (P1)\n Type.Object({\n action: Type.Literal('instances'),\n event_id: Type.String({\n description: '\u91CD\u590D\u65E5\u7A0B\u7684 Event ID',\n }),\n calendar_id: Type.Optional(\n Type.String({\n description: 'Calendar ID (optional; primary calendar used if omitted)',\n }),\n ),\n start_time: Type.String({\n description: \"\u67E5\u8BE2\u8D77\u59CB\u65F6\u95F4\uFF08ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\uFF09\",\n }),\n end_time: Type.String({\n description: \"\u67E5\u8BE2\u7ED3\u675F\u65F6\u95F4\uFF08ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\uFF09\",\n }),\n page_size: Type.Optional(\n Type.Number({\n description: '\u6BCF\u9875\u6570\u91CF',\n }),\n ),\n page_token: Type.Optional(\n Type.String({\n description: '\u5206\u9875\u6807\u8BB0',\n }),\n ),\n }),\n\n // INSTANCE_VIEW (P1)\n Type.Object({\n action: Type.Literal('instance_view'),\n start_time: Type.String({\n description: \"\u67E5\u8BE2\u8D77\u59CB\u65F6\u95F4\uFF08ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\uFF09\",\n }),\n end_time: Type.String({\n description: \"\u67E5\u8BE2\u7ED3\u675F\u65F6\u95F4\uFF08ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\uFF09\",\n }),\n calendar_id: Type.Optional(\n Type.String({\n description: 'Calendar ID (optional; primary calendar used if omitted)',\n }),\n ),\n page_size: Type.Optional(\n Type.Number({\n description: '\u6BCF\u9875\u6570\u91CF',\n }),\n ),\n page_token: Type.Optional(\n Type.String({\n description: '\u5206\u9875\u6807\u8BB0',\n }),\n ),\n }),\n]);\n\n// ---------------------------------------------------------------------------\n// Params type\n// ---------------------------------------------------------------------------\n\ntype FeishuCalendarEventParams =\n | {\n action: 'create';\n start_time: string;\n end_time: string;\n summary?: string;\n user_open_id?: string;\n calendar_id?: string;\n description?: string;\n attendees?: Array<{ type: string; id: string }>;\n vchat?: {\n vc_type?: 'vc' | 'third_party' | 'no_meeting';\n icon_type?: 'vc' | 'live' | 'default';\n description?: string;\n meeting_url?: string;\n };\n visibility?: 'default' | 'public' | 'private';\n attendee_ability?: 'none' | 'can_see_others' | 'can_invite_others' | 'can_modify_event';\n free_busy_status?: 'busy' | 'free';\n location?: {\n name?: string;\n address?: string;\n latitude?: number;\n longitude?: number;\n };\n reminders?: Array<{ minutes: number }>;\n recurrence?: string;\n }\n | {\n action: 'list';\n start_time: string;\n end_time: string;\n calendar_id?: string;\n }\n | {\n action: 'get';\n event_id: string;\n calendar_id?: string;\n }\n | {\n action: 'patch';\n event_id: string;\n calendar_id?: string;\n summary?: string;\n description?: string;\n start_time?: string;\n end_time?: string;\n location?: string;\n }\n | {\n action: 'delete';\n event_id: string;\n calendar_id?: string;\n need_notification?: boolean;\n }\n | {\n action: 'search';\n query: string;\n calendar_id?: string;\n page_size?: number;\n page_token?: string;\n }\n | {\n action: 'reply';\n event_id: string;\n calendar_id?: string;\n rsvp_status: 'accept' | 'decline' | 'tentative';\n }\n | {\n action: 'instances';\n event_id: string;\n calendar_id?: string;\n start_time: string;\n end_time: string;\n page_size?: number;\n page_token?: string;\n }\n | {\n action: 'instance_view';\n start_time: string;\n end_time: string;\n calendar_id?: string;\n page_size?: number;\n page_token?: string;\n };\n\nfunction normalizeCalendarTimeValue(value: unknown): string | undefined {\n if (value === null || value === undefined) return undefined;\n\n if (typeof value === 'string') {\n const iso = unixTimestampToISO8601(value);\n return iso ?? value;\n }\n\n if (typeof value !== 'object') return undefined;\n\n const timeObj = value as { timestamp?: unknown; date?: unknown };\n const fromTimestamp = unixTimestampToISO8601(timeObj.timestamp as string | number | undefined);\n if (fromTimestamp) return fromTimestamp;\n\n if (typeof timeObj.date === 'string') return timeObj.date;\n\n return undefined;\n}\n\nfunction normalizeEventTimeFields(event: Record<string, any> | undefined): Record<string, any> | undefined {\n if (!event) return event;\n\n const normalized: Record<string, any> = { ...event };\n\n const startTime = normalizeCalendarTimeValue(event.start_time);\n if (startTime) {\n normalized.start_time = startTime;\n }\n\n const endTime = normalizeCalendarTimeValue(event.end_time);\n if (endTime) {\n normalized.end_time = endTime;\n }\n\n const createTime = unixTimestampToISO8601(event.create_time as string | number | undefined);\n if (createTime) {\n normalized.create_time = createTime;\n }\n\n return normalized;\n}\n\nfunction normalizeEventListTimeFields(\n events: Array<Record<string, any>> | undefined,\n): Array<Record<string, any>> | undefined {\n if (!events) return events;\n return events.map((item) => normalizeEventTimeFields(item) as Record<string, any>);\n}\n\n// ---------------------------------------------------------------------------\n// Registration\n// ---------------------------------------------------------------------------\n\nexport function registerFeishuCalendarEventTool(api: OpenClawPluginApi) {\n if (!api.config) return;\n const cfg = api.config;\n\n const { toolClient, log } = createToolContext(api, 'feishu_calendar_event');\n\n const resolveCalendarId = async (client: ReturnType<typeof toolClient>): Promise<string | null> => {\n const primaryRes = await client.invoke(\n 'feishu_calendar_calendar.primary',\n (sdk, opts) => sdk.calendar.calendar.primary({}, opts),\n { as: 'user' },\n );\n const data = primaryRes.data as CalendarPrimaryData | undefined;\n const cid = data?.calendars?.[0]?.calendar?.calendar_id;\n if (cid) {\n log.info(`resolveCalendarId: primary() returned calendar_id=${cid}`);\n return cid;\n }\n return null;\n };\n\n const resolveCalendarIdOrFail = async (\n calendarId: string | undefined,\n client: ReturnType<typeof toolClient>,\n ): Promise<string> => {\n if (calendarId) return calendarId;\n const resolved = await resolveCalendarId(client);\n if (!resolved) throw new Error('Could not determine primary calendar');\n return resolved;\n };\n\n api.registerTool(\n {\n name: 'feishu_calendar_event',\n label: 'Feishu Calendar Events',\n description:\n \"\u3010\u4EE5\u7528\u6237\u8EAB\u4EFD\u3011\u98DE\u4E66\u65E5\u7A0B\u7BA1\u7406\u5DE5\u5177\u3002\u5F53\u7528\u6237\u8981\u6C42\u67E5\u770B\u65E5\u7A0B\u3001\u521B\u5EFA\u4F1A\u8BAE\u3001\u7EA6\u4F1A\u8BAE\u3001\u4FEE\u6539\u65E5\u7A0B\u3001\u5220\u9664\u65E5\u7A0B\u3001\u641C\u7D22\u65E5\u7A0B\u3001\u56DE\u590D\u65E5\u7A0B\u9080\u8BF7\u65F6\u4F7F\u7528\u3002Actions: create\uFF08\u521B\u5EFA\u65E5\u5386\u4E8B\u4EF6\uFF09, list\uFF08\u67E5\u8BE2\u65F6\u95F4\u8303\u56F4\u5185\u7684\u65E5\u7A0B\uFF0C\u81EA\u52A8\u5C55\u5F00\u91CD\u590D\u65E5\u7A0B\uFF09, get\uFF08\u83B7\u53D6\u65E5\u7A0B\u8BE6\u60C5\uFF09, patch\uFF08\u66F4\u65B0\u65E5\u7A0B\uFF09, delete\uFF08\u5220\u9664\u65E5\u7A0B\uFF09, search\uFF08\u641C\u7D22\u65E5\u7A0B\uFF09, reply\uFF08\u56DE\u590D\u65E5\u7A0B\u9080\u8BF7\uFF09, instances\uFF08\u83B7\u53D6\u91CD\u590D\u65E5\u7A0B\u7684\u5B9E\u4F8B\u5217\u8868\uFF0C\u4EC5\u5BF9\u91CD\u590D\u65E5\u7A0B\u6709\u6548\uFF09, instance_view\uFF08\u67E5\u770B\u5C55\u5F00\u540E\u7684\u65E5\u7A0B\u5217\u8868\uFF09\u3002\u3010\u91CD\u8981\u3011create \u65F6\u5FC5\u987B\u4F20 user_open_id \u53C2\u6570\uFF0C\u503C\u4E3A\u6D88\u606F\u4E0A\u4E0B\u6587\u4E2D\u7684 SenderId\uFF08\u683C\u5F0F ou_xxx\uFF09\uFF0C\u5426\u5219\u65E5\u7A0B\u53EA\u5728\u5E94\u7528\u65E5\u5386\u4E0A\uFF0C\u7528\u6237\u5B8C\u5168\u770B\u4E0D\u5230\u3002list \u64CD\u4F5C\u4F7F\u7528 instance_view \u63A5\u53E3\uFF0C\u4F1A\u81EA\u52A8\u5C55\u5F00\u91CD\u590D\u65E5\u7A0B\u4E3A\u591A\u4E2A\u5B9E\u4F8B\uFF0C\u65F6\u95F4\u533A\u95F4\u4E0D\u80FD\u8D85\u8FC740\u5929\uFF0C\u8FD4\u56DE\u5B9E\u4F8B\u6570\u91CF\u4E0A\u96501000\u3002\u65F6\u95F4\u53C2\u6570\u4F7F\u7528ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\u3002\",\n parameters: FeishuCalendarEventSchema,\n async execute(_toolCallId: string, params: unknown) {\n const p = params as FeishuCalendarEventParams;\n try {\n const client = toolClient();\n\n switch (p.action) {\n // -----------------------------------------------------------------\n // CREATE EVENT\n // -----------------------------------------------------------------\n case 'create': {\n if (!p.summary) return json({ error: 'summary is required' });\n if (!p.start_time) return json({ error: 'start_time is required' });\n if (!p.end_time) return json({ error: 'end_time is required' });\n\n const startTs = parseTimeToTimestamp(p.start_time);\n const endTs = parseTimeToTimestamp(p.end_time);\n if (!startTs || !endTs)\n return json({\n error:\n \"Invalid time format. Must use ISO 8601 / RFC 3339 with timezone, e.g. '2024-01-01T00:00:00+08:00' or '2026-02-25 14:00:00'. Do not pass Unix timestamp numbers.\",\n received_start: p.start_time,\n received_end: p.end_time,\n });\n\n log.info(\n `create: summary=${p.summary}, start_time=${p.start_time} -> ts=${startTs}, end_time=${p.end_time} -> ts=${endTs}, user_open_id=${p.user_open_id ?? 'MISSING'}, attendees=${JSON.stringify(p.attendees ?? [])}, vchat=${p.vchat?.vc_type ?? 'auto'}, location=${p.location?.name ?? 'none'}`,\n );\n\n // Resolve bot's calendar\n const calendarId = await resolveCalendarIdOrFail(p.calendar_id, client);\n\n const eventData: any = {\n summary: p.summary,\n start_time: { timestamp: startTs },\n end_time: { timestamp: endTs },\n need_notification: true,\n attendee_ability: p.attendee_ability ?? 'can_modify_event',\n };\n if (p.description) eventData.description = p.description;\n\n // \u89C6\u9891\u4F1A\u8BAE\u914D\u7F6E\n if (p.vchat) {\n eventData.vchat = {};\n if (p.vchat.vc_type) eventData.vchat.vc_type = p.vchat.vc_type;\n if (p.vchat.icon_type) eventData.vchat.icon_type = p.vchat.icon_type;\n if (p.vchat.description) eventData.vchat.description = p.vchat.description;\n if (p.vchat.meeting_url) eventData.vchat.meeting_url = p.vchat.meeting_url;\n }\n\n // \u516C\u5F00\u8303\u56F4\n if (p.visibility) eventData.visibility = p.visibility;\n\n // \u5FD9\u95F2\u72B6\u6001\n if (p.free_busy_status) eventData.free_busy_status = p.free_busy_status;\n\n // \u5730\u70B9\u4FE1\u606F\n if (p.location) {\n eventData.location = {};\n if (p.location.name) eventData.location.name = p.location.name;\n if (p.location.address) eventData.location.address = p.location.address;\n if (p.location.latitude !== undefined) eventData.location.latitude = p.location.latitude;\n if (p.location.longitude !== undefined) eventData.location.longitude = p.location.longitude;\n }\n\n // \u63D0\u9192\u5217\u8868\n if (p.reminders) {\n eventData.reminders = p.reminders.map((r) => ({ minutes: r.minutes }));\n }\n\n // \u91CD\u590D\u89C4\u5219\n if (p.recurrence) eventData.recurrence = p.recurrence;\n\n const res = await client.invoke(\n 'feishu_calendar_event.create',\n (sdk, opts) =>\n sdk.calendar.calendarEvent.create(\n {\n path: { calendar_id: calendarId },\n data: eventData,\n },\n opts,\n ),\n { as: 'user' },\n );\n assertLarkOk(res);\n log.info(`event created: event_id=${res.data?.event?.event_id}`);\n\n // Build attendee list: merge explicit attendees + user_open_id\n const allAttendees: Array<{ type: string; id: string }> = [...(p.attendees ?? [])];\n if (p.user_open_id) {\n const alreadyIncluded = allAttendees.some((a) => a.type === 'user' && a.id === p.user_open_id);\n if (!alreadyIncluded) {\n allAttendees.push({ type: 'user', id: p.user_open_id });\n }\n }\n\n log.info(`allAttendees=${JSON.stringify(allAttendees)}`);\n let attendeeError: string | undefined;\n\n const operateId = p.user_open_id ?? p.attendees?.find((a) => a.type === 'user')?.id;\n\n if (allAttendees.length > 0 && res.data?.event?.event_id) {\n const attendeeData = allAttendees.map((a) => ({\n type: a.type as 'user' | 'chat' | 'resource' | 'third_party',\n user_id: a.type === 'user' ? a.id : undefined,\n chat_id: a.type === 'chat' ? a.id : undefined,\n room_id: a.type === 'resource' ? a.id : undefined,\n third_party_email: a.type === 'third_party' ? a.id : undefined,\n operate_id: operateId,\n }));\n\n try {\n const attendeeRes = await client.invoke(\n 'feishu_calendar_event.create',\n (sdk, opts) =>\n sdk.calendar.calendarEventAttendee.create(\n {\n path: {\n calendar_id: calendarId,\n event_id: res.data?.event?.event_id!,\n },\n params: { user_id_type: 'open_id' as any },\n data: {\n attendees: attendeeData,\n need_notification: true,\n },\n },\n opts,\n ),\n { as: 'user' },\n );\n assertLarkOk(attendeeRes);\n log.info(`attendee API response: ${JSON.stringify(attendeeRes.data)}`);\n } catch (attendeeErr) {\n attendeeError = formatLarkError(attendeeErr);\n log.info(`attendee add FAILED: ${attendeeError}`);\n }\n }\n\n // Strip calendarId from app_link \u2014 it points to bot's calendar, users can't access it\n const appLink = (res.data?.event as any)?.app_link as string | undefined;\n\n const safeEvent = res.data?.event\n ? {\n event_id: res.data.event.event_id,\n summary: res.data.event.summary,\n app_link: appLink,\n start_time: unixTimestampToISO8601(startTs) ?? p.start_time,\n end_time: unixTimestampToISO8601(endTs) ?? p.end_time,\n }\n : undefined;\n\n const result: any = {\n event: safeEvent,\n attendees: allAttendees.map((a) => ({\n type: a.type,\n id: a.id,\n })),\n _debug: {\n calendar_id: calendarId,\n operate_id: operateId,\n start_input: p.start_time,\n start_iso8601: unixTimestampToISO8601(startTs) ?? p.start_time,\n end_input: p.end_time,\n end_iso8601: unixTimestampToISO8601(endTs) ?? p.end_time,\n attendees_count: allAttendees.length,\n },\n };\n if (attendeeError) {\n result.warning = `\u65E5\u7A0B\u5DF2\u521B\u5EFA\uFF0C\u4F46\u6DFB\u52A0\u53C2\u4F1A\u4EBA\u5931\u8D25\uFF1A${attendeeError}`;\n } else if (allAttendees.length === 0) {\n result.error =\n '\u65E5\u7A0B\u5DF2\u521B\u5EFA\u5728\u5E94\u7528\u65E5\u5386\u4E0A\uFF0C\u4F46\u672A\u6DFB\u52A0\u4EFB\u4F55\u53C2\u4F1A\u4EBA\uFF0C\u7528\u6237\u770B\u4E0D\u5230\u6B64\u65E5\u7A0B\u3002\u8BF7\u91CD\u65B0\u8C03\u7528\u65F6\u4F20\u5165 user_open_id \u53C2\u6570\u3002';\n } else {\n result.note = `\u5DF2\u6210\u529F\u6DFB\u52A0 ${allAttendees.length} \u4F4D\u53C2\u4F1A\u4EBA\uFF0C\u65E5\u7A0B\u5E94\u51FA\u73B0\u5728\u53C2\u4F1A\u4EBA\u7684\u98DE\u4E66\u65E5\u5386\u4E2D\u3002`;\n }\n return json(result);\n }\n\n // -----------------------------------------------------------------\n // LIST EVENTS (\u4F7F\u7528 instance_view \u63A5\u53E3\uFF0C\u81EA\u52A8\u5C55\u5F00\u91CD\u590D\u65E5\u7A0B)\n // -----------------------------------------------------------------\n case 'list': {\n if (!p.start_time) return json({ error: 'start_time is required' });\n if (!p.end_time) return json({ error: 'end_time is required' });\n\n const startTs = parseTimeToTimestamp(p.start_time);\n const endTs = parseTimeToTimestamp(p.end_time);\n if (!startTs || !endTs)\n return json({\n error:\n \"Invalid time format. Must use ISO 8601 / RFC 3339 with timezone, e.g. '2024-01-01T00:00:00+08:00' or '2026-02-25 14:00:00'. Do not pass Unix timestamps.\",\n received_start: p.start_time,\n received_end: p.end_time,\n });\n\n const calendarId = await resolveCalendarIdOrFail(p.calendar_id, client);\n\n log.info(\n `list: calendar_id=${calendarId}, start_time=${startTs}, end_time=${endTs} (using instance_view)`,\n );\n\n const res = await client.invoke(\n 'feishu_calendar_event.instance_view',\n (sdk, opts) =>\n sdk.calendar.calendarEvent.instanceView(\n {\n path: { calendar_id: calendarId },\n params: {\n start_time: startTs,\n end_time: endTs,\n user_id_type: 'open_id' as any,\n },\n },\n opts,\n ),\n { as: 'user' },\n );\n assertLarkOk(res);\n\n const data = res.data as PaginatedData | undefined;\n log.info(`list: returned ${data?.items?.length ?? 0} event instances`);\n\n return json({\n events: normalizeEventListTimeFields(data?.items as Array<Record<string, any>> | undefined),\n has_more: data?.has_more ?? false,\n page_token: data?.page_token,\n });\n }\n\n // -----------------------------------------------------------------\n // GET EVENT\n // -----------------------------------------------------------------\n case 'get': {\n if (!p.event_id) return json({ error: 'event_id is required' });\n\n const calendarId = await resolveCalendarIdOrFail(p.calendar_id, client);\n\n log.info(`get: calendar_id=${calendarId}, event_id=${p.event_id}`);\n\n const res = await client.invoke(\n 'feishu_calendar_event.get',\n (sdk, opts) =>\n sdk.calendar.calendarEvent.get(\n {\n path: { calendar_id: calendarId, event_id: p.event_id },\n },\n opts,\n ),\n { as: 'user' },\n );\n assertLarkOk(res);\n\n log.info(`get: retrieved event ${p.event_id}`);\n\n return json({\n event: normalizeEventTimeFields(res.data?.event as Record<string, any> | undefined),\n });\n }\n\n // -----------------------------------------------------------------\n // PATCH EVENT (P1)\n // -----------------------------------------------------------------\n case 'patch': {\n if (!p.event_id) return json({ error: 'event_id is required' });\n\n const calendarId = await resolveCalendarIdOrFail(p.calendar_id, client);\n\n const updateData: any = {};\n\n // Handle time conversion if provided\n if (p.start_time) {\n const startTs = parseTimeToTimestamp(p.start_time);\n if (!startTs)\n return json({\n error:\n \"start_time \u683C\u5F0F\u9519\u8BEF\uFF01\u5FC5\u987B\u4F7F\u7528ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\",\n received: p.start_time,\n });\n updateData.start_time = { timestamp: startTs };\n }\n\n if (p.end_time) {\n const endTs = parseTimeToTimestamp(p.end_time);\n if (!endTs)\n return json({\n error:\n \"end_time \u683C\u5F0F\u9519\u8BEF\uFF01\u5FC5\u987B\u4F7F\u7528ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\",\n received: p.end_time,\n });\n updateData.end_time = { timestamp: endTs };\n }\n\n if (p.summary) updateData.summary = p.summary;\n if (p.description) updateData.description = p.description;\n if (p.location) updateData.location = { name: p.location };\n\n log.info(\n `patch: calendar_id=${calendarId}, event_id=${p.event_id}, fields=${Object.keys(updateData).join(',')}`,\n );\n\n const res = await client.invoke(\n 'feishu_calendar_event.patch',\n (sdk, opts) =>\n sdk.calendar.calendarEvent.patch(\n {\n path: { calendar_id: calendarId, event_id: p.event_id },\n data: updateData,\n },\n opts,\n ),\n { as: 'user' },\n );\n assertLarkOk(res);\n\n log.info(`patch: updated event ${p.event_id}`);\n\n return json({\n event: normalizeEventTimeFields(res.data?.event as Record<string, any> | undefined),\n });\n }\n\n // -----------------------------------------------------------------\n // DELETE EVENT (P1)\n // -----------------------------------------------------------------\n case 'delete': {\n if (!p.event_id) return json({ error: 'event_id is required' });\n\n const calendarId = await resolveCalendarIdOrFail(p.calendar_id, client);\n\n log.info(\n `delete: calendar_id=${calendarId}, event_id=${p.event_id}, notify=${p.need_notification ?? true}`,\n );\n\n const res = await client.invoke(\n 'feishu_calendar_event.delete',\n (sdk, opts) =>\n sdk.calendar.calendarEvent.delete(\n {\n path: { calendar_id: calendarId, event_id: p.event_id },\n params: {\n need_notification: (p.need_notification ?? true) as any,\n },\n },\n opts,\n ),\n { as: 'user' },\n );\n assertLarkOk(res);\n\n log.info(`delete: deleted event ${p.event_id}`);\n\n return json({\n success: true,\n event_id: p.event_id,\n });\n }\n\n // -----------------------------------------------------------------\n // SEARCH EVENT (P1)\n // -----------------------------------------------------------------\n case 'search': {\n if (!p.query) return json({ error: 'query is required' });\n\n const calendarId = await resolveCalendarIdOrFail(p.calendar_id, client);\n\n log.info(`search: calendar_id=${calendarId}, query=${p.query}, page_size=${p.page_size ?? 50}`);\n\n const res = await client.invoke(\n 'feishu_calendar_event.search',\n (sdk, opts) =>\n sdk.calendar.calendarEvent.search(\n {\n path: { calendar_id: calendarId },\n params: {\n page_size: p.page_size,\n page_token: p.page_token,\n },\n data: {\n query: p.query,\n },\n },\n opts,\n ),\n { as: 'user' },\n );\n assertLarkOk(res);\n\n const data = res.data as PaginatedData | undefined;\n log.info(`search: found ${data?.items?.length ?? 0} events`);\n\n return json({\n events: normalizeEventListTimeFields(data?.items as Array<Record<string, any>> | undefined),\n has_more: data?.has_more ?? false,\n page_token: data?.page_token,\n });\n }\n\n // -----------------------------------------------------------------\n // REPLY EVENT (P1)\n // -----------------------------------------------------------------\n case 'reply': {\n if (!p.event_id) return json({ error: 'event_id is required' });\n if (!p.rsvp_status) return json({ error: 'rsvp_status is required' });\n\n const calendarId = await resolveCalendarIdOrFail(p.calendar_id, client);\n\n log.info(`reply: calendar_id=${calendarId}, event_id=${p.event_id}, rsvp=${p.rsvp_status}`);\n\n const res = await client.invoke(\n 'feishu_calendar_event.reply',\n (sdk, opts) =>\n sdk.calendar.calendarEvent.reply(\n {\n path: { calendar_id: calendarId, event_id: p.event_id },\n data: {\n rsvp_status: p.rsvp_status,\n },\n },\n opts,\n ),\n { as: 'user' },\n );\n assertLarkOk(res);\n\n log.info(`reply: replied to event ${p.event_id} with ${p.rsvp_status}`);\n\n return json({\n success: true,\n event_id: p.event_id,\n rsvp_status: p.rsvp_status,\n });\n }\n\n // -----------------------------------------------------------------\n // INSTANCES (P1)\n // -----------------------------------------------------------------\n case 'instances': {\n if (!p.event_id) return json({ error: 'event_id is required' });\n if (!p.start_time) return json({ error: 'start_time is required' });\n if (!p.end_time) return json({ error: 'end_time is required' });\n\n const calendarId = await resolveCalendarIdOrFail(p.calendar_id, client);\n\n const startTs = parseTimeToTimestamp(p.start_time);\n const endTs = parseTimeToTimestamp(p.end_time);\n\n if (!startTs || !endTs)\n return json({\n error:\n \"Invalid time format. Must use ISO 8601 / RFC 3339 with timezone, e.g. '2024-01-01T00:00:00+08:00'\",\n received_start: p.start_time,\n received_end: p.end_time,\n });\n\n log.info(`instances: calendar_id=${calendarId}, event_id=${p.event_id}, start=${startTs}, end=${endTs}`);\n\n const res = await client.invoke(\n 'feishu_calendar_event.instances',\n (sdk, opts) =>\n sdk.calendar.calendarEvent.instances(\n {\n path: { calendar_id: calendarId, event_id: p.event_id },\n params: {\n start_time: startTs as any,\n end_time: endTs as any,\n page_size: p.page_size,\n page_token: p.page_token,\n },\n },\n opts,\n ),\n { as: 'user' },\n );\n assertLarkOk(res);\n\n const data = res.data as PaginatedData | undefined;\n log.info(`instances: returned ${data?.items?.length ?? 0} instances`);\n\n return json({\n instances: normalizeEventListTimeFields(data?.items as Array<Record<string, any>> | undefined),\n has_more: data?.has_more ?? false,\n page_token: data?.page_token,\n });\n }\n\n // -----------------------------------------------------------------\n // INSTANCE_VIEW (P1)\n // -----------------------------------------------------------------\n case 'instance_view': {\n if (!p.start_time) return json({ error: 'start_time is required' });\n if (!p.end_time) return json({ error: 'end_time is required' });\n\n const calendarId = await resolveCalendarIdOrFail(p.calendar_id, client);\n\n const startTs = parseTimeToTimestamp(p.start_time);\n const endTs = parseTimeToTimestamp(p.end_time);\n\n if (!startTs || !endTs)\n return json({\n error:\n \"Invalid time format. Must use ISO 8601 / RFC 3339 with timezone, e.g. '2024-01-01T00:00:00+08:00'\",\n received_start: p.start_time,\n received_end: p.end_time,\n });\n\n log.info(`instance_view: calendar_id=${calendarId}, start=${startTs}, end=${endTs}`);\n\n const res = await client.invoke(\n 'feishu_calendar_event.instance_view',\n (sdk, opts) =>\n sdk.calendar.calendarEvent.instanceView(\n {\n path: { calendar_id: calendarId },\n params: {\n start_time: startTs,\n end_time: endTs,\n user_id_type: 'open_id' as any,\n },\n },\n opts,\n ),\n { as: 'user' },\n );\n assertLarkOk(res);\n\n const data = res.data as PaginatedData | undefined;\n log.info(`instance_view: returned ${data?.items?.length ?? 0} events`);\n\n return json({\n events: normalizeEventListTimeFields(data?.items as Array<Record<string, any>> | undefined),\n has_more: data?.has_more ?? false,\n page_token: data?.page_token,\n });\n }\n }\n } catch (err) {\n return await handleInvokeErrorWithAutoAuth(err, cfg);\n }\n },\n },\n { name: 'feishu_calendar_event' },\n );\n\n api.logger.info?.('feishu_calendar_event: Registered feishu_calendar_event tool');\n}\n"],
|
|
5
|
+
"mappings": "AAiBA,SAAS,YAAY;AACrB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAOP,MAAM,4BAA4B,KAAK,MAAM;AAAA;AAAA,EAE3C,KAAK,OAAO;AAAA,IACV,QAAQ,KAAK,QAAQ,QAAQ;AAAA,IAC7B,YAAY,KAAK,OAAO;AAAA,MACtB,aAAa;AAAA,IACf,CAAC;AAAA,IACD,UAAU,KAAK,OAAO;AAAA,MACpB,aAAa;AAAA,IACf,CAAC;AAAA,IACD,SAAS,KAAK;AAAA,MACZ,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,cAAc,KAAK;AAAA,MACjB,KAAK,OAAO;AAAA,QACV,aACE;AAAA,MACJ,CAAC;AAAA,IACH;AAAA,IACA,aAAa,KAAK;AAAA,MAChB,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,aAAa,KAAK;AAAA,MAChB,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,WAAW,KAAK;AAAA,MACd,KAAK;AAAA,QACH,KAAK,OAAO;AAAA,UACV,MAAM,KAAK,MAAM;AAAA,YACf,KAAK,QAAQ,MAAM;AAAA,YACnB,KAAK,QAAQ,MAAM;AAAA,YACnB,KAAK,QAAQ,UAAU;AAAA,YACvB,KAAK,QAAQ,aAAa;AAAA,UAC5B,CAAC;AAAA,UACD,IAAI,KAAK,OAAO;AAAA,YACd,aAAa;AAAA,UACf,CAAC;AAAA,QACH,CAAC;AAAA,QACD;AAAA,UACE,aACE;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAAA,IACA,OAAO,KAAK;AAAA,MACV,KAAK;AAAA,QACH;AAAA,UACE,SAAS,KAAK;AAAA,YACZ,KAAK,MAAM,CAAC,KAAK,QAAQ,IAAI,GAAG,KAAK,QAAQ,aAAa,GAAG,KAAK,QAAQ,YAAY,CAAC,GAAG;AAAA,cACxF,aACE;AAAA,YACJ,CAAC;AAAA,UACH;AAAA,UACA,WAAW,KAAK;AAAA,YACd,KAAK,MAAM,CAAC,KAAK,QAAQ,IAAI,GAAG,KAAK,QAAQ,MAAM,GAAG,KAAK,QAAQ,SAAS,CAAC,GAAG;AAAA,cAC9E,aAAa;AAAA,YACf,CAAC;AAAA,UACH;AAAA,UACA,aAAa,KAAK;AAAA,YAChB,KAAK,OAAO;AAAA,cACV,aAAa;AAAA,YACf,CAAC;AAAA,UACH;AAAA,UACA,aAAa,KAAK;AAAA,YAChB,KAAK,OAAO;AAAA,cACV,aAAa;AAAA,YACf,CAAC;AAAA,UACH;AAAA,QACF;AAAA,QACA;AAAA,UACE,aAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,IACA,YAAY,KAAK;AAAA,MACf,KAAK,MAAM,CAAC,KAAK,QAAQ,SAAS,GAAG,KAAK,QAAQ,QAAQ,GAAG,KAAK,QAAQ,SAAS,CAAC,GAAG;AAAA,QACrF,aACE;AAAA,MACJ,CAAC;AAAA,IACH;AAAA,IACA,kBAAkB,KAAK;AAAA,MACrB,KAAK;AAAA,QACH;AAAA,UACE,KAAK,QAAQ,MAAM;AAAA,UACnB,KAAK,QAAQ,gBAAgB;AAAA,UAC7B,KAAK,QAAQ,mBAAmB;AAAA,UAChC,KAAK,QAAQ,kBAAkB;AAAA,QACjC;AAAA,QACA;AAAA,UACE,aACE;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAAA,IACA,kBAAkB,KAAK;AAAA,MACrB,KAAK,MAAM,CAAC,KAAK,QAAQ,MAAM,GAAG,KAAK,QAAQ,MAAM,CAAC,GAAG;AAAA,QACvD,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,UAAU,KAAK;AAAA,MACb,KAAK;AAAA,QACH;AAAA,UACE,MAAM,KAAK;AAAA,YACT,KAAK,OAAO;AAAA,cACV,aAAa;AAAA,YACf,CAAC;AAAA,UACH;AAAA,UACA,SAAS,KAAK;AAAA,YACZ,KAAK,OAAO;AAAA,cACV,aAAa;AAAA,YACf,CAAC;AAAA,UACH;AAAA,UACA,UAAU,KAAK;AAAA,YACb,KAAK,OAAO;AAAA,cACV,aAAa;AAAA,YACf,CAAC;AAAA,UACH;AAAA,UACA,WAAW,KAAK;AAAA,YACd,KAAK,OAAO;AAAA,cACV,aAAa;AAAA,YACf,CAAC;AAAA,UACH;AAAA,QACF;AAAA,QACA;AAAA,UACE,aAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,IACA,WAAW,KAAK;AAAA,MACd,KAAK;AAAA,QACH,KAAK,OAAO;AAAA,UACV,SAAS,KAAK,OAAO;AAAA,YACnB,aACE;AAAA,UACJ,CAAC;AAAA,QACH,CAAC;AAAA,QACD;AAAA,UACE,aAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,IACA,YAAY,KAAK;AAAA,MACf,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAAA;AAAA,EAGD,KAAK,OAAO;AAAA,IACV,QAAQ,KAAK,QAAQ,MAAM;AAAA,IAC3B,YAAY,KAAK,OAAO;AAAA,MACtB,aACE;AAAA,IACJ,CAAC;AAAA,IACD,UAAU,KAAK,OAAO;AAAA,MACpB,aAAa;AAAA,IACf,CAAC;AAAA,IACD,aAAa,KAAK;AAAA,MAChB,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAAA;AAAA,EAGD,KAAK,OAAO;AAAA,IACV,QAAQ,KAAK,QAAQ,KAAK;AAAA,IAC1B,UAAU,KAAK,OAAO;AAAA,MACpB,aAAa;AAAA,IACf,CAAC;AAAA,IACD,aAAa,KAAK;AAAA,MAChB,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAAA;AAAA,EAGD,KAAK,OAAO;AAAA,IACV,QAAQ,KAAK,QAAQ,OAAO;AAAA,IAC5B,UAAU,KAAK,OAAO;AAAA,MACpB,aAAa;AAAA,IACf,CAAC;AAAA,IACD,aAAa,KAAK;AAAA,MAChB,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,SAAS,KAAK;AAAA,MACZ,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,aAAa,KAAK;AAAA,MAChB,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,YAAY,KAAK;AAAA,MACf,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,UAAU,KAAK;AAAA,MACb,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,UAAU,KAAK;AAAA,MACb,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAAA;AAAA,EAGD,KAAK,OAAO;AAAA,IACV,QAAQ,KAAK,QAAQ,QAAQ;AAAA,IAC7B,UAAU,KAAK,OAAO;AAAA,MACpB,aAAa;AAAA,IACf,CAAC;AAAA,IACD,aAAa,KAAK;AAAA,MAChB,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,mBAAmB,KAAK;AAAA,MACtB,KAAK,QAAQ;AAAA,QACX,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAAA;AAAA,EAGD,KAAK,OAAO;AAAA,IACV,QAAQ,KAAK,QAAQ,QAAQ;AAAA,IAC7B,OAAO,KAAK,OAAO;AAAA,MACjB,aAAa;AAAA,IACf,CAAC;AAAA,IACD,aAAa,KAAK;AAAA,MAChB,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,WAAW,KAAK;AAAA,MACd,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,YAAY,KAAK;AAAA,MACf,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAAA;AAAA,EAGD,KAAK,OAAO;AAAA,IACV,QAAQ,KAAK,QAAQ,OAAO;AAAA,IAC5B,UAAU,KAAK,OAAO;AAAA,MACpB,aAAa;AAAA,IACf,CAAC;AAAA,IACD,aAAa,KAAK;AAAA,MAChB,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,aAAa,KAAK,MAAM,CAAC,KAAK,QAAQ,QAAQ,GAAG,KAAK,QAAQ,SAAS,GAAG,KAAK,QAAQ,WAAW,CAAC,CAAC;AAAA,EACtG,CAAC;AAAA;AAAA,EAGD,KAAK,OAAO;AAAA,IACV,QAAQ,KAAK,QAAQ,WAAW;AAAA,IAChC,UAAU,KAAK,OAAO;AAAA,MACpB,aAAa;AAAA,IACf,CAAC;AAAA,IACD,aAAa,KAAK;AAAA,MAChB,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,YAAY,KAAK,OAAO;AAAA,MACtB,aAAa;AAAA,IACf,CAAC;AAAA,IACD,UAAU,KAAK,OAAO;AAAA,MACpB,aAAa;AAAA,IACf,CAAC;AAAA,IACD,WAAW,KAAK;AAAA,MACd,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,YAAY,KAAK;AAAA,MACf,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAAA;AAAA,EAGD,KAAK,OAAO;AAAA,IACV,QAAQ,KAAK,QAAQ,eAAe;AAAA,IACpC,YAAY,KAAK,OAAO;AAAA,MACtB,aAAa;AAAA,IACf,CAAC;AAAA,IACD,UAAU,KAAK,OAAO;AAAA,MACpB,aAAa;AAAA,IACf,CAAC;AAAA,IACD,aAAa,KAAK;AAAA,MAChB,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,WAAW,KAAK;AAAA,MACd,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,IACA,YAAY,KAAK;AAAA,MACf,KAAK,OAAO;AAAA,QACV,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH,CAAC;AA4FD,SAAS,2BAA2B,OAAoC;AACtE,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAElD,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,MAAM,uBAAuB,KAAK;AACxC,WAAO,OAAO;AAAA,EAChB;AAEA,MAAI,OAAO,UAAU,SAAU,QAAO;AAEtC,QAAM,UAAU;AAChB,QAAM,gBAAgB,uBAAuB,QAAQ,SAAwC;AAC7F,MAAI,cAAe,QAAO;AAE1B,MAAI,OAAO,QAAQ,SAAS,SAAU,QAAO,QAAQ;AAErD,SAAO;AACT;AAEA,SAAS,yBAAyB,OAAyE;AACzG,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,aAAkC,EAAE,GAAG,MAAM;AAEnD,QAAM,YAAY,2BAA2B,MAAM,UAAU;AAC7D,MAAI,WAAW;AACb,eAAW,aAAa;AAAA,EAC1B;AAEA,QAAM,UAAU,2BAA2B,MAAM,QAAQ;AACzD,MAAI,SAAS;AACX,eAAW,WAAW;AAAA,EACxB;AAEA,QAAM,aAAa,uBAAuB,MAAM,WAA0C;AAC1F,MAAI,YAAY;AACd,eAAW,cAAc;AAAA,EAC3B;AAEA,SAAO;AACT;AAEA,SAAS,6BACP,QACwC;AACxC,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,IAAI,CAAC,SAAS,yBAAyB,IAAI,CAAwB;AACnF;AAMO,SAAS,gCAAgC,KAAwB;AACtE,MAAI,CAAC,IAAI,OAAQ;AACjB,QAAM,MAAM,IAAI;AAEhB,QAAM,EAAE,YAAY,IAAI,IAAI,kBAAkB,KAAK,uBAAuB;AAE1E,QAAM,oBAAoB,OAAO,WAAkE;AACjG,UAAM,aAAa,MAAM,OAAO;AAAA,MAC9B;AAAA,MACA,CAAC,KAAK,SAAS,IAAI,SAAS,SAAS,QAAQ,CAAC,GAAG,IAAI;AAAA,MACrD,EAAE,IAAI,OAAO;AAAA,IACf;AACA,UAAM,OAAO,WAAW;AACxB,UAAM,MAAM,MAAM,YAAY,CAAC,GAAG,UAAU;AAC5C,QAAI,KAAK;AACP,UAAI,KAAK,qDAAqD,GAAG,EAAE;AACnE,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAEA,QAAM,0BAA0B,OAC9B,YACA,WACoB;AACpB,QAAI,WAAY,QAAO;AACvB,UAAM,WAAW,MAAM,kBAAkB,MAAM;AAC/C,QAAI,CAAC,SAAU,OAAM,IAAI,MAAM,sCAAsC;AACrE,WAAO;AAAA,EACT;AAEA,MAAI;AAAA,IACF;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aACE;AAAA,MACF,YAAY;AAAA,MACZ,MAAM,QAAQ,aAAqB,QAAiB;AAClD,cAAM,IAAI;AACV,YAAI;AACF,gBAAM,SAAS,WAAW;AAE1B,kBAAQ,EAAE,QAAQ;AAAA;AAAA;AAAA;AAAA,YAIhB,KAAK,UAAU;AACb,kBAAI,CAAC,EAAE,QAAS,QAAO,KAAK,EAAE,OAAO,sBAAsB,CAAC;AAC5D,kBAAI,CAAC,EAAE,WAAY,QAAO,KAAK,EAAE,OAAO,yBAAyB,CAAC;AAClE,kBAAI,CAAC,EAAE,SAAU,QAAO,KAAK,EAAE,OAAO,uBAAuB,CAAC;AAE9D,oBAAM,UAAU,qBAAqB,EAAE,UAAU;AACjD,oBAAM,QAAQ,qBAAqB,EAAE,QAAQ;AAC7C,kBAAI,CAAC,WAAW,CAAC;AACf,uBAAO,KAAK;AAAA,kBACV,OACE;AAAA,kBACF,gBAAgB,EAAE;AAAA,kBAClB,cAAc,EAAE;AAAA,gBAClB,CAAC;AAEH,kBAAI;AAAA,gBACF,mBAAmB,EAAE,OAAO,gBAAgB,EAAE,UAAU,UAAU,OAAO,cAAc,EAAE,QAAQ,UAAU,KAAK,kBAAkB,EAAE,gBAAgB,SAAS,eAAe,KAAK,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,WAAW,EAAE,OAAO,WAAW,MAAM,cAAc,EAAE,UAAU,QAAQ,MAAM;AAAA,cAC5R;AAGA,oBAAM,aAAa,MAAM,wBAAwB,EAAE,aAAa,MAAM;AAEtE,oBAAM,YAAiB;AAAA,gBACrB,SAAS,EAAE;AAAA,gBACX,YAAY,EAAE,WAAW,QAAQ;AAAA,gBACjC,UAAU,EAAE,WAAW,MAAM;AAAA,gBAC7B,mBAAmB;AAAA,gBACnB,kBAAkB,EAAE,oBAAoB;AAAA,cAC1C;AACA,kBAAI,EAAE,YAAa,WAAU,cAAc,EAAE;AAG7C,kBAAI,EAAE,OAAO;AACX,0BAAU,QAAQ,CAAC;AACnB,oBAAI,EAAE,MAAM,QAAS,WAAU,MAAM,UAAU,EAAE,MAAM;AACvD,oBAAI,EAAE,MAAM,UAAW,WAAU,MAAM,YAAY,EAAE,MAAM;AAC3D,oBAAI,EAAE,MAAM,YAAa,WAAU,MAAM,cAAc,EAAE,MAAM;AAC/D,oBAAI,EAAE,MAAM,YAAa,WAAU,MAAM,cAAc,EAAE,MAAM;AAAA,cACjE;AAGA,kBAAI,EAAE,WAAY,WAAU,aAAa,EAAE;AAG3C,kBAAI,EAAE,iBAAkB,WAAU,mBAAmB,EAAE;AAGvD,kBAAI,EAAE,UAAU;AACd,0BAAU,WAAW,CAAC;AACtB,oBAAI,EAAE,SAAS,KAAM,WAAU,SAAS,OAAO,EAAE,SAAS;AAC1D,oBAAI,EAAE,SAAS,QAAS,WAAU,SAAS,UAAU,EAAE,SAAS;AAChE,oBAAI,EAAE,SAAS,aAAa,OAAW,WAAU,SAAS,WAAW,EAAE,SAAS;AAChF,oBAAI,EAAE,SAAS,cAAc,OAAW,WAAU,SAAS,YAAY,EAAE,SAAS;AAAA,cACpF;AAGA,kBAAI,EAAE,WAAW;AACf,0BAAU,YAAY,EAAE,UAAU,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE;AAAA,cACvE;AAGA,kBAAI,EAAE,WAAY,WAAU,aAAa,EAAE;AAE3C,oBAAM,MAAM,MAAM,OAAO;AAAA,gBACvB;AAAA,gBACA,CAAC,KAAK,SACJ,IAAI,SAAS,cAAc;AAAA,kBACzB;AAAA,oBACE,MAAM,EAAE,aAAa,WAAW;AAAA,oBAChC,MAAM;AAAA,kBACR;AAAA,kBACA;AAAA,gBACF;AAAA,gBACF,EAAE,IAAI,OAAO;AAAA,cACf;AACA,2BAAa,GAAG;AAChB,kBAAI,KAAK,2BAA2B,IAAI,MAAM,OAAO,QAAQ,EAAE;AAG/D,oBAAM,eAAoD,CAAC,GAAI,EAAE,aAAa,CAAC,CAAE;AACjF,kBAAI,EAAE,cAAc;AAClB,sBAAM,kBAAkB,aAAa,KAAK,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,OAAO,EAAE,YAAY;AAC7F,oBAAI,CAAC,iBAAiB;AACpB,+BAAa,KAAK,EAAE,MAAM,QAAQ,IAAI,EAAE,aAAa,CAAC;AAAA,gBACxD;AAAA,cACF;AAEA,kBAAI,KAAK,gBAAgB,KAAK,UAAU,YAAY,CAAC,EAAE;AACvD,kBAAI;AAEJ,oBAAM,YAAY,EAAE,gBAAgB,EAAE,WAAW,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,GAAG;AAEjF,kBAAI,aAAa,SAAS,KAAK,IAAI,MAAM,OAAO,UAAU;AACxD,sBAAM,eAAe,aAAa,IAAI,CAAC,OAAO;AAAA,kBAC5C,MAAM,EAAE;AAAA,kBACR,SAAS,EAAE,SAAS,SAAS,EAAE,KAAK;AAAA,kBACpC,SAAS,EAAE,SAAS,SAAS,EAAE,KAAK;AAAA,kBACpC,SAAS,EAAE,SAAS,aAAa,EAAE,KAAK;AAAA,kBACxC,mBAAmB,EAAE,SAAS,gBAAgB,EAAE,KAAK;AAAA,kBACrD,YAAY;AAAA,gBACd,EAAE;AAEF,oBAAI;AACF,wBAAM,cAAc,MAAM,OAAO;AAAA,oBAC/B;AAAA,oBACA,CAAC,KAAK,SACJ,IAAI,SAAS,sBAAsB;AAAA,sBACjC;AAAA,wBACE,MAAM;AAAA,0BACJ,aAAa;AAAA,0BACb,UAAU,IAAI,MAAM,OAAO;AAAA,wBAC7B;AAAA,wBACA,QAAQ,EAAE,cAAc,UAAiB;AAAA,wBACzC,MAAM;AAAA,0BACJ,WAAW;AAAA,0BACX,mBAAmB;AAAA,wBACrB;AAAA,sBACF;AAAA,sBACA;AAAA,oBACF;AAAA,oBACF,EAAE,IAAI,OAAO;AAAA,kBACf;AACA,+BAAa,WAAW;AACxB,sBAAI,KAAK,0BAA0B,KAAK,UAAU,YAAY,IAAI,CAAC,EAAE;AAAA,gBACvE,SAAS,aAAa;AACpB,kCAAgB,gBAAgB,WAAW;AAC3C,sBAAI,KAAK,wBAAwB,aAAa,EAAE;AAAA,gBAClD;AAAA,cACF;AAGA,oBAAM,UAAW,IAAI,MAAM,OAAe;AAE1C,oBAAM,YAAY,IAAI,MAAM,QACxB;AAAA,gBACE,UAAU,IAAI,KAAK,MAAM;AAAA,gBACzB,SAAS,IAAI,KAAK,MAAM;AAAA,gBACxB,UAAU;AAAA,gBACV,YAAY,uBAAuB,OAAO,KAAK,EAAE;AAAA,gBACjD,UAAU,uBAAuB,KAAK,KAAK,EAAE;AAAA,cAC/C,IACA;AAEJ,oBAAM,SAAc;AAAA,gBAClB,OAAO;AAAA,gBACP,WAAW,aAAa,IAAI,CAAC,OAAO;AAAA,kBAClC,MAAM,EAAE;AAAA,kBACR,IAAI,EAAE;AAAA,gBACR,EAAE;AAAA,gBACF,QAAQ;AAAA,kBACN,aAAa;AAAA,kBACb,YAAY;AAAA,kBACZ,aAAa,EAAE;AAAA,kBACf,eAAe,uBAAuB,OAAO,KAAK,EAAE;AAAA,kBACpD,WAAW,EAAE;AAAA,kBACb,aAAa,uBAAuB,KAAK,KAAK,EAAE;AAAA,kBAChD,iBAAiB,aAAa;AAAA,gBAChC;AAAA,cACF;AACA,kBAAI,eAAe;AACjB,uBAAO,UAAU,6FAAkB,aAAa;AAAA,cAClD,WAAW,aAAa,WAAW,GAAG;AACpC,uBAAO,QACL;AAAA,cACJ,OAAO;AACL,uBAAO,OAAO,kCAAS,aAAa,MAAM;AAAA,cAC5C;AACA,qBAAO,KAAK,MAAM;AAAA,YACpB;AAAA;AAAA;AAAA;AAAA,YAKA,KAAK,QAAQ;AACX,kBAAI,CAAC,EAAE,WAAY,QAAO,KAAK,EAAE,OAAO,yBAAyB,CAAC;AAClE,kBAAI,CAAC,EAAE,SAAU,QAAO,KAAK,EAAE,OAAO,uBAAuB,CAAC;AAE9D,oBAAM,UAAU,qBAAqB,EAAE,UAAU;AACjD,oBAAM,QAAQ,qBAAqB,EAAE,QAAQ;AAC7C,kBAAI,CAAC,WAAW,CAAC;AACf,uBAAO,KAAK;AAAA,kBACV,OACE;AAAA,kBACF,gBAAgB,EAAE;AAAA,kBAClB,cAAc,EAAE;AAAA,gBAClB,CAAC;AAEH,oBAAM,aAAa,MAAM,wBAAwB,EAAE,aAAa,MAAM;AAEtE,kBAAI;AAAA,gBACF,qBAAqB,UAAU,gBAAgB,OAAO,cAAc,KAAK;AAAA,cAC3E;AAEA,oBAAM,MAAM,MAAM,OAAO;AAAA,gBACvB;AAAA,gBACA,CAAC,KAAK,SACJ,IAAI,SAAS,cAAc;AAAA,kBACzB;AAAA,oBACE,MAAM,EAAE,aAAa,WAAW;AAAA,oBAChC,QAAQ;AAAA,sBACN,YAAY;AAAA,sBACZ,UAAU;AAAA,sBACV,cAAc;AAAA,oBAChB;AAAA,kBACF;AAAA,kBACA;AAAA,gBACF;AAAA,gBACF,EAAE,IAAI,OAAO;AAAA,cACf;AACA,2BAAa,GAAG;AAEhB,oBAAM,OAAO,IAAI;AACjB,kBAAI,KAAK,kBAAkB,MAAM,OAAO,UAAU,CAAC,kBAAkB;AAErE,qBAAO,KAAK;AAAA,gBACV,QAAQ,6BAA6B,MAAM,KAA+C;AAAA,gBAC1F,UAAU,MAAM,YAAY;AAAA,gBAC5B,YAAY,MAAM;AAAA,cACpB,CAAC;AAAA,YACH;AAAA;AAAA;AAAA;AAAA,YAKA,KAAK,OAAO;AACV,kBAAI,CAAC,EAAE,SAAU,QAAO,KAAK,EAAE,OAAO,uBAAuB,CAAC;AAE9D,oBAAM,aAAa,MAAM,wBAAwB,EAAE,aAAa,MAAM;AAEtE,kBAAI,KAAK,oBAAoB,UAAU,cAAc,EAAE,QAAQ,EAAE;AAEjE,oBAAM,MAAM,MAAM,OAAO;AAAA,gBACvB;AAAA,gBACA,CAAC,KAAK,SACJ,IAAI,SAAS,cAAc;AAAA,kBACzB;AAAA,oBACE,MAAM,EAAE,aAAa,YAAY,UAAU,EAAE,SAAS;AAAA,kBACxD;AAAA,kBACA;AAAA,gBACF;AAAA,gBACF,EAAE,IAAI,OAAO;AAAA,cACf;AACA,2BAAa,GAAG;AAEhB,kBAAI,KAAK,wBAAwB,EAAE,QAAQ,EAAE;AAE7C,qBAAO,KAAK;AAAA,gBACV,OAAO,yBAAyB,IAAI,MAAM,KAAwC;AAAA,cACpF,CAAC;AAAA,YACH;AAAA;AAAA;AAAA;AAAA,YAKA,KAAK,SAAS;AACZ,kBAAI,CAAC,EAAE,SAAU,QAAO,KAAK,EAAE,OAAO,uBAAuB,CAAC;AAE9D,oBAAM,aAAa,MAAM,wBAAwB,EAAE,aAAa,MAAM;AAEtE,oBAAM,aAAkB,CAAC;AAGzB,kBAAI,EAAE,YAAY;AAChB,sBAAM,UAAU,qBAAqB,EAAE,UAAU;AACjD,oBAAI,CAAC;AACH,yBAAO,KAAK;AAAA,oBACV,OACE;AAAA,oBACF,UAAU,EAAE;AAAA,kBACd,CAAC;AACH,2BAAW,aAAa,EAAE,WAAW,QAAQ;AAAA,cAC/C;AAEA,kBAAI,EAAE,UAAU;AACd,sBAAM,QAAQ,qBAAqB,EAAE,QAAQ;AAC7C,oBAAI,CAAC;AACH,yBAAO,KAAK;AAAA,oBACV,OACE;AAAA,oBACF,UAAU,EAAE;AAAA,kBACd,CAAC;AACH,2BAAW,WAAW,EAAE,WAAW,MAAM;AAAA,cAC3C;AAEA,kBAAI,EAAE,QAAS,YAAW,UAAU,EAAE;AACtC,kBAAI,EAAE,YAAa,YAAW,cAAc,EAAE;AAC9C,kBAAI,EAAE,SAAU,YAAW,WAAW,EAAE,MAAM,EAAE,SAAS;AAEzD,kBAAI;AAAA,gBACF,sBAAsB,UAAU,cAAc,EAAE,QAAQ,YAAY,OAAO,KAAK,UAAU,EAAE,KAAK,GAAG,CAAC;AAAA,cACvG;AAEA,oBAAM,MAAM,MAAM,OAAO;AAAA,gBACvB;AAAA,gBACA,CAAC,KAAK,SACJ,IAAI,SAAS,cAAc;AAAA,kBACzB;AAAA,oBACE,MAAM,EAAE,aAAa,YAAY,UAAU,EAAE,SAAS;AAAA,oBACtD,MAAM;AAAA,kBACR;AAAA,kBACA;AAAA,gBACF;AAAA,gBACF,EAAE,IAAI,OAAO;AAAA,cACf;AACA,2BAAa,GAAG;AAEhB,kBAAI,KAAK,wBAAwB,EAAE,QAAQ,EAAE;AAE7C,qBAAO,KAAK;AAAA,gBACV,OAAO,yBAAyB,IAAI,MAAM,KAAwC;AAAA,cACpF,CAAC;AAAA,YACH;AAAA;AAAA;AAAA;AAAA,YAKA,KAAK,UAAU;AACb,kBAAI,CAAC,EAAE,SAAU,QAAO,KAAK,EAAE,OAAO,uBAAuB,CAAC;AAE9D,oBAAM,aAAa,MAAM,wBAAwB,EAAE,aAAa,MAAM;AAEtE,kBAAI;AAAA,gBACF,uBAAuB,UAAU,cAAc,EAAE,QAAQ,YAAY,EAAE,qBAAqB,IAAI;AAAA,cAClG;AAEA,oBAAM,MAAM,MAAM,OAAO;AAAA,gBACvB;AAAA,gBACA,CAAC,KAAK,SACJ,IAAI,SAAS,cAAc;AAAA,kBACzB;AAAA,oBACE,MAAM,EAAE,aAAa,YAAY,UAAU,EAAE,SAAS;AAAA,oBACtD,QAAQ;AAAA,sBACN,mBAAoB,EAAE,qBAAqB;AAAA,oBAC7C;AAAA,kBACF;AAAA,kBACA;AAAA,gBACF;AAAA,gBACF,EAAE,IAAI,OAAO;AAAA,cACf;AACA,2BAAa,GAAG;AAEhB,kBAAI,KAAK,yBAAyB,EAAE,QAAQ,EAAE;AAE9C,qBAAO,KAAK;AAAA,gBACV,SAAS;AAAA,gBACT,UAAU,EAAE;AAAA,cACd,CAAC;AAAA,YACH;AAAA;AAAA;AAAA;AAAA,YAKA,KAAK,UAAU;AACb,kBAAI,CAAC,EAAE,MAAO,QAAO,KAAK,EAAE,OAAO,oBAAoB,CAAC;AAExD,oBAAM,aAAa,MAAM,wBAAwB,EAAE,aAAa,MAAM;AAEtE,kBAAI,KAAK,uBAAuB,UAAU,WAAW,EAAE,KAAK,eAAe,EAAE,aAAa,EAAE,EAAE;AAE9F,oBAAM,MAAM,MAAM,OAAO;AAAA,gBACvB;AAAA,gBACA,CAAC,KAAK,SACJ,IAAI,SAAS,cAAc;AAAA,kBACzB;AAAA,oBACE,MAAM,EAAE,aAAa,WAAW;AAAA,oBAChC,QAAQ;AAAA,sBACN,WAAW,EAAE;AAAA,sBACb,YAAY,EAAE;AAAA,oBAChB;AAAA,oBACA,MAAM;AAAA,sBACJ,OAAO,EAAE;AAAA,oBACX;AAAA,kBACF;AAAA,kBACA;AAAA,gBACF;AAAA,gBACF,EAAE,IAAI,OAAO;AAAA,cACf;AACA,2BAAa,GAAG;AAEhB,oBAAM,OAAO,IAAI;AACjB,kBAAI,KAAK,iBAAiB,MAAM,OAAO,UAAU,CAAC,SAAS;AAE3D,qBAAO,KAAK;AAAA,gBACV,QAAQ,6BAA6B,MAAM,KAA+C;AAAA,gBAC1F,UAAU,MAAM,YAAY;AAAA,gBAC5B,YAAY,MAAM;AAAA,cACpB,CAAC;AAAA,YACH;AAAA;AAAA;AAAA;AAAA,YAKA,KAAK,SAAS;AACZ,kBAAI,CAAC,EAAE,SAAU,QAAO,KAAK,EAAE,OAAO,uBAAuB,CAAC;AAC9D,kBAAI,CAAC,EAAE,YAAa,QAAO,KAAK,EAAE,OAAO,0BAA0B,CAAC;AAEpE,oBAAM,aAAa,MAAM,wBAAwB,EAAE,aAAa,MAAM;AAEtE,kBAAI,KAAK,sBAAsB,UAAU,cAAc,EAAE,QAAQ,UAAU,EAAE,WAAW,EAAE;AAE1F,oBAAM,MAAM,MAAM,OAAO;AAAA,gBACvB;AAAA,gBACA,CAAC,KAAK,SACJ,IAAI,SAAS,cAAc;AAAA,kBACzB;AAAA,oBACE,MAAM,EAAE,aAAa,YAAY,UAAU,EAAE,SAAS;AAAA,oBACtD,MAAM;AAAA,sBACJ,aAAa,EAAE;AAAA,oBACjB;AAAA,kBACF;AAAA,kBACA;AAAA,gBACF;AAAA,gBACF,EAAE,IAAI,OAAO;AAAA,cACf;AACA,2BAAa,GAAG;AAEhB,kBAAI,KAAK,2BAA2B,EAAE,QAAQ,SAAS,EAAE,WAAW,EAAE;AAEtE,qBAAO,KAAK;AAAA,gBACV,SAAS;AAAA,gBACT,UAAU,EAAE;AAAA,gBACZ,aAAa,EAAE;AAAA,cACjB,CAAC;AAAA,YACH;AAAA;AAAA;AAAA;AAAA,YAKA,KAAK,aAAa;AAChB,kBAAI,CAAC,EAAE,SAAU,QAAO,KAAK,EAAE,OAAO,uBAAuB,CAAC;AAC9D,kBAAI,CAAC,EAAE,WAAY,QAAO,KAAK,EAAE,OAAO,yBAAyB,CAAC;AAClE,kBAAI,CAAC,EAAE,SAAU,QAAO,KAAK,EAAE,OAAO,uBAAuB,CAAC;AAE9D,oBAAM,aAAa,MAAM,wBAAwB,EAAE,aAAa,MAAM;AAEtE,oBAAM,UAAU,qBAAqB,EAAE,UAAU;AACjD,oBAAM,QAAQ,qBAAqB,EAAE,QAAQ;AAE7C,kBAAI,CAAC,WAAW,CAAC;AACf,uBAAO,KAAK;AAAA,kBACV,OACE;AAAA,kBACF,gBAAgB,EAAE;AAAA,kBAClB,cAAc,EAAE;AAAA,gBAClB,CAAC;AAEH,kBAAI,KAAK,0BAA0B,UAAU,cAAc,EAAE,QAAQ,WAAW,OAAO,SAAS,KAAK,EAAE;AAEvG,oBAAM,MAAM,MAAM,OAAO;AAAA,gBACvB;AAAA,gBACA,CAAC,KAAK,SACJ,IAAI,SAAS,cAAc;AAAA,kBACzB;AAAA,oBACE,MAAM,EAAE,aAAa,YAAY,UAAU,EAAE,SAAS;AAAA,oBACtD,QAAQ;AAAA,sBACN,YAAY;AAAA,sBACZ,UAAU;AAAA,sBACV,WAAW,EAAE;AAAA,sBACb,YAAY,EAAE;AAAA,oBAChB;AAAA,kBACF;AAAA,kBACA;AAAA,gBACF;AAAA,gBACF,EAAE,IAAI,OAAO;AAAA,cACf;AACA,2BAAa,GAAG;AAEhB,oBAAM,OAAO,IAAI;AACjB,kBAAI,KAAK,uBAAuB,MAAM,OAAO,UAAU,CAAC,YAAY;AAEpE,qBAAO,KAAK;AAAA,gBACV,WAAW,6BAA6B,MAAM,KAA+C;AAAA,gBAC7F,UAAU,MAAM,YAAY;AAAA,gBAC5B,YAAY,MAAM;AAAA,cACpB,CAAC;AAAA,YACH;AAAA;AAAA;AAAA;AAAA,YAKA,KAAK,iBAAiB;AACpB,kBAAI,CAAC,EAAE,WAAY,QAAO,KAAK,EAAE,OAAO,yBAAyB,CAAC;AAClE,kBAAI,CAAC,EAAE,SAAU,QAAO,KAAK,EAAE,OAAO,uBAAuB,CAAC;AAE9D,oBAAM,aAAa,MAAM,wBAAwB,EAAE,aAAa,MAAM;AAEtE,oBAAM,UAAU,qBAAqB,EAAE,UAAU;AACjD,oBAAM,QAAQ,qBAAqB,EAAE,QAAQ;AAE7C,kBAAI,CAAC,WAAW,CAAC;AACf,uBAAO,KAAK;AAAA,kBACV,OACE;AAAA,kBACF,gBAAgB,EAAE;AAAA,kBAClB,cAAc,EAAE;AAAA,gBAClB,CAAC;AAEH,kBAAI,KAAK,8BAA8B,UAAU,WAAW,OAAO,SAAS,KAAK,EAAE;AAEnF,oBAAM,MAAM,MAAM,OAAO;AAAA,gBACvB;AAAA,gBACA,CAAC,KAAK,SACJ,IAAI,SAAS,cAAc;AAAA,kBACzB;AAAA,oBACE,MAAM,EAAE,aAAa,WAAW;AAAA,oBAChC,QAAQ;AAAA,sBACN,YAAY;AAAA,sBACZ,UAAU;AAAA,sBACV,cAAc;AAAA,oBAChB;AAAA,kBACF;AAAA,kBACA;AAAA,gBACF;AAAA,gBACF,EAAE,IAAI,OAAO;AAAA,cACf;AACA,2BAAa,GAAG;AAEhB,oBAAM,OAAO,IAAI;AACjB,kBAAI,KAAK,2BAA2B,MAAM,OAAO,UAAU,CAAC,SAAS;AAErE,qBAAO,KAAK;AAAA,gBACV,QAAQ,6BAA6B,MAAM,KAA+C;AAAA,gBAC1F,UAAU,MAAM,YAAY;AAAA,gBAC5B,YAAY,MAAM;AAAA,cACpB,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF,SAAS,KAAK;AACZ,iBAAO,MAAM,8BAA8B,KAAK,GAAG;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AAAA,IACA,EAAE,MAAM,wBAAwB;AAAA,EAClC;AAEA,MAAI,OAAO,OAAO,8DAA8D;AAClF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { json, createToolContext, parseTimeToRFC3339, assertLarkOk, handleInvokeErrorWithAutoAuth } from "../helpers";
|
|
3
|
+
const FeishuCalendarFreebusySchema = Type.Object({
|
|
4
|
+
action: Type.Literal("list"),
|
|
5
|
+
time_min: Type.String({
|
|
6
|
+
description: "\u67E5\u8BE2\u8D77\u59CB\u65F6\u95F4\uFF08ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\uFF09"
|
|
7
|
+
}),
|
|
8
|
+
time_max: Type.String({
|
|
9
|
+
description: "\u67E5\u8BE2\u7ED3\u675F\u65F6\u95F4\uFF08ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\uFF09"
|
|
10
|
+
}),
|
|
11
|
+
user_ids: Type.Array(
|
|
12
|
+
Type.String({
|
|
13
|
+
description: "\u7528\u6237 open_id"
|
|
14
|
+
}),
|
|
15
|
+
{
|
|
16
|
+
description: "\u8981\u67E5\u8BE2\u5FD9\u95F2\u7684\u7528\u6237 ID \u5217\u8868\uFF081-10 \u4E2A\u7528\u6237\uFF09",
|
|
17
|
+
minItems: 1,
|
|
18
|
+
maxItems: 10
|
|
19
|
+
}
|
|
20
|
+
)
|
|
21
|
+
});
|
|
22
|
+
function registerFeishuCalendarFreebusyTool(api) {
|
|
23
|
+
if (!api.config) return;
|
|
24
|
+
const cfg = api.config;
|
|
25
|
+
const { toolClient, log } = createToolContext(api, "feishu_calendar_freebusy");
|
|
26
|
+
api.registerTool(
|
|
27
|
+
{
|
|
28
|
+
name: "feishu_calendar_freebusy",
|
|
29
|
+
label: "Feishu Calendar Free/Busy Status",
|
|
30
|
+
description: "\u3010\u4EE5\u7528\u6237\u8EAB\u4EFD\u3011\u98DE\u4E66\u65E5\u5386\u5FD9\u95F2\u67E5\u8BE2\u5DE5\u5177\u3002\u5F53\u7528\u6237\u8981\u6C42\u67E5\u8BE2\u67D0\u65F6\u95F4\u6BB5\u5185\u67D0\u4EBA\u662F\u5426\u7A7A\u95F2\u3001\u67E5\u770B\u5FD9\u95F2\u72B6\u6001\u65F6\u4F7F\u7528\u3002\u652F\u6301\u6279\u91CF\u67E5\u8BE2 1-10 \u4E2A\u7528\u6237\u7684\u4E3B\u65E5\u5386\u5FD9\u95F2\u4FE1\u606F\uFF0C\u7528\u4E8E\u5B89\u6392\u4F1A\u8BAE\u65F6\u95F4\u3002",
|
|
31
|
+
parameters: FeishuCalendarFreebusySchema,
|
|
32
|
+
async execute(_toolCallId, params) {
|
|
33
|
+
const p = params;
|
|
34
|
+
log.info(`[FREEBUSY] Execute called with params: ${JSON.stringify(p)}`);
|
|
35
|
+
try {
|
|
36
|
+
const client = toolClient();
|
|
37
|
+
if (p.action !== "list") {
|
|
38
|
+
log.warn(`[FREEBUSY] Unknown action: ${p.action}`);
|
|
39
|
+
return json({ error: `Unknown action: ${p.action}` });
|
|
40
|
+
}
|
|
41
|
+
if (!p.user_ids || p.user_ids.length === 0) {
|
|
42
|
+
log.warn(`[FREEBUSY] user_ids is empty`);
|
|
43
|
+
return json({
|
|
44
|
+
error: "user_ids is required (1-10 user IDs)"
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (p.user_ids.length > 10) {
|
|
48
|
+
log.warn(`[FREEBUSY] user_ids exceeds limit: ${p.user_ids.length}`);
|
|
49
|
+
return json({
|
|
50
|
+
error: `user_ids count exceeds limit, maximum 10 users (current: ${p.user_ids.length})`
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
log.info(`[FREEBUSY] Validation passed, user_ids count: ${p.user_ids.length}`);
|
|
54
|
+
const timeMin = parseTimeToRFC3339(p.time_min);
|
|
55
|
+
const timeMax = parseTimeToRFC3339(p.time_max);
|
|
56
|
+
if (!timeMin || !timeMax) {
|
|
57
|
+
log.warn(`[FREEBUSY] Time format error: time_min=${p.time_min}, time_max=${p.time_max}`);
|
|
58
|
+
return json({
|
|
59
|
+
error: "Invalid time format. Must use ISO 8601 / RFC 3339 with timezone, e.g. '2024-01-01T00:00:00+08:00' or '2026-02-25 14:00:00'.",
|
|
60
|
+
received_time_min: p.time_min,
|
|
61
|
+
received_time_max: p.time_max
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
log.info(
|
|
65
|
+
`[FREEBUSY] Calling batch API: time_min=${p.time_min} -> ${timeMin}, time_max=${p.time_max} -> ${timeMax}, user_ids=${p.user_ids.length}`
|
|
66
|
+
);
|
|
67
|
+
const res = await client.invoke(
|
|
68
|
+
"feishu_calendar_freebusy.list",
|
|
69
|
+
(sdk, opts) => sdk.calendar.freebusy.batch(
|
|
70
|
+
{
|
|
71
|
+
data: {
|
|
72
|
+
time_min: timeMin,
|
|
73
|
+
time_max: timeMax,
|
|
74
|
+
user_ids: p.user_ids,
|
|
75
|
+
include_external_calendar: true,
|
|
76
|
+
only_busy: true
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
78
|
+
}
|
|
79
|
+
// SDK 类型定义可能未包含所有字段
|
|
80
|
+
},
|
|
81
|
+
opts
|
|
82
|
+
),
|
|
83
|
+
{ as: "user" }
|
|
84
|
+
);
|
|
85
|
+
assertLarkOk(res);
|
|
86
|
+
const data = res.data;
|
|
87
|
+
const freebusyLists = data?.freebusy_lists ?? [];
|
|
88
|
+
log.info(`[FREEBUSY] Success: returned ${freebusyLists.length} user(s) freebusy data`);
|
|
89
|
+
return json({
|
|
90
|
+
freebusy_lists: freebusyLists,
|
|
91
|
+
_debug: {
|
|
92
|
+
time_min_input: p.time_min,
|
|
93
|
+
time_min_rfc3339: timeMin,
|
|
94
|
+
time_max_input: p.time_max,
|
|
95
|
+
time_max_rfc3339: timeMax,
|
|
96
|
+
user_count: p.user_ids.length
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
} catch (err) {
|
|
100
|
+
return await handleInvokeErrorWithAutoAuth(err, cfg);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
{ name: "feishu_calendar_freebusy" }
|
|
105
|
+
);
|
|
106
|
+
api.logger.info?.("feishu_calendar_freebusy: Registered feishu_calendar_freebusy tool");
|
|
107
|
+
}
|
|
108
|
+
export {
|
|
109
|
+
registerFeishuCalendarFreebusyTool
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=freebusy.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/tools/oapi/calendar/freebusy.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * feishu_calendar_freebusy tool -- Query user/room calendar free/busy status.\n *\n * P0 Actions: list\n *\n * Uses the Feishu Calendar API:\n * - list: POST /open-apis/calendar/v4/freebusy/batch (\u6279\u91CF\u67E5\u8BE2\u63A5\u53E3)\n */\n\nimport type { OpenClawPluginApi } from 'openclaw/plugin-sdk';\nimport { Type } from '@sinclair/typebox';\nimport { json, createToolContext, parseTimeToRFC3339, assertLarkOk, handleInvokeErrorWithAutoAuth } from '../helpers';\nimport type { FreebusyData } from '../sdk-types';\n\n// ---------------------------------------------------------------------------\n// Schema\n// ---------------------------------------------------------------------------\n\nconst FeishuCalendarFreebusySchema = Type.Object({\n action: Type.Literal('list'),\n time_min: Type.String({\n description: \"\u67E5\u8BE2\u8D77\u59CB\u65F6\u95F4\uFF08ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\uFF09\",\n }),\n time_max: Type.String({\n description: \"\u67E5\u8BE2\u7ED3\u675F\u65F6\u95F4\uFF08ISO 8601 / RFC 3339 \u683C\u5F0F\uFF08\u5305\u542B\u65F6\u533A\uFF09\uFF0C\u4F8B\u5982 '2024-01-01T00:00:00+08:00'\uFF09\",\n }),\n user_ids: Type.Array(\n Type.String({\n description: '\u7528\u6237 open_id',\n }),\n {\n description: '\u8981\u67E5\u8BE2\u5FD9\u95F2\u7684\u7528\u6237 ID \u5217\u8868\uFF081-10 \u4E2A\u7528\u6237\uFF09',\n minItems: 1,\n maxItems: 10,\n },\n ),\n});\n\n// ---------------------------------------------------------------------------\n// Params type\n// ---------------------------------------------------------------------------\n\ninterface FeishuCalendarFreebusyParams {\n action: 'list';\n time_min: string;\n time_max: string;\n user_ids: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Registration\n// ---------------------------------------------------------------------------\n\nexport function registerFeishuCalendarFreebusyTool(api: OpenClawPluginApi) {\n if (!api.config) return;\n const cfg = api.config;\n\n const { toolClient, log } = createToolContext(api, 'feishu_calendar_freebusy');\n\n api.registerTool(\n {\n name: 'feishu_calendar_freebusy',\n label: 'Feishu Calendar Free/Busy Status',\n description:\n '\u3010\u4EE5\u7528\u6237\u8EAB\u4EFD\u3011\u98DE\u4E66\u65E5\u5386\u5FD9\u95F2\u67E5\u8BE2\u5DE5\u5177\u3002\u5F53\u7528\u6237\u8981\u6C42\u67E5\u8BE2\u67D0\u65F6\u95F4\u6BB5\u5185\u67D0\u4EBA\u662F\u5426\u7A7A\u95F2\u3001\u67E5\u770B\u5FD9\u95F2\u72B6\u6001\u65F6\u4F7F\u7528\u3002\u652F\u6301\u6279\u91CF\u67E5\u8BE2 1-10 \u4E2A\u7528\u6237\u7684\u4E3B\u65E5\u5386\u5FD9\u95F2\u4FE1\u606F\uFF0C\u7528\u4E8E\u5B89\u6392\u4F1A\u8BAE\u65F6\u95F4\u3002',\n parameters: FeishuCalendarFreebusySchema,\n async execute(_toolCallId, params) {\n const p = params as FeishuCalendarFreebusyParams;\n\n log.info(`[FREEBUSY] Execute called with params: ${JSON.stringify(p)}`);\n\n try {\n const client = toolClient();\n\n if (p.action !== 'list') {\n log.warn(`[FREEBUSY] Unknown action: ${p.action}`);\n return json({ error: `Unknown action: ${p.action}` });\n }\n\n // Validate user_ids (batch API requires 1-10 users)\n if (!p.user_ids || p.user_ids.length === 0) {\n log.warn(`[FREEBUSY] user_ids is empty`);\n return json({\n error: 'user_ids is required (1-10 user IDs)',\n });\n }\n\n if (p.user_ids.length > 10) {\n log.warn(`[FREEBUSY] user_ids exceeds limit: ${p.user_ids.length}`);\n return json({\n error: `user_ids count exceeds limit, maximum 10 users (current: ${p.user_ids.length})`,\n });\n }\n\n log.info(`[FREEBUSY] Validation passed, user_ids count: ${p.user_ids.length}`);\n\n // Convert time strings to RFC 3339 format (required by freebusy API)\n const timeMin = parseTimeToRFC3339(p.time_min);\n const timeMax = parseTimeToRFC3339(p.time_max);\n\n if (!timeMin || !timeMax) {\n log.warn(`[FREEBUSY] Time format error: time_min=${p.time_min}, time_max=${p.time_max}`);\n return json({\n error:\n \"Invalid time format. Must use ISO 8601 / RFC 3339 with timezone, e.g. '2024-01-01T00:00:00+08:00' or '2026-02-25 14:00:00'.\",\n received_time_min: p.time_min,\n received_time_max: p.time_max,\n });\n }\n\n log.info(\n `[FREEBUSY] Calling batch API: time_min=${p.time_min} -> ${timeMin}, time_max=${p.time_max} -> ${timeMax}, user_ids=${p.user_ids.length}`,\n );\n\n const res = await client.invoke(\n 'feishu_calendar_freebusy.list',\n (sdk, opts) =>\n sdk.calendar.freebusy.batch(\n {\n data: {\n time_min: timeMin,\n time_max: timeMax,\n user_ids: p.user_ids,\n include_external_calendar: true,\n only_busy: true,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any, // SDK \u7C7B\u578B\u5B9A\u4E49\u53EF\u80FD\u672A\u5305\u542B\u6240\u6709\u5B57\u6BB5\n },\n opts,\n ),\n { as: 'user' },\n );\n assertLarkOk(res);\n\n const data = res.data as FreebusyData | undefined;\n const freebusyLists = data?.freebusy_lists ?? [];\n log.info(`[FREEBUSY] Success: returned ${freebusyLists.length} user(s) freebusy data`);\n\n return json({\n freebusy_lists: freebusyLists,\n _debug: {\n time_min_input: p.time_min,\n time_min_rfc3339: timeMin,\n time_max_input: p.time_max,\n time_max_rfc3339: timeMax,\n user_count: p.user_ids.length,\n },\n });\n } catch (err) {\n return await handleInvokeErrorWithAutoAuth(err, cfg);\n }\n },\n },\n { name: 'feishu_calendar_freebusy' },\n );\n\n api.logger.info?.('feishu_calendar_freebusy: Registered feishu_calendar_freebusy tool');\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { registerFeishuCalendarCalendarTool } from "./calendar";
|
|
2
|
+
import { registerFeishuCalendarEventTool } from "./event";
|
|
3
|
+
import { registerFeishuCalendarEventAttendeeTool } from "./event-attendee";
|
|
4
|
+
import { registerFeishuCalendarFreebusyTool } from "./freebusy";
|
|
5
|
+
export {
|
|
6
|
+
registerFeishuCalendarCalendarTool,
|
|
7
|
+
registerFeishuCalendarEventAttendeeTool,
|
|
8
|
+
registerFeishuCalendarEventTool,
|
|
9
|
+
registerFeishuCalendarFreebusyTool
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/tools/oapi/calendar/index.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport { registerFeishuCalendarCalendarTool } from './calendar';\nexport { registerFeishuCalendarEventTool } from './event';\nexport { registerFeishuCalendarEventAttendeeTool } from './event-attendee';\nexport { registerFeishuCalendarFreebusyTool } from './freebusy';\n"],
|
|
5
|
+
"mappings": "AAKA,SAAS,0CAA0C;AACnD,SAAS,uCAAuC;AAChD,SAAS,+CAA+C;AACxD,SAAS,0CAA0C;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { json, createToolContext, assertLarkOk, handleInvokeErrorWithAutoAuth } from "../helpers";
|
|
3
|
+
const FeishuChatSchema = Type.Union([
|
|
4
|
+
// SEARCH
|
|
5
|
+
Type.Object({
|
|
6
|
+
action: Type.Literal("search"),
|
|
7
|
+
query: Type.String({
|
|
8
|
+
description: "\u641C\u7D22\u5173\u952E\u8BCD\uFF08\u5FC5\u586B\uFF09\u3002\u652F\u6301\u5339\u914D\u7FA4\u540D\u79F0\u3001\u7FA4\u6210\u5458\u540D\u79F0\u3002\u652F\u6301\u591A\u8BED\u79CD\u3001\u62FC\u97F3\u3001\u524D\u7F00\u7B49\u6A21\u7CCA\u641C\u7D22\u3002"
|
|
9
|
+
}),
|
|
10
|
+
page_size: Type.Optional(
|
|
11
|
+
Type.Integer({
|
|
12
|
+
description: "\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA420\uFF09",
|
|
13
|
+
minimum: 1
|
|
14
|
+
})
|
|
15
|
+
),
|
|
16
|
+
page_token: Type.Optional(
|
|
17
|
+
Type.String({
|
|
18
|
+
description: "\u5206\u9875\u6807\u8BB0\u3002\u9996\u6B21\u8BF7\u6C42\u65E0\u9700\u586B\u5199"
|
|
19
|
+
})
|
|
20
|
+
),
|
|
21
|
+
user_id_type: Type.Optional(
|
|
22
|
+
Type.Union([Type.Literal("open_id"), Type.Literal("union_id"), Type.Literal("user_id")], {
|
|
23
|
+
description: "\u7528\u6237 ID \u7C7B\u578B\uFF08\u9ED8\u8BA4 open_id\uFF09"
|
|
24
|
+
})
|
|
25
|
+
)
|
|
26
|
+
}),
|
|
27
|
+
// GET
|
|
28
|
+
Type.Object({
|
|
29
|
+
action: Type.Literal("get"),
|
|
30
|
+
chat_id: Type.String({
|
|
31
|
+
description: "\u7FA4 ID\uFF08\u683C\u5F0F\u5982 oc_xxx\uFF09"
|
|
32
|
+
}),
|
|
33
|
+
user_id_type: Type.Optional(
|
|
34
|
+
Type.Union([Type.Literal("open_id"), Type.Literal("union_id"), Type.Literal("user_id")], {
|
|
35
|
+
description: "\u7528\u6237 ID \u7C7B\u578B\uFF08\u9ED8\u8BA4 open_id\uFF09"
|
|
36
|
+
})
|
|
37
|
+
)
|
|
38
|
+
})
|
|
39
|
+
]);
|
|
40
|
+
function registerChatSearchTool(api) {
|
|
41
|
+
if (!api.config) return;
|
|
42
|
+
const cfg = api.config;
|
|
43
|
+
const { toolClient, log } = createToolContext(api, "feishu_chat");
|
|
44
|
+
api.registerTool(
|
|
45
|
+
{
|
|
46
|
+
name: "feishu_chat",
|
|
47
|
+
label: "Feishu: Chat Management",
|
|
48
|
+
description: "\u4EE5\u7528\u6237\u8EAB\u4EFD\u8C03\u7528\u98DE\u4E66\u7FA4\u804A\u7BA1\u7406\u5DE5\u5177\u3002Actions: search\uFF08\u641C\u7D22\u7FA4\u5217\u8868\uFF0C\u652F\u6301\u5173\u952E\u8BCD\u5339\u914D\u7FA4\u540D\u79F0\u3001\u7FA4\u6210\u5458\uFF09, get\uFF08\u83B7\u53D6\u6307\u5B9A\u7FA4\u7684\u8BE6\u7EC6\u4FE1\u606F\uFF0C\u5305\u62EC\u7FA4\u540D\u79F0\u3001\u63CF\u8FF0\u3001\u5934\u50CF\u3001\u7FA4\u4E3B\u3001\u6743\u9650\u914D\u7F6E\u7B49\uFF09\u3002",
|
|
49
|
+
parameters: FeishuChatSchema,
|
|
50
|
+
async execute(_toolCallId, params) {
|
|
51
|
+
const p = params;
|
|
52
|
+
try {
|
|
53
|
+
const client = toolClient();
|
|
54
|
+
switch (p.action) {
|
|
55
|
+
// -----------------------------------------------------------------
|
|
56
|
+
// SEARCH
|
|
57
|
+
// -----------------------------------------------------------------
|
|
58
|
+
case "search": {
|
|
59
|
+
log.info(`search: query="${p.query}", page_size=${p.page_size ?? 20}`);
|
|
60
|
+
const res = await client.invoke(
|
|
61
|
+
"feishu_chat.search",
|
|
62
|
+
(sdk, opts) => sdk.im.v1.chat.search(
|
|
63
|
+
{
|
|
64
|
+
params: {
|
|
65
|
+
user_id_type: p.user_id_type || "open_id",
|
|
66
|
+
query: p.query,
|
|
67
|
+
page_size: p.page_size,
|
|
68
|
+
page_token: p.page_token
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
opts
|
|
72
|
+
),
|
|
73
|
+
{ as: "user" }
|
|
74
|
+
);
|
|
75
|
+
assertLarkOk(res);
|
|
76
|
+
const data = res.data;
|
|
77
|
+
const chatCount = data?.items?.length ?? 0;
|
|
78
|
+
log.info(`search: found ${chatCount} chats`);
|
|
79
|
+
return json({
|
|
80
|
+
items: data?.items,
|
|
81
|
+
has_more: data?.has_more ?? false,
|
|
82
|
+
page_token: data?.page_token
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
// -----------------------------------------------------------------
|
|
86
|
+
// GET
|
|
87
|
+
// -----------------------------------------------------------------
|
|
88
|
+
case "get": {
|
|
89
|
+
log.info(`get: chat_id=${p.chat_id}, user_id_type=${p.user_id_type ?? "open_id"}`);
|
|
90
|
+
const res = await client.invoke(
|
|
91
|
+
"feishu_chat.get",
|
|
92
|
+
(sdk, opts) => sdk.im.v1.chat.get(
|
|
93
|
+
{
|
|
94
|
+
path: {
|
|
95
|
+
chat_id: p.chat_id
|
|
96
|
+
},
|
|
97
|
+
params: {
|
|
98
|
+
user_id_type: p.user_id_type || "open_id"
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
...opts ?? {},
|
|
103
|
+
headers: {
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
105
|
+
...opts?.headers ?? {},
|
|
106
|
+
"X-Chat-Custom-Header": "enable_chat_list_security_check"
|
|
107
|
+
}
|
|
108
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
109
|
+
}
|
|
110
|
+
),
|
|
111
|
+
{ as: "user" }
|
|
112
|
+
);
|
|
113
|
+
assertLarkOk(res);
|
|
114
|
+
log.info(`get: retrieved chat info for ${p.chat_id}`);
|
|
115
|
+
return json({
|
|
116
|
+
chat: res.data
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
} catch (err) {
|
|
121
|
+
return await handleInvokeErrorWithAutoAuth(err, cfg);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
{ name: "feishu_chat" }
|
|
126
|
+
);
|
|
127
|
+
api.logger.info?.("feishu_chat: Registered feishu_chat tool");
|
|
128
|
+
}
|
|
129
|
+
export {
|
|
130
|
+
registerChatSearchTool
|
|
131
|
+
};
|
|
132
|
+
//# sourceMappingURL=chat.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/tools/oapi/chat/chat.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * feishu_chat tool -- \u7BA1\u7406\u98DE\u4E66\u7FA4\u804A\n *\n * Actions:\n * - search: \u641C\u7D22\u5BF9\u7528\u6237\u6216\u673A\u5668\u4EBA\u53EF\u89C1\u7684\u7FA4\u5217\u8868\n * - get: \u83B7\u53D6\u6307\u5B9A\u7FA4\u7684\u8BE6\u7EC6\u4FE1\u606F\n *\n * Uses the Feishu IM v1 API:\n * - search: GET /open-apis/im/v1/chats/search\n * - get: GET /open-apis/im/v1/chats/:chat_id\n */\n\nimport type { OpenClawPluginApi } from 'openclaw/plugin-sdk';\nimport { Type } from '@sinclair/typebox';\nimport { json, createToolContext, assertLarkOk, handleInvokeErrorWithAutoAuth } from '../helpers';\nimport type { PaginatedData } from '../sdk-types';\n\n// ---------------------------------------------------------------------------\n// Schema\n// ---------------------------------------------------------------------------\n\nconst FeishuChatSchema = Type.Union([\n // SEARCH\n Type.Object({\n action: Type.Literal('search'),\n query: Type.String({\n description: '\u641C\u7D22\u5173\u952E\u8BCD\uFF08\u5FC5\u586B\uFF09\u3002\u652F\u6301\u5339\u914D\u7FA4\u540D\u79F0\u3001\u7FA4\u6210\u5458\u540D\u79F0\u3002' + '\u652F\u6301\u591A\u8BED\u79CD\u3001\u62FC\u97F3\u3001\u524D\u7F00\u7B49\u6A21\u7CCA\u641C\u7D22\u3002',\n }),\n page_size: Type.Optional(\n Type.Integer({\n description: '\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA420\uFF09',\n minimum: 1,\n }),\n ),\n page_token: Type.Optional(\n Type.String({\n description: '\u5206\u9875\u6807\u8BB0\u3002\u9996\u6B21\u8BF7\u6C42\u65E0\u9700\u586B\u5199',\n }),\n ),\n user_id_type: Type.Optional(\n Type.Union([Type.Literal('open_id'), Type.Literal('union_id'), Type.Literal('user_id')], {\n description: '\u7528\u6237 ID \u7C7B\u578B\uFF08\u9ED8\u8BA4 open_id\uFF09',\n }),\n ),\n }),\n\n // GET\n Type.Object({\n action: Type.Literal('get'),\n chat_id: Type.String({\n description: '\u7FA4 ID\uFF08\u683C\u5F0F\u5982 oc_xxx\uFF09',\n }),\n user_id_type: Type.Optional(\n Type.Union([Type.Literal('open_id'), Type.Literal('union_id'), Type.Literal('user_id')], {\n description: '\u7528\u6237 ID \u7C7B\u578B\uFF08\u9ED8\u8BA4 open_id\uFF09',\n }),\n ),\n }),\n]);\n\n// ---------------------------------------------------------------------------\n// Params type\n// ---------------------------------------------------------------------------\n\ntype FeishuChatParams =\n | {\n action: 'search';\n query: string;\n page_size?: number;\n page_token?: string;\n user_id_type?: 'open_id' | 'union_id' | 'user_id';\n }\n | {\n action: 'get';\n chat_id: string;\n user_id_type?: 'open_id' | 'union_id' | 'user_id';\n };\n\n// ---------------------------------------------------------------------------\n// Registration\n// ---------------------------------------------------------------------------\n\nexport function registerChatSearchTool(api: OpenClawPluginApi) {\n if (!api.config) return;\n const cfg = api.config;\n\n const { toolClient, log } = createToolContext(api, 'feishu_chat');\n\n api.registerTool(\n {\n name: 'feishu_chat',\n label: 'Feishu: Chat Management',\n description:\n '\u4EE5\u7528\u6237\u8EAB\u4EFD\u8C03\u7528\u98DE\u4E66\u7FA4\u804A\u7BA1\u7406\u5DE5\u5177\u3002Actions: search\uFF08\u641C\u7D22\u7FA4\u5217\u8868\uFF0C\u652F\u6301\u5173\u952E\u8BCD\u5339\u914D\u7FA4\u540D\u79F0\u3001\u7FA4\u6210\u5458\uFF09, get\uFF08\u83B7\u53D6\u6307\u5B9A\u7FA4\u7684\u8BE6\u7EC6\u4FE1\u606F\uFF0C\u5305\u62EC\u7FA4\u540D\u79F0\u3001\u63CF\u8FF0\u3001\u5934\u50CF\u3001\u7FA4\u4E3B\u3001\u6743\u9650\u914D\u7F6E\u7B49\uFF09\u3002',\n parameters: FeishuChatSchema,\n async execute(_toolCallId: string, params: unknown) {\n const p = params as FeishuChatParams;\n try {\n const client = toolClient();\n\n switch (p.action) {\n // -----------------------------------------------------------------\n // SEARCH\n // -----------------------------------------------------------------\n case 'search': {\n log.info(`search: query=\"${p.query}\", page_size=${p.page_size ?? 20}`);\n\n const res = await client.invoke(\n 'feishu_chat.search',\n (sdk, opts) =>\n sdk.im.v1.chat.search(\n {\n params: {\n user_id_type: p.user_id_type || 'open_id',\n query: p.query,\n page_size: p.page_size,\n page_token: p.page_token,\n },\n },\n opts,\n ),\n { as: 'user' },\n );\n assertLarkOk(res);\n\n const data = res.data as PaginatedData | undefined;\n const chatCount = data?.items?.length ?? 0;\n log.info(`search: found ${chatCount} chats`);\n\n return json({\n items: data?.items,\n has_more: data?.has_more ?? false,\n page_token: data?.page_token,\n });\n }\n\n // -----------------------------------------------------------------\n // GET\n // -----------------------------------------------------------------\n case 'get': {\n log.info(`get: chat_id=${p.chat_id}, user_id_type=${p.user_id_type ?? 'open_id'}`);\n\n const res = await client.invoke(\n 'feishu_chat.get',\n (sdk, opts) =>\n sdk.im.v1.chat.get(\n {\n path: {\n chat_id: p.chat_id,\n },\n params: {\n user_id_type: p.user_id_type || 'open_id',\n },\n },\n {\n ...(opts ?? {}),\n headers: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ...((opts as any)?.headers ?? {}),\n 'X-Chat-Custom-Header': 'enable_chat_list_security_check',\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any,\n ),\n { as: 'user' },\n );\n assertLarkOk(res);\n\n log.info(`get: retrieved chat info for ${p.chat_id}`);\n\n return json({\n chat: res.data,\n });\n }\n }\n } catch (err) {\n return await handleInvokeErrorWithAutoAuth(err, cfg);\n }\n },\n },\n { name: 'feishu_chat' },\n );\n\n api.logger.info?.('feishu_chat: Registered feishu_chat tool');\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { registerChatSearchTool } from "./chat";
|
|
2
|
+
import { registerChatMembersTool } from "./members";
|
|
3
|
+
function registerFeishuChatTools(api) {
|
|
4
|
+
registerChatSearchTool(api);
|
|
5
|
+
registerChatMembersTool(api);
|
|
6
|
+
api.logger.info?.("feishu_chat: Registered feishu_chat, feishu_chat_members");
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
registerFeishuChatTools
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/tools/oapi/chat/index.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * Chat Tools Index\n *\n * \u7FA4\u7EC4\u76F8\u5173\u5DE5\u5177\n */\n\nimport type { OpenClawPluginApi } from 'openclaw/plugin-sdk';\nimport { registerChatSearchTool } from './chat';\nimport { registerChatMembersTool } from './members';\n\nexport function registerFeishuChatTools(api: OpenClawPluginApi) {\n registerChatSearchTool(api);\n registerChatMembersTool(api);\n\n api.logger.info?.('feishu_chat: Registered feishu_chat, feishu_chat_members');\n}\n"],
|
|
5
|
+
"mappings": "AAUA,SAAS,8BAA8B;AACvC,SAAS,+BAA+B;AAEjC,SAAS,wBAAwB,KAAwB;AAC9D,yBAAuB,GAAG;AAC1B,0BAAwB,GAAG;AAE3B,MAAI,OAAO,OAAO,0DAA0D;AAC9E;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { json, createToolContext, assertLarkOk, handleInvokeErrorWithAutoAuth } from "../helpers";
|
|
3
|
+
const ChatMembersSchema = Type.Object({
|
|
4
|
+
chat_id: Type.String({
|
|
5
|
+
description: "\u7FA4 ID\uFF08\u683C\u5F0F\u5982 oc_xxx\uFF09\u3002\u53EF\u4EE5\u901A\u8FC7 feishu_chat_search \u5DE5\u5177\u641C\u7D22\u83B7\u53D6"
|
|
6
|
+
}),
|
|
7
|
+
member_id_type: Type.Optional(
|
|
8
|
+
Type.Union([Type.Literal("open_id"), Type.Literal("union_id"), Type.Literal("user_id")])
|
|
9
|
+
),
|
|
10
|
+
page_size: Type.Optional(
|
|
11
|
+
Type.Integer({
|
|
12
|
+
description: "\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA420\uFF09",
|
|
13
|
+
minimum: 1
|
|
14
|
+
})
|
|
15
|
+
),
|
|
16
|
+
page_token: Type.Optional(
|
|
17
|
+
Type.String({
|
|
18
|
+
description: "\u5206\u9875\u6807\u8BB0\u3002\u9996\u6B21\u8BF7\u6C42\u65E0\u9700\u586B\u5199"
|
|
19
|
+
})
|
|
20
|
+
)
|
|
21
|
+
});
|
|
22
|
+
function registerChatMembersTool(api) {
|
|
23
|
+
if (!api.config) return;
|
|
24
|
+
const cfg = api.config;
|
|
25
|
+
const { toolClient, log } = createToolContext(api, "feishu_chat_members");
|
|
26
|
+
api.registerTool(
|
|
27
|
+
{
|
|
28
|
+
name: "feishu_chat_members",
|
|
29
|
+
label: "Feishu: Get Chat Members",
|
|
30
|
+
description: "\u4EE5\u7528\u6237\u7684\u8EAB\u4EFD\u83B7\u53D6\u6307\u5B9A\u7FA4\u7EC4\u7684\u6210\u5458\u5217\u8868\u3002\u8FD4\u56DE\u6210\u5458\u4FE1\u606F\uFF0C\u5305\u542B\u6210\u5458 ID\u3001\u59D3\u540D\u7B49\u3002\u6CE8\u610F\uFF1A\u4E0D\u4F1A\u8FD4\u56DE\u7FA4\u7EC4\u5185\u7684\u673A\u5668\u4EBA\u6210\u5458\u3002",
|
|
31
|
+
parameters: ChatMembersSchema,
|
|
32
|
+
async execute(_toolCallId, params) {
|
|
33
|
+
const p = params;
|
|
34
|
+
try {
|
|
35
|
+
const client = toolClient();
|
|
36
|
+
log.info(`chat_members: chat_id="${p.chat_id}", page_size=${p.page_size ?? 20}`);
|
|
37
|
+
const res = await client.invoke(
|
|
38
|
+
"feishu_chat_members.default",
|
|
39
|
+
(sdk, opts) => sdk.im.v1.chatMembers.get(
|
|
40
|
+
{
|
|
41
|
+
path: { chat_id: p.chat_id },
|
|
42
|
+
params: {
|
|
43
|
+
member_id_type: p.member_id_type || "open_id",
|
|
44
|
+
page_size: p.page_size,
|
|
45
|
+
page_token: p.page_token
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
...opts ?? {},
|
|
50
|
+
headers: {
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
52
|
+
...opts?.headers ?? {},
|
|
53
|
+
"X-Chat-Custom-Header": "enable_chat_list_security_check"
|
|
54
|
+
}
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
56
|
+
}
|
|
57
|
+
),
|
|
58
|
+
{ as: "user" }
|
|
59
|
+
);
|
|
60
|
+
assertLarkOk(res);
|
|
61
|
+
const data = res.data;
|
|
62
|
+
const memberCount = data?.items?.length ?? 0;
|
|
63
|
+
const memberTotal = data?.member_total ?? 0;
|
|
64
|
+
log.info(`chat_members: found ${memberCount} members (total: ${memberTotal})`);
|
|
65
|
+
return json({
|
|
66
|
+
items: data?.items,
|
|
67
|
+
has_more: data?.has_more ?? false,
|
|
68
|
+
page_token: data?.page_token,
|
|
69
|
+
member_total: memberTotal
|
|
70
|
+
});
|
|
71
|
+
} catch (err) {
|
|
72
|
+
return await handleInvokeErrorWithAutoAuth(err, cfg);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
{ name: "feishu_chat_members" }
|
|
77
|
+
);
|
|
78
|
+
api.logger.info?.("feishu_chat_members: Registered feishu_chat_members tool");
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
registerChatMembersTool
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=members.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/tools/oapi/chat/members.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * feishu_chat_members tool -- \u83B7\u53D6\u7FA4\u6210\u5458\u5217\u8868\n *\n * \u83B7\u53D6\u6307\u5B9A\u7FA4\u7EC4\u7684\u6210\u5458\u4FE1\u606F\uFF0C\u5305\u62EC\u6210\u5458\u540D\u5B57\u4E0E ID\n * \u4F7F\u7528 sdk.im.v1.chatMembers.get \u63A5\u53E3\n */\n\nimport type { OpenClawPluginApi } from 'openclaw/plugin-sdk';\nimport { Type } from '@sinclair/typebox';\nimport { json, createToolContext, assertLarkOk, handleInvokeErrorWithAutoAuth } from '../helpers';\nimport type { ChatMemberListData } from '../sdk-types';\n\n// ---------------------------------------------------------------------------\n// Schema\n// ---------------------------------------------------------------------------\n\nconst ChatMembersSchema = Type.Object({\n chat_id: Type.String({\n description: '\u7FA4 ID\uFF08\u683C\u5F0F\u5982 oc_xxx\uFF09\u3002' + '\u53EF\u4EE5\u901A\u8FC7 feishu_chat_search \u5DE5\u5177\u641C\u7D22\u83B7\u53D6',\n }),\n member_id_type: Type.Optional(\n Type.Union([Type.Literal('open_id'), Type.Literal('union_id'), Type.Literal('user_id')]),\n ),\n page_size: Type.Optional(\n Type.Integer({\n description: '\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA420\uFF09',\n minimum: 1,\n }),\n ),\n page_token: Type.Optional(\n Type.String({\n description: '\u5206\u9875\u6807\u8BB0\u3002\u9996\u6B21\u8BF7\u6C42\u65E0\u9700\u586B\u5199',\n }),\n ),\n});\n\n// ---------------------------------------------------------------------------\n// Params type\n// ---------------------------------------------------------------------------\n\ninterface ChatMembersParams {\n chat_id: string;\n member_id_type?: 'open_id' | 'union_id' | 'user_id';\n page_size?: number;\n page_token?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Registration\n// ---------------------------------------------------------------------------\n\nexport function registerChatMembersTool(api: OpenClawPluginApi) {\n if (!api.config) return;\n const cfg = api.config;\n\n const { toolClient, log } = createToolContext(api, 'feishu_chat_members');\n\n api.registerTool(\n {\n name: 'feishu_chat_members',\n label: 'Feishu: Get Chat Members',\n description:\n '\u4EE5\u7528\u6237\u7684\u8EAB\u4EFD\u83B7\u53D6\u6307\u5B9A\u7FA4\u7EC4\u7684\u6210\u5458\u5217\u8868\u3002' +\n '\u8FD4\u56DE\u6210\u5458\u4FE1\u606F\uFF0C\u5305\u542B\u6210\u5458 ID\u3001\u59D3\u540D\u7B49\u3002' +\n '\u6CE8\u610F\uFF1A\u4E0D\u4F1A\u8FD4\u56DE\u7FA4\u7EC4\u5185\u7684\u673A\u5668\u4EBA\u6210\u5458\u3002',\n parameters: ChatMembersSchema,\n async execute(_toolCallId: string, params: unknown) {\n const p = params as ChatMembersParams;\n try {\n const client = toolClient();\n\n log.info(`chat_members: chat_id=\"${p.chat_id}\", page_size=${p.page_size ?? 20}`);\n\n const res = await client.invoke(\n 'feishu_chat_members.default',\n (sdk, opts) =>\n sdk.im.v1.chatMembers.get(\n {\n path: { chat_id: p.chat_id },\n params: {\n member_id_type: p.member_id_type || 'open_id',\n page_size: p.page_size,\n page_token: p.page_token,\n },\n },\n {\n ...(opts ?? {}),\n headers: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ...((opts as any)?.headers ?? {}),\n 'X-Chat-Custom-Header': 'enable_chat_list_security_check',\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any,\n ),\n { as: 'user' },\n );\n assertLarkOk(res);\n\n const data = res.data as ChatMemberListData | undefined;\n const memberCount = data?.items?.length ?? 0;\n const memberTotal = data?.member_total ?? 0;\n log.info(`chat_members: found ${memberCount} members (total: ${memberTotal})`);\n\n return json({\n items: data?.items,\n has_more: data?.has_more ?? false,\n page_token: data?.page_token,\n member_total: memberTotal,\n });\n } catch (err) {\n return await handleInvokeErrorWithAutoAuth(err, cfg);\n }\n },\n },\n { name: 'feishu_chat_members' },\n );\n\n api.logger.info?.('feishu_chat_members: Registered feishu_chat_members tool');\n}\n"],
|
|
5
|
+
"mappings": "AAWA,SAAS,YAAY;AACrB,SAAS,MAAM,mBAAmB,cAAc,qCAAqC;AAOrF,MAAM,oBAAoB,KAAK,OAAO;AAAA,EACpC,SAAS,KAAK,OAAO;AAAA,IACnB,aAAa;AAAA,EACf,CAAC;AAAA,EACD,gBAAgB,KAAK;AAAA,IACnB,KAAK,MAAM,CAAC,KAAK,QAAQ,SAAS,GAAG,KAAK,QAAQ,UAAU,GAAG,KAAK,QAAQ,SAAS,CAAC,CAAC;AAAA,EACzF;AAAA,EACA,WAAW,KAAK;AAAA,IACd,KAAK,QAAQ;AAAA,MACX,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA,EACA,YAAY,KAAK;AAAA,IACf,KAAK,OAAO;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AACF,CAAC;AAiBM,SAAS,wBAAwB,KAAwB;AAC9D,MAAI,CAAC,IAAI,OAAQ;AACjB,QAAM,MAAM,IAAI;AAEhB,QAAM,EAAE,YAAY,IAAI,IAAI,kBAAkB,KAAK,qBAAqB;AAExE,MAAI;AAAA,IACF;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aACE;AAAA,MAGF,YAAY;AAAA,MACZ,MAAM,QAAQ,aAAqB,QAAiB;AAClD,cAAM,IAAI;AACV,YAAI;AACF,gBAAM,SAAS,WAAW;AAE1B,cAAI,KAAK,0BAA0B,EAAE,OAAO,gBAAgB,EAAE,aAAa,EAAE,EAAE;AAE/E,gBAAM,MAAM,MAAM,OAAO;AAAA,YACvB;AAAA,YACA,CAAC,KAAK,SACJ,IAAI,GAAG,GAAG,YAAY;AAAA,cACpB;AAAA,gBACE,MAAM,EAAE,SAAS,EAAE,QAAQ;AAAA,gBAC3B,QAAQ;AAAA,kBACN,gBAAgB,EAAE,kBAAkB;AAAA,kBACpC,WAAW,EAAE;AAAA,kBACb,YAAY,EAAE;AAAA,gBAChB;AAAA,cACF;AAAA,cACA;AAAA,gBACE,GAAI,QAAQ,CAAC;AAAA,gBACb,SAAS;AAAA;AAAA,kBAEP,GAAK,MAAc,WAAW,CAAC;AAAA,kBAC/B,wBAAwB;AAAA,gBAC1B;AAAA;AAAA,cAEF;AAAA,YACF;AAAA,YACF,EAAE,IAAI,OAAO;AAAA,UACf;AACA,uBAAa,GAAG;AAEhB,gBAAM,OAAO,IAAI;AACjB,gBAAM,cAAc,MAAM,OAAO,UAAU;AAC3C,gBAAM,cAAc,MAAM,gBAAgB;AAC1C,cAAI,KAAK,uBAAuB,WAAW,oBAAoB,WAAW,GAAG;AAE7E,iBAAO,KAAK;AAAA,YACV,OAAO,MAAM;AAAA,YACb,UAAU,MAAM,YAAY;AAAA,YAC5B,YAAY,MAAM;AAAA,YAClB,cAAc;AAAA,UAChB,CAAC;AAAA,QACH,SAAS,KAAK;AACZ,iBAAO,MAAM,8BAA8B,KAAK,GAAG;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AAAA,IACA,EAAE,MAAM,sBAAsB;AAAA,EAChC;AAEA,MAAI,OAAO,OAAO,0DAA0D;AAC9E;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|