@plurnk/plurnk-providers 1.21.0 → 1.22.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 (144) hide show
  1. package/.env.defaults +110 -24
  2. package/README.md +19 -6
  3. package/SPEC.md +250 -97
  4. package/dist/AiSdkProvider.d.ts +19 -13
  5. package/dist/AiSdkProvider.d.ts.map +1 -1
  6. package/dist/AiSdkProvider.js +154 -73
  7. package/dist/AiSdkProvider.js.map +1 -1
  8. package/dist/AiSdkRequestBody.d.ts +7 -11
  9. package/dist/AiSdkRequestBody.d.ts.map +1 -1
  10. package/dist/AiSdkRequestBody.js +18 -90
  11. package/dist/AiSdkRequestBody.js.map +1 -1
  12. package/dist/InferenceAdmission.d.ts +7 -0
  13. package/dist/InferenceAdmission.d.ts.map +1 -0
  14. package/dist/InferenceAdmission.js +58 -0
  15. package/dist/InferenceAdmission.js.map +1 -0
  16. package/dist/Mock.d.ts +1 -1
  17. package/dist/Mock.d.ts.map +1 -1
  18. package/dist/Mock.js +2 -2
  19. package/dist/Mock.js.map +1 -1
  20. package/dist/Pool.d.ts +2 -2
  21. package/dist/Pool.d.ts.map +1 -1
  22. package/dist/Pool.js +2 -2
  23. package/dist/Pool.js.map +1 -1
  24. package/dist/RepeatedLine.d.ts +9 -0
  25. package/dist/RepeatedLine.d.ts.map +1 -0
  26. package/dist/RepeatedLine.js +27 -0
  27. package/dist/RepeatedLine.js.map +1 -0
  28. package/dist/RequestFields.d.ts +25 -0
  29. package/dist/RequestFields.d.ts.map +1 -0
  30. package/dist/RequestFields.js +240 -0
  31. package/dist/RequestFields.js.map +1 -0
  32. package/dist/accounting.d.ts.map +1 -1
  33. package/dist/accounting.js +38 -7
  34. package/dist/accounting.js.map +1 -1
  35. package/dist/aiSdkTransport.d.ts +8 -3
  36. package/dist/aiSdkTransport.d.ts.map +1 -1
  37. package/dist/aiSdkTransport.js +77 -24
  38. package/dist/aiSdkTransport.js.map +1 -1
  39. package/dist/catalogProvider.d.ts +4 -3
  40. package/dist/catalogProvider.d.ts.map +1 -1
  41. package/dist/catalogProvider.js +73 -170
  42. package/dist/catalogProvider.js.map +1 -1
  43. package/dist/compatibleProvider.d.ts.map +1 -1
  44. package/dist/compatibleProvider.js +11 -9
  45. package/dist/compatibleProvider.js.map +1 -1
  46. package/dist/discover.d.ts +0 -1
  47. package/dist/discover.d.ts.map +1 -1
  48. package/dist/discover.js +1 -10
  49. package/dist/discover.js.map +1 -1
  50. package/dist/env.d.ts +19 -8
  51. package/dist/env.d.ts.map +1 -1
  52. package/dist/env.js +125 -23
  53. package/dist/env.js.map +1 -1
  54. package/dist/errors.d.ts +1 -8
  55. package/dist/errors.d.ts.map +1 -1
  56. package/dist/errors.js +9 -13
  57. package/dist/errors.js.map +1 -1
  58. package/dist/index.d.ts +8 -7
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +6 -5
  61. package/dist/index.js.map +1 -1
  62. package/dist/model-options.d.ts +3 -0
  63. package/dist/model-options.d.ts.map +1 -0
  64. package/dist/model-options.js +26 -0
  65. package/dist/model-options.js.map +1 -0
  66. package/dist/ollama.d.ts.map +1 -1
  67. package/dist/ollama.js +1 -0
  68. package/dist/ollama.js.map +1 -1
  69. package/dist/provider-env.d.ts +3 -0
  70. package/dist/provider-env.d.ts.map +1 -0
  71. package/dist/provider-env.js +8 -0
  72. package/dist/provider-env.js.map +1 -0
  73. package/dist/providerError.d.ts +2 -2
  74. package/dist/providerError.d.ts.map +1 -1
  75. package/dist/providerError.js +19 -22
  76. package/dist/providerError.js.map +1 -1
  77. package/dist/reasoning-effort.d.ts +4 -3
  78. package/dist/reasoning-effort.d.ts.map +1 -1
  79. package/dist/reasoning-effort.js +18 -2
  80. package/dist/reasoning-effort.js.map +1 -1
  81. package/dist/sdkModels.d.ts +3 -2
  82. package/dist/sdkModels.d.ts.map +1 -1
  83. package/dist/sdkModels.js +39 -66
  84. package/dist/sdkModels.js.map +1 -1
  85. package/dist/types.d.ts +8 -8
  86. package/dist/types.d.ts.map +1 -1
  87. package/dist/types.js +5 -5
  88. package/dist/types.js.map +1 -1
  89. package/dist/usage.d.ts +5 -1
  90. package/dist/usage.d.ts.map +1 -1
  91. package/dist/usage.js +62 -17
  92. package/dist/usage.js.map +1 -1
  93. package/package.json +6 -7
  94. package/src/AiSdkProvider.test.ts +0 -2841
  95. package/src/AiSdkProvider.ts +0 -1064
  96. package/src/AiSdkRequestBody.ts +0 -364
  97. package/src/LeadingReasoning.test.ts +0 -34
  98. package/src/LeadingReasoning.ts +0 -87
  99. package/src/Mock.test.ts +0 -209
  100. package/src/Mock.ts +0 -197
  101. package/src/Pool.test.ts +0 -267
  102. package/src/Pool.ts +0 -261
  103. package/src/ProviderRegistry.test.ts +0 -483
  104. package/src/ProviderRegistry.ts +0 -128
  105. package/src/accounting.test.ts +0 -139
  106. package/src/accounting.ts +0 -172
  107. package/src/accountingPublic.ts +0 -9
  108. package/src/aiSdkTransport.test.ts +0 -476
  109. package/src/aiSdkTransport.ts +0 -776
  110. package/src/boundaries.test.ts +0 -73
  111. package/src/capacity.test.ts +0 -124
  112. package/src/capacity.ts +0 -174
  113. package/src/catalogProvider.test.ts +0 -900
  114. package/src/catalogProvider.ts +0 -476
  115. package/src/compatibleProvider.test.ts +0 -157
  116. package/src/compatibleProvider.ts +0 -217
  117. package/src/cost.test.ts +0 -114
  118. package/src/cost.ts +0 -140
  119. package/src/defaults.test.ts +0 -30
  120. package/src/defaults.ts +0 -9
  121. package/src/discover.test.ts +0 -200
  122. package/src/discover.ts +0 -136
  123. package/src/env.test.ts +0 -335
  124. package/src/env.ts +0 -380
  125. package/src/errors.test.ts +0 -278
  126. package/src/errors.ts +0 -234
  127. package/src/index.ts +0 -100
  128. package/src/inputModalities.test.ts +0 -54
  129. package/src/lexicon-guard.test.ts +0 -58
  130. package/src/notices.ts +0 -22
  131. package/src/ollama.test.ts +0 -66
  132. package/src/ollama.ts +0 -66
  133. package/src/openai.ts +0 -15
  134. package/src/promptTokens.ts +0 -45
  135. package/src/providerDefaults.test.ts +0 -51
  136. package/src/providerError.ts +0 -143
  137. package/src/reasoning-effort.ts +0 -15
  138. package/src/sdkModels.test.ts +0 -293
  139. package/src/sdkModels.ts +0 -460
  140. package/src/types.ts +0 -337
  141. package/src/usage.test.ts +0 -149
  142. package/src/usage.ts +0 -266
  143. package/src/warnings.test.ts +0 -31
  144. package/src/warnings.ts +0 -0
