{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAInE,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCX,CAAC;AAeX,KAAK,YAAY,GAAG,OAAO,MAAM,GAAG;IACnC,QAAQ,EAAE,OAAO,eAAe,CAAC;CACjC,CAAC;AAmBF,KAAK,QAAQ,CACZ,SAAS,SAAS,aAAa,EAC/B,QAAQ,SAAS,MAAM,YAAY,CAAC,SAAS,CAAC,IAC3C,YAAY,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;AAE9G,wBAAgB,QAAQ,CAAC,SAAS,SAAS,aAAa,EAAE,QAAQ,SAAS,MAAM,YAAY,CAAC,SAAS,CAAC,EACvG,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,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAG7D;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;;;;;;;;;;GAUG;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 type { Api, KnownProvider, Model, Usage } from \"./types.js\";\n\nconst DEEPSEEK_BASE_URL = \"https://api.deepseek.com/v1\";\n\nconst DEEPSEEK_MODELS = {\n\t\"deepseek-chat\": {\n\t\tid: \"deepseek-chat\",\n\t\tname: \"DeepSeek Chat\",\n\t\tapi: \"openai-completions\",\n\t\tprovider: \"deepseek\",\n\t\tbaseUrl: DEEPSEEK_BASE_URL,\n\t\treasoning: false,\n\t\tinput: [\"text\"],\n\t\tcost: {\n\t\t\tinput: 0.28,\n\t\t\toutput: 0.42,\n\t\t\tcacheRead: 0.028,\n\t\t\tcacheWrite: 0,\n\t\t},\n\t\tcontextWindow: 128000,\n\t\tmaxTokens: 8000,\n\t} satisfies Model<\"openai-completions\">,\n\t\"deepseek-reasoner\": {\n\t\tid: \"deepseek-reasoner\",\n\t\tname: \"DeepSeek Reasoner\",\n\t\tapi: \"openai-completions\",\n\t\tprovider: \"deepseek\",\n\t\tbaseUrl: DEEPSEEK_BASE_URL,\n\t\treasoning: true,\n\t\tinput: [\"text\"],\n\t\tcost: {\n\t\t\tinput: 0.55,\n\t\t\toutput: 2.19,\n\t\t\tcacheRead: 0.14,\n\t\t\tcacheWrite: 0,\n\t\t},\n\t\tcontextWindow: 128000,\n\t\tmaxTokens: 64000,\n\t} satisfies Model<\"openai-completions\">,\n} as const;\n\nconst ZAI_MODELS = Object.fromEntries(\n\tObject.entries(MODELS.zai).map(([id, model]) => [\n\t\tid,\n\t\t{\n\t\t\t...model,\n\t\t\tcompat: {\n\t\t\t\t...(model.compat ?? {}),\n\t\t\t\tthinkingFormat: \"zai\",\n\t\t\t},\n\t\t} satisfies Model<\"openai-completions\">,\n\t]),\n) as typeof MODELS.zai;\n\ntype ModelCatalog = typeof MODELS & {\n\tdeepseek: typeof DEEPSEEK_MODELS;\n};\n\nconst ALL_MODELS: ModelCatalog = {\n\t...MODELS,\n\tdeepseek: DEEPSEEK_MODELS,\n\tzai: ZAI_MODELS,\n};\n\nconst modelRegistry: Map<string, Map<string, Model<Api>>> = new Map();\n\n// Initialize registry from MODELS on module load\nfor (const [provider, models] of Object.entries(ALL_MODELS)) {\n\tconst providerModels = new Map<string, Model<Api>>();\n\tfor (const [id, model] of Object.entries(models)) {\n\t\tproviderModels.set(id, model as Model<Api>);\n\t}\n\tmodelRegistry.set(provider, providerModels);\n}\n\ntype ModelApi<\n\tTProvider extends KnownProvider,\n\tTModelId extends keyof ModelCatalog[TProvider],\n> = ModelCatalog[TProvider][TModelId] extends { api: infer TApi } ? (TApi extends Api ? TApi : never) : never;\n\nexport function getModel<TProvider extends KnownProvider, TModelId extends keyof ModelCatalog[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 ModelCatalog[TProvider]>>[] {\n\tconst models = modelRegistry.get(provider);\n\treturn models ? (Array.from(models.values()) as Model<ModelApi<TProvider, keyof ModelCatalog[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 * Resolution order:\n * 1. Explicit `model.compat.supportsXhigh` capability declaration (authoritative).\n * 2. Built-in detection for known model families (legacy fallback).\n *\n * Supported by built-in detection today:\n * - GPT-5.2 / GPT-5.3 / GPT-5.4 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\tconst declared = (model.compat as { supportsXhigh?: boolean } | undefined)?.supportsXhigh;\n\tif (declared !== undefined) {\n\t\treturn declared;\n\t}\n\n\tif (model.id.includes(\"gpt-5.2\") || model.id.includes(\"gpt-5.3\") || model.id.includes(\"gpt-5.4\")) {\n\t\treturn true;\n\t}\n\n\tif (model.id.includes(\"opus-4-6\") || model.id.includes(\"opus-4.6\")) {\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"]}