@ai-sdk/google 4.0.50 → 4.0.53
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/CHANGELOG.md +30 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +1154 -577
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +147 -6
- package/dist/internal/index.js +86 -42
- package/dist/internal/index.js.map +1 -1
- package/docs/15-google.mdx +71 -0
- package/package.json +6 -6
- package/src/convert-json-schema-to-openapi-schema.ts +13 -1
- package/src/google-batch.ts +670 -0
- package/src/google-files.ts +27 -2
- package/src/google-language-model.ts +58 -35
- package/src/google-prepare-tools.ts +45 -21
- package/src/google-provider.ts +7 -6
- package/src/interactions/build-google-interactions-stream-transform.ts +13 -5
package/src/google-files.ts
CHANGED
|
@@ -34,6 +34,17 @@ interface GoogleFilesConfig {
|
|
|
34
34
|
fetch?: FetchFunction;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
function encodePathSegment(value: string): string {
|
|
38
|
+
const encodedValue = encodeURIComponent(value);
|
|
39
|
+
|
|
40
|
+
// URL parsing normalizes both literal and percent-encoded dot segments.
|
|
41
|
+
return encodedValue === '.'
|
|
42
|
+
? '%252E'
|
|
43
|
+
: encodedValue === '..'
|
|
44
|
+
? '%252E%252E'
|
|
45
|
+
: encodedValue;
|
|
46
|
+
}
|
|
47
|
+
|
|
37
48
|
export class GoogleFiles implements FilesV4 {
|
|
38
49
|
readonly specificationVersion = 'v4';
|
|
39
50
|
|
|
@@ -106,7 +117,7 @@ export class GoogleFiles implements FilesV4 {
|
|
|
106
117
|
'X-Goog-Upload-Offset': '0',
|
|
107
118
|
'X-Goog-Upload-Command': 'upload, finalize',
|
|
108
119
|
},
|
|
109
|
-
body: fileBytes,
|
|
120
|
+
body: ensureArrayBufferBacked(fileBytes),
|
|
110
121
|
});
|
|
111
122
|
|
|
112
123
|
if (!uploadResponse.ok) {
|
|
@@ -137,8 +148,14 @@ export class GoogleFiles implements FilesV4 {
|
|
|
137
148
|
|
|
138
149
|
await delay(pollIntervalMs);
|
|
139
150
|
|
|
151
|
+
const fileNameMatch = /^files\/([^/]+)$/.exec(file.name);
|
|
152
|
+
const filePath =
|
|
153
|
+
fileNameMatch != null
|
|
154
|
+
? `files/${encodePathSegment(fileNameMatch[1])}`
|
|
155
|
+
: encodePathSegment(file.name);
|
|
156
|
+
|
|
140
157
|
const { value: fileStatus } = await getFromApi({
|
|
141
|
-
url: `${this.config.baseURL}/${
|
|
158
|
+
url: `${this.config.baseURL}/${filePath}`,
|
|
142
159
|
validateUrl: false,
|
|
143
160
|
headers: combineHeaders(resolvedHeaders),
|
|
144
161
|
successfulResponseHandler: createJsonResponseHandler(
|
|
@@ -182,6 +199,14 @@ export class GoogleFiles implements FilesV4 {
|
|
|
182
199
|
}
|
|
183
200
|
}
|
|
184
201
|
|
|
202
|
+
function ensureArrayBufferBacked(data: Uint8Array): Uint8Array<ArrayBuffer> {
|
|
203
|
+
if (data.buffer instanceof ArrayBuffer) {
|
|
204
|
+
return data as Uint8Array<ArrayBuffer>;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return new Uint8Array(data);
|
|
208
|
+
}
|
|
209
|
+
|
|
185
210
|
type GoogleFileResource = {
|
|
186
211
|
name: string;
|
|
187
212
|
displayName?: string | null;
|
|
@@ -62,7 +62,7 @@ const configurableSafetySettingCategories = [
|
|
|
62
62
|
'HARM_CATEGORY_SEXUALLY_EXPLICIT',
|
|
63
63
|
] as const;
|
|
64
64
|
|
|
65
|
-
type
|
|
65
|
+
export type GoogleLanguageModelConfig = {
|
|
66
66
|
provider: string;
|
|
67
67
|
baseURL: string;
|
|
68
68
|
headers?: Resolvable<Record<string, string | undefined>>;
|
|
@@ -80,7 +80,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
80
80
|
|
|
81
81
|
readonly modelId: GoogleModelId;
|
|
82
82
|
|
|
83
|
-
private readonly config:
|
|
83
|
+
private readonly config: GoogleLanguageModelConfig;
|
|
84
84
|
private readonly generateId: () => string;
|
|
85
85
|
|
|
86
86
|
static [WORKFLOW_SERIALIZE](model: GoogleLanguageModel) {
|
|
@@ -92,12 +92,12 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
92
92
|
|
|
93
93
|
static [WORKFLOW_DESERIALIZE](options: {
|
|
94
94
|
modelId: string;
|
|
95
|
-
config:
|
|
95
|
+
config: GoogleLanguageModelConfig;
|
|
96
96
|
}) {
|
|
97
97
|
return new GoogleLanguageModel(options.modelId, options.config);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
constructor(modelId: GoogleModelId, config:
|
|
100
|
+
constructor(modelId: GoogleModelId, config: GoogleLanguageModelConfig) {
|
|
101
101
|
this.modelId = modelId;
|
|
102
102
|
this.config = config;
|
|
103
103
|
this.generateId = config.generateId ?? generateId;
|
|
@@ -111,7 +111,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
111
111
|
return this.config.supportedUrls?.() ?? {};
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
protected async getArgs(
|
|
115
115
|
{
|
|
116
116
|
prompt,
|
|
117
117
|
maxOutputTokens,
|
|
@@ -375,38 +375,19 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
375
375
|
};
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
378
|
+
protected convertGenerateContentResponse({
|
|
379
|
+
response,
|
|
380
|
+
warnings,
|
|
381
|
+
providerOptionsNames,
|
|
382
|
+
}: {
|
|
383
|
+
response: InferSchema<typeof responseSchema>;
|
|
384
|
+
warnings: SharedV4Warning[];
|
|
385
|
+
providerOptionsNames: readonly string[];
|
|
386
|
+
}): LanguageModelV4GenerateResult {
|
|
383
387
|
const wrapProviderMetadata = (payload: Record<string, unknown>) =>
|
|
384
388
|
Object.fromEntries(
|
|
385
389
|
providerOptionsNames.map(name => [name, payload]),
|
|
386
390
|
) as SharedV4ProviderMetadata;
|
|
387
|
-
|
|
388
|
-
const mergedHeaders = combineHeaders(
|
|
389
|
-
this.config.headers ? await resolve(this.config.headers) : undefined,
|
|
390
|
-
options.headers,
|
|
391
|
-
extraHeaders,
|
|
392
|
-
);
|
|
393
|
-
|
|
394
|
-
const {
|
|
395
|
-
responseHeaders,
|
|
396
|
-
value: response,
|
|
397
|
-
rawValue: rawResponse,
|
|
398
|
-
} = await postJsonToApi({
|
|
399
|
-
url: `${this.config.baseURL}/${getModelPath(
|
|
400
|
-
this.modelId,
|
|
401
|
-
)}:generateContent`,
|
|
402
|
-
headers: mergedHeaders,
|
|
403
|
-
body: args,
|
|
404
|
-
failedResponseHandler: googleFailedResponseHandler,
|
|
405
|
-
successfulResponseHandler: createJsonResponseHandler(responseSchema),
|
|
406
|
-
abortSignal: options.abortSignal,
|
|
407
|
-
fetch: this.config.fetch,
|
|
408
|
-
});
|
|
409
|
-
|
|
410
391
|
const candidate = response.candidates[0];
|
|
411
392
|
const content: Array<LanguageModelV4Content> = [];
|
|
412
393
|
|
|
@@ -566,10 +547,52 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
566
547
|
finishMessage: candidate.finishMessage ?? null,
|
|
567
548
|
serviceTier: usageMetadata?.serviceTier ?? null,
|
|
568
549
|
} satisfies GoogleProviderMetadata),
|
|
569
|
-
request: { body: args },
|
|
570
550
|
response: {
|
|
571
551
|
// TODO timestamp, model id
|
|
572
552
|
id: response.responseId ?? undefined,
|
|
553
|
+
},
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
async doGenerate(
|
|
558
|
+
options: LanguageModelV4CallOptions,
|
|
559
|
+
): Promise<LanguageModelV4GenerateResult> {
|
|
560
|
+
const { args, warnings, providerOptionsNames, extraHeaders } =
|
|
561
|
+
await this.getArgs(options);
|
|
562
|
+
|
|
563
|
+
const mergedHeaders = combineHeaders(
|
|
564
|
+
this.config.headers ? await resolve(this.config.headers) : undefined,
|
|
565
|
+
options.headers,
|
|
566
|
+
extraHeaders,
|
|
567
|
+
);
|
|
568
|
+
|
|
569
|
+
const {
|
|
570
|
+
responseHeaders,
|
|
571
|
+
value: response,
|
|
572
|
+
rawValue: rawResponse,
|
|
573
|
+
} = await postJsonToApi({
|
|
574
|
+
url: `${this.config.baseURL}/${getModelPath(
|
|
575
|
+
this.modelId,
|
|
576
|
+
)}:generateContent`,
|
|
577
|
+
headers: mergedHeaders,
|
|
578
|
+
body: args,
|
|
579
|
+
failedResponseHandler: googleFailedResponseHandler,
|
|
580
|
+
successfulResponseHandler: createJsonResponseHandler(responseSchema),
|
|
581
|
+
abortSignal: options.abortSignal,
|
|
582
|
+
fetch: this.config.fetch,
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
const result = this.convertGenerateContentResponse({
|
|
586
|
+
response,
|
|
587
|
+
warnings,
|
|
588
|
+
providerOptionsNames,
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
return {
|
|
592
|
+
...result,
|
|
593
|
+
request: { body: args },
|
|
594
|
+
response: {
|
|
595
|
+
...result.response,
|
|
573
596
|
headers: responseHeaders,
|
|
574
597
|
body: rawResponse,
|
|
575
598
|
},
|
|
@@ -1563,7 +1586,7 @@ export const getUrlContextMetadataSchema = () =>
|
|
|
1563
1586
|
.nullish(),
|
|
1564
1587
|
});
|
|
1565
1588
|
|
|
1566
|
-
const responseSchema = lazySchema(() =>
|
|
1589
|
+
export const responseSchema = lazySchema(() =>
|
|
1567
1590
|
zodSchema(
|
|
1568
1591
|
z.object({
|
|
1569
1592
|
responseId: z.string().nullish(),
|
|
@@ -3,10 +3,25 @@ import {
|
|
|
3
3
|
type LanguageModelV4CallOptions,
|
|
4
4
|
type SharedV4Warning,
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
convertJSONSchemaToOpenAPISchema,
|
|
8
|
+
isRecursiveJSONSchemaReferenceError,
|
|
9
|
+
} from './convert-json-schema-to-openapi-schema';
|
|
7
10
|
import type { GoogleModelId } from './google-language-model-options';
|
|
8
11
|
import { getGoogleModelCapabilities } from './google-model-capabilities';
|
|
9
12
|
|
|
13
|
+
type FunctionTool = Extract<
|
|
14
|
+
NonNullable<LanguageModelV4CallOptions['tools']>[number],
|
|
15
|
+
{ type: 'function' }
|
|
16
|
+
>;
|
|
17
|
+
|
|
18
|
+
type GoogleFunctionDeclaration = {
|
|
19
|
+
name: string;
|
|
20
|
+
description: string;
|
|
21
|
+
parameters?: unknown;
|
|
22
|
+
parametersJsonSchema?: unknown;
|
|
23
|
+
};
|
|
24
|
+
|
|
10
25
|
export function prepareTools({
|
|
11
26
|
tools,
|
|
12
27
|
toolChoice,
|
|
@@ -21,11 +36,7 @@ export function prepareTools({
|
|
|
21
36
|
tools:
|
|
22
37
|
| Array<
|
|
23
38
|
| {
|
|
24
|
-
functionDeclarations:
|
|
25
|
-
name: string;
|
|
26
|
-
description: string;
|
|
27
|
-
parameters: unknown;
|
|
28
|
-
}>;
|
|
39
|
+
functionDeclarations: GoogleFunctionDeclaration[];
|
|
29
40
|
}
|
|
30
41
|
| Record<string, any>
|
|
31
42
|
>
|
|
@@ -172,18 +183,10 @@ export function prepareTools({
|
|
|
172
183
|
});
|
|
173
184
|
|
|
174
185
|
if (hasFunctionTools && usesGemini3Features && googleTools.length > 0) {
|
|
175
|
-
const functionDeclarations:
|
|
176
|
-
name: string;
|
|
177
|
-
description: string;
|
|
178
|
-
parameters: unknown;
|
|
179
|
-
}> = [];
|
|
186
|
+
const functionDeclarations: GoogleFunctionDeclaration[] = [];
|
|
180
187
|
for (const tool of tools) {
|
|
181
188
|
if (tool.type === 'function') {
|
|
182
|
-
functionDeclarations.push(
|
|
183
|
-
name: tool.name,
|
|
184
|
-
description: tool.description ?? '',
|
|
185
|
-
parameters: convertJSONSchemaToOpenAPISchema(tool.inputSchema),
|
|
186
|
-
});
|
|
189
|
+
functionDeclarations.push(prepareFunctionDeclaration(tool));
|
|
187
190
|
}
|
|
188
191
|
}
|
|
189
192
|
|
|
@@ -238,11 +241,7 @@ export function prepareTools({
|
|
|
238
241
|
for (const tool of tools) {
|
|
239
242
|
switch (tool.type) {
|
|
240
243
|
case 'function':
|
|
241
|
-
functionDeclarations.push(
|
|
242
|
-
name: tool.name,
|
|
243
|
-
description: tool.description ?? '',
|
|
244
|
-
parameters: convertJSONSchemaToOpenAPISchema(tool.inputSchema),
|
|
245
|
-
});
|
|
244
|
+
functionDeclarations.push(prepareFunctionDeclaration(tool));
|
|
246
245
|
if (tool.strict === true) {
|
|
247
246
|
hasStrictTools = true;
|
|
248
247
|
}
|
|
@@ -314,3 +313,28 @@ export function prepareTools({
|
|
|
314
313
|
}
|
|
315
314
|
}
|
|
316
315
|
}
|
|
316
|
+
|
|
317
|
+
function prepareFunctionDeclaration(
|
|
318
|
+
tool: FunctionTool,
|
|
319
|
+
): GoogleFunctionDeclaration {
|
|
320
|
+
const declaration = {
|
|
321
|
+
name: tool.name,
|
|
322
|
+
description: tool.description ?? '',
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
try {
|
|
326
|
+
return {
|
|
327
|
+
...declaration,
|
|
328
|
+
parameters: convertJSONSchemaToOpenAPISchema(tool.inputSchema),
|
|
329
|
+
};
|
|
330
|
+
} catch (error) {
|
|
331
|
+
if (!isRecursiveJSONSchemaReferenceError(error)) {
|
|
332
|
+
throw error;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return {
|
|
336
|
+
...declaration,
|
|
337
|
+
parametersJsonSchema: tool.inputSchema,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
}
|
package/src/google-provider.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
EmbeddingModelV4,
|
|
3
|
+
Experimental_BatchLanguageModelV4 as BatchLanguageModelV4,
|
|
3
4
|
Experimental_VideoModelV4,
|
|
4
5
|
FilesV4,
|
|
5
6
|
ImageModelV4,
|
|
@@ -21,7 +22,7 @@ import {
|
|
|
21
22
|
import { VERSION } from './version';
|
|
22
23
|
import { GoogleEmbeddingModel } from './google-embedding-model';
|
|
23
24
|
import type { GoogleEmbeddingModelId } from './google-embedding-model-options';
|
|
24
|
-
import {
|
|
25
|
+
import { GoogleBatchLanguageModel } from './google-batch';
|
|
25
26
|
import type { GoogleModelId } from './google-language-model-options';
|
|
26
27
|
import { googleTools } from './google-tools';
|
|
27
28
|
|
|
@@ -46,11 +47,11 @@ import { GoogleSpeechTranslationModel } from './speech-translation/google-speech
|
|
|
46
47
|
import type { GoogleSpeechTranslationModelId } from './speech-translation/google-speech-translation-model-options';
|
|
47
48
|
|
|
48
49
|
export interface GoogleProvider extends ProviderV4 {
|
|
49
|
-
(modelId: GoogleModelId):
|
|
50
|
+
(modelId: GoogleModelId): BatchLanguageModelV4;
|
|
50
51
|
|
|
51
|
-
languageModel(modelId: GoogleModelId):
|
|
52
|
+
languageModel(modelId: GoogleModelId): BatchLanguageModelV4;
|
|
52
53
|
|
|
53
|
-
chat(modelId: GoogleModelId):
|
|
54
|
+
chat(modelId: GoogleModelId): BatchLanguageModelV4;
|
|
54
55
|
|
|
55
56
|
/**
|
|
56
57
|
* Creates a model for image generation.
|
|
@@ -63,7 +64,7 @@ export interface GoogleProvider extends ProviderV4 {
|
|
|
63
64
|
/**
|
|
64
65
|
* @deprecated Use `chat()` instead.
|
|
65
66
|
*/
|
|
66
|
-
generativeAI(modelId: GoogleModelId):
|
|
67
|
+
generativeAI(modelId: GoogleModelId): BatchLanguageModelV4;
|
|
67
68
|
|
|
68
69
|
/**
|
|
69
70
|
* Creates a model for text embeddings.
|
|
@@ -240,7 +241,7 @@ export function createGoogle(
|
|
|
240
241
|
);
|
|
241
242
|
|
|
242
243
|
const createChatModel = (modelId: GoogleModelId) =>
|
|
243
|
-
new
|
|
244
|
+
new GoogleBatchLanguageModel(modelId, {
|
|
244
245
|
provider: providerName,
|
|
245
246
|
baseURL,
|
|
246
247
|
headers: getHeaders,
|
|
@@ -6,7 +6,10 @@ import type {
|
|
|
6
6
|
SharedV4ProviderMetadata,
|
|
7
7
|
SharedV4Warning,
|
|
8
8
|
} from '@ai-sdk/provider';
|
|
9
|
-
import
|
|
9
|
+
import {
|
|
10
|
+
createProviderStreamError,
|
|
11
|
+
type ParseResult,
|
|
12
|
+
} from '@ai-sdk/provider-utils';
|
|
10
13
|
import type {
|
|
11
14
|
GoogleInteractionsEvent,
|
|
12
15
|
GoogleInteractionsUsage,
|
|
@@ -821,10 +824,15 @@ export function buildGoogleInteractionsStreamTransform({
|
|
|
821
824
|
{ event_type: 'error' }
|
|
822
825
|
>;
|
|
823
826
|
finishStatus = 'failed';
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
827
|
+
controller.enqueue({
|
|
828
|
+
type: 'error',
|
|
829
|
+
error: createProviderStreamError({
|
|
830
|
+
message: event.error?.message ?? 'Unknown interaction error',
|
|
831
|
+
type: event.event_type,
|
|
832
|
+
code: event.error?.code ?? undefined,
|
|
833
|
+
data: event,
|
|
834
|
+
}),
|
|
835
|
+
});
|
|
828
836
|
break;
|
|
829
837
|
}
|
|
830
838
|
|