@linxiraos/pi-catalog 1.1.26 → 1.2.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 +4 -6
- package/dist/types/compat/auth-ids.d.ts +2 -2
- package/dist/types/compat/collapse.d.ts +7 -0
- package/dist/types/compat/image-tokenization.d.ts +52 -0
- package/dist/types/compat/judgment-questions.d.ts +7 -0
- package/dist/types/compat/prompt-cache-lookback.d.ts +7 -0
- package/dist/types/compat/provider-ids.d.ts +1 -1
- package/dist/types/compat/reasoning-carry.d.ts +21 -0
- package/dist/types/compat/request-size.d.ts +7 -0
- package/dist/types/compat/taxonomy.d.ts +0 -10
- package/dist/types/compat/types.d.ts +4 -0
- package/dist/types/discovery/antigravity.d.ts +13 -3
- package/dist/types/hosts.d.ts +4 -0
- package/dist/types/model-cache.d.ts +6 -0
- package/dist/types/model-manager.d.ts +16 -0
- package/dist/types/provider-models/account-access.d.ts +11 -0
- package/dist/types/provider-models/google.d.ts +23 -1
- package/dist/types/provider-models/openai-compat.d.ts +19 -1
- package/dist/types/provider-models/special.d.ts +8 -0
- package/dist/types/types.d.ts +134 -23
- package/dist/types/wire/cloudflare-ai-gateway.d.ts +0 -10
- package/dist/types/wire/cloudflare.d.ts +10 -0
- package/dist/types/wire/factory-droid.d.ts +1 -1
- package/dist/types/wire/gemini-headers.d.ts +6 -3
- package/package.json +4 -4
- package/src/build.ts +39 -35
- package/src/compat/auth-ids.ts +6 -0
- package/src/compat/axes.ts +43 -5
- package/src/compat/cascade.ts +6 -1
- package/src/compat/collapse.d.ts +7 -0
- package/src/compat/collapse.ts +11 -0
- package/src/compat/image-tokenization.ts +166 -0
- package/src/compat/judgment-questions.ts +12 -0
- package/src/compat/prompt-cache-lookback.ts +23 -0
- package/src/compat/provider-ids.d.ts +1 -1
- package/src/compat/provider-ids.ts +3 -0
- package/src/compat/reasoning-carry.ts +64 -0
- package/src/compat/request-size.ts +25 -0
- package/src/compat/resolve.ts +36 -25
- package/src/compat/rules/README.md +13 -3
- package/src/compat/rules/auth/_order.kdl +2 -2
- package/src/compat/rules/auth/cloudflare-workers-ai.kdl +9 -0
- package/src/compat/rules/auth/coralbricks.kdl +13 -0
- package/src/compat/rules/auth/minimax-code-cn.kdl +1 -1
- package/src/compat/rules/auth/minimax-code.kdl +1 -1
- package/src/compat/rules/auth/openai-codex.kdl +1 -1
- package/src/compat/rules/auth/snowflake.kdl +11 -0
- package/src/compat/rules/auth/stencil.kdl +1 -1
- package/src/compat/rules/classes/anthropic.kdl +188 -7
- package/src/compat/rules/classes/deepseek.kdl +11 -3
- package/src/compat/rules/classes/gemini.kdl +12 -0
- package/src/compat/rules/classes/glm.kdl +17 -8
- package/src/compat/rules/classes/kimi.kdl +15 -0
- package/src/compat/rules/classes/meta.kdl +4 -4
- package/src/compat/rules/classes/minimax.kdl +31 -1
- package/src/compat/rules/classes/openai.kdl +114 -4
- package/src/compat/rules/classes/qwen.kdl +2 -1
- package/src/compat/rules/providers/abliteration.kdl +7 -0
- package/src/compat/rules/providers/amazon-bedrock.kdl +0 -7
- package/src/compat/rules/providers/anthropic.kdl +13 -0
- package/src/compat/rules/providers/apple.kdl +1 -0
- package/src/compat/rules/providers/cloudflare-workers-ai.kdl +34 -0
- package/src/compat/rules/providers/coralbricks.kdl +62 -0
- package/src/compat/rules/providers/cursor.kdl +28 -8
- package/src/compat/rules/providers/devin.kdl +2 -2
- package/src/compat/rules/providers/factory-droid.kdl +77 -13
- package/src/compat/rules/providers/github-copilot.kdl +29 -0
- package/src/compat/rules/providers/google-antigravity.kdl +8 -1
- package/src/compat/rules/providers/groq.kdl +21 -0
- package/src/compat/rules/providers/image-tokenization.kdl +42 -0
- package/src/compat/rules/providers/judgment-questions.kdl +53 -0
- package/src/compat/rules/providers/litellm.kdl +4 -1
- package/src/compat/rules/providers/meta.kdl +3 -3
- package/src/compat/rules/providers/minimax-code-cn.kdl +10 -5
- package/src/compat/rules/providers/minimax-code.kdl +10 -5
- package/src/compat/rules/providers/mistral.kdl +25 -1
- package/src/compat/rules/providers/moonshot.kdl +11 -0
- package/src/compat/rules/providers/muse-code.kdl +7 -0
- package/src/compat/rules/providers/ollama.kdl +3 -0
- package/src/compat/rules/providers/openai-codex.kdl +18 -13
- package/src/compat/rules/providers/openai.kdl +22 -0
- package/src/compat/rules/providers/opencode-go.kdl +11 -0
- package/src/compat/rules/providers/opencode-zen.kdl +20 -0
- package/src/compat/rules/providers/openrouter.kdl +6 -0
- package/src/compat/rules/providers/snowflake.kdl +135 -0
- package/src/compat/rules/providers/tool-result-images.kdl +16 -0
- package/src/compat/rules/providers/zhipu-coding-plan.kdl +10 -0
- package/src/compat/rules/runtime/behavior.kdl +8 -5
- package/src/compat/rules/taxonomy/_collapse.kdl +52 -2
- package/src/compat/rules/taxonomy/deepseek.kdl +4 -0
- package/src/compat/rules/taxonomy/kimi.kdl +5 -0
- package/src/compat/rules.json +1 -1
- package/src/compat/taxonomy.d.ts +0 -10
- package/src/compat/taxonomy.ts +3 -3
- package/src/compat/types.d.ts +4 -0
- package/src/compat/types.ts +4 -0
- package/src/discovery/antigravity.d.ts +13 -3
- package/src/discovery/antigravity.ts +33 -17
- package/src/discovery/cursor.ts +28 -4
- package/src/discovery/devin.ts +20 -2
- package/src/hosts.d.ts +4 -0
- package/src/hosts.ts +2 -0
- package/src/model-cache.d.ts +6 -0
- package/src/model-cache.ts +123 -47
- package/src/model-manager.d.ts +16 -0
- package/src/model-manager.ts +107 -41
- package/src/model-tokenizer.ts +3 -0
- package/src/models.json +1 -1
- package/src/provider-models/account-access.d.ts +11 -0
- package/src/provider-models/account-access.ts +30 -0
- package/src/provider-models/cache-provider-id.ts +13 -6
- package/src/provider-models/cline-pass.ts +33 -0
- package/src/provider-models/descriptors.ts +4 -0
- package/src/provider-models/google.d.ts +23 -1
- package/src/provider-models/google.ts +72 -14
- package/src/provider-models/openai-compat.d.ts +19 -1
- package/src/provider-models/openai-compat.ts +281 -42
- package/src/provider-models/special.d.ts +8 -0
- package/src/provider-models/special.ts +26 -22
- package/src/types.d.ts +134 -23
- package/src/types.ts +183 -20
- package/src/wire/cloudflare-ai-gateway.d.ts +0 -10
- package/src/wire/cloudflare-ai-gateway.ts +0 -36
- package/src/wire/cloudflare.ts +40 -0
- package/src/wire/factory-droid.d.ts +1 -1
- package/src/wire/factory-droid.ts +1 -1
- package/src/wire/gemini-headers.d.ts +6 -3
- package/src/wire/gemini-headers.ts +39 -21
|
@@ -1071,8 +1071,8 @@ export interface OpenAIModelManagerConfig {
|
|
|
1071
1071
|
fetch?: FetchImpl;
|
|
1072
1072
|
}
|
|
1073
1073
|
|
|
1074
|
-
export function openaiModelManagerOptions(config?: OpenAIModelManagerConfig): ModelManagerOptions<
|
|
1075
|
-
|
|
1074
|
+
export function openaiModelManagerOptions(config?: OpenAIModelManagerConfig): ModelManagerOptions<Api> {
|
|
1075
|
+
const options = createOpenAICompatibleModelManagerOptions({
|
|
1076
1076
|
api: "openai-responses",
|
|
1077
1077
|
providerId: "openai",
|
|
1078
1078
|
defaultBaseUrl: OPENAI_API_BASE_URL,
|
|
@@ -1081,6 +1081,30 @@ export function openaiModelManagerOptions(config?: OpenAIModelManagerConfig): Mo
|
|
|
1081
1081
|
filterModel: (_entry, model, references) => isLikelyOpenAIResponsesModelId(model.id, references),
|
|
1082
1082
|
mapModel: mapWithBundledReference,
|
|
1083
1083
|
});
|
|
1084
|
+
const fetchDiscovered = options.fetchDynamicModels;
|
|
1085
|
+
if (!fetchDiscovered) return options;
|
|
1086
|
+
return {
|
|
1087
|
+
...options,
|
|
1088
|
+
fetchDynamicModels: async () => appendUnbundledSeedModels("openai", await fetchDiscovered()),
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
/**
|
|
1093
|
+
* Append the authored seed rows that neither discovery nor the bundled catalog
|
|
1094
|
+
* carries yet: a seed added since the last models.json regeneration (the
|
|
1095
|
+
* Decisions judge row) reaches runtime through a successful discovery. Seeds
|
|
1096
|
+
* already bundled keep resolving through the bundled slice, and the static
|
|
1097
|
+
* catalog (and with it the cache fingerprint) stays the bundled one.
|
|
1098
|
+
*/
|
|
1099
|
+
function appendUnbundledSeedModels(
|
|
1100
|
+
providerId: GeneratedProvider,
|
|
1101
|
+
discovered: readonly ModelSpec<Api>[] | null,
|
|
1102
|
+
): readonly ModelSpec<Api>[] | null {
|
|
1103
|
+
if (!discovered) return null;
|
|
1104
|
+
const known = new Set(getBundledModels(providerId).map(model => model.id));
|
|
1105
|
+
for (const model of discovered) known.add(model.id);
|
|
1106
|
+
const seeds = seedModels(providerId).filter(seed => !known.has(seed.id));
|
|
1107
|
+
return seeds.length === 0 ? discovered : [...discovered, ...seeds.map(seed => ({ ...seed }))];
|
|
1084
1108
|
}
|
|
1085
1109
|
|
|
1086
1110
|
/**
|
|
@@ -1618,10 +1642,171 @@ export function deepinfraModelManagerOptions(
|
|
|
1618
1642
|
return {
|
|
1619
1643
|
providerId: "deepinfra",
|
|
1620
1644
|
dynamicModelsAuthoritative: true,
|
|
1645
|
+
// `vision`/`vlm` tags are the whole truth for modality on this host.
|
|
1646
|
+
dynamicInputAuthoritative: true,
|
|
1621
1647
|
fetchDynamicModels: () => fetchDeepinfraModels({ baseUrl, apiKey, fetch: config?.fetch, references }),
|
|
1622
1648
|
};
|
|
1623
1649
|
}
|
|
1624
1650
|
|
|
1651
|
+
// ---------------------------------------------------------------------------
|
|
1652
|
+
// CoralBricks
|
|
1653
|
+
// ---------------------------------------------------------------------------
|
|
1654
|
+
|
|
1655
|
+
export const CORALBRICKS_BASE_URL = "https://inference.coralbricks.ai/v1";
|
|
1656
|
+
|
|
1657
|
+
/** CoralBricks OpenAI-compatible discovery configuration. */
|
|
1658
|
+
export interface CoralbricksModelManagerConfig {
|
|
1659
|
+
apiKey?: string;
|
|
1660
|
+
baseUrl?: string;
|
|
1661
|
+
fetch?: FetchImpl;
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
/**
|
|
1665
|
+
* The CoralBricks-specific fields of a `GET /v1/models` row: per-million USD
|
|
1666
|
+
* pricing and the capability flags Coral documents as authoritative
|
|
1667
|
+
* (https://www.coralbricks.ai/docs.md).
|
|
1668
|
+
*/
|
|
1669
|
+
interface CoralbricksModelRecord extends OpenAICompatibleModelRecord {
|
|
1670
|
+
context_length?: unknown;
|
|
1671
|
+
pricing?: unknown;
|
|
1672
|
+
supports_chat?: unknown;
|
|
1673
|
+
supports_image_input?: unknown;
|
|
1674
|
+
supports_tools?: unknown;
|
|
1675
|
+
supports_reasoning?: unknown;
|
|
1676
|
+
reasoning?: unknown;
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
/**
|
|
1680
|
+
* Read one live per-million price; a missing or negative field falls back to
|
|
1681
|
+
* the bundled reference. An explicit `0` is a real price: the manager keeps it
|
|
1682
|
+
* because `coralbricksModelManagerOptions` declares `dynamicCostAuthoritative`.
|
|
1683
|
+
*/
|
|
1684
|
+
function coralRate(value: unknown, fallback: number): number {
|
|
1685
|
+
const parsed = toNumber(value);
|
|
1686
|
+
return parsed !== undefined && parsed >= 0 ? parsed : fallback;
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
/**
|
|
1690
|
+
* Map one CoralBricks catalog row to a chat model spec; non-chat rows
|
|
1691
|
+
* (`supports_chat: false`) are dropped. Pricing arrives in Coral's own
|
|
1692
|
+
* per-million field names; `cached_input_per_m` is $0 on every model and a
|
|
1693
|
+
* missing field falls back to the bundled reference.
|
|
1694
|
+
* Live reasoning capabilities and controls override the bundled fallback.
|
|
1695
|
+
* The endpoint publishes no output cap, so `maxTokens` keeps its reference
|
|
1696
|
+
* value rather than being invented from the context window.
|
|
1697
|
+
*/
|
|
1698
|
+
function mapCoralbricksModel(
|
|
1699
|
+
entry: CoralbricksModelRecord,
|
|
1700
|
+
defaults: ModelSpec<"openai-completions">,
|
|
1701
|
+
reference: ModelSpec<"openai-completions"> | undefined,
|
|
1702
|
+
): ModelSpec<"openai-completions"> | null {
|
|
1703
|
+
if (entry.supports_chat === false) {
|
|
1704
|
+
return null;
|
|
1705
|
+
}
|
|
1706
|
+
const pricing = isRecord(entry.pricing) ? entry.pricing : {};
|
|
1707
|
+
// A bundled reference may lend metadata, but its runner kind is not
|
|
1708
|
+
// evidence the chat roster advertised it.
|
|
1709
|
+
const { kind: _inheritedKind, ...chatReference } = reference ?? {};
|
|
1710
|
+
const hasReasoningFlag = typeof entry.supports_reasoning === "boolean";
|
|
1711
|
+
const reasoning = hasReasoningFlag
|
|
1712
|
+
? entry.supports_reasoning === true
|
|
1713
|
+
: (reference?.reasoning ?? defaults.reasoning);
|
|
1714
|
+
const controls = isRecord(entry.reasoning) ? entry.reasoning : undefined;
|
|
1715
|
+
const wireEfforts = controls?.supported_efforts;
|
|
1716
|
+
let thinking = reasoning ? reference?.thinking : undefined;
|
|
1717
|
+
let compat = reference?.compat;
|
|
1718
|
+
if (reasoning && Array.isArray(wireEfforts)) {
|
|
1719
|
+
const efforts = THINKING_EFFORTS.filter(effort => wireEfforts.includes(effort));
|
|
1720
|
+
// `none` is the server's off default, not an Effort (nor `minimal`).
|
|
1721
|
+
const defaultLevel = efforts.find(effort => effort === controls?.default_effort);
|
|
1722
|
+
thinking =
|
|
1723
|
+
efforts.length > 0
|
|
1724
|
+
? {
|
|
1725
|
+
mode: "effort",
|
|
1726
|
+
efforts,
|
|
1727
|
+
...(defaultLevel !== undefined && { defaultLevel }),
|
|
1728
|
+
...(typeof controls?.mandatory === "boolean" && { requiresEffort: controls.mandatory }),
|
|
1729
|
+
}
|
|
1730
|
+
: undefined;
|
|
1731
|
+
}
|
|
1732
|
+
if (hasReasoningFlag || Array.isArray(wireEfforts)) {
|
|
1733
|
+
// An explicit empty/unknown vocabulary must not regrow a guessed dial
|
|
1734
|
+
// from identity or KDL. Missing legacy metadata still uses the reference.
|
|
1735
|
+
compat = { ...compat, trustExplicitThinkingOnly: true };
|
|
1736
|
+
}
|
|
1737
|
+
if (reasoning && controls) {
|
|
1738
|
+
if (controls.mandatory === true || controls.disable === null) {
|
|
1739
|
+
compat = { ...compat, reasoningDisableMode: "lowest-effort" };
|
|
1740
|
+
} else if (isRecord(controls.disable) && controls.disable.reasoning_effort === "none") {
|
|
1741
|
+
compat = { ...compat, reasoningDisableMode: "none-effort" };
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
const input: ("text" | "image")[] =
|
|
1745
|
+
entry.supports_image_input === true
|
|
1746
|
+
? ["text", "image"]
|
|
1747
|
+
: entry.supports_image_input === false
|
|
1748
|
+
? ["text"]
|
|
1749
|
+
: (reference?.input ?? defaults.input);
|
|
1750
|
+
return {
|
|
1751
|
+
...defaults,
|
|
1752
|
+
...chatReference,
|
|
1753
|
+
id: defaults.id,
|
|
1754
|
+
name: reference?.name ?? defaults.name,
|
|
1755
|
+
api: defaults.api,
|
|
1756
|
+
provider: defaults.provider,
|
|
1757
|
+
baseUrl: defaults.baseUrl,
|
|
1758
|
+
reasoning,
|
|
1759
|
+
thinking,
|
|
1760
|
+
compat,
|
|
1761
|
+
input,
|
|
1762
|
+
...(typeof entry.supports_tools === "boolean" ? { supportsTools: entry.supports_tools } : {}),
|
|
1763
|
+
cost: {
|
|
1764
|
+
input: coralRate(pricing.input_per_m, reference?.cost.input ?? 0),
|
|
1765
|
+
output: coralRate(pricing.output_per_m, reference?.cost.output ?? 0),
|
|
1766
|
+
cacheRead: coralRate(pricing.cached_input_per_m, reference?.cost.cacheRead ?? 0),
|
|
1767
|
+
cacheWrite: coralRate(pricing.cache_write_per_m, reference?.cost.cacheWrite ?? 0),
|
|
1768
|
+
},
|
|
1769
|
+
contextWindow: toPositiveNumber(entry.context_length, reference?.contextWindow ?? null),
|
|
1770
|
+
maxTokens: reference?.maxTokens ?? null,
|
|
1771
|
+
};
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
/**
|
|
1775
|
+
* Builds CoralBricks' model-discovery manager. `/v1/models` is key-protected
|
|
1776
|
+
* (401 without a bearer key), so a keyless config serves only the bundled
|
|
1777
|
+
* reviewed seed rows; with a key, live rows are authoritative over the bundle.
|
|
1778
|
+
*/
|
|
1779
|
+
export function coralbricksModelManagerOptions(
|
|
1780
|
+
config?: CoralbricksModelManagerConfig,
|
|
1781
|
+
): ModelManagerOptions<"openai-completions"> {
|
|
1782
|
+
const apiKey = config?.apiKey;
|
|
1783
|
+
const baseUrl = config?.baseUrl ?? CORALBRICKS_BASE_URL;
|
|
1784
|
+
const references = createBundledReferenceMap<"openai-completions">("coralbricks");
|
|
1785
|
+
return {
|
|
1786
|
+
providerId: "coralbricks",
|
|
1787
|
+
dynamicModelsAuthoritative: true,
|
|
1788
|
+
dynamicReasoningAuthoritative: true,
|
|
1789
|
+
// `supports_image_input` is the row's whole truth for modality (Coral
|
|
1790
|
+
// answers unsupported content with `400 unsupported_content_type`).
|
|
1791
|
+
dynamicInputAuthoritative: true,
|
|
1792
|
+
// Coral's `pricing` block is the deployment tariff; an explicit live `0`
|
|
1793
|
+
// (a free model or no cache-write charge) must not revert to the bundle.
|
|
1794
|
+
dynamicCostAuthoritative: true,
|
|
1795
|
+
...(apiKey && {
|
|
1796
|
+
fetchDynamicModels: () =>
|
|
1797
|
+
fetchOpenAICompatibleModels({
|
|
1798
|
+
api: "openai-completions",
|
|
1799
|
+
provider: "coralbricks",
|
|
1800
|
+
baseUrl,
|
|
1801
|
+
apiKey,
|
|
1802
|
+
fetch: config?.fetch,
|
|
1803
|
+
mapModel: (entry, defaults) =>
|
|
1804
|
+
mapCoralbricksModel(entry as CoralbricksModelRecord, defaults, references.get(defaults.id)),
|
|
1805
|
+
}),
|
|
1806
|
+
}),
|
|
1807
|
+
};
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1625
1810
|
// ---------------------------------------------------------------------------
|
|
1626
1811
|
// 6. xAI
|
|
1627
1812
|
// ---------------------------------------------------------------------------
|
|
@@ -2180,21 +2365,24 @@ export function clampKimiK27CodeMaxTokens(modelId: string, candidate: number | n
|
|
|
2180
2365
|
}
|
|
2181
2366
|
|
|
2182
2367
|
/**
|
|
2183
|
-
* Fireworks Fast variants we surface
|
|
2184
|
-
*
|
|
2185
|
-
*
|
|
2186
|
-
*
|
|
2187
|
-
*
|
|
2188
|
-
*
|
|
2368
|
+
* Fireworks Fast variants we surface: the Fast table on
|
|
2369
|
+
* https://docs.fireworks.ai/serverless/serverless-modes, minus the US-only
|
|
2370
|
+
* router (it needs the `us.api.fireworks.ai` host). That table, not a request
|
|
2371
|
+
* outcome, decides membership: add or drop a row when Fireworks changes it.
|
|
2372
|
+
* Each inherits the base model's limits/modalities/thinking and overrides
|
|
2373
|
+
* only the cost with the Fast prices from the Serverless pricing table;
|
|
2374
|
+
* `cacheWrite` stays 0 (Fireworks bills no cache-write). Derived from the
|
|
2375
|
+
* bundled base entries so metadata stays in lockstep, and the runtime
|
|
2376
|
+
* auto-falls back to the base id on a failed fast request.
|
|
2377
|
+
* See https://docs.fireworks.ai/serverless/pricing.
|
|
2189
2378
|
*/
|
|
2190
2379
|
const FIREWORKS_FAST_VARIANT_SPECS: ReadonlyArray<{
|
|
2191
2380
|
base: string;
|
|
2192
2381
|
name: string;
|
|
2193
2382
|
cost: { input: number; output: number; cacheRead: number };
|
|
2194
2383
|
}> = [
|
|
2195
|
-
{ base: "kimi-
|
|
2196
|
-
{ base: "
|
|
2197
|
-
{ base: "glm-5.1", name: "GLM-5.1 Fast", cost: { input: 2.8, output: 8.8, cacheRead: 0.52 } },
|
|
2384
|
+
{ base: "kimi-k3", name: "Kimi K3 Fast", cost: { input: 4.5, output: 22.5, cacheRead: 0.45 } },
|
|
2385
|
+
{ base: "glm-5.3", name: "GLM-5.3 Fast", cost: { input: 2.1, output: 6.6, cacheRead: 0.39 } },
|
|
2198
2386
|
{ base: "glm-5.2", name: "GLM-5.2 Fast", cost: { input: 2.1, output: 6.6, cacheRead: 0.21 } },
|
|
2199
2387
|
];
|
|
2200
2388
|
|
|
@@ -2299,6 +2487,7 @@ function mapFireworksControlPlaneModel(
|
|
|
2299
2487
|
publicModelId: string,
|
|
2300
2488
|
reference: ModelSpec<"openai-completions"> | undefined,
|
|
2301
2489
|
baseUrl: string,
|
|
2490
|
+
cost: ModelSpec<"openai-completions">["cost"] | undefined,
|
|
2302
2491
|
): ModelSpec<"openai-completions"> {
|
|
2303
2492
|
const name = toModelName(record.displayName, reference?.name ?? publicModelId);
|
|
2304
2493
|
const supportsImage = toBoolean(record.supportsImageInput) === true;
|
|
@@ -2332,6 +2521,7 @@ function mapFireworksControlPlaneModel(
|
|
|
2332
2521
|
provider: "fireworks",
|
|
2333
2522
|
baseUrl,
|
|
2334
2523
|
name,
|
|
2524
|
+
cost: cost ?? base.cost,
|
|
2335
2525
|
// The control plane exposes capability flags but no reasoning bit. Every
|
|
2336
2526
|
// serverless chat LLM Fireworks ships reasons, and `buildModel` derives
|
|
2337
2527
|
// the Fireworks effort map from the id at build time — so default
|
|
@@ -2355,6 +2545,7 @@ async function fetchFireworksServerlessModels(options: {
|
|
|
2355
2545
|
baseUrl: string;
|
|
2356
2546
|
apiKey: string;
|
|
2357
2547
|
resolveReference: (publicModelId: string) => ModelSpec<"openai-completions"> | undefined;
|
|
2548
|
+
resolveCost: (publicModelId: string) => ModelSpec<"openai-completions">["cost"] | undefined;
|
|
2358
2549
|
fetch?: FetchImpl;
|
|
2359
2550
|
}): Promise<ModelSpec<"openai-completions">[] | null> {
|
|
2360
2551
|
const listUrl = toFireworksControlPlaneModelsUrl(options.baseUrl, FIREWORKS_CONTROL_PLANE_ACCOUNT);
|
|
@@ -2401,6 +2592,7 @@ async function fetchFireworksServerlessModels(options: {
|
|
|
2401
2592
|
publicModelId,
|
|
2402
2593
|
options.resolveReference(publicModelId),
|
|
2403
2594
|
options.baseUrl,
|
|
2595
|
+
options.resolveCost(publicModelId),
|
|
2404
2596
|
),
|
|
2405
2597
|
);
|
|
2406
2598
|
}
|
|
@@ -2449,6 +2641,39 @@ async function loadModelsDevReferences<TApi extends Api>(fetchImpl?: FetchImpl):
|
|
|
2449
2641
|
return new Map<string, ModelSpec<TApi>>();
|
|
2450
2642
|
}
|
|
2451
2643
|
}
|
|
2644
|
+
|
|
2645
|
+
/**
|
|
2646
|
+
* Fireworks' own models.dev rows, consulted only for pricing during dynamic
|
|
2647
|
+
* discovery. A bare-id reference comes from whichever host carries the id with
|
|
2648
|
+
* the largest window, so its price is often another host's, and Fireworks-only
|
|
2649
|
+
* models have none. models.dev keys these rows by wire id
|
|
2650
|
+
* (`accounts/fireworks/models/glm-5p3`), so they are re-keyed to public ids.
|
|
2651
|
+
* Rows that publish no price are skipped so the reference price stays; a
|
|
2652
|
+
* published zero is Fireworks' price and wins. Absent from
|
|
2653
|
+
* `MODELS_DEV_PROVIDER_DESCRIPTORS`: the control plane alone decides which
|
|
2654
|
+
* models exist.
|
|
2655
|
+
*/
|
|
2656
|
+
const FIREWORKS_MODELS_DEV_DESCRIPTORS: readonly ModelsDevProviderDescriptor[] = [
|
|
2657
|
+
openAiCompletionsDescriptor("fireworks-ai", "fireworks", "https://api.fireworks.ai/inference/v1", {
|
|
2658
|
+
// `mapModelsDevToModels` maps an absent price to zeros, so tell them apart on the raw row.
|
|
2659
|
+
filterModel: (_id, raw) => typeof raw.cost?.input === "number" || typeof raw.cost?.output === "number",
|
|
2660
|
+
}),
|
|
2661
|
+
];
|
|
2662
|
+
|
|
2663
|
+
async function loadFireworksModelsDevCosts(
|
|
2664
|
+
fetchImpl?: FetchImpl,
|
|
2665
|
+
): Promise<Map<string, ModelSpec<"openai-completions">["cost"]>> {
|
|
2666
|
+
const costs = new Map<string, ModelSpec<"openai-completions">["cost"]>();
|
|
2667
|
+
try {
|
|
2668
|
+
const payload = await fetchWellKnownModels(fetchImpl);
|
|
2669
|
+
for (const model of mapModelsDevToModels(payload as Record<string, unknown>, FIREWORKS_MODELS_DEV_DESCRIPTORS)) {
|
|
2670
|
+
costs.set(toFireworksPublicModelId(model.id), model.cost);
|
|
2671
|
+
}
|
|
2672
|
+
} catch {
|
|
2673
|
+
// Optional enrichment: without it, discovered rows keep their reference price.
|
|
2674
|
+
}
|
|
2675
|
+
return costs;
|
|
2676
|
+
}
|
|
2452
2677
|
export function fireworksModelManagerOptions(
|
|
2453
2678
|
config?: FireworksModelManagerConfig,
|
|
2454
2679
|
): ModelManagerOptions<"openai-completions"> {
|
|
@@ -2461,12 +2686,17 @@ export function fireworksModelManagerOptions(
|
|
|
2461
2686
|
providerId: "fireworks",
|
|
2462
2687
|
...(apiKey && {
|
|
2463
2688
|
fetchDynamicModels: async () => {
|
|
2464
|
-
|
|
2689
|
+
// Both loaders share one in-flight models.dev request.
|
|
2690
|
+
const [modelsDevReferences, fireworksCosts] = await Promise.all([
|
|
2691
|
+
loadModelsDevReferences<"openai-completions">(config?.fetch),
|
|
2692
|
+
loadFireworksModelsDevCosts(config?.fetch),
|
|
2693
|
+
]);
|
|
2465
2694
|
return fetchFireworksServerlessModels({
|
|
2466
2695
|
baseUrl,
|
|
2467
2696
|
apiKey,
|
|
2468
2697
|
resolveReference: publicModelId =>
|
|
2469
2698
|
modelsDevReferences.get(publicModelId) ?? bundledReferences(publicModelId),
|
|
2699
|
+
resolveCost: publicModelId => fireworksCosts.get(publicModelId),
|
|
2470
2700
|
fetch: config?.fetch,
|
|
2471
2701
|
});
|
|
2472
2702
|
},
|
|
@@ -3004,7 +3234,7 @@ function openCodeBaseUrlForApi(api: Api, basePath: string): string {
|
|
|
3004
3234
|
// rules (`runtime/behavior.kdl`; #887, #1617, #8957).
|
|
3005
3235
|
// Runtime-discovered rows cached before model-identity corrections retain
|
|
3006
3236
|
// stale capability metadata until the authoritative catalog TTL expires.
|
|
3007
|
-
const OPENCODE_CACHE_MIGRATION_MODEL_IDS = ["glm-5.3-flash"] as const;
|
|
3237
|
+
const OPENCODE_CACHE_MIGRATION_MODEL_IDS = ["glm-5.3-flash", "longcat-2.5-preview-free", "space-bunny-free"] as const;
|
|
3008
3238
|
const OPENCODE_ZEN_CACHE_MIGRATION_MODEL_IDS = ["gemini-3.7-flash", "gemini-3.8-flash"] as const;
|
|
3009
3239
|
|
|
3010
3240
|
// Billing-variant suffixes the OpenCode gateways append to a base model id
|
|
@@ -3093,8 +3323,8 @@ function openCodeModelManagerOptions(
|
|
|
3093
3323
|
},
|
|
3094
3324
|
},
|
|
3095
3325
|
...(apiKey && {
|
|
3096
|
-
fetchDynamicModels: () =>
|
|
3097
|
-
fetchOpenAICompatibleModels<Api>({
|
|
3326
|
+
fetchDynamicModels: async () => {
|
|
3327
|
+
const discovered = await fetchOpenAICompatibleModels<Api>({
|
|
3098
3328
|
api: "openai-completions",
|
|
3099
3329
|
provider: providerId,
|
|
3100
3330
|
baseUrl: discoveryBaseUrl,
|
|
@@ -3152,7 +3382,12 @@ function openCodeModelManagerOptions(
|
|
|
3152
3382
|
};
|
|
3153
3383
|
},
|
|
3154
3384
|
fetch: config?.fetch,
|
|
3155
|
-
})
|
|
3385
|
+
});
|
|
3386
|
+
if (!discovered) return null;
|
|
3387
|
+
const seeds = seedModels(providerId).map(seed => ({ ...seed, baseUrl: basePath }));
|
|
3388
|
+
const seedIds = new Set(seeds.map(seed => seed.id));
|
|
3389
|
+
return [...discovered.filter(model => !seedIds.has(model.id)), ...seeds];
|
|
3390
|
+
},
|
|
3156
3391
|
}),
|
|
3157
3392
|
};
|
|
3158
3393
|
}
|
|
@@ -3245,8 +3480,9 @@ export interface OpenRouterModelManagerConfig {
|
|
|
3245
3480
|
* OpenRouter's Decisions API lives at `/api/alpha`, a sibling of the `/api/v1`
|
|
3246
3481
|
* chat root; derive it so a custom gateway base URL keeps both aligned.
|
|
3247
3482
|
*/
|
|
3248
|
-
function openrouterDecisionsBaseUrl(chatBaseUrl: string): string {
|
|
3249
|
-
|
|
3483
|
+
export function openrouterDecisionsBaseUrl(chatBaseUrl: string): string {
|
|
3484
|
+
const base = chatBaseUrl.replace(/\/+$/g, "");
|
|
3485
|
+
return base.endsWith("/v1") ? `${base.slice(0, -"/v1".length)}/alpha` : `${base}/alpha`;
|
|
3250
3486
|
}
|
|
3251
3487
|
|
|
3252
3488
|
function mapOpenRouterThinking(entry: OpenAICompatibleModelRecord): ThinkingConfig | undefined {
|
|
@@ -4219,6 +4455,7 @@ export function syntheticModelManagerOptions(
|
|
|
4219
4455
|
return {
|
|
4220
4456
|
providerId: "synthetic",
|
|
4221
4457
|
dynamicModelsAuthoritative: true,
|
|
4458
|
+
dynamicReasoningAuthoritative: true,
|
|
4222
4459
|
...(apiKey && {
|
|
4223
4460
|
fetchDynamicModels: () =>
|
|
4224
4461
|
fetchOpenAICompatibleModels({
|
|
@@ -4477,8 +4714,8 @@ const META_MUSE_MODEL_BY_ID: Partial<Record<string, ModelSpec<"openai-responses"
|
|
|
4477
4714
|
* text-only model with no limits. Only ids that classify into the
|
|
4478
4715
|
* `muse-spark` family with a revision qualify. The template's explicit
|
|
4479
4716
|
* `thinking` is dropped: only reviewed seed rows may advertise `max` (1.3
|
|
4480
|
-
* standard), so an unknown revision takes the provider's
|
|
4481
|
-
* from `providers/meta.kdl` at build time.
|
|
4717
|
+
* standard and contributor), so an unknown revision takes the provider's
|
|
4718
|
+
* five-tier ladder from `providers/meta.kdl` at build time.
|
|
4482
4719
|
*/
|
|
4483
4720
|
function museSparkLineageSpec(id: string): ModelSpec<"openai-responses"> | undefined {
|
|
4484
4721
|
const identity = classifyModel("meta", id, { lenient: true });
|
|
@@ -6142,7 +6379,7 @@ function parseCopilotTokenPriceTier(value: unknown): CopilotTokenPriceTier | und
|
|
|
6142
6379
|
return undefined;
|
|
6143
6380
|
}
|
|
6144
6381
|
return {
|
|
6145
|
-
contextMax: toNumber(value.context_max),
|
|
6382
|
+
contextMax: toNumber(value.max_prompt_tokens) ?? toNumber(value.context_max),
|
|
6146
6383
|
inputPrice: toNumber(value.input_price),
|
|
6147
6384
|
outputPrice: toNumber(value.output_price),
|
|
6148
6385
|
cachePrice: toNumber(value.cache_price),
|
|
@@ -6258,6 +6495,9 @@ export function githubCopilotModelManagerOptions(config?: GithubCopilotModelMana
|
|
|
6258
6495
|
return {
|
|
6259
6496
|
providerId: "github-copilot",
|
|
6260
6497
|
cacheProviderId: resolveModelCacheProviderId("github-copilot", { apiKey: rawApiKey, baseUrl }),
|
|
6498
|
+
// Copilot discovery pre-applies the correct image fallback for omitted
|
|
6499
|
+
// `supports.vision`; the live row's modality is authoritative.
|
|
6500
|
+
dynamicInputAuthoritative: true,
|
|
6261
6501
|
dropCachedModelIdsOnStaticMismatch: COPILOT_CACHE_INVALIDATED_MODEL_IDS,
|
|
6262
6502
|
// COPILOT_API_HEADERS are compile-time wire identity constants, not
|
|
6263
6503
|
// credentials. The cache omits all request headers for
|
|
@@ -6328,11 +6568,21 @@ export function githubCopilotModelManagerOptions(config?: GithubCopilotModelMana
|
|
|
6328
6568
|
? ["text"]
|
|
6329
6569
|
: (reference?.input ?? defaults.input);
|
|
6330
6570
|
// With COPILOT_API_HEADERS the served window is the long-context
|
|
6331
|
-
// ceiling; the default tier
|
|
6332
|
-
//
|
|
6333
|
-
// tier
|
|
6571
|
+
// ceiling; the default tier reports its prompt boundary in
|
|
6572
|
+
// token_prices.default.max_prompt_tokens (or legacy context_max).
|
|
6573
|
+
// Cap the base entry to the default tier — the long tier is
|
|
6574
|
+
// the opt-in `-1m` sibling below. On tiered legacy rows the
|
|
6575
|
+
// model-wide max_prompt_tokens may be tighter than the billed
|
|
6576
|
+
// default ceiling (#13912), so use the smaller bound.
|
|
6334
6577
|
const tokenPrices = extractCopilotTokenPrices(entry);
|
|
6335
|
-
const
|
|
6578
|
+
const billedDefaultMax = tokenPrices.defaultTier?.contextMax;
|
|
6579
|
+
const tieredPromptBudget =
|
|
6580
|
+
(tokenPrices.longContext?.contextMax ?? 0) > 0 ? (copilotLimits.maxPromptTokens ?? 0) : 0;
|
|
6581
|
+
const defaultContextMax =
|
|
6582
|
+
tieredPromptBudget > 0 &&
|
|
6583
|
+
(billedDefaultMax === undefined || billedDefaultMax <= 0 || tieredPromptBudget < billedDefaultMax)
|
|
6584
|
+
? tieredPromptBudget
|
|
6585
|
+
: billedDefaultMax;
|
|
6336
6586
|
const defaultTierWindow =
|
|
6337
6587
|
defaultContextMax !== undefined &&
|
|
6338
6588
|
defaultContextMax > 0 &&
|
|
@@ -7077,23 +7327,12 @@ const MODELS_DEV_PROVIDER_DESCRIPTORS_CODING_PLANS: readonly ModelsDevProviderDe
|
|
|
7077
7327
|
allowsSyntheticReasoningContentForToolCalls: false,
|
|
7078
7328
|
},
|
|
7079
7329
|
}),
|
|
7080
|
-
// --- MiniMax
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
reasoningContentField: "reasoning_content",
|
|
7087
|
-
},
|
|
7088
|
-
}),
|
|
7089
|
-
openAiCompletionsDescriptor("minimax-cn-coding-plan", "minimax-code-cn", "https://api.minimaxi.com/v1", {
|
|
7090
|
-
compat: {
|
|
7091
|
-
supportsStore: false,
|
|
7092
|
-
supportsDeveloperRole: false,
|
|
7093
|
-
supportsReasoningEffort: false,
|
|
7094
|
-
reasoningContentField: "reasoning_content",
|
|
7095
|
-
},
|
|
7096
|
-
}),
|
|
7330
|
+
// --- MiniMax Token Plan ---
|
|
7331
|
+
// MiniMax documents its Anthropic-compatible API as the recommended
|
|
7332
|
+
// protocol: signed thinking blocks, `output_config.effort` depth control,
|
|
7333
|
+
// and prompt-cache usage reporting.
|
|
7334
|
+
anthropicMessagesDescriptor("minimax-coding-plan", "minimax-code", "https://api.minimax.io/anthropic"),
|
|
7335
|
+
anthropicMessagesDescriptor("minimax-cn-coding-plan", "minimax-code-cn", "https://api.minimaxi.com/anthropic"),
|
|
7097
7336
|
// --- Alibaba Coding Plan ---
|
|
7098
7337
|
openAiCompletionsDescriptor(
|
|
7099
7338
|
"alibaba-coding-plan",
|
|
@@ -24,6 +24,12 @@ export interface OpenAICodexModelManagerConfig {
|
|
|
24
24
|
* keeps the previous/bundled catalog instead.
|
|
25
25
|
*/
|
|
26
26
|
resolveAccounts?: () => Promise<readonly OpenAICodexAccount[] | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Codex backend base URL (e.g. a Codex-compatible gateway from `models.yml`).
|
|
29
|
+
* Defaults to the official ChatGPT backend. Also scopes the discovery cache,
|
|
30
|
+
* so a gateway roster never serves the official endpoint and vice versa.
|
|
31
|
+
*/
|
|
32
|
+
baseUrl?: string;
|
|
27
33
|
clientVersion?: string;
|
|
28
34
|
fetch?: FetchImpl;
|
|
29
35
|
}
|
|
@@ -59,6 +65,8 @@ export declare function devinModelManagerOptions(config?: DevinModelManagerConfi
|
|
|
59
65
|
export declare function factoryDroidModelManagerOptions(config?: FactoryDroidModelDiscoveryOptions): ModelManagerOptions<"factory-droid-agent">;
|
|
60
66
|
export declare function localModelManagerOptions(): ModelManagerOptions<"local-inference">;
|
|
61
67
|
export declare function webModelManagerOptions(): ModelManagerOptions<"web-search">;
|
|
68
|
+
/** Cloudflare Workers AI judges: the authored Clef rows; the account id resolves per request. */
|
|
69
|
+
export declare function cloudflareWorkersAiModelManagerOptions(): ModelManagerOptions<"workers-ai-systemone">;
|
|
62
70
|
/** Credentials and endpoint overrides for the TypeSafe catalog manager. */
|
|
63
71
|
export interface TypeSafeModelManagerConfig {
|
|
64
72
|
apiKey?: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { logger, once } from "@linxiraos/pi-utils";
|
|
2
2
|
import { buildModel } from "../build";
|
|
3
3
|
import { apiRouteFor } from "../compat/behavior";
|
|
4
|
-
import { seedModels } from "../compat/providers";
|
|
4
|
+
import { providerEntry, seedModels } from "../compat/providers";
|
|
5
5
|
import { type CodexModelDiscoveryResult, fetchCodexModels } from "../discovery/codex";
|
|
6
6
|
import type { DevinModelDiscoveryOptions } from "../discovery/devin";
|
|
7
7
|
import {
|
|
@@ -15,6 +15,7 @@ import type { ModelManagerOptions } from "../model-manager";
|
|
|
15
15
|
import { getBundledModel } from "../models";
|
|
16
16
|
import type { Api, FetchImpl, Model, ModelSpec } from "../types";
|
|
17
17
|
import { DEVIN_DEFAULT_BASE_URL } from "../wire/devin";
|
|
18
|
+
import { unionAccountCatalogs } from "./account-access";
|
|
18
19
|
import { toModelSpec } from "./bundled-references";
|
|
19
20
|
import { resolveModelCacheProviderId } from "./cache-provider-id";
|
|
20
21
|
|
|
@@ -45,6 +46,12 @@ export interface OpenAICodexModelManagerConfig {
|
|
|
45
46
|
* keeps the previous/bundled catalog instead.
|
|
46
47
|
*/
|
|
47
48
|
resolveAccounts?: () => Promise<readonly OpenAICodexAccount[] | null>;
|
|
49
|
+
/**
|
|
50
|
+
* Codex backend base URL (e.g. a Codex-compatible gateway from `models.yml`).
|
|
51
|
+
* Defaults to the official ChatGPT backend. Also scopes the discovery cache,
|
|
52
|
+
* so a gateway roster never serves the official endpoint and vice versa.
|
|
53
|
+
*/
|
|
54
|
+
baseUrl?: string;
|
|
48
55
|
clientVersion?: string;
|
|
49
56
|
fetch?: FetchImpl;
|
|
50
57
|
}
|
|
@@ -52,11 +59,11 @@ export interface OpenAICodexModelManagerConfig {
|
|
|
52
59
|
export function openaiCodexModelManagerOptions(
|
|
53
60
|
config: OpenAICodexModelManagerConfig = {},
|
|
54
61
|
): ModelManagerOptions<"openai-codex-responses"> {
|
|
55
|
-
const { resolveAccounts, clientVersion, fetch } = config;
|
|
62
|
+
const { resolveAccounts, baseUrl, clientVersion, fetch } = config;
|
|
56
63
|
return {
|
|
57
64
|
providerId: "openai-codex",
|
|
58
|
-
cacheProviderId: resolveModelCacheProviderId("openai-codex"),
|
|
59
|
-
dynamicModelsAuthoritative: true,
|
|
65
|
+
cacheProviderId: resolveModelCacheProviderId("openai-codex", { baseUrl }),
|
|
66
|
+
dynamicModelsAuthoritative: providerEntry("openai-codex")?.dynamicModelsAuthoritative === true,
|
|
60
67
|
...(resolveAccounts
|
|
61
68
|
? {
|
|
62
69
|
fetchDynamicModels: async () => {
|
|
@@ -68,6 +75,7 @@ export function openaiCodexModelManagerOptions(
|
|
|
68
75
|
result: await fetchCodexModels({
|
|
69
76
|
accessToken: account.accessToken,
|
|
70
77
|
accountId: account.accountId,
|
|
78
|
+
baseUrl,
|
|
71
79
|
clientVersion,
|
|
72
80
|
fetchFn: fetch,
|
|
73
81
|
}),
|
|
@@ -81,9 +89,8 @@ export function openaiCodexModelManagerOptions(
|
|
|
81
89
|
}
|
|
82
90
|
|
|
83
91
|
/**
|
|
84
|
-
* Merge complete per-account Codex catalogs into one authoritative list
|
|
85
|
-
*
|
|
86
|
-
* account access is merged from every account whose catalog lists that id.
|
|
92
|
+
* Merge complete per-account Codex catalogs into one authoritative list via
|
|
93
|
+
* {@link unionAccountCatalogs}.
|
|
87
94
|
*
|
|
88
95
|
* Returns `null` when any account's fetch failed transiently, so a partial list
|
|
89
96
|
* cannot replace the previous or bundled authoritative catalog. An account
|
|
@@ -95,8 +102,7 @@ export function openaiCodexModelManagerOptions(
|
|
|
95
102
|
function unionCodexModels(
|
|
96
103
|
results: readonly { accountId: string | undefined; result: CodexModelDiscoveryResult | null }[],
|
|
97
104
|
): ModelSpec<"openai-codex-responses">[] | null {
|
|
98
|
-
const
|
|
99
|
-
let catalogs = 0;
|
|
105
|
+
const catalogs: ModelSpec<"openai-codex-responses">[][] = [];
|
|
100
106
|
for (const { accountId, result } of results) {
|
|
101
107
|
if (!result) return null;
|
|
102
108
|
if (result.rejectedStatus !== undefined) {
|
|
@@ -106,20 +112,9 @@ function unionCodexModels(
|
|
|
106
112
|
});
|
|
107
113
|
continue;
|
|
108
114
|
}
|
|
109
|
-
catalogs
|
|
110
|
-
for (const model of result.models) {
|
|
111
|
-
const existing = byId.get(model.id);
|
|
112
|
-
if (!existing) {
|
|
113
|
-
byId.set(model.id, model);
|
|
114
|
-
} else if (model.accountAccess) {
|
|
115
|
-
byId.set(model.id, {
|
|
116
|
-
...existing,
|
|
117
|
-
accountAccess: { ...existing.accountAccess, ...model.accountAccess },
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
}
|
|
115
|
+
catalogs.push(result.models);
|
|
121
116
|
}
|
|
122
|
-
return catalogs > 0 ?
|
|
117
|
+
return catalogs.length > 0 ? unionAccountCatalogs(catalogs) : null;
|
|
123
118
|
}
|
|
124
119
|
|
|
125
120
|
// ---------------------------------------------------------------------------
|
|
@@ -410,6 +405,15 @@ export function webModelManagerOptions(): ModelManagerOptions<"web-search"> {
|
|
|
410
405
|
};
|
|
411
406
|
}
|
|
412
407
|
|
|
408
|
+
/** Cloudflare Workers AI judges: the authored Clef rows; the account id resolves per request. */
|
|
409
|
+
export function cloudflareWorkersAiModelManagerOptions(): ModelManagerOptions<"workers-ai-systemone"> {
|
|
410
|
+
return {
|
|
411
|
+
providerId: "cloudflare-workers-ai",
|
|
412
|
+
cacheProviderId: resolveModelCacheProviderId("cloudflare-workers-ai"),
|
|
413
|
+
staticModels: seedModels<"workers-ai-systemone">("cloudflare-workers-ai"),
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
|
|
413
417
|
/** Credentials and endpoint overrides for the TypeSafe catalog manager. */
|
|
414
418
|
export interface TypeSafeModelManagerConfig {
|
|
415
419
|
apiKey?: string;
|