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 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
- A dynamic, environment-variable-driven provider for [Vercel AI SDK](https://sdk.vercel.ai/). Resolves AI provider configuration from env var conventions at runtime, so you can switch models without touching code.
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
  [![npm version](https://img.shields.io/npm/v/ai-sdk-provider-env)](https://www.npmjs.com/package/ai-sdk-provider-env)
8
8
  [![license](https://img.shields.io/npm/l/ai-sdk-provider-env)](./LICENSE)
9
9
 
10
- ## Motivation
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
- pnpm add @ai-sdk/openai # for OpenAI
35
- pnpm add @ai-sdk/anthropic # for Anthropic
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 { createProviderRegistry, generateText } from 'ai'
22
+ import { generateText } from 'ai'
44
23
  import { envProvider } from 'ai-sdk-provider-env'
45
24
 
46
- const registry = createProviderRegistry({
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({ model, prompt: 'Hello!' })
27
+ const { text } = await generateText({
28
+ model: provider.languageModel('openai/gpt-4o'),
29
+ prompt: 'Hello!',
30
+ })
55
31
  ```
56
32
 
57
- Any env var prefix is a config set. Two endpoints? Two prefixes, zero code changes:
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
- const draft = await generateText({
70
- model: registry.languageModel('env:fast/llama-3-8b'),
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 Variable Convention
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
- ## Preset Auto-Detect
53
+ Model ID format: `{configSet}/{modelId}`. The config set maps to an uppercased env var prefix.
124
54
 
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:
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
- # 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 })
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
- import { envProvider } from 'ai-sdk-provider-env'
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
- **Options** (`EnvProviderOptions`):
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
- Examples: `openai/gpt-4o`, `anthropic/claude-sonnet-4-20250514`, `myapi/some-model`.
193
-
194
- ## Advanced Usage
195
-
196
- ### Custom separator
197
-
198
- If single underscores conflict with your naming scheme, use double underscores or any other string:
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
- ```ts
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
- ### Default headers
80
+ ### Compatibility modes
242
81
 
243
- Set HTTP headers that apply to all providers. Per-config-set headers (from env vars or code configs) override defaults with the same key:
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
- ```ts
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
- ### Custom headers via env vars
91
+ ## Built-in Presets
254
92
 
255
- Set per-config-set HTTP headers using the `HEADERS` env var. The value must be valid JSON:
93
+ When the config set name matches a preset, it auto-applies only `_API_KEY` is needed:
256
94
 
257
95
  ```bash
258
- OPENAI_HEADERS={"X-Custom":"value","X-Request-Source":"my-app"}
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
- import { createProviderRegistry, generateText } from 'ai'
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
- **Option B** provide explicit factories (single-file / `bun build --compile`):
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
- ```ts
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
- const provider = envProvider({
320
- factories: { openai: createOpenAI },
321
- })
322
- ```
125
+ ## Documentation
323
126
 
324
- For the full guide (factory key mapping, lazy-strict behavior, combining with other options), see **[Bundler Usage Guide](./docs/bundler.md)**.
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