@colinlu50/openclaw-lark-stream 2026.3.17
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 +141 -0
- package/README.zh.md +70 -0
- package/bin/openclaw-lark.js +48 -0
- package/index.d.ts +36 -0
- package/index.js +118 -0
- package/openclaw.plugin.json +10 -0
- package/package.json +66 -0
- package/skills/feishu-bitable/SKILL.md +248 -0
- package/skills/feishu-bitable/references/examples.md +813 -0
- package/skills/feishu-bitable/references/field-properties.md +763 -0
- package/skills/feishu-bitable/references/record-values.md +911 -0
- package/skills/feishu-calendar/SKILL.md +244 -0
- package/skills/feishu-channel-rules/SKILL.md +24 -0
- package/skills/feishu-channel-rules/references/markdown-syntax.md +138 -0
- package/skills/feishu-create-doc/SKILL.md +719 -0
- package/skills/feishu-fetch-doc/SKILL.md +93 -0
- package/skills/feishu-im-read/SKILL.md +163 -0
- package/skills/feishu-task/SKILL.md +293 -0
- package/skills/feishu-troubleshoot/SKILL.md +70 -0
- package/skills/feishu-update-doc/SKILL.md +285 -0
- package/src/card/builder.d.ts +106 -0
- package/src/card/builder.js +443 -0
- package/src/card/cardkit.d.ts +90 -0
- package/src/card/cardkit.js +181 -0
- package/src/card/flush-controller.d.ts +45 -0
- package/src/card/flush-controller.js +134 -0
- package/src/card/image-resolver.d.ts +45 -0
- package/src/card/image-resolver.js +112 -0
- package/src/card/markdown-style.d.ts +16 -0
- package/src/card/markdown-style.js +97 -0
- package/src/card/reply-dispatcher-types.d.ts +120 -0
- package/src/card/reply-dispatcher-types.js +57 -0
- package/src/card/reply-dispatcher.d.ts +15 -0
- package/src/card/reply-dispatcher.js +299 -0
- package/src/card/reply-mode.d.ts +38 -0
- package/src/card/reply-mode.js +65 -0
- package/src/card/streaming-card-controller.d.ts +101 -0
- package/src/card/streaming-card-controller.js +810 -0
- package/src/card/unavailable-guard.d.ts +35 -0
- package/src/card/unavailable-guard.js +83 -0
- package/src/channel/abort-detect.d.ts +34 -0
- package/src/channel/abort-detect.js +124 -0
- package/src/channel/chat-queue.d.ts +41 -0
- package/src/channel/chat-queue.js +58 -0
- package/src/channel/config-adapter.d.ts +23 -0
- package/src/channel/config-adapter.js +101 -0
- package/src/channel/directory.d.ts +57 -0
- package/src/channel/directory.js +191 -0
- package/src/channel/event-handlers.d.ts +15 -0
- package/src/channel/event-handlers.js +221 -0
- package/src/channel/monitor.d.ts +17 -0
- package/src/channel/monitor.js +129 -0
- package/src/channel/onboarding-config.d.ts +17 -0
- package/src/channel/onboarding-config.js +88 -0
- package/src/channel/onboarding-migrate.d.ts +25 -0
- package/src/channel/onboarding-migrate.js +67 -0
- package/src/channel/onboarding.d.ts +12 -0
- package/src/channel/onboarding.js +296 -0
- package/src/channel/plugin.d.ts +13 -0
- package/src/channel/plugin.js +278 -0
- package/src/channel/probe.d.ts +14 -0
- package/src/channel/probe.js +21 -0
- package/src/channel/types.d.ts +36 -0
- package/src/channel/types.js +7 -0
- package/src/commands/auth.d.ts +21 -0
- package/src/commands/auth.js +161 -0
- package/src/commands/diagnose.d.ts +69 -0
- package/src/commands/diagnose.js +807 -0
- package/src/commands/doctor.d.ts +26 -0
- package/src/commands/doctor.js +584 -0
- package/src/commands/index.d.ts +25 -0
- package/src/commands/index.js +212 -0
- package/src/commands/locale.d.ts +7 -0
- package/src/commands/locale.js +7 -0
- package/src/core/accounts.d.ts +37 -0
- package/src/core/accounts.js +163 -0
- package/src/core/agent-config.d.ts +100 -0
- package/src/core/agent-config.js +139 -0
- package/src/core/api-error.d.ts +48 -0
- package/src/core/api-error.js +112 -0
- package/src/core/app-owner-fallback.d.ts +21 -0
- package/src/core/app-owner-fallback.js +38 -0
- package/src/core/app-scope-checker.d.ts +87 -0
- package/src/core/app-scope-checker.js +190 -0
- package/src/core/auth-errors.d.ts +144 -0
- package/src/core/auth-errors.js +154 -0
- package/src/core/chat-info-cache.d.ts +57 -0
- package/src/core/chat-info-cache.js +152 -0
- package/src/core/config-schema.d.ts +448 -0
- package/src/core/config-schema.js +200 -0
- package/src/core/device-flow.d.ts +77 -0
- package/src/core/device-flow.js +212 -0
- package/src/core/domains.d.ts +18 -0
- package/src/core/domains.js +28 -0
- package/src/core/feishu-fetch.d.ts +18 -0
- package/src/core/feishu-fetch.js +25 -0
- package/src/core/footer-config.d.ts +24 -0
- package/src/core/footer-config.js +39 -0
- package/src/core/lark-client.d.ts +108 -0
- package/src/core/lark-client.js +353 -0
- package/src/core/lark-logger.d.ts +23 -0
- package/src/core/lark-logger.js +154 -0
- package/src/core/lark-ticket.d.ts +29 -0
- package/src/core/lark-ticket.js +35 -0
- package/src/core/message-unavailable.d.ts +53 -0
- package/src/core/message-unavailable.js +130 -0
- package/src/core/owner-policy.d.ts +31 -0
- package/src/core/owner-policy.js +52 -0
- package/src/core/permission-url.d.ts +22 -0
- package/src/core/permission-url.js +72 -0
- package/src/core/raw-request.d.ts +27 -0
- package/src/core/raw-request.js +62 -0
- package/src/core/scope-manager.d.ts +168 -0
- package/src/core/scope-manager.js +213 -0
- package/src/core/security-check.d.ts +72 -0
- package/src/core/security-check.js +174 -0
- package/src/core/shutdown-hooks.d.ts +22 -0
- package/src/core/shutdown-hooks.js +56 -0
- package/src/core/targets.d.ts +60 -0
- package/src/core/targets.js +164 -0
- package/src/core/token-store.d.ts +54 -0
- package/src/core/token-store.js +314 -0
- package/src/core/tool-client.d.ts +176 -0
- package/src/core/tool-client.js +380 -0
- package/src/core/tool-scopes.d.ts +153 -0
- package/src/core/tool-scopes.js +326 -0
- package/src/core/tools-config.d.ts +55 -0
- package/src/core/tools-config.js +137 -0
- package/src/core/types.d.ts +87 -0
- package/src/core/types.js +11 -0
- package/src/core/uat-client.d.ts +46 -0
- package/src/core/uat-client.js +187 -0
- package/src/core/version.d.ts +25 -0
- package/src/core/version.js +49 -0
- package/src/messaging/converters/audio.d.ts +8 -0
- package/src/messaging/converters/audio.js +21 -0
- package/src/messaging/converters/calendar.d.ts +13 -0
- package/src/messaging/converters/calendar.js +50 -0
- package/src/messaging/converters/content-converter.d.ts +41 -0
- package/src/messaging/converters/content-converter.js +106 -0
- package/src/messaging/converters/file.d.ts +8 -0
- package/src/messaging/converters/file.js +20 -0
- package/src/messaging/converters/folder.d.ts +8 -0
- package/src/messaging/converters/folder.js +20 -0
- package/src/messaging/converters/hongbao.d.ts +8 -0
- package/src/messaging/converters/hongbao.js +16 -0
- package/src/messaging/converters/image.d.ts +8 -0
- package/src/messaging/converters/image.js +18 -0
- package/src/messaging/converters/index.d.ts +8 -0
- package/src/messaging/converters/index.js +50 -0
- package/src/messaging/converters/interactive/card-converter.d.ts +76 -0
- package/src/messaging/converters/interactive/card-converter.js +1173 -0
- package/src/messaging/converters/interactive/card-utils.d.ts +9 -0
- package/src/messaging/converters/interactive/card-utils.js +42 -0
- package/src/messaging/converters/interactive/index.d.ts +8 -0
- package/src/messaging/converters/interactive/index.js +21 -0
- package/src/messaging/converters/interactive/legacy.d.ts +11 -0
- package/src/messaging/converters/interactive/legacy.js +57 -0
- package/src/messaging/converters/interactive/types.d.ts +23 -0
- package/src/messaging/converters/interactive/types.js +24 -0
- package/src/messaging/converters/location.d.ts +8 -0
- package/src/messaging/converters/location.js +19 -0
- package/src/messaging/converters/merge-forward.d.ts +32 -0
- package/src/messaging/converters/merge-forward.js +225 -0
- package/src/messaging/converters/post.d.ts +11 -0
- package/src/messaging/converters/post.js +135 -0
- package/src/messaging/converters/share.d.ts +9 -0
- package/src/messaging/converters/share.js +23 -0
- package/src/messaging/converters/sticker.d.ts +8 -0
- package/src/messaging/converters/sticker.js +18 -0
- package/src/messaging/converters/system.d.ts +12 -0
- package/src/messaging/converters/system.js +32 -0
- package/src/messaging/converters/text.d.ts +8 -0
- package/src/messaging/converters/text.js +14 -0
- package/src/messaging/converters/todo.d.ts +8 -0
- package/src/messaging/converters/todo.js +41 -0
- package/src/messaging/converters/types.d.ts +107 -0
- package/src/messaging/converters/types.js +7 -0
- package/src/messaging/converters/unknown.d.ts +8 -0
- package/src/messaging/converters/unknown.js +16 -0
- package/src/messaging/converters/utils.d.ts +22 -0
- package/src/messaging/converters/utils.js +51 -0
- package/src/messaging/converters/video-chat.d.ts +8 -0
- package/src/messaging/converters/video-chat.js +23 -0
- package/src/messaging/converters/video.d.ts +8 -0
- package/src/messaging/converters/video.js +32 -0
- package/src/messaging/converters/vote.d.ts +8 -0
- package/src/messaging/converters/vote.js +24 -0
- package/src/messaging/inbound/dedup.d.ts +59 -0
- package/src/messaging/inbound/dedup.js +116 -0
- package/src/messaging/inbound/dispatch-builders.d.ts +84 -0
- package/src/messaging/inbound/dispatch-builders.js +152 -0
- package/src/messaging/inbound/dispatch-commands.d.ts +27 -0
- package/src/messaging/inbound/dispatch-commands.js +112 -0
- package/src/messaging/inbound/dispatch-context.d.ts +67 -0
- package/src/messaging/inbound/dispatch-context.js +136 -0
- package/src/messaging/inbound/dispatch.d.ts +47 -0
- package/src/messaging/inbound/dispatch.js +264 -0
- package/src/messaging/inbound/enrich.d.ts +102 -0
- package/src/messaging/inbound/enrich.js +227 -0
- package/src/messaging/inbound/gate-effects.d.ts +23 -0
- package/src/messaging/inbound/gate-effects.js +43 -0
- package/src/messaging/inbound/gate.d.ts +60 -0
- package/src/messaging/inbound/gate.js +233 -0
- package/src/messaging/inbound/handler.d.ts +35 -0
- package/src/messaging/inbound/handler.js +173 -0
- package/src/messaging/inbound/media-resolver.d.ts +32 -0
- package/src/messaging/inbound/media-resolver.js +87 -0
- package/src/messaging/inbound/mention.d.ts +39 -0
- package/src/messaging/inbound/mention.js +81 -0
- package/src/messaging/inbound/parse-io.d.ts +50 -0
- package/src/messaging/inbound/parse-io.js +81 -0
- package/src/messaging/inbound/parse.d.ts +28 -0
- package/src/messaging/inbound/parse.js +106 -0
- package/src/messaging/inbound/permission.d.ts +17 -0
- package/src/messaging/inbound/permission.js +40 -0
- package/src/messaging/inbound/policy.d.ts +94 -0
- package/src/messaging/inbound/policy.js +160 -0
- package/src/messaging/inbound/reaction-handler.d.ts +61 -0
- package/src/messaging/inbound/reaction-handler.js +221 -0
- package/src/messaging/inbound/user-name-cache.d.ts +82 -0
- package/src/messaging/inbound/user-name-cache.js +241 -0
- package/src/messaging/outbound/actions.d.ts +16 -0
- package/src/messaging/outbound/actions.js +309 -0
- package/src/messaging/outbound/chat-manage.d.ts +64 -0
- package/src/messaging/outbound/chat-manage.js +111 -0
- package/src/messaging/outbound/deliver.d.ts +155 -0
- package/src/messaging/outbound/deliver.js +298 -0
- package/src/messaging/outbound/fetch.d.ts +12 -0
- package/src/messaging/outbound/fetch.js +12 -0
- package/src/messaging/outbound/forward.d.ts +26 -0
- package/src/messaging/outbound/forward.js +48 -0
- package/src/messaging/outbound/media-url-utils.d.ts +29 -0
- package/src/messaging/outbound/media-url-utils.js +130 -0
- package/src/messaging/outbound/media.d.ts +260 -0
- package/src/messaging/outbound/media.js +758 -0
- package/src/messaging/outbound/outbound.d.ts +89 -0
- package/src/messaging/outbound/outbound.js +121 -0
- package/src/messaging/outbound/reactions.d.ts +124 -0
- package/src/messaging/outbound/reactions.js +378 -0
- package/src/messaging/outbound/send.d.ts +152 -0
- package/src/messaging/outbound/send.js +355 -0
- package/src/messaging/outbound/typing.d.ts +71 -0
- package/src/messaging/outbound/typing.js +179 -0
- package/src/messaging/shared/message-lookup.d.ts +54 -0
- package/src/messaging/shared/message-lookup.js +117 -0
- package/src/messaging/types.d.ts +176 -0
- package/src/messaging/types.js +10 -0
- package/src/tools/auto-auth.d.ts +56 -0
- package/src/tools/auto-auth.js +919 -0
- package/src/tools/helpers.d.ts +260 -0
- package/src/tools/helpers.js +364 -0
- package/src/tools/mcp/doc/create.d.ts +12 -0
- package/src/tools/mcp/doc/create.js +44 -0
- package/src/tools/mcp/doc/fetch.d.ts +12 -0
- package/src/tools/mcp/doc/fetch.js +36 -0
- package/src/tools/mcp/doc/index.d.ts +12 -0
- package/src/tools/mcp/doc/index.js +41 -0
- package/src/tools/mcp/doc/update.d.ts +12 -0
- package/src/tools/mcp/doc/update.js +61 -0
- package/src/tools/mcp/shared.d.ts +59 -0
- package/src/tools/mcp/shared.js +226 -0
- package/src/tools/oapi/bitable/app-table-field.d.ts +16 -0
- package/src/tools/oapi/bitable/app-table-field.js +222 -0
- package/src/tools/oapi/bitable/app-table-record.d.ts +20 -0
- package/src/tools/oapi/bitable/app-table-record.js +436 -0
- package/src/tools/oapi/bitable/app-table-view.d.ts +17 -0
- package/src/tools/oapi/bitable/app-table-view.js +195 -0
- package/src/tools/oapi/bitable/app-table.d.ts +19 -0
- package/src/tools/oapi/bitable/app-table.js +247 -0
- package/src/tools/oapi/bitable/app.d.ts +18 -0
- package/src/tools/oapi/bitable/app.js +186 -0
- package/src/tools/oapi/bitable/index.d.ts +9 -0
- package/src/tools/oapi/bitable/index.js +9 -0
- package/src/tools/oapi/calendar/calendar.d.ts +15 -0
- package/src/tools/oapi/calendar/calendar.js +122 -0
- package/src/tools/oapi/calendar/event-attendee.d.ts +16 -0
- package/src/tools/oapi/calendar/event-attendee.js +263 -0
- package/src/tools/oapi/calendar/event.d.ts +16 -0
- package/src/tools/oapi/calendar/event.js +709 -0
- package/src/tools/oapi/calendar/freebusy.d.ts +13 -0
- package/src/tools/oapi/calendar/freebusy.js +111 -0
- package/src/tools/oapi/calendar/index.d.ts +8 -0
- package/src/tools/oapi/calendar/index.js +8 -0
- package/src/tools/oapi/chat/chat.d.ts +16 -0
- package/src/tools/oapi/chat/chat.js +124 -0
- package/src/tools/oapi/chat/index.d.ts +10 -0
- package/src/tools/oapi/chat/index.js +15 -0
- package/src/tools/oapi/chat/members.d.ts +11 -0
- package/src/tools/oapi/chat/members.js +81 -0
- package/src/tools/oapi/common/get-user.d.ts +12 -0
- package/src/tools/oapi/common/get-user.js +106 -0
- package/src/tools/oapi/common/index.d.ts +6 -0
- package/src/tools/oapi/common/index.js +6 -0
- package/src/tools/oapi/common/search-user.d.ts +11 -0
- package/src/tools/oapi/common/search-user.js +73 -0
- package/src/tools/oapi/drive/doc-comments.d.ts +15 -0
- package/src/tools/oapi/drive/doc-comments.js +279 -0
- package/src/tools/oapi/drive/doc-media.d.ts +19 -0
- package/src/tools/oapi/drive/doc-media.js +335 -0
- package/src/tools/oapi/drive/file.d.ts +19 -0
- package/src/tools/oapi/drive/file.js +483 -0
- package/src/tools/oapi/drive/index.d.ts +12 -0
- package/src/tools/oapi/drive/index.js +36 -0
- package/src/tools/oapi/helpers.d.ts +182 -0
- package/src/tools/oapi/helpers.js +354 -0
- package/src/tools/oapi/im/format-messages.d.ts +50 -0
- package/src/tools/oapi/im/format-messages.js +165 -0
- package/src/tools/oapi/im/index.d.ts +10 -0
- package/src/tools/oapi/im/index.js +17 -0
- package/src/tools/oapi/im/message-read.d.ts +13 -0
- package/src/tools/oapi/im/message-read.js +411 -0
- package/src/tools/oapi/im/message.d.ts +16 -0
- package/src/tools/oapi/im/message.js +149 -0
- package/src/tools/oapi/im/resource.d.ts +13 -0
- package/src/tools/oapi/im/resource.js +150 -0
- package/src/tools/oapi/im/time-utils.d.ts +46 -0
- package/src/tools/oapi/im/time-utils.js +201 -0
- package/src/tools/oapi/im/user-name-uat.d.ts +26 -0
- package/src/tools/oapi/im/user-name-uat.js +140 -0
- package/src/tools/oapi/index.d.ts +11 -0
- package/src/tools/oapi/index.js +58 -0
- package/src/tools/oapi/sdk-types.d.ts +96 -0
- package/src/tools/oapi/sdk-types.js +12 -0
- package/src/tools/oapi/search/doc-search.d.ts +13 -0
- package/src/tools/oapi/search/doc-search.js +191 -0
- package/src/tools/oapi/search/index.d.ts +12 -0
- package/src/tools/oapi/search/index.js +33 -0
- package/src/tools/oapi/sheets/index.d.ts +12 -0
- package/src/tools/oapi/sheets/index.js +31 -0
- package/src/tools/oapi/sheets/sheet.d.ts +16 -0
- package/src/tools/oapi/sheets/sheet.js +652 -0
- package/src/tools/oapi/task/comment.d.ts +15 -0
- package/src/tools/oapi/task/comment.js +140 -0
- package/src/tools/oapi/task/index.d.ts +8 -0
- package/src/tools/oapi/task/index.js +8 -0
- package/src/tools/oapi/task/subtask.d.ts +14 -0
- package/src/tools/oapi/task/subtask.js +162 -0
- package/src/tools/oapi/task/task.d.ts +16 -0
- package/src/tools/oapi/task/task.js +344 -0
- package/src/tools/oapi/task/tasklist.d.ts +21 -0
- package/src/tools/oapi/task/tasklist.js +321 -0
- package/src/tools/oapi/wiki/index.d.ts +12 -0
- package/src/tools/oapi/wiki/index.js +34 -0
- package/src/tools/oapi/wiki/space-node.d.ts +17 -0
- package/src/tools/oapi/wiki/space-node.js +230 -0
- package/src/tools/oapi/wiki/space.d.ts +15 -0
- package/src/tools/oapi/wiki/space.js +130 -0
- package/src/tools/oauth-batch-auth.d.ts +11 -0
- package/src/tools/oauth-batch-auth.js +142 -0
- package/src/tools/oauth-cards.d.ts +39 -0
- package/src/tools/oauth-cards.js +315 -0
- package/src/tools/oauth.d.ts +47 -0
- package/src/tools/oauth.js +620 -0
- package/src/tools/onboarding-auth.d.ts +27 -0
- package/src/tools/onboarding-auth.js +130 -0
- package/src/tools/tat/im/index.d.ts +15 -0
- package/src/tools/tat/im/index.js +18 -0
- package/src/tools/tat/im/resource.d.ts +15 -0
- package/src/tools/tat/im/resource.js +157 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* feishu_wiki_space tool -- Manage Feishu Wiki spaces.
|
|
6
|
+
*
|
|
7
|
+
* Actions: list, get, create
|
|
8
|
+
*
|
|
9
|
+
* Uses the Feishu Wiki API:
|
|
10
|
+
* - list: GET /open-apis/wiki/v2/spaces
|
|
11
|
+
* - get: GET /open-apis/wiki/v2/spaces/:space_id
|
|
12
|
+
* - create: POST /open-apis/wiki/v2/spaces
|
|
13
|
+
*/
|
|
14
|
+
import { Type } from '@sinclair/typebox';
|
|
15
|
+
import { json, createToolContext, assertLarkOk, handleInvokeErrorWithAutoAuth, registerTool, } from '../helpers';
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Schema
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
const FeishuWikiSpaceSchema = Type.Union([
|
|
20
|
+
// LIST SPACES
|
|
21
|
+
Type.Object({
|
|
22
|
+
action: Type.Literal('list'),
|
|
23
|
+
page_size: Type.Optional(Type.Integer({
|
|
24
|
+
description: '分页大小(默认 10,最大 50)',
|
|
25
|
+
minimum: 1,
|
|
26
|
+
maximum: 50,
|
|
27
|
+
})),
|
|
28
|
+
page_token: Type.Optional(Type.String({
|
|
29
|
+
description: '分页标记。首次请求无需填写',
|
|
30
|
+
})),
|
|
31
|
+
}),
|
|
32
|
+
// GET SPACE
|
|
33
|
+
Type.Object({
|
|
34
|
+
action: Type.Literal('get'),
|
|
35
|
+
space_id: Type.String({
|
|
36
|
+
description: '知识空间 ID(必填)',
|
|
37
|
+
}),
|
|
38
|
+
}),
|
|
39
|
+
// CREATE SPACE
|
|
40
|
+
Type.Object({
|
|
41
|
+
action: Type.Literal('create'),
|
|
42
|
+
name: Type.Optional(Type.String({
|
|
43
|
+
description: '知识空间名称',
|
|
44
|
+
})),
|
|
45
|
+
description: Type.Optional(Type.String({
|
|
46
|
+
description: '知识空间描述',
|
|
47
|
+
})),
|
|
48
|
+
}),
|
|
49
|
+
]);
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Registration
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
export function registerFeishuWikiSpaceTool(api) {
|
|
54
|
+
if (!api.config)
|
|
55
|
+
return;
|
|
56
|
+
const cfg = api.config;
|
|
57
|
+
const { toolClient, log } = createToolContext(api, 'feishu_wiki_space');
|
|
58
|
+
registerTool(api, {
|
|
59
|
+
name: 'feishu_wiki_space',
|
|
60
|
+
label: 'Feishu Wiki Spaces',
|
|
61
|
+
description: '飞书知识空间管理工具。当用户要求查看知识库列表、获取知识库信息、创建知识库时使用。Actions: list(列出知识空间), get(获取知识空间信息), create(创建知识空间)。' +
|
|
62
|
+
'【重要】space_id 可以从浏览器 URL 中获取,或通过 list 接口获取。' +
|
|
63
|
+
'【重要】知识空间(Space)是知识库的基本组成单位,包含多个具有层级关系的文档节点。',
|
|
64
|
+
parameters: FeishuWikiSpaceSchema,
|
|
65
|
+
async execute(_toolCallId, params) {
|
|
66
|
+
const p = params;
|
|
67
|
+
try {
|
|
68
|
+
const client = toolClient();
|
|
69
|
+
switch (p.action) {
|
|
70
|
+
// -----------------------------------------------------------------
|
|
71
|
+
// LIST SPACES
|
|
72
|
+
// -----------------------------------------------------------------
|
|
73
|
+
case 'list': {
|
|
74
|
+
log.info(`list: page_size=${p.page_size ?? 10}`);
|
|
75
|
+
const res = await client.invoke('feishu_wiki_space.list', (sdk, opts) => sdk.wiki.space.list({
|
|
76
|
+
params: {
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
78
|
+
page_size: p.page_size,
|
|
79
|
+
page_token: p.page_token,
|
|
80
|
+
},
|
|
81
|
+
}, opts), { as: 'user' });
|
|
82
|
+
assertLarkOk(res);
|
|
83
|
+
const data = res.data;
|
|
84
|
+
log.info(`list: returned ${data?.items?.length ?? 0} spaces`);
|
|
85
|
+
return json({
|
|
86
|
+
spaces: data?.items,
|
|
87
|
+
has_more: data?.has_more,
|
|
88
|
+
page_token: data?.page_token,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
// -----------------------------------------------------------------
|
|
92
|
+
// GET SPACE
|
|
93
|
+
// -----------------------------------------------------------------
|
|
94
|
+
case 'get': {
|
|
95
|
+
log.info(`get: space_id=${p.space_id}`);
|
|
96
|
+
const res = await client.invoke('feishu_wiki_space.get', (sdk, opts) => sdk.wiki.space.get({
|
|
97
|
+
path: { space_id: p.space_id },
|
|
98
|
+
}, opts), { as: 'user' });
|
|
99
|
+
assertLarkOk(res);
|
|
100
|
+
log.info(`get: retrieved space ${p.space_id}`);
|
|
101
|
+
return json({
|
|
102
|
+
space: res.data?.space,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
// -----------------------------------------------------------------
|
|
106
|
+
// CREATE SPACE
|
|
107
|
+
// -----------------------------------------------------------------
|
|
108
|
+
case 'create': {
|
|
109
|
+
log.info(`create: name=${p.name ?? '(empty)'}, description=${p.description ?? '(empty)'}`);
|
|
110
|
+
const res = await client.invoke('feishu_wiki_space.create', (sdk, opts) => sdk.wiki.space.create({
|
|
111
|
+
data: {
|
|
112
|
+
name: p.name,
|
|
113
|
+
description: p.description,
|
|
114
|
+
},
|
|
115
|
+
}, opts), { as: 'user' });
|
|
116
|
+
assertLarkOk(res);
|
|
117
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
118
|
+
log.info(`create: created space_id=${res.data?.space?.space_id}`);
|
|
119
|
+
return json({
|
|
120
|
+
space: res.data?.space,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
return await handleInvokeErrorWithAutoAuth(err, cfg);
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
}, { name: 'feishu_wiki_space' });
|
|
130
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* feishu_oauth_batch_auth tool — 批量授权应用已开通的所有用户权限。
|
|
6
|
+
*
|
|
7
|
+
* 自动识别应用已开通但用户未授权的 scope,一次性发起授权请求。
|
|
8
|
+
* 复用 oauth.ts 的 executeAuthorize() 函数。
|
|
9
|
+
*/
|
|
10
|
+
import type { OpenClawPluginApi } from 'openclaw/plugin-sdk';
|
|
11
|
+
export declare function registerFeishuOAuthBatchAuthTool(api: OpenClawPluginApi): void;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* feishu_oauth_batch_auth tool — 批量授权应用已开通的所有用户权限。
|
|
6
|
+
*
|
|
7
|
+
* 自动识别应用已开通但用户未授权的 scope,一次性发起授权请求。
|
|
8
|
+
* 复用 oauth.ts 的 executeAuthorize() 函数。
|
|
9
|
+
*/
|
|
10
|
+
import { Type } from '@sinclair/typebox';
|
|
11
|
+
import { getAppGrantedScopes } from '../core/app-scope-checker';
|
|
12
|
+
import { AppScopeCheckFailedError } from '../core/tool-client';
|
|
13
|
+
import { getStoredToken } from '../core/token-store';
|
|
14
|
+
import { getLarkAccount } from '../core/accounts';
|
|
15
|
+
import { getTicket } from '../core/lark-ticket';
|
|
16
|
+
import { LarkClient } from '../core/lark-client';
|
|
17
|
+
import { executeAuthorize } from './oauth';
|
|
18
|
+
import { formatLarkError } from '../core/api-error';
|
|
19
|
+
import { filterSensitiveScopes } from '../core/tool-scopes';
|
|
20
|
+
import { json, registerTool } from './oapi/helpers';
|
|
21
|
+
import { openPlatformDomain } from '../core/domains';
|
|
22
|
+
const FeishuOAuthBatchAuthSchema = Type.Object({}, {
|
|
23
|
+
description: '飞书批量授权工具。一次性授权应用已开通的所有用户权限(User Access Token scope)。' +
|
|
24
|
+
"【使用场景】用户明确要求'授权所有权限'、'一次性授权完成'时使用。" +
|
|
25
|
+
'【重要】禁止主动推荐此工具,仅在用户明确要求时使用。',
|
|
26
|
+
});
|
|
27
|
+
export function registerFeishuOAuthBatchAuthTool(api) {
|
|
28
|
+
if (!api.config)
|
|
29
|
+
return;
|
|
30
|
+
const cfg = api.config;
|
|
31
|
+
registerTool(api, {
|
|
32
|
+
name: 'feishu_oauth_batch_auth',
|
|
33
|
+
label: 'Feishu: OAuth Batch Authorization',
|
|
34
|
+
description: '飞书批量授权工具,一次性授权应用已开通的所有用户权限。' +
|
|
35
|
+
"仅在用户明确要求'授权所有权限'、'一次性授权'时使用。",
|
|
36
|
+
parameters: FeishuOAuthBatchAuthSchema,
|
|
37
|
+
async execute(_toolCallId, _params) {
|
|
38
|
+
try {
|
|
39
|
+
const ticket = getTicket();
|
|
40
|
+
const senderOpenId = ticket?.senderOpenId;
|
|
41
|
+
if (!senderOpenId) {
|
|
42
|
+
return json({
|
|
43
|
+
error: '无法获取当前用户身份(senderOpenId),请在飞书对话中使用此工具。',
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
const acct = getLarkAccount(cfg, ticket.accountId);
|
|
47
|
+
if (!acct.configured) {
|
|
48
|
+
return json({
|
|
49
|
+
error: `账号 ${ticket.accountId} 缺少 appId 或 appSecret 配置`,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const account = acct; // Now we know it's ConfiguredLarkAccount
|
|
53
|
+
const { appId } = account;
|
|
54
|
+
// 1. 查询应用已开通的 user scope
|
|
55
|
+
const sdk = LarkClient.fromAccount(account).sdk;
|
|
56
|
+
let appScopes;
|
|
57
|
+
try {
|
|
58
|
+
appScopes = await getAppGrantedScopes(sdk, appId, 'user');
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
if (err instanceof AppScopeCheckFailedError) {
|
|
62
|
+
return json({
|
|
63
|
+
error: 'app_scope_check_failed',
|
|
64
|
+
message: `应用缺少核心权限 application:application:self_manage,无法查询可授权 scope 列表。\n\n` +
|
|
65
|
+
`请管理员在飞书开放平台开通此权限后重试。`,
|
|
66
|
+
permission_link: `${openPlatformDomain(account.brand)}/app/${appId}/auth?q=application:application:self_manage`,
|
|
67
|
+
app_id: appId,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
throw err;
|
|
71
|
+
}
|
|
72
|
+
// 2. 边界情况:应用无 user scope
|
|
73
|
+
if (appScopes.length === 0) {
|
|
74
|
+
return json({
|
|
75
|
+
success: false,
|
|
76
|
+
message: '当前应用未开通任何用户级权限(User Access Token scope),' +
|
|
77
|
+
'无法使用用户身份调用 API。\n\n' +
|
|
78
|
+
'如需使用用户级功能,请联系管理员在开放平台开通相关权限。',
|
|
79
|
+
total_app_scopes: 0,
|
|
80
|
+
app_id: appId,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
// 3. 查询用户已授权的 scope
|
|
84
|
+
const existing = await getStoredToken(appId, senderOpenId);
|
|
85
|
+
const grantedScopes = new Set(existing?.scope?.split(/\s+/).filter(Boolean) ?? []);
|
|
86
|
+
// 4. 计算差集(应用已开通但用户未授权)
|
|
87
|
+
let missingScopes = appScopes.filter((s) => !grantedScopes.has(s));
|
|
88
|
+
missingScopes = filterSensitiveScopes(missingScopes);
|
|
89
|
+
// 5. 边界情况:用户已授权所有 scope
|
|
90
|
+
if (missingScopes.length === 0) {
|
|
91
|
+
return json({
|
|
92
|
+
success: true,
|
|
93
|
+
message: `您已授权所有可用权限(共 ${appScopes.length} 个),无需重复授权。`,
|
|
94
|
+
total_app_scopes: appScopes.length,
|
|
95
|
+
already_granted: appScopes.length,
|
|
96
|
+
missing: 0,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
// 6. 飞书限制:单次最多请求 100 个 scope
|
|
100
|
+
const MAX_SCOPES_PER_BATCH = 100;
|
|
101
|
+
let scopesToAuthorize = missingScopes;
|
|
102
|
+
let batchInfo = '';
|
|
103
|
+
if (missingScopes.length > MAX_SCOPES_PER_BATCH) {
|
|
104
|
+
// 分批授权:取前 50 个
|
|
105
|
+
scopesToAuthorize = missingScopes.slice(0, MAX_SCOPES_PER_BATCH);
|
|
106
|
+
const remainingCount = missingScopes.length - MAX_SCOPES_PER_BATCH;
|
|
107
|
+
batchInfo =
|
|
108
|
+
`\n\n由于飞书限制(单次最多 ${MAX_SCOPES_PER_BATCH} 个 scope),` +
|
|
109
|
+
`本次将授权前 ${MAX_SCOPES_PER_BATCH} 个权限。\n` +
|
|
110
|
+
`授权完成后,还需授权剩余 ${remainingCount} 个权限`;
|
|
111
|
+
}
|
|
112
|
+
// 7. 调用共享的 executeAuthorize() 函数(复用 oauth.ts 逻辑)
|
|
113
|
+
const scope = scopesToAuthorize.join(' ');
|
|
114
|
+
const result = await executeAuthorize({
|
|
115
|
+
account,
|
|
116
|
+
senderOpenId,
|
|
117
|
+
scope,
|
|
118
|
+
isBatchAuth: true,
|
|
119
|
+
totalAppScopes: appScopes.length,
|
|
120
|
+
alreadyGranted: grantedScopes.size,
|
|
121
|
+
batchInfo,
|
|
122
|
+
cfg,
|
|
123
|
+
ticket,
|
|
124
|
+
});
|
|
125
|
+
// 8. 如果是分批授权,在返回结果中添加提示
|
|
126
|
+
if (batchInfo && result.details) {
|
|
127
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
128
|
+
const details = result.details;
|
|
129
|
+
if (details.message) {
|
|
130
|
+
details.message = details.message + batchInfo;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
api.logger.error?.(`feishu_oauth_batch_auth: ${err}`);
|
|
137
|
+
return json({ error: formatLarkError(err) });
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
}, { name: 'feishu_oauth_batch_auth' });
|
|
141
|
+
api.logger.info?.('feishu_oauth_batch_auth: Registered feishu_oauth_batch_auth tool');
|
|
142
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* oauth-cards.ts — OAuth 授权卡片构建函数。
|
|
6
|
+
*
|
|
7
|
+
* 从 oauth.ts 提取的纯 UI 函数,与 OAuth 业务流程解耦。
|
|
8
|
+
* 卡片使用 v2 JSON 结构 + i18n_content 支持多语言。
|
|
9
|
+
*/
|
|
10
|
+
import type { LarkBrand } from '../core/types';
|
|
11
|
+
type Locale = 'zh_cn' | 'en_us';
|
|
12
|
+
export declare function buildAuthCard(params: {
|
|
13
|
+
verificationUriComplete: string;
|
|
14
|
+
expiresMin: number;
|
|
15
|
+
scope?: string;
|
|
16
|
+
isBatchAuth?: boolean;
|
|
17
|
+
totalAppScopes?: number;
|
|
18
|
+
alreadyGranted?: number;
|
|
19
|
+
batchInfo?: string;
|
|
20
|
+
filteredScopes?: string[];
|
|
21
|
+
appId?: string;
|
|
22
|
+
showBatchAuthHint?: boolean;
|
|
23
|
+
brand?: LarkBrand;
|
|
24
|
+
}): Record<string, unknown>;
|
|
25
|
+
/** scope 字符串 → 可读描述(支持多语言) */
|
|
26
|
+
export declare function formatScopeDescription(locale: Locale, params: {
|
|
27
|
+
scope?: string;
|
|
28
|
+
isBatchAuth?: boolean;
|
|
29
|
+
totalAppScopes?: number;
|
|
30
|
+
alreadyGranted?: number;
|
|
31
|
+
batchInfo?: string;
|
|
32
|
+
filteredScopes?: string[];
|
|
33
|
+
appId?: string;
|
|
34
|
+
}): string;
|
|
35
|
+
export declare function toInAppWebUrl(targetUrl: string, brand?: LarkBrand): string;
|
|
36
|
+
export declare function buildAuthSuccessCard(brand?: LarkBrand): Record<string, unknown>;
|
|
37
|
+
export declare function buildAuthFailedCard(_reason: string): Record<string, unknown>;
|
|
38
|
+
export declare function buildAuthIdentityMismatchCard(brand?: LarkBrand): Record<string, unknown>;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* oauth-cards.ts — OAuth 授权卡片构建函数。
|
|
6
|
+
*
|
|
7
|
+
* 从 oauth.ts 提取的纯 UI 函数,与 OAuth 业务流程解耦。
|
|
8
|
+
* 卡片使用 v2 JSON 结构 + i18n_content 支持多语言。
|
|
9
|
+
*/
|
|
10
|
+
import { applinkDomain } from '../core/domains';
|
|
11
|
+
/** v2 卡片 i18n 配置,注入到 config 中 */
|
|
12
|
+
const I18N_CONFIG = {
|
|
13
|
+
update_multi: true,
|
|
14
|
+
locales: ['zh_cn', 'en_us'],
|
|
15
|
+
};
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// i18n texts
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
const CARD_TEXTS = {
|
|
20
|
+
zh_cn: {
|
|
21
|
+
authRequired: '请授权以继续当前操作',
|
|
22
|
+
goAuth: '前往授权',
|
|
23
|
+
expiresHint: (min) => `<font color='grey'>授权链接将在 ${min} 分钟后失效,届时需重新发起</font>`,
|
|
24
|
+
batchAuthHint: "<font color='grey'>💡如果你希望一次性授予所有插件所需要的权限,可以告诉我「授予所有用户权限」,我会协助你完成。</font>",
|
|
25
|
+
batchScopeMsg: (count, total, granted) => `应用需要授权 **${count}** 个用户权限(共 ${total} 个,已授权 ${granted} 个)。`,
|
|
26
|
+
scopePreviewLabel: '**将要授权的权限**',
|
|
27
|
+
scopeListLabel: '**将要授权的权限列表**',
|
|
28
|
+
scopeDesc: '授权后,应用将能够以你的身份执行相关操作。',
|
|
29
|
+
requiredScopes: '所需权限:',
|
|
30
|
+
authSuccess: '授权成功',
|
|
31
|
+
authSuccessBody: (brandName) => `你的${brandName}账号已成功授权,正在为你继续执行操作。\n\n` +
|
|
32
|
+
"<font color='grey'>如需撤销授权,可随时告诉我。</font>",
|
|
33
|
+
authIncomplete: '授权未完成',
|
|
34
|
+
authExpiredBody: '授权链接已过期,请重新发起授权。',
|
|
35
|
+
authMismatchTitle: '授权失败,操作账号与发起账号不一致',
|
|
36
|
+
authMismatchBody: (brandName) => `检测到当前进行授权操作的${brandName}账号与发起授权请求的账号不一致。为保障数据安全,本次授权已被拒绝。\n\n` +
|
|
37
|
+
"<font color='grey'>请授权请求的发起人使用其账号,点击授权链接完成授权。</font>",
|
|
38
|
+
},
|
|
39
|
+
en_us: {
|
|
40
|
+
authRequired: 'Authorize to continue',
|
|
41
|
+
goAuth: 'Authorize Now',
|
|
42
|
+
expiresHint: (min) => `<font color='grey'>This link will time out in ${min} minutes, so you'll need a new one if it expires.</font>`,
|
|
43
|
+
batchAuthHint: "<font color='grey'>💡 If you'd like to grant all permissions at once, just say \"Authorize all\", and I'll take care of it.</font>",
|
|
44
|
+
batchScopeMsg: (count, total, granted) => `The app requires ${count} additional user token permissions (${granted} of ${total} granted).`,
|
|
45
|
+
scopePreviewLabel: '**Permissions to authorize**',
|
|
46
|
+
scopeListLabel: '**Permissions to authorize**',
|
|
47
|
+
scopeDesc: 'Once authorized, the app can perform actions on your behalf.',
|
|
48
|
+
requiredScopes: 'Required permissions:',
|
|
49
|
+
authSuccess: 'Authorized',
|
|
50
|
+
authSuccessBody: (brandName) => `${brandName} account authorized. Continuing with your request.\n\n` +
|
|
51
|
+
"<font color='grey'>Let me know if you ever need to revoke the permissions.</font>",
|
|
52
|
+
authIncomplete: 'Authorization incomplete',
|
|
53
|
+
authExpiredBody: 'The link is no longer active. Please restart the process.',
|
|
54
|
+
authMismatchTitle: 'Authorization failed: Account mismatch',
|
|
55
|
+
authMismatchBody: (brandName) => `The ${brandName} account used for authorization does not match the account that initiated the request. To protect your data, this request has been denied.\n\n` +
|
|
56
|
+
"<font color='grey'>Only the person who started this request can authorize it using their account.</font>",
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
/** 构造 i18n_content 对象(双语) */
|
|
60
|
+
function i18nContent(zh, en) {
|
|
61
|
+
return { zh_cn: zh, en_us: en };
|
|
62
|
+
}
|
|
63
|
+
/** 构造带 i18n_content 的 plain_text(默认语言为英文) */
|
|
64
|
+
function i18nPlainText(zh, en) {
|
|
65
|
+
return { tag: 'plain_text', content: en, i18n_content: i18nContent(zh, en) };
|
|
66
|
+
}
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// Card builders
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
export function buildAuthCard(params) {
|
|
71
|
+
const { verificationUriComplete, expiresMin, scope, isBatchAuth, totalAppScopes, alreadyGranted, batchInfo, filteredScopes, appId, showBatchAuthHint, brand, } = params;
|
|
72
|
+
const inAppUrl = toInAppWebUrl(verificationUriComplete, brand);
|
|
73
|
+
const multiUrl = {
|
|
74
|
+
url: inAppUrl,
|
|
75
|
+
pc_url: inAppUrl,
|
|
76
|
+
android_url: inAppUrl,
|
|
77
|
+
ios_url: inAppUrl,
|
|
78
|
+
};
|
|
79
|
+
const scopeParams = { scope, isBatchAuth, totalAppScopes, alreadyGranted, batchInfo, filteredScopes, appId };
|
|
80
|
+
const scopeDescZh = formatScopeDescription('zh_cn', scopeParams);
|
|
81
|
+
const scopeDescEn = formatScopeDescription('en_us', scopeParams);
|
|
82
|
+
const zhT = CARD_TEXTS.zh_cn;
|
|
83
|
+
const enT = CARD_TEXTS.en_us;
|
|
84
|
+
const elements = [
|
|
85
|
+
// 授权说明
|
|
86
|
+
{
|
|
87
|
+
tag: 'markdown',
|
|
88
|
+
content: scopeDescEn,
|
|
89
|
+
i18n_content: i18nContent(scopeDescZh, scopeDescEn),
|
|
90
|
+
text_size: 'normal',
|
|
91
|
+
},
|
|
92
|
+
// 授权按钮(small,靠右)
|
|
93
|
+
{
|
|
94
|
+
tag: 'column_set',
|
|
95
|
+
flex_mode: 'none',
|
|
96
|
+
horizontal_align: 'right',
|
|
97
|
+
columns: [
|
|
98
|
+
{
|
|
99
|
+
tag: 'column',
|
|
100
|
+
width: 'auto',
|
|
101
|
+
elements: [
|
|
102
|
+
{
|
|
103
|
+
tag: 'button',
|
|
104
|
+
text: i18nPlainText(zhT.goAuth, enT.goAuth),
|
|
105
|
+
type: 'primary',
|
|
106
|
+
size: 'medium',
|
|
107
|
+
multi_url: multiUrl,
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
},
|
|
113
|
+
// 失效时间提醒
|
|
114
|
+
{
|
|
115
|
+
tag: 'markdown',
|
|
116
|
+
content: enT.expiresHint(expiresMin),
|
|
117
|
+
i18n_content: i18nContent(zhT.expiresHint(expiresMin), enT.expiresHint(expiresMin)),
|
|
118
|
+
text_size: 'notation',
|
|
119
|
+
},
|
|
120
|
+
// 批量授权提示(仅 auto-auth 流程展示)
|
|
121
|
+
...(showBatchAuthHint
|
|
122
|
+
? [
|
|
123
|
+
{
|
|
124
|
+
tag: 'markdown',
|
|
125
|
+
content: enT.batchAuthHint,
|
|
126
|
+
i18n_content: i18nContent(zhT.batchAuthHint, enT.batchAuthHint),
|
|
127
|
+
text_size: 'notation',
|
|
128
|
+
},
|
|
129
|
+
]
|
|
130
|
+
: []),
|
|
131
|
+
];
|
|
132
|
+
return {
|
|
133
|
+
schema: '2.0',
|
|
134
|
+
config: {
|
|
135
|
+
wide_screen_mode: false,
|
|
136
|
+
...I18N_CONFIG,
|
|
137
|
+
style: {
|
|
138
|
+
color: {
|
|
139
|
+
'light-yellow-bg': {
|
|
140
|
+
light_mode: 'rgba(255, 214, 102, 0.12)',
|
|
141
|
+
dark_mode: 'rgba(255, 214, 102, 0.08)',
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
header: {
|
|
147
|
+
title: i18nPlainText(zhT.authRequired, enT.authRequired),
|
|
148
|
+
subtitle: {
|
|
149
|
+
tag: 'plain_text',
|
|
150
|
+
content: '',
|
|
151
|
+
},
|
|
152
|
+
template: 'blue',
|
|
153
|
+
padding: '12px 12px 12px 12px',
|
|
154
|
+
icon: {
|
|
155
|
+
tag: 'standard_icon',
|
|
156
|
+
token: 'lock-chat_filled',
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
body: { elements },
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/** scope 字符串 → 可读描述(支持多语言) */
|
|
163
|
+
export function formatScopeDescription(locale, params) {
|
|
164
|
+
const { scope, isBatchAuth, totalAppScopes, alreadyGranted, batchInfo } = params;
|
|
165
|
+
const t = CARD_TEXTS[locale];
|
|
166
|
+
const scopes = scope?.split(/\s+/).filter(Boolean);
|
|
167
|
+
if (isBatchAuth && scopes && scopes.length > 0) {
|
|
168
|
+
let message = t.batchScopeMsg(scopes.length, totalAppScopes ?? 0, alreadyGranted ?? 0);
|
|
169
|
+
if (scopes.length > 5) {
|
|
170
|
+
const previewScopes = scopes.slice(0, 3).join('\n');
|
|
171
|
+
message += `\n\n${t.scopePreviewLabel}:\n${previewScopes}\n...\n`;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
const scopeList = scopes.map((s, idx) => `${idx + 1}. ${s}`).join('\n');
|
|
175
|
+
message += `\n\n${t.scopeListLabel}:\n${scopeList}\n`;
|
|
176
|
+
}
|
|
177
|
+
if (batchInfo) {
|
|
178
|
+
message += `\n\n${batchInfo}`;
|
|
179
|
+
}
|
|
180
|
+
return message;
|
|
181
|
+
}
|
|
182
|
+
if (!scopes?.length)
|
|
183
|
+
return t.scopeDesc;
|
|
184
|
+
return t.scopeDesc + '\n\n' + t.requiredScopes + '\n' + scopes.map((s) => `- ${s}`).join('\n');
|
|
185
|
+
}
|
|
186
|
+
export function toInAppWebUrl(targetUrl, brand) {
|
|
187
|
+
const encoded = encodeURIComponent(targetUrl);
|
|
188
|
+
const lkMeta = encodeURIComponent(JSON.stringify({
|
|
189
|
+
'page-meta': {
|
|
190
|
+
showNavBar: 'false',
|
|
191
|
+
showBottomNavBar: 'false',
|
|
192
|
+
},
|
|
193
|
+
}));
|
|
194
|
+
return (`${applinkDomain(brand)}/client/web_url/open` +
|
|
195
|
+
`?mode=sidebar-semi&max_width=800&reload=false&url=${encoded}&lk_meta=${lkMeta}`);
|
|
196
|
+
}
|
|
197
|
+
export function buildAuthSuccessCard(brand) {
|
|
198
|
+
const zhT = CARD_TEXTS.zh_cn;
|
|
199
|
+
const enT = CARD_TEXTS.en_us;
|
|
200
|
+
const brandZh = brand === 'lark' ? 'Lark' : '飞书';
|
|
201
|
+
const brandEn = brand === 'lark' ? 'Lark' : 'Feishu';
|
|
202
|
+
return {
|
|
203
|
+
schema: '2.0',
|
|
204
|
+
config: {
|
|
205
|
+
wide_screen_mode: false,
|
|
206
|
+
...I18N_CONFIG,
|
|
207
|
+
style: {
|
|
208
|
+
color: {
|
|
209
|
+
'light-green-bg': {
|
|
210
|
+
light_mode: 'rgba(52, 199, 89, 0.12)',
|
|
211
|
+
dark_mode: 'rgba(52, 199, 89, 0.08)',
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
header: {
|
|
217
|
+
title: i18nPlainText(zhT.authSuccess, enT.authSuccess),
|
|
218
|
+
subtitle: {
|
|
219
|
+
tag: 'plain_text',
|
|
220
|
+
content: '',
|
|
221
|
+
},
|
|
222
|
+
template: 'green',
|
|
223
|
+
padding: '12px 12px 12px 12px',
|
|
224
|
+
icon: {
|
|
225
|
+
tag: 'standard_icon',
|
|
226
|
+
token: 'yes_filled',
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
body: {
|
|
230
|
+
elements: [
|
|
231
|
+
{
|
|
232
|
+
tag: 'markdown',
|
|
233
|
+
content: enT.authSuccessBody(brandEn),
|
|
234
|
+
i18n_content: i18nContent(zhT.authSuccessBody(brandZh), enT.authSuccessBody(brandEn)),
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
export function buildAuthFailedCard(_reason) {
|
|
241
|
+
const zhT = CARD_TEXTS.zh_cn;
|
|
242
|
+
const enT = CARD_TEXTS.en_us;
|
|
243
|
+
return {
|
|
244
|
+
schema: '2.0',
|
|
245
|
+
config: {
|
|
246
|
+
wide_screen_mode: false,
|
|
247
|
+
...I18N_CONFIG,
|
|
248
|
+
style: {
|
|
249
|
+
color: {
|
|
250
|
+
'light-grey-bg': {
|
|
251
|
+
light_mode: 'rgba(142, 142, 147, 0.12)',
|
|
252
|
+
dark_mode: 'rgba(142, 142, 147, 0.08)',
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
header: {
|
|
258
|
+
title: i18nPlainText(zhT.authIncomplete, enT.authIncomplete),
|
|
259
|
+
subtitle: {
|
|
260
|
+
tag: 'plain_text',
|
|
261
|
+
content: '',
|
|
262
|
+
},
|
|
263
|
+
template: 'yellow',
|
|
264
|
+
padding: '12px 12px 12px 12px',
|
|
265
|
+
icon: {
|
|
266
|
+
tag: 'standard_icon',
|
|
267
|
+
token: 'warning_filled',
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
body: {
|
|
271
|
+
elements: [
|
|
272
|
+
{
|
|
273
|
+
tag: 'markdown',
|
|
274
|
+
content: enT.authExpiredBody,
|
|
275
|
+
i18n_content: i18nContent(zhT.authExpiredBody, enT.authExpiredBody),
|
|
276
|
+
},
|
|
277
|
+
],
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
export function buildAuthIdentityMismatchCard(brand) {
|
|
282
|
+
const zhT = CARD_TEXTS.zh_cn;
|
|
283
|
+
const enT = CARD_TEXTS.en_us;
|
|
284
|
+
const brandZh = brand === 'lark' ? 'Lark' : '飞书';
|
|
285
|
+
const brandEn = brand === 'lark' ? 'Lark' : 'Feishu';
|
|
286
|
+
return {
|
|
287
|
+
schema: '2.0',
|
|
288
|
+
config: {
|
|
289
|
+
wide_screen_mode: false,
|
|
290
|
+
...I18N_CONFIG,
|
|
291
|
+
},
|
|
292
|
+
header: {
|
|
293
|
+
title: i18nPlainText(zhT.authMismatchTitle, enT.authMismatchTitle),
|
|
294
|
+
subtitle: {
|
|
295
|
+
tag: 'plain_text',
|
|
296
|
+
content: '',
|
|
297
|
+
},
|
|
298
|
+
template: 'red',
|
|
299
|
+
padding: '12px 12px 12px 12px',
|
|
300
|
+
icon: {
|
|
301
|
+
tag: 'standard_icon',
|
|
302
|
+
token: 'close_filled',
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
body: {
|
|
306
|
+
elements: [
|
|
307
|
+
{
|
|
308
|
+
tag: 'markdown',
|
|
309
|
+
content: enT.authMismatchBody(brandEn),
|
|
310
|
+
i18n_content: i18nContent(zhT.authMismatchBody(brandZh), enT.authMismatchBody(brandEn)),
|
|
311
|
+
},
|
|
312
|
+
],
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
}
|