@shop-os/modelkit 0.3.8 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +2 -2
- package/dist/catalog.cjs +50 -36
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +12 -1
- package/dist/catalog.d.ts +12 -1
- package/dist/catalog.js +50 -36
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +165 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +165 -70
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,31 @@ header in the release PR.
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.4.1] - Unreleased
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- `veo-3.1`, `veo-3.1-fast`, `veo-3.1-lite` and `gemini-omni-flash` are `deprecated`, replaced by `gemini-omni-1.1-flash`, with no exposure. Google shuts down their provider models (`veo-3.1-generate-preview`, `veo-3.1-fast-generate-preview`, `veo-3.1-lite-generate-preview`, `gemini-omni-flash-preview`) on 2026-10-22. The rows still resolve, so stored ids keep working until then.
|
|
16
|
+
- `gemini-3-pro-image-preview` sends `gemini-3-pro-image` and `gemini-3.1-flash-image-preview` sends `gemini-3.1-flash-image`: Google listed the preview endpoints for shutdown on 2026-06-25, and the GA ids cost the same. The catalog ids are unchanged, since they are pricing keys and stored model ids.
|
|
17
|
+
- `higgsfield-dop-preview` is priced `flat`: Higgsfield bills DoP per generation, a fixed-length clip with no duration knob.
|
|
18
|
+
|
|
19
|
+
### Live rows
|
|
20
|
+
pro-backend's `apply-model-shutdowns` script (PR #1486) makes the same changes to the live `model_catalog` rows per environment, including clearing the deprecated rows' exposure.
|
|
21
|
+
|
|
22
|
+
## [0.4.0] - Unreleased
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- `ModelKitError` code `provider_billing`: the provider account is out of credit or quota. HTTP 402 always maps to it; so does any 4xx whose structured `error.code` / `error.type` (or top-level `code` / `type`) is a billing code such as OpenAI's `insufficient_quota`; free-text matches ("Exhausted balance", "Insufficient credit") count only on 403 and 429, never on a 400/422 whose validation detail may echo the request. It is never retried; before, a 402 was a generic `provider_rejected` and OpenAI's quota 429 was retried as `rate_limited`. Text calls are unchanged (they surface the `ai` SDK's error).
|
|
26
|
+
- `UsageEvent.latencyMs`: the call's wall time from dispatch to the provider's final answer, on every image, video, audio and video-tool event and on single-step text calls (`generateText`/`streamText` with one step, `generateObject`, `streamObject`). A video includes its polling. A multi-step text call (a tool loop) emits its events with **no** `latencyMs`: its wall time includes tool execution and every step, and stamping it on each step's event would inflate per-model p95s and trip the absolute duration alert. `submitVideoTool` stamps `submittedAt` on the submission and `videoToolResult` measures from it; a stored submission without it emits no latency.
|
|
27
|
+
|
|
28
|
+
### Breaking
|
|
29
|
+
- `ModelKitErrorCode` gains `provider_billing`, so an exhaustive `Record<ModelKitErrorCode, ...>` in a consumer (cowork's `BY_KIT_CODE`) needs an entry, and code that matched a 402 as `provider_rejected` sees the new code. Hence the minor bump: consumers on `^0.3` keep 0.3.x until they move.
|
|
30
|
+
|
|
31
|
+
### Known gaps
|
|
32
|
+
- Three adapters retry a raw `status === 429` themselves before `classifyHttpError` sees the response: `adapters/higgsfield.ts` (status poll), `adapters/ark.ts` (task poll) and `adapters/google-files.ts` (Files API file-state poll). A quota-exhausted 429 (`insufficient_quota`-style) on those paths is still retried as a rate limit instead of surfacing as `provider_billing`. Follow-up: route those checks through the classifier.
|
|
33
|
+
|
|
34
|
+
### Consumer follow-up (separate PR, AGENTS.md section 3)
|
|
35
|
+
Map `usage.latencyMs` to the usage-client `latency_ms` field in each app's `onUsage` sink, map `provider_billing` in error categorizers, and log it with the standard `{ err, code: "provider_billing" }` shape on ECS request paths (the Phase 2 CloudWatch metric filter matches on `code`).
|
|
36
|
+
|
|
12
37
|
## [0.3.8] - Unreleased
|
|
13
38
|
|
|
14
39
|
### Added
|
package/README.md
CHANGED
|
@@ -132,7 +132,7 @@ An optional second `CallContext` argument selects enterprise keys, adds cancella
|
|
|
132
132
|
(combined with `abortSignal`), sets media `maxRetries`, and sets `onUnsupported`. Package-level functions read
|
|
133
133
|
keys from the environment; a configured kit adds routing, catalog overrides, custom
|
|
134
134
|
fetch, provider endpoint overrides (`endpoints.ark` for the Ark base url), logging, and
|
|
135
|
-
the `onUsage` sink.
|
|
135
|
+
the `onUsage` sink. Usage events carry `latencyMs`, the call's wall time from dispatch to the provider's final answer (a video's polling included); a video tool measures from the `submittedAt` the kit stamps on the submission. A multi-step text call (tool loop) carries none, since its wall time is not model latency.
|
|
136
136
|
|
|
137
137
|
### Durable media execution
|
|
138
138
|
|
|
@@ -266,7 +266,7 @@ const defaultKit = createDefaultModelKit({ keys: { pro: keysFromEnv(process.env)
|
|
|
266
266
|
| Keys | Enterprise keys win only when every key the adapter (and its route, e.g. the cloudflare token for a vendor that really goes through the gateway) needs is set on the enterprise tier; a fallback to pro keys is logged once per call. |
|
|
267
267
|
| Routing | Cloudflare AI Gateway for text only. Never for Gemini images or Omni. fal passthrough for geo-blocked regions; the fal direct route submits to the queue and polls, so `job.result({ timeoutMs, signal })` is live. |
|
|
268
268
|
| Retry | One classifier, one policy. Never on content blocks, aborts, or 4xx except 429; SDKs with their own retry (Replicate) run under a single kit attempt; a 429 on a status poll keeps polling unless `CallContext.maxRetries` is `0`. See durable media execution above. |
|
|
269
|
-
| Errors | `ModelKitError` with `code`, `provider`, `status`, `body`. Gemini `blockReason` and fal `body.detail` are lifted into `body`. A throw with no HTTP status (fetch failed, reset, DNS) is a retryable `network` error on every adapter. |
|
|
269
|
+
| Errors | `ModelKitError` with `code`, `provider`, `status`, `body`. Gemini `blockReason` and fal `body.detail` are lifted into `body`. A throw with no HTTP status (fetch failed, reset, DNS) is a retryable `network` error on every adapter. An out-of-credit provider account is `provider_billing` and is never retried: HTTP 402, a 4xx whose structured error code is a billing code (`insufficient_quota`, ...), or a 403/429 whose text names the exhausted account ("Exhausted balance", "Insufficient credit"). Text calls go through `ai` and surface the SDK's own error instead. |
|
|
270
270
|
| Usage | One event per call with the canonical model id and the row's `usage.unit` (adapters supply the quantity in that unit). Gemini image events carry the token counts too (`inputTokens`/`outputTokens`); Google's raw `usageMetadata` rides on `raw.providerMetadata.google`. Video usage is emitted on completion; Seedance keeps `usage`, `duration`, `framespersecond` and `resolution` from the poll on `raw`. Audio: Lyria 3 returns no duration, so it emits `unit: "images", quantity: 1` (token counts ride along as `inputTokens`/`outputTokens`); Replicate audio (Lyria 2, MMAudio) emits `unit: "compute_seconds"` with the prediction time. |
|
|
271
271
|
| Media parts | `prepareMediaPart` turns a `MediaRef` into an AI SDK file part. Google inlines bytes up to 20 MB and uploads larger payloads through the Files API; call the returned `cleanup` after the request. Other providers get the reference inline. |
|
|
272
272
|
|
package/dist/catalog.cjs
CHANGED
|
@@ -275,35 +275,43 @@ var IMAGE_MODELS = [
|
|
|
275
275
|
GEMINI_PROMPT_MAX_CHARS,
|
|
276
276
|
NANO_BANANA_2_1_RATIOS
|
|
277
277
|
),
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
278
|
+
// Google retired the -preview endpoints for the GA ids; the catalog ids stay because they
|
|
279
|
+
// are pricing keys and stored model ids.
|
|
280
|
+
{
|
|
281
|
+
...geminiImage(
|
|
282
|
+
"gemini-3-pro-image-preview",
|
|
283
|
+
"Nano Banana Pro",
|
|
284
|
+
["nb-pro"],
|
|
285
|
+
["1K", "2K", "4K"],
|
|
286
|
+
{
|
|
287
|
+
provider: "google",
|
|
288
|
+
description: "Create stunning, production-quality visuals with exceptional realism, detail, and typography. Best for campaigns, e-commerce, product photography, and hero creatives.",
|
|
289
|
+
logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
|
|
290
|
+
},
|
|
291
|
+
["cowork", "space_builder"],
|
|
292
|
+
{ images: 14 },
|
|
293
|
+
GEMINI_PROMPT_MAX_CHARS
|
|
294
|
+
),
|
|
295
|
+
providerModelId: "gemini-3-pro-image"
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
...geminiImage(
|
|
299
|
+
"gemini-3.1-flash-image-preview",
|
|
300
|
+
"Nano Banana 2",
|
|
301
|
+
["nb-2"],
|
|
302
|
+
// Flash 3.1 is the only Gemini image model with the 512 tier.
|
|
303
|
+
["512", "1K", "2K", "4K"],
|
|
304
|
+
{
|
|
305
|
+
provider: "google",
|
|
306
|
+
description: "Generate high-quality images at speed. Perfect for brainstorming, concept boards, concept testing, creative exploration, and large batch workflows.",
|
|
307
|
+
logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
|
|
308
|
+
},
|
|
309
|
+
["cowork", "space_builder"],
|
|
310
|
+
{ images: 14 },
|
|
311
|
+
GEMINI_PROMPT_MAX_CHARS
|
|
312
|
+
),
|
|
313
|
+
providerModelId: "gemini-3.1-flash-image"
|
|
314
|
+
},
|
|
307
315
|
geminiImage(
|
|
308
316
|
"gemini-3.1-flash-lite-image",
|
|
309
317
|
"Nano Banana Lite",
|
|
@@ -1437,6 +1445,7 @@ var OMNI_PROMPT = { referenceSyntax: "caption", maxChars: 5e4 };
|
|
|
1437
1445
|
var BYTEDANCE_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/3bba5d81-4e57-4e71-911b-cdfa05acca2c_compressed.png";
|
|
1438
1446
|
var GOOGLE_LOGO2 = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png";
|
|
1439
1447
|
var VIDEO_MODELS = [
|
|
1448
|
+
// Google shuts down the Veo 3.1 previews and Omni Flash 1.0 on 2026-10-22.
|
|
1440
1449
|
{
|
|
1441
1450
|
id: "veo-3.1",
|
|
1442
1451
|
aliases: [
|
|
@@ -1449,8 +1458,9 @@ var VIDEO_MODELS = [
|
|
|
1449
1458
|
type: "video",
|
|
1450
1459
|
adapter: "google-genai",
|
|
1451
1460
|
providerModelId: "veo-3.1-generate-preview",
|
|
1452
|
-
lifecycle: "
|
|
1453
|
-
|
|
1461
|
+
lifecycle: "deprecated",
|
|
1462
|
+
replacedBy: "gemini-omni-1.1-flash",
|
|
1463
|
+
exposure: [],
|
|
1454
1464
|
constraints: {
|
|
1455
1465
|
aspectRatios: [...OMNI_RATIOS],
|
|
1456
1466
|
resolutions: ["720p", "1080p", "4k"],
|
|
@@ -1485,7 +1495,8 @@ var VIDEO_MODELS = [
|
|
|
1485
1495
|
type: "video",
|
|
1486
1496
|
adapter: "google-genai",
|
|
1487
1497
|
providerModelId: "veo-3.1-fast-generate-preview",
|
|
1488
|
-
lifecycle: "
|
|
1498
|
+
lifecycle: "deprecated",
|
|
1499
|
+
replacedBy: "gemini-omni-1.1-flash",
|
|
1489
1500
|
exposure: [],
|
|
1490
1501
|
constraints: {
|
|
1491
1502
|
aspectRatios: [...OMNI_RATIOS],
|
|
@@ -1515,7 +1526,8 @@ var VIDEO_MODELS = [
|
|
|
1515
1526
|
type: "video",
|
|
1516
1527
|
adapter: "google-genai",
|
|
1517
1528
|
providerModelId: "veo-3.1-lite-generate-preview",
|
|
1518
|
-
lifecycle: "
|
|
1529
|
+
lifecycle: "deprecated",
|
|
1530
|
+
replacedBy: "gemini-omni-1.1-flash",
|
|
1519
1531
|
exposure: [],
|
|
1520
1532
|
constraints: {
|
|
1521
1533
|
aspectRatios: [...OMNI_RATIOS],
|
|
@@ -1546,8 +1558,9 @@ var VIDEO_MODELS = [
|
|
|
1546
1558
|
type: "video",
|
|
1547
1559
|
adapter: "google-genai",
|
|
1548
1560
|
providerModelId: "gemini-omni-flash-preview",
|
|
1549
|
-
lifecycle: "
|
|
1550
|
-
|
|
1561
|
+
lifecycle: "deprecated",
|
|
1562
|
+
replacedBy: "gemini-omni-1.1-flash",
|
|
1563
|
+
exposure: [],
|
|
1551
1564
|
constraints: {
|
|
1552
1565
|
// 1.0 rejects `resolution`; it renders 720p. No defaults: the adapter
|
|
1553
1566
|
// sends ratio and duration only when the caller set them, so a
|
|
@@ -2102,7 +2115,8 @@ var VIDEO_MODELS = [
|
|
|
2102
2115
|
},
|
|
2103
2116
|
defaults: {},
|
|
2104
2117
|
usage: { ...VIDEO_USAGE },
|
|
2105
|
-
|
|
2118
|
+
// Higgsfield bills DoP per generation: a fixed-length clip with no duration knob.
|
|
2119
|
+
pricingKind: "flat",
|
|
2106
2120
|
display: {
|
|
2107
2121
|
provider: "higgsfield",
|
|
2108
2122
|
description: "Higgsfield DOP image-to-video model; animates a required first-frame image from a text prompt with an optional last-frame image and motion controls."
|