@xmanrui/dsh-im 0.17.0 → 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 +964 -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 +15 -0
- package/plugin-src/client/channels/weixin/index.js +54 -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 +29 -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/shared/image-prompt.mjs +32 -1
- package/src/channels/weixin/weixin-api.mjs +1 -1
- package/src/channels/weixin/weixin-bridge.mjs +23 -3
- package/src/channels/weixin/weixin-controller.mjs +15 -0
|
@@ -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);
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
createWorkspaceAwareController,
|
|
21
21
|
observeBotWorkspaceRemovals,
|
|
22
22
|
} from '../../../../src/channels/shared/bot-workspace-store.mjs';
|
|
23
|
+
import { listAgentPresetCatalog } from '../../../../src/channels/shared/agent-preset.mjs';
|
|
23
24
|
|
|
24
25
|
function harnessOrigin(webServer, configured) {
|
|
25
26
|
if (configured !== undefined) return new URL(configured);
|
|
@@ -77,7 +78,9 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
77
78
|
if (canListConfiguredBots) {
|
|
78
79
|
await workspaces.reconcile(configuredBots.map((bot) => bot.id));
|
|
79
80
|
}
|
|
80
|
-
await Promise.all(configuredBots.map((bot) => workspaces.ensure(bot.id
|
|
81
|
+
await Promise.all(configuredBots.map((bot) => workspaces.ensure(bot.id, {
|
|
82
|
+
defaultAgentPreset: config.agentPreset,
|
|
83
|
+
})));
|
|
81
84
|
const observedConfigStore = typeof configStore.removeBot === 'function'
|
|
82
85
|
? observeBotWorkspaceRemovals(configStore, {
|
|
83
86
|
workspaces,
|
|
@@ -115,7 +118,6 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
115
118
|
const harness = new Harness({
|
|
116
119
|
baseUrl: harnessOrigin(ctx.webServer, config.harnessBaseUrl),
|
|
117
120
|
workspace: defaultWorkspace,
|
|
118
|
-
...(config.agentPreset == null ? {} : { agentPreset: config.agentPreset }),
|
|
119
121
|
// This plugin is already hosted by a running DSH process. Starting a
|
|
120
122
|
// second DSH would create a competing server and lifecycle.
|
|
121
123
|
autostart: false,
|
|
@@ -133,7 +135,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
133
135
|
createRuntime: async ({ botId, config: botConfig, appSecret, repair }) => {
|
|
134
136
|
const state = await stateFor(botConfig);
|
|
135
137
|
const id = botId ?? botConfig.id ?? botConfig.appId;
|
|
136
|
-
await workspaces.ensure(id);
|
|
138
|
+
await workspaces.ensure(id, { defaultAgentPreset: config.agentPreset });
|
|
137
139
|
const workspaceScope = createBotWorkspaceScope(harness, { botId: id, workspaces, state });
|
|
138
140
|
return new Runtime({
|
|
139
141
|
lark,
|
|
@@ -166,6 +168,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
166
168
|
const controller = createWorkspaceAwareController(coreController, {
|
|
167
169
|
workspaces,
|
|
168
170
|
stateFor: stateForBotId,
|
|
171
|
+
agentPresetCatalog: () => listAgentPresetCatalog(ctx),
|
|
169
172
|
});
|
|
170
173
|
|
|
171
174
|
const supervisor = createSupervisor({
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import QRCode from 'qrcode';
|
|
2
|
+
import {
|
|
3
|
+
normalizeAgentPresetCatalog,
|
|
4
|
+
normalizeAgentPresetId,
|
|
5
|
+
} from '../../../../src/channels/shared/agent-preset.mjs';
|
|
2
6
|
import { publicConnectionTestResult } from '../../../../src/channels/shared/connection-test.mjs';
|
|
3
7
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
4
8
|
import { publicWorkspaceError, validWorkspacePayload } from '../shared/workspace-rpc.mjs';
|
|
9
|
+
import { validAgentPresetPayload } from '../shared/agent-preset-rpc.mjs';
|
|
5
10
|
import {
|
|
6
11
|
FEISHU_ENDPOINTS,
|
|
7
12
|
FEISHU_RPC_CHANNEL,
|
|
@@ -253,6 +258,7 @@ function publicBotEntry(entry) {
|
|
|
253
258
|
state: connectionState(source, registration, connected),
|
|
254
259
|
connected,
|
|
255
260
|
configured: source.configured === true,
|
|
261
|
+
agentPreset: normalizeAgentPresetId(source.agentPreset),
|
|
256
262
|
bot: publicBot(source.bot),
|
|
257
263
|
health: publicHealth(source, connected),
|
|
258
264
|
};
|
|
@@ -294,6 +300,7 @@ export async function toPublicFeishuStatus(status, { encodeQr = qrCodeDataUrl }
|
|
|
294
300
|
bot: publicBot(source.bot),
|
|
295
301
|
health: publicHealth(source, connected),
|
|
296
302
|
bots,
|
|
303
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog),
|
|
297
304
|
totals: {
|
|
298
305
|
configured: bots.length || (source.configured === true ? 1 : 0),
|
|
299
306
|
connected: bots.length ? bots.filter((bot) => bot.connected).length : (connected ? 1 : 0),
|
|
@@ -378,6 +385,10 @@ function validPayload(endpoint, payload) {
|
|
|
378
385
|
return validWorkspacePayload(payload)
|
|
379
386
|
? null : '请输入工作区绝对路径。';
|
|
380
387
|
}
|
|
388
|
+
if (endpoint === FEISHU_ENDPOINTS.setAgentPreset) {
|
|
389
|
+
return validAgentPresetPayload(payload)
|
|
390
|
+
? null : '请选择 Agent Preset。';
|
|
391
|
+
}
|
|
381
392
|
return 'Unknown Feishu endpoint.';
|
|
382
393
|
}
|
|
383
394
|
|
|
@@ -606,6 +617,12 @@ export function createFeishuRpcHandler(controller, { encodeQr = qrCodeDataUrl }
|
|
|
606
617
|
await controller.updateWorkspace(payload.botId, payload.workspace),
|
|
607
618
|
{ encodeQr: cachedEncodeQr },
|
|
608
619
|
);
|
|
620
|
+
} else if (endpoint === FEISHU_ENDPOINTS.setAgentPreset) {
|
|
621
|
+
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
|
622
|
+
value = await toPublicFeishuStatus(
|
|
623
|
+
await controller.updateAgentPreset(payload.botId, payload.agentPreset),
|
|
624
|
+
{ encodeQr: cachedEncodeQr },
|
|
625
|
+
);
|
|
609
626
|
} else {
|
|
610
627
|
if (typeof controller.deleteBot !== 'function') throw new Error('Multi-bot delete is unavailable');
|
|
611
628
|
value = await toPublicFeishuStatus(await controller.deleteBot(payload.botId), { encodeQr: cachedEncodeQr });
|
|
@@ -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';
|
|
@@ -57,7 +58,9 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
57
58
|
?? await new WorkspaceStore(paths.workspaces, { defaultWorkspace }).load();
|
|
58
59
|
const configuredBots = configStore.list();
|
|
59
60
|
await workspaces.reconcile(configuredBots.map((bot) => bot.botId));
|
|
60
|
-
await Promise.all(configuredBots.map((bot) => workspaces.ensure(bot.botId
|
|
61
|
+
await Promise.all(configuredBots.map((bot) => workspaces.ensure(bot.botId, {
|
|
62
|
+
defaultAgentPreset: config.agentPreset,
|
|
63
|
+
})));
|
|
61
64
|
const observedConfigStore = typeof configStore.remove === 'function'
|
|
62
65
|
? observeBotWorkspaceRemovals(configStore, { workspaces })
|
|
63
66
|
: configStore;
|
|
@@ -80,7 +83,6 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
80
83
|
const harness = new Harness({
|
|
81
84
|
baseUrl: harnessOrigin(ctx.webServer, config.harnessBaseUrl),
|
|
82
85
|
workspace: defaultWorkspace,
|
|
83
|
-
...(config.agentPreset == null ? {} : { agentPreset: config.agentPreset }),
|
|
84
86
|
autostart: false,
|
|
85
87
|
dshBin: config.dshBin ?? 'dsh',
|
|
86
88
|
...(commandExecutor ? { commandExecutor } : {}),
|
|
@@ -94,7 +96,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
94
96
|
logger,
|
|
95
97
|
createRuntime: async ({ botId, config: botConfig, appSecret }) => {
|
|
96
98
|
const state = await stateFor(botId);
|
|
97
|
-
await workspaces.ensure(botId);
|
|
99
|
+
await workspaces.ensure(botId, { defaultAgentPreset: config.agentPreset });
|
|
98
100
|
const workspaceScope = createBotWorkspaceScope(harness, { botId, workspaces, state });
|
|
99
101
|
return new Runtime({
|
|
100
102
|
config: botConfig,
|
|
@@ -125,7 +127,11 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
125
127
|
}
|
|
126
128
|
},
|
|
127
129
|
});
|
|
128
|
-
const controller = createWorkspaceAwareController(coreController, {
|
|
130
|
+
const controller = createWorkspaceAwareController(coreController, {
|
|
131
|
+
workspaces,
|
|
132
|
+
stateFor,
|
|
133
|
+
agentPresetCatalog: () => listAgentPresetCatalog(ctx),
|
|
134
|
+
});
|
|
129
135
|
const supervisor = createSupervisor({
|
|
130
136
|
controller,
|
|
131
137
|
harness,
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
} from '../../../../src/channels/shared/connection-test.mjs';
|
|
6
6
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
7
7
|
import { publicWorkspaceError, SET_WORKSPACE_ENDPOINT, validWorkspacePayload } from '../shared/workspace-rpc.mjs';
|
|
8
|
+
import { SET_AGENT_PRESET_ENDPOINT, validAgentPresetPayload } from '../shared/agent-preset-rpc.mjs';
|
|
8
9
|
|
|
9
10
|
export const QQ_RPC_CHANNEL = '/qq';
|
|
10
11
|
export const QQ_ENDPOINTS = Object.freeze({
|
|
@@ -16,6 +17,7 @@ export const QQ_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
|
});
|
|
20
22
|
export const QQ_RPC_ENDPOINTS = Object.freeze(Object.values(QQ_ENDPOINTS));
|
|
21
23
|
|
|
@@ -70,6 +72,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
70
72
|
return validWorkspacePayload(payload)
|
|
71
73
|
? null : '请输入工作区绝对路径。';
|
|
72
74
|
}
|
|
75
|
+
if (endpoint === QQ_ENDPOINTS.setAgentPreset) {
|
|
76
|
+
return validAgentPresetPayload(payload)
|
|
77
|
+
? null : '请选择 Agent Preset。';
|
|
78
|
+
}
|
|
73
79
|
return 'Unknown QQ endpoint.';
|
|
74
80
|
}
|
|
75
81
|
|
|
@@ -165,6 +171,12 @@ export function createQqRpcHandler(controller, { encodeQr = qrDataUrl } = {}) {
|
|
|
165
171
|
await controller.updateWorkspace(payload.botId, payload.workspace),
|
|
166
172
|
cachedEncode,
|
|
167
173
|
);
|
|
174
|
+
} else if (endpoint === QQ_ENDPOINTS.setAgentPreset) {
|
|
175
|
+
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
|
176
|
+
value = await publicStatus(
|
|
177
|
+
await controller.updateAgentPreset(payload.botId, payload.agentPreset),
|
|
178
|
+
cachedEncode,
|
|
179
|
+
);
|
|
168
180
|
} else {
|
|
169
181
|
value = await publicStatus(await controller.deleteBot(payload.botId), cachedEncode);
|
|
170
182
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AGENT_PRESET_ID } from '../../../../src/channels/shared/agent-preset.mjs';
|
|
2
|
+
|
|
3
|
+
export const SET_AGENT_PRESET_ENDPOINT = 'bot.preset.set';
|
|
4
|
+
|
|
5
|
+
function isRecord(value) {
|
|
6
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function validAgentPresetPayload(payload) {
|
|
10
|
+
return isRecord(payload)
|
|
11
|
+
&& Object.keys(payload).every((key) => ['botId', 'agentPreset'].includes(key))
|
|
12
|
+
&& typeof payload.botId === 'string'
|
|
13
|
+
&& /^[A-Za-z0-9_-]{1,128}$/.test(payload.botId)
|
|
14
|
+
&& (payload.agentPreset === null
|
|
15
|
+
|| (typeof payload.agentPreset === 'string' && AGENT_PRESET_ID.test(payload.agentPreset)));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function publicAgentPresetError(error) {
|
|
19
|
+
if (![
|
|
20
|
+
'agent-preset-invalid',
|
|
21
|
+
'agent-preset-unavailable',
|
|
22
|
+
'workspace-bot-not-found',
|
|
23
|
+
].includes(error?.code)) return null;
|
|
24
|
+
return { code: error.code, message: error.message };
|
|
25
|
+
}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
createWorkspaceAwareController,
|
|
12
12
|
observeBotWorkspaceRemovals,
|
|
13
13
|
} from '../../../../src/channels/shared/bot-workspace-store.mjs';
|
|
14
|
+
import { listAgentPresetCatalog } from '../../../../src/channels/shared/agent-preset.mjs';
|
|
14
15
|
|
|
15
16
|
export function harnessOrigin(webServer, configured) {
|
|
16
17
|
if (configured !== undefined) return new URL(configured);
|
|
@@ -59,7 +60,9 @@ export async function createTokenProductionController(ctx, config, internals, de
|
|
|
59
60
|
?? await new WorkspaceStore(paths.workspaces, { defaultWorkspace }).load();
|
|
60
61
|
const configuredBots = configStore.list();
|
|
61
62
|
await workspaces.reconcile(configuredBots.map((bot) => bot.botId));
|
|
62
|
-
await Promise.all(configuredBots.map((bot) => workspaces.ensure(bot.botId
|
|
63
|
+
await Promise.all(configuredBots.map((bot) => workspaces.ensure(bot.botId, {
|
|
64
|
+
defaultAgentPreset: config.agentPreset,
|
|
65
|
+
})));
|
|
63
66
|
const observedConfigStore = typeof configStore.remove === 'function'
|
|
64
67
|
? observeBotWorkspaceRemovals(configStore, { workspaces })
|
|
65
68
|
: configStore;
|
|
@@ -81,7 +84,6 @@ export async function createTokenProductionController(ctx, config, internals, de
|
|
|
81
84
|
const harness = new ResolvedHarness({
|
|
82
85
|
baseUrl: harnessOrigin(ctx.webServer, config.harnessBaseUrl),
|
|
83
86
|
workspace: defaultWorkspace,
|
|
84
|
-
...(config.agentPreset == null ? {} : { agentPreset: config.agentPreset }),
|
|
85
87
|
autostart: false,
|
|
86
88
|
dshBin: config.dshBin ?? 'dsh',
|
|
87
89
|
...(commandExecutor ? { commandExecutor } : {}),
|
|
@@ -95,7 +97,7 @@ export async function createTokenProductionController(ctx, config, internals, de
|
|
|
95
97
|
...(internals.inspectToken ? { inspectToken: internals.inspectToken } : {}),
|
|
96
98
|
createRuntime: async ({ botId, config: botConfig, token }) => {
|
|
97
99
|
const state = await stateFor(botId);
|
|
98
|
-
await workspaces.ensure(botId);
|
|
100
|
+
await workspaces.ensure(botId, { defaultAgentPreset: config.agentPreset });
|
|
99
101
|
const workspaceScope = createBotWorkspaceScope(harness, { botId, workspaces, state });
|
|
100
102
|
return new ResolvedRuntime({
|
|
101
103
|
...channelRuntimeOptions,
|
|
@@ -127,7 +129,11 @@ export async function createTokenProductionController(ctx, config, internals, de
|
|
|
127
129
|
}
|
|
128
130
|
},
|
|
129
131
|
});
|
|
130
|
-
const controller = createWorkspaceAwareController(coreController, {
|
|
132
|
+
const controller = createWorkspaceAwareController(coreController, {
|
|
133
|
+
workspaces,
|
|
134
|
+
stateFor,
|
|
135
|
+
agentPresetCatalog: () => listAgentPresetCatalog(ctx),
|
|
136
|
+
});
|
|
131
137
|
const supervisor = createSupervisor({
|
|
132
138
|
channel,
|
|
133
139
|
controller,
|
|
@@ -5,6 +5,10 @@ import {
|
|
|
5
5
|
SET_WORKSPACE_ENDPOINT,
|
|
6
6
|
validWorkspacePayload,
|
|
7
7
|
} from './workspace-rpc.mjs';
|
|
8
|
+
import {
|
|
9
|
+
SET_AGENT_PRESET_ENDPOINT,
|
|
10
|
+
validAgentPresetPayload,
|
|
11
|
+
} from './agent-preset-rpc.mjs';
|
|
8
12
|
|
|
9
13
|
export const TOKEN_BOT_ENDPOINTS = Object.freeze({
|
|
10
14
|
status: 'connection.status',
|
|
@@ -12,6 +16,7 @@ export const TOKEN_BOT_ENDPOINTS = Object.freeze({
|
|
|
12
16
|
reconnectBot: 'bot.reconnect',
|
|
13
17
|
deleteBot: 'bot.delete',
|
|
14
18
|
setWorkspace: SET_WORKSPACE_ENDPOINT,
|
|
19
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
15
20
|
});
|
|
16
21
|
|
|
17
22
|
const ENDPOINTS = Object.freeze(Object.values(TOKEN_BOT_ENDPOINTS));
|
|
@@ -57,6 +62,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
57
62
|
return validWorkspacePayload(payload)
|
|
58
63
|
? null : '请输入工作区绝对路径。';
|
|
59
64
|
}
|
|
65
|
+
if (endpoint === TOKEN_BOT_ENDPOINTS.setAgentPreset) {
|
|
66
|
+
return validAgentPresetPayload(payload)
|
|
67
|
+
? null : '请选择 Agent Preset。';
|
|
68
|
+
}
|
|
60
69
|
return 'Unknown bot endpoint.';
|
|
61
70
|
}
|
|
62
71
|
|
|
@@ -132,6 +141,9 @@ export function createTokenBotRpcHandler(controller, { channel }) {
|
|
|
132
141
|
} else if (endpoint === TOKEN_BOT_ENDPOINTS.setWorkspace) {
|
|
133
142
|
if (typeof controller.updateWorkspace !== 'function') throw new Error('Workspace update is unavailable');
|
|
134
143
|
value = await controller.updateWorkspace(payload.botId, payload.workspace);
|
|
144
|
+
} else if (endpoint === TOKEN_BOT_ENDPOINTS.setAgentPreset) {
|
|
145
|
+
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
|
146
|
+
value = await controller.updateAgentPreset(payload.botId, payload.agentPreset);
|
|
135
147
|
} else {
|
|
136
148
|
value = await controller.deleteBot(payload.botId);
|
|
137
149
|
}
|
|
@@ -20,6 +20,8 @@ export function publicWorkspaceError(error) {
|
|
|
20
20
|
'workspace-not-found',
|
|
21
21
|
'workspace-not-directory',
|
|
22
22
|
'workspace-bot-not-found',
|
|
23
|
+
'agent-preset-invalid',
|
|
24
|
+
'agent-preset-unavailable',
|
|
23
25
|
].includes(error?.code)) return null;
|
|
24
26
|
return { code: error.code, message: error.message };
|
|
25
27
|
}
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
createWorkspaceAwareController,
|
|
13
13
|
observeBotWorkspaceRemovals,
|
|
14
14
|
} from '../../../../src/channels/shared/bot-workspace-store.mjs';
|
|
15
|
+
import { listAgentPresetCatalog } from '../../../../src/channels/shared/agent-preset.mjs';
|
|
15
16
|
import { createTokenConnectionSupervisor } from '../shared/connection-supervisor.mjs';
|
|
16
17
|
import { harnessOrigin, pluginPaths } from '../shared/production.mjs';
|
|
17
18
|
import { createHarnessCommandExecutor } from '../../harness-command-executor.mjs';
|
|
@@ -37,7 +38,9 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
37
38
|
?? await new WorkspaceStore(paths.workspaces, { defaultWorkspace }).load();
|
|
38
39
|
const configuredBots = configStore.list();
|
|
39
40
|
await workspaces.reconcile(configuredBots.map((bot) => bot.botId));
|
|
40
|
-
await Promise.all(configuredBots.map((bot) => workspaces.ensure(bot.botId
|
|
41
|
+
await Promise.all(configuredBots.map((bot) => workspaces.ensure(bot.botId, {
|
|
42
|
+
defaultAgentPreset: config.agentPreset,
|
|
43
|
+
})));
|
|
41
44
|
const observedConfigStore = typeof configStore.remove === 'function'
|
|
42
45
|
? observeBotWorkspaceRemovals(configStore, { workspaces })
|
|
43
46
|
: configStore;
|
|
@@ -59,7 +62,6 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
59
62
|
const harness = new ResolvedHarness({
|
|
60
63
|
baseUrl: harnessOrigin(ctx.webServer, config.harnessBaseUrl),
|
|
61
64
|
workspace: defaultWorkspace,
|
|
62
|
-
...(config.agentPreset == null ? {} : { agentPreset: config.agentPreset }),
|
|
63
65
|
autostart: false,
|
|
64
66
|
dshBin: config.dshBin ?? 'dsh',
|
|
65
67
|
...(commandExecutor ? { commandExecutor } : {}),
|
|
@@ -73,7 +75,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
73
75
|
...(internals.inspectCredentials ? { inspectCredentials: internals.inspectCredentials } : {}),
|
|
74
76
|
createRuntime: async ({ botId, config: botConfig, botToken, appToken }) => {
|
|
75
77
|
const state = await stateFor(botId);
|
|
76
|
-
await workspaces.ensure(botId);
|
|
78
|
+
await workspaces.ensure(botId, { defaultAgentPreset: config.agentPreset });
|
|
77
79
|
const workspaceScope = createBotWorkspaceScope(harness, { botId, workspaces, state });
|
|
78
80
|
return new ResolvedRuntime({
|
|
79
81
|
config: botConfig,
|
|
@@ -105,7 +107,11 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
105
107
|
}
|
|
106
108
|
},
|
|
107
109
|
});
|
|
108
|
-
const controller = createWorkspaceAwareController(coreController, {
|
|
110
|
+
const controller = createWorkspaceAwareController(coreController, {
|
|
111
|
+
workspaces,
|
|
112
|
+
stateFor,
|
|
113
|
+
agentPresetCatalog: () => listAgentPresetCatalog(ctx),
|
|
114
|
+
});
|
|
109
115
|
const supervisor = createSupervisor({
|
|
110
116
|
channel: 'slack',
|
|
111
117
|
controller,
|
|
@@ -5,6 +5,10 @@ import {
|
|
|
5
5
|
SET_WORKSPACE_ENDPOINT,
|
|
6
6
|
validWorkspacePayload,
|
|
7
7
|
} from '../shared/workspace-rpc.mjs';
|
|
8
|
+
import {
|
|
9
|
+
SET_AGENT_PRESET_ENDPOINT,
|
|
10
|
+
validAgentPresetPayload,
|
|
11
|
+
} from '../shared/agent-preset-rpc.mjs';
|
|
8
12
|
|
|
9
13
|
export const SLACK_RPC_CHANNEL = '/slack';
|
|
10
14
|
export const SLACK_ENDPOINTS = Object.freeze({
|
|
@@ -13,6 +17,7 @@ export const SLACK_ENDPOINTS = Object.freeze({
|
|
|
13
17
|
reconnectBot: 'bot.reconnect',
|
|
14
18
|
deleteBot: 'bot.delete',
|
|
15
19
|
setWorkspace: SET_WORKSPACE_ENDPOINT,
|
|
20
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
16
21
|
});
|
|
17
22
|
export const SLACK_RPC_ENDPOINTS = Object.freeze(Object.values(SLACK_ENDPOINTS));
|
|
18
23
|
|
|
@@ -66,6 +71,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
66
71
|
return validWorkspacePayload(payload)
|
|
67
72
|
? null : '请输入工作区绝对路径。';
|
|
68
73
|
}
|
|
74
|
+
if (endpoint === SLACK_ENDPOINTS.setAgentPreset) {
|
|
75
|
+
return validAgentPresetPayload(payload)
|
|
76
|
+
? null : '请选择 Agent Preset。';
|
|
77
|
+
}
|
|
69
78
|
return 'Unknown Slack endpoint.';
|
|
70
79
|
}
|
|
71
80
|
|
|
@@ -145,6 +154,10 @@ export function createSlackRpcHandler(controller) {
|
|
|
145
154
|
if (typeof controller.updateWorkspace !== 'function') throw new Error('Workspace update is unavailable');
|
|
146
155
|
value = await controller.updateWorkspace(payload.botId, payload.workspace);
|
|
147
156
|
}
|
|
157
|
+
else if (endpoint === SLACK_ENDPOINTS.setAgentPreset) {
|
|
158
|
+
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
|
159
|
+
value = await controller.updateAgentPreset(payload.botId, payload.agentPreset);
|
|
160
|
+
}
|
|
148
161
|
else value = await controller.deleteBot(payload.botId);
|
|
149
162
|
return signal?.aborted
|
|
150
163
|
? { ok: false, error: { code: 'cancelled', message: 'The request was cancelled.' } }
|
|
@@ -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';
|
|
@@ -57,7 +58,9 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
57
58
|
?? await new WorkspaceStore(paths.workspaces, { defaultWorkspace }).load();
|
|
58
59
|
const configuredBots = configStore.list();
|
|
59
60
|
await workspaces.reconcile(configuredBots.map((bot) => bot.botId));
|
|
60
|
-
await Promise.all(configuredBots.map((bot) => workspaces.ensure(bot.botId
|
|
61
|
+
await Promise.all(configuredBots.map((bot) => workspaces.ensure(bot.botId, {
|
|
62
|
+
defaultAgentPreset: config.agentPreset,
|
|
63
|
+
})));
|
|
61
64
|
const observedConfigStore = typeof configStore.remove === 'function'
|
|
62
65
|
? observeBotWorkspaceRemovals(configStore, { workspaces })
|
|
63
66
|
: configStore;
|
|
@@ -83,7 +86,6 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
83
86
|
const harness = new Harness({
|
|
84
87
|
baseUrl: harnessOrigin(ctx.webServer, config.harnessBaseUrl),
|
|
85
88
|
workspace: defaultWorkspace,
|
|
86
|
-
...(config.agentPreset == null ? {} : { agentPreset: config.agentPreset }),
|
|
87
89
|
autostart: false,
|
|
88
90
|
dshBin: config.dshBin ?? 'dsh',
|
|
89
91
|
...(commandExecutor ? { commandExecutor } : {}),
|
|
@@ -97,7 +99,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
97
99
|
logger,
|
|
98
100
|
createRuntime: async ({ botId, config: botConfig, secret }) => {
|
|
99
101
|
const state = await stateFor(botId);
|
|
100
|
-
await workspaces.ensure(botId);
|
|
102
|
+
await workspaces.ensure(botId, { defaultAgentPreset: config.agentPreset });
|
|
101
103
|
const workspaceScope = createBotWorkspaceScope(harness, { botId, workspaces, state });
|
|
102
104
|
return new Runtime({
|
|
103
105
|
config: botConfig,
|
|
@@ -129,7 +131,11 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
129
131
|
}
|
|
130
132
|
},
|
|
131
133
|
});
|
|
132
|
-
const controller = createWorkspaceAwareController(coreController, {
|
|
134
|
+
const controller = createWorkspaceAwareController(coreController, {
|
|
135
|
+
workspaces,
|
|
136
|
+
stateFor,
|
|
137
|
+
agentPresetCatalog: () => listAgentPresetCatalog(ctx),
|
|
138
|
+
});
|
|
133
139
|
const supervisor = createSupervisor({
|
|
134
140
|
controller,
|
|
135
141
|
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 WECOM_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
|
});
|
|
20
22
|
export const WECOM_RPC_ENDPOINTS = Object.freeze(Object.values(WECOM_ENDPOINTS));
|
|
21
23
|
|
|
@@ -70,6 +72,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
70
72
|
return validWorkspacePayload(payload)
|
|
71
73
|
? null : '请输入工作区绝对路径。';
|
|
72
74
|
}
|
|
75
|
+
if (endpoint === WECOM_ENDPOINTS.setAgentPreset) {
|
|
76
|
+
return validAgentPresetPayload(payload)
|
|
77
|
+
? null : '请选择 Agent Preset。';
|
|
78
|
+
}
|
|
73
79
|
return 'Unknown Enterprise WeChat endpoint.';
|
|
74
80
|
}
|
|
75
81
|
|
|
@@ -166,6 +172,12 @@ export function createWecomRpcHandler(controller, { encodeQr = qrDataUrl } = {})
|
|
|
166
172
|
await controller.updateWorkspace(payload.botId, payload.workspace),
|
|
167
173
|
cachedEncode,
|
|
168
174
|
);
|
|
175
|
+
} else if (endpoint === WECOM_ENDPOINTS.setAgentPreset) {
|
|
176
|
+
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
|
177
|
+
value = await publicStatus(
|
|
178
|
+
await controller.updateAgentPreset(payload.botId, payload.agentPreset),
|
|
179
|
+
cachedEncode,
|
|
180
|
+
);
|
|
169
181
|
} else {
|
|
170
182
|
value = await publicStatus(await controller.deleteBot(payload.botId), cachedEncode);
|
|
171
183
|
}
|
|
@@ -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';
|
|
@@ -60,7 +61,9 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
60
61
|
?? await new WorkspaceStore(paths.workspaces, { defaultWorkspace }).load();
|
|
61
62
|
const configuredBots = configStore.list();
|
|
62
63
|
await workspaces.reconcile(configuredBots.map((bot) => bot.botId));
|
|
63
|
-
await Promise.all(configuredBots.map((bot) => workspaces.ensure(bot.botId
|
|
64
|
+
await Promise.all(configuredBots.map((bot) => workspaces.ensure(bot.botId, {
|
|
65
|
+
defaultAgentPreset: config.agentPreset,
|
|
66
|
+
})));
|
|
64
67
|
const observedConfigStore = typeof configStore.remove === 'function'
|
|
65
68
|
? observeBotWorkspaceRemovals(configStore, { workspaces })
|
|
66
69
|
: configStore;
|
|
@@ -83,7 +86,6 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
83
86
|
const harness = new Harness({
|
|
84
87
|
baseUrl: harnessOrigin(ctx.webServer, config.harnessBaseUrl),
|
|
85
88
|
workspace: defaultWorkspace,
|
|
86
|
-
...(config.agentPreset == null ? {} : { agentPreset: config.agentPreset }),
|
|
87
89
|
autostart: false,
|
|
88
90
|
dshBin: config.dshBin ?? 'dsh',
|
|
89
91
|
...(commandExecutor ? { commandExecutor } : {}),
|
|
@@ -97,7 +99,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
97
99
|
logger,
|
|
98
100
|
createRuntime: async ({ botId, config: accountConfig, token }) => {
|
|
99
101
|
const state = await stateFor(botId);
|
|
100
|
-
await workspaces.ensure(botId);
|
|
102
|
+
await workspaces.ensure(botId, { defaultAgentPreset: config.agentPreset });
|
|
101
103
|
const workspaceScope = createBotWorkspaceScope(harness, { botId, workspaces, state });
|
|
102
104
|
return new Runtime({
|
|
103
105
|
api,
|
|
@@ -129,7 +131,11 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
129
131
|
}
|
|
130
132
|
},
|
|
131
133
|
});
|
|
132
|
-
const controller = createWorkspaceAwareController(coreController, {
|
|
134
|
+
const controller = createWorkspaceAwareController(coreController, {
|
|
135
|
+
workspaces,
|
|
136
|
+
stateFor,
|
|
137
|
+
agentPresetCatalog: () => listAgentPresetCatalog(ctx),
|
|
138
|
+
});
|
|
133
139
|
const supervisor = createSupervisor({
|
|
134
140
|
controller,
|
|
135
141
|
harness,
|