@agentproto/model-catalog 0.5.0 → 0.6.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.
Files changed (38) hide show
  1. package/dist/access/index.d.ts +5 -5
  2. package/dist/audio/index.d.ts +1 -1
  3. package/dist/{audio-BbeLA_4x.d.ts → audio-DR0g_ZH_.d.ts} +1 -0
  4. package/dist/{base-C4kz9Dxc.d.ts → base-B8IIoaqg.d.ts} +2 -0
  5. package/dist/{catalog-BPDMuxzf.d.ts → catalog-CLQ-Bo1n.d.ts} +17 -1
  6. package/dist/{chunk-S74S3Q7Z.mjs → chunk-34LOJCOZ.mjs} +3 -3
  7. package/dist/{chunk-S74S3Q7Z.mjs.map → chunk-34LOJCOZ.mjs.map} +1 -1
  8. package/dist/{chunk-VIVKDMAT.mjs → chunk-DUAH5LWG.mjs} +3 -3
  9. package/dist/{chunk-VIVKDMAT.mjs.map → chunk-DUAH5LWG.mjs.map} +1 -1
  10. package/dist/chunk-DW45X6XT.mjs +70 -0
  11. package/dist/chunk-DW45X6XT.mjs.map +1 -0
  12. package/dist/{chunk-FCPS2VGK.mjs → chunk-EXT2CSSJ.mjs} +683 -527
  13. package/dist/chunk-EXT2CSSJ.mjs.map +1 -0
  14. package/dist/{chunk-TQSSXYY5.mjs → chunk-HL2G36MT.mjs} +4 -62
  15. package/dist/chunk-HL2G36MT.mjs.map +1 -0
  16. package/dist/{chunk-GCDMRPDR.mjs → chunk-HWBCMKT2.mjs} +4 -4
  17. package/dist/{chunk-GCDMRPDR.mjs.map → chunk-HWBCMKT2.mjs.map} +1 -1
  18. package/dist/cost/index.mjs +3 -3
  19. package/dist/curation/index.d.ts +4 -4
  20. package/dist/curation/index.mjs +3 -3
  21. package/dist/{evaluate-CVzfLCd0.d.ts → evaluate-Df3GphJP.d.ts} +2 -2
  22. package/dist/{index-DSgqNd3Z.d.ts → index-C2XMLGDa.d.ts} +1 -1
  23. package/dist/{index-CgOxudo5.d.ts → index-D-sc36bL.d.ts} +3 -3
  24. package/dist/index.d.ts +7 -7
  25. package/dist/index.mjs +7 -6
  26. package/dist/index.mjs.map +1 -1
  27. package/dist/llm/index.d.ts +2 -2
  28. package/dist/llm/index.mjs +1 -1
  29. package/dist/overlay/index.d.ts +3 -3
  30. package/dist/picker/index.d.ts +6 -6
  31. package/dist/route-identity/index.d.ts +68 -14
  32. package/dist/route-identity/index.mjs +2842 -19
  33. package/dist/route-identity/index.mjs.map +1 -1
  34. package/dist/schema/index.d.ts +9 -2
  35. package/dist/schema/index.mjs +2 -1
  36. package/package.json +1 -1
  37. package/dist/chunk-FCPS2VGK.mjs.map +0 -1
  38. package/dist/chunk-TQSSXYY5.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cost/index.ts"],"names":["resolved","baseCostUsd","credits","calculatedCredits","markup"],"mappings":"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","file":"chunk-GCDMRPDR.mjs","sourcesContent":["/**\n * Cost dispatcher — computes credit cost + production USD cost for any\n * model id, regardless of kind. Single entry point used by orchestrator,\n * billing audits, and (eventually) the metered MCP gen layer.\n *\n * Per-kind formulas:\n * - LLM → reuses `calculateLLMCreditCost` (token math + cache + markup)\n * - Image → `creditCost × numOutputs`\n * - Video → `creditCost × multipliers[resolution|duration|mode]`\n * - Audio → `creditCost × (characters or seconds)` per `billingUnit`\n */\n\nimport {\n calculateLLMCreditCost,\n type LLMCreditCostResult,\n} from \"../llm/index.js\"\nimport { getModel } from \"../registry/index.js\"\nimport { computeCenticredits, pricingRegistry } from \"../pricing/index.js\"\n\n/**\n * Voice metadata → default audio model the dispatcher bills through.\n *\n * Voices are render-targets, not priced units. A MiniMax voice can be\n * played through `minimax/speech-02-hd` OR `…-turbo`; an ElevenLabs\n * voice through any of their model tiers. We default to the cheapest\n * model per provider so a drive-by voice-id call doesn't over-bill.\n * Callers wanting HD / premium-tier pricing should pass the audio\n * model id directly with the voice as metadata — see\n * `text-to-speech.tool.ts` for the canonical pattern.\n *\n * Add a new provider here when a new voice catalog lands (e.g.\n * `ELEVENLABS_VOICES` if/when we surface their voice IDs).\n */\nconst VOICE_PROVIDER_DEFAULT_MODEL: Record<string, string> = {\n minimax: \"minimax/speech-02-turbo\",\n elevenlabs: \"elevenlabs/flash-v2.5\",\n}\n\nexport type CostUsage =\n | {\n kind: \"llm\"\n inputTokens: number\n outputTokens: number\n cacheReadInputTokens?: number\n cacheCreationInputTokens?: number\n }\n | { kind: \"image\"; numOutputs?: number }\n | {\n kind: \"video\"\n resolution?: string\n duration?: number\n mode?: string\n }\n | { kind: \"audio\"; characters?: number; seconds?: number }\n\nexport interface CostResult {\n kind: \"llm\" | \"image\" | \"video\" | \"audio\"\n modelId: string\n /** Canonical model id after alias resolution (LLM only; same as modelId for media) */\n canonicalId: string\n /**\n * Total **centicredits** to charge (1 displayed credit = 100 cc).\n * Honors per-model overrides. Feed straight into the ledger — the\n * `credit_transactions.credits` column stores cc, so no `× 100`\n * conversion at the call site. Format for display with\n * `displayCredits(cc) → cr`.\n */\n credits: number\n /**\n * Centicredits the pure formula (provider cost × category markup)\n * would have charged, independent of any per-model override. Equal\n * to `credits` when no override is in play. Surfaced so\n * reconciliation can diff \"what we did\" vs \"what the formula said\"\n * without recomputing — persisted to `usage_events.calculated_credits`.\n */\n calculatedCredits: number\n /** Production cost in USD (provider-side, before markup) */\n baseCostUsd: number\n /** Per-kind breakdown — inputCredits/outputCredits for LLM, etc. All in cc. */\n breakdown: Record<string, number>\n /** True iff fallback pricing was used (currently LLM-only) */\n isFallback: boolean\n /** Markup applied (1.0 = catalog rate as-is) */\n markup: number\n}\n\nexport class UnknownModelError extends Error {\n constructor(public readonly modelId: string) {\n super(`Unknown model id: \"${modelId}\"`)\n this.name = \"UnknownModelError\"\n }\n}\n\nexport class CostUsageKindMismatchError extends Error {\n constructor(\n public readonly modelId: string,\n public readonly expected: string,\n public readonly got: string\n ) {\n super(\n `Model \"${modelId}\" is kind \"${expected}\", but received usage of kind \"${got}\"`\n )\n this.name = \"CostUsageKindMismatchError\"\n }\n}\n\nexport interface CalculateCostOptions {\n /**\n * App that's invoking the model. Routes per-app markup overrides\n * registered via `pricingRegistry.registerApp(appId, ...)`. When\n * omitted, core defaults apply.\n */\n appId?: string\n}\n\n/**\n * Computes credit + USD cost for a model run.\n *\n * Throws `UnknownModelError` for ids not in any catalog (LLM has its own\n * fallback path inside `calculateLLMCreditCost` — this surface preserves\n * that for back-compat).\n *\n * Throws `CostUsageKindMismatchError` if `usage.kind` doesn't match the\n * resolved model's kind (data integrity guard).\n *\n * Image / video / audio credits are derived at call time via the\n * pricing registry (`provider_cost × category-markup`). LLM keeps its\n * own per-model markup table inside `calculateLLMCreditCost` —\n * collapsing that follows in W6b.\n */\nexport function calculateCost(\n modelId: string,\n usage: CostUsage,\n opts: CalculateCostOptions = {}\n): CostResult {\n // LLM has a fallback path that returns valid pricing even for unknown\n // ids (preserves the orchestrator's existing tolerance). Other kinds\n // throw for unknowns.\n if (usage.kind === \"llm\") {\n const llmResult: LLMCreditCostResult = calculateLLMCreditCost(modelId, {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n cacheReadInputTokens: usage.cacheReadInputTokens,\n cacheCreationInputTokens: usage.cacheCreationInputTokens,\n })\n const resolved = getModel(modelId)\n const canonicalId =\n resolved && resolved.kind === \"llm\" ? resolved.canonicalId : modelId\n return {\n kind: \"llm\",\n modelId,\n canonicalId,\n credits: llmResult.credits,\n calculatedCredits: llmResult.calculatedCredits,\n baseCostUsd: llmResult.productionCost,\n breakdown: {\n inputCredits: llmResult.inputCredits,\n outputCredits: llmResult.outputCredits,\n cacheReadCredits: llmResult.cacheReadCredits,\n cacheWriteCredits: llmResult.cacheWriteCredits,\n },\n isFallback: llmResult.isFallback,\n markup: llmResult.markup,\n }\n }\n\n const resolved = getModel(modelId)\n if (!resolved) throw new UnknownModelError(modelId)\n // `voice` is structurally audio for billing purposes (MiniMax voice\n // metadata billed via per-character output). Accept `audio` usage on\n // voice models so the per-kind branches below can pattern-match.\n const expectedUsageKind: CostUsage[\"kind\"] =\n resolved.kind === \"voice\" ? \"audio\" : resolved.kind\n if (expectedUsageKind !== usage.kind) {\n // Pass `expectedUsageKind` (not `resolved.kind`) so the error message\n // accurately says \"audio\" rather than \"voice\" when a voice model is\n // billed — the caller must supply audio usage, not voice usage.\n throw new CostUsageKindMismatchError(modelId, expectedUsageKind, usage.kind)\n }\n\n if (resolved.kind === \"image\") {\n // `usage.kind` is \"image\" here (guarded above) but TS won't cross-narrow\n // it from `resolved.kind`, so check explicitly before reading numOutputs.\n const numOutputs = Math.max(\n 1,\n usage.kind === \"image\" ? (usage.numOutputs ?? 1) : 1\n )\n const baseCostUsd = resolved.def.pricing.baseCost * numOutputs\n const perOutputCredits = computeCenticredits({\n baseCostUsd: resolved.def.pricing.baseCost,\n category: \"image\",\n overrideCreditCost: resolved.def.pricing.overrideCreditCost,\n appId: opts.appId,\n })\n const credits = perOutputCredits * numOutputs\n // Formula-only (ignores override) — for `usage_events.calculated_credits`.\n const formulaPerOutput = computeCenticredits({\n baseCostUsd: resolved.def.pricing.baseCost,\n category: \"image\",\n appId: opts.appId,\n })\n const calculatedCredits = formulaPerOutput * numOutputs\n const markup = pricingRegistry.getMarkup(\"image\", opts.appId)\n return {\n kind: \"image\",\n modelId,\n canonicalId: modelId,\n credits,\n calculatedCredits,\n baseCostUsd,\n breakdown: {\n perOutputCredits,\n numOutputs,\n },\n isFallback: false,\n markup,\n }\n }\n\n if (resolved.kind === \"video\") {\n if (usage.kind !== \"video\") {\n throw new CostUsageKindMismatchError(modelId, \"video\", usage.kind)\n }\n const pricing = resolved.def.pricing\n // Provider-side multipliers — re-applied to BOTH the provider cost\n // (what we pay) AND the derived credit cost (so margin holds).\n const mult = pricing.multipliers\n const resMult =\n usage.resolution && mult?.resolution\n ? (mult.resolution[usage.resolution] ?? 1.0)\n : 1.0\n const durMult =\n usage.duration && mult?.duration\n ? (mult.duration[usage.duration] ?? 1.0)\n : 1.0\n const modMult =\n usage.mode && mult?.mode ? (mult.mode[usage.mode] ?? 1.0) : 1.0\n const variantMultiplier = resMult * durMult * modMult\n const baseCostUsd = pricing.baseCost * variantMultiplier\n const perClipCredits = computeCenticredits({\n baseCostUsd: pricing.baseCost,\n category: \"video\",\n overrideCreditCost: pricing.overrideCreditCost,\n appId: opts.appId,\n })\n const credits = Math.ceil(perClipCredits * variantMultiplier)\n const formulaPerClip = computeCenticredits({\n baseCostUsd: pricing.baseCost,\n category: \"video\",\n appId: opts.appId,\n })\n const calculatedCredits = Math.ceil(formulaPerClip * variantMultiplier)\n const markup = pricingRegistry.getMarkup(\"video\", opts.appId)\n return {\n kind: \"video\",\n modelId,\n canonicalId: modelId,\n credits,\n calculatedCredits,\n baseCostUsd,\n breakdown: {\n perClipCredits,\n resolutionMultiplier: resMult,\n durationMultiplier: durMult,\n modeMultiplier: modMult,\n variantMultiplier,\n },\n isFallback: false,\n markup,\n }\n }\n\n // Audio (and voice, delegated as audio — see expectedUsageKind above).\n if (usage.kind !== \"audio\") {\n throw new CostUsageKindMismatchError(modelId, \"audio\", usage.kind)\n }\n\n if (resolved.kind === \"voice\") {\n // Voice rows are metadata; delegate to the provider's default audio model.\n const provider = resolved.voice.provider\n const delegateModelId = VOICE_PROVIDER_DEFAULT_MODEL[provider]\n if (!delegateModelId) throw new UnknownModelError(modelId)\n const delegateResult = calculateCost(delegateModelId, usage, opts)\n return {\n ...delegateResult,\n modelId,\n canonicalId: delegateModelId,\n }\n }\n\n // Only `audio` remains (llm returned at top; image/video/voice handled\n // above). Narrow explicitly so `.def` is type-safe.\n if (resolved.kind !== \"audio\") throw new UnknownModelError(modelId)\n const audioPricing = resolved.def.pricing\n // Map the provider's billing unit to a quantity of billable units.\n // The catalog DATA uses `per_1k_chars` (chars ÷ 1000) and `per_minute`\n // (whole minutes, rounded UP to match provider invoicing). `per_character`\n // / `per_second` are handled too so a future data migration to those units\n // keeps working. NOTE: do not switch on the zod enum value alone — the\n // audio schema enum is stale (`per_character|per_second`) while the data\n // still ships `per_1k_chars|per_minute`; trusting the enum bills 0.\n const billingUnit = audioPricing.billingUnit as string\n let quantity: number\n switch (billingUnit) {\n case \"per_1k_chars\":\n quantity = Math.max(0, usage.characters ?? 0) / 1000\n break\n case \"per_character\":\n quantity = Math.max(0, usage.characters ?? 0)\n break\n case \"per_minute\":\n quantity = Math.ceil(Math.max(0, usage.seconds ?? 0) / 60)\n break\n case \"per_second\":\n default:\n quantity = Math.max(0, usage.seconds ?? 0)\n break\n }\n const baseCostUsd = audioPricing.baseCost * quantity\n const perUnitCredits = computeCenticredits({\n baseCostUsd: audioPricing.baseCost,\n category: \"audio\",\n overrideCreditCost: audioPricing.overrideCreditCost,\n appId: opts.appId,\n })\n // Per-call floor (1 cc) so a non-empty call never rounds to 0; a genuinely\n // empty call (quantity 0, e.g. empty-string TTS) bills nothing.\n const credits =\n quantity > 0 ? Math.max(1, Math.ceil(perUnitCredits * quantity)) : 0\n const formulaPerUnit = computeCenticredits({\n baseCostUsd: audioPricing.baseCost,\n category: \"audio\",\n appId: opts.appId,\n })\n const calculatedCredits =\n quantity > 0 ? Math.max(1, Math.ceil(formulaPerUnit * quantity)) : 0\n const markup = pricingRegistry.getMarkup(\"audio\", opts.appId)\n return {\n kind: \"audio\",\n modelId,\n canonicalId: modelId,\n credits,\n calculatedCredits,\n baseCostUsd,\n breakdown: {\n perUnitCredits,\n quantity,\n },\n isFallback: false,\n markup,\n }\n}\n\n// Thin ergonomic wrappers around `calculateCost`. Two reasons they exist:\n// 1. Callers with a known kind don't want to construct the full union.\n// 2. The kind/usage union is a `calculateCost` implementation detail —\n// wrapper types are narrower and easier to read at call sites.\n\nexport function calculateLLMCost(\n modelId: string,\n usage: {\n inputTokens: number\n outputTokens: number\n cacheReadInputTokens?: number\n cacheCreationInputTokens?: number\n },\n opts?: CalculateCostOptions\n): CostResult {\n return calculateCost(modelId, { kind: \"llm\", ...usage }, opts)\n}\n\nexport function calculateImageCost(\n modelId: string,\n usage: { numOutputs?: number },\n opts?: CalculateCostOptions\n): CostResult {\n return calculateCost(modelId, { kind: \"image\", ...usage }, opts)\n}\n\nexport function calculateVideoCost(\n modelId: string,\n usage: { resolution?: string; duration?: number; mode?: string },\n opts?: CalculateCostOptions\n): CostResult {\n return calculateCost(modelId, { kind: \"video\", ...usage }, opts)\n}\n\nexport function calculateAudioCost(\n modelId: string,\n usage: { characters?: number; seconds?: number },\n opts?: CalculateCostOptions\n): CostResult {\n return calculateCost(modelId, { kind: \"audio\", ...usage }, opts)\n}\n"]}