package/.env.defaults CHANGED
@@ -11,11 +11,15 @@
11
11
  # PLURNK_MODEL_local=openai/model-name-from-endpoint
12
12
  # PLURNK_BASEURL_local=http://127.0.0.1:8080/v1
13
13
  # PLURNK_MODEL=cloud
14
- # PLURNK_MODEL=google/gemini-3-flash
14
+ # PLURNK_MODEL=deepseek/deepseek-v4-flash
15
15
 
16
16
  # --- Capacity ---
17
- # Total output envelope INCLUDING reasoning: positive tokens or context percentage in (0,100).
18
- # Known model limits cap it. Must leave input capacity; the context budget is derived, not set here.
17
+ # Simultaneous inference attempts per resolved endpoint in this process; -1 = unrestricted.
18
+ # Positive limits queue excess calls. Aliases sharing an endpoint must agree on its limit.
19
+ PLURNK_PROVIDERS_MAX_CONCURRENCY=-1
20
+ # PLURNK_PROVIDERS_MAX_CONCURRENCY_local=1
21
+ # Reserved output INCLUDING reasoning: positive tokens or context percentage in (0,100).
22
+ # Known model limits cap it; input capacity is derived. Exact-counting calls may grant unused context.
19
23
  PLURNK_PROVIDERS_OUTPUT_BUDGET=35%
