Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/hot-onions-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@ai-sdk/anthropic': patch
'@ai-sdk/google': patch
---

Support for custom provider name in google and anthropic providers
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { createAnthropic } from '@ai-sdk/anthropic';
import { generateText } from 'ai';
import 'dotenv/config';

import { NodeSDK } from '@opentelemetry/sdk-node';
import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';

const sdk = new NodeSDK({
traceExporter: new ConsoleSpanExporter(),
instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start();

async function main() {
const myCustomProvider = createAnthropic({
name: 'my-anthropic-proxy',
});

await generateText({
model: myCustomProvider('claude-sonnet-4-20250514'),
prompt: 'Say hello in 5 words',
experimental_telemetry: {
isEnabled: true,
functionId: 'anthropic-custom-provider-demo',
metadata: {
environment: 'demo',
endpoint_type: 'my-anthropic-proxy',
cost_tracking: 'enabled',
},
},
});

await sdk.shutdown();
}

main().catch(console.error);
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { createGoogleGenerativeAI } from '@ai-sdk/google';
import { generateText } from 'ai';
import 'dotenv/config';

import { NodeSDK } from '@opentelemetry/sdk-node';
import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';

const sdk = new NodeSDK({
traceExporter: new ConsoleSpanExporter(),
instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start();

async function main() {
const myCustomProvider = createGoogleGenerativeAI({
name: 'my-custom-provider',
});

await generateText({
model: myCustomProvider('gemini-2.5-flash'),
prompt: 'Say hello in 5 words',
experimental_telemetry: {
isEnabled: true,
functionId: 'custom-provider-demo',
metadata: {
environment: 'demo',
customer_id: 'demo-user',
request_source: 'example',
},
},
});

await sdk.shutdown();
}

main().catch(console.error);
25 changes: 25 additions & 0 deletions packages/anthropic/src/anthropic-provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,28 @@ describe('createAnthropic', () => {
});
});
});

describe('anthropic provider - custom provider name', () => {
beforeEach(() => {
vi.clearAllMocks();
});

it('should use custom provider name when specified', () => {
const provider = createAnthropic({
name: 'my-claude-proxy',
apiKey: 'test-api-key',
});

const model = provider('claude-3-haiku-20240307');
expect(model.provider).toBe('my-claude-proxy');
});

it('should default to anthropic.messages when name not specified', () => {
const provider = createAnthropic({
apiKey: 'test-api-key',
});

const model = provider('claude-3-haiku-20240307');
expect(model.provider).toBe('anthropic.messages');
});
});
10 changes: 9 additions & 1 deletion packages/anthropic/src/anthropic-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ or to provide a custom fetch implementation for e.g. testing.
fetch?: FetchFunction;

generateId?: () => string;

/**
* Custom provider name
* Defaults to 'anthropic.messages'.
*/
name?: string;
}

/**
Expand All @@ -78,6 +84,8 @@ export function createAnthropic(
}),
) ?? 'https://api.anthropic.com/v1';

const providerName = options.name ?? 'anthropic.messages';

const getHeaders = () =>
withUserAgentSuffix(
{
Expand All @@ -94,7 +102,7 @@ export function createAnthropic(

const createChatModel = (modelId: AnthropicMessagesModelId) =>
new AnthropicMessagesLanguageModel(modelId, {
provider: 'anthropic.messages',
provider: providerName,
baseURL,
headers: getHeaders,
fetch: options.fetch,
Expand Down
37 changes: 37 additions & 0 deletions packages/google/src/google-provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,3 +268,40 @@ describe('google-provider', () => {
`);
});
});

describe('google provider - custom provider name', () => {
beforeEach(() => {
vi.clearAllMocks();
});

it('should use custom provider name when specified', () => {
const provider = createGoogleGenerativeAI({
name: 'my-gemini-proxy',
apiKey: 'test-api-key',
});

provider('gemini-pro');

expect(GoogleGenerativeAILanguageModel).toHaveBeenCalledWith(
'gemini-pro',
expect.objectContaining({
provider: 'my-gemini-proxy',
}),
);
});

it('should default to google.generative-ai when name not specified', () => {
const provider = createGoogleGenerativeAI({
apiKey: 'test-api-key',
});

provider('gemini-pro');

expect(GoogleGenerativeAILanguageModel).toHaveBeenCalledWith(
'gemini-pro',
expect.objectContaining({
provider: 'google.generative-ai',
}),
);
});
});
14 changes: 11 additions & 3 deletions packages/google/src/google-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ or to provide a custom fetch implementation for e.g. testing.
Optional function to generate a unique ID for each request.
*/
generateId?: () => string;

/**
* Custom provider name
* Defaults to 'google.generative-ai'.
*/
name?: string;
}

/**
Expand All @@ -102,6 +108,8 @@ export function createGoogleGenerativeAI(
withoutTrailingSlash(options.baseURL) ??
'https://generativelanguage.googleapis.com/v1beta';

const providerName = options.name ?? 'google.generative-ai';

const getHeaders = () =>
withUserAgentSuffix(
{
Expand All @@ -117,7 +125,7 @@ export function createGoogleGenerativeAI(

const createChatModel = (modelId: GoogleGenerativeAIModelId) =>
new GoogleGenerativeAILanguageModel(modelId, {
provider: 'google.generative-ai',
provider: providerName,
baseURL,
headers: getHeaders,
generateId: options.generateId ?? generateId,
Expand All @@ -138,7 +146,7 @@ export function createGoogleGenerativeAI(

const createEmbeddingModel = (modelId: GoogleGenerativeAIEmbeddingModelId) =>
new GoogleGenerativeAIEmbeddingModel(modelId, {
provider: 'google.generative-ai',
provider: providerName,
baseURL,
headers: getHeaders,
fetch: options.fetch,
Expand All @@ -149,7 +157,7 @@ export function createGoogleGenerativeAI(
settings: GoogleGenerativeAIImageSettings = {},
) =>
new GoogleGenerativeAIImageModel(modelId, settings, {
provider: 'google.generative-ai',
provider: providerName,
baseURL,
headers: getHeaders,
fetch: options.fetch,
Expand Down
Loading