@broberg/ai-sdk 0.55.3 → 0.56.1

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/dist/index.d.ts CHANGED
@@ -1,772 +1,8 @@
1
1
  import { z } from 'zod';
2
- export { AvailabilitySource, AvailabilityStatus, ModelStatus, ModelUnavailableError, ResolveOptions, ResolveResult, listModels, resolveModel } from './registry.js';
2
+ import { T as Tier, U as Usage, C as ChatResult, a as ChatStreamEvent, b as TranslateResult, I as ImageResult, A as AnimateResult, c as TrainStyleResult, E as EmbeddingResult, d as TranscribeResult, O as OcrResult, M as ModerationResult, J as JudgeResult, P as PodcastResult, B as BatchRequestItem, e as TierSpec, f as BatchJob, g as BatchResultItem, h as ProviderAdapter, i as CostSink, j as ToolCall, k as Tool, l as Transport, m as Capability, R as Region, n as BudgetConfig, o as BudgetStore } from './registry-U66vzTm0.js';
3
+ export { p as AlignedWordTimings, q as AvailabilitySource, r as AvailabilityStatus, s as AzureWordBoundary, t as CallOptions, u as ChatRequest, v as ContentPart, D as DialogueRequest, w as DialogueTurn, x as EmbeddingRequest, y as ImageRequest, z as JudgeAnswer, F as JudgeChoiceAnswer, G as JudgeNoulAnswer, H as JudgeQuestion, K as JudgeScoreAnswer, L as LoraWeight, N as Message, Q as ModelStatus, S as ModelUnavailableError, V as ModerationItem, W as ModerationRequest, X as OcrPage, Y as OcrRequest, Z as ResolveOptions, _ as ResolveResult, $ as Role, a0 as TierDescription, a1 as TrainStyleRequest, a2 as TranscribeRequest, a3 as TtsRequest, a4 as WordTiming, a5 as alignWordTimings, a6 as classifyRegionName, a7 as describeTier, a8 as listModels, a9 as regionOfHost, aa as regionOfProvider, ab as resolveModel } from './registry-U66vzTm0.js';
3
4
  export { DEFAULT_CLIP_SEC, MEDIA_PRICING_CHECKED_AT, MediaPrice, MediaUnit, PRICING_STALE_AFTER_DAYS, PricingFreshness, UnitFreshness, getMediaPrice, listMediaPrices, pricingFreshness, pricingGeneratedAt } from './pricing.js';
4
5
 