20
24
  # Optional reasoning subset of output, using the same units; must be smaller than total output.
21
25
  # Unset/empty = provider-adaptive budget, not reasoning off.
@@ -26,23 +30,44 @@ PLURNK_PROVIDERS_OUTPUT_BUDGET=35%
26
30
 
27
31
  # --- Reasoning ---
28
32
  # off | adaptive | low | medium | high | xhigh | max. Seed for durable Worker reasoning.
29
- # adaptive uses native dynamic reasoning where supported, otherwise the supported high posture.
30
- PLURNK_PROVIDERS_REASONING=adaptive
33
+ # adaptive prefers native dynamic reasoning, then the supported fallback below.
34
+ PLURNK_PROVIDERS_EFFORT=adaptive
35
+ # Fixed effort when native adaptation is unavailable; empty/unsupported = enabled provider default.
36
+ PLURNK_PROVIDERS_EFFORT_FALLBACK=high
31
37
  # Response interpretation: verbatim = trust structured reasoning fields; think-tags = extract one
32
38
  # leading <think> envelope. Select only for an endpoint that emits it; independent of activation.
33
39
  PLURNK_PROVIDERS_REASONING_RESPONSE_STYLE=verbatim
34
- # Reasoning wire for one route, over PLURNK_PROVIDERS_PROVIDER_<NAME>_REASONING_STYLE; usually
35
- # alias-scoped. thinking_config = Gemini through an OpenAI-compatible endpoint (readable thoughts,
36
- # levels low/medium/high, no off). Empty = the provider's declaration.
37
- # PLURNK_PROVIDERS_REASONING_STYLE=
38
- # PLURNK_PROVIDERS_REASONING_STYLE_<alias>=thinking_config
40
+ # Compatible wire declarations below supplement Models.dev; native SDKs own their protocols.
41
+ # Route knobs use the same suffix, e.g. PLURNK_PROVIDERS_REASONING_BUDGET_PATH_<alias>.
42
+ # PLURNK_PROVIDERS_OUTPUT_PATH_<alias>=/max_completion_tokens
43
+ # PLURNK_PROVIDERS_REASONING_EFFORT_PATH_<alias>=/reasoning_effort
44
+ # PLURNK_PROVIDERS_REASONING_CONTROLS_<alias>=exclusive
45
+ # PLURNK_PROVIDERS_REASONING_ON_BODY_<alias>='{"enable_thinking":true}'
46
+ # PLURNK_PROVIDERS_REASONING_OFF_BODY_<alias>='{"enable_thinking":false}'
47
+ # PLURNK_PROVIDERS_REASONING_EFFORTS_<alias>=low,medium,high
48
+ # PLURNK_PROVIDERS_REASONING_TRANSPORT_EFFORTS_<alias>=none,low,medium,high
49
+ # PLURNK_PROVIDERS_OPTIONS_NAMESPACE_<alias>=openrouter
50
+ # PLURNK_PROVIDERS_REASONING_ADAPTIVE_BODY_<alias>='{}'
51
+ # PLURNK_PROVIDERS_REASONING_TOGGLE_BODY_<alias>='{"reasoning":{"enabled":true}}'
52
+ # PLURNK_PROVIDERS_ADAPTIVE_OPTIONS_<alias>='[{"models":["*"],"options":{"<sdk-namespace>":{…}}}]'
53
+ # PLURNK_PROVIDERS_SYSTEM_CACHE_OPTIONS_<alias>=
54
+ # PLURNK_PROVIDERS_APP_URL_<alias>=https://example.test/app
55
+ # PLURNK_PROVIDERS_APP_NAME_<alias>=Example
39
56
 