1
+ {"version":3,"sources":["../src/cost/index.ts"],"names":["resolved","baseCostUsd","credits","calculatedCredits","markup"],"mappings":"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","file":"chunk-HWBCMKT2.mjs","sourcesContent":["/**\n * Cost dispatcher — computes credit cost + production USD cost for any\n * model id, regardless of kind. Single entry point used by orchestrator,\n * billing audits, and (eventually) the metered MCP gen layer.\n *\n * Per-kind formulas:\n * - LLM → reuses `calculateLLMCreditCost` (token math + cache + markup)\n * - Image → `creditCost × numOutputs`\n * - Video → `creditCost × multipliers[resolution|duration|mode]`\n * - Audio → `creditCost × (characters or seconds)` per `billingUnit`\n */\n\nimport {\n calculateLLMCreditCost,\n type LLMCreditCostResult,\n} from \"../llm/index.js\"\nimport { getModel } from \"../registry/index.js\"\nimport { computeCenticredits, pricingRegistry } from \"../pricing/index.js\"\n\n/**\n * Voice metadata → default audio model the dispatcher bills through.\n *\n * Voices are render-targets, not priced units. A MiniMax voice can be\n * played through `minimax/speech-02-hd` OR `…-turbo`; an ElevenLabs\n * voice through any of their model tiers. We default to the cheapest\n * model per provider so a drive-by voice-id call doesn't over-bill.\n * Callers wanting HD / premium-tier pricing should pass the audio\n * model id directly with the voice as metadata — see\n * `text-to-speech.tool.ts` for the canonical pattern.\n *\n * Add a new provider here when a new voice catalog lands (e.g.\n * `ELEVENLABS_VOICES` if/when we surface their voice IDs).\n */\nconst VOICE_PROVIDER_DEFAULT_MODEL: Record<string, string> = {\n minimax: \"minimax/speech-02-turbo\",\n elevenlabs: \"elevenlabs/flash-v2.5\",\n}\n\nexport type CostUsage =\n | {\n kind: \"llm\"\n inputTokens: number\n outputTokens: number\n cacheReadInputTokens?: number\n cacheCreationInputTokens?: number\n }\n | { kind: \"image\"; numOutputs?: number }\n | {\n kind: \"video\"\n resolution?: string\n duration?: number\n mode?: string\n }\n | { kind: \"audio\"; characters?: number; seconds?: number }\n\nexport interface CostResult {\n kind: \"llm\" | \"image\" | \"video\" | \"audio\"\n modelId: string\n /** Canonical model id after alias resolution (LLM only; same as modelId for media) */\n canonicalId: string\n /**\n * Total **centicredits** to charge (1 displayed credit = 100 cc).\n * Honors per-model overrides. Feed straight into the ledger — the\n * `credit_transactions.credits` column stores cc, so no `× 100`\n * conversion at the call site. Format for display with\n * `displayCredits(cc) → cr`.\n */\n credits: number\n /**\n * Centicredits the pure formula (provider cost × category markup)\n * would have charged, independent of any per-model override. Equal\n * to `credits` when no override is in play. Surfaced so\n * reconciliation can diff \"what we did\" vs \"what the formula said\"\n * without recomputing — persisted to `usage_events.calculated_credits`.\n */\n calculatedCredits: number\n /** Production cost in USD (provider-side, before markup) */\n baseCostUsd: number\n /** Per-kind breakdown — inputCredits/outputCredits for LLM, etc. All in cc. */\n breakdown: Record<string, number>\n /** True iff fallback pricing was used (currently LLM-only) */\n isFallback: boolean\n /** Markup applied (1.0 = catalog rate as-is) */\n markup: number\n}\n\nexport class UnknownModelError extends Error {\n constructor(public readonly modelId: string) {\n super(`Unknown model id: \"${modelId}\"`)\n this.name = \"UnknownModelError\"\n }\n}\n\nexport class CostUsageKindMismatchError extends Error {\n constructor(\n public readonly modelId: string,\n public readonly expected: string,\n public readonly got: string\n ) {\n super(\n `Model \"${modelId}\" is kind \"${expected}\", but received usage of kind \"${got}\"`\n )\n this.name = \"CostUsageKindMismatchError\"\n }\n}\n\nexport interface CalculateCostOptions {\n /**\n * App that's invoking the model. Routes per-app markup overrides\n * registered via `pricingRegistry.registerApp(appId, ...)`. When\n * omitted, core defaults apply.\n */\n appId?: string\n}\n\n/**\n * Computes credit + USD cost for a model run.\n *\n * Throws `UnknownModelError` for ids not in any catalog (LLM has its own\n * fallback path inside `calculateLLMCreditCost` — this surface preserves\n * that for back-compat).\n *\n * Throws `CostUsageKindMismatchError` if `usage.kind` doesn't match the\n * resolved model's kind (data integrity guard).\n *\n * Image / video / audio credits are derived at call time via the\n * pricing registry (`provider_cost × category-markup`). LLM keeps its\n * own per-model markup table inside `calculateLLMCreditCost` —\n * collapsing that follows in W6b.\n */\nexport function calculateCost(\n modelId: string,\n usage: CostUsage,\n opts: CalculateCostOptions = {}\n): CostResult {\n // LLM has a fallback path that returns valid pricing even for unknown\n // ids (preserves the orchestrator's existing tolerance). Other kinds\n // throw for unknowns.\n if (usage.kind === \"llm\") {\n const llmResult: LLMCreditCostResult = calculateLLMCreditCost(modelId, {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n cacheReadInputTokens: usage.cacheReadInputTokens,\n cacheCreationInputTokens: usage.cacheCreationInputTokens,\n })\n const resolved = getModel(modelId)\n const canonicalId =\n resolved && resolved.kind === \"llm\" ? resolved.canonicalId : modelId\n return {\n kind: \"llm\",\n modelId,\n canonicalId,\n credits: llmResult.credits,\n calculatedCredits: llmResult.calculatedCredits,\n baseCostUsd: llmResult.productionCost,\n breakdown: {\n inputCredits: llmResult.inputCredits,\n outputCredits: llmResult.outputCredits,\n cacheReadCredits: llmResult.cacheReadCredits,\n cacheWriteCredits: llmResult.cacheWriteCredits,\n },\n isFallback: llmResult.isFallback,\n markup: llmResult.markup,\n }\n }\n\n const resolved = getModel(modelId)\n if (!resolved) throw new UnknownModelError(modelId)\n // `voice` is structurally audio for billing purposes (MiniMax voice\n // metadata billed via per-character output). Accept `audio` usage on\n // voice models so the per-kind branches below can pattern-match.\n const expectedUsageKind: CostUsage[\"kind\"] =\n resolved.kind === \"voice\" ? \"audio\" : resolved.kind\n if (expectedUsageKind !== usage.kind) {\n // Pass `expectedUsageKind` (not `resolved.kind`) so the error message\n // accurately says \"audio\" rather than \"voice\" when a voice model is\n // billed — the caller must supply audio usage, not voice usage.\n throw new CostUsageKindMismatchError(modelId, expectedUsageKind, usage.kind)\n }\n\n if (resolved.kind === \"image\") {\n // `usage.kind` is \"image\" here (guarded above) but TS won't cross-narrow\n // it from `resolved.kind`, so check explicitly before reading numOutputs.\n const numOutputs = Math.max(\n 1,\n usage.kind === \"image\" ? (usage.numOutputs ?? 1) : 1\n )\n const baseCostUsd = resolved.def.pricing.baseCost * numOutputs\n const perOutputCredits = computeCenticredits({\n baseCostUsd: resolved.def.pricing.baseCost,\n category: \"image\",\n overrideCreditCost: resolved.def.pricing.overrideCreditCost,\n appId: opts.appId,\n })\n const credits = perOutputCredits * numOutputs\n // Formula-only (ignores override) — for `usage_events.calculated_credits`.\n const formulaPerOutput = computeCenticredits({\n baseCostUsd: resolved.def.pricing.baseCost,\n category: \"image\",\n appId: opts.appId,\n })\n const calculatedCredits = formulaPerOutput * numOutputs\n const markup = pricingRegistry.getMarkup(\"image\", opts.appId)\n return {\n kind: \"image\",\n modelId,\n canonicalId: modelId,\n credits,\n calculatedCredits,\n baseCostUsd,\n breakdown: {\n perOutputCredits,\n numOutputs,\n },\n isFallback: false,\n markup,\n }\n }\n\n if (resolved.kind === \"video\") {\n if (usage.kind !== \"video\") {\n throw new CostUsageKindMismatchError(modelId, \"video\", usage.kind)\n }\n const pricing = resolved.def.pricing\n // Provider-side multipliers — re-applied to BOTH the provider cost\n // (what we pay) AND the derived credit cost (so margin holds).\n const mult = pricing.multipliers\n const resMult =\n usage.resolution && mult?.resolution\n ? (mult.resolution[usage.resolution] ?? 1.0)\n : 1.0\n const durMult =\n usage.duration && mult?.duration\n ? (mult.duration[usage.duration] ?? 1.0)\n : 1.0\n const modMult =\n usage.mode && mult?.mode ? (mult.mode[usage.mode] ?? 1.0) : 1.0\n const variantMultiplier = resMult * durMult * modMult\n const baseCostUsd = pricing.baseCost * variantMultiplier\n const perClipCredits = computeCenticredits({\n baseCostUsd: pricing.baseCost,\n category: \"video\",\n overrideCreditCost: pricing.overrideCreditCost,\n appId: opts.appId,\n })\n const credits = Math.ceil(perClipCredits * variantMultiplier)\n const formulaPerClip = computeCenticredits({\n baseCostUsd: pricing.baseCost,\n category: \"video\",\n appId: opts.appId,\n })\n const calculatedCredits = Math.ceil(formulaPerClip * variantMultiplier)\n const markup = pricingRegistry.getMarkup(\"video\", opts.appId)\n return {\n kind: \"video\",\n modelId,\n canonicalId: modelId,\n credits,\n calculatedCredits,\n baseCostUsd,\n breakdown: {\n perClipCredits,\n resolutionMultiplier: resMult,\n durationMultiplier: durMult,\n modeMultiplier: modMult,\n variantMultiplier,\n },\n isFallback: false,\n markup,\n }\n }\n\n // Audio (and voice, delegated as audio — see expectedUsageKind above).\n if (usage.kind !== \"audio\") {\n throw new CostUsageKindMismatchError(modelId, \"audio\", usage.kind)\n }\n\n if (resolved.kind === \"voice\") {\n // Voice rows are metadata; delegate to the provider's default audio model.\n const provider = resolved.voice.provider\n const delegateModelId = VOICE_PROVIDER_DEFAULT_MODEL[provider]\n if (!delegateModelId) throw new UnknownModelError(modelId)\n const delegateResult = calculateCost(delegateModelId, usage, opts)\n return {\n ...delegateResult,\n modelId,\n canonicalId: delegateModelId,\n }\n }\n\n // Only `audio` remains (llm returned at top; image/video/voice handled\n // above). Narrow explicitly so `.def` is type-safe.\n if (resolved.kind !== \"audio\") throw new UnknownModelError(modelId)\n const audioPricing = resolved.def.pricing\n // Map the provider's billing unit to a quantity of billable units.\n // The catalog DATA uses `per_1k_chars` (chars ÷ 1000) and `per_minute`\n // (whole minutes, rounded UP to match provider invoicing). `per_character`\n // / `per_second` are handled too so a future data migration to those units\n // keeps working. NOTE: do not switch on the zod enum value alone — the\n // audio schema enum is stale (`per_character|per_second`) while the data\n // still ships `per_1k_chars|per_minute`; trusting the enum bills 0.\n const billingUnit = audioPricing.billingUnit as string\n let quantity: number\n switch (billingUnit) {\n case \"per_1k_chars\":\n quantity = Math.max(0, usage.characters ?? 0) / 1000\n break\n case \"per_character\":\n quantity = Math.max(0, usage.characters ?? 0)\n break\n case \"per_minute\":\n quantity = Math.ceil(Math.max(0, usage.seconds ?? 0) / 60)\n break\n case \"per_second\":\n default:\n quantity = Math.max(0, usage.seconds ?? 0)\n break\n }\n const baseCostUsd = audioPricing.baseCost * quantity\n const perUnitCredits = computeCenticredits({\n baseCostUsd: audioPricing.baseCost,\n category: \"audio\",\n overrideCreditCost: audioPricing.overrideCreditCost,\n appId: opts.appId,\n })\n // Per-call floor (1 cc) so a non-empty call never rounds to 0; a genuinely\n // empty call (quantity 0, e.g. empty-string TTS) bills nothing.\n const credits =\n quantity > 0 ? Math.max(1, Math.ceil(perUnitCredits * quantity)) : 0\n const formulaPerUnit = computeCenticredits({\n baseCostUsd: audioPricing.baseCost,\n category: \"audio\",\n appId: opts.appId,\n })\n const calculatedCredits =\n quantity > 0 ? Math.max(1, Math.ceil(formulaPerUnit * quantity)) : 0\n const markup = pricingRegistry.getMarkup(\"audio\", opts.appId)\n return {\n kind: \"audio\",\n modelId,\n canonicalId: modelId,\n credits,\n calculatedCredits,\n baseCostUsd,\n breakdown: {\n perUnitCredits,\n quantity,\n },\n isFallback: false,\n markup,\n }\n}\n\n// Thin ergonomic wrappers around `calculateCost`. Two reasons they exist:\n// 1. Callers with a known kind don't want to construct the full union.\n// 2. The kind/usage union is a `calculateCost` implementation detail —\n// wrapper types are narrower and easier to read at call sites.\n\nexport function calculateLLMCost(\n modelId: string,\n usage: {\n inputTokens: number\n outputTokens: number\n cacheReadInputTokens?: number\n cacheCreationInputTokens?: number\n },\n opts?: CalculateCostOptions\n): CostResult {\n return calculateCost(modelId, { kind: \"llm\", ...usage }, opts)\n}\n\nexport function calculateImageCost(\n modelId: string,\n usage: { numOutputs?: number },\n opts?: CalculateCostOptions\n): CostResult {\n return calculateCost(modelId, { kind: \"image\", ...usage }, opts)\n}\n\nexport function calculateVideoCost(\n modelId: string,\n usage: { resolution?: string; duration?: number; mode?: string },\n opts?: CalculateCostOptions\n): CostResult {\n return calculateCost(modelId, { kind: \"video\", ...usage }, opts)\n}\n\nexport function calculateAudioCost(\n modelId: string,\n usage: { characters?: number; seconds?: number },\n opts?: CalculateCostOptions\n): CostResult {\n return calculateCost(modelId, { kind: \"audio\", ...usage }, opts)\n}\n"]}
@@ -1,9 +1,9 @@
1
- export { CostUsageKindMismatchError, UnknownModelError, calculateAudioCost, calculateCost, calculateImageCost, calculateLLMCost, calculateVideoCost } from '../chunk-GCDMRPDR.mjs';
2
- import '../chunk-S74S3Q7Z.mjs';
1
+ export { CostUsageKindMismatchError, UnknownModelError, calculateAudioCost, calculateCost, calculateImageCost, calculateLLMCost, calculateVideoCost } from '../chunk-HWBCMKT2.mjs';
2
+ import '../chunk-34LOJCOZ.mjs';
3
3
  import '../chunk-WTHHXXIK.mjs';
