@modesto_ma/dsh-channels 0.5.0-beta.4 → 0.5.0-beta.6
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/README.md +49 -28
- package/docs/attachment-pipeline-v2.md +1 -1
- package/docs/feishu-onboarding.md +6 -5
- package/lib/client.js +1874 -1510
- package/lib/client.js.map +1 -1
- package/lib/index.js +736 -353
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
- package/src/client/api.ts +45 -2
- package/src/client/avatar.tsx +36 -0
- package/src/client/icon.tsx +25 -0
- package/src/client/index.ts +78 -23
- package/src/client/number-field.ts +97 -0
- package/src/client/origin-cache.ts +45 -0
- package/src/client/origin.tsx +201 -0
- package/src/client/panel/access-tab.tsx +90 -21
- package/src/client/panel/advanced-tab.tsx +59 -68
- package/src/client/panel/connection-tab.tsx +147 -164
- package/src/client/panel/credentials-card.tsx +124 -87
- package/src/client/panel/fields-tab.tsx +27 -0
- package/src/client/panel/index.tsx +77 -54
- package/src/client/panel/profiles.ts +73 -0
- package/src/client/panel/shared.tsx +358 -253
- package/src/client/panel/whitelist.tsx +203 -0
- package/src/client/panel/wiki-tab.tsx +33 -39
- package/src/client/styles.ts +132 -92
- package/src/domain.ts +42 -0
- package/src/feishu/scopes.ts +2 -1
- package/src/feishu-channel.ts +87 -0
- package/src/index.ts +1 -1
- package/src/routing/inbound.ts +13 -5
- package/src/service.ts +146 -3
- package/src/session/routes.ts +45 -4
- package/src/settings/contract.ts +265 -152
- package/src/settings/routes.ts +47 -0
- package/src/settings/surface.ts +201 -197
- package/src/client/panel/access-card.tsx +0 -329
- package/src/client/panel/analyze-token-card.tsx +0 -70
- package/src/client/panel/model-tab.tsx +0 -23
- package/src/client/panel/sessions-tab.tsx +0 -24
- package/src/client/panel/workspace-tab.tsx +0 -24
package/src/settings/contract.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Web 设置面板的线上契约:Host 半侧的路由/面板数据与 Browser 半侧的渲染共用。
|
|
3
3
|
*
|
|
4
4
|
* 本模块**没有运行时依赖**:Host 与 Client bundle 都直接内联它。因此这里只放
|
|
5
|
-
*
|
|
5
|
+
* 常量、字段清单、可序列化的 wire 类型与无依赖的纯文案函数,不 import zod / node / DSH 内部包。
|
|
6
6
|
*
|
|
7
7
|
* @module dsh-channels/settings/contract
|
|
8
8
|
*/
|
|
@@ -38,6 +38,71 @@ export const ACCESS_REQUESTS_ROUTE = '/dsh-channels/access/requests'
|
|
|
38
38
|
* [`EditableFieldWire.browse`],保留手写输入。
|
|
39
39
|
*/
|
|
40
40
|
export const PICK_DIRECTORY_ROUTE = '/dsh-channels/pick-directory'
|
|
41
|
+
/** 会话的飞书来源(GET/HEAD,`?sessionId=`):对话右侧栏「飞书来源」标签与会话头部入口使用。 */
|
|
42
|
+
export const SESSION_ORIGIN_ROUTE = '/dsh-channels/session-origin'
|
|
43
|
+
|
|
44
|
+
/** Where one Feishu-routed Session came from; names are resolved live and may be absent. */
|
|
45
|
+
export interface SessionOriginWire {
|
|
46
|
+
sessionId: string
|
|
47
|
+
/** `p2p` = 私聊,`group` = 群聊。 */
|
|
48
|
+
chatType: 'p2p' | 'group'
|
|
49
|
+
/** `thread` = 话题内会话,`chat` = 整个聊天一个会话(话题不可用时的降级)。 */
|
|
50
|
+
kind: 'thread' | 'chat'
|
|
51
|
+
chatId: string
|
|
52
|
+
/** 群名(群聊且能读取群信息时)。 */
|
|
53
|
+
chatName?: string
|
|
54
|
+
/** 群头像 URL(群聊且能读取群信息时)。 */
|
|
55
|
+
chatAvatarUrl?: string
|
|
56
|
+
/** 发起人 user_id(日志平台分析话题为请求人)。 */
|
|
57
|
+
senderUserId: string
|
|
58
|
+
/** 发起人姓名(通讯录或群成员列表能查到时)。 */
|
|
59
|
+
senderName?: string
|
|
60
|
+
/** 发起人头像 URL(通讯录能查到时)。 */
|
|
61
|
+
senderAvatarUrl?: string
|
|
62
|
+
/** 日志平台分析话题:群内成员都可以继续。 */
|
|
63
|
+
shared: boolean
|
|
64
|
+
/** Epoch ms when the Session was bound to its Feishu route. */
|
|
65
|
+
createdAt: number
|
|
66
|
+
/** Whether the Feishu route still points at this Session (false after `/renew`, `/new` or route expiry). */
|
|
67
|
+
bound: boolean
|
|
68
|
+
/** Epoch ms of the route's last activity, while bound. */
|
|
69
|
+
lastActivityAt?: number
|
|
70
|
+
/** 在飞书客户端打开该聊天的链接。 */
|
|
71
|
+
chatLink: string
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* `GET PROFILES_ROUTE?users=<user_id,...>&chats=<chat_id,...>`: live Feishu
|
|
76
|
+
* names and avatars for the users and chats the panel shows. At most
|
|
77
|
+
* {@link PROFILES_MAX_IDS} ids per list.
|
|
78
|
+
*/
|
|
79
|
+
export const PROFILES_ROUTE = '/dsh-channels/profiles'
|
|
80
|
+
|
|
81
|
+
/** Most `user_id`s, and separately most `chat_id`s, one profiles request may name. */
|
|
82
|
+
export const PROFILES_MAX_IDS = 200
|
|
83
|
+
|
|
84
|
+
/** Display name and avatar of one Feishu user or chat. */
|
|
85
|
+
export interface FeishuProfileWire {
|
|
86
|
+
name?: string
|
|
87
|
+
/** `https:` image URL on the Feishu CDN. */
|
|
88
|
+
avatarUrl?: string
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* `GET PROFILES_ROUTE` response. Ids Feishu could not resolve, and ids that
|
|
93
|
+
* are not valid Feishu ids, are absent; `warning` carries the Feishu reason
|
|
94
|
+
* when a lookup failed (typically a missing scope).
|
|
95
|
+
*/
|
|
96
|
+
export interface FeishuProfilesWire {
|
|
97
|
+
users: Record<string, FeishuProfileWire>
|
|
98
|
+
chats: Record<string, FeishuProfileWire>
|
|
99
|
+
warning?: string
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** `GET SESSION_ORIGIN_ROUTE` response: `origin` is null for a Session not started from Feishu. */
|
|
103
|
+
export interface SessionOriginResponse {
|
|
104
|
+
origin: SessionOriginWire | null
|
|
105
|
+
}
|
|
41
106
|
|
|
42
107
|
/**
|
|
43
108
|
* 可由 Web 面板覆盖的配置项。顶层键对应 `src/config.ts` 的字段;`feishuTools.*`
|
|
@@ -52,52 +117,62 @@ export const PICK_DIRECTORY_ROUTE = '/dsh-channels/pick-directory'
|
|
|
52
117
|
* `baseDir`(工作区根目录 = 模型/工具产生文件的落点)可覆盖,但面板只接受
|
|
53
118
|
* **绝对路径**(`~` 会展开);已有 Session / 目录不迁移,只影响之后新建的
|
|
54
119
|
* 会话。校验与保存时建目录见 `src/workspaces.ts`。
|
|
120
|
+
*
|
|
121
|
+
* 数组顺序就是面板里同一分组内字段的显示顺序。
|
|
55
122
|
*/
|
|
56
123
|
export const EDITABLE_KEYS = [
|
|
57
|
-
//
|
|
58
|
-
'baseDir',
|
|
59
|
-
// 行为
|
|
124
|
+
// 会话:触发
|
|
60
125
|
'dmMode',
|
|
61
126
|
'requireMention',
|
|
62
127
|
'threadFallback',
|
|
128
|
+
// 会话:工作区
|
|
129
|
+
'baseDir',
|
|
130
|
+
'topicIsolation',
|
|
131
|
+
// 会话:话题与卡片
|
|
132
|
+
'routeTtlMs',
|
|
133
|
+
'approvalTimeoutMs',
|
|
134
|
+
'questionTimeoutMs',
|
|
135
|
+
'refreshMs',
|
|
136
|
+
'statusRefreshMs',
|
|
137
|
+
// 会话:飞书侧功能
|
|
63
138
|
'welcomeOnboarding',
|
|
64
139
|
'slashCommandPanel',
|
|
65
140
|
'allowPermissionSwitch',
|
|
66
|
-
//
|
|
67
|
-
'
|
|
68
|
-
|
|
69
|
-
'
|
|
70
|
-
'
|
|
71
|
-
'
|
|
72
|
-
//
|
|
141
|
+
// 模型
|
|
142
|
+
'provider',
|
|
143
|
+
'model',
|
|
144
|
+
'reasoningEffort',
|
|
145
|
+
'maxTokens',
|
|
146
|
+
'agentPreset',
|
|
147
|
+
// 附件(v2 管线)
|
|
73
148
|
'acceptAttachments',
|
|
74
149
|
'attachmentStore',
|
|
75
150
|
'prefetchImages',
|
|
151
|
+
'historyBootstrapLimit',
|
|
152
|
+
// 模型工具(`feishuTools.*` 是嵌套配置,覆盖层仍写成嵌套对象)
|
|
153
|
+
'feishuTools.attachmentFetch',
|
|
154
|
+
'feishuTools.topicMessages',
|
|
155
|
+
'feishuTools.sendFile',
|
|
156
|
+
// 限额与超时
|
|
76
157
|
'prefetchTimeoutMs',
|
|
77
158
|
'prefetchImageMaxBytes',
|
|
78
159
|
'prefetchTotalMaxBytes',
|
|
79
|
-
'historyBootstrapLimit',
|
|
80
|
-
// 模型工具(feishuTools 子项)
|
|
81
|
-
'feishuTools.attachmentFetch',
|
|
82
160
|
'feishuTools.attachmentFetchMaxResources',
|
|
83
161
|
'feishuTools.attachmentFetchMaxBytes',
|
|
84
162
|
'feishuTools.attachmentFetchTimeoutMs',
|
|
85
|
-
'feishuTools.topicMessages',
|
|
86
163
|
'feishuTools.topicMessagesTimeoutMs',
|
|
87
|
-
'
|
|
164
|
+
'promptContextTimeoutMs',
|
|
165
|
+
// 准入与授权(白名单由「访问授权」tab 的列表管理)
|
|
166
|
+
'accessMode',
|
|
167
|
+
'adminUserId',
|
|
168
|
+
'authRequestTtlDays',
|
|
169
|
+
// 知识库(顶层 `wikiRoots` 字符串列表;为空时不挂载任何知识库工具)
|
|
88
170
|
'feishuTools.wikiRead',
|
|
89
171
|
'feishuTools.wikiWrite',
|
|
90
|
-
// 知识库范围(顶层 `wikiRoots` 字符串列表;为空时不挂载任何知识库工具)
|
|
91
172
|
'wikiRoots',
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
'model',
|
|
96
|
-
'reasoningEffort',
|
|
97
|
-
'agentPreset',
|
|
98
|
-
// 流式卡片
|
|
99
|
-
'refreshMs',
|
|
100
|
-
'statusRefreshMs',
|
|
173
|
+
// 日志平台分析接口(访问令牌是凭据引用 analyzeToken,值写在 DSH 凭据里)
|
|
174
|
+
'analyzeListen',
|
|
175
|
+
// 日志
|
|
101
176
|
'loggerLevel',
|
|
102
177
|
] as const
|
|
103
178
|
|
|
@@ -140,7 +215,19 @@ export type StringListItemFormat = 'wiki-root-link'
|
|
|
140
215
|
* panel tab (see {@link TAB_FIELD_GROUPS}); the Host is the source of truth for
|
|
141
216
|
* which key belongs to which group.
|
|
142
217
|
*/
|
|
143
|
-
export type FieldGroup =
|
|
218
|
+
export type FieldGroup =
|
|
219
|
+
| 'trigger'
|
|
220
|
+
| 'workspace'
|
|
221
|
+
| 'cards'
|
|
222
|
+
| 'features'
|
|
223
|
+
| 'model'
|
|
224
|
+
| 'attachments'
|
|
225
|
+
| 'tools'
|
|
226
|
+
| 'limits'
|
|
227
|
+
| 'access'
|
|
228
|
+
| 'wiki'
|
|
229
|
+
| 'analyze'
|
|
230
|
+
| 'logging'
|
|
144
231
|
|
|
145
232
|
/** One selectable value rendered by the generic form. */
|
|
146
233
|
export interface FieldOptionWire {
|
|
@@ -148,14 +235,38 @@ export interface FieldOptionWire {
|
|
|
148
235
|
label: string
|
|
149
236
|
}
|
|
150
237
|
|
|
238
|
+
/**
|
|
239
|
+
* A two-value `select` rendered as a switch: `on` is the value stored while
|
|
240
|
+
* the switch is on, `off` while it is off. Both are members of `options`.
|
|
241
|
+
*/
|
|
242
|
+
export interface FieldToggleWire {
|
|
243
|
+
on: string
|
|
244
|
+
off: string
|
|
245
|
+
}
|
|
246
|
+
|
|
151
247
|
/** One editable row, fully described by the Host so the client stays schema-free. */
|
|
152
248
|
export interface EditableFieldWire {
|
|
153
249
|
key: EditableKey
|
|
154
250
|
label: string
|
|
155
251
|
kind: FieldKind
|
|
156
252
|
group: FieldGroup
|
|
253
|
+
/** One-line description always shown under the label. */
|
|
254
|
+
summary?: string
|
|
255
|
+
/** Longer explanation, collapsed behind the row's「详情」link. */
|
|
157
256
|
help?: string
|
|
158
257
|
options?: readonly FieldOptionWire[]
|
|
258
|
+
/** `select` only: render the two options as a switch. */
|
|
259
|
+
toggle?: FieldToggleWire
|
|
260
|
+
/**
|
|
261
|
+
* `number` only: display unit next to the input. With `scale`, the input
|
|
262
|
+
* shows `stored / scale` and the panel submits `round(input * scale)`;
|
|
263
|
+
* `min` / `max` / `step` stay in stored units.
|
|
264
|
+
*/
|
|
265
|
+
unit?: string
|
|
266
|
+
/** `number` only: stored units per displayed unit (e.g. 1000 for 秒 over ms). */
|
|
267
|
+
scale?: number
|
|
268
|
+
/** `number` only: an empty input clears the override instead of failing. */
|
|
269
|
+
optional?: boolean
|
|
159
270
|
/** Selector is not editable yet (e.g. pick the provider before the model). */
|
|
160
271
|
disabled?: boolean
|
|
161
272
|
min?: number
|
|
@@ -167,7 +278,7 @@ export interface EditableFieldWire {
|
|
|
167
278
|
maxItems?: number
|
|
168
279
|
/** `string-list` only: format every non-empty entry must satisfy. */
|
|
169
280
|
itemFormat?: StringListItemFormat
|
|
170
|
-
/** Render across the
|
|
281
|
+
/** Render the control below the label across the row width (paths, lists). */
|
|
171
282
|
wide?: boolean
|
|
172
283
|
/**
|
|
173
284
|
* `directory`:给这个 text 字段加一个「选择目录…」按钮,点击后由 Host
|
|
@@ -218,14 +329,6 @@ export interface CatalogWire {
|
|
|
218
329
|
export type ConfigValue = string | number | boolean | readonly string[]
|
|
219
330
|
export type EditableValues = Partial<Record<EditableKey, ConfigValue>>
|
|
220
331
|
|
|
221
|
-
/** Read-only facts shown in the advanced card. */
|
|
222
|
-
export interface ReadOnlyFieldWire {
|
|
223
|
-
key: string
|
|
224
|
-
label: string
|
|
225
|
-
value: string
|
|
226
|
-
help?: string
|
|
227
|
-
}
|
|
228
|
-
|
|
229
332
|
/** One credential reference plus its Host-side state (values never cross the wire). */
|
|
230
333
|
export interface CredentialRefWire {
|
|
231
334
|
ref: string
|
|
@@ -344,7 +447,6 @@ export interface PanelConfigWire {
|
|
|
344
447
|
/** 与当前运行中连接不一致、需重连才生效的字段。 */
|
|
345
448
|
restartPendingKeys: EditableKey[]
|
|
346
449
|
fields: EditableFieldWire[]
|
|
347
|
-
readOnly: ReadOnlyFieldWire[]
|
|
348
450
|
credentials: {
|
|
349
451
|
appId: CredentialRefWire
|
|
350
452
|
appSecret: CredentialRefWire
|
|
@@ -530,9 +632,9 @@ export type ClearCredentialResponse =
|
|
|
530
632
|
*/
|
|
531
633
|
export const PANEL_TABS = [
|
|
532
634
|
{ id: 'connection', label: '连接' },
|
|
533
|
-
{ id: 'sessions', label: '
|
|
635
|
+
{ id: 'sessions', label: '会话' },
|
|
534
636
|
{ id: 'model', label: '模型' },
|
|
535
|
-
{ id: '
|
|
637
|
+
{ id: 'attachments', label: '附件与工具' },
|
|
536
638
|
{ id: 'access', label: '访问授权' },
|
|
537
639
|
{ id: 'wiki', label: '知识库' },
|
|
538
640
|
{ id: 'advanced', label: '高级' },
|
|
@@ -540,92 +642,91 @@ export const PANEL_TABS = [
|
|
|
540
642
|
|
|
541
643
|
export type PanelTabId = (typeof PANEL_TABS)[number]['id']
|
|
542
644
|
|
|
543
|
-
/** Which editable field groups each tab renders
|
|
645
|
+
/** Which editable field groups each tab renders, in section order. */
|
|
544
646
|
export const TAB_FIELD_GROUPS: Readonly<Record<PanelTabId, readonly FieldGroup[]>> = {
|
|
545
647
|
connection: [],
|
|
546
|
-
sessions: ['
|
|
648
|
+
sessions: ['trigger', 'workspace', 'cards', 'features'],
|
|
547
649
|
model: ['model'],
|
|
548
|
-
|
|
650
|
+
attachments: ['attachments', 'tools', 'limits'],
|
|
549
651
|
access: ['access'],
|
|
550
652
|
wiki: ['wiki'],
|
|
551
|
-
advanced: ['
|
|
653
|
+
advanced: ['analyze', 'logging'],
|
|
552
654
|
}
|
|
553
655
|
|
|
554
656
|
/** Section heading for one field group inside its tab. */
|
|
555
657
|
export const FIELD_GROUP_LABELS: Readonly<Record<FieldGroup, string>> = {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
model: '
|
|
561
|
-
|
|
562
|
-
|
|
658
|
+
trigger: '触发',
|
|
659
|
+
workspace: '工作区',
|
|
660
|
+
cards: '话题与卡片',
|
|
661
|
+
features: '飞书侧功能',
|
|
662
|
+
model: '模型',
|
|
663
|
+
attachments: '入站附件',
|
|
664
|
+
tools: '模型可用的飞书工具',
|
|
665
|
+
limits: '限额与超时',
|
|
666
|
+
access: '准入',
|
|
563
667
|
wiki: '知识库工具',
|
|
668
|
+
analyze: '日志分析接口',
|
|
669
|
+
logging: '日志',
|
|
564
670
|
}
|
|
565
671
|
|
|
672
|
+
/** Groups rendered collapsed behind one summary row (rarely changed values). */
|
|
673
|
+
export const COLLAPSED_FIELD_GROUPS: readonly FieldGroup[] = ['limits']
|
|
674
|
+
|
|
675
|
+
/** `unit` of byte-count fields; the panel adds a MiB reading next to them. */
|
|
676
|
+
export const BYTES_UNIT = '字节'
|
|
677
|
+
|
|
566
678
|
/** Display labels for the panel header/cards (kept on the wire so the client owns no copy). */
|
|
567
679
|
export const PANEL_COPY = {
|
|
568
680
|
title: '飞书渠道',
|
|
569
|
-
description: '飞书长连接、应用凭据与渠道配置。凭据只写入 DSH 凭据库且不回显;标注「需重连」的项在连接建立时读取。',
|
|
570
681
|
// ---- lifecycle / status -------------------------------------------------
|
|
571
|
-
statusCard: '连接状态',
|
|
572
682
|
phaseUnconfigured: '待配置',
|
|
573
683
|
phaseIdle: '未连接',
|
|
574
684
|
phaseConnecting: '连接中',
|
|
575
685
|
phaseConnected: '已连接',
|
|
576
686
|
phaseError: '连接失败',
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
statusSummaryError: '最近一次连接飞书失败,请检查凭据与网络后重试。',
|
|
687
|
+
statusSummaryConnected: '机器人在线,可以收发消息',
|
|
688
|
+
statusSummaryUnconfigured: '还没有填写飞书应用凭据,插件不会连接飞书',
|
|
689
|
+
statusSummaryIdle: '凭据已就绪,还没有建立连接',
|
|
690
|
+
statusSummaryConnecting: '正在连接飞书…',
|
|
691
|
+
statusSummaryError: '连接飞书失败,请检查凭据与网络后重试',
|
|
692
|
+
uptimePrefix: '运行',
|
|
584
693
|
lastError: '最近一次连接失败',
|
|
585
|
-
|
|
586
|
-
scopeCheckOk: '
|
|
587
|
-
scopeCheckMissing: '
|
|
588
|
-
|
|
694
|
+
checksTitle: '自检',
|
|
695
|
+
scopeCheckOk: '插件需要的飞书权限都已开通',
|
|
696
|
+
scopeCheckMissing: '{n} 项权限未开通',
|
|
697
|
+
scopeCheckMissingRequired: '{n} 项必需权限未开通,相关功能无法使用',
|
|
698
|
+
scopeCheckMissingOptional: '不影响收发消息,只有相关功能不可用。开通后需在开发者后台发布新版本。',
|
|
699
|
+
scopeCheckPublish: '开通后需在开发者后台发布新版本。',
|
|
700
|
+
scopeCheckOpenAll: '全部开通',
|
|
589
701
|
scopeCheckOpenOne: '去开通',
|
|
590
|
-
scopeCheckOptional: '可选',
|
|
591
702
|
scopeCheckRequired: '必需',
|
|
592
|
-
scopeCheckError: '
|
|
703
|
+
scopeCheckError: '无法读取权限开通情况',
|
|
593
704
|
slashCommandSyncTitle: '斜杠指令面板',
|
|
594
|
-
slashCommandSyncOk: '
|
|
595
|
-
|
|
596
|
-
slashCommandSyncCreated: '本次新增',
|
|
597
|
-
slashCommandSyncUpdated: '本次更新',
|
|
598
|
-
slashCommandSyncRemoved: '本次删除',
|
|
599
|
-
slashCommandSyncError: '同步飞书原生斜杠指令面板失败(不影响直接输入命令):',
|
|
705
|
+
slashCommandSyncOk: '已同步 {total} 条命令,飞书客户端约 5 分钟后刷新',
|
|
706
|
+
slashCommandSyncError: '同步失败,直接输入命令不受影响',
|
|
600
707
|
missingConfig: '缺少配置',
|
|
601
|
-
statusHintUnconfigured: '配置完成后插件会自动连接;也可以稍后在本页手动连接。',
|
|
602
|
-
connectionInfo: '连接信息',
|
|
603
|
-
connectionStateLabel: '飞书长连接',
|
|
604
|
-
botOpenId: 'Bot open_id',
|
|
605
|
-
uptime: '运行时长',
|
|
606
708
|
routeCount: '话题路由',
|
|
607
709
|
liveAgentCount: '活动会话',
|
|
608
710
|
inflightTurnCount: '在途回复',
|
|
711
|
+
botOpenId: 'Bot open_id',
|
|
609
712
|
healthReasons: '健康判定',
|
|
610
713
|
unknownValue: '—',
|
|
611
714
|
connect: '连接飞书',
|
|
612
715
|
connecting: '连接中…',
|
|
613
716
|
// ---- onboarding ---------------------------------------------------------
|
|
614
717
|
onboardingTitle: '开始使用飞书渠道',
|
|
615
|
-
onboardingIntro: '只需三步:在飞书开放平台创建自建应用,把 App ID / App Secret 填入本页,保存后自动连接。',
|
|
616
718
|
onboardingStep1Title: '创建飞书自建应用',
|
|
617
|
-
onboardingStep1Text: '
|
|
719
|
+
onboardingStep1Text: '在 open.feishu.cn/app 创建企业自建应用,开启机器人能力;事件订阅选「长连接」,订阅 im.message.receive_v1。',
|
|
618
720
|
onboardingStep2Title: '填写应用凭据',
|
|
619
|
-
onboardingStep2Text: '
|
|
620
|
-
onboardingStep3Title: '
|
|
621
|
-
onboardingStep3Text: '
|
|
622
|
-
onboardingDocsHint: '开放平台地址:open.feishu.cn/app;应用需要开通 im:message、im:message:send_as_bot 等消息权限。',
|
|
721
|
+
onboardingStep2Text: '把 App ID(cli_ 开头)和 App Secret 填到下方「应用凭据」。',
|
|
722
|
+
onboardingStep3Title: '保存后自动连接',
|
|
723
|
+
onboardingStep3Text: '两项都保存后插件会自动连接,状态变成「已连接」就能在飞书里私聊机器人。',
|
|
623
724
|
// ---- credentials --------------------------------------------------------
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
appIdLabel: '
|
|
627
|
-
appSecretLabel: '
|
|
628
|
-
|
|
725
|
+
credentialsTitle: '应用凭据',
|
|
726
|
+
credentialsHint: '值只存在本机凭据库,面板不回显。',
|
|
727
|
+
appIdLabel: 'App ID',
|
|
728
|
+
appSecretLabel: 'App Secret',
|
|
729
|
+
credentialStore: '凭据库',
|
|
629
730
|
saveCredentials: '保存凭据',
|
|
630
731
|
savingCredentials: '保存中…',
|
|
631
732
|
credentialSaved: '凭据已保存',
|
|
@@ -635,28 +736,30 @@ export const PANEL_COPY = {
|
|
|
635
736
|
credentialAutoConnectFailed: '凭据已保存,但自动连接失败',
|
|
636
737
|
credentialRemoved: '已移除存储的凭据',
|
|
637
738
|
credentialRemovedPending: '已移除存储的凭据,重启飞书连接后生效',
|
|
638
|
-
|
|
739
|
+
replaceCredential: '更换',
|
|
740
|
+
setCredential: '设置',
|
|
741
|
+
cancel: '取消',
|
|
742
|
+
removeCredential: '移除',
|
|
639
743
|
removingCredential: '移除中…',
|
|
640
744
|
credentialConfigured: '已配置',
|
|
641
745
|
credentialMissing: '未配置',
|
|
642
746
|
credentialReadOnly: '当前凭据存储不可写',
|
|
643
747
|
appIdPlaceholder: '输入 App ID(cli_…)',
|
|
644
748
|
appSecretPlaceholder: '输入 App Secret',
|
|
645
|
-
|
|
646
|
-
// ----
|
|
647
|
-
|
|
648
|
-
sessionsTabHelp: '私聊、群聊触发方式与入站内容:附件存储/预取、模型工具开关与读取预算;「需重连」项在下次连接时读取。',
|
|
649
|
-
modelTabHelp: '飞书会话使用的模型服务商、模型、推理档位与 Agent 预设;下拉选项来自宿主机实时目录,保存后对新会话生效。',
|
|
650
|
-
workspaceTabHelp: '每个用户一个工作区(模型/工具产生文件的落点),每个话题在其中拥有独立工作目录;只影响之后新建的话题。入站附件默认存于 DSH 原生附件库,不占用话题目录。插件不会自动删除工作区或话题目录;过期目录可手动删除,话题下次对话时会重建空目录。',
|
|
651
|
-
accessTabHelp: '准入采用 fail-closed:管理员不受白名单限制,非管理员私聊会被拒绝,群聊需要「群已授权 + 用户在白名单」两层同时命中。',
|
|
652
|
-
wikiTabHelp: '知识库工具以应用身份访问「知识库范围」内的文档、电子表格和多维表格。只有管理员或知识库白名单里的用户发起的话题能用;每次打开、新建、修改仍需话题发起人在授权卡上确认。',
|
|
653
|
-
advancedTabHelp: '流式刷新等低层参数、Web 覆盖文件与只读信息。',
|
|
654
|
-
save: '保存更改',
|
|
749
|
+
credentialRemoveConfirm: '确定移除已存储的凭据值?移除后不会回显,需要时须重新填写。',
|
|
750
|
+
// ---- forms --------------------------------------------------------------
|
|
751
|
+
save: '保存',
|
|
655
752
|
saving: '保存中…',
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
753
|
+
discard: '放弃',
|
|
754
|
+
dirtyCount: '{n} 项未保存',
|
|
755
|
+
dirtyRestart: ',其中 {n} 项需要重连后生效',
|
|
756
|
+
details: '详情',
|
|
757
|
+
expand: '展开',
|
|
758
|
+
collapse: '收起',
|
|
759
|
+
collapsedCount: '{n} 项',
|
|
760
|
+
collapsedClean: '一般不用改',
|
|
761
|
+
collapsedChanged: '{n} 项已在面板修改',
|
|
762
|
+
restartTag: '需重连',
|
|
660
763
|
listAdd: '添加',
|
|
661
764
|
listRemove: '移除',
|
|
662
765
|
listEntry: '第 {n} 项',
|
|
@@ -668,64 +771,61 @@ export const PANEL_COPY = {
|
|
|
668
771
|
directoryPicked: '已选择目录',
|
|
669
772
|
directoryPickFailed: '无法打开系统目录选择器',
|
|
670
773
|
saved: '已保存',
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
774
|
+
saveInvalid: '请先修正标红的配置项',
|
|
775
|
+
numberInvalid: '请输入数字',
|
|
776
|
+
numberMin: '不得小于 {n}',
|
|
777
|
+
numberMax: '不得大于 {n}',
|
|
778
|
+
modelFootnote: '对之后新建的会话生效。',
|
|
779
|
+
catalogFailed: '模型目录加载失败,已退回手填。',
|
|
780
|
+
catalogLoading: '正在读取宿主机选项…',
|
|
781
|
+
catalogUnavailable: '宿主机未提供可选项,请手填。',
|
|
782
|
+
// ---- restart ------------------------------------------------------------
|
|
783
|
+
restartBanner: '以下配置要重启飞书连接后生效:',
|
|
784
|
+
restartWarning: '重启会断开当前飞书连接并中断进行中的回复,确定现在重启?',
|
|
785
|
+
reconnect: '重启连接',
|
|
681
786
|
reconnecting: '重连中…',
|
|
682
|
-
refresh: '
|
|
787
|
+
refresh: '刷新',
|
|
683
788
|
retry: '重试',
|
|
684
789
|
pollFailed: '状态刷新失败',
|
|
685
790
|
connectDone: '已连接飞书',
|
|
686
791
|
reconnectDone: '已重启飞书连接',
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
credentialRemoveConfirm: '确定移除已存储的凭据值?移除后不会回显,需要时须重新填写。',
|
|
691
|
-
analyzeTokenCard: '日志分析接口令牌',
|
|
692
|
-
analyzeTokenCardHelp: '日志平台调用分析接口时 Authorization: Bearer 后面的值。经 DSH 凭据服务写入本机凭据库,面板永不回显;保存或移除后下一次请求即生效,无需重连。未配置时接口对所有请求返回 503。',
|
|
792
|
+
loading: '加载中…',
|
|
793
|
+
loadFailed: '设置面板加载失败',
|
|
794
|
+
// ---- advanced -----------------------------------------------------------
|
|
693
795
|
analyzeTokenLabel: '访问令牌',
|
|
796
|
+
analyzeTokenSummary: '请求头 Authorization: Bearer 的值,保存后立即生效;未配置时接口拒绝所有请求',
|
|
694
797
|
analyzeTokenPlaceholder: '填写新令牌(建议 32 位以上随机串)',
|
|
695
|
-
saveAnalyzeToken: '保存令牌',
|
|
696
798
|
analyzeTokenSaved: '令牌已保存,下一次请求生效',
|
|
697
799
|
analyzeTokenRemoved: '令牌已移除,接口将拒绝所有请求',
|
|
698
|
-
|
|
699
|
-
loading: '加载中…',
|
|
700
|
-
loadFailed: '设置面板加载失败',
|
|
701
|
-
catalogFailed: '模型目录加载失败,已退回手填。',
|
|
702
|
-
catalogLoading: '正在读取宿主机选项…',
|
|
703
|
-
catalogUnavailable: '宿主机未提供可选项,请手填。',
|
|
704
|
-
version: '插件版本',
|
|
800
|
+
overlayTitle: 'Web 覆盖',
|
|
705
801
|
overlayPath: '覆盖文件',
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
802
|
+
overlayCount: '{n} 项配置由面板覆盖',
|
|
803
|
+
noOverrides: '当前没有面板覆盖的配置',
|
|
804
|
+
overlayPathHelp: '面板保存的配置写在这个 JSON 文件里,优先级高于 profile。可以直接编辑;面板保存会整体重写它。',
|
|
805
|
+
clear: '恢复 profile 配置',
|
|
806
|
+
clearing: '恢复中…',
|
|
807
|
+
clearConfirm: '确定删除所有面板覆盖,恢复为 profile 配置?',
|
|
808
|
+
cleared: '已恢复为 profile 配置',
|
|
711
809
|
// ---- access -------------------------------------------------------------
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
810
|
+
debugModeWarning: '调试模式已打开:应用可用范围内的任何人都能和机器人对话。用完请在「访问授权」关闭。',
|
|
811
|
+
accessAdminMissingWarning: '没有可用的管理员,所有对话都会被拒绝。请在下方填写管理员 user_id(私聊机器人发送 /userid 获取)。',
|
|
812
|
+
accessAdminCurrent: '当前管理员',
|
|
813
|
+
accessAdminSourceConfig: '已配置',
|
|
814
|
+
accessAdminSourceOwner: '应用所有者',
|
|
815
|
+
profilesWarning: '部分飞书名字和头像未能读取:{reason}',
|
|
816
|
+
accessNotLoaded: '飞书连接建立后加载授权列表',
|
|
817
|
+
accessRequestsTitle: '待处理申请',
|
|
717
818
|
accessGroupsTitle: '已授权群',
|
|
718
|
-
accessGroupsEmpty: '尚未授权任何群。机器人被拉进群后,管理员会收到带 chat_id 的群信息卡;也可在群内发送 /groupid 获取。',
|
|
719
819
|
accessUsersTitle: '已授权用户',
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
accessGroupChatIdPlaceholder: '群 chat_id(oc_…)',
|
|
820
|
+
accessGroupsEmpty: '还没有授权任何群',
|
|
821
|
+
accessUsersEmpty: '还没有授权任何用户',
|
|
822
|
+
accessGroupChatIdPlaceholder: 'chat_id(oc_…,群里发 /groupid 获取)',
|
|
724
823
|
accessGroupNamePlaceholder: '群名(可选)',
|
|
725
|
-
accessUserIdPlaceholder: '
|
|
824
|
+
accessUserIdPlaceholder: 'user_id(私聊机器人发 /userid 获取)',
|
|
726
825
|
accessUserNamePlaceholder: '昵称(可选)',
|
|
727
826
|
accessAddGroup: '添加群',
|
|
728
827
|
accessAddUser: '添加用户',
|
|
828
|
+
accessAdd: '添加',
|
|
729
829
|
accessRemove: '移除',
|
|
730
830
|
accessAllow: '授权',
|
|
731
831
|
accessDeny: '忽略',
|
|
@@ -733,22 +833,35 @@ export const PANEL_COPY = {
|
|
|
733
833
|
accessSourceCommand: '对话命令',
|
|
734
834
|
accessSourceCard: '授权卡',
|
|
735
835
|
accessSourcePanel: '设置面板',
|
|
736
|
-
accessRequestGroup: '
|
|
737
|
-
accessRequestUser: '
|
|
738
|
-
|
|
739
|
-
accessRequestExpires: '
|
|
836
|
+
accessRequestGroup: '申请授权群',
|
|
837
|
+
accessRequestUser: '申请使用',
|
|
838
|
+
accessRequestIn: '在「{group}」',
|
|
839
|
+
accessRequestExpires: '{date} 前有效',
|
|
740
840
|
accessGroupAdded: '已添加群授权',
|
|
741
841
|
accessGroupRemoved: '已移除群授权',
|
|
742
842
|
accessUserAdded: '已添加用户授权',
|
|
743
843
|
accessUserRemoved: '已移除用户授权',
|
|
744
844
|
accessRequestAllowed: '已授权',
|
|
745
845
|
accessRequestDenied: '已忽略',
|
|
746
|
-
accessHints: '三种授权入口:群内 /auth 命令、入群与用户授权卡、本面板。撤销立即生效;白名单只约束非管理员(管理员在任何私聊/群聊都直接放行),非管理员需要群和用户两层同时命中。',
|
|
747
846
|
// ---- wiki ---------------------------------------------------------------
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
wikiUsersEmpty: '
|
|
847
|
+
wikiUsersTitle: '可使用的人',
|
|
848
|
+
wikiUsersAdminPlus: '管理员 + {n}',
|
|
849
|
+
wikiUsersEmpty: '目前只有管理员发起的话题能用知识库工具',
|
|
850
|
+
wikiUsersHint: '也可以在飞书发 /auth wiki add @用户',
|
|
751
851
|
wikiUserAdded: '已加入知识库白名单',
|
|
752
852
|
wikiUserRemoved: '已移出知识库白名单',
|
|
753
|
-
accessChatIdHint: 'chat_id 可从入群群信息卡或群内 /groupid 获取;user_id 可私聊机器人发送 /userid 获取。',
|
|
754
853
|
} as const
|
|
854
|
+
|
|
855
|
+
/**
|
|
856
|
+
* Fill `{name}` placeholders of one `PANEL_COPY` template.
|
|
857
|
+
*
|
|
858
|
+
* @param template - Copy containing `{name}` placeholders.
|
|
859
|
+
* @param values - Replacement per placeholder name.
|
|
860
|
+
* @returns The filled string; unknown placeholders stay as written.
|
|
861
|
+
*/
|
|
862
|
+
export function fillCopy(template: string, values: Readonly<Record<string, string | number>>): string {
|
|
863
|
+
return template.replace(/\{(\w+)\}/g, (match, name: string) => {
|
|
864
|
+
const value = values[name]
|
|
865
|
+
return value === undefined ? match : String(value)
|
|
866
|
+
})
|
|
867
|
+
}
|