40
57
  # --- Sampling ---
41
58
  # Temperature; empty = omit, retaining the provider's sampling default.
42
59
  PLURNK_PROVIDERS_TEMPERATURE=
60
+ # Nucleus probability mass, 0..1; empty = omit.
61
+ PLURNK_PROVIDERS_TOP_P=
62
+ # Token shortlist, non-negative integer; empty = omit. Support and zero semantics vary by endpoint.
63
+ PLURNK_PROVIDERS_TOP_K=
64
+ # Presence penalty, -2..2; empty = omit.
65
+ PLURNK_PROVIDERS_PRESENCE_PENALTY=
66
+ # Sampling seed, safe integer; empty = omit. Reproducibility depends on the endpoint.
67
+ PLURNK_PROVIDERS_SEED=
43
68
  # Repetition penalty; empty = omit. Values above 1 can penalize required verbatim repetition.
44
69
  PLURNK_PROVIDERS_REPEAT_PENALTY=
45
- # Frequency penalty; 0 = off. Support and effect depend on the endpoint.
70
+ # Frequency penalty, -2..2; 0 = no configured override. Support depends on the endpoint.
46
71
  PLURNK_PROVIDERS_FREQUENCY_PENALTY=0
47
72
  # Repeat-penalty window, tokens; unset = endpoint default.
48
73
  # PLURNK_PROVIDERS_REPEAT_LAST_N=512
@@ -56,7 +81,15 @@ PLURNK_PROVIDERS_DRY_MULTIPLIER=0
56
81
  # --- Cache and billing ---
57
82
  # Stable Worker affinity on supported routes: 1 = on; 0 = off. Unknown routes get no guessed field.
58
83
  PLURNK_PROVIDERS_CACHE_AFFINITY=1
59
- # Explicit cache writes: stable-system = reusable system boundary on supported Claude routes;
84
+ # FIELD declares placement, independent of the enable switch; null clears it for an alias.
85
+ # target is header or body with name, or provider-option with provider and name.
86
+ # PLURNK_PROVIDERS_CACHE_AFFINITY_FIELD_<alias>='{"target":"header","name":"x-session-id"}'
87
+ PLURNK_PROVIDERS_PROVIDER_OPENAI_CACHE_AFFINITY_FIELD='{"target":"provider-option","provider":"openai","name":"promptCacheKey"}'
88
+ PLURNK_PROVIDERS_PROVIDER_DEEPINFRA_CACHE_AFFINITY_FIELD='{"target":"provider-option","provider":"deepinfra","name":"prompt_cache_key"}'
89
+ PLURNK_PROVIDERS_PROVIDER_OPENROUTER_CACHE_AFFINITY_FIELD='{"target":"header","name":"x-session-id"}'
90
+ PLURNK_PROVIDERS_PROVIDER_CLOUDFLARE_WORKERS_AI_CACHE_AFFINITY_FIELD='{"target":"header","name":"x-session-affinity"}'
91
+ PLURNK_PROVIDERS_PROVIDER_FIREWORKS_AI_CACHE_AFFINITY_FIELD='{"target":"header","name":"x-session-affinity"}'
92
+ # Explicit cache writes: stable-system = reusable system boundary where SYSTEM_CACHE_OPTIONS declares it;
60
93
  # off = no explicit writes. This is distinct from affinity and can affect billing.
