@broberg/ai-sdk 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -946,6 +946,8 @@ interface FalAdapterConfig {
946
946
  pollIntervalMs?: number;
947
947
  timeoutMs?: number;
948
948
  fetch?: typeof fetch;
949
+ /** Override the per-image USD price (else a built-in estimate per model, 0 if unknown). */
950
+ pricePerImage?: number;
949
951
  }
950
952
  declare function falAdapter(config?: FalAdapterConfig): ProviderAdapter;
951
953
 
@@ -976,8 +978,8 @@ declare const falStubAdapter: ProviderAdapter;
976
978
  * wires the live adapters. */
977
979
  declare const stubProviders: Record<string, ProviderAdapter>;
978
980
 
979
- declare const VERSION: "0.1.0";
980
- declare const SDK_TAG: "@broberg/ai-sdk@0.1.0";
981
+ declare const VERSION: "0.1.2";
982
+ declare const SDK_TAG: "@broberg/ai-sdk@0.1.2";
981
983
 
982
984
  /** Built-in defaults. Every entry is overridable via AiConfig.defaults or a
983
985
  * per-call override. Model IDs are current at scaffold time; callers pin their
@@ -1082,8 +1084,9 @@ interface CostSummary {
1082
1084
  byProvider: Record<string, number>;
1083
1085
  byCapability: Record<string, number>;
1084
1086
  }
1085
- /** Aggregate the recorded spend from a sqliteSink DB. */
1086
- declare function getCostSummary(dbPath: string): CostSummary;
1087
+ /** Aggregate the recorded spend from a sqliteSink DB. Creates the table if the
1088
+ * DB has never been written to, so an empty DB summarises cleanly to 0. */
1089
+ declare function getCostSummary(dbPath: string): Promise<CostSummary>;
1087
1090
 
1088
1091
  interface PricingEntry {
1089
1092
  /** USD per 1M input tokens. */
package/dist/index.js CHANGED
@@ -565,6 +565,12 @@ function openrouterAdapter(config = {}) {
565
565
  }
566
566
 
567
567
  // src/providers/fal.ts
568
+ var FAL_IMAGE_PRICE_ESTIMATE = {
569
+ "fal-ai/flux/schnell": 3e-3,
570
+ "fal-ai/flux/dev": 0.025,
571
+ "fal-ai/flux-pro": 0.05,
572
+ "fal-ai/flux-pro/v1.1": 0.04
573
+ };
568
574
  var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
569
575
  function falAdapter(config = {}) {
570
576
  const doFetch = config.fetch ?? fetch;
@@ -590,6 +596,7 @@ function falAdapter(config = {}) {
590
596
  inputTokens: 0,
591
597
  outputTokens: 0
592
598
  });
599
+ usage.costUsd = config.pricePerImage ?? FAL_IMAGE_PRICE_ESTIMATE[req.spec.model] ?? 0;
593
600
  return { url, usage };
594
601
  }
