ai-sdk-provider-env 0.3.0 → 0.4.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 +69 -264
- package/dist/index.cjs +127 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -12
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +64 -12
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +127 -41
- package/dist/index.mjs.map +1 -1
- package/llms.txt +180 -0
- package/package.json +11 -25
package/README.md
CHANGED
|
@@ -1,60 +1,38 @@
|
|
|
1
|
-
> [中文](./README_zh.md)
|
|
1
|
+
> [For AI agent (llms.txt)](./llms.txt) | [中文](./README_zh.md)
|
|
2
2
|
|
|
3
3
|
# ai-sdk-provider-env
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Environment-variable-driven provider for [Vercel AI SDK](https://sdk.vercel.ai/). Switch AI providers and models without code changes.
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/ai-sdk-provider-env)
|
|
8
8
|
[](./LICENSE)
|
|
9
9
|
|
|
10
|
-
##
|
|
11
|
-
|
|
12
|
-
Using multiple AI providers with Vercel AI SDK means importing each SDK, configuring API keys and base URLs, and wiring everything together — per provider, per project. Switching providers requires code changes.
|
|
13
|
-
|
|
14
|
-
`ai-sdk-provider-env` eliminates this boilerplate. Define provider configurations through environment variables, resolve them at runtime. Add a new provider by setting env vars, switch models by changing a string — no code changes needed.
|
|
15
|
-
|
|
16
|
-
## Features
|
|
17
|
-
|
|
18
|
-
- Resolve provider config (base URL, API key, compatibility mode) from environment variables automatically
|
|
19
|
-
- Built-in presets for popular providers, so you only need to set an API key
|
|
20
|
-
- Supports OpenAI, Anthropic, Google Gemini, and any OpenAI-compatible API
|
|
21
|
-
- Implements `ProviderV3`, plugs directly into `createProviderRegistry`
|
|
22
|
-
- Provider instances are cached, no redundant initialization
|
|
23
|
-
- Fully customizable: custom fetch, env-based headers, custom separator, code-based configs
|
|
24
|
-
|
|
25
|
-
## Installation
|
|
10
|
+
## Quick Start
|
|
26
11
|
|
|
27
12
|
```bash
|
|
28
13
|
pnpm add ai-sdk-provider-env
|
|
29
14
|
```
|
|
30
15
|
|
|
31
|
-
Install provider SDKs as needed:
|
|
32
|
-
|
|
33
16
|
```bash
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
pnpm add @ai-sdk/google # for Google AI Studio (Gemini)
|
|
37
|
-
pnpm add @ai-sdk/openai-compatible # for generic OpenAI-compatible APIs
|
|
17
|
+
# .env
|
|
18
|
+
OPENAI_API_KEY=sk-xxx
|
|
38
19
|
```
|
|
39
20
|
|
|
40
|
-
## Quick Start
|
|
41
|
-
|
|
42
21
|
```ts
|
|
43
|
-
import {
|
|
22
|
+
import { generateText } from 'ai'
|
|
44
23
|
import { envProvider } from 'ai-sdk-provider-env'
|
|
45
24
|
|
|
46
|
-
const
|
|
47
|
-
env: envProvider(),
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
// Use a preset: only API_KEY is required
|
|
51
|
-
// OPENAI_API_KEY=sk-xxx (OPENAI_PRESET=openai is optional — auto-detected)
|
|
52
|
-
const model = registry.languageModel('env:openai/gpt-4o')
|
|
25
|
+
const provider = envProvider()
|
|
53
26
|
|
|
54
|
-
const { text } = await generateText({
|
|
27
|
+
const { text } = await generateText({
|
|
28
|
+
model: provider.languageModel('openai/gpt-4o'),
|
|
29
|
+
prompt: 'Hello!',
|
|
30
|
+
})
|
|
55
31
|
```
|
|
56
32
|
|
|
57
|
-
|
|
33
|
+
The config set name `openai` auto-matches the built-in preset — only an API key is needed.
|
|
34
|
+
|
|
35
|
+
Any [valid](#environment-variables) env var prefix becomes a config set. Two endpoints, zero code changes:
|
|
58
36
|
|
|
59
37
|
```bash
|
|
60
38
|
# .env
|
|
@@ -66,259 +44,86 @@ SMART_API_KEY=key-smart
|
|
|
66
44
|
```
|
|
67
45
|
|
|
68
46
|
```ts
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
prompt: 'Write a story',
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
const review = await generateText({
|
|
75
|
-
model: registry.languageModel('env:smart/gpt-4o'),
|
|
76
|
-
prompt: `Review this: ${draft.text}`,
|
|
77
|
-
})
|
|
47
|
+
provider.languageModel('fast/llama-3-8b')
|
|
48
|
+
provider.languageModel('smart/gpt-4o')
|
|
78
49
|
```
|
|
79
50
|
|
|
80
|
-
## Environment
|
|
81
|
-
|
|
82
|
-
The model ID format is `{configSet}/{modelId}`. The config set name maps to an env var prefix (uppercased).
|
|
83
|
-
|
|
84
|
-
With the default separator `_`, a config set reads these variables (`[MYAI]` = your config set name, uppercased):
|
|
85
|
-
|
|
86
|
-
| Variable | Required | Description |
|
|
87
|
-
|---|---|---|
|
|
88
|
-
| `[MYAI]_API_KEY` | Yes | API key |
|
|
89
|
-
| `[MYAI]_BASE_URL` | Yes (unless preset is set or auto-detected) | API base URL |
|
|
90
|
-
| `[MYAI]_PRESET` | No | Built-in preset name (e.g. `openai`) |
|
|
91
|
-
| `[MYAI]_COMPATIBLE` | No | Compatibility mode (default: `openai-compatible`) |
|
|
92
|
-
| `[MYAI]_HEADERS` | No | Custom HTTP headers (JSON format) |
|
|
93
|
-
|
|
94
|
-
When `PRESET` is set, `BASE_URL` and `COMPATIBLE` become optional and fall back to the preset's values.
|
|
95
|
-
|
|
96
|
-
**Compatibility modes:**
|
|
97
|
-
|
|
98
|
-
| Value | Behavior |
|
|
99
|
-
|---|---|
|
|
100
|
-
| `openai` | Uses `@ai-sdk/openai` |
|
|
101
|
-
| `anthropic` | Uses `@ai-sdk/anthropic` |
|
|
102
|
-
| `gemini` | Uses `@ai-sdk/google` |
|
|
103
|
-
| `openai-compatible` | Uses `@ai-sdk/openai-compatible` with the config set name as the provider name (default) |
|
|
104
|
-
|
|
105
|
-
## Built-in Presets
|
|
106
|
-
|
|
107
|
-
| Preset name | Base URL | Compatible |
|
|
108
|
-
|---|---|---|
|
|
109
|
-
| `openai` | `https://api.openai.com/v1` | `openai` |
|
|
110
|
-
| `anthropic` | `https://api.anthropic.com` | `anthropic` |
|
|
111
|
-
| `google` | `https://generativelanguage.googleapis.com/v1beta` | `gemini` |
|
|
112
|
-
| `deepseek` | `https://api.deepseek.com` | `openai-compatible` |
|
|
113
|
-
| `zhipu` | `https://open.bigmodel.cn/api/paas/v4` | `openai-compatible` |
|
|
114
|
-
| `groq` | `https://api.groq.com/openai/v1` | `openai-compatible` |
|
|
115
|
-
| `together` | `https://api.together.xyz/v1` | `openai-compatible` |
|
|
116
|
-
| `fireworks` | `https://api.fireworks.ai/inference/v1` | `openai-compatible` |
|
|
117
|
-
| `mistral` | `https://api.mistral.ai/v1` | `openai-compatible` |
|
|
118
|
-
| `moonshot` | `https://api.moonshot.cn/v1` | `openai-compatible` |
|
|
119
|
-
| `perplexity` | `https://api.perplexity.ai` | `openai-compatible` |
|
|
120
|
-
| `openrouter` | `https://openrouter.ai/api/v1` | `openai-compatible` |
|
|
121
|
-
| `siliconflow` | `https://api.siliconflow.cn/v1` | `openai-compatible` |
|
|
51
|
+
## Environment Variables
|
|
122
52
|
|
|
123
|
-
|
|
53
|
+
Model ID format: `{configSet}/{modelId}`. The config set maps to an uppercased env var prefix.
|
|
124
54
|
|
|
125
|
-
|
|
55
|
+
Config set names must match `[A-Za-z_][A-Za-z0-9_-]*` — ASCII letters, digits, underscores, and hyphens. **Hyphens are automatically normalized to underscores** for env var lookup:
|
|
126
56
|
|
|
127
57
|
```bash
|
|
128
|
-
#
|
|
129
|
-
|
|
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 })
|
|
58
|
+
# Config set "my-api" → reads MY_API_* env vars
|
|
59
|
+
MY_API_BASE_URL=https://api.example.com/v1
|
|
60
|
+
MY_API_API_KEY=sk-xxx
|
|
143
61
|
```
|
|
144
62
|
|
|
145
|
-
## API Reference
|
|
146
|
-
|
|
147
|
-
### `envProvider(options?)`
|
|
148
|
-
|
|
149
|
-
Returns a `ProviderV3` instance.
|
|
150
|
-
|
|
151
63
|
```ts
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const provider = envProvider(options)
|
|
64
|
+
provider.languageModel('my-api/some-model') // reads MY_API_* env vars
|
|
65
|
+
provider.languageModel('my_api/some-model') // same env vars
|
|
155
66
|
```
|
|
156
67
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
| Option | Type | Default | Description |
|
|
160
|
-
|---|---|---|---|
|
|
161
|
-
| `separator` | `string` | `'_'` | Separator between the prefix and the variable name |
|
|
162
|
-
| `configs` | `Record<string, ConfigSetEntry>` | `undefined` | Explicit config sets (takes precedence over env vars) |
|
|
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). |
|
|
166
|
-
|
|
167
|
-
**`EnvProviderDefaults`:**
|
|
168
|
-
|
|
169
|
-
| Option | Type | Default | Description |
|
|
170
|
-
|---|---|---|---|
|
|
171
|
-
| `fetch` | `typeof globalThis.fetch` | `undefined` | Custom fetch implementation passed to all created providers |
|
|
172
|
-
| `headers` | `Record<string, string>` | `undefined` | Default HTTP headers for all providers (overridden by config-set headers) |
|
|
173
|
-
|
|
174
|
-
**`ConfigSetEntry`:**
|
|
175
|
-
|
|
176
|
-
```ts
|
|
177
|
-
interface ConfigSetEntry {
|
|
178
|
-
apiKey: string
|
|
179
|
-
preset?: string
|
|
180
|
-
baseURL?: string
|
|
181
|
-
compatible?: 'openai' | 'anthropic' | 'gemini' | 'openai-compatible' // default: 'openai-compatible'
|
|
182
|
-
headers?: Record<string, string>
|
|
183
|
-
}
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
**Model ID format:**
|
|
187
|
-
|
|
188
|
-
```
|
|
189
|
-
{configSet}/{modelId}
|
|
190
|
-
```
|
|
68
|
+
> For config set names outside these rules (e.g. Unicode, dots), use the [`configs` option](./docs/advanced.md#code-based-configs) instead.
|
|
191
69
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
```ts
|
|
201
|
-
const provider = envProvider({ separator: '__' })
|
|
202
|
-
|
|
203
|
-
// Now reads: OPENAI__BASE_URL, OPENAI__API_KEY, OPENAI__PRESET, OPENAI__COMPATIBLE
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
### Code-based configs
|
|
207
|
-
|
|
208
|
-
Skip env vars entirely and pass config directly. This takes the highest precedence:
|
|
209
|
-
|
|
210
|
-
```ts
|
|
211
|
-
const provider = envProvider({
|
|
212
|
-
configs: {
|
|
213
|
-
openai: {
|
|
214
|
-
baseURL: 'https://api.openai.com/v1',
|
|
215
|
-
apiKey: process.env.OPENAI_KEY!,
|
|
216
|
-
compatible: 'openai',
|
|
217
|
-
},
|
|
218
|
-
claude: {
|
|
219
|
-
baseURL: 'https://api.anthropic.com',
|
|
220
|
-
apiKey: process.env.ANTHROPIC_KEY!,
|
|
221
|
-
compatible: 'anthropic',
|
|
222
|
-
},
|
|
223
|
-
deepseek: {
|
|
224
|
-
preset: 'deepseek',
|
|
225
|
-
apiKey: process.env.DEEPSEEK_KEY!,
|
|
226
|
-
},
|
|
227
|
-
},
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
const model = provider.languageModel('openai/gpt-4o')
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
### Custom fetch
|
|
234
|
-
|
|
235
|
-
Pass a custom fetch implementation to all providers. Useful for proxies, logging, or test mocks:
|
|
70
|
+
| Variable | Required | Description |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| `{PREFIX}_API_KEY` | Yes | API key |
|
|
73
|
+
| `{PREFIX}_BASE_URL` | Unless preset matches | API base URL |
|
|
74
|
+
| `{PREFIX}_PRESET` | No | Built-in preset name (e.g. `openai`) |
|
|
75
|
+
| `{PREFIX}_COMPATIBLE` | No | `openai` · `anthropic` · `gemini` · `openai-compatible` (default) |
|
|
76
|
+
| `{PREFIX}_HEADERS` | No | Custom HTTP headers (JSON) |
|
|
236
77
|
|
|
237
|
-
|
|
238
|
-
const provider = envProvider({ defaults: { fetch: myCustomFetch } })
|
|
239
|
-
```
|
|
78
|
+
When `_PRESET` is set or [auto-detected](#built-in-presets), `_BASE_URL` and `_COMPATIBLE` fall back to preset defaults.
|
|
240
79
|
|
|
241
|
-
###
|
|
80
|
+
### Compatibility modes
|
|
242
81
|
|
|
243
|
-
|
|
82
|
+
| Value | SDK | Fallback |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| `openai` | `@ai-sdk/openai` | `@ai-sdk/openai-compatible` if not installed |
|
|
85
|
+
| `anthropic` | `@ai-sdk/anthropic` | None |
|
|
86
|
+
| `gemini` | `@ai-sdk/google` | None |
|
|
87
|
+
| `openai-compatible` | `@ai-sdk/openai-compatible` (default) | — |
|
|
244
88
|
|
|
245
|
-
|
|
246
|
-
const provider = envProvider({
|
|
247
|
-
defaults: {
|
|
248
|
-
headers: { 'X-App-Name': 'my-app', 'X-Request-Source': 'server' },
|
|
249
|
-
},
|
|
250
|
-
})
|
|
251
|
-
```
|
|
89
|
+
Install provider SDKs as needed: `pnpm add @ai-sdk/openai @ai-sdk/anthropic @ai-sdk/google`
|
|
252
90
|
|
|
253
|
-
|
|
91
|
+
## Built-in Presets
|
|
254
92
|
|
|
255
|
-
|
|
93
|
+
When the config set name matches a preset, it auto-applies — only `_API_KEY` is needed:
|
|
256
94
|
|
|
257
95
|
```bash
|
|
258
|
-
|
|
96
|
+
DEEPSEEK_API_KEY=sk-xxx # config set "deepseek" matches the preset
|
|
259
97
|
```
|
|
260
98
|
|
|
261
|
-
These headers are merged into every request made by that config set's provider. When combined with `defaults.headers`, config-set headers take precedence for the same key.
|
|
262
|
-
|
|
263
|
-
### Using with `createProviderRegistry`
|
|
264
|
-
|
|
265
|
-
`envProvider()` implements `ProviderV3`, so it works directly with `createProviderRegistry`:
|
|
266
|
-
|
|
267
99
|
```ts
|
|
268
|
-
|
|
269
|
-
import { envProvider } from 'ai-sdk-provider-env'
|
|
270
|
-
|
|
271
|
-
const registry = createProviderRegistry({
|
|
272
|
-
env: envProvider(),
|
|
273
|
-
})
|
|
274
|
-
|
|
275
|
-
// Language model
|
|
276
|
-
const model = registry.languageModel('env:openai/gpt-4o')
|
|
277
|
-
|
|
278
|
-
// Embedding model
|
|
279
|
-
const embedder = registry.embeddingModel('env:openai/text-embedding-3-small')
|
|
280
|
-
|
|
281
|
-
// Image model
|
|
282
|
-
const imageModel = registry.imageModel('env:openai/dall-e-3')
|
|
283
|
-
|
|
284
|
-
const { text } = await generateText({
|
|
285
|
-
model,
|
|
286
|
-
prompt: 'Hello!',
|
|
287
|
-
})
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
The model ID format inside the registry is `{registryKey}:{configSet}/{modelId}`. With the setup above, `env:openai/gpt-4o` means config set `openai`, model `gpt-4o`.
|
|
291
|
-
|
|
292
|
-
You can also mount multiple providers side by side:
|
|
293
|
-
|
|
294
|
-
```ts
|
|
295
|
-
import { createOpenAI } from '@ai-sdk/openai'
|
|
296
|
-
|
|
297
|
-
const registry = createProviderRegistry({
|
|
298
|
-
env: envProvider(),
|
|
299
|
-
openai: createOpenAI({ apiKey: process.env.OPENAI_API_KEY }),
|
|
300
|
-
})
|
|
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
|
|
100
|
+
provider.languageModel('deepseek/deepseek-chat') // just works
|
|
311
101
|
```
|
|
312
102
|
|
|
313
|
-
|
|
103
|
+
| Preset | Base URL | Compatible |
|
|
104
|
+
|---|---|---|
|
|
105
|
+
| `openai` | `https://api.openai.com/v1` | `openai` |
|
|
106
|
+
| `anthropic` | `https://api.anthropic.com` | `anthropic` |
|
|
107
|
+
| `google` | `https://generativelanguage.googleapis.com/v1beta` | `gemini` |
|
|
108
|
+
| `deepseek` | `https://api.deepseek.com` | `openai-compatible` |
|
|
109
|
+
| `groq` | `https://api.groq.com/openai/v1` | `openai-compatible` |
|
|
110
|
+
| `together` | `https://api.together.xyz/v1` | `openai-compatible` |
|
|
111
|
+
| `fireworks` | `https://api.fireworks.ai/inference/v1` | `openai-compatible` |
|
|
112
|
+
| `mistral` | `https://api.mistral.ai/v1` | `openai-compatible` |
|
|
113
|
+
| `moonshot` | `https://api.moonshot.ai/v1` | `openai-compatible` |
|
|
114
|
+
| `moonshot-china` | `https://api.moonshot.cn/v1` | `openai-compatible` |
|
|
115
|
+
| `perplexity` | `https://api.perplexity.ai` | `openai-compatible` |
|
|
116
|
+
| `openrouter` | `https://openrouter.ai/api/v1` | `openai-compatible` |
|
|
117
|
+
| `siliconflow` | `https://api.siliconflow.com/v1` | `openai-compatible` |
|
|
118
|
+
| `siliconflow-china` | `https://api.siliconflow.cn/v1` | `openai-compatible` |
|
|
119
|
+
| `xai` | `https://api.x.ai/v1` | `openai-compatible` |
|
|
120
|
+
| `zai` | `https://api.z.ai/api/paas/v4` | `openai-compatible` |
|
|
121
|
+
| `zhipu` | `https://open.bigmodel.cn/api/paas/v4` | `openai-compatible` |
|
|
314
122
|
|
|
315
|
-
|
|
316
|
-
import { createOpenAI } from '@ai-sdk/openai'
|
|
317
|
-
import { envProvider } from 'ai-sdk-provider-env'
|
|
123
|
+
To disable auto-detection: `envProvider({ presetAutoDetect: false })`. See [Advanced Usage](./docs/advanced.md#preset-auto-detect) for details.
|
|
318
124
|
|
|
319
|
-
|
|
320
|
-
factories: { openai: createOpenAI },
|
|
321
|
-
})
|
|
322
|
-
```
|
|
125
|
+
## Documentation
|
|
323
126
|
|
|
324
|
-
|
|
127
|
+
- **[API Reference](./docs/api-reference.md)** — `envProvider()` options, types, model ID format
|
|
128
|
+
- **[Advanced Usage](./docs/advanced.md)** — Code-based configs, custom fetch/headers, custom separator, provider registry
|
|
129
|
+
- **[Bundler Usage](./docs/bundler.md)** — For `bun build`, `vite build`, and other bundlers
|