@agentproto/model-catalog 0.8.0 → 0.8.2
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.
- package/README.md +1 -0
- package/dist/{chunk-3EFNFMEY.mjs → chunk-5FI5TGZ3.mjs} +4 -4
- package/dist/{chunk-3EFNFMEY.mjs.map → chunk-5FI5TGZ3.mjs.map} +1 -1
- package/dist/{chunk-23CZZUOP.mjs → chunk-GYQQFBOE.mjs} +483 -131
- package/dist/chunk-GYQQFBOE.mjs.map +1 -0
- package/dist/{chunk-KPDJINN6.mjs → chunk-LXN4OEHG.mjs} +167 -100
- package/dist/chunk-LXN4OEHG.mjs.map +1 -0
- package/dist/{chunk-WYZQKVME.mjs → chunk-T7727XPZ.mjs} +4 -4
- package/dist/{chunk-WYZQKVME.mjs.map → chunk-T7727XPZ.mjs.map} +1 -1
- package/dist/{chunk-PFEEV4K3.mjs → chunk-ZGIO6HG2.mjs} +3 -3
- package/dist/{chunk-PFEEV4K3.mjs.map → chunk-ZGIO6HG2.mjs.map} +1 -1
- package/dist/cost/index.mjs +4 -4
- package/dist/curation/index.mjs +4 -4
- package/dist/index.mjs +6 -6
- package/dist/llm/index.mjs +1 -1
- package/dist/route-identity/index.mjs +2 -2
- package/package.json +1 -1
- package/dist/chunk-23CZZUOP.mjs.map +0 -1
- package/dist/chunk-KPDJINN6.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getModel } from './chunk-
|
|
2
|
-
import { calculateLLMCreditCost } from './chunk-
|
|
1
|
+
import { getModel } from './chunk-5FI5TGZ3.mjs';
|
|
2
|
+
import { calculateLLMCreditCost } from './chunk-GYQQFBOE.mjs';
|
|
3
3
|
import { computeCenticredits, pricingRegistry } from './chunk-QHELXPSL.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -223,5 +223,5 @@ function calculateAudioCost(modelId, usage, opts) {
|
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
export { CostUsageKindMismatchError, UnknownModelError, calculateAudioCost, calculateCost, calculateImageCost, calculateLLMCost, calculateVideoCost };
|
|
226
|
-
//# sourceMappingURL=chunk-
|
|
227
|
-
//# sourceMappingURL=chunk-
|
|
226
|
+
//# sourceMappingURL=chunk-T7727XPZ.mjs.map
|
|
227
|
+
//# sourceMappingURL=chunk-T7727XPZ.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cost/index.ts"],"names":["resolved","baseCostUsd","credits","calculatedCredits","markup"],"mappings":"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","file":"chunk-WYZQKVME.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-T7727XPZ.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,4 +1,4 @@
|
|
|
1
|
-
import { listModels } from './chunk-
|
|
1
|
+
import { listModels } from './chunk-5FI5TGZ3.mjs';
|
|
2
2
|
import { modelHasTag } from './chunk-WTHHXXIK.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -130,5 +130,5 @@ function filterVoicesByProviders(voices, providerTokens) {
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
export { applyProfile, expandProviders, filterVoicesByProviders, getProviderGroup, getSurfaceProfile, groupForProvider, listProviderGroups, listSurfaceProfiles, listSurfaced, modelMatchesProfile };
|
|
133
|
-
//# sourceMappingURL=chunk-
|
|
134
|
-
//# sourceMappingURL=chunk-
|
|
133
|
+
//# sourceMappingURL=chunk-ZGIO6HG2.mjs.map
|
|
134
|
+
//# sourceMappingURL=chunk-ZGIO6HG2.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/curation/index.ts"],"names":[],"mappings":"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","file":"chunk-PFEEV4K3.mjs","sourcesContent":["/**\n * Curation — what an app SURFACES from the catalog, distinct from\n * model-access (who MAY use a model: tier/scope policy). Curation is the\n * \"feature/provider catalog\" layer: an app composes views over the one\n * registry (\"all s2s voices from OpenAI OR Google\", \"images only\", …)\n * without touching the underlying data.\n *\n * Two registries, both following the canonical profile-registry shape\n * (`listX()` / `getX(id)` throwing with the known-id list):\n *\n * 1. PROVIDER GROUPS — a company (`openai`) maps to every provider tag\n * it owns across kinds (`openai` for the LLM/audio company tag,\n * `openai-realtime` for its voice engine). This is what reconciles\n * the two provider vocabularies in the registry: audio MODELS are\n * tagged by company, voices by engine. Curating by group spans both.\n *\n * 2. SURFACE PROFILES — named presets (`voice-s2s`, `images`, …) an app\n * selects from. Permissive by default (`all`); apps narrow only when\n * a picker should diverge.\n *\n * Selection precedence (caller's job): per-call arg → per-app/guild\n * config → env → `all` fallback.\n */\n\nimport {\n listModels,\n type CatalogKind,\n type ResolvedModel,\n} from \"../registry/index.js\"\nimport { modelHasTag } from \"../enrichment/index.js\"\nimport type { CatalogVoice } from \"../schema/voice.js\"\n\n// ───────────────────────────────────────────────────────────────────────\n// Provider groups — company → provider tags across kinds\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface ProviderGroup {\n /** Canonical company id, e.g. \"openai\", \"google\". */\n id: string\n /** Display label. */\n label: string\n /**\n * Every provider tag this company owns across kinds. Audio/image/LLM use\n * the company tag (`openai`); the voice engine uses its own (`openai-realtime`).\n */\n providers: readonly string[]\n}\n\nconst PROVIDER_GROUPS: readonly ProviderGroup[] = [\n { id: \"openai\", label: \"OpenAI\", providers: [\"openai\", \"openai-realtime\"] },\n { id: \"google\", label: \"Google\", providers: [\"google\", \"gemini-live\"] },\n { id: \"anthropic\", label: \"Anthropic\", providers: [\"anthropic\"] },\n { id: \"minimax\", label: \"MiniMax\", providers: [\"minimax\"] },\n { id: \"elevenlabs\", label: \"ElevenLabs\", providers: [\"elevenlabs\"] },\n { id: \"replicate\", label: \"Replicate\", providers: [\"replicate\"] },\n { id: \"deepgram\", label: \"Deepgram\", providers: [\"deepgram\"] },\n { id: \"assemblyai\", label: \"AssemblyAI\", providers: [\"assemblyai\"] },\n]\n\nexport function listProviderGroups(): readonly ProviderGroup[] {\n return PROVIDER_GROUPS\n}\n\nexport function getProviderGroup(id: string): ProviderGroup {\n const group = PROVIDER_GROUPS.find(g => g.id === id)\n if (!group) {\n const known = PROVIDER_GROUPS.map(g => g.id).join(\", \")\n throw new Error(`curation: unknown provider group \"${id}\". Known: ${known}`)\n }\n return group\n}\n\n/** The group that owns a raw provider tag, if any. */\nexport function groupForProvider(\n providerTag: string\n): ProviderGroup | undefined {\n return PROVIDER_GROUPS.find(g => g.providers.includes(providerTag))\n}\n\n/**\n * Expand a mixed list of provider-group ids and raw provider tags into the\n * flat set of provider tags to match against. A token that is a known\n * group id expands to its members; anything else passes through as a raw\n * tag (so callers can target an engine directly, e.g. `gemini-live`).\n */\nexport function expandProviders(tokens: readonly string[]): string[] {\n const out = new Set<string>()\n for (const token of tokens) {\n const group = PROVIDER_GROUPS.find(g => g.id === token)\n if (group) {\n for (const p of group.providers) out.add(p)\n } else {\n out.add(token)\n }\n }\n return [...out]\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Surface profiles — named views an app surfaces\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface SurfaceProfile {\n id: string\n description: string\n /** Restrict to these kinds. Undefined/empty = every kind. */\n kinds?: readonly CatalogKind[]\n /**\n * Restrict to these provider GROUP ids or raw provider tags (OR-set).\n * Expanded via `expandProviders`, so `[\"openai\"]` covers both the\n * `openai` company tag and the `openai-realtime` voice engine.\n */\n providers?: readonly string[]\n /** Require all of these capability tags (AND-set): `s2s`, `tts`, `edit`, … */\n capabilities?: readonly string[]\n /** Require all of these arbitrary tags (AND-set). */\n tags?: readonly string[]\n}\n\nconst SURFACE_PROFILES: readonly SurfaceProfile[] = [\n {\n id: \"all\",\n description: \"Everything the catalog offers — the permissive default\",\n },\n {\n id: \"text\",\n description: \"Text models (LLMs) only\",\n kinds: [\"llm\"],\n },\n {\n id: \"images\",\n description: \"Image models only\",\n kinds: [\"image\"],\n },\n {\n id: \"video\",\n description: \"Video models only\",\n kinds: [\"video\"],\n },\n {\n id: \"audio\",\n description: \"Audio models (TTS / STT / s2s) only\",\n kinds: [\"audio\"],\n },\n {\n id: \"voice\",\n description: \"Every curated voice, any provider\",\n kinds: [\"voice\"],\n },\n {\n id: \"voice-s2s\",\n description:\n \"Speech-to-speech voice engines (OpenAI Realtime, Gemini Live)\",\n kinds: [\"voice\"],\n capabilities: [\"s2s\"],\n },\n {\n id: \"voice-tts\",\n description: \"Sequential TTS voices (MiniMax, ElevenLabs)\",\n kinds: [\"voice\"],\n capabilities: [\"tts\"],\n },\n]\n\nexport function listSurfaceProfiles(): readonly SurfaceProfile[] {\n return SURFACE_PROFILES\n}\n\nexport function getSurfaceProfile(id: string): SurfaceProfile {\n const profile = SURFACE_PROFILES.find(p => p.id === id)\n if (!profile) {\n const known = SURFACE_PROFILES.map(p => p.id).join(\", \")\n throw new Error(\n `curation: unknown surface profile \"${id}\". Known: ${known}`\n )\n }\n return profile\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Filters\n// ───────────────────────────────────────────────────────────────────────\n\n/**\n * True iff a model passes a surface profile. Provider membership, like\n * capability/tag membership, is checked against the enrichment tag\n * vocabulary (every kind emits its provider as a tag), so this is uniform\n * across kinds and naturally spans the company/engine provider split.\n */\nexport function modelMatchesProfile(\n model: ResolvedModel,\n profile: SurfaceProfile\n): boolean {\n if (profile.kinds && profile.kinds.length > 0) {\n if (!profile.kinds.includes(model.kind)) return false\n }\n if (profile.providers && profile.providers.length > 0) {\n const tags = expandProviders(profile.providers)\n if (!tags.some(tag => modelHasTag(model, tag))) return false\n }\n if (profile.capabilities) {\n if (!profile.capabilities.every(cap => modelHasTag(model, cap)))\n return false\n }\n if (profile.tags) {\n if (!profile.tags.every(tag => modelHasTag(model, tag))) return false\n }\n return true\n}\n\n/** Filter a model list down to what a surface profile exposes. */\nexport function applyProfile(\n models: ResolvedModel[],\n profile: SurfaceProfile\n): ResolvedModel[] {\n return models.filter(model => modelMatchesProfile(model, profile))\n}\n\n/**\n * The catalog as a surface profile exposes it — `applyProfile` over the\n * full registry. The composable entry point for \"show me this view\".\n */\nexport function listSurfaced(profile: SurfaceProfile): ResolvedModel[] {\n return applyProfile(listModels(), profile)\n}\n\n/**\n * Voice-list curation. The merged voice catalog (curated + live\n * ElevenLabs) is `CatalogVoice[]`, not `ResolvedModel[]`, so it gets its\n * own provider filter — same group-expansion semantics. Only the provider\n * facet of a profile applies to a raw voice list (kind is implicitly\n * voice; capability/tag live on the registry projection).\n */\nexport function filterVoicesByProviders(\n voices: CatalogVoice[],\n providerTokens: readonly string[]\n): CatalogVoice[] {\n if (providerTokens.length === 0) return voices\n const tags = new Set(expandProviders(providerTokens))\n return voices.filter(v => tags.has(v.provider))\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/curation/index.ts"],"names":[],"mappings":"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","file":"chunk-ZGIO6HG2.mjs","sourcesContent":["/**\n * Curation — what an app SURFACES from the catalog, distinct from\n * model-access (who MAY use a model: tier/scope policy). Curation is the\n * \"feature/provider catalog\" layer: an app composes views over the one\n * registry (\"all s2s voices from OpenAI OR Google\", \"images only\", …)\n * without touching the underlying data.\n *\n * Two registries, both following the canonical profile-registry shape\n * (`listX()` / `getX(id)` throwing with the known-id list):\n *\n * 1. PROVIDER GROUPS — a company (`openai`) maps to every provider tag\n * it owns across kinds (`openai` for the LLM/audio company tag,\n * `openai-realtime` for its voice engine). This is what reconciles\n * the two provider vocabularies in the registry: audio MODELS are\n * tagged by company, voices by engine. Curating by group spans both.\n *\n * 2. SURFACE PROFILES — named presets (`voice-s2s`, `images`, …) an app\n * selects from. Permissive by default (`all`); apps narrow only when\n * a picker should diverge.\n *\n * Selection precedence (caller's job): per-call arg → per-app/guild\n * config → env → `all` fallback.\n */\n\nimport {\n listModels,\n type CatalogKind,\n type ResolvedModel,\n} from \"../registry/index.js\"\nimport { modelHasTag } from \"../enrichment/index.js\"\nimport type { CatalogVoice } from \"../schema/voice.js\"\n\n// ───────────────────────────────────────────────────────────────────────\n// Provider groups — company → provider tags across kinds\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface ProviderGroup {\n /** Canonical company id, e.g. \"openai\", \"google\". */\n id: string\n /** Display label. */\n label: string\n /**\n * Every provider tag this company owns across kinds. Audio/image/LLM use\n * the company tag (`openai`); the voice engine uses its own (`openai-realtime`).\n */\n providers: readonly string[]\n}\n\nconst PROVIDER_GROUPS: readonly ProviderGroup[] = [\n { id: \"openai\", label: \"OpenAI\", providers: [\"openai\", \"openai-realtime\"] },\n { id: \"google\", label: \"Google\", providers: [\"google\", \"gemini-live\"] },\n { id: \"anthropic\", label: \"Anthropic\", providers: [\"anthropic\"] },\n { id: \"minimax\", label: \"MiniMax\", providers: [\"minimax\"] },\n { id: \"elevenlabs\", label: \"ElevenLabs\", providers: [\"elevenlabs\"] },\n { id: \"replicate\", label: \"Replicate\", providers: [\"replicate\"] },\n { id: \"deepgram\", label: \"Deepgram\", providers: [\"deepgram\"] },\n { id: \"assemblyai\", label: \"AssemblyAI\", providers: [\"assemblyai\"] },\n]\n\nexport function listProviderGroups(): readonly ProviderGroup[] {\n return PROVIDER_GROUPS\n}\n\nexport function getProviderGroup(id: string): ProviderGroup {\n const group = PROVIDER_GROUPS.find(g => g.id === id)\n if (!group) {\n const known = PROVIDER_GROUPS.map(g => g.id).join(\", \")\n throw new Error(`curation: unknown provider group \"${id}\". Known: ${known}`)\n }\n return group\n}\n\n/** The group that owns a raw provider tag, if any. */\nexport function groupForProvider(\n providerTag: string\n): ProviderGroup | undefined {\n return PROVIDER_GROUPS.find(g => g.providers.includes(providerTag))\n}\n\n/**\n * Expand a mixed list of provider-group ids and raw provider tags into the\n * flat set of provider tags to match against. A token that is a known\n * group id expands to its members; anything else passes through as a raw\n * tag (so callers can target an engine directly, e.g. `gemini-live`).\n */\nexport function expandProviders(tokens: readonly string[]): string[] {\n const out = new Set<string>()\n for (const token of tokens) {\n const group = PROVIDER_GROUPS.find(g => g.id === token)\n if (group) {\n for (const p of group.providers) out.add(p)\n } else {\n out.add(token)\n }\n }\n return [...out]\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Surface profiles — named views an app surfaces\n// ───────────────────────────────────────────────────────────────────────\n\nexport interface SurfaceProfile {\n id: string\n description: string\n /** Restrict to these kinds. Undefined/empty = every kind. */\n kinds?: readonly CatalogKind[]\n /**\n * Restrict to these provider GROUP ids or raw provider tags (OR-set).\n * Expanded via `expandProviders`, so `[\"openai\"]` covers both the\n * `openai` company tag and the `openai-realtime` voice engine.\n */\n providers?: readonly string[]\n /** Require all of these capability tags (AND-set): `s2s`, `tts`, `edit`, … */\n capabilities?: readonly string[]\n /** Require all of these arbitrary tags (AND-set). */\n tags?: readonly string[]\n}\n\nconst SURFACE_PROFILES: readonly SurfaceProfile[] = [\n {\n id: \"all\",\n description: \"Everything the catalog offers — the permissive default\",\n },\n {\n id: \"text\",\n description: \"Text models (LLMs) only\",\n kinds: [\"llm\"],\n },\n {\n id: \"images\",\n description: \"Image models only\",\n kinds: [\"image\"],\n },\n {\n id: \"video\",\n description: \"Video models only\",\n kinds: [\"video\"],\n },\n {\n id: \"audio\",\n description: \"Audio models (TTS / STT / s2s) only\",\n kinds: [\"audio\"],\n },\n {\n id: \"voice\",\n description: \"Every curated voice, any provider\",\n kinds: [\"voice\"],\n },\n {\n id: \"voice-s2s\",\n description:\n \"Speech-to-speech voice engines (OpenAI Realtime, Gemini Live)\",\n kinds: [\"voice\"],\n capabilities: [\"s2s\"],\n },\n {\n id: \"voice-tts\",\n description: \"Sequential TTS voices (MiniMax, ElevenLabs)\",\n kinds: [\"voice\"],\n capabilities: [\"tts\"],\n },\n]\n\nexport function listSurfaceProfiles(): readonly SurfaceProfile[] {\n return SURFACE_PROFILES\n}\n\nexport function getSurfaceProfile(id: string): SurfaceProfile {\n const profile = SURFACE_PROFILES.find(p => p.id === id)\n if (!profile) {\n const known = SURFACE_PROFILES.map(p => p.id).join(\", \")\n throw new Error(\n `curation: unknown surface profile \"${id}\". Known: ${known}`\n )\n }\n return profile\n}\n\n// ───────────────────────────────────────────────────────────────────────\n// Filters\n// ───────────────────────────────────────────────────────────────────────\n\n/**\n * True iff a model passes a surface profile. Provider membership, like\n * capability/tag membership, is checked against the enrichment tag\n * vocabulary (every kind emits its provider as a tag), so this is uniform\n * across kinds and naturally spans the company/engine provider split.\n */\nexport function modelMatchesProfile(\n model: ResolvedModel,\n profile: SurfaceProfile\n): boolean {\n if (profile.kinds && profile.kinds.length > 0) {\n if (!profile.kinds.includes(model.kind)) return false\n }\n if (profile.providers && profile.providers.length > 0) {\n const tags = expandProviders(profile.providers)\n if (!tags.some(tag => modelHasTag(model, tag))) return false\n }\n if (profile.capabilities) {\n if (!profile.capabilities.every(cap => modelHasTag(model, cap)))\n return false\n }\n if (profile.tags) {\n if (!profile.tags.every(tag => modelHasTag(model, tag))) return false\n }\n return true\n}\n\n/** Filter a model list down to what a surface profile exposes. */\nexport function applyProfile(\n models: ResolvedModel[],\n profile: SurfaceProfile\n): ResolvedModel[] {\n return models.filter(model => modelMatchesProfile(model, profile))\n}\n\n/**\n * The catalog as a surface profile exposes it — `applyProfile` over the\n * full registry. The composable entry point for \"show me this view\".\n */\nexport function listSurfaced(profile: SurfaceProfile): ResolvedModel[] {\n return applyProfile(listModels(), profile)\n}\n\n/**\n * Voice-list curation. The merged voice catalog (curated + live\n * ElevenLabs) is `CatalogVoice[]`, not `ResolvedModel[]`, so it gets its\n * own provider filter — same group-expansion semantics. Only the provider\n * facet of a profile applies to a raw voice list (kind is implicitly\n * voice; capability/tag live on the registry projection).\n */\nexport function filterVoicesByProviders(\n voices: CatalogVoice[],\n providerTokens: readonly string[]\n): CatalogVoice[] {\n if (providerTokens.length === 0) return voices\n const tags = new Set(expandProviders(providerTokens))\n return voices.filter(v => tags.has(v.provider))\n}\n"]}
|
package/dist/cost/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { CostUsageKindMismatchError, UnknownModelError, calculateAudioCost, calculateCost, calculateImageCost, calculateLLMCost, calculateVideoCost } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
1
|
+
export { CostUsageKindMismatchError, UnknownModelError, calculateAudioCost, calculateCost, calculateImageCost, calculateLLMCost, calculateVideoCost } from '../chunk-T7727XPZ.mjs';
|
|
2
|
+
import '../chunk-5FI5TGZ3.mjs';
|
|
3
|
+
import '../chunk-LXN4OEHG.mjs';
|
|
4
4
|
import '../chunk-WTHHXXIK.mjs';
|
|
5
5
|
import '../chunk-H6JUTF3U.mjs';
|
|
6
6
|
import '../chunk-DW45X6XT.mjs';
|
|
7
7
|
import '../chunk-O7TXHU5W.mjs';
|
|
8
|
-
import '../chunk-
|
|
8
|
+
import '../chunk-GYQQFBOE.mjs';
|
|
9
9
|
import '../chunk-QHELXPSL.mjs';
|
|
10
10
|
import '../chunk-2LWYZOWB.mjs';
|
|
11
11
|
import '../chunk-IJZ4XPO2.mjs';
|
package/dist/curation/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { applyProfile, expandProviders, filterVoicesByProviders, getProviderGroup, getSurfaceProfile, groupForProvider, listProviderGroups, listSurfaceProfiles, listSurfaced, modelMatchesProfile } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
1
|
+
export { applyProfile, expandProviders, filterVoicesByProviders, getProviderGroup, getSurfaceProfile, groupForProvider, listProviderGroups, listSurfaceProfiles, listSurfaced, modelMatchesProfile } from '../chunk-ZGIO6HG2.mjs';
|
|
2
|
+
import '../chunk-5FI5TGZ3.mjs';
|
|
3
|
+
import '../chunk-LXN4OEHG.mjs';
|
|
4
4
|
import '../chunk-WTHHXXIK.mjs';
|
|
5
5
|
import '../chunk-H6JUTF3U.mjs';
|
|
6
6
|
import '../chunk-DW45X6XT.mjs';
|
|
7
7
|
import '../chunk-O7TXHU5W.mjs';
|
|
8
|
-
import '../chunk-
|
|
8
|
+
import '../chunk-GYQQFBOE.mjs';
|
|
9
9
|
import '../chunk-QHELXPSL.mjs';
|
|
10
10
|
import '../chunk-2LWYZOWB.mjs';
|
|
11
11
|
import '../chunk-IJZ4XPO2.mjs';
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { applyProfile, expandProviders, filterVoicesByProviders, getProviderGroup, getSurfaceProfile, groupForProvider, listProviderGroups, listSurfaceProfiles, listSurfaced, modelMatchesProfile } from './chunk-
|
|
2
|
-
export { CostUsageKindMismatchError, UnknownModelError, calculateAudioCost, calculateCost, calculateImageCost, calculateLLMCost, calculateVideoCost } from './chunk-
|
|
3
|
-
import { getModel } from './chunk-
|
|
4
|
-
export { getModel, getModelsByProvider, getStaticModelProvider, isAgentVisible, listModels, resolveAlias } from './chunk-
|
|
5
|
-
import './chunk-
|
|
1
|
+
export { applyProfile, expandProviders, filterVoicesByProviders, getProviderGroup, getSurfaceProfile, groupForProvider, listProviderGroups, listSurfaceProfiles, listSurfaced, modelMatchesProfile } from './chunk-ZGIO6HG2.mjs';
|
|
2
|
+
export { CostUsageKindMismatchError, UnknownModelError, calculateAudioCost, calculateCost, calculateImageCost, calculateLLMCost, calculateVideoCost } from './chunk-T7727XPZ.mjs';
|
|
3
|
+
import { getModel } from './chunk-5FI5TGZ3.mjs';
|
|
4
|
+
export { getModel, getModelsByProvider, getStaticModelProvider, isAgentVisible, listModels, resolveAlias } from './chunk-5FI5TGZ3.mjs';
|
|
5
|
+
import './chunk-LXN4OEHG.mjs';
|
|
6
6
|
export { shouldDebit } from './chunk-XFDXTFV3.mjs';
|
|
7
7
|
export { evaluateAccess, evaluateCatalogDefaults } from './chunk-HRRG2RZO.mjs';
|
|
8
8
|
import { priceTierForModel } from './chunk-WTHHXXIK.mjs';
|
|
@@ -11,7 +11,7 @@ export { clearCatalogOverlays, getMergedOverlay, registerCatalogOverlay } from '
|
|
|
11
11
|
export { AudioCapabilitiesSchema, AudioEntrySchema, AudioPricingSchema, ImageAspectRatioSchema, ImageCapabilitiesSchema, ImageEntrySchema, ImagePricingSchema, ImageReferenceImagesSchema, LLMEntrySchema, LlmPricingSchema, ModelEntrySchema, VideoCapabilitiesSchema, VideoCostMultipliersSchema, VideoEntrySchema, VideoPricingSchema, VideoResolutionSchema } from './chunk-HL2G36MT.mjs';
|
|
12
12
|
export { CatalogPriceTierSchema, CatalogProviderSchema, LifecycleSchema, ModelKindSchema, NsfwPolicySchema, PROVIDER_KEY_ENV, PROVIDER_KEY_ENV_ALIASES, baseEntryShape } from './chunk-DW45X6XT.mjs';
|
|
13
13
|
import './chunk-O7TXHU5W.mjs';
|
|
14
|
-
export { DEFAULT_PRICING, LLM_PRICING_CATALOG, MODEL_ALIASES, calculateLLMCreditCost, resolvePricing } from './chunk-
|
|
14
|
+
export { DEFAULT_PRICING, LLM_PRICING_CATALOG, MODEL_ALIASES, calculateLLMCreditCost, resolvePricing } from './chunk-GYQQFBOE.mjs';
|
|
15
15
|
export { CC_USD_RATE, CREDIT_USD_RATE, DEFAULT_PRICING_FLOORS, DEFAULT_PRICING_MARKUP, computeCenticredits, pricingRegistry } from './chunk-QHELXPSL.mjs';
|
|
16
16
|
export { AGENT_EDITABLE_MODEL_IDS, AGENT_GENERATIVE_MODEL_IDS, AGENT_IMAGE_MODEL_IDS, IMAGE_MODEL_CATALOG, IMAGE_MODEL_IDS, generateImageModelTable } from './chunk-2LWYZOWB.mjs';
|
|
17
17
|
export { AGENT_VIDEO_MODEL_IDS, VIDEO_MODEL_CATALOG, VIDEO_MODEL_IDS, generateVideoModelTable } from './chunk-IJZ4XPO2.mjs';
|
package/dist/llm/index.mjs
CHANGED
|
@@ -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, resolvePricingExact } from '../chunk-
|
|
2
|
+
export { DEFAULT_PRICING, LLM_PRICING_CATALOG, MODEL_ALIASES, calculateLLMCreditCost, getCacheStats, getModelProvider, resolveAlias, resolveContextWindow, resolveModelRoute, resolvePricing, resolvePricingExact } from '../chunk-GYQQFBOE.mjs';
|
|
3
3
|
import '../chunk-QHELXPSL.mjs';
|
|
4
4
|
//# sourceMappingURL=index.mjs.map
|
|
5
5
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { InvalidModelRefError, OPENROUTER_VARIANTS, clearCustomRoutes, diagnoseModelRef, formatModelRef, isModelRefString, listRouterLlmRoutes, parseModelRef, registerCustomRoute, resolveCustomRoute, resolveLlmModelRoute, stripAnthropicNativeVendor, stripFixedNativeVendor, stripRouteSuffix, tryParseModelRef } from '../chunk-
|
|
1
|
+
export { InvalidModelRefError, OPENROUTER_VARIANTS, clearCustomRoutes, diagnoseModelRef, formatModelRef, isModelRefString, listRouterLlmRoutes, parseModelRef, registerCustomRoute, resolveCustomRoute, resolveLlmModelRoute, stripAnthropicNativeVendor, stripFixedNativeVendor, stripRouteSuffix, tryParseModelRef } from '../chunk-LXN4OEHG.mjs';
|
|
2
2
|
import '../chunk-DW45X6XT.mjs';
|
|
3
|
-
import '../chunk-
|
|
3
|
+
import '../chunk-GYQQFBOE.mjs';
|
|
4
4
|
import '../chunk-QHELXPSL.mjs';
|
|
5
5
|
//# sourceMappingURL=index.mjs.map
|
|
6
6
|
//# sourceMappingURL=index.mjs.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentproto/model-catalog",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Unified, dependency-light model catalog: LLM, image, video, audio entries + cost dispatcher + picker. Zod-only; the OSS core that @agstudio/model-catalog layers billing/access/BYOK on top of.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agentproto",
|