595
602
  async function runSync(model, headers, body) {
@@ -975,117 +982,147 @@ function createAI(config = {}) {
975
982
  msgs.push({ role: "user", content: input.prompt ?? "" });
976
983
  return msgs;
977
984
  }
985
+ async function runCapability(opts) {
986
+ const routes = [
987
+ opts.primary,
988
+ ...(opts.fallback ?? []).map(
989
+ (f) => typeof f === "string" ? resolveTier(f, void 0, cfg.defaults) : f
990
+ )
991
+ ];
992
+ let lastErr;
993
+ for (let i = 0; i < routes.length; i++) {
994
+ const spec = routes[i];
995
+ preflight(spec, opts.estIn, opts.estOut);
996
+ try {
997
+ const t0 = performance.now();
998
+ const res = await opts.invoke(spec);
999
+ enrich(res.usage, opts.capability, i === 0 ? opts.tier : void 0, opts.purpose, performance.now() - t0);
1000
+ settle(res.usage);
1001
+ await report(res.usage);
1002
+ return res;
1003
+ } catch (e) {
1004
+ lastErr = e;
1005
+ }
1006
+ }
1007
+ throw lastErr;
1008
+ }
978
1009
  const client = {
979
1010
  async chat(input) {
980
1011
  input = chatInputSchema.parse(input);
981
- const spec = resolveTier(input.tier ?? "smart", input.override, cfg.defaults);
982
- const adapter = pickProvider(spec.provider);
983
- if (!adapter.chat) {
984
- throw new Error(`createAI: provider "${spec.provider}" does not support chat`);
985
- }
1012
+ const tier = input.tier ?? "smart";
986
1013
  const messages = toMessages(input);
987
1014
  const estIn = messages.reduce(
988
1015
  (n, m) => n + estTokens(typeof m.content === "string" ? m.content : JSON.stringify(m.content)),
989
1016
  0
990
1017
  );
991
- preflight(spec, estIn, input.maxTokens ?? 512);
992
- const t0 = performance.now();
993
- const res = await adapter.chat({
994
- messages,
995
- spec,
996
- tools: input.tools,
997
- maxTokens: input.maxTokens,
998
- temperature: input.temperature
1018
+ return runCapability({
1019
+ primary: resolveTier(tier, input.override, cfg.defaults),
1020
+ fallback: input.fallback,
1021
+ capability: "chat",
1022
+ tier,
1023
+ purpose: input.purpose,
1024
+ estIn,
1025
+ estOut: input.maxTokens ?? 512,
1026
+ invoke: async (spec) => {
1027
+ const adapter = pickProvider(spec.provider);
1028
+ if (!adapter.chat) throw new Error(`createAI: provider "${spec.provider}" does not support chat`);
1029
+ return adapter.chat({ messages, spec, tools: input.tools, maxTokens: input.maxTokens, temperature: input.temperature });
1030
+ }
999
1031
  });
1000
- enrich(res.usage, "chat", input.tier ?? "smart", input.purpose, performance.now() - t0);
1001
- settle(res.usage);
1002
- await report(res.usage);
1003
- return res;
1004
1032
  },
1005
1033
  async vision(input) {
1006
1034
  input = visionInputSchema.parse(input);
1007
- const spec = resolveTier(input.tier ?? VISION_DEFAULT_TIER, input.override, cfg.defaults);
1008
- const adapter = pickProvider(spec.provider);
1009
- if (!adapter.vision) {
1010
- throw new Error(`createAI: provider "${spec.provider}" does not support vision`);
1011
- }
1035
+ const tier = input.tier ?? VISION_DEFAULT_TIER;
1012
1036
  const messages = buildVisionMessages(input);
1013
- preflight(spec, estTokens(input.prompt) + 1e3, 512);
1014
- const t0 = performance.now();
1015
- const res = await adapter.vision({ messages, spec });
1016
- enrich(res.usage, "vision", input.tier ?? VISION_DEFAULT_TIER, input.purpose, performance.now() - t0);
1017
- settle(res.usage);
1018
- await report(res.usage);
1019
- return res;
1037
+ return runCapability({
1038
+ primary: resolveTier(tier, input.override, cfg.defaults),
1039
+ fallback: input.fallback,
1040
+ capability: "vision",
1041
+ tier,
1042
+ purpose: input.purpose,
1043
+ estIn: estTokens(input.prompt) + 1e3,
1044
+ // prompt + ~1k image payload
1045
+ estOut: 512,
1046
+ invoke: async (spec) => {
1047
+ const adapter = pickProvider(spec.provider);
1048
+ if (!adapter.vision) throw new Error(`createAI: provider "${spec.provider}" does not support vision`);
1049
+ return adapter.vision({ messages, spec });
1050
+ }
1051
+ });
1020
1052
  },
1021
1053
  async translate(input) {
1022
1054
  input = translateInputSchema.parse(input);
1023
- const spec = resolveTier(input.tier ?? TRANSLATE_DEFAULT_TIER, input.override, cfg.defaults);
1024
- const adapter = pickProvider(spec.provider);
1025
- if (!adapter.chat) {
1026
- throw new Error(`createAI: provider "${spec.provider}" does not support chat (translate routes through chat)`);
1027
- }
1055
+ const tier = input.tier ?? TRANSLATE_DEFAULT_TIER;
1028
1056
  const messages = buildTranslateMessages(input);
1029
1057
  const estIn = estTokens(input.text) + 40;
1030
- preflight(spec, estIn, estIn);
1031
- const t0 = performance.now();
1032
- const res = await adapter.chat({ messages, spec });
1033
- enrich(res.usage, "translate", input.tier ?? TRANSLATE_DEFAULT_TIER, input.purpose, performance.now() - t0);
1034
- settle(res.usage);
1035
- await report(res.usage);
1058
+ const res = await runCapability({
1059
+ primary: resolveTier(tier, input.override, cfg.defaults),
1060
+ fallback: input.fallback,
1061
+ capability: "translate",
1062
+ tier,
1063
+ purpose: input.purpose,
1064
+ estIn,
1065
+ estOut: estIn,
1066
+ invoke: async (spec) => {
1067
+ const adapter = pickProvider(spec.provider);
1068
+ if (!adapter.chat) throw new Error(`createAI: provider "${spec.provider}" does not support chat (translate routes through chat)`);
1069
+ return adapter.chat({ messages, spec });
1070
+ }
1071
+ });
1036
1072
  return { text: res.text, usage: res.usage };
1037
1073
  },
1038
1074
  async image(input) {
1039
1075
  input = imageInputSchema.parse(input);
1040
- const spec = { ...DEFAULT_IMAGE_SPEC, ...input.override };
1041
- const adapter = pickProvider(spec.provider);
1042
- if (!adapter.image) {
1043
- throw new Error(`createAI: provider "${spec.provider}" does not support image`);
1044
- }
1045
- preflight(spec, 0, 0);
1046
- const t0 = performance.now();
1047
- const res = await adapter.image({
1048
- prompt: input.prompt,
1049
- spec,
1050
- width: input.width,
1051
- height: input.height
1076
+ return runCapability({
1077
+ primary: { ...DEFAULT_IMAGE_SPEC, ...input.override },
1078
+ fallback: input.fallback,
1079
+ capability: "image",
1080
+ purpose: input.purpose,
1081
+ estIn: 0,
1082
+ // image cost is not token-based
1083
+ estOut: 0,
1084
+ invoke: async (spec) => {
1085
+ const adapter = pickProvider(spec.provider);
1086
+ if (!adapter.image) throw new Error(`createAI: provider "${spec.provider}" does not support image`);
1087
+ return adapter.image({ prompt: input.prompt, spec, width: input.width, height: input.height });
1088
+ }
1052
1089
  });
1053
- enrich(res.usage, "image", void 0, input.purpose, performance.now() - t0);
1054
- settle(res.usage);
1055
- await report(res.usage);
1056
- return res;
1057
1090
  },
1058
1091
  async embedding(input) {
1059
1092
  input = embeddingInputSchema.parse(input);
1060
- const spec = resolveTier(input.tier ?? EMBEDDING_DEFAULT_TIER, input.override, cfg.defaults);
1061
- const adapter = pickProvider(spec.provider);
1062
- if (!adapter.embedding) {
1063
- throw new Error(`createAI: provider "${spec.provider}" does not support embedding`);
1064
- }
1093
+ const tier = input.tier ?? EMBEDDING_DEFAULT_TIER;
1065
1094
  const text = Array.isArray(input.text) ? input.text : [input.text];
1066
- preflight(spec, text.reduce((n, t) => n + estTokens(t), 0), 0);
1067
- const t0 = performance.now();
1068
- const res = await adapter.embedding({ input: text, spec });
1069
- enrich(res.usage, "embedding", input.tier ?? EMBEDDING_DEFAULT_TIER, input.purpose, performance.now() - t0);
1070
- settle(res.usage);
1071
- await report(res.usage);
1072
- return res;
1095
+ return runCapability({
1096
+ primary: resolveTier(tier, input.override, cfg.defaults),
1097
+ fallback: input.fallback,
1098
+ capability: "embedding",
1099
+ tier,
1100
+ purpose: input.purpose,
1101
+ estIn: text.reduce((n, t) => n + estTokens(t), 0),
1102
+ estOut: 0,
1103
+ invoke: async (spec) => {
1104
+ const adapter = pickProvider(spec.provider);
1105
+ if (!adapter.embedding) throw new Error(`createAI: provider "${spec.provider}" does not support embedding`);
1106
+ return adapter.embedding({ input: text, spec });
1107
+ }
1108
+ });
1073
1109
  },
1074
1110
  async transcribe(input) {
1075
1111
  input = transcribeInputSchema.parse(input);
1076
- const spec = { ...DEFAULT_TRANSCRIBE_SPEC, ...input.override };
1077
- const adapter = pickProvider(spec.provider);
1078
- if (!adapter.transcribe) {
1079
- throw new Error(`createAI: provider "${spec.provider}" does not support transcribe`);
1080
- }
1081
1112
  const audio = await resolveAudio(input.audio);
1082
- preflight(spec, 0, 0);
1083
- const t0 = performance.now();
1084
- const res = await adapter.transcribe({ audio, language: input.language, spec });
1085
- enrich(res.usage, "transcribe", void 0, input.purpose, performance.now() - t0);
1086
- settle(res.usage);
1087
- await report(res.usage);
1088
- return res;
1113
+ return runCapability({
1114
+ primary: { ...DEFAULT_TRANSCRIBE_SPEC, ...input.override },
1115
+ fallback: input.fallback,
1116
+ capability: "transcribe",
1117
+ purpose: input.purpose,
1118
+ estIn: 0,
1119
+ estOut: 0,
1120
+ invoke: async (spec) => {
1121
+ const adapter = pickProvider(spec.provider);
1122
+ if (!adapter.transcribe) throw new Error(`createAI: provider "${spec.provider}" does not support transcribe`);
1123
+ return adapter.transcribe({ audio, language: input.language, spec });
1124
+ }
1125
+ });
1089
1126
  },
1090
1127
  // Replaced below with the real prompt-contracts (needs the client itself).
1091
1128
  contracts: void 0
@@ -1175,8 +1212,8 @@ var stubProviders = {
1175
1212
  };
1176
1213
 
1177
1214
  // src/version.ts
1178
- var VERSION = "0.1.0";
1179
- var SDK_TAG = "@broberg/ai-sdk@0.1.0";
1215
+ var VERSION = "0.1.2";
1216
+ var SDK_TAG = "@broberg/ai-sdk@0.1.2";
1180
1217
 
1181
1218
  // src/cost/sinks/noop.ts
1182
1219
  var noopSink = {
@@ -1298,7 +1335,6 @@ function discordSink(config) {
1298
1335
  }
1299
1336
 
1300
1337
  // src/cost/sinks/sqlite.ts
1301
- import { Database } from "bun:sqlite";
1302
1338
  var CREATE_TABLE = `
1303
1339
  CREATE TABLE IF NOT EXISTS ai_usage (
1304
1340
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -1317,19 +1353,28 @@ CREATE TABLE IF NOT EXISTS ai_usage (
1317
1353
  latency_ms INTEGER NOT NULL,
1318
1354
  subprocess INTEGER NOT NULL DEFAULT 0
1319
1355
  )`;
1356
+ async function openDb(dbPath, readonly = false) {
1357
+ const { Database } = await import("bun:sqlite");
1358
+ return new Database(dbPath, readonly ? { readonly: true } : void 0);
1359
+ }
1320
1360
  function sqliteSink(config) {
1321
- const db = new Database(config.dbPath);
1322
- db.run(CREATE_TABLE);
1323
- const insert = db.prepare(
1324
- `INSERT INTO ai_usage
1325
- (ts, provider, model, tier, transport, capability, purpose,
1326
- input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens,
1327
- cost_usd, latency_ms, subprocess)
1328
- VALUES ($ts, $provider, $model, $tier, $transport, $capability, $purpose,
1329
- $input, $output, $cacheRead, $cacheCreation, $cost, $latency, $subprocess)`
1330
- );
1361
+ let ready = null;
1362
+ const init = async () => {
1363
+ const db = await openDb(config.dbPath);
1364
+ db.run(CREATE_TABLE);
1365
+ const insert = db.prepare(
1366
+ `INSERT INTO ai_usage
1367
+ (ts, provider, model, tier, transport, capability, purpose,
1368
+ input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens,
1369
+ cost_usd, latency_ms, subprocess)
1370
+ VALUES ($ts, $provider, $model, $tier, $transport, $capability, $purpose,
1371
+ $input, $output, $cacheRead, $cacheCreation, $cost, $latency, $subprocess)`
1372
+ );
1373
+ return insert;
1374
+ };
1331
1375
  return {
1332
- record(usage) {
1376
+ async record(usage) {
1377
+ const insert = await (ready ??= init());
1333
1378
  insert.run({
1334
1379
  $ts: usage.ts || (/* @__PURE__ */ new Date()).toISOString(),
1335
1380
  $provider: usage.provider,
@@ -1349,19 +1394,16 @@ function sqliteSink(config) {
1349
1394
  }
1350
1395
  };
1351
1396
  }
1352
- function getCostSummary(dbPath) {
1353
- const db = new Database(dbPath, { readonly: true });
1397
+ async function getCostSummary(dbPath) {
1398
+ const db = await openDb(dbPath);
1399
+ db.run(CREATE_TABLE);
1354
1400
  const total = db.query(`SELECT SUM(cost_usd) AS total FROM ai_usage`).get();
1355
1401
  const byProvider = {};
1356
- for (const row of db.query(
1357
- `SELECT provider, SUM(cost_usd) AS sum FROM ai_usage GROUP BY provider`
1358
- ).all()) {
1402
+ for (const row of db.query(`SELECT provider, SUM(cost_usd) AS sum FROM ai_usage GROUP BY provider`).all()) {
1359
1403
  byProvider[row.provider] = row.sum;
1360
1404
  }
1361
1405
  const byCapability = {};
1362
- for (const row of db.query(
1363
- `SELECT capability, SUM(cost_usd) AS sum FROM ai_usage GROUP BY capability`
1364
- ).all()) {
1406
+ for (const row of db.query(`SELECT capability, SUM(cost_usd) AS sum FROM ai_usage GROUP BY capability`).all()) {
1365
1407
  byCapability[row.capability] = row.sum;
1366
1408
  }
1367
1409
  return { totalUsd: total?.total ?? 0, byProvider, byCapability };
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/providers/tools.ts","../src/cost/pricing.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/fal.ts","../src/providers/registry.ts","../src/cost/budget.ts","../src/capabilities/vision.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/cost/sinks/noop.ts","../src/cost/sinks/multi.ts","../src/cost/sinks/upmetrics.ts","../src/cost/sinks/discord.ts","../src/cost/sinks/sqlite.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. Model IDs are current at scaffold time; callers pin their\n * own via config. `cheap` routes through the local `claude -p` subprocess\n * (Max plan → costUsd 0); everything else is HTTP. */\nexport const DEFAULT_TIER_MAP: Record<Tier, TierSpec> = {\n fast: { provider: \"anthropic\", model: \"claude-haiku-4-5\", transport: \"http\" },\n smart: { provider: \"anthropic\", model: \"claude-sonnet-4-6\", transport: \"http\" },\n powerful: { provider: \"anthropic\", model: \"claude-opus-4-8\", transport: \"http\" },\n cheap: { provider: \"anthropic\", model: \"claude-haiku-4-5\", transport: \"subprocess\" },\n vision: { provider: \"anthropic\", model: \"claude-sonnet-4-6\", transport: \"http\" },\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","// 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","// Versioned per-(provider, model) pricing. F3.6 populates the table + adds tests\n// + MiniMax coverage. F3.1 ships the type + lookup with an empty table, so\n// computeCost returns 0 for every model until F3.6 lands (calls still complete).\nexport interface PricingEntry {\n /** USD per 1M input tokens. */\n inputPer1M: number;\n /** USD per 1M output tokens. */\n outputPer1M: number;\n /** USD per 1M cache-read tokens (falls back to input rate if unset). */\n cacheReadPer1M?: number;\n /** USD per 1M cache-write/creation tokens (falls back to input rate if unset). */\n cacheWritePer1M?: number;\n /** Pricing snapshot version (date or tag) so stale entries are detectable. */\n version: string;\n}\n\n// USD per 1M tokens. Anthropic cache multipliers follow the standard model:\n// cache-read ≈ 0.1× input, cache-write ≈ 1.25× input. Verified against the\n// pricing tables in cms (packages/cms-ai/src/providers) + trail (model-lab).\n// MiniMax M2.7 is an estimate pending confirmation against OpenRouter's live\n// price page — flagged in its version string.\nconst V = \"2026-06-02\";\n\n/** Keyed `${provider}:${model}`. */\nconst PRICING: Record<string, PricingEntry> = {\n // Anthropic (direct API). DEFAULT_TIER_MAP: fast/cheap=haiku, smart/vision=sonnet, powerful=opus.\n \"anthropic:claude-haiku-4-5\": {\n inputPer1M: 0.8,\n outputPer1M: 4.0,\n cacheReadPer1M: 0.08,\n cacheWritePer1M: 1.0,\n version: V,\n },\n \"anthropic:claude-sonnet-4-6\": {\n inputPer1M: 3.0,\n outputPer1M: 15.0,\n cacheReadPer1M: 0.3,\n cacheWritePer1M: 3.75,\n version: V,\n },\n \"anthropic:claude-opus-4-8\": {\n inputPer1M: 15.0,\n outputPer1M: 75.0,\n cacheReadPer1M: 1.5,\n cacheWritePer1M: 18.75,\n version: V,\n },\n\n // OpenAI. embedding default tier = text-embedding-3-small (no output tokens).\n \"openai:text-embedding-3-small\": { inputPer1M: 0.02, outputPer1M: 0, version: V },\n \"openai:text-embedding-3-large\": { inputPer1M: 0.13, outputPer1M: 0, version: V },\n \"openai:gpt-4o\": { inputPer1M: 2.5, outputPer1M: 10.0, version: V },\n \"openai:gpt-4o-mini\": { inputPer1M: 0.15, outputPer1M: 0.6, version: V },\n // Whisper is priced per minute, not per token — not representable here; transcribe\n // (F5.6) computes its own cost. Listed as 0 so token-based compute never charges it.\n \"openai:whisper-1\": { inputPer1M: 0, outputPer1M: 0, version: V },\n\n // OpenRouter (meta-router — model slugs include the upstream vendor).\n \"openrouter:anthropic/claude-sonnet-4-6\": { inputPer1M: 3.0, outputPer1M: 15.0, version: V },\n \"openrouter:anthropic/claude-haiku-4-5\": { inputPer1M: 0.8, outputPer1M: 4.0, version: V },\n \"openrouter:google/gemini-2.5-flash\": { inputPer1M: 0.3, outputPer1M: 2.5, version: V },\n \"openrouter:minimax/minimax-m2.7\": {\n inputPer1M: 0.3,\n outputPer1M: 1.2,\n version: `${V}-estimate`,\n },\n\n // Google Gemini (direct). Image-gen model used by cms.\n \"google:gemini-2.5-flash\": { inputPer1M: 0.3, outputPer1M: 2.5, version: V },\n};\n\nexport function getPrice(provider: string, model: string): PricingEntry | undefined {\n return PRICING[`${provider}:${model}`];\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 { toProviderTools, fromProviderToolCall } from \"./tools.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n ChatRequest,\n ChatResult,\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 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 } = {},\n): ProviderAdapter {\n const baseUrl = config.baseUrl ?? \"https://api.anthropic.com\";\n const version = config.anthropicVersion ?? \"2023-06-01\";\n\n async function chatHttp(req: ChatRequest): Promise<ChatResult> {\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\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 } else {\n messages.push({ role: m.role === \"assistant\" ? \"assistant\" : \"user\", content: contentBlocks(m.content) });\n }\n }\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\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 return { name: \"anthropic\", chat, vision: chat };\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 { toProviderTools, fromProviderToolCall } from \"./tools.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n ChatRequest,\n ChatResult,\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}\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 };\n error?: unknown;\n}\n\n/** SDK message → OpenAI message (string content, or multimodal parts for vision). */\nfunction 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 return base;\n }\n const content = m.content.map((p) => {\n if (p.type === \"text\") return { type: \"text\", text: p.text };\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\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 const text = 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 const result: ChatResult = { text, usage };\n if (toolCalls && toolCalls.length > 0) result.toolCalls = toolCalls;\n return result;\n }\n\n return {\n name: config.name,\n chat,\n // gpt-4o-class models are multimodal — vision shares the chat path.\n vision: chat,\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\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; cost stays 0 for v1.\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 { toProviderTools, fromProviderToolCall } from \"./tools.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n ChatRequest,\n ChatResult,\n Message,\n ContentPart,\n ToolCall,\n} from \"../types.js\";\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 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\nexport function geminiAdapter(\n config: { apiKey?: string; baseUrl?: string } = {},\n): ProviderAdapter {\n const baseUrl = config.baseUrl ?? \"https://generativelanguage.googleapis.com/v1beta\";\n\n async function chat(req: ChatRequest): Promise<ChatResult> {\n const apiKey = config.apiKey ?? process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY;\n if (!apiKey) {\n throw new Error(\"gemini adapter: API key not set (env GOOGLE_API_KEY)\");\n }\n\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\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\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 return { name: \"gemini\", chat, vision: chat };\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 });\n}\n","// fal.ai image adapter (F5.3). Two 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// Auth header `Authorization: Key <FAL_KEY>`. No @fal-ai/client — plain fetch.\nimport { freshUsage } from \"../cost/usage.js\";\nimport type { ProviderAdapter, ImageRequest, ImageResult } from \"../types.js\";\n\ninterface FalImagesResponse {\n images?: { url?: string }[];\n error?: unknown;\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 fetch?: typeof fetch;\n}\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 async function image(req: ImageRequest): Promise<ImageResult> {\n const apiKey = config.apiKey ?? process.env.FAL_KEY;\n if (!apiKey) throw new Error(\"fal adapter: FAL_KEY not set\");\n const headers = { \"content-type\": \"application/json\", Authorization: `Key ${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\n const mode = config.mode ?? \"sync\";\n const url = await (mode === \"sync\"\n ? runSync(req.spec.model, headers, body)\n : runQueue(req.spec.model, headers, body));\n\n // fal cost is not token-based and rarely returned; record 0 (image capability).\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 return { url, usage };\n }\n\n async function runSync(\n model: string,\n headers: Record<string, string>,\n body: unknown,\n ): Promise<string> {\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 out;\n }\n\n async function runQueue(\n model: string,\n headers: Record<string, string>,\n body: unknown,\n ): Promise<string> {\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(`fal queue submit ${submitRes.status}`);\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() + timeoutMs;\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: generation FAILED\");\n if (Date.now() >= deadline) throw new Error(`fal queue: timed out after ${timeoutMs}ms`);\n await sleep(pollIntervalMs);\n }\n\n const resultRes = await doFetch(responseUrl, { headers });\n const result = (await resultRes.json()) as FalImagesResponse;\n const out = result.images?.[0]?.url;\n if (!out) throw new Error(\"fal queue: no image url in result\");\n return out;\n }\n\n return { name: \"fal\", 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 { falAdapter } from \"./fal.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 fal: falAdapter(),\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 } from \"../types.js\";\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 spentUsd = 0;\n\n constructor(private readonly config: BudgetConfig) {}\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 check(requested: number): void {\n const { perCallUsd, rollingUsd } = this.config;\n if (perCallUsd !== undefined && requested > perCallUsd) {\n throw new BudgetExceededError(\"per-call\", perCallUsd, this.spentUsd, requested);\n }\n if (rollingUsd !== undefined && this.spentUsd + requested > rollingUsd) {\n throw new BudgetExceededError(\"rolling\", rollingUsd, this.spentUsd, requested);\n }\n }\n\n /** Add an actual cost to the running total (after a successful call). */\n record(actual: number): void {\n this.spentUsd += actual;\n }\n\n get totalSpent(): number {\n return this.spentUsd;\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 single-user multimodal message (text + image) for a vision call. */\nexport function buildVisionMessages(input: VisionInput): Message[] {\n return [\n {\n role: \"user\",\n content: [\n { type: \"text\", text: input.prompt },\n { type: \"image\", image: input.image, mimeType: input.mimeType },\n ],\n },\n ];\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 ImageResult,\n EmbeddingResult,\n TranscribeResult,\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 \"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} 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 ...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 ...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 imageInputSchema = z.object({\n prompt: z.string(),\n width: z.number().int().positive().optional(),\n height: z.number().int().positive().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 ...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\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});\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 TranslateInput = z.infer<typeof translateInputSchema>;\nexport type ImageInput = z.infer<typeof imageInputSchema>;\nexport type EmbeddingInput = z.infer<typeof embeddingInputSchema>;\nexport type TranscribeInput = z.infer<typeof transcribeInputSchema>;\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 vision(input: VisionInput): Promise<ChatResult>;\n translate(input: TranslateInput): Promise<TranslateResult>;\n image(input: ImageInput): Promise<ImageResult>;\n embedding(input: EmbeddingInput): Promise<EmbeddingResult>;\n transcribe(input: TranscribeInput): Promise<TranscribeResult>;\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 { 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 { 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 {\n aiConfigSchema,\n chatInputSchema,\n visionInputSchema,\n translateInputSchema,\n imageInputSchema,\n embeddingInputSchema,\n transcribeInputSchema,\n} from \"./schema/inputs.js\";\nimport type {\n AiConfig,\n AiClient,\n ChatInput,\n VisionInput,\n TranslateInput,\n ImageInput,\n EmbeddingInput,\n TranscribeInput,\n} from \"./schema/inputs.js\";\nimport type {\n ChatResult,\n ImageResult,\n EmbeddingResult,\n TranscribeResult,\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\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 function preflight(spec: TierSpec, estInTokens: number, estOutTokens: number): void {\n if (!budget) return;\n 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 function settle(usage: Usage): void {\n if (budget) 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 ): Usage {\n usage.capability = capability;\n if (tier) usage.tier = tier;\n if (purpose) usage.purpose = purpose;\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) return input.messages;\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 const client: AiClient = {\n async chat(input: ChatInput): Promise<ChatResult> {\n input = chatInputSchema.parse(input);\n const spec = resolveTier(input.tier ?? \"smart\", input.override, cfg.defaults);\n const adapter = pickProvider(spec.provider);\n if (!adapter.chat) {\n throw new Error(`createAI: provider \"${spec.provider}\" does not support chat`);\n }\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 preflight(spec, estIn, input.maxTokens ?? 512);\n const t0 = performance.now();\n const res = await adapter.chat({\n messages,\n spec,\n tools: input.tools,\n maxTokens: input.maxTokens,\n temperature: input.temperature,\n });\n enrich(res.usage, \"chat\", input.tier ?? \"smart\", input.purpose, performance.now() - t0);\n settle(res.usage);\n await report(res.usage);\n return res;\n },\n\n async vision(input: VisionInput): Promise<ChatResult> {\n input = visionInputSchema.parse(input);\n const spec = resolveTier(input.tier ?? VISION_DEFAULT_TIER, input.override, cfg.defaults);\n const adapter = pickProvider(spec.provider);\n if (!adapter.vision) {\n throw new Error(`createAI: provider \"${spec.provider}\" does not support vision`);\n }\n const messages: Message[] = buildVisionMessages(input);\n // Rough: prompt tokens + ~1k for the image payload.\n preflight(spec, estTokens(input.prompt) + 1000, 512);\n const t0 = performance.now();\n const res = await adapter.vision({ messages, spec });\n enrich(res.usage, \"vision\", input.tier ?? VISION_DEFAULT_TIER, input.purpose, performance.now() - t0);\n settle(res.usage);\n await report(res.usage);\n return res;\n },\n\n async translate(input: TranslateInput): Promise<TranslateResult> {\n input = translateInputSchema.parse(input);\n const spec = resolveTier(input.tier ?? TRANSLATE_DEFAULT_TIER, input.override, cfg.defaults);\n const adapter = pickProvider(spec.provider);\n if (!adapter.chat) {\n throw new Error(`createAI: provider \"${spec.provider}\" does not support chat (translate routes through chat)`);\n }\n const messages: Message[] = buildTranslateMessages(input);\n const estIn = estTokens(input.text) + 40;\n preflight(spec, estIn, estIn);\n const t0 = performance.now();\n const res = await adapter.chat({ messages, spec });\n enrich(res.usage, \"translate\", input.tier ?? TRANSLATE_DEFAULT_TIER, input.purpose, performance.now() - t0);\n settle(res.usage);\n await report(res.usage);\n return { text: res.text, usage: res.usage };\n },\n\n async image(input: ImageInput): Promise<ImageResult> {\n input = imageInputSchema.parse(input);\n const spec: TierSpec = { ...DEFAULT_IMAGE_SPEC, ...input.override };\n const adapter = pickProvider(spec.provider);\n if (!adapter.image) {\n throw new Error(`createAI: provider \"${spec.provider}\" does not support image`);\n }\n // Image cost is not token-based; pre-flight estimates 0 (only a per-call\n // ceiling of 0 would block). Actual cost is folded in post-call.\n preflight(spec, 0, 0);\n const t0 = performance.now();\n const res = await adapter.image({\n prompt: input.prompt,\n spec,\n width: input.width,\n height: input.height,\n });\n enrich(res.usage, \"image\", undefined, input.purpose, performance.now() - t0);\n settle(res.usage);\n await report(res.usage);\n return res;\n },\n\n async embedding(input: EmbeddingInput): Promise<EmbeddingResult> {\n input = embeddingInputSchema.parse(input);\n const spec = resolveTier(input.tier ?? EMBEDDING_DEFAULT_TIER, input.override, cfg.defaults);\n const adapter = pickProvider(spec.provider);\n if (!adapter.embedding) {\n throw new Error(`createAI: provider \"${spec.provider}\" does not support embedding`);\n }\n const text = Array.isArray(input.text) ? input.text : [input.text];\n preflight(spec, text.reduce((n, t) => n + estTokens(t), 0), 0);\n const t0 = performance.now();\n const res = await adapter.embedding({ input: text, spec });\n enrich(res.usage, \"embedding\", input.tier ?? EMBEDDING_DEFAULT_TIER, input.purpose, performance.now() - t0);\n settle(res.usage);\n await report(res.usage);\n return res;\n },\n\n async transcribe(input: TranscribeInput): Promise<TranscribeResult> {\n input = transcribeInputSchema.parse(input);\n const spec: TierSpec = { ...DEFAULT_TRANSCRIBE_SPEC, ...input.override };\n const adapter = pickProvider(spec.provider);\n if (!adapter.transcribe) {\n throw new Error(`createAI: provider \"${spec.provider}\" does not support transcribe`);\n }\n const audio = await resolveAudio(input.audio);\n preflight(spec, 0, 0);\n const t0 = performance.now();\n const res = await adapter.transcribe({ audio, language: input.language, spec });\n enrich(res.usage, \"transcribe\", undefined, input.purpose, performance.now() - t0);\n settle(res.usage);\n await report(res.usage);\n return res;\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/** 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 openai: openaiStubAdapter,\n fal: falStubAdapter,\n};\n","// AUTO-GENERATED by scripts/gen-version.mjs — do not edit, do not commit.\nexport const VERSION = \"0.1.0\" as const;\nexport const SDK_TAG = \"@broberg/ai-sdk@0.1.0\" as const;\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 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.\nimport { Database } from \"bun:sqlite\";\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\nexport function sqliteSink(config: SqliteSinkConfig): CostSink {\n const db = new Database(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\n return {\n record(usage: Usage): void {\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. */\nexport function getCostSummary(dbPath: string): CostSummary {\n const db = new Database(dbPath, { readonly: true });\n const total = db\n .query<{ total: number | null }, []>(`SELECT SUM(cost_usd) AS total FROM ai_usage`)\n .get();\n const byProvider: Record<string, number> = {};\n for (const row of db\n .query<{ provider: string; sum: number }, []>(\n `SELECT provider, SUM(cost_usd) AS sum FROM ai_usage GROUP BY provider`,\n )\n .all()) {\n byProvider[row.provider] = row.sum;\n }\n const byCapability: Record<string, number> = {};\n for (const row of db\n .query<{ capability: string; sum: number }, []>(\n `SELECT capability, SUM(cost_usd) AS sum FROM ai_usage GROUP BY capability`,\n )\n .all()) {\n byCapability[row.capability] = row.sum;\n }\n return { totalUsd: total?.total ?? 0, byProvider, byCapability };\n}\n"],"mappings":"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","names":["res"]}
1
+ {"version":3,"sources":["../src/routing/tier-map.ts","../src/transport/http.ts","../src/transport/subprocess.ts","../src/providers/tools.ts","../src/cost/pricing.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/fal.ts","../src/providers/registry.ts","../src/cost/budget.ts","../src/capabilities/vision.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/cost/sinks/noop.ts","../src/cost/sinks/multi.ts","../src/cost/sinks/upmetrics.ts","../src/cost/sinks/discord.ts","../src/cost/sinks/sqlite.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. Model IDs are current at scaffold time; callers pin their\n * own via config. `cheap` routes through the local `claude -p` subprocess\n * (Max plan → costUsd 0); everything else is HTTP. */\nexport const DEFAULT_TIER_MAP: Record<Tier, TierSpec> = {\n fast: { provider: \"anthropic\", model: \"claude-haiku-4-5\", transport: \"http\" },\n smart: { provider: \"anthropic\", model: \"claude-sonnet-4-6\", transport: \"http\" },\n powerful: { provider: \"anthropic\", model: \"claude-opus-4-8\", transport: \"http\" },\n cheap: { provider: \"anthropic\", model: \"claude-haiku-4-5\", transport: \"subprocess\" },\n vision: { provider: \"anthropic\", model: \"claude-sonnet-4-6\", transport: \"http\" },\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","// 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","// Versioned per-(provider, model) pricing. F3.6 populates the table + adds tests\n// + MiniMax coverage. F3.1 ships the type + lookup with an empty table, so\n// computeCost returns 0 for every model until F3.6 lands (calls still complete).\nexport interface PricingEntry {\n /** USD per 1M input tokens. */\n inputPer1M: number;\n /** USD per 1M output tokens. */\n outputPer1M: number;\n /** USD per 1M cache-read tokens (falls back to input rate if unset). */\n cacheReadPer1M?: number;\n /** USD per 1M cache-write/creation tokens (falls back to input rate if unset). */\n cacheWritePer1M?: number;\n /** Pricing snapshot version (date or tag) so stale entries are detectable. */\n version: string;\n}\n\n// USD per 1M tokens. Anthropic cache multipliers follow the standard model:\n// cache-read ≈ 0.1× input, cache-write ≈ 1.25× input. Verified against the\n// pricing tables in cms (packages/cms-ai/src/providers) + trail (model-lab).\n// MiniMax M2.7 is an estimate pending confirmation against OpenRouter's live\n// price page — flagged in its version string.\nconst V = \"2026-06-02\";\n\n/** Keyed `${provider}:${model}`. */\nconst PRICING: Record<string, PricingEntry> = {\n // Anthropic (direct API). DEFAULT_TIER_MAP: fast/cheap=haiku, smart/vision=sonnet, powerful=opus.\n \"anthropic:claude-haiku-4-5\": {\n inputPer1M: 0.8,\n outputPer1M: 4.0,\n cacheReadPer1M: 0.08,\n cacheWritePer1M: 1.0,\n version: V,\n },\n \"anthropic:claude-sonnet-4-6\": {\n inputPer1M: 3.0,\n outputPer1M: 15.0,\n cacheReadPer1M: 0.3,\n cacheWritePer1M: 3.75,\n version: V,\n },\n \"anthropic:claude-opus-4-8\": {\n inputPer1M: 15.0,\n outputPer1M: 75.0,\n cacheReadPer1M: 1.5,\n cacheWritePer1M: 18.75,\n version: V,\n },\n\n // OpenAI. embedding default tier = text-embedding-3-small (no output tokens).\n \"openai:text-embedding-3-small\": { inputPer1M: 0.02, outputPer1M: 0, version: V },\n \"openai:text-embedding-3-large\": { inputPer1M: 0.13, outputPer1M: 0, version: V },\n \"openai:gpt-4o\": { inputPer1M: 2.5, outputPer1M: 10.0, version: V },\n \"openai:gpt-4o-mini\": { inputPer1M: 0.15, outputPer1M: 0.6, version: V },\n // Whisper is priced per minute, not per token — not representable here; transcribe\n // (F5.6) computes its own cost. Listed as 0 so token-based compute never charges it.\n \"openai:whisper-1\": { inputPer1M: 0, outputPer1M: 0, version: V },\n\n // OpenRouter (meta-router — model slugs include the upstream vendor).\n \"openrouter:anthropic/claude-sonnet-4-6\": { inputPer1M: 3.0, outputPer1M: 15.0, version: V },\n \"openrouter:anthropic/claude-haiku-4-5\": { inputPer1M: 0.8, outputPer1M: 4.0, version: V },\n \"openrouter:google/gemini-2.5-flash\": { inputPer1M: 0.3, outputPer1M: 2.5, version: V },\n \"openrouter:minimax/minimax-m2.7\": {\n inputPer1M: 0.3,\n outputPer1M: 1.2,\n version: `${V}-estimate`,\n },\n\n // Google Gemini (direct). Image-gen model used by cms.\n \"google:gemini-2.5-flash\": { inputPer1M: 0.3, outputPer1M: 2.5, version: V },\n};\n\nexport function getPrice(provider: string, model: string): PricingEntry | undefined {\n return PRICING[`${provider}:${model}`];\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 { toProviderTools, fromProviderToolCall } from \"./tools.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n ChatRequest,\n ChatResult,\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 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 } = {},\n): ProviderAdapter {\n const baseUrl = config.baseUrl ?? \"https://api.anthropic.com\";\n const version = config.anthropicVersion ?? \"2023-06-01\";\n\n async function chatHttp(req: ChatRequest): Promise<ChatResult> {\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\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 } else {\n messages.push({ role: m.role === \"assistant\" ? \"assistant\" : \"user\", content: contentBlocks(m.content) });\n }\n }\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\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 return { name: \"anthropic\", chat, vision: chat };\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 { toProviderTools, fromProviderToolCall } from \"./tools.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n ChatRequest,\n ChatResult,\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}\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 };\n error?: unknown;\n}\n\n/** SDK message → OpenAI message (string content, or multimodal parts for vision). */\nfunction 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 return base;\n }\n const content = m.content.map((p) => {\n if (p.type === \"text\") return { type: \"text\", text: p.text };\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\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 const text = 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 const result: ChatResult = { text, usage };\n if (toolCalls && toolCalls.length > 0) result.toolCalls = toolCalls;\n return result;\n }\n\n return {\n name: config.name,\n chat,\n // gpt-4o-class models are multimodal — vision shares the chat path.\n vision: chat,\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\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; cost stays 0 for v1.\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 { toProviderTools, fromProviderToolCall } from \"./tools.js\";\nimport { freshUsage } from \"../cost/usage.js\";\nimport type {\n ProviderAdapter,\n ChatRequest,\n ChatResult,\n Message,\n ContentPart,\n ToolCall,\n} from \"../types.js\";\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 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\nexport function geminiAdapter(\n config: { apiKey?: string; baseUrl?: string } = {},\n): ProviderAdapter {\n const baseUrl = config.baseUrl ?? \"https://generativelanguage.googleapis.com/v1beta\";\n\n async function chat(req: ChatRequest): Promise<ChatResult> {\n const apiKey = config.apiKey ?? process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY;\n if (!apiKey) {\n throw new Error(\"gemini adapter: API key not set (env GOOGLE_API_KEY)\");\n }\n\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\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\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 return { name: \"gemini\", chat, vision: chat };\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 });\n}\n","// fal.ai image adapter (F5.3). Two 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// Auth header `Authorization: Key <FAL_KEY>`. No @fal-ai/client — plain fetch.\nimport { freshUsage } from \"../cost/usage.js\";\nimport type { ProviderAdapter, ImageRequest, ImageResult } from \"../types.js\";\n\ninterface FalImagesResponse {\n images?: { url?: string }[];\n error?: unknown;\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 fetch?: typeof fetch;\n /** Override the per-image USD price (else a built-in estimate per model, 0 if unknown). */\n pricePerImage?: 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-pro\": 0.05,\n \"fal-ai/flux-pro/v1.1\": 0.04,\n};\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 async function image(req: ImageRequest): Promise<ImageResult> {\n const apiKey = config.apiKey ?? process.env.FAL_KEY;\n if (!apiKey) throw new Error(\"fal adapter: FAL_KEY not set\");\n const headers = { \"content-type\": \"application/json\", Authorization: `Key ${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\n const mode = config.mode ?? \"sync\";\n const url = await (mode === \"sync\"\n ? runSync(req.spec.model, headers, body)\n : runQueue(req.spec.model, headers, body));\n\n // fal returns no price; estimate per-image (one image per call) so usage.costUsd\n // isn't silently 0. Override via config.pricePerImage.\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;\n return { url, usage };\n }\n\n async function runSync(\n model: string,\n headers: Record<string, string>,\n body: unknown,\n ): Promise<string> {\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 out;\n }\n\n async function runQueue(\n model: string,\n headers: Record<string, string>,\n body: unknown,\n ): Promise<string> {\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(`fal queue submit ${submitRes.status}`);\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() + timeoutMs;\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: generation FAILED\");\n if (Date.now() >= deadline) throw new Error(`fal queue: timed out after ${timeoutMs}ms`);\n await sleep(pollIntervalMs);\n }\n\n const resultRes = await doFetch(responseUrl, { headers });\n const result = (await resultRes.json()) as FalImagesResponse;\n const out = result.images?.[0]?.url;\n if (!out) throw new Error(\"fal queue: no image url in result\");\n return out;\n }\n\n return { name: \"fal\", 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 { falAdapter } from \"./fal.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 fal: falAdapter(),\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 } from \"../types.js\";\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 spentUsd = 0;\n\n constructor(private readonly config: BudgetConfig) {}\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 check(requested: number): void {\n const { perCallUsd, rollingUsd } = this.config;\n if (perCallUsd !== undefined && requested > perCallUsd) {\n throw new BudgetExceededError(\"per-call\", perCallUsd, this.spentUsd, requested);\n }\n if (rollingUsd !== undefined && this.spentUsd + requested > rollingUsd) {\n throw new BudgetExceededError(\"rolling\", rollingUsd, this.spentUsd, requested);\n }\n }\n\n /** Add an actual cost to the running total (after a successful call). */\n record(actual: number): void {\n this.spentUsd += actual;\n }\n\n get totalSpent(): number {\n return this.spentUsd;\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 single-user multimodal message (text + image) for a vision call. */\nexport function buildVisionMessages(input: VisionInput): Message[] {\n return [\n {\n role: \"user\",\n content: [\n { type: \"text\", text: input.prompt },\n { type: \"image\", image: input.image, mimeType: input.mimeType },\n ],\n },\n ];\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 ImageResult,\n EmbeddingResult,\n TranscribeResult,\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 \"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} 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 ...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 ...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 imageInputSchema = z.object({\n prompt: z.string(),\n width: z.number().int().positive().optional(),\n height: z.number().int().positive().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 ...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\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});\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 TranslateInput = z.infer<typeof translateInputSchema>;\nexport type ImageInput = z.infer<typeof imageInputSchema>;\nexport type EmbeddingInput = z.infer<typeof embeddingInputSchema>;\nexport type TranscribeInput = z.infer<typeof transcribeInputSchema>;\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 vision(input: VisionInput): Promise<ChatResult>;\n translate(input: TranslateInput): Promise<TranslateResult>;\n image(input: ImageInput): Promise<ImageResult>;\n embedding(input: EmbeddingInput): Promise<EmbeddingResult>;\n transcribe(input: TranscribeInput): Promise<TranscribeResult>;\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 { 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 { 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 {\n aiConfigSchema,\n chatInputSchema,\n visionInputSchema,\n translateInputSchema,\n imageInputSchema,\n embeddingInputSchema,\n transcribeInputSchema,\n} from \"./schema/inputs.js\";\nimport type {\n AiConfig,\n AiClient,\n ChatInput,\n VisionInput,\n TranslateInput,\n ImageInput,\n EmbeddingInput,\n TranscribeInput,\n} from \"./schema/inputs.js\";\nimport type {\n ChatResult,\n ImageResult,\n EmbeddingResult,\n TranscribeResult,\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\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 function preflight(spec: TierSpec, estInTokens: number, estOutTokens: number): void {\n if (!budget) return;\n 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 function settle(usage: Usage): void {\n if (budget) 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 ): Usage {\n usage.capability = capability;\n if (tier) usage.tier = tier;\n if (purpose) usage.purpose = purpose;\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) return input.messages;\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 /** 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 estIn: number;\n estOut: number;\n invoke: (spec: TierSpec) => Promise<R>;\n }): Promise<R> {\n const routes: TierSpec[] = [\n 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 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);\n 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 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 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 });\n },\n });\n },\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 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 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 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 return runCapability({\n primary: { ...DEFAULT_IMAGE_SPEC, ...input.override },\n fallback: input.fallback,\n capability: \"image\",\n purpose: input.purpose,\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({ prompt: input.prompt, spec, width: input.width, height: input.height });\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 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 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, spec });\n },\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/** 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 openai: openaiStubAdapter,\n fal: falStubAdapter,\n};\n","// AUTO-GENERATED by scripts/gen-version.mjs — do not edit, do not commit.\nexport const VERSION = \"0.1.2\" as const;\nexport const SDK_TAG = \"@broberg/ai-sdk@0.1.2\" as const;\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 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"],"mappings":"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","names":["res"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@broberg/ai-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Unified AI/LLM SDK — one facade, all providers, all capabilities, first-class cost control on every call.",
5
5
  "type": "module",
6
6
  "license": "FSL-1.1-Apache-2.0",