{"version":3,"sources":["../src/pricing.ts","../src/shape/pricing.ts","../src/shape/capabilities.ts","../src/shape/thinking.ts","../src/catalog/anthropic.ts","../src/catalog/openai.ts","../src/catalog/google.ts","../src/catalog/index.ts","../src/catalog/pricing.ts"],"sourcesContent":["// `@odla-ai/ai/pricing` — the model price list, on its own.\n//\n// This entrypoint exists so cost accounting can depend on odla-ai's pricing\n// without depending on odla-ai's runtime. It pulls in the catalog and the two\n// pure pricing/usage shapes and nothing else: no provider adapters, no client,\n// no `@anthropic-ai/sdk` / `openai` / `@google/genai`. `@odla-ai/o11y` imports\n// it to price LLM telemetry from one source of truth instead of maintaining a\n// second, drifting price table.\n//\n// Everything here is re-exported from the package root as well; importing the\n// subpath only buys you the smaller bundle.\n\nexport { costUsd, promptTokens, ratesForPrompt, scaleLongContext } from \"./shape/pricing\";\nexport type { LongContextPricing, ModelPricing, TokenRates } from \"./shape/pricing\";\nexport type { OracleUsage } from \"./shape/usage\";\nexport { modelPricing, priceCall, pricedModels } from \"./catalog/pricing\";\nexport { DEFAULT_CATALOG, buildCatalog } from \"./catalog/index\";\nexport type { Catalog } from \"./catalog/index\";\nexport type { ModelSpec } from \"./shape/capabilities\";\n","// Model pricing — USD per million tokens, carried on the catalog's ModelSpec.\n// Field names deliberately mirror @odla/o11y-core's ModelPrice so a spec's\n// pricing can back its costUsd() override without adaptation.\n\nimport type { OracleUsage } from \"./usage\";\n\n/** The four per-token rates one request is billed at. */\nexport interface TokenRates {\n  /** USD per MTok of input. */\n  inputPerMTok: number;\n  /** USD per MTok of output (thinking tokens bill as output). */\n  outputPerMTok: number;\n  /** USD per MTok read from the prompt cache. Falls back to `inputPerMTok`. */\n  cacheReadPerMTok?: number;\n  /** USD per MTok written to the prompt cache (default-TTL tier). Falls back to\n   *  `inputPerMTok`. */\n  cacheWritePerMTok?: number;\n}\n\n/**\n * The rates a model charges once a request's prompt is longer than a\n * threshold. Every provider that prices this way replaces the rate of the\n * WHOLE request, not of the tokens past the threshold, so one extra prompt\n * token can multiply the bill. Cache rates left out here fall back to this\n * tier's `inputPerMTok`, never to the base tier's cheaper cache rates.\n */\nexport interface LongContextPricing extends TokenRates {\n  /** Prompt length in tokens. A request whose prompt is longer than this pays\n   *  these rates; a prompt of exactly this length still pays the base rates. */\n  aboveTokens: number;\n}\n\n/** USD prices per million tokens (MTok) for one model. Absent pricing means\n *  \"unknown\" — never assume free. */\nexport interface ModelPricing extends TokenRates {\n  /** Rates for requests whose prompt exceeds a length threshold. Absent means\n   *  the model charges one rate at every prompt length. */\n  longContext?: LongContextPricing;\n  /** Free-text qualifier, e.g. \"intro $2/$10 per MTok through 2026-08-31\". */\n  note?: string;\n}\n\n/**\n * The prompt length of one request: every token the model read, however it was\n * billed. The token classes in `OracleUsage` are disjoint, so a prompt served\n * mostly from the cache is still as long as the three classes summed — and it\n * is that length, not the uncached part, that selects a long-context rate.\n */\nexport function promptTokens(usage: OracleUsage): number {\n  return usage.inputTokens + (usage.cacheReadTokens ?? 0) + (usage.cacheCreationTokens ?? 0);\n}\n\n/**\n * The rates a request with a prompt of `prompt` tokens is billed at: the\n * long-context tier when the model has one and the prompt is over its\n * threshold, the base rates otherwise.\n */\nexport function ratesForPrompt(pricing: ModelPricing, prompt: number): TokenRates {\n  const long = pricing.longContext;\n  return long && prompt > long.aboveTokens ? long : pricing;\n}\n\n/**\n * Build a long-context tier from multipliers over a model's base rates — the\n * way OpenAI states it (\"2x input and 1.5x output\"). The input multiplier\n * covers every prompt-side rate: input, cache read, and cache write. A cache\n * rate the base does not carry stays absent, so it falls back to the tier's\n * input rate rather than inventing a discount.\n */\nexport function scaleLongContext(\n  base: TokenRates,\n  aboveTokens: number,\n  inputFactor: number,\n  outputFactor: number,\n): LongContextPricing {\n  return {\n    aboveTokens,\n    inputPerMTok: base.inputPerMTok * inputFactor,\n    outputPerMTok: base.outputPerMTok * outputFactor,\n    ...(base.cacheReadPerMTok === undefined ? {} : { cacheReadPerMTok: base.cacheReadPerMTok * inputFactor }),\n    ...(base.cacheWritePerMTok === undefined ? {} : { cacheWritePerMTok: base.cacheWritePerMTok * inputFactor }),\n  };\n}\n\n/**\n * Compute the USD cost of one request from its token usage. The four token\n * classes in `OracleUsage` are disjoint (Anthropic semantics, which the shape\n * mirrors), so each is priced at its own rate and summed. Callers must check\n * that pricing exists first — unknown pricing is \"no number\", never $0.\n *\n * `usage` must be ONE request's usage. A long-context tier is chosen by that\n * request's prompt length, so pricing a sum of several requests would bill\n * short prompts at the long rate; price each request, then add the dollars.\n */\nexport function costUsd(pricing: ModelPricing, usage: OracleUsage): number {\n  const rates = ratesForPrompt(pricing, promptTokens(usage));\n  const cacheRead = rates.cacheReadPerMTok ?? rates.inputPerMTok;\n  const cacheWrite = rates.cacheWritePerMTok ?? rates.inputPerMTok;\n  return (\n    (usage.inputTokens / 1e6) * rates.inputPerMTok +\n    (usage.outputTokens / 1e6) * rates.outputPerMTok +\n    ((usage.cacheReadTokens ?? 0) / 1e6) * cacheRead +\n    ((usage.cacheCreationTokens ?? 0) / 1e6) * cacheWrite\n  );\n}\n","// Model capabilities + request validation. This is the \"config is data\"\n// doctrine from odla-kg: what a model can do is a data descriptor, and every\n// request is checked against it *before* dispatch so a mismatch fails fast with\n// a clear CapabilityError instead of a confusing provider 400 (the canonical\n// example: audio input to a Claude model — Claude has no audio input).\n\nimport {\n  CapabilityError,\n  blocksOf,\n  type OracleRequest,\n  type ProviderId,\n} from \"./index\";\nimport type { ModelPricing } from \"./pricing\";\nimport type { Superpowers } from \"./superpowers\";\nimport type { ThinkingSupport } from \"./thinking\";\n\n/** The kind of model — chat/multimodal is the v1 focus; the others are modeled\n *  so embeddings, transcription, TTS, and image generation slot in later. */\nexport type ModelKind = \"chat\" | \"embed\" | \"transcribe\" | \"tts\" | \"image\";\n\nexport interface Capabilities {\n  kind: ModelKind;\n  /** Accepts text input. */\n  textIn: boolean;\n  /** Accepts image input (ImageBlock). */\n  imageIn: boolean;\n  /** Accepts audio input (AudioBlock). */\n  audioIn: boolean;\n  /** Accepts document/PDF input (DocumentBlock). */\n  documentIn: boolean;\n  /** Supports tool / function calling. */\n  toolUse: boolean;\n  /** Supports a native reasoning/thinking mode. */\n  thinking: boolean;\n  /** Supports an effort/reasoning-depth knob. */\n  effort: boolean;\n  /** Supports streaming responses. */\n  streaming: boolean;\n  /** Supports constrained JSON / structured output. */\n  structuredOutput: boolean;\n  /** Supports a provider server-side web-search tool. */\n  webSearch: boolean;\n  /** Tool results may carry content blocks natively (image/document blocks\n   *  inside a `tool_result`). When absent or false, the provider adapter\n   *  degrades non-text blocks in tool results to `[type]` text placeholders —\n   *  a lossy but non-fatal fallback, so this flag is discovery metadata for\n   *  consumers (e.g. vision-feeding tools) rather than a validation gate. */\n  toolResultBlocks?: boolean;\n}\n\n/** A catalog entry: a canonical model id mapped to a provider, that provider's\n *  native model id, and what the model can do. */\nexport interface ModelSpec {\n  /** Canonical id used across odla-ai (e.g. \"claude-opus-4-8\", \"gpt-5\"). */\n  id: string;\n  provider: ProviderId;\n  /** The id passed to the provider SDK. Often equal to `id`. */\n  nativeId: string;\n  capabilities: Capabilities;\n  contextWindow?: number;\n  maxOutput?: number;\n  /** Provider display name, for catalog/dashboard rendering. */\n  displayName?: string;\n  /** USD pricing per MTok; absent means unknown — never assume free. */\n  pricing?: ModelPricing;\n  /** Reasoning descriptor (thinking control + effort ladder). Authoritative\n   *  over the `capabilities.thinking`/`effort` booleans when present. */\n  thinking?: ThinkingSupport;\n  /** Provider server-side capabilities (web search, grounding, …) with typed\n   *  per-provider config. */\n  superpowers?: Superpowers;\n  /** Which of the provider's endpoints to call. OpenAI only today: `\"chat\"` is\n   *  Chat Completions, `\"responses\"` is `/v1/responses` — the only OpenAI\n   *  endpoint where reasoning and function tools coexist. Omit to let the\n   *  adapter choose (see `openaiApiFor`). */\n  api?: \"chat\" | \"responses\";\n}\n\n/** Sensible chat/multimodal defaults; per-model tables override what differs. */\nexport function chatCapabilities(overrides: Partial<Capabilities> = {}): Capabilities {\n  return {\n    kind: \"chat\",\n    textIn: true,\n    imageIn: true,\n    audioIn: false,\n    documentIn: false,\n    toolUse: true,\n    thinking: false,\n    effort: false,\n    streaming: true,\n    structuredOutput: true,\n    webSearch: false,\n    toolResultBlocks: false,\n    ...overrides,\n  };\n}\n\n/**\n * Validate a request against a model's capabilities. Throws CapabilityError on\n * the first violation. Runs before any provider call — the single choke point\n * that turns \"audio to Claude\" from an opaque upstream 400 into a clear error.\n */\nexport function validateRequest(spec: ModelSpec, req: OracleRequest): void {\n  const caps = spec.capabilities;\n  const fail = (what: string): never => {\n    throw new CapabilityError(\n      `Model \"${spec.id}\" (${spec.provider}) does not support ${what}.`,\n    );\n  };\n\n  if (caps.kind !== \"chat\") fail(`chat requests (it is a \"${caps.kind}\" model)`);\n\n  for (const msg of req.messages) {\n    for (const block of blocksOf(msg.content)) {\n      if (block.type === \"image\" && !caps.imageIn) fail(\"image input\");\n      if (block.type === \"audio\" && !caps.audioIn) fail(\"audio input\");\n      if (block.type === \"document\" && !caps.documentIn) fail(\"document (PDF) input\");\n    }\n  }\n\n  if (req.tools && req.tools.length > 0 && !caps.toolUse) fail(\"tool use\");\n  if (req.webSearch && !caps.webSearch && !spec.superpowers?.webSearch) fail(\"web search\");\n  if (req.responseFormat && !caps.structuredOutput) fail(\"structured output\");\n\n  const descriptor = spec.thinking;\n  if (descriptor) {\n    // Descriptor-aware gating: the per-model ThinkingSupport is authoritative.\n    if (req.thinking === \"off\" && descriptor.control === \"always-on\") {\n      fail(\"disabling thinking (thinking is always on for this model)\");\n    }\n    if (req.thinking === \"adaptive\" && descriptor.control === \"none\") fail(\"thinking\");\n    if (req.effort) {\n      const levels = descriptor.effortLevels ?? [];\n      if (!levels.includes(req.effort)) {\n        throw new CapabilityError(\n          `Model \"${spec.id}\" (${spec.provider}) does not support effort \"${req.effort}\". ` +\n            `Supported levels: ${levels.join(\", \") || \"(none)\"}.`,\n        );\n      }\n    }\n  } else {\n    // Legacy boolean fallback for specs authored before ThinkingSupport existed.\n    if (req.effort && !caps.effort) fail(\"the effort parameter\");\n    if (req.thinking === \"adaptive\" && !caps.thinking) fail(\"thinking\");\n  }\n}\n","// Per-model reasoning descriptor: how a model's thinking toggle behaves and how\n// the unified cross-provider effort ladder maps to that model's native knob.\n// This replaces the old lossy adapter heuristics (OpenAI silently collapsing\n// high/xhigh/max → \"high\"; Gemini ignoring effort entirely) with explicit,\n// per-model data that validateRequest can enforce.\n\nimport type { ProviderId } from \"./blocks\";\nimport type { Effort } from \"./request\";\nimport type { ModelSpec } from \"./capabilities\";\n\n/** How a model's `thinking` request field behaves. Describes the request\n *  toggle, not whether the model reasons internally. */\nexport type ThinkingControl =\n  /** No native thinking toggle; `thinking: \"adaptive\"` is rejected. */\n  | \"none\"\n  /** Thinking cannot be disabled; `thinking: \"off\"` is rejected. */\n  | \"always-on\"\n  /** Off unless the request sets `thinking: \"adaptive\"`. */\n  | \"opt-in\"\n  /** Adaptive unless the request sets `thinking: \"off\"`. */\n  | \"on-by-default\"\n  /** Legacy token-budget style; `\"adaptive\"` maps to a budget_tokens value. */\n  | \"budget\";\n\n/** The provider-native knob one unified `Effort` level maps to. The `param`\n *  discriminant lets each adapter assert the variant it expects and fail loudly\n *  on a mis-authored catalog entry. */\nexport type NativeEffort =\n  /** Anthropic `output_config.effort`. */\n  | { param: \"outputConfigEffort\"; value: Effort }\n  /** OpenAI `reasoning_effort`. */\n  | { param: \"reasoningEffort\"; value: string }\n  /** Google `thinkingConfig.thinkingBudget` (-1 = dynamic). */\n  | { param: \"thinkingBudget\"; value: number }\n  /** Google `thinkingConfig.thinkingLevel` (Gemini 3.x generation). */\n  | { param: \"thinkingLevel\"; value: \"minimal\" | \"low\" | \"medium\" | \"high\" };\n\n/** A model's reasoning descriptor: the effort-ladder levels it actually\n *  supports and how each maps to the provider-native knob. */\nexport interface ThinkingSupport {\n  control: ThinkingControl;\n  /** Ladder levels the model accepts, ascending. Omitted/empty = no effort knob. */\n  effortLevels?: Effort[];\n  /** Native mapping per supported level; keys must equal `effortLevels`. */\n  effortMap?: Partial<Record<Effort, NativeEffort>>;\n  /** `control: \"budget\"` only — the budget_tokens sent when a request asks for\n   *  `thinking: \"adaptive\"` (clamped below maxTokens by the adapter). */\n  defaultBudgetTokens?: number;\n  /** The native effort value to send when the request carries FUNCTION TOOLS.\n   *\n   *  Some reasoning models refuse tools while any reasoning is in play on the\n   *  provider's chat endpoint, and reason by default when the parameter is\n   *  omitted — so sending nothing is what fails. OpenAI's gpt-5.6 line says so\n   *  outright: \"Function tools with reasoning_effort are not supported … use\n   *  /v1/responses or set reasoning_effort to 'none'\".\n   *\n   *  Set it and the adapter sends this value for tool-carrying requests instead\n   *  of leaving the model on its default. Requesting an explicit `effort`\n   *  alongside tools on such a model is a CapabilityError, not a silent\n   *  downgrade — the caller asked for depth the endpoint cannot give. */\n  toolsEffort?: NativeEffort;\n}\n\n/** The full unified effort ladder, ascending. */\nexport const EFFORT_LEVELS: readonly Effort[] = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"];\n\n/** Resolve the provider-native mapping for an effort level on a model, or\n *  undefined when the model does not map that level. */\nexport function nativeEffort(spec: ModelSpec, effort: Effort): NativeEffort | undefined {\n  return spec.thinking?.effortMap?.[effort];\n}\n\n/** The effort levels a spec supports — descriptor first; specs authored before\n *  the descriptor existed fall back to the legacy capability boolean (all\n *  levels when `capabilities.effort` is true). */\nexport function supportedEffortLevels(spec: ModelSpec): Effort[] {\n  if (spec.thinking) return spec.thinking.effortLevels ?? [];\n  return spec.capabilities.effort ? [...EFFORT_LEVELS] : [];\n}\n\n/** Generic Gemini thinkingBudget ladder used when no hand-tuned map exists. */\nconst GOOGLE_BUDGETS: Record<Effort, number> = {\n  low: 1_024,\n  medium: 4_096,\n  high: 8_192,\n  xhigh: 16_384,\n  max: 24_576,\n};\n\n/**\n * Derive a sensible per-provider `effortMap` for a set of levels: identity\n * maps for Anthropic (`output_config.effort`) and OpenAI (`reasoning_effort`),\n * a generic token-budget ladder for Google. Used by callers (e.g. the odla\n * platform's catalog editor) that know a model's levels but not its native\n * knob values; hand-tuned catalog entries override this.\n */\nexport function defaultEffortMap(\n  provider: ProviderId,\n  levels: Effort[],\n  nativeId?: string,\n): Partial<Record<Effort, NativeEffort>> {\n  const out: Partial<Record<Effort, NativeEffort>> = {};\n  for (const level of levels) {\n    if (provider === \"google\" && nativeId?.startsWith(\"gemini-3\")) {\n      if (level === \"low\" || level === \"medium\" || level === \"high\") {\n        out[level] = { param: \"thinkingLevel\", value: level };\n      }\n    } else if (provider === \"google\") out[level] = { param: \"thinkingBudget\", value: GOOGLE_BUDGETS[level] };\n    else if (provider === \"openai\") out[level] = { param: \"reasoningEffort\", value: level };\n    else out[level] = { param: \"outputConfigEffort\", value: level };\n  }\n  return out;\n}\n","// Anthropic (Claude) model catalog — config as data.\n//\n// VERIFIED 2026-07-15 against the live Models API (GET /v1/models via\n// listModels() with a real key): ids, display names, context windows, max\n// output, adaptive-thinking support, and per-model effort ladders all come\n// from the listing (opus-4-6/sonnet-4-6 have no \"xhigh\"; haiku-4-5 has no\n// adaptive thinking — it is budget_tokens-style). Pricing from the Anthropic\n// docs the same day (cache rates from the documented multipliers: read 0.1×,\n// default-TTL write 1.25×). web_search_20260209 verified with a live call on\n// claude-fable-5. Re-verify via listModels() before shipping if time has\n// passed — never hardcode model ids from memory.\n//\n// 2026-10-09, from Anthropic's models overview, the Haiku 5.5 model page and\n// migration guide, the programmatic tool calling page and the pricing page\n// (docs, not a Models API listing): Claude Haiku 5.5 added, the first model\n// here priced by prompt length; Sonnet 5's $2/$10 \"intro\" price is now its\n// standard price; Haiku 4.5 is a legacy model.\n\nimport { chatCapabilities, type ModelSpec } from \"../shape/capabilities\";\nimport type { ModelPricing, TokenRates } from \"../shape/pricing\";\nimport type { Effort } from \"../shape/request\";\nimport type { Superpowers } from \"../shape/superpowers\";\nimport { defaultEffortMap, type ThinkingControl, type ThinkingSupport } from \"../shape/thinking\";\n\nconst FRONTIER = () =>\n  chatCapabilities({\n    documentIn: true, // PDF\n    thinking: true, // adaptive\n    effort: true, // output_config.effort\n    webSearch: true, // web_search_20260209\n    audioIn: false, // Claude has no audio input\n    toolResultBlocks: true, // adapter maps image/document blocks inside tool_result\n  });\n\nconst WEB_SEARCH: Superpowers = {\n  webSearch: { type: \"anthropic-web-search\", toolType: \"web_search_20260209\" },\n};\n\nconst FIVE: Effort[] = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"];\nconst FOUR: Effort[] = [\"low\", \"medium\", \"high\", \"max\"]; // 4.6 tier: no xhigh\n\nconst thinking = (control: ThinkingControl, levels: Effort[]): ThinkingSupport => ({\n  control,\n  effortLevels: levels,\n  effortMap: defaultEffortMap(\"anthropic\", levels),\n});\n\nconst rates = (inputPerMTok: number, outputPerMTok: number): TokenRates => ({\n  inputPerMTok,\n  outputPerMTok,\n  cacheReadPerMTok: inputPerMTok * 0.1,\n  cacheWritePerMTok: inputPerMTok * 1.25,\n});\n\nconst price = (inputPerMTok: number, outputPerMTok: number, note?: string): ModelPricing => ({\n  ...rates(inputPerMTok, outputPerMTok),\n  ...(note ? { note } : {}),\n});\n\n/** Built-in Anthropic (Claude) catalog: one `ModelSpec` per model (canonical id, native id, capabilities, limits, pricing, thinking descriptor). */\nexport const ANTHROPIC_MODELS: ModelSpec[] = [\n  {\n    id: \"claude-opus-5\",\n    provider: \"anthropic\",\n    nativeId: \"claude-opus-5\",\n    displayName: \"Claude Opus 5\",\n    capabilities: FRONTIER(),\n    contextWindow: 1_000_000,\n    maxOutput: 128_000,\n    pricing: price(5, 25),\n    thinking: thinking(\"on-by-default\", FIVE),\n    superpowers: WEB_SEARCH,\n  },\n  {\n    id: \"claude-opus-4-8\",\n    provider: \"anthropic\",\n    nativeId: \"claude-opus-4-8\",\n    displayName: \"Claude Opus 4.8\",\n    capabilities: FRONTIER(),\n    contextWindow: 1_000_000,\n    maxOutput: 128_000,\n    pricing: price(5, 25),\n    thinking: thinking(\"opt-in\", FIVE),\n    superpowers: WEB_SEARCH,\n  },\n  {\n    id: \"claude-opus-4-7\",\n    provider: \"anthropic\",\n    nativeId: \"claude-opus-4-7\",\n    displayName: \"Claude Opus 4.7\",\n    capabilities: FRONTIER(),\n    contextWindow: 1_000_000,\n    maxOutput: 128_000,\n    pricing: price(5, 25),\n    thinking: thinking(\"opt-in\", FIVE),\n    superpowers: WEB_SEARCH,\n  },\n  {\n    id: \"claude-opus-4-6\",\n    provider: \"anthropic\",\n    nativeId: \"claude-opus-4-6\",\n    displayName: \"Claude Opus 4.6\",\n    capabilities: FRONTIER(),\n    contextWindow: 1_000_000,\n    maxOutput: 128_000,\n    pricing: price(5, 25),\n    thinking: thinking(\"opt-in\", FOUR),\n    superpowers: WEB_SEARCH,\n  },\n  {\n    // Thinking is always on for Fable 5 — thinking:\"off\" is rejected.\n    id: \"claude-fable-5\",\n    provider: \"anthropic\",\n    nativeId: \"claude-fable-5\",\n    displayName: \"Claude Fable 5\",\n    capabilities: FRONTIER(),\n    contextWindow: 1_000_000,\n    maxOutput: 128_000,\n    pricing: price(10, 50),\n    thinking: thinking(\"always-on\", FIVE),\n    superpowers: WEB_SEARCH,\n  },\n  {\n    // Sonnet 5 runs adaptive thinking unless the request turns it off.\n    id: \"claude-sonnet-5\",\n    provider: \"anthropic\",\n    nativeId: \"claude-sonnet-5\",\n    displayName: \"Claude Sonnet 5\",\n    capabilities: FRONTIER(),\n    contextWindow: 1_000_000,\n    maxOutput: 128_000,\n    pricing: price(2, 10),\n    thinking: thinking(\"on-by-default\", FIVE),\n    superpowers: WEB_SEARCH,\n  },\n  {\n    id: \"claude-sonnet-4-6\",\n    provider: \"anthropic\",\n    nativeId: \"claude-sonnet-4-6\",\n    displayName: \"Claude Sonnet 4.6\",\n    capabilities: FRONTIER(),\n    contextWindow: 1_000_000,\n    maxOutput: 128_000,\n    pricing: price(3, 15),\n    thinking: thinking(\"opt-in\", FOUR),\n    superpowers: WEB_SEARCH,\n  },\n  {\n    // Haiku 5.5 is the first Haiku on the frontier request shape: adaptive\n    // thinking on unless the request turns it off, the full effort ladder, no\n    // sampling params. Unlike Haiku 4.5 it supports programmatic tool calling,\n    // which web_search_20260209's dynamic filtering runs through, so it takes\n    // the same web search the frontier tier does. It is also priced by prompt\n    // length — a request whose prompt is over 100K tokens pays five times as\n    // much on every token, cache reads and writes included.\n    id: \"claude-haiku-5-5\",\n    provider: \"anthropic\",\n    nativeId: \"claude-haiku-5-5\",\n    displayName: \"Claude Haiku 5.5\",\n    capabilities: FRONTIER(),\n    contextWindow: 1_000_000,\n    maxOutput: 128_000,\n    pricing: { ...price(0.1, 0.5), longContext: { aboveTokens: 100_000, ...rates(0.5, 2.5) } },\n    thinking: thinking(\"on-by-default\", FIVE),\n    superpowers: WEB_SEARCH,\n  },\n  {\n    // Haiku 4.5 (legacy since Haiku 5.5, which costs a tenth as much up to\n    // 100K prompt tokens): no effort param, no adaptive thinking (budget_tokens\n    // style), web search needs Sonnet-4.6+ — all reflected below.\n    id: \"claude-haiku-4-5\",\n    provider: \"anthropic\",\n    // The convenient canonical id routes to Anthropic's pinned dated model.\n    nativeId: \"claude-haiku-4-5-20251001\",\n    displayName: \"Claude Haiku 4.5\",\n    capabilities: chatCapabilities({\n      documentIn: true,\n      thinking: true, // budget-style thinking (mapped to budget_tokens)\n      effort: false,\n      webSearch: false,\n      audioIn: false,\n      toolResultBlocks: true, // same messages API + adapter mapping as the frontier tier\n    }),\n    contextWindow: 200_000,\n    maxOutput: 64_000,\n    pricing: price(1, 5),\n    thinking: { control: \"budget\", defaultBudgetTokens: 8_192 },\n  },\n];\n","// OpenAI model catalog — config as data.\n//\n// VERIFIED 2026-08-30 against the account's live /v1/models list (via\n// listModels() with a real key) and the official model/pricing pages\n// (developers.openai.com). reasoning_effort ladders verified EMPIRICALLY with\n// live calls per model: the gpt-5.4/5.5 generation accepts low/medium/high/\n// xhigh (plus \"none\", not part of the unified ladder — reachable via\n// providerExtras); the gpt-5 generation accepts low/medium/high only; search/\n// audio/4o lines reject reasoning_effort outright. OpenAI now publishes full\n// limits, modalities, effort ladders, tools, and token/cache prices for the\n// gpt-5.6 Sol/Terra/Luna family, so those stable ids are authoritative builtins\n// rather than mutable provider-discovery imports. Re-verify via listModels()\n// and the official model pages as the lineup drifts; do NOT trust ids from\n// memory. Pass a custom catalog to init() to add models without a release.\n\nimport { chatCapabilities, type ModelSpec } from \"../shape/capabilities\";\nimport { scaleLongContext, type ModelPricing } from \"../shape/pricing\";\nimport type { Effort } from \"../shape/request\";\nimport { defaultEffortMap, type ThinkingSupport } from \"../shape/thinking\";\n\nconst LADDER_54: Effort[] = [\"low\", \"medium\", \"high\", \"xhigh\"];\nconst LADDER_5: Effort[] = [\"low\", \"medium\", \"high\"];\nconst LADDER_56: Effort[] = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"];\n\n// OpenAI reasoning models have no thinking on/off toggle in the canonical\n// shape (control:\"none\"); depth is driven purely by the effort ladder.\nconst reasoning = (levels: Effort[]): ThinkingSupport => ({\n  control: \"none\",\n  effortLevels: levels,\n  effortMap: defaultEffortMap(\"openai\", levels),\n});\n\n// GPT-5.6 reasons at medium by default and accepts `none` as the native off\n// value. The canonical toggle therefore starts on while the explicit effort\n// ladder remains low..max.\nconst reasoning56 = (): ThinkingSupport => ({\n  control: \"on-by-default\",\n  effortLevels: LADDER_56,\n  effortMap: defaultEffortMap(\"openai\", LADDER_56),\n});\n\nconst price = (\n  inputPerMTok: number,\n  outputPerMTok: number,\n  cacheReadPerMTok: number,\n  note?: string,\n): ModelPricing => ({ inputPerMTok, outputPerMTok, cacheReadPerMTok, ...(note ? { note } : {}) });\n\n/** OpenAI's long-context rule, verified against its pricing page 2026-10-09:\n *  a prompt over 272K input tokens bills the whole request at 2× on every\n *  prompt-side rate (input, cached input, cache writes) and 1.5× on output. */\nconst longContext = (base: ModelPricing): ModelPricing => ({\n  ...base,\n  longContext: scaleLongContext(base, 272_000, 2, 1.5),\n});\n\nconst price56 = (\n  inputPerMTok: number,\n  outputPerMTok: number,\n  cacheReadPerMTok: number,\n  note?: string,\n): ModelPricing => longContext({\n  inputPerMTok,\n  outputPerMTok,\n  cacheReadPerMTok,\n  cacheWritePerMTok: inputPerMTok * 1.25,\n  ...(note ? { note } : {}),\n});\n\n/** Built-in OpenAI catalog: one `ModelSpec` per model (canonical id == native id, capabilities, limits, pricing, thinking descriptor). */\nexport const OPENAI_MODELS: ModelSpec[] = [\n  {\n    id: \"gpt-5.6-sol\",\n    provider: \"openai\",\n    nativeId: \"gpt-5.6-sol\",\n    displayName: \"GPT-5.6 Sol\",\n    capabilities: chatCapabilities({ thinking: true, effort: true, webSearch: true }),\n    contextWindow: 1_050_000,\n    maxOutput: 128_000,\n    pricing: price56(4, 20, 0.4, \"promotional pricing through at least 2026-11-21\"),\n    thinking: reasoning56(),\n    superpowers: { webSearch: { type: \"openai-web-search\", contextSize: \"medium\" } },\n    api: \"responses\",\n  },\n  {\n    id: \"gpt-5.6-terra\",\n    provider: \"openai\",\n    nativeId: \"gpt-5.6-terra\",\n    displayName: \"GPT-5.6 Terra\",\n    capabilities: chatCapabilities({ thinking: true, effort: true, webSearch: true }),\n    contextWindow: 1_050_000,\n    maxOutput: 128_000,\n    pricing: price56(2, 12, 0.2),\n    thinking: reasoning56(),\n    superpowers: { webSearch: { type: \"openai-web-search\", contextSize: \"medium\" } },\n    api: \"responses\",\n  },\n  {\n    id: \"gpt-5.6-luna\",\n    provider: \"openai\",\n    nativeId: \"gpt-5.6-luna\",\n    displayName: \"GPT-5.6 Luna\",\n    capabilities: chatCapabilities({ thinking: true, effort: true, webSearch: true }),\n    contextWindow: 1_050_000,\n    maxOutput: 128_000,\n    pricing: price56(0.2, 1.2, 0.02),\n    thinking: reasoning56(),\n    superpowers: { webSearch: { type: \"openai-web-search\", contextSize: \"medium\" } },\n    api: \"responses\",\n  },\n  {\n    id: \"gpt-5.5\",\n    provider: \"openai\",\n    nativeId: \"gpt-5.5\",\n    displayName: \"GPT-5.5\",\n    capabilities: chatCapabilities({ effort: true }),\n    contextWindow: 1_050_000,\n    maxOutput: 128_000,\n    pricing: longContext(price(5, 30, 0.5)),\n    thinking: reasoning(LADDER_54),\n  },\n  {\n    id: \"gpt-5.4\",\n    provider: \"openai\",\n    nativeId: \"gpt-5.4\",\n    displayName: \"GPT-5.4\",\n    capabilities: chatCapabilities({ effort: true }),\n    contextWindow: 1_050_000,\n    maxOutput: 128_000,\n    pricing: longContext(price(2.5, 15, 0.25)),\n    thinking: reasoning(LADDER_54),\n  },\n  {\n    // Compact GPT-5.4 reasoning model. The default for odla-o11y AI triage.\n    id: \"gpt-5.4-mini\",\n    provider: \"openai\",\n    nativeId: \"gpt-5.4-mini\",\n    displayName: \"GPT-5.4 mini\",\n    capabilities: chatCapabilities({ effort: true }),\n    contextWindow: 400_000,\n    maxOutput: 128_000,\n    pricing: price(0.75, 4.5, 0.075),\n    thinking: reasoning(LADDER_54),\n  },\n  {\n    id: \"gpt-5.4-nano\",\n    provider: \"openai\",\n    nativeId: \"gpt-5.4-nano\",\n    displayName: \"GPT-5.4 nano\",\n    capabilities: chatCapabilities({ effort: true }),\n    contextWindow: 400_000,\n    maxOutput: 128_000,\n    pricing: price(0.2, 1.25, 0.02),\n    thinking: reasoning(LADDER_54),\n  },\n  {\n    id: \"gpt-5\",\n    provider: \"openai\",\n    nativeId: \"gpt-5\",\n    displayName: \"GPT-5\",\n    capabilities: chatCapabilities({ effort: true }),\n    contextWindow: 400_000,\n    maxOutput: 128_000,\n    pricing: price(1.25, 10, 0.125),\n    thinking: reasoning(LADDER_5),\n  },\n  {\n    id: \"gpt-5-mini\",\n    provider: \"openai\",\n    nativeId: \"gpt-5-mini\",\n    displayName: \"GPT-5 mini\",\n    capabilities: chatCapabilities({ effort: true }),\n    contextWindow: 400_000,\n    maxOutput: 128_000,\n    pricing: price(0.25, 2, 0.025),\n    thinking: reasoning(LADDER_5),\n  },\n  {\n    id: \"gpt-5-nano\",\n    provider: \"openai\",\n    nativeId: \"gpt-5-nano\",\n    displayName: \"GPT-5 nano\",\n    capabilities: chatCapabilities({ effort: true }),\n    contextWindow: 400_000,\n    maxOutput: 128_000,\n    pricing: price(0.05, 0.4, 0.005),\n    thinking: reasoning(LADDER_5),\n  },\n  {\n    // Search-tuned chat model: the adapter sends web_search_options when a\n    // request sets webSearch. No reasoning-effort knob (verified: 400).\n    id: \"gpt-5-search-api\",\n    provider: \"openai\",\n    nativeId: \"gpt-5-search-api\",\n    displayName: \"GPT-5 Search API\",\n    capabilities: chatCapabilities({ webSearch: true }),\n    contextWindow: 400_000,\n    maxOutput: 128_000,\n    pricing: price(1.25, 10, 0.125, \"plus per-search-call tool fees\"),\n    thinking: { control: \"none\" },\n    superpowers: { webSearch: { type: \"openai-web-search\", contextSize: \"medium\" } },\n  },\n  {\n    // Non-reasoning multimodal chat (image input, no effort knob).\n    id: \"gpt-4o\",\n    provider: \"openai\",\n    nativeId: \"gpt-4o\",\n    displayName: \"GPT-4o\",\n    capabilities: chatCapabilities(),\n    contextWindow: 128_000,\n    maxOutput: 16_384,\n    pricing: price(2.5, 10, 1.25),\n    thinking: { control: \"none\" },\n  },\n  {\n    // Audio-input model line — accepts audio, not images.\n    id: \"gpt-audio\",\n    provider: \"openai\",\n    nativeId: \"gpt-audio\",\n    displayName: \"GPT Audio\",\n    capabilities: chatCapabilities({ imageIn: false, audioIn: true }),\n    contextWindow: 128_000,\n    maxOutput: 16_384,\n    pricing: price(2.5, 10, 0.25, \"text tokens; audio tokens bill separately\"),\n    thinking: { control: \"none\" },\n  },\n];\n","// Google (Gemini) model catalog — config as data.\n//\n// VERIFIED 2026-07-15 against the live models.list (via listModels() with a\n// real key) and ai.google.dev pricing. Thinking knobs verified EMPIRICALLY per\n// model: the Gemini 3.x generation takes thinkingConfig.thinkingLevel\n// (minimal/low/medium/high — pro rejects minimal) and still accepts budgets;\n// the 2.5 generation takes thinkingBudget only (pro: 128–32768, cannot\n// disable; flash: 0–24576, 0 = off); 2.0-flash has no thinking. Note\n// gemini-3-pro-preview was RETIRED upstream (404) — hence its absence.\n// Re-verify via listModels() before shipping; do NOT trust ids from memory.\n//\n// Gemini is natively multimodal: text + image + audio + PDF input, tool\n// calling via functionDeclarations, structured output via responseSchema, and\n// web grounding via the googleSearch tool — hence the broad default caps.\n\nimport { chatCapabilities, type ModelSpec } from \"../shape/capabilities\";\nimport type { ModelPricing } from \"../shape/pricing\";\nimport type { Effort } from \"../shape/request\";\nimport type { Superpowers } from \"../shape/superpowers\";\nimport type { NativeEffort, ThinkingControl, ThinkingSupport } from \"../shape/thinking\";\n\nconst GEMINI = (over: { thinking?: boolean; effort?: boolean } = {}) =>\n  chatCapabilities({\n    audioIn: true,\n    documentIn: true,\n    thinking: over.thinking ?? true,\n    effort: over.effort ?? true,\n    webSearch: true, // googleSearch grounding\n  });\n\nconst GROUNDING: Superpowers = { webSearch: { type: \"google-search-grounding\" } };\n\n// Gemini 3.x: unified ladder → thinkingConfig.thinkingLevel (identity).\nconst levels = (control: ThinkingControl): ThinkingSupport => ({\n  control,\n  effortLevels: [\"low\", \"medium\", \"high\"],\n  effortMap: {\n    low: { param: \"thinkingLevel\", value: \"low\" },\n    medium: { param: \"thinkingLevel\", value: \"medium\" },\n    high: { param: \"thinkingLevel\", value: \"high\" },\n  },\n});\n\n// Gemini 2.5: unified ladder → thinkingConfig.thinkingBudget token values.\nconst budgets = (control: ThinkingControl, values: [number, number, number, number, number]): ThinkingSupport => {\n  const ladder: Effort[] = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"];\n  const effortMap: Partial<Record<Effort, NativeEffort>> = {};\n  ladder.forEach((level, i) => {\n    effortMap[level] = { param: \"thinkingBudget\", value: values[i]! };\n  });\n  return { control, effortLevels: ladder, effortMap };\n};\n\nconst price = (\n  inputPerMTok: number,\n  outputPerMTok: number,\n  cacheReadPerMTok: number,\n  note?: string,\n): ModelPricing => ({ inputPerMTok, outputPerMTok, cacheReadPerMTok, ...(note ? { note } : {}) });\n\n/** A Gemini Pro price with its second rate card: a prompt over 200K tokens\n *  bills the whole request at the higher rates. Verified against\n *  ai.google.dev/gemini-api/docs/pricing on 2026-10-09. */\nconst tiered = (base: ModelPricing, input: number, output: number, cacheRead: number): ModelPricing => ({\n  ...base,\n  longContext: { aboveTokens: 200_000, inputPerMTok: input, outputPerMTok: output, cacheReadPerMTok: cacheRead },\n});\n\n/** Built-in Google (Gemini) catalog: one `ModelSpec` per model (canonical id == native id, capabilities, limits, pricing, thinking descriptor). */\nexport const GOOGLE_MODELS: ModelSpec[] = [\n  {\n    // Stable model and limits verified 2026-08-29 against Google's model and\n    // pricing pages. The single output price is intentionally the conservative\n    // image-token rate; text/thinking output is cheaper, as the note records.\n    id: \"gemini-3.1-flash-lite-image\",\n    provider: \"google\",\n    nativeId: \"gemini-3.1-flash-lite-image\",\n    displayName: \"Nano Banana 2 Lite\",\n    capabilities: chatCapabilities({\n      audioIn: false,\n      documentIn: false,\n      thinking: true,\n      effort: true,\n      structuredOutput: false,\n      webSearch: false,\n    }),\n    contextWindow: 65_536,\n    maxOutput: 4_096,\n    pricing: {\n      inputPerMTok: 0.25,\n      outputPerMTok: 30,\n      note: \"image output; text/thinking output is $1.50/MTok; one 1K image is 1,120 tokens ($0.0336)\",\n    },\n    thinking: {\n      control: \"always-on\",\n      effortLevels: [\"low\", \"high\"],\n      effortMap: {\n        low: { param: \"thinkingLevel\", value: \"minimal\" },\n        high: { param: \"thinkingLevel\", value: \"high\" },\n      },\n    },\n  },\n  {\n    // Stable identity, limits, capabilities, and paid standard pricing\n    // verified 2026-08-30 against Google's model, image-generation, and\n    // pricing pages. Image output is the conservative catalog rate.\n    id: \"gemini-3.1-flash-image\",\n    provider: \"google\",\n    nativeId: \"gemini-3.1-flash-image\",\n    displayName: \"Nano Banana 2\",\n    capabilities: chatCapabilities({\n      audioIn: false,\n      documentIn: true,\n      toolUse: false,\n      thinking: true,\n      effort: true,\n      structuredOutput: false,\n      webSearch: true,\n    }),\n    contextWindow: 131_072,\n    maxOutput: 32_768,\n    pricing: {\n      inputPerMTok: 0.5,\n      outputPerMTok: 60,\n      note: \"image output; text/thinking output is $3/MTok; 0.5K/1K/2K/4K images cost $0.045/$0.067/$0.101/$0.151\",\n    },\n    thinking: {\n      control: \"always-on\",\n      effortLevels: [\"low\", \"high\"],\n      effortMap: {\n        low: { param: \"thinkingLevel\", value: \"minimal\" },\n        high: { param: \"thinkingLevel\", value: \"high\" },\n      },\n    },\n    superpowers: GROUNDING,\n  },\n  {\n    id: \"gemini-3-pro-image\",\n    provider: \"google\",\n    nativeId: \"gemini-3-pro-image\",\n    displayName: \"Nano Banana Pro\",\n    capabilities: chatCapabilities({\n      audioIn: false,\n      documentIn: false,\n      toolUse: false,\n      thinking: true,\n      effort: false,\n      structuredOutput: false,\n      webSearch: true,\n    }),\n    contextWindow: 65_536,\n    maxOutput: 32_768,\n    pricing: {\n      inputPerMTok: 2,\n      outputPerMTok: 120,\n      note: \"image output; text/thinking output is $12/MTok; 1K/2K images cost $0.134 and 4K images cost $0.24\",\n    },\n    thinking: { control: \"always-on\" },\n    superpowers: GROUNDING,\n  },\n  {\n    id: \"gemini-3.5-flash\",\n    provider: \"google\",\n    nativeId: \"gemini-3.5-flash\",\n    displayName: \"Gemini 3.5 Flash\",\n    capabilities: GEMINI(),\n    contextWindow: 1_048_576,\n    maxOutput: 65_536,\n    pricing: price(1.5, 9, 0.15),\n    thinking: levels(\"on-by-default\"),\n    superpowers: GROUNDING,\n  },\n  {\n    id: \"gemini-3.1-pro-preview\",\n    provider: \"google\",\n    nativeId: \"gemini-3.1-pro-preview\",\n    displayName: \"Gemini 3.1 Pro Preview\",\n    capabilities: GEMINI(),\n    contextWindow: 1_048_576,\n    maxOutput: 65_536,\n    pricing: tiered(price(2, 12, 0.2), 4, 18, 0.4),\n    thinking: levels(\"always-on\"),\n    superpowers: GROUNDING,\n  },\n  {\n    id: \"gemini-3-flash-preview\",\n    provider: \"google\",\n    nativeId: \"gemini-3-flash-preview\",\n    displayName: \"Gemini 3 Flash Preview\",\n    capabilities: GEMINI(),\n    contextWindow: 1_048_576,\n    maxOutput: 65_536,\n    pricing: price(0.5, 3, 0.05),\n    thinking: levels(\"on-by-default\"),\n    superpowers: GROUNDING,\n  },\n  {\n    // 2.5 Pro only works in thinking mode (budget 0 rejected upstream).\n    id: \"gemini-2.5-pro\",\n    provider: \"google\",\n    nativeId: \"gemini-2.5-pro\",\n    displayName: \"Gemini 2.5 Pro\",\n    capabilities: GEMINI(),\n    contextWindow: 1_048_576,\n    maxOutput: 65_536,\n    pricing: tiered(price(1.25, 10, 0.125), 2.5, 15, 0.25),\n    thinking: budgets(\"always-on\", [2_048, 8_192, 16_384, 24_576, 32_768]),\n    superpowers: GROUNDING,\n  },\n  {\n    id: \"gemini-2.5-flash\",\n    provider: \"google\",\n    nativeId: \"gemini-2.5-flash\",\n    displayName: \"Gemini 2.5 Flash\",\n    capabilities: GEMINI(),\n    contextWindow: 1_048_576,\n    maxOutput: 65_536,\n    pricing: price(0.3, 2.5, 0.03),\n    thinking: budgets(\"on-by-default\", [1_024, 4_096, 8_192, 16_384, 24_576]),\n    superpowers: GROUNDING,\n  },\n  {\n    id: \"gemini-2.5-flash-image\",\n    provider: \"google\",\n    nativeId: \"gemini-2.5-flash-image\",\n    displayName: \"Nano Banana\",\n    capabilities: chatCapabilities({\n      audioIn: false,\n      documentIn: false,\n      toolUse: false,\n      thinking: false,\n      effort: false,\n      structuredOutput: true,\n      webSearch: false,\n    }),\n    contextWindow: 65_536,\n    maxOutput: 32_768,\n    pricing: {\n      inputPerMTok: 0.3,\n      outputPerMTok: 30,\n      note: \"image output; text output is $2.50/MTok; one 1K image is 1,290 tokens ($0.039)\",\n    },\n    thinking: { control: \"none\" },\n  },\n  {\n    id: \"gemini-2.0-flash\",\n    provider: \"google\",\n    nativeId: \"gemini-2.0-flash\",\n    displayName: \"Gemini 2.0 Flash\",\n    capabilities: GEMINI({ thinking: false, effort: false }),\n    contextWindow: 1_048_576,\n    maxOutput: 8_192,\n    pricing: price(0.1, 0.4, 0.025),\n    thinking: { control: \"none\" },\n    superpowers: GROUNDING,\n  },\n];\n","// The model catalog: canonical model id → ModelSpec (provider, native id,\n// capabilities). The default catalog merges the three per-provider tables;\n// init() accepts a custom or extended catalog so apps can add/override models\n// without waiting on a release.\n\nimport { ConfigError, type ProviderId } from \"../shape/index\";\nimport type { ModelSpec } from \"../shape/capabilities\";\nimport { ANTHROPIC_MODELS } from \"./anthropic\";\nimport { OPENAI_MODELS } from \"./openai\";\nimport { GOOGLE_MODELS } from \"./google\";\n\n/** Canonical id → spec. */\nexport type Catalog = Record<string, ModelSpec>;\n\nfunction index(specs: ModelSpec[]): Catalog {\n  const out: Catalog = {};\n  for (const spec of specs) out[spec.id] = spec;\n  return out;\n}\n\n/** The built-in catalog across Anthropic, OpenAI, and Google. */\nexport const DEFAULT_CATALOG: Catalog = index([\n  ...ANTHROPIC_MODELS,\n  ...OPENAI_MODELS,\n  ...GOOGLE_MODELS,\n]);\n\n/** Merge extra specs over a base catalog (later entries win by id). */\nexport function buildCatalog(base: Catalog, extra: ModelSpec[] = []): Catalog {\n  return { ...base, ...index(extra) };\n}\n\n/** Look up a model, throwing a ConfigError (with the known ids) if unknown. */\nexport function resolveModel(catalog: Catalog, id: string): ModelSpec {\n  const spec = catalog[id];\n  if (!spec) {\n    const known = Object.keys(catalog).sort().join(\", \");\n    throw new ConfigError(`Unknown model \"${id}\". Known models: ${known || \"(none)\"}.`);\n  }\n  return spec;\n}\n\n/** List every provider the catalog can route to. */\nexport function providersInCatalog(catalog: Catalog): ProviderId[] {\n  const set = new Set<ProviderId>();\n  for (const spec of Object.values(catalog)) set.add(spec.provider);\n  return [...set];\n}\n\nexport { ANTHROPIC_MODELS, OPENAI_MODELS, GOOGLE_MODELS };\n","// Catalog-backed pricing lookup. The catalog already carries per-model\n// `ModelPricing`; this is the seam that lets a cost-accounting consumer price a\n// call from a model id alone, without holding a Catalog or an Ai client.\n//\n// Deliberately free of provider-SDK imports (the whole `catalog/` + `shape/`\n// subtree is), so `@odla-ai/ai/pricing` stays a few KB in a Worker bundle.\n\nimport { costUsd, type ModelPricing } from \"../shape/pricing\";\nimport type { OracleUsage } from \"../shape/usage\";\nimport { DEFAULT_CATALOG, type Catalog } from \"./index\";\n\n/**\n * Look up a model's USD pricing by canonical id.\n *\n * Returns `undefined` for an unknown model *and* for a known model whose spec\n * carries no `pricing` — the two are the same answer to the only question that\n * matters downstream: \"can this call be priced?\". Unlike `resolveModel`, an\n * unknown id is not an error, because a cost path must degrade to \"unpriced\"\n * rather than throw inside telemetry.\n *\n * @param id Canonical model id, e.g. `\"claude-opus-4-8\"`.\n * @param catalog Catalog to read; defaults to the built-in `DEFAULT_CATALOG`.\n */\nexport function modelPricing(id: string, catalog: Catalog = DEFAULT_CATALOG): ModelPricing | undefined {\n  return catalog[id]?.pricing;\n}\n\n/**\n * Price one call from a model id and its token usage.\n *\n * Returns `undefined` when the model has no known pricing, so a caller can\n * never mistake missing catalog data for a free call. Cache-read and\n * cache-write tokens are priced at their own rates when the spec declares them\n * and fall back to the input rate otherwise (see `costUsd`).\n *\n * @param id Canonical model id, e.g. `\"gpt-5\"`.\n * @param usage Token counts for the call.\n * @param catalog Catalog to read; defaults to the built-in `DEFAULT_CATALOG`.\n */\nexport function priceCall(id: string, usage: OracleUsage, catalog: Catalog = DEFAULT_CATALOG): number | undefined {\n  const pricing = modelPricing(id, catalog);\n  return pricing ? costUsd(pricing, usage) : undefined;\n}\n\n/**\n * The canonical ids of every model in `catalog` that carries pricing, sorted.\n * Useful for a coverage assertion (\"does our catalog price everything we\n * route to?\") and for rendering a pricing table.\n *\n * @param catalog Catalog to read; defaults to the built-in `DEFAULT_CATALOG`.\n */\nexport function pricedModels(catalog: Catalog = DEFAULT_CATALOG): string[] {\n  return Object.keys(catalog)\n    .filter((id) => catalog[id]?.pricing !== undefined)\n    .sort();\n}\n"],"mappings":"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","names":["rates","levels","levels","levels","price","price"]}