diff --git a/.changeset/spotty-suits-reply.md b/.changeset/spotty-suits-reply.md
new file mode 100644
index 000000000000..df64a040fca6
--- /dev/null
+++ b/.changeset/spotty-suits-reply.md
@@ -0,0 +1,5 @@
+---
+'ai': patch
+---
+
+chore (ai/core): move custom provider to stable
diff --git a/content/docs/03-ai-sdk-core/40-provider-management.mdx b/content/docs/03-ai-sdk-core/40-provider-management.mdx
index 8145f7bfc9f0..e31d5ff6b42d 100644
--- a/content/docs/03-ai-sdk-core/40-provider-management.mdx
+++ b/content/docs/03-ai-sdk-core/40-provider-management.mdx
@@ -5,8 +5,6 @@ description: Learn how to work with multiple providers
# Provider Management
-Provider management is an experimental feature.
-
When you work with multiple providers and models, it is often desirable to manage them in a central place
and access the models through simple string ids.
@@ -18,7 +16,7 @@ The provider registry lets you mix **multiple providers** and access them throug
## Custom Providers
-You can create a [custom provider](/docs/reference/ai-sdk-core/custom-provider) using `experimental_customProvider`.
+You can create a [custom provider](/docs/reference/ai-sdk-core/custom-provider) using `customProvider`.
### Example: custom model settings
@@ -27,7 +25,7 @@ with pre-configured settings.
```ts
import { openai as originalOpenAI } from '@ai-sdk/openai';
-import { experimental_customProvider as customProvider } from 'ai';
+import { customProvider } from 'ai';
// custom provider with different model settings:
export const openai = customProvider({
@@ -49,7 +47,7 @@ You can also provide model name aliases, so you can update the model version in
```ts
import { anthropic as originalAnthropic } from '@ai-sdk/anthropic';
-import { experimental_customProvider as customProvider } from 'ai';
+import { customProvider } from 'ai';
// custom provider with alias names:
export const anthropic = customProvider({
@@ -69,7 +67,7 @@ You can limit the available models in the system, even if you have multiple prov
```ts
import { anthropic } from '@ai-sdk/anthropic';
import { openai } from '@ai-sdk/openai';
-import { experimental_customProvider as customProvider } from 'ai';
+import { customProvider } from 'ai';
export const myProvider = customProvider({
languageModels: {
@@ -87,6 +85,8 @@ export const myProvider = customProvider({
## Provider Registry
+The provider registry is an experimental feature.
+
You can create a [provider registry](/docs/reference/ai-sdk-core/provider-registry) with multiple providers and models using `experimental_createProviderRegistry`.
### Example: Setup
diff --git a/content/docs/07-reference/01-ai-sdk-core/40-provider-registry.mdx b/content/docs/07-reference/01-ai-sdk-core/40-provider-registry.mdx
index d77aaf6c05b4..b23ddc7b10a7 100644
--- a/content/docs/07-reference/01-ai-sdk-core/40-provider-registry.mdx
+++ b/content/docs/07-reference/01-ai-sdk-core/40-provider-registry.mdx
@@ -5,7 +5,7 @@ description: Registry for managing multiple providers and models (API Reference)
# `createProviderRegistry()`
-Provider management is an experimental feature.
+The provider registry is an experimental feature.
When you work with multiple providers and models, it is often desirable to manage them
in a central place and access the models through simple string ids.
diff --git a/content/docs/07-reference/01-ai-sdk-core/42-custom-provider.mdx b/content/docs/07-reference/01-ai-sdk-core/42-custom-provider.mdx
index af7d886a2052..517e2e9d200a 100644
--- a/content/docs/07-reference/01-ai-sdk-core/42-custom-provider.mdx
+++ b/content/docs/07-reference/01-ai-sdk-core/42-custom-provider.mdx
@@ -5,8 +5,6 @@ description: Custom provider that uses models from a different provider (API Ref
# `customProvider()`
-Provider management is an experimental feature.
-
With a custom provider, you can map ids to any model.
This allows you to set up custom model configurations, alias names, and more.
The custom provider also supports a fallback provider, which is useful for
@@ -18,7 +16,7 @@ You can create a custom provider using `experiental_createCustomProvider`.
```ts
import { openai } from '@ai-sdk/openai';
-import { experimental_customProvider as customProvider } from 'ai';
+import { customProvider } from 'ai';
// custom provider with different model settings:
export const myOpenAI = customProvider({
@@ -34,10 +32,7 @@ export const myOpenAI = customProvider({
## Import
-
+
## API Signature
diff --git a/examples/ai-core/src/registry/setup-registry.ts b/examples/ai-core/src/registry/setup-registry.ts
index 6f4779b9773c..d0f30a6f33e8 100644
--- a/examples/ai-core/src/registry/setup-registry.ts
+++ b/examples/ai-core/src/registry/setup-registry.ts
@@ -8,7 +8,7 @@ import { replicate } from '@ai-sdk/replicate';
import { xai } from '@ai-sdk/xai';
import {
experimental_createProviderRegistry as createProviderRegistry,
- experimental_customProvider as customProvider,
+ customProvider,
} from 'ai';
import 'dotenv/config';
diff --git a/packages/ai/core/registry/custom-provider.test.ts b/packages/ai/core/registry/custom-provider.test.ts
index 06d3ec42b3da..a41f813dba2a 100644
--- a/packages/ai/core/registry/custom-provider.test.ts
+++ b/packages/ai/core/registry/custom-provider.test.ts
@@ -1,10 +1,9 @@
import { NoSuchModelError } from '@ai-sdk/provider';
import { describe, expect, it, vi } from 'vitest';
-import { experimental_customProvider } from './custom-provider';
-
import { MockEmbeddingModelV1 } from '../test/mock-embedding-model-v1';
import { MockImageModelV1 } from '../test/mock-image-model-v1';
import { MockLanguageModelV1 } from '../test/mock-language-model-v1';
+import { customProvider } from './custom-provider';
const mockLanguageModel = new MockLanguageModelV1();
const mockEmbeddingModel = new MockEmbeddingModelV1();
@@ -16,7 +15,7 @@ const mockFallbackProvider = {
describe('languageModel', () => {
it('should return the language model if it exists', () => {
- const provider = experimental_customProvider({
+ const provider = customProvider({
languageModels: { 'test-model': mockLanguageModel },
});
@@ -26,7 +25,7 @@ describe('languageModel', () => {
it('should use fallback provider if model not found and fallback exists', () => {
mockFallbackProvider.languageModel.mockReturnValue(mockLanguageModel);
- const provider = experimental_customProvider({
+ const provider = customProvider({
fallbackProvider: mockFallbackProvider,
});
@@ -37,7 +36,7 @@ describe('languageModel', () => {
});
it('should throw NoSuchModelError if model not found and no fallback', () => {
- const provider = experimental_customProvider({});
+ const provider = customProvider({});
expect(() => provider.languageModel('test-model')).toThrow(
NoSuchModelError,
);
@@ -46,7 +45,7 @@ describe('languageModel', () => {
describe('textEmbeddingModel', () => {
it('should return the embedding model if it exists', () => {
- const provider = experimental_customProvider({
+ const provider = customProvider({
textEmbeddingModels: { 'test-model': mockEmbeddingModel },
});
@@ -56,7 +55,7 @@ describe('textEmbeddingModel', () => {
it('should use fallback provider if model not found and fallback exists', () => {
mockFallbackProvider.textEmbeddingModel.mockReturnValue(mockEmbeddingModel);
- const provider = experimental_customProvider({
+ const provider = customProvider({
fallbackProvider: mockFallbackProvider,
});
@@ -67,7 +66,7 @@ describe('textEmbeddingModel', () => {
});
it('should throw NoSuchModelError if model not found and no fallback', () => {
- const provider = experimental_customProvider({});
+ const provider = customProvider({});
expect(() => provider.textEmbeddingModel('test-model')).toThrow(
NoSuchModelError,
@@ -79,7 +78,7 @@ describe('imageModel', () => {
const mockImageModel = new MockImageModelV1();
it('should return the image model if it exists', () => {
- const provider = experimental_customProvider({
+ const provider = customProvider({
imageModels: { 'test-model': mockImageModel },
});
@@ -89,7 +88,7 @@ describe('imageModel', () => {
it('should use fallback provider if model not found and fallback exists', () => {
mockFallbackProvider.imageModel = vi.fn().mockReturnValue(mockImageModel);
- const provider = experimental_customProvider({
+ const provider = customProvider({
fallbackProvider: mockFallbackProvider,
});
@@ -98,7 +97,7 @@ describe('imageModel', () => {
});
it('should throw NoSuchModelError if model not found and no fallback', () => {
- const provider = experimental_customProvider({});
+ const provider = customProvider({});
expect(() => provider.imageModel('test-model')).toThrow(NoSuchModelError);
});
diff --git a/packages/ai/core/registry/custom-provider.ts b/packages/ai/core/registry/custom-provider.ts
index 205ed2d8b7e7..e0774a14556b 100644
--- a/packages/ai/core/registry/custom-provider.ts
+++ b/packages/ai/core/registry/custom-provider.ts
@@ -18,7 +18,7 @@ import { NoSuchModelError } from '@ai-sdk/provider';
*
* @throws {NoSuchModelError} Throws when a requested model is not found and no fallback provider is available.
*/
-export function experimental_customProvider<
+export function customProvider<
LANGUAGE_MODELS extends Record,
EMBEDDING_MODELS extends Record>,
IMAGE_MODELS extends Record,
@@ -80,6 +80,11 @@ export function experimental_customProvider<
};
}
+/**
+ * @deprecated Use `customProvider` instead.
+ */
+export const experimental_customProvider = customProvider;
+
type ExtractModelId> = Extract<
keyof MODELS,
string
diff --git a/packages/ai/core/registry/index.ts b/packages/ai/core/registry/index.ts
index 6dbb02fee572..73384da6293d 100644
--- a/packages/ai/core/registry/index.ts
+++ b/packages/ai/core/registry/index.ts
@@ -1,3 +1,3 @@
-export { experimental_customProvider } from './custom-provider';
-export * from './no-such-provider-error';
-export * from './provider-registry';
+export { customProvider, experimental_customProvider } from './custom-provider';
+export { NoSuchProviderError } from './no-such-provider-error';
+export { experimental_createProviderRegistry } from './provider-registry';