Skip to content

Commit 74c4f22

Browse files
fix(core): support LanguageModelV3 in MastraModelGateway.resolveLanguageModel (#11489)
## Summary This PR enables custom gateways to return either `LanguageModelV2` (AI SDK v5) or `LanguageModelV3` (AI SDK v6) from the `resolveLanguageModel` method. ## Changes - **`packages/core/src/llm/model/gateways/base.ts`** - Added `GatewayLanguageModel` union type (`LanguageModelV2 | LanguageModelV3`) - Updated `MastraModelGateway.resolveLanguageModel` abstract method to return `GatewayLanguageModel` - **`packages/core/src/llm/model/router.ts`** - Added `isLanguageModelV3` type guard function - Updated `doGenerate` and `doStream` methods to detect V3 models and wrap them with `AISDKV6LanguageModel` - Updated internal `resolveLanguageModel` return type and `modelInstances` Map to use `GatewayLanguageModel` - **`packages/core/src/llm/model/gateways/index.ts`** & **`packages/core/src/llm/index.ts`** - Exported `GatewayLanguageModel` type for external use ## Example Usage ```typescript import { MastraModelGateway, type GatewayLanguageModel } from '@mastra/core/llm'; import { createOpenAICompatible } from '@ai-sdk/openai-compatible'; // v6 class CustomGateway extends MastraModelGateway { async resolveLanguageModel({ modelId, providerId, apiKey }): Promise<GatewayLanguageModel> { // Now works with both V2 and V3! return createOpenAICompatible({ name: providerId, apiKey, baseURL: 'https://...', }).chatModel(modelId); } } ``` ## Testing - All 115 gateway and router tests pass ✅ - Type check passes ✅ Fixes #11443 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for AI SDK v6 language models in the core runtime. * Routing and model resolution updated to handle mixed v5/v6 models while preserving full backward compatibility with existing v5 workflows. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Abhi Aiyer <abhiaiyer91@gmail.com>
1 parent 4f0b3c6 commit 74c4f22

File tree

5 files changed

+43
-6
lines changed

5 files changed

+43
-6
lines changed

.changeset/giant-maps-kiss.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@mastra/core": patch
3+
---
4+
5+
fix(core): support LanguageModelV3 in MastraModelGateway.resolveLanguageModel

packages/core/src/llm/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ export type LLMStreamObjectOptions<Z extends ZodSchema | JSONSchema7 | undefined
148148
} & LLMInnerStreamOptions<Z> &
149149
DefaultLLMStreamObjectOptions;
150150

151-
export type { ProviderConfig } from './model/gateways/base';
151+
export type { ProviderConfig, GatewayLanguageModel } from './model/gateways/base';
152152
export { MastraModelGateway, NetlifyGateway, ModelsDevGateway, AzureOpenAIGateway } from './model/gateways';
153153
export type { AzureOpenAIGatewayConfig } from './model/gateways';
154154

packages/core/src/llm/model/gateways/base.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
import type { LanguageModelV2 } from '@ai-sdk/provider-v5';
7+
import type { LanguageModelV3 } from '@ai-sdk/provider-v6';
78

89
export interface ProviderConfig {
910
url?: string;
@@ -15,6 +16,12 @@ export interface ProviderConfig {
1516
gateway: string;
1617
}
1718

19+
/**
20+
* Union type for language models that can be returned by gateways.
21+
* Supports both AI SDK v5 (LanguageModelV2) and v6 (LanguageModelV3).
22+
*/
23+
export type GatewayLanguageModel = LanguageModelV2 | LanguageModelV3;
24+
1825
export abstract class MastraModelGateway {
1926
/**
2027
* Unique identifier for the gateway
@@ -51,10 +58,14 @@ export abstract class MastraModelGateway {
5158

5259
abstract getApiKey(modelId: string): Promise<string>;
5360

61+
/**
62+
* Resolve a language model from the gateway.
63+
* Supports returning either LanguageModelV2 (AI SDK v5) or LanguageModelV3 (AI SDK v6).
64+
*/
5465
abstract resolveLanguageModel(args: {
5566
modelId: string;
5667
providerId: string;
5768
apiKey: string;
5869
headers?: Record<string, string>;
59-
}): Promise<LanguageModelV2> | LanguageModelV2;
70+
}): Promise<GatewayLanguageModel> | GatewayLanguageModel;
6071
}