4
4
  import '../chunk-H6JUTF3U.mjs';
5
5
  import '../chunk-O7TXHU5W.mjs';
6
- import '../chunk-FCPS2VGK.mjs';
6
+ import '../chunk-EXT2CSSJ.mjs';
7
7
  import '../chunk-QHELXPSL.mjs';
8
8
  import '../chunk-2LWYZOWB.mjs';
9
9
  import '../chunk-IJZ4XPO2.mjs';
@@ -1,12 +1,12 @@
1
- import { C as CatalogKind, R as ResolvedModel } from '../index-DSgqNd3Z.js';
1
+ import { C as CatalogKind, R as ResolvedModel } from '../index-C2XMLGDa.js';
2
2
  import { CatalogVoice } from '../schema/voice.js';
3
- import '../catalog-BPDMuxzf.js';
4
- import '../base-C4kz9Dxc.js';
3
+ import '../catalog-CLQ-Bo1n.js';
4
+ import '../base-B8IIoaqg.js';
5
5
  import 'zod';
6
6
  import '../image/index.js';
7
7
  import '../video/index.js';
8
8
  import '../audio/index.js';
9
- import '../audio-BbeLA_4x.js';
9
+ import '../audio-DR0g_ZH_.js';
10
10
 
11
11
  /**
12
12
  * Curation — what an app SURFACES from the catalog, distinct from
@@ -1,9 +1,9 @@
1
- export { applyProfile, expandProviders, filterVoicesByProviders, getProviderGroup, getSurfaceProfile, groupForProvider, listProviderGroups, listSurfaceProfiles, listSurfaced, modelMatchesProfile } from '../chunk-VIVKDMAT.mjs';
2
- import '../chunk-S74S3Q7Z.mjs';
1
+ export { applyProfile, expandProviders, filterVoicesByProviders, getProviderGroup, getSurfaceProfile, groupForProvider, listProviderGroups, listSurfaceProfiles, listSurfaced, modelMatchesProfile } from '../chunk-DUAH5LWG.mjs';
2
+ import '../chunk-34LOJCOZ.mjs';
3
3
  import '../chunk-WTHHXXIK.mjs';
4
4
  import '../chunk-H6JUTF3U.mjs';
5
5
  import '../chunk-O7TXHU5W.mjs';
6
- import '../chunk-FCPS2VGK.mjs';
6
+ import '../chunk-EXT2CSSJ.mjs';
7
7
  import '../chunk-QHELXPSL.mjs';
8
8
  import '../chunk-2LWYZOWB.mjs';
9
9
  import '../chunk-IJZ4XPO2.mjs';
@@ -1,5 +1,5 @@
1
- import { R as ResolvedModel } from './index-DSgqNd3Z.js';
2
- import { M as ModelKind } from './base-C4kz9Dxc.js';
1
+ import { R as ResolvedModel } from './index-C2XMLGDa.js';
2
+ import { M as ModelKind } from './base-B8IIoaqg.js';
3
3
 
4
4
  /**
5
5
  * Access control types — workspace-override rules + app scope.
@@ -1,4 +1,4 @@
1
- import { c as LLMPricing } from './catalog-BPDMuxzf.js';
1
+ import { c as LLMPricing } from './catalog-CLQ-Bo1n.js';
2
2
  import { ImageModelDefinition } from './image/index.js';
3
3
  import { VideoModelDefinition } from './video/index.js';
4
4
  import { AudioModelDefinition } from './audio/index.js';
@@ -1,6 +1,6 @@
1
- import { A as AccessDecision } from './evaluate-CVzfLCd0.js';
2
- import { C as CatalogPriceTier, L as Lifecycle, M as ModelKind } from './base-C4kz9Dxc.js';
3
- import { R as ResolvedModel } from './index-DSgqNd3Z.js';
1
+ import { A as AccessDecision } from './evaluate-Df3GphJP.js';
2
+ import { C as CatalogPriceTier, L as Lifecycle, M as ModelKind } from './base-B8IIoaqg.js';
3
+ import { R as ResolvedModel } from './index-C2XMLGDa.js';
4
4
 
5
5
  /**
6
6
  * Model enrichment — `catalogPriceTier` / `tags` / `lifecycle` / `actions`
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { ImageAspectRatio, ImageAspectRatioSchema, ImageCapabilities, ImageCapabilitiesSchema, ImageEntry, ImageEntrySchema, ImagePricing, ImagePricingSchema, ImageReferenceImages, ImageReferenceImagesSchema, LLMEntry, LLMEntrySchema, LlmPricing, LlmPricingSchema, ModelEntry, ModelEntrySchema, VideoCapabilities, VideoCapabilitiesSchema, VideoCostMultipliers, VideoCostMultipliersSchema, VideoEntry, VideoEntrySchema, VideoPricing, VideoPricingSchema, VideoResolution, VideoResolutionSchema } from './schema/index.js';
2
- export { D as DEFAULT_PRICING, L as LLMCreditCostResult, c as LLMPricing, d as LLMUsageBreakdown, e as LLM_PRICING_CATALOG, M as MODEL_ALIASES, i as calculateLLMCreditCost, n as resolvePricing } from './catalog-BPDMuxzf.js';
2
+ export { D as DEFAULT_PRICING, L as LLMCreditCostResult, c as LLMPricing, d as LLMUsageBreakdown, e as LLM_PRICING_CATALOG, M as MODEL_ALIASES, i as calculateLLMCreditCost, n as resolvePricing } from './catalog-CLQ-Bo1n.js';
3
3
  export { AGENT_EDITABLE_MODEL_IDS, AGENT_GENERATIVE_MODEL_IDS, AGENT_IMAGE_MODEL_IDS, IMAGE_MODEL_CATALOG, IMAGE_MODEL_IDS, ImageModelDefinition, generateImageModelTable } from './image/index.js';
4
4
  export { AGENT_VIDEO_MODEL_IDS, VIDEO_MODEL_CATALOG, VIDEO_MODEL_IDS, VideoModelDefinition, generateVideoModelTable } from './video/index.js';
5
5
  export { AGENT_AUDIO_MODEL_IDS, AGENT_STT_MODEL_IDS, AGENT_TTS_MODEL_IDS, AUDIO_MODEL_CATALOG, AUDIO_MODEL_IDS, AudioBillingUnit, AudioModality, AudioModelDefinition, AudioProvider, DEFAULT_GEMINI_LIVE_MODEL, GEMINI_LIVE_MODEL_IDS, S2S_MODEL_IDS, generateAudioModelTable, isAcceptedGeminiLiveModel } from './audio/index.js';
@@ -9,14 +9,14 @@ export { ProviderGroup, SurfaceProfile, applyProfile, expandProviders, filterVoi
9
9
  export { CC_USD_RATE, CREDIT_USD_RATE, DEFAULT_PRICING_FLOORS, DEFAULT_PRICING_MARKUP, PricingCategory, PricingMarkup, computeCenticredits, pricingRegistry } from './pricing/index.js';
10
10
  export { CalculateCostOptions, CostResult, CostUsage, CostUsageKindMismatchError, UnknownModelError, calculateAudioCost, calculateCost, calculateImageCost, calculateLLMCost, calculateVideoCost } from './cost/index.js';
11
11
  export { ShouldDebitDecision, ShouldDebitInput, shouldDebit } from './byok/index.js';
12
- export { A as AccessDecision, a as AccessEffect, b as AccessEvalInput, c as AccessRule, d as AccessTarget, e as AppScope, f as evaluateAccess } from './evaluate-CVzfLCd0.js';
12
+ export { A as AccessDecision, a as AccessEffect, b as AccessEvalInput, c as AccessRule, d as AccessTarget, e as AppScope, f as evaluateAccess } from './evaluate-Df3GphJP.js';
13
13
  export { CatalogDefaultDecision, evaluateCatalogDefaults } from './access/index.js';
14
14
  export { CatalogOverlay, MergedOverlay, clearCatalogOverlays, getMergedOverlay, registerCatalogOverlay } from './overlay/index.js';
15
- import { R as ResolvedModel } from './index-DSgqNd3Z.js';
16
- export { C as CatalogKind, L as ListModelsFilter, g as getModel, a as getModelsByProvider, b as getStaticModelProvider, i as isAgentVisible, l as listModels, r as resolveAlias } from './index-DSgqNd3Z.js';
17
- export { A as AvailableConnector, a as AvailableModel, b as AvailableModelCapabilities, c as AvailableModelsActor, d as AvailableModelsResponse, L as ListAvailableModelsParams, M as ModelEnrichment, g as getEnrichment, m as modelHasAction, e as modelHasTag, f as modelMatchesCatalogPriceTier, h as modelMatchesKind, i as modelMatchesPriceTier, p as priceTierForModel } from './index-CgOxudo5.js';
18
- export { A as AudioCapabilities, a as AudioCapabilitiesSchema, b as AudioEntry, c as AudioEntrySchema, d as AudioPricing, e as AudioPricingSchema } from './audio-BbeLA_4x.js';
19
- export { C as CatalogPriceTier, a as CatalogPriceTierSchema, b as CatalogProvider, c as CatalogProviderSchema, L as Lifecycle, d as LifecycleSchema, M as ModelKind, e as ModelKindSchema, N as NsfwPolicy, f as NsfwPolicySchema, P as PROVIDER_KEY_ENV, g as PROVIDER_KEY_ENV_ALIASES, h as baseEntryShape } from './base-C4kz9Dxc.js';
15
+ import { R as ResolvedModel } from './index-C2XMLGDa.js';
16
+ export { C as CatalogKind, L as ListModelsFilter, g as getModel, a as getModelsByProvider, b as getStaticModelProvider, i as isAgentVisible, l as listModels, r as resolveAlias } from './index-C2XMLGDa.js';
17
+ export { A as AvailableConnector, a as AvailableModel, b as AvailableModelCapabilities, c as AvailableModelsActor, d as AvailableModelsResponse, L as ListAvailableModelsParams, M as ModelEnrichment, g as getEnrichment, m as modelHasAction, e as modelHasTag, f as modelMatchesCatalogPriceTier, h as modelMatchesKind, i as modelMatchesPriceTier, p as priceTierForModel } from './index-D-sc36bL.js';
18
+ export { A as AudioCapabilities, a as AudioCapabilitiesSchema, b as AudioEntry, c as AudioEntrySchema, d as AudioPricing, e as AudioPricingSchema } from './audio-DR0g_ZH_.js';
19
+ export { C as CatalogPriceTier, a as CatalogPriceTierSchema, b as CatalogProvider, c as CatalogProviderSchema, L as Lifecycle, d as LifecycleSchema, M as ModelKind, e as ModelKindSchema, N as NsfwPolicy, f as NsfwPolicySchema, P as PROVIDER_KEY_ENV, g as PROVIDER_KEY_ENV_ALIASES, h as baseEntryShape } from './base-B8IIoaqg.js';
20
20
  import 'zod';
21
21
 
22
22
  /**
package/dist/index.mjs CHANGED
@@ -1,15 +1,16 @@
1
- export { applyProfile, expandProviders, filterVoicesByProviders, getProviderGroup, getSurfaceProfile, groupForProvider, listProviderGroups, listSurfaceProfiles, listSurfaced, modelMatchesProfile } from './chunk-VIVKDMAT.mjs';
2
- export { CostUsageKindMismatchError, UnknownModelError, calculateAudioCost, calculateCost, calculateImageCost, calculateLLMCost, calculateVideoCost } from './chunk-GCDMRPDR.mjs';
3
- import { getModel } from './chunk-S74S3Q7Z.mjs';
4
- export { getModel, getModelsByProvider, getStaticModelProvider, isAgentVisible, listModels, resolveAlias } from './chunk-S74S3Q7Z.mjs';
1
+ export { applyProfile, expandProviders, filterVoicesByProviders, getProviderGroup, getSurfaceProfile, groupForProvider, listProviderGroups, listSurfaceProfiles, listSurfaced, modelMatchesProfile } from './chunk-DUAH5LWG.mjs';
2
+ export { CostUsageKindMismatchError, UnknownModelError, calculateAudioCost, calculateCost, calculateImageCost, calculateLLMCost, calculateVideoCost } from './chunk-HWBCMKT2.mjs';
3
+ import { getModel } from './chunk-34LOJCOZ.mjs';
4
+ export { getModel, getModelsByProvider, getStaticModelProvider, isAgentVisible, listModels, resolveAlias } from './chunk-34LOJCOZ.mjs';
5
5
  export { shouldDebit } from './chunk-XFDXTFV3.mjs';
6
6
  export { evaluateAccess, evaluateCatalogDefaults } from './chunk-HRRG2RZO.mjs';
7
7
  import { priceTierForModel } from './chunk-WTHHXXIK.mjs';
8
8
  export { assertReservedPrefixDiscipline, getActions, getEnrichment, isActionTag, modelHasAction, modelHasTag, modelMatchesCatalogPriceTier, modelMatchesKind, modelMatchesPriceTier, priceTierForModel } from './chunk-WTHHXXIK.mjs';
9
9
  export { clearCatalogOverlays, getMergedOverlay, registerCatalogOverlay } from './chunk-H6JUTF3U.mjs';
10
- export { AudioCapabilitiesSchema, AudioEntrySchema, AudioPricingSchema, CatalogPriceTierSchema, CatalogProviderSchema, ImageAspectRatioSchema, ImageCapabilitiesSchema, ImageEntrySchema, ImagePricingSchema, ImageReferenceImagesSchema, LLMEntrySchema, LifecycleSchema, LlmPricingSchema, ModelEntrySchema, ModelKindSchema, NsfwPolicySchema, PROVIDER_KEY_ENV, PROVIDER_KEY_ENV_ALIASES, VideoCapabilitiesSchema, VideoCostMultipliersSchema, VideoEntrySchema, VideoPricingSchema, VideoResolutionSchema, baseEntryShape } from './chunk-TQSSXYY5.mjs';
10
+ export { AudioCapabilitiesSchema, AudioEntrySchema, AudioPricingSchema, ImageAspectRatioSchema, ImageCapabilitiesSchema, ImageEntrySchema, ImagePricingSchema, ImageReferenceImagesSchema, LLMEntrySchema, LlmPricingSchema, ModelEntrySchema, VideoCapabilitiesSchema, VideoCostMultipliersSchema, VideoEntrySchema, VideoPricingSchema, VideoResolutionSchema } from './chunk-HL2G36MT.mjs';
11
+ export { CatalogPriceTierSchema, CatalogProviderSchema, LifecycleSchema, ModelKindSchema, NsfwPolicySchema, PROVIDER_KEY_ENV, PROVIDER_KEY_ENV_ALIASES, baseEntryShape } from './chunk-DW45X6XT.mjs';
11
12
  import './chunk-O7TXHU5W.mjs';
12
- export { DEFAULT_PRICING, LLM_PRICING_CATALOG, MODEL_ALIASES, calculateLLMCreditCost, resolvePricing } from './chunk-FCPS2VGK.mjs';
13
+ export { DEFAULT_PRICING, LLM_PRICING_CATALOG, MODEL_ALIASES, calculateLLMCreditCost, resolvePricing } from './chunk-EXT2CSSJ.mjs';
13
14
  export { CC_USD_RATE, CREDIT_USD_RATE, DEFAULT_PRICING_FLOORS, DEFAULT_PRICING_MARKUP, computeCenticredits, pricingRegistry } from './chunk-QHELXPSL.mjs';
14
15
  export { AGENT_EDITABLE_MODEL_IDS, AGENT_GENERATIVE_MODEL_IDS, AGENT_IMAGE_MODEL_IDS, IMAGE_MODEL_CATALOG, IMAGE_MODEL_IDS, generateImageModelTable } from './chunk-2LWYZOWB.mjs';
15
16
  export { AGENT_VIDEO_MODEL_IDS, VIDEO_MODEL_CATALOG, VIDEO_MODEL_IDS, generateVideoModelTable } from './chunk-IJZ4XPO2.mjs';
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAoEO,SAAS,oBAAoB,EAAA,EAAoB;AACtD,EAAA,MAAM,KAAA,GAAQ,SAAS,EAAE,CAAA;AACzB,EAAA,OAAO,KAAA,GAAQ,iBAAA,CAA0B,KAAK,CAAA,GAAI,CAAA;AACpD","file":"index.mjs","sourcesContent":["/**\n * @agentproto/model-catalog — unified model catalog.\n *\n * Single source of truth for LLM, image, video, audio, and voice model\n * entries. Owns cost dispatch, BYOK policy, and access control evaluation.\n * Zod-only OSS core; @agentproto/model-catalog layers billing/access/BYOK\n * policy on top.\n *\n * Subpath imports for tree-shaking:\n * import { LLM_PRICING_CATALOG } from \"@agentproto/model-catalog/llm\"\n * import { calculateCost } from \"@agentproto/model-catalog/cost\"\n * import { shouldDebit } from \"@agentproto/model-catalog/byok\"\n * import { evaluateAccess } from \"@agentproto/model-catalog/access\"\n * import { VOICE_CATALOG } from \"@agentproto/model-catalog/voice\"\n * import { listSurfaced } from \"@agentproto/model-catalog/curation\"\n */\n\nexport * from \"./schema/index.js\"\n// LLM has its own `resolveAlias` (legacy back-compat for the app legacy pricing module).\n// At the top level we prefer the cross-kind `resolveAlias` from the registry.\nexport {\n LLM_PRICING_CATALOG,\n MODEL_ALIASES,\n DEFAULT_PRICING,\n resolvePricing,\n calculateLLMCreditCost,\n} from \"./llm/index.js\"\nexport type {\n LLMPricing,\n LLMUsageBreakdown,\n LLMCreditCostResult,\n} from \"./llm/index.js\"\nexport * from \"./image/index.js\"\nexport * from \"./video/index.js\"\nexport * from \"./audio/index.js\"\nexport * from \"./voice/index.js\"\nexport * from \"./curation/index.js\"\nexport * from \"./pricing/index.js\"\nexport * from \"./cost/index.js\"\nexport * from \"./byok/index.js\"\nexport * from \"./access/index.js\"\nexport * from \"./overlay/index.js\"\nexport * from \"./registry/index.js\"\nexport {\n getActions,\n isActionTag,\n assertReservedPrefixDiscipline,\n} from \"./registry/actions.js\"\nexport {\n getEnrichment,\n modelHasTag,\n modelHasAction,\n modelMatchesCatalogPriceTier,\n modelMatchesPriceTier,\n modelMatchesKind,\n priceTierForModel,\n type ModelEnrichment,\n} from \"./enrichment/index.js\"\n\nimport { getModel } from \"./registry/index.js\"\nimport { priceTierForModel as priceTierForModelInternal } from \"./enrichment/index.js\"\n\n/**\n * Display price gauge level (1..5) for a model id — resolves the catalog\n * entry then defers to {@link priceTierForModel}. 0 for an unknown id.\n * The id→level convenience used by the WhatsApp / slash pickers, which carry\n * a model id rather than a resolved model.\n */\nexport function priceTierForModelId(id: string): number {\n const model = getModel(id)\n return model ? priceTierForModelInternal(model) : 0\n}\nexport type {\n AvailableModel,\n AvailableModelCapabilities,\n AvailableConnector,\n AvailableModelsActor,\n AvailableModelsResponse,\n ListAvailableModelsParams,\n} from \"./picker/index.js\"\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAoEO,SAAS,oBAAoB,EAAA,EAAoB;AACtD,EAAA,MAAM,KAAA,GAAQ,SAAS,EAAE,CAAA;AACzB,EAAA,OAAO,KAAA,GAAQ,iBAAA,CAA0B,KAAK,CAAA,GAAI,CAAA;AACpD","file":"index.mjs","sourcesContent":["/**\n * @agentproto/model-catalog — unified model catalog.\n *\n * Single source of truth for LLM, image, video, audio, and voice model\n * entries. Owns cost dispatch, BYOK policy, and access control evaluation.\n * Zod-only OSS core; @agentproto/model-catalog layers billing/access/BYOK\n * policy on top.\n *\n * Subpath imports for tree-shaking:\n * import { LLM_PRICING_CATALOG } from \"@agentproto/model-catalog/llm\"\n * import { calculateCost } from \"@agentproto/model-catalog/cost\"\n * import { shouldDebit } from \"@agentproto/model-catalog/byok\"\n * import { evaluateAccess } from \"@agentproto/model-catalog/access\"\n * import { VOICE_CATALOG } from \"@agentproto/model-catalog/voice\"\n * import { listSurfaced } from \"@agentproto/model-catalog/curation\"\n */\n\nexport * from \"./schema/index.js\"\n// LLM has its own `resolveAlias` (legacy back-compat for the app legacy pricing module).\n// At the top level we prefer the cross-kind `resolveAlias` from the registry.\nexport {\n LLM_PRICING_CATALOG,\n MODEL_ALIASES,\n DEFAULT_PRICING,\n resolvePricing,\n calculateLLMCreditCost,\n} from \"./llm/index.js\"\nexport type {\n LLMPricing,\n LLMUsageBreakdown,\n LLMCreditCostResult,\n} from \"./llm/index.js\"\nexport * from \"./image/index.js\"\nexport * from \"./video/index.js\"\nexport * from \"./audio/index.js\"\nexport * from \"./voice/index.js\"\nexport * from \"./curation/index.js\"\nexport * from \"./pricing/index.js\"\nexport * from \"./cost/index.js\"\nexport * from \"./byok/index.js\"\nexport * from \"./access/index.js\"\nexport * from \"./overlay/index.js\"\nexport * from \"./registry/index.js\"\nexport {\n getActions,\n isActionTag,\n assertReservedPrefixDiscipline,\n} from \"./registry/actions.js\"\nexport {\n getEnrichment,\n modelHasTag,\n modelHasAction,\n modelMatchesCatalogPriceTier,\n modelMatchesPriceTier,\n modelMatchesKind,\n priceTierForModel,\n type ModelEnrichment,\n} from \"./enrichment/index.js\"\n\nimport { getModel } from \"./registry/index.js\"\nimport { priceTierForModel as priceTierForModelInternal } from \"./enrichment/index.js\"\n\n/**\n * Display price gauge level (1..5) for a model id — resolves the catalog\n * entry then defers to {@link priceTierForModel}. 0 for an unknown id.\n * The id→level convenience used by the WhatsApp / slash pickers, which carry\n * a model id rather than a resolved model.\n */\nexport function priceTierForModelId(id: string): number {\n const model = getModel(id)\n return model ? priceTierForModelInternal(model) : 0\n}\nexport type {\n AvailableModel,\n AvailableModelCapabilities,\n AvailableConnector,\n AvailableModelsActor,\n AvailableModelsResponse,\n ListAvailableModelsParams,\n} from \"./picker/index.js\"\n"]}
@@ -1,5 +1,5 @@
1
- export { C as CacheStats, a as CalculateLLMCreditCostOptions, b as ContextWindowEntry, D as DEFAULT_PRICING, K as KnownLlmId, L as LLMCreditCostResult, c as LLMPricing, d as LLMUsageBreakdown, e as LLM_PRICING_CATALOG, f as LlmModelAlias, g as LlmModelId, M as MODEL_ALIASES, h as ModelRoute, i as calculateLLMCreditCost, j as getCacheStats, k as getModelProvider, r as resolveAlias, l as resolveContextWindow, m as resolveModelRoute, n as resolvePricing } from '../catalog-BPDMuxzf.js';
2
- import '../base-C4kz9Dxc.js';
1
+ export { C as CacheStats, a as CalculateLLMCreditCostOptions, b as ContextWindowEntry, D as DEFAULT_PRICING, K as KnownLlmId, L as LLMCreditCostResult, c as LLMPricing, d as LLMUsageBreakdown, e as LLM_PRICING_CATALOG, f as LlmModelAlias, g as LlmModelId, M as MODEL_ALIASES, h as ModelRoute, i as calculateLLMCreditCost, j as getCacheStats, k as getModelProvider, r as resolveAlias, l as resolveContextWindow, m as resolveModelRoute, n as resolvePricing } from '../catalog-CLQ-Bo1n.js';
2
+ import '../base-B8IIoaqg.js';
3
3
  import 'zod';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  export { LLM_TIERS, OPERATOR_AGENT_MODELS, OPERATOR_DEFAULT_GEMINI, OPERATOR_DEFAULT_PREMIUM, OPERATOR_DEFAULT_STANDARD, WORKFLOW_FAST_MODEL, WORKFLOW_PREMIUM_MODEL, WORKFLOW_TINY_MODEL } from '../chunk-O7TXHU5W.mjs';
