@mariozechner/pi-ai 0.49.3 → 0.50.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 (108) hide show
  1. package/README.md +32 -22
  2. package/dist/api-registry.d.ts +20 -0
  3. package/dist/api-registry.d.ts.map +1 -0
  4. package/dist/api-registry.js +44 -0
  5. package/dist/api-registry.js.map +1 -0
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +22 -67
  8. package/dist/cli.js.map +1 -1
  9. package/dist/env-api-keys.d.ts +9 -0
  10. package/dist/env-api-keys.d.ts.map +1 -0
  11. package/dist/env-api-keys.js +91 -0
  12. package/dist/env-api-keys.js.map +1 -0
  13. package/dist/index.d.ts +4 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +4 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/models.generated.d.ts +599 -70
  18. package/dist/models.generated.d.ts.map +1 -1
  19. package/dist/models.generated.js +619 -90
  20. package/dist/models.generated.js.map +1 -1
  21. package/dist/providers/amazon-bedrock.d.ts +3 -2
  22. package/dist/providers/amazon-bedrock.d.ts.map +1 -1
  23. package/dist/providers/amazon-bedrock.js +52 -5
  24. package/dist/providers/amazon-bedrock.js.map +1 -1
  25. package/dist/providers/anthropic.d.ts +3 -2
  26. package/dist/providers/anthropic.d.ts.map +1 -1
  27. package/dist/providers/anthropic.js +20 -2
  28. package/dist/providers/anthropic.js.map +1 -1
  29. package/dist/providers/azure-openai-responses.d.ts +15 -0
  30. package/dist/providers/azure-openai-responses.d.ts.map +1 -0
  31. package/dist/providers/azure-openai-responses.js +184 -0
  32. package/dist/providers/azure-openai-responses.js.map +1 -0
  33. package/dist/providers/google-gemini-cli.d.ts +3 -2
  34. package/dist/providers/google-gemini-cli.d.ts.map +1 -1
  35. package/dist/providers/google-gemini-cli.js +68 -1
  36. package/dist/providers/google-gemini-cli.js.map +1 -1
  37. package/dist/providers/google-vertex.d.ts +3 -2
  38. package/dist/providers/google-vertex.d.ts.map +1 -1
  39. package/dist/providers/google-vertex.js +81 -1
  40. package/dist/providers/google-vertex.js.map +1 -1
  41. package/dist/providers/google.d.ts +3 -2
  42. package/dist/providers/google.d.ts.map +1 -1
  43. package/dist/providers/google.js +84 -3
  44. package/dist/providers/google.js.map +1 -1
  45. package/dist/providers/openai-codex-responses.d.ts +3 -2
  46. package/dist/providers/openai-codex-responses.d.ts.map +1 -1
  47. package/dist/providers/openai-codex-responses.js +57 -307
  48. package/dist/providers/openai-codex-responses.js.map +1 -1
  49. package/dist/providers/openai-completions.d.ts +5 -2
  50. package/dist/providers/openai-completions.d.ts.map +1 -1
  51. package/dist/providers/openai-completions.js +78 -41
  52. package/dist/providers/openai-completions.js.map +1 -1
  53. package/dist/providers/openai-responses-shared.d.ts +17 -0
  54. package/dist/providers/openai-responses-shared.d.ts.map +1 -0
  55. package/dist/providers/openai-responses-shared.js +424 -0
  56. package/dist/providers/openai-responses-shared.js.map +1 -0
  57. package/dist/providers/openai-responses.d.ts +3 -2
  58. package/dist/providers/openai-responses.d.ts.map +1 -1
  59. package/dist/providers/openai-responses.js +25 -415
  60. package/dist/providers/openai-responses.js.map +1 -1
  61. package/dist/providers/register-builtins.d.ts +3 -0
  62. package/dist/providers/register-builtins.d.ts.map +1 -0
  63. package/dist/providers/register-builtins.js +63 -0
  64. package/dist/providers/register-builtins.js.map +1 -0
  65. package/dist/providers/simple-options.d.ts +8 -0
  66. package/dist/providers/simple-options.d.ts.map +1 -0
  67. package/dist/providers/simple-options.js +32 -0
  68. package/dist/providers/simple-options.js.map +1 -0
  69. package/dist/stream.d.ts +5 -10
  70. package/dist/stream.d.ts.map +1 -1
  71. package/dist/stream.js +17 -420
  72. package/dist/stream.js.map +1 -1
  73. package/dist/types.d.ts +18 -22
  74. package/dist/types.d.ts.map +1 -1
  75. package/dist/types.js +0 -1
  76. package/dist/types.js.map +1 -1
  77. package/dist/utils/event-stream.d.ts +2 -0
  78. package/dist/utils/event-stream.d.ts.map +1 -1
  79. package/dist/utils/event-stream.js +4 -0
  80. package/dist/utils/event-stream.js.map +1 -1
  81. package/dist/utils/oauth/anthropic.d.ts +2 -1
  82. package/dist/utils/oauth/anthropic.d.ts.map +1 -1
  83. package/dist/utils/oauth/anthropic.js +13 -0
  84. package/dist/utils/oauth/anthropic.js.map +1 -1
  85. package/dist/utils/oauth/github-copilot.d.ts +2 -1
  86. package/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  87. package/dist/utils/oauth/github-copilot.js +25 -0
  88. package/dist/utils/oauth/github-copilot.js.map +1 -1
  89. package/dist/utils/oauth/google-antigravity.d.ts +2 -1
  90. package/dist/utils/oauth/google-antigravity.d.ts.map +1 -1
  91. package/dist/utils/oauth/google-antigravity.js +19 -0
  92. package/dist/utils/oauth/google-antigravity.js.map +1 -1
  93. package/dist/utils/oauth/google-gemini-cli.d.ts +2 -1
  94. package/dist/utils/oauth/google-gemini-cli.d.ts.map +1 -1
  95. package/dist/utils/oauth/google-gemini-cli.js +19 -0
  96. package/dist/utils/oauth/google-gemini-cli.js.map +1 -1
  97. package/dist/utils/oauth/index.d.ts +26 -16
  98. package/dist/utils/oauth/index.d.ts.map +1 -1
  99. package/dist/utils/oauth/index.js +65 -84
  100. package/dist/utils/oauth/index.js.map +1 -1
  101. package/dist/utils/oauth/openai-codex.d.ts +2 -1
  102. package/dist/utils/oauth/openai-codex.d.ts.map +1 -1
  103. package/dist/utils/oauth/openai-codex.js +20 -1
  104. package/dist/utils/oauth/openai-codex.js.map +1 -1
  105. package/dist/utils/oauth/types.d.ts +28 -6
  106. package/dist/utils/oauth/types.d.ts.map +1 -1
  107. package/dist/utils/oauth/types.js.map +1 -1
  108. package/package.json +3 -1