packages/core/src/llm/model/gateways/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { MastraError } from '../../../error/index.js';
22
import type { MastraModelGateway } from './base.js';
3-
export { MastraModelGateway, type ProviderConfig } from './base.js';
3+
export { MastraModelGateway, type ProviderConfig, type GatewayLanguageModel } from './base.js';
44
export { AzureOpenAIGateway, type AzureOpenAIGatewayConfig } from './azure.js';
55
export { ModelsDevGateway } from './models-dev.js';
66
export { NetlifyGateway } from './netlify.js';

packages/core/src/llm/model/router.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { createHash } from 'node:crypto';
22
import { createOpenAICompatible } from '@ai-sdk/openai-compatible-v5';
33
import type { LanguageModelV2, LanguageModelV2CallOptions, LanguageModelV2StreamPart } from '@ai-sdk/provider-v5';
4+
import type { LanguageModelV3 } from '@ai-sdk/provider-v6';
45
import { AISDKV5LanguageModel } from './aisdk/v5/model';
6+
import { AISDKV6LanguageModel } from './aisdk/v6/model';
57
import { parseModelRouterId } from './gateway-resolver.js';
6-
import type { MastraModelGateway } from './gateways/base.js';
8+
import type { GatewayLanguageModel, MastraModelGateway } from './gateways/base.js';
79
import { findGatewayForModel } from './gateways/index.js';
810

911
import { ModelsDevGateway } from './gateways/models-dev.js';
@@ -12,6 +14,13 @@ import type { ModelRouterModelId } from './provider-registry.js';
1214
import { PROVIDER_REGISTRY } from './provider-registry.js';
1315
import type { MastraLanguageModelV2, OpenAICompatibleConfig } from './shared.types';
1416

17+
/**
18+
* Type guard to check if a model is a LanguageModelV3 (AI SDK v6)
19+
*/
20+
function isLanguageModelV3(model: GatewayLanguageModel): model is LanguageModelV3 {
21+
return model.specificationVersion === 'v3';
22+
}
23+
1524
type StreamResult = Awaited<ReturnType<LanguageModelV2['doStream']>>;
1625

1726
function getStaticProvidersByGateway(name: string) {
@@ -127,6 +136,12 @@ export class ModelRouterLanguageModel implements MastraLanguageModelV2 {
127136
...parseModelRouterId(this.config.routerId, gatewayPrefix),
128137
});
129138

139+
// Handle both V2 and V3 models
140+
if (isLanguageModelV3(model)) {
141+
const aiSDKV6Model = new AISDKV6LanguageModel(model);
142+
// Cast V3 stream result to V2 format - the stream contents are compatible at runtime
143+
return aiSDKV6Model.doGenerate(options as any) as unknown as Promise<StreamResult>;
144+
}
130145
const aiSDKV5Model = new AISDKV5LanguageModel(model);
131146
return aiSDKV5Model.doGenerate(options);
132147
}
@@ -164,6 +179,12 @@ export class ModelRouterLanguageModel implements MastraLanguageModelV2 {
164179
...parseModelRouterId(this.config.routerId, gatewayPrefix),
165180
});
166181

182+
// Handle both V2 and V3 models
183+
if (isLanguageModelV3(model)) {
184+
const aiSDKV6Model = new AISDKV6LanguageModel(model);
185+
// Cast V3 stream result to V2 format - the stream contents are compatible at runtime
186+
return aiSDKV6Model.doStream(options as any) as unknown as Promise<StreamResult>;
187+
}
167188
const aiSDKV5Model = new AISDKV5LanguageModel(model);
168189
return aiSDKV5Model.doStream(options);
169190
}
@@ -178,7 +199,7 @@ export class ModelRouterLanguageModel implements MastraLanguageModelV2 {
178199
providerId: string;
179200
apiKey: string;
180201
headers?: Record<string, string>;
181-
}): Promise<LanguageModelV2> {
202+
}): Promise<GatewayLanguageModel> {
182203
const key = createHash('sha256')
183204
.update(
184205
this.gateway.id +
@@ -208,5 +229,5 @@ export class ModelRouterLanguageModel implements MastraLanguageModelV2 {
208229
ModelRouterLanguageModel.modelInstances.set(key, modelInstance);
209230
return modelInstance;
210231
}
211-
private static modelInstances = new Map<string, LanguageModelV2>();
232+
private static modelInstances = new Map<string, GatewayLanguageModel>();
212233
}

0 commit comments

Comments
 (0)