2
- export { DEFAULT_PRICING, LLM_PRICING_CATALOG, MODEL_ALIASES, calculateLLMCreditCost, getCacheStats, getModelProvider, resolveAlias, resolveContextWindow, resolveModelRoute, resolvePricing } from '../chunk-FCPS2VGK.mjs';
2
+ export { DEFAULT_PRICING, LLM_PRICING_CATALOG, MODEL_ALIASES, calculateLLMCreditCost, getCacheStats, getModelProvider, resolveAlias, resolveContextWindow, resolveModelRoute, resolvePricing } from '../chunk-EXT2CSSJ.mjs';
3
3
  import '../chunk-QHELXPSL.mjs';
4
4
  //# sourceMappingURL=index.mjs.map
5
5
  //# sourceMappingURL=index.mjs.map
@@ -1,11 +1,11 @@
1
- import { c as LLMPricing } from '../catalog-BPDMuxzf.js';
1
+ import { c as LLMPricing } from '../catalog-CLQ-Bo1n.js';
2
2
  import { ImageModelDefinition } from '../image/index.js';
3
3
  import { VideoModelDefinition } from '../video/index.js';
4
4
  import { AudioModelDefinition } from '../audio/index.js';
5
5
  import { CatalogVoice } from '../schema/voice.js';