5
- type FailureKind = "auth" | "not_found" | "rate_limit" | "server" | "timeout" | "network" | "other";
6
- interface CallFailure {
7
- provider: string;
8
- /** The model we ASKED for (the route that failed). */
9
- model: string;
10
- transport: string;
11
- capability: Capability;
12
- tier?: Tier;
13
- purpose?: string;
14
- labels?: Record<string, string>;
15
- latencyMs: number;
16
- ts: string;
17
- /** HTTP status as a string ("401", "503"), or "timeout" | "network" | "unknown". */
18
- errorCode: string;
19
- errorKind: FailureKind;
20
- }
21
-
22
- /** Coarse data-residency of the endpoint a call went to.
23
- *
24
- * - `"eu"` — EU/EEA. **The only positive residency claim.** Nothing else is folded
25
- * in: an adequacy decision is not EU residency, so the UK, Switzerland
26
- * and Canada are deliberately NOT `"eu"` here.
27
- * - `"us"` — United States.
28
- * - `"cn"` — China.
29
- * - `"unknown"` — we genuinely cannot say: an aggregator that picks its own upstream,
30
- * or a region string we do not recognise.
31
- *
32
- * **`"unknown"` is NOT a synonym for safe.** `region !== "us"` is not an EU check —
33
- * it passes every OpenRouter call. Only `region === "eu"` may be treated as EU-resident.
34
- */
35
- type Region = "eu" | "us" | "cn" | "unknown";
36
- /** Region of the endpoint a call will actually hit. Never throws — a residency
37
- * reading must not be able to break a call that already succeeded. */
38
- declare function regionOfHost(hostOrUrl: string | undefined): Region;
39
- /** Classify a provider REGION STRING — a Vertex/GCP location like `europe-west1`, or
40
- * an Azure region like `westeurope`. Anything unrecognised is `"unknown"`: a region
41
- * name we have never seen is exactly the case where guessing is most tempting and
42
- * least defensible. Never throws — a residency reading must not be able to break a
43
- * call that already succeeded. */
44
- declare function classifyRegionName(name: string | undefined): Region;
45
- /** Region for an adapter whose endpoint is fixed. Unknown provider → `"unknown"`.
46
- *
47
- * **DO NOT BUILD A RESIDENCY GUARD ON THIS.** Use {@link regionOfHost} on the base URL
48
- * the call will actually use. Found by a consumer building exactly that guard (super,
49
- * 2026-08-30): `regionOfProvider("mistral")` is `"unknown"` — correct, because Mistral
50
- * takes a `baseUrl` and a name cannot answer for residency — but a guard written as
51
- * `regionOfProvider(p) === "eu"` therefore REJECTS Mistral, which is the only EU route
52
- * we have. It fails closed and is useless: it filters out the thing it exists to allow.
53
- *
54
- * The trap is invisible from the signature, which is why it is written here rather than
55
- * only in the docs. This function answers "is this provider's endpoint fixed, and where
56
- * is it?" — a narrower question than "where will my call go?". */
57
- declare function regionOfProvider(provider: string): Region;
58
-
59
- /** One dictionary entry. `alias` says it differently; `ipa` says it in phonemes.
60
- *
61
- * **`ipa` is NOT the "more precise" option for a FOREIGN word — measured 2026-09-04.**
62
- * Christian listened to `workflow` as `ˈwɜːkfloʊ` through the da-DK voices jeppe and
63
- * christel and reported: *"ikke korrekt engelsk med et sjovt mix"*. A Danish neural
64
- * voice renders English phonemes through Danish phonology, so foreign IPA comes out a
65
- * hybrid rather than English. The symbols are honoured; the accent is not.
66
- *
67
- * So pick by what the word IS, not by which field sounds more exact:
68
- * - a DANISH word the voice mispronounces → `ipa` does what you want.
69
- * - an ENGLISH word inside Danish text → neither field is right yet. `alias` (spell it
70
- * the way a Dane would say it) is the honest workaround today; a real engine switch
71
- * is F051.2, and it is blocked on a listening test, not on code.
72
- *
73
- * Dated on purpose. This is a measurement of two specific voices on one date, not a
74
- * permanent property of IPA — Azure ships new voices, and the next reader deserves to
75
- * see that it may have moved. */
76
- interface Pronunciation {
77
- /** The word as it appears in the text. Matched whole-word, case-insensitively. */
78
- word: string;
79
- /** Say this instead. Azure `<sub alias>`; ElevenLabs plain substitution. */
80
- alias?: string;
81
- /** Also match INSIDE a hyphenated compound — `AI` in `AI-agenter` (F051.3).
82
- *
83
- * Danish puts abbreviations there constantly. cms measured their own articles:
84
- * "AI-agenter" 13 times, "AI-native" 12, 60+ occurrences in all, every one read aloud
85
- * as one mangled word. Christian heard it as "HTLM" and asked why AI was not spelled
86
- * out too — it WAS, just never in a compound.
87
- *
88
- * **Per entry, and defaulting to `false`, because the right answer depends on the
89
- * word.** `AI` yes; `mail` no — a rule for `mail` must not fire inside `e-mail`.
90
- * Measured rather than reasoned: `@broberg/speech-dictionary` ships the general
91
- * loosening and pays exactly that price today. A single global answer is wrong for
92
- * one of the two classes whichever way it is set, so the person who wrote the entry
93
- * decides.
94
- *
95
- * Default `false` is also the safe direction to be wrong in: flipping it would change
96
- * the audio for every existing consumer IN SOUND, where there is no compile error, no
97
- * red test and no log line to notice it by. */
98
- matchInCompounds?: boolean;
99
- /** IPA phonemes. Azure `<phoneme alphabet="ipa" ph>`. ElevenLabs cannot do this
100
- * (it THROWS rather than silently skipping). See the type doc above before reaching
101
- * for this on a foreign word. */
102
- ipa?: string;
103
- /** Reserved for a future per-entry language switch; carried but not yet emitted. */
104
- lang?: string;
105
- }
106
-
107
- /** One entry of Azure's `[nnnn].word.json`, verbatim field names. */
108
- interface AzureWordBoundary {
109
- Text: string;
110
- /** Milliseconds into the audio. */
111
- AudioOffset: number;
112
- /** Milliseconds. */
113
- Duration: number;
114
- }
115
- interface WordTiming {
116
- /** The spoken word, as Azure reported it. */
117
- text: string;
118
- startMs: number;
119
- endMs: number;
120
- /** Character span in the SOURCE text. Several spoken words share one span when they
121
- * came from one substituted manuscript word. */
122
- sourceStart: number;
123
- sourceEnd: number;
124
- }
125
- interface AlignedWordTimings {
126
- /** Every word we could place in the source, in audio order. */
127
- words: WordTiming[];
128
- /** Spoken words we could NOT place, in order, verbatim.
129
- *
130
- * Named rather than dropped, and never given a guessed offset. "I could not place
131
- * this" and "it was here" must not be the same answer — the same discipline as
132
- * `rerank.unscored` (F052). A highlighter that treats `words` as complete must look
133
- * here. */
134
- unaligned: string[];
135
- }
136
- /** A pronunciation entry, narrowed to what alignment needs. */
137
- interface AliasEntry {
138
- word: string;
139
- alias?: string;
140
- }
141
- /**
142
- * Map Azure's spoken word list onto positions in the SOURCE text.
143
- *
144
- * Two rules carry the whole function:
145
- *
146
- * **The walk only moves FORWARD.** That is what puts a repeated word on its own
147
- * occurrence — "AI er AI" must not place the second on the first. Searching from 0 each
148
- * time passes every test with distinct words and fails silently on real prose.
149
- *
150
- * **A substitution is matched as a RUN, not word by word.** Azure speaks SSML, so
151
- * `<sub alias='broberg punktum a i'>broberg.ai</sub>` puts four words in the list where
152
- * the manuscript has one. Matching them individually is not merely imprecise, it is
153
- * wrong in a way that bites every Danish text: MEASURED on cms's own dictionary entry,
154
- * a per-word map made the alias's "i" swallow the next real Danish word "i" in
155
- * "broberg.ai i dag". An alias's parts are often ordinary words ("a", "i", "punktum"),
156
- * so a lookup table cannot be the mechanism — the run has to be consumed positionally.
157
- */
158
- declare function alignWordTimings(text: string, words: AzureWordBoundary[], opts?: {
159
- pronunciations?: AliasEntry[];
160
- }): AlignedWordTimings;
161
-
162
- /** How a call reaches the model. `http` = provider REST API; `subprocess` = local
163
- * `claude -p` CLI (Max plan, costUsd 0). */
164
- type Transport = "http" | "subprocess";
165
- /** Named capability tier. Resolves to a (provider, model, transport) triple via
166
- * the tier map, overridable per call. */
167
- type Tier = "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding";
168
- /** The concrete routing target a Tier (or a per-call override) resolves to. */
169
- interface TierSpec {
170
- provider: string;
171
- model: string;
172
- transport: Transport;
173
- }
174
- /** High-level capability a call exercises. Mirrors the capability layer (F5). */
175
- type Capability = "chat" | "vision" | "video" | "translate" | "image" | "animate" | "embedding" | "transcribe" | "ocr" | "moderation" | "podcast" | "tts" | "trainStyle" | "mockup" | "design" | "extract" | "classify" | "rerank" | "judge";
176
- type Role = "system" | "user" | "assistant" | "tool";
177
- /** A piece of message content. Text everywhere; image parts feed vision. */
178
- type ContentPart = {
179
- type: "text";
180
- text: string;
181
- } | {
182
- type: "image";
183
- image: string | Uint8Array;
184
- mimeType?: string;
185
- } | {
186
- type: "video";
187
- video: string | Uint8Array;
188
- mimeType?: string;
189
- };
190
- interface Message {
191
- role: Role;
192
- content: string | ContentPart[];
193
- /** Set on assistant messages that called tools. Accepts either spelling of the
194
- * arguments field — see ToolCallLike. */
195
- toolCalls?: ToolCallLike[];
196
- /** Set on `tool` role messages — which call this result answers. */
197
- toolCallId?: string;
198
- /** F049 — Mistral's `prefix`: start the model's reply with this text instead of
199
- * asking it to. Only valid on the LAST message, and only when that message is an
200
- * `assistant` one; anything else throws rather than being sent, because Mistral
201
- * documents no behaviour for it elsewhere.
202
- *
203
- * Mistral's own first-listed use case is Language Adherence, and it pairs with a
204
- * system instruction rather than replacing one — they warn that a prefix alone
205
- * gives "noisy and unpredictable answers". Measured on this repo's own data: an
206
- * explicit language rule in the system prompt already took 5/15 wrong answers to
207
- * 0/15, and every leak began in the FIRST words ("Tak for din henvendelse"), which
208
- * is exactly what a prefix pins.
209
- *
210
- * **The SDK strips the prefix back off the response**, in `chat` and `chatStream`
211
- * alike, so a caller never has to. Mistral's own example does
212
- * `content[len(prefix):]` by hand; forgetting it puts "Here is the answer in
213
- * Norwegian:" at the top of a real customer's email — a defect that reads as
214
- * formatting rather than as a bug. */
215
- prefix?: boolean;
216
- }
217
- /** SDK-level tool definition. Adapters convert this to each provider's format
218
- * (F4.5). `parameters` is a JSON Schema object. */
219
- interface Tool {
220
- name: string;
221
- description: string;
222
- parameters: Record<string, unknown>;
223
- }
224
- /** A model's request to invoke a tool, normalized across providers (F4.5).
225
- * This is what we EMIT — `arguments` is always present on a ToolCall we return. */
226
- interface ToolCall {
227
- id: string;
228
- name: string;
229
- arguments: Record<string, unknown>;
230
- }
231
- /** What we ACCEPT when a tool call is handed BACK to us in a message history.
232
- *
233
- * F043. `@broberg/chat` spells the same field `args`, consistently across its
234
- * ModelEvent / ChatFrame / ChatTool.run. Two packages describing the same thing
235
- * with two names cost cms a production outage: a rename living in a workaround was
236
- * deleted along with the workaround, and the next call failed with
237
- * `messages.1.toolCalls.0.arguments — Required`.
238
- *
239
- * So we read both and keep emitting `arguments`. Accepting is cheap and cannot
240
- * break anyone; renaming would have broken a consumer who adopted the same day, and
241
- * asking every consumer that bridges the two packages to remember a translation is
242
- * how this happens again. Precedence is `arguments` when both are set. */
243
- type ToolCallLike = {
244
- id: string;
245
- name: string;
246
- arguments?: Record<string, unknown>;
247
- args?: Record<string, unknown>;
248
- };
249
- /** Per-call usage. Fields mirror the upmetrics `agent_runs` schema 1:1 so the
250
- * upmetricsSink (F3.7) forwards without re-mapping. `costUsd` is 0 for
251
- * subprocess (Max plan); `subprocess:true` lets dashboards split free vs paid. */
252
- interface Usage {
253
- provider: string;
254
- /** The model we ASKED for — the pricing key and the stable grouping. */
255
- model: string;
256
- /** F071.2 — the model that ANSWERED, as the provider reported it. Differs from `model`
257
- * when an alias like "mistral-large-latest" resolves to a dated model; that is how a
258
- * silent overnight move becomes visible. Unset when the provider does not say. */
259
- servedModel?: string;
260
- tier?: Tier;
261
- /** Data-residency of the endpoint that ACTUALLY answered (F042). Derived from the
262
- * host/region the request used, not from the provider's name — vertex, azure and
263
- * bfl are EU by default but a consumer can point them elsewhere.
264
- *
265
- * **Only `"eu"` is a positive residency claim.** `"unknown"` means we cannot say
266
- * (an aggregator picked its own upstream, or the region string is one we do not
267
- * recognise) — it is NOT a synonym for safe, so `region !== "us"` is not an EU check. */
268
- region: Region;
269
- transport: Transport;
270
- inputTokens: number;
271
- outputTokens: number;
272
- cacheReadTokens: number;
273
- cacheCreationTokens: number;
274
- costUsd: number;
275
- /** How `costUsd` was arrived at (F050). Absent means the same as `"computed"`;
276
- * it is optional only so that adding it could not break a consumer building a
277
- * Usage by hand.
278
- *
279
- * - `"reported"` — the PROVIDER told us what the call cost (BFL returns credits).
280
- * - `"computed"` — a price table rate × a quantity we actually measured (tokens).
281
- * - `"estimated"` — a quantity or a rate was ASSUMED. A video call with no
282
- * `durationSec` is billed at {@link DEFAULT_CLIP_SEC} seconds regardless of the
283
- * clip that came back, and fal's per-image rates are fal's own estimates.
284
- * - `"unpriced"` — we have NO price for this model, so `costUsd` is 0 because we
285
- * could not answer, not because the call was free. Those two were the same
286
- * number, and the free one is much rarer than the unknown one.
287
- *
288
- * This is a DATA field on purpose. upmetrics distinguishes reported / computed /
289
- * unpriced / untokened, and it reads fields — a JSDoc note saying "this one is a
290
- * guess" never reaches it, so an assumed number arrived there indistinguishable
291
- * from a measured one. super did exactly that and passed it on as measured. */
292
- costBasis?: "reported" | "computed" | "estimated" | "unpriced";
293
- toolCalls?: {
294
- name: string;
295
- count: number;
296
- errorCount?: number;
297
- }[];
298
- latencyMs: number;
299
- capability: Capability;
300
- purpose?: string;
301
- /** Consumer-defined attribution dimensions (e.g. {tenantId}) for per-tenant
302
- * cost breakdown — the sink forwards these (F011). */
303
- labels?: Record<string, string>;
304
- ts: string;
305
- subprocess?: true;
306
- }
307
- /** A cost reporter. Fans `Usage` out to Upmetrics / Discord / sqlite / etc.
308
- * Implementations must never throw into the caller (F3.3). */
309
- interface CostSink {
310
- record(usage: Usage): void | Promise<void>;
311
- /** F071.1 — optional: a FAILED call attempt (no cost). Sinks that sum spend (sqlite,
312
- * budget, your own) may ignore it; leaving it out means they never see failures. */
313
- recordFailure?(failure: CallFailure): void | Promise<void>;
314
- }
315
- /** Backing store for a BudgetGuard's rolling total. Default is in-memory
316
- * (per createAI instance). A persistent store (e.g. sqliteBudgetStore) makes
317
- * the rolling budget survive restarts + shared across processes (F7.1). */
318
- interface BudgetStore {
319
- getSpent(): number | Promise<number>;
320
- addSpent(usd: number): void | Promise<void>;
321
- }
322
- /** Pre-flight budget ceilings, enforced before a call fires (F3.2). */
323
- interface BudgetConfig {
324
- /** Reject a single call whose estimated cost exceeds this many USD. */
325
- perCallUsd?: number;
326
- /** Reject once cumulative spend exceeds this many USD. */
327
- rollingUsd?: number;
328
- /** Where the rolling total lives. Omit for in-memory (per instance). */
329
- store?: BudgetStore;
330
- }
331
- /** Per-call options shared by every capability: which tier, optional routing
332
- * override, optional fallback chain, and a free-text purpose for cost reports. */
333
- interface CallOptions {
334
- tier?: Tier;
335
- /** Override any part of the resolved TierSpec for this call only. */
336
- override?: Partial<TierSpec>;
337
- /** Ordered fallbacks tried if the primary route errors (inventory finding:
338
- * cms/trail/sanne/xrt81 all hand-roll this — make it first-class). */
339
- fallback?: (Tier | TierSpec)[];
340
- purpose?: string;
341
- /** Consumer-defined attribution dimensions (e.g. {tenantId}) carried onto
342
- * Usage and forwarded by the cost sink for per-tenant cost breakdown (F011). */
343
- labels?: Record<string, string>;
344
- }
345
- interface ChatRequest {
346
- messages: Message[];
347
- spec: TierSpec;
348
- tools?: Tool[];
349
- maxTokens?: number;
350
- /** F039 — Mistral prompt caching. A stable application-level id for "the same
351
- * conversation" (a conversation id, a session id). Requests sharing a prefix AND
352
- * this key reuse the cached prefix at 10% of the input rate. Not auto-generated:
353
- * only the caller knows what "the same conversation" means, and an SDK-invented
354
- * key would either collide across tenants or never hit.
355
- *
356
- * BIND IT TO THE TENANT, not only to the conversation. This key IS a shared-prefix
357
- * identity: two callers passing the same key can be served each other's cached
358
- * prefix. So two tenants with identical transcripts must still get DIFFERENT keys
359
- * — derive it from (tenant, conversation), never from the conversation alone.
360
- * (components' requirement while building @broberg/chat, 2026-08-27, where two
361
- * knowledge bases are written for readers with different permissions.) */
362
- promptCacheKey?: string;
363
- /** F039.2 — prompt caching is ON by default where the provider supports it.
364
- * Set false to opt out (e.g. a one-shot call whose prefix will never repeat).
365
- * Off has no cost benefit and no penalty; a cache MISS was measured to cost
366
- * exactly the same as a call with no key at all. */
367
- promptCache?: boolean;
368
- temperature?: number;
369
- /** F074.3 — Mistral's `reasoning_effort`. Undefined = the SDK's default: "none" for
370
- * models that think by default (Large 4), nothing for the rest. */
371
- reasoningEffort?: "none" | "high";
372
- /** "json" → request JSON-object output where the provider supports it (F009). */
373
- responseFormat?: "json" | "text";
374
- }
375
- interface ChatResult {
376
- text: string;
377
- toolCalls?: ToolCall[];
378
- usage: Usage;
379
- }
380
- /** A single event from `ai.chatStream` / `adapter.chatStream` (F8). A streamed
381
- * turn yields `text`/`tool_call` events as they arrive, one `usage` event when
382
- * the provider reports totals, and a terminal `finish` (or `error`). Tool calls
383
- * are emitted COMPLETE — accumulated across wire fragments, never partial. */
384
- type ChatStreamEvent = {
385
- type: "text";
386
- delta: string;
387
- } | {
388
- type: "tool_call";
389
- id: string;
390
- name: string;
391
- args: Record<string, unknown>;
392
- } | {
393
- type: "usage";
394
- costUsd: number;
395
- model: string;
396
- usage: Usage;
397
- } | {
398
- type: "finish";
399
- reason: "end_turn" | "tool_calls" | "length" | "stop";
400
- } | {
401
- type: "error";
402
- message: string;
403
- status?: number;
404
- };
405
- /** A trained LoRA to merge at inference time (F021). */
406
- interface LoraWeight {
407
- /** URL (or fal path) to the LoRA weights. */
408
- path: string;
409
- /** Scales the LoRA before merging (default 1). */
410
- scale?: number;
411
- }
412
- interface ImageRequest {
413
- prompt: string;
414
- spec: TierSpec;
415
- width?: number;
416
- height?: number;
417
- /** LoRAs to merge at inference (F021) — e.g. a trained brand/style LoRA. */
418
- loras?: LoraWeight[];
419
- /** F023 — a BFL finetune id (a subject trained in the BFL dashboard). Routes to the
420
- * EU-resident BFL finetuned-portrait endpoint. */
421
- finetune?: string;
422
- /** F023 — how strongly the finetune is applied (BFL finetune_strength, ~0–2). */
423
- finetuneStrength?: number;
424
- /** F023.5 — 1–8 reference photos of a subject (URL or raw bytes). Routes to the
425
- * EU-resident BFL FLUX 2 multi-reference endpoint — generate a likeness with NO
426
- * training step. Bytes are base64-inlined into the EU call (no cross-region fetch). */
427
- referenceImages?: (string | Uint8Array)[];
428
- /** F023.5 — fixed seed for reproducible output (BFL). */
429
- seed?: number;
430
- /** F023.5 — output container (BFL FLUX 2): "jpeg" | "png" | "webp". Default jpeg. */
431
- outputFormat?: "jpeg" | "png" | "webp";
432
- /** F023.5 — BFL content-moderation strictness, 0 (strict) … 6 (lax). Default 2. */
433
- safetyTolerance?: number;
434
- /** F021.4 — re-roll once with a fresh seed if fal's safety-checker false-positives
435
- * and returns a black image (has_nsfw_concepts). fal only. */
436
- retryOnBlack?: boolean;
437
- }
438
- interface ImageResult {
439
- url: string;
440
- usage: Usage;
441
- }
442
- /** Image-to-video generation (F024) — animate a still into a short clip. */
443
- interface AnimateRequest {
444
- /** Input image: a URL (passed through) or raw bytes. Where bytes are uploaded is
445
- * the ADAPTER's business — fal uses fal storage, the Gemini/Veo default inlines
446
- * them — so do not read a storage provider out of this field. */
447
- image: string | Uint8Array;
448
- /** Motion/scene prompt, e.g. "the subject turns and smiles". */
449
- prompt?: string;
450
- /** Clip length in seconds (provider-dependent; Veo ≤ 8s). */
451
- durationSec?: number;
452
- /** e.g. "720p" / "1080p" (provider-dependent). */
453
- resolution?: string;
454
- spec: TierSpec;
455
- }
456
- interface AnimateResult {
457
- /** URL to the generated video. For fal this is a public hosted URL; for the
458
- * Gemini/Veo route it is Google's file URI (needs the API key to fetch — the
459
- * bytes are also returned below, already downloaded). */
460
- url: string;
461
- /** The downloaded video bytes — set by providers whose result URL is auth-gated
462
- * or short-lived (Gemini/Veo). Absent for providers that return a public URL (fal). */
463
- bytes?: Uint8Array;
464
- /** MIME type of `bytes` (e.g. "video/mp4"). */
465
- mimeType?: string;
466
- usage: Usage;
467
- }
468
- /** Style/brand LoRA training (F021) — fal fal-ai/flux-lora-fast-training. */
469
- interface TrainStyleRequest {
470
- /** A hosted archive URL, or an array of image URLs the SDK zips in-memory. */
471
- images: string | string[];
472
- spec: TierSpec;
473
- /** Style LoRA (disables captioning/masks). Default true. */
474
- isStyle?: boolean;
475
- triggerWord?: string;
476
- /** Training steps (~1000 typical). */
477
- steps?: number;
478
- createMasks?: boolean;
479
- }
480
- interface TrainStyleResult {
481
- /** URL to the trained LoRA weights — pass to ai.image({ lora }). */
482
- loraUrl: string;
483
- /** URL to the training config file. */
484
- configUrl: string;
485
- usage: Usage;
486
- }
487
- interface EmbeddingRequest {
488
- input: string[];
489
- spec: TierSpec;
490
- }
491
- interface EmbeddingResult {
492
- vectors: number[][];
493
- usage: Usage;
494
- }
495
- /** Timestamp granularity a caller can request from `ai.transcribe` (F036). */
496
- type TimestampGranularity = "word" | "segment";
497
- /** A single word with its start/end offset in seconds. */
498
- interface WordTimestamp {
499
- word: string;
500
- start: number;
501
- end: number;
502
- }
503
- /** A phrase/sentence segment with its start/end offset in seconds. */
504
- interface SegmentTimestamp {
505
- text: string;
506
- start: number;
507
- end: number;
508
- }
509
- interface TranscribeRequest {
510
- /** Raw audio bytes (the client resolves a URL to bytes before calling). */
511
- audio: Uint8Array;
512
- language?: string;
513
- /** Audio length in seconds — enables per-minute cost (Whisper). Omit → cost 0. */
514
- durationSec?: number;
515
- /** Bias recognition toward these brand/jargon terms (Azure phraseList, F029.3).
516
- * Providers without biasing support (Voxtral/Whisper) ignore it. */
517
- phrases?: string[];
518
- /** Request timestamps (F036). The client normalizes the input to this array.
519
- * Adapters without timestamp support ignore it (result omits words/segments). */
520
- timestamps?: TimestampGranularity[];
521
- spec: TierSpec;
522
- }
523
- interface TranscribeResult {
524
- text: string;
525
- /** Word-level timing — present only when "word" timestamps were requested. */
526
- words?: WordTimestamp[];
527
- /** Segment (phrase/sentence) timing — present when any timestamps were requested. */
528
- segments?: SegmentTimestamp[];
529
- usage: Usage;
530
- }
531
- interface OcrRequest {
532
- /** A URL, data-URL, or raw bytes of the document/image. */
533
- document: string | Uint8Array;
534
- mimeType?: string;
535
- spec: TierSpec;
536
- }
537
- interface OcrPage {
538
- index: number;
539
- markdown: string;
540
- }
541
- interface OcrResult {
542
- pages: OcrPage[];
543
- usage: Usage;
544
- }
545
- interface ModerationRequest {
546
- input: string[];
547
- spec: TierSpec;
548
- }
549
- interface ModerationItem {
550
- /** True if any category tripped. */
551
- flagged: boolean;
552
- categories: Record<string, boolean>;
553
- categoryScores: Record<string, number>;
554
- }
555
- interface ModerationResult {
556
- results: ModerationItem[];
557
- usage: Usage;
558
- }
559
- /** TypeSafe's EntryType: plain text OR JSON structure. Instructions, choice option
560
- * descriptions, score levels and noul criteria all accept it — and TypeSafe's own
561
- * headline patterns (walking a taxonomy, a JSON rubric that sharpens the boundary
562
- * between options) depend on it. Measured live 2026-10-01: structured instructions and
563
- * object-valued choice options → 200. */
564
- type JudgeEntry = string | null | unknown[] | {
565
- [key: string]: unknown;
566
- };
567
- type JudgeQuestion =
568
- /** `criteria` is an OBJECT with `true`/`false`, not a string — measured live: a string
569
- * is a 422 from TypeSafe. The first version of this type had it as a string, which
570
- * let through exactly the shape the server refuses. */
571
- {
572
- type: "noul";
573
- instructions: JudgeEntry;
574
- criteria?: {
575
- true?: JudgeEntry;
576
- false?: JudgeEntry;
577
- };
578
- } | {
579
- type: "choice";
580
- instructions: JudgeEntry;
581
- criteria: Record<string, JudgeEntry>;
582
- } | {
583
- type: "score";
584
- instructions: JudgeEntry;
585
- criteria: JudgeEntry[];
586
- };
587
- interface JudgeNoulAnswer {
588
- type: "noul";
589
- /** Probability 0–1 that the answer is yes. */
590
- noul: number;
591
- }
592
- interface JudgeChoiceAnswer {
593
- type: "choice";
594
- /** The key of the most probable option. ALWAYS one of yours — Jev cannot answer
595
- * "none of these". Read `confidence` to decide whether to act on it. */
596
- choice: string;
597
- probabilities: Record<string, number>;
598
- /** How peaked the distribution is, 0–1. NOT the same as the winning probability. */
599
- confidence: number;
600
- }
601
- interface JudgeScoreAnswer {
602
- type: "score";
603
- /** Probability-weighted level; can fall BETWEEN levels (1.5). */
604
- score: number;
605
- probabilities: Record<string, number>;
606
- /** Level number → the level as you DESCRIBED it. If you passed structured levels,
607
- * the legend echoes structure, not text — measured live: {"0":{"level":"minor"}}. */
608
- legend: Record<string, JudgeEntry>;
609
- confidence: number;
610
- }
611
- type JudgeAnswer = JudgeNoulAnswer | JudgeChoiceAnswer | JudgeScoreAnswer;
612
- interface JudgeRequest {
613
- state: string | string[] | Record<string, unknown>;
614
- questions: Record<string, JudgeQuestion>;
615
- spec: TierSpec;
616
- }
617
- interface JudgeResult {
618
- answers: Record<string, JudgeAnswer>;
619
- usage: Usage;
620
- }
621
- interface DialogueTurn {
622
- text: string;
623
- voiceId: string;
624
- }
625
- interface DialogueRequest {
626
- inputs: DialogueTurn[];
627
- /** F051.4 — the pronunciation dictionary, applied to EACH line. cms measured the
628
- * gap: a two-host podcast could not get a dictionary at all, so "broberg.ai" was
629
- * said wrong in every episode — they could fix the sponsor read and the host's
630
- * hand-off (both `ai.tts`) and not the conversation, which is 95% of the audio. */
631
- pronunciations?: Pronunciation[];
632
- /** Output container, e.g. "mp3" (default). */
633
- format?: string;
634
- spec: TierSpec;
635
- }
636
- interface PodcastResult {
637
- /** Episode audio bytes. */
638
- audio: Uint8Array;
639
- mimeType: string;
640
- /** F055 — per-word timings, present only when `wordTimings` was asked for AND the
641
- * route produces them. Its ABSENCE says "not available here"; an empty `words` array
642
- * would say "the text had no words", which is a different claim.
643
- *
644
- * `sourceStart`/`sourceEnd` index the ORIGINAL text you passed, not the SSML we sent
645
- * — Azure reports only audio time, so the link back to the manuscript is derived
646
- * here. `unaligned` names any spoken word that could not be placed. */
647
- wordTimings?: AlignedWordTimings;
648
- /** F055.4 — the EXACT markup we sent the provider, verbatim, not rebuilt.
649
- *
650
- * Why it exists: the text you passed is not what was spoken. A pronunciation
651
- * dictionary rewrites it, so `text` is a RETELLING of the audio — and without this
652
- * field a consumer cannot check our retelling any more than we could check theirs.
653
- * cms filed exactly that (11 September 2026) while we were asking them for markup
654
- * only we could produce.
655
- *
656
- * UNDEFINED when the route builds no markup (ElevenLabs routes by voice, not SSML).
657
- * An empty string would say "we sent empty markup", which is a different claim. */
658
- ssml?: string;
659
- usage: Usage;
660
- }
661
-
662
- interface TtsRequest {
663
- text: string;
664
- voiceId: string;
665
- /** BCP-47 locale (e.g. "da-DK"). Azure uses it for SSML xml:lang; ElevenLabs ignores it. */
666
- lang?: string;
667
- /** Provider output-format hint (e.g. an Azure X-Microsoft-OutputFormat); ElevenLabs ignores it. */
668
- format?: string;
669
- /** Speaking-rate multiplier (Azure): 1 = normal, 0.9 = 10% slower, 1.1 = faster. ElevenLabs ignores it. */
670
- rate?: number;
671
- /** F051 — pronunciation dictionary. A Danish voice says English jargon wrongly:
672
- * measured on da-DK, "AI" comes out as the word "aj", "native" as "nativ".
673
- *
674
- * Azure renders these as SSML (`<sub alias>` / `<phoneme alphabet="ipa" ph>`);
675
- * ElevenLabs has no SSML and can only apply `alias`. **This is the CONTROLLED DOOR
676
- * into SSML** — the substitution happens adapter-side AFTER the text is escaped, so
677
- * `text` can never inject markup, and `alias`/`ipa` are escaped too. */
678
- pronunciations?: Pronunciation[];
679
- /** F055 — ask for per-word timings so a reader can highlight each word as it is
680
- * spoken. Azure only. Absent from the result means "this route does not produce
681
- * them", which is a different answer from an empty list.
682
- *
683
- * **This changes the ROUTE, not just the payload.** The real-time endpoint returns
684
- * audio only; word boundaries exist solely on Azure's asynchronous batch synthesis
685
- * API, so the call becomes submit → poll → fetch. Microsoft quotes 10–20s for half
686
- * of all jobs and up to 120s for 95%. Worth it for a pre-generated, cached reading;
687
- * wrong for anything a user is waiting on. */
688
- wordTimings?: boolean;
689
- spec: TierSpec;
690
- }
691
- interface BatchRequestItem {
692
- customId: string;
693
- prompt: string;
694
- }
695
- interface BatchJob {
696
- jobId: string;
697
- status: string;
698
- total?: number;
699
- completed?: number;
700
- }
701
- interface BatchResultItem {
702
- customId: string;
703
- text: string;
704
- }
705
- /** The thin contract every provider implements (F4). A provider need only
706
- * support the capabilities it offers — `chat` is the baseline; vision/image/
707
- * embedding are optional and absence is a typed capability gap. */
708
- interface ProviderAdapter {
709
- readonly name: string;
710
- /** Every capability is optional — an adapter implements only what it supports
711
- * (e.g. fal does image only). The client guards each call and throws a clear
712
- * "provider X does not support Y" when a capability is absent. */
713
- chat?(req: ChatRequest): Promise<ChatResult>;
714
- /** Streaming chat (F8). Optional — absence is a typed "no streaming support".
715
- * Same request shape as chat; yields ChatStreamEvents as the turn unfolds. */
716
- chatStream?(req: ChatRequest): AsyncIterable<ChatStreamEvent>;
717
- /** Dedicated translation engine (F032) — e.g. DeepL. When absent, `ai.translate`
718
- * falls back to a chat prompt-contract (the historical default for every
719
- * other provider). `to`/`from` are provider-specific: a chat-routed call
720
- * accepts free-form names ("Danish"); DeepL requires real codes ("DA"). */
721
- translate?(req: TranslateRequest): Promise<TranslateResult>;
722
- vision?(req: ChatRequest): Promise<ChatResult>;
723
- image?(req: ImageRequest): Promise<ImageResult>;
724
- /** Image-to-video generation (F024) — animate a still into a short clip. gemini
725
- * (Veo 3.1) by default; override to fal for Kling/Seedance. Name only the DEFAULT
726
- * route here — provider-doc-drift.test.ts fails if this and DEFAULT_ANIMATE_SPEC
727
- * disagree, because this sentence is the editor tooltip a consumer reads when
728
- * deciding which API key to buy. */
729
- animate?(req: AnimateRequest): Promise<AnimateResult>;
730
- /** Train a style/brand LoRA from images (F021). fal. */
731
- trainStyle?(req: TrainStyleRequest): Promise<TrainStyleResult>;
732
- embedding?(req: EmbeddingRequest): Promise<EmbeddingResult>;
733
- transcribe?(req: TranscribeRequest): Promise<TranscribeResult>;
734
- ocr?(req: OcrRequest): Promise<OcrResult>;
735
- moderate?(req: ModerationRequest): Promise<ModerationResult>;
736
- /** F066 — typed decisions with calibrated probabilities (TypeSafe Jev). */
737
- judge?(req: JudgeRequest): Promise<JudgeResult>;
738
- /** Multi-voice dialogue → one audio episode (F020). ElevenLabs. */
739
- dialogue?(req: DialogueRequest): Promise<PodcastResult>;
740
- /** Single-voice TTS (F020.4) → audio. ElevenLabs. */
741
- tts?(req: TtsRequest): Promise<PodcastResult>;
742
- /** Batch (F016.1) — async chat-request processing at 50% cost. Mistral. */
743
- batchSubmit?(req: {
744
- items: BatchRequestItem[];
745
- spec: TierSpec;
746
- }): Promise<BatchJob>;
747
- batchStatus?(req: {
748
- jobId: string;
749
- spec: TierSpec;
750
- }): Promise<BatchJob>;
751
- batchResults?(req: {
752
- jobId: string;
753
- spec: TierSpec;
754
- }): Promise<BatchResultItem[]>;
755
- }
756
- interface TranslateResult {
757
- text: string;
758
- usage: Usage;
759
- }
760
- /** Dedicated-engine translation request (F032) — used only by adapters that
761
- * implement `ProviderAdapter.translate` directly (e.g. DeepL); chat-routed
762
- * providers never see this shape, they get a built prompt instead. */
763
- interface TranslateRequest {
764
- text: string;
765
- to: string;
766
- from?: string;
767
- spec: TierSpec;
768
- }
769
-
770
6
  interface MockupInput {
771
7
  description: string;
772
8
  constraints?: string;
@@ -1060,6 +296,7 @@ declare const chatInputSchema: z.ZodObject<{
1060
296
  transport: "http" | "subprocess";
1061
297
  }>]>, "many">>;