61
94
  PLURNK_PROVIDERS_CACHE_WRITE_POLICY=stable-system
62
95
  # Provider service tier; unset = provider default. Usually set per alias: routing can change cost.
@@ -67,14 +100,21 @@ PLURNK_PROVIDERS_CACHE_WRITE_POLICY=stable-system
67
100
  # PLURNK_PROVIDERS_COST=input=0.22,output=0.66,reasoning=0.66,cacheRead=0.007
68
101
 
69
102
  # --- Connectivity (milliseconds; each deadline accepts 0 = off) ---
70
- # Logical generation deadline, including physical attempts and retry delays.
103
+ # Logical generation deadline, including admission queues, physical attempts and retry delays.
71
104
  PLURNK_PROVIDERS_OPERATION_TIMEOUT=2700000
72
105
  # Deadline per physical generation attempt; a streamed attempt is bounded only until content flows.
73
106
  PLURNK_PROVIDERS_FETCH_TIMEOUT=600000
74
- # Wait from stream start to first semantic content; metadata/empty deltas do not count.
107
+ # Wait from dispatch (after admission, before response headers) to first semantic content;
108
+ # metadata/empty deltas do not count.
75
109
  PLURNK_PROVIDERS_FIRST_CONTENT_TIMEOUT=180000
76
110
  # Maximum silence between semantic content chunks after content begins.
77
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
+ # 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 and is re-issued (a tool-call finish always
116
+ # does). Reasoning billed but not streamed is exempt. 0 = off.
117
+ PLURNK_PROVIDERS_DROPPED_OUTPUT_TOKENS=32
78
118
  # Retries for 429, Retry-After, or X-Should-Retry:true; 0 = none. Other failures return immediately
79
119
  # to Core's separate recovery window. Retry-After takes precedence over backoff.
80
120
  PLURNK_PROVIDERS_RETRY_ATTEMPTS=3
@@ -104,14 +144,60 @@ PLURNK_PROVIDERS_PROBE_DELAY=250
104
144
  # PLURNK_PROVIDERS_PROVIDER_ACME_NPM=@ai-sdk/openai-compatible
105
145
  # PLURNK_PROVIDERS_PROVIDER_ACME_BASE_URL=https://api.acme.example/v1
106
146
  # PLURNK_PROVIDERS_PROVIDER_ACME_API_KEY_ENV=ACME_API_KEY
107
- # Reasoning wire adaptations that are not expressed by catalog metadata:
108
- # Fireworks requires an explicit off effort; Cloudflare graded models require an effort.
109
- PLURNK_PROVIDERS_PROVIDER_FIREWORKS_AI_REASONING_STYLE=effort_explicit
110
- PLURNK_PROVIDERS_PROVIDER_CLOUDFLARE_WORKERS_AI_REASONING_STYLE=effort_required
147
+ # Compatible request fields use RFC 6901 pointers; output defaults to the SDK's max_tokens.
148
+ # Effort vocabulary and budget bounds come from Models.dev; EFFORTS adds declared values.
149
+ # ON_BODY applies whenever reasoning is active. OFF_BODY disables it. ADAPTIVE_BODY replaces
150
+ # the graded fallback; {} leaves the enabled endpoint at its native default.
151
+ # TOGGLE_BODY enables a catalog toggle when no adaptive body or supported fallback applies.
152
+ # Bodies contain only reasoning controls, not model/messages, sampling, or token ceilings.
153
+ # With both paths declared, CONTROLS must say exclusive or combined. Fixed effort plus a numeric
154
+ # budget on an exclusive route fails before inference; adaptive + budget selects the numeric dial.
155
+ # PLURNK_PROVIDERS_PROVIDER_ACME_OUTPUT_PATH=/max_completion_tokens
156
+ # PLURNK_PROVIDERS_PROVIDER_ACME_REASONING_EFFORT_PATH=/reasoning/effort
157
+ # PLURNK_PROVIDERS_PROVIDER_ACME_REASONING_BUDGET_PATH=/reasoning/max_tokens
158
+ # PLURNK_PROVIDERS_PROVIDER_ACME_REASONING_CONTROLS=exclusive
159
+ # PLURNK_PROVIDERS_PROVIDER_ACME_REASONING_EFFORTS=low,medium,high
160
+ # PLURNK_PROVIDERS_PROVIDER_ACME_REASONING_ON_BODY='{"reasoning":{"enabled":true}}'
161
+ # PLURNK_PROVIDERS_PROVIDER_ACME_REASONING_OFF_BODY='{"reasoning":{"enabled":false}}'
162
+ # PLURNK_PROVIDERS_PROVIDER_ACME_REASONING_ADAPTIVE_BODY='{}'
163
+ PLURNK_PROVIDERS_PROVIDER_FIREWORKS_AI_REASONING_EFFORT_PATH=/reasoning_effort
164
+ PLURNK_PROVIDERS_PROVIDER_FIREWORKS_AI_REASONING_OFF_BODY='{"reasoning_effort":"none"}'
165
+ PLURNK_PROVIDERS_PROVIDER_FIREWORKS_AI_REASONING_TOGGLE_BODY='{"reasoning_effort":true}'
166
+ PLURNK_PROVIDERS_PROVIDER_CLOUDFLARE_WORKERS_AI_REASONING_EFFORT_PATH=/reasoning_effort
111
167
  # Additional supported Cloudflare effort values, comma-separated; empty = Models.dev only.
