@plurnk/plurnk-providers 1.3.12 → 1.5.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.
Files changed (139) hide show
  1. package/.env.defaults +47 -38
  2. package/README.md +68 -4
  3. package/SPEC.md +245 -62
  4. package/dist/AiSdkProvider.d.ts +19 -5
  5. package/dist/AiSdkProvider.d.ts.map +1 -1
  6. package/dist/AiSdkProvider.js +264 -156
  7. package/dist/AiSdkProvider.js.map +1 -1
  8. package/dist/Mock.d.ts +15 -17
  9. package/dist/Mock.d.ts.map +1 -1
  10. package/dist/Mock.js +27 -10
  11. package/dist/Mock.js.map +1 -1
  12. package/dist/Pool.d.ts +8 -2
  13. package/dist/Pool.d.ts.map +1 -1
  14. package/dist/Pool.js +41 -8
  15. package/dist/Pool.js.map +1 -1
  16. package/dist/ProviderRegistry.d.ts +4 -1
  17. package/dist/ProviderRegistry.d.ts.map +1 -1
  18. package/dist/ProviderRegistry.js +7 -3
  19. package/dist/ProviderRegistry.js.map +1 -1
  20. package/dist/accounting.d.ts +3 -0
  21. package/dist/accounting.d.ts.map +1 -0
  22. package/dist/accounting.js +84 -0
  23. package/dist/accounting.js.map +1 -0
  24. package/dist/aiSdkTransport.d.ts +5 -2
  25. package/dist/aiSdkTransport.d.ts.map +1 -1
  26. package/dist/aiSdkTransport.js +91 -5
  27. package/dist/aiSdkTransport.js.map +1 -1
  28. package/dist/catalogProvider.d.ts +5 -2
  29. package/dist/catalogProvider.d.ts.map +1 -1
  30. package/dist/catalogProvider.js +24 -11
  31. package/dist/catalogProvider.js.map +1 -1
  32. package/dist/compatibleProvider.d.ts.map +1 -1
  33. package/dist/compatibleProvider.js +11 -4
  34. package/dist/compatibleProvider.js.map +1 -1
  35. package/dist/cost.d.ts +11 -0
  36. package/dist/cost.d.ts.map +1 -0
  37. package/dist/cost.js +61 -0
  38. package/dist/cost.js.map +1 -0
  39. package/dist/discover.d.ts +2 -0
  40. package/dist/discover.d.ts.map +1 -1
  41. package/dist/discover.js +15 -9
  42. package/dist/discover.js.map +1 -1
  43. package/dist/env.d.ts +4 -6
  44. package/dist/env.d.ts.map +1 -1
  45. package/dist/env.js +27 -29
  46. package/dist/env.js.map +1 -1
  47. package/dist/errors.d.ts +27 -0
  48. package/dist/errors.d.ts.map +1 -0
  49. package/dist/errors.js +152 -0
  50. package/dist/errors.js.map +1 -0
  51. package/dist/index.d.ts +12 -6
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +8 -5
  54. package/dist/index.js.map +1 -1
  55. package/dist/notices.d.ts +10 -0
  56. package/dist/notices.d.ts.map +1 -0
  57. package/dist/notices.js +11 -0
  58. package/dist/notices.js.map +1 -0
  59. package/dist/ollama.d.ts.map +1 -1
  60. package/dist/ollama.js +3 -3
  61. package/dist/ollama.js.map +1 -1
  62. package/dist/openai.d.ts +1 -1
  63. package/dist/openai.d.ts.map +1 -1
  64. package/dist/promptTokens.d.ts +4 -0
  65. package/dist/promptTokens.d.ts.map +1 -0
  66. package/dist/promptTokens.js +32 -0
  67. package/dist/promptTokens.js.map +1 -0
  68. package/dist/sdkModels.d.ts +2 -0
  69. package/dist/sdkModels.d.ts.map +1 -1
  70. package/dist/sdkModels.js +17 -6
  71. package/dist/sdkModels.js.map +1 -1
  72. package/dist/types.d.ts +52 -16
  73. package/dist/types.d.ts.map +1 -1
  74. package/dist/types.js +1 -1
  75. package/dist/types.js.map +1 -1
  76. package/dist/usage.d.ts +4 -0
  77. package/dist/usage.d.ts.map +1 -1
  78. package/dist/usage.js +64 -19
  79. package/dist/usage.js.map +1 -1
  80. package/dist/warnings.js +0 -0
  81. package/dist/warnings.js.map +1 -1
  82. package/package.json +15 -10
  83. package/src/AiSdkProvider.test.ts +750 -169
  84. package/src/AiSdkProvider.ts +354 -200
  85. package/src/Mock.test.ts +29 -14
  86. package/src/Mock.ts +36 -15
  87. package/src/Pool.test.ts +43 -6
  88. package/src/Pool.ts +56 -10
  89. package/src/ProviderRegistry.test.ts +158 -9
  90. package/src/ProviderRegistry.ts +19 -6
  91. package/src/accounting.test.ts +58 -0
  92. package/src/accounting.ts +88 -0
  93. package/src/aiSdkTransport.ts +101 -8
  94. package/src/boundaries.test.ts +9 -3
  95. package/src/catalogProvider.test.ts +43 -15
  96. package/src/catalogProvider.ts +32 -16
  97. package/src/compatibleProvider.test.ts +96 -0
  98. package/src/compatibleProvider.ts +15 -6
  99. package/src/cost.test.ts +64 -0
  100. package/src/cost.ts +78 -0
  101. package/src/defaults.test.ts +1 -0
  102. package/src/discover.test.ts +48 -7
  103. package/src/discover.ts +31 -21
  104. package/src/env.test.ts +38 -48
  105. package/src/env.ts +43 -40
  106. package/src/errors.test.ts +148 -0
  107. package/src/errors.ts +208 -0
  108. package/src/index.ts +30 -8
  109. package/src/lexicon-guard.test.ts +6 -6
  110. package/src/notices.ts +22 -0
  111. package/src/ollama.test.ts +64 -0
  112. package/src/ollama.ts +6 -3
  113. package/src/openai.ts +3 -0
  114. package/src/promptTokens.ts +41 -0
  115. package/src/sdkModels.test.ts +29 -3
  116. package/src/sdkModels.ts +19 -11
  117. package/src/types.ts +125 -64
  118. package/src/usage.test.ts +24 -5
  119. package/src/usage.ts +72 -21
  120. package/src/warnings.test.ts +10 -10
  121. package/src/warnings.ts +0 -0
  122. package/dist/OpenAICompat.d.ts +0 -76
  123. package/dist/OpenAICompat.d.ts.map +0 -1
  124. package/dist/OpenAICompat.js +0 -555
  125. package/dist/OpenAICompat.js.map +0 -1
  126. package/dist/openaiStream.d.ts +0 -47
  127. package/dist/openaiStream.d.ts.map +0 -1
  128. package/dist/openaiStream.js +0 -280
  129. package/dist/openaiStream.js.map +0 -1
  130. package/dist/standardProviders.d.ts +0 -31
  131. package/dist/standardProviders.d.ts.map +0 -1
  132. package/dist/standardProviders.js +0 -518
  133. package/dist/standardProviders.js.map +0 -1
  134. package/dist/telemetry.d.ts +0 -24
  135. package/dist/telemetry.d.ts.map +0 -1
  136. package/dist/telemetry.js +0 -85
  137. package/dist/telemetry.js.map +0 -1
  138. package/src/telemetry.test.ts +0 -69
  139. package/src/telemetry.ts +0 -116
