@xmanrui/dsh-im 0.17.1 → 0.18.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/README.en.md +3 -2
- package/README.md +3 -2
- package/lib/client.js +931 -538
- package/lib/index.js +189 -144
- package/package.json +1 -1
- package/plugin-src/client/agent-preset.js +110 -0
- package/plugin-src/client/channels/dingtalk/api.js +5 -0
- package/plugin-src/client/channels/dingtalk/index.js +48 -2
- package/plugin-src/client/channels/feishu/api.js +5 -0
- package/plugin-src/client/channels/feishu/index.js +39 -2
- package/plugin-src/client/channels/qq/api.js +5 -0
- package/plugin-src/client/channels/qq/index.js +37 -6
- package/plugin-src/client/channels/shared/token-api.js +5 -0
- package/plugin-src/client/channels/shared/token-channel.js +34 -6
- package/plugin-src/client/channels/wecom/api.js +5 -0
- package/plugin-src/client/channels/wecom/index.js +37 -6
- package/plugin-src/client/channels/weixin/api.js +5 -0
- package/plugin-src/client/channels/weixin/index.js +50 -4
- package/plugin-src/client/channels/whatsapp/api.js +5 -0
- package/plugin-src/client/channels/whatsapp/index.js +30 -4
- package/plugin-src/client/i18n.js +9 -0
- package/plugin-src/client/styles.js +8 -0
- package/plugin-src/host/channels/dingtalk/production.mjs +10 -4
- package/plugin-src/host/channels/dingtalk/rpc.mjs +12 -0
- package/plugin-src/host/channels/feishu/connection-supervisor.mjs +1 -1
- package/plugin-src/host/channels/feishu/production.mjs +6 -3
- package/plugin-src/host/channels/feishu/rpc.mjs +17 -0
- package/plugin-src/host/channels/qq/production.mjs +10 -4
- package/plugin-src/host/channels/qq/rpc.mjs +12 -0
- package/plugin-src/host/channels/shared/agent-preset-rpc.mjs +25 -0
- package/plugin-src/host/channels/shared/production.mjs +10 -4
- package/plugin-src/host/channels/shared/rpc.mjs +12 -0
- package/plugin-src/host/channels/shared/workspace-rpc.mjs +2 -0
- package/plugin-src/host/channels/slack/production.mjs +10 -4
- package/plugin-src/host/channels/slack/rpc.mjs +13 -0
- package/plugin-src/host/channels/wecom/production.mjs +10 -4
- package/plugin-src/host/channels/wecom/rpc.mjs +12 -0
- package/plugin-src/host/channels/weixin/production.mjs +10 -4
- package/plugin-src/host/channels/weixin/rpc.mjs +15 -0
- package/plugin-src/host/channels/whatsapp/production.mjs +10 -4
- package/plugin-src/host/channels/whatsapp/rpc.mjs +12 -0
- package/src/channels/discord/discord-api.mjs +1 -1
- package/src/channels/shared/agent-preset.mjs +74 -0
- package/src/channels/shared/bot-workspace-store.mjs +141 -14
- package/src/channels/shared/harness-client.mjs +6 -4
- package/src/channels/weixin/weixin-api.mjs +1 -1
|
@@ -4,6 +4,11 @@ import { CredentialActionIcon, CredentialBindingPanel } from '../../credential-b
|
|
|
4
4
|
import { h } from '../../i18n.js';
|
|
5
5
|
import { installDingtalkStyles } from '../dingtalk/styles.js';
|
|
6
6
|
import { WorkspaceEditor } from '../../workspace-editor.js';
|
|
7
|
+
import {
|
|
8
|
+
AgentPresetCatalogContext,
|
|
9
|
+
AgentPresetEditor,
|
|
10
|
+
EMPTY_AGENT_PRESET_CATALOG,
|
|
11
|
+
} from '../../agent-preset.js';
|
|
7
12
|
import { useWorkspaceSnapshotFence } from '../../workspace-snapshot-fence.js';
|
|
8
13
|
|
|
9
14
|
const Button = React.forwardRef(function Button(
|
|
@@ -63,7 +68,7 @@ export function createTokenChannelSettings(definition) {
|
|
|
63
68
|
accountSettingsEndpoint = null,
|
|
64
69
|
} = definition;
|
|
65
70
|
|
|
66
|
-
function AccountCard({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
|
|
71
|
+
function AccountCard({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onAgentPresetSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
|
|
67
72
|
const state = busy === 'reconnect' ? 'connecting' : account.state;
|
|
68
73
|
const tone = account.connected ? 'success' : state === 'error' ? 'error' : 'warning';
|
|
69
74
|
const stateLabel = account.connected ? '运行正常' : state === 'connecting' ? '正在连接' : '连接未就绪';
|
|
@@ -90,6 +95,11 @@ export function createTokenChannelSettings(definition) {
|
|
|
90
95
|
disabled: Boolean(busy),
|
|
91
96
|
onSave: onWorkspaceSave,
|
|
92
97
|
}),
|
|
98
|
+
h(AgentPresetEditor, {
|
|
99
|
+
agentPreset: account.agentPreset,
|
|
100
|
+
disabled: Boolean(busy),
|
|
101
|
+
onSave: onAgentPresetSave,
|
|
102
|
+
}),
|
|
93
103
|
AccountSettings ? h(AccountSettings, {
|
|
94
104
|
account,
|
|
95
105
|
busy: Boolean(busy),
|
|
@@ -122,6 +132,7 @@ export function createTokenChannelSettings(definition) {
|
|
|
122
132
|
function SettingsTab({ rpcCall }) {
|
|
123
133
|
const [model, setModel] = React.useState({
|
|
124
134
|
phase: 'loading', bots: [], totals: { configured: 0, connected: 0 }, error: null,
|
|
135
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
|
125
136
|
});
|
|
126
137
|
const [credentialOpen, setCredentialOpen] = React.useState(false);
|
|
127
138
|
const [credentialError, setCredentialError] = React.useState(null);
|
|
@@ -156,7 +167,10 @@ export function createTokenChannelSettings(definition) {
|
|
|
156
167
|
const snapshot = api.normalizeSnapshot(await invoke(endpoints.status, {}, signal));
|
|
157
168
|
if (!mounted.current || signal?.aborted
|
|
158
169
|
|| !workspaceFence.canCommitStatus(workspaceVersion)) return;
|
|
159
|
-
setModel({
|
|
170
|
+
setModel({
|
|
171
|
+
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals, error: null,
|
|
172
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
173
|
+
});
|
|
160
174
|
} catch (error) {
|
|
161
175
|
if (error?.name !== 'AbortError' && mounted.current && !signal?.aborted
|
|
162
176
|
&& workspaceFence.canCommitStatus(workspaceVersion)) {
|
|
@@ -199,7 +213,10 @@ export function createTokenChannelSettings(definition) {
|
|
|
199
213
|
));
|
|
200
214
|
if (!mounted.current) return;
|
|
201
215
|
if (workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
202
|
-
setModel({
|
|
216
|
+
setModel({
|
|
217
|
+
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals, error: null,
|
|
218
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
219
|
+
});
|
|
203
220
|
}
|
|
204
221
|
setCredentialOpen(false);
|
|
205
222
|
} catch (error) {
|
|
@@ -218,7 +235,10 @@ export function createTokenChannelSettings(definition) {
|
|
|
218
235
|
const value = await invoke(endpoint, payload);
|
|
219
236
|
const snapshot = api.normalizeSnapshot(value);
|
|
220
237
|
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
221
|
-
setModel({
|
|
238
|
+
setModel({
|
|
239
|
+
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals, error: null,
|
|
240
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
241
|
+
});
|
|
222
242
|
}
|
|
223
243
|
if (mounted.current && operation === 'reconnect') {
|
|
224
244
|
setTestNoticeByBot((current) => ({
|
|
@@ -267,6 +287,12 @@ export function createTokenChannelSettings(definition) {
|
|
|
267
287
|
endpoints.setWorkspace,
|
|
268
288
|
{ botId: account.botId, workspace },
|
|
269
289
|
),
|
|
290
|
+
onAgentPresetSave: (agentPreset) => botAction(
|
|
291
|
+
account,
|
|
292
|
+
'preset',
|
|
293
|
+
endpoints.setAgentPreset,
|
|
294
|
+
{ botId: account.botId, agentPreset },
|
|
295
|
+
),
|
|
270
296
|
onAccountSettingsSave: AccountSettings && accountSettingsEndpoint
|
|
271
297
|
? (payload) => botAction(
|
|
272
298
|
account,
|
|
@@ -287,7 +313,9 @@ export function createTokenChannelSettings(definition) {
|
|
|
287
313
|
})))))
|
|
288
314
|
: null;
|
|
289
315
|
|
|
290
|
-
return h(
|
|
316
|
+
return h(AgentPresetCatalogContext.Provider, {
|
|
317
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
318
|
+
}, h('section', {
|
|
291
319
|
className: `ddt-page ${pageClass} dim-channelPage`,
|
|
292
320
|
'aria-label': `${channel} 设置`,
|
|
293
321
|
},
|
|
@@ -353,7 +381,7 @@ export function createTokenChannelSettings(definition) {
|
|
|
353
381
|
'aria-hidden': 'true',
|
|
354
382
|
}, h(LogoGlyph, { size: 64 }))))
|
|
355
383
|
: null,
|
|
356
|
-
botList));
|
|
384
|
+
botList)));
|
|
357
385
|
}
|
|
358
386
|
|
|
359
387
|
return { SettingsTab, AccountCard };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
|
|
2
|
+
|
|
1
3
|
export const WECOM_RPC_CHANNEL = '/wecom';
|
|
2
4
|
|
|
3
5
|
export const WECOM_ENDPOINTS = Object.freeze({
|
|
@@ -9,6 +11,7 @@ export const WECOM_ENDPOINTS = Object.freeze({
|
|
|
9
11
|
reconnectBot: 'bot.reconnect',
|
|
10
12
|
deleteBot: 'bot.delete',
|
|
11
13
|
setWorkspace: 'bot.workspace.set',
|
|
14
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
12
15
|
});
|
|
13
16
|
|
|
14
17
|
const PROVISION_STATES = new Set(['starting', 'pending', 'refreshing', 'connecting', 'connected', 'failed', 'cancelled']);
|
|
@@ -91,6 +94,7 @@ function normalizeBot(value) {
|
|
|
91
94
|
connected,
|
|
92
95
|
state: connected ? 'connected' : state,
|
|
93
96
|
workspace: text(value.workspace, '', 4_096),
|
|
97
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
94
98
|
bot: {
|
|
95
99
|
name: text(value.bot?.name, '企业微信机器人', 100),
|
|
96
100
|
appIdMasked: text(value.bot?.appIdMasked, '应用标识已安全保存', 140),
|
|
@@ -116,6 +120,7 @@ export function normalizeSnapshot(value) {
|
|
|
116
120
|
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
117
121
|
provisioning: source.provisioning ? normalizeProvisioning(source.provisioning) : null,
|
|
118
122
|
testMessage: normalizeTestMessage(source.testMessage),
|
|
123
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog),
|
|
119
124
|
};
|
|
120
125
|
}
|
|
121
126
|
|
|
@@ -4,6 +4,11 @@ import { WecomLogoGlyph } from '../../channel-logos.js';
|
|
|
4
4
|
import { CredentialActionIcon, CredentialBindingPanel, QrActionIcon } from '../../credential-binding.js';
|
|
5
5
|
import { h } from '../../i18n.js';
|
|
6
6
|
import { WorkspaceEditor } from '../../workspace-editor.js';
|
|
7
|
+
import {
|
|
8
|
+
AgentPresetCatalogContext,
|
|
9
|
+
AgentPresetEditor,
|
|
10
|
+
EMPTY_AGENT_PRESET_CATALOG,
|
|
11
|
+
} from '../../agent-preset.js';
|
|
7
12
|
import { useWorkspaceSnapshotFence } from '../../workspace-snapshot-fence.js';
|
|
8
13
|
import { installDingtalkStyles } from '../dingtalk/styles.js';
|
|
9
14
|
import {
|
|
@@ -155,6 +160,7 @@ export function AccountCard({
|
|
|
155
160
|
removing,
|
|
156
161
|
onReconnect,
|
|
157
162
|
onWorkspaceSave,
|
|
163
|
+
onAgentPresetSave,
|
|
158
164
|
onRequestRemove,
|
|
159
165
|
onConfirmRemove,
|
|
160
166
|
onCancelRemove,
|
|
@@ -179,6 +185,11 @@ export function AccountCard({
|
|
|
179
185
|
disabled: Boolean(busy),
|
|
180
186
|
onSave: onWorkspaceSave,
|
|
181
187
|
}),
|
|
188
|
+
h(AgentPresetEditor, {
|
|
189
|
+
agentPreset: account.agentPreset,
|
|
190
|
+
disabled: Boolean(busy),
|
|
191
|
+
onSave: onAgentPresetSave,
|
|
192
|
+
}),
|
|
182
193
|
h('div', { className: 'ddt-accountFooter dim-cardFooter' },
|
|
183
194
|
summary ? h('div', { className: 'ddt-summary dim-cardSummary' }, summary) : null,
|
|
184
195
|
feedback ? h('div', {
|
|
@@ -195,7 +206,10 @@ export function AccountCard({
|
|
|
195
206
|
}
|
|
196
207
|
|
|
197
208
|
export function WecomSettingsTab({ rpcCall }) {
|
|
198
|
-
const [model, setModel] = React.useState({
|
|
209
|
+
const [model, setModel] = React.useState({
|
|
210
|
+
phase: 'loading', bots: [], totals: { configured: 0, connected: 0 }, error: null,
|
|
211
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
|
212
|
+
});
|
|
199
213
|
const [provision, setProvision] = React.useState(null);
|
|
200
214
|
const [busy, setBusy] = React.useState(false);
|
|
201
215
|
const [busyByBot, setBusyByBot] = React.useState({});
|
|
@@ -253,7 +267,10 @@ export function WecomSettingsTab({ rpcCall }) {
|
|
|
253
267
|
const snapshot = normalizeSnapshot(await invoke(WECOM_ENDPOINTS.status, {}, signal));
|
|
254
268
|
if (!mounted.current || signal?.aborted
|
|
255
269
|
|| !workspaceFence.canCommitStatus(workspaceVersion)) return undefined;
|
|
256
|
-
setModel({
|
|
270
|
+
setModel({
|
|
271
|
+
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals, error: null,
|
|
272
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
273
|
+
});
|
|
257
274
|
if (restore && snapshot.provisioning) setProvision({
|
|
258
275
|
...snapshot.provisioning,
|
|
259
276
|
durationMs: Math.max(1, snapshot.provisioning.expiresAt - Date.now()),
|
|
@@ -317,7 +334,10 @@ export function WecomSettingsTab({ rpcCall }) {
|
|
|
317
334
|
));
|
|
318
335
|
if (!mounted.current) return;
|
|
319
336
|
if (workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
320
|
-
setModel({
|
|
337
|
+
setModel({
|
|
338
|
+
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals, error: null,
|
|
339
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
340
|
+
});
|
|
321
341
|
}
|
|
322
342
|
setCredentialOpen(false);
|
|
323
343
|
} catch (error) {
|
|
@@ -377,7 +397,10 @@ export function WecomSettingsTab({ rpcCall }) {
|
|
|
377
397
|
try {
|
|
378
398
|
const snapshot = normalizeSnapshot(await invoke(endpoint, payload));
|
|
379
399
|
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
380
|
-
setModel({
|
|
400
|
+
setModel({
|
|
401
|
+
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals, error: null,
|
|
402
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
403
|
+
});
|
|
381
404
|
}
|
|
382
405
|
return snapshot;
|
|
383
406
|
} finally {
|
|
@@ -455,6 +478,12 @@ export function WecomSettingsTab({ rpcCall }) {
|
|
|
455
478
|
WECOM_ENDPOINTS.setWorkspace,
|
|
456
479
|
{ botId: account.botId, workspace },
|
|
457
480
|
),
|
|
481
|
+
onAgentPresetSave: (agentPreset) => botAction(
|
|
482
|
+
account,
|
|
483
|
+
'preset',
|
|
484
|
+
WECOM_ENDPOINTS.setAgentPreset,
|
|
485
|
+
{ botId: account.botId, agentPreset },
|
|
486
|
+
),
|
|
458
487
|
onRequestRemove: () => setRemoveTarget(account.botId),
|
|
459
488
|
onCancelRemove: () => setRemoveTarget(null),
|
|
460
489
|
onConfirmRemove: async () => {
|
|
@@ -478,7 +507,9 @@ export function WecomSettingsTab({ rpcCall }) {
|
|
|
478
507
|
})
|
|
479
508
|
: null;
|
|
480
509
|
|
|
481
|
-
return h(
|
|
510
|
+
return h(AgentPresetCatalogContext.Provider, {
|
|
511
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
512
|
+
}, h('section', { className: 'ddt-page dwecom-page dim-channelPage', 'aria-label': '企业微信设置' },
|
|
482
513
|
h(Heading, {
|
|
483
514
|
totals: model.totals,
|
|
484
515
|
adding: Boolean(provision),
|
|
@@ -497,7 +528,7 @@ export function WecomSettingsTab({ rpcCall }) {
|
|
|
497
528
|
provisionView,
|
|
498
529
|
model.bots.length === 0 && !provision && !credentialOpen
|
|
499
530
|
? h(EmptyView, { busy, onStart: () => void startProvisioning() }) : null,
|
|
500
|
-
botList));
|
|
531
|
+
botList)));
|
|
501
532
|
}
|
|
502
533
|
|
|
503
534
|
export function apply(ctx) {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
|
|
2
|
+
|
|
1
3
|
export const WEIXIN_RPC_CHANNEL = '/weixin';
|
|
2
4
|
export const WEIXIN_ENDPOINTS = Object.freeze({
|
|
3
5
|
status: 'connection.status',
|
|
@@ -8,6 +10,7 @@ export const WEIXIN_ENDPOINTS = Object.freeze({
|
|
|
8
10
|
reconnectBot: 'bot.reconnect',
|
|
9
11
|
deleteBot: 'bot.delete',
|
|
10
12
|
setWorkspace: 'bot.workspace.set',
|
|
13
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
11
14
|
});
|
|
12
15
|
|
|
13
16
|
const ACCOUNT_STATES = new Set(['connected', 'connecting', 'offline', 'error']);
|
|
@@ -124,6 +127,7 @@ function normalizeBot(value) {
|
|
|
124
127
|
connected,
|
|
125
128
|
configured: value.configured === true,
|
|
126
129
|
workspace: string(value.workspace).slice(0, 4_096),
|
|
130
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
127
131
|
bot: {
|
|
128
132
|
name: string(value.bot.name, '微信机器人'),
|
|
129
133
|
accountIdMasked: string(value.bot.accountIdMasked, '已安全保存'),
|
|
@@ -163,6 +167,7 @@ export function normalizeSnapshot(value) {
|
|
|
163
167
|
},
|
|
164
168
|
provisioning: value.provisioning ? normalizeProvisioning(value.provisioning) : null,
|
|
165
169
|
testMessage: normalizeTestMessage(value.testMessage),
|
|
170
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(value.agentPresetCatalog),
|
|
166
171
|
};
|
|
167
172
|
}
|
|
168
173
|
|
|
@@ -16,6 +16,11 @@ import {
|
|
|
16
16
|
} from './api.js';
|
|
17
17
|
import { createPollScheduler, useAnimationFrameScheduler } from '../../lifecycle.js';
|
|
18
18
|
import { WorkspaceEditor } from '../../workspace-editor.js';
|
|
19
|
+
import {
|
|
20
|
+
AgentPresetCatalogContext,
|
|
21
|
+
AgentPresetEditor,
|
|
22
|
+
EMPTY_AGENT_PRESET_CATALOG,
|
|
23
|
+
} from '../../agent-preset.js';
|
|
19
24
|
import { useWorkspaceSnapshotFence } from '../../workspace-snapshot-fence.js';
|
|
20
25
|
import { installWeixinStyles } from './styles.js';
|
|
21
26
|
|
|
@@ -202,6 +207,7 @@ export function AccountCard({
|
|
|
202
207
|
removing,
|
|
203
208
|
onReconnect,
|
|
204
209
|
onWorkspaceSave,
|
|
210
|
+
onAgentPresetSave,
|
|
205
211
|
onRequestRemove,
|
|
206
212
|
onConfirmRemove,
|
|
207
213
|
onCancelRemove,
|
|
@@ -228,6 +234,11 @@ export function AccountCard({
|
|
|
228
234
|
disabled: Boolean(busy),
|
|
229
235
|
onSave: onWorkspaceSave,
|
|
230
236
|
}),
|
|
237
|
+
h(AgentPresetEditor, {
|
|
238
|
+
agentPreset: account.agentPreset,
|
|
239
|
+
disabled: Boolean(busy),
|
|
240
|
+
onSave: onAgentPresetSave,
|
|
241
|
+
}),
|
|
231
242
|
h('div', { className: 'dxw-accountFooter dim-cardFooter' },
|
|
232
243
|
summary ? h('div', { className: 'dxw-summary dim-cardSummary' }, summary) : null,
|
|
233
244
|
account.lastMessageError ? h('div', {
|
|
@@ -264,6 +275,7 @@ function AccountList(props) {
|
|
|
264
275
|
removing: props.removeTarget === account.botId,
|
|
265
276
|
onReconnect: () => props.onReconnect(account),
|
|
266
277
|
onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
|
|
278
|
+
onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
|
|
267
279
|
onRequestRemove: () => props.onRequestRemove(account),
|
|
268
280
|
onConfirmRemove: () => props.onConfirmRemove(account),
|
|
269
281
|
onCancelRemove: props.onCancelRemove,
|
|
@@ -289,6 +301,7 @@ export function mergeWeixinProvisioningSnapshot(
|
|
|
289
301
|
export function WeixinSettingsTab({ rpcCall }) {
|
|
290
302
|
const [model, setModel] = React.useState({
|
|
291
303
|
phase: 'loading', bots: [], totals: EMPTY_TOTALS, revision: 0, error: null,
|
|
304
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
|
292
305
|
});
|
|
293
306
|
const [provision, setProvision] = React.useState(null);
|
|
294
307
|
const [busy, setBusy] = React.useState(false);
|
|
@@ -331,6 +344,7 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
331
344
|
setModel({
|
|
332
345
|
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals,
|
|
333
346
|
revision: snapshot.revision, error: null,
|
|
347
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
334
348
|
});
|
|
335
349
|
if (snapshot.provisioning) {
|
|
336
350
|
setProvision((current) => mergeWeixinProvisioningSnapshot(
|
|
@@ -519,7 +533,10 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
519
533
|
{ botId: account.botId, sendTest: true },
|
|
520
534
|
));
|
|
521
535
|
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
522
|
-
setModel((current) => ({
|
|
536
|
+
setModel((current) => ({
|
|
537
|
+
...current, bots: snapshot.bots, totals: snapshot.totals, revision: snapshot.revision,
|
|
538
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? current.agentPresetCatalog,
|
|
539
|
+
}));
|
|
523
540
|
}
|
|
524
541
|
const refreshed = snapshot.bots.find((bot) => bot.botId === account.botId);
|
|
525
542
|
let feedback;
|
|
@@ -563,6 +580,29 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
563
580
|
setModel({
|
|
564
581
|
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals,
|
|
565
582
|
revision: snapshot.revision, error: null,
|
|
583
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
} finally {
|
|
587
|
+
const shouldRefresh = workspaceFence.endMutation();
|
|
588
|
+
if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
|
|
589
|
+
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
590
|
+
}
|
|
591
|
+
}, [invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
592
|
+
|
|
593
|
+
const saveAgentPreset = React.useCallback(async (account, agentPreset) => {
|
|
594
|
+
const snapshotVersion = workspaceFence.beginMutation();
|
|
595
|
+
setBotBusy(account.botId, 'preset');
|
|
596
|
+
try {
|
|
597
|
+
const snapshot = normalizeSnapshot(await invoke(
|
|
598
|
+
WEIXIN_ENDPOINTS.setAgentPreset,
|
|
599
|
+
{ botId: account.botId, agentPreset },
|
|
600
|
+
));
|
|
601
|
+
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
602
|
+
setModel({
|
|
603
|
+
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals,
|
|
604
|
+
revision: snapshot.revision, error: null,
|
|
605
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
566
606
|
});
|
|
567
607
|
}
|
|
568
608
|
} finally {
|
|
@@ -581,7 +621,10 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
581
621
|
confirm: true,
|
|
582
622
|
}));
|
|
583
623
|
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
584
|
-
setModel((current) => ({
|
|
624
|
+
setModel((current) => ({
|
|
625
|
+
...current, bots: snapshot.bots, totals: snapshot.totals, revision: snapshot.revision,
|
|
626
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? current.agentPresetCatalog,
|
|
627
|
+
}));
|
|
585
628
|
}
|
|
586
629
|
setRemoveTarget(null);
|
|
587
630
|
announce('微信账号及本机凭据已移除。');
|
|
@@ -621,7 +664,9 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
621
664
|
});
|
|
622
665
|
}
|
|
623
666
|
|
|
624
|
-
return h(
|
|
667
|
+
return h(AgentPresetCatalogContext.Provider, {
|
|
668
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
669
|
+
}, h('section', { className: 'dxw-page dim-channelPage', 'aria-label': '微信设置' },
|
|
625
670
|
h(Heading, {
|
|
626
671
|
totals: model.totals,
|
|
627
672
|
adding: Boolean(provision),
|
|
@@ -654,12 +699,13 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
654
699
|
removeTarget,
|
|
655
700
|
onReconnect: (account) => void reconnect(account),
|
|
656
701
|
onWorkspaceSave: saveWorkspace,
|
|
702
|
+
onAgentPresetSave: saveAgentPreset,
|
|
657
703
|
onRequestRemove: (account) => setRemoveTarget(account.botId),
|
|
658
704
|
onConfirmRemove: (account) => void remove(account),
|
|
659
705
|
onCancelRemove: () => setRemoveTarget(null),
|
|
660
706
|
})
|
|
661
707
|
: null),
|
|
662
|
-
);
|
|
708
|
+
));
|
|
663
709
|
}
|
|
664
710
|
|
|
665
711
|
export function apply(ctx) {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
|
|
2
|
+
|
|
1
3
|
export const WHATSAPP_RPC_CHANNEL = '/whatsapp';
|
|
2
4
|
|
|
3
5
|
export const WHATSAPP_ENDPOINTS = Object.freeze({
|
|
@@ -8,6 +10,7 @@ export const WHATSAPP_ENDPOINTS = Object.freeze({
|
|
|
8
10
|
reconnectBot: 'bot.reconnect',
|
|
9
11
|
deleteBot: 'bot.delete',
|
|
10
12
|
setWorkspace: 'bot.workspace.set',
|
|
13
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
11
14
|
});
|
|
12
15
|
|
|
13
16
|
const PROVISION_STATES = new Set(['starting', 'pending', 'connecting', 'connected', 'failed', 'cancelled']);
|
|
@@ -82,6 +85,7 @@ function normalizeBot(value) {
|
|
|
82
85
|
connected,
|
|
83
86
|
state: connected ? 'connected' : state,
|
|
84
87
|
workspace: text(value.workspace, '', 4_096),
|
|
88
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
85
89
|
bot: {
|
|
86
90
|
name: text(value.bot?.name, 'WhatsApp机器人', 100),
|
|
87
91
|
idMasked: text(value.bot?.idMasked, 'WhatsApp账号', 140),
|
|
@@ -109,6 +113,7 @@ export function normalizeSnapshot(value) {
|
|
|
109
113
|
bots,
|
|
110
114
|
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
111
115
|
provisioning: source.provisioning ? normalizeProvisioning(source.provisioning) : null,
|
|
116
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog),
|
|
112
117
|
};
|
|
113
118
|
}
|
|
114
119
|
|
|
@@ -4,6 +4,11 @@ import { WhatsappLogoGlyph } from '../../channel-logos.js';
|
|
|
4
4
|
import { QrActionIcon } from '../../credential-binding.js';
|
|
5
5
|
import { h } from '../../i18n.js';
|
|
6
6
|
import { WorkspaceEditor } from '../../workspace-editor.js';
|
|
7
|
+
import {
|
|
8
|
+
AgentPresetCatalogContext,
|
|
9
|
+
AgentPresetEditor,
|
|
10
|
+
EMPTY_AGENT_PRESET_CATALOG,
|
|
11
|
+
} from '../../agent-preset.js';
|
|
7
12
|
import { useWorkspaceSnapshotFence } from '../../workspace-snapshot-fence.js';
|
|
8
13
|
import { installDingtalkStyles } from '../dingtalk/styles.js';
|
|
9
14
|
import {
|
|
@@ -173,6 +178,7 @@ export function WhatsappAccountCard({
|
|
|
173
178
|
removing,
|
|
174
179
|
onReconnect,
|
|
175
180
|
onWorkspaceSave,
|
|
181
|
+
onAgentPresetSave,
|
|
176
182
|
onRequestRemove,
|
|
177
183
|
onConfirmRemove,
|
|
178
184
|
onCancelRemove,
|
|
@@ -205,6 +211,11 @@ export function WhatsappAccountCard({
|
|
|
205
211
|
disabled: Boolean(busy),
|
|
206
212
|
onSave: onWorkspaceSave,
|
|
207
213
|
}),
|
|
214
|
+
h(AgentPresetEditor, {
|
|
215
|
+
agentPreset: account.agentPreset,
|
|
216
|
+
disabled: Boolean(busy),
|
|
217
|
+
onSave: onAgentPresetSave,
|
|
218
|
+
}),
|
|
208
219
|
h('div', { className: 'ddt-accountFooter dim-cardFooter' },
|
|
209
220
|
summary ? h('div', { className: 'ddt-summary dim-cardSummary' }, summary) : null,
|
|
210
221
|
testNotice ? h('div', {
|
|
@@ -229,6 +240,7 @@ export function WhatsappAccountCard({
|
|
|
229
240
|
export function WhatsappSettingsTab({ rpcCall }) {
|
|
230
241
|
const [model, setModel] = React.useState({
|
|
231
242
|
phase: 'loading', bots: [], totals: { configured: 0, connected: 0 }, error: null,
|
|
243
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
|
232
244
|
});
|
|
233
245
|
const [provision, setProvision] = React.useState(null);
|
|
234
246
|
const [busy, setBusy] = React.useState(false);
|
|
@@ -264,7 +276,10 @@ export function WhatsappSettingsTab({ rpcCall }) {
|
|
|
264
276
|
const snapshot = normalizeSnapshot(await invoke(WHATSAPP_ENDPOINTS.status, {}, signal));
|
|
265
277
|
if (!mounted.current || signal?.aborted
|
|
266
278
|
|| !workspaceFence.canCommitStatus(workspaceVersion)) return undefined;
|
|
267
|
-
setModel({
|
|
279
|
+
setModel({
|
|
280
|
+
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals, error: null,
|
|
281
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
282
|
+
});
|
|
268
283
|
if (restore && snapshot.provisioning) setProvision({
|
|
269
284
|
...snapshot.provisioning,
|
|
270
285
|
durationMs: Math.max(1, snapshot.provisioning.expiresAt - Date.now()),
|
|
@@ -392,7 +407,10 @@ export function WhatsappSettingsTab({ rpcCall }) {
|
|
|
392
407
|
const value = await invoke(endpoint, payload);
|
|
393
408
|
const snapshot = normalizeSnapshot(value);
|
|
394
409
|
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
395
|
-
setModel({
|
|
410
|
+
setModel({
|
|
411
|
+
phase: 'ready', bots: snapshot.bots, totals: snapshot.totals, error: null,
|
|
412
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
413
|
+
});
|
|
396
414
|
if (operation === 'reconnect') {
|
|
397
415
|
setTestNoticeByBot((current) => ({
|
|
398
416
|
...current,
|
|
@@ -441,6 +459,12 @@ export function WhatsappSettingsTab({ rpcCall }) {
|
|
|
441
459
|
WHATSAPP_ENDPOINTS.setWorkspace,
|
|
442
460
|
{ botId: account.botId, workspace },
|
|
443
461
|
),
|
|
462
|
+
onAgentPresetSave: (agentPreset) => botAction(
|
|
463
|
+
account,
|
|
464
|
+
'preset',
|
|
465
|
+
WHATSAPP_ENDPOINTS.setAgentPreset,
|
|
466
|
+
{ botId: account.botId, agentPreset },
|
|
467
|
+
),
|
|
444
468
|
onRequestRemove: () => setRemoveTarget(account.botId),
|
|
445
469
|
onCancelRemove: () => setRemoveTarget(null),
|
|
446
470
|
onConfirmRemove: async () => {
|
|
@@ -453,7 +477,9 @@ export function WhatsappSettingsTab({ rpcCall }) {
|
|
|
453
477
|
})))))
|
|
454
478
|
: null;
|
|
455
479
|
|
|
456
|
-
return h(
|
|
480
|
+
return h(AgentPresetCatalogContext.Provider, {
|
|
481
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
482
|
+
}, h('section', {
|
|
457
483
|
className: 'ddt-page dwa-page dim-channelPage',
|
|
458
484
|
'aria-label': 'WhatsApp 设置',
|
|
459
485
|
},
|
|
@@ -490,5 +516,5 @@ export function WhatsappSettingsTab({ rpcCall }) {
|
|
|
490
516
|
: model.bots.length === 0
|
|
491
517
|
? h(EmptyView, { busy, onStart: () => void startProvisioning(false) })
|
|
492
518
|
: null,
|
|
493
|
-
botList));
|
|
519
|
+
botList)));
|
|
494
520
|
}
|
|
@@ -117,6 +117,15 @@ const EN = Object.freeze({
|
|
|
117
117
|
'工作区路径不存在。': 'The workspace path does not exist.',
|
|
118
118
|
'工作区路径必须指向一个目录。': 'The workspace path must point to a directory.',
|
|
119
119
|
'找不到要修改的机器人。': 'The bot could not be found.',
|
|
120
|
+
'Agent Preset': 'Agent Preset',
|
|
121
|
+
'跟随 Host 默认': 'Follow the Host default',
|
|
122
|
+
'(已不可用)': ' (unavailable)',
|
|
123
|
+
'只影响新建会话;若当前聊天已有会话,先发送 /new,再发送普通消息生效。': 'This affects only new sessions. If the current chat already has a session, send /new, then send a regular message to apply it.',
|
|
124
|
+
'当前 Agent Preset 已不可用,请选择其他 Preset 或跟随 Host 默认。': 'The current Agent Preset is unavailable. Choose another preset or follow the Host default.',
|
|
125
|
+
'Agent Preset 修改失败,请重试。': 'Could not update the Agent Preset. Try again.',
|
|
126
|
+
'请选择 Agent Preset。': 'Choose an Agent Preset.',
|
|
127
|
+
'Agent Preset 无效。': 'The Agent Preset is invalid.',
|
|
128
|
+
'Agent Preset 不存在或不可用。': 'The Agent Preset does not exist or is unavailable.',
|
|
120
129
|
'尚未检查': 'Not checked yet',
|
|
121
130
|
'刚刚': 'Just now',
|
|
122
131
|
'检查连接': 'Check connection',
|
|
@@ -142,6 +142,14 @@ const CSS = String.raw`
|
|
|
142
142
|
.dim-panel .dim-workspaceEdit { grid-column: 2; grid-row: 1; padding: 0; border: 0; color: #1677ff; background: transparent; font: inherit; font-weight: 560; white-space: nowrap; cursor: pointer; }
|
|
143
143
|
.dim-panel .dim-workspaceEdit:disabled { cursor: not-allowed; opacity: .55; }
|
|
144
144
|
.dim-panel .dim-workspacePath { min-width: 0; max-width: 100%; grid-column: 1 / -1; grid-row: 2; display: block; overflow-x: auto; overflow-y: hidden; color: var(--dsw-alias-label-primary, #1f2329); font: 12px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: nowrap; }
|
|
145
|
+
.dim-panel .dim-preset { min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr) max-content; align-items: center; column-gap: 10px; row-gap: 4px; margin-top: 6px; padding: 6px 10px; border: 1px solid var(--dsw-alias-border-l1, #eef0f3); border-radius: 9px; background: var(--dsw-alias-bg-module-platform, #f7f8fa); }
|
|
146
|
+
.dim-panel .dim-presetHeader { display: contents; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: normal; }
|
|
147
|
+
.dim-panel .dim-presetHeader > span { grid-column: 1; grid-row: 1; white-space: nowrap; }
|
|
148
|
+
.dim-panel .dim-presetStatus { grid-column: 2; grid-row: 1; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 12px; white-space: nowrap; }
|
|
149
|
+
.dim-panel .dim-presetSelect { min-width: 0; max-width: 100%; grid-column: 1 / -1; grid-row: 2; height: 30px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 7px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-1, #fff); font: inherit; font-size: 12px; }
|
|
150
|
+
.dim-panel .dim-presetSelect:disabled { cursor: not-allowed; opacity: .55; }
|
|
151
|
+
.dim-panel .dim-presetHelp { grid-column: 1 / -1; grid-row: 3; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; line-height: 1.4; }
|
|
152
|
+
.dim-panel .dim-presetError { grid-column: 1 / -1; grid-row: 4; margin: 0; color: var(--dsw-alias-state-error-primary, #d54941); font-size: 12px; line-height: 1.4; }
|
|
145
153
|
.dim-directoryPickerBackdrop { --dim-blue: var(--dsw-alias-state-business-primary, #3370ff); --dim-blue-soft: color-mix(in srgb, var(--dim-blue) 9%, transparent); position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: 24px; background: rgb(15 17 21 / 42%); backdrop-filter: blur(3px); }
|
|
146
154
|
.dim-directoryPickerBackdrop, .dim-directoryPickerBackdrop *, .dim-directoryPickerBackdrop *::before, .dim-directoryPickerBackdrop *::after { box-sizing: border-box; }
|
|
147
155
|
.dim-directoryPicker { width: min(720px, 100%); height: min(620px, calc(100vh - 48px)); min-height: 420px; display: grid; grid-template-rows: auto minmax(0, 1fr) auto; overflow: hidden; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 18px; outline: none; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-1, #fff); box-shadow: 0 24px 72px rgb(15 17 21 / 24%); }
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
createWorkspaceAwareController,
|
|
15
15
|
observeBotWorkspaceRemovals,
|
|
16
16
|
} from '../../../../src/channels/shared/bot-workspace-store.mjs';
|
|
17
|
+
import { listAgentPresetCatalog } from '../../../../src/channels/shared/agent-preset.mjs';
|
|
17
18
|
import { createConnectionSupervisor } from './connection-supervisor.mjs';
|
|
18
19
|
import { createHarnessCommandExecutor } from '../../harness-command-executor.mjs';
|
|
19
20
|
import { createHarnessSessionExecutors } from '../../harness-session-coordinator.mjs';
|
|
@@ -63,7 +64,9 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
63
64
|
if (canListConfiguredBots) {
|
|
64
65
|
await workspaces.reconcile(configuredBots.map((bot) => bot.botId));
|
|
65
66
|
}
|
|
66
|
-
await Promise.all(configuredBots.map((bot) => workspaces.ensure(bot.botId
|
|
67
|
+
await Promise.all(configuredBots.map((bot) => workspaces.ensure(bot.botId, {
|
|
68
|
+
defaultAgentPreset: config.agentPreset,
|
|
69
|
+
})));
|
|
67
70
|
const observedConfigStore = typeof configStore.remove === 'function'
|
|
68
71
|
? observeBotWorkspaceRemovals(configStore, { workspaces })
|
|
69
72
|
: configStore;
|
|
@@ -89,7 +92,6 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
89
92
|
const harness = new Harness({
|
|
90
93
|
baseUrl: harnessOrigin(ctx.webServer, config.harnessBaseUrl),
|
|
91
94
|
workspace: defaultWorkspace,
|
|
92
|
-
...(config.agentPreset == null ? {} : { agentPreset: config.agentPreset }),
|
|
93
95
|
autostart: false,
|
|
94
96
|
dshBin: config.dshBin ?? 'dsh',
|
|
95
97
|
...(commandExecutor ? { commandExecutor } : {}),
|
|
@@ -103,7 +105,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
103
105
|
logger,
|
|
104
106
|
createRuntime: async ({ botId, config: botConfig, clientSecret }) => {
|
|
105
107
|
const state = await stateFor(botId);
|
|
106
|
-
await workspaces.ensure(botId);
|
|
108
|
+
await workspaces.ensure(botId, { defaultAgentPreset: config.agentPreset });
|
|
107
109
|
const workspaceScope = createBotWorkspaceScope(harness, { botId, workspaces, state });
|
|
108
110
|
return new Runtime({
|
|
109
111
|
config: botConfig,
|
|
@@ -135,7 +137,11 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
135
137
|
}
|
|
136
138
|
},
|
|
137
139
|
});
|
|
138
|
-
const controller = createWorkspaceAwareController(coreController, {
|
|
140
|
+
const controller = createWorkspaceAwareController(coreController, {
|
|
141
|
+
workspaces,
|
|
142
|
+
stateFor,
|
|
143
|
+
agentPresetCatalog: () => listAgentPresetCatalog(ctx),
|
|
144
|
+
});
|
|
139
145
|
const supervisor = createSupervisor({
|
|
140
146
|
controller,
|
|
141
147
|
harness,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import QRCode from 'qrcode';
|
|
2
2
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
3
3
|
import { publicWorkspaceError, SET_WORKSPACE_ENDPOINT, validWorkspacePayload } from '../shared/workspace-rpc.mjs';
|
|
4
|
+
import { SET_AGENT_PRESET_ENDPOINT, validAgentPresetPayload } from '../shared/agent-preset-rpc.mjs';
|
|
4
5
|
import {
|
|
5
6
|
connectionTestTargetUnavailable,
|
|
6
7
|
publicConnectionTestResult,
|
|
@@ -16,6 +17,7 @@ export const DINGTALK_ENDPOINTS = Object.freeze({
|
|
|
16
17
|
reconnectBot: 'bot.reconnect',
|
|
17
18
|
deleteBot: 'bot.delete',
|
|
18
19
|
setWorkspace: SET_WORKSPACE_ENDPOINT,
|
|
20
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
19
21
|
approveSender: 'bot.sender.approve',
|
|
20
22
|
revokeSender: 'bot.sender.revoke',
|
|
21
23
|
});
|
|
@@ -88,6 +90,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
88
90
|
return validWorkspacePayload(payload)
|
|
89
91
|
? null : '请输入工作区绝对路径。';
|
|
90
92
|
}
|
|
93
|
+
if (endpoint === DINGTALK_ENDPOINTS.setAgentPreset) {
|
|
94
|
+
return validAgentPresetPayload(payload)
|
|
95
|
+
? null : '请选择 Agent Preset。';
|
|
96
|
+
}
|
|
91
97
|
if (endpoint === DINGTALK_ENDPOINTS.approveSender) {
|
|
92
98
|
return exactKeys(payload, ['botId', 'requestId', 'confirm'])
|
|
93
99
|
&& validId(payload.botId)
|
|
@@ -245,6 +251,12 @@ export function createDingtalkRpcHandler(controller, { encodeQr = qrDataUrl } =
|
|
|
245
251
|
await controller.updateWorkspace(payload.botId, payload.workspace),
|
|
246
252
|
cachedEncode,
|
|
247
253
|
);
|
|
254
|
+
} else if (endpoint === DINGTALK_ENDPOINTS.setAgentPreset) {
|
|
255
|
+
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
|
256
|
+
value = await publicStatus(
|
|
257
|
+
await controller.updateAgentPreset(payload.botId, payload.agentPreset),
|
|
258
|
+
cachedEncode,
|
|
259
|
+
);
|
|
248
260
|
} else if (endpoint === DINGTALK_ENDPOINTS.approveSender) {
|
|
249
261
|
value = await publicStatus(
|
|
250
262
|
await controller.approveSender(payload.botId, payload.requestId),
|
|
@@ -129,7 +129,7 @@ export class ConnectionSupervisor {
|
|
|
129
129
|
await this.#controller.initialize();
|
|
130
130
|
if (this.#closed) return;
|
|
131
131
|
|
|
132
|
-
const status = this.#controller.status();
|
|
132
|
+
const status = await this.#controller.status();
|
|
133
133
|
this.#resolveReady?.(status);
|
|
134
134
|
this.#resolveReady = null;
|
|
135
135
|
const current = totals(status);
|