@oh-my-pi/pi-ai 15.10.7 → 15.10.9

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 (50) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/types/model-thinking.d.ts +4 -2
  3. package/dist/types/provider-models/google.d.ts +3 -0
  4. package/dist/types/provider-models/ollama.d.ts +2 -0
  5. package/dist/types/provider-models/openai-compat.d.ts +49 -1
  6. package/dist/types/providers/amazon-bedrock.d.ts +6 -5
  7. package/dist/types/providers/anthropic.d.ts +6 -5
  8. package/dist/types/providers/openai-completions.d.ts +1 -1
  9. package/dist/types/providers/openai-responses-shared.d.ts +1 -1
  10. package/dist/types/rate-limit-utils.d.ts +3 -2
  11. package/dist/types/registry/api-key-validation.d.ts +4 -0
  12. package/dist/types/registry/oauth/anthropic.d.ts +2 -1
  13. package/dist/types/registry/oauth/github-copilot.d.ts +16 -12
  14. package/dist/types/registry/oauth/types.d.ts +2 -0
  15. package/dist/types/registry/oauth/xai-oauth.d.ts +2 -1
  16. package/dist/types/registry/types.d.ts +2 -1
  17. package/dist/types/types.d.ts +32 -3
  18. package/dist/types/usage/google-antigravity.d.ts +26 -1
  19. package/dist/types/usage.d.ts +2 -2
  20. package/dist/types/utils/discovery/gemini.d.ts +2 -2
  21. package/dist/types/utils/discovery/openai-compatible.d.ts +2 -2
  22. package/package.json +2 -2
  23. package/src/auth-storage.ts +3 -1
  24. package/src/model-thinking.ts +41 -11
  25. package/src/models.json +597 -445
  26. package/src/provider-models/google.ts +18 -1
  27. package/src/provider-models/ollama.ts +6 -4
  28. package/src/provider-models/openai-compat.ts +121 -15
  29. package/src/providers/amazon-bedrock.ts +17 -14
  30. package/src/providers/anthropic.ts +40 -17
  31. package/src/providers/openai-codex-responses.ts +93 -7
  32. package/src/providers/openai-completions.ts +56 -10
  33. package/src/providers/openai-responses-shared.ts +5 -2
  34. package/src/rate-limit-utils.ts +13 -3
  35. package/src/registry/api-key-login.ts +3 -0
  36. package/src/registry/api-key-validation.ts +11 -3
  37. package/src/registry/kilo.ts +3 -2
  38. package/src/registry/oauth/__tests__/xai-oauth.test.ts +4 -7
  39. package/src/registry/oauth/anthropic.ts +36 -16
  40. package/src/registry/oauth/github-copilot.ts +62 -41
  41. package/src/registry/oauth/minimax-code.ts +2 -0
  42. package/src/registry/oauth/types.ts +2 -0
  43. package/src/registry/oauth/xai-oauth.ts +16 -8
  44. package/src/registry/oauth/xiaomi.ts +9 -4
  45. package/src/registry/types.ts +2 -2
  46. package/src/types.ts +33 -3
  47. package/src/usage/google-antigravity.ts +37 -0
  48. package/src/usage.ts +2 -2
  49. package/src/utils/discovery/gemini.ts +2 -2
  50. package/src/utils/discovery/openai-compatible.ts +2 -2
