{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAG/C,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AA8EnE,MAAM,MAAM,wBAAwB,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;CAAE,CAAC;AAG9F;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,wBAAwB,KAAK,IAAI,GAAG,MAAM,IAAI,CAMjG;AAMD,KAAK,QAAQ,CACZ,SAAS,SAAS,aAAa,EAC/B,QAAQ,SAAS,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,IAC9C,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,SAAS;IAAE,GAAG,EAAE,MAAM,IAAI,CAAA;CAAE,GAAG,CAAC,IAAI,SAAS,GAAG,GAAG,IAAI,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;AAEjH,wBAAgB,QAAQ,CAAC,SAAS,SAAS,aAAa,EAAE,QAAQ,SAAS,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,EAC1G,QAAQ,EAAE,SAAS,EACnB,OAAO,EAAE,QAAQ,GACf,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAGtC;AAED,wBAAgB,YAAY,IAAI,aAAa,EAAE,CAE9C;AAED,wBAAgB,SAAS,CAAC,SAAS,SAAS,aAAa,EACxD,QAAQ,EAAE,SAAS,GACjB,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAGhE;AAED,wBAAgB,aAAa,CAAC,IAAI,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAO/F;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAe3E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,SAAS,GAAG,EAC9C,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,EACjC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,GAC/B,OAAO,CAGT","sourcesContent":["import { MODELS } from \"./models.generated.js\";\nimport { getAnthropicCapabilities } from \"./providers/anthropic-capabilities.js\";\nimport { _setRegistryHook } from \"./providers/anthropic-discovery.js\";\nimport type { Api, KnownProvider, Model, Usage } from \"./types.js\";\n\nconst modelRegistry: Map<string, Map<string, Model<Api>>> = new Map();\n\n/**\n * Apply per-model capability overrides at registry-load time.\n *\n * The generated `models.generated.ts` mirrors what the provider reports for\n * the default tier (e.g. Anthropic's 200k window for Opus 4.5). When the\n * capability table declares an opt-in that unlocks a larger window, the\n * registry should advertise that window so the UI (modeline, picker) and\n * compaction logic operate against the real ceiling we will request.\n *\n * Runtime discovery (see anthropic-discovery.ts) may also push fresher\n * model entries into the registry post-auth via `_registerModelForDiscovery`\n * below; this load-time pass is the cold-start fallback only.\n */\nfunction applyCapabilityOverrides(model: Model<Api>): Model<Api> {\n\tif (model.api !== \"anthropic-messages\" && model.api !== \"bedrock-converse-stream\") {\n\t\treturn model;\n\t}\n\tconst caps = getAnthropicCapabilities(model.id, model.provider);\n\tif (caps.contextWindow && caps.contextWindow !== model.contextWindow) {\n\t\treturn { ...model, contextWindow: caps.contextWindow };\n\t}\n\treturn model;\n}\n\n// Initialize registry from MODELS on module load\nfor (const [provider, models] of Object.entries(MODELS)) {\n\tconst providerModels = new Map<string, Model<Api>>();\n\tfor (const [id, model] of Object.entries(models)) {\n\t\tproviderModels.set(id, applyCapabilityOverrides(model as Model<Api>));\n\t}\n\tmodelRegistry.set(provider, providerModels);\n}\n\n/**\n * Insert or upgrade a registry entry. Used by the discovery layer to surface\n * newly-discovered model ids (e.g. `claude-opus-4.6-1m` on Copilot) without\n * regenerating models.generated.ts.\n *\n * When an existing entry is present, the capability-related fields are\n * refreshed but the pricing is preserved (discovery endpoints rarely\n * report cost). When new, the fresh entry is inserted as-is.\n *\n * Fires registered change listeners so downstream snapshots\n * (e.g. coding-agent's ModelRegistry) can rebuild.\n */\nfunction _registerModelForDiscovery(provider: string, model: Model<Api>): void {\n\tlet providerModels = modelRegistry.get(provider);\n\tif (!providerModels) {\n\t\tproviderModels = new Map();\n\t\tmodelRegistry.set(provider, providerModels);\n\t}\n\tconst prev = providerModels.get(model.id);\n\tconst isNew = !prev;\n\tconst merged: Model<Api> = prev\n\t\t? {\n\t\t\t\t...prev,\n\t\t\t\tcontextWindow: model.contextWindow,\n\t\t\t\tmaxTokens: model.maxTokens,\n\t\t\t\treasoning: model.reasoning,\n\t\t\t\tinput: model.input,\n\t\t\t}\n\t\t: model;\n\tproviderModels.set(model.id, merged);\n\tif (isNew) {\n\t\tfor (const listener of modelChangeListeners) {\n\t\t\ttry {\n\t\t\t\tlistener({ type: \"added\", provider, model: merged });\n\t\t\t} catch {\n\t\t\t\t// Listener errors must not break discovery.\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport type ModelRegistryChangeEvent = { type: \"added\"; provider: string; model: Model<Api> };\nconst modelChangeListeners: Array<(e: ModelRegistryChangeEvent) => void> = [];\n\n/**\n * Subscribe to registry mutations performed by the discovery layer\n * (newly-published model ids). Returns an unsubscribe function.\n */\nexport function onModelRegistryChange(listener: (e: ModelRegistryChangeEvent) => void): () => void {\n\tmodelChangeListeners.push(listener);\n\treturn () => {\n\t\tconst i = modelChangeListeners.indexOf(listener);\n\t\tif (i >= 0) modelChangeListeners.splice(i, 1);\n\t};\n}\n\n// Wire the registry-mutation hook into the discovery module so it does not\n// need a back-reference to models.ts (which would cycle).\n_setRegistryHook(_registerModelForDiscovery);\n\ntype ModelApi<\n\tTProvider extends KnownProvider,\n\tTModelId extends keyof (typeof MODELS)[TProvider],\n> = (typeof MODELS)[TProvider][TModelId] extends { api: infer TApi } ? (TApi extends Api ? TApi : never) : never;\n\nexport function getModel<TProvider extends KnownProvider, TModelId extends keyof (typeof MODELS)[TProvider]>(\n\tprovider: TProvider,\n\tmodelId: TModelId,\n): Model<ModelApi<TProvider, TModelId>> {\n\tconst providerModels = modelRegistry.get(provider);\n\treturn providerModels?.get(modelId as string) as Model<ModelApi<TProvider, TModelId>>;\n}\n\nexport function getProviders(): KnownProvider[] {\n\treturn Array.from(modelRegistry.keys()) as KnownProvider[];\n}\n\nexport function getModels<TProvider extends KnownProvider>(\n\tprovider: TProvider,\n): Model<ModelApi<TProvider, keyof (typeof MODELS)[TProvider]>>[] {\n\tconst models = modelRegistry.get(provider);\n\treturn models ? (Array.from(models.values()) as Model<ModelApi<TProvider, keyof (typeof MODELS)[TProvider]>>[]) : [];\n}\n\nexport function calculateCost<TApi extends Api>(model: Model<TApi>, usage: Usage): Usage[\"cost\"] {\n\tusage.cost.input = (model.cost.input / 1000000) * usage.input;\n\tusage.cost.output = (model.cost.output / 1000000) * usage.output;\n\tusage.cost.cacheRead = (model.cost.cacheRead / 1000000) * usage.cacheRead;\n\tusage.cost.cacheWrite = (model.cost.cacheWrite / 1000000) * usage.cacheWrite;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n\treturn usage.cost;\n}\n\n/**\n * Check if a model supports xhigh thinking level.\n *\n * Supported today:\n * - GPT-5.2 / GPT-5.3 / GPT-5.4 / GPT-5.5 model families\n * - Opus 4.6 models (xhigh maps to adaptive effort \"max\" on Anthropic-compatible providers)\n */\nexport function supportsXhigh<TApi extends Api>(model: Model<TApi>): boolean {\n\tif (\n\t\tmodel.id.includes(\"gpt-5.2\") ||\n\t\tmodel.id.includes(\"gpt-5.3\") ||\n\t\tmodel.id.includes(\"gpt-5.4\") ||\n\t\tmodel.id.includes(\"gpt-5.5\")\n\t) {\n\t\treturn true;\n\t}\n\n\tif (getAnthropicCapabilities(model.id, model.provider).xhighEffort) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Check if two models are equal by comparing both their id and provider.\n * Returns false if either model is null or undefined.\n */\nexport function modelsAreEqual<TApi extends Api>(\n\ta: Model<TApi> | null | undefined,\n\tb: Model<TApi> | null | undefined,\n): boolean {\n\tif (!a || !b) return false;\n\treturn a.id === b.id && a.provider === b.provider;\n}\n"]}