@plurnk/plurnk-providers 1.26.0 → 1.28.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/.env.defaults +8 -11
- package/README.md +11 -2
- package/SPEC.md +67 -40
- package/dist/AiSdkProvider.d.ts +3 -3
- package/dist/AiSdkProvider.d.ts.map +1 -1
- package/dist/AiSdkProvider.js +27 -39
- package/dist/AiSdkProvider.js.map +1 -1
- package/dist/Mock.d.ts +2 -0
- package/dist/Mock.d.ts.map +1 -1
- package/dist/Mock.js +16 -4
- package/dist/Mock.js.map +1 -1
- package/dist/Pool.d.ts +2 -0
- package/dist/Pool.d.ts.map +1 -1
- package/dist/Pool.js +28 -6
- package/dist/Pool.js.map +1 -1
- package/dist/accounting.d.ts.map +1 -1
- package/dist/accounting.js +39 -46
- package/dist/accounting.js.map +1 -1
- package/dist/aiSdkTransport.d.ts +5 -8
- package/dist/aiSdkTransport.d.ts.map +1 -1
- package/dist/aiSdkTransport.js +95 -177
- package/dist/aiSdkTransport.js.map +1 -1
- package/dist/capacity.d.ts +17 -4
- package/dist/capacity.d.ts.map +1 -1
- package/dist/capacity.js +68 -21
- package/dist/capacity.js.map +1 -1
- package/dist/catalogProvider.d.ts.map +1 -1
- package/dist/catalogProvider.js +1 -3
- package/dist/catalogProvider.js.map +1 -1
- package/dist/compatibleProvider.d.ts.map +1 -1
- package/dist/compatibleProvider.js +1 -3
- package/dist/compatibleProvider.js.map +1 -1
- package/dist/cost.d.ts.map +1 -1
- package/dist/cost.js +4 -5
- package/dist/cost.js.map +1 -1
- package/dist/env.d.ts +1 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +16 -9
- package/dist/env.js.map +1 -1
- package/dist/errors.d.ts +2 -4
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +3 -32
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/native-tools.d.ts +5 -0
- package/dist/native-tools.d.ts.map +1 -0
- package/dist/native-tools.js +18 -0
- package/dist/native-tools.js.map +1 -0
- package/dist/ollama.d.ts.map +1 -1
- package/dist/ollama.js +2 -0
- package/dist/ollama.js.map +1 -1
- package/dist/providerError.d.ts +1 -1
- package/dist/providerError.d.ts.map +1 -1
- package/dist/providerError.js +1 -3
- package/dist/providerError.js.map +1 -1
- package/dist/sdkModels.d.ts.map +1 -1
- package/dist/sdkModels.js +11 -9
- package/dist/sdkModels.js.map +1 -1
- package/dist/types.d.ts +5 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/dist/RepeatedLine.d.ts +0 -9
- package/dist/RepeatedLine.d.ts.map +0 -1
- package/dist/RepeatedLine.js +0 -27
- package/dist/RepeatedLine.js.map +0 -1
package/.env.defaults
CHANGED
|
@@ -21,6 +21,10 @@ PLURNK_PROVIDERS_MAX_CONCURRENCY=-1
|
|
|
21
21
|
# Reserved output INCLUDING reasoning: positive tokens or context percentage in (0,100).
|
|
22
22
|
# Known model limits cap it; input capacity is derived. Exact-counting calls may grant unused context.
|
|
23
23
|
PLURNK_PROVIDERS_OUTPUT_BUDGET=35%
|
|
24
|
+
# The least response room any request keeps, in the same units; capped by the output budget.
|
|
25
|
+
# The context window less this floor is the input wall: a packet past the reservation is still sent with
|
|
26
|
+
# its grant flexed down to the remainder; only a packet past the wall cannot be sent.
|
|
27
|
+
PLURNK_PROVIDERS_OUTPUT_FLOOR=10%
|
|
24
28
|
# Optional reasoning subset of output, using the same units; must be smaller than total output.
|
|
25
29
|
# Unset/empty = provider-adaptive budget, not reasoning off.
|
|
26
30
|
# PLURNK_PROVIDERS_REASONING_BUDGET=8192
|
|
@@ -99,21 +103,14 @@ PLURNK_PROVIDERS_CACHE_WRITE_POLICY=stable-system
|
|
|
99
103
|
# Supported keys: input, output, reasoning, cacheRead, cacheWrite. This is estimation, not billing truth.
|
|
100
104
|
# PLURNK_PROVIDERS_COST=input=0.22,output=0.66,reasoning=0.66,cacheRead=0.007
|
|
101
105
|
|
|
102
|
-
# --- Connectivity (milliseconds;
|
|
106
|
+
# --- Connectivity (milliseconds; 0 = off) ---
|
|
103
107
|
# Logical generation deadline, including admission queues, physical attempts and retry delays.
|
|
104
108
|
PLURNK_PROVIDERS_OPERATION_TIMEOUT=2700000
|
|
105
|
-
#
|
|
109
|
+
# Discovery and tokenizer HTTP requests only; never a generation deadline.
|
|
106
110
|
PLURNK_PROVIDERS_FETCH_TIMEOUT=600000
|
|
107
|
-
# Wait from dispatch (after admission, before response headers) to first semantic content;
|
|
108
|
-
# metadata/empty deltas do not count.
|
|
109
|
-
PLURNK_PROVIDERS_FIRST_CONTENT_TIMEOUT=180000
|
|
110
|
-
# Maximum silence between semantic content chunks after content begins.
|
|
111
|
-
PLURNK_PROVIDERS_STREAM_IDLE_TIMEOUT=120000
|
|
112
|
-
# A line of 16+ characters streamed this many times stops the response as a repetition; 0 = off.
|
|
113
|
-
PLURNK_PROVIDERS_REPEATED_LINE_LIMIT=32
|
|
114
111
|
# A response billed for this many more output tokens than it streamed characters (text and reasoning)
|
|
115
|
-
# never delivered its output; it fails as output_dropped
|
|
116
|
-
#
|
|
112
|
+
# never delivered its output; it fails as output_dropped. Native tool calls are retained with a
|
|
113
|
+
# warning, not retried for this reason. Reasoning billed but not streamed is exempt. 0 = off.
|
|
117
114
|
PLURNK_PROVIDERS_DROPPED_OUTPUT_TOKENS=32
|
|
118
115
|
# Retries for 429, Retry-After, or X-Should-Retry:true; 0 = none. Other failures return immediately
|
|
119
116
|
# to Core's separate recovery window. Retry-After takes precedence over backoff.
|
package/README.md
CHANGED
|
@@ -12,6 +12,9 @@ Ordinary provider behavior is intentionally not reimplemented here:
|
|
|
12
12
|
- PLURNK owns aliases, generation envelopes, normalized usage and errors,
|
|
13
13
|
evidence capture, first-party metadata, and local endpoint capabilities.
|
|
14
14
|
|
|
15
|
+
Native tool calling is explicitly disabled through each protocol's standard
|
|
16
|
+
controls; PLURNK operations travel as text ({§provider-native-tools-disabled}).
|
|
17
|
+
|
|
15
18
|
See [SPEC.md](SPEC.md) for the contract, [the model reference](docs/models.md)
|
|
16
19
|
for what a model is told about routes and generation, and
|
|
17
20
|
[.env.defaults](.env.defaults) for every knob.
|
|
@@ -114,6 +117,11 @@ flowchart TD
|
|
|
114
117
|
- **Output** accepts positive tokens or a percentage of context; known model
|
|
115
118
|
limits cap it. An explicit reasoning budget must be smaller than total output.
|
|
116
119
|
Leaving the reasoning budget unset does not disable reasoning.
|
|
120
|
+
- **Output floor** (`PLURNK_PROVIDERS_OUTPUT_FLOOR`, shipped `10%`) is the least
|
|
121
|
+
response room any request keeps, never above the output budget. The window less
|
|
122
|
+
the floor is the input wall: a packet past the budget is still sent with its
|
|
123
|
+
grant flexed down to the remainder; only a packet past the wall cannot be sent
|
|
124
|
+
({§provider-output-floor}).
|
|
117
125
|
- **Context** is derived from the live endpoint or catalog. An operator cap can
|
|
118
126
|
shrink known capacity or declare unknown capacity, never enlarge known limits.
|
|
119
127
|
Prompt projection and initialization reasoning READ limits are separate Core policy.
|
|
@@ -188,9 +196,10 @@ opt-in for endpoints that emit a leading `<think>` envelope, not a reasoning swi
|
|
|
188
196
|
| Concern | Boundary |
|
|
189
197
|
| --- | --- |
|
|
190
198
|
| Inference concurrency | Optional per-endpoint, process-local admission; queued calls remain cancellable. The default is unrestricted ({§provider-inference-admission}). |
|
|
191
|
-
|
|
|
199
|
+
| Generation deadline | One whole-call allowance across queueing, requests and retries; caller cancellation still applies. No first-content or inter-chunk cutoff. |
|
|
200
|
+
| Discovery/tokenizer HTTP | Separate non-generation fetch bound; does not limit inference. |
|
|
192
201
|
| Provider-directed waits | Bounded retries honor `Retry-After`; other recoverable failures return to Core. |
|
|
193
|
-
| Loop recovery | Core reissues within its recovery window, then parks
|
|
202
|
+
| Loop recovery | Core reissues within its recovery window, then parks attended loops or concludes unattended loops on the failure. |
|
|
194
203
|
| Cache affinity | Stable Worker identity through documented provider controls; not a cache-hit guarantee. |
|
|
195
204
|
| Explicit cache writes | Separate policy on supported routes; can affect billing. |
|
|
196
205
|
| Service tier | Explicit route choice that may change price and availability. |
|
package/SPEC.md
CHANGED
|
@@ -95,12 +95,12 @@ fails hard.
|
|
|
95
95
|
|
|
96
96
|
§provider-capacity-admission `assessRequestCapacity` intersects every known
|
|
97
97
|
physical input constraint: independent `maxInputTokens` and
|
|
98
|
-
`contextWindow -
|
|
98
|
+
`contextWindow - outputFloor`, the input wall ({§provider-output-floor}). Its result is `admit`, `reject`, or `defer` and
|
|
99
99
|
retains the complete limit and measurement evidence. Exact fit admits; exact
|
|
100
|
-
overflow rejects. A proven upper bound admits only when it fits. Unknown limits,
|
|
100
|
+
overflow of the wall rejects; a prompt between the curation reservation and the wall is admitted with its grant flexed down. A proven upper bound admits only when it fits. Unknown limits,
|
|
101
101
|
an upper bound above a limit, estimates, and unavailable measurements defer to
|
|
102
|
-
the upstream provider as capacity oracle. The
|
|
103
|
-
exposed as `inputCapacity`; `null` means the available limits cannot establish
|
|
102
|
+
the upstream provider as capacity oracle. The curation reservation's intersection, `maxInputTokens` and `contextWindow - outputBudget`, is
|
|
103
|
+
exposed as `inputCapacity`, the line Core packs the room against; the wall's, as `inputWall`; `null` means the available limits cannot establish
|
|
104
104
|
one. A known combined context and output budget must leave positive input
|
|
105
105
|
capacity. Consumers may display or use that fact as policy, but MUST NOT
|
|
106
106
|
substitute their own content heuristic for request-shaped admission.
|
|
@@ -167,6 +167,25 @@ message count, grammar presence, worker identity, or another incidental request
|
|
|
167
167
|
shape. The signal never enters model-facing messages. Generic
|
|
168
168
|
provider callers MAY omit it; Core supplies it for every model call.
|
|
169
169
|
|
|
170
|
+
§provider-native-tools-disabled Generation requests declare no native tools and
|
|
171
|
+
select the SDK's portable `none` tool choice, for emissions and BARE alike.
|
|
172
|
+
The built-in transports preserve that intent after SDK serialization:
|
|
173
|
+
|
|
174
|
+
| Protocol | No-tool wire representation |
|
|
175
|
+
| --- | --- |
|
|
176
|
+
| OpenAI-compatible Chat Completions and Responses | `tools: []`, `tool_choice: "none"` |
|
|
177
|
+
| Anthropic Messages | `tools: []`, `tool_choice: {"type":"none"}` |
|
|
178
|
+
| Gemini GenerateContent | `tools: []`, `toolConfig: {"functionCallingConfig":{"mode":"NONE"}}` |
|
|
179
|
+
| Bedrock Converse | No tool configuration; the protocol has no `none` choice. |
|
|
180
|
+
| Installed SDK provider plugins | Portable `none` intent; the plugin owns its wire projection. |
|
|
181
|
+
|
|
182
|
+
This is a text-generation contract, not provider/model tuning or prompt
|
|
183
|
+
teaching. Callers cannot supply tools or override the choice through request
|
|
184
|
+
extensions. Do not add deprecated function-call fields, dummy tools, or fields
|
|
185
|
+
from another protocol. The opt-out neither constrains arbitrary prose nor
|
|
186
|
+
proves that an endpoint honors it; unexpected native calls retain their full
|
|
187
|
+
evidence and follow {§provider-native-tool-calls}.
|
|
188
|
+
|
|
170
189
|
A successful return carries the model's raw content and reasoning, normalized
|
|
171
190
|
finish reason, model identity, its ordered {§provider-request-accounting}, the
|
|
172
191
|
request's `ProviderRequestCapacity`, opaque evidence, optional metadata, and
|
|
@@ -175,6 +194,12 @@ accounting evidence. The provider transports and observes model
|
|
|
175
194
|
output; it never retries, discards, or repairs an otherwise completed exchange
|
|
176
195
|
because PLURNK grammar did not accept it.
|
|
177
196
|
|
|
197
|
+
§provider-generation-completion Stream consumption follows the provider's
|
|
198
|
+
completion boundary, subject to caller cancellation and configured deadlines.
|
|
199
|
+
Repeated content or reasoning does not interrupt a response or request another
|
|
200
|
+
generation. Preserve the complete response, its finish reason, and trailing
|
|
201
|
+
usage and charge evidence before returning it to the consumer.
|
|
202
|
+
|
|
178
203
|
§provider-request-observer When a consumer supplies the request observer, the
|
|
179
204
|
adapter opens one durable identity through it immediately before each physical
|
|
180
205
|
I/O and settles that identity with the resulting
|
|
@@ -184,6 +209,15 @@ observer is a durability sink, not an alternate evidence representation; the
|
|
|
184
209
|
same ordered records remain on the final generation result or
|
|
185
210
|
error.
|
|
186
211
|
|
|
212
|
+
The adapter also settles {§provider-request-evidence}. A successful request
|
|
213
|
+
retains its normalized transport response; a failed request retains received
|
|
214
|
+
SDK raw chunks (or the error response body), partial content and reasoning,
|
|
215
|
+
available response identity/headers, usage/charge evidence, and its error and
|
|
216
|
+
cancellation cause. Failure capture is independent of successful raw-body
|
|
217
|
+
capture. These are the SDK's received values, not a claim of byte-for-byte
|
|
218
|
+
HTTP capture. Settlement is durable before returning the failure; a process
|
|
219
|
+
crash before settlement leaves a pending request, not an invented response.
|
|
220
|
+
|
|
187
221
|
§provider-reasoning-observer When a consumer supplies `observeReasoning`, the
|
|
188
222
|
provider synchronously delivers each exact, ordered, nonempty readable-reasoning
|
|
189
223
|
delta as it becomes available. A transport without incremental reasoning emits
|
|
@@ -446,7 +480,7 @@ The universal groups are:
|
|
|
446
480
|
- reasoning activation and optional explicit budget;
|
|
447
481
|
- explicit reasoning response-content style;
|
|
448
482
|
- decode tuning;
|
|
449
|
-
-
|
|
483
|
+
- whole-call generation, discovery/tokenizer HTTP, retry, and probe budgets;
|
|
450
484
|
- local GBNF and llama-server capability pins;
|
|
451
485
|
- context-window and generation-envelope overrides;
|
|
452
486
|
- provider-documented cache affinity and explicit cache-write policy;
|
|
@@ -503,7 +537,8 @@ Provider and model facts resolve independently:
|
|
|
503
537
|
| Context window | Catalog metadata or local endpoint probe. | `PLURNK_PROVIDERS_CONTEXT_WINDOW`. | Minimum when both exist; sole value otherwise. Cataloged cloud miss fails construction; compatible probe miss remains `null` with one warning. |
|
|
504
538
|
| Maximum input | Catalog `limit.input`; no generic live probe. | None. | Catalog value or `null`; never reconstructed from context and output. |
|
|
505
539
|
| Maximum output | Catalog `limit.output`; no generic live probe. | None. | Minimum of catalog value and effective context, or `null`. |
|
|
506
|
-
| Total output budget | None. | `PLURNK_PROVIDERS_OUTPUT_BUDGET`. | Curation reservation: percentage of effective context or absolute count, capped by known context/output limits; a call may only tighten it. The response grant
|
|
540
|
+
| Total output budget | None. | `PLURNK_PROVIDERS_OUTPUT_BUDGET`. | Curation reservation: percentage of effective context or absolute count, capped by known context/output limits; a call may only tighten it. The response grant flexes under {§provider-flexed-allowance}. |
|
|
541
|
+
| Output floor | None. | `PLURNK_PROVIDERS_OUTPUT_FLOOR`, shipped as `10%`. | The least response room any request keeps: percentage of effective context or absolute count, capped by the output budget; `window − floor` is the input wall ({§provider-output-floor}). |
|
|
507
542
|
| Effort | Catalog `reasoning_options` intersected with the installed adapter; explicit adapter declaration for uncataloged routes. | `PLURNK_PROVIDERS_EFFORT`, initially; durable worker selection thereafter. | A supported member of {§effort-wire}, projected under {§provider-effort}. The shipped selection is `adaptive`. |
|
|
508
543
|
| Reasoning budget | None. | Optional `PLURNK_PROVIDERS_REASONING_BUDGET`. | Percentage of effective context or absolute count; valid only as a strict subset of total output and effective unless reasoning is `off`. |
|
|
509
544
|
| Cost override | None. | Optional `PLURNK_PROVIDERS_COST`. | {§operator-cost-override} — comma-separated `key=value` per-1M-token USD rates over `input, output, reasoning, cacheRead, cacheWrite`; merges over the Models.dev catalog block (the catalog is the starting point), alias-scoped like every knob. Without catalog rates the override must declare `input` and `output`. The cost estimate's `source` names the override; a provider-reported response cost still outranks any estimate. |
|
|
@@ -643,16 +678,6 @@ reasoning enclosure only after preserving grammar evidence. Process-wide
|
|
|
643
678
|
llama-server flags are fallback server configuration, not part of the PLURNK
|
|
644
679
|
contract and need not be synchronized with an alias.
|
|
645
680
|
|
|
646
|
-
§repetition-stop **A response that repeats itself is stopped.** A degenerate model can stream one line
|
|
647
|
-
without end; content keeps arriving, so no silence deadline fires, and the call runs to its output
|
|
648
|
-
allowance. The transport counts the complete lines of each streamed channel, text and reasoning, and
|
|
649
|
-
when one line of 16 or more characters has appeared `PLURNK_PROVIDERS_REPEATED_LINE_LIMIT` times it stops
|
|
650
|
-
reading: the stream is cancelled, the physical request settles with whatever usage the chunks carried,
|
|
651
|
-
and the call fails as `repetition` (422, not retryable) carrying the partial attempt and the sentence
|
|
652
|
-
"The response repeated one line N times and was stopped: `<line>`". The consumer reads it as an invalid
|
|
653
|
-
emission, never as a provider failure to recover. Measured: a granite-4.2-8b run repeated one line 358
|
|
654
|
-
times across 45,875 tokens and 9 min 42 s; a limit of 32 stops it 14.6% of the way in (#876).
|
|
655
|
-
|
|
656
681
|
§llama-reasoning-request The allowance is cumulative across the complete response. Opening a second or
|
|
657
682
|
later reasoning block does not replenish it. Template parsing, the reasoning
|
|
658
683
|
sampler, normalized usage, and the returned reasoning channel MUST agree on that
|
|
@@ -730,17 +755,18 @@ request-accounting row. Capacity failures are not connectivity failures and are
|
|
|
730
755
|
never retried by the provider scheduler; bounded packet recovery belongs to the
|
|
731
756
|
consumer.
|
|
732
757
|
|
|
733
|
-
§provider-flexed-allowance **
|
|
734
|
-
configured output budget is the
|
|
758
|
+
§provider-flexed-allowance **The grant is the window's remainder, between the floor and the model's limit.** The
|
|
759
|
+
configured output budget is the reservation curation packs the input against
|
|
735
760
|
(`window − outputBudget`), and it is the only allowance the model is ever
|
|
736
|
-
shown — the packet's disclosed `tokensResponseMax` stays the configured
|
|
737
|
-
so the response discipline it teaches never varies. The wire
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
the
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
761
|
+
shown — the packet's disclosed `tokensResponseMax` stays the configured reservation
|
|
762
|
+
so the response discipline it teaches never varies. The wire grants the remainder: with an exact prompt count
|
|
763
|
+
(llama-server's input-token endpoint) `window − promptTokens − 256`, clamped to no less than the
|
|
764
|
+
output floor and no more than the model's own output limit, so a response overflowing the disclosed reservation
|
|
765
|
+
completes whenever the window's unclaimed room can hold it, and a prompt that ate into the reservation still leaves the floor. Every other
|
|
766
|
+
measurement kind — and any pool — grants the reservation, clamped by the same remainder taken from the prompt's estimate so the wire never asks the window for more than it has; an estimate proves
|
|
767
|
+
nothing about the true remainder, so it never rejects.
|
|
768
|
+
|
|
769
|
+
§provider-output-floor **The floor is the wall's other side.** `PLURNK_PROVIDERS_OUTPUT_FLOOR`, shipped as `10%`, is the least response room any request keeps, capped by the output budget; `window − floor`, intersected with `maxInputTokens`, is the physical input wall exposed as `inputWall`. A request under the curation reservation is the ordinary case; a request between the reservation and the wall is admitted with its grant flexed down to the remainder; an exact prompt over the wall is rejected before I/O; an estimate over the wall defers to the upstream provider as capacity oracle with its grant at the floor. Core consults the wall, never the reservation, to end a loop ({§context-wall} in the core contract). A response exceeding even the grant is cut,
|
|
744
770
|
and the notice names the true per-call grant (`capacity.responseMax` on the
|
|
745
771
|
response) — the tolerance's honest edge, never worse than the fixed allowance
|
|
746
772
|
it forgives.
|
|
@@ -772,29 +798,30 @@ unconfigured. Their grammar protection remains at {§provider-grammar-transport}
|
|
|
772
798
|
§provider-connectivity The provider adapter owns one attempt scheduler around
|
|
773
799
|
the complete generation exchange; SDK-internal retries are disabled.
|
|
774
800
|
`PLURNK_PROVIDERS_RETRY_ATTEMPTS=N` permits at most `N + 1` physical requests.
|
|
775
|
-
|
|
776
|
-
|
|
801
|
+
Generation has one configurable deadline; `0` disables it. Caller cancellation
|
|
802
|
+
and the caller's task allowance remain authoritative. Initial silence, a pause
|
|
803
|
+
between chunks, and buffered output do not acquire separate deadlines.
|
|
777
804
|
|
|
778
805
|
| Layer | Operator knob | Boundary | Expiry |
|
|
779
806
|
| --- | --- | --- | --- |
|
|
780
807
|
| Operation | `PLURNK_PROVIDERS_OPERATION_TIMEOUT` | Complete logical call, including admission queueing, every attempt and retry delay. | Final `deadline_exceeded` Problem at 504 with `timeoutPhase=operation`; not retried inside this operation. Consumer recovery is separate. Enforced as a race, not only the advisory signal, so a wedged transport that never observes the abort cannot hang the loop past the deadline (#505); a well-behaved transport unwinds within a short grace and settles its own attempt evidence first. |
|
|
781
|
-
|
|
|
782
|
-
| First content | `PLURNK_PROVIDERS_FIRST_CONTENT_TIMEOUT` | Dispatch through first semantic model content ({§provider-first-content-at-dispatch}); metadata, empty deltas, and transport activity do not satisfy it. | Surfaced `network_failure` with `timeoutPhase=first_content`; never transport-retried (#479). |
|
|
783
|
-
| Stream idle | `PLURNK_PROVIDERS_STREAM_IDLE_TIMEOUT` | Silence between semantic content chunks after content begins. | Surfaced `network_failure` with `timeoutPhase=stream_idle`; never transport-retried (#479). |
|
|
784
|
-
| Repeated line | `PLURNK_PROVIDERS_REPEATED_LINE_LIMIT` | A streamed line of 16 or more characters repeated this many times; `0` disables. | Stopped as `repetition` ({§repetition-stop}); never transport-retried. |
|
|
785
|
-
|
|
786
|
-
§provider-first-content-at-dispatch The first-content deadline is armed when the
|
|
787
|
-
admitted attempt is dispatched, before response headers, so an endpoint that accepts
|
|
788
|
-
the request and never answers fails at `timeoutPhase=first_content` instead of holding
|
|
789
|
-
the attempt for the whole attempt deadline. It still begins only after admission
|
|
790
|
-
({§provider-inference-admission}).
|
|
808
|
+
| Discovery/tokenizer HTTP | `PLURNK_PROVIDERS_FETCH_TIMEOUT` | Non-generation endpoint discovery and tokenizer requests only. | Ordinary HTTP failure at the owning discovery or measurement boundary. Never interrupts generation. |
|
|
791
809
|
|
|
792
810
|
Settled calls remove their deadline timers and cancellation subscriptions.
|
|
793
811
|
|
|
794
812
|
Caller cancellation spans the operation and preserves the caller's reason.
|
|
813
|
+
|
|
814
|
+
§provider-cancellation-evidence Received usage/charge evidence and available
|
|
815
|
+
response identity survive cancellation and deadline normalization through
|
|
816
|
+
physical-request settlement, independently of optional raw-body capture.
|
|
817
|
+
This includes SDK abort events and non-Error cancellation reasons. Concurrent
|
|
818
|
+
requests keep independent evidence even when cancelled by the same scope.
|
|
819
|
+
Absent evidence remains absent; stopping a request neither invents usage nor
|
|
820
|
+
retries generation to obtain it. Partial output is never a completed response.
|
|
821
|
+
|
|
795
822
|
A 2xx exchange whose body cannot be processed (a provider invalid-response)
|
|
796
823
|
classifies as the non-retryable 502 on the first failure unless an explicit
|
|
797
|
-
`x-should-retry` directive says otherwise (#479).
|
|
824
|
+
`x-should-retry` directive says otherwise (#479). When a
|
|
798
825
|
directive-driven retry sequence exhausts, `attempts` and `retryExhausted`
|
|
799
826
|
are added and the classification is final. Every admitted physical attempt opens
|
|
800
827
|
and settles exactly one ordered {§provider-request-accounting} record, including
|
|
@@ -988,7 +1015,7 @@ alias scoping. Zero, other negative values and non-integers are invalid.
|
|
|
988
1015
|
| Admission | FIFO among live waiters. The lease begins before the physical request observer and ends after the complete response or transport failure settles, including streamed bodies. |
|
|
989
1016
|
| Cancellation | A queued abort removes that waiter and preserves the caller's reason. It opens no physical request or accounting row. In-flight cancellation signals the transport; capacity is released when that attempt unwinds. A transport still running despite abort does not authorize exceeding the limit. |
|
|
990
1017
|
| Retries | Backoff holds no lease. Each retry rejoins admission as a new physical attempt. |
|
|
991
|
-
|
|
|
1018
|
+
| Deadline | The whole-call operation deadline includes queueing, every physical attempt and retry wait. Transport adds no generation deadline. |
|
|
992
1019
|
| Scope | Workers, tools, messages, waits, token measurement and endpoint discovery are not serialized by inference admission. Independent endpoints progress independently. No cross-process or machine-wide capacity guarantee is implied. |
|
|
993
1020
|
|
|
994
1021
|
Admission neither changes worker lifecycle nor selects another model or endpoint.
|
package/dist/AiSdkProvider.d.ts
CHANGED
|
@@ -28,9 +28,6 @@ export type AiSdkProviderConfig = {
|
|
|
28
28
|
attributions?: (context: PluginAttributionContext) => PluginAttribution;
|
|
29
29
|
fetchTimeoutMs: number;
|
|
30
30
|
operationTimeoutMs: number;
|
|
31
|
-
firstContentTimeoutMs: number;
|
|
32
|
-
streamIdleTimeoutMs?: number;
|
|
33
|
-
repeatedLineLimit?: number;
|
|
34
31
|
droppedOutputTokens?: number;
|
|
35
32
|
headers?: Record<string, string>;
|
|
36
33
|
fetch?: ProviderFetch;
|
|
@@ -39,6 +36,7 @@ export type AiSdkProviderConfig = {
|
|
|
39
36
|
maxInputTokens?: number | null;
|
|
40
37
|
maxOutputTokens?: number | null;
|
|
41
38
|
outputBudget?: number | null;
|
|
39
|
+
outputFloor?: number | null;
|
|
42
40
|
reasoningBudget?: number | null;
|
|
43
41
|
supportedEfforts?: readonly Effort[];
|
|
44
42
|
adaptiveEffort?: NativeEffort | "provider-default";
|
|
@@ -92,9 +90,11 @@ export default class AiSdkProvider implements Provider {
|
|
|
92
90
|
get maxInputTokens(): number | null;
|
|
93
91
|
get maxOutputTokens(): number | null;
|
|
94
92
|
get outputBudget(): number | null;
|
|
93
|
+
get outputFloor(): number | null;
|
|
95
94
|
get reasoningBudget(): number | null;
|
|
96
95
|
get supportedEfforts(): readonly Effort[];
|
|
97
96
|
get inputCapacity(): number | null;
|
|
97
|
+
get inputWall(): number | null;
|
|
98
98
|
get model(): string;
|
|
99
99
|
get servedModel(): string | undefined;
|
|
100
100
|
get requiresOutputBudget(): boolean | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiSdkProvider.d.ts","sourceRoot":"","sources":["../src/AiSdkProvider.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAmB,sBAAsB,EAAE,QAAQ,EAAmB,sBAAsB,EAAE,oBAAoB,EAA6B,uBAAuB,EAA6B,gBAAgB,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACxR,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,KAAK,EAAe,SAAS,EAAE,MAAM,IAAI,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAEtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAMxC,OAAO,KAAK,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAQvF,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,kBAAkB,MAAM,yBAAyB,CAAC;AAE9D,MAAM,MAAM,aAAa,GAAG,OAAO,UAAU,CAAC,KAAK,CAAC;AAwBpD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;AAE3D,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAI3E,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,UAAU,CAAC;AAE/C,MAAM,MAAM,aAAa,GACnB;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/F,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC;AAIzF,MAAM,MAAM,mBAAmB,GAAG;IAC9B,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,iBAAiB,CAAC;IACxE,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,
|
|
1
|
+
{"version":3,"file":"AiSdkProvider.d.ts","sourceRoot":"","sources":["../src/AiSdkProvider.ts"],"names":[],"mappings":"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"}
|
package/dist/AiSdkProvider.js
CHANGED
|
@@ -15,7 +15,7 @@ import { emitWarningOnce } from "./warnings.js";
|
|
|
15
15
|
import { resolveProviderCost } from "./cost.js";
|
|
16
16
|
import { validateProviderRequestAccounting } from "./accounting.js";
|
|
17
17
|
import { validateProviderUsage } from "./usage.js";
|
|
18
|
-
import { assessRequestCapacity, effectiveInputCapacity, effectiveOutputBudget, effectiveReasoningBudget } from "./capacity.js";
|
|
18
|
+
import { assessRequestCapacity, effectiveInputCapacity, effectiveInputWall, effectiveOutputBudget, effectiveOutputFloor, effectiveReasoningBudget } from "./capacity.js";
|
|
19
19
|
import { nativeFixedEffort } from "./reasoning-effort.js";
|
|
20
20
|
import AiSdkRequestBody from "./AiSdkRequestBody.js";
|
|
21
21
|
import LeadingReasoning from "./LeadingReasoning.js";
|
|
@@ -89,9 +89,6 @@ export default class AiSdkProvider {
|
|
|
89
89
|
#languageModel;
|
|
90
90
|
#fetchTimeoutMs;
|
|
91
91
|
#operationTimeoutMs;
|
|
92
|
-
#firstContentTimeoutMs;
|
|
93
|
-
#streamIdleTimeoutMs;
|
|
94
|
-
#repeatedLineLimit;
|
|
95
92
|
#droppedOutputTokens;
|
|
96
93
|
#headers;
|
|
97
94
|
#fetch;
|
|
@@ -103,6 +100,7 @@ export default class AiSdkProvider {
|
|
|
103
100
|
#maxInputTokens;
|
|
104
101
|
#maxOutputTokens;
|
|
105
102
|
#outputBudget;
|
|
103
|
+
#outputFloor;
|
|
106
104
|
#reasoningBudget;
|
|
107
105
|
#additiveReasoningProvider;
|
|
108
106
|
#effort;
|
|
@@ -156,8 +154,6 @@ export default class AiSdkProvider {
|
|
|
156
154
|
for (const [name, value] of [
|
|
157
155
|
["fetchTimeoutMs", config.fetchTimeoutMs],
|
|
158
156
|
["operationTimeoutMs", config.operationTimeoutMs],
|
|
159
|
-
["firstContentTimeoutMs", config.firstContentTimeoutMs],
|
|
160
|
-
["streamIdleTimeoutMs", config.streamIdleTimeoutMs],
|
|
161
157
|
]) {
|
|
162
158
|
if (value !== undefined && (!Number.isInteger(value) || value < 0 || value > MAX_TIMER_MS)) {
|
|
163
159
|
throw new Error(`${config.source ?? "provider"}: ${name} must be an integer from 0 through ${MAX_TIMER_MS} milliseconds`);
|
|
@@ -165,9 +161,6 @@ export default class AiSdkProvider {
|
|
|
165
161
|
}
|
|
166
162
|
this.#fetchTimeoutMs = config.fetchTimeoutMs;
|
|
167
163
|
this.#operationTimeoutMs = config.operationTimeoutMs;
|
|
168
|
-
this.#firstContentTimeoutMs = config.firstContentTimeoutMs;
|
|
169
|
-
this.#streamIdleTimeoutMs = config.streamIdleTimeoutMs;
|
|
170
|
-
this.#repeatedLineLimit = config.repeatedLineLimit ?? 0;
|
|
171
164
|
this.#droppedOutputTokens = config.droppedOutputTokens ?? 0;
|
|
172
165
|
this.#headers = config.headers ?? {};
|
|
173
166
|
this.#fetch = config.fetch ?? ((input, init) => globalThis.fetch(input, init));
|
|
@@ -176,6 +169,7 @@ export default class AiSdkProvider {
|
|
|
176
169
|
this.#maxInputTokens = config.maxInputTokens ?? null;
|
|
177
170
|
this.#maxOutputTokens = config.maxOutputTokens ?? null;
|
|
178
171
|
this.#outputBudget = config.outputBudget ?? null;
|
|
172
|
+
this.#outputFloor = config.outputFloor ?? null;
|
|
179
173
|
this.#reasoningBudget = config.reasoningBudget ?? null;
|
|
180
174
|
this.#additiveReasoningProvider = config.additiveReasoningProvider;
|
|
181
175
|
this.#effort = config.effort;
|
|
@@ -271,12 +265,15 @@ export default class AiSdkProvider {
|
|
|
271
265
|
["maxInputTokens", this.#maxInputTokens],
|
|
272
266
|
["maxOutputTokens", this.#maxOutputTokens],
|
|
273
267
|
["outputBudget", this.#outputBudget],
|
|
268
|
+
["outputFloor", this.#outputFloor],
|
|
274
269
|
["reasoningBudget", this.#reasoningBudget],
|
|
275
270
|
]) {
|
|
276
271
|
if (value !== null && (!Number.isSafeInteger(value) || value <= 0)) {
|
|
277
272
|
throw new Error(`${this.#source}: ${name} must be a positive safe integer or null`);
|
|
278
273
|
}
|
|
279
274
|
}
|
|
275
|
+
// {§provider-output-floor}: the floor is never above the output budget.
|
|
276
|
+
this.#outputFloor = effectiveOutputFloor({ configured: this.#outputFloor, outputBudget: this.#outputBudget });
|
|
280
277
|
if (this.#reasoningBudget !== null
|
|
281
278
|
&& this.#outputBudget !== null
|
|
282
279
|
&& this.#reasoningBudget >= this.#outputBudget) {
|
|
@@ -316,6 +313,7 @@ export default class AiSdkProvider {
|
|
|
316
313
|
get maxInputTokens() { return this.#maxInputTokens; }
|
|
317
314
|
get maxOutputTokens() { return this.#maxOutputTokens; }
|
|
318
315
|
get outputBudget() { return this.#outputBudget; }
|
|
316
|
+
get outputFloor() { return this.#outputFloor; }
|
|
319
317
|
get reasoningBudget() { return this.#reasoningBudget; }
|
|
320
318
|
get supportedEfforts() { return this.#supportedEfforts; }
|
|
321
319
|
get inputCapacity() {
|
|
@@ -325,6 +323,14 @@ export default class AiSdkProvider {
|
|
|
325
323
|
outputBudget: this.#outputBudget,
|
|
326
324
|
});
|
|
327
325
|
}
|
|
326
|
+
// {§provider-output-floor}: the physical input wall, the window less the floor.
|
|
327
|
+
get inputWall() {
|
|
328
|
+
return effectiveInputWall({
|
|
329
|
+
contextWindow: this.#contextWindow,
|
|
330
|
+
maxInputTokens: this.#maxInputTokens,
|
|
331
|
+
outputFloor: this.#outputFloor,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
328
334
|
get model() { return this.#model; }
|
|
329
335
|
// Backend's self-reported served id; undefined when unprobed/unknown.
|
|
330
336
|
get servedModel() { return this.#servedModel; }
|
|
@@ -392,6 +398,7 @@ export default class AiSdkProvider {
|
|
|
392
398
|
maxInputTokens: this.#maxInputTokens,
|
|
393
399
|
maxOutputTokens: this.#maxOutputTokens,
|
|
394
400
|
outputBudget,
|
|
401
|
+
outputFloor: this.#outputFloor,
|
|
395
402
|
reasoningBudget,
|
|
396
403
|
measurement: await this.countPromptTokens(messages, signal),
|
|
397
404
|
});
|
|
@@ -436,10 +443,10 @@ export default class AiSdkProvider {
|
|
|
436
443
|
if (capacity.prompt.kind !== "exact") {
|
|
437
444
|
throw new TypeError(`${this.#source}: only an exact prompt measurement may reject capacity`);
|
|
438
445
|
}
|
|
439
|
-
throw new ProviderError(this.#source, "capacity_exceeded", `The exact provider request uses ${capacity.prompt.tokens} input tokens, exceeding its ${capacity.
|
|
446
|
+
throw new ProviderError(this.#source, "capacity_exceeded", `The exact provider request uses ${capacity.prompt.tokens} input tokens, exceeding its ${capacity.inputWall} token input wall.`, { capacity, extensions: { capacityStage: "preflight", capacity } });
|
|
440
447
|
}
|
|
441
|
-
// {§provider-flexed-allowance}
|
|
442
|
-
//
|
|
448
|
+
// {§provider-flexed-allowance}: the wire grants the flexed allowance —
|
|
449
|
+
// the window's remainder, between the floor and the model's limit.
|
|
443
450
|
const effectiveMaxOutputTokens = capacity.responseMax ?? capacity.outputBudget ?? undefined;
|
|
444
451
|
const nativeReasoningBudget = this.#requestBody.nativeReasoningBudget(capacity.outputBudget, capacity.reasoningBudget);
|
|
445
452
|
// Both transports project the same resolved sampling; managed fields still win.
|
|
@@ -529,7 +536,7 @@ export default class AiSdkProvider {
|
|
|
529
536
|
catch (cause) {
|
|
530
537
|
throw new ProviderRequestObserverError(cause);
|
|
531
538
|
}
|
|
532
|
-
const settleAccounting = async (outcome, usage, evidence, status) => {
|
|
539
|
+
const settleAccounting = async (outcome, usage, evidence, forensicEvidence, status) => {
|
|
533
540
|
let requestAccounting;
|
|
534
541
|
let normalizationFailure;
|
|
535
542
|
try {
|
|
@@ -558,7 +565,7 @@ export default class AiSdkProvider {
|
|
|
558
565
|
}
|
|
559
566
|
accounting.push(requestAccounting);
|
|
560
567
|
try {
|
|
561
|
-
await settle?.(requestAccounting);
|
|
568
|
+
await settle?.(requestAccounting, forensicEvidence);
|
|
562
569
|
}
|
|
563
570
|
catch (cause) {
|
|
564
571
|
throw new ProviderRequestObserverError(cause);
|
|
@@ -579,10 +586,6 @@ export default class AiSdkProvider {
|
|
|
579
586
|
messages,
|
|
580
587
|
signal: operationSignal,
|
|
581
588
|
fetch: this.#fetch,
|
|
582
|
-
fetchTimeoutMs: this.#fetchTimeoutMs,
|
|
583
|
-
firstContentTimeoutMs: this.#firstContentTimeoutMs,
|
|
584
|
-
streamIdleTimeoutMs: this.#streamIdleTimeoutMs,
|
|
585
|
-
repeatedLineLimit: this.#repeatedLineLimit,
|
|
586
589
|
streaming: this.#streaming,
|
|
587
590
|
captureRawBody: this.#rawBody,
|
|
588
591
|
...observers,
|
|
@@ -596,10 +599,6 @@ export default class AiSdkProvider {
|
|
|
596
599
|
systemProviderOptions: this.#systemCacheProviderOptions,
|
|
597
600
|
messages,
|
|
598
601
|
signal: operationSignal,
|
|
599
|
-
fetchTimeoutMs: this.#fetchTimeoutMs,
|
|
600
|
-
firstContentTimeoutMs: this.#firstContentTimeoutMs,
|
|
601
|
-
streamIdleTimeoutMs: this.#streamIdleTimeoutMs,
|
|
602
|
-
repeatedLineLimit: this.#repeatedLineLimit,
|
|
603
602
|
streaming: this.#streaming,
|
|
604
603
|
captureRawBody: this.#rawBody,
|
|
605
604
|
...observers,
|
|
@@ -628,13 +627,13 @@ export default class AiSdkProvider {
|
|
|
628
627
|
if (transportFailureOutputObserved(error))
|
|
629
628
|
recoveredAfterOutput = true;
|
|
630
629
|
const failure = transportFailureEvidence(error);
|
|
631
|
-
await settleAccounting("error", failure.usage, failure.chargeEvidence, failure.status);
|
|
630
|
+
await settleAccounting("error", failure.usage, failure.chargeEvidence, failure, failure.status);
|
|
632
631
|
throw error;
|
|
633
632
|
}
|
|
634
633
|
if (!structuredReasoning && liveProjection !== undefined)
|
|
635
634
|
observeRequestReasoning(liveProjection.finish());
|
|
636
635
|
successfulReasoningStream = requestReasoningStream;
|
|
637
|
-
await settleAccounting("response", response.usage, response.chargeEvidence);
|
|
636
|
+
await settleAccounting("response", response.usage, response.chargeEvidence, response);
|
|
638
637
|
return response;
|
|
639
638
|
};
|
|
640
639
|
const executeRequest = async () => {
|
|
@@ -667,9 +666,9 @@ export default class AiSdkProvider {
|
|
|
667
666
|
|| err instanceof ProviderReasoningObserverError)
|
|
668
667
|
throw err.cause;
|
|
669
668
|
if (signal?.aborted)
|
|
670
|
-
throw
|
|
669
|
+
throw signal.reason;
|
|
671
670
|
if (operationTimeout?.aborted) {
|
|
672
|
-
const timeout = new ProviderTimeoutError(
|
|
671
|
+
const timeout = new ProviderTimeoutError(this.#operationTimeoutMs, err);
|
|
673
672
|
throw new ProviderError(this.#source, "deadline_exceeded", timeout.message, {
|
|
674
673
|
status: 504,
|
|
675
674
|
cause: timeout,
|
|
@@ -828,9 +827,8 @@ export default class AiSdkProvider {
|
|
|
828
827
|
...(notices !== undefined ? { notices } : {}),
|
|
829
828
|
};
|
|
830
829
|
// {§provider-flexed-allowance} (#482): conformance judges the GRANT the
|
|
831
|
-
// wire actually sent, not the configured
|
|
832
|
-
// is overflow tolerance working, never a provider fault.
|
|
833
|
-
// was this guard still holding the floor after the flex landed.
|
|
830
|
+
// wire actually sent, not the configured reservation — output between
|
|
831
|
+
// the two is overflow tolerance working, never a provider fault.
|
|
834
832
|
const grantedOutput = capacity.responseMax ?? capacity.outputBudget;
|
|
835
833
|
if (grantedOutput !== null
|
|
836
834
|
&& usage?.outputTokens !== undefined
|
|
@@ -850,16 +848,6 @@ export default class AiSdkProvider {
|
|
|
850
848
|
},
|
|
851
849
|
});
|
|
852
850
|
}
|
|
853
|
-
if (raw.finishReason === "repetition") {
|
|
854
|
-
// {§repetition-stop}: the stream was stopped at a repeated line; the partial attempt is evidence, and the
|
|
855
|
-
// consumer reads it as an invalid emission, never as a provider failure to recover.
|
|
856
|
-
const attempt = {
|
|
857
|
-
assistant: { ...assistant, finishReason: raw.finishReason },
|
|
858
|
-
...evidence,
|
|
859
|
-
};
|
|
860
|
-
const { line, count } = raw.repetition;
|
|
861
|
-
throw new ProviderError(this.#source, "repetition", `The response repeated one line ${count} times and was stopped: \`${line}\``, { attempt, accounting, extensions: { stage: "provider-response", finishReason: "repetition", repeatedLine: line, repeatedCount: count } });
|
|
862
|
-
}
|
|
863
851
|
if (raw.finishReason === "resource_interrupted") {
|
|
864
852
|
const attempt = {
|
|
865
853
|
assistant: { ...assistant, finishReason: raw.finishReason },
|