package/SPEC.md CHANGED
@@ -8,8 +8,9 @@ ordinary provider protocols.
8
8
 
9
9
  The provider stack has four owners:
10
10
 
11
- 1. Models.dev supplies a build-time snapshot of provider package, API endpoint,
12
- credential names, models, context windows, output limits, and USD prices.
11
+ 1. Models.dev supplies a release-time snapshot of provider package, API
12
+ endpoint, credential names, models, context windows, output limits,
13
+ reasoning capability, and USD prices.
13
14
  2. Official AI SDK providers own vendor request and response protocols.
14
15
  3. This package owns the PLURNK contract: aliases, envelopes, normalized usage
15
16
  and errors, evidence, local capabilities, and first-party metadata.
@@ -23,7 +24,8 @@ provider declaration, or left explicitly unknown.
23
24
 
24
25
  ## §2 Provider interface
25
26
 
26
- `Provider` exposes immutable model facts and one generation operation:
27
+ §provider-interface `Provider` exposes immutable model facts and one generation
28
+ operation:
27
29
 
28
30
  ```ts
29
31
  interface Provider {
@@ -35,26 +37,57 @@ interface Provider {
35
37
  readonly reasoningReserve?: number | null;
36
38
  readonly completionReserve?: number | null;
37
39
 
38
- countTokens(text: string): number;
40
+ countPromptTokens(
41
+ messages: readonly ChatMessage[],
42
+ signal?: AbortSignal,
43
+ ): Promise<PromptTokenMeasurement>;
39
44
  tokenize?(text: string): Promise<number[]>;
40
45
  calculateCost(usage: ProviderUsage): number;
46
+ calculateCharge?(usage: ProviderUsage): Exclude<ProviderCost, { kind: "authoritative" }>;
41
47
  generate(args: GenerateArgs): Promise<ProviderResponse>;
42
48
  }
43
49
  ```
44
50
 
