@ai-sdk/google 4.0.53 → 4.0.55

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/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.53" : "0.0.0-test";
10
+ var VERSION = true ? "4.0.55" : "0.0.0-test";
11
11
 
12
12
  // src/google-embedding-model.ts
13
13
  import {
@@ -2014,18 +2014,21 @@ var GoogleLanguageModel = class _GoogleLanguageModel {
2014
2014
  warnings,
2015
2015
  providerOptionsNames
2016
2016
  }) {
2017
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
2017
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
2018
2018
  const wrapProviderMetadata = (payload) => Object.fromEntries(
2019
2019
  providerOptionsNames.map((name) => [name, payload])
2020
2020
  );
2021
- const candidate = response.candidates[0];
2021
+ const candidate = (_a = response.candidates) == null ? void 0 : _a[0];
2022
+ const promptBlockReason = (_b = response.promptFeedback) == null ? void 0 : _b.blockReason;
2023
+ const isPromptBlocked = (candidate == null ? void 0 : candidate.finishReason) == null && promptBlockReason != null;
2024
+ const rawFinishReason = (_d = (_c = candidate == null ? void 0 : candidate.finishReason) != null ? _c : promptBlockReason) != null ? _d : void 0;
2022
2025
  const content = [];
2023
- const parts = (_b = (_a = candidate.content) == null ? void 0 : _a.parts) != null ? _b : [];
2026
+ const parts = (_f = (_e = candidate == null ? void 0 : candidate.content) == null ? void 0 : _e.parts) != null ? _f : [];
2024
2027
  const usageMetadata = response.usageMetadata;
2025
2028
  let lastCodeExecutionToolCallId;
2026
2029
  let lastServerToolCallId;
2027
2030
  for (const part of parts) {
2028
- if ("executableCode" in part && ((_c = part.executableCode) == null ? void 0 : _c.code)) {
2031
+ if ("executableCode" in part && ((_g = part.executableCode) == null ? void 0 : _g.code)) {
2029
2032
  const toolCallId = this.config.generateId();
2030
2033
  lastCodeExecutionToolCallId = toolCallId;
2031
2034
  content.push({
@@ -2043,7 +2046,7 @@ var GoogleLanguageModel = class _GoogleLanguageModel {
2043
2046
  toolName: "code_execution",
2044
2047
  result: {
2045
2048
  outcome: part.codeExecutionResult.outcome,
2046
- output: (_d = part.codeExecutionResult.output) != null ? _d : ""
2049
+ output: (_h = part.codeExecutionResult.output) != null ? _h : ""
2047
2050
  }
2048
2051
  });
2049
2052
  } else if ("text" in part && part.text != null) {
@@ -2067,7 +2070,7 @@ var GoogleLanguageModel = class _GoogleLanguageModel {
2067
2070
  type: "tool-call",
2068
2071
  toolCallId: part.functionCall.id || this.config.generateId(),
2069
2072
  toolName: part.functionCall.name,
2070
- input: JSON.stringify((_e = part.functionCall.args) != null ? _e : {}),
2073
+ input: JSON.stringify((_i = part.functionCall.args) != null ? _i : {}),
2071
2074
  providerMetadata: part.thoughtSignature ? wrapProviderMetadata({
2072
2075
  thoughtSignature: part.thoughtSignature
2073
2076
  }) : void 0
@@ -2090,7 +2093,7 @@ var GoogleLanguageModel = class _GoogleLanguageModel {
2090
2093
  type: "tool-call",
2091
2094
  toolCallId,
2092
2095
  toolName: `server:${part.toolCall.toolType}`,
2093
- input: JSON.stringify((_f = part.toolCall.args) != null ? _f : {}),
2096
+ input: JSON.stringify((_j = part.toolCall.args) != null ? _j : {}),
2094
2097
  providerExecuted: true,
2095
2098
  dynamic: true,
2096
2099
  providerMetadata: part.thoughtSignature ? wrapProviderMetadata({
@@ -2108,7 +2111,7 @@ var GoogleLanguageModel = class _GoogleLanguageModel {
2108
2111
  type: "tool-result",
2109
2112
  toolCallId: responseToolCallId,
2110
2113
  toolName: `server:${part.toolResponse.toolType}`,
2111
- result: (_g = part.toolResponse.response) != null ? _g : {},
2114
+ result: (_k = part.toolResponse.response) != null ? _k : {},
2112
2115
  providerMetadata: part.thoughtSignature ? wrapProviderMetadata({
2113
2116
  thoughtSignature: part.thoughtSignature,
2114
2117
  serverToolCallId: responseToolCallId,
@@ -2121,39 +2124,39 @@ var GoogleLanguageModel = class _GoogleLanguageModel {
2121
2124
  lastServerToolCallId = void 0;
2122
2125
  }
2123
2126
  }
2124
- const sources = (_h = extractSources({
2125
- groundingMetadata: candidate.groundingMetadata,
2127
+ const sources = (_l = extractSources({
2128
+ groundingMetadata: candidate == null ? void 0 : candidate.groundingMetadata,
2126
2129
  generateId: this.config.generateId
2127
- })) != null ? _h : [];
2130
+ })) != null ? _l : [];
2128
2131
  for (const source of sources) {
2129
2132
  content.push(source);
2130
2133
  }
2131
2134
  return {
2132
2135
  content,
2133
2136
  finishReason: {
2134
- unified: mapGoogleFinishReason({
2135
- finishReason: candidate.finishReason,
2137
+ unified: isPromptBlocked ? "content-filter" : mapGoogleFinishReason({
2138
+ finishReason: rawFinishReason,
2136
2139
  // Only count client-executed tool calls for finish reason determination.
2137
2140
  hasToolCalls: content.some(
2138
2141
  (part) => part.type === "tool-call" && !part.providerExecuted
2139
2142
  )
2140
2143
  }),
2141
- raw: (_i = candidate.finishReason) != null ? _i : void 0
2144
+ raw: rawFinishReason
2142
2145
  },
2143
2146
  usage: convertGoogleUsage(usageMetadata),
2144
2147
  warnings,
2145
2148
  providerMetadata: wrapProviderMetadata({
2146
- promptFeedback: (_j = response.promptFeedback) != null ? _j : null,
2147
- groundingMetadata: (_k = candidate.groundingMetadata) != null ? _k : null,
2148
- urlContextMetadata: (_l = candidate.urlContextMetadata) != null ? _l : null,
2149
- safetyRatings: (_m = candidate.safetyRatings) != null ? _m : null,
2149
+ promptFeedback: (_m = response.promptFeedback) != null ? _m : null,
2150
+ groundingMetadata: (_n = candidate == null ? void 0 : candidate.groundingMetadata) != null ? _n : null,
2151
+ urlContextMetadata: (_o = candidate == null ? void 0 : candidate.urlContextMetadata) != null ? _o : null,
2152
+ safetyRatings: (_p = candidate == null ? void 0 : candidate.safetyRatings) != null ? _p : null,
2150
2153
  usageMetadata: usageMetadata != null ? usageMetadata : null,
2151
- finishMessage: (_n = candidate.finishMessage) != null ? _n : null,
2152
- serviceTier: (_o = usageMetadata == null ? void 0 : usageMetadata.serviceTier) != null ? _o : null
2154
+ finishMessage: (_q = candidate == null ? void 0 : candidate.finishMessage) != null ? _q : null,
2155
+ serviceTier: (_r = usageMetadata == null ? void 0 : usageMetadata.serviceTier) != null ? _r : null
2153
2156
  }),
2154
2157
  response: {
2155
2158
  // TODO timestamp, model id
2156
- id: (_p = response.responseId) != null ? _p : void 0
2159
+ id: (_s = response.responseId) != null ? _s : void 0
2157
2160
  }
2158
2161
  };
2159
2162
  }
@@ -2268,7 +2271,7 @@ var GoogleLanguageModel = class _GoogleLanguageModel {
2268
2271
  controller.enqueue({ type: "stream-start", warnings });
2269
2272
  },
2270
2273
  transform(chunk, controller) {
2271
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2274
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
2272
2275
  if (options.includeRawChunks) {
2273
2276
  controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
2274
2277
  }
@@ -2290,6 +2293,22 @@ var GoogleLanguageModel = class _GoogleLanguageModel {
2290
2293
  }
2291
2294
  const candidate = (_a = value.candidates) == null ? void 0 : _a[0];
2292
2295
  if (candidate == null) {
2296
+ const promptBlockReason2 = (_b = value.promptFeedback) == null ? void 0 : _b.blockReason;
2297
+ if (promptBlockReason2 != null) {
2298
+ finishReason = {
2299
+ unified: "content-filter",
2300
+ raw: promptBlockReason2
2301
+ };
2302
+ providerMetadata = wrapProviderMetadata({
2303
+ promptFeedback: (_c = value.promptFeedback) != null ? _c : null,
2304
+ groundingMetadata: lastGroundingMetadata,
2305
+ urlContextMetadata: lastUrlContextMetadata,
2306
+ safetyRatings: null,
2307
+ usageMetadata: usageMetadata != null ? usageMetadata : null,
2308
+ finishMessage: null,
2309
+ serviceTier: (_d = usage == null ? void 0 : usage.serviceTier) != null ? _d : null
2310
+ });
2311
+ }
2293
2312
  return;
2294
2313
  }
2295
2314
  const content = candidate.content;
@@ -2312,9 +2331,9 @@ var GoogleLanguageModel = class _GoogleLanguageModel {
2312
2331
  }
2313
2332
  }
2314
2333
  if (content != null) {
2315
- const parts = (_b = content.parts) != null ? _b : [];
2334
+ const parts = (_e = content.parts) != null ? _e : [];
2316
2335
  for (const part of parts) {
2317
- if ("executableCode" in part && ((_c = part.executableCode) == null ? void 0 : _c.code)) {
2336
+ if ("executableCode" in part && ((_f = part.executableCode) == null ? void 0 : _f.code)) {
2318
2337
  const toolCallId = generateId4();
2319
2338
  lastCodeExecutionToolCallId = toolCallId;
2320
2339
  controller.enqueue({
@@ -2333,7 +2352,7 @@ var GoogleLanguageModel = class _GoogleLanguageModel {
2333
2352
  toolName: "code_execution",
2334
2353
  result: {
2335
2354
  outcome: part.codeExecutionResult.outcome,
2336
- output: (_d = part.codeExecutionResult.output) != null ? _d : ""
2355
+ output: (_g = part.codeExecutionResult.output) != null ? _g : ""
2337
2356
  }
2338
2357
  });
2339
2358
  }
@@ -2433,7 +2452,7 @@ var GoogleLanguageModel = class _GoogleLanguageModel {
2433
2452
  type: "tool-call",
2434
2453
  toolCallId,
2435
2454
  toolName: `server:${part.toolCall.toolType}`,
2436
- input: JSON.stringify((_e = part.toolCall.args) != null ? _e : {}),
2455
+ input: JSON.stringify((_h = part.toolCall.args) != null ? _h : {}),
2437
2456
  providerExecuted: true,
2438
2457
  dynamic: true,
2439
2458
  providerMetadata: serverMeta
@@ -2449,7 +2468,7 @@ var GoogleLanguageModel = class _GoogleLanguageModel {
2449
2468
  type: "tool-result",
2450
2469
  toolCallId: responseToolCallId,
2451
2470
  toolName: `server:${part.toolResponse.toolType}`,
2452
- result: (_f = part.toolResponse.response) != null ? _f : {},
2471
+ result: (_i = part.toolResponse.response) != null ? _i : {},
2453
2472
  providerMetadata: serverMeta
2454
2473
  });
2455
2474
  lastServerToolCallId = void 0;
@@ -2516,7 +2535,7 @@ var GoogleLanguageModel = class _GoogleLanguageModel {
2516
2535
  } else if (isCompleteCall) {
2517
2536
  const toolCallId = part.functionCall.id || generateId4();
2518
2537
  const toolName = part.functionCall.name;
2519
- const args2 = typeof part.functionCall.args === "string" ? part.functionCall.args : JSON.stringify((_g = part.functionCall.args) != null ? _g : {});
2538
+ const args2 = typeof part.functionCall.args === "string" ? part.functionCall.args : JSON.stringify((_j = part.functionCall.args) != null ? _j : {});
2520
2539
  controller.enqueue({
2521
2540
  type: "tool-input-start",
2522
2541
  id: toolCallId,
@@ -2567,22 +2586,25 @@ var GoogleLanguageModel = class _GoogleLanguageModel {
2567
2586
  }
2568
2587
  }
2569
2588
  }
2570
- if (candidate.finishReason != null) {
2589
+ const promptBlockReason = (_k = value.promptFeedback) == null ? void 0 : _k.blockReason;
2590
+ const isPromptBlocked = candidate.finishReason == null && promptBlockReason != null;
2591
+ const rawFinishReason = (_m = (_l = candidate.finishReason) != null ? _l : promptBlockReason) != null ? _m : void 0;
2592
+ if (rawFinishReason != null) {
2571
2593
  finishReason = {
2572
- unified: mapGoogleFinishReason({
2573
- finishReason: candidate.finishReason,
2594
+ unified: isPromptBlocked ? "content-filter" : mapGoogleFinishReason({
2595
+ finishReason: rawFinishReason,
2574
2596
  hasToolCalls
2575
2597
  }),
2576
- raw: candidate.finishReason
2598
+ raw: rawFinishReason
2577
2599
  };
2578
2600
  providerMetadata = wrapProviderMetadata({
2579
- promptFeedback: (_h = value.promptFeedback) != null ? _h : null,
2601
+ promptFeedback: (_n = value.promptFeedback) != null ? _n : null,
2580
2602
  groundingMetadata: lastGroundingMetadata,
2581
2603
  urlContextMetadata: lastUrlContextMetadata,
2582
- safetyRatings: (_i = candidate.safetyRatings) != null ? _i : null,
2604
+ safetyRatings: (_o = candidate.safetyRatings) != null ? _o : null,
2583
2605
  usageMetadata: usageMetadata != null ? usageMetadata : null,
2584
- finishMessage: (_j = candidate.finishMessage) != null ? _j : null,
2585
- serviceTier: (_k = usage == null ? void 0 : usage.serviceTier) != null ? _k : null
2606
+ finishMessage: (_p = candidate.finishMessage) != null ? _p : null,
2607
+ serviceTier: (_q = usage == null ? void 0 : usage.serviceTier) != null ? _q : null
2586
2608
  });
2587
2609
  }
2588
2610
  },
@@ -2950,7 +2972,7 @@ var responseSchema = lazySchema5(
2950
2972
  groundingMetadata: getGroundingMetadataSchema().nullish(),
2951
2973
  urlContextMetadata: getUrlContextMetadataSchema().nullish()
2952
2974
  })
2953
- ),
2975
+ ).nullish(),
2954
2976
  usageMetadata: usageSchema.nullish(),
2955
2977
  promptFeedback: z5.object({
2956
2978
  blockReason: z5.string().nullish(),
@@ -8003,21 +8025,538 @@ var GoogleRealtimeModel = class {
8003
8025
  }
8004
8026
  };
8005
8027
 
8006
- // src/speech-translation/google-speech-translation-model.ts
8028
+ // src/transcription/google-transcription-model.ts
8007
8029
  import {
8008
8030
  InvalidArgumentError as InvalidArgumentError2
8009
8031
  } from "@ai-sdk/provider";
8010
8032
  import {
8011
- connectToWebSocket,
8012
8033
  combineHeaders as combineHeaders9,
8013
- convertBase64ToUint8Array as convertBase64ToUint8Array2,
8034
+ connectToWebSocket,
8014
8035
  convertToBase64 as convertToBase644,
8036
+ createJsonResponseHandler as createJsonResponseHandler9,
8015
8037
  parseProviderOptions as parseProviderOptions8,
8038
+ postJsonToApi as postJsonToApi7,
8039
+ resolve as resolve7,
8016
8040
  safeParseJSON as safeParseJSON2,
8017
8041
  serializeModelOptions as serializeModelOptions6,
8042
+ waitForWebSocketBufferDrain,
8018
8043
  WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE7,
8019
- WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE7,
8020
- waitForWebSocketBufferDrain
8044
+ WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE7
8045
+ } from "@ai-sdk/provider-utils";
8046
+ import { z as z23 } from "zod/v4";
8047
+
8048
+ // src/transcription/google-transcription-model-options.ts
8049
+ import { z as z22 } from "zod/v4";
8050
+ var googleTranscriptionModelOptions = z22.object({
8051
+ /**
8052
+ * BCP-47 language codes providing hints about the languages present in the
8053
+ * audio. If omitted or empty, defaults to automatic language detection.
8054
+ */
8055
+ languageCodes: z22.array(z22.string()).optional(),
8056
+ /**
8057
+ * Custom vocabulary phrases, which bias the speech recognition model
8058
+ * toward recognizing specific terms.
8059
+ */
8060
+ customVocabulary: z22.array(z22.string()).optional(),
8061
+ /**
8062
+ * Enables word-level timestamp generation.
8063
+ */
8064
+ wordTimestamp: z22.boolean().optional(),
8065
+ /**
8066
+ * Enables speaker diarization.
8067
+ */
8068
+ diarization: z22.boolean().optional(),
8069
+ /**
8070
+ * Transcription output formatting mode.
8071
+ *
8072
+ * - `VERBATIM` (default): exact literal transcript preserving filler
8073
+ * words, repetitions, and false starts.
8074
+ * - `SMART`: cleans up and structures the transcript in real time —
8075
+ * disfluency removal, inline self-corrections, structured formatting
8076
+ * (lists, numbers, dates, paragraph breaks), and grammar/casing polish.
8077
+ */
8078
+ mode: z22.enum(["SMART", "VERBATIM"]).optional()
8079
+ });
8080
+
8081
+ // src/transcription/google-transcription-model.ts
8082
+ var liveWebSocketPath = "google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent";
8083
+ var defaultFinishGraceMs = 3e3;
8084
+ function getLiveWebSocketURL(baseURL, apiKey) {
8085
+ const url = getRealtimeWebSocketURL(baseURL, liveWebSocketPath);
8086
+ url.searchParams.set("key", apiKey);
8087
+ return url;
8088
+ }
8089
+ function isLiveTranscriptionModelId(modelId) {
8090
+ return modelId.includes("-live");
8091
+ }
8092
+ var GoogleTranscriptionModel = class _GoogleTranscriptionModel {
8093
+ constructor(modelId, config) {
8094
+ this.modelId = modelId;
8095
+ this.config = config;
8096
+ this.specificationVersion = "v4";
8097
+ }
8098
+ static [WORKFLOW_SERIALIZE7](model) {
8099
+ return serializeModelOptions6({
8100
+ modelId: model.modelId,
8101
+ config: model.config
8102
+ });
8103
+ }
8104
+ static [WORKFLOW_DESERIALIZE7](options) {
8105
+ return new _GoogleTranscriptionModel(options.modelId, options.config);
8106
+ }
8107
+ get provider() {
8108
+ return this.config.provider;
8109
+ }
8110
+ async parseOptions(providerOptions) {
8111
+ return parseProviderOptions8({
8112
+ provider: "google",
8113
+ providerOptions,
8114
+ schema: googleTranscriptionModelOptions
8115
+ });
8116
+ }
8117
+ async doGenerate(options) {
8118
+ var _a, _b, _c, _d, _e, _f;
8119
+ if (isLiveTranscriptionModelId(this.modelId)) {
8120
+ throw new InvalidArgumentError2({
8121
+ argument: "modelId",
8122
+ message: `Model '${this.modelId}' only supports streaming transcription. Use experimental_streamTranscribe, or a unary model such as 'gemini-3.5-transcribe'.`
8123
+ });
8124
+ }
8125
+ const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
8126
+ const warnings = [];
8127
+ const googleOptions = await this.parseOptions(options.providerOptions);
8128
+ const transcriptionConfig = buildTranscriptionConfig(googleOptions);
8129
+ const requestBody = {
8130
+ model: this.modelId,
8131
+ input: [
8132
+ {
8133
+ type: "audio",
8134
+ data: convertToBase644(options.audio),
8135
+ mime_type: options.mediaType
8136
+ }
8137
+ ],
8138
+ ...transcriptionConfig != null ? { generation_config: { transcription_config: transcriptionConfig } } : {}
8139
+ };
8140
+ const {
8141
+ value: response,
8142
+ responseHeaders,
8143
+ rawValue: rawResponse
8144
+ } = await postJsonToApi7({
8145
+ url: `${this.config.baseURL}/interactions`,
8146
+ headers: combineHeaders9(
8147
+ this.config.headers ? await resolve7(this.config.headers) : void 0,
8148
+ options.headers
8149
+ ),
8150
+ body: requestBody,
8151
+ failedResponseHandler: googleFailedResponseHandler,
8152
+ successfulResponseHandler: createJsonResponseHandler9(
8153
+ googleInteractionsTranscriptionResponseSchema
8154
+ ),
8155
+ abortSignal: options.abortSignal,
8156
+ fetch: this.config.fetch
8157
+ });
8158
+ let text = "";
8159
+ const segments = [];
8160
+ for (const step of (_d = response.steps) != null ? _d : []) {
8161
+ for (const content of (_e = step.content) != null ? _e : []) {
8162
+ if (content.type !== "text" || content.text == null) continue;
8163
+ text += content.text;
8164
+ for (const annotation of (_f = content.annotations) != null ? _f : []) {
8165
+ if (annotation.type !== "word_info") continue;
8166
+ const startSecond = parseOffsetSeconds(annotation.start_offset);
8167
+ const endSecond = parseOffsetSeconds(annotation.end_offset);
8168
+ if (annotation.text == null || startSecond == null || endSecond == null) {
8169
+ continue;
8170
+ }
8171
+ segments.push({ text: annotation.text, startSecond, endSecond });
8172
+ }
8173
+ }
8174
+ }
8175
+ return {
8176
+ text,
8177
+ segments,
8178
+ language: void 0,
8179
+ durationInSeconds: void 0,
8180
+ warnings,
8181
+ response: {
8182
+ timestamp: currentDate,
8183
+ modelId: this.modelId,
8184
+ headers: responseHeaders,
8185
+ body: rawResponse
8186
+ },
8187
+ ...response.usage != null ? {
8188
+ providerMetadata: {
8189
+ google: { usage: response.usage }
8190
+ }
8191
+ } : {}
8192
+ };
8193
+ }
8194
+ async doStream(options) {
8195
+ var _a, _b, _c, _d, _e, _f, _g;
8196
+ if (!isLiveTranscriptionModelId(this.modelId)) {
8197
+ throw new InvalidArgumentError2({
8198
+ argument: "modelId",
8199
+ message: `Model '${this.modelId}' does not support streaming transcription. Use a live model such as 'gemini-3.5-transcribe-live'.`
8200
+ });
8201
+ }
8202
+ const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
8203
+ const warnings = [];
8204
+ const googleOptions = await this.parseOptions(options.providerOptions);
8205
+ validateLiveInputAudioFormat(options.inputAudioFormat);
8206
+ const headers = combineHeaders9(
8207
+ this.config.headers ? await resolve7(this.config.headers) : void 0,
8208
+ options.headers
8209
+ );
8210
+ let apiKey;
8211
+ for (const [key, value] of Object.entries(headers)) {
8212
+ if (key.toLowerCase() === "x-goog-api-key" && value != null) {
8213
+ apiKey = value;
8214
+ }
8215
+ }
8216
+ if (apiKey == null) {
8217
+ throw new Error(
8218
+ "Google Generative AI API key is required for streaming transcription."
8219
+ );
8220
+ }
8221
+ const webSocketHeaders = Object.fromEntries(
8222
+ Object.entries(headers).filter(
8223
+ ([key]) => key.toLowerCase() !== "x-goog-api-key"
8224
+ )
8225
+ );
8226
+ const setup = {
8227
+ model: getModelPath(this.modelId),
8228
+ inputAudioTranscription: (_d = buildAudioTranscriptionConfig(googleOptions)) != null ? _d : {}
8229
+ };
8230
+ return {
8231
+ request: { body: setup },
8232
+ response: {
8233
+ timestamp: currentDate,
8234
+ modelId: this.modelId
8235
+ },
8236
+ stream: createGoogleLiveTranscriptionStream({
8237
+ webSocket: this.config.webSocket,
8238
+ url: getLiveWebSocketURL(this.config.baseURL, apiKey),
8239
+ headers: webSocketHeaders,
8240
+ setup,
8241
+ inputAudioRate: (_e = options.inputAudioFormat.rate) != null ? _e : 16e3,
8242
+ finishGraceMs: (_g = (_f = this.config._internal) == null ? void 0 : _f.finishGraceMs) != null ? _g : defaultFinishGraceMs,
8243
+ warnings,
8244
+ audio: options.audio,
8245
+ abortSignal: options.abortSignal,
8246
+ includeRawChunks: options.includeRawChunks
8247
+ })
8248
+ };
8249
+ }
8250
+ };
8251
+ function createGoogleLiveTranscriptionStream({
8252
+ webSocket,
8253
+ url,
8254
+ headers,
8255
+ setup,
8256
+ inputAudioRate,
8257
+ finishGraceMs,
8258
+ warnings,
8259
+ audio,
8260
+ abortSignal,
8261
+ includeRawChunks
8262
+ }) {
8263
+ let finished = false;
8264
+ let cleanup = () => {
8265
+ };
8266
+ return new ReadableStream({
8267
+ start: (controller) => {
8268
+ let audioReader;
8269
+ let connection;
8270
+ let resolveSetupComplete;
8271
+ const setupComplete = new Promise((resolve8) => {
8272
+ resolveSetupComplete = resolve8;
8273
+ });
8274
+ let segmentCounter = 0;
8275
+ let segmentBuffer = "";
8276
+ let fullText = "";
8277
+ let latestInterim = "";
8278
+ let language;
8279
+ let audioEnded = false;
8280
+ let usageMetadata;
8281
+ let finishTimer;
8282
+ const segmentId = () => `google-segment-${segmentCounter}`;
8283
+ const cancelPendingFinish = () => {
8284
+ if (finishTimer != null) {
8285
+ clearTimeout(finishTimer);
8286
+ finishTimer = void 0;
8287
+ }
8288
+ };
8289
+ const schedulePendingFinish = () => {
8290
+ if (finished || !audioEnded) return;
8291
+ cancelPendingFinish();
8292
+ finishTimer = setTimeout(() => {
8293
+ finishTimer = void 0;
8294
+ finish();
8295
+ }, finishGraceMs);
8296
+ };
8297
+ cleanup = (closeCode) => {
8298
+ cancelPendingFinish();
8299
+ if (audioReader != null) {
8300
+ void audioReader.cancel().catch(() => {
8301
+ });
8302
+ } else {
8303
+ void audio.cancel().catch(() => {
8304
+ });
8305
+ }
8306
+ connection == null ? void 0 : connection.close(closeCode);
8307
+ };
8308
+ const finishWithError = (error) => {
8309
+ if (finished) return;
8310
+ finished = true;
8311
+ cleanup();
8312
+ controller.error(error);
8313
+ };
8314
+ const completeSegment = () => {
8315
+ if (segmentBuffer === "") {
8316
+ if (latestInterim === "") return;
8317
+ segmentBuffer = latestInterim;
8318
+ }
8319
+ latestInterim = "";
8320
+ controller.enqueue({
8321
+ type: "transcript-final",
8322
+ id: segmentId(),
8323
+ text: segmentBuffer
8324
+ });
8325
+ fullText += fullText === "" ? segmentBuffer : ` ${segmentBuffer}`;
8326
+ segmentBuffer = "";
8327
+ segmentCounter++;
8328
+ };
8329
+ const finish = () => {
8330
+ if (finished) return;
8331
+ completeSegment();
8332
+ finished = true;
8333
+ controller.enqueue({
8334
+ type: "finish",
8335
+ text: fullText,
8336
+ segments: [],
8337
+ language,
8338
+ durationInSeconds: void 0,
8339
+ ...usageMetadata != null ? { providerMetadata: { google: { usageMetadata } } } : {}
8340
+ });
8341
+ controller.close();
8342
+ cleanup(1e3);
8343
+ };
8344
+ const sendAudio = async (socket) => {
8345
+ audioReader = audio.getReader();
8346
+ try {
8347
+ while (true) {
8348
+ const { done, value } = await audioReader.read();
8349
+ if (done || finished) break;
8350
+ socket.send(
8351
+ JSON.stringify({
8352
+ realtimeInput: {
8353
+ audio: {
8354
+ data: convertToBase644(value),
8355
+ mimeType: `audio/pcm;rate=${inputAudioRate}`
8356
+ }
8357
+ }
8358
+ })
8359
+ );
8360
+ await waitForWebSocketBufferDrain(socket);
8361
+ }
8362
+ } finally {
8363
+ audioReader.releaseLock();
8364
+ audioReader = void 0;
8365
+ }
8366
+ if (!finished) {
8367
+ socket.send(
8368
+ JSON.stringify({ realtimeInput: { audioStreamEnd: true } })
8369
+ );
8370
+ audioEnded = true;
8371
+ schedulePendingFinish();
8372
+ }
8373
+ };
8374
+ connection = connectToWebSocket({
8375
+ url,
8376
+ headers,
8377
+ webSocket,
8378
+ abortSignal,
8379
+ onAbort: finishWithError,
8380
+ onProcessingError: finishWithError,
8381
+ onOpen: (socket) => {
8382
+ controller.enqueue({ type: "stream-start", warnings });
8383
+ socket.send(JSON.stringify({ setup }));
8384
+ void setupComplete.then(() => finished ? void 0 : sendAudio(socket)).catch(finishWithError);
8385
+ },
8386
+ onMessageText: async (text) => {
8387
+ var _a, _b;
8388
+ if (finished) return;
8389
+ const parsed = await safeParseJSON2({ text });
8390
+ if (!parsed.success) return;
8391
+ const message = parsed.value;
8392
+ if (includeRawChunks) {
8393
+ controller.enqueue({ type: "raw", rawValue: message });
8394
+ }
8395
+ if (message.setupComplete != null) {
8396
+ resolveSetupComplete();
8397
+ }
8398
+ if (message.usageMetadata != null) {
8399
+ usageMetadata = message.usageMetadata;
8400
+ }
8401
+ if (message.error != null) {
8402
+ finishWithError(
8403
+ new Error((_a = message.error.message) != null ? _a : "Google Live API error")
8404
+ );
8405
+ return;
8406
+ }
8407
+ const serverContent = message.serverContent;
8408
+ const interim = serverContent == null ? void 0 : serverContent.interimInputTranscription;
8409
+ if (interim == null ? void 0 : interim.text) {
8410
+ schedulePendingFinish();
8411
+ latestInterim = interim.text;
8412
+ controller.enqueue({
8413
+ type: "transcript-partial",
8414
+ id: segmentId(),
8415
+ text: interim.text
8416
+ });
8417
+ }
8418
+ const transcription = (_b = serverContent == null ? void 0 : serverContent.inputTranscription) != null ? _b : message.inputTranscription;
8419
+ if (transcription != null) {
8420
+ if (transcription.languageCode != null) {
8421
+ language = transcription.languageCode;
8422
+ }
8423
+ if (transcription.text) {
8424
+ schedulePendingFinish();
8425
+ latestInterim = "";
8426
+ segmentBuffer += transcription.text;
8427
+ controller.enqueue({
8428
+ type: "transcript-delta",
8429
+ id: segmentId(),
8430
+ delta: transcription.text
8431
+ });
8432
+ }
8433
+ if (transcription.finished === true) {
8434
+ completeSegment();
8435
+ }
8436
+ }
8437
+ if (serverContent == null ? void 0 : serverContent.turnComplete) {
8438
+ completeSegment();
8439
+ }
8440
+ const interactionStatus = serverContent == null ? void 0 : serverContent.interactionStatus;
8441
+ if (audioEnded && (interactionStatus === "IDLE" || interactionStatus === "REQUIRES_ACTION" || (serverContent == null ? void 0 : serverContent.turnComplete) === true && interactionStatus == null)) {
8442
+ finish();
8443
+ }
8444
+ },
8445
+ onSocketError: () => {
8446
+ finishWithError(new Error("Google Live transcription error"));
8447
+ },
8448
+ onClose: ({ code, reason }) => {
8449
+ if (finished) return;
8450
+ if (audioEnded) {
8451
+ finish();
8452
+ return;
8453
+ }
8454
+ finishWithError(
8455
+ new Error(
8456
+ `Google Live transcription WebSocket closed unexpectedly before finishing (code ${code != null ? code : "unknown"}${reason ? `, reason: ${reason}` : ""}).`
8457
+ )
8458
+ );
8459
+ }
8460
+ });
8461
+ },
8462
+ cancel: () => {
8463
+ if (finished) return;
8464
+ finished = true;
8465
+ cleanup();
8466
+ }
8467
+ });
8468
+ }
8469
+ function buildAudioTranscriptionConfig(options) {
8470
+ if (options == null) return void 0;
8471
+ const config = {};
8472
+ if (options.languageCodes != null) {
8473
+ config.languageCodes = options.languageCodes;
8474
+ }
8475
+ if (options.customVocabulary != null) {
8476
+ config.customVocabulary = options.customVocabulary;
8477
+ }
8478
+ if (options.wordTimestamp != null) {
8479
+ config.wordTimestamp = options.wordTimestamp;
8480
+ }
8481
+ if (options.diarization != null) {
8482
+ config.diarization = options.diarization;
8483
+ }
8484
+ if (options.mode != null) {
8485
+ config.mode = options.mode;
8486
+ }
8487
+ return Object.keys(config).length > 0 ? config : void 0;
8488
+ }
8489
+ function buildTranscriptionConfig(options) {
8490
+ var _a;
8491
+ if (options == null) return void 0;
8492
+ const config = {};
8493
+ if (options.languageCodes != null) {
8494
+ config.language_codes = options.languageCodes;
8495
+ }
8496
+ if (options.customVocabulary != null) {
8497
+ config.custom_vocabulary = options.customVocabulary;
8498
+ }
8499
+ if (options.mode != null || options.diarization === true || options.wordTimestamp === true) {
8500
+ config.mode = {
8501
+ type: ((_a = options.mode) != null ? _a : "VERBATIM").toLowerCase(),
8502
+ ...options.diarization === true ? { diarization_mode: "speaker" } : {},
8503
+ ...options.wordTimestamp === true ? { timestamp_granularities: ["word"] } : {}
8504
+ };
8505
+ }
8506
+ return Object.keys(config).length > 0 ? config : void 0;
8507
+ }
8508
+ function parseOffsetSeconds(offset) {
8509
+ if (offset == null) return void 0;
8510
+ const parsed = Number.parseFloat(offset);
8511
+ return Number.isFinite(parsed) ? parsed : void 0;
8512
+ }
8513
+ function validateLiveInputAudioFormat(inputAudioFormat) {
8514
+ if (inputAudioFormat.type !== "audio/pcm" || inputAudioFormat.rate != null && inputAudioFormat.rate !== 16e3) {
8515
+ throw new InvalidArgumentError2({
8516
+ argument: "inputAudioFormat",
8517
+ message: "The Gemini Live transcription API only supports 16kHz 16-bit PCM input audio."
8518
+ });
8519
+ }
8520
+ }
8521
+ var googleInteractionsWordAnnotationSchema = z23.object({
8522
+ type: z23.string().nullish(),
8523
+ text: z23.string().nullish(),
8524
+ speaker: z23.string().nullish(),
8525
+ start_offset: z23.string().nullish(),
8526
+ end_offset: z23.string().nullish()
8527
+ });
8528
+ var googleInteractionsTranscriptionResponseSchema = z23.object({
8529
+ status: z23.string().nullish(),
8530
+ steps: z23.array(
8531
+ z23.object({
8532
+ type: z23.string().nullish(),
8533
+ content: z23.array(
8534
+ z23.object({
8535
+ type: z23.string().nullish(),
8536
+ text: z23.string().nullish(),
8537
+ annotations: z23.array(googleInteractionsWordAnnotationSchema).nullish()
8538
+ })
8539
+ ).nullish()
8540
+ })
8541
+ ).nullish(),
8542
+ usage: z23.record(z23.string(), z23.unknown()).nullish()
8543
+ });
8544
+
8545
+ // src/speech-translation/google-speech-translation-model.ts
8546
+ import {
8547
+ InvalidArgumentError as InvalidArgumentError3
8548
+ } from "@ai-sdk/provider";
8549
+ import {
8550
+ connectToWebSocket as connectToWebSocket2,
8551
+ combineHeaders as combineHeaders10,
8552
+ convertBase64ToUint8Array as convertBase64ToUint8Array2,
8553
+ convertToBase64 as convertToBase645,
8554
+ parseProviderOptions as parseProviderOptions9,
8555
+ safeParseJSON as safeParseJSON3,
8556
+ serializeModelOptions as serializeModelOptions7,
8557
+ WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE8,
8558
+ WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE8,
8559
+ waitForWebSocketBufferDrain as waitForWebSocketBufferDrain2
8021
8560
  } from "@ai-sdk/provider-utils";
8022
8561
 
8023
8562
  // src/speech-translation/google-speech-translation-model-options.ts
@@ -8025,26 +8564,26 @@ import {
8025
8564
  lazySchema as lazySchema20,
8026
8565
  zodSchema as zodSchema20
8027
8566
  } from "@ai-sdk/provider-utils";
8028
- import { z as z22 } from "zod/v4";
8567
+ import { z as z24 } from "zod/v4";
8029
8568
  var googleSpeechTranslationModelOptions = lazySchema20(
8030
8569
  () => zodSchema20(
8031
- z22.object({
8570
+ z24.object({
8032
8571
  /**
8033
8572
  * Whether input audio already in the target language should be echoed
8034
8573
  * instead of producing silence.
8035
8574
  */
8036
- echoTargetLanguage: z22.boolean().optional()
8575
+ echoTargetLanguage: z24.boolean().optional()
8037
8576
  })
8038
8577
  )
8039
8578
  );
8040
8579
 
8041
8580
  // src/speech-translation/google-speech-translation-model.ts
8042
- var liveWebSocketPath = "google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent";
8043
- var defaultFinishGraceMs = 1e3;
8581
+ var liveWebSocketPath2 = "google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent";
8582
+ var defaultFinishGraceMs2 = 1e3;
8044
8583
  var googleLiveOutputAudioRate = 24e3;
8045
8584
  var pcm16SilenceAmplitudeThreshold = 128;
8046
- function getLiveWebSocketURL(baseURL, apiKey) {
8047
- const url = getRealtimeWebSocketURL(baseURL, liveWebSocketPath);
8585
+ function getLiveWebSocketURL2(baseURL, apiKey) {
8586
+ const url = getRealtimeWebSocketURL(baseURL, liveWebSocketPath2);
8048
8587
  url.searchParams.set("key", apiKey);
8049
8588
  return url;
8050
8589
  }
@@ -8054,13 +8593,13 @@ var GoogleSpeechTranslationModel = class _GoogleSpeechTranslationModel {
8054
8593
  this.modelId = modelId;
8055
8594
  this.config = config;
8056
8595
  }
8057
- static [WORKFLOW_SERIALIZE7](model) {
8058
- return serializeModelOptions6({
8596
+ static [WORKFLOW_SERIALIZE8](model) {
8597
+ return serializeModelOptions7({
8059
8598
  modelId: model.modelId,
8060
8599
  config: model.config
8061
8600
  });
8062
8601
  }
8063
- static [WORKFLOW_DESERIALIZE7](options) {
8602
+ static [WORKFLOW_DESERIALIZE8](options) {
8064
8603
  return new _GoogleSpeechTranslationModel(options.modelId, options.config);
8065
8604
  }
8066
8605
  get provider() {
@@ -8069,13 +8608,13 @@ var GoogleSpeechTranslationModel = class _GoogleSpeechTranslationModel {
8069
8608
  async doStream(options) {
8070
8609
  var _a, _b, _c, _d, _e, _f;
8071
8610
  if (options.targetLanguage == null) {
8072
- throw new InvalidArgumentError2({
8611
+ throw new InvalidArgumentError3({
8073
8612
  argument: "targetLanguage",
8074
8613
  message: `targetLanguage is required for translation model '${this.modelId}'.`
8075
8614
  });
8076
8615
  }
8077
8616
  const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
8078
- const googleOptions = await parseProviderOptions8({
8617
+ const googleOptions = await parseProviderOptions9({
8079
8618
  provider: "google",
8080
8619
  providerOptions: options.providerOptions,
8081
8620
  schema: googleSpeechTranslationModelOptions
@@ -8096,7 +8635,7 @@ var GoogleSpeechTranslationModel = class _GoogleSpeechTranslationModel {
8096
8635
  details: "The Gemini Live API always outputs 24kHz 16-bit PCM audio and does not accept an output audio format."
8097
8636
  });
8098
8637
  }
8099
- const headers = combineHeaders9(this.config.headers(), options.headers);
8638
+ const headers = combineHeaders10(this.config.headers(), options.headers);
8100
8639
  let apiKey;
8101
8640
  for (const [key, value] of Object.entries(headers)) {
8102
8641
  if (key.toLowerCase() === "x-goog-api-key" && value != null) {
@@ -8126,11 +8665,11 @@ var GoogleSpeechTranslationModel = class _GoogleSpeechTranslationModel {
8126
8665
  },
8127
8666
  stream: createGoogleLiveSpeechTranslationStream({
8128
8667
  webSocket: this.config.webSocket,
8129
- url: getLiveWebSocketURL(this.config.baseURL, apiKey),
8668
+ url: getLiveWebSocketURL2(this.config.baseURL, apiKey),
8130
8669
  headers: webSocketHeaders,
8131
8670
  setup,
8132
8671
  inputAudioRate: (_d = options.inputAudioFormat.rate) != null ? _d : 16e3,
8133
- finishGraceMs: (_f = (_e = this.config._internal) == null ? void 0 : _e.finishGraceMs) != null ? _f : defaultFinishGraceMs,
8672
+ finishGraceMs: (_f = (_e = this.config._internal) == null ? void 0 : _e.finishGraceMs) != null ? _f : defaultFinishGraceMs2,
8134
8673
  warnings,
8135
8674
  audio: options.audio,
8136
8675
  abortSignal: options.abortSignal,
@@ -8159,8 +8698,8 @@ function createGoogleLiveSpeechTranslationStream({
8159
8698
  let audioReader;
8160
8699
  let connection;
8161
8700
  let resolveSetupComplete;
8162
- const setupComplete = new Promise((resolve7) => {
8163
- resolveSetupComplete = resolve7;
8701
+ const setupComplete = new Promise((resolve8) => {
8702
+ resolveSetupComplete = resolve8;
8164
8703
  });
8165
8704
  let turnCounter = 0;
8166
8705
  let sourceText = "";
@@ -8255,13 +8794,13 @@ function createGoogleLiveSpeechTranslationStream({
8255
8794
  JSON.stringify({
8256
8795
  realtimeInput: {
8257
8796
  audio: {
8258
- data: convertToBase644(value),
8797
+ data: convertToBase645(value),
8259
8798
  mimeType: `audio/pcm;rate=${inputAudioRate}`
8260
8799
  }
8261
8800
  }
8262
8801
  })
8263
8802
  );
8264
- await waitForWebSocketBufferDrain(socket);
8803
+ await waitForWebSocketBufferDrain2(socket);
8265
8804
  }
8266
8805
  } finally {
8267
8806
  audioReader.releaseLock();
@@ -8277,7 +8816,7 @@ function createGoogleLiveSpeechTranslationStream({
8277
8816
  }
8278
8817
  }
8279
8818
  };
8280
- connection = connectToWebSocket({
8819
+ connection = connectToWebSocket2({
8281
8820
  url,
8282
8821
  headers,
8283
8822
  webSocket,
@@ -8292,7 +8831,7 @@ function createGoogleLiveSpeechTranslationStream({
8292
8831
  onMessageText: async (text) => {
8293
8832
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
8294
8833
  if (finished) return;
8295
- const parsed = await safeParseJSON2({ text });
8834
+ const parsed = await safeParseJSON3({ text });
8296
8835
  if (!parsed.success) return;
8297
8836
  const message = parsed.value;
8298
8837
  if (includeRawChunks) {
@@ -8449,7 +8988,7 @@ function buildGoogleLiveSpeechTranslationSetup({
8449
8988
  }
8450
8989
  function validateGoogleSpeechTranslationInputAudioFormat(inputAudioFormat) {
8451
8990
  if (inputAudioFormat.type !== "audio/pcm" || inputAudioFormat.rate != null && inputAudioFormat.rate !== 16e3) {
8452
- throw new InvalidArgumentError2({
8991
+ throw new InvalidArgumentError3({
8453
8992
  argument: "inputAudioFormat",
8454
8993
  message: "The Gemini Live translation API only supports 16kHz 16-bit PCM input audio."
8455
8994
  });
@@ -8574,6 +9113,13 @@ function createGoogle(options = {}) {
8574
9113
  headers: getHeaders,
8575
9114
  fetch: options.fetch
8576
9115
  });
9116
+ const createTranscriptionModel = (modelId) => new GoogleTranscriptionModel(modelId, {
9117
+ provider: `${providerName}.transcription`,
9118
+ baseURL,
9119
+ headers: getHeaders,
9120
+ fetch: options.fetch,
9121
+ webSocket: options.webSocket
9122
+ });
8577
9123
  const experimentalRealtimeFactory = Object.assign(
8578
9124
  (modelId) => createRealtimeModel(modelId),
8579
9125
  {
@@ -8628,6 +9174,8 @@ function createGoogle(options = {}) {
8628
9174
  provider.files = createFiles;
8629
9175
  provider.speech = createSpeechModel;
8630
9176
  provider.speechModel = createSpeechModel;
9177
+ provider.transcription = createTranscriptionModel;
9178
+ provider.transcriptionModel = createTranscriptionModel;
8631
9179
  provider.translation = createSpeechTranslationModel;
8632
9180
  provider.speechTranslationModel = createSpeechTranslationModel;
8633
9181
  provider.interactions = createInteractionsModel;
@@ -8639,6 +9187,7 @@ export {
8639
9187
  GoogleRealtimeModel as Experimental_GoogleRealtimeModel,
8640
9188
  GoogleSpeechTranslationModel as Experimental_GoogleSpeechTranslationModel,
8641
9189
  GoogleSpeechTranslationModel as Experimental_GoogleTranslationModel,
9190
+ GoogleTranscriptionModel,
8642
9191
  VERSION,
8643
9192
  createGoogle,
8644
9193
  createGoogle as createGoogleGenerativeAI,