package/dist/stream.js CHANGED
@@ -1,438 +1,35 @@
1
- // NEVER convert to top-level imports - breaks browser/Vite builds (web-ui)
2
- let _existsSync = null;
3
- let _homedir = null;
4
- let _join = null;
5
- // Eagerly load in Node.js environment only
1
+ import "./providers/register-builtins.js";
2
+ import { getApiProvider } from "./api-registry.js";
3
+ export { getEnvApiKey } from "./env-api-keys.js";
4
+ // Set up http proxy according to env variables for `fetch` based SDKs in Node.js.
5
+ // Bun has builtin support for this.
6
6
  if (typeof process !== "undefined" && process.versions?.node) {
7
- import("node:fs").then((m) => {
8
- _existsSync = m.existsSync;
7
+ import("undici").then((m) => {
8
+ const { EnvHttpProxyAgent, setGlobalDispatcher } = m;
9
+ setGlobalDispatcher(new EnvHttpProxyAgent());
9
10
  });
10
- import("node:os").then((m) => {
11
- _homedir = m.homedir;
12
- });
13
- import("node:path").then((m) => {
14
- _join = m.join;
15
- });
16
- }
17
- import { supportsXhigh } from "./models.js";
18
- import { streamBedrock } from "./providers/amazon-bedrock.js";
19
- import { streamAnthropic } from "./providers/anthropic.js";
20
- import { streamGoogle } from "./providers/google.js";
21
- import { streamGoogleGeminiCli, } from "./providers/google-gemini-cli.js";
22
- import { streamGoogleVertex } from "./providers/google-vertex.js";
23
- import { streamOpenAICodexResponses } from "./providers/openai-codex-responses.js";
24
- import { streamOpenAICompletions } from "./providers/openai-completions.js";
25
- import { streamOpenAIResponses } from "./providers/openai-responses.js";
26
- let cachedVertexAdcCredentialsExists = null;
27
- function hasVertexAdcCredentials() {
28
- if (cachedVertexAdcCredentialsExists === null) {
29
- // In browser or if node modules not loaded yet, return false
30
- if (!_existsSync || !_homedir || !_join) {
31
- cachedVertexAdcCredentialsExists = false;
32
- return false;
33
- }
34
- // Check GOOGLE_APPLICATION_CREDENTIALS env var first (standard way)
35
- const gacPath = process.env.GOOGLE_APPLICATION_CREDENTIALS;
36
- if (gacPath) {
37
- cachedVertexAdcCredentialsExists = _existsSync(gacPath);
38
- }
39
- else {
40
- // Fall back to default ADC path (lazy evaluation)
41
- cachedVertexAdcCredentialsExists = _existsSync(_join(_homedir(), ".config", "gcloud", "application_default_credentials.json"));
42
- }
43
- }
44
- return cachedVertexAdcCredentialsExists;
45
11
  }
46
- export function getEnvApiKey(provider) {
47
- // Fall back to environment variables
48
- if (provider === "github-copilot") {
49
- return process.env.COPILOT_GITHUB_TOKEN || process.env.GH_TOKEN || process.env.GITHUB_TOKEN;
50
- }
51
- // ANTHROPIC_OAUTH_TOKEN takes precedence over ANTHROPIC_API_KEY
52
- if (provider === "anthropic") {
53
- return process.env.ANTHROPIC_OAUTH_TOKEN || process.env.ANTHROPIC_API_KEY;
54
- }
55
- // Vertex AI uses Application Default Credentials, not API keys.
56
- // Auth is configured via `gcloud auth application-default login`.
57
- if (provider === "google-vertex") {
58
- const hasCredentials = hasVertexAdcCredentials();
59
- const hasProject = !!(process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT);
60
- const hasLocation = !!process.env.GOOGLE_CLOUD_LOCATION;
61
- if (hasCredentials && hasProject && hasLocation) {
62
- return "<authenticated>";
63
- }
64
- }
65
- if (provider === "amazon-bedrock") {
66
- // Amazon Bedrock supports multiple credential sources:
67
- // 1. AWS_PROFILE - named profile from ~/.aws/credentials
68
- // 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - standard IAM keys
69
- // 3. AWS_BEARER_TOKEN_BEDROCK - Bedrock API keys (bearer token)
70
- // 4. AWS_CONTAINER_CREDENTIALS_RELATIVE_URI - ECS task roles
71
- // 5. AWS_CONTAINER_CREDENTIALS_FULL_URI - ECS task roles (full URI)
72
- // 6. AWS_WEB_IDENTITY_TOKEN_FILE - IRSA (IAM Roles for Service Accounts)
73
- if (process.env.AWS_PROFILE ||
74
- (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||
75
- process.env.AWS_BEARER_TOKEN_BEDROCK ||
76
- process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ||
77
- process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI ||
78
- process.env.AWS_WEB_IDENTITY_TOKEN_FILE) {
79
- return "<authenticated>";
80
- }
12
+ function resolveApiProvider(api) {
13
+ const provider = getApiProvider(api);
14
+ if (!provider) {
15
+ throw new Error(`No API provider registered for api: ${api}`);
81
16
  }
82
- const envMap = {
83
- openai: "OPENAI_API_KEY",
84
- google: "GEMINI_API_KEY",
85
- groq: "GROQ_API_KEY",
86
- cerebras: "CEREBRAS_API_KEY",
87
- xai: "XAI_API_KEY",
88
- openrouter: "OPENROUTER_API_KEY",
89
- "vercel-ai-gateway": "AI_GATEWAY_API_KEY",
90
- zai: "ZAI_API_KEY",
91
- mistral: "MISTRAL_API_KEY",
92
- minimax: "MINIMAX_API_KEY",
93
- "minimax-cn": "MINIMAX_CN_API_KEY",
94
- opencode: "OPENCODE_API_KEY",
95
- };
96
- const envVar = envMap[provider];
97
- return envVar ? process.env[envVar] : undefined;
17
+ return provider;
98
18
  }
99
19
  export function stream(model, context, options) {
100
- // Vertex AI uses Application Default Credentials, not API keys
101
- if (model.api === "google-vertex") {
102
- return streamGoogleVertex(model, context, options);
103
- }
104
- else if (model.api === "bedrock-converse-stream") {
105
- // Bedrock doesn't have any API keys instead it sources credentials from standard AWS env variables or from given AWS profile.
106
- return streamBedrock(model, context, (options || {}));
107
- }
108
- const apiKey = options?.apiKey || getEnvApiKey(model.provider);
109
- if (!apiKey) {
110
- throw new Error(`No API key for provider: ${model.provider}`);
111
- }
112
- const providerOptions = { ...options, apiKey };
113
- const api = model.api;
114
- switch (api) {
115
- case "anthropic-messages":
116
- return streamAnthropic(model, context, providerOptions);
117
- case "openai-completions":
118
- return streamOpenAICompletions(model, context, providerOptions);
119
- case "openai-responses":
120
- return streamOpenAIResponses(model, context, providerOptions);
121
- case "openai-codex-responses":
122
- return streamOpenAICodexResponses(model, context, providerOptions);
123
- case "google-generative-ai":
124
- return streamGoogle(model, context, providerOptions);
125
- case "google-gemini-cli":
126
- return streamGoogleGeminiCli(model, context, providerOptions);
127
- default: {
128
- // This should never be reached if all Api cases are handled
129
- const _exhaustive = api;
130
- throw new Error(`Unhandled API: ${_exhaustive}`);
131
- }
132
- }
20
+ const provider = resolveApiProvider(model.api);
21
+ return provider.stream(model, context, options);
133
22
  }
134
23
  export async function complete(model, context, options) {
135
24
  const s = stream(model, context, options);
136
25
  return s.result();
137
26
  }
138
27
  export function streamSimple(model, context, options) {
139
- // Vertex AI uses Application Default Credentials, not API keys
140
- if (model.api === "google-vertex") {
141
- const providerOptions = mapOptionsForApi(model, options, undefined);
142
- return stream(model, context, providerOptions);
143
- }
144
- else if (model.api === "bedrock-converse-stream") {
145
- // Bedrock doesn't have any API keys instead it sources credentials from standard AWS env variables or from given AWS profile.
146
- const providerOptions = mapOptionsForApi(model, options, undefined);
147
- return stream(model, context, providerOptions);
148
- }
149
- const apiKey = options?.apiKey || getEnvApiKey(model.provider);
150
- if (!apiKey) {
151
- throw new Error(`No API key for provider: ${model.provider}`);
152
- }
153
- const providerOptions = mapOptionsForApi(model, options, apiKey);
154
- return stream(model, context, providerOptions);
28
+ const provider = resolveApiProvider(model.api);
29
+ return provider.streamSimple(model, context, options);
155
30
  }
156
31
  export async function completeSimple(model, context, options) {
157
32
  const s = streamSimple(model, context, options);
158
33
  return s.result();
159
34
  }
160
- function mapOptionsForApi(model, options, apiKey) {
161
- const base = {
162
- temperature: options?.temperature,
163
- maxTokens: options?.maxTokens || Math.min(model.maxTokens, 32000),
164
- signal: options?.signal,
165
- apiKey: apiKey || options?.apiKey,
166
- sessionId: options?.sessionId,
167
- headers: options?.headers,
168
- onPayload: options?.onPayload,
169
- };
170
- // Helper to clamp xhigh to high for providers that don't support it
171
- const clampReasoning = (effort) => (effort === "xhigh" ? "high" : effort);
172
- /**
173
- * Adjust maxTokens to account for thinking budget.
174
- * APIs like Anthropic and Bedrock require max_tokens > thinking.budget_tokens.
175
- * Returns { adjustedMaxTokens, adjustedThinkingBudget }
176
- */
177
- const adjustMaxTokensForThinking = (baseMaxTokens, modelMaxTokens, reasoningLevel, customBudgets) => {
178
- const defaultBudgets = {
179
- minimal: 1024,
180
- low: 2048,
181
- medium: 8192,
182
- high: 16384,
183
- };
184
- const budgets = { ...defaultBudgets, ...customBudgets };
185
- const minOutputTokens = 1024;
186
- const level = clampReasoning(reasoningLevel);
187
- let thinkingBudget = budgets[level];
188
- // Caller's maxTokens is the desired output; add thinking budget on top, capped at model limit
189
- const maxTokens = Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);
190
- // If not enough room for thinking + output, reduce thinking budget
191
- if (maxTokens <= thinkingBudget) {
192
- thinkingBudget = Math.max(0, maxTokens - minOutputTokens);
193
- }
194
- return { maxTokens, thinkingBudget };
195
- };
196
- switch (model.api) {
197
- case "anthropic-messages": {
198
- // Explicitly disable thinking when reasoning is not specified
199
- if (!options?.reasoning) {
200
- return { ...base, thinkingEnabled: false };
201
- }
202
- // Claude requires max_tokens > thinking.budget_tokens
203
- // So we need to ensure maxTokens accounts for both thinking and output
204
- const adjusted = adjustMaxTokensForThinking(base.maxTokens || 0, model.maxTokens, options.reasoning, options?.thinkingBudgets);
205
- return {
206
- ...base,
207
- maxTokens: adjusted.maxTokens,
208
- thinkingEnabled: true,
209
- thinkingBudgetTokens: adjusted.thinkingBudget,
210
- };
211
- }
212
- case "bedrock-converse-stream": {
213
- // Explicitly disable thinking when reasoning is not specified
214
- if (!options?.reasoning) {
215
- return { ...base, reasoning: undefined };
216
- }
217
- // Claude requires max_tokens > thinking.budget_tokens (same as Anthropic direct API)
218
- // So we need to ensure maxTokens accounts for both thinking and output
219
- if (model.id.includes("anthropic.claude") || model.id.includes("anthropic/claude")) {
220
- const adjusted = adjustMaxTokensForThinking(base.maxTokens || 0, model.maxTokens, options.reasoning, options?.thinkingBudgets);
221
- return {
222
- ...base,
223
- maxTokens: adjusted.maxTokens,
224
- reasoning: options.reasoning,
225
- thinkingBudgets: {
226
- ...(options?.thinkingBudgets || {}),
227
- [clampReasoning(options.reasoning)]: adjusted.thinkingBudget,
228
- },
229
- };
230
- }
231
- // Non-Claude models - pass through
232
- return {
233
- ...base,
234
- reasoning: options?.reasoning,
235
- thinkingBudgets: options?.thinkingBudgets,
236
- };
237
- }
238
- case "openai-completions":
239
- return {
240
- ...base,
241
- reasoningEffort: supportsXhigh(model) ? options?.reasoning : clampReasoning(options?.reasoning),
242
- };
243
- case "openai-responses":
244
- return {
245
- ...base,
246
- reasoningEffort: supportsXhigh(model) ? options?.reasoning : clampReasoning(options?.reasoning),
247
- };
248
- case "openai-codex-responses":
249
- return {
250
- ...base,
251
- reasoningEffort: supportsXhigh(model) ? options?.reasoning : clampReasoning(options?.reasoning),
252
- };
253
- case "google-generative-ai": {
254
- // Explicitly disable thinking when reasoning is not specified
255
- // This is needed because Gemini has "dynamic thinking" enabled by default
256
- if (!options?.reasoning) {
257
- return { ...base, thinking: { enabled: false } };
258
- }
259
- const googleModel = model;
260
- const effort = clampReasoning(options.reasoning);
261
- // Gemini 3 models use thinkingLevel exclusively instead of thinkingBudget.
262
- // https://ai.google.dev/gemini-api/docs/thinking#set-budget
263
- if (isGemini3ProModel(googleModel) || isGemini3FlashModel(googleModel)) {
264
- return {
265
- ...base,
266
- thinking: {
267
- enabled: true,
268
- level: getGemini3ThinkingLevel(effort, googleModel),
269
- },
270
- };
271
- }
272
- return {
273
- ...base,
274
- thinking: {
275
- enabled: true,
276
- budgetTokens: getGoogleBudget(googleModel, effort, options?.thinkingBudgets),
277
- },
278
- };
279
- }
280
- case "google-gemini-cli": {
281
- if (!options?.reasoning) {
282
- return { ...base, thinking: { enabled: false } };
283
- }
284
- const effort = clampReasoning(options.reasoning);
285
- // Gemini 3 models use thinkingLevel instead of thinkingBudget
286
- if (model.id.includes("3-pro") || model.id.includes("3-flash")) {
287
- return {
288
- ...base,
289
- thinking: {
290
- enabled: true,
291
- level: getGeminiCliThinkingLevel(effort, model.id),
292
- },
293
- };
294
- }
295
- // Models using thinkingBudget (Gemini 2.x, Claude via Antigravity)
296
- // Claude requires max_tokens > thinking.budget_tokens
297
- // So we need to ensure maxTokens accounts for both thinking and output
298
- const defaultBudgets = {
299
- minimal: 1024,
300
- low: 2048,
301
- medium: 8192,
302
- high: 16384,
303
- };
304
- const budgets = { ...defaultBudgets, ...options?.thinkingBudgets };
305
- const minOutputTokens = 1024;
306
- let thinkingBudget = budgets[effort];
307
- // Caller's maxTokens is the desired output; add thinking budget on top, capped at model limit
308
- const maxTokens = Math.min((base.maxTokens || 0) + thinkingBudget, model.maxTokens);
309
- // If not enough room for thinking + output, reduce thinking budget
310
- if (maxTokens <= thinkingBudget) {
311
- thinkingBudget = Math.max(0, maxTokens - minOutputTokens);
312
- }
313
- return {
314
- ...base,
315
- maxTokens,
316
- thinking: {
317
- enabled: true,
318
- budgetTokens: thinkingBudget,
319
- },
320
- };
321
- }
322
- case "google-vertex": {
323
- // Explicitly disable thinking when reasoning is not specified
324
- if (!options?.reasoning) {
325
- return { ...base, thinking: { enabled: false } };
326
- }
327
- const vertexModel = model;
328
- const effort = clampReasoning(options.reasoning);
329
- const geminiModel = vertexModel;
330
- if (isGemini3ProModel(geminiModel) || isGemini3FlashModel(geminiModel)) {
331
- return {
332
- ...base,
333
- thinking: {
334
- enabled: true,
335
- level: getGemini3ThinkingLevel(effort, geminiModel),
336
- },
337
- };
338
- }
339
- return {
340
- ...base,
341
- thinking: {
342
- enabled: true,
343
- budgetTokens: getGoogleBudget(geminiModel, effort, options?.thinkingBudgets),
344
- },
345
- };
346
- }
347
- default: {
348
- // Exhaustiveness check
349
- const _exhaustive = model.api;
350
- throw new Error(`Unhandled API in mapOptionsForApi: ${_exhaustive}`);
351
- }
352
- }
353
- }
354
- function isGemini3ProModel(model) {
355
- // Covers gemini-3-pro, gemini-3-pro-preview, and possible other prefixed ids in the future
356
- return model.id.includes("3-pro");
357
- }
358
- function isGemini3FlashModel(model) {
359
- // Covers gemini-3-flash, gemini-3-flash-preview, and possible other prefixed ids in the future
360
- return model.id.includes("3-flash");
361
- }
362
- function getGemini3ThinkingLevel(effort, model) {
363
- if (isGemini3ProModel(model)) {
364
- // Gemini 3 Pro only supports LOW/HIGH (for now)
365
- switch (effort) {
366
- case "minimal":
367
- case "low":
368
- return "LOW";
369
- case "medium":
370
- case "high":
371
- return "HIGH";
372
- }
373
- }
374
- // Gemini 3 Flash supports all four levels
375
- switch (effort) {
376
- case "minimal":
377
- return "MINIMAL";
378
- case "low":
379
- return "LOW";
380
- case "medium":
381
- return "MEDIUM";
382
- case "high":
383
- return "HIGH";
384
- }
385
- }
386
- function getGeminiCliThinkingLevel(effort, modelId) {
387
- if (modelId.includes("3-pro")) {
388
- // Gemini 3 Pro only supports LOW/HIGH (for now)
389
- switch (effort) {
390
- case "minimal":
391
- case "low":
392
- return "LOW";
393
- case "medium":
394
- case "high":
395
- return "HIGH";
396
- }
397
- }
398
- // Gemini 3 Flash supports all four levels
399
- switch (effort) {
400
- case "minimal":
401
- return "MINIMAL";
402
- case "low":
403
- return "LOW";
404
- case "medium":
405
- return "MEDIUM";
406
- case "high":
407
- return "HIGH";
408
- }
409
- }
410
- function getGoogleBudget(model, effort, customBudgets) {
411
- // Custom budgets take precedence if provided for this level
412
- if (customBudgets?.[effort] !== undefined) {
413
- return customBudgets[effort];
414
- }
415
- // See https://ai.google.dev/gemini-api/docs/thinking#set-budget
416
- if (model.id.includes("2.5-pro")) {
417
- const budgets = {
418
- minimal: 128,
419
- low: 2048,
420
- medium: 8192,
421
- high: 32768,
422
- };
423
- return budgets[effort];
424
- }
425
- if (model.id.includes("2.5-flash")) {
426
- // Covers 2.5-flash-lite as well
427
- const budgets = {
428
- minimal: 128,
429
- low: 2048,
430
- medium: 8192,
431
- high: 24576,
432
- };
433
- return budgets[effort];
434
- }
435
- // Unknown model - use dynamic
436
- return -1;
437
- }
438
35
  //# sourceMappingURL=stream.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream.js","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"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","sourcesContent":["// NEVER convert to top-level imports - breaks browser/Vite builds (web-ui)\nlet _existsSync: typeof import(\"node:fs\").existsSync | null = null;\nlet _homedir: typeof import(\"node:os\").homedir | null = null;\nlet _join: typeof import(\"node:path\").join | null = null;\n\n// Eagerly load in Node.js environment only\nif (typeof process !== \"undefined\" && process.versions?.node) {\n\timport(\"node:fs\").then((m) => {\n\t\t_existsSync = m.existsSync;\n\t});\n\timport(\"node:os\").then((m) => {\n\t\t_homedir = m.homedir;\n\t});\n\timport(\"node:path\").then((m) => {\n\t\t_join = m.join;\n\t});\n}\n\nimport { supportsXhigh } from \"./models.js\";\nimport { type BedrockOptions, streamBedrock } from \"./providers/amazon-bedrock.js\";\nimport { type AnthropicOptions, streamAnthropic } from \"./providers/anthropic.js\";\nimport { type GoogleOptions, streamGoogle } from \"./providers/google.js\";\nimport {\n\ttype GoogleGeminiCliOptions,\n\ttype GoogleThinkingLevel,\n\tstreamGoogleGeminiCli,\n} from \"./providers/google-gemini-cli.js\";\nimport { type GoogleVertexOptions, streamGoogleVertex } from \"./providers/google-vertex.js\";\nimport { type OpenAICodexResponsesOptions, streamOpenAICodexResponses } from \"./providers/openai-codex-responses.js\";\nimport { type OpenAICompletionsOptions, streamOpenAICompletions } from \"./providers/openai-completions.js\";\nimport { type OpenAIResponsesOptions, streamOpenAIResponses } from \"./providers/openai-responses.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tContext,\n\tKnownProvider,\n\tModel,\n\tOptionsForApi,\n\tSimpleStreamOptions,\n\tThinkingBudgets,\n\tThinkingLevel,\n} from \"./types.js\";\n\nlet cachedVertexAdcCredentialsExists: boolean | null = null;\n\nfunction hasVertexAdcCredentials(): boolean {\n\tif (cachedVertexAdcCredentialsExists === null) {\n\t\t// In browser or if node modules not loaded yet, return false\n\t\tif (!_existsSync || !_homedir || !_join) {\n\t\t\tcachedVertexAdcCredentialsExists = false;\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check GOOGLE_APPLICATION_CREDENTIALS env var first (standard way)\n\t\tconst gacPath = process.env.GOOGLE_APPLICATION_CREDENTIALS;\n\t\tif (gacPath) {\n\t\t\tcachedVertexAdcCredentialsExists = _existsSync(gacPath);\n\t\t} else {\n\t\t\t// Fall back to default ADC path (lazy evaluation)\n\t\t\tcachedVertexAdcCredentialsExists = _existsSync(\n\t\t\t\t_join(_homedir(), \".config\", \"gcloud\", \"application_default_credentials.json\"),\n\t\t\t);\n\t\t}\n\t}\n\treturn cachedVertexAdcCredentialsExists;\n}\n\n/**\n * Get API key for provider from known environment variables, e.g. OPENAI_API_KEY.\n *\n * Will not return API keys for providers that require OAuth tokens.\n */\nexport function getEnvApiKey(provider: KnownProvider): string | undefined;\nexport function getEnvApiKey(provider: string): string | undefined;\nexport function getEnvApiKey(provider: any): string | undefined {\n\t// Fall back to environment variables\n\tif (provider === \"github-copilot\") {\n\t\treturn process.env.COPILOT_GITHUB_TOKEN || process.env.GH_TOKEN || process.env.GITHUB_TOKEN;\n\t}\n\n\t// ANTHROPIC_OAUTH_TOKEN takes precedence over ANTHROPIC_API_KEY\n\tif (provider === \"anthropic\") {\n\t\treturn process.env.ANTHROPIC_OAUTH_TOKEN || process.env.ANTHROPIC_API_KEY;\n\t}\n\n\t// Vertex AI uses Application Default Credentials, not API keys.\n\t// Auth is configured via `gcloud auth application-default login`.\n\tif (provider === \"google-vertex\") {\n\t\tconst hasCredentials = hasVertexAdcCredentials();\n\t\tconst hasProject = !!(process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT);\n\t\tconst hasLocation = !!process.env.GOOGLE_CLOUD_LOCATION;\n\n\t\tif (hasCredentials && hasProject && hasLocation) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\tif (provider === \"amazon-bedrock\") {\n\t\t// Amazon Bedrock supports multiple credential sources:\n\t\t// 1. AWS_PROFILE - named profile from ~/.aws/credentials\n\t\t// 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - standard IAM keys\n\t\t// 3. AWS_BEARER_TOKEN_BEDROCK - Bedrock API keys (bearer token)\n\t\t// 4. AWS_CONTAINER_CREDENTIALS_RELATIVE_URI - ECS task roles\n\t\t// 5. AWS_CONTAINER_CREDENTIALS_FULL_URI - ECS task roles (full URI)\n\t\t// 6. AWS_WEB_IDENTITY_TOKEN_FILE - IRSA (IAM Roles for Service Accounts)\n\t\tif (\n\t\t\tprocess.env.AWS_PROFILE ||\n\t\t\t(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||\n\t\t\tprocess.env.AWS_BEARER_TOKEN_BEDROCK ||\n\t\t\tprocess.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ||\n\t\t\tprocess.env.AWS_CONTAINER_CREDENTIALS_FULL_URI ||\n\t\t\tprocess.env.AWS_WEB_IDENTITY_TOKEN_FILE\n\t\t) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\tconst envMap: Record<string, string> = {\n\t\topenai: \"OPENAI_API_KEY\",\n\t\tgoogle: \"GEMINI_API_KEY\",\n\t\tgroq: \"GROQ_API_KEY\",\n\t\tcerebras: \"CEREBRAS_API_KEY\",\n\t\txai: \"XAI_API_KEY\",\n\t\topenrouter: \"OPENROUTER_API_KEY\",\n\t\t\"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n\t\tzai: \"ZAI_API_KEY\",\n\t\tmistral: \"MISTRAL_API_KEY\",\n\t\tminimax: \"MINIMAX_API_KEY\",\n\t\t\"minimax-cn\": \"MINIMAX_CN_API_KEY\",\n\t\topencode: \"OPENCODE_API_KEY\",\n\t};\n\n\tconst envVar = envMap[provider];\n\treturn envVar ? process.env[envVar] : undefined;\n}\n\nexport function stream<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: OptionsForApi<TApi>,\n): AssistantMessageEventStream {\n\t// Vertex AI uses Application Default Credentials, not API keys\n\tif (model.api === \"google-vertex\") {\n\t\treturn streamGoogleVertex(model as Model<\"google-vertex\">, context, options as GoogleVertexOptions);\n\t} else if (model.api === \"bedrock-converse-stream\") {\n\t\t// Bedrock doesn't have any API keys instead it sources credentials from standard AWS env variables or from given AWS profile.\n\t\treturn streamBedrock(model as Model<\"bedrock-converse-stream\">, context, (options || {}) as BedrockOptions);\n\t}\n\n\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider);\n\tif (!apiKey) {\n\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t}\n\tconst providerOptions = { ...options, apiKey };\n\n\tconst api: Api = model.api;\n\tswitch (api) {\n\t\tcase \"anthropic-messages\":\n\t\t\treturn streamAnthropic(model as Model<\"anthropic-messages\">, context, providerOptions);\n\n\t\tcase \"openai-completions\":\n\t\t\treturn streamOpenAICompletions(model as Model<\"openai-completions\">, context, providerOptions as any);\n\n\t\tcase \"openai-responses\":\n\t\t\treturn streamOpenAIResponses(model as Model<\"openai-responses\">, context, providerOptions as any);\n\n\t\tcase \"openai-codex-responses\":\n\t\t\treturn streamOpenAICodexResponses(model as Model<\"openai-codex-responses\">, context, providerOptions as any);\n\n\t\tcase \"google-generative-ai\":\n\t\t\treturn streamGoogle(model as Model<\"google-generative-ai\">, context, providerOptions);\n\n\t\tcase \"google-gemini-cli\":\n\t\t\treturn streamGoogleGeminiCli(\n\t\t\t\tmodel as Model<\"google-gemini-cli\">,\n\t\t\t\tcontext,\n\t\t\t\tproviderOptions as GoogleGeminiCliOptions,\n\t\t\t);\n\n\t\tdefault: {\n\t\t\t// This should never be reached if all Api cases are handled\n\t\t\tconst _exhaustive: never = api;\n\t\t\tthrow new Error(`Unhandled API: ${_exhaustive}`);\n\t\t}\n\t}\n}\n\nexport async function complete<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: OptionsForApi<TApi>,\n): Promise<AssistantMessage> {\n\tconst s = stream(model, context, options);\n\treturn s.result();\n}\n\nexport function streamSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream {\n\t// Vertex AI uses Application Default Credentials, not API keys\n\tif (model.api === \"google-vertex\") {\n\t\tconst providerOptions = mapOptionsForApi(model, options, undefined);\n\t\treturn stream(model, context, providerOptions);\n\t} else if (model.api === \"bedrock-converse-stream\") {\n\t\t// Bedrock doesn't have any API keys instead it sources credentials from standard AWS env variables or from given AWS profile.\n\t\tconst providerOptions = mapOptionsForApi(model, options, undefined);\n\t\treturn stream(model, context, providerOptions);\n\t}\n\n\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider);\n\tif (!apiKey) {\n\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t}\n\n\tconst providerOptions = mapOptionsForApi(model, options, apiKey);\n\treturn stream(model, context, providerOptions);\n}\n\nexport async function completeSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = streamSimple(model, context, options);\n\treturn s.result();\n}\n\nfunction mapOptionsForApi<TApi extends Api>(\n\tmodel: Model<TApi>,\n\toptions?: SimpleStreamOptions,\n\tapiKey?: string,\n): OptionsForApi<TApi> {\n\tconst base = {\n\t\ttemperature: options?.temperature,\n\t\tmaxTokens: options?.maxTokens || Math.min(model.maxTokens, 32000),\n\t\tsignal: options?.signal,\n\t\tapiKey: apiKey || options?.apiKey,\n\t\tsessionId: options?.sessionId,\n\t\theaders: options?.headers,\n\t\tonPayload: options?.onPayload,\n\t};\n\n\t// Helper to clamp xhigh to high for providers that don't support it\n\tconst clampReasoning = (effort: ThinkingLevel | undefined) => (effort === \"xhigh\" ? \"high\" : effort);\n\n\t/**\n\t * Adjust maxTokens to account for thinking budget.\n\t * APIs like Anthropic and Bedrock require max_tokens > thinking.budget_tokens.\n\t * Returns { adjustedMaxTokens, adjustedThinkingBudget }\n\t */\n\tconst adjustMaxTokensForThinking = (\n\t\tbaseMaxTokens: number,\n\t\tmodelMaxTokens: number,\n\t\treasoningLevel: ThinkingLevel,\n\t\tcustomBudgets?: ThinkingBudgets,\n\t): { maxTokens: number; thinkingBudget: number } => {\n\t\tconst defaultBudgets: ThinkingBudgets = {\n\t\t\tminimal: 1024,\n\t\t\tlow: 2048,\n\t\t\tmedium: 8192,\n\t\t\thigh: 16384,\n\t\t};\n\t\tconst budgets = { ...defaultBudgets, ...customBudgets };\n\n\t\tconst minOutputTokens = 1024;\n\t\tconst level = clampReasoning(reasoningLevel)!;\n\t\tlet thinkingBudget = budgets[level]!;\n\t\t// Caller's maxTokens is the desired output; add thinking budget on top, capped at model limit\n\t\tconst maxTokens = Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);\n\n\t\t// If not enough room for thinking + output, reduce thinking budget\n\t\tif (maxTokens <= thinkingBudget) {\n\t\t\tthinkingBudget = Math.max(0, maxTokens - minOutputTokens);\n\t\t}\n\n\t\treturn { maxTokens, thinkingBudget };\n\t};\n\n\tswitch (model.api) {\n\t\tcase \"anthropic-messages\": {\n\t\t\t// Explicitly disable thinking when reasoning is not specified\n\t\t\tif (!options?.reasoning) {\n\t\t\t\treturn { ...base, thinkingEnabled: false } satisfies AnthropicOptions;\n\t\t\t}\n\n\t\t\t// Claude requires max_tokens > thinking.budget_tokens\n\t\t\t// So we need to ensure maxTokens accounts for both thinking and output\n\t\t\tconst adjusted = adjustMaxTokensForThinking(\n\t\t\t\tbase.maxTokens || 0,\n\t\t\t\tmodel.maxTokens,\n\t\t\t\toptions.reasoning,\n\t\t\t\toptions?.thinkingBudgets,\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tmaxTokens: adjusted.maxTokens,\n\t\t\t\tthinkingEnabled: true,\n\t\t\t\tthinkingBudgetTokens: adjusted.thinkingBudget,\n\t\t\t} satisfies AnthropicOptions;\n\t\t}\n\n\t\tcase \"bedrock-converse-stream\": {\n\t\t\t// Explicitly disable thinking when reasoning is not specified\n\t\t\tif (!options?.reasoning) {\n\t\t\t\treturn { ...base, reasoning: undefined } satisfies BedrockOptions;\n\t\t\t}\n\n\t\t\t// Claude requires max_tokens > thinking.budget_tokens (same as Anthropic direct API)\n\t\t\t// So we need to ensure maxTokens accounts for both thinking and output\n\t\t\tif (model.id.includes(\"anthropic.claude\") || model.id.includes(\"anthropic/claude\")) {\n\t\t\t\tconst adjusted = adjustMaxTokensForThinking(\n\t\t\t\t\tbase.maxTokens || 0,\n\t\t\t\t\tmodel.maxTokens,\n\t\t\t\t\toptions.reasoning,\n\t\t\t\t\toptions?.thinkingBudgets,\n\t\t\t\t);\n\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\tmaxTokens: adjusted.maxTokens,\n\t\t\t\t\treasoning: options.reasoning,\n\t\t\t\t\tthinkingBudgets: {\n\t\t\t\t\t\t...(options?.thinkingBudgets || {}),\n\t\t\t\t\t\t[clampReasoning(options.reasoning)!]: adjusted.thinkingBudget,\n\t\t\t\t\t},\n\t\t\t\t} satisfies BedrockOptions;\n\t\t\t}\n\n\t\t\t// Non-Claude models - pass through\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\treasoning: options?.reasoning,\n\t\t\t\tthinkingBudgets: options?.thinkingBudgets,\n\t\t\t} satisfies BedrockOptions;\n\t\t}\n\n\t\tcase \"openai-completions\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\treasoningEffort: supportsXhigh(model) ? options?.reasoning : clampReasoning(options?.reasoning),\n\t\t\t} satisfies OpenAICompletionsOptions;\n\n\t\tcase \"openai-responses\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\treasoningEffort: supportsXhigh(model) ? options?.reasoning : clampReasoning(options?.reasoning),\n\t\t\t} satisfies OpenAIResponsesOptions;\n\n\t\tcase \"openai-codex-responses\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\treasoningEffort: supportsXhigh(model) ? options?.reasoning : clampReasoning(options?.reasoning),\n\t\t\t} satisfies OpenAICodexResponsesOptions;\n\n\t\tcase \"google-generative-ai\": {\n\t\t\t// Explicitly disable thinking when reasoning is not specified\n\t\t\t// This is needed because Gemini has \"dynamic thinking\" enabled by default\n\t\t\tif (!options?.reasoning) {\n\t\t\t\treturn { ...base, thinking: { enabled: false } } satisfies GoogleOptions;\n\t\t\t}\n\n\t\t\tconst googleModel = model as Model<\"google-generative-ai\">;\n\t\t\tconst effort = clampReasoning(options.reasoning)!;\n\n\t\t\t// Gemini 3 models use thinkingLevel exclusively instead of thinkingBudget.\n\t\t\t// https://ai.google.dev/gemini-api/docs/thinking#set-budget\n\t\t\tif (isGemini3ProModel(googleModel) || isGemini3FlashModel(googleModel)) {\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\tthinking: {\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\tlevel: getGemini3ThinkingLevel(effort, googleModel),\n\t\t\t\t\t},\n\t\t\t\t} satisfies GoogleOptions;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tthinking: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tbudgetTokens: getGoogleBudget(googleModel, effort, options?.thinkingBudgets),\n\t\t\t\t},\n\t\t\t} satisfies GoogleOptions;\n\t\t}\n\n\t\tcase \"google-gemini-cli\": {\n\t\t\tif (!options?.reasoning) {\n\t\t\t\treturn { ...base, thinking: { enabled: false } } satisfies GoogleGeminiCliOptions;\n\t\t\t}\n\n\t\t\tconst effort = clampReasoning(options.reasoning)!;\n\n\t\t\t// Gemini 3 models use thinkingLevel instead of thinkingBudget\n\t\t\tif (model.id.includes(\"3-pro\") || model.id.includes(\"3-flash\")) {\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\tthinking: {\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\tlevel: getGeminiCliThinkingLevel(effort, model.id),\n\t\t\t\t\t},\n\t\t\t\t} satisfies GoogleGeminiCliOptions;\n\t\t\t}\n\n\t\t\t// Models using thinkingBudget (Gemini 2.x, Claude via Antigravity)\n\t\t\t// Claude requires max_tokens > thinking.budget_tokens\n\t\t\t// So we need to ensure maxTokens accounts for both thinking and output\n\t\t\tconst defaultBudgets: ThinkingBudgets = {\n\t\t\t\tminimal: 1024,\n\t\t\t\tlow: 2048,\n\t\t\t\tmedium: 8192,\n\t\t\t\thigh: 16384,\n\t\t\t};\n\t\t\tconst budgets = { ...defaultBudgets, ...options?.thinkingBudgets };\n\n\t\t\tconst minOutputTokens = 1024;\n\t\t\tlet thinkingBudget = budgets[effort]!;\n\t\t\t// Caller's maxTokens is the desired output; add thinking budget on top, capped at model limit\n\t\t\tconst maxTokens = Math.min((base.maxTokens || 0) + thinkingBudget, model.maxTokens);\n\n\t\t\t// If not enough room for thinking + output, reduce thinking budget\n\t\t\tif (maxTokens <= thinkingBudget) {\n\t\t\t\tthinkingBudget = Math.max(0, maxTokens - minOutputTokens);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tmaxTokens,\n\t\t\t\tthinking: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tbudgetTokens: thinkingBudget,\n\t\t\t\t},\n\t\t\t} satisfies GoogleGeminiCliOptions;\n\t\t}\n\n\t\tcase \"google-vertex\": {\n\t\t\t// Explicitly disable thinking when reasoning is not specified\n\t\t\tif (!options?.reasoning) {\n\t\t\t\treturn { ...base, thinking: { enabled: false } } satisfies GoogleVertexOptions;\n\t\t\t}\n\n\t\t\tconst vertexModel = model as Model<\"google-vertex\">;\n\t\t\tconst effort = clampReasoning(options.reasoning)!;\n\t\t\tconst geminiModel = vertexModel as unknown as Model<\"google-generative-ai\">;\n\n\t\t\tif (isGemini3ProModel(geminiModel) || isGemini3FlashModel(geminiModel)) {\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\tthinking: {\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\tlevel: getGemini3ThinkingLevel(effort, geminiModel),\n\t\t\t\t\t},\n\t\t\t\t} satisfies GoogleVertexOptions;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tthinking: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tbudgetTokens: getGoogleBudget(geminiModel, effort, options?.thinkingBudgets),\n\t\t\t\t},\n\t\t\t} satisfies GoogleVertexOptions;\n\t\t}\n\n\t\tdefault: {\n\t\t\t// Exhaustiveness check\n\t\t\tconst _exhaustive: never = model.api;\n\t\t\tthrow new Error(`Unhandled API in mapOptionsForApi: ${_exhaustive}`);\n\t\t}\n\t}\n}\n\ntype ClampedThinkingLevel = Exclude<ThinkingLevel, \"xhigh\">;\n\nfunction isGemini3ProModel(model: Model<\"google-generative-ai\">): boolean {\n\t// Covers gemini-3-pro, gemini-3-pro-preview, and possible other prefixed ids in the future\n\treturn model.id.includes(\"3-pro\");\n}\n\nfunction isGemini3FlashModel(model: Model<\"google-generative-ai\">): boolean {\n\t// Covers gemini-3-flash, gemini-3-flash-preview, and possible other prefixed ids in the future\n\treturn model.id.includes(\"3-flash\");\n}\n\nfunction getGemini3ThinkingLevel(\n\teffort: ClampedThinkingLevel,\n\tmodel: Model<\"google-generative-ai\">,\n): GoogleThinkingLevel {\n\tif (isGemini3ProModel(model)) {\n\t\t// Gemini 3 Pro only supports LOW/HIGH (for now)\n\t\tswitch (effort) {\n\t\t\tcase \"minimal\":\n\t\t\tcase \"low\":\n\t\t\t\treturn \"LOW\";\n\t\t\tcase \"medium\":\n\t\t\tcase \"high\":\n\t\t\t\treturn \"HIGH\";\n\t\t}\n\t}\n\t// Gemini 3 Flash supports all four levels\n\tswitch (effort) {\n\t\tcase \"minimal\":\n\t\t\treturn \"MINIMAL\";\n\t\tcase \"low\":\n\t\t\treturn \"LOW\";\n\t\tcase \"medium\":\n\t\t\treturn \"MEDIUM\";\n\t\tcase \"high\":\n\t\t\treturn \"HIGH\";\n\t}\n}\n\nfunction getGeminiCliThinkingLevel(effort: ClampedThinkingLevel, modelId: string): GoogleThinkingLevel {\n\tif (modelId.includes(\"3-pro\")) {\n\t\t// Gemini 3 Pro only supports LOW/HIGH (for now)\n\t\tswitch (effort) {\n\t\t\tcase \"minimal\":\n\t\t\tcase \"low\":\n\t\t\t\treturn \"LOW\";\n\t\t\tcase \"medium\":\n\t\t\tcase \"high\":\n\t\t\t\treturn \"HIGH\";\n\t\t}\n\t}\n\t// Gemini 3 Flash supports all four levels\n\tswitch (effort) {\n\t\tcase \"minimal\":\n\t\t\treturn \"MINIMAL\";\n\t\tcase \"low\":\n\t\t\treturn \"LOW\";\n\t\tcase \"medium\":\n\t\t\treturn \"MEDIUM\";\n\t\tcase \"high\":\n\t\t\treturn \"HIGH\";\n\t}\n}\n\nfunction getGoogleBudget(\n\tmodel: Model<\"google-generative-ai\">,\n\teffort: ClampedThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): number {\n\t// Custom budgets take precedence if provided for this level\n\tif (customBudgets?.[effort] !== undefined) {\n\t\treturn customBudgets[effort]!;\n\t}\n\n\t// See https://ai.google.dev/gemini-api/docs/thinking#set-budget\n\tif (model.id.includes(\"2.5-pro\")) {\n\t\tconst budgets: Record<ClampedThinkingLevel, number> = {\n\t\t\tminimal: 128,\n\t\t\tlow: 2048,\n\t\t\tmedium: 8192,\n\t\t\thigh: 32768,\n\t\t};\n\t\treturn budgets[effort];\n\t}\n\n\tif (model.id.includes(\"2.5-flash\")) {\n\t\t// Covers 2.5-flash-lite as well\n\t\tconst budgets: Record<ClampedThinkingLevel, number> = {\n\t\t\tminimal: 128,\n\t\t\tlow: 2048,\n\t\t\tmedium: 8192,\n\t\t\thigh: 24576,\n\t\t};\n\t\treturn budgets[effort];\n\t}\n\n\t// Unknown model - use dynamic\n\treturn -1;\n}\n"]}
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAYnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,kFAAkF;AAClF,oCAAoC;AACpC,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC9D,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,GAAG,CAAC,CAAC;QACrD,mBAAmB,CAAC,IAAI,iBAAiB,EAAE,CAAC,CAAC;IAAA,CAC7C,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAQ,EAAE;IACrC,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,uCAAuC,GAAG,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,QAAQ,CAAC;AAAA,CAChB;AAED,MAAM,UAAU,MAAM,CACrB,KAAkB,EAClB,OAAgB,EAChB,OAA+B,EACD;IAC9B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAwB,CAAC,CAAC;AAAA,CACjE;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC7B,KAAkB,EAClB,OAAgB,EAChB,OAA+B,EACH;IAC5B,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;AAAA,CAClB;AAED,MAAM,UAAU,YAAY,CAC3B,KAAkB,EAClB,OAAgB,EAChB,OAA6B,EACC;IAC9B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,QAAQ,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAAA,CACtD;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,KAAkB,EAClB,OAAgB,EAChB,OAA6B,EACD;IAC5B,MAAM,CAAC,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;AAAA,CAClB","sourcesContent":["import \"./providers/register-builtins.js\";\n\nimport { getApiProvider } from \"./api-registry.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tContext,\n\tModel,\n\tProviderStreamOptions,\n\tSimpleStreamOptions,\n\tStreamOptions,\n} from \"./types.js\";\n\nexport { getEnvApiKey } from \"./env-api-keys.js\";\n\n// Set up http proxy according to env variables for `fetch` based SDKs in Node.js.\n// Bun has builtin support for this.\nif (typeof process !== \"undefined\" && process.versions?.node) {\n\timport(\"undici\").then((m) => {\n\t\tconst { EnvHttpProxyAgent, setGlobalDispatcher } = m;\n\t\tsetGlobalDispatcher(new EnvHttpProxyAgent());\n\t});\n}\n\nfunction resolveApiProvider(api: Api) {\n\tconst provider = getApiProvider(api);\n\tif (!provider) {\n\t\tthrow new Error(`No API provider registered for api: ${api}`);\n\t}\n\treturn provider;\n}\n\nexport function stream<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: ProviderStreamOptions,\n): AssistantMessageEventStream {\n\tconst provider = resolveApiProvider(model.api);\n\treturn provider.stream(model, context, options as StreamOptions);\n}\n\nexport async function complete<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: ProviderStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = stream(model, context, options);\n\treturn s.result();\n}\n\nexport function streamSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream {\n\tconst provider = resolveApiProvider(model.api);\n\treturn provider.streamSimple(model, context, options);\n}\n\nexport async function completeSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = streamSimple(model, context, options);\n\treturn s.result();\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -1,26 +1,8 @@
1
- import type { BedrockOptions } from "./providers/amazon-bedrock.js";
2
- import type { AnthropicOptions } from "./providers/anthropic.js";
3
- import type { GoogleOptions } from "./providers/google.js";
4
- import type { GoogleGeminiCliOptions } from "./providers/google-gemini-cli.js";
5
- import type { GoogleVertexOptions } from "./providers/google-vertex.js";
6
- import type { OpenAICodexResponsesOptions } from "./providers/openai-codex-responses.js";
7
- import type { OpenAICompletionsOptions } from "./providers/openai-completions.js";
8
- import type { OpenAIResponsesOptions } from "./providers/openai-responses.js";
9
1
  import type { AssistantMessageEventStream } from "./utils/event-stream.js";
10
2
  export type { AssistantMessageEventStream } from "./utils/event-stream.js";
11
- export type Api = "openai-completions" | "openai-responses" | "openai-codex-responses" | "anthropic-messages" | "bedrock-converse-stream" | "google-generative-ai" | "google-gemini-cli" | "google-vertex";
12
- export interface ApiOptionsMap {
13
- "anthropic-messages": AnthropicOptions;
14
- "bedrock-converse-stream": BedrockOptions;
15
- "openai-completions": OpenAICompletionsOptions;
16
- "openai-responses": OpenAIResponsesOptions;
17
- "openai-codex-responses": OpenAICodexResponsesOptions;
18
- "google-generative-ai": GoogleOptions;
19
- "google-gemini-cli": GoogleGeminiCliOptions;
20
- "google-vertex": GoogleVertexOptions;
21
- }
22
- export type OptionsForApi<TApi extends Api> = ApiOptionsMap[TApi];
23
- export type KnownProvider = "amazon-bedrock" | "anthropic" | "google" | "google-gemini-cli" | "google-antigravity" | "google-vertex" | "openai" | "openai-codex" | "github-copilot" | "xai" | "groq" | "cerebras" | "openrouter" | "vercel-ai-gateway" | "zai" | "mistral" | "minimax" | "minimax-cn" | "opencode";
3
+ export type KnownApi = "openai-completions" | "openai-responses" | "azure-openai-responses" | "openai-codex-responses" | "anthropic-messages" | "bedrock-converse-stream" | "google-generative-ai" | "google-gemini-cli" | "google-vertex";
4
+ export type Api = KnownApi | (string & {});
5
+ export type KnownProvider = "amazon-bedrock" | "anthropic" | "google" | "google-gemini-cli" | "google-antigravity" | "google-vertex" | "openai" | "azure-openai-responses" | "openai-codex" | "github-copilot" | "xai" | "groq" | "cerebras" | "openrouter" | "vercel-ai-gateway" | "zai" | "mistral" | "minimax" | "minimax-cn" | "opencode";
24
6
  export type Provider = KnownProvider | string;
25
7
  export type ThinkingLevel = "minimal" | "low" | "medium" | "high" | "xhigh";
26
8
  /** Token budgets for each thinking level (token-based providers only) */
@@ -52,12 +34,13 @@ export interface StreamOptions {
52
34
  */
53
35
  headers?: Record<string, string>;
54
36
  }
37
+ export type ProviderStreamOptions = StreamOptions & Record<string, unknown>;
55
38
  export interface SimpleStreamOptions extends StreamOptions {
56
39
  reasoning?: ThinkingLevel;
57
40
  /** Custom token budgets for thinking levels (token-based providers only) */
58
41
  thinkingBudgets?: ThinkingBudgets;
59
42
  }
60
- export type StreamFunction<TApi extends Api> = (model: Model<TApi>, context: Context, options: OptionsForApi<TApi>) => AssistantMessageEventStream;
43
+ export type StreamFunction<TApi extends Api = Api, TOptions extends StreamOptions = StreamOptions> = (model: Model<TApi>, context: Context, options?: TOptions) => AssistantMessageEventStream;
61
44
  export interface TextContent {
62
45
  type: "text";
63
46
  text: string;
@@ -211,10 +194,23 @@ export interface OpenAICompletionsCompat {
211
194
  requiresMistralToolIds?: boolean;
212
195
  /** Format for reasoning/thinking parameter. "openai" uses reasoning_effort, "zai" uses thinking: { type: "enabled" }. Default: "openai". */
213
196
  thinkingFormat?: "openai" | "zai";
197
+ /** OpenRouter-specific routing preferences. Only used when baseUrl points to OpenRouter. */
198
+ openRouterRouting?: OpenRouterRouting;
214
199
  }
215
200
  /** Compatibility settings for OpenAI Responses APIs. */
216
201
  export interface OpenAIResponsesCompat {
217
202
  }
203
+ /**
204
+ * OpenRouter provider routing preferences.
205
+ * Controls which upstream providers OpenRouter routes requests to.
206
+ * @see https://openrouter.ai/docs/provider-routing
207
+ */
208
+ export interface OpenRouterRouting {
209
+ /** List of provider slugs to exclusively use for this request (e.g., ["amazon-bedrock", "anthropic"]). */
210
+ only?: string[];
211
+ /** List of provider slugs to try in order (e.g., ["anthropic", "openai"]). */
212
+ order?: string[];
213
+ }
218
214
  export interface Model<TApi extends Api> {
219
215
  id: string;
220
216
  name: string;