45
- `contextWindow: null` means genuinely unknown. A consumer MUST NOT invent a
46
- stand-in. A cataloged cloud model without a context window fails construction
47
- unless the operator pins `PLURNK_PROVIDERS_CONTEXT_WINDOW`. A local probe
48
- failure degrades to `null` and emits one warning because a transient probe
49
- failure must not make a usable local endpoint unbootable.
50
-
51
- `countTokens` is synchronous and non-negative. The common fallback is a
52
- conservative chars/2 ruler and is announced once. `tokenize` exists only when
53
- the endpoint exposes its real vocabulary.
54
-
55
- `calculateCost` returns estimated USD. Models.dev rates are converted at the
56
- provider boundary. Unknown pricing returns `0`; it is not represented as a
57
- fabricated rate.
51
+ `contextWindow` is provider physics and resolves under
52
+ {§model-fact-resolution}. `null` means genuinely unknown; a consumer MUST NOT
53
+ invent a stand-in. The context-window knob never carries model-facing prompt
54
+ policy or grinder pressure.
55
+
56
+ `PromptTokenMeasurement` is a discriminated request-level result:
57
+
58
+ | `kind` | Meaning | May authorize physical admission |
59
+ | ------------- | ------------------------------------------------------ | -------------------------------- |
60
+ | `exact` | Exact count for the complete provider request. | Yes. |
61
+ | `upper_bound` | Proven upper bound for the complete provider request. | Yes. |
62
+ | `estimate` | Empirical prediction with required causal `detail`. | No. |
63
+
64
+ Every result carries a non-negative integer `tokens` and a non-empty `source`.
65
+ `countPromptTokens` receives the same messages supplied to `generate` and may
66
+ perform cancellable provider I/O. The common fallback is chars/2 over message
67
+ content; it is announced once and reported honestly as an estimate because it
68
+ knows neither the serving vocabulary nor provider-owned request framing.
69
+ An unavailable optional counting endpoint likewise returns an estimate naming
70
+ the cause. A malformed measurement is a provider contract violation and fails
71
+ hard; consumers do not reinterpret it as ordinary unavailability.
72
+
73
+ `tokenize` is the separate content-token capability and exists only when the
74
+ endpoint exposes its real vocabulary. Content tokenization does not substitute
75
+ for complete-request measurement.
76
+
77
+ §provider-monetary-evidence One precedence path converts each provider response
78
+ into {§provider-cost} evidence:
79
+
80
+ | Precedence | Evidence | Result |
81
+ | --- | --- | --- |
82
+ | 1 | A documented monetary field on that response | The adapter normalizes it as `ProviderResponse.charge`; its decimal USD equivalent wins. |
83
+ | 2 | Exact response usage and the exact model's Models.dev rates | `calculateCharge` returns estimated USD, or explicit free when every applicable rate is zero. |
84
+ | 3 | Neither | Unknown; no cost is reported. |
85
+
86
+ Models.dev is the sole supported fallback rate table. Missing usage or rates
87
+ never proves free. The numeric `calculateCost` method remains callable only as a
88
+ frozen 1.x compatibility surface and is not a monetary-reporting authority.
89
+ `providerCostUsd` exposes authoritative, estimated, and free evidence as decimal
90
+ USD and returns `null` for unknown evidence.
58
91
 
59
92
  ### Generation
60
93
 
@@ -64,13 +97,13 @@ fabricated rate.
64
97
  - caller cancellation through `signal`;
65
98
  - optional `grammar` and `maxTokens`;
66
99
  - standard `sampling` intent;
67
- - first-party attribution, client, strike, workspace, loop, and turn metadata.
100
+ - opaque attribution tags plus client, strike, workspace, loop, and turn metadata.
68
101
 
69
- It returns the model's raw content and reasoning, normalized usage, normalized
70
- finish reason, model identity, opaque evidence, optional metadata, and optional
71
- telemetry. The provider transports and observes model output; it never retries,
72
- discards, or repairs an otherwise completed exchange because PLURNK grammar did
73
- not accept it.
102
+ A successful return carries the model's raw content and reasoning, normalized
103
+ usage, normalized finish reason, model identity, opaque evidence, optional
104
+ metadata, and optional notices. The provider transports and observes model
105
+ output; it never retries, discards, or repairs an otherwise completed exchange
106
+ because PLURNK grammar did not accept it.
74
107
 
75
108
  Usage obeys:
76
109
 
@@ -79,13 +112,38 @@ total = prompt + completion + reasoning
79
112
  cached ⊆ prompt
