@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
|
@@ -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.
|
|
111
|
+
'user-agent': 'DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 0.18.0)',
|
|
112
112
|
},
|
|
113
113
|
...(body === undefined ? {} : { body: JSON.stringify(body) }),
|
|
114
114
|
signal: requestSignal(signal, timeoutMs),
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/** Matches DeepSeek Harness agent-preset directory ids. */
|
|
2
|
+
export const AGENT_PRESET_ID = /^[a-z0-9][a-z0-9-]*$/;
|
|
3
|
+
|
|
4
|
+
export const EMPTY_AGENT_PRESET_CATALOG = Object.freeze({
|
|
5
|
+
defaultId: '',
|
|
6
|
+
items: Object.freeze([]),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export function normalizeAgentPresetId(value) {
|
|
10
|
+
if (value == null) return null;
|
|
11
|
+
if (typeof value !== 'string') return null;
|
|
12
|
+
const id = value.trim();
|
|
13
|
+
return AGENT_PRESET_ID.test(id) ? id : null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function validateAgentPresetId(value) {
|
|
17
|
+
if (value == null || value === '') return null;
|
|
18
|
+
const id = normalizeAgentPresetId(value);
|
|
19
|
+
if (!id) {
|
|
20
|
+
const error = new Error('Agent Preset 无效。');
|
|
21
|
+
error.code = 'agent-preset-invalid';
|
|
22
|
+
throw error;
|
|
23
|
+
}
|
|
24
|
+
return id;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function catalogItem(value) {
|
|
28
|
+
if (typeof value === 'string') {
|
|
29
|
+
const id = normalizeAgentPresetId(value);
|
|
30
|
+
return id ? { id, label: id } : null;
|
|
31
|
+
}
|
|
32
|
+
if (!value || typeof value !== 'object') return null;
|
|
33
|
+
if (value.broken !== undefined) return null;
|
|
34
|
+
const id = normalizeAgentPresetId(value.id);
|
|
35
|
+
if (!id) return null;
|
|
36
|
+
const label = typeof value.name === 'string' && value.name.trim()
|
|
37
|
+
? value.name.trim().slice(0, 128)
|
|
38
|
+
: typeof value.label === 'string' && value.label.trim()
|
|
39
|
+
? value.label.trim().slice(0, 128)
|
|
40
|
+
: id;
|
|
41
|
+
return { id, label };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function normalizeAgentPresetCatalog(value) {
|
|
45
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
46
|
+
return { defaultId: '', items: [] };
|
|
47
|
+
}
|
|
48
|
+
const items = [];
|
|
49
|
+
const seen = new Set();
|
|
50
|
+
for (const entry of Array.isArray(value.items) ? value.items : []) {
|
|
51
|
+
const item = catalogItem(entry);
|
|
52
|
+
if (!item || seen.has(item.id)) continue;
|
|
53
|
+
seen.add(item.id);
|
|
54
|
+
items.push(item);
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
defaultId: normalizeAgentPresetId(value.defaultId) ?? '',
|
|
58
|
+
items,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export async function listAgentPresetCatalog(ctx) {
|
|
63
|
+
try {
|
|
64
|
+
const service = typeof ctx?.get === 'function' ? ctx.get('agentPresets') : ctx?.agentPresets;
|
|
65
|
+
if (!service || typeof service.list !== 'function') return { defaultId: '', items: [] };
|
|
66
|
+
const listed = await service.list();
|
|
67
|
+
return normalizeAgentPresetCatalog({
|
|
68
|
+
defaultId: typeof service.defaultId === 'string' ? service.defaultId : '',
|
|
69
|
+
items: Array.isArray(listed) ? listed : [],
|
|
70
|
+
});
|
|
71
|
+
} catch {
|
|
72
|
+
return { defaultId: '', items: [] };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -9,6 +9,10 @@ import {
|
|
|
9
9
|
} from 'node:fs/promises';
|
|
10
10
|
import { dirname, isAbsolute, resolve } from 'node:path';
|
|
11
11
|
|
|
12
|
+
import {
|
|
13
|
+
normalizeAgentPresetCatalog,
|
|
14
|
+
validateAgentPresetId,
|
|
15
|
+
} from './agent-preset.mjs';
|
|
12
16
|
import { CONNECTION_TEST_STATE_IDENTITY } from './connection-test.mjs';
|
|
13
17
|
import { WORKSPACE_SESSION_STALE } from './workspace-session.mjs';
|
|
14
18
|
|
|
@@ -49,7 +53,22 @@ function normalizeDocument(value) {
|
|
|
49
53
|
|| typeof workspace !== 'string' || !isAbsolute(workspace)) return null;
|
|
50
54
|
workspaces[botId] = resolve(workspace);
|
|
51
55
|
}
|
|
52
|
-
|
|
56
|
+
let agentPresets = {};
|
|
57
|
+
if (value.agentPresets !== undefined) {
|
|
58
|
+
if (!value.agentPresets || typeof value.agentPresets !== 'object'
|
|
59
|
+
|| Array.isArray(value.agentPresets)) return null;
|
|
60
|
+
for (const [botId, agentPreset] of Object.entries(value.agentPresets)) {
|
|
61
|
+
if (!/^[A-Za-z0-9_-]{1,128}$/.test(botId)) return null;
|
|
62
|
+
try {
|
|
63
|
+
const normalized = validateAgentPresetId(agentPreset);
|
|
64
|
+
if (!normalized) return null;
|
|
65
|
+
agentPresets[botId] = normalized;
|
|
66
|
+
} catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return { version: 1, workspaces, agentPresets };
|
|
53
72
|
}
|
|
54
73
|
|
|
55
74
|
export async function validateWorkspacePath(value) {
|
|
@@ -79,6 +98,7 @@ export class BotWorkspaceStore {
|
|
|
79
98
|
#path;
|
|
80
99
|
#defaultWorkspace;
|
|
81
100
|
#workspaces = {};
|
|
101
|
+
#agentPresets = {};
|
|
82
102
|
#generations = new Map();
|
|
83
103
|
#nextGeneration = 1;
|
|
84
104
|
#incarnations = new Map();
|
|
@@ -100,9 +120,11 @@ export class BotWorkspaceStore {
|
|
|
100
120
|
const normalized = normalizeDocument(JSON.parse(await readFile(this.#path, 'utf8')));
|
|
101
121
|
if (!normalized) throw new Error('dsh-im workspace config is invalid');
|
|
102
122
|
this.#workspaces = normalized.workspaces;
|
|
123
|
+
this.#agentPresets = normalized.agentPresets;
|
|
103
124
|
} catch (error) {
|
|
104
125
|
if (error?.code !== 'ENOENT') throw error;
|
|
105
126
|
this.#workspaces = {};
|
|
127
|
+
this.#agentPresets = {};
|
|
106
128
|
}
|
|
107
129
|
this.#generations.clear();
|
|
108
130
|
this.#nextGeneration = 1;
|
|
@@ -130,6 +152,10 @@ export class BotWorkspaceStore {
|
|
|
130
152
|
return this.#workspaces[botIdOf(botId)] ?? this.#defaultWorkspace;
|
|
131
153
|
}
|
|
132
154
|
|
|
155
|
+
agentPresetFor(botId) {
|
|
156
|
+
return this.#agentPresets[botIdOf(botId)] ?? null;
|
|
157
|
+
}
|
|
158
|
+
|
|
133
159
|
generationFor(botId) {
|
|
134
160
|
return this.#generations.get(botIdOf(botId)) ?? null;
|
|
135
161
|
}
|
|
@@ -148,18 +174,24 @@ export class BotWorkspaceStore {
|
|
|
148
174
|
}
|
|
149
175
|
}
|
|
150
176
|
|
|
151
|
-
async ensure(botId, { workspace = this.#defaultWorkspace } = {}) {
|
|
177
|
+
async ensure(botId, { workspace = this.#defaultWorkspace, defaultAgentPreset } = {}) {
|
|
152
178
|
const id = botIdOf(botId);
|
|
153
179
|
const initialWorkspace = resolve(workspace);
|
|
154
180
|
return this.#enqueue(id, async () => {
|
|
155
181
|
if (!this.#workspaces[id]) {
|
|
182
|
+
const agentPreset = validateAgentPresetId(defaultAgentPreset);
|
|
183
|
+
const hadAgentPreset = Object.hasOwn(this.#agentPresets, id);
|
|
184
|
+
const previousAgentPreset = this.#agentPresets[id];
|
|
156
185
|
this.#workspaces[id] = initialWorkspace;
|
|
186
|
+
if (agentPreset) this.#agentPresets[id] = agentPreset;
|
|
157
187
|
this.#generations.set(id, this.#freshGeneration());
|
|
158
188
|
this.#incarnations.set(id, this.#freshIncarnation());
|
|
159
189
|
try {
|
|
160
190
|
await this.#persist();
|
|
161
191
|
} catch (error) {
|
|
162
192
|
delete this.#workspaces[id];
|
|
193
|
+
if (hadAgentPreset) this.#agentPresets[id] = previousAgentPreset;
|
|
194
|
+
else delete this.#agentPresets[id];
|
|
163
195
|
this.#generations.delete(id);
|
|
164
196
|
this.#incarnations.delete(id);
|
|
165
197
|
throw error;
|
|
@@ -207,6 +239,37 @@ export class BotWorkspaceStore {
|
|
|
207
239
|
});
|
|
208
240
|
}
|
|
209
241
|
|
|
242
|
+
async setAgentPreset(botId, value, { incarnation } = {}) {
|
|
243
|
+
const id = botIdOf(botId);
|
|
244
|
+
if (!this.has(id)
|
|
245
|
+
|| (incarnation !== undefined && incarnation !== this.incarnationFor(id))) {
|
|
246
|
+
const error = new Error('找不到要修改的机器人。');
|
|
247
|
+
error.code = 'workspace-bot-not-found';
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
250
|
+
const agentPreset = validateAgentPresetId(value);
|
|
251
|
+
return this.#enqueue(id, async () => {
|
|
252
|
+
if (!this.has(id)
|
|
253
|
+
|| (incarnation !== undefined && incarnation !== this.incarnationFor(id))) {
|
|
254
|
+
const error = new Error('找不到要修改的机器人。');
|
|
255
|
+
error.code = 'workspace-bot-not-found';
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
258
|
+
const previous = this.#agentPresets[id] ?? null;
|
|
259
|
+
if (previous === agentPreset) return agentPreset;
|
|
260
|
+
if (agentPreset) this.#agentPresets[id] = agentPreset;
|
|
261
|
+
else delete this.#agentPresets[id];
|
|
262
|
+
try {
|
|
263
|
+
await this.#persist();
|
|
264
|
+
} catch (error) {
|
|
265
|
+
if (previous) this.#agentPresets[id] = previous;
|
|
266
|
+
else delete this.#agentPresets[id];
|
|
267
|
+
throw error;
|
|
268
|
+
}
|
|
269
|
+
return agentPreset;
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
210
273
|
async bindWorkspaceSession(botId, value, {
|
|
211
274
|
conversationKey,
|
|
212
275
|
sessionId,
|
|
@@ -353,7 +416,11 @@ export class BotWorkspaceStore {
|
|
|
353
416
|
|
|
354
417
|
async reconcile(activeBotIds) {
|
|
355
418
|
const active = new Set([...activeBotIds].map(botIdOf));
|
|
356
|
-
const candidates = new Set([
|
|
419
|
+
const candidates = new Set([
|
|
420
|
+
...Object.keys(this.#workspaces),
|
|
421
|
+
...Object.keys(this.#agentPresets),
|
|
422
|
+
...this.#dirtyRemovals,
|
|
423
|
+
]);
|
|
357
424
|
for (const botId of candidates) {
|
|
358
425
|
if (!active.has(botId)) await this.remove(botId);
|
|
359
426
|
}
|
|
@@ -364,7 +431,11 @@ export class BotWorkspaceStore {
|
|
|
364
431
|
return {
|
|
365
432
|
...status,
|
|
366
433
|
bots: status.bots.map((bot) => bot?.botId
|
|
367
|
-
? {
|
|
434
|
+
? {
|
|
435
|
+
...bot,
|
|
436
|
+
workspace: this.workspaceFor(bot.botId),
|
|
437
|
+
agentPreset: this.agentPresetFor(bot.botId),
|
|
438
|
+
}
|
|
368
439
|
: bot),
|
|
369
440
|
};
|
|
370
441
|
}
|
|
@@ -392,8 +463,10 @@ export class BotWorkspaceStore {
|
|
|
392
463
|
|
|
393
464
|
async #retireCurrentIncarnation(id) {
|
|
394
465
|
const hadWorkspace = Object.hasOwn(this.#workspaces, id);
|
|
395
|
-
const
|
|
466
|
+
const hadPreset = Object.hasOwn(this.#agentPresets, id);
|
|
467
|
+
const needsCleanup = hadWorkspace || hadPreset || this.#dirtyRemovals.has(id);
|
|
396
468
|
delete this.#workspaces[id];
|
|
469
|
+
delete this.#agentPresets[id];
|
|
397
470
|
this.#generations.delete(id);
|
|
398
471
|
this.#incarnations.delete(id);
|
|
399
472
|
if (!needsCleanup) return {
|
|
@@ -425,6 +498,9 @@ export class BotWorkspaceStore {
|
|
|
425
498
|
|
|
426
499
|
async #persist() {
|
|
427
500
|
const document = { version: 1, workspaces: this.#workspaces };
|
|
501
|
+
if (Object.keys(this.#agentPresets).length > 0) {
|
|
502
|
+
document.agentPresets = this.#agentPresets;
|
|
503
|
+
}
|
|
428
504
|
await mkdir(dirname(this.#path), { recursive: true, mode: 0o700 });
|
|
429
505
|
const temporary = `${this.#path}.tmp`;
|
|
430
506
|
await writeFile(temporary, `${JSON.stringify(document, null, 2)}\n`, {
|
|
@@ -436,7 +512,8 @@ export class BotWorkspaceStore {
|
|
|
436
512
|
}
|
|
437
513
|
|
|
438
514
|
async #persistCurrentDocument() {
|
|
439
|
-
if (Object.keys(this.#workspaces).length > 0
|
|
515
|
+
if (Object.keys(this.#workspaces).length > 0
|
|
516
|
+
|| Object.keys(this.#agentPresets).length > 0) {
|
|
440
517
|
await this.#persist();
|
|
441
518
|
return;
|
|
442
519
|
}
|
|
@@ -450,10 +527,29 @@ export class BotWorkspaceStore {
|
|
|
450
527
|
}
|
|
451
528
|
}
|
|
452
529
|
|
|
453
|
-
function
|
|
530
|
+
function resolveAgentPresetCatalog(catalog) {
|
|
531
|
+
if (!catalog) return null;
|
|
532
|
+
const value = typeof catalog === 'function' ? catalog() : catalog;
|
|
533
|
+
return value && typeof value.then === 'function'
|
|
534
|
+
? value.then(normalizeAgentPresetCatalog)
|
|
535
|
+
: normalizeAgentPresetCatalog(value);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
function decorateResult(workspaces, result, catalog) {
|
|
539
|
+
const decorate = (value) => {
|
|
540
|
+
const decorated = workspaces.decorateStatus(value);
|
|
541
|
+
if (!catalog || !decorated || typeof decorated !== 'object') return decorated;
|
|
542
|
+
const attachCatalog = (agentPresetCatalog) => (
|
|
543
|
+
agentPresetCatalog ? { ...decorated, agentPresetCatalog } : decorated
|
|
544
|
+
);
|
|
545
|
+
const agentPresetCatalog = resolveAgentPresetCatalog(catalog);
|
|
546
|
+
return agentPresetCatalog && typeof agentPresetCatalog.then === 'function'
|
|
547
|
+
? agentPresetCatalog.then(attachCatalog)
|
|
548
|
+
: attachCatalog(agentPresetCatalog);
|
|
549
|
+
};
|
|
454
550
|
return result && typeof result.then === 'function'
|
|
455
|
-
? result.then(
|
|
456
|
-
:
|
|
551
|
+
? result.then(decorate)
|
|
552
|
+
: decorate(result);
|
|
457
553
|
}
|
|
458
554
|
|
|
459
555
|
function targetStatus(controller) {
|
|
@@ -608,9 +704,11 @@ export function createBotWorkspaceScope(harness, { botId, workspaces, state }) {
|
|
|
608
704
|
throw error;
|
|
609
705
|
}
|
|
610
706
|
const generation = workspaces.generationFor(botId);
|
|
707
|
+
const agentPreset = workspaces.agentPresetFor(botId);
|
|
611
708
|
const sessionId = await target.createSession({
|
|
612
709
|
...options,
|
|
613
710
|
workspace: workspaces.workspaceFor(botId),
|
|
711
|
+
...(agentPreset == null ? {} : { agentPreset }),
|
|
614
712
|
});
|
|
615
713
|
sessionGenerations.set(sessionId, generation);
|
|
616
714
|
return sessionId;
|
|
@@ -765,7 +863,7 @@ export function createBotScopedHarness(harness, options) {
|
|
|
765
863
|
return createBotWorkspaceScope(harness, options).harness;
|
|
766
864
|
}
|
|
767
865
|
|
|
768
|
-
export function createWorkspaceAwareController(controller, { workspaces, stateFor }) {
|
|
866
|
+
export function createWorkspaceAwareController(controller, { workspaces, stateFor, agentPresetCatalog } = {}) {
|
|
769
867
|
if (!controller || !workspaces || typeof stateFor !== 'function') {
|
|
770
868
|
throw new TypeError('controller, workspaces, and stateFor are required');
|
|
771
869
|
}
|
|
@@ -778,6 +876,7 @@ export function createWorkspaceAwareController(controller, { workspaces, stateFo
|
|
|
778
876
|
if (transitions.get(botId) === current) transitions.delete(botId);
|
|
779
877
|
});
|
|
780
878
|
};
|
|
879
|
+
const decorate = (value) => decorateResult(workspaces, value, agentPresetCatalog);
|
|
781
880
|
const updateWorkspace = (botId, workspace) => {
|
|
782
881
|
// Capture at API invocation, before even waiting for an older outer
|
|
783
882
|
// transition. A queued request still belongs to the incarnation that the
|
|
@@ -795,7 +894,34 @@ export function createWorkspaceAwareController(controller, { workspaces, stateFo
|
|
|
795
894
|
clearSessions: () => state.clearSessions(),
|
|
796
895
|
incarnation,
|
|
797
896
|
});
|
|
798
|
-
return
|
|
897
|
+
return decorate(await controller.status());
|
|
898
|
+
});
|
|
899
|
+
};
|
|
900
|
+
const updateAgentPreset = (botId, agentPreset) => {
|
|
901
|
+
const incarnation = workspaces.incarnationFor(botId);
|
|
902
|
+
const normalizedAgentPreset = validateAgentPresetId(agentPreset);
|
|
903
|
+
return withBotTransition(botId, async () => {
|
|
904
|
+
const snapshot = await controller.status();
|
|
905
|
+
if (!snapshot?.bots?.some((bot) => bot?.botId === botId)) {
|
|
906
|
+
const error = new Error('找不到要修改的机器人。');
|
|
907
|
+
error.code = 'workspace-bot-not-found';
|
|
908
|
+
throw error;
|
|
909
|
+
}
|
|
910
|
+
const catalog = normalizedAgentPreset && agentPresetCatalog
|
|
911
|
+
? await resolveAgentPresetCatalog(agentPresetCatalog)
|
|
912
|
+
: null;
|
|
913
|
+
if (normalizedAgentPreset && agentPresetCatalog
|
|
914
|
+
&& !catalog?.items.some((item) => item.id === normalizedAgentPreset)) {
|
|
915
|
+
const error = new Error('Agent Preset 不存在或不可用。');
|
|
916
|
+
error.code = 'agent-preset-unavailable';
|
|
917
|
+
throw error;
|
|
918
|
+
}
|
|
919
|
+
await workspaces.setAgentPreset(botId, normalizedAgentPreset, { incarnation });
|
|
920
|
+
return decorateResult(
|
|
921
|
+
workspaces,
|
|
922
|
+
await controller.status(),
|
|
923
|
+
catalog ?? agentPresetCatalog,
|
|
924
|
+
);
|
|
799
925
|
});
|
|
800
926
|
};
|
|
801
927
|
const deleteWithWorkspace = (botId, invokeDelete) => withBotTransition(botId, async () => {
|
|
@@ -822,7 +948,7 @@ export function createWorkspaceAwareController(controller, { workspaces, stateFo
|
|
|
822
948
|
try {
|
|
823
949
|
const result = await invokeDelete();
|
|
824
950
|
await workspaces.finishRemoval(removal);
|
|
825
|
-
return
|
|
951
|
+
return decorate(result);
|
|
826
952
|
} catch (error) {
|
|
827
953
|
const after = await targetStatus(controller).catch(() => null);
|
|
828
954
|
const knownAbsent = Array.isArray(after?.bots)
|
|
@@ -836,6 +962,7 @@ export function createWorkspaceAwareController(controller, { workspaces, stateFo
|
|
|
836
962
|
return new Proxy(controller, {
|
|
837
963
|
get(target, property) {
|
|
838
964
|
if (property === 'updateWorkspace') return updateWorkspace;
|
|
965
|
+
if (property === 'updateAgentPreset') return updateAgentPreset;
|
|
839
966
|
const value = Reflect.get(target, property, target);
|
|
840
967
|
if (typeof value !== 'function') return value;
|
|
841
968
|
if (property === 'deleteBot') {
|
|
@@ -848,11 +975,11 @@ export function createWorkspaceAwareController(controller, { workspaces, stateFo
|
|
|
848
975
|
return async (...args) => {
|
|
849
976
|
const before = await target.status();
|
|
850
977
|
const botId = before?.bots?.[0]?.botId;
|
|
851
|
-
if (!botId) return
|
|
978
|
+
if (!botId) return decorate(value.apply(target, args));
|
|
852
979
|
return deleteWithWorkspace(botId, () => value.apply(target, args));
|
|
853
980
|
};
|
|
854
981
|
}
|
|
855
|
-
return (...args) =>
|
|
982
|
+
return (...args) => decorate(value.apply(target, args));
|
|
856
983
|
},
|
|
857
984
|
});
|
|
858
985
|
}
|
|
@@ -592,11 +592,13 @@ export class HarnessClient {
|
|
|
592
592
|
}
|
|
593
593
|
|
|
594
594
|
async createSession(options = {}) {
|
|
595
|
-
|
|
596
|
-
|
|
595
|
+
const { agentPreset: requestedPreset, ...rpcOptions } = options;
|
|
596
|
+
await this.ensureRunning(rpcOptions);
|
|
597
|
+
const workspaceId = await this.workspaceId(rpcOptions);
|
|
597
598
|
const payload = { workspaceId };
|
|
598
|
-
|
|
599
|
-
|
|
599
|
+
const agentPreset = requestedPreset !== undefined ? requestedPreset : this.#agentPreset;
|
|
600
|
+
if (agentPreset != null) payload.agentPreset = agentPreset;
|
|
601
|
+
const created = await this.rpc('session.create', payload, 30_000, rpcOptions);
|
|
600
602
|
return created.sessionId;
|
|
601
603
|
}
|
|
602
604
|
|