1062
298
  purpose: z.ZodOptional<z.ZodString>;
299
+ allowFloating: z.ZodOptional<z.ZodBoolean>;
1063
300
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1064
301
  /** F039 — reuse a cached prompt prefix on Mistral at 10% of the input rate.
1065
302
  * A stable id for "the same conversation" (conversation id, session id).
@@ -1228,6 +465,7 @@ declare const chatInputSchema: z.ZodObject<{
1228
465
  model: string;
1229
466
  transport: "http" | "subprocess";
1230
467
  })[] | undefined;
468
+ allowFloating?: boolean | undefined;
1231
469
  labels?: Record<string, string> | undefined;
1232
470
  }, {
1233
471
  system?: string | undefined;
@@ -1274,6 +512,7 @@ declare const chatInputSchema: z.ZodObject<{
1274
512
  model: string;
1275
513
  transport: "http" | "subprocess";
1276
514
  })[] | undefined;
515
+ allowFloating?: boolean | undefined;
1277
516
  labels?: Record<string, string> | undefined;
1278
517
  }>;
1279
518
  declare const visionInputSchema: z.ZodObject<{
@@ -1305,6 +544,7 @@ declare const visionInputSchema: z.ZodObject<{
1305
544
  transport: "http" | "subprocess";
1306
545
  }>]>, "many">>;
1307
546
  purpose: z.ZodOptional<z.ZodString>;
547
+ allowFloating: z.ZodOptional<z.ZodBoolean>;
1308
548
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1309
549
  image: z.ZodUnion<[z.ZodString, z.ZodType<Uint8Array<ArrayBuffer>, z.ZodTypeDef, Uint8Array<ArrayBuffer>>]>;
1310
550
  prompt: z.ZodString;
@@ -1329,6 +569,7 @@ declare const visionInputSchema: z.ZodObject<{
1329
569
  model: string;
1330
570
  transport: "http" | "subprocess";
1331
571
  })[] | undefined;
572
+ allowFloating?: boolean | undefined;
1332
573
  labels?: Record<string, string> | undefined;
1333
574
  }, {
1334
575
  image: string | Uint8Array<ArrayBuffer>;
@@ -1347,6 +588,7 @@ declare const visionInputSchema: z.ZodObject<{
1347
588
  model: string;
1348
589
  transport: "http" | "subprocess";
1349
590
  })[] | undefined;
591
+ allowFloating?: boolean | undefined;
1350
592
  labels?: Record<string, string> | undefined;
1351
593
  }>;
1352
594
  declare const videoInputSchema: z.ZodObject<{
@@ -1378,6 +620,7 @@ declare const videoInputSchema: z.ZodObject<{
1378
620
  transport: "http" | "subprocess";
1379
621
  }>]>, "many">>;
1380
622
  purpose: z.ZodOptional<z.ZodString>;
623
+ allowFloating: z.ZodOptional<z.ZodBoolean>;
1381
624
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1382
625
  video: z.ZodUnion<[z.ZodString, z.ZodType<Uint8Array<ArrayBuffer>, z.ZodTypeDef, Uint8Array<ArrayBuffer>>]>;
1383
626
  prompt: z.ZodString;
@@ -1401,6 +644,7 @@ declare const videoInputSchema: z.ZodObject<{
1401
644
  model: string;
1402
645
  transport: "http" | "subprocess";
1403
646
  })[] | undefined;
647
+ allowFloating?: boolean | undefined;
1404
648
  labels?: Record<string, string> | undefined;
1405
649
  }, {
1406
650
  video: string | Uint8Array<ArrayBuffer>;
@@ -1419,6 +663,7 @@ declare const videoInputSchema: z.ZodObject<{
1419
663
  model: string;
1420
664
  transport: "http" | "subprocess";
1421
665
  })[] | undefined;
666
+ allowFloating?: boolean | undefined;
1422
667
  labels?: Record<string, string> | undefined;
1423
668
  }>;
1424
669
  declare const translateInputSchema: z.ZodObject<{
@@ -1450,6 +695,7 @@ declare const translateInputSchema: z.ZodObject<{
1450
695
  transport: "http" | "subprocess";
1451
696
  }>]>, "many">>;
1452
697
  purpose: z.ZodOptional<z.ZodString>;
698
+ allowFloating: z.ZodOptional<z.ZodBoolean>;
1453
699
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1454
700
  text: z.ZodString;
1455
701
  to: z.ZodString;
@@ -1469,6 +715,7 @@ declare const translateInputSchema: z.ZodObject<{
1469
715
  model: string;
1470
716
  transport: "http" | "subprocess";
1471
717
  })[] | undefined;
718
+ allowFloating?: boolean | undefined;
1472
719
  labels?: Record<string, string> | undefined;
1473
720
  from?: string | undefined;
1474
721
  }, {
@@ -1486,6 +733,7 @@ declare const translateInputSchema: z.ZodObject<{
1486
733
  model: string;
1487
734
  transport: "http" | "subprocess";
1488
735
  })[] | undefined;
736
+ allowFloating?: boolean | undefined;
1489
737
  labels?: Record<string, string> | undefined;
1490
738
  from?: string | undefined;
1491
739
  }>;
@@ -1518,6 +766,7 @@ declare const imageInputSchema: z.ZodObject<{
1518
766
  transport: "http" | "subprocess";
1519
767
  }>]>, "many">>;
1520
768
  purpose: z.ZodOptional<z.ZodString>;
769
+ allowFloating: z.ZodOptional<z.ZodBoolean>;
1521
770
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1522
771
  prompt: z.ZodString;
1523
772
  width: z.ZodOptional<z.ZodNumber>;
@@ -1574,6 +823,7 @@ declare const imageInputSchema: z.ZodObject<{
1574
823
  model: string;
1575
824
  transport: "http" | "subprocess";
1576
825
  })[] | undefined;
826
+ allowFloating?: boolean | undefined;
1577
827
  labels?: Record<string, string> | undefined;
1578
828
  finetune?: string | undefined;
1579
829
  finetuneStrength?: number | undefined;
@@ -1603,6 +853,7 @@ declare const imageInputSchema: z.ZodObject<{
1603
853
  model: string;
1604
854
  transport: "http" | "subprocess";
1605
855
  })[] | undefined;
856
+ allowFloating?: boolean | undefined;
1606
857
  labels?: Record<string, string> | undefined;
1607
858
  finetune?: string | undefined;
1608
859
  finetuneStrength?: number | undefined;
@@ -1639,6 +890,7 @@ declare const animateInputSchema: z.ZodObject<{
1639
890
  transport: "http" | "subprocess";
1640
891
  }>]>, "many">>;
1641
892
  purpose: z.ZodOptional<z.ZodString>;
893
+ allowFloating: z.ZodOptional<z.ZodBoolean>;
1642
894
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1643
895
  /** Input image: a URL or raw bytes. Where bytes are uploaded is the ADAPTER's
1644
896
  * business — fal uses fal storage, the Gemini/Veo default inlines them. */