80
113
  ```
81
114
 
82
- `completion` excludes reasoning. Known vendor finish reasons normalize to
115
+ `completion` excludes reasoning. Ordinary vendor finish reasons normalize to
83
116
  `stop`, `length`, `tool_calls`, or `content_filter`; an unknown value becomes
84
- `null` and emits a warning.
117
+ `null` and emits a warning. `resource_interrupted` is the distinct failed-attempt
118
+ disposition defined by {§provider-interrupted-attempt}.
119
+
120
+ ### Tagged reasoning responses
121
+
122
+ §provider-tagged-reasoning Structured provider or SDK reasoning fields are
123
+ authoritative. Visible content is interpreted as tagged reasoning only under an
124
+ explicit alias-scoped response style:
125
+
126
+ | Effective style | Leading content | Normalized result |
127
+ | --------------- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
128
+ | `verbatim` | Any bytes. | Content remains exact; only structured reasoning fields populate `reasoning`. |
129
+ | `think-tags` | No exact leading `<think>`. | Content remains exact. |
130
+ | `think-tags` | `<think>reasoning</think>visible`. | The first envelope body becomes reasoning; the exact suffix becomes content. Later tags remain literal. |
131
+ | `think-tags` | `<think>reasoning` with no close, including a capped turn. | The complete post-open tail becomes reasoning; content is empty. |
132
+
133
+ Tag projection never runs when readable structured reasoning is already
134
+ present. Streamed and buffered transports converge on this response boundary.
135
+ When the upstream reports only combined output usage, the existing
136
+ sum-preserving text-proportion estimate reclassifies completion versus reasoning
137
+ without changing prompt, cached input, total output, or billed output.
138
+
139
+ Grammar evidence retains the exact pre-projection sentence and its Unicode
140
+ content offset. Response classification cannot rewrite what a transported GBNF
141
+ rail observed.
85
142
 
86
143
  ## §3 AI SDK boundary
87
144
 
88
- Cataloged providers instantiate their Models.dev-declared AI SDK package.
145
+ §provider-sdk-boundary Cataloged providers instantiate their
146
+ Models.dev-declared AI SDK package.
89
147
  Standard request shaping, streaming, retries, cancellation, timeouts, usage,
90
148
  and vendor error parsing belong to the SDK.
91
149
 
@@ -100,6 +158,15 @@ PLURNK maps its generic settings to AI SDK call settings:
100
158
  Provider-specific options are permitted only where they preserve a documented
101
159
  PLURNK product contract the generic SDK surface cannot express.
102
160
 
161
+ §deepseek-reasoning-request The direct DeepSeek catalog path maps the common
162
+ reasoning intent to its OpenAI-compatible controls:
163
+
164
+ | PLURNK mode | `thinking` | `reasoning_effort` |
165
+ | ----------- | --------------------- | -------------------- |
166
+ | `off` | `{ type: disabled }` | omitted |
167
+ | `adaptive` | omitted | omitted |
168
+ | `on` | `{ type: enabled }` | budget-derived tier |
169
+
103
170
  The compatible transport is deliberately retained for:
104
171
 
105
172
  - `openai` local endpoints, including llama-server and vLLM;
@@ -112,7 +179,8 @@ SDK's ordinary transport.
112
179
 
113
180
  ## §4 Operator configuration
114
181
 
115
- Every operational value is an environment knob documented in `.env.defaults`.
182
+ §provider-configuration Every operational value is an environment knob
183
+ documented in `.env.defaults`.
116
184
  There are no hidden tuning constants. Every `PLURNK_PROVIDERS_*` knob may be
117
185
  scoped to an alias by appending `_<alias>`; the scoped value wins.
118
186
 
@@ -125,12 +193,11 @@ knob's owning contract.
125
193
  The universal groups are:
126
194
 
127
195
  - reasoning activation and optional explicit budget;
196
+ - explicit reasoning response-content style;
128
197
  - decode tuning;
129
198
  - request, stream-idle, retry, and probe budgets;
130
199
  - local GBNF and llama-server capability pins;
131
200
  - context-window and generation-envelope overrides;
132
- - explicit input, cached-input, and output USD-per-million rates for models
133
- absent from the snapshot or deliberate operator overrides;
134
201
  - opt-in logprob and raw-body capture.
135
202
 
136
203
  Operator secrets and machine-specific values never belong in committed
@@ -138,10 +205,26 @@ defaults.
138
205
 
139
206
  ## §5 Resolution
140
207
 
141
- `PLURNK_MODEL_<alias>=<provider>/<model-id>` declares an alias.
208
+ §provider-resolution `PLURNK_MODEL_<alias>=<provider>/<model-id>` declares an
209
+ alias.
142
210
  `PLURNK_MODEL=<alias>` selects the boot alias. Model IDs may contain `/`.
143
211
  `PLURNK_BASEURL_<alias>` is a per-alias endpoint override.
144
212
 
213
+ ### §model-fact-resolution Model fact precedence
214
+
215
+ Provider and model facts resolve independently:
216
+
217
+ | Fact | Natural source | Operator source | Effective value |
218
+ | -------------------- | ------------------------------------------------------ | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
219
+ | Context window | Catalog metadata or a local endpoint probe. | `PLURNK_PROVIDERS_CONTEXT_WINDOW`. | Minimum when both exist; the sole value otherwise. A cataloged cloud miss fails construction; a compatible probe miss remains `null` with one warning. |
220
+ | Completion envelope | Catalog `maxOutput`; there is no live limit probe. | `PLURNK_PROVIDERS_COMPLETION_RESERVE`. | An absolute reserve wins. A percentage derives from the effective window and is capped by catalog `maxOutput` when present. |
221
+ | Reasoning capability | Catalog `reasoning: true`, exposed by snapshot lookup. | Runtime activation, reserve, and adapter wire style. | The catalog bit is informational; provider construction neither activates nor blocks reasoning from it. |
222
+ | Estimated USD rates | Models.dev input, output, and optional cache-read rates. | None. | Missing rates produce unknown evidence; explicit all-zero rates produce free evidence. No live price fetch exists. |
223
+
224
+ Models.dev cache-read cost defaults to its input cost when omitted. Cache-write
225
+ cost remains snapshot information; the current usage record has no cache-write
226
+ quantity to price.
227
+
145
228
  `instantiateProvider` resolves in this order:
146
229
 
147
230
  1. A Models.dev provider and model, using its declared AI SDK package.
@@ -161,6 +244,11 @@ Model IDs resolve exactly first. A unique catalog suffix is accepted to avoid
161
244
  forcing a vendor-owned resource prefix into PLURNK aliases. Ambiguous suffixes
162
245
  fail to resolve.
163
246
 
247
+ The catalog package identifies the protocol family, not a mandatory client
248
+ implementation. xAI uses its documented OpenAI-compatible response directly
249
+ because that wire includes exact cost ticks the corresponding AI SDK projection
250
+ omits.
251
+
164
252
  Provider declarations configure facts, not credentials:
165
253
 
166
254
  ```dotenv
@@ -181,29 +269,35 @@ belongs in MCP, schemes, executors, or mimetypes instead.
181
269
 