112
168
  PLURNK_PROVIDERS_PROVIDER_CLOUDFLARE_WORKERS_AI_REASONING_EFFORTS=
113
169
  # Direct DeepSeek thinking activation and effort.
114
- PLURNK_PROVIDERS_PROVIDER_DEEPSEEK_REASONING_STYLE=thinking_effort
170
+ PLURNK_PROVIDERS_PROVIDER_DEEPSEEK_REASONING_EFFORT_PATH=/reasoning_effort
171
+ PLURNK_PROVIDERS_PROVIDER_DEEPSEEK_REASONING_ON_BODY='{"thinking":{"type":"enabled"}}'
172
+ PLURNK_PROVIDERS_PROVIDER_DEEPSEEK_REASONING_OFF_BODY='{"thinking":{"type":"disabled"}}'
173
+ # OpenRouter's native SDK accepts these same fields in per-call provider options.
174
+ PLURNK_PROVIDERS_PROVIDER_OPENROUTER_OPTIONS_NAMESPACE=openrouter
175
+ PLURNK_PROVIDERS_PROVIDER_OPENROUTER_REASONING_EFFORT_PATH=/reasoning/effort
176
+ PLURNK_PROVIDERS_PROVIDER_OPENROUTER_REASONING_BUDGET_PATH=/reasoning/max_tokens
177
+ PLURNK_PROVIDERS_PROVIDER_OPENROUTER_REASONING_CONTROLS=exclusive
178
+ PLURNK_PROVIDERS_PROVIDER_OPENROUTER_REASONING_TRANSPORT_EFFORTS=none,minimal,low,medium,high,xhigh,max
179
+ PLURNK_PROVIDERS_PROVIDER_OPENROUTER_REASONING_ON_BODY='{"reasoning":{"enabled":true}}'
180
+ PLURNK_PROVIDERS_PROVIDER_OPENROUTER_REASONING_OFF_BODY='{"reasoning":{"effort":"none"}}'
181
+ # DeepInfra's and Together's native SDKs extend openai-compatible, which overwrites a raw `reasoning_effort`
182
+ # option; the effort rides the SDK's own `reasoningEffort`, so every catalog effort, max included, reaches the wire.
183
+ PLURNK_PROVIDERS_PROVIDER_DEEPINFRA_OPTIONS_NAMESPACE=deepinfra
184
+ PLURNK_PROVIDERS_PROVIDER_DEEPINFRA_REASONING_EFFORT_PATH=/reasoningEffort
185
+ PLURNK_PROVIDERS_PROVIDER_DEEPINFRA_REASONING_OFF_BODY='{"reasoningEffort":"none"}'
186
+ PLURNK_PROVIDERS_PROVIDER_TOGETHERAI_OPTIONS_NAMESPACE=togetherai
187
+ PLURNK_PROVIDERS_PROVIDER_TOGETHERAI_REASONING_EFFORT_PATH=/reasoningEffort
188
+ PLURNK_PROVIDERS_PROVIDER_TOGETHERAI_REASONING_OFF_BODY='{"reasoningEffort":"none"}'
189
+ # Model-family provider options: a JSON array of {"models":["<glob>",…],"options":{…}} rules matched
190
+ # against the route's model id, first match wins ({§provider-model-options}). ADAPTIVE_OPTIONS replaces the
191
+ # adaptive policy's projection; SYSTEM_CACHE_OPTIONS marks the stable system prompt for cache writes.
192
+ # None ship: the shipped defaults serve open models only; declare a closed family's options yourself.
193
+ # Alibaba DashScope (OpenAI-compatible): max_tokens is answer-only, max_completion_tokens is inclusive;
194
+ # effort and thinking budget are alternatives; enable_thinking switches reasoning.
195
+ PLURNK_PROVIDERS_PROVIDER_ALIBABA_OUTPUT_PATH=/max_completion_tokens
196
+ PLURNK_PROVIDERS_PROVIDER_ALIBABA_REASONING_EFFORT_PATH=/reasoning_effort
197
+ PLURNK_PROVIDERS_PROVIDER_ALIBABA_REASONING_BUDGET_PATH=/thinking_budget
198
+ PLURNK_PROVIDERS_PROVIDER_ALIBABA_REASONING_CONTROLS=exclusive
199
+ PLURNK_PROVIDERS_PROVIDER_ALIBABA_REASONING_ON_BODY='{"enable_thinking":true}'
200
+ PLURNK_PROVIDERS_PROVIDER_ALIBABA_REASONING_OFF_BODY='{"enable_thinking":false}'
115
201
  # Uncataloged compatible providers: SDK, endpoint, and credential-variable name.
