@ai-sdk/google 4.0.0-beta.31 → 4.0.0-beta.33

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 CHANGED
@@ -1,5 +1,18 @@
1
1
  # @ai-sdk/google
2
2
 
3
+ ## 4.0.0-beta.33
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [3ae1786]
8
+ - @ai-sdk/provider-utils@5.0.0-beta.17
9
+
10
+ ## 4.0.0-beta.32
11
+
12
+ ### Patch Changes
13
+
14
+ - 5036db8: feat(google-vertex): add support for streaming tool arguments input
15
+
3
16
  ## 4.0.0-beta.31
4
17
 
5
18
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -39,6 +39,7 @@ declare const googleLanguageModelOptions: _ai_sdk_provider_utils.LazySchema<{
39
39
  longitude: number;
40
40
  } | undefined;
41
41
  } | undefined;
42
+ streamFunctionCallArguments?: boolean | undefined;
42
43
  serviceTier?: "standard" | "flex" | "priority" | undefined;
43
44
  }>;
44
45
  type GoogleLanguageModelOptions = InferSchema<typeof googleLanguageModelOptions>;
@@ -48,8 +49,17 @@ declare const responseSchema: _ai_sdk_provider_utils.LazySchema<{
48
49
  content?: Record<string, never> | {
49
50
  parts?: ({
50
51
  functionCall: {
51
- name: string;
52
- args: unknown;
52
+ name?: string | null | undefined;
53
+ args?: unknown;
54
+ partialArgs?: {
55
+ jsonPath: string;
56
+ stringValue?: string | null | undefined;
57
+ numberValue?: number | null | undefined;
58
+ boolValue?: boolean | null | undefined;
59
+ nullValue?: unknown;
60
+ willContinue?: boolean | null | undefined;
61
+ }[] | null | undefined;
62
+ willContinue?: boolean | null | undefined;
53
63
  };
54
64
  thoughtSignature?: string | null | undefined;
55
65
  } | {
package/dist/index.d.ts CHANGED
@@ -39,6 +39,7 @@ declare const googleLanguageModelOptions: _ai_sdk_provider_utils.LazySchema<{
39
39
  longitude: number;
40
40
  } | undefined;
41
41
  } | undefined;
42
+ streamFunctionCallArguments?: boolean | undefined;
42
43
  serviceTier?: "standard" | "flex" | "priority" | undefined;
43
44
  }>;
44
45
  type GoogleLanguageModelOptions = InferSchema<typeof googleLanguageModelOptions>;
@@ -48,8 +49,17 @@ declare const responseSchema: _ai_sdk_provider_utils.LazySchema<{
48
49
  content?: Record<string, never> | {
49
50
  parts?: ({
50
51
  functionCall: {
51
- name: string;
52
- args: unknown;
52
+ name?: string | null | undefined;
53
+ args?: unknown;
54
+ partialArgs?: {
55
+ jsonPath: string;
56
+ stringValue?: string | null | undefined;
57
+ numberValue?: number | null | undefined;
58
+ boolValue?: boolean | null | undefined;
59
+ nullValue?: unknown;
60
+ willContinue?: boolean | null | undefined;
61
+ }[] | null | undefined;
62
+ willContinue?: boolean | null | undefined;
53
63
  };
54
64
  thoughtSignature?: string | null | undefined;
55
65
  } | {
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ module.exports = __toCommonJS(index_exports);
30
30
  var import_provider_utils17 = require("@ai-sdk/provider-utils");
31
31
 
32
32
  // src/version.ts
33
- var VERSION = true ? "4.0.0-beta.31" : "0.0.0-test";
33
+ var VERSION = true ? "4.0.0-beta.33" : "0.0.0-test";
34
34
 
35
35
  // src/google-generative-ai-embedding-model.ts
36
36
  var import_provider = require("@ai-sdk/provider");
@@ -869,6 +869,16 @@ var googleLanguageModelOptions = (0, import_provider_utils5.lazySchema)(
869
869
  longitude: import_v44.z.number()
870
870
  }).optional()
871
871
  }).optional(),
872
+ /**
873
+ * Optional. When set to true, function call arguments will be streamed
874
+ * incrementally via partialArgs in streaming responses. Only supported
875
+ * on the Vertex AI API (not the Gemini API).
876
+ *
877
+ * @default true
878
+ *
879
+ * https://docs.cloud.google.com/vertex-ai/generative-ai/docs/multimodal/function-calling#streaming-fc
880
+ */
881
+ streamFunctionCallArguments: import_v44.z.boolean().optional(),
872
882
  /**
873
883
  * Optional. The service tier to use for the request.
874
884
  */
@@ -1127,6 +1137,229 @@ function prepareTools({
1127
1137
  }
1128
1138
  }
1129
1139
 
1140
+ // src/google-json-accumulator.ts
1141
+ var GoogleJSONAccumulator = class {
1142
+ constructor() {
1143
+ this.accumulatedArgs = {};
1144
+ this.jsonText = "";
1145
+ /**
1146
+ * Stack representing the currently "open" containers in the JSON output.
1147
+ * Entry 0 is always the root `{` object once the first value is written.
1148
+ */
1149
+ this.pathStack = [];
1150
+ /**
1151
+ * Whether a string value is currently "open" (willContinue was true),
1152
+ * meaning the closing quote has not yet been emitted.
1153
+ */
1154
+ this.stringOpen = false;
1155
+ }
1156
+ /**
1157
+ * Input: [{jsonPath:"$.brightness",numberValue:50}]
1158
+ * Output: { currentJSON:{brightness:50}, textDelta:'{"brightness":50' }
1159
+ */
1160
+ processPartialArgs(partialArgs) {
1161
+ let delta = "";
1162
+ for (const arg of partialArgs) {
1163
+ const rawPath = arg.jsonPath.replace(/^\$\./, "");
1164
+ if (!rawPath) continue;
1165
+ const segments = parsePath(rawPath);
1166
+ const existingValue = getNestedValue(this.accumulatedArgs, segments);
1167
+ const isStringContinuation = arg.stringValue != null && existingValue !== void 0;
1168
+ if (isStringContinuation) {
1169
+ const escaped = JSON.stringify(arg.stringValue).slice(1, -1);
1170
+ setNestedValue(
1171
+ this.accumulatedArgs,
1172
+ segments,
1173
+ existingValue + arg.stringValue
1174
+ );
1175
+ delta += escaped;
1176
+ continue;
1177
+ }
1178
+ const resolved = resolvePartialArgValue(arg);
1179
+ if (resolved == null) continue;
1180
+ setNestedValue(this.accumulatedArgs, segments, resolved.value);
1181
+ delta += this.emitNavigationTo(segments, arg, resolved.json);
1182
+ }
1183
+ this.jsonText += delta;
1184
+ return {
1185
+ currentJSON: this.accumulatedArgs,
1186
+ textDelta: delta
1187
+ };
1188
+ }
1189
+ /**
1190
+ * Input: jsonText='{"brightness":50', accumulatedArgs={brightness:50}
1191
+ * Output: { finalJSON:'{"brightness":50}', closingDelta:'}' }
1192
+ */
1193
+ finalize() {
1194
+ const finalArgs = JSON.stringify(this.accumulatedArgs);
1195
+ const closingDelta = finalArgs.slice(this.jsonText.length);
1196
+ return { finalJSON: finalArgs, closingDelta };
1197
+ }
1198
+ /**
1199
+ * Input: pathStack=[] (first call) or pathStack=[root,...] (subsequent calls)
1200
+ * Output: '{' (first call) or '' (subsequent calls)
1201
+ */
1202
+ ensureRoot() {
1203
+ if (this.pathStack.length === 0) {
1204
+ this.pathStack.push({ segment: "", isArray: false, childCount: 0 });
1205
+ return "{";
1206
+ }
1207
+ return "";
1208
+ }
1209
+ /**
1210
+ * Emits the JSON text fragment needed to navigate from the current open
1211
+ * path to the new leaf at `targetSegments`, then writes the value.
1212
+ *
1213
+ * Input: targetSegments=["recipe","name"], arg={jsonPath:"$.recipe.name",stringValue:"Lasagna"}, valueJson='"Lasagna"'
1214
+ * Output: '{"recipe":{"name":"Lasagna"'
1215
+ */
1216
+ emitNavigationTo(targetSegments, arg, valueJson) {
1217
+ let fragment = "";
1218
+ if (this.stringOpen) {
1219
+ fragment += '"';
1220
+ this.stringOpen = false;
1221
+ }
1222
+ fragment += this.ensureRoot();
1223
+ const targetContainerSegments = targetSegments.slice(0, -1);
1224
+ const leafSegment = targetSegments[targetSegments.length - 1];
1225
+ const commonDepth = this.findCommonStackDepth(targetContainerSegments);
1226
+ fragment += this.closeDownTo(commonDepth);
1227
+ fragment += this.openDownTo(targetContainerSegments, leafSegment);
1228
+ fragment += this.emitLeaf(leafSegment, arg, valueJson);
1229
+ return fragment;
1230
+ }
1231
+ /**
1232
+ * Returns the stack depth to preserve when navigating to a new target
1233
+ * container path. Always >= 1 (the root is never popped).
1234
+ *
1235
+ * Input: stack=[root,"recipe","ingredients",0], target=["recipe","ingredients",1]
1236
+ * Output: 3 (keep root+"recipe"+"ingredients")
1237
+ */
1238
+ findCommonStackDepth(targetContainer) {
1239
+ const maxDepth = Math.min(
1240
+ this.pathStack.length - 1,
1241
+ targetContainer.length
1242
+ );
1243
+ let common = 0;
1244
+ for (let i = 0; i < maxDepth; i++) {
1245
+ if (this.pathStack[i + 1].segment === targetContainer[i]) {
1246
+ common++;
1247
+ } else {
1248
+ break;
1249
+ }
1250
+ }
1251
+ return common + 1;
1252
+ }
1253
+ /**
1254
+ * Closes containers from the current stack depth back down to `targetDepth`.
1255
+ *
1256
+ * Input: this.pathStack=[root,"recipe","ingredients",0], targetDepth=3
1257
+ * Output: '}'
1258
+ */
1259
+ closeDownTo(targetDepth) {
1260
+ let fragment = "";
1261
+ while (this.pathStack.length > targetDepth) {
1262
+ const entry = this.pathStack.pop();
1263
+ fragment += entry.isArray ? "]" : "}";
1264
+ }
1265
+ return fragment;
1266
+ }
1267
+ /**
1268
+ * Opens containers from the current stack depth down to the full target
1269
+ * container path, emitting opening `{`, `[`, keys, and commas as needed.
1270
+ * `leafSegment` is used to determine if the innermost container is an array.
1271
+ *
1272
+ * Input: this.pathStack=[root], targetContainer=["recipe","ingredients"], leafSegment=0
1273
+ * Output: '"recipe":{"ingredients":['
1274
+ */
1275
+ openDownTo(targetContainer, leafSegment) {
1276
+ let fragment = "";
1277
+ const startIdx = this.pathStack.length - 1;
1278
+ for (let i = startIdx; i < targetContainer.length; i++) {
1279
+ const seg = targetContainer[i];
1280
+ const parentEntry = this.pathStack[this.pathStack.length - 1];
1281
+ if (parentEntry.childCount > 0) {
1282
+ fragment += ",";
1283
+ }
1284
+ parentEntry.childCount++;
1285
+ if (typeof seg === "string") {
1286
+ fragment += `${JSON.stringify(seg)}:`;
1287
+ }
1288
+ const childSeg = i + 1 < targetContainer.length ? targetContainer[i + 1] : leafSegment;
1289
+ const isArray = typeof childSeg === "number";
1290
+ fragment += isArray ? "[" : "{";
1291
+ this.pathStack.push({ segment: seg, isArray, childCount: 0 });
1292
+ }
1293
+ return fragment;
1294
+ }
1295
+ /**
1296
+ * Emits the comma, key, and value for a leaf entry in the current container.
1297
+ *
1298
+ * Input: leafSegment="name", arg={stringValue:"Lasagna"}, valueJson='"Lasagna"'
1299
+ * Output: '"name":"Lasagna"' (or ',"name":"Lasagna"' if container.childCount > 0)
1300
+ */
1301
+ emitLeaf(leafSegment, arg, valueJson) {
1302
+ let fragment = "";
1303
+ const container = this.pathStack[this.pathStack.length - 1];
1304
+ if (container.childCount > 0) {
1305
+ fragment += ",";
1306
+ }
1307
+ container.childCount++;
1308
+ if (typeof leafSegment === "string") {
1309
+ fragment += `${JSON.stringify(leafSegment)}:`;
1310
+ }
1311
+ if (arg.stringValue != null && arg.willContinue) {
1312
+ fragment += valueJson.slice(0, -1);
1313
+ this.stringOpen = true;
1314
+ } else {
1315
+ fragment += valueJson;
1316
+ }
1317
+ return fragment;
1318
+ }
1319
+ };
1320
+ function parsePath(rawPath) {
1321
+ const segments = [];
1322
+ for (const part of rawPath.split(".")) {
1323
+ const bracketIdx = part.indexOf("[");
1324
+ if (bracketIdx === -1) {
1325
+ segments.push(part);
1326
+ } else {
1327
+ if (bracketIdx > 0) segments.push(part.slice(0, bracketIdx));
1328
+ for (const m of part.matchAll(/\[(\d+)\]/g)) {
1329
+ segments.push(parseInt(m[1], 10));
1330
+ }
1331
+ }
1332
+ }
1333
+ return segments;
1334
+ }
1335
+ function getNestedValue(obj, segments) {
1336
+ let current = obj;
1337
+ for (const seg of segments) {
1338
+ if (current == null || typeof current !== "object") return void 0;
1339
+ current = current[seg];
1340
+ }
1341
+ return current;
1342
+ }
1343
+ function setNestedValue(obj, segments, value) {
1344
+ let current = obj;
1345
+ for (let i = 0; i < segments.length - 1; i++) {
1346
+ const seg = segments[i];
1347
+ const nextSeg = segments[i + 1];
1348
+ if (current[seg] == null) {
1349
+ current[seg] = typeof nextSeg === "number" ? [] : {};
1350
+ }
1351
+ current = current[seg];
1352
+ }
1353
+ current[segments[segments.length - 1]] = value;
1354
+ }
1355
+ function resolvePartialArgValue(arg) {
1356
+ var _a, _b;
1357
+ const value = (_b = (_a = arg.stringValue) != null ? _a : arg.numberValue) != null ? _b : arg.boolValue;
1358
+ if (value != null) return { value, json: JSON.stringify(value) };
1359
+ if ("nullValue" in arg) return { value: null, json: "null" };
1360
+ return void 0;
1361
+ }
1362
+
1130
1363
  // src/map-google-generative-ai-finish-reason.ts
1131
1364
  function mapGoogleGenerativeAIFinishReason({
1132
1365
  finishReason,
@@ -1185,7 +1418,7 @@ var GoogleGenerativeAILanguageModel = class {
1185
1418
  reasoning,
1186
1419
  providerOptions
1187
1420
  }) {
1188
- var _a;
1421
+ var _a, _b;
1189
1422
  const warnings = [];
1190
1423
  const providerOptionsName = this.config.provider.includes("vertex") ? "vertex" : "google";
1191
1424
  let googleOptions = await (0, import_provider_utils6.parseProviderOptions)({
@@ -1200,14 +1433,21 @@ var GoogleGenerativeAILanguageModel = class {
1200
1433
  schema: googleLanguageModelOptions
1201
1434
  });
1202
1435
  }
1436
+ const isVertexProvider = this.config.provider.startsWith("google.vertex.");
1203
1437
  if ((tools == null ? void 0 : tools.some(
1204
1438
  (tool) => tool.type === "provider" && tool.id === "google.vertex_rag_store"
1205
- )) && !this.config.provider.startsWith("google.vertex.")) {
1439
+ )) && !isVertexProvider) {
1206
1440
  warnings.push({
1207
1441
  type: "other",
1208
1442
  message: `The 'vertex_rag_store' tool is only supported with the Google Vertex provider and might not be supported or could behave unexpectedly with the current Google provider (${this.config.provider}).`
1209
1443
  });
1210
1444
  }
1445
+ if ((googleOptions == null ? void 0 : googleOptions.streamFunctionCallArguments) && !isVertexProvider) {
1446
+ warnings.push({
1447
+ type: "other",
1448
+ message: `'streamFunctionCallArguments' is only supported on the Vertex AI API and will be ignored with the current Google provider (${this.config.provider}). See https://docs.cloud.google.com/vertex-ai/generative-ai/docs/multimodal/function-calling#streaming-fc`
1449
+ });
1450
+ }
1211
1451
  const isGemmaModel = this.modelId.toLowerCase().startsWith("gemma-");
1212
1452
  const supportsFunctionResponseParts = this.modelId.startsWith("gemini-3");
1213
1453
  const { contents, systemInstruction } = convertToGoogleGenerativeAIMessages(
@@ -1233,6 +1473,19 @@ var GoogleGenerativeAILanguageModel = class {
1233
1473
  warnings
1234
1474
  });
1235
1475
  const thinkingConfig = (googleOptions == null ? void 0 : googleOptions.thinkingConfig) || resolvedThinking ? { ...resolvedThinking, ...googleOptions == null ? void 0 : googleOptions.thinkingConfig } : void 0;
1476
+ const streamFunctionCallArguments = isVertexProvider ? (_a = googleOptions == null ? void 0 : googleOptions.streamFunctionCallArguments) != null ? _a : true : void 0;
1477
+ const toolConfig = googleToolConfig || streamFunctionCallArguments || (googleOptions == null ? void 0 : googleOptions.retrievalConfig) ? {
1478
+ ...googleToolConfig,
1479
+ ...streamFunctionCallArguments && {
1480
+ functionCallingConfig: {
1481
+ ...googleToolConfig == null ? void 0 : googleToolConfig.functionCallingConfig,
1482
+ streamFunctionCallArguments: true
1483
+ }
1484
+ },
1485
+ ...(googleOptions == null ? void 0 : googleOptions.retrievalConfig) && {
1486
+ retrievalConfig: googleOptions.retrievalConfig
1487
+ }
1488
+ } : void 0;
1236
1489
  return {
1237
1490
  args: {
1238
1491
  generationConfig: {
@@ -1250,7 +1503,7 @@ var GoogleGenerativeAILanguageModel = class {
1250
1503
  responseSchema: (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && // Google GenAI does not support all OpenAPI Schema features,
1251
1504
  // so this is needed as an escape hatch:
1252
1505
  // TODO convert into provider option
1253
- ((_a = googleOptions == null ? void 0 : googleOptions.structuredOutputs) != null ? _a : true) ? convertJSONSchemaToOpenAPISchema(responseFormat.schema) : void 0,
1506
+ ((_b = googleOptions == null ? void 0 : googleOptions.structuredOutputs) != null ? _b : true) ? convertJSONSchemaToOpenAPISchema(responseFormat.schema) : void 0,
1254
1507
  ...(googleOptions == null ? void 0 : googleOptions.audioTimestamp) && {
1255
1508
  audioTimestamp: googleOptions.audioTimestamp
1256
1509
  },
@@ -1268,10 +1521,7 @@ var GoogleGenerativeAILanguageModel = class {
1268
1521
  systemInstruction: isGemmaModel ? void 0 : systemInstruction,
1269
1522
  safetySettings: googleOptions == null ? void 0 : googleOptions.safetySettings,
1270
1523
  tools: googleTools2,
1271
- toolConfig: (googleOptions == null ? void 0 : googleOptions.retrievalConfig) ? {
1272
- ...googleToolConfig,
1273
- retrievalConfig: googleOptions.retrievalConfig
1274
- } : googleToolConfig,
1524
+ toolConfig,
1275
1525
  cachedContent: googleOptions == null ? void 0 : googleOptions.cachedContent,
1276
1526
  labels: googleOptions == null ? void 0 : googleOptions.labels,
1277
1527
  serviceTier: googleOptions == null ? void 0 : googleOptions.serviceTier
@@ -1349,7 +1599,7 @@ var GoogleGenerativeAILanguageModel = class {
1349
1599
  providerMetadata: thoughtSignatureMetadata
1350
1600
  });
1351
1601
  }
1352
- } else if ("functionCall" in part) {
1602
+ } else if ("functionCall" in part && part.functionCall.name != null && part.functionCall.args != null) {
1353
1603
  content.push({
1354
1604
  type: "tool-call",
1355
1605
  toolCallId: this.config.generateId(),
@@ -1494,6 +1744,7 @@ var GoogleGenerativeAILanguageModel = class {
1494
1744
  const emittedSourceUrls = /* @__PURE__ */ new Set();
1495
1745
  let lastCodeExecutionToolCallId;
1496
1746
  let lastServerToolCallId;
1747
+ const activeStreamingToolCalls = [];
1497
1748
  return {
1498
1749
  stream: response.pipeThrough(
1499
1750
  new TransformStream({
@@ -1501,7 +1752,7 @@ var GoogleGenerativeAILanguageModel = class {
1501
1752
  controller.enqueue({ type: "stream-start", warnings });
1502
1753
  },
1503
1754
  transform(chunk, controller) {
1504
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
1755
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
1505
1756
  if (options.includeRawChunks) {
1506
1757
  controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
1507
1758
  }
@@ -1693,36 +1944,110 @@ var GoogleGenerativeAILanguageModel = class {
1693
1944
  lastServerToolCallId = void 0;
1694
1945
  }
1695
1946
  }
1696
- const toolCallDeltas = getToolCallsFromParts({
1697
- parts: content.parts,
1698
- generateId: generateId3,
1699
- providerOptionsName
1700
- });
1701
- if (toolCallDeltas != null) {
1702
- for (const toolCall of toolCallDeltas) {
1947
+ for (const part of parts) {
1948
+ if (!("functionCall" in part)) continue;
1949
+ const providerMeta = part.thoughtSignature ? {
1950
+ [providerOptionsName]: {
1951
+ thoughtSignature: part.thoughtSignature
1952
+ }
1953
+ } : void 0;
1954
+ const isStreamingChunk = part.functionCall.partialArgs != null || part.functionCall.name != null && part.functionCall.willContinue === true;
1955
+ const isTerminalChunk = part.functionCall.name == null && part.functionCall.args == null && part.functionCall.partialArgs == null && part.functionCall.willContinue == null;
1956
+ const isCompleteCall = part.functionCall.name != null && part.functionCall.args != null && part.functionCall.partialArgs == null;
1957
+ if (isStreamingChunk) {
1958
+ if (part.functionCall.name != null && part.functionCall.willContinue === true) {
1959
+ const toolCallId = generateId3();
1960
+ const accumulator = new GoogleJSONAccumulator();
1961
+ activeStreamingToolCalls.push({
1962
+ toolCallId,
1963
+ toolName: part.functionCall.name,
1964
+ accumulator,
1965
+ providerMetadata: providerMeta
1966
+ });
1967
+ controller.enqueue({
1968
+ type: "tool-input-start",
1969
+ id: toolCallId,
1970
+ toolName: part.functionCall.name,
1971
+ providerMetadata: providerMeta
1972
+ });
1973
+ if (part.functionCall.partialArgs != null) {
1974
+ const { textDelta } = accumulator.processPartialArgs(
1975
+ part.functionCall.partialArgs
1976
+ );
1977
+ if (textDelta.length > 0) {
1978
+ controller.enqueue({
1979
+ type: "tool-input-delta",
1980
+ id: toolCallId,
1981
+ delta: textDelta,
1982
+ providerMetadata: providerMeta
1983
+ });
1984
+ }
1985
+ }
1986
+ } else if (part.functionCall.partialArgs != null && activeStreamingToolCalls.length > 0) {
1987
+ const active = activeStreamingToolCalls[activeStreamingToolCalls.length - 1];
1988
+ const { textDelta } = active.accumulator.processPartialArgs(
1989
+ part.functionCall.partialArgs
1990
+ );
1991
+ if (textDelta.length > 0) {
1992
+ controller.enqueue({
1993
+ type: "tool-input-delta",
1994
+ id: active.toolCallId,
1995
+ delta: textDelta,
1996
+ providerMetadata: providerMeta
1997
+ });
1998
+ }
1999
+ }
2000
+ } else if (isTerminalChunk && activeStreamingToolCalls.length > 0) {
2001
+ const active = activeStreamingToolCalls.pop();
2002
+ const { finalJSON, closingDelta } = active.accumulator.finalize();
2003
+ if (closingDelta.length > 0) {
2004
+ controller.enqueue({
2005
+ type: "tool-input-delta",
2006
+ id: active.toolCallId,
2007
+ delta: closingDelta,
2008
+ providerMetadata: active.providerMetadata
2009
+ });
2010
+ }
2011
+ controller.enqueue({
2012
+ type: "tool-input-end",
2013
+ id: active.toolCallId,
2014
+ providerMetadata: active.providerMetadata
2015
+ });
2016
+ controller.enqueue({
2017
+ type: "tool-call",
2018
+ toolCallId: active.toolCallId,
2019
+ toolName: active.toolName,
2020
+ input: finalJSON,
2021
+ providerMetadata: active.providerMetadata
2022
+ });
2023
+ hasToolCalls = true;
2024
+ } else if (isCompleteCall) {
2025
+ const toolCallId = generateId3();
2026
+ const toolName = part.functionCall.name;
2027
+ const args2 = typeof part.functionCall.args === "string" ? part.functionCall.args : JSON.stringify((_i = part.functionCall.args) != null ? _i : {});
1703
2028
  controller.enqueue({
1704
2029
  type: "tool-input-start",
1705
- id: toolCall.toolCallId,
1706
- toolName: toolCall.toolName,
1707
- providerMetadata: toolCall.providerMetadata
2030
+ id: toolCallId,
2031
+ toolName,
2032
+ providerMetadata: providerMeta
1708
2033
  });
1709
2034
  controller.enqueue({
1710
2035
  type: "tool-input-delta",
1711
- id: toolCall.toolCallId,
1712
- delta: toolCall.args,
1713
- providerMetadata: toolCall.providerMetadata
2036
+ id: toolCallId,
2037
+ delta: args2,
2038
+ providerMetadata: providerMeta
1714
2039
  });
1715
2040
  controller.enqueue({
1716
2041
  type: "tool-input-end",
1717
- id: toolCall.toolCallId,
1718
- providerMetadata: toolCall.providerMetadata
2042
+ id: toolCallId,
2043
+ providerMetadata: providerMeta
1719
2044
  });
1720
2045
  controller.enqueue({
1721
2046
  type: "tool-call",
1722
- toolCallId: toolCall.toolCallId,
1723
- toolName: toolCall.toolName,
1724
- input: toolCall.args,
1725
- providerMetadata: toolCall.providerMetadata
2047
+ toolCallId,
2048
+ toolName,
2049
+ input: args2,
2050
+ providerMetadata: providerMeta
1726
2051
  });
1727
2052
  hasToolCalls = true;
1728
2053
  }
@@ -1738,12 +2063,12 @@ var GoogleGenerativeAILanguageModel = class {
1738
2063
  };
1739
2064
  providerMetadata = {
1740
2065
  [providerOptionsName]: {
1741
- promptFeedback: (_i = value.promptFeedback) != null ? _i : null,
2066
+ promptFeedback: (_j = value.promptFeedback) != null ? _j : null,
1742
2067
  groundingMetadata: lastGroundingMetadata,
1743
2068
  urlContextMetadata: lastUrlContextMetadata,
1744
- safetyRatings: (_j = candidate.safetyRatings) != null ? _j : null,
2069
+ safetyRatings: (_k = candidate.safetyRatings) != null ? _k : null,
1745
2070
  usageMetadata: usageMetadata != null ? usageMetadata : null,
1746
- finishMessage: (_k = candidate.finishMessage) != null ? _k : null,
2071
+ finishMessage: (_l = candidate.finishMessage) != null ? _l : null,
1747
2072
  serviceTier
1748
2073
  }
1749
2074
  };
@@ -1845,26 +2170,6 @@ function resolveGemini25ThinkingConfig({
1845
2170
  }
1846
2171
  return { thinkingBudget };
1847
2172
  }
1848
- function getToolCallsFromParts({
1849
- parts,
1850
- generateId: generateId3,
1851
- providerOptionsName
1852
- }) {
1853
- const functionCallParts = parts == null ? void 0 : parts.filter(
1854
- (part) => "functionCall" in part
1855
- );
1856
- return functionCallParts == null || functionCallParts.length === 0 ? void 0 : functionCallParts.map((part) => ({
1857
- type: "tool-call",
1858
- toolCallId: generateId3(),
1859
- toolName: part.functionCall.name,
1860
- args: JSON.stringify(part.functionCall.args),
1861
- providerMetadata: part.thoughtSignature ? {
1862
- [providerOptionsName]: {
1863
- thoughtSignature: part.thoughtSignature
1864
- }
1865
- } : void 0
1866
- }));
1867
- }
1868
2173
  function extractSources({
1869
2174
  groundingMetadata,
1870
2175
  generateId: generateId3
@@ -2008,14 +2313,24 @@ var getGroundingMetadataSchema = () => import_v45.z.object({
2008
2313
  import_v45.z.object({})
2009
2314
  ]).nullish()
2010
2315
  });
2316
+ var partialArgSchema = import_v45.z.object({
2317
+ jsonPath: import_v45.z.string(),
2318
+ stringValue: import_v45.z.string().nullish(),
2319
+ numberValue: import_v45.z.number().nullish(),
2320
+ boolValue: import_v45.z.boolean().nullish(),
2321
+ nullValue: import_v45.z.unknown().nullish(),
2322
+ willContinue: import_v45.z.boolean().nullish()
2323
+ });
2011
2324
  var getContentSchema = () => import_v45.z.object({
2012
2325
  parts: import_v45.z.array(
2013
2326
  import_v45.z.union([
2014
2327
  // note: order matters since text can be fully empty
2015
2328
  import_v45.z.object({
2016
2329
  functionCall: import_v45.z.object({
2017
- name: import_v45.z.string(),
2018
- args: import_v45.z.unknown()
2330
+ name: import_v45.z.string().nullish(),
2331
+ args: import_v45.z.unknown().nullish(),
2332
+ partialArgs: import_v45.z.array(partialArgSchema).nullish(),
2333
+ willContinue: import_v45.z.boolean().nullish()
2019
2334
  }),
2020
2335
  thoughtSignature: import_v45.z.string().nullish()
2021
2336
  }),