anygate 0.5.11 → 0.6.1
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/dist/{chunk-6AFYEDSU.js → chunk-4N4RDHGZ.js} +21 -6
- package/dist/{chunk-6AFYEDSU.js.map → chunk-4N4RDHGZ.js.map} +1 -1
- package/dist/{chunk-55RHVPE4.js → chunk-BY4AKT2X.js} +1540 -829
- package/dist/chunk-BY4AKT2X.js.map +1 -0
- package/dist/{chunk-5UF4TVCM.js → chunk-UE2I2ETX.js} +25 -3
- package/dist/chunk-UE2I2ETX.js.map +1 -0
- package/dist/{chunk-72WNE2IK.js → chunk-UT3JLF3M.js} +2 -13
- package/dist/cli.js +1728 -680
- package/dist/cli.js.map +1 -1
- package/dist/{command-7AI36ICY.js → command-XIDZGWNR.js} +417 -108
- package/dist/command-XIDZGWNR.js.map +1 -0
- package/dist/{constants-HE3EOSMH.js → constants-WLMOLKEO.js} +9 -3
- package/dist/{provider-templates-MNJZTG3Z.js → provider-templates-336QE7ZV.js} +3 -3
- package/dist/registry/data/templates/agentrouter.json +19 -0
- package/dist/registry/data/templates/cohere.json +5 -2
- package/dist/registry/data/templates/fireworks.json +1 -1
- package/dist/registry/data/templates/sambanova.json +8 -7
- package/dist/ui/dist/assets/index-Bnth1xGD.js +7 -0
- package/dist/ui/dist/assets/index-bNoUNC_v.css +1 -0
- package/dist/ui/dist/index.html +2 -2
- package/package.json +110 -94
- package/dist/chunk-55RHVPE4.js.map +0 -1
- package/dist/chunk-5UF4TVCM.js.map +0 -1
- package/dist/command-7AI36ICY.js.map +0 -1
- package/dist/ui/dist/assets/index-DWAOH_B3.css +0 -1
- package/dist/ui/dist/assets/index-qxVU3kMy.js +0 -6
- /package/dist/{chunk-72WNE2IK.js.map → chunk-UT3JLF3M.js.map} +0 -0
- /package/dist/{constants-HE3EOSMH.js.map → constants-WLMOLKEO.js.map} +0 -0
- /package/dist/{provider-templates-MNJZTG3Z.js.map → provider-templates-336QE7ZV.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
buildClaudeCodeBillingSystemLine,
|
|
20
20
|
buildCodexAppRootConfig,
|
|
21
21
|
buildImportProviderList,
|
|
22
|
+
buildProviderAllModelRoutes,
|
|
22
23
|
buildVertexRuntimeConfig,
|
|
23
24
|
cachedModelToLocal,
|
|
24
25
|
catalogEntryFromModel,
|
|
@@ -69,8 +70,6 @@ import {
|
|
|
69
70
|
getValidationStatus,
|
|
70
71
|
grabRoundTripSignature,
|
|
71
72
|
hasApplicationDefaultCredentials,
|
|
72
|
-
init_config,
|
|
73
|
-
init_paths,
|
|
74
73
|
injectClaudeIdentity,
|
|
75
74
|
isClaudeAppRunning,
|
|
76
75
|
isCodexAppRunning,
|
|
@@ -173,7 +172,7 @@ import {
|
|
|
173
172
|
validateModels,
|
|
174
173
|
writeSecureLogLine,
|
|
175
174
|
zenRegistryStub
|
|
176
|
-
} from "./chunk-
|
|
175
|
+
} from "./chunk-BY4AKT2X.js";
|
|
177
176
|
import {
|
|
178
177
|
BACKENDS,
|
|
179
178
|
CONFLICTING_ENV_VARS,
|
|
@@ -181,15 +180,15 @@ import {
|
|
|
181
180
|
MAX_MODEL_CATALOG,
|
|
182
181
|
VERSION,
|
|
183
182
|
VERTEX_ANTHROPIC_NPM
|
|
184
|
-
} from "./chunk-
|
|
183
|
+
} from "./chunk-UE2I2ETX.js";
|
|
185
184
|
import {
|
|
186
185
|
filterTemplates,
|
|
187
186
|
getTemplateById,
|
|
188
187
|
listAddableTemplates,
|
|
189
188
|
listSupportedTemplates,
|
|
190
189
|
listVisibleOAuthTemplates
|
|
191
|
-
} from "./chunk-
|
|
192
|
-
import "./chunk-
|
|
190
|
+
} from "./chunk-4N4RDHGZ.js";
|
|
191
|
+
import "./chunk-UT3JLF3M.js";
|
|
193
192
|
|
|
194
193
|
// src/cli.ts
|
|
195
194
|
import pc18 from "picocolors";
|
|
@@ -200,8 +199,6 @@ import { fileURLToPath } from "url";
|
|
|
200
199
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
201
200
|
import { homedir } from "os";
|
|
202
201
|
import { join } from "path";
|
|
203
|
-
init_config();
|
|
204
|
-
init_paths();
|
|
205
202
|
var SKILL_DIR_NAME = "anygate-cli";
|
|
206
203
|
var SKILL_INSTALL_DIRS = [
|
|
207
204
|
join(getAppHome(), "skills"),
|
|
@@ -242,7 +239,8 @@ function skillInstallTargets() {
|
|
|
242
239
|
}
|
|
243
240
|
function formatProviderModels(provider) {
|
|
244
241
|
const models = provider.modelsCache?.models ?? [];
|
|
245
|
-
if (models.length === 0)
|
|
242
|
+
if (models.length === 0)
|
|
243
|
+
return ` (no cached models \u2014 run: anygate providers refresh-models ${provider.id})`;
|
|
246
244
|
const lines = models.slice(0, 40).map((m) => ` ${m.id}${m.name !== m.id ? ` (${m.name})` : ""}`);
|
|
247
245
|
if (models.length > 40) lines.push(` ... and ${models.length - 40} more`);
|
|
248
246
|
return lines.join("\n");
|
|
@@ -253,13 +251,19 @@ function buildLiveStateSection() {
|
|
|
253
251
|
const enabled = registry.providers.filter((p18) => p18.enabled);
|
|
254
252
|
const prefLines = [];
|
|
255
253
|
if (prefs.lastProvider || prefs.lastModel) {
|
|
256
|
-
prefLines.push(
|
|
254
|
+
prefLines.push(
|
|
255
|
+
` Claude last launch: provider=${prefs.lastProvider ?? "(none)"} model=${prefs.lastModel ?? "(none)"}`
|
|
256
|
+
);
|
|
257
257
|
}
|
|
258
258
|
if (prefs.lastCodexProvider || prefs.lastCodexModel) {
|
|
259
|
-
prefLines.push(
|
|
259
|
+
prefLines.push(
|
|
260
|
+
` Codex last launch: provider=${prefs.lastCodexProvider ?? "(none)"} model=${prefs.lastCodexModel ?? "(none)"}`
|
|
261
|
+
);
|
|
260
262
|
}
|
|
261
263
|
if (prefs.lastGeminiProvider || prefs.lastGeminiModel) {
|
|
262
|
-
prefLines.push(
|
|
264
|
+
prefLines.push(
|
|
265
|
+
` Gemini last launch: provider=${prefs.lastGeminiProvider ?? "(none)"} model=${prefs.lastGeminiModel ?? "(none)"}`
|
|
266
|
+
);
|
|
263
267
|
}
|
|
264
268
|
if (prefs.favoriteModels?.length) {
|
|
265
269
|
prefLines.push(` Favorites (${prefs.favoriteModels.length}/${MAX_MODEL_CATALOG}):`);
|
|
@@ -267,10 +271,12 @@ function buildLiveStateSection() {
|
|
|
267
271
|
prefLines.push(` ${f.providerId} / ${f.modelId}`);
|
|
268
272
|
}
|
|
269
273
|
}
|
|
270
|
-
const providerBlocks = enabled.length === 0 ? [" No registry providers configured. Built-in cloud: zen, go (OpenCode Zen/Go)."] : enabled.map(
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
+
const providerBlocks = enabled.length === 0 ? [" No registry providers configured. Built-in cloud: zen, go (OpenCode Zen/Go)."] : enabled.map(
|
|
275
|
+
(p18) => [
|
|
276
|
+
` ${p18.name} (${p18.id}) \u2014 ${p18.modelsCache?.models.length ?? 0} cached model(s)`,
|
|
277
|
+
formatProviderModels(p18)
|
|
278
|
+
].join("\n")
|
|
279
|
+
);
|
|
274
280
|
return `
|
|
275
281
|
================================================================================
|
|
276
282
|
CURRENT LOCAL STATE (from disk \u2014 no network)
|
|
@@ -770,7 +776,9 @@ import * as p from "@clack/prompts";
|
|
|
770
776
|
import open from "open";
|
|
771
777
|
var ONBOARDING_TEMPLATES = ["kilo", "nvidia", "groq", "mistral", "cerebras"];
|
|
772
778
|
function categorizeOnboardingProviders() {
|
|
773
|
-
const templates = ONBOARDING_TEMPLATES.map((id) => getTemplateById(id)).filter(
|
|
779
|
+
const templates = ONBOARDING_TEMPLATES.map((id) => getTemplateById(id)).filter(
|
|
780
|
+
(t) => t !== void 0 && t.supported
|
|
781
|
+
);
|
|
774
782
|
const keyless = [];
|
|
775
783
|
const apiKeyRequired = [];
|
|
776
784
|
for (const t of templates) {
|
|
@@ -800,7 +808,7 @@ async function handleKeylessProvider(template) {
|
|
|
800
808
|
}
|
|
801
809
|
async function handleApiKeyProvider(template) {
|
|
802
810
|
const signupUrl = template.signupUrl ?? "https://opencode.ai/auth";
|
|
803
|
-
printApiKeyProviderPanel(template.name, signupUrl);
|
|
811
|
+
printApiKeyProviderPanel(template.name, signupUrl, template.signupNote);
|
|
804
812
|
let choice = await p.select({
|
|
805
813
|
message: `How would you like to set up ${template.name}?`,
|
|
806
814
|
options: [
|
|
@@ -812,7 +820,7 @@ async function handleApiKeyProvider(template) {
|
|
|
812
820
|
{
|
|
813
821
|
value: "signup",
|
|
814
822
|
label: pc.cyan("Open signup page in browser"),
|
|
815
|
-
hint: `Free tier at ${signupUrl}`
|
|
823
|
+
hint: template.signupNote ?? `Free tier at ${signupUrl}`
|
|
816
824
|
},
|
|
817
825
|
{
|
|
818
826
|
value: "skip",
|
|
@@ -1032,28 +1040,27 @@ async function runMainMenu() {
|
|
|
1032
1040
|
switch (choice) {
|
|
1033
1041
|
case "claude":
|
|
1034
1042
|
gateOutro("Launching Claude Code...");
|
|
1035
|
-
return
|
|
1036
|
-
// The actual launch is handled by the claude command
|
|
1043
|
+
return dispatchCommand({ command: "claude", claudeArgs: [] });
|
|
1037
1044
|
case "codex":
|
|
1038
1045
|
gateOutro("Launching Codex...");
|
|
1039
|
-
return
|
|
1046
|
+
return dispatchCommand({ command: "codex", claudeArgs: [] });
|
|
1040
1047
|
case "providers":
|
|
1041
1048
|
gateOutro("Opening provider manager...");
|
|
1042
|
-
return
|
|
1049
|
+
return dispatchCommand({ command: "providers", claudeArgs: [] });
|
|
1043
1050
|
case "onboarding":
|
|
1044
1051
|
return runOnboardingFlow();
|
|
1045
1052
|
case "doctor":
|
|
1046
1053
|
gateOutro("Running diagnostics...");
|
|
1047
|
-
return
|
|
1054
|
+
return dispatchCommand({ command: "doctor", claudeArgs: [] });
|
|
1048
1055
|
case "server":
|
|
1049
1056
|
gateOutro("Starting server...");
|
|
1050
|
-
return
|
|
1057
|
+
return dispatchCommand({ command: "server", claudeArgs: [] });
|
|
1051
1058
|
case "ui":
|
|
1052
1059
|
gateOutro("Opening dashboard...");
|
|
1053
|
-
return
|
|
1060
|
+
return dispatchCommand({ command: "ui", claudeArgs: [] });
|
|
1054
1061
|
case "settings":
|
|
1055
1062
|
gateOutro("Opening settings...");
|
|
1056
|
-
return
|
|
1063
|
+
return dispatchCommand({ command: "providers", claudeArgs: [] });
|
|
1057
1064
|
default:
|
|
1058
1065
|
return 0;
|
|
1059
1066
|
}
|
|
@@ -1122,7 +1129,10 @@ async function validateImportKey(lp, entry) {
|
|
|
1122
1129
|
allowInsecureLocal: catalogTemplate?.apiKeyOptional === true
|
|
1123
1130
|
});
|
|
1124
1131
|
if (!urlCheck.ok || !urlCheck.normalizedUrl) {
|
|
1125
|
-
return reject(
|
|
1132
|
+
return reject(
|
|
1133
|
+
"invalid-key",
|
|
1134
|
+
`${urlCheck.error ?? "Invalid API base URL."} ${urlCheck.hint ?? ""}`.trim()
|
|
1135
|
+
);
|
|
1126
1136
|
}
|
|
1127
1137
|
safeBaseUrl = urlCheck.normalizedUrl;
|
|
1128
1138
|
}
|
|
@@ -1200,7 +1210,10 @@ async function importFromOpencode(options = {}) {
|
|
|
1200
1210
|
continue;
|
|
1201
1211
|
}
|
|
1202
1212
|
const isOAuth = isOAuthImportProvider(lp.id, oauth);
|
|
1203
|
-
const entry = localProviderToRegistry(
|
|
1213
|
+
const entry = localProviderToRegistry(
|
|
1214
|
+
lp,
|
|
1215
|
+
isOAuth ? { authType: "oauth", authRef: oauthAuthRef(lp.id) } : void 0
|
|
1216
|
+
);
|
|
1204
1217
|
if (!entry) {
|
|
1205
1218
|
skipped.push({
|
|
1206
1219
|
id: lp.id,
|
|
@@ -1233,7 +1246,9 @@ async function importFromOpencode(options = {}) {
|
|
|
1233
1246
|
existing,
|
|
1234
1247
|
incoming: entry,
|
|
1235
1248
|
incomingProvider: lp,
|
|
1236
|
-
existingKeyHint: await keyHint(existing.id, existing.authRef, {
|
|
1249
|
+
existingKeyHint: await keyHint(existing.id, existing.authRef, {
|
|
1250
|
+
oauth: existing.authType === "oauth"
|
|
1251
|
+
}),
|
|
1237
1252
|
incomingKeyHint: await keyHint(entry.id, entry.authRef, {
|
|
1238
1253
|
fallbackKey: lp.apiKey,
|
|
1239
1254
|
oauth: isOAuth
|
|
@@ -1254,7 +1269,10 @@ async function importFromOpencode(options = {}) {
|
|
|
1254
1269
|
continue;
|
|
1255
1270
|
}
|
|
1256
1271
|
if (existingIdx >= 0) {
|
|
1257
|
-
registry.providers[existingIdx] = {
|
|
1272
|
+
registry.providers[existingIdx] = {
|
|
1273
|
+
...entry,
|
|
1274
|
+
addedAt: registry.providers[existingIdx].addedAt
|
|
1275
|
+
};
|
|
1258
1276
|
} else {
|
|
1259
1277
|
registry.providers.push(entry);
|
|
1260
1278
|
}
|
|
@@ -1295,7 +1313,8 @@ function detectShellProfile() {
|
|
|
1295
1313
|
const shell = process.env["SHELL"] ?? "";
|
|
1296
1314
|
if (process.platform === "darwin") {
|
|
1297
1315
|
if (shell.includes("zsh")) return { display: "~/.zshrc", path: `${homedir2()}/.zshrc` };
|
|
1298
|
-
if (shell.includes("bash"))
|
|
1316
|
+
if (shell.includes("bash"))
|
|
1317
|
+
return { display: "~/.bash_profile", path: `${homedir2()}/.bash_profile` };
|
|
1299
1318
|
return { display: "~/.profile", path: `${homedir2()}/.profile` };
|
|
1300
1319
|
}
|
|
1301
1320
|
if (process.platform === "linux") {
|
|
@@ -1350,28 +1369,70 @@ async function resolveOrCollectApiKey(simulate = false, trace = false) {
|
|
|
1350
1369
|
const saveOptions = (() => {
|
|
1351
1370
|
if (isMac) {
|
|
1352
1371
|
return [
|
|
1353
|
-
{
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1372
|
+
{
|
|
1373
|
+
value: "keychain",
|
|
1374
|
+
label: "Keychain only",
|
|
1375
|
+
hint: "Key stored encrypted in Keychain; anygate reads it automatically next time"
|
|
1376
|
+
},
|
|
1377
|
+
{
|
|
1378
|
+
value: "keychain-autoload",
|
|
1379
|
+
label: `Keychain + ${display} auto-load`,
|
|
1380
|
+
hint: `Key in Keychain; ${display} also exports it so all terminal tools can see it`
|
|
1381
|
+
},
|
|
1382
|
+
{
|
|
1383
|
+
value: "profile",
|
|
1384
|
+
label: `${display} only (plaintext)`,
|
|
1385
|
+
hint: "Key written directly to your shell profile \u2014 simpler but less secure"
|
|
1386
|
+
},
|
|
1387
|
+
{
|
|
1388
|
+
value: "session",
|
|
1389
|
+
label: "This session only",
|
|
1390
|
+
hint: "Not saved anywhere \u2014 you'll be asked again next time"
|
|
1391
|
+
}
|
|
1357
1392
|
];
|
|
1358
1393
|
}
|
|
1359
1394
|
if (isWindows4) {
|
|
1360
1395
|
return [
|
|
1361
|
-
{
|
|
1362
|
-
|
|
1363
|
-
|
|
1396
|
+
{
|
|
1397
|
+
value: "credential-manager",
|
|
1398
|
+
label: "Windows Credential Manager",
|
|
1399
|
+
hint: "Key stored securely; anygate reads it automatically next time"
|
|
1400
|
+
},
|
|
1401
|
+
{
|
|
1402
|
+
value: "setx",
|
|
1403
|
+
label: "Persistent environment variable (plaintext)",
|
|
1404
|
+
hint: "Runs setx \u2014 key visible in System Properties \u2192 Environment Variables"
|
|
1405
|
+
},
|
|
1406
|
+
{
|
|
1407
|
+
value: "session",
|
|
1408
|
+
label: "This session only",
|
|
1409
|
+
hint: "Not saved anywhere \u2014 you'll be asked again next time"
|
|
1410
|
+
}
|
|
1364
1411
|
];
|
|
1365
1412
|
}
|
|
1366
1413
|
const opts = [];
|
|
1367
1414
|
if (secretServiceAvailable) {
|
|
1368
|
-
opts.push({
|
|
1415
|
+
opts.push({
|
|
1416
|
+
value: "secret-service",
|
|
1417
|
+
label: "Secret Service (GNOME Keyring / KWallet)",
|
|
1418
|
+
hint: "Key stored securely in your desktop keyring; anygate reads it automatically next time"
|
|
1419
|
+
});
|
|
1369
1420
|
} else if (!simulate) {
|
|
1370
|
-
p2.log.info(
|
|
1421
|
+
p2.log.info(
|
|
1422
|
+
"No keyring daemon detected \u2014 secure storage requires GNOME Keyring or KWallet running."
|
|
1423
|
+
);
|
|
1371
1424
|
}
|
|
1372
1425
|
opts.push(
|
|
1373
|
-
{
|
|
1374
|
-
|
|
1426
|
+
{
|
|
1427
|
+
value: "profile",
|
|
1428
|
+
label: `${display} (plaintext)`,
|
|
1429
|
+
hint: "Key written directly to your shell profile"
|
|
1430
|
+
},
|
|
1431
|
+
{
|
|
1432
|
+
value: "session",
|
|
1433
|
+
label: "This session only",
|
|
1434
|
+
hint: "Not saved anywhere \u2014 you'll be asked again next time"
|
|
1435
|
+
}
|
|
1375
1436
|
);
|
|
1376
1437
|
return opts;
|
|
1377
1438
|
})();
|
|
@@ -1412,7 +1473,9 @@ async function resolveOrCollectApiKey(simulate = false, trace = false) {
|
|
|
1412
1473
|
${autoLoadLine}
|
|
1413
1474
|
`);
|
|
1414
1475
|
}
|
|
1415
|
-
p2.log.success(
|
|
1476
|
+
p2.log.success(
|
|
1477
|
+
`Key saved to Keychain and auto-load added to ${display} \u2014 active now and in all future terminals.`
|
|
1478
|
+
);
|
|
1416
1479
|
} catch {
|
|
1417
1480
|
p2.log.success("Key saved to Keychain \u2014 active now and automatically loaded next time.");
|
|
1418
1481
|
p2.log.warn(`Could not write auto-load line to ${display}`);
|
|
@@ -1422,15 +1485,21 @@ ${autoLoadLine}
|
|
|
1422
1485
|
}
|
|
1423
1486
|
} else if (saveChoice === "credential-manager") {
|
|
1424
1487
|
if (await saveToCredentialStore(trimmedKey)) {
|
|
1425
|
-
p2.log.success(
|
|
1488
|
+
p2.log.success(
|
|
1489
|
+
"Key saved to Windows Credential Manager \u2014 active now and automatically loaded next time."
|
|
1490
|
+
);
|
|
1426
1491
|
} else {
|
|
1427
1492
|
p2.log.warn("Could not write to Credential Manager \u2014 key will be used for this session only");
|
|
1428
1493
|
}
|
|
1429
1494
|
} else if (saveChoice === "setx") {
|
|
1430
1495
|
try {
|
|
1431
|
-
const result = spawnSync("setx", ["OPENCODE_API_KEY", trimmedKey], {
|
|
1496
|
+
const result = spawnSync("setx", ["OPENCODE_API_KEY", trimmedKey], {
|
|
1497
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1498
|
+
});
|
|
1432
1499
|
if (result.status !== 0) throw new Error("setx exited with non-zero status");
|
|
1433
|
-
p2.log.success(
|
|
1500
|
+
p2.log.success(
|
|
1501
|
+
"Key saved as a user environment variable \u2014 active now and in all future terminals."
|
|
1502
|
+
);
|
|
1434
1503
|
} catch {
|
|
1435
1504
|
p2.log.warn("Could not run setx \u2014 key will be used for this session only");
|
|
1436
1505
|
}
|
|
@@ -1534,7 +1603,9 @@ async function runFirstRunWizard(trace = false) {
|
|
|
1534
1603
|
return runFirstRunWizard(trace);
|
|
1535
1604
|
}
|
|
1536
1605
|
if (result.imported.length === 0) {
|
|
1537
|
-
p3.log.warn(
|
|
1606
|
+
p3.log.warn(
|
|
1607
|
+
"No providers imported. Configure providers in OpenCode first, or use Quick start with Zen."
|
|
1608
|
+
);
|
|
1538
1609
|
return runFirstRunWizard(trace);
|
|
1539
1610
|
}
|
|
1540
1611
|
p3.log.success(
|
|
@@ -1545,9 +1616,6 @@ async function runFirstRunWizard(trace = false) {
|
|
|
1545
1616
|
return "continue";
|
|
1546
1617
|
}
|
|
1547
1618
|
|
|
1548
|
-
// src/cli/claude.ts
|
|
1549
|
-
init_config();
|
|
1550
|
-
|
|
1551
1619
|
// src/apps/shared/prompts.ts
|
|
1552
1620
|
import * as p4 from "@clack/prompts";
|
|
1553
1621
|
import pc3 from "picocolors";
|
|
@@ -1565,23 +1633,32 @@ function scoreModelSearch(query, fields) {
|
|
|
1565
1633
|
return { normalized, compact: normalized.replace(/\s+/g, ""), weight: field.weight };
|
|
1566
1634
|
});
|
|
1567
1635
|
const tokens = normalizedQuery.split(" ").filter(Boolean);
|
|
1568
|
-
if (!tokens.every(
|
|
1636
|
+
if (!tokens.every(
|
|
1637
|
+
(token) => searchableFields.some(
|
|
1638
|
+
(field) => field.normalized.includes(token) || field.compact.includes(token)
|
|
1639
|
+
)
|
|
1640
|
+
)) {
|
|
1569
1641
|
return 0;
|
|
1570
1642
|
}
|
|
1571
1643
|
let score = 1;
|
|
1572
1644
|
for (const field of searchableFields) {
|
|
1573
1645
|
if (field.normalized === normalizedQuery) score = Math.max(score, field.weight + 300);
|
|
1574
1646
|
else if (field.compact === compactQuery) score = Math.max(score, field.weight + 260);
|
|
1575
|
-
else if (field.normalized.startsWith(normalizedQuery))
|
|
1647
|
+
else if (field.normalized.startsWith(normalizedQuery))
|
|
1648
|
+
score = Math.max(score, field.weight + 180);
|
|
1576
1649
|
else if (field.compact.startsWith(compactQuery)) score = Math.max(score, field.weight + 150);
|
|
1577
1650
|
else if (field.normalized.includes(normalizedQuery)) score = Math.max(score, field.weight + 90);
|
|
1578
1651
|
else if (field.compact.includes(compactQuery)) score = Math.max(score, field.weight + 70);
|
|
1579
1652
|
}
|
|
1580
|
-
return score + tokens.reduce(
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1653
|
+
return score + tokens.reduce(
|
|
1654
|
+
(sum, token) => sum + searchableFields.reduce((best, field) => {
|
|
1655
|
+
if (field.normalized.split(" ").includes(token)) return Math.max(best, 30);
|
|
1656
|
+
if (field.normalized.includes(token) || field.compact.includes(token))
|
|
1657
|
+
return Math.max(best, 12);
|
|
1658
|
+
return best;
|
|
1659
|
+
}, 0),
|
|
1660
|
+
0
|
|
1661
|
+
);
|
|
1585
1662
|
}
|
|
1586
1663
|
|
|
1587
1664
|
// src/apps/shared/prompts.ts
|
|
@@ -1687,7 +1764,11 @@ async function selectLargeCatalog(models, browseList, toOption, message, initial
|
|
|
1687
1764
|
const method = await p4.select({
|
|
1688
1765
|
message: `${message} (${models.length} available)`,
|
|
1689
1766
|
options: [
|
|
1690
|
-
{
|
|
1767
|
+
{
|
|
1768
|
+
value: MODE_SEARCH,
|
|
1769
|
+
label: pc3.cyan("Search models"),
|
|
1770
|
+
hint: "Filter by name, id, or brand"
|
|
1771
|
+
},
|
|
1691
1772
|
{
|
|
1692
1773
|
value: MODE_BROWSE,
|
|
1693
1774
|
label: pc3.cyan("Browse all models"),
|
|
@@ -1703,13 +1784,9 @@ async function selectLargeCatalog(models, browseList, toOption, message, initial
|
|
|
1703
1784
|
continue;
|
|
1704
1785
|
}
|
|
1705
1786
|
if (mode === "browse") {
|
|
1706
|
-
const picked = await pickModelFromPagedList(
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
message,
|
|
1710
|
-
initialModelId,
|
|
1711
|
-
{ search: true }
|
|
1712
|
-
);
|
|
1787
|
+
const picked = await pickModelFromPagedList(browseList, toOption, message, initialModelId, {
|
|
1788
|
+
search: true
|
|
1789
|
+
});
|
|
1713
1790
|
if (picked === "search") {
|
|
1714
1791
|
mode = "search";
|
|
1715
1792
|
continue;
|
|
@@ -1757,10 +1834,7 @@ async function selectModelWithSearch(models, toOption, message, initialModelId,
|
|
|
1757
1834
|
if (models.length === 0) return null;
|
|
1758
1835
|
const orderedBrowse = browseList ?? sortModelsByBrand(models);
|
|
1759
1836
|
if (models.length <= MODEL_SEARCH_THRESHOLD) {
|
|
1760
|
-
const options = [
|
|
1761
|
-
...models.map(toOption),
|
|
1762
|
-
navOption("__back__", "\u2190 Go back", "")
|
|
1763
|
-
];
|
|
1837
|
+
const options = [...models.map(toOption), navOption("__back__", "\u2190 Go back", "")];
|
|
1764
1838
|
const initialValue = initialModelId && options.some((o) => o.value === initialModelId) ? initialModelId : options[0]?.value;
|
|
1765
1839
|
const picked = await p4.select({
|
|
1766
1840
|
message,
|
|
@@ -1908,7 +1982,8 @@ function isGeminiNonInteractive(args) {
|
|
|
1908
1982
|
for (let i = 0; i < args.length; i++) {
|
|
1909
1983
|
const arg = args[i];
|
|
1910
1984
|
if (arg === "--") return false;
|
|
1911
|
-
if (arg === "-p" || arg === "--prompt" || arg === "-i" || arg === "--prompt-interactive")
|
|
1985
|
+
if (arg === "-p" || arg === "--prompt" || arg === "-i" || arg === "--prompt-interactive")
|
|
1986
|
+
return true;
|
|
1912
1987
|
if (arg.startsWith("-")) {
|
|
1913
1988
|
i = skipAttachedFlagValue(args, i);
|
|
1914
1989
|
continue;
|
|
@@ -1956,6 +2031,10 @@ function resolveLaunchTarget(explicit, prefs, agent) {
|
|
|
1956
2031
|
const slug = explicit.modelId ? parseModelSlug(explicit.modelId) : null;
|
|
1957
2032
|
const providerId = explicit.providerId ?? slug?.providerId ?? (agent === "claude" ? prefs.lastProvider : agent === "codex" ? prefs.lastCodexProvider : agent === "antigravity" ? prefs.lastAntigravityProvider : prefs.lastGeminiProvider);
|
|
1958
2033
|
const modelId = slug?.modelId ?? explicit.modelId ?? (agent === "claude" ? prefs.lastModel : agent === "codex" ? prefs.lastCodexModel : agent === "antigravity" ? prefs.lastAntigravityModel : prefs.lastGeminiModel);
|
|
2034
|
+
if (explicit.allModels) {
|
|
2035
|
+
if (!providerId) return null;
|
|
2036
|
+
return { providerId, allModels: true };
|
|
2037
|
+
}
|
|
1959
2038
|
if (!providerId || !modelId) return null;
|
|
1960
2039
|
return { providerId, modelId };
|
|
1961
2040
|
}
|
|
@@ -1968,6 +2047,7 @@ function findProviderAndModel(providers, target) {
|
|
|
1968
2047
|
return { provider, model };
|
|
1969
2048
|
}
|
|
1970
2049
|
function hasCompleteExplicitLaunch(explicit) {
|
|
2050
|
+
if (explicit.allModels && explicit.providerId) return true;
|
|
1971
2051
|
if (explicit.providerId && explicit.modelId) return true;
|
|
1972
2052
|
if (explicit.modelId) {
|
|
1973
2053
|
const slug = parseModelSlug(explicit.modelId);
|
|
@@ -1985,16 +2065,16 @@ function planLaunchWizard(opts) {
|
|
|
1985
2065
|
return {
|
|
1986
2066
|
skip: false,
|
|
1987
2067
|
target: null,
|
|
1988
|
-
error: "
|
|
2068
|
+
error: "A provider is required \u2014 use --provider, --all-models, or a saved preference."
|
|
1989
2069
|
};
|
|
1990
2070
|
}
|
|
1991
2071
|
return { skip: true, target };
|
|
1992
2072
|
}
|
|
1993
|
-
if (explicit.providerId || explicit.modelId) {
|
|
2073
|
+
if (explicit.providerId || explicit.modelId || explicit.allModels) {
|
|
1994
2074
|
return {
|
|
1995
2075
|
skip: false,
|
|
1996
2076
|
target: null,
|
|
1997
|
-
error: "Both --provider and --model are required (or use provider__model slug with --model)."
|
|
2077
|
+
error: explicit.allModels ? "Use --all-models with --provider to launch every model from a provider." : "Both --provider and --model are required (or use provider__model slug with --model)."
|
|
1998
2078
|
};
|
|
1999
2079
|
}
|
|
2000
2080
|
if (nonInteractive) {
|
|
@@ -2011,9 +2091,12 @@ function planLaunchWizard(opts) {
|
|
|
2011
2091
|
return { skip: false, target: null };
|
|
2012
2092
|
}
|
|
2013
2093
|
function nonInteractiveLaunchError(agent) {
|
|
2014
|
-
if (agent === "claude")
|
|
2015
|
-
|
|
2016
|
-
if (agent === "
|
|
2094
|
+
if (agent === "claude")
|
|
2095
|
+
return "Print mode requires --provider and --model, or saved preferences from a prior launch.";
|
|
2096
|
+
if (agent === "codex")
|
|
2097
|
+
return "Non-interactive Codex launch requires --provider and --model, or saved preferences from a prior launch.";
|
|
2098
|
+
if (agent === "antigravity")
|
|
2099
|
+
return "Non-interactive Antigravity launch requires --provider and --model, or saved preferences from a prior launch.";
|
|
2017
2100
|
return "Non-interactive Gemini launch requires --provider and --model, or saved preferences from a prior launch.";
|
|
2018
2101
|
}
|
|
2019
2102
|
function isAntigravityNonInteractive(args) {
|
|
@@ -2027,7 +2110,6 @@ function isAntigravityNonInteractive(args) {
|
|
|
2027
2110
|
// src/cli/providers-command.ts
|
|
2028
2111
|
import pc4 from "picocolors";
|
|
2029
2112
|
import * as p5 from "@clack/prompts";
|
|
2030
|
-
init_config();
|
|
2031
2113
|
function providerHubChoiceValue(entry) {
|
|
2032
2114
|
return `provider:${entry.id}`;
|
|
2033
2115
|
}
|
|
@@ -2039,8 +2121,16 @@ async function runProvidersImport() {
|
|
|
2039
2121
|
const choice = await p5.select({
|
|
2040
2122
|
message: "Which configuration should we keep?",
|
|
2041
2123
|
options: [
|
|
2042
|
-
{
|
|
2043
|
-
|
|
2124
|
+
{
|
|
2125
|
+
value: "keep",
|
|
2126
|
+
label: pc4.cyan("Keep mine"),
|
|
2127
|
+
hint: "Leave your current anygate config unchanged"
|
|
2128
|
+
},
|
|
2129
|
+
{
|
|
2130
|
+
value: "import",
|
|
2131
|
+
label: pc4.cyan("Use imported"),
|
|
2132
|
+
hint: "Replace with OpenCode settings and refresh models"
|
|
2133
|
+
},
|
|
2044
2134
|
{ value: "skip", label: pc4.dim("Skip this provider"), hint: "" }
|
|
2045
2135
|
]
|
|
2046
2136
|
});
|
|
@@ -2183,7 +2273,9 @@ async function runProvidersRefreshModels(providerId) {
|
|
|
2183
2273
|
}
|
|
2184
2274
|
const diff = result.previousModelCount === void 0 ? 0 : (result.modelCount ?? 0) - result.previousModelCount;
|
|
2185
2275
|
const diffStr = result.previousModelCount === void 0 ? "" : diff > 0 ? ` (+${diff})` : diff < 0 ? ` (${diff})` : "";
|
|
2186
|
-
p5.log.success(
|
|
2276
|
+
p5.log.success(
|
|
2277
|
+
`${result.name}: ${result.modelCount} model${result.modelCount === 1 ? "" : "s"} updated${diffStr}.`
|
|
2278
|
+
);
|
|
2187
2279
|
if (result.reason) {
|
|
2188
2280
|
p5.log.warn(result.reason);
|
|
2189
2281
|
}
|
|
@@ -2251,7 +2343,9 @@ async function pickTemplateFromCatalog() {
|
|
|
2251
2343
|
const query = String(searchInput);
|
|
2252
2344
|
const matched = filterTemplates(templates, query);
|
|
2253
2345
|
if (matched.length === 0) {
|
|
2254
|
-
const alreadyAdded = filterTemplates(listSupportedTemplates(), query).filter(
|
|
2346
|
+
const alreadyAdded = filterTemplates(listSupportedTemplates(), query).filter(
|
|
2347
|
+
(t) => configuredIds.has(t.id)
|
|
2348
|
+
);
|
|
2255
2349
|
if (alreadyAdded.length > 0) {
|
|
2256
2350
|
p5.log.info(`Already configured: ${alreadyAdded.map((t) => t.name).join(", ")}`);
|
|
2257
2351
|
} else {
|
|
@@ -2275,7 +2369,9 @@ async function pickTemplateFromCatalog() {
|
|
|
2275
2369
|
}
|
|
2276
2370
|
async function runOpenCodeCloudDetail() {
|
|
2277
2371
|
const registry = loadRegistry();
|
|
2278
|
-
const routes = registry.providers.filter(
|
|
2372
|
+
const routes = registry.providers.filter(
|
|
2373
|
+
(provider) => provider.id === "zen" || provider.id === "go"
|
|
2374
|
+
);
|
|
2279
2375
|
printCloudProviderPanel("OpenCode Zen / Go");
|
|
2280
2376
|
if (routes.length === 0) return "back";
|
|
2281
2377
|
const choice = await p5.select({
|
|
@@ -2327,7 +2423,11 @@ async function runProviderDetail(id) {
|
|
|
2327
2423
|
label: provider.enabled ? "Disable provider" : "Enable provider",
|
|
2328
2424
|
hint: provider.enabled ? "Hide from anygate claude picker" : "Show in anygate claude picker"
|
|
2329
2425
|
},
|
|
2330
|
-
{
|
|
2426
|
+
{
|
|
2427
|
+
value: "remove",
|
|
2428
|
+
label: "Remove provider",
|
|
2429
|
+
hint: "Delete from registry and Keychain when safe"
|
|
2430
|
+
},
|
|
2331
2431
|
{ value: "back", label: "Back", hint: "" }
|
|
2332
2432
|
);
|
|
2333
2433
|
const action = await p5.select({
|
|
@@ -2380,7 +2480,8 @@ function parseProvidersArgs(args) {
|
|
|
2380
2480
|
if (first === "list") return { subcommand: "list", showHelp: false };
|
|
2381
2481
|
if (first === "remove" || first === "rm") {
|
|
2382
2482
|
const targetId = args[1];
|
|
2383
|
-
if (!targetId)
|
|
2483
|
+
if (!targetId)
|
|
2484
|
+
return { subcommand: "remove", showHelp: true, error: "Usage: anygate providers remove <id>" };
|
|
2384
2485
|
return { subcommand: "remove", showHelp: false, removeId: targetId };
|
|
2385
2486
|
}
|
|
2386
2487
|
if (first === "refresh-models") {
|
|
@@ -2408,6 +2509,36 @@ ${pc4.bold("Usage:")}
|
|
|
2408
2509
|
anygate providers refresh-models Refresh model catalog for all/specific provider
|
|
2409
2510
|
anygate providers auth <id> Sign in with OAuth (xAI, OpenAI, GitHub Copilot, \u2026)`;
|
|
2410
2511
|
}
|
|
2512
|
+
async function promptTemplateBaseUrl(template) {
|
|
2513
|
+
const entered = await p5.text({
|
|
2514
|
+
message: template.urlPrompt ?? "API Base URL:",
|
|
2515
|
+
placeholder: template.urlPlaceholder ?? template.defaultBaseUrl,
|
|
2516
|
+
defaultValue: template.defaultBaseUrl ?? "",
|
|
2517
|
+
validate: (v) => v.trim() || template.defaultBaseUrl ? void 0 : "URL is required"
|
|
2518
|
+
});
|
|
2519
|
+
if (p5.isCancel(entered)) return null;
|
|
2520
|
+
const baseUrl = String(entered ?? "").trim() || (template.defaultBaseUrl ?? "");
|
|
2521
|
+
if (!baseUrl) return null;
|
|
2522
|
+
let allowInsecureLocal = false;
|
|
2523
|
+
if (/^http:\/\//i.test(baseUrl)) {
|
|
2524
|
+
p5.log.warn(
|
|
2525
|
+
"HTTP is not encrypted. Only use it for a trusted local or LAN server, like Ollama on your own network."
|
|
2526
|
+
);
|
|
2527
|
+
const allowLocal = await p5.confirm({
|
|
2528
|
+
message: "Allow insecure HTTP for this local/LAN server?",
|
|
2529
|
+
initialValue: true
|
|
2530
|
+
});
|
|
2531
|
+
if (p5.isCancel(allowLocal)) return null;
|
|
2532
|
+
allowInsecureLocal = allowLocal === true;
|
|
2533
|
+
}
|
|
2534
|
+
const valid = await validateCustomEndpointUrl(baseUrl, { allowInsecureLocal });
|
|
2535
|
+
if (!valid.ok || !valid.normalizedUrl) {
|
|
2536
|
+
p5.log.error(valid.error ?? "Invalid URL.");
|
|
2537
|
+
if (valid.hint) p5.log.info(valid.hint);
|
|
2538
|
+
return null;
|
|
2539
|
+
}
|
|
2540
|
+
return valid.normalizedUrl;
|
|
2541
|
+
}
|
|
2411
2542
|
async function runTemplateAddFlow(t) {
|
|
2412
2543
|
const template = t ?? await pickTemplateFromCatalog();
|
|
2413
2544
|
if (!template) return 0;
|
|
@@ -2416,9 +2547,16 @@ async function runTemplateAddFlow(t) {
|
|
|
2416
2547
|
});
|
|
2417
2548
|
if (p5.isCancel(inputKey)) return 0;
|
|
2418
2549
|
const apiKey = String(inputKey ?? "").trim();
|
|
2419
|
-
|
|
2550
|
+
let baseUrl;
|
|
2551
|
+
if (template.urlPrompt) {
|
|
2552
|
+
const collected = await promptTemplateBaseUrl(template);
|
|
2553
|
+
if (!collected) return 1;
|
|
2554
|
+
baseUrl = collected;
|
|
2555
|
+
}
|
|
2556
|
+
const result = await addProviderFromTemplate(template, apiKey, { baseUrl });
|
|
2420
2557
|
if (!result.added) {
|
|
2421
2558
|
if (result.error) p5.log.error(result.error);
|
|
2559
|
+
if (result.hint) p5.log.info(result.hint);
|
|
2422
2560
|
return 1;
|
|
2423
2561
|
}
|
|
2424
2562
|
logConnected(template.name, result.modelCount ?? 0);
|
|
@@ -2457,7 +2595,9 @@ async function runCustomEndpointAddFlow() {
|
|
|
2457
2595
|
const usesHttp = /^http:\/\//i.test(String(baseUrl).trim());
|
|
2458
2596
|
let allowInsecureHttp = false;
|
|
2459
2597
|
if (usesHttp) {
|
|
2460
|
-
p5.log.warn(
|
|
2598
|
+
p5.log.warn(
|
|
2599
|
+
"HTTP is not encrypted. Only use it for a trusted local or LAN server, like Ollama on your own network."
|
|
2600
|
+
);
|
|
2461
2601
|
const allowLocal = await p5.confirm({
|
|
2462
2602
|
message: "Allow insecure HTTP for this local/LAN server?",
|
|
2463
2603
|
initialValue: true
|
|
@@ -2567,12 +2707,24 @@ async function runProvidersHub() {
|
|
|
2567
2707
|
hint
|
|
2568
2708
|
});
|
|
2569
2709
|
}
|
|
2570
|
-
options.push({
|
|
2710
|
+
options.push({
|
|
2711
|
+
value: "auth-menu",
|
|
2712
|
+
label: "\u2192 Sign in with OAuth",
|
|
2713
|
+
hint: "GitHub Copilot \xB7 xAI \xB7 OpenAI"
|
|
2714
|
+
});
|
|
2571
2715
|
if (entries.length > 0) {
|
|
2572
|
-
options.push({
|
|
2716
|
+
options.push({
|
|
2717
|
+
value: "refresh-all",
|
|
2718
|
+
label: "\u21BA Refresh all models",
|
|
2719
|
+
hint: "Update model lists for all providers"
|
|
2720
|
+
});
|
|
2573
2721
|
}
|
|
2574
2722
|
if (hasOpencode) {
|
|
2575
|
-
options.push({
|
|
2723
|
+
options.push({
|
|
2724
|
+
value: "import",
|
|
2725
|
+
label: "\u2192 Import providers from OpenCode CLI",
|
|
2726
|
+
hint: "One-time import"
|
|
2727
|
+
});
|
|
2576
2728
|
}
|
|
2577
2729
|
options.push({ value: "done", label: "Done", hint: "" });
|
|
2578
2730
|
const choice = await p5.select({
|
|
@@ -2651,7 +2803,9 @@ async function runProvidersCommand(args) {
|
|
|
2651
2803
|
|
|
2652
2804
|
// src/cli/claude.ts
|
|
2653
2805
|
async function handleClaudeCommand(parsed) {
|
|
2654
|
-
const { dryRun, setup, trace, launchProvider
|
|
2806
|
+
const { dryRun, setup, trace, launchProvider } = parsed;
|
|
2807
|
+
const launchAllModels = parsed.launchAllModels || parsed.launchModel === "All";
|
|
2808
|
+
const launchModel = launchAllModels && !parsed.launchModel ? "All" : parsed.launchModel;
|
|
2655
2809
|
const claudeArgs = normalizeClaudeAgentArgs(parsed.claudeArgs);
|
|
2656
2810
|
const agentStdout = wantsCleanAgentStdout("claude", claudeArgs);
|
|
2657
2811
|
setAgentStdoutMode(agentStdout);
|
|
@@ -2666,7 +2820,7 @@ async function handleClaudeCommand(parsed) {
|
|
|
2666
2820
|
const conflicts = detectConflicts();
|
|
2667
2821
|
const favorites = dryRun ? [] : prefs.favoriteModels ?? [];
|
|
2668
2822
|
const launchPlan = planLaunchWizard({
|
|
2669
|
-
explicit: { providerId: launchProvider, modelId: launchModel },
|
|
2823
|
+
explicit: launchAllModels ? { providerId: launchProvider, allModels: true } : { providerId: launchProvider, modelId: launchModel },
|
|
2670
2824
|
childArgs: claudeArgs,
|
|
2671
2825
|
agent: "claude",
|
|
2672
2826
|
prefs
|
|
@@ -2677,7 +2831,13 @@ Error: ${launchPlan.error}
|
|
|
2677
2831
|
`));
|
|
2678
2832
|
return 1;
|
|
2679
2833
|
}
|
|
2680
|
-
|
|
2834
|
+
let catalogMode = false;
|
|
2835
|
+
const hasFavorites = favorites.length > 0;
|
|
2836
|
+
if (launchPlan.skip && launchPlan.target) {
|
|
2837
|
+
if (launchPlan.target.allModels) {
|
|
2838
|
+
catalogMode = "provider-all";
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2681
2841
|
if (!agentStdout) gateIntro("Claude Code");
|
|
2682
2842
|
if (setup && !dryRun && !agentStdout) {
|
|
2683
2843
|
p6.log.info("Provider setup now lives in anygate providers \u2014 opening that next is recommended.");
|
|
@@ -2727,7 +2887,7 @@ Error: ${launchPlan.error}
|
|
|
2727
2887
|
}
|
|
2728
2888
|
return baseOption;
|
|
2729
2889
|
});
|
|
2730
|
-
if (
|
|
2890
|
+
if (hasFavorites) {
|
|
2731
2891
|
providerOptions.unshift({
|
|
2732
2892
|
value: "__favorites__",
|
|
2733
2893
|
label: "\u2B50 Favorites Catalog",
|
|
@@ -2738,19 +2898,35 @@ Error: ${launchPlan.error}
|
|
|
2738
2898
|
let activeProvider;
|
|
2739
2899
|
let selectedModel;
|
|
2740
2900
|
if (launchPlan.skip && launchPlan.target) {
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
`Provider
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2901
|
+
if (launchPlan.target.allModels) {
|
|
2902
|
+
const resolvedProvider = allProviders.find((lp) => lp.id === launchPlan.target.providerId);
|
|
2903
|
+
if (!resolvedProvider) {
|
|
2904
|
+
p6.log.error(`Provider not found: ${launchPlan.target.providerId}`);
|
|
2905
|
+
return 1;
|
|
2906
|
+
}
|
|
2907
|
+
activeProvider = resolvedProvider;
|
|
2908
|
+
selectedModel = activeProvider.models[0];
|
|
2909
|
+
catalogMode = "provider-all";
|
|
2910
|
+
if (!agentStdout) {
|
|
2911
|
+
p6.log.step(`Using all ${activeProvider.models.length} models from ${activeProvider.name}`);
|
|
2912
|
+
}
|
|
2913
|
+
if (!dryRun) recordLaunchSelection("claude", activeProvider.id, selectedModel.id, prefs);
|
|
2914
|
+
} else {
|
|
2915
|
+
const resolved = findProviderAndModel(allProviders, launchPlan.target);
|
|
2916
|
+
if (!resolved) {
|
|
2917
|
+
p6.log.error(
|
|
2918
|
+
`Provider/model not found: ${launchPlan.target.providerId} / ${launchPlan.target.modelId}`
|
|
2919
|
+
);
|
|
2920
|
+
return 1;
|
|
2921
|
+
}
|
|
2922
|
+
activeProvider = resolved.provider;
|
|
2923
|
+
selectedModel = resolved.model;
|
|
2924
|
+
catalogMode = false;
|
|
2925
|
+
if (!agentStdout) {
|
|
2926
|
+
p6.log.step(`Using ${selectedModel.name || selectedModel.id} (${activeProvider.name})`);
|
|
2927
|
+
}
|
|
2928
|
+
if (!dryRun) recordLaunchSelection("claude", activeProvider.id, selectedModel.id, prefs);
|
|
2752
2929
|
}
|
|
2753
|
-
if (!dryRun) recordLaunchSelection("claude", activeProvider.id, selectedModel.id, prefs);
|
|
2754
2930
|
} else {
|
|
2755
2931
|
let currentInitialProvider = initialProvider;
|
|
2756
2932
|
while (true) {
|
|
@@ -2792,6 +2968,7 @@ Error: ${launchPlan.error}
|
|
|
2792
2968
|
const sel = available[Number(pickedIdx)];
|
|
2793
2969
|
activeProvider = sel.provider;
|
|
2794
2970
|
selectedModel = sel.model;
|
|
2971
|
+
catalogMode = "favorites";
|
|
2795
2972
|
if (!dryRun) recordLaunchSelection("claude", activeProvider.id, selectedModel.id, prefs);
|
|
2796
2973
|
break;
|
|
2797
2974
|
} else {
|
|
@@ -2822,6 +2999,32 @@ Error: ${launchPlan.error}
|
|
|
2822
2999
|
} else {
|
|
2823
3000
|
activeProvider = selectedProvider;
|
|
2824
3001
|
}
|
|
3002
|
+
const modelModeChoice = await p6.select({
|
|
3003
|
+
message: `Launch mode for ${activeProvider.name}?`,
|
|
3004
|
+
options: [
|
|
3005
|
+
{
|
|
3006
|
+
value: "specific",
|
|
3007
|
+
label: "One model",
|
|
3008
|
+
hint: "Pick a specific model from this provider"
|
|
3009
|
+
},
|
|
3010
|
+
{
|
|
3011
|
+
value: "all",
|
|
3012
|
+
label: `All models (${activeProvider.models.length})`,
|
|
3013
|
+
hint: "Every model from this provider in the /model switcher"
|
|
3014
|
+
},
|
|
3015
|
+
navOption("__back__", "\u2190 Back", "Choose a different provider")
|
|
3016
|
+
]
|
|
3017
|
+
});
|
|
3018
|
+
if (p6.isCancel(modelModeChoice) || modelModeChoice === "__back__") {
|
|
3019
|
+
currentInitialProvider = activeProvider.id;
|
|
3020
|
+
continue;
|
|
3021
|
+
}
|
|
3022
|
+
if (modelModeChoice === "all") {
|
|
3023
|
+
catalogMode = "provider-all";
|
|
3024
|
+
selectedModel = activeProvider.models[0];
|
|
3025
|
+
if (!dryRun) recordLaunchSelection("claude", activeProvider.id, selectedModel.id, prefs);
|
|
3026
|
+
break;
|
|
3027
|
+
}
|
|
2825
3028
|
const pickedModelResult = await pickLocalModel(activeProvider, conflicts, prefs);
|
|
2826
3029
|
if (pickedModelResult === "back") {
|
|
2827
3030
|
currentInitialProvider = activeProvider.id;
|
|
@@ -2829,22 +3032,25 @@ Error: ${launchPlan.error}
|
|
|
2829
3032
|
}
|
|
2830
3033
|
if (!pickedModelResult) return 0;
|
|
2831
3034
|
selectedModel = pickedModelResult;
|
|
3035
|
+
catalogMode = false;
|
|
2832
3036
|
if (!dryRun) recordLaunchSelection("claude", activeProvider.id, selectedModel.id, prefs);
|
|
2833
3037
|
break;
|
|
2834
3038
|
}
|
|
2835
3039
|
}
|
|
2836
3040
|
}
|
|
2837
3041
|
const localProviders = catalog.length > 0 ? catalog : null;
|
|
2838
|
-
if (
|
|
2839
|
-
const resolveRoute = makeRouteResolver(
|
|
2840
|
-
localProviders
|
|
2841
|
-
);
|
|
3042
|
+
if (catalogMode === "favorites") {
|
|
3043
|
+
const resolveRoute = makeRouteResolver(localProviders);
|
|
2842
3044
|
const startingRoute = resolveRoute(activeProvider.id, selectedModel.id) ?? null;
|
|
2843
3045
|
if (!startingRoute) {
|
|
2844
3046
|
p6.log.error("Could not resolve a proxy route for the selected model.");
|
|
2845
3047
|
return 1;
|
|
2846
3048
|
}
|
|
2847
|
-
const { routes: catalogRoutes, droppedFavorites } = buildCatalogRoutes(
|
|
3049
|
+
const { routes: catalogRoutes, droppedFavorites } = buildCatalogRoutes(
|
|
3050
|
+
startingRoute,
|
|
3051
|
+
favorites,
|
|
3052
|
+
resolveRoute
|
|
3053
|
+
);
|
|
2848
3054
|
if (droppedFavorites.length > 0) {
|
|
2849
3055
|
p6.log.warn(
|
|
2850
3056
|
`Skipping ${droppedFavorites.length} favorite${droppedFavorites.length === 1 ? "" : "s"} that are no longer available in /model`
|
|
@@ -2882,6 +3088,35 @@ Error: ${launchPlan.error}
|
|
|
2882
3088
|
claudeArgs
|
|
2883
3089
|
);
|
|
2884
3090
|
}
|
|
3091
|
+
if (catalogMode === "provider-all") {
|
|
3092
|
+
const resolveRoute = makeRouteResolver(localProviders);
|
|
3093
|
+
const startingRoute = resolveRoute(activeProvider.id, selectedModel.id) ?? null;
|
|
3094
|
+
if (!startingRoute) {
|
|
3095
|
+
p6.log.error("Could not resolve a proxy route for the starting model.");
|
|
3096
|
+
return 1;
|
|
3097
|
+
}
|
|
3098
|
+
const catalogRoutes = buildProviderAllModelRoutes(activeProvider, startingRoute, resolveRoute);
|
|
3099
|
+
if (dryRun) {
|
|
3100
|
+
console.log("");
|
|
3101
|
+
console.log(pc5.bold(pc5.cyan(" DRY RUN \u2014 would execute (provider catalog mode):")));
|
|
3102
|
+
console.log("");
|
|
3103
|
+
console.log(` ${pc5.bold("Provider:")} ${activeProvider.name}`);
|
|
3104
|
+
console.log(` ${pc5.bold("Starting model:")} ${selectedModel.id}`);
|
|
3105
|
+
console.log(` ${pc5.bold("/model catalog:")} ${catalogRoutes.length} model(s)`);
|
|
3106
|
+
catalogRoutes.forEach((r) => console.log(` ${pc5.dim(r.displayName)}`));
|
|
3107
|
+
console.log("");
|
|
3108
|
+
console.log(pc5.dim(" (dry run complete \u2014 Claude Code was NOT launched)"));
|
|
3109
|
+
console.log("");
|
|
3110
|
+
return 0;
|
|
3111
|
+
}
|
|
3112
|
+
return launchClaudeViaCatalog(
|
|
3113
|
+
catalogRoutes,
|
|
3114
|
+
startingRoute,
|
|
3115
|
+
selectedModel.contextWindow,
|
|
3116
|
+
trace ?? false,
|
|
3117
|
+
claudeArgs
|
|
3118
|
+
);
|
|
3119
|
+
}
|
|
2885
3120
|
if (dryRun) {
|
|
2886
3121
|
const formatDesc = selectedModel.modelFormat === "anthropic" ? "direct passthrough" : "via SDK adapter proxy";
|
|
2887
3122
|
const endpoint = selectedModel.modelFormat === "anthropic" ? selectedModel.baseUrl ?? "(unknown)" : selectedModel.npm ?? "SDK";
|
|
@@ -2891,7 +3126,9 @@ Error: ${launchPlan.error}
|
|
|
2891
3126
|
console.log(` ${pc5.bold("Provider:")} ${activeProvider.name}`);
|
|
2892
3127
|
console.log(` ${pc5.bold("Model:")} ${selectedModel.id}`);
|
|
2893
3128
|
console.log(` ${pc5.bold("Format:")} ${selectedModel.modelFormat} (${formatDesc})`);
|
|
2894
|
-
console.log(
|
|
3129
|
+
console.log(
|
|
3130
|
+
` ${pc5.bold(selectedModel.modelFormat === "anthropic" ? "Endpoint:" : "SDK npm:")} ${endpoint}`
|
|
3131
|
+
);
|
|
2895
3132
|
console.log(` ${pc5.bold("Key:")} ${activeProvider.name} provider key`);
|
|
2896
3133
|
console.log("");
|
|
2897
3134
|
console.log(pc5.dim(" (dry run complete \u2014 Claude Code was NOT launched)"));
|
|
@@ -2900,9 +3137,7 @@ Error: ${launchPlan.error}
|
|
|
2900
3137
|
}
|
|
2901
3138
|
const launchApiKey = await resolveLocalProviderApiKey(activeProvider);
|
|
2902
3139
|
if (!launchApiKey?.trim()) {
|
|
2903
|
-
p6.log.error(
|
|
2904
|
-
new CredentialUnavailableError(activeProvider.id).userMessage
|
|
2905
|
-
);
|
|
3140
|
+
p6.log.error(new CredentialUnavailableError(activeProvider.id).userMessage);
|
|
2906
3141
|
return 1;
|
|
2907
3142
|
}
|
|
2908
3143
|
const isAvailable = await quickValidateModel(activeProvider.id, selectedModel.id);
|
|
@@ -2936,7 +3171,9 @@ Error: ${launchPlan.error}
|
|
|
2936
3171
|
);
|
|
2937
3172
|
if (!isAgentStdoutMode()) p6.log.info(`Cloud Code proxy started on port ${proxyHandle.port}`);
|
|
2938
3173
|
} catch (err) {
|
|
2939
|
-
p6.log.error(
|
|
3174
|
+
p6.log.error(
|
|
3175
|
+
`Failed to start Cloud Code proxy: ${err instanceof Error ? err.message : String(err)}`
|
|
3176
|
+
);
|
|
2940
3177
|
return 1;
|
|
2941
3178
|
}
|
|
2942
3179
|
childEnv = buildChildEnv(
|
|
@@ -2965,7 +3202,9 @@ Error: ${launchPlan.error}
|
|
|
2965
3202
|
);
|
|
2966
3203
|
if (!isAgentStdoutMode()) p6.log.info(`OAuth proxy started on port ${proxyHandle.port}`);
|
|
2967
3204
|
} catch (err) {
|
|
2968
|
-
p6.log.error(
|
|
3205
|
+
p6.log.error(
|
|
3206
|
+
`Failed to start OAuth proxy: ${err instanceof Error ? err.message : String(err)}`
|
|
3207
|
+
);
|
|
2969
3208
|
return 1;
|
|
2970
3209
|
}
|
|
2971
3210
|
childEnv = buildChildEnv(
|
|
@@ -3012,7 +3251,9 @@ Error: ${launchPlan.error}
|
|
|
3012
3251
|
);
|
|
3013
3252
|
}
|
|
3014
3253
|
} catch (err) {
|
|
3015
|
-
p6.log.error(
|
|
3254
|
+
p6.log.error(
|
|
3255
|
+
`Failed to start SDK adapter proxy: ${err instanceof Error ? err.message : String(err)}`
|
|
3256
|
+
);
|
|
3016
3257
|
return 1;
|
|
3017
3258
|
}
|
|
3018
3259
|
childEnv = buildChildEnv(
|
|
@@ -3041,7 +3282,9 @@ Error: ${launchPlan.error}
|
|
|
3041
3282
|
async function launchClaudeViaCatalog(catalogRoutes, startingRoute, contextWindow, trace, claudeArgs) {
|
|
3042
3283
|
let proxyHandle;
|
|
3043
3284
|
try {
|
|
3044
|
-
proxyHandle = await startProxyCatalog(catalogRoutes, startingRoute.aliasId, trace
|
|
3285
|
+
proxyHandle = await startProxyCatalog(catalogRoutes, startingRoute.aliasId, trace, {
|
|
3286
|
+
app: "Claude"
|
|
3287
|
+
});
|
|
3045
3288
|
p6.log.info(
|
|
3046
3289
|
`Switch menu active \u2014 proxy on port ${proxyHandle.port} ` + pc5.dim(`(${catalogRoutes.length} model${catalogRoutes.length !== 1 ? "s" : ""} in /model)`)
|
|
3047
3290
|
);
|
|
@@ -3073,7 +3316,6 @@ async function launchClaudeViaCatalog(catalogRoutes, startingRoute, contextWindo
|
|
|
3073
3316
|
// src/apps/codex/cli.ts
|
|
3074
3317
|
import pc8 from "picocolors";
|
|
3075
3318
|
import * as p9 from "@clack/prompts";
|
|
3076
|
-
init_config();
|
|
3077
3319
|
|
|
3078
3320
|
// src/apps/codex/proxy.ts
|
|
3079
3321
|
import { createHash } from "crypto";
|
|
@@ -3130,7 +3372,9 @@ function applyClaudeCodeOAuthIdentity(input, sdkParams) {
|
|
|
3130
3372
|
import { streamText, generateText, tool, jsonSchema } from "ai";
|
|
3131
3373
|
function messageText(content) {
|
|
3132
3374
|
if (typeof content === "string") return content;
|
|
3133
|
-
return (content ?? []).map(
|
|
3375
|
+
return (content ?? []).map(
|
|
3376
|
+
(p18) => p18.type === "output_text" || p18.type === "input_text" || p18.type === "text" ? p18.text ?? "" : ""
|
|
3377
|
+
).join("");
|
|
3134
3378
|
}
|
|
3135
3379
|
function extractDeveloperAndInstructions(items, instructions) {
|
|
3136
3380
|
const developerParts = [];
|
|
@@ -3174,9 +3418,16 @@ function mergeConsecutiveMessages(messages) {
|
|
|
3174
3418
|
return out;
|
|
3175
3419
|
}
|
|
3176
3420
|
function ensureUserFirst(messages) {
|
|
3177
|
-
if (messages.length === 0)
|
|
3421
|
+
if (messages.length === 0)
|
|
3422
|
+
return [{ role: "user", content: [{ type: "text", text: "(empty input)" }] }];
|
|
3178
3423
|
if (messages[0].role === "assistant") {
|
|
3179
|
-
return [
|
|
3424
|
+
return [
|
|
3425
|
+
{
|
|
3426
|
+
role: "user",
|
|
3427
|
+
content: [{ type: "text", text: "(conversation continued)" }]
|
|
3428
|
+
},
|
|
3429
|
+
...messages
|
|
3430
|
+
];
|
|
3180
3431
|
}
|
|
3181
3432
|
return messages;
|
|
3182
3433
|
}
|
|
@@ -3256,12 +3507,14 @@ function translateResponsesInput(input, instructions, npm) {
|
|
|
3256
3507
|
const { rawId } = splitToolUseId(item.call_id);
|
|
3257
3508
|
messages.push({
|
|
3258
3509
|
role: "tool",
|
|
3259
|
-
content: [
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3510
|
+
content: [
|
|
3511
|
+
{
|
|
3512
|
+
type: "tool-result",
|
|
3513
|
+
toolCallId: rawId,
|
|
3514
|
+
toolName: toolNames.get(rawId) ?? "unknown",
|
|
3515
|
+
output: { type: "text", value: serializeToolResultContent(item.output) }
|
|
3516
|
+
}
|
|
3517
|
+
]
|
|
3265
3518
|
});
|
|
3266
3519
|
} else if ("role" in item) {
|
|
3267
3520
|
const role = item.role === "assistant" ? "assistant" : "user";
|
|
@@ -3283,8 +3536,14 @@ var TOOL_SEARCH_FLAT = {
|
|
|
3283
3536
|
parameters: {
|
|
3284
3537
|
type: "object",
|
|
3285
3538
|
properties: {
|
|
3286
|
-
query: {
|
|
3287
|
-
|
|
3539
|
+
query: {
|
|
3540
|
+
type: "string",
|
|
3541
|
+
description: "Search query describing the tool or capability needed."
|
|
3542
|
+
},
|
|
3543
|
+
limit: {
|
|
3544
|
+
type: "number",
|
|
3545
|
+
description: "Maximum number of matching tools to return. Defaults to 8."
|
|
3546
|
+
}
|
|
3288
3547
|
},
|
|
3289
3548
|
required: ["query"],
|
|
3290
3549
|
additionalProperties: false
|
|
@@ -3367,7 +3626,12 @@ function translateResponsesTools(tools, options = {}) {
|
|
|
3367
3626
|
continue;
|
|
3368
3627
|
}
|
|
3369
3628
|
if (t.type === "custom") {
|
|
3370
|
-
addTool(t.name, {
|
|
3629
|
+
addTool(t.name, {
|
|
3630
|
+
type: "function",
|
|
3631
|
+
name: t.name,
|
|
3632
|
+
description: t.description ?? "",
|
|
3633
|
+
parameters: { type: "object", properties: {} }
|
|
3634
|
+
});
|
|
3371
3635
|
continue;
|
|
3372
3636
|
}
|
|
3373
3637
|
if (t.type !== "function" || !t.name) continue;
|
|
@@ -3469,7 +3733,13 @@ async function writeResponsesStream(fullStream, modelId, write, onDone, onProgre
|
|
|
3469
3733
|
emit("response.output_item.added", {
|
|
3470
3734
|
type: "response.output_item.added",
|
|
3471
3735
|
output_index: textOutputIndex,
|
|
3472
|
-
item: {
|
|
3736
|
+
item: {
|
|
3737
|
+
id: textItemId,
|
|
3738
|
+
type: "message",
|
|
3739
|
+
role: "assistant",
|
|
3740
|
+
status: "in_progress",
|
|
3741
|
+
content: []
|
|
3742
|
+
}
|
|
3473
3743
|
});
|
|
3474
3744
|
emit("response.content_part.added", {
|
|
3475
3745
|
type: "response.content_part.added",
|
|
@@ -3723,7 +3993,14 @@ async function writeResponsesStream(fullStream, modelId, write, onDone, onProgre
|
|
|
3723
3993
|
emit("response.output_item.added", {
|
|
3724
3994
|
type: "response.output_item.added",
|
|
3725
3995
|
output_index: idx,
|
|
3726
|
-
item: {
|
|
3996
|
+
item: {
|
|
3997
|
+
type: "function_call",
|
|
3998
|
+
id: itemId,
|
|
3999
|
+
call_id: callId,
|
|
4000
|
+
name: call.name,
|
|
4001
|
+
arguments: "",
|
|
4002
|
+
status: "in_progress"
|
|
4003
|
+
}
|
|
3727
4004
|
});
|
|
3728
4005
|
emit("response.function_call_arguments.done", {
|
|
3729
4006
|
type: "response.function_call_arguments.done",
|
|
@@ -3731,9 +4008,20 @@ async function writeResponsesStream(fullStream, modelId, write, onDone, onProgre
|
|
|
3731
4008
|
output_index: idx,
|
|
3732
4009
|
arguments: args
|
|
3733
4010
|
});
|
|
3734
|
-
const fcItem = {
|
|
4011
|
+
const fcItem = {
|
|
4012
|
+
type: "function_call",
|
|
4013
|
+
id: itemId,
|
|
4014
|
+
call_id: callId,
|
|
4015
|
+
name: call.name,
|
|
4016
|
+
arguments: args,
|
|
4017
|
+
status: "completed"
|
|
4018
|
+
};
|
|
3735
4019
|
const fcSplit = splitBackFunctionCall(fcItem, namespaceMap, customToolNames);
|
|
3736
|
-
emit("response.output_item.done", {
|
|
4020
|
+
emit("response.output_item.done", {
|
|
4021
|
+
type: "response.output_item.done",
|
|
4022
|
+
output_index: idx,
|
|
4023
|
+
item: fcSplit
|
|
4024
|
+
});
|
|
3737
4025
|
outputItems.push(fcSplit);
|
|
3738
4026
|
}
|
|
3739
4027
|
} else if (textItemId) {
|
|
@@ -3797,7 +4085,13 @@ async function writeResponsesStream(fullStream, modelId, write, onDone, onProgre
|
|
|
3797
4085
|
outputItems.push(fcItem);
|
|
3798
4086
|
}
|
|
3799
4087
|
if (outputItems.length === 0) {
|
|
3800
|
-
outputItems.push({
|
|
4088
|
+
outputItems.push({
|
|
4089
|
+
id: newItemId("msg"),
|
|
4090
|
+
type: "message",
|
|
4091
|
+
role: "assistant",
|
|
4092
|
+
status: "completed",
|
|
4093
|
+
content: [{ type: "output_text", text: "(conversation context was too large to summarize)" }]
|
|
4094
|
+
});
|
|
3801
4095
|
}
|
|
3802
4096
|
let finalOutput = outputItems;
|
|
3803
4097
|
if (isCompaction) {
|
|
@@ -3811,7 +4105,9 @@ async function writeResponsesStream(fullStream, modelId, write, onDone, onProgre
|
|
|
3811
4105
|
toolCallCount: toolStates.length,
|
|
3812
4106
|
toolNames: toolStates.map((t) => t.name),
|
|
3813
4107
|
loopDetected,
|
|
3814
|
-
dsmlToolCallsRecovered: dsml?.calls.length
|
|
4108
|
+
dsmlToolCallsRecovered: dsml?.calls.length,
|
|
4109
|
+
inputTokens: usage.input_tokens,
|
|
4110
|
+
outputTokens: usage.output_tokens
|
|
3815
4111
|
});
|
|
3816
4112
|
emit("response.completed", {
|
|
3817
4113
|
type: "response.completed",
|
|
@@ -3831,11 +4127,18 @@ async function streamResponsesResponse(model, params, modelId, write, onDone, on
|
|
|
3831
4127
|
const idleTimeoutMs = options?.idleTimeoutMs ?? STREAM_IDLE_TIMEOUT_MS;
|
|
3832
4128
|
const abort = new AbortController();
|
|
3833
4129
|
let idleTimer = setTimeout(
|
|
3834
|
-
() => abort.abort(
|
|
4130
|
+
() => abort.abort(
|
|
4131
|
+
new Error(`no data received from provider for ${Math.round(idleTimeoutMs / 1e3)}s`)
|
|
4132
|
+
),
|
|
3835
4133
|
idleTimeoutMs
|
|
3836
4134
|
);
|
|
3837
|
-
const result = streamText({
|
|
3838
|
-
|
|
4135
|
+
const result = streamText({
|
|
4136
|
+
model,
|
|
4137
|
+
...params,
|
|
4138
|
+
abortSignal: abort.signal,
|
|
4139
|
+
onError: () => {
|
|
4140
|
+
}
|
|
4141
|
+
});
|
|
3839
4142
|
Promise.resolve(result.text).catch(() => {
|
|
3840
4143
|
});
|
|
3841
4144
|
Promise.resolve(result.toolCalls).catch(() => {
|
|
@@ -3853,7 +4156,9 @@ async function streamResponsesResponse(model, params, modelId, write, onDone, on
|
|
|
3853
4156
|
for await (const part of result.fullStream) {
|
|
3854
4157
|
clearTimeout(idleTimer);
|
|
3855
4158
|
idleTimer = setTimeout(
|
|
3856
|
-
() => abort.abort(
|
|
4159
|
+
() => abort.abort(
|
|
4160
|
+
new Error(`no data received from provider for ${Math.round(idleTimeoutMs / 1e3)}s`)
|
|
4161
|
+
),
|
|
3857
4162
|
idleTimeoutMs
|
|
3858
4163
|
);
|
|
3859
4164
|
yield part;
|
|
@@ -3906,7 +4211,13 @@ async function generateResponsesResponse(model, params, modelId) {
|
|
|
3906
4211
|
arguments: typeof argsRaw === "string" ? argsRaw : JSON.stringify(argsRaw ?? {}),
|
|
3907
4212
|
status: "completed"
|
|
3908
4213
|
};
|
|
3909
|
-
output.push(
|
|
4214
|
+
output.push(
|
|
4215
|
+
splitBackFunctionCall(
|
|
4216
|
+
fcItem,
|
|
4217
|
+
params.namespaceMap,
|
|
4218
|
+
params.customToolNames
|
|
4219
|
+
)
|
|
4220
|
+
);
|
|
3910
4221
|
}
|
|
3911
4222
|
if (r.text !== null && r.text !== void 0) {
|
|
3912
4223
|
output.push({
|
|
@@ -3918,7 +4229,13 @@ async function generateResponsesResponse(model, params, modelId) {
|
|
|
3918
4229
|
});
|
|
3919
4230
|
}
|
|
3920
4231
|
if (output.length === 0) {
|
|
3921
|
-
output.push({
|
|
4232
|
+
output.push({
|
|
4233
|
+
id: newItemId("msg"),
|
|
4234
|
+
type: "message",
|
|
4235
|
+
role: "assistant",
|
|
4236
|
+
status: "completed",
|
|
4237
|
+
content: [{ type: "output_text", text: "(conversation context was too large to summarize)" }]
|
|
4238
|
+
});
|
|
3922
4239
|
}
|
|
3923
4240
|
const inputTokens = r.usage?.inputTokens ?? 0;
|
|
3924
4241
|
const outputTokens = r.usage?.outputTokens ?? 0;
|
|
@@ -3944,80 +4261,102 @@ function responsesErrorBody(modelId, message, statusCode = 401) {
|
|
|
3944
4261
|
created_at: Math.floor(Date.now() / 1e3),
|
|
3945
4262
|
status: "failed",
|
|
3946
4263
|
output: [],
|
|
3947
|
-
error: {
|
|
4264
|
+
error: {
|
|
4265
|
+
message,
|
|
4266
|
+
type: statusCode === 429 ? "rate_limit_error" : "api_error",
|
|
4267
|
+
code: String(statusCode)
|
|
4268
|
+
}
|
|
3948
4269
|
};
|
|
3949
4270
|
}
|
|
3950
4271
|
function writeResponsesErrorStream(modelId, message, write, statusCode = 401) {
|
|
3951
|
-
write(
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
4272
|
+
write(
|
|
4273
|
+
sseChunk("response.completed", {
|
|
4274
|
+
type: "response.completed",
|
|
4275
|
+
response: responsesErrorBody(modelId, message, statusCode)
|
|
4276
|
+
})
|
|
4277
|
+
);
|
|
3955
4278
|
}
|
|
3956
4279
|
function writeResponsesRateLimitStream(modelId, message, write) {
|
|
3957
4280
|
const responseId = newResponseId();
|
|
3958
4281
|
const itemId = newItemId("msg");
|
|
3959
4282
|
const createdAt = Math.floor(Date.now() / 1e3);
|
|
3960
4283
|
const content = [{ type: "output_text", text: message }];
|
|
3961
|
-
write(
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4284
|
+
write(
|
|
4285
|
+
sseChunk("response.created", {
|
|
4286
|
+
type: "response.created",
|
|
4287
|
+
response: {
|
|
4288
|
+
id: responseId,
|
|
4289
|
+
object: "response",
|
|
4290
|
+
model: modelId,
|
|
4291
|
+
created_at: createdAt,
|
|
4292
|
+
status: "in_progress",
|
|
4293
|
+
output: []
|
|
4294
|
+
}
|
|
4295
|
+
})
|
|
4296
|
+
);
|
|
4297
|
+
write(
|
|
4298
|
+
sseChunk("response.output_item.added", {
|
|
4299
|
+
type: "response.output_item.added",
|
|
4300
|
+
output_index: 0,
|
|
4301
|
+
item: { id: itemId, type: "message", role: "assistant", status: "in_progress", content: [] }
|
|
4302
|
+
})
|
|
4303
|
+
);
|
|
4304
|
+
write(
|
|
4305
|
+
sseChunk("response.content_part.added", {
|
|
4306
|
+
type: "response.content_part.added",
|
|
4307
|
+
item_id: itemId,
|
|
4308
|
+
output_index: 0,
|
|
4309
|
+
content_index: 0,
|
|
4310
|
+
part: { type: "output_text", text: "" }
|
|
4311
|
+
})
|
|
4312
|
+
);
|
|
4313
|
+
write(
|
|
4314
|
+
sseChunk("response.output_text.delta", {
|
|
4315
|
+
type: "response.output_text.delta",
|
|
4316
|
+
item_id: itemId,
|
|
4317
|
+
output_index: 0,
|
|
4318
|
+
content_index: 0,
|
|
4319
|
+
delta: message
|
|
4320
|
+
})
|
|
4321
|
+
);
|
|
4322
|
+
write(
|
|
4323
|
+
sseChunk("response.output_text.done", {
|
|
4324
|
+
type: "response.output_text.done",
|
|
4325
|
+
item_id: itemId,
|
|
4326
|
+
output_index: 0,
|
|
4327
|
+
content_index: 0,
|
|
4328
|
+
text: message
|
|
4329
|
+
})
|
|
4330
|
+
);
|
|
4331
|
+
write(
|
|
4332
|
+
sseChunk("response.content_part.done", {
|
|
4333
|
+
type: "response.content_part.done",
|
|
4334
|
+
item_id: itemId,
|
|
4335
|
+
output_index: 0,
|
|
4336
|
+
content_index: 0,
|
|
4337
|
+
part: { type: "output_text", text: message }
|
|
4338
|
+
})
|
|
4339
|
+
);
|
|
4340
|
+
write(
|
|
4341
|
+
sseChunk("response.output_item.done", {
|
|
4342
|
+
type: "response.output_item.done",
|
|
4343
|
+
output_index: 0,
|
|
4344
|
+
item: { id: itemId, type: "message", role: "assistant", status: "completed", content }
|
|
4345
|
+
})
|
|
4346
|
+
);
|
|
4347
|
+
write(
|
|
4348
|
+
sseChunk("response.completed", {
|
|
4349
|
+
type: "response.completed",
|
|
4350
|
+
response: {
|
|
4351
|
+
id: responseId,
|
|
4352
|
+
object: "response",
|
|
4353
|
+
model: modelId,
|
|
4354
|
+
created_at: createdAt,
|
|
4355
|
+
status: "completed",
|
|
4356
|
+
output: [{ id: itemId, type: "message", role: "assistant", status: "completed", content }]
|
|
4357
|
+
}
|
|
4358
|
+
})
|
|
4359
|
+
);
|
|
4021
4360
|
}
|
|
4022
4361
|
function responsesRateLimitBody(modelId, message) {
|
|
4023
4362
|
const itemId = newItemId("msg");
|
|
@@ -4108,7 +4447,9 @@ var COMPACTION_PROMPT_MARKER = "You are performing a CONTEXT CHECKPOINT COMPACTI
|
|
|
4108
4447
|
function inputItemText(content) {
|
|
4109
4448
|
if (typeof content === "string") return content;
|
|
4110
4449
|
if (!Array.isArray(content)) return "";
|
|
4111
|
-
return content.map(
|
|
4450
|
+
return content.map(
|
|
4451
|
+
(p18) => p18 && typeof p18 === "object" && typeof p18.text === "string" ? p18.text : ""
|
|
4452
|
+
).join("");
|
|
4112
4453
|
}
|
|
4113
4454
|
function isLikelyCodexCompactionRequest(body) {
|
|
4114
4455
|
if (!Array.isArray(body.input)) return false;
|
|
@@ -4159,9 +4500,7 @@ function codexRouteLookupIds(requestedModel) {
|
|
|
4159
4500
|
function findCodexProxyRoute(routes, requestedModel) {
|
|
4160
4501
|
const ids = codexRouteLookupIds(requestedModel);
|
|
4161
4502
|
for (const id of ids) {
|
|
4162
|
-
const route = routes.find(
|
|
4163
|
-
(r) => r.modelId === id || codexAppModelSlug(r.modelId) === id
|
|
4164
|
-
);
|
|
4503
|
+
const route = routes.find((r) => r.modelId === id || codexAppModelSlug(r.modelId) === id);
|
|
4165
4504
|
if (route) return route;
|
|
4166
4505
|
}
|
|
4167
4506
|
return void 0;
|
|
@@ -4177,21 +4516,42 @@ async function startCodexProxy(routes, options = {}) {
|
|
|
4177
4516
|
const opts = typeof options === "boolean" ? { debug: options } : options;
|
|
4178
4517
|
const debug = opts.debug ?? false;
|
|
4179
4518
|
const requireAuth = opts.requireAuth ?? true;
|
|
4519
|
+
const analyticsApp = opts.app ?? "codex";
|
|
4520
|
+
const routeByModelId = new Map(routes.map((r) => [r.modelId, r]));
|
|
4521
|
+
const trackUsage = (modelId, inputTokens, outputTokens) => {
|
|
4522
|
+
if (inputTokens <= 0 && outputTokens <= 0) return;
|
|
4523
|
+
try {
|
|
4524
|
+
const route = routeByModelId.get(modelId);
|
|
4525
|
+
recordUsage({
|
|
4526
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4527
|
+
modelId: route?.upstreamModelId ?? modelId,
|
|
4528
|
+
npm: route?.npm,
|
|
4529
|
+
providerId: route?.providerId,
|
|
4530
|
+
app: analyticsApp,
|
|
4531
|
+
inputTokens,
|
|
4532
|
+
outputTokens
|
|
4533
|
+
});
|
|
4534
|
+
} catch {
|
|
4535
|
+
}
|
|
4536
|
+
};
|
|
4180
4537
|
silenceSdkWarnings();
|
|
4181
4538
|
const models = /* @__PURE__ */ new Map();
|
|
4182
4539
|
for (const route of routes) {
|
|
4183
|
-
models.set(
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4540
|
+
models.set(
|
|
4541
|
+
route.modelId,
|
|
4542
|
+
await createLanguageModel({
|
|
4543
|
+
npm: route.npm,
|
|
4544
|
+
modelId: route.upstreamModelId,
|
|
4545
|
+
apiKey: route.apiKey,
|
|
4546
|
+
baseURL: route.baseURL,
|
|
4547
|
+
providerId: route.providerId ?? route.modelId,
|
|
4548
|
+
authType: route.authType,
|
|
4549
|
+
oauthAccountId: route.oauthAccountId,
|
|
4550
|
+
providerData: route.providerData,
|
|
4551
|
+
vertex: route.vertex,
|
|
4552
|
+
headers: route.headers
|
|
4553
|
+
})
|
|
4554
|
+
);
|
|
4195
4555
|
}
|
|
4196
4556
|
return new Promise((resolve, reject2) => {
|
|
4197
4557
|
const log17 = debug ? makeTraceLogger(getCodexProxyDebugLogPath()) : () => {
|
|
@@ -4203,7 +4563,9 @@ async function startCodexProxy(routes, options = {}) {
|
|
|
4203
4563
|
const server = createServer(async (req, res) => {
|
|
4204
4564
|
const url = req.url ?? "/";
|
|
4205
4565
|
if (debug) {
|
|
4206
|
-
log17(
|
|
4566
|
+
log17(
|
|
4567
|
+
`-> ${req.method} ${url} content-type=${req.headers["content-type"] ?? "(none)"} content-encoding=${req.headers["content-encoding"] ?? "(none)"} content-length=${req.headers["content-length"] ?? "(none)"}`
|
|
4568
|
+
);
|
|
4207
4569
|
}
|
|
4208
4570
|
if (!requireAuth && req.method === "POST") {
|
|
4209
4571
|
const origin = req.headers.origin;
|
|
@@ -4219,7 +4581,9 @@ async function startCodexProxy(routes, options = {}) {
|
|
|
4219
4581
|
}
|
|
4220
4582
|
};
|
|
4221
4583
|
if (!isValidLoopback(origin) || !isValidLoopback(referer)) {
|
|
4222
|
-
sendJson(res, 403, {
|
|
4584
|
+
sendJson(res, 403, {
|
|
4585
|
+
error: { message: "Forbidden origin", type: "invalid_request_error" }
|
|
4586
|
+
});
|
|
4223
4587
|
return;
|
|
4224
4588
|
}
|
|
4225
4589
|
}
|
|
@@ -4257,7 +4621,9 @@ async function startCodexProxy(routes, options = {}) {
|
|
|
4257
4621
|
const id = url.slice("/v1/models/".length);
|
|
4258
4622
|
const route = findCodexProxyRoute(routes, id);
|
|
4259
4623
|
if (!route) {
|
|
4260
|
-
sendJson(res, 404, {
|
|
4624
|
+
sendJson(res, 404, {
|
|
4625
|
+
error: { message: `Model not found: ${id}`, type: "invalid_request_error" }
|
|
4626
|
+
});
|
|
4261
4627
|
return;
|
|
4262
4628
|
}
|
|
4263
4629
|
sendJson(res, 200, {
|
|
@@ -4281,9 +4647,13 @@ async function startCodexProxy(routes, options = {}) {
|
|
|
4281
4647
|
rawBody = await readBody(req);
|
|
4282
4648
|
} catch (err) {
|
|
4283
4649
|
if (debug) {
|
|
4284
|
-
log17(
|
|
4650
|
+
log17(
|
|
4651
|
+
`Error: failed to read/decode request body on POST ${url}: ${formatUpstreamError(err)} content-encoding=${req.headers["content-encoding"] ?? "(none)"}`
|
|
4652
|
+
);
|
|
4285
4653
|
}
|
|
4286
|
-
sendJson(res, 400, {
|
|
4654
|
+
sendJson(res, 400, {
|
|
4655
|
+
error: { message: "Invalid request body", type: "invalid_request_error" }
|
|
4656
|
+
});
|
|
4287
4657
|
return;
|
|
4288
4658
|
}
|
|
4289
4659
|
let body;
|
|
@@ -4292,22 +4662,34 @@ async function startCodexProxy(routes, options = {}) {
|
|
|
4292
4662
|
} catch (err) {
|
|
4293
4663
|
if (debug) {
|
|
4294
4664
|
const headers = JSON.stringify(req.headers);
|
|
4295
|
-
log17(
|
|
4665
|
+
log17(
|
|
4666
|
+
`Error: Invalid JSON body on POST ${url}: ${formatUpstreamError(err)} headers=${headers} rawBody=${JSON.stringify(rawBody.slice(0, 2e3))}`
|
|
4667
|
+
);
|
|
4296
4668
|
}
|
|
4297
|
-
sendJson(res, 400, {
|
|
4669
|
+
sendJson(res, 400, {
|
|
4670
|
+
error: { message: "Invalid JSON body", type: "invalid_request_error" }
|
|
4671
|
+
});
|
|
4298
4672
|
return;
|
|
4299
4673
|
}
|
|
4300
4674
|
if (debug) {
|
|
4301
4675
|
const prevId = body.previous_response_id ?? null;
|
|
4302
4676
|
const inputItems = Array.isArray(body.input) ? body.input.length : typeof body.input === "string" ? 1 : 0;
|
|
4303
4677
|
const tools = Array.isArray(body.tools) ? body.tools : [];
|
|
4304
|
-
const toolNames = tools.map(
|
|
4305
|
-
|
|
4306
|
-
|
|
4678
|
+
const toolNames = tools.map(
|
|
4679
|
+
(t) => t && typeof t === "object" && "name" in t ? t.name : "?"
|
|
4680
|
+
).join(",");
|
|
4681
|
+
log17(
|
|
4682
|
+
`request: model=${String(body.model ?? "")} previous_response_id=${prevId ?? "(none)"} input_items=${inputItems} body_bytes=${rawBody.length} tools=[${toolNames || "none"}]`
|
|
4683
|
+
);
|
|
4684
|
+
const mcpTools = tools.filter(
|
|
4685
|
+
(t) => t && typeof t === "object" && "name" in t && String(t.name).startsWith("mcp__")
|
|
4686
|
+
);
|
|
4307
4687
|
for (const t of mcpTools) {
|
|
4308
4688
|
const mt = t;
|
|
4309
4689
|
const subTools = mt.type === "namespace" && Array.isArray(mt.tools) ? ` subTools=[${mt.tools.length}]` : "";
|
|
4310
|
-
log17(
|
|
4690
|
+
log17(
|
|
4691
|
+
` mcp-tool: name=${mt.name} type=${mt.type} desc=${JSON.stringify(String(mt.description ?? "")).slice(0, 120)}${subTools}`
|
|
4692
|
+
);
|
|
4311
4693
|
}
|
|
4312
4694
|
}
|
|
4313
4695
|
const modelId = String(body.model ?? "");
|
|
@@ -4322,41 +4704,55 @@ async function startCodexProxy(routes, options = {}) {
|
|
|
4322
4704
|
resolved = { route: fallbackRoute, languageModel: fallbackLm };
|
|
4323
4705
|
} else {
|
|
4324
4706
|
if (debug) {
|
|
4325
|
-
log17(
|
|
4707
|
+
log17(
|
|
4708
|
+
`resolveModel failed: requested="${modelId}" known=[${routes.map((r) => r.modelId).join(", ")}]`
|
|
4709
|
+
);
|
|
4326
4710
|
}
|
|
4327
|
-
sendJson(res, 404, {
|
|
4711
|
+
sendJson(res, 404, {
|
|
4712
|
+
error: { message: `Unknown model: ${modelId}`, type: "invalid_request_error" }
|
|
4713
|
+
});
|
|
4328
4714
|
return;
|
|
4329
4715
|
}
|
|
4330
4716
|
}
|
|
4331
4717
|
const { route, languageModel } = resolved;
|
|
4332
4718
|
try {
|
|
4333
|
-
let params = applyClaudeCodeOAuthIdentity(
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4719
|
+
let params = applyClaudeCodeOAuthIdentity(
|
|
4720
|
+
route,
|
|
4721
|
+
translateResponsesRequest(
|
|
4722
|
+
body,
|
|
4723
|
+
route.npm,
|
|
4724
|
+
{
|
|
4725
|
+
providerId: route.providerId,
|
|
4726
|
+
apiBaseUrl: route.baseURL,
|
|
4727
|
+
supportedParameters: route.supportedParameters,
|
|
4728
|
+
reasoning: route.reasoning,
|
|
4729
|
+
interleavedReasoningField: route.interleavedReasoningField,
|
|
4730
|
+
upstreamModelId: route.upstreamModelId
|
|
4731
|
+
},
|
|
4732
|
+
{ maxTools: maxToolsForNpm(route.npm) }
|
|
4733
|
+
)
|
|
4734
|
+
);
|
|
4346
4735
|
if (route.contextWindow && route.contextWindow > 0) {
|
|
4347
4736
|
const before = params.messages.length;
|
|
4348
4737
|
const estimatedChars = estimateCodexRequestChars(params);
|
|
4349
4738
|
const compaction = isLikelyCodexCompactionRequest(body);
|
|
4350
|
-
if (debug)
|
|
4739
|
+
if (debug)
|
|
4740
|
+
log17(
|
|
4741
|
+
`context check: model=${route.modelId} window=${route.contextWindow} chars=${estimatedChars} compaction=${compaction ? "yes" : "no"} messages=${before}`
|
|
4742
|
+
);
|
|
4351
4743
|
params = protectCodexCompactionParams(body, params, route.contextWindow);
|
|
4352
4744
|
params.isCompaction = compaction;
|
|
4353
4745
|
if (debug && params.messages.length < before) {
|
|
4354
|
-
log17(
|
|
4746
|
+
log17(
|
|
4747
|
+
`context trim: model=${route.modelId} window=${route.contextWindow} kept=${params.messages.length}/${before} messages`
|
|
4748
|
+
);
|
|
4355
4749
|
}
|
|
4356
4750
|
}
|
|
4357
4751
|
if (debug) {
|
|
4358
4752
|
const effort = body.reasoning?.effort;
|
|
4359
|
-
log17(
|
|
4753
|
+
log17(
|
|
4754
|
+
`model=${route.modelId} effort=${effort ?? "(none)"} providerOptions=${JSON.stringify(params.providerOptions)}`
|
|
4755
|
+
);
|
|
4360
4756
|
}
|
|
4361
4757
|
if (body.stream) {
|
|
4362
4758
|
res.writeHead(200, {
|
|
@@ -4366,16 +4762,28 @@ async function startCodexProxy(routes, options = {}) {
|
|
|
4366
4762
|
});
|
|
4367
4763
|
const write = (chunk) => res.write(chunk);
|
|
4368
4764
|
try {
|
|
4369
|
-
await streamResponsesResponse(
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4765
|
+
await streamResponsesResponse(
|
|
4766
|
+
languageModel,
|
|
4767
|
+
params,
|
|
4768
|
+
modelId,
|
|
4769
|
+
write,
|
|
4770
|
+
(summary) => {
|
|
4771
|
+
trackUsage(modelId, summary.inputTokens ?? 0, summary.outputTokens ?? 0);
|
|
4772
|
+
if (debug) {
|
|
4773
|
+
const failure = `${summary.aborted ? " aborted=yes" : ""}${summary.errorMessage ? ` error=${JSON.stringify(summary.errorMessage)}` : ""}`;
|
|
4774
|
+
log17(
|
|
4775
|
+
`response done: model=${route.modelId} reasoningChars=${summary.reasoningChars} textChars=${summary.textChars} toolCalls=${summary.toolCallCount} toolNames=[${summary.toolNames.join(",")}] loopDetected=${summary.loopDetected ?? "no"} dsmlRecovered=${summary.dsmlToolCallsRecovered ?? 0}${failure} reasoningPreview=${JSON.stringify(summary.reasoningPreview)}`
|
|
4776
|
+
);
|
|
4777
|
+
}
|
|
4778
|
+
},
|
|
4779
|
+
(progress) => {
|
|
4780
|
+
if (debug) {
|
|
4781
|
+
log17(
|
|
4782
|
+
`response progress: model=${route.modelId} elapsedMs=${progress.elapsedMs} reasoningChars=${progress.reasoningChars} textChars=${progress.textChars} toolCalls=${progress.toolCallCount} reasoningTail=${JSON.stringify(progress.reasoningTail)}`
|
|
4783
|
+
);
|
|
4784
|
+
}
|
|
4377
4785
|
}
|
|
4378
|
-
|
|
4786
|
+
);
|
|
4379
4787
|
} catch (err) {
|
|
4380
4788
|
const msg = formatUpstreamError(err);
|
|
4381
4789
|
const status = upstreamHttpStatus(err);
|
|
@@ -4390,6 +4798,8 @@ async function startCodexProxy(routes, options = {}) {
|
|
|
4390
4798
|
} else {
|
|
4391
4799
|
try {
|
|
4392
4800
|
const response = await generateResponsesResponse(languageModel, params, modelId);
|
|
4801
|
+
const u = response["usage"];
|
|
4802
|
+
trackUsage(modelId, u?.input_tokens ?? 0, u?.output_tokens ?? 0);
|
|
4393
4803
|
sendJson(res, 200, response);
|
|
4394
4804
|
} catch (err) {
|
|
4395
4805
|
const msg = formatUpstreamError(err);
|
|
@@ -4475,7 +4885,9 @@ async function startCodexProxy(routes, options = {}) {
|
|
|
4475
4885
|
if (requireAuth) {
|
|
4476
4886
|
const inboundKey = extractApiKey(req);
|
|
4477
4887
|
if (!inboundKey || inboundKey !== PROXY_PLACEHOLDER_KEY) {
|
|
4478
|
-
socket.write(
|
|
4888
|
+
socket.write(
|
|
4889
|
+
"HTTP/1.1 401 Unauthorized\r\nContent-Length: 0\r\nConnection: close\r\n\r\n"
|
|
4890
|
+
);
|
|
4479
4891
|
socket.destroy();
|
|
4480
4892
|
return;
|
|
4481
4893
|
}
|
|
@@ -4522,11 +4934,16 @@ Sec-WebSocket-Accept: ${wsAcceptKey(clientKey)}\r
|
|
|
4522
4934
|
try {
|
|
4523
4935
|
body = JSON.parse(frame.text);
|
|
4524
4936
|
} catch {
|
|
4525
|
-
if (debug)
|
|
4526
|
-
|
|
4937
|
+
if (debug)
|
|
4938
|
+
log17(
|
|
4939
|
+
`WS Error: Invalid JSON body: rawBody=${JSON.stringify(frame.text.slice(0, 2e3))}`
|
|
4940
|
+
);
|
|
4941
|
+
sendWsEvent(
|
|
4942
|
+
`event: error
|
|
4527
4943
|
data: ${JSON.stringify({ error: { message: "Invalid JSON", type: "invalid_request_error" } })}
|
|
4528
4944
|
|
|
4529
|
-
`
|
|
4945
|
+
`
|
|
4946
|
+
);
|
|
4530
4947
|
closeSocket();
|
|
4531
4948
|
return;
|
|
4532
4949
|
}
|
|
@@ -4534,8 +4951,12 @@ data: ${JSON.stringify({ error: { message: "Invalid JSON", type: "invalid_reques
|
|
|
4534
4951
|
const prevId = body.previous_response_id ?? null;
|
|
4535
4952
|
const inputItems = Array.isArray(body.input) ? body.input.length : typeof body.input === "string" ? 1 : 0;
|
|
4536
4953
|
const tools = Array.isArray(body.tools) ? body.tools : [];
|
|
4537
|
-
const toolNames = tools.map(
|
|
4538
|
-
|
|
4954
|
+
const toolNames = tools.map(
|
|
4955
|
+
(t) => t && typeof t === "object" && "name" in t ? t.name : "?"
|
|
4956
|
+
).join(",");
|
|
4957
|
+
log17(
|
|
4958
|
+
`WS request: model=${String(body.model ?? "")} previous_response_id=${prevId ?? "(none)"} input_items=${inputItems} body_bytes=${frame.text.length} tools=[${toolNames || "none"}]`
|
|
4959
|
+
);
|
|
4539
4960
|
}
|
|
4540
4961
|
const modelId = String(body.model ?? "");
|
|
4541
4962
|
let resolved = resolveModel(routes, models, modelId);
|
|
@@ -4546,55 +4967,82 @@ data: ${JSON.stringify({ error: { message: "Invalid JSON", type: "invalid_reques
|
|
|
4546
4967
|
if (debug) log17(`WS resolveModel fallback: requested="${modelId}" \u2192 ${fb.modelId}`);
|
|
4547
4968
|
resolved = { route: fb, languageModel: fbLm };
|
|
4548
4969
|
} else {
|
|
4549
|
-
if (debug)
|
|
4550
|
-
|
|
4970
|
+
if (debug)
|
|
4971
|
+
log17(
|
|
4972
|
+
`WS resolveModel failed: requested="${modelId}" known=[${routes.map((r) => r.modelId).join(", ")}]`
|
|
4973
|
+
);
|
|
4974
|
+
sendWsEvent(
|
|
4975
|
+
`event: error
|
|
4551
4976
|
data: ${JSON.stringify({ error: { message: `Unknown model: ${modelId}` } })}
|
|
4552
4977
|
|
|
4553
|
-
`
|
|
4978
|
+
`
|
|
4979
|
+
);
|
|
4554
4980
|
closeSocket();
|
|
4555
4981
|
return;
|
|
4556
4982
|
}
|
|
4557
4983
|
}
|
|
4558
4984
|
const { route, languageModel } = resolved;
|
|
4559
4985
|
try {
|
|
4560
|
-
let params = applyClaudeCodeOAuthIdentity(
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4986
|
+
let params = applyClaudeCodeOAuthIdentity(
|
|
4987
|
+
route,
|
|
4988
|
+
translateResponsesRequest(
|
|
4989
|
+
body,
|
|
4990
|
+
route.npm,
|
|
4991
|
+
{
|
|
4992
|
+
providerId: route.providerId,
|
|
4993
|
+
apiBaseUrl: route.baseURL,
|
|
4994
|
+
supportedParameters: route.supportedParameters,
|
|
4995
|
+
reasoning: route.reasoning,
|
|
4996
|
+
interleavedReasoningField: route.interleavedReasoningField,
|
|
4997
|
+
upstreamModelId: route.upstreamModelId
|
|
4998
|
+
},
|
|
4999
|
+
{ maxTools: maxToolsForNpm(route.npm) }
|
|
5000
|
+
)
|
|
5001
|
+
);
|
|
4573
5002
|
if (route.contextWindow && route.contextWindow > 0) {
|
|
4574
5003
|
const before = params.messages.length;
|
|
4575
5004
|
const estimatedChars = estimateCodexRequestChars(params);
|
|
4576
5005
|
const compaction = isLikelyCodexCompactionRequest(body);
|
|
4577
|
-
if (debug)
|
|
5006
|
+
if (debug)
|
|
5007
|
+
log17(
|
|
5008
|
+
`WS context check: model=${route.modelId} window=${route.contextWindow} chars=${estimatedChars} compaction=${compaction ? "yes" : "no"} messages=${before} tools=${params.tools ? Object.keys(params.tools).length : 0}`
|
|
5009
|
+
);
|
|
4578
5010
|
params = protectCodexCompactionParams(body, params, route.contextWindow);
|
|
4579
5011
|
params.isCompaction = compaction;
|
|
4580
5012
|
if (debug && params.messages.length < before) {
|
|
4581
|
-
log17(
|
|
5013
|
+
log17(
|
|
5014
|
+
`WS context trim: model=${route.modelId} window=${route.contextWindow} kept=${params.messages.length}/${before} messages tools=${params.tools ? Object.keys(params.tools).length : 0}`
|
|
5015
|
+
);
|
|
4582
5016
|
}
|
|
4583
5017
|
}
|
|
4584
5018
|
if (debug) {
|
|
4585
5019
|
const effort = body.reasoning?.effort;
|
|
4586
|
-
log17(
|
|
5020
|
+
log17(
|
|
5021
|
+
`WS model=${route.modelId} effort=${effort ?? "(none)"} providerOptions=${JSON.stringify(params.providerOptions)}`
|
|
5022
|
+
);
|
|
4587
5023
|
}
|
|
4588
|
-
await streamResponsesResponse(
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
5024
|
+
await streamResponsesResponse(
|
|
5025
|
+
languageModel,
|
|
5026
|
+
params,
|
|
5027
|
+
modelId,
|
|
5028
|
+
sendWsEvent,
|
|
5029
|
+
(summary) => {
|
|
5030
|
+
trackUsage(modelId, summary.inputTokens ?? 0, summary.outputTokens ?? 0);
|
|
5031
|
+
if (debug) {
|
|
5032
|
+
const failure = `${summary.aborted ? " aborted=yes" : ""}${summary.errorMessage ? ` error=${JSON.stringify(summary.errorMessage)}` : ""}`;
|
|
5033
|
+
log17(
|
|
5034
|
+
`WS response done: model=${route.modelId} reasoningChars=${summary.reasoningChars} textChars=${summary.textChars} toolCalls=${summary.toolCallCount} toolNames=[${summary.toolNames.join(",")}] loopDetected=${summary.loopDetected ?? "no"} dsmlRecovered=${summary.dsmlToolCallsRecovered ?? 0}${failure} reasoningPreview=${JSON.stringify(summary.reasoningPreview)}`
|
|
5035
|
+
);
|
|
5036
|
+
}
|
|
5037
|
+
},
|
|
5038
|
+
(progress) => {
|
|
5039
|
+
if (debug) {
|
|
5040
|
+
log17(
|
|
5041
|
+
`WS response progress: model=${route.modelId} elapsedMs=${progress.elapsedMs} reasoningChars=${progress.reasoningChars} textChars=${progress.textChars} toolCalls=${progress.toolCallCount} reasoningTail=${JSON.stringify(progress.reasoningTail)}`
|
|
5042
|
+
);
|
|
5043
|
+
}
|
|
4596
5044
|
}
|
|
4597
|
-
|
|
5045
|
+
);
|
|
4598
5046
|
} catch (err) {
|
|
4599
5047
|
const msg = formatUpstreamError(err);
|
|
4600
5048
|
const status = upstreamHttpStatus(err);
|
|
@@ -4706,7 +5154,6 @@ function codexProviderEnvKey(providerId) {
|
|
|
4706
5154
|
}
|
|
4707
5155
|
|
|
4708
5156
|
// src/apps/codex/session.ts
|
|
4709
|
-
init_paths();
|
|
4710
5157
|
import {
|
|
4711
5158
|
copyFileSync,
|
|
4712
5159
|
existsSync as existsSync3,
|
|
@@ -4912,7 +5359,6 @@ import { execFileSync, execSync, spawn } from "child_process";
|
|
|
4912
5359
|
import { existsSync as existsSync4 } from "fs";
|
|
4913
5360
|
import { homedir as homedir4 } from "os";
|
|
4914
5361
|
import { join as join4 } from "path";
|
|
4915
|
-
init_config();
|
|
4916
5362
|
var isWindows = process.platform === "win32";
|
|
4917
5363
|
var CODEX_CI_ENV_VARS = [
|
|
4918
5364
|
"CI",
|
|
@@ -5029,7 +5475,9 @@ import pc6 from "picocolors";
|
|
|
5029
5475
|
import * as p7 from "@clack/prompts";
|
|
5030
5476
|
async function pickCodexProvider(providers, prefs, hasFavorites = false, initialProviderId, agentLabel = "Codex") {
|
|
5031
5477
|
if (providers.length === 0 && !hasFavorites) return null;
|
|
5032
|
-
const options = providers.map(
|
|
5478
|
+
const options = providers.map(
|
|
5479
|
+
(lp) => providerSelectOption(lp)
|
|
5480
|
+
);
|
|
5033
5481
|
if (hasFavorites) {
|
|
5034
5482
|
options.unshift({
|
|
5035
5483
|
value: "__favorites__",
|
|
@@ -5037,7 +5485,13 @@ async function pickCodexProvider(providers, prefs, hasFavorites = false, initial
|
|
|
5037
5485
|
hint: `${prefs.favoriteModels?.length ?? 0} saved favorites`
|
|
5038
5486
|
});
|
|
5039
5487
|
}
|
|
5040
|
-
const initial = initialProviderId && options.some((o) => o.value === initialProviderId) ? initialProviderId :
|
|
5488
|
+
const initial = initialProviderId && options.some((o) => o.value === initialProviderId) ? initialProviderId : (
|
|
5489
|
+
// When favorites exist, default to the Favorites Catalog so the gateway
|
|
5490
|
+
// exposes ALL saved models to the client picker — not just the last
|
|
5491
|
+
// single-provider selection (remembered via lastCodexProvider), which
|
|
5492
|
+
// would otherwise collapse the catalog to a single model.
|
|
5493
|
+
hasFavorites ? "__favorites__" : prefs.lastCodexProvider && options.some((o) => o.value === prefs.lastCodexProvider) ? prefs.lastCodexProvider : options[0].value
|
|
5494
|
+
);
|
|
5041
5495
|
const chosen = await p7.select({
|
|
5042
5496
|
message: `Which provider for ${agentLabel}?`,
|
|
5043
5497
|
options,
|
|
@@ -5116,7 +5570,8 @@ function rejectManagedFlags(codexArgs) {
|
|
|
5116
5570
|
if (takesValue.has(arg)) i++;
|
|
5117
5571
|
continue;
|
|
5118
5572
|
}
|
|
5119
|
-
if (arg.startsWith("--profile=") || arg.startsWith("--model=") || arg.startsWith("--provider=") || arg.startsWith("-m="))
|
|
5573
|
+
if (arg.startsWith("--profile=") || arg.startsWith("--model=") || arg.startsWith("--provider=") || arg.startsWith("-m="))
|
|
5574
|
+
continue;
|
|
5120
5575
|
out.push(arg);
|
|
5121
5576
|
}
|
|
5122
5577
|
return out;
|
|
@@ -5227,14 +5682,15 @@ async function resolveFavorite(fav, ctx) {
|
|
|
5227
5682
|
apiKey: await resolveLocalProviderApiKey(found.provider) ?? "",
|
|
5228
5683
|
authType: found.provider.authType,
|
|
5229
5684
|
oauthAccountId: found.provider.oauthAccountId,
|
|
5230
|
-
providerData: found.provider.providerData
|
|
5685
|
+
providerData: found.provider.providerData,
|
|
5686
|
+
headers: found.provider.headers
|
|
5231
5687
|
};
|
|
5232
5688
|
}
|
|
5233
5689
|
return void 0;
|
|
5234
5690
|
}
|
|
5235
5691
|
async function buildFavoritesList(starting, favorites, ctx, max = 20, options = {}) {
|
|
5236
|
-
const seen = /* @__PURE__ */ new Set();
|
|
5237
5692
|
const out = [];
|
|
5693
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5238
5694
|
if (starting) {
|
|
5239
5695
|
seen.add(`${starting.providerId}::${starting.model.id}`);
|
|
5240
5696
|
out.push(starting);
|
|
@@ -5362,11 +5818,7 @@ async function resolveCodexFavorites(activeProvider, selectedModel, compatible,
|
|
|
5362
5818
|
{ providerId: activeProvider.id, modelId: selectedModel.id },
|
|
5363
5819
|
ctx
|
|
5364
5820
|
);
|
|
5365
|
-
const { resolved, droppedFavorites } = await buildFavoritesList(
|
|
5366
|
-
startingResolved,
|
|
5367
|
-
favorites,
|
|
5368
|
-
ctx
|
|
5369
|
-
);
|
|
5821
|
+
const { resolved, droppedFavorites } = await buildFavoritesList(startingResolved, favorites, ctx);
|
|
5370
5822
|
if (droppedFavorites.length > 0) {
|
|
5371
5823
|
p8.log.warn(
|
|
5372
5824
|
`Skipped ${droppedFavorites.length} stale/unauthorized favorite(s): ${droppedFavorites.map((f) => `${f.providerId}:${f.modelId}`).join(", ")}`
|
|
@@ -5403,10 +5855,7 @@ function buildCloudCodeProxyRoute(model, apiKey, providerData) {
|
|
|
5403
5855
|
};
|
|
5404
5856
|
}
|
|
5405
5857
|
function buildOAuthAnthropicProxyRoute(model, apiKey, providerId, providerData) {
|
|
5406
|
-
const aliasId = claudeCodeClientModelId(
|
|
5407
|
-
aliasModelId(model.id, providerId),
|
|
5408
|
-
model.contextWindow
|
|
5409
|
-
);
|
|
5858
|
+
const aliasId = claudeCodeClientModelId(aliasModelId(model.id, providerId), model.contextWindow);
|
|
5410
5859
|
return {
|
|
5411
5860
|
aliasId,
|
|
5412
5861
|
realModelId: model.upstreamModelId || model.id,
|
|
@@ -5422,15 +5871,28 @@ function buildOAuthAnthropicProxyRoute(model, apiKey, providerId, providerData)
|
|
|
5422
5871
|
refreshToken: () => resolveProviderCredential(providerId, oauthAuthRef(providerId))
|
|
5423
5872
|
};
|
|
5424
5873
|
}
|
|
5425
|
-
async function partitionAndStartCloudCodeBackend(items, toOutput, trace) {
|
|
5874
|
+
async function partitionAndStartCloudCodeBackend(items, toOutput, trace, app) {
|
|
5426
5875
|
if (items.length === 0) return { backendItems: [], backend: null };
|
|
5427
5876
|
const proxyRoutes = items.map(
|
|
5428
|
-
(item) => item.model.modelFormat === "cloud-code" ? buildCloudCodeProxyRoute(item.model, item.apiKey, item.providerData ?? {}) : buildOAuthAnthropicProxyRoute(
|
|
5877
|
+
(item) => item.model.modelFormat === "cloud-code" ? buildCloudCodeProxyRoute(item.model, item.apiKey, item.providerData ?? {}) : buildOAuthAnthropicProxyRoute(
|
|
5878
|
+
item.model,
|
|
5879
|
+
item.apiKey,
|
|
5880
|
+
item.providerId,
|
|
5881
|
+
item.providerData ?? {}
|
|
5882
|
+
)
|
|
5883
|
+
);
|
|
5884
|
+
if (app) for (const route of proxyRoutes) route.app = app;
|
|
5885
|
+
const backend = await startCloudCodeCatalogBackend(
|
|
5886
|
+
proxyRoutes,
|
|
5887
|
+
proxyRoutes[0].aliasId,
|
|
5888
|
+
trace,
|
|
5889
|
+
app
|
|
5429
5890
|
);
|
|
5430
|
-
const backend = await startCloudCodeCatalogBackend(proxyRoutes, proxyRoutes[0].aliasId, trace);
|
|
5431
5891
|
return {
|
|
5432
5892
|
backend,
|
|
5433
|
-
backendItems: proxyRoutes.map(
|
|
5893
|
+
backendItems: proxyRoutes.map(
|
|
5894
|
+
(proxyRoute, index) => toOutput(proxyRoute, backend, items[index])
|
|
5895
|
+
)
|
|
5434
5896
|
};
|
|
5435
5897
|
}
|
|
5436
5898
|
async function buildSingleModelCloudCodeRoute(model, apiKey, providerId, providerData, trace) {
|
|
@@ -5438,8 +5900,8 @@ async function buildSingleModelCloudCodeRoute(model, apiKey, providerId, provide
|
|
|
5438
5900
|
const backend = await startCloudCodeCatalogBackend([proxyRoute], proxyRoute.aliasId, trace);
|
|
5439
5901
|
return { proxyRoute, backend };
|
|
5440
5902
|
}
|
|
5441
|
-
async function startCloudCodeCatalogBackend(routes, startingAliasId, trace) {
|
|
5442
|
-
const handle = await startProxyCatalog(routes, startingAliasId, trace ?? false);
|
|
5903
|
+
async function startCloudCodeCatalogBackend(routes, startingAliasId, trace, app) {
|
|
5904
|
+
const handle = await startProxyCatalog(routes, startingAliasId, trace ?? false, { app });
|
|
5443
5905
|
return { port: handle.port, token: handle.token, handle };
|
|
5444
5906
|
}
|
|
5445
5907
|
|
|
@@ -5513,12 +5975,15 @@ async function writeLaunchArtifacts(route, selectedModel, providerName, proxyPor
|
|
|
5513
5975
|
reasoning: route.reasoning,
|
|
5514
5976
|
interleavedReasoningField: route.interleavedReasoningField
|
|
5515
5977
|
});
|
|
5516
|
-
writeOverlayFile(
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5978
|
+
writeOverlayFile(
|
|
5979
|
+
profilePath,
|
|
5980
|
+
buildCodexProfileToml({
|
|
5981
|
+
route,
|
|
5982
|
+
proxyPort,
|
|
5983
|
+
catalogPath,
|
|
5984
|
+
modelReasoningEffort: caps.defaultLevel || void 0
|
|
5985
|
+
})
|
|
5986
|
+
);
|
|
5522
5987
|
return { profilePath, catalogPath };
|
|
5523
5988
|
}
|
|
5524
5989
|
async function writeFavoritesLaunchArtifacts(resolved, starting, proxyPort) {
|
|
@@ -5535,12 +6000,38 @@ async function writeFavoritesLaunchArtifacts(resolved, starting, proxyPort) {
|
|
|
5535
6000
|
upstreamModelId: model.upstreamModelId || model.id,
|
|
5536
6001
|
apiKey: ""
|
|
5537
6002
|
};
|
|
5538
|
-
writeOverlayFile(
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
6003
|
+
writeOverlayFile(
|
|
6004
|
+
profilePath,
|
|
6005
|
+
buildCodexProfileToml({
|
|
6006
|
+
route: dummyRoute,
|
|
6007
|
+
proxyPort,
|
|
6008
|
+
catalogPath,
|
|
6009
|
+
modelReasoningEffort: defaultReasoningEffortForFavorite(starting)
|
|
6010
|
+
})
|
|
6011
|
+
);
|
|
6012
|
+
return { profilePath, catalogPath };
|
|
6013
|
+
}
|
|
6014
|
+
async function writeAllModelsLaunchArtifacts(activeProvider, selectedModel, routable, proxyPort) {
|
|
6015
|
+
const catalogPath = getCatalogOutputPath(activeProvider.id);
|
|
6016
|
+
const catalog = buildCatalogFile(routable, activeProvider.name);
|
|
6017
|
+
writeOverlayFile(catalogPath, serializeCatalog(catalog));
|
|
6018
|
+
const profilePath = getProfileOutputPath();
|
|
6019
|
+
const dummyRoute = {
|
|
6020
|
+
tier: "proxy",
|
|
6021
|
+
modelId: selectedModel.id,
|
|
6022
|
+
providerId: "anygate-proxy",
|
|
6023
|
+
npm: selectedModel.npm ?? "@ai-sdk/openai-compatible",
|
|
6024
|
+
upstreamModelId: selectedModel.upstreamModelId || selectedModel.id,
|
|
6025
|
+
apiKey: ""
|
|
6026
|
+
};
|
|
6027
|
+
writeOverlayFile(
|
|
6028
|
+
profilePath,
|
|
6029
|
+
buildCodexProfileToml({
|
|
6030
|
+
route: dummyRoute,
|
|
6031
|
+
proxyPort,
|
|
6032
|
+
catalogPath
|
|
6033
|
+
})
|
|
6034
|
+
);
|
|
5544
6035
|
return { profilePath, catalogPath };
|
|
5545
6036
|
}
|
|
5546
6037
|
function printCodexCleanupReminder(hadProxy) {
|
|
@@ -5618,19 +6109,24 @@ async function runCodexVertexLaunch(passthroughArgs, trace) {
|
|
|
5618
6109
|
const debugLogPath = getCodexProxyDebugLogPath();
|
|
5619
6110
|
let proxyHandle = null;
|
|
5620
6111
|
try {
|
|
5621
|
-
p9.log.info(
|
|
6112
|
+
p9.log.info(
|
|
6113
|
+
`Vertex AI \xB7 ${selectedEntry.display_name} \u2014 project: ${config.project} / location: ${config.location}`
|
|
6114
|
+
);
|
|
5622
6115
|
proxyHandle = await startCodexProxy(allRoutes, { debug: trace });
|
|
5623
6116
|
const proxyPort = proxyHandle.port;
|
|
5624
6117
|
const catalogPath = getCatalogOutputPath("vertex");
|
|
5625
6118
|
writeOverlayFile(catalogPath, serializeCatalog(buildCatalogFile(allModels, "Vertex AI")));
|
|
5626
6119
|
const profilePath = getProfileOutputPath();
|
|
5627
6120
|
const caps = getReasoningCapabilities(VERTEX_ANTHROPIC_NPM, selectedEntry.id);
|
|
5628
|
-
writeOverlayFile(
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
6121
|
+
writeOverlayFile(
|
|
6122
|
+
profilePath,
|
|
6123
|
+
buildCodexProfileToml({
|
|
6124
|
+
route: startingRoute,
|
|
6125
|
+
proxyPort,
|
|
6126
|
+
catalogPath,
|
|
6127
|
+
modelReasoningEffort: caps.defaultLevel || void 0
|
|
6128
|
+
})
|
|
6129
|
+
);
|
|
5634
6130
|
writeSessionLock({
|
|
5635
6131
|
pid: process.pid,
|
|
5636
6132
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -5692,7 +6188,9 @@ async function runCodexCommand(codexArgs, trace = false, launch = {}) {
|
|
|
5692
6188
|
console.error(pc8.red("anygate codex --vertex requires an interactive terminal."));
|
|
5693
6189
|
return 1;
|
|
5694
6190
|
}
|
|
5695
|
-
console.error(
|
|
6191
|
+
console.error(
|
|
6192
|
+
pc8.yellow(`Another anygate codex session may be running (pid ${sessionCheck.lock.pid}).`)
|
|
6193
|
+
);
|
|
5696
6194
|
console.error("Run anygate codex --restore to clean up, or wait for it to finish.");
|
|
5697
6195
|
return 1;
|
|
5698
6196
|
}
|
|
@@ -5700,8 +6198,9 @@ async function runCodexCommand(codexArgs, trace = false, launch = {}) {
|
|
|
5700
6198
|
return runCodexVertexLaunch(passthroughArgs, trace);
|
|
5701
6199
|
}
|
|
5702
6200
|
const prefs = loadPreferences();
|
|
6201
|
+
const launchAllModels = Boolean(launch.launchAllModels || launch.launchModel === "All");
|
|
5703
6202
|
const launchPlan = planLaunchWizard({
|
|
5704
|
-
explicit: { providerId: launch.launchProvider, modelId: launch.launchModel },
|
|
6203
|
+
explicit: launchAllModels ? { providerId: launch.launchProvider, allModels: true } : { providerId: launch.launchProvider, modelId: launch.launchModel },
|
|
5705
6204
|
childArgs: passthroughArgs,
|
|
5706
6205
|
agent: "codex",
|
|
5707
6206
|
prefs
|
|
@@ -5717,12 +6216,16 @@ Error: ${launchPlan.error}
|
|
|
5717
6216
|
const sessionCheck = checkSessionLock(isTty || allowNonTty);
|
|
5718
6217
|
if (!sessionCheck.ok) {
|
|
5719
6218
|
if (sessionCheck.reason === "non_tty") {
|
|
5720
|
-
console.error(
|
|
5721
|
-
|
|
5722
|
-
|
|
6219
|
+
console.error(
|
|
6220
|
+
pc8.red(
|
|
6221
|
+
"anygate codex requires an interactive terminal (or use --provider and --model for non-interactive launch)."
|
|
6222
|
+
)
|
|
6223
|
+
);
|
|
5723
6224
|
return 1;
|
|
5724
6225
|
}
|
|
5725
|
-
console.error(
|
|
6226
|
+
console.error(
|
|
6227
|
+
pc8.yellow(`Another anygate codex session may be running (pid ${sessionCheck.lock.pid}).`)
|
|
6228
|
+
);
|
|
5726
6229
|
console.error("Run anygate codex --restore to clean up, or wait for it to finish.");
|
|
5727
6230
|
return 1;
|
|
5728
6231
|
}
|
|
@@ -5762,13 +6265,23 @@ Error: ${launchPlan.error}
|
|
|
5762
6265
|
if (compatible.length === 0) {
|
|
5763
6266
|
if (!configOnly) {
|
|
5764
6267
|
p9.log.warn("No Codex-compatible providers in your registry.");
|
|
5765
|
-
p9.log.info(
|
|
6268
|
+
p9.log.info(
|
|
6269
|
+
"Add a provider with anygate providers add, or sign in with anygate providers auth openai."
|
|
6270
|
+
);
|
|
5766
6271
|
}
|
|
5767
6272
|
return 0;
|
|
5768
6273
|
}
|
|
5769
6274
|
const favorites = prefs.favoriteModels ?? [];
|
|
5770
|
-
const
|
|
5771
|
-
|
|
6275
|
+
const hasFavorites = favorites.length > 0;
|
|
6276
|
+
let catalogMode = false;
|
|
6277
|
+
if (launchPlan.skip && launchPlan.target && launchPlan.target.allModels) {
|
|
6278
|
+
catalogMode = "provider-all";
|
|
6279
|
+
}
|
|
6280
|
+
let favoritesActive = false;
|
|
6281
|
+
if (configOnly && hasFavorites && !launchPlan.skip) {
|
|
6282
|
+
favoritesActive = true;
|
|
6283
|
+
}
|
|
6284
|
+
if (hasFavorites && !configOnly && !launchPlan.skip) {
|
|
5772
6285
|
p9.log.info(
|
|
5773
6286
|
`Favorites mode active \u2014 Codex picker will show ${favorites.length + 1} models (1 starting + ${favorites.length} favorites).`
|
|
5774
6287
|
);
|
|
@@ -5777,22 +6290,41 @@ Error: ${launchPlan.error}
|
|
|
5777
6290
|
let activeProvider = compatible.find((lp) => lp.id === prefs.lastCodexProvider) ?? compatible[0];
|
|
5778
6291
|
let selectedModel = activeProvider.models.find((m) => m.id === prefs.lastCodexModel) ?? activeProvider.models[0];
|
|
5779
6292
|
if (!configOnly && launchPlan.skip && launchPlan.target) {
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
`Provider
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
6293
|
+
if (launchPlan.target.allModels) {
|
|
6294
|
+
const foundProvider = compatible.find((lp) => lp.id === launchPlan.target.providerId);
|
|
6295
|
+
if (!foundProvider) {
|
|
6296
|
+
p9.log.error(`Provider not found: ${launchPlan.target.providerId}`);
|
|
6297
|
+
return 1;
|
|
6298
|
+
}
|
|
6299
|
+
activeProvider = foundProvider;
|
|
6300
|
+
selectedModel = activeProvider.models[0];
|
|
6301
|
+
catalogMode = "provider-all";
|
|
6302
|
+
if (!agentStdout) {
|
|
6303
|
+
p9.log.step(`Using all ${activeProvider.models.length} models from ${activeProvider.name}`);
|
|
6304
|
+
}
|
|
6305
|
+
} else {
|
|
6306
|
+
const resolved = findProviderAndModel(compatible, launchPlan.target);
|
|
6307
|
+
if (!resolved) {
|
|
6308
|
+
p9.log.error(
|
|
6309
|
+
`Provider/model not found: ${launchPlan.target.providerId} / ${launchPlan.target.modelId}`
|
|
6310
|
+
);
|
|
6311
|
+
return 1;
|
|
6312
|
+
}
|
|
6313
|
+
activeProvider = resolved.provider;
|
|
6314
|
+
selectedModel = resolved.model;
|
|
6315
|
+
if (!agentStdout) {
|
|
6316
|
+
p9.log.step(`Using ${selectedModel.name || selectedModel.id} (${activeProvider.name})`);
|
|
6317
|
+
}
|
|
5791
6318
|
}
|
|
5792
6319
|
} else if (!configOnly) {
|
|
5793
6320
|
let currentInitialProvider = prefs.lastCodexProvider && compatible.some((o) => o.id === prefs.lastCodexProvider) ? prefs.lastCodexProvider : compatible[0].id;
|
|
5794
6321
|
while (true) {
|
|
5795
|
-
const pickedProvider = await pickCodexProvider(
|
|
6322
|
+
const pickedProvider = await pickCodexProvider(
|
|
6323
|
+
compatible,
|
|
6324
|
+
prefs,
|
|
6325
|
+
hasFavorites,
|
|
6326
|
+
currentInitialProvider
|
|
6327
|
+
);
|
|
5796
6328
|
if (!pickedProvider) return 0;
|
|
5797
6329
|
if (pickedProvider === "__favorites__") {
|
|
5798
6330
|
const favoritePick = await pickFavoriteStartingModel(
|
|
@@ -5805,9 +6337,36 @@ Error: ${launchPlan.error}
|
|
|
5805
6337
|
if (favoritePick === "cancelled" || favoritePick === "unavailable") return 0;
|
|
5806
6338
|
activeProvider = favoritePick.provider;
|
|
5807
6339
|
selectedModel = favoritePick.model;
|
|
6340
|
+
catalogMode = "favorites";
|
|
6341
|
+
favoritesActive = true;
|
|
5808
6342
|
break;
|
|
5809
6343
|
} else {
|
|
5810
6344
|
activeProvider = pickedProvider;
|
|
6345
|
+
const modelModeChoice = await p9.select({
|
|
6346
|
+
message: `Launch mode for ${activeProvider.name}?`,
|
|
6347
|
+
options: [
|
|
6348
|
+
{
|
|
6349
|
+
value: "specific",
|
|
6350
|
+
label: "One model",
|
|
6351
|
+
hint: "Pick a specific model"
|
|
6352
|
+
},
|
|
6353
|
+
{
|
|
6354
|
+
value: "all",
|
|
6355
|
+
label: `All models (${activeProvider.models.length})`,
|
|
6356
|
+
hint: "Every model from this provider in the picker"
|
|
6357
|
+
},
|
|
6358
|
+
navOption("__back__", "\u2190 Back", "Choose a different provider")
|
|
6359
|
+
]
|
|
6360
|
+
});
|
|
6361
|
+
if (p9.isCancel(modelModeChoice) || modelModeChoice === "__back__") {
|
|
6362
|
+
currentInitialProvider = activeProvider.id;
|
|
6363
|
+
continue;
|
|
6364
|
+
}
|
|
6365
|
+
if (modelModeChoice === "all") {
|
|
6366
|
+
catalogMode = "provider-all";
|
|
6367
|
+
selectedModel = activeProvider.models[0];
|
|
6368
|
+
break;
|
|
6369
|
+
}
|
|
5811
6370
|
const pickedModelResult = await pickCodexModel(activeProvider, prefs);
|
|
5812
6371
|
if (pickedModelResult === "back") {
|
|
5813
6372
|
currentInitialProvider = activeProvider.id;
|
|
@@ -5855,7 +6414,64 @@ Error: ${launchPlan.error}
|
|
|
5855
6414
|
let cloudCodeBackendFav = null;
|
|
5856
6415
|
try {
|
|
5857
6416
|
let proxyPort;
|
|
5858
|
-
if (
|
|
6417
|
+
if (catalogMode === "provider-all") {
|
|
6418
|
+
const routable = routableModelsForProvider(activeProvider, "codex");
|
|
6419
|
+
const backendModels = routable.filter((m) => needsCloudCodeBackend(m, activeProvider.authType));
|
|
6420
|
+
const regularModels = routable.filter((m) => !needsCloudCodeBackend(m, activeProvider.authType));
|
|
6421
|
+
let backendCodexRoutes = [];
|
|
6422
|
+
if (backendModels.length > 0) {
|
|
6423
|
+
const partitioned = await partitionAndStartCloudCodeBackend(
|
|
6424
|
+
backendModels.map((model) => ({
|
|
6425
|
+
providerId: activeProvider.id,
|
|
6426
|
+
model,
|
|
6427
|
+
apiKey,
|
|
6428
|
+
oauthAccountId: activeProvider.oauthAccountId,
|
|
6429
|
+
providerData: activeProvider.providerData ?? {}
|
|
6430
|
+
})),
|
|
6431
|
+
(cr, backend) => ({
|
|
6432
|
+
modelId: cr.aliasId,
|
|
6433
|
+
npm: "@ai-sdk/anthropic",
|
|
6434
|
+
apiKey: backend.token,
|
|
6435
|
+
baseURL: `http://127.0.0.1:${backend.port}`,
|
|
6436
|
+
upstreamModelId: cr.aliasId,
|
|
6437
|
+
providerId: cr.providerId ?? activeProvider.id,
|
|
6438
|
+
authType: "oauth",
|
|
6439
|
+
oauthAccountId: activeProvider.oauthAccountId,
|
|
6440
|
+
providerData: activeProvider.providerData ?? {},
|
|
6441
|
+
contextWindow: cr.contextWindow,
|
|
6442
|
+
supportedParameters: cr.supportedParameters,
|
|
6443
|
+
reasoning: cr.reasoning,
|
|
6444
|
+
interleavedReasoningField: cr.interleavedReasoningField
|
|
6445
|
+
}),
|
|
6446
|
+
trace,
|
|
6447
|
+
"codex"
|
|
6448
|
+
);
|
|
6449
|
+
cloudCodeBackendFav = partitioned.backend;
|
|
6450
|
+
backendCodexRoutes = partitioned.backendItems;
|
|
6451
|
+
}
|
|
6452
|
+
const regularRoutes = regularModels.map((model) => {
|
|
6453
|
+
const r = resolveCodexRoute(activeProvider, model, apiKey);
|
|
6454
|
+
return {
|
|
6455
|
+
modelId: r.modelId,
|
|
6456
|
+
npm: r.npm,
|
|
6457
|
+
apiKey: r.apiKey,
|
|
6458
|
+
baseURL: r.baseURL,
|
|
6459
|
+
upstreamModelId: r.upstreamModelId,
|
|
6460
|
+
providerId: r.providerId,
|
|
6461
|
+
authType: r.authType,
|
|
6462
|
+
oauthAccountId: r.oauthAccountId,
|
|
6463
|
+
providerData: r.providerData,
|
|
6464
|
+
contextWindow: r.contextWindow,
|
|
6465
|
+
supportedParameters: r.supportedParameters,
|
|
6466
|
+
reasoning: r.reasoning,
|
|
6467
|
+
interleavedReasoningField: r.interleavedReasoningField,
|
|
6468
|
+
headers: r.headers
|
|
6469
|
+
};
|
|
6470
|
+
});
|
|
6471
|
+
const allRoutes = [...backendCodexRoutes, ...regularRoutes];
|
|
6472
|
+
proxyHandle = await startCodexProxy(allRoutes, { requireAuth: true, debug: trace });
|
|
6473
|
+
proxyPort = proxyHandle.port;
|
|
6474
|
+
} else if (favoritesActive && resolvedFavorites.length > 0) {
|
|
5859
6475
|
const needsBackend = (r) => {
|
|
5860
6476
|
const m = r.model;
|
|
5861
6477
|
const prov = providersById.get(r.providerId);
|
|
@@ -5888,7 +6504,8 @@ Error: ${launchPlan.error}
|
|
|
5888
6504
|
providerData: original.providerData,
|
|
5889
6505
|
contextWindow: cr.contextWindow
|
|
5890
6506
|
}),
|
|
5891
|
-
trace
|
|
6507
|
+
trace,
|
|
6508
|
+
"codex"
|
|
5892
6509
|
);
|
|
5893
6510
|
cloudCodeBackendFav = partitioned.backend;
|
|
5894
6511
|
backendCodexRoutes = partitioned.backendItems;
|
|
@@ -5907,21 +6524,26 @@ Error: ${launchPlan.error}
|
|
|
5907
6524
|
trace
|
|
5908
6525
|
);
|
|
5909
6526
|
cloudCodeBackend = backend;
|
|
5910
|
-
proxyHandle = await startCodexProxy(
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
6527
|
+
proxyHandle = await startCodexProxy(
|
|
6528
|
+
[
|
|
6529
|
+
{
|
|
6530
|
+
modelId: cloudRoute.aliasId,
|
|
6531
|
+
npm: "@ai-sdk/anthropic",
|
|
6532
|
+
apiKey: cloudCodeBackend.token,
|
|
6533
|
+
baseURL: `http://127.0.0.1:${cloudCodeBackend.port}`,
|
|
6534
|
+
upstreamModelId: cloudRoute.aliasId,
|
|
6535
|
+
providerId: route.providerId,
|
|
6536
|
+
authType: route.authType,
|
|
6537
|
+
oauthAccountId: route.oauthAccountId,
|
|
6538
|
+
providerData,
|
|
6539
|
+
contextWindow: route.contextWindow,
|
|
6540
|
+
supportedParameters: route.supportedParameters,
|
|
6541
|
+
reasoning: route.reasoning,
|
|
6542
|
+
interleavedReasoningField: route.interleavedReasoningField
|
|
6543
|
+
}
|
|
6544
|
+
],
|
|
6545
|
+
{ debug: trace }
|
|
6546
|
+
);
|
|
5925
6547
|
proxyPort = proxyHandle.port;
|
|
5926
6548
|
} else if (route.authType === "oauth" && selectedModel.modelFormat === "anthropic") {
|
|
5927
6549
|
const providerData = activeProvider.providerData ?? {};
|
|
@@ -5933,44 +6555,59 @@ Error: ${launchPlan.error}
|
|
|
5933
6555
|
trace
|
|
5934
6556
|
);
|
|
5935
6557
|
cloudCodeBackend = backend;
|
|
5936
|
-
proxyHandle = await startCodexProxy(
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
6558
|
+
proxyHandle = await startCodexProxy(
|
|
6559
|
+
[
|
|
6560
|
+
{
|
|
6561
|
+
modelId: oauthRoute.aliasId,
|
|
6562
|
+
npm: "@ai-sdk/anthropic",
|
|
6563
|
+
apiKey: cloudCodeBackend.token,
|
|
6564
|
+
baseURL: `http://127.0.0.1:${cloudCodeBackend.port}`,
|
|
6565
|
+
upstreamModelId: oauthRoute.aliasId,
|
|
6566
|
+
providerId: route.providerId,
|
|
6567
|
+
authType: route.authType,
|
|
6568
|
+
oauthAccountId: route.oauthAccountId,
|
|
6569
|
+
providerData,
|
|
6570
|
+
contextWindow: route.contextWindow,
|
|
6571
|
+
supportedParameters: route.supportedParameters,
|
|
6572
|
+
reasoning: route.reasoning,
|
|
6573
|
+
interleavedReasoningField: route.interleavedReasoningField
|
|
6574
|
+
}
|
|
6575
|
+
],
|
|
6576
|
+
{ debug: trace }
|
|
6577
|
+
);
|
|
5951
6578
|
proxyPort = proxyHandle.port;
|
|
5952
6579
|
} else if (route.tier === "proxy") {
|
|
5953
|
-
proxyHandle = await startCodexProxy(
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
6580
|
+
proxyHandle = await startCodexProxy(
|
|
6581
|
+
[
|
|
6582
|
+
{
|
|
6583
|
+
modelId: route.modelId,
|
|
6584
|
+
npm: route.npm,
|
|
6585
|
+
apiKey: route.apiKey,
|
|
6586
|
+
baseURL: route.baseURL,
|
|
6587
|
+
upstreamModelId: route.upstreamModelId,
|
|
6588
|
+
providerId: route.providerId,
|
|
6589
|
+
authType: route.authType,
|
|
6590
|
+
oauthAccountId: route.oauthAccountId,
|
|
6591
|
+
providerData: route.providerData,
|
|
6592
|
+
supportedParameters: route.supportedParameters,
|
|
6593
|
+
reasoning: route.reasoning,
|
|
6594
|
+
interleavedReasoningField: route.interleavedReasoningField,
|
|
6595
|
+
headers: route.headers
|
|
6596
|
+
}
|
|
6597
|
+
],
|
|
6598
|
+
{ debug: trace }
|
|
6599
|
+
);
|
|
5968
6600
|
proxyPort = proxyHandle.port;
|
|
5969
6601
|
}
|
|
5970
6602
|
const startingFavorite = resolvedFavorites.find(
|
|
5971
6603
|
(r) => r.providerId === activeProvider.id && r.model.id === selectedModel.id
|
|
5972
6604
|
) ?? resolvedFavorites[0];
|
|
5973
|
-
const { profilePath, catalogPath } =
|
|
6605
|
+
const { profilePath, catalogPath } = catalogMode === "provider-all" && proxyPort ? await writeAllModelsLaunchArtifacts(
|
|
6606
|
+
activeProvider,
|
|
6607
|
+
selectedModel,
|
|
6608
|
+
routableModelsForProvider(activeProvider, "codex"),
|
|
6609
|
+
proxyPort
|
|
6610
|
+
) : favoritesActive && resolvedFavorites.length > 0 && proxyPort && startingFavorite ? await writeFavoritesLaunchArtifacts(resolvedFavorites, startingFavorite, proxyPort) : await writeLaunchArtifacts(route, selectedModel, activeProvider.name, proxyPort);
|
|
5974
6611
|
writeSessionLock({
|
|
5975
6612
|
pid: process.pid,
|
|
5976
6613
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -5984,8 +6621,22 @@ Error: ${launchPlan.error}
|
|
|
5984
6621
|
console.log("");
|
|
5985
6622
|
console.log(pc8.bold(pc8.cyan(" CONFIG PREVIEW \u2014 anygate codex")));
|
|
5986
6623
|
console.log("");
|
|
5987
|
-
if (
|
|
5988
|
-
|
|
6624
|
+
if (catalogMode === "provider-all") {
|
|
6625
|
+
const allModels = routableModelsForProvider(activeProvider, "codex");
|
|
6626
|
+
console.log(
|
|
6627
|
+
` ${pc8.bold("Mode:")} Provider Catalog (${allModels.length} model${allModels.length !== 1 ? "s" : ""})`
|
|
6628
|
+
);
|
|
6629
|
+
console.log(` ${pc8.bold("Provider:")} ${activeProvider.name}`);
|
|
6630
|
+
console.log(` ${pc8.bold("Starting model:")} ${selectedModel.id}`);
|
|
6631
|
+
console.log("");
|
|
6632
|
+
console.log(` ${pc8.bold("Models:")}`);
|
|
6633
|
+
for (const m of allModels) {
|
|
6634
|
+
console.log(` ${pc8.cyan(m.id)}`);
|
|
6635
|
+
}
|
|
6636
|
+
} else if (favoritesActive && resolvedFavorites.length > 0) {
|
|
6637
|
+
console.log(
|
|
6638
|
+
` ${pc8.bold("Mode:")} Favorites Catalog (${resolvedFavorites.length} model${resolvedFavorites.length !== 1 ? "s" : ""})`
|
|
6639
|
+
);
|
|
5989
6640
|
console.log("");
|
|
5990
6641
|
console.log(` ${pc8.bold("Models:")}`);
|
|
5991
6642
|
for (const r of resolvedFavorites) {
|
|
@@ -6015,6 +6666,7 @@ Error: ${launchPlan.error}
|
|
|
6015
6666
|
}
|
|
6016
6667
|
}
|
|
6017
6668
|
const favoritesLaunch = favoritesActive && resolvedFavorites.length > 0;
|
|
6669
|
+
const providerAllLaunch = catalogMode === "provider-all";
|
|
6018
6670
|
const launchModelId = favoritesLaunch ? codexCliFavoritesSlug(activeProvider.id, selectedModel.id) : selectedModel.id;
|
|
6019
6671
|
if (!agentStdout) {
|
|
6020
6672
|
logActiveModel(modelLabel, launchModelId);
|
|
@@ -6029,11 +6681,9 @@ Error: ${launchPlan.error}
|
|
|
6029
6681
|
upstreamModelId: selectedModel.upstreamModelId || selectedModel.id,
|
|
6030
6682
|
apiKey: ""
|
|
6031
6683
|
};
|
|
6032
|
-
const
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
);
|
|
6036
|
-
const hadProxy = (route.tier === "proxy" || route.tier === "cloud-code" || favoritesLaunch) && !!proxyPort;
|
|
6684
|
+
const useProxyRoute = favoritesLaunch || providerAllLaunch || route.tier === "cloud-code";
|
|
6685
|
+
const childEnv = buildCodexChildEnv(useProxyRoute ? dummyRoute : route, proxyPort);
|
|
6686
|
+
const hadProxy = (route.tier === "proxy" || route.tier === "cloud-code" || favoritesLaunch || providerAllLaunch) && !!proxyPort;
|
|
6037
6687
|
const exitCode = await launchCodex(launchModelId, childEnv, passthroughArgs);
|
|
6038
6688
|
if (trace) printTraceLog(debugLogPath);
|
|
6039
6689
|
printCodexCleanupReminder(hadProxy);
|
|
@@ -6053,7 +6703,7 @@ Error: ${launchPlan.error}
|
|
|
6053
6703
|
// src/cli/codex.ts
|
|
6054
6704
|
async function handleCodexCommand(parsed) {
|
|
6055
6705
|
if (parsed.showVersion) {
|
|
6056
|
-
const { VERSION: VERSION2 } = await import("./constants-
|
|
6706
|
+
const { VERSION: VERSION2 } = await import("./constants-WLMOLKEO.js");
|
|
6057
6707
|
console.log(VERSION2);
|
|
6058
6708
|
return 0;
|
|
6059
6709
|
}
|
|
@@ -6064,6 +6714,7 @@ async function handleCodexCommand(parsed) {
|
|
|
6064
6714
|
return runCodexCommand(parsed.claudeArgs ?? [], parsed.trace ?? false, {
|
|
6065
6715
|
launchProvider: parsed.launchProvider,
|
|
6066
6716
|
launchModel: parsed.launchModel,
|
|
6717
|
+
launchAllModels: parsed.launchAllModels || parsed.launchModel === "All",
|
|
6067
6718
|
vertex: parsed.vertex
|
|
6068
6719
|
});
|
|
6069
6720
|
}
|
|
@@ -6071,7 +6722,6 @@ async function handleCodexCommand(parsed) {
|
|
|
6071
6722
|
// src/apps/codex/app.ts
|
|
6072
6723
|
import pc9 from "picocolors";
|
|
6073
6724
|
import * as p10 from "@clack/prompts";
|
|
6074
|
-
init_config();
|
|
6075
6725
|
|
|
6076
6726
|
// src/apps/codex/app-provider-routes.ts
|
|
6077
6727
|
function codexRouteToProxyRoute(provider, model, apiKey) {
|
|
@@ -6130,7 +6780,8 @@ async function buildCodexAppProviderCatalogRoutes(provider, apiKey, selectedMode
|
|
|
6130
6780
|
interleavedReasoningField: original.model.interleavedReasoningField,
|
|
6131
6781
|
headers: provider.headers
|
|
6132
6782
|
}),
|
|
6133
|
-
trace
|
|
6783
|
+
trace,
|
|
6784
|
+
"codex-app"
|
|
6134
6785
|
);
|
|
6135
6786
|
for (let index = 0; index < backendModels.length; index++) {
|
|
6136
6787
|
const model = backendModels[index];
|
|
@@ -6312,7 +6963,9 @@ function applyAppConfigPatch(spec, configPath = getCodexConfigPath()) {
|
|
|
6312
6963
|
try {
|
|
6313
6964
|
existing = parseCodexConfig(existingText);
|
|
6314
6965
|
} catch (err) {
|
|
6315
|
-
throw new Error(
|
|
6966
|
+
throw new Error(
|
|
6967
|
+
`Invalid existing Codex config at ${configPath}: ${err instanceof Error ? err.message : err}`
|
|
6968
|
+
);
|
|
6316
6969
|
}
|
|
6317
6970
|
const merged = mergeAppConfig(existing, spec);
|
|
6318
6971
|
const text4 = `${stringify(merged)}
|
|
@@ -6350,9 +7003,24 @@ function restoreConfigFromState(state, configPath = getCodexConfigPath()) {
|
|
|
6350
7003
|
if ("hadOpenAIBaseUrl" in state) {
|
|
6351
7004
|
applyRestoreKey(config, "openai_base_url", Boolean(state.hadOpenAIBaseUrl), state.openAIBaseUrl);
|
|
6352
7005
|
}
|
|
6353
|
-
applyRestoreKey(
|
|
6354
|
-
|
|
6355
|
-
|
|
7006
|
+
applyRestoreKey(
|
|
7007
|
+
config,
|
|
7008
|
+
"model_reasoning_effort",
|
|
7009
|
+
state.hadModelReasoningEffort,
|
|
7010
|
+
state.modelReasoningEffort
|
|
7011
|
+
);
|
|
7012
|
+
applyRestoreNumber(
|
|
7013
|
+
config,
|
|
7014
|
+
"model_context_window",
|
|
7015
|
+
state.hadModelContextWindow ?? false,
|
|
7016
|
+
state.modelContextWindow
|
|
7017
|
+
);
|
|
7018
|
+
applyRestoreNumber(
|
|
7019
|
+
config,
|
|
7020
|
+
"model_auto_compact_token_limit",
|
|
7021
|
+
state.hadModelAutoCompactTokenLimit ?? false,
|
|
7022
|
+
state.modelAutoCompactTokenLimit
|
|
7023
|
+
);
|
|
6356
7024
|
const sidecar = getCodexAppSidecarProfilePath();
|
|
6357
7025
|
if (existsSync5(sidecar)) {
|
|
6358
7026
|
try {
|
|
@@ -6379,14 +7047,7 @@ function previewAppConfigToml(spec) {
|
|
|
6379
7047
|
}
|
|
6380
7048
|
|
|
6381
7049
|
// src/apps/codex/app-session.ts
|
|
6382
|
-
import {
|
|
6383
|
-
copyFileSync as copyFileSync2,
|
|
6384
|
-
existsSync as existsSync6,
|
|
6385
|
-
mkdirSync as mkdirSync4,
|
|
6386
|
-
readdirSync as readdirSync2,
|
|
6387
|
-
readFileSync as readFileSync5,
|
|
6388
|
-
rmSync as rmSync3
|
|
6389
|
-
} from "fs";
|
|
7050
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync5, rmSync as rmSync3 } from "fs";
|
|
6390
7051
|
import { basename as basename2, join as join6 } from "path";
|
|
6391
7052
|
function getAppSessionLockPath(env = process.env) {
|
|
6392
7053
|
return join6(getAnygateICodexDir(env), "session-app.json");
|
|
@@ -6697,7 +7358,9 @@ async function runCodexAppVertexLaunch(configOnly, trace = false) {
|
|
|
6697
7358
|
console.log(` ${pc9.bold("Project:")} ${config.project}`);
|
|
6698
7359
|
console.log(` ${pc9.bold("Location:")} ${config.location}`);
|
|
6699
7360
|
console.log(` ${pc9.bold("Model:")} ${selectedEntry.display_name}`);
|
|
6700
|
-
console.log(
|
|
7361
|
+
console.log(
|
|
7362
|
+
` ${pc9.bold("Catalog:")} ${vertexModels.length} model${vertexModels.length !== 1 ? "s" : ""} available`
|
|
7363
|
+
);
|
|
6701
7364
|
console.log("");
|
|
6702
7365
|
console.log(` ${pc9.bold("Catalog file:")}`);
|
|
6703
7366
|
console.log(` ${pc9.dim(shortenPath(catalogPath))}`);
|
|
@@ -6720,7 +7383,7 @@ async function runCodexAppVertexLaunch(configOnly, trace = false) {
|
|
|
6720
7383
|
vertex: vertexConfig,
|
|
6721
7384
|
contextWindow: m.contextWindow
|
|
6722
7385
|
})),
|
|
6723
|
-
{ requireAuth: false, debug: trace }
|
|
7386
|
+
{ requireAuth: false, debug: trace, app: "codex-app" }
|
|
6724
7387
|
);
|
|
6725
7388
|
const proxyPort = proxyHandle.port;
|
|
6726
7389
|
const catalogFile = buildAppCatalogFile(vertexModels, "Vertex AI", selectedEntry.id);
|
|
@@ -6743,7 +7406,9 @@ async function runCodexAppVertexLaunch(configOnly, trace = false) {
|
|
|
6743
7406
|
proxyPort
|
|
6744
7407
|
});
|
|
6745
7408
|
sessionActive = true;
|
|
6746
|
-
p10.log.info(
|
|
7409
|
+
p10.log.info(
|
|
7410
|
+
`Vertex AI \xB7 ${selectedEntry.display_name} \u2014 project: ${config.project} / location: ${config.location}`
|
|
7411
|
+
);
|
|
6747
7412
|
logProxy(proxyPort);
|
|
6748
7413
|
logActiveModel(selectedEntry.display_name, selectedEntry.id);
|
|
6749
7414
|
try {
|
|
@@ -6803,8 +7468,14 @@ async function runCodexAppCommand(args, opts = {}) {
|
|
|
6803
7468
|
console.error(pc9.red("anygate codex-app requires an interactive terminal."));
|
|
6804
7469
|
return 1;
|
|
6805
7470
|
}
|
|
6806
|
-
console.error(
|
|
6807
|
-
|
|
7471
|
+
console.error(
|
|
7472
|
+
pc9.yellow(
|
|
7473
|
+
`Another anygate codex-app session may be running (pid ${sessionCheck.lock.pid}).`
|
|
7474
|
+
)
|
|
7475
|
+
);
|
|
7476
|
+
console.error(
|
|
7477
|
+
"Stop it with Ctrl+C in that terminal, or run anygate codex-app --restore after it exits."
|
|
7478
|
+
);
|
|
6808
7479
|
return 1;
|
|
6809
7480
|
}
|
|
6810
7481
|
}
|
|
@@ -6838,33 +7509,43 @@ async function runCodexAppCommand(args, opts = {}) {
|
|
|
6838
7509
|
}
|
|
6839
7510
|
const prefs = loadPreferences();
|
|
6840
7511
|
const favorites = prefs.favoriteModels ?? [];
|
|
6841
|
-
const
|
|
7512
|
+
const hasFavorites = favorites.length > 0;
|
|
7513
|
+
let favoritesMode = false;
|
|
7514
|
+
let useProviderAll = false;
|
|
6842
7515
|
const useFavoritesCatalog = args.includes("--favorites");
|
|
6843
|
-
if (favoritesActive && !configOnly) {
|
|
6844
|
-
p10.log.info(
|
|
6845
|
-
`Favorites mode active \u2014 Codex App picker will show ${favorites.length + 1} models (1 starting + ${favorites.length} favorites).`
|
|
6846
|
-
);
|
|
6847
|
-
p10.log.info("Edit with `anygate models`.");
|
|
6848
|
-
}
|
|
6849
7516
|
let activeProvider = providerForCodexPicker(
|
|
6850
7517
|
compatible.find((lp) => lp.id === prefs.lastCodexProvider) ?? compatible[0]
|
|
6851
7518
|
);
|
|
6852
7519
|
let selectedModel = activeProvider.models.find((m) => m.id === prefs.lastCodexModel) ?? activeProvider.models[0];
|
|
6853
|
-
if (!configOnly && opts.launchProvider && opts.launchModel) {
|
|
6854
|
-
|
|
6855
|
-
compatible
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
7520
|
+
if (!configOnly && opts.launchProvider && opts.launchModel || opts.launchProvider && (opts.launchAllModels || opts.launchModel === "All")) {
|
|
7521
|
+
if (opts.launchAllModels || opts.launchModel === "All") {
|
|
7522
|
+
const foundProvider = compatible.find((lp) => lp.id === opts.launchProvider);
|
|
7523
|
+
if (!foundProvider) {
|
|
7524
|
+
p10.log.error(`Provider not found: ${opts.launchProvider}`);
|
|
7525
|
+
return 1;
|
|
7526
|
+
}
|
|
7527
|
+
activeProvider = providerForCodexPicker(foundProvider);
|
|
7528
|
+
selectedModel = activeProvider.models[0];
|
|
7529
|
+
useProviderAll = true;
|
|
7530
|
+
if (!configOnly) {
|
|
7531
|
+
p10.log.step(`Using all ${activeProvider.models.length} models from ${activeProvider.name}`);
|
|
7532
|
+
}
|
|
7533
|
+
} else {
|
|
7534
|
+
const bootSelection = resolveBootSelection(
|
|
7535
|
+
compatible,
|
|
7536
|
+
opts.launchProvider,
|
|
7537
|
+
opts.launchModel,
|
|
7538
|
+
providerForCodexPicker
|
|
7539
|
+
);
|
|
7540
|
+
if ("error" in bootSelection) {
|
|
7541
|
+
p10.log.error(bootSelection.error);
|
|
7542
|
+
return 1;
|
|
7543
|
+
}
|
|
7544
|
+
activeProvider = bootSelection.provider;
|
|
7545
|
+
selectedModel = bootSelection.model;
|
|
6863
7546
|
}
|
|
6864
|
-
activeProvider = bootSelection.provider;
|
|
6865
|
-
selectedModel = bootSelection.model;
|
|
6866
7547
|
} else if (!configOnly) {
|
|
6867
|
-
if (useFavoritesCatalog &&
|
|
7548
|
+
if (useFavoritesCatalog && hasFavorites) {
|
|
6868
7549
|
const firstFavorite = resolveFirstAvailableFavorite(
|
|
6869
7550
|
favorites,
|
|
6870
7551
|
compatible.map(providerForCodexPicker)
|
|
@@ -6875,10 +7556,16 @@ async function runCodexAppCommand(args, opts = {}) {
|
|
|
6875
7556
|
}
|
|
6876
7557
|
activeProvider = providerForCodexPicker(firstFavorite.provider);
|
|
6877
7558
|
selectedModel = firstFavorite.model;
|
|
7559
|
+
favoritesMode = true;
|
|
6878
7560
|
} else {
|
|
6879
7561
|
let currentInitialProvider = prefs.lastCodexProvider && compatible.some((o) => o.id === prefs.lastCodexProvider) ? prefs.lastCodexProvider : compatible[0].id;
|
|
6880
7562
|
while (true) {
|
|
6881
|
-
const pickedProvider = await pickCodexProvider(
|
|
7563
|
+
const pickedProvider = await pickCodexProvider(
|
|
7564
|
+
compatible,
|
|
7565
|
+
prefs,
|
|
7566
|
+
hasFavorites,
|
|
7567
|
+
currentInitialProvider
|
|
7568
|
+
);
|
|
6882
7569
|
if (!pickedProvider) return 0;
|
|
6883
7570
|
if (pickedProvider === "__favorites__") {
|
|
6884
7571
|
const favoritePick = await pickFavoriteStartingModel(
|
|
@@ -6891,9 +7578,35 @@ async function runCodexAppCommand(args, opts = {}) {
|
|
|
6891
7578
|
if (favoritePick === "cancelled" || favoritePick === "unavailable") return 0;
|
|
6892
7579
|
activeProvider = favoritePick.provider;
|
|
6893
7580
|
selectedModel = favoritePick.model;
|
|
7581
|
+
favoritesMode = true;
|
|
6894
7582
|
break;
|
|
6895
7583
|
} else {
|
|
6896
7584
|
activeProvider = providerForCodexPicker(pickedProvider);
|
|
7585
|
+
const modelModeChoice = await p10.select({
|
|
7586
|
+
message: `Launch mode for ${activeProvider.name}?`,
|
|
7587
|
+
options: [
|
|
7588
|
+
{
|
|
7589
|
+
value: "specific",
|
|
7590
|
+
label: "One model",
|
|
7591
|
+
hint: "Pick a specific model"
|
|
7592
|
+
},
|
|
7593
|
+
{
|
|
7594
|
+
value: "all",
|
|
7595
|
+
label: `All models (${activeProvider.models.length})`,
|
|
7596
|
+
hint: "Every model from this provider in the model switcher"
|
|
7597
|
+
},
|
|
7598
|
+
navOption("__back__", "\u2190 Back", "Choose a different provider")
|
|
7599
|
+
]
|
|
7600
|
+
});
|
|
7601
|
+
if (p10.isCancel(modelModeChoice) || modelModeChoice === "__back__") {
|
|
7602
|
+
currentInitialProvider = activeProvider.id;
|
|
7603
|
+
continue;
|
|
7604
|
+
}
|
|
7605
|
+
if (modelModeChoice === "all") {
|
|
7606
|
+
useProviderAll = true;
|
|
7607
|
+
selectedModel = activeProvider.models[0];
|
|
7608
|
+
break;
|
|
7609
|
+
}
|
|
6897
7610
|
const pickedModelResult = await pickCodexModel(activeProvider, prefs);
|
|
6898
7611
|
if (pickedModelResult === "back") {
|
|
6899
7612
|
currentInitialProvider = activeProvider.id;
|
|
@@ -6914,9 +7627,15 @@ async function runCodexAppCommand(args, opts = {}) {
|
|
|
6914
7627
|
return 1;
|
|
6915
7628
|
}
|
|
6916
7629
|
activeProvider.apiKey = apiKey;
|
|
7630
|
+
if (hasFavorites && !configOnly && !useProviderAll) {
|
|
7631
|
+
p10.log.info(
|
|
7632
|
+
`Favorites mode active \u2014 Codex App picker will show ${favorites.length + 1} models (1 starting + ${favorites.length} favorites).`
|
|
7633
|
+
);
|
|
7634
|
+
p10.log.info("Edit with `anygate models`.");
|
|
7635
|
+
}
|
|
6917
7636
|
let cloudCodeBackend = null;
|
|
6918
7637
|
let cloudCodeBackendFav = null;
|
|
6919
|
-
const appProviderRoutes =
|
|
7638
|
+
const appProviderRoutes = !favoritesMode ? await buildCodexAppProviderCatalogRoutes(activeProvider, apiKey, selectedModel.id, trace) : null;
|
|
6920
7639
|
cloudCodeBackend = appProviderRoutes?.backend ?? null;
|
|
6921
7640
|
const route = appProviderRoutes ? codexProxyRouteToCodexRoute(appProviderRoutes.selectedRoute, activeProvider.id) : resolveCodexRoute(activeProvider, selectedModel, apiKey);
|
|
6922
7641
|
const appRoute = { ...route, tier: "proxy" };
|
|
@@ -6924,19 +7643,21 @@ async function runCodexAppCommand(args, opts = {}) {
|
|
|
6924
7643
|
const catalogModels = appProviderRoutes?.catalogModels ?? routable;
|
|
6925
7644
|
let resolvedFavorites = [];
|
|
6926
7645
|
let providersById = /* @__PURE__ */ new Map();
|
|
6927
|
-
if (
|
|
6928
|
-
const res = await resolveCodexFavorites(
|
|
7646
|
+
if (favoritesMode) {
|
|
7647
|
+
const res = await resolveCodexFavorites(
|
|
7648
|
+
activeProvider,
|
|
7649
|
+
selectedModel,
|
|
7650
|
+
compatible,
|
|
7651
|
+
favorites,
|
|
7652
|
+
"codex-app"
|
|
7653
|
+
);
|
|
6929
7654
|
resolvedFavorites = res.resolvedFavorites;
|
|
6930
7655
|
providersById = res.providersById;
|
|
6931
7656
|
}
|
|
6932
7657
|
if (!configOnly) {
|
|
6933
7658
|
const modelLabel = formatCodexModelLabel(selectedModel);
|
|
6934
|
-
const
|
|
6935
|
-
|
|
6936
|
-
modelLabel,
|
|
6937
|
-
selectedModel.id,
|
|
6938
|
-
appRoute
|
|
6939
|
-
);
|
|
7659
|
+
const isExplicitLaunch = Boolean(opts.launchProvider) && Boolean(opts.launchModel || opts.launchAllModels);
|
|
7660
|
+
const confirmed = useFavoritesCatalog || isExplicitLaunch || await confirmCodexLaunch(activeProvider.name, modelLabel, selectedModel.id, appRoute);
|
|
6940
7661
|
if (!confirmed) {
|
|
6941
7662
|
cloudCodeBackend?.handle.close();
|
|
6942
7663
|
return 0;
|
|
@@ -6945,8 +7666,8 @@ async function runCodexAppCommand(args, opts = {}) {
|
|
|
6945
7666
|
let proxyHandle = null;
|
|
6946
7667
|
let sessionActive = false;
|
|
6947
7668
|
try {
|
|
6948
|
-
const catalogPath =
|
|
6949
|
-
const activeRoute =
|
|
7669
|
+
const catalogPath = favoritesMode && resolvedFavorites.length > 0 ? getFavoritesAppCatalogPath() : getAppCatalogPath(route.providerId);
|
|
7670
|
+
const activeRoute = favoritesMode && resolvedFavorites.length > 0 ? {
|
|
6950
7671
|
tier: "proxy",
|
|
6951
7672
|
modelId: codexCliFavoritesSlug(activeProvider.id, selectedModel.id),
|
|
6952
7673
|
providerId: activeProvider.id,
|
|
@@ -6962,8 +7683,10 @@ async function runCodexAppCommand(args, opts = {}) {
|
|
|
6962
7683
|
console.log("");
|
|
6963
7684
|
console.log(pc9.bold(pc9.cyan(" CONFIG PREVIEW \u2014 anygate codex-app")));
|
|
6964
7685
|
console.log("");
|
|
6965
|
-
if (
|
|
6966
|
-
console.log(
|
|
7686
|
+
if (favoritesMode) {
|
|
7687
|
+
console.log(
|
|
7688
|
+
` ${pc9.bold("Mode:")} Favorites Catalog (${resolvedFavorites.length} model${resolvedFavorites.length !== 1 ? "s" : ""})`
|
|
7689
|
+
);
|
|
6967
7690
|
console.log("");
|
|
6968
7691
|
console.log(` ${pc9.bold("Models:")}`);
|
|
6969
7692
|
for (const r of resolvedFavorites) {
|
|
@@ -6973,7 +7696,9 @@ async function runCodexAppCommand(args, opts = {}) {
|
|
|
6973
7696
|
console.log(` ${pc9.bold("Mode:")} Single model`);
|
|
6974
7697
|
console.log(` ${pc9.bold("Provider:")} ${activeProvider.name}`);
|
|
6975
7698
|
console.log(` ${pc9.bold("Model:")} ${formatCodexModelLabel(selectedModel)}`);
|
|
6976
|
-
console.log(
|
|
7699
|
+
console.log(
|
|
7700
|
+
` ${pc9.bold("Catalog:")} ${routable.length} model${routable.length !== 1 ? "s" : ""} available`
|
|
7701
|
+
);
|
|
6977
7702
|
}
|
|
6978
7703
|
console.log("");
|
|
6979
7704
|
console.log(` ${pc9.bold("config.toml patch preview:")}`);
|
|
@@ -6994,7 +7719,7 @@ async function runCodexAppCommand(args, opts = {}) {
|
|
|
6994
7719
|
return 0;
|
|
6995
7720
|
}
|
|
6996
7721
|
let proxyPort;
|
|
6997
|
-
if (
|
|
7722
|
+
if (favoritesMode && resolvedFavorites.length > 0) {
|
|
6998
7723
|
const needsBackend = (r) => {
|
|
6999
7724
|
const m = r.model;
|
|
7000
7725
|
const prov = providersById.get(r.providerId);
|
|
@@ -7012,7 +7737,11 @@ async function runCodexAppCommand(args, opts = {}) {
|
|
|
7012
7737
|
return { ...route2, oauthAccountId: provider?.oauthAccountId, providerData };
|
|
7013
7738
|
});
|
|
7014
7739
|
const startingAlias = backendRoutes[0].aliasId;
|
|
7015
|
-
cloudCodeBackendFav = await startCloudCodeCatalogBackend(
|
|
7740
|
+
cloudCodeBackendFav = await startCloudCodeCatalogBackend(
|
|
7741
|
+
backendRoutes,
|
|
7742
|
+
startingAlias,
|
|
7743
|
+
trace
|
|
7744
|
+
);
|
|
7016
7745
|
backendCodexRoutes = backendRoutes.map((cr) => ({
|
|
7017
7746
|
modelId: cr.aliasId,
|
|
7018
7747
|
npm: "@ai-sdk/anthropic",
|
|
@@ -7027,23 +7756,25 @@ async function runCodexAppCommand(args, opts = {}) {
|
|
|
7027
7756
|
}));
|
|
7028
7757
|
}
|
|
7029
7758
|
const regularRoutes = buildCodexProxyRoutesFromResolved(regularResolved, providersById);
|
|
7030
|
-
proxyHandle = await startCodexProxy(
|
|
7031
|
-
|
|
7032
|
-
|
|
7033
|
-
|
|
7759
|
+
proxyHandle = await startCodexProxy([...backendCodexRoutes, ...regularRoutes], {
|
|
7760
|
+
requireAuth: false,
|
|
7761
|
+
debug: trace,
|
|
7762
|
+
app: "codex-app"
|
|
7763
|
+
});
|
|
7034
7764
|
proxyPort = proxyHandle.port;
|
|
7035
7765
|
} else {
|
|
7036
7766
|
if (!appProviderRoutes) {
|
|
7037
7767
|
throw new Error("Codex App provider routes were not initialized");
|
|
7038
7768
|
}
|
|
7039
|
-
proxyHandle = await startCodexProxy(
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7769
|
+
proxyHandle = await startCodexProxy(appProviderRoutes.routes, {
|
|
7770
|
+
requireAuth: false,
|
|
7771
|
+
debug: trace,
|
|
7772
|
+
app: "codex-app"
|
|
7773
|
+
});
|
|
7043
7774
|
proxyPort = proxyHandle.port;
|
|
7044
7775
|
}
|
|
7045
7776
|
const modelLabel = formatCodexModelLabel(selectedModel);
|
|
7046
|
-
const catalogFile =
|
|
7777
|
+
const catalogFile = favoritesMode && resolvedFavorites.length > 0 ? buildFavoritesAppCatalog(resolvedFavorites) : buildAppCatalogFile(catalogModels, activeProvider.name, appRoute.modelId);
|
|
7047
7778
|
writeOverlayFile(catalogPath, serializeCatalog(catalogFile));
|
|
7048
7779
|
const spec = {
|
|
7049
7780
|
route: activeRoute,
|
|
@@ -7064,11 +7795,17 @@ async function runCodexAppCommand(args, opts = {}) {
|
|
|
7064
7795
|
});
|
|
7065
7796
|
sessionActive = true;
|
|
7066
7797
|
const prevRecent = prefs.recentModelsByProvider?.[activeProvider.id] ?? [];
|
|
7067
|
-
const updatedRecent = [
|
|
7798
|
+
const updatedRecent = [
|
|
7799
|
+
selectedModel.id,
|
|
7800
|
+
...prevRecent.filter((id) => id !== selectedModel.id)
|
|
7801
|
+
].slice(0, 3);
|
|
7068
7802
|
savePreferences({
|
|
7069
7803
|
lastCodexProvider: activeProvider.id,
|
|
7070
7804
|
lastCodexModel: selectedModel.id,
|
|
7071
|
-
recentModelsByProvider: {
|
|
7805
|
+
recentModelsByProvider: {
|
|
7806
|
+
...prefs.recentModelsByProvider,
|
|
7807
|
+
[activeProvider.id]: updatedRecent
|
|
7808
|
+
}
|
|
7072
7809
|
});
|
|
7073
7810
|
logProxy(proxyPort);
|
|
7074
7811
|
logActiveModel(modelLabel, selectedModel.id);
|
|
@@ -7109,7 +7846,7 @@ async function runCodexAppCommand(args, opts = {}) {
|
|
|
7109
7846
|
// src/cli/codex-app.ts
|
|
7110
7847
|
async function handleCodexAppCommand(parsed) {
|
|
7111
7848
|
if (parsed.showVersion) {
|
|
7112
|
-
const { VERSION: VERSION2 } = await import("./constants-
|
|
7849
|
+
const { VERSION: VERSION2 } = await import("./constants-WLMOLKEO.js");
|
|
7113
7850
|
console.log(VERSION2);
|
|
7114
7851
|
return 0;
|
|
7115
7852
|
}
|
|
@@ -7136,14 +7873,14 @@ This command launches the ChatGPT Desktop app with anygate's provider registry.
|
|
|
7136
7873
|
return runCodexAppCommand(parsed.claudeArgs ?? [], {
|
|
7137
7874
|
vertex: parsed.vertex,
|
|
7138
7875
|
launchProvider: parsed.launchProvider,
|
|
7139
|
-
launchModel: parsed.launchModel
|
|
7876
|
+
launchModel: parsed.launchModel,
|
|
7877
|
+
launchAllModels: parsed.launchAllModels || parsed.launchModel === "All"
|
|
7140
7878
|
});
|
|
7141
7879
|
}
|
|
7142
7880
|
|
|
7143
7881
|
// src/apps/claude/desktop.ts
|
|
7144
7882
|
import pc10 from "picocolors";
|
|
7145
7883
|
import * as p11 from "@clack/prompts";
|
|
7146
|
-
init_config();
|
|
7147
7884
|
|
|
7148
7885
|
// src/apps/claude/desktop-app.ts
|
|
7149
7886
|
import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5 } from "fs";
|
|
@@ -7425,10 +8162,21 @@ async function runClaudeAppCommand(args, boot) {
|
|
|
7425
8162
|
const prefs = loadPreferences();
|
|
7426
8163
|
const favorites = prefs.favoriteModels ?? [];
|
|
7427
8164
|
const hasFavorites = favorites.length > 0;
|
|
8165
|
+
const launchAllModels = Boolean(boot?.launchAllModels || boot?.launchModel === "All");
|
|
7428
8166
|
let activeProvider = null;
|
|
7429
8167
|
let selectedModel = null;
|
|
7430
8168
|
let useFavorites = false;
|
|
7431
|
-
|
|
8169
|
+
let useProviderAll = false;
|
|
8170
|
+
if (boot?.launchProvider && launchAllModels) {
|
|
8171
|
+
const foundProvider = compatible.find((lp) => lp.id === boot.launchProvider);
|
|
8172
|
+
if (!foundProvider) {
|
|
8173
|
+
p11.log.error(`Provider not found: ${boot.launchProvider}`);
|
|
8174
|
+
return 1;
|
|
8175
|
+
}
|
|
8176
|
+
activeProvider = foundProvider;
|
|
8177
|
+
selectedModel = activeProvider.models[0];
|
|
8178
|
+
useProviderAll = true;
|
|
8179
|
+
} else if (boot?.launchProvider && boot?.launchModel) {
|
|
7432
8180
|
const bootSelection = resolveBootSelection(
|
|
7433
8181
|
compatible,
|
|
7434
8182
|
boot.launchProvider,
|
|
@@ -7444,15 +8192,59 @@ async function runClaudeAppCommand(args, boot) {
|
|
|
7444
8192
|
} else if (useFavoritesCatalog && hasFavorites) {
|
|
7445
8193
|
useFavorites = true;
|
|
7446
8194
|
} else {
|
|
7447
|
-
const pickedProvider = await pickCodexProvider(
|
|
8195
|
+
const pickedProvider = await pickCodexProvider(
|
|
8196
|
+
compatible,
|
|
8197
|
+
prefs,
|
|
8198
|
+
hasFavorites,
|
|
8199
|
+
void 0,
|
|
8200
|
+
"Claude"
|
|
8201
|
+
);
|
|
7448
8202
|
if (!pickedProvider) return 0;
|
|
7449
8203
|
if (pickedProvider === "__favorites__") {
|
|
7450
8204
|
useFavorites = true;
|
|
7451
8205
|
} else {
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
8206
|
+
while (true) {
|
|
8207
|
+
const pickedProvider2 = await pickCodexProvider(
|
|
8208
|
+
compatible,
|
|
8209
|
+
prefs,
|
|
8210
|
+
hasFavorites,
|
|
8211
|
+
void 0,
|
|
8212
|
+
"Claude"
|
|
8213
|
+
);
|
|
8214
|
+
if (!pickedProvider2) return 0;
|
|
8215
|
+
if (pickedProvider2 === "__favorites__") {
|
|
8216
|
+
useFavorites = true;
|
|
8217
|
+
break;
|
|
8218
|
+
} else {
|
|
8219
|
+
activeProvider = providerForClaudePicker(pickedProvider2);
|
|
8220
|
+
const modelModeChoice = await p11.select({
|
|
8221
|
+
message: `Launch mode for ${activeProvider.name}?`,
|
|
8222
|
+
options: [
|
|
8223
|
+
{
|
|
8224
|
+
value: "specific",
|
|
8225
|
+
label: "One model",
|
|
8226
|
+
hint: "Pick a specific model"
|
|
8227
|
+
},
|
|
8228
|
+
{
|
|
8229
|
+
value: "all",
|
|
8230
|
+
label: `All models (${activeProvider.models.length})`,
|
|
8231
|
+
hint: "Every model from this provider in the model picker"
|
|
8232
|
+
},
|
|
8233
|
+
navOption("__back__", "\u2190 Back", "Choose a different provider")
|
|
8234
|
+
]
|
|
8235
|
+
});
|
|
8236
|
+
if (p11.isCancel(modelModeChoice) || modelModeChoice === "__back__") continue;
|
|
8237
|
+
if (modelModeChoice === "all") {
|
|
8238
|
+
useProviderAll = true;
|
|
8239
|
+
selectedModel = activeProvider.models[0];
|
|
8240
|
+
break;
|
|
8241
|
+
}
|
|
8242
|
+
const pickedModel = await pickCodexModel(activeProvider, prefs);
|
|
8243
|
+
if (!pickedModel) return 0;
|
|
8244
|
+
selectedModel = pickedModel;
|
|
8245
|
+
break;
|
|
8246
|
+
}
|
|
8247
|
+
}
|
|
7456
8248
|
}
|
|
7457
8249
|
}
|
|
7458
8250
|
if (activeProvider) {
|
|
@@ -7470,7 +8262,9 @@ async function runClaudeAppCommand(args, boot) {
|
|
|
7470
8262
|
const antigravityProvider = catalog.find((lp) => lp.id === "antigravity");
|
|
7471
8263
|
const cloudCodeFavoriteModels = favorites.map((fav) => {
|
|
7472
8264
|
if (fav.providerId !== "antigravity") return null;
|
|
7473
|
-
const model = antigravityProvider?.models.find(
|
|
8265
|
+
const model = antigravityProvider?.models.find(
|
|
8266
|
+
(m) => m.id === fav.modelId
|
|
8267
|
+
);
|
|
7474
8268
|
return model?.modelFormat === "cloud-code" ? model : null;
|
|
7475
8269
|
}).filter((m) => m !== null);
|
|
7476
8270
|
const regularFavorites = favorites.filter(
|
|
@@ -7488,21 +8282,23 @@ async function runClaudeAppCommand(args, boot) {
|
|
|
7488
8282
|
const startingAlias = cloudRoutes[0].aliasId;
|
|
7489
8283
|
cloudCodeFavBackend = await startCloudCodeCatalogBackend(cloudRoutes, startingAlias, trace);
|
|
7490
8284
|
const favBackend = cloudCodeFavBackend;
|
|
7491
|
-
cloudCodeServerModels = cloudCodeFavoriteModels.map(
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
8285
|
+
cloudCodeServerModels = cloudCodeFavoriteModels.map(
|
|
8286
|
+
(model) => modelToServerModelInfo(model, antigravityProvider, {
|
|
8287
|
+
isFree: false,
|
|
8288
|
+
providerId: "antigravity",
|
|
8289
|
+
sourceBackend: "antigravity",
|
|
8290
|
+
modelFormat: "anthropic",
|
|
8291
|
+
cost: void 0,
|
|
8292
|
+
baseUrl: `http://127.0.0.1:${favBackend.port}`,
|
|
8293
|
+
completionsUrl: void 0,
|
|
8294
|
+
npm: void 0,
|
|
8295
|
+
apiBaseUrl: void 0,
|
|
8296
|
+
apiKey: favBackend.token,
|
|
8297
|
+
authType: void 0,
|
|
8298
|
+
oauthAccountId: void 0,
|
|
8299
|
+
headers: void 0
|
|
8300
|
+
})
|
|
8301
|
+
);
|
|
7506
8302
|
}
|
|
7507
8303
|
const regularLocalProviders = providersForTarget(catalog, "claude-app");
|
|
7508
8304
|
const regularAllModels = regularLocalProviders.flatMap(
|
|
@@ -7517,21 +8313,71 @@ async function runClaudeAppCommand(args, boot) {
|
|
|
7517
8313
|
seen.add(key);
|
|
7518
8314
|
return true;
|
|
7519
8315
|
});
|
|
8316
|
+
} else if (useProviderAll) {
|
|
8317
|
+
const routableProvider = providersForTarget(catalog, "claude-app").find(
|
|
8318
|
+
(lp) => lp.id === activeProvider.id
|
|
8319
|
+
);
|
|
8320
|
+
const allServerModels = localProvidersToServerModels(
|
|
8321
|
+
routableProvider ? [routableProvider] : [activeProvider]
|
|
8322
|
+
);
|
|
8323
|
+
const cloudCodeIndices = allServerModels.map((m, i) => m.modelFormat === "cloud-code" ? i : -1).filter((i) => i >= 0);
|
|
8324
|
+
if (cloudCodeIndices.length > 0 && activeProvider.apiKey) {
|
|
8325
|
+
const providerData = activeProvider.providerData ?? {};
|
|
8326
|
+
const cloudCodeModels = cloudCodeIndices.map((i) => allServerModels[i]);
|
|
8327
|
+
const cloudRoutes = cloudCodeModels.map(
|
|
8328
|
+
(model) => buildCloudCodeProxyRoute(
|
|
8329
|
+
{ id: model.id, name: model.name, modelFormat: "cloud-code" },
|
|
8330
|
+
activeProvider.apiKey,
|
|
8331
|
+
providerData
|
|
8332
|
+
)
|
|
8333
|
+
);
|
|
8334
|
+
const startingAlias = cloudRoutes[0].aliasId;
|
|
8335
|
+
cloudCodeBackend = await startCloudCodeCatalogBackend(
|
|
8336
|
+
cloudRoutes,
|
|
8337
|
+
startingAlias,
|
|
8338
|
+
trace,
|
|
8339
|
+
"claude-desktop"
|
|
8340
|
+
);
|
|
8341
|
+
const backend = cloudCodeBackend;
|
|
8342
|
+
for (let idx of cloudCodeIndices) {
|
|
8343
|
+
const m = allServerModels[idx];
|
|
8344
|
+
allServerModels[idx] = {
|
|
8345
|
+
...m,
|
|
8346
|
+
modelFormat: "anthropic",
|
|
8347
|
+
baseUrl: `http://127.0.0.1:${backend.port}`,
|
|
8348
|
+
apiBaseUrl: void 0,
|
|
8349
|
+
apiKey: backend.token,
|
|
8350
|
+
completionsUrl: void 0,
|
|
8351
|
+
authType: void 0,
|
|
8352
|
+
oauthAccountId: void 0,
|
|
8353
|
+
headers: void 0
|
|
8354
|
+
};
|
|
8355
|
+
}
|
|
8356
|
+
}
|
|
8357
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8358
|
+
serverModels = allServerModels.filter((m) => {
|
|
8359
|
+
const key = `${m.providerId}:${m.id}`;
|
|
8360
|
+
if (seen.has(key)) return false;
|
|
8361
|
+
seen.add(key);
|
|
8362
|
+
return true;
|
|
8363
|
+
});
|
|
7520
8364
|
} else if (selectedModel.modelFormat === "cloud-code") {
|
|
7521
8365
|
const providerData = activeProvider.providerData ?? {};
|
|
7522
8366
|
const cloudRoute = buildCloudCodeProxyRoute(selectedModel, activeProvider.apiKey, providerData);
|
|
7523
8367
|
cloudCodeBackend = await startCloudCodeCatalogBackend([cloudRoute], cloudRoute.aliasId, trace);
|
|
7524
|
-
serverModels = [
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
|
|
8368
|
+
serverModels = [
|
|
8369
|
+
modelToServerModelInfo(selectedModel, activeProvider, {
|
|
8370
|
+
modelFormat: "anthropic",
|
|
8371
|
+
baseUrl: `http://127.0.0.1:${cloudCodeBackend.port}`,
|
|
8372
|
+
completionsUrl: void 0,
|
|
8373
|
+
npm: void 0,
|
|
8374
|
+
apiBaseUrl: void 0,
|
|
8375
|
+
apiKey: cloudCodeBackend.token,
|
|
8376
|
+
authType: void 0,
|
|
8377
|
+
oauthAccountId: void 0,
|
|
8378
|
+
headers: void 0
|
|
8379
|
+
})
|
|
8380
|
+
];
|
|
7535
8381
|
} else {
|
|
7536
8382
|
serverModels = [modelToServerModelInfo(selectedModel, activeProvider)];
|
|
7537
8383
|
}
|
|
@@ -7549,7 +8395,10 @@ async function runClaudeAppCommand(args, boot) {
|
|
|
7549
8395
|
catalog: createGatewayModelCatalog(serverModels, { maskGatewayIds: true }),
|
|
7550
8396
|
backends: BACKENDS,
|
|
7551
8397
|
gateway: { maskGatewayIds: true },
|
|
7552
|
-
debugLogPath
|
|
8398
|
+
debugLogPath,
|
|
8399
|
+
// Claude Desktop embeds the gateway router rather than running
|
|
8400
|
+
// `anygate server`, so attribute its traffic to the app, not 'gateway'.
|
|
8401
|
+
app: "claude-desktop"
|
|
7553
8402
|
});
|
|
7554
8403
|
uuid = writeAnygateIConfig(proxyHandle.port);
|
|
7555
8404
|
writeSessionLock2({
|
|
@@ -7562,11 +8411,17 @@ async function runClaudeAppCommand(args, boot) {
|
|
|
7562
8411
|
setupExitCleanup(uuid);
|
|
7563
8412
|
if (!useFavorites) {
|
|
7564
8413
|
const prevRecent = prefs.recentModelsByProvider?.[activeProvider.id] ?? [];
|
|
7565
|
-
const updatedRecent = [
|
|
8414
|
+
const updatedRecent = [
|
|
8415
|
+
selectedModel.id,
|
|
8416
|
+
...prevRecent.filter((id) => id !== selectedModel.id)
|
|
8417
|
+
].slice(0, 3);
|
|
7566
8418
|
savePreferences({
|
|
7567
8419
|
lastCodexProvider: activeProvider.id,
|
|
7568
8420
|
lastCodexModel: selectedModel.id,
|
|
7569
|
-
recentModelsByProvider: {
|
|
8421
|
+
recentModelsByProvider: {
|
|
8422
|
+
...prefs.recentModelsByProvider,
|
|
8423
|
+
[activeProvider.id]: updatedRecent
|
|
8424
|
+
}
|
|
7570
8425
|
});
|
|
7571
8426
|
}
|
|
7572
8427
|
console.log(`
|
|
@@ -7580,6 +8435,10 @@ ${pc10.green("\u2714")} Proxy started on port ${proxyHandle.port}`);
|
|
|
7580
8435
|
${pc10.bold("Claude Desktop 3P Mode Active")}`);
|
|
7581
8436
|
if (useFavorites) {
|
|
7582
8437
|
console.log(`${pc10.dim("Catalog:")} Favorite models only`);
|
|
8438
|
+
} else if (useProviderAll) {
|
|
8439
|
+
console.log(
|
|
8440
|
+
`${pc10.dim("Catalog:")} All ${activeProvider.name} models (${serverModels.length})`
|
|
8441
|
+
);
|
|
7583
8442
|
} else {
|
|
7584
8443
|
console.log(`${pc10.dim("Model:")} ${selectedModel.id}`);
|
|
7585
8444
|
console.log(`${pc10.dim("Provider:")} ${activeProvider.name}`);
|
|
@@ -7612,7 +8471,7 @@ ${pc10.bold("Claude Desktop 3P Mode Active")}`);
|
|
|
7612
8471
|
// src/cli/claude-app.ts
|
|
7613
8472
|
async function handleClaudeAppCommand(parsed) {
|
|
7614
8473
|
if (parsed.showVersion) {
|
|
7615
|
-
const { VERSION: VERSION2 } = await import("./constants-
|
|
8474
|
+
const { VERSION: VERSION2 } = await import("./constants-WLMOLKEO.js");
|
|
7616
8475
|
console.log(VERSION2);
|
|
7617
8476
|
return 0;
|
|
7618
8477
|
}
|
|
@@ -7637,17 +8496,16 @@ This command launches the Claude Desktop app with anygate's provider registry.
|
|
|
7637
8496
|
}
|
|
7638
8497
|
return runClaudeAppCommand(parsed.claudeArgs ?? [], {
|
|
7639
8498
|
launchProvider: parsed.launchProvider,
|
|
7640
|
-
launchModel: parsed.launchModel
|
|
8499
|
+
launchModel: parsed.launchModel,
|
|
8500
|
+
launchAllModels: parsed.launchAllModels || parsed.launchModel === "All"
|
|
7641
8501
|
});
|
|
7642
8502
|
}
|
|
7643
8503
|
|
|
7644
8504
|
// src/apps/gemini/cli.ts
|
|
7645
8505
|
import pc11 from "picocolors";
|
|
7646
8506
|
import * as p13 from "@clack/prompts";
|
|
7647
|
-
init_config();
|
|
7648
8507
|
|
|
7649
8508
|
// src/apps/gemini/launch.ts
|
|
7650
|
-
init_config();
|
|
7651
8509
|
import { spawn as spawn2 } from "child_process";
|
|
7652
8510
|
import { existsSync as existsSync9, mkdirSync as mkdirSync6, mkdtempSync, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
|
|
7653
8511
|
import { homedir as homedir6, tmpdir } from "os";
|
|
@@ -7737,7 +8595,9 @@ function launchGemini(geminiPath, modelId, env, extraArgs) {
|
|
|
7737
8595
|
import * as p12 from "@clack/prompts";
|
|
7738
8596
|
async function pickGeminiProvider(providers, prefs, hasFavorites = false, initialProviderId) {
|
|
7739
8597
|
if (providers.length === 0 && !hasFavorites) return null;
|
|
7740
|
-
const options = providers.map(
|
|
8598
|
+
const options = providers.map(
|
|
8599
|
+
(lp) => providerSelectOption(lp)
|
|
8600
|
+
);
|
|
7741
8601
|
if (hasFavorites) {
|
|
7742
8602
|
options.unshift({
|
|
7743
8603
|
value: "__favorites__",
|
|
@@ -7854,7 +8714,8 @@ function rejectGeminiManagedFlags(geminiArgs) {
|
|
|
7854
8714
|
if (takesValue.has(arg)) i++;
|
|
7855
8715
|
continue;
|
|
7856
8716
|
}
|
|
7857
|
-
if (arg.startsWith("--model=") || arg.startsWith("--provider=") || arg.startsWith("-m="))
|
|
8717
|
+
if (arg.startsWith("--model=") || arg.startsWith("--provider=") || arg.startsWith("-m="))
|
|
8718
|
+
continue;
|
|
7858
8719
|
out.push(arg);
|
|
7859
8720
|
}
|
|
7860
8721
|
return out;
|
|
@@ -7889,7 +8750,9 @@ function lookupGeminiRoute(routes, requestedModel, defaultRoute) {
|
|
|
7889
8750
|
}
|
|
7890
8751
|
const fallback = defaultRoute ?? routes[0];
|
|
7891
8752
|
if (requestedModel !== fallback.aliasId) {
|
|
7892
|
-
console.error(
|
|
8753
|
+
console.error(
|
|
8754
|
+
`[gemini-proxy] model '${requestedModel}' not in catalog \u2014 remapping to default route '${fallback.aliasId}' (upstream: ${fallback.realModelId})`
|
|
8755
|
+
);
|
|
7893
8756
|
}
|
|
7894
8757
|
return fallback;
|
|
7895
8758
|
}
|
|
@@ -8037,7 +8900,9 @@ async function startGeminiProxy(routes, debug = false) {
|
|
|
8037
8900
|
const plog = debug ? makeTraceLogger(getGeminiProxyDebugLogPath()) : () => {
|
|
8038
8901
|
};
|
|
8039
8902
|
const onRejection = (reason) => {
|
|
8040
|
-
plog(
|
|
8903
|
+
plog(
|
|
8904
|
+
`Unhandled Rejection: ${reason instanceof Error ? reason.stack || reason.message : String(reason)}`
|
|
8905
|
+
);
|
|
8041
8906
|
};
|
|
8042
8907
|
const onException = (error) => {
|
|
8043
8908
|
plog(`Uncaught Exception: ${error.stack || error.message}`);
|
|
@@ -8117,7 +8982,7 @@ ${rawBody}`);
|
|
|
8117
8982
|
const modelCommand = parseModelCommand(lastUserTurn);
|
|
8118
8983
|
if (modelCommand !== null) {
|
|
8119
8984
|
if (modelCommand === "") {
|
|
8120
|
-
const current = sessionRouteOverride ??
|
|
8985
|
+
const current = sessionRouteOverride ?? lookupGeminiRoute(routes, requestedModel) ?? defaultRoute;
|
|
8121
8986
|
const availableList = routes.map((r) => ` - ${r.aliasId} (${r.displayName})`).join("\n");
|
|
8122
8987
|
const exampleId = routes.length > 1 ? routes[1].aliasId : routes[0]?.aliasId ?? "deepseek-v4";
|
|
8123
8988
|
const text4 = `Current model: ${current.displayName} (${current.aliasId})
|
|
@@ -8134,16 +8999,25 @@ Example: .model ${exampleId}`;
|
|
|
8134
8999
|
if (targetRoute) {
|
|
8135
9000
|
sessionRouteOverride = targetRoute;
|
|
8136
9001
|
plog(`.model switch: ${targetRoute.aliasId} (${targetRoute.realModelId})`);
|
|
8137
|
-
sendMockGeminiResponse(
|
|
9002
|
+
sendMockGeminiResponse(
|
|
9003
|
+
res,
|
|
9004
|
+
`\u2705 Switched model to ${targetRoute.displayName} (${targetRoute.aliasId})`,
|
|
9005
|
+
isStream,
|
|
9006
|
+
targetRoute.aliasId
|
|
9007
|
+
);
|
|
8138
9008
|
} else {
|
|
8139
9009
|
const available = routes.map((r) => r.aliasId).join(", ");
|
|
8140
|
-
sendMockGeminiResponse(
|
|
9010
|
+
sendMockGeminiResponse(
|
|
9011
|
+
res,
|
|
9012
|
+
`\u274C Model '${modelCommand}' not found.
|
|
8141
9013
|
|
|
8142
|
-
Available: ${available}`,
|
|
9014
|
+
Available: ${available}`,
|
|
9015
|
+
isStream
|
|
9016
|
+
);
|
|
8143
9017
|
}
|
|
8144
9018
|
return;
|
|
8145
9019
|
}
|
|
8146
|
-
const route = sessionRouteOverride ??
|
|
9020
|
+
const route = sessionRouteOverride ?? lookupGeminiRoute(routes, requestedModel) ?? defaultRoute;
|
|
8147
9021
|
plog(`Route selected: ${route.aliasId} (upstream model: ${route.realModelId})`);
|
|
8148
9022
|
body.contents = sanitizeModelSwitchTurns(body.contents || []);
|
|
8149
9023
|
const languageModel = await getOrInitModel(route);
|
|
@@ -8155,7 +9029,12 @@ Available: ${available}`, isStream);
|
|
|
8155
9029
|
params.providerOptions,
|
|
8156
9030
|
deepMergeProviderOptions(
|
|
8157
9031
|
thinkingProviderOptions(route.npm || "@ai-sdk/openai-compatible"),
|
|
8158
|
-
effortProviderOptions(
|
|
9032
|
+
effortProviderOptions(
|
|
9033
|
+
route.npm || "@ai-sdk/openai-compatible",
|
|
9034
|
+
"high",
|
|
9035
|
+
route.realModelId,
|
|
9036
|
+
route
|
|
9037
|
+
)
|
|
8159
9038
|
)
|
|
8160
9039
|
);
|
|
8161
9040
|
plog(`Translated SDK params:
|
|
@@ -8164,7 +9043,7 @@ ${JSON.stringify(params, null, 2)}`);
|
|
|
8164
9043
|
res.writeHead(200, {
|
|
8165
9044
|
"Content-Type": "text/event-stream",
|
|
8166
9045
|
"Cache-Control": "no-cache",
|
|
8167
|
-
|
|
9046
|
+
Connection: "keep-alive"
|
|
8168
9047
|
});
|
|
8169
9048
|
plog("Starting streamText...");
|
|
8170
9049
|
const { fullStream } = streamText2({
|
|
@@ -8179,10 +9058,12 @@ ${JSON.stringify(params, null, 2)}`);
|
|
|
8179
9058
|
if (isThinking && (p18.type === "tool-input-start" || p18.type === "tool-call" || p18.type === "finish")) {
|
|
8180
9059
|
isThinking = false;
|
|
8181
9060
|
const chunk = {
|
|
8182
|
-
candidates: [
|
|
9061
|
+
candidates: [
|
|
9062
|
+
{ content: { role: "model", parts: [{ text: `
|
|
8183
9063
|
</thinking>
|
|
8184
9064
|
|
|
8185
|
-
` }] } }
|
|
9065
|
+
` }] } }
|
|
9066
|
+
],
|
|
8186
9067
|
modelVersion: route.aliasId
|
|
8187
9068
|
};
|
|
8188
9069
|
res.write(`data: ${JSON.stringify(chunk)}
|
|
@@ -8213,12 +9094,14 @@ ${JSON.stringify(params, null, 2)}`);
|
|
|
8213
9094
|
` + text4;
|
|
8214
9095
|
}
|
|
8215
9096
|
const chunk = {
|
|
8216
|
-
candidates: [
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
|
|
9097
|
+
candidates: [
|
|
9098
|
+
{
|
|
9099
|
+
content: {
|
|
9100
|
+
role: "model",
|
|
9101
|
+
parts: [{ text: text4 }]
|
|
9102
|
+
}
|
|
8220
9103
|
}
|
|
8221
|
-
|
|
9104
|
+
],
|
|
8222
9105
|
modelVersion: route.aliasId
|
|
8223
9106
|
};
|
|
8224
9107
|
const data = `data: ${JSON.stringify(chunk)}
|
|
@@ -8237,14 +9120,18 @@ ${JSON.stringify(params, null, 2)}`);
|
|
|
8237
9120
|
const name = buf ? buf.name : p18.toolName;
|
|
8238
9121
|
plog(`Streaming tool call: ${name} with args: ${JSON.stringify(args)}`);
|
|
8239
9122
|
const chunk = {
|
|
8240
|
-
candidates: [
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
9123
|
+
candidates: [
|
|
9124
|
+
{
|
|
9125
|
+
content: {
|
|
9126
|
+
role: "model",
|
|
9127
|
+
parts: [
|
|
9128
|
+
{
|
|
9129
|
+
functionCall: { name, args }
|
|
9130
|
+
}
|
|
9131
|
+
]
|
|
9132
|
+
}
|
|
8246
9133
|
}
|
|
8247
|
-
|
|
9134
|
+
],
|
|
8248
9135
|
modelVersion: route.aliasId
|
|
8249
9136
|
};
|
|
8250
9137
|
res.write(`data: ${JSON.stringify(chunk)}
|
|
@@ -8252,9 +9139,11 @@ ${JSON.stringify(params, null, 2)}`);
|
|
|
8252
9139
|
`);
|
|
8253
9140
|
} else if (p18.type === "finish") {
|
|
8254
9141
|
const chunk = {
|
|
8255
|
-
candidates: [
|
|
8256
|
-
|
|
8257
|
-
|
|
9142
|
+
candidates: [
|
|
9143
|
+
{
|
|
9144
|
+
finishReason: mapFinishReason(p18.finishReason ?? "")
|
|
9145
|
+
}
|
|
9146
|
+
],
|
|
8258
9147
|
usageMetadata: {
|
|
8259
9148
|
promptTokenCount: p18.totalUsage?.inputTokens || 0,
|
|
8260
9149
|
candidatesTokenCount: p18.totalUsage?.outputTokens || 0
|
|
@@ -8295,13 +9184,15 @@ ${result.reasoning}
|
|
|
8295
9184
|
}
|
|
8296
9185
|
}
|
|
8297
9186
|
const response = {
|
|
8298
|
-
candidates: [
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
9187
|
+
candidates: [
|
|
9188
|
+
{
|
|
9189
|
+
content: {
|
|
9190
|
+
role: "model",
|
|
9191
|
+
parts
|
|
9192
|
+
},
|
|
9193
|
+
finishReason: mapFinishReason(result.finishReason ?? "")
|
|
9194
|
+
}
|
|
9195
|
+
],
|
|
8305
9196
|
usageMetadata: {
|
|
8306
9197
|
promptTokenCount: result.usage?.inputTokens || 0,
|
|
8307
9198
|
candidatesTokenCount: result.usage?.outputTokens || 0
|
|
@@ -8319,13 +9210,19 @@ ${JSON.stringify(response, null, 2)}`);
|
|
|
8319
9210
|
res.writeHead(404);
|
|
8320
9211
|
res.end("Not Found");
|
|
8321
9212
|
} catch (err) {
|
|
8322
|
-
plog(
|
|
9213
|
+
plog(
|
|
9214
|
+
`Error handling request: ${err instanceof Error ? err.stack || err.message : String(err)}`
|
|
9215
|
+
);
|
|
8323
9216
|
const errMsg = formatUpstreamError(err);
|
|
8324
9217
|
if (debug) {
|
|
8325
9218
|
console.error(`[Gemini Proxy] ${errMsg}`);
|
|
8326
9219
|
}
|
|
8327
9220
|
if (!res.headersSent) {
|
|
8328
|
-
sendMockGeminiResponse(
|
|
9221
|
+
sendMockGeminiResponse(
|
|
9222
|
+
res,
|
|
9223
|
+
`\u26A0 ${errMsg}`,
|
|
9224
|
+
req.url?.includes("streamGenerateContent") ?? false
|
|
9225
|
+
);
|
|
8329
9226
|
} else {
|
|
8330
9227
|
try {
|
|
8331
9228
|
writeGeminiStreamText(res, `\u26A0 ${errMsg}`);
|
|
@@ -8412,28 +9309,34 @@ function sendMockGeminiResponse(res, text4, isStream, modelVersion) {
|
|
|
8412
9309
|
res.writeHead(200, {
|
|
8413
9310
|
"Content-Type": "text/event-stream",
|
|
8414
9311
|
"Cache-Control": "no-cache",
|
|
8415
|
-
|
|
9312
|
+
Connection: "keep-alive"
|
|
8416
9313
|
});
|
|
8417
9314
|
writeGeminiStreamText(res, text4, modelVersion);
|
|
8418
9315
|
res.end();
|
|
8419
9316
|
} else {
|
|
8420
9317
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
8421
|
-
res.end(
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
|
|
8428
|
-
|
|
9318
|
+
res.end(
|
|
9319
|
+
JSON.stringify({
|
|
9320
|
+
candidates: [
|
|
9321
|
+
{
|
|
9322
|
+
content: { role: "model", parts: [{ text: text4 }] },
|
|
9323
|
+
finishReason: "STOP"
|
|
9324
|
+
}
|
|
9325
|
+
],
|
|
9326
|
+
usageMetadata: { promptTokenCount: 0, candidatesTokenCount: 0 },
|
|
9327
|
+
...modelVersion ? { modelVersion } : {}
|
|
9328
|
+
})
|
|
9329
|
+
);
|
|
8429
9330
|
}
|
|
8430
9331
|
}
|
|
8431
9332
|
function writeGeminiStreamText(res, text4, modelVersion) {
|
|
8432
9333
|
const chunk = {
|
|
8433
|
-
candidates: [
|
|
8434
|
-
|
|
8435
|
-
|
|
8436
|
-
|
|
9334
|
+
candidates: [
|
|
9335
|
+
{
|
|
9336
|
+
content: { role: "model", parts: [{ text: text4 }] },
|
|
9337
|
+
finishReason: "STOP"
|
|
9338
|
+
}
|
|
9339
|
+
],
|
|
8437
9340
|
usageMetadata: { promptTokenCount: 0, candidatesTokenCount: 0 },
|
|
8438
9341
|
...modelVersion ? { modelVersion } : {}
|
|
8439
9342
|
};
|
|
@@ -8487,7 +9390,8 @@ async function rewriteGeminiBackendRoutes(routes, launchModelId, trace) {
|
|
|
8487
9390
|
backendUrl: `http://127.0.0.1:${backend.port}`,
|
|
8488
9391
|
apiKey: backend.token
|
|
8489
9392
|
}),
|
|
8490
|
-
trace
|
|
9393
|
+
trace,
|
|
9394
|
+
"gemini"
|
|
8491
9395
|
);
|
|
8492
9396
|
if (!partitioned.backend) {
|
|
8493
9397
|
return { routes, launchModelId, backend: null };
|
|
@@ -8567,8 +9471,9 @@ async function runGeminiCommand(geminiArgs, trace = false, launch = {}) {
|
|
|
8567
9471
|
const agentStdout = wantsCleanAgentStdout("gemini", passthroughArgs);
|
|
8568
9472
|
setAgentStdoutMode(agentStdout);
|
|
8569
9473
|
const prefs = loadPreferences();
|
|
9474
|
+
const launchAllModels = Boolean(launch.launchAllModels || launch.launchModel === "All");
|
|
8570
9475
|
const launchPlan = planLaunchWizard({
|
|
8571
|
-
explicit: { providerId: launch.launchProvider, modelId: launch.launchModel },
|
|
9476
|
+
explicit: launchAllModels ? { providerId: launch.launchProvider, allModels: true } : { providerId: launch.launchProvider, modelId: launch.launchModel },
|
|
8572
9477
|
childArgs: passthroughArgs,
|
|
8573
9478
|
agent: "gemini",
|
|
8574
9479
|
prefs
|
|
@@ -8602,7 +9507,9 @@ Error: ${launchPlan.error}
|
|
|
8602
9507
|
const compatible = providersForTarget(providersForPicker(catalog), "gemini");
|
|
8603
9508
|
if (compatible.length === 0) {
|
|
8604
9509
|
p13.log.warn("No Gemini-compatible providers in your registry.");
|
|
8605
|
-
p13.log.info(
|
|
9510
|
+
p13.log.info(
|
|
9511
|
+
"Add a provider with anygate providers add, or sign in with anygate providers auth openai."
|
|
9512
|
+
);
|
|
8606
9513
|
return 0;
|
|
8607
9514
|
}
|
|
8608
9515
|
let activeProvider = compatible.find((lp) => lp.id === prefs.lastGeminiProvider) ?? compatible[0];
|
|
@@ -8611,7 +9518,6 @@ Error: ${launchPlan.error}
|
|
|
8611
9518
|
p13.log.error(`Provider "${activeProvider.name}" has no models available.`);
|
|
8612
9519
|
return 1;
|
|
8613
9520
|
}
|
|
8614
|
-
;
|
|
8615
9521
|
if (launchPlan.skip && launchPlan.target) {
|
|
8616
9522
|
const resolved = findProviderAndModel(compatible, launchPlan.target);
|
|
8617
9523
|
if (!resolved) {
|
|
@@ -8660,9 +9566,7 @@ Error: ${launchPlan.error}
|
|
|
8660
9566
|
recordLaunchSelection("gemini", activeProvider.id, selectedModel.id, prefs);
|
|
8661
9567
|
const launchApiKey = await resolveLocalProviderApiKey(activeProvider);
|
|
8662
9568
|
if (!launchApiKey?.trim()) {
|
|
8663
|
-
p13.log.error(
|
|
8664
|
-
new CredentialUnavailableError(activeProvider.id).userMessage
|
|
8665
|
-
);
|
|
9569
|
+
p13.log.error(new CredentialUnavailableError(activeProvider.id).userMessage);
|
|
8666
9570
|
return 1;
|
|
8667
9571
|
}
|
|
8668
9572
|
const providerRoutes = activeProvider.models.map((m) => ({
|
|
@@ -8764,6 +9668,13 @@ Error: ${launchPlan.error}
|
|
|
8764
9668
|
if (!agentStdout) {
|
|
8765
9669
|
p13.log.info(`Gemini proxy started on port ${proxyHandle.port}`);
|
|
8766
9670
|
p13.log.info(`\u{1F4A1} Type ${pc11.bold(".model <id>")} in the chat to switch models mid-session.`);
|
|
9671
|
+
if (launchAllModels) {
|
|
9672
|
+
p13.log.info(
|
|
9673
|
+
pc11.dim(
|
|
9674
|
+
`All ${activeProvider.models.length} ${activeProvider.name} models are available \u2014 type .model <id> to switch.`
|
|
9675
|
+
)
|
|
9676
|
+
);
|
|
9677
|
+
}
|
|
8767
9678
|
}
|
|
8768
9679
|
let exitCode = 1;
|
|
8769
9680
|
try {
|
|
@@ -8785,7 +9696,7 @@ Error: ${launchPlan.error}
|
|
|
8785
9696
|
// src/cli/gemini.ts
|
|
8786
9697
|
async function handleGeminiCommand(parsed) {
|
|
8787
9698
|
if (parsed.showVersion) {
|
|
8788
|
-
const { VERSION: VERSION2 } = await import("./constants-
|
|
9699
|
+
const { VERSION: VERSION2 } = await import("./constants-WLMOLKEO.js");
|
|
8789
9700
|
console.log(VERSION2);
|
|
8790
9701
|
return 0;
|
|
8791
9702
|
}
|
|
@@ -8795,12 +9706,12 @@ async function handleGeminiCommand(parsed) {
|
|
|
8795
9706
|
}
|
|
8796
9707
|
return runGeminiCommand(parsed.claudeArgs ?? [], parsed.trace ?? false, {
|
|
8797
9708
|
launchProvider: parsed.launchProvider,
|
|
8798
|
-
launchModel: parsed.launchModel
|
|
9709
|
+
launchModel: parsed.launchModel,
|
|
9710
|
+
launchAllModels: parsed.launchAllModels || parsed.launchModel === "All"
|
|
8799
9711
|
});
|
|
8800
9712
|
}
|
|
8801
9713
|
|
|
8802
9714
|
// src/apps/gemini/antigravity.ts
|
|
8803
|
-
init_config();
|
|
8804
9715
|
import pc12 from "picocolors";
|
|
8805
9716
|
import * as p14 from "@clack/prompts";
|
|
8806
9717
|
import { appendFileSync as appendFileSync2 } from "fs";
|
|
@@ -9085,7 +9996,9 @@ function evaluateAgySwitchCompatibility(opts) {
|
|
|
9085
9996
|
const shapeMatches = validation.warnings.length === 0 && validation.switchSlots.length > 0;
|
|
9086
9997
|
const warnings = [];
|
|
9087
9998
|
if (opts.versionReadError) {
|
|
9088
|
-
warnings.push(
|
|
9999
|
+
warnings.push(
|
|
10000
|
+
`Could not read agy --version (${opts.versionReadError}); validating AGY fixture shape instead.`
|
|
10001
|
+
);
|
|
9089
10002
|
}
|
|
9090
10003
|
if (opts.version && KNOWN_INCOMPATIBLE_AGY_VERSIONS.has(opts.version)) {
|
|
9091
10004
|
return {
|
|
@@ -9109,9 +10022,13 @@ function evaluateAgySwitchCompatibility(opts) {
|
|
|
9109
10022
|
};
|
|
9110
10023
|
}
|
|
9111
10024
|
if (opts.version && !KNOWN_COMPATIBLE_AGY_VERSIONS.has(opts.version)) {
|
|
9112
|
-
warnings.push(
|
|
10025
|
+
warnings.push(
|
|
10026
|
+
`Unvalidated AGY version ${opts.version}; fixture shape matches, so multi-model switching remains enabled.`
|
|
10027
|
+
);
|
|
9113
10028
|
} else if (!opts.version && !opts.versionReadError) {
|
|
9114
|
-
warnings.push(
|
|
10029
|
+
warnings.push(
|
|
10030
|
+
"AGY version is unknown; fixture shape matches, so multi-model switching remains enabled."
|
|
10031
|
+
);
|
|
9115
10032
|
}
|
|
9116
10033
|
return {
|
|
9117
10034
|
mode: "multi-model",
|
|
@@ -9169,10 +10086,7 @@ function withCascadeCheckpointer(entry, maxTokenLimit = 128e3) {
|
|
|
9169
10086
|
function applyRouteContextBounds(entry, route) {
|
|
9170
10087
|
const maxTokenLimit = route.contextWindow ?? 128e3;
|
|
9171
10088
|
const maxOutputTokens = Math.min(entry.maxOutputTokens ?? 65536, maxTokenLimit);
|
|
9172
|
-
const checkpointTokenLimit = Math.min(
|
|
9173
|
-
128e3,
|
|
9174
|
-
Math.max(1, maxTokenLimit - maxOutputTokens)
|
|
9175
|
-
);
|
|
10089
|
+
const checkpointTokenLimit = Math.min(128e3, Math.max(1, maxTokenLimit - maxOutputTokens));
|
|
9176
10090
|
entry.maxTokens = maxTokenLimit;
|
|
9177
10091
|
entry.maxOutputTokens = maxOutputTokens;
|
|
9178
10092
|
entry.supportsImages = route.inputTypes?.includes("image") ?? false;
|
|
@@ -9255,7 +10169,9 @@ function injectGatewayModels(fixture, routes, templateKey) {
|
|
|
9255
10169
|
if (routes.length > 0) {
|
|
9256
10170
|
result.models[GATEWAY_CASCADE_ANCHOR_ID] ??= structuredClone(template);
|
|
9257
10171
|
result.models[GATEWAY_CASCADE_FALLBACK_ID] ??= structuredClone(GATEWAY_CASCADE_FALLBACK_ENTRY);
|
|
9258
|
-
result.models[GATEWAY_CASCADE_INTENT_MODEL_ID] ??= structuredClone(
|
|
10172
|
+
result.models[GATEWAY_CASCADE_INTENT_MODEL_ID] ??= structuredClone(
|
|
10173
|
+
GATEWAY_CASCADE_INTENT_MODEL_ENTRY
|
|
10174
|
+
);
|
|
9259
10175
|
if (!result.models[GATEWAY_CASCADE_PLAN_ANCHOR_ID]) {
|
|
9260
10176
|
const planAnchor = withCascadeCheckpointer(structuredClone(template));
|
|
9261
10177
|
planAnchor.model = GATEWAY_CASCADE_PLAN_MODEL;
|
|
@@ -9274,9 +10190,11 @@ function injectGatewayModels(fixture, routes, templateKey) {
|
|
|
9274
10190
|
result.agentModelSorts = [
|
|
9275
10191
|
{
|
|
9276
10192
|
displayName: "Recommended",
|
|
9277
|
-
groups: [
|
|
9278
|
-
|
|
9279
|
-
|
|
10193
|
+
groups: [
|
|
10194
|
+
{
|
|
10195
|
+
modelIds: slots.map((slot) => slot.slotId)
|
|
10196
|
+
}
|
|
10197
|
+
]
|
|
9280
10198
|
}
|
|
9281
10199
|
];
|
|
9282
10200
|
return result;
|
|
@@ -9321,6 +10239,7 @@ function buildAntigravityRoutes(resolvedFavorites, maxRoutes = MAX_MODEL_CATALOG
|
|
|
9321
10239
|
...fav.authType ? { authType: fav.authType } : {},
|
|
9322
10240
|
...fav.oauthAccountId ? { oauthAccountId: fav.oauthAccountId } : {},
|
|
9323
10241
|
...fav.providerData ? { providerData: fav.providerData } : {},
|
|
10242
|
+
...fav.headers ? { headers: fav.headers } : {},
|
|
9324
10243
|
baseURL,
|
|
9325
10244
|
contextWindow,
|
|
9326
10245
|
inputTypes
|
|
@@ -10603,8 +11522,16 @@ async function startCloudCodeGateway(routes, opts = {}) {
|
|
|
10603
11522
|
if (trace) log17(`[gateway] active route: ${route.catalogId} via ${model}`);
|
|
10604
11523
|
}
|
|
10605
11524
|
if (isCloudCodeOAuthRoute(route)) {
|
|
10606
|
-
handleCloudCodeForwardRequest(
|
|
10607
|
-
|
|
11525
|
+
handleCloudCodeForwardRequest(
|
|
11526
|
+
res,
|
|
11527
|
+
route,
|
|
11528
|
+
parsed,
|
|
11529
|
+
lowerUrl,
|
|
11530
|
+
log17
|
|
11531
|
+
).catch((err) => {
|
|
11532
|
+
log17(
|
|
11533
|
+
`[gateway] cloud-code forward error: ${err instanceof Error ? err.stack || err.message : String(err)}`
|
|
11534
|
+
);
|
|
10608
11535
|
if (!res.headersSent) {
|
|
10609
11536
|
respondJson(res, 500, { error: { code: 500, message: formatUpstreamError(err) } });
|
|
10610
11537
|
} else if (!res.writableEnded) {
|
|
@@ -10616,7 +11543,11 @@ async function startCloudCodeGateway(routes, opts = {}) {
|
|
|
10616
11543
|
const baseProviderOptions = providerOptionsCache.get(route.catalogId);
|
|
10617
11544
|
const isStream = lowerUrl.includes("stream");
|
|
10618
11545
|
const conversationKey = conversationKeyFromRequest(parsed);
|
|
10619
|
-
const requestOptions = reasoningEchoOptionsForRoute(
|
|
11546
|
+
const requestOptions = reasoningEchoOptionsForRoute(
|
|
11547
|
+
route,
|
|
11548
|
+
parsed,
|
|
11549
|
+
reasoningEchoesByConversation
|
|
11550
|
+
);
|
|
10620
11551
|
const rememberReasoning = (reasoning) => {
|
|
10621
11552
|
if (!shouldEchoReasoningForRoute(route)) return;
|
|
10622
11553
|
rememberReasoningEcho(reasoningEchoesByConversation, conversationKey, reasoning);
|
|
@@ -10626,7 +11557,9 @@ async function startCloudCodeGateway(routes, opts = {}) {
|
|
|
10626
11557
|
requestOptions,
|
|
10627
11558
|
onReasoningWithToolCall: rememberReasoning
|
|
10628
11559
|
}).catch((err) => {
|
|
10629
|
-
log17(
|
|
11560
|
+
log17(
|
|
11561
|
+
`[gateway] stream error: ${err instanceof Error ? err.stack || err.message : String(err)}`
|
|
11562
|
+
);
|
|
10630
11563
|
if (!res.headersSent) {
|
|
10631
11564
|
respondJson(res, 500, { error: { code: 500, message: formatUpstreamError(err) } });
|
|
10632
11565
|
} else if (!res.writableEnded) {
|
|
@@ -10638,7 +11571,9 @@ async function startCloudCodeGateway(routes, opts = {}) {
|
|
|
10638
11571
|
requestOptions,
|
|
10639
11572
|
onReasoningWithToolCall: rememberReasoning
|
|
10640
11573
|
}).catch((err) => {
|
|
10641
|
-
log17(
|
|
11574
|
+
log17(
|
|
11575
|
+
`[gateway] unary error: ${err instanceof Error ? err.stack || err.message : String(err)}`
|
|
11576
|
+
);
|
|
10642
11577
|
if (!res.headersSent) {
|
|
10643
11578
|
respondJson(res, 500, { error: { code: 500, message: formatUpstreamError(err) } });
|
|
10644
11579
|
}
|
|
@@ -10659,7 +11594,13 @@ async function startCloudCodeGateway(routes, opts = {}) {
|
|
|
10659
11594
|
return;
|
|
10660
11595
|
}
|
|
10661
11596
|
if (lowerUrl.includes("userquota")) {
|
|
10662
|
-
respondJson(res, 200, {
|
|
11597
|
+
respondJson(res, 200, {
|
|
11598
|
+
quotaSummary: {
|
|
11599
|
+
remainingQueries: 9999,
|
|
11600
|
+
totalQueries: 9999,
|
|
11601
|
+
quotaType: "GATEWAY_UNLIMITED"
|
|
11602
|
+
}
|
|
11603
|
+
});
|
|
10663
11604
|
return;
|
|
10664
11605
|
}
|
|
10665
11606
|
if (lowerUrl.includes("userinfo")) {
|
|
@@ -10738,7 +11679,12 @@ async function startCloudCodeGateway(routes, opts = {}) {
|
|
|
10738
11679
|
}
|
|
10739
11680
|
respondJson(res, 200, {});
|
|
10740
11681
|
}).catch((err) => {
|
|
10741
|
-
respondJson(res, 400, {
|
|
11682
|
+
respondJson(res, 400, {
|
|
11683
|
+
error: {
|
|
11684
|
+
code: 400,
|
|
11685
|
+
message: `Failed to read request: ${err instanceof Error ? err.message : String(err)}`
|
|
11686
|
+
}
|
|
11687
|
+
});
|
|
10742
11688
|
});
|
|
10743
11689
|
});
|
|
10744
11690
|
return new Promise((resolve, reject2) => {
|
|
@@ -11012,10 +11958,13 @@ function respondJson(res, status, data) {
|
|
|
11012
11958
|
res.end(body);
|
|
11013
11959
|
}
|
|
11014
11960
|
async function handleStreamingRequest(res, route, providerOptions, parsed, log17, options = {}) {
|
|
11015
|
-
const sdkParams = applyClaudeCodeOAuthIdentity(
|
|
11016
|
-
|
|
11017
|
-
|
|
11018
|
-
|
|
11961
|
+
const sdkParams = applyClaudeCodeOAuthIdentity(
|
|
11962
|
+
route,
|
|
11963
|
+
translateRequest(parsed, {
|
|
11964
|
+
...options.requestOptions,
|
|
11965
|
+
maxTools: maxToolsForNpm(route.npm)
|
|
11966
|
+
})
|
|
11967
|
+
);
|
|
11019
11968
|
const effectiveProviderOptions = deepMergeProviderOptions(
|
|
11020
11969
|
providerOptions,
|
|
11021
11970
|
sdkParams.providerOptions
|
|
@@ -11028,7 +11977,8 @@ async function handleStreamingRequest(res, route, providerOptions, parsed, log17
|
|
|
11028
11977
|
providerId: route.providerId,
|
|
11029
11978
|
authType: route.authType,
|
|
11030
11979
|
oauthAccountId: route.oauthAccountId,
|
|
11031
|
-
providerData: route.providerData
|
|
11980
|
+
providerData: route.providerData,
|
|
11981
|
+
headers: route.headers
|
|
11032
11982
|
});
|
|
11033
11983
|
const responseId = `gateway-${Date.now()}`;
|
|
11034
11984
|
const { fullStream } = streamText3({
|
|
@@ -11148,10 +12098,13 @@ async function handleStreamingRequest(res, route, providerOptions, parsed, log17
|
|
|
11148
12098
|
res.end();
|
|
11149
12099
|
}
|
|
11150
12100
|
async function handleUnaryRequest(res, route, providerOptions, parsed, _log, options = {}) {
|
|
11151
|
-
const sdkParams = applyClaudeCodeOAuthIdentity(
|
|
11152
|
-
|
|
11153
|
-
|
|
11154
|
-
|
|
12101
|
+
const sdkParams = applyClaudeCodeOAuthIdentity(
|
|
12102
|
+
route,
|
|
12103
|
+
translateRequest(parsed, {
|
|
12104
|
+
...options.requestOptions,
|
|
12105
|
+
maxTools: maxToolsForNpm(route.npm)
|
|
12106
|
+
})
|
|
12107
|
+
);
|
|
11155
12108
|
const effectiveProviderOptions = deepMergeProviderOptions(
|
|
11156
12109
|
providerOptions,
|
|
11157
12110
|
sdkParams.providerOptions
|
|
@@ -11164,7 +12117,8 @@ async function handleUnaryRequest(res, route, providerOptions, parsed, _log, opt
|
|
|
11164
12117
|
providerId: route.providerId,
|
|
11165
12118
|
authType: route.authType,
|
|
11166
12119
|
oauthAccountId: route.oauthAccountId,
|
|
11167
|
-
providerData: route.providerData
|
|
12120
|
+
providerData: route.providerData,
|
|
12121
|
+
headers: route.headers
|
|
11168
12122
|
});
|
|
11169
12123
|
const responseId = `gateway-${Date.now()}`;
|
|
11170
12124
|
const result = await generateText3({
|
|
@@ -11186,7 +12140,10 @@ async function handleUnaryRequest(res, route, providerOptions, parsed, _log, opt
|
|
|
11186
12140
|
if (result.toolCalls?.length) {
|
|
11187
12141
|
for (const tc of result.toolCalls) {
|
|
11188
12142
|
parts.push({
|
|
11189
|
-
functionCall: {
|
|
12143
|
+
functionCall: {
|
|
12144
|
+
name: tc.toolName,
|
|
12145
|
+
args: normalizeFunctionCallArgs(tc.input)
|
|
12146
|
+
}
|
|
11190
12147
|
});
|
|
11191
12148
|
}
|
|
11192
12149
|
}
|
|
@@ -11197,10 +12154,12 @@ async function handleUnaryRequest(res, route, providerOptions, parsed, _log, opt
|
|
|
11197
12154
|
parts.push({ text: "" });
|
|
11198
12155
|
}
|
|
11199
12156
|
const response = {
|
|
11200
|
-
candidates: [
|
|
11201
|
-
|
|
11202
|
-
|
|
11203
|
-
|
|
12157
|
+
candidates: [
|
|
12158
|
+
{
|
|
12159
|
+
content: { role: "model", parts },
|
|
12160
|
+
finishReason: mapFinishReason2(result.finishReason ?? "")
|
|
12161
|
+
}
|
|
12162
|
+
],
|
|
11204
12163
|
usageMetadata: {
|
|
11205
12164
|
promptTokenCount: result.usage?.inputTokens || 0,
|
|
11206
12165
|
candidatesTokenCount: result.usage?.outputTokens || 0,
|
|
@@ -11233,7 +12192,8 @@ async function resolveAntigravityLaunchRoutes(opts) {
|
|
|
11233
12192
|
apiKey,
|
|
11234
12193
|
authType: opts.provider.authType,
|
|
11235
12194
|
oauthAccountId: opts.provider.oauthAccountId,
|
|
11236
|
-
providerData: opts.provider.providerData
|
|
12195
|
+
providerData: opts.provider.providerData,
|
|
12196
|
+
headers: opts.provider.headers
|
|
11237
12197
|
};
|
|
11238
12198
|
const ctx = {
|
|
11239
12199
|
agent: "antigravity",
|
|
@@ -11260,7 +12220,6 @@ async function resolveAntigravityLaunchRoutes(opts) {
|
|
|
11260
12220
|
}
|
|
11261
12221
|
|
|
11262
12222
|
// src/gateway/antigravity/launch-cli.ts
|
|
11263
|
-
init_config();
|
|
11264
12223
|
import { execFileSync as execFileSync2, execSync as execSync2, spawn as spawn3 } from "child_process";
|
|
11265
12224
|
import { existsSync as existsSync10 } from "fs";
|
|
11266
12225
|
import { homedir as homedir7 } from "os";
|
|
@@ -11435,7 +12394,6 @@ function prepareIdeProfile(profileDir, gatewayUrl, isIDE) {
|
|
|
11435
12394
|
}
|
|
11436
12395
|
|
|
11437
12396
|
// src/gateway/antigravity/launch-ide.ts
|
|
11438
|
-
init_config();
|
|
11439
12397
|
function sleep(ms) {
|
|
11440
12398
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11441
12399
|
}
|
|
@@ -11486,14 +12444,20 @@ function defaultProcessList() {
|
|
|
11486
12444
|
}
|
|
11487
12445
|
}
|
|
11488
12446
|
function isAntigravityIdeRunning(profileDir, processList = defaultProcessList) {
|
|
11489
|
-
if (process.platform === "win32")
|
|
12447
|
+
if (process.platform === "win32")
|
|
12448
|
+
return winIsProcessRunningForProfile("Antigravity IDE.exe", profileDir);
|
|
11490
12449
|
const output = processList();
|
|
11491
|
-
return output.split("\n").some(
|
|
12450
|
+
return output.split("\n").some(
|
|
12451
|
+
(line2) => line2.includes("Antigravity IDE.app") && line2.includes(`--user-data-dir=${profileDir}`)
|
|
12452
|
+
);
|
|
11492
12453
|
}
|
|
11493
12454
|
function isAntigravityAppRunning(profileDir, processList = defaultProcessList) {
|
|
11494
|
-
if (process.platform === "win32")
|
|
12455
|
+
if (process.platform === "win32")
|
|
12456
|
+
return winIsProcessRunningForProfile("Antigravity.exe", profileDir);
|
|
11495
12457
|
const output = processList();
|
|
11496
|
-
return output.split("\n").some(
|
|
12458
|
+
return output.split("\n").some(
|
|
12459
|
+
(line2) => line2.includes("Antigravity.app") && line2.includes(`--user-data-dir=${profileDir}`)
|
|
12460
|
+
);
|
|
11497
12461
|
}
|
|
11498
12462
|
async function waitForAntigravityIdeQuit(profileDir, options = {}) {
|
|
11499
12463
|
const processList = options.processList ?? defaultProcessList;
|
|
@@ -11564,7 +12528,14 @@ function findAntigravityAppBinary() {
|
|
|
11564
12528
|
if (process.platform !== "darwin") return null;
|
|
11565
12529
|
const defaultPath = "/Applications/Antigravity.app/Contents/MacOS/Antigravity";
|
|
11566
12530
|
if (existsSync11(defaultPath)) return defaultPath;
|
|
11567
|
-
const homePath = join11(
|
|
12531
|
+
const homePath = join11(
|
|
12532
|
+
homedir9(),
|
|
12533
|
+
"Applications",
|
|
12534
|
+
"Antigravity.app",
|
|
12535
|
+
"Contents",
|
|
12536
|
+
"MacOS",
|
|
12537
|
+
"Antigravity"
|
|
12538
|
+
);
|
|
11568
12539
|
if (existsSync11(homePath)) return homePath;
|
|
11569
12540
|
return null;
|
|
11570
12541
|
}
|
|
@@ -11579,7 +12550,16 @@ function findAntigravityIdeBinary() {
|
|
|
11579
12550
|
if (process.platform !== "darwin") return null;
|
|
11580
12551
|
const defaultPath = "/Applications/Antigravity IDE.app/Contents/Resources/app/bin/antigravity-ide";
|
|
11581
12552
|
if (existsSync11(defaultPath)) return defaultPath;
|
|
11582
|
-
const homePath = join11(
|
|
12553
|
+
const homePath = join11(
|
|
12554
|
+
homedir9(),
|
|
12555
|
+
"Applications",
|
|
12556
|
+
"Antigravity IDE.app",
|
|
12557
|
+
"Contents",
|
|
12558
|
+
"Resources",
|
|
12559
|
+
"app",
|
|
12560
|
+
"bin",
|
|
12561
|
+
"antigravity-ide"
|
|
12562
|
+
);
|
|
11583
12563
|
if (existsSync11(homePath)) return homePath;
|
|
11584
12564
|
return null;
|
|
11585
12565
|
}
|
|
@@ -11599,10 +12579,7 @@ function launchAntigravityApp(env, profileDir, gatewayUrl, extraArgs) {
|
|
|
11599
12579
|
return;
|
|
11600
12580
|
}
|
|
11601
12581
|
prepareIdeProfile(profileDir, gatewayUrl, false);
|
|
11602
|
-
const args = [
|
|
11603
|
-
`--user-data-dir=${profileDir}`,
|
|
11604
|
-
...extraArgs
|
|
11605
|
-
];
|
|
12582
|
+
const args = [`--user-data-dir=${profileDir}`, ...extraArgs];
|
|
11606
12583
|
const child = spawn4(binaryPath, args, {
|
|
11607
12584
|
stdio: "inherit",
|
|
11608
12585
|
env
|
|
@@ -11702,7 +12679,9 @@ function resolveAntigravityBootModel(provider, modelSelector) {
|
|
|
11702
12679
|
};
|
|
11703
12680
|
}
|
|
11704
12681
|
async function pickAntigravityCliFavoriteLaunchModel(favorites, allProviders) {
|
|
11705
|
-
const resolved = favorites.map((favorite) => resolveFavoriteModel(favorite, allProviders)).filter(
|
|
12682
|
+
const resolved = favorites.map((favorite) => resolveFavoriteModel(favorite, allProviders)).filter(
|
|
12683
|
+
(entry) => entry !== null
|
|
12684
|
+
);
|
|
11706
12685
|
if (resolved.length === 0) {
|
|
11707
12686
|
p14.log.warn("No Antigravity CLI favorites are available.");
|
|
11708
12687
|
p14.log.info(pc12.dim("Manage them with `anygate favorites --agy`."));
|
|
@@ -11743,6 +12722,15 @@ async function resolveAntigravityLaunch(prefs, boot) {
|
|
|
11743
12722
|
p14.log.info(pc12.dim("Run anygate providers add or import to get started."));
|
|
11744
12723
|
return null;
|
|
11745
12724
|
}
|
|
12725
|
+
if (boot?.launchProvider && boot?.launchAllModels) {
|
|
12726
|
+
const provider = allProviders.find((p18) => p18.id === boot.launchProvider);
|
|
12727
|
+
if (!provider) {
|
|
12728
|
+
p14.log.error(`Provider not found: ${boot.launchProvider}`);
|
|
12729
|
+
return null;
|
|
12730
|
+
}
|
|
12731
|
+
const model = provider.models[0];
|
|
12732
|
+
return { provider, model, allProviders, allModels: true };
|
|
12733
|
+
}
|
|
11746
12734
|
if (boot?.launchProvider && boot?.launchModel) {
|
|
11747
12735
|
const provider = allProviders.find((p18) => p18.id === boot.launchProvider);
|
|
11748
12736
|
if (!provider) {
|
|
@@ -11799,11 +12787,15 @@ async function resolveAntigravityLaunch(prefs, boot) {
|
|
|
11799
12787
|
}
|
|
11800
12788
|
}
|
|
11801
12789
|
async function resolveAndBuildRoutes(provider, model, allProviders, prefs, opts) {
|
|
12790
|
+
const allModelsFavorites = opts.allModels ? provider.models.map((m) => ({
|
|
12791
|
+
providerId: provider.id,
|
|
12792
|
+
modelId: m.id
|
|
12793
|
+
})) : [];
|
|
11802
12794
|
const result = await resolveAntigravityLaunchRoutes({
|
|
11803
12795
|
provider,
|
|
11804
12796
|
model,
|
|
11805
12797
|
allProviders,
|
|
11806
|
-
favorites: prefs.antigravityCliFavoriteModels ?? [],
|
|
12798
|
+
favorites: opts.allModels ? allModelsFavorites : prefs.antigravityCliFavoriteModels ?? [],
|
|
11807
12799
|
maxRoutes: opts.maxRoutes
|
|
11808
12800
|
});
|
|
11809
12801
|
if (!result) {
|
|
@@ -11822,7 +12814,9 @@ async function resolveAndBuildRoutes(provider, model, allProviders, prefs, opts)
|
|
|
11822
12814
|
);
|
|
11823
12815
|
}
|
|
11824
12816
|
if (result.capacitySkippedFavorites.length > 0) {
|
|
11825
|
-
p14.log.warn(
|
|
12817
|
+
p14.log.warn(
|
|
12818
|
+
formatAgyCapacityWarning(opts.validatedSlotCount, result.capacitySkippedFavorites.length)
|
|
12819
|
+
);
|
|
11826
12820
|
p14.log.warn(
|
|
11827
12821
|
"Not exposed: " + result.capacitySkippedFavorites.map((fav) => `${fav.providerId}:${fav.modelId}`).join(", ")
|
|
11828
12822
|
);
|
|
@@ -11867,7 +12861,9 @@ async function runAntigravityCommand(intro, tracePrefix, trace, boot, launch, op
|
|
|
11867
12861
|
const prefs = loadPreferences();
|
|
11868
12862
|
gateIntro(intro);
|
|
11869
12863
|
if (tracePrefix === "agy" && (prefs.favoriteModels?.length ?? 0) > 0 && (prefs.antigravityCliFavoriteModels?.length ?? 0) === 0 && !prefs.antigravityCliFavoritesHintShown) {
|
|
11870
|
-
p14.log.info(
|
|
12864
|
+
p14.log.info(
|
|
12865
|
+
"Tip: AGY uses its own favorites list. Run `anygate favorites --agy` to set up switching."
|
|
12866
|
+
);
|
|
11871
12867
|
savePreferences({ antigravityCliFavoritesHintShown: true });
|
|
11872
12868
|
}
|
|
11873
12869
|
const agyFavorites = prefs.antigravityCliFavoriteModels ?? [];
|
|
@@ -11913,7 +12909,8 @@ async function launchWithSelection(selection, prefs, opts, trace, tracePrefix, b
|
|
|
11913
12909
|
maxRoutes: routeLimit,
|
|
11914
12910
|
validatedSlotCount: routeLimit,
|
|
11915
12911
|
pauseForCapacityWarning: opts.pauseForCapacityWarning ?? false,
|
|
11916
|
-
childArgs: opts.childArgs ?? []
|
|
12912
|
+
childArgs: opts.childArgs ?? [],
|
|
12913
|
+
allModels: selection.allModels
|
|
11917
12914
|
});
|
|
11918
12915
|
if (!routeResult) return 1;
|
|
11919
12916
|
savePreferences({
|
|
@@ -11953,7 +12950,12 @@ async function runAgyCommand(childArgs, trace = false, boot) {
|
|
|
11953
12950
|
trace,
|
|
11954
12951
|
boot,
|
|
11955
12952
|
(env, routes) => launchAntigravityCli(env, buildAgyLaunchArgs(routes[0].displayName, childArgs)),
|
|
11956
|
-
{
|
|
12953
|
+
{
|
|
12954
|
+
childArgs,
|
|
12955
|
+
versionGuard: true,
|
|
12956
|
+
pauseForCapacityWarning: true,
|
|
12957
|
+
useFavoritesCatalog: agyArgsIncludeFavoritesFlag(childArgs)
|
|
12958
|
+
}
|
|
11957
12959
|
);
|
|
11958
12960
|
}
|
|
11959
12961
|
async function runAntigravityAppCommand(childArgs, trace = false, boot) {
|
|
@@ -11970,7 +12972,9 @@ async function runAntigravityAppCommand(childArgs, trace = false, boot) {
|
|
|
11970
12972
|
initialValue: true
|
|
11971
12973
|
});
|
|
11972
12974
|
if (p14.isCancel(restart) || !restart) {
|
|
11973
|
-
p14.log.info(
|
|
12975
|
+
p14.log.info(
|
|
12976
|
+
"Quit and reopen Antigravity when you are ready for the new gateway to take effect."
|
|
12977
|
+
);
|
|
11974
12978
|
return 0;
|
|
11975
12979
|
}
|
|
11976
12980
|
quitAntigravityAppGracefully();
|
|
@@ -12001,7 +13005,12 @@ async function runAntigravityAppCommand(childArgs, trace = false, boot) {
|
|
|
12001
13005
|
}
|
|
12002
13006
|
return 0;
|
|
12003
13007
|
},
|
|
12004
|
-
{
|
|
13008
|
+
{
|
|
13009
|
+
childArgs,
|
|
13010
|
+
versionGuard: false,
|
|
13011
|
+
pauseForCapacityWarning: false,
|
|
13012
|
+
useFavoritesCatalog: agyArgsIncludeFavoritesFlag(childArgs)
|
|
13013
|
+
}
|
|
12005
13014
|
);
|
|
12006
13015
|
}
|
|
12007
13016
|
async function runAntigravityIdeCommand(childArgs, trace = false, boot) {
|
|
@@ -12018,7 +13027,9 @@ async function runAntigravityIdeCommand(childArgs, trace = false, boot) {
|
|
|
12018
13027
|
initialValue: true
|
|
12019
13028
|
});
|
|
12020
13029
|
if (p14.isCancel(restart) || !restart) {
|
|
12021
|
-
p14.log.info(
|
|
13030
|
+
p14.log.info(
|
|
13031
|
+
"Quit and reopen Antigravity IDE when you are ready for the new gateway to take effect."
|
|
13032
|
+
);
|
|
12022
13033
|
return 0;
|
|
12023
13034
|
}
|
|
12024
13035
|
quitAntigravityIdeGracefully();
|
|
@@ -12049,7 +13060,12 @@ async function runAntigravityIdeCommand(childArgs, trace = false, boot) {
|
|
|
12049
13060
|
}
|
|
12050
13061
|
return 0;
|
|
12051
13062
|
},
|
|
12052
|
-
{
|
|
13063
|
+
{
|
|
13064
|
+
childArgs,
|
|
13065
|
+
versionGuard: false,
|
|
13066
|
+
pauseForCapacityWarning: false,
|
|
13067
|
+
useFavoritesCatalog: agyArgsIncludeFavoritesFlag(childArgs)
|
|
13068
|
+
}
|
|
12053
13069
|
);
|
|
12054
13070
|
}
|
|
12055
13071
|
|
|
@@ -12139,7 +13155,7 @@ Examples:
|
|
|
12139
13155
|
`;
|
|
12140
13156
|
async function handleAgyCommand(parsed) {
|
|
12141
13157
|
if (parsed.showVersion) {
|
|
12142
|
-
const { VERSION: VERSION2 } = await import("./constants-
|
|
13158
|
+
const { VERSION: VERSION2 } = await import("./constants-WLMOLKEO.js");
|
|
12143
13159
|
console.log(VERSION2);
|
|
12144
13160
|
return 0;
|
|
12145
13161
|
}
|
|
@@ -12149,12 +13165,13 @@ async function handleAgyCommand(parsed) {
|
|
|
12149
13165
|
}
|
|
12150
13166
|
return runAgyCommand(parsed.claudeArgs ?? [], parsed.trace ?? false, {
|
|
12151
13167
|
launchProvider: parsed.launchProvider,
|
|
12152
|
-
launchModel: parsed.launchModel
|
|
13168
|
+
launchModel: parsed.launchModel,
|
|
13169
|
+
launchAllModels: parsed.launchAllModels || parsed.launchModel === "All"
|
|
12153
13170
|
});
|
|
12154
13171
|
}
|
|
12155
13172
|
async function handleAntigravityAppCommand(parsed) {
|
|
12156
13173
|
if (parsed.showVersion) {
|
|
12157
|
-
const { VERSION: VERSION2 } = await import("./constants-
|
|
13174
|
+
const { VERSION: VERSION2 } = await import("./constants-WLMOLKEO.js");
|
|
12158
13175
|
console.log(VERSION2);
|
|
12159
13176
|
return 0;
|
|
12160
13177
|
}
|
|
@@ -12164,12 +13181,13 @@ async function handleAntigravityAppCommand(parsed) {
|
|
|
12164
13181
|
}
|
|
12165
13182
|
return runAntigravityAppCommand(parsed.claudeArgs ?? [], parsed.trace ?? false, {
|
|
12166
13183
|
launchProvider: parsed.launchProvider,
|
|
12167
|
-
launchModel: parsed.launchModel
|
|
13184
|
+
launchModel: parsed.launchModel,
|
|
13185
|
+
launchAllModels: parsed.launchAllModels || parsed.launchModel === "All"
|
|
12168
13186
|
});
|
|
12169
13187
|
}
|
|
12170
13188
|
async function handleAntigravityIdeCommand(parsed) {
|
|
12171
13189
|
if (parsed.showVersion) {
|
|
12172
|
-
const { VERSION: VERSION2 } = await import("./constants-
|
|
13190
|
+
const { VERSION: VERSION2 } = await import("./constants-WLMOLKEO.js");
|
|
12173
13191
|
console.log(VERSION2);
|
|
12174
13192
|
return 0;
|
|
12175
13193
|
}
|
|
@@ -12179,7 +13197,8 @@ async function handleAntigravityIdeCommand(parsed) {
|
|
|
12179
13197
|
}
|
|
12180
13198
|
return runAntigravityIdeCommand(parsed.claudeArgs ?? [], parsed.trace ?? false, {
|
|
12181
13199
|
launchProvider: parsed.launchProvider,
|
|
12182
|
-
launchModel: parsed.launchModel
|
|
13200
|
+
launchModel: parsed.launchModel,
|
|
13201
|
+
launchAllModels: parsed.launchAllModels || parsed.launchModel === "All"
|
|
12183
13202
|
});
|
|
12184
13203
|
}
|
|
12185
13204
|
|
|
@@ -12274,12 +13293,11 @@ Options:
|
|
|
12274
13293
|
`);
|
|
12275
13294
|
return 0;
|
|
12276
13295
|
}
|
|
12277
|
-
const { runUiCommand } = await import("./command-
|
|
13296
|
+
const { runUiCommand } = await import("./command-XIDZGWNR.js");
|
|
12278
13297
|
return runUiCommand({ trace: parsed.trace });
|
|
12279
13298
|
}
|
|
12280
13299
|
|
|
12281
13300
|
// src/cli/models.ts
|
|
12282
|
-
init_config();
|
|
12283
13301
|
import pc14 from "picocolors";
|
|
12284
13302
|
import * as p16 from "@clack/prompts";
|
|
12285
13303
|
|
|
@@ -12287,7 +13305,7 @@ import * as p16 from "@clack/prompts";
|
|
|
12287
13305
|
import * as p15 from "@clack/prompts";
|
|
12288
13306
|
import pc13 from "picocolors";
|
|
12289
13307
|
|
|
12290
|
-
// src/apps/
|
|
13308
|
+
// src/apps/shared/favorites.ts
|
|
12291
13309
|
function isFavorite(list, fav) {
|
|
12292
13310
|
return list.some((f) => f.providerId === fav.providerId && f.modelId === fav.modelId);
|
|
12293
13311
|
}
|
|
@@ -12371,7 +13389,11 @@ async function pickGlobalFavoriteModel(providers, favorites, opts) {
|
|
|
12371
13389
|
message: "Add a favorite",
|
|
12372
13390
|
options: [
|
|
12373
13391
|
{ value: "back", label: pc13.cyan("\u2190 Back to favorites"), hint: "" },
|
|
12374
|
-
{
|
|
13392
|
+
{
|
|
13393
|
+
value: ADD_BY_PROVIDER,
|
|
13394
|
+
label: pc13.cyan("Browse by provider \u2192"),
|
|
13395
|
+
hint: "Pick one provider first"
|
|
13396
|
+
}
|
|
12375
13397
|
]
|
|
12376
13398
|
});
|
|
12377
13399
|
if (p15.isCancel(fallback) || fallback === "back") return null;
|
|
@@ -12398,7 +13420,9 @@ async function pickGlobalFavoriteModel(providers, favorites, opts) {
|
|
|
12398
13420
|
const picked = parseGlobalFavoritePickKey(result.id, matched);
|
|
12399
13421
|
if (!picked) continue;
|
|
12400
13422
|
if (isFavorite(favorites, { providerId: picked.providerId, modelId: picked.model.id })) {
|
|
12401
|
-
p15.log.warn(
|
|
13423
|
+
p15.log.warn(
|
|
13424
|
+
`${picked.model.name || picked.model.id} (${picked.providerName}) is already in your favorites.`
|
|
13425
|
+
);
|
|
12402
13426
|
continue;
|
|
12403
13427
|
}
|
|
12404
13428
|
return picked;
|
|
@@ -12427,7 +13451,9 @@ async function runModelsCommand(parsed) {
|
|
|
12427
13451
|
}));
|
|
12428
13452
|
if (favoriteProviders.length === 0) {
|
|
12429
13453
|
p16.log.warn("No providers found.");
|
|
12430
|
-
p16.log.info(
|
|
13454
|
+
p16.log.info(
|
|
13455
|
+
`OpenCode Zen/Go is always available. Add providers with ${pc14.cyan("anygate providers")}.`
|
|
13456
|
+
);
|
|
12431
13457
|
gateOutro("Done");
|
|
12432
13458
|
return 0;
|
|
12433
13459
|
}
|
|
@@ -12500,7 +13526,9 @@ async function runModelsCommand(parsed) {
|
|
|
12500
13526
|
}
|
|
12501
13527
|
}
|
|
12502
13528
|
if (addPath === "free") {
|
|
12503
|
-
const globalPick = await pickGlobalFavoriteModel(favoriteProviders, favorites, {
|
|
13529
|
+
const globalPick = await pickGlobalFavoriteModel(favoriteProviders, favorites, {
|
|
13530
|
+
freeOnly: true
|
|
13531
|
+
});
|
|
12504
13532
|
if (globalPick === null) continue;
|
|
12505
13533
|
if (globalPick !== ADD_BY_PROVIDER) {
|
|
12506
13534
|
provider = favoriteProviders.find((ap) => ap.id === globalPick.providerId);
|
|
@@ -12694,7 +13722,7 @@ async function runValidateSubcommand(parsed) {
|
|
|
12694
13722
|
// src/cli/providers.ts
|
|
12695
13723
|
async function handleProvidersCommand(parsed) {
|
|
12696
13724
|
if (parsed.showVersion) {
|
|
12697
|
-
const { VERSION: VERSION2 } = await import("./constants-
|
|
13725
|
+
const { VERSION: VERSION2 } = await import("./constants-WLMOLKEO.js");
|
|
12698
13726
|
console.log(VERSION2);
|
|
12699
13727
|
return 0;
|
|
12700
13728
|
}
|
|
@@ -12807,7 +13835,7 @@ async function runDoctorCommand(_dryRun) {
|
|
|
12807
13835
|
// src/cli/doctor.ts
|
|
12808
13836
|
async function handleDoctorCommand(parsed) {
|
|
12809
13837
|
if (parsed.showVersion) {
|
|
12810
|
-
const { VERSION: VERSION2 } = await import("./constants-
|
|
13838
|
+
const { VERSION: VERSION2 } = await import("./constants-WLMOLKEO.js");
|
|
12811
13839
|
console.log(VERSION2);
|
|
12812
13840
|
return 0;
|
|
12813
13841
|
}
|
|
@@ -12862,7 +13890,8 @@ function detectShell() {
|
|
|
12862
13890
|
if (shell.includes("zsh")) return "zsh";
|
|
12863
13891
|
if (shell.includes("bash")) return "bash";
|
|
12864
13892
|
if (shell.includes("fish")) return "fish";
|
|
12865
|
-
if (process.env["PSModulePath"] || process.env["POWERSHELL_DISTRIBUTION_CHANNEL"])
|
|
13893
|
+
if (process.env["PSModulePath"] || process.env["POWERSHELL_DISTRIBUTION_CHANNEL"])
|
|
13894
|
+
return "powershell";
|
|
12866
13895
|
return void 0;
|
|
12867
13896
|
}
|
|
12868
13897
|
function normalizeShell(input) {
|
|
@@ -12905,7 +13934,9 @@ _anygate "$@"
|
|
|
12905
13934
|
`;
|
|
12906
13935
|
}
|
|
12907
13936
|
function fishScript() {
|
|
12908
|
-
const lines = SUBCOMMANDS.map(
|
|
13937
|
+
const lines = SUBCOMMANDS.map(
|
|
13938
|
+
(c) => `complete -c anygate -n "not __fish_seen_subcommand_from ${SUBCOMMANDS.join(" ")}" -a ${c} -d 'anygate ${c}'`
|
|
13939
|
+
);
|
|
12909
13940
|
lines.push(`complete -c anygate -s h -l help -d 'Show help'`);
|
|
12910
13941
|
lines.push(`complete -c anygate -s v -l version -d 'Show version'`);
|
|
12911
13942
|
return `# anygate fish completion
|
|
@@ -12944,7 +13975,7 @@ function runCompletionsCommand(shellArg) {
|
|
|
12944
13975
|
// src/cli/completions.ts
|
|
12945
13976
|
async function handleCompletionsCommand(parsed) {
|
|
12946
13977
|
if (parsed.showVersion) {
|
|
12947
|
-
const { VERSION: VERSION2 } = await import("./constants-
|
|
13978
|
+
const { VERSION: VERSION2 } = await import("./constants-WLMOLKEO.js");
|
|
12948
13979
|
console.log(VERSION2);
|
|
12949
13980
|
return 0;
|
|
12950
13981
|
}
|
|
@@ -12971,18 +14002,11 @@ Examples:
|
|
|
12971
14002
|
|
|
12972
14003
|
// src/apps/shared/self-update.ts
|
|
12973
14004
|
import pc17 from "picocolors";
|
|
12974
|
-
import { spawn as spawn5
|
|
14005
|
+
import { spawn as spawn5 } from "child_process";
|
|
12975
14006
|
import * as p17 from "@clack/prompts";
|
|
12976
|
-
|
|
12977
|
-
|
|
12978
|
-
|
|
12979
|
-
const found = execFileSync4("where", ["npm"], { stdio: ["ignore", "pipe", "ignore"] }).toString().split(/\r?\n/).map((s) => s.trim()).find((s) => s.toLowerCase().endsWith(".cmd") || s.toLowerCase().endsWith("npm"));
|
|
12980
|
-
if (found) return found;
|
|
12981
|
-
} catch {
|
|
12982
|
-
}
|
|
12983
|
-
return "npm.cmd";
|
|
12984
|
-
}
|
|
12985
|
-
return "npm";
|
|
14007
|
+
var INSTALL_ARGS = ["install", "-g", "anygate@latest"];
|
|
14008
|
+
function resolveNpmSpawn() {
|
|
14009
|
+
return { bin: "npm", shell: process.platform === "win32" };
|
|
12986
14010
|
}
|
|
12987
14011
|
async function runUpdateCommand(dryRun) {
|
|
12988
14012
|
const update = await checkForUpdates();
|
|
@@ -12993,9 +14017,9 @@ async function runUpdateCommand(dryRun) {
|
|
|
12993
14017
|
p17.log.info(
|
|
12994
14018
|
`Update available: ${pc17.cyan(`v${update.currentVersion}`)} \u2192 ${pc17.green(`v${update.latestVersion}`)}`
|
|
12995
14019
|
);
|
|
12996
|
-
const npmBin =
|
|
14020
|
+
const { bin: npmBin, shell } = resolveNpmSpawn();
|
|
12997
14021
|
if (dryRun) {
|
|
12998
|
-
p17.log.step(`Would run: ${pc17.bold(`${npmBin}
|
|
14022
|
+
p17.log.step(`Would run: ${pc17.bold(`${npmBin} ${INSTALL_ARGS.join(" ")}`)}`);
|
|
12999
14023
|
p17.log.warn("Dry run \u2014 no changes made.");
|
|
13000
14024
|
return 0;
|
|
13001
14025
|
}
|
|
@@ -13007,23 +14031,35 @@ async function runUpdateCommand(dryRun) {
|
|
|
13007
14031
|
p17.log.info(`Update skipped. Run ${pc17.cyan(UPDATE_COMMAND)} later if you change your mind.`);
|
|
13008
14032
|
return 0;
|
|
13009
14033
|
}
|
|
13010
|
-
p17.log.info(`Running ${pc17.cyan(`${npmBin}
|
|
13011
|
-
const child = spawn5(npmBin, [
|
|
14034
|
+
p17.log.info(`Running ${pc17.cyan(`${npmBin} ${INSTALL_ARGS.join(" ")}`)}...`);
|
|
14035
|
+
const child = spawn5(npmBin, [...INSTALL_ARGS], {
|
|
13012
14036
|
stdio: "inherit",
|
|
14037
|
+
shell,
|
|
13013
14038
|
windowsHide: true
|
|
13014
14039
|
});
|
|
13015
14040
|
return new Promise((resolve) => {
|
|
14041
|
+
let settled = false;
|
|
14042
|
+
const settle = (code) => {
|
|
14043
|
+
settled = true;
|
|
14044
|
+
resolve(code);
|
|
14045
|
+
};
|
|
13016
14046
|
child.on("error", (err) => {
|
|
13017
|
-
|
|
13018
|
-
|
|
14047
|
+
if (settled) return;
|
|
14048
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
14049
|
+
p17.log.error(`Could not start npm: ${msg}`);
|
|
14050
|
+
p17.log.info(`Update anygate manually with: ${pc17.cyan(UPDATE_COMMAND)}`);
|
|
14051
|
+
settle(1);
|
|
13019
14052
|
});
|
|
13020
14053
|
child.on("close", (code) => {
|
|
14054
|
+
if (settled) return;
|
|
13021
14055
|
if (code === 0) {
|
|
13022
|
-
p17.log.success(
|
|
14056
|
+
p17.log.success(
|
|
14057
|
+
"anygate updated. Restart your shell or re-run anygate to use the new version."
|
|
14058
|
+
);
|
|
13023
14059
|
} else {
|
|
13024
14060
|
p17.log.error(`Update failed (exit ${code}). Try ${pc17.cyan(UPDATE_COMMAND)} manually.`);
|
|
13025
14061
|
}
|
|
13026
|
-
|
|
14062
|
+
settle(code ?? 1);
|
|
13027
14063
|
});
|
|
13028
14064
|
});
|
|
13029
14065
|
}
|
|
@@ -13031,7 +14067,7 @@ async function runUpdateCommand(dryRun) {
|
|
|
13031
14067
|
// src/cli/update.ts
|
|
13032
14068
|
async function handleUpdateCommand(parsed) {
|
|
13033
14069
|
if (parsed.showVersion) {
|
|
13034
|
-
const { VERSION: VERSION2 } = await import("./constants-
|
|
14070
|
+
const { VERSION: VERSION2 } = await import("./constants-WLMOLKEO.js");
|
|
13035
14071
|
console.log(VERSION2);
|
|
13036
14072
|
return 0;
|
|
13037
14073
|
}
|
|
@@ -13086,9 +14122,21 @@ registerCommand("completions", handleCompletionsCommand);
|
|
|
13086
14122
|
registerCommand("update", handleUpdateCommand);
|
|
13087
14123
|
|
|
13088
14124
|
// src/cli.ts
|
|
13089
|
-
var STARTER_CLAUDE_FLAGS = /* @__PURE__ */ new Set([
|
|
14125
|
+
var STARTER_CLAUDE_FLAGS = /* @__PURE__ */ new Set([
|
|
14126
|
+
"--dry-run",
|
|
14127
|
+
"--setup",
|
|
14128
|
+
"--trace",
|
|
14129
|
+
"--help",
|
|
14130
|
+
"-h",
|
|
14131
|
+
"--version",
|
|
14132
|
+
"-v"
|
|
14133
|
+
]);
|
|
13090
14134
|
var GATEWAY_LAUNCH_FLAGS = /* @__PURE__ */ new Set(["--provider", "--model"]);
|
|
13091
14135
|
function parseGatewayLaunchFlag(arg, rest, index, parsed) {
|
|
14136
|
+
if (arg === "--all-models") {
|
|
14137
|
+
parsed.launchAllModels = true;
|
|
14138
|
+
return index;
|
|
14139
|
+
}
|
|
13092
14140
|
if (arg === "--provider" || arg === "--model") {
|
|
13093
14141
|
const value = rest[index + 1];
|
|
13094
14142
|
if (!value || value.startsWith("-")) {
|