@xmanrui/dsh-im 0.19.0 → 1.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmanrui/dsh-im",
3
- "version": "0.19.0",
3
+ "version": "1.0.0",
4
4
  "description": "把九种 IM 机器人和公网 AI Office 接入本机 DeepSeek Harness。 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -53,6 +53,7 @@ export async function createProductionController(ctx, config = {}, internals = {
53
53
  const logger = typeof ctx.logger === 'function'
54
54
  ? ctx.logger('dsh-dingtalk')
55
55
  : (ctx.logger ?? console);
56
+ const agentPresetCatalog = () => listAgentPresetCatalog(ctx);
56
57
  const paths = pluginPaths(config);
57
58
  const configStore = await new ConfigStore(paths.config).load();
58
59
  const defaultWorkspace = resolve(config.workspace ?? process.cwd());
@@ -106,7 +107,9 @@ export async function createProductionController(ctx, config = {}, internals = {
106
107
  createRuntime: async ({ botId, config: botConfig, clientSecret }) => {
107
108
  const state = await stateFor(botId);
108
109
  await workspaces.ensure(botId, { defaultAgentPreset: config.agentPreset });
109
- const workspaceScope = createBotWorkspaceScope(harness, { botId, workspaces, state });
110
+ const workspaceScope = createBotWorkspaceScope(harness, {
111
+ botId, workspaces, state, agentPresetCatalog,
112
+ });
110
113
  return new Runtime({
111
114
  config: botConfig,
112
115
  clientSecret,
@@ -140,7 +143,7 @@ export async function createProductionController(ctx, config = {}, internals = {
140
143
  const controller = createWorkspaceAwareController(coreController, {
141
144
  workspaces,
142
145
  stateFor,
143
- agentPresetCatalog: () => listAgentPresetCatalog(ctx),
146
+ agentPresetCatalog,
144
147
  });
145
148
  const supervisor = createSupervisor({
146
149
  controller,
@@ -66,6 +66,7 @@ export async function createProductionController(ctx, config = {}, internals = {
66
66
  const logger = typeof ctx.logger === 'function'
67
67
  ? ctx.logger('dsh-feishu')
68
68
  : (ctx.logger ?? console);
69
+ const agentPresetCatalog = () => listAgentPresetCatalog(ctx);
69
70
  const paths = pluginPaths(config);
70
71
  const configStore = await new ConfigStore(paths.config).load();
71
72
  const defaultWorkspace = resolve(config.workspace ?? process.cwd());
@@ -136,7 +137,9 @@ export async function createProductionController(ctx, config = {}, internals = {
136
137
  const state = await stateFor(botConfig);
137
138
  const id = botId ?? botConfig.id ?? botConfig.appId;
138
139
  await workspaces.ensure(id, { defaultAgentPreset: config.agentPreset });
139
- const workspaceScope = createBotWorkspaceScope(harness, { botId: id, workspaces, state });
140
+ const workspaceScope = createBotWorkspaceScope(harness, {
141
+ botId: id, workspaces, state, agentPresetCatalog,
142
+ });
140
143
  return new Runtime({
141
144
  lark,
142
145
  botId: id,
@@ -170,7 +173,7 @@ export async function createProductionController(ctx, config = {}, internals = {
170
173
  const controller = createWorkspaceAwareController(coreController, {
171
174
  workspaces,
172
175
  stateFor: stateForBotId,
173
- agentPresetCatalog: () => listAgentPresetCatalog(ctx),
176
+ agentPresetCatalog,
174
177
  });
175
178
 
176
179
  const supervisor = createSupervisor({
@@ -50,6 +50,7 @@ export async function createProductionController(ctx, config = {}, internals = {
50
50
  const QrAuth = internals.QrAuth ?? QqQrAuth;
51
51
  const createSupervisor = internals.createConnectionSupervisor ?? createConnectionSupervisor;
52
52
  const logger = typeof ctx.logger === 'function' ? ctx.logger('dsh-im:qq') : (ctx.logger ?? console);
53
+ const agentPresetCatalog = () => listAgentPresetCatalog(ctx);
53
54
  const paths = pluginPaths(config);
54
55
  const configStore = await new ConfigStore(paths.config).load();
55
56
  const defaultWorkspace = resolve(config.workspace ?? process.cwd());
@@ -97,7 +98,9 @@ export async function createProductionController(ctx, config = {}, internals = {
97
98
  createRuntime: async ({ botId, config: botConfig, appSecret }) => {
98
99
  const state = await stateFor(botId);
99
100
  await workspaces.ensure(botId, { defaultAgentPreset: config.agentPreset });
100
- const workspaceScope = createBotWorkspaceScope(harness, { botId, workspaces, state });
101
+ const workspaceScope = createBotWorkspaceScope(harness, {
102
+ botId, workspaces, state, agentPresetCatalog,
103
+ });
101
104
  return new Runtime({
102
105
  config: botConfig,
103
106
  appSecret,
@@ -130,7 +133,7 @@ export async function createProductionController(ctx, config = {}, internals = {
130
133
  const controller = createWorkspaceAwareController(coreController, {
131
134
  workspaces,
132
135
  stateFor,
133
- agentPresetCatalog: () => listAgentPresetCatalog(ctx),
136
+ agentPresetCatalog,
134
137
  });
135
138
  const supervisor = createSupervisor({
136
139
  controller,
@@ -52,6 +52,7 @@ export async function createTokenProductionController(ctx, config, internals, de
52
52
  const createSupervisor = internals.createConnectionSupervisor ?? createTokenConnectionSupervisor;
53
53
  const logger = typeof ctx.logger === 'function'
54
54
  ? ctx.logger(`dsh-im:${channel}`) : (ctx.logger ?? console);
55
+ const agentPresetCatalog = () => listAgentPresetCatalog(ctx);
55
56
  const paths = pluginPaths(config, channel);
56
57
  const configStore = await new ResolvedConfigStore(paths.config).load();
57
58
  const defaultWorkspace = resolve(config.workspace ?? process.cwd());
@@ -98,7 +99,9 @@ export async function createTokenProductionController(ctx, config, internals, de
98
99
  createRuntime: async ({ botId, config: botConfig, token }) => {
99
100
  const state = await stateFor(botId);
100
101
  await workspaces.ensure(botId, { defaultAgentPreset: config.agentPreset });
101
- const workspaceScope = createBotWorkspaceScope(harness, { botId, workspaces, state });
102
+ const workspaceScope = createBotWorkspaceScope(harness, {
103
+ botId, workspaces, state, agentPresetCatalog,
104
+ });
102
105
  return new ResolvedRuntime({
103
106
  ...channelRuntimeOptions,
104
107
  config: botConfig,
@@ -132,7 +135,7 @@ export async function createTokenProductionController(ctx, config, internals, de
132
135
  const controller = createWorkspaceAwareController(coreController, {
133
136
  workspaces,
134
137
  stateFor,
135
- agentPresetCatalog: () => listAgentPresetCatalog(ctx),
138
+ agentPresetCatalog,
136
139
  });
137
140
  const supervisor = createSupervisor({
138
141
  channel,
@@ -30,6 +30,7 @@ export async function createProductionController(ctx, config = {}, internals = {
30
30
  const createSupervisor = internals.createConnectionSupervisor ?? createTokenConnectionSupervisor;
31
31
  const logger = typeof ctx.logger === 'function'
32
32
  ? ctx.logger('dsh-im:slack') : (ctx.logger ?? console);
33
+ const agentPresetCatalog = () => listAgentPresetCatalog(ctx);
33
34
  const paths = pluginPaths(config, 'slack');
34
35
  const configStore = await new ResolvedConfigStore(paths.config).load();
35
36
  const defaultWorkspace = resolve(config.workspace ?? process.cwd());
@@ -76,7 +77,9 @@ export async function createProductionController(ctx, config = {}, internals = {
76
77
  createRuntime: async ({ botId, config: botConfig, botToken, appToken }) => {
77
78
  const state = await stateFor(botId);
78
79
  await workspaces.ensure(botId, { defaultAgentPreset: config.agentPreset });
79
- const workspaceScope = createBotWorkspaceScope(harness, { botId, workspaces, state });
80
+ const workspaceScope = createBotWorkspaceScope(harness, {
81
+ botId, workspaces, state, agentPresetCatalog,
82
+ });
80
83
  return new ResolvedRuntime({
81
84
  config: botConfig,
82
85
  botToken,
@@ -110,7 +113,7 @@ export async function createProductionController(ctx, config = {}, internals = {
110
113
  const controller = createWorkspaceAwareController(coreController, {
111
114
  workspaces,
112
115
  stateFor,
113
- agentPresetCatalog: () => listAgentPresetCatalog(ctx),
116
+ agentPresetCatalog,
114
117
  });
115
118
  const supervisor = createSupervisor({
116
119
  channel: 'slack',
@@ -50,6 +50,7 @@ export async function createProductionController(ctx, config = {}, internals = {
50
50
  const QrAuth = internals.QrAuth ?? WecomQrAuth;
51
51
  const createSupervisor = internals.createConnectionSupervisor ?? createConnectionSupervisor;
52
52
  const logger = typeof ctx.logger === 'function' ? ctx.logger('dsh-im:wecom') : (ctx.logger ?? console);
53
+ const agentPresetCatalog = () => listAgentPresetCatalog(ctx);
53
54
  const paths = pluginPaths(config);
54
55
  const configStore = await new ConfigStore(paths.config).load();
55
56
  const defaultWorkspace = resolve(config.workspace ?? process.cwd());
@@ -100,7 +101,9 @@ export async function createProductionController(ctx, config = {}, internals = {
100
101
  createRuntime: async ({ botId, config: botConfig, secret }) => {
101
102
  const state = await stateFor(botId);
102
103
  await workspaces.ensure(botId, { defaultAgentPreset: config.agentPreset });
103
- const workspaceScope = createBotWorkspaceScope(harness, { botId, workspaces, state });
104
+ const workspaceScope = createBotWorkspaceScope(harness, {
105
+ botId, workspaces, state, agentPresetCatalog,
106
+ });
104
107
  return new Runtime({
105
108
  config: botConfig,
106
109
  secret,
@@ -134,7 +137,7 @@ export async function createProductionController(ctx, config = {}, internals = {
134
137
  const controller = createWorkspaceAwareController(coreController, {
135
138
  workspaces,
136
139
  stateFor,
137
- agentPresetCatalog: () => listAgentPresetCatalog(ctx),
140
+ agentPresetCatalog,
138
141
  });
139
142
  const supervisor = createSupervisor({
140
143
  controller,
@@ -53,6 +53,7 @@ export async function createProductionController(ctx, config = {}, internals = {
53
53
  const logger = typeof ctx.logger === 'function'
54
54
  ? ctx.logger('dsh-weixin')
55
55
  : (ctx.logger ?? console);
56
+ const agentPresetCatalog = () => listAgentPresetCatalog(ctx);
56
57
  const paths = pluginPaths(config);
57
58
  const configStore = await new ConfigStore(paths.config).load();
58
59
  const defaultWorkspace = resolve(config.workspace ?? process.cwd());
@@ -100,7 +101,9 @@ export async function createProductionController(ctx, config = {}, internals = {
100
101
  createRuntime: async ({ botId, config: accountConfig, token }) => {
101
102
  const state = await stateFor(botId);
102
103
  await workspaces.ensure(botId, { defaultAgentPreset: config.agentPreset });
103
- const workspaceScope = createBotWorkspaceScope(harness, { botId, workspaces, state });
104
+ const workspaceScope = createBotWorkspaceScope(harness, {
105
+ botId, workspaces, state, agentPresetCatalog,
106
+ });
104
107
  return new Runtime({
105
108
  api,
106
109
  config: accountConfig,
@@ -134,7 +137,7 @@ export async function createProductionController(ctx, config = {}, internals = {
134
137
  const controller = createWorkspaceAwareController(coreController, {
135
138
  workspaces,
136
139
  stateFor,
137
- agentPresetCatalog: () => listAgentPresetCatalog(ctx),
140
+ agentPresetCatalog,
138
141
  });
139
142
  const supervisor = createSupervisor({
140
143
  controller,
@@ -50,6 +50,7 @@ export async function createProductionController(ctx, config = {}, internals = {
50
50
  if (!ctx?.webServer) throw new TypeError('dsh-im WhatsApp requires ctx.webServer');
51
51
  const logger = typeof ctx.logger === 'function'
52
52
  ? ctx.logger('dsh-im:whatsapp') : (ctx.logger ?? console);
53
+ const agentPresetCatalog = () => listAgentPresetCatalog(ctx);
53
54
  const ConfigStore = internals.ConfigStore ?? WhatsappConfigStore;
54
55
  const StateStore = internals.StateStore ?? WhatsappStateStore;
55
56
  const Harness = internals.HarnessClient ?? WhatsappHarnessClient;
@@ -103,7 +104,9 @@ export async function createProductionController(ctx, config = {}, internals = {
103
104
  createRuntime: async ({ botId, config: botConfig, authDir }) => {
104
105
  const state = await stateFor(botId);
105
106
  await workspaces.ensure(botId, { defaultAgentPreset: config.agentPreset });
106
- const workspaceScope = createBotWorkspaceScope(harness, { botId, workspaces, state });
107
+ const workspaceScope = createBotWorkspaceScope(harness, {
108
+ botId, workspaces, state, agentPresetCatalog,
109
+ });
107
110
  return new Runtime({
108
111
  config: botConfig,
109
112
  authDir,
@@ -141,7 +144,7 @@ export async function createProductionController(ctx, config = {}, internals = {
141
144
  const controller = createWorkspaceAwareController(coreController, {
142
145
  workspaces,
143
146
  stateFor,
144
- agentPresetCatalog: () => listAgentPresetCatalog(ctx),
147
+ agentPresetCatalog,
145
148
  });
146
149
  const supervisor = createSupervisor({
147
150
  channel: 'whatsapp',
@@ -18,6 +18,10 @@ import {
18
18
  isModelCommand,
19
19
  runModelCommand,
20
20
  } from '../shared/model-command.mjs';
21
+ import {
22
+ isPresetCommand,
23
+ runPresetCommand,
24
+ } from '../shared/preset-command.mjs';
21
25
  import { runWorkspaceCommand } from '../shared/workspace-command.mjs';
22
26
  import { askInWorkspaceSession } from '../shared/workspace-session.mjs';
23
27
  import {
@@ -44,6 +48,10 @@ const HELP_TEXT = [
44
48
  '/models 按序号列出所有可用模型',
45
49
  '/model [序号或完整模型ID] 查看或切换当前会话模型',
46
50
  '示例:先发 /models,再发 /model 2',
51
+ '/presetlist 按序号列出可用 Agent Preset',
52
+ '/preset [序号或完整ID] 查看或设置当前机器人 Agent Preset',
53
+ '纯数字 ID:/preset id:<ID>',
54
+ '/preset --default 跟随 Host 默认',
47
55
  '/stop 停止当前任务',
48
56
  '/steer 补充指令 纠偏当前任务',
49
57
  '/status 检查连接状态',
@@ -336,7 +344,9 @@ export class DingtalkHarnessBridge {
336
344
  const commandText = nonEmptyString(promptMessage.content) ?? '';
337
345
  const commandRunner = isControlCommand(commandText)
338
346
  ? runControlCommand
339
- : (isModelCommand(commandText) ? runModelCommand : null);
347
+ : (isModelCommand(commandText)
348
+ ? runModelCommand
349
+ : (isPresetCommand(commandText) ? runPresetCommand : null));
340
350
  const addressed = String(message.conversationType) !== '2' || message?.isInAtList === true;
341
351
  if (commandRunner && sessionWebhook && addressed) {
342
352
  let task;
@@ -108,7 +108,7 @@ export class DiscordApi {
108
108
  headers: {
109
109
  authorization: `Bot ${this.#token}`,
110
110
  'content-type': 'application/json',
111
- 'user-agent': 'DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 0.19.0)',
111
+ 'user-agent': 'DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 1.0.0)',
112
112
  },
113
113
  ...(body === undefined ? {} : { body: JSON.stringify(body) }),
114
114
  signal: requestSignal(signal, timeoutMs),
@@ -28,6 +28,10 @@ import {
28
28
  isModelCommand,
29
29
  runModelCommand,
30
30
  } from '../shared/model-command.mjs';
31
+ import {
32
+ isPresetCommand,
33
+ runPresetCommand,
34
+ } from '../shared/preset-command.mjs';
31
35
  import { runWorkspaceCommand, resolveSessionListWorkspace, workspacePathSnapshot } from '../shared/workspace-command.mjs';
32
36
  import { askInWorkspaceSession } from '../shared/workspace-session.mjs';
33
37
  import {
@@ -88,6 +92,10 @@ const HELP_TEXT = [
88
92
  '/models 按序号列出所有可用模型',
89
93
  '/model [序号或完整模型ID] 查看或切换当前会话模型',
90
94
  '示例:先发 /models,再发 /model 2',
95
+ '/presetlist 按序号列出可用 Agent Preset',
96
+ '/preset [序号或完整ID] 查看或设置当前机器人 Agent Preset',
97
+ '纯数字 ID:/preset id:<ID>',
98
+ '/preset --default 跟随 Host 默认',
91
99
  '/stop 停止当前任务',
92
100
  '/steer 补充指令 纠偏当前任务',
93
101
  '/status 检查连接状态',
@@ -389,7 +397,9 @@ export class FeishuHarnessBridge {
389
397
  const commandText = nonEmptyString(commandMessage.content) ?? '';
390
398
  const commandRunner = isControlCommand(commandText)
391
399
  ? runControlCommand
392
- : (isModelCommand(commandText) ? runModelCommand : null);
400
+ : (isModelCommand(commandText)
401
+ ? runModelCommand
402
+ : (isPresetCommand(commandText) ? runPresetCommand : null));
393
403
  if (commandRunner && addressed) {
394
404
  const processing = this.#processFastCommand(
395
405
  event,
@@ -189,6 +189,10 @@ export function menuHelpText() {
189
189
  '/watch ID 或序号 关注会话(完成后推送)',
190
190
  '/compact 压缩上下文',
191
191
  '/workspace 绝对路径 切换工作区',
192
+ '/presetlist 列出可用 Agent Preset',
193
+ '/preset [序号或完整ID] 查看或设置当前机器人 Agent Preset',
194
+ '纯数字 ID:/preset id:<ID>',
195
+ '/preset --default 跟随 Host 默认',
192
196
  ].join('\n');
193
197
  }
194
198
 
@@ -15,6 +15,10 @@ import {
15
15
  isModelCommand,
16
16
  runModelCommand,
17
17
  } from '../shared/model-command.mjs';
18
+ import {
19
+ isPresetCommand,
20
+ runPresetCommand,
21
+ } from '../shared/preset-command.mjs';
18
22
  import { askInWorkspaceSession } from '../shared/workspace-session.mjs';
19
23
  import {
20
24
  fetchImageBuffer,
@@ -49,6 +53,10 @@ const HELP_TEXT = [
49
53
  '/models 按序号列出所有可用模型',
50
54
  '/model [序号或完整模型ID] 查看或切换当前会话模型',
51
55
  '示例:先发 /models,再发 /model 2',
56
+ '/presetlist 按序号列出可用 Agent Preset',
57
+ '/preset [序号或完整ID] 查看或设置当前机器人 Agent Preset',
58
+ '纯数字 ID:/preset id:<ID>',
59
+ '/preset --default 跟随 Host 默认',
52
60
  '/stop 停止当前任务',
53
61
  '/steer 补充指令 纠偏当前任务',
54
62
  '/status 检查连接状态',
@@ -201,7 +209,9 @@ export class QqHarnessBridge {
201
209
  const commandText = safeText(message);
202
210
  const commandRunner = isControlCommand(commandText)
203
211
  ? runControlCommand
204
- : (isModelCommand(commandText) ? runModelCommand : null);
212
+ : (isModelCommand(commandText)
213
+ ? runModelCommand
214
+ : (isPresetCommand(commandText) ? runPresetCommand : null));
205
215
  const allowed = this.#ownerUserOpenid === '*' || sender === this.#ownerUserOpenid;
206
216
  const addressed = message.kind !== 'group'
207
217
  || message.rawEventType === 'GROUP_AT_MESSAGE_CREATE';
@@ -535,6 +535,19 @@ function resolveAgentPresetCatalog(catalog) {
535
535
  : normalizeAgentPresetCatalog(value);
536
536
  }
537
537
 
538
+ function unavailableAgentPreset() {
539
+ const error = new Error('Agent Preset 不存在或不可用。');
540
+ error.code = 'agent-preset-unavailable';
541
+ return error;
542
+ }
543
+
544
+ function assertCurrentBotScope(isCurrentScope) {
545
+ if (isCurrentScope()) return;
546
+ const error = new Error('找不到要修改的机器人。');
547
+ error.code = 'workspace-bot-not-found';
548
+ throw error;
549
+ }
550
+
538
551
  function decorateResult(workspaces, result, catalog) {
539
552
  const decorate = (value) => {
540
553
  const decorated = workspaces.decorateStatus(value);
@@ -580,14 +593,74 @@ export function observeBotWorkspaceRemovals(
580
593
  });
581
594
  }
582
595
 
583
- export function createBotWorkspaceScope(harness, { botId, workspaces, state }) {
596
+ export function createBotWorkspaceScope(
597
+ harness,
598
+ { botId, workspaces, state, agentPresetCatalog } = {},
599
+ ) {
584
600
  if (!harness || !workspaces || !state) throw new TypeError('harness, workspaces, and state are required');
585
601
  const incarnation = workspaces.incarnationFor(botId);
586
602
  const isCurrentScope = () => workspaces.has(botId)
587
603
  && workspaces.incarnationFor(botId) === incarnation;
604
+ const presetSettings = async (catalog = agentPresetCatalog) => {
605
+ let normalizedCatalog;
606
+ try {
607
+ normalizedCatalog = await resolveAgentPresetCatalog(catalog)
608
+ ?? normalizeAgentPresetCatalog(null);
609
+ } catch (error) {
610
+ assertCurrentBotScope(isCurrentScope);
611
+ throw error;
612
+ }
613
+ assertCurrentBotScope(isCurrentScope);
614
+ return {
615
+ agentPreset: workspaces.agentPresetFor(botId),
616
+ agentPresetCatalog: normalizedCatalog,
617
+ };
618
+ };
588
619
  const sessionGenerations = new Map();
589
620
  const scopedHarness = new Proxy(harness, {
590
621
  get(target, property) {
622
+ if (property === 'agentPresetSettings') {
623
+ return async (options = {}) => {
624
+ options?.signal?.throwIfAborted();
625
+ assertCurrentBotScope(isCurrentScope);
626
+ const settings = await presetSettings();
627
+ options?.signal?.throwIfAborted();
628
+ return settings;
629
+ };
630
+ }
631
+ if (property === 'updateAgentPreset') {
632
+ return async (value, options = {}) => {
633
+ options?.signal?.throwIfAborted();
634
+ assertCurrentBotScope(isCurrentScope);
635
+ const agentPreset = value === '--default' ? null : validateAgentPresetId(value);
636
+ let catalog = null;
637
+ if (agentPreset) {
638
+ ({ agentPresetCatalog: catalog } = await presetSettings());
639
+ options?.signal?.throwIfAborted();
640
+ if (!catalog.items.some((item) => item.id === agentPreset)) {
641
+ throw unavailableAgentPreset();
642
+ }
643
+ }
644
+ await workspaces.setAgentPreset(botId, agentPreset, { incarnation });
645
+ assertCurrentBotScope(isCurrentScope);
646
+ if (catalog) {
647
+ return {
648
+ agentPreset: workspaces.agentPresetFor(botId),
649
+ agentPresetCatalog: catalog,
650
+ };
651
+ }
652
+ try {
653
+ return await presetSettings();
654
+ } catch (error) {
655
+ if (error?.code === 'workspace-bot-not-found') throw error;
656
+ assertCurrentBotScope(isCurrentScope);
657
+ return {
658
+ agentPreset: workspaces.agentPresetFor(botId),
659
+ agentPresetCatalog: normalizeAgentPresetCatalog(null),
660
+ };
661
+ }
662
+ };
663
+ }
591
664
  if (property === 'currentWorkspace') {
592
665
  return () => {
593
666
  if (!isCurrentScope()) {
@@ -912,9 +985,7 @@ export function createWorkspaceAwareController(controller, { workspaces, stateFo
912
985
  : null;
913
986
  if (normalizedAgentPreset && agentPresetCatalog
914
987
  && !catalog?.items.some((item) => item.id === normalizedAgentPreset)) {
915
- const error = new Error('Agent Preset 不存在或不可用。');
916
- error.code = 'agent-preset-unavailable';
917
- throw error;
988
+ throw unavailableAgentPreset();
918
989
  }
919
990
  await workspaces.setAgentPreset(botId, normalizedAgentPreset, { incarnation });
920
991
  return decorateResult(