@broberg/ai-sdk 0.5.0 → 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 +105 -9
- 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,17 +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
|
-
// Google Gemini (direct).
|
|
249
|
-
|
|
256
|
+
// Google Gemini (direct). Provider key is "gemini" — matches the adapter's
|
|
257
|
+
// usage.provider + the override.provider callers pass. (Image-gen models are
|
|
258
|
+
// priced per-image in the adapter, not here.)
|
|
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 }
|
|
250
282
|
};
|
|
251
283
|
function getPrice(provider, model) {
|
|
252
284
|
const exact = PRICING[`${provider}:${model}`];
|
|
@@ -300,6 +332,9 @@ function contentBlocks(content) {
|
|
|
300
332
|
if (typeof content === "string") return content;
|
|
301
333
|
return content.map((p) => {
|
|
302
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
|
+
}
|
|
303
338
|
if (typeof p.image === "string" && /^https?:\/\//.test(p.image)) {
|
|
304
339
|
return { type: "image", source: { type: "url", url: p.image } };
|
|
305
340
|
}
|
|
@@ -550,6 +585,10 @@ function toOpenAIMessage(m) {
|
|
|
550
585
|
}
|
|
551
586
|
const content = m.content.map((p) => {
|
|
552
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
|
+
}
|
|
553
592
|
const url = typeof p.image === "string" ? p.image : `data:${p.mimeType ?? "image/png"};base64,${Buffer.from(p.image).toString("base64")}`;
|
|
554
593
|
return { type: "image_url", image_url: { url } };
|
|
555
594
|
});
|
|
@@ -784,6 +823,10 @@ function partsFrom(content) {
|
|
|
784
823
|
if (typeof content === "string") return [{ text: content }];
|
|
785
824
|
return content.map((p) => {
|
|
786
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
|
+
}
|
|
787
830
|
const data = typeof p.image === "string" ? p.image.replace(/^data:[^;]+;base64,/, "") : Buffer.from(p.image).toString("base64");
|
|
788
831
|
return { inlineData: { mimeType: p.mimeType ?? "image/png", data } };
|
|
789
832
|
});
|
|
@@ -981,6 +1024,15 @@ function openrouterAdapter(config = {}) {
|
|
|
981
1024
|
});
|
|
982
1025
|
}
|
|
983
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
|
+
|
|
984
1036
|
// src/providers/fal.ts
|
|
985
1037
|
var FAL_IMAGE_PRICE_ESTIMATE = {
|
|
986
1038
|
"fal-ai/flux/schnell": 3e-3,
|
|
@@ -1068,6 +1120,7 @@ var defaultProviders = {
|
|
|
1068
1120
|
gemini: geminiAdapter(),
|
|
1069
1121
|
deepinfra: deepinfraAdapter(),
|
|
1070
1122
|
openrouter: openrouterAdapter(),
|
|
1123
|
+
mistral: mistralAdapter(),
|
|
1071
1124
|
fal: falAdapter()
|
|
1072
1125
|
};
|
|
1073
1126
|
|
|
@@ -1142,6 +1195,20 @@ function buildVisionMessages(input) {
|
|
|
1142
1195
|
];
|
|
1143
1196
|
}
|
|
1144
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
|
+
|
|
1145
1212
|
// src/capabilities/translate.ts
|
|
1146
1213
|
var TRANSLATE_DEFAULT_TIER = "fast";
|
|
1147
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.";
|
|
@@ -1277,6 +1344,7 @@ var tierSchema = z.enum([
|
|
|
1277
1344
|
"powerful",
|
|
1278
1345
|
"cheap",
|
|
1279
1346
|
"vision",
|
|
1347
|
+
"video",
|
|
1280
1348
|
"embedding"
|
|
1281
1349
|
]);
|
|
1282
1350
|
var tierSpecSchema = z.object({
|
|
@@ -1334,6 +1402,12 @@ var visionInputSchema = z.object({
|
|
|
1334
1402
|
mimeType: z.string().optional(),
|
|
1335
1403
|
...callOptions
|
|
1336
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
|
+
});
|
|
1337
1411
|
var translateInputSchema = z.object({
|
|
1338
1412
|
text: z.string(),
|
|
1339
1413
|
to: z.string(),
|
|
@@ -1559,6 +1633,27 @@ function createAI(config = {}) {
|
|
|
1559
1633
|
}
|
|
1560
1634
|
});
|
|
1561
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
|
+
},
|
|
1562
1657
|
async translate(input) {
|
|
1563
1658
|
input = translateInputSchema.parse(input);
|
|
1564
1659
|
const tier = input.tier ?? TRANSLATE_DEFAULT_TIER;
|
|
@@ -1725,8 +1820,8 @@ var stubProviders = {
|
|
|
1725
1820
|
};
|
|
1726
1821
|
|
|
1727
1822
|
// src/version.ts
|
|
1728
|
-
var VERSION = "0.
|
|
1729
|
-
var SDK_TAG = "@broberg/ai-sdk@0.
|
|
1823
|
+
var VERSION = "0.6.0";
|
|
1824
|
+
var SDK_TAG = "@broberg/ai-sdk@0.6.0";
|
|
1730
1825
|
|
|
1731
1826
|
// src/cost/budget-store.ts
|
|
1732
1827
|
function sqliteBudgetStore(config) {
|
|
@@ -1984,6 +2079,7 @@ export {
|
|
|
1984
2079
|
makeContracts,
|
|
1985
2080
|
makeOpenAICompatibleAdapter,
|
|
1986
2081
|
messageSchema,
|
|
2082
|
+
mistralAdapter,
|
|
1987
2083
|
multiSink,
|
|
1988
2084
|
noopSink,
|
|
1989
2085
|
openaiAdapter,
|