@jacobbd/relay-ai 0.7.0 → 0.7.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-IYYLLN5T.js → chunk-6CBNKM55.js} +866 -18
- package/dist/chunk-6CBNKM55.js.map +1 -0
- package/dist/{chunk-EJONCU3B.js → chunk-HXGZ4CTV.js} +13 -1
- package/dist/chunk-HXGZ4CTV.js.map +1 -0
- package/dist/cli.js +172 -671
- package/dist/cli.js.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/{provider-templates-BPGB5V2L.js → provider-templates-4H3C4DRL.js} +2 -2
- package/dist/ui/public/app.js +71 -15
- package/dist/ui/public/provider-model-browser.js +4 -1
- package/dist/ui/public/style.css +7 -0
- package/dist/{ui-command-3CWMSARO.js → ui-command-S3TQKB3D.js} +32 -11
- package/dist/ui-command-S3TQKB3D.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-EJONCU3B.js.map +0 -1
- package/dist/chunk-IYYLLN5T.js.map +0 -1
- package/dist/ui-command-3CWMSARO.js.map +0 -1
- /package/dist/{provider-templates-BPGB5V2L.js.map → provider-templates-4H3C4DRL.js.map} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
getTemplateById,
|
|
4
4
|
init_provider_templates
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-HXGZ4CTV.js";
|
|
6
6
|
|
|
7
7
|
// src/constants.ts
|
|
8
8
|
import { homedir } from "os";
|
|
@@ -11,7 +11,7 @@ import { join } from "path";
|
|
|
11
11
|
// package.json
|
|
12
12
|
var package_default = {
|
|
13
13
|
name: "@jacobbd/relay-ai",
|
|
14
|
-
version: "0.7.
|
|
14
|
+
version: "0.7.1",
|
|
15
15
|
publishConfig: {
|
|
16
16
|
access: "public"
|
|
17
17
|
},
|
|
@@ -157,6 +157,7 @@ var PARENT_SESSION_ENV_VARS = [
|
|
|
157
157
|
];
|
|
158
158
|
var OPENCODE_CACHE_PATH = join(homedir(), ".cache", "opencode", "models.json");
|
|
159
159
|
var MAX_MODEL_CATALOG = 20;
|
|
160
|
+
var MIN_CONTEXT_WINDOW = 128e3;
|
|
160
161
|
var VERTEX_ANTHROPIC_NPM = "@ai-sdk/google-vertex/anthropic";
|
|
161
162
|
function classifyModelFormat(modelId, providerNpm) {
|
|
162
163
|
if (providerNpm === "@ai-sdk/anthropic") return "anthropic";
|
|
@@ -1472,13 +1473,36 @@ function providerSelectOption(provider) {
|
|
|
1472
1473
|
}
|
|
1473
1474
|
function modelSelectOption(model, hint) {
|
|
1474
1475
|
const label = formatCodexModelLabel(model);
|
|
1475
|
-
|
|
1476
|
+
let defaultHint = hint;
|
|
1477
|
+
if (!defaultHint) {
|
|
1478
|
+
const isCloudflare = model.id.startsWith("@cf/") || model.id.startsWith("@hf/");
|
|
1479
|
+
if (model.isFree) {
|
|
1480
|
+
defaultHint = pc.green(isCloudflare ? "Free (10k/day)" : "Free");
|
|
1481
|
+
} else if (model.cost && (model.cost.input > 0 || model.cost.output > 0)) {
|
|
1482
|
+
const inputStr = `$${model.cost.input}`;
|
|
1483
|
+
const outputStr = `$${model.cost.output}`;
|
|
1484
|
+
defaultHint = pc.dim(isCloudflare ? `Paid plan req (${inputStr}/${outputStr} 1M)` : `${inputStr}/${outputStr} 1M`);
|
|
1485
|
+
} else {
|
|
1486
|
+
defaultHint = model.name !== model.id ? model.id : model.brand || model.family || "";
|
|
1487
|
+
}
|
|
1488
|
+
} else if (hint === "recent") {
|
|
1489
|
+
const isCloudflare = model.id.startsWith("@cf/") || model.id.startsWith("@hf/");
|
|
1490
|
+
const freeLabel = isCloudflare ? "Free (10k/day)" : "Free";
|
|
1491
|
+
const freeSuffix = model.isFree ? " \xB7 " + pc.green(freeLabel) : "";
|
|
1492
|
+
defaultHint = fmtRecentHint() + freeSuffix;
|
|
1493
|
+
}
|
|
1494
|
+
const ctxSuffix = fmtContextWindow(model.contextWindow);
|
|
1476
1495
|
return {
|
|
1477
1496
|
value: model.id,
|
|
1478
1497
|
label: fmtModel(label),
|
|
1479
|
-
hint:
|
|
1498
|
+
hint: defaultHint && ctxSuffix ? `${defaultHint} \xB7 ${ctxSuffix}` : defaultHint || ctxSuffix
|
|
1480
1499
|
};
|
|
1481
1500
|
}
|
|
1501
|
+
function fmtContextWindow(contextWindow) {
|
|
1502
|
+
if (!contextWindow) return "";
|
|
1503
|
+
const k = contextWindow >= 1e3 ? `${Math.round(contextWindow / 1e3)}k` : String(contextWindow);
|
|
1504
|
+
return pc.dim(`${k} ctx`);
|
|
1505
|
+
}
|
|
1482
1506
|
function navOption(value, label, hint = "") {
|
|
1483
1507
|
return { value, label: pc.cyan(label), hint };
|
|
1484
1508
|
}
|
|
@@ -3689,6 +3713,7 @@ function isFreeProviderAccess(providerId, templateId) {
|
|
|
3689
3713
|
return FREE_PROVIDER_IDS.has((providerId ?? "").toLowerCase()) || FREE_PROVIDER_IDS.has((templateId ?? "").toLowerCase());
|
|
3690
3714
|
}
|
|
3691
3715
|
function classifyFreeStatus(opts) {
|
|
3716
|
+
if (opts.freeAccess === true) return "free_provider";
|
|
3692
3717
|
if (isFreeProviderAccess(opts.providerId, opts.templateId)) return "free_provider";
|
|
3693
3718
|
if (isZeroCost(opts.model.cost)) return "verified_free";
|
|
3694
3719
|
if (isPaidCost(opts.model.cost)) return "paid";
|
|
@@ -3850,7 +3875,12 @@ function enrichModelsWithPricing(models, index, platform) {
|
|
|
3850
3875
|
return models.map((model) => {
|
|
3851
3876
|
const cost = lookupModelCost(index, model.id, platform) ?? lookupModelCost(index, model.upstreamModelId, platform);
|
|
3852
3877
|
if (!cost) return model;
|
|
3853
|
-
const freeStatus = classifyFreeStatus({
|
|
3878
|
+
const freeStatus = classifyFreeStatus({
|
|
3879
|
+
model: { ...model, cost },
|
|
3880
|
+
// Keep provider-granted free access (e.g. Cloudflare's daily allowance) when
|
|
3881
|
+
// real pricing resolves later.
|
|
3882
|
+
freeAccess: model.freeStatus === "free_provider"
|
|
3883
|
+
});
|
|
3854
3884
|
return { ...model, cost, isFree: isFreeStatus(freeStatus), freeStatus };
|
|
3855
3885
|
});
|
|
3856
3886
|
}
|
|
@@ -7288,16 +7318,707 @@ function localProvidersToServerModels(localProviders) {
|
|
|
7288
7318
|
);
|
|
7289
7319
|
}
|
|
7290
7320
|
|
|
7321
|
+
// src/antigravity/slot-registry.ts
|
|
7322
|
+
var AGY_SLOT_VALIDATION_SOURCE = "AGY CLI 1.0.10 / Antigravity IDE 2.1.1 fixture capture 2026-06-23";
|
|
7323
|
+
var AGY_NATIVE_SLOT_REGISTRY = [
|
|
7324
|
+
{
|
|
7325
|
+
slotId: "gemini-3.5-flash-low",
|
|
7326
|
+
model: "MODEL_PLACEHOLDER_M20",
|
|
7327
|
+
role: "agent-switch",
|
|
7328
|
+
status: "validated",
|
|
7329
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE
|
|
7330
|
+
},
|
|
7331
|
+
{
|
|
7332
|
+
slotId: "gemini-3.5-flash-extra-low",
|
|
7333
|
+
model: "MODEL_PLACEHOLDER_M187",
|
|
7334
|
+
role: "agent-switch",
|
|
7335
|
+
status: "validated",
|
|
7336
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE
|
|
7337
|
+
},
|
|
7338
|
+
{
|
|
7339
|
+
slotId: "gemini-3.1-pro-low",
|
|
7340
|
+
model: "MODEL_PLACEHOLDER_M36",
|
|
7341
|
+
role: "agent-switch",
|
|
7342
|
+
status: "validated",
|
|
7343
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE
|
|
7344
|
+
},
|
|
7345
|
+
{
|
|
7346
|
+
slotId: "gemini-pro-agent",
|
|
7347
|
+
model: "MODEL_PLACEHOLDER_M16",
|
|
7348
|
+
role: "agent-switch",
|
|
7349
|
+
status: "validated",
|
|
7350
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE
|
|
7351
|
+
},
|
|
7352
|
+
{
|
|
7353
|
+
slotId: "claude-sonnet-4-6",
|
|
7354
|
+
model: "MODEL_PLACEHOLDER_M35",
|
|
7355
|
+
role: "agent-switch",
|
|
7356
|
+
status: "validated",
|
|
7357
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE
|
|
7358
|
+
},
|
|
7359
|
+
{
|
|
7360
|
+
slotId: "claude-opus-4-6-thinking",
|
|
7361
|
+
model: "MODEL_PLACEHOLDER_M26",
|
|
7362
|
+
role: "agent-switch",
|
|
7363
|
+
status: "validated",
|
|
7364
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE
|
|
7365
|
+
},
|
|
7366
|
+
{
|
|
7367
|
+
slotId: "gpt-oss-120b-medium",
|
|
7368
|
+
model: "MODEL_OPENAI_GPT_OSS_120B_MEDIUM",
|
|
7369
|
+
role: "agent-switch",
|
|
7370
|
+
status: "validated",
|
|
7371
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE
|
|
7372
|
+
},
|
|
7373
|
+
{
|
|
7374
|
+
slotId: "gemini-3-flash-agent",
|
|
7375
|
+
model: "MODEL_PLACEHOLDER_M132",
|
|
7376
|
+
role: "cascade-plan",
|
|
7377
|
+
status: "reserved",
|
|
7378
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE,
|
|
7379
|
+
notes: "Visible in agentModelSorts, but reserved for cascade plan construction."
|
|
7380
|
+
},
|
|
7381
|
+
{
|
|
7382
|
+
slotId: "gemini-2.5-flash",
|
|
7383
|
+
model: "MODEL_GOOGLE_GEMINI_2_5_FLASH",
|
|
7384
|
+
role: "cascade-intent",
|
|
7385
|
+
status: "reserved",
|
|
7386
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE
|
|
7387
|
+
},
|
|
7388
|
+
{
|
|
7389
|
+
slotId: "gemini-2.5-flash-lite",
|
|
7390
|
+
model: "MODEL_GOOGLE_GEMINI_2_5_FLASH_LITE",
|
|
7391
|
+
role: "cascade-fallback",
|
|
7392
|
+
status: "reserved",
|
|
7393
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE
|
|
7394
|
+
},
|
|
7395
|
+
{
|
|
7396
|
+
slotId: "gemini-3.1-pro-high",
|
|
7397
|
+
model: "MODEL_PLACEHOLDER_M37",
|
|
7398
|
+
role: "agent-switch",
|
|
7399
|
+
status: "candidate",
|
|
7400
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE,
|
|
7401
|
+
notes: "Model-shaped fixture entry; requires live switching proof before promotion."
|
|
7402
|
+
},
|
|
7403
|
+
{
|
|
7404
|
+
slotId: "gemini-2.5-pro",
|
|
7405
|
+
model: "MODEL_GOOGLE_GEMINI_2_5_PRO",
|
|
7406
|
+
role: "agent-switch",
|
|
7407
|
+
status: "candidate",
|
|
7408
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE,
|
|
7409
|
+
notes: "Model-shaped fixture entry; requires live switching proof before promotion."
|
|
7410
|
+
},
|
|
7411
|
+
{
|
|
7412
|
+
slotId: "gemini-2.5-flash-thinking",
|
|
7413
|
+
model: "MODEL_GOOGLE_GEMINI_2_5_FLASH_THINKING",
|
|
7414
|
+
role: "agent-switch",
|
|
7415
|
+
status: "candidate",
|
|
7416
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE,
|
|
7417
|
+
notes: "Model-shaped fixture entry; requires live switching proof before promotion."
|
|
7418
|
+
},
|
|
7419
|
+
{
|
|
7420
|
+
slotId: "gemini-3-flash",
|
|
7421
|
+
model: "MODEL_PLACEHOLDER_M18",
|
|
7422
|
+
role: "command",
|
|
7423
|
+
status: "candidate",
|
|
7424
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE,
|
|
7425
|
+
notes: "Command model in the fixture; not switch-safe without live proof."
|
|
7426
|
+
},
|
|
7427
|
+
{
|
|
7428
|
+
slotId: "gemini-3.1-flash-lite",
|
|
7429
|
+
model: "MODEL_PLACEHOLDER_M50",
|
|
7430
|
+
role: "cascade-checkpoint",
|
|
7431
|
+
status: "candidate",
|
|
7432
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE,
|
|
7433
|
+
notes: "Checkpoint/search/commit slot; route as helper until live proof exists."
|
|
7434
|
+
},
|
|
7435
|
+
{
|
|
7436
|
+
slotId: "gemini-3.1-flash-image",
|
|
7437
|
+
model: "MODEL_PLACEHOLDER_M21",
|
|
7438
|
+
role: "image",
|
|
7439
|
+
status: "candidate",
|
|
7440
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE,
|
|
7441
|
+
notes: "Image generation slot; not switch-safe without live proof."
|
|
7442
|
+
},
|
|
7443
|
+
{
|
|
7444
|
+
slotId: "tab_jump_flash_lite_preview",
|
|
7445
|
+
model: "MODEL_PLACEHOLDER_M28",
|
|
7446
|
+
role: "tab",
|
|
7447
|
+
status: "unsafe",
|
|
7448
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE
|
|
7449
|
+
},
|
|
7450
|
+
{
|
|
7451
|
+
slotId: "tab_flash_lite_preview",
|
|
7452
|
+
model: "MODEL_PLACEHOLDER_M19",
|
|
7453
|
+
role: "tab",
|
|
7454
|
+
status: "unsafe",
|
|
7455
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE
|
|
7456
|
+
},
|
|
7457
|
+
{
|
|
7458
|
+
slotId: "chat_20706",
|
|
7459
|
+
model: "MODEL_CHAT_20706",
|
|
7460
|
+
role: "chat",
|
|
7461
|
+
status: "unsafe",
|
|
7462
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE
|
|
7463
|
+
},
|
|
7464
|
+
{
|
|
7465
|
+
slotId: "chat_23310",
|
|
7466
|
+
model: "MODEL_CHAT_23310",
|
|
7467
|
+
role: "chat",
|
|
7468
|
+
status: "unsafe",
|
|
7469
|
+
validatedWith: AGY_SLOT_VALIDATION_SOURCE
|
|
7470
|
+
}
|
|
7471
|
+
];
|
|
7472
|
+
var KNOWN_COMPATIBLE_AGY_VERSIONS = /* @__PURE__ */ new Set([
|
|
7473
|
+
"1.0.10",
|
|
7474
|
+
"1.1.0",
|
|
7475
|
+
"1.1.1",
|
|
7476
|
+
"1.1.2",
|
|
7477
|
+
"1.1.3",
|
|
7478
|
+
"1.1.4",
|
|
7479
|
+
"1.1.5",
|
|
7480
|
+
"1.1.6",
|
|
7481
|
+
"1.1.7"
|
|
7482
|
+
]);
|
|
7483
|
+
var KNOWN_INCOMPATIBLE_AGY_VERSIONS = /* @__PURE__ */ new Set(["1.0.9"]);
|
|
7484
|
+
function withFixtureModel(definition, model) {
|
|
7485
|
+
return model === definition.model ? definition : { ...definition, model };
|
|
7486
|
+
}
|
|
7487
|
+
function assertNoDuplicateSwitchEnums(fixture, definitions) {
|
|
7488
|
+
const seen = /* @__PURE__ */ new Map();
|
|
7489
|
+
for (const definition of definitions) {
|
|
7490
|
+
if (definition.status !== "validated") continue;
|
|
7491
|
+
const actualModel = fixture.models[definition.slotId]?.model;
|
|
7492
|
+
if (!actualModel) continue;
|
|
7493
|
+
const previousSlotId = seen.get(actualModel);
|
|
7494
|
+
if (previousSlotId) {
|
|
7495
|
+
throw new Error(
|
|
7496
|
+
`Duplicate AGY switch slot enum ${actualModel}: ${previousSlotId} and ${definition.slotId}`
|
|
7497
|
+
);
|
|
7498
|
+
}
|
|
7499
|
+
seen.set(actualModel, definition.slotId);
|
|
7500
|
+
}
|
|
7501
|
+
}
|
|
7502
|
+
function validateAgySlotRegistry(fixture) {
|
|
7503
|
+
assertNoDuplicateSwitchEnums(fixture, AGY_NATIVE_SLOT_REGISTRY);
|
|
7504
|
+
const switchSlots = [];
|
|
7505
|
+
const reservedSlots = [];
|
|
7506
|
+
const candidateSlots = [];
|
|
7507
|
+
const warnings = [];
|
|
7508
|
+
for (const definition of AGY_NATIVE_SLOT_REGISTRY) {
|
|
7509
|
+
const entry = fixture.models[definition.slotId];
|
|
7510
|
+
if (!entry) {
|
|
7511
|
+
if (definition.status === "validated" || definition.status === "reserved") {
|
|
7512
|
+
warnings.push(`AGY slot ${definition.slotId} missing from fixture`);
|
|
7513
|
+
}
|
|
7514
|
+
continue;
|
|
7515
|
+
}
|
|
7516
|
+
if (entry.model !== definition.model) {
|
|
7517
|
+
warnings.push(
|
|
7518
|
+
`AGY slot ${definition.slotId} expected ${definition.model} but fixture has ${entry.model}`
|
|
7519
|
+
);
|
|
7520
|
+
continue;
|
|
7521
|
+
}
|
|
7522
|
+
if (definition.status === "validated") {
|
|
7523
|
+
switchSlots.push(withFixtureModel(definition, entry.model));
|
|
7524
|
+
} else if (definition.status === "reserved") {
|
|
7525
|
+
reservedSlots.push(withFixtureModel(definition, entry.model));
|
|
7526
|
+
} else if (definition.status === "candidate") {
|
|
7527
|
+
candidateSlots.push(withFixtureModel(definition, entry.model));
|
|
7528
|
+
}
|
|
7529
|
+
}
|
|
7530
|
+
return { switchSlots, reservedSlots, candidateSlots, warnings };
|
|
7531
|
+
}
|
|
7532
|
+
function getValidatedAgySwitchSlots(fixture) {
|
|
7533
|
+
return validateAgySlotRegistry(fixture).switchSlots;
|
|
7534
|
+
}
|
|
7535
|
+
function evaluateAgySwitchCompatibility(opts) {
|
|
7536
|
+
const validation = validateAgySlotRegistry(opts.fixture);
|
|
7537
|
+
const shapeMatches = validation.warnings.length === 0 && validation.switchSlots.length > 0;
|
|
7538
|
+
const warnings = [];
|
|
7539
|
+
if (opts.versionReadError) {
|
|
7540
|
+
warnings.push(`Could not read agy --version (${opts.versionReadError}); validating AGY fixture shape instead.`);
|
|
7541
|
+
}
|
|
7542
|
+
if (opts.version && KNOWN_INCOMPATIBLE_AGY_VERSIONS.has(opts.version)) {
|
|
7543
|
+
return {
|
|
7544
|
+
mode: "single-model",
|
|
7545
|
+
validatedSwitchSlotCount: validation.switchSlots.length,
|
|
7546
|
+
warnings: [
|
|
7547
|
+
...warnings,
|
|
7548
|
+
`Known-incompatible AGY version ${opts.version}; falling back to single-model mode.`
|
|
7549
|
+
]
|
|
7550
|
+
};
|
|
7551
|
+
}
|
|
7552
|
+
if (!shapeMatches) {
|
|
7553
|
+
return {
|
|
7554
|
+
mode: "single-model",
|
|
7555
|
+
validatedSwitchSlotCount: validation.switchSlots.length,
|
|
7556
|
+
warnings: [
|
|
7557
|
+
...warnings,
|
|
7558
|
+
...validation.warnings,
|
|
7559
|
+
"AGY fixture shape does not match the validated slot registry; falling back to single-model mode."
|
|
7560
|
+
]
|
|
7561
|
+
};
|
|
7562
|
+
}
|
|
7563
|
+
if (opts.version && !KNOWN_COMPATIBLE_AGY_VERSIONS.has(opts.version)) {
|
|
7564
|
+
return {
|
|
7565
|
+
mode: "single-model",
|
|
7566
|
+
validatedSwitchSlotCount: validation.switchSlots.length,
|
|
7567
|
+
warnings: [
|
|
7568
|
+
...warnings,
|
|
7569
|
+
`Unvalidated AGY version ${opts.version}; falling back to single-model mode for maximum stability.`
|
|
7570
|
+
]
|
|
7571
|
+
};
|
|
7572
|
+
} else if (!opts.version && !opts.versionReadError) {
|
|
7573
|
+
warnings.push("AGY version is unknown; fixture shape matches, so multi-model switching remains enabled.");
|
|
7574
|
+
}
|
|
7575
|
+
return {
|
|
7576
|
+
mode: "multi-model",
|
|
7577
|
+
validatedSwitchSlotCount: validation.switchSlots.length,
|
|
7578
|
+
warnings
|
|
7579
|
+
};
|
|
7580
|
+
}
|
|
7581
|
+
|
|
7582
|
+
// src/antigravity/catalog.ts
|
|
7583
|
+
var RELAY_CASCADE_PLAN_MODEL = "MODEL_PLACEHOLDER_M132";
|
|
7584
|
+
var RELAY_AGENT_PLACEHOLDER = "MODEL_PLACEHOLDER_M20";
|
|
7585
|
+
var RELAY_CASCADE_CHECKPOINT_MODEL = "MODEL_PLACEHOLDER_M50";
|
|
7586
|
+
var RELAY_CASCADE_INTENT_MODEL = "MODEL_GOOGLE_GEMINI_2_5_FLASH";
|
|
7587
|
+
var RELAY_CASCADE_ANCHOR_ID = "gemini-3.5-flash-low";
|
|
7588
|
+
var RELAY_CASCADE_PLAN_ANCHOR_ID = "gemini-3-flash-agent";
|
|
7589
|
+
var RELAY_CASCADE_FALLBACK_ID = "gemini-2.5-flash-lite";
|
|
7590
|
+
var RELAY_CASCADE_INTENT_MODEL_ID = "gemini-2.5-flash";
|
|
7591
|
+
function withCascadeCheckpointer(entry, maxTokenLimit = 128e3) {
|
|
7592
|
+
const tokenThreshold = Math.min(5e4, Math.floor(maxTokenLimit * 0.75));
|
|
7593
|
+
const existingModelExperiments = entry.modelExperiments;
|
|
7594
|
+
entry.modelExperiments = {
|
|
7595
|
+
...existingModelExperiments,
|
|
7596
|
+
experiments: {
|
|
7597
|
+
...existingModelExperiments?.experiments ?? {},
|
|
7598
|
+
CASCADE_USE_EXPERIMENT_CHECKPOINTER: {
|
|
7599
|
+
stringValue: JSON.stringify({
|
|
7600
|
+
strategy: "CHECKPOINT_STRATEGY_SAME_MODEL",
|
|
7601
|
+
max_token_limit: String(maxTokenLimit),
|
|
7602
|
+
token_threshold: String(tokenThreshold),
|
|
7603
|
+
max_overhead_ratio: "0.15",
|
|
7604
|
+
moving_window_size: "1",
|
|
7605
|
+
enabled: true,
|
|
7606
|
+
max_output_tokens: "16384",
|
|
7607
|
+
checkpoint_model: RELAY_CASCADE_CHECKPOINT_MODEL,
|
|
7608
|
+
use_last_planner_model: true,
|
|
7609
|
+
is_sync: true,
|
|
7610
|
+
max_user_requests: 10,
|
|
7611
|
+
include_last_user_message: true,
|
|
7612
|
+
include_conversation_log: false,
|
|
7613
|
+
include_running_task_snapshots: true,
|
|
7614
|
+
include_subagent_snapshots: true,
|
|
7615
|
+
include_artifact_snapshots: true,
|
|
7616
|
+
retry_config: {
|
|
7617
|
+
max_retries: 0,
|
|
7618
|
+
initial_sleep_duration_ms: 1e3,
|
|
7619
|
+
exponential_multiplier: 2,
|
|
7620
|
+
include_error_feedback: false
|
|
7621
|
+
}
|
|
7622
|
+
})
|
|
7623
|
+
}
|
|
7624
|
+
}
|
|
7625
|
+
};
|
|
7626
|
+
return entry;
|
|
7627
|
+
}
|
|
7628
|
+
var ANTIGRAVITY_REQUIRED_INPUT_TOKENS = 128e3;
|
|
7629
|
+
var ANTIGRAVITY_MIN_OUTPUT_TOKENS = 8192;
|
|
7630
|
+
var ANTIGRAVITY_MIN_CONTEXT_WINDOW = ANTIGRAVITY_REQUIRED_INPUT_TOKENS + ANTIGRAVITY_MIN_OUTPUT_TOKENS;
|
|
7631
|
+
function applyRouteContextBounds(entry, route) {
|
|
7632
|
+
const maxTokenLimit = route.contextWindow ?? 128e3;
|
|
7633
|
+
const maxOutputTokens = Math.min(
|
|
7634
|
+
entry.maxOutputTokens ?? 65536,
|
|
7635
|
+
Math.max(
|
|
7636
|
+
ANTIGRAVITY_MIN_OUTPUT_TOKENS,
|
|
7637
|
+
maxTokenLimit - ANTIGRAVITY_REQUIRED_INPUT_TOKENS
|
|
7638
|
+
)
|
|
7639
|
+
);
|
|
7640
|
+
const checkpointTokenLimit = Math.min(
|
|
7641
|
+
128e3,
|
|
7642
|
+
Math.max(1, maxTokenLimit - maxOutputTokens)
|
|
7643
|
+
);
|
|
7644
|
+
entry.maxTokens = maxTokenLimit;
|
|
7645
|
+
entry.maxOutputTokens = maxOutputTokens;
|
|
7646
|
+
return withCascadeCheckpointer(entry, checkpointTokenLimit);
|
|
7647
|
+
}
|
|
7648
|
+
var RELAY_CASCADE_FALLBACK_ENTRY = withCascadeCheckpointer({
|
|
7649
|
+
displayName: "Gemini 3.1 Flash Lite",
|
|
7650
|
+
model: "MODEL_GOOGLE_GEMINI_2_5_FLASH_LITE",
|
|
7651
|
+
apiProvider: "API_PROVIDER_GOOGLE_GEMINI",
|
|
7652
|
+
modelProvider: "MODEL_PROVIDER_GOOGLE",
|
|
7653
|
+
tokenizerType: "LLAMA_WITH_SPECIAL",
|
|
7654
|
+
maxTokens: 1048576,
|
|
7655
|
+
maxOutputTokens: 65535,
|
|
7656
|
+
quotaInfo: { remainingFraction: 1 }
|
|
7657
|
+
});
|
|
7658
|
+
var RELAY_CASCADE_INTENT_MODEL_ENTRY = withCascadeCheckpointer({
|
|
7659
|
+
...RELAY_CASCADE_FALLBACK_ENTRY,
|
|
7660
|
+
model: RELAY_CASCADE_INTENT_MODEL
|
|
7661
|
+
});
|
|
7662
|
+
function planRelayCatalogSlots(catalog, routes, templateKey) {
|
|
7663
|
+
const validation = validateAgySlotRegistry(catalog);
|
|
7664
|
+
const switchSlots = getValidatedAgySwitchSlots(catalog);
|
|
7665
|
+
const templateSlot = switchSlots.find((slot) => slot.slotId === templateKey);
|
|
7666
|
+
const orderedSlots = templateSlot ? [templateSlot, ...switchSlots.filter((slot) => slot.slotId !== templateKey)] : switchSlots;
|
|
7667
|
+
if (routes.length > 0 && orderedSlots.length === 0) {
|
|
7668
|
+
throw new Error("No validated AGY switch slots are available for the selected launch route");
|
|
7669
|
+
}
|
|
7670
|
+
const switchableRoutes = routes.slice(0, orderedSlots.length);
|
|
7671
|
+
const skippedRoutes = routes.slice(orderedSlots.length);
|
|
7672
|
+
const slots = switchableRoutes.map((route, index) => ({
|
|
7673
|
+
slotId: orderedSlots[index].slotId,
|
|
7674
|
+
route
|
|
7675
|
+
}));
|
|
7676
|
+
return {
|
|
7677
|
+
slots,
|
|
7678
|
+
switchableRoutes,
|
|
7679
|
+
skippedRoutes,
|
|
7680
|
+
validation
|
|
7681
|
+
};
|
|
7682
|
+
}
|
|
7683
|
+
function resolveRelayCatalogSlots(catalog, routes, templateKey) {
|
|
7684
|
+
return planRelayCatalogSlots(catalog, routes, templateKey).slots;
|
|
7685
|
+
}
|
|
7686
|
+
function buildRelayCatalogEntry(route, template) {
|
|
7687
|
+
const entry = structuredClone(template);
|
|
7688
|
+
entry.displayName = route.displayName;
|
|
7689
|
+
entry.model = template.model ?? RELAY_AGENT_PLACEHOLDER;
|
|
7690
|
+
entry.requestedModelId = route.catalogId;
|
|
7691
|
+
entry.modelVersion = route.catalogId;
|
|
7692
|
+
entry.modelVersionId = route.catalogId;
|
|
7693
|
+
entry.quotaInfo = { remainingFraction: 1, resetTime: "2026-06-23T02:00:57Z" };
|
|
7694
|
+
return applyRouteContextBounds(entry, route);
|
|
7695
|
+
}
|
|
7696
|
+
function buildRelayCatalogSlotEntry(route, template) {
|
|
7697
|
+
const entry = structuredClone(template);
|
|
7698
|
+
entry.displayName = route.displayName;
|
|
7699
|
+
entry.quotaInfo = { remainingFraction: 1, resetTime: "2026-06-23T02:00:57Z" };
|
|
7700
|
+
delete entry.requestedModelId;
|
|
7701
|
+
delete entry.modelVersion;
|
|
7702
|
+
delete entry.modelVersionId;
|
|
7703
|
+
delete entry.isInternal;
|
|
7704
|
+
return applyRouteContextBounds(entry, route);
|
|
7705
|
+
}
|
|
7706
|
+
function injectRelayModels(fixture, routes, templateKey) {
|
|
7707
|
+
const result = structuredClone(fixture);
|
|
7708
|
+
const template = fixture.models[templateKey];
|
|
7709
|
+
if (!template) {
|
|
7710
|
+
throw new Error(`Template model "${templateKey}" not found in catalog fixture`);
|
|
7711
|
+
}
|
|
7712
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7713
|
+
for (const route of routes) {
|
|
7714
|
+
if (seen.has(route.catalogId)) {
|
|
7715
|
+
throw new Error(`Catalog ID collision: ${route.catalogId}`);
|
|
7716
|
+
}
|
|
7717
|
+
if (fixture.models[route.catalogId]) {
|
|
7718
|
+
throw new Error(`Catalog ID collision with native model: ${route.catalogId}`);
|
|
7719
|
+
}
|
|
7720
|
+
seen.add(route.catalogId);
|
|
7721
|
+
}
|
|
7722
|
+
if (routes.length > 0) {
|
|
7723
|
+
result.models[RELAY_CASCADE_ANCHOR_ID] ??= structuredClone(template);
|
|
7724
|
+
result.models[RELAY_CASCADE_FALLBACK_ID] ??= structuredClone(RELAY_CASCADE_FALLBACK_ENTRY);
|
|
7725
|
+
result.models[RELAY_CASCADE_INTENT_MODEL_ID] ??= structuredClone(RELAY_CASCADE_INTENT_MODEL_ENTRY);
|
|
7726
|
+
if (!result.models[RELAY_CASCADE_PLAN_ANCHOR_ID]) {
|
|
7727
|
+
const planAnchor = withCascadeCheckpointer(structuredClone(template));
|
|
7728
|
+
planAnchor.model = RELAY_CASCADE_PLAN_MODEL;
|
|
7729
|
+
result.models[RELAY_CASCADE_PLAN_ANCHOR_ID] = planAnchor;
|
|
7730
|
+
}
|
|
7731
|
+
const slotPlan = planRelayCatalogSlots(result, routes, templateKey);
|
|
7732
|
+
const slots = slotPlan.slots;
|
|
7733
|
+
for (const { slotId, route } of slots) {
|
|
7734
|
+
const slotTemplate = result.models[slotId] ?? template;
|
|
7735
|
+
if (result.models[slotId]) {
|
|
7736
|
+
result.models[slotId] = buildRelayCatalogSlotEntry(route, slotTemplate);
|
|
7737
|
+
}
|
|
7738
|
+
result.models[route.catalogId] = buildRelayCatalogEntry(route, slotTemplate);
|
|
7739
|
+
}
|
|
7740
|
+
result.defaultAgentModelId = slots[0]?.slotId ?? RELAY_CASCADE_ANCHOR_ID;
|
|
7741
|
+
result.agentModelSorts = [
|
|
7742
|
+
{
|
|
7743
|
+
displayName: "Recommended",
|
|
7744
|
+
groups: [{
|
|
7745
|
+
modelIds: slots.map((slot) => slot.slotId)
|
|
7746
|
+
}]
|
|
7747
|
+
}
|
|
7748
|
+
];
|
|
7749
|
+
return result;
|
|
7750
|
+
}
|
|
7751
|
+
if (!result.agentModelSorts?.[0]?.groups?.[0]) {
|
|
7752
|
+
result.agentModelSorts = [
|
|
7753
|
+
{
|
|
7754
|
+
displayName: "Recommended",
|
|
7755
|
+
groups: [{ modelIds: [] }]
|
|
7756
|
+
}
|
|
7757
|
+
];
|
|
7758
|
+
}
|
|
7759
|
+
return result;
|
|
7760
|
+
}
|
|
7761
|
+
function buildAntigravityRoutes(resolvedFavorites, maxRoutes = MAX_MODEL_CATALOG) {
|
|
7762
|
+
const routes = [];
|
|
7763
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7764
|
+
for (const fav of resolvedFavorites) {
|
|
7765
|
+
if (routes.length >= maxRoutes) break;
|
|
7766
|
+
const favModel = fav.model;
|
|
7767
|
+
const modelId = favModel.id;
|
|
7768
|
+
const safeModelSlug = modelId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7769
|
+
const catalogId = `relay-ai__${fav.providerId}__${safeModelSlug}`;
|
|
7770
|
+
if (seen.has(catalogId)) continue;
|
|
7771
|
+
seen.add(catalogId);
|
|
7772
|
+
const npm = favModel.npm || "@ai-sdk/openai-compatible";
|
|
7773
|
+
const upstreamModelId2 = favModel.upstreamModelId || modelId;
|
|
7774
|
+
const baseURL = favModel.apiBaseUrl || favModel.completionsUrl || void 0;
|
|
7775
|
+
const contextWindow = favModel.contextWindow;
|
|
7776
|
+
const modelFormat = favModel.modelFormat;
|
|
7777
|
+
routes.push({
|
|
7778
|
+
catalogId,
|
|
7779
|
+
providerId: fav.providerId,
|
|
7780
|
+
providerName: fav.providerName,
|
|
7781
|
+
modelId,
|
|
7782
|
+
upstreamModelId: upstreamModelId2,
|
|
7783
|
+
displayName: `${favModel.name} (Relay)`,
|
|
7784
|
+
...modelFormat ? { modelFormat } : {},
|
|
7785
|
+
npm,
|
|
7786
|
+
apiKey: fav.apiKey,
|
|
7787
|
+
...fav.authType ? { authType: fav.authType } : {},
|
|
7788
|
+
...fav.oauthAccountId ? { oauthAccountId: fav.oauthAccountId } : {},
|
|
7789
|
+
...fav.providerData ? { providerData: fav.providerData } : {},
|
|
7790
|
+
baseURL,
|
|
7791
|
+
contextWindow
|
|
7792
|
+
});
|
|
7793
|
+
}
|
|
7794
|
+
return applyUniqueAntigravityRouteLabels(routes);
|
|
7795
|
+
}
|
|
7796
|
+
function routeBaseModelName(route) {
|
|
7797
|
+
const relayMatch = route.displayName.match(/^(.*) \(Relay(?: - .*)?\)$/);
|
|
7798
|
+
return relayMatch?.[1] ?? route.displayName;
|
|
7799
|
+
}
|
|
7800
|
+
function authKindLabel(route) {
|
|
7801
|
+
if (route.authType === "oauth") return "OAuth";
|
|
7802
|
+
if (route.authType === "api") return "API key";
|
|
7803
|
+
if (route.authType === "none") return "local";
|
|
7804
|
+
return "provider";
|
|
7805
|
+
}
|
|
7806
|
+
function duplicateCounts(values) {
|
|
7807
|
+
const counts = /* @__PURE__ */ new Map();
|
|
7808
|
+
for (const value of values) {
|
|
7809
|
+
counts.set(value, (counts.get(value) ?? 0) + 1);
|
|
7810
|
+
}
|
|
7811
|
+
return counts;
|
|
7812
|
+
}
|
|
7813
|
+
function assertUniqueRouteDisplayNames(routes) {
|
|
7814
|
+
const counts = duplicateCounts(routes.map((route) => route.displayName));
|
|
7815
|
+
const duplicate = [...counts.entries()].find(([, count]) => count > 1);
|
|
7816
|
+
if (duplicate) {
|
|
7817
|
+
throw new Error(`Duplicate AGY model label after disambiguation: ${duplicate[0]}`);
|
|
7818
|
+
}
|
|
7819
|
+
}
|
|
7820
|
+
function applyUniqueAntigravityRouteLabels(routes) {
|
|
7821
|
+
const baseNames = routes.map(routeBaseModelName);
|
|
7822
|
+
const baseNameCounts = duplicateCounts(baseNames);
|
|
7823
|
+
const upstreamCounts = duplicateCounts(routes.map((route) => route.upstreamModelId));
|
|
7824
|
+
const providerNameCounts = duplicateCounts(routes.map((route) => route.providerName));
|
|
7825
|
+
const labeled = routes.map((route, index) => {
|
|
7826
|
+
const baseName = baseNames[index];
|
|
7827
|
+
const needsSuffix = (baseNameCounts.get(baseName) ?? 0) > 1 || (upstreamCounts.get(route.upstreamModelId) ?? 0) > 1;
|
|
7828
|
+
if (!needsSuffix) {
|
|
7829
|
+
return { ...route, displayName: `${baseName} (Relay)` };
|
|
7830
|
+
}
|
|
7831
|
+
const providerName = route.providerName || route.providerId;
|
|
7832
|
+
const providerSuffix = (providerNameCounts.get(providerName) ?? 0) > 1 ? `${providerName} ${authKindLabel(route)}` : providerName;
|
|
7833
|
+
return {
|
|
7834
|
+
...route,
|
|
7835
|
+
displayName: `${baseName} (Relay - ${providerSuffix})`
|
|
7836
|
+
};
|
|
7837
|
+
});
|
|
7838
|
+
const firstPassCounts = duplicateCounts(labeled.map((route) => route.displayName));
|
|
7839
|
+
const withProviderIds = labeled.map((route) => {
|
|
7840
|
+
if ((firstPassCounts.get(route.displayName) ?? 0) <= 1) return route;
|
|
7841
|
+
return {
|
|
7842
|
+
...route,
|
|
7843
|
+
displayName: route.displayName.replace(/\)$/, ` - ${route.providerId})`)
|
|
7844
|
+
};
|
|
7845
|
+
});
|
|
7846
|
+
assertUniqueRouteDisplayNames(withProviderIds);
|
|
7847
|
+
return withProviderIds;
|
|
7848
|
+
}
|
|
7849
|
+
function routeLabels(routes) {
|
|
7850
|
+
assertUniqueRouteDisplayNames(routes);
|
|
7851
|
+
const labels = /* @__PURE__ */ new Map();
|
|
7852
|
+
for (const route of routes) {
|
|
7853
|
+
labels.set(route.catalogId, route.displayName);
|
|
7854
|
+
}
|
|
7855
|
+
return labels;
|
|
7856
|
+
}
|
|
7857
|
+
function buildClientModelConfigData(routes, catalog, templateKey = RELAY_CASCADE_ANCHOR_ID, precomputedSlots) {
|
|
7858
|
+
const catalogRoutes = routes.slice(0, MAX_MODEL_CATALOG);
|
|
7859
|
+
const slots = precomputedSlots ?? (catalog ? resolveRelayCatalogSlots(catalog, catalogRoutes, templateKey) : catalogRoutes.map((route) => ({ slotId: route.catalogId, route })));
|
|
7860
|
+
const labels = routeLabels(catalogRoutes);
|
|
7861
|
+
const clientModelConfigs = slots.map(({ slotId, route }) => {
|
|
7862
|
+
const entry = catalog?.models[slotId] ?? catalog?.models[route.catalogId] ?? catalog?.models[RELAY_CASCADE_ANCHOR_ID];
|
|
7863
|
+
const label = labels.get(route.catalogId) ?? route.displayName;
|
|
7864
|
+
return {
|
|
7865
|
+
label,
|
|
7866
|
+
modelOrAlias: {
|
|
7867
|
+
alias: slotId,
|
|
7868
|
+
choice: { case: "alias", value: slotId }
|
|
7869
|
+
},
|
|
7870
|
+
disabled: false,
|
|
7871
|
+
supportedMimeTypes: entry?.supportedMimeTypes ?? {},
|
|
7872
|
+
quotaInfo: entry?.quotaInfo ?? { remainingFraction: 1 },
|
|
7873
|
+
tagTitle: entry?.tagTitle,
|
|
7874
|
+
tagDescription: entry?.tagDescription,
|
|
7875
|
+
supportsThoughtCirculation: entry?.supportsThoughtCirculation ?? false
|
|
7876
|
+
};
|
|
7877
|
+
});
|
|
7878
|
+
return {
|
|
7879
|
+
clientModelConfigs,
|
|
7880
|
+
clientModelSorts: [
|
|
7881
|
+
{
|
|
7882
|
+
name: "Recommended",
|
|
7883
|
+
groups: [
|
|
7884
|
+
{
|
|
7885
|
+
groupName: "",
|
|
7886
|
+
modelLabels: clientModelConfigs.map((config) => config.label)
|
|
7887
|
+
}
|
|
7888
|
+
]
|
|
7889
|
+
}
|
|
7890
|
+
],
|
|
7891
|
+
defaultOverrideModelConfig: clientModelConfigs[0] ?? {}
|
|
7892
|
+
};
|
|
7893
|
+
}
|
|
7894
|
+
function buildListModelConfigsResponse(routes, catalog, templateKey = RELAY_CASCADE_ANCHOR_ID) {
|
|
7895
|
+
const catalogRoutes = routes.slice(0, MAX_MODEL_CATALOG);
|
|
7896
|
+
const slots = catalog ? resolveRelayCatalogSlots(catalog, catalogRoutes, templateKey) : catalogRoutes.map((route) => ({ slotId: route.catalogId, route }));
|
|
7897
|
+
const config = slots.map(({ slotId }) => ({
|
|
7898
|
+
requestedModelId: slotId,
|
|
7899
|
+
planModel: RELAY_CASCADE_PLAN_MODEL,
|
|
7900
|
+
requestedModel: catalog?.models[slotId]?.model ?? RELAY_AGENT_PLACEHOLDER
|
|
7901
|
+
}));
|
|
7902
|
+
return {
|
|
7903
|
+
...buildClientModelConfigData(routes, catalog, templateKey, slots),
|
|
7904
|
+
allowedModelConfigs: config,
|
|
7905
|
+
defaultAgentModelConfig: config[0] ?? {}
|
|
7906
|
+
};
|
|
7907
|
+
}
|
|
7908
|
+
var CURRENT_EXPERIMENT_IDS = [
|
|
7909
|
+
105979552,
|
|
7910
|
+
105979574,
|
|
7911
|
+
106015351,
|
|
7912
|
+
105979579,
|
|
7913
|
+
105867471,
|
|
7914
|
+
105979530,
|
|
7915
|
+
105995634,
|
|
7916
|
+
106121401,
|
|
7917
|
+
106100625,
|
|
7918
|
+
104638466,
|
|
7919
|
+
101868197,
|
|
7920
|
+
104817729,
|
|
7921
|
+
105695344,
|
|
7922
|
+
106064591,
|
|
7923
|
+
104913215,
|
|
7924
|
+
106324349,
|
|
7925
|
+
106309078,
|
|
7926
|
+
105821930,
|
|
7927
|
+
104922093,
|
|
7928
|
+
103012598,
|
|
7929
|
+
106143956,
|
|
7930
|
+
105856899,
|
|
7931
|
+
106312323,
|
|
7932
|
+
106064030,
|
|
7933
|
+
105746183,
|
|
7934
|
+
105757908,
|
|
7935
|
+
104892493,
|
|
7936
|
+
105822886,
|
|
7937
|
+
105785683,
|
|
7938
|
+
105721273,
|
|
7939
|
+
105897325,
|
|
7940
|
+
105658071,
|
|
7941
|
+
106240758,
|
|
7942
|
+
105943702,
|
|
7943
|
+
106106760,
|
|
7944
|
+
106283618,
|
|
7945
|
+
105620019,
|
|
7946
|
+
106038160,
|
|
7947
|
+
106309520,
|
|
7948
|
+
106281951,
|
|
7949
|
+
106264532,
|
|
7950
|
+
106222835,
|
|
7951
|
+
106094629,
|
|
7952
|
+
105887313,
|
|
7953
|
+
105849474,
|
|
7954
|
+
106032303,
|
|
7955
|
+
106228452,
|
|
7956
|
+
106113900,
|
|
7957
|
+
106121607,
|
|
7958
|
+
105979531,
|
|
7959
|
+
105979553,
|
|
7960
|
+
106015328,
|
|
7961
|
+
105867469,
|
|
7962
|
+
105979517,
|
|
7963
|
+
106121399,
|
|
7964
|
+
106100654,
|
|
7965
|
+
104638459,
|
|
7966
|
+
101551624,
|
|
7967
|
+
104673683,
|
|
7968
|
+
105695346,
|
|
7969
|
+
106064590,
|
|
7970
|
+
104913210,
|
|
7971
|
+
105821928,
|
|
7972
|
+
104922082,
|
|
7973
|
+
103012592,
|
|
7974
|
+
106064028,
|
|
7975
|
+
105746181,
|
|
7976
|
+
104892490,
|
|
7977
|
+
105822881,
|
|
7978
|
+
105721268,
|
|
7979
|
+
105895316,
|
|
7980
|
+
105658068,
|
|
7981
|
+
106240748,
|
|
7982
|
+
105943694,
|
|
7983
|
+
106283614,
|
|
7984
|
+
105620012,
|
|
7985
|
+
106038153,
|
|
7986
|
+
105887311,
|
|
7987
|
+
106032301,
|
|
7988
|
+
106113877,
|
|
7989
|
+
106121604
|
|
7990
|
+
];
|
|
7991
|
+
function buildListExperimentsResponse() {
|
|
7992
|
+
return {
|
|
7993
|
+
experimentIds: [...CURRENT_EXPERIMENT_IDS]
|
|
7994
|
+
};
|
|
7995
|
+
}
|
|
7996
|
+
|
|
7291
7997
|
// src/target-compatibility.ts
|
|
7292
7998
|
function blacklistAgentForTarget(target) {
|
|
7293
7999
|
if (target === "claude-app") return "codex-app";
|
|
7294
8000
|
return target;
|
|
7295
8001
|
}
|
|
8002
|
+
function contextFloorForTarget(target) {
|
|
8003
|
+
if (target === "antigravity") return ANTIGRAVITY_MIN_CONTEXT_WINDOW;
|
|
8004
|
+
if (target === "server") return 0;
|
|
8005
|
+
return MIN_CONTEXT_WINDOW;
|
|
8006
|
+
}
|
|
8007
|
+
function meetsContextFloor(target, contextWindow) {
|
|
8008
|
+
return contextWindow === void 0 || contextWindow >= contextFloorForTarget(target);
|
|
8009
|
+
}
|
|
7296
8010
|
function isTargetCompatibleModel(ctx) {
|
|
7297
8011
|
const blacklistAgent = blacklistAgentForTarget(ctx.target);
|
|
7298
8012
|
if (shouldHideModel({ providerId: ctx.providerId, modelId: ctx.model.id, agent: blacklistAgent })) {
|
|
7299
8013
|
return { compatible: false, reason: "model is hidden by compatibility filters" };
|
|
7300
8014
|
}
|
|
8015
|
+
if (!meetsContextFloor(ctx.target, ctx.model.contextWindow)) {
|
|
8016
|
+
const floor = contextFloorForTarget(ctx.target);
|
|
8017
|
+
return {
|
|
8018
|
+
compatible: false,
|
|
8019
|
+
reason: `${ctx.target} needs a ${Math.round(floor / 1e3)}K+ context window; this model has ${Math.round(ctx.model.contextWindow / 1e3)}K`
|
|
8020
|
+
};
|
|
8021
|
+
}
|
|
7301
8022
|
if (ctx.model.modelFormat === "cloud-code") {
|
|
7302
8023
|
if (ctx.target === "server") {
|
|
7303
8024
|
return { compatible: false, reason: "Cloud Code models are not supported for the server target yet" };
|
|
@@ -7362,8 +8083,11 @@ function modelFormatForNpm(npm) {
|
|
|
7362
8083
|
return npm === "@ai-sdk/anthropic" ? "anthropic" : "openai";
|
|
7363
8084
|
}
|
|
7364
8085
|
function modelsUrl(baseUrl, template) {
|
|
7365
|
-
|
|
8086
|
+
let trimmed = baseUrl.replace(/\/$/, "");
|
|
7366
8087
|
if (template.modelsPath) {
|
|
8088
|
+
if (trimmed.endsWith("/v1") && (template.modelsPath.startsWith("/models") || template.modelsPath.startsWith("/ai/models"))) {
|
|
8089
|
+
trimmed = trimmed.slice(0, -3);
|
|
8090
|
+
}
|
|
7367
8091
|
const path = template.modelsPath.startsWith("/") ? template.modelsPath : `/${template.modelsPath}`;
|
|
7368
8092
|
return `${trimmed}${path}`;
|
|
7369
8093
|
}
|
|
@@ -7400,20 +8124,64 @@ function parseNativePricing(pricing) {
|
|
|
7400
8124
|
if (cacheWrite !== void 0) cost.cache_write = cacheWrite;
|
|
7401
8125
|
return cost;
|
|
7402
8126
|
}
|
|
8127
|
+
function parseCloudflarePricing(priceValue) {
|
|
8128
|
+
if (!Array.isArray(priceValue)) return void 0;
|
|
8129
|
+
let input;
|
|
8130
|
+
let output;
|
|
8131
|
+
for (const item of priceValue) {
|
|
8132
|
+
if (typeof item !== "object" || !item) continue;
|
|
8133
|
+
const row = item;
|
|
8134
|
+
const unit = String(row.unit || "").toLowerCase();
|
|
8135
|
+
const price = Number(row.price);
|
|
8136
|
+
if (!Number.isFinite(price)) continue;
|
|
8137
|
+
if (unit.includes("input")) input = price;
|
|
8138
|
+
else if (unit.includes("output")) output = price;
|
|
8139
|
+
}
|
|
8140
|
+
if (input === void 0 && output === void 0) return void 0;
|
|
8141
|
+
return { input: input ?? 0, output: output ?? 0 };
|
|
8142
|
+
}
|
|
8143
|
+
var LEGACY_NON_TOOL_MODELS = /* @__PURE__ */ new Set([
|
|
8144
|
+
"@cf/google/gemma-2b-it-lora",
|
|
8145
|
+
"@cf/google/gemma-7b-it-lora",
|
|
8146
|
+
"@cf/meta-llama/llama-2-7b-chat-hf-lora",
|
|
8147
|
+
"@cf/mistral/mistral-7b-instruct-v0.2-lora"
|
|
8148
|
+
]);
|
|
7403
8149
|
function parseModelList(body, npm) {
|
|
7404
|
-
const rows = body.data ?? body.models ?? [];
|
|
8150
|
+
const rows = body.data ?? body.models ?? body.result ?? [];
|
|
7405
8151
|
const format = modelFormatForNpm(npm);
|
|
7406
8152
|
const models = [];
|
|
7407
8153
|
for (const row of rows) {
|
|
7408
|
-
const rawId = row.id?.trim();
|
|
8154
|
+
const rawId = (row.name?.startsWith("@cf/") || row.name?.startsWith("@hf/") ? row.name : row.id)?.trim();
|
|
7409
8155
|
if (!rawId) continue;
|
|
8156
|
+
let contextWindowFromProps;
|
|
8157
|
+
let isFreeFromProps;
|
|
8158
|
+
let costFromProps;
|
|
8159
|
+
if (Array.isArray(row.properties)) {
|
|
8160
|
+
if (LEGACY_NON_TOOL_MODELS.has(rawId)) continue;
|
|
8161
|
+
const cwProp = row.properties.find((p8) => p8.property_id === "context_window");
|
|
8162
|
+
if (cwProp?.value) contextWindowFromProps = toNumber(cwProp.value);
|
|
8163
|
+
const priceProp = row.properties.find((p8) => p8.property_id === "price");
|
|
8164
|
+
const isRestrictedPaidPlan = rawId.includes("/glm-") || rawId.includes("/kimi-");
|
|
8165
|
+
if (isRestrictedPaidPlan) {
|
|
8166
|
+
costFromProps = parseCloudflarePricing(priceProp?.value);
|
|
8167
|
+
isFreeFromProps = false;
|
|
8168
|
+
} else {
|
|
8169
|
+
isFreeFromProps = true;
|
|
8170
|
+
if (priceProp?.value) {
|
|
8171
|
+
costFromProps = parseCloudflarePricing(priceProp.value);
|
|
8172
|
+
}
|
|
8173
|
+
}
|
|
8174
|
+
}
|
|
7410
8175
|
const { id, upstreamModelId: upstreamModelId2 } = normalizeGoogleModelId(rawId, npm);
|
|
7411
|
-
const family = id.split(/[-/:]/)[0] ?? id;
|
|
7412
|
-
const cost = parseNativePricing(row.pricing);
|
|
8176
|
+
const family = id.replace(/^@[a-z0-9_-]+\//i, "").split(/[-/:]/)[0] ?? id;
|
|
8177
|
+
const cost = costFromProps ?? parseNativePricing(row.pricing);
|
|
7413
8178
|
const freeStatus = classifyFreeStatus({
|
|
7414
|
-
model: { cost, isFree: row.isFree }
|
|
8179
|
+
model: { cost, isFree: row.isFree },
|
|
8180
|
+
// Cloudflare standard models carry a list price but are covered by the free
|
|
8181
|
+
// daily Neuron allowance, so free access is a provider rule, not a price.
|
|
8182
|
+
freeAccess: isFreeFromProps === true
|
|
7415
8183
|
});
|
|
7416
|
-
const contextWindow = row.context_length ?? row.contextWindow ?? row.context_window ?? resolveContextWindow(id);
|
|
8184
|
+
const contextWindow = contextWindowFromProps ?? row.context_length ?? row.contextWindow ?? row.context_window ?? resolveContextWindow(id);
|
|
7417
8185
|
models.push({
|
|
7418
8186
|
id,
|
|
7419
8187
|
name: normalizeGoogleDisplayName(row.name, id),
|
|
@@ -10697,14 +11465,14 @@ function codexAppInstallHint() {
|
|
|
10697
11465
|
|
|
10698
11466
|
// src/claude-desktop/app-launch.ts
|
|
10699
11467
|
import { execSync as execSync3, spawn as spawn3 } from "child_process";
|
|
10700
|
-
import { existsSync as existsSync12, readdirSync as readdirSync2, statSync as statSync4 } from "fs";
|
|
11468
|
+
import { existsSync as existsSync12, readdirSync as readdirSync2, readFileSync as readFileSync12, statSync as statSync4 } from "fs";
|
|
10701
11469
|
import { homedir as homedir8 } from "os";
|
|
10702
11470
|
import { join as join12 } from "path";
|
|
10703
11471
|
import * as p7 from "@clack/prompts";
|
|
10704
11472
|
var CLAUDE_BUNDLE_ID = "com.anthropic.claudefordesktop";
|
|
10705
11473
|
function claudeAppSupported() {
|
|
10706
|
-
if (process.platform !== "darwin" && process.platform !== "win32") {
|
|
10707
|
-
throw new Error("Claude Desktop launch is supported on macOS and
|
|
11474
|
+
if (process.platform !== "darwin" && process.platform !== "win32" && process.platform !== "linux") {
|
|
11475
|
+
throw new Error("Claude Desktop launch is supported on macOS, Windows, and Linux only.");
|
|
10708
11476
|
}
|
|
10709
11477
|
}
|
|
10710
11478
|
function run2(cmd, encoding = "utf8") {
|
|
@@ -10746,6 +11514,58 @@ function winClaudeExeCandidates() {
|
|
|
10746
11514
|
}
|
|
10747
11515
|
return out;
|
|
10748
11516
|
}
|
|
11517
|
+
function linuxClaudeCandidates() {
|
|
11518
|
+
return [
|
|
11519
|
+
// Wrapper launcher installed by the .deb/.rpm — sets up the Electron sandbox.
|
|
11520
|
+
"/usr/bin/claude-desktop",
|
|
11521
|
+
"/usr/lib/claude-desktop/claude-desktop",
|
|
11522
|
+
"/opt/Claude/claude-desktop",
|
|
11523
|
+
join12(homedir8(), ".local", "bin", "claude-desktop")
|
|
11524
|
+
];
|
|
11525
|
+
}
|
|
11526
|
+
function linuxWhichClaude() {
|
|
11527
|
+
try {
|
|
11528
|
+
const out = run2("command -v claude-desktop");
|
|
11529
|
+
return out && existsSync12(out) ? out : null;
|
|
11530
|
+
} catch {
|
|
11531
|
+
return null;
|
|
11532
|
+
}
|
|
11533
|
+
}
|
|
11534
|
+
function linuxMatchingPids() {
|
|
11535
|
+
try {
|
|
11536
|
+
const out = run2("pgrep -x claude-desktop");
|
|
11537
|
+
return out.split(/\s+/).map((s) => Number.parseInt(s, 10)).filter((n) => Number.isFinite(n) && n > 0);
|
|
11538
|
+
} catch {
|
|
11539
|
+
return [];
|
|
11540
|
+
}
|
|
11541
|
+
}
|
|
11542
|
+
function linuxMainPid() {
|
|
11543
|
+
const pids = linuxMatchingPids();
|
|
11544
|
+
for (const pid of pids) {
|
|
11545
|
+
try {
|
|
11546
|
+
const cmdline = readFileSync12(`/proc/${pid}/cmdline`, "utf8");
|
|
11547
|
+
if (!cmdline.includes("--type=")) return pid;
|
|
11548
|
+
} catch {
|
|
11549
|
+
}
|
|
11550
|
+
}
|
|
11551
|
+
return pids[0] ?? null;
|
|
11552
|
+
}
|
|
11553
|
+
function linuxQuit() {
|
|
11554
|
+
const pid = linuxMainPid();
|
|
11555
|
+
if (pid === null) return;
|
|
11556
|
+
try {
|
|
11557
|
+
process.kill(pid, "SIGTERM");
|
|
11558
|
+
} catch {
|
|
11559
|
+
}
|
|
11560
|
+
}
|
|
11561
|
+
function linuxForceQuit() {
|
|
11562
|
+
for (const pid of linuxMatchingPids()) {
|
|
11563
|
+
try {
|
|
11564
|
+
process.kill(pid, "SIGKILL");
|
|
11565
|
+
} catch {
|
|
11566
|
+
}
|
|
11567
|
+
}
|
|
11568
|
+
}
|
|
10749
11569
|
function mdfindClaudeApp() {
|
|
10750
11570
|
try {
|
|
10751
11571
|
const out = run2(`mdfind "kMDItemCFBundleIdentifier == '${CLAUDE_BUNDLE_ID}'"`);
|
|
@@ -10777,6 +11597,15 @@ function findClaudeApp() {
|
|
|
10777
11597
|
} catch {
|
|
10778
11598
|
}
|
|
10779
11599
|
}
|
|
11600
|
+
if (process.platform === "linux") {
|
|
11601
|
+
for (const path of linuxClaudeCandidates()) {
|
|
11602
|
+
try {
|
|
11603
|
+
if (existsSync12(path)) return path;
|
|
11604
|
+
} catch {
|
|
11605
|
+
}
|
|
11606
|
+
}
|
|
11607
|
+
return linuxWhichClaude();
|
|
11608
|
+
}
|
|
10780
11609
|
return null;
|
|
10781
11610
|
}
|
|
10782
11611
|
function darwinIsRunning2() {
|
|
@@ -10809,6 +11638,7 @@ function winHasWindow2() {
|
|
|
10809
11638
|
function isClaudeAppRunning() {
|
|
10810
11639
|
if (process.platform === "darwin") return darwinIsRunning2();
|
|
10811
11640
|
if (process.platform === "win32") return winMatchingPids2().length > 0 || winHasWindow2();
|
|
11641
|
+
if (process.platform === "linux") return linuxMatchingPids().length > 0;
|
|
10812
11642
|
return false;
|
|
10813
11643
|
}
|
|
10814
11644
|
function sleep2(ms) {
|
|
@@ -10819,12 +11649,16 @@ async function waitForQuit2(timeoutMs) {
|
|
|
10819
11649
|
while (Date.now() < deadline) {
|
|
10820
11650
|
if (process.platform === "win32") {
|
|
10821
11651
|
if (winMatchingPids2().length === 0) return true;
|
|
11652
|
+
} else if (process.platform === "linux") {
|
|
11653
|
+
if (linuxMatchingPids().length === 0) return true;
|
|
10822
11654
|
} else if (!darwinIsRunning2()) {
|
|
10823
11655
|
return true;
|
|
10824
11656
|
}
|
|
10825
11657
|
await sleep2(200);
|
|
10826
11658
|
}
|
|
10827
|
-
|
|
11659
|
+
if (process.platform === "win32") return winMatchingPids2().length === 0;
|
|
11660
|
+
if (process.platform === "linux") return linuxMatchingPids().length === 0;
|
|
11661
|
+
return !darwinIsRunning2();
|
|
10828
11662
|
}
|
|
10829
11663
|
function openClaudeAppAt(path) {
|
|
10830
11664
|
if (process.platform === "darwin") {
|
|
@@ -10841,6 +11675,10 @@ function openClaudeAppAt(path) {
|
|
|
10841
11675
|
} else {
|
|
10842
11676
|
runPowerShell2(`Start-Process -FilePath '${path.replace(/'/g, "''")}'`);
|
|
10843
11677
|
}
|
|
11678
|
+
return;
|
|
11679
|
+
}
|
|
11680
|
+
if (process.platform === "linux") {
|
|
11681
|
+
spawn3(path, [], { stdio: "ignore", detached: true }).unref();
|
|
10844
11682
|
}
|
|
10845
11683
|
}
|
|
10846
11684
|
function openClaudeApp() {
|
|
@@ -10867,6 +11705,7 @@ function winQuitGraceful2() {
|
|
|
10867
11705
|
function quitClaudeAppGracefully() {
|
|
10868
11706
|
if (process.platform === "darwin") darwinQuit2();
|
|
10869
11707
|
else if (process.platform === "win32") winQuitGraceful2();
|
|
11708
|
+
else if (process.platform === "linux") linuxQuit();
|
|
10870
11709
|
}
|
|
10871
11710
|
function winForceQuit2() {
|
|
10872
11711
|
const pids = winMatchingPids2();
|
|
@@ -10888,9 +11727,11 @@ async function launchOrRestartClaudeApp(prompt = "Restart Claude Desktop to appl
|
|
|
10888
11727
|
return;
|
|
10889
11728
|
}
|
|
10890
11729
|
if (process.platform === "darwin") darwinQuit2();
|
|
10891
|
-
else winQuitGraceful2();
|
|
11730
|
+
else if (process.platform === "win32") winQuitGraceful2();
|
|
11731
|
+
else if (process.platform === "linux") linuxQuit();
|
|
10892
11732
|
if (!await waitForQuit2(5e3)) {
|
|
10893
11733
|
if (process.platform === "win32") winForceQuit2();
|
|
11734
|
+
else if (process.platform === "linux") linuxForceQuit();
|
|
10894
11735
|
await waitForQuit2(5e3);
|
|
10895
11736
|
}
|
|
10896
11737
|
if (appPath) openClaudeAppAt(appPath);
|
|
@@ -11070,6 +11911,13 @@ export {
|
|
|
11070
11911
|
resolveLocalProviderApiKey,
|
|
11071
11912
|
formatRegistryAuthLabel,
|
|
11072
11913
|
resolveProvidersForDisplay,
|
|
11914
|
+
evaluateAgySwitchCompatibility,
|
|
11915
|
+
resolveRelayCatalogSlots,
|
|
11916
|
+
injectRelayModels,
|
|
11917
|
+
buildAntigravityRoutes,
|
|
11918
|
+
buildListModelConfigsResponse,
|
|
11919
|
+
buildListExperimentsResponse,
|
|
11920
|
+
meetsContextFloor,
|
|
11073
11921
|
routableModelsForTarget,
|
|
11074
11922
|
providersForTarget,
|
|
11075
11923
|
refreshProviderModels,
|
|
@@ -11111,4 +11959,4 @@ export {
|
|
|
11111
11959
|
supportsClaudeTransparentMode,
|
|
11112
11960
|
buildHttpProxyRoutes
|
|
11113
11961
|
};
|
|
11114
|
-
//# sourceMappingURL=chunk-
|
|
11962
|
+
//# sourceMappingURL=chunk-6CBNKM55.js.map
|