116
202
  PLURNK_PROVIDERS_PROVIDER_BAICHUAN_NPM=@ai-sdk/openai-compatible
117
203
  PLURNK_PROVIDERS_PROVIDER_BAICHUAN_BASE_URL=https://api.baichuan-ai.com/v1
@@ -124,8 +210,8 @@ PLURNK_PROVIDERS_PROVIDER_QIANFAN_API_KEY_ENV=QIANFAN_API_KEY
124
210
  # OpenAI-compatible fallback endpoint; PLURNK_BASEURL_<alias> overrides it for one declared alias.
125
211
  OPENAI_BASE_URL=https://api.openai.com/v1
126
212
 
127
- # --- OpenRouter application attribution ---
128
- # Public application URL; empty suppresses attribution, including the title.
129
- OPENROUTER_HTTP_REFERER=https://github.com/plurnk/plurnk-service
130
- # Application display name, sent only with a nonempty URL.
131
- OPENROUTER_APP_TITLE=Plurnk
213
+ # --- Application attribution (routes on the OpenRouter SDK) ---
214
+ # Public application URL the SDK sends as HTTP-Referer; empty suppresses attribution, including the name.
215
+ PLURNK_PROVIDERS_PROVIDER_OPENROUTER_APP_URL=https://github.com/plurnk/plurnk-service
216
+ # Application display name the SDK sends as X-OpenRouter-Title, only with a nonempty URL.
217
+ PLURNK_PROVIDERS_PROVIDER_OPENROUTER_APP_NAME=Plurnk
package/README.md CHANGED
@@ -22,6 +22,8 @@ Model facts do not share one fallback chain. Context windows, output envelopes,
22
22
  reasoning activation, and estimated prices resolve independently
23
23
  ({§model-fact-resolution}). PLURNK does not fetch live per-token prices, and the
24
24
  local estimate is not an authoritative relay-settled charge.
25
+ Router accounting includes separately billed BYOK inference, not merely the
26
+ router fee; incomplete billing evidence remains unknown ({§provider-monetary-evidence}).
25
27
 
