@agent-relay/dashboard 2.0.93 → 2.0.94
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/out/404.html +1 -1
- package/out/_next/static/chunks/{3663-47290254b8f6f5dd.js → 3663-191a9aa9104061af.js} +1 -1
- package/out/_next/static/chunks/4201-d11188cf35739bff.js +1 -0
- package/out/_next/static/chunks/5787-f6fd7a3fbfe5eae6.js +73 -0
- package/out/_next/static/chunks/app/app/[[...slug]]/{page-c1376e695ba19e38.js → page-2b872f60e3d64014.js} +1 -1
- package/out/_next/static/chunks/app/{page-f2ebc7d0bc08e395.js → page-ca5511e5d65100a5.js} +1 -1
- package/out/about.html +1 -1
- package/out/about.txt +1 -1
- package/out/app/onboarding.html +1 -1
- package/out/app/onboarding.txt +1 -1
- package/out/app.html +1 -1
- package/out/app.txt +2 -2
- package/out/blog/go-to-bed-wake-up-to-a-finished-product.html +1 -1
- package/out/blog/go-to-bed-wake-up-to-a-finished-product.txt +1 -1
- package/out/blog/let-them-cook-multi-agent-orchestration.html +1 -1
- package/out/blog/let-them-cook-multi-agent-orchestration.txt +1 -1
- package/out/blog.html +1 -1
- package/out/blog.txt +1 -1
- package/out/careers.html +1 -1
- package/out/careers.txt +1 -1
- package/out/changelog.html +1 -1
- package/out/changelog.txt +1 -1
- package/out/cloud/link.html +1 -1
- package/out/cloud/link.txt +1 -1
- package/out/complete-profile.html +1 -1
- package/out/complete-profile.txt +1 -1
- package/out/connect-repos.html +1 -1
- package/out/connect-repos.txt +1 -1
- package/out/contact.html +1 -1
- package/out/contact.txt +1 -1
- package/out/dev/cli-tools.html +1 -1
- package/out/dev/cli-tools.txt +1 -1
- package/out/dev/log-viewer.html +1 -1
- package/out/dev/log-viewer.txt +1 -1
- package/out/docs.html +1 -1
- package/out/docs.txt +1 -1
- package/out/history.html +1 -1
- package/out/history.txt +2 -2
- package/out/index.html +1 -1
- package/out/index.txt +2 -2
- package/out/login.html +1 -1
- package/out/login.txt +1 -1
- package/out/metrics.html +1 -1
- package/out/metrics.txt +2 -2
- package/out/pricing.html +1 -1
- package/out/pricing.txt +1 -1
- package/out/privacy.html +1 -1
- package/out/privacy.txt +1 -1
- package/out/providers/setup/claude.html +1 -1
- package/out/providers/setup/claude.txt +1 -1
- package/out/providers/setup/codex.html +1 -1
- package/out/providers/setup/codex.txt +1 -1
- package/out/providers/setup/cursor.html +1 -1
- package/out/providers/setup/cursor.txt +1 -1
- package/out/providers.html +1 -1
- package/out/providers.txt +1 -1
- package/out/security.html +1 -1
- package/out/security.txt +1 -1
- package/out/signup.html +1 -1
- package/out/signup.txt +1 -1
- package/out/terms.html +1 -1
- package/out/terms.txt +1 -1
- package/package.json +1 -1
- package/src/adapters/cloudFetchAdapter.test.ts +49 -0
- package/src/adapters/types.ts +1 -0
- package/src/components/SpawnModal.test.tsx +127 -0
- package/src/components/SpawnModal.tsx +20 -8
- package/src/components/settings/SettingsPage.tsx +6 -1
- package/src/lib/model-options.test.ts +21 -0
- package/src/lib/model-options.ts +119 -0
- package/src/providers/AgentProvider.tsx +3 -4
- package/out/_next/static/chunks/270-8c0b8109123a0c5f.js +0 -73
- package/out/_next/static/chunks/5518-3b96a248632a79c0.js +0 -1
- /package/out/_next/static/{9CykW6n4dJn75_XoFVN_X → wgSCX8AQnjVl_Rnx1gUp5}/_buildManifest.js +0 -0
- /package/out/_next/static/{9CykW6n4dJn75_XoFVN_X → wgSCX8AQnjVl_Rnx1gUp5}/_ssgManifest.js +0 -0
|
@@ -220,4 +220,131 @@ describe('SpawnModal', () => {
|
|
|
220
220
|
expect(config.cwd).toBe('/custom/path');
|
|
221
221
|
});
|
|
222
222
|
});
|
|
223
|
+
|
|
224
|
+
describe('model selection', () => {
|
|
225
|
+
it('falls back to a supported Codex model and applies the default reasoning effort override', async () => {
|
|
226
|
+
const onSpawn = vi.fn().mockResolvedValue(true);
|
|
227
|
+
|
|
228
|
+
renderSpawnModal({
|
|
229
|
+
onSpawn,
|
|
230
|
+
agentDefaults: {
|
|
231
|
+
defaultCliType: 'codex',
|
|
232
|
+
defaultModels: {
|
|
233
|
+
codex: 'gpt-5.1-codex-mini',
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
modelOptions: {
|
|
237
|
+
codex: [
|
|
238
|
+
{
|
|
239
|
+
value: 'gpt-5.4',
|
|
240
|
+
label: 'GPT-5.4',
|
|
241
|
+
reasoningEfforts: ['low', 'medium', 'high', 'xhigh'],
|
|
242
|
+
defaultReasoningEffort: 'xhigh',
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
value: 'gpt-5.1-codex-max',
|
|
246
|
+
label: 'GPT-5.1 Codex Max',
|
|
247
|
+
reasoningEfforts: ['low', 'medium', 'high', 'xhigh'],
|
|
248
|
+
defaultReasoningEffort: 'xhigh',
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
},
|
|
252
|
+
registryDefaultModels: {
|
|
253
|
+
codex: 'gpt-5.4',
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
const modelSelect = await screen.findByLabelText('Model') as HTMLSelectElement;
|
|
258
|
+
expect(modelSelect.value).toBe('gpt-5.4');
|
|
259
|
+
|
|
260
|
+
fireEvent.submit(getForm());
|
|
261
|
+
|
|
262
|
+
await waitFor(() => {
|
|
263
|
+
expect(onSpawn).toHaveBeenCalled();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
const config = onSpawn.mock.calls[0][0];
|
|
267
|
+
expect(config.command).toBe('codex --model gpt-5.4 -c model_reasoning_effort="xhigh"');
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('applies the Codex mini reasoning effort override when mini is selected', async () => {
|
|
271
|
+
const onSpawn = vi.fn().mockResolvedValue(true);
|
|
272
|
+
|
|
273
|
+
renderSpawnModal({
|
|
274
|
+
onSpawn,
|
|
275
|
+
agentDefaults: {
|
|
276
|
+
defaultCliType: 'codex',
|
|
277
|
+
defaultModels: {
|
|
278
|
+
codex: 'gpt-5.1-codex-mini',
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
modelOptions: {
|
|
282
|
+
codex: [
|
|
283
|
+
{
|
|
284
|
+
value: 'gpt-5.1-codex-mini',
|
|
285
|
+
label: 'GPT-5.1 Codex Mini',
|
|
286
|
+
reasoningEfforts: ['medium', 'high'],
|
|
287
|
+
defaultReasoningEffort: 'high',
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
value: 'gpt-5.4',
|
|
291
|
+
label: 'GPT-5.4',
|
|
292
|
+
reasoningEfforts: ['low', 'medium', 'high', 'xhigh'],
|
|
293
|
+
defaultReasoningEffort: 'xhigh',
|
|
294
|
+
},
|
|
295
|
+
],
|
|
296
|
+
},
|
|
297
|
+
registryDefaultModels: {
|
|
298
|
+
codex: 'gpt-5.4',
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
const modelSelect = await screen.findByLabelText('Model') as HTMLSelectElement;
|
|
303
|
+
expect(modelSelect.value).toBe('gpt-5.1-codex-mini');
|
|
304
|
+
|
|
305
|
+
fireEvent.submit(getForm());
|
|
306
|
+
|
|
307
|
+
await waitFor(() => {
|
|
308
|
+
expect(onSpawn).toHaveBeenCalled();
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const config = onSpawn.mock.calls[0][0];
|
|
312
|
+
expect(config.command).toBe('codex --model gpt-5.1-codex-mini -c model_reasoning_effort="high"');
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it('falls back to a supported OpenCode model when a saved default is no longer offered', async () => {
|
|
316
|
+
const onSpawn = vi.fn().mockResolvedValue(true);
|
|
317
|
+
|
|
318
|
+
renderSpawnModal({
|
|
319
|
+
onSpawn,
|
|
320
|
+
agentDefaults: {
|
|
321
|
+
defaultCliType: 'opencode',
|
|
322
|
+
defaultModels: {
|
|
323
|
+
opencode: 'openai/gpt-5.1-codex',
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
modelOptions: {
|
|
327
|
+
opencode: [
|
|
328
|
+
{ value: 'openai/gpt-5.2', label: 'GPT-5.2' },
|
|
329
|
+
{ value: 'openai/gpt-5.1-codex-max', label: 'GPT-5.1 Codex Max' },
|
|
330
|
+
],
|
|
331
|
+
},
|
|
332
|
+
registryDefaultModels: {
|
|
333
|
+
opencode: 'openai/gpt-5.2',
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
const modelSelect = await screen.findByLabelText('Model') as HTMLSelectElement;
|
|
338
|
+
expect(modelSelect.value).toBe('openai/gpt-5.2');
|
|
339
|
+
|
|
340
|
+
fireEvent.submit(getForm());
|
|
341
|
+
|
|
342
|
+
await waitFor(() => {
|
|
343
|
+
expect(onSpawn).toHaveBeenCalled();
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
const config = onSpawn.mock.calls[0][0];
|
|
347
|
+
expect(config.command).toBe('opencode --model openai/gpt-5.2');
|
|
348
|
+
});
|
|
349
|
+
});
|
|
223
350
|
});
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
|
|
9
9
|
import { useDashboardConfig } from '../adapters';
|
|
10
|
+
import { buildCommandWithModel, resolveSupportedModel } from '../lib/model-options';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Model options are fetched from the server (/api/models) which sources them
|
|
@@ -67,6 +68,8 @@ export interface SpawnModalProps {
|
|
|
67
68
|
export interface ModelOption {
|
|
68
69
|
value: string;
|
|
69
70
|
label: string;
|
|
71
|
+
reasoningEfforts?: Array<'low' | 'medium' | 'high' | 'xhigh'>;
|
|
72
|
+
defaultReasoningEffort?: 'low' | 'medium' | 'high' | 'xhigh';
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
const EMPTY_MODEL_OPTIONS: ModelOption[] = [];
|
|
@@ -173,10 +176,8 @@ export function SpawnModal({
|
|
|
173
176
|
}, [modelOptions]);
|
|
174
177
|
|
|
175
178
|
const getDefaultModelForCli = useCallback((cli: string): string => {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
?? getModelsForCli(cli)[0]?.value
|
|
179
|
-
?? '';
|
|
179
|
+
const options = getModelsForCli(cli);
|
|
180
|
+
return resolveSupportedModel(options, agentDefaults?.defaultModels?.[cli], registryDefaultModels?.[cli]);
|
|
180
181
|
}, [agentDefaults, registryDefaultModels, getModelsForCli]);
|
|
181
182
|
|
|
182
183
|
const [selectedTemplate, setSelectedTemplate] = useState(AGENT_TEMPLATES[0]);
|
|
@@ -197,8 +198,14 @@ export function SpawnModal({
|
|
|
197
198
|
|
|
198
199
|
/** Get selected model for the current template */
|
|
199
200
|
const getSelectedModel = useCallback((cli: string): string => {
|
|
200
|
-
|
|
201
|
-
|
|
201
|
+
const options = getModelsForCli(cli);
|
|
202
|
+
return resolveSupportedModel(
|
|
203
|
+
options,
|
|
204
|
+
selectedModels[cli],
|
|
205
|
+
agentDefaults?.defaultModels?.[cli],
|
|
206
|
+
registryDefaultModels?.[cli],
|
|
207
|
+
);
|
|
208
|
+
}, [selectedModels, agentDefaults, registryDefaultModels, getModelsForCli]);
|
|
202
209
|
|
|
203
210
|
const setModelForCli = useCallback((cli: string, model: string) => {
|
|
204
211
|
setSelectedModels(prev => ({ ...prev, [cli]: model }));
|
|
@@ -213,11 +220,16 @@ export function SpawnModal({
|
|
|
213
220
|
if (template?.supportsModelSelection) {
|
|
214
221
|
const model = getSelectedModel(selectedTemplate.id);
|
|
215
222
|
if (model) {
|
|
216
|
-
return
|
|
223
|
+
return buildCommandWithModel(
|
|
224
|
+
selectedTemplate.command,
|
|
225
|
+
selectedTemplate.id,
|
|
226
|
+
model,
|
|
227
|
+
getModelsForCli(selectedTemplate.id),
|
|
228
|
+
);
|
|
217
229
|
}
|
|
218
230
|
}
|
|
219
231
|
return selectedTemplate.command;
|
|
220
|
-
}, [selectedTemplate, customCommand, getSelectedModel]);
|
|
232
|
+
}, [selectedTemplate, customCommand, getSelectedModel, getModelsForCli]);
|
|
221
233
|
|
|
222
234
|
const shadowMode = useMemo(() => deriveShadowMode(effectiveCommand), [effectiveCommand]);
|
|
223
235
|
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import React, { useState, useEffect, useCallback } from 'react';
|
|
14
14
|
import { useDashboardConfig, type DashboardFeatures } from '../../adapters';
|
|
15
|
+
import { resolveSupportedModel } from '../../lib/model-options';
|
|
15
16
|
import type { Settings, CliType } from './types';
|
|
16
17
|
import type { ModelOption } from '../SpawnModal';
|
|
17
18
|
|
|
@@ -410,7 +411,11 @@ export function SettingsPage({
|
|
|
410
411
|
description={`Default model when spawning ${label} agents`}
|
|
411
412
|
>
|
|
412
413
|
<select
|
|
413
|
-
value={
|
|
414
|
+
value={resolveSupportedModel(
|
|
415
|
+
models,
|
|
416
|
+
settings.agentDefaults?.defaultModels?.[id],
|
|
417
|
+
registryDefaultModels?.[id],
|
|
418
|
+
)}
|
|
414
419
|
onChange={(e) => updateSettings((prev) => ({
|
|
415
420
|
...prev,
|
|
416
421
|
agentDefaults: {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { parseSpawnCommand } from './model-options';
|
|
4
|
+
|
|
5
|
+
describe('parseSpawnCommand', () => {
|
|
6
|
+
it('extracts provider, model, and Codex reasoning effort from the modal command', () => {
|
|
7
|
+
expect(parseSpawnCommand('codex --model gpt-5.4 -c model_reasoning_effort="xhigh"')).toEqual({
|
|
8
|
+
provider: 'codex',
|
|
9
|
+
model: 'gpt-5.4',
|
|
10
|
+
reasoningEffort: 'xhigh',
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('handles inline model syntax and commands without reasoning effort overrides', () => {
|
|
15
|
+
expect(parseSpawnCommand('opencode --model=openai/gpt-5.2')).toEqual({
|
|
16
|
+
provider: 'opencode',
|
|
17
|
+
model: 'openai/gpt-5.2',
|
|
18
|
+
reasoningEffort: undefined,
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { ModelOption } from '../components/SpawnModal';
|
|
2
|
+
|
|
3
|
+
export type ReasoningEffort = NonNullable<ModelOption['defaultReasoningEffort']>;
|
|
4
|
+
|
|
5
|
+
const REASONING_EFFORTS: ReasoningEffort[] = ['low', 'medium', 'high', 'xhigh'];
|
|
6
|
+
|
|
7
|
+
function isReasoningEffort(value: string): value is ReasoningEffort {
|
|
8
|
+
return REASONING_EFFORTS.includes(value as ReasoningEffort);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function stripWrappingQuotes(value: string): string {
|
|
12
|
+
if (value.length >= 2) {
|
|
13
|
+
const first = value[0];
|
|
14
|
+
const last = value[value.length - 1];
|
|
15
|
+
if ((first === '"' && last === '"') || (first === "'" && last === "'")) {
|
|
16
|
+
return value.slice(1, -1);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function tokenizeCommand(command: string): string[] {
|
|
24
|
+
return command.match(/"[^"]*"|'[^']*'|\S+/g) ?? [];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function hasOptionValue(options: ModelOption[], value: string | undefined): value is string {
|
|
28
|
+
return typeof value === 'string' && options.some((option) => option.value === value);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getModelOption(options: ModelOption[], value: string | undefined): ModelOption | undefined {
|
|
32
|
+
return typeof value === 'string'
|
|
33
|
+
? options.find((option) => option.value === value)
|
|
34
|
+
: undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function resolveSupportedModel(options: ModelOption[], ...candidates: Array<string | undefined>): string {
|
|
38
|
+
if (options.length === 0) {
|
|
39
|
+
return candidates.find((candidate): candidate is string => typeof candidate === 'string' && candidate.length > 0) ?? '';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for (const candidate of candidates) {
|
|
43
|
+
if (hasOptionValue(options, candidate)) {
|
|
44
|
+
return candidate;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return options[0]?.value ?? '';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function getDefaultReasoningEffortForModel(
|
|
52
|
+
options: ModelOption[],
|
|
53
|
+
model: string | undefined,
|
|
54
|
+
): ReasoningEffort | undefined {
|
|
55
|
+
return getModelOption(options, model)?.defaultReasoningEffort;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function parseSpawnCommand(command: string): {
|
|
59
|
+
provider: string;
|
|
60
|
+
model?: string;
|
|
61
|
+
reasoningEffort?: ReasoningEffort;
|
|
62
|
+
} {
|
|
63
|
+
const tokens = tokenizeCommand(command.trim());
|
|
64
|
+
const provider = tokens[0] ?? '';
|
|
65
|
+
let model: string | undefined;
|
|
66
|
+
let reasoningEffort: ReasoningEffort | undefined;
|
|
67
|
+
|
|
68
|
+
for (let index = 1; index < tokens.length; index += 1) {
|
|
69
|
+
const token = tokens[index];
|
|
70
|
+
|
|
71
|
+
if (token === '--model') {
|
|
72
|
+
const next = tokens[index + 1];
|
|
73
|
+
if (typeof next === 'string' && next.length > 0) {
|
|
74
|
+
model = stripWrappingQuotes(next);
|
|
75
|
+
}
|
|
76
|
+
index += 1;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (token.startsWith('--model=')) {
|
|
81
|
+
const value = stripWrappingQuotes(token.slice('--model='.length));
|
|
82
|
+
if (value) {
|
|
83
|
+
model = value;
|
|
84
|
+
}
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const configToken = token === '-c' ? tokens[index + 1] : token;
|
|
89
|
+
if (typeof configToken === 'string' && configToken.startsWith('model_reasoning_effort=')) {
|
|
90
|
+
const value = stripWrappingQuotes(configToken.slice('model_reasoning_effort='.length));
|
|
91
|
+
if (isReasoningEffort(value)) {
|
|
92
|
+
reasoningEffort = value;
|
|
93
|
+
}
|
|
94
|
+
if (token === '-c') {
|
|
95
|
+
index += 1;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return { provider, model, reasoningEffort };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function buildCommandWithModel(
|
|
104
|
+
baseCommand: string,
|
|
105
|
+
cli: string,
|
|
106
|
+
model: string,
|
|
107
|
+
options: ModelOption[],
|
|
108
|
+
): string {
|
|
109
|
+
const parts = [baseCommand, '--model', model];
|
|
110
|
+
const reasoningEffort = cli === 'codex'
|
|
111
|
+
? getDefaultReasoningEffortForModel(options, model)
|
|
112
|
+
: undefined;
|
|
113
|
+
|
|
114
|
+
if (reasoningEffort) {
|
|
115
|
+
parts.push('-c', 'model_reasoning_effort="' + reasoningEffort + '"');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return parts.join(' ');
|
|
119
|
+
}
|
|
@@ -17,6 +17,7 @@ import { useRecentRepos } from '../components/hooks/useRecentRepos';
|
|
|
17
17
|
import { useWorkspaceRepos } from '../components/hooks/useWorkspaceRepos';
|
|
18
18
|
import { useCloudWorkspace } from './CloudWorkspaceProvider';
|
|
19
19
|
import { api, convertApiDecision, getCsrfToken } from '../lib/api';
|
|
20
|
+
import { parseSpawnCommand } from '../lib/model-options';
|
|
20
21
|
import { mergeAgentsForDashboard } from '../lib/agent-merge';
|
|
21
22
|
import type { DashboardData } from '../components/hooks/useWebSocket';
|
|
22
23
|
|
|
@@ -493,16 +494,14 @@ export function AgentProvider({ children, data, isConnected }: AgentProviderProp
|
|
|
493
494
|
setIsSpawning(true);
|
|
494
495
|
setSpawnError(null);
|
|
495
496
|
try {
|
|
496
|
-
const
|
|
497
|
-
const provider = commandParts[0];
|
|
498
|
-
const modelIdx = commandParts.indexOf('--model');
|
|
499
|
-
const model = modelIdx !== -1 && commandParts[modelIdx + 1] ? commandParts[modelIdx + 1] : undefined;
|
|
497
|
+
const { provider, model, reasoningEffort } = parseSpawnCommand(config.command);
|
|
500
498
|
|
|
501
499
|
if (hasWorkspaceApi && apiAdapter && activeCloudWorkspaceId) {
|
|
502
500
|
const result = await apiAdapter.spawnAgent(activeCloudWorkspaceId, {
|
|
503
501
|
name: config.name,
|
|
504
502
|
provider,
|
|
505
503
|
model,
|
|
504
|
+
reasoningEffort,
|
|
506
505
|
cwd: config.cwd,
|
|
507
506
|
});
|
|
508
507
|
if (!result.success) {
|