182
270
  A provider plugin:
183
271
 
184
- 1. declares `plurnk: { kind: "provider", name }` in `package.json`;
185
- 2. may use any npm scope;
186
- 3. default-exports an AI SDK provider with `languageModel(modelId)`;
187
- 4. peers on compatible `ai` and `@plurnk/plurnk-providers` majors.
272
+ 1. declares the exact string `plurnk: { kind: "provider", name }` in `package.json` ({§plugin-family-kind});
273
+ 2. may declare always-on package-level `plurnk.attribution` and/or implement the
274
+ synchronous runtime `attributions(context)` hook under {§plugin-attribution};
275
+ 3. may use any npm scope;
276
+ 4. default-exports an AI SDK provider with `languageModel(modelId)`;
277
+ 5. peers on compatible `ai` and `@plurnk/plurnk-providers` majors.
188
278
 
189
279
  PLURNK adapts the returned language model. The plugin does not implement the
190
280
  PLURNK `Provider`, read PLURNK tuning knobs, or reproduce transport policy.
191
281
 
192
282
  Discovery is scope-agnostic and memoized per process. Duplicate names fail hard.
193
- The common plugin trust gate applies before import. A plugin absent from
283
+ The common plugin trust gate applies before import ({§plugin-trust-boundary}). A plugin absent from
194
284
  Models.dev requires an explicit context-window pin because PLURNK will not guess
195
- model physics.
285
+ model physics. `Discovery.packageAttributions` carries the canonical package map;
286
+ the published name-keyed `Discovery.attributions` remains its 1.x projection.
196
287
 
197
288
  ## §7 Local capabilities
198
289
 
199
- The `openai` local adapter probes `/v1/models`. A llama-server fingerprint may
290
+ §provider-local-capabilities The `openai` local adapter probes `/v1/models`. A
291
+ llama-server fingerprint may
200
292
  also expose:
201
293
 
202
294
  - the actual served model and per-slot context window;
295
+ - request-scoped reasoning parsing and a cumulative response-wide allowance;
203
296
  - GBNF constrained sampling;
204
297
  - slot count and worker-sticky slot affinity;
205
298
  - EOS marker removal;
206
- - exact `/tokenize`;
299
+ - exact complete-request counting through `/v1/chat/completions/input_tokens`;
300
+ - exact content token IDs through `/tokenize`;
207
301
  - the requirement that the caller provide `maxTokens`.
208
302
 
209
303
  `PLURNK_PROVIDERS_LLAMA_SERVER` may force or disable detection. Probe attempts
@@ -212,9 +306,34 @@ and delay are knobs. A failed probe does not silently assert capabilities.
212
306
  Ollama probes `/api/show` for its model context and uses its documented
213
307
  OpenAI-compatible generation endpoint through the SDK adapter.
214
308
 
309
+ ### llama-server reasoning
310
+
311
+ For a detected llama-server, PLURNK sends the complete reasoning contract on
312
+ every request:
313
+
314
+ | Mode | Template activation | `thinking_budget_tokens` |
315
+ |---|---:|---:|
316
+ | `off` | false | `0` |
317
+ | `adaptive` | true | resolved reasoning reserve |
318
+ | `on` | true | explicit reasoning budget |
319
+
320
+ The explicit budget may tighten but MUST NOT exceed the resolved reasoning
321
+ reserve. Template calls normally use `reasoning_format: "auto"` for a separate
322
+ readable channel. A GBNF-bearing call uses `"none"` so the exact constrained
323
+ sentence survives response projection; the adapter separates its leading
324
+ reasoning enclosure only after preserving grammar evidence. Process-wide
325
+ llama-server flags are fallback server configuration, not part of the PLURNK
326
+ contract and need not be synchronized with an alias.
327
+
328
+ §llama-reasoning-request The allowance is cumulative across the complete response. Opening a second or
329
+ later reasoning block does not replenish it. Template parsing, the reasoning
330
+ sampler, normalized usage, and the returned reasoning channel MUST agree on that
331
+ response boundary.
332
+
215
333
  ## §8 Request authority
216
334
 
217
- The caller's `sampling` bag expresses sampling intent. It cannot override:
335
+ §provider-request-authority The caller's `sampling` bag expresses sampling
336
+ intent. It cannot override:
218
337
 
219
338
  - model or messages;
220
339
  - stream mode;
@@ -235,32 +354,75 @@ backend.
235
354
 
236
355
  ## §9 Failures, retries, and cancellation
237
356
 
