@xmanrui/dsh-im 4.10.0 → 4.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PROACTIVE_DELIVERY.en.md +15 -1
- package/PROACTIVE_DELIVERY.md +15 -1
- package/README.en.md +7 -2
- package/README.md +8 -3
- package/lib/client.js +2341 -1315
- package/lib/index.js +250 -245
- package/package.json +4 -3
- package/plugin-src/client/channel-card-meta.js +9 -1
- package/plugin-src/client/channels/dingtalk/api.js +4 -0
- package/plugin-src/client/channels/dingtalk/index.js +41 -7
- package/plugin-src/client/channels/feishu/api.js +4 -0
- package/plugin-src/client/channels/feishu/group-settings.js +581 -0
- package/plugin-src/client/channels/feishu/index.js +64 -233
- package/plugin-src/client/channels/qq/api.js +4 -0
- package/plugin-src/client/channels/qq/index.js +41 -7
- package/plugin-src/client/channels/shared/collapsible-account.js +80 -0
- package/plugin-src/client/channels/shared/token-api.js +4 -0
- package/plugin-src/client/channels/shared/token-channel.js +62 -29
- package/plugin-src/client/channels/wecom/api.js +4 -0
- package/plugin-src/client/channels/wecom/index.js +41 -7
- package/plugin-src/client/channels/weixin/api.js +4 -0
- package/plugin-src/client/channels/weixin/index.js +41 -7
- package/plugin-src/client/channels/whatsapp/api.js +4 -0
- package/plugin-src/client/channels/whatsapp/index.js +40 -7
- package/plugin-src/client/delivery-settings.js +73 -5
- package/plugin-src/client/i18n.js +22 -0
- package/plugin-src/client/model-setting.js +104 -0
- package/plugin-src/client/styles.js +62 -0
- package/plugin-src/host/channels/dingtalk/production.mjs +3 -0
- package/plugin-src/host/channels/dingtalk/rpc.mjs +11 -0
- package/plugin-src/host/channels/feishu/production.mjs +3 -0
- package/plugin-src/host/channels/feishu/rpc.mjs +16 -0
- package/plugin-src/host/channels/qq/production.mjs +3 -0
- package/plugin-src/host/channels/qq/rpc.mjs +11 -0
- package/plugin-src/host/channels/shared/model-setting-rpc.mjs +19 -0
- package/plugin-src/host/channels/shared/production.mjs +3 -0
- package/plugin-src/host/channels/shared/rpc.mjs +9 -0
- package/plugin-src/host/channels/shared/workspace-rpc.mjs +2 -0
- package/plugin-src/host/channels/slack/production.mjs +3 -0
- package/plugin-src/host/channels/slack/rpc.mjs +9 -0
- package/plugin-src/host/channels/wecom/production.mjs +3 -0
- package/plugin-src/host/channels/wecom/rpc.mjs +11 -0
- package/plugin-src/host/channels/weixin/production.mjs +3 -0
- package/plugin-src/host/channels/weixin/rpc.mjs +11 -0
- package/plugin-src/host/channels/whatsapp/production.mjs +3 -0
- package/plugin-src/host/channels/whatsapp/rpc.mjs +11 -0
- package/plugin-src/host/delivery-adapter.mjs +141 -3
- package/plugin-src/host/delivery-rpc.mjs +12 -0
- package/plugin-src/host/delivery-service.mjs +110 -3
- package/plugin-src/host/delivery-suggestions.mjs +46 -0
- package/plugin-src/host/harness-session-coordinator.mjs +6 -5
- package/plugin-src/host/index.mjs +18 -1
- package/plugin-src/host/session-sync-coordinator.mjs +217 -0
- package/scripts/verify-package.mjs +12 -6
- package/src/channels/shared/bot-workspace-store.mjs +285 -38
- package/src/channels/shared/harness-client.mjs +124 -43
- package/src/channels/shared/i18n-en/wecom.mjs +24 -0
- package/src/channels/shared/model-setting.mjs +110 -0
- package/src/channels/wecom/wecom-bridge.mjs +275 -2
- package/src/channels/wecom/wecom-cards.mjs +101 -0
- package/src/channels/wecom/wecom-runtime.mjs +2 -0
- package/src/channels/whatsapp/whatsapp-runtime.mjs +78 -26
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
|
|
2
|
+
import { normalizeModelCatalog, normalizeModelSelection, SET_MODEL_ENDPOINT } from '../../model-setting.js';
|
|
2
3
|
import { normalizeLastMessageError } from '../../last-message-error.js';
|
|
3
4
|
import { normalizeAccessPolicy } from '../../../../src/channels/shared/access-policy.mjs';
|
|
4
5
|
import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
|
|
@@ -30,6 +31,7 @@ export const TOKEN_BOT_ENDPOINTS = Object.freeze({
|
|
|
30
31
|
reconnectBot: 'bot.reconnect',
|
|
31
32
|
deleteBot: 'bot.delete',
|
|
32
33
|
setWorkspace: 'bot.workspace.set',
|
|
34
|
+
setModel: SET_MODEL_ENDPOINT,
|
|
33
35
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
34
36
|
setContextEnhancement: 'bot.context-enhancement.set',
|
|
35
37
|
setAccessPolicy: 'bot.access-policy.set',
|
|
@@ -60,6 +62,7 @@ export function createTokenChannelApi(channel, connectionSummary, {
|
|
|
60
62
|
connected,
|
|
61
63
|
state: connected ? 'connected' : state,
|
|
62
64
|
workspace: text(value.workspace, '', 4_096),
|
|
65
|
+
model: normalizeModelSelection(value.model),
|
|
63
66
|
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
64
67
|
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
|
|
65
68
|
...(Object.hasOwn(value, 'accessPolicy')
|
|
@@ -97,6 +100,7 @@ export function createTokenChannelApi(channel, connectionSummary, {
|
|
|
97
100
|
bots,
|
|
98
101
|
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
99
102
|
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog),
|
|
103
|
+
modelCatalog: normalizeModelCatalog(source.modelCatalog),
|
|
100
104
|
};
|
|
101
105
|
};
|
|
102
106
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
3
|
import { CredentialActionIcon, CredentialBindingPanel } from '../../credential-binding.js';
|
|
4
|
+
import { CollapsibleAccountSection } from './collapsible-account.js';
|
|
4
5
|
import { h } from '../../i18n.js';
|
|
5
6
|
import { installDingtalkStyles } from '../dingtalk/styles.js';
|
|
6
7
|
import { WorkspaceEditor } from '../../workspace-editor.js';
|
|
@@ -10,6 +11,11 @@ import {
|
|
|
10
11
|
AgentPresetEditor,
|
|
11
12
|
EMPTY_AGENT_PRESET_CATALOG,
|
|
12
13
|
} from '../../agent-preset.js';
|
|
14
|
+
import {
|
|
15
|
+
EMPTY_MODEL_CATALOG,
|
|
16
|
+
ModelCatalogContext,
|
|
17
|
+
ModelEditor,
|
|
18
|
+
} from '../../model-setting.js';
|
|
13
19
|
import { useWorkspaceSnapshotFence } from '../../workspace-snapshot-fence.js';
|
|
14
20
|
import {
|
|
15
21
|
BotSettingsButton,
|
|
@@ -75,7 +81,7 @@ export function createTokenChannelSettings(definition) {
|
|
|
75
81
|
accountSettingsEndpoint = null,
|
|
76
82
|
} = definition;
|
|
77
83
|
|
|
78
|
-
function AccountCard({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onAgentPresetSave, onContextEnhancementSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
|
|
84
|
+
function AccountCard({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onModelSave, onAgentPresetSave, onContextEnhancementSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
|
|
79
85
|
const state = busy === 'reconnect' ? 'connecting' : account.state;
|
|
80
86
|
const tone = account.connected ? 'success' : state === 'error' ? 'error' : 'warning';
|
|
81
87
|
const stateLabel = account.connected ? '运行正常' : state === 'connecting' ? '正在连接' : '连接未就绪';
|
|
@@ -83,32 +89,45 @@ export function createTokenChannelSettings(definition) {
|
|
|
83
89
|
const identity = account.bot.username ? `@${account.bot.username}` : account.bot.idMasked;
|
|
84
90
|
return h('article', { className: 'ddt-card dim-botCard', 'data-bot-id': account.botId },
|
|
85
91
|
h('div', { className: 'ddt-cardBody dim-botCardBody' },
|
|
86
|
-
h(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
92
|
+
h(CollapsibleAccountSection, {
|
|
93
|
+
id: `tok-settings-${account.botId.replace(/[^a-zA-Z0-9_-]/g, '-')}`,
|
|
94
|
+
header: h('div', { className: 'ddt-accountTop dim-botCardTop' },
|
|
95
|
+
h('div', { className: 'ddt-accountIdentity dim-botIdentity' },
|
|
96
|
+
h('div', { className: `ddt-avatar dim-botAvatar ${avatarClass}`, 'aria-hidden': 'true' },
|
|
97
|
+
h(LogoGlyph, { size: 29 })),
|
|
98
|
+
h('div', { className: 'dim-botName' },
|
|
99
|
+
h('h3', null, account.bot.name), h('p', null, identity))),
|
|
100
|
+
h('div', {
|
|
101
|
+
className: 'dim-botCardTools',
|
|
102
|
+
// The header is the collapse toggle; keep inner controls clickable.
|
|
103
|
+
onClick: (event) => { event.stopPropagation(); },
|
|
104
|
+
onKeyDown: (event) => { if (event.key === 'Enter' || event.key === ' ') event.stopPropagation(); },
|
|
105
|
+
},
|
|
106
|
+
h(BotStatusMeta, {
|
|
107
|
+
className: 'ddt-health',
|
|
108
|
+
dotClassName: 'ddt-dot',
|
|
109
|
+
tone,
|
|
110
|
+
stateLabel,
|
|
111
|
+
lastCheckedAt: account.health.lastCheckedAt,
|
|
112
|
+
formatCheckedTime: checkedTime,
|
|
113
|
+
}),
|
|
114
|
+
h(BotSettingsButton, {
|
|
115
|
+
channel: channel.toLowerCase(),
|
|
116
|
+
botId: account.botId,
|
|
117
|
+
botName: account.bot.name,
|
|
118
|
+
connected: account.connected,
|
|
119
|
+
accessPolicy: account.accessPolicy,
|
|
120
|
+
}))),
|
|
121
|
+
},
|
|
122
|
+
h(WorkspaceEditor, {
|
|
123
|
+
workspace: account.workspace,
|
|
124
|
+
disabled: Boolean(busy),
|
|
125
|
+
onSave: onWorkspaceSave,
|
|
126
|
+
}),
|
|
127
|
+
h(ModelEditor, {
|
|
128
|
+
model: account.model,
|
|
110
129
|
disabled: Boolean(busy),
|
|
111
|
-
onSave:
|
|
130
|
+
onSave: onModelSave,
|
|
112
131
|
}),
|
|
113
132
|
h(AgentPresetEditor, {
|
|
114
133
|
agentPreset: account.agentPreset,
|
|
@@ -147,7 +166,9 @@ export function createTokenChannelSettings(definition) {
|
|
|
147
166
|
testNotice ? h('div', {
|
|
148
167
|
className: 'ddt-summary dim-cardFeedback',
|
|
149
168
|
role: 'status',
|
|
150
|
-
}, testNotice) : null))
|
|
169
|
+
}, testNotice) : null)),
|
|
170
|
+
),
|
|
171
|
+
),
|
|
151
172
|
removing ? h('div', { className: 'ddt-confirm dim-confirm', role: 'alertdialog' },
|
|
152
173
|
h('strong', null, `从 DeepSeek Harness 移除“${account.bot.name}”?`),
|
|
153
174
|
h('p', null, `这会停止消息连接,并删除本机保存的 ${credentialNoun}、机器人配置及会话映射。${platformLabel}中的机器人不会被自动删除。`),
|
|
@@ -161,6 +182,7 @@ export function createTokenChannelSettings(definition) {
|
|
|
161
182
|
const [model, setModel] = React.useState({
|
|
162
183
|
phase: 'loading', bots: [], totals: { configured: 0, connected: 0 }, error: null,
|
|
163
184
|
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
|
185
|
+
modelCatalog: EMPTY_MODEL_CATALOG,
|
|
164
186
|
});
|
|
165
187
|
const [credentialOpen, setCredentialOpen] = React.useState(false);
|
|
166
188
|
const [credentialError, setCredentialError] = React.useState(null);
|
|
@@ -198,6 +220,7 @@ export function createTokenChannelSettings(definition) {
|
|
|
198
220
|
setModel({
|
|
199
221
|
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals, error: null,
|
|
200
222
|
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
223
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
|
|
201
224
|
});
|
|
202
225
|
} catch (error) {
|
|
203
226
|
if (error?.name !== 'AbortError' && mounted.current && !signal?.aborted
|
|
@@ -244,6 +267,7 @@ export function createTokenChannelSettings(definition) {
|
|
|
244
267
|
setModel({
|
|
245
268
|
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals, error: null,
|
|
246
269
|
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
270
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
|
|
247
271
|
});
|
|
248
272
|
}
|
|
249
273
|
setCredentialOpen(false);
|
|
@@ -266,6 +290,7 @@ export function createTokenChannelSettings(definition) {
|
|
|
266
290
|
setModel({
|
|
267
291
|
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals, error: null,
|
|
268
292
|
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
293
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
|
|
269
294
|
});
|
|
270
295
|
}
|
|
271
296
|
if (mounted.current && operation === 'reconnect') {
|
|
@@ -318,6 +343,12 @@ export function createTokenChannelSettings(definition) {
|
|
|
318
343
|
endpoints.setWorkspace,
|
|
319
344
|
{ botId: account.botId, workspace },
|
|
320
345
|
),
|
|
346
|
+
onModelSave: (selectedModel) => botAction(
|
|
347
|
+
account,
|
|
348
|
+
'model',
|
|
349
|
+
endpoints.setModel,
|
|
350
|
+
{ botId: account.botId, model: selectedModel },
|
|
351
|
+
),
|
|
321
352
|
onAgentPresetSave: (agentPreset) => botAction(
|
|
322
353
|
account,
|
|
323
354
|
'preset',
|
|
@@ -350,7 +381,9 @@ export function createTokenChannelSettings(definition) {
|
|
|
350
381
|
})))))
|
|
351
382
|
: null;
|
|
352
383
|
|
|
353
|
-
return h(
|
|
384
|
+
return h(ModelCatalogContext.Provider, {
|
|
385
|
+
value: model.modelCatalog ?? EMPTY_MODEL_CATALOG,
|
|
386
|
+
}, h(AgentPresetCatalogContext.Provider, {
|
|
354
387
|
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
355
388
|
}, h('section', {
|
|
356
389
|
className: `ddt-page ${pageClass} dim-channelPage`,
|
|
@@ -418,7 +451,7 @@ export function createTokenChannelSettings(definition) {
|
|
|
418
451
|
'aria-hidden': 'true',
|
|
419
452
|
}, h(LogoGlyph, { size: 64 }))))
|
|
420
453
|
: null,
|
|
421
|
-
botList)));
|
|
454
|
+
botList))));
|
|
422
455
|
}
|
|
423
456
|
|
|
424
457
|
return { SettingsTab, AccountCard };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
|
|
2
|
+
import { normalizeModelCatalog, normalizeModelSelection, SET_MODEL_ENDPOINT } from '../../model-setting.js';
|
|
2
3
|
import { normalizeLastMessageError } from '../../last-message-error.js';
|
|
3
4
|
import { normalizeAccessPolicy } from '../../../../src/channels/shared/access-policy.mjs';
|
|
4
5
|
import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
|
|
@@ -14,6 +15,7 @@ export const WECOM_ENDPOINTS = Object.freeze({
|
|
|
14
15
|
reconnectBot: 'bot.reconnect',
|
|
15
16
|
deleteBot: 'bot.delete',
|
|
16
17
|
setWorkspace: 'bot.workspace.set',
|
|
18
|
+
setModel: SET_MODEL_ENDPOINT,
|
|
17
19
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
18
20
|
setContextEnhancement: 'bot.context-enhancement.set',
|
|
19
21
|
setAccessPolicy: 'bot.access-policy.set',
|
|
@@ -99,6 +101,7 @@ function normalizeBot(value) {
|
|
|
99
101
|
connected,
|
|
100
102
|
state: connected ? 'connected' : state,
|
|
101
103
|
workspace: text(value.workspace, '', 4_096),
|
|
104
|
+
model: normalizeModelSelection(value.model),
|
|
102
105
|
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
103
106
|
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
|
|
104
107
|
...(Object.hasOwn(value, 'accessPolicy')
|
|
@@ -131,6 +134,7 @@ export function normalizeSnapshot(value) {
|
|
|
131
134
|
provisioning: source.provisioning ? normalizeProvisioning(source.provisioning) : null,
|
|
132
135
|
testMessage: normalizeTestMessage(source.testMessage),
|
|
133
136
|
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog),
|
|
137
|
+
modelCatalog: normalizeModelCatalog(source.modelCatalog),
|
|
134
138
|
};
|
|
135
139
|
}
|
|
136
140
|
|
|
@@ -2,6 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { WecomLogoGlyph } from '../../channel-logos.js';
|
|
4
4
|
import { CredentialActionIcon, CredentialBindingPanel, QrActionIcon } from '../../credential-binding.js';
|
|
5
|
+
import { CollapsibleAccountSection } from '../shared/collapsible-account.js';
|
|
5
6
|
import { h } from '../../i18n.js';
|
|
6
7
|
import { WorkspaceEditor } from '../../workspace-editor.js';
|
|
7
8
|
import { ContextEnhancementEditor } from '../../context-enhancement.js';
|
|
@@ -10,6 +11,11 @@ import {
|
|
|
10
11
|
AgentPresetEditor,
|
|
11
12
|
EMPTY_AGENT_PRESET_CATALOG,
|
|
12
13
|
} from '../../agent-preset.js';
|
|
14
|
+
import {
|
|
15
|
+
EMPTY_MODEL_CATALOG,
|
|
16
|
+
ModelCatalogContext,
|
|
17
|
+
ModelEditor,
|
|
18
|
+
} from '../../model-setting.js';
|
|
13
19
|
import { useWorkspaceSnapshotFence } from '../../workspace-snapshot-fence.js';
|
|
14
20
|
import {
|
|
15
21
|
BotSettingsButton,
|
|
@@ -166,6 +172,7 @@ export function AccountCard({
|
|
|
166
172
|
removing,
|
|
167
173
|
onReconnect,
|
|
168
174
|
onWorkspaceSave,
|
|
175
|
+
onModelSave,
|
|
169
176
|
onAgentPresetSave,
|
|
170
177
|
onContextEnhancementSave,
|
|
171
178
|
onRequestRemove,
|
|
@@ -177,12 +184,19 @@ export function AccountCard({
|
|
|
177
184
|
const summary = account.error?.message ?? (account.connected ? null : account.health.summary);
|
|
178
185
|
return h('article', { className: 'ddt-card dim-botCard', 'data-bot-id': account.botId },
|
|
179
186
|
h('div', { className: 'ddt-cardBody dim-botCardBody' },
|
|
180
|
-
h(
|
|
187
|
+
h(CollapsibleAccountSection, {
|
|
188
|
+
id: `wec-settings-${account.botId.replace(/[^a-zA-Z0-9_-]/g, '-')}`,
|
|
189
|
+
header: h('div', { className: 'ddt-accountTop dim-botCardTop' },
|
|
181
190
|
h('div', { className: 'ddt-accountIdentity dim-botIdentity' },
|
|
182
191
|
h('div', { className: 'ddt-avatar dim-botAvatar dwecom-avatar', 'aria-hidden': 'true' }, h(WecomLogoGlyph, { size: 29 })),
|
|
183
192
|
h('div', { className: 'dim-botName' },
|
|
184
193
|
h('h3', null, account.bot.name), h('p', null, account.bot.appIdMasked))),
|
|
185
|
-
h('div', {
|
|
194
|
+
h('div', {
|
|
195
|
+
className: 'dim-botCardTools',
|
|
196
|
+
// The header is the collapse toggle; keep inner controls clickable.
|
|
197
|
+
onClick: (event) => { event.stopPropagation(); },
|
|
198
|
+
onKeyDown: (event) => { if (event.key === 'Enter' || event.key === ' ') event.stopPropagation(); },
|
|
199
|
+
},
|
|
186
200
|
h(BotStatusMeta, {
|
|
187
201
|
className: 'ddt-health',
|
|
188
202
|
dotClassName: 'ddt-dot',
|
|
@@ -197,12 +211,18 @@ export function AccountCard({
|
|
|
197
211
|
botName: account.bot.name,
|
|
198
212
|
connected: account.connected,
|
|
199
213
|
accessPolicy: account.accessPolicy,
|
|
200
|
-
})))
|
|
201
|
-
|
|
214
|
+
})))
|
|
215
|
+
},
|
|
216
|
+
h(WorkspaceEditor, {
|
|
202
217
|
workspace: account.workspace,
|
|
203
218
|
disabled: Boolean(busy),
|
|
204
219
|
onSave: onWorkspaceSave,
|
|
205
220
|
}),
|
|
221
|
+
h(ModelEditor, {
|
|
222
|
+
model: account.model,
|
|
223
|
+
disabled: Boolean(busy),
|
|
224
|
+
onSave: onModelSave,
|
|
225
|
+
}),
|
|
206
226
|
h(AgentPresetEditor, {
|
|
207
227
|
agentPreset: account.agentPreset,
|
|
208
228
|
disabled: Boolean(busy),
|
|
@@ -227,7 +247,9 @@ export function AccountCard({
|
|
|
227
247
|
className: 'ddt-summary dim-cardFeedback',
|
|
228
248
|
role: 'status',
|
|
229
249
|
'aria-live': 'polite',
|
|
230
|
-
}, feedback) : null))
|
|
250
|
+
}, feedback) : null)),
|
|
251
|
+
),
|
|
252
|
+
),
|
|
231
253
|
removing ? h(RemoveConfirmation, {
|
|
232
254
|
account, busy: busy === 'delete', onConfirm: onConfirmRemove, onCancel: onCancelRemove,
|
|
233
255
|
}) : null);
|
|
@@ -237,6 +259,7 @@ export function WecomSettingsTab({ rpcCall }) {
|
|
|
237
259
|
const [model, setModel] = React.useState({
|
|
238
260
|
phase: 'loading', bots: [], totals: { configured: 0, connected: 0 }, error: null,
|
|
239
261
|
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
|
262
|
+
modelCatalog: EMPTY_MODEL_CATALOG,
|
|
240
263
|
});
|
|
241
264
|
const [provision, setProvision] = React.useState(null);
|
|
242
265
|
const [busy, setBusy] = React.useState(false);
|
|
@@ -298,6 +321,7 @@ export function WecomSettingsTab({ rpcCall }) {
|
|
|
298
321
|
setModel({
|
|
299
322
|
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals, error: null,
|
|
300
323
|
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
324
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
|
|
301
325
|
});
|
|
302
326
|
if (restore && snapshot.provisioning) setProvision({
|
|
303
327
|
...snapshot.provisioning,
|
|
@@ -365,6 +389,7 @@ export function WecomSettingsTab({ rpcCall }) {
|
|
|
365
389
|
setModel({
|
|
366
390
|
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals, error: null,
|
|
367
391
|
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
392
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
|
|
368
393
|
});
|
|
369
394
|
}
|
|
370
395
|
setCredentialOpen(false);
|
|
@@ -428,6 +453,7 @@ export function WecomSettingsTab({ rpcCall }) {
|
|
|
428
453
|
setModel({
|
|
429
454
|
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals, error: null,
|
|
430
455
|
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
456
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
|
|
431
457
|
});
|
|
432
458
|
}
|
|
433
459
|
return snapshot;
|
|
@@ -509,6 +535,12 @@ export function WecomSettingsTab({ rpcCall }) {
|
|
|
509
535
|
WECOM_ENDPOINTS.setWorkspace,
|
|
510
536
|
{ botId: account.botId, workspace },
|
|
511
537
|
),
|
|
538
|
+
onModelSave: (selectedModel) => botAction(
|
|
539
|
+
account,
|
|
540
|
+
'model',
|
|
541
|
+
WECOM_ENDPOINTS.setModel,
|
|
542
|
+
{ botId: account.botId, model: selectedModel },
|
|
543
|
+
),
|
|
512
544
|
onAgentPresetSave: (agentPreset) => botAction(
|
|
513
545
|
account,
|
|
514
546
|
'preset',
|
|
@@ -544,7 +576,9 @@ export function WecomSettingsTab({ rpcCall }) {
|
|
|
544
576
|
})
|
|
545
577
|
: null;
|
|
546
578
|
|
|
547
|
-
return h(
|
|
579
|
+
return h(ModelCatalogContext.Provider, {
|
|
580
|
+
value: model.modelCatalog ?? EMPTY_MODEL_CATALOG,
|
|
581
|
+
}, h(AgentPresetCatalogContext.Provider, {
|
|
548
582
|
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
549
583
|
}, h('section', { className: 'ddt-page dwecom-page dim-channelPage', 'aria-label': '企业微信设置' },
|
|
550
584
|
h(Heading, {
|
|
@@ -565,5 +599,5 @@ export function WecomSettingsTab({ rpcCall }) {
|
|
|
565
599
|
provisionView,
|
|
566
600
|
model.bots.length === 0 && !provision && !credentialOpen
|
|
567
601
|
? h(EmptyView, { busy, onStart: () => void startProvisioning() }) : null,
|
|
568
|
-
botList)));
|
|
602
|
+
botList))));
|
|
569
603
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
|
|
2
|
+
import { normalizeModelCatalog, normalizeModelSelection, SET_MODEL_ENDPOINT } from '../../model-setting.js';
|
|
2
3
|
import { normalizeLastMessageError } from '../../last-message-error.js';
|
|
3
4
|
import { normalizeAccessPolicy } from '../../../../src/channels/shared/access-policy.mjs';
|
|
4
5
|
import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
|
|
@@ -13,6 +14,7 @@ export const WEIXIN_ENDPOINTS = Object.freeze({
|
|
|
13
14
|
reconnectBot: 'bot.reconnect',
|
|
14
15
|
deleteBot: 'bot.delete',
|
|
15
16
|
setWorkspace: 'bot.workspace.set',
|
|
17
|
+
setModel: SET_MODEL_ENDPOINT,
|
|
16
18
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
17
19
|
setContextEnhancement: 'bot.context-enhancement.set',
|
|
18
20
|
setAccessPolicy: 'bot.access-policy.set',
|
|
@@ -124,6 +126,7 @@ function normalizeBot(value) {
|
|
|
124
126
|
connected,
|
|
125
127
|
configured: value.configured === true,
|
|
126
128
|
workspace: string(value.workspace).slice(0, 4_096),
|
|
129
|
+
model: normalizeModelSelection(value.model),
|
|
127
130
|
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
128
131
|
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
|
|
129
132
|
...(Object.hasOwn(value, 'accessPolicy')
|
|
@@ -169,6 +172,7 @@ export function normalizeSnapshot(value) {
|
|
|
169
172
|
provisioning: value.provisioning ? normalizeProvisioning(value.provisioning) : null,
|
|
170
173
|
testMessage: normalizeTestMessage(value.testMessage),
|
|
171
174
|
agentPresetCatalog: normalizeAgentPresetCatalog(value.agentPresetCatalog),
|
|
175
|
+
modelCatalog: normalizeModelCatalog(value.modelCatalog),
|
|
172
176
|
};
|
|
173
177
|
}
|
|
174
178
|
|
|
@@ -2,6 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { WeixinLogoGlyph } from '../../channel-logos.js';
|
|
4
4
|
import { QrActionIcon } from '../../credential-binding.js';
|
|
5
|
+
import { CollapsibleAccountSection } from '../shared/collapsible-account.js';
|
|
5
6
|
import { h } from '../../i18n.js';
|
|
6
7
|
import {
|
|
7
8
|
WEIXIN_ENDPOINTS,
|
|
@@ -21,6 +22,11 @@ import {
|
|
|
21
22
|
AgentPresetEditor,
|
|
22
23
|
EMPTY_AGENT_PRESET_CATALOG,
|
|
23
24
|
} from '../../agent-preset.js';
|
|
25
|
+
import {
|
|
26
|
+
EMPTY_MODEL_CATALOG,
|
|
27
|
+
ModelCatalogContext,
|
|
28
|
+
ModelEditor,
|
|
29
|
+
} from '../../model-setting.js';
|
|
24
30
|
import { useWorkspaceSnapshotFence } from '../../workspace-snapshot-fence.js';
|
|
25
31
|
import {
|
|
26
32
|
BotSettingsButton,
|
|
@@ -208,6 +214,7 @@ export function AccountCard({
|
|
|
208
214
|
removing,
|
|
209
215
|
onReconnect,
|
|
210
216
|
onWorkspaceSave,
|
|
217
|
+
onModelSave,
|
|
211
218
|
onAgentPresetSave,
|
|
212
219
|
onContextEnhancementSave,
|
|
213
220
|
onRequestRemove,
|
|
@@ -219,11 +226,18 @@ export function AccountCard({
|
|
|
219
226
|
const summary = account.error?.message ?? (account.connected ? null : account.health.summary);
|
|
220
227
|
return h('article', { className: 'dxw-card dim-botCard', tabIndex: -1, 'data-bot-id': account.botId },
|
|
221
228
|
h('div', { className: 'dxw-cardBody dim-botCardBody' },
|
|
222
|
-
h(
|
|
229
|
+
h(CollapsibleAccountSection, {
|
|
230
|
+
id: `dxw-settings-${account.botId.replace(/[^a-zA-Z0-9_-]/g, '-')}`,
|
|
231
|
+
header: h('div', { className: 'dxw-accountTop dim-botCardTop' },
|
|
223
232
|
h('div', { className: 'dxw-accountIdentity dim-botIdentity' },
|
|
224
233
|
h('div', { className: 'dxw-avatar dim-botAvatar', 'aria-hidden': 'true' }, h(WeixinLogoGlyph, { size: 27 })),
|
|
225
234
|
h('div', { className: 'dim-botName' }, h('h3', null, account.bot.name), h('p', null, account.bot.accountIdMasked))),
|
|
226
|
-
h('div', {
|
|
235
|
+
h('div', {
|
|
236
|
+
className: 'dim-botCardTools',
|
|
237
|
+
// The header is the collapse toggle; keep inner controls clickable.
|
|
238
|
+
onClick: (event) => { event.stopPropagation(); },
|
|
239
|
+
onKeyDown: (event) => { if (event.key === 'Enter' || event.key === ' ') event.stopPropagation(); },
|
|
240
|
+
},
|
|
227
241
|
h(BotStatusMeta, {
|
|
228
242
|
className: 'dxw-health',
|
|
229
243
|
dotClassName: 'dxw-dot',
|
|
@@ -238,12 +252,18 @@ export function AccountCard({
|
|
|
238
252
|
botName: account.bot.name,
|
|
239
253
|
connected: account.connected,
|
|
240
254
|
accessPolicy: account.accessPolicy,
|
|
241
|
-
})))
|
|
242
|
-
|
|
255
|
+
})))
|
|
256
|
+
},
|
|
257
|
+
h(WorkspaceEditor, {
|
|
243
258
|
workspace: account.workspace,
|
|
244
259
|
disabled: Boolean(busy),
|
|
245
260
|
onSave: onWorkspaceSave,
|
|
246
261
|
}),
|
|
262
|
+
h(ModelEditor, {
|
|
263
|
+
model: account.model,
|
|
264
|
+
disabled: Boolean(busy),
|
|
265
|
+
onSave: onModelSave,
|
|
266
|
+
}),
|
|
247
267
|
h(AgentPresetEditor, {
|
|
248
268
|
agentPreset: account.agentPreset,
|
|
249
269
|
disabled: Boolean(busy),
|
|
@@ -270,7 +290,9 @@ export function AccountCard({
|
|
|
270
290
|
className: 'dxw-summary dim-cardFeedback',
|
|
271
291
|
role: 'status',
|
|
272
292
|
'aria-live': 'polite',
|
|
273
|
-
}, feedback) : null))
|
|
293
|
+
}, feedback) : null)),
|
|
294
|
+
),
|
|
295
|
+
),
|
|
274
296
|
removing ? h('div', { className: 'dxw-confirm dim-confirm', role: 'alertdialog' },
|
|
275
297
|
h('strong', null, '从此 Harness 移除这个微信账号?'),
|
|
276
298
|
h('p', null, '这会停止消息连接,并删除本机保存的 bot_token、账号配置和会话映射。其他微信账号不受影响。'),
|
|
@@ -296,6 +318,7 @@ function AccountList(props) {
|
|
|
296
318
|
removing: props.removeTarget === account.botId,
|
|
297
319
|
onReconnect: () => props.onReconnect(account),
|
|
298
320
|
onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
|
|
321
|
+
onModelSave: (model) => props.onModelSave(account, model),
|
|
299
322
|
onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
|
|
300
323
|
onContextEnhancementSave: (config) => props.onContextEnhancementSave(account, config),
|
|
301
324
|
onRequestRemove: () => props.onRequestRemove(account),
|
|
@@ -324,6 +347,7 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
324
347
|
const [model, setModel] = React.useState({
|
|
325
348
|
phase: 'loading', bots: [], totals: EMPTY_TOTALS, revision: 0, error: null,
|
|
326
349
|
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
|
350
|
+
modelCatalog: EMPTY_MODEL_CATALOG,
|
|
327
351
|
});
|
|
328
352
|
const [provision, setProvision] = React.useState(null);
|
|
329
353
|
const [busy, setBusy] = React.useState(false);
|
|
@@ -367,6 +391,7 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
367
391
|
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals,
|
|
368
392
|
revision: snapshot.revision, error: null,
|
|
369
393
|
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
394
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
|
|
370
395
|
});
|
|
371
396
|
if (snapshot.provisioning) {
|
|
372
397
|
setProvision((current) => mergeWeixinProvisioningSnapshot(
|
|
@@ -558,6 +583,7 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
558
583
|
setModel((current) => ({
|
|
559
584
|
...current, bots: snapshot.bots, totals: snapshot.totals, revision: snapshot.revision,
|
|
560
585
|
agentPresetCatalog: snapshot.agentPresetCatalog ?? current.agentPresetCatalog,
|
|
586
|
+
modelCatalog: snapshot.modelCatalog ?? current.modelCatalog,
|
|
561
587
|
}));
|
|
562
588
|
}
|
|
563
589
|
const refreshed = snapshot.bots.find((bot) => bot.botId === account.botId);
|
|
@@ -603,6 +629,7 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
603
629
|
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals,
|
|
604
630
|
revision: snapshot.revision, error: null,
|
|
605
631
|
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
632
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
|
|
606
633
|
});
|
|
607
634
|
}
|
|
608
635
|
} finally {
|
|
@@ -625,6 +652,7 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
625
652
|
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals,
|
|
626
653
|
revision: snapshot.revision, error: null,
|
|
627
654
|
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
655
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
|
|
628
656
|
});
|
|
629
657
|
}
|
|
630
658
|
} finally {
|
|
@@ -646,6 +674,7 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
646
674
|
setModel((current) => ({
|
|
647
675
|
...current, bots: snapshot.bots, totals: snapshot.totals, revision: snapshot.revision,
|
|
648
676
|
agentPresetCatalog: snapshot.agentPresetCatalog ?? current.agentPresetCatalog,
|
|
677
|
+
modelCatalog: snapshot.modelCatalog ?? current.modelCatalog,
|
|
649
678
|
}));
|
|
650
679
|
}
|
|
651
680
|
setRemoveTarget(null);
|
|
@@ -686,7 +715,9 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
686
715
|
});
|
|
687
716
|
}
|
|
688
717
|
|
|
689
|
-
return h(
|
|
718
|
+
return h(ModelCatalogContext.Provider, {
|
|
719
|
+
value: model.modelCatalog ?? EMPTY_MODEL_CATALOG,
|
|
720
|
+
}, h(AgentPresetCatalogContext.Provider, {
|
|
690
721
|
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
691
722
|
}, h('section', { className: 'dxw-page dim-channelPage', 'aria-label': '微信设置' },
|
|
692
723
|
h(Heading, {
|
|
@@ -721,6 +752,9 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
721
752
|
removeTarget,
|
|
722
753
|
onReconnect: (account) => void reconnect(account),
|
|
723
754
|
onWorkspaceSave: saveWorkspace,
|
|
755
|
+
onModelSave: (account, selectedModel) => saveBotSetting(
|
|
756
|
+
account, 'model', WEIXIN_ENDPOINTS.setModel, { model: selectedModel },
|
|
757
|
+
),
|
|
724
758
|
onAgentPresetSave: (account, agentPreset) => saveBotSetting(
|
|
725
759
|
account, 'preset', WEIXIN_ENDPOINTS.setAgentPreset, { agentPreset },
|
|
726
760
|
),
|
|
@@ -732,5 +766,5 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
732
766
|
onCancelRemove: () => setRemoveTarget(null),
|
|
733
767
|
})
|
|
734
768
|
: null),
|
|
735
|
-
));
|
|
769
|
+
)));
|
|
736
770
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
|
|
2
|
+
import { normalizeModelCatalog, normalizeModelSelection, SET_MODEL_ENDPOINT } from '../../model-setting.js';
|
|
2
3
|
import { normalizeLastMessageError } from '../../last-message-error.js';
|
|
3
4
|
import { normalizeAccessPolicy } from '../../../../src/channels/shared/access-policy.mjs';
|
|
4
5
|
import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
|
|
@@ -14,6 +15,7 @@ export const WHATSAPP_ENDPOINTS = Object.freeze({
|
|
|
14
15
|
deleteBot: 'bot.delete',
|
|
15
16
|
setAccessPolicy: 'bot.access-policy.set',
|
|
16
17
|
setWorkspace: 'bot.workspace.set',
|
|
18
|
+
setModel: SET_MODEL_ENDPOINT,
|
|
17
19
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
18
20
|
setContextEnhancement: 'bot.context-enhancement.set',
|
|
19
21
|
});
|
|
@@ -90,6 +92,7 @@ function normalizeBot(value) {
|
|
|
90
92
|
connected,
|
|
91
93
|
state: connected ? 'connected' : state,
|
|
92
94
|
workspace: text(value.workspace, '', 4_096),
|
|
95
|
+
model: normalizeModelSelection(value.model),
|
|
93
96
|
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
94
97
|
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
|
|
95
98
|
...(Object.hasOwn(value, 'accessPolicy')
|
|
@@ -124,6 +127,7 @@ export function normalizeSnapshot(value) {
|
|
|
124
127
|
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
125
128
|
provisioning: source.provisioning ? normalizeProvisioning(source.provisioning) : null,
|
|
126
129
|
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog),
|
|
130
|
+
modelCatalog: normalizeModelCatalog(source.modelCatalog),
|
|
127
131
|
};
|
|
128
132
|
}
|
|
129
133
|
|