@ai-sdk/google 3.0.12 → 3.0.13
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 +9 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +9 -5
- package/src/__snapshots__/google-generative-ai-embedding-model.test.ts.snap +0 -33
- package/src/convert-json-schema-to-openapi-schema.test.ts +0 -684
- package/src/convert-to-google-generative-ai-messages.test.ts +0 -495
- package/src/get-model-path.test.ts +0 -16
- package/src/google-generative-ai-embedding-model.test.ts +0 -204
- package/src/google-generative-ai-image-model.test.ts +0 -411
- package/src/google-generative-ai-language-model.test.ts +0 -4616
- package/src/google-prepare-tools.test.ts +0 -474
- package/src/google-provider.test.ts +0 -307
- package/src/google-supported-file-url.test.ts +0 -57
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
-
import { createGoogleGenerativeAI } from './google-provider';
|
|
3
|
-
import { GoogleGenerativeAILanguageModel } from './google-generative-ai-language-model';
|
|
4
|
-
import { GoogleGenerativeAIEmbeddingModel } from './google-generative-ai-embedding-model';
|
|
5
|
-
import { GoogleGenerativeAIImageModel } from './google-generative-ai-image-model';
|
|
6
|
-
|
|
7
|
-
// Mock the imported modules using a partial mock to preserve original exports
|
|
8
|
-
vi.mock('@ai-sdk/provider-utils', async importOriginal => {
|
|
9
|
-
const mod = await importOriginal<typeof import('@ai-sdk/provider-utils')>();
|
|
10
|
-
return {
|
|
11
|
-
...mod,
|
|
12
|
-
loadApiKey: vi.fn().mockImplementation(({ apiKey }) => apiKey),
|
|
13
|
-
generateId: vi.fn().mockReturnValue('mock-id'),
|
|
14
|
-
withoutTrailingSlash: vi.fn().mockImplementation(url => url),
|
|
15
|
-
};
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
vi.mock('./google-generative-ai-language-model', () => ({
|
|
19
|
-
GoogleGenerativeAILanguageModel: vi.fn(),
|
|
20
|
-
}));
|
|
21
|
-
|
|
22
|
-
vi.mock('./google-generative-ai-embedding-model', () => ({
|
|
23
|
-
GoogleGenerativeAIEmbeddingModel: vi.fn(),
|
|
24
|
-
}));
|
|
25
|
-
vi.mock('./google-generative-ai-image-model', () => ({
|
|
26
|
-
GoogleGenerativeAIImageModel: vi.fn(),
|
|
27
|
-
}));
|
|
28
|
-
vi.mock('./version', () => ({
|
|
29
|
-
VERSION: '0.0.0-test',
|
|
30
|
-
}));
|
|
31
|
-
describe('google-provider', () => {
|
|
32
|
-
beforeEach(() => {
|
|
33
|
-
vi.clearAllMocks();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('should create a language model with default settings', () => {
|
|
37
|
-
const provider = createGoogleGenerativeAI({
|
|
38
|
-
apiKey: 'test-api-key',
|
|
39
|
-
});
|
|
40
|
-
provider('gemini-pro');
|
|
41
|
-
|
|
42
|
-
expect(GoogleGenerativeAILanguageModel).toHaveBeenCalledWith(
|
|
43
|
-
'gemini-pro',
|
|
44
|
-
expect.objectContaining({
|
|
45
|
-
provider: 'google.generative-ai',
|
|
46
|
-
baseURL: 'https://generativelanguage.googleapis.com/v1beta',
|
|
47
|
-
headers: expect.any(Function),
|
|
48
|
-
generateId: expect.any(Function),
|
|
49
|
-
supportedUrls: expect.any(Function),
|
|
50
|
-
}),
|
|
51
|
-
);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('should throw an error when using new keyword', () => {
|
|
55
|
-
const provider = createGoogleGenerativeAI({ apiKey: 'test-api-key' });
|
|
56
|
-
|
|
57
|
-
expect(() => new (provider as any)('gemini-pro')).toThrow(
|
|
58
|
-
'The Google Generative AI model function cannot be called with the new keyword.',
|
|
59
|
-
);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should create an embedding model with correct settings', () => {
|
|
63
|
-
const provider = createGoogleGenerativeAI({
|
|
64
|
-
apiKey: 'test-api-key',
|
|
65
|
-
});
|
|
66
|
-
provider.embeddingModel('embedding-001');
|
|
67
|
-
|
|
68
|
-
expect(GoogleGenerativeAIEmbeddingModel).toHaveBeenCalledWith(
|
|
69
|
-
'embedding-001',
|
|
70
|
-
expect.objectContaining({
|
|
71
|
-
provider: 'google.generative-ai',
|
|
72
|
-
headers: expect.any(Function),
|
|
73
|
-
baseURL: 'https://generativelanguage.googleapis.com/v1beta',
|
|
74
|
-
}),
|
|
75
|
-
);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('should pass custom headers to the model constructor', () => {
|
|
79
|
-
const customHeaders = { 'Custom-Header': 'custom-value' };
|
|
80
|
-
const provider = createGoogleGenerativeAI({
|
|
81
|
-
apiKey: 'test-api-key',
|
|
82
|
-
headers: customHeaders,
|
|
83
|
-
});
|
|
84
|
-
provider('gemini-pro');
|
|
85
|
-
|
|
86
|
-
expect(GoogleGenerativeAILanguageModel).toHaveBeenCalledWith(
|
|
87
|
-
expect.anything(),
|
|
88
|
-
expect.objectContaining({
|
|
89
|
-
headers: expect.any(Function),
|
|
90
|
-
}),
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
const options = (GoogleGenerativeAILanguageModel as any).mock.calls[0][1];
|
|
94
|
-
const headers = options.headers();
|
|
95
|
-
expect(headers).toEqual({
|
|
96
|
-
'x-goog-api-key': 'test-api-key',
|
|
97
|
-
'custom-header': 'custom-value',
|
|
98
|
-
'user-agent': 'ai-sdk/google/0.0.0-test',
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('should pass custom generateId function to the model constructor', () => {
|
|
103
|
-
const customGenerateId = () => 'custom-id';
|
|
104
|
-
const provider = createGoogleGenerativeAI({
|
|
105
|
-
apiKey: 'test-api-key',
|
|
106
|
-
generateId: customGenerateId,
|
|
107
|
-
});
|
|
108
|
-
provider('gemini-pro');
|
|
109
|
-
|
|
110
|
-
expect(GoogleGenerativeAILanguageModel).toHaveBeenCalledWith(
|
|
111
|
-
expect.anything(),
|
|
112
|
-
expect.objectContaining({
|
|
113
|
-
generateId: customGenerateId,
|
|
114
|
-
}),
|
|
115
|
-
);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it('should use chat method to create a model', () => {
|
|
119
|
-
const provider = createGoogleGenerativeAI({
|
|
120
|
-
apiKey: 'test-api-key',
|
|
121
|
-
});
|
|
122
|
-
provider.chat('gemini-pro');
|
|
123
|
-
|
|
124
|
-
expect(GoogleGenerativeAILanguageModel).toHaveBeenCalledWith(
|
|
125
|
-
'gemini-pro',
|
|
126
|
-
expect.any(Object),
|
|
127
|
-
);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('should use custom baseURL when provided', () => {
|
|
131
|
-
const customBaseURL = 'https://custom-endpoint.example.com';
|
|
132
|
-
const provider = createGoogleGenerativeAI({
|
|
133
|
-
apiKey: 'test-api-key',
|
|
134
|
-
baseURL: customBaseURL,
|
|
135
|
-
});
|
|
136
|
-
provider('gemini-pro');
|
|
137
|
-
|
|
138
|
-
expect(GoogleGenerativeAILanguageModel).toHaveBeenCalledWith(
|
|
139
|
-
'gemini-pro',
|
|
140
|
-
expect.objectContaining({
|
|
141
|
-
baseURL: customBaseURL,
|
|
142
|
-
}),
|
|
143
|
-
);
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it('should create an image model with default settings', () => {
|
|
147
|
-
const provider = createGoogleGenerativeAI({
|
|
148
|
-
apiKey: 'test-api-key',
|
|
149
|
-
});
|
|
150
|
-
provider.image('imagen-3.0-generate-002');
|
|
151
|
-
|
|
152
|
-
expect(GoogleGenerativeAIImageModel).toHaveBeenCalledWith(
|
|
153
|
-
'imagen-3.0-generate-002',
|
|
154
|
-
{},
|
|
155
|
-
expect.objectContaining({
|
|
156
|
-
provider: 'google.generative-ai',
|
|
157
|
-
headers: expect.any(Function),
|
|
158
|
-
baseURL: 'https://generativelanguage.googleapis.com/v1beta',
|
|
159
|
-
}),
|
|
160
|
-
);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('should create an image model with custom maxImagesPerCall', () => {
|
|
164
|
-
const provider = createGoogleGenerativeAI({
|
|
165
|
-
apiKey: 'test-api-key',
|
|
166
|
-
});
|
|
167
|
-
const imageSettings = {
|
|
168
|
-
maxImagesPerCall: 3,
|
|
169
|
-
};
|
|
170
|
-
provider.image('imagen-3.0-generate-002', imageSettings);
|
|
171
|
-
|
|
172
|
-
expect(GoogleGenerativeAIImageModel).toHaveBeenCalledWith(
|
|
173
|
-
'imagen-3.0-generate-002',
|
|
174
|
-
imageSettings,
|
|
175
|
-
expect.objectContaining({
|
|
176
|
-
provider: 'google.generative-ai',
|
|
177
|
-
headers: expect.any(Function),
|
|
178
|
-
baseURL: 'https://generativelanguage.googleapis.com/v1beta',
|
|
179
|
-
}),
|
|
180
|
-
);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it('should support deprecated methods', () => {
|
|
184
|
-
const provider = createGoogleGenerativeAI({
|
|
185
|
-
apiKey: 'test-api-key',
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
provider.generativeAI('gemini-pro');
|
|
189
|
-
provider.embedding('embedding-001');
|
|
190
|
-
provider.embeddingModel('embedding-001');
|
|
191
|
-
|
|
192
|
-
expect(GoogleGenerativeAILanguageModel).toHaveBeenCalledTimes(1);
|
|
193
|
-
expect(GoogleGenerativeAIEmbeddingModel).toHaveBeenCalledTimes(2);
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it('should include YouTube URLs in supportedUrls', () => {
|
|
197
|
-
const provider = createGoogleGenerativeAI({
|
|
198
|
-
apiKey: 'test-api-key',
|
|
199
|
-
});
|
|
200
|
-
provider('gemini-pro');
|
|
201
|
-
|
|
202
|
-
const call = vi.mocked(GoogleGenerativeAILanguageModel).mock.calls[0];
|
|
203
|
-
const supportedUrlsFunction = call[1].supportedUrls;
|
|
204
|
-
|
|
205
|
-
expect(supportedUrlsFunction).toBeDefined();
|
|
206
|
-
|
|
207
|
-
const supportedUrls = supportedUrlsFunction!() as Record<string, RegExp[]>;
|
|
208
|
-
const patterns = supportedUrls['*'];
|
|
209
|
-
|
|
210
|
-
expect(patterns).toBeDefined();
|
|
211
|
-
expect(Array.isArray(patterns)).toBe(true);
|
|
212
|
-
|
|
213
|
-
const testResults = {
|
|
214
|
-
supportedUrls: [
|
|
215
|
-
'https://generativelanguage.googleapis.com/v1beta/files/test123',
|
|
216
|
-
'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
|
|
217
|
-
'https://youtube.com/watch?v=dQw4w9WgXcQ',
|
|
218
|
-
'https://youtu.be/dQw4w9WgXcQ',
|
|
219
|
-
].map(url => ({
|
|
220
|
-
url,
|
|
221
|
-
isSupported: patterns.some((pattern: RegExp) => pattern.test(url)),
|
|
222
|
-
})),
|
|
223
|
-
unsupportedUrls: [
|
|
224
|
-
'https://example.com',
|
|
225
|
-
'https://vimeo.com/123456789',
|
|
226
|
-
'https://youtube.com/channel/UCdQw4w9WgXcQ',
|
|
227
|
-
].map(url => ({
|
|
228
|
-
url,
|
|
229
|
-
isSupported: patterns.some((pattern: RegExp) => pattern.test(url)),
|
|
230
|
-
})),
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
expect(testResults).toMatchInlineSnapshot(`
|
|
234
|
-
{
|
|
235
|
-
"supportedUrls": [
|
|
236
|
-
{
|
|
237
|
-
"isSupported": true,
|
|
238
|
-
"url": "https://generativelanguage.googleapis.com/v1beta/files/test123",
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
"isSupported": true,
|
|
242
|
-
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
|
|
243
|
-
},
|
|
244
|
-
{
|
|
245
|
-
"isSupported": true,
|
|
246
|
-
"url": "https://youtube.com/watch?v=dQw4w9WgXcQ",
|
|
247
|
-
},
|
|
248
|
-
{
|
|
249
|
-
"isSupported": true,
|
|
250
|
-
"url": "https://youtu.be/dQw4w9WgXcQ",
|
|
251
|
-
},
|
|
252
|
-
],
|
|
253
|
-
"unsupportedUrls": [
|
|
254
|
-
{
|
|
255
|
-
"isSupported": false,
|
|
256
|
-
"url": "https://example.com",
|
|
257
|
-
},
|
|
258
|
-
{
|
|
259
|
-
"isSupported": false,
|
|
260
|
-
"url": "https://vimeo.com/123456789",
|
|
261
|
-
},
|
|
262
|
-
{
|
|
263
|
-
"isSupported": false,
|
|
264
|
-
"url": "https://youtube.com/channel/UCdQw4w9WgXcQ",
|
|
265
|
-
},
|
|
266
|
-
],
|
|
267
|
-
}
|
|
268
|
-
`);
|
|
269
|
-
});
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
describe('google provider - custom provider name', () => {
|
|
273
|
-
beforeEach(() => {
|
|
274
|
-
vi.clearAllMocks();
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
it('should use custom provider name when specified', () => {
|
|
278
|
-
const provider = createGoogleGenerativeAI({
|
|
279
|
-
name: 'my-gemini-proxy',
|
|
280
|
-
apiKey: 'test-api-key',
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
provider('gemini-pro');
|
|
284
|
-
|
|
285
|
-
expect(GoogleGenerativeAILanguageModel).toHaveBeenCalledWith(
|
|
286
|
-
'gemini-pro',
|
|
287
|
-
expect.objectContaining({
|
|
288
|
-
provider: 'my-gemini-proxy',
|
|
289
|
-
}),
|
|
290
|
-
);
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
it('should default to google.generative-ai when name not specified', () => {
|
|
294
|
-
const provider = createGoogleGenerativeAI({
|
|
295
|
-
apiKey: 'test-api-key',
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
provider('gemini-pro');
|
|
299
|
-
|
|
300
|
-
expect(GoogleGenerativeAILanguageModel).toHaveBeenCalledWith(
|
|
301
|
-
'gemini-pro',
|
|
302
|
-
expect.objectContaining({
|
|
303
|
-
provider: 'google.generative-ai',
|
|
304
|
-
}),
|
|
305
|
-
);
|
|
306
|
-
});
|
|
307
|
-
});
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { isSupportedFileUrl } from './google-supported-file-url';
|
|
2
|
-
import { it, expect } from 'vitest';
|
|
3
|
-
|
|
4
|
-
it('should return true for valid Google generative language file URLs', () => {
|
|
5
|
-
const validUrl = new URL(
|
|
6
|
-
'https://generativelanguage.googleapis.com/v1beta/files/00000000-00000000-00000000-00000000',
|
|
7
|
-
);
|
|
8
|
-
expect(isSupportedFileUrl(validUrl)).toBe(true);
|
|
9
|
-
|
|
10
|
-
const simpleValidUrl = new URL(
|
|
11
|
-
'https://generativelanguage.googleapis.com/v1beta/files/test123',
|
|
12
|
-
);
|
|
13
|
-
expect(isSupportedFileUrl(simpleValidUrl)).toBe(true);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('should return true for valid YouTube URLs', () => {
|
|
17
|
-
const validYouTubeUrls = [
|
|
18
|
-
new URL('https://www.youtube.com/watch?v=dQw4w9WgXcQ'),
|
|
19
|
-
new URL('https://youtube.com/watch?v=dQw4w9WgXcQ'),
|
|
20
|
-
new URL('https://youtu.be/dQw4w9WgXcQ'),
|
|
21
|
-
new URL('https://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=youtu.be'),
|
|
22
|
-
new URL('https://youtu.be/dQw4w9WgXcQ?t=42'),
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
validYouTubeUrls.forEach(url => {
|
|
26
|
-
expect(isSupportedFileUrl(url)).toBe(true);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('should return false for invalid YouTube URLs', () => {
|
|
31
|
-
const invalidYouTubeUrls = [
|
|
32
|
-
new URL('https://youtube.com/channel/UCdQw4w9WgXcQ'),
|
|
33
|
-
new URL('https://youtube.com/playlist?list=PLdQw4w9WgXcQ'),
|
|
34
|
-
new URL('https://m.youtube.com/watch?v=dQw4w9WgXcQ'),
|
|
35
|
-
new URL('http://youtube.com/watch?v=dQw4w9WgXcQ'),
|
|
36
|
-
new URL('https://vimeo.com/123456789'),
|
|
37
|
-
];
|
|
38
|
-
|
|
39
|
-
invalidYouTubeUrls.forEach(url => {
|
|
40
|
-
expect(isSupportedFileUrl(url)).toBe(false);
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('should return false for non-Google generative language file URLs', () => {
|
|
45
|
-
const testCases = [
|
|
46
|
-
new URL('https://example.com'),
|
|
47
|
-
new URL('https://example.com/foo/bar'),
|
|
48
|
-
new URL('https://generativelanguage.googleapis.com'),
|
|
49
|
-
new URL('https://generativelanguage.googleapis.com/v1/other'),
|
|
50
|
-
new URL('http://generativelanguage.googleapis.com/v1beta/files/test'),
|
|
51
|
-
new URL('https://api.googleapis.com/v1beta/files/test'),
|
|
52
|
-
];
|
|
53
|
-
|
|
54
|
-
testCases.forEach(url => {
|
|
55
|
-
expect(isSupportedFileUrl(url)).toBe(false);
|
|
56
|
-
});
|
|
57
|
-
});
|