@@ -1665,6 +917,7 @@ declare const animateInputSchema: z.ZodObject<{
1665
917
  model: string;
1666
918
  transport: "http" | "subprocess";
1667
919
  })[] | undefined;
920
+ allowFloating?: boolean | undefined;
1668
921
  labels?: Record<string, string> | undefined;
1669
922
  durationSec?: number | undefined;
1670
923
  }, {
@@ -1683,6 +936,7 @@ declare const animateInputSchema: z.ZodObject<{
1683
936
  model: string;
1684
937
  transport: "http" | "subprocess";
1685
938
  })[] | undefined;
939
+ allowFloating?: boolean | undefined;
1686
940
  labels?: Record<string, string> | undefined;
1687
941
  durationSec?: number | undefined;
1688
942
  }>;
@@ -1715,6 +969,7 @@ declare const trainStyleInputSchema: z.ZodObject<{
1715
969
  transport: "http" | "subprocess";
1716
970
  }>]>, "many">>;
1717
971
  purpose: z.ZodOptional<z.ZodString>;
972
+ allowFloating: z.ZodOptional<z.ZodBoolean>;
1718
973
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1719
974
  /** A hosted archive URL, or an array of image URLs the SDK zips in-memory. */
1720
975
  images: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
@@ -1738,6 +993,7 @@ declare const trainStyleInputSchema: z.ZodObject<{
1738
993
  model: string;
1739
994
  transport: "http" | "subprocess";
1740
995
  })[] | undefined;