package/CHANGELOG.md CHANGED
@@ -2,6 +2,36 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [15.10.9] - 2026-06-09
6
+
7
+ ### Added
8
+
9
+ - Added `antigravityRankingStrategy` and registered it as the default `CredentialRankingStrategy` for `google-antigravity`, so multi-account selection consumes the per-counter Antigravity usage reports (sorted ascending by `remainingFraction` in `fetchAntigravityUsage`) before falling back to round-robin — preventing the exhausted-counter credential from being chosen first when an unblocked sibling has headroom ([#2187](https://github.com/can1357/oh-my-pi/issues/2187)).
10
+ - Added Claude Fable 5 to the first-party Anthropic catalog, seeded directly via `ANTHROPIC_CURATED_FALLBACK_MODELS` rather than waiting on models.dev (1M context / 128k output, adaptive thinking, $10/$50 per MTok). The model parser recognizes the `fable` kind so effort tiers (low→max), adaptive thinking, and Opus-4.7-style sampling restrictions apply; token limits and pricing are pinned in `applyAnthropicCatalogPolicy`.
11
+
12
+ ### Fixed
13
+
14
+ - Fixed `google-antigravity` not rotating to another stored OAuth account when Cloud Code Assist returns `429 You have exhausted your capacity on this model. Your quota will reset after …`. `parseRateLimitReason` matched the literal `capacity` before the `quota will reset` suffix and downgraded the failure to `MODEL_CAPACITY_EXHAUSTED` (45–75 s backoff), and `isUsageLimitError` returned false for the same message — so `markUsageLimitReached` was never invoked and the agent kept hammering the exhausted credential while the retry layer bailed on the multi-hour `retry-after`. Both paths now treat the Antigravity phrasing as `QUOTA_EXHAUSTED` / usage-limit, blocking the current credential until reset and letting the session pick an unblocked sibling ([#2187](https://github.com/can1357/oh-my-pi/issues/2187)).
15
+ - Fixed OpenRouter Anthropic chat-completions requests placing `cache_control` on empty assistant tool-call content. The cache marker now skips empty text and attaches to the most recent non-empty text part, avoiding HTTP 400 payloads with `{type:"text", text:"", cache_control:...}`.
16
+ - Fixed Fable-only Anthropic request shaping to cover Claude Mythos 5, and added Mythos 5 to the first-party Anthropic catalog seed. Adaptive display, sampling suppression, mid-conversation system messages, forced-tool-choice downgrade, and Bedrock adaptive metadata now handle both model families.
17
+ - Fixed adaptive-only Claude models (Opus 4.6+, Sonnet 4.6+, Fable/Mythos 5) returning HTTP 400 `"thinking.type.disabled" is not supported for this model` whenever thinking was turned off (utility calls and forced-tool turns route through the disable path). These models accept only `thinking.type: "adaptive"`; the request builder now omits the thinking field and pins the lowest adaptive effort instead of emitting `type: "disabled"`.
18
+ - Widened the OpenAI-completions first-event watchdog floor from 120s to 300s for DeepSeek V4 reasoning models hosted on the official DeepSeek API. The reasoner emits no SSE bytes until its private chain-of-thought finishes, which routinely takes longer than the generic 100s first-event budget under load — every chat then aborted with `OpenAI completions stream timed out while waiting for the first event` and silently retried. Mirrors the existing GLM coding-plan widening ([#2177](https://github.com/can1357/oh-my-pi/issues/2177)).
19
+
20
+ ## [15.10.8] - 2026-06-09
21
+
22
+ ### Added
23
+
24
+ - Added optional `fetch` transport override (`fetch?: FetchImpl`) to Google, Ollama, and OpenAI-compatible model-manager options so dynamic model discovery and metadata lookups can use a caller-supplied HTTP client instead of only global `fetch`
25
+ - Added optional `fetch` on OAuth controller and API-key validation/login flows so token exchange, refresh, and device/PKCE login requests can be routed through a custom `fetch` implementation
26
+ - Added optional `fetch` support to usage polling context, allowing usage providers to execute usage checks using an injected HTTP client
27
+ - Added `AssistantMessage.upstreamProvider`, capturing the upstream provider an aggregator routed the request to (OpenRouter reports it via a top-level `provider` field on every chunk, e.g. `"Anthropic"`). Surfaced from the OpenAI-completions stream alongside `responseId`.
28
+
29
+ ### Fixed
30
+
31
+ - Fixed a degenerate OpenAI Codex stream (the model emits whitespace-only `function_call_arguments.delta` frames forever — commonly seen right after a `todo` tool call) terminating the turn with an error instead of recovering. The whitespace-loop circuit-breaker now (a) stops aborting the shared per-request `AbortController` — `requestSignal` is an `AbortSignal.any` over it, so aborting latched it and made every reopen on the reused `requestSetup` impossible — and (b) drops the half-built junk tool call and replays the request from scratch, bounded by `CODEX_WHITESPACE_LOOP_RETRY_LIMIT` (2). Sampling nondeterminism usually clears the loop on a fresh attempt; once the budget is exhausted the error is surfaced as before, but without the junk tool call polluting the message.
32
+ - Capped requested output tokens at 64k (`OPENAI_MAX_OUTPUT_TOKENS`, mirroring Anthropic's `CLAUDE_CODE_MAX_OUTPUT_TOKENS`) on OpenAI-family wires with a known upstream output cap — the `openai-completions` request builder (non-OpenRouter) and the shared responses sampling helper (`openai-responses`, `azure-openai-responses`). A model's catalog `maxTokens` often tracks its context window rather than the upstream's per-request output cap, so requesting the full ceiling 400'd (e.g. `z-ai/glm-4.7` asking for 131072 output exceeded the upstream's 131072-token *total* context). Output is now `min(requested, model.maxTokens, 64000)`.
33
+ - Stopped sending `max_tokens`/`max_completion_tokens` on OpenRouter (`openrouter.ai`) completions requests. OpenRouter filters out any upstream whose advertised output cap is below the requested `max_tokens`, so a value derived from the catalog (which reflects the highest-cap provider) silently excluded lower-cap upstreams — `provider.order: ["cerebras"]` for `z-ai/glm-4.7` fell through to DeepInfra because Cerebras's ~40k output cap is below the request, while `only: ["cerebras"]` (no fallback target) bypassed the filter and worked. Omitting the field lets each upstream self-cap and keeps provider routing (`only`/`order`) honored. Kimi via OpenRouter stays exempt — it derives TPM rate limits from `max_tokens`.
34
+
5
35
  ## [15.10.7] - 2026-06-08
6
36
 
7
37
  ### Fixed
@@ -71,7 +71,7 @@ export declare function mapEffortToGoogleThinkingLevel<TApi extends Api>(model:
71
71
  /** Maps a normalized thinking effort to Anthropic adaptive effort values. */
72
72
  export declare function mapEffortToAnthropicAdaptiveEffort<TApi extends Api>(model: ApiModel<TApi>, effort: Effort): "low" | "medium" | "high" | "xhigh" | "max";
73
73
  /**
74
- * Returns true for Anthropic models with Opus 4.7 API restrictions:
74
+ * Returns true for Anthropic models with Opus 4.7+/Fable/Mythos API restrictions:
75
75
  * - Sampling parameters (temperature/top_p/top_k) return 400 error
76
76
  * - Thinking content is omitted by default (needs display: "summarized")
77
77
  */
@@ -79,7 +79,9 @@ export declare function hasOpus47ApiRestrictions(modelId: string): boolean;
79
79
  /**
80
80
  * Mid-conversation `role: "system"` messages (system instructions appended at
81
81
  * non-first positions in the `messages` array) are supported starting with
82
- * Claude Opus 4.8. Earlier Claude models reject the role.
82
+ * Claude Opus 4.8 and the Claude Fable/Mythos 5 generation. Earlier Claude
83
+ * models reject the role.
83
84
  * @see https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages
84
85
  */
85
86
  export declare function supportsMidConversationSystemMessages(modelId: string): boolean;
87
+ export declare function isAnthropicFableOrMythosModel(modelId: string): boolean;
@@ -2,6 +2,7 @@ import type { ModelManagerOptions } from "../model-manager";
2
2
  import type { FetchImpl } from "../types";
3
3
  export interface GoogleModelManagerConfig {
4
4
  apiKey?: string;
5
+ fetch?: FetchImpl;
5
6
  }
6
7
  export interface GoogleVertexModelManagerConfig {
7
8
  apiKey?: string;
@@ -13,10 +14,12 @@ export interface GoogleVertexModelManagerConfig {
13
14
  export interface GoogleAntigravityModelManagerConfig {
14
15
  oauthToken?: string;
15
16
  endpoint?: string;
17
+ fetch?: FetchImpl;
16
18
  }
17
19
  export interface GoogleGeminiCliModelManagerConfig {
18
20
  oauthToken?: string;
19
21
  endpoint?: string;
22
+ fetch?: FetchImpl;
20
23
  }
21
24
  export declare function googleModelManagerOptions(config?: GoogleModelManagerConfig): ModelManagerOptions<"google-generative-ai">;
22
25
  export declare function googleVertexModelManagerOptions(_config?: GoogleVertexModelManagerConfig): ModelManagerOptions;
@@ -1,7 +1,9 @@
1
1
  import type { ModelManagerOptions } from "../model-manager";
2
+ import type { FetchImpl } from "../types";
2
3
  export interface OllamaCloudModelManagerConfig {
3
4
  apiKey?: string;
4
5
  baseUrl?: string;
6
+ fetch?: FetchImpl;
5
7
  }
6
8
  export declare function normalizeOllamaCloudBaseUrl(baseUrl?: string): string;
7
9
  export declare function ollamaCloudModelManagerOptions(config?: OllamaCloudModelManagerConfig): ModelManagerOptions<"ollama-chat">;
@@ -1,6 +1,6 @@
1
1
  import type { ModelManagerOptions } from "../model-manager";
2
2
  import { getBundledModels } from "../models";
3
- import type { Api, Model, Provider } from "../types";
3
+ import type { Api, FetchImpl, Model, Provider } from "../types";
4
4
  export interface ModelsDevModel {
5
5
  id?: string;
6
6
  name?: string;
@@ -24,44 +24,63 @@ export interface ModelsDevModel {
24
24
  npm?: string;
25
25
  };
26
26
  }
27
+ /**
28
+ * Curated Anthropic models that are live or limited-availability on the
29
+ * first-party `/v1/models` endpoint but that models.dev has not catalogued yet.
30
+ * Seeded into model generation so the bundled catalog is never gated on
31
+ * models.dev's update cadence; deduped behind upstream catalog / models.dev
32
+ * entries once those appear. Token limits and pricing are pinned
33
+ * authoritatively in
34
+ * `applyAnthropicCatalogPolicy`, and `thinking` is derived by
35
+ * `refreshModelThinking` during generation.
36
+ */
37
+ export declare const ANTHROPIC_CURATED_FALLBACK_MODELS: readonly Model<"anthropic-messages">[];
27
38
  type SimpleProviderConfig = {
28
39
  apiKey?: string;
29
40
  baseUrl?: string;
41
+ fetch?: FetchImpl;
30
42
  };
31
43
  export declare function createSimpleOpenAICompletionsOptions(providerId: Parameters<typeof getBundledModels>[0], defaultBaseUrl: string, config?: SimpleProviderConfig): ModelManagerOptions<"openai-completions">;
32
44
  export interface OpenAIModelManagerConfig {
33
45
  apiKey?: string;
34
46
  baseUrl?: string;
47
+ fetch?: FetchImpl;
35
48
  }
36
49
  export declare function openaiModelManagerOptions(config?: OpenAIModelManagerConfig): ModelManagerOptions<"openai-responses">;
37
50
  export interface GroqModelManagerConfig {
38
51
  apiKey?: string;
39
52
  baseUrl?: string;
53
+ fetch?: FetchImpl;
40
54
  }
41
55
  export declare function groqModelManagerOptions(config?: GroqModelManagerConfig): ModelManagerOptions<"openai-completions">;
42
56
  export interface CerebrasModelManagerConfig {
43
57
  apiKey?: string;
44
58
  baseUrl?: string;
59
+ fetch?: FetchImpl;
45
60
  }
46
61
  export declare function cerebrasModelManagerOptions(config?: CerebrasModelManagerConfig): ModelManagerOptions<"openai-completions">;
47
62
  export interface HuggingfaceModelManagerConfig {
48
63
  apiKey?: string;
49
64
  baseUrl?: string;
65
+ fetch?: FetchImpl;
50
66
  }
51
67
  export declare function huggingfaceModelManagerOptions(config?: HuggingfaceModelManagerConfig): ModelManagerOptions<"openai-completions">;
52
68
  export interface NvidiaModelManagerConfig {
53
69
  apiKey?: string;
54
70
  baseUrl?: string;
71
+ fetch?: FetchImpl;
55
72
  }
56
73
  export declare function nvidiaModelManagerOptions(config?: NvidiaModelManagerConfig): ModelManagerOptions<"openai-completions">;
57
74
  export interface XaiModelManagerConfig {
58
75
  apiKey?: string;
59
76
  baseUrl?: string;
77
+ fetch?: FetchImpl;
60
78
  }
61
79
  export declare function xaiModelManagerOptions(config?: XaiModelManagerConfig): ModelManagerOptions<"openai-completions">;
62
80
  export interface XaiOAuthModelManagerConfig {
63
81
  apiKey?: string;
64
82
  baseUrl?: string;
83
+ fetch?: FetchImpl;
65
84
  }
66
85
  interface XAICuratedModel {
67
86
  id: string;
@@ -110,16 +129,19 @@ export declare function isLikelyAimlApiChatModelId(id: string): boolean;
110
129
  export interface AimlApiModelManagerConfig {
111
130
  apiKey?: string;
112
131
  baseUrl?: string;
132
+ fetch?: FetchImpl;
113
133
  }
114
134
  export declare function aimlApiModelManagerOptions(config?: AimlApiModelManagerConfig): ModelManagerOptions<"openai-completions">;
115
135
  export interface DeepSeekModelManagerConfig {
116
136
  apiKey?: string;
117
137
  baseUrl?: string;
138
+ fetch?: FetchImpl;
118
139
  }
119
140
  export declare function deepseekModelManagerOptions(config?: DeepSeekModelManagerConfig): ModelManagerOptions<"openai-completions">;
120
141
  export interface ZhipuCodingPlanModelManagerConfig {
121
142
  apiKey?: string;
122
143
  baseUrl?: string;
144
+ fetch?: FetchImpl;
123
145
  }
124
146
  export declare function zhipuCodingPlanModelManagerOptions(config?: ZhipuCodingPlanModelManagerConfig): ModelManagerOptions<"openai-completions">;
125
147
  /**
@@ -151,11 +173,13 @@ export declare function stripFireworksDeepSeekThinkingToggle(model: Model<"opena
151
173
  export interface FireworksModelManagerConfig {
152
174
  apiKey?: string;
153
175
  baseUrl?: string;
176
+ fetch?: FetchImpl;
154
177
  }
155
178
  export declare function fireworksModelManagerOptions(config?: FireworksModelManagerConfig): ModelManagerOptions<"openai-completions">;
156
179
  export interface FirepassModelManagerConfig {
157
180
  apiKey?: string;
158
181
  baseUrl?: string;
182
+ fetch?: FetchImpl;
159
183
  }
160
184
  /**
161
185
  * Fire Pass is a Fireworks subscription product that exposes a single router
@@ -168,93 +192,111 @@ export declare function firepassModelManagerOptions(_config?: FirepassModelManag
168
192
  export interface WaferModelManagerConfig {
169
193
  apiKey?: string;
170
194
  baseUrl?: string;
195
+ fetch?: FetchImpl;
171
196
  }
172
197
  export declare function waferPassModelManagerOptions(config?: WaferModelManagerConfig): ModelManagerOptions<"openai-completions">;
173
198
  export declare function waferServerlessModelManagerOptions(config?: WaferModelManagerConfig): ModelManagerOptions<"openai-completions">;
174
199
  export interface MistralModelManagerConfig {
175
200
  apiKey?: string;
176
201
  baseUrl?: string;
202
+ fetch?: FetchImpl;
177
203
  }
178
204
  export declare function mistralModelManagerOptions(config?: MistralModelManagerConfig): ModelManagerOptions<"openai-completions">;
179
205
  export interface OpenCodeModelManagerConfig {
180
206
  apiKey?: string;
181
207
  baseUrl?: string;
208
+ fetch?: FetchImpl;
182
209
  }
183
210
  export declare function opencodeZenModelManagerOptions(config?: OpenCodeModelManagerConfig): ModelManagerOptions<Api>;
184
211
  export declare function opencodeGoModelManagerOptions(config?: OpenCodeModelManagerConfig): ModelManagerOptions<Api>;
185
212
  export interface OllamaModelManagerConfig {
186
213
  apiKey?: string;
187
214
  baseUrl?: string;
215
+ fetch?: FetchImpl;
188
216
  }
189
217
  export declare function ollamaModelManagerOptions(config?: OllamaModelManagerConfig): ModelManagerOptions<"openai-responses">;
190
218
  export interface OpenRouterModelManagerConfig {
191
219
  apiKey?: string;
192
220
  baseUrl?: string;
221
+ fetch?: FetchImpl;
193
222
  }
194
223
  export declare function openrouterModelManagerOptions(config?: OpenRouterModelManagerConfig): ModelManagerOptions<"openai-completions">;
195
224
  export interface ZenMuxModelManagerConfig {
196
225
  apiKey?: string;
197
226
  baseUrl?: string;
227
+ fetch?: FetchImpl;
198
228
  }
199
229
  export declare function zenmuxModelManagerOptions(config?: ZenMuxModelManagerConfig): ModelManagerOptions<Api>;
200
230
  export interface KiloModelManagerConfig {
201
231
  apiKey?: string;
202
232
  baseUrl?: string;
233
+ fetch?: FetchImpl;
203
234
  }
204
235
  export declare function kiloModelManagerOptions(config?: KiloModelManagerConfig): ModelManagerOptions<"openai-completions">;
205
236
  export interface AlibabaCodingPlanModelManagerConfig {
206
237
  apiKey?: string;
207
238
  baseUrl?: string;
239
+ fetch?: FetchImpl;
208
240
  }
209
241
  export declare function alibabaCodingPlanModelManagerOptions(config?: AlibabaCodingPlanModelManagerConfig): ModelManagerOptions<"openai-completions">;
210
242
  export interface VercelAiGatewayModelManagerConfig {
211
243
  apiKey?: string;
212
244
  baseUrl?: string;
245
+ fetch?: FetchImpl;
213
246
  }
214
247
  export declare function vercelAiGatewayModelManagerOptions(config?: VercelAiGatewayModelManagerConfig): ModelManagerOptions<"anthropic-messages">;
215
248
  export interface KimiCodeModelManagerConfig {
216
249
  apiKey?: string;
217
250
  baseUrl?: string;
251
+ fetch?: FetchImpl;
218
252
  }
219
253
  export declare function kimiCodeModelManagerOptions(config?: KimiCodeModelManagerConfig): ModelManagerOptions<"openai-completions">;
220
254
  export interface LmStudioModelManagerConfig {
221
255
  apiKey?: string;
222
256
  baseUrl?: string;
257
+ fetch?: FetchImpl;
223
258
  }
224
259
  export declare function lmStudioModelManagerOptions(config?: LmStudioModelManagerConfig): ModelManagerOptions<"openai-completions">;
225
260
  export interface SyntheticModelManagerConfig {
226
261
  apiKey?: string;
227
262
  baseUrl?: string;
263
+ fetch?: FetchImpl;
228
264
  }
229
265
  export declare function syntheticModelManagerOptions(config?: SyntheticModelManagerConfig): ModelManagerOptions<"openai-completions">;
230
266
  export interface VeniceModelManagerConfig {
231
267
  apiKey?: string;
232
268
  baseUrl?: string;
269
+ fetch?: FetchImpl;
233
270
  }
234
271
  export declare function veniceModelManagerOptions(config?: VeniceModelManagerConfig): ModelManagerOptions<"openai-completions">;
235
272
  export interface TogetherModelManagerConfig {
236
273
  apiKey?: string;
237
274
  baseUrl?: string;
275
+ fetch?: FetchImpl;
238
276
  }
239
277
  export declare function togetherModelManagerOptions(config?: TogetherModelManagerConfig): ModelManagerOptions<"openai-completions">;
240
278
  export interface MoonshotModelManagerConfig {
241
279
  apiKey?: string;
242
280
  baseUrl?: string;
281
+ fetch?: FetchImpl;
243
282
  }
244
283
  export declare function moonshotModelManagerOptions(config?: MoonshotModelManagerConfig): ModelManagerOptions<"openai-completions">;
245
284
  export interface QwenPortalModelManagerConfig {
246
285
  apiKey?: string;
247
286
  baseUrl?: string;
287
+ fetch?: FetchImpl;
248
288
  }
249
289
  export declare function qwenPortalModelManagerOptions(config?: QwenPortalModelManagerConfig): ModelManagerOptions<"openai-completions">;
250
290
  export interface QianfanModelManagerConfig {
251
291
  apiKey?: string;
252
292
  baseUrl?: string;
293
+ fetch?: FetchImpl;
253
294
  }
254
295
  export declare function qianfanModelManagerOptions(config?: QianfanModelManagerConfig): ModelManagerOptions<"openai-completions">;
255
296
  export interface CloudflareAiGatewayModelManagerConfig {
256
297
  apiKey?: string;
257
298
  baseUrl?: string;
299
+ fetch?: FetchImpl;
258
300
  }
259
301
  export declare function cloudflareAiGatewayModelManagerOptions(config?: CloudflareAiGatewayModelManagerConfig): ModelManagerOptions<"anthropic-messages">;
260
302
  /** Region codes for Xiaomi Token Plan clusters exposed as separate login providers. */
@@ -263,6 +305,7 @@ export type XiaomiTokenPlanRegion = "sgp" | "ams" | "cn";
263
305
  export interface XiaomiModelManagerConfig {
264
306
  apiKey?: string;
265
307
  baseUrl?: string;
308
+ fetch?: FetchImpl;
266
309
  providerId?: Provider;
267
310
  tokenPlanRegion?: XiaomiTokenPlanRegion;
268
311
  }
@@ -271,26 +314,31 @@ export declare function xiaomiModelManagerOptions(config?: XiaomiModelManagerCon
271
314
  export interface LiteLLMModelManagerConfig {
272
315
  apiKey?: string;
273
316
  baseUrl?: string;
317
+ fetch?: FetchImpl;
274
318
  }
275
319
  export declare function litellmModelManagerOptions(config?: LiteLLMModelManagerConfig): ModelManagerOptions<"openai-completions">;
276
320
  export interface VllmModelManagerConfig {
277
321
  apiKey?: string;
278
322
  baseUrl?: string;
323
+ fetch?: FetchImpl;
279
324
  }
280
325
  export declare function vllmModelManagerOptions(config?: VllmModelManagerConfig): ModelManagerOptions<"openai-completions">;
281
326
  export interface NanoGptModelManagerConfig {
282
327
  apiKey?: string;
283
328
  baseUrl?: string;
329
+ fetch?: FetchImpl;
284
330
  }
285
331
  export declare function nanoGptModelManagerOptions(config?: NanoGptModelManagerConfig): ModelManagerOptions<"openai-completions">;
286
332
  export interface GithubCopilotModelManagerConfig {
287
333
  apiKey?: string;
288
334
  baseUrl?: string;
335
+ fetch?: FetchImpl;
289
336
  }
290
337
  export declare function githubCopilotModelManagerOptions(config?: GithubCopilotModelManagerConfig): ModelManagerOptions<Api>;
291
338
  export interface AnthropicModelManagerConfig {
292
339
  apiKey?: string;
293
340
  baseUrl?: string;
341
+ fetch?: FetchImpl;
294
342
  }
295
343
  export declare function anthropicModelManagerOptions(config?: AnthropicModelManagerConfig): ModelManagerOptions<"anthropic-messages">;
296
344
  export { UNK_CONTEXT_WINDOW, UNK_MAX_TOKENS } from "./discovery-constants";
@@ -27,11 +27,12 @@ export interface BedrockOptions extends StreamOptions {
27
27
  * - `"omitted"`: thinking content is suppressed; the encrypted signature still
28
28
  * travels back for multi-turn continuity.
29
29
  *
30
- * Starting with Claude Opus 4.7 the Anthropic API default is `"omitted"`, which
31
- * leaves callers waiting on a silent stream during long reasoning runs (issue
32
- * #1373). We default to `"summarized"` so adaptive-thinking models that accept
33
- * the field keep producing visible thinking deltas. Older adaptive-thinking
34
- * models (Opus 4.6, Sonnet 4.6+) reject the field, so we omit it for them.
30
+ * Starting with Claude Opus 4.7 and Claude Fable/Mythos 5 the Anthropic API
31
+ * default is `"omitted"`, which leaves callers waiting on a silent stream during
32
+ * long reasoning runs (issue #1373). We default to `"summarized"` so adaptive-
33
+ * thinking models that accept the field keep producing visible thinking deltas.
34
+ * Older adaptive-thinking models (Opus 4.6, Sonnet 4.6+) reject the field, so
35
+ * we omit it for them.
35
36
  */
36
37
  thinkingDisplay?: BedrockThinkingDisplay;
37
38
  }
@@ -56,17 +56,18 @@ export type AnthropicThinkingDisplay = "summarized" | "omitted";
56
56
  export interface AnthropicOptions extends StreamOptions {
57
57
  /**
58
58
  * Enable extended thinking.
59
- * For Opus 4.6+: uses adaptive thinking (Claude decides when/how much to think).
60
- * For older models: uses budget-based thinking with thinkingBudgetTokens.
59
+ * For adaptive-capable models (Opus 4.6+, Sonnet 4.6+, Fable/Mythos 5):
60
+ * uses adaptive thinking (Claude decides when/how much to think). For older
61
+ * models: uses budget-based thinking with thinkingBudgetTokens.
61
62
  */
62
63
  thinkingEnabled?: boolean;
63
64
  /**
64
65
  * Token budget for extended thinking (older models only).
65
- * Ignored for Opus 4.6+ which uses adaptive thinking.
66
+ * Ignored for adaptive-capable models.
66
67
  */
67
68
  thinkingBudgetTokens?: number;
68
69
  /**
69
- * Effort level for adaptive thinking (Opus 4.6+ only).
70
+ * Effort level for adaptive thinking.
70
71
  * Controls how much thinking Claude allocates:
71
72
  * - "max": Always thinks with no constraints
72
73
  * - "high": Always thinks, deep reasoning (default)
@@ -182,7 +183,7 @@ export declare function normalizeExtraBetas(betas?: string[] | string): string[]
182
183
  export declare function buildAnthropicClientOptions(args: AnthropicClientOptionsArgs): AnthropicClientOptionsResult;
183
184
  /**
184
185
  * A single Anthropic conversation turn, including the mid-conversation
185
- * `system` role (Opus 4.8+).
186
+ * `system` role (Opus 4.8+ and Fable/Mythos 5).
186
187
  */
187
188
  export type AnthropicMessageParam = MessageParam;
188
189
  export declare function convertAnthropicMessages(messages: Message[], model: Model<"anthropic-messages">, isOAuthToken: boolean, baseUrl?: string | undefined): AnthropicMessageParam[];
@@ -41,7 +41,7 @@ export interface OpenAICompletionsOptions extends StreamOptions {
41
41
  * Exported for unit testing.
42
42
  */
43
43
  export declare function applyOpenRouterRoutingVariant(modelId: string, variant: string | undefined): string;
44
- /** Returns the widened OpenAI stream watchdog floor for slow GLM coding-plan reasoning models. */
44
+ /** Returns the widened OpenAI stream watchdog floor for slow reasoning models hosted on OpenAI-compatible endpoints. */
45
45
  export declare function getOpenAICompletionsStreamIdleTimeoutFallbackMs(model: Model<"openai-completions">): number | undefined;
46
46
  export declare const streamOpenAICompletions: StreamFunction<"openai-completions">;
47
47
  export declare function parseChunkUsage(rawUsage: object, model: Model<"openai-completions">, premiumRequests: number | undefined): AssistantMessage["usage"];
@@ -85,7 +85,7 @@ type CommonSamplingOptions = Pick<StreamOptions, "temperature" | "topP" | "topK"
85
85
  * can let the upstream apply its own default instead of 400-ing on `maxTokens` values that
86
86
  * reflect the model's context window rather than the upstream output limit.
87
87
  */
88
- export declare function applyCommonResponsesSamplingParams<P extends CommonResponsesParams>(params: P, options: CommonSamplingOptions | undefined, model: Pick<Model, "provider" | "omitMaxOutputTokens">): void;
88
+ export declare function applyCommonResponsesSamplingParams<P extends CommonResponsesParams>(params: P, options: CommonSamplingOptions | undefined, model: Pick<Model, "provider" | "omitMaxOutputTokens" | "maxTokens">): void;
89
89
  type ReasoningOptions = {
90
90
  reasoning?: string;
91
91
  reasoningSummary?: "auto" | "detailed" | "concise" | null;
@@ -5,10 +5,11 @@
5
5
  export type RateLimitReason = "QUOTA_EXHAUSTED" | "RATE_LIMIT_EXCEEDED" | "MODEL_CAPACITY_EXHAUSTED" | "SERVER_ERROR" | "UNKNOWN";
6
6
  /**
7
7
  * Classify a rate-limit error message into a reason category.
8
- * Priority order: MODEL_CAPACITY > RATE_LIMIT > QUOTA > SERVER_ERROR > UNKNOWN.
8
+ * Priority order: QUOTA (Antigravity "quota will reset") > MODEL_CAPACITY > QUOTA (account) >
9
+ * RATE_LIMIT > QUOTA (generic) > SERVER_ERROR > UNKNOWN.
9
10
  *
10
11
  * "resource exhausted" maps to MODEL_CAPACITY (transient, short wait)
11
- * "quota exceeded" maps to QUOTA_EXHAUSTED (long wait, switch account)
12
+ * "quota exceeded" / "quota will reset" maps to QUOTA_EXHAUSTED (long wait, switch account)
12
13
  */
13
14
  export declare function parseRateLimitReason(errorMessage: string): RateLimitReason;
14
15
  /**
@@ -1,9 +1,11 @@
1
+ import type { FetchImpl } from "../types";
1
2
  type OpenAICompatibleValidationOptions = {
2
3
  provider: string;
3
4
  apiKey: string;
4
5
  baseUrl: string;
5
6
  model: string;
6
7
  signal?: AbortSignal;
8
+ fetch?: FetchImpl;
7
9
  };
8
10
  type AnthropicCompatibleValidationOptions = {
9
11
  provider: string;
@@ -11,12 +13,14 @@ type AnthropicCompatibleValidationOptions = {
11
13
  baseUrl: string;
12
14
  model: string;
13
15
  signal?: AbortSignal;
16
+ fetch?: FetchImpl;
14
17
  };
15
18
  type ModelListValidationOptions = {
16
19
  provider: string;
17
20
  apiKey: string;
18
21
  modelsUrl: string;
19
22
  signal?: AbortSignal;
23
+ fetch?: FetchImpl;
20
24
  };
21
25
  /**
22
26
  * Validate an API key against an OpenAI-compatible chat completions endpoint.
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Anthropic OAuth flow (Claude Pro/Max)
3
3
  */
4
+ import type { FetchImpl } from "../../types";
4
5
  import { OAuthCallbackFlow } from "./callback-server";
5
6
  import type { OAuthController, OAuthCredentials } from "./types";
6
7
  export declare class AnthropicOAuthFlow extends OAuthCallbackFlow {
@@ -19,4 +20,4 @@ export declare function loginAnthropic(ctrl: OAuthController): Promise<OAuthCred
19
20
  /**
20
21
  * Refresh Anthropic OAuth token
21
22
  */
22
- export declare function refreshAnthropicToken(refreshToken: string): Promise<OAuthCredentials>;
23
+ export declare function refreshAnthropicToken(refreshToken: string, fetchOverride?: FetchImpl): Promise<OAuthCredentials>;
@@ -1,8 +1,22 @@
1
+ import type { FetchImpl } from "../../types";
1
2
  import type { OAuthCredentials } from "./types";
2
3
  export declare const COPILOT_USER_AGENT: "opencode/1.3.15";
3
4
  export declare const OPENCODE_HEADERS: {
4
5
  readonly "User-Agent": "opencode/1.3.15";
5
6
  };
7
+ type GitHubCopilotLoginOptions = {
8
+ onAuth: (url: string, instructions?: string) => void;
9
+ onPrompt: (prompt: {
10
+ message: string;
11
+ placeholder?: string;
12
+ allowEmpty?: boolean;
13
+ }) => Promise<string>;
14
+ onProgress?: (message: string) => void;
15
+ signal?: AbortSignal;
16
+ pollIntervalFloorMs?: number;
17
+ pollIntervalScaleMs?: number;
18
+ fetch?: FetchImpl;
19
+ };
6
20
  export type ParsedGitHubCopilotApiKey = {
7
21
  accessToken: string;
8
22
  enterpriseUrl?: string;
@@ -24,15 +38,5 @@ export declare function refreshGitHubCopilotToken(refreshToken: string, enterpri
24
38
  * @param options.onProgress - Optional progress callback
25
39
  * @param options.signal - Optional AbortSignal for cancellation
26
40
  */
27
- export declare function loginGitHubCopilot(options: {
28
- onAuth: (url: string, instructions?: string) => void;
29
- onPrompt: (prompt: {
30
- message: string;
31
- placeholder?: string;
32
- allowEmpty?: boolean;
33
- }) => Promise<string>;
34
- onProgress?: (message: string) => void;
35
- signal?: AbortSignal;
36
- pollIntervalFloorMs?: number;
37
- pollIntervalScaleMs?: number;
38
- }): Promise<OAuthCredentials>;
41
+ export declare function loginGitHubCopilot(options: GitHubCopilotLoginOptions): Promise<OAuthCredentials>;
42
+ export {};
@@ -1,3 +1,4 @@
1
+ import type { FetchImpl } from "../../types";
1
2
  import type { OAuthProviderUnion } from "../registry";
2
3
  export type OAuthCredentials = {
3
4
  refresh: string;
@@ -30,6 +31,7 @@ export interface OAuthController {
30
31
  onManualCodeInput?(): Promise<string>;
31
32
  onPrompt?(prompt: OAuthPrompt): Promise<string>;
32
33
  signal?: AbortSignal;
34
+ fetch?: FetchImpl;
33
35
  }
34
36
  export interface OAuthLoginCallbacks extends OAuthController {
35
37
  onAuth: (info: OAuthAuthInfo) => void;
@@ -7,6 +7,7 @@
7
7
  * {@link validateXAIEndpoint}: any non-HTTPS or non-`x.ai`/`*.x.ai` host is
8
8
  * rejected on every call site, not just the first.
9
9
  */
10
+ import type { FetchImpl } from "../../types";
10
11
  import { OAuthCallbackFlow } from "./callback-server";
11
12
  import type { OAuthController, OAuthCredentials } from "./types";
12
13
  /**
@@ -57,4 +58,4 @@ export declare function loginXAIOAuth(ctrl: OAuthController): Promise<OAuthCrede
57
58
  * re-validates the cached `token_endpoint` on the refresh hot path so a
58
59
  * cached-but-poisoned endpoint cannot silently leak a refresh_token.
59
60
  */
60
- export declare function refreshXAIOAuthToken(refreshToken: string): Promise<OAuthCredentials>;
61
+ export declare function refreshXAIOAuthToken(refreshToken: string, fetchOverride?: FetchImpl): Promise<OAuthCredentials>;
@@ -9,12 +9,13 @@
9
9
  * line in `./registry.ts`.
10
10
  */
11
11
  import type { ModelManagerOptions } from "../model-manager";
12
- import type { Api } from "../types";
12
+ import type { Api, FetchImpl } from "../types";
13
13
  import type { OAuthCredentials, OAuthLoginCallbacks } from "./oauth/types";
14
14
  /** Config passed to a provider's runtime model-manager factory. */
15
15
  export type ModelManagerConfig = {
16
16
  apiKey?: string;
17
17
  baseUrl?: string;
18
+ fetch?: FetchImpl;
18
19
  };
19
20
  /**
20
21
  * API-key environment fallback: either a single env var name (e.g.
@@ -15,6 +15,18 @@ import type { OpenAIResponsesOptions } from "./providers/openai-responses";
15
15
  import type { KnownProviderId } from "./registry";
16
16
  import type { AssistantMessageEventStream } from "./utils/event-stream";
17
17
  export type { AssistantMessageEventStream } from "./utils/event-stream";
18
+ /**
19
+ * Ceiling on the output-token count omp requests from any OpenAI-family endpoint
20
+ * (openai-responses, azure/xai responses, and openai-completions). Mirrors
21
+ * Anthropic's {@link CLAUDE_CODE_MAX_OUTPUT_TOKENS}.
22
+ *
23
+ * Catalog `maxTokens` frequently reflects a model's context window rather than a
24
+ * given upstream's real per-request output cap. OpenRouter, for instance,
25
+ * advertises 131072 output tokens for `z-ai/glm-4.7`, but the Cerebras upstream
26
+ * only allows ~131072 tokens total — so requesting the full ceiling overflows
27
+ * with a 400. Requested output is clamped to this value (and to `model.maxTokens`).
28
+ */
29
+ export declare const OPENAI_MAX_OUTPUT_TOKENS = 64000;
18
30
  export type KnownApi = "openai-completions" | "openai-responses" | "openai-codex-responses" | "azure-openai-responses" | "anthropic-messages" | "bedrock-converse-stream" | "google-generative-ai" | "google-gemini-cli" | "google-vertex" | "ollama-chat" | "cursor-agent";
19
31
  export type Api = KnownApi | (string & {});
20
32
  export interface ApiOptionsMap {
@@ -449,6 +461,14 @@ export interface AssistantMessage {
449
461
  provider: Provider;
450
462
  model: string;
451
463
  responseId?: string;
464
+ /**
465
+ * Name of the upstream provider an aggregator routed this request to, as
466
+ * reported in the response (e.g. OpenRouter's top-level `provider` field:
467
+ * `"OpenAI"`, `"Anthropic"`, `"Together"`). Distinct from `provider`, which
468
+ * is the configured gateway we called (`"openrouter"`). Undefined for direct
469
+ * providers that expose no such field.
470
+ */
471
+ upstreamProvider?: string;
452
472
  usage: Usage;
453
473
  stopReason: StopReason;
454
474
  errorMessage?: string;
@@ -721,11 +741,20 @@ export interface AnthropicCompat {
721
741
  supportsLongCacheRetention?: boolean;
722
742
  /**
723
743
  * Whether mid-conversation `role: "system"` messages are accepted in the
724
- * `messages` array (Claude Opus 4.8+ on the first-party Claude API and
725
- * Claude Platform on AWS). When unset, auto-detected from the model id and
726
- * base URL. Not available on Bedrock, Vertex AI, or Microsoft Foundry.
744
+ * `messages` array (Claude Opus 4.8+ and Claude Fable/Mythos 5 on the
745
+ * first-party Claude API and Claude Platform on AWS). When unset,
746
+ * auto-detected from the model id and base URL. Not available on Bedrock,
747
+ * Vertex AI, or Microsoft Foundry.
727
748
  */
728
749
  supportsMidConversationSystem?: boolean;
750
+ /**
751
+ * Whether the model accepts a forced `tool_choice` (`{ type: "any" }` or
752
+ * `{ type: "tool", name }`). Claude Fable/Mythos 5 reject forced tool use
753
+ * outright ("tool_choice forces tool use is not compatible with this model");
754
+ * the request builder downgrades forced choices to `auto` when this is false.
755
+ * When unset, auto-detected from the model id. Default: true.
756
+ */
757
+ supportsForcedToolChoice?: boolean;
729
758
  }
730
759
  /**
731
760
  * OpenRouter provider routing preferences.