238
- Provider failures normalize to `ProviderError` with source, kind, status where
239
- available, and the original cause. A caught failure is surfaced or deliberately
240
- preserved; it is never converted into an empty model turn.
241
-
242
- The AI SDK owns attempt scheduling. `PLURNK_PROVIDERS_RETRY_ATTEMPTS` is the
243
- maximum retry count. Caller cancellation spans the operation. Total and
244
- stream-chunk deadlines are separately configurable.
357
+ §provider-failure-normalization Provider failures normalize to `ProviderError`.
358
+ Its public contract is an RFC
359
+ 9457 Problem Details object with an exact status, stable type, occurrence
360
+ detail, and provider-kind extension; the original error remains its cause.
361
+ A caught failure is surfaced or deliberately preserved; it is never converted
362
+ into an empty model turn or reduced to a message plus a generic status.
363
+ Upstream diagnostic text is bounded by
364
+ `PLURNK_PROVIDERS_ERROR_DETAIL_LIMIT`; the committed `.env.defaults` owns its
365
+ normal value. Retry exhaustion is preserved as `attempts` and
366
+ `retryExhausted`, and the resulting Problem is not marked retryable after the
367
+ provider has consumed its automatic retry budget.
368
+
369
+ The AI SDK owns one attempt scheduler around the complete generation exchange.
370
+ `PLURNK_PROVIDERS_RETRY_ATTEMPTS` is the maximum retry count, including a
371
+ configured stream-chunk deadline that expires while consuming a response body.
372
+ The total generation deadline and caller cancellation span that scheduler and
373
+ every attempt; neither restarts during replay. Total and stream-chunk deadlines
374
+ are separately configurable.
245
375
 
246
376
  HTTP 408, 409, 429, and ordinary 5xx responses are retryable unless the endpoint
247
377
  explicitly says otherwise. Endpoint control responses 520–527 are final so a
248
378
  router can prevent multiplicative retries behind its own retry policy.
249
379
 
380
+ ### §provider-interrupted-attempt Provider-declared interruption
381
+
382
+ A successful transport response can still declare that inference did not
383
+ complete. That response is evidence for one failed provider attempt, never a
384
+ completed exchange.
385
+
386
+ | Concern | Contract |
387
+ | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
388
+ | Normalized finish reason | Exact `insufficient_system_resource` becomes `resource_interrupted`; the raw value remains in `assistantRaw`. |
389
+ | `generate` outcome | Throw `ProviderError(kind="resource_interrupted")` at local status 503 with the normalized attempt on `error.attempt`. |
390
+ | Partial response | Preserve content, reasoning, usage, model, metadata, optional raw body, and other evidence without admitting it as success. |
391
+ | Automatic replay | None; the Problem has `retryable: false`, and AI SDK retry scheduling has already completed at the successful transport. |
392
+ | Capacity-pool overflow | None; a sibling success would erase the known billed failed attempt from the current `ProviderResponse` surface. |
393
+ | Consumer admission | Persist the evidence as an unaccepted attempt; never parse it into executable work, even when its frame looks complete. |
394
+
250
395
  ## §10 Grammar
251
396
 
252
397
  GBNF is a local llama-server capability, not a generic provider expectation.
253
398
  The consumer chooses whether to supply a grammar. The provider never creates or
254
399
  rewrites one.
255
400
 
256
- When transported, output is validated locally after completion. Divergence
257
- attaches `grammar_unenforced` telemetry with its position; the bytes still
258
- return. `PLURNK_PROVIDERS_GBNF_DEBUG` validates but withholds the grammar and
259
- compares the unconstrained result for diagnostics.
401
+ GBNF defines the accepted raw sampled text; it runs before response reasoning
402
+ is separated from regular content. The shipped PLURNK sentence is owned by
403
+ `plurnk-contracts` {§gbnf-turn-shape} and {§gbnf-reasoning-boundary}; this package does
404
+ not restate or rewrite it.
405
+
406
+ When a grammar-capable adapter receives a grammar, `ProviderResponse` carries
407
+ `grammarEvidence: { input, contentStart, transported }`. `input` is the exact
408
+ pre-projection sentence represented by the response, `contentStart` is its
409
+ Unicode-code-point offset to `assistant.content`, and `transported` says whether
410
+ the grammar was actually sent. Active llama-server template reasoning requests
411
+ the unprojected sentence, records it, and then separates its leading enclosure;
412
+ an empty body therefore remains observable. An endpoint that projects despite
413
+ that request supplies no independent evidence. For an unsplit response, `input`
414
+ is `content` and `contentStart` is zero.
415
+
416
+ §gbnf-response-observation The provider transports and represents; it does not grade its own enforcement.
417
+ The consumer validates `grammarEvidence.input` outside the enforcer's failure
418
+ domain. `PLURNK_PROVIDERS_GBNF_DEBUG` still validates grammar syntax before the
419
+ call and sets `transported: false` for the unconstrained comparison.
420
+
260
421
 
261
422
  ## §11 Evidence and metadata
262
423
 
263
- `assistantRaw` is an opaque normalized transport record. Provider top-level
424
+ §provider-evidence `assistantRaw` is an opaque normalized transport record.
425
+ Provider top-level
264
426
  metadata is forwarded as an open bag without reinterpreting currencies or
265
427
  vendor fields.
266
428
 
@@ -270,25 +432,42 @@ When enabled, raw per-token model logprob is canonical; alternatives are
270
432
  preserved when returned. Raw body/chunks preserve wire evidence the normalized
271
433
  record omits.
272
434
 