996
+ allowFloating?: boolean | undefined;
1741
997
  labels?: Record<string, string> | undefined;
1742
998
  isStyle?: boolean | undefined;
1743
999
  triggerWord?: string | undefined;
@@ -1757,6 +1013,7 @@ declare const trainStyleInputSchema: z.ZodObject<{
1757
1013
  model: string;
1758
1014
  transport: "http" | "subprocess";
1759
1015
  })[] | undefined;
1016
+ allowFloating?: boolean | undefined;
1760
1017
  labels?: Record<string, string> | undefined;
1761
1018
  isStyle?: boolean | undefined;
1762
1019
  triggerWord?: string | undefined;
@@ -1791,6 +1048,7 @@ declare const embeddingInputSchema: z.ZodObject<{
1791
1048
  transport: "http" | "subprocess";
1792
1049
  }>]>, "many">>;
1793
1050
  purpose: z.ZodOptional<z.ZodString>;
1051
+ allowFloating: z.ZodOptional<z.ZodBoolean>;
1794
1052
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1795
1053
  text: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
1796
1054
  }, "strip", z.ZodTypeAny, {
@@ -1807,6 +1065,7 @@ declare const embeddingInputSchema: z.ZodObject<{
1807
1065
  model: string;
1808
1066
  transport: "http" | "subprocess";
1809
1067
  })[] | undefined;
