@ai-sdk/google 4.0.51 → 4.0.54
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 +27 -0
- package/dist/index.d.ts +62 -3
- package/dist/index.js +621 -105
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +4 -3
- package/dist/internal/index.js +43 -17
- package/dist/internal/index.js.map +1 -1
- package/docs/15-google.mdx +28 -16
- package/package.json +2 -2
- package/src/convert-json-schema-to-openapi-schema.ts +13 -1
- package/src/google-batch.ts +9 -78
- package/src/google-files.ts +27 -2
- package/src/google-prepare-tools.ts +45 -21
- package/src/google-provider.ts +27 -0
- package/src/index.ts +5 -0
- package/src/interactions/build-google-interactions-stream-transform.ts +13 -5
- package/src/transcription/google-transcription-model-options.ts +50 -0
- package/src/transcription/google-transcription-model.ts +714 -0
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "@ai-sdk/provider-utils";
|
|
8
8
|
|
|
9
9
|
// src/version.ts
|
|
10
|
-
var VERSION = true ? "4.0.
|
|
10
|
+
var VERSION = true ? "4.0.54" : "0.0.0-test";
|
|
11
11
|
|
|
12
12
|
// src/google-embedding-model.ts
|
|
13
13
|
import {
|
|
@@ -253,18 +253,18 @@ var googleGenerativeAISingleEmbeddingResponseSchema = lazySchema3(
|
|
|
253
253
|
|
|
254
254
|
// src/google-batch.ts
|
|
255
255
|
import {
|
|
256
|
-
EmptyResponseBodyError,
|
|
257
256
|
InvalidArgumentError,
|
|
258
257
|
InvalidResponseDataError
|
|
259
258
|
} from "@ai-sdk/provider";
|
|
260
259
|
import {
|
|
261
260
|
combineHeaders as combineHeaders3,
|
|
262
261
|
convertAsyncIteratorToReadableStream,
|
|
262
|
+
createJsonLinesResponseHandler,
|
|
263
263
|
createJsonResponseHandler as createJsonResponseHandler3,
|
|
264
264
|
generateId as generateId2,
|
|
265
265
|
getFromApi,
|
|
266
266
|
lazySchema as lazySchema6,
|
|
267
|
-
|
|
267
|
+
normalizeBatchRequestCounts,
|
|
268
268
|
postJsonToApi as postJsonToApi3,
|
|
269
269
|
postToApi,
|
|
270
270
|
resolve as resolve3,
|
|
@@ -331,6 +331,10 @@ function convertGoogleUsage(usage) {
|
|
|
331
331
|
import {
|
|
332
332
|
UnsupportedFunctionalityError
|
|
333
333
|
} from "@ai-sdk/provider";
|
|
334
|
+
var recursiveReferenceFunctionalityPrefix = "recursive JSON Schema reference:";
|
|
335
|
+
function isRecursiveJSONSchemaReferenceError(error) {
|
|
336
|
+
return UnsupportedFunctionalityError.isInstance(error) && error.functionality.startsWith(recursiveReferenceFunctionalityPrefix);
|
|
337
|
+
}
|
|
334
338
|
function convertJSONSchemaToOpenAPISchema(jsonSchema, isRoot = true) {
|
|
335
339
|
const rootSchema = typeof jsonSchema === "object" ? jsonSchema : void 0;
|
|
336
340
|
return convertJSONSchemaDefinition(jsonSchema, isRoot, {
|
|
@@ -471,7 +475,7 @@ function convertJSONSchemaReference({
|
|
|
471
475
|
);
|
|
472
476
|
if (referenceContext.resolvingReferences.has(referenceKey)) {
|
|
473
477
|
throw new UnsupportedFunctionalityError({
|
|
474
|
-
functionality:
|
|
478
|
+
functionality: `${recursiveReferenceFunctionalityPrefix} ${reference}`,
|
|
475
479
|
message: "Google schema conversion does not support recursive JSON Schema references."
|
|
476
480
|
});
|
|
477
481
|
}
|
|
@@ -1278,7 +1282,6 @@ function prepareTools({
|
|
|
1278
1282
|
modelId,
|
|
1279
1283
|
isVertexProvider = false
|
|
1280
1284
|
}) {
|
|
1281
|
-
var _a, _b;
|
|
1282
1285
|
tools = (tools == null ? void 0 : tools.length) ? tools : void 0;
|
|
1283
1286
|
const toolWarnings = [];
|
|
1284
1287
|
const { supportsGemini2Tools, supportsFileSearch, usesGemini3Features } = getGoogleModelCapabilities(modelId);
|
|
@@ -1396,11 +1399,7 @@ function prepareTools({
|
|
|
1396
1399
|
const functionDeclarations2 = [];
|
|
1397
1400
|
for (const tool of tools) {
|
|
1398
1401
|
if (tool.type === "function") {
|
|
1399
|
-
functionDeclarations2.push(
|
|
1400
|
-
name: tool.name,
|
|
1401
|
-
description: (_a = tool.description) != null ? _a : "",
|
|
1402
|
-
parameters: convertJSONSchemaToOpenAPISchema(tool.inputSchema)
|
|
1403
|
-
});
|
|
1402
|
+
functionDeclarations2.push(prepareFunctionDeclaration(tool));
|
|
1404
1403
|
}
|
|
1405
1404
|
}
|
|
1406
1405
|
const combinedToolConfig = {
|
|
@@ -1444,11 +1443,7 @@ function prepareTools({
|
|
|
1444
1443
|
for (const tool of tools) {
|
|
1445
1444
|
switch (tool.type) {
|
|
1446
1445
|
case "function":
|
|
1447
|
-
functionDeclarations.push(
|
|
1448
|
-
name: tool.name,
|
|
1449
|
-
description: (_b = tool.description) != null ? _b : "",
|
|
1450
|
-
parameters: convertJSONSchemaToOpenAPISchema(tool.inputSchema)
|
|
1451
|
-
});
|
|
1446
|
+
functionDeclarations.push(prepareFunctionDeclaration(tool));
|
|
1452
1447
|
if (tool.strict === true) {
|
|
1453
1448
|
hasStrictTools = true;
|
|
1454
1449
|
}
|
|
@@ -1515,6 +1510,27 @@ function prepareTools({
|
|
|
1515
1510
|
}
|
|
1516
1511
|
}
|
|
1517
1512
|
}
|
|
1513
|
+
function prepareFunctionDeclaration(tool) {
|
|
1514
|
+
var _a;
|
|
1515
|
+
const declaration = {
|
|
1516
|
+
name: tool.name,
|
|
1517
|
+
description: (_a = tool.description) != null ? _a : ""
|
|
1518
|
+
};
|
|
1519
|
+
try {
|
|
1520
|
+
return {
|
|
1521
|
+
...declaration,
|
|
1522
|
+
parameters: convertJSONSchemaToOpenAPISchema(tool.inputSchema)
|
|
1523
|
+
};
|
|
1524
|
+
} catch (error) {
|
|
1525
|
+
if (!isRecursiveJSONSchemaReferenceError(error)) {
|
|
1526
|
+
throw error;
|
|
1527
|
+
}
|
|
1528
|
+
return {
|
|
1529
|
+
...declaration,
|
|
1530
|
+
parametersJsonSchema: tool.inputSchema
|
|
1531
|
+
};
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1518
1534
|
|
|
1519
1535
|
// src/google-json-accumulator.ts
|
|
1520
1536
|
var GoogleJSONAccumulator = class {
|
|
@@ -3254,17 +3270,19 @@ var GoogleBatchLanguageModel = class _GoogleBatchLanguageModel extends GoogleLan
|
|
|
3254
3270
|
});
|
|
3255
3271
|
}
|
|
3256
3272
|
const encodedResponsesFile = responsesFile.split("/").map((segment) => encodeURIComponent(segment)).join("/");
|
|
3257
|
-
const { value:
|
|
3273
|
+
const { value: lines } = await getFromApi({
|
|
3258
3274
|
url: `${this.getBaseOrigin()}/download/v1beta/${encodedResponsesFile}:download?alt=media`,
|
|
3259
3275
|
headers: await this.getHeaders(options.headers),
|
|
3260
3276
|
failedResponseHandler: googleFailedResponseHandler,
|
|
3261
|
-
successfulResponseHandler:
|
|
3277
|
+
successfulResponseHandler: createJsonLinesResponseHandler(
|
|
3278
|
+
googleBatchResultLineSchema
|
|
3279
|
+
),
|
|
3262
3280
|
abortSignal: options.abortSignal,
|
|
3263
3281
|
fetch: this.batchConfig.fetch,
|
|
3264
3282
|
validateUrl: false
|
|
3265
3283
|
});
|
|
3266
3284
|
return convertAsyncIteratorToReadableStream(
|
|
3267
|
-
this.iterateBatchResults(
|
|
3285
|
+
this.iterateBatchResults(lines)
|
|
3268
3286
|
);
|
|
3269
3287
|
}
|
|
3270
3288
|
async retrieveBatch(options) {
|
|
@@ -3430,15 +3448,12 @@ function convertGoogleRequestCounts(counts) {
|
|
|
3430
3448
|
const completed = parseCount((_a = counts == null ? void 0 : counts.successfulRequestCount) != null ? _a : 0);
|
|
3431
3449
|
const failed = parseCount((_b = counts == null ? void 0 : counts.failedRequestCount) != null ? _b : 0);
|
|
3432
3450
|
const pending = parseCount((_c = counts == null ? void 0 : counts.pendingRequestCount) != null ? _c : 0);
|
|
3433
|
-
|
|
3434
|
-
return void 0;
|
|
3435
|
-
}
|
|
3436
|
-
return {
|
|
3451
|
+
return normalizeBatchRequestCounts({
|
|
3437
3452
|
total,
|
|
3438
3453
|
pending,
|
|
3439
3454
|
completed,
|
|
3440
3455
|
failed
|
|
3441
|
-
};
|
|
3456
|
+
});
|
|
3442
3457
|
}
|
|
3443
3458
|
function parseCount(value) {
|
|
3444
3459
|
const count = typeof value === "string" && /^\d+$/.test(value) ? Number(value) : value;
|
|
@@ -3464,54 +3479,6 @@ var googleUploadUrlResponseHandler = async ({
|
|
|
3464
3479
|
}
|
|
3465
3480
|
return { value: uploadUrl };
|
|
3466
3481
|
};
|
|
3467
|
-
var rawStreamResponseHandler = async ({ response }) => {
|
|
3468
|
-
if (response.body == null) {
|
|
3469
|
-
throw new EmptyResponseBodyError();
|
|
3470
|
-
}
|
|
3471
|
-
return { value: response.body };
|
|
3472
|
-
};
|
|
3473
|
-
async function* parseJsonLines(stream) {
|
|
3474
|
-
const reader = stream.getReader();
|
|
3475
|
-
const decoder = new TextDecoder();
|
|
3476
|
-
let buffer = "";
|
|
3477
|
-
let finished = false;
|
|
3478
|
-
try {
|
|
3479
|
-
while (true) {
|
|
3480
|
-
const { done, value } = await reader.read();
|
|
3481
|
-
if (done) {
|
|
3482
|
-
finished = true;
|
|
3483
|
-
buffer += decoder.decode();
|
|
3484
|
-
break;
|
|
3485
|
-
}
|
|
3486
|
-
buffer += decoder.decode(value, { stream: true });
|
|
3487
|
-
let lineEnd = buffer.indexOf("\n");
|
|
3488
|
-
while (lineEnd !== -1) {
|
|
3489
|
-
const line = buffer.slice(0, lineEnd).replace(/\r$/, "");
|
|
3490
|
-
buffer = buffer.slice(lineEnd + 1);
|
|
3491
|
-
if (line.trim().length > 0) {
|
|
3492
|
-
yield await parseJSON({
|
|
3493
|
-
text: line,
|
|
3494
|
-
schema: googleBatchResultLineSchema
|
|
3495
|
-
});
|
|
3496
|
-
}
|
|
3497
|
-
lineEnd = buffer.indexOf("\n");
|
|
3498
|
-
}
|
|
3499
|
-
}
|
|
3500
|
-
const finalLine = buffer.replace(/\r$/, "");
|
|
3501
|
-
if (finalLine.trim().length > 0) {
|
|
3502
|
-
yield await parseJSON({
|
|
3503
|
-
text: finalLine,
|
|
3504
|
-
schema: googleBatchResultLineSchema
|
|
3505
|
-
});
|
|
3506
|
-
}
|
|
3507
|
-
} finally {
|
|
3508
|
-
if (!finished) {
|
|
3509
|
-
await reader.cancel().catch(() => {
|
|
3510
|
-
});
|
|
3511
|
-
}
|
|
3512
|
-
reader.releaseLock();
|
|
3513
|
-
}
|
|
3514
|
-
}
|
|
3515
3482
|
|
|
3516
3483
|
// src/tool/code-execution.ts
|
|
3517
3484
|
import { createProviderExecutedToolFactory } from "@ai-sdk/provider-utils";
|
|
@@ -3902,6 +3869,10 @@ import {
|
|
|
3902
3869
|
getFromApi as getFromApi2
|
|
3903
3870
|
} from "@ai-sdk/provider-utils";
|
|
3904
3871
|
import { z as z15 } from "zod/v4";
|
|
3872
|
+
function encodePathSegment(value) {
|
|
3873
|
+
const encodedValue = encodeURIComponent(value);
|
|
3874
|
+
return encodedValue === "." ? "%252E" : encodedValue === ".." ? "%252E%252E" : encodedValue;
|
|
3875
|
+
}
|
|
3905
3876
|
var GoogleFiles = class {
|
|
3906
3877
|
constructor(config) {
|
|
3907
3878
|
this.config = config;
|
|
@@ -3963,7 +3934,7 @@ var GoogleFiles = class {
|
|
|
3963
3934
|
"X-Goog-Upload-Offset": "0",
|
|
3964
3935
|
"X-Goog-Upload-Command": "upload, finalize"
|
|
3965
3936
|
},
|
|
3966
|
-
body: fileBytes
|
|
3937
|
+
body: ensureArrayBufferBacked(fileBytes)
|
|
3967
3938
|
});
|
|
3968
3939
|
if (!uploadResponse.ok) {
|
|
3969
3940
|
const errorBody = await uploadResponse.text();
|
|
@@ -3985,8 +3956,10 @@ var GoogleFiles = class {
|
|
|
3985
3956
|
});
|
|
3986
3957
|
}
|
|
3987
3958
|
await delay(pollIntervalMs);
|
|
3959
|
+
const fileNameMatch = /^files\/([^/]+)$/.exec(file.name);
|
|
3960
|
+
const filePath = fileNameMatch != null ? `files/${encodePathSegment(fileNameMatch[1])}` : encodePathSegment(file.name);
|
|
3988
3961
|
const { value: fileStatus } = await getFromApi2({
|
|
3989
|
-
url: `${this.config.baseURL}/${
|
|
3962
|
+
url: `${this.config.baseURL}/${filePath}`,
|
|
3990
3963
|
validateUrl: false,
|
|
3991
3964
|
headers: combineHeaders4(resolvedHeaders),
|
|
3992
3965
|
successfulResponseHandler: createJsonResponseHandler4(
|
|
@@ -4024,6 +3997,12 @@ var GoogleFiles = class {
|
|
|
4024
3997
|
};
|
|
4025
3998
|
}
|
|
4026
3999
|
};
|
|
4000
|
+
function ensureArrayBufferBacked(data) {
|
|
4001
|
+
if (data.buffer instanceof ArrayBuffer) {
|
|
4002
|
+
return data;
|
|
4003
|
+
}
|
|
4004
|
+
return new Uint8Array(data);
|
|
4005
|
+
}
|
|
4027
4006
|
var googleFileResponseSchema = lazySchema14(
|
|
4028
4007
|
() => zodSchema14(
|
|
4029
4008
|
z15.object({
|
|
@@ -4683,6 +4662,11 @@ import {
|
|
|
4683
4662
|
WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE6
|
|
4684
4663
|
} from "@ai-sdk/provider-utils";
|
|
4685
4664
|
|
|
4665
|
+
// src/interactions/build-google-interactions-stream-transform.ts
|
|
4666
|
+
import {
|
|
4667
|
+
createProviderStreamError
|
|
4668
|
+
} from "@ai-sdk/provider-utils";
|
|
4669
|
+
|
|
4686
4670
|
// src/interactions/convert-google-interactions-usage.ts
|
|
4687
4671
|
import { createNullLanguageModelUsage as createNullLanguageModelUsage2 } from "@ai-sdk/provider-utils";
|
|
4688
4672
|
function convertGoogleInteractionsUsage(usage) {
|
|
@@ -4977,7 +4961,7 @@ function buildGoogleInteractionsStreamTransform({
|
|
|
4977
4961
|
controller.enqueue({ type: "stream-start", warnings });
|
|
4978
4962
|
},
|
|
4979
4963
|
transform(chunk, controller) {
|
|
4980
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
|
|
4964
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
|
|
4981
4965
|
if (includeRawChunks) {
|
|
4982
4966
|
controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
|
|
4983
4967
|
}
|
|
@@ -5388,10 +5372,15 @@ function buildGoogleInteractionsStreamTransform({
|
|
|
5388
5372
|
case "error": {
|
|
5389
5373
|
const event = value;
|
|
5390
5374
|
finishStatus = "failed";
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5375
|
+
controller.enqueue({
|
|
5376
|
+
type: "error",
|
|
5377
|
+
error: createProviderStreamError({
|
|
5378
|
+
message: (_r = (_q = event.error) == null ? void 0 : _q.message) != null ? _r : "Unknown interaction error",
|
|
5379
|
+
type: event.event_type,
|
|
5380
|
+
code: (_t = (_s = event.error) == null ? void 0 : _s.code) != null ? _t : void 0,
|
|
5381
|
+
data: event
|
|
5382
|
+
})
|
|
5383
|
+
});
|
|
5395
5384
|
break;
|
|
5396
5385
|
}
|
|
5397
5386
|
default:
|
|
@@ -8014,21 +8003,538 @@ var GoogleRealtimeModel = class {
|
|
|
8014
8003
|
}
|
|
8015
8004
|
};
|
|
8016
8005
|
|
|
8017
|
-
// src/
|
|
8006
|
+
// src/transcription/google-transcription-model.ts
|
|
8018
8007
|
import {
|
|
8019
8008
|
InvalidArgumentError as InvalidArgumentError2
|
|
8020
8009
|
} from "@ai-sdk/provider";
|
|
8021
8010
|
import {
|
|
8022
|
-
connectToWebSocket,
|
|
8023
8011
|
combineHeaders as combineHeaders9,
|
|
8024
|
-
|
|
8012
|
+
connectToWebSocket,
|
|
8025
8013
|
convertToBase64 as convertToBase644,
|
|
8014
|
+
createJsonResponseHandler as createJsonResponseHandler9,
|
|
8026
8015
|
parseProviderOptions as parseProviderOptions8,
|
|
8016
|
+
postJsonToApi as postJsonToApi7,
|
|
8017
|
+
resolve as resolve7,
|
|
8027
8018
|
safeParseJSON as safeParseJSON2,
|
|
8028
8019
|
serializeModelOptions as serializeModelOptions6,
|
|
8020
|
+
waitForWebSocketBufferDrain,
|
|
8029
8021
|
WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE7,
|
|
8030
|
-
WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE7
|
|
8031
|
-
|
|
8022
|
+
WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE7
|
|
8023
|
+
} from "@ai-sdk/provider-utils";
|
|
8024
|
+
import { z as z23 } from "zod/v4";
|
|
8025
|
+
|
|
8026
|
+
// src/transcription/google-transcription-model-options.ts
|
|
8027
|
+
import { z as z22 } from "zod/v4";
|
|
8028
|
+
var googleTranscriptionModelOptions = z22.object({
|
|
8029
|
+
/**
|
|
8030
|
+
* BCP-47 language codes providing hints about the languages present in the
|
|
8031
|
+
* audio. If omitted or empty, defaults to automatic language detection.
|
|
8032
|
+
*/
|
|
8033
|
+
languageCodes: z22.array(z22.string()).optional(),
|
|
8034
|
+
/**
|
|
8035
|
+
* Custom vocabulary phrases, which bias the speech recognition model
|
|
8036
|
+
* toward recognizing specific terms.
|
|
8037
|
+
*/
|
|
8038
|
+
customVocabulary: z22.array(z22.string()).optional(),
|
|
8039
|
+
/**
|
|
8040
|
+
* Enables word-level timestamp generation.
|
|
8041
|
+
*/
|
|
8042
|
+
wordTimestamp: z22.boolean().optional(),
|
|
8043
|
+
/**
|
|
8044
|
+
* Enables speaker diarization.
|
|
8045
|
+
*/
|
|
8046
|
+
diarization: z22.boolean().optional(),
|
|
8047
|
+
/**
|
|
8048
|
+
* Transcription output formatting mode.
|
|
8049
|
+
*
|
|
8050
|
+
* - `VERBATIM` (default): exact literal transcript preserving filler
|
|
8051
|
+
* words, repetitions, and false starts.
|
|
8052
|
+
* - `SMART`: cleans up and structures the transcript in real time —
|
|
8053
|
+
* disfluency removal, inline self-corrections, structured formatting
|
|
8054
|
+
* (lists, numbers, dates, paragraph breaks), and grammar/casing polish.
|
|
8055
|
+
*/
|
|
8056
|
+
mode: z22.enum(["SMART", "VERBATIM"]).optional()
|
|
8057
|
+
});
|
|
8058
|
+
|
|
8059
|
+
// src/transcription/google-transcription-model.ts
|
|
8060
|
+
var liveWebSocketPath = "google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent";
|
|
8061
|
+
var defaultFinishGraceMs = 3e3;
|
|
8062
|
+
function getLiveWebSocketURL(baseURL, apiKey) {
|
|
8063
|
+
const url = getRealtimeWebSocketURL(baseURL, liveWebSocketPath);
|
|
8064
|
+
url.searchParams.set("key", apiKey);
|
|
8065
|
+
return url;
|
|
8066
|
+
}
|
|
8067
|
+
function isLiveTranscriptionModelId(modelId) {
|
|
8068
|
+
return modelId.includes("-live");
|
|
8069
|
+
}
|
|
8070
|
+
var GoogleTranscriptionModel = class _GoogleTranscriptionModel {
|
|
8071
|
+
constructor(modelId, config) {
|
|
8072
|
+
this.modelId = modelId;
|
|
8073
|
+
this.config = config;
|
|
8074
|
+
this.specificationVersion = "v4";
|
|
8075
|
+
}
|
|
8076
|
+
static [WORKFLOW_SERIALIZE7](model) {
|
|
8077
|
+
return serializeModelOptions6({
|
|
8078
|
+
modelId: model.modelId,
|
|
8079
|
+
config: model.config
|
|
8080
|
+
});
|
|
8081
|
+
}
|
|
8082
|
+
static [WORKFLOW_DESERIALIZE7](options) {
|
|
8083
|
+
return new _GoogleTranscriptionModel(options.modelId, options.config);
|
|
8084
|
+
}
|
|
8085
|
+
get provider() {
|
|
8086
|
+
return this.config.provider;
|
|
8087
|
+
}
|
|
8088
|
+
async parseOptions(providerOptions) {
|
|
8089
|
+
return parseProviderOptions8({
|
|
8090
|
+
provider: "google",
|
|
8091
|
+
providerOptions,
|
|
8092
|
+
schema: googleTranscriptionModelOptions
|
|
8093
|
+
});
|
|
8094
|
+
}
|
|
8095
|
+
async doGenerate(options) {
|
|
8096
|
+
var _a, _b, _c, _d, _e, _f;
|
|
8097
|
+
if (isLiveTranscriptionModelId(this.modelId)) {
|
|
8098
|
+
throw new InvalidArgumentError2({
|
|
8099
|
+
argument: "modelId",
|
|
8100
|
+
message: `Model '${this.modelId}' only supports streaming transcription. Use experimental_streamTranscribe, or a unary model such as 'gemini-3.5-transcribe'.`
|
|
8101
|
+
});
|
|
8102
|
+
}
|
|
8103
|
+
const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
|
|
8104
|
+
const warnings = [];
|
|
8105
|
+
const googleOptions = await this.parseOptions(options.providerOptions);
|
|
8106
|
+
const transcriptionConfig = buildTranscriptionConfig(googleOptions);
|
|
8107
|
+
const requestBody = {
|
|
8108
|
+
model: this.modelId,
|
|
8109
|
+
input: [
|
|
8110
|
+
{
|
|
8111
|
+
type: "audio",
|
|
8112
|
+
data: convertToBase644(options.audio),
|
|
8113
|
+
mime_type: options.mediaType
|
|
8114
|
+
}
|
|
8115
|
+
],
|
|
8116
|
+
...transcriptionConfig != null ? { generation_config: { transcription_config: transcriptionConfig } } : {}
|
|
8117
|
+
};
|
|
8118
|
+
const {
|
|
8119
|
+
value: response,
|
|
8120
|
+
responseHeaders,
|
|
8121
|
+
rawValue: rawResponse
|
|
8122
|
+
} = await postJsonToApi7({
|
|
8123
|
+
url: `${this.config.baseURL}/interactions`,
|
|
8124
|
+
headers: combineHeaders9(
|
|
8125
|
+
this.config.headers ? await resolve7(this.config.headers) : void 0,
|
|
8126
|
+
options.headers
|
|
8127
|
+
),
|
|
8128
|
+
body: requestBody,
|
|
8129
|
+
failedResponseHandler: googleFailedResponseHandler,
|
|
8130
|
+
successfulResponseHandler: createJsonResponseHandler9(
|
|
8131
|
+
googleInteractionsTranscriptionResponseSchema
|
|
8132
|
+
),
|
|
8133
|
+
abortSignal: options.abortSignal,
|
|
8134
|
+
fetch: this.config.fetch
|
|
8135
|
+
});
|
|
8136
|
+
let text = "";
|
|
8137
|
+
const segments = [];
|
|
8138
|
+
for (const step of (_d = response.steps) != null ? _d : []) {
|
|
8139
|
+
for (const content of (_e = step.content) != null ? _e : []) {
|
|
8140
|
+
if (content.type !== "text" || content.text == null) continue;
|
|
8141
|
+
text += content.text;
|
|
8142
|
+
for (const annotation of (_f = content.annotations) != null ? _f : []) {
|
|
8143
|
+
if (annotation.type !== "word_info") continue;
|
|
8144
|
+
const startSecond = parseOffsetSeconds(annotation.start_offset);
|
|
8145
|
+
const endSecond = parseOffsetSeconds(annotation.end_offset);
|
|
8146
|
+
if (annotation.text == null || startSecond == null || endSecond == null) {
|
|
8147
|
+
continue;
|
|
8148
|
+
}
|
|
8149
|
+
segments.push({ text: annotation.text, startSecond, endSecond });
|
|
8150
|
+
}
|
|
8151
|
+
}
|
|
8152
|
+
}
|
|
8153
|
+
return {
|
|
8154
|
+
text,
|
|
8155
|
+
segments,
|
|
8156
|
+
language: void 0,
|
|
8157
|
+
durationInSeconds: void 0,
|
|
8158
|
+
warnings,
|
|
8159
|
+
response: {
|
|
8160
|
+
timestamp: currentDate,
|
|
8161
|
+
modelId: this.modelId,
|
|
8162
|
+
headers: responseHeaders,
|
|
8163
|
+
body: rawResponse
|
|
8164
|
+
},
|
|
8165
|
+
...response.usage != null ? {
|
|
8166
|
+
providerMetadata: {
|
|
8167
|
+
google: { usage: response.usage }
|
|
8168
|
+
}
|
|
8169
|
+
} : {}
|
|
8170
|
+
};
|
|
8171
|
+
}
|
|
8172
|
+
async doStream(options) {
|
|
8173
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
8174
|
+
if (!isLiveTranscriptionModelId(this.modelId)) {
|
|
8175
|
+
throw new InvalidArgumentError2({
|
|
8176
|
+
argument: "modelId",
|
|
8177
|
+
message: `Model '${this.modelId}' does not support streaming transcription. Use a live model such as 'gemini-3.5-transcribe-live'.`
|
|
8178
|
+
});
|
|
8179
|
+
}
|
|
8180
|
+
const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
|
|
8181
|
+
const warnings = [];
|
|
8182
|
+
const googleOptions = await this.parseOptions(options.providerOptions);
|
|
8183
|
+
validateLiveInputAudioFormat(options.inputAudioFormat);
|
|
8184
|
+
const headers = combineHeaders9(
|
|
8185
|
+
this.config.headers ? await resolve7(this.config.headers) : void 0,
|
|
8186
|
+
options.headers
|
|
8187
|
+
);
|
|
8188
|
+
let apiKey;
|
|
8189
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
8190
|
+
if (key.toLowerCase() === "x-goog-api-key" && value != null) {
|
|
8191
|
+
apiKey = value;
|
|
8192
|
+
}
|
|
8193
|
+
}
|
|
8194
|
+
if (apiKey == null) {
|
|
8195
|
+
throw new Error(
|
|
8196
|
+
"Google Generative AI API key is required for streaming transcription."
|
|
8197
|
+
);
|
|
8198
|
+
}
|
|
8199
|
+
const webSocketHeaders = Object.fromEntries(
|
|
8200
|
+
Object.entries(headers).filter(
|
|
8201
|
+
([key]) => key.toLowerCase() !== "x-goog-api-key"
|
|
8202
|
+
)
|
|
8203
|
+
);
|
|
8204
|
+
const setup = {
|
|
8205
|
+
model: getModelPath(this.modelId),
|
|
8206
|
+
inputAudioTranscription: (_d = buildAudioTranscriptionConfig(googleOptions)) != null ? _d : {}
|
|
8207
|
+
};
|
|
8208
|
+
return {
|
|
8209
|
+
request: { body: setup },
|
|
8210
|
+
response: {
|
|
8211
|
+
timestamp: currentDate,
|
|
8212
|
+
modelId: this.modelId
|
|
8213
|
+
},
|
|
8214
|
+
stream: createGoogleLiveTranscriptionStream({
|
|
8215
|
+
webSocket: this.config.webSocket,
|
|
8216
|
+
url: getLiveWebSocketURL(this.config.baseURL, apiKey),
|
|
8217
|
+
headers: webSocketHeaders,
|
|
8218
|
+
setup,
|
|
8219
|
+
inputAudioRate: (_e = options.inputAudioFormat.rate) != null ? _e : 16e3,
|
|
8220
|
+
finishGraceMs: (_g = (_f = this.config._internal) == null ? void 0 : _f.finishGraceMs) != null ? _g : defaultFinishGraceMs,
|
|
8221
|
+
warnings,
|
|
8222
|
+
audio: options.audio,
|
|
8223
|
+
abortSignal: options.abortSignal,
|
|
8224
|
+
includeRawChunks: options.includeRawChunks
|
|
8225
|
+
})
|
|
8226
|
+
};
|
|
8227
|
+
}
|
|
8228
|
+
};
|
|
8229
|
+
function createGoogleLiveTranscriptionStream({
|
|
8230
|
+
webSocket,
|
|
8231
|
+
url,
|
|
8232
|
+
headers,
|
|
8233
|
+
setup,
|
|
8234
|
+
inputAudioRate,
|
|
8235
|
+
finishGraceMs,
|
|
8236
|
+
warnings,
|
|
8237
|
+
audio,
|
|
8238
|
+
abortSignal,
|
|
8239
|
+
includeRawChunks
|
|
8240
|
+
}) {
|
|
8241
|
+
let finished = false;
|
|
8242
|
+
let cleanup = () => {
|
|
8243
|
+
};
|
|
8244
|
+
return new ReadableStream({
|
|
8245
|
+
start: (controller) => {
|
|
8246
|
+
let audioReader;
|
|
8247
|
+
let connection;
|
|
8248
|
+
let resolveSetupComplete;
|
|
8249
|
+
const setupComplete = new Promise((resolve8) => {
|
|
8250
|
+
resolveSetupComplete = resolve8;
|
|
8251
|
+
});
|
|
8252
|
+
let segmentCounter = 0;
|
|
8253
|
+
let segmentBuffer = "";
|
|
8254
|
+
let fullText = "";
|
|
8255
|
+
let latestInterim = "";
|
|
8256
|
+
let language;
|
|
8257
|
+
let audioEnded = false;
|
|
8258
|
+
let usageMetadata;
|
|
8259
|
+
let finishTimer;
|
|
8260
|
+
const segmentId = () => `google-segment-${segmentCounter}`;
|
|
8261
|
+
const cancelPendingFinish = () => {
|
|
8262
|
+
if (finishTimer != null) {
|
|
8263
|
+
clearTimeout(finishTimer);
|
|
8264
|
+
finishTimer = void 0;
|
|
8265
|
+
}
|
|
8266
|
+
};
|
|
8267
|
+
const schedulePendingFinish = () => {
|
|
8268
|
+
if (finished || !audioEnded) return;
|
|
8269
|
+
cancelPendingFinish();
|
|
8270
|
+
finishTimer = setTimeout(() => {
|
|
8271
|
+
finishTimer = void 0;
|
|
8272
|
+
finish();
|
|
8273
|
+
}, finishGraceMs);
|
|
8274
|
+
};
|
|
8275
|
+
cleanup = (closeCode) => {
|
|
8276
|
+
cancelPendingFinish();
|
|
8277
|
+
if (audioReader != null) {
|
|
8278
|
+
void audioReader.cancel().catch(() => {
|
|
8279
|
+
});
|
|
8280
|
+
} else {
|
|
8281
|
+
void audio.cancel().catch(() => {
|
|
8282
|
+
});
|
|
8283
|
+
}
|
|
8284
|
+
connection == null ? void 0 : connection.close(closeCode);
|
|
8285
|
+
};
|
|
8286
|
+
const finishWithError = (error) => {
|
|
8287
|
+
if (finished) return;
|
|
8288
|
+
finished = true;
|
|
8289
|
+
cleanup();
|
|
8290
|
+
controller.error(error);
|
|
8291
|
+
};
|
|
8292
|
+
const completeSegment = () => {
|
|
8293
|
+
if (segmentBuffer === "") {
|
|
8294
|
+
if (latestInterim === "") return;
|
|
8295
|
+
segmentBuffer = latestInterim;
|
|
8296
|
+
}
|
|
8297
|
+
latestInterim = "";
|
|
8298
|
+
controller.enqueue({
|
|
8299
|
+
type: "transcript-final",
|
|
8300
|
+
id: segmentId(),
|
|
8301
|
+
text: segmentBuffer
|
|
8302
|
+
});
|
|
8303
|
+
fullText += fullText === "" ? segmentBuffer : ` ${segmentBuffer}`;
|
|
8304
|
+
segmentBuffer = "";
|
|
8305
|
+
segmentCounter++;
|
|
8306
|
+
};
|
|
8307
|
+
const finish = () => {
|
|
8308
|
+
if (finished) return;
|
|
8309
|
+
completeSegment();
|
|
8310
|
+
finished = true;
|
|
8311
|
+
controller.enqueue({
|
|
8312
|
+
type: "finish",
|
|
8313
|
+
text: fullText,
|
|
8314
|
+
segments: [],
|
|
8315
|
+
language,
|
|
8316
|
+
durationInSeconds: void 0,
|
|
8317
|
+
...usageMetadata != null ? { providerMetadata: { google: { usageMetadata } } } : {}
|
|
8318
|
+
});
|
|
8319
|
+
controller.close();
|
|
8320
|
+
cleanup(1e3);
|
|
8321
|
+
};
|
|
8322
|
+
const sendAudio = async (socket) => {
|
|
8323
|
+
audioReader = audio.getReader();
|
|
8324
|
+
try {
|
|
8325
|
+
while (true) {
|
|
8326
|
+
const { done, value } = await audioReader.read();
|
|
8327
|
+
if (done || finished) break;
|
|
8328
|
+
socket.send(
|
|
8329
|
+
JSON.stringify({
|
|
8330
|
+
realtimeInput: {
|
|
8331
|
+
audio: {
|
|
8332
|
+
data: convertToBase644(value),
|
|
8333
|
+
mimeType: `audio/pcm;rate=${inputAudioRate}`
|
|
8334
|
+
}
|
|
8335
|
+
}
|
|
8336
|
+
})
|
|
8337
|
+
);
|
|
8338
|
+
await waitForWebSocketBufferDrain(socket);
|
|
8339
|
+
}
|
|
8340
|
+
} finally {
|
|
8341
|
+
audioReader.releaseLock();
|
|
8342
|
+
audioReader = void 0;
|
|
8343
|
+
}
|
|
8344
|
+
if (!finished) {
|
|
8345
|
+
socket.send(
|
|
8346
|
+
JSON.stringify({ realtimeInput: { audioStreamEnd: true } })
|
|
8347
|
+
);
|
|
8348
|
+
audioEnded = true;
|
|
8349
|
+
schedulePendingFinish();
|
|
8350
|
+
}
|
|
8351
|
+
};
|
|
8352
|
+
connection = connectToWebSocket({
|
|
8353
|
+
url,
|
|
8354
|
+
headers,
|
|
8355
|
+
webSocket,
|
|
8356
|
+
abortSignal,
|
|
8357
|
+
onAbort: finishWithError,
|
|
8358
|
+
onProcessingError: finishWithError,
|
|
8359
|
+
onOpen: (socket) => {
|
|
8360
|
+
controller.enqueue({ type: "stream-start", warnings });
|
|
8361
|
+
socket.send(JSON.stringify({ setup }));
|
|
8362
|
+
void setupComplete.then(() => finished ? void 0 : sendAudio(socket)).catch(finishWithError);
|
|
8363
|
+
},
|
|
8364
|
+
onMessageText: async (text) => {
|
|
8365
|
+
var _a, _b;
|
|
8366
|
+
if (finished) return;
|
|
8367
|
+
const parsed = await safeParseJSON2({ text });
|
|
8368
|
+
if (!parsed.success) return;
|
|
8369
|
+
const message = parsed.value;
|
|
8370
|
+
if (includeRawChunks) {
|
|
8371
|
+
controller.enqueue({ type: "raw", rawValue: message });
|
|
8372
|
+
}
|
|
8373
|
+
if (message.setupComplete != null) {
|
|
8374
|
+
resolveSetupComplete();
|
|
8375
|
+
}
|
|
8376
|
+
if (message.usageMetadata != null) {
|
|
8377
|
+
usageMetadata = message.usageMetadata;
|
|
8378
|
+
}
|
|
8379
|
+
if (message.error != null) {
|
|
8380
|
+
finishWithError(
|
|
8381
|
+
new Error((_a = message.error.message) != null ? _a : "Google Live API error")
|
|
8382
|
+
);
|
|
8383
|
+
return;
|
|
8384
|
+
}
|
|
8385
|
+
const serverContent = message.serverContent;
|
|
8386
|
+
const interim = serverContent == null ? void 0 : serverContent.interimInputTranscription;
|
|
8387
|
+
if (interim == null ? void 0 : interim.text) {
|
|
8388
|
+
schedulePendingFinish();
|
|
8389
|
+
latestInterim = interim.text;
|
|
8390
|
+
controller.enqueue({
|
|
8391
|
+
type: "transcript-partial",
|
|
8392
|
+
id: segmentId(),
|
|
8393
|
+
text: interim.text
|
|
8394
|
+
});
|
|
8395
|
+
}
|
|
8396
|
+
const transcription = (_b = serverContent == null ? void 0 : serverContent.inputTranscription) != null ? _b : message.inputTranscription;
|
|
8397
|
+
if (transcription != null) {
|
|
8398
|
+
if (transcription.languageCode != null) {
|
|
8399
|
+
language = transcription.languageCode;
|
|
8400
|
+
}
|
|
8401
|
+
if (transcription.text) {
|
|
8402
|
+
schedulePendingFinish();
|
|
8403
|
+
latestInterim = "";
|
|
8404
|
+
segmentBuffer += transcription.text;
|
|
8405
|
+
controller.enqueue({
|
|
8406
|
+
type: "transcript-delta",
|
|
8407
|
+
id: segmentId(),
|
|
8408
|
+
delta: transcription.text
|
|
8409
|
+
});
|
|
8410
|
+
}
|
|
8411
|
+
if (transcription.finished === true) {
|
|
8412
|
+
completeSegment();
|
|
8413
|
+
}
|
|
8414
|
+
}
|
|
8415
|
+
if (serverContent == null ? void 0 : serverContent.turnComplete) {
|
|
8416
|
+
completeSegment();
|
|
8417
|
+
}
|
|
8418
|
+
const interactionStatus = serverContent == null ? void 0 : serverContent.interactionStatus;
|
|
8419
|
+
if (audioEnded && (interactionStatus === "IDLE" || interactionStatus === "REQUIRES_ACTION" || (serverContent == null ? void 0 : serverContent.turnComplete) === true && interactionStatus == null)) {
|
|
8420
|
+
finish();
|
|
8421
|
+
}
|
|
8422
|
+
},
|
|
8423
|
+
onSocketError: () => {
|
|
8424
|
+
finishWithError(new Error("Google Live transcription error"));
|
|
8425
|
+
},
|
|
8426
|
+
onClose: ({ code, reason }) => {
|
|
8427
|
+
if (finished) return;
|
|
8428
|
+
if (audioEnded) {
|
|
8429
|
+
finish();
|
|
8430
|
+
return;
|
|
8431
|
+
}
|
|
8432
|
+
finishWithError(
|
|
8433
|
+
new Error(
|
|
8434
|
+
`Google Live transcription WebSocket closed unexpectedly before finishing (code ${code != null ? code : "unknown"}${reason ? `, reason: ${reason}` : ""}).`
|
|
8435
|
+
)
|
|
8436
|
+
);
|
|
8437
|
+
}
|
|
8438
|
+
});
|
|
8439
|
+
},
|
|
8440
|
+
cancel: () => {
|
|
8441
|
+
if (finished) return;
|
|
8442
|
+
finished = true;
|
|
8443
|
+
cleanup();
|
|
8444
|
+
}
|
|
8445
|
+
});
|
|
8446
|
+
}
|
|
8447
|
+
function buildAudioTranscriptionConfig(options) {
|
|
8448
|
+
if (options == null) return void 0;
|
|
8449
|
+
const config = {};
|
|
8450
|
+
if (options.languageCodes != null) {
|
|
8451
|
+
config.languageCodes = options.languageCodes;
|
|
8452
|
+
}
|
|
8453
|
+
if (options.customVocabulary != null) {
|
|
8454
|
+
config.customVocabulary = options.customVocabulary;
|
|
8455
|
+
}
|
|
8456
|
+
if (options.wordTimestamp != null) {
|
|
8457
|
+
config.wordTimestamp = options.wordTimestamp;
|
|
8458
|
+
}
|
|
8459
|
+
if (options.diarization != null) {
|
|
8460
|
+
config.diarization = options.diarization;
|
|
8461
|
+
}
|
|
8462
|
+
if (options.mode != null) {
|
|
8463
|
+
config.mode = options.mode;
|
|
8464
|
+
}
|
|
8465
|
+
return Object.keys(config).length > 0 ? config : void 0;
|
|
8466
|
+
}
|
|
8467
|
+
function buildTranscriptionConfig(options) {
|
|
8468
|
+
var _a;
|
|
8469
|
+
if (options == null) return void 0;
|
|
8470
|
+
const config = {};
|
|
8471
|
+
if (options.languageCodes != null) {
|
|
8472
|
+
config.language_codes = options.languageCodes;
|
|
8473
|
+
}
|
|
8474
|
+
if (options.customVocabulary != null) {
|
|
8475
|
+
config.custom_vocabulary = options.customVocabulary;
|
|
8476
|
+
}
|
|
8477
|
+
if (options.mode != null || options.diarization === true || options.wordTimestamp === true) {
|
|
8478
|
+
config.mode = {
|
|
8479
|
+
type: ((_a = options.mode) != null ? _a : "VERBATIM").toLowerCase(),
|
|
8480
|
+
...options.diarization === true ? { diarization_mode: "speaker" } : {},
|
|
8481
|
+
...options.wordTimestamp === true ? { timestamp_granularities: ["word"] } : {}
|
|
8482
|
+
};
|
|
8483
|
+
}
|
|
8484
|
+
return Object.keys(config).length > 0 ? config : void 0;
|
|
8485
|
+
}
|
|
8486
|
+
function parseOffsetSeconds(offset) {
|
|
8487
|
+
if (offset == null) return void 0;
|
|
8488
|
+
const parsed = Number.parseFloat(offset);
|
|
8489
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
8490
|
+
}
|
|
8491
|
+
function validateLiveInputAudioFormat(inputAudioFormat) {
|
|
8492
|
+
if (inputAudioFormat.type !== "audio/pcm" || inputAudioFormat.rate != null && inputAudioFormat.rate !== 16e3) {
|
|
8493
|
+
throw new InvalidArgumentError2({
|
|
8494
|
+
argument: "inputAudioFormat",
|
|
8495
|
+
message: "The Gemini Live transcription API only supports 16kHz 16-bit PCM input audio."
|
|
8496
|
+
});
|
|
8497
|
+
}
|
|
8498
|
+
}
|
|
8499
|
+
var googleInteractionsWordAnnotationSchema = z23.object({
|
|
8500
|
+
type: z23.string().nullish(),
|
|
8501
|
+
text: z23.string().nullish(),
|
|
8502
|
+
speaker: z23.string().nullish(),
|
|
8503
|
+
start_offset: z23.string().nullish(),
|
|
8504
|
+
end_offset: z23.string().nullish()
|
|
8505
|
+
});
|
|
8506
|
+
var googleInteractionsTranscriptionResponseSchema = z23.object({
|
|
8507
|
+
status: z23.string().nullish(),
|
|
8508
|
+
steps: z23.array(
|
|
8509
|
+
z23.object({
|
|
8510
|
+
type: z23.string().nullish(),
|
|
8511
|
+
content: z23.array(
|
|
8512
|
+
z23.object({
|
|
8513
|
+
type: z23.string().nullish(),
|
|
8514
|
+
text: z23.string().nullish(),
|
|
8515
|
+
annotations: z23.array(googleInteractionsWordAnnotationSchema).nullish()
|
|
8516
|
+
})
|
|
8517
|
+
).nullish()
|
|
8518
|
+
})
|
|
8519
|
+
).nullish(),
|
|
8520
|
+
usage: z23.record(z23.string(), z23.unknown()).nullish()
|
|
8521
|
+
});
|
|
8522
|
+
|
|
8523
|
+
// src/speech-translation/google-speech-translation-model.ts
|
|
8524
|
+
import {
|
|
8525
|
+
InvalidArgumentError as InvalidArgumentError3
|
|
8526
|
+
} from "@ai-sdk/provider";
|
|
8527
|
+
import {
|
|
8528
|
+
connectToWebSocket as connectToWebSocket2,
|
|
8529
|
+
combineHeaders as combineHeaders10,
|
|
8530
|
+
convertBase64ToUint8Array as convertBase64ToUint8Array2,
|
|
8531
|
+
convertToBase64 as convertToBase645,
|
|
8532
|
+
parseProviderOptions as parseProviderOptions9,
|
|
8533
|
+
safeParseJSON as safeParseJSON3,
|
|
8534
|
+
serializeModelOptions as serializeModelOptions7,
|
|
8535
|
+
WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE8,
|
|
8536
|
+
WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE8,
|
|
8537
|
+
waitForWebSocketBufferDrain as waitForWebSocketBufferDrain2
|
|
8032
8538
|
} from "@ai-sdk/provider-utils";
|
|
8033
8539
|
|
|
8034
8540
|
// src/speech-translation/google-speech-translation-model-options.ts
|
|
@@ -8036,26 +8542,26 @@ import {
|
|
|
8036
8542
|
lazySchema as lazySchema20,
|
|
8037
8543
|
zodSchema as zodSchema20
|
|
8038
8544
|
} from "@ai-sdk/provider-utils";
|
|
8039
|
-
import { z as
|
|
8545
|
+
import { z as z24 } from "zod/v4";
|
|
8040
8546
|
var googleSpeechTranslationModelOptions = lazySchema20(
|
|
8041
8547
|
() => zodSchema20(
|
|
8042
|
-
|
|
8548
|
+
z24.object({
|
|
8043
8549
|
/**
|
|
8044
8550
|
* Whether input audio already in the target language should be echoed
|
|
8045
8551
|
* instead of producing silence.
|
|
8046
8552
|
*/
|
|
8047
|
-
echoTargetLanguage:
|
|
8553
|
+
echoTargetLanguage: z24.boolean().optional()
|
|
8048
8554
|
})
|
|
8049
8555
|
)
|
|
8050
8556
|
);
|
|
8051
8557
|
|
|
8052
8558
|
// src/speech-translation/google-speech-translation-model.ts
|
|
8053
|
-
var
|
|
8054
|
-
var
|
|
8559
|
+
var liveWebSocketPath2 = "google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent";
|
|
8560
|
+
var defaultFinishGraceMs2 = 1e3;
|
|
8055
8561
|
var googleLiveOutputAudioRate = 24e3;
|
|
8056
8562
|
var pcm16SilenceAmplitudeThreshold = 128;
|
|
8057
|
-
function
|
|
8058
|
-
const url = getRealtimeWebSocketURL(baseURL,
|
|
8563
|
+
function getLiveWebSocketURL2(baseURL, apiKey) {
|
|
8564
|
+
const url = getRealtimeWebSocketURL(baseURL, liveWebSocketPath2);
|
|
8059
8565
|
url.searchParams.set("key", apiKey);
|
|
8060
8566
|
return url;
|
|
8061
8567
|
}
|
|
@@ -8065,13 +8571,13 @@ var GoogleSpeechTranslationModel = class _GoogleSpeechTranslationModel {
|
|
|
8065
8571
|
this.modelId = modelId;
|
|
8066
8572
|
this.config = config;
|
|
8067
8573
|
}
|
|
8068
|
-
static [
|
|
8069
|
-
return
|
|
8574
|
+
static [WORKFLOW_SERIALIZE8](model) {
|
|
8575
|
+
return serializeModelOptions7({
|
|
8070
8576
|
modelId: model.modelId,
|
|
8071
8577
|
config: model.config
|
|
8072
8578
|
});
|
|
8073
8579
|
}
|
|
8074
|
-
static [
|
|
8580
|
+
static [WORKFLOW_DESERIALIZE8](options) {
|
|
8075
8581
|
return new _GoogleSpeechTranslationModel(options.modelId, options.config);
|
|
8076
8582
|
}
|
|
8077
8583
|
get provider() {
|
|
@@ -8080,13 +8586,13 @@ var GoogleSpeechTranslationModel = class _GoogleSpeechTranslationModel {
|
|
|
8080
8586
|
async doStream(options) {
|
|
8081
8587
|
var _a, _b, _c, _d, _e, _f;
|
|
8082
8588
|
if (options.targetLanguage == null) {
|
|
8083
|
-
throw new
|
|
8589
|
+
throw new InvalidArgumentError3({
|
|
8084
8590
|
argument: "targetLanguage",
|
|
8085
8591
|
message: `targetLanguage is required for translation model '${this.modelId}'.`
|
|
8086
8592
|
});
|
|
8087
8593
|
}
|
|
8088
8594
|
const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
|
|
8089
|
-
const googleOptions = await
|
|
8595
|
+
const googleOptions = await parseProviderOptions9({
|
|
8090
8596
|
provider: "google",
|
|
8091
8597
|
providerOptions: options.providerOptions,
|
|
8092
8598
|
schema: googleSpeechTranslationModelOptions
|
|
@@ -8107,7 +8613,7 @@ var GoogleSpeechTranslationModel = class _GoogleSpeechTranslationModel {
|
|
|
8107
8613
|
details: "The Gemini Live API always outputs 24kHz 16-bit PCM audio and does not accept an output audio format."
|
|
8108
8614
|
});
|
|
8109
8615
|
}
|
|
8110
|
-
const headers =
|
|
8616
|
+
const headers = combineHeaders10(this.config.headers(), options.headers);
|
|
8111
8617
|
let apiKey;
|
|
8112
8618
|
for (const [key, value] of Object.entries(headers)) {
|
|
8113
8619
|
if (key.toLowerCase() === "x-goog-api-key" && value != null) {
|
|
@@ -8137,11 +8643,11 @@ var GoogleSpeechTranslationModel = class _GoogleSpeechTranslationModel {
|
|
|
8137
8643
|
},
|
|
8138
8644
|
stream: createGoogleLiveSpeechTranslationStream({
|
|
8139
8645
|
webSocket: this.config.webSocket,
|
|
8140
|
-
url:
|
|
8646
|
+
url: getLiveWebSocketURL2(this.config.baseURL, apiKey),
|
|
8141
8647
|
headers: webSocketHeaders,
|
|
8142
8648
|
setup,
|
|
8143
8649
|
inputAudioRate: (_d = options.inputAudioFormat.rate) != null ? _d : 16e3,
|
|
8144
|
-
finishGraceMs: (_f = (_e = this.config._internal) == null ? void 0 : _e.finishGraceMs) != null ? _f :
|
|
8650
|
+
finishGraceMs: (_f = (_e = this.config._internal) == null ? void 0 : _e.finishGraceMs) != null ? _f : defaultFinishGraceMs2,
|
|
8145
8651
|
warnings,
|
|
8146
8652
|
audio: options.audio,
|
|
8147
8653
|
abortSignal: options.abortSignal,
|
|
@@ -8170,8 +8676,8 @@ function createGoogleLiveSpeechTranslationStream({
|
|
|
8170
8676
|
let audioReader;
|
|
8171
8677
|
let connection;
|
|
8172
8678
|
let resolveSetupComplete;
|
|
8173
|
-
const setupComplete = new Promise((
|
|
8174
|
-
resolveSetupComplete =
|
|
8679
|
+
const setupComplete = new Promise((resolve8) => {
|
|
8680
|
+
resolveSetupComplete = resolve8;
|
|
8175
8681
|
});
|
|
8176
8682
|
let turnCounter = 0;
|
|
8177
8683
|
let sourceText = "";
|
|
@@ -8266,13 +8772,13 @@ function createGoogleLiveSpeechTranslationStream({
|
|
|
8266
8772
|
JSON.stringify({
|
|
8267
8773
|
realtimeInput: {
|
|
8268
8774
|
audio: {
|
|
8269
|
-
data:
|
|
8775
|
+
data: convertToBase645(value),
|
|
8270
8776
|
mimeType: `audio/pcm;rate=${inputAudioRate}`
|
|
8271
8777
|
}
|
|
8272
8778
|
}
|
|
8273
8779
|
})
|
|
8274
8780
|
);
|
|
8275
|
-
await
|
|
8781
|
+
await waitForWebSocketBufferDrain2(socket);
|
|
8276
8782
|
}
|
|
8277
8783
|
} finally {
|
|
8278
8784
|
audioReader.releaseLock();
|
|
@@ -8288,7 +8794,7 @@ function createGoogleLiveSpeechTranslationStream({
|
|
|
8288
8794
|
}
|
|
8289
8795
|
}
|
|
8290
8796
|
};
|
|
8291
|
-
connection =
|
|
8797
|
+
connection = connectToWebSocket2({
|
|
8292
8798
|
url,
|
|
8293
8799
|
headers,
|
|
8294
8800
|
webSocket,
|
|
@@ -8303,7 +8809,7 @@ function createGoogleLiveSpeechTranslationStream({
|
|
|
8303
8809
|
onMessageText: async (text) => {
|
|
8304
8810
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
8305
8811
|
if (finished) return;
|
|
8306
|
-
const parsed = await
|
|
8812
|
+
const parsed = await safeParseJSON3({ text });
|
|
8307
8813
|
if (!parsed.success) return;
|
|
8308
8814
|
const message = parsed.value;
|
|
8309
8815
|
if (includeRawChunks) {
|
|
@@ -8460,7 +8966,7 @@ function buildGoogleLiveSpeechTranslationSetup({
|
|
|
8460
8966
|
}
|
|
8461
8967
|
function validateGoogleSpeechTranslationInputAudioFormat(inputAudioFormat) {
|
|
8462
8968
|
if (inputAudioFormat.type !== "audio/pcm" || inputAudioFormat.rate != null && inputAudioFormat.rate !== 16e3) {
|
|
8463
|
-
throw new
|
|
8969
|
+
throw new InvalidArgumentError3({
|
|
8464
8970
|
argument: "inputAudioFormat",
|
|
8465
8971
|
message: "The Gemini Live translation API only supports 16kHz 16-bit PCM input audio."
|
|
8466
8972
|
});
|
|
@@ -8585,6 +9091,13 @@ function createGoogle(options = {}) {
|
|
|
8585
9091
|
headers: getHeaders,
|
|
8586
9092
|
fetch: options.fetch
|
|
8587
9093
|
});
|
|
9094
|
+
const createTranscriptionModel = (modelId) => new GoogleTranscriptionModel(modelId, {
|
|
9095
|
+
provider: `${providerName}.transcription`,
|
|
9096
|
+
baseURL,
|
|
9097
|
+
headers: getHeaders,
|
|
9098
|
+
fetch: options.fetch,
|
|
9099
|
+
webSocket: options.webSocket
|
|
9100
|
+
});
|
|
8588
9101
|
const experimentalRealtimeFactory = Object.assign(
|
|
8589
9102
|
(modelId) => createRealtimeModel(modelId),
|
|
8590
9103
|
{
|
|
@@ -8639,6 +9152,8 @@ function createGoogle(options = {}) {
|
|
|
8639
9152
|
provider.files = createFiles;
|
|
8640
9153
|
provider.speech = createSpeechModel;
|
|
8641
9154
|
provider.speechModel = createSpeechModel;
|
|
9155
|
+
provider.transcription = createTranscriptionModel;
|
|
9156
|
+
provider.transcriptionModel = createTranscriptionModel;
|
|
8642
9157
|
provider.translation = createSpeechTranslationModel;
|
|
8643
9158
|
provider.speechTranslationModel = createSpeechTranslationModel;
|
|
8644
9159
|
provider.interactions = createInteractionsModel;
|
|
@@ -8650,6 +9165,7 @@ export {
|
|
|
8650
9165
|
GoogleRealtimeModel as Experimental_GoogleRealtimeModel,
|
|
8651
9166
|
GoogleSpeechTranslationModel as Experimental_GoogleSpeechTranslationModel,
|
|
8652
9167
|
GoogleSpeechTranslationModel as Experimental_GoogleTranslationModel,
|
|
9168
|
+
GoogleTranscriptionModel,
|
|
8653
9169
|
VERSION,
|
|
8654
9170
|
createGoogle,
|
|
8655
9171
|
createGoogle as createGoogleGenerativeAI,
|