@lazyingart/agintiflow 0.18.0 → 0.19.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.md +2 -0
- package/docs/model-selection.md +70 -0
- package/package.json +4 -2
- package/public/app.js +110 -3
- package/public/index.html +65 -0
- package/public/styles.css +76 -0
- package/references/model-routing-provider-design.md +32 -5
- package/scripts/smoke-model-roles.js +88 -0
- package/scripts/smoke-web-api.js +12 -0
- package/src/auxiliary-tools.js +14 -5
- package/src/cli.js +117 -2
- package/src/config.js +30 -1
- package/src/interactive-cli.js +220 -12
- package/src/model-routing.js +171 -9
- package/src/tool-wrappers.js +4 -1
- package/src/web-db.js +28 -2
- package/web.js +68 -1
package/src/model-routing.js
CHANGED
|
@@ -69,6 +69,83 @@ const COMPLEX_ROUTE_HINTS = [
|
|
|
69
69
|
|
|
70
70
|
export const ROUTING_MODES = ["smart", "fast", "complex", "manual"];
|
|
71
71
|
|
|
72
|
+
export const MODEL_PROVIDER_GROUPS = {
|
|
73
|
+
deepseek: {
|
|
74
|
+
label: "DeepSeek",
|
|
75
|
+
provider: "deepseek",
|
|
76
|
+
role: "default route/main",
|
|
77
|
+
description: "Primary low-cost coding route. Flash is used for fast planning; Pro is used for complex execution.",
|
|
78
|
+
},
|
|
79
|
+
openai: {
|
|
80
|
+
label: "OpenAI",
|
|
81
|
+
provider: "openai",
|
|
82
|
+
role: "spare/frontier",
|
|
83
|
+
description: "Optional frontier spare or direct manual route, usually with explicit reasoning effort.",
|
|
84
|
+
},
|
|
85
|
+
qwen: {
|
|
86
|
+
label: "Qwen",
|
|
87
|
+
provider: "qwen",
|
|
88
|
+
role: "regional/general",
|
|
89
|
+
description: "DashScope/OpenAI-compatible Qwen route for Chinese and general work.",
|
|
90
|
+
},
|
|
91
|
+
"venice-uncensored": {
|
|
92
|
+
label: "Venice Uncensored",
|
|
93
|
+
provider: "venice",
|
|
94
|
+
role: "alternate text",
|
|
95
|
+
description: "Venice uncensored text models for optional manual routes.",
|
|
96
|
+
},
|
|
97
|
+
"venice-gpt": {
|
|
98
|
+
label: "Venice GPT",
|
|
99
|
+
provider: "venice",
|
|
100
|
+
role: "alternate GPT",
|
|
101
|
+
description: "GPT-family models routed through Venice.",
|
|
102
|
+
},
|
|
103
|
+
"venice-claude": {
|
|
104
|
+
label: "Venice Claude",
|
|
105
|
+
provider: "venice",
|
|
106
|
+
role: "alternate Claude",
|
|
107
|
+
description: "Claude-family models routed through Venice.",
|
|
108
|
+
},
|
|
109
|
+
"venice-gemma": {
|
|
110
|
+
label: "Venice Gemma",
|
|
111
|
+
provider: "venice",
|
|
112
|
+
role: "alternate Gemma",
|
|
113
|
+
description: "Gemma-family Venice models.",
|
|
114
|
+
},
|
|
115
|
+
"venice-qwen": {
|
|
116
|
+
label: "Venice Qwen",
|
|
117
|
+
provider: "venice",
|
|
118
|
+
role: "alternate Qwen",
|
|
119
|
+
description: "Qwen-family Venice models.",
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export const AUXILIARY_MODEL_CATALOG = {
|
|
124
|
+
grsai: [
|
|
125
|
+
{
|
|
126
|
+
id: "nano-banana-2",
|
|
127
|
+
label: "Nano Banana 2",
|
|
128
|
+
type: "image",
|
|
129
|
+
description: "Default auxiliary image-generation route through GRS AI-compatible APIs.",
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: "gpt-image-2",
|
|
133
|
+
label: "GPT Image 2",
|
|
134
|
+
type: "image",
|
|
135
|
+
description: "High-quality image generation when available through the configured auxiliary endpoint.",
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
"venice-image": [
|
|
139
|
+
{ id: "nano-banana-2", label: "Nano Banana 2", type: "image", price: "$0.10/image" },
|
|
140
|
+
{ id: "gpt-image-2", label: "GPT Image 2", type: "image", price: "$0.27/image" },
|
|
141
|
+
{ id: "gpt-image-2-edit", label: "GPT Image 2 Edit", type: "inpaint", price: "$0.36/edit" },
|
|
142
|
+
{ id: "wan-2-7-pro-edit", label: "Wan 2.7 Pro Edit", type: "inpaint", price: "$0.09/edit" },
|
|
143
|
+
{ id: "grok-imagine-image", label: "Grok Imagine", type: "image", price: "$0.03/image" },
|
|
144
|
+
{ id: "qwen-image-2-pro", label: "Qwen Image 2 Pro", type: "image", price: "$0.10/image" },
|
|
145
|
+
{ id: "bria-bg-remover", label: "Background Remover", type: "image", price: "$0.03/image" },
|
|
146
|
+
],
|
|
147
|
+
};
|
|
148
|
+
|
|
72
149
|
export const PROVIDER_MODEL_CATALOG = {
|
|
73
150
|
deepseek: [
|
|
74
151
|
{
|
|
@@ -250,20 +327,35 @@ export function getProviderDefaults(provider = "deepseek") {
|
|
|
250
327
|
};
|
|
251
328
|
}
|
|
252
329
|
|
|
253
|
-
|
|
330
|
+
function providerDefaultModel(provider, fallback) {
|
|
331
|
+
if (provider === "deepseek" && fallback) return fallback;
|
|
332
|
+
return getProviderDefaults(provider).model || fallback;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export function getModelPresets(overrides = {}) {
|
|
336
|
+
const routeProvider = overrides.routeProvider || process.env.AGINTI_ROUTE_PROVIDER || "deepseek";
|
|
337
|
+
const mainProvider = overrides.mainProvider || process.env.AGINTI_MAIN_PROVIDER || "deepseek";
|
|
254
338
|
return {
|
|
255
339
|
fast: {
|
|
256
340
|
id: "fast",
|
|
257
341
|
label: "Fast base",
|
|
258
|
-
provider:
|
|
259
|
-
model:
|
|
342
|
+
provider: routeProvider,
|
|
343
|
+
model:
|
|
344
|
+
overrides.routeModel ||
|
|
345
|
+
process.env.AGINTI_ROUTE_MODEL ||
|
|
346
|
+
process.env.DEEPSEEK_FAST_MODEL ||
|
|
347
|
+
providerDefaultModel(routeProvider, "deepseek-v4-flash"),
|
|
260
348
|
description: "Default fast route for normal browser, shell, and short coding tasks.",
|
|
261
349
|
},
|
|
262
350
|
complex: {
|
|
263
351
|
id: "complex",
|
|
264
352
|
label: "Complex reasoning",
|
|
265
|
-
provider:
|
|
266
|
-
model:
|
|
353
|
+
provider: mainProvider,
|
|
354
|
+
model:
|
|
355
|
+
overrides.mainModel ||
|
|
356
|
+
process.env.AGINTI_MAIN_MODEL ||
|
|
357
|
+
process.env.DEEPSEEK_PRO_MODEL ||
|
|
358
|
+
providerDefaultModel(mainProvider, "deepseek-v4-pro"),
|
|
267
359
|
description: "Higher-capacity DeepSeek route for multi-step coding and design tasks.",
|
|
268
360
|
},
|
|
269
361
|
mock: {
|
|
@@ -367,8 +459,9 @@ export function getModelPresets() {
|
|
|
367
459
|
id: "codexPrimary",
|
|
368
460
|
label: "Codex primary wrapper",
|
|
369
461
|
provider: "codex-wrapper",
|
|
370
|
-
model: process.env.CODEX_PRIMARY_MODEL || "gpt-5.5",
|
|
371
|
-
reasoning:
|
|
462
|
+
model: overrides.wrapperModel || process.env.AGINTI_WRAPPER_MODEL || process.env.CODEX_PRIMARY_MODEL || "gpt-5.5",
|
|
463
|
+
reasoning:
|
|
464
|
+
overrides.wrapperReasoning || process.env.AGINTI_WRAPPER_REASONING || process.env.CODEX_PRIMARY_REASONING || "medium",
|
|
372
465
|
description: "External Codex wrapper route for coding enhancement tasks.",
|
|
373
466
|
},
|
|
374
467
|
codexSpare: {
|
|
@@ -382,6 +475,65 @@ export function getModelPresets() {
|
|
|
382
475
|
};
|
|
383
476
|
}
|
|
384
477
|
|
|
478
|
+
export function getModelRoleDefaults(overrides = {}) {
|
|
479
|
+
const presets = getModelPresets(overrides);
|
|
480
|
+
const spareProvider = overrides.spareProvider || process.env.AGINTI_SPARE_PROVIDER || "openai";
|
|
481
|
+
const spareModel = overrides.spareModel || process.env.AGINTI_SPARE_MODEL || "gpt-5.4";
|
|
482
|
+
const auxiliaryProvider = overrides.auxiliaryProvider || process.env.AGINTI_AUX_PROVIDER || "grsai";
|
|
483
|
+
const auxiliaryModel = overrides.auxiliaryModel || process.env.AGINTI_AUX_MODEL || process.env.VENICE_IMAGE_MODEL || "nano-banana-2";
|
|
484
|
+
return {
|
|
485
|
+
route: {
|
|
486
|
+
id: "route",
|
|
487
|
+
label: "Route model",
|
|
488
|
+
command: "/route",
|
|
489
|
+
provider: presets.fast.provider,
|
|
490
|
+
model: presets.fast.model,
|
|
491
|
+
description: "Fast planner and triage model. Default: DeepSeek V4 Flash.",
|
|
492
|
+
},
|
|
493
|
+
main: {
|
|
494
|
+
id: "main",
|
|
495
|
+
label: "Main model",
|
|
496
|
+
command: "/model",
|
|
497
|
+
provider: presets.complex.provider,
|
|
498
|
+
model: presets.complex.model,
|
|
499
|
+
description: "Complex executor for coding, debugging, writing, and long tasks. Default: DeepSeek V4 Pro.",
|
|
500
|
+
},
|
|
501
|
+
spare: {
|
|
502
|
+
id: "spare",
|
|
503
|
+
label: "Spare model",
|
|
504
|
+
command: "/spare",
|
|
505
|
+
provider: spareProvider,
|
|
506
|
+
model: spareModel,
|
|
507
|
+
reasoning: overrides.spareReasoning || process.env.AGINTI_SPARE_REASONING || "medium",
|
|
508
|
+
description: "Fallback or cross-check model. Default: OpenAI GPT-5.4 medium reasoning.",
|
|
509
|
+
},
|
|
510
|
+
wrapper: {
|
|
511
|
+
id: "wrapper",
|
|
512
|
+
label: "Wrapper",
|
|
513
|
+
command: "/wrapper",
|
|
514
|
+
provider: "codex",
|
|
515
|
+
model: presets.codexPrimary.model,
|
|
516
|
+
reasoning: presets.codexPrimary.reasoning,
|
|
517
|
+
description: "External coding wrapper when enabled. Default: Codex with GPT-5.5 medium reasoning.",
|
|
518
|
+
},
|
|
519
|
+
auxiliary: {
|
|
520
|
+
id: "auxiliary",
|
|
521
|
+
label: "Auxiliary",
|
|
522
|
+
command: "/auxilliary",
|
|
523
|
+
provider: auxiliaryProvider,
|
|
524
|
+
model: auxiliaryModel,
|
|
525
|
+
description: "Image/media tools. Default: GRS AI/Nano Banana; Venice image is optional.",
|
|
526
|
+
},
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
export function modelsForProviderGroup(groupId) {
|
|
531
|
+
const group = MODEL_PROVIDER_GROUPS[groupId];
|
|
532
|
+
if (!group) return [];
|
|
533
|
+
if (group.provider !== "venice") return PROVIDER_MODEL_CATALOG[group.provider] || [];
|
|
534
|
+
return (PROVIDER_MODEL_CATALOG.venice || []).filter((item) => item.bucket === groupId);
|
|
535
|
+
}
|
|
536
|
+
|
|
385
537
|
export function scoreTaskComplexity(goal = "", taskProfile = "auto") {
|
|
386
538
|
const text = String(goal).toLowerCase();
|
|
387
539
|
let score = text.length > 600 ? 2 : text.length > 240 ? 1 : 0;
|
|
@@ -399,10 +551,20 @@ export function normalizeRoutingMode(value) {
|
|
|
399
551
|
return ROUTING_MODES.includes(value) ? value : "smart";
|
|
400
552
|
}
|
|
401
553
|
|
|
402
|
-
export function selectModelRoute({
|
|
554
|
+
export function selectModelRoute({
|
|
555
|
+
routingMode = "smart",
|
|
556
|
+
provider = "deepseek",
|
|
557
|
+
model = "",
|
|
558
|
+
goal = "",
|
|
559
|
+
taskProfile = "auto",
|
|
560
|
+
routeProvider = "",
|
|
561
|
+
routeModel = "",
|
|
562
|
+
mainProvider = "",
|
|
563
|
+
mainModel = "",
|
|
564
|
+
} = {}) {
|
|
403
565
|
const mode = normalizeRoutingMode(routingMode);
|
|
404
566
|
const requestedProvider = String(provider || "deepseek").toLowerCase();
|
|
405
|
-
const presets = getModelPresets();
|
|
567
|
+
const presets = getModelPresets({ routeProvider, routeModel, mainProvider, mainModel });
|
|
406
568
|
|
|
407
569
|
if (requestedProvider === "mock") {
|
|
408
570
|
const defaults = getProviderDefaults("mock");
|
package/src/tool-wrappers.js
CHANGED
|
@@ -52,7 +52,10 @@ function codexArgs(prompt, config, preset) {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
function wrapperCommand(wrapper, prompt, config, { fallback = false } = {}) {
|
|
55
|
-
const presets = getModelPresets(
|
|
55
|
+
const presets = getModelPresets({
|
|
56
|
+
wrapperModel: config.wrapperModel,
|
|
57
|
+
wrapperReasoning: config.wrapperReasoning,
|
|
58
|
+
});
|
|
56
59
|
switch (wrapper) {
|
|
57
60
|
case "codex":
|
|
58
61
|
return {
|
package/src/web-db.js
CHANGED
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { DatabaseSync } from "node:sqlite";
|
|
4
|
-
import { getModelPresets } from "./model-routing.js";
|
|
4
|
+
import { getModelPresets, getModelRoleDefaults } from "./model-routing.js";
|
|
5
5
|
|
|
6
|
-
const PREFERENCES_SCHEMA_VERSION =
|
|
6
|
+
const PREFERENCES_SCHEMA_VERSION = 7;
|
|
7
7
|
|
|
8
8
|
function defaultPreferences(baseDir) {
|
|
9
9
|
const presets = getModelPresets();
|
|
10
|
+
const roles = getModelRoleDefaults();
|
|
10
11
|
return {
|
|
11
12
|
preferencesSchemaVersion: PREFERENCES_SCHEMA_VERSION,
|
|
12
13
|
routingMode: "smart",
|
|
13
14
|
provider: "deepseek",
|
|
14
15
|
model: presets.fast.model,
|
|
16
|
+
routeProvider: roles.route.provider,
|
|
17
|
+
routeModel: roles.route.model,
|
|
18
|
+
mainProvider: roles.main.provider,
|
|
19
|
+
mainModel: roles.main.model,
|
|
20
|
+
spareProvider: roles.spare.provider,
|
|
21
|
+
spareModel: roles.spare.model,
|
|
22
|
+
spareReasoning: roles.spare.reasoning,
|
|
23
|
+
wrapperModel: roles.wrapper.model,
|
|
24
|
+
wrapperReasoning: roles.wrapper.reasoning,
|
|
25
|
+
auxiliaryProvider: roles.auxiliary.provider,
|
|
26
|
+
auxiliaryModel: roles.auxiliary.model,
|
|
15
27
|
headless: true,
|
|
16
28
|
maxSteps: 24,
|
|
17
29
|
startUrl: "",
|
|
@@ -107,6 +119,20 @@ export class WebDatabase {
|
|
|
107
119
|
preferences.allowParallelScouts = true;
|
|
108
120
|
preferences.parallelScoutCount = 3;
|
|
109
121
|
}
|
|
122
|
+
if ((parsed.preferencesSchemaVersion || 1) < 7) {
|
|
123
|
+
const roles = getModelRoleDefaults();
|
|
124
|
+
preferences.routeProvider = preferences.routeProvider || roles.route.provider;
|
|
125
|
+
preferences.routeModel = preferences.routeModel || roles.route.model;
|
|
126
|
+
preferences.mainProvider = preferences.mainProvider || roles.main.provider;
|
|
127
|
+
preferences.mainModel = preferences.mainModel || roles.main.model;
|
|
128
|
+
preferences.spareProvider = preferences.spareProvider || roles.spare.provider;
|
|
129
|
+
preferences.spareModel = preferences.spareModel || roles.spare.model;
|
|
130
|
+
preferences.spareReasoning = preferences.spareReasoning || roles.spare.reasoning;
|
|
131
|
+
preferences.wrapperModel = preferences.wrapperModel || roles.wrapper.model;
|
|
132
|
+
preferences.wrapperReasoning = preferences.wrapperReasoning || roles.wrapper.reasoning;
|
|
133
|
+
preferences.auxiliaryProvider = preferences.auxiliaryProvider || roles.auxiliary.provider;
|
|
134
|
+
preferences.auxiliaryModel = preferences.auxiliaryModel || roles.auxiliary.model;
|
|
135
|
+
}
|
|
110
136
|
this.savePreferences(preferences);
|
|
111
137
|
}
|
|
112
138
|
return preferences;
|
package/web.js
CHANGED
|
@@ -6,7 +6,15 @@ import { runAgent } from "./src/agent-runner.js";
|
|
|
6
6
|
import { resolveRuntimeConfig } from "./src/config.js";
|
|
7
7
|
import { WebDatabase } from "./src/web-db.js";
|
|
8
8
|
import { SessionStore } from "./src/session-store.js";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
AUXILIARY_MODEL_CATALOG,
|
|
11
|
+
MODEL_PROVIDER_GROUPS,
|
|
12
|
+
PROVIDER_MODEL_CATALOG,
|
|
13
|
+
getModelPresets,
|
|
14
|
+
getModelRoleDefaults,
|
|
15
|
+
getProviderDefaults,
|
|
16
|
+
normalizeRoutingMode,
|
|
17
|
+
} from "./src/model-routing.js";
|
|
10
18
|
import { listAgentWrappers, normalizeWrapperName } from "./src/tool-wrappers.js";
|
|
11
19
|
import { getDockerSandboxStatus, getSandboxLogs, runDockerPreflight } from "./src/docker-sandbox.js";
|
|
12
20
|
import { normalizePackageInstallPolicy, normalizeSandboxMode } from "./src/command-policy.js";
|
|
@@ -113,6 +121,7 @@ function serializeRun(run) {
|
|
|
113
121
|
|
|
114
122
|
function normalizePreferencePayload(body = {}, current = db.getPreferences()) {
|
|
115
123
|
const modelPresets = getModelPresets();
|
|
124
|
+
const modelRoles = getModelRoleDefaults();
|
|
116
125
|
const providerCandidate = body.provider || current.provider || "deepseek";
|
|
117
126
|
const provider = ["openai", "deepseek", "qwen", "venice", "mock"].includes(providerCandidate) ? providerCandidate : "deepseek";
|
|
118
127
|
const routingMode =
|
|
@@ -132,6 +141,50 @@ function normalizePreferencePayload(body = {}, current = db.getPreferences()) {
|
|
|
132
141
|
: current.provider !== provider
|
|
133
142
|
? providerDefaults.model
|
|
134
143
|
: current.model || modelPresets.fast.model || providerDefaults.model,
|
|
144
|
+
routeProvider:
|
|
145
|
+
typeof body.routeProvider === "string" && body.routeProvider.trim()
|
|
146
|
+
? body.routeProvider.trim()
|
|
147
|
+
: current.routeProvider || modelRoles.route.provider,
|
|
148
|
+
routeModel:
|
|
149
|
+
typeof body.routeModel === "string" && body.routeModel.trim()
|
|
150
|
+
? body.routeModel.trim()
|
|
151
|
+
: current.routeModel || modelRoles.route.model,
|
|
152
|
+
mainProvider:
|
|
153
|
+
typeof body.mainProvider === "string" && body.mainProvider.trim()
|
|
154
|
+
? body.mainProvider.trim()
|
|
155
|
+
: current.mainProvider || modelRoles.main.provider,
|
|
156
|
+
mainModel:
|
|
157
|
+
typeof body.mainModel === "string" && body.mainModel.trim()
|
|
158
|
+
? body.mainModel.trim()
|
|
159
|
+
: current.mainModel || modelRoles.main.model,
|
|
160
|
+
spareProvider:
|
|
161
|
+
typeof body.spareProvider === "string" && body.spareProvider.trim()
|
|
162
|
+
? body.spareProvider.trim()
|
|
163
|
+
: current.spareProvider || modelRoles.spare.provider,
|
|
164
|
+
spareModel:
|
|
165
|
+
typeof body.spareModel === "string" && body.spareModel.trim()
|
|
166
|
+
? body.spareModel.trim()
|
|
167
|
+
: current.spareModel || modelRoles.spare.model,
|
|
168
|
+
spareReasoning:
|
|
169
|
+
typeof body.spareReasoning === "string" && body.spareReasoning.trim()
|
|
170
|
+
? body.spareReasoning.trim()
|
|
171
|
+
: current.spareReasoning || modelRoles.spare.reasoning,
|
|
172
|
+
wrapperModel:
|
|
173
|
+
typeof body.wrapperModel === "string" && body.wrapperModel.trim()
|
|
174
|
+
? body.wrapperModel.trim()
|
|
175
|
+
: current.wrapperModel || modelRoles.wrapper.model,
|
|
176
|
+
wrapperReasoning:
|
|
177
|
+
typeof body.wrapperReasoning === "string" && body.wrapperReasoning.trim()
|
|
178
|
+
? body.wrapperReasoning.trim()
|
|
179
|
+
: current.wrapperReasoning || modelRoles.wrapper.reasoning,
|
|
180
|
+
auxiliaryProvider:
|
|
181
|
+
typeof body.auxiliaryProvider === "string" && body.auxiliaryProvider.trim()
|
|
182
|
+
? body.auxiliaryProvider.trim()
|
|
183
|
+
: current.auxiliaryProvider || modelRoles.auxiliary.provider,
|
|
184
|
+
auxiliaryModel:
|
|
185
|
+
typeof body.auxiliaryModel === "string" && body.auxiliaryModel.trim()
|
|
186
|
+
? body.auxiliaryModel.trim()
|
|
187
|
+
: current.auxiliaryModel || modelRoles.auxiliary.model,
|
|
135
188
|
headless: typeof body.headless === "boolean" ? body.headless : Boolean(current.headless),
|
|
136
189
|
maxSteps: Number.isFinite(parsedMaxSteps) && parsedMaxSteps > 0 ? parsedMaxSteps : Number(current.maxSteps) || 24,
|
|
137
190
|
startUrl: typeof body.startUrl === "string" ? body.startUrl.trim() : current.startUrl || "",
|
|
@@ -223,6 +276,17 @@ function buildRunConfig(body, overrides = {}) {
|
|
|
223
276
|
provider: merged.provider,
|
|
224
277
|
model: merged.model || getProviderDefaults(merged.provider).model,
|
|
225
278
|
routingMode: merged.routingMode,
|
|
279
|
+
routeProvider: merged.routeProvider,
|
|
280
|
+
routeModel: merged.routeModel,
|
|
281
|
+
mainProvider: merged.mainProvider,
|
|
282
|
+
mainModel: merged.mainModel,
|
|
283
|
+
spareProvider: merged.spareProvider,
|
|
284
|
+
spareModel: merged.spareModel,
|
|
285
|
+
spareReasoning: merged.spareReasoning,
|
|
286
|
+
wrapperModel: merged.wrapperModel,
|
|
287
|
+
wrapperReasoning: merged.wrapperReasoning,
|
|
288
|
+
auxiliaryProvider: merged.auxiliaryProvider,
|
|
289
|
+
auxiliaryModel: merged.auxiliaryModel,
|
|
226
290
|
headless: merged.headless,
|
|
227
291
|
maxSteps: merged.maxSteps,
|
|
228
292
|
allowedDomains: String(merged.allowedDomains || "")
|
|
@@ -586,6 +650,9 @@ app.get("/api/config", async (_req, res) => {
|
|
|
586
650
|
maxSteps: 24,
|
|
587
651
|
},
|
|
588
652
|
modelCatalog: PROVIDER_MODEL_CATALOG,
|
|
653
|
+
modelGroups: MODEL_PROVIDER_GROUPS,
|
|
654
|
+
auxiliaryModelCatalog: AUXILIARY_MODEL_CATALOG,
|
|
655
|
+
modelRoles: getModelRoleDefaults(preferences),
|
|
589
656
|
taskProfiles: listTaskProfiles(),
|
|
590
657
|
skills: listSkills(),
|
|
591
658
|
routing: {
|