1068
+ allowFloating?: boolean | undefined;
1810
1069
  labels?: Record<string, string> | undefined;
1811
1070
  }, {
1812
1071
  text: string | string[];
@@ -1822,6 +1081,7 @@ declare const embeddingInputSchema: z.ZodObject<{
1822
1081
  model: string;
1823
1082
  transport: "http" | "subprocess";
1824
1083
  })[] | undefined;
1084
+ allowFloating?: boolean | undefined;
1825
1085
  labels?: Record<string, string> | undefined;
1826
1086
  }>;
1827
1087
  declare const transcribeInputSchema: z.ZodObject<{
@@ -1853,6 +1113,7 @@ declare const transcribeInputSchema: z.ZodObject<{
1853
1113
  transport: "http" | "subprocess";
1854
1114
  }>]>, "many">>;
1855
1115
  purpose: z.ZodOptional<z.ZodString>;
1116
+ allowFloating: z.ZodOptional<z.ZodBoolean>;
1856
1117
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1857
1118
  /** Audio URL or raw bytes. */
1858
1119
  audio: z.ZodUnion<[z.ZodString, z.ZodType<Uint8Array<ArrayBuffer>, z.ZodTypeDef, Uint8Array<ArrayBuffer>>]>;
@@ -1881,6 +1142,7 @@ declare const transcribeInputSchema: z.ZodObject<{
1881
1142
  model: string;
1882
1143
  transport: "http" | "subprocess";
1883
1144
  })[] | undefined;
1145
+ allowFloating?: boolean | undefined;
1884
1146
  labels?: Record<string, string> | undefined;
1885
1147
  durationSec?: number | undefined;
1886
1148
  phrases?: string[] | undefined;
@@ -1900,6 +1162,7 @@ declare const transcribeInputSchema: z.ZodObject<{
1900
1162
  model: string;
1901
1163
  transport: "http" | "subprocess";
1902
1164
  })[] | undefined;
1165
+ allowFloating?: boolean | undefined;
1903
1166
  labels?: Record<string, string> | undefined;
1904
1167
  durationSec?: number | undefined;
1905
1168
  phrases?: string[] | undefined;
