Skip to content

Commit 176466a

Browse files
authored
chore(provider): align V4 model return types to have their own definitions across all model interfaces (#14250)
## Background Many V4 model interfaces in `provider` defined their return types inline inside the `doGenerate`/`doEmbed`/etc. method signatures. This made it cumbersome to reference those types by name elsewhere (requiring `Awaited<ReturnType<ModelV4['doMethod']>>`). It also made them inconsistent with `LanguageModelV4` and `EmbeddingModelV4`, which were already using their own distinct type definitions for their return types. ## Summary Each V4 model interface now has its return type extracted into a dedicated file (e.g. `image-model-v4-result.ts`, `speech-model-v4-result.ts`) and exported by name. This applies to all V4 interfaces: `LanguageModelV4`, `EmbeddingModelV4`, `ImageModelV4`, `VideoModelV4`, `SpeechModelV4`, `TranscriptionModelV4`, `RerankingModelV4`, `FilesV4`, and `SkillsV4`. The `ai` package is updated to use these named types instead of the verbose `Awaited<ReturnType<...>>` pattern. ## Manual Verification N/A — pure type-level refactoring with no runtime behavior changes. ## Checklist - [ ] Tests have been added / updated (for bug fixes / features) - [ ] Documentation has been added / updated (for bug fixes / features) - [x] A _patch_ changeset for relevant packages has been added (for bug fixes / features - run `pnpm changeset` in the project root) - [x] I have reviewed this pull request (self-review) ## Future Work N/A ## Related Issues N/A
1 parent 6360015 commit 176466a

28 files changed

+579
-526
lines changed

.changeset/hot-pugs-count.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@ai-sdk/provider": patch
3+
"ai": patch
4+
---
5+
6+
chore(provider): align V4 model return types to have their own definitions across all model interfaces

packages/ai/src/generate-text/generate-text.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {
2-
LanguageModelV4,
32
LanguageModelV4Content,
3+
LanguageModelV4GenerateResult,
44
LanguageModelV4ToolCall,
55
} from '@ai-sdk/provider';
66
import {
@@ -673,9 +673,9 @@ export async function generateText<
673673

674674
const callSettings = prepareCallSettings(settings);
675675

676-
let currentModelResponse: Awaited<
677-
ReturnType<LanguageModelV4['doGenerate']>
678-
> & { response: { id: string; timestamp: Date; modelId: string } };
676+
let currentModelResponse: LanguageModelV4GenerateResult & {
677+
response: { id: string; timestamp: Date; modelId: string };
678+
};
679679
let clientToolCalls: Array<TypedToolCall<TOOLS>> = [];
680680
let clientToolOutputs: Array<ToolOutput<TOOLS>> = [];
681681
const steps: GenerateTextResult<TOOLS, CONTEXT, OUTPUT>['steps'] = [];

packages/ai/src/middleware/wrap-embedding-model.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
EmbeddingModelV3,
33
EmbeddingModelV4,
44
EmbeddingModelV4CallOptions,
5+
EmbeddingModelV4Result,
56
} from '@ai-sdk/provider';
67
import { asEmbeddingModelV4 } from '../model/as-embedding-model-v4';
78
import { EmbeddingModelMiddleware } from '../types';
@@ -74,7 +75,7 @@ const doWrap = ({
7475
overrideSupportsParallelCalls?.({ model }) ?? model.supportsParallelCalls,
7576
async doEmbed(
7677
params: EmbeddingModelV4CallOptions,
77-
): Promise<Awaited<ReturnType<EmbeddingModelV4['doEmbed']>>> {
78+
): Promise<EmbeddingModelV4Result> {
7879
const transformedParams = await doTransform({ params });
7980
const doEmbed = async () => model.doEmbed(transformedParams);
8081
return wrapEmbed

packages/ai/src/middleware/wrap-image-model.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
ImageModelV3,
44
ImageModelV4,
55
ImageModelV4CallOptions,
6+
ImageModelV4Result,
67
} from '@ai-sdk/provider';
78
import { asImageModelV4 } from '../model/as-image-model-v4';
89
import { ImageModelMiddleware } from '../types';
@@ -77,7 +78,7 @@ const doWrap = ({
7778
maxImagesPerCall,
7879
async doGenerate(
7980
params: ImageModelV4CallOptions,
80-
): Promise<Awaited<ReturnType<ImageModelV4['doGenerate']>>> {
81+
): Promise<ImageModelV4Result> {
8182
const transformedParams = await doTransform({ params });
8283
const doGenerate = async () => model.doGenerate(transformedParams);
8384
return wrapGenerate

packages/ai/src/upload-skill/upload-skill-result.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { SkillsV4UploadResult } from '@ai-sdk/provider';
1+
import { SkillsV4UploadSkillResult } from '@ai-sdk/provider';
22
import { ProviderReference } from '../types/provider-reference';
33
import { Warning } from '../types/warning';
44

55
export type UploadSkillResult = Omit<
6-
SkillsV4UploadResult,
6+
SkillsV4UploadSkillResult,
77
'providerReference' | 'warnings'
88
> & {
99
readonly providerReference: ProviderReference;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { SharedV4ProviderOptions } from '../../shared/v4/shared-v4-provider-options';
2+
3+
/**
4+
* Options for uploading a file via the files interface.
5+
*/
6+
export type FilesV4UploadFileCallOptions = {
7+
/**
8+
* The file data as raw bytes or a base64-encoded string.
9+
*/
10+
data: Uint8Array | string;
11+
12+
/**
13+
* The IANA media type of the file (e.g. `'application/pdf'`).
14+
*/
15+
mediaType: string;
16+
17+
/**
18+
* The filename of the file.
19+
*/
20+
filename?: string;
21+
22+
/**
23+
* Additional provider-specific options. They are passed through
24+
* to the provider from the AI SDK and enable provider-specific
25+
* functionality that can be fully encapsulated in the provider.
26+
*/
27+
providerOptions?: SharedV4ProviderOptions;
28+
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { SharedV4ProviderMetadata } from '../../shared/v4/shared-v4-provider-metadata';
2+
import { SharedV4ProviderReference } from '../../shared/v4/shared-v4-provider-reference';
3+
import { SharedV4Warning } from '../../shared/v4/shared-v4-warning';
4+
5+
/**
6+
* Result of uploading a file via the files interface.
7+
*/
8+
export type FilesV4UploadFileResult = {
9+
/**
10+
* A provider reference mapping provider names to provider-specific file identifiers.
11+
*/
12+
providerReference: SharedV4ProviderReference;
13+
14+
/**
15+
* The IANA media type of the uploaded file, if available from the provider.
16+
*/
17+
mediaType?: string;
18+
19+
/**
20+
* The filename of the uploaded file, if available from the provider.
21+
*/
22+
filename?: string;
23+
24+
/**
25+
* Additional provider-specific metadata. They are passed through
26+
* to the provider from the AI SDK and enable provider-specific
27+
* functionality that can be fully encapsulated in the provider.
28+
*/
29+
providerMetadata?: SharedV4ProviderMetadata;
30+
31+
/**
32+
* Warnings from the provider.
33+
*/
34+
warnings: Array<SharedV4Warning>;
35+
};

packages/provider/src/files/v4/files-v4.ts

Lines changed: 2 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,5 @@
1-
import { SharedV4ProviderMetadata } from '../../shared/v4/shared-v4-provider-metadata';
2-
import { SharedV4ProviderOptions } from '../../shared/v4/shared-v4-provider-options';
3-
import { SharedV4ProviderReference } from '../../shared/v4/shared-v4-provider-reference';
4-
import { SharedV4Warning } from '../../shared/v4/shared-v4-warning';
5-
6-
/**
7-
* Result of uploading a file via the files interface.
8-
*/
9-
export type FilesV4UploadFileResult = {
10-
/**
11-
* A provider reference mapping provider names to provider-specific file identifiers.
12-
*/
13-
providerReference: SharedV4ProviderReference;
14-
15-
/**
16-
* The IANA media type of the uploaded file, if available from the provider.
17-
*/
18-
mediaType?: string;
19-
20-
/**
21-
* The filename of the uploaded file, if available from the provider.
22-
*/
23-
filename?: string;
24-
25-
/**
26-
* Additional provider-specific metadata. They are passed through
27-
* to the provider from the AI SDK and enable provider-specific
28-
* functionality that can be fully encapsulated in the provider.
29-
*/
30-
providerMetadata?: SharedV4ProviderMetadata;
31-
32-
/**
33-
* Warnings from the provider.
34-
*/
35-
warnings: Array<SharedV4Warning>;
36-
};
37-
38-
/**
39-
* Options for uploading a file via the files interface.
40-
*/
41-
export type FilesV4UploadFileCallOptions = {
42-
/**
43-
* The file data as raw bytes or a base64-encoded string.
44-
*/
45-
data: Uint8Array | string;
46-
47-
/**
48-
* The IANA media type of the file (e.g. `'application/pdf'`).
49-
*/
50-
mediaType: string;
51-
52-
/**
53-
* The filename of the file.
54-
*/
55-
filename?: string;
56-
57-
/**
58-
* Additional provider-specific options. They are passed through
59-
* to the provider from the AI SDK and enable provider-specific
60-
* functionality that can be fully encapsulated in the provider.
61-
*/
62-
providerOptions?: SharedV4ProviderOptions;
63-
};
1+
import { FilesV4UploadFileCallOptions } from './files-v4-upload-file-call-options';
2+
import { FilesV4UploadFileResult } from './files-v4-upload-file-result';
643

654
/**
665
* Specification for a file management interface that implements the files interface version 4.
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
export type {
2-
FilesV4,
3-
FilesV4UploadFileCallOptions,
4-
FilesV4UploadFileResult,
5-
} from './files-v4';
1+
export type { FilesV4 } from './files-v4';
2+
export type { FilesV4UploadFileCallOptions } from './files-v4-upload-file-call-options';
3+
export type { FilesV4UploadFileResult } from './files-v4-upload-file-result';
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { JSONArray, JSONValue } from '../../json-value';
2+
import { SharedV4Warning } from '../../shared/v4/shared-v4-warning';
3+
import { ImageModelV4Usage } from './image-model-v4-usage';
4+
5+
export type ImageModelV4ProviderMetadata = Record<
6+
string,
7+
{
8+
images: JSONArray;
9+
} & JSONValue
10+
>;
11+
12+
/**
13+
* The result of an image model doGenerate call.
14+
*/
15+
export type ImageModelV4Result = {
16+
/**
17+
* Generated images as base64 encoded strings or binary data.
18+
* The images should be returned without any unnecessary conversion.
19+
* If the API returns base64 encoded strings, the images should be returned
20+
* as base64 encoded strings. If the API returns binary data, the images should
21+
* be returned as binary data.
22+
*/
23+
images: Array<string> | Array<Uint8Array>;
24+
25+
/**
26+
* Warnings for the call, e.g. unsupported features.
27+
*/
28+
warnings: Array<SharedV4Warning>;
29+
30+
/**
31+
* Additional provider-specific metadata. They are passed through
32+
* from the provider to the AI SDK and enable provider-specific
33+
* results that can be fully encapsulated in the provider.
34+
*
35+
* The outer record is keyed by the provider name, and the inner
36+
* record is provider-specific metadata. It always includes an
37+
* `images` key with image-specific metadata
38+
*
39+
* ```ts
40+
* {
41+
* "openai": {
42+
* "images": ["revisedPrompt": "Revised prompt here."]
43+
* }
44+
* }
45+
* ```
46+
*/
47+
providerMetadata?: ImageModelV4ProviderMetadata;
48+
49+
/**
50+
* Response information for telemetry and debugging purposes.
51+
*/
52+
response: {
53+
/**
54+
* Timestamp for the start of the generated response.
55+
*/
56+
timestamp: Date;
57+
58+
/**
59+
* The ID of the response model that was used to generate the response.
60+
*/
61+
modelId: string;
62+
63+
/**
64+
* Response headers.
65+
*/
66+
headers: Record<string, string> | undefined;
67+
};
68+
69+
/**
70+
* Optional token usage for the image generation call (if the provider reports it).
71+
*/
72+
usage?: ImageModelV4Usage;
73+
};

0 commit comments

Comments
 (0)