@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/cli.js
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { runAgent } from "./agent-runner.js";
|
|
2
2
|
import { loadConfig } from "./config.js";
|
|
3
3
|
import { listAgentWrappers } from "./tool-wrappers.js";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
AUXILIARY_MODEL_CATALOG,
|
|
6
|
+
MODEL_PROVIDER_GROUPS,
|
|
7
|
+
PROVIDER_MODEL_CATALOG,
|
|
8
|
+
getModelPresets,
|
|
9
|
+
getModelRoleDefaults,
|
|
10
|
+
modelsForProviderGroup,
|
|
11
|
+
} from "./model-routing.js";
|
|
5
12
|
import { getDockerSandboxStatus, runDockerPreflight } from "./docker-sandbox.js";
|
|
6
13
|
import { buildCapabilityReport, printCapabilityReport } from "./capabilities.js";
|
|
7
14
|
import { startInteractiveCli } from "./interactive-cli.js";
|
|
@@ -39,6 +46,17 @@ export function parseArgs(argv) {
|
|
|
39
46
|
sessionId: "",
|
|
40
47
|
provider: "",
|
|
41
48
|
model: "",
|
|
49
|
+
routeProvider: "",
|
|
50
|
+
routeModel: "",
|
|
51
|
+
mainProvider: "",
|
|
52
|
+
mainModel: "",
|
|
53
|
+
spareProvider: "",
|
|
54
|
+
spareModel: "",
|
|
55
|
+
spareReasoning: "",
|
|
56
|
+
wrapperModel: "",
|
|
57
|
+
wrapperReasoning: "",
|
|
58
|
+
auxiliaryProvider: "",
|
|
59
|
+
auxiliaryModel: "",
|
|
42
60
|
routingMode: "",
|
|
43
61
|
commandCwd: "",
|
|
44
62
|
sandboxMode: "",
|
|
@@ -57,6 +75,7 @@ export function parseArgs(argv) {
|
|
|
57
75
|
headless: undefined,
|
|
58
76
|
maxSteps: undefined,
|
|
59
77
|
listRoutes: false,
|
|
78
|
+
listModels: false,
|
|
60
79
|
listWrappers: false,
|
|
61
80
|
sandboxStatus: false,
|
|
62
81
|
sandboxPreflight: false,
|
|
@@ -116,6 +135,61 @@ export function parseArgs(argv) {
|
|
|
116
135
|
i += 1;
|
|
117
136
|
continue;
|
|
118
137
|
}
|
|
138
|
+
if (arg === "--route-provider") {
|
|
139
|
+
result.routeProvider = readOption(argv, i);
|
|
140
|
+
i += 1;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (arg === "--route-model") {
|
|
144
|
+
result.routeModel = readOption(argv, i);
|
|
145
|
+
i += 1;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (arg === "--main-provider") {
|
|
149
|
+
result.mainProvider = readOption(argv, i);
|
|
150
|
+
i += 1;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (arg === "--main-model") {
|
|
154
|
+
result.mainModel = readOption(argv, i);
|
|
155
|
+
i += 1;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (arg === "--spare-provider") {
|
|
159
|
+
result.spareProvider = readOption(argv, i);
|
|
160
|
+
i += 1;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (arg === "--spare-model") {
|
|
164
|
+
result.spareModel = readOption(argv, i);
|
|
165
|
+
i += 1;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (arg === "--spare-reasoning") {
|
|
169
|
+
result.spareReasoning = readOption(argv, i);
|
|
170
|
+
i += 1;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (arg === "--wrapper-model") {
|
|
174
|
+
result.wrapperModel = readOption(argv, i);
|
|
175
|
+
i += 1;
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (arg === "--wrapper-reasoning") {
|
|
179
|
+
result.wrapperReasoning = readOption(argv, i);
|
|
180
|
+
i += 1;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (arg === "--aux-provider" || arg === "--auxiliary-provider") {
|
|
184
|
+
result.auxiliaryProvider = readOption(argv, i);
|
|
185
|
+
i += 1;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (arg === "--aux-model" || arg === "--auxiliary-model") {
|
|
189
|
+
result.auxiliaryModel = readOption(argv, i);
|
|
190
|
+
i += 1;
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
119
193
|
if (arg === "--routing") {
|
|
120
194
|
result.routingMode = readOption(argv, i);
|
|
121
195
|
i += 1;
|
|
@@ -236,6 +310,10 @@ export function parseArgs(argv) {
|
|
|
236
310
|
result.listRoutes = true;
|
|
237
311
|
continue;
|
|
238
312
|
}
|
|
313
|
+
if (arg === "--list-models" || arg === "--models") {
|
|
314
|
+
result.listModels = true;
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
239
317
|
if (arg === "--list-wrappers") {
|
|
240
318
|
result.listWrappers = true;
|
|
241
319
|
continue;
|
|
@@ -267,7 +345,7 @@ export function parseArgs(argv) {
|
|
|
267
345
|
|
|
268
346
|
function printUsage() {
|
|
269
347
|
console.log(
|
|
270
|
-
'Usage: aginti [chat] OR aginti web [--port 3210] OR aginti
|
|
348
|
+
'Usage: aginti [chat] OR aginti web [--port 3210] OR aginti models OR aginti skills [query] OR aginti auth [deepseek|openai|qwen|venice|grsai] OR aginti resume [latest|<session-id>] ["prompt"] OR aginti queue <session-id> "message" OR aginti [--image] [--latex] [--routing smart|fast|complex|manual] [--provider deepseek|openai|qwen|venice|mock] [--model MODEL] [--route-model MODEL] [--main-model MODEL] [--spare-model MODEL --spare-reasoning medium] [--aux-provider grsai|venice --aux-model MODEL] [--sandbox-mode host|docker-readonly|docker-workspace] [--package-install-policy block|prompt|allow] [--approve-package-installs] [--allow-shell|--no-shell] [--allow-file-tools|--no-file-tools] [--web-search|--no-web-search] [--parallel-scouts|--no-parallel-scouts --scout-count 1..10] [--allow-auxiliary-tools|--no-auxiliary-tools] [--allow-wrappers --wrapper codex --wrapper-model gpt-5.5] [--list-models|--list-routes] "your task"'
|
|
271
349
|
);
|
|
272
350
|
}
|
|
273
351
|
|
|
@@ -316,6 +394,33 @@ function printRoutes() {
|
|
|
316
394
|
}
|
|
317
395
|
}
|
|
318
396
|
|
|
397
|
+
function printModels() {
|
|
398
|
+
const roles = getModelRoleDefaults();
|
|
399
|
+
console.log("Model roles:");
|
|
400
|
+
for (const role of Object.values(roles)) {
|
|
401
|
+
const reasoning = role.reasoning ? ` reasoning=${role.reasoning}` : "";
|
|
402
|
+
console.log(` ${role.command}: ${role.provider}/${role.model}${reasoning} - ${role.description}`);
|
|
403
|
+
}
|
|
404
|
+
console.log("");
|
|
405
|
+
console.log("Provider groups:");
|
|
406
|
+
for (const [id, group] of Object.entries(MODEL_PROVIDER_GROUPS)) {
|
|
407
|
+
const models = modelsForProviderGroup(id)
|
|
408
|
+
.map((item) => item.id)
|
|
409
|
+
.join(", ");
|
|
410
|
+
console.log(` ${id}: provider=${group.provider} role=${group.role} models=${models || "(none)"}`);
|
|
411
|
+
}
|
|
412
|
+
console.log("");
|
|
413
|
+
console.log("Auxiliary image groups:");
|
|
414
|
+
for (const [id, models] of Object.entries(AUXILIARY_MODEL_CATALOG)) {
|
|
415
|
+
console.log(` ${id}: ${models.map((item) => item.id).join(", ")}`);
|
|
416
|
+
}
|
|
417
|
+
console.log("");
|
|
418
|
+
console.log("Direct provider models:");
|
|
419
|
+
for (const [provider, models] of Object.entries(PROVIDER_MODEL_CATALOG)) {
|
|
420
|
+
console.log(` ${provider}: ${models.map((item) => item.id).join(", ")}`);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
319
424
|
function printWrappers() {
|
|
320
425
|
for (const wrapper of listAgentWrappers()) {
|
|
321
426
|
console.log(`${wrapper.name}: ${wrapper.available ? "available" : "missing"} - ${wrapper.role}`);
|
|
@@ -580,6 +685,11 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
580
685
|
return;
|
|
581
686
|
}
|
|
582
687
|
|
|
688
|
+
if (argv[0] === "models" || argv[0] === "model") {
|
|
689
|
+
printModels();
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
|
|
583
693
|
if (argv[0] === "skills" || argv[0] === "skill") {
|
|
584
694
|
printSkills(argv.slice(1).join(" ").trim());
|
|
585
695
|
return;
|
|
@@ -633,6 +743,11 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
633
743
|
return;
|
|
634
744
|
}
|
|
635
745
|
|
|
746
|
+
if (args.listModels) {
|
|
747
|
+
printModels();
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
|
|
636
751
|
if (args.listWrappers) {
|
|
637
752
|
printWrappers();
|
|
638
753
|
return;
|
package/src/config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import crypto from "node:crypto";
|
|
3
|
-
import { getProviderDefaults, normalizeRoutingMode, selectModelRoute } from "./model-routing.js";
|
|
3
|
+
import { getModelRoleDefaults, getProviderDefaults, normalizeRoutingMode, selectModelRoute } from "./model-routing.js";
|
|
4
4
|
import { normalizePackageInstallPolicy, normalizeSandboxMode } from "./command-policy.js";
|
|
5
5
|
import { normalizeWrapperName } from "./tool-wrappers.js";
|
|
6
6
|
import { loadProjectEnv, resolveProjectRoot } from "./project.js";
|
|
@@ -53,6 +53,23 @@ export function resolveRuntimeConfig(args, overrides = {}) {
|
|
|
53
53
|
model: overrides.model || args.model || process.env.LLM_MODEL || "",
|
|
54
54
|
goal: args.goal || "",
|
|
55
55
|
taskProfile,
|
|
56
|
+
routeProvider: overrides.routeProvider || args.routeProvider || process.env.AGINTI_ROUTE_PROVIDER || "",
|
|
57
|
+
routeModel: overrides.routeModel || args.routeModel || process.env.AGINTI_ROUTE_MODEL || "",
|
|
58
|
+
mainProvider: overrides.mainProvider || args.mainProvider || process.env.AGINTI_MAIN_PROVIDER || "",
|
|
59
|
+
mainModel: overrides.mainModel || args.mainModel || process.env.AGINTI_MAIN_MODEL || "",
|
|
60
|
+
});
|
|
61
|
+
const modelRoles = getModelRoleDefaults({
|
|
62
|
+
routeProvider: overrides.routeProvider || args.routeProvider || process.env.AGINTI_ROUTE_PROVIDER || "",
|
|
63
|
+
routeModel: overrides.routeModel || args.routeModel || process.env.AGINTI_ROUTE_MODEL || "",
|
|
64
|
+
mainProvider: overrides.mainProvider || args.mainProvider || process.env.AGINTI_MAIN_PROVIDER || "",
|
|
65
|
+
mainModel: overrides.mainModel || args.mainModel || process.env.AGINTI_MAIN_MODEL || "",
|
|
66
|
+
spareProvider: overrides.spareProvider || args.spareProvider || process.env.AGINTI_SPARE_PROVIDER || "",
|
|
67
|
+
spareModel: overrides.spareModel || args.spareModel || process.env.AGINTI_SPARE_MODEL || "",
|
|
68
|
+
spareReasoning: overrides.spareReasoning || args.spareReasoning || process.env.AGINTI_SPARE_REASONING || "",
|
|
69
|
+
wrapperModel: overrides.wrapperModel || args.wrapperModel || process.env.AGINTI_WRAPPER_MODEL || "",
|
|
70
|
+
wrapperReasoning: overrides.wrapperReasoning || args.wrapperReasoning || process.env.AGINTI_WRAPPER_REASONING || "",
|
|
71
|
+
auxiliaryProvider: overrides.auxiliaryProvider || args.auxiliaryProvider || process.env.AGINTI_AUX_PROVIDER || "",
|
|
72
|
+
auxiliaryModel: overrides.auxiliaryModel || args.auxiliaryModel || process.env.AGINTI_AUX_MODEL || "",
|
|
56
73
|
});
|
|
57
74
|
|
|
58
75
|
const defaults = getProviderDefaults(route.provider);
|
|
@@ -79,6 +96,18 @@ export function resolveRuntimeConfig(args, overrides = {}) {
|
|
|
79
96
|
taskProfile,
|
|
80
97
|
routeReason: route.reason,
|
|
81
98
|
routeComplexityScore: route.complexityScore,
|
|
99
|
+
modelRoles,
|
|
100
|
+
routeProvider: modelRoles.route.provider,
|
|
101
|
+
routeModel: modelRoles.route.model,
|
|
102
|
+
mainProvider: modelRoles.main.provider,
|
|
103
|
+
mainModel: modelRoles.main.model,
|
|
104
|
+
spareProvider: modelRoles.spare.provider,
|
|
105
|
+
spareModel: modelRoles.spare.model,
|
|
106
|
+
spareReasoning: modelRoles.spare.reasoning,
|
|
107
|
+
wrapperModel: modelRoles.wrapper.model,
|
|
108
|
+
wrapperReasoning: modelRoles.wrapper.reasoning,
|
|
109
|
+
auxiliaryProvider: modelRoles.auxiliary.provider,
|
|
110
|
+
auxiliaryModel: modelRoles.auxiliary.model,
|
|
82
111
|
requestedProvider,
|
|
83
112
|
requestedModel: overrides.model || args.model || process.env.LLM_MODEL || "",
|
|
84
113
|
provider: route.provider,
|
package/src/interactive-cli.js
CHANGED
|
@@ -10,6 +10,13 @@ import { recommendedMaxStepsForTask } from "./engineering-guidance.js";
|
|
|
10
10
|
import { normalizeAuthProvider, runAuthWizard, shouldPromptForDeepSeek } from "./auth-onboarding.js";
|
|
11
11
|
import { SessionStore } from "./session-store.js";
|
|
12
12
|
import { listSkills, selectSkillsForGoal } from "./skill-library.js";
|
|
13
|
+
import {
|
|
14
|
+
AUXILIARY_MODEL_CATALOG,
|
|
15
|
+
MODEL_PROVIDER_GROUPS,
|
|
16
|
+
PROVIDER_MODEL_CATALOG,
|
|
17
|
+
getModelRoleDefaults,
|
|
18
|
+
modelsForProviderGroup,
|
|
19
|
+
} from "./model-routing.js";
|
|
13
20
|
|
|
14
21
|
const useColor = Boolean(input.isTTY && output.isTTY && process.env.AGINTIFLOW_NO_COLOR !== "1");
|
|
15
22
|
const ansi = {
|
|
@@ -59,6 +66,11 @@ const SLASH_COMMANDS = [
|
|
|
59
66
|
"/profile",
|
|
60
67
|
"/web-search",
|
|
61
68
|
"/scouts",
|
|
69
|
+
"/models",
|
|
70
|
+
"/route",
|
|
71
|
+
"/main",
|
|
72
|
+
"/spare",
|
|
73
|
+
"/wrapper",
|
|
62
74
|
"/routing",
|
|
63
75
|
"/provider",
|
|
64
76
|
"/model",
|
|
@@ -560,8 +572,16 @@ function printHelp() {
|
|
|
560
572
|
" /auth [deepseek|openai|qwen|venice|grsai] Alias for /login.",
|
|
561
573
|
" /instructions Show AGINTI.md project instructions status.",
|
|
562
574
|
" /memory Alias for /instructions.",
|
|
563
|
-
" /
|
|
564
|
-
"
|
|
575
|
+
" /models Show route/main/spare/wrapper/auxiliary model roles.",
|
|
576
|
+
" /route <mode|provider/model>",
|
|
577
|
+
" Set routing mode or fast route model, e.g. /route deepseek/deepseek-v4-flash.",
|
|
578
|
+
" /model <provider/model> Set the active/main model, e.g. /model deepseek/deepseek-v4-pro.",
|
|
579
|
+
" /spare <provider/model> [reasoning]",
|
|
580
|
+
" Set spare model, e.g. /spare openai/gpt-5.4 medium.",
|
|
581
|
+
" /wrapper [on|off|codex model reasoning]",
|
|
582
|
+
" Configure optional external wrapper.",
|
|
583
|
+
" /auxilliary [status|grsai|venice|model grsai/nano-banana-2|on|off|image]",
|
|
584
|
+
" Manage optional auxiliary skills, including image generation.",
|
|
565
585
|
" /new Start a fresh session on the next message.",
|
|
566
586
|
" /resume <session-id> Continue a saved session.",
|
|
567
587
|
" /sessions List recent sessions in this project.",
|
|
@@ -571,7 +591,6 @@ function printHelp() {
|
|
|
571
591
|
" /scouts on|off|<1-10> Enable parallel DeepSeek scouts and set scout count.",
|
|
572
592
|
" /routing <mode> Set routing: smart, fast, complex, manual.",
|
|
573
593
|
" /provider <name> Set provider: deepseek, openai, qwen, venice, mock.",
|
|
574
|
-
" /model <name> Set an explicit model, or /model auto.",
|
|
575
594
|
" /docker on Use docker-workspace with approved package installs.",
|
|
576
595
|
" /docker off Use host shell policy.",
|
|
577
596
|
" /latex on Use the LaTeX/PDF profile in Docker with a larger step budget.",
|
|
@@ -1357,6 +1376,11 @@ function printStatus(state) {
|
|
|
1357
1376
|
printSystemLine(`status=${state.status || "idle"}${state.activeGoal ? ` workingOn=${state.activeGoal}` : ""}`);
|
|
1358
1377
|
if (state.lastEvent) printSystemLine(`last=${state.lastEvent}`);
|
|
1359
1378
|
printSystemLine(`provider=${state.provider || "auto"} routing=${state.routingMode} model=${state.model || "auto"}`);
|
|
1379
|
+
printSystemLine(
|
|
1380
|
+
`roles route=${state.routeProvider || "deepseek"}/${state.routeModel || "deepseek-v4-flash"} main=${
|
|
1381
|
+
state.mainProvider || "deepseek"
|
|
1382
|
+
}/${state.mainModel || "deepseek-v4-pro"} spare=${state.spareProvider || "openai"}/${state.spareModel || "gpt-5.4"}`
|
|
1383
|
+
);
|
|
1360
1384
|
printSystemLine(`profile=${state.taskProfile} maxSteps=${state.maxSteps}`);
|
|
1361
1385
|
printSystemLine(
|
|
1362
1386
|
`shell=${state.allowShellTool} files=${state.allowFileTools} webSearch=${state.allowWebSearch} scouts=${state.allowParallelScouts}:${state.parallelScoutCount} auxiliary=${state.allowAuxiliaryTools} sandbox=${state.sandboxMode} installs=${state.packageInstallPolicy}`
|
|
@@ -1480,6 +1504,17 @@ function createState(args = {}) {
|
|
|
1480
1504
|
allowWrapperTools: args.allowWrapperTools ?? false,
|
|
1481
1505
|
allowDestructive: args.allowDestructive ?? false,
|
|
1482
1506
|
preferredWrapper: args.preferredWrapper || "codex",
|
|
1507
|
+
routeProvider: args.routeProvider || "",
|
|
1508
|
+
routeModel: args.routeModel || "",
|
|
1509
|
+
mainProvider: args.mainProvider || "",
|
|
1510
|
+
mainModel: args.mainModel || "",
|
|
1511
|
+
spareProvider: args.spareProvider || "openai",
|
|
1512
|
+
spareModel: args.spareModel || "gpt-5.4",
|
|
1513
|
+
spareReasoning: args.spareReasoning || "medium",
|
|
1514
|
+
wrapperModel: args.wrapperModel || "gpt-5.5",
|
|
1515
|
+
wrapperReasoning: args.wrapperReasoning || "medium",
|
|
1516
|
+
auxiliaryProvider: args.auxiliaryProvider || "grsai",
|
|
1517
|
+
auxiliaryModel: args.auxiliaryModel || "nano-banana-2",
|
|
1483
1518
|
taskProfile: normalizeTaskProfile(args.taskProfile || "auto"),
|
|
1484
1519
|
headless: args.headless ?? false,
|
|
1485
1520
|
maxSteps:
|
|
@@ -1490,6 +1525,81 @@ function createState(args = {}) {
|
|
|
1490
1525
|
};
|
|
1491
1526
|
}
|
|
1492
1527
|
|
|
1528
|
+
function parseProviderModel(value, fallbackProvider = "") {
|
|
1529
|
+
const text = String(value || "").trim();
|
|
1530
|
+
if (!text) return { provider: fallbackProvider, model: "" };
|
|
1531
|
+
if (text.includes("/")) {
|
|
1532
|
+
const [provider, ...modelParts] = text.split("/");
|
|
1533
|
+
return {
|
|
1534
|
+
provider: provider.trim() || fallbackProvider,
|
|
1535
|
+
model: modelParts.join("/").trim(),
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1538
|
+
const parts = text.split(/\s+/).filter(Boolean);
|
|
1539
|
+
if (parts.length >= 2 && ["deepseek", "openai", "qwen", "venice", "mock", "grsai", "venice-image"].includes(parts[0])) {
|
|
1540
|
+
return { provider: parts[0], model: parts.slice(1).join(" ") };
|
|
1541
|
+
}
|
|
1542
|
+
return { provider: fallbackProvider, model: text };
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
function printModelRoles(state) {
|
|
1546
|
+
const roles = getModelRoleDefaults({
|
|
1547
|
+
routeProvider: state.routeProvider,
|
|
1548
|
+
routeModel: state.routeModel,
|
|
1549
|
+
mainProvider: state.mainProvider,
|
|
1550
|
+
mainModel: state.mainModel,
|
|
1551
|
+
spareProvider: state.spareProvider,
|
|
1552
|
+
spareModel: state.spareModel,
|
|
1553
|
+
spareReasoning: state.spareReasoning,
|
|
1554
|
+
wrapperModel: state.wrapperModel,
|
|
1555
|
+
wrapperReasoning: state.wrapperReasoning,
|
|
1556
|
+
auxiliaryProvider: state.auxiliaryProvider,
|
|
1557
|
+
auxiliaryModel: state.auxiliaryModel,
|
|
1558
|
+
});
|
|
1559
|
+
const roleLines = Object.values(roles).map((role) => {
|
|
1560
|
+
const reasoning = role.reasoning ? ` reasoning=${role.reasoning}` : "";
|
|
1561
|
+
return `${role.command.padEnd(12)} ${role.provider}/${role.model}${reasoning}\n ${role.description}`;
|
|
1562
|
+
});
|
|
1563
|
+
const groups = Object.entries(MODEL_PROVIDER_GROUPS).map(([id, group]) => {
|
|
1564
|
+
const models = modelsForProviderGroup(id)
|
|
1565
|
+
.map((item) => item.id)
|
|
1566
|
+
.join(", ");
|
|
1567
|
+
return `${id}: ${group.role}${models ? ` (${models})` : ""}`;
|
|
1568
|
+
});
|
|
1569
|
+
const auxiliary = Object.entries(AUXILIARY_MODEL_CATALOG).map(
|
|
1570
|
+
([id, models]) => `${id}: ${models.map((item) => item.id).join(", ")}`
|
|
1571
|
+
);
|
|
1572
|
+
const directProviders = Object.entries(PROVIDER_MODEL_CATALOG).map(([provider, models]) => {
|
|
1573
|
+
const compact = models
|
|
1574
|
+
.slice(0, 6)
|
|
1575
|
+
.map((item) => item.id)
|
|
1576
|
+
.join(", ");
|
|
1577
|
+
return `${provider}: ${compact}${models.length > 6 ? ", ..." : ""}`;
|
|
1578
|
+
});
|
|
1579
|
+
printAgentMessage(
|
|
1580
|
+
[
|
|
1581
|
+
"Model roles",
|
|
1582
|
+
...roleLines,
|
|
1583
|
+
"",
|
|
1584
|
+
"Set roles",
|
|
1585
|
+
"/route deepseek/deepseek-v4-flash",
|
|
1586
|
+
"/model deepseek/deepseek-v4-pro",
|
|
1587
|
+
"/spare openai/gpt-5.4 medium",
|
|
1588
|
+
"/wrapper codex gpt-5.5 medium",
|
|
1589
|
+
"/auxilliary model grsai/nano-banana-2",
|
|
1590
|
+
"",
|
|
1591
|
+
"Provider groups",
|
|
1592
|
+
...groups,
|
|
1593
|
+
"",
|
|
1594
|
+
"Auxiliary image groups",
|
|
1595
|
+
...auxiliary,
|
|
1596
|
+
"",
|
|
1597
|
+
"Direct provider models",
|
|
1598
|
+
...directProviders,
|
|
1599
|
+
].join("\n")
|
|
1600
|
+
);
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1493
1603
|
async function maybeOnboardDeepSeekKey(state) {
|
|
1494
1604
|
if (!shouldPromptForDeepSeek(state, process.cwd())) return;
|
|
1495
1605
|
|
|
@@ -1591,7 +1701,9 @@ async function handleCommand(line, state, packageDir) {
|
|
|
1591
1701
|
[
|
|
1592
1702
|
`Auxiliary tools: ${state.allowAuxiliaryTools ? "on" : "off"}`,
|
|
1593
1703
|
`Image generation: ${keys.grsai ? "GRSAI key available" : "missing GRSAI key"}`,
|
|
1594
|
-
|
|
1704
|
+
`Venice image: ${keys.venice ? "Venice key available" : "missing Venice key"}`,
|
|
1705
|
+
`Selected auxiliary: ${state.auxiliaryProvider || "grsai"}/${state.auxiliaryModel || "nano-banana-2"}`,
|
|
1706
|
+
"Use `/auxilliary grsai` or `/auxilliary venice` to paste a key, `/auxilliary model grsai/nano-banana-2`, `/auxilliary image`, or `/auxilliary off`.",
|
|
1595
1707
|
].join("\n")
|
|
1596
1708
|
);
|
|
1597
1709
|
return true;
|
|
@@ -1612,11 +1724,18 @@ async function handleCommand(line, state, packageDir) {
|
|
|
1612
1724
|
printSystemLine("auxiliary=on profile=image");
|
|
1613
1725
|
return true;
|
|
1614
1726
|
}
|
|
1615
|
-
if (
|
|
1616
|
-
|
|
1727
|
+
if (action.startsWith("model")) {
|
|
1728
|
+
const selected = parseProviderModel(action.replace(/^model\s*/, ""), state.auxiliaryProvider || "grsai");
|
|
1729
|
+
state.auxiliaryProvider = selected.provider || "grsai";
|
|
1730
|
+
state.auxiliaryModel = selected.model || state.auxiliaryModel || "nano-banana-2";
|
|
1731
|
+
printSystemLine(`auxiliary=${state.auxiliaryProvider}/${state.auxiliaryModel}`);
|
|
1732
|
+
return true;
|
|
1733
|
+
}
|
|
1734
|
+
if (["grsai", "venice", "login", "key", "token"].includes(action)) {
|
|
1735
|
+
await promptAndSaveProviderKey(action === "venice" ? "venice" : "grsai", state);
|
|
1617
1736
|
return true;
|
|
1618
1737
|
}
|
|
1619
|
-
printAgentMessage("Usage: /auxilliary [status|grsai|on|off|image]");
|
|
1738
|
+
printAgentMessage("Usage: /auxilliary [status|grsai|venice|model grsai/nano-banana-2|on|off|image]");
|
|
1620
1739
|
return true;
|
|
1621
1740
|
}
|
|
1622
1741
|
if (command === "new") {
|
|
@@ -1702,6 +1821,89 @@ async function handleCommand(line, state, packageDir) {
|
|
|
1702
1821
|
printSystemLine(`parallelScouts=${state.allowParallelScouts ? "on" : "off"} count=${state.parallelScoutCount}`);
|
|
1703
1822
|
return true;
|
|
1704
1823
|
}
|
|
1824
|
+
if (command === "models") {
|
|
1825
|
+
printModelRoles(state);
|
|
1826
|
+
return true;
|
|
1827
|
+
}
|
|
1828
|
+
if (command === "route") {
|
|
1829
|
+
if (!value) {
|
|
1830
|
+
printAgentMessage(
|
|
1831
|
+
`Route model: ${state.routeProvider || "deepseek"}/${state.routeModel || "deepseek-v4-flash"}\nUse /route deepseek/deepseek-v4-flash or /route fast|smart|complex.`
|
|
1832
|
+
);
|
|
1833
|
+
return true;
|
|
1834
|
+
}
|
|
1835
|
+
if (["smart", "fast", "complex", "manual"].includes(value)) {
|
|
1836
|
+
state.routingMode = value;
|
|
1837
|
+
printSystemLine(`routing=${state.routingMode}`);
|
|
1838
|
+
return true;
|
|
1839
|
+
}
|
|
1840
|
+
const selected = parseProviderModel(value, state.routeProvider || "deepseek");
|
|
1841
|
+
state.routeProvider = selected.provider || "deepseek";
|
|
1842
|
+
state.routeModel = selected.model || state.routeModel || "deepseek-v4-flash";
|
|
1843
|
+
printSystemLine(`route=${state.routeProvider}/${state.routeModel}`);
|
|
1844
|
+
return true;
|
|
1845
|
+
}
|
|
1846
|
+
if (command === "main" || command === "model") {
|
|
1847
|
+
if (!value || value === "auto") {
|
|
1848
|
+
if (command === "main") {
|
|
1849
|
+
state.mainProvider = "";
|
|
1850
|
+
state.mainModel = "";
|
|
1851
|
+
printSystemLine("main=auto");
|
|
1852
|
+
} else {
|
|
1853
|
+
state.model = "";
|
|
1854
|
+
printSystemLine("model=auto");
|
|
1855
|
+
}
|
|
1856
|
+
return true;
|
|
1857
|
+
}
|
|
1858
|
+
const selected = parseProviderModel(value, state.mainProvider || state.provider || "deepseek");
|
|
1859
|
+
if (command === "main" || selected.provider) {
|
|
1860
|
+
state.mainProvider = selected.provider || "deepseek";
|
|
1861
|
+
state.mainModel = selected.model || "deepseek-v4-pro";
|
|
1862
|
+
if (command === "model") {
|
|
1863
|
+
state.provider = state.mainProvider;
|
|
1864
|
+
state.model = state.mainModel;
|
|
1865
|
+
}
|
|
1866
|
+
printSystemLine(`main=${state.mainProvider}/${state.mainModel}`);
|
|
1867
|
+
return true;
|
|
1868
|
+
}
|
|
1869
|
+
state.model = value;
|
|
1870
|
+
printSystemLine(`model=${state.model || "auto"}`);
|
|
1871
|
+
return true;
|
|
1872
|
+
}
|
|
1873
|
+
if (command === "spare") {
|
|
1874
|
+
if (!value) {
|
|
1875
|
+
printAgentMessage(`Spare model: ${state.spareProvider}/${state.spareModel} reasoning=${state.spareReasoning}`);
|
|
1876
|
+
return true;
|
|
1877
|
+
}
|
|
1878
|
+
const parts = value.split(/\s+/).filter(Boolean);
|
|
1879
|
+
const selected = parseProviderModel(parts[0] || "", state.spareProvider || "openai");
|
|
1880
|
+
state.spareProvider = selected.provider || "openai";
|
|
1881
|
+
state.spareModel = selected.model || state.spareModel || "gpt-5.4";
|
|
1882
|
+
if (parts[1]) state.spareReasoning = parts[1];
|
|
1883
|
+
printSystemLine(`spare=${state.spareProvider}/${state.spareModel} reasoning=${state.spareReasoning}`);
|
|
1884
|
+
return true;
|
|
1885
|
+
}
|
|
1886
|
+
if (command === "wrapper") {
|
|
1887
|
+
if (!value) {
|
|
1888
|
+
printAgentMessage(
|
|
1889
|
+
`Wrapper: ${state.preferredWrapper || "codex"} model=${state.wrapperModel || "gpt-5.5"} reasoning=${
|
|
1890
|
+
state.wrapperReasoning || "medium"
|
|
1891
|
+
} tools=${state.allowWrapperTools ? "on" : "off"}`
|
|
1892
|
+
);
|
|
1893
|
+
return true;
|
|
1894
|
+
}
|
|
1895
|
+
const parts = value.split(/\s+/).filter(Boolean);
|
|
1896
|
+
if (parts[0] === "on" || parts[0] === "off") {
|
|
1897
|
+
state.allowWrapperTools = parts[0] === "on";
|
|
1898
|
+
printSystemLine(`wrappers=${state.allowWrapperTools ? "on" : "off"}`);
|
|
1899
|
+
return true;
|
|
1900
|
+
}
|
|
1901
|
+
state.preferredWrapper = parts[0] || state.preferredWrapper || "codex";
|
|
1902
|
+
if (parts[1]) state.wrapperModel = parts[1];
|
|
1903
|
+
if (parts[2]) state.wrapperReasoning = parts[2];
|
|
1904
|
+
printSystemLine(`wrapper=${state.preferredWrapper} model=${state.wrapperModel} reasoning=${state.wrapperReasoning}`);
|
|
1905
|
+
return true;
|
|
1906
|
+
}
|
|
1705
1907
|
if (command === "routing") {
|
|
1706
1908
|
state.routingMode = value || "smart";
|
|
1707
1909
|
printSystemLine(`routing=${state.routingMode}`);
|
|
@@ -1712,11 +1914,6 @@ async function handleCommand(line, state, packageDir) {
|
|
|
1712
1914
|
printSystemLine(`provider=${state.provider || "auto"}`);
|
|
1713
1915
|
return true;
|
|
1714
1916
|
}
|
|
1715
|
-
if (command === "model") {
|
|
1716
|
-
state.model = value === "auto" ? "" : value;
|
|
1717
|
-
printSystemLine(`model=${state.model || "auto"}`);
|
|
1718
|
-
return true;
|
|
1719
|
-
}
|
|
1720
1917
|
if (command === "installs") {
|
|
1721
1918
|
state.packageInstallPolicy = normalizePackageInstallPolicy(value || "prompt");
|
|
1722
1919
|
printSystemLine(`installs=${state.packageInstallPolicy}`);
|
|
@@ -1803,6 +2000,17 @@ async function runPrompt(prompt, state, packageDir) {
|
|
|
1803
2000
|
allowWrapperTools: state.allowWrapperTools,
|
|
1804
2001
|
allowDestructive: state.allowDestructive,
|
|
1805
2002
|
preferredWrapper: state.preferredWrapper,
|
|
2003
|
+
routeProvider: state.routeProvider,
|
|
2004
|
+
routeModel: state.routeModel,
|
|
2005
|
+
mainProvider: state.mainProvider,
|
|
2006
|
+
mainModel: state.mainModel,
|
|
2007
|
+
spareProvider: state.spareProvider,
|
|
2008
|
+
spareModel: state.spareModel,
|
|
2009
|
+
spareReasoning: state.spareReasoning,
|
|
2010
|
+
wrapperModel: state.wrapperModel,
|
|
2011
|
+
wrapperReasoning: state.wrapperReasoning,
|
|
2012
|
+
auxiliaryProvider: state.auxiliaryProvider,
|
|
2013
|
+
auxiliaryModel: state.auxiliaryModel,
|
|
1806
2014
|
taskProfile: state.taskProfile,
|
|
1807
2015
|
maxSteps: runMaxSteps,
|
|
1808
2016
|
headless: state.headless,
|