@@ -1934,6 +1197,7 @@ declare const ocrInputSchema: z.ZodObject<{
1934
1197
  transport: "http" | "subprocess";
1935
1198
  }>]>, "many">>;
1936
1199
  purpose: z.ZodOptional<z.ZodString>;
1200
+ allowFloating: z.ZodOptional<z.ZodBoolean>;
1937
1201
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1938
1202
  /** A URL, data-URL, or raw bytes of the document/image. */
1939
1203
  document: z.ZodUnion<[z.ZodString, z.ZodType<Uint8Array<ArrayBuffer>, z.ZodTypeDef, Uint8Array<ArrayBuffer>>]>;
@@ -1954,6 +1218,7 @@ declare const ocrInputSchema: z.ZodObject<{
1954
1218
  model: string;
1955
1219
  transport: "http" | "subprocess";
1956
1220
  })[] | undefined;
1221
+ allowFloating?: boolean | undefined;
1957
1222
  labels?: Record<string, string> | undefined;
1958
1223
  }, {
1959
1224
  document: string | Uint8Array<ArrayBuffer>;
@@ -1970,6 +1235,7 @@ declare const ocrInputSchema: z.ZodObject<{
1970
1235
  model: string;
1971
1236
  transport: "http" | "subprocess";
1972
1237
  })[] | undefined;
1238
+ allowFloating?: boolean | undefined;
1973
1239
  labels?: Record<string, string> | undefined;
1974
1240
  }>;
1975
1241
  declare const moderationInputSchema: z.ZodObject<{
@@ -2001,6 +1267,7 @@ declare const moderationInputSchema: z.ZodObject<{
2001
1267
  transport: "http" | "subprocess";
2002
1268
  }>]>, "many">>;
2003
1269
  purpose: z.ZodOptional<z.ZodString>;
1270
+ allowFloating: z.ZodOptional<z.ZodBoolean>;
2004
1271
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
2005
1272
  input: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
2006
1273
  }, "strip", z.ZodTypeAny, {
@@ -2017,6 +1284,7 @@ declare const moderationInputSchema: z.ZodObject<{
2017
1284
  model: string;
2018
1285
  transport: "http" | "subprocess";
2019
1286
  })[] | undefined;
1287
+ allowFloating?: boolean | undefined;
2020
1288
  labels?: Record<string, string> | undefined;
2021
1289
  }, {
2022
1290
  input: string | string[];
@@ -2032,6 +1300,7 @@ declare const moderationInputSchema: z.ZodObject<{
2032
1300
  model: string;
2033
1301
  transport: "http" | "subprocess";
2034
1302
  })[] | undefined;
1303
+ allowFloating?: boolean | undefined;
2035
1304
  labels?: Record<string, string> | undefined;
2036
1305
  }>;
2037
1306
  declare const judgeInputSchema: z.ZodObject<{
@@ -2063,6 +1332,7 @@ declare const judgeInputSchema: z.ZodObject<{
2063
1332
  transport: "http" | "subprocess";
2064
1333
  }>]>, "many">>;
2065
1334
  purpose: z.ZodOptional<z.ZodString>;
1335
+ allowFloating: z.ZodOptional<z.ZodBoolean>;
2066
1336
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
2067
1337
  state: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">, z.ZodRecord<z.ZodString, z.ZodUnknown>]>;
2068
1338
  questions: z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
@@ -2177,6 +1447,7 @@ declare const judgeInputSchema: z.ZodObject<{
2177
1447
  model: string;
2178
1448
  transport: "http" | "subprocess";
2179
1449
  })[] | undefined;
1450
+ allowFloating?: boolean | undefined;
2180
1451
  labels?: Record<string, string> | undefined;
2181
1452
  }, {
2182
1453
  state: string | string[] | Record<string, unknown>;
@@ -2208,6 +1479,7 @@ declare const judgeInputSchema: z.ZodObject<{
2208
1479
  model: string;
2209
1480
  transport: "http" | "subprocess";
2210
1481
  })[] | undefined;
1482
+ allowFloating?: boolean | undefined;
2211
1483
  labels?: Record<string, string> | undefined;
2212
1484
  }>;
2213
1485
  declare const podcastInputSchema: z.ZodObject<{
@@ -2239,6 +1511,7 @@ declare const podcastInputSchema: z.ZodObject<{
2239
1511
  transport: "http" | "subprocess";
2240
1512
  }>]>, "many">>;
2241
1513
  purpose: z.ZodOptional<z.ZodString>;
1514
+ allowFloating: z.ZodOptional<z.ZodBoolean>;
2242
1515
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
2243
1516
  script: z.ZodArray<z.ZodObject<{
2244
1517
  speaker: z.ZodString;
@@ -2300,6 +1573,7 @@ declare const podcastInputSchema: z.ZodObject<{
2300
1573
  model: string;
2301
1574
  transport: "http" | "subprocess";
2302
1575
  })[] | undefined;
1576
+ allowFloating?: boolean | undefined;
2303
1577
  labels?: Record<string, string> | undefined;
2304
1578
  format?: string | undefined;
2305
1579
  }, {
@@ -2327,6 +1601,7 @@ declare const podcastInputSchema: z.ZodObject<{
2327
1601
  model: string;
2328
1602
  transport: "http" | "subprocess";
2329
1603
  })[] | undefined;
1604
+ allowFloating?: boolean | undefined;
2330
1605
  labels?: Record<string, string> | undefined;
2331
1606
  format?: string | undefined;
2332
1607
  }>;
@@ -2359,6 +1634,7 @@ declare const ttsInputSchema: z.ZodObject<{
2359
1634
  transport: "http" | "subprocess";
2360
1635
  }>]>, "many">>;
2361
1636
  purpose: z.ZodOptional<z.ZodString>;
1637
+ allowFloating: z.ZodOptional<z.ZodBoolean>;
2362
1638
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
2363
1639
  text: z.ZodString;
2364
1640
  voice: z.ZodString;
@@ -2423,6 +1699,7 @@ declare const ttsInputSchema: z.ZodObject<{
2423
1699
  model: string;
2424
1700
  transport: "http" | "subprocess";
2425
1701
  })[] | undefined;
1702
+ allowFloating?: boolean | undefined;
2426
1703
  labels?: Record<string, string> | undefined;
2427
1704
  lang?: string | undefined;
2428
1705
  format?: string | undefined;
@@ -2451,6 +1728,7 @@ declare const ttsInputSchema: z.ZodObject<{
2451
1728
  model: string;
2452
1729
  transport: "http" | "subprocess";
2453
1730
  })[] | undefined;
1731
+ allowFloating?: boolean | undefined;
2454
1732
  labels?: Record<string, string> | undefined;
2455
1733
  lang?: string | undefined;
2456
1734
  format?: string | undefined;