273
- Readable reasoning and encrypted reasoning are separate. Encrypted reasoning is
274
- preserved verbatim and never decoded or synthesized.
435
+ §provider-encrypted-reasoning **Readable reasoning and encrypted reasoning are
436
+ separate.** Encrypted payload bytes remain opaque and are never decoded. The
437
+ provider boundary distinguishes preserved detail evidence from derived entity
438
+ classification:
439
+
440
+ | Provider fact | Meaning |
441
+ | -------------------------------- | ------- |
442
+ | `id` | The provider's reasoning-detail identity, or `null`; never an AG-UI message or tool-call identity. |
443
+ | `subtype` | A provider-normalized classification supported by wire structure. OpenAI-compatible `message.reasoning_details` is `message`; no PLURNK operation is reclassified as a native tool call. |
444
+ | `encrypted[*].data` / `format` | Ordered provider evidence, retained without decoding or concatenation across distinct details. |
445
+
446
+ Unrecognized detail shapes are omitted at this normalization boundary. Core
447
+ may preserve normalized items as forensic evidence, but a client protocol must
448
+ correlate them to an entity it actually created rather than reusing `id`.
275
449
 
276
450
  ## §12 Generation envelopes
277
451
 
278
- Reasoning and completion reserves are percentages of the resolved context
452
+ §provider-generation-envelope Reasoning and completion reserves are percentages
453
+ of the resolved context
279
454
  window or absolute token counts. Absolute pins win. The provider reports the
280
- resolved reserves; the consumer owns prompt packing and the per-call output cap.
281
-
282
- Models.dev `maxOutput` constrains a percentage-derived completion reserve but
283
- does not override an explicit absolute operator choice. Unknown model physics
284
- remain unknown.
455
+ resolved reserves; the consumer owns prompt packing and the per-call output
456
+ cap. Model-limit precedence is defined once in {§model-fact-resolution}.
285
457
 
286
458
  ## §13 Capacity pool
287
459
 
288
- `Pool` fronts interchangeable `Provider` instances. It keeps workers sticky for
460
+ §provider-capacity-pool `Pool` fronts interchangeable `Provider` instances. It
461
+ keeps workers sticky for
289
462
  cache locality, selects a healthy sibling for overflow, and preserves the same
290
463
  Provider contract. Whether endpoints are interchangeable is a consumer
291
- decision, not inferred from provider names.
464
+ decision, not inferred from provider names. Overflow is limited to transport
465
+ availability and rate-limit failures that carry no normalized response attempt;
466
+ {§provider-interrupted-attempt} propagates without overflow.
467
+
468
+ Prompt measurement covers every backend that could receive the request. The
469
+ pool takes the largest result; differing exact counts or any proven bound yield
470
+ an `upper_bound`, while any estimate makes the aggregate an estimate.
292
471
 
293
472
  ## §14 Conformance
294
473
 
@@ -298,8 +477,12 @@ Coverage MUST prove:
298
477
  - exact and unique-suffix model lookup;
299
478
  - native SDK request mapping and normalized responses;
300
479
  - compatible extension preservation;
301
- - timeout, retry, cancellation, and final-error behavior;
480
+ - timeout, retry, cancellation, interrupted-attempt, and final-error behavior;
302
481
  - local capability probes and pins;
482
+ - exact, bounded, and estimated complete-request token measurements;
483
+ - local reasoning activation, response-wide allowance, and GBNF coexistence;
484
+ - explicit tagged-reasoning projection across streamed, buffered, capped, and
485
+ literal-tag responses;
303
486
  - usage, costs, evidence, metadata isolation, and grammar observation;
304
487
  - alias scoping and fail-hard invalid configuration.
305
488
 
@@ -1,21 +1,29 @@
1
- import type { ChatMessage, Provider, ProviderResponse, ProviderUsage } from "./types.ts";
2
- import type { Reasoning, ReserveSpec } from "./env.ts";
1
+ import type { AuthoritativeChargeNormalizer, ChatMessage, PromptTokenMeasurement, Provider, ProviderResponse, ProviderUsage } from "./types.ts";
2
+ import type { ProviderCost } from "@plurnk/plurnk-contracts";
3
+ import type { Reasoning, ReasoningResponseStyle, ReserveSpec } from "./env.ts";
3
4
  import type { LanguageModel } from "ai";
5
+ import type { PluginAttribution, PluginAttributionContext } from "@plurnk/plurnk-meta";
4
6
  export type ProviderFetch = typeof globalThis.fetch;
5
- export type ReasoningStyle = "none" | "think" | "include_reasoning" | "effort" | "effort_explicit" | "template" | "anthropic";
7
+ export type ReasoningStyle = "none" | "think" | "include_reasoning" | "effort" | "effort_explicit" | "thinking_effort" | "template" | "anthropic";
6
8
  export type GrammarStyle = "none" | "llamacpp";
