@broberg/ai-sdk 0.21.1 → 0.23.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.
- package/dist/index.d.ts +45 -7
- package/dist/index.js +289 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routing/tier-map.ts","../src/transport/http.ts","../src/transport/subprocess.ts","../src/transport/stream.ts","../src/providers/tools.ts","../src/cost/usage.ts","../src/providers/anthropic.ts","../src/providers/openai-compatible.ts","../src/providers/openai.ts","../src/providers/gemini.ts","../src/providers/deepinfra.ts","../src/providers/openrouter.ts","../src/providers/requesty.ts","../src/providers/deepseek.ts","../src/providers/mistral.ts","../src/providers/elevenlabs.ts","../src/providers/azure.ts","../src/providers/fal.ts","../src/providers/bfl.ts","../src/providers/registry.ts","../src/cost/budget.ts","../src/capabilities/vision.ts","../src/capabilities/video.ts","../src/capabilities/translate.ts","../src/capabilities/embedding.ts","../src/capabilities/transcribe.ts","../src/capabilities/contracts/index.ts","../src/schema/inputs.ts","../src/client.ts","../src/providers/stub.ts","../src/version.ts","../src/availability/refresh.ts","../src/cost/budget-store.ts","../src/cost/sinks/noop.ts","../src/cost/sinks/multi.ts","../src/cost/sinks/upmetrics.ts","../src/cost/sinks/discord.ts","../src/cost/sinks/sqlite.ts","../src/cost/upmetrics-read.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","// HTTP transport: a thin fetch wrapper. Provider-agnostic — the adapter supplies\n// the fully-built url/headers/body and parses the returned json itself.\nimport type { TransportRequest, HttpResponse } from \"./types.js\";\n\nexport async function httpTransport(req: TransportRequest): Promise<HttpResponse> {\n if (!req.http) {\n throw new Error(\"httpTransport: req.http is required for http transport\");\n }\n const { url, method = \"POST\", headers, body } = req.http;\n const res = await fetch(url, {\n method,\n headers,\n body:\n body === undefined\n ? undefined\n : typeof body === \"string\"\n ? body\n : JSON.stringify(body),\n });\n const json: unknown = await res.json().catch(() => undefined);\n return { ok: res.ok, status: res.status, json };\n}\n","// Subprocess transport: runs the local `claude -p` CLI (Anthropic Max plan).\n// No API key, no metered charge — costUsd is always 0, flagged subprocess:true so\n// dashboards can split free (Max) from paid (API). Token counts still come back\n// from the CLI's JSON so usage is tracked even when cost is zero.\nimport type { TransportRequest, SubprocessResponse } from \"./types.js\";\n\n/** The subset of `claude -p --output-format json` output we read. The CLI emits\n * more fields; we only need the result text + token usage. */\ninterface ClaudeCliJson {\n result?: string;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n };\n}\n\n/** Pure parser for the `claude -p --output-format json` stdout. Exported so it\n * can be unit-tested without spawning the binary. costUsd is pinned to 0. */\nexport function parseClaudeCliJson(raw: string): SubprocessResponse {\n let parsed: ClaudeCliJson;\n try {\n parsed = JSON.parse(raw) as ClaudeCliJson;\n } catch {\n throw new Error(\n `subprocessTransport: could not parse claude -p JSON output: ${raw.slice(0, 200)}`,\n );\n }\n const u = parsed.usage ?? {};\n return {\n text: parsed.result ?? \"\",\n inputTokens: u.input_tokens ?? 0,\n outputTokens: u.output_tokens ?? 0,\n cacheReadTokens: u.cache_read_input_tokens ?? 0,\n cacheCreationTokens: u.cache_creation_input_tokens ?? 0,\n costUsd: 0,\n subprocess: true,\n };\n}\n\nexport async function subprocessTransport(\n req: TransportRequest,\n): Promise<SubprocessResponse> {\n if (!req.subprocess) {\n throw new Error(\"subprocessTransport: req.subprocess is required for subprocess transport\");\n }\n const { prompt, systemPrompt } = req.subprocess;\n\n const cmd = [\"claude\", \"-p\", \"--output-format\", \"json\", \"--model\", req.spec.model];\n if (systemPrompt) cmd.push(\"--system-prompt\", systemPrompt);\n\n // Prompt goes in on stdin as a Blob (no argv length limit, no manual FileSink).\n const proc = (() => {\n try {\n return Bun.spawn(cmd, {\n stdin: new Blob([prompt]),\n stdout: \"pipe\",\n stderr: \"pipe\",\n });\n } catch (err) {\n throw new Error(\n `subprocessTransport: failed to spawn 'claude' — is the CLI installed and on PATH? (${String(err)})`,\n );\n }\n })();\n\n const [stdout, stderr, exitCode] = await Promise.all([\n new Response(proc.stdout).text(),\n new Response(proc.stderr).text(),\n proc.exited,\n ]);\n\n if (exitCode !== 0) {\n throw new Error(\n `subprocessTransport: claude -p exited ${exitCode}: ${stderr.slice(0, 300) || stdout.slice(0, 300)}`,\n );\n }\n\n return parseClaudeCliJson(stdout);\n}\n","// SSE streaming transport (F8.1). Like httpTransport but yields the parsed\n// `data:` payloads from the response body instead of awaiting .json() — pure\n// fetch + a ReadableStream reader, so it is Node 18+ and Bun safe. The adapter\n// supplies the `stream:true` body and parses each yielded JSON string itself.\nimport type { TransportRequest } from \"./types.js\";\n\n/** HTTP error from a streaming connect — carries `status` so the client's\n * pre-stream fallback can tell an eligible 429/5xx from a hard 4xx. */\nexport class StreamHttpError extends Error {\n readonly status: number;\n constructor(message: string, status: number) {\n super(message);\n this.name = \"StreamHttpError\";\n this.status = status;\n }\n}\n\nexport interface StreamTransportRequest extends TransportRequest {\n /** Injectable fetch for tests. */\n fetch?: typeof fetch;\n}\n\n/**\n * Open an SSE stream and yield each event's `data:` payload as a raw string\n * (the JSON after `data: `), skipping the `[DONE]` terminator and non-data\n * lines. Throws StreamHttpError before the first yield on a non-2xx connect.\n */\nexport async function* streamTransport(req: StreamTransportRequest): AsyncIterable<string> {\n if (!req.http) throw new Error(\"streamTransport: req.http is required for http transport\");\n const { url, method = \"POST\", headers, body } = req.http;\n const fetchImpl = req.fetch ?? fetch;\n const res = await fetchImpl(url, {\n method,\n headers,\n body:\n body === undefined\n ? undefined\n : typeof body === \"string\"\n ? body\n : JSON.stringify(body),\n });\n if (!res.ok || !res.body) {\n const text = await res.text().catch(() => \"\");\n throw new StreamHttpError(`stream ${res.status}: ${text.slice(0, 300)}`, res.status);\n }\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n // OpenAI/Anthropic emit one `data: {json}\\n\\n` per event — parse per line.\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) >= 0) {\n const line = buffer.slice(0, nl).replace(/\\r$/, \"\");\n buffer = buffer.slice(nl + 1);\n if (!line.startsWith(\"data:\")) continue; // skip comments / event: / id:\n const data = line.slice(5).trim();\n if (data === \"[DONE]\") return;\n if (data) yield data;\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n","// Cross-provider tool/function-calling normalization. The SDK speaks one Tool /\n// ToolCall shape; each provider has its own. toProviderTools builds the request\n// tools array; fromProviderToolCall parses one tool-call out of a response.\n// OpenAI, DeepInfra and OpenRouter share the OpenAI-compatible format.\nimport type { Tool, ToolCall } from \"../types.js\";\n\ntype ToolProvider = \"openai\" | \"deepinfra\" | \"openrouter\" | \"gemini\" | \"anthropic\";\n\nfunction family(provider: string): ToolProvider {\n if (provider === \"gemini\" || provider === \"google\") return \"gemini\";\n if (provider === \"anthropic\") return \"anthropic\";\n // openai, deepinfra, openrouter — all OpenAI-compatible\n return \"openai\";\n}\n\n/** Convert SDK tools to a provider's request format. */\nexport function toProviderTools(tools: Tool[], provider: string): unknown {\n switch (family(provider)) {\n case \"openai\":\n return tools.map((t) => ({\n type: \"function\",\n function: { name: t.name, description: t.description, parameters: t.parameters },\n }));\n case \"gemini\":\n return [\n {\n functionDeclarations: tools.map((t) => ({\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n })),\n },\n ];\n case \"anthropic\":\n return tools.map((t) => ({\n name: t.name,\n description: t.description,\n input_schema: t.parameters,\n }));\n default:\n throw new Error(`toProviderTools: unsupported provider family for \"${provider}\"`);\n }\n}\n\n/** Parse a single provider-shaped tool call back into the SDK ToolCall shape. */\nexport function fromProviderToolCall(raw: unknown, provider: string): ToolCall {\n const r = raw as Record<string, unknown>;\n switch (family(provider)) {\n case \"openai\": {\n // { id, type:\"function\", function:{ name, arguments:\"<json>\" } }\n const fn = (r.function ?? {}) as { name?: string; arguments?: string };\n return {\n id: typeof r.id === \"string\" ? r.id : \"\",\n name: fn.name ?? \"\",\n arguments: parseArgs(fn.arguments),\n };\n }\n case \"gemini\": {\n // { functionCall:{ name, args } } or { name, args }\n const fc = (r.functionCall ?? r) as { name?: string; args?: unknown };\n return {\n id: \"\", // Gemini function calls have no id\n name: fc.name ?? \"\",\n arguments: (fc.args as Record<string, unknown>) ?? {},\n };\n }\n case \"anthropic\": {\n // { type:\"tool_use\", id, name, input }\n return {\n id: typeof r.id === \"string\" ? r.id : \"\",\n name: typeof r.name === \"string\" ? r.name : \"\",\n arguments: (r.input as Record<string, unknown>) ?? {},\n };\n }\n default:\n throw new Error(`fromProviderToolCall: unsupported provider family for \"${provider}\"`);\n }\n}\n\nfunction parseArgs(raw: unknown): Record<string, unknown> {\n if (raw === undefined || raw === null) return {};\n if (typeof raw === \"object\") return raw as Record<string, unknown>;\n if (typeof raw === \"string\") {\n try {\n return JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return {};\n }\n }\n return {};\n}\n","// Usage construction + cost computation. Real adapters (F4) build their Usage via\n// freshUsage() and fill costUsd from computeCost(). The pricing table lives in\n// ./pricing.ts (F3.6); until a model is priced, computeCost returns 0 so calls\n// still complete (cost just shows $0 rather than throwing).\nimport { getPrice } from \"./pricing.js\";\nimport type { Usage, Transport, Capability } from \"../types.js\";\n\n/**\n * Cost in USD for a call. cache-read/creation tokens are priced separately when\n * the pricing entry defines rates for them; otherwise they fall back to the\n * input rate (read) / are ignored (creation). Unknown model → 0.\n */\nexport function computeCost(\n provider: string,\n model: string,\n inputTokens: number,\n outputTokens: number,\n cacheReadTokens = 0,\n cacheCreationTokens = 0,\n): number {\n const price = getPrice(provider, model);\n if (!price) return 0;\n const perToken = (per1M: number) => per1M / 1_000_000;\n const inRate = perToken(price.inputPer1M);\n const outRate = perToken(price.outputPer1M);\n const cacheReadRate =\n price.cacheReadPer1M !== undefined ? perToken(price.cacheReadPer1M) : inRate;\n const cacheWriteRate =\n price.cacheWritePer1M !== undefined ? perToken(price.cacheWritePer1M) : inRate;\n return (\n inputTokens * inRate +\n outputTokens * outRate +\n cacheReadTokens * cacheReadRate +\n cacheCreationTokens * cacheWriteRate\n );\n}\n\n/** Build a Usage with cost computed from the pricing table. Adapters call this\n * after a successful provider call; latencyMs/ts/capability are stamped by the\n * client (call-context owner), so they default to 0/\"\"/the passed capability. */\nexport function freshUsage(args: {\n provider: string;\n model: string;\n transport: Transport;\n capability: Capability;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheCreationTokens?: number;\n subprocess?: boolean;\n}): Usage {\n const cacheReadTokens = args.cacheReadTokens ?? 0;\n const cacheCreationTokens = args.cacheCreationTokens ?? 0;\n // Subprocess (Max plan) is never a metered charge to us — cost is always 0.\n const costUsd = args.subprocess\n ? 0\n : computeCost(\n args.provider,\n args.model,\n args.inputTokens,\n args.outputTokens,\n cacheReadTokens,\n cacheCreationTokens,\n );\n const usage: Usage = {\n provider: args.provider,\n model: args.model,\n transport: args.transport,\n inputTokens: args.inputTokens,\n outputTokens: args.outputTokens,\n cacheReadTokens,\n cacheCreationTokens,\n costUsd,\n latencyMs: 0,\n capability: args.capability,\n ts: \"\",\n };\n if (args.subprocess) usage.subprocess = true;\n return usage;\n}\n","// Anthropic adapter (F4.6) — the real one (F2.5 shipped only a stub). Two\n// transports: http (api.anthropic.com/v1/messages) and subprocess (claude -p,\n// Max plan, costUsd 0). Critical for the xrt81 vision pilot. Tools normalized\n// via F4.5. No @anthropic-ai/sdk package — plain fetch through httpTransport.\nimport { httpTransport } from \"../transport/http.js\";\nimport { subprocessTransport } from \"../transport/subprocess.js\";\nimport { streamTransport } from \"../transport/stream.js\";\nimport { toProviderTools, fromProviderToolCall } from \"./tools.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n ChatRequest,\n ChatResult,\n ChatStreamEvent,\n Message,\n ContentPart,\n ToolCall,\n} from \"../types.js\";\n\ninterface AnthropicBlock {\n type: string;\n text?: string;\n id?: string;\n name?: string;\n input?: Record<string, unknown>;\n}\ninterface AnthropicResponse {\n content?: AnthropicBlock[];\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n error?: unknown;\n}\n\nfunction contentBlocks(content: string | ContentPart[]): unknown {\n if (typeof content === \"string\") return content;\n return content.map((p) => {\n if (p.type === \"text\") return { type: \"text\", text: p.text };\n // Anthropic has no native video input — route video via a video-capable\n // provider (Gemini, F019) instead.\n if (p.type === \"video\") {\n throw new Error(\"anthropic adapter: video input is not supported — use a video provider (e.g. gemini)\");\n }\n if (typeof p.image === \"string\" && /^https?:\\/\\//.test(p.image)) {\n return { type: \"image\", source: { type: \"url\", url: p.image } };\n }\n const data =\n typeof p.image === \"string\"\n ? p.image.replace(/^data:[^;]+;base64,/, \"\")\n : Buffer.from(p.image).toString(\"base64\");\n return {\n type: \"image\",\n source: { type: \"base64\", media_type: p.mimeType ?? \"image/png\", data },\n };\n });\n}\n\n/** Flatten messages to a single prompt for the subprocess (claude -p) path. */\nfunction flattenForSubprocess(messages: Message[]): { prompt: string; system?: string } {\n const sys: string[] = [];\n const turns: string[] = [];\n for (const m of messages) {\n const text =\n typeof m.content === \"string\"\n ? m.content\n : m.content.map((p) => (p.type === \"text\" ? p.text : \"[image]\")).join(\" \");\n if (m.role === \"system\") sys.push(text);\n else turns.push(`${m.role}: ${text}`);\n }\n return { prompt: turns.join(\"\\n\\n\"), system: sys.length ? sys.join(\"\\n\") : undefined };\n}\n\nexport function anthropicAdapter(\n config: { apiKey?: string; baseUrl?: string; anthropicVersion?: string; fetch?: typeof fetch } = {},\n): ProviderAdapter {\n const baseUrl = config.baseUrl ?? \"https://api.anthropic.com\";\n const version = config.anthropicVersion ?? \"2023-06-01\";\n\n /** Build the /v1/messages body (shared by the http + stream paths). */\n function buildBody(req: ChatRequest): Record<string, unknown> {\n const system: string[] = [];\n const messages: { role: string; content: unknown }[] = [];\n for (const m of req.messages as Message[]) {\n if (m.role === \"system\") {\n system.push(typeof m.content === \"string\" ? m.content : \"\");\n continue;\n }\n // tool-result turn → a user message carrying a tool_result block (F8.7).\n if (m.role === \"tool\") {\n messages.push({\n role: \"user\",\n content: [\n {\n type: \"tool_result\",\n tool_use_id: m.toolCallId ?? \"\",\n content: typeof m.content === \"string\" ? m.content : \"\",\n },\n ],\n });\n continue;\n }\n // assistant turn that called tools → text blocks + tool_use blocks (F8.7).\n if (m.role === \"assistant\" && m.toolCalls && m.toolCalls.length > 0) {\n const blocks: unknown[] = [];\n if (typeof m.content === \"string\") {\n if (m.content.length > 0) blocks.push({ type: \"text\", text: m.content });\n } else {\n blocks.push(...(contentBlocks(m.content) as unknown[]));\n }\n for (const tc of m.toolCalls) {\n blocks.push({ type: \"tool_use\", id: tc.id, name: tc.name, input: tc.arguments });\n }\n messages.push({ role: \"assistant\", content: blocks });\n continue;\n }\n messages.push({ role: m.role === \"assistant\" ? \"assistant\" : \"user\", content: contentBlocks(m.content) });\n }\n const body: Record<string, unknown> = {\n model: req.spec.model,\n max_tokens: req.maxTokens ?? 1024, // Anthropic requires max_tokens\n messages,\n };\n if (system.length > 0) body.system = system.join(\"\\n\");\n if (req.tools) body.tools = toProviderTools(req.tools, \"anthropic\");\n if (req.temperature !== undefined) body.temperature = req.temperature;\n return body;\n }\n\n function apiKeyOrThrow(): string {\n const apiKey = config.apiKey ?? process.env.ANTHROPIC_API_KEY;\n if (!apiKey) throw new Error(\"anthropic adapter: API key not set (env ANTHROPIC_API_KEY)\");\n return apiKey;\n }\n\n async function chatHttp(req: ChatRequest): Promise<ChatResult> {\n const apiKey = apiKeyOrThrow();\n const body = buildBody(req);\n\n const res = await httpTransport({\n spec: req.spec,\n http: {\n url: `${baseUrl}/v1/messages`,\n headers: {\n \"content-type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": version,\n },\n body,\n },\n });\n if (!res.ok) throw new Error(`anthropic ${res.status}: ${JSON.stringify(res.json).slice(0, 300)}`);\n\n const data = res.json as AnthropicResponse;\n const blocks = data.content ?? [];\n const text = blocks\n .filter((b) => b.type === \"text\" && typeof b.text === \"string\")\n .map((b) => b.text)\n .join(\"\");\n const toolCalls: ToolCall[] = blocks\n .filter((b) => b.type === \"tool_use\")\n .map((b) => fromProviderToolCall(b, \"anthropic\"));\n\n const usage = freshUsage({\n provider: \"anthropic\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"chat\",\n inputTokens: data.usage?.input_tokens ?? 0,\n outputTokens: data.usage?.output_tokens ?? 0,\n cacheReadTokens: data.usage?.cache_read_input_tokens ?? 0,\n cacheCreationTokens: data.usage?.cache_creation_input_tokens ?? 0,\n });\n const result: ChatResult = { text, usage };\n if (toolCalls.length > 0) result.toolCalls = toolCalls;\n return result;\n }\n\n async function chatSubprocess(req: ChatRequest): Promise<ChatResult> {\n const { prompt, system } = flattenForSubprocess(req.messages as Message[]);\n const r = await subprocessTransport({ spec: req.spec, subprocess: { prompt, systemPrompt: system } });\n const usage = freshUsage({\n provider: \"anthropic\",\n model: req.spec.model,\n transport: \"subprocess\",\n capability: \"chat\",\n inputTokens: r.inputTokens,\n outputTokens: r.outputTokens,\n cacheReadTokens: r.cacheReadTokens,\n cacheCreationTokens: r.cacheCreationTokens,\n subprocess: true,\n });\n return { text: r.text, usage };\n }\n\n async function chat(req: ChatRequest): Promise<ChatResult> {\n return req.spec.transport === \"subprocess\" ? chatSubprocess(req) : chatHttp(req);\n }\n\n // Streaming chat (F8.4) over the native /v1/messages SSE. Maps\n // content_block_delta(text_delta) → text events, accumulates tool_use blocks\n // (id/name from content_block_start, input from input_json_delta) → complete\n // tool_call events, and reads usage from message_start + message_delta. Only\n // the http transport streams — `claude -p` subprocess is one-shot.\n async function* chatStream(req: ChatRequest): AsyncIterable<ChatStreamEvent> {\n if (req.spec.transport === \"subprocess\") {\n throw new Error(\"anthropic adapter: streaming is not supported over the subprocess transport\");\n }\n const apiKey = apiKeyOrThrow();\n const body = { ...buildBody(req), stream: true };\n const stream = streamTransport({\n spec: req.spec,\n fetch: config.fetch,\n http: {\n url: `${baseUrl}/v1/messages`,\n headers: {\n \"content-type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": version,\n },\n body,\n },\n });\n\n let inputTokens = 0;\n let outputTokens = 0;\n let cacheReadTokens = 0;\n let cacheCreationTokens = 0;\n let stopReason: string | null = null;\n // index → accumulated tool_use block (input_json_delta fragments concatenated).\n const toolBlocks = new Map<number, { id: string; name: string; json: string }>();\n\n for await (const data of stream) {\n let ev: AnthropicStreamEvent;\n try {\n ev = JSON.parse(data) as AnthropicStreamEvent;\n } catch {\n continue;\n }\n switch (ev.type) {\n case \"message_start\": {\n const u = ev.message?.usage;\n inputTokens = u?.input_tokens ?? 0;\n cacheReadTokens = u?.cache_read_input_tokens ?? 0;\n cacheCreationTokens = u?.cache_creation_input_tokens ?? 0;\n break;\n }\n case \"content_block_start\": {\n if (ev.content_block?.type === \"tool_use\" && ev.index !== undefined) {\n toolBlocks.set(ev.index, {\n id: ev.content_block.id ?? \"\",\n name: ev.content_block.name ?? \"\",\n json: \"\",\n });\n }\n break;\n }\n case \"content_block_delta\": {\n const d = ev.delta;\n if (d?.type === \"text_delta\" && d.text) {\n yield { type: \"text\", delta: d.text };\n } else if (d?.type === \"input_json_delta\" && d.partial_json && ev.index !== undefined) {\n const b = toolBlocks.get(ev.index);\n if (b) b.json += d.partial_json;\n }\n break;\n }\n case \"message_delta\": {\n if (ev.delta?.stop_reason) stopReason = ev.delta.stop_reason;\n if (ev.usage?.output_tokens !== undefined) outputTokens = ev.usage.output_tokens;\n break;\n }\n default:\n break; // content_block_stop / message_stop / ping\n }\n }\n\n for (const [, b] of [...toolBlocks.entries()].sort((a, c) => a[0] - c[0])) {\n let args: Record<string, unknown> = {};\n try {\n args = b.json ? (JSON.parse(b.json) as Record<string, unknown>) : {};\n } catch {\n args = {};\n }\n yield { type: \"tool_call\", id: b.id, name: b.name, args };\n }\n const usage = freshUsage({\n provider: \"anthropic\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"chat\",\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheCreationTokens,\n });\n yield { type: \"usage\", costUsd: usage.costUsd, model: usage.model, usage };\n yield { type: \"finish\", reason: mapAnthropicStop(stopReason) };\n }\n\n return { name: \"anthropic\", chat, chatStream, vision: chat };\n}\n\n/** Anthropic Messages SSE event (only the fields we read). */\ninterface AnthropicStreamEvent {\n type: string;\n index?: number;\n message?: {\n usage?: {\n input_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n };\n content_block?: { type?: string; id?: string; name?: string };\n delta?: { type?: string; text?: string; partial_json?: string; stop_reason?: string };\n usage?: { output_tokens?: number };\n}\n\n/** Map Anthropic stop_reason → the SDK's ChatStreamEvent finish reason. */\nfunction mapAnthropicStop(reason: string | null): \"end_turn\" | \"tool_calls\" | \"length\" | \"stop\" {\n switch (reason) {\n case \"tool_use\":\n return \"tool_calls\";\n case \"max_tokens\":\n return \"length\";\n case \"stop_sequence\":\n return \"stop\";\n default:\n return \"end_turn\";\n }\n}\n","// Shared core for OpenAI-compatible chat APIs. OpenAI (F4.1), DeepInfra (F4.3)\n// and OpenRouter (F4.4) all speak this wire format — only base URL, key and a\n// couple of headers differ. The adapter uses httpTransport (F2.4) for the wire\n// I/O and the F4.5 tool contract for tool round-tripping.\nimport { httpTransport } from \"../transport/http.js\";\nimport { streamTransport } from \"../transport/stream.js\";\nimport { toProviderTools, fromProviderToolCall } from \"./tools.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n ChatRequest,\n ChatResult,\n ChatStreamEvent,\n Message,\n ToolCall,\n} from \"../types.js\";\n\nexport interface OpenAICompatibleConfig {\n /** Provider name recorded on Usage (e.g. \"openai\", \"deepinfra\", \"openrouter\"). */\n name: string;\n /** Chat completions base, e.g. \"https://api.openai.com/v1\". */\n baseUrl: string;\n /** Resolved at call time if omitted (env var per provider). */\n apiKey?: string;\n /** Extra headers (e.g. OpenRouter's HTTP-Referer / X-Title). */\n extraHeaders?: Record<string, string>;\n /** Injectable fetch for the streaming path (tests). */\n fetch?: typeof fetch;\n /** OpenRouter ground-truth cost (F010): send `usage:{include:true}` and use the\n * response's `usage.cost` (USD) as costUsd, falling back to the pricing table.\n * Only OpenRouter returns this field — openai/deepinfra leave it false. */\n costFromResponseField?: boolean;\n}\n\ninterface OAToolCall {\n id?: string;\n function?: { name?: string; arguments?: string };\n}\ninterface OAResponse {\n choices?: { message?: { content?: string | null; tool_calls?: OAToolCall[] } }[];\n usage?: { prompt_tokens?: number; completion_tokens?: number; cost?: number };\n error?: unknown;\n}\n\n/** SDK message → OpenAI message (string content, or multimodal parts for vision).\n * Threads the normalized tool form to the wire: a `tool`-role message's\n * `toolCallId` → `tool_call_id`, and an assistant message's `toolCalls` →\n * `tool_calls:[{id,type:'function',function:{name,arguments}}]` (F8.3) so a\n * multi-turn tool conversation round-trips. Exported for serialization tests. */\nexport function toOpenAIMessage(m: Message): Record<string, unknown> {\n if (typeof m.content === \"string\") {\n const base: Record<string, unknown> = { role: m.role, content: m.content };\n if (m.toolCallId) base.tool_call_id = m.toolCallId;\n if (m.toolCalls && m.toolCalls.length > 0) {\n base.tool_calls = m.toolCalls.map((tc) => ({\n id: tc.id,\n type: \"function\",\n function: { name: tc.name, arguments: JSON.stringify(tc.arguments) },\n }));\n }\n return base;\n }\n const content = m.content.map((p) => {\n if (p.type === \"text\") return { type: \"text\", text: p.text };\n if (p.type === \"video\") {\n // F019.3 — OpenRouter video models. `video_url` mirrors `image_url`;\n // VERIFIED live 2026-06-04 against gemma-4 + nvidia-nemotron (both described\n // a real 2MB clip sent inline as a base64 data-URL).\n const url =\n typeof p.video === \"string\"\n ? p.video\n : `data:${p.mimeType ?? \"video/mp4\"};base64,${Buffer.from(p.video).toString(\"base64\")}`;\n return { type: \"video_url\", video_url: { url } };\n }\n const url =\n typeof p.image === \"string\"\n ? p.image\n : `data:${p.mimeType ?? \"image/png\"};base64,${Buffer.from(p.image).toString(\"base64\")}`;\n return { type: \"image_url\", image_url: { url } };\n });\n return { role: m.role, content };\n}\n\nexport function makeOpenAICompatibleAdapter(config: OpenAICompatibleConfig): ProviderAdapter {\n async function chat(req: ChatRequest): Promise<ChatResult> {\n const apiKey = config.apiKey ?? process.env[`${config.name.toUpperCase()}_API_KEY`];\n if (!apiKey) {\n throw new Error(`${config.name} adapter: API key not set (env ${config.name.toUpperCase()}_API_KEY)`);\n }\n const body: Record<string, unknown> = {\n model: req.spec.model,\n messages: req.messages.map(toOpenAIMessage),\n };\n if (req.tools) body.tools = toProviderTools(req.tools, \"openai\");\n if (req.maxTokens !== undefined) body.max_tokens = req.maxTokens;\n if (req.temperature !== undefined) body.temperature = req.temperature;\n if (req.responseFormat === \"json\") body.response_format = { type: \"json_object\" };\n if (config.costFromResponseField) body.usage = { include: true };\n\n const res = await httpTransport({\n spec: req.spec,\n http: {\n url: `${config.baseUrl}/chat/completions`,\n headers: {\n \"content-type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...config.extraHeaders,\n },\n body,\n },\n });\n if (!res.ok) {\n throw new Error(`${config.name} ${res.status}: ${JSON.stringify(res.json).slice(0, 300)}`);\n }\n const data = res.json as OAResponse;\n const msg = data.choices?.[0]?.message;\n // Reasoning/multimodal models can return `content` as an array of blocks (or\n // null) instead of a plain string — coerce so callers always get a string\n // (was: `?? \"\"`, which left an array through → consumer `text.replace` crash).\n const text = contentToText(msg?.content);\n const toolCalls: ToolCall[] | undefined = msg?.tool_calls?.map((tc) =>\n fromProviderToolCall(tc, \"openai\"),\n );\n const usage = freshUsage({\n provider: config.name,\n model: req.spec.model,\n transport: \"http\",\n capability: \"chat\",\n inputTokens: data.usage?.prompt_tokens ?? 0,\n outputTokens: data.usage?.completion_tokens ?? 0,\n });\n if (config.costFromResponseField && typeof data.usage?.cost === \"number\") {\n usage.costUsd = data.usage.cost; // OpenRouter ground-truth beats the estimate\n }\n const result: ChatResult = { text, usage };\n if (toolCalls && toolCalls.length > 0) result.toolCalls = toolCalls;\n return result;\n }\n\n // Streaming chat (F8.2). Parses the OpenAI chat.completions SSE: content\n // deltas → text events, tool_calls deltas accumulated (index-keyed, arguments\n // string concatenated) → complete tool_call events at end, the include_usage\n // chunk → a usage event, finish_reason → the terminal finish (emitted last so\n // tool_calls + usage precede it).\n async function* chatStream(req: ChatRequest): AsyncIterable<ChatStreamEvent> {\n const apiKey = config.apiKey ?? process.env[`${config.name.toUpperCase()}_API_KEY`];\n if (!apiKey) {\n throw new Error(`${config.name} adapter: API key not set (env ${config.name.toUpperCase()}_API_KEY)`);\n }\n const body: Record<string, unknown> = {\n model: req.spec.model,\n messages: req.messages.map(toOpenAIMessage),\n stream: true,\n stream_options: { include_usage: true },\n };\n if (req.tools) body.tools = toProviderTools(req.tools, \"openai\");\n if (req.maxTokens !== undefined) body.max_tokens = req.maxTokens;\n if (req.temperature !== undefined) body.temperature = req.temperature;\n if (req.responseFormat === \"json\") body.response_format = { type: \"json_object\" };\n if (config.costFromResponseField) body.usage = { include: true };\n\n const stream = streamTransport({\n spec: req.spec,\n fetch: config.fetch,\n http: {\n url: `${config.baseUrl}/chat/completions`,\n headers: {\n \"content-type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...config.extraHeaders,\n },\n body,\n },\n });\n\n // index → accumulated tool call (id/name set once, arguments concatenated).\n const toolAcc = new Map<number, { id: string; name: string; args: string }>();\n let finishReason: string | null = null;\n\n for await (const data of stream) {\n let chunk: OAStreamChunk;\n try {\n chunk = JSON.parse(data) as OAStreamChunk;\n } catch {\n continue; // ignore unparseable keep-alive noise\n }\n const choice = chunk.choices?.[0];\n if (choice) {\n const delta = choice.delta ?? {};\n if (typeof delta.content === \"string\" && delta.content.length > 0) {\n yield { type: \"text\", delta: delta.content };\n }\n for (const tc of delta.tool_calls ?? []) {\n const idx = tc.index ?? 0;\n const cur = toolAcc.get(idx) ?? { id: \"\", name: \"\", args: \"\" };\n if (tc.id) cur.id = tc.id;\n if (tc.function?.name) cur.name = tc.function.name;\n if (tc.function?.arguments) cur.args += tc.function.arguments;\n toolAcc.set(idx, cur);\n }\n if (choice.finish_reason) finishReason = choice.finish_reason;\n }\n if (chunk.usage) {\n const usage = freshUsage({\n provider: config.name,\n model: req.spec.model,\n transport: \"http\",\n capability: \"chat\",\n inputTokens: chunk.usage.prompt_tokens ?? 0,\n outputTokens: chunk.usage.completion_tokens ?? 0,\n });\n if (config.costFromResponseField && typeof chunk.usage.cost === \"number\") {\n usage.costUsd = chunk.usage.cost; // OpenRouter ground-truth\n }\n yield { type: \"usage\", costUsd: usage.costUsd, model: usage.model, usage };\n }\n }\n\n // Flush accumulated tool calls (complete), then the terminal finish.\n for (const [, t] of [...toolAcc.entries()].sort((a, b) => a[0] - b[0])) {\n let args: Record<string, unknown> = {};\n try {\n args = t.args ? (JSON.parse(t.args) as Record<string, unknown>) : {};\n } catch {\n args = {};\n }\n yield { type: \"tool_call\", id: t.id, name: t.name, args };\n }\n yield { type: \"finish\", reason: mapFinishReason(finishReason) };\n }\n\n return {\n name: config.name,\n chat,\n chatStream,\n // gpt-4o-class models are multimodal — vision shares the chat path.\n vision: chat,\n };\n}\n\n/** OpenAI streaming chunk shape (only the fields we read). */\ninterface OAStreamChunk {\n choices?: {\n delta?: {\n content?: string | null;\n tool_calls?: { index?: number; id?: string; function?: { name?: string; arguments?: string } }[];\n };\n finish_reason?: string | null;\n }[];\n usage?: { prompt_tokens?: number; completion_tokens?: number; cost?: number };\n}\n\n/** Coerce an OpenAI `message.content` to a string. Most providers return a string,\n * but reasoning/multimodal models can return an array of content blocks (or null). */\nfunction contentToText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return content\n .map((p) => {\n if (typeof p === \"string\") return p;\n const t = (p as { text?: unknown } | null)?.text;\n return typeof t === \"string\" ? t : \"\";\n })\n .join(\"\");\n }\n return \"\";\n}\n\n/** Map OpenAI finish_reason → the SDK's ChatStreamEvent finish reason. */\nfunction mapFinishReason(reason: string | null): \"end_turn\" | \"tool_calls\" | \"length\" | \"stop\" {\n switch (reason) {\n case \"tool_calls\":\n return \"tool_calls\";\n case \"length\":\n return \"length\";\n case \"stop\":\n return \"stop\";\n default:\n return \"end_turn\";\n }\n}\n","// OpenAI adapter (F4.1 chat/vision + F5.4 embedding). Chat/vision come from the\n// shared OpenAI-compatible core; embedding uses the /embeddings endpoint. No\n// openai npm package — plain fetch through httpTransport.\nimport { makeOpenAICompatibleAdapter } from \"./openai-compatible.js\";\nimport { httpTransport } from \"../transport/http.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n EmbeddingRequest,\n EmbeddingResult,\n TranscribeRequest,\n TranscribeResult,\n} from \"../types.js\";\n\n/** Whisper-family per-minute USD prices (audio is not token-priced). */\nconst WHISPER_PRICE_PER_MIN: Record<string, number> = {\n \"whisper-1\": 0.006,\n};\n\nexport function openaiAdapter(\n config: { apiKey?: string; baseUrl?: string; fetch?: typeof fetch } = {},\n): ProviderAdapter {\n const baseUrl = config.baseUrl ?? \"https://api.openai.com/v1\";\n const base = makeOpenAICompatibleAdapter({ name: \"openai\", baseUrl, apiKey: config.apiKey });\n\n async function embedding(req: EmbeddingRequest): Promise<EmbeddingResult> {\n const apiKey = config.apiKey ?? process.env.OPENAI_API_KEY;\n if (!apiKey) throw new Error(\"openai adapter: API key not set (env OPENAI_API_KEY)\");\n const res = await httpTransport({\n spec: req.spec,\n http: {\n url: `${baseUrl}/embeddings`,\n headers: { \"content-type\": \"application/json\", Authorization: `Bearer ${apiKey}` },\n body: { model: req.spec.model, input: req.input },\n },\n });\n if (!res.ok) {\n throw new Error(`openai ${res.status}: ${JSON.stringify(res.json).slice(0, 300)}`);\n }\n const data = res.json as {\n data?: { embedding: number[] }[];\n usage?: { prompt_tokens?: number };\n };\n const vectors = (data.data ?? []).map((d) => d.embedding);\n const usage = freshUsage({\n provider: \"openai\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"embedding\",\n inputTokens: data.usage?.prompt_tokens ?? 0,\n outputTokens: 0,\n });\n return { vectors, usage };\n }\n\n async function transcribe(req: TranscribeRequest): Promise<TranscribeResult> {\n const apiKey = config.apiKey ?? process.env.OPENAI_API_KEY;\n if (!apiKey) throw new Error(\"openai adapter: API key not set (env OPENAI_API_KEY)\");\n // Whisper is multipart/form-data — bypass httpTransport (JSON-only). Don't set\n // content-type; fetch adds the multipart boundary.\n const form = new FormData();\n form.append(\"file\", new Blob([req.audio]), \"audio\");\n form.append(\"model\", req.spec.model);\n if (req.language) form.append(\"language\", req.language);\n const fetchImpl = config.fetch ?? fetch;\n const res = await fetchImpl(`${baseUrl}/audio/transcriptions`, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${apiKey}` },\n body: form,\n });\n if (!res.ok) {\n throw new Error(`openai ${res.status}: ${(await res.text().catch(() => \"\")).slice(0, 200)}`);\n }\n const data = (await res.json()) as { text?: string };\n const usage = freshUsage({\n provider: \"openai\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"transcribe\",\n inputTokens: 0,\n outputTokens: 0, // Whisper is per-minute, not token-priced.\n });\n // Per-minute cost when the caller supplies the audio duration (API returns none).\n if (req.durationSec !== undefined) {\n const perMinute = WHISPER_PRICE_PER_MIN[req.spec.model] ?? 0;\n usage.costUsd = (req.durationSec / 60) * perMinute;\n }\n return { text: data.text ?? \"\", usage };\n }\n\n return { ...base, embedding, transcribe };\n}\n","// Google Gemini adapter (F4.2). generateContent REST API; API key in the query\n// param (?key=), not a header. System turns map to systemInstruction; assistant\n// maps to role \"model\". Token counts come from usageMetadata. Tools normalized\n// via F4.5. No @google/generative-ai package — plain fetch through httpTransport.\nimport { httpTransport } from \"../transport/http.js\";\nimport { streamTransport } from \"../transport/stream.js\";\nimport { toProviderTools, fromProviderToolCall } from \"./tools.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n ChatRequest,\n ChatResult,\n ChatStreamEvent,\n ImageRequest,\n ImageResult,\n AnimateRequest,\n AnimateResult,\n Message,\n ContentPart,\n ToolCall,\n} from \"../types.js\";\n\n/** Per-image USD price for Gemini image-gen models (generateContent image output\n * is billed per image). Official ai.google.dev/gemini-api/docs/pricing, standard\n * paid tier, at the 1K/1024px output size (Google's per-image price rises with\n * resolution — 2K/4K cost more; we record the common 1K default). Overridable\n * per call via geminiAdapter config.pricePerImage. */\nconst GEMINI_IMAGE_PRICE_PER_IMAGE: Record<string, number> = {\n \"gemini-2.5-flash-image\": 0.039, // \"nano-banana\" — 1024px = 1290 tok\n \"gemini-3.1-flash-image\": 0.067, // 1K=$0.067, 2K=$0.101, 4K=$0.151\n \"gemini-3.1-flash-image-preview\": 0.067,\n \"gemini-3-pro-image\": 0.134, // premium — 1K/2K=$0.134, 4K=$0.24\n \"gemini-3-pro-image-preview\": 0.134, // was $0.039 — wrong (that's the flash price); pro is $0.134\n};\n\ninterface GeminiPart {\n text?: string;\n functionCall?: { name: string; args: Record<string, unknown> };\n inlineData?: { mimeType: string; data: string };\n}\ninterface GeminiResponse {\n candidates?: { content?: { parts?: GeminiPart[] } }[];\n usageMetadata?: { promptTokenCount?: number; candidatesTokenCount?: number };\n error?: unknown;\n}\n\nfunction partsFrom(content: string | ContentPart[]): GeminiPart[] {\n if (typeof content === \"string\") return [{ text: content }];\n return content.map((p): GeminiPart => {\n if (p.type === \"text\") return { text: p.text };\n // Video (F019) and image both go inline as base64 — Gemini accepts video mime\n // types natively. (Clips over ~20MB need the Files API — not handled here.)\n if (p.type === \"video\") {\n const data =\n typeof p.video === \"string\"\n ? p.video.replace(/^data:[^;]+;base64,/, \"\")\n : Buffer.from(p.video).toString(\"base64\");\n return { inlineData: { mimeType: p.mimeType ?? \"video/mp4\", data } };\n }\n const data =\n typeof p.image === \"string\"\n ? p.image.replace(/^data:[^;]+;base64,/, \"\")\n : Buffer.from(p.image).toString(\"base64\");\n return { inlineData: { mimeType: p.mimeType ?? \"image/png\", data } };\n });\n}\n\n/** Per-SECOND USD for Veo video models (F024). Official ai.google.dev/gemini-api/\n * docs/pricing (2026-06, \"video with audio\", 720p/1080p default; 4K costs more).\n * Override per call via config.pricePerSecond. Unknown model → 0 (never fabricated). */\nconst VEO_PRICE_PER_SEC: Record<string, number> = {\n \"veo-3.1-generate-preview\": 0.4, // standard; 4K = 0.60\n \"veo-3.1-fast-generate-preview\": 0.1, // 720p; 1080p = 0.12, 4K = 0.30\n \"veo-3.1-lite-generate-preview\": 0.05, // 720p; 1080p = 0.08\n \"veo-3.0-generate-001\": 0.4,\n \"veo-3.0-fast-generate-001\": 0.1,\n};\n\nexport function geminiAdapter(\n config: {\n apiKey?: string;\n baseUrl?: string;\n fetch?: typeof fetch;\n pricePerImage?: number;\n /** Override the per-SECOND Veo video price (else estimate per model, 0 if unknown). */\n pricePerSecond?: number;\n /** Poll interval for Veo long-running operations (default 5s). */\n pollIntervalMs?: number;\n /** Deadline for a Veo job (default 300000 = 5 min). */\n videoTimeoutMs?: number;\n } = {},\n): ProviderAdapter {\n const baseUrl = config.baseUrl ?? \"https://generativelanguage.googleapis.com/v1beta\";\n\n function resolveKey(): string {\n const apiKey = config.apiKey ?? process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY;\n if (!apiKey) throw new Error(\"gemini adapter: API key not set (env GOOGLE_API_KEY)\");\n return apiKey;\n }\n\n /** Build the generateContent body (shared by the http + stream paths). */\n function buildBody(req: ChatRequest): Record<string, unknown> {\n const systemParts: GeminiPart[] = [];\n const contents: { role: string; parts: GeminiPart[] }[] = [];\n for (const m of req.messages as Message[]) {\n if (m.role === \"system\") {\n systemParts.push(...partsFrom(m.content));\n } else {\n contents.push({\n role: m.role === \"assistant\" ? \"model\" : \"user\",\n parts: partsFrom(m.content),\n });\n }\n }\n const body: Record<string, unknown> = { contents };\n if (systemParts.length > 0) body.systemInstruction = { parts: systemParts };\n if (req.tools) body.tools = toProviderTools(req.tools, \"gemini\");\n const genConfig: Record<string, unknown> = {};\n if (req.maxTokens !== undefined) genConfig.maxOutputTokens = req.maxTokens;\n if (req.temperature !== undefined) genConfig.temperature = req.temperature;\n if (Object.keys(genConfig).length > 0) body.generationConfig = genConfig;\n return body;\n }\n\n async function chat(req: ChatRequest): Promise<ChatResult> {\n const apiKey = resolveKey();\n const body = buildBody(req);\n\n const res = await httpTransport({\n spec: req.spec,\n http: {\n url: `${baseUrl}/models/${req.spec.model}:generateContent?key=${encodeURIComponent(apiKey)}`,\n headers: { \"content-type\": \"application/json\" },\n body,\n },\n });\n if (!res.ok) {\n throw new Error(`gemini ${res.status}: ${JSON.stringify(res.json).slice(0, 300)}`);\n }\n const data = res.json as GeminiResponse;\n const parts = data.candidates?.[0]?.content?.parts ?? [];\n const text = parts\n .filter((p) => typeof p.text === \"string\")\n .map((p) => p.text)\n .join(\"\");\n const toolCalls: ToolCall[] = parts\n .filter((p) => p.functionCall)\n .map((p) => fromProviderToolCall({ functionCall: p.functionCall }, \"gemini\"));\n\n const usage = freshUsage({\n provider: \"gemini\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"chat\",\n inputTokens: data.usageMetadata?.promptTokenCount ?? 0,\n outputTokens: data.usageMetadata?.candidatesTokenCount ?? 0,\n });\n const result: ChatResult = { text, usage };\n if (toolCalls.length > 0) result.toolCalls = toolCalls;\n return result;\n }\n\n // Streaming chat (F8.6) over streamGenerateContent?alt=sse. Each SSE chunk is\n // a partial GenerateContentResponse: parts[].text → text events, parts[].\n // functionCall → complete tool_call events (gemini sends each call whole), and\n // the final usageMetadata → a usage event. finishReason maps the terminal.\n async function* chatStream(req: ChatRequest): AsyncIterable<ChatStreamEvent> {\n const apiKey = resolveKey();\n const body = buildBody(req);\n const stream = streamTransport({\n spec: req.spec,\n fetch: config.fetch,\n http: {\n url: `${baseUrl}/models/${req.spec.model}:streamGenerateContent?alt=sse&key=${encodeURIComponent(apiKey)}`,\n headers: { \"content-type\": \"application/json\" },\n body,\n },\n });\n\n const toolCalls: ToolCall[] = [];\n let inputTokens = 0;\n let outputTokens = 0;\n let finishReason: string | null = null;\n\n for await (const data of stream) {\n let chunk: GeminiResponse & { candidates?: { finishReason?: string }[] };\n try {\n chunk = JSON.parse(data) as typeof chunk;\n } catch {\n continue;\n }\n const candidate = chunk.candidates?.[0];\n for (const p of candidate?.content?.parts ?? []) {\n if (typeof p.text === \"string\" && p.text.length > 0) {\n yield { type: \"text\", delta: p.text };\n } else if (p.functionCall) {\n toolCalls.push(fromProviderToolCall({ functionCall: p.functionCall }, \"gemini\"));\n }\n }\n if (candidate?.finishReason) finishReason = candidate.finishReason;\n if (chunk.usageMetadata) {\n inputTokens = chunk.usageMetadata.promptTokenCount ?? inputTokens;\n outputTokens = chunk.usageMetadata.candidatesTokenCount ?? outputTokens;\n }\n }\n\n for (const tc of toolCalls) {\n yield { type: \"tool_call\", id: tc.id, name: tc.name, args: tc.arguments };\n }\n const usage = freshUsage({\n provider: \"gemini\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"chat\",\n inputTokens,\n outputTokens,\n });\n yield { type: \"usage\", costUsd: usage.costUsd, model: usage.model, usage };\n yield {\n type: \"finish\",\n reason: toolCalls.length > 0 ? \"tool_calls\" : mapGeminiFinish(finishReason),\n };\n }\n\n // Image generation (F013) via generateContent with IMAGE response modality.\n // Gemini returns the image inline as base64 (not a hosted URL like fal), so we\n // hand it back as a data: URL. Built to match cms's nano-banana request.\n async function image(req: ImageRequest): Promise<ImageResult> {\n const apiKey = resolveKey();\n // Direct fetch (injectable for tests) — generateContent is JSON in/out but\n // we read inline image bytes, so we don't route through httpTransport here.\n const fetchImpl = config.fetch ?? fetch;\n const res = await fetchImpl(`${baseUrl}/models/${req.spec.model}:generateContent?key=${encodeURIComponent(apiKey)}`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n contents: [{ role: \"user\", parts: [{ text: req.prompt }] }],\n // The multimodal image model can return text + image; ask for both.\n generationConfig: { responseModalities: [\"TEXT\", \"IMAGE\"] },\n }),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`gemini image ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as GeminiResponse & {\n candidates?: { content?: { parts?: GeminiImagePart[] } }[];\n promptFeedback?: { blockReason?: string };\n };\n if (data.promptFeedback?.blockReason) {\n throw new Error(`gemini image blocked: ${data.promptFeedback.blockReason}`);\n }\n let url: string | undefined;\n for (const p of data.candidates?.[0]?.content?.parts ?? []) {\n // Some responses use camelCase inlineData, others snake_case inline_data.\n const inline = p.inlineData ?? p.inline_data;\n const mime = inline?.mimeType ?? inline?.mime_type;\n const b64 = inline?.data;\n if (mime && b64) {\n url = `data:${mime};base64,${b64}`;\n break;\n }\n }\n if (!url) throw new Error(\"gemini image: response contained no inline image data\");\n const usage = freshUsage({\n provider: \"gemini\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"image\",\n inputTokens: data.usageMetadata?.promptTokenCount ?? 0,\n outputTokens: data.usageMetadata?.candidatesTokenCount ?? 0,\n });\n usage.costUsd = config.pricePerImage ?? GEMINI_IMAGE_PRICE_PER_IMAGE[req.spec.model] ?? 0;\n return { url, usage };\n }\n\n // Image-to-video (F024) via Veo on the Gemini API — :predictLongRunning. Submit\n // returns an operation; poll until done; the result is an auth-gated file URI, so\n // we download the bytes with the key and hand them back (the URI alone needs auth).\n async function animate(req: AnimateRequest): Promise<AnimateResult> {\n const apiKey = resolveKey();\n const fetchImpl = config.fetch ?? fetch;\n const pollIntervalMs = config.pollIntervalMs ?? 5000;\n const deadline = Date.now() + (config.videoTimeoutMs ?? 300000);\n\n // Input image → inline base64 + mime (URL is fetched to bytes first).\n const { data, mimeType } = await toInlineImage(req.image, fetchImpl);\n const parameters: Record<string, unknown> = {};\n // durationSeconds must be a NUMBER (the API rejects a string, despite some docs).\n if (req.durationSec !== undefined) parameters.durationSeconds = req.durationSec;\n if (req.resolution !== undefined) parameters.resolution = req.resolution;\n // Veo's predict image field is bytesBase64Encoded + mimeType (NOT generateContent's\n // inlineData — the API rejects that: \"inlineData isn't supported by this model\").\n const body = {\n instances: [{ prompt: req.prompt ?? \"\", image: { bytesBase64Encoded: data, mimeType } }],\n ...(Object.keys(parameters).length ? { parameters } : {}),\n };\n\n const submit = await fetchImpl(\n `${baseUrl}/models/${req.spec.model}:predictLongRunning?key=${encodeURIComponent(apiKey)}`,\n { method: \"POST\", headers: { \"content-type\": \"application/json\" }, body: JSON.stringify(body) },\n );\n if (!submit.ok) {\n throw new Error(`gemini animate ${submit.status}: ${(await submit.text().catch(() => \"\")).slice(0, 300)}`);\n }\n const op = (await submit.json()) as { name?: string };\n if (!op.name) throw new Error(\"gemini animate: no operation name in submit response\");\n\n // Poll the operation until done.\n let videoUri: string | undefined;\n for (;;) {\n const poll = await fetchImpl(`${baseUrl}/${op.name}?key=${encodeURIComponent(apiKey)}`, {\n headers: { \"content-type\": \"application/json\" },\n });\n if (!poll.ok) throw new Error(`gemini animate poll ${poll.status}`);\n const opData = (await poll.json()) as VeoOperation;\n if (opData.error) throw new Error(`gemini animate: ${opData.error.message ?? \"operation error\"}`);\n if (opData.done) {\n videoUri = opData.response?.generateVideoResponse?.generatedSamples?.[0]?.video?.uri;\n if (!videoUri) throw new Error(`gemini animate: done but no video uri: ${JSON.stringify(opData.response).slice(0, 300)}`);\n break;\n }\n if (Date.now() >= deadline) throw new Error(\"gemini animate: timed out\");\n await new Promise((r) => setTimeout(r, pollIntervalMs));\n }\n\n // Download the bytes (the URI is auth-gated + short-lived).\n const dl = await fetchImpl(videoUri.includes(\"key=\") ? videoUri : `${videoUri}${videoUri.includes(\"?\") ? \"&\" : \"?\"}key=${encodeURIComponent(apiKey)}`);\n if (!dl.ok) throw new Error(`gemini animate download ${dl.status}`);\n const bytes = new Uint8Array(await dl.arrayBuffer());\n\n const usage = freshUsage({\n provider: \"gemini\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"animate\",\n inputTokens: 0,\n outputTokens: 0,\n });\n const perSec = config.pricePerSecond ?? VEO_PRICE_PER_SEC[req.spec.model] ?? 0;\n usage.costUsd = perSec * (req.durationSec ?? 8);\n return { url: videoUri, bytes, mimeType: \"video/mp4\", usage };\n }\n\n return { name: \"gemini\", chat, chatStream, image, animate, vision: chat };\n}\n\n/** A Veo predictLongRunning operation result shape. */\ninterface VeoOperation {\n done?: boolean;\n error?: { message?: string };\n response?: {\n generateVideoResponse?: {\n generatedSamples?: { video?: { uri?: string } }[];\n };\n };\n}\n\n/** Resolve an image input to { data(base64), mimeType } — a URL is fetched to bytes. */\nasync function toInlineImage(\n image: string | Uint8Array,\n fetchImpl: typeof fetch,\n): Promise<{ data: string; mimeType: string }> {\n if (typeof image !== \"string\") {\n return { data: Buffer.from(image).toString(\"base64\"), mimeType: sniffMime(image) };\n }\n if (/^https?:\\/\\//i.test(image)) {\n const res = await fetchImpl(image);\n if (!res.ok) throw new Error(`gemini animate: failed to fetch image (${res.status})`);\n const bytes = new Uint8Array(await res.arrayBuffer());\n const mimeType = res.headers.get(\"content-type\") ?? sniffMime(bytes);\n return { data: Buffer.from(bytes).toString(\"base64\"), mimeType };\n }\n // A data: URI or bare base64.\n const comma = image.startsWith(\"data:\") ? image.indexOf(\",\") : -1;\n const b64 = comma >= 0 ? image.slice(comma + 1) : image;\n const mimeType = image.startsWith(\"data:\") ? image.slice(5, image.indexOf(\";\")) : \"image/png\";\n return { data: b64, mimeType };\n}\n\nfunction sniffMime(b: Uint8Array): string {\n if (b[0] === 0x89 && b[1] === 0x50) return \"image/png\";\n if (b[0] === 0x47 && b[1] === 0x49) return \"image/gif\";\n if (b[0] === 0x52 && b[1] === 0x49 && b[8] === 0x57) return \"image/webp\";\n return \"image/jpeg\";\n}\n\n/** Image part shape on a generateContent response (camel + snake aliases). */\ninterface GeminiInline {\n mimeType?: string;\n mime_type?: string;\n data?: string;\n}\ninterface GeminiImagePart {\n text?: string;\n inlineData?: GeminiInline;\n inline_data?: GeminiInline;\n}\n\n/** Map Gemini finishReason → the SDK's ChatStreamEvent finish reason. */\nfunction mapGeminiFinish(reason: string | null): \"end_turn\" | \"tool_calls\" | \"length\" | \"stop\" {\n switch (reason) {\n case \"MAX_TOKENS\":\n return \"length\";\n case \"STOP\":\n return \"end_turn\";\n default:\n return reason ? \"stop\" : \"end_turn\";\n }\n}\n","// DeepInfra adapter (F4.3). DeepInfra exposes an OpenAI-compatible endpoint, so\n// this is the shared core pointed at DeepInfra's base URL + key. No extra deps.\nimport { makeOpenAICompatibleAdapter } from \"./openai-compatible.js\";\nimport type { ProviderAdapter } from \"../types.js\";\n\nexport function deepinfraAdapter(\n config: { apiKey?: string; baseUrl?: string } = {},\n): ProviderAdapter {\n return makeOpenAICompatibleAdapter({\n name: \"deepinfra\",\n baseUrl: config.baseUrl ?? \"https://api.deepinfra.com/v1/openai\",\n apiKey: config.apiKey,\n });\n}\n","// OpenRouter adapter (F4.4). Meta-router with an OpenAI-compatible API — reuses\n// the shared core + OpenRouter's attribution headers. Any upstream model is\n// reachable by its slug, e.g. \"minimax/minimax-m2.7\", \"google/gemini-2.5-flash\".\nimport { makeOpenAICompatibleAdapter } from \"./openai-compatible.js\";\nimport type { ProviderAdapter } from \"../types.js\";\n\nexport function openrouterAdapter(\n config: { apiKey?: string; baseUrl?: string; referer?: string; title?: string } = {},\n): ProviderAdapter {\n return makeOpenAICompatibleAdapter({\n name: \"openrouter\",\n baseUrl: config.baseUrl ?? \"https://openrouter.ai/api/v1\",\n apiKey: config.apiKey,\n extraHeaders: {\n \"HTTP-Referer\": config.referer ?? \"https://broberg.ai\",\n \"X-Title\": config.title ?? \"@broberg/ai-sdk\",\n },\n // OpenRouter returns ground-truth usage.cost (USD) when usage:{include:true}\n // is set — use it over the local pricing-table estimate (F010).\n costFromResponseField: true,\n });\n}\n","// Requesty adapter (F028). An OpenAI-compatible AI gateway (400+ models, 30+\n// providers) — a drop-in alternative to the `openrouter` upstream. Reuses the\n// shared OpenAI-compatible core; only the base URL + key differ. Requesty returns\n// ground-truth `usage.cost`, so cost is exact (not a table estimate). Key from\n// REQUESTY_API_KEY. EU data-residency endpoint via `eu:true`.\n//\n// GDPR note: the EU endpoint keeps only Requesty's GATEWAY in the EU (Frankfurt).\n// End-to-end EU residency still requires an EU-region MODEL slug (Bedrock\n// `@eu-central-1`, Vertex `@eu`, Azure `@swedencentral`, Mistral EU-default) — a\n// global slug routes inference outside the EU despite the EU endpoint.\nimport { makeOpenAICompatibleAdapter } from \"./openai-compatible.js\";\nimport type { ProviderAdapter } from \"../types.js\";\n\nconst US_BASE = \"https://router.requesty.ai/v1\";\nconst EU_BASE = \"https://router.eu.requesty.ai/v1\";\n\nexport function requestyAdapter(\n config: { apiKey?: string; baseUrl?: string; eu?: boolean; referer?: string; title?: string } = {},\n): ProviderAdapter {\n return makeOpenAICompatibleAdapter({\n name: \"requesty\",\n baseUrl: config.baseUrl ?? (config.eu ? EU_BASE : US_BASE),\n apiKey: config.apiKey,\n extraHeaders: {\n \"HTTP-Referer\": config.referer ?? \"https://broberg.ai\",\n \"X-Title\": config.title ?? \"@broberg/ai-sdk\",\n },\n // Requesty returns ground-truth usage.cost (USD) by default — use it over the\n // local pricing-table estimate (same as OpenRouter, F010).\n costFromResponseField: true,\n });\n}\n","// DeepSeek adapter (F030) — the opt-in NON-PII secondary route for the Anthropic\n// phase-out. DeepSeek's direct API is OpenAI-compatible, so this reuses the shared\n// core; only base URL + key differ. Reached via `override:{ provider:\"deepseek\",\n// model:\"…\" }` — never a default tier. Key from DEEPSEEK_API_KEY.\n//\n// GDPR: DeepSeek is CN-hosted → NOT GDPR-safe. Use ONLY for non-PII workloads\n// (e.g. public web/article scanning). Personal data stays on Mistral EU.\n//\n// Models (direct api.deepseek.com): `deepseek-chat` (non-thinking) and\n// `deepseek-reasoner` (thinking) — both DEPRECATE 2026-07-24 and map to\n// `deepseek-v4-flash`. Prefer `deepseek-v4-flash` going forward (same model, not\n// sunset). The direct API does NOT return a cost field → cost comes from the\n// pricing table (verify rates against a real key; see src/cost/pricing.ts).\nimport { makeOpenAICompatibleAdapter } from \"./openai-compatible.js\";\nimport type { ProviderAdapter } from \"../types.js\";\n\nexport function deepseekAdapter(\n config: { apiKey?: string; baseUrl?: string } = {},\n): ProviderAdapter {\n return makeOpenAICompatibleAdapter({\n name: \"deepseek\", // → key DEEPSEEK_API_KEY\n baseUrl: config.baseUrl ?? \"https://api.deepseek.com/v1\",\n apiKey: config.apiKey,\n // Direct API returns no usage.cost → price from the table (not response).\n costFromResponseField: false,\n });\n}\n","// Mistral adapter. Mistral's La Plateforme exposes an OpenAI-compatible chat\n// endpoint (the shared core), plus two specialty endpoints we add here:\n// /ocr (F016.2, per-page) and /moderations (F016.4, per-token). Key resolved\n// from MISTRAL_API_KEY when not passed.\nimport { makeOpenAICompatibleAdapter } from \"./openai-compatible.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n OcrRequest,\n OcrResult,\n OcrPage,\n ModerationRequest,\n ModerationResult,\n ModerationItem,\n EmbeddingRequest,\n EmbeddingResult,\n TranscribeRequest,\n TranscribeResult,\n BatchRequestItem,\n BatchJob,\n BatchResultItem,\n TierSpec,\n} from \"../types.js\";\n\n/** Per-page USD for Mistral OCR ($2 / 1000 pages). Overridable via config. */\nconst MISTRAL_OCR_PRICE_PER_PAGE = 0.002;\n\n/** Per-minute USD for Voxtral transcription models (F016.3). */\nconst VOXTRAL_PRICE_PER_MIN: Record<string, number> = {\n \"voxtral-mini-latest\": 0.002,\n \"voxtral-mini-2507\": 0.002,\n \"voxtral-mini-2602\": 0.002,\n};\n\nexport function mistralAdapter(\n config: { apiKey?: string; baseUrl?: string; fetch?: typeof fetch; pricePerPage?: number } = {},\n): ProviderAdapter {\n const baseUrl = config.baseUrl ?? \"https://api.mistral.ai/v1\";\n const base = makeOpenAICompatibleAdapter({ name: \"mistral\", baseUrl, apiKey: config.apiKey });\n\n function key(): string {\n const k = config.apiKey ?? process.env.MISTRAL_API_KEY;\n if (!k) throw new Error(\"mistral adapter: API key not set (env MISTRAL_API_KEY)\");\n return k;\n }\n const fetchImpl = config.fetch ?? fetch;\n\n // OCR (F016.2) — POST /ocr. document is a URL/data-URL; image/* routes as an\n // image, anything else as a document (PDF etc.). Billed per page processed.\n async function ocr(req: OcrRequest): Promise<OcrResult> {\n const isImage = (req.mimeType ?? \"\").startsWith(\"image/\");\n const url =\n typeof req.document === \"string\"\n ? req.document\n : `data:${req.mimeType ?? \"application/pdf\"};base64,${Buffer.from(req.document).toString(\"base64\")}`;\n const document = isImage\n ? { type: \"image_url\", image_url: url }\n : { type: \"document_url\", document_url: url };\n\n const res = await fetchImpl(`${baseUrl}/ocr`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: `Bearer ${key()}` },\n body: JSON.stringify({ model: req.spec.model, document }),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`mistral ocr ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as {\n pages?: { index?: number; markdown?: string }[];\n usage_info?: { pages_processed?: number };\n };\n const pages: OcrPage[] = (data.pages ?? []).map((p, i) => ({\n index: p.index ?? i,\n markdown: p.markdown ?? \"\",\n }));\n const pagesProcessed = data.usage_info?.pages_processed ?? pages.length;\n const usage = freshUsage({\n provider: \"mistral\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"ocr\",\n inputTokens: 0,\n outputTokens: 0,\n });\n usage.costUsd = pagesProcessed * (config.pricePerPage ?? MISTRAL_OCR_PRICE_PER_PAGE);\n return { pages, usage };\n }\n\n // Moderation (F016.4) — POST /moderations. Returns per-input category booleans\n // + scores; `flagged` = any category true. Billed per input token (estimated\n // from input length when the API omits a usage count).\n async function moderate(req: ModerationRequest): Promise<ModerationResult> {\n const res = await fetchImpl(`${baseUrl}/moderations`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: `Bearer ${key()}` },\n body: JSON.stringify({ model: req.spec.model, input: req.input }),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`mistral moderation ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as {\n results?: { categories?: Record<string, boolean>; category_scores?: Record<string, number> }[];\n usage?: { prompt_tokens?: number };\n };\n const results: ModerationItem[] = (data.results ?? []).map((r) => {\n const categories = r.categories ?? {};\n return {\n flagged: Object.values(categories).some(Boolean),\n categories,\n categoryScores: r.category_scores ?? {},\n };\n });\n // The moderation endpoint usually omits token counts → estimate from input.\n const estIn = req.input.reduce((n, s) => n + Math.ceil(s.length / 4), 0);\n const usage = freshUsage({\n provider: \"mistral\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"moderation\",\n inputTokens: data.usage?.prompt_tokens ?? estIn,\n outputTokens: 0,\n });\n return { results, usage };\n }\n\n // Embeddings (F016.5) — POST /embeddings (OpenAI-compatible). Per-token input.\n async function embedding(req: EmbeddingRequest): Promise<EmbeddingResult> {\n const res = await fetchImpl(`${baseUrl}/embeddings`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: `Bearer ${key()}` },\n body: JSON.stringify({ model: req.spec.model, input: req.input }),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`mistral embeddings ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as {\n data?: { embedding: number[] }[];\n usage?: { prompt_tokens?: number; total_tokens?: number };\n };\n const vectors = (data.data ?? []).map((d) => d.embedding);\n const usage = freshUsage({\n provider: \"mistral\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"embedding\",\n inputTokens: data.usage?.prompt_tokens ?? data.usage?.total_tokens ?? 0,\n outputTokens: 0,\n });\n return { vectors, usage };\n }\n\n // Transcribe (F016.3) — Voxtral via OpenAI-compatible /audio/transcriptions\n // (multipart). Per-minute cost when durationSec is supplied.\n async function transcribe(req: TranscribeRequest): Promise<TranscribeResult> {\n const form = new FormData();\n form.append(\"file\", new Blob([req.audio]), \"audio\");\n form.append(\"model\", req.spec.model);\n if (req.language) form.append(\"language\", req.language);\n const res = await fetchImpl(`${baseUrl}/audio/transcriptions`, {\n method: \"POST\",\n headers: { authorization: `Bearer ${key()}` },\n body: form,\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`mistral transcribe ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as { text?: string };\n const usage = freshUsage({\n provider: \"mistral\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"transcribe\",\n inputTokens: 0,\n outputTokens: 0,\n });\n if (req.durationSec !== undefined) {\n usage.costUsd = (req.durationSec / 60) * (VOXTRAL_PRICE_PER_MIN[req.spec.model] ?? 0);\n }\n return { text: data.text ?? \"\", usage };\n }\n\n // Batch (F016.1) — async chat at 50% cost. Upload a JSONL of requests → create\n // a job → poll status → download results. Each line: {custom_id, body:{model,messages}}.\n async function batchSubmit(req: { items: BatchRequestItem[]; spec: TierSpec }): Promise<BatchJob> {\n const jsonl = req.items\n .map((it) =>\n JSON.stringify({\n custom_id: it.customId,\n body: { model: req.spec.model, messages: [{ role: \"user\", content: it.prompt }] },\n }),\n )\n .join(\"\\n\");\n // Upload the input file (multipart, purpose=batch).\n const form = new FormData();\n form.append(\"purpose\", \"batch\");\n form.append(\"file\", new Blob([jsonl], { type: \"application/jsonl\" }), \"batch.jsonl\");\n const up = await fetchImpl(`${baseUrl}/files`, {\n method: \"POST\",\n headers: { authorization: `Bearer ${key()}` },\n body: form,\n });\n if (!up.ok) throw new Error(`mistral batch upload ${up.status}: ${(await up.text().catch(() => \"\")).slice(0, 200)}`);\n const fileId = ((await up.json()) as { id?: string }).id;\n // Create the batch job.\n const job = await fetchImpl(`${baseUrl}/batch/jobs`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: `Bearer ${key()}` },\n body: JSON.stringify({ input_files: [fileId], model: req.spec.model, endpoint: \"/v1/chat/completions\" }),\n });\n if (!job.ok) throw new Error(`mistral batch job ${job.status}: ${(await job.text().catch(() => \"\")).slice(0, 200)}`);\n const data = (await job.json()) as { id?: string; status?: string; total_requests?: number };\n return { jobId: data.id ?? \"\", status: data.status ?? \"queued\", total: data.total_requests };\n }\n\n async function batchStatus(req: { jobId: string; spec: TierSpec }): Promise<BatchJob> {\n const res = await fetchImpl(`${baseUrl}/batch/jobs/${req.jobId}`, { headers: { authorization: `Bearer ${key()}` } });\n if (!res.ok) throw new Error(`mistral batch status ${res.status}`);\n const d = (await res.json()) as { id?: string; status?: string; total_requests?: number; succeeded_requests?: number };\n return { jobId: d.id ?? req.jobId, status: d.status ?? \"unknown\", total: d.total_requests, completed: d.succeeded_requests };\n }\n\n async function batchResults(req: { jobId: string; spec: TierSpec }): Promise<BatchResultItem[]> {\n const job = await fetchImpl(`${baseUrl}/batch/jobs/${req.jobId}`, { headers: { authorization: `Bearer ${key()}` } });\n if (!job.ok) throw new Error(`mistral batch results ${job.status}`);\n const outputFile = ((await job.json()) as { output_file?: string }).output_file;\n if (!outputFile) throw new Error(\"mistral batch: job has no output_file yet (not finished)\");\n const content = await fetchImpl(`${baseUrl}/files/${outputFile}/content`, { headers: { authorization: `Bearer ${key()}` } });\n if (!content.ok) throw new Error(`mistral batch download ${content.status}`);\n const lines = (await content.text()).trim().split(\"\\n\").filter(Boolean);\n return lines.map((line) => {\n const row = JSON.parse(line) as { custom_id?: string; response?: { body?: { choices?: { message?: { content?: string } }[] } } };\n return { customId: row.custom_id ?? \"\", text: row.response?.body?.choices?.[0]?.message?.content ?? \"\" };\n });\n }\n\n return { ...base, ocr, moderate, embedding, transcribe, batchSubmit, batchStatus, batchResults };\n}\n","// ElevenLabs adapter (F020). Text-to-Dialogue (eleven_v3) turns a manuscript of\n// {text, voice_id} turns into ONE cohesive multi-voice audio episode — the\n// \"instant podcast\" primitive. Also single-voice TTS + voice listing. Audio out\n// is MP3 bytes; billed per character. Key from ELEVENLABS_API_KEY.\nimport { freshUsage } from \"../cost/usage.js\";\nimport type { ProviderAdapter, DialogueRequest, TtsRequest, PodcastResult } from \"../types.js\";\n\n/** USD per 1000 characters (ElevenLabs bills per char; API overage ≈ $0.10–0.18/1k). */\nconst ELEVENLABS_PRICE_PER_1K_CHARS = 0.15;\n\n/** Curated Danish voices (F020.3) — friendly name → ElevenLabs voiceId. Apps can\n * pass these names to `ai.podcast`/`ai.tts` instead of raw IDs. */\nexport const ELEVENLABS_DANISH_VOICES: Record<string, string> = {\n soren: \"xj6X4BCUsv9oxohm1E8o\",\n jesper: \"Bl1YwS3uJac5zEOSNESn\",\n mads: \"BIWC0507fYMfhPcAEIRP\",\n noam: \"V34B5u5UbLdNJVEkcgXp\",\n camilla: \"4RklGmuxoAskAbGXplXN\",\n};\n\n/** Resolve a curated voice name to its voiceId; pass a raw voiceId through unchanged. */\nexport function resolveVoice(nameOrId: string): string {\n return ELEVENLABS_DANISH_VOICES[nameOrId] ?? nameOrId;\n}\n\nexport interface ElevenLabsVoice {\n voiceId: string;\n name: string;\n language?: string;\n}\n\nexport function elevenlabsAdapter(\n config: { apiKey?: string; baseUrl?: string; fetch?: typeof fetch; pricePer1kChars?: number } = {},\n): ProviderAdapter & {\n listVoices(): Promise<ElevenLabsVoice[]>;\n} {\n const baseUrl = config.baseUrl ?? \"https://api.elevenlabs.io/v1\";\n const fetchImpl = config.fetch ?? fetch;\n\n function key(): string {\n const k = config.apiKey ?? process.env.ELEVENLABS_API_KEY;\n if (!k) throw new Error(\"elevenlabs adapter: API key not set (env ELEVENLABS_API_KEY)\");\n return k;\n }\n\n function priceFor(chars: number, model: string): ReturnType<typeof freshUsage> {\n const usage = freshUsage({\n provider: \"elevenlabs\",\n model,\n transport: \"http\",\n capability: \"podcast\",\n inputTokens: 0,\n outputTokens: 0,\n });\n usage.costUsd = (chars / 1000) * (config.pricePer1kChars ?? ELEVENLABS_PRICE_PER_1K_CHARS);\n return usage;\n }\n\n // Multi-voice dialogue → one episode. POST /text-to-dialogue.\n async function dialogue(req: DialogueRequest): Promise<PodcastResult> {\n const res = await fetchImpl(`${baseUrl}/text-to-dialogue`, {\n method: \"POST\",\n headers: { \"xi-api-key\": key(), \"content-type\": \"application/json\", accept: \"audio/mpeg\" },\n body: JSON.stringify({\n model_id: req.spec.model,\n inputs: req.inputs.map((t) => ({ text: t.text, voice_id: t.voiceId })),\n ...(req.format ? { output_format: req.format } : {}),\n }),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`elevenlabs dialogue ${res.status}: ${body.slice(0, 300)}`);\n }\n const audio = new Uint8Array(await res.arrayBuffer());\n const chars = req.inputs.reduce((n, t) => n + t.text.length, 0);\n return { audio, mimeType: \"audio/mpeg\", usage: priceFor(chars, req.spec.model) };\n }\n\n // Single-voice TTS. POST /text-to-speech/{voice_id}.\n async function tts(req: TtsRequest): Promise<PodcastResult> {\n const model = req.spec.model;\n const res = await fetchImpl(`${baseUrl}/text-to-speech/${req.voiceId}`, {\n method: \"POST\",\n headers: { \"xi-api-key\": key(), \"content-type\": \"application/json\", accept: \"audio/mpeg\" },\n body: JSON.stringify({ text: req.text, model_id: model }),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`elevenlabs tts ${res.status}: ${body.slice(0, 300)}`);\n }\n const audio = new Uint8Array(await res.arrayBuffer());\n return { audio, mimeType: \"audio/mpeg\", usage: priceFor(req.text.length, model) };\n }\n\n async function listVoices(): Promise<ElevenLabsVoice[]> {\n const res = await fetchImpl(`${baseUrl}/voices`, { headers: { \"xi-api-key\": key() } });\n if (!res.ok) throw new Error(`elevenlabs voices ${res.status}`);\n const data = (await res.json()) as { voices?: { voice_id: string; name: string; labels?: { language?: string } }[] };\n return (data.voices ?? []).map((v) => ({ voiceId: v.voice_id, name: v.name, language: v.labels?.language }));\n }\n\n return { name: \"elevenlabs\", dialogue, tts, listVoices };\n}\n","// Azure Speech (Cognitive Services) TTS adapter (F026). Natural EU-resident\n// neural Danish read-aloud behind the existing `ai.tts` capability. Azure Speech\n// is NOT reachable via OpenRouter (that proxies LLM chat/completions only) — this\n// is a direct SSML REST call, region-pinned to an EU host. Audio out is MP3 bytes;\n// billed per character. Key + region from AZURE_SPEECH_KEY / AZURE_SPEECH_REGION.\nimport { freshUsage } from \"../cost/usage.js\";\nimport type { ProviderAdapter, TtsRequest, PodcastResult, TranscribeRequest, TranscribeResult } from \"../types.js\";\n\n/** USD per 1000 characters. ≈ Azure neural standard ($16 / 1M chars) — verify on\n * azure.microsoft.com/pricing; override via config.pricePer1kChars. */\nconst AZURE_TTS_PRICE_PER_1K_CHARS = 0.016;\n\n/** USD per audio-minute for speech-to-text. ≈ Azure standard STT ($1 / audio-hour\n * = $0.0167/min) — verify the fast-transcription rate on azure.microsoft.com/pricing;\n * override via config.sttPricePerMin. */\nconst AZURE_STT_PRICE_PER_MIN = 0.0167;\n\n/** Fast-transcription REST api-version. 2025-10-15 is required for the `phraseList`\n * biasing field (2024-11-15 rejects it as \"Invalid JSON\"); both serve plain\n * transcription. Override via config.sttApiVersion. (Live-verified F029.) */\nconst DEFAULT_STT_API_VERSION = \"2025-10-15\";\n\n/** Default region — EU/GDPR-clean. Override via config.region / AZURE_SPEECH_REGION. */\nconst DEFAULT_REGION = \"westeurope\";\n\n/** Default MP3 output (Azure's X-Microsoft-OutputFormat). */\nconst DEFAULT_FORMAT = \"audio-24khz-48kbitrate-mono-mp3\";\n\n/** Short language code → Azure STT locale. A full locale (\"da-DK\") passes through;\n * omitted language defaults to da-DK (the EU-Danish use-case this was built for). */\nconst AZURE_LOCALE_MAP: Record<string, string> = {\n da: \"da-DK\", en: \"en-US\", de: \"de-DE\", sv: \"sv-SE\", nb: \"nb-NO\", no: \"nb-NO\",\n fi: \"fi-FI\", nl: \"nl-NL\", fr: \"fr-FR\", es: \"es-ES\", it: \"it-IT\", pt: \"pt-PT\",\n};\nfunction toAzureLocale(lang?: string): string {\n if (!lang) return \"da-DK\";\n if (lang.includes(\"-\")) return lang;\n return AZURE_LOCALE_MAP[lang.toLowerCase()] ?? lang;\n}\n\n/** A curated Danish-speaking Azure voice, exposed so a consuming app can render a\n * picker. `native` = a true da-DK voice (most natural); otherwise a multilingual\n * voice that also speaks Danish (Azure has only 2 native da-DK voices). */\nexport interface AzureVoiceInfo {\n /** Friendly name a caller passes as `voice` (e.g. \"christel\"). */\n name: string;\n /** Full Azure voice name (e.g. \"da-DK-ChristelNeural\"). */\n voiceId: string;\n gender: \"female\" | \"male\";\n /** Display label for a UI picker. */\n display: string;\n /** True for the 2 native da-DK voices; false for multilingual voices speaking Danish. */\n native: boolean;\n /** Per-voice default speaking rate, applied when a call passes no explicit `rate`\n * (e.g. Christel reads a touch fast, so her natural default is 0.85). Omitted = 1 (normal). */\n defaultRate?: number;\n}\n\n/** Curated da-DK roster (F026) — 2 native + 4 multilingual, 3 of each gender.\n * Verified against Azure's voices/list (only Christel + Jeppe are native da-DK). */\nexport const AZURE_DANISH_VOICE_LIST: AzureVoiceInfo[] = [\n { name: \"christel\", voiceId: \"da-DK-ChristelNeural\", gender: \"female\", display: \"Christel\", native: true, defaultRate: 0.85 },\n { name: \"seraphina\", voiceId: \"de-DE-SeraphinaMultilingualNeural\", gender: \"female\", display: \"Seraphina\", native: false },\n { name: \"ava\", voiceId: \"en-US-AvaMultilingualNeural\", gender: \"female\", display: \"Ava\", native: false },\n { name: \"jeppe\", voiceId: \"da-DK-JeppeNeural\", gender: \"male\", display: \"Jeppe\", native: true },\n { name: \"florian\", voiceId: \"de-DE-FlorianMultilingualNeural\", gender: \"male\", display: \"Florian\", native: false },\n { name: \"andrew\", voiceId: \"en-US-AndrewMultilingualNeural\", gender: \"male\", display: \"Andrew\", native: false },\n];\n\n/** Friendly name → full Azure voice name. Distinct from ELEVENLABS_DANISH_VOICES so\n * the client's resolveVoice passes these through unchanged to this adapter. */\nexport const AZURE_DANISH_VOICES: Record<string, string> = Object.fromEntries(\n AZURE_DANISH_VOICE_LIST.map((v) => [v.name, v.voiceId]),\n);\n\n/** The curated Danish voice roster, for a consuming app to present in a picker. */\nexport function listAzureDanishVoices(): AzureVoiceInfo[] {\n return AZURE_DANISH_VOICE_LIST;\n}\n\n/** Resolve a curated friendly name to its full Azure voice; pass a full voice name\n * (e.g. \"da-DK-ChristelNeural\") through unchanged. */\nexport function resolveAzureVoice(nameOrVoice: string): string {\n return AZURE_DANISH_VOICES[nameOrVoice] ?? nameOrVoice;\n}\n\n/** XML-escape so a `&`/`<` in the text can't break the SSML envelope. */\nfunction xmlEscape(s: string): string {\n return s\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n/** Derive the BCP-47 locale from a voice name: \"da-DK-ChristelNeural\" → \"da-DK\". */\nfunction localeOf(voice: string): string {\n const parts = voice.split(\"-\");\n return parts.length >= 2 ? `${parts[0]}-${parts[1]}` : \"en-US\";\n}\n\nexport function azureAdapter(\n config: {\n apiKey?: string;\n region?: string;\n fetch?: typeof fetch;\n pricePer1kChars?: number;\n /** USD per audio-minute for transcribe (overrides AZURE_STT_PRICE_PER_MIN). */\n sttPricePerMin?: number;\n /** STT base URL override (e.g. a resource custom domain). */\n sttBaseUrl?: string;\n /** Resource name → custom-domain STT host `{resource}.cognitiveservices.azure.com`\n * (or env AZURE_SPEECH_RESOURCE). Without it, STT uses the regional host. */\n resource?: string;\n /** Fast-transcription api-version (overrides the GA default). */\n sttApiVersion?: string;\n /** phraseList biasing weight (0–2) applied when a call passes `phrases`. Default 1.5. */\n sttBiasingWeight?: number;\n } = {},\n): ProviderAdapter {\n const fetchImpl = config.fetch ?? fetch;\n\n function key(): string {\n const k = config.apiKey ?? process.env.AZURE_SPEECH_KEY;\n if (!k) throw new Error(\"azure adapter: API key not set (env AZURE_SPEECH_KEY)\");\n return k;\n }\n function region(): string {\n return config.region ?? process.env.AZURE_SPEECH_REGION ?? DEFAULT_REGION;\n }\n /** STT host. Default = regional cognitive host; a resource name (config/env) →\n * the custom-domain host (some resources require it). Live-verified per resource. */\n function sttBaseUrl(): string {\n if (config.sttBaseUrl) return config.sttBaseUrl.replace(/\\/$/, \"\");\n const resource = config.resource ?? process.env.AZURE_SPEECH_RESOURCE;\n if (resource) return `https://${resource}.cognitiveservices.azure.com`;\n return `https://${region()}.api.cognitive.microsoft.com`;\n }\n\n function priceFor(chars: number, model: string): ReturnType<typeof freshUsage> {\n const usage = freshUsage({\n provider: \"azure\",\n model,\n transport: \"http\",\n capability: \"tts\",\n inputTokens: 0,\n outputTokens: 0,\n });\n usage.costUsd = (chars / 1000) * (config.pricePer1kChars ?? AZURE_TTS_PRICE_PER_1K_CHARS);\n return usage;\n }\n\n // Single-voice TTS. POST .../cognitiveservices/v1 with an SSML body.\n async function tts(req: TtsRequest): Promise<PodcastResult> {\n const voice = resolveAzureVoice(req.voiceId);\n const lang = req.lang ?? localeOf(voice);\n const format = req.format ?? DEFAULT_FORMAT;\n // Speaking rate via SSML <prosody>: a multiplier of the default (1 = normal,\n // 0.9 = 10% slower, 1.1 = 10% faster). An explicit req.rate wins; otherwise the\n // voice's own defaultRate (e.g. Christel = 0.85) applies; else no wrapper.\n const escaped = xmlEscape(req.text);\n const effRate = req.rate ?? AZURE_DANISH_VOICE_LIST.find((v) => v.voiceId === voice)?.defaultRate;\n const inner =\n effRate != null && effRate !== 1 ? `<prosody rate='${effRate}'>${escaped}</prosody>` : escaped;\n const ssml =\n `<speak version='1.0' xml:lang='${lang}'>` +\n `<voice name='${voice}'>${inner}</voice></speak>`;\n const res = await fetchImpl(\n `https://${region()}.tts.speech.microsoft.com/cognitiveservices/v1`,\n {\n method: \"POST\",\n headers: {\n \"Ocp-Apim-Subscription-Key\": key(),\n \"Content-Type\": \"application/ssml+xml\",\n \"X-Microsoft-OutputFormat\": format,\n },\n body: ssml,\n },\n );\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`azure tts ${res.status}: ${body.slice(0, 300)}`);\n }\n const audio = new Uint8Array(await res.arrayBuffer());\n return { audio, mimeType: \"audio/mpeg\", usage: priceFor(req.text.length, req.spec.model) };\n }\n\n // Speech-to-text (F029) via Azure fast transcription. Synchronous multipart POST\n // → { combinedPhrases:[{text}], durationMilliseconds }. da-DK forced (Voxtral can't).\n // Cost is per audio-minute from the response's real duration. EU-resident.\n async function transcribe(req: TranscribeRequest): Promise<TranscribeResult> {\n const locale = toAzureLocale(req.language);\n const definition: Record<string, unknown> = { locales: [locale] };\n // Bias toward known brand/jargon terms (F029.3) — lifts accuracy on names the\n // model wouldn't otherwise know (e.g. \"cardmem\", \"Pins\"). Other STTs ignore phrases.\n if (req.phrases && req.phrases.length > 0) {\n definition.phraseList = { phrases: req.phrases, biasingWeight: config.sttBiasingWeight ?? 1.5 };\n }\n const form = new FormData();\n form.append(\"audio\", new Blob([req.audio]), \"audio\");\n form.append(\"definition\", JSON.stringify(definition));\n const url = `${sttBaseUrl()}/speechtotext/transcriptions:transcribe?api-version=${config.sttApiVersion ?? DEFAULT_STT_API_VERSION}`;\n const res = await fetchImpl(url, {\n method: \"POST\",\n headers: { \"Ocp-Apim-Subscription-Key\": key() },\n body: form,\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`azure transcribe ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as {\n combinedPhrases?: { text?: string }[];\n durationMilliseconds?: number;\n };\n const text = data.combinedPhrases?.[0]?.text ?? \"\";\n // Prefer the API's real duration; fall back to a caller-supplied durationSec.\n const minutes =\n data.durationMilliseconds != null\n ? data.durationMilliseconds / 60000\n : (req.durationSec ?? 0) / 60;\n const usage = freshUsage({\n provider: \"azure\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"transcribe\",\n inputTokens: 0,\n outputTokens: 0,\n });\n usage.costUsd = minutes * (config.sttPricePerMin ?? AZURE_STT_PRICE_PER_MIN);\n return { text, usage };\n }\n\n return { name: \"azure\", tts, transcribe };\n}\n","// fal.ai adapter (F5.3 + F021). Image modes, both observed in the F1 inventory:\n// - sync : POST https://fal.run/{model}, image URL straight back (sanneandersen)\n// - queue : POST https://queue.fal.run/{model} → poll status → fetch result\n// F021 adds LoRA style-training (trainStyle) + LoRA inference (image loras).\n// Auth header `Authorization: Key <FAL_KEY>`. No @fal-ai/client — plain fetch.\nimport { deflateRawSync, crc32 } from \"node:zlib\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n ImageRequest,\n ImageResult,\n AnimateRequest,\n AnimateResult,\n TrainStyleRequest,\n TrainStyleResult,\n} from \"../types.js\";\n\ninterface FalImagesResponse {\n images?: { url?: string }[];\n has_nsfw_concepts?: boolean[];\n error?: unknown;\n}\ninterface FalTrainResponse {\n diffusers_lora_file?: { url?: string };\n config_file?: { url?: string };\n}\ninterface FalQueueSubmit {\n request_id?: string;\n status_url?: string;\n response_url?: string;\n}\ninterface FalQueueStatus {\n status?: \"IN_QUEUE\" | \"IN_PROGRESS\" | \"COMPLETED\" | \"FAILED\";\n}\n\nexport interface FalAdapterConfig {\n apiKey?: string;\n /** \"sync\" (default — fal.run, fast models) or \"queue\" (queue.fal.run, polled). */\n mode?: \"sync\" | \"queue\";\n syncBaseUrl?: string;\n queueBaseUrl?: string;\n pollIntervalMs?: number;\n timeoutMs?: number;\n /** Deadline for training jobs — they take minutes (default 600000 = 10 min). */\n trainTimeoutMs?: number;\n /** Deadline for video jobs — they take minutes (default 600000 = 10 min). */\n videoTimeoutMs?: number;\n fetch?: typeof fetch;\n /** Override the per-image USD price (else a built-in estimate per model, 0 if unknown). */\n pricePerImage?: number;\n /** Override the flat per-training USD price (else ~$2 estimate). */\n pricePerTraining?: number;\n /** Override the per-SECOND video USD price (else a built-in estimate per model, 0 if unknown). */\n pricePerSecond?: number;\n}\n\n// Per-image USD ESTIMATES (fal prices by megapixel/model and changes often —\n// verify before relying on these; override via config.pricePerImage). fal does\n// not return a price, so this is the SDK's best-effort cost for `usage.costUsd`.\nconst FAL_IMAGE_PRICE_ESTIMATE: Record<string, number> = {\n \"fal-ai/flux/schnell\": 0.003,\n \"fal-ai/flux/dev\": 0.025,\n \"fal-ai/flux-lora\": 0.025,\n \"fal-ai/flux-pro\": 0.05,\n \"fal-ai/flux-pro/v1.1\": 0.04,\n};\n// Flat training estimate (fal-ai/flux-lora-fast-training, ~$2; override via config).\nconst FAL_TRAIN_PRICE_ESTIMATE = 2.0;\n\n// Per-SECOND USD estimates for video models (F024). fal does not return a price,\n// and rates vary by model/resolution — these are populated from real observed fal\n// spend (a live smoke), never guessed; override via config.pricePerSecond. Unknown\n// model → 0 (cost surfaced via the live smoke, not a fabricated number).\nconst FAL_VIDEO_PRICE_PER_SEC: Record<string, number> = {};\n// Default clip length to bill when the caller doesn't pass durationSec (Veo ≈ 8s).\nconst FAL_VIDEO_DEFAULT_SEC = 8;\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nexport function falAdapter(config: FalAdapterConfig = {}): ProviderAdapter {\n const doFetch = config.fetch ?? fetch;\n const syncBase = config.syncBaseUrl ?? \"https://fal.run\";\n const queueBase = config.queueBaseUrl ?? \"https://queue.fal.run\";\n const pollIntervalMs = config.pollIntervalMs ?? 2000;\n const timeoutMs = config.timeoutMs ?? 60000;\n\n // sa flagged the gotcha: their env is FAL_API_KEY, the older convention is FAL_KEY.\n // Accept either so no repo has to alias one to the other.\n const resolveKey = () => config.apiKey ?? process.env.FAL_KEY ?? process.env.FAL_API_KEY;\n const authHeaders = (apiKey: string) => ({\n \"content-type\": \"application/json\",\n Authorization: `Key ${apiKey}`,\n });\n\n async function image(req: ImageRequest): Promise<ImageResult> {\n const apiKey = resolveKey();\n if (!apiKey) throw new Error(\"fal adapter: FAL_KEY not set\");\n const headers = authHeaders(apiKey);\n\n const body: Record<string, unknown> = { prompt: req.prompt };\n if (req.width !== undefined && req.height !== undefined) {\n body.image_size = { width: req.width, height: req.height };\n }\n if (req.loras && req.loras.length > 0) {\n body.loras = req.loras.map((l) => ({ path: l.path, scale: l.scale ?? 1 }));\n }\n\n const mode = config.mode ?? \"sync\";\n const run = (b: Record<string, unknown>) =>\n mode === \"sync\" ? runSync(req.spec.model, headers, b) : runQueue(req.spec.model, headers, b);\n\n let calls = 1;\n let { url, flagged } = await run(body);\n // F021.4 — fal's NSFW safety-checker occasionally false-positives on clean\n // LoRA output and returns a fully BLACK image (has_nsfw_concepts[0]=true).\n // When retryOnBlack is set, re-roll ONCE with a fresh seed.\n if (flagged && req.retryOnBlack) {\n calls++;\n ({ url, flagged } = await run({ ...body, seed: Math.floor(Math.random() * 1e9) }));\n }\n\n // fal returns no price; estimate per-image so usage.costUsd isn't silently 0.\n // A re-roll is a second billed generation → multiply by the call count.\n const usage = freshUsage({\n provider: \"fal\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"image\",\n inputTokens: 0,\n outputTokens: 0,\n });\n usage.costUsd = (config.pricePerImage ?? FAL_IMAGE_PRICE_ESTIMATE[req.spec.model] ?? 0) * calls;\n return { url, usage };\n }\n\n async function animate(req: AnimateRequest): Promise<AnimateResult> {\n const apiKey = resolveKey();\n if (!apiKey) throw new Error(\"fal adapter: FAL_KEY not set\");\n const headers = authHeaders(apiKey);\n\n // Input image: a URL passes through; raw bytes are uploaded to fal storage\n // (fal needs a fetchable URL, not a data: URI — same gotcha as trainStyle).\n const imageUrl =\n typeof req.image === \"string\" && /^https?:\\/\\//i.test(req.image)\n ? req.image\n : await uploadToFalStorage(toBytes(req.image), sniffImageType(req.image), \"input\", apiKey);\n\n const body: Record<string, unknown> = { image_url: imageUrl };\n if (req.prompt !== undefined) body.prompt = req.prompt;\n if (req.durationSec !== undefined) body.duration = req.durationSec;\n if (req.resolution !== undefined) body.resolution = req.resolution;\n\n // Video is long-running → always the queue, with the longer deadline.\n const result = await queueResult(req.spec.model, headers, body, config.videoTimeoutMs ?? 600000);\n const url = extractVideoUrl(result);\n if (!url) {\n throw new Error(\n `fal animate: no video url in result — keys [${Object.keys(\n (result as Record<string, unknown>) ?? {},\n ).join(\", \")}]: ${JSON.stringify(result).slice(0, 500)}`,\n );\n }\n\n const usage = freshUsage({\n provider: \"fal\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"animate\",\n inputTokens: 0,\n outputTokens: 0,\n });\n // fal returns no price → per-second estimate × duration (override config.pricePerSecond).\n const perSec = config.pricePerSecond ?? FAL_VIDEO_PRICE_PER_SEC[req.spec.model] ?? 0;\n usage.costUsd = perSec * (req.durationSec ?? FAL_VIDEO_DEFAULT_SEC);\n return { url, usage };\n }\n\n async function trainStyle(req: TrainStyleRequest): Promise<TrainStyleResult> {\n const apiKey = resolveKey();\n if (!apiKey) throw new Error(\"fal adapter: FAL_KEY not set\");\n const headers = authHeaders(apiKey);\n\n const body: Record<string, unknown> = {\n images_data_url: await resolveImagesUrl(req.images, apiKey),\n is_style: req.isStyle ?? true,\n };\n if (req.triggerWord !== undefined) body.trigger_word = req.triggerWord;\n if (req.steps !== undefined) body.steps = req.steps;\n if (req.createMasks !== undefined) body.create_masks = req.createMasks;\n\n // Training runs on the queue and takes minutes — use the longer deadline.\n const result = (await queueResult(\n req.spec.model,\n headers,\n body,\n config.trainTimeoutMs ?? 600000,\n )) as FalTrainResponse;\n // fal's LoRA trainers vary in output shape (field renames, wrappers, multiple\n // trainer endpoints). Extract defensively across known/likely locations, then\n // fall back to scanning for any *.safetensors url. If still nothing, surface the\n // RAW response so a shape mismatch is diagnosable without a key on this side.\n const { loraUrl, configUrl } = extractTrainedFiles(result);\n if (!loraUrl) {\n throw new Error(\n `fal trainStyle: no LoRA file url in result — fal returned keys [${Object.keys(\n (result as Record<string, unknown>) ?? {},\n ).join(\", \")}]: ${JSON.stringify(result).slice(0, 800)}`,\n );\n }\n\n const usage = freshUsage({\n provider: \"fal\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"trainStyle\",\n inputTokens: 0,\n outputTokens: 0,\n });\n usage.costUsd = config.pricePerTraining ?? FAL_TRAIN_PRICE_ESTIMATE;\n return { loraUrl, configUrl: configUrl ?? \"\", usage };\n }\n\n /** A hosted archive URL passes straight through; an array of image URLs is fetched,\n * zipped in-memory, and uploaded to fal storage. fal REJECTS data: URIs here\n * (\"Invalid URL: URL too long\") — images_data_url must be a real http URL it can\n * fetch, so we upload the zip and pass the returned file_url. */\n async function resolveImagesUrl(images: string | string[], apiKey: string): Promise<string> {\n if (typeof images === \"string\") return images;\n const files = await Promise.all(\n images.map(async (url, i) => {\n const res = await doFetch(url);\n if (!res.ok) throw new Error(`fal trainStyle: failed to fetch image ${url} (${res.status})`);\n return { name: fileNameFromUrl(url, i), data: new Uint8Array(await res.arrayBuffer()) };\n }),\n );\n return uploadToFalStorage(buildZip(files), \"application/zip\", \"styleset.zip\", apiKey);\n }\n\n /** Upload bytes to fal storage: initiate (auth'd) → PUT to the returned signed url\n * → return the public file_url. fal CDN serves it back, fetchable by the trainer. */\n async function uploadToFalStorage(\n bytes: Uint8Array,\n contentType: string,\n fileName: string,\n apiKey: string,\n ): Promise<string> {\n const initiate = await doFetch(\"https://rest.alpha.fal.ai/storage/upload/initiate\", {\n method: \"POST\",\n headers: { Authorization: `Key ${apiKey}`, \"content-type\": \"application/json\" },\n body: JSON.stringify({ content_type: contentType, file_name: fileName }),\n });\n if (!initiate.ok) {\n throw new Error(\n `fal storage initiate ${initiate.status}: ${(await initiate.text().catch(() => \"\")).slice(0, 200)}`,\n );\n }\n const { upload_url, file_url } = (await initiate.json()) as { upload_url: string; file_url: string };\n const put = await doFetch(upload_url, {\n method: \"PUT\",\n headers: { \"content-type\": contentType },\n body: bytes,\n });\n if (!put.ok) throw new Error(`fal storage upload PUT ${put.status}`);\n return file_url;\n }\n\n /** Returns the image url + whether fal's safety-checker flagged it (→ black image). */\n async function runSync(\n model: string,\n headers: Record<string, string>,\n body: unknown,\n ): Promise<{ url: string; flagged: boolean }> {\n const res = await doFetch(`${syncBase}/${model}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n throw new Error(`fal ${res.status}: ${(await res.text().catch(() => \"\")).slice(0, 200)}`);\n }\n const data = (await res.json()) as FalImagesResponse;\n const out = data.images?.[0]?.url;\n if (!out) throw new Error(`fal: no image url in response`);\n return { url: out, flagged: data.has_nsfw_concepts?.[0] === true };\n }\n\n async function runQueue(\n model: string,\n headers: Record<string, string>,\n body: unknown,\n ): Promise<{ url: string; flagged: boolean }> {\n const result = (await queueResult(model, headers, body, timeoutMs)) as FalImagesResponse;\n const out = result.images?.[0]?.url;\n if (!out) throw new Error(\"fal queue: no image url in result\");\n return { url: out, flagged: result.has_nsfw_concepts?.[0] === true };\n }\n\n /** Generic fal queue runner: submit → poll status → fetch+return the raw result JSON. */\n async function queueResult(\n model: string,\n headers: Record<string, string>,\n body: unknown,\n deadlineMs: number,\n ): Promise<unknown> {\n const submitRes = await doFetch(`${queueBase}/${model}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n if (!submitRes.ok) {\n throw new Error(\n `fal queue submit ${submitRes.status}: ${(await submitRes.text().catch(() => \"\")).slice(0, 200)}`,\n );\n }\n const submit = (await submitRes.json()) as FalQueueSubmit;\n const statusUrl = submit.status_url;\n const responseUrl = submit.response_url;\n if (!statusUrl || !responseUrl) throw new Error(\"fal queue: missing status/response url\");\n\n const deadline = Date.now() + deadlineMs;\n for (;;) {\n const statusRes = await doFetch(statusUrl, { headers });\n const status = (await statusRes.json()) as FalQueueStatus;\n if (status.status === \"COMPLETED\") break;\n if (status.status === \"FAILED\") throw new Error(\"fal queue: job FAILED\");\n if (Date.now() >= deadline) throw new Error(`fal queue: timed out after ${deadlineMs}ms`);\n await sleep(pollIntervalMs);\n }\n\n const resultRes = await doFetch(responseUrl, { headers });\n if (!resultRes.ok) {\n throw new Error(\n `fal queue result ${resultRes.status}: ${(await resultRes.text().catch(() => \"\")).slice(0, 300)}`,\n );\n }\n return resultRes.json();\n }\n\n return { name: \"fal\", image, animate, trainStyle };\n}\n\n/** Coerce an image input to bytes (a non-http string is treated as base64/data-URI). */\nfunction toBytes(img: string | Uint8Array): Uint8Array {\n if (typeof img !== \"string\") return img;\n const b64 = img.startsWith(\"data:\") ? img.slice(img.indexOf(\",\") + 1) : img;\n return new Uint8Array(Buffer.from(b64, \"base64\"));\n}\n\n/** Sniff a content-type from the bytes' magic (PNG/WebP/GIF), default JPEG. */\nfunction sniffImageType(img: string | Uint8Array): string {\n const b = toBytes(img);\n if (b[0] === 0x89 && b[1] === 0x50) return \"image/png\";\n if (b[0] === 0x47 && b[1] === 0x49) return \"image/gif\";\n if (b[0] === 0x52 && b[1] === 0x49 && b[8] === 0x57) return \"image/webp\";\n return \"image/jpeg\";\n}\n\n/** Find the result video URL across fal's video-output shapes (video.url, a wrapper,\n * or any *.mp4/.webm url anywhere in the response). */\nexport function extractVideoUrl(result: unknown): string | undefined {\n const r = result as Record<string, unknown> | null | undefined;\n const root = (r?.data ?? r?.response ?? r?.output ?? r) as Record<string, unknown> | null | undefined;\n return (\n urlOf(root?.video) ??\n urlOf((root?.videos as unknown[] | undefined)?.[0]) ??\n deepFindUrl(root, (u) => /\\.(mp4|webm|mov)(\\?|$)/i.test(u))\n );\n}\n\n// ── fal trained-file extraction (defensive against output-shape variance) ────\n\nfunction urlOf(v: unknown): string | undefined {\n if (typeof v === \"string\") return v;\n if (v && typeof v === \"object\" && typeof (v as { url?: unknown }).url === \"string\") {\n return (v as { url: string }).url;\n }\n return undefined;\n}\n\n/** BFS the response for the first {url}/string url matching `match`. */\nfunction deepFindUrl(obj: unknown, match: (url: string) => boolean): string | undefined {\n const stack: unknown[] = [obj];\n while (stack.length) {\n const cur = stack.pop();\n if (typeof cur === \"string\") {\n if (match(cur)) return cur;\n continue;\n }\n if (cur && typeof cur === \"object\") {\n const u = (cur as { url?: unknown }).url;\n if (typeof u === \"string\" && match(u)) return u;\n for (const v of Object.values(cur as Record<string, unknown>)) stack.push(v);\n }\n }\n return undefined;\n}\n\n/** Find the LoRA + config urls across known field names, an optional data/response/\n * output wrapper, and — as a last resort — any *.safetensors / config *.json url\n * anywhere in the response. fal's LoRA trainers vary in output shape. */\nexport function extractTrainedFiles(result: unknown): { loraUrl?: string; configUrl?: string } {\n const r = result as Record<string, unknown> | null | undefined;\n const root = (r?.data ?? r?.response ?? r?.output ?? r) as\n | Record<string, unknown>\n | null\n | undefined;\n const loraUrl =\n urlOf(root?.diffusers_lora_file) ??\n urlOf(root?.lora_file) ??\n urlOf(root?.safetensors) ??\n urlOf(root?.lora) ??\n deepFindUrl(root, (u) => /\\.safetensors(\\?|$)/i.test(u));\n const configUrl =\n urlOf(root?.config_file) ??\n urlOf(root?.config) ??\n deepFindUrl(root, (u) => /config[^/]*\\.json(\\?|$)/i.test(u));\n return { loraUrl, configUrl };\n}\n\n// ── In-memory ZIP (store via DEFLATE, node:zlib — zero new deps) ──────────────\n\nfunction fileNameFromUrl(url: string, i: number): string {\n const base = url.split(\"?\")[0]!.split(\"/\").pop() || \"\";\n return /\\.[a-z0-9]+$/i.test(base) ? base : `image_${i}.png`;\n}\n\n/** Build a spec-compliant ZIP (DEFLATE method) from named byte entries. */\nfunction buildZip(files: { name: string; data: Uint8Array }[]): Uint8Array {\n const parts: Buffer[] = [];\n const central: Buffer[] = [];\n let offset = 0;\n for (const f of files) {\n const nameBuf = Buffer.from(f.name, \"utf8\");\n const data = Buffer.from(f.data);\n const comp = deflateRawSync(data);\n const crc = crc32(data) >>> 0;\n\n const lfh = Buffer.alloc(30);\n lfh.writeUInt32LE(0x04034b50, 0); // local file header signature\n lfh.writeUInt16LE(20, 4); // version needed\n lfh.writeUInt16LE(0, 6); // flags\n lfh.writeUInt16LE(8, 8); // method = deflate\n lfh.writeUInt16LE(0, 10); // mod time\n lfh.writeUInt16LE(0x21, 12); // mod date (1980-01-01)\n lfh.writeUInt32LE(crc, 14);\n lfh.writeUInt32LE(comp.length, 18); // compressed size\n lfh.writeUInt32LE(data.length, 22); // uncompressed size\n lfh.writeUInt16LE(nameBuf.length, 26);\n lfh.writeUInt16LE(0, 28); // extra len\n parts.push(lfh, nameBuf, comp);\n\n const cdh = Buffer.alloc(46);\n cdh.writeUInt32LE(0x02014b50, 0); // central directory header signature\n cdh.writeUInt16LE(20, 4); // version made by\n cdh.writeUInt16LE(20, 6); // version needed\n cdh.writeUInt16LE(0, 8); // flags\n cdh.writeUInt16LE(8, 10); // method\n cdh.writeUInt16LE(0, 12); // mod time\n cdh.writeUInt16LE(0x21, 14); // mod date\n cdh.writeUInt32LE(crc, 16);\n cdh.writeUInt32LE(comp.length, 20);\n cdh.writeUInt32LE(data.length, 24);\n cdh.writeUInt16LE(nameBuf.length, 28);\n cdh.writeUInt16LE(0, 30); // extra len\n cdh.writeUInt16LE(0, 32); // comment len\n cdh.writeUInt16LE(0, 34); // disk number start\n cdh.writeUInt16LE(0, 36); // internal attrs\n cdh.writeUInt32LE(0, 38); // external attrs\n cdh.writeUInt32LE(offset, 42); // local header offset\n central.push(cdh, nameBuf);\n\n offset += lfh.length + nameBuf.length + comp.length;\n }\n const cd = Buffer.concat(central);\n const eocd = Buffer.alloc(22);\n eocd.writeUInt32LE(0x06054b50, 0); // end of central directory signature\n eocd.writeUInt16LE(0, 4); // disk number\n eocd.writeUInt16LE(0, 6); // cd start disk\n eocd.writeUInt16LE(files.length, 8); // entries this disk\n eocd.writeUInt16LE(files.length, 10); // total entries\n eocd.writeUInt32LE(cd.length, 12); // cd size\n eocd.writeUInt32LE(offset, 16); // cd offset\n eocd.writeUInt16LE(0, 20); // comment len\n return Buffer.concat([...parts, cd, eocd]);\n}\n","// Black Forest Labs (FLUX) adapter — F023 / F023.5. EU-RESIDENT image generation.\n//\n// GDPR CRUX (non-negotiable): this adapter hard-pins https://api.eu.bfl.ai — the\n// dedicated EU endpoint — NEVER the global api.bfl.ai (which auto-failovers to the\n// US and could route a face out of the EEA). A face = biometric personal data, so\n// EU residency is what makes this compliant; \"German company\" alone is not enough.\n// The default base is asserted in bfl.test.ts.\n//\n// Two EU-resident likeness modes (route by what ai.image is given):\n// • referenceImages (F023.5) → FLUX 2 multi-reference: 1–8 photos in the generate\n// call, NO training step. Default model flux-2-max ($0.25/img); pass\n// override:{ model:\"flux-2-pro\" } for ~half price ($0.12/img). Bytes are\n// base64-inlined into the EU call (no cross-region fetch); URLs pass through.\n// • finetune (F023) → flux-pro-1.1-ultra-finetuned, a subject trained ONCE in the\n// BFL dashboard (finetune-CREATE was retired from the public API — live-verified\n// 2026-06-16: POST /v1/finetune 404s on every region; legacy eu1/us1 hosts dead).\n// See the dashboard SOP in docs/features/F023-bfl-eu-portrait-lora.md.\n//\n// Auth header `x-key`. Request→poll: POST returns {id, polling_url, cost}; we poll the\n// EU get_result by id (deliberately NOT the returned polling_url) so a response carrying\n// a face never transits a non-EU host. BFL returns the real `cost` in credits\n// (1 credit = $0.01, official) → usage.costUsd is exact, not estimated.\nimport { freshUsage } from \"../cost/usage.js\";\nimport type { ProviderAdapter, ImageRequest, ImageResult } from \"../types.js\";\n\nconst EU_BASE = \"https://api.eu.bfl.ai\";\n/** BFL bills in credits; 1 credit = $0.01 USD (official, bfl.ai/pricing). */\nconst BFL_CREDIT_USD = 0.01;\n\ninterface BflSubmitResponse {\n id?: string;\n polling_url?: string;\n /** BFL's billed cost for this request, in credits. */\n cost?: number;\n}\ninterface BflResultResponse {\n id?: string;\n /** \"Ready\" | \"Pending\" | \"Error\" | \"Request Moderated\" | \"Content Moderated\" | \"Task not found\" */\n status?: string;\n result?: { sample?: string } | null;\n progress?: number | null;\n}\n\nexport interface BflAdapterConfig {\n apiKey?: string;\n /** EU-resident base. Do NOT point this at api.bfl.ai (global, US-failover) — see header. */\n baseUrl?: string;\n pollIntervalMs?: number;\n timeoutMs?: number;\n fetch?: typeof fetch;\n /** Override the per-image USD price (else the built-in finetuned-inference estimate). */\n pricePerImage?: number;\n}\n\n// flux-pro-1.1-ultra-finetuned per-image USD. BFL bills per generated image; verify\n// against bfl.ai/pricing before relying on this (override via config.pricePerImage).\nconst BFL_IMAGE_PRICE = 0.06;\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nfunction gcd(a: number, b: number): number {\n return b === 0 ? a : gcd(b, a % b);\n}\n\n/** Remaining BFL account credits + their USD value (1 credit = $0.01). */\nexport interface BflCredits {\n credits: number;\n usd: number;\n}\n\n/** F023.6 — check the BFL account's remaining credit balance (`GET /v1/credits`).\n * Account-level (region-independent); EU-pinned by default for consistency. Use it\n * for budget-gating before a generate call: `if ((await bflCredits()).usd < 1) …`. */\nexport async function bflCredits(\n opts: { apiKey?: string; baseUrl?: string; fetch?: typeof fetch } = {},\n): Promise<BflCredits> {\n const apiKey = opts.apiKey ?? process.env.BFL_API_KEY;\n if (!apiKey) throw new Error(\"bflCredits: BFL_API_KEY not set\");\n const doFetch = opts.fetch ?? fetch;\n const res = await doFetch(`${opts.baseUrl ?? EU_BASE}/v1/credits`, { headers: { \"x-key\": apiKey } });\n if (!res.ok) {\n throw new Error(`bflCredits ${res.status}: ${(await res.text().catch(() => \"\")).slice(0, 200)}`);\n }\n const data = (await res.json()) as { credits?: number };\n const credits = typeof data.credits === \"number\" ? data.credits : 0;\n return { credits, usd: credits * BFL_CREDIT_USD };\n}\n\nexport function bflAdapter(config: BflAdapterConfig = {}): ProviderAdapter {\n const doFetch = config.fetch ?? fetch;\n const base = config.baseUrl ?? EU_BASE;\n const pollIntervalMs = config.pollIntervalMs ?? 1500;\n const timeoutMs = config.timeoutMs ?? 120000;\n\n const resolveKey = () => config.apiKey ?? process.env.BFL_API_KEY;\n\n async function image(req: ImageRequest): Promise<ImageResult> {\n const apiKey = resolveKey();\n if (!apiKey) throw new Error(\"bfl adapter: BFL_API_KEY not set\");\n const headers = { \"content-type\": \"application/json\", \"x-key\": apiKey };\n\n const body: Record<string, unknown> = { prompt: req.prompt };\n if (req.referenceImages?.length) {\n // F023.5 — FLUX 2 multi-reference: input_image, input_image_2 … input_image_8.\n req.referenceImages.forEach((img, i) => {\n body[i === 0 ? \"input_image\" : `input_image_${i + 1}`] = toBflImage(img);\n });\n if (req.width) body.width = req.width;\n if (req.height) body.height = req.height;\n if (req.seed !== undefined) body.seed = req.seed;\n body.output_format = req.outputFormat ?? \"jpeg\";\n body.safety_tolerance = req.safetyTolerance ?? 2;\n } else if (req.finetune) {\n // F023 — finetuned subject (trained once in the BFL dashboard).\n body.finetune_id = req.finetune;\n if (req.finetuneStrength !== undefined) body.finetune_strength = req.finetuneStrength;\n // flux-pro-1.1-ultra takes aspect_ratio, not width/height — derive it when both given.\n if (req.width && req.height) {\n const g = gcd(req.width, req.height) || 1;\n body.aspect_ratio = `${req.width / g}:${req.height / g}`;\n }\n } else {\n throw new Error(\n \"bfl adapter: requires referenceImages (FLUX 2 multi-reference) or a finetune id. \" +\n \"ai.image({ referenceImages: [...] }) needs no training; ai.image({ finetune }) uses a subject \" +\n \"trained once in the BFL dashboard (dashboard.bfl.ai — finetune-create is not in the public API).\",\n );\n }\n\n const submitRes = await doFetch(`${base}/v1/${req.spec.model}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n if (!submitRes.ok) {\n throw new Error(`bfl ${submitRes.status}: ${(await submitRes.text().catch(() => \"\")).slice(0, 200)}`);\n }\n const submit = (await submitRes.json()) as BflSubmitResponse;\n if (!submit.id) throw new Error(\"bfl: no task id in submit response\");\n\n const sample = await poll(submit.id, apiKey);\n\n const usage = freshUsage({\n provider: \"bfl\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"image\",\n inputTokens: 0,\n outputTokens: 0,\n });\n // BFL returns the real billed cost (credits) — use it; fall back to the estimate.\n usage.costUsd =\n typeof submit.cost === \"number\"\n ? submit.cost * BFL_CREDIT_USD\n : (config.pricePerImage ?? BFL_IMAGE_PRICE);\n return { url: sample, usage };\n }\n\n /** A URL passes through; raw bytes / a data: URI become a plain base64 string\n * (BFL's input_image wants base64, not a data: URI — verified live). */\n function toBflImage(img: string | Uint8Array): string {\n if (typeof img !== \"string\") return Buffer.from(img).toString(\"base64\");\n if (/^https?:\\/\\//i.test(img)) return img;\n const comma = img.startsWith(\"data:\") ? img.indexOf(\",\") : -1;\n return comma >= 0 ? img.slice(comma + 1) : img;\n }\n\n /** Poll the EU get_result by id until Ready (or a terminal/moderated status). */\n async function poll(id: string, apiKey: string): Promise<string> {\n const headers = { \"x-key\": apiKey };\n const deadline = Date.now() + timeoutMs;\n for (;;) {\n const res = await doFetch(`${base}/v1/get_result?id=${encodeURIComponent(id)}`, { headers });\n if (!res.ok) throw new Error(`bfl get_result ${res.status}`);\n const data = (await res.json()) as BflResultResponse;\n const status = data.status ?? \"\";\n if (status === \"Ready\") {\n const sample = data.result?.sample;\n if (!sample) throw new Error(\"bfl: status Ready but no result.sample url\");\n return sample;\n }\n if (status === \"Error\" || status === \"Failed\" || status === \"Task not found\") {\n throw new Error(`bfl: generation ${status}`);\n }\n if (status.includes(\"Moderated\")) {\n throw new Error(`bfl: ${status} — prompt or output flagged by BFL safety`);\n }\n if (Date.now() >= deadline) throw new Error(`bfl: timed out after ${timeoutMs}ms`);\n await sleep(pollIntervalMs);\n }\n }\n\n return { name: \"bfl\", image };\n}\n","// Default provider registry — the live adapters wired when AiConfig.providers is\n// absent. A bare createAI() makes real calls (keys from env). fal stays a stub\n// until F5.3 ships the real fal.ai image adapter.\nimport { anthropicAdapter } from \"./anthropic.js\";\nimport { openaiAdapter } from \"./openai.js\";\nimport { geminiAdapter } from \"./gemini.js\";\nimport { deepinfraAdapter } from \"./deepinfra.js\";\nimport { openrouterAdapter } from \"./openrouter.js\";\nimport { requestyAdapter } from \"./requesty.js\";\nimport { deepseekAdapter } from \"./deepseek.js\";\nimport { mistralAdapter } from \"./mistral.js\";\nimport { elevenlabsAdapter } from \"./elevenlabs.js\";\nimport { azureAdapter } from \"./azure.js\";\nimport { falAdapter } from \"./fal.js\";\nimport { bflAdapter } from \"./bfl.js\";\nimport type { ProviderAdapter } from \"../types.js\";\n\nexport const defaultProviders: Record<string, ProviderAdapter> = {\n anthropic: anthropicAdapter(),\n openai: openaiAdapter(),\n gemini: geminiAdapter(),\n deepinfra: deepinfraAdapter(),\n openrouter: openrouterAdapter(),\n requesty: requestyAdapter(),\n deepseek: deepseekAdapter(),\n mistral: mistralAdapter(),\n elevenlabs: elevenlabsAdapter(),\n azure: azureAdapter(),\n fal: falAdapter(),\n bfl: bflAdapter(),\n};\n","// Pre-flight budget guard. check() runs BEFORE the transport fires, so a call\n// that would breach a ceiling never reaches the provider. record() folds the\n// actual cost into the running total after a successful call.\nimport type { BudgetConfig, BudgetStore } from \"../types.js\";\n\n/** Default rolling-total store: in-memory, per BudgetGuard instance. */\nclass InMemoryBudgetStore implements BudgetStore {\n private spentUsd = 0;\n getSpent(): number {\n return this.spentUsd;\n }\n addSpent(usd: number): void {\n this.spentUsd += usd;\n }\n}\n\nexport class BudgetExceededError extends Error {\n readonly kind: \"per-call\" | \"rolling\";\n readonly limit: number;\n readonly spent: number;\n readonly requested: number;\n\n constructor(\n kind: \"per-call\" | \"rolling\",\n limit: number,\n spent: number,\n requested: number,\n ) {\n super(\n `Budget exceeded (${kind}): this call's estimated $${requested.toFixed(6)} ` +\n (kind === \"rolling\"\n ? `+ $${spent.toFixed(6)} already spent exceeds the $${limit.toFixed(6)} rolling ceiling`\n : `exceeds the $${limit.toFixed(6)} per-call ceiling`),\n );\n this.name = \"BudgetExceededError\";\n this.kind = kind;\n this.limit = limit;\n this.spent = spent;\n this.requested = requested;\n }\n}\n\nexport class BudgetGuard {\n private readonly store: BudgetStore;\n\n constructor(private readonly config: BudgetConfig) {\n this.store = config.store ?? new InMemoryBudgetStore();\n }\n\n /** Throws BudgetExceededError if `requested` would breach the per-call ceiling\n * or push the rolling total past its ceiling. Call before firing the request.\n * Async because a persistent store may be I/O-backed. */\n async check(requested: number): Promise<void> {\n const { perCallUsd, rollingUsd } = this.config;\n if (perCallUsd !== undefined && requested > perCallUsd) {\n throw new BudgetExceededError(\"per-call\", perCallUsd, await this.store.getSpent(), requested);\n }\n if (rollingUsd !== undefined) {\n const spent = await this.store.getSpent();\n if (spent + requested > rollingUsd) {\n throw new BudgetExceededError(\"rolling\", rollingUsd, spent, requested);\n }\n }\n }\n\n /** Add an actual cost to the running total (after a successful call). */\n async record(actual: number): Promise<void> {\n await this.store.addSpent(actual);\n }\n\n async totalSpent(): Promise<number> {\n return this.store.getSpent();\n }\n}\n","// Vision capability helper. The client owns orchestration (tier/budget/sink);\n// this module owns the vision-specific message shaping so it's unit-testable and\n// the capabilities/ layout stays meaningful. Default tier: \"vision\".\nimport type { VisionInput } from \"../schema/inputs.js\";\nimport type { Message, Tier } from \"../types.js\";\n\nexport const VISION_DEFAULT_TIER: Tier = \"vision\";\n\n/** Build the multimodal message(s) (optional system + user text + image) for a\n * vision call. A `system` instruction drives instruction-following far better\n * than packing rules into `prompt` for instruction-heavy tasks (e.g. a JSON critic). */\nexport function buildVisionMessages(input: VisionInput): Message[] {\n const messages: Message[] = [];\n if (input.system) messages.push({ role: \"system\", content: input.system });\n messages.push({\n role: \"user\",\n content: [\n { type: \"text\", text: input.prompt },\n { type: \"image\", image: input.image, mimeType: input.mimeType },\n ],\n });\n return messages;\n}\n","// Video Vision capability (F019). Like vision, but the multimodal part is a\n// video the model watches natively (Gemini, OpenRouter video models). The client\n// owns orchestration; this module owns the message shaping. Default tier: \"video\".\nimport type { VideoInput } from \"../schema/inputs.js\";\nimport type { Message, Tier } from \"../types.js\";\n\nexport const VIDEO_DEFAULT_TIER: Tier = \"video\";\n\n/** Build the message(s) (optional system + video + prompt) for a video-analysis call. */\nexport function buildVideoMessages(input: VideoInput): Message[] {\n const messages: Message[] = [];\n if (input.system) messages.push({ role: \"system\", content: input.system });\n messages.push({\n role: \"user\",\n content: [\n { type: \"video\", video: input.video, mimeType: input.mimeType },\n { type: \"text\", text: input.prompt },\n ],\n });\n return messages;\n}\n","// Translate capability helper. A thin prompt-contract on top of chat — the\n// client orchestrates (tier/budget/sink); this builds the messages. Default\n// tier: \"fast\". Returns the translation only, no preamble.\nimport type { TranslateInput } from \"../schema/inputs.js\";\nimport type { Message, Tier } from \"../types.js\";\n\nexport const TRANSLATE_DEFAULT_TIER: Tier = \"fast\";\n\nconst TRANSLATE_SYSTEM =\n \"You are a translation engine. Translate the user's text only. \" +\n \"Return the translation and nothing else — no preamble, no quotes.\";\n\nexport function buildTranslateMessages(input: TranslateInput): Message[] {\n const fromClause = input.from ? ` from ${input.from}` : \"\";\n return [\n { role: \"system\", content: TRANSLATE_SYSTEM },\n { role: \"user\", content: `Translate${fromClause} to ${input.to}:\\n\\n${input.text}` },\n ];\n}\n","// Embedding capability marker. The client orchestrates; this names the default\n// tier (OpenAI text-embedding-3-small via the embedding tier).\nimport type { Tier } from \"../types.js\";\n\nexport const EMBEDDING_DEFAULT_TIER: Tier = \"embedding\";\n","// Transcribe capability. No tier in the tier map (provider-specific, like image)\n// — defaults to OpenAI Whisper, overridable per call. Synergy: cctalk Danish\n// dictation. costUsd is 0 for v1 (Whisper is priced per minute, not per token).\nimport type { TierSpec } from \"../types.js\";\n\nexport const DEFAULT_TRANSCRIBE_SPEC: TierSpec = {\n provider: \"openai\",\n model: \"whisper-1\",\n transport: \"http\",\n};\n\n/** Fetch a URL to raw bytes; pass through bytes unchanged. */\nexport async function resolveAudio(\n audio: string | Uint8Array,\n fetchImpl: typeof fetch = fetch,\n): Promise<Uint8Array> {\n if (typeof audio !== \"string\") return audio;\n if (!/^https?:\\/\\//.test(audio)) {\n throw new Error(\"transcribe: string audio must be an http(s) URL (or pass raw bytes)\");\n }\n const res = await fetchImpl(audio);\n if (!res.ok) throw new Error(`transcribe: failed to fetch audio (${res.status})`);\n return new Uint8Array(await res.arrayBuffer());\n}\n","// Prompt-contract capabilities (F5.5). Each is a fixed system prompt over\n// chat/vision; extract adds Zod output validation with one retry. Exposed as\n// ai.contracts.* — built from the client so budget/cost tracking apply.\nimport type { AiClient, VisionInput } from \"../../schema/inputs.js\";\nimport type {\n Contracts,\n MockupInput,\n MockupResult,\n DesignInput,\n DesignResult,\n ExtractInput,\n ExtractResult,\n ClassifyInput,\n ClassifyResult,\n RerankInput,\n RerankResult,\n} from \"./types.js\";\n\n/** Pull the first JSON value out of a model reply (tolerates ```json fences + prose). */\nexport function parseJsonLoose(text: string): unknown {\n const fenced = text.replace(/```(?:json)?/gi, \"\").trim();\n const start = fenced.search(/[[{]/);\n if (start === -1) throw new Error(\"no JSON found in model output\");\n const slice = fenced.slice(start);\n // Walk back from the end to the matching closing bracket.\n const lastObj = slice.lastIndexOf(\"}\");\n const lastArr = slice.lastIndexOf(\"]\");\n const end = Math.max(lastObj, lastArr);\n return JSON.parse(slice.slice(0, end + 1));\n}\n\ntype ChatVision = Pick<AiClient, \"chat\" | \"vision\">;\n\nexport function makeContracts(client: ChatVision): Contracts {\n return {\n async mockup(input: MockupInput): Promise<MockupResult> {\n const constraints = input.constraints ? `\\n\\nConstraints:\\n${input.constraints}` : \"\";\n const res = await client.chat({\n system:\n \"You are a UI mockup generator. Output a single self-contained HTML document \" +\n \"using Tailwind CSS utility classes. Return ONLY the HTML — no markdown, no prose.\",\n prompt: `Build a UI mockup for:\\n${input.description}${constraints}`,\n tier: input.tier ?? \"smart\",\n purpose: input.purpose ?? \"contract:mockup\",\n });\n return { html: res.text, usage: res.usage };\n },\n\n async design(input: DesignInput): Promise<DesignResult> {\n const res = await client.vision({\n image: input.screenshot as VisionInput[\"image\"],\n prompt:\n \"You are a design-iteration engine. Given this screenshot, apply the instructions \" +\n `and return a single self-contained HTML document (Tailwind), ONLY the HTML.\\n\\n` +\n `Instructions:\\n${input.instructions}`,\n tier: input.tier ?? \"powerful\",\n purpose: input.purpose ?? \"contract:design\",\n });\n return { html: res.text, usage: res.usage };\n },\n\n async extract<T>(input: ExtractInput<T>): Promise<ExtractResult<T>> {\n const base =\n \"You are a structured-data extractor. Extract the requested data from the text and \" +\n \"return ONLY valid JSON — no markdown, no prose.\" +\n (input.instructions ? `\\n\\n${input.instructions}` : \"\");\n const run = async (reinforce: boolean) => {\n const res = await client.chat({\n system: reinforce ? `${base}\\n\\nYour previous output was not valid JSON. Return ONLY parseable JSON.` : base,\n prompt: input.text,\n tier: input.tier ?? \"smart\",\n purpose: input.purpose ?? \"contract:extract\",\n });\n return res;\n };\n let res = await run(false);\n try {\n return { data: input.schema.parse(parseJsonLoose(res.text)), usage: res.usage };\n } catch {\n // one retry with reinforcement\n res = await run(true);\n return { data: input.schema.parse(parseJsonLoose(res.text)), usage: res.usage };\n }\n },\n\n async classify(input: ClassifyInput): Promise<ClassifyResult> {\n const res = await client.chat({\n system:\n \"You are a zero-shot classifier. Choose exactly one label from the provided list. \" +\n 'Return ONLY JSON: {\"label\": \"<one of the labels>\", \"confidence\": <0..1>}.',\n prompt: `Labels: ${JSON.stringify(input.labels)}\\n\\nText:\\n${input.text}`,\n tier: input.tier ?? \"cheap\",\n purpose: input.purpose ?? \"contract:classify\",\n });\n const parsed = parseJsonLoose(res.text) as { label?: string; confidence?: number };\n const label = input.labels.includes(parsed.label ?? \"\") ? parsed.label! : (input.labels[0] ?? \"\");\n const confidence = typeof parsed.confidence === \"number\" ? parsed.confidence : 0;\n return { label, confidence, usage: res.usage };\n },\n\n async rerank(input: RerankInput): Promise<RerankResult> {\n const res = await client.chat({\n system:\n \"You are a relevance reranker. Score each item 0..1 for relevance to the query and \" +\n 'return ONLY JSON: [{\"item\": \"<verbatim item>\", \"score\": <0..1>}], ordered by score desc.',\n prompt: `Query: ${input.query}\\n\\nItems:\\n${JSON.stringify(input.items)}`,\n tier: input.tier ?? \"fast\",\n purpose: input.purpose ?? \"contract:rerank\",\n });\n const raw = parseJsonLoose(res.text) as { item?: string; score?: number }[];\n const ranked = (Array.isArray(raw) ? raw : [])\n .map((r) => ({ item: String(r.item ?? \"\"), score: typeof r.score === \"number\" ? r.score : 0 }))\n .sort((a, b) => b.score - a.score);\n return { ranked, usage: res.usage };\n },\n };\n}\n","// Zod is the single source of truth for the public input shapes. The TypeScript\n// types are derived via z.infer — no hand-written interface duplicates them.\n// The client .parse()s every input at the boundary, so invalid input throws a\n// ZodError before any provider work happens.\nimport { z } from \"zod\";\nimport type {\n ProviderAdapter,\n CostSink,\n TranslateResult,\n ChatResult,\n ChatStreamEvent,\n ImageResult,\n AnimateResult,\n TrainStyleResult,\n EmbeddingResult,\n TranscribeResult,\n OcrResult,\n ModerationResult,\n PodcastResult,\n BatchRequestItem,\n BatchJob,\n BatchResultItem,\n TierSpec,\n} from \"../types.js\";\nimport type { Contracts } from \"../capabilities/contracts/types.js\";\n\n// ── Reusable sub-schemas ───────────────────────────────────────────────────\n\nexport const transportSchema = z.enum([\"http\", \"subprocess\"]);\n\nexport const tierSchema = z.enum([\n \"fast\",\n \"smart\",\n \"powerful\",\n \"cheap\",\n \"vision\",\n \"video\",\n \"embedding\",\n]);\n\nexport const tierSpecSchema = z.object({\n provider: z.string(),\n model: z.string(),\n transport: transportSchema,\n});\n\nexport const toolSchema = z.object({\n name: z.string(),\n description: z.string(),\n parameters: z.record(z.unknown()),\n});\n\nexport const toolCallSchema = z.object({\n id: z.string(),\n name: z.string(),\n arguments: z.record(z.unknown()),\n});\n\nexport const contentPartSchema = z.union([\n z.object({ type: z.literal(\"text\"), text: z.string() }),\n z.object({\n type: z.literal(\"image\"),\n image: z.union([z.string(), z.instanceof(Uint8Array)]),\n mimeType: z.string().optional(),\n }),\n]);\n\nexport const messageSchema = z.object({\n role: z.enum([\"system\", \"user\", \"assistant\", \"tool\"]),\n content: z.union([z.string(), z.array(contentPartSchema)]),\n toolCalls: z.array(toolCallSchema).optional(),\n toolCallId: z.string().optional(),\n});\n\n/** Per-call options shared by every capability input. */\nconst callOptions = {\n tier: tierSchema.optional(),\n override: tierSpecSchema.partial().optional(),\n fallback: z.array(z.union([tierSchema, tierSpecSchema])).optional(),\n purpose: z.string().optional(),\n /** Consumer-defined attribution dimensions (e.g. {tenantId}) ridden into the\n * cost sink for per-tenant/per-customer cost breakdown (F011). */\n labels: z.record(z.string(), z.string()).optional(),\n} as const;\n\n// ── The 5 capability inputs ────────────────────────────────────────────────\n\nexport const chatInputSchema = z.object({\n prompt: z.string().optional(),\n messages: z.array(messageSchema).optional(),\n system: z.string().optional(),\n tools: z.array(toolSchema).optional(),\n maxTokens: z.number().int().positive().optional(),\n temperature: z.number().min(0).max(2).optional(),\n /** \"json\" requests JSON-object output (OpenAI-compatible response_format). */\n responseFormat: z.enum([\"json\", \"text\"]).optional(),\n ...callOptions,\n});\n\nexport const visionInputSchema = z.object({\n image: z.union([z.string(), z.instanceof(Uint8Array)]),\n prompt: z.string(),\n mimeType: z.string().optional(),\n /** System instruction — drives instruction-following far better than stuffing\n * rules into `prompt` for instruction-heavy vision tasks (e.g. a JSON critic). */\n system: z.string().optional(),\n ...callOptions,\n});\n\n// F019 — analyze a video natively (e.g. \"what's in the first 30s?\"). Same shape\n// as vision but with a video payload (URL, data-URL, or raw bytes).\nexport const videoInputSchema = z.object({\n video: z.union([z.string(), z.instanceof(Uint8Array)]),\n prompt: z.string(),\n mimeType: z.string().optional(),\n /** System instruction — same instruction-following benefit as on vision. */\n system: z.string().optional(),\n ...callOptions,\n});\n\nexport const translateInputSchema = z.object({\n text: z.string(),\n to: z.string(),\n from: z.string().optional(),\n ...callOptions,\n});\n\nexport const loraWeightSchema = z.object({\n path: z.string(),\n scale: z.number().optional(),\n});\n\nexport const imageInputSchema = z.object({\n prompt: z.string(),\n width: z.number().int().positive().optional(),\n height: z.number().int().positive().optional(),\n /** LoRAs to merge at inference (F021). */\n loras: z.array(loraWeightSchema).optional(),\n /** Shorthand for a single LoRA — normalized to loras:[{path, scale:1}]. */\n lora: z.string().optional(),\n /** F023 — a BFL finetune id (subject trained in the BFL dashboard). Routes to the\n * EU-resident BFL finetuned-portrait endpoint. */\n finetune: z.string().optional(),\n /** F023 — BFL finetune_strength (~0–2; higher = stronger likeness). */\n finetuneStrength: z.number().min(0).max(2).optional(),\n /** F023.5 — 1–8 reference photos (URL or raw bytes) → EU-resident BFL FLUX 2\n * multi-reference generation (likeness, no training step). */\n referenceImages: z.array(z.union([z.string(), z.instanceof(Uint8Array)])).min(1).max(8).optional(),\n /** F023.5 — fixed seed for reproducible output (BFL). */\n seed: z.number().int().optional(),\n /** F023.5 — output container (BFL FLUX 2). Default jpeg. */\n outputFormat: z.enum([\"jpeg\", \"png\", \"webp\"]).optional(),\n /** F023.5 — BFL content-moderation strictness, 0 (strict) … 6 (lax). Default 2. */\n safetyTolerance: z.number().int().min(0).max(6).optional(),\n /** F021.4 — re-roll once if fal returns a black image (NSFW false-positive). */\n retryOnBlack: z.boolean().optional(),\n ...callOptions,\n});\n\n// Image-to-video (F024) — animate a still into a short clip via a pluggable provider.\nexport const animateInputSchema = z.object({\n /** Input image: a URL or raw bytes (uploaded to fal storage). */\n image: z.union([z.string(), z.instanceof(Uint8Array)]),\n /** Motion/scene prompt. */\n prompt: z.string().optional(),\n /** Clip length in seconds (provider-dependent; Veo ≤ 8s). */\n durationSec: z.number().positive().optional(),\n /** e.g. \"720p\" / \"1080p\" (provider-dependent). */\n resolution: z.string().optional(),\n ...callOptions,\n});\n\nexport const trainStyleInputSchema = z.object({\n /** A hosted archive URL, or an array of image URLs the SDK zips in-memory. */\n images: z.union([z.string(), z.array(z.string())]),\n /** Style LoRA (disables captioning/masks). Default true. */\n isStyle: z.boolean().optional(),\n triggerWord: z.string().optional(),\n steps: z.number().int().positive().optional(),\n createMasks: z.boolean().optional(),\n ...callOptions,\n});\n\nexport const embeddingInputSchema = z.object({\n text: z.union([z.string(), z.array(z.string())]),\n ...callOptions,\n});\n\nexport const transcribeInputSchema = z.object({\n /** Audio URL or raw bytes. */\n audio: z.union([z.string(), z.instanceof(Uint8Array)]),\n language: z.string().optional(),\n /** Audio length in seconds — enables Whisper per-minute cost. */\n durationSec: z.number().positive().optional(),\n /** Bias toward brand/jargon terms (Azure phraseList, F029.3); others ignore it. */\n phrases: z.array(z.string()).optional(),\n ...callOptions,\n});\n\n// OCR (F016.2) — document/image → structured markdown text, billed per page.\nexport const ocrInputSchema = z.object({\n /** A URL, data-URL, or raw bytes of the document/image. */\n document: z.union([z.string(), z.instanceof(Uint8Array)]),\n /** image/* → routed as an image; anything else → a document (PDF etc.). */\n mimeType: z.string().optional(),\n ...callOptions,\n});\n\n// Moderation (F016.4) — classify text against safety categories, billed per token.\nexport const moderationInputSchema = z.object({\n input: z.union([z.string(), z.array(z.string())]),\n ...callOptions,\n});\n\n// Podcast (F020) — a finished manuscript (speaker turns) + a speaker→voiceId map →\n// one finished multi-voice audio episode (ElevenLabs Text-to-Dialogue).\nexport const podcastInputSchema = z.object({\n script: z.array(z.object({ speaker: z.string(), text: z.string() })).min(1),\n voices: z.record(z.string(), z.string()),\n format: z.string().optional(),\n ...callOptions,\n});\n\n// Single-voice TTS (F020.4) — text → audio. `voice` is a curated name or a voiceId.\n// `lang`/`format` (F026) are used by the Azure adapter; ElevenLabs ignores them.\nexport const ttsInputSchema = z.object({\n text: z.string(),\n voice: z.string(),\n lang: z.string().optional(),\n format: z.string().optional(),\n rate: z.number().positive().optional(),\n ...callOptions,\n});\n\n// ── Client config ──────────────────────────────────────────────────────────\n\nexport const budgetSchema = z.object({\n perCallUsd: z.number().positive().optional(),\n rollingUsd: z.number().positive().optional(),\n});\n\n/** F022 — opt-in proactive availability gate. Off by default so existing call\n * sites are byte-identical. When autoResolve is on, a suspended primary model\n * is transparently swapped to `fallback` before dispatch (synchronous, no I/O). */\nexport const availabilitySchema = z.object({\n autoResolve: z.boolean().optional(),\n fallback: z.union([z.string(), z.array(z.string())]).optional(),\n});\n\nexport const aiConfigSchema = z.object({\n defaults: z.record(tierSchema, tierSpecSchema).optional(),\n // Functions can't be deeply validated — z.custom asserts the TS type and\n // passes the value through untouched.\n providers: z.record(z.string(), z.custom<ProviderAdapter>()).optional(),\n costSink: z.custom<CostSink>().optional(),\n budget: budgetSchema.optional(),\n availability: availabilitySchema.optional(),\n});\n\n// ── Derived types (z.infer is the single source) ───────────────────────────\n\nexport type ChatInput = z.infer<typeof chatInputSchema>;\nexport type VisionInput = z.infer<typeof visionInputSchema>;\nexport type VideoInput = z.infer<typeof videoInputSchema>;\nexport type TranslateInput = z.infer<typeof translateInputSchema>;\nexport type ImageInput = z.infer<typeof imageInputSchema>;\nexport type AnimateInput = z.infer<typeof animateInputSchema>;\nexport type TrainStyleInput = z.infer<typeof trainStyleInputSchema>;\nexport type EmbeddingInput = z.infer<typeof embeddingInputSchema>;\nexport type TranscribeInput = z.infer<typeof transcribeInputSchema>;\nexport type OcrInput = z.infer<typeof ocrInputSchema>;\nexport type ModerationInput = z.infer<typeof moderationInputSchema>;\nexport type PodcastInput = z.infer<typeof podcastInputSchema>;\nexport type TtsInput = z.infer<typeof ttsInputSchema>;\nexport type AiConfig = z.infer<typeof aiConfigSchema>;\n\n/** The public facade. Defined here because it depends on the derived inputs. */\nexport interface AiClient {\n chat(input: ChatInput): Promise<ChatResult>;\n /** Streaming chat (F8) — same input as chat; yields ChatStreamEvents. The\n * caller owns the tool-loop (per-turn engine, not an agent runtime). */\n chatStream(input: ChatInput): AsyncIterable<ChatStreamEvent>;\n vision(input: VisionInput): Promise<ChatResult>;\n /** Video Vision (F019) — analyze a video natively. Default tier: \"video\". */\n video(input: VideoInput): Promise<ChatResult>;\n translate(input: TranslateInput): Promise<TranslateResult>;\n image(input: ImageInput): Promise<ImageResult>;\n /** Image-to-video (F024) — animate a still into a short clip → { url, usage }. fal. */\n animate(input: AnimateInput): Promise<AnimateResult>;\n /** Train a style/brand LoRA from images (F021) → { loraUrl, configUrl }. fal. */\n trainStyle(input: TrainStyleInput): Promise<TrainStyleResult>;\n embedding(input: EmbeddingInput): Promise<EmbeddingResult>;\n transcribe(input: TranscribeInput): Promise<TranscribeResult>;\n /** OCR (F016.2) — document/image → structured markdown, billed per page. Mistral. */\n ocr(input: OcrInput): Promise<OcrResult>;\n /** Moderation (F016.4) — classify text against safety categories. Mistral. */\n moderate(input: ModerationInput): Promise<ModerationResult>;\n /** Podcast (F020) — a finished manuscript → one multi-voice audio episode. ElevenLabs. */\n podcast(input: PodcastInput): Promise<PodcastResult>;\n /** Single-voice TTS (F020.4) — text → audio. `voice` = curated name or voiceId. ElevenLabs. */\n tts(input: TtsInput): Promise<PodcastResult>;\n /** Batch (F016.1) — submit many chat requests for async (≤24h) processing at 50% cost. Mistral. */\n batch: {\n submit(input: { requests: BatchRequestItem[]; override?: TierSpec }): Promise<BatchJob>;\n status(jobId: string, override?: TierSpec): Promise<BatchJob>;\n results(jobId: string, override?: TierSpec): Promise<BatchResultItem[]>;\n };\n /** Prompt-contract capabilities (F5.5) layered on chat/vision. */\n contracts: Contracts;\n}\n","// createAI() — the facade factory. Resolves routing, picks a provider adapter,\n// delegates the call, stamps call-context metadata onto Usage, and reports to the\n// cost sink. Provider specifics live in adapters; cost compute/budget land in F3.\nimport { resolveTier } from \"./routing/tier-map.js\";\nimport { resolveModel } from \"./availability/resolve.js\";\nimport { defaultProviders } from \"./providers/registry.js\";\nimport { computeCost } from \"./cost/usage.js\";\nimport { BudgetGuard } from \"./cost/budget.js\";\nimport { buildVisionMessages, VISION_DEFAULT_TIER } from \"./capabilities/vision.js\";\nimport { buildVideoMessages, VIDEO_DEFAULT_TIER } from \"./capabilities/video.js\";\nimport { buildTranslateMessages, TRANSLATE_DEFAULT_TIER } from \"./capabilities/translate.js\";\nimport { EMBEDDING_DEFAULT_TIER } from \"./capabilities/embedding.js\";\nimport { DEFAULT_TRANSCRIBE_SPEC, resolveAudio } from \"./capabilities/transcribe.js\";\nimport { makeContracts } from \"./capabilities/contracts/index.js\";\nimport { resolveVoice } from \"./providers/elevenlabs.js\";\nimport {\n aiConfigSchema,\n chatInputSchema,\n visionInputSchema,\n videoInputSchema,\n translateInputSchema,\n imageInputSchema,\n animateInputSchema,\n trainStyleInputSchema,\n embeddingInputSchema,\n transcribeInputSchema,\n ocrInputSchema,\n moderationInputSchema,\n podcastInputSchema,\n ttsInputSchema,\n} from \"./schema/inputs.js\";\nimport type {\n AiConfig,\n AiClient,\n ChatInput,\n VisionInput,\n VideoInput,\n TranslateInput,\n ImageInput,\n AnimateInput,\n TrainStyleInput,\n EmbeddingInput,\n TranscribeInput,\n OcrInput,\n ModerationInput,\n PodcastInput,\n TtsInput,\n} from \"./schema/inputs.js\";\nimport type {\n ChatResult,\n ChatStreamEvent,\n ImageResult,\n AnimateResult,\n TrainStyleResult,\n EmbeddingResult,\n TranscribeResult,\n OcrResult,\n ModerationResult,\n PodcastResult,\n BatchRequestItem,\n BatchJob,\n BatchResultItem,\n TranslateResult,\n ProviderAdapter,\n Message,\n Capability,\n Tier,\n TierSpec,\n Usage,\n} from \"./types.js\";\n\n/** Built-in image route (no image tier in the tier map — fal owns its routing). */\nconst DEFAULT_IMAGE_SPEC: TierSpec = {\n provider: \"fal\",\n model: \"fal-ai/flux/schnell\",\n transport: \"http\",\n};\n/** LoRA-inference route (F021) — used by ai.image when loras are supplied. */\nconst DEFAULT_LORA_IMAGE_SPEC: TierSpec = {\n provider: \"fal\",\n model: \"fal-ai/flux-lora\",\n transport: \"http\",\n};\n/** Style-LoRA training route (F021) — fal flux-lora-fast-training. */\nconst DEFAULT_TRAINSTYLE_SPEC: TierSpec = {\n provider: \"fal\",\n model: \"fal-ai/flux-lora-fast-training\",\n transport: \"http\",\n};\n/** Image-to-video route (F024) — Veo 3.1 DIRECT via the Gemini API (no fal markup,\n * our existing GEMINI_API_KEY, and the path to EU via Vertex later). Override to\n * {provider:\"fal\", model:\"fal-ai/veo3.1/...\"} for the aggregator / other models\n * (Kling, Seedance). US-hosted: consent-gated use (F024). */\nconst DEFAULT_ANIMATE_SPEC: TierSpec = {\n provider: \"gemini\",\n model: \"veo-3.1-generate-preview\",\n transport: \"http\",\n};\n/** Default audio directive appended to every ai.animate prompt (F024, Christian's\n * preference): no generated speech (it's the weak link, esp. non-English), but\n * ambient sounds matched to the scene are wanted. A soft prompt instruction. */\nconst ANIMATE_AUDIO_DIRECTIVE =\n \"No spoken dialogue, no talking, no voiceover. Include natural ambient background sounds that match the environment.\";\n/** EU-resident finetuned-portrait route (F023) — BFL, used by ai.image when a\n * `finetune` id is supplied. Hard-pinned to api.eu.bfl.ai inside the adapter. */\nconst DEFAULT_BFL_FINETUNE_SPEC: TierSpec = {\n provider: \"bfl\",\n model: \"flux-pro-1.1-ultra-finetuned\",\n transport: \"http\",\n};\n/** EU-resident multi-reference route (F023.5) — BFL FLUX 2, used by ai.image when\n * `referenceImages` are supplied (likeness with no training step). flux-2-max =\n * premium-quality default; override to flux-2-pro/flex for volume. EU-pinned. */\nconst DEFAULT_BFL_REFERENCE_SPEC: TierSpec = {\n provider: \"bfl\",\n model: \"flux-2-max\",\n transport: \"http\",\n};\n\n/** OCR + moderation are Mistral specialty endpoints (F016) — no tier, route by default. */\nconst DEFAULT_OCR_SPEC: TierSpec = { provider: \"mistral\", model: \"mistral-ocr-latest\", transport: \"http\" };\nconst DEFAULT_MODERATION_SPEC: TierSpec = { provider: \"mistral\", model: \"mistral-moderation-latest\", transport: \"http\" };\n/** Podcast route (F020) — ElevenLabs Text-to-Dialogue, eleven_v3 (multi-voice, multilingual). */\nconst DEFAULT_PODCAST_SPEC: TierSpec = { provider: \"elevenlabs\", model: \"eleven_v3\", transport: \"http\" };\n/** Single-voice TTS route (F020.4) — ElevenLabs eleven_multilingual_v2 (good Danish). */\nconst DEFAULT_TTS_SPEC: TierSpec = { provider: \"elevenlabs\", model: \"eleven_multilingual_v2\", transport: \"http\" };\n/** Batch route (F016.1) — Mistral batch jobs (50% cost), cheap default model. */\nconst DEFAULT_BATCH_SPEC: TierSpec = { provider: \"mistral\", model: \"mistral-small-latest\", transport: \"http\" };\n\nexport function createAI(config: AiConfig = {}): AiClient {\n // Validate config at the boundary (throws ZodError on bad shape).\n const cfg = aiConfigSchema.parse(config);\n const providers = cfg.providers ?? defaultProviders;\n const budget = cfg.budget ? new BudgetGuard(cfg.budget) : undefined;\n\n const estTokens = (s: string): number => Math.ceil(s.length / 4);\n\n /** Pre-flight budget check. Estimates this call's cost and throws\n * BudgetExceededError before the transport fires. No-op without a budget. */\n async function preflight(spec: TierSpec, estInTokens: number, estOutTokens: number): Promise<void> {\n if (!budget) return;\n await budget.check(computeCost(spec.provider, spec.model, estInTokens, estOutTokens));\n }\n\n /** Fold the actual cost into the rolling total after a successful call. */\n async function settle(usage: Usage): Promise<void> {\n if (budget) await budget.record(usage.costUsd);\n }\n\n function pickProvider(name: string): ProviderAdapter {\n const adapter = providers[name];\n if (!adapter) {\n throw new Error(\n `createAI: no provider adapter registered for \"${name}\". Registered: ${Object.keys(providers).join(\", \") || \"(none)\"}`,\n );\n }\n return adapter;\n }\n\n /** Stamp call-context metadata the client owns onto the adapter's Usage:\n * capability, tier, purpose, the wall-clock latency, and the timestamp. */\n function enrich(\n usage: Usage,\n capability: Capability,\n tier: Tier | undefined,\n purpose: string | undefined,\n latencyMs: number,\n labels: Record<string, string> | undefined,\n ): Usage {\n usage.capability = capability;\n if (tier) usage.tier = tier;\n if (purpose) usage.purpose = purpose;\n if (labels && Object.keys(labels).length > 0) usage.labels = labels;\n usage.latencyMs = Math.round(latencyMs);\n if (!usage.ts) usage.ts = new Date().toISOString();\n return usage;\n }\n\n async function report(usage: Usage): Promise<void> {\n if (!cfg.costSink) return;\n try {\n await cfg.costSink.record(usage);\n } catch {\n // A broken sink must never crash a real AI call (F3.3 invariant).\n }\n }\n\n function toMessages(input: ChatInput): Message[] {\n if (input.messages && input.messages.length > 0) {\n // A top-level `system` must survive when `messages` is also supplied — prepend\n // it (unless the caller already leads with a system message) instead of\n // silently dropping it. Regression: system + messages → system was lost, so a\n // \"return ONLY JSON\" system instruction never reached the model (cms #4234).\n if (input.system && input.messages[0]?.role !== \"system\") {\n return [{ role: \"system\", content: input.system }, ...input.messages];\n }\n return input.messages;\n }\n const msgs: Message[] = [];\n if (input.system) msgs.push({ role: \"system\", content: input.system });\n msgs.push({ role: \"user\", content: input.prompt ?? \"\" });\n return msgs;\n }\n\n /** F022 — opt-in proactive availability gate. When cfg.availability.autoResolve\n * is set, swap a known-suspended primary model to its configured fallback\n * BEFORE dispatch (synchronous, registry-only — no I/O). Default off → the\n * spec is returned untouched and behaviour is byte-identical. This sits in\n * front of the reactive route-fallback below. */\n function applyAvailability(spec: TierSpec): TierSpec {\n if (!cfg.availability?.autoResolve) return spec;\n const r = resolveModel(spec.model, { fallback: cfg.availability.fallback, provider: spec.provider });\n return r.fellBack ? { ...spec, model: r.model } : spec;\n }\n\n /** Run a capability with an optional fallback chain. Tries the primary route,\n * then each fallback (Tier or TierSpec) in order if the call errors. A budget\n * breach propagates immediately (not a fallback trigger). On the first\n * success: stamp Usage, settle the budget, report to the sink, return. */\n async function runCapability<R extends { usage: Usage }>(opts: {\n primary: TierSpec;\n fallback?: (Tier | TierSpec)[];\n capability: Capability;\n tier?: Tier;\n purpose?: string;\n labels?: Record<string, string>;\n estIn: number;\n estOut: number;\n invoke: (spec: TierSpec) => Promise<R>;\n }): Promise<R> {\n const routes: TierSpec[] = [\n applyAvailability(opts.primary),\n ...(opts.fallback ?? []).map((f) =>\n typeof f === \"string\" ? resolveTier(f, undefined, cfg.defaults) : f,\n ),\n ];\n let lastErr: unknown;\n for (let i = 0; i < routes.length; i++) {\n const spec = routes[i]!;\n await preflight(spec, opts.estIn, opts.estOut); // BudgetExceededError propagates\n try {\n const t0 = performance.now();\n const res = await opts.invoke(spec);\n enrich(res.usage, opts.capability, i === 0 ? opts.tier : undefined, opts.purpose, performance.now() - t0, opts.labels);\n await settle(res.usage);\n await report(res.usage);\n return res;\n } catch (e) {\n lastErr = e; // try the next fallback route\n }\n }\n throw lastErr;\n }\n\n /** Whether a pre-first-token streaming error should fall back to the next\n * route. Eligible: network/timeout/parse (no status) + 429 + 5xx. Hard 4xx\n * bubbles up (no silent re-route) — sa contract #2565. */\n function eligibleForFallback(e: unknown): boolean {\n const status = (e as { status?: number } | null)?.status;\n if (status === undefined) return true;\n return status === 429 || status >= 500;\n }\n\n function errorEvent(e: unknown): ChatStreamEvent {\n const ev: ChatStreamEvent = {\n type: \"error\",\n message: e instanceof Error ? e.message : String(e),\n };\n const status = (e as { status?: number } | null)?.status;\n if (status !== undefined) ev.status = status;\n return ev;\n }\n\n /** Streaming chat with pre-stream fallback (F8.1). Yields ChatStreamEvents as\n * the turn unfolds. Fallback re-routes only BEFORE the first text/tool_call\n * event (deltas can't be un-emitted); once streaming has begun, an error is\n * surfaced as an error event and the stream ends. Budget breaches propagate. */\n async function* chatStreamImpl(input: ChatInput): AsyncIterable<ChatStreamEvent> {\n input = chatInputSchema.parse(input);\n const tier = input.tier ?? \"smart\";\n const messages = toMessages(input);\n const estIn = messages.reduce(\n (n, m) => n + estTokens(typeof m.content === \"string\" ? m.content : JSON.stringify(m.content)),\n 0,\n );\n const estOut = input.maxTokens ?? 512;\n const routes: TierSpec[] = [\n resolveTier(tier, input.override, cfg.defaults),\n ...(input.fallback ?? []).map((f) =>\n typeof f === \"string\" ? resolveTier(f, undefined, cfg.defaults) : f,\n ),\n ];\n\n let lastErr: unknown;\n for (let i = 0; i < routes.length; i++) {\n const spec = routes[i]!;\n await preflight(spec, estIn, estOut); // BudgetExceededError propagates\n const adapter = pickProvider(spec.provider);\n if (!adapter.chatStream) {\n throw new Error(`createAI: provider \"${spec.provider}\" does not support streaming`);\n }\n const t0 = performance.now();\n let emitted = false;\n try {\n for await (const ev of adapter.chatStream({\n messages,\n spec,\n tools: input.tools,\n maxTokens: input.maxTokens,\n temperature: input.temperature,\n responseFormat: input.responseFormat,\n })) {\n if (ev.type === \"text\" || ev.type === \"tool_call\") emitted = true;\n if (ev.type === \"usage\") {\n enrich(ev.usage, \"chat\", i === 0 ? tier : undefined, input.purpose, performance.now() - t0, input.labels);\n await settle(ev.usage);\n await report(ev.usage);\n }\n yield ev;\n }\n return; // stream completed cleanly\n } catch (e) {\n lastErr = e;\n if (emitted || !eligibleForFallback(e)) {\n yield errorEvent(e); // mid-stream or hard error → surface + stop\n return;\n }\n // pre-first-token eligible error → try the next route\n }\n }\n yield errorEvent(lastErr);\n }\n\n const client: AiClient = {\n async chat(input: ChatInput): Promise<ChatResult> {\n input = chatInputSchema.parse(input);\n const tier = input.tier ?? \"smart\";\n const messages = toMessages(input);\n const estIn = messages.reduce(\n (n, m) => n + estTokens(typeof m.content === \"string\" ? m.content : JSON.stringify(m.content)),\n 0,\n );\n return runCapability({\n primary: resolveTier(tier, input.override, cfg.defaults),\n fallback: input.fallback,\n capability: \"chat\",\n tier,\n purpose: input.purpose,\n labels: input.labels,\n estIn,\n estOut: input.maxTokens ?? 512,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.chat) throw new Error(`createAI: provider \"${spec.provider}\" does not support chat`);\n return adapter.chat({ messages, spec, tools: input.tools, maxTokens: input.maxTokens, temperature: input.temperature, responseFormat: input.responseFormat });\n },\n });\n },\n\n chatStream: chatStreamImpl,\n\n async vision(input: VisionInput): Promise<ChatResult> {\n input = visionInputSchema.parse(input);\n const tier = input.tier ?? VISION_DEFAULT_TIER;\n const messages: Message[] = buildVisionMessages(input);\n return runCapability({\n primary: resolveTier(tier, input.override, cfg.defaults),\n fallback: input.fallback,\n capability: \"vision\",\n tier,\n purpose: input.purpose,\n labels: input.labels,\n estIn: estTokens(input.prompt) + 1000, // prompt + ~1k image payload\n estOut: 512,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.vision) throw new Error(`createAI: provider \"${spec.provider}\" does not support vision`);\n return adapter.vision({ messages, spec });\n },\n });\n },\n\n async video(input: VideoInput): Promise<ChatResult> {\n input = videoInputSchema.parse(input);\n const tier = input.tier ?? VIDEO_DEFAULT_TIER;\n const messages: Message[] = buildVideoMessages(input);\n return runCapability({\n primary: resolveTier(tier, input.override, cfg.defaults),\n fallback: input.fallback,\n capability: \"video\",\n tier,\n purpose: input.purpose,\n labels: input.labels,\n estIn: estTokens(input.prompt) + 4000, // prompt + video tokens (native video ≈ frames)\n estOut: 512,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n // Video routes through the vision method — same multimodal message path.\n if (!adapter.vision) throw new Error(`createAI: provider \"${spec.provider}\" does not support video`);\n return adapter.vision({ messages, spec });\n },\n });\n },\n\n async translate(input: TranslateInput): Promise<TranslateResult> {\n input = translateInputSchema.parse(input);\n const tier = input.tier ?? TRANSLATE_DEFAULT_TIER;\n const messages: Message[] = buildTranslateMessages(input);\n const estIn = estTokens(input.text) + 40;\n const res = await runCapability<ChatResult>({\n primary: resolveTier(tier, input.override, cfg.defaults),\n fallback: input.fallback,\n capability: \"translate\",\n tier,\n purpose: input.purpose,\n labels: input.labels,\n estIn,\n estOut: estIn,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.chat) throw new Error(`createAI: provider \"${spec.provider}\" does not support chat (translate routes through chat)`);\n return adapter.chat({ messages, spec });\n },\n });\n return { text: res.text, usage: res.usage };\n },\n\n async image(input: ImageInput): Promise<ImageResult> {\n input = imageInputSchema.parse(input);\n // Normalize the `lora` shorthand into the loras array.\n const loras = [\n ...(input.loras ?? []),\n ...(input.lora ? [{ path: input.lora }] : []),\n ];\n // Route by what's supplied (override still wins): `referenceImages` → the EU\n // BFL FLUX 2 multi-reference endpoint (F023.5, no training step); a `finetune`\n // id → the EU BFL finetuned-portrait endpoint (F023); LoRAs → flux-lora (F021,\n // flux/schnell can't merge LoRAs); else the plain image route.\n const base = input.referenceImages?.length\n ? DEFAULT_BFL_REFERENCE_SPEC\n : input.finetune\n ? DEFAULT_BFL_FINETUNE_SPEC\n : loras.length > 0\n ? DEFAULT_LORA_IMAGE_SPEC\n : DEFAULT_IMAGE_SPEC;\n return runCapability({\n primary: { ...base, ...input.override },\n fallback: input.fallback,\n capability: \"image\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: 0, // image cost is not token-based\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.image) throw new Error(`createAI: provider \"${spec.provider}\" does not support image`);\n return adapter.image({\n prompt: input.prompt,\n spec,\n width: input.width,\n height: input.height,\n loras: loras.length ? loras : undefined,\n finetune: input.finetune,\n finetuneStrength: input.finetuneStrength,\n referenceImages: input.referenceImages,\n seed: input.seed,\n outputFormat: input.outputFormat,\n safetyTolerance: input.safetyTolerance,\n retryOnBlack: input.retryOnBlack,\n });\n },\n });\n },\n\n async animate(input: AnimateInput): Promise<AnimateResult> {\n input = animateInputSchema.parse(input);\n // Append the default audio directive (no speech, ambient sounds matched to scene).\n const prompt = input.prompt?.trim()\n ? `${input.prompt.trim()} ${ANIMATE_AUDIO_DIRECTIVE}`\n : ANIMATE_AUDIO_DIRECTIVE;\n return runCapability({\n primary: { ...DEFAULT_ANIMATE_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"animate\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: 0, // video cost is per-second, not token-based\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.animate) throw new Error(`createAI: provider \"${spec.provider}\" does not support animate`);\n return adapter.animate({\n image: input.image,\n prompt,\n durationSec: input.durationSec,\n resolution: input.resolution,\n spec,\n });\n },\n });\n },\n\n async trainStyle(input: TrainStyleInput): Promise<TrainStyleResult> {\n input = trainStyleInputSchema.parse(input);\n return runCapability({\n primary: { ...DEFAULT_TRAINSTYLE_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"trainStyle\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: 0, // training is priced flat by fal, not token-based\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.trainStyle)\n throw new Error(`createAI: provider \"${spec.provider}\" does not support trainStyle`);\n return adapter.trainStyle({\n images: input.images,\n spec,\n isStyle: input.isStyle,\n triggerWord: input.triggerWord,\n steps: input.steps,\n createMasks: input.createMasks,\n });\n },\n });\n },\n\n async ocr(input: OcrInput): Promise<OcrResult> {\n input = ocrInputSchema.parse(input);\n return runCapability({\n primary: { ...DEFAULT_OCR_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"ocr\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: 0, // OCR cost is per-page, not token-based\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.ocr) throw new Error(`createAI: provider \"${spec.provider}\" does not support ocr`);\n return adapter.ocr({ document: input.document, mimeType: input.mimeType, spec });\n },\n });\n },\n\n async moderate(input: ModerationInput): Promise<ModerationResult> {\n input = moderationInputSchema.parse(input);\n const items = Array.isArray(input.input) ? input.input : [input.input];\n return runCapability({\n primary: { ...DEFAULT_MODERATION_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"moderation\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: items.reduce((n, s) => n + estTokens(s), 0),\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.moderate) throw new Error(`createAI: provider \"${spec.provider}\" does not support moderation`);\n return adapter.moderate({ input: items, spec });\n },\n });\n },\n\n async podcast(input: PodcastInput): Promise<PodcastResult> {\n input = podcastInputSchema.parse(input);\n // Map each manuscript turn to a {text, voiceId} dialogue input.\n const inputs = input.script.map((turn) => {\n const mapped = input.voices[turn.speaker];\n if (!mapped) throw new Error(`ai.podcast: no voice mapped for speaker \"${turn.speaker}\"`);\n return { text: turn.text, voiceId: resolveVoice(mapped) }; // curated name → voiceId\n });\n const chars = input.script.reduce((n, t) => n + t.text.length, 0);\n return runCapability({\n primary: { ...DEFAULT_PODCAST_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"podcast\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: chars, // per-character cost (not token-based)\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.dialogue) throw new Error(`createAI: provider \"${spec.provider}\" does not support podcast/dialogue`);\n return adapter.dialogue({ inputs, format: input.format, spec });\n },\n });\n },\n\n async tts(input: TtsInput): Promise<PodcastResult> {\n input = ttsInputSchema.parse(input);\n return runCapability({\n primary: { ...DEFAULT_TTS_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"tts\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: input.text.length, // per-character cost\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.tts) throw new Error(`createAI: provider \"${spec.provider}\" does not support tts`);\n return adapter.tts({ text: input.text, voiceId: resolveVoice(input.voice), lang: input.lang, format: input.format, rate: input.rate, spec });\n },\n });\n },\n\n async embedding(input: EmbeddingInput): Promise<EmbeddingResult> {\n input = embeddingInputSchema.parse(input);\n const tier = input.tier ?? EMBEDDING_DEFAULT_TIER;\n const text = Array.isArray(input.text) ? input.text : [input.text];\n return runCapability({\n primary: resolveTier(tier, input.override, cfg.defaults),\n fallback: input.fallback,\n capability: \"embedding\",\n tier,\n purpose: input.purpose,\n labels: input.labels,\n estIn: text.reduce((n, t) => n + estTokens(t), 0),\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.embedding) throw new Error(`createAI: provider \"${spec.provider}\" does not support embedding`);\n return adapter.embedding({ input: text, spec });\n },\n });\n },\n\n async transcribe(input: TranscribeInput): Promise<TranscribeResult> {\n input = transcribeInputSchema.parse(input);\n const audio = await resolveAudio(input.audio);\n return runCapability({\n primary: { ...DEFAULT_TRANSCRIBE_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"transcribe\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: 0,\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.transcribe) throw new Error(`createAI: provider \"${spec.provider}\" does not support transcribe`);\n return adapter.transcribe({ audio, language: input.language, durationSec: input.durationSec, phrases: input.phrases, spec });\n },\n });\n },\n\n batch: {\n async submit(input: { requests: BatchRequestItem[]; override?: TierSpec }): Promise<BatchJob> {\n const spec = { ...DEFAULT_BATCH_SPEC, ...input.override };\n const adapter = pickProvider(spec.provider);\n if (!adapter.batchSubmit) throw new Error(`createAI: provider \"${spec.provider}\" does not support batch`);\n return adapter.batchSubmit({ items: input.requests, spec });\n },\n async status(jobId: string, override?: TierSpec): Promise<BatchJob> {\n const spec = { ...DEFAULT_BATCH_SPEC, ...override };\n const adapter = pickProvider(spec.provider);\n if (!adapter.batchStatus) throw new Error(`createAI: provider \"${spec.provider}\" does not support batch`);\n return adapter.batchStatus({ jobId, spec });\n },\n async results(jobId: string, override?: TierSpec): Promise<BatchResultItem[]> {\n const spec = { ...DEFAULT_BATCH_SPEC, ...override };\n const adapter = pickProvider(spec.provider);\n if (!adapter.batchResults) throw new Error(`createAI: provider \"${spec.provider}\" does not support batch`);\n return adapter.batchResults({ jobId, spec });\n },\n },\n\n // Replaced below with the real prompt-contracts (needs the client itself).\n contracts: undefined as unknown as AiClient[\"contracts\"],\n };\n\n client.contracts = makeContracts(client);\n return client;\n}\n","// Stub provider adapters (F2.5). They satisfy ProviderAdapter so the client wires\n// up and resolves without real network calls. Real implementations land in F4\n// (anthropic/openai/gemini/openrouter/deepinfra) and F5.3 (fal image). The stub\n// usage carries zero tokens/cost — F3.1 fills real numbers in the live adapters.\nimport type {\n ProviderAdapter,\n ChatRequest,\n ChatResult,\n ImageRequest,\n ImageResult,\n EmbeddingRequest,\n EmbeddingResult,\n Usage,\n Capability,\n} from \"../types.js\";\n\nfunction stubUsage(\n provider: string,\n model: string,\n transport: \"http\" | \"subprocess\",\n capability: Capability,\n): Usage {\n return {\n provider,\n model,\n transport,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheCreationTokens: 0,\n costUsd: 0,\n latencyMs: 0,\n capability,\n // ts is supplied by the caller-side at real call time; stub uses a fixed marker\n // ('' avoids Date.now() — keeps the stub pure/deterministic for tests).\n ts: \"\",\n };\n}\n\nfunction lastUserText(req: ChatRequest): string {\n for (let i = req.messages.length - 1; i >= 0; i--) {\n const m = req.messages[i];\n if (m && m.role === \"user\") {\n return typeof m.content === \"string\"\n ? m.content\n : m.content.map((p) => (p.type === \"text\" ? p.text : \"[image]\")).join(\" \");\n }\n }\n return \"\";\n}\n\n/** Anthropic adapter stub (HTTP path). */\nexport const anthropicApiAdapter: ProviderAdapter = {\n name: \"anthropic\",\n async chat(req: ChatRequest): Promise<ChatResult> {\n return {\n text: `[stub:anthropic-api] ${lastUserText(req)}`,\n usage: stubUsage(\"anthropic\", req.spec.model, \"http\", \"chat\"),\n };\n },\n async vision(req: ChatRequest): Promise<ChatResult> {\n return {\n text: `[stub:anthropic-api:vision] ${lastUserText(req)}`,\n usage: stubUsage(\"anthropic\", req.spec.model, \"http\", \"vision\"),\n };\n },\n};\n\n/** Anthropic adapter stub (subprocess / `claude -p` path). */\nexport const anthropicSubprocessAdapter: ProviderAdapter = {\n name: \"anthropic\",\n async chat(req: ChatRequest): Promise<ChatResult> {\n const usage = stubUsage(\"anthropic\", req.spec.model, \"subprocess\", \"chat\");\n usage.subprocess = true;\n return { text: `[stub:anthropic-subprocess] ${lastUserText(req)}`, usage };\n },\n};\n\n/** Mistral adapter stub — covers the default text/vision tiers (F030: fast/smart/\n * powerful/vision/cheap all default to Mistral EU after the Anthropic phase-out). */\nexport const mistralStubAdapter: ProviderAdapter = {\n name: \"mistral\",\n async chat(req: ChatRequest): Promise<ChatResult> {\n return {\n text: `[stub:mistral] ${lastUserText(req)}`,\n usage: stubUsage(\"mistral\", req.spec.model, \"http\", \"chat\"),\n };\n },\n async vision(req: ChatRequest): Promise<ChatResult> {\n return {\n text: `[stub:mistral:vision] ${lastUserText(req)}`,\n usage: stubUsage(\"mistral\", req.spec.model, \"http\", \"vision\"),\n };\n },\n};\n\n/** OpenAI adapter stub — covers the embedding default tier + a chat fallback. */\nexport const openaiStubAdapter: ProviderAdapter = {\n name: \"openai\",\n async chat(req: ChatRequest): Promise<ChatResult> {\n return {\n text: `[stub:openai] ${lastUserText(req)}`,\n usage: stubUsage(\"openai\", req.spec.model, \"http\", \"chat\"),\n };\n },\n async embedding(req: EmbeddingRequest): Promise<EmbeddingResult> {\n return {\n vectors: req.input.map(() => [0, 0, 0]),\n usage: stubUsage(\"openai\", req.spec.model, \"http\", \"embedding\"),\n };\n },\n};\n\n/** fal.ai adapter stub — image generation (real one in fal.ts, F5.3). */\nexport const falStubAdapter: ProviderAdapter = {\n name: \"fal\",\n async image(req: ImageRequest): Promise<ImageResult> {\n return {\n url: `https://stub.fal/${encodeURIComponent(req.prompt).slice(0, 32)}.png`,\n usage: stubUsage(\"fal\", req.spec.model, \"http\", \"image\"),\n };\n },\n};\n\n/** Stub provider registry — deterministic, no network. Used by tests via\n * createAI({ providers: stubProviders }). The real default registry (registry.ts)\n * wires the live adapters. */\nexport const stubProviders: Record<string, ProviderAdapter> = {\n anthropic: anthropicApiAdapter,\n mistral: mistralStubAdapter,\n openai: openaiStubAdapter,\n fal: falStubAdapter,\n};\n","// AUTO-GENERATED by scripts/gen-version.mjs — do not edit, do not commit.\nexport const VERSION = \"0.21.1\" as const;\nexport const SDK_TAG = \"@broberg/ai-sdk@0.21.1\" as const;\n","// F022 — async, off-the-hot-path availability refresh. The host runs this\n// out-of-band (a timer / at idle); it mutates the registry overlay so the next\n// synchronous resolveModel() sees overnight changes like the 2026-06-12 Fable /\n// Mythos suspension. NEVER on the resolve hot path. Never hard-fails the SDK:\n// a network/auth error keeps the curated defaults.\nimport { providerIds, setAvailability } from \"./registry.js\";\n\nexport interface RefreshOptions {\n /** Only \"anthropic\" is wired in v1 (where the incident hit). */\n provider?: \"anthropic\";\n /** Injectable for tests. Defaults to global fetch. */\n fetch?: typeof fetch;\n /** Defaults to process.env.ANTHROPIC_API_KEY. */\n apiKey?: string;\n /** Min ms between live fetches for a provider (default 1h). */\n ttlMs?: number;\n /** Injectable clock for deterministic TTL tests. Defaults to Date.now(). */\n now?: number;\n}\n\nexport interface RefreshResult {\n refreshed: boolean;\n checked: number;\n markedUnavailable: string[];\n}\n\nconst NOT_REFRESHED: RefreshResult = { refreshed: false, checked: 0, markedUnavailable: [] };\nconst DEFAULT_TTL_MS = 60 * 60 * 1000; // 1h\nconst ANTHROPIC_MODELS_URL = \"https://api.anthropic.com/v1/models\";\n\n/** Last successful live fetch per provider, for TTL short-circuiting. */\nconst lastRefreshAt = new Map<string, number>();\n\n/** Reset the TTL bookkeeping. For tests. */\nexport function resetRefreshState(): void {\n lastRefreshAt.clear();\n}\n\ninterface AnthropicModelsResponse {\n data?: { id?: string }[];\n}\n\n/**\n * Reconcile tracked models against the provider's live list. For Anthropic:\n * GET /v1/models — any tracked anthropic id NOT in the live set is marked\n * unavailable; ids present are (re)marked available. TTL-cached; a fetch within\n * the window is a no-op. Returns { refreshed:false } on any error or missing key.\n */\nexport async function refreshAvailability(opts: RefreshOptions = {}): Promise<RefreshResult> {\n const provider = opts.provider ?? \"anthropic\";\n if (provider !== \"anthropic\") return NOT_REFRESHED;\n\n const ttl = opts.ttlMs ?? DEFAULT_TTL_MS;\n const now = opts.now ?? Date.now();\n const last = lastRefreshAt.get(provider);\n if (last !== undefined && now - last < ttl) return NOT_REFRESHED; // within TTL → skip\n\n const apiKey = opts.apiKey ?? process.env.ANTHROPIC_API_KEY;\n if (!apiKey) return NOT_REFRESHED;\n\n const f = opts.fetch ?? fetch;\n let liveIds: Set<string>;\n try {\n const res = await f(ANTHROPIC_MODELS_URL, {\n headers: { \"x-api-key\": apiKey, \"anthropic-version\": \"2023-06-01\", accept: \"application/json\" },\n });\n if (!res.ok) return NOT_REFRESHED;\n const json = (await res.json()) as AnthropicModelsResponse;\n liveIds = new Set((json.data ?? []).map((m) => m.id).filter((id): id is string => typeof id === \"string\"));\n } catch {\n return NOT_REFRESHED; // network error → keep defaults\n }\n\n // A models list that came back empty is almost certainly an API hiccup, not\n // \"every model is dead\" — don't suspend the whole provider on it.\n if (liveIds.size === 0) return NOT_REFRESHED;\n\n const tracked = providerIds(provider);\n const markedUnavailable: string[] = [];\n for (const id of tracked) {\n const live = liveIds.has(id);\n if (live) {\n setAvailability(id, true);\n } else {\n setAvailability(id, false, \"not in provider model list (live refresh)\");\n markedUnavailable.push(id);\n }\n }\n\n lastRefreshAt.set(provider, now);\n return { refreshed: true, checked: tracked.length, markedUnavailable };\n}\n","// Persistent BudgetStore backed by bun:sqlite (F7.1). The rolling total survives\n// process restarts and is shared by every process pointing at the same file, so\n// a budget ceiling is a real production guard — not a per-process counter that\n// resets on deploy. bun:sqlite is imported lazily (Node-safe import, like sqliteSink).\nimport type { BudgetStore } from \"../types.js\";\n\nexport interface SqliteBudgetStoreConfig {\n /** SQLite file path, e.g. \"./ai-budget.db\". */\n dbPath: string;\n /** Window/bucket key — use e.g. a day-stamp for a daily budget. Default \"default\". */\n key?: string;\n}\n\nexport function sqliteBudgetStore(config: SqliteBudgetStoreConfig): BudgetStore {\n const key = config.key ?? \"default\";\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let ready: Promise<any> | null = null;\n const open = async () => {\n const { Database } = await import(\"bun:sqlite\");\n const db = new Database(config.dbPath);\n db.run(\n `CREATE TABLE IF NOT EXISTS budget_spend (key TEXT PRIMARY KEY, spent_usd REAL NOT NULL DEFAULT 0)`,\n );\n return db;\n };\n\n return {\n async getSpent(): Promise<number> {\n const db = await (ready ??= open());\n const row = db\n .query(`SELECT spent_usd FROM budget_spend WHERE key = $key`)\n .get({ $key: key }) as { spent_usd: number } | null;\n return row?.spent_usd ?? 0;\n },\n async addSpent(usd: number): Promise<void> {\n const db = await (ready ??= open());\n db.run(\n `INSERT INTO budget_spend (key, spent_usd) VALUES ($key, $usd)\n ON CONFLICT(key) DO UPDATE SET spent_usd = spent_usd + $usd`,\n { $key: key, $usd: usd },\n );\n },\n };\n}\n","import type { CostSink } from \"../../types.js\";\n\n/** A sink that does nothing. The default when no costSink is configured. */\nexport const noopSink: CostSink = {\n record() {\n // intentionally empty\n },\n};\n","import type { CostSink, Usage } from \"../../types.js\";\n\n/** Fan a Usage out to several sinks. Uses allSettled so one failing sink never\n * prevents the others from recording (and never propagates to the caller). */\nexport function multiSink(sinks: CostSink[]): CostSink {\n return {\n async record(usage: Usage): Promise<void> {\n // async wrapper turns a synchronous throw in s.record into a rejected\n // promise, so allSettled isolates it (a sync throw would otherwise escape\n // the .map before allSettled ran).\n await Promise.allSettled(sinks.map(async (s) => s.record(usage)));\n },\n };\n}\n","// upmetricsSink — the canonical cost sink. Forwards each Usage to the upmetrics\n// agent-run ingest (POST /api/agent, mode:\"record\"). Field mapping follows\n// upmetrics/docs/AGENT-SCHEMA.md \"For cost-sink authors\" exactly:\n// - agent_kind / agent_name are injected (not in Usage; required by ingest)\n// - camelCase Usage → snake_case wire fields\n// - capability + transport ride in tags (no top-level column)\n// - toolCalls[].errorCount → tool_calls[].error_count (deep rename)\n// - latencyMs → duration_ms; ts → started_at; ended_at = ts + latency\n// Errors never propagate (CostSink invariant). Do NOT use @upmetrics/agent\n// wrapAnthropic here — the SDK already owns the provider call.\nimport { SDK_TAG } from \"../../version.js\";\nimport type { CostSink, Usage } from \"../../types.js\";\n\nexport interface UpmetricsSinkConfig {\n /** Ingest base URL, e.g. https://upmetrics.org */\n baseUrl: string;\n /** Per-project api_key → sent as the X-Upmetrics-Key header. */\n apiKey: string;\n /** Consumer name dashboards group by (e.g. \"cms\", \"trail\", \"xrt81\") — NOT the\n * capability. */\n agentName: string;\n /** Defaults to \"chatbot\" (\"embedding\" auto-selected for embedding calls). */\n agentKind?: string;\n /** When true, guarantees no prompt/response content is ever sent (the sink\n * sends none regardless — Usage carries no excerpts — so this is belt-and-\n * suspenders for GDPR-health projects). */\n complianceMode?: boolean;\n /** Injectable fetch for testing; defaults to global fetch. */\n fetch?: typeof fetch;\n /** Optional error hook (errors are otherwise swallowed silently). */\n onError?: (err: unknown) => void;\n}\n\nexport function upmetricsSink(config: UpmetricsSinkConfig): CostSink {\n const doFetch = config.fetch ?? fetch;\n const url = `${config.baseUrl.replace(/\\/$/, \"\")}/api/agent`;\n\n return {\n async record(usage: Usage): Promise<void> {\n try {\n const startedAt = usage.ts || new Date().toISOString();\n const endedAt = new Date(\n new Date(startedAt).getTime() + (usage.latencyMs || 0),\n ).toISOString();\n\n const agentKind =\n config.agentKind ?? (usage.capability === \"embedding\" ? \"embedding\" : \"chatbot\");\n\n const body: Record<string, unknown> = {\n mode: \"record\",\n agent_kind: agentKind,\n agent_name: config.agentName,\n provider: usage.provider,\n model: usage.model,\n status: \"success\",\n input_tokens: usage.inputTokens,\n output_tokens: usage.outputTokens,\n cache_read_tokens: usage.cacheReadTokens,\n cache_creation_tokens: usage.cacheCreationTokens,\n cost_usd: usage.costUsd,\n duration_ms: usage.latencyMs,\n started_at: startedAt,\n ended_at: endedAt,\n tags: {\n // Consumer attribution labels (e.g. tenantId) ride in tags so no new\n // top-level field risks the strict-shape ingest schema (F011). The\n // SDK-owned keys win — a label can never clobber capability/transport/sdk.\n ...usage.labels,\n capability: usage.capability,\n transport: usage.transport,\n sdk: SDK_TAG,\n },\n };\n if (usage.tier !== undefined) body.tier = usage.tier;\n if (usage.purpose !== undefined) body.purpose = usage.purpose;\n if (usage.toolCalls) {\n body.tool_calls = usage.toolCalls.map((t) => ({\n name: t.name,\n count: t.count,\n error_count: t.errorCount ?? 0,\n }));\n }\n // complianceMode is a no-op today (we never send excerpts) but documents intent.\n void config.complianceMode;\n\n const res = await doFetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"X-Upmetrics-Key\": config.apiKey,\n },\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n config.onError?.(\n new Error(`upmetricsSink: ingest returned ${res.status}: ${text.slice(0, 200)}`),\n );\n }\n } catch (err) {\n // Never let a sink failure crash a real AI call.\n config.onError?.(err);\n }\n },\n };\n}\n","// discordSink — posts a per-call cost embed to a Discord webhook. Secondary sink\n// (upmetricsSink is canonical); handy for repos not wired to Upmetrics or for an\n// at-a-glance spend feed. Plain fetch, no Discord SDK. Errors never propagate.\nimport type { CostSink, Usage } from \"../../types.js\";\n\nexport interface DiscordSinkConfig {\n webhookUrl: string;\n /** Skip posting paid calls below this USD threshold (anti-spam). Subprocess\n * (Max-plan free) calls always post so the \"free\" feed stays visible.\n * Default 0 → post everything. */\n minUsd?: number;\n fetch?: typeof fetch;\n onError?: (err: unknown) => void;\n}\n\nexport function discordSink(config: DiscordSinkConfig): CostSink {\n const doFetch = config.fetch ?? fetch;\n const minUsd = config.minUsd ?? 0;\n\n return {\n async record(usage: Usage): Promise<void> {\n try {\n // Skip cheap PAID calls; always show subprocess (free) calls.\n if (!usage.subprocess && usage.costUsd < minUsd) return;\n\n const costLabel = usage.subprocess\n ? \"Max plan (free)\"\n : `$${usage.costUsd.toFixed(6)}`;\n\n const embed = {\n title: `AI call — ${usage.capability}`,\n fields: [\n { name: \"Provider\", value: usage.provider, inline: true },\n { name: \"Model\", value: usage.model, inline: true },\n { name: \"Transport\", value: usage.transport, inline: true },\n { name: \"Cost\", value: costLabel, inline: true },\n {\n name: \"Tokens\",\n value: `${usage.inputTokens} in / ${usage.outputTokens} out`,\n inline: true,\n },\n { name: \"Latency\", value: `${usage.latencyMs} ms`, inline: true },\n ],\n timestamp: usage.ts || new Date().toISOString(),\n };\n\n const res = await doFetch(config.webhookUrl, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ embeds: [embed] }),\n });\n if (!res.ok) {\n config.onError?.(new Error(`discordSink: webhook returned ${res.status}`));\n }\n } catch (err) {\n config.onError?.(err);\n }\n },\n };\n}\n","// sqliteSink — persists every Usage to a local bun:sqlite DB. Secondary/offline\n// sink (upmetricsSink is canonical). No npm dependency — bun:sqlite is built in.\n//\n// IMPORTANT: bun:sqlite is imported LAZILY (dynamic import on first use), not at\n// module top level. A static `import \"bun:sqlite\"` would leak into the package\n// entry and crash every Node consumer (`ERR_UNSUPPORTED_ESM_URL_SCHEME`). With\n// the lazy import, importing @broberg/ai-sdk works everywhere; bun:sqlite only\n// loads when sqliteSink/getCostSummary actually run (Bun only).\nimport type { CostSink, Usage } from \"../../types.js\";\n\nexport interface SqliteSinkConfig {\n /** Path to the SQLite file, e.g. \"./ai-cost.db\" (or \":memory:\"). */\n dbPath: string;\n}\n\nconst CREATE_TABLE = `\nCREATE TABLE IF NOT EXISTS ai_usage (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n ts TEXT NOT NULL,\n provider TEXT NOT NULL,\n model TEXT NOT NULL,\n tier TEXT,\n transport TEXT NOT NULL,\n capability TEXT NOT NULL,\n purpose TEXT,\n input_tokens INTEGER NOT NULL,\n output_tokens INTEGER NOT NULL,\n cache_read_tokens INTEGER NOT NULL,\n cache_creation_tokens INTEGER NOT NULL,\n cost_usd REAL NOT NULL,\n latency_ms INTEGER NOT NULL,\n subprocess INTEGER NOT NULL DEFAULT 0\n)`;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function openDb(dbPath: string, readonly = false): Promise<any> {\n const { Database } = await import(\"bun:sqlite\");\n return new Database(dbPath, readonly ? { readonly: true } : undefined);\n}\n\nexport function sqliteSink(config: SqliteSinkConfig): CostSink {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let ready: Promise<any> | null = null;\n const init = async () => {\n const db = await openDb(config.dbPath);\n db.run(CREATE_TABLE);\n const insert = db.prepare(\n `INSERT INTO ai_usage\n (ts, provider, model, tier, transport, capability, purpose,\n input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens,\n cost_usd, latency_ms, subprocess)\n VALUES ($ts, $provider, $model, $tier, $transport, $capability, $purpose,\n $input, $output, $cacheRead, $cacheCreation, $cost, $latency, $subprocess)`,\n );\n return insert;\n };\n\n return {\n async record(usage: Usage): Promise<void> {\n const insert = await (ready ??= init());\n insert.run({\n $ts: usage.ts || new Date().toISOString(),\n $provider: usage.provider,\n $model: usage.model,\n $tier: usage.tier ?? null,\n $transport: usage.transport,\n $capability: usage.capability,\n $purpose: usage.purpose ?? null,\n $input: usage.inputTokens,\n $output: usage.outputTokens,\n $cacheRead: usage.cacheReadTokens,\n $cacheCreation: usage.cacheCreationTokens,\n $cost: usage.costUsd,\n $latency: usage.latencyMs,\n $subprocess: usage.subprocess ? 1 : 0,\n });\n },\n };\n}\n\nexport interface CostSummary {\n totalUsd: number;\n byProvider: Record<string, number>;\n byCapability: Record<string, number>;\n}\n\n/** Aggregate the recorded spend from a sqliteSink DB. Creates the table if the\n * DB has never been written to, so an empty DB summarises cleanly to 0. */\nexport async function getCostSummary(dbPath: string): Promise<CostSummary> {\n const db = await openDb(dbPath);\n db.run(CREATE_TABLE);\n const total = db\n .query(`SELECT SUM(cost_usd) AS total FROM ai_usage`)\n .get() as { total: number | null };\n const byProvider: Record<string, number> = {};\n for (const row of db\n .query(`SELECT provider, SUM(cost_usd) AS sum FROM ai_usage GROUP BY provider`)\n .all() as { provider: string; sum: number }[]) {\n byProvider[row.provider] = row.sum;\n }\n const byCapability: Record<string, number> = {};\n for (const row of db\n .query(`SELECT capability, SUM(cost_usd) AS sum FROM ai_usage GROUP BY capability`)\n .all() as { capability: string; sum: number }[]) {\n byCapability[row.capability] = row.sum;\n }\n return { totalUsd: total?.total ?? 0, byProvider, byCapability };\n}\n","// upmetricsCostClient — the cost READ-back side, companion to upmetricsSink (the\n// write side). Upmetrics owns cost AGGREGATION (it already rolls up agent_runs):\n// this is a thin, browser-clean wrapper over its public cost read-API\n// (upmetrics/docs/COST-API.md, F014) so a consuming app reads its OWN accumulated\n// cost from the canonical source instead of re-aggregating locally.\n//\n// Money is integer micro-USD ($1 = 1_000_000); Upmetrics rounds once at the\n// response boundary so sub-cent calls aren't lost. Pure fetch, zero new deps, no\n// bun:sqlite import → safe to import from a browser/Vite build.\n\n/** Thrown when the cost read-API rejects (e.g. 401 invalid_api_key) or is unreachable. */\nexport class UpmetricsCostError extends Error {\n readonly status?: number;\n readonly code?: string;\n constructor(message: string, opts?: { status?: number; code?: string }) {\n super(message);\n this.name = \"UpmetricsCostError\";\n this.status = opts?.status;\n this.code = opts?.code;\n }\n}\n\nexport interface UpmetricsCostClientConfig {\n /** Read-API base URL, e.g. https://upmetrics.org */\n baseUrl: string;\n /** Per-project api_key (uk_…) — sent as X-Upmetrics-Key; resolves to your own project only. */\n apiKey: string;\n /** Injectable fetch for testing; defaults to global fetch. */\n fetch?: typeof fetch;\n}\n\n/** Shared filter surface for summary + timeseries (mirrors COST-API.md query params). */\nexport interface CostQuery {\n /** Relative window; ignored when from/to are given. */\n window?: \"day\" | \"week\" | \"month\";\n /** Explicit window start (ISO-8601 or epoch-ms) — overrides `window`. */\n from?: string | number;\n /** Explicit window end (ISO-8601 or epoch-ms) — overrides `window`. */\n to?: string | number;\n provider?: string;\n model?: string;\n tier?: string;\n /** Filter to one consumer (the sink's agent_name). */\n agentName?: string;\n transport?: \"http\" | \"subprocess\";\n /** Tag filters → `tag.<key>=<value>` (e.g. { tenantId: \"sanne\" }). */\n tags?: Record<string, string>;\n}\n\nexport interface CostSummaryQuery extends CostQuery {\n /** Break the total down per distinct value of this tag key (the per-tenant view). */\n groupBy?: string;\n}\n\nexport interface CostTimeseriesQuery extends CostQuery {\n /** Bucket granularity (default \"day\"). */\n bucket?: \"day\" | \"hour\";\n}\n\n/** One breakdown row, ordered by cost desc. `tier`/`capability` fall back to \"(none)\". */\nexport interface UpmetricsCostRow {\n key: string;\n micro_usd: number;\n input_tokens: number;\n output_tokens: number;\n run_count: number;\n}\n\nexport interface UpmetricsCostSummary {\n generated_at: string;\n window: { from: string; to: string };\n total_micro_usd: number;\n input_tokens: number;\n output_tokens: number;\n cache_read_tokens: number;\n cache_creation_tokens: number;\n run_count: number;\n metered: { metered_micro_usd: number; free_run_count: number };\n by_provider: UpmetricsCostRow[];\n by_model: UpmetricsCostRow[];\n by_tier: UpmetricsCostRow[];\n by_capability: UpmetricsCostRow[];\n /** Present only when `groupBy` was requested. */\n group_by?: string;\n by_group?: UpmetricsCostRow[];\n}\n\nexport interface UpmetricsCostTimeseries {\n generated_at: string;\n bucket: \"day\" | \"hour\";\n window: { from: string; to: string };\n /** Only non-zero buckets are returned — pad missing buckets yourself. */\n points: Array<{\n ts: string;\n micro_usd: number;\n input_tokens: number;\n output_tokens: number;\n run_count: number;\n }>;\n}\n\n/** Convert integer micro-USD to a USD float for display. `$1 = 1_000_000`. */\nexport const usdFromMicro = (microUsd: number): number => microUsd / 1_000_000;\n\nfunction buildQuery(q: CostQuery & { groupBy?: string; bucket?: string }): string {\n const p = new URLSearchParams();\n if (q.bucket) p.set(\"bucket\", q.bucket);\n if (q.from !== undefined) p.set(\"from\", String(q.from));\n if (q.to !== undefined) p.set(\"to\", String(q.to));\n // `window` is ignored server-side when from/to are present; only send it otherwise.\n if (q.window && q.from === undefined && q.to === undefined) p.set(\"window\", q.window);\n if (q.provider) p.set(\"provider\", q.provider);\n if (q.model) p.set(\"model\", q.model);\n if (q.tier) p.set(\"tier\", q.tier);\n if (q.agentName) p.set(\"agent_name\", q.agentName);\n if (q.transport) p.set(\"transport\", q.transport);\n if (q.groupBy) p.set(\"groupBy\", q.groupBy);\n for (const [k, v] of Object.entries(q.tags ?? {})) p.set(`tag.${k}`, v);\n const s = p.toString();\n return s ? `?${s}` : \"\";\n}\n\nexport function upmetricsCostClient(config: UpmetricsCostClientConfig): {\n summary(query?: CostSummaryQuery): Promise<UpmetricsCostSummary>;\n timeseries(query?: CostTimeseriesQuery): Promise<UpmetricsCostTimeseries>;\n} {\n const doFetch = config.fetch ?? fetch;\n const base = config.baseUrl.replace(/\\/$/, \"\");\n\n async function get<T>(path: string, query: string): Promise<T> {\n let res: Response;\n try {\n res = await doFetch(`${base}${path}${query}`, {\n method: \"GET\",\n headers: { \"X-Upmetrics-Key\": config.apiKey },\n });\n } catch (err) {\n throw new UpmetricsCostError(\n `upmetricsCostClient: ${path} unreachable: ${(err as Error)?.message ?? String(err)}`,\n );\n }\n if (!res.ok) {\n let code: string | undefined;\n const text = await res.text().catch(() => \"\");\n try {\n code = (JSON.parse(text) as { error?: string }).error;\n } catch {\n /* non-JSON error body */\n }\n throw new UpmetricsCostError(\n `upmetricsCostClient: ${path} returned ${res.status}${code ? ` (${code})` : \"\"}`,\n { status: res.status, code },\n );\n }\n return (await res.json()) as T;\n }\n\n return {\n summary(query: CostSummaryQuery = {}): Promise<UpmetricsCostSummary> {\n return get<UpmetricsCostSummary>(\"/api/cost/summary\", buildQuery(query));\n },\n timeseries(query: CostTimeseriesQuery = {}): Promise<UpmetricsCostTimeseries> {\n return get<UpmetricsCostTimeseries>(\"/api/cost/timeseries\", buildQuery(query));\n },\n };\n}\n"],"mappings":"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","names":["url","data","mimeType","EU_BASE","sleep","res"]}
|
|
1
|
+
{"version":3,"sources":["../src/routing/tier-map.ts","../src/transport/http.ts","../src/transport/subprocess.ts","../src/transport/stream.ts","../src/providers/tools.ts","../src/cost/usage.ts","../src/providers/anthropic.ts","../src/providers/openai-compatible.ts","../src/providers/openai.ts","../src/providers/media.ts","../src/providers/gemini.ts","../src/providers/deepinfra.ts","../src/providers/openrouter.ts","../src/providers/requesty.ts","../src/providers/deepseek.ts","../src/providers/mistral.ts","../src/providers/elevenlabs.ts","../src/providers/azure.ts","../src/providers/vertex.ts","../src/providers/deepl.ts","../src/providers/fal.ts","../src/providers/bfl.ts","../src/providers/registry.ts","../src/cost/budget.ts","../src/capabilities/vision.ts","../src/capabilities/video.ts","../src/capabilities/translate.ts","../src/capabilities/embedding.ts","../src/capabilities/transcribe.ts","../src/capabilities/contracts/index.ts","../src/schema/inputs.ts","../src/client.ts","../src/providers/stub.ts","../src/version.ts","../src/availability/refresh.ts","../src/cost/budget-store.ts","../src/cost/sinks/noop.ts","../src/cost/sinks/multi.ts","../src/cost/sinks/upmetrics.ts","../src/cost/sinks/discord.ts","../src/cost/sinks/sqlite.ts","../src/cost/upmetrics-read.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","// HTTP transport: a thin fetch wrapper. Provider-agnostic — the adapter supplies\n// the fully-built url/headers/body and parses the returned json itself.\nimport type { TransportRequest, HttpResponse } from \"./types.js\";\n\nexport async function httpTransport(req: TransportRequest): Promise<HttpResponse> {\n if (!req.http) {\n throw new Error(\"httpTransport: req.http is required for http transport\");\n }\n const { url, method = \"POST\", headers, body } = req.http;\n const res = await fetch(url, {\n method,\n headers,\n body:\n body === undefined\n ? undefined\n : typeof body === \"string\"\n ? body\n : JSON.stringify(body),\n });\n const json: unknown = await res.json().catch(() => undefined);\n return { ok: res.ok, status: res.status, json };\n}\n","// Subprocess transport: runs the local `claude -p` CLI (Anthropic Max plan).\n// No API key, no metered charge — costUsd is always 0, flagged subprocess:true so\n// dashboards can split free (Max) from paid (API). Token counts still come back\n// from the CLI's JSON so usage is tracked even when cost is zero.\nimport type { TransportRequest, SubprocessResponse } from \"./types.js\";\n\n/** The subset of `claude -p --output-format json` output we read. The CLI emits\n * more fields; we only need the result text + token usage. */\ninterface ClaudeCliJson {\n result?: string;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n };\n}\n\n/** Pure parser for the `claude -p --output-format json` stdout. Exported so it\n * can be unit-tested without spawning the binary. costUsd is pinned to 0. */\nexport function parseClaudeCliJson(raw: string): SubprocessResponse {\n let parsed: ClaudeCliJson;\n try {\n parsed = JSON.parse(raw) as ClaudeCliJson;\n } catch {\n throw new Error(\n `subprocessTransport: could not parse claude -p JSON output: ${raw.slice(0, 200)}`,\n );\n }\n const u = parsed.usage ?? {};\n return {\n text: parsed.result ?? \"\",\n inputTokens: u.input_tokens ?? 0,\n outputTokens: u.output_tokens ?? 0,\n cacheReadTokens: u.cache_read_input_tokens ?? 0,\n cacheCreationTokens: u.cache_creation_input_tokens ?? 0,\n costUsd: 0,\n subprocess: true,\n };\n}\n\nexport async function subprocessTransport(\n req: TransportRequest,\n): Promise<SubprocessResponse> {\n if (!req.subprocess) {\n throw new Error(\"subprocessTransport: req.subprocess is required for subprocess transport\");\n }\n const { prompt, systemPrompt } = req.subprocess;\n\n const cmd = [\"claude\", \"-p\", \"--output-format\", \"json\", \"--model\", req.spec.model];\n if (systemPrompt) cmd.push(\"--system-prompt\", systemPrompt);\n\n // Prompt goes in on stdin as a Blob (no argv length limit, no manual FileSink).\n const proc = (() => {\n try {\n return Bun.spawn(cmd, {\n stdin: new Blob([prompt]),\n stdout: \"pipe\",\n stderr: \"pipe\",\n });\n } catch (err) {\n throw new Error(\n `subprocessTransport: failed to spawn 'claude' — is the CLI installed and on PATH? (${String(err)})`,\n );\n }\n })();\n\n const [stdout, stderr, exitCode] = await Promise.all([\n new Response(proc.stdout).text(),\n new Response(proc.stderr).text(),\n proc.exited,\n ]);\n\n if (exitCode !== 0) {\n throw new Error(\n `subprocessTransport: claude -p exited ${exitCode}: ${stderr.slice(0, 300) || stdout.slice(0, 300)}`,\n );\n }\n\n return parseClaudeCliJson(stdout);\n}\n","// SSE streaming transport (F8.1). Like httpTransport but yields the parsed\n// `data:` payloads from the response body instead of awaiting .json() — pure\n// fetch + a ReadableStream reader, so it is Node 18+ and Bun safe. The adapter\n// supplies the `stream:true` body and parses each yielded JSON string itself.\nimport type { TransportRequest } from \"./types.js\";\n\n/** HTTP error from a streaming connect — carries `status` so the client's\n * pre-stream fallback can tell an eligible 429/5xx from a hard 4xx. */\nexport class StreamHttpError extends Error {\n readonly status: number;\n constructor(message: string, status: number) {\n super(message);\n this.name = \"StreamHttpError\";\n this.status = status;\n }\n}\n\nexport interface StreamTransportRequest extends TransportRequest {\n /** Injectable fetch for tests. */\n fetch?: typeof fetch;\n}\n\n/**\n * Open an SSE stream and yield each event's `data:` payload as a raw string\n * (the JSON after `data: `), skipping the `[DONE]` terminator and non-data\n * lines. Throws StreamHttpError before the first yield on a non-2xx connect.\n */\nexport async function* streamTransport(req: StreamTransportRequest): AsyncIterable<string> {\n if (!req.http) throw new Error(\"streamTransport: req.http is required for http transport\");\n const { url, method = \"POST\", headers, body } = req.http;\n const fetchImpl = req.fetch ?? fetch;\n const res = await fetchImpl(url, {\n method,\n headers,\n body:\n body === undefined\n ? undefined\n : typeof body === \"string\"\n ? body\n : JSON.stringify(body),\n });\n if (!res.ok || !res.body) {\n const text = await res.text().catch(() => \"\");\n throw new StreamHttpError(`stream ${res.status}: ${text.slice(0, 300)}`, res.status);\n }\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n // OpenAI/Anthropic emit one `data: {json}\\n\\n` per event — parse per line.\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) >= 0) {\n const line = buffer.slice(0, nl).replace(/\\r$/, \"\");\n buffer = buffer.slice(nl + 1);\n if (!line.startsWith(\"data:\")) continue; // skip comments / event: / id:\n const data = line.slice(5).trim();\n if (data === \"[DONE]\") return;\n if (data) yield data;\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n","// Cross-provider tool/function-calling normalization. The SDK speaks one Tool /\n// ToolCall shape; each provider has its own. toProviderTools builds the request\n// tools array; fromProviderToolCall parses one tool-call out of a response.\n// OpenAI, DeepInfra and OpenRouter share the OpenAI-compatible format.\nimport type { Tool, ToolCall } from \"../types.js\";\n\ntype ToolProvider = \"openai\" | \"deepinfra\" | \"openrouter\" | \"gemini\" | \"anthropic\";\n\nfunction family(provider: string): ToolProvider {\n if (provider === \"gemini\" || provider === \"google\") return \"gemini\";\n if (provider === \"anthropic\") return \"anthropic\";\n // openai, deepinfra, openrouter — all OpenAI-compatible\n return \"openai\";\n}\n\n/** Convert SDK tools to a provider's request format. */\nexport function toProviderTools(tools: Tool[], provider: string): unknown {\n switch (family(provider)) {\n case \"openai\":\n return tools.map((t) => ({\n type: \"function\",\n function: { name: t.name, description: t.description, parameters: t.parameters },\n }));\n case \"gemini\":\n return [\n {\n functionDeclarations: tools.map((t) => ({\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n })),\n },\n ];\n case \"anthropic\":\n return tools.map((t) => ({\n name: t.name,\n description: t.description,\n input_schema: t.parameters,\n }));\n default:\n throw new Error(`toProviderTools: unsupported provider family for \"${provider}\"`);\n }\n}\n\n/** Parse a single provider-shaped tool call back into the SDK ToolCall shape. */\nexport function fromProviderToolCall(raw: unknown, provider: string): ToolCall {\n const r = raw as Record<string, unknown>;\n switch (family(provider)) {\n case \"openai\": {\n // { id, type:\"function\", function:{ name, arguments:\"<json>\" } }\n const fn = (r.function ?? {}) as { name?: string; arguments?: string };\n return {\n id: typeof r.id === \"string\" ? r.id : \"\",\n name: fn.name ?? \"\",\n arguments: parseArgs(fn.arguments),\n };\n }\n case \"gemini\": {\n // { functionCall:{ name, args } } or { name, args }\n const fc = (r.functionCall ?? r) as { name?: string; args?: unknown };\n return {\n id: \"\", // Gemini function calls have no id\n name: fc.name ?? \"\",\n arguments: (fc.args as Record<string, unknown>) ?? {},\n };\n }\n case \"anthropic\": {\n // { type:\"tool_use\", id, name, input }\n return {\n id: typeof r.id === \"string\" ? r.id : \"\",\n name: typeof r.name === \"string\" ? r.name : \"\",\n arguments: (r.input as Record<string, unknown>) ?? {},\n };\n }\n default:\n throw new Error(`fromProviderToolCall: unsupported provider family for \"${provider}\"`);\n }\n}\n\nfunction parseArgs(raw: unknown): Record<string, unknown> {\n if (raw === undefined || raw === null) return {};\n if (typeof raw === \"object\") return raw as Record<string, unknown>;\n if (typeof raw === \"string\") {\n try {\n return JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return {};\n }\n }\n return {};\n}\n","// Usage construction + cost computation. Real adapters (F4) build their Usage via\n// freshUsage() and fill costUsd from computeCost(). The pricing table lives in\n// ./pricing.ts (F3.6); until a model is priced, computeCost returns 0 so calls\n// still complete (cost just shows $0 rather than throwing).\nimport { getPrice } from \"./pricing.js\";\nimport type { Usage, Transport, Capability } from \"../types.js\";\n\n/**\n * Cost in USD for a call. cache-read/creation tokens are priced separately when\n * the pricing entry defines rates for them; otherwise they fall back to the\n * input rate (read) / are ignored (creation). Unknown model → 0.\n */\nexport function computeCost(\n provider: string,\n model: string,\n inputTokens: number,\n outputTokens: number,\n cacheReadTokens = 0,\n cacheCreationTokens = 0,\n): number {\n const price = getPrice(provider, model);\n if (!price) return 0;\n const perToken = (per1M: number) => per1M / 1_000_000;\n const inRate = perToken(price.inputPer1M);\n const outRate = perToken(price.outputPer1M);\n const cacheReadRate =\n price.cacheReadPer1M !== undefined ? perToken(price.cacheReadPer1M) : inRate;\n const cacheWriteRate =\n price.cacheWritePer1M !== undefined ? perToken(price.cacheWritePer1M) : inRate;\n return (\n inputTokens * inRate +\n outputTokens * outRate +\n cacheReadTokens * cacheReadRate +\n cacheCreationTokens * cacheWriteRate\n );\n}\n\n/** Build a Usage with cost computed from the pricing table. Adapters call this\n * after a successful provider call; latencyMs/ts/capability are stamped by the\n * client (call-context owner), so they default to 0/\"\"/the passed capability. */\nexport function freshUsage(args: {\n provider: string;\n model: string;\n transport: Transport;\n capability: Capability;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheCreationTokens?: number;\n subprocess?: boolean;\n}): Usage {\n const cacheReadTokens = args.cacheReadTokens ?? 0;\n const cacheCreationTokens = args.cacheCreationTokens ?? 0;\n // Subprocess (Max plan) is never a metered charge to us — cost is always 0.\n const costUsd = args.subprocess\n ? 0\n : computeCost(\n args.provider,\n args.model,\n args.inputTokens,\n args.outputTokens,\n cacheReadTokens,\n cacheCreationTokens,\n );\n const usage: Usage = {\n provider: args.provider,\n model: args.model,\n transport: args.transport,\n inputTokens: args.inputTokens,\n outputTokens: args.outputTokens,\n cacheReadTokens,\n cacheCreationTokens,\n costUsd,\n latencyMs: 0,\n capability: args.capability,\n ts: \"\",\n };\n if (args.subprocess) usage.subprocess = true;\n return usage;\n}\n","// Anthropic adapter (F4.6) — the real one (F2.5 shipped only a stub). Two\n// transports: http (api.anthropic.com/v1/messages) and subprocess (claude -p,\n// Max plan, costUsd 0). Critical for the xrt81 vision pilot. Tools normalized\n// via F4.5. No @anthropic-ai/sdk package — plain fetch through httpTransport.\nimport { httpTransport } from \"../transport/http.js\";\nimport { subprocessTransport } from \"../transport/subprocess.js\";\nimport { streamTransport } from \"../transport/stream.js\";\nimport { toProviderTools, fromProviderToolCall } from \"./tools.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n ChatRequest,\n ChatResult,\n ChatStreamEvent,\n Message,\n ContentPart,\n ToolCall,\n} from \"../types.js\";\n\ninterface AnthropicBlock {\n type: string;\n text?: string;\n id?: string;\n name?: string;\n input?: Record<string, unknown>;\n}\ninterface AnthropicResponse {\n content?: AnthropicBlock[];\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n error?: unknown;\n}\n\nfunction contentBlocks(content: string | ContentPart[]): unknown {\n if (typeof content === \"string\") return content;\n return content.map((p) => {\n if (p.type === \"text\") return { type: \"text\", text: p.text };\n // Anthropic has no native video input — route video via a video-capable\n // provider (Gemini, F019) instead.\n if (p.type === \"video\") {\n throw new Error(\"anthropic adapter: video input is not supported — use a video provider (e.g. gemini)\");\n }\n if (typeof p.image === \"string\" && /^https?:\\/\\//.test(p.image)) {\n return { type: \"image\", source: { type: \"url\", url: p.image } };\n }\n const data =\n typeof p.image === \"string\"\n ? p.image.replace(/^data:[^;]+;base64,/, \"\")\n : Buffer.from(p.image).toString(\"base64\");\n return {\n type: \"image\",\n source: { type: \"base64\", media_type: p.mimeType ?? \"image/png\", data },\n };\n });\n}\n\n/** Flatten messages to a single prompt for the subprocess (claude -p) path. */\nfunction flattenForSubprocess(messages: Message[]): { prompt: string; system?: string } {\n const sys: string[] = [];\n const turns: string[] = [];\n for (const m of messages) {\n const text =\n typeof m.content === \"string\"\n ? m.content\n : m.content.map((p) => (p.type === \"text\" ? p.text : \"[image]\")).join(\" \");\n if (m.role === \"system\") sys.push(text);\n else turns.push(`${m.role}: ${text}`);\n }\n return { prompt: turns.join(\"\\n\\n\"), system: sys.length ? sys.join(\"\\n\") : undefined };\n}\n\nexport function anthropicAdapter(\n config: { apiKey?: string; baseUrl?: string; anthropicVersion?: string; fetch?: typeof fetch } = {},\n): ProviderAdapter {\n const baseUrl = config.baseUrl ?? \"https://api.anthropic.com\";\n const version = config.anthropicVersion ?? \"2023-06-01\";\n\n /** Build the /v1/messages body (shared by the http + stream paths). */\n function buildBody(req: ChatRequest): Record<string, unknown> {\n const system: string[] = [];\n const messages: { role: string; content: unknown }[] = [];\n for (const m of req.messages as Message[]) {\n if (m.role === \"system\") {\n system.push(typeof m.content === \"string\" ? m.content : \"\");\n continue;\n }\n // tool-result turn → a user message carrying a tool_result block (F8.7).\n if (m.role === \"tool\") {\n messages.push({\n role: \"user\",\n content: [\n {\n type: \"tool_result\",\n tool_use_id: m.toolCallId ?? \"\",\n content: typeof m.content === \"string\" ? m.content : \"\",\n },\n ],\n });\n continue;\n }\n // assistant turn that called tools → text blocks + tool_use blocks (F8.7).\n if (m.role === \"assistant\" && m.toolCalls && m.toolCalls.length > 0) {\n const blocks: unknown[] = [];\n if (typeof m.content === \"string\") {\n if (m.content.length > 0) blocks.push({ type: \"text\", text: m.content });\n } else {\n blocks.push(...(contentBlocks(m.content) as unknown[]));\n }\n for (const tc of m.toolCalls) {\n blocks.push({ type: \"tool_use\", id: tc.id, name: tc.name, input: tc.arguments });\n }\n messages.push({ role: \"assistant\", content: blocks });\n continue;\n }\n messages.push({ role: m.role === \"assistant\" ? \"assistant\" : \"user\", content: contentBlocks(m.content) });\n }\n const body: Record<string, unknown> = {\n model: req.spec.model,\n max_tokens: req.maxTokens ?? 1024, // Anthropic requires max_tokens\n messages,\n };\n if (system.length > 0) body.system = system.join(\"\\n\");\n if (req.tools) body.tools = toProviderTools(req.tools, \"anthropic\");\n if (req.temperature !== undefined) body.temperature = req.temperature;\n return body;\n }\n\n function apiKeyOrThrow(): string {\n const apiKey = config.apiKey ?? process.env.ANTHROPIC_API_KEY;\n if (!apiKey) throw new Error(\"anthropic adapter: API key not set (env ANTHROPIC_API_KEY)\");\n return apiKey;\n }\n\n async function chatHttp(req: ChatRequest): Promise<ChatResult> {\n const apiKey = apiKeyOrThrow();\n const body = buildBody(req);\n\n const res = await httpTransport({\n spec: req.spec,\n http: {\n url: `${baseUrl}/v1/messages`,\n headers: {\n \"content-type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": version,\n },\n body,\n },\n });\n if (!res.ok) throw new Error(`anthropic ${res.status}: ${JSON.stringify(res.json).slice(0, 300)}`);\n\n const data = res.json as AnthropicResponse;\n const blocks = data.content ?? [];\n const text = blocks\n .filter((b) => b.type === \"text\" && typeof b.text === \"string\")\n .map((b) => b.text)\n .join(\"\");\n const toolCalls: ToolCall[] = blocks\n .filter((b) => b.type === \"tool_use\")\n .map((b) => fromProviderToolCall(b, \"anthropic\"));\n\n const usage = freshUsage({\n provider: \"anthropic\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"chat\",\n inputTokens: data.usage?.input_tokens ?? 0,\n outputTokens: data.usage?.output_tokens ?? 0,\n cacheReadTokens: data.usage?.cache_read_input_tokens ?? 0,\n cacheCreationTokens: data.usage?.cache_creation_input_tokens ?? 0,\n });\n const result: ChatResult = { text, usage };\n if (toolCalls.length > 0) result.toolCalls = toolCalls;\n return result;\n }\n\n async function chatSubprocess(req: ChatRequest): Promise<ChatResult> {\n const { prompt, system } = flattenForSubprocess(req.messages as Message[]);\n const r = await subprocessTransport({ spec: req.spec, subprocess: { prompt, systemPrompt: system } });\n const usage = freshUsage({\n provider: \"anthropic\",\n model: req.spec.model,\n transport: \"subprocess\",\n capability: \"chat\",\n inputTokens: r.inputTokens,\n outputTokens: r.outputTokens,\n cacheReadTokens: r.cacheReadTokens,\n cacheCreationTokens: r.cacheCreationTokens,\n subprocess: true,\n });\n return { text: r.text, usage };\n }\n\n async function chat(req: ChatRequest): Promise<ChatResult> {\n return req.spec.transport === \"subprocess\" ? chatSubprocess(req) : chatHttp(req);\n }\n\n // Streaming chat (F8.4) over the native /v1/messages SSE. Maps\n // content_block_delta(text_delta) → text events, accumulates tool_use blocks\n // (id/name from content_block_start, input from input_json_delta) → complete\n // tool_call events, and reads usage from message_start + message_delta. Only\n // the http transport streams — `claude -p` subprocess is one-shot.\n async function* chatStream(req: ChatRequest): AsyncIterable<ChatStreamEvent> {\n if (req.spec.transport === \"subprocess\") {\n throw new Error(\"anthropic adapter: streaming is not supported over the subprocess transport\");\n }\n const apiKey = apiKeyOrThrow();\n const body = { ...buildBody(req), stream: true };\n const stream = streamTransport({\n spec: req.spec,\n fetch: config.fetch,\n http: {\n url: `${baseUrl}/v1/messages`,\n headers: {\n \"content-type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": version,\n },\n body,\n },\n });\n\n let inputTokens = 0;\n let outputTokens = 0;\n let cacheReadTokens = 0;\n let cacheCreationTokens = 0;\n let stopReason: string | null = null;\n // index → accumulated tool_use block (input_json_delta fragments concatenated).\n const toolBlocks = new Map<number, { id: string; name: string; json: string }>();\n\n for await (const data of stream) {\n let ev: AnthropicStreamEvent;\n try {\n ev = JSON.parse(data) as AnthropicStreamEvent;\n } catch {\n continue;\n }\n switch (ev.type) {\n case \"message_start\": {\n const u = ev.message?.usage;\n inputTokens = u?.input_tokens ?? 0;\n cacheReadTokens = u?.cache_read_input_tokens ?? 0;\n cacheCreationTokens = u?.cache_creation_input_tokens ?? 0;\n break;\n }\n case \"content_block_start\": {\n if (ev.content_block?.type === \"tool_use\" && ev.index !== undefined) {\n toolBlocks.set(ev.index, {\n id: ev.content_block.id ?? \"\",\n name: ev.content_block.name ?? \"\",\n json: \"\",\n });\n }\n break;\n }\n case \"content_block_delta\": {\n const d = ev.delta;\n if (d?.type === \"text_delta\" && d.text) {\n yield { type: \"text\", delta: d.text };\n } else if (d?.type === \"input_json_delta\" && d.partial_json && ev.index !== undefined) {\n const b = toolBlocks.get(ev.index);\n if (b) b.json += d.partial_json;\n }\n break;\n }\n case \"message_delta\": {\n if (ev.delta?.stop_reason) stopReason = ev.delta.stop_reason;\n if (ev.usage?.output_tokens !== undefined) outputTokens = ev.usage.output_tokens;\n break;\n }\n default:\n break; // content_block_stop / message_stop / ping\n }\n }\n\n for (const [, b] of [...toolBlocks.entries()].sort((a, c) => a[0] - c[0])) {\n let args: Record<string, unknown> = {};\n try {\n args = b.json ? (JSON.parse(b.json) as Record<string, unknown>) : {};\n } catch {\n args = {};\n }\n yield { type: \"tool_call\", id: b.id, name: b.name, args };\n }\n const usage = freshUsage({\n provider: \"anthropic\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"chat\",\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheCreationTokens,\n });\n yield { type: \"usage\", costUsd: usage.costUsd, model: usage.model, usage };\n yield { type: \"finish\", reason: mapAnthropicStop(stopReason) };\n }\n\n return { name: \"anthropic\", chat, chatStream, vision: chat };\n}\n\n/** Anthropic Messages SSE event (only the fields we read). */\ninterface AnthropicStreamEvent {\n type: string;\n index?: number;\n message?: {\n usage?: {\n input_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n };\n content_block?: { type?: string; id?: string; name?: string };\n delta?: { type?: string; text?: string; partial_json?: string; stop_reason?: string };\n usage?: { output_tokens?: number };\n}\n\n/** Map Anthropic stop_reason → the SDK's ChatStreamEvent finish reason. */\nfunction mapAnthropicStop(reason: string | null): \"end_turn\" | \"tool_calls\" | \"length\" | \"stop\" {\n switch (reason) {\n case \"tool_use\":\n return \"tool_calls\";\n case \"max_tokens\":\n return \"length\";\n case \"stop_sequence\":\n return \"stop\";\n default:\n return \"end_turn\";\n }\n}\n","// Shared core for OpenAI-compatible chat APIs. OpenAI (F4.1), DeepInfra (F4.3)\n// and OpenRouter (F4.4) all speak this wire format — only base URL, key and a\n// couple of headers differ. The adapter uses httpTransport (F2.4) for the wire\n// I/O and the F4.5 tool contract for tool round-tripping.\nimport { httpTransport } from \"../transport/http.js\";\nimport { streamTransport } from \"../transport/stream.js\";\nimport { toProviderTools, fromProviderToolCall } from \"./tools.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n ChatRequest,\n ChatResult,\n ChatStreamEvent,\n Message,\n ToolCall,\n} from \"../types.js\";\n\nexport interface OpenAICompatibleConfig {\n /** Provider name recorded on Usage (e.g. \"openai\", \"deepinfra\", \"openrouter\"). */\n name: string;\n /** Chat completions base, e.g. \"https://api.openai.com/v1\". */\n baseUrl: string;\n /** Resolved at call time if omitted (env var per provider). */\n apiKey?: string;\n /** Extra headers (e.g. OpenRouter's HTTP-Referer / X-Title). */\n extraHeaders?: Record<string, string>;\n /** Injectable fetch for the streaming path (tests). */\n fetch?: typeof fetch;\n /** OpenRouter ground-truth cost (F010): send `usage:{include:true}` and use the\n * response's `usage.cost` (USD) as costUsd, falling back to the pricing table.\n * Only OpenRouter returns this field — openai/deepinfra leave it false. */\n costFromResponseField?: boolean;\n}\n\ninterface OAToolCall {\n id?: string;\n function?: { name?: string; arguments?: string };\n}\ninterface OAResponse {\n choices?: { message?: { content?: string | null; tool_calls?: OAToolCall[] } }[];\n usage?: { prompt_tokens?: number; completion_tokens?: number; cost?: number };\n error?: unknown;\n}\n\n/** SDK message → OpenAI message (string content, or multimodal parts for vision).\n * Threads the normalized tool form to the wire: a `tool`-role message's\n * `toolCallId` → `tool_call_id`, and an assistant message's `toolCalls` →\n * `tool_calls:[{id,type:'function',function:{name,arguments}}]` (F8.3) so a\n * multi-turn tool conversation round-trips. Exported for serialization tests. */\nexport function toOpenAIMessage(m: Message): Record<string, unknown> {\n if (typeof m.content === \"string\") {\n const base: Record<string, unknown> = { role: m.role, content: m.content };\n if (m.toolCallId) base.tool_call_id = m.toolCallId;\n if (m.toolCalls && m.toolCalls.length > 0) {\n base.tool_calls = m.toolCalls.map((tc) => ({\n id: tc.id,\n type: \"function\",\n function: { name: tc.name, arguments: JSON.stringify(tc.arguments) },\n }));\n }\n return base;\n }\n const content = m.content.map((p) => {\n if (p.type === \"text\") return { type: \"text\", text: p.text };\n if (p.type === \"video\") {\n // F019.3 — OpenRouter video models. `video_url` mirrors `image_url`;\n // VERIFIED live 2026-06-04 against gemma-4 + nvidia-nemotron (both described\n // a real 2MB clip sent inline as a base64 data-URL).\n const url =\n typeof p.video === \"string\"\n ? p.video\n : `data:${p.mimeType ?? \"video/mp4\"};base64,${Buffer.from(p.video).toString(\"base64\")}`;\n return { type: \"video_url\", video_url: { url } };\n }\n const url =\n typeof p.image === \"string\"\n ? p.image\n : `data:${p.mimeType ?? \"image/png\"};base64,${Buffer.from(p.image).toString(\"base64\")}`;\n return { type: \"image_url\", image_url: { url } };\n });\n return { role: m.role, content };\n}\n\nexport function makeOpenAICompatibleAdapter(config: OpenAICompatibleConfig): ProviderAdapter {\n async function chat(req: ChatRequest): Promise<ChatResult> {\n const apiKey = config.apiKey ?? process.env[`${config.name.toUpperCase()}_API_KEY`];\n if (!apiKey) {\n throw new Error(`${config.name} adapter: API key not set (env ${config.name.toUpperCase()}_API_KEY)`);\n }\n const body: Record<string, unknown> = {\n model: req.spec.model,\n messages: req.messages.map(toOpenAIMessage),\n };\n if (req.tools) body.tools = toProviderTools(req.tools, \"openai\");\n if (req.maxTokens !== undefined) body.max_tokens = req.maxTokens;\n if (req.temperature !== undefined) body.temperature = req.temperature;\n if (req.responseFormat === \"json\") body.response_format = { type: \"json_object\" };\n if (config.costFromResponseField) body.usage = { include: true };\n\n const res = await httpTransport({\n spec: req.spec,\n http: {\n url: `${config.baseUrl}/chat/completions`,\n headers: {\n \"content-type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...config.extraHeaders,\n },\n body,\n },\n });\n if (!res.ok) {\n throw new Error(`${config.name} ${res.status}: ${JSON.stringify(res.json).slice(0, 300)}`);\n }\n const data = res.json as OAResponse;\n const msg = data.choices?.[0]?.message;\n // Reasoning/multimodal models can return `content` as an array of blocks (or\n // null) instead of a plain string — coerce so callers always get a string\n // (was: `?? \"\"`, which left an array through → consumer `text.replace` crash).\n const text = contentToText(msg?.content);\n const toolCalls: ToolCall[] | undefined = msg?.tool_calls?.map((tc) =>\n fromProviderToolCall(tc, \"openai\"),\n );\n const usage = freshUsage({\n provider: config.name,\n model: req.spec.model,\n transport: \"http\",\n capability: \"chat\",\n inputTokens: data.usage?.prompt_tokens ?? 0,\n outputTokens: data.usage?.completion_tokens ?? 0,\n });\n if (config.costFromResponseField && typeof data.usage?.cost === \"number\") {\n usage.costUsd = data.usage.cost; // OpenRouter ground-truth beats the estimate\n }\n const result: ChatResult = { text, usage };\n if (toolCalls && toolCalls.length > 0) result.toolCalls = toolCalls;\n return result;\n }\n\n // Streaming chat (F8.2). Parses the OpenAI chat.completions SSE: content\n // deltas → text events, tool_calls deltas accumulated (index-keyed, arguments\n // string concatenated) → complete tool_call events at end, the include_usage\n // chunk → a usage event, finish_reason → the terminal finish (emitted last so\n // tool_calls + usage precede it).\n async function* chatStream(req: ChatRequest): AsyncIterable<ChatStreamEvent> {\n const apiKey = config.apiKey ?? process.env[`${config.name.toUpperCase()}_API_KEY`];\n if (!apiKey) {\n throw new Error(`${config.name} adapter: API key not set (env ${config.name.toUpperCase()}_API_KEY)`);\n }\n const body: Record<string, unknown> = {\n model: req.spec.model,\n messages: req.messages.map(toOpenAIMessage),\n stream: true,\n stream_options: { include_usage: true },\n };\n if (req.tools) body.tools = toProviderTools(req.tools, \"openai\");\n if (req.maxTokens !== undefined) body.max_tokens = req.maxTokens;\n if (req.temperature !== undefined) body.temperature = req.temperature;\n if (req.responseFormat === \"json\") body.response_format = { type: \"json_object\" };\n if (config.costFromResponseField) body.usage = { include: true };\n\n const stream = streamTransport({\n spec: req.spec,\n fetch: config.fetch,\n http: {\n url: `${config.baseUrl}/chat/completions`,\n headers: {\n \"content-type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...config.extraHeaders,\n },\n body,\n },\n });\n\n // index → accumulated tool call (id/name set once, arguments concatenated).\n const toolAcc = new Map<number, { id: string; name: string; args: string }>();\n let finishReason: string | null = null;\n\n for await (const data of stream) {\n let chunk: OAStreamChunk;\n try {\n chunk = JSON.parse(data) as OAStreamChunk;\n } catch {\n continue; // ignore unparseable keep-alive noise\n }\n const choice = chunk.choices?.[0];\n if (choice) {\n const delta = choice.delta ?? {};\n if (typeof delta.content === \"string\" && delta.content.length > 0) {\n yield { type: \"text\", delta: delta.content };\n }\n for (const tc of delta.tool_calls ?? []) {\n const idx = tc.index ?? 0;\n const cur = toolAcc.get(idx) ?? { id: \"\", name: \"\", args: \"\" };\n if (tc.id) cur.id = tc.id;\n if (tc.function?.name) cur.name = tc.function.name;\n if (tc.function?.arguments) cur.args += tc.function.arguments;\n toolAcc.set(idx, cur);\n }\n if (choice.finish_reason) finishReason = choice.finish_reason;\n }\n if (chunk.usage) {\n const usage = freshUsage({\n provider: config.name,\n model: req.spec.model,\n transport: \"http\",\n capability: \"chat\",\n inputTokens: chunk.usage.prompt_tokens ?? 0,\n outputTokens: chunk.usage.completion_tokens ?? 0,\n });\n if (config.costFromResponseField && typeof chunk.usage.cost === \"number\") {\n usage.costUsd = chunk.usage.cost; // OpenRouter ground-truth\n }\n yield { type: \"usage\", costUsd: usage.costUsd, model: usage.model, usage };\n }\n }\n\n // Flush accumulated tool calls (complete), then the terminal finish.\n for (const [, t] of [...toolAcc.entries()].sort((a, b) => a[0] - b[0])) {\n let args: Record<string, unknown> = {};\n try {\n args = t.args ? (JSON.parse(t.args) as Record<string, unknown>) : {};\n } catch {\n args = {};\n }\n yield { type: \"tool_call\", id: t.id, name: t.name, args };\n }\n yield { type: \"finish\", reason: mapFinishReason(finishReason) };\n }\n\n return {\n name: config.name,\n chat,\n chatStream,\n // gpt-4o-class models are multimodal — vision shares the chat path.\n vision: chat,\n };\n}\n\n/** OpenAI streaming chunk shape (only the fields we read). */\ninterface OAStreamChunk {\n choices?: {\n delta?: {\n content?: string | null;\n tool_calls?: { index?: number; id?: string; function?: { name?: string; arguments?: string } }[];\n };\n finish_reason?: string | null;\n }[];\n usage?: { prompt_tokens?: number; completion_tokens?: number; cost?: number };\n}\n\n/** Coerce an OpenAI `message.content` to a string. Most providers return a string,\n * but reasoning/multimodal models can return an array of content blocks (or null). */\nfunction contentToText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return content\n .map((p) => {\n if (typeof p === \"string\") return p;\n const t = (p as { text?: unknown } | null)?.text;\n return typeof t === \"string\" ? t : \"\";\n })\n .join(\"\");\n }\n return \"\";\n}\n\n/** Map OpenAI finish_reason → the SDK's ChatStreamEvent finish reason. */\nfunction mapFinishReason(reason: string | null): \"end_turn\" | \"tool_calls\" | \"length\" | \"stop\" {\n switch (reason) {\n case \"tool_calls\":\n return \"tool_calls\";\n case \"length\":\n return \"length\";\n case \"stop\":\n return \"stop\";\n default:\n return \"end_turn\";\n }\n}\n","// OpenAI adapter (F4.1 chat/vision + F5.4 embedding). Chat/vision come from the\n// shared OpenAI-compatible core; embedding uses the /embeddings endpoint. No\n// openai npm package — plain fetch through httpTransport.\nimport { makeOpenAICompatibleAdapter } from \"./openai-compatible.js\";\nimport { httpTransport } from \"../transport/http.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n EmbeddingRequest,\n EmbeddingResult,\n TranscribeRequest,\n TranscribeResult,\n} from \"../types.js\";\n\n/** Whisper-family per-minute USD prices (audio is not token-priced). */\nconst WHISPER_PRICE_PER_MIN: Record<string, number> = {\n \"whisper-1\": 0.006,\n};\n\nexport function openaiAdapter(\n config: { apiKey?: string; baseUrl?: string; fetch?: typeof fetch } = {},\n): ProviderAdapter {\n const baseUrl = config.baseUrl ?? \"https://api.openai.com/v1\";\n const base = makeOpenAICompatibleAdapter({ name: \"openai\", baseUrl, apiKey: config.apiKey });\n\n async function embedding(req: EmbeddingRequest): Promise<EmbeddingResult> {\n const apiKey = config.apiKey ?? process.env.OPENAI_API_KEY;\n if (!apiKey) throw new Error(\"openai adapter: API key not set (env OPENAI_API_KEY)\");\n const res = await httpTransport({\n spec: req.spec,\n http: {\n url: `${baseUrl}/embeddings`,\n headers: { \"content-type\": \"application/json\", Authorization: `Bearer ${apiKey}` },\n body: { model: req.spec.model, input: req.input },\n },\n });\n if (!res.ok) {\n throw new Error(`openai ${res.status}: ${JSON.stringify(res.json).slice(0, 300)}`);\n }\n const data = res.json as {\n data?: { embedding: number[] }[];\n usage?: { prompt_tokens?: number };\n };\n const vectors = (data.data ?? []).map((d) => d.embedding);\n const usage = freshUsage({\n provider: \"openai\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"embedding\",\n inputTokens: data.usage?.prompt_tokens ?? 0,\n outputTokens: 0,\n });\n return { vectors, usage };\n }\n\n async function transcribe(req: TranscribeRequest): Promise<TranscribeResult> {\n const apiKey = config.apiKey ?? process.env.OPENAI_API_KEY;\n if (!apiKey) throw new Error(\"openai adapter: API key not set (env OPENAI_API_KEY)\");\n // Whisper is multipart/form-data — bypass httpTransport (JSON-only). Don't set\n // content-type; fetch adds the multipart boundary.\n const form = new FormData();\n form.append(\"file\", new Blob([req.audio]), \"audio\");\n form.append(\"model\", req.spec.model);\n if (req.language) form.append(\"language\", req.language);\n const fetchImpl = config.fetch ?? fetch;\n const res = await fetchImpl(`${baseUrl}/audio/transcriptions`, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${apiKey}` },\n body: form,\n });\n if (!res.ok) {\n throw new Error(`openai ${res.status}: ${(await res.text().catch(() => \"\")).slice(0, 200)}`);\n }\n const data = (await res.json()) as { text?: string };\n const usage = freshUsage({\n provider: \"openai\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"transcribe\",\n inputTokens: 0,\n outputTokens: 0, // Whisper is per-minute, not token-priced.\n });\n // Per-minute cost when the caller supplies the audio duration (API returns none).\n if (req.durationSec !== undefined) {\n const perMinute = WHISPER_PRICE_PER_MIN[req.spec.model] ?? 0;\n usage.costUsd = (req.durationSec / 60) * perMinute;\n }\n return { text: data.text ?? \"\", usage };\n }\n\n return { ...base, embedding, transcribe };\n}\n","// Shared image-input helpers (F031). Extracted from gemini.ts once a second\n// provider (vertex.ts) needed the exact same URL/bytes/data-URI → inline\n// base64+mime resolution for Veo's `image:{bytesBase64Encoded, mimeType}` field.\n\n/** Resolve an image input to { data(base64), mimeType } — a URL is fetched to bytes. */\nexport async function toInlineImage(\n image: string | Uint8Array,\n fetchImpl: typeof fetch,\n): Promise<{ data: string; mimeType: string }> {\n if (typeof image !== \"string\") {\n return { data: Buffer.from(image).toString(\"base64\"), mimeType: sniffMime(image) };\n }\n if (/^https?:\\/\\//i.test(image)) {\n const res = await fetchImpl(image);\n if (!res.ok) throw new Error(`toInlineImage: failed to fetch image (${res.status})`);\n const bytes = new Uint8Array(await res.arrayBuffer());\n const mimeType = res.headers.get(\"content-type\") ?? sniffMime(bytes);\n return { data: Buffer.from(bytes).toString(\"base64\"), mimeType };\n }\n // A data: URI or bare base64.\n const comma = image.startsWith(\"data:\") ? image.indexOf(\",\") : -1;\n const b64 = comma >= 0 ? image.slice(comma + 1) : image;\n const mimeType = image.startsWith(\"data:\") ? image.slice(5, image.indexOf(\";\")) : \"image/png\";\n return { data: b64, mimeType };\n}\n\nexport function sniffMime(b: Uint8Array): string {\n if (b[0] === 0x89 && b[1] === 0x50) return \"image/png\";\n if (b[0] === 0x47 && b[1] === 0x49) return \"image/gif\";\n if (b[0] === 0x52 && b[1] === 0x49 && b[8] === 0x57) return \"image/webp\";\n return \"image/jpeg\";\n}\n","// Google Gemini adapter (F4.2). generateContent REST API; API key in the query\n// param (?key=), not a header. System turns map to systemInstruction; assistant\n// maps to role \"model\". Token counts come from usageMetadata. Tools normalized\n// via F4.5. No @google/generative-ai package — plain fetch through httpTransport.\nimport { httpTransport } from \"../transport/http.js\";\nimport { streamTransport } from \"../transport/stream.js\";\nimport { toProviderTools, fromProviderToolCall } from \"./tools.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport { toInlineImage } from \"./media.js\";\nimport type {\n ProviderAdapter,\n ChatRequest,\n ChatResult,\n ChatStreamEvent,\n ImageRequest,\n ImageResult,\n AnimateRequest,\n AnimateResult,\n Message,\n ContentPart,\n ToolCall,\n} from \"../types.js\";\n\n/** Per-image USD price for Gemini image-gen models (generateContent image output\n * is billed per image). Official ai.google.dev/gemini-api/docs/pricing, standard\n * paid tier, at the 1K/1024px output size (Google's per-image price rises with\n * resolution — 2K/4K cost more; we record the common 1K default). Overridable\n * per call via geminiAdapter config.pricePerImage. */\nconst GEMINI_IMAGE_PRICE_PER_IMAGE: Record<string, number> = {\n \"gemini-2.5-flash-image\": 0.039, // \"nano-banana\" — 1024px = 1290 tok\n \"gemini-3.1-flash-image\": 0.067, // 1K=$0.067, 2K=$0.101, 4K=$0.151\n \"gemini-3.1-flash-image-preview\": 0.067,\n \"gemini-3-pro-image\": 0.134, // premium — 1K/2K=$0.134, 4K=$0.24\n \"gemini-3-pro-image-preview\": 0.134, // was $0.039 — wrong (that's the flash price); pro is $0.134\n};\n\ninterface GeminiPart {\n text?: string;\n functionCall?: { name: string; args: Record<string, unknown> };\n inlineData?: { mimeType: string; data: string };\n}\ninterface GeminiResponse {\n candidates?: { content?: { parts?: GeminiPart[] } }[];\n usageMetadata?: { promptTokenCount?: number; candidatesTokenCount?: number };\n error?: unknown;\n}\n\nfunction partsFrom(content: string | ContentPart[]): GeminiPart[] {\n if (typeof content === \"string\") return [{ text: content }];\n return content.map((p): GeminiPart => {\n if (p.type === \"text\") return { text: p.text };\n // Video (F019) and image both go inline as base64 — Gemini accepts video mime\n // types natively. (Clips over ~20MB need the Files API — not handled here.)\n if (p.type === \"video\") {\n const data =\n typeof p.video === \"string\"\n ? p.video.replace(/^data:[^;]+;base64,/, \"\")\n : Buffer.from(p.video).toString(\"base64\");\n return { inlineData: { mimeType: p.mimeType ?? \"video/mp4\", data } };\n }\n const data =\n typeof p.image === \"string\"\n ? p.image.replace(/^data:[^;]+;base64,/, \"\")\n : Buffer.from(p.image).toString(\"base64\");\n return { inlineData: { mimeType: p.mimeType ?? \"image/png\", data } };\n });\n}\n\n/** Per-SECOND USD for Veo video models (F024). Official ai.google.dev/gemini-api/\n * docs/pricing (2026-06, \"video with audio\", 720p/1080p default; 4K costs more).\n * Override per call via config.pricePerSecond. Unknown model → 0 (never fabricated). */\nconst VEO_PRICE_PER_SEC: Record<string, number> = {\n \"veo-3.1-generate-preview\": 0.4, // standard; 4K = 0.60\n \"veo-3.1-fast-generate-preview\": 0.1, // 720p; 1080p = 0.12, 4K = 0.30\n \"veo-3.1-lite-generate-preview\": 0.05, // 720p; 1080p = 0.08\n \"veo-3.0-generate-001\": 0.4,\n \"veo-3.0-fast-generate-001\": 0.1,\n};\n\nexport function geminiAdapter(\n config: {\n apiKey?: string;\n baseUrl?: string;\n fetch?: typeof fetch;\n pricePerImage?: number;\n /** Override the per-SECOND Veo video price (else estimate per model, 0 if unknown). */\n pricePerSecond?: number;\n /** Poll interval for Veo long-running operations (default 5s). */\n pollIntervalMs?: number;\n /** Deadline for a Veo job (default 300000 = 5 min). */\n videoTimeoutMs?: number;\n } = {},\n): ProviderAdapter {\n const baseUrl = config.baseUrl ?? \"https://generativelanguage.googleapis.com/v1beta\";\n\n function resolveKey(): string {\n const apiKey = config.apiKey ?? process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY;\n if (!apiKey) throw new Error(\"gemini adapter: API key not set (env GOOGLE_API_KEY)\");\n return apiKey;\n }\n\n /** Build the generateContent body (shared by the http + stream paths). */\n function buildBody(req: ChatRequest): Record<string, unknown> {\n const systemParts: GeminiPart[] = [];\n const contents: { role: string; parts: GeminiPart[] }[] = [];\n for (const m of req.messages as Message[]) {\n if (m.role === \"system\") {\n systemParts.push(...partsFrom(m.content));\n } else {\n contents.push({\n role: m.role === \"assistant\" ? \"model\" : \"user\",\n parts: partsFrom(m.content),\n });\n }\n }\n const body: Record<string, unknown> = { contents };\n if (systemParts.length > 0) body.systemInstruction = { parts: systemParts };\n if (req.tools) body.tools = toProviderTools(req.tools, \"gemini\");\n const genConfig: Record<string, unknown> = {};\n if (req.maxTokens !== undefined) genConfig.maxOutputTokens = req.maxTokens;\n if (req.temperature !== undefined) genConfig.temperature = req.temperature;\n if (Object.keys(genConfig).length > 0) body.generationConfig = genConfig;\n return body;\n }\n\n async function chat(req: ChatRequest): Promise<ChatResult> {\n const apiKey = resolveKey();\n const body = buildBody(req);\n\n const res = await httpTransport({\n spec: req.spec,\n http: {\n url: `${baseUrl}/models/${req.spec.model}:generateContent?key=${encodeURIComponent(apiKey)}`,\n headers: { \"content-type\": \"application/json\" },\n body,\n },\n });\n if (!res.ok) {\n throw new Error(`gemini ${res.status}: ${JSON.stringify(res.json).slice(0, 300)}`);\n }\n const data = res.json as GeminiResponse;\n const parts = data.candidates?.[0]?.content?.parts ?? [];\n const text = parts\n .filter((p) => typeof p.text === \"string\")\n .map((p) => p.text)\n .join(\"\");\n const toolCalls: ToolCall[] = parts\n .filter((p) => p.functionCall)\n .map((p) => fromProviderToolCall({ functionCall: p.functionCall }, \"gemini\"));\n\n const usage = freshUsage({\n provider: \"gemini\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"chat\",\n inputTokens: data.usageMetadata?.promptTokenCount ?? 0,\n outputTokens: data.usageMetadata?.candidatesTokenCount ?? 0,\n });\n const result: ChatResult = { text, usage };\n if (toolCalls.length > 0) result.toolCalls = toolCalls;\n return result;\n }\n\n // Streaming chat (F8.6) over streamGenerateContent?alt=sse. Each SSE chunk is\n // a partial GenerateContentResponse: parts[].text → text events, parts[].\n // functionCall → complete tool_call events (gemini sends each call whole), and\n // the final usageMetadata → a usage event. finishReason maps the terminal.\n async function* chatStream(req: ChatRequest): AsyncIterable<ChatStreamEvent> {\n const apiKey = resolveKey();\n const body = buildBody(req);\n const stream = streamTransport({\n spec: req.spec,\n fetch: config.fetch,\n http: {\n url: `${baseUrl}/models/${req.spec.model}:streamGenerateContent?alt=sse&key=${encodeURIComponent(apiKey)}`,\n headers: { \"content-type\": \"application/json\" },\n body,\n },\n });\n\n const toolCalls: ToolCall[] = [];\n let inputTokens = 0;\n let outputTokens = 0;\n let finishReason: string | null = null;\n\n for await (const data of stream) {\n let chunk: GeminiResponse & { candidates?: { finishReason?: string }[] };\n try {\n chunk = JSON.parse(data) as typeof chunk;\n } catch {\n continue;\n }\n const candidate = chunk.candidates?.[0];\n for (const p of candidate?.content?.parts ?? []) {\n if (typeof p.text === \"string\" && p.text.length > 0) {\n yield { type: \"text\", delta: p.text };\n } else if (p.functionCall) {\n toolCalls.push(fromProviderToolCall({ functionCall: p.functionCall }, \"gemini\"));\n }\n }\n if (candidate?.finishReason) finishReason = candidate.finishReason;\n if (chunk.usageMetadata) {\n inputTokens = chunk.usageMetadata.promptTokenCount ?? inputTokens;\n outputTokens = chunk.usageMetadata.candidatesTokenCount ?? outputTokens;\n }\n }\n\n for (const tc of toolCalls) {\n yield { type: \"tool_call\", id: tc.id, name: tc.name, args: tc.arguments };\n }\n const usage = freshUsage({\n provider: \"gemini\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"chat\",\n inputTokens,\n outputTokens,\n });\n yield { type: \"usage\", costUsd: usage.costUsd, model: usage.model, usage };\n yield {\n type: \"finish\",\n reason: toolCalls.length > 0 ? \"tool_calls\" : mapGeminiFinish(finishReason),\n };\n }\n\n // Image generation (F013) via generateContent with IMAGE response modality.\n // Gemini returns the image inline as base64 (not a hosted URL like fal), so we\n // hand it back as a data: URL. Built to match cms's nano-banana request.\n async function image(req: ImageRequest): Promise<ImageResult> {\n const apiKey = resolveKey();\n // Direct fetch (injectable for tests) — generateContent is JSON in/out but\n // we read inline image bytes, so we don't route through httpTransport here.\n const fetchImpl = config.fetch ?? fetch;\n const res = await fetchImpl(`${baseUrl}/models/${req.spec.model}:generateContent?key=${encodeURIComponent(apiKey)}`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n contents: [{ role: \"user\", parts: [{ text: req.prompt }] }],\n // The multimodal image model can return text + image; ask for both.\n generationConfig: { responseModalities: [\"TEXT\", \"IMAGE\"] },\n }),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`gemini image ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as GeminiResponse & {\n candidates?: { content?: { parts?: GeminiImagePart[] } }[];\n promptFeedback?: { blockReason?: string };\n };\n if (data.promptFeedback?.blockReason) {\n throw new Error(`gemini image blocked: ${data.promptFeedback.blockReason}`);\n }\n let url: string | undefined;\n for (const p of data.candidates?.[0]?.content?.parts ?? []) {\n // Some responses use camelCase inlineData, others snake_case inline_data.\n const inline = p.inlineData ?? p.inline_data;\n const mime = inline?.mimeType ?? inline?.mime_type;\n const b64 = inline?.data;\n if (mime && b64) {\n url = `data:${mime};base64,${b64}`;\n break;\n }\n }\n if (!url) throw new Error(\"gemini image: response contained no inline image data\");\n const usage = freshUsage({\n provider: \"gemini\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"image\",\n inputTokens: data.usageMetadata?.promptTokenCount ?? 0,\n outputTokens: data.usageMetadata?.candidatesTokenCount ?? 0,\n });\n usage.costUsd = config.pricePerImage ?? GEMINI_IMAGE_PRICE_PER_IMAGE[req.spec.model] ?? 0;\n return { url, usage };\n }\n\n // Image-to-video (F024) via Veo on the Gemini API — :predictLongRunning. Submit\n // returns an operation; poll until done; the result is an auth-gated file URI, so\n // we download the bytes with the key and hand them back (the URI alone needs auth).\n async function animate(req: AnimateRequest): Promise<AnimateResult> {\n const apiKey = resolveKey();\n const fetchImpl = config.fetch ?? fetch;\n const pollIntervalMs = config.pollIntervalMs ?? 5000;\n const deadline = Date.now() + (config.videoTimeoutMs ?? 300000);\n\n // Input image → inline base64 + mime (URL is fetched to bytes first).\n const { data, mimeType } = await toInlineImage(req.image, fetchImpl);\n const parameters: Record<string, unknown> = {};\n // durationSeconds must be a NUMBER (the API rejects a string, despite some docs).\n if (req.durationSec !== undefined) parameters.durationSeconds = req.durationSec;\n if (req.resolution !== undefined) parameters.resolution = req.resolution;\n // Veo's predict image field is bytesBase64Encoded + mimeType (NOT generateContent's\n // inlineData — the API rejects that: \"inlineData isn't supported by this model\").\n const body = {\n instances: [{ prompt: req.prompt ?? \"\", image: { bytesBase64Encoded: data, mimeType } }],\n ...(Object.keys(parameters).length ? { parameters } : {}),\n };\n\n const submit = await fetchImpl(\n `${baseUrl}/models/${req.spec.model}:predictLongRunning?key=${encodeURIComponent(apiKey)}`,\n { method: \"POST\", headers: { \"content-type\": \"application/json\" }, body: JSON.stringify(body) },\n );\n if (!submit.ok) {\n throw new Error(`gemini animate ${submit.status}: ${(await submit.text().catch(() => \"\")).slice(0, 300)}`);\n }\n const op = (await submit.json()) as { name?: string };\n if (!op.name) throw new Error(\"gemini animate: no operation name in submit response\");\n\n // Poll the operation until done.\n let videoUri: string | undefined;\n for (;;) {\n const poll = await fetchImpl(`${baseUrl}/${op.name}?key=${encodeURIComponent(apiKey)}`, {\n headers: { \"content-type\": \"application/json\" },\n });\n if (!poll.ok) throw new Error(`gemini animate poll ${poll.status}`);\n const opData = (await poll.json()) as VeoOperation;\n if (opData.error) throw new Error(`gemini animate: ${opData.error.message ?? \"operation error\"}`);\n if (opData.done) {\n videoUri = opData.response?.generateVideoResponse?.generatedSamples?.[0]?.video?.uri;\n if (!videoUri) throw new Error(`gemini animate: done but no video uri: ${JSON.stringify(opData.response).slice(0, 300)}`);\n break;\n }\n if (Date.now() >= deadline) throw new Error(\"gemini animate: timed out\");\n await new Promise((r) => setTimeout(r, pollIntervalMs));\n }\n\n // Download the bytes (the URI is auth-gated + short-lived).\n const dl = await fetchImpl(videoUri.includes(\"key=\") ? videoUri : `${videoUri}${videoUri.includes(\"?\") ? \"&\" : \"?\"}key=${encodeURIComponent(apiKey)}`);\n if (!dl.ok) throw new Error(`gemini animate download ${dl.status}`);\n const bytes = new Uint8Array(await dl.arrayBuffer());\n\n const usage = freshUsage({\n provider: \"gemini\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"animate\",\n inputTokens: 0,\n outputTokens: 0,\n });\n const perSec = config.pricePerSecond ?? VEO_PRICE_PER_SEC[req.spec.model] ?? 0;\n usage.costUsd = perSec * (req.durationSec ?? 8);\n return { url: videoUri, bytes, mimeType: \"video/mp4\", usage };\n }\n\n return { name: \"gemini\", chat, chatStream, image, animate, vision: chat };\n}\n\n/** A Veo predictLongRunning operation result shape. */\ninterface VeoOperation {\n done?: boolean;\n error?: { message?: string };\n response?: {\n generateVideoResponse?: {\n generatedSamples?: { video?: { uri?: string } }[];\n };\n };\n}\n\n/** Image part shape on a generateContent response (camel + snake aliases). */\ninterface GeminiInline {\n mimeType?: string;\n mime_type?: string;\n data?: string;\n}\ninterface GeminiImagePart {\n text?: string;\n inlineData?: GeminiInline;\n inline_data?: GeminiInline;\n}\n\n/** Map Gemini finishReason → the SDK's ChatStreamEvent finish reason. */\nfunction mapGeminiFinish(reason: string | null): \"end_turn\" | \"tool_calls\" | \"length\" | \"stop\" {\n switch (reason) {\n case \"MAX_TOKENS\":\n return \"length\";\n case \"STOP\":\n return \"end_turn\";\n default:\n return reason ? \"stop\" : \"end_turn\";\n }\n}\n","// DeepInfra adapter (F4.3). DeepInfra exposes an OpenAI-compatible endpoint, so\n// this is the shared core pointed at DeepInfra's base URL + key. No extra deps.\nimport { makeOpenAICompatibleAdapter } from \"./openai-compatible.js\";\nimport type { ProviderAdapter } from \"../types.js\";\n\nexport function deepinfraAdapter(\n config: { apiKey?: string; baseUrl?: string } = {},\n): ProviderAdapter {\n return makeOpenAICompatibleAdapter({\n name: \"deepinfra\",\n baseUrl: config.baseUrl ?? \"https://api.deepinfra.com/v1/openai\",\n apiKey: config.apiKey,\n });\n}\n","// OpenRouter adapter (F4.4). Meta-router with an OpenAI-compatible API — reuses\n// the shared core + OpenRouter's attribution headers. Any upstream model is\n// reachable by its slug, e.g. \"minimax/minimax-m2.7\", \"google/gemini-2.5-flash\".\nimport { makeOpenAICompatibleAdapter } from \"./openai-compatible.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type { ProviderAdapter, ImageRequest, ImageResult } from \"../types.js\";\n\n// F033.1 — OpenRouter's unified Image API (POST /images, distinct from\n// /chat/completions) returns base64 image data under data[].b64_json, plus a\n// ground-truth usage.cost (USD) like chat does. Vector/SVG output is the same\n// shape with data[].media_type = \"image/svg+xml\". A model/policy error can come\n// back as HTTP 200 with an empty data[] and a structured `error` — surfaced so\n// the caller sees the real cause, not a generic \"no image data\".\ninterface OpenRouterImageResponse {\n data?: { b64_json?: string; media_type?: string }[];\n usage?: { cost?: number };\n error?: { message?: string } | string;\n}\n\n// Per-image USD ESTIMATES — fallback for when OpenRouter's response omits\n// usage.cost. Verified 2026-07-03 against openrouter.ai/recraft/recraft-v4.1*\n// (override via config.pricePerImage).\nconst OPENROUTER_IMAGE_PRICE_ESTIMATE: Record<string, number> = {\n \"recraft/recraft-v4.1\": 0.035,\n \"recraft/recraft-v4.1-vector\": 0.08,\n};\n\nexport interface OpenRouterAdapterConfig {\n apiKey?: string;\n baseUrl?: string;\n referer?: string;\n title?: string;\n fetch?: typeof fetch;\n /** Override the per-image USD price (else OPENROUTER_IMAGE_PRICE_ESTIMATE, else 0). */\n pricePerImage?: number;\n}\n\nexport function openrouterAdapter(config: OpenRouterAdapterConfig = {}): ProviderAdapter {\n const baseUrl = config.baseUrl ?? \"https://openrouter.ai/api/v1\";\n const headers = {\n \"HTTP-Referer\": config.referer ?? \"https://broberg.ai\",\n \"X-Title\": config.title ?? \"@broberg/ai-sdk\",\n };\n const base = makeOpenAICompatibleAdapter({\n name: \"openrouter\",\n baseUrl,\n apiKey: config.apiKey,\n extraHeaders: headers,\n // Forward the injectable fetch so an override applies uniformly to\n // chat/chatStream/vision as well as the image() path below.\n fetch: config.fetch,\n // OpenRouter returns ground-truth usage.cost (USD) when usage:{include:true}\n // is set — use it over the local pricing-table estimate (F010).\n costFromResponseField: true,\n });\n\n async function image(req: ImageRequest): Promise<ImageResult> {\n const apiKey = config.apiKey ?? process.env.OPENROUTER_API_KEY;\n if (!apiKey) throw new Error(\"openrouter adapter: OPENROUTER_API_KEY not set\");\n const doFetch = config.fetch ?? fetch;\n\n const body: Record<string, unknown> = { model: req.spec.model, prompt: req.prompt };\n if (req.width !== undefined && req.height !== undefined) {\n body.size = `${req.width}x${req.height}`;\n }\n // OpenRouter's Image API takes top-level `seed` (reproducibility) and\n // `output_format` (png/jpeg/webp) — forward the ImageRequest fields the\n // rest of the SDK exposes (matches bfl.ts) instead of silently dropping them.\n if (req.seed !== undefined) body.seed = req.seed;\n if (req.outputFormat !== undefined) body.output_format = req.outputFormat;\n\n const res = await doFetch(`${baseUrl}/images`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...headers,\n },\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n throw new Error(`openrouter images ${res.status}: ${(await res.text().catch(() => \"\")).slice(0, 300)}`);\n }\n const data = (await res.json()) as OpenRouterImageResponse;\n const first = data.data?.[0];\n if (!first?.b64_json) {\n // A flagged/failed generation can arrive as 200 + empty data + an error\n // payload — surface it so a moderation block reads differently than a glitch.\n const errMsg = typeof data.error === \"string\" ? data.error : data.error?.message;\n throw new Error(`openrouter images: ${errMsg ?? \"no image data in response\"}`);\n }\n\n const usage = freshUsage({\n provider: \"openrouter\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"image\",\n inputTokens: 0,\n outputTokens: 0,\n });\n usage.costUsd =\n data.usage?.cost ?? config.pricePerImage ?? OPENROUTER_IMAGE_PRICE_ESTIMATE[req.spec.model] ?? 0;\n return { url: `data:${first.media_type ?? \"image/png\"};base64,${first.b64_json}`, usage };\n }\n\n return { ...base, image };\n}\n","// Requesty adapter (F028). An OpenAI-compatible AI gateway (400+ models, 30+\n// providers) — a drop-in alternative to the `openrouter` upstream. Reuses the\n// shared OpenAI-compatible core; only the base URL + key differ. Requesty returns\n// ground-truth `usage.cost`, so cost is exact (not a table estimate). Key from\n// REQUESTY_API_KEY. EU data-residency endpoint via `eu:true`.\n//\n// GDPR note: the EU endpoint keeps only Requesty's GATEWAY in the EU (Frankfurt).\n// End-to-end EU residency still requires an EU-region MODEL slug (Bedrock\n// `@eu-central-1`, Vertex `@eu`, Azure `@swedencentral`, Mistral EU-default) — a\n// global slug routes inference outside the EU despite the EU endpoint.\nimport { makeOpenAICompatibleAdapter } from \"./openai-compatible.js\";\nimport type { ProviderAdapter } from \"../types.js\";\n\nconst US_BASE = \"https://router.requesty.ai/v1\";\nconst EU_BASE = \"https://router.eu.requesty.ai/v1\";\n\nexport function requestyAdapter(\n config: { apiKey?: string; baseUrl?: string; eu?: boolean; referer?: string; title?: string } = {},\n): ProviderAdapter {\n return makeOpenAICompatibleAdapter({\n name: \"requesty\",\n baseUrl: config.baseUrl ?? (config.eu ? EU_BASE : US_BASE),\n apiKey: config.apiKey,\n extraHeaders: {\n \"HTTP-Referer\": config.referer ?? \"https://broberg.ai\",\n \"X-Title\": config.title ?? \"@broberg/ai-sdk\",\n },\n // Requesty returns ground-truth usage.cost (USD) by default — use it over the\n // local pricing-table estimate (same as OpenRouter, F010).\n costFromResponseField: true,\n });\n}\n","// DeepSeek adapter (F030) — the opt-in NON-PII secondary route for the Anthropic\n// phase-out. DeepSeek's direct API is OpenAI-compatible, so this reuses the shared\n// core; only base URL + key differ. Reached via `override:{ provider:\"deepseek\",\n// model:\"…\" }` — never a default tier. Key from DEEPSEEK_API_KEY.\n//\n// GDPR: DeepSeek is CN-hosted → NOT GDPR-safe. Use ONLY for non-PII workloads\n// (e.g. public web/article scanning). Personal data stays on Mistral EU.\n//\n// Models (direct api.deepseek.com): `deepseek-chat` (non-thinking) and\n// `deepseek-reasoner` (thinking) — both DEPRECATE 2026-07-24 and map to\n// `deepseek-v4-flash`. Prefer `deepseek-v4-flash` going forward (same model, not\n// sunset). The direct API does NOT return a cost field → cost comes from the\n// pricing table (verify rates against a real key; see src/cost/pricing.ts).\nimport { makeOpenAICompatibleAdapter } from \"./openai-compatible.js\";\nimport type { ProviderAdapter } from \"../types.js\";\n\nexport function deepseekAdapter(\n config: { apiKey?: string; baseUrl?: string } = {},\n): ProviderAdapter {\n return makeOpenAICompatibleAdapter({\n name: \"deepseek\", // → key DEEPSEEK_API_KEY\n baseUrl: config.baseUrl ?? \"https://api.deepseek.com/v1\",\n apiKey: config.apiKey,\n // Direct API returns no usage.cost → price from the table (not response).\n costFromResponseField: false,\n });\n}\n","// Mistral adapter. Mistral's La Plateforme exposes an OpenAI-compatible chat\n// endpoint (the shared core), plus two specialty endpoints we add here:\n// /ocr (F016.2, per-page) and /moderations (F016.4, per-token). Key resolved\n// from MISTRAL_API_KEY when not passed.\nimport { makeOpenAICompatibleAdapter } from \"./openai-compatible.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n OcrRequest,\n OcrResult,\n OcrPage,\n ModerationRequest,\n ModerationResult,\n ModerationItem,\n EmbeddingRequest,\n EmbeddingResult,\n TranscribeRequest,\n TranscribeResult,\n BatchRequestItem,\n BatchJob,\n BatchResultItem,\n TierSpec,\n} from \"../types.js\";\n\n/** Per-page USD for Mistral OCR ($2 / 1000 pages). Overridable via config. */\nconst MISTRAL_OCR_PRICE_PER_PAGE = 0.002;\n\n/** Per-minute USD for Voxtral transcription models (F016.3). */\nconst VOXTRAL_PRICE_PER_MIN: Record<string, number> = {\n \"voxtral-mini-latest\": 0.002,\n \"voxtral-mini-2507\": 0.002,\n \"voxtral-mini-2602\": 0.002,\n};\n\nexport function mistralAdapter(\n config: { apiKey?: string; baseUrl?: string; fetch?: typeof fetch; pricePerPage?: number } = {},\n): ProviderAdapter {\n const baseUrl = config.baseUrl ?? \"https://api.mistral.ai/v1\";\n const base = makeOpenAICompatibleAdapter({ name: \"mistral\", baseUrl, apiKey: config.apiKey });\n\n function key(): string {\n const k = config.apiKey ?? process.env.MISTRAL_API_KEY;\n if (!k) throw new Error(\"mistral adapter: API key not set (env MISTRAL_API_KEY)\");\n return k;\n }\n const fetchImpl = config.fetch ?? fetch;\n\n // OCR (F016.2) — POST /ocr. document is a URL/data-URL; image/* routes as an\n // image, anything else as a document (PDF etc.). Billed per page processed.\n async function ocr(req: OcrRequest): Promise<OcrResult> {\n const isImage = (req.mimeType ?? \"\").startsWith(\"image/\");\n const url =\n typeof req.document === \"string\"\n ? req.document\n : `data:${req.mimeType ?? \"application/pdf\"};base64,${Buffer.from(req.document).toString(\"base64\")}`;\n const document = isImage\n ? { type: \"image_url\", image_url: url }\n : { type: \"document_url\", document_url: url };\n\n const res = await fetchImpl(`${baseUrl}/ocr`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: `Bearer ${key()}` },\n body: JSON.stringify({ model: req.spec.model, document }),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`mistral ocr ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as {\n pages?: { index?: number; markdown?: string }[];\n usage_info?: { pages_processed?: number };\n };\n const pages: OcrPage[] = (data.pages ?? []).map((p, i) => ({\n index: p.index ?? i,\n markdown: p.markdown ?? \"\",\n }));\n const pagesProcessed = data.usage_info?.pages_processed ?? pages.length;\n const usage = freshUsage({\n provider: \"mistral\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"ocr\",\n inputTokens: 0,\n outputTokens: 0,\n });\n usage.costUsd = pagesProcessed * (config.pricePerPage ?? MISTRAL_OCR_PRICE_PER_PAGE);\n return { pages, usage };\n }\n\n // Moderation (F016.4) — POST /moderations. Returns per-input category booleans\n // + scores; `flagged` = any category true. Billed per input token (estimated\n // from input length when the API omits a usage count).\n async function moderate(req: ModerationRequest): Promise<ModerationResult> {\n const res = await fetchImpl(`${baseUrl}/moderations`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: `Bearer ${key()}` },\n body: JSON.stringify({ model: req.spec.model, input: req.input }),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`mistral moderation ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as {\n results?: { categories?: Record<string, boolean>; category_scores?: Record<string, number> }[];\n usage?: { prompt_tokens?: number };\n };\n const results: ModerationItem[] = (data.results ?? []).map((r) => {\n const categories = r.categories ?? {};\n return {\n flagged: Object.values(categories).some(Boolean),\n categories,\n categoryScores: r.category_scores ?? {},\n };\n });\n // The moderation endpoint usually omits token counts → estimate from input.\n const estIn = req.input.reduce((n, s) => n + Math.ceil(s.length / 4), 0);\n const usage = freshUsage({\n provider: \"mistral\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"moderation\",\n inputTokens: data.usage?.prompt_tokens ?? estIn,\n outputTokens: 0,\n });\n return { results, usage };\n }\n\n // Embeddings (F016.5) — POST /embeddings (OpenAI-compatible). Per-token input.\n async function embedding(req: EmbeddingRequest): Promise<EmbeddingResult> {\n const res = await fetchImpl(`${baseUrl}/embeddings`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: `Bearer ${key()}` },\n body: JSON.stringify({ model: req.spec.model, input: req.input }),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`mistral embeddings ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as {\n data?: { embedding: number[] }[];\n usage?: { prompt_tokens?: number; total_tokens?: number };\n };\n const vectors = (data.data ?? []).map((d) => d.embedding);\n const usage = freshUsage({\n provider: \"mistral\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"embedding\",\n inputTokens: data.usage?.prompt_tokens ?? data.usage?.total_tokens ?? 0,\n outputTokens: 0,\n });\n return { vectors, usage };\n }\n\n // Transcribe (F016.3) — Voxtral via OpenAI-compatible /audio/transcriptions\n // (multipart). Per-minute cost when durationSec is supplied.\n async function transcribe(req: TranscribeRequest): Promise<TranscribeResult> {\n const form = new FormData();\n form.append(\"file\", new Blob([req.audio]), \"audio\");\n form.append(\"model\", req.spec.model);\n if (req.language) form.append(\"language\", req.language);\n const res = await fetchImpl(`${baseUrl}/audio/transcriptions`, {\n method: \"POST\",\n headers: { authorization: `Bearer ${key()}` },\n body: form,\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`mistral transcribe ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as { text?: string };\n const usage = freshUsage({\n provider: \"mistral\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"transcribe\",\n inputTokens: 0,\n outputTokens: 0,\n });\n if (req.durationSec !== undefined) {\n usage.costUsd = (req.durationSec / 60) * (VOXTRAL_PRICE_PER_MIN[req.spec.model] ?? 0);\n }\n return { text: data.text ?? \"\", usage };\n }\n\n // Batch (F016.1) — async chat at 50% cost. Upload a JSONL of requests → create\n // a job → poll status → download results. Each line: {custom_id, body:{model,messages}}.\n async function batchSubmit(req: { items: BatchRequestItem[]; spec: TierSpec }): Promise<BatchJob> {\n const jsonl = req.items\n .map((it) =>\n JSON.stringify({\n custom_id: it.customId,\n body: { model: req.spec.model, messages: [{ role: \"user\", content: it.prompt }] },\n }),\n )\n .join(\"\\n\");\n // Upload the input file (multipart, purpose=batch).\n const form = new FormData();\n form.append(\"purpose\", \"batch\");\n form.append(\"file\", new Blob([jsonl], { type: \"application/jsonl\" }), \"batch.jsonl\");\n const up = await fetchImpl(`${baseUrl}/files`, {\n method: \"POST\",\n headers: { authorization: `Bearer ${key()}` },\n body: form,\n });\n if (!up.ok) throw new Error(`mistral batch upload ${up.status}: ${(await up.text().catch(() => \"\")).slice(0, 200)}`);\n const fileId = ((await up.json()) as { id?: string }).id;\n // Create the batch job.\n const job = await fetchImpl(`${baseUrl}/batch/jobs`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: `Bearer ${key()}` },\n body: JSON.stringify({ input_files: [fileId], model: req.spec.model, endpoint: \"/v1/chat/completions\" }),\n });\n if (!job.ok) throw new Error(`mistral batch job ${job.status}: ${(await job.text().catch(() => \"\")).slice(0, 200)}`);\n const data = (await job.json()) as { id?: string; status?: string; total_requests?: number };\n return { jobId: data.id ?? \"\", status: data.status ?? \"queued\", total: data.total_requests };\n }\n\n async function batchStatus(req: { jobId: string; spec: TierSpec }): Promise<BatchJob> {\n const res = await fetchImpl(`${baseUrl}/batch/jobs/${req.jobId}`, { headers: { authorization: `Bearer ${key()}` } });\n if (!res.ok) throw new Error(`mistral batch status ${res.status}`);\n const d = (await res.json()) as { id?: string; status?: string; total_requests?: number; succeeded_requests?: number };\n return { jobId: d.id ?? req.jobId, status: d.status ?? \"unknown\", total: d.total_requests, completed: d.succeeded_requests };\n }\n\n async function batchResults(req: { jobId: string; spec: TierSpec }): Promise<BatchResultItem[]> {\n const job = await fetchImpl(`${baseUrl}/batch/jobs/${req.jobId}`, { headers: { authorization: `Bearer ${key()}` } });\n if (!job.ok) throw new Error(`mistral batch results ${job.status}`);\n const outputFile = ((await job.json()) as { output_file?: string }).output_file;\n if (!outputFile) throw new Error(\"mistral batch: job has no output_file yet (not finished)\");\n const content = await fetchImpl(`${baseUrl}/files/${outputFile}/content`, { headers: { authorization: `Bearer ${key()}` } });\n if (!content.ok) throw new Error(`mistral batch download ${content.status}`);\n const lines = (await content.text()).trim().split(\"\\n\").filter(Boolean);\n return lines.map((line) => {\n const row = JSON.parse(line) as { custom_id?: string; response?: { body?: { choices?: { message?: { content?: string } }[] } } };\n return { customId: row.custom_id ?? \"\", text: row.response?.body?.choices?.[0]?.message?.content ?? \"\" };\n });\n }\n\n return { ...base, ocr, moderate, embedding, transcribe, batchSubmit, batchStatus, batchResults };\n}\n","// ElevenLabs adapter (F020). Text-to-Dialogue (eleven_v3) turns a manuscript of\n// {text, voice_id} turns into ONE cohesive multi-voice audio episode — the\n// \"instant podcast\" primitive. Also single-voice TTS + voice listing. Audio out\n// is MP3 bytes; billed per character. Key from ELEVENLABS_API_KEY.\nimport { freshUsage } from \"../cost/usage.js\";\nimport type { ProviderAdapter, DialogueRequest, TtsRequest, PodcastResult } from \"../types.js\";\n\n/** USD per 1000 characters (ElevenLabs bills per char; API overage ≈ $0.10–0.18/1k). */\nconst ELEVENLABS_PRICE_PER_1K_CHARS = 0.15;\n\n/** Curated Danish voices (F020.3) — friendly name → ElevenLabs voiceId. Apps can\n * pass these names to `ai.podcast`/`ai.tts` instead of raw IDs. */\nexport const ELEVENLABS_DANISH_VOICES: Record<string, string> = {\n soren: \"xj6X4BCUsv9oxohm1E8o\",\n jesper: \"Bl1YwS3uJac5zEOSNESn\",\n mads: \"BIWC0507fYMfhPcAEIRP\",\n noam: \"V34B5u5UbLdNJVEkcgXp\",\n camilla: \"4RklGmuxoAskAbGXplXN\",\n};\n\n/** Resolve a curated voice name to its voiceId; pass a raw voiceId through unchanged. */\nexport function resolveVoice(nameOrId: string): string {\n return ELEVENLABS_DANISH_VOICES[nameOrId] ?? nameOrId;\n}\n\nexport interface ElevenLabsVoice {\n voiceId: string;\n name: string;\n language?: string;\n}\n\nexport function elevenlabsAdapter(\n config: { apiKey?: string; baseUrl?: string; fetch?: typeof fetch; pricePer1kChars?: number } = {},\n): ProviderAdapter & {\n listVoices(): Promise<ElevenLabsVoice[]>;\n} {\n const baseUrl = config.baseUrl ?? \"https://api.elevenlabs.io/v1\";\n const fetchImpl = config.fetch ?? fetch;\n\n function key(): string {\n const k = config.apiKey ?? process.env.ELEVENLABS_API_KEY;\n if (!k) throw new Error(\"elevenlabs adapter: API key not set (env ELEVENLABS_API_KEY)\");\n return k;\n }\n\n function priceFor(chars: number, model: string): ReturnType<typeof freshUsage> {\n const usage = freshUsage({\n provider: \"elevenlabs\",\n model,\n transport: \"http\",\n capability: \"podcast\",\n inputTokens: 0,\n outputTokens: 0,\n });\n usage.costUsd = (chars / 1000) * (config.pricePer1kChars ?? ELEVENLABS_PRICE_PER_1K_CHARS);\n return usage;\n }\n\n // Multi-voice dialogue → one episode. POST /text-to-dialogue.\n async function dialogue(req: DialogueRequest): Promise<PodcastResult> {\n const res = await fetchImpl(`${baseUrl}/text-to-dialogue`, {\n method: \"POST\",\n headers: { \"xi-api-key\": key(), \"content-type\": \"application/json\", accept: \"audio/mpeg\" },\n body: JSON.stringify({\n model_id: req.spec.model,\n inputs: req.inputs.map((t) => ({ text: t.text, voice_id: t.voiceId })),\n ...(req.format ? { output_format: req.format } : {}),\n }),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`elevenlabs dialogue ${res.status}: ${body.slice(0, 300)}`);\n }\n const audio = new Uint8Array(await res.arrayBuffer());\n const chars = req.inputs.reduce((n, t) => n + t.text.length, 0);\n return { audio, mimeType: \"audio/mpeg\", usage: priceFor(chars, req.spec.model) };\n }\n\n // Single-voice TTS. POST /text-to-speech/{voice_id}.\n async function tts(req: TtsRequest): Promise<PodcastResult> {\n const model = req.spec.model;\n const res = await fetchImpl(`${baseUrl}/text-to-speech/${req.voiceId}`, {\n method: \"POST\",\n headers: { \"xi-api-key\": key(), \"content-type\": \"application/json\", accept: \"audio/mpeg\" },\n body: JSON.stringify({ text: req.text, model_id: model }),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`elevenlabs tts ${res.status}: ${body.slice(0, 300)}`);\n }\n const audio = new Uint8Array(await res.arrayBuffer());\n return { audio, mimeType: \"audio/mpeg\", usage: priceFor(req.text.length, model) };\n }\n\n async function listVoices(): Promise<ElevenLabsVoice[]> {\n const res = await fetchImpl(`${baseUrl}/voices`, { headers: { \"xi-api-key\": key() } });\n if (!res.ok) throw new Error(`elevenlabs voices ${res.status}`);\n const data = (await res.json()) as { voices?: { voice_id: string; name: string; labels?: { language?: string } }[] };\n return (data.voices ?? []).map((v) => ({ voiceId: v.voice_id, name: v.name, language: v.labels?.language }));\n }\n\n return { name: \"elevenlabs\", dialogue, tts, listVoices };\n}\n","// Azure Speech (Cognitive Services) TTS adapter (F026). Natural EU-resident\n// neural Danish read-aloud behind the existing `ai.tts` capability. Azure Speech\n// is NOT reachable via OpenRouter (that proxies LLM chat/completions only) — this\n// is a direct SSML REST call, region-pinned to an EU host. Audio out is MP3 bytes;\n// billed per character. Key + region from AZURE_SPEECH_KEY / AZURE_SPEECH_REGION.\nimport { freshUsage } from \"../cost/usage.js\";\nimport type { ProviderAdapter, TtsRequest, PodcastResult, TranscribeRequest, TranscribeResult } from \"../types.js\";\n\n/** USD per 1000 characters. ≈ Azure neural standard ($16 / 1M chars) — verify on\n * azure.microsoft.com/pricing; override via config.pricePer1kChars. */\nconst AZURE_TTS_PRICE_PER_1K_CHARS = 0.016;\n\n/** USD per audio-minute for speech-to-text. ≈ Azure standard STT ($1 / audio-hour\n * = $0.0167/min) — verify the fast-transcription rate on azure.microsoft.com/pricing;\n * override via config.sttPricePerMin. */\nconst AZURE_STT_PRICE_PER_MIN = 0.0167;\n\n/** Fast-transcription REST api-version. 2025-10-15 is required for the `phraseList`\n * biasing field (2024-11-15 rejects it as \"Invalid JSON\"); both serve plain\n * transcription. Override via config.sttApiVersion. (Live-verified F029.) */\nconst DEFAULT_STT_API_VERSION = \"2025-10-15\";\n\n/** Default region — EU/GDPR-clean. Override via config.region / AZURE_SPEECH_REGION. */\nconst DEFAULT_REGION = \"westeurope\";\n\n/** Default MP3 output (Azure's X-Microsoft-OutputFormat). */\nconst DEFAULT_FORMAT = \"audio-24khz-48kbitrate-mono-mp3\";\n\n/** Short language code → Azure STT locale. A full locale (\"da-DK\") passes through;\n * omitted language defaults to da-DK (the EU-Danish use-case this was built for). */\nconst AZURE_LOCALE_MAP: Record<string, string> = {\n da: \"da-DK\", en: \"en-US\", de: \"de-DE\", sv: \"sv-SE\", nb: \"nb-NO\", no: \"nb-NO\",\n fi: \"fi-FI\", nl: \"nl-NL\", fr: \"fr-FR\", es: \"es-ES\", it: \"it-IT\", pt: \"pt-PT\",\n};\nfunction toAzureLocale(lang?: string): string {\n if (!lang) return \"da-DK\";\n if (lang.includes(\"-\")) return lang;\n return AZURE_LOCALE_MAP[lang.toLowerCase()] ?? lang;\n}\n\n/** A curated Danish-speaking Azure voice, exposed so a consuming app can render a\n * picker. `native` = a true da-DK voice (most natural); otherwise a multilingual\n * voice that also speaks Danish (Azure has only 2 native da-DK voices). */\nexport interface AzureVoiceInfo {\n /** Friendly name a caller passes as `voice` (e.g. \"christel\"). */\n name: string;\n /** Full Azure voice name (e.g. \"da-DK-ChristelNeural\"). */\n voiceId: string;\n gender: \"female\" | \"male\";\n /** Display label for a UI picker. */\n display: string;\n /** True for the 2 native da-DK voices; false for multilingual voices speaking Danish. */\n native: boolean;\n /** Per-voice default speaking rate, applied when a call passes no explicit `rate`\n * (e.g. Christel reads a touch fast, so her natural default is 0.85). Omitted = 1 (normal). */\n defaultRate?: number;\n}\n\n/** Curated da-DK roster (F026) — 2 native + 4 multilingual, 3 of each gender.\n * Verified against Azure's voices/list (only Christel + Jeppe are native da-DK). */\nexport const AZURE_DANISH_VOICE_LIST: AzureVoiceInfo[] = [\n { name: \"christel\", voiceId: \"da-DK-ChristelNeural\", gender: \"female\", display: \"Christel\", native: true, defaultRate: 0.85 },\n { name: \"seraphina\", voiceId: \"de-DE-SeraphinaMultilingualNeural\", gender: \"female\", display: \"Seraphina\", native: false },\n { name: \"ava\", voiceId: \"en-US-AvaMultilingualNeural\", gender: \"female\", display: \"Ava\", native: false },\n { name: \"jeppe\", voiceId: \"da-DK-JeppeNeural\", gender: \"male\", display: \"Jeppe\", native: true },\n { name: \"florian\", voiceId: \"de-DE-FlorianMultilingualNeural\", gender: \"male\", display: \"Florian\", native: false },\n { name: \"andrew\", voiceId: \"en-US-AndrewMultilingualNeural\", gender: \"male\", display: \"Andrew\", native: false },\n];\n\n/** Friendly name → full Azure voice name. Distinct from ELEVENLABS_DANISH_VOICES so\n * the client's resolveVoice passes these through unchanged to this adapter. */\nexport const AZURE_DANISH_VOICES: Record<string, string> = Object.fromEntries(\n AZURE_DANISH_VOICE_LIST.map((v) => [v.name, v.voiceId]),\n);\n\n/** The curated Danish voice roster, for a consuming app to present in a picker. */\nexport function listAzureDanishVoices(): AzureVoiceInfo[] {\n return AZURE_DANISH_VOICE_LIST;\n}\n\n/** Resolve a curated friendly name to its full Azure voice; pass a full voice name\n * (e.g. \"da-DK-ChristelNeural\") through unchanged. */\nexport function resolveAzureVoice(nameOrVoice: string): string {\n return AZURE_DANISH_VOICES[nameOrVoice] ?? nameOrVoice;\n}\n\n/** XML-escape so a `&`/`<` in the text can't break the SSML envelope. */\nfunction xmlEscape(s: string): string {\n return s\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n/** Derive the BCP-47 locale from a voice name: \"da-DK-ChristelNeural\" → \"da-DK\". */\nfunction localeOf(voice: string): string {\n const parts = voice.split(\"-\");\n return parts.length >= 2 ? `${parts[0]}-${parts[1]}` : \"en-US\";\n}\n\nexport function azureAdapter(\n config: {\n apiKey?: string;\n region?: string;\n fetch?: typeof fetch;\n pricePer1kChars?: number;\n /** USD per audio-minute for transcribe (overrides AZURE_STT_PRICE_PER_MIN). */\n sttPricePerMin?: number;\n /** STT base URL override (e.g. a resource custom domain). */\n sttBaseUrl?: string;\n /** Resource name → custom-domain STT host `{resource}.cognitiveservices.azure.com`\n * (or env AZURE_SPEECH_RESOURCE). Without it, STT uses the regional host. */\n resource?: string;\n /** Fast-transcription api-version (overrides the GA default). */\n sttApiVersion?: string;\n /** phraseList biasing weight (0–2) applied when a call passes `phrases`. Default 1.5. */\n sttBiasingWeight?: number;\n } = {},\n): ProviderAdapter {\n const fetchImpl = config.fetch ?? fetch;\n\n function key(): string {\n const k = config.apiKey ?? process.env.AZURE_SPEECH_KEY;\n if (!k) throw new Error(\"azure adapter: API key not set (env AZURE_SPEECH_KEY)\");\n return k;\n }\n function region(): string {\n return config.region ?? process.env.AZURE_SPEECH_REGION ?? DEFAULT_REGION;\n }\n /** STT host. Default = regional cognitive host; a resource name (config/env) →\n * the custom-domain host (some resources require it). Live-verified per resource. */\n function sttBaseUrl(): string {\n if (config.sttBaseUrl) return config.sttBaseUrl.replace(/\\/$/, \"\");\n const resource = config.resource ?? process.env.AZURE_SPEECH_RESOURCE;\n if (resource) return `https://${resource}.cognitiveservices.azure.com`;\n return `https://${region()}.api.cognitive.microsoft.com`;\n }\n\n function priceFor(chars: number, model: string): ReturnType<typeof freshUsage> {\n const usage = freshUsage({\n provider: \"azure\",\n model,\n transport: \"http\",\n capability: \"tts\",\n inputTokens: 0,\n outputTokens: 0,\n });\n usage.costUsd = (chars / 1000) * (config.pricePer1kChars ?? AZURE_TTS_PRICE_PER_1K_CHARS);\n return usage;\n }\n\n // Single-voice TTS. POST .../cognitiveservices/v1 with an SSML body.\n async function tts(req: TtsRequest): Promise<PodcastResult> {\n const voice = resolveAzureVoice(req.voiceId);\n const lang = req.lang ?? localeOf(voice);\n const format = req.format ?? DEFAULT_FORMAT;\n // Speaking rate via SSML <prosody>: a multiplier of the default (1 = normal,\n // 0.9 = 10% slower, 1.1 = 10% faster). An explicit req.rate wins; otherwise the\n // voice's own defaultRate (e.g. Christel = 0.85) applies; else no wrapper.\n const escaped = xmlEscape(req.text);\n const effRate = req.rate ?? AZURE_DANISH_VOICE_LIST.find((v) => v.voiceId === voice)?.defaultRate;\n const inner =\n effRate != null && effRate !== 1 ? `<prosody rate='${effRate}'>${escaped}</prosody>` : escaped;\n const ssml =\n `<speak version='1.0' xml:lang='${lang}'>` +\n `<voice name='${voice}'>${inner}</voice></speak>`;\n const res = await fetchImpl(\n `https://${region()}.tts.speech.microsoft.com/cognitiveservices/v1`,\n {\n method: \"POST\",\n headers: {\n \"Ocp-Apim-Subscription-Key\": key(),\n \"Content-Type\": \"application/ssml+xml\",\n \"X-Microsoft-OutputFormat\": format,\n },\n body: ssml,\n },\n );\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`azure tts ${res.status}: ${body.slice(0, 300)}`);\n }\n const audio = new Uint8Array(await res.arrayBuffer());\n return { audio, mimeType: \"audio/mpeg\", usage: priceFor(req.text.length, req.spec.model) };\n }\n\n // Speech-to-text (F029) via Azure fast transcription. Synchronous multipart POST\n // → { combinedPhrases:[{text}], durationMilliseconds }. da-DK forced (Voxtral can't).\n // Cost is per audio-minute from the response's real duration. EU-resident.\n async function transcribe(req: TranscribeRequest): Promise<TranscribeResult> {\n const locale = toAzureLocale(req.language);\n const definition: Record<string, unknown> = { locales: [locale] };\n // Bias toward known brand/jargon terms (F029.3) — lifts accuracy on names the\n // model wouldn't otherwise know (e.g. \"cardmem\", \"Pins\"). Other STTs ignore phrases.\n if (req.phrases && req.phrases.length > 0) {\n definition.phraseList = { phrases: req.phrases, biasingWeight: config.sttBiasingWeight ?? 1.5 };\n }\n const form = new FormData();\n form.append(\"audio\", new Blob([req.audio]), \"audio\");\n form.append(\"definition\", JSON.stringify(definition));\n const url = `${sttBaseUrl()}/speechtotext/transcriptions:transcribe?api-version=${config.sttApiVersion ?? DEFAULT_STT_API_VERSION}`;\n const res = await fetchImpl(url, {\n method: \"POST\",\n headers: { \"Ocp-Apim-Subscription-Key\": key() },\n body: form,\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`azure transcribe ${res.status}: ${body.slice(0, 300)}`);\n }\n const data = (await res.json()) as {\n combinedPhrases?: { text?: string }[];\n durationMilliseconds?: number;\n };\n const text = data.combinedPhrases?.[0]?.text ?? \"\";\n // Prefer the API's real duration; fall back to a caller-supplied durationSec.\n const minutes =\n data.durationMilliseconds != null\n ? data.durationMilliseconds / 60000\n : (req.durationSec ?? 0) / 60;\n const usage = freshUsage({\n provider: \"azure\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"transcribe\",\n inputTokens: 0,\n outputTokens: 0,\n });\n usage.costUsd = minutes * (config.sttPricePerMin ?? AZURE_STT_PRICE_PER_MIN);\n return { text, usage };\n }\n\n return { name: \"azure\", tts, transcribe };\n}\n","// Google Cloud Vertex AI adapter (F031) — EU-resident `ai.animate` (Veo). Reuses\n// the exact Veo request/poll/download shape proven live in gemini.ts (F024), but\n// swaps: (a) endpoint → a region-pinned Vertex host (default europe-west1, the\n// whole reason this adapter exists), (b) auth → a GCP service-account OAuth2\n// Bearer token, self-minted via node:crypto (zero extra deps), not an API key.\n//\n// UNVERIFIED SHAPE NOTE: the inline-bytes response parsing below (`response.\n// videos[].bytesBase64Encoded`) is our best-effort read of Vertex's public Veo\n// docs — it has not yet been proven against a real Vertex response (F031.3's\n// live smoke does that). A `gcsUri`-shaped response throws a clear error rather\n// than silently mis-parsing.\nimport { createSign } from \"node:crypto\";\nimport { readFileSync } from \"node:fs\";\nimport { toInlineImage } from \"./media.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type { ProviderAdapter, AnimateRequest, AnimateResult } from \"../types.js\";\n\nconst TOKEN_ENDPOINT = \"https://oauth2.googleapis.com/token\";\nconst DEFAULT_REGION = \"europe-west1\";\nconst CLOUD_PLATFORM_SCOPE = \"https://www.googleapis.com/auth/cloud-platform\";\n\n/** Per-SECOND USD for Veo on Vertex — same model family/pricing as the consumer\n * Gemini API (F024's VEO_PRICE_PER_SEC). Override per call via config.pricePerSecond. */\nconst VERTEX_VEO_PRICE_PER_SEC: Record<string, number> = {\n \"veo-3.1-generate-preview\": 0.4,\n \"veo-3.1-fast-generate-preview\": 0.1,\n \"veo-3.1-lite-generate-preview\": 0.05,\n \"veo-3.0-generate-001\": 0.4,\n \"veo-3.0-fast-generate-001\": 0.1,\n};\n\ninterface ServiceAccountCredentials {\n client_email: string;\n private_key: string;\n}\n\ninterface VertexOperation {\n done?: boolean;\n error?: { message?: string };\n response?: {\n videos?: { bytesBase64Encoded?: string; gcsUri?: string; mimeType?: string }[];\n };\n}\n\nfunction base64url(input: Buffer | string): string {\n const buf = typeof input === \"string\" ? Buffer.from(input) : input;\n return buf.toString(\"base64\").replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nfunction resolveCredentials(config: { credentials?: string }): ServiceAccountCredentials {\n const inline = config.credentials ?? process.env.GOOGLE_VERTEX_CREDENTIALS;\n if (inline) {\n try {\n return JSON.parse(inline) as ServiceAccountCredentials;\n } catch {\n throw new Error(\"vertex adapter: GOOGLE_VERTEX_CREDENTIALS is not valid JSON\");\n }\n }\n const path = process.env.GOOGLE_APPLICATION_CREDENTIALS;\n if (path) {\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch (err) {\n throw new Error(`vertex adapter: failed to read GOOGLE_APPLICATION_CREDENTIALS file: ${(err as Error).message}`);\n }\n return JSON.parse(raw) as ServiceAccountCredentials;\n }\n throw new Error(\n \"vertex adapter: service-account credentials not set (env GOOGLE_VERTEX_CREDENTIALS inline JSON, or GOOGLE_APPLICATION_CREDENTIALS file path)\",\n );\n}\n\n/** Self-sign a JWT and exchange it for a Bearer access token — no google-auth-library dep. */\nasync function mintAccessToken(\n creds: ServiceAccountCredentials,\n fetchImpl: typeof fetch,\n): Promise<{ token: string; expiresAt: number }> {\n const now = Math.floor(Date.now() / 1000);\n const header = { alg: \"RS256\", typ: \"JWT\" };\n const claims = {\n iss: creds.client_email,\n scope: CLOUD_PLATFORM_SCOPE,\n aud: TOKEN_ENDPOINT,\n iat: now,\n exp: now + 3600,\n };\n const unsigned = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(claims))}`;\n const signature = createSign(\"RSA-SHA256\").update(unsigned).sign(creds.private_key);\n const jwt = `${unsigned}.${base64url(signature)}`;\n\n const res = await fetchImpl(TOKEN_ENDPOINT, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"urn:ietf:params:oauth:grant-type:jwt-bearer\",\n assertion: jwt,\n }).toString(),\n });\n if (!res.ok) {\n throw new Error(`vertex adapter: token exchange failed ${res.status}: ${(await res.text().catch(() => \"\")).slice(0, 300)}`);\n }\n const data = (await res.json()) as { access_token?: string; expires_in?: number };\n if (!data.access_token) throw new Error(\"vertex adapter: token exchange returned no access_token\");\n return { token: data.access_token, expiresAt: Date.now() + (data.expires_in ?? 3600) * 1000 };\n}\n\nexport function vertexAdapter(\n config: {\n /** Inline service-account JSON; else env GOOGLE_VERTEX_CREDENTIALS or GOOGLE_APPLICATION_CREDENTIALS (file path). */\n credentials?: string;\n /** GCP project id; else env GOOGLE_VERTEX_PROJECT. Required — never guessed. */\n project?: string;\n /** Vertex region; default \"europe-west1\" (EU by default — this adapter's reason to exist). */\n region?: string;\n fetch?: typeof fetch;\n pricePerSecond?: number;\n pollIntervalMs?: number;\n videoTimeoutMs?: number;\n } = {},\n): ProviderAdapter {\n const fetchImpl = config.fetch ?? fetch;\n let cached: { token: string; expiresAt: number } | null = null;\n\n function region(): string {\n return config.region ?? process.env.GOOGLE_VERTEX_REGION ?? DEFAULT_REGION;\n }\n function project(): string {\n const p = config.project ?? process.env.GOOGLE_VERTEX_PROJECT;\n if (!p) throw new Error(\"vertex adapter: project not set (config.project or env GOOGLE_VERTEX_PROJECT)\");\n return p;\n }\n async function accessToken(): Promise<string> {\n if (cached && cached.expiresAt - 60_000 > Date.now()) return cached.token;\n const creds = resolveCredentials(config);\n cached = await mintAccessToken(creds, fetchImpl);\n return cached.token;\n }\n\n async function animate(req: AnimateRequest): Promise<AnimateResult> {\n const token = await accessToken();\n const proj = project();\n const reg = region();\n const pollIntervalMs = config.pollIntervalMs ?? 5000;\n const deadline = Date.now() + (config.videoTimeoutMs ?? 300000);\n const baseUrl = `https://${reg}-aiplatform.googleapis.com/v1`;\n\n const { data, mimeType } = await toInlineImage(req.image, fetchImpl);\n const parameters: Record<string, unknown> = {};\n if (req.durationSec !== undefined) parameters.durationSeconds = req.durationSec;\n if (req.resolution !== undefined) parameters.resolution = req.resolution;\n const body = {\n instances: [{ prompt: req.prompt ?? \"\", image: { bytesBase64Encoded: data, mimeType } }],\n ...(Object.keys(parameters).length ? { parameters } : {}),\n };\n\n const submit = await fetchImpl(\n `${baseUrl}/projects/${proj}/locations/${reg}/publishers/google/models/${req.spec.model}:predictLongRunning`,\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: `Bearer ${token}` },\n body: JSON.stringify(body),\n },\n );\n if (!submit.ok) {\n throw new Error(`vertex animate ${submit.status}: ${(await submit.text().catch(() => \"\")).slice(0, 300)}`);\n }\n const op = (await submit.json()) as { name?: string };\n if (!op.name) throw new Error(\"vertex animate: no operation name in submit response\");\n\n let videoB64: string | undefined;\n let videoMime = \"video/mp4\";\n for (;;) {\n const poll = await fetchImpl(`${baseUrl}/${op.name}`, { headers: { authorization: `Bearer ${token}` } });\n if (!poll.ok) throw new Error(`vertex animate poll ${poll.status}`);\n const opData = (await poll.json()) as VertexOperation;\n if (opData.error) throw new Error(`vertex animate: ${opData.error.message ?? \"operation error\"}`);\n if (opData.done) {\n const video = opData.response?.videos?.[0];\n if (!video) {\n throw new Error(`vertex animate: done but no video in response: ${JSON.stringify(opData.response).slice(0, 300)}`);\n }\n if (!video.bytesBase64Encoded) {\n if (video.gcsUri) {\n throw new Error(\n `vertex animate: response returned a gcsUri (\"${video.gcsUri}\") — GCS download not yet supported (F031.x); this build only handles inline bytes`,\n );\n }\n throw new Error(`vertex animate: done but no bytesBase64Encoded in response: ${JSON.stringify(opData.response).slice(0, 300)}`);\n }\n videoB64 = video.bytesBase64Encoded;\n videoMime = video.mimeType ?? \"video/mp4\";\n break;\n }\n if (Date.now() >= deadline) throw new Error(\"vertex animate: timed out\");\n await new Promise((r) => setTimeout(r, pollIntervalMs));\n }\n\n const usage = freshUsage({\n provider: \"vertex\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"animate\",\n inputTokens: 0,\n outputTokens: 0,\n });\n const perSec = config.pricePerSecond ?? VERTEX_VEO_PRICE_PER_SEC[req.spec.model] ?? 0;\n usage.costUsd = perSec * (req.durationSec ?? 8);\n return { url: `vertex://${op.name}`, bytes: Buffer.from(videoB64, \"base64\"), mimeType: videoMime, usage };\n }\n\n return { name: \"vertex\", animate };\n}\n","// DeepL translation adapter (F032) — a dedicated MT engine, not a chat model.\n// Implements ProviderAdapter.translate directly (no chat prompt-contract).\n// EU-hosted (Falun, Sweden per deepl.com). Opt-in via override:{provider:\"deepl\"};\n// the LLM-prompt-based ai.translate stays the default for every other provider.\n//\n// CONTRACT NOTE: DeepL requires real language codes (\"DA\", \"EN-US\", \"DE\", …) in\n// `to`/`from` — NOT the free-form names the chat-based route accepts (\"Danish\").\n// This adapter does not translate names to codes; pass DeepL's own codes.\nimport { freshUsage } from \"../cost/usage.js\";\nimport type { ProviderAdapter, TranslateRequest, TranslateResult } from \"../types.js\";\n\n/** USD per 1000 characters. UNVERIFIED ESTIMATE — DeepL's own pricing pages\n * resisted automated fetch (JS-rendered / bot-protected) as of 2026-06-20;\n * third-party sources converge loosely around €20/1M chars for the Pro API,\n * but conflicting subscription-tier reports exist. Verify against\n * deepl.com/pro-api directly before relying on this for a budget decision.\n * Override via config.pricePer1kChars. Free-tier (\":fx\" key, within quota) is\n * genuinely $0 — this rate only matters for Pro usage past the free allowance. */\nconst DEEPL_PRICE_PER_1K_CHARS_ESTIMATE = 0.0217;\n\nexport function deeplAdapter(\n config: { apiKey?: string; baseUrl?: string; fetch?: typeof fetch; pricePer1kChars?: number } = {},\n): ProviderAdapter {\n const fetchImpl = config.fetch ?? fetch;\n\n function key(): string {\n const k = config.apiKey ?? process.env.DEEPL_API_KEY;\n if (!k) throw new Error(\"deepl adapter: API key not set (env DEEPL_API_KEY)\");\n return k;\n }\n\n // DeepL Free API keys always end in \":fx\" — a documented DeepL convention —\n // and must hit the free-tier host, not the Pro one.\n function baseUrl(apiKey: string): string {\n return config.baseUrl ?? (apiKey.endsWith(\":fx\") ? \"https://api-free.deepl.com\" : \"https://api.deepl.com\");\n }\n\n async function translate(req: TranslateRequest): Promise<TranslateResult> {\n const apiKey = key();\n const body: Record<string, unknown> = { text: [req.text], target_lang: req.to.toUpperCase() };\n if (req.from) body.source_lang = req.from.toUpperCase();\n\n const res = await fetchImpl(`${baseUrl(apiKey)}/v2/translate`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: `DeepL-Auth-Key ${apiKey}` },\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n const errBody = await res.text().catch(() => \"\");\n throw new Error(`deepl translate ${res.status}: ${errBody.slice(0, 300)}`);\n }\n const data = (await res.json()) as { translations?: { text?: string; detected_source_language?: string }[] };\n const text = data.translations?.[0]?.text;\n if (text === undefined) throw new Error(\"deepl translate: response contained no translation\");\n\n const usage = freshUsage({\n provider: \"deepl\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"translate\",\n inputTokens: 0,\n outputTokens: 0,\n });\n usage.costUsd = (req.text.length / 1000) * (config.pricePer1kChars ?? DEEPL_PRICE_PER_1K_CHARS_ESTIMATE);\n return { text, usage };\n }\n\n return { name: \"deepl\", translate };\n}\n","// fal.ai adapter (F5.3 + F021). Image modes, both observed in the F1 inventory:\n// - sync : POST https://fal.run/{model}, image URL straight back (sanneandersen)\n// - queue : POST https://queue.fal.run/{model} → poll status → fetch result\n// F021 adds LoRA style-training (trainStyle) + LoRA inference (image loras).\n// Auth header `Authorization: Key <FAL_KEY>`. No @fal-ai/client — plain fetch.\nimport { deflateRawSync, crc32 } from \"node:zlib\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n ImageRequest,\n ImageResult,\n AnimateRequest,\n AnimateResult,\n TrainStyleRequest,\n TrainStyleResult,\n} from \"../types.js\";\n\ninterface FalImagesResponse {\n images?: { url?: string }[];\n has_nsfw_concepts?: boolean[];\n error?: unknown;\n}\ninterface FalTrainResponse {\n diffusers_lora_file?: { url?: string };\n config_file?: { url?: string };\n}\ninterface FalQueueSubmit {\n request_id?: string;\n status_url?: string;\n response_url?: string;\n}\ninterface FalQueueStatus {\n status?: \"IN_QUEUE\" | \"IN_PROGRESS\" | \"COMPLETED\" | \"FAILED\";\n}\n\nexport interface FalAdapterConfig {\n apiKey?: string;\n /** \"sync\" (default — fal.run, fast models) or \"queue\" (queue.fal.run, polled). */\n mode?: \"sync\" | \"queue\";\n syncBaseUrl?: string;\n queueBaseUrl?: string;\n pollIntervalMs?: number;\n timeoutMs?: number;\n /** Deadline for training jobs — they take minutes (default 600000 = 10 min). */\n trainTimeoutMs?: number;\n /** Deadline for video jobs — they take minutes (default 600000 = 10 min). */\n videoTimeoutMs?: number;\n fetch?: typeof fetch;\n /** Override the per-image USD price (else a built-in estimate per model, 0 if unknown). */\n pricePerImage?: number;\n /** Override the flat per-training USD price (else ~$2 estimate). */\n pricePerTraining?: number;\n /** Override the per-SECOND video USD price (else a built-in estimate per model, 0 if unknown). */\n pricePerSecond?: number;\n}\n\n// Per-image USD ESTIMATES (fal prices by megapixel/model and changes often —\n// verify before relying on these; override via config.pricePerImage). fal does\n// not return a price, so this is the SDK's best-effort cost for `usage.costUsd`.\nconst FAL_IMAGE_PRICE_ESTIMATE: Record<string, number> = {\n \"fal-ai/flux/schnell\": 0.003,\n \"fal-ai/flux/dev\": 0.025,\n \"fal-ai/flux-lora\": 0.025,\n \"fal-ai/flux-pro\": 0.05,\n \"fal-ai/flux-pro/v1.1\": 0.04,\n};\n// Flat training estimate (fal-ai/flux-lora-fast-training, ~$2; override via config).\nconst FAL_TRAIN_PRICE_ESTIMATE = 2.0;\n\n// Per-SECOND USD estimates for video models (F024). fal does not return a price,\n// and rates vary by model/resolution — entries are fal's OFFICIAL published\n// per-second rate (fal.ai/models/<id> pricing), not guessed; override via\n// config.pricePerSecond. Unknown model → 0 (cost surfaced via a live smoke,\n// not a fabricated number).\nconst FAL_VIDEO_PRICE_PER_SEC: Record<string, number> = {\n // Kling 2.5 Turbo Pro i2v — the blessed FAL_KEY-only image→video route (F014\n // contentpush spike). $0.35 for the first 5 s + $0.07/additional s = a flat\n // $0.07/s (1080p); per-second-billed, commercial-use, not deprecated.\n \"fal-ai/kling-video/v2.5-turbo/pro/image-to-video\": 0.07,\n};\n// Default clip length to bill when the caller doesn't pass durationSec (Veo ≈ 8s).\nconst FAL_VIDEO_DEFAULT_SEC = 8;\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nexport function falAdapter(config: FalAdapterConfig = {}): ProviderAdapter {\n const doFetch = config.fetch ?? fetch;\n const syncBase = config.syncBaseUrl ?? \"https://fal.run\";\n const queueBase = config.queueBaseUrl ?? \"https://queue.fal.run\";\n const pollIntervalMs = config.pollIntervalMs ?? 2000;\n const timeoutMs = config.timeoutMs ?? 60000;\n\n // sa flagged the gotcha: their env is FAL_API_KEY, the older convention is FAL_KEY.\n // Accept either so no repo has to alias one to the other.\n const resolveKey = () => config.apiKey ?? process.env.FAL_KEY ?? process.env.FAL_API_KEY;\n const authHeaders = (apiKey: string) => ({\n \"content-type\": \"application/json\",\n Authorization: `Key ${apiKey}`,\n });\n\n async function image(req: ImageRequest): Promise<ImageResult> {\n const apiKey = resolveKey();\n if (!apiKey) throw new Error(\"fal adapter: FAL_KEY not set\");\n const headers = authHeaders(apiKey);\n\n const body: Record<string, unknown> = { prompt: req.prompt };\n if (req.width !== undefined && req.height !== undefined) {\n body.image_size = { width: req.width, height: req.height };\n }\n if (req.loras && req.loras.length > 0) {\n body.loras = req.loras.map((l) => ({ path: l.path, scale: l.scale ?? 1 }));\n }\n\n const mode = config.mode ?? \"sync\";\n const run = (b: Record<string, unknown>) =>\n mode === \"sync\" ? runSync(req.spec.model, headers, b) : runQueue(req.spec.model, headers, b);\n\n let calls = 1;\n let { url, flagged } = await run(body);\n // F021.4 — fal's NSFW safety-checker occasionally false-positives on clean\n // LoRA output and returns a fully BLACK image (has_nsfw_concepts[0]=true).\n // When retryOnBlack is set, re-roll ONCE with a fresh seed.\n if (flagged && req.retryOnBlack) {\n calls++;\n ({ url, flagged } = await run({ ...body, seed: Math.floor(Math.random() * 1e9) }));\n }\n\n // fal returns no price; estimate per-image so usage.costUsd isn't silently 0.\n // A re-roll is a second billed generation → multiply by the call count.\n const usage = freshUsage({\n provider: \"fal\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"image\",\n inputTokens: 0,\n outputTokens: 0,\n });\n usage.costUsd = (config.pricePerImage ?? FAL_IMAGE_PRICE_ESTIMATE[req.spec.model] ?? 0) * calls;\n return { url, usage };\n }\n\n async function animate(req: AnimateRequest): Promise<AnimateResult> {\n const apiKey = resolveKey();\n if (!apiKey) throw new Error(\"fal adapter: FAL_KEY not set\");\n const headers = authHeaders(apiKey);\n\n // Input image: a URL passes through; raw bytes are uploaded to fal storage\n // (fal needs a fetchable URL, not a data: URI — same gotcha as trainStyle).\n const imageUrl =\n typeof req.image === \"string\" && /^https?:\\/\\//i.test(req.image)\n ? req.image\n : await uploadToFalStorage(toBytes(req.image), sniffImageType(req.image), \"input\", apiKey);\n\n const body: Record<string, unknown> = { image_url: imageUrl };\n if (req.prompt !== undefined) body.prompt = req.prompt;\n if (req.durationSec !== undefined) body.duration = req.durationSec;\n if (req.resolution !== undefined) body.resolution = req.resolution;\n\n // Video is long-running → always the queue, with the longer deadline.\n const result = await queueResult(req.spec.model, headers, body, config.videoTimeoutMs ?? 600000);\n const url = extractVideoUrl(result);\n if (!url) {\n throw new Error(\n `fal animate: no video url in result — keys [${Object.keys(\n (result as Record<string, unknown>) ?? {},\n ).join(\", \")}]: ${JSON.stringify(result).slice(0, 500)}`,\n );\n }\n\n const usage = freshUsage({\n provider: \"fal\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"animate\",\n inputTokens: 0,\n outputTokens: 0,\n });\n // fal returns no price → per-second estimate × duration (override config.pricePerSecond).\n const perSec = config.pricePerSecond ?? FAL_VIDEO_PRICE_PER_SEC[req.spec.model] ?? 0;\n usage.costUsd = perSec * (req.durationSec ?? FAL_VIDEO_DEFAULT_SEC);\n return { url, usage };\n }\n\n async function trainStyle(req: TrainStyleRequest): Promise<TrainStyleResult> {\n const apiKey = resolveKey();\n if (!apiKey) throw new Error(\"fal adapter: FAL_KEY not set\");\n const headers = authHeaders(apiKey);\n\n const body: Record<string, unknown> = {\n images_data_url: await resolveImagesUrl(req.images, apiKey),\n is_style: req.isStyle ?? true,\n };\n if (req.triggerWord !== undefined) body.trigger_word = req.triggerWord;\n if (req.steps !== undefined) body.steps = req.steps;\n if (req.createMasks !== undefined) body.create_masks = req.createMasks;\n\n // Training runs on the queue and takes minutes — use the longer deadline.\n const result = (await queueResult(\n req.spec.model,\n headers,\n body,\n config.trainTimeoutMs ?? 600000,\n )) as FalTrainResponse;\n // fal's LoRA trainers vary in output shape (field renames, wrappers, multiple\n // trainer endpoints). Extract defensively across known/likely locations, then\n // fall back to scanning for any *.safetensors url. If still nothing, surface the\n // RAW response so a shape mismatch is diagnosable without a key on this side.\n const { loraUrl, configUrl } = extractTrainedFiles(result);\n if (!loraUrl) {\n throw new Error(\n `fal trainStyle: no LoRA file url in result — fal returned keys [${Object.keys(\n (result as Record<string, unknown>) ?? {},\n ).join(\", \")}]: ${JSON.stringify(result).slice(0, 800)}`,\n );\n }\n\n const usage = freshUsage({\n provider: \"fal\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"trainStyle\",\n inputTokens: 0,\n outputTokens: 0,\n });\n usage.costUsd = config.pricePerTraining ?? FAL_TRAIN_PRICE_ESTIMATE;\n return { loraUrl, configUrl: configUrl ?? \"\", usage };\n }\n\n /** A hosted archive URL passes straight through; an array of image URLs is fetched,\n * zipped in-memory, and uploaded to fal storage. fal REJECTS data: URIs here\n * (\"Invalid URL: URL too long\") — images_data_url must be a real http URL it can\n * fetch, so we upload the zip and pass the returned file_url. */\n async function resolveImagesUrl(images: string | string[], apiKey: string): Promise<string> {\n if (typeof images === \"string\") return images;\n const files = await Promise.all(\n images.map(async (url, i) => {\n const res = await doFetch(url);\n if (!res.ok) throw new Error(`fal trainStyle: failed to fetch image ${url} (${res.status})`);\n return { name: fileNameFromUrl(url, i), data: new Uint8Array(await res.arrayBuffer()) };\n }),\n );\n return uploadToFalStorage(buildZip(files), \"application/zip\", \"styleset.zip\", apiKey);\n }\n\n /** Upload bytes to fal storage: initiate (auth'd) → PUT to the returned signed url\n * → return the public file_url. fal CDN serves it back, fetchable by the trainer. */\n async function uploadToFalStorage(\n bytes: Uint8Array,\n contentType: string,\n fileName: string,\n apiKey: string,\n ): Promise<string> {\n const initiate = await doFetch(\"https://rest.alpha.fal.ai/storage/upload/initiate\", {\n method: \"POST\",\n headers: { Authorization: `Key ${apiKey}`, \"content-type\": \"application/json\" },\n body: JSON.stringify({ content_type: contentType, file_name: fileName }),\n });\n if (!initiate.ok) {\n throw new Error(\n `fal storage initiate ${initiate.status}: ${(await initiate.text().catch(() => \"\")).slice(0, 200)}`,\n );\n }\n const { upload_url, file_url } = (await initiate.json()) as { upload_url: string; file_url: string };\n const put = await doFetch(upload_url, {\n method: \"PUT\",\n headers: { \"content-type\": contentType },\n body: bytes,\n });\n if (!put.ok) throw new Error(`fal storage upload PUT ${put.status}`);\n return file_url;\n }\n\n /** Returns the image url + whether fal's safety-checker flagged it (→ black image). */\n async function runSync(\n model: string,\n headers: Record<string, string>,\n body: unknown,\n ): Promise<{ url: string; flagged: boolean }> {\n const res = await doFetch(`${syncBase}/${model}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n throw new Error(`fal ${res.status}: ${(await res.text().catch(() => \"\")).slice(0, 200)}`);\n }\n const data = (await res.json()) as FalImagesResponse;\n const out = data.images?.[0]?.url;\n if (!out) throw new Error(`fal: no image url in response`);\n return { url: out, flagged: data.has_nsfw_concepts?.[0] === true };\n }\n\n async function runQueue(\n model: string,\n headers: Record<string, string>,\n body: unknown,\n ): Promise<{ url: string; flagged: boolean }> {\n const result = (await queueResult(model, headers, body, timeoutMs)) as FalImagesResponse;\n const out = result.images?.[0]?.url;\n if (!out) throw new Error(\"fal queue: no image url in result\");\n return { url: out, flagged: result.has_nsfw_concepts?.[0] === true };\n }\n\n /** Generic fal queue runner: submit → poll status → fetch+return the raw result JSON. */\n async function queueResult(\n model: string,\n headers: Record<string, string>,\n body: unknown,\n deadlineMs: number,\n ): Promise<unknown> {\n const submitRes = await doFetch(`${queueBase}/${model}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n if (!submitRes.ok) {\n throw new Error(\n `fal queue submit ${submitRes.status}: ${(await submitRes.text().catch(() => \"\")).slice(0, 200)}`,\n );\n }\n const submit = (await submitRes.json()) as FalQueueSubmit;\n const statusUrl = submit.status_url;\n const responseUrl = submit.response_url;\n if (!statusUrl || !responseUrl) throw new Error(\"fal queue: missing status/response url\");\n\n const deadline = Date.now() + deadlineMs;\n for (;;) {\n const statusRes = await doFetch(statusUrl, { headers });\n const status = (await statusRes.json()) as FalQueueStatus;\n if (status.status === \"COMPLETED\") break;\n if (status.status === \"FAILED\") throw new Error(\"fal queue: job FAILED\");\n if (Date.now() >= deadline) throw new Error(`fal queue: timed out after ${deadlineMs}ms`);\n await sleep(pollIntervalMs);\n }\n\n const resultRes = await doFetch(responseUrl, { headers });\n if (!resultRes.ok) {\n throw new Error(\n `fal queue result ${resultRes.status}: ${(await resultRes.text().catch(() => \"\")).slice(0, 300)}`,\n );\n }\n return resultRes.json();\n }\n\n return { name: \"fal\", image, animate, trainStyle };\n}\n\n/** Coerce an image input to bytes (a non-http string is treated as base64/data-URI). */\nfunction toBytes(img: string | Uint8Array): Uint8Array {\n if (typeof img !== \"string\") return img;\n const b64 = img.startsWith(\"data:\") ? img.slice(img.indexOf(\",\") + 1) : img;\n return new Uint8Array(Buffer.from(b64, \"base64\"));\n}\n\n/** Sniff a content-type from the bytes' magic (PNG/WebP/GIF), default JPEG. */\nfunction sniffImageType(img: string | Uint8Array): string {\n const b = toBytes(img);\n if (b[0] === 0x89 && b[1] === 0x50) return \"image/png\";\n if (b[0] === 0x47 && b[1] === 0x49) return \"image/gif\";\n if (b[0] === 0x52 && b[1] === 0x49 && b[8] === 0x57) return \"image/webp\";\n return \"image/jpeg\";\n}\n\n/** Find the result video URL across fal's video-output shapes (video.url, a wrapper,\n * or any *.mp4/.webm url anywhere in the response). */\nexport function extractVideoUrl(result: unknown): string | undefined {\n const r = result as Record<string, unknown> | null | undefined;\n const root = (r?.data ?? r?.response ?? r?.output ?? r) as Record<string, unknown> | null | undefined;\n return (\n urlOf(root?.video) ??\n urlOf((root?.videos as unknown[] | undefined)?.[0]) ??\n deepFindUrl(root, (u) => /\\.(mp4|webm|mov)(\\?|$)/i.test(u))\n );\n}\n\n// ── fal trained-file extraction (defensive against output-shape variance) ────\n\nfunction urlOf(v: unknown): string | undefined {\n if (typeof v === \"string\") return v;\n if (v && typeof v === \"object\" && typeof (v as { url?: unknown }).url === \"string\") {\n return (v as { url: string }).url;\n }\n return undefined;\n}\n\n/** BFS the response for the first {url}/string url matching `match`. */\nfunction deepFindUrl(obj: unknown, match: (url: string) => boolean): string | undefined {\n const stack: unknown[] = [obj];\n while (stack.length) {\n const cur = stack.pop();\n if (typeof cur === \"string\") {\n if (match(cur)) return cur;\n continue;\n }\n if (cur && typeof cur === \"object\") {\n const u = (cur as { url?: unknown }).url;\n if (typeof u === \"string\" && match(u)) return u;\n for (const v of Object.values(cur as Record<string, unknown>)) stack.push(v);\n }\n }\n return undefined;\n}\n\n/** Find the LoRA + config urls across known field names, an optional data/response/\n * output wrapper, and — as a last resort — any *.safetensors / config *.json url\n * anywhere in the response. fal's LoRA trainers vary in output shape. */\nexport function extractTrainedFiles(result: unknown): { loraUrl?: string; configUrl?: string } {\n const r = result as Record<string, unknown> | null | undefined;\n const root = (r?.data ?? r?.response ?? r?.output ?? r) as\n | Record<string, unknown>\n | null\n | undefined;\n const loraUrl =\n urlOf(root?.diffusers_lora_file) ??\n urlOf(root?.lora_file) ??\n urlOf(root?.safetensors) ??\n urlOf(root?.lora) ??\n deepFindUrl(root, (u) => /\\.safetensors(\\?|$)/i.test(u));\n const configUrl =\n urlOf(root?.config_file) ??\n urlOf(root?.config) ??\n deepFindUrl(root, (u) => /config[^/]*\\.json(\\?|$)/i.test(u));\n return { loraUrl, configUrl };\n}\n\n// ── In-memory ZIP (store via DEFLATE, node:zlib — zero new deps) ──────────────\n\nfunction fileNameFromUrl(url: string, i: number): string {\n const base = url.split(\"?\")[0]!.split(\"/\").pop() || \"\";\n return /\\.[a-z0-9]+$/i.test(base) ? base : `image_${i}.png`;\n}\n\n/** Build a spec-compliant ZIP (DEFLATE method) from named byte entries. */\nfunction buildZip(files: { name: string; data: Uint8Array }[]): Uint8Array {\n const parts: Buffer[] = [];\n const central: Buffer[] = [];\n let offset = 0;\n for (const f of files) {\n const nameBuf = Buffer.from(f.name, \"utf8\");\n const data = Buffer.from(f.data);\n const comp = deflateRawSync(data);\n const crc = crc32(data) >>> 0;\n\n const lfh = Buffer.alloc(30);\n lfh.writeUInt32LE(0x04034b50, 0); // local file header signature\n lfh.writeUInt16LE(20, 4); // version needed\n lfh.writeUInt16LE(0, 6); // flags\n lfh.writeUInt16LE(8, 8); // method = deflate\n lfh.writeUInt16LE(0, 10); // mod time\n lfh.writeUInt16LE(0x21, 12); // mod date (1980-01-01)\n lfh.writeUInt32LE(crc, 14);\n lfh.writeUInt32LE(comp.length, 18); // compressed size\n lfh.writeUInt32LE(data.length, 22); // uncompressed size\n lfh.writeUInt16LE(nameBuf.length, 26);\n lfh.writeUInt16LE(0, 28); // extra len\n parts.push(lfh, nameBuf, comp);\n\n const cdh = Buffer.alloc(46);\n cdh.writeUInt32LE(0x02014b50, 0); // central directory header signature\n cdh.writeUInt16LE(20, 4); // version made by\n cdh.writeUInt16LE(20, 6); // version needed\n cdh.writeUInt16LE(0, 8); // flags\n cdh.writeUInt16LE(8, 10); // method\n cdh.writeUInt16LE(0, 12); // mod time\n cdh.writeUInt16LE(0x21, 14); // mod date\n cdh.writeUInt32LE(crc, 16);\n cdh.writeUInt32LE(comp.length, 20);\n cdh.writeUInt32LE(data.length, 24);\n cdh.writeUInt16LE(nameBuf.length, 28);\n cdh.writeUInt16LE(0, 30); // extra len\n cdh.writeUInt16LE(0, 32); // comment len\n cdh.writeUInt16LE(0, 34); // disk number start\n cdh.writeUInt16LE(0, 36); // internal attrs\n cdh.writeUInt32LE(0, 38); // external attrs\n cdh.writeUInt32LE(offset, 42); // local header offset\n central.push(cdh, nameBuf);\n\n offset += lfh.length + nameBuf.length + comp.length;\n }\n const cd = Buffer.concat(central);\n const eocd = Buffer.alloc(22);\n eocd.writeUInt32LE(0x06054b50, 0); // end of central directory signature\n eocd.writeUInt16LE(0, 4); // disk number\n eocd.writeUInt16LE(0, 6); // cd start disk\n eocd.writeUInt16LE(files.length, 8); // entries this disk\n eocd.writeUInt16LE(files.length, 10); // total entries\n eocd.writeUInt32LE(cd.length, 12); // cd size\n eocd.writeUInt32LE(offset, 16); // cd offset\n eocd.writeUInt16LE(0, 20); // comment len\n return Buffer.concat([...parts, cd, eocd]);\n}\n","// Black Forest Labs (FLUX) adapter — F023 / F023.5. EU-RESIDENT image generation.\n//\n// GDPR CRUX (non-negotiable): this adapter hard-pins https://api.eu.bfl.ai — the\n// dedicated EU endpoint — NEVER the global api.bfl.ai (which auto-failovers to the\n// US and could route a face out of the EEA). A face = biometric personal data, so\n// EU residency is what makes this compliant; \"German company\" alone is not enough.\n// The default base is asserted in bfl.test.ts.\n//\n// Two EU-resident likeness modes (route by what ai.image is given):\n// • referenceImages (F023.5) → FLUX 2 multi-reference: 1–8 photos in the generate\n// call, NO training step. Default model flux-2-max ($0.25/img); pass\n// override:{ model:\"flux-2-pro\" } for ~half price ($0.12/img). Bytes are\n// base64-inlined into the EU call (no cross-region fetch); URLs pass through.\n// • finetune (F023) → flux-pro-1.1-ultra-finetuned, a subject trained ONCE in the\n// BFL dashboard (finetune-CREATE was retired from the public API — live-verified\n// 2026-06-16: POST /v1/finetune 404s on every region; legacy eu1/us1 hosts dead).\n// See the dashboard SOP in docs/features/F023-bfl-eu-portrait-lora.md.\n//\n// Auth header `x-key`. Request→poll: POST returns {id, polling_url, cost}; we poll the\n// EU get_result by id (deliberately NOT the returned polling_url) so a response carrying\n// a face never transits a non-EU host. BFL returns the real `cost` in credits\n// (1 credit = $0.01, official) → usage.costUsd is exact, not estimated.\nimport { freshUsage } from \"../cost/usage.js\";\nimport type { ProviderAdapter, ImageRequest, ImageResult } from \"../types.js\";\n\nconst EU_BASE = \"https://api.eu.bfl.ai\";\n/** BFL bills in credits; 1 credit = $0.01 USD (official, bfl.ai/pricing). */\nconst BFL_CREDIT_USD = 0.01;\n\ninterface BflSubmitResponse {\n id?: string;\n polling_url?: string;\n /** BFL's billed cost for this request, in credits. */\n cost?: number;\n}\ninterface BflResultResponse {\n id?: string;\n /** \"Ready\" | \"Pending\" | \"Error\" | \"Request Moderated\" | \"Content Moderated\" | \"Task not found\" */\n status?: string;\n result?: { sample?: string } | null;\n progress?: number | null;\n}\n\nexport interface BflAdapterConfig {\n apiKey?: string;\n /** EU-resident base. Do NOT point this at api.bfl.ai (global, US-failover) — see header. */\n baseUrl?: string;\n pollIntervalMs?: number;\n timeoutMs?: number;\n fetch?: typeof fetch;\n /** Override the per-image USD price (else the built-in finetuned-inference estimate). */\n pricePerImage?: number;\n}\n\n// flux-pro-1.1-ultra-finetuned per-image USD. BFL bills per generated image; verify\n// against bfl.ai/pricing before relying on this (override via config.pricePerImage).\nconst BFL_IMAGE_PRICE = 0.06;\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nfunction gcd(a: number, b: number): number {\n return b === 0 ? a : gcd(b, a % b);\n}\n\n/** Remaining BFL account credits + their USD value (1 credit = $0.01). */\nexport interface BflCredits {\n credits: number;\n usd: number;\n}\n\n/** F023.6 — check the BFL account's remaining credit balance (`GET /v1/credits`).\n * Account-level (region-independent); EU-pinned by default for consistency. Use it\n * for budget-gating before a generate call: `if ((await bflCredits()).usd < 1) …`. */\nexport async function bflCredits(\n opts: { apiKey?: string; baseUrl?: string; fetch?: typeof fetch } = {},\n): Promise<BflCredits> {\n const apiKey = opts.apiKey ?? process.env.BFL_API_KEY;\n if (!apiKey) throw new Error(\"bflCredits: BFL_API_KEY not set\");\n const doFetch = opts.fetch ?? fetch;\n const res = await doFetch(`${opts.baseUrl ?? EU_BASE}/v1/credits`, { headers: { \"x-key\": apiKey } });\n if (!res.ok) {\n throw new Error(`bflCredits ${res.status}: ${(await res.text().catch(() => \"\")).slice(0, 200)}`);\n }\n const data = (await res.json()) as { credits?: number };\n const credits = typeof data.credits === \"number\" ? data.credits : 0;\n return { credits, usd: credits * BFL_CREDIT_USD };\n}\n\nexport function bflAdapter(config: BflAdapterConfig = {}): ProviderAdapter {\n const doFetch = config.fetch ?? fetch;\n const base = config.baseUrl ?? EU_BASE;\n const pollIntervalMs = config.pollIntervalMs ?? 1500;\n const timeoutMs = config.timeoutMs ?? 120000;\n\n const resolveKey = () => config.apiKey ?? process.env.BFL_API_KEY;\n\n async function image(req: ImageRequest): Promise<ImageResult> {\n const apiKey = resolveKey();\n if (!apiKey) throw new Error(\"bfl adapter: BFL_API_KEY not set\");\n const headers = { \"content-type\": \"application/json\", \"x-key\": apiKey };\n\n const body: Record<string, unknown> = { prompt: req.prompt };\n if (req.referenceImages?.length) {\n // F023.5 — FLUX 2 multi-reference: input_image, input_image_2 … input_image_8.\n req.referenceImages.forEach((img, i) => {\n body[i === 0 ? \"input_image\" : `input_image_${i + 1}`] = toBflImage(img);\n });\n if (req.width) body.width = req.width;\n if (req.height) body.height = req.height;\n if (req.seed !== undefined) body.seed = req.seed;\n body.output_format = req.outputFormat ?? \"jpeg\";\n body.safety_tolerance = req.safetyTolerance ?? 2;\n } else if (req.finetune) {\n // F023 — finetuned subject (trained once in the BFL dashboard).\n body.finetune_id = req.finetune;\n if (req.finetuneStrength !== undefined) body.finetune_strength = req.finetuneStrength;\n // flux-pro-1.1-ultra takes aspect_ratio, not width/height — derive it when both given.\n if (req.width && req.height) {\n const g = gcd(req.width, req.height) || 1;\n body.aspect_ratio = `${req.width / g}:${req.height / g}`;\n }\n } else {\n throw new Error(\n \"bfl adapter: requires referenceImages (FLUX 2 multi-reference) or a finetune id. \" +\n \"ai.image({ referenceImages: [...] }) needs no training; ai.image({ finetune }) uses a subject \" +\n \"trained once in the BFL dashboard (dashboard.bfl.ai — finetune-create is not in the public API).\",\n );\n }\n\n const submitRes = await doFetch(`${base}/v1/${req.spec.model}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n if (!submitRes.ok) {\n throw new Error(`bfl ${submitRes.status}: ${(await submitRes.text().catch(() => \"\")).slice(0, 200)}`);\n }\n const submit = (await submitRes.json()) as BflSubmitResponse;\n if (!submit.id) throw new Error(\"bfl: no task id in submit response\");\n\n const sample = await poll(submit.id, apiKey);\n\n const usage = freshUsage({\n provider: \"bfl\",\n model: req.spec.model,\n transport: \"http\",\n capability: \"image\",\n inputTokens: 0,\n outputTokens: 0,\n });\n // BFL returns the real billed cost (credits) — use it; fall back to the estimate.\n usage.costUsd =\n typeof submit.cost === \"number\"\n ? submit.cost * BFL_CREDIT_USD\n : (config.pricePerImage ?? BFL_IMAGE_PRICE);\n return { url: sample, usage };\n }\n\n /** A URL passes through; raw bytes / a data: URI become a plain base64 string\n * (BFL's input_image wants base64, not a data: URI — verified live). */\n function toBflImage(img: string | Uint8Array): string {\n if (typeof img !== \"string\") return Buffer.from(img).toString(\"base64\");\n if (/^https?:\\/\\//i.test(img)) return img;\n const comma = img.startsWith(\"data:\") ? img.indexOf(\",\") : -1;\n return comma >= 0 ? img.slice(comma + 1) : img;\n }\n\n /** Poll the EU get_result by id until Ready (or a terminal/moderated status). */\n async function poll(id: string, apiKey: string): Promise<string> {\n const headers = { \"x-key\": apiKey };\n const deadline = Date.now() + timeoutMs;\n for (;;) {\n const res = await doFetch(`${base}/v1/get_result?id=${encodeURIComponent(id)}`, { headers });\n if (!res.ok) throw new Error(`bfl get_result ${res.status}`);\n const data = (await res.json()) as BflResultResponse;\n const status = data.status ?? \"\";\n if (status === \"Ready\") {\n const sample = data.result?.sample;\n if (!sample) throw new Error(\"bfl: status Ready but no result.sample url\");\n return sample;\n }\n if (status === \"Error\" || status === \"Failed\" || status === \"Task not found\") {\n throw new Error(`bfl: generation ${status}`);\n }\n if (status.includes(\"Moderated\")) {\n throw new Error(`bfl: ${status} — prompt or output flagged by BFL safety`);\n }\n if (Date.now() >= deadline) throw new Error(`bfl: timed out after ${timeoutMs}ms`);\n await sleep(pollIntervalMs);\n }\n }\n\n return { name: \"bfl\", image };\n}\n","// Default provider registry — the live adapters wired when AiConfig.providers is\n// absent. A bare createAI() makes real calls (keys from env). fal stays a stub\n// until F5.3 ships the real fal.ai image adapter.\nimport { anthropicAdapter } from \"./anthropic.js\";\nimport { openaiAdapter } from \"./openai.js\";\nimport { geminiAdapter } from \"./gemini.js\";\nimport { deepinfraAdapter } from \"./deepinfra.js\";\nimport { openrouterAdapter } from \"./openrouter.js\";\nimport { requestyAdapter } from \"./requesty.js\";\nimport { deepseekAdapter } from \"./deepseek.js\";\nimport { mistralAdapter } from \"./mistral.js\";\nimport { elevenlabsAdapter } from \"./elevenlabs.js\";\nimport { azureAdapter } from \"./azure.js\";\nimport { vertexAdapter } from \"./vertex.js\";\nimport { deeplAdapter } from \"./deepl.js\";\nimport { falAdapter } from \"./fal.js\";\nimport { bflAdapter } from \"./bfl.js\";\nimport type { ProviderAdapter } from \"../types.js\";\n\nexport const defaultProviders: Record<string, ProviderAdapter> = {\n anthropic: anthropicAdapter(),\n openai: openaiAdapter(),\n gemini: geminiAdapter(),\n deepinfra: deepinfraAdapter(),\n openrouter: openrouterAdapter(),\n requesty: requestyAdapter(),\n deepseek: deepseekAdapter(),\n mistral: mistralAdapter(),\n elevenlabs: elevenlabsAdapter(),\n azure: azureAdapter(),\n vertex: vertexAdapter(),\n deepl: deeplAdapter(),\n fal: falAdapter(),\n bfl: bflAdapter(),\n};\n","// Pre-flight budget guard. check() runs BEFORE the transport fires, so a call\n// that would breach a ceiling never reaches the provider. record() folds the\n// actual cost into the running total after a successful call.\nimport type { BudgetConfig, BudgetStore } from \"../types.js\";\n\n/** Default rolling-total store: in-memory, per BudgetGuard instance. */\nclass InMemoryBudgetStore implements BudgetStore {\n private spentUsd = 0;\n getSpent(): number {\n return this.spentUsd;\n }\n addSpent(usd: number): void {\n this.spentUsd += usd;\n }\n}\n\nexport class BudgetExceededError extends Error {\n readonly kind: \"per-call\" | \"rolling\";\n readonly limit: number;\n readonly spent: number;\n readonly requested: number;\n\n constructor(\n kind: \"per-call\" | \"rolling\",\n limit: number,\n spent: number,\n requested: number,\n ) {\n super(\n `Budget exceeded (${kind}): this call's estimated $${requested.toFixed(6)} ` +\n (kind === \"rolling\"\n ? `+ $${spent.toFixed(6)} already spent exceeds the $${limit.toFixed(6)} rolling ceiling`\n : `exceeds the $${limit.toFixed(6)} per-call ceiling`),\n );\n this.name = \"BudgetExceededError\";\n this.kind = kind;\n this.limit = limit;\n this.spent = spent;\n this.requested = requested;\n }\n}\n\nexport class BudgetGuard {\n private readonly store: BudgetStore;\n\n constructor(private readonly config: BudgetConfig) {\n this.store = config.store ?? new InMemoryBudgetStore();\n }\n\n /** Throws BudgetExceededError if `requested` would breach the per-call ceiling\n * or push the rolling total past its ceiling. Call before firing the request.\n * Async because a persistent store may be I/O-backed. */\n async check(requested: number): Promise<void> {\n const { perCallUsd, rollingUsd } = this.config;\n if (perCallUsd !== undefined && requested > perCallUsd) {\n throw new BudgetExceededError(\"per-call\", perCallUsd, await this.store.getSpent(), requested);\n }\n if (rollingUsd !== undefined) {\n const spent = await this.store.getSpent();\n if (spent + requested > rollingUsd) {\n throw new BudgetExceededError(\"rolling\", rollingUsd, spent, requested);\n }\n }\n }\n\n /** Add an actual cost to the running total (after a successful call). */\n async record(actual: number): Promise<void> {\n await this.store.addSpent(actual);\n }\n\n async totalSpent(): Promise<number> {\n return this.store.getSpent();\n }\n}\n","// Vision capability helper. The client owns orchestration (tier/budget/sink);\n// this module owns the vision-specific message shaping so it's unit-testable and\n// the capabilities/ layout stays meaningful. Default tier: \"vision\".\nimport type { VisionInput } from \"../schema/inputs.js\";\nimport type { Message, Tier } from \"../types.js\";\n\nexport const VISION_DEFAULT_TIER: Tier = \"vision\";\n\n/** Build the multimodal message(s) (optional system + user text + image) for a\n * vision call. A `system` instruction drives instruction-following far better\n * than packing rules into `prompt` for instruction-heavy tasks (e.g. a JSON critic). */\nexport function buildVisionMessages(input: VisionInput): Message[] {\n const messages: Message[] = [];\n if (input.system) messages.push({ role: \"system\", content: input.system });\n messages.push({\n role: \"user\",\n content: [\n { type: \"text\", text: input.prompt },\n { type: \"image\", image: input.image, mimeType: input.mimeType },\n ],\n });\n return messages;\n}\n","// Video Vision capability (F019). Like vision, but the multimodal part is a\n// video the model watches natively (Gemini, OpenRouter video models). The client\n// owns orchestration; this module owns the message shaping. Default tier: \"video\".\nimport type { VideoInput } from \"../schema/inputs.js\";\nimport type { Message, Tier } from \"../types.js\";\n\nexport const VIDEO_DEFAULT_TIER: Tier = \"video\";\n\n/** Build the message(s) (optional system + video + prompt) for a video-analysis call. */\nexport function buildVideoMessages(input: VideoInput): Message[] {\n const messages: Message[] = [];\n if (input.system) messages.push({ role: \"system\", content: input.system });\n messages.push({\n role: \"user\",\n content: [\n { type: \"video\", video: input.video, mimeType: input.mimeType },\n { type: \"text\", text: input.prompt },\n ],\n });\n return messages;\n}\n","// Translate capability helper. A thin prompt-contract on top of chat — the\n// client orchestrates (tier/budget/sink); this builds the messages. Default\n// tier: \"fast\". Returns the translation only, no preamble.\nimport type { TranslateInput } from \"../schema/inputs.js\";\nimport type { Message, Tier } from \"../types.js\";\n\nexport const TRANSLATE_DEFAULT_TIER: Tier = \"fast\";\n\nconst TRANSLATE_SYSTEM =\n \"You are a translation engine. Translate the user's text only. \" +\n \"Return the translation and nothing else — no preamble, no quotes.\";\n\nexport function buildTranslateMessages(input: TranslateInput): Message[] {\n const fromClause = input.from ? ` from ${input.from}` : \"\";\n return [\n { role: \"system\", content: TRANSLATE_SYSTEM },\n { role: \"user\", content: `Translate${fromClause} to ${input.to}:\\n\\n${input.text}` },\n ];\n}\n","// Embedding capability marker. The client orchestrates; this names the default\n// tier (OpenAI text-embedding-3-small via the embedding tier).\nimport type { Tier } from \"../types.js\";\n\nexport const EMBEDDING_DEFAULT_TIER: Tier = \"embedding\";\n","// Transcribe capability. No tier in the tier map (provider-specific, like image)\n// — defaults to OpenAI Whisper, overridable per call. Synergy: cctalk Danish\n// dictation. costUsd is 0 for v1 (Whisper is priced per minute, not per token).\nimport type { TierSpec } from \"../types.js\";\n\nexport const DEFAULT_TRANSCRIBE_SPEC: TierSpec = {\n provider: \"openai\",\n model: \"whisper-1\",\n transport: \"http\",\n};\n\n/** Fetch a URL to raw bytes; pass through bytes unchanged. */\nexport async function resolveAudio(\n audio: string | Uint8Array,\n fetchImpl: typeof fetch = fetch,\n): Promise<Uint8Array> {\n if (typeof audio !== \"string\") return audio;\n if (!/^https?:\\/\\//.test(audio)) {\n throw new Error(\"transcribe: string audio must be an http(s) URL (or pass raw bytes)\");\n }\n const res = await fetchImpl(audio);\n if (!res.ok) throw new Error(`transcribe: failed to fetch audio (${res.status})`);\n return new Uint8Array(await res.arrayBuffer());\n}\n","// Prompt-contract capabilities (F5.5). Each is a fixed system prompt over\n// chat/vision; extract adds Zod output validation with one retry. Exposed as\n// ai.contracts.* — built from the client so budget/cost tracking apply.\nimport type { AiClient, VisionInput } from \"../../schema/inputs.js\";\nimport type {\n Contracts,\n MockupInput,\n MockupResult,\n DesignInput,\n DesignResult,\n ExtractInput,\n ExtractResult,\n ClassifyInput,\n ClassifyResult,\n RerankInput,\n RerankResult,\n} from \"./types.js\";\n\n/** Pull the first JSON value out of a model reply (tolerates ```json fences + prose). */\nexport function parseJsonLoose(text: string): unknown {\n const fenced = text.replace(/```(?:json)?/gi, \"\").trim();\n const start = fenced.search(/[[{]/);\n if (start === -1) throw new Error(\"no JSON found in model output\");\n const slice = fenced.slice(start);\n // Walk back from the end to the matching closing bracket.\n const lastObj = slice.lastIndexOf(\"}\");\n const lastArr = slice.lastIndexOf(\"]\");\n const end = Math.max(lastObj, lastArr);\n return JSON.parse(slice.slice(0, end + 1));\n}\n\ntype ChatVision = Pick<AiClient, \"chat\" | \"vision\">;\n\nexport function makeContracts(client: ChatVision): Contracts {\n return {\n async mockup(input: MockupInput): Promise<MockupResult> {\n const constraints = input.constraints ? `\\n\\nConstraints:\\n${input.constraints}` : \"\";\n const res = await client.chat({\n system:\n \"You are a UI mockup generator. Output a single self-contained HTML document \" +\n \"using Tailwind CSS utility classes. Return ONLY the HTML — no markdown, no prose.\",\n prompt: `Build a UI mockup for:\\n${input.description}${constraints}`,\n tier: input.tier ?? \"smart\",\n purpose: input.purpose ?? \"contract:mockup\",\n });\n return { html: res.text, usage: res.usage };\n },\n\n async design(input: DesignInput): Promise<DesignResult> {\n const res = await client.vision({\n image: input.screenshot as VisionInput[\"image\"],\n prompt:\n \"You are a design-iteration engine. Given this screenshot, apply the instructions \" +\n `and return a single self-contained HTML document (Tailwind), ONLY the HTML.\\n\\n` +\n `Instructions:\\n${input.instructions}`,\n tier: input.tier ?? \"powerful\",\n purpose: input.purpose ?? \"contract:design\",\n });\n return { html: res.text, usage: res.usage };\n },\n\n async extract<T>(input: ExtractInput<T>): Promise<ExtractResult<T>> {\n const base =\n \"You are a structured-data extractor. Extract the requested data from the text and \" +\n \"return ONLY valid JSON — no markdown, no prose.\" +\n (input.instructions ? `\\n\\n${input.instructions}` : \"\");\n const run = async (reinforce: boolean) => {\n const res = await client.chat({\n system: reinforce ? `${base}\\n\\nYour previous output was not valid JSON. Return ONLY parseable JSON.` : base,\n prompt: input.text,\n tier: input.tier ?? \"smart\",\n purpose: input.purpose ?? \"contract:extract\",\n });\n return res;\n };\n let res = await run(false);\n try {\n return { data: input.schema.parse(parseJsonLoose(res.text)), usage: res.usage };\n } catch {\n // one retry with reinforcement\n res = await run(true);\n return { data: input.schema.parse(parseJsonLoose(res.text)), usage: res.usage };\n }\n },\n\n async classify(input: ClassifyInput): Promise<ClassifyResult> {\n const res = await client.chat({\n system:\n \"You are a zero-shot classifier. Choose exactly one label from the provided list. \" +\n 'Return ONLY JSON: {\"label\": \"<one of the labels>\", \"confidence\": <0..1>}.',\n prompt: `Labels: ${JSON.stringify(input.labels)}\\n\\nText:\\n${input.text}`,\n tier: input.tier ?? \"cheap\",\n purpose: input.purpose ?? \"contract:classify\",\n });\n const parsed = parseJsonLoose(res.text) as { label?: string; confidence?: number };\n const label = input.labels.includes(parsed.label ?? \"\") ? parsed.label! : (input.labels[0] ?? \"\");\n const confidence = typeof parsed.confidence === \"number\" ? parsed.confidence : 0;\n return { label, confidence, usage: res.usage };\n },\n\n async rerank(input: RerankInput): Promise<RerankResult> {\n const res = await client.chat({\n system:\n \"You are a relevance reranker. Score each item 0..1 for relevance to the query and \" +\n 'return ONLY JSON: [{\"item\": \"<verbatim item>\", \"score\": <0..1>}], ordered by score desc.',\n prompt: `Query: ${input.query}\\n\\nItems:\\n${JSON.stringify(input.items)}`,\n tier: input.tier ?? \"fast\",\n purpose: input.purpose ?? \"contract:rerank\",\n });\n const raw = parseJsonLoose(res.text) as { item?: string; score?: number }[];\n const ranked = (Array.isArray(raw) ? raw : [])\n .map((r) => ({ item: String(r.item ?? \"\"), score: typeof r.score === \"number\" ? r.score : 0 }))\n .sort((a, b) => b.score - a.score);\n return { ranked, usage: res.usage };\n },\n };\n}\n","// Zod is the single source of truth for the public input shapes. The TypeScript\n// types are derived via z.infer — no hand-written interface duplicates them.\n// The client .parse()s every input at the boundary, so invalid input throws a\n// ZodError before any provider work happens.\nimport { z } from \"zod\";\nimport type {\n ProviderAdapter,\n CostSink,\n TranslateResult,\n ChatResult,\n ChatStreamEvent,\n ImageResult,\n AnimateResult,\n TrainStyleResult,\n EmbeddingResult,\n TranscribeResult,\n OcrResult,\n ModerationResult,\n PodcastResult,\n BatchRequestItem,\n BatchJob,\n BatchResultItem,\n TierSpec,\n} from \"../types.js\";\nimport type { Contracts } from \"../capabilities/contracts/types.js\";\n\n// ── Reusable sub-schemas ───────────────────────────────────────────────────\n\nexport const transportSchema = z.enum([\"http\", \"subprocess\"]);\n\nexport const tierSchema = z.enum([\n \"fast\",\n \"smart\",\n \"powerful\",\n \"cheap\",\n \"vision\",\n \"video\",\n \"embedding\",\n]);\n\nexport const tierSpecSchema = z.object({\n provider: z.string(),\n model: z.string(),\n transport: transportSchema,\n});\n\nexport const toolSchema = z.object({\n name: z.string(),\n description: z.string(),\n parameters: z.record(z.unknown()),\n});\n\nexport const toolCallSchema = z.object({\n id: z.string(),\n name: z.string(),\n arguments: z.record(z.unknown()),\n});\n\nexport const contentPartSchema = z.union([\n z.object({ type: z.literal(\"text\"), text: z.string() }),\n z.object({\n type: z.literal(\"image\"),\n image: z.union([z.string(), z.instanceof(Uint8Array)]),\n mimeType: z.string().optional(),\n }),\n]);\n\nexport const messageSchema = z.object({\n role: z.enum([\"system\", \"user\", \"assistant\", \"tool\"]),\n content: z.union([z.string(), z.array(contentPartSchema)]),\n toolCalls: z.array(toolCallSchema).optional(),\n toolCallId: z.string().optional(),\n});\n\n/** Per-call options shared by every capability input. */\nconst callOptions = {\n tier: tierSchema.optional(),\n override: tierSpecSchema.partial().optional(),\n fallback: z.array(z.union([tierSchema, tierSpecSchema])).optional(),\n purpose: z.string().optional(),\n /** Consumer-defined attribution dimensions (e.g. {tenantId}) ridden into the\n * cost sink for per-tenant/per-customer cost breakdown (F011). */\n labels: z.record(z.string(), z.string()).optional(),\n} as const;\n\n// ── The 5 capability inputs ────────────────────────────────────────────────\n\nexport const chatInputSchema = z.object({\n prompt: z.string().optional(),\n messages: z.array(messageSchema).optional(),\n system: z.string().optional(),\n tools: z.array(toolSchema).optional(),\n maxTokens: z.number().int().positive().optional(),\n temperature: z.number().min(0).max(2).optional(),\n /** \"json\" requests JSON-object output (OpenAI-compatible response_format). */\n responseFormat: z.enum([\"json\", \"text\"]).optional(),\n ...callOptions,\n});\n\nexport const visionInputSchema = z.object({\n image: z.union([z.string(), z.instanceof(Uint8Array)]),\n prompt: z.string(),\n mimeType: z.string().optional(),\n /** System instruction — drives instruction-following far better than stuffing\n * rules into `prompt` for instruction-heavy vision tasks (e.g. a JSON critic). */\n system: z.string().optional(),\n ...callOptions,\n});\n\n// F019 — analyze a video natively (e.g. \"what's in the first 30s?\"). Same shape\n// as vision but with a video payload (URL, data-URL, or raw bytes).\nexport const videoInputSchema = z.object({\n video: z.union([z.string(), z.instanceof(Uint8Array)]),\n prompt: z.string(),\n mimeType: z.string().optional(),\n /** System instruction — same instruction-following benefit as on vision. */\n system: z.string().optional(),\n ...callOptions,\n});\n\nexport const translateInputSchema = z.object({\n text: z.string(),\n to: z.string(),\n from: z.string().optional(),\n ...callOptions,\n});\n\nexport const loraWeightSchema = z.object({\n path: z.string(),\n scale: z.number().optional(),\n});\n\nexport const imageInputSchema = z.object({\n prompt: z.string(),\n width: z.number().int().positive().optional(),\n height: z.number().int().positive().optional(),\n /** LoRAs to merge at inference (F021). */\n loras: z.array(loraWeightSchema).optional(),\n /** Shorthand for a single LoRA — normalized to loras:[{path, scale:1}]. */\n lora: z.string().optional(),\n /** F023 — a BFL finetune id (subject trained in the BFL dashboard). Routes to the\n * EU-resident BFL finetuned-portrait endpoint. */\n finetune: z.string().optional(),\n /** F023 — BFL finetune_strength (~0–2; higher = stronger likeness). */\n finetuneStrength: z.number().min(0).max(2).optional(),\n /** F023.5 — 1–8 reference photos (URL or raw bytes) → EU-resident BFL FLUX 2\n * multi-reference generation (likeness, no training step). */\n referenceImages: z.array(z.union([z.string(), z.instanceof(Uint8Array)])).min(1).max(8).optional(),\n /** F023.5 — fixed seed for reproducible output (BFL). */\n seed: z.number().int().optional(),\n /** F023.5 — output container (BFL FLUX 2). Default jpeg. */\n outputFormat: z.enum([\"jpeg\", \"png\", \"webp\"]).optional(),\n /** F023.5 — BFL content-moderation strictness, 0 (strict) … 6 (lax). Default 2. */\n safetyTolerance: z.number().int().min(0).max(6).optional(),\n /** F021.4 — re-roll once if fal returns a black image (NSFW false-positive). */\n retryOnBlack: z.boolean().optional(),\n ...callOptions,\n});\n\n// Image-to-video (F024) — animate a still into a short clip via a pluggable provider.\nexport const animateInputSchema = z.object({\n /** Input image: a URL or raw bytes (uploaded to fal storage). */\n image: z.union([z.string(), z.instanceof(Uint8Array)]),\n /** Motion/scene prompt. */\n prompt: z.string().optional(),\n /** Clip length in seconds (provider-dependent; Veo ≤ 8s). */\n durationSec: z.number().positive().optional(),\n /** e.g. \"720p\" / \"1080p\" (provider-dependent). */\n resolution: z.string().optional(),\n ...callOptions,\n});\n\nexport const trainStyleInputSchema = z.object({\n /** A hosted archive URL, or an array of image URLs the SDK zips in-memory. */\n images: z.union([z.string(), z.array(z.string())]),\n /** Style LoRA (disables captioning/masks). Default true. */\n isStyle: z.boolean().optional(),\n triggerWord: z.string().optional(),\n steps: z.number().int().positive().optional(),\n createMasks: z.boolean().optional(),\n ...callOptions,\n});\n\nexport const embeddingInputSchema = z.object({\n text: z.union([z.string(), z.array(z.string())]),\n ...callOptions,\n});\n\nexport const transcribeInputSchema = z.object({\n /** Audio URL or raw bytes. */\n audio: z.union([z.string(), z.instanceof(Uint8Array)]),\n language: z.string().optional(),\n /** Audio length in seconds — enables Whisper per-minute cost. */\n durationSec: z.number().positive().optional(),\n /** Bias toward brand/jargon terms (Azure phraseList, F029.3); others ignore it. */\n phrases: z.array(z.string()).optional(),\n ...callOptions,\n});\n\n// OCR (F016.2) — document/image → structured markdown text, billed per page.\nexport const ocrInputSchema = z.object({\n /** A URL, data-URL, or raw bytes of the document/image. */\n document: z.union([z.string(), z.instanceof(Uint8Array)]),\n /** image/* → routed as an image; anything else → a document (PDF etc.). */\n mimeType: z.string().optional(),\n ...callOptions,\n});\n\n// Moderation (F016.4) — classify text against safety categories, billed per token.\nexport const moderationInputSchema = z.object({\n input: z.union([z.string(), z.array(z.string())]),\n ...callOptions,\n});\n\n// Podcast (F020) — a finished manuscript (speaker turns) + a speaker→voiceId map →\n// one finished multi-voice audio episode (ElevenLabs Text-to-Dialogue).\nexport const podcastInputSchema = z.object({\n script: z.array(z.object({ speaker: z.string(), text: z.string() })).min(1),\n voices: z.record(z.string(), z.string()),\n format: z.string().optional(),\n ...callOptions,\n});\n\n// Single-voice TTS (F020.4) — text → audio. `voice` is a curated name or a voiceId.\n// `lang`/`format` (F026) are used by the Azure adapter; ElevenLabs ignores them.\nexport const ttsInputSchema = z.object({\n text: z.string(),\n voice: z.string(),\n lang: z.string().optional(),\n format: z.string().optional(),\n rate: z.number().positive().optional(),\n ...callOptions,\n});\n\n// ── Client config ──────────────────────────────────────────────────────────\n\nexport const budgetSchema = z.object({\n perCallUsd: z.number().positive().optional(),\n rollingUsd: z.number().positive().optional(),\n});\n\n/** F022 — opt-in proactive availability gate. Off by default so existing call\n * sites are byte-identical. When autoResolve is on, a suspended primary model\n * is transparently swapped to `fallback` before dispatch (synchronous, no I/O). */\nexport const availabilitySchema = z.object({\n autoResolve: z.boolean().optional(),\n fallback: z.union([z.string(), z.array(z.string())]).optional(),\n});\n\nexport const aiConfigSchema = z.object({\n defaults: z.record(tierSchema, tierSpecSchema).optional(),\n // Functions can't be deeply validated — z.custom asserts the TS type and\n // passes the value through untouched.\n providers: z.record(z.string(), z.custom<ProviderAdapter>()).optional(),\n costSink: z.custom<CostSink>().optional(),\n budget: budgetSchema.optional(),\n availability: availabilitySchema.optional(),\n});\n\n// ── Derived types (z.infer is the single source) ───────────────────────────\n\nexport type ChatInput = z.infer<typeof chatInputSchema>;\nexport type VisionInput = z.infer<typeof visionInputSchema>;\nexport type VideoInput = z.infer<typeof videoInputSchema>;\nexport type TranslateInput = z.infer<typeof translateInputSchema>;\nexport type ImageInput = z.infer<typeof imageInputSchema>;\nexport type AnimateInput = z.infer<typeof animateInputSchema>;\nexport type TrainStyleInput = z.infer<typeof trainStyleInputSchema>;\nexport type EmbeddingInput = z.infer<typeof embeddingInputSchema>;\nexport type TranscribeInput = z.infer<typeof transcribeInputSchema>;\nexport type OcrInput = z.infer<typeof ocrInputSchema>;\nexport type ModerationInput = z.infer<typeof moderationInputSchema>;\nexport type PodcastInput = z.infer<typeof podcastInputSchema>;\nexport type TtsInput = z.infer<typeof ttsInputSchema>;\nexport type AiConfig = z.infer<typeof aiConfigSchema>;\n\n/** The public facade. Defined here because it depends on the derived inputs. */\nexport interface AiClient {\n chat(input: ChatInput): Promise<ChatResult>;\n /** Streaming chat (F8) — same input as chat; yields ChatStreamEvents. The\n * caller owns the tool-loop (per-turn engine, not an agent runtime). */\n chatStream(input: ChatInput): AsyncIterable<ChatStreamEvent>;\n vision(input: VisionInput): Promise<ChatResult>;\n /** Video Vision (F019) — analyze a video natively. Default tier: \"video\". */\n video(input: VideoInput): Promise<ChatResult>;\n translate(input: TranslateInput): Promise<TranslateResult>;\n image(input: ImageInput): Promise<ImageResult>;\n /** Image-to-video (F024) — animate a still into a short clip → { url, usage }. fal. */\n animate(input: AnimateInput): Promise<AnimateResult>;\n /** Train a style/brand LoRA from images (F021) → { loraUrl, configUrl }. fal. */\n trainStyle(input: TrainStyleInput): Promise<TrainStyleResult>;\n embedding(input: EmbeddingInput): Promise<EmbeddingResult>;\n transcribe(input: TranscribeInput): Promise<TranscribeResult>;\n /** OCR (F016.2) — document/image → structured markdown, billed per page. Mistral. */\n ocr(input: OcrInput): Promise<OcrResult>;\n /** Moderation (F016.4) — classify text against safety categories. Mistral. */\n moderate(input: ModerationInput): Promise<ModerationResult>;\n /** Podcast (F020) — a finished manuscript → one multi-voice audio episode. ElevenLabs. */\n podcast(input: PodcastInput): Promise<PodcastResult>;\n /** Single-voice TTS (F020.4) — text → audio. `voice` = curated name or voiceId. ElevenLabs. */\n tts(input: TtsInput): Promise<PodcastResult>;\n /** Batch (F016.1) — submit many chat requests for async (≤24h) processing at 50% cost. Mistral. */\n batch: {\n submit(input: { requests: BatchRequestItem[]; override?: TierSpec }): Promise<BatchJob>;\n status(jobId: string, override?: TierSpec): Promise<BatchJob>;\n results(jobId: string, override?: TierSpec): Promise<BatchResultItem[]>;\n };\n /** Prompt-contract capabilities (F5.5) layered on chat/vision. */\n contracts: Contracts;\n}\n","// createAI() — the facade factory. Resolves routing, picks a provider adapter,\n// delegates the call, stamps call-context metadata onto Usage, and reports to the\n// cost sink. Provider specifics live in adapters; cost compute/budget land in F3.\nimport { resolveTier } from \"./routing/tier-map.js\";\nimport { resolveModel } from \"./availability/resolve.js\";\nimport { defaultProviders } from \"./providers/registry.js\";\nimport { computeCost } from \"./cost/usage.js\";\nimport { BudgetGuard } from \"./cost/budget.js\";\nimport { buildVisionMessages, VISION_DEFAULT_TIER } from \"./capabilities/vision.js\";\nimport { buildVideoMessages, VIDEO_DEFAULT_TIER } from \"./capabilities/video.js\";\nimport { buildTranslateMessages, TRANSLATE_DEFAULT_TIER } from \"./capabilities/translate.js\";\nimport { EMBEDDING_DEFAULT_TIER } from \"./capabilities/embedding.js\";\nimport { DEFAULT_TRANSCRIBE_SPEC, resolveAudio } from \"./capabilities/transcribe.js\";\nimport { makeContracts } from \"./capabilities/contracts/index.js\";\nimport { resolveVoice } from \"./providers/elevenlabs.js\";\nimport {\n aiConfigSchema,\n chatInputSchema,\n visionInputSchema,\n videoInputSchema,\n translateInputSchema,\n imageInputSchema,\n animateInputSchema,\n trainStyleInputSchema,\n embeddingInputSchema,\n transcribeInputSchema,\n ocrInputSchema,\n moderationInputSchema,\n podcastInputSchema,\n ttsInputSchema,\n} from \"./schema/inputs.js\";\nimport type {\n AiConfig,\n AiClient,\n ChatInput,\n VisionInput,\n VideoInput,\n TranslateInput,\n ImageInput,\n AnimateInput,\n TrainStyleInput,\n EmbeddingInput,\n TranscribeInput,\n OcrInput,\n ModerationInput,\n PodcastInput,\n TtsInput,\n} from \"./schema/inputs.js\";\nimport type {\n ChatResult,\n ChatStreamEvent,\n ImageResult,\n AnimateResult,\n TrainStyleResult,\n EmbeddingResult,\n TranscribeResult,\n OcrResult,\n ModerationResult,\n PodcastResult,\n BatchRequestItem,\n BatchJob,\n BatchResultItem,\n TranslateResult,\n ProviderAdapter,\n Message,\n Capability,\n Tier,\n TierSpec,\n Usage,\n} from \"./types.js\";\n\n/** Built-in image route (no image tier in the tier map — fal owns its routing). */\nconst DEFAULT_IMAGE_SPEC: TierSpec = {\n provider: \"fal\",\n model: \"fal-ai/flux/schnell\",\n transport: \"http\",\n};\n/** LoRA-inference route (F021) — used by ai.image when loras are supplied. */\nconst DEFAULT_LORA_IMAGE_SPEC: TierSpec = {\n provider: \"fal\",\n model: \"fal-ai/flux-lora\",\n transport: \"http\",\n};\n/** Style-LoRA training route (F021) — fal flux-lora-fast-training. */\nconst DEFAULT_TRAINSTYLE_SPEC: TierSpec = {\n provider: \"fal\",\n model: \"fal-ai/flux-lora-fast-training\",\n transport: \"http\",\n};\n/** Image-to-video route (F024) — Veo 3.1 DIRECT via the Gemini API (no fal markup,\n * our existing GEMINI_API_KEY, and the path to EU via Vertex later). Override to\n * {provider:\"fal\", model:\"fal-ai/veo3.1/...\"} for the aggregator / other models\n * (Kling, Seedance). US-hosted: consent-gated use (F024). */\nconst DEFAULT_ANIMATE_SPEC: TierSpec = {\n provider: \"gemini\",\n model: \"veo-3.1-generate-preview\",\n transport: \"http\",\n};\n/** Default audio directive appended to every ai.animate prompt (F024, Christian's\n * preference): no generated speech (it's the weak link, esp. non-English), but\n * ambient sounds matched to the scene are wanted. A soft prompt instruction. */\nconst ANIMATE_AUDIO_DIRECTIVE =\n \"No spoken dialogue, no talking, no voiceover. Include natural ambient background sounds that match the environment.\";\n/** EU-resident finetuned-portrait route (F023) — BFL, used by ai.image when a\n * `finetune` id is supplied. Hard-pinned to api.eu.bfl.ai inside the adapter. */\nconst DEFAULT_BFL_FINETUNE_SPEC: TierSpec = {\n provider: \"bfl\",\n model: \"flux-pro-1.1-ultra-finetuned\",\n transport: \"http\",\n};\n/** EU-resident multi-reference route (F023.5) — BFL FLUX 2, used by ai.image when\n * `referenceImages` are supplied (likeness with no training step). flux-2-max =\n * premium-quality default; override to flux-2-pro/flex for volume. EU-pinned. */\nconst DEFAULT_BFL_REFERENCE_SPEC: TierSpec = {\n provider: \"bfl\",\n model: \"flux-2-max\",\n transport: \"http\",\n};\n\n/** OCR + moderation are Mistral specialty endpoints (F016) — no tier, route by default. */\nconst DEFAULT_OCR_SPEC: TierSpec = { provider: \"mistral\", model: \"mistral-ocr-latest\", transport: \"http\" };\nconst DEFAULT_MODERATION_SPEC: TierSpec = { provider: \"mistral\", model: \"mistral-moderation-latest\", transport: \"http\" };\n/** Podcast route (F020) — ElevenLabs Text-to-Dialogue, eleven_v3 (multi-voice, multilingual). */\nconst DEFAULT_PODCAST_SPEC: TierSpec = { provider: \"elevenlabs\", model: \"eleven_v3\", transport: \"http\" };\n/** Single-voice TTS route (F020.4) — ElevenLabs eleven_multilingual_v2 (good Danish). */\nconst DEFAULT_TTS_SPEC: TierSpec = { provider: \"elevenlabs\", model: \"eleven_multilingual_v2\", transport: \"http\" };\n/** Batch route (F016.1) — Mistral batch jobs (50% cost), cheap default model. */\nconst DEFAULT_BATCH_SPEC: TierSpec = { provider: \"mistral\", model: \"mistral-small-latest\", transport: \"http\" };\n\nexport function createAI(config: AiConfig = {}): AiClient {\n // Validate config at the boundary (throws ZodError on bad shape).\n const cfg = aiConfigSchema.parse(config);\n const providers = cfg.providers ?? defaultProviders;\n const budget = cfg.budget ? new BudgetGuard(cfg.budget) : undefined;\n\n const estTokens = (s: string): number => Math.ceil(s.length / 4);\n\n /** Pre-flight budget check. Estimates this call's cost and throws\n * BudgetExceededError before the transport fires. No-op without a budget. */\n async function preflight(spec: TierSpec, estInTokens: number, estOutTokens: number): Promise<void> {\n if (!budget) return;\n await budget.check(computeCost(spec.provider, spec.model, estInTokens, estOutTokens));\n }\n\n /** Fold the actual cost into the rolling total after a successful call. */\n async function settle(usage: Usage): Promise<void> {\n if (budget) await budget.record(usage.costUsd);\n }\n\n function pickProvider(name: string): ProviderAdapter {\n const adapter = providers[name];\n if (!adapter) {\n throw new Error(\n `createAI: no provider adapter registered for \"${name}\". Registered: ${Object.keys(providers).join(\", \") || \"(none)\"}`,\n );\n }\n return adapter;\n }\n\n /** Stamp call-context metadata the client owns onto the adapter's Usage:\n * capability, tier, purpose, the wall-clock latency, and the timestamp. */\n function enrich(\n usage: Usage,\n capability: Capability,\n tier: Tier | undefined,\n purpose: string | undefined,\n latencyMs: number,\n labels: Record<string, string> | undefined,\n ): Usage {\n usage.capability = capability;\n if (tier) usage.tier = tier;\n if (purpose) usage.purpose = purpose;\n if (labels && Object.keys(labels).length > 0) usage.labels = labels;\n usage.latencyMs = Math.round(latencyMs);\n if (!usage.ts) usage.ts = new Date().toISOString();\n return usage;\n }\n\n async function report(usage: Usage): Promise<void> {\n if (!cfg.costSink) return;\n try {\n await cfg.costSink.record(usage);\n } catch {\n // A broken sink must never crash a real AI call (F3.3 invariant).\n }\n }\n\n function toMessages(input: ChatInput): Message[] {\n if (input.messages && input.messages.length > 0) {\n // A top-level `system` must survive when `messages` is also supplied — prepend\n // it (unless the caller already leads with a system message) instead of\n // silently dropping it. Regression: system + messages → system was lost, so a\n // \"return ONLY JSON\" system instruction never reached the model (cms #4234).\n if (input.system && input.messages[0]?.role !== \"system\") {\n return [{ role: \"system\", content: input.system }, ...input.messages];\n }\n return input.messages;\n }\n const msgs: Message[] = [];\n if (input.system) msgs.push({ role: \"system\", content: input.system });\n msgs.push({ role: \"user\", content: input.prompt ?? \"\" });\n return msgs;\n }\n\n /** F022 — opt-in proactive availability gate. When cfg.availability.autoResolve\n * is set, swap a known-suspended primary model to its configured fallback\n * BEFORE dispatch (synchronous, registry-only — no I/O). Default off → the\n * spec is returned untouched and behaviour is byte-identical. This sits in\n * front of the reactive route-fallback below. */\n function applyAvailability(spec: TierSpec): TierSpec {\n if (!cfg.availability?.autoResolve) return spec;\n const r = resolveModel(spec.model, { fallback: cfg.availability.fallback, provider: spec.provider });\n return r.fellBack ? { ...spec, model: r.model } : spec;\n }\n\n /** Run a capability with an optional fallback chain. Tries the primary route,\n * then each fallback (Tier or TierSpec) in order if the call errors. A budget\n * breach propagates immediately (not a fallback trigger). On the first\n * success: stamp Usage, settle the budget, report to the sink, return. */\n async function runCapability<R extends { usage: Usage }>(opts: {\n primary: TierSpec;\n fallback?: (Tier | TierSpec)[];\n capability: Capability;\n tier?: Tier;\n purpose?: string;\n labels?: Record<string, string>;\n estIn: number;\n estOut: number;\n invoke: (spec: TierSpec) => Promise<R>;\n }): Promise<R> {\n const routes: TierSpec[] = [\n applyAvailability(opts.primary),\n ...(opts.fallback ?? []).map((f) =>\n typeof f === \"string\" ? resolveTier(f, undefined, cfg.defaults) : f,\n ),\n ];\n let lastErr: unknown;\n for (let i = 0; i < routes.length; i++) {\n const spec = routes[i]!;\n await preflight(spec, opts.estIn, opts.estOut); // BudgetExceededError propagates\n try {\n const t0 = performance.now();\n const res = await opts.invoke(spec);\n enrich(res.usage, opts.capability, i === 0 ? opts.tier : undefined, opts.purpose, performance.now() - t0, opts.labels);\n await settle(res.usage);\n await report(res.usage);\n return res;\n } catch (e) {\n lastErr = e; // try the next fallback route\n }\n }\n throw lastErr;\n }\n\n /** Whether a pre-first-token streaming error should fall back to the next\n * route. Eligible: network/timeout/parse (no status) + 429 + 5xx. Hard 4xx\n * bubbles up (no silent re-route) — sa contract #2565. */\n function eligibleForFallback(e: unknown): boolean {\n const status = (e as { status?: number } | null)?.status;\n if (status === undefined) return true;\n return status === 429 || status >= 500;\n }\n\n function errorEvent(e: unknown): ChatStreamEvent {\n const ev: ChatStreamEvent = {\n type: \"error\",\n message: e instanceof Error ? e.message : String(e),\n };\n const status = (e as { status?: number } | null)?.status;\n if (status !== undefined) ev.status = status;\n return ev;\n }\n\n /** Streaming chat with pre-stream fallback (F8.1). Yields ChatStreamEvents as\n * the turn unfolds. Fallback re-routes only BEFORE the first text/tool_call\n * event (deltas can't be un-emitted); once streaming has begun, an error is\n * surfaced as an error event and the stream ends. Budget breaches propagate. */\n async function* chatStreamImpl(input: ChatInput): AsyncIterable<ChatStreamEvent> {\n input = chatInputSchema.parse(input);\n const tier = input.tier ?? \"smart\";\n const messages = toMessages(input);\n const estIn = messages.reduce(\n (n, m) => n + estTokens(typeof m.content === \"string\" ? m.content : JSON.stringify(m.content)),\n 0,\n );\n const estOut = input.maxTokens ?? 512;\n const routes: TierSpec[] = [\n resolveTier(tier, input.override, cfg.defaults),\n ...(input.fallback ?? []).map((f) =>\n typeof f === \"string\" ? resolveTier(f, undefined, cfg.defaults) : f,\n ),\n ];\n\n let lastErr: unknown;\n for (let i = 0; i < routes.length; i++) {\n const spec = routes[i]!;\n await preflight(spec, estIn, estOut); // BudgetExceededError propagates\n const adapter = pickProvider(spec.provider);\n if (!adapter.chatStream) {\n throw new Error(`createAI: provider \"${spec.provider}\" does not support streaming`);\n }\n const t0 = performance.now();\n let emitted = false;\n try {\n for await (const ev of adapter.chatStream({\n messages,\n spec,\n tools: input.tools,\n maxTokens: input.maxTokens,\n temperature: input.temperature,\n responseFormat: input.responseFormat,\n })) {\n if (ev.type === \"text\" || ev.type === \"tool_call\") emitted = true;\n if (ev.type === \"usage\") {\n enrich(ev.usage, \"chat\", i === 0 ? tier : undefined, input.purpose, performance.now() - t0, input.labels);\n await settle(ev.usage);\n await report(ev.usage);\n }\n yield ev;\n }\n return; // stream completed cleanly\n } catch (e) {\n lastErr = e;\n if (emitted || !eligibleForFallback(e)) {\n yield errorEvent(e); // mid-stream or hard error → surface + stop\n return;\n }\n // pre-first-token eligible error → try the next route\n }\n }\n yield errorEvent(lastErr);\n }\n\n const client: AiClient = {\n async chat(input: ChatInput): Promise<ChatResult> {\n input = chatInputSchema.parse(input);\n const tier = input.tier ?? \"smart\";\n const messages = toMessages(input);\n const estIn = messages.reduce(\n (n, m) => n + estTokens(typeof m.content === \"string\" ? m.content : JSON.stringify(m.content)),\n 0,\n );\n return runCapability({\n primary: resolveTier(tier, input.override, cfg.defaults),\n fallback: input.fallback,\n capability: \"chat\",\n tier,\n purpose: input.purpose,\n labels: input.labels,\n estIn,\n estOut: input.maxTokens ?? 512,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.chat) throw new Error(`createAI: provider \"${spec.provider}\" does not support chat`);\n return adapter.chat({ messages, spec, tools: input.tools, maxTokens: input.maxTokens, temperature: input.temperature, responseFormat: input.responseFormat });\n },\n });\n },\n\n chatStream: chatStreamImpl,\n\n async vision(input: VisionInput): Promise<ChatResult> {\n input = visionInputSchema.parse(input);\n const tier = input.tier ?? VISION_DEFAULT_TIER;\n const messages: Message[] = buildVisionMessages(input);\n return runCapability({\n primary: resolveTier(tier, input.override, cfg.defaults),\n fallback: input.fallback,\n capability: \"vision\",\n tier,\n purpose: input.purpose,\n labels: input.labels,\n estIn: estTokens(input.prompt) + 1000, // prompt + ~1k image payload\n estOut: 512,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.vision) throw new Error(`createAI: provider \"${spec.provider}\" does not support vision`);\n return adapter.vision({ messages, spec });\n },\n });\n },\n\n async video(input: VideoInput): Promise<ChatResult> {\n input = videoInputSchema.parse(input);\n const tier = input.tier ?? VIDEO_DEFAULT_TIER;\n const messages: Message[] = buildVideoMessages(input);\n return runCapability({\n primary: resolveTier(tier, input.override, cfg.defaults),\n fallback: input.fallback,\n capability: \"video\",\n tier,\n purpose: input.purpose,\n labels: input.labels,\n estIn: estTokens(input.prompt) + 4000, // prompt + video tokens (native video ≈ frames)\n estOut: 512,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n // Video routes through the vision method — same multimodal message path.\n if (!adapter.vision) throw new Error(`createAI: provider \"${spec.provider}\" does not support video`);\n return adapter.vision({ messages, spec });\n },\n });\n },\n\n async translate(input: TranslateInput): Promise<TranslateResult> {\n input = translateInputSchema.parse(input);\n const tier = input.tier ?? TRANSLATE_DEFAULT_TIER;\n const messages: Message[] = buildTranslateMessages(input);\n const estIn = estTokens(input.text) + 40;\n const res = await runCapability<TranslateResult>({\n primary: resolveTier(tier, input.override, cfg.defaults),\n fallback: input.fallback,\n capability: \"translate\",\n tier,\n purpose: input.purpose,\n labels: input.labels,\n estIn,\n estOut: estIn,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n // A dedicated translation engine (F032, e.g. DeepL) is preferred when the\n // resolved provider implements it — its `to`/`from` are provider-specific\n // codes, not the free-form names the chat prompt-contract accepts.\n if (adapter.translate) return adapter.translate({ text: input.text, to: input.to, from: input.from, spec });\n if (!adapter.chat) throw new Error(`createAI: provider \"${spec.provider}\" does not support chat (translate routes through chat)`);\n return adapter.chat({ messages, spec });\n },\n });\n return { text: res.text, usage: res.usage };\n },\n\n async image(input: ImageInput): Promise<ImageResult> {\n input = imageInputSchema.parse(input);\n // Normalize the `lora` shorthand into the loras array.\n const loras = [\n ...(input.loras ?? []),\n ...(input.lora ? [{ path: input.lora }] : []),\n ];\n // Route by what's supplied (override still wins): `referenceImages` → the EU\n // BFL FLUX 2 multi-reference endpoint (F023.5, no training step); a `finetune`\n // id → the EU BFL finetuned-portrait endpoint (F023); LoRAs → flux-lora (F021,\n // flux/schnell can't merge LoRAs); else the plain image route.\n const base = input.referenceImages?.length\n ? DEFAULT_BFL_REFERENCE_SPEC\n : input.finetune\n ? DEFAULT_BFL_FINETUNE_SPEC\n : loras.length > 0\n ? DEFAULT_LORA_IMAGE_SPEC\n : DEFAULT_IMAGE_SPEC;\n return runCapability({\n primary: { ...base, ...input.override },\n fallback: input.fallback,\n capability: \"image\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: 0, // image cost is not token-based\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.image) throw new Error(`createAI: provider \"${spec.provider}\" does not support image`);\n return adapter.image({\n prompt: input.prompt,\n spec,\n width: input.width,\n height: input.height,\n loras: loras.length ? loras : undefined,\n finetune: input.finetune,\n finetuneStrength: input.finetuneStrength,\n referenceImages: input.referenceImages,\n seed: input.seed,\n outputFormat: input.outputFormat,\n safetyTolerance: input.safetyTolerance,\n retryOnBlack: input.retryOnBlack,\n });\n },\n });\n },\n\n async animate(input: AnimateInput): Promise<AnimateResult> {\n input = animateInputSchema.parse(input);\n // Append the default audio directive (no speech, ambient sounds matched to scene).\n const prompt = input.prompt?.trim()\n ? `${input.prompt.trim()} ${ANIMATE_AUDIO_DIRECTIVE}`\n : ANIMATE_AUDIO_DIRECTIVE;\n return runCapability({\n primary: { ...DEFAULT_ANIMATE_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"animate\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: 0, // video cost is per-second, not token-based\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.animate) throw new Error(`createAI: provider \"${spec.provider}\" does not support animate`);\n return adapter.animate({\n image: input.image,\n prompt,\n durationSec: input.durationSec,\n resolution: input.resolution,\n spec,\n });\n },\n });\n },\n\n async trainStyle(input: TrainStyleInput): Promise<TrainStyleResult> {\n input = trainStyleInputSchema.parse(input);\n return runCapability({\n primary: { ...DEFAULT_TRAINSTYLE_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"trainStyle\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: 0, // training is priced flat by fal, not token-based\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.trainStyle)\n throw new Error(`createAI: provider \"${spec.provider}\" does not support trainStyle`);\n return adapter.trainStyle({\n images: input.images,\n spec,\n isStyle: input.isStyle,\n triggerWord: input.triggerWord,\n steps: input.steps,\n createMasks: input.createMasks,\n });\n },\n });\n },\n\n async ocr(input: OcrInput): Promise<OcrResult> {\n input = ocrInputSchema.parse(input);\n return runCapability({\n primary: { ...DEFAULT_OCR_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"ocr\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: 0, // OCR cost is per-page, not token-based\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.ocr) throw new Error(`createAI: provider \"${spec.provider}\" does not support ocr`);\n return adapter.ocr({ document: input.document, mimeType: input.mimeType, spec });\n },\n });\n },\n\n async moderate(input: ModerationInput): Promise<ModerationResult> {\n input = moderationInputSchema.parse(input);\n const items = Array.isArray(input.input) ? input.input : [input.input];\n return runCapability({\n primary: { ...DEFAULT_MODERATION_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"moderation\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: items.reduce((n, s) => n + estTokens(s), 0),\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.moderate) throw new Error(`createAI: provider \"${spec.provider}\" does not support moderation`);\n return adapter.moderate({ input: items, spec });\n },\n });\n },\n\n async podcast(input: PodcastInput): Promise<PodcastResult> {\n input = podcastInputSchema.parse(input);\n // Map each manuscript turn to a {text, voiceId} dialogue input.\n const inputs = input.script.map((turn) => {\n const mapped = input.voices[turn.speaker];\n if (!mapped) throw new Error(`ai.podcast: no voice mapped for speaker \"${turn.speaker}\"`);\n return { text: turn.text, voiceId: resolveVoice(mapped) }; // curated name → voiceId\n });\n const chars = input.script.reduce((n, t) => n + t.text.length, 0);\n return runCapability({\n primary: { ...DEFAULT_PODCAST_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"podcast\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: chars, // per-character cost (not token-based)\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.dialogue) throw new Error(`createAI: provider \"${spec.provider}\" does not support podcast/dialogue`);\n return adapter.dialogue({ inputs, format: input.format, spec });\n },\n });\n },\n\n async tts(input: TtsInput): Promise<PodcastResult> {\n input = ttsInputSchema.parse(input);\n return runCapability({\n primary: { ...DEFAULT_TTS_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"tts\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: input.text.length, // per-character cost\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.tts) throw new Error(`createAI: provider \"${spec.provider}\" does not support tts`);\n return adapter.tts({ text: input.text, voiceId: resolveVoice(input.voice), lang: input.lang, format: input.format, rate: input.rate, spec });\n },\n });\n },\n\n async embedding(input: EmbeddingInput): Promise<EmbeddingResult> {\n input = embeddingInputSchema.parse(input);\n const tier = input.tier ?? EMBEDDING_DEFAULT_TIER;\n const text = Array.isArray(input.text) ? input.text : [input.text];\n return runCapability({\n primary: resolveTier(tier, input.override, cfg.defaults),\n fallback: input.fallback,\n capability: \"embedding\",\n tier,\n purpose: input.purpose,\n labels: input.labels,\n estIn: text.reduce((n, t) => n + estTokens(t), 0),\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.embedding) throw new Error(`createAI: provider \"${spec.provider}\" does not support embedding`);\n return adapter.embedding({ input: text, spec });\n },\n });\n },\n\n async transcribe(input: TranscribeInput): Promise<TranscribeResult> {\n input = transcribeInputSchema.parse(input);\n const audio = await resolveAudio(input.audio);\n return runCapability({\n primary: { ...DEFAULT_TRANSCRIBE_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"transcribe\",\n purpose: input.purpose,\n labels: input.labels,\n estIn: 0,\n estOut: 0,\n invoke: async (spec) => {\n const adapter = pickProvider(spec.provider);\n if (!adapter.transcribe) throw new Error(`createAI: provider \"${spec.provider}\" does not support transcribe`);\n return adapter.transcribe({ audio, language: input.language, durationSec: input.durationSec, phrases: input.phrases, spec });\n },\n });\n },\n\n batch: {\n async submit(input: { requests: BatchRequestItem[]; override?: TierSpec }): Promise<BatchJob> {\n const spec = { ...DEFAULT_BATCH_SPEC, ...input.override };\n const adapter = pickProvider(spec.provider);\n if (!adapter.batchSubmit) throw new Error(`createAI: provider \"${spec.provider}\" does not support batch`);\n return adapter.batchSubmit({ items: input.requests, spec });\n },\n async status(jobId: string, override?: TierSpec): Promise<BatchJob> {\n const spec = { ...DEFAULT_BATCH_SPEC, ...override };\n const adapter = pickProvider(spec.provider);\n if (!adapter.batchStatus) throw new Error(`createAI: provider \"${spec.provider}\" does not support batch`);\n return adapter.batchStatus({ jobId, spec });\n },\n async results(jobId: string, override?: TierSpec): Promise<BatchResultItem[]> {\n const spec = { ...DEFAULT_BATCH_SPEC, ...override };\n const adapter = pickProvider(spec.provider);\n if (!adapter.batchResults) throw new Error(`createAI: provider \"${spec.provider}\" does not support batch`);\n return adapter.batchResults({ jobId, spec });\n },\n },\n\n // Replaced below with the real prompt-contracts (needs the client itself).\n contracts: undefined as unknown as AiClient[\"contracts\"],\n };\n\n client.contracts = makeContracts(client);\n return client;\n}\n","// Stub provider adapters (F2.5). They satisfy ProviderAdapter so the client wires\n// up and resolves without real network calls. Real implementations land in F4\n// (anthropic/openai/gemini/openrouter/deepinfra) and F5.3 (fal image). The stub\n// usage carries zero tokens/cost — F3.1 fills real numbers in the live adapters.\nimport type {\n ProviderAdapter,\n ChatRequest,\n ChatResult,\n ImageRequest,\n ImageResult,\n EmbeddingRequest,\n EmbeddingResult,\n Usage,\n Capability,\n} from \"../types.js\";\n\nfunction stubUsage(\n provider: string,\n model: string,\n transport: \"http\" | \"subprocess\",\n capability: Capability,\n): Usage {\n return {\n provider,\n model,\n transport,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheCreationTokens: 0,\n costUsd: 0,\n latencyMs: 0,\n capability,\n // ts is supplied by the caller-side at real call time; stub uses a fixed marker\n // ('' avoids Date.now() — keeps the stub pure/deterministic for tests).\n ts: \"\",\n };\n}\n\nfunction lastUserText(req: ChatRequest): string {\n for (let i = req.messages.length - 1; i >= 0; i--) {\n const m = req.messages[i];\n if (m && m.role === \"user\") {\n return typeof m.content === \"string\"\n ? m.content\n : m.content.map((p) => (p.type === \"text\" ? p.text : \"[image]\")).join(\" \");\n }\n }\n return \"\";\n}\n\n/** Anthropic adapter stub (HTTP path). */\nexport const anthropicApiAdapter: ProviderAdapter = {\n name: \"anthropic\",\n async chat(req: ChatRequest): Promise<ChatResult> {\n return {\n text: `[stub:anthropic-api] ${lastUserText(req)}`,\n usage: stubUsage(\"anthropic\", req.spec.model, \"http\", \"chat\"),\n };\n },\n async vision(req: ChatRequest): Promise<ChatResult> {\n return {\n text: `[stub:anthropic-api:vision] ${lastUserText(req)}`,\n usage: stubUsage(\"anthropic\", req.spec.model, \"http\", \"vision\"),\n };\n },\n};\n\n/** Anthropic adapter stub (subprocess / `claude -p` path). */\nexport const anthropicSubprocessAdapter: ProviderAdapter = {\n name: \"anthropic\",\n async chat(req: ChatRequest): Promise<ChatResult> {\n const usage = stubUsage(\"anthropic\", req.spec.model, \"subprocess\", \"chat\");\n usage.subprocess = true;\n return { text: `[stub:anthropic-subprocess] ${lastUserText(req)}`, usage };\n },\n};\n\n/** Mistral adapter stub — covers the default text/vision tiers (F030: fast/smart/\n * powerful/vision/cheap all default to Mistral EU after the Anthropic phase-out). */\nexport const mistralStubAdapter: ProviderAdapter = {\n name: \"mistral\",\n async chat(req: ChatRequest): Promise<ChatResult> {\n return {\n text: `[stub:mistral] ${lastUserText(req)}`,\n usage: stubUsage(\"mistral\", req.spec.model, \"http\", \"chat\"),\n };\n },\n async vision(req: ChatRequest): Promise<ChatResult> {\n return {\n text: `[stub:mistral:vision] ${lastUserText(req)}`,\n usage: stubUsage(\"mistral\", req.spec.model, \"http\", \"vision\"),\n };\n },\n};\n\n/** OpenAI adapter stub — covers the embedding default tier + a chat fallback. */\nexport const openaiStubAdapter: ProviderAdapter = {\n name: \"openai\",\n async chat(req: ChatRequest): Promise<ChatResult> {\n return {\n text: `[stub:openai] ${lastUserText(req)}`,\n usage: stubUsage(\"openai\", req.spec.model, \"http\", \"chat\"),\n };\n },\n async embedding(req: EmbeddingRequest): Promise<EmbeddingResult> {\n return {\n vectors: req.input.map(() => [0, 0, 0]),\n usage: stubUsage(\"openai\", req.spec.model, \"http\", \"embedding\"),\n };\n },\n};\n\n/** fal.ai adapter stub — image generation (real one in fal.ts, F5.3). */\nexport const falStubAdapter: ProviderAdapter = {\n name: \"fal\",\n async image(req: ImageRequest): Promise<ImageResult> {\n return {\n url: `https://stub.fal/${encodeURIComponent(req.prompt).slice(0, 32)}.png`,\n usage: stubUsage(\"fal\", req.spec.model, \"http\", \"image\"),\n };\n },\n};\n\n/** Stub provider registry — deterministic, no network. Used by tests via\n * createAI({ providers: stubProviders }). The real default registry (registry.ts)\n * wires the live adapters. */\nexport const stubProviders: Record<string, ProviderAdapter> = {\n anthropic: anthropicApiAdapter,\n mistral: mistralStubAdapter,\n openai: openaiStubAdapter,\n fal: falStubAdapter,\n};\n","// AUTO-GENERATED by scripts/gen-version.mjs — do not edit, do not commit.\nexport const VERSION = \"0.23.0\" as const;\nexport const SDK_TAG = \"@broberg/ai-sdk@0.23.0\" as const;\n","// F022 — async, off-the-hot-path availability refresh. The host runs this\n// out-of-band (a timer / at idle); it mutates the registry overlay so the next\n// synchronous resolveModel() sees overnight changes like the 2026-06-12 Fable /\n// Mythos suspension. NEVER on the resolve hot path. Never hard-fails the SDK:\n// a network/auth error keeps the curated defaults.\nimport { providerIds, setAvailability } from \"./registry.js\";\n\nexport interface RefreshOptions {\n /** Only \"anthropic\" is wired in v1 (where the incident hit). */\n provider?: \"anthropic\";\n /** Injectable for tests. Defaults to global fetch. */\n fetch?: typeof fetch;\n /** Defaults to process.env.ANTHROPIC_API_KEY. */\n apiKey?: string;\n /** Min ms between live fetches for a provider (default 1h). */\n ttlMs?: number;\n /** Injectable clock for deterministic TTL tests. Defaults to Date.now(). */\n now?: number;\n}\n\nexport interface RefreshResult {\n refreshed: boolean;\n checked: number;\n markedUnavailable: string[];\n}\n\nconst NOT_REFRESHED: RefreshResult = { refreshed: false, checked: 0, markedUnavailable: [] };\nconst DEFAULT_TTL_MS = 60 * 60 * 1000; // 1h\nconst ANTHROPIC_MODELS_URL = \"https://api.anthropic.com/v1/models\";\n\n/** Last successful live fetch per provider, for TTL short-circuiting. */\nconst lastRefreshAt = new Map<string, number>();\n\n/** Reset the TTL bookkeeping. For tests. */\nexport function resetRefreshState(): void {\n lastRefreshAt.clear();\n}\n\ninterface AnthropicModelsResponse {\n data?: { id?: string }[];\n}\n\n/**\n * Reconcile tracked models against the provider's live list. For Anthropic:\n * GET /v1/models — any tracked anthropic id NOT in the live set is marked\n * unavailable; ids present are (re)marked available. TTL-cached; a fetch within\n * the window is a no-op. Returns { refreshed:false } on any error or missing key.\n */\nexport async function refreshAvailability(opts: RefreshOptions = {}): Promise<RefreshResult> {\n const provider = opts.provider ?? \"anthropic\";\n if (provider !== \"anthropic\") return NOT_REFRESHED;\n\n const ttl = opts.ttlMs ?? DEFAULT_TTL_MS;\n const now = opts.now ?? Date.now();\n const last = lastRefreshAt.get(provider);\n if (last !== undefined && now - last < ttl) return NOT_REFRESHED; // within TTL → skip\n\n const apiKey = opts.apiKey ?? process.env.ANTHROPIC_API_KEY;\n if (!apiKey) return NOT_REFRESHED;\n\n const f = opts.fetch ?? fetch;\n let liveIds: Set<string>;\n try {\n const res = await f(ANTHROPIC_MODELS_URL, {\n headers: { \"x-api-key\": apiKey, \"anthropic-version\": \"2023-06-01\", accept: \"application/json\" },\n });\n if (!res.ok) return NOT_REFRESHED;\n const json = (await res.json()) as AnthropicModelsResponse;\n liveIds = new Set((json.data ?? []).map((m) => m.id).filter((id): id is string => typeof id === \"string\"));\n } catch {\n return NOT_REFRESHED; // network error → keep defaults\n }\n\n // A models list that came back empty is almost certainly an API hiccup, not\n // \"every model is dead\" — don't suspend the whole provider on it.\n if (liveIds.size === 0) return NOT_REFRESHED;\n\n const tracked = providerIds(provider);\n const markedUnavailable: string[] = [];\n for (const id of tracked) {\n const live = liveIds.has(id);\n if (live) {\n setAvailability(id, true);\n } else {\n setAvailability(id, false, \"not in provider model list (live refresh)\");\n markedUnavailable.push(id);\n }\n }\n\n lastRefreshAt.set(provider, now);\n return { refreshed: true, checked: tracked.length, markedUnavailable };\n}\n","// Persistent BudgetStore backed by bun:sqlite (F7.1). The rolling total survives\n// process restarts and is shared by every process pointing at the same file, so\n// a budget ceiling is a real production guard — not a per-process counter that\n// resets on deploy. bun:sqlite is imported lazily (Node-safe import, like sqliteSink).\nimport type { BudgetStore } from \"../types.js\";\n\nexport interface SqliteBudgetStoreConfig {\n /** SQLite file path, e.g. \"./ai-budget.db\". */\n dbPath: string;\n /** Window/bucket key — use e.g. a day-stamp for a daily budget. Default \"default\". */\n key?: string;\n}\n\nexport function sqliteBudgetStore(config: SqliteBudgetStoreConfig): BudgetStore {\n const key = config.key ?? \"default\";\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let ready: Promise<any> | null = null;\n const open = async () => {\n const { Database } = await import(\"bun:sqlite\");\n const db = new Database(config.dbPath);\n db.run(\n `CREATE TABLE IF NOT EXISTS budget_spend (key TEXT PRIMARY KEY, spent_usd REAL NOT NULL DEFAULT 0)`,\n );\n return db;\n };\n\n return {\n async getSpent(): Promise<number> {\n const db = await (ready ??= open());\n const row = db\n .query(`SELECT spent_usd FROM budget_spend WHERE key = $key`)\n .get({ $key: key }) as { spent_usd: number } | null;\n return row?.spent_usd ?? 0;\n },\n async addSpent(usd: number): Promise<void> {\n const db = await (ready ??= open());\n db.run(\n `INSERT INTO budget_spend (key, spent_usd) VALUES ($key, $usd)\n ON CONFLICT(key) DO UPDATE SET spent_usd = spent_usd + $usd`,\n { $key: key, $usd: usd },\n );\n },\n };\n}\n","import type { CostSink } from \"../../types.js\";\n\n/** A sink that does nothing. The default when no costSink is configured. */\nexport const noopSink: CostSink = {\n record() {\n // intentionally empty\n },\n};\n","import type { CostSink, Usage } from \"../../types.js\";\n\n/** Fan a Usage out to several sinks. Uses allSettled so one failing sink never\n * prevents the others from recording (and never propagates to the caller). */\nexport function multiSink(sinks: CostSink[]): CostSink {\n return {\n async record(usage: Usage): Promise<void> {\n // async wrapper turns a synchronous throw in s.record into a rejected\n // promise, so allSettled isolates it (a sync throw would otherwise escape\n // the .map before allSettled ran).\n await Promise.allSettled(sinks.map(async (s) => s.record(usage)));\n },\n };\n}\n","// upmetricsSink — the canonical cost sink. Forwards each Usage to the upmetrics\n// agent-run ingest (POST /api/agent, mode:\"record\"). Field mapping follows\n// upmetrics/docs/AGENT-SCHEMA.md \"For cost-sink authors\" exactly:\n// - agent_kind / agent_name are injected (not in Usage; required by ingest)\n// - camelCase Usage → snake_case wire fields\n// - capability + transport ride in tags (no top-level column)\n// - toolCalls[].errorCount → tool_calls[].error_count (deep rename)\n// - latencyMs → duration_ms; ts → started_at; ended_at = ts + latency\n// Errors never propagate (CostSink invariant). Do NOT use @upmetrics/agent\n// wrapAnthropic here — the SDK already owns the provider call.\nimport { SDK_TAG } from \"../../version.js\";\nimport type { CostSink, Usage } from \"../../types.js\";\n\nexport interface UpmetricsSinkConfig {\n /** Ingest base URL, e.g. https://upmetrics.org */\n baseUrl: string;\n /** Per-project api_key → sent as the X-Upmetrics-Key header. */\n apiKey: string;\n /** Consumer name dashboards group by (e.g. \"cms\", \"trail\", \"xrt81\") — NOT the\n * capability. */\n agentName: string;\n /** Defaults to \"chatbot\" (\"embedding\" auto-selected for embedding calls). */\n agentKind?: string;\n /** When true, guarantees no prompt/response content is ever sent (the sink\n * sends none regardless — Usage carries no excerpts — so this is belt-and-\n * suspenders for GDPR-health projects). */\n complianceMode?: boolean;\n /** Injectable fetch for testing; defaults to global fetch. */\n fetch?: typeof fetch;\n /** Optional error hook (errors are otherwise swallowed silently). */\n onError?: (err: unknown) => void;\n}\n\nexport function upmetricsSink(config: UpmetricsSinkConfig): CostSink {\n const doFetch = config.fetch ?? fetch;\n const url = `${config.baseUrl.replace(/\\/$/, \"\")}/api/agent`;\n\n return {\n async record(usage: Usage): Promise<void> {\n try {\n const startedAt = usage.ts || new Date().toISOString();\n const endedAt = new Date(\n new Date(startedAt).getTime() + (usage.latencyMs || 0),\n ).toISOString();\n\n const agentKind =\n config.agentKind ?? (usage.capability === \"embedding\" ? \"embedding\" : \"chatbot\");\n\n const body: Record<string, unknown> = {\n mode: \"record\",\n agent_kind: agentKind,\n agent_name: config.agentName,\n provider: usage.provider,\n model: usage.model,\n status: \"success\",\n input_tokens: usage.inputTokens,\n output_tokens: usage.outputTokens,\n cache_read_tokens: usage.cacheReadTokens,\n cache_creation_tokens: usage.cacheCreationTokens,\n cost_usd: usage.costUsd,\n duration_ms: usage.latencyMs,\n started_at: startedAt,\n ended_at: endedAt,\n tags: {\n // Consumer attribution labels (e.g. tenantId) ride in tags so no new\n // top-level field risks the strict-shape ingest schema (F011). The\n // SDK-owned keys win — a label can never clobber capability/transport/sdk.\n ...usage.labels,\n capability: usage.capability,\n transport: usage.transport,\n sdk: SDK_TAG,\n },\n };\n if (usage.tier !== undefined) body.tier = usage.tier;\n if (usage.purpose !== undefined) body.purpose = usage.purpose;\n if (usage.toolCalls) {\n body.tool_calls = usage.toolCalls.map((t) => ({\n name: t.name,\n count: t.count,\n error_count: t.errorCount ?? 0,\n }));\n }\n // complianceMode is a no-op today (we never send excerpts) but documents intent.\n void config.complianceMode;\n\n const res = await doFetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"X-Upmetrics-Key\": config.apiKey,\n },\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n config.onError?.(\n new Error(`upmetricsSink: ingest returned ${res.status}: ${text.slice(0, 200)}`),\n );\n }\n } catch (err) {\n // Never let a sink failure crash a real AI call.\n config.onError?.(err);\n }\n },\n };\n}\n","// discordSink — posts a per-call cost embed to a Discord webhook. Secondary sink\n// (upmetricsSink is canonical); handy for repos not wired to Upmetrics or for an\n// at-a-glance spend feed. Plain fetch, no Discord SDK. Errors never propagate.\nimport type { CostSink, Usage } from \"../../types.js\";\n\nexport interface DiscordSinkConfig {\n webhookUrl: string;\n /** Skip posting paid calls below this USD threshold (anti-spam). Subprocess\n * (Max-plan free) calls always post so the \"free\" feed stays visible.\n * Default 0 → post everything. */\n minUsd?: number;\n fetch?: typeof fetch;\n onError?: (err: unknown) => void;\n}\n\nexport function discordSink(config: DiscordSinkConfig): CostSink {\n const doFetch = config.fetch ?? fetch;\n const minUsd = config.minUsd ?? 0;\n\n return {\n async record(usage: Usage): Promise<void> {\n try {\n // Skip cheap PAID calls; always show subprocess (free) calls.\n if (!usage.subprocess && usage.costUsd < minUsd) return;\n\n const costLabel = usage.subprocess\n ? \"Max plan (free)\"\n : `$${usage.costUsd.toFixed(6)}`;\n\n const embed = {\n title: `AI call — ${usage.capability}`,\n fields: [\n { name: \"Provider\", value: usage.provider, inline: true },\n { name: \"Model\", value: usage.model, inline: true },\n { name: \"Transport\", value: usage.transport, inline: true },\n { name: \"Cost\", value: costLabel, inline: true },\n {\n name: \"Tokens\",\n value: `${usage.inputTokens} in / ${usage.outputTokens} out`,\n inline: true,\n },\n { name: \"Latency\", value: `${usage.latencyMs} ms`, inline: true },\n ],\n timestamp: usage.ts || new Date().toISOString(),\n };\n\n const res = await doFetch(config.webhookUrl, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ embeds: [embed] }),\n });\n if (!res.ok) {\n config.onError?.(new Error(`discordSink: webhook returned ${res.status}`));\n }\n } catch (err) {\n config.onError?.(err);\n }\n },\n };\n}\n","// sqliteSink — persists every Usage to a local bun:sqlite DB. Secondary/offline\n// sink (upmetricsSink is canonical). No npm dependency — bun:sqlite is built in.\n//\n// IMPORTANT: bun:sqlite is imported LAZILY (dynamic import on first use), not at\n// module top level. A static `import \"bun:sqlite\"` would leak into the package\n// entry and crash every Node consumer (`ERR_UNSUPPORTED_ESM_URL_SCHEME`). With\n// the lazy import, importing @broberg/ai-sdk works everywhere; bun:sqlite only\n// loads when sqliteSink/getCostSummary actually run (Bun only).\nimport type { CostSink, Usage } from \"../../types.js\";\n\nexport interface SqliteSinkConfig {\n /** Path to the SQLite file, e.g. \"./ai-cost.db\" (or \":memory:\"). */\n dbPath: string;\n}\n\nconst CREATE_TABLE = `\nCREATE TABLE IF NOT EXISTS ai_usage (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n ts TEXT NOT NULL,\n provider TEXT NOT NULL,\n model TEXT NOT NULL,\n tier TEXT,\n transport TEXT NOT NULL,\n capability TEXT NOT NULL,\n purpose TEXT,\n input_tokens INTEGER NOT NULL,\n output_tokens INTEGER NOT NULL,\n cache_read_tokens INTEGER NOT NULL,\n cache_creation_tokens INTEGER NOT NULL,\n cost_usd REAL NOT NULL,\n latency_ms INTEGER NOT NULL,\n subprocess INTEGER NOT NULL DEFAULT 0\n)`;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function openDb(dbPath: string, readonly = false): Promise<any> {\n const { Database } = await import(\"bun:sqlite\");\n return new Database(dbPath, readonly ? { readonly: true } : undefined);\n}\n\nexport function sqliteSink(config: SqliteSinkConfig): CostSink {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let ready: Promise<any> | null = null;\n const init = async () => {\n const db = await openDb(config.dbPath);\n db.run(CREATE_TABLE);\n const insert = db.prepare(\n `INSERT INTO ai_usage\n (ts, provider, model, tier, transport, capability, purpose,\n input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens,\n cost_usd, latency_ms, subprocess)\n VALUES ($ts, $provider, $model, $tier, $transport, $capability, $purpose,\n $input, $output, $cacheRead, $cacheCreation, $cost, $latency, $subprocess)`,\n );\n return insert;\n };\n\n return {\n async record(usage: Usage): Promise<void> {\n const insert = await (ready ??= init());\n insert.run({\n $ts: usage.ts || new Date().toISOString(),\n $provider: usage.provider,\n $model: usage.model,\n $tier: usage.tier ?? null,\n $transport: usage.transport,\n $capability: usage.capability,\n $purpose: usage.purpose ?? null,\n $input: usage.inputTokens,\n $output: usage.outputTokens,\n $cacheRead: usage.cacheReadTokens,\n $cacheCreation: usage.cacheCreationTokens,\n $cost: usage.costUsd,\n $latency: usage.latencyMs,\n $subprocess: usage.subprocess ? 1 : 0,\n });\n },\n };\n}\n\nexport interface CostSummary {\n totalUsd: number;\n byProvider: Record<string, number>;\n byCapability: Record<string, number>;\n}\n\n/** Aggregate the recorded spend from a sqliteSink DB. Creates the table if the\n * DB has never been written to, so an empty DB summarises cleanly to 0. */\nexport async function getCostSummary(dbPath: string): Promise<CostSummary> {\n const db = await openDb(dbPath);\n db.run(CREATE_TABLE);\n const total = db\n .query(`SELECT SUM(cost_usd) AS total FROM ai_usage`)\n .get() as { total: number | null };\n const byProvider: Record<string, number> = {};\n for (const row of db\n .query(`SELECT provider, SUM(cost_usd) AS sum FROM ai_usage GROUP BY provider`)\n .all() as { provider: string; sum: number }[]) {\n byProvider[row.provider] = row.sum;\n }\n const byCapability: Record<string, number> = {};\n for (const row of db\n .query(`SELECT capability, SUM(cost_usd) AS sum FROM ai_usage GROUP BY capability`)\n .all() as { capability: string; sum: number }[]) {\n byCapability[row.capability] = row.sum;\n }\n return { totalUsd: total?.total ?? 0, byProvider, byCapability };\n}\n","// upmetricsCostClient — the cost READ-back side, companion to upmetricsSink (the\n// write side). Upmetrics owns cost AGGREGATION (it already rolls up agent_runs):\n// this is a thin, browser-clean wrapper over its public cost read-API\n// (upmetrics/docs/COST-API.md, F014) so a consuming app reads its OWN accumulated\n// cost from the canonical source instead of re-aggregating locally.\n//\n// Money is integer micro-USD ($1 = 1_000_000); Upmetrics rounds once at the\n// response boundary so sub-cent calls aren't lost. Pure fetch, zero new deps, no\n// bun:sqlite import → safe to import from a browser/Vite build.\n\n/** Thrown when the cost read-API rejects (e.g. 401 invalid_api_key) or is unreachable. */\nexport class UpmetricsCostError extends Error {\n readonly status?: number;\n readonly code?: string;\n constructor(message: string, opts?: { status?: number; code?: string }) {\n super(message);\n this.name = \"UpmetricsCostError\";\n this.status = opts?.status;\n this.code = opts?.code;\n }\n}\n\nexport interface UpmetricsCostClientConfig {\n /** Read-API base URL, e.g. https://upmetrics.org */\n baseUrl: string;\n /** Per-project api_key (uk_…) — sent as X-Upmetrics-Key; resolves to your own project only. */\n apiKey: string;\n /** Injectable fetch for testing; defaults to global fetch. */\n fetch?: typeof fetch;\n}\n\n/** Shared filter surface for summary + timeseries (mirrors COST-API.md query params). */\nexport interface CostQuery {\n /** Relative window; ignored when from/to are given. */\n window?: \"day\" | \"week\" | \"month\";\n /** Explicit window start (ISO-8601 or epoch-ms) — overrides `window`. */\n from?: string | number;\n /** Explicit window end (ISO-8601 or epoch-ms) — overrides `window`. */\n to?: string | number;\n provider?: string;\n model?: string;\n tier?: string;\n /** Filter to one consumer (the sink's agent_name). */\n agentName?: string;\n transport?: \"http\" | \"subprocess\";\n /** Tag filters → `tag.<key>=<value>` (e.g. { tenantId: \"sanne\" }). */\n tags?: Record<string, string>;\n}\n\nexport interface CostSummaryQuery extends CostQuery {\n /** Break the total down per distinct value of this tag key (the per-tenant view). */\n groupBy?: string;\n}\n\nexport interface CostTimeseriesQuery extends CostQuery {\n /** Bucket granularity (default \"day\"). */\n bucket?: \"day\" | \"hour\";\n}\n\n/** One breakdown row, ordered by cost desc. `tier`/`capability` fall back to \"(none)\". */\nexport interface UpmetricsCostRow {\n key: string;\n micro_usd: number;\n input_tokens: number;\n output_tokens: number;\n run_count: number;\n}\n\nexport interface UpmetricsCostSummary {\n generated_at: string;\n window: { from: string; to: string };\n total_micro_usd: number;\n input_tokens: number;\n output_tokens: number;\n cache_read_tokens: number;\n cache_creation_tokens: number;\n run_count: number;\n metered: { metered_micro_usd: number; free_run_count: number };\n by_provider: UpmetricsCostRow[];\n by_model: UpmetricsCostRow[];\n by_tier: UpmetricsCostRow[];\n by_capability: UpmetricsCostRow[];\n /** Present only when `groupBy` was requested. */\n group_by?: string;\n by_group?: UpmetricsCostRow[];\n}\n\nexport interface UpmetricsCostTimeseries {\n generated_at: string;\n bucket: \"day\" | \"hour\";\n window: { from: string; to: string };\n /** Only non-zero buckets are returned — pad missing buckets yourself. */\n points: Array<{\n ts: string;\n micro_usd: number;\n input_tokens: number;\n output_tokens: number;\n run_count: number;\n }>;\n}\n\n/** Convert integer micro-USD to a USD float for display. `$1 = 1_000_000`. */\nexport const usdFromMicro = (microUsd: number): number => microUsd / 1_000_000;\n\nfunction buildQuery(q: CostQuery & { groupBy?: string; bucket?: string }): string {\n const p = new URLSearchParams();\n if (q.bucket) p.set(\"bucket\", q.bucket);\n if (q.from !== undefined) p.set(\"from\", String(q.from));\n if (q.to !== undefined) p.set(\"to\", String(q.to));\n // `window` is ignored server-side when from/to are present; only send it otherwise.\n if (q.window && q.from === undefined && q.to === undefined) p.set(\"window\", q.window);\n if (q.provider) p.set(\"provider\", q.provider);\n if (q.model) p.set(\"model\", q.model);\n if (q.tier) p.set(\"tier\", q.tier);\n if (q.agentName) p.set(\"agent_name\", q.agentName);\n if (q.transport) p.set(\"transport\", q.transport);\n if (q.groupBy) p.set(\"groupBy\", q.groupBy);\n for (const [k, v] of Object.entries(q.tags ?? {})) p.set(`tag.${k}`, v);\n const s = p.toString();\n return s ? `?${s}` : \"\";\n}\n\nexport function upmetricsCostClient(config: UpmetricsCostClientConfig): {\n summary(query?: CostSummaryQuery): Promise<UpmetricsCostSummary>;\n timeseries(query?: CostTimeseriesQuery): Promise<UpmetricsCostTimeseries>;\n} {\n const doFetch = config.fetch ?? fetch;\n const base = config.baseUrl.replace(/\\/$/, \"\");\n\n async function get<T>(path: string, query: string): Promise<T> {\n let res: Response;\n try {\n res = await doFetch(`${base}${path}${query}`, {\n method: \"GET\",\n headers: { \"X-Upmetrics-Key\": config.apiKey },\n });\n } catch (err) {\n throw new UpmetricsCostError(\n `upmetricsCostClient: ${path} unreachable: ${(err as Error)?.message ?? String(err)}`,\n );\n }\n if (!res.ok) {\n let code: string | undefined;\n const text = await res.text().catch(() => \"\");\n try {\n code = (JSON.parse(text) as { error?: string }).error;\n } catch {\n /* non-JSON error body */\n }\n throw new UpmetricsCostError(\n `upmetricsCostClient: ${path} returned ${res.status}${code ? ` (${code})` : \"\"}`,\n { status: res.status, code },\n );\n }\n return (await res.json()) as T;\n }\n\n return {\n summary(query: CostSummaryQuery = {}): Promise<UpmetricsCostSummary> {\n return get<UpmetricsCostSummary>(\"/api/cost/summary\", buildQuery(query));\n },\n timeseries(query: CostTimeseriesQuery = {}): Promise<UpmetricsCostTimeseries> {\n return get<UpmetricsCostTimeseries>(\"/api/cost/timeseries\", buildQuery(query));\n },\n };\n}\n"],"mappings":"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","names":["url","mimeType","data","DEFAULT_REGION","EU_BASE","sleep","res"]}
|