@@ -2467,6 +1745,8 @@ declare const aiConfigSchema: z.ZodObject<{
2467
1745
  /** F039.2 — client-wide opt-out from prompt caching (default: on where the
2468
1746
  * provider supports it). A per-call `promptCache` wins over this. */
2469
1747
  promptCache: z.ZodOptional<z.ZodBoolean>;
1748
+ /** F077.3 — refuse any "-latest" model id unless the call passes allowFloating: true. */
1749
+ strictPinning: z.ZodOptional<z.ZodBoolean>;
2470
1750
  defaults: z.ZodOptional<z.ZodRecord<z.ZodEnum<["fast", "smart", "powerful", "cheap", "vision", "video", "embedding"]>, z.ZodObject<{
2471
1751
  provider: z.ZodString;
2472
1752
  model: z.ZodString;
@@ -2509,6 +1789,7 @@ declare const aiConfigSchema: z.ZodObject<{
2509
1789
  promptCache?: boolean | undefined;
2510
1790
  labels?: Record<string, string> | undefined;
2511
1791
  byok?: boolean | undefined;
1792
+ strictPinning?: boolean | undefined;
2512
1793
  defaults?: Partial<Record<"vision" | "video" | "embedding" | "fast" | "smart" | "powerful" | "cheap", {
2513
1794
  provider: string;
2514
1795
  model: string;
@@ -2528,6 +1809,7 @@ declare const aiConfigSchema: z.ZodObject<{
2528
1809
  promptCache?: boolean | undefined;
2529
1810
  labels?: Record<string, string> | undefined;
2530
1811
  byok?: boolean | undefined;
1812
+ strictPinning?: boolean | undefined;
2531
1813
  defaults?: Partial<Record<"vision" | "video" | "embedding" | "fast" | "smart" | "powerful" | "cheap", {
2532
1814
  provider: string;
2533
1815
  model: string;
@@ -2950,8 +2232,8 @@ declare const falStubAdapter: ProviderAdapter;
2950
2232
  * wires the live adapters. */
2951
2233
  declare const stubProviders: Record<string, ProviderAdapter>;
2952
2234
 
2953
- declare const VERSION: "0.55.3";
2954
- declare const SDK_TAG: "@broberg/ai-sdk@0.55.3";
2235
+ declare const VERSION: "0.56.1";
2236
+ declare const SDK_TAG: "@broberg/ai-sdk@0.56.1";
2955
2237
 
2956
2238
  /** Built-in defaults. Every entry is overridable via AiConfig.defaults or a
2957
2239
  * per-call override.
@@ -3476,4 +2758,4 @@ interface StreamTransportRequest extends TransportRequest {
3476
2758
  */
3477
2759
  declare function streamTransport(req: StreamTransportRequest): AsyncIterable<string>;
3478
2760
 
3479
- export { AZURE_DANISH_VOICES, AZURE_DANISH_VOICE_LIST, type AiClient, type AiConfig, type AlignedWordTimings, type AzureVoiceInfo, type AzureWordBoundary, type BatchJob, type BatchRequestItem, type BatchResultItem, type BflAdapterConfig, type BflCredits, type BudgetConfig, BudgetExceededError, BudgetGuard, type BudgetStore, CONFIG_DERIVED_HOSTS, type CallOptions, type Capability, type ChatInput, type ChatRequest, type ChatResult, type ChatStreamEvent, type CheckVoiceOptions, type ClassifyInput, type ClassifyResult, type ContentPart, type Contracts, type CostQuery, type CostSink, type CostSummary, type CostSummaryQuery, type CostTimeseriesQuery, DEFAULT_BASE_URLS, DEFAULT_TIER_MAP, type DesignInput, type DesignResult, type DialogueRequest, type DialogueTurn, type DiscordSinkConfig, ELEVENLABS_DANISH_VOICES, type EmbeddingInput, type EmbeddingRequest, type EmbeddingResult, type ExtractInput, type ExtractResult, type FalAdapterConfig, type FixedHostProvider, type HttpResponse, type ImageInput, type ImageRequest, type ImageResult, type JudgeAnswer, type JudgeChoiceAnswer, type JudgeInput, type JudgeNoulAnswer, type JudgeQuestion, type JudgeResult, type JudgeScoreAnswer, LOCALLY_PINNED_HOSTS, type LoraWeight, type Message, type MockupInput, type MockupResult, type ModerationInput, type ModerationItem, type ModerationRequest, type ModerationResult, type OcrInput, type OcrPage, type OcrRequest, type OcrResult, type OpenAICompatibleConfig, type PodcastInput, type PodcastResult, type PriceDriftResult, type PriceDriftRow, type PricingEntry, type ProviderAdapter, type RefreshOptions, type RefreshResult, type Region, type RerankInput, type RerankResult, type Role, type RouteForecast, SDK_TAG, type SqliteBudgetStoreConfig, type SqliteSinkConfig, StreamHttpError, type SubprocessResponse, type Tier, type TierSpec, type Tool, type ToolCall, type TrainStyleInput, type TrainStyleRequest, type TrainStyleResult, type TranscribeInput, type TranscribeRequest, type TranscribeResult, type TranslateInput, type TranslateResult, type Transport, type TransportRequest, type TransportResponse, type TtsInput, type TtsRequest, type UpmetricsCostClientConfig, UpmetricsCostError, type UpmetricsCostRow, type UpmetricsCostSummary, type UpmetricsCostTimeseries, type UpmetricsSink, type UpmetricsSinkConfig, type UpmetricsSinkStats, type Usage, VERSION, type VideoInput, type VisionInput, type VoiceInfo, type VoiceProvider, type VoiceResolveResult, type VoiceStatus, VoiceUnavailableError, type WordTiming, aiConfigSchema, alignWordTimings, anthropicAdapter, anthropicApiAdapter, anthropicSubprocessAdapter, azureAdapter, bflAdapter, bflCredits, byokAdapter, chatInputSchema, checkPriceDrift, checkVoice, classifyRegionName, computeCost, createAI, deepinfraAdapter, deeplAdapter, deepseekAdapter, defaultBaseUrl, defaultProviders, discordSink, elevenlabsAdapter, embeddingInputSchema, falAdapter, falStubAdapter, freshUsage, fromProviderToolCall, geminiAdapter, getCostSummary, getPrice, httpTransport, imageInputSchema, isByokKeyed, listAzureDanishVoices, listVoices, makeContracts, makeOpenAICompatibleAdapter, matchLabel, messageSchema, mistralAdapter, mistralStubAdapter, multiSink, noopSink, openaiAdapter, openaiStubAdapter, openrouterAdapter, parseClaudeCliJson, parseJsonLoose, refreshAvailability, regionOfHost, regionOfProvider, requestyAdapter, resetRefreshState, resetRegistry, resolveAzureVoice, resolveTier, resolveVoice, sqliteBudgetStore, sqliteSink, streamTransport, stubProviders, subprocessTransport, tierSpecSchema, toProviderTools, toolSchema, translateInputSchema, typesafeAdapter, upmetricsCostClient, upmetricsSink, usdFromMicro, vertexAdapter, visionInputSchema, wouldProviderRouteTo, wouldRouteTo };
2761
+ export { AZURE_DANISH_VOICES, AZURE_DANISH_VOICE_LIST, type AiClient, type AiConfig, type AzureVoiceInfo, BatchJob, BatchRequestItem, BatchResultItem, type BflAdapterConfig, type BflCredits, BudgetConfig, BudgetExceededError, BudgetGuard, BudgetStore, CONFIG_DERIVED_HOSTS, Capability, type ChatInput, ChatResult, ChatStreamEvent, type CheckVoiceOptions, type ClassifyInput, type ClassifyResult, type Contracts, type CostQuery, CostSink, type CostSummary, type CostSummaryQuery, type CostTimeseriesQuery, DEFAULT_BASE_URLS, DEFAULT_TIER_MAP, type DesignInput, type DesignResult, type DiscordSinkConfig, ELEVENLABS_DANISH_VOICES, type EmbeddingInput, EmbeddingResult, type ExtractInput, type ExtractResult, type FalAdapterConfig, type FixedHostProvider, type HttpResponse, type ImageInput, ImageResult, type JudgeInput, JudgeResult, LOCALLY_PINNED_HOSTS, type MockupInput, type MockupResult, type ModerationInput, ModerationResult, type OcrInput, OcrResult, type OpenAICompatibleConfig, type PodcastInput, PodcastResult, type PriceDriftResult, type PriceDriftRow, type PricingEntry, ProviderAdapter, type RefreshOptions, type RefreshResult, Region, type RerankInput, type RerankResult, type RouteForecast, SDK_TAG, type SqliteBudgetStoreConfig, type SqliteSinkConfig, StreamHttpError, type SubprocessResponse, Tier, TierSpec, Tool, ToolCall, type TrainStyleInput, TrainStyleResult, type TranscribeInput, TranscribeResult, type TranslateInput, TranslateResult, Transport, type TransportRequest, type TransportResponse, type TtsInput, type UpmetricsCostClientConfig, UpmetricsCostError, type UpmetricsCostRow, type UpmetricsCostSummary, type UpmetricsCostTimeseries, type UpmetricsSink, type UpmetricsSinkConfig, type UpmetricsSinkStats, Usage, VERSION, type VideoInput, type VisionInput, type VoiceInfo, type VoiceProvider, type VoiceResolveResult, type VoiceStatus, VoiceUnavailableError, aiConfigSchema, anthropicAdapter, anthropicApiAdapter, anthropicSubprocessAdapter, azureAdapter, bflAdapter, bflCredits, byokAdapter, chatInputSchema, checkPriceDrift, checkVoice, computeCost, createAI, deepinfraAdapter, deeplAdapter, deepseekAdapter, defaultBaseUrl, defaultProviders, discordSink, elevenlabsAdapter, embeddingInputSchema, falAdapter, falStubAdapter, freshUsage, fromProviderToolCall, geminiAdapter, getCostSummary, getPrice, httpTransport, imageInputSchema, isByokKeyed, listAzureDanishVoices, listVoices, makeContracts, makeOpenAICompatibleAdapter, matchLabel, messageSchema, mistralAdapter, mistralStubAdapter, multiSink, noopSink, openaiAdapter, openaiStubAdapter, openrouterAdapter, parseClaudeCliJson, parseJsonLoose, refreshAvailability, requestyAdapter, resetRefreshState, resetRegistry, resolveAzureVoice, resolveTier, resolveVoice, sqliteBudgetStore, sqliteSink, streamTransport, stubProviders, subprocessTransport, tierSpecSchema, toProviderTools, toolSchema, translateInputSchema, typesafeAdapter, upmetricsCostClient, upmetricsSink, usdFromMicro, vertexAdapter, visionInputSchema, wouldProviderRouteTo, wouldRouteTo };