@ai-sdk/google 1.0.4 → 1.0.6

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.
@@ -0,0 +1,659 @@
1
+ // src/google-generative-ai-language-model.ts
2
+ import {
3
+ combineHeaders,
4
+ createEventSourceResponseHandler,
5
+ createJsonResponseHandler,
6
+ postJsonToApi,
7
+ resolve
8
+ } from "@ai-sdk/provider-utils";
9
+ import { z as z2 } from "zod";
10
+
11
+ // src/convert-json-schema-to-openapi-schema.ts
12
+ function convertJSONSchemaToOpenAPISchema(jsonSchema) {
13
+ if (isEmptyObjectSchema(jsonSchema)) {
14
+ return void 0;
15
+ }
16
+ if (typeof jsonSchema === "boolean") {
17
+ return { type: "boolean", properties: {} };
18
+ }
19
+ const {
20
+ type,
21
+ description,
22
+ required,
23
+ properties,
24
+ items,
25
+ allOf,
26
+ anyOf,
27
+ oneOf,
28
+ format,
29
+ const: constValue,
30
+ minLength
31
+ } = jsonSchema;
32
+ const result = {};
33
+ if (description)
34
+ result.description = description;
35
+ if (required)
36
+ result.required = required;
37
+ if (format)
38
+ result.format = format;
39
+ if (constValue !== void 0) {
40
+ result.enum = [constValue];
41
+ }
42
+ if (type) {
43
+ if (Array.isArray(type)) {
44
+ if (type.includes("null")) {
45
+ result.type = type.filter((t) => t !== "null")[0];
46
+ result.nullable = true;
47
+ } else {
48
+ result.type = type;
49
+ }
50
+ } else if (type === "null") {
51
+ result.type = "null";
52
+ } else {
53
+ result.type = type;
54
+ }
55
+ }
56
+ if (properties != null) {
57
+ result.properties = Object.entries(properties).reduce(
58
+ (acc, [key, value]) => {
59
+ acc[key] = convertJSONSchemaToOpenAPISchema(value);
60
+ return acc;
61
+ },
62
+ {}
63
+ );
64
+ }
65
+ if (items) {
66
+ result.items = Array.isArray(items) ? items.map(convertJSONSchemaToOpenAPISchema) : convertJSONSchemaToOpenAPISchema(items);
67
+ }
68
+ if (allOf) {
69
+ result.allOf = allOf.map(convertJSONSchemaToOpenAPISchema);
70
+ }
71
+ if (anyOf) {
72
+ result.anyOf = anyOf.map(convertJSONSchemaToOpenAPISchema);
73
+ }
74
+ if (oneOf) {
75
+ result.oneOf = oneOf.map(convertJSONSchemaToOpenAPISchema);
76
+ }
77
+ if (minLength !== void 0)
78
+ result.minLength = minLength;
79
+ return result;
80
+ }
81
+ function isEmptyObjectSchema(jsonSchema) {
82
+ return jsonSchema != null && typeof jsonSchema === "object" && jsonSchema.type === "object" && (jsonSchema.properties == null || Object.keys(jsonSchema.properties).length === 0);
83
+ }
84
+
85
+ // src/convert-to-google-generative-ai-messages.ts
86
+ import {
87
+ UnsupportedFunctionalityError
88
+ } from "@ai-sdk/provider";
89
+ import { convertUint8ArrayToBase64 } from "@ai-sdk/provider-utils";
90
+ function convertToGoogleGenerativeAIMessages(prompt) {
91
+ var _a, _b;
92
+ const systemInstructionParts = [];
93
+ const contents = [];
94
+ let systemMessagesAllowed = true;
95
+ for (const { role, content } of prompt) {
96
+ switch (role) {
97
+ case "system": {
98
+ if (!systemMessagesAllowed) {
99
+ throw new UnsupportedFunctionalityError({
100
+ functionality: "system messages are only supported at the beginning of the conversation"
101
+ });
102
+ }
103
+ systemInstructionParts.push({ text: content });
104
+ break;
105
+ }
106
+ case "user": {
107
+ systemMessagesAllowed = false;
108
+ const parts = [];
109
+ for (const part of content) {
110
+ switch (part.type) {
111
+ case "text": {
112
+ parts.push({ text: part.text });
113
+ break;
114
+ }
115
+ case "image": {
116
+ parts.push(
117
+ part.image instanceof URL ? {
118
+ fileData: {
119
+ mimeType: (_a = part.mimeType) != null ? _a : "image/jpeg",
120
+ fileUri: part.image.toString()
121
+ }
122
+ } : {
123
+ inlineData: {
124
+ mimeType: (_b = part.mimeType) != null ? _b : "image/jpeg",
125
+ data: convertUint8ArrayToBase64(part.image)
126
+ }
127
+ }
128
+ );
129
+ break;
130
+ }
131
+ case "file": {
132
+ parts.push(
133
+ part.data instanceof URL ? {
134
+ fileData: {
135
+ mimeType: part.mimeType,
136
+ fileUri: part.data.toString()
137
+ }
138
+ } : {
139
+ inlineData: {
140
+ mimeType: part.mimeType,
141
+ data: part.data
142
+ }
143
+ }
144
+ );
145
+ break;
146
+ }
147
+ default: {
148
+ const _exhaustiveCheck = part;
149
+ throw new UnsupportedFunctionalityError({
150
+ functionality: `prompt part: ${_exhaustiveCheck}`
151
+ });
152
+ }
153
+ }
154
+ }
155
+ contents.push({ role: "user", parts });
156
+ break;
157
+ }
158
+ case "assistant": {
159
+ systemMessagesAllowed = false;
160
+ contents.push({
161
+ role: "model",
162
+ parts: content.map((part) => {
163
+ switch (part.type) {
164
+ case "text": {
165
+ return part.text.length === 0 ? void 0 : { text: part.text };
166
+ }
167
+ case "tool-call": {
168
+ return {
169
+ functionCall: {
170
+ name: part.toolName,
171
+ args: part.args
172
+ }
173
+ };
174
+ }
175
+ }
176
+ }).filter(
177
+ (part) => part !== void 0
178
+ )
179
+ });
180
+ break;
181
+ }
182
+ case "tool": {
183
+ systemMessagesAllowed = false;
184
+ contents.push({
185
+ role: "user",
186
+ parts: content.map((part) => ({
187
+ functionResponse: {
188
+ name: part.toolName,
189
+ response: {
190
+ name: part.toolName,
191
+ content: part.result
192
+ }
193
+ }
194
+ }))
195
+ });
196
+ break;
197
+ }
198
+ default: {
199
+ const _exhaustiveCheck = role;
200
+ throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
201
+ }
202
+ }
203
+ }
204
+ return {
205
+ systemInstruction: systemInstructionParts.length > 0 ? { parts: systemInstructionParts } : void 0,
206
+ contents
207
+ };
208
+ }
209
+
210
+ // src/get-model-path.ts
211
+ function getModelPath(modelId) {
212
+ return modelId.includes("/") ? modelId : `models/${modelId}`;
213
+ }
214
+
215
+ // src/google-error.ts
216
+ import { createJsonErrorResponseHandler } from "@ai-sdk/provider-utils";
217
+ import { z } from "zod";
218
+ var googleErrorDataSchema = z.object({
219
+ error: z.object({
220
+ code: z.number().nullable(),
221
+ message: z.string(),
222
+ status: z.string()
223
+ })
224
+ });
225
+ var googleFailedResponseHandler = createJsonErrorResponseHandler({
226
+ errorSchema: googleErrorDataSchema,
227
+ errorToMessage: (data) => data.error.message
228
+ });
229
+
230
+ // src/google-prepare-tools.ts
231
+ import {
232
+ UnsupportedFunctionalityError as UnsupportedFunctionalityError2
233
+ } from "@ai-sdk/provider";
234
+ function prepareTools(mode, useSearchGrounding) {
235
+ var _a, _b;
236
+ const tools = ((_a = mode.tools) == null ? void 0 : _a.length) ? mode.tools : void 0;
237
+ const toolWarnings = [];
238
+ if (useSearchGrounding) {
239
+ return {
240
+ tools: { googleSearchRetrieval: {} },
241
+ toolConfig: void 0,
242
+ toolWarnings
243
+ };
244
+ }
245
+ if (tools == null) {
246
+ return { tools: void 0, toolConfig: void 0, toolWarnings };
247
+ }
248
+ const functionDeclarations = [];
249
+ for (const tool of tools) {
250
+ if (tool.type === "provider-defined") {
251
+ toolWarnings.push({ type: "unsupported-tool", tool });
252
+ } else {
253
+ functionDeclarations.push({
254
+ name: tool.name,
255
+ description: (_b = tool.description) != null ? _b : "",
256
+ parameters: convertJSONSchemaToOpenAPISchema(tool.parameters)
257
+ });
258
+ }
259
+ }
260
+ const toolChoice = mode.toolChoice;
261
+ if (toolChoice == null) {
262
+ return {
263
+ tools: { functionDeclarations },
264
+ toolConfig: void 0,
265
+ toolWarnings
266
+ };
267
+ }
268
+ const type = toolChoice.type;
269
+ switch (type) {
270
+ case "auto":
271
+ return {
272
+ tools: { functionDeclarations },
273
+ toolConfig: { functionCallingConfig: { mode: "AUTO" } },
274
+ toolWarnings
275
+ };
276
+ case "none":
277
+ return {
278
+ tools: { functionDeclarations },
279
+ toolConfig: { functionCallingConfig: { mode: "NONE" } },
280
+ toolWarnings
281
+ };
282
+ case "required":
283
+ return {
284
+ tools: { functionDeclarations },
285
+ toolConfig: { functionCallingConfig: { mode: "ANY" } },
286
+ toolWarnings
287
+ };
288
+ case "tool":
289
+ return {
290
+ tools: { functionDeclarations },
291
+ toolConfig: {
292
+ functionCallingConfig: {
293
+ mode: "ANY",
294
+ allowedFunctionNames: [toolChoice.toolName]
295
+ }
296
+ },
297
+ toolWarnings
298
+ };
299
+ default: {
300
+ const _exhaustiveCheck = type;
301
+ throw new UnsupportedFunctionalityError2({
302
+ functionality: `Unsupported tool choice type: ${_exhaustiveCheck}`
303
+ });
304
+ }
305
+ }
306
+ }
307
+
308
+ // src/map-google-generative-ai-finish-reason.ts
309
+ function mapGoogleGenerativeAIFinishReason({
310
+ finishReason,
311
+ hasToolCalls
312
+ }) {
313
+ switch (finishReason) {
314
+ case "STOP":
315
+ return hasToolCalls ? "tool-calls" : "stop";
316
+ case "MAX_TOKENS":
317
+ return "length";
318
+ case "RECITATION":
319
+ case "SAFETY":
320
+ return "content-filter";
321
+ case "FINISH_REASON_UNSPECIFIED":
322
+ case "OTHER":
323
+ return "other";
324
+ default:
325
+ return "unknown";
326
+ }
327
+ }
328
+
329
+ // src/google-generative-ai-language-model.ts
330
+ var GoogleGenerativeAILanguageModel = class {
331
+ constructor(modelId, settings, config) {
332
+ this.specificationVersion = "v1";
333
+ this.defaultObjectGenerationMode = "json";
334
+ this.supportsImageUrls = false;
335
+ this.modelId = modelId;
336
+ this.settings = settings;
337
+ this.config = config;
338
+ }
339
+ get supportsStructuredOutputs() {
340
+ var _a;
341
+ return (_a = this.settings.structuredOutputs) != null ? _a : true;
342
+ }
343
+ get provider() {
344
+ return this.config.provider;
345
+ }
346
+ async getArgs({
347
+ mode,
348
+ prompt,
349
+ maxTokens,
350
+ temperature,
351
+ topP,
352
+ topK,
353
+ frequencyPenalty,
354
+ presencePenalty,
355
+ stopSequences,
356
+ responseFormat,
357
+ seed
358
+ }) {
359
+ var _a, _b;
360
+ const type = mode.type;
361
+ const warnings = [];
362
+ if (seed != null) {
363
+ warnings.push({
364
+ type: "unsupported-setting",
365
+ setting: "seed"
366
+ });
367
+ }
368
+ const generationConfig = {
369
+ // standardized settings:
370
+ maxOutputTokens: maxTokens,
371
+ temperature,
372
+ topK,
373
+ topP,
374
+ frequencyPenalty,
375
+ presencePenalty,
376
+ stopSequences,
377
+ // response format:
378
+ responseMimeType: (responseFormat == null ? void 0 : responseFormat.type) === "json" ? "application/json" : void 0,
379
+ responseSchema: (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && // Google GenAI does not support all OpenAPI Schema features,
380
+ // so this is needed as an escape hatch:
381
+ this.supportsStructuredOutputs ? convertJSONSchemaToOpenAPISchema(responseFormat.schema) : void 0
382
+ };
383
+ const { contents, systemInstruction } = convertToGoogleGenerativeAIMessages(prompt);
384
+ switch (type) {
385
+ case "regular": {
386
+ const { tools, toolConfig, toolWarnings } = prepareTools(
387
+ mode,
388
+ (_a = this.settings.useSearchGrounding) != null ? _a : false
389
+ );
390
+ return {
391
+ args: {
392
+ generationConfig,
393
+ contents,
394
+ systemInstruction,
395
+ safetySettings: this.settings.safetySettings,
396
+ tools,
397
+ toolConfig,
398
+ cachedContent: this.settings.cachedContent
399
+ },
400
+ warnings: [...warnings, ...toolWarnings]
401
+ };
402
+ }
403
+ case "object-json": {
404
+ return {
405
+ args: {
406
+ generationConfig: {
407
+ ...generationConfig,
408
+ responseMimeType: "application/json",
409
+ responseSchema: mode.schema != null && // Google GenAI does not support all OpenAPI Schema features,
410
+ // so this is needed as an escape hatch:
411
+ this.supportsStructuredOutputs ? convertJSONSchemaToOpenAPISchema(mode.schema) : void 0
412
+ },
413
+ contents,
414
+ systemInstruction,
415
+ safetySettings: this.settings.safetySettings,
416
+ cachedContent: this.settings.cachedContent
417
+ },
418
+ warnings
419
+ };
420
+ }
421
+ case "object-tool": {
422
+ return {
423
+ args: {
424
+ generationConfig,
425
+ contents,
426
+ tools: {
427
+ functionDeclarations: [
428
+ {
429
+ name: mode.tool.name,
430
+ description: (_b = mode.tool.description) != null ? _b : "",
431
+ parameters: convertJSONSchemaToOpenAPISchema(
432
+ mode.tool.parameters
433
+ )
434
+ }
435
+ ]
436
+ },
437
+ toolConfig: { functionCallingConfig: { mode: "ANY" } },
438
+ safetySettings: this.settings.safetySettings,
439
+ cachedContent: this.settings.cachedContent
440
+ },
441
+ warnings
442
+ };
443
+ }
444
+ default: {
445
+ const _exhaustiveCheck = type;
446
+ throw new Error(`Unsupported type: ${_exhaustiveCheck}`);
447
+ }
448
+ }
449
+ }
450
+ supportsUrl(url) {
451
+ return url.toString().startsWith("https://generativelanguage.googleapis.com/v1beta/files/");
452
+ }
453
+ async doGenerate(options) {
454
+ var _a, _b, _c, _d, _e, _f;
455
+ const { args, warnings } = await this.getArgs(options);
456
+ const body = JSON.stringify(args);
457
+ const mergedHeaders = combineHeaders(
458
+ await resolve(this.config.headers),
459
+ options.headers
460
+ );
461
+ const { responseHeaders, value: response } = await postJsonToApi({
462
+ url: `${this.config.baseURL}/${getModelPath(
463
+ this.modelId
464
+ )}:generateContent`,
465
+ headers: mergedHeaders,
466
+ body: args,
467
+ failedResponseHandler: googleFailedResponseHandler,
468
+ successfulResponseHandler: createJsonResponseHandler(responseSchema),
469
+ abortSignal: options.abortSignal,
470
+ fetch: this.config.fetch
471
+ });
472
+ const { contents: rawPrompt, ...rawSettings } = args;
473
+ const candidate = response.candidates[0];
474
+ const toolCalls = getToolCallsFromParts({
475
+ parts: (_b = (_a = candidate.content) == null ? void 0 : _a.parts) != null ? _b : [],
476
+ generateId: this.config.generateId
477
+ });
478
+ const usageMetadata = response.usageMetadata;
479
+ return {
480
+ text: getTextFromParts((_d = (_c = candidate.content) == null ? void 0 : _c.parts) != null ? _d : []),
481
+ toolCalls,
482
+ finishReason: mapGoogleGenerativeAIFinishReason({
483
+ finishReason: candidate.finishReason,
484
+ hasToolCalls: toolCalls != null && toolCalls.length > 0
485
+ }),
486
+ usage: {
487
+ promptTokens: (_e = usageMetadata == null ? void 0 : usageMetadata.promptTokenCount) != null ? _e : NaN,
488
+ completionTokens: (_f = usageMetadata == null ? void 0 : usageMetadata.candidatesTokenCount) != null ? _f : NaN
489
+ },
490
+ rawCall: { rawPrompt, rawSettings },
491
+ rawResponse: { headers: responseHeaders },
492
+ warnings,
493
+ request: { body }
494
+ };
495
+ }
496
+ async doStream(options) {
497
+ const { args, warnings } = await this.getArgs(options);
498
+ const body = JSON.stringify(args);
499
+ const headers = combineHeaders(
500
+ await resolve(this.config.headers),
501
+ options.headers
502
+ );
503
+ const { responseHeaders, value: response } = await postJsonToApi({
504
+ url: `${this.config.baseURL}/${getModelPath(
505
+ this.modelId
506
+ )}:streamGenerateContent?alt=sse`,
507
+ headers,
508
+ body: args,
509
+ failedResponseHandler: googleFailedResponseHandler,
510
+ successfulResponseHandler: createEventSourceResponseHandler(chunkSchema),
511
+ abortSignal: options.abortSignal,
512
+ fetch: this.config.fetch
513
+ });
514
+ const { contents: rawPrompt, ...rawSettings } = args;
515
+ let finishReason = "unknown";
516
+ let usage = {
517
+ promptTokens: Number.NaN,
518
+ completionTokens: Number.NaN
519
+ };
520
+ const generateId = this.config.generateId;
521
+ let hasToolCalls = false;
522
+ return {
523
+ stream: response.pipeThrough(
524
+ new TransformStream({
525
+ transform(chunk, controller) {
526
+ var _a, _b, _c;
527
+ if (!chunk.success) {
528
+ controller.enqueue({ type: "error", error: chunk.error });
529
+ return;
530
+ }
531
+ const value = chunk.value;
532
+ const usageMetadata = value.usageMetadata;
533
+ if (usageMetadata != null) {
534
+ usage = {
535
+ promptTokens: (_a = usageMetadata.promptTokenCount) != null ? _a : NaN,
536
+ completionTokens: (_b = usageMetadata.candidatesTokenCount) != null ? _b : NaN
537
+ };
538
+ }
539
+ const candidate = (_c = value.candidates) == null ? void 0 : _c[0];
540
+ if (candidate == null) {
541
+ return;
542
+ }
543
+ if (candidate.finishReason != null) {
544
+ finishReason = mapGoogleGenerativeAIFinishReason({
545
+ finishReason: candidate.finishReason,
546
+ hasToolCalls
547
+ });
548
+ }
549
+ const content = candidate.content;
550
+ if (content == null) {
551
+ return;
552
+ }
553
+ const deltaText = getTextFromParts(content.parts);
554
+ if (deltaText != null) {
555
+ controller.enqueue({
556
+ type: "text-delta",
557
+ textDelta: deltaText
558
+ });
559
+ }
560
+ const toolCallDeltas = getToolCallsFromParts({
561
+ parts: content.parts,
562
+ generateId
563
+ });
564
+ if (toolCallDeltas != null) {
565
+ for (const toolCall of toolCallDeltas) {
566
+ controller.enqueue({
567
+ type: "tool-call-delta",
568
+ toolCallType: "function",
569
+ toolCallId: toolCall.toolCallId,
570
+ toolName: toolCall.toolName,
571
+ argsTextDelta: toolCall.args
572
+ });
573
+ controller.enqueue({
574
+ type: "tool-call",
575
+ toolCallType: "function",
576
+ toolCallId: toolCall.toolCallId,
577
+ toolName: toolCall.toolName,
578
+ args: toolCall.args
579
+ });
580
+ hasToolCalls = true;
581
+ }
582
+ }
583
+ },
584
+ flush(controller) {
585
+ controller.enqueue({ type: "finish", finishReason, usage });
586
+ }
587
+ })
588
+ ),
589
+ rawCall: { rawPrompt, rawSettings },
590
+ rawResponse: { headers: responseHeaders },
591
+ warnings,
592
+ request: { body }
593
+ };
594
+ }
595
+ };
596
+ function getToolCallsFromParts({
597
+ parts,
598
+ generateId
599
+ }) {
600
+ const functionCallParts = parts.filter(
601
+ (part) => "functionCall" in part
602
+ );
603
+ return functionCallParts.length === 0 ? void 0 : functionCallParts.map((part) => ({
604
+ toolCallType: "function",
605
+ toolCallId: generateId(),
606
+ toolName: part.functionCall.name,
607
+ args: JSON.stringify(part.functionCall.args)
608
+ }));
609
+ }
610
+ function getTextFromParts(parts) {
611
+ const textParts = parts.filter((part) => "text" in part);
612
+ return textParts.length === 0 ? void 0 : textParts.map((part) => part.text).join("");
613
+ }
614
+ var contentSchema = z2.object({
615
+ role: z2.string(),
616
+ parts: z2.array(
617
+ z2.union([
618
+ z2.object({
619
+ text: z2.string()
620
+ }),
621
+ z2.object({
622
+ functionCall: z2.object({
623
+ name: z2.string(),
624
+ args: z2.unknown()
625
+ })
626
+ })
627
+ ])
628
+ )
629
+ });
630
+ var responseSchema = z2.object({
631
+ candidates: z2.array(
632
+ z2.object({
633
+ content: contentSchema.nullish(),
634
+ finishReason: z2.string().nullish()
635
+ })
636
+ ),
637
+ usageMetadata: z2.object({
638
+ promptTokenCount: z2.number().nullish(),
639
+ candidatesTokenCount: z2.number().nullish(),
640
+ totalTokenCount: z2.number().nullish()
641
+ }).nullish()
642
+ });
643
+ var chunkSchema = z2.object({
644
+ candidates: z2.array(
645
+ z2.object({
646
+ content: contentSchema.nullish(),
647
+ finishReason: z2.string().nullish()
648
+ })
649
+ ).nullish(),
650
+ usageMetadata: z2.object({
651
+ promptTokenCount: z2.number().nullish(),
652
+ candidatesTokenCount: z2.number().nullish(),
653
+ totalTokenCount: z2.number().nullish()
654
+ }).nullish()
655
+ });
656
+ export {
657
+ GoogleGenerativeAILanguageModel
658
+ };
659
+ //# sourceMappingURL=index.mjs.map