6
- import '../base-C4kz9Dxc.js';
6
+ import '../base-B8IIoaqg.js';
7
7
  import 'zod';
8
- import '../audio-BbeLA_4x.js';
8
+ import '../audio-DR0g_ZH_.js';
9
9
 
10
10
  /**
11
11
  * Consumer catalog overlays.
@@ -1,11 +1,11 @@
1
- import '../evaluate-CVzfLCd0.js';
2
- import '../base-C4kz9Dxc.js';
3
- export { A as AvailableConnector, a as AvailableModel, b as AvailableModelCapabilities, c as AvailableModelsActor, d as AvailableModelsResponse, L as ListAvailableModelsParams, P as PRICE_TIER_NAMES, j as PRICE_TIER_SLOTS, k as priceTierBar, l as priceTierName } from '../index-CgOxudo5.js';
4
- import '../index-DSgqNd3Z.js';
5
- import '../catalog-BPDMuxzf.js';
1
+ import '../evaluate-Df3GphJP.js';
2
+ import '../base-B8IIoaqg.js';
3
+ export { A as AvailableConnector, a as AvailableModel, b as AvailableModelCapabilities, c as AvailableModelsActor, d as AvailableModelsResponse, L as ListAvailableModelsParams, P as PRICE_TIER_NAMES, j as PRICE_TIER_SLOTS, k as priceTierBar, l as priceTierName } from '../index-D-sc36bL.js';
4
+ import '../index-C2XMLGDa.js';
5
+ import '../catalog-CLQ-Bo1n.js';
6
6
  import '../image/index.js';
7
7
  import '../video/index.js';
8
8
  import '../audio/index.js';
9
- import '../audio-BbeLA_4x.js';
9
+ import '../audio-DR0g_ZH_.js';
10
10
  import 'zod';
11
11
  import '../schema/voice.js';
@@ -1,32 +1,62 @@
1
- import { c as LLMPricing } from '../catalog-BPDMuxzf.js';
2
- import '../base-C4kz9Dxc.js';
1
+ import { c as LLMPricing } from '../catalog-CLQ-Bo1n.js';
2
+ import '../base-B8IIoaqg.js';
3
3
  import 'zod';
4
4
 
5
5
  /**
6
6
  * Route-aware model identity.
7
7
  *
8
8
  * Canonical reference syntax:
9
- * vendor/product[@route]
9
+ * [route:]vendor/product[:pin][@route]
10
10
  *
11
11
  * A model product (who built it + what product) is separate from its serving
12
- * route (how we reach it / how we are billed).
12
+ * route (how we reach it / how we are billed) and from an optional `:pin` —
13
+ * an OpenRouter routing variant or an inference-provider selector.
14
+ *
15
+ * Three axes:
16
+ *
17
+ * | Axis | Question it answers | Example value |
18
+ * |---------------------|------------------------------|---------------------------|
19
+ * | `vendor` | who built the model | `openai`, `anthropic` |
20
+ * | `route` | how we reach it / are billed | `openrouter`, `huggingface`, `openai` (direct) |
21
+ * | `inferenceProvider` / `variant` | who runs the GPUs behind a router, or which routing mode | `cerebras`, `groq` (provider); `free`, `nitro` (variant) |
13
22
  *
14
23
  * Examples:
15
- * openai/gpt-4o → vendor openai, product gpt-4o, route openai (direct)
16
- * openai/gpt-4o@openrouter → same product, routed through OpenRouter
17
- * openai/gpt-4o@agentik-proxy → same product, operator-configured proxy route
24
+ * openai/gpt-4o → vendor openai, product gpt-4o, route openai (direct)
25
+ * openai/gpt-4o@openrouter → same product, routed through OpenRouter
26
+ * openai/gpt-4o@agentik-proxy → same product, operator-configured proxy route
27
+ * deepseek/deepseek-chat:free@openrouter → OpenRouter, variant "free"
28
+ * openrouter:deepseek/deepseek-chat:free → legacy PREFIX form, same result
29
+ * meta-llama/Llama-3.1-8B:cerebras@huggingface → HuggingFace, inference-provider pin "cerebras"
30
+ *
31
+ * `:pin` classification (per the resolved route):
32
+ * - `openrouter` (or no explicit route) + pin ∈ {free, nitro, floor, online,
33
+ * exacto} → `variant` (a routing mode, not a provider).
34
+ * - anything else → `inferenceProvider` (HF inference provider / OpenRouter
35
+ * provider pin).
18
36
  *
19
37
  * Design invariants:
20
38
  * - `vendor` is who built the model; `route` is how we reach it.
21
39
  * - `provider/model` strings parse as vendor/product with implicit route = vendor
22
40
  * (backward-compatible reference form).
23
- * - Unscoped `xx@yy` is rejected.
41
+ * - Unscoped `xx@yy` is rejected; bare ids without a slash are rejected
42
+ * (lenient handling belongs in consumers — see `tryParseModelRef`).
43
+ * - The legacy `route:` PREFIX (colon before the first `/`, prefix must be a
44
+ * known route name) parses; an explicit `@route` suffix wins on conflict.
45
+ * `formatModelRef` always emits the canonical suffix form.
24
46
  * - Route metadata (pricing, limits, transport, availability) is separate from
25
47
  * product metadata and computed at resolution time.
26
48
  * - The abstraction is generic across model kinds; only LLM has a concrete
27
49
  * resolver today.
28
50
  */
