@linxiraos/pi-catalog 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +79 -0
- package/README.md +4 -2
- package/THIRD-PARTY-NOTICES.txt +55 -5
- package/dist/types/build.d.ts +3 -2
- package/dist/types/compat/auth-ids.d.ts +2 -2
- package/dist/types/compat/axes.d.ts +1 -1
- package/dist/types/compat/behavior.d.ts +5 -0
- package/dist/types/compat/catalog-endpoint.d.ts +8 -0
- package/dist/types/compat/image-tokenization.d.ts +9 -1
- package/dist/types/compat/judgment-images.d.ts +25 -0
- package/dist/types/compat/provider-ids.d.ts +1 -1
- package/dist/types/compat/request-compression.d.ts +23 -0
- package/dist/types/compat/request-size.d.ts +12 -3
- package/dist/types/compat/thinking-replay.d.ts +9 -0
- package/dist/types/compat/types.d.ts +4 -0
- package/dist/types/discovery/antigravity.d.ts +7 -0
- package/dist/types/model-cache.d.ts +7 -0
- package/dist/types/model-manager.d.ts +6 -0
- package/dist/types/model-thinking.d.ts +11 -1
- package/dist/types/models.d.ts +16 -1
- package/dist/types/pricing.d.ts +37 -1
- package/dist/types/provider-models/openai-compat.d.ts +18 -46
- package/dist/types/types.d.ts +63 -12
- package/dist/types/wire/codex.d.ts +2 -0
- package/package.json +6 -6
- package/src/build.d.ts +3 -2
- package/src/build.ts +159 -80
- package/src/compat/auth-ids.ts +2 -0
- package/src/compat/axes.d.ts +1 -1
- package/src/compat/axes.ts +129 -4
- package/src/compat/behavior.d.ts +5 -0
- package/src/compat/behavior.ts +9 -1
- package/src/compat/cascade.ts +4 -1
- package/src/compat/catalog-endpoint.ts +43 -0
- package/src/compat/image-tokenization.ts +28 -10
- package/src/compat/judgment-images.ts +83 -0
- package/src/compat/provider-ids.d.ts +1 -1
- package/src/compat/provider-ids.ts +1 -0
- package/src/compat/request-compression.ts +43 -0
- package/src/compat/request-size.ts +20 -5
- package/src/compat/resolve.ts +90 -53
- package/src/compat/rules/README.md +32 -3
- package/src/compat/rules/auth/_order.kdl +1 -1
- package/src/compat/rules/auth/google-antigravity.kdl +1 -1
- package/src/compat/rules/auth/sambanova.kdl +9 -0
- package/src/compat/rules/auth/stencil.kdl +1 -1
- package/src/compat/rules/classes/anthropic.kdl +42 -2
- package/src/compat/rules/classes/deepseek.kdl +4 -0
- package/src/compat/rules/classes/gemini.kdl +46 -2
- package/src/compat/rules/classes/meta.kdl +7 -0
- package/src/compat/rules/classes/minimax.kdl +11 -1
- package/src/compat/rules/classes/openai.kdl +34 -3
- package/src/compat/rules/classes/xai.kdl +26 -0
- package/src/compat/rules/providers/amazon-bedrock.kdl +1 -0
- package/src/compat/rules/providers/anthropic.kdl +23 -0
- package/src/compat/rules/providers/azure.kdl +2 -0
- package/src/compat/rules/providers/cerebras.kdl +3 -0
- package/src/compat/rules/providers/cline-pass.kdl +16 -0
- package/src/compat/rules/providers/commandcode.kdl +10 -0
- package/src/compat/rules/providers/cursor.kdl +50 -1
- package/src/compat/rules/providers/deepinfra.kdl +3 -1
- package/src/compat/rules/providers/devin.kdl +117 -6
- package/src/compat/rules/providers/factory-droid.kdl +6 -0
- package/src/compat/rules/providers/firepass.kdl +15 -0
- package/src/compat/rules/providers/fireworks.kdl +26 -0
- package/src/compat/rules/providers/github-copilot.kdl +24 -0
- package/src/compat/rules/providers/google-antigravity.kdl +37 -0
- package/src/compat/rules/providers/google-gemini-cli.kdl +1 -0
- package/src/compat/rules/providers/google-vertex.kdl +5 -0
- package/src/compat/rules/providers/google.kdl +1 -0
- package/src/compat/rules/providers/image-tokenization.kdl +2 -1
- package/src/compat/rules/providers/local.kdl +8 -1
- package/src/compat/rules/providers/meta.kdl +16 -0
- package/src/compat/rules/providers/moonshot.kdl +2 -0
- package/src/compat/rules/providers/muse-code.kdl +49 -0
- package/src/compat/rules/providers/native-tools.kdl +3 -0
- package/src/compat/rules/providers/ollama-cloud.kdl +10 -0
- package/src/compat/rules/providers/openai-codex.kdl +29 -5
- package/src/compat/rules/providers/openai.kdl +1 -0
- package/src/compat/rules/providers/opencode-go.kdl +35 -0
- package/src/compat/rules/providers/opencode-zen.kdl +4 -0
- package/src/compat/rules/providers/openrouter.kdl +19 -0
- package/src/compat/rules/providers/sambanova.kdl +60 -0
- package/src/compat/rules/providers/tool-call-names.kdl +37 -0
- package/src/compat/rules/providers/typesafe.kdl +11 -0
- package/src/compat/rules/providers/umans.kdl +7 -0
- package/src/compat/rules/providers/venice.kdl +7 -0
- package/src/compat/rules/providers/xai-oauth.kdl +16 -6
- package/src/compat/rules/providers/xai.kdl +3 -0
- package/src/compat/rules/providers/zai.kdl +5 -0
- package/src/compat/rules/runtime/behavior.kdl +128 -8
- package/src/compat/rules/taxonomy/_collapse.kdl +11 -0
- package/src/compat/rules/taxonomy/gemma.kdl +1 -0
- package/src/compat/rules/taxonomy/meta.kdl +7 -0
- package/src/compat/rules/taxonomy/openai.kdl +2 -0
- package/src/compat/rules.json +1 -1
- package/src/compat/thinking-replay.ts +33 -0
- package/src/compat/types.d.ts +4 -0
- package/src/compat/types.ts +4 -0
- package/src/discovery/antigravity.d.ts +7 -0
- package/src/discovery/antigravity.ts +13 -0
- package/src/discovery/codex.ts +0 -4
- package/src/discovery/cursor.ts +28 -20
- package/src/discovery/devin.ts +7 -8
- package/src/model-cache.d.ts +7 -0
- package/src/model-cache.ts +8 -0
- package/src/model-manager.d.ts +6 -0
- package/src/model-manager.ts +41 -21
- package/src/model-thinking.d.ts +80 -0
- package/src/model-thinking.ts +13 -1
- package/src/model-tokenizer.ts +7 -1
- package/src/models.d.ts +16 -1
- package/src/models.json +1 -1
- package/src/models.ts +26 -12
- package/src/pricing.d.ts +37 -1
- package/src/pricing.ts +123 -12
- package/src/provider-models/bundled-references.ts +5 -2
- package/src/provider-models/cache-provider-id.ts +1 -1
- package/src/provider-models/descriptors.ts +2 -0
- package/src/provider-models/google.ts +7 -1
- package/src/provider-models/openai-compat.d.ts +18 -46
- package/src/provider-models/openai-compat.ts +188 -104
- package/src/provider-models/special.ts +1 -0
- package/src/types.d.ts +63 -12
- package/src/types.ts +71 -9
- package/src/wire/codex.d.ts +2 -0
- package/src/wire/codex.ts +17 -0
|
@@ -39,8 +39,17 @@ import {
|
|
|
39
39
|
type OpenAICompat,
|
|
40
40
|
type Provider,
|
|
41
41
|
type ThinkingConfig,
|
|
42
|
+
type TokenCost,
|
|
42
43
|
} from "../types";
|
|
43
|
-
import {
|
|
44
|
+
import {
|
|
45
|
+
discoveryFetch,
|
|
46
|
+
isAnthropicOAuthToken,
|
|
47
|
+
isRecord,
|
|
48
|
+
toBoolean,
|
|
49
|
+
toNumber,
|
|
50
|
+
toPositiveNumber,
|
|
51
|
+
toPositiveNumberOrNull,
|
|
52
|
+
} from "../utils";
|
|
44
53
|
import { ALIBABA_TOKEN_PLAN_BASE_URL, parseAlibabaTokenPlanCredential } from "../wire/alibaba-token-plan";
|
|
45
54
|
import { normalizeCharmHyperBaseUrl } from "../wire/charm-hyper";
|
|
46
55
|
import { CLINEPASS_API_BASE_URL, clinePassClientHeaders } from "../wire/cline-pass";
|
|
@@ -550,6 +559,40 @@ function mapWithBundledReference<TApi extends Api>(
|
|
|
550
559
|
};
|
|
551
560
|
}
|
|
552
561
|
|
|
562
|
+
/**
|
|
563
|
+
* Rates from an OpenRouter-shaped `pricing` object (USD per token, as decimal
|
|
564
|
+
* strings). Missing, zero, or negative legs (`-1` marks router-priced rows)
|
|
565
|
+
* map to 0, which the model manager fills from its reference sources.
|
|
566
|
+
*/
|
|
567
|
+
function perTokenPricingCost(pricing: unknown): TokenCost {
|
|
568
|
+
const rates = isRecord(pricing) ? pricing : {};
|
|
569
|
+
return {
|
|
570
|
+
input: toPositiveNumber(rates.prompt, 0) * 1_000_000,
|
|
571
|
+
output: toPositiveNumber(rates.completion, 0) * 1_000_000,
|
|
572
|
+
cacheRead: toPositiveNumber(rates.input_cache_read, 0) * 1_000_000,
|
|
573
|
+
cacheWrite: toPositiveNumber(rates.input_cache_write, 0) * 1_000_000,
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Rates from NanoGPT's detailed roster: prompt and completion are USD per
|
|
579
|
+
* million tokens, the cache legs per thousand. Legs the row does not price
|
|
580
|
+
* keep `fallback`.
|
|
581
|
+
*/
|
|
582
|
+
function nanoGptPricingCost(pricing: unknown, fallback: TokenCost): TokenCost {
|
|
583
|
+
if (!isRecord(pricing) || pricing.unit !== "per_million_tokens") return fallback;
|
|
584
|
+
const perThousand = (value: unknown, fallbackRate: number): number => {
|
|
585
|
+
const rate = toPositiveNumber(value, 0);
|
|
586
|
+
return rate > 0 ? rate * 1_000 : fallbackRate;
|
|
587
|
+
};
|
|
588
|
+
return {
|
|
589
|
+
input: toPositiveNumber(pricing.prompt, fallback.input),
|
|
590
|
+
output: toPositiveNumber(pricing.completion, fallback.output),
|
|
591
|
+
cacheRead: perThousand(pricing.cacheReadInputPer1kTokens, fallback.cacheRead),
|
|
592
|
+
cacheWrite: perThousand(pricing.cacheWriteInputPer1kTokens, fallback.cacheWrite),
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
|
|
553
596
|
function normalizeAnthropicBaseUrl(baseUrl: string | undefined, fallback: string): string {
|
|
554
597
|
const value = baseUrl?.trim();
|
|
555
598
|
if (!value) {
|
|
@@ -1265,6 +1308,87 @@ export function cerebrasModelManagerOptions(
|
|
|
1265
1308
|
});
|
|
1266
1309
|
}
|
|
1267
1310
|
|
|
1311
|
+
// ---------------------------------------------------------------------------
|
|
1312
|
+
// 3.5 SambaNova
|
|
1313
|
+
// ---------------------------------------------------------------------------
|
|
1314
|
+
|
|
1315
|
+
/** SambaNova discovery inputs: `apiKey` enables the live roster; `baseUrl` defaults to SambaNova Cloud. */
|
|
1316
|
+
export interface SambaNovaModelManagerConfig {
|
|
1317
|
+
apiKey?: string;
|
|
1318
|
+
baseUrl?: string;
|
|
1319
|
+
fetch?: FetchImpl;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
/**
|
|
1323
|
+
* One SambaNova per-token USD rate (a decimal string) as a per-million rate.
|
|
1324
|
+
* `absent` is the value for a missing field; a present field that is not a
|
|
1325
|
+
* nonnegative number yields `undefined`.
|
|
1326
|
+
*/
|
|
1327
|
+
function sambanovaRate(value: unknown, absent: number | undefined): number | undefined {
|
|
1328
|
+
if (value === undefined || value === null) return absent;
|
|
1329
|
+
const parsed = toNumber(value);
|
|
1330
|
+
return parsed !== undefined && parsed >= 0 ? Math.round(parsed * 1e12) / 1e6 : undefined;
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
/**
|
|
1334
|
+
* Map SambaNova's `pricing` block. Prompt and completion rates are required;
|
|
1335
|
+
* cache rates default to 0 when absent. An unreadable card stays unpriced
|
|
1336
|
+
* (`unknown`) instead of reading as free, and an all-zero card is a declared
|
|
1337
|
+
* free tier.
|
|
1338
|
+
*/
|
|
1339
|
+
function sambanovaPricing(
|
|
1340
|
+
pricing: unknown,
|
|
1341
|
+
fallback: TokenCost,
|
|
1342
|
+
): Pick<ModelSpec<"openai-completions">, "cost" | "pricingStatus"> {
|
|
1343
|
+
const rates = isRecord(pricing) ? pricing : {};
|
|
1344
|
+
const input = sambanovaRate(rates.prompt, undefined);
|
|
1345
|
+
const output = sambanovaRate(rates.completion, undefined);
|
|
1346
|
+
const cacheRead = sambanovaRate(rates.input_cache_read, 0);
|
|
1347
|
+
const cacheWrite = sambanovaRate(rates.input_cache_write, 0);
|
|
1348
|
+
if (input === undefined || output === undefined || cacheRead === undefined || cacheWrite === undefined) {
|
|
1349
|
+
return { cost: fallback, pricingStatus: "unknown" };
|
|
1350
|
+
}
|
|
1351
|
+
const cost = { input, output, cacheRead, cacheWrite };
|
|
1352
|
+
return input + output + cacheRead + cacheWrite === 0 ? { cost, pricingStatus: "free" } : { cost };
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
/**
|
|
1356
|
+
* SambaNova Cloud's model manager. `/v1/models` requires a key, so a keyless
|
|
1357
|
+
* manager serves only the bundled seed; with a key the live roster replaces
|
|
1358
|
+
* it. Rows carry pricing and limits but no capability metadata: reasoning,
|
|
1359
|
+
* thinking wire format, and image input come from `providers/sambanova.kdl`.
|
|
1360
|
+
*/
|
|
1361
|
+
export function sambanovaModelManagerOptions(
|
|
1362
|
+
config?: SambaNovaModelManagerConfig,
|
|
1363
|
+
): ModelManagerOptions<"openai-completions"> {
|
|
1364
|
+
const apiKey = config?.apiKey;
|
|
1365
|
+
const baseUrl = config?.baseUrl ?? "https://api.sambanova.ai/v1";
|
|
1366
|
+
return {
|
|
1367
|
+
providerId: "sambanova",
|
|
1368
|
+
dynamicModelsAuthoritative: true,
|
|
1369
|
+
// The live `pricing` block is the tariff: an explicit `0` must not revert
|
|
1370
|
+
// to the bundled seed's rate.
|
|
1371
|
+
dynamicCostAuthoritative: true,
|
|
1372
|
+
...(apiKey && {
|
|
1373
|
+
fetchDynamicModels: () =>
|
|
1374
|
+
fetchOpenAICompatibleModels({
|
|
1375
|
+
api: "openai-completions",
|
|
1376
|
+
provider: "sambanova",
|
|
1377
|
+
baseUrl,
|
|
1378
|
+
apiKey,
|
|
1379
|
+
filterModel: (_entry, model) => !isExcludedModel("sambanova", model.id),
|
|
1380
|
+
mapModel: (entry, defaults) => ({
|
|
1381
|
+
...defaults,
|
|
1382
|
+
...sambanovaPricing(entry.pricing, defaults.cost),
|
|
1383
|
+
contextWindow: toPositiveNumber(entry.context_length, defaults.contextWindow),
|
|
1384
|
+
maxTokens: toPositiveNumber(entry.max_completion_tokens, defaults.maxTokens),
|
|
1385
|
+
}),
|
|
1386
|
+
fetch: config?.fetch,
|
|
1387
|
+
}),
|
|
1388
|
+
}),
|
|
1389
|
+
};
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1268
1392
|
// ---------------------------------------------------------------------------
|
|
1269
1393
|
// 4. Hugging Face
|
|
1270
1394
|
// ---------------------------------------------------------------------------
|
|
@@ -2296,74 +2420,6 @@ export function zhipuCodingPlanModelManagerOptions(
|
|
|
2296
2420
|
// 7.5 Fireworks
|
|
2297
2421
|
// ---------------------------------------------------------------------------
|
|
2298
2422
|
|
|
2299
|
-
/**
|
|
2300
|
-
* Fireworks-published cap for the Kimi K2 family. Fireworks' `/v1/models`
|
|
2301
|
-
* envelope generically reports `max_completion_tokens: 65536` for every Kimi
|
|
2302
|
-
* deployment, but Kimi K2 (instruct / thinking / turbo) on Fireworks is
|
|
2303
|
-
* documented to ship long reasoning traces that should be bounded — capping
|
|
2304
|
-
* at 32,768 prevents handing callers a budget the router cannot honor.
|
|
2305
|
-
* See https://github.com/can1357/oh-my-pi/issues/1849.
|
|
2306
|
-
*/
|
|
2307
|
-
export const FIREWORKS_KIMI_MAX_TOKENS = 32_768;
|
|
2308
|
-
|
|
2309
|
-
/**
|
|
2310
|
-
* Fireworks' output ceiling for Kimi K2.7-Code specifically. Its `/v1/models`
|
|
2311
|
-
* generic `max_completion_tokens` is 65,536 and Fireworks serves it in full —
|
|
2312
|
-
* verified with a single completion emitting 58,971 output tokens and
|
|
2313
|
-
* `max_tokens: 200000` accepted without error. Unlike the older K2.5/K2.6
|
|
2314
|
-
* family (see {@link FIREWORKS_KIMI_MAX_TOKENS}), K2.7-Code is not clamped to
|
|
2315
|
-
* 32,768; that ceiling only truncated it.
|
|
2316
|
-
*/
|
|
2317
|
-
export const FIREWORKS_KIMI_K27_CODE_MAX_TOKENS = 65_536;
|
|
2318
|
-
|
|
2319
|
-
/**
|
|
2320
|
-
* Returns true for the Kimi K2.5 / K2.6 family served by Fireworks-backed
|
|
2321
|
-
* providers (`fireworks` direct, `firepass` router) that share the 32,768
|
|
2322
|
-
* `maxTokens` ceiling. Matches both the public catalog id (`kimi-k2.5`,
|
|
2323
|
-
* `kimi-k2.6`, `kimi-k2.6-turbo`) and the canonical Fireworks wire id
|
|
2324
|
-
* (`accounts/fireworks/{models,routers}/kimi-k2…`).
|
|
2325
|
-
*
|
|
2326
|
-
* K2.7-Code (incl. `-fast` / `-highspeed`) is deliberately excluded: unlike the
|
|
2327
|
-
* earlier K2 family it serves its full context on Fireworks — verified with a
|
|
2328
|
-
* single completion emitting 58,971 output tokens and `max_tokens: 200000`
|
|
2329
|
-
* accepted without error — so the 32,768 cap would only truncate it. It inherits
|
|
2330
|
-
* Fireworks' reported `max_completion_tokens` (65,536) instead.
|
|
2331
|
-
*/
|
|
2332
|
-
export function isFireworksKimiK2ModelId(modelId: string): boolean {
|
|
2333
|
-
const identity = classifyModel("fireworks", modelId, { lenient: true });
|
|
2334
|
-
if (identity.class !== "kimi" || identity.family === "k2.7-code") return false;
|
|
2335
|
-
return identity.family?.startsWith("k2") === true;
|
|
2336
|
-
}
|
|
2337
|
-
|
|
2338
|
-
/**
|
|
2339
|
-
* Clamp the Kimi K2 family's `maxTokens` to {@link FIREWORKS_KIMI_MAX_TOKENS}
|
|
2340
|
-
* on Fireworks-backed providers, leaving every other model untouched.
|
|
2341
|
-
*/
|
|
2342
|
-
export function clampFireworksKimiMaxTokens(modelId: string, candidate: number): number;
|
|
2343
|
-
export function clampFireworksKimiMaxTokens(modelId: string, candidate: number | null): number | null;
|
|
2344
|
-
export function clampFireworksKimiMaxTokens(modelId: string, candidate: number | null): number | null {
|
|
2345
|
-
if (candidate === null) return null;
|
|
2346
|
-
return isFireworksKimiK2ModelId(modelId) ? Math.min(candidate, FIREWORKS_KIMI_MAX_TOKENS) : candidate;
|
|
2347
|
-
}
|
|
2348
|
-
|
|
2349
|
-
/**
|
|
2350
|
-
* Kimi K2.7 Code's documented recommended output budget. Some provider
|
|
2351
|
-
* discovery rows report the context-sized `max_completion_tokens` instead.
|
|
2352
|
-
*/
|
|
2353
|
-
export const KIMI_K27_CODE_RECOMMENDED_MAX_TOKENS = 32_768;
|
|
2354
|
-
|
|
2355
|
-
export function isKimiK27CodeModelId(modelId: string): boolean {
|
|
2356
|
-
const identity = classifyModel("fireworks", modelId, { lenient: true });
|
|
2357
|
-
return identity.class === "kimi" && identity.family === "k2.7-code";
|
|
2358
|
-
}
|
|
2359
|
-
|
|
2360
|
-
export function clampKimiK27CodeMaxTokens(modelId: string, candidate: number): number;
|
|
2361
|
-
export function clampKimiK27CodeMaxTokens(modelId: string, candidate: number | null): number | null;
|
|
2362
|
-
export function clampKimiK27CodeMaxTokens(modelId: string, candidate: number | null): number | null {
|
|
2363
|
-
if (candidate === null) return null;
|
|
2364
|
-
return isKimiK27CodeModelId(modelId) ? Math.min(candidate, KIMI_K27_CODE_RECOMMENDED_MAX_TOKENS) : candidate;
|
|
2365
|
-
}
|
|
2366
|
-
|
|
2367
2423
|
/**
|
|
2368
2424
|
* Fireworks Fast variants we surface: the Fast table on
|
|
2369
2425
|
* https://docs.fireworks.ai/serverless/serverless-modes, minus the US-only
|
|
@@ -2493,15 +2549,9 @@ function mapFireworksControlPlaneModel(
|
|
|
2493
2549
|
const supportsImage = toBoolean(record.supportsImageInput) === true;
|
|
2494
2550
|
const supportsTools = toBoolean(record.supportsTools);
|
|
2495
2551
|
const contextWindow = toPositiveNumber(record.contextLength, reference?.contextWindow ?? null);
|
|
2496
|
-
// The control plane reports no max-output budget
|
|
2497
|
-
//
|
|
2498
|
-
|
|
2499
|
-
const fallbackMaxTokens = isKimiK27CodeModelId(publicModelId)
|
|
2500
|
-
? FIREWORKS_KIMI_K27_CODE_MAX_TOKENS
|
|
2501
|
-
: isFireworksKimiK2ModelId(publicModelId)
|
|
2502
|
-
? FIREWORKS_KIMI_MAX_TOKENS
|
|
2503
|
-
: null;
|
|
2504
|
-
const maxTokens = clampFireworksKimiMaxTokens(publicModelId, reference?.maxTokens ?? fallbackMaxTokens);
|
|
2552
|
+
// The control plane reports no max-output budget; Fireworks' per-model
|
|
2553
|
+
// output caps and fallbacks are rule-owned (providers/fireworks.kdl).
|
|
2554
|
+
const maxTokens = reference?.maxTokens ?? null;
|
|
2505
2555
|
const base: ModelSpec<"openai-completions"> = reference ?? {
|
|
2506
2556
|
id: publicModelId,
|
|
2507
2557
|
name,
|
|
@@ -2941,8 +2991,9 @@ function buildClinePassFreeModel(id: string, liveCatalog?: ClinePassLiveCatalog)
|
|
|
2941
2991
|
input: upstream?.input ?? live?.input ?? fallback.input,
|
|
2942
2992
|
contextWindow: upstream?.contextWindow ?? live?.contextWindow ?? fallback.contextWindow,
|
|
2943
2993
|
maxTokens: upstream?.maxTokens ?? live?.maxTokens ?? fallback.maxTokens,
|
|
2944
|
-
//
|
|
2945
|
-
|
|
2994
|
+
// No reasoning-effort control means no effort ladder: the cline-pass
|
|
2995
|
+
// rules trust only explicit thinking, so a copied ladder would surface.
|
|
2996
|
+
thinking: undefined,
|
|
2946
2997
|
compat: { supportsReasoningEffort: false, wireModelIdMode: "raw" },
|
|
2947
2998
|
};
|
|
2948
2999
|
}
|
|
@@ -3215,12 +3266,18 @@ export interface OpenCodeModelManagerConfig {
|
|
|
3215
3266
|
fetch?: FetchImpl;
|
|
3216
3267
|
}
|
|
3217
3268
|
|
|
3269
|
+
const OPENCODE_ZEN_BASE_PATH = "https://opencode.ai/zen";
|
|
3270
|
+
const OPENCODE_ZEN_GOOGLE_BASE_URL = "https://opencode.ai/inference/google/v1beta";
|
|
3271
|
+
|
|
3218
3272
|
function normalizeOpenCodeBasePath(baseUrl: string | undefined, fallbackBasePath: string): string {
|
|
3219
3273
|
const value = normalizeAnthropicBaseUrl(baseUrl, fallbackBasePath);
|
|
3220
3274
|
return value.endsWith("/v1") ? value.slice(0, -3) : value;
|
|
3221
3275
|
}
|
|
3222
3276
|
|
|
3223
3277
|
function openCodeBaseUrlForApi(api: Api, basePath: string): string {
|
|
3278
|
+
if (api === "google-generative-ai" && basePath === OPENCODE_ZEN_BASE_PATH) {
|
|
3279
|
+
return OPENCODE_ZEN_GOOGLE_BASE_URL;
|
|
3280
|
+
}
|
|
3224
3281
|
return api === "anthropic-messages" ? basePath : `${basePath}/v1`;
|
|
3225
3282
|
}
|
|
3226
3283
|
|
|
@@ -3234,7 +3291,12 @@ function openCodeBaseUrlForApi(api: Api, basePath: string): string {
|
|
|
3234
3291
|
// rules (`runtime/behavior.kdl`; #887, #1617, #8957).
|
|
3235
3292
|
// Runtime-discovered rows cached before model-identity corrections retain
|
|
3236
3293
|
// stale capability metadata until the authoritative catalog TTL expires.
|
|
3237
|
-
const OPENCODE_CACHE_MIGRATION_MODEL_IDS = [
|
|
3294
|
+
const OPENCODE_CACHE_MIGRATION_MODEL_IDS = [
|
|
3295
|
+
"deepseek-flash",
|
|
3296
|
+
"glm-5.3-flash",
|
|
3297
|
+
"longcat-2.5-preview-free",
|
|
3298
|
+
"space-bunny-free",
|
|
3299
|
+
] as const;
|
|
3238
3300
|
const OPENCODE_ZEN_CACHE_MIGRATION_MODEL_IDS = ["gemini-3.7-flash", "gemini-3.8-flash"] as const;
|
|
3239
3301
|
|
|
3240
3302
|
// Billing-variant suffixes the OpenCode gateways append to a base model id
|
|
@@ -3269,7 +3331,10 @@ function openCodeModelManagerOptions(
|
|
|
3269
3331
|
const apiOverrides = (id: string): Api | undefined => {
|
|
3270
3332
|
// Route pins live in the `api-routes` behavior rules.
|
|
3271
3333
|
const route = apiRouteFor(providerId, id)?.api;
|
|
3272
|
-
return route === "openai-completions" ||
|
|
3334
|
+
return route === "openai-completions" ||
|
|
3335
|
+
route === "openai-responses" ||
|
|
3336
|
+
route === "anthropic-messages" ||
|
|
3337
|
+
route === "google-generative-ai"
|
|
3273
3338
|
? route
|
|
3274
3339
|
: undefined;
|
|
3275
3340
|
};
|
|
@@ -3893,6 +3958,7 @@ export function kiloModelManagerOptions(config?: KiloModelManagerConfig): ModelM
|
|
|
3893
3958
|
provider: "kilo",
|
|
3894
3959
|
baseUrl,
|
|
3895
3960
|
apiKey,
|
|
3961
|
+
mapModel: (entry, defaults) => ({ ...defaults, cost: perTokenPricingCost(entry.pricing) }),
|
|
3896
3962
|
fetch: config?.fetch,
|
|
3897
3963
|
}),
|
|
3898
3964
|
};
|
|
@@ -4570,11 +4636,7 @@ export function veniceModelManagerOptions(
|
|
|
4570
4636
|
config,
|
|
4571
4637
|
mapModel: (entry, defaults, reference) => {
|
|
4572
4638
|
const model = mapWithBundledReference(entry, defaults, reference);
|
|
4573
|
-
return {
|
|
4574
|
-
...model,
|
|
4575
|
-
maxTokens: clampKimiK27CodeMaxTokens(defaults.id, model.maxTokens),
|
|
4576
|
-
compat: { ...model.compat, supportsUsageInStreaming: false },
|
|
4577
|
-
};
|
|
4639
|
+
return { ...model, compat: { ...model.compat, supportsUsageInStreaming: false } };
|
|
4578
4640
|
},
|
|
4579
4641
|
});
|
|
4580
4642
|
}
|
|
@@ -4727,7 +4789,9 @@ function museSparkLineageSpec(id: string): ModelSpec<"openai-responses"> | undef
|
|
|
4727
4789
|
let templateRevision: readonly [number, number, number] | undefined;
|
|
4728
4790
|
for (const model of seedModels<"openai-responses">("meta")) {
|
|
4729
4791
|
if ((billingVariantPlain(model.id) !== undefined) !== contributor) continue;
|
|
4730
|
-
const
|
|
4792
|
+
const seedIdentity = classifyModel("meta", model.id, { lenient: true });
|
|
4793
|
+
if (seedIdentity.family !== "muse-spark") continue;
|
|
4794
|
+
const candidate = parseRevision(seedIdentity.revision ?? "");
|
|
4731
4795
|
if (candidate === undefined) continue;
|
|
4732
4796
|
if (templateRevision === undefined || compareRevision(candidate, templateRevision) > 0) {
|
|
4733
4797
|
template = model;
|
|
@@ -6282,10 +6346,29 @@ export function nanoGptModelManagerOptions(
|
|
|
6282
6346
|
provider: "nanogpt",
|
|
6283
6347
|
baseUrl,
|
|
6284
6348
|
apiKey,
|
|
6349
|
+
// Only the detailed roster carries per-model pricing, names, and limits.
|
|
6350
|
+
query: { detailed: "true" },
|
|
6285
6351
|
mapModel: (entry, defaults) => {
|
|
6286
6352
|
const reference = resolveReference(defaults.id);
|
|
6287
|
-
|
|
6288
|
-
|
|
6353
|
+
// The detailed roster names its output cap `max_output_tokens`.
|
|
6354
|
+
const maxOutputTokens = entry.max_output_tokens ?? entry.max_completion_tokens;
|
|
6355
|
+
const mapped = mapWithBundledReference(
|
|
6356
|
+
{ ...entry, max_completion_tokens: maxOutputTokens },
|
|
6357
|
+
reference
|
|
6358
|
+
? defaults
|
|
6359
|
+
: {
|
|
6360
|
+
...defaults,
|
|
6361
|
+
contextWindow: toPositiveNumberOrNull(entry.context_length),
|
|
6362
|
+
maxTokens: toPositiveNumberOrNull(maxOutputTokens),
|
|
6363
|
+
},
|
|
6364
|
+
reference,
|
|
6365
|
+
);
|
|
6366
|
+
return {
|
|
6367
|
+
...mapped,
|
|
6368
|
+
api: "openai-completions",
|
|
6369
|
+
provider: "nanogpt",
|
|
6370
|
+
cost: { ...mapped.cost, ...nanoGptPricingCost(entry.pricing, mapped.cost) },
|
|
6371
|
+
};
|
|
6289
6372
|
},
|
|
6290
6373
|
filterModel: (_entry, model) => {
|
|
6291
6374
|
const match = NANO_GPT_THINKING_SUFFIX_RE.exec(model.id);
|
|
@@ -6969,13 +7052,10 @@ function createOpenCodeApiResolution(
|
|
|
6969
7052
|
rules: ApiResolutionRule[];
|
|
6970
7053
|
} {
|
|
6971
7054
|
const completionsBaseUrl = `${basePath}/v1`;
|
|
6972
|
-
|
|
6973
|
-
// - openai-completions / openai-responses / google-generative-ai → /v1
|
|
6974
|
-
// - anthropic-messages → bare basePath (the Anthropic client appends /v1/messages)
|
|
6975
|
-
const baseUrlForApi = (api: Api): string => (api === "anthropic-messages" ? basePath : completionsBaseUrl);
|
|
7055
|
+
const baseUrlForApi = (api: Api): string => openCodeBaseUrlForApi(api, basePath);
|
|
6976
7056
|
// Per-id route pins live in the `api-routes` behavior rules.
|
|
6977
7057
|
const overrideRules: ApiResolutionRule[] = (
|
|
6978
|
-
["openai-completions", "openai-responses", "anthropic-messages"] as const
|
|
7058
|
+
["openai-completions", "openai-responses", "anthropic-messages", "google-generative-ai"] as const
|
|
6979
7059
|
).map(api => ({
|
|
6980
7060
|
matches: modelId => apiRouteFor(providerId, modelId)?.api === api,
|
|
6981
7061
|
resolved: { api, baseUrl: baseUrlForApi(api) },
|
|
@@ -7004,8 +7084,17 @@ function createOpenCodeApiResolution(
|
|
|
7004
7084
|
|
|
7005
7085
|
// Resolver rules for the models.dev descriptor path; the per-id pins live in
|
|
7006
7086
|
// the `api-routes` behavior rules, which also drive the live-discovery mapper.
|
|
7007
|
-
const OPENCODE_ZEN_API_RESOLUTION = createOpenCodeApiResolution(
|
|
7008
|
-
const
|
|
7087
|
+
const OPENCODE_ZEN_API_RESOLUTION = createOpenCodeApiResolution(OPENCODE_ZEN_BASE_PATH, "opencode-zen");
|
|
7088
|
+
const OPENCODE_GO_BASE_PATH = "https://opencode.ai/inference/go";
|
|
7089
|
+
const OPENCODE_GO_API_RESOLUTION = createOpenCodeApiResolution(OPENCODE_GO_BASE_PATH, "opencode-go");
|
|
7090
|
+
|
|
7091
|
+
/**
|
|
7092
|
+
* OpenCode Go endpoint for one request API. The model generator re-bases
|
|
7093
|
+
* previous-snapshot rows with it so retained rows follow endpoint moves.
|
|
7094
|
+
*/
|
|
7095
|
+
export function openCodeGoBaseUrlForApi(api: Api): string {
|
|
7096
|
+
return openCodeBaseUrlForApi(api, OPENCODE_GO_BASE_PATH);
|
|
7097
|
+
}
|
|
7009
7098
|
|
|
7010
7099
|
const COPILOT_BASE_URL = "https://api.githubcopilot.com";
|
|
7011
7100
|
|
|
@@ -7383,7 +7472,7 @@ const OPENCODE_MODELS_DEV_DESCRIPTORS: readonly ModelsDevProviderDescriptor[] =
|
|
|
7383
7472
|
OPENCODE_ZEN_API_RESOLUTION.defaultResolution,
|
|
7384
7473
|
),
|
|
7385
7474
|
}),
|
|
7386
|
-
openAiCompletionsDescriptor("opencode-go", "opencode-go",
|
|
7475
|
+
openAiCompletionsDescriptor("opencode-go", "opencode-go", `${OPENCODE_GO_BASE_PATH}/v1`, {
|
|
7387
7476
|
filterModel: filterActiveToolCallModels,
|
|
7388
7477
|
resolveApi: (modelId, raw) =>
|
|
7389
7478
|
resolveApiByRules(
|
|
@@ -7464,12 +7553,7 @@ const MODELS_DEV_PROVIDER_DESCRIPTORS_SPECIALIZED: readonly ModelsDevProviderDes
|
|
|
7464
7553
|
// --- Synthetic ---
|
|
7465
7554
|
openAiCompletionsDescriptor("synthetic", "synthetic", "https://api.synthetic.new/openai/v1"),
|
|
7466
7555
|
// --- Venice AI ---
|
|
7467
|
-
openAiCompletionsDescriptor("venice", "venice", "https://api.venice.ai/api/v1",
|
|
7468
|
-
transformModel: model => {
|
|
7469
|
-
const maxTokens = clampKimiK27CodeMaxTokens(model.id, model.maxTokens);
|
|
7470
|
-
return maxTokens === model.maxTokens ? model : { ...model, maxTokens };
|
|
7471
|
-
},
|
|
7472
|
-
}),
|
|
7556
|
+
openAiCompletionsDescriptor("venice", "venice", "https://api.venice.ai/api/v1"),
|
|
7473
7557
|
// --- Ollama Cloud ---
|
|
7474
7558
|
simpleModelsDevDescriptor("ollama-cloud", "ollama-cloud", "ollama-chat", "https://ollama.com"),
|
|
7475
7559
|
// --- Xiaomi Token Plan ---
|
|
@@ -64,6 +64,7 @@ export function openaiCodexModelManagerOptions(
|
|
|
64
64
|
providerId: "openai-codex",
|
|
65
65
|
cacheProviderId: resolveModelCacheProviderId("openai-codex", { baseUrl }),
|
|
66
66
|
dynamicModelsAuthoritative: providerEntry("openai-codex")?.dynamicModelsAuthoritative === true,
|
|
67
|
+
keepStaticNames: providerEntry("openai-codex")?.keepBundledNames === true,
|
|
67
68
|
...(resolveAccounts
|
|
68
69
|
? {
|
|
69
70
|
fetchDynamicModels: async () => {
|
package/src/types.d.ts
CHANGED
|
@@ -93,6 +93,14 @@ export interface ThinkingConfig {
|
|
|
93
93
|
* provides an explicit wire off-path.
|
|
94
94
|
*/
|
|
95
95
|
requiresEffort?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* The catalog has no evidence this model reasons (unclassified id, no
|
|
98
|
+
* capability metadata). The ladder is offered for the user to opt into:
|
|
99
|
+
* sessions leave thinking unset until the user picks an effort, and a
|
|
100
|
+
* request without an effort goes out as non-reasoning (see
|
|
101
|
+
* `withoutUnverifiedThinking`).
|
|
102
|
+
*/
|
|
103
|
+
unverified?: boolean;
|
|
96
104
|
}
|
|
97
105
|
export type Provider = string;
|
|
98
106
|
/** Token budgets for each thinking level (token-based providers only) */
|
|
@@ -443,6 +451,8 @@ export interface OpenAICompat {
|
|
|
443
451
|
reasoningDeltasMayBeCumulative?: boolean;
|
|
444
452
|
/** Strip leaked DeepSeek chat-template special tokens from visible content deltas. Default: auto-detected. */
|
|
445
453
|
stripDeepseekSpecialTokens?: boolean;
|
|
454
|
+
/** Drop assistant thinking blocks from replayed chat-completions history. Default: false. */
|
|
455
|
+
stripThinkingHistory?: boolean;
|
|
446
456
|
/** Heal leaked chat-template/tool-call/thinking markup from visible content deltas. Default: auto-detected. */
|
|
447
457
|
streamMarkupHealingPattern?: OpenAIStreamMarkupHealingPattern;
|
|
448
458
|
/** Whether this wire may revise already-streamed text (`stream-revision` axis). Unassigned: append-only. */
|
|
@@ -492,6 +502,14 @@ export interface AnthropicCompat {
|
|
|
492
502
|
* contract instead. Default: false.
|
|
493
503
|
*/
|
|
494
504
|
firstPartyProvider?: boolean;
|
|
505
|
+
/**
|
|
506
|
+
* Whether the provider honors Claude Code's `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS`
|
|
507
|
+
* kill switch, which withholds pre-release fields (`context_management`, beta
|
|
508
|
+
* tool fields, task budgets, structured-output format, `thinking.block_binding`,
|
|
509
|
+
* server compaction) with their betas. Rule-owned on the
|
|
510
|
+
* provider whose `ANTHROPIC_*` env routing Claude Code shares. Default: false.
|
|
511
|
+
*/
|
|
512
|
+
honorsClaudeCodeBetaKillSwitch?: boolean;
|
|
495
513
|
/**
|
|
496
514
|
* Whether requests may carry `output_config.effort` (and its effort beta
|
|
497
515
|
* header). Vertex AI rejects the field/header. Default: true.
|
|
@@ -858,12 +876,15 @@ export interface ResolvedOpenAISharedCompat {
|
|
|
858
876
|
* `buildModel`; request handlers read fields and never detect, resolve, or
|
|
859
877
|
* allocate.
|
|
860
878
|
*/
|
|
861
|
-
export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat & Required<Omit<OpenAICompat, "supportsDeveloperRole" | "supportsReasoningEffort" | "trustExplicitThinkingOnly" | "reasoningEffortMap" | "supportsReasoningParams" | "supportsReasoningSummary" | "statefulResponses" | "supportsSamplingParams" | "supportsPenaltyAndStopParams" | "thinkingFormat" | "kimiApiFormat" | "reasoningDisableMode" | "omitReasoningEffort" | "includeEncryptedReasoning" | "filterReasoningHistory" | "disableReasoningOnForcedToolChoice" | "disableReasoningOnToolChoice" | "disableReasoningWithTools" | "supportsToolChoice" | "supportsForcedToolChoice" | "supportsNamedToolChoice" | "reasoningContentField" | "mistralReasoningContentParts" | "requiresReasoningContentForToolCalls" | "requiresReasoningContentForAllAssistantTurns" | "allowsSyntheticReasoningContentForToolCalls" | "syntheticReasoningContentFallback" | "replayReasoningContent" | "qwenPreserveThinking" | "qwenTemplateReasoningEffort" | "requiresThinkingAsText" | "requiresMistralToolIds" | "requiresToolResultName" | "requiresAssistantAfterToolResult" | "requiresAssistantContentForToolCalls" | "stripDeepseekSpecialTokens" | "streamMarkupHealingPattern" | "reasoningDeltasMayBeCumulative" | "emptyLengthFinishIsContextError" | "usesOpenAIToolCallIdLimit" | "promptCacheSessionHeader" | "sessionHeader" | "supportsPromptCacheBreakpoints" | "promptCacheBreakpointTtl" | "openRouterRouting" | "isOpenRouterHost" | "supportsStrictMode" | "supportsLongPromptCacheRetention" | "alwaysSendMaxTokens" | "clampOutputToModelMax" | "wireModelIdMode" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolSchemaFlavor" | "streamFirstEventTimeoutMs" | "streamIdleTimeoutMs" | "streamRevision" | "cacheControlFormat" | "thinkingKeep" | "strictResponsesPairing" | "supportsImageDetailOriginal" | "supportsConfigurationUpdate" | "supportsSteering" | "stripImageInput" | "thinkingLoopGuard" | "whenThinking">> & {
|
|
879
|
+
export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat & Required<Omit<OpenAICompat, "supportsDeveloperRole" | "supportsReasoningEffort" | "trustExplicitThinkingOnly" | "reasoningEffortMap" | "supportsReasoningParams" | "supportsReasoningSummary" | "statefulResponses" | "supportsSamplingParams" | "supportsPenaltyAndStopParams" | "thinkingFormat" | "kimiApiFormat" | "reasoningDisableMode" | "omitReasoningEffort" | "includeEncryptedReasoning" | "filterReasoningHistory" | "disableReasoningOnForcedToolChoice" | "disableReasoningOnToolChoice" | "disableReasoningWithTools" | "supportsToolChoice" | "supportsForcedToolChoice" | "supportsNamedToolChoice" | "reasoningContentField" | "mistralReasoningContentParts" | "requiresReasoningContentForToolCalls" | "requiresReasoningContentForAllAssistantTurns" | "allowsSyntheticReasoningContentForToolCalls" | "syntheticReasoningContentFallback" | "replayReasoningContent" | "qwenPreserveThinking" | "qwenTemplateReasoningEffort" | "requiresThinkingAsText" | "requiresMistralToolIds" | "requiresToolResultName" | "requiresAssistantAfterToolResult" | "requiresAssistantContentForToolCalls" | "stripDeepseekSpecialTokens" | "stripThinkingHistory" | "streamMarkupHealingPattern" | "reasoningDeltasMayBeCumulative" | "emptyLengthFinishIsContextError" | "usesOpenAIToolCallIdLimit" | "promptCacheSessionHeader" | "sessionHeader" | "supportsPromptCacheBreakpoints" | "promptCacheBreakpointTtl" | "openRouterRouting" | "isOpenRouterHost" | "supportsStrictMode" | "supportsLongPromptCacheRetention" | "alwaysSendMaxTokens" | "clampOutputToModelMax" | "wireModelIdMode" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolSchemaFlavor" | "streamFirstEventTimeoutMs" | "streamIdleTimeoutMs" | "streamRevision" | "cacheControlFormat" | "thinkingKeep" | "strictResponsesPairing" | "supportsImageDetailOriginal" | "supportsConfigurationUpdate" | "supportsSteering" | "stripImageInput" | "thinkingLoopGuard" | "whenThinking">> & {
|
|
862
880
|
vercelGatewayRouting?: OpenAICompat["vercelGatewayRouting"];
|
|
863
881
|
extraBody?: OpenAICompat["extraBody"];
|
|
864
882
|
cacheControlFormat?: OpenAICompat["cacheControlFormat"];
|
|
865
883
|
thinkingKeep?: OpenAICompat["thinkingKeep"];
|
|
866
884
|
streamIdleTimeoutMs?: number;
|
|
885
|
+
stripThinkingHistory?: boolean;
|
|
886
|
+
/** The configured `baseUrl` is the official OpenAI API (provider `openai`); unset otherwise. */
|
|
887
|
+
officialEndpoint?: boolean;
|
|
867
888
|
toolStrictMode: ResolvedToolStrictMode;
|
|
868
889
|
/** The model sits behind Vercel AI Gateway. */
|
|
869
890
|
isVercelGatewayHost: boolean;
|
|
@@ -928,9 +949,11 @@ export interface ResolvedOpenAIResponsesCompat extends ResolvedOpenAISharedCompa
|
|
|
928
949
|
isVercelGatewayHost: boolean;
|
|
929
950
|
/**
|
|
930
951
|
* The configured endpoint is first-party OpenAI (`provider === "openai"` on
|
|
931
|
-
* an `api.openai.com` or unset baseUrl)
|
|
932
|
-
*
|
|
933
|
-
*
|
|
952
|
+
* an `api.openai.com` or unset baseUrl), or the Codex backend
|
|
953
|
+
* (`openai-codex-responses` on the default Codex baseUrl). Gates platform
|
|
954
|
+
* OpenAI's official-only Responses behavior (default-on stateful
|
|
955
|
+
* `previous_response_id` chaining and the `text.verbosity` field; the Codex
|
|
956
|
+
* adapter is not governed by either gate) and host request-size budgets.
|
|
934
957
|
*/
|
|
935
958
|
officialEndpoint: boolean;
|
|
936
959
|
/** Run Harmony-protocol leak detection/mitigation on streamed output. */
|
|
@@ -1055,23 +1078,43 @@ export interface GoogleCompat {
|
|
|
1055
1078
|
antigravityUsageLabel?: string;
|
|
1056
1079
|
/** Strip image inputs before encoding (text-only serving of a multimodal id). */
|
|
1057
1080
|
stripImageInput?: boolean;
|
|
1081
|
+
/**
|
|
1082
|
+
* Largest width or height a single image may carry for a Claude reader on
|
|
1083
|
+
* this host (see {@link AnthropicCompat.maxImageDimension}). Setting this or
|
|
1084
|
+
* {@link maxImagePayloadBytes} turns on Claude's image clamp, many-image
|
|
1085
|
+
* cap included; unset leaves images as sent.
|
|
1086
|
+
*/
|
|
1087
|
+
maxImageDimension?: number;
|
|
1088
|
+
/**
|
|
1089
|
+
* Largest base64 payload a single image may carry, in bytes (see
|
|
1090
|
+
* {@link AnthropicCompat.maxImagePayloadBytes}).
|
|
1091
|
+
*/
|
|
1092
|
+
maxImagePayloadBytes?: number;
|
|
1058
1093
|
/** Thinking-loop watchdog guard family applied to streamed reasoning. */
|
|
1059
1094
|
thinkingLoopGuard?: "gemini" | "deepseek" | "xai";
|
|
1060
1095
|
/** See {@link BedrockCompat.supportsSamplingParams}. */
|
|
1061
1096
|
supportsSamplingParams?: boolean;
|
|
1062
1097
|
}
|
|
1063
1098
|
/** Fully-resolved google-API compat view, materialized once by `buildModel`. */
|
|
1064
|
-
export type ResolvedGoogleCompat = Required<Omit<GoogleCompat, "streamFirstEventTimeoutMs" | "streamIdleTimeoutMs" | "thinkingLoopGuard" | "antigravityUsageLabel" | "supportsSamplingParams">> & {
|
|
1099
|
+
export type ResolvedGoogleCompat = Required<Omit<GoogleCompat, "streamFirstEventTimeoutMs" | "streamIdleTimeoutMs" | "thinkingLoopGuard" | "antigravityUsageLabel" | "supportsSamplingParams" | "maxImageDimension" | "maxImagePayloadBytes">> & {
|
|
1065
1100
|
streamFirstEventTimeoutMs?: number;
|
|
1066
1101
|
streamIdleTimeoutMs?: number;
|
|
1067
1102
|
thinkingLoopGuard?: GoogleCompat["thinkingLoopGuard"];
|
|
1068
1103
|
antigravityUsageLabel?: string;
|
|
1069
1104
|
supportsSamplingParams?: boolean;
|
|
1105
|
+
maxImageDimension?: number;
|
|
1106
|
+
maxImagePayloadBytes?: number;
|
|
1070
1107
|
};
|
|
1108
|
+
/** Ollama chat history compatibility resolved by the catalog. */
|
|
1109
|
+
export interface OllamaCompat {
|
|
1110
|
+
/** Omit assistant thinking when the deployment rejects it in history. */
|
|
1111
|
+
stripThinkingHistory?: boolean;
|
|
1112
|
+
}
|
|
1113
|
+
export type ResolvedOllamaCompat = Required<OllamaCompat>;
|
|
1071
1114
|
/** Sparse, user-authored compat overrides for a given API (models.json / config vocabulary). */
|
|
1072
|
-
export type CompatConfigOf<TApi extends Api> = TApi extends "openai-completions" | "openrouter" | "openai-responses" | "azure-openai-responses" | "openai-codex-responses" ? OpenAICompat : TApi extends "anthropic-messages" ? AnthropicCompat : TApi extends "bedrock-converse-stream" ? BedrockCompat : TApi extends "devin-agent" ? DevinCompat : TApi extends "google-generative-ai" | "google-vertex" | "google-gemini-cli" ? GoogleCompat : undefined;
|
|
1115
|
+
export type CompatConfigOf<TApi extends Api> = TApi extends "openai-completions" | "openrouter" | "openai-responses" | "azure-openai-responses" | "openai-codex-responses" ? OpenAICompat : TApi extends "anthropic-messages" ? AnthropicCompat : TApi extends "bedrock-converse-stream" ? BedrockCompat : TApi extends "devin-agent" ? DevinCompat : TApi extends "google-generative-ai" | "google-vertex" | "google-gemini-cli" ? GoogleCompat : TApi extends "ollama-chat" ? OllamaCompat : undefined;
|
|
1073
1116
|
/** Resolved compat for a given API: complete record, materialized once by `buildModel`. */
|
|
1074
|
-
export type CompatOf<TApi extends Api> = TApi extends "openrouter" ? ResolvedOpenRouterCompat : TApi extends "openai-completions" ? ResolvedOpenAICompat : TApi extends "openai-responses" | "azure-openai-responses" | "openai-codex-responses" ? ResolvedOpenAIResponsesCompat : TApi extends "anthropic-messages" ? ResolvedAnthropicCompat : TApi extends "bedrock-converse-stream" ? ResolvedBedrockCompat : TApi extends "devin-agent" ? ResolvedDevinCompat : TApi extends "google-generative-ai" | "google-vertex" | "google-gemini-cli" ? ResolvedGoogleCompat : undefined;
|
|
1117
|
+
export type CompatOf<TApi extends Api> = TApi extends "openrouter" ? ResolvedOpenRouterCompat : TApi extends "openai-completions" ? ResolvedOpenAICompat : TApi extends "openai-responses" | "azure-openai-responses" | "openai-codex-responses" ? ResolvedOpenAIResponsesCompat : TApi extends "anthropic-messages" ? ResolvedAnthropicCompat : TApi extends "bedrock-converse-stream" ? ResolvedBedrockCompat : TApi extends "devin-agent" ? ResolvedDevinCompat : TApi extends "google-generative-ai" | "google-vertex" | "google-gemini-cli" ? ResolvedGoogleCompat : TApi extends "ollama-chat" ? ResolvedOllamaCompat : undefined;
|
|
1075
1118
|
/** Provider-native compaction endpoint configuration for one model. */
|
|
1076
1119
|
export interface RemoteCompactionConfig<TApi extends Api = Api> {
|
|
1077
1120
|
/** Enables provider-native compaction for providers not enabled by built-in policy. */
|
|
@@ -1145,7 +1188,7 @@ export interface ModelCost extends TokenCost {
|
|
|
1145
1188
|
* generations rather than providers: DeepSeek V3 through V4 share
|
|
1146
1189
|
* `"deepseek-v3"`; Kimi K2 through K3 share `"kimi-k2"`.
|
|
1147
1190
|
*/
|
|
1148
|
-
export type ModelTokenizer = "claude-v3" | "claude-v47" | "claude-v5" | "claude-v5-sonnet" | "qwen3" | "deepseek-v3" | "kimi-k2" | "glm5";
|
|
1191
|
+
export type ModelTokenizer = "claude-v3" | "claude-v47" | "claude-v5" | "claude-v5-sonnet" | "qwen3" | "deepseek-v3" | "kimi-k2" | "glm5" | "o200k";
|
|
1149
1192
|
/** One account's discovered entitlements on a model; see {@link Model.accountAccess}. */
|
|
1150
1193
|
export interface ModelAccountAccess {
|
|
1151
1194
|
/**
|
|
@@ -1198,6 +1241,8 @@ export interface Model<TApi extends Api = Api> {
|
|
|
1198
1241
|
requiresGlyphTokenization?: boolean;
|
|
1199
1242
|
/** Whether this model requires Cursor's tool-schema combiner projection. */
|
|
1200
1243
|
requiresCursorToolSchemaProjection?: boolean;
|
|
1244
|
+
/** Whether advertised tool schemas occupy every model request's context (false for deferred catalogs). */
|
|
1245
|
+
toolSchemasInContext?: boolean;
|
|
1201
1246
|
/** Whether this model requires tool-result images hoisted into sibling user content blocks. */
|
|
1202
1247
|
requiresToolResultImageHoisting?: boolean;
|
|
1203
1248
|
/**
|
|
@@ -1246,6 +1291,12 @@ export interface Model<TApi extends Api = Api> {
|
|
|
1246
1291
|
* than ZETA's general image pipeline. `stb` local backends reject WebP.
|
|
1247
1292
|
*/
|
|
1248
1293
|
imageInputDecoder?: "stb";
|
|
1294
|
+
/**
|
|
1295
|
+
* Most images one request may carry, from user configuration. Replaces the
|
|
1296
|
+
* catalog's `image-count-budget` for hosts no rule names, such as a custom
|
|
1297
|
+
* gateway in front of a vendor with a higher limit.
|
|
1298
|
+
*/
|
|
1299
|
+
imageCountBudget?: number;
|
|
1249
1300
|
/**
|
|
1250
1301
|
* Native provider tool-call support. `false` is the only unsupported signal:
|
|
1251
1302
|
* `true` and `undefined` both mean callers may use native tools. Catalog and
|
|
@@ -1328,6 +1379,8 @@ export interface Model<TApi extends Api = Api> {
|
|
|
1328
1379
|
contextWindow: number | null;
|
|
1329
1380
|
/** Preserve the host's supplied window instead of applying inferred expansion or reference-price caps. */
|
|
1330
1381
|
contextWindowAuthoritative?: boolean;
|
|
1382
|
+
/** The long-context price tier does not cap the runtime context window when extended context is off. */
|
|
1383
|
+
longContextWindowUncapped?: boolean;
|
|
1331
1384
|
/** Optional larger prompt window available when extended context is enabled. */
|
|
1332
1385
|
maxContextWindow?: number;
|
|
1333
1386
|
maxTokens: number | null;
|
|
@@ -1354,7 +1407,7 @@ export interface Model<TApi extends Api = Api> {
|
|
|
1354
1407
|
* Streaming transport override. When `"pi-native"`, `streamSimple` routes
|
|
1355
1408
|
* the request to the model's `baseUrl` via the auth-gateway's
|
|
1356
1409
|
* `POST /v1/pi/stream` endpoint instead of dispatching the per-API
|
|
1357
|
-
* provider client. The `baseUrl` must point at an `
|
|
1410
|
+
* provider client. The `baseUrl` must point at an `zetacode auth-gateway`
|
|
1358
1411
|
* (or compatible) host; `headers.Authorization` (or `apiKey` resolved by
|
|
1359
1412
|
* the registry) carries the gateway bearer.
|
|
1360
1413
|
*
|
|
@@ -1369,8 +1422,6 @@ export interface Model<TApi extends Api = Api> {
|
|
|
1369
1422
|
preferWebsockets?: boolean;
|
|
1370
1423
|
/** Codex Responses Lite transport: send the lite marker and carry instructions/tools as input items (mirrors codex-rs `use_responses_lite`). */
|
|
1371
1424
|
useResponsesLite?: boolean;
|
|
1372
|
-
/** Codex Code Mode restriction: model expects tools routed through a programmatic exec surface (mirrors codex-rs `tool_mode`). */
|
|
1373
|
-
toolMode?: "code_mode_only";
|
|
1374
1425
|
/**
|
|
1375
1426
|
* Service-tier ids the provider advertises for this model (Codex discovery
|
|
1376
1427
|
* `service_tiers[].id`, e.g. `priority`, `ultrafast`). Absent when the
|
|
@@ -1463,7 +1514,7 @@ export interface Model<TApi extends Api = Api> {
|
|
|
1463
1514
|
* vocabulary of `buildModel`. Identical to `Model` except `compat` carries the
|
|
1464
1515
|
* sparse override shape and nothing is resolved yet.
|
|
1465
1516
|
*/
|
|
1466
|
-
export interface ModelSpec<TApi extends Api = Api> extends Omit<Model<TApi>, "compat" | "identity" | "compatConfig" | "requiresGlyphTokenization" | "requiresCursorToolSchemaProjection" | "requiresToolResultImageHoisting" | "supportsAssistantPrefill" | "supportsComputerUseConfig"> {
|
|
1517
|
+
export interface ModelSpec<TApi extends Api = Api> extends Omit<Model<TApi>, "compat" | "identity" | "compatConfig" | "requiresGlyphTokenization" | "requiresCursorToolSchemaProjection" | "toolSchemasInContext" | "requiresToolResultImageHoisting" | "supportsAssistantPrefill" | "supportsComputerUseConfig"> {
|
|
1467
1518
|
/** Sparse compatibility overrides; resolved into `Model.compat` by `buildModel`. */
|
|
1468
1519
|
compat?: CompatConfigOf<TApi>;
|
|
1469
1520
|
}
|