@plurnk/plurnk-providers 1.29.0 → 3.0.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 +20 -14
- package/README.md +8 -8
- package/SPEC.md +45 -28
- package/dist/AiSdkProvider.d.ts +9 -3
- package/dist/AiSdkProvider.d.ts.map +1 -1
- package/dist/AiSdkProvider.js +36 -10
- package/dist/AiSdkProvider.js.map +1 -1
- package/dist/AiSdkRequestBody.d.ts +2 -1
- package/dist/AiSdkRequestBody.d.ts.map +1 -1
- package/dist/AiSdkRequestBody.js +7 -3
- package/dist/AiSdkRequestBody.js.map +1 -1
- package/dist/Pool.d.ts +2 -2
- package/dist/Pool.d.ts.map +1 -1
- package/dist/Pool.js.map +1 -1
- package/dist/ProviderRegistry.d.ts.map +1 -1
- package/dist/ProviderRegistry.js +3 -3
- package/dist/ProviderRegistry.js.map +1 -1
- package/dist/RequestFields.d.ts +0 -1
- package/dist/RequestFields.d.ts.map +1 -1
- package/dist/RequestFields.js +1 -12
- package/dist/RequestFields.js.map +1 -1
- package/dist/aiSdkTransport.js +2 -2
- package/dist/aiSdkTransport.js.map +1 -1
- package/dist/catalogProvider.d.ts +5 -4
- package/dist/catalogProvider.d.ts.map +1 -1
- package/dist/catalogProvider.js +3 -1
- package/dist/catalogProvider.js.map +1 -1
- package/dist/discover.js.map +1 -1
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +6 -49
- package/dist/env.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/notices.d.ts +1 -1
- package/dist/sdkModels.d.ts +2 -1
- package/dist/sdkModels.d.ts.map +1 -1
- package/dist/sdkModels.js +11 -5
- package/dist/sdkModels.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +20 -19
package/.env.defaults
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# PLURNK_BASEURL_local=http://127.0.0.1:8080/v1
|
|
13
13
|
# PLURNK_MODEL=cloud
|
|
14
14
|
# PLURNK_MODEL=deepseek/deepseek-v4-flash
|
|
15
|
+
# Any declared alias's own endpoint, overriding its provider's.
|
|
16
|
+
# PLURNK_BASEURL_<alias>=<url>
|
|
15
17
|
|
|
16
18
|
# --- Capacity ---
|
|
17
19
|
# Simultaneous inference attempts per resolved endpoint in this process; -1 = unrestricted.
|
|
@@ -43,20 +45,20 @@ PLURNK_PROVIDERS_EFFORT_FALLBACK=high
|
|
|
43
45
|
PLURNK_PROVIDERS_REASONING_RESPONSE_STYLE=verbatim
|
|
44
46
|
# Compatible wire declarations below supplement Models.dev; native SDKs own their protocols.
|
|
45
47
|
# Route knobs use the same suffix, e.g. PLURNK_PROVIDERS_REASONING_BUDGET_PATH_<alias>.
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
#
|
|
48
|
+
# PLURNK_PROVIDERS_OUTPUT_PATH=/max_completion_tokens
|
|
49
|
+
# PLURNK_PROVIDERS_REASONING_EFFORT_PATH=/reasoning_effort
|
|
50
|
+
# PLURNK_PROVIDERS_REASONING_CONTROLS=exclusive
|
|
51
|
+
# PLURNK_PROVIDERS_REASONING_ON_BODY='{"enable_thinking":true}'
|
|
52
|
+
# PLURNK_PROVIDERS_REASONING_OFF_BODY='{"enable_thinking":false}'
|
|
53
|
+
# PLURNK_PROVIDERS_REASONING_EFFORTS=low,medium,high
|
|
54
|
+
# PLURNK_PROVIDERS_REASONING_TRANSPORT_EFFORTS=none,low,medium,high
|
|
55
|
+
# PLURNK_PROVIDERS_OPTIONS_NAMESPACE=openrouter
|
|
56
|
+
# PLURNK_PROVIDERS_REASONING_ADAPTIVE_BODY='{}'
|
|
57
|
+
# PLURNK_PROVIDERS_REASONING_TOGGLE_BODY='{"reasoning":{"enabled":true}}'
|
|
58
|
+
# PLURNK_PROVIDERS_ADAPTIVE_OPTIONS='[{"models":["*"],"options":{"<sdk-namespace>":{…}}}]'
|
|
59
|
+
# PLURNK_PROVIDERS_SYSTEM_CACHE_OPTIONS=
|
|
60
|
+
# PLURNK_PROVIDERS_APP_URL=https://example.test/app
|
|
61
|
+
# PLURNK_PROVIDERS_APP_NAME=Example
|
|
60
62
|
|
|
61
63
|
# --- Sampling ---
|
|
62
64
|
# Temperature; empty = omit, retaining the provider's sampling default.
|
|
@@ -97,6 +99,7 @@ PLURNK_PROVIDERS_PROVIDER_FIREWORKS_AI_CACHE_AFFINITY_FIELD='{"target":"header",
|
|
|
97
99
|
# off = no explicit writes. This is distinct from affinity and can affect billing.
|
|
98
100
|
PLURNK_PROVIDERS_CACHE_WRITE_POLICY=stable-system
|
|
99
101
|
# Provider service tier; unset = provider default. Usually set per alias: routing can change cost.
|
|
102
|
+
# Native routes send it only where the SDK documents one ({§provider-request-controls}); others warn.
|
|
100
103
|
# PLURNK_PROVIDERS_SERVICE_TIER=
|
|
101
104
|
# PLURNK_PROVIDERS_SERVICE_TIER_myfireworks=priority
|
|
102
105
|
# USD per million tokens, merged over Models.dev rates; omitted categories retain catalog values.
|
|
@@ -131,6 +134,7 @@ PLURNK_PROVIDERS_PROBE_DELAY=250
|
|
|
131
134
|
|
|
132
135
|
# --- Evidence capture ---
|
|
133
136
|
# OpenAI top_logprobs: off/unset = none; 0 = chosen token only; N > 0 = alternatives.
|
|
137
|
+
# Compatible routes and native OpenAI send it; other native routes warn ({§provider-request-controls}).
|
|
134
138
|
# PLURNK_PROVIDERS_TOP_LOGPROBS=3
|
|
135
139
|
# Retain raw wire body: unset/empty/0 = off; other values = on. Usually isolate to one capture alias.
|
|
136
140
|
# PLURNK_PROVIDERS_RAWBODY=1
|
|
@@ -157,6 +161,8 @@ PLURNK_PROVIDERS_PROBE_DELAY=250
|
|
|
157
161
|
# PLURNK_PROVIDERS_PROVIDER_ACME_REASONING_ON_BODY='{"reasoning":{"enabled":true}}'
|
|
158
162
|
# PLURNK_PROVIDERS_PROVIDER_ACME_REASONING_OFF_BODY='{"reasoning":{"enabled":false}}'
|
|
159
163
|
# PLURNK_PROVIDERS_PROVIDER_ACME_REASONING_ADAPTIVE_BODY='{}'
|
|
164
|
+
# The form of every provider declaration; NAME is the route's provider segment.
|
|
165
|
+
# PLURNK_PROVIDERS_PROVIDER_<NAME>_<SETTING>=<value>
|
|
160
166
|
PLURNK_PROVIDERS_PROVIDER_FIREWORKS_AI_REASONING_EFFORT_PATH=/reasoning_effort
|
|
161
167
|
PLURNK_PROVIDERS_PROVIDER_FIREWORKS_AI_REASONING_OFF_BODY='{"reasoning_effort":"none"}'
|
|
162
168
|
PLURNK_PROVIDERS_PROVIDER_FIREWORKS_AI_REASONING_TOGGLE_BODY='{"reasoning_effort":true}'
|
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
import { ProviderError } from "@plurnk/plurnk-providers/errors";
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
The package root composes the complete Node provider runtime, including
|
|
45
|
+
The package root composes the complete Node provider runtime, including extension
|
|
46
46
|
discovery and environment-file defaults.
|
|
47
47
|
|
|
48
48
|
## Configure a model
|
|
@@ -126,10 +126,10 @@ flowchart TD
|
|
|
126
126
|
shrink known capacity or declare unknown capacity, never enlarge known limits.
|
|
127
127
|
Prompt projection and initialization reasoning READ limits are separate Core policy.
|
|
128
128
|
|
|
129
|
-
## Provider
|
|
129
|
+
## Provider extensions
|
|
130
130
|
|
|
131
131
|
Most integrations should use an MCP server, executor, scheme, or a provider
|
|
132
|
-
declaration. A provider
|
|
132
|
+
declaration. A provider extension is only needed for a protocol binding unavailable
|
|
133
133
|
through the catalog and installed SDK packages.
|
|
134
134
|
|
|
135
135
|
It may use any npm scope. Its package manifest declares the PLURNK name:
|
|
@@ -149,16 +149,16 @@ It may use any npm scope. Its package manifest declares the PLURNK name:
|
|
|
149
149
|
|
|
150
150
|
The default export is an AI SDK provider with
|
|
151
151
|
`languageModel(modelId)`. PLURNK adapts that language model into its own
|
|
152
|
-
contract, so
|
|
152
|
+
contract, so extensions do not reproduce retries, usage normalization, envelopes,
|
|
153
153
|
notices, or RFC 9457 failure normalization.
|
|
154
154
|
|
|
155
155
|
The manifest may declare always-on `plurnk.attribution`. The default export may
|
|
156
156
|
also implement synchronous `attributions(context)` and decide per provider
|
|
157
157
|
attempt whether to return no, one, or many additional opaque tags
|
|
158
|
-
({§
|
|
158
|
+
({§extension-attribution}).
|
|
159
159
|
|
|
160
160
|
Discovery is scope-agnostic and rejects duplicate names.
|
|
161
|
-
Third-party discovery uses the shared pre-import trust contract ({§
|
|
161
|
+
Third-party discovery uses the shared pre-import trust contract ({§extension-trust-boundary}).
|
|
162
162
|
|
|
163
163
|
## Local endpoints
|
|
164
164
|
|
|
@@ -199,14 +199,14 @@ opt-in for endpoints that emit a leading `<think>` envelope, not a reasoning swi
|
|
|
199
199
|
| Generation deadline | One whole-call allowance across queueing, requests and retries; caller cancellation still applies. No first-content or inter-chunk cutoff. |
|
|
200
200
|
| Discovery/tokenizer HTTP | Separate non-generation fetch bound; does not limit inference. |
|
|
201
201
|
| Provider-directed waits | Bounded retries honor `Retry-After`; other recoverable failures return to Core. |
|
|
202
|
-
| Loop recovery | Core reissues within its recovery window, then parks
|
|
202
|
+
| Loop recovery | Core reissues within its recovery window, then parks for a review-capable owner or concludes on the failure. |
|
|
203
203
|
| Cache affinity | Stable Worker identity through documented provider controls; not a cache-hit guarantee. |
|
|
204
204
|
| Explicit cache writes | Separate policy on supported routes; can affect billing. |
|
|
205
205
|
| Service tier | Explicit route choice that may change price and availability. |
|
|
206
206
|
| Cost | Provider monetary evidence wins; known usage and catalog rates yield an estimate, not a settled charge. |
|
|
207
207
|
|
|
208
208
|
For uncataloged compatible endpoints, declare the SDK, URL, and credential-variable
|
|
209
|
-
name together; the examples are in the defaults reference. A provider
|
|
209
|
+
name together; the examples are in the defaults reference. A provider extension is
|
|
210
210
|
needed only when the protocol cannot be expressed by the installed adapters.
|
|
211
211
|
|
|
212
212
|
## Configured-provider packet conformance matrix
|
package/SPEC.md
CHANGED
|
@@ -103,7 +103,9 @@ the upstream provider as capacity oracle. The curation reservation's intersectio
|
|
|
103
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
|
-
substitute their own content heuristic for request-shaped admission.
|
|
106
|
+
substitute their own content heuristic for request-shaped admission. A consumer
|
|
107
|
+
may assess a request before sending it; `generate` repeats the assessment as its
|
|
108
|
+
own guard.
|
|
107
109
|
|
|
108
110
|
`tokenize` is the separate content-token capability and exists only when the
|
|
109
111
|
endpoint exposes its real vocabulary. Content tokenization does not substitute
|
|
@@ -177,7 +179,7 @@ The built-in transports preserve that intent after SDK serialization:
|
|
|
177
179
|
| Anthropic Messages | `tools: []`, `tool_choice: {"type":"none"}` |
|
|
178
180
|
| Gemini GenerateContent | `tools: []`, `toolConfig: {"functionCallingConfig":{"mode":"NONE"}}` |
|
|
179
181
|
| Bedrock Converse | No tool configuration; the protocol has no `none` choice. |
|
|
180
|
-
| Installed SDK provider
|
|
182
|
+
| Installed SDK provider extensions | Portable `none` intent; the extension owns its wire projection. |
|
|
181
183
|
|
|
182
184
|
This is a text-generation contract, not provider/model tuning or prompt
|
|
183
185
|
teaching. Callers cannot supply tools or override the choice through request
|
|
@@ -451,8 +453,6 @@ Native SDKs retain their own output field; `OUTPUT_PATH` is incompatible with an
|
|
|
451
453
|
options namespace. Request-local options are projected after the effective
|
|
452
454
|
envelope is known, never frozen into SDK model construction. Streaming and
|
|
453
455
|
non-streaming calls use the same projection.
|
|
454
|
-
Retired `REASONING_STYLE` selectors fail at the selected provider/alias boundary;
|
|
455
|
-
they neither select a preset nor silently coexist with these declarations.
|
|
456
456
|
|
|
457
457
|
A native SDK's portable reasoning setting has no `max`, so a native route without
|
|
458
458
|
a namespace cannot send an effort the catalog documents beyond it; construction
|
|
@@ -554,12 +554,9 @@ The provider segment of a model route IS the Models.dev id (#459) —
|
|
|
554
554
|
configurations align with the catalog end to end (`fireworks-ai/…`,
|
|
555
555
|
`cloudflare-workers-ai/@cf/…`, `togetherai/…`), and the
|
|
556
556
|
`PLURNK_PROVIDERS_PROVIDER_<PREFIX>_*` prefix is that id uppercased with
|
|
557
|
-
non-alphanumerics as underscores (`FIREWORKS_AI`).
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
silently resolves. Custom declared providers keep their operator-chosen
|
|
561
|
-
names; the built-in local `ollama` rail keeps its name (the catalog's
|
|
562
|
-
`ollama-cloud` is a different provider).
|
|
557
|
+
non-alphanumerics as underscores (`FIREWORKS_AI`). Custom declared providers
|
|
558
|
+
keep their operator-chosen names; the built-in local `ollama` rail keeps its
|
|
559
|
+
name (the catalog's `ollama-cloud` is a different provider).
|
|
563
560
|
|
|
564
561
|
`instantiateProvider` resolves in this order:
|
|
565
562
|
|
|
@@ -567,14 +564,14 @@ names; the built-in local `ollama` rail keeps its name (the catalog's
|
|
|
567
564
|
2. An operator provider declaration:
|
|
568
565
|
`PLURNK_PROVIDERS_PROVIDER_<NAME>_{NPM,BASE_URL,API_KEY_ENV}`.
|
|
569
566
|
3. The local `openai` or `ollama` adapter.
|
|
570
|
-
4. A discovered AI SDK provider
|
|
567
|
+
4. A discovered AI SDK provider extension.
|
|
571
568
|
5. A precise unknown-provider error.
|
|
572
569
|
|
|
573
|
-
Earlier sources are authoritative. Installed
|
|
570
|
+
Earlier sources are authoritative. Installed extensions cannot shadow a cataloged
|
|
574
571
|
or explicitly declared name. This remains true when a named model is absent
|
|
575
572
|
from the Models.dev snapshot: construction requires an explicit
|
|
576
573
|
`PLURNK_PROVIDERS_CONTEXT_WINDOW` and never falls through to a same-name
|
|
577
|
-
|
|
574
|
+
extension.
|
|
578
575
|
|
|
579
576
|
Model IDs resolve exactly first. A unique catalog suffix is accepted to avoid
|
|
580
577
|
forcing a vendor-owned resource prefix into PLURNK aliases. Ambiguous suffixes
|
|
@@ -603,36 +600,36 @@ The named secret remains in the operator environment. `${ENV_NAME}` inside a
|
|
|
603
600
|
catalog or declared endpoint is expanded at construction and fails clearly
|
|
604
601
|
when absent.
|
|
605
602
|
|
|
606
|
-
## §6 Provider
|
|
603
|
+
## §6 Provider extensions
|
|
607
604
|
|
|
608
|
-
Provider
|
|
605
|
+
Provider extensions are the escape hatch for a protocol binding not represented by
|
|
609
606
|
Models.dev, installed SDK providers, or a declaration. Most extensibility
|
|
610
607
|
belongs in MCP, schemes, executors, or mimetypes instead.
|
|
611
608
|
|
|
612
|
-
A provider
|
|
609
|
+
A provider extension:
|
|
613
610
|
|
|
614
|
-
1. declares the exact string `plurnk: { kind: "provider", name }` in `package.json` ({§
|
|
611
|
+
1. declares the exact string `plurnk: { kind: "provider", name }` in `package.json` ({§extension-kind});
|
|
615
612
|
2. may declare always-on package-level `plurnk.attribution` and/or implement the
|
|
616
|
-
synchronous runtime `attributions(context)` hook under {§
|
|
613
|
+
synchronous runtime `attributions(context)` hook under {§extension-attribution};
|
|
617
614
|
3. may use any npm scope;
|
|
618
615
|
4. default-exports an AI SDK provider with `languageModel(modelId)`;
|
|
619
616
|
5. peers on compatible `ai` and `@plurnk/plurnk-providers` majors.
|
|
620
617
|
|
|
621
|
-
§provider-grammar-transport
|
|
618
|
+
§provider-grammar-transport An extension whose backend accepts a llama.cpp-style
|
|
622
619
|
GBNF grammar may declare `plurnk.grammarStyle: "llamacpp"` beside its kind and
|
|
623
620
|
name; the discovery records it and the adapted Provider carries the capability,
|
|
624
621
|
so an operator's grammar file ({§operator-grammar}) rides the wire exactly as
|
|
625
622
|
on a probed llama-server. Absence or `"none"` keeps the grammar off the wire;
|
|
626
|
-
any other value fails discovery loudly. The declaration is the
|
|
623
|
+
any other value fails discovery loudly. The declaration is the extension author's
|
|
627
624
|
fact about their backend; the transport evidence on each response
|
|
628
625
|
({§provider-grammar-evidence}) is where a wrong declaration shows, never by
|
|
629
626
|
degrading admission.
|
|
630
627
|
|
|
631
|
-
PLURNK adapts the returned language model. The
|
|
628
|
+
PLURNK adapts the returned language model. The extension does not implement the
|
|
632
629
|
PLURNK `Provider`, read PLURNK tuning knobs, or reproduce transport policy.
|
|
633
630
|
|
|
634
631
|
Discovery is scope-agnostic and memoized per process. Duplicate names fail hard.
|
|
635
|
-
The common
|
|
632
|
+
The common extension trust gate applies before import ({§extension-trust-boundary}). An extension absent from
|
|
636
633
|
Models.dev requires an explicit context-window pin because PLURNK will not guess
|
|
637
634
|
model physics. `Discovery.packageAttributions` carries the canonical package map.
|
|
638
635
|
|
|
@@ -701,14 +698,35 @@ Generic AI SDK calls accept only settings represented by the SDK's portable
|
|
|
701
698
|
surface. Compatible endpoints may carry additional sampling keys after reserved
|
|
702
699
|
keys are removed.
|
|
703
700
|
|
|
701
|
+
§provider-request-controls **A configured service tier or logprobs count reaches a
|
|
702
|
+
native route only through the per-call option its SDK documents.** On a compatible
|
|
703
|
+
route, `PLURNK_PROVIDERS_SERVICE_TIER` and `PLURNK_PROVIDERS_TOP_LOGPROBS` are the
|
|
704
|
+
body fields `service_tier`, `logprobs` and `top_logprobs`. A native route sends them
|
|
705
|
+
in its SDK's `providerOptions` namespace, serialized by that SDK. A control the SDK
|
|
706
|
+
does not document is not sent, and one process warning,
|
|
707
|
+
`PLURNK_REQUEST_CONTROL_UNSUPPORTED`, names it, so a configured choice never
|
|
708
|
+
disappears in silence. The tier passes verbatim: the SDK owns its vocabulary, and a
|
|
709
|
+
value it drops surfaces as its call warning ({§provider-sdk-warning}). A logprobs
|
|
710
|
+
count of 0 asks for the chosen token only.
|
|
711
|
+
|
|
712
|
+
| Native SDK | Namespace | Service tier | Logprobs |
|
|
713
|
+
| --- | --- | --- | --- |
|
|
714
|
+
| OpenAI | `openai` | sent | sent |
|
|
715
|
+
| Groq | `groq` | sent | not sent |
|
|
716
|
+
| Cerebras | `cerebras` | sent | not sent |
|
|
717
|
+
| xAI | `xai` | sent | not sent |
|
|
718
|
+
| Google | `google` | sent | not sent |
|
|
719
|
+
| Anthropic | `anthropic` | sent | not sent |
|
|
720
|
+
| Amazon Bedrock | `bedrock` | sent | not sent |
|
|
721
|
+
| Mistral, Together, DeepInfra, OpenRouter | none | not sent | not sent |
|
|
722
|
+
|
|
704
723
|
§openrouter-app-attribution **A route on the OpenRouter SDK identifies the calling
|
|
705
724
|
application only as its provider declares.** `APP_URL`, an absolute HTTP(S) URL, and
|
|
706
725
|
the optional `APP_NAME` are provider declarations (`PLURNK_PROVIDERS_PROVIDER_<NAME>_`,
|
|
707
726
|
overridable per route or alias); the SDK sends them as `HTTP-Referer` and
|
|
708
727
|
`X-OpenRouter-Title`. The shipped floor declares them for `openrouter` only, so
|
|
709
728
|
another provider on the same SDK package sends none; an empty `APP_URL` suppresses
|
|
710
|
-
both.
|
|
711
|
-
`OPENROUTER_X_TITLE` fail construction.
|
|
729
|
+
both.
|
|
712
730
|
|
|
713
731
|
## §9 Failures, retries, and cancellation
|
|
714
732
|
|
|
@@ -997,8 +1015,7 @@ replayed. Missing output usage cannot prove a violation.
|
|
|
997
1015
|
as `35%`. `PLURNK_PROVIDERS_REASONING_BUDGET` is optional; leaving it unset
|
|
998
1016
|
preserves provider-adaptive depth. A backend known to decode without a finite
|
|
999
1017
|
limit advertises `requiresOutputBudget` and fails construction when no total can
|
|
1000
|
-
be resolved.
|
|
1001
|
-
a second envelope contract.
|
|
1018
|
+
be resolved.
|
|
1002
1019
|
|
|
1003
1020
|
## §13 Inference capacity
|
|
1004
1021
|
|
|
@@ -1011,7 +1028,7 @@ alias scoping. Zero, other negative values and non-integers are invalid.
|
|
|
1011
1028
|
|
|
1012
1029
|
| Boundary | Contract |
|
|
1013
1030
|
| --- | --- |
|
|
1014
|
-
| Identity | Provider instances and aliases sharing the resolved API base URL share one allowance. SDK
|
|
1031
|
+
| Identity | Provider instances and aliases sharing the resolved API base URL share one allowance. SDK- or extension-owned endpoints without a resolved URL share their provider identity. Conflicting limits for one identity fail construction, naming the identity and both values; they never create independent queues. The daemon reads its environment once at boot, so an identity's limit cannot change within a process: reconstructing a provider from that environment reuses its allowance, and in-flight leases keep counting. |
|
|
1015
1032
|
| 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. |
|
|
1016
1033
|
| 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. |
|
|
1017
1034
|
| Retries | Backoff holds no lease. Each retry rejoins admission as a new physical attempt. |
|
|
@@ -1045,7 +1062,7 @@ complete-envelope derivation per backend before taking the minimum.
|
|
|
1045
1062
|
|
|
1046
1063
|
Coverage MUST prove:
|
|
1047
1064
|
|
|
1048
|
-
- catalog, declaration, local, and
|
|
1065
|
+
- catalog, declaration, local, and extension resolution;
|
|
1049
1066
|
- exact and unique-suffix model lookup;
|
|
1050
1067
|
- native SDK request mapping and normalized responses;
|
|
1051
1068
|
- compatible extension preservation;
|
package/dist/AiSdkProvider.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { JSONValue } from "ai";
|
|
|
4
4
|
import type { EffortSetting, ReasoningResponseStyle } from "./env.ts";
|
|
5
5
|
import type { InputModality } from "./types.ts";
|
|
6
6
|
import type { LanguageModel } from "ai";
|
|
7
|
-
import type {
|
|
7
|
+
import type { ExtensionAttribution, ExtensionAttributionContext } from "@plurnk/plurnk-meta";
|
|
8
8
|
import type RequestFields from "./RequestFields.ts";
|
|
9
9
|
import type InferenceAdmission from "./InferenceAdmission.ts";
|
|
10
10
|
export type ProviderFetch = typeof globalThis.fetch;
|
|
@@ -25,7 +25,7 @@ export type AiSdkProviderConfig = {
|
|
|
25
25
|
model: string;
|
|
26
26
|
url?: string;
|
|
27
27
|
languageModel?: LanguageModel;
|
|
28
|
-
attributions?: (context:
|
|
28
|
+
attributions?: (context: ExtensionAttributionContext) => ExtensionAttribution;
|
|
29
29
|
fetchTimeoutMs: number;
|
|
30
30
|
operationTimeoutMs: number;
|
|
31
31
|
droppedOutputTokens?: number;
|
|
@@ -54,6 +54,7 @@ export type AiSdkProviderConfig = {
|
|
|
54
54
|
systemCacheProviderOptions?: AiSdkProviderOptions;
|
|
55
55
|
reasoningResponseProviderOptions?: AiSdkProviderOptions;
|
|
56
56
|
serviceTier?: string;
|
|
57
|
+
requestControls?: NativeRequestControls;
|
|
57
58
|
streaming?: boolean;
|
|
58
59
|
apiKeyRejectedMessage?: string;
|
|
59
60
|
eosText?: string;
|
|
@@ -80,9 +81,14 @@ export type AiSdkProviderConfig = {
|
|
|
80
81
|
topLogprobs?: number | null;
|
|
81
82
|
rawBody?: boolean;
|
|
82
83
|
};
|
|
84
|
+
export interface NativeRequestControls {
|
|
85
|
+
readonly namespace: string;
|
|
86
|
+
readonly serviceTier: boolean;
|
|
87
|
+
readonly logprobs: boolean;
|
|
88
|
+
}
|
|
83
89
|
export default class AiSdkProvider implements Provider {
|
|
84
90
|
#private;
|
|
85
|
-
readonly attributions?: (context:
|
|
91
|
+
readonly attributions?: (context: ExtensionAttributionContext) => ExtensionAttribution;
|
|
86
92
|
tokenize?: (text: string) => Promise<number[]>;
|
|
87
93
|
constructor(config: AiSdkProviderConfig);
|
|
88
94
|
get contextWindow(): number | null;
|
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"AiSdkProvider.d.ts","sourceRoot":"","sources":["../src/AiSdkProvider.ts"],"names":[],"mappings":"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"}
|
package/dist/AiSdkProvider.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// PLURNK adapter over an AI SDK language model. Implements the universal generate()
|
|
2
2
|
// spine — signal merging, the SSE call, usage mapping, finishReason
|
|
3
|
-
// normalization, response assembly
|
|
3
|
+
// normalization, response assembly.
|
|
4
4
|
//
|
|
5
5
|
// Composition, not inheritance: an official AI SDK language model supplies the
|
|
6
|
-
// ordinary vendor protocol. The compatible URL path
|
|
6
|
+
// ordinary vendor protocol. The compatible URL path serves only PLURNK
|
|
7
7
|
// extensions and local endpoint probes the SDK cannot represent.
|
|
8
8
|
import { EFFORTS, MAX_TIMER_MS } from "@plurnk/plurnk-contracts";
|
|
9
9
|
import { UnsupportedEffortError } from "./types.js";
|
|
@@ -82,6 +82,26 @@ const providerWarningMessage = (warning) => {
|
|
|
82
82
|
case "other": return warning.message;
|
|
83
83
|
}
|
|
84
84
|
};
|
|
85
|
+
// {§provider-request-controls} — a native route forwards a configured control only through its
|
|
86
|
+
// SDK's documented provider option; a control the SDK does not document is named once and not
|
|
87
|
+
// sent, never dropped in silence (#988).
|
|
88
|
+
const nativeControlOptions = (source, controls, serviceTier, topLogprobs) => {
|
|
89
|
+
const options = {};
|
|
90
|
+
const unsupported = (knob) => emitWarningOnce(`${source}: ${knob} is not a provider option this route's SDK${controls === undefined ? "" : ` (${controls.namespace})`} documents, so it is not sent`, "PLURNK_REQUEST_CONTROL_UNSUPPORTED");
|
|
91
|
+
if (serviceTier !== undefined) {
|
|
92
|
+
if (controls?.serviceTier === true)
|
|
93
|
+
options.serviceTier = serviceTier;
|
|
94
|
+
else
|
|
95
|
+
unsupported("PLURNK_PROVIDERS_SERVICE_TIER");
|
|
96
|
+
}
|
|
97
|
+
if (topLogprobs !== null) {
|
|
98
|
+
if (controls?.logprobs === true)
|
|
99
|
+
options.logprobs = topLogprobs > 0 ? topLogprobs : true;
|
|
100
|
+
else
|
|
101
|
+
unsupported("PLURNK_PROVIDERS_TOP_LOGPROBS");
|
|
102
|
+
}
|
|
103
|
+
return controls === undefined || Object.keys(options).length === 0 ? undefined : { [controls.namespace]: options };
|
|
104
|
+
};
|
|
85
105
|
export default class AiSdkProvider {
|
|
86
106
|
#inferenceAdmission;
|
|
87
107
|
#model;
|
|
@@ -126,6 +146,7 @@ export default class AiSdkProvider {
|
|
|
126
146
|
#systemCacheProviderOptions;
|
|
127
147
|
#reasoningResponseProviderOptions;
|
|
128
148
|
#serviceTier;
|
|
149
|
+
#controlOptions;
|
|
129
150
|
#streaming;
|
|
130
151
|
#supportsSlotPinning;
|
|
131
152
|
#slotCount;
|
|
@@ -181,7 +202,7 @@ export default class AiSdkProvider {
|
|
|
181
202
|
if (!this.#supportedEfforts.includes(this.#effort.mode)) {
|
|
182
203
|
throw new UnsupportedEffortError(config.source ?? "provider", this.#effort.mode, this.#supportedEfforts);
|
|
183
204
|
}
|
|
184
|
-
// Loud guard: an out-of-date consumer (stale
|
|
205
|
+
// Loud guard: an out-of-date consumer (stale extension dist) omitting the
|
|
185
206
|
// required tuning fields must fail at construction, not silently send
|
|
186
207
|
// undefined sampling on every grammar request.
|
|
187
208
|
if (config.temperature === undefined || config.repeatPenalty === undefined) {
|
|
@@ -257,6 +278,12 @@ export default class AiSdkProvider {
|
|
|
257
278
|
this.#supportsSlotPinning = config.supportsSlotPinning ?? false;
|
|
258
279
|
this.#slotCount = config.slotCount ?? null;
|
|
259
280
|
this.#topLogprobs = config.topLogprobs ?? null;
|
|
281
|
+
if (this.#languageModel === undefined && config.requestControls !== undefined) {
|
|
282
|
+
throw new Error(`${this.#source}: native request controls require an AI SDK model`);
|
|
283
|
+
}
|
|
284
|
+
this.#controlOptions = this.#languageModel === undefined
|
|
285
|
+
? undefined
|
|
286
|
+
: nativeControlOptions(this.#source, config.requestControls, this.#serviceTier, this.#topLogprobs);
|
|
260
287
|
this.#rawBody = config.rawBody ?? false;
|
|
261
288
|
this.#servedModel = config.servedModel;
|
|
262
289
|
this.#requiresOutputBudget = config.requiresOutputBudget;
|
|
@@ -306,7 +333,7 @@ export default class AiSdkProvider {
|
|
|
306
333
|
return tokens;
|
|
307
334
|
};
|
|
308
335
|
}
|
|
309
|
-
this.#requestBody = new AiSdkRequestBody({ reasoningBudget: this.#reasoningBudget, additiveReasoningProvider: this.#additiveReasoningProvider, effort: this.#effort, adaptiveEffortProviderOptions: this.#adaptiveEffortProviderOptions, repeatPenalty: this.#repeatPenalty, dryMultiplier: this.#dryMultiplier, dryBase: this.#dryBase, dryAllowedLength: this.#dryAllowedLength, repeatLastN: this.#repeatLastN, reasoningStyle: this.#reasoningStyle, source: this.#source, grammarStyle: this.#grammarStyle, cacheAffinity: this.#cacheAffinity, reasoningResponseProviderOptions: this.#reasoningResponseProviderOptions, supportsSlotPinning: this.#supportsSlotPinning, slotCount: this.#slotCount });
|
|
336
|
+
this.#requestBody = new AiSdkRequestBody({ reasoningBudget: this.#reasoningBudget, additiveReasoningProvider: this.#additiveReasoningProvider, effort: this.#effort, adaptiveEffortProviderOptions: this.#adaptiveEffortProviderOptions, repeatPenalty: this.#repeatPenalty, dryMultiplier: this.#dryMultiplier, dryBase: this.#dryBase, dryAllowedLength: this.#dryAllowedLength, repeatLastN: this.#repeatLastN, reasoningStyle: this.#reasoningStyle, source: this.#source, grammarStyle: this.#grammarStyle, cacheAffinity: this.#cacheAffinity, reasoningResponseProviderOptions: this.#reasoningResponseProviderOptions, controlOptions: this.#controlOptions, supportsSlotPinning: this.#supportsSlotPinning, slotCount: this.#slotCount });
|
|
310
337
|
}
|
|
311
338
|
get contextWindow() { return this.#contextWindow; }
|
|
312
339
|
get inputModalities() { return this.#inputModalities; }
|
|
@@ -782,10 +809,9 @@ export default class AiSdkProvider {
|
|
|
782
809
|
if (sendGrammar !== undefined
|
|
783
810
|
&& this.tokenize !== undefined
|
|
784
811
|
&& usage?.outputTokens !== undefined) {
|
|
785
|
-
//
|
|
786
|
-
//
|
|
787
|
-
//
|
|
788
|
-
// requires the serving vocabulary; an estimate cannot prove absence.
|
|
812
|
+
// {§diagnostic-observation} — billed output tokens far beyond every visible channel are reported
|
|
813
|
+
// as the two counts, naming no cause. The count requires the serving vocabulary; an estimate
|
|
814
|
+
// cannot prove absence.
|
|
789
815
|
try {
|
|
790
816
|
const [contentTokens, reasoningTokens] = await Promise.all([
|
|
791
817
|
this.tokenize(raw.content),
|
|
@@ -795,9 +821,9 @@ export default class AiSdkProvider {
|
|
|
795
821
|
if (usage.outputTokens > visible + 64) {
|
|
796
822
|
(notices ??= []).push({
|
|
797
823
|
source: this.#source,
|
|
798
|
-
kind: "
|
|
824
|
+
kind: "output_unaccounted",
|
|
799
825
|
level: "warn",
|
|
800
|
-
message:
|
|
826
|
+
message: `${usage.outputTokens} output tokens billed; ${visible} visible across content and reasoning.`,
|
|
801
827
|
position: [...raw.content].length,
|
|
802
828
|
});
|
|
803
829
|
}
|