@broberg/ai-sdk 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +124 -44
- package/dist/index.js +102 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,6 +5,8 @@ var DEFAULT_TIER_MAP = {
|
|
|
5
5
|
powerful: { provider: "anthropic", model: "claude-opus-4-8", transport: "http" },
|
|
6
6
|
cheap: { provider: "anthropic", model: "claude-haiku-4-5", transport: "subprocess" },
|
|
7
7
|
vision: { provider: "anthropic", model: "claude-sonnet-4-6", transport: "http" },
|
|
8
|
+
// Native video understanding — Gemini leads; flash-lite is the cheap default (F019).
|
|
9
|
+
video: { provider: "gemini", model: "gemini-2.5-flash-lite", transport: "http" },
|
|
8
10
|
embedding: { provider: "openai", model: "text-embedding-3-small", transport: "http" }
|
|
9
11
|
};
|
|
10
12
|
function resolveTier(tier, override, configMap) {
|
|
@@ -205,6 +207,7 @@ function parseArgs(raw) {
|
|
|
205
207
|
|
|
206
208
|
// src/cost/pricing.ts
|
|
207
209
|
var V = "2026-06-02";
|
|
210
|
+
var MS = "2026-06-04-mistral.ai";
|
|
208
211
|
var PRICING = {
|
|
209
212
|
// Anthropic (direct API). DEFAULT_TIER_MAP: fast/cheap=haiku, smart/vision=sonnet, powerful=opus.
|
|
210
213
|
"anthropic:claude-haiku-4-5": {
|
|
@@ -236,19 +239,46 @@ var PRICING = {
|
|
|
236
239
|
// Whisper is priced per minute, not per token — not representable here; transcribe
|
|
237
240
|
// (F5.6) computes its own cost. Listed as 0 so token-based compute never charges it.
|
|
238
241
|
"openai:whisper-1": { inputPer1M: 0, outputPer1M: 0, version: V },
|
|
239
|
-
// OpenRouter (meta-router — model slugs include the upstream vendor).
|
|
240
|
-
|
|
241
|
-
|
|
242
|
+
// OpenRouter (meta-router — model slugs include the upstream vendor). Slugs use
|
|
243
|
+
// dots (claude-sonnet-4.6) to match OpenRouter's live ids; the dashed forms
|
|
244
|
+
// never matched a real call. Caught by the F014 catalogue research.
|
|
245
|
+
"openrouter:anthropic/claude-sonnet-4.6": { inputPer1M: 3, outputPer1M: 15, version: V },
|
|
246
|
+
// OpenRouter ground-truth $1/$5 — a markup over Anthropic-direct's $0.8/$4
|
|
247
|
+
// (the `anthropic:` entry above). Was masked while the slug used dashes.
|
|
248
|
+
"openrouter:anthropic/claude-haiku-4.5": { inputPer1M: 1, outputPer1M: 5, version: "2026-06-04" },
|
|
242
249
|
"openrouter:google/gemini-2.5-flash": { inputPer1M: 0.3, outputPer1M: 2.5, version: V },
|
|
250
|
+
// Ground-truth from OpenRouter /api/v1/models (was a 0.3 estimate; now 0.279).
|
|
243
251
|
"openrouter:minimax/minimax-m2.7": {
|
|
244
|
-
inputPer1M: 0.
|
|
252
|
+
inputPer1M: 0.279,
|
|
245
253
|
outputPer1M: 1.2,
|
|
246
|
-
version:
|
|
254
|
+
version: "2026-06-04"
|
|
247
255
|
},
|
|
248
256
|
// Google Gemini (direct). Provider key is "gemini" — matches the adapter's
|
|
249
257
|
// usage.provider + the override.provider callers pass. (Image-gen models are
|
|
250
258
|
// priced per-image in the adapter, not here.)
|
|
251
|
-
"gemini:gemini-2.5-flash": { inputPer1M: 0.3, outputPer1M: 2.5, version: V }
|
|
259
|
+
"gemini:gemini-2.5-flash": { inputPer1M: 0.3, outputPer1M: 2.5, version: V },
|
|
260
|
+
// flash-lite is the default `video` tier (F019) — cheap native video understanding.
|
|
261
|
+
"gemini:gemini-2.5-flash-lite": { inputPer1M: 0.1, outputPer1M: 0.4, version: "2026-06-04-or-xref" },
|
|
262
|
+
// Mistral (direct, La Plateforme). Official prices from mistral.ai/pricing
|
|
263
|
+
// (2026-06-04, per Christian's CD report). EU/Paris-hosted — the designated
|
|
264
|
+
// GDPR-safe provider for client/personal-data workloads (see F015). NB:
|
|
265
|
+
// medium-3.5 is the premium "Vibe" coding tier ($1.5/$7.5); Large 3 ($0.5/$1.5)
|
|
266
|
+
// is the cheaper frontier general-purpose model despite the higher number.
|
|
267
|
+
"mistral:mistral-large-latest": { inputPer1M: 0.5, outputPer1M: 1.5, version: MS },
|
|
268
|
+
"mistral:mistral-large-2512": { inputPer1M: 0.5, outputPer1M: 1.5, version: MS },
|
|
269
|
+
"mistral:mistral-medium-latest": { inputPer1M: 1.5, outputPer1M: 7.5, version: MS },
|
|
270
|
+
"mistral:mistral-medium-3.5": { inputPer1M: 1.5, outputPer1M: 7.5, version: MS },
|
|
271
|
+
"mistral:mistral-medium-3": { inputPer1M: 0.4, outputPer1M: 2, version: "2026-06-04-or-xref" },
|
|
272
|
+
"mistral:mistral-small-latest": { inputPer1M: 0.1, outputPer1M: 0.3, version: MS },
|
|
273
|
+
"mistral:mistral-small-2603": { inputPer1M: 0.1, outputPer1M: 0.3, version: MS },
|
|
274
|
+
"mistral:ministral-3b-latest": { inputPer1M: 0.1, outputPer1M: 0.1, version: MS },
|
|
275
|
+
"mistral:ministral-8b-latest": { inputPer1M: 0.15, outputPer1M: 0.15, version: MS },
|
|
276
|
+
"mistral:ministral-14b-latest": { inputPer1M: 0.2, outputPer1M: 0.2, version: MS },
|
|
277
|
+
"mistral:magistral-medium-latest": { inputPer1M: 2, outputPer1M: 5, version: MS },
|
|
278
|
+
"mistral:magistral-small-latest": { inputPer1M: 0.5, outputPer1M: 1.5, version: MS },
|
|
279
|
+
"mistral:devstral-latest": { inputPer1M: 0.4, outputPer1M: 2, version: MS },
|
|
280
|
+
"mistral:codestral-latest": { inputPer1M: 0.3, outputPer1M: 0.9, version: MS },
|
|
281
|
+
"mistral:open-mistral-nemo": { inputPer1M: 0.15, outputPer1M: 0.15, version: MS }
|
|
252
282
|
};
|
|
253
283
|
function getPrice(provider, model) {
|
|
254
284
|
const exact = PRICING[`${provider}:${model}`];
|
|
@@ -302,6 +332,9 @@ function contentBlocks(content) {
|
|
|
302
332
|
if (typeof content === "string") return content;
|
|
303
333
|
return content.map((p) => {
|
|
304
334
|
if (p.type === "text") return { type: "text", text: p.text };
|
|
335
|
+
if (p.type === "video") {
|
|
336
|
+
throw new Error("anthropic adapter: video input is not supported \u2014 use a video provider (e.g. gemini)");
|
|
337
|
+
}
|
|
305
338
|
if (typeof p.image === "string" && /^https?:\/\//.test(p.image)) {
|
|
306
339
|
return { type: "image", source: { type: "url", url: p.image } };
|
|
307
340
|
}
|
|
@@ -552,6 +585,10 @@ function toOpenAIMessage(m) {
|
|
|
552
585
|
}
|
|
553
586
|
const content = m.content.map((p) => {
|
|
554
587
|
if (p.type === "text") return { type: "text", text: p.text };
|
|
588
|
+
if (p.type === "video") {
|
|
589
|
+
const url2 = typeof p.video === "string" ? p.video : `data:${p.mimeType ?? "video/mp4"};base64,${Buffer.from(p.video).toString("base64")}`;
|
|
590
|
+
return { type: "video_url", video_url: { url: url2 } };
|
|
591
|
+
}
|
|
555
592
|
const url = typeof p.image === "string" ? p.image : `data:${p.mimeType ?? "image/png"};base64,${Buffer.from(p.image).toString("base64")}`;
|
|
556
593
|
return { type: "image_url", image_url: { url } };
|
|
557
594
|
});
|
|
@@ -786,6 +823,10 @@ function partsFrom(content) {
|
|
|
786
823
|
if (typeof content === "string") return [{ text: content }];
|
|
787
824
|
return content.map((p) => {
|
|
788
825
|
if (p.type === "text") return { text: p.text };
|
|
826
|
+
if (p.type === "video") {
|
|
827
|
+
const data2 = typeof p.video === "string" ? p.video.replace(/^data:[^;]+;base64,/, "") : Buffer.from(p.video).toString("base64");
|
|
828
|
+
return { inlineData: { mimeType: p.mimeType ?? "video/mp4", data: data2 } };
|
|
829
|
+
}
|
|
789
830
|
const data = typeof p.image === "string" ? p.image.replace(/^data:[^;]+;base64,/, "") : Buffer.from(p.image).toString("base64");
|
|
790
831
|
return { inlineData: { mimeType: p.mimeType ?? "image/png", data } };
|
|
791
832
|
});
|
|
@@ -983,6 +1024,15 @@ function openrouterAdapter(config = {}) {
|
|
|
983
1024
|
});
|
|
984
1025
|
}
|
|
985
1026
|
|
|
1027
|
+
// src/providers/mistral.ts
|
|
1028
|
+
function mistralAdapter(config = {}) {
|
|
1029
|
+
return makeOpenAICompatibleAdapter({
|
|
1030
|
+
name: "mistral",
|
|
1031
|
+
baseUrl: config.baseUrl ?? "https://api.mistral.ai/v1",
|
|
1032
|
+
apiKey: config.apiKey
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
|
|
986
1036
|
// src/providers/fal.ts
|
|
987
1037
|
var FAL_IMAGE_PRICE_ESTIMATE = {
|
|
988
1038
|
"fal-ai/flux/schnell": 3e-3,
|
|
@@ -1070,6 +1120,7 @@ var defaultProviders = {
|
|
|
1070
1120
|
gemini: geminiAdapter(),
|
|
1071
1121
|
deepinfra: deepinfraAdapter(),
|
|
1072
1122
|
openrouter: openrouterAdapter(),
|
|
1123
|
+
mistral: mistralAdapter(),
|
|
1073
1124
|
fal: falAdapter()
|
|
1074
1125
|
};
|
|
1075
1126
|
|
|
@@ -1144,6 +1195,20 @@ function buildVisionMessages(input) {
|
|
|
1144
1195
|
];
|
|
1145
1196
|
}
|
|
1146
1197
|
|
|
1198
|
+
// src/capabilities/video.ts
|
|
1199
|
+
var VIDEO_DEFAULT_TIER = "video";
|
|
1200
|
+
function buildVideoMessages(input) {
|
|
1201
|
+
return [
|
|
1202
|
+
{
|
|
1203
|
+
role: "user",
|
|
1204
|
+
content: [
|
|
1205
|
+
{ type: "video", video: input.video, mimeType: input.mimeType },
|
|
1206
|
+
{ type: "text", text: input.prompt }
|
|
1207
|
+
]
|
|
1208
|
+
}
|
|
1209
|
+
];
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1147
1212
|
// src/capabilities/translate.ts
|
|
1148
1213
|
var TRANSLATE_DEFAULT_TIER = "fast";
|
|
1149
1214
|
var TRANSLATE_SYSTEM = "You are a translation engine. Translate the user's text only. Return the translation and nothing else \u2014 no preamble, no quotes.";
|
|
@@ -1279,6 +1344,7 @@ var tierSchema = z.enum([
|
|
|
1279
1344
|
"powerful",
|
|
1280
1345
|
"cheap",
|
|
1281
1346
|
"vision",
|
|
1347
|
+
"video",
|
|
1282
1348
|
"embedding"
|
|
1283
1349
|
]);
|
|
1284
1350
|
var tierSpecSchema = z.object({
|
|
@@ -1336,6 +1402,12 @@ var visionInputSchema = z.object({
|
|
|
1336
1402
|
mimeType: z.string().optional(),
|
|
1337
1403
|
...callOptions
|
|
1338
1404
|
});
|
|
1405
|
+
var videoInputSchema = z.object({
|
|
1406
|
+
video: z.union([z.string(), z.instanceof(Uint8Array)]),
|
|
1407
|
+
prompt: z.string(),
|
|
1408
|
+
mimeType: z.string().optional(),
|
|
1409
|
+
...callOptions
|
|
1410
|
+
});
|
|
1339
1411
|
var translateInputSchema = z.object({
|
|
1340
1412
|
text: z.string(),
|
|
1341
1413
|
to: z.string(),
|
|
@@ -1561,6 +1633,27 @@ function createAI(config = {}) {
|
|
|
1561
1633
|
}
|
|
1562
1634
|
});
|
|
1563
1635
|
},
|
|
1636
|
+
async video(input) {
|
|
1637
|
+
input = videoInputSchema.parse(input);
|
|
1638
|
+
const tier = input.tier ?? VIDEO_DEFAULT_TIER;
|
|
1639
|
+
const messages = buildVideoMessages(input);
|
|
1640
|
+
return runCapability({
|
|
1641
|
+
primary: resolveTier(tier, input.override, cfg.defaults),
|
|
1642
|
+
fallback: input.fallback,
|
|
1643
|
+
capability: "video",
|
|
1644
|
+
tier,
|
|
1645
|
+
purpose: input.purpose,
|
|
1646
|
+
labels: input.labels,
|
|
1647
|
+
estIn: estTokens(input.prompt) + 4e3,
|
|
1648
|
+
// prompt + video tokens (native video ≈ frames)
|
|
1649
|
+
estOut: 512,
|
|
1650
|
+
invoke: async (spec) => {
|
|
1651
|
+
const adapter = pickProvider(spec.provider);
|
|
1652
|
+
if (!adapter.vision) throw new Error(`createAI: provider "${spec.provider}" does not support video`);
|
|
1653
|
+
return adapter.vision({ messages, spec });
|
|
1654
|
+
}
|
|
1655
|
+
});
|
|
1656
|
+
},
|
|
1564
1657
|
async translate(input) {
|
|
1565
1658
|
input = translateInputSchema.parse(input);
|
|
1566
1659
|
const tier = input.tier ?? TRANSLATE_DEFAULT_TIER;
|
|
@@ -1727,8 +1820,8 @@ var stubProviders = {
|
|
|
1727
1820
|
};
|
|
1728
1821
|
|
|
1729
1822
|
// src/version.ts
|
|
1730
|
-
var VERSION = "0.
|
|
1731
|
-
var SDK_TAG = "@broberg/ai-sdk@0.
|
|
1823
|
+
var VERSION = "0.6.0";
|
|
1824
|
+
var SDK_TAG = "@broberg/ai-sdk@0.6.0";
|
|
1732
1825
|
|
|
1733
1826
|
// src/cost/budget-store.ts
|
|
1734
1827
|
function sqliteBudgetStore(config) {
|
|
@@ -1986,6 +2079,7 @@ export {
|
|
|
1986
2079
|
makeContracts,
|
|
1987
2080
|
makeOpenAICompatibleAdapter,
|
|
1988
2081
|
messageSchema,
|
|
2082
|
+
mistralAdapter,
|
|
1989
2083
|
multiSink,
|
|
1990
2084
|
noopSink,
|
|
1991
2085
|
openaiAdapter,
|