7
9
  export type AiSdkProviderConfig = {
8
10
  model: string;
9
11
  url?: string;
10
12
  languageModel?: LanguageModel;
13
+ attributions?: (context: PluginAttributionContext) => PluginAttribution;
11
14
  fetchTimeoutMs: number;
12
15
  streamIdleTimeoutMs?: number;
13
16
  headers?: Record<string, string>;
14
17
  fetch?: ProviderFetch;
15
18
  contextWindow?: number | null;
16
19
  reasoningStyle?: ReasoningStyle;
17
- countTokens?: (text: string) => number;
20
+ reasoningResponseStyle?: ReasoningResponseStyle;
21
+ countPromptTokens?: (messages: readonly ChatMessage[], signal?: AbortSignal) => PromptTokenMeasurement | Promise<PromptTokenMeasurement>;
18
22
  calculateCost?: (usage: ProviderUsage) => number;
23
+ calculateCharge?: (usage: ProviderUsage) => Exclude<ProviderCost, {
24
+ kind: "authoritative";
25
+ }>;
26
+ normalizeCharge?: AuthoritativeChargeNormalizer;
19
27
  source?: string;
20
28
  grammarStyle?: GrammarStyle;
21
29
  promptCacheKey?: boolean;
@@ -28,6 +36,7 @@ export type AiSdkProviderConfig = {
28
36
  supportsSlotPinning?: boolean;
29
37
  slotCount?: number | null;
30
38
  tokenizeUrl?: string;
39
+ promptTokensUrl?: string;
31
40
  servedModel?: string;
32
41
  requiresMaxTokens?: boolean;
33
42
  reasoning: Reasoning;
@@ -39,6 +48,7 @@ export type AiSdkProviderConfig = {
39
48
  dryAllowedLength?: number;
40
49
  repeatLastN?: number;
41
50
  retryAttempts: number;
51
+ errorDetailLimit?: number;
42
52
  topLogprobs?: number | null;
43
53
  rawBody?: boolean;
44
54
  reasoningReserve?: ReserveSpec;
@@ -48,6 +58,7 @@ export type AiSdkProviderConfig = {
48
58
  export declare const effortFromBudget: (budget: number) => "low" | "medium" | "high";
49
59
  export default class AiSdkProvider implements Provider {
50
60
  #private;
61
+ readonly attributions?: (context: PluginAttributionContext) => PluginAttribution;
51
62
  tokenize?: (text: string) => Promise<number[]>;
52
63
  constructor(config: AiSdkProviderConfig);
53
64
  get contextWindow(): number | null;
@@ -57,8 +68,11 @@ export default class AiSdkProvider implements Provider {
57
68
  get servedModel(): string | undefined;
58
69
  get requiresMaxTokens(): boolean | undefined;
59
70
  get constrainsOutput(): boolean;
60
- countTokens(text: string): number;
71
+ countPromptTokens(messages: readonly ChatMessage[], signal?: AbortSignal): Promise<PromptTokenMeasurement>;
61
72
  calculateCost(usage: ProviderUsage): number;
73
+ calculateCharge(usage: ProviderUsage): Exclude<ProviderCost, {
74
+ kind: "authoritative";
75
+ }>;
62
76
  generate({ messages, workerId, primaryWorkerId, signal, grammar, maxTokens, attributions, client, strikes, workspaceId, loop, turn, sampling }: {
63
77
  messages: ChatMessage[];
64
78
  workerId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"AiSdkProvider.d.ts","sourceRoot":"","sources":["../src/AiSdkProvider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AiSdkProvider.d.ts","sourceRoot":"","sources":["../src/AiSdkProvider.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,6BAA6B,EAAE,WAAW,EAAmB,sBAAsB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACjK,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAOxC,OAAO,KAAK,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAGvF,MAAM,MAAM,aAAa,GAAG,OAAO,UAAU,CAAC,KAAK,CAAC;AAIpD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,mBAAmB,GAAG,QAAQ,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,UAAU,GAAG,WAAW,CAAC;AAIlJ,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,UAAU,CAAC;AAE/C,MAAM,MAAM,mBAAmB,GAAG;IAC9B,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,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;IAChD,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,sBAAsB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACzI,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,MAAM,CAAC;IACjD,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC,CAAC;IAC7F,eAAe,CAAC,EAAE,6BAA6B,CAAC;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,YAAY,CAAC;IAM5B,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAI1B,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,eAAe,CAAC,EAAE,MAAM,CAAC;IAKzB,WAAW,CAAC,EAAE,MAAM,CAAC;IAIrB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAM5B,SAAS,EAAE,SAAS,CAAC;IAOrB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IAKtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAK1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IAKrB,aAAa,EAAE,MAAM,CAAC;IAItB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAQ1B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAOlB,gBAAgB,CAAC,EAAE,WAAW,CAAC;IAC/B,iBAAiB,CAAC,EAAE,WAAW,CAAC;IAIhC,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAmEF,eAAO,MAAM,gBAAgB,WAAY,MAAM,KAAG,KAAK,GAAG,QAAQ,GAAG,MAIpE,CAAC;AAwBF,MAAM,CAAC,OAAO,OAAO,aAAc,YAAW,QAAQ;;IA6ClD,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,iBAAiB,CAAC;IAMjF,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/C,YAAY,MAAM,EAAE,mBAAmB,EAkFtC;IAED,IAAI,aAAa,IAAI,MAAM,GAAG,IAAI,CAAgC;IAQlE,IAAI,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAAyD;IAC9F,IAAI,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAA0D;IAChG,IAAI,KAAK,IAAI,MAAM,CAAwB;IAE3C,IAAI,WAAW,IAAI,MAAM,GAAG,SAAS,CAA8B;IAEnE,IAAI,iBAAiB,IAAI,OAAO,GAAG,SAAS,CAAoC;IAIhF,IAAI,gBAAgB,IAAI,OAAO,CAA0C;IAEnE,iBAAiB,CACnB,QAAQ,EAAE,SAAS,WAAW,EAAE,EAChC,MAAM,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,sBAAsB,CAAC,CA8CjC;IACD,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAAuC;IAClF,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC,CAGtF;IAwLK,QAAQ,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8Oxc;CAEJ"}