29
51
 
52
+ /**
53
+ * OpenRouter variant suffixes — a CLOSED list. A `:pin` matching one of
54
+ * these on the OpenRouter route (or on a route-less/implicit-route id) is a
55
+ * routing *variant*, never an inference-provider pin.
56
+ * @see https://openrouter.ai/docs/features/provider-routing
57
+ */
58
+ declare const OPENROUTER_VARIANTS: readonly ["free", "nitro", "floor", "online", "exacto"];
59
+ type OpenRouterVariant = (typeof OPENROUTER_VARIANTS)[number];
30
60
  interface ModelRef {
31
61
  /** The original, trimmed string. */
32
62
  raw: string;
@@ -36,6 +66,14 @@ interface ModelRef {
36
66
  product: string;
37
67
  /** Routing target — defaults to vendor for direct vendor access. */
38
68
  route: string;
69
+ /**
70
+ * Explicit `:pin` classified as an inference-provider selector (HF
71
+ * inference provider, or an OpenRouter provider pin outside the closed
72
+ * variant list) rather than a routing variant.
73
+ */
74
+ inferenceProvider?: string;
75
+ /** OpenRouter routing variant (`free`, `nitro`, `floor`, `online`, `exacto`) — a closed list, never a provider. */
76
+ variant?: string;
39
77
  }
40
78
  declare class InvalidModelRefError extends Error {
41
79
  readonly raw: string;
@@ -43,18 +81,33 @@ declare class InvalidModelRefError extends Error {
43
81
  constructor(raw: string, message: string);
44
82
  }
45
83
  /**
46
- * Parse a model reference in `vendor/product[@route]` form.
84
+ * Parse a model reference in `[route:]vendor/product[:pin][@route]` form.
47
85
  *
48
86
  * - `openai/gpt-4o` → `{ vendor: "openai", product: "gpt-4o", route: "openai" }`
49
87
  * - `openai/gpt-4o@openrouter` → route "openrouter"
88
+ * - `deepseek/deepseek-chat:free@openrouter` → route "openrouter", variant "free"
89
+ * - `meta-llama/Llama-3.1-8B:cerebras@huggingface` → route "huggingface", inferenceProvider "cerebras"
90
+ * - `openrouter:anthropic/claude-sonnet-4.5` → legacy prefix, route "openrouter"
50
91
  *
51
- * Rejects empty strings, unscoped `@` refs, missing segments, and segments
52
- * containing `/` or `@`.
92
+ * Rejects empty strings, unscoped `@` refs, bare ids without a slash, missing
93
+ * segments, and segments containing `/` or `@`. `@route` wins over the
94
+ * legacy prefix when both are present.
53
95
  */
54
96
  declare function parseModelRef(raw: string): ModelRef;
55
97
  /**
56
- * Format a {@link ModelRef} back to its canonical string.
57
- * Implicit direct routes omit the `@route` suffix.
98
+ * {@link parseModelRef}, but never throws — returns `undefined` for any
99
+ * input the strict grammar rejects (bare ids, malformed refs, …). Lenient
100
+ * handling of non-canonical ids belongs in callers; this just makes the
101
+ * strict parser safe to probe.
102
+ */
103
+ declare function tryParseModelRef(raw: string): ModelRef | undefined;
104
+ /**
105
+ * Format a {@link ModelRef} back to its canonical string
106
+ * `vendor/product[:pin][@route]`. Implicit direct routes omit the `@route`
107
+ * suffix. Always emits the canonical suffix form — never the legacy
108
+ * `route:` prefix — so `formatModelRef(parseModelRef(x))` is stable
109
+ * (idempotent under re-parse). Prefers `variant` over `inferenceProvider`
110
+ * when (implausibly) both are set, since parse only ever produces one.
58
111
  */
59
112
  declare function formatModelRef(ref: ModelRef): string;
60
113
  /** True when `raw` matches the `vendor/product[@route]` shape. */
@@ -124,6 +177,7 @@ declare function clearCustomRoutes(): void;
124
177
  * openai/gpt-4o → direct OpenAI pricing / transport
125
178
  * openai/gpt-4o@openrouter → OpenRouter route pricing / transport
126
179
  * openai/gpt-4o@requesty → Requesty route pricing / transport
180
+ * meta-llama/Llama-3.1-8B:cerebras@huggingface → HuggingFace, pinned to the "cerebras" inference provider
127
181
  * openai/gpt-4o@agentik-proxy → custom route config (if registered)
128
182
  *
129
183
  * Bare legacy ids (e.g. `gpt-4o`, `claude-sonnet-4-5`) are also accepted and
@@ -155,4 +209,4 @@ interface ModelRefDiagnostic {
155
209
  */
156
210
  declare function diagnoseModelRef(input: string | ModelRef): ModelRefDiagnostic | undefined;
157
211
 
158
- export { type CustomRouteConfig, InvalidModelRefError, type ModelProductMeta, type ModelRef, type ModelRefDiagnostic, type ModelRouteAvailability, type ModelRouteLimits, type ModelRouteMeta, type ModelRouteTransport, type ResolvedLlmModelRoute, type ResolvedModelRoute, clearCustomRoutes, diagnoseModelRef, formatModelRef, isModelRefString, parseModelRef, registerCustomRoute, resolveCustomRoute, resolveLlmModelRoute };
212
+ export { type CustomRouteConfig, InvalidModelRefError, type ModelProductMeta, type ModelRef, type ModelRefDiagnostic, type ModelRouteAvailability, type ModelRouteLimits, type ModelRouteMeta, type ModelRouteTransport, OPENROUTER_VARIANTS, type OpenRouterVariant, type ResolvedLlmModelRoute, type ResolvedModelRoute, clearCustomRoutes, diagnoseModelRef, formatModelRef, isModelRefString, parseModelRef, registerCustomRoute, resolveCustomRoute, resolveLlmModelRoute, tryParseModelRef };