@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,285 @@
|
|
|
1
|
+
import { DEFAULT_ACCOUNT_ID, formatDocsLink } from "openclaw/plugin-sdk";
|
|
2
|
+
import { getLarkCredentials } from "../core/accounts";
|
|
3
|
+
import { probeFeishu } from "./probe";
|
|
4
|
+
import {
|
|
5
|
+
setFeishuDmPolicy,
|
|
6
|
+
setFeishuAllowFrom,
|
|
7
|
+
setFeishuGroupPolicy,
|
|
8
|
+
setFeishuGroupAllowFrom,
|
|
9
|
+
parseAllowFromInput
|
|
10
|
+
} from "./onboarding-config";
|
|
11
|
+
import { migrateLegacyGroupAllowFrom } from "./onboarding-migrate";
|
|
12
|
+
const channel = "feishu";
|
|
13
|
+
async function noteFeishuCredentialHelp(prompter) {
|
|
14
|
+
await prompter.note(
|
|
15
|
+
[
|
|
16
|
+
"1) Go to Feishu Open Platform (open.feishu.cn)",
|
|
17
|
+
"2) Create a self-built app",
|
|
18
|
+
"3) Get App ID and App Secret from Credentials page",
|
|
19
|
+
"4) Enable required permissions: im:message, im:chat, contact:user.base:readonly",
|
|
20
|
+
"5) Publish the app or add it to a test group",
|
|
21
|
+
"Tip: you can also set FEISHU_APP_ID / FEISHU_APP_SECRET env vars.",
|
|
22
|
+
`Docs: ${formatDocsLink("/channels/feishu", "feishu")}`
|
|
23
|
+
].join("\n"),
|
|
24
|
+
"Feishu credentials"
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
async function promptFeishuAllowFrom(params) {
|
|
28
|
+
const existing = params.cfg.channels?.feishu?.allowFrom ?? [];
|
|
29
|
+
await params.prompter.note(
|
|
30
|
+
[
|
|
31
|
+
"Allowlist Feishu DMs by open_id or user_id.",
|
|
32
|
+
"You can find user open_id in Feishu admin console or via API.",
|
|
33
|
+
"Examples:",
|
|
34
|
+
"- ou_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
|
35
|
+
"- on_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
36
|
+
].join("\n"),
|
|
37
|
+
"Feishu allowlist"
|
|
38
|
+
);
|
|
39
|
+
while (true) {
|
|
40
|
+
const entry = await params.prompter.text({
|
|
41
|
+
message: "Feishu allowFrom (user open_ids)",
|
|
42
|
+
placeholder: "ou_xxxxx, ou_yyyyy",
|
|
43
|
+
initialValue: existing[0] ? String(existing[0]) : void 0,
|
|
44
|
+
validate: (value) => String(value ?? "").trim() ? void 0 : "Required"
|
|
45
|
+
});
|
|
46
|
+
const parts = parseAllowFromInput(String(entry));
|
|
47
|
+
if (parts.length === 0) {
|
|
48
|
+
await params.prompter.note("Enter at least one user.", "Feishu allowlist");
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const unique = [.../* @__PURE__ */ new Set([...existing.map((v) => String(v).trim()).filter(Boolean), ...parts])];
|
|
52
|
+
return setFeishuAllowFrom(params.cfg, unique);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function acquireCredentials(params) {
|
|
56
|
+
const { prompter, feishuCfg } = params;
|
|
57
|
+
let next = params.cfg;
|
|
58
|
+
const hasConfigCreds = Boolean(feishuCfg?.appId?.trim() && feishuCfg?.appSecret?.trim());
|
|
59
|
+
const canUseEnv = Boolean(
|
|
60
|
+
!hasConfigCreds && process.env.FEISHU_APP_ID?.trim() && process.env.FEISHU_APP_SECRET?.trim()
|
|
61
|
+
);
|
|
62
|
+
let appId = null;
|
|
63
|
+
let appSecret = null;
|
|
64
|
+
if (canUseEnv) {
|
|
65
|
+
const keepEnv = await prompter.confirm({
|
|
66
|
+
message: "FEISHU_APP_ID + FEISHU_APP_SECRET detected. Use env vars?",
|
|
67
|
+
initialValue: true
|
|
68
|
+
});
|
|
69
|
+
if (keepEnv) {
|
|
70
|
+
next = {
|
|
71
|
+
...next,
|
|
72
|
+
channels: {
|
|
73
|
+
...next.channels,
|
|
74
|
+
feishu: { ...next.channels?.feishu, enabled: true }
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
} else {
|
|
78
|
+
appId = String(
|
|
79
|
+
await prompter.text({
|
|
80
|
+
message: "Enter Feishu App ID",
|
|
81
|
+
validate: (value) => value?.trim() ? void 0 : "Required"
|
|
82
|
+
})
|
|
83
|
+
).trim();
|
|
84
|
+
appSecret = String(
|
|
85
|
+
await prompter.text({
|
|
86
|
+
message: "Enter Feishu App Secret",
|
|
87
|
+
validate: (value) => value?.trim() ? void 0 : "Required"
|
|
88
|
+
})
|
|
89
|
+
).trim();
|
|
90
|
+
}
|
|
91
|
+
} else if (hasConfigCreds) {
|
|
92
|
+
const keep = await prompter.confirm({
|
|
93
|
+
message: "Feishu credentials already configured. Keep them?",
|
|
94
|
+
initialValue: true
|
|
95
|
+
});
|
|
96
|
+
if (!keep) {
|
|
97
|
+
appId = String(
|
|
98
|
+
await prompter.text({
|
|
99
|
+
message: "Enter Feishu App ID",
|
|
100
|
+
validate: (value) => value?.trim() ? void 0 : "Required"
|
|
101
|
+
})
|
|
102
|
+
).trim();
|
|
103
|
+
appSecret = String(
|
|
104
|
+
await prompter.text({
|
|
105
|
+
message: "Enter Feishu App Secret",
|
|
106
|
+
validate: (value) => value?.trim() ? void 0 : "Required"
|
|
107
|
+
})
|
|
108
|
+
).trim();
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
appId = String(
|
|
112
|
+
await prompter.text({
|
|
113
|
+
message: "Enter Feishu App ID",
|
|
114
|
+
validate: (value) => value?.trim() ? void 0 : "Required"
|
|
115
|
+
})
|
|
116
|
+
).trim();
|
|
117
|
+
appSecret = String(
|
|
118
|
+
await prompter.text({
|
|
119
|
+
message: "Enter Feishu App Secret",
|
|
120
|
+
validate: (value) => value?.trim() ? void 0 : "Required"
|
|
121
|
+
})
|
|
122
|
+
).trim();
|
|
123
|
+
}
|
|
124
|
+
return { cfg: next, appId, appSecret };
|
|
125
|
+
}
|
|
126
|
+
const dmPolicy = {
|
|
127
|
+
label: "Feishu",
|
|
128
|
+
channel,
|
|
129
|
+
policyKey: "channels.feishu.dmPolicy",
|
|
130
|
+
allowFromKey: "channels.feishu.allowFrom",
|
|
131
|
+
getCurrent: (cfg) => cfg.channels?.feishu?.dmPolicy ?? "pairing",
|
|
132
|
+
setPolicy: (cfg, policy) => setFeishuDmPolicy(cfg, policy),
|
|
133
|
+
promptAllowFrom: promptFeishuAllowFrom
|
|
134
|
+
};
|
|
135
|
+
const feishuOnboardingAdapter = {
|
|
136
|
+
channel,
|
|
137
|
+
// -----------------------------------------------------------------------
|
|
138
|
+
// getStatus
|
|
139
|
+
// -----------------------------------------------------------------------
|
|
140
|
+
getStatus: async ({ cfg }) => {
|
|
141
|
+
const feishuCfg = cfg.channels?.feishu;
|
|
142
|
+
const configured = Boolean(getLarkCredentials(feishuCfg));
|
|
143
|
+
let probeResult = null;
|
|
144
|
+
if (configured && feishuCfg) {
|
|
145
|
+
try {
|
|
146
|
+
probeResult = await probeFeishu(feishuCfg);
|
|
147
|
+
} catch {
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const statusLines = [];
|
|
151
|
+
if (!configured) {
|
|
152
|
+
statusLines.push("Feishu: needs app credentials");
|
|
153
|
+
} else if (probeResult?.ok) {
|
|
154
|
+
statusLines.push(`Feishu: connected as ${probeResult.botName ?? probeResult.botOpenId ?? "bot"}`);
|
|
155
|
+
} else {
|
|
156
|
+
statusLines.push("Feishu: configured (connection not verified)");
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
channel,
|
|
160
|
+
configured,
|
|
161
|
+
statusLines,
|
|
162
|
+
selectionHint: configured ? "configured" : "needs app creds",
|
|
163
|
+
quickstartScore: configured ? 2 : 0
|
|
164
|
+
};
|
|
165
|
+
},
|
|
166
|
+
// -----------------------------------------------------------------------
|
|
167
|
+
// configure
|
|
168
|
+
// -----------------------------------------------------------------------
|
|
169
|
+
configure: async ({ cfg, prompter }) => {
|
|
170
|
+
const feishuCfg = cfg.channels?.feishu;
|
|
171
|
+
const resolved = getLarkCredentials(feishuCfg);
|
|
172
|
+
let next = cfg;
|
|
173
|
+
if (!resolved) {
|
|
174
|
+
await noteFeishuCredentialHelp(prompter);
|
|
175
|
+
}
|
|
176
|
+
const creds = await acquireCredentials({ cfg: next, prompter, feishuCfg });
|
|
177
|
+
next = creds.cfg;
|
|
178
|
+
if (creds.appId && creds.appSecret) {
|
|
179
|
+
next = {
|
|
180
|
+
...next,
|
|
181
|
+
channels: {
|
|
182
|
+
...next.channels,
|
|
183
|
+
feishu: {
|
|
184
|
+
...next.channels?.feishu,
|
|
185
|
+
enabled: true,
|
|
186
|
+
appId: creds.appId,
|
|
187
|
+
appSecret: creds.appSecret
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
const testCfg = next.channels?.feishu;
|
|
192
|
+
try {
|
|
193
|
+
const probe = await probeFeishu(testCfg);
|
|
194
|
+
if (probe.ok) {
|
|
195
|
+
await prompter.note(`Connected as ${probe.botName ?? probe.botOpenId ?? "bot"}`, "Feishu connection test");
|
|
196
|
+
} else {
|
|
197
|
+
await prompter.note(`Connection failed: ${probe.error ?? "unknown error"}`, "Feishu connection test");
|
|
198
|
+
}
|
|
199
|
+
} catch (err) {
|
|
200
|
+
await prompter.note(`Connection test failed: ${String(err)}`, "Feishu connection test");
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const currentDomain = next.channels?.feishu?.domain ?? "feishu";
|
|
204
|
+
const domain = await prompter.select({
|
|
205
|
+
message: "Which Feishu domain?",
|
|
206
|
+
options: [
|
|
207
|
+
{ value: "feishu", label: "Feishu (feishu.cn) - China" },
|
|
208
|
+
{ value: "lark", label: "Lark (larksuite.com) - International" }
|
|
209
|
+
],
|
|
210
|
+
initialValue: currentDomain
|
|
211
|
+
});
|
|
212
|
+
if (domain) {
|
|
213
|
+
next = {
|
|
214
|
+
...next,
|
|
215
|
+
channels: {
|
|
216
|
+
...next.channels,
|
|
217
|
+
feishu: {
|
|
218
|
+
...next.channels?.feishu,
|
|
219
|
+
domain
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
next = await migrateLegacyGroupAllowFrom({ cfg: next, prompter });
|
|
225
|
+
const groupPolicy = await prompter.select({
|
|
226
|
+
message: "Group chat policy \u2014 which groups can interact with the bot?",
|
|
227
|
+
options: [
|
|
228
|
+
{
|
|
229
|
+
value: "allowlist",
|
|
230
|
+
label: "Allowlist \u2014 only groups listed in `groups` config (default)"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
value: "open",
|
|
234
|
+
label: "Open \u2014 any group (requires @mention)"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
value: "disabled",
|
|
238
|
+
label: "Disabled \u2014 no group interactions"
|
|
239
|
+
}
|
|
240
|
+
],
|
|
241
|
+
initialValue: next.channels?.feishu?.groupPolicy ?? "allowlist"
|
|
242
|
+
});
|
|
243
|
+
if (groupPolicy) {
|
|
244
|
+
next = setFeishuGroupPolicy(next, groupPolicy);
|
|
245
|
+
}
|
|
246
|
+
if (groupPolicy !== "disabled") {
|
|
247
|
+
const existing = next.channels?.feishu?.groupAllowFrom ?? [];
|
|
248
|
+
const entry = await prompter.text({
|
|
249
|
+
message: "Group sender allowlist \u2014 which users can trigger the bot in allowed groups? (user open_ids)",
|
|
250
|
+
placeholder: "ou_xxxxx, ou_yyyyy",
|
|
251
|
+
initialValue: existing.length > 0 ? existing.map(String).join(", ") : void 0
|
|
252
|
+
});
|
|
253
|
+
if (entry) {
|
|
254
|
+
const parts = parseAllowFromInput(String(entry));
|
|
255
|
+
if (parts.length > 0) {
|
|
256
|
+
next = setFeishuGroupAllowFrom(next, parts);
|
|
257
|
+
}
|
|
258
|
+
} else if (groupPolicy === "allowlist") {
|
|
259
|
+
await prompter.note(
|
|
260
|
+
"Empty sender list + allowlist = nobody can trigger. Use groupPolicy 'open' if you want anyone in allowed groups to trigger.",
|
|
261
|
+
"Note"
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return { cfg: next, accountId: DEFAULT_ACCOUNT_ID };
|
|
266
|
+
},
|
|
267
|
+
// -----------------------------------------------------------------------
|
|
268
|
+
// dmPolicy
|
|
269
|
+
// -----------------------------------------------------------------------
|
|
270
|
+
dmPolicy,
|
|
271
|
+
// -----------------------------------------------------------------------
|
|
272
|
+
// disable
|
|
273
|
+
// -----------------------------------------------------------------------
|
|
274
|
+
disable: (cfg) => ({
|
|
275
|
+
...cfg,
|
|
276
|
+
channels: {
|
|
277
|
+
...cfg.channels,
|
|
278
|
+
feishu: { ...cfg.channels?.feishu, enabled: false }
|
|
279
|
+
}
|
|
280
|
+
})
|
|
281
|
+
};
|
|
282
|
+
export {
|
|
283
|
+
feishuOnboardingAdapter
|
|
284
|
+
};
|
|
285
|
+
//# sourceMappingURL=onboarding.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/channel/onboarding.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * Onboarding wizard adapter for the Lark/Feishu channel plugin.\n *\n * Implements the ChannelOnboardingAdapter interface so the `openclaw\n * setup` wizard can configure Feishu credentials, domain, group\n * policies, and DM allowlists interactively.\n */\n\nimport type {\n ChannelOnboardingAdapter,\n ChannelOnboardingDmPolicy,\n ClawdbotConfig,\n WizardPrompter,\n} from 'openclaw/plugin-sdk';\nimport { DEFAULT_ACCOUNT_ID, formatDocsLink } from 'openclaw/plugin-sdk';\nimport type { FeishuConfig } from '../core/types';\nimport { getLarkCredentials } from '../core/accounts';\nimport { probeFeishu } from './probe';\nimport {\n setFeishuDmPolicy,\n setFeishuAllowFrom,\n setFeishuGroupPolicy,\n setFeishuGroupAllowFrom,\n parseAllowFromInput,\n} from './onboarding-config';\nimport { migrateLegacyGroupAllowFrom } from './onboarding-migrate';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst channel = 'feishu' as const;\n\n// ---------------------------------------------------------------------------\n// Prompter helpers\n// ---------------------------------------------------------------------------\n\nasync function noteFeishuCredentialHelp(prompter: WizardPrompter): Promise<void> {\n await prompter.note(\n [\n '1) Go to Feishu Open Platform (open.feishu.cn)',\n '2) Create a self-built app',\n '3) Get App ID and App Secret from Credentials page',\n '4) Enable required permissions: im:message, im:chat, contact:user.base:readonly',\n '5) Publish the app or add it to a test group',\n 'Tip: you can also set FEISHU_APP_ID / FEISHU_APP_SECRET env vars.',\n `Docs: ${formatDocsLink('/channels/feishu', 'feishu')}`,\n ].join('\\n'),\n 'Feishu credentials',\n );\n}\n\nasync function promptFeishuAllowFrom(params: {\n cfg: ClawdbotConfig;\n prompter: WizardPrompter;\n accountId?: string;\n}): Promise<ClawdbotConfig> {\n const existing = params.cfg.channels?.feishu?.allowFrom ?? [];\n\n await params.prompter.note(\n [\n 'Allowlist Feishu DMs by open_id or user_id.',\n 'You can find user open_id in Feishu admin console or via API.',\n 'Examples:',\n '- ou_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',\n '- on_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',\n ].join('\\n'),\n 'Feishu allowlist',\n );\n\n while (true) {\n const entry = await params.prompter.text({\n message: 'Feishu allowFrom (user open_ids)',\n placeholder: 'ou_xxxxx, ou_yyyyy',\n initialValue: existing[0] ? String(existing[0]) : undefined,\n validate: (value) => (String(value ?? '').trim() ? undefined : 'Required'),\n });\n\n const parts = parseAllowFromInput(String(entry));\n if (parts.length === 0) {\n await params.prompter.note('Enter at least one user.', 'Feishu allowlist');\n continue;\n }\n\n const unique = [...new Set([...existing.map((v: string | number) => String(v).trim()).filter(Boolean), ...parts])];\n return setFeishuAllowFrom(params.cfg, unique);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Credential acquisition\n// ---------------------------------------------------------------------------\n\nasync function acquireCredentials(params: {\n cfg: ClawdbotConfig;\n prompter: WizardPrompter;\n feishuCfg: FeishuConfig | undefined;\n}): Promise<{ cfg: ClawdbotConfig; appId: string | null; appSecret: string | null }> {\n const { prompter, feishuCfg } = params;\n let next = params.cfg;\n\n const hasConfigCreds = Boolean(feishuCfg?.appId?.trim() && feishuCfg?.appSecret?.trim());\n const canUseEnv = Boolean(\n !hasConfigCreds && process.env.FEISHU_APP_ID?.trim() && process.env.FEISHU_APP_SECRET?.trim(),\n );\n\n let appId: string | null = null;\n let appSecret: string | null = null;\n\n if (canUseEnv) {\n const keepEnv = await prompter.confirm({\n message: 'FEISHU_APP_ID + FEISHU_APP_SECRET detected. Use env vars?',\n initialValue: true,\n });\n if (keepEnv) {\n next = {\n ...next,\n channels: {\n ...next.channels,\n feishu: { ...next.channels?.feishu, enabled: true },\n },\n };\n } else {\n appId = String(\n await prompter.text({\n message: 'Enter Feishu App ID',\n validate: (value) => (value?.trim() ? undefined : 'Required'),\n }),\n ).trim();\n appSecret = String(\n await prompter.text({\n message: 'Enter Feishu App Secret',\n validate: (value) => (value?.trim() ? undefined : 'Required'),\n }),\n ).trim();\n }\n } else if (hasConfigCreds) {\n const keep = await prompter.confirm({\n message: 'Feishu credentials already configured. Keep them?',\n initialValue: true,\n });\n if (!keep) {\n appId = String(\n await prompter.text({\n message: 'Enter Feishu App ID',\n validate: (value) => (value?.trim() ? undefined : 'Required'),\n }),\n ).trim();\n appSecret = String(\n await prompter.text({\n message: 'Enter Feishu App Secret',\n validate: (value) => (value?.trim() ? undefined : 'Required'),\n }),\n ).trim();\n }\n } else {\n appId = String(\n await prompter.text({\n message: 'Enter Feishu App ID',\n validate: (value) => (value?.trim() ? undefined : 'Required'),\n }),\n ).trim();\n appSecret = String(\n await prompter.text({\n message: 'Enter Feishu App Secret',\n validate: (value) => (value?.trim() ? undefined : 'Required'),\n }),\n ).trim();\n }\n\n return { cfg: next, appId, appSecret };\n}\n\n// ---------------------------------------------------------------------------\n// DM policy\n// ---------------------------------------------------------------------------\n\nconst dmPolicy: ChannelOnboardingDmPolicy = {\n label: 'Feishu',\n channel,\n policyKey: 'channels.feishu.dmPolicy',\n allowFromKey: 'channels.feishu.allowFrom',\n getCurrent: (cfg) => (cfg.channels?.feishu as FeishuConfig | undefined)?.dmPolicy ?? 'pairing',\n setPolicy: (cfg, policy) => setFeishuDmPolicy(cfg, policy),\n promptAllowFrom: promptFeishuAllowFrom,\n};\n\n// ---------------------------------------------------------------------------\n// Adapter\n// ---------------------------------------------------------------------------\n\nexport const feishuOnboardingAdapter: ChannelOnboardingAdapter = {\n channel,\n\n // -----------------------------------------------------------------------\n // getStatus\n // -----------------------------------------------------------------------\n getStatus: async ({ cfg }) => {\n const feishuCfg = cfg.channels?.feishu as FeishuConfig | undefined;\n const configured = Boolean(getLarkCredentials(feishuCfg));\n\n // Attempt a live probe when credentials are present.\n let probeResult = null;\n if (configured && feishuCfg) {\n try {\n probeResult = await probeFeishu(feishuCfg);\n } catch {\n // Ignore probe errors -- status degrades gracefully.\n }\n }\n\n const statusLines: string[] = [];\n if (!configured) {\n statusLines.push('Feishu: needs app credentials');\n } else if (probeResult?.ok) {\n statusLines.push(`Feishu: connected as ${probeResult.botName ?? probeResult.botOpenId ?? 'bot'}`);\n } else {\n statusLines.push('Feishu: configured (connection not verified)');\n }\n\n return {\n channel,\n configured,\n statusLines,\n selectionHint: configured ? 'configured' : 'needs app creds',\n quickstartScore: configured ? 2 : 0,\n };\n },\n\n // -----------------------------------------------------------------------\n // configure\n // -----------------------------------------------------------------------\n configure: async ({ cfg, prompter }) => {\n const feishuCfg = cfg.channels?.feishu as FeishuConfig | undefined;\n const resolved = getLarkCredentials(feishuCfg);\n\n let next = cfg;\n\n // Show credential help if nothing is configured yet.\n if (!resolved) {\n await noteFeishuCredentialHelp(prompter);\n }\n\n // --- Credential acquisition ---\n const creds = await acquireCredentials({ cfg: next, prompter, feishuCfg });\n next = creds.cfg;\n\n // --- Persist and test credentials ---\n if (creds.appId && creds.appSecret) {\n next = {\n ...next,\n channels: {\n ...next.channels,\n feishu: {\n ...next.channels?.feishu,\n enabled: true,\n appId: creds.appId,\n appSecret: creds.appSecret,\n },\n },\n };\n\n const testCfg = next.channels?.feishu as FeishuConfig;\n try {\n const probe = await probeFeishu(testCfg);\n if (probe.ok) {\n await prompter.note(`Connected as ${probe.botName ?? probe.botOpenId ?? 'bot'}`, 'Feishu connection test');\n } else {\n await prompter.note(`Connection failed: ${probe.error ?? 'unknown error'}`, 'Feishu connection test');\n }\n } catch (err) {\n await prompter.note(`Connection test failed: ${String(err)}`, 'Feishu connection test');\n }\n }\n\n // --- Domain selection ---\n const currentDomain = (next.channels?.feishu as FeishuConfig | undefined)?.domain ?? 'feishu';\n const domain = await prompter.select({\n message: 'Which Feishu domain?',\n options: [\n { value: 'feishu', label: 'Feishu (feishu.cn) - China' },\n { value: 'lark', label: 'Lark (larksuite.com) - International' },\n ],\n initialValue: currentDomain,\n });\n if (domain) {\n next = {\n ...next,\n channels: {\n ...next.channels,\n feishu: {\n ...next.channels?.feishu,\n domain: domain as 'feishu' | 'lark',\n },\n },\n };\n }\n\n // --- Legacy migration ---\n next = await migrateLegacyGroupAllowFrom({ cfg: next, prompter });\n\n // --- Group policy ---\n const groupPolicy = await prompter.select({\n message: 'Group chat policy \u2014 which groups can interact with the bot?',\n options: [\n {\n value: 'allowlist',\n label: 'Allowlist \u2014 only groups listed in `groups` config (default)',\n },\n {\n value: 'open',\n label: 'Open \u2014 any group (requires @mention)',\n },\n {\n value: 'disabled',\n label: 'Disabled \u2014 no group interactions',\n },\n ],\n initialValue: (next.channels?.feishu as FeishuConfig | undefined)?.groupPolicy ?? 'allowlist',\n });\n if (groupPolicy) {\n next = setFeishuGroupPolicy(next, groupPolicy as 'open' | 'allowlist' | 'disabled');\n }\n\n // --- Group sender allowlist ---\n if (groupPolicy !== 'disabled') {\n const existing = (next.channels?.feishu as FeishuConfig | undefined)?.groupAllowFrom ?? [];\n const entry = await prompter.text({\n message: 'Group sender allowlist \u2014 which users can trigger the bot in allowed groups? (user open_ids)',\n placeholder: 'ou_xxxxx, ou_yyyyy',\n initialValue: existing.length > 0 ? existing.map(String).join(', ') : undefined,\n });\n if (entry) {\n const parts = parseAllowFromInput(String(entry));\n if (parts.length > 0) {\n next = setFeishuGroupAllowFrom(next, parts);\n }\n } else if (groupPolicy === 'allowlist') {\n await prompter.note(\n 'Empty sender list + allowlist = nobody can trigger. ' +\n \"Use groupPolicy 'open' if you want anyone in allowed groups to trigger.\",\n 'Note',\n );\n }\n }\n\n return { cfg: next, accountId: DEFAULT_ACCOUNT_ID };\n },\n\n // -----------------------------------------------------------------------\n // dmPolicy\n // -----------------------------------------------------------------------\n dmPolicy,\n\n // -----------------------------------------------------------------------\n // disable\n // -----------------------------------------------------------------------\n disable: (cfg) => ({\n ...cfg,\n channels: {\n ...cfg.channels,\n feishu: { ...cfg.channels?.feishu, enabled: false },\n },\n }),\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk";
|
|
2
|
+
import { getLarkAccount, getLarkAccountIds, getDefaultLarkAccountId } from "../core/accounts";
|
|
3
|
+
import {
|
|
4
|
+
listFeishuDirectoryPeers,
|
|
5
|
+
listFeishuDirectoryGroups,
|
|
6
|
+
listFeishuDirectoryPeersLive,
|
|
7
|
+
listFeishuDirectoryGroupsLive
|
|
8
|
+
} from "./directory";
|
|
9
|
+
import { feishuOnboardingAdapter } from "./onboarding";
|
|
10
|
+
import { feishuOutbound } from "../messaging/outbound/outbound";
|
|
11
|
+
import { feishuMessageActions } from "../messaging/outbound/actions";
|
|
12
|
+
import { resolveFeishuGroupToolPolicy } from "../messaging/inbound/policy";
|
|
13
|
+
import { LarkClient } from "../core/lark-client";
|
|
14
|
+
import { sendMessageFeishu } from "../messaging/outbound/send";
|
|
15
|
+
import { normalizeFeishuTarget, looksLikeFeishuId } from "../core/targets";
|
|
16
|
+
import { triggerOnboarding } from "../tools/onboarding-auth";
|
|
17
|
+
import { setAccountEnabled, applyAccountConfig, deleteAccount, collectFeishuSecurityWarnings } from "./config-adapter";
|
|
18
|
+
import { larkLogger } from "../core/lark-logger";
|
|
19
|
+
import { FEISHU_CONFIG_JSON_SCHEMA } from "../core/config-schema";
|
|
20
|
+
const pluginLog = larkLogger("channel/plugin");
|
|
21
|
+
const PROBE_CACHE_TTL_MS = 10 * 60 * 1e3;
|
|
22
|
+
function adaptDirectoryParams(params) {
|
|
23
|
+
return {
|
|
24
|
+
cfg: params.cfg,
|
|
25
|
+
query: params.query ?? void 0,
|
|
26
|
+
limit: params.limit ?? void 0,
|
|
27
|
+
accountId: params.accountId ?? void 0
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const meta = {
|
|
31
|
+
id: "feishu",
|
|
32
|
+
label: "Feishu",
|
|
33
|
+
selectionLabel: "Lark/Feishu (\u98DE\u4E66)",
|
|
34
|
+
docsPath: "/channels/feishu",
|
|
35
|
+
docsLabel: "feishu",
|
|
36
|
+
blurb: "\u98DE\u4E66/Lark enterprise messaging.",
|
|
37
|
+
aliases: ["lark"],
|
|
38
|
+
order: 70
|
|
39
|
+
};
|
|
40
|
+
const feishuPlugin = {
|
|
41
|
+
id: "feishu",
|
|
42
|
+
meta: {
|
|
43
|
+
...meta
|
|
44
|
+
},
|
|
45
|
+
// -------------------------------------------------------------------------
|
|
46
|
+
// Pairing
|
|
47
|
+
// -------------------------------------------------------------------------
|
|
48
|
+
pairing: {
|
|
49
|
+
idLabel: "feishuUserId",
|
|
50
|
+
normalizeAllowEntry: (entry) => entry.replace(/^(feishu|user|open_id):/i, ""),
|
|
51
|
+
notifyApproval: async ({ cfg, id }) => {
|
|
52
|
+
const accountId = getDefaultLarkAccountId(cfg);
|
|
53
|
+
pluginLog.info("notifyApproval called", { id, accountId });
|
|
54
|
+
await sendMessageFeishu({
|
|
55
|
+
cfg,
|
|
56
|
+
to: id,
|
|
57
|
+
text: PAIRING_APPROVED_MESSAGE,
|
|
58
|
+
accountId
|
|
59
|
+
});
|
|
60
|
+
try {
|
|
61
|
+
await triggerOnboarding({ cfg, userOpenId: id, accountId });
|
|
62
|
+
pluginLog.info("onboarding completed", { id });
|
|
63
|
+
} catch (err) {
|
|
64
|
+
pluginLog.warn("onboarding failed", { id, error: String(err) });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
// -------------------------------------------------------------------------
|
|
69
|
+
// Capabilities
|
|
70
|
+
// -------------------------------------------------------------------------
|
|
71
|
+
capabilities: {
|
|
72
|
+
chatTypes: ["direct", "group"],
|
|
73
|
+
media: true,
|
|
74
|
+
reactions: true,
|
|
75
|
+
threads: true,
|
|
76
|
+
polls: false,
|
|
77
|
+
nativeCommands: true,
|
|
78
|
+
blockStreaming: true
|
|
79
|
+
},
|
|
80
|
+
// -------------------------------------------------------------------------
|
|
81
|
+
// Agent prompt
|
|
82
|
+
// -------------------------------------------------------------------------
|
|
83
|
+
agentPrompt: {
|
|
84
|
+
messageToolHints: () => [
|
|
85
|
+
"- Feishu targeting: omit `target` to reply to the current conversation (auto-inferred). Explicit targets: `user:open_id` or `chat:chat_id`.",
|
|
86
|
+
"- Feishu supports interactive cards for rich messages.",
|
|
87
|
+
"- Feishu reactions use UPPERCASE emoji type names (e.g. `OK`,`THUMBSUP`,`THANKS`,`MUSCLE`,`FINGERHEART`,`APPLAUSE`,`FISTBUMP`,`JIAYI`,`DONE`,`SMILE`,`BLUSH` ), not Unicode emoji characters.",
|
|
88
|
+
"- Feishu `action=delete`/`action=unsend` only deletes messages sent by the bot. When the user quotes a message and says 'delete this', use the **quoted message's** message_id, not the user's own message_id."
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
// -------------------------------------------------------------------------
|
|
92
|
+
// Groups
|
|
93
|
+
// -------------------------------------------------------------------------
|
|
94
|
+
groups: {
|
|
95
|
+
resolveToolPolicy: resolveFeishuGroupToolPolicy
|
|
96
|
+
},
|
|
97
|
+
// -------------------------------------------------------------------------
|
|
98
|
+
// Reload
|
|
99
|
+
// -------------------------------------------------------------------------
|
|
100
|
+
reload: { configPrefixes: ["channels.feishu"] },
|
|
101
|
+
// -------------------------------------------------------------------------
|
|
102
|
+
// Config schema (JSON Schema)
|
|
103
|
+
// -------------------------------------------------------------------------
|
|
104
|
+
configSchema: {
|
|
105
|
+
schema: FEISHU_CONFIG_JSON_SCHEMA
|
|
106
|
+
},
|
|
107
|
+
// -------------------------------------------------------------------------
|
|
108
|
+
// Config adapter
|
|
109
|
+
// -------------------------------------------------------------------------
|
|
110
|
+
config: {
|
|
111
|
+
listAccountIds: (cfg) => getLarkAccountIds(cfg),
|
|
112
|
+
resolveAccount: (cfg, accountId) => getLarkAccount(cfg, accountId),
|
|
113
|
+
defaultAccountId: (cfg) => getDefaultLarkAccountId(cfg),
|
|
114
|
+
setAccountEnabled: ({ cfg, accountId, enabled }) => {
|
|
115
|
+
return setAccountEnabled(cfg, accountId, enabled);
|
|
116
|
+
},
|
|
117
|
+
deleteAccount: ({ cfg, accountId }) => {
|
|
118
|
+
return deleteAccount(cfg, accountId);
|
|
119
|
+
},
|
|
120
|
+
isConfigured: (account) => account.configured,
|
|
121
|
+
describeAccount: (account) => ({
|
|
122
|
+
accountId: account.accountId,
|
|
123
|
+
enabled: account.enabled,
|
|
124
|
+
configured: account.configured,
|
|
125
|
+
name: account.name,
|
|
126
|
+
appId: account.appId,
|
|
127
|
+
brand: account.brand
|
|
128
|
+
}),
|
|
129
|
+
resolveAllowFrom: ({ cfg, accountId }) => {
|
|
130
|
+
const account = getLarkAccount(cfg, accountId);
|
|
131
|
+
return (account.config?.allowFrom ?? []).map((entry) => String(entry));
|
|
132
|
+
},
|
|
133
|
+
formatAllowFrom: ({ allowFrom }) => allowFrom.map((entry) => String(entry).trim()).filter(Boolean).map((entry) => entry.toLowerCase())
|
|
134
|
+
},
|
|
135
|
+
// -------------------------------------------------------------------------
|
|
136
|
+
// Security
|
|
137
|
+
// -------------------------------------------------------------------------
|
|
138
|
+
security: {
|
|
139
|
+
collectWarnings: ({ cfg, accountId }) => collectFeishuSecurityWarnings({ cfg, accountId: accountId ?? DEFAULT_ACCOUNT_ID })
|
|
140
|
+
},
|
|
141
|
+
// -------------------------------------------------------------------------
|
|
142
|
+
// Setup
|
|
143
|
+
// -------------------------------------------------------------------------
|
|
144
|
+
setup: {
|
|
145
|
+
resolveAccountId: () => DEFAULT_ACCOUNT_ID,
|
|
146
|
+
applyAccountConfig: ({ cfg, accountId }) => {
|
|
147
|
+
return applyAccountConfig(cfg, accountId, { enabled: true });
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
// -------------------------------------------------------------------------
|
|
151
|
+
// Onboarding
|
|
152
|
+
// -------------------------------------------------------------------------
|
|
153
|
+
onboarding: feishuOnboardingAdapter,
|
|
154
|
+
// -------------------------------------------------------------------------
|
|
155
|
+
// Messaging
|
|
156
|
+
// -------------------------------------------------------------------------
|
|
157
|
+
messaging: {
|
|
158
|
+
normalizeTarget: (raw) => normalizeFeishuTarget(raw) ?? void 0,
|
|
159
|
+
targetResolver: {
|
|
160
|
+
looksLikeId: looksLikeFeishuId,
|
|
161
|
+
hint: "<chatId|user:openId|chat:chatId>"
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
// -------------------------------------------------------------------------
|
|
165
|
+
// Directory
|
|
166
|
+
// -------------------------------------------------------------------------
|
|
167
|
+
directory: {
|
|
168
|
+
self: async () => null,
|
|
169
|
+
listPeers: async (p) => listFeishuDirectoryPeers(adaptDirectoryParams(p)),
|
|
170
|
+
listGroups: async (p) => listFeishuDirectoryGroups(adaptDirectoryParams(p)),
|
|
171
|
+
listPeersLive: async (p) => listFeishuDirectoryPeersLive(adaptDirectoryParams(p)),
|
|
172
|
+
listGroupsLive: async (p) => listFeishuDirectoryGroupsLive(adaptDirectoryParams(p))
|
|
173
|
+
},
|
|
174
|
+
// -------------------------------------------------------------------------
|
|
175
|
+
// Outbound
|
|
176
|
+
// -------------------------------------------------------------------------
|
|
177
|
+
outbound: feishuOutbound,
|
|
178
|
+
// -------------------------------------------------------------------------
|
|
179
|
+
// Threading
|
|
180
|
+
// -------------------------------------------------------------------------
|
|
181
|
+
threading: {
|
|
182
|
+
buildToolContext: ({ context, hasRepliedRef }) => ({
|
|
183
|
+
currentChannelId: normalizeFeishuTarget(context.To ?? "") ?? void 0,
|
|
184
|
+
currentThreadTs: context.MessageThreadId != null ? String(context.MessageThreadId) : void 0,
|
|
185
|
+
currentMessageId: context.CurrentMessageId,
|
|
186
|
+
hasRepliedRef
|
|
187
|
+
})
|
|
188
|
+
},
|
|
189
|
+
// -------------------------------------------------------------------------
|
|
190
|
+
// Actions
|
|
191
|
+
// -------------------------------------------------------------------------
|
|
192
|
+
actions: feishuMessageActions,
|
|
193
|
+
// -------------------------------------------------------------------------
|
|
194
|
+
// Status
|
|
195
|
+
// -------------------------------------------------------------------------
|
|
196
|
+
status: {
|
|
197
|
+
defaultRuntime: {
|
|
198
|
+
accountId: DEFAULT_ACCOUNT_ID,
|
|
199
|
+
running: false,
|
|
200
|
+
lastStartAt: null,
|
|
201
|
+
lastStopAt: null,
|
|
202
|
+
lastError: null,
|
|
203
|
+
port: null
|
|
204
|
+
},
|
|
205
|
+
buildChannelSummary: ({ snapshot }) => ({
|
|
206
|
+
configured: snapshot.configured ?? false,
|
|
207
|
+
running: snapshot.running ?? false,
|
|
208
|
+
lastStartAt: snapshot.lastStartAt ?? null,
|
|
209
|
+
lastStopAt: snapshot.lastStopAt ?? null,
|
|
210
|
+
lastError: snapshot.lastError ?? null,
|
|
211
|
+
port: snapshot.port ?? null,
|
|
212
|
+
probe: snapshot.probe,
|
|
213
|
+
lastProbeAt: snapshot.lastProbeAt ?? null
|
|
214
|
+
}),
|
|
215
|
+
probeAccount: async ({ account }) => {
|
|
216
|
+
return await LarkClient.fromAccount(account).probe({ maxAgeMs: PROBE_CACHE_TTL_MS });
|
|
217
|
+
},
|
|
218
|
+
buildAccountSnapshot: ({ account, runtime, probe }) => ({
|
|
219
|
+
accountId: account.accountId,
|
|
220
|
+
enabled: account.enabled,
|
|
221
|
+
configured: account.configured,
|
|
222
|
+
name: account.name,
|
|
223
|
+
appId: account.appId,
|
|
224
|
+
brand: account.brand,
|
|
225
|
+
running: runtime?.running ?? false,
|
|
226
|
+
lastStartAt: runtime?.lastStartAt ?? null,
|
|
227
|
+
lastStopAt: runtime?.lastStopAt ?? null,
|
|
228
|
+
lastError: runtime?.lastError ?? null,
|
|
229
|
+
port: runtime?.port ?? null,
|
|
230
|
+
probe
|
|
231
|
+
})
|
|
232
|
+
},
|
|
233
|
+
// -------------------------------------------------------------------------
|
|
234
|
+
// Gateway
|
|
235
|
+
// -------------------------------------------------------------------------
|
|
236
|
+
gateway: {
|
|
237
|
+
startAccount: async (ctx) => {
|
|
238
|
+
const { monitorFeishuProvider } = await import("./monitor.js");
|
|
239
|
+
const account = getLarkAccount(ctx.cfg, ctx.accountId);
|
|
240
|
+
const port = account.config?.webhookPort ?? null;
|
|
241
|
+
ctx.setStatus({ accountId: ctx.accountId, port });
|
|
242
|
+
ctx.log?.info(`starting feishu[${ctx.accountId}] (mode: ${account.config?.connectionMode ?? "websocket"})`);
|
|
243
|
+
return monitorFeishuProvider({
|
|
244
|
+
config: ctx.cfg,
|
|
245
|
+
runtime: ctx.runtime,
|
|
246
|
+
abortSignal: ctx.abortSignal,
|
|
247
|
+
accountId: ctx.accountId
|
|
248
|
+
});
|
|
249
|
+
},
|
|
250
|
+
stopAccount: async (ctx) => {
|
|
251
|
+
ctx.log?.info(`stopping feishu[${ctx.accountId}]`);
|
|
252
|
+
LarkClient.clearCache(ctx.accountId);
|
|
253
|
+
ctx.log?.info(`stopped feishu[${ctx.accountId}]`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
export {
|
|
258
|
+
feishuPlugin
|
|
259
|
+
};
|
|
260
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/channel/plugin.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * ChannelPlugin interface implementation for the Lark/Feishu channel.\n *\n * This is the top-level entry point that the OpenClaw plugin system uses to\n * discover capabilities, resolve accounts, obtain outbound adapters, and\n * start the inbound event gateway.\n */\n\nimport type { ChannelMeta, ChannelPlugin, ChannelThreadingToolContext, ClawdbotConfig } from 'openclaw/plugin-sdk';\nimport { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE } from 'openclaw/plugin-sdk';\nimport type { LarkAccount } from '../core/types';\nimport { getLarkAccount, getLarkAccountIds, getDefaultLarkAccountId } from '../core/accounts';\nimport {\n listFeishuDirectoryPeers,\n listFeishuDirectoryGroups,\n listFeishuDirectoryPeersLive,\n listFeishuDirectoryGroupsLive,\n} from './directory';\nimport { feishuOnboardingAdapter } from './onboarding';\nimport { feishuOutbound } from '../messaging/outbound/outbound';\nimport { feishuMessageActions } from '../messaging/outbound/actions';\nimport { resolveFeishuGroupToolPolicy } from '../messaging/inbound/policy';\nimport { LarkClient } from '../core/lark-client';\nimport { sendMessageFeishu } from '../messaging/outbound/send';\nimport { normalizeFeishuTarget, looksLikeFeishuId } from '../core/targets';\nimport { triggerOnboarding } from '../tools/onboarding-auth';\nimport { setAccountEnabled, applyAccountConfig, deleteAccount, collectFeishuSecurityWarnings } from './config-adapter';\nimport { larkLogger } from '../core/lark-logger';\nimport { FEISHU_CONFIG_JSON_SCHEMA } from '../core/config-schema';\n\nconst pluginLog = larkLogger('channel/plugin');\n\n/** \u72B6\u6001\u8F6E\u8BE2\u7684\u63A2\u9488\u7ED3\u679C\u7F13\u5B58\u65F6\u957F\uFF0810 \u5206\u949F\uFF09\u3002 */\nconst PROBE_CACHE_TTL_MS = 10 * 60 * 1000;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Convert nullable SDK params to optional params for directory functions. */\nfunction adaptDirectoryParams(params: {\n cfg: ClawdbotConfig;\n query?: string | null;\n limit?: number | null;\n accountId?: string | null;\n}): { cfg: ClawdbotConfig; query?: string; limit?: number; accountId?: string } {\n return {\n cfg: params.cfg,\n query: params.query ?? undefined,\n limit: params.limit ?? undefined,\n accountId: params.accountId ?? undefined,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Meta\n// ---------------------------------------------------------------------------\n\nconst meta: ChannelMeta = {\n id: 'feishu',\n label: 'Feishu',\n selectionLabel: 'Lark/Feishu (\\u98DE\\u4E66)',\n docsPath: '/channels/feishu',\n docsLabel: 'feishu',\n blurb: '\\u98DE\\u4E66/Lark enterprise messaging.',\n aliases: ['lark'],\n order: 70,\n};\n\n// ---------------------------------------------------------------------------\n// Channel plugin definition\n// ---------------------------------------------------------------------------\n\nexport const feishuPlugin: ChannelPlugin<LarkAccount> = {\n id: 'feishu',\n\n meta: {\n ...meta,\n },\n\n // -------------------------------------------------------------------------\n // Pairing\n // -------------------------------------------------------------------------\n\n pairing: {\n idLabel: 'feishuUserId',\n normalizeAllowEntry: (entry) => entry.replace(/^(feishu|user|open_id):/i, ''),\n notifyApproval: async ({ cfg, id }) => {\n const accountId = getDefaultLarkAccountId(cfg);\n pluginLog.info('notifyApproval called', { id, accountId });\n\n // 1. \u53D1\u9001\u914D\u5BF9\u6210\u529F\u6D88\u606F\uFF08\u4FDD\u6301\u73B0\u6709\u884C\u4E3A\uFF09\n await sendMessageFeishu({\n cfg,\n to: id,\n text: PAIRING_APPROVED_MESSAGE,\n accountId,\n });\n\n // 2. \u89E6\u53D1 onboarding\n try {\n await triggerOnboarding({ cfg, userOpenId: id, accountId });\n pluginLog.info('onboarding completed', { id });\n } catch (err) {\n pluginLog.warn('onboarding failed', { id, error: String(err) });\n }\n },\n },\n\n // -------------------------------------------------------------------------\n // Capabilities\n // -------------------------------------------------------------------------\n\n capabilities: {\n chatTypes: ['direct', 'group'],\n media: true,\n reactions: true,\n threads: true,\n polls: false,\n nativeCommands: true,\n blockStreaming: true,\n },\n\n // -------------------------------------------------------------------------\n // Agent prompt\n // -------------------------------------------------------------------------\n\n agentPrompt: {\n messageToolHints: () => [\n '- Feishu targeting: omit `target` to reply to the current conversation (auto-inferred). Explicit targets: `user:open_id` or `chat:chat_id`.',\n '- Feishu supports interactive cards for rich messages.',\n '- Feishu reactions use UPPERCASE emoji type names (e.g. `OK`,`THUMBSUP`,`THANKS`,`MUSCLE`,`FINGERHEART`,`APPLAUSE`,`FISTBUMP`,`JIAYI`,`DONE`,`SMILE`,`BLUSH` ), not Unicode emoji characters.',\n \"- Feishu `action=delete`/`action=unsend` only deletes messages sent by the bot. When the user quotes a message and says 'delete this', use the **quoted message's** message_id, not the user's own message_id.\",\n ],\n },\n\n // -------------------------------------------------------------------------\n // Groups\n // -------------------------------------------------------------------------\n\n groups: {\n resolveToolPolicy: resolveFeishuGroupToolPolicy,\n },\n\n // -------------------------------------------------------------------------\n // Reload\n // -------------------------------------------------------------------------\n\n reload: { configPrefixes: ['channels.feishu'] },\n\n // -------------------------------------------------------------------------\n // Config schema (JSON Schema)\n // -------------------------------------------------------------------------\n\n configSchema: {\n schema: FEISHU_CONFIG_JSON_SCHEMA,\n },\n\n // -------------------------------------------------------------------------\n // Config adapter\n // -------------------------------------------------------------------------\n\n config: {\n listAccountIds: (cfg) => getLarkAccountIds(cfg),\n resolveAccount: (cfg, accountId) => getLarkAccount(cfg, accountId),\n defaultAccountId: (cfg) => getDefaultLarkAccountId(cfg),\n\n setAccountEnabled: ({ cfg, accountId, enabled }) => {\n return setAccountEnabled(cfg, accountId, enabled);\n },\n\n deleteAccount: ({ cfg, accountId }) => {\n return deleteAccount(cfg, accountId);\n },\n\n isConfigured: (account) => account.configured,\n\n describeAccount: (account) => ({\n accountId: account.accountId,\n enabled: account.enabled,\n configured: account.configured,\n name: account.name,\n appId: account.appId,\n brand: account.brand,\n }),\n\n resolveAllowFrom: ({ cfg, accountId }) => {\n const account = getLarkAccount(cfg, accountId);\n return (account.config?.allowFrom ?? []).map((entry) => String(entry));\n },\n\n formatAllowFrom: ({ allowFrom }) =>\n allowFrom\n .map((entry) => String(entry).trim())\n .filter(Boolean)\n .map((entry) => entry.toLowerCase()),\n },\n\n // -------------------------------------------------------------------------\n // Security\n // -------------------------------------------------------------------------\n\n security: {\n collectWarnings: ({ cfg, accountId }) =>\n collectFeishuSecurityWarnings({ cfg, accountId: accountId ?? DEFAULT_ACCOUNT_ID }),\n },\n\n // -------------------------------------------------------------------------\n // Setup\n // -------------------------------------------------------------------------\n\n setup: {\n resolveAccountId: () => DEFAULT_ACCOUNT_ID,\n applyAccountConfig: ({ cfg, accountId }) => {\n return applyAccountConfig(cfg, accountId, { enabled: true });\n },\n },\n\n // -------------------------------------------------------------------------\n // Onboarding\n // -------------------------------------------------------------------------\n\n onboarding: feishuOnboardingAdapter,\n\n // -------------------------------------------------------------------------\n // Messaging\n // -------------------------------------------------------------------------\n\n messaging: {\n normalizeTarget: (raw) => normalizeFeishuTarget(raw) ?? undefined,\n targetResolver: {\n looksLikeId: looksLikeFeishuId,\n hint: '<chatId|user:openId|chat:chatId>',\n },\n },\n\n // -------------------------------------------------------------------------\n // Directory\n // -------------------------------------------------------------------------\n\n directory: {\n self: async () => null,\n listPeers: async (p) => listFeishuDirectoryPeers(adaptDirectoryParams(p)),\n listGroups: async (p) => listFeishuDirectoryGroups(adaptDirectoryParams(p)),\n listPeersLive: async (p) => listFeishuDirectoryPeersLive(adaptDirectoryParams(p)),\n listGroupsLive: async (p) => listFeishuDirectoryGroupsLive(adaptDirectoryParams(p)),\n },\n\n // -------------------------------------------------------------------------\n // Outbound\n // -------------------------------------------------------------------------\n\n outbound: feishuOutbound,\n\n // -------------------------------------------------------------------------\n // Threading\n // -------------------------------------------------------------------------\n\n threading: {\n buildToolContext: ({ context, hasRepliedRef }): ChannelThreadingToolContext => ({\n currentChannelId: normalizeFeishuTarget(context.To ?? '') ?? undefined,\n currentThreadTs: context.MessageThreadId != null ? String(context.MessageThreadId) : undefined,\n currentMessageId: context.CurrentMessageId,\n hasRepliedRef,\n }),\n },\n\n // -------------------------------------------------------------------------\n // Actions\n // -------------------------------------------------------------------------\n\n actions: feishuMessageActions,\n\n // -------------------------------------------------------------------------\n // Status\n // -------------------------------------------------------------------------\n\n status: {\n defaultRuntime: {\n accountId: DEFAULT_ACCOUNT_ID,\n running: false,\n lastStartAt: null,\n lastStopAt: null,\n lastError: null,\n port: null,\n },\n buildChannelSummary: ({ snapshot }) => ({\n configured: snapshot.configured ?? false,\n running: snapshot.running ?? false,\n lastStartAt: snapshot.lastStartAt ?? null,\n lastStopAt: snapshot.lastStopAt ?? null,\n lastError: snapshot.lastError ?? null,\n port: snapshot.port ?? null,\n probe: snapshot.probe,\n lastProbeAt: snapshot.lastProbeAt ?? null,\n }),\n probeAccount: async ({ account }) => {\n return await LarkClient.fromAccount(account).probe({ maxAgeMs: PROBE_CACHE_TTL_MS });\n },\n buildAccountSnapshot: ({ account, runtime, probe }) => ({\n accountId: account.accountId,\n enabled: account.enabled,\n configured: account.configured,\n name: account.name,\n appId: account.appId,\n brand: account.brand,\n running: runtime?.running ?? false,\n lastStartAt: runtime?.lastStartAt ?? null,\n lastStopAt: runtime?.lastStopAt ?? null,\n lastError: runtime?.lastError ?? null,\n port: runtime?.port ?? null,\n probe,\n }),\n },\n\n // -------------------------------------------------------------------------\n // Gateway\n // -------------------------------------------------------------------------\n\n gateway: {\n startAccount: async (ctx) => {\n const { monitorFeishuProvider } = await import('./monitor.js');\n const account = getLarkAccount(ctx.cfg, ctx.accountId);\n const port = account.config?.webhookPort ?? null;\n ctx.setStatus({ accountId: ctx.accountId, port });\n ctx.log?.info(`starting feishu[${ctx.accountId}] (mode: ${account.config?.connectionMode ?? 'websocket'})`);\n return monitorFeishuProvider({\n config: ctx.cfg,\n runtime: ctx.runtime,\n abortSignal: ctx.abortSignal,\n accountId: ctx.accountId,\n });\n },\n\n stopAccount: async (ctx) => {\n ctx.log?.info(`stopping feishu[${ctx.accountId}]`);\n LarkClient.clearCache(ctx.accountId);\n ctx.log?.info(`stopped feishu[${ctx.accountId}]`);\n },\n },\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { LarkClient } from "../core/lark-client";
|
|
2
|
+
async function probeFeishu(credentials) {
|
|
3
|
+
if (!credentials?.appId || !credentials?.appSecret) {
|
|
4
|
+
return {
|
|
5
|
+
ok: false,
|
|
6
|
+
error: "missing credentials (appId, appSecret)"
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
return LarkClient.fromCredentials(credentials).probe();
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
probeFeishu
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=probe.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/channel/probe.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport type { FeishuProbeResult } from './types';\nimport { LarkClient, type LarkClientCredentials } from '../core/lark-client';\n\n/**\n * Probe the Feishu bot connection by calling the bot/v3/info API.\n *\n * Returns a result indicating whether the bot is reachable and its\n * basic identity (name, open_id). Used by onboarding and status\n * checks to verify credentials before committing them to config.\n */\nexport async function probeFeishu(credentials?: LarkClientCredentials): Promise<FeishuProbeResult> {\n if (!credentials?.appId || !credentials?.appSecret) {\n return {\n ok: false,\n error: 'missing credentials (appId, appSecret)',\n };\n }\n\n return LarkClient.fromCredentials(credentials).probe();\n}\n"],
|
|
5
|
+
"mappings": "AAMA,SAAS,kBAA8C;AASvD,eAAsB,YAAY,aAAiE;AACjG,MAAI,CAAC,aAAa,SAAS,CAAC,aAAa,WAAW;AAClD,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO,WAAW,gBAAgB,WAAW,EAAE,MAAM;AACvD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|