@ai-sdk/google-vertex 5.0.98 → 5.0.99
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 +13 -0
- package/dist/anthropic/edge/index.d.ts +84 -80
- package/dist/anthropic/edge/index.d.ts.map +1 -0
- package/dist/anthropic/edge/index.js +232 -272
- package/dist/anthropic/edge/index.js.map +1 -1
- package/dist/anthropic/index.d.ts +69 -66
- package/dist/anthropic/index.d.ts.map +1 -0
- package/dist/anthropic/index.js +166 -177
- package/dist/anthropic/index.js.map +1 -1
- package/dist/edge/index.d.ts +206 -194
- package/dist/edge/index.d.ts.map +1 -0
- package/dist/edge/index.js +1408 -1846
- package/dist/edge/index.js.map +1 -1
- package/dist/index.d.ts +265 -252
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1349 -1761
- package/dist/index.js.map +1 -1
- package/dist/maas/edge/index.d.ts +62 -59
- package/dist/maas/edge/index.d.ts.map +1 -0
- package/dist/maas/edge/index.js +166 -196
- package/dist/maas/edge/index.js.map +1 -1
- package/dist/maas/index.d.ts +47 -45
- package/dist/maas/index.d.ts.map +1 -0
- package/dist/maas/index.js +101 -102
- package/dist/maas/index.js.map +1 -1
- package/dist/xai/edge/index.d.ts +77 -73
- package/dist/xai/edge/index.d.ts.map +1 -0
- package/dist/xai/edge/index.js +203 -235
- package/dist/xai/edge/index.js.map +1 -1
- package/dist/xai/index.d.ts +62 -59
- package/dist/xai/index.d.ts.map +1 -0
- package/dist/xai/index.js +138 -141
- package/dist/xai/index.js.map +1 -1
- package/docs/16-google-vertex.mdx +3 -3
- package/package.json +11 -11
package/dist/edge/index.js
CHANGED
|
@@ -1,1907 +1,1469 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
// src/google-vertex-provider-base.ts
|
|
5
|
-
import {
|
|
6
|
-
GoogleInteractionsLanguageModel,
|
|
7
|
-
GoogleLanguageModel as GoogleLanguageModel2,
|
|
8
|
-
GoogleSpeechModel
|
|
9
|
-
} from "@ai-sdk/google/internal";
|
|
10
|
-
import {
|
|
11
|
-
generateId,
|
|
12
|
-
loadOptionalSetting,
|
|
13
|
-
loadSetting,
|
|
14
|
-
normalizeHeaders,
|
|
15
|
-
resolve as resolve6,
|
|
16
|
-
withoutTrailingSlash,
|
|
17
|
-
withUserAgentSuffix
|
|
18
|
-
} from "@ai-sdk/provider-utils";
|
|
19
|
-
|
|
20
|
-
// src/version.ts
|
|
21
|
-
var VERSION = true ? "5.0.98" : "0.0.0-test";
|
|
22
|
-
|
|
23
|
-
// src/google-vertex-embedding-model.ts
|
|
24
|
-
import {
|
|
25
|
-
TooManyEmbeddingValuesForCallError
|
|
26
|
-
} from "@ai-sdk/provider";
|
|
27
|
-
import {
|
|
28
|
-
combineHeaders,
|
|
29
|
-
createJsonResponseHandler,
|
|
30
|
-
postJsonToApi,
|
|
31
|
-
resolve,
|
|
32
|
-
parseProviderOptions,
|
|
33
|
-
serializeModelOptions,
|
|
34
|
-
WORKFLOW_SERIALIZE,
|
|
35
|
-
WORKFLOW_DESERIALIZE
|
|
36
|
-
} from "@ai-sdk/provider-utils";
|
|
37
|
-
import { z as z3 } from "zod/v4";
|
|
38
|
-
|
|
39
|
-
// src/google-vertex-error.ts
|
|
40
|
-
import { createJsonErrorResponseHandler } from "@ai-sdk/provider-utils";
|
|
1
|
+
import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, connectToWebSocket, convertBase64ToUint8Array, convertToBase64, convertUint8ArrayToBase64, createJsonErrorResponseHandler, createJsonResponseHandler, generateId, getRuntimeEnvironmentUserAgent, lazySchema, loadOptionalSetting, loadSetting, normalizeHeaders, parseProviderOptions, postJsonToApi, resolve, safeParseJSON, serializeModelOptions, waitForWebSocketBufferDrain, withUserAgentSuffix, withoutTrailingSlash, zodSchema } from "@ai-sdk/provider-utils";
|
|
2
|
+
import { GoogleInteractionsLanguageModel, GoogleLanguageModel, GoogleSpeechModel, googleTools } from "@ai-sdk/google/internal";
|
|
3
|
+
import { AISDKError, InvalidArgumentError, TooManyEmbeddingValuesForCallError } from "@ai-sdk/provider";
|
|
41
4
|
import { z } from "zod/v4";
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
5
|
+
//#region src/version.ts
|
|
6
|
+
const VERSION = "5.0.99";
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/google-vertex-error.ts
|
|
9
|
+
const googleVertexErrorDataSchema = z.object({ error: z.object({
|
|
10
|
+
code: z.number().nullable(),
|
|
11
|
+
message: z.string(),
|
|
12
|
+
status: z.string()
|
|
13
|
+
}) });
|
|
14
|
+
const googleVertexFailedResponseHandler = createJsonErrorResponseHandler({
|
|
15
|
+
errorSchema: googleVertexErrorDataSchema,
|
|
16
|
+
errorToMessage: (data) => data.error.message
|
|
48
17
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
*/
|
|
91
|
-
title: z2.string().optional(),
|
|
92
|
-
/**
|
|
93
|
-
* Optional. When set to true, input text will be truncated. When set to false,
|
|
94
|
-
* an error is returned if the input text is longer than the maximum length supported by the model. Defaults to true.
|
|
95
|
-
*/
|
|
96
|
-
autoTruncate: z2.boolean().optional()
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/google-vertex-embedding-model-options.ts
|
|
20
|
+
const googleVertexEmbeddingModelOptions = z.object({
|
|
21
|
+
/**
|
|
22
|
+
* Optional. Optional reduced dimension for the output embedding.
|
|
23
|
+
* If set, excessive values in the output embedding are truncated from the end.
|
|
24
|
+
*/
|
|
25
|
+
outputDimensionality: z.number().optional(),
|
|
26
|
+
/**
|
|
27
|
+
* Optional. Specifies the task type for generating embeddings.
|
|
28
|
+
* Supported task types:
|
|
29
|
+
* - SEMANTIC_SIMILARITY: Optimized for text similarity.
|
|
30
|
+
* - CLASSIFICATION: Optimized for text classification.
|
|
31
|
+
* - CLUSTERING: Optimized for clustering texts based on similarity.
|
|
32
|
+
* - RETRIEVAL_DOCUMENT: Optimized for document retrieval.
|
|
33
|
+
* - RETRIEVAL_QUERY: Optimized for query-based retrieval.
|
|
34
|
+
* - QUESTION_ANSWERING: Optimized for answering questions.
|
|
35
|
+
* - FACT_VERIFICATION: Optimized for verifying factual information.
|
|
36
|
+
* - CODE_RETRIEVAL_QUERY: Optimized for retrieving code blocks based on natural language queries.
|
|
37
|
+
*/
|
|
38
|
+
taskType: z.enum([
|
|
39
|
+
"SEMANTIC_SIMILARITY",
|
|
40
|
+
"CLASSIFICATION",
|
|
41
|
+
"CLUSTERING",
|
|
42
|
+
"RETRIEVAL_DOCUMENT",
|
|
43
|
+
"RETRIEVAL_QUERY",
|
|
44
|
+
"QUESTION_ANSWERING",
|
|
45
|
+
"FACT_VERIFICATION",
|
|
46
|
+
"CODE_RETRIEVAL_QUERY"
|
|
47
|
+
]).optional(),
|
|
48
|
+
/**
|
|
49
|
+
* Optional. The title of the document being embedded.
|
|
50
|
+
* Only valid when task_type is set to 'RETRIEVAL_DOCUMENT'.
|
|
51
|
+
* Helps the model produce better embeddings by providing additional context.
|
|
52
|
+
*/
|
|
53
|
+
title: z.string().optional(),
|
|
54
|
+
/**
|
|
55
|
+
* Optional. When set to true, input text will be truncated. When set to false,
|
|
56
|
+
* an error is returned if the input text is longer than the maximum length supported by the model. Defaults to true.
|
|
57
|
+
*/
|
|
58
|
+
autoTruncate: z.boolean().optional()
|
|
97
59
|
});
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
var GoogleVertexEmbeddingModel = class
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
task_type: googleOptions.taskType,
|
|
205
|
-
title: googleOptions.title
|
|
206
|
-
})),
|
|
207
|
-
parameters: {
|
|
208
|
-
outputDimensionality: googleOptions.outputDimensionality,
|
|
209
|
-
autoTruncate: googleOptions.autoTruncate
|
|
210
|
-
}
|
|
211
|
-
},
|
|
212
|
-
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
213
|
-
successfulResponseHandler: createJsonResponseHandler(
|
|
214
|
-
googleVertexTextEmbeddingResponseSchema
|
|
215
|
-
),
|
|
216
|
-
abortSignal,
|
|
217
|
-
fetch: this.config.fetch
|
|
218
|
-
});
|
|
219
|
-
return {
|
|
220
|
-
warnings: [],
|
|
221
|
-
embeddings: response.predictions.map(
|
|
222
|
-
(prediction) => prediction.embeddings.values
|
|
223
|
-
),
|
|
224
|
-
usage: {
|
|
225
|
-
tokens: response.predictions.reduce(
|
|
226
|
-
(tokenCount, prediction) => tokenCount + prediction.embeddings.statistics.token_count,
|
|
227
|
-
0
|
|
228
|
-
)
|
|
229
|
-
},
|
|
230
|
-
response: { headers: responseHeaders, body: rawValue }
|
|
231
|
-
};
|
|
232
|
-
}
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/google-vertex-embedding-model.ts
|
|
62
|
+
var GoogleVertexEmbeddingModel = class GoogleVertexEmbeddingModel {
|
|
63
|
+
static [WORKFLOW_SERIALIZE](model) {
|
|
64
|
+
return serializeModelOptions({
|
|
65
|
+
modelId: model.modelId,
|
|
66
|
+
config: model.config
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
static [WORKFLOW_DESERIALIZE](options) {
|
|
70
|
+
return new GoogleVertexEmbeddingModel(options.modelId, options.config);
|
|
71
|
+
}
|
|
72
|
+
get provider() {
|
|
73
|
+
return this.config.provider;
|
|
74
|
+
}
|
|
75
|
+
get maxEmbeddingsPerCall() {
|
|
76
|
+
return usesEmbedContentEndpoint(this.modelId) ? 1 : 250;
|
|
77
|
+
}
|
|
78
|
+
constructor(modelId, config) {
|
|
79
|
+
this.specificationVersion = "v4";
|
|
80
|
+
this.supportsParallelCalls = true;
|
|
81
|
+
this.modelId = modelId;
|
|
82
|
+
this.config = config;
|
|
83
|
+
}
|
|
84
|
+
async doEmbed({ values, headers, abortSignal, providerOptions }) {
|
|
85
|
+
let googleOptions = await parseProviderOptions({
|
|
86
|
+
provider: "googleVertex",
|
|
87
|
+
providerOptions,
|
|
88
|
+
schema: googleVertexEmbeddingModelOptions
|
|
89
|
+
});
|
|
90
|
+
if (googleOptions == null) googleOptions = await parseProviderOptions({
|
|
91
|
+
provider: "vertex",
|
|
92
|
+
providerOptions,
|
|
93
|
+
schema: googleVertexEmbeddingModelOptions
|
|
94
|
+
});
|
|
95
|
+
if (googleOptions == null) googleOptions = await parseProviderOptions({
|
|
96
|
+
provider: "google",
|
|
97
|
+
providerOptions,
|
|
98
|
+
schema: googleVertexEmbeddingModelOptions
|
|
99
|
+
});
|
|
100
|
+
googleOptions = googleOptions ?? {};
|
|
101
|
+
if (values.length > this.maxEmbeddingsPerCall) throw new TooManyEmbeddingValuesForCallError({
|
|
102
|
+
provider: this.provider,
|
|
103
|
+
modelId: this.modelId,
|
|
104
|
+
maxEmbeddingsPerCall: this.maxEmbeddingsPerCall,
|
|
105
|
+
values
|
|
106
|
+
});
|
|
107
|
+
const mergedHeaders = combineHeaders(this.config.headers ? await resolve(this.config.headers) : void 0, headers);
|
|
108
|
+
if (usesEmbedContentEndpoint(this.modelId)) {
|
|
109
|
+
const { responseHeaders, value: response, rawValue } = await postJsonToApi({
|
|
110
|
+
url: `${this.config.baseURL}/models/${this.modelId}:embedContent`,
|
|
111
|
+
headers: mergedHeaders,
|
|
112
|
+
body: {
|
|
113
|
+
content: { parts: [{ text: values[0] }] },
|
|
114
|
+
embedContentConfig: {
|
|
115
|
+
outputDimensionality: googleOptions.outputDimensionality,
|
|
116
|
+
taskType: googleOptions.taskType,
|
|
117
|
+
title: googleOptions.title,
|
|
118
|
+
autoTruncate: googleOptions.autoTruncate
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
122
|
+
successfulResponseHandler: createJsonResponseHandler(googleVertexEmbedContentResponseSchema),
|
|
123
|
+
abortSignal,
|
|
124
|
+
fetch: this.config.fetch
|
|
125
|
+
});
|
|
126
|
+
return {
|
|
127
|
+
warnings: [],
|
|
128
|
+
embeddings: [response.embedding.values],
|
|
129
|
+
usage: response.usageMetadata?.promptTokenCount == null ? void 0 : { tokens: response.usageMetadata.promptTokenCount },
|
|
130
|
+
response: {
|
|
131
|
+
headers: responseHeaders,
|
|
132
|
+
body: rawValue
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
const url = `${this.config.baseURL}/models/${this.modelId}:predict`;
|
|
137
|
+
const { responseHeaders, value: response, rawValue } = await postJsonToApi({
|
|
138
|
+
url,
|
|
139
|
+
headers: mergedHeaders,
|
|
140
|
+
body: {
|
|
141
|
+
instances: values.map((value) => ({
|
|
142
|
+
content: value,
|
|
143
|
+
task_type: googleOptions.taskType,
|
|
144
|
+
title: googleOptions.title
|
|
145
|
+
})),
|
|
146
|
+
parameters: {
|
|
147
|
+
outputDimensionality: googleOptions.outputDimensionality,
|
|
148
|
+
autoTruncate: googleOptions.autoTruncate
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
152
|
+
successfulResponseHandler: createJsonResponseHandler(googleVertexTextEmbeddingResponseSchema),
|
|
153
|
+
abortSignal,
|
|
154
|
+
fetch: this.config.fetch
|
|
155
|
+
});
|
|
156
|
+
return {
|
|
157
|
+
warnings: [],
|
|
158
|
+
embeddings: response.predictions.map((prediction) => prediction.embeddings.values),
|
|
159
|
+
usage: { tokens: response.predictions.reduce((tokenCount, prediction) => tokenCount + prediction.embeddings.statistics.token_count, 0) },
|
|
160
|
+
response: {
|
|
161
|
+
headers: responseHeaders,
|
|
162
|
+
body: rawValue
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
}
|
|
233
166
|
};
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
})
|
|
242
|
-
})
|
|
243
|
-
})
|
|
244
|
-
)
|
|
245
|
-
});
|
|
246
|
-
var googleVertexEmbedContentResponseSchema = z3.object({
|
|
247
|
-
embedding: z3.object({
|
|
248
|
-
values: z3.array(z3.number())
|
|
249
|
-
}),
|
|
250
|
-
usageMetadata: z3.object({
|
|
251
|
-
promptTokenCount: z3.number().nullish()
|
|
252
|
-
}).nullish()
|
|
167
|
+
const googleVertexTextEmbeddingResponseSchema = z.object({ predictions: z.array(z.object({ embeddings: z.object({
|
|
168
|
+
values: z.array(z.number()),
|
|
169
|
+
statistics: z.object({ token_count: z.number() })
|
|
170
|
+
}) })) });
|
|
171
|
+
const googleVertexEmbedContentResponseSchema = z.object({
|
|
172
|
+
embedding: z.object({ values: z.array(z.number()) }),
|
|
173
|
+
usageMetadata: z.object({ promptTokenCount: z.number().nullish() }).nullish()
|
|
253
174
|
});
|
|
254
175
|
function usesEmbedContentEndpoint(modelId) {
|
|
255
|
-
|
|
176
|
+
return modelId === "gemini-embedding-2" || modelId === "gemini-embedding-2-preview";
|
|
256
177
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
serializeModelOptions as serializeModelOptions2,
|
|
264
|
-
WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE2,
|
|
265
|
-
WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE2
|
|
266
|
-
} from "@ai-sdk/provider-utils";
|
|
267
|
-
var googleVertexImageModelsWithFileInputSupport = /* @__PURE__ */ new Set([
|
|
268
|
-
"gemini-2.5-flash-image",
|
|
269
|
-
"gemini-3-pro-image-preview",
|
|
270
|
-
"gemini-3.1-flash-image-preview"
|
|
178
|
+
//#endregion
|
|
179
|
+
//#region src/google-vertex-image-model.ts
|
|
180
|
+
const googleVertexImageModelsWithFileInputSupport = /* @__PURE__ */ new Set([
|
|
181
|
+
"gemini-2.5-flash-image",
|
|
182
|
+
"gemini-3-pro-image-preview",
|
|
183
|
+
"gemini-3.1-flash-image-preview"
|
|
271
184
|
]);
|
|
272
|
-
var GoogleVertexImageModel = class
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
googleVertex: innerVertexOptions,
|
|
384
|
-
vertex: innerVertexOptions
|
|
385
|
-
},
|
|
386
|
-
headers,
|
|
387
|
-
abortSignal
|
|
388
|
-
});
|
|
389
|
-
const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
|
|
390
|
-
const images = [];
|
|
391
|
-
for (const part of result.content) {
|
|
392
|
-
if (part.type === "file" && part.mediaType.startsWith("image/") && part.data.type === "data") {
|
|
393
|
-
images.push(convertToBase64(part.data.data));
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
const geminiPayload = {
|
|
397
|
-
images: images.map(() => ({}))
|
|
398
|
-
};
|
|
399
|
-
return {
|
|
400
|
-
images,
|
|
401
|
-
...result.finishReason.unified === "content-filter" ? { isRetryable: false } : {},
|
|
402
|
-
warnings,
|
|
403
|
-
providerMetadata: {
|
|
404
|
-
googleVertex: geminiPayload,
|
|
405
|
-
vertex: geminiPayload
|
|
406
|
-
},
|
|
407
|
-
response: {
|
|
408
|
-
timestamp: currentDate,
|
|
409
|
-
modelId: this.modelId,
|
|
410
|
-
headers: result.response?.headers
|
|
411
|
-
},
|
|
412
|
-
usage: result.usage ? {
|
|
413
|
-
inputTokens: result.usage.inputTokens.total,
|
|
414
|
-
outputTokens: result.usage.outputTokens.total,
|
|
415
|
-
totalTokens: (result.usage.inputTokens.total ?? 0) + (result.usage.outputTokens.total ?? 0)
|
|
416
|
-
} : void 0
|
|
417
|
-
};
|
|
418
|
-
}
|
|
185
|
+
var GoogleVertexImageModel = class GoogleVertexImageModel {
|
|
186
|
+
static [WORKFLOW_SERIALIZE](model) {
|
|
187
|
+
return serializeModelOptions({
|
|
188
|
+
modelId: model.modelId,
|
|
189
|
+
config: model.config
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
static [WORKFLOW_DESERIALIZE](options) {
|
|
193
|
+
return new GoogleVertexImageModel(options.modelId, options.config);
|
|
194
|
+
}
|
|
195
|
+
get supportsFileInputs() {
|
|
196
|
+
return googleVertexImageModelsWithFileInputSupport.has(this.modelId) ? true : void 0;
|
|
197
|
+
}
|
|
198
|
+
get supportsMaskInputs() {
|
|
199
|
+
return this.supportsFileInputs === true ? false : void 0;
|
|
200
|
+
}
|
|
201
|
+
get provider() {
|
|
202
|
+
return this.config.provider;
|
|
203
|
+
}
|
|
204
|
+
constructor(modelId, config) {
|
|
205
|
+
this.modelId = modelId;
|
|
206
|
+
this.config = config;
|
|
207
|
+
this.specificationVersion = "v4";
|
|
208
|
+
this.maxImagesPerCall = 1;
|
|
209
|
+
}
|
|
210
|
+
async doGenerate(options) {
|
|
211
|
+
if (!this.modelId.startsWith("gemini-")) throw new Error("Google image models other than Gemini are no longer supported. Use a model ID that starts with `gemini-`.");
|
|
212
|
+
const { prompt, size, aspectRatio, seed, providerOptions, headers, abortSignal, files, mask } = options;
|
|
213
|
+
const warnings = [];
|
|
214
|
+
if (mask != null) throw new Error("Gemini image models do not support mask-based image editing.");
|
|
215
|
+
if (size != null) warnings.push({
|
|
216
|
+
type: "unsupported",
|
|
217
|
+
feature: "size",
|
|
218
|
+
details: "This model does not support the `size` option. Use `aspectRatio` instead."
|
|
219
|
+
});
|
|
220
|
+
const userContent = [];
|
|
221
|
+
if (prompt != null) userContent.push({
|
|
222
|
+
type: "text",
|
|
223
|
+
text: prompt
|
|
224
|
+
});
|
|
225
|
+
if (files != null && files.length > 0) for (const file of files) if (file.type === "url") userContent.push({
|
|
226
|
+
type: "file",
|
|
227
|
+
data: {
|
|
228
|
+
type: "url",
|
|
229
|
+
url: new URL(file.url)
|
|
230
|
+
},
|
|
231
|
+
mediaType: "image/*"
|
|
232
|
+
});
|
|
233
|
+
else userContent.push({
|
|
234
|
+
type: "file",
|
|
235
|
+
data: {
|
|
236
|
+
type: "data",
|
|
237
|
+
data: typeof file.data === "string" ? file.data : new Uint8Array(file.data)
|
|
238
|
+
},
|
|
239
|
+
mediaType: file.mediaType
|
|
240
|
+
});
|
|
241
|
+
const languageModelPrompt = [{
|
|
242
|
+
role: "user",
|
|
243
|
+
content: userContent
|
|
244
|
+
}];
|
|
245
|
+
const languageModel = new GoogleLanguageModel(this.modelId, {
|
|
246
|
+
provider: this.config.provider,
|
|
247
|
+
baseURL: this.config.baseURL,
|
|
248
|
+
headers: this.config.headers ?? {},
|
|
249
|
+
fetch: this.config.fetch,
|
|
250
|
+
generateId: this.config.generateId ?? generateId,
|
|
251
|
+
supportedUrls: () => ({ "*": [/^https?:\/\/.*$/, /^gs:\/\/.*$/] })
|
|
252
|
+
});
|
|
253
|
+
const { responseModalities: _strippedResponseModalities, imageConfig: userImageConfig, ...userVertexOptions } = providerOptions?.googleVertex ?? providerOptions?.vertex ?? {};
|
|
254
|
+
const innerVertexOptions = {
|
|
255
|
+
...userVertexOptions,
|
|
256
|
+
responseModalities: ["IMAGE"],
|
|
257
|
+
imageConfig: aspectRatio != null || userImageConfig != null ? {
|
|
258
|
+
...userImageConfig,
|
|
259
|
+
...aspectRatio != null ? { aspectRatio } : {}
|
|
260
|
+
} : void 0
|
|
261
|
+
};
|
|
262
|
+
const result = await languageModel.doGenerate({
|
|
263
|
+
prompt: languageModelPrompt,
|
|
264
|
+
seed,
|
|
265
|
+
providerOptions: {
|
|
266
|
+
googleVertex: innerVertexOptions,
|
|
267
|
+
vertex: innerVertexOptions
|
|
268
|
+
},
|
|
269
|
+
headers,
|
|
270
|
+
abortSignal
|
|
271
|
+
});
|
|
272
|
+
const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
|
|
273
|
+
const images = [];
|
|
274
|
+
for (const part of result.content) if (part.type === "file" && part.mediaType.startsWith("image/") && part.data.type === "data") images.push(convertToBase64(part.data.data));
|
|
275
|
+
const geminiPayload = { images: images.map(() => ({})) };
|
|
276
|
+
return {
|
|
277
|
+
images,
|
|
278
|
+
...result.finishReason.unified === "content-filter" ? { isRetryable: false } : {},
|
|
279
|
+
warnings,
|
|
280
|
+
providerMetadata: {
|
|
281
|
+
googleVertex: geminiPayload,
|
|
282
|
+
vertex: geminiPayload
|
|
283
|
+
},
|
|
284
|
+
response: {
|
|
285
|
+
timestamp: currentDate,
|
|
286
|
+
modelId: this.modelId,
|
|
287
|
+
headers: result.response?.headers
|
|
288
|
+
},
|
|
289
|
+
usage: result.usage ? {
|
|
290
|
+
inputTokens: result.usage.inputTokens.total,
|
|
291
|
+
outputTokens: result.usage.outputTokens.total,
|
|
292
|
+
totalTokens: (result.usage.inputTokens.total ?? 0) + (result.usage.outputTokens.total ?? 0)
|
|
293
|
+
} : void 0
|
|
294
|
+
};
|
|
295
|
+
}
|
|
419
296
|
};
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
var
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
510
|
-
successfulResponseHandler: createJsonResponseHandler2(
|
|
511
|
-
googleVertexCloudTTSResponseSchema
|
|
512
|
-
),
|
|
513
|
-
abortSignal: options.abortSignal,
|
|
514
|
-
fetch: this.config.fetch
|
|
515
|
-
});
|
|
516
|
-
const audio = response.audioContent != null ? convertBase64ToUint8Array(response.audioContent) : new Uint8Array(0);
|
|
517
|
-
return {
|
|
518
|
-
audio,
|
|
519
|
-
warnings,
|
|
520
|
-
request: {
|
|
521
|
-
body: JSON.stringify(requestBody)
|
|
522
|
-
},
|
|
523
|
-
response: {
|
|
524
|
-
timestamp: currentDate,
|
|
525
|
-
modelId: this.modelId,
|
|
526
|
-
headers: responseHeaders,
|
|
527
|
-
body: rawResponse
|
|
528
|
-
},
|
|
529
|
-
providerMetadata: {
|
|
530
|
-
google: {
|
|
531
|
-
mimeType: "audio/wav"
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
};
|
|
535
|
-
}
|
|
297
|
+
//#endregion
|
|
298
|
+
//#region src/google-vertex-cloud-tts-speech-model.ts
|
|
299
|
+
const DEFAULT_VOICE = "Kore";
|
|
300
|
+
const DEFAULT_LANGUAGE = "en-US";
|
|
301
|
+
const CHIRP3_HD_VOICE_INFIX = "Chirp3-HD";
|
|
302
|
+
const CLOUD_TTS_SYNTHESIZE_URL = "https://texttospeech.googleapis.com/v1/text:synthesize";
|
|
303
|
+
/**
|
|
304
|
+
* Speech model for Chirp 3: HD voices on the Google Cloud Text-to-Speech API.
|
|
305
|
+
*
|
|
306
|
+
* Unlike the Gemini TTS models (which go through the Vertex
|
|
307
|
+
* `generateContent` endpoint via `GoogleSpeechModel`), Chirp 3: HD voices are
|
|
308
|
+
* served by the dedicated Cloud Text-to-Speech `text:synthesize` endpoint,
|
|
309
|
+
* reusing the provider's Google Cloud credentials.
|
|
310
|
+
*/
|
|
311
|
+
var GoogleVertexCloudTTSSpeechModel = class GoogleVertexCloudTTSSpeechModel {
|
|
312
|
+
static [WORKFLOW_SERIALIZE](model) {
|
|
313
|
+
return serializeModelOptions({
|
|
314
|
+
modelId: model.modelId,
|
|
315
|
+
config: model.config
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
static [WORKFLOW_DESERIALIZE](options) {
|
|
319
|
+
return new GoogleVertexCloudTTSSpeechModel(options.modelId, options.config);
|
|
320
|
+
}
|
|
321
|
+
get provider() {
|
|
322
|
+
return this.config.provider;
|
|
323
|
+
}
|
|
324
|
+
constructor(modelId, config) {
|
|
325
|
+
this.modelId = modelId;
|
|
326
|
+
this.config = config;
|
|
327
|
+
this.specificationVersion = "v4";
|
|
328
|
+
}
|
|
329
|
+
async doGenerate(options) {
|
|
330
|
+
const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
|
|
331
|
+
const warnings = [];
|
|
332
|
+
const { text, voice = DEFAULT_VOICE, outputFormat, instructions, speed, language } = options;
|
|
333
|
+
let voiceName;
|
|
334
|
+
let languageCode;
|
|
335
|
+
if (voice.includes(CHIRP3_HD_VOICE_INFIX)) {
|
|
336
|
+
voiceName = voice;
|
|
337
|
+
const localePrefix = voice.split(CHIRP3_HD_VOICE_INFIX)[0].replace(/-$/, "");
|
|
338
|
+
languageCode = language ?? (localePrefix || DEFAULT_LANGUAGE);
|
|
339
|
+
} else {
|
|
340
|
+
languageCode = language ?? DEFAULT_LANGUAGE;
|
|
341
|
+
voiceName = `${languageCode}-${CHIRP3_HD_VOICE_INFIX}-${voice}`;
|
|
342
|
+
}
|
|
343
|
+
if (instructions != null) warnings.push({
|
|
344
|
+
type: "unsupported",
|
|
345
|
+
feature: "instructions",
|
|
346
|
+
details: "Google Cloud Text-to-Speech Chirp 3: HD voices do not support the `instructions` option. It was ignored."
|
|
347
|
+
});
|
|
348
|
+
if (outputFormat != null && outputFormat !== "wav") warnings.push({
|
|
349
|
+
type: "unsupported",
|
|
350
|
+
feature: "outputFormat",
|
|
351
|
+
details: `Unsupported output format: ${outputFormat}. Using wav instead.`
|
|
352
|
+
});
|
|
353
|
+
const requestBody = {
|
|
354
|
+
input: { text },
|
|
355
|
+
voice: {
|
|
356
|
+
languageCode,
|
|
357
|
+
name: voiceName
|
|
358
|
+
},
|
|
359
|
+
audioConfig: {
|
|
360
|
+
audioEncoding: "LINEAR16",
|
|
361
|
+
...speed != null ? { speakingRate: speed } : {}
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
const { value: response, responseHeaders, rawValue: rawResponse } = await postJsonToApi({
|
|
365
|
+
url: CLOUD_TTS_SYNTHESIZE_URL,
|
|
366
|
+
headers: combineHeaders(this.config.headers ? await resolve(this.config.headers) : void 0, options.headers),
|
|
367
|
+
body: requestBody,
|
|
368
|
+
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
369
|
+
successfulResponseHandler: createJsonResponseHandler(googleVertexCloudTTSResponseSchema),
|
|
370
|
+
abortSignal: options.abortSignal,
|
|
371
|
+
fetch: this.config.fetch
|
|
372
|
+
});
|
|
373
|
+
return {
|
|
374
|
+
audio: response.audioContent != null ? convertBase64ToUint8Array(response.audioContent) : /* @__PURE__ */ new Uint8Array(0),
|
|
375
|
+
warnings,
|
|
376
|
+
request: { body: JSON.stringify(requestBody) },
|
|
377
|
+
response: {
|
|
378
|
+
timestamp: currentDate,
|
|
379
|
+
modelId: this.modelId,
|
|
380
|
+
headers: responseHeaders,
|
|
381
|
+
body: rawResponse
|
|
382
|
+
},
|
|
383
|
+
providerMetadata: { google: { mimeType: "audio/wav" } }
|
|
384
|
+
};
|
|
385
|
+
}
|
|
536
386
|
};
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
fileSearch: googleTools.fileSearch,
|
|
549
|
-
codeExecution: googleTools.codeExecution,
|
|
550
|
-
vertexRagStore: googleTools.vertexRagStore
|
|
387
|
+
const googleVertexCloudTTSResponseSchema = z.object({ audioContent: z.string().nullish() });
|
|
388
|
+
//#endregion
|
|
389
|
+
//#region src/google-vertex-tools.ts
|
|
390
|
+
const googleVertexTools = {
|
|
391
|
+
googleSearch: googleTools.googleSearch,
|
|
392
|
+
enterpriseWebSearch: googleTools.enterpriseWebSearch,
|
|
393
|
+
googleMaps: googleTools.googleMaps,
|
|
394
|
+
urlContext: googleTools.urlContext,
|
|
395
|
+
fileSearch: googleTools.fileSearch,
|
|
396
|
+
codeExecution: googleTools.codeExecution,
|
|
397
|
+
vertexRagStore: googleTools.vertexRagStore
|
|
551
398
|
};
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
* transcription result can include segments.
|
|
583
|
-
*
|
|
584
|
-
* Enabling word-level timestamps can reduce transcription quality and speed
|
|
585
|
-
* for Chirp models.
|
|
586
|
-
*/
|
|
587
|
-
enableWordTimeOffsets: z5.boolean().optional(),
|
|
588
|
-
/**
|
|
589
|
-
* The Cloud Speech-to-Text region for the request (e.g. `'us'`, `'eu'`,
|
|
590
|
-
* `'us-central1'`). Defaults to the provider `location`.
|
|
591
|
-
*
|
|
592
|
-
* Note: Speech-to-Text regions differ from Vertex AI regions. Chirp is only
|
|
593
|
-
* available in specific Speech-to-Text regions and is not available in the
|
|
594
|
-
* `global` location.
|
|
595
|
-
*/
|
|
596
|
-
region: z5.string().optional()
|
|
399
|
+
//#endregion
|
|
400
|
+
//#region src/google-vertex-transcription-model-options.ts
|
|
401
|
+
const googleVertexTranscriptionProviderOptionsSchema = z.object({
|
|
402
|
+
/**
|
|
403
|
+
* BCP-47 language codes to recognize (e.g. `['en-US']`), or `['auto']` to let
|
|
404
|
+
* Chirp auto-detect the spoken language. Defaults to `['auto']`. For
|
|
405
|
+
* `telephony`, pass a supported explicit language code.
|
|
406
|
+
*/
|
|
407
|
+
languageCodes: z.array(z.string()).optional(),
|
|
408
|
+
/**
|
|
409
|
+
* Whether to add punctuation to the transcript. Defaults to `true`.
|
|
410
|
+
*/
|
|
411
|
+
enableAutomaticPunctuation: z.boolean().optional(),
|
|
412
|
+
/**
|
|
413
|
+
* Whether to include word-level timestamps. Defaults to `true` so the
|
|
414
|
+
* transcription result can include segments.
|
|
415
|
+
*
|
|
416
|
+
* Enabling word-level timestamps can reduce transcription quality and speed
|
|
417
|
+
* for Chirp models.
|
|
418
|
+
*/
|
|
419
|
+
enableWordTimeOffsets: z.boolean().optional(),
|
|
420
|
+
/**
|
|
421
|
+
* The Cloud Speech-to-Text region for the request (e.g. `'us'`, `'eu'`,
|
|
422
|
+
* `'us-central1'`). Defaults to the provider `location`.
|
|
423
|
+
*
|
|
424
|
+
* Note: Speech-to-Text regions differ from Vertex AI regions. Chirp is only
|
|
425
|
+
* available in specific Speech-to-Text regions and is not available in the
|
|
426
|
+
* `global` location.
|
|
427
|
+
*/
|
|
428
|
+
region: z.string().optional()
|
|
597
429
|
});
|
|
598
|
-
|
|
599
|
-
|
|
430
|
+
//#endregion
|
|
431
|
+
//#region src/google-vertex-transcription-model.ts
|
|
600
432
|
function parseDurationSeconds(value) {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
const seconds = Number.parseFloat(value);
|
|
605
|
-
return Number.isFinite(seconds) ? seconds : void 0;
|
|
433
|
+
if (value == null) return;
|
|
434
|
+
const seconds = Number.parseFloat(value);
|
|
435
|
+
return Number.isFinite(seconds) ? seconds : void 0;
|
|
606
436
|
}
|
|
607
437
|
function convertBcp47ToIso6391(value) {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
return void 0;
|
|
616
|
-
}
|
|
438
|
+
if (value == null) return;
|
|
439
|
+
try {
|
|
440
|
+
const language = new Intl.Locale(value).language;
|
|
441
|
+
return language.length === 2 ? language : void 0;
|
|
442
|
+
} catch {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
617
445
|
}
|
|
618
|
-
var GoogleVertexTranscriptionModel = class
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
language,
|
|
701
|
-
durationInSeconds: parseDurationSeconds(
|
|
702
|
-
response.metadata?.totalBilledDuration
|
|
703
|
-
),
|
|
704
|
-
warnings,
|
|
705
|
-
response: {
|
|
706
|
-
timestamp: currentDate,
|
|
707
|
-
modelId: this.modelId,
|
|
708
|
-
headers: responseHeaders,
|
|
709
|
-
body: rawResponse
|
|
710
|
-
}
|
|
711
|
-
};
|
|
712
|
-
}
|
|
446
|
+
var GoogleVertexTranscriptionModel = class GoogleVertexTranscriptionModel {
|
|
447
|
+
static [WORKFLOW_SERIALIZE](model) {
|
|
448
|
+
return serializeModelOptions({
|
|
449
|
+
modelId: model.modelId,
|
|
450
|
+
config: model.config
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
static [WORKFLOW_DESERIALIZE](options) {
|
|
454
|
+
return new GoogleVertexTranscriptionModel(options.modelId, options.config);
|
|
455
|
+
}
|
|
456
|
+
get provider() {
|
|
457
|
+
return this.config.provider;
|
|
458
|
+
}
|
|
459
|
+
constructor(modelId, config) {
|
|
460
|
+
this.modelId = modelId;
|
|
461
|
+
this.config = config;
|
|
462
|
+
this.specificationVersion = "v4";
|
|
463
|
+
}
|
|
464
|
+
async doGenerate(options) {
|
|
465
|
+
const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
|
|
466
|
+
const warnings = [];
|
|
467
|
+
let googleOptions;
|
|
468
|
+
for (const provider of [
|
|
469
|
+
"googleVertex",
|
|
470
|
+
"vertex",
|
|
471
|
+
"google"
|
|
472
|
+
]) {
|
|
473
|
+
googleOptions = await parseProviderOptions({
|
|
474
|
+
provider,
|
|
475
|
+
providerOptions: options.providerOptions,
|
|
476
|
+
schema: googleVertexTranscriptionProviderOptionsSchema
|
|
477
|
+
});
|
|
478
|
+
if (googleOptions != null) break;
|
|
479
|
+
}
|
|
480
|
+
const region = googleOptions?.region ?? this.config.location;
|
|
481
|
+
const languageCodes = googleOptions?.languageCodes ?? ["auto"];
|
|
482
|
+
const content = typeof options.audio === "string" ? options.audio : convertUint8ArrayToBase64(options.audio);
|
|
483
|
+
const requestBody = {
|
|
484
|
+
config: {
|
|
485
|
+
model: this.modelId,
|
|
486
|
+
languageCodes,
|
|
487
|
+
autoDecodingConfig: {},
|
|
488
|
+
features: {
|
|
489
|
+
enableWordTimeOffsets: googleOptions?.enableWordTimeOffsets ?? true,
|
|
490
|
+
enableAutomaticPunctuation: googleOptions?.enableAutomaticPunctuation ?? true
|
|
491
|
+
}
|
|
492
|
+
},
|
|
493
|
+
content
|
|
494
|
+
};
|
|
495
|
+
const url = `https://${region === "global" ? "speech.googleapis.com" : `${region}-speech.googleapis.com`}/v2/projects/${this.config.project}/locations/${region}/recognizers/_:recognize`;
|
|
496
|
+
const { value: response, responseHeaders, rawValue: rawResponse } = await postJsonToApi({
|
|
497
|
+
url,
|
|
498
|
+
headers: combineHeaders(this.config.headers ? await resolve(this.config.headers) : void 0, options.headers),
|
|
499
|
+
body: requestBody,
|
|
500
|
+
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
501
|
+
successfulResponseHandler: createJsonResponseHandler(googleVertexTranscriptionResponseSchema),
|
|
502
|
+
abortSignal: options.abortSignal,
|
|
503
|
+
fetch: this.config.fetch
|
|
504
|
+
});
|
|
505
|
+
const results = response.results ?? [];
|
|
506
|
+
return {
|
|
507
|
+
text: results.map((result) => result.alternatives?.[0]?.transcript ?? "").join(" ").trim(),
|
|
508
|
+
segments: results.flatMap((result) => result.alternatives?.[0]?.words?.flatMap((word) => {
|
|
509
|
+
const startSecond = parseDurationSeconds(word.startOffset);
|
|
510
|
+
const endSecond = parseDurationSeconds(word.endOffset);
|
|
511
|
+
return word.word == null || startSecond == null || endSecond == null ? [] : [{
|
|
512
|
+
text: word.word,
|
|
513
|
+
startSecond,
|
|
514
|
+
endSecond
|
|
515
|
+
}];
|
|
516
|
+
}) ?? []),
|
|
517
|
+
language: convertBcp47ToIso6391(results[0]?.languageCode),
|
|
518
|
+
durationInSeconds: parseDurationSeconds(response.metadata?.totalBilledDuration),
|
|
519
|
+
warnings,
|
|
520
|
+
response: {
|
|
521
|
+
timestamp: currentDate,
|
|
522
|
+
modelId: this.modelId,
|
|
523
|
+
headers: responseHeaders,
|
|
524
|
+
body: rawResponse
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
}
|
|
713
528
|
};
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
})
|
|
728
|
-
).nullish(),
|
|
729
|
-
languageCode: z6.string().nullish()
|
|
730
|
-
})
|
|
731
|
-
).nullish(),
|
|
732
|
-
metadata: z6.object({
|
|
733
|
-
totalBilledDuration: z6.string().nullish()
|
|
734
|
-
}).nullish()
|
|
529
|
+
const googleVertexTranscriptionResponseSchema = z.object({
|
|
530
|
+
results: z.array(z.object({
|
|
531
|
+
alternatives: z.array(z.object({
|
|
532
|
+
transcript: z.string().nullish(),
|
|
533
|
+
words: z.array(z.object({
|
|
534
|
+
word: z.string().nullish(),
|
|
535
|
+
startOffset: z.string().nullish(),
|
|
536
|
+
endOffset: z.string().nullish()
|
|
537
|
+
})).nullish()
|
|
538
|
+
})).nullish(),
|
|
539
|
+
languageCode: z.string().nullish()
|
|
540
|
+
})).nullish(),
|
|
541
|
+
metadata: z.object({ totalBilledDuration: z.string().nullish() }).nullish()
|
|
735
542
|
});
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
wordTimestamp: z7.boolean().optional(),
|
|
774
|
-
/**
|
|
775
|
-
* Enables speaker diarization.
|
|
776
|
-
*/
|
|
777
|
-
diarization: z7.boolean().optional(),
|
|
778
|
-
/**
|
|
779
|
-
* Transcription output formatting mode.
|
|
780
|
-
*
|
|
781
|
-
* - `VERBATIM` (default): exact literal transcript preserving filler
|
|
782
|
-
* words, repetitions, and false starts.
|
|
783
|
-
* - `SMART`: cleans up and structures the transcript in real time —
|
|
784
|
-
* disfluency removal, inline self-corrections, structured formatting
|
|
785
|
-
* (lists, numbers, dates, paragraph breaks), and grammar/casing polish.
|
|
786
|
-
*/
|
|
787
|
-
mode: z7.enum(["SMART", "VERBATIM"]).optional()
|
|
543
|
+
//#endregion
|
|
544
|
+
//#region src/gemini-transcription/google-vertex-gemini-transcription-model-options.ts
|
|
545
|
+
/**
|
|
546
|
+
* Speech recognition options for Gemini transcription models on Vertex,
|
|
547
|
+
* shared by unary (`gemini-3.5-transcribe`) and live
|
|
548
|
+
* (`gemini-3.5-transcribe-live`) variants. Maps onto Google's
|
|
549
|
+
* `AudioTranscriptionConfig`.
|
|
550
|
+
*/
|
|
551
|
+
const googleVertexGeminiTranscriptionModelOptions = z.object({
|
|
552
|
+
/**
|
|
553
|
+
* BCP-47 language codes providing hints about the languages present in the
|
|
554
|
+
* audio. If omitted or empty, defaults to automatic language detection.
|
|
555
|
+
*/
|
|
556
|
+
languageCodes: z.array(z.string()).optional(),
|
|
557
|
+
/**
|
|
558
|
+
* Custom vocabulary phrases, which bias the speech recognition model
|
|
559
|
+
* toward recognizing specific terms.
|
|
560
|
+
*/
|
|
561
|
+
customVocabulary: z.array(z.string()).optional(),
|
|
562
|
+
/**
|
|
563
|
+
* Enables word-level timestamp generation.
|
|
564
|
+
*/
|
|
565
|
+
wordTimestamp: z.boolean().optional(),
|
|
566
|
+
/**
|
|
567
|
+
* Enables speaker diarization.
|
|
568
|
+
*/
|
|
569
|
+
diarization: z.boolean().optional(),
|
|
570
|
+
/**
|
|
571
|
+
* Transcription output formatting mode.
|
|
572
|
+
*
|
|
573
|
+
* - `VERBATIM` (default): exact literal transcript preserving filler
|
|
574
|
+
* words, repetitions, and false starts.
|
|
575
|
+
* - `SMART`: cleans up and structures the transcript in real time —
|
|
576
|
+
* disfluency removal, inline self-corrections, structured formatting
|
|
577
|
+
* (lists, numbers, dates, paragraph breaks), and grammar/casing polish.
|
|
578
|
+
*/
|
|
579
|
+
mode: z.enum(["SMART", "VERBATIM"]).optional()
|
|
788
580
|
});
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
581
|
+
//#endregion
|
|
582
|
+
//#region src/gemini-transcription/google-vertex-gemini-transcription-model.ts
|
|
583
|
+
const liveWebSocketPath = "google.cloud.aiplatform.v1.LlmBidiService/BidiGenerateContent";
|
|
584
|
+
/**
|
|
585
|
+
* After the input audio has ended, finish when no terminal signal
|
|
586
|
+
* (`turnComplete` / idle `interactionStatus`) arrives within this window.
|
|
587
|
+
* Trailing transcripts reset the timer.
|
|
588
|
+
*/
|
|
589
|
+
const defaultFinishGraceMs = 3e3;
|
|
590
|
+
/** Live transcription is only supported by `*-live` model variants. */
|
|
793
591
|
function isLiveTranscriptionModelId(modelId) {
|
|
794
|
-
|
|
592
|
+
return modelId.includes("-live");
|
|
795
593
|
}
|
|
594
|
+
/** Regional Vertex hostname (mirrors the provider's base-URL host rules). */
|
|
796
595
|
function vertexHost(location) {
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
}
|
|
801
|
-
return `${location}-aiplatform.googleapis.com`;
|
|
596
|
+
if (location === "global") return "aiplatform.googleapis.com";
|
|
597
|
+
if (location === "eu" || location === "us") return `aiplatform.${location}.rep.googleapis.com`;
|
|
598
|
+
return `${location}-aiplatform.googleapis.com`;
|
|
802
599
|
}
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
return {
|
|
942
|
-
request: { body: setup },
|
|
943
|
-
response: {
|
|
944
|
-
timestamp: currentDate,
|
|
945
|
-
modelId: this.modelId
|
|
946
|
-
},
|
|
947
|
-
stream: createVertexLiveTranscriptionStream({
|
|
948
|
-
webSocket: this.config.webSocket,
|
|
949
|
-
url,
|
|
950
|
-
headers,
|
|
951
|
-
setup,
|
|
952
|
-
inputAudioRate: options.inputAudioFormat.rate ?? 16e3,
|
|
953
|
-
finishGraceMs: this.config._internal?.finishGraceMs ?? defaultFinishGraceMs,
|
|
954
|
-
warnings,
|
|
955
|
-
audio: options.audio,
|
|
956
|
-
abortSignal: options.abortSignal,
|
|
957
|
-
includeRawChunks: options.includeRawChunks
|
|
958
|
-
})
|
|
959
|
-
};
|
|
960
|
-
}
|
|
600
|
+
/**
|
|
601
|
+
* Gemini transcription on Vertex AI. Unary variants transcribe via
|
|
602
|
+
* `generateContent`; live variants stream over the Vertex Live API WebSocket
|
|
603
|
+
* (`LlmBidiService/BidiGenerateContent`) with OAuth Bearer authentication
|
|
604
|
+
* from the provider's resolved headers.
|
|
605
|
+
*/
|
|
606
|
+
var GoogleVertexGeminiTranscriptionModel = class GoogleVertexGeminiTranscriptionModel {
|
|
607
|
+
static [WORKFLOW_SERIALIZE](model) {
|
|
608
|
+
return serializeModelOptions({
|
|
609
|
+
modelId: model.modelId,
|
|
610
|
+
config: model.config
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
static [WORKFLOW_DESERIALIZE](options) {
|
|
614
|
+
return new GoogleVertexGeminiTranscriptionModel(options.modelId, options.config);
|
|
615
|
+
}
|
|
616
|
+
get provider() {
|
|
617
|
+
return this.config.provider;
|
|
618
|
+
}
|
|
619
|
+
constructor(modelId, config) {
|
|
620
|
+
this.modelId = modelId;
|
|
621
|
+
this.config = config;
|
|
622
|
+
this.specificationVersion = "v4";
|
|
623
|
+
}
|
|
624
|
+
async parseOptions(providerOptions) {
|
|
625
|
+
for (const provider of [
|
|
626
|
+
"googleVertex",
|
|
627
|
+
"vertex",
|
|
628
|
+
"google"
|
|
629
|
+
]) {
|
|
630
|
+
const parsed = await parseProviderOptions({
|
|
631
|
+
provider,
|
|
632
|
+
providerOptions,
|
|
633
|
+
schema: googleVertexGeminiTranscriptionModelOptions
|
|
634
|
+
});
|
|
635
|
+
if (parsed != null) return parsed;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
async doGenerate(options) {
|
|
639
|
+
if (isLiveTranscriptionModelId(this.modelId)) throw new InvalidArgumentError({
|
|
640
|
+
argument: "modelId",
|
|
641
|
+
message: `Model '${this.modelId}' only supports streaming transcription. Use experimental_streamTranscribe, or a unary model such as 'gemini-3.5-transcribe'.`
|
|
642
|
+
});
|
|
643
|
+
const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
|
|
644
|
+
const warnings = [];
|
|
645
|
+
const audioTranscriptionConfig = buildAudioTranscriptionConfig(await this.parseOptions(options.providerOptions));
|
|
646
|
+
const requestBody = {
|
|
647
|
+
contents: [{
|
|
648
|
+
role: "user",
|
|
649
|
+
parts: [{ inlineData: {
|
|
650
|
+
mimeType: options.mediaType,
|
|
651
|
+
data: convertToBase64(options.audio)
|
|
652
|
+
} }]
|
|
653
|
+
}],
|
|
654
|
+
...audioTranscriptionConfig != null ? { generationConfig: { audioTranscriptionConfig } } : {}
|
|
655
|
+
};
|
|
656
|
+
const { value: response, responseHeaders, rawValue: rawResponse } = await postJsonToApi({
|
|
657
|
+
url: `${this.config.baseURL}/models/${this.modelId}:generateContent`,
|
|
658
|
+
headers: combineHeaders(this.config.headers ? await resolve(this.config.headers) : void 0, options.headers),
|
|
659
|
+
body: requestBody,
|
|
660
|
+
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
661
|
+
successfulResponseHandler: createJsonResponseHandler(googleVertexGeminiTranscriptionResponseSchema),
|
|
662
|
+
abortSignal: options.abortSignal,
|
|
663
|
+
fetch: this.config.fetch
|
|
664
|
+
});
|
|
665
|
+
const parts = response.candidates?.[0]?.content?.parts ?? [];
|
|
666
|
+
const plainText = parts.map((part) => part.text ?? "").join("");
|
|
667
|
+
const transcriptionText = parts.map((part) => part.audioTranscription?.text ?? "").join("");
|
|
668
|
+
const text = plainText !== "" ? plainText : transcriptionText;
|
|
669
|
+
let language;
|
|
670
|
+
const segments = [];
|
|
671
|
+
for (const part of parts) {
|
|
672
|
+
const transcription = part.audioTranscription;
|
|
673
|
+
if (transcription == null) continue;
|
|
674
|
+
language ??= transcription.languageCode ?? void 0;
|
|
675
|
+
for (const word of transcription.words ?? []) {
|
|
676
|
+
const startSecond = parseOffsetSeconds(word.startOffset);
|
|
677
|
+
const endSecond = parseOffsetSeconds(word.endOffset);
|
|
678
|
+
if (word.word == null || startSecond == null || endSecond == null) continue;
|
|
679
|
+
segments.push({
|
|
680
|
+
text: word.word,
|
|
681
|
+
startSecond,
|
|
682
|
+
endSecond
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
return {
|
|
687
|
+
text,
|
|
688
|
+
segments,
|
|
689
|
+
language,
|
|
690
|
+
durationInSeconds: void 0,
|
|
691
|
+
warnings,
|
|
692
|
+
response: {
|
|
693
|
+
timestamp: currentDate,
|
|
694
|
+
modelId: this.modelId,
|
|
695
|
+
headers: responseHeaders,
|
|
696
|
+
body: rawResponse
|
|
697
|
+
},
|
|
698
|
+
...response.usageMetadata != null ? { providerMetadata: { google: { usageMetadata: response.usageMetadata } } } : {}
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
async doStream(options) {
|
|
702
|
+
if (!isLiveTranscriptionModelId(this.modelId)) throw new InvalidArgumentError({
|
|
703
|
+
argument: "modelId",
|
|
704
|
+
message: `Model '${this.modelId}' does not support streaming transcription. Use a live model such as 'gemini-3.5-transcribe-live'.`
|
|
705
|
+
});
|
|
706
|
+
const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
|
|
707
|
+
const warnings = [];
|
|
708
|
+
const googleOptions = await this.parseOptions(options.providerOptions);
|
|
709
|
+
validateLiveInputAudioFormat(options.inputAudioFormat);
|
|
710
|
+
const headers = combineHeaders(this.config.headers ? await resolve(this.config.headers) : void 0, options.headers);
|
|
711
|
+
const { project, location } = this.config;
|
|
712
|
+
const modelResource = `projects/${project}/locations/${location}/publishers/google/models/${this.modelId}`;
|
|
713
|
+
const url = new URL(`wss://${vertexHost(location)}/ws/${liveWebSocketPath}`);
|
|
714
|
+
const setup = {
|
|
715
|
+
model: modelResource,
|
|
716
|
+
inputAudioTranscription: buildAudioTranscriptionConfig(googleOptions) ?? {}
|
|
717
|
+
};
|
|
718
|
+
return {
|
|
719
|
+
request: { body: setup },
|
|
720
|
+
response: {
|
|
721
|
+
timestamp: currentDate,
|
|
722
|
+
modelId: this.modelId
|
|
723
|
+
},
|
|
724
|
+
stream: createVertexLiveTranscriptionStream({
|
|
725
|
+
webSocket: this.config.webSocket,
|
|
726
|
+
url,
|
|
727
|
+
headers,
|
|
728
|
+
setup,
|
|
729
|
+
inputAudioRate: options.inputAudioFormat.rate ?? 16e3,
|
|
730
|
+
finishGraceMs: this.config._internal?.finishGraceMs ?? defaultFinishGraceMs,
|
|
731
|
+
warnings,
|
|
732
|
+
audio: options.audio,
|
|
733
|
+
abortSignal: options.abortSignal,
|
|
734
|
+
includeRawChunks: options.includeRawChunks
|
|
735
|
+
})
|
|
736
|
+
};
|
|
737
|
+
}
|
|
961
738
|
};
|
|
962
|
-
function createVertexLiveTranscriptionStream({
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
id: segmentId(),
|
|
1140
|
-
delta: transcription.text
|
|
1141
|
-
});
|
|
1142
|
-
}
|
|
1143
|
-
if (transcription.finished === true) {
|
|
1144
|
-
completeSegment();
|
|
1145
|
-
}
|
|
1146
|
-
}
|
|
1147
|
-
if (serverContent?.turnComplete) {
|
|
1148
|
-
completeSegment();
|
|
1149
|
-
}
|
|
1150
|
-
const interactionStatus = serverContent?.interactionStatus;
|
|
1151
|
-
if (audioEnded && (interactionStatus === "IDLE" || interactionStatus === "REQUIRES_ACTION" || serverContent?.turnComplete === true && interactionStatus == null)) {
|
|
1152
|
-
finish();
|
|
1153
|
-
}
|
|
1154
|
-
},
|
|
1155
|
-
onSocketError: () => {
|
|
1156
|
-
finishWithError(
|
|
1157
|
-
new Error(
|
|
1158
|
-
"Vertex Live transcription error." + (webSocket == null ? " Note: the native WebSocket implementation cannot send the Authorization header required by Vertex. Pass a header-capable WebSocket implementation (e.g. the 'ws' package) via createVertex({ webSocket })." : "")
|
|
1159
|
-
)
|
|
1160
|
-
);
|
|
1161
|
-
},
|
|
1162
|
-
onClose: ({ code, reason }) => {
|
|
1163
|
-
if (finished) return;
|
|
1164
|
-
if (audioEnded) {
|
|
1165
|
-
finish();
|
|
1166
|
-
return;
|
|
1167
|
-
}
|
|
1168
|
-
finishWithError(
|
|
1169
|
-
new Error(
|
|
1170
|
-
`Vertex Live transcription WebSocket closed unexpectedly before finishing (code ${code ?? "unknown"}${reason ? `, reason: ${reason}` : ""}).`
|
|
1171
|
-
)
|
|
1172
|
-
);
|
|
1173
|
-
}
|
|
1174
|
-
});
|
|
1175
|
-
},
|
|
1176
|
-
cancel: () => {
|
|
1177
|
-
if (finished) return;
|
|
1178
|
-
finished = true;
|
|
1179
|
-
cleanup();
|
|
1180
|
-
}
|
|
1181
|
-
});
|
|
739
|
+
function createVertexLiveTranscriptionStream({ webSocket, url, headers, setup, inputAudioRate, finishGraceMs, warnings, audio, abortSignal, includeRawChunks }) {
|
|
740
|
+
let finished = false;
|
|
741
|
+
let cleanup = () => {};
|
|
742
|
+
return new ReadableStream({
|
|
743
|
+
start: (controller) => {
|
|
744
|
+
let audioReader;
|
|
745
|
+
let connection;
|
|
746
|
+
let resolveSetupComplete;
|
|
747
|
+
const setupComplete = new Promise((resolvePromise) => {
|
|
748
|
+
resolveSetupComplete = resolvePromise;
|
|
749
|
+
});
|
|
750
|
+
let segmentCounter = 0;
|
|
751
|
+
let segmentBuffer = "";
|
|
752
|
+
let fullText = "";
|
|
753
|
+
let latestInterim = "";
|
|
754
|
+
let language;
|
|
755
|
+
let audioEnded = false;
|
|
756
|
+
let usageMetadata;
|
|
757
|
+
let finishTimer;
|
|
758
|
+
const segmentId = () => `google-segment-${segmentCounter}`;
|
|
759
|
+
const cancelPendingFinish = () => {
|
|
760
|
+
if (finishTimer != null) {
|
|
761
|
+
clearTimeout(finishTimer);
|
|
762
|
+
finishTimer = void 0;
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
const schedulePendingFinish = () => {
|
|
766
|
+
if (finished || !audioEnded) return;
|
|
767
|
+
cancelPendingFinish();
|
|
768
|
+
finishTimer = setTimeout(() => {
|
|
769
|
+
finishTimer = void 0;
|
|
770
|
+
finish();
|
|
771
|
+
}, finishGraceMs);
|
|
772
|
+
};
|
|
773
|
+
cleanup = (closeCode) => {
|
|
774
|
+
cancelPendingFinish();
|
|
775
|
+
if (audioReader != null) audioReader.cancel().catch(() => {});
|
|
776
|
+
else audio.cancel().catch(() => {});
|
|
777
|
+
connection?.close(closeCode);
|
|
778
|
+
};
|
|
779
|
+
const finishWithError = (error) => {
|
|
780
|
+
if (finished) return;
|
|
781
|
+
finished = true;
|
|
782
|
+
cleanup();
|
|
783
|
+
controller.error(error);
|
|
784
|
+
};
|
|
785
|
+
const completeSegment = () => {
|
|
786
|
+
if (segmentBuffer === "") {
|
|
787
|
+
if (latestInterim === "") return;
|
|
788
|
+
segmentBuffer = latestInterim;
|
|
789
|
+
}
|
|
790
|
+
latestInterim = "";
|
|
791
|
+
controller.enqueue({
|
|
792
|
+
type: "transcript-final",
|
|
793
|
+
id: segmentId(),
|
|
794
|
+
text: segmentBuffer
|
|
795
|
+
});
|
|
796
|
+
fullText += fullText === "" ? segmentBuffer : ` ${segmentBuffer}`;
|
|
797
|
+
segmentBuffer = "";
|
|
798
|
+
segmentCounter++;
|
|
799
|
+
};
|
|
800
|
+
const finish = () => {
|
|
801
|
+
if (finished) return;
|
|
802
|
+
completeSegment();
|
|
803
|
+
finished = true;
|
|
804
|
+
controller.enqueue({
|
|
805
|
+
type: "finish",
|
|
806
|
+
text: fullText,
|
|
807
|
+
segments: [],
|
|
808
|
+
language,
|
|
809
|
+
durationInSeconds: void 0,
|
|
810
|
+
...usageMetadata != null ? { providerMetadata: { google: { usageMetadata } } } : {}
|
|
811
|
+
});
|
|
812
|
+
controller.close();
|
|
813
|
+
cleanup(1e3);
|
|
814
|
+
};
|
|
815
|
+
const sendAudio = async (socket) => {
|
|
816
|
+
audioReader = audio.getReader();
|
|
817
|
+
try {
|
|
818
|
+
while (true) {
|
|
819
|
+
const { done, value } = await audioReader.read();
|
|
820
|
+
if (done || finished) break;
|
|
821
|
+
socket.send(JSON.stringify({ realtimeInput: { audio: {
|
|
822
|
+
data: convertToBase64(value),
|
|
823
|
+
mimeType: `audio/pcm;rate=${inputAudioRate}`
|
|
824
|
+
} } }));
|
|
825
|
+
await waitForWebSocketBufferDrain(socket);
|
|
826
|
+
}
|
|
827
|
+
} finally {
|
|
828
|
+
audioReader.releaseLock();
|
|
829
|
+
audioReader = void 0;
|
|
830
|
+
}
|
|
831
|
+
if (!finished) {
|
|
832
|
+
socket.send(JSON.stringify({ realtimeInput: { audioStreamEnd: true } }));
|
|
833
|
+
audioEnded = true;
|
|
834
|
+
schedulePendingFinish();
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
connection = connectToWebSocket({
|
|
838
|
+
url,
|
|
839
|
+
headers,
|
|
840
|
+
webSocket,
|
|
841
|
+
abortSignal,
|
|
842
|
+
onAbort: finishWithError,
|
|
843
|
+
onProcessingError: finishWithError,
|
|
844
|
+
onOpen: (socket) => {
|
|
845
|
+
controller.enqueue({
|
|
846
|
+
type: "stream-start",
|
|
847
|
+
warnings
|
|
848
|
+
});
|
|
849
|
+
socket.send(JSON.stringify({ setup }));
|
|
850
|
+
setupComplete.then(() => finished ? void 0 : sendAudio(socket)).catch(finishWithError);
|
|
851
|
+
},
|
|
852
|
+
onMessageText: async (text) => {
|
|
853
|
+
if (finished) return;
|
|
854
|
+
const parsed = await safeParseJSON({ text });
|
|
855
|
+
if (!parsed.success) return;
|
|
856
|
+
const message = parsed.value;
|
|
857
|
+
if (includeRawChunks) controller.enqueue({
|
|
858
|
+
type: "raw",
|
|
859
|
+
rawValue: message
|
|
860
|
+
});
|
|
861
|
+
if (message.setupComplete != null) resolveSetupComplete();
|
|
862
|
+
if (message.usageMetadata != null) usageMetadata = message.usageMetadata;
|
|
863
|
+
if (message.error != null) {
|
|
864
|
+
finishWithError(new Error(message.error.message ?? "Vertex Live API error"));
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
const serverContent = message.serverContent;
|
|
868
|
+
const interim = serverContent?.interimInputTranscription;
|
|
869
|
+
if (interim?.text) {
|
|
870
|
+
schedulePendingFinish();
|
|
871
|
+
latestInterim = interim.text;
|
|
872
|
+
controller.enqueue({
|
|
873
|
+
type: "transcript-partial",
|
|
874
|
+
id: segmentId(),
|
|
875
|
+
text: interim.text
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
const transcription = serverContent?.inputTranscription ?? message.inputTranscription;
|
|
879
|
+
if (transcription != null) {
|
|
880
|
+
if (transcription.languageCode != null) language = transcription.languageCode;
|
|
881
|
+
if (transcription.text) {
|
|
882
|
+
schedulePendingFinish();
|
|
883
|
+
latestInterim = "";
|
|
884
|
+
segmentBuffer += transcription.text;
|
|
885
|
+
controller.enqueue({
|
|
886
|
+
type: "transcript-delta",
|
|
887
|
+
id: segmentId(),
|
|
888
|
+
delta: transcription.text
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
if (transcription.finished === true) completeSegment();
|
|
892
|
+
}
|
|
893
|
+
if (serverContent?.turnComplete) completeSegment();
|
|
894
|
+
const interactionStatus = serverContent?.interactionStatus;
|
|
895
|
+
if (audioEnded && (interactionStatus === "IDLE" || interactionStatus === "REQUIRES_ACTION" || serverContent?.turnComplete === true && interactionStatus == null)) finish();
|
|
896
|
+
},
|
|
897
|
+
onSocketError: () => {
|
|
898
|
+
finishWithError(/* @__PURE__ */ new Error("Vertex Live transcription error." + (webSocket == null ? " Note: the native WebSocket implementation cannot send the Authorization header required by Vertex. Pass a header-capable WebSocket implementation (e.g. the 'ws' package) via createVertex({ webSocket })." : "")));
|
|
899
|
+
},
|
|
900
|
+
onClose: ({ code, reason }) => {
|
|
901
|
+
if (finished) return;
|
|
902
|
+
if (audioEnded) {
|
|
903
|
+
finish();
|
|
904
|
+
return;
|
|
905
|
+
}
|
|
906
|
+
finishWithError(/* @__PURE__ */ new Error(`Vertex Live transcription WebSocket closed unexpectedly before finishing (code ${code ?? "unknown"}${reason ? `, reason: ${reason}` : ""}).`));
|
|
907
|
+
}
|
|
908
|
+
});
|
|
909
|
+
},
|
|
910
|
+
cancel: () => {
|
|
911
|
+
if (finished) return;
|
|
912
|
+
finished = true;
|
|
913
|
+
cleanup();
|
|
914
|
+
}
|
|
915
|
+
});
|
|
1182
916
|
}
|
|
917
|
+
/**
|
|
918
|
+
* Builds Google's `AudioTranscriptionConfig` from provider options; returns
|
|
919
|
+
* undefined when no options are set.
|
|
920
|
+
*/
|
|
1183
921
|
function buildAudioTranscriptionConfig(options) {
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
if (options.wordTimestamp != null) {
|
|
1193
|
-
config.wordTimestamp = options.wordTimestamp;
|
|
1194
|
-
}
|
|
1195
|
-
if (options.diarization != null) {
|
|
1196
|
-
config.diarization = options.diarization;
|
|
1197
|
-
}
|
|
1198
|
-
if (options.mode != null) {
|
|
1199
|
-
config.mode = options.mode;
|
|
1200
|
-
}
|
|
1201
|
-
return Object.keys(config).length > 0 ? config : void 0;
|
|
922
|
+
if (options == null) return void 0;
|
|
923
|
+
const config = {};
|
|
924
|
+
if (options.languageCodes != null) config.languageCodes = options.languageCodes;
|
|
925
|
+
if (options.customVocabulary != null) config.customVocabulary = options.customVocabulary;
|
|
926
|
+
if (options.wordTimestamp != null) config.wordTimestamp = options.wordTimestamp;
|
|
927
|
+
if (options.diarization != null) config.diarization = options.diarization;
|
|
928
|
+
if (options.mode != null) config.mode = options.mode;
|
|
929
|
+
return Object.keys(config).length > 0 ? config : void 0;
|
|
1202
930
|
}
|
|
1203
931
|
function validateLiveInputAudioFormat(inputAudioFormat) {
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
});
|
|
1209
|
-
}
|
|
932
|
+
if (inputAudioFormat.type !== "audio/pcm" || inputAudioFormat.rate != null && inputAudioFormat.rate !== 16e3) throw new InvalidArgumentError({
|
|
933
|
+
argument: "inputAudioFormat",
|
|
934
|
+
message: "The Gemini Live transcription API only supports 16kHz 16-bit PCM input audio."
|
|
935
|
+
});
|
|
1210
936
|
}
|
|
937
|
+
/** Parses a Google duration offset such as `"1s"` or `"9.400s"` to seconds. */
|
|
1211
938
|
function parseOffsetSeconds(offset) {
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
939
|
+
if (offset == null) return void 0;
|
|
940
|
+
const parsed = Number.parseFloat(offset);
|
|
941
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
1215
942
|
}
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
943
|
+
const googleVertexGeminiTranscriptionWordSchema = z.object({
|
|
944
|
+
word: z.string().nullish(),
|
|
945
|
+
startOffset: z.string().nullish(),
|
|
946
|
+
endOffset: z.string().nullish()
|
|
1220
947
|
});
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
words: z8.array(googleVertexGeminiTranscriptionWordSchema).nullish()
|
|
1233
|
-
}).nullish()
|
|
1234
|
-
})
|
|
1235
|
-
).nullish()
|
|
1236
|
-
}).nullish()
|
|
1237
|
-
})
|
|
1238
|
-
).nullish(),
|
|
1239
|
-
usageMetadata: z8.record(z8.string(), z8.unknown()).nullish()
|
|
948
|
+
const googleVertexGeminiTranscriptionResponseSchema = z.object({
|
|
949
|
+
candidates: z.array(z.object({ content: z.object({ parts: z.array(z.object({
|
|
950
|
+
text: z.string().nullish(),
|
|
951
|
+
audioTranscription: z.object({
|
|
952
|
+
text: z.string().nullish(),
|
|
953
|
+
languageCode: z.string().nullish(),
|
|
954
|
+
speakerLabel: z.string().nullish(),
|
|
955
|
+
words: z.array(googleVertexGeminiTranscriptionWordSchema).nullish()
|
|
956
|
+
}).nullish()
|
|
957
|
+
})).nullish() }).nullish() })).nullish(),
|
|
958
|
+
usageMetadata: z.record(z.string(), z.unknown()).nullish()
|
|
1240
959
|
});
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
z9.looseObject({
|
|
1262
|
-
pollIntervalMs: z9.number().positive().nullish(),
|
|
1263
|
-
pollTimeoutMs: z9.number().positive().nullish(),
|
|
1264
|
-
personGeneration: z9.enum(["dont_allow", "allow_adult", "allow_all"]).nullish(),
|
|
1265
|
-
negativePrompt: z9.string().nullish(),
|
|
1266
|
-
generateAudio: z9.boolean().nullish(),
|
|
1267
|
-
gcsOutputDirectory: z9.string().nullish(),
|
|
1268
|
-
referenceImages: z9.array(
|
|
1269
|
-
z9.object({
|
|
1270
|
-
bytesBase64Encoded: z9.string().nullish(),
|
|
1271
|
-
gcsUri: z9.string().nullish()
|
|
1272
|
-
})
|
|
1273
|
-
).nullish()
|
|
1274
|
-
})
|
|
1275
|
-
)
|
|
1276
|
-
);
|
|
1277
|
-
|
|
1278
|
-
// src/google-vertex-video-model.ts
|
|
960
|
+
//#endregion
|
|
961
|
+
//#region src/google-vertex-video-model-options.ts
|
|
962
|
+
const googleVertexVideoModelOptionsSchema = lazySchema(() => zodSchema(z.looseObject({
|
|
963
|
+
pollIntervalMs: z.number().positive().nullish(),
|
|
964
|
+
pollTimeoutMs: z.number().positive().nullish(),
|
|
965
|
+
personGeneration: z.enum([
|
|
966
|
+
"dont_allow",
|
|
967
|
+
"allow_adult",
|
|
968
|
+
"allow_all"
|
|
969
|
+
]).nullish(),
|
|
970
|
+
negativePrompt: z.string().nullish(),
|
|
971
|
+
generateAudio: z.boolean().nullish(),
|
|
972
|
+
gcsOutputDirectory: z.string().nullish(),
|
|
973
|
+
referenceImages: z.array(z.object({
|
|
974
|
+
bytesBase64Encoded: z.string().nullish(),
|
|
975
|
+
gcsUri: z.string().nullish()
|
|
976
|
+
})).nullish()
|
|
977
|
+
})));
|
|
978
|
+
//#endregion
|
|
979
|
+
//#region src/google-vertex-video-model.ts
|
|
1279
980
|
function getFirstFrameImage(options) {
|
|
1280
|
-
|
|
981
|
+
return options.frameImages?.find((frame) => frame.frameType === "first_frame")?.image;
|
|
1281
982
|
}
|
|
1282
983
|
function resolveStartImage(options) {
|
|
1283
|
-
|
|
984
|
+
return getFirstFrameImage(options) ?? options.image;
|
|
1284
985
|
}
|
|
1285
986
|
function getLastFrameImage(options) {
|
|
1286
|
-
|
|
987
|
+
return options.frameImages?.find((frame) => frame.frameType === "last_frame")?.image;
|
|
1287
988
|
}
|
|
1288
989
|
function getInputReferences(options) {
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
}
|
|
1292
|
-
return options.inputReferences != null && options.inputReferences.length > 0 ? options.inputReferences : void 0;
|
|
990
|
+
if (options.frameImages != null && options.frameImages.length > 0) return;
|
|
991
|
+
return options.inputReferences != null && options.inputReferences.length > 0 ? options.inputReferences : void 0;
|
|
1293
992
|
}
|
|
1294
993
|
function convertFileToVertexImage(file, warnings) {
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
bytesBase64Encoded: base64Data,
|
|
1312
|
-
mimeType: file.mediaType || "image/png"
|
|
1313
|
-
};
|
|
994
|
+
if (file.type === "url") {
|
|
995
|
+
if (file.url.startsWith("gs://")) return {
|
|
996
|
+
gcsUri: file.url,
|
|
997
|
+
mimeType: "image/png"
|
|
998
|
+
};
|
|
999
|
+
warnings.push({
|
|
1000
|
+
type: "unsupported",
|
|
1001
|
+
feature: "URL-based image input",
|
|
1002
|
+
details: "Vertex AI video models require base64-encoded images or GCS URIs. URL will be ignored."
|
|
1003
|
+
});
|
|
1004
|
+
return;
|
|
1005
|
+
}
|
|
1006
|
+
return {
|
|
1007
|
+
bytesBase64Encoded: typeof file.data === "string" ? file.data : convertUint8ArrayToBase64(file.data),
|
|
1008
|
+
mimeType: file.mediaType || "image/png"
|
|
1009
|
+
};
|
|
1314
1010
|
}
|
|
1315
1011
|
function convertInputReferenceImage(file, warnings) {
|
|
1316
|
-
|
|
1317
|
-
|
|
1012
|
+
const image = convertFileToVertexImage(file, warnings);
|
|
1013
|
+
return image != null ? {
|
|
1014
|
+
image,
|
|
1015
|
+
referenceType: "asset"
|
|
1016
|
+
} : void 0;
|
|
1318
1017
|
}
|
|
1319
1018
|
var GoogleVertexVideoModel = class {
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
});
|
|
1510
|
-
}
|
|
1511
|
-
return {
|
|
1512
|
-
operation: { operationName },
|
|
1513
|
-
warnings,
|
|
1514
|
-
response: {
|
|
1515
|
-
timestamp: currentDate,
|
|
1516
|
-
modelId: this.modelId,
|
|
1517
|
-
headers: responseHeaders
|
|
1518
|
-
}
|
|
1519
|
-
};
|
|
1520
|
-
}
|
|
1521
|
-
async doStatus(options) {
|
|
1522
|
-
const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
|
|
1523
|
-
const { operationName } = options.operation;
|
|
1524
|
-
const { value: statusOperation, responseHeaders } = await postJsonToApi5({
|
|
1525
|
-
url: `${this.config.baseURL}/models/${this.modelId}:fetchPredictOperation`,
|
|
1526
|
-
headers: combineHeaders5(
|
|
1527
|
-
await resolve5(this.config.headers),
|
|
1528
|
-
options.headers
|
|
1529
|
-
),
|
|
1530
|
-
body: {
|
|
1531
|
-
operationName
|
|
1532
|
-
},
|
|
1533
|
-
successfulResponseHandler: createJsonResponseHandler5(
|
|
1534
|
-
googleVertexOperationSchema
|
|
1535
|
-
),
|
|
1536
|
-
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
1537
|
-
abortSignal: options.abortSignal,
|
|
1538
|
-
fetch: this.config.fetch
|
|
1539
|
-
});
|
|
1540
|
-
if (!statusOperation.done) {
|
|
1541
|
-
return {
|
|
1542
|
-
status: "pending",
|
|
1543
|
-
response: {
|
|
1544
|
-
timestamp: currentDate,
|
|
1545
|
-
modelId: this.modelId,
|
|
1546
|
-
headers: responseHeaders
|
|
1547
|
-
}
|
|
1548
|
-
};
|
|
1549
|
-
}
|
|
1550
|
-
if (statusOperation.error) {
|
|
1551
|
-
return {
|
|
1552
|
-
status: "error",
|
|
1553
|
-
error: `Video generation failed: ${statusOperation.error.message}`,
|
|
1554
|
-
response: {
|
|
1555
|
-
timestamp: currentDate,
|
|
1556
|
-
modelId: this.modelId,
|
|
1557
|
-
headers: responseHeaders
|
|
1558
|
-
}
|
|
1559
|
-
};
|
|
1560
|
-
}
|
|
1561
|
-
return this.buildCompletedResult({
|
|
1562
|
-
finalOperation: statusOperation,
|
|
1563
|
-
responseHeaders,
|
|
1564
|
-
warnings: [],
|
|
1565
|
-
currentDate
|
|
1566
|
-
});
|
|
1567
|
-
}
|
|
1019
|
+
get provider() {
|
|
1020
|
+
return this.config.provider;
|
|
1021
|
+
}
|
|
1022
|
+
get maxVideosPerCall() {
|
|
1023
|
+
return 4;
|
|
1024
|
+
}
|
|
1025
|
+
constructor(modelId, config) {
|
|
1026
|
+
this.modelId = modelId;
|
|
1027
|
+
this.config = config;
|
|
1028
|
+
this.specificationVersion = "v4";
|
|
1029
|
+
}
|
|
1030
|
+
async buildRequest(options) {
|
|
1031
|
+
const warnings = [];
|
|
1032
|
+
const googleVertexOptions = await parseProviderOptions({
|
|
1033
|
+
provider: "googleVertex",
|
|
1034
|
+
providerOptions: options.providerOptions,
|
|
1035
|
+
schema: googleVertexVideoModelOptionsSchema
|
|
1036
|
+
}) ?? await parseProviderOptions({
|
|
1037
|
+
provider: "vertex",
|
|
1038
|
+
providerOptions: options.providerOptions,
|
|
1039
|
+
schema: googleVertexVideoModelOptionsSchema
|
|
1040
|
+
});
|
|
1041
|
+
const instances = [{}];
|
|
1042
|
+
const instance = instances[0];
|
|
1043
|
+
if (options.prompt != null) instance.prompt = options.prompt;
|
|
1044
|
+
const startImage = resolveStartImage(options);
|
|
1045
|
+
if (startImage != null) {
|
|
1046
|
+
const image = convertFileToVertexImage(startImage, warnings);
|
|
1047
|
+
if (image != null) instance.image = image;
|
|
1048
|
+
}
|
|
1049
|
+
const lastFrameImage = getLastFrameImage(options);
|
|
1050
|
+
if (lastFrameImage != null) {
|
|
1051
|
+
const lastFrame = convertFileToVertexImage(lastFrameImage, warnings);
|
|
1052
|
+
if (lastFrame != null) instance.lastFrame = lastFrame;
|
|
1053
|
+
}
|
|
1054
|
+
const inputReferences = getInputReferences(options);
|
|
1055
|
+
if (inputReferences != null) instance.referenceImages = inputReferences.flatMap((reference) => {
|
|
1056
|
+
const converted = convertInputReferenceImage(reference, warnings);
|
|
1057
|
+
return converted != null ? [converted] : [];
|
|
1058
|
+
});
|
|
1059
|
+
else if (googleVertexOptions?.referenceImages != null) instance.referenceImages = googleVertexOptions.referenceImages;
|
|
1060
|
+
const parameters = { sampleCount: options.n };
|
|
1061
|
+
if (options.aspectRatio) parameters.aspectRatio = options.aspectRatio;
|
|
1062
|
+
if (options.resolution) parameters.resolution = {
|
|
1063
|
+
"1280x720": "720p",
|
|
1064
|
+
"1920x1080": "1080p",
|
|
1065
|
+
"3840x2160": "4k"
|
|
1066
|
+
}[options.resolution] || options.resolution;
|
|
1067
|
+
if (options.duration) parameters.durationSeconds = options.duration;
|
|
1068
|
+
if (options.seed) parameters.seed = options.seed;
|
|
1069
|
+
const generateAudio = options.generateAudio ?? googleVertexOptions?.generateAudio;
|
|
1070
|
+
if (generateAudio != null) parameters.generateAudio = generateAudio;
|
|
1071
|
+
if (googleVertexOptions != null) {
|
|
1072
|
+
const opts = googleVertexOptions;
|
|
1073
|
+
if (opts.personGeneration !== void 0 && opts.personGeneration !== null) parameters.personGeneration = opts.personGeneration;
|
|
1074
|
+
if (opts.negativePrompt !== void 0 && opts.negativePrompt !== null) parameters.negativePrompt = opts.negativePrompt;
|
|
1075
|
+
if (opts.gcsOutputDirectory !== void 0 && opts.gcsOutputDirectory !== null) parameters.gcsOutputDirectory = opts.gcsOutputDirectory;
|
|
1076
|
+
for (const [key, value] of Object.entries(opts)) if (![
|
|
1077
|
+
"pollIntervalMs",
|
|
1078
|
+
"pollTimeoutMs",
|
|
1079
|
+
"personGeneration",
|
|
1080
|
+
"negativePrompt",
|
|
1081
|
+
"generateAudio",
|
|
1082
|
+
"gcsOutputDirectory",
|
|
1083
|
+
"referenceImages"
|
|
1084
|
+
].includes(key)) parameters[key] = value;
|
|
1085
|
+
}
|
|
1086
|
+
return {
|
|
1087
|
+
instances,
|
|
1088
|
+
parameters,
|
|
1089
|
+
warnings,
|
|
1090
|
+
googleVertexOptions
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
buildCompletedResult({ finalOperation, responseHeaders, warnings, currentDate }) {
|
|
1094
|
+
const response = finalOperation.response;
|
|
1095
|
+
if (!response?.videos || response.videos.length === 0) throw new AISDKError({
|
|
1096
|
+
name: "VERTEX_VIDEO_GENERATION_ERROR",
|
|
1097
|
+
message: `No videos in response. Response: ${JSON.stringify(finalOperation)}`
|
|
1098
|
+
});
|
|
1099
|
+
const videos = [];
|
|
1100
|
+
const videoMetadata = [];
|
|
1101
|
+
for (const video of response.videos) if (video.bytesBase64Encoded) {
|
|
1102
|
+
videos.push({
|
|
1103
|
+
type: "base64",
|
|
1104
|
+
data: video.bytesBase64Encoded,
|
|
1105
|
+
mediaType: video.mimeType || "video/mp4"
|
|
1106
|
+
});
|
|
1107
|
+
videoMetadata.push({ mimeType: video.mimeType });
|
|
1108
|
+
} else if (video.gcsUri) {
|
|
1109
|
+
videos.push({
|
|
1110
|
+
type: "url",
|
|
1111
|
+
url: video.gcsUri,
|
|
1112
|
+
mediaType: video.mimeType || "video/mp4"
|
|
1113
|
+
});
|
|
1114
|
+
videoMetadata.push({
|
|
1115
|
+
gcsUri: video.gcsUri,
|
|
1116
|
+
mimeType: video.mimeType
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
if (videos.length === 0) throw new AISDKError({
|
|
1120
|
+
name: "VERTEX_VIDEO_GENERATION_ERROR",
|
|
1121
|
+
message: "No valid videos in response"
|
|
1122
|
+
});
|
|
1123
|
+
return {
|
|
1124
|
+
status: "completed",
|
|
1125
|
+
videos,
|
|
1126
|
+
warnings,
|
|
1127
|
+
response: {
|
|
1128
|
+
timestamp: currentDate,
|
|
1129
|
+
modelId: this.modelId,
|
|
1130
|
+
headers: responseHeaders
|
|
1131
|
+
},
|
|
1132
|
+
providerMetadata: (() => {
|
|
1133
|
+
const payload = { videos: videoMetadata };
|
|
1134
|
+
return {
|
|
1135
|
+
googleVertex: payload,
|
|
1136
|
+
"google-vertex": payload,
|
|
1137
|
+
vertex: payload
|
|
1138
|
+
};
|
|
1139
|
+
})()
|
|
1140
|
+
};
|
|
1141
|
+
}
|
|
1142
|
+
async doStart(options) {
|
|
1143
|
+
const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
|
|
1144
|
+
const { instances, parameters, warnings } = await this.buildRequest(options);
|
|
1145
|
+
const { value: operation, responseHeaders } = await postJsonToApi({
|
|
1146
|
+
url: `${this.config.baseURL}/models/${this.modelId}:predictLongRunning`,
|
|
1147
|
+
headers: combineHeaders(await resolve(this.config.headers), options.headers),
|
|
1148
|
+
body: {
|
|
1149
|
+
instances,
|
|
1150
|
+
parameters
|
|
1151
|
+
},
|
|
1152
|
+
successfulResponseHandler: createJsonResponseHandler(googleVertexOperationSchema),
|
|
1153
|
+
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
1154
|
+
abortSignal: options.abortSignal,
|
|
1155
|
+
fetch: this.config.fetch
|
|
1156
|
+
});
|
|
1157
|
+
const operationName = operation.name;
|
|
1158
|
+
if (!operationName) throw new AISDKError({
|
|
1159
|
+
name: "VERTEX_VIDEO_GENERATION_ERROR",
|
|
1160
|
+
message: "No operation name returned from API"
|
|
1161
|
+
});
|
|
1162
|
+
return {
|
|
1163
|
+
operation: { operationName },
|
|
1164
|
+
warnings,
|
|
1165
|
+
response: {
|
|
1166
|
+
timestamp: currentDate,
|
|
1167
|
+
modelId: this.modelId,
|
|
1168
|
+
headers: responseHeaders
|
|
1169
|
+
}
|
|
1170
|
+
};
|
|
1171
|
+
}
|
|
1172
|
+
async doStatus(options) {
|
|
1173
|
+
const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
|
|
1174
|
+
const { operationName } = options.operation;
|
|
1175
|
+
const { value: statusOperation, responseHeaders } = await postJsonToApi({
|
|
1176
|
+
url: `${this.config.baseURL}/models/${this.modelId}:fetchPredictOperation`,
|
|
1177
|
+
headers: combineHeaders(await resolve(this.config.headers), options.headers),
|
|
1178
|
+
body: { operationName },
|
|
1179
|
+
successfulResponseHandler: createJsonResponseHandler(googleVertexOperationSchema),
|
|
1180
|
+
failedResponseHandler: googleVertexFailedResponseHandler,
|
|
1181
|
+
abortSignal: options.abortSignal,
|
|
1182
|
+
fetch: this.config.fetch
|
|
1183
|
+
});
|
|
1184
|
+
if (!statusOperation.done) return {
|
|
1185
|
+
status: "pending",
|
|
1186
|
+
response: {
|
|
1187
|
+
timestamp: currentDate,
|
|
1188
|
+
modelId: this.modelId,
|
|
1189
|
+
headers: responseHeaders
|
|
1190
|
+
}
|
|
1191
|
+
};
|
|
1192
|
+
if (statusOperation.error) return {
|
|
1193
|
+
status: "error",
|
|
1194
|
+
error: `Video generation failed: ${statusOperation.error.message}`,
|
|
1195
|
+
response: {
|
|
1196
|
+
timestamp: currentDate,
|
|
1197
|
+
modelId: this.modelId,
|
|
1198
|
+
headers: responseHeaders
|
|
1199
|
+
}
|
|
1200
|
+
};
|
|
1201
|
+
return this.buildCompletedResult({
|
|
1202
|
+
finalOperation: statusOperation,
|
|
1203
|
+
responseHeaders,
|
|
1204
|
+
warnings: [],
|
|
1205
|
+
currentDate
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
1568
1208
|
};
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
raiMediaFilteredCount: z10.number().nullish()
|
|
1586
|
-
}).nullish()
|
|
1209
|
+
const googleVertexOperationSchema = z.object({
|
|
1210
|
+
name: z.string().nullish(),
|
|
1211
|
+
done: z.boolean().nullish(),
|
|
1212
|
+
error: z.object({
|
|
1213
|
+
code: z.number().nullish(),
|
|
1214
|
+
message: z.string(),
|
|
1215
|
+
status: z.string().nullish()
|
|
1216
|
+
}).nullish(),
|
|
1217
|
+
response: z.object({
|
|
1218
|
+
videos: z.array(z.object({
|
|
1219
|
+
bytesBase64Encoded: z.string().nullish(),
|
|
1220
|
+
gcsUri: z.string().nullish(),
|
|
1221
|
+
mimeType: z.string().nullish()
|
|
1222
|
+
})).nullish(),
|
|
1223
|
+
raiMediaFilteredCount: z.number().nullish()
|
|
1224
|
+
}).nullish()
|
|
1587
1225
|
});
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1226
|
+
//#endregion
|
|
1227
|
+
//#region src/google-vertex-provider-base.ts
|
|
1228
|
+
const EXPRESS_MODE_BASE_URL = "https://aiplatform.googleapis.com/v1/publishers/google";
|
|
1229
|
+
const ENDPOINT_MODEL_PREFIX = "endpoints/";
|
|
1592
1230
|
function isEndpointModelId(modelId) {
|
|
1593
|
-
|
|
1231
|
+
return modelId.startsWith(ENDPOINT_MODEL_PREFIX);
|
|
1594
1232
|
}
|
|
1595
1233
|
function createExpressModeFetch(apiKey, customFetch) {
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1234
|
+
return async (url, init) => {
|
|
1235
|
+
const modifiedInit = {
|
|
1236
|
+
...init,
|
|
1237
|
+
headers: {
|
|
1238
|
+
...init?.headers ? normalizeHeaders(init.headers) : {},
|
|
1239
|
+
"x-goog-api-key": apiKey
|
|
1240
|
+
}
|
|
1241
|
+
};
|
|
1242
|
+
return (customFetch ?? fetch)(url.toString(), modifiedInit);
|
|
1243
|
+
};
|
|
1606
1244
|
}
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
if (modelId.startsWith("gemini")) {
|
|
1731
|
-
return new GoogleVertexGeminiTranscriptionModel(modelId, {
|
|
1732
|
-
provider: config.provider,
|
|
1733
|
-
baseURL: loadBaseURL(),
|
|
1734
|
-
headers: config.headers,
|
|
1735
|
-
fetch: config.fetch,
|
|
1736
|
-
webSocket: options.webSocket,
|
|
1737
|
-
project: loadGoogleVertexProject(),
|
|
1738
|
-
location: loadGoogleVertexLocation()
|
|
1739
|
-
});
|
|
1740
|
-
}
|
|
1741
|
-
return new GoogleVertexTranscriptionModel(modelId, {
|
|
1742
|
-
provider: config.provider,
|
|
1743
|
-
headers: config.headers,
|
|
1744
|
-
fetch: config.fetch,
|
|
1745
|
-
project: loadGoogleVertexProject(),
|
|
1746
|
-
location: loadGoogleVertexLocation()
|
|
1747
|
-
});
|
|
1748
|
-
};
|
|
1749
|
-
const provider = function(modelId) {
|
|
1750
|
-
if (new.target) {
|
|
1751
|
-
throw new Error(
|
|
1752
|
-
"The Google Vertex AI model function cannot be called with the new keyword."
|
|
1753
|
-
);
|
|
1754
|
-
}
|
|
1755
|
-
return createChatModel(modelId);
|
|
1756
|
-
};
|
|
1757
|
-
provider.specificationVersion = "v4";
|
|
1758
|
-
provider.languageModel = createChatModel;
|
|
1759
|
-
provider.interactions = createInteractionsModel;
|
|
1760
|
-
provider.embeddingModel = createEmbeddingModel;
|
|
1761
|
-
provider.textEmbeddingModel = createEmbeddingModel;
|
|
1762
|
-
provider.image = createImageModel;
|
|
1763
|
-
provider.imageModel = createImageModel;
|
|
1764
|
-
provider.video = createVideoModel;
|
|
1765
|
-
provider.videoModel = createVideoModel;
|
|
1766
|
-
provider.speech = createSpeechModel;
|
|
1767
|
-
provider.speechModel = createSpeechModel;
|
|
1768
|
-
provider.transcription = createTranscriptionModel;
|
|
1769
|
-
provider.transcriptionModel = createTranscriptionModel;
|
|
1770
|
-
provider.tools = googleVertexTools;
|
|
1771
|
-
return provider;
|
|
1245
|
+
/**
|
|
1246
|
+
* Create a Google Vertex AI provider instance.
|
|
1247
|
+
*/
|
|
1248
|
+
function createGoogleVertex$1(options = {}) {
|
|
1249
|
+
const apiKey = loadOptionalSetting({
|
|
1250
|
+
settingValue: options.apiKey,
|
|
1251
|
+
environmentVariableName: "GOOGLE_VERTEX_API_KEY"
|
|
1252
|
+
});
|
|
1253
|
+
const loadGoogleVertexProject = () => loadSetting({
|
|
1254
|
+
settingValue: options.project,
|
|
1255
|
+
settingName: "project",
|
|
1256
|
+
environmentVariableName: "GOOGLE_VERTEX_PROJECT",
|
|
1257
|
+
description: "Google Vertex project"
|
|
1258
|
+
});
|
|
1259
|
+
const loadGoogleVertexLocation = () => loadSetting({
|
|
1260
|
+
settingValue: options.location,
|
|
1261
|
+
settingName: "location",
|
|
1262
|
+
environmentVariableName: "GOOGLE_VERTEX_LOCATION",
|
|
1263
|
+
description: "Google Vertex location"
|
|
1264
|
+
});
|
|
1265
|
+
const loadBaseURL = ({ endpoint = false } = {}) => {
|
|
1266
|
+
if (apiKey) return withoutTrailingSlash(options.baseURL) ?? EXPRESS_MODE_BASE_URL;
|
|
1267
|
+
const region = loadGoogleVertexLocation();
|
|
1268
|
+
const project = loadGoogleVertexProject();
|
|
1269
|
+
const getHost = () => {
|
|
1270
|
+
if (region === "global") return "aiplatform.googleapis.com";
|
|
1271
|
+
else if (region === "eu" || region === "us") return `aiplatform.${region}.rep.googleapis.com`;
|
|
1272
|
+
else return `${region}-aiplatform.googleapis.com`;
|
|
1273
|
+
};
|
|
1274
|
+
return withoutTrailingSlash(options.baseURL) ?? `https://${getHost()}/v1beta1/projects/${project}/locations/${region}${endpoint ? "" : "/publishers/google"}`;
|
|
1275
|
+
};
|
|
1276
|
+
const createConfig = (name, { endpoint = false } = {}) => {
|
|
1277
|
+
const getHeaders = async () => {
|
|
1278
|
+
const originalHeaders = await resolve(options.headers ?? {});
|
|
1279
|
+
return withUserAgentSuffix(originalHeaders, `ai-sdk-google-vertex/${VERSION}`);
|
|
1280
|
+
};
|
|
1281
|
+
return {
|
|
1282
|
+
provider: `google.vertex.${name}`,
|
|
1283
|
+
headers: getHeaders,
|
|
1284
|
+
fetch: apiKey ? createExpressModeFetch(apiKey, options.fetch) : options.fetch,
|
|
1285
|
+
baseURL: loadBaseURL({ endpoint })
|
|
1286
|
+
};
|
|
1287
|
+
};
|
|
1288
|
+
const createChatModel = (modelId) => {
|
|
1289
|
+
const endpoint = isEndpointModelId(modelId);
|
|
1290
|
+
if (endpoint && apiKey) throw new Error("Google Vertex tuned models do not support Express Mode API keys. Use standard Google Cloud credentials instead.");
|
|
1291
|
+
return new GoogleLanguageModel(modelId, {
|
|
1292
|
+
...createConfig("chat", { endpoint }),
|
|
1293
|
+
generateId: options.generateId ?? generateId,
|
|
1294
|
+
supportedUrls: () => ({ "*": [/^https?:\/\/.*$/, /^gs:\/\/.*$/] }),
|
|
1295
|
+
downloadToolResultFiles: {
|
|
1296
|
+
maxBytes: options.toolResultDownloads?.maxBytes ?? 7340032,
|
|
1297
|
+
supportsGoogleCloudStorageUrls: true
|
|
1298
|
+
}
|
|
1299
|
+
});
|
|
1300
|
+
};
|
|
1301
|
+
const createInteractionsModel = (modelIdOrAgent) => {
|
|
1302
|
+
if (apiKey) throw new Error("Google Vertex Interactions models do not support Express Mode API keys. Use standard Google Cloud credentials instead.");
|
|
1303
|
+
return new GoogleInteractionsLanguageModel(modelIdOrAgent, {
|
|
1304
|
+
...createConfig("interactions", { endpoint: true }),
|
|
1305
|
+
generateId: options.generateId ?? generateId
|
|
1306
|
+
});
|
|
1307
|
+
};
|
|
1308
|
+
const createEmbeddingModel = (modelId) => new GoogleVertexEmbeddingModel(modelId, createConfig("embedding"));
|
|
1309
|
+
const createImageModel = (modelId) => new GoogleVertexImageModel(modelId, {
|
|
1310
|
+
...createConfig("image"),
|
|
1311
|
+
generateId: options.generateId ?? generateId
|
|
1312
|
+
});
|
|
1313
|
+
const createVideoModel = (modelId) => new GoogleVertexVideoModel(modelId, {
|
|
1314
|
+
...createConfig("video"),
|
|
1315
|
+
generateId: options.generateId ?? generateId
|
|
1316
|
+
});
|
|
1317
|
+
const createSpeechModel = (modelId) => {
|
|
1318
|
+
if (modelId.startsWith("chirp")) {
|
|
1319
|
+
if (apiKey) throw new Error("Google Vertex Chirp speech models do not support Express Mode API keys. Use standard Google Cloud credentials instead.");
|
|
1320
|
+
const config = createConfig("speech");
|
|
1321
|
+
return new GoogleVertexCloudTTSSpeechModel(modelId, {
|
|
1322
|
+
provider: config.provider,
|
|
1323
|
+
headers: config.headers,
|
|
1324
|
+
fetch: config.fetch
|
|
1325
|
+
});
|
|
1326
|
+
}
|
|
1327
|
+
return new GoogleSpeechModel(modelId, createConfig("speech"));
|
|
1328
|
+
};
|
|
1329
|
+
const createTranscriptionModel = (modelId) => {
|
|
1330
|
+
if (apiKey) throw new Error("Google Vertex transcription models do not support Express Mode API keys. Use standard Google Cloud credentials instead.");
|
|
1331
|
+
const config = createConfig("transcription");
|
|
1332
|
+
if (modelId.startsWith("gemini")) return new GoogleVertexGeminiTranscriptionModel(modelId, {
|
|
1333
|
+
provider: config.provider,
|
|
1334
|
+
baseURL: loadBaseURL(),
|
|
1335
|
+
headers: config.headers,
|
|
1336
|
+
fetch: config.fetch,
|
|
1337
|
+
webSocket: options.webSocket,
|
|
1338
|
+
project: loadGoogleVertexProject(),
|
|
1339
|
+
location: loadGoogleVertexLocation()
|
|
1340
|
+
});
|
|
1341
|
+
return new GoogleVertexTranscriptionModel(modelId, {
|
|
1342
|
+
provider: config.provider,
|
|
1343
|
+
headers: config.headers,
|
|
1344
|
+
fetch: config.fetch,
|
|
1345
|
+
project: loadGoogleVertexProject(),
|
|
1346
|
+
location: loadGoogleVertexLocation()
|
|
1347
|
+
});
|
|
1348
|
+
};
|
|
1349
|
+
const provider = function(modelId) {
|
|
1350
|
+
if (new.target) throw new Error("The Google Vertex AI model function cannot be called with the new keyword.");
|
|
1351
|
+
return createChatModel(modelId);
|
|
1352
|
+
};
|
|
1353
|
+
provider.specificationVersion = "v4";
|
|
1354
|
+
provider.languageModel = createChatModel;
|
|
1355
|
+
provider.interactions = createInteractionsModel;
|
|
1356
|
+
provider.embeddingModel = createEmbeddingModel;
|
|
1357
|
+
provider.textEmbeddingModel = createEmbeddingModel;
|
|
1358
|
+
provider.image = createImageModel;
|
|
1359
|
+
provider.imageModel = createImageModel;
|
|
1360
|
+
provider.video = createVideoModel;
|
|
1361
|
+
provider.videoModel = createVideoModel;
|
|
1362
|
+
provider.speech = createSpeechModel;
|
|
1363
|
+
provider.speechModel = createSpeechModel;
|
|
1364
|
+
provider.transcription = createTranscriptionModel;
|
|
1365
|
+
provider.transcriptionModel = createTranscriptionModel;
|
|
1366
|
+
provider.tools = googleVertexTools;
|
|
1367
|
+
return provider;
|
|
1772
1368
|
}
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
environmentVariableName: "GOOGLE_PRIVATE_KEY_ID"
|
|
1799
|
-
})
|
|
1800
|
-
};
|
|
1801
|
-
} catch (error) {
|
|
1802
|
-
throw new Error(`Failed to load Google credentials: ${error.message}`);
|
|
1803
|
-
}
|
|
1369
|
+
//#endregion
|
|
1370
|
+
//#region src/edge/google-vertex-auth-edge.ts
|
|
1371
|
+
const loadCredentials = async () => {
|
|
1372
|
+
try {
|
|
1373
|
+
return {
|
|
1374
|
+
clientEmail: loadSetting({
|
|
1375
|
+
settingValue: void 0,
|
|
1376
|
+
settingName: "clientEmail",
|
|
1377
|
+
environmentVariableName: "GOOGLE_CLIENT_EMAIL",
|
|
1378
|
+
description: "Google client email"
|
|
1379
|
+
}),
|
|
1380
|
+
privateKey: loadSetting({
|
|
1381
|
+
settingValue: void 0,
|
|
1382
|
+
settingName: "privateKey",
|
|
1383
|
+
environmentVariableName: "GOOGLE_PRIVATE_KEY",
|
|
1384
|
+
description: "Google private key"
|
|
1385
|
+
}),
|
|
1386
|
+
privateKeyId: loadOptionalSetting({
|
|
1387
|
+
settingValue: void 0,
|
|
1388
|
+
environmentVariableName: "GOOGLE_PRIVATE_KEY_ID"
|
|
1389
|
+
})
|
|
1390
|
+
};
|
|
1391
|
+
} catch (error) {
|
|
1392
|
+
throw new Error(`Failed to load Google credentials: ${error.message}`);
|
|
1393
|
+
}
|
|
1804
1394
|
};
|
|
1805
|
-
|
|
1806
|
-
|
|
1395
|
+
const base64url = (str) => {
|
|
1396
|
+
return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
1807
1397
|
};
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
return await crypto.subtle.importKey(
|
|
1818
|
-
"pkcs8",
|
|
1819
|
-
binaryData,
|
|
1820
|
-
{ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
|
|
1821
|
-
true,
|
|
1822
|
-
["sign"]
|
|
1823
|
-
);
|
|
1398
|
+
const importPrivateKey = async (pemKey) => {
|
|
1399
|
+
const pemContents = pemKey.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replace(/\s/g, "");
|
|
1400
|
+
const binaryString = atob(pemContents);
|
|
1401
|
+
const binaryData = new Uint8Array(binaryString.length);
|
|
1402
|
+
for (let i = 0; i < binaryString.length; i++) binaryData[i] = binaryString.charCodeAt(i);
|
|
1403
|
+
return await crypto.subtle.importKey("pkcs8", binaryData, {
|
|
1404
|
+
name: "RSASSA-PKCS1-v1_5",
|
|
1405
|
+
hash: "SHA-256"
|
|
1406
|
+
}, true, ["sign"]);
|
|
1824
1407
|
};
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
const encoder = new TextEncoder();
|
|
1846
|
-
const data = encoder.encode(signingInput);
|
|
1847
|
-
const signature = await crypto.subtle.sign(
|
|
1848
|
-
"RSASSA-PKCS1-v1_5",
|
|
1849
|
-
privateKey,
|
|
1850
|
-
data
|
|
1851
|
-
);
|
|
1852
|
-
const signatureBase64 = base64url(
|
|
1853
|
-
String.fromCharCode(...new Uint8Array(signature))
|
|
1854
|
-
);
|
|
1855
|
-
return `${base64url(JSON.stringify(header))}.${base64url(
|
|
1856
|
-
JSON.stringify(payload)
|
|
1857
|
-
)}.${signatureBase64}`;
|
|
1408
|
+
const buildJwt = async (credentials) => {
|
|
1409
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
1410
|
+
const header = {
|
|
1411
|
+
alg: "RS256",
|
|
1412
|
+
typ: "JWT"
|
|
1413
|
+
};
|
|
1414
|
+
if (credentials.privateKeyId) header.kid = credentials.privateKeyId;
|
|
1415
|
+
const payload = {
|
|
1416
|
+
iss: credentials.clientEmail,
|
|
1417
|
+
scope: "https://www.googleapis.com/auth/cloud-platform",
|
|
1418
|
+
aud: "https://oauth2.googleapis.com/token",
|
|
1419
|
+
exp: now + 3600,
|
|
1420
|
+
iat: now
|
|
1421
|
+
};
|
|
1422
|
+
const privateKey = await importPrivateKey(credentials.privateKey);
|
|
1423
|
+
const signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}`;
|
|
1424
|
+
const data = new TextEncoder().encode(signingInput);
|
|
1425
|
+
const signature = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", privateKey, data);
|
|
1426
|
+
const signatureBase64 = base64url(String.fromCharCode(...new Uint8Array(signature)));
|
|
1427
|
+
return `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}.${signatureBase64}`;
|
|
1858
1428
|
};
|
|
1429
|
+
/**
|
|
1430
|
+
* Generate an authentication token for Google Vertex AI in a manner compatible
|
|
1431
|
+
* with the Edge runtime.
|
|
1432
|
+
*/
|
|
1859
1433
|
async function generateAuthToken(credentials) {
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
})
|
|
1873
|
-
});
|
|
1874
|
-
if (!response.ok) {
|
|
1875
|
-
throw new Error(`Token request failed: ${response.statusText}`);
|
|
1876
|
-
}
|
|
1877
|
-
const data = await response.json();
|
|
1878
|
-
return data.access_token;
|
|
1434
|
+
const creds = credentials || await loadCredentials();
|
|
1435
|
+
const jwt = await buildJwt(creds);
|
|
1436
|
+
const response = await fetch("https://oauth2.googleapis.com/token", {
|
|
1437
|
+
method: "POST",
|
|
1438
|
+
headers: withUserAgentSuffix({ "Content-Type": "application/x-www-form-urlencoded" }, `ai-sdk-google-vertex/${VERSION}`, getRuntimeEnvironmentUserAgent()),
|
|
1439
|
+
body: new URLSearchParams({
|
|
1440
|
+
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
|
1441
|
+
assertion: jwt
|
|
1442
|
+
})
|
|
1443
|
+
});
|
|
1444
|
+
if (!response.ok) throw new Error(`Token request failed: ${response.statusText}`);
|
|
1445
|
+
return (await response.json()).access_token;
|
|
1879
1446
|
}
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
function
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
options.googleCredentials
|
|
1895
|
-
)}`,
|
|
1896
|
-
...await resolve7(options.headers)
|
|
1897
|
-
})
|
|
1898
|
-
});
|
|
1447
|
+
//#endregion
|
|
1448
|
+
//#region src/edge/google-vertex-provider-edge.ts
|
|
1449
|
+
function createGoogleVertex(options = {}) {
|
|
1450
|
+
if (loadOptionalSetting({
|
|
1451
|
+
settingValue: options.apiKey,
|
|
1452
|
+
environmentVariableName: "GOOGLE_VERTEX_API_KEY"
|
|
1453
|
+
})) return createGoogleVertex$1(options);
|
|
1454
|
+
return createGoogleVertex$1({
|
|
1455
|
+
...options,
|
|
1456
|
+
headers: async () => ({
|
|
1457
|
+
Authorization: `Bearer ${await generateAuthToken(options.googleCredentials)}`,
|
|
1458
|
+
...await resolve(options.headers)
|
|
1459
|
+
})
|
|
1460
|
+
});
|
|
1899
1461
|
}
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1462
|
+
/**
|
|
1463
|
+
* Default Google Vertex AI provider instance.
|
|
1464
|
+
*/
|
|
1465
|
+
const googleVertex = createGoogleVertex();
|
|
1466
|
+
//#endregion
|
|
1467
|
+
export { createGoogleVertex, createGoogleVertex as createVertex, googleVertex, googleVertex as vertex };
|
|
1468
|
+
|
|
1907
1469
|
//# sourceMappingURL=index.js.map
|