@broberg/ai-sdk 0.28.0 → 0.30.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.
@@ -73,31 +73,34 @@ var PRICING = {
73
73
  // $0, which is worse than no tracking (a confident wrong number).
74
74
  "vertex:gemini-2.5-flash": { inputPer1M: 0.3, outputPer1M: 2.5, version: V },
75
75
  "vertex:gemini-2.5-flash-lite": { inputPer1M: 0.1, outputPer1M: 0.4, version: "2026-06-04-or-xref" },
76
+ // Cached prompt tokens bill at 10% of the input rate (F039, measured 2026-08-27:
77
+ // an 8,810-token prefix reported 8,784 cached on the second call WITH a
78
+ // prompt_cache_key, and 0 without one at every size up to 57k).
76
79
  // Mistral (direct, La Plateforme). Official prices from mistral.ai/pricing
77
80
  // (2026-06-04, per Christian's CD report). EU/Paris-hosted — the designated
78
81
  // GDPR-safe provider for client/personal-data workloads (see F015). NB:
79
82
  // medium-3.5 is the premium "Vibe" coding tier ($1.5/$7.5); Large 3 ($0.5/$1.5)
80
83
  // is the cheaper frontier general-purpose model despite the higher number.
81
- "mistral:mistral-large-latest": { inputPer1M: 0.5, outputPer1M: 1.5, version: MS },
82
- "mistral:mistral-large-2512": { inputPer1M: 0.5, outputPer1M: 1.5, version: MS },
83
- "mistral:mistral-medium-latest": { inputPer1M: 1.5, outputPer1M: 7.5, version: MS },
84
- "mistral:mistral-medium-3.5": { inputPer1M: 1.5, outputPer1M: 7.5, version: MS },
85
- "mistral:mistral-medium-3": { inputPer1M: 0.4, outputPer1M: 2, version: "2026-06-04-or-xref" },
86
- "mistral:mistral-small-latest": { inputPer1M: 0.1, outputPer1M: 0.3, version: MS },
87
- "mistral:mistral-small-2603": { inputPer1M: 0.1, outputPer1M: 0.3, version: MS },
88
- "mistral:ministral-3b-latest": { inputPer1M: 0.1, outputPer1M: 0.1, version: MS },
89
- "mistral:ministral-8b-latest": { inputPer1M: 0.15, outputPer1M: 0.15, version: MS },
90
- "mistral:ministral-14b-latest": { inputPer1M: 0.2, outputPer1M: 0.2, version: MS },
91
- "mistral:magistral-medium-latest": { inputPer1M: 2, outputPer1M: 5, version: MS },
92
- "mistral:magistral-small-latest": { inputPer1M: 0.5, outputPer1M: 1.5, version: MS },
93
- "mistral:devstral-latest": { inputPer1M: 0.4, outputPer1M: 2, version: MS },
94
- "mistral:codestral-latest": { inputPer1M: 0.3, outputPer1M: 0.9, version: MS },
95
- "mistral:open-mistral-nemo": { inputPer1M: 0.15, outputPer1M: 0.15, version: MS },
84
+ "mistral:mistral-large-latest": { inputPer1M: 0.5, cacheReadPer1M: 0.05, outputPer1M: 1.5, version: MS },
85
+ "mistral:mistral-large-2512": { inputPer1M: 0.5, cacheReadPer1M: 0.05, outputPer1M: 1.5, version: MS },
86
+ "mistral:mistral-medium-latest": { inputPer1M: 1.5, cacheReadPer1M: 0.15, outputPer1M: 7.5, version: MS },
87
+ "mistral:mistral-medium-3.5": { inputPer1M: 1.5, cacheReadPer1M: 0.15, outputPer1M: 7.5, version: MS },
88
+ "mistral:mistral-medium-3": { inputPer1M: 0.4, cacheReadPer1M: 0.04, outputPer1M: 2, version: "2026-06-04-or-xref" },
89
+ "mistral:mistral-small-latest": { inputPer1M: 0.1, cacheReadPer1M: 0.01, outputPer1M: 0.3, version: MS },
90
+ "mistral:mistral-small-2603": { inputPer1M: 0.1, cacheReadPer1M: 0.01, outputPer1M: 0.3, version: MS },
91
+ "mistral:ministral-3b-latest": { inputPer1M: 0.1, cacheReadPer1M: 0.01, outputPer1M: 0.1, version: MS },
92
+ "mistral:ministral-8b-latest": { inputPer1M: 0.15, cacheReadPer1M: 0.015, outputPer1M: 0.15, version: MS },
93
+ "mistral:ministral-14b-latest": { inputPer1M: 0.2, cacheReadPer1M: 0.02, outputPer1M: 0.2, version: MS },
94
+ "mistral:magistral-medium-latest": { inputPer1M: 2, cacheReadPer1M: 0.2, outputPer1M: 5, version: MS },
95
+ "mistral:magistral-small-latest": { inputPer1M: 0.5, cacheReadPer1M: 0.05, outputPer1M: 1.5, version: MS },
96
+ "mistral:devstral-latest": { inputPer1M: 0.4, cacheReadPer1M: 0.04, outputPer1M: 2, version: MS },
97
+ "mistral:codestral-latest": { inputPer1M: 0.3, cacheReadPer1M: 0.03, outputPer1M: 0.9, version: MS },
98
+ "mistral:open-mistral-nemo": { inputPer1M: 0.15, cacheReadPer1M: 0.015, outputPer1M: 0.15, version: MS },
96
99
  // Moderation (F016.4) — per input token; output 0. (OCR is per-page in the adapter.)
97
- "mistral:mistral-moderation-latest": { inputPer1M: 0.1, outputPer1M: 0, version: MS },
100
+ "mistral:mistral-moderation-latest": { inputPer1M: 0.1, cacheReadPer1M: 0.01, outputPer1M: 0, version: MS },
98
101
  // Embeddings (F016.5) — per input token.
99
- "mistral:mistral-embed": { inputPer1M: 0.1, outputPer1M: 0, version: MS },
100
- "mistral:codestral-embed": { inputPer1M: 0.15, outputPer1M: 0, version: MS }
102
+ "mistral:mistral-embed": { inputPer1M: 0.1, cacheReadPer1M: 0.01, outputPer1M: 0, version: MS },
103
+ "mistral:codestral-embed": { inputPer1M: 0.15, cacheReadPer1M: 0.015, outputPer1M: 0, version: MS }
101
104
  };
