@shop-os/modelkit 0.3.8 → 0.4.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/CHANGELOG.md +15 -0
- package/README.md +2 -2
- 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.map +1 -1
- package/dist/index.cjs +115 -34
- 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 +115 -34
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,21 @@ header in the release PR.
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.4.0] - Unreleased
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- `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).
|
|
16
|
+
- `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.
|
|
17
|
+
|
|
18
|
+
### Breaking
|
|
19
|
+
- `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.
|
|
20
|
+
|
|
21
|
+
### Known gaps
|
|
22
|
+
- 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.
|
|
23
|
+
|
|
24
|
+
### Consumer follow-up (separate PR, AGENTS.md section 3)
|
|
25
|
+
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`).
|
|
26
|
+
|
|
12
27
|
## [0.3.8] - Unreleased
|
|
13
28
|
|
|
14
29
|
### 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
|
|