ai 5.0.6 → 5.0.7

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,11 @@
1
1
  # ai
2
2
 
3
+ ## 5.0.7
4
+
5
+ ### Patch Changes
6
+
7
+ - 8e72304: fix (ai): handle invalid tool calls
8
+
3
9
  ## 5.0.6
4
10
 
5
11
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -428,6 +428,8 @@ type StaticToolCall<TOOLS extends ToolSet> = ValueOf<{
428
428
  input: TOOLS[NAME] extends Tool<infer PARAMETERS> ? PARAMETERS : never;
429
429
  providerExecuted?: boolean;
430
430
  dynamic?: false | undefined;
431
+ invalid?: false | undefined;
432
+ error?: never;
431
433
  providerMetadata?: ProviderMetadata;
432
434
  };
433
435
  }>;
@@ -439,6 +441,15 @@ type DynamicToolCall = {
439
441
  providerExecuted?: boolean;
440
442
  dynamic: true;
441
443
  providerMetadata?: ProviderMetadata;
444
+ /**
445
+ * True if this is caused by an unparsable tool call or
446
+ * a tool that does not exist.
447
+ */
448
+ invalid?: boolean;
449
+ /**
450
+ * The error that caused the tool call to be invalid.
451
+ */
452
+ error?: unknown;
442
453
  };
443
454
  type TypedToolCall<TOOLS extends ToolSet> = StaticToolCall<TOOLS> | DynamicToolCall;
444
455
 
@@ -1450,7 +1461,8 @@ type ToolUIPart<TOOLS extends UITools = UITools> = ValueOf<{
1450
1461
  callProviderMetadata?: ProviderMetadata;
1451
1462
  } | {
1452
1463
  state: 'output-error';
1453
- input: TOOLS[NAME]['input'];
1464
+ input: TOOLS[NAME]['input'] | undefined;
1465
+ rawInput?: unknown;
1454
1466
  output?: never;
1455
1467
  errorText: string;
1456
1468
  providerExecuted?: boolean;
@@ -1545,6 +1557,15 @@ type UIMessageChunk<METADATA = unknown, DATA_TYPES extends UIDataTypes = UIDataT
1545
1557
  providerExecuted?: boolean;
1546
1558
  providerMetadata?: ProviderMetadata;
1547
1559
  dynamic?: boolean;
1560
+ } | {
1561
+ type: 'tool-input-error';
1562
+ toolCallId: string;
1563
+ toolName: string;
1564
+ input: unknown;
1565
+ providerExecuted?: boolean;
1566
+ providerMetadata?: ProviderMetadata;
1567
+ dynamic?: boolean;
1568
+ errorText: string;
1548
1569
  } | {
1549
1570
  type: 'tool-output-available';
1550
1571
  toolCallId: string;
package/dist/index.d.ts CHANGED
@@ -428,6 +428,8 @@ type StaticToolCall<TOOLS extends ToolSet> = ValueOf<{
428
428
  input: TOOLS[NAME] extends Tool<infer PARAMETERS> ? PARAMETERS : never;
429
429
  providerExecuted?: boolean;
430
430
  dynamic?: false | undefined;
431
+ invalid?: false | undefined;
432
+ error?: never;
431
433
  providerMetadata?: ProviderMetadata;
432
434
  };
433
435
  }>;
@@ -439,6 +441,15 @@ type DynamicToolCall = {
439
441
  providerExecuted?: boolean;
440
442
  dynamic: true;
441
443
  providerMetadata?: ProviderMetadata;
444
+ /**
445
+ * True if this is caused by an unparsable tool call or
446
+ * a tool that does not exist.
447
+ */
448
+ invalid?: boolean;
449
+ /**
450
+ * The error that caused the tool call to be invalid.
451
+ */
452
+ error?: unknown;
442
453
  };
443
454
  type TypedToolCall<TOOLS extends ToolSet> = StaticToolCall<TOOLS> | DynamicToolCall;
444
455
 