102
105
  function getPrice(provider, model) {
103
106
  const exact = PRICING[`${provider}:${model}`];
@@ -111,4 +114,4 @@ export {
111
114
  PRICING,
112
115
  getPrice
113
116
  };
114
- //# sourceMappingURL=chunk-LUPUAAHZ.js.map
117
+ //# sourceMappingURL=chunk-LKVCPMVI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cost/pricing.ts"],"sourcesContent":["// Versioned per-(provider, model) pricing. F3.6 populates the table + adds tests\n// + MiniMax coverage. F3.1 ships the type + lookup with an empty table, so\n// computeCost returns 0 for every model until F3.6 lands (calls still complete).\nexport interface PricingEntry {\n /** USD per 1M input tokens. */\n inputPer1M: number;\n /** USD per 1M output tokens. */\n outputPer1M: number;\n /** USD per 1M cache-read tokens (falls back to input rate if unset). */\n cacheReadPer1M?: number;\n /** USD per 1M cache-write/creation tokens (falls back to input rate if unset). */\n cacheWritePer1M?: number;\n /** Pricing snapshot version (date or tag) so stale entries are detectable. */\n version: string;\n}\n\n// USD per 1M tokens. Anthropic cache multipliers follow the standard model:\n// cache-read ≈ 0.1× input, cache-write ≈ 1.25× input. Verified against the\n// pricing tables in cms (packages/cms-ai/src/providers) + trail (model-lab).\n// MiniMax M2.7 is an estimate pending confirmation against OpenRouter's live\n// price page — flagged in its version string.\nconst V = \"2026-06-02\";\n// Mistral prices come straight from mistral.ai/pricing (per Christian's CD report).\nconst MS = \"2026-06-04-mistral.ai\";\n\n/** Keyed `${provider}:${model}`. Exported so the catalogue-research job (F014)\n * can enumerate every priced entry and diff it against the live provider lists. */\nexport const PRICING: Record<string, PricingEntry> = {\n // Anthropic (direct API). DEFAULT_TIER_MAP: fast/cheap=haiku, smart/vision=sonnet, powerful=opus.\n \"anthropic:claude-haiku-4-5\": {\n inputPer1M: 0.8,\n outputPer1M: 4.0,\n cacheReadPer1M: 0.08,\n cacheWritePer1M: 1.0,\n version: V,\n },\n \"anthropic:claude-sonnet-4-6\": {\n inputPer1M: 3.0,\n outputPer1M: 15.0,\n cacheReadPer1M: 0.3,\n cacheWritePer1M: 3.75,\n version: V,\n },\n \"anthropic:claude-opus-4-8\": {\n inputPer1M: 15.0,\n outputPer1M: 75.0,\n cacheReadPer1M: 1.5,\n cacheWritePer1M: 18.75,\n version: V,\n },\n\n // OpenAI. embedding default tier = text-embedding-3-small (no output tokens).\n \"openai:text-embedding-3-small\": { inputPer1M: 0.02, outputPer1M: 0, version: V },\n \"openai:text-embedding-3-large\": { inputPer1M: 0.13, outputPer1M: 0, version: V },\n \"openai:gpt-4o\": { inputPer1M: 2.5, outputPer1M: 10.0, version: V },\n \"openai:gpt-4o-mini\": { inputPer1M: 0.15, outputPer1M: 0.6, version: V },\n // Whisper is priced per minute, not per token — not representable here; transcribe\n // (F5.6) computes its own cost. Listed as 0 so token-based compute never charges it.\n \"openai:whisper-1\": { inputPer1M: 0, outputPer1M: 0, version: V },\n\n // OpenRouter (meta-router — model slugs include the upstream vendor). Slugs use\n // dots (claude-sonnet-4.6) to match OpenRouter's live ids; the dashed forms\n // never matched a real call. Caught by the F014 catalogue research.\n \"openrouter:anthropic/claude-sonnet-4.6\": { inputPer1M: 3.0, outputPer1M: 15.0, version: V },\n // OpenRouter ground-truth $1/$5 — a markup over Anthropic-direct's $0.8/$4\n // (the `anthropic:` entry above). Was masked while the slug used dashes.\n \"openrouter:anthropic/claude-haiku-4.5\": { inputPer1M: 1.0, outputPer1M: 5.0, version: \"2026-06-04\" },\n \"openrouter:google/gemini-2.5-flash\": { inputPer1M: 0.3, outputPer1M: 2.5, version: V },\n // Ground-truth from OpenRouter /api/v1/models (was a 0.3 estimate; now 0.279).\n \"openrouter:minimax/minimax-m2.7\": {\n inputPer1M: 0.279,\n outputPer1M: 1.2,\n version: \"2026-06-04\",\n },\n // DeepSeek V4 (CN-hosted — NOT GDPR-safe; non-personal-data workloads only).\n // On 2026-05-22 DeepSeek made the \"75% off\" promo the permanent official price.\n // V4-Pro $0.435/$0.87 is ~34x cheaper than GPT-5.5 on output; flash is cheaper\n // still. Numbers match OpenRouter /api/v1/models 1:1 (no router markup). A strong\n // cheap route for fleet background work once `claude -p` is API-billed (15 Jun).\n \"openrouter:deepseek/deepseek-v4-pro\": { inputPer1M: 0.435, outputPer1M: 0.87, version: \"2026-05-22-deepseek-official\" },\n \"openrouter:deepseek/deepseek-v4-flash\": { inputPer1M: 0.0983, outputPer1M: 0.1966, version: \"2026-05-22-deepseek-official\" },\n // DeepSeek DIRECT API (provider \"deepseek\", F030 non-PII secondary). Rates from\n // api-docs.deepseek.com 2026-06-30 ($0.14/$0.28 per 1M; both map to deepseek-v4-flash).\n // `deepseek-chat` (non-thinking) + `deepseek-reasoner` (thinking) DEPRECATE 2026-07-24.\n // (The bare `deepseek-v4-flash` basename is already priced via the openrouter entry\n // above — kept distinct here to avoid a basename collision in the F027 pricing-API.)\n // Verify against a real key when it lands.\n \"deepseek:deepseek-chat\": { inputPer1M: 0.14, outputPer1M: 0.28, version: \"2026-06-30-deepseek-direct\" },\n \"deepseek:deepseek-reasoner\": { inputPer1M: 0.14, outputPer1M: 0.28, version: \"2026-06-30-deepseek-direct\" },\n\n // Google Gemini (direct). Provider key is \"gemini\" — matches the adapter's\n // usage.provider + the override.provider callers pass. (Image-gen models are\n // priced per-image in the adapter, not here.)\n \"gemini:gemini-2.5-flash\": { inputPer1M: 0.3, outputPer1M: 2.5, version: V },\n // flash-lite is the default `video` tier (F019) — cheap native video understanding.\n \"gemini:gemini-2.5-flash-lite\": { inputPer1M: 0.1, outputPer1M: 0.4, version: \"2026-06-04-or-xref\" },\n\n // Vertex AI (F038) — the EU-resident route to the SAME Gemini models, so Google's\n // published Gemini token prices apply. Listed separately because cost lookups key on\n // `provider:model`: without these rows an EU vision/video call would silently log\n // $0, which is worse than no tracking (a confident wrong number).\n \"vertex:gemini-2.5-flash\": { inputPer1M: 0.3, outputPer1M: 2.5, version: V },\n \"vertex:gemini-2.5-flash-lite\": { inputPer1M: 0.1, outputPer1M: 0.4, version: \"2026-06-04-or-xref\" },\n\n // Cached prompt tokens bill at 10% of the input rate (F039, measured 2026-08-27:\n // an 8,810-token prefix reported 8,784 cached on the second call WITH a\n // prompt_cache_key, and 0 without one at every size up to 57k).\n // Mistral (direct, La Plateforme). Official prices from mistral.ai/pricing\n // (2026-06-04, per Christian's CD report). EU/Paris-hosted — the designated\n // GDPR-safe provider for client/personal-data workloads (see F015). NB:\n // medium-3.5 is the premium \"Vibe\" coding tier ($1.5/$7.5); Large 3 ($0.5/$1.5)\n // is the cheaper frontier general-purpose model despite the higher number.\n \"mistral:mistral-large-latest\": { inputPer1M: 0.5, cacheReadPer1M: 0.05, outputPer1M: 1.5, version: MS },\n \"mistral:mistral-large-2512\": { inputPer1M: 0.5, cacheReadPer1M: 0.05, outputPer1M: 1.5, version: MS },\n \"mistral:mistral-medium-latest\": { inputPer1M: 1.5, cacheReadPer1M: 0.15, outputPer1M: 7.5, version: MS },\n \"mistral:mistral-medium-3.5\": { inputPer1M: 1.5, cacheReadPer1M: 0.15, outputPer1M: 7.5, version: MS },\n \"mistral:mistral-medium-3\": { inputPer1M: 0.4, cacheReadPer1M: 0.04, outputPer1M: 2.0, version: \"2026-06-04-or-xref\" },\n \"mistral:mistral-small-latest\": { inputPer1M: 0.1, cacheReadPer1M: 0.01, outputPer1M: 0.3, version: MS },\n \"mistral:mistral-small-2603\": { inputPer1M: 0.1, cacheReadPer1M: 0.01, outputPer1M: 0.3, version: MS },\n \"mistral:ministral-3b-latest\": { inputPer1M: 0.1, cacheReadPer1M: 0.01, outputPer1M: 0.1, version: MS },\n \"mistral:ministral-8b-latest\": { inputPer1M: 0.15, cacheReadPer1M: 0.015, outputPer1M: 0.15, version: MS },\n \"mistral:ministral-14b-latest\": { inputPer1M: 0.2, cacheReadPer1M: 0.02, outputPer1M: 0.2, version: MS },\n \"mistral:magistral-medium-latest\": { inputPer1M: 2.0, cacheReadPer1M: 0.2, outputPer1M: 5.0, version: MS },\n \"mistral:magistral-small-latest\": { inputPer1M: 0.5, cacheReadPer1M: 0.05, outputPer1M: 1.5, version: MS },\n \"mistral:devstral-latest\": { inputPer1M: 0.4, cacheReadPer1M: 0.04, outputPer1M: 2.0, version: MS },\n \"mistral:codestral-latest\": { inputPer1M: 0.3, cacheReadPer1M: 0.03, outputPer1M: 0.9, version: MS },\n \"mistral:open-mistral-nemo\": { inputPer1M: 0.15, cacheReadPer1M: 0.015, outputPer1M: 0.15, version: MS },\n // Moderation (F016.4) — per input token; output 0. (OCR is per-page in the adapter.)\n \"mistral:mistral-moderation-latest\": { inputPer1M: 0.1, cacheReadPer1M: 0.01, outputPer1M: 0, version: MS },\n // Embeddings (F016.5) — per input token.\n \"mistral:mistral-embed\": { inputPer1M: 0.1, cacheReadPer1M: 0.01, outputPer1M: 0, version: MS },\n \"mistral:codestral-embed\": { inputPer1M: 0.15, cacheReadPer1M: 0.015, outputPer1M: 0, version: MS },\n};\n\nexport function getPrice(provider: string, model: string): PricingEntry | undefined {\n const exact = PRICING[`${provider}:${model}`];\n if (exact) return exact;\n // Providers ship dated model snapshots, e.g. \"claude-haiku-4-5-20251001\".\n // Strip a trailing -YYYYMMDD and retry the base lookup so a dated variant\n // prices the same as its base model instead of falling through to 0 — a real\n // paid call must never be logged as $0 (F012). Covers openrouter slugs too.\n const base = model.replace(/-\\d{8}$/, \"\");\n if (base !== model) return PRICING[`${provider}:${base}`];\n return undefined;\n}\n"],"mappings":"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","names":[]}
@@ -1,21 +1,56 @@
1
+ // src/routing/tier-map.ts
2
+ var DEFAULT_TIER_MAP = {
3
+ fast: { provider: "mistral", model: "mistral-small-latest", transport: "http" },
4
+ smart: { provider: "mistral", model: "mistral-large-latest", transport: "http" },
5
+ powerful: { provider: "mistral", model: "mistral-large-latest", transport: "http" },
6
+ cheap: { provider: "mistral", model: "mistral-small-latest", transport: "http" },
7
+ // Vision: small-latest (vision-capable, cheap EU) is the default; override to
8
+ // mistral-large-latest for demanding image/spatial/composition work.
9
+ vision: { provider: "mistral", model: "mistral-small-latest", transport: "http" },
10
+ // Native video understanding — Gemini leads; flash-lite is the cheap default (F019).
11
+ // NOT Anthropic → out of the F030 phase-out (its own EU epic if/when needed).
12
+ video: { provider: "gemini", model: "gemini-2.5-flash-lite", transport: "http" },
13
+ // NOT Anthropic → out of F030 (EU-embedding migration is its own future epic).
14
+ embedding: { provider: "openai", model: "text-embedding-3-small", transport: "http" }
15
+ };
16
+ function resolveTier(tier, override, configMap) {
17
+ const base = configMap?.[tier] ?? DEFAULT_TIER_MAP[tier];
18
+ return { ...base, ...override };
19
+ }
20
+
1
21
  // src/availability/registry.ts
2
22
  var SUSPENDED_FABLE_MYTHOS = "suspended \u2014 US export-control directive (2026-06-12)";
3
23
  var DEFAULTS = [
4
24
  // ── Anthropic ────────────────────────────────────────────────────────────
5
- { id: "claude-haiku-4-5", aliases: ["haiku", "fast"], provider: "anthropic", available: true, status: "available", source: "default" },
6
- { id: "claude-sonnet-4-6", aliases: ["sonnet", "smart"], provider: "anthropic", available: true, status: "available", source: "default" },
7
- { id: "claude-opus-4-8", aliases: ["opus", "powerful"], provider: "anthropic", available: true, status: "available", source: "default" },
25
+ { id: "claude-haiku-4-5", aliases: ["haiku"], provider: "anthropic", available: true, status: "available", source: "default" },
26
+ { id: "claude-sonnet-4-6", aliases: ["sonnet"], provider: "anthropic", available: true, status: "available", source: "default" },
27
+ { id: "claude-opus-4-8", aliases: ["opus"], provider: "anthropic", available: true, status: "available", source: "default" },
8
28
  { id: "claude-fable-5", aliases: ["fable"], provider: "anthropic", available: true, status: "available", source: "default" },
9
29
  { id: "claude-mythos-5", aliases: ["mythos"], provider: "anthropic", available: false, status: "suspended", note: SUSPENDED_FABLE_MYTHOS, source: "default" },
10
30
  // ── Gemini ───────────────────────────────────────────────────────────────
11
31
  { id: "gemini-2.5-flash", aliases: ["gemini-flash"], provider: "gemini", available: true, status: "available", source: "default" },
12
- { id: "gemini-2.5-flash-lite", aliases: ["gemini-flash-lite", "video"], provider: "gemini", available: true, status: "available", source: "default" },
32
+ { id: "gemini-2.5-flash-lite", aliases: ["gemini-flash-lite"], provider: "gemini", available: true, status: "available", source: "default" },
13
33
  // ── OpenAI ───────────────────────────────────────────────────────────────
14
- { id: "text-embedding-3-small", aliases: ["embedding"], provider: "openai", available: true, status: "available", source: "default" },
34
+ { id: "text-embedding-3-small", aliases: [], provider: "openai", available: true, status: "available", source: "default" },
15
35
  // ── Mistral (EU / GDPR) ──────────────────────────────────────────────────
16
36
  { id: "mistral-large-latest", aliases: ["mistral-large"], provider: "mistral", available: true, status: "available", source: "default" },
17
37
  { id: "mistral-small-latest", aliases: ["mistral-small"], provider: "mistral", available: true, status: "available", source: "default" }
18
38
  ];
39
+ var TIER_ALIAS_CONFLICTS = [];
40
+ function applyTierAliases(entries) {
41
+ for (const [tier, spec] of Object.entries(DEFAULT_TIER_MAP)) {
42
+ const owner = entries.find((e) => e.id === spec.model && e.provider === spec.provider);
43
+ for (const e of entries) {
44
+ if (e !== owner && e.aliases.includes(tier)) {
45
+ TIER_ALIAS_CONFLICTS.push(`${tier} is hand-declared on ${e.id} (${e.provider}) but tier ${tier} calls ${spec.model} (${spec.provider})`);
46
+ e.aliases = e.aliases.filter((a) => a !== tier);
47
+ }
48
+ }
49
+ if (owner && !owner.aliases.includes(tier)) owner.aliases.push(tier);
50
+ }
51
+ return entries;
52
+ }
53
+ applyTierAliases(DEFAULTS);
19
54
  var OVERLAY = /* @__PURE__ */ new Map();
20
55
  var ALIAS_INDEX = /* @__PURE__ */ new Map();
21
56
  function seed() {
@@ -83,15 +118,16 @@ var ModelUnavailableError = class extends Error {
83
118
  function listModels(opts = {}) {
84
119
  return allEntries(opts.provider);
85
120
  }
86
- function isAvailable(requested) {
121
+ function isAvailable(requested, requireKnown = false) {
87
122
  const e = getEntry(requested);
88
- return e ? e.available : true;
123
+ if (!e) return !requireKnown;
124
+ return e.available;
89
125
  }
90
126
  function resolveModel(requested, opts = {}) {
91
127
  const id = canonicalId(requested) ?? requested;
92
128
  const entry = getEntry(requested);
93
129
  const provider = opts.provider ?? entry?.provider;
94
- if (isAvailable(requested)) {
130
+ if (isAvailable(requested, opts.requireKnown)) {
95
131
  return {
96
132
  ok: true,
97
133
  model: id,
@@ -103,7 +139,7 @@ function resolveModel(requested, opts = {}) {
103
139
  }
104
140
  const chain = opts.fallback === void 0 ? [] : Array.isArray(opts.fallback) ? opts.fallback : [opts.fallback];
105
141
  for (const fb of chain) {
106
- if (isAvailable(fb)) {
142
+ if (isAvailable(fb, opts.requireKnown)) {
107
143
  const fbId = canonicalId(fb) ?? fb;
108
144
  return {
109
145
  ok: false,
@@ -116,8 +152,10 @@ function resolveModel(requested, opts = {}) {
116
152
  };
117
153
  }
118
154
  }
155
+ const unknownAndGating = !entry && opts.requireKnown;
156
+ const reason = unknownAndGating ? `${id} is not a model this registry knows \u2014 requireKnown was set, so it is not assumed usable` : entry?.note ?? `${id} is unavailable`;
119
157
  if (opts.throwIfUnavailable) {
120
- throw new ModelUnavailableError(id, entry?.note, provider);
158
+ throw new ModelUnavailableError(id, reason, provider);
121
159
  }
122
160
  return {
123
161
  ok: false,
@@ -125,12 +163,14 @@ function resolveModel(requested, opts = {}) {
125
163
  requested: id,
126
164
  provider,
127
165
  fellBack: false,
128
- status: entry?.status ?? "suspended",
129
- reason: entry?.note ?? `${id} is unavailable`
166
+ status: entry?.status ?? "unknown",
167
+ reason
130
168
  };
131
169
  }
132
170
 
133
171
  export {
172
+ DEFAULT_TIER_MAP,
173
+ resolveTier,
134
174
  resetRegistry,
135
175
  providerIds,
136
176
  setAvailability,
@@ -138,4 +178,4 @@ export {
138
178
  listModels,
139
179
  resolveModel
140
180
  };
141
- //# sourceMappingURL=chunk-IT7HNKLY.js.map
181
+ //# sourceMappingURL=chunk-V2PD522L.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/routing/tier-map.ts","../src/availability/registry.ts","../src/availability/types.ts","../src/availability/resolve.ts"],"sourcesContent":["// Tier routing: a named Tier resolves to a concrete (provider, model, transport).\n// Precedence is per-call override > client config map > built-in defaults.\nimport type { Tier, TierSpec } from \"../types.js\";\n\n/** Built-in defaults. Every entry is overridable via AiConfig.defaults or a\n * per-call override.\n *\n * F030 — Anthropic API phase-out: `ANTHROPIC_API_KEY` was globally removed, so the\n * default cloud route may NOT hit Anthropic Console. `fast`/`smart`/`powerful`/\n * `vision` now default to **Mistral EU** (Paris-hosted, Schrems II-safe — so every\n * default text/vision call is GDPR-safe by default). Claude stays reachable as a\n * NON-default quality fallback for non-PII via `override:{provider:\"openrouter\",\n * model:\"anthropic/claude-…\"}`. DeepSeek (CN) is the opt-in non-PII secondary\n * (`provider:\"deepseek\"`), never a default. Magistral (reasoning) / mistral-large\n * for vision are per-call overrides, not defaults (don't pay the premium on all). */\nexport const DEFAULT_TIER_MAP: Record<Tier, TierSpec> = {\n fast: { provider: \"mistral\", model: \"mistral-small-latest\", transport: \"http\" },\n smart: { provider: \"mistral\", model: \"mistral-large-latest\", transport: \"http\" },\n powerful: { provider: \"mistral\", model: \"mistral-large-latest\", transport: \"http\" },\n cheap: { provider: \"mistral\", model: \"mistral-small-latest\", transport: \"http\" },\n // Vision: small-latest (vision-capable, cheap EU) is the default; override to\n // mistral-large-latest for demanding image/spatial/composition work.\n vision: { provider: \"mistral\", model: \"mistral-small-latest\", transport: \"http\" },\n // Native video understanding — Gemini leads; flash-lite is the cheap default (F019).\n // NOT Anthropic → out of the F030 phase-out (its own EU epic if/when needed).\n video: { provider: \"gemini\", model: \"gemini-2.5-flash-lite\", transport: \"http\" },\n // NOT Anthropic → out of F030 (EU-embedding migration is its own future epic).\n embedding: { provider: \"openai\", model: \"text-embedding-3-small\", transport: \"http\" },\n};\n\n/**\n * Resolve a Tier to a concrete TierSpec.\n *\n * Merge order (later wins): DEFAULT_TIER_MAP < configMap < override.\n * - `configMap` is the client-level AiConfig.defaults (per-tier full specs).\n * - `override` is a per-call Partial<TierSpec> — only the fields it sets win.\n */\nexport function resolveTier(\n tier: Tier,\n override?: Partial<TierSpec>,\n configMap?: Partial<Record<Tier, TierSpec>>,\n): TierSpec {\n const base = configMap?.[tier] ?? DEFAULT_TIER_MAP[tier];\n return { ...base, ...override };\n}\n","// F022 — the model-availability registry: the ONE source both resolveModel()\n// (spawn / call path) and listModels() (UI picker) read. A curated default seed\n// (works offline — the durable floor) plus a mutable overlay that\n// refreshAvailability() updates from the live provider list.\n//\n// Scope note: this is a LIVENESS view (is this id alive right now?), not the\n// rich capability/price inventory (that is F017 src/catalogue). We only track\n// ids we want to assert status on; anything not here is fail-open (treated\n// available) so we never block a model we simply do not track.\nimport { DEFAULT_TIER_MAP } from \"../routing/tier-map.js\";\nimport type { AvailabilityStatus, AvailabilitySource, ModelStatus } from \"./types.js\";\n\n/** Internal registry row. `aliases[0]` surfaces as ModelStatus.alias. */\nexport interface RegistryEntry {\n id: string;\n aliases: string[];\n provider: string;\n available: boolean;\n status: AvailabilityStatus;\n note?: string;\n source: AvailabilitySource;\n}\n\nconst SUSPENDED_FABLE_MYTHOS = \"suspended — US export-control directive (2026-06-12)\";\n\n/** Curated defaults. Aliases here are MODEL-IDENTITY names only (short names for\n * the model itself). TIER aliases — fast/smart/powerful/cheap/vision/video/\n * embedding — are NOT written here: they are derived from DEFAULT_TIER_MAP below,\n * because hand-maintaining them in two places is exactly how they drifted.\n *\n * They HAD drifted, and it crossed the EU border: this list said `smart` was\n * claude-sonnet-4-6 (Anthropic, US) for the ~3 months after F030 pointed the\n * default tiers at Mistral EU, so resolveModel('smart') named a US model while\n * ai.chat({tier:'smart'}) called an EU one. Anyone using resolveModel to SHOW or\n * DECIDE where data goes — the obvious use — got the wrong answer. Measured by\n * fd-sundhed in 0.21.1, still true in 0.28.0, fixed here by deleting the second\n * list rather than correcting it. */\nconst DEFAULTS: RegistryEntry[] = [\n // ── Anthropic ────────────────────────────────────────────────────────────\n { id: \"claude-haiku-4-5\", aliases: [\"haiku\"], provider: \"anthropic\", available: true, status: \"available\", source: \"default\" },\n { id: \"claude-sonnet-4-6\", aliases: [\"sonnet\"], provider: \"anthropic\", available: true, status: \"available\", source: \"default\" },\n { id: \"claude-opus-4-8\", aliases: [\"opus\"], provider: \"anthropic\", available: true, status: \"available\", source: \"default\" },\n { id: \"claude-fable-5\", aliases: [\"fable\"], provider: \"anthropic\", available: true, status: \"available\", source: \"default\" },\n { id: \"claude-mythos-5\", aliases: [\"mythos\"], provider: \"anthropic\", available: false, status: \"suspended\", note: SUSPENDED_FABLE_MYTHOS, source: \"default\" },\n // ── Gemini ───────────────────────────────────────────────────────────────\n { id: \"gemini-2.5-flash\", aliases: [\"gemini-flash\"], provider: \"gemini\", available: true, status: \"available\", source: \"default\" },\n { id: \"gemini-2.5-flash-lite\", aliases: [\"gemini-flash-lite\"], provider: \"gemini\", available: true, status: \"available\", source: \"default\" },\n // ── OpenAI ───────────────────────────────────────────────────────────────\n { id: \"text-embedding-3-small\", aliases: [], provider: \"openai\", available: true, status: \"available\", source: \"default\" },\n // ── Mistral (EU / GDPR) ──────────────────────────────────────────────────\n { id: \"mistral-large-latest\", aliases: [\"mistral-large\"], provider: \"mistral\", available: true, status: \"available\", source: \"default\" },\n { id: \"mistral-small-latest\", aliases: [\"mistral-small\"], provider: \"mistral\", available: true, status: \"available\", source: \"default\" },\n];\n\n/** Attach every tier name as an alias of the model that tier ACTUALLY calls.\n * One source: DEFAULT_TIER_MAP decides, the registry follows. A tier whose model\n * is not in the registry is left unaliased on purpose — resolveModel then reports\n * status \"unknown\" (fail-open) instead of inventing a row, and the drift test\n * catches it. */\nexport const TIER_ALIAS_CONFLICTS: string[] = [];\n\nfunction applyTierAliases(entries: RegistryEntry[]): RegistryEntry[] {\n for (const [tier, spec] of Object.entries(DEFAULT_TIER_MAP)) {\n const owner = entries.find((e) => e.id === spec.model && e.provider === spec.provider);\n // A tier name hand-written on any OTHER row is the drift bug returning. It\n // would resolve correctly TODAY only because seed() lets the last write win\n // and the rows happen to be ordered favourably — reorder the array and the\n // tier silently points at the wrong provider again. Record it so a test can\n // fail on it, then strip it so runtime is right regardless.\n for (const e of entries) {\n if (e !== owner && e.aliases.includes(tier)) {\n TIER_ALIAS_CONFLICTS.push(`${tier} is hand-declared on ${e.id} (${e.provider}) but tier ${tier} calls ${spec.model} (${spec.provider})`);\n e.aliases = e.aliases.filter((a) => a !== tier);\n }\n }\n if (owner && !owner.aliases.includes(tier)) owner.aliases.push(tier);\n }\n return entries;\n}\napplyTierAliases(DEFAULTS);\n\n/** The live overlay, keyed by canonical id. Seeded from DEFAULTS (deep-copied so\n * resetting is clean). refreshAvailability() mutates this; resolve/listModels\n * read it synchronously. */\nlet OVERLAY = new Map<string, RegistryEntry>();\n/** alias → canonical id, rebuilt whenever the overlay is seeded. */\nlet ALIAS_INDEX = new Map<string, string>();\n\nfunction seed(): void {\n OVERLAY = new Map(DEFAULTS.map((e) => [e.id, { ...e, aliases: [...e.aliases] }]));\n ALIAS_INDEX = new Map();\n for (const e of DEFAULTS) for (const a of e.aliases) ALIAS_INDEX.set(a, e.id);\n}\nseed();\n\n/** Reset the overlay back to the curated defaults. For tests. */\nexport function resetRegistry(): void {\n seed();\n}\n\n/** Canonical id for a model id OR alias; null when we track neither. */\nexport function canonicalId(requested: string): string | null {\n if (OVERLAY.has(requested)) return requested;\n return ALIAS_INDEX.get(requested) ?? null;\n}\n\n/** The current entry for an id/alias, or undefined when untracked (fail-open). */\nexport function getEntry(requested: string): RegistryEntry | undefined {\n const id = canonicalId(requested);\n return id ? OVERLAY.get(id) : undefined;\n}\n\n/** All tracked entries (optionally provider-scoped), as a public ModelStatus[]. */\nexport function allEntries(provider?: string): ModelStatus[] {\n const rows: ModelStatus[] = [];\n for (const e of OVERLAY.values()) {\n if (provider && e.provider !== provider) continue;\n rows.push({\n id: e.id,\n alias: e.aliases[0],\n provider: e.provider,\n available: e.available,\n status: e.status,\n note: e.note,\n source: e.source,\n });\n }\n return rows;\n}\n\n/** Provider-scoped canonical ids (for refresh reconciliation). */\nexport function providerIds(provider: string): string[] {\n return [...OVERLAY.values()].filter((e) => e.provider === provider).map((e) => e.id);\n}\n\n/** Mark a tracked id available/suspended from a live refresh. No-op if untracked. */\nexport function setAvailability(id: string, available: boolean, note?: string): void {\n const e = OVERLAY.get(id);\n if (!e) return;\n e.available = available;\n e.status = available ? \"available\" : \"suspended\";\n e.source = \"refresh\";\n if (note !== undefined) e.note = note;\n else if (available) e.note = undefined;\n}\n","// F022 — Model Availability Harness. Public types for the availability layer:\n// the shared status read (ModelStatus), the resolve result, and the structured\n// error a caller can flag on. The registry is the one source both the spawn /\n// call path (resolveModel) and UI pickers (listModels) read.\n\nexport type AvailabilityStatus = \"available\" | \"suspended\" | \"unknown\";\n\n/** Where a model's current availability came from: the curated default seed,\n * or a live provider refresh (Anthropic GET /v1/models). */\nexport type AvailabilitySource = \"default\" | \"refresh\";\n\n/** One row of the shared status read — what a UI model-picker renders. */\nexport interface ModelStatus {\n /** Canonical provider model id, e.g. \"claude-fable-5\". */\n id: string;\n /** Short/tier alias, e.g. \"fable\" (the first registered alias). */\n alias?: string;\n /** \"anthropic\" | \"openai\" | \"gemini\" | \"mistral\" | … */\n provider: string;\n available: boolean;\n status: AvailabilityStatus;\n /** Friendly reason, e.g. \"suspended — US export-control directive (2026-06-12)\". */\n note?: string;\n source: AvailabilitySource;\n}\n\n/** Result of resolveModel — the spawn / call path consumes this synchronously. */\nexport interface ResolveResult {\n /** True when the requested model itself is available. */\n ok: boolean;\n /** The id to actually use: `requested` when ok, else the first available fallback. */\n model: string;\n /** What the caller asked for (id or alias, normalized to the canonical id). */\n requested: string;\n provider?: string;\n /** True when `model` differs from `requested` because we fell back. */\n fellBack: boolean;\n status: AvailabilityStatus;\n /** Why it degraded / why it is unavailable. */\n reason?: string;\n}\n\n/** Thrown by resolveModel when the requested model is unavailable, no usable\n * fallback exists, and the caller passed `throwIfUnavailable`. Callers flag on\n * `.code === \"model_unavailable\"`. */\nexport class ModelUnavailableError extends Error {\n readonly code = \"model_unavailable\";\n readonly requested: string;\n readonly provider?: string;\n readonly note?: string;\n constructor(requested: string, note?: string, provider?: string) {\n super(`model \"${requested}\" is unavailable${note ? ` (${note})` : \"\"}`);\n this.name = \"ModelUnavailableError\";\n this.requested = requested;\n this.note = note;\n this.provider = provider;\n }\n}\n","// F022 — the synchronous, zero-I/O resolve + status read. This is the spawn /\n// call hot path (buddy's launcher calls resolveModel per spawn, cardmem #4842):\n// it MUST never await and never touch the network. Freshness comes only from a\n// prior async refreshAvailability(); resolve just reads the in-memory registry.\nimport { allEntries, canonicalId, getEntry } from \"./registry.js\";\nimport { ModelUnavailableError } from \"./types.js\";\nimport type { ModelStatus, ResolveResult } from \"./types.js\";\n\nexport interface ResolveOptions {\n /** One id/alias or an ordered chain to try when `requested` is unavailable. */\n fallback?: string | string[];\n /** Scope hint (passed through to the result); does not gate lookup. */\n provider?: string;\n /** Throw ModelUnavailableError instead of returning ok:false when there is no\n * usable fallback. For callers that want to flag rather than degrade. */\n throwIfUnavailable?: boolean;\n /** Treat an id we do not track as UNUSABLE instead of fail-open.\n *\n * Default is fail-open: we never block a model we simply do not track. That is\n * right for liveness, and wrong for a caller who is GATING — cms measured the\n * consequence: resolveModel(\"cheap\") answered {ok:true, model:\"cheap\"}, so a\n * consumer following our own instruction to gate on `ok` passed the gate and\n * then sent the literal string \"cheap\" to a provider as a model id. A\n * success-shaped non-answer is worse than an error, because an error gets\n * handled and a shape does not.\n *\n * Set this when you need \"a model you actually know about\". Off by default so\n * no existing caller changes behaviour. */\n requireKnown?: boolean;\n}\n\n/** The shared status read — UI pickers grey out `available:false` rows. */\nexport function listModels(opts: { provider?: string } = {}): ModelStatus[] {\n return allEntries(opts.provider);\n}\n\n/** Is this id/alias currently usable? Untracked ids are fail-open (true) unless\n * the caller asked for requireKnown. */\nfunction isAvailable(requested: string, requireKnown = false): boolean {\n const e = getEntry(requested);\n if (!e) return !requireKnown; // fail-open on unknown, unless gating\n return e.available;\n}\n\n/**\n * Resolve a requested model (id or alias) to one that is actually usable.\n * Synchronous + offline by contract (cardmem #4842) — reads the registry only.\n *\n * - Available → pass through ({ ok:true, fellBack:false }).\n * - Unavailable + a fallback that IS available → swap ({ ok:false, fellBack:true }).\n * - Unavailable + no usable fallback → throw (throwIfUnavailable) or return ok:false.\n * - Unknown id → treated available (never block a model we do not track).\n */\nexport function resolveModel(requested: string, opts: ResolveOptions = {}): ResolveResult {\n const id = canonicalId(requested) ?? requested;\n const entry = getEntry(requested);\n const provider = opts.provider ?? entry?.provider;\n\n if (isAvailable(requested, opts.requireKnown)) {\n return {\n ok: true,\n model: id,\n requested: id,\n provider,\n fellBack: false,\n status: entry?.status ?? \"unknown\",\n };\n }\n\n // Requested is suspended — walk the fallback chain for the first available one.\n const chain = opts.fallback === undefined ? [] : Array.isArray(opts.fallback) ? opts.fallback : [opts.fallback];\n for (const fb of chain) {\n if (isAvailable(fb, opts.requireKnown)) {\n const fbId = canonicalId(fb) ?? fb;\n return {\n ok: false,\n model: fbId,\n requested: id,\n provider,\n fellBack: true,\n status: entry?.status ?? \"suspended\",\n reason: entry?.note ?? `${id} is unavailable`,\n };\n }\n }\n\n // No usable fallback.\n const unknownAndGating = !entry && opts.requireKnown;\n const reason = unknownAndGating\n ? `${id} is not a model this registry knows — requireKnown was set, so it is not assumed usable`\n : (entry?.note ?? `${id} is unavailable`);\n if (opts.throwIfUnavailable) {\n throw new ModelUnavailableError(id, reason, provider);\n }\n return {\n ok: false,\n model: id,\n requested: id,\n provider,\n fellBack: false,\n status: entry?.status ?? \"unknown\",\n reason,\n };\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.ts CHANGED
@@ -117,6 +117,12 @@ interface ChatRequest {
117
117
  spec: TierSpec;
118
118
  tools?: Tool[];
119
119
  maxTokens?: number;
120
+ /** F039 — Mistral prompt caching. A stable application-level id for "the same
121
+ * conversation" (a conversation id, a session id). Requests sharing a prefix AND
122
+ * this key reuse the cached prefix at 10% of the input rate. Not auto-generated:
123
+ * only the caller knows what "the same conversation" means, and an SDK-invented
124
+ * key would either collide across tenants or never hit. */
125
+ promptCacheKey?: string;
120
126
  temperature?: number;
121
127
  /** "json" → request JSON-object output where the provider supports it (F009). */
122
128
  responseFormat?: "json" | "text";
@@ -595,6 +601,9 @@ declare const chatInputSchema: z.ZodObject<{
595
601
  }>]>, "many">>;
596
602
  purpose: z.ZodOptional<z.ZodString>;
597
603
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
604
+ /** F039 — reuse a cached prompt prefix on Mistral at 10% of the input rate.
605
+ * A stable id for "the same conversation" (conversation id, session id). */
606
+ promptCacheKey: z.ZodOptional<z.ZodString>;
598
607
  prompt: z.ZodOptional<z.ZodString>;
599
608
  messages: z.ZodOptional<z.ZodArray<z.ZodObject<{
600
609
  role: z.ZodEnum<["system", "user", "assistant", "tool"]>;
@@ -687,6 +696,7 @@ declare const chatInputSchema: z.ZodObject<{
687
696
  responseFormat: z.ZodOptional<z.ZodEnum<["json", "text"]>>;
688
697
  }, "strip", z.ZodTypeAny, {
689
698
  system?: string | undefined;
699
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
690
700
  prompt?: string | undefined;
691
701
  messages?: {
692
702
  role: "system" | "user" | "assistant" | "tool";
@@ -712,9 +722,9 @@ declare const chatInputSchema: z.ZodObject<{
712
722
  }[] | undefined;
713
723
  temperature?: number | undefined;
714
724
  purpose?: string | undefined;
725
+ promptCacheKey?: string | undefined;
715
726
  maxTokens?: number | undefined;
716
727
  responseFormat?: "text" | "json" | undefined;
717
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
718
728
  override?: {
719
729
  provider?: string | undefined;
720
730
  model?: string | undefined;
@@ -728,6 +738,7 @@ declare const chatInputSchema: z.ZodObject<{
728
738
  labels?: Record<string, string> | undefined;
729
739
  }, {
730
740
  system?: string | undefined;
741
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
731
742
  prompt?: string | undefined;
732
743
  messages?: {
733
744
  role: "system" | "user" | "assistant" | "tool";
@@ -753,9 +764,9 @@ declare const chatInputSchema: z.ZodObject<{
753
764
  }[] | undefined;
754
765
  temperature?: number | undefined;
755
766
  purpose?: string | undefined;
767
+ promptCacheKey?: string | undefined;
756
768
  maxTokens?: number | undefined;
757
769
  responseFormat?: "text" | "json" | undefined;
758
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
759
770
  override?: {
760
771
  provider?: string | undefined;
761
772
  model?: string | undefined;
@@ -808,9 +819,9 @@ declare const visionInputSchema: z.ZodObject<{
808
819
  image: string | Uint8Array<ArrayBuffer>;
809
820
  prompt: string;
810
821
  system?: string | undefined;
822
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
811
823
  mimeType?: string | undefined;
812
824
  purpose?: string | undefined;
813
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
814
825
  override?: {
815
826
  provider?: string | undefined;
816
827
  model?: string | undefined;
@@ -826,9 +837,9 @@ declare const visionInputSchema: z.ZodObject<{
826
837
  image: string | Uint8Array<ArrayBuffer>;
827
838
  prompt: string;
828
839
  system?: string | undefined;
840
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
829
841
  mimeType?: string | undefined;
830
842
  purpose?: string | undefined;
831
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
832
843
  override?: {
833
844
  provider?: string | undefined;
834
845
  model?: string | undefined;
@@ -880,9 +891,9 @@ declare const videoInputSchema: z.ZodObject<{
880
891
  video: string | Uint8Array<ArrayBuffer>;
881
892
  prompt: string;
882
893
  system?: string | undefined;
894
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
883
895
  mimeType?: string | undefined;
884
896
  purpose?: string | undefined;
885
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
886
897
  override?: {
887
898
  provider?: string | undefined;
888
899
  model?: string | undefined;
@@ -898,9 +909,9 @@ declare const videoInputSchema: z.ZodObject<{
898
909
  video: string | Uint8Array<ArrayBuffer>;
899
910
  prompt: string;
900
911
  system?: string | undefined;
912
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
901
913
  mimeType?: string | undefined;
902
914
  purpose?: string | undefined;
903
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
904
915
  override?: {
905
916
  provider?: string | undefined;
906
917
  model?: string | undefined;
@@ -949,8 +960,8 @@ declare const translateInputSchema: z.ZodObject<{
949
960
  }, "strip", z.ZodTypeAny, {
950
961
  text: string;
951
962
  to: string;
952
- purpose?: string | undefined;
953
963
  tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
964
+ purpose?: string | undefined;
954
965
  override?: {
955
966
  provider?: string | undefined;
956
967
  model?: string | undefined;
@@ -966,8 +977,8 @@ declare const translateInputSchema: z.ZodObject<{
966
977
  }, {
967
978
  text: string;
968
979
  to: string;
969
- purpose?: string | undefined;
970
980
  tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
981
+ purpose?: string | undefined;
971
982
  override?: {
972
983
  provider?: string | undefined;
973
984
  model?: string | undefined;
@@ -1045,6 +1056,7 @@ declare const imageInputSchema: z.ZodObject<{
1045
1056
  retryOnBlack: z.ZodOptional<z.ZodBoolean>;
1046
1057
  }, "strip", z.ZodTypeAny, {
1047
1058
  prompt: string;
1059
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1048
1060
  seed?: number | undefined;
1049
1061
  purpose?: string | undefined;
1050
1062
  loras?: {
@@ -1054,7 +1066,6 @@ declare const imageInputSchema: z.ZodObject<{
1054
1066
  lora?: string | undefined;
1055
1067
  width?: number | undefined;
1056
1068
  height?: number | undefined;
1057
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1058
1069
  override?: {
1059
1070
  provider?: string | undefined;
1060
1071
  model?: string | undefined;
@@ -1074,6 +1085,7 @@ declare const imageInputSchema: z.ZodObject<{
1074
1085
  retryOnBlack?: boolean | undefined;
1075
1086
  }, {
1076
1087
  prompt: string;
1088
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1077
1089
  seed?: number | undefined;
1078
1090
  purpose?: string | undefined;
1079
1091
  loras?: {
@@ -1083,7 +1095,6 @@ declare const imageInputSchema: z.ZodObject<{
1083
1095
  lora?: string | undefined;
1084
1096
  width?: number | undefined;
1085
1097
  height?: number | undefined;
1086
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1087
1098
  override?: {
1088
1099
  provider?: string | undefined;
1089
1100
  model?: string | undefined;
@@ -1142,10 +1153,10 @@ declare const animateInputSchema: z.ZodObject<{
1142
1153
  resolution: z.ZodOptional<z.ZodString>;
1143
1154
  }, "strip", z.ZodTypeAny, {
1144
1155
  image: string | Uint8Array<ArrayBuffer>;
1156
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1145
1157
  prompt?: string | undefined;
1146
1158
  resolution?: string | undefined;
1147
1159
  purpose?: string | undefined;
1148
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1149
1160
  override?: {
1150
1161
  provider?: string | undefined;
1151
1162
  model?: string | undefined;
@@ -1160,10 +1171,10 @@ declare const animateInputSchema: z.ZodObject<{
1160
1171
  durationSec?: number | undefined;
1161
1172
  }, {
1162
1173
  image: string | Uint8Array<ArrayBuffer>;
1174
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1163
1175
  prompt?: string | undefined;
1164
1176
  resolution?: string | undefined;
1165
1177
  purpose?: string | undefined;
1166
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1167
1178
  override?: {
1168
1179
  provider?: string | undefined;
1169
1180
  model?: string | undefined;
@@ -1216,9 +1227,9 @@ declare const trainStyleInputSchema: z.ZodObject<{
1216
1227
  createMasks: z.ZodOptional<z.ZodBoolean>;
1217
1228
  }, "strip", z.ZodTypeAny, {
1218
1229
  images: string | string[];
1230
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1219
1231
  purpose?: string | undefined;
1220
1232
  steps?: number | undefined;
1221
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1222
1233
  override?: {
1223
1234
  provider?: string | undefined;
1224
1235
  model?: string | undefined;
@@ -1235,9 +1246,9 @@ declare const trainStyleInputSchema: z.ZodObject<{
1235
1246
  createMasks?: boolean | undefined;
1236
1247
  }, {
1237
1248
  images: string | string[];
1249
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1238
1250
  purpose?: string | undefined;
1239
1251
  steps?: number | undefined;
1240
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1241
1252
  override?: {
1242
1253
  provider?: string | undefined;
1243
1254
  model?: string | undefined;
@@ -1286,8 +1297,8 @@ declare const embeddingInputSchema: z.ZodObject<{
1286
1297
  text: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
1287
1298
  }, "strip", z.ZodTypeAny, {
1288
1299
  text: string | string[];
1289
- purpose?: string | undefined;
1290
1300
  tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1301
+ purpose?: string | undefined;
1291
1302
  override?: {
1292
1303
  provider?: string | undefined;
1293
1304
  model?: string | undefined;
@@ -1301,8 +1312,8 @@ declare const embeddingInputSchema: z.ZodObject<{
1301
1312
  labels?: Record<string, string> | undefined;
1302
1313
  }, {
1303
1314
  text: string | string[];
1304
- purpose?: string | undefined;
1305
1315
  tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1316
+ purpose?: string | undefined;
1306
1317
  override?: {
1307
1318
  provider?: string | undefined;
1308
1319
  model?: string | undefined;
@@ -1359,9 +1370,9 @@ declare const transcribeInputSchema: z.ZodObject<{
1359
1370
  timestamps: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["word", "segment"]>, z.ZodArray<z.ZodEnum<["word", "segment"]>, "many">]>>;
1360
1371
  }, "strip", z.ZodTypeAny, {
1361
1372
  audio: string | Uint8Array<ArrayBuffer>;
1373
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1362
1374
  language?: string | undefined;
1363
1375
  purpose?: string | undefined;
1364
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1365
1376
  override?: {
1366
1377
  provider?: string | undefined;
1367
1378
  model?: string | undefined;
@@ -1378,9 +1389,9 @@ declare const transcribeInputSchema: z.ZodObject<{
1378
1389
  timestamps?: "word" | "segment" | ("word" | "segment")[] | undefined;
1379
1390
  }, {
1380
1391
  audio: string | Uint8Array<ArrayBuffer>;
1392
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1381
1393
  language?: string | undefined;
1382
1394
  purpose?: string | undefined;
1383
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1384
1395
  override?: {
1385
1396
  provider?: string | undefined;
1386
1397
  model?: string | undefined;
@@ -1432,9 +1443,9 @@ declare const ocrInputSchema: z.ZodObject<{
1432
1443
  mimeType: z.ZodOptional<z.ZodString>;
1433
1444
  }, "strip", z.ZodTypeAny, {
1434
1445
  document: string | Uint8Array<ArrayBuffer>;
1446
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1435
1447
  mimeType?: string | undefined;
1436
1448
  purpose?: string | undefined;
1437
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1438
1449
  override?: {
1439
1450
  provider?: string | undefined;
1440
1451
  model?: string | undefined;
@@ -1448,9 +1459,9 @@ declare const ocrInputSchema: z.ZodObject<{
1448
1459
  labels?: Record<string, string> | undefined;
1449
1460
  }, {
1450
1461
  document: string | Uint8Array<ArrayBuffer>;
1462
+ tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1451
1463
  mimeType?: string | undefined;
1452
1464
  purpose?: string | undefined;
1453
- tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1454
1465
  override?: {
1455
1466
  provider?: string | undefined;
1456
1467
  model?: string | undefined;
@@ -1496,8 +1507,8 @@ declare const moderationInputSchema: z.ZodObject<{
1496
1507
  input: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
1497
1508
  }, "strip", z.ZodTypeAny, {
1498
1509
  input: string | string[];
1499
- purpose?: string | undefined;
1500
1510
  tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1511
+ purpose?: string | undefined;
1501
1512
  override?: {
1502
1513
  provider?: string | undefined;
1503
1514
  model?: string | undefined;
@@ -1511,8 +1522,8 @@ declare const moderationInputSchema: z.ZodObject<{
1511
1522
  labels?: Record<string, string> | undefined;
1512
1523
  }, {
1513
1524
  input: string | string[];
1514
- purpose?: string | undefined;
1515
1525
  tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1526
+ purpose?: string | undefined;
1516
1527
  override?: {
1517
1528
  provider?: string | undefined;
1518
1529
  model?: string | undefined;
@@ -1573,8 +1584,8 @@ declare const podcastInputSchema: z.ZodObject<{
1573
1584
  speaker: string;
1574
1585
  }[];
1575
1586
  voices: Record<string, string>;
1576
- purpose?: string | undefined;
1577
1587
  tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1588
+ purpose?: string | undefined;
1578
1589
  override?: {
1579
1590
  provider?: string | undefined;
1580
1591
  model?: string | undefined;
@@ -1593,8 +1604,8 @@ declare const podcastInputSchema: z.ZodObject<{
1593
1604
  speaker: string;
1594
1605
  }[];
1595
1606
  voices: Record<string, string>;
1596
- purpose?: string | undefined;
1597
1607
  tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1608
+ purpose?: string | undefined;
1598
1609
  override?: {
1599
1610
  provider?: string | undefined;
1600
1611
  model?: string | undefined;
@@ -1641,7 +1652,15 @@ declare const ttsInputSchema: z.ZodObject<{
1641
1652
  text: z.ZodString;
1642
1653
  voice: z.ZodString;
1643
1654
  /** F037: voice to use if `voice` is one we know the provider has retired. Without
1644
- * it a retired voice throws VoiceUnavailableError rather than reaching the API. */
1655
+ * it a retired voice throws VoiceUnavailableError rather than reaching the API.
1656
+ *
1657
+ * THINK BEFORE SETTING THIS. It is right for batch work where any acceptable voice
1658
+ * will do (a generated podcast, a bulk render). It is WRONG where the voice is an
1659
+ * identity a human recognises — a brand voice, a house narrator: falling back means
1660
+ * your product suddenly speaks with a stranger's voice and says nothing about why.
1661
+ * There, leave it unset and let the throw alarm you. Silence WITH a message beats
1662
+ * the wrong audio WITHOUT one. (torrent-search-api's call on their own house voice,
1663
+ * 2026-08-11 — they took the alarm over the fallback, deliberately.) */
1645
1664
  voiceFallback: z.ZodOptional<z.ZodString>;
1646
1665
  lang: z.ZodOptional<z.ZodString>;
1647
1666
  format: z.ZodOptional<z.ZodString>;
@@ -1649,8 +1668,8 @@ declare const ttsInputSchema: z.ZodObject<{
1649
1668
  }, "strip", z.ZodTypeAny, {
1650
1669
  text: string;
1651
1670
  voice: string;
1652
- purpose?: string | undefined;
1653
1671
  tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1672
+ purpose?: string | undefined;
1654
1673
  override?: {
1655
1674
  provider?: string | undefined;
1656
1675
  model?: string | undefined;
@@ -1669,8 +1688,8 @@ declare const ttsInputSchema: z.ZodObject<{
1669
1688
  }, {
1670
1689
  text: string;
1671
1690
  voice: string;
1672
- purpose?: string | undefined;
1673
1691
  tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
1692
+ purpose?: string | undefined;
1674
1693
  override?: {
1675
1694
  provider?: string | undefined;
1676
1695
  model?: string | undefined;
@@ -2053,8 +2072,8 @@ declare const falStubAdapter: ProviderAdapter;
2053
2072
  * wires the live adapters. */
2054
2073
  declare const stubProviders: Record<string, ProviderAdapter>;
2055
2074
 
2056
- declare const VERSION: "0.28.0";
2057
- declare const SDK_TAG: "@broberg/ai-sdk@0.28.0";
2075
+ declare const VERSION: "0.30.0";
2076
+ declare const SDK_TAG: "@broberg/ai-sdk@0.30.0";
2058
2077
 
2059
2078
  /** Built-in defaults. Every entry is overridable via AiConfig.defaults or a
2060
2079
  * per-call override.