26
28
  ## Runtime-neutral contracts
27
29
 
@@ -45,16 +47,16 @@ discovery and environment-file defaults.
45
47
  Select a catalog route directly:
46
48
 
47
49
  ```dotenv
48
- PLURNK_MODEL=google/gemini-3-flash
49
- GEMINI_API_KEY=...
50
+ PLURNK_MODEL=deepseek/deepseek-v4-flash
51
+ DEEPSEEK_API_KEY=...
50
52
  ```
51
53
 
52
54
  Declare an alias when the route needs a reusable name or scoped tuning:
53
55
 
54
56
  ```dotenv
55
- PLURNK_MODEL_fast=openai/gpt-5-mini
57
+ PLURNK_MODEL_fast=deepinfra/zai-org/GLM-5.3-Flash
56
58
  PLURNK_MODEL=fast
57
- OPENAI_API_KEY=...
59
+ DEEPINFRA_API_KEY=...
58
60
  ```
59
61
 
60
62
  Cataloged providers need no endpoint declaration. To add an
@@ -88,6 +90,13 @@ changing a startup default is not a command to retarget existing Workers.
88
90
  Clients expose explicit model, reasoning, and child-model controls; their
89
91
  available effort choices come from the selected route.
90
92
 
93
+ Sampling uses endpoint defaults unless configured. `TEMPERATURE`, `TOP_P`,
94
+ `TOP_K`, `PRESENCE_PENALTY`, `FREQUENCY_PENALTY`, and `SEED` use the same
95
+ `PLURNK_PROVIDERS_<KNOB>_<alias>` form. Supported values depend on the endpoint;
96
+ Models.dev does not supply a recommended sampling profile. See the
97
+ [sampling contract](SPEC.md) ({§provider-sampling-passthrough}) and
98
+ [environment panel](.env.defaults) for ranges and omission rules.
99
+
91
100
  ## Capacity and reasoning
92
101
 
93
102
  ```mermaid
@@ -99,8 +108,9 @@ flowchart TD
99
108
  ```
100
109
 
101
110
  - **Effort** and **budget** are independent. `adaptive` requests native dynamic
102
- reasoning where supported, otherwise the supported high posture. Fixed effort
103
- names must be supported by the route; an unsupported request is not silently downgraded.
111
+ reasoning where supported, otherwise `PLURNK_PROVIDERS_EFFORT_FALLBACK`
112
+ (default `high`). An unavailable fallback retains the reasoning-enabled provider default.
113
+ Fixed effort names must be supported by the route; unsupported requests are not silently downgraded.
104
114
  - **Output** accepts positive tokens or a percentage of context; known model
105
115
  limits cap it. An explicit reasoning budget must be smaller than total output.
106
116
  Leaving the reasoning budget unset does not disable reasoning.
@@ -157,6 +167,8 @@ PLURNK_MODEL=local
157
167
  # Optional explicit generation allowances, in tokens:
158
168
  # PLURNK_PROVIDERS_OUTPUT_BUDGET_local=8192
159
169
  # PLURNK_PROVIDERS_REASONING_BUDGET_local=4096
170
+ # Optional: serialize inference on a single-slot endpoint without serializing workers:
171
+ # PLURNK_PROVIDERS_MAX_CONCURRENCY_local=1
160
172
  ```
161
173
 
162
174
  Endpoint probing supplies served-model capacity and llama-server capabilities.
@@ -175,6 +187,7 @@ opt-in for endpoints that emit a leading `<think>` envelope, not a reasoning swi
175
187
 
176
188
  | Concern | Boundary |
177
189
  | --- | --- |
190
+ | Inference concurrency | Optional per-endpoint, process-local admission; queued calls remain cancellable. The default is unrestricted ({§provider-inference-admission}). |
178
191
  | Attempt, first-content, idle deadlines | Provider transport; a timeout surfaces a failure, not a fabricated response. |
179
192
  | Provider-directed waits | Bounded retries honor `Retry-After`; other recoverable failures return to Core. |
180
193
  | Loop recovery | Core reissues within its recovery window, then parks for a prompt or wake. |