{"version":3,"file":"model-tiers.d.ts","sourceRoot":"","sources":["../src/model-tiers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtE;;;;;GAKG;AACH,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAKhD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,SAAS,CAIrE;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAM5E,CAAC;AAyBF;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAMxG","sourcesContent":["import type { Api, KnownProvider, Model, Provider } from \"./types.js\";\n\n/**\n * Capability tiers for subagent model selection. A tier keyword resolves to a\n * concrete model within the caller's current provider via the curated\n * {@link MODEL_TIERS} map, so it works regardless of which single provider the\n * user is authed to.\n */\nexport type Tier = \"fast\" | \"normal\" | \"strong\";\n\n/** Prefix that marks a model string as a tier keyword (e.g. `tier:fast`). */\nconst TIER_SIGIL = \"tier:\";\n\n/**\n * Parse a model string into a {@link Tier}, or undefined if it is not a tier\n * keyword. Tier keywords carry a `tier:` sigil so they never collide with a\n * concrete model id that happens to be named `fast`/`normal`/`strong`.\n */\nexport function parseTier(model: string | undefined): Tier | undefined {\n\tif (!model || !model.startsWith(TIER_SIGIL)) return undefined;\n\tconst suffix = model.slice(TIER_SIGIL.length);\n\treturn suffix === \"fast\" || suffix === \"normal\" || suffix === \"strong\" ? suffix : undefined;\n}\n\n/**\n * Maintainer-curated tier -> concrete-model-id map, per provider. Pinned (not a\n * runtime cost heuristic) so tier resolution is deterministic and the ladder is\n * controlled here. `normal` is a deliberately chosen everyday model, not the\n * provider's default (which tends to be the priciest / `strong` end).\n *\n * Partial: uncurated providers (routers like openrouter/vercel, or a user's\n * custom provider) have no row; callers fall back to the parent model with a\n * warning rather than guessing.\n *\n * Ids are patterns resolved through alias logic, so an alias like\n * `claude-sonnet-5` matches a future dated `claude-sonnet-5-YYYYMMDD`.\n */\nexport const MODEL_TIERS: Partial<Record<KnownProvider, Record<Tier, string>>> = {\n\tanthropic: { fast: \"claude-haiku-4-5\", normal: \"claude-sonnet-5\", strong: \"claude-opus-4-8\" },\n\t\"openai-codex\": { fast: \"gpt-5.6-luna\", normal: \"gpt-5.6-terra\", strong: \"gpt-5.6-sol\" },\n\topenai: { fast: \"gpt-5.6-luna\", normal: \"gpt-5.6-terra\", strong: \"gpt-5.6-sol\" },\n\tgoogle: { fast: \"gemini-2.5-flash\", normal: \"gemini-2.5-pro\", strong: \"gemini-3-pro-preview\" },\n\t\"amazon-bedrock\": { fast: \"claude-haiku-4-5\", normal: \"claude-sonnet-5\", strong: \"claude-opus-4-8\" },\n};\n\n/** A model id is an \"alias\" when it has no trailing date (`-YYYYMMDD`). */\nfunction isAlias(id: string): boolean {\n\treturn id.endsWith(\"-latest\") || !/-\\d{8}$/.test(id);\n}\n\n/**\n * Match a curated tier id against one provider's authed pool. The pool is\n * already provider-scoped, so this is simpler than the general cross-provider\n * resolver: exact id, else alias-preferring partial match.\n */\nfunction matchInPool(wantId: string, pool: Model<Api>[]): Model<Api> | undefined {\n\tconst want = wantId.toLowerCase();\n\tconst exact = pool.find((m) => m.id.toLowerCase() === want);\n\tif (exact) return exact;\n\n\tconst matches = pool.filter((m) => m.id.toLowerCase().includes(want) || m.name?.toLowerCase().includes(want));\n\tif (matches.length === 0) return undefined;\n\n\tconst aliases = matches.filter((m) => isAlias(m.id));\n\tconst pick = (aliases.length > 0 ? aliases : matches).sort((a, b) => b.id.localeCompare(a.id));\n\treturn pick[0];\n}\n\n/**\n * Resolve a tier to a concrete authed model for a provider, or undefined when\n * the provider is uncurated or the curated id is not in the authed pool. The\n * caller decides the fallback (curated `normal`, then parent model).\n */\nexport function resolveTier(tier: Tier, provider: Provider, authed: Model<Api>[]): Model<Api> | undefined {\n\tconst row = MODEL_TIERS[provider as KnownProvider];\n\tif (!row) return undefined;\n\tconst pool = authed.filter((m) => m.provider === provider);\n\tif (pool.length === 0) return undefined;\n\treturn matchInPool(row[tier], pool);\n}\n"]}