@@ -1450,7 +1461,8 @@ type ToolUIPart<TOOLS extends UITools = UITools> = ValueOf<{
1450
1461
  callProviderMetadata?: ProviderMetadata;
1451
1462
  } | {
1452
1463
  state: 'output-error';
1453
- input: TOOLS[NAME]['input'];
1464
+ input: TOOLS[NAME]['input'] | undefined;
1465
+ rawInput?: unknown;
1454
1466
  output?: never;
1455
1467
  errorText: string;
1456
1468
  providerExecuted?: boolean;
@@ -1545,6 +1557,15 @@ type UIMessageChunk<METADATA = unknown, DATA_TYPES extends UIDataTypes = UIDataT
1545
1557
  providerExecuted?: boolean;
1546
1558
  providerMetadata?: ProviderMetadata;
1547
1559
  dynamic?: boolean;
1560
+ } | {
1561
+ type: 'tool-input-error';
1562
+ toolCallId: string;
1563
+ toolName: string;
1564
+ input: unknown;
1565
+ providerExecuted?: boolean;
1566
+ providerMetadata?: ProviderMetadata;
1567
+ dynamic?: boolean;
1568
+ errorText: string;
1548
1569
  } | {
1549
1570
  type: 'tool-output-available';
1550
1571
  toolCallId: string;
package/dist/index.js CHANGED
@@ -1765,38 +1765,50 @@ async function parseToolCall({
1765
1765
  system,
1766
1766
  messages
1767
1767
  }) {
1768
- if (tools == null) {
1769
- throw new NoSuchToolError({ toolName: toolCall.toolName });
1770
- }
1771
1768
  try {
1772
- return await doParseToolCall({ toolCall, tools });
1773
- } catch (error) {
1774
- if (repairToolCall == null || !(NoSuchToolError.isInstance(error) || InvalidToolInputError.isInstance(error))) {
1775
- throw error;
1769
+ if (tools == null) {
1770
+ throw new NoSuchToolError({ toolName: toolCall.toolName });
1776
1771
  }
1777
- let repairedToolCall = null;
1778
1772
  try {
1779
- repairedToolCall = await repairToolCall({
1780
- toolCall,
1781
- tools,
1782
- inputSchema: ({ toolName }) => {
1783
- const { inputSchema } = tools[toolName];
1784
- return (0, import_provider_utils8.asSchema)(inputSchema).jsonSchema;
1785
- },
1786
- system,
1787
- messages,
1788
- error
1789
- });
1790
- } catch (repairError) {
1791
- throw new ToolCallRepairError({
1792
- cause: repairError,
1793
- originalError: error
1794
- });
1795
- }
1796
- if (repairedToolCall == null) {
1797
- throw error;
1773
+ return await doParseToolCall({ toolCall, tools });
1774
+ } catch (error) {
1775
+ if (repairToolCall == null || !(NoSuchToolError.isInstance(error) || InvalidToolInputError.isInstance(error))) {
1776
+ throw error;
1777
+ }
1778
+ let repairedToolCall = null;
1779
+ try {
1780
+ repairedToolCall = await repairToolCall({
1781
+ toolCall,
1782
+ tools,
1783
+ inputSchema: ({ toolName }) => {
1784
+ const { inputSchema } = tools[toolName];
1785
+ return (0, import_provider_utils8.asSchema)(inputSchema).jsonSchema;
1786
+ },
1787
+ system,
1788
+ messages,
1789
+ error
1790
+ });
1791
+ } catch (repairError) {
1792
+ throw new ToolCallRepairError({
1793
+ cause: repairError,
1794
+ originalError: error
1795
+ });
1796
+ }
1797
+ if (repairedToolCall == null) {
1798
+ throw error;
1799
+ }
1800
+ return await doParseToolCall({ toolCall: repairedToolCall, tools });
1798
1801
  }
1799
- return await doParseToolCall({ toolCall: repairedToolCall, tools });
1802
+ } catch (error) {
1803
+ return {
1804
+ type: "tool-call",
1805
+ toolCallId: toolCall.toolCallId,
1806
+ toolName: toolCall.toolName,
1807
+ input: toolCall.input,
1808
+ dynamic: true,
1809
+ invalid: true,
1810
+ error
1811
+ };
1800
1812
  }
1801
1813
  }
1802
1814
  async function doParseToolCall({
@@ -2246,6 +2258,9 @@ async function generateText({
2246
2258
  )
2247
2259
  );
2248
2260
  for (const toolCall of stepToolCalls) {
2261
+ if (toolCall.invalid) {
2262
+ continue;
2263
+ }
2249
2264
  const tool3 = tools[toolCall.toolName];
2250
2265
  if ((tool3 == null ? void 0 : tool3.onInputAvailable) != null) {
2251
2266
  await tool3.onInputAvailable({
@@ -2257,18 +2272,38 @@ async function generateText({
2257
2272
  });
2258
2273
  }
2259
2274
  }
2275
+ const invalidToolCalls = stepToolCalls.filter(
2276
+ (toolCall) => toolCall.invalid && toolCall.dynamic
2277
+ );
2278
+ clientToolOutputs = [];
2279
+ for (const toolCall of invalidToolCalls) {
2280
+ clientToolOutputs.push({
2281
+ type: "tool-error",
2282
+ toolCallId: toolCall.toolCallId,
2283
+ toolName: toolCall.toolName,
2284
+ input: toolCall.input,
2285
+ error: (0, import_provider_utils9.getErrorMessage)(toolCall.error),
2286
+ dynamic: true
2287
+ });
2288
+ }
2260
2289
  clientToolCalls = stepToolCalls.filter(
2261
- (toolCall) => toolCall.providerExecuted !== true
2290
+ (toolCall) => !toolCall.providerExecuted
2262
2291
  );
2263
- clientToolOutputs = tools == null ? [] : await executeTools({
2264
- toolCalls: clientToolCalls,
2265
- tools,
2266
- tracer,
2267
- telemetry,
2268
- messages: stepInputMessages,
2269
- abortSignal,
2270
- experimental_context
2271
- });
2292
+ if (tools != null) {
2293
+ clientToolOutputs.push(
2294
+ ...await executeTools({
2295
+ toolCalls: clientToolCalls.filter(
2296
+ (toolCall) => !toolCall.invalid
2297
+ ),
2298
+ tools,
2299
+ tracer,
2300
+ telemetry,
2301
+ messages: stepInputMessages,
2302
+ abortSignal,
2303
+ experimental_context
2304
+ })
2305
+ );
2306
+ }
2272
2307
  const stepContent = asContent({
2273
2308
  content: currentModelResponse.content,
2274
2309
  toolCalls: stepToolCalls,
@@ -2760,6 +2795,16 @@ var uiMessageChunkSchema = import_v47.z.union([
2760
2795
  providerMetadata: providerMetadataSchema.optional(),
2761
2796
  dynamic: import_v47.z.boolean().optional()
2762
2797
  }),
2798
+ import_v47.z.strictObject({
2799
+ type: import_v47.z.literal("tool-input-error"),
2800
+ toolCallId: import_v47.z.string(),
2801
+ toolName: import_v47.z.string(),
2802
+ input: import_v47.z.unknown(),
2803
+ providerExecuted: import_v47.z.boolean().optional(),
2804
+ providerMetadata: providerMetadataSchema.optional(),
2805
+ dynamic: import_v47.z.boolean().optional(),
2806
+ errorText: import_v47.z.string()
2807
+ }),
2763
2808
  import_v47.z.strictObject({
2764
2809
  type: import_v47.z.literal("tool-output-available"),
2765
2810
  toolCallId: import_v47.z.string(),
@@ -3299,6 +3344,7 @@ function processUIMessageStream({
3299
3344
  anyPart.input = anyOptions.input;
3300
3345
  anyPart.output = anyOptions.output;
3301
3346
  anyPart.errorText = anyOptions.errorText;
3347
+ anyPart.rawInput = anyOptions.rawInput;
3302
3348
  anyPart.providerExecuted = (_a17 = anyOptions.providerExecuted) != null ? _a17 : part.providerExecuted;
3303
3349
  if (anyOptions.providerMetadata != null && part.state === "input-available") {
3304
3350
  part.callProviderMetadata = anyOptions.providerMetadata;
@@ -3310,6 +3356,7 @@ function processUIMessageStream({
3310
3356
  state: options.state,
3311
3357
  input: anyOptions.input,
3312
3358
  output: anyOptions.output,
3359
+ rawInput: anyOptions.rawInput,
3313
3360
  errorText: anyOptions.errorText,
3314
3361
  providerExecuted: anyOptions.providerExecuted,
3315
3362
  ...anyOptions.providerMetadata != null ? { callProviderMetadata: anyOptions.providerMetadata } : {}
@@ -3317,6 +3364,7 @@ function processUIMessageStream({
3317
3364
  }
3318
3365
  }
3319
3366
  function updateDynamicToolPart(options) {
3367
+ var _a17;
3320
3368
  const part = state.message.parts.find(
3321
3369
  (part2) => part2.type === "dynamic-tool" && part2.toolCallId === options.toolCallId
3322
3370
  );
@@ -3328,6 +3376,7 @@ function processUIMessageStream({
3328
3376
  anyPart.input = anyOptions.input;
3329
3377
  anyPart.output = anyOptions.output;
3330
3378
  anyPart.errorText = anyOptions.errorText;
3379
+ anyPart.rawInput = (_a17 = anyOptions.rawInput) != null ? _a17 : anyPart.rawInput;
3331
3380
  if (anyOptions.providerMetadata != null && part.state === "input-available") {
3332
3381
  part.callProviderMetadata = anyOptions.providerMetadata;
3333
3382
  }
@@ -3521,6 +3570,31 @@ function processUIMessageStream({
3521
3570
  }
3522
3571
  break;
3523
3572
  }
3573
+ case "tool-input-error": {
3574
+ if (chunk.dynamic) {
3575
+ updateDynamicToolPart({
3576
+ toolCallId: chunk.toolCallId,
3577
+ toolName: chunk.toolName,
3578
+ state: "output-error",
3579
+ input: chunk.input,
3580
+ errorText: chunk.errorText,
3581
+ providerMetadata: chunk.providerMetadata
3582
+ });
3583
+ } else {
3584
+ updateToolPart({
3585
+ toolCallId: chunk.toolCallId,
3586
+ toolName: chunk.toolName,
3587
+ state: "output-error",
3588
+ input: void 0,
3589
+ rawInput: chunk.input,
3590
+ errorText: chunk.errorText,
3591
+ providerExecuted: chunk.providerExecuted,
3592
+ providerMetadata: chunk.providerMetadata
3593
+ });
3594
+ }
3595
+ write();
3596
+ break;
3597
+ }
3524
3598
  case "tool-output-available": {
3525
3599
  if (chunk.dynamic) {
3526
3600
  const toolInvocation = getDynamicToolInvocation(
@@ -3566,6 +3640,7 @@ function processUIMessageStream({
3566
3640
  toolName: getToolName(toolInvocation),
3567
3641
  state: "output-error",
3568
3642
  input: toolInvocation.input,
3643
+ rawInput: toolInvocation.rawInput,
3569
3644
  errorText: chunk.errorText
3570
3645
  });
3571
3646
  }
@@ -4015,6 +4090,17 @@ function runToolsTransformation({
4015
4090
  messages
4016
4091
  });
4017
4092
  controller.enqueue(toolCall);
4093
+ if (toolCall.invalid) {
4094
+ toolResultsStreamController.enqueue({
4095
+ type: "tool-error",
4096
+ toolCallId: toolCall.toolCallId,
4097
+ toolName: toolCall.toolName,
4098
+ input: toolCall.input,
4099
+ error: (0, import_provider_utils12.getErrorMessage)(toolCall.error),
4100
+ dynamic: true
4101
+ });
4102
+ break;
4103
+ }
4018
4104
  const tool3 = tools[toolCall.toolName];
4019
4105
  toolInputs.set(toolCall.toolCallId, toolCall.input);
4020
4106
  if (tool3.onInputAvailable != null) {
@@ -4327,6 +4413,7 @@ var DefaultStreamTextResult = class {
4327
4413
  this._steps = new DelayedPromise();
4328
4414
  this.output = output;
4329
4415
  this.includeRawChunks = includeRawChunks;
4416
+ this.tools = tools;
4330
4417
  let stepFinish;
4331
4418
  let recordedContent = [];
4332
4419
  const recordedResponseMessages = [];
@@ -5135,6 +5222,13 @@ var DefaultStreamTextResult = class {
5135
5222
  originalMessages,
5136
5223
  responseMessageId: generateMessageId
5137
5224
  }) : void 0;
5225
+ const toolNamesByCallId = {};
5226
+ const isDynamic = (toolCallId) => {
5227
+ var _a16, _b;
5228
+ const toolName = toolNamesByCallId[toolCallId];
5229
+ const dynamic = ((_b = (_a16 = this.tools) == null ? void 0 : _a16[toolName]) == null ? void 0 : _b.type) === "dynamic";
5230
+ return dynamic ? true : void 0;
5231
+ };
5138
5232
  const baseStream = this.fullStream.pipeThrough(
5139
5233
  new TransformStream({
5140
5234
  transform: async (part, controller) => {
@@ -5224,12 +5318,14 @@ var DefaultStreamTextResult = class {
5224
5318
  break;
5225
5319
  }
5226
5320
  case "tool-input-start": {
5321
+ toolNamesByCallId[part.id] = part.toolName;
5322
+ const dynamic = isDynamic(part.id);
5227
5323
  controller.enqueue({
5228
5324
  type: "tool-input-start",
5229
5325
  toolCallId: part.id,
5230
5326
  toolName: part.toolName,
5231
5327
  ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
5232
- ...part.dynamic != null ? { dynamic: part.dynamic } : {}
5328
+ ...dynamic != null ? { dynamic } : {}
5233
5329
  });
5234
5330
  break;
5235
5331
  }
@@ -5242,34 +5338,51 @@ var DefaultStreamTextResult = class {
5242
5338
  break;
5243
5339
  }
5244
5340
  case "tool-call": {
5245
- controller.enqueue({
5246
- type: "tool-input-available",
5247
- toolCallId: part.toolCallId,
5248
- toolName: part.toolName,
5249
- input: part.input,
5250
- ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
5251
- ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
5252
- ...part.dynamic != null ? { dynamic: part.dynamic } : {}
5253
- });
5341
+ toolNamesByCallId[part.toolCallId] = part.toolName;
5342
+ const dynamic = isDynamic(part.toolCallId);
5343
+ if (part.invalid) {
5344
+ controller.enqueue({
5345
+ type: "tool-input-error",
5346
+ toolCallId: part.toolCallId,
5347
+ toolName: part.toolName,
5348
+ input: part.input,
5349
+ ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
5350
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
5351
+ ...dynamic != null ? { dynamic } : {},
5352
+ errorText: onError(part.error)
5353
+ });
5354
+ } else {
5355
+ controller.enqueue({
5356
+ type: "tool-input-available",
5357
+ toolCallId: part.toolCallId,
5358
+ toolName: part.toolName,
5359
+ input: part.input,
5360
+ ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
5361
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
5362
+ ...dynamic != null ? { dynamic } : {}
5363
+ });
5364
+ }
5254
5365
  break;
5255
5366
  }
5256
5367
  case "tool-result": {
5368
+ const dynamic = isDynamic(part.toolCallId);
5257
5369
  controller.enqueue({
5258
5370
  type: "tool-output-available",
5259
5371
  toolCallId: part.toolCallId,
5260
5372
  output: part.output,
5261
5373
  ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
5262
- ...part.dynamic != null ? { dynamic: part.dynamic } : {}
5374
+ ...dynamic != null ? { dynamic } : {}
5263
5375
  });
5264
5376
  break;
5265
5377
  }
5266
5378
  case "tool-error": {
5379
+ const dynamic = isDynamic(part.toolCallId);
5267
5380
  controller.enqueue({
5268
5381
  type: "tool-output-error",
5269
5382
  toolCallId: part.toolCallId,
5270
5383
  errorText: onError(part.error),
5271
5384
  ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
5272
- ...part.dynamic != null ? { dynamic: part.dynamic } : {}
5385
+ ...dynamic != null ? { dynamic } : {}
5273
5386
  });
5274
5387
  break;
5275
5388
  }
@@ -9292,7 +9405,7 @@ function convertToModelMessages(messages, options) {
9292
9405
  case "assistant": {
9293
9406
  if (message.parts != null) {
9294
9407
  let processBlock2 = function() {
9295
- var _a16;
9408
+ var _a16, _b;
9296
9409
  if (block.length === 0) {
9297
9410
  return;
9298
9411
  }
@@ -9344,7 +9457,7 @@ function convertToModelMessages(messages, options) {
9344
9457
  type: "tool-call",
9345
9458
  toolCallId: part.toolCallId,
9346
9459
  toolName,
9347
- input: part.input,
9460
+ input: part.state === "output-error" ? (_a16 = part.input) != null ? _a16 : part.rawInput : part.input,
9348
9461
  providerExecuted: part.providerExecuted,
9349
9462
  ...part.callProviderMetadata != null ? { providerOptions: part.callProviderMetadata } : {}
9350
9463
  });
@@ -9355,7 +9468,7 @@ function convertToModelMessages(messages, options) {
9355
9468
  toolName,
9356
9469
  output: createToolModelOutput({
9357
9470
  output: part.state === "output-error" ? part.errorText : part.output,
9358
- tool: (_a16 = options == null ? void 0 : options.tools) == null ? void 0 : _a16[toolName],
9471
+ tool: (_b = options == null ? void 0 : options.tools) == null ? void 0 : _b[toolName],
9359
9472
  errorMode: part.state === "output-error" ? "json" : "none"
9360
9473
  })
9361
9474
  });