ai-sdk-provider-env 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -5
- package/dist/index.cjs +62 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +110 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +110 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +62 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ Using multiple AI providers with Vercel AI SDK means importing each SDK, configu
|
|
|
17
17
|
|
|
18
18
|
- Resolve provider config (base URL, API key, compatibility mode) from environment variables automatically
|
|
19
19
|
- Built-in presets for popular providers, so you only need to set an API key
|
|
20
|
-
- Supports OpenAI, Anthropic, and any OpenAI-compatible API
|
|
20
|
+
- Supports OpenAI, Anthropic, Google Gemini, and any OpenAI-compatible API
|
|
21
21
|
- Implements `ProviderV3`, plugs directly into `createProviderRegistry`
|
|
22
22
|
- Provider instances are cached, no redundant initialization
|
|
23
23
|
- Fully customizable: custom fetch, env-based headers, custom separator, code-based configs
|
|
@@ -33,6 +33,7 @@ Install provider SDKs as needed:
|
|
|
33
33
|
```bash
|
|
34
34
|
pnpm add @ai-sdk/openai # for OpenAI
|
|
35
35
|
pnpm add @ai-sdk/anthropic # for Anthropic
|
|
36
|
+
pnpm add @ai-sdk/google # for Google AI Studio (Gemini)
|
|
36
37
|
pnpm add @ai-sdk/openai-compatible # for generic OpenAI-compatible APIs
|
|
37
38
|
```
|
|
38
39
|
|
|
@@ -47,8 +48,7 @@ const registry = createProviderRegistry({
|
|
|
47
48
|
})
|
|
48
49
|
|
|
49
50
|
// Use a preset: only API_KEY is required
|
|
50
|
-
// OPENAI_PRESET=openai
|
|
51
|
-
// OPENAI_API_KEY=sk-xxx
|
|
51
|
+
// OPENAI_API_KEY=sk-xxx (OPENAI_PRESET=openai is optional — auto-detected)
|
|
52
52
|
const model = registry.languageModel('env:openai/gpt-4o')
|
|
53
53
|
|
|
54
54
|
const { text } = await generateText({ model, prompt: 'Hello!' })
|
|
@@ -86,7 +86,7 @@ With the default separator `_`, a config set reads these variables (`[MYAI]` = y
|
|
|
86
86
|
| Variable | Required | Description |
|
|
87
87
|
|---|---|---|
|
|
88
88
|
| `[MYAI]_API_KEY` | Yes | API key |
|
|
89
|
-
| `[MYAI]_BASE_URL` | Yes (unless preset is set) | API base URL |
|
|
89
|
+
| `[MYAI]_BASE_URL` | Yes (unless preset is set or auto-detected) | API base URL |
|
|
90
90
|
| `[MYAI]_PRESET` | No | Built-in preset name (e.g. `openai`) |
|
|
91
91
|
| `[MYAI]_COMPATIBLE` | No | Compatibility mode (default: `openai-compatible`) |
|
|
92
92
|
| `[MYAI]_HEADERS` | No | Custom HTTP headers (JSON format) |
|
|
@@ -99,6 +99,7 @@ When `PRESET` is set, `BASE_URL` and `COMPATIBLE` become optional and fall back
|
|
|
99
99
|
|---|---|
|
|
100
100
|
| `openai` | Uses `@ai-sdk/openai` |
|
|
101
101
|
| `anthropic` | Uses `@ai-sdk/anthropic` |
|
|
102
|
+
| `gemini` | Uses `@ai-sdk/google` |
|
|
102
103
|
| `openai-compatible` | Uses `@ai-sdk/openai-compatible` with the config set name as the provider name (default) |
|
|
103
104
|
|
|
104
105
|
## Built-in Presets
|
|
@@ -107,6 +108,7 @@ When `PRESET` is set, `BASE_URL` and `COMPATIBLE` become optional and fall back
|
|
|
107
108
|
|---|---|---|
|
|
108
109
|
| `openai` | `https://api.openai.com/v1` | `openai` |
|
|
109
110
|
| `anthropic` | `https://api.anthropic.com` | `anthropic` |
|
|
111
|
+
| `google` | `https://generativelanguage.googleapis.com/v1beta` | `gemini` |
|
|
110
112
|
| `deepseek` | `https://api.deepseek.com` | `openai-compatible` |
|
|
111
113
|
| `zhipu` | `https://open.bigmodel.cn/api/paas/v4` | `openai-compatible` |
|
|
112
114
|
| `groq` | `https://api.groq.com/openai/v1` | `openai-compatible` |
|
|
@@ -118,6 +120,28 @@ When `PRESET` is set, `BASE_URL` and `COMPATIBLE` become optional and fall back
|
|
|
118
120
|
| `openrouter` | `https://openrouter.ai/api/v1` | `openai-compatible` |
|
|
119
121
|
| `siliconflow` | `https://api.siliconflow.cn/v1` | `openai-compatible` |
|
|
120
122
|
|
|
123
|
+
## Preset Auto-Detect
|
|
124
|
+
|
|
125
|
+
`presetAutoDetect` is enabled by default. When the config set name exactly matches a built-in preset name, the preset is applied automatically — no `_PRESET` env var needed. Only an API key is required:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
# OPENROUTER_API_KEY is all you need
|
|
129
|
+
OPENROUTER_API_KEY=sk-or-xxx
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
const provider = envProvider()
|
|
134
|
+
|
|
135
|
+
// Works — openrouter preset auto-detected from config set name
|
|
136
|
+
const model = provider.languageModel('openrouter/some-model')
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Explicit `_PRESET` and `_BASE_URL` env vars always take precedence over auto-detect. To disable this behavior:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
envProvider({ presetAutoDetect: false })
|
|
143
|
+
```
|
|
144
|
+
|
|
121
145
|
## API Reference
|
|
122
146
|
|
|
123
147
|
### `envProvider(options?)`
|
|
@@ -137,6 +161,8 @@ const provider = envProvider(options)
|
|
|
137
161
|
| `separator` | `string` | `'_'` | Separator between the prefix and the variable name |
|
|
138
162
|
| `configs` | `Record<string, ConfigSetEntry>` | `undefined` | Explicit config sets (takes precedence over env vars) |
|
|
139
163
|
| `defaults` | `EnvProviderDefaults` | `undefined` | Global defaults applied to all providers (can be overridden per config set) |
|
|
164
|
+
| `presetAutoDetect` | `boolean` | `true` | Auto-apply a built-in preset when the config set name matches. Set to `false` to require explicit `_PRESET` configuration. |
|
|
165
|
+
| `factories` | `EnvProviderFactories` | `undefined` | User-provided factory functions for [bundler-safe usage](#bundler-usage). |
|
|
140
166
|
|
|
141
167
|
**`EnvProviderDefaults`:**
|
|
142
168
|
|
|
@@ -152,7 +178,7 @@ interface ConfigSetEntry {
|
|
|
152
178
|
apiKey: string
|
|
153
179
|
preset?: string
|
|
154
180
|
baseURL?: string
|
|
155
|
-
compatible?: 'openai' | 'anthropic' | 'openai-compatible' // default: 'openai-compatible'
|
|
181
|
+
compatible?: 'openai' | 'anthropic' | 'gemini' | 'openai-compatible' // default: 'openai-compatible'
|
|
156
182
|
headers?: Record<string, string>
|
|
157
183
|
}
|
|
158
184
|
```
|
|
@@ -273,3 +299,26 @@ const registry = createProviderRegistry({
|
|
|
273
299
|
openai: createOpenAI({ apiKey: process.env.OPENAI_API_KEY }),
|
|
274
300
|
})
|
|
275
301
|
```
|
|
302
|
+
|
|
303
|
+
## Bundler Usage
|
|
304
|
+
|
|
305
|
+
Works out of the box without a bundler. If you bundle your app, two options:
|
|
306
|
+
|
|
307
|
+
**Option A** — mark packages as external (server-side with `node_modules`):
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
bun build --packages=external
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
**Option B** — provide explicit factories (single-file / `bun build --compile`):
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
import { createOpenAI } from '@ai-sdk/openai'
|
|
317
|
+
import { envProvider } from 'ai-sdk-provider-env'
|
|
318
|
+
|
|
319
|
+
const provider = envProvider({
|
|
320
|
+
factories: { openai: createOpenAI },
|
|
321
|
+
})
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
For the full guide (factory key mapping, lazy-strict behavior, combining with other options), see **[Bundler Usage Guide](./docs/bundler.md)**.
|
package/dist/index.cjs
CHANGED
|
@@ -58,6 +58,19 @@ function createAnthropicProvider(opts) {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
|
+
* Create a Google Generative AI (Gemini) provider.
|
|
62
|
+
*
|
|
63
|
+
* Dynamically requires `@ai-sdk/google`, so it only needs to be installed when actually used.
|
|
64
|
+
*/
|
|
65
|
+
function createGeminiProvider(opts) {
|
|
66
|
+
try {
|
|
67
|
+
const { createGoogleGenerativeAI } = require("@ai-sdk/google");
|
|
68
|
+
return createGoogleGenerativeAI(opts);
|
|
69
|
+
} catch {
|
|
70
|
+
throw new Error("[ai-sdk-provider-env] gemini compatibility mode requires @ai-sdk/google. Run: npm install @ai-sdk/google");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
61
74
|
* Create an OpenAI Compatible provider.
|
|
62
75
|
*
|
|
63
76
|
* Dynamically requires `@ai-sdk/openai-compatible`, so it only needs to be installed when actually used.
|
|
@@ -88,6 +101,10 @@ const builtinPresets = {
|
|
|
88
101
|
baseURL: "https://api.anthropic.com",
|
|
89
102
|
compatible: "anthropic"
|
|
90
103
|
},
|
|
104
|
+
google: {
|
|
105
|
+
baseURL: "https://generativelanguage.googleapis.com/v1beta",
|
|
106
|
+
compatible: "gemini"
|
|
107
|
+
},
|
|
91
108
|
deepseek: {
|
|
92
109
|
baseURL: "https://api.deepseek.com",
|
|
93
110
|
compatible: "openai-compatible"
|
|
@@ -138,6 +155,7 @@ const builtinPresets = {
|
|
|
138
155
|
const defaultFactories = {
|
|
139
156
|
createOpenAI: createOpenAIProvider,
|
|
140
157
|
createAnthropic: createAnthropicProvider,
|
|
158
|
+
createGemini: createGeminiProvider,
|
|
141
159
|
createOpenAICompatible: createOpenAICompatibleProvider
|
|
142
160
|
};
|
|
143
161
|
/**
|
|
@@ -210,13 +228,24 @@ function createEnvProvider(factories, options = {}) {
|
|
|
210
228
|
};
|
|
211
229
|
}
|
|
212
230
|
const baseURL = env("BASE_URL");
|
|
213
|
-
if (
|
|
214
|
-
return {
|
|
231
|
+
if (baseURL) return {
|
|
215
232
|
baseURL,
|
|
216
233
|
apiKey,
|
|
217
234
|
compatible: env("COMPATIBLE") ?? "openai-compatible",
|
|
218
235
|
...headers && { headers }
|
|
219
236
|
};
|
|
237
|
+
if (options.presetAutoDetect !== false) {
|
|
238
|
+
const autoPreset = builtinPresets[configSet.toLowerCase()];
|
|
239
|
+
if (autoPreset) return {
|
|
240
|
+
baseURL: autoPreset.baseURL,
|
|
241
|
+
apiKey,
|
|
242
|
+
compatible: env("COMPATIBLE") ?? autoPreset.compatible ?? "openai-compatible",
|
|
243
|
+
...headers && { headers }
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const available = Object.keys(builtinPresets).join(", ");
|
|
247
|
+
const presetHint = builtinPresets[configSet.toLowerCase()] ? ` (Note: "${configSet}" matches a built-in preset, but presetAutoDetect is disabled.)` : "";
|
|
248
|
+
throw new Error(`[ai-sdk-provider-env] Missing env var ${prefix}${separator}BASE_URL (or set ${prefix}${separator}PRESET to use a preset. Available presets: ${available})${presetHint}`);
|
|
220
249
|
}
|
|
221
250
|
/**
|
|
222
251
|
* Create the underlying provider based on the compatibility mode.
|
|
@@ -236,11 +265,12 @@ function createEnvProvider(factories, options = {}) {
|
|
|
236
265
|
switch (compatible) {
|
|
237
266
|
case "openai": return factories.createOpenAI(baseOpts);
|
|
238
267
|
case "anthropic": return factories.createAnthropic(baseOpts);
|
|
268
|
+
case "gemini": return factories.createGemini(baseOpts);
|
|
239
269
|
case "openai-compatible": return factories.createOpenAICompatible({
|
|
240
270
|
name: configSet,
|
|
241
271
|
...baseOpts
|
|
242
272
|
});
|
|
243
|
-
default: throw new Error(`[ai-sdk-provider-env] Unknown compatible mode "${compatible}". Supported values: "openai", "anthropic", "openai-compatible". Set COMPATIBLE=openai-compatible (or omit it) to use the OpenAI-compatible provider.`);
|
|
273
|
+
default: throw new Error(`[ai-sdk-provider-env] Unknown compatible mode "${compatible}". Supported values: "openai", "anthropic", "gemini", "openai-compatible". Set COMPATIBLE=openai-compatible (or omit it) to use the OpenAI-compatible provider.`);
|
|
244
274
|
}
|
|
245
275
|
}
|
|
246
276
|
/**
|
|
@@ -318,6 +348,24 @@ function createEnvProvider(factories, options = {}) {
|
|
|
318
348
|
};
|
|
319
349
|
}
|
|
320
350
|
/**
|
|
351
|
+
* Build internal `ProviderFactories` from user-provided `EnvProviderFactories`.
|
|
352
|
+
*
|
|
353
|
+
* Uses lazy-strict semantics: each factory slot is only evaluated when actually called.
|
|
354
|
+
* If the user provided a factory for a given compatible mode, it is used;
|
|
355
|
+
* otherwise, a clear error is thrown (no silent fallback to dynamic `require()`).
|
|
356
|
+
*/
|
|
357
|
+
function buildUserFactories(userFactories) {
|
|
358
|
+
function missingFactory(key, fnName, pkg) {
|
|
359
|
+
throw new Error(`[ai-sdk-provider-env] No factory provided for "${key}". When using the factories option, provide a factory for each compatibility mode you use. Add: import { ${fnName} } from '${pkg}' and set factories: { ${key}: ${fnName} }`);
|
|
360
|
+
}
|
|
361
|
+
return {
|
|
362
|
+
createOpenAI: (opts) => userFactories.openai ? userFactories.openai(opts) : missingFactory("openai", "createOpenAI", "@ai-sdk/openai"),
|
|
363
|
+
createAnthropic: (opts) => userFactories.anthropic ? userFactories.anthropic(opts) : missingFactory("anthropic", "createAnthropic", "@ai-sdk/anthropic"),
|
|
364
|
+
createGemini: (opts) => userFactories.gemini ? userFactories.gemini(opts) : missingFactory("gemini", "createGoogleGenerativeAI", "@ai-sdk/google"),
|
|
365
|
+
createOpenAICompatible: (opts) => userFactories.openaiCompatible ? userFactories.openaiCompatible(opts) : missingFactory("openaiCompatible", "createOpenAICompatible", "@ai-sdk/openai-compatible")
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
321
369
|
* Create a dynamic, environment-variable-driven AI SDK provider.
|
|
322
370
|
*
|
|
323
371
|
* Automatically resolves provider configurations from env var naming conventions,
|
|
@@ -349,9 +397,19 @@ function createEnvProvider(factories, options = {}) {
|
|
|
349
397
|
* // MYAPI_API_KEY=xxx
|
|
350
398
|
* const model2 = registry.languageModel('env:myapi/some-model')
|
|
351
399
|
* ```
|
|
400
|
+
*
|
|
401
|
+
* @example Bundler-safe usage with explicit factories
|
|
402
|
+
* ```ts
|
|
403
|
+
* import { createOpenAI } from '@ai-sdk/openai'
|
|
404
|
+
* import { envProvider } from 'ai-sdk-provider-env'
|
|
405
|
+
*
|
|
406
|
+
* const provider = envProvider({
|
|
407
|
+
* factories: { openai: createOpenAI },
|
|
408
|
+
* })
|
|
409
|
+
* ```
|
|
352
410
|
*/
|
|
353
411
|
function envProvider(options = {}) {
|
|
354
|
-
return createEnvProvider(defaultFactories, options);
|
|
412
|
+
return createEnvProvider(options.factories ? buildUserFactories(options.factories) : defaultFactories, options);
|
|
355
413
|
}
|
|
356
414
|
|
|
357
415
|
//#endregion
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["process","NoSuchModelError"],"sources":["../src/factories.ts","../src/presets.ts","../src/env-provider.ts"],"sourcesContent":["import type { ProviderV3 } from '@ai-sdk/provider'\n\nexport interface ProviderOpts {\n baseURL: string\n apiKey: string\n headers?: Record<string, string>\n fetch?: typeof globalThis.fetch\n}\n\n/**\n * Create an OpenAI provider.\n *\n * Dynamically requires `@ai-sdk/openai`, so it only needs to be installed when actually used.\n */\nexport function createOpenAIProvider(opts: ProviderOpts): ProviderV3 {\n try {\n // eslint-disable-next-line ts/no-require-imports\n const { createOpenAI } = require('@ai-sdk/openai')\n return createOpenAI(opts)\n }\n catch {\n throw new Error(\n '[ai-sdk-provider-env] openai compatibility mode requires @ai-sdk/openai. '\n + 'Run: npm install @ai-sdk/openai',\n )\n }\n}\n\n/**\n * Create an Anthropic provider.\n *\n * Dynamically requires `@ai-sdk/anthropic`, so it only needs to be installed when actually used.\n */\nexport function createAnthropicProvider(opts: ProviderOpts): ProviderV3 {\n try {\n // eslint-disable-next-line ts/no-require-imports\n const { createAnthropic } = require('@ai-sdk/anthropic')\n return createAnthropic(opts)\n }\n catch {\n throw new Error(\n '[ai-sdk-provider-env] anthropic compatibility mode requires @ai-sdk/anthropic. '\n + 'Run: npm install @ai-sdk/anthropic',\n )\n }\n}\n\n/**\n * Create an OpenAI Compatible provider.\n *\n * Dynamically requires `@ai-sdk/openai-compatible`, so it only needs to be installed when actually used.\n */\nexport function createOpenAICompatibleProvider(opts: ProviderOpts & { name: string }): ProviderV3 {\n try {\n // eslint-disable-next-line ts/no-require-imports\n const { createOpenAICompatible } = require('@ai-sdk/openai-compatible')\n return createOpenAICompatible(opts)\n }\n catch {\n throw new Error(\n '[ai-sdk-provider-env] openai-compatible mode requires @ai-sdk/openai-compatible. '\n + 'Run: npm install @ai-sdk/openai-compatible',\n )\n }\n}\n","import type { PresetConfig } from './types'\n\n/**\n * Built-in preset configurations for common providers.\n *\n * When using a preset, only `{PREFIX}__PRESET` and `{PREFIX}__API_KEY`\n * are required; `BASE_URL` and `COMPATIBLE` are provided by the preset.\n */\nexport const builtinPresets: Record<string, PresetConfig> = {\n // OpenAI\n openai: {\n baseURL: 'https://api.openai.com/v1',\n compatible: 'openai',\n },\n\n // Anthropic\n anthropic: {\n baseURL: 'https://api.anthropic.com',\n compatible: 'anthropic',\n },\n\n // DeepSeek\n deepseek: {\n baseURL: 'https://api.deepseek.com',\n compatible: 'openai-compatible',\n },\n\n // Zhipu AI (GLM series)\n zhipu: {\n baseURL: 'https://open.bigmodel.cn/api/paas/v4',\n compatible: 'openai-compatible',\n },\n\n // Groq\n groq: {\n baseURL: 'https://api.groq.com/openai/v1',\n compatible: 'openai-compatible',\n },\n\n // Together AI\n together: {\n baseURL: 'https://api.together.xyz/v1',\n compatible: 'openai-compatible',\n },\n\n // Fireworks AI\n fireworks: {\n baseURL: 'https://api.fireworks.ai/inference/v1',\n compatible: 'openai-compatible',\n },\n\n // Mistral AI\n mistral: {\n baseURL: 'https://api.mistral.ai/v1',\n compatible: 'openai-compatible',\n },\n\n // Moonshot AI\n moonshot: {\n baseURL: 'https://api.moonshot.cn/v1',\n compatible: 'openai-compatible',\n },\n\n // Perplexity\n perplexity: {\n baseURL: 'https://api.perplexity.ai',\n compatible: 'openai-compatible',\n },\n\n // OpenRouter\n openrouter: {\n baseURL: 'https://openrouter.ai/api/v1',\n compatible: 'openai-compatible',\n },\n\n // SiliconFlow\n siliconflow: {\n baseURL: 'https://api.siliconflow.cn/v1',\n compatible: 'openai-compatible',\n },\n}\n","import type { ProviderV3 } from '@ai-sdk/provider'\nimport type { ProviderOpts } from './factories'\nimport type { EnvProviderOptions } from './types'\nimport process from 'node:process'\nimport { NoSuchModelError } from '@ai-sdk/provider'\nimport { createAnthropicProvider, createOpenAICompatibleProvider, createOpenAIProvider } from './factories'\nimport { builtinPresets } from './presets'\n\n/**\n * Interface for provider factory functions, used for dependency injection.\n *\n * In production, `defaultFactories` delegates to the real SDK implementations.\n * In tests, fake factories can be injected to avoid module mocking.\n */\nexport interface ProviderFactories {\n createOpenAI: (opts: ProviderOpts) => ProviderV3\n createAnthropic: (opts: ProviderOpts) => ProviderV3\n createOpenAICompatible: (opts: ProviderOpts & { name: string }) => ProviderV3\n}\n\n/**\n * Default factories that delegate to the real implementations in `factories.ts`.\n */\nconst defaultFactories: ProviderFactories = {\n createOpenAI: createOpenAIProvider,\n createAnthropic: createAnthropicProvider,\n createOpenAICompatible: createOpenAICompatibleProvider,\n}\n\n/**\n * Internally resolved configuration with all required fields determined.\n */\ninterface ResolvedConfig {\n baseURL: string\n apiKey: string\n compatible: string\n headers?: Record<string, string>\n}\n\n/**\n * Testable core implementation that accepts injected provider factories.\n *\n * In tests, call this function directly with fake factories\n * to avoid module mocking entirely.\n */\nexport function createEnvProvider(\n factories: ProviderFactories,\n options: EnvProviderOptions = {},\n): ProviderV3 {\n const separator = options.separator ?? '_'\n const defaultFetch = options.defaults?.fetch\n const defaultHeaders = options.defaults?.headers\n\n // Cache created providers to avoid redundant initialization\n const cache = new Map<string, ProviderV3>()\n\n /**\n * Resolve baseURL and compatible from a preset name.\n */\n function resolvePreset(presetName: string): { baseURL: string, compatible: string } {\n const preset = builtinPresets[presetName]\n if (!preset) {\n const available = Object.keys(builtinPresets).join(', ')\n throw new Error(\n `[ai-sdk-provider-env] Unknown preset \"${presetName}\". Available presets: ${available}`,\n )\n }\n return {\n baseURL: preset.baseURL,\n compatible: preset.compatible ?? 'openai-compatible',\n }\n }\n\n /**\n * Resolve config set configuration from explicit configs, presets, or environment variables.\n */\n function resolveConfig(configSet: string): ResolvedConfig {\n // Explicit configs take precedence over env vars\n if (options.configs?.[configSet]) {\n const config = options.configs[configSet]\n\n // Code-based configs also support presets\n if (config.preset) {\n const preset = resolvePreset(config.preset)\n return {\n baseURL: config.baseURL ?? preset.baseURL,\n apiKey: config.apiKey,\n compatible: config.compatible ?? preset.compatible,\n ...(config.headers && { headers: config.headers }),\n }\n }\n\n if (!config.baseURL) {\n throw new Error(\n `[ai-sdk-provider-env] Missing baseURL in config for \"${configSet}\"`\n + ` (or set preset to use a built-in preset)`,\n )\n }\n\n return {\n baseURL: config.baseURL,\n apiKey: config.apiKey,\n compatible: config.compatible ?? 'openai-compatible',\n ...(config.headers && { headers: config.headers }),\n }\n }\n\n const prefix = configSet.toUpperCase()\n const env = (key: string): string | undefined => process.env[`${prefix}${separator}${key}`]\n\n const apiKey = env('API_KEY')\n if (!apiKey) {\n throw new Error(\n `[ai-sdk-provider-env] Missing env var ${prefix}${separator}API_KEY`,\n )\n }\n\n // Parse headers from env var (JSON format)\n const headersRaw = env('HEADERS')\n let headers: Record<string, string> | undefined\n if (headersRaw) {\n try {\n headers = JSON.parse(headersRaw)\n }\n catch {\n throw new Error(\n `[ai-sdk-provider-env] Invalid JSON in ${prefix}${separator}HEADERS: ${headersRaw}`,\n )\n }\n }\n\n // Check for preset\n const presetName = env('PRESET')\n if (presetName) {\n const preset = resolvePreset(presetName)\n return {\n baseURL: env('BASE_URL') ?? preset.baseURL,\n apiKey,\n compatible: env('COMPATIBLE') ?? preset.compatible,\n ...(headers && { headers }),\n }\n }\n\n // Without a preset, BASE_URL is required\n const baseURL = env('BASE_URL')\n if (!baseURL) {\n throw new Error(\n `[ai-sdk-provider-env] Missing env var ${prefix}${separator}BASE_URL`\n + ` (or set ${prefix}${separator}PRESET to use a preset)`,\n )\n }\n\n return {\n baseURL,\n apiKey,\n compatible: env('COMPATIBLE') ?? 'openai-compatible',\n ...(headers && { headers }),\n }\n }\n\n /**\n * Create the underlying provider based on the compatibility mode.\n */\n function createUnderlying(configSet: string, config: ResolvedConfig): ProviderV3 {\n const { baseURL, apiKey, compatible, headers } = config\n\n // Merge headers: defaults.headers as base, config-set headers override matching keys\n const mergedHeaders = (defaultHeaders || headers)\n ? { ...defaultHeaders, ...headers }\n : undefined\n\n const baseOpts = {\n baseURL,\n apiKey,\n ...(mergedHeaders && { headers: mergedHeaders }),\n ...(defaultFetch && { fetch: defaultFetch }),\n }\n\n switch (compatible) {\n case 'openai':\n return factories.createOpenAI(baseOpts)\n case 'anthropic':\n return factories.createAnthropic(baseOpts)\n case 'openai-compatible':\n return factories.createOpenAICompatible({ name: configSet, ...baseOpts })\n default:\n throw new Error(\n `[ai-sdk-provider-env] Unknown compatible mode \"${compatible}\".`\n + ` Supported values: \"openai\", \"anthropic\", \"openai-compatible\".`\n + ` Set COMPATIBLE=openai-compatible (or omit it) to use the OpenAI-compatible provider.`,\n )\n }\n }\n\n /**\n * Get or create a cached provider for the given config set.\n */\n function getProvider(configSet: string): ProviderV3 {\n const key = configSet.toUpperCase()\n const cached = cache.get(key)\n if (cached)\n return cached\n\n const config = resolveConfig(configSet)\n const provider = createUnderlying(configSet, config)\n cache.set(key, provider)\n return provider\n }\n\n /**\n * Parse a model ID. The first `/` separates the config set name from the actual model ID.\n */\n function parseModelId(modelId: string): { configSet: string, model: string } {\n const slashIndex = modelId.indexOf('/')\n if (slashIndex === -1) {\n throw new Error(\n `[ai-sdk-provider-env] Invalid model ID \"${modelId}\". `\n + `Expected format: \"{configSet}/{modelId}\", e.g. \"zhipu/glm-4\"`,\n )\n }\n return {\n configSet: modelId.slice(0, slashIndex),\n model: modelId.slice(slashIndex + 1),\n }\n }\n\n return {\n specificationVersion: 'v3' as const,\n\n languageModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n return getProvider(configSet).languageModel(model)\n },\n\n embeddingModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n return getProvider(configSet).embeddingModel(model)\n },\n\n imageModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n return getProvider(configSet).imageModel(model)\n },\n\n textEmbeddingModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.textEmbeddingModel) {\n throw new NoSuchModelError({ modelId, modelType: 'embeddingModel' })\n }\n return provider.textEmbeddingModel(model)\n },\n\n transcriptionModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.transcriptionModel) {\n throw new NoSuchModelError({ modelId, modelType: 'transcriptionModel' })\n }\n return provider.transcriptionModel(model)\n },\n\n speechModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.speechModel) {\n throw new NoSuchModelError({ modelId, modelType: 'speechModel' })\n }\n return provider.speechModel(model)\n },\n\n rerankingModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.rerankingModel) {\n throw new NoSuchModelError({ modelId, modelType: 'rerankingModel' })\n }\n return provider.rerankingModel(model)\n },\n }\n}\n\n/**\n * Create a dynamic, environment-variable-driven AI SDK provider.\n *\n * Automatically resolves provider configurations from env var naming conventions,\n * with built-in preset support for quick setup.\n *\n * Env var convention (using config set `ZHIPU` with default separator `_` as example):\n * - `ZHIPU_PRESET` — use a built-in preset (BASE_URL and COMPATIBLE become optional)\n * - `ZHIPU_BASE_URL` — API base URL\n * - `ZHIPU_API_KEY` — API key (required)\n * - `ZHIPU_COMPATIBLE` — compatibility mode (defaults to `'openai-compatible'`)\n * - `ZHIPU_HEADERS` — custom HTTP headers (JSON format)\n *\n * @example\n * ```ts\n * import { createProviderRegistry } from 'ai'\n * import { envProvider } from 'ai-sdk-provider-env'\n *\n * const registry = createProviderRegistry({\n * env: envProvider(),\n * })\n *\n * // Use a preset (only API_KEY is required)\n * // DEEPSEEK_PRESET=deepseek\n * // DEEPSEEK_API_KEY=sk-xxx\n * const model = registry.languageModel('env:deepseek/deepseek-chat')\n *\n * // Specify all parameters manually\n * // MYAPI_BASE_URL=https://api.example.com/v1\n * // MYAPI_API_KEY=xxx\n * const model2 = registry.languageModel('env:myapi/some-model')\n * ```\n */\nexport function envProvider(options: EnvProviderOptions = {}): ProviderV3 {\n return createEnvProvider(defaultFactories, options)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["process","NoSuchModelError"],"sources":["../src/factories.ts","../src/presets.ts","../src/env-provider.ts"],"sourcesContent":["import type { ProviderV3 } from '@ai-sdk/provider'\n\nexport interface ProviderOpts {\n baseURL: string\n apiKey: string\n headers?: Record<string, string>\n fetch?: typeof globalThis.fetch\n}\n\n/**\n * Create an OpenAI provider.\n *\n * Dynamically requires `@ai-sdk/openai`, so it only needs to be installed when actually used.\n */\nexport function createOpenAIProvider(opts: ProviderOpts): ProviderV3 {\n try {\n // eslint-disable-next-line ts/no-require-imports\n const { createOpenAI } = require('@ai-sdk/openai')\n return createOpenAI(opts)\n }\n catch {\n throw new Error(\n '[ai-sdk-provider-env] openai compatibility mode requires @ai-sdk/openai. '\n + 'Run: npm install @ai-sdk/openai',\n )\n }\n}\n\n/**\n * Create an Anthropic provider.\n *\n * Dynamically requires `@ai-sdk/anthropic`, so it only needs to be installed when actually used.\n */\nexport function createAnthropicProvider(opts: ProviderOpts): ProviderV3 {\n try {\n // eslint-disable-next-line ts/no-require-imports\n const { createAnthropic } = require('@ai-sdk/anthropic')\n return createAnthropic(opts)\n }\n catch {\n throw new Error(\n '[ai-sdk-provider-env] anthropic compatibility mode requires @ai-sdk/anthropic. '\n + 'Run: npm install @ai-sdk/anthropic',\n )\n }\n}\n\n/**\n * Create a Google Generative AI (Gemini) provider.\n *\n * Dynamically requires `@ai-sdk/google`, so it only needs to be installed when actually used.\n */\nexport function createGeminiProvider(opts: ProviderOpts): ProviderV3 {\n try {\n // eslint-disable-next-line ts/no-require-imports\n const { createGoogleGenerativeAI } = require('@ai-sdk/google')\n return createGoogleGenerativeAI(opts)\n }\n catch {\n throw new Error(\n '[ai-sdk-provider-env] gemini compatibility mode requires @ai-sdk/google. '\n + 'Run: npm install @ai-sdk/google',\n )\n }\n}\n\n/**\n * Create an OpenAI Compatible provider.\n *\n * Dynamically requires `@ai-sdk/openai-compatible`, so it only needs to be installed when actually used.\n */\nexport function createOpenAICompatibleProvider(opts: ProviderOpts & { name: string }): ProviderV3 {\n try {\n // eslint-disable-next-line ts/no-require-imports\n const { createOpenAICompatible } = require('@ai-sdk/openai-compatible')\n return createOpenAICompatible(opts)\n }\n catch {\n throw new Error(\n '[ai-sdk-provider-env] openai-compatible mode requires @ai-sdk/openai-compatible. '\n + 'Run: npm install @ai-sdk/openai-compatible',\n )\n }\n}\n","import type { PresetConfig } from './types'\n\n/**\n * Built-in preset configurations for common providers.\n *\n * When using a preset, only `{PREFIX}__PRESET` and `{PREFIX}__API_KEY`\n * are required; `BASE_URL` and `COMPATIBLE` are provided by the preset.\n */\nexport const builtinPresets: Record<string, PresetConfig> = {\n // OpenAI\n openai: {\n baseURL: 'https://api.openai.com/v1',\n compatible: 'openai',\n },\n\n // Anthropic\n anthropic: {\n baseURL: 'https://api.anthropic.com',\n compatible: 'anthropic',\n },\n\n // Google AI Studio (Gemini)\n google: {\n baseURL: 'https://generativelanguage.googleapis.com/v1beta',\n compatible: 'gemini',\n },\n\n // DeepSeek\n deepseek: {\n baseURL: 'https://api.deepseek.com',\n compatible: 'openai-compatible',\n },\n\n // Zhipu AI (GLM series)\n zhipu: {\n baseURL: 'https://open.bigmodel.cn/api/paas/v4',\n compatible: 'openai-compatible',\n },\n\n // Groq\n groq: {\n baseURL: 'https://api.groq.com/openai/v1',\n compatible: 'openai-compatible',\n },\n\n // Together AI\n together: {\n baseURL: 'https://api.together.xyz/v1',\n compatible: 'openai-compatible',\n },\n\n // Fireworks AI\n fireworks: {\n baseURL: 'https://api.fireworks.ai/inference/v1',\n compatible: 'openai-compatible',\n },\n\n // Mistral AI\n mistral: {\n baseURL: 'https://api.mistral.ai/v1',\n compatible: 'openai-compatible',\n },\n\n // Moonshot AI\n moonshot: {\n baseURL: 'https://api.moonshot.cn/v1',\n compatible: 'openai-compatible',\n },\n\n // Perplexity\n perplexity: {\n baseURL: 'https://api.perplexity.ai',\n compatible: 'openai-compatible',\n },\n\n // OpenRouter\n openrouter: {\n baseURL: 'https://openrouter.ai/api/v1',\n compatible: 'openai-compatible',\n },\n\n // SiliconFlow\n siliconflow: {\n baseURL: 'https://api.siliconflow.cn/v1',\n compatible: 'openai-compatible',\n },\n}\n","import type { ProviderV3 } from '@ai-sdk/provider'\nimport type { ProviderOpts } from './factories'\nimport type { EnvProviderFactories, EnvProviderOptions } from './types'\nimport process from 'node:process'\nimport { NoSuchModelError } from '@ai-sdk/provider'\nimport { createAnthropicProvider, createGeminiProvider, createOpenAICompatibleProvider, createOpenAIProvider } from './factories'\nimport { builtinPresets } from './presets'\n\n/**\n * Interface for provider factory functions, used for dependency injection.\n *\n * In production, `defaultFactories` delegates to the real SDK implementations.\n * In tests, fake factories can be injected to avoid module mocking.\n */\nexport interface ProviderFactories {\n createOpenAI: (opts: ProviderOpts) => ProviderV3\n createAnthropic: (opts: ProviderOpts) => ProviderV3\n createGemini: (opts: ProviderOpts) => ProviderV3\n createOpenAICompatible: (opts: ProviderOpts & { name: string }) => ProviderV3\n}\n\n/**\n * Default factories that delegate to the real implementations in `factories.ts`.\n */\nconst defaultFactories: ProviderFactories = {\n createOpenAI: createOpenAIProvider,\n createAnthropic: createAnthropicProvider,\n createGemini: createGeminiProvider,\n createOpenAICompatible: createOpenAICompatibleProvider,\n}\n\n/**\n * Internally resolved configuration with all required fields determined.\n */\ninterface ResolvedConfig {\n baseURL: string\n apiKey: string\n compatible: string\n headers?: Record<string, string>\n}\n\n/**\n * Testable core implementation that accepts injected provider factories.\n *\n * In tests, call this function directly with fake factories\n * to avoid module mocking entirely.\n */\nexport function createEnvProvider(\n factories: ProviderFactories,\n options: Omit<EnvProviderOptions, 'factories'> = {},\n): ProviderV3 {\n const separator = options.separator ?? '_'\n const defaultFetch = options.defaults?.fetch\n const defaultHeaders = options.defaults?.headers\n\n // Cache created providers to avoid redundant initialization\n const cache = new Map<string, ProviderV3>()\n\n /**\n * Resolve baseURL and compatible from a preset name.\n */\n function resolvePreset(presetName: string): { baseURL: string, compatible: string } {\n const preset = builtinPresets[presetName]\n if (!preset) {\n const available = Object.keys(builtinPresets).join(', ')\n throw new Error(\n `[ai-sdk-provider-env] Unknown preset \"${presetName}\". Available presets: ${available}`,\n )\n }\n return {\n baseURL: preset.baseURL,\n compatible: preset.compatible ?? 'openai-compatible',\n }\n }\n\n /**\n * Resolve config set configuration from explicit configs, presets, or environment variables.\n */\n function resolveConfig(configSet: string): ResolvedConfig {\n // Explicit configs take precedence over env vars\n if (options.configs?.[configSet]) {\n const config = options.configs[configSet]\n\n // Code-based configs also support presets\n if (config.preset) {\n const preset = resolvePreset(config.preset)\n return {\n baseURL: config.baseURL ?? preset.baseURL,\n apiKey: config.apiKey,\n compatible: config.compatible ?? preset.compatible,\n ...(config.headers && { headers: config.headers }),\n }\n }\n\n if (!config.baseURL) {\n throw new Error(\n `[ai-sdk-provider-env] Missing baseURL in config for \"${configSet}\"`\n + ` (or set preset to use a built-in preset)`,\n )\n }\n\n return {\n baseURL: config.baseURL,\n apiKey: config.apiKey,\n compatible: config.compatible ?? 'openai-compatible',\n ...(config.headers && { headers: config.headers }),\n }\n }\n\n const prefix = configSet.toUpperCase()\n const env = (key: string): string | undefined => process.env[`${prefix}${separator}${key}`]\n\n const apiKey = env('API_KEY')\n if (!apiKey) {\n throw new Error(\n `[ai-sdk-provider-env] Missing env var ${prefix}${separator}API_KEY`,\n )\n }\n\n // Parse headers from env var (JSON format)\n const headersRaw = env('HEADERS')\n let headers: Record<string, string> | undefined\n if (headersRaw) {\n try {\n headers = JSON.parse(headersRaw)\n }\n catch {\n throw new Error(\n `[ai-sdk-provider-env] Invalid JSON in ${prefix}${separator}HEADERS: ${headersRaw}`,\n )\n }\n }\n\n // Check for preset\n const presetName = env('PRESET')\n if (presetName) {\n const preset = resolvePreset(presetName)\n return {\n baseURL: env('BASE_URL') ?? preset.baseURL,\n apiKey,\n compatible: env('COMPATIBLE') ?? preset.compatible,\n ...(headers && { headers }),\n }\n }\n\n // Without a preset, try BASE_URL first\n const baseURL = env('BASE_URL')\n if (baseURL) {\n return {\n baseURL,\n apiKey,\n compatible: env('COMPATIBLE') ?? 'openai-compatible',\n ...(headers && { headers }),\n }\n }\n\n // Auto-detect: if configSet name matches a built-in preset, use it automatically\n if (options.presetAutoDetect !== false) {\n const autoPreset = builtinPresets[configSet.toLowerCase()]\n if (autoPreset) {\n return {\n baseURL: autoPreset.baseURL,\n apiKey,\n compatible: env('COMPATIBLE') ?? autoPreset.compatible ?? 'openai-compatible',\n ...(headers && { headers }),\n }\n }\n }\n\n // Error: neither BASE_URL nor a matching preset found\n const available = Object.keys(builtinPresets).join(', ')\n const presetHint = builtinPresets[configSet.toLowerCase()]\n ? ` (Note: \"${configSet}\" matches a built-in preset, but presetAutoDetect is disabled.)`\n : ''\n throw new Error(\n `[ai-sdk-provider-env] Missing env var ${prefix}${separator}BASE_URL`\n + ` (or set ${prefix}${separator}PRESET to use a preset.`\n + ` Available presets: ${available})${presetHint}`,\n )\n }\n\n /**\n * Create the underlying provider based on the compatibility mode.\n */\n function createUnderlying(configSet: string, config: ResolvedConfig): ProviderV3 {\n const { baseURL, apiKey, compatible, headers } = config\n\n // Merge headers: defaults.headers as base, config-set headers override matching keys\n const mergedHeaders = (defaultHeaders || headers)\n ? { ...defaultHeaders, ...headers }\n : undefined\n\n const baseOpts = {\n baseURL,\n apiKey,\n ...(mergedHeaders && { headers: mergedHeaders }),\n ...(defaultFetch && { fetch: defaultFetch }),\n }\n\n switch (compatible) {\n case 'openai':\n return factories.createOpenAI(baseOpts)\n case 'anthropic':\n return factories.createAnthropic(baseOpts)\n case 'gemini':\n return factories.createGemini(baseOpts)\n case 'openai-compatible':\n return factories.createOpenAICompatible({ name: configSet, ...baseOpts })\n default:\n throw new Error(\n `[ai-sdk-provider-env] Unknown compatible mode \"${compatible}\".`\n + ` Supported values: \"openai\", \"anthropic\", \"gemini\", \"openai-compatible\".`\n + ` Set COMPATIBLE=openai-compatible (or omit it) to use the OpenAI-compatible provider.`,\n )\n }\n }\n\n /**\n * Get or create a cached provider for the given config set.\n */\n function getProvider(configSet: string): ProviderV3 {\n const key = configSet.toUpperCase()\n const cached = cache.get(key)\n if (cached)\n return cached\n\n const config = resolveConfig(configSet)\n const provider = createUnderlying(configSet, config)\n cache.set(key, provider)\n return provider\n }\n\n /**\n * Parse a model ID. The first `/` separates the config set name from the actual model ID.\n */\n function parseModelId(modelId: string): { configSet: string, model: string } {\n const slashIndex = modelId.indexOf('/')\n if (slashIndex === -1) {\n throw new Error(\n `[ai-sdk-provider-env] Invalid model ID \"${modelId}\". `\n + `Expected format: \"{configSet}/{modelId}\", e.g. \"zhipu/glm-4\"`,\n )\n }\n return {\n configSet: modelId.slice(0, slashIndex),\n model: modelId.slice(slashIndex + 1),\n }\n }\n\n return {\n specificationVersion: 'v3' as const,\n\n languageModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n return getProvider(configSet).languageModel(model)\n },\n\n embeddingModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n return getProvider(configSet).embeddingModel(model)\n },\n\n imageModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n return getProvider(configSet).imageModel(model)\n },\n\n textEmbeddingModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.textEmbeddingModel) {\n throw new NoSuchModelError({ modelId, modelType: 'embeddingModel' })\n }\n return provider.textEmbeddingModel(model)\n },\n\n transcriptionModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.transcriptionModel) {\n throw new NoSuchModelError({ modelId, modelType: 'transcriptionModel' })\n }\n return provider.transcriptionModel(model)\n },\n\n speechModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.speechModel) {\n throw new NoSuchModelError({ modelId, modelType: 'speechModel' })\n }\n return provider.speechModel(model)\n },\n\n rerankingModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.rerankingModel) {\n throw new NoSuchModelError({ modelId, modelType: 'rerankingModel' })\n }\n return provider.rerankingModel(model)\n },\n }\n}\n\n/**\n * Build internal `ProviderFactories` from user-provided `EnvProviderFactories`.\n *\n * Uses lazy-strict semantics: each factory slot is only evaluated when actually called.\n * If the user provided a factory for a given compatible mode, it is used;\n * otherwise, a clear error is thrown (no silent fallback to dynamic `require()`).\n */\nfunction buildUserFactories(userFactories: EnvProviderFactories): ProviderFactories {\n function missingFactory(key: string, fnName: string, pkg: string): never {\n throw new Error(\n `[ai-sdk-provider-env] No factory provided for \"${key}\". `\n + `When using the factories option, provide a factory for each compatibility mode you use. `\n + `Add: import { ${fnName} } from '${pkg}' and set factories: { ${key}: ${fnName} }`,\n )\n }\n\n return {\n createOpenAI: opts =>\n userFactories.openai\n ? userFactories.openai(opts)\n : missingFactory('openai', 'createOpenAI', '@ai-sdk/openai'),\n createAnthropic: opts =>\n userFactories.anthropic\n ? userFactories.anthropic(opts)\n : missingFactory('anthropic', 'createAnthropic', '@ai-sdk/anthropic'),\n createGemini: opts =>\n userFactories.gemini\n ? userFactories.gemini(opts)\n : missingFactory('gemini', 'createGoogleGenerativeAI', '@ai-sdk/google'),\n createOpenAICompatible: opts =>\n userFactories.openaiCompatible\n ? userFactories.openaiCompatible(opts)\n : missingFactory('openaiCompatible', 'createOpenAICompatible', '@ai-sdk/openai-compatible'),\n }\n}\n\n/**\n * Create a dynamic, environment-variable-driven AI SDK provider.\n *\n * Automatically resolves provider configurations from env var naming conventions,\n * with built-in preset support for quick setup.\n *\n * Env var convention (using config set `ZHIPU` with default separator `_` as example):\n * - `ZHIPU_PRESET` — use a built-in preset (BASE_URL and COMPATIBLE become optional)\n * - `ZHIPU_BASE_URL` — API base URL\n * - `ZHIPU_API_KEY` — API key (required)\n * - `ZHIPU_COMPATIBLE` — compatibility mode (defaults to `'openai-compatible'`)\n * - `ZHIPU_HEADERS` — custom HTTP headers (JSON format)\n *\n * @example\n * ```ts\n * import { createProviderRegistry } from 'ai'\n * import { envProvider } from 'ai-sdk-provider-env'\n *\n * const registry = createProviderRegistry({\n * env: envProvider(),\n * })\n *\n * // Use a preset (only API_KEY is required)\n * // DEEPSEEK_PRESET=deepseek\n * // DEEPSEEK_API_KEY=sk-xxx\n * const model = registry.languageModel('env:deepseek/deepseek-chat')\n *\n * // Specify all parameters manually\n * // MYAPI_BASE_URL=https://api.example.com/v1\n * // MYAPI_API_KEY=xxx\n * const model2 = registry.languageModel('env:myapi/some-model')\n * ```\n *\n * @example Bundler-safe usage with explicit factories\n * ```ts\n * import { createOpenAI } from '@ai-sdk/openai'\n * import { envProvider } from 'ai-sdk-provider-env'\n *\n * const provider = envProvider({\n * factories: { openai: createOpenAI },\n * })\n * ```\n */\nexport function envProvider(options: EnvProviderOptions = {}): ProviderV3 {\n const factories = options.factories\n ? buildUserFactories(options.factories)\n : defaultFactories\n return createEnvProvider(factories, options)\n}\n"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as _ai_sdk_provider0 from "@ai-sdk/provider";
|
|
1
2
|
import { ProviderV3 } from "@ai-sdk/provider";
|
|
2
3
|
|
|
3
4
|
//#region src/types.d.ts
|
|
@@ -23,9 +24,10 @@ interface ConfigSetEntry {
|
|
|
23
24
|
*
|
|
24
25
|
* - `'openai'` — uses `createOpenAI`
|
|
25
26
|
* - `'anthropic'` — uses `createAnthropic`
|
|
27
|
+
* - `'gemini'` — uses `createGoogleGenerativeAI`
|
|
26
28
|
* - `'openai-compatible'` — uses `createOpenAICompatible` with the config set name as the provider name (default)
|
|
27
29
|
*/
|
|
28
|
-
compatible?: 'openai' | 'anthropic' | 'openai-compatible';
|
|
30
|
+
compatible?: 'openai' | 'anthropic' | 'gemini' | 'openai-compatible';
|
|
29
31
|
/**
|
|
30
32
|
* Custom HTTP headers appended to API requests.
|
|
31
33
|
*
|
|
@@ -47,9 +49,10 @@ interface PresetConfig {
|
|
|
47
49
|
*
|
|
48
50
|
* - `'openai'` — uses `createOpenAI`
|
|
49
51
|
* - `'anthropic'` — uses `createAnthropic`
|
|
52
|
+
* - `'gemini'` — uses `createGoogleGenerativeAI`
|
|
50
53
|
* - `'openai-compatible'` — uses `createOpenAICompatible` with the config set name as the provider name (default)
|
|
51
54
|
*/
|
|
52
|
-
compatible?: 'openai' | 'anthropic' | 'openai-compatible';
|
|
55
|
+
compatible?: 'openai' | 'anthropic' | 'gemini' | 'openai-compatible';
|
|
53
56
|
}
|
|
54
57
|
/**
|
|
55
58
|
* Global defaults for `envProvider()`.
|
|
@@ -81,6 +84,63 @@ interface EnvProviderDefaults {
|
|
|
81
84
|
*/
|
|
82
85
|
headers?: Record<string, string>;
|
|
83
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Options passed to user-provided factory functions.
|
|
89
|
+
*
|
|
90
|
+
* This is the library's own type — it does NOT reference any optional peer dependency types,
|
|
91
|
+
* so your `.d.ts` output won't force consumers to install `@ai-sdk/*` packages.
|
|
92
|
+
*/
|
|
93
|
+
interface EnvProviderFactoryOptions {
|
|
94
|
+
/** API base URL */
|
|
95
|
+
baseURL: string;
|
|
96
|
+
/** API key */
|
|
97
|
+
apiKey: string;
|
|
98
|
+
/** Custom HTTP headers */
|
|
99
|
+
headers?: Record<string, string>;
|
|
100
|
+
/** Custom fetch implementation */
|
|
101
|
+
fetch?: typeof globalThis.fetch;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Options passed to the `openai-compatible` factory function.
|
|
105
|
+
*
|
|
106
|
+
* Extends {@link EnvProviderFactoryOptions} with a `name` field
|
|
107
|
+
* that identifies the config set (used as the provider name).
|
|
108
|
+
*/
|
|
109
|
+
interface EnvProviderNamedFactoryOptions extends EnvProviderFactoryOptions {
|
|
110
|
+
/** Config set name, used as the provider name */
|
|
111
|
+
name: string;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* User-provided factory functions for bundler-safe provider creation.
|
|
115
|
+
*
|
|
116
|
+
* When using a bundler (e.g. `bun build --compile`), dynamic `require()` calls
|
|
117
|
+
* cannot resolve optional peer dependencies. Providing factories via static imports
|
|
118
|
+
* allows the bundler to trace and include only the providers you actually use.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```ts
|
|
122
|
+
* import { createOpenAI } from '@ai-sdk/openai'
|
|
123
|
+
* import { createAnthropic } from '@ai-sdk/anthropic'
|
|
124
|
+
* import { envProvider } from 'ai-sdk-provider-env'
|
|
125
|
+
*
|
|
126
|
+
* const provider = envProvider({
|
|
127
|
+
* factories: {
|
|
128
|
+
* openai: createOpenAI,
|
|
129
|
+
* anthropic: createAnthropic,
|
|
130
|
+
* },
|
|
131
|
+
* })
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
interface EnvProviderFactories {
|
|
135
|
+
/** Factory for `compatible: 'openai'` — e.g. pass `createOpenAI` from `@ai-sdk/openai` */
|
|
136
|
+
openai?: (options: EnvProviderFactoryOptions) => _ai_sdk_provider0.ProviderV3;
|
|
137
|
+
/** Factory for `compatible: 'anthropic'` — e.g. pass `createAnthropic` from `@ai-sdk/anthropic` */
|
|
138
|
+
anthropic?: (options: EnvProviderFactoryOptions) => _ai_sdk_provider0.ProviderV3;
|
|
139
|
+
/** Factory for `compatible: 'gemini'` — e.g. pass `createGoogleGenerativeAI` from `@ai-sdk/google` */
|
|
140
|
+
gemini?: (options: EnvProviderFactoryOptions) => _ai_sdk_provider0.ProviderV3;
|
|
141
|
+
/** Factory for `compatible: 'openai-compatible'` — e.g. pass `createOpenAICompatible` from `@ai-sdk/openai-compatible` */
|
|
142
|
+
openaiCompatible?: (options: EnvProviderNamedFactoryOptions) => _ai_sdk_provider0.ProviderV3;
|
|
143
|
+
}
|
|
84
144
|
/**
|
|
85
145
|
* Options for `envProvider()`.
|
|
86
146
|
*/
|
|
@@ -133,6 +193,43 @@ interface EnvProviderOptions {
|
|
|
133
193
|
* })
|
|
134
194
|
*/
|
|
135
195
|
defaults?: EnvProviderDefaults;
|
|
196
|
+
/**
|
|
197
|
+
* Automatically use a built-in preset when the config set name matches a preset name.
|
|
198
|
+
*
|
|
199
|
+
* When enabled (default), if a config set name matches a built-in preset name (e.g., `openai`, `anthropic`, `deepseek`),
|
|
200
|
+
* that preset is automatically applied without requiring the `{PREFIX}_PRESET` environment variable.
|
|
201
|
+
* Set to `false` to disable this behavior and require explicit preset configuration.
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* // With presetAutoDetect enabled (default):
|
|
205
|
+
* // OPENAI_API_KEY=sk-xxx
|
|
206
|
+
* // → automatically uses the 'openai' preset
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* // With presetAutoDetect disabled:
|
|
210
|
+
* // OPENAI_API_KEY=sk-xxx
|
|
211
|
+
* // OPENAI_PRESET=openai (required)
|
|
212
|
+
* envProvider({ presetAutoDetect: false })
|
|
213
|
+
*/
|
|
214
|
+
presetAutoDetect?: boolean;
|
|
215
|
+
/**
|
|
216
|
+
* User-provided factory functions for bundler-safe provider creation.
|
|
217
|
+
*
|
|
218
|
+
* When set, the library uses these factories instead of dynamic `require()` calls.
|
|
219
|
+
* Only provide factories for the compatibility modes you actually use —
|
|
220
|
+
* a clear error is thrown if a missing factory is needed at runtime.
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```ts
|
|
224
|
+
* import { createOpenAI } from '@ai-sdk/openai'
|
|
225
|
+
* import { envProvider } from 'ai-sdk-provider-env'
|
|
226
|
+
*
|
|
227
|
+
* const provider = envProvider({
|
|
228
|
+
* factories: { openai: createOpenAI },
|
|
229
|
+
* })
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
232
|
+
factories?: EnvProviderFactories;
|
|
136
233
|
}
|
|
137
234
|
//#endregion
|
|
138
235
|
//#region src/env-provider.d.ts
|
|
@@ -168,6 +265,16 @@ interface EnvProviderOptions {
|
|
|
168
265
|
* // MYAPI_API_KEY=xxx
|
|
169
266
|
* const model2 = registry.languageModel('env:myapi/some-model')
|
|
170
267
|
* ```
|
|
268
|
+
*
|
|
269
|
+
* @example Bundler-safe usage with explicit factories
|
|
270
|
+
* ```ts
|
|
271
|
+
* import { createOpenAI } from '@ai-sdk/openai'
|
|
272
|
+
* import { envProvider } from 'ai-sdk-provider-env'
|
|
273
|
+
*
|
|
274
|
+
* const provider = envProvider({
|
|
275
|
+
* factories: { openai: createOpenAI },
|
|
276
|
+
* })
|
|
277
|
+
* ```
|
|
171
278
|
*/
|
|
172
279
|
declare function envProvider(options?: EnvProviderOptions): ProviderV3;
|
|
173
280
|
//#endregion
|
|
@@ -180,5 +287,5 @@ declare function envProvider(options?: EnvProviderOptions): ProviderV3;
|
|
|
180
287
|
*/
|
|
181
288
|
declare const builtinPresets: Record<string, PresetConfig>;
|
|
182
289
|
//#endregion
|
|
183
|
-
export { type ConfigSetEntry, type EnvProviderDefaults, type EnvProviderOptions, type PresetConfig, builtinPresets, envProvider };
|
|
290
|
+
export { type ConfigSetEntry, type EnvProviderDefaults, type EnvProviderFactories, type EnvProviderFactoryOptions, type EnvProviderNamedFactoryOptions, type EnvProviderOptions, type PresetConfig, builtinPresets, envProvider };
|
|
184
291
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/env-provider.ts","../src/presets.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/env-provider.ts","../src/presets.ts"],"mappings":";;;;;;;;AAMA;;UAAiB,cAAA;EA0BC;EAxBhB,MAAA;EAMA;;;;;EAAA,MAAA;EAkBgB;EAhBhB,OAAA;EAwB2B;;;;AAmB7B;;;;EAlCE,UAAA;EA2Ce;;;;;;EApCf,OAAA,GAAU,MAAA;AAAA;;;;;;UAQK,YAAA;EA4Df;EA1DA,OAAA;EA0D0B;;;AAS5B;;;;;EA1DE,UAAA;AAAA;;;;;;UAQe,mBAAA;EAkF6B;;;;;;;;EAzE5C,KAAA,UAAe,UAAA,CAAW,KAAA;EAuE1B;;;;;;;;;;;;;EAxDA,OAAA,GAAU,MAAA;AAAA;;;;;;;UASK,yBAAA;EAkJiB;EAhJhC,OAAA;EAyFA;EAvFA,MAAA;EAuFyB;EArFzB,OAAA,GAAU,MAAA;EAqGC;EAnGX,KAAA,UAAe,UAAA,CAAW,KAAA;AAAA;;;;;;;UASX,8BAAA,SAAuC,yBAAA;ECmR7B;EDjRzB,IAAA;AAAA;;;;;;;;;AEvGF;;;;;;;;;;;;;UF+HiB,oBAAA;;EAEf,MAAA,IAAU,OAAA,EAAS,yBAAA,KAAyB,iBAAA,CAAgC,UAAA;;EAE5E,SAAA,IAAa,OAAA,EAAS,yBAAA,KAAyB,iBAAA,CAAgC,UAAA;;EAE/E,MAAA,IAAU,OAAA,EAAS,yBAAA,KAAyB,iBAAA,CAAgC,UAAA;;EAE5E,gBAAA,IAAoB,OAAA,EAAS,8BAAA,KAA8B,iBAAA,CAAgC,UAAA;AAAA;;;;UAM5E,kBAAA;;;;;;;;;;;;;;EAcf,SAAA;;;;;;;;;;;;;;;;;;;EAoBA,OAAA,GAAU,MAAA,SAAe,cAAA;;;;;;;;;;;;;;;EAgBzB,QAAA,GAAW,mBAAA;;;;;;;;;;;;;;;;;;;EAoBX,gBAAA;;;;;;;;;;;;;;;;;;EAmBA,SAAA,GAAY,oBAAA;AAAA;;;;;;;;;;;AAlJd;;;;;;;;;;;;;AAiBA;;;;;AA0BA;;;;;;;;;;;;;;;;;iBCyPgB,WAAA,CAAY,OAAA,GAAS,kBAAA,GAA0B,UAAA;;;;;;AD1X/D;;;cEEa,cAAA,EAAgB,MAAA,SAAe,YAAA"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as _ai_sdk_provider0 from "@ai-sdk/provider";
|
|
1
2
|
import { ProviderV3 } from "@ai-sdk/provider";
|
|
2
3
|
|
|
3
4
|
//#region src/types.d.ts
|
|
@@ -23,9 +24,10 @@ interface ConfigSetEntry {
|
|
|
23
24
|
*
|
|
24
25
|
* - `'openai'` — uses `createOpenAI`
|
|
25
26
|
* - `'anthropic'` — uses `createAnthropic`
|
|
27
|
+
* - `'gemini'` — uses `createGoogleGenerativeAI`
|
|
26
28
|
* - `'openai-compatible'` — uses `createOpenAICompatible` with the config set name as the provider name (default)
|
|
27
29
|
*/
|
|
28
|
-
compatible?: 'openai' | 'anthropic' | 'openai-compatible';
|
|
30
|
+
compatible?: 'openai' | 'anthropic' | 'gemini' | 'openai-compatible';
|
|
29
31
|
/**
|
|
30
32
|
* Custom HTTP headers appended to API requests.
|
|
31
33
|
*
|
|
@@ -47,9 +49,10 @@ interface PresetConfig {
|
|
|
47
49
|
*
|
|
48
50
|
* - `'openai'` — uses `createOpenAI`
|
|
49
51
|
* - `'anthropic'` — uses `createAnthropic`
|
|
52
|
+
* - `'gemini'` — uses `createGoogleGenerativeAI`
|
|
50
53
|
* - `'openai-compatible'` — uses `createOpenAICompatible` with the config set name as the provider name (default)
|
|
51
54
|
*/
|
|
52
|
-
compatible?: 'openai' | 'anthropic' | 'openai-compatible';
|
|
55
|
+
compatible?: 'openai' | 'anthropic' | 'gemini' | 'openai-compatible';
|
|
53
56
|
}
|
|
54
57
|
/**
|
|
55
58
|
* Global defaults for `envProvider()`.
|
|
@@ -81,6 +84,63 @@ interface EnvProviderDefaults {
|
|
|
81
84
|
*/
|
|
82
85
|
headers?: Record<string, string>;
|
|
83
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Options passed to user-provided factory functions.
|
|
89
|
+
*
|
|
90
|
+
* This is the library's own type — it does NOT reference any optional peer dependency types,
|
|
91
|
+
* so your `.d.ts` output won't force consumers to install `@ai-sdk/*` packages.
|
|
92
|
+
*/
|
|
93
|
+
interface EnvProviderFactoryOptions {
|
|
94
|
+
/** API base URL */
|
|
95
|
+
baseURL: string;
|
|
96
|
+
/** API key */
|
|
97
|
+
apiKey: string;
|
|
98
|
+
/** Custom HTTP headers */
|
|
99
|
+
headers?: Record<string, string>;
|
|
100
|
+
/** Custom fetch implementation */
|
|
101
|
+
fetch?: typeof globalThis.fetch;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Options passed to the `openai-compatible` factory function.
|
|
105
|
+
*
|
|
106
|
+
* Extends {@link EnvProviderFactoryOptions} with a `name` field
|
|
107
|
+
* that identifies the config set (used as the provider name).
|
|
108
|
+
*/
|
|
109
|
+
interface EnvProviderNamedFactoryOptions extends EnvProviderFactoryOptions {
|
|
110
|
+
/** Config set name, used as the provider name */
|
|
111
|
+
name: string;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* User-provided factory functions for bundler-safe provider creation.
|
|
115
|
+
*
|
|
116
|
+
* When using a bundler (e.g. `bun build --compile`), dynamic `require()` calls
|
|
117
|
+
* cannot resolve optional peer dependencies. Providing factories via static imports
|
|
118
|
+
* allows the bundler to trace and include only the providers you actually use.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```ts
|
|
122
|
+
* import { createOpenAI } from '@ai-sdk/openai'
|
|
123
|
+
* import { createAnthropic } from '@ai-sdk/anthropic'
|
|
124
|
+
* import { envProvider } from 'ai-sdk-provider-env'
|
|
125
|
+
*
|
|
126
|
+
* const provider = envProvider({
|
|
127
|
+
* factories: {
|
|
128
|
+
* openai: createOpenAI,
|
|
129
|
+
* anthropic: createAnthropic,
|
|
130
|
+
* },
|
|
131
|
+
* })
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
interface EnvProviderFactories {
|
|
135
|
+
/** Factory for `compatible: 'openai'` — e.g. pass `createOpenAI` from `@ai-sdk/openai` */
|
|
136
|
+
openai?: (options: EnvProviderFactoryOptions) => _ai_sdk_provider0.ProviderV3;
|
|
137
|
+
/** Factory for `compatible: 'anthropic'` — e.g. pass `createAnthropic` from `@ai-sdk/anthropic` */
|
|
138
|
+
anthropic?: (options: EnvProviderFactoryOptions) => _ai_sdk_provider0.ProviderV3;
|
|
139
|
+
/** Factory for `compatible: 'gemini'` — e.g. pass `createGoogleGenerativeAI` from `@ai-sdk/google` */
|
|
140
|
+
gemini?: (options: EnvProviderFactoryOptions) => _ai_sdk_provider0.ProviderV3;
|
|
141
|
+
/** Factory for `compatible: 'openai-compatible'` — e.g. pass `createOpenAICompatible` from `@ai-sdk/openai-compatible` */
|
|
142
|
+
openaiCompatible?: (options: EnvProviderNamedFactoryOptions) => _ai_sdk_provider0.ProviderV3;
|
|
143
|
+
}
|
|
84
144
|
/**
|
|
85
145
|
* Options for `envProvider()`.
|
|
86
146
|
*/
|
|
@@ -133,6 +193,43 @@ interface EnvProviderOptions {
|
|
|
133
193
|
* })
|
|
134
194
|
*/
|
|
135
195
|
defaults?: EnvProviderDefaults;
|
|
196
|
+
/**
|
|
197
|
+
* Automatically use a built-in preset when the config set name matches a preset name.
|
|
198
|
+
*
|
|
199
|
+
* When enabled (default), if a config set name matches a built-in preset name (e.g., `openai`, `anthropic`, `deepseek`),
|
|
200
|
+
* that preset is automatically applied without requiring the `{PREFIX}_PRESET` environment variable.
|
|
201
|
+
* Set to `false` to disable this behavior and require explicit preset configuration.
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* // With presetAutoDetect enabled (default):
|
|
205
|
+
* // OPENAI_API_KEY=sk-xxx
|
|
206
|
+
* // → automatically uses the 'openai' preset
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* // With presetAutoDetect disabled:
|
|
210
|
+
* // OPENAI_API_KEY=sk-xxx
|
|
211
|
+
* // OPENAI_PRESET=openai (required)
|
|
212
|
+
* envProvider({ presetAutoDetect: false })
|
|
213
|
+
*/
|
|
214
|
+
presetAutoDetect?: boolean;
|
|
215
|
+
/**
|
|
216
|
+
* User-provided factory functions for bundler-safe provider creation.
|
|
217
|
+
*
|
|
218
|
+
* When set, the library uses these factories instead of dynamic `require()` calls.
|
|
219
|
+
* Only provide factories for the compatibility modes you actually use —
|
|
220
|
+
* a clear error is thrown if a missing factory is needed at runtime.
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```ts
|
|
224
|
+
* import { createOpenAI } from '@ai-sdk/openai'
|
|
225
|
+
* import { envProvider } from 'ai-sdk-provider-env'
|
|
226
|
+
*
|
|
227
|
+
* const provider = envProvider({
|
|
228
|
+
* factories: { openai: createOpenAI },
|
|
229
|
+
* })
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
232
|
+
factories?: EnvProviderFactories;
|
|
136
233
|
}
|
|
137
234
|
//#endregion
|
|
138
235
|
//#region src/env-provider.d.ts
|
|
@@ -168,6 +265,16 @@ interface EnvProviderOptions {
|
|
|
168
265
|
* // MYAPI_API_KEY=xxx
|
|
169
266
|
* const model2 = registry.languageModel('env:myapi/some-model')
|
|
170
267
|
* ```
|
|
268
|
+
*
|
|
269
|
+
* @example Bundler-safe usage with explicit factories
|
|
270
|
+
* ```ts
|
|
271
|
+
* import { createOpenAI } from '@ai-sdk/openai'
|
|
272
|
+
* import { envProvider } from 'ai-sdk-provider-env'
|
|
273
|
+
*
|
|
274
|
+
* const provider = envProvider({
|
|
275
|
+
* factories: { openai: createOpenAI },
|
|
276
|
+
* })
|
|
277
|
+
* ```
|
|
171
278
|
*/
|
|
172
279
|
declare function envProvider(options?: EnvProviderOptions): ProviderV3;
|
|
173
280
|
//#endregion
|
|
@@ -180,5 +287,5 @@ declare function envProvider(options?: EnvProviderOptions): ProviderV3;
|
|
|
180
287
|
*/
|
|
181
288
|
declare const builtinPresets: Record<string, PresetConfig>;
|
|
182
289
|
//#endregion
|
|
183
|
-
export { type ConfigSetEntry, type EnvProviderDefaults, type EnvProviderOptions, type PresetConfig, builtinPresets, envProvider };
|
|
290
|
+
export { type ConfigSetEntry, type EnvProviderDefaults, type EnvProviderFactories, type EnvProviderFactoryOptions, type EnvProviderNamedFactoryOptions, type EnvProviderOptions, type PresetConfig, builtinPresets, envProvider };
|
|
184
291
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/env-provider.ts","../src/presets.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/env-provider.ts","../src/presets.ts"],"mappings":";;;;;;;;AAMA;;UAAiB,cAAA;EA0BC;EAxBhB,MAAA;EAMA;;;;;EAAA,MAAA;EAkBgB;EAhBhB,OAAA;EAwB2B;;;;AAmB7B;;;;EAlCE,UAAA;EA2Ce;;;;;;EApCf,OAAA,GAAU,MAAA;AAAA;;;;;;UAQK,YAAA;EA4Df;EA1DA,OAAA;EA0D0B;;;AAS5B;;;;;EA1DE,UAAA;AAAA;;;;;;UAQe,mBAAA;EAkF6B;;;;;;;;EAzE5C,KAAA,UAAe,UAAA,CAAW,KAAA;EAuE1B;;;;;;;;;;;;;EAxDA,OAAA,GAAU,MAAA;AAAA;;;;;;;UASK,yBAAA;EAkJiB;EAhJhC,OAAA;EAyFA;EAvFA,MAAA;EAuFyB;EArFzB,OAAA,GAAU,MAAA;EAqGC;EAnGX,KAAA,UAAe,UAAA,CAAW,KAAA;AAAA;;;;;;;UASX,8BAAA,SAAuC,yBAAA;ECmR7B;EDjRzB,IAAA;AAAA;;;;;;;;;AEvGF;;;;;;;;;;;;;UF+HiB,oBAAA;;EAEf,MAAA,IAAU,OAAA,EAAS,yBAAA,KAAyB,iBAAA,CAAgC,UAAA;;EAE5E,SAAA,IAAa,OAAA,EAAS,yBAAA,KAAyB,iBAAA,CAAgC,UAAA;;EAE/E,MAAA,IAAU,OAAA,EAAS,yBAAA,KAAyB,iBAAA,CAAgC,UAAA;;EAE5E,gBAAA,IAAoB,OAAA,EAAS,8BAAA,KAA8B,iBAAA,CAAgC,UAAA;AAAA;;;;UAM5E,kBAAA;;;;;;;;;;;;;;EAcf,SAAA;;;;;;;;;;;;;;;;;;;EAoBA,OAAA,GAAU,MAAA,SAAe,cAAA;;;;;;;;;;;;;;;EAgBzB,QAAA,GAAW,mBAAA;;;;;;;;;;;;;;;;;;;EAoBX,gBAAA;;;;;;;;;;;;;;;;;;EAmBA,SAAA,GAAY,oBAAA;AAAA;;;;;;;;;;;AAlJd;;;;;;;;;;;;;AAiBA;;;;;AA0BA;;;;;;;;;;;;;;;;;iBCyPgB,WAAA,CAAY,OAAA,GAAS,kBAAA,GAA0B,UAAA;;;;;;AD1X/D;;;cEEa,cAAA,EAAgB,MAAA,SAAe,YAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -34,6 +34,19 @@ function createAnthropicProvider(opts) {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
|
+
* Create a Google Generative AI (Gemini) provider.
|
|
38
|
+
*
|
|
39
|
+
* Dynamically requires `@ai-sdk/google`, so it only needs to be installed when actually used.
|
|
40
|
+
*/
|
|
41
|
+
function createGeminiProvider(opts) {
|
|
42
|
+
try {
|
|
43
|
+
const { createGoogleGenerativeAI } = __require("@ai-sdk/google");
|
|
44
|
+
return createGoogleGenerativeAI(opts);
|
|
45
|
+
} catch {
|
|
46
|
+
throw new Error("[ai-sdk-provider-env] gemini compatibility mode requires @ai-sdk/google. Run: npm install @ai-sdk/google");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
37
50
|
* Create an OpenAI Compatible provider.
|
|
38
51
|
*
|
|
39
52
|
* Dynamically requires `@ai-sdk/openai-compatible`, so it only needs to be installed when actually used.
|
|
@@ -64,6 +77,10 @@ const builtinPresets = {
|
|
|
64
77
|
baseURL: "https://api.anthropic.com",
|
|
65
78
|
compatible: "anthropic"
|
|
66
79
|
},
|
|
80
|
+
google: {
|
|
81
|
+
baseURL: "https://generativelanguage.googleapis.com/v1beta",
|
|
82
|
+
compatible: "gemini"
|
|
83
|
+
},
|
|
67
84
|
deepseek: {
|
|
68
85
|
baseURL: "https://api.deepseek.com",
|
|
69
86
|
compatible: "openai-compatible"
|
|
@@ -114,6 +131,7 @@ const builtinPresets = {
|
|
|
114
131
|
const defaultFactories = {
|
|
115
132
|
createOpenAI: createOpenAIProvider,
|
|
116
133
|
createAnthropic: createAnthropicProvider,
|
|
134
|
+
createGemini: createGeminiProvider,
|
|
117
135
|
createOpenAICompatible: createOpenAICompatibleProvider
|
|
118
136
|
};
|
|
119
137
|
/**
|
|
@@ -186,13 +204,24 @@ function createEnvProvider(factories, options = {}) {
|
|
|
186
204
|
};
|
|
187
205
|
}
|
|
188
206
|
const baseURL = env("BASE_URL");
|
|
189
|
-
if (
|
|
190
|
-
return {
|
|
207
|
+
if (baseURL) return {
|
|
191
208
|
baseURL,
|
|
192
209
|
apiKey,
|
|
193
210
|
compatible: env("COMPATIBLE") ?? "openai-compatible",
|
|
194
211
|
...headers && { headers }
|
|
195
212
|
};
|
|
213
|
+
if (options.presetAutoDetect !== false) {
|
|
214
|
+
const autoPreset = builtinPresets[configSet.toLowerCase()];
|
|
215
|
+
if (autoPreset) return {
|
|
216
|
+
baseURL: autoPreset.baseURL,
|
|
217
|
+
apiKey,
|
|
218
|
+
compatible: env("COMPATIBLE") ?? autoPreset.compatible ?? "openai-compatible",
|
|
219
|
+
...headers && { headers }
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
const available = Object.keys(builtinPresets).join(", ");
|
|
223
|
+
const presetHint = builtinPresets[configSet.toLowerCase()] ? ` (Note: "${configSet}" matches a built-in preset, but presetAutoDetect is disabled.)` : "";
|
|
224
|
+
throw new Error(`[ai-sdk-provider-env] Missing env var ${prefix}${separator}BASE_URL (or set ${prefix}${separator}PRESET to use a preset. Available presets: ${available})${presetHint}`);
|
|
196
225
|
}
|
|
197
226
|
/**
|
|
198
227
|
* Create the underlying provider based on the compatibility mode.
|
|
@@ -212,11 +241,12 @@ function createEnvProvider(factories, options = {}) {
|
|
|
212
241
|
switch (compatible) {
|
|
213
242
|
case "openai": return factories.createOpenAI(baseOpts);
|
|
214
243
|
case "anthropic": return factories.createAnthropic(baseOpts);
|
|
244
|
+
case "gemini": return factories.createGemini(baseOpts);
|
|
215
245
|
case "openai-compatible": return factories.createOpenAICompatible({
|
|
216
246
|
name: configSet,
|
|
217
247
|
...baseOpts
|
|
218
248
|
});
|
|
219
|
-
default: throw new Error(`[ai-sdk-provider-env] Unknown compatible mode "${compatible}". Supported values: "openai", "anthropic", "openai-compatible". Set COMPATIBLE=openai-compatible (or omit it) to use the OpenAI-compatible provider.`);
|
|
249
|
+
default: throw new Error(`[ai-sdk-provider-env] Unknown compatible mode "${compatible}". Supported values: "openai", "anthropic", "gemini", "openai-compatible". Set COMPATIBLE=openai-compatible (or omit it) to use the OpenAI-compatible provider.`);
|
|
220
250
|
}
|
|
221
251
|
}
|
|
222
252
|
/**
|
|
@@ -294,6 +324,24 @@ function createEnvProvider(factories, options = {}) {
|
|
|
294
324
|
};
|
|
295
325
|
}
|
|
296
326
|
/**
|
|
327
|
+
* Build internal `ProviderFactories` from user-provided `EnvProviderFactories`.
|
|
328
|
+
*
|
|
329
|
+
* Uses lazy-strict semantics: each factory slot is only evaluated when actually called.
|
|
330
|
+
* If the user provided a factory for a given compatible mode, it is used;
|
|
331
|
+
* otherwise, a clear error is thrown (no silent fallback to dynamic `require()`).
|
|
332
|
+
*/
|
|
333
|
+
function buildUserFactories(userFactories) {
|
|
334
|
+
function missingFactory(key, fnName, pkg) {
|
|
335
|
+
throw new Error(`[ai-sdk-provider-env] No factory provided for "${key}". When using the factories option, provide a factory for each compatibility mode you use. Add: import { ${fnName} } from '${pkg}' and set factories: { ${key}: ${fnName} }`);
|
|
336
|
+
}
|
|
337
|
+
return {
|
|
338
|
+
createOpenAI: (opts) => userFactories.openai ? userFactories.openai(opts) : missingFactory("openai", "createOpenAI", "@ai-sdk/openai"),
|
|
339
|
+
createAnthropic: (opts) => userFactories.anthropic ? userFactories.anthropic(opts) : missingFactory("anthropic", "createAnthropic", "@ai-sdk/anthropic"),
|
|
340
|
+
createGemini: (opts) => userFactories.gemini ? userFactories.gemini(opts) : missingFactory("gemini", "createGoogleGenerativeAI", "@ai-sdk/google"),
|
|
341
|
+
createOpenAICompatible: (opts) => userFactories.openaiCompatible ? userFactories.openaiCompatible(opts) : missingFactory("openaiCompatible", "createOpenAICompatible", "@ai-sdk/openai-compatible")
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
297
345
|
* Create a dynamic, environment-variable-driven AI SDK provider.
|
|
298
346
|
*
|
|
299
347
|
* Automatically resolves provider configurations from env var naming conventions,
|
|
@@ -325,9 +373,19 @@ function createEnvProvider(factories, options = {}) {
|
|
|
325
373
|
* // MYAPI_API_KEY=xxx
|
|
326
374
|
* const model2 = registry.languageModel('env:myapi/some-model')
|
|
327
375
|
* ```
|
|
376
|
+
*
|
|
377
|
+
* @example Bundler-safe usage with explicit factories
|
|
378
|
+
* ```ts
|
|
379
|
+
* import { createOpenAI } from '@ai-sdk/openai'
|
|
380
|
+
* import { envProvider } from 'ai-sdk-provider-env'
|
|
381
|
+
*
|
|
382
|
+
* const provider = envProvider({
|
|
383
|
+
* factories: { openai: createOpenAI },
|
|
384
|
+
* })
|
|
385
|
+
* ```
|
|
328
386
|
*/
|
|
329
387
|
function envProvider(options = {}) {
|
|
330
|
-
return createEnvProvider(defaultFactories, options);
|
|
388
|
+
return createEnvProvider(options.factories ? buildUserFactories(options.factories) : defaultFactories, options);
|
|
331
389
|
}
|
|
332
390
|
|
|
333
391
|
//#endregion
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/factories.ts","../src/presets.ts","../src/env-provider.ts"],"sourcesContent":["import type { ProviderV3 } from '@ai-sdk/provider'\n\nexport interface ProviderOpts {\n baseURL: string\n apiKey: string\n headers?: Record<string, string>\n fetch?: typeof globalThis.fetch\n}\n\n/**\n * Create an OpenAI provider.\n *\n * Dynamically requires `@ai-sdk/openai`, so it only needs to be installed when actually used.\n */\nexport function createOpenAIProvider(opts: ProviderOpts): ProviderV3 {\n try {\n // eslint-disable-next-line ts/no-require-imports\n const { createOpenAI } = require('@ai-sdk/openai')\n return createOpenAI(opts)\n }\n catch {\n throw new Error(\n '[ai-sdk-provider-env] openai compatibility mode requires @ai-sdk/openai. '\n + 'Run: npm install @ai-sdk/openai',\n )\n }\n}\n\n/**\n * Create an Anthropic provider.\n *\n * Dynamically requires `@ai-sdk/anthropic`, so it only needs to be installed when actually used.\n */\nexport function createAnthropicProvider(opts: ProviderOpts): ProviderV3 {\n try {\n // eslint-disable-next-line ts/no-require-imports\n const { createAnthropic } = require('@ai-sdk/anthropic')\n return createAnthropic(opts)\n }\n catch {\n throw new Error(\n '[ai-sdk-provider-env] anthropic compatibility mode requires @ai-sdk/anthropic. '\n + 'Run: npm install @ai-sdk/anthropic',\n )\n }\n}\n\n/**\n * Create an OpenAI Compatible provider.\n *\n * Dynamically requires `@ai-sdk/openai-compatible`, so it only needs to be installed when actually used.\n */\nexport function createOpenAICompatibleProvider(opts: ProviderOpts & { name: string }): ProviderV3 {\n try {\n // eslint-disable-next-line ts/no-require-imports\n const { createOpenAICompatible } = require('@ai-sdk/openai-compatible')\n return createOpenAICompatible(opts)\n }\n catch {\n throw new Error(\n '[ai-sdk-provider-env] openai-compatible mode requires @ai-sdk/openai-compatible. '\n + 'Run: npm install @ai-sdk/openai-compatible',\n )\n }\n}\n","import type { PresetConfig } from './types'\n\n/**\n * Built-in preset configurations for common providers.\n *\n * When using a preset, only `{PREFIX}__PRESET` and `{PREFIX}__API_KEY`\n * are required; `BASE_URL` and `COMPATIBLE` are provided by the preset.\n */\nexport const builtinPresets: Record<string, PresetConfig> = {\n // OpenAI\n openai: {\n baseURL: 'https://api.openai.com/v1',\n compatible: 'openai',\n },\n\n // Anthropic\n anthropic: {\n baseURL: 'https://api.anthropic.com',\n compatible: 'anthropic',\n },\n\n // DeepSeek\n deepseek: {\n baseURL: 'https://api.deepseek.com',\n compatible: 'openai-compatible',\n },\n\n // Zhipu AI (GLM series)\n zhipu: {\n baseURL: 'https://open.bigmodel.cn/api/paas/v4',\n compatible: 'openai-compatible',\n },\n\n // Groq\n groq: {\n baseURL: 'https://api.groq.com/openai/v1',\n compatible: 'openai-compatible',\n },\n\n // Together AI\n together: {\n baseURL: 'https://api.together.xyz/v1',\n compatible: 'openai-compatible',\n },\n\n // Fireworks AI\n fireworks: {\n baseURL: 'https://api.fireworks.ai/inference/v1',\n compatible: 'openai-compatible',\n },\n\n // Mistral AI\n mistral: {\n baseURL: 'https://api.mistral.ai/v1',\n compatible: 'openai-compatible',\n },\n\n // Moonshot AI\n moonshot: {\n baseURL: 'https://api.moonshot.cn/v1',\n compatible: 'openai-compatible',\n },\n\n // Perplexity\n perplexity: {\n baseURL: 'https://api.perplexity.ai',\n compatible: 'openai-compatible',\n },\n\n // OpenRouter\n openrouter: {\n baseURL: 'https://openrouter.ai/api/v1',\n compatible: 'openai-compatible',\n },\n\n // SiliconFlow\n siliconflow: {\n baseURL: 'https://api.siliconflow.cn/v1',\n compatible: 'openai-compatible',\n },\n}\n","import type { ProviderV3 } from '@ai-sdk/provider'\nimport type { ProviderOpts } from './factories'\nimport type { EnvProviderOptions } from './types'\nimport process from 'node:process'\nimport { NoSuchModelError } from '@ai-sdk/provider'\nimport { createAnthropicProvider, createOpenAICompatibleProvider, createOpenAIProvider } from './factories'\nimport { builtinPresets } from './presets'\n\n/**\n * Interface for provider factory functions, used for dependency injection.\n *\n * In production, `defaultFactories` delegates to the real SDK implementations.\n * In tests, fake factories can be injected to avoid module mocking.\n */\nexport interface ProviderFactories {\n createOpenAI: (opts: ProviderOpts) => ProviderV3\n createAnthropic: (opts: ProviderOpts) => ProviderV3\n createOpenAICompatible: (opts: ProviderOpts & { name: string }) => ProviderV3\n}\n\n/**\n * Default factories that delegate to the real implementations in `factories.ts`.\n */\nconst defaultFactories: ProviderFactories = {\n createOpenAI: createOpenAIProvider,\n createAnthropic: createAnthropicProvider,\n createOpenAICompatible: createOpenAICompatibleProvider,\n}\n\n/**\n * Internally resolved configuration with all required fields determined.\n */\ninterface ResolvedConfig {\n baseURL: string\n apiKey: string\n compatible: string\n headers?: Record<string, string>\n}\n\n/**\n * Testable core implementation that accepts injected provider factories.\n *\n * In tests, call this function directly with fake factories\n * to avoid module mocking entirely.\n */\nexport function createEnvProvider(\n factories: ProviderFactories,\n options: EnvProviderOptions = {},\n): ProviderV3 {\n const separator = options.separator ?? '_'\n const defaultFetch = options.defaults?.fetch\n const defaultHeaders = options.defaults?.headers\n\n // Cache created providers to avoid redundant initialization\n const cache = new Map<string, ProviderV3>()\n\n /**\n * Resolve baseURL and compatible from a preset name.\n */\n function resolvePreset(presetName: string): { baseURL: string, compatible: string } {\n const preset = builtinPresets[presetName]\n if (!preset) {\n const available = Object.keys(builtinPresets).join(', ')\n throw new Error(\n `[ai-sdk-provider-env] Unknown preset \"${presetName}\". Available presets: ${available}`,\n )\n }\n return {\n baseURL: preset.baseURL,\n compatible: preset.compatible ?? 'openai-compatible',\n }\n }\n\n /**\n * Resolve config set configuration from explicit configs, presets, or environment variables.\n */\n function resolveConfig(configSet: string): ResolvedConfig {\n // Explicit configs take precedence over env vars\n if (options.configs?.[configSet]) {\n const config = options.configs[configSet]\n\n // Code-based configs also support presets\n if (config.preset) {\n const preset = resolvePreset(config.preset)\n return {\n baseURL: config.baseURL ?? preset.baseURL,\n apiKey: config.apiKey,\n compatible: config.compatible ?? preset.compatible,\n ...(config.headers && { headers: config.headers }),\n }\n }\n\n if (!config.baseURL) {\n throw new Error(\n `[ai-sdk-provider-env] Missing baseURL in config for \"${configSet}\"`\n + ` (or set preset to use a built-in preset)`,\n )\n }\n\n return {\n baseURL: config.baseURL,\n apiKey: config.apiKey,\n compatible: config.compatible ?? 'openai-compatible',\n ...(config.headers && { headers: config.headers }),\n }\n }\n\n const prefix = configSet.toUpperCase()\n const env = (key: string): string | undefined => process.env[`${prefix}${separator}${key}`]\n\n const apiKey = env('API_KEY')\n if (!apiKey) {\n throw new Error(\n `[ai-sdk-provider-env] Missing env var ${prefix}${separator}API_KEY`,\n )\n }\n\n // Parse headers from env var (JSON format)\n const headersRaw = env('HEADERS')\n let headers: Record<string, string> | undefined\n if (headersRaw) {\n try {\n headers = JSON.parse(headersRaw)\n }\n catch {\n throw new Error(\n `[ai-sdk-provider-env] Invalid JSON in ${prefix}${separator}HEADERS: ${headersRaw}`,\n )\n }\n }\n\n // Check for preset\n const presetName = env('PRESET')\n if (presetName) {\n const preset = resolvePreset(presetName)\n return {\n baseURL: env('BASE_URL') ?? preset.baseURL,\n apiKey,\n compatible: env('COMPATIBLE') ?? preset.compatible,\n ...(headers && { headers }),\n }\n }\n\n // Without a preset, BASE_URL is required\n const baseURL = env('BASE_URL')\n if (!baseURL) {\n throw new Error(\n `[ai-sdk-provider-env] Missing env var ${prefix}${separator}BASE_URL`\n + ` (or set ${prefix}${separator}PRESET to use a preset)`,\n )\n }\n\n return {\n baseURL,\n apiKey,\n compatible: env('COMPATIBLE') ?? 'openai-compatible',\n ...(headers && { headers }),\n }\n }\n\n /**\n * Create the underlying provider based on the compatibility mode.\n */\n function createUnderlying(configSet: string, config: ResolvedConfig): ProviderV3 {\n const { baseURL, apiKey, compatible, headers } = config\n\n // Merge headers: defaults.headers as base, config-set headers override matching keys\n const mergedHeaders = (defaultHeaders || headers)\n ? { ...defaultHeaders, ...headers }\n : undefined\n\n const baseOpts = {\n baseURL,\n apiKey,\n ...(mergedHeaders && { headers: mergedHeaders }),\n ...(defaultFetch && { fetch: defaultFetch }),\n }\n\n switch (compatible) {\n case 'openai':\n return factories.createOpenAI(baseOpts)\n case 'anthropic':\n return factories.createAnthropic(baseOpts)\n case 'openai-compatible':\n return factories.createOpenAICompatible({ name: configSet, ...baseOpts })\n default:\n throw new Error(\n `[ai-sdk-provider-env] Unknown compatible mode \"${compatible}\".`\n + ` Supported values: \"openai\", \"anthropic\", \"openai-compatible\".`\n + ` Set COMPATIBLE=openai-compatible (or omit it) to use the OpenAI-compatible provider.`,\n )\n }\n }\n\n /**\n * Get or create a cached provider for the given config set.\n */\n function getProvider(configSet: string): ProviderV3 {\n const key = configSet.toUpperCase()\n const cached = cache.get(key)\n if (cached)\n return cached\n\n const config = resolveConfig(configSet)\n const provider = createUnderlying(configSet, config)\n cache.set(key, provider)\n return provider\n }\n\n /**\n * Parse a model ID. The first `/` separates the config set name from the actual model ID.\n */\n function parseModelId(modelId: string): { configSet: string, model: string } {\n const slashIndex = modelId.indexOf('/')\n if (slashIndex === -1) {\n throw new Error(\n `[ai-sdk-provider-env] Invalid model ID \"${modelId}\". `\n + `Expected format: \"{configSet}/{modelId}\", e.g. \"zhipu/glm-4\"`,\n )\n }\n return {\n configSet: modelId.slice(0, slashIndex),\n model: modelId.slice(slashIndex + 1),\n }\n }\n\n return {\n specificationVersion: 'v3' as const,\n\n languageModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n return getProvider(configSet).languageModel(model)\n },\n\n embeddingModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n return getProvider(configSet).embeddingModel(model)\n },\n\n imageModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n return getProvider(configSet).imageModel(model)\n },\n\n textEmbeddingModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.textEmbeddingModel) {\n throw new NoSuchModelError({ modelId, modelType: 'embeddingModel' })\n }\n return provider.textEmbeddingModel(model)\n },\n\n transcriptionModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.transcriptionModel) {\n throw new NoSuchModelError({ modelId, modelType: 'transcriptionModel' })\n }\n return provider.transcriptionModel(model)\n },\n\n speechModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.speechModel) {\n throw new NoSuchModelError({ modelId, modelType: 'speechModel' })\n }\n return provider.speechModel(model)\n },\n\n rerankingModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.rerankingModel) {\n throw new NoSuchModelError({ modelId, modelType: 'rerankingModel' })\n }\n return provider.rerankingModel(model)\n },\n }\n}\n\n/**\n * Create a dynamic, environment-variable-driven AI SDK provider.\n *\n * Automatically resolves provider configurations from env var naming conventions,\n * with built-in preset support for quick setup.\n *\n * Env var convention (using config set `ZHIPU` with default separator `_` as example):\n * - `ZHIPU_PRESET` — use a built-in preset (BASE_URL and COMPATIBLE become optional)\n * - `ZHIPU_BASE_URL` — API base URL\n * - `ZHIPU_API_KEY` — API key (required)\n * - `ZHIPU_COMPATIBLE` — compatibility mode (defaults to `'openai-compatible'`)\n * - `ZHIPU_HEADERS` — custom HTTP headers (JSON format)\n *\n * @example\n * ```ts\n * import { createProviderRegistry } from 'ai'\n * import { envProvider } from 'ai-sdk-provider-env'\n *\n * const registry = createProviderRegistry({\n * env: envProvider(),\n * })\n *\n * // Use a preset (only API_KEY is required)\n * // DEEPSEEK_PRESET=deepseek\n * // DEEPSEEK_API_KEY=sk-xxx\n * const model = registry.languageModel('env:deepseek/deepseek-chat')\n *\n * // Specify all parameters manually\n * // MYAPI_BASE_URL=https://api.example.com/v1\n * // MYAPI_API_KEY=xxx\n * const model2 = registry.languageModel('env:myapi/some-model')\n * ```\n */\nexport function envProvider(options: EnvProviderOptions = {}): ProviderV3 {\n return createEnvProvider(defaultFactories, options)\n}\n"],"mappings":";;;;;;;;;;;;;;AAcA,SAAgB,qBAAqB,MAAgC;AACnE,KAAI;EAEF,MAAM,EAAE,2BAAyB,iBAAiB;AAClD,SAAO,aAAa,KAAK;SAErB;AACJ,QAAM,IAAI,MACR,2GAED;;;;;;;;AASL,SAAgB,wBAAwB,MAAgC;AACtE,KAAI;EAEF,MAAM,EAAE,8BAA4B,oBAAoB;AACxD,SAAO,gBAAgB,KAAK;SAExB;AACJ,QAAM,IAAI,MACR,oHAED;;;;;;;;AASL,SAAgB,+BAA+B,MAAmD;AAChG,KAAI;EAEF,MAAM,EAAE,qCAAmC,4BAA4B;AACvE,SAAO,uBAAuB,KAAK;SAE/B;AACJ,QAAM,IAAI,MACR,8HAED;;;;;;;;;;;;ACtDL,MAAa,iBAA+C;CAE1D,QAAQ;EACN,SAAS;EACT,YAAY;EACb;CAGD,WAAW;EACT,SAAS;EACT,YAAY;EACb;CAGD,UAAU;EACR,SAAS;EACT,YAAY;EACb;CAGD,OAAO;EACL,SAAS;EACT,YAAY;EACb;CAGD,MAAM;EACJ,SAAS;EACT,YAAY;EACb;CAGD,UAAU;EACR,SAAS;EACT,YAAY;EACb;CAGD,WAAW;EACT,SAAS;EACT,YAAY;EACb;CAGD,SAAS;EACP,SAAS;EACT,YAAY;EACb;CAGD,UAAU;EACR,SAAS;EACT,YAAY;EACb;CAGD,YAAY;EACV,SAAS;EACT,YAAY;EACb;CAGD,YAAY;EACV,SAAS;EACT,YAAY;EACb;CAGD,aAAa;EACX,SAAS;EACT,YAAY;EACb;CACF;;;;;;;ACzDD,MAAM,mBAAsC;CAC1C,cAAc;CACd,iBAAiB;CACjB,wBAAwB;CACzB;;;;;;;AAkBD,SAAgB,kBACd,WACA,UAA8B,EAAE,EACpB;CACZ,MAAM,YAAY,QAAQ,aAAa;CACvC,MAAM,eAAe,QAAQ,UAAU;CACvC,MAAM,iBAAiB,QAAQ,UAAU;CAGzC,MAAM,wBAAQ,IAAI,KAAyB;;;;CAK3C,SAAS,cAAc,YAA6D;EAClF,MAAM,SAAS,eAAe;AAC9B,MAAI,CAAC,QAAQ;GACX,MAAM,YAAY,OAAO,KAAK,eAAe,CAAC,KAAK,KAAK;AACxD,SAAM,IAAI,MACR,yCAAyC,WAAW,wBAAwB,YAC7E;;AAEH,SAAO;GACL,SAAS,OAAO;GAChB,YAAY,OAAO,cAAc;GAClC;;;;;CAMH,SAAS,cAAc,WAAmC;AAExD,MAAI,QAAQ,UAAU,YAAY;GAChC,MAAM,SAAS,QAAQ,QAAQ;AAG/B,OAAI,OAAO,QAAQ;IACjB,MAAM,SAAS,cAAc,OAAO,OAAO;AAC3C,WAAO;KACL,SAAS,OAAO,WAAW,OAAO;KAClC,QAAQ,OAAO;KACf,YAAY,OAAO,cAAc,OAAO;KACxC,GAAI,OAAO,WAAW,EAAE,SAAS,OAAO,SAAS;KAClD;;AAGH,OAAI,CAAC,OAAO,QACV,OAAM,IAAI,MACR,wDAAwD,UAAU,4CAEnE;AAGH,UAAO;IACL,SAAS,OAAO;IAChB,QAAQ,OAAO;IACf,YAAY,OAAO,cAAc;IACjC,GAAI,OAAO,WAAW,EAAE,SAAS,OAAO,SAAS;IAClD;;EAGH,MAAM,SAAS,UAAU,aAAa;EACtC,MAAM,OAAO,QAAoC,QAAQ,IAAI,GAAG,SAAS,YAAY;EAErF,MAAM,SAAS,IAAI,UAAU;AAC7B,MAAI,CAAC,OACH,OAAM,IAAI,MACR,yCAAyC,SAAS,UAAU,SAC7D;EAIH,MAAM,aAAa,IAAI,UAAU;EACjC,IAAI;AACJ,MAAI,WACF,KAAI;AACF,aAAU,KAAK,MAAM,WAAW;UAE5B;AACJ,SAAM,IAAI,MACR,yCAAyC,SAAS,UAAU,WAAW,aACxE;;EAKL,MAAM,aAAa,IAAI,SAAS;AAChC,MAAI,YAAY;GACd,MAAM,SAAS,cAAc,WAAW;AACxC,UAAO;IACL,SAAS,IAAI,WAAW,IAAI,OAAO;IACnC;IACA,YAAY,IAAI,aAAa,IAAI,OAAO;IACxC,GAAI,WAAW,EAAE,SAAS;IAC3B;;EAIH,MAAM,UAAU,IAAI,WAAW;AAC/B,MAAI,CAAC,QACH,OAAM,IAAI,MACR,yCAAyC,SAAS,UAAU,mBAC9C,SAAS,UAAU,yBAClC;AAGH,SAAO;GACL;GACA;GACA,YAAY,IAAI,aAAa,IAAI;GACjC,GAAI,WAAW,EAAE,SAAS;GAC3B;;;;;CAMH,SAAS,iBAAiB,WAAmB,QAAoC;EAC/E,MAAM,EAAE,SAAS,QAAQ,YAAY,YAAY;EAGjD,MAAM,gBAAiB,kBAAkB,UACrC;GAAE,GAAG;GAAgB,GAAG;GAAS,GACjC;EAEJ,MAAM,WAAW;GACf;GACA;GACA,GAAI,iBAAiB,EAAE,SAAS,eAAe;GAC/C,GAAI,gBAAgB,EAAE,OAAO,cAAc;GAC5C;AAED,UAAQ,YAAR;GACE,KAAK,SACH,QAAO,UAAU,aAAa,SAAS;GACzC,KAAK,YACH,QAAO,UAAU,gBAAgB,SAAS;GAC5C,KAAK,oBACH,QAAO,UAAU,uBAAuB;IAAE,MAAM;IAAW,GAAG;IAAU,CAAC;GAC3E,QACE,OAAM,IAAI,MACR,kDAAkD,WAAW,uJAG9D;;;;;;CAOP,SAAS,YAAY,WAA+B;EAClD,MAAM,MAAM,UAAU,aAAa;EACnC,MAAM,SAAS,MAAM,IAAI,IAAI;AAC7B,MAAI,OACF,QAAO;EAGT,MAAM,WAAW,iBAAiB,WADnB,cAAc,UAAU,CACa;AACpD,QAAM,IAAI,KAAK,SAAS;AACxB,SAAO;;;;;CAMT,SAAS,aAAa,SAAuD;EAC3E,MAAM,aAAa,QAAQ,QAAQ,IAAI;AACvC,MAAI,eAAe,GACjB,OAAM,IAAI,MACR,2CAA2C,QAAQ,iEAEpD;AAEH,SAAO;GACL,WAAW,QAAQ,MAAM,GAAG,WAAW;GACvC,OAAO,QAAQ,MAAM,aAAa,EAAE;GACrC;;AAGH,QAAO;EACL,sBAAsB;EAEtB,cAAc,SAAiB;GAC7B,MAAM,EAAE,WAAW,UAAU,aAAa,QAAQ;AAClD,UAAO,YAAY,UAAU,CAAC,cAAc,MAAM;;EAGpD,eAAe,SAAiB;GAC9B,MAAM,EAAE,WAAW,UAAU,aAAa,QAAQ;AAClD,UAAO,YAAY,UAAU,CAAC,eAAe,MAAM;;EAGrD,WAAW,SAAiB;GAC1B,MAAM,EAAE,WAAW,UAAU,aAAa,QAAQ;AAClD,UAAO,YAAY,UAAU,CAAC,WAAW,MAAM;;EAGjD,mBAAmB,SAAiB;GAClC,MAAM,EAAE,WAAW,UAAU,aAAa,QAAQ;GAClD,MAAM,WAAW,YAAY,UAAU;AACvC,OAAI,CAAC,SAAS,mBACZ,OAAM,IAAI,iBAAiB;IAAE;IAAS,WAAW;IAAkB,CAAC;AAEtE,UAAO,SAAS,mBAAmB,MAAM;;EAG3C,mBAAmB,SAAiB;GAClC,MAAM,EAAE,WAAW,UAAU,aAAa,QAAQ;GAClD,MAAM,WAAW,YAAY,UAAU;AACvC,OAAI,CAAC,SAAS,mBACZ,OAAM,IAAI,iBAAiB;IAAE;IAAS,WAAW;IAAsB,CAAC;AAE1E,UAAO,SAAS,mBAAmB,MAAM;;EAG3C,YAAY,SAAiB;GAC3B,MAAM,EAAE,WAAW,UAAU,aAAa,QAAQ;GAClD,MAAM,WAAW,YAAY,UAAU;AACvC,OAAI,CAAC,SAAS,YACZ,OAAM,IAAI,iBAAiB;IAAE;IAAS,WAAW;IAAe,CAAC;AAEnE,UAAO,SAAS,YAAY,MAAM;;EAGpC,eAAe,SAAiB;GAC9B,MAAM,EAAE,WAAW,UAAU,aAAa,QAAQ;GAClD,MAAM,WAAW,YAAY,UAAU;AACvC,OAAI,CAAC,SAAS,eACZ,OAAM,IAAI,iBAAiB;IAAE;IAAS,WAAW;IAAkB,CAAC;AAEtE,UAAO,SAAS,eAAe,MAAM;;EAExC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCH,SAAgB,YAAY,UAA8B,EAAE,EAAc;AACxE,QAAO,kBAAkB,kBAAkB,QAAQ"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/factories.ts","../src/presets.ts","../src/env-provider.ts"],"sourcesContent":["import type { ProviderV3 } from '@ai-sdk/provider'\n\nexport interface ProviderOpts {\n baseURL: string\n apiKey: string\n headers?: Record<string, string>\n fetch?: typeof globalThis.fetch\n}\n\n/**\n * Create an OpenAI provider.\n *\n * Dynamically requires `@ai-sdk/openai`, so it only needs to be installed when actually used.\n */\nexport function createOpenAIProvider(opts: ProviderOpts): ProviderV3 {\n try {\n // eslint-disable-next-line ts/no-require-imports\n const { createOpenAI } = require('@ai-sdk/openai')\n return createOpenAI(opts)\n }\n catch {\n throw new Error(\n '[ai-sdk-provider-env] openai compatibility mode requires @ai-sdk/openai. '\n + 'Run: npm install @ai-sdk/openai',\n )\n }\n}\n\n/**\n * Create an Anthropic provider.\n *\n * Dynamically requires `@ai-sdk/anthropic`, so it only needs to be installed when actually used.\n */\nexport function createAnthropicProvider(opts: ProviderOpts): ProviderV3 {\n try {\n // eslint-disable-next-line ts/no-require-imports\n const { createAnthropic } = require('@ai-sdk/anthropic')\n return createAnthropic(opts)\n }\n catch {\n throw new Error(\n '[ai-sdk-provider-env] anthropic compatibility mode requires @ai-sdk/anthropic. '\n + 'Run: npm install @ai-sdk/anthropic',\n )\n }\n}\n\n/**\n * Create a Google Generative AI (Gemini) provider.\n *\n * Dynamically requires `@ai-sdk/google`, so it only needs to be installed when actually used.\n */\nexport function createGeminiProvider(opts: ProviderOpts): ProviderV3 {\n try {\n // eslint-disable-next-line ts/no-require-imports\n const { createGoogleGenerativeAI } = require('@ai-sdk/google')\n return createGoogleGenerativeAI(opts)\n }\n catch {\n throw new Error(\n '[ai-sdk-provider-env] gemini compatibility mode requires @ai-sdk/google. '\n + 'Run: npm install @ai-sdk/google',\n )\n }\n}\n\n/**\n * Create an OpenAI Compatible provider.\n *\n * Dynamically requires `@ai-sdk/openai-compatible`, so it only needs to be installed when actually used.\n */\nexport function createOpenAICompatibleProvider(opts: ProviderOpts & { name: string }): ProviderV3 {\n try {\n // eslint-disable-next-line ts/no-require-imports\n const { createOpenAICompatible } = require('@ai-sdk/openai-compatible')\n return createOpenAICompatible(opts)\n }\n catch {\n throw new Error(\n '[ai-sdk-provider-env] openai-compatible mode requires @ai-sdk/openai-compatible. '\n + 'Run: npm install @ai-sdk/openai-compatible',\n )\n }\n}\n","import type { PresetConfig } from './types'\n\n/**\n * Built-in preset configurations for common providers.\n *\n * When using a preset, only `{PREFIX}__PRESET` and `{PREFIX}__API_KEY`\n * are required; `BASE_URL` and `COMPATIBLE` are provided by the preset.\n */\nexport const builtinPresets: Record<string, PresetConfig> = {\n // OpenAI\n openai: {\n baseURL: 'https://api.openai.com/v1',\n compatible: 'openai',\n },\n\n // Anthropic\n anthropic: {\n baseURL: 'https://api.anthropic.com',\n compatible: 'anthropic',\n },\n\n // Google AI Studio (Gemini)\n google: {\n baseURL: 'https://generativelanguage.googleapis.com/v1beta',\n compatible: 'gemini',\n },\n\n // DeepSeek\n deepseek: {\n baseURL: 'https://api.deepseek.com',\n compatible: 'openai-compatible',\n },\n\n // Zhipu AI (GLM series)\n zhipu: {\n baseURL: 'https://open.bigmodel.cn/api/paas/v4',\n compatible: 'openai-compatible',\n },\n\n // Groq\n groq: {\n baseURL: 'https://api.groq.com/openai/v1',\n compatible: 'openai-compatible',\n },\n\n // Together AI\n together: {\n baseURL: 'https://api.together.xyz/v1',\n compatible: 'openai-compatible',\n },\n\n // Fireworks AI\n fireworks: {\n baseURL: 'https://api.fireworks.ai/inference/v1',\n compatible: 'openai-compatible',\n },\n\n // Mistral AI\n mistral: {\n baseURL: 'https://api.mistral.ai/v1',\n compatible: 'openai-compatible',\n },\n\n // Moonshot AI\n moonshot: {\n baseURL: 'https://api.moonshot.cn/v1',\n compatible: 'openai-compatible',\n },\n\n // Perplexity\n perplexity: {\n baseURL: 'https://api.perplexity.ai',\n compatible: 'openai-compatible',\n },\n\n // OpenRouter\n openrouter: {\n baseURL: 'https://openrouter.ai/api/v1',\n compatible: 'openai-compatible',\n },\n\n // SiliconFlow\n siliconflow: {\n baseURL: 'https://api.siliconflow.cn/v1',\n compatible: 'openai-compatible',\n },\n}\n","import type { ProviderV3 } from '@ai-sdk/provider'\nimport type { ProviderOpts } from './factories'\nimport type { EnvProviderFactories, EnvProviderOptions } from './types'\nimport process from 'node:process'\nimport { NoSuchModelError } from '@ai-sdk/provider'\nimport { createAnthropicProvider, createGeminiProvider, createOpenAICompatibleProvider, createOpenAIProvider } from './factories'\nimport { builtinPresets } from './presets'\n\n/**\n * Interface for provider factory functions, used for dependency injection.\n *\n * In production, `defaultFactories` delegates to the real SDK implementations.\n * In tests, fake factories can be injected to avoid module mocking.\n */\nexport interface ProviderFactories {\n createOpenAI: (opts: ProviderOpts) => ProviderV3\n createAnthropic: (opts: ProviderOpts) => ProviderV3\n createGemini: (opts: ProviderOpts) => ProviderV3\n createOpenAICompatible: (opts: ProviderOpts & { name: string }) => ProviderV3\n}\n\n/**\n * Default factories that delegate to the real implementations in `factories.ts`.\n */\nconst defaultFactories: ProviderFactories = {\n createOpenAI: createOpenAIProvider,\n createAnthropic: createAnthropicProvider,\n createGemini: createGeminiProvider,\n createOpenAICompatible: createOpenAICompatibleProvider,\n}\n\n/**\n * Internally resolved configuration with all required fields determined.\n */\ninterface ResolvedConfig {\n baseURL: string\n apiKey: string\n compatible: string\n headers?: Record<string, string>\n}\n\n/**\n * Testable core implementation that accepts injected provider factories.\n *\n * In tests, call this function directly with fake factories\n * to avoid module mocking entirely.\n */\nexport function createEnvProvider(\n factories: ProviderFactories,\n options: Omit<EnvProviderOptions, 'factories'> = {},\n): ProviderV3 {\n const separator = options.separator ?? '_'\n const defaultFetch = options.defaults?.fetch\n const defaultHeaders = options.defaults?.headers\n\n // Cache created providers to avoid redundant initialization\n const cache = new Map<string, ProviderV3>()\n\n /**\n * Resolve baseURL and compatible from a preset name.\n */\n function resolvePreset(presetName: string): { baseURL: string, compatible: string } {\n const preset = builtinPresets[presetName]\n if (!preset) {\n const available = Object.keys(builtinPresets).join(', ')\n throw new Error(\n `[ai-sdk-provider-env] Unknown preset \"${presetName}\". Available presets: ${available}`,\n )\n }\n return {\n baseURL: preset.baseURL,\n compatible: preset.compatible ?? 'openai-compatible',\n }\n }\n\n /**\n * Resolve config set configuration from explicit configs, presets, or environment variables.\n */\n function resolveConfig(configSet: string): ResolvedConfig {\n // Explicit configs take precedence over env vars\n if (options.configs?.[configSet]) {\n const config = options.configs[configSet]\n\n // Code-based configs also support presets\n if (config.preset) {\n const preset = resolvePreset(config.preset)\n return {\n baseURL: config.baseURL ?? preset.baseURL,\n apiKey: config.apiKey,\n compatible: config.compatible ?? preset.compatible,\n ...(config.headers && { headers: config.headers }),\n }\n }\n\n if (!config.baseURL) {\n throw new Error(\n `[ai-sdk-provider-env] Missing baseURL in config for \"${configSet}\"`\n + ` (or set preset to use a built-in preset)`,\n )\n }\n\n return {\n baseURL: config.baseURL,\n apiKey: config.apiKey,\n compatible: config.compatible ?? 'openai-compatible',\n ...(config.headers && { headers: config.headers }),\n }\n }\n\n const prefix = configSet.toUpperCase()\n const env = (key: string): string | undefined => process.env[`${prefix}${separator}${key}`]\n\n const apiKey = env('API_KEY')\n if (!apiKey) {\n throw new Error(\n `[ai-sdk-provider-env] Missing env var ${prefix}${separator}API_KEY`,\n )\n }\n\n // Parse headers from env var (JSON format)\n const headersRaw = env('HEADERS')\n let headers: Record<string, string> | undefined\n if (headersRaw) {\n try {\n headers = JSON.parse(headersRaw)\n }\n catch {\n throw new Error(\n `[ai-sdk-provider-env] Invalid JSON in ${prefix}${separator}HEADERS: ${headersRaw}`,\n )\n }\n }\n\n // Check for preset\n const presetName = env('PRESET')\n if (presetName) {\n const preset = resolvePreset(presetName)\n return {\n baseURL: env('BASE_URL') ?? preset.baseURL,\n apiKey,\n compatible: env('COMPATIBLE') ?? preset.compatible,\n ...(headers && { headers }),\n }\n }\n\n // Without a preset, try BASE_URL first\n const baseURL = env('BASE_URL')\n if (baseURL) {\n return {\n baseURL,\n apiKey,\n compatible: env('COMPATIBLE') ?? 'openai-compatible',\n ...(headers && { headers }),\n }\n }\n\n // Auto-detect: if configSet name matches a built-in preset, use it automatically\n if (options.presetAutoDetect !== false) {\n const autoPreset = builtinPresets[configSet.toLowerCase()]\n if (autoPreset) {\n return {\n baseURL: autoPreset.baseURL,\n apiKey,\n compatible: env('COMPATIBLE') ?? autoPreset.compatible ?? 'openai-compatible',\n ...(headers && { headers }),\n }\n }\n }\n\n // Error: neither BASE_URL nor a matching preset found\n const available = Object.keys(builtinPresets).join(', ')\n const presetHint = builtinPresets[configSet.toLowerCase()]\n ? ` (Note: \"${configSet}\" matches a built-in preset, but presetAutoDetect is disabled.)`\n : ''\n throw new Error(\n `[ai-sdk-provider-env] Missing env var ${prefix}${separator}BASE_URL`\n + ` (or set ${prefix}${separator}PRESET to use a preset.`\n + ` Available presets: ${available})${presetHint}`,\n )\n }\n\n /**\n * Create the underlying provider based on the compatibility mode.\n */\n function createUnderlying(configSet: string, config: ResolvedConfig): ProviderV3 {\n const { baseURL, apiKey, compatible, headers } = config\n\n // Merge headers: defaults.headers as base, config-set headers override matching keys\n const mergedHeaders = (defaultHeaders || headers)\n ? { ...defaultHeaders, ...headers }\n : undefined\n\n const baseOpts = {\n baseURL,\n apiKey,\n ...(mergedHeaders && { headers: mergedHeaders }),\n ...(defaultFetch && { fetch: defaultFetch }),\n }\n\n switch (compatible) {\n case 'openai':\n return factories.createOpenAI(baseOpts)\n case 'anthropic':\n return factories.createAnthropic(baseOpts)\n case 'gemini':\n return factories.createGemini(baseOpts)\n case 'openai-compatible':\n return factories.createOpenAICompatible({ name: configSet, ...baseOpts })\n default:\n throw new Error(\n `[ai-sdk-provider-env] Unknown compatible mode \"${compatible}\".`\n + ` Supported values: \"openai\", \"anthropic\", \"gemini\", \"openai-compatible\".`\n + ` Set COMPATIBLE=openai-compatible (or omit it) to use the OpenAI-compatible provider.`,\n )\n }\n }\n\n /**\n * Get or create a cached provider for the given config set.\n */\n function getProvider(configSet: string): ProviderV3 {\n const key = configSet.toUpperCase()\n const cached = cache.get(key)\n if (cached)\n return cached\n\n const config = resolveConfig(configSet)\n const provider = createUnderlying(configSet, config)\n cache.set(key, provider)\n return provider\n }\n\n /**\n * Parse a model ID. The first `/` separates the config set name from the actual model ID.\n */\n function parseModelId(modelId: string): { configSet: string, model: string } {\n const slashIndex = modelId.indexOf('/')\n if (slashIndex === -1) {\n throw new Error(\n `[ai-sdk-provider-env] Invalid model ID \"${modelId}\". `\n + `Expected format: \"{configSet}/{modelId}\", e.g. \"zhipu/glm-4\"`,\n )\n }\n return {\n configSet: modelId.slice(0, slashIndex),\n model: modelId.slice(slashIndex + 1),\n }\n }\n\n return {\n specificationVersion: 'v3' as const,\n\n languageModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n return getProvider(configSet).languageModel(model)\n },\n\n embeddingModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n return getProvider(configSet).embeddingModel(model)\n },\n\n imageModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n return getProvider(configSet).imageModel(model)\n },\n\n textEmbeddingModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.textEmbeddingModel) {\n throw new NoSuchModelError({ modelId, modelType: 'embeddingModel' })\n }\n return provider.textEmbeddingModel(model)\n },\n\n transcriptionModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.transcriptionModel) {\n throw new NoSuchModelError({ modelId, modelType: 'transcriptionModel' })\n }\n return provider.transcriptionModel(model)\n },\n\n speechModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.speechModel) {\n throw new NoSuchModelError({ modelId, modelType: 'speechModel' })\n }\n return provider.speechModel(model)\n },\n\n rerankingModel(modelId: string) {\n const { configSet, model } = parseModelId(modelId)\n const provider = getProvider(configSet)\n if (!provider.rerankingModel) {\n throw new NoSuchModelError({ modelId, modelType: 'rerankingModel' })\n }\n return provider.rerankingModel(model)\n },\n }\n}\n\n/**\n * Build internal `ProviderFactories` from user-provided `EnvProviderFactories`.\n *\n * Uses lazy-strict semantics: each factory slot is only evaluated when actually called.\n * If the user provided a factory for a given compatible mode, it is used;\n * otherwise, a clear error is thrown (no silent fallback to dynamic `require()`).\n */\nfunction buildUserFactories(userFactories: EnvProviderFactories): ProviderFactories {\n function missingFactory(key: string, fnName: string, pkg: string): never {\n throw new Error(\n `[ai-sdk-provider-env] No factory provided for \"${key}\". `\n + `When using the factories option, provide a factory for each compatibility mode you use. `\n + `Add: import { ${fnName} } from '${pkg}' and set factories: { ${key}: ${fnName} }`,\n )\n }\n\n return {\n createOpenAI: opts =>\n userFactories.openai\n ? userFactories.openai(opts)\n : missingFactory('openai', 'createOpenAI', '@ai-sdk/openai'),\n createAnthropic: opts =>\n userFactories.anthropic\n ? userFactories.anthropic(opts)\n : missingFactory('anthropic', 'createAnthropic', '@ai-sdk/anthropic'),\n createGemini: opts =>\n userFactories.gemini\n ? userFactories.gemini(opts)\n : missingFactory('gemini', 'createGoogleGenerativeAI', '@ai-sdk/google'),\n createOpenAICompatible: opts =>\n userFactories.openaiCompatible\n ? userFactories.openaiCompatible(opts)\n : missingFactory('openaiCompatible', 'createOpenAICompatible', '@ai-sdk/openai-compatible'),\n }\n}\n\n/**\n * Create a dynamic, environment-variable-driven AI SDK provider.\n *\n * Automatically resolves provider configurations from env var naming conventions,\n * with built-in preset support for quick setup.\n *\n * Env var convention (using config set `ZHIPU` with default separator `_` as example):\n * - `ZHIPU_PRESET` — use a built-in preset (BASE_URL and COMPATIBLE become optional)\n * - `ZHIPU_BASE_URL` — API base URL\n * - `ZHIPU_API_KEY` — API key (required)\n * - `ZHIPU_COMPATIBLE` — compatibility mode (defaults to `'openai-compatible'`)\n * - `ZHIPU_HEADERS` — custom HTTP headers (JSON format)\n *\n * @example\n * ```ts\n * import { createProviderRegistry } from 'ai'\n * import { envProvider } from 'ai-sdk-provider-env'\n *\n * const registry = createProviderRegistry({\n * env: envProvider(),\n * })\n *\n * // Use a preset (only API_KEY is required)\n * // DEEPSEEK_PRESET=deepseek\n * // DEEPSEEK_API_KEY=sk-xxx\n * const model = registry.languageModel('env:deepseek/deepseek-chat')\n *\n * // Specify all parameters manually\n * // MYAPI_BASE_URL=https://api.example.com/v1\n * // MYAPI_API_KEY=xxx\n * const model2 = registry.languageModel('env:myapi/some-model')\n * ```\n *\n * @example Bundler-safe usage with explicit factories\n * ```ts\n * import { createOpenAI } from '@ai-sdk/openai'\n * import { envProvider } from 'ai-sdk-provider-env'\n *\n * const provider = envProvider({\n * factories: { openai: createOpenAI },\n * })\n * ```\n */\nexport function envProvider(options: EnvProviderOptions = {}): ProviderV3 {\n const factories = options.factories\n ? buildUserFactories(options.factories)\n : defaultFactories\n return createEnvProvider(factories, options)\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-sdk-provider-env",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"description": "A dynamic, environment-variable-driven provider for Vercel AI SDK — resolves provider configurations from env var conventions at runtime",
|
|
6
6
|
"author": "maou-shonen",
|
|
7
7
|
"license": "MIT",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"@ai-sdk/anthropic": ">=3.0.0",
|
|
51
|
+
"@ai-sdk/google": ">=3.0.0",
|
|
51
52
|
"@ai-sdk/openai": ">=3.0.0",
|
|
52
53
|
"@ai-sdk/openai-compatible": ">=2.0.0",
|
|
53
54
|
"@ai-sdk/provider": ">=3.0.0",
|
|
@@ -57,6 +58,9 @@
|
|
|
57
58
|
"@ai-sdk/anthropic": {
|
|
58
59
|
"optional": true
|
|
59
60
|
},
|
|
61
|
+
"@ai-sdk/google": {
|
|
62
|
+
"optional": true
|
|
63
|
+
},
|
|
60
64
|
"@ai-sdk/openai": {
|
|
61
65
|
"optional": true
|
|
62
66
|
},
|
|
@@ -66,6 +70,7 @@
|
|
|
66
70
|
},
|
|
67
71
|
"devDependencies": {
|
|
68
72
|
"@ai-sdk/anthropic": "^3.0.0",
|
|
73
|
+
"@ai-sdk/google": "^3.0.0",
|
|
69
74
|
"@ai-sdk/openai": "^3.0.0",
|
|
70
75
|
"@ai-sdk/openai-compatible": "^2.0.0",
|
|
71
76
|
"@ai-sdk/provider": "^3.0.0",
|