@ai-sdk-tool/parser 4.1.20 → 4.1.21

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.
@@ -5,7 +5,7 @@ import {
5
5
  parse as parse2,
6
6
  stringify,
7
7
  unescapeXml
8
- } from "./chunk-TLZV6QE3.js";
8
+ } from "./chunk-NU2CVJEB.js";
9
9
  import {
10
10
  parse
11
11
  } from "./chunk-KLP3RUJ2.js";
@@ -482,13 +482,312 @@ function shouldEmitRawToolCallTextOnError(options) {
482
482
  }
483
483
 
484
484
  // src/core/protocols/hermes-protocol.ts
485
+ var RJSON_IDENTIFIER_CHAR_REGEX = /[$a-zA-Z0-9_\-+.*?!|&%^/#\\]/;
486
+ var RJSON_NUMBER_TOKEN_REGEX = /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
487
+ function validateNonEmptyDelimiters(toolCallStart, toolCallEnd) {
488
+ if (toolCallStart.length === 0) {
489
+ throw new TypeError("hermesProtocol toolCallStart must not be empty");
490
+ }
491
+ if (toolCallEnd.length === 0) {
492
+ throw new TypeError("hermesProtocol toolCallEnd must not be empty");
493
+ }
494
+ return {};
495
+ }
496
+ function isRjsonIdentifierChar(ch) {
497
+ return ch != null && RJSON_IDENTIFIER_CHAR_REGEX.test(ch);
498
+ }
499
+ function isRjsonPropertyLikeDelimiter(startTag) {
500
+ const key = startTag.endsWith(":") ? startTag.slice(0, -1) : "";
501
+ return key.length > 0 && [...key].every((ch) => isRjsonIdentifierChar(ch));
502
+ }
503
+ function previousRjsonToken(json, index, minIndex = 0) {
504
+ let start = index - 1;
505
+ while (start >= minIndex && isRjsonIdentifierChar(json[start])) {
506
+ start -= 1;
507
+ }
508
+ return json.slice(start + 1, index);
509
+ }
510
+ function previousTokenAllowsComment(json, index, minIndex = 0) {
511
+ const previous = previousRjsonToken(json, index, minIndex);
512
+ if (previous.length === 0) {
513
+ return true;
514
+ }
515
+ return RJSON_NUMBER_TOKEN_REGEX.test(previous) || previous === "true" || previous === "false" || previous === "null";
516
+ }
517
+ function startsRjsonComment(json, index, minIndex = 0) {
518
+ if (!(json[index] === "/" && json[index + 1] === "/" || json[index] === "/" && json[index + 1] === "*")) {
519
+ return false;
520
+ }
521
+ if (index > minIndex && isRjsonIdentifierChar(json[index - 1])) {
522
+ return previousTokenAllowsComment(json, index, minIndex);
523
+ }
524
+ return true;
525
+ }
526
+ function hasNestedStartBoundary(segment, startIndex) {
527
+ const previous = segment[startIndex - 1];
528
+ return previous == null || WHITESPACE_JSON_REGEX.test(previous) || previous === "}";
529
+ }
530
+ function isLikelyNestedToolCallStart(segment, startIndex, startTag) {
531
+ if (isRjsonPropertyLikeDelimiter(startTag)) {
532
+ return false;
533
+ }
534
+ const jsonStart = skipJsonWhitespace(segment, startIndex + startTag.length);
535
+ return segment[jsonStart] === "{" && hasNestedStartBoundary(segment, startIndex);
536
+ }
537
+ function findToolCallBoundaryOutsideRjsonSyntax(text, scanFrom, startTag, endTag) {
538
+ let quote = null;
539
+ let esc = false;
540
+ let inLineComment = false;
541
+ let inBlockComment = false;
542
+ let lineCommentSawEndTag = false;
543
+ let blockCommentSawEndTag = false;
544
+ let nestedStartIndex = null;
545
+ for (let index = scanFrom; index < text.length; index += 1) {
546
+ const ch = text[index];
547
+ if (esc) {
548
+ esc = false;
549
+ continue;
550
+ }
551
+ if (quote !== null) {
552
+ if (ch === "\\") {
553
+ esc = true;
554
+ continue;
555
+ }
556
+ if (ch === quote) {
557
+ quote = null;
558
+ }
559
+ continue;
560
+ }
561
+ if (inLineComment) {
562
+ if (ch === "\n" || ch === "\r") {
563
+ inLineComment = false;
564
+ lineCommentSawEndTag = false;
565
+ continue;
566
+ }
567
+ if (text.startsWith(endTag, index)) {
568
+ lineCommentSawEndTag = true;
569
+ index += endTag.length - 1;
570
+ continue;
571
+ }
572
+ if (lineCommentSawEndTag && text.startsWith(startTag, index) && text[skipJsonWhitespace(text, index + startTag.length)] === "{") {
573
+ nestedStartIndex = index;
574
+ inLineComment = false;
575
+ lineCommentSawEndTag = false;
576
+ index += startTag.length - 1;
577
+ continue;
578
+ }
579
+ continue;
580
+ }
581
+ if (inBlockComment) {
582
+ if (ch === "*" && text[index + 1] === "/") {
583
+ inBlockComment = false;
584
+ blockCommentSawEndTag = false;
585
+ index += 1;
586
+ continue;
587
+ }
588
+ if (text.startsWith(endTag, index)) {
589
+ blockCommentSawEndTag = true;
590
+ index += endTag.length - 1;
591
+ continue;
592
+ }
593
+ if (blockCommentSawEndTag && text.startsWith(startTag, index) && text[skipJsonWhitespace(text, index + startTag.length)] === "{") {
594
+ nestedStartIndex = index;
595
+ inBlockComment = false;
596
+ blockCommentSawEndTag = false;
597
+ index += startTag.length - 1;
598
+ continue;
599
+ }
600
+ continue;
601
+ }
602
+ if (startsRjsonComment(text, index, scanFrom)) {
603
+ if (text[index + 1] === "/") {
604
+ inLineComment = true;
605
+ lineCommentSawEndTag = false;
606
+ index += 1;
607
+ continue;
608
+ }
609
+ if (text[index + 1] === "*") {
610
+ inBlockComment = true;
611
+ blockCommentSawEndTag = false;
612
+ index += 1;
613
+ continue;
614
+ }
615
+ }
616
+ if (text.startsWith(endTag, index)) {
617
+ return nestedStartIndex == null ? { kind: "end", endIdx: index } : { kind: "nested", endIdx: index, nestedStartIndex };
618
+ }
619
+ if (nestedStartIndex == null && text.startsWith(startTag, index) && isLikelyNestedToolCallStart(text, index, startTag)) {
620
+ nestedStartIndex = index;
621
+ index += startTag.length - 1;
622
+ continue;
623
+ }
624
+ if (ch === '"' || ch === "'") {
625
+ quote = ch;
626
+ }
627
+ }
628
+ return null;
629
+ }
630
+ function findNextToolCallSpan(text, searchFrom, startTag, endTag) {
631
+ const startIdx = text.indexOf(startTag, searchFrom);
632
+ if (startIdx === -1) {
633
+ return null;
634
+ }
635
+ const jsonStart = startIdx + startTag.length;
636
+ const boundary = findToolCallBoundaryOutsideRjsonSyntax(
637
+ text,
638
+ jsonStart,
639
+ startTag,
640
+ endTag
641
+ );
642
+ if (boundary == null) {
643
+ return { startIdx, found: false };
644
+ }
645
+ if (boundary.kind === "nested") {
646
+ return { startIdx, found: false };
647
+ }
648
+ return { startIdx, found: true, jsonStart, endIdx: boundary.endIdx };
649
+ }
485
650
  function canonicalizeToolInput(argumentsValue) {
486
651
  return JSON.stringify(argumentsValue != null ? argumentsValue : {});
487
652
  }
653
+ var CHAR_CODE_BACKSLASH = 92;
654
+ var CHAR_CODE_QUOTE = 34;
655
+ var CHAR_CODE_LF = 10;
656
+ var CHAR_CODE_CR = 13;
657
+ var CHAR_CODE_TAB = 9;
658
+ var CHAR_CODE_SLASH = 47;
659
+ var CHAR_CODE_STAR = 42;
660
+ var CHAR_CODE_CONTROL_UPPER = 31;
661
+ var CHAR_CODE_SINGLE_QUOTE = 39;
662
+ function hasControlCharInString(json) {
663
+ let quote = null;
664
+ let esc = false;
665
+ for (let i = 0; i < json.length; i += 1) {
666
+ const code = json.charCodeAt(i);
667
+ if (esc) {
668
+ esc = false;
669
+ if (code <= CHAR_CODE_CONTROL_UPPER) {
670
+ return true;
671
+ }
672
+ continue;
673
+ }
674
+ if (quote !== null && code === CHAR_CODE_BACKSLASH) {
675
+ esc = true;
676
+ continue;
677
+ }
678
+ if (quote !== null) {
679
+ if (code === quote) {
680
+ quote = null;
681
+ continue;
682
+ }
683
+ if (code <= CHAR_CODE_CONTROL_UPPER) {
684
+ return true;
685
+ }
686
+ continue;
687
+ }
688
+ if (code === CHAR_CODE_SLASH && json.charCodeAt(i + 1) === CHAR_CODE_SLASH) {
689
+ i += 2;
690
+ while (i < json.length && json.charCodeAt(i) !== CHAR_CODE_LF && json.charCodeAt(i) !== CHAR_CODE_CR) {
691
+ i += 1;
692
+ }
693
+ continue;
694
+ }
695
+ if (code === CHAR_CODE_SLASH && json.charCodeAt(i + 1) === CHAR_CODE_STAR) {
696
+ i += 2;
697
+ while (i + 1 < json.length && !(json.charCodeAt(i) === CHAR_CODE_STAR && json.charCodeAt(i + 1) === CHAR_CODE_SLASH)) {
698
+ i += 1;
699
+ }
700
+ i += 1;
701
+ continue;
702
+ }
703
+ if (code === CHAR_CODE_QUOTE || code === CHAR_CODE_SINGLE_QUOTE) {
704
+ quote = code;
705
+ }
706
+ }
707
+ return false;
708
+ }
709
+ function normalizeJsonStringCtrl(json) {
710
+ if (!hasControlCharInString(json)) {
711
+ return json;
712
+ }
713
+ const parts = [];
714
+ let chunkStart = 0;
715
+ let quote = null;
716
+ let esc = false;
717
+ const flushUpTo = (end) => {
718
+ if (chunkStart < end) {
719
+ parts.push(json.slice(chunkStart, end));
720
+ }
721
+ };
722
+ const escapeForCode = (code) => {
723
+ switch (code) {
724
+ case CHAR_CODE_LF:
725
+ return "\\n";
726
+ case CHAR_CODE_CR:
727
+ return "\\r";
728
+ case CHAR_CODE_TAB:
729
+ return "\\t";
730
+ default:
731
+ return `\\u${code.toString(16).padStart(4, "0")}`;
732
+ }
733
+ };
734
+ for (let i = 0; i < json.length; i += 1) {
735
+ const code = json.charCodeAt(i);
736
+ if (esc) {
737
+ esc = false;
738
+ if (code <= CHAR_CODE_CONTROL_UPPER) {
739
+ flushUpTo(i - 1);
740
+ parts.push(escapeForCode(code));
741
+ chunkStart = i + 1;
742
+ }
743
+ continue;
744
+ }
745
+ if (quote !== null && code === CHAR_CODE_BACKSLASH) {
746
+ esc = true;
747
+ continue;
748
+ }
749
+ if (quote !== null) {
750
+ if (code === quote) {
751
+ quote = null;
752
+ continue;
753
+ }
754
+ if (code <= CHAR_CODE_CONTROL_UPPER) {
755
+ flushUpTo(i);
756
+ parts.push(escapeForCode(code));
757
+ chunkStart = i + 1;
758
+ }
759
+ continue;
760
+ }
761
+ if (code === CHAR_CODE_SLASH && json.charCodeAt(i + 1) === CHAR_CODE_SLASH) {
762
+ i += 2;
763
+ while (i < json.length && json.charCodeAt(i) !== CHAR_CODE_LF && json.charCodeAt(i) !== CHAR_CODE_CR) {
764
+ i += 1;
765
+ }
766
+ continue;
767
+ }
768
+ if (code === CHAR_CODE_SLASH && json.charCodeAt(i + 1) === CHAR_CODE_STAR) {
769
+ i += 2;
770
+ while (i + 1 < json.length && !(json.charCodeAt(i) === CHAR_CODE_STAR && json.charCodeAt(i + 1) === CHAR_CODE_SLASH)) {
771
+ i += 1;
772
+ }
773
+ i += 1;
774
+ continue;
775
+ }
776
+ if (code === CHAR_CODE_QUOTE || code === CHAR_CODE_SINGLE_QUOTE) {
777
+ quote = code;
778
+ }
779
+ }
780
+ if (chunkStart < json.length) {
781
+ parts.push(json.slice(chunkStart));
782
+ }
783
+ return parts.join("");
784
+ }
488
785
  function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
489
786
  var _a;
490
787
  try {
491
- const parsedToolCall = parse(toolCallJson);
788
+ const parsedToolCall = parse(
789
+ normalizeJsonStringCtrl(toolCallJson)
790
+ );
492
791
  processedElements.push({
493
792
  type: "tool-call",
494
793
  toolCallId: generateToolCallId(),
@@ -496,6 +795,8 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
496
795
  input: canonicalizeToolInput(parsedToolCall.arguments)
497
796
  });
498
797
  } catch (error) {
798
+ const salvagedToolName = extractStreamingToolCallProgress(toolCallJson).toolName;
799
+ const salvagedToolCallId = generateToolCallId();
499
800
  logParseFailure({
500
801
  phase: "generated-text",
501
802
  reason: "Failed to parse tool call JSON segment",
@@ -505,24 +806,17 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
505
806
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
506
807
  options,
507
808
  "Could not process JSON tool call, keeping original text.",
508
- { toolCall: fullMatch, error }
809
+ {
810
+ toolCall: fullMatch,
811
+ error,
812
+ toolName: salvagedToolName,
813
+ toolCallId: salvagedToolCallId,
814
+ dropReason: "malformed-tool-call-body"
815
+ }
509
816
  );
510
817
  processedElements.push({ type: "text", text: fullMatch });
511
818
  }
512
819
  }
513
- function processMatchedToolCall(context) {
514
- const { match, text, currentIndex, processedElements, options } = context;
515
- const startIndex = match.index;
516
- const toolCallJson = match[1];
517
- if (startIndex > currentIndex) {
518
- const textSegment = text.slice(currentIndex, startIndex);
519
- addTextSegment(textSegment, processedElements);
520
- }
521
- if (toolCallJson) {
522
- processToolCallJson(toolCallJson, match[0], processedElements, options);
523
- }
524
- return startIndex + match[0].length;
525
- }
526
820
  var WHITESPACE_JSON_REGEX = /\s/;
527
821
  function skipJsonWhitespace(text, fromIndex) {
528
822
  let index = fromIndex;
@@ -789,7 +1083,9 @@ function canonicalizeArgumentsProgressInput(progress, toolName, tools) {
789
1083
  return void 0;
790
1084
  }
791
1085
  try {
792
- const parsedArguments = parse(progress.argumentsText);
1086
+ const parsedArguments = parse(
1087
+ normalizeJsonStringCtrl(progress.argumentsText)
1088
+ );
793
1089
  return stringifyToolInputWithSchema({
794
1090
  toolName,
795
1091
  args: parsedArguments,
@@ -849,14 +1145,16 @@ function closeTextBlock(state, controller) {
849
1145
  }
850
1146
  }
851
1147
  function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer, tools, options) {
852
- var _a;
1148
+ var _a, _b, _c, _d;
853
1149
  if (!state.currentToolCallJson && trailingBuffer.length === 0) {
854
1150
  state.isInsideToolCall = false;
855
1151
  return;
856
1152
  }
857
1153
  if (state.currentToolCallJson) {
858
1154
  try {
859
- const parsedToolCall = parse(state.currentToolCallJson);
1155
+ const parsedToolCall = parse(
1156
+ normalizeJsonStringCtrl(state.currentToolCallJson)
1157
+ );
860
1158
  emitToolCallFromParsed(state, controller, parsedToolCall, tools);
861
1159
  state.currentToolCallJson = "";
862
1160
  state.isInsideToolCall = false;
@@ -888,11 +1186,19 @@ function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer
888
1186
  id: errorId
889
1187
  });
890
1188
  }
1189
+ const streamingToolCallId = (_b = (_a = state.activeToolInput) == null ? void 0 : _a.id) != null ? _b : generateToolCallId();
1190
+ const streamingToolName = (_c = state.activeToolInput) == null ? void 0 : _c.toolName;
891
1191
  closeToolInput(state, controller);
892
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
1192
+ const toolName = streamingToolName != null ? streamingToolName : state.currentToolCallJson ? extractStreamingToolCallProgress(state.currentToolCallJson).toolName : void 0;
1193
+ (_d = options == null ? void 0 : options.onError) == null ? void 0 : _d.call(
893
1194
  options,
894
1195
  shouldEmitRawFallback ? "Could not complete streaming JSON tool call at finish; emitting original text." : "Could not complete streaming JSON tool call at finish.",
895
- { toolCall: errorContent }
1196
+ {
1197
+ toolCall: errorContent,
1198
+ toolCallId: streamingToolCallId,
1199
+ toolName,
1200
+ dropReason: "unfinished-tool-call"
1201
+ }
896
1202
  );
897
1203
  state.currentToolCallJson = "";
898
1204
  state.isInsideToolCall = false;
@@ -937,14 +1243,18 @@ function publishText(text, state, controller, tools) {
937
1243
  }
938
1244
  }
939
1245
  function emitToolCall(context) {
940
- var _a;
1246
+ var _a, _b, _c, _d, _e;
941
1247
  const { state, controller, toolCallStart, toolCallEnd, options, tools } = context;
942
1248
  try {
943
- const parsedToolCall = parse(state.currentToolCallJson);
1249
+ const parsedToolCall = parse(
1250
+ normalizeJsonStringCtrl(state.currentToolCallJson)
1251
+ );
944
1252
  emitToolCallFromParsed(state, controller, parsedToolCall, tools);
945
1253
  } catch (error) {
946
1254
  const errorContent = `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`;
947
1255
  const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
1256
+ const streamingToolCallId = (_b = (_a = state.activeToolInput) == null ? void 0 : _a.id) != null ? _b : generateToolCallId();
1257
+ const streamingToolName = (_d = (_c = state.activeToolInput) == null ? void 0 : _c.toolName) != null ? _d : extractStreamingToolCallProgress(state.currentToolCallJson).toolName;
948
1258
  logParseFailure({
949
1259
  phase: "stream",
950
1260
  reason: "Failed to parse streaming tool call JSON segment",
@@ -968,11 +1278,15 @@ function emitToolCall(context) {
968
1278
  });
969
1279
  }
970
1280
  closeToolInput(state, controller);
971
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
1281
+ (_e = options == null ? void 0 : options.onError) == null ? void 0 : _e.call(
972
1282
  options,
973
1283
  shouldEmitRawFallback ? "Could not process streaming JSON tool call; emitting original text." : "Could not process streaming JSON tool call.",
974
1284
  {
975
- toolCall: errorContent
1285
+ toolCall: errorContent,
1286
+ error,
1287
+ toolCallId: streamingToolCallId,
1288
+ toolName: streamingToolName,
1289
+ dropReason: "malformed-tool-call-body"
976
1290
  }
977
1291
  );
978
1292
  }
@@ -989,24 +1303,118 @@ function processTagMatch(context) {
989
1303
  state.activeToolInput = null;
990
1304
  }
991
1305
  }
992
- function processBufferTags(context) {
1306
+ function recoverNestedStreamingToolCall(options) {
1307
+ var _a, _b, _c, _d;
1308
+ const { context, jsonSoFar, nestedStartIndex, startIndex, tag } = options;
1309
+ const {
1310
+ state,
1311
+ controller,
1312
+ toolCallStart,
1313
+ toolCallEnd,
1314
+ options: parserOptions
1315
+ } = context;
1316
+ const droppedToolCall = `${toolCallStart}${jsonSoFar.slice(
1317
+ 0,
1318
+ nestedStartIndex
1319
+ )}`;
1320
+ const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(parserOptions);
1321
+ const streamingToolCallId = (_a = state.activeToolInput) == null ? void 0 : _a.id;
1322
+ const streamingToolName = (_c = (_b = state.activeToolInput) == null ? void 0 : _b.toolName) != null ? _c : extractStreamingToolCallProgress(jsonSoFar.slice(0, nestedStartIndex)).toolName;
1323
+ logParseFailure({
1324
+ phase: "stream",
1325
+ reason: "Abandoning malformed streaming tool call before nested start tag",
1326
+ snippet: droppedToolCall
1327
+ });
1328
+ if (shouldEmitRawFallback) {
1329
+ const errorId = generateId();
1330
+ controller.enqueue({
1331
+ type: "text-start",
1332
+ id: errorId
1333
+ });
1334
+ controller.enqueue({
1335
+ type: "text-delta",
1336
+ id: errorId,
1337
+ delta: droppedToolCall
1338
+ });
1339
+ controller.enqueue({
1340
+ type: "text-end",
1341
+ id: errorId
1342
+ });
1343
+ }
1344
+ closeToolInput(state, controller);
1345
+ (_d = parserOptions == null ? void 0 : parserOptions.onError) == null ? void 0 : _d.call(
1346
+ parserOptions,
1347
+ shouldEmitRawFallback ? "Could not process malformed streaming JSON tool call before nested start; emitting original text." : "Could not process malformed streaming JSON tool call before nested start.",
1348
+ {
1349
+ toolCall: droppedToolCall,
1350
+ toolCallId: streamingToolCallId,
1351
+ toolName: streamingToolName,
1352
+ dropReason: "malformed-nested-tool-call"
1353
+ }
1354
+ );
1355
+ state.currentToolCallJson = "";
1356
+ state.isInsideToolCall = false;
1357
+ state.buffer = jsonSoFar.slice(nestedStartIndex) + toolCallEnd + state.buffer.slice(startIndex + tag.length);
1358
+ return getPotentialStartIndex(state.buffer, toolCallStart);
1359
+ }
1360
+ function processInsideToolCallBoundary(context) {
993
1361
  const { state, controller, toolCallStart, toolCallEnd, tools } = context;
994
- let startIndex = getPotentialStartIndex(
995
- state.buffer,
996
- state.isInsideToolCall ? toolCallEnd : toolCallStart
1362
+ const currentLength = state.currentToolCallJson.length;
1363
+ const combined = state.currentToolCallJson + state.buffer;
1364
+ const boundary = findToolCallBoundaryOutsideRjsonSyntax(
1365
+ combined,
1366
+ 0,
1367
+ toolCallStart,
1368
+ toolCallEnd
1369
+ );
1370
+ if (boundary == null) {
1371
+ return false;
1372
+ }
1373
+ const relativeEndIndex = boundary.endIdx - currentLength;
1374
+ if (relativeEndIndex < 0) {
1375
+ return false;
1376
+ }
1377
+ if (boundary.kind === "nested") {
1378
+ recoverNestedStreamingToolCall({
1379
+ context,
1380
+ jsonSoFar: combined.slice(0, boundary.endIdx),
1381
+ nestedStartIndex: boundary.nestedStartIndex,
1382
+ startIndex: relativeEndIndex,
1383
+ tag: toolCallEnd
1384
+ });
1385
+ return true;
1386
+ }
1387
+ publishText(
1388
+ state.buffer.slice(0, relativeEndIndex),
1389
+ state,
1390
+ controller,
1391
+ tools
997
1392
  );
1393
+ state.buffer = state.buffer.slice(relativeEndIndex + toolCallEnd.length);
1394
+ processTagMatch(context);
1395
+ return true;
1396
+ }
1397
+ function processBufferTags(context) {
1398
+ const { state, controller, toolCallStart, tools } = context;
1399
+ while (state.isInsideToolCall) {
1400
+ if (!processInsideToolCallBoundary(context)) {
1401
+ return;
1402
+ }
1403
+ }
1404
+ let startIndex = getPotentialStartIndex(state.buffer, toolCallStart);
998
1405
  while (startIndex != null) {
999
- const tag = state.isInsideToolCall ? toolCallEnd : toolCallStart;
1000
- if (startIndex + tag.length > state.buffer.length) {
1406
+ if (startIndex + toolCallStart.length > state.buffer.length) {
1001
1407
  break;
1002
1408
  }
1003
1409
  publishText(state.buffer.slice(0, startIndex), state, controller, tools);
1004
- state.buffer = state.buffer.slice(startIndex + tag.length);
1410
+ state.buffer = state.buffer.slice(startIndex + toolCallStart.length);
1005
1411
  processTagMatch(context);
1006
- startIndex = getPotentialStartIndex(
1007
- state.buffer,
1008
- state.isInsideToolCall ? toolCallEnd : toolCallStart
1009
- );
1412
+ while (state.isInsideToolCall) {
1413
+ if (!processInsideToolCallBoundary(context)) {
1414
+ return;
1415
+ }
1416
+ }
1417
+ startIndex = getPotentialStartIndex(state.buffer, toolCallStart);
1010
1418
  }
1011
1419
  }
1012
1420
  function handlePartialTag(state, controller, toolCallStart, toolCallEnd, tools) {
@@ -1044,6 +1452,7 @@ var hermesProtocol = ({
1044
1452
  toolCallStart = "<tool_call>",
1045
1453
  toolCallEnd = "</tool_call>"
1046
1454
  } = {}) => ({
1455
+ ...validateNonEmptyDelimiters(toolCallStart, toolCallEnd),
1047
1456
  formatTools({
1048
1457
  tools,
1049
1458
  toolSystemPromptTemplate
@@ -1068,24 +1477,42 @@ var hermesProtocol = ({
1068
1477
  text,
1069
1478
  options
1070
1479
  }) {
1071
- const startEsc = escapeRegExp(toolCallStart);
1072
- const endEsc = escapeRegExp(toolCallEnd);
1073
- const toolCallRegex = new RegExp(
1074
- `${startEsc}([\0-\uFFFF]*?)${endEsc}`,
1075
- "gs"
1076
- );
1077
1480
  const processedElements = [];
1078
1481
  let currentIndex = 0;
1079
- let match = toolCallRegex.exec(text);
1080
- while (match !== null) {
1081
- currentIndex = processMatchedToolCall({
1082
- match,
1482
+ let searchFrom = 0;
1483
+ while (searchFrom < text.length) {
1484
+ const span = findNextToolCallSpan(
1083
1485
  text,
1084
- currentIndex,
1085
- processedElements,
1086
- options
1087
- });
1088
- match = toolCallRegex.exec(text);
1486
+ searchFrom,
1487
+ toolCallStart,
1488
+ toolCallEnd
1489
+ );
1490
+ if (span === null) {
1491
+ break;
1492
+ }
1493
+ if (!span.found) {
1494
+ const skipTo = span.startIdx + toolCallStart.length;
1495
+ if (skipTo > currentIndex) {
1496
+ addTextSegment(text.slice(currentIndex, skipTo), processedElements);
1497
+ currentIndex = skipTo;
1498
+ }
1499
+ searchFrom = skipTo;
1500
+ continue;
1501
+ }
1502
+ const toolCallJson = text.slice(span.jsonStart, span.endIdx);
1503
+ const fullMatch = text.slice(
1504
+ span.startIdx,
1505
+ span.endIdx + toolCallEnd.length
1506
+ );
1507
+ if (span.startIdx > currentIndex) {
1508
+ addTextSegment(
1509
+ text.slice(currentIndex, span.startIdx),
1510
+ processedElements
1511
+ );
1512
+ }
1513
+ processToolCallJson(toolCallJson, fullMatch, processedElements, options);
1514
+ currentIndex = span.endIdx + toolCallEnd.length;
1515
+ searchFrom = currentIndex;
1089
1516
  }
1090
1517
  if (currentIndex < text.length) {
1091
1518
  const remainingText = text.slice(currentIndex);
@@ -1138,14 +1565,26 @@ var hermesProtocol = ({
1138
1565
  });
1139
1566
  },
1140
1567
  extractToolCallSegments({ text }) {
1141
- const startEsc = escapeRegExp(toolCallStart);
1142
- const endEsc = escapeRegExp(toolCallEnd);
1143
- const regex = new RegExp(`${startEsc}([\0-\uFFFF]*?)${endEsc}`, "gs");
1144
1568
  const segments = [];
1145
- let m = regex.exec(text);
1146
- while (m != null) {
1147
- segments.push(m[0]);
1148
- m = regex.exec(text);
1569
+ let searchFrom = 0;
1570
+ while (searchFrom < text.length) {
1571
+ const span = findNextToolCallSpan(
1572
+ text,
1573
+ searchFrom,
1574
+ toolCallStart,
1575
+ toolCallEnd
1576
+ );
1577
+ if (span === null) {
1578
+ break;
1579
+ }
1580
+ if (!span.found) {
1581
+ searchFrom = span.startIdx + toolCallStart.length;
1582
+ continue;
1583
+ }
1584
+ segments.push(
1585
+ text.slice(span.startIdx, span.endIdx + toolCallEnd.length)
1586
+ );
1587
+ searchFrom = span.endIdx + toolCallEnd.length;
1149
1588
  }
1150
1589
  return segments;
1151
1590
  }
@@ -1434,7 +1873,13 @@ function processToolCall(params) {
1434
1873
  (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
1435
1874
  options,
1436
1875
  `Could not process XML tool call: ${toolCall.toolName}`,
1437
- { toolCall: originalCallText, error }
1876
+ {
1877
+ toolCall: originalCallText,
1878
+ error,
1879
+ toolName: toolCall.toolName,
1880
+ toolCallId: generateToolCallId(),
1881
+ dropReason: "malformed-tool-call-body"
1882
+ }
1438
1883
  );
1439
1884
  processedElements.push({ type: "text", text: originalCallText });
1440
1885
  }
@@ -1876,7 +2321,10 @@ function handleStreamingToolCallEnd(params) {
1876
2321
  });
1877
2322
  (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
1878
2323
  toolCall: original,
1879
- error
2324
+ error,
2325
+ toolName: currentToolCall.name,
2326
+ toolCallId: currentToolCall.toolCallId,
2327
+ dropReason: "malformed-tool-call-body"
1880
2328
  });
1881
2329
  }
1882
2330
  }
@@ -2438,7 +2886,13 @@ var morphXmlProtocol = (protocolOptions) => {
2438
2886
  (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
2439
2887
  options,
2440
2888
  "Could not complete streaming XML tool call at finish.",
2441
- { toolCall: unfinishedContent, error }
2889
+ {
2890
+ toolCall: unfinishedContent,
2891
+ toolCallId: currentToolCall.toolCallId,
2892
+ toolName: currentToolCall.name,
2893
+ dropReason: "unfinished-tool-call",
2894
+ error
2895
+ }
2442
2896
  );
2443
2897
  }
2444
2898
  buffer = "";
@@ -2664,7 +3118,8 @@ var QWEN3CODER_TOOL_PARSER_CALL_TAG_NAMES = /* @__PURE__ */ new Set([
2664
3118
  "invoke",
2665
3119
  "tool_call"
2666
3120
  ]);
2667
- var CALL_SHORTHAND_VALUE_RE = /^<\s*(call|function|tool|invoke)\b\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>/]+))/i;
3121
+ var CALL_SHORTHAND_VALUE_RE = /^<\s*(call|function|tool|invoke)\b\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>/<]+))/i;
3122
+ var NESTED_CALL_SHORTHAND_VALUE_RE = /<\s*(?:call|function|tool|invoke)\b\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>/<]+))/i;
2668
3123
  var QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_START_RE = /<\s*(?!\/)\s*(call|function|tool|invoke)\b/i;
2669
3124
  var QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_TAG_RE = /<\s*(?!\/)\s*(call|function|tool|invoke)\b[^>]*>/i;
2670
3125
  var QWEN3CODER_TOOL_PARSER_STREAM_TOOL_CALL_CLOSE_TAG_RE = /<\s*\/\s*tool_call\s*>/i;
@@ -3063,6 +3518,12 @@ function getShorthandValue(openTag) {
3063
3518
  }
3064
3519
  return unescapeXml(value);
3065
3520
  }
3521
+ function extractShorthandToolNameFromRaw(rawText) {
3522
+ var _a, _b;
3523
+ const match = NESTED_CALL_SHORTHAND_VALUE_RE.exec(rawText);
3524
+ const value = (_b = (_a = match == null ? void 0 : match[1]) != null ? _a : match == null ? void 0 : match[2]) != null ? _b : match == null ? void 0 : match[3];
3525
+ return value ? unescapeXml(value) : null;
3526
+ }
3066
3527
  function extractFirstTagText(xml, tagName) {
3067
3528
  var _a;
3068
3529
  const lower = xml.toLowerCase();
@@ -3384,6 +3845,20 @@ function parseQwen3CoderToolParserClosedMatches(inner, outerNameAttr) {
3384
3845
  }
3385
3846
  return closedCalls.concat(trailingCalls);
3386
3847
  }
3848
+ var QWEN3CODER_TOOL_NAME_SALVAGE_REGEX = /<(?:function|call|tool|invoke)(?:\s*=\s*"([^"]+)"|\s*=\s*'([^']+)'|\s*=\s*([^\s>/]+)|\s+name\s*=\s*"([^"]+)"|\s+name\s*=\s*'([^']+)')|<(?:name|tool_name)\b[^>]*>([\s\S]*?)<\s*\/\s*(?:name|tool_name)\s*>/i;
3849
+ function extractQwen3CoderToolNameFromMarkup(markup) {
3850
+ var _a, _b, _c, _d, _e;
3851
+ const match = markup.match(QWEN3CODER_TOOL_NAME_SALVAGE_REGEX);
3852
+ if (!match) {
3853
+ return void 0;
3854
+ }
3855
+ const name = (_e = (_d = (_c = (_b = (_a = match[1]) != null ? _a : match[2]) != null ? _b : match[3]) != null ? _c : match[4]) != null ? _d : match[5]) != null ? _e : match[6];
3856
+ if (!name) {
3857
+ return void 0;
3858
+ }
3859
+ const trimmed = name.trim();
3860
+ return trimmed.length > 0 ? trimmed : void 0;
3861
+ }
3387
3862
  function parseQwen3CoderToolParserToolCallSegment(segment) {
3388
3863
  var _a;
3389
3864
  const extracted = extractToolCallInnerXml(segment);
@@ -3508,7 +3983,12 @@ var qwen3CoderProtocol = () => ({
3508
3983
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
3509
3984
  options,
3510
3985
  "Could not process Qwen3CoderToolParser XML tool call; keeping original text.",
3511
- { toolCall: fallbackText }
3986
+ {
3987
+ toolCall: fallbackText,
3988
+ toolName: extractQwen3CoderToolNameFromMarkup(segment),
3989
+ toolCallId: generateToolCallId(),
3990
+ dropReason: "malformed-tool-call-body"
3991
+ }
3512
3992
  );
3513
3993
  processedElements.push({ type: "text", text: fallbackText });
3514
3994
  return false;
@@ -3521,7 +4001,12 @@ var qwen3CoderProtocol = () => ({
3521
4001
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
3522
4002
  options,
3523
4003
  "Could not process Qwen3CoderToolParser <function> call; keeping original text.",
3524
- { toolCall: raw }
4004
+ {
4005
+ toolCall: raw,
4006
+ toolName: extractQwen3CoderToolNameFromMarkup(raw),
4007
+ toolCallId: generateToolCallId(),
4008
+ dropReason: "malformed-tool-call-body"
4009
+ }
3525
4010
  );
3526
4011
  processedElements.push({ type: "text", text: raw });
3527
4012
  };
@@ -3771,7 +4256,7 @@ var qwen3CoderProtocol = () => ({
3771
4256
  });
3772
4257
  };
3773
4258
  const finalizeCall = (controller, callState, fallbackToolName, rawToolCallText = null) => {
3774
- var _a, _b;
4259
+ var _a, _b, _c, _d;
3775
4260
  const resolvedToolName = (_a = callState.toolName) != null ? _a : fallbackToolName;
3776
4261
  if (!resolvedToolName || resolvedToolName.trim().length === 0) {
3777
4262
  const shouldEmitRaw = shouldEmitRawToolCallTextOnError(options);
@@ -3785,12 +4270,14 @@ var qwen3CoderProtocol = () => ({
3785
4270
  flushText(controller, rawText);
3786
4271
  }
3787
4272
  });
3788
- (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
4273
+ (_d = options == null ? void 0 : options.onError) == null ? void 0 : _d.call(
3789
4274
  options,
3790
4275
  shouldEmitRaw && rawToolCallText ? "Could not resolve Qwen3CoderToolParser tool name for tool call; emitting original text." : "Could not resolve Qwen3CoderToolParser tool name for tool call",
3791
4276
  {
3792
4277
  toolCallId: callState.toolCallId,
3793
- toolCall: rawToolCallText
4278
+ toolCall: rawToolCallText,
4279
+ toolName: (_c = (_b = callState.toolName) != null ? _b : fallbackToolName) != null ? _c : void 0,
4280
+ dropReason: "unresolved-tool-name"
3794
4281
  }
3795
4282
  );
3796
4283
  return false;
@@ -4246,25 +4733,36 @@ var qwen3CoderProtocol = () => ({
4246
4733
  }
4247
4734
  }
4248
4735
  };
4249
- const reportUnfinishedToolCallAtFinish = (controller, rawToolCall) => {
4250
- var _a;
4736
+ const reportUnfinishedToolCallAtFinish = (controller, rawToolCall, metadata = {}) => {
4737
+ var _a, _b;
4251
4738
  const shouldEmitRaw = shouldEmitRawToolCallTextOnError(options);
4252
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
4739
+ const toolName = (_a = metadata.toolName) != null ? _a : extractShorthandToolNameFromRaw(rawToolCall);
4740
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
4253
4741
  options,
4254
4742
  shouldEmitRaw ? "Could not complete streaming Qwen3CoderToolParser XML tool call at finish; emitting original text." : "Could not complete streaming Qwen3CoderToolParser XML tool call at finish.",
4255
- { toolCall: rawToolCall }
4743
+ {
4744
+ toolCall: rawToolCall,
4745
+ ...metadata.toolCallId ? { toolCallId: metadata.toolCallId } : {},
4746
+ ...toolName ? { toolName } : {},
4747
+ dropReason: "unfinished-tool-call"
4748
+ }
4256
4749
  );
4257
4750
  if (shouldEmitRaw) {
4258
4751
  flushText(controller, rawToolCall);
4259
4752
  }
4260
4753
  };
4261
- const reportUnfinishedImplicitCallAtFinish = (controller, rawCallText) => {
4754
+ const reportUnfinishedImplicitCallAtFinish = (controller, rawCallText, callState) => {
4262
4755
  var _a;
4263
4756
  const shouldEmitRaw = shouldEmitRawToolCallTextOnError(options);
4264
4757
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
4265
4758
  options,
4266
4759
  shouldEmitRaw ? "Could not complete streaming Qwen3CoderToolParser call block at finish; emitting original text." : "Could not complete streaming Qwen3CoderToolParser call block at finish.",
4267
- { toolCall: rawCallText }
4760
+ {
4761
+ toolCall: rawCallText,
4762
+ toolCallId: callState.toolCallId,
4763
+ ...callState.toolName ? { toolName: callState.toolName } : {},
4764
+ dropReason: "unfinished-tool-call"
4765
+ }
4268
4766
  );
4269
4767
  if (shouldEmitRaw) {
4270
4768
  flushText(controller, rawCallText);
@@ -4315,7 +4813,10 @@ var qwen3CoderProtocol = () => ({
4315
4813
  flushText(controller, result.trailingText);
4316
4814
  }
4317
4815
  if (!result.ok && toolCall.emittedToolCallCount === 0) {
4318
- reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
4816
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw, {
4817
+ toolCallId: toolCall.activeCall.toolCallId,
4818
+ ...toolCall.activeCall.toolName ? { toolName: toolCall.activeCall.toolName } : {}
4819
+ });
4319
4820
  }
4320
4821
  } else if (toolCall.mode === "multi") {
4321
4822
  if (toolCall.activeCall) {
@@ -4332,14 +4833,21 @@ var qwen3CoderProtocol = () => ({
4332
4833
  flushText(controller, result.trailingText);
4333
4834
  }
4334
4835
  if (!result.ok && toolCall.emittedToolCallCount === 0) {
4335
- reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
4836
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw, {
4837
+ toolCallId: toolCall.activeCall.toolCallId,
4838
+ ...toolCall.activeCall.toolName ? { toolName: toolCall.activeCall.toolName } : {}
4839
+ });
4336
4840
  }
4337
4841
  toolCall.activeCall = null;
4338
4842
  } else if (toolCall.emittedToolCallCount === 0) {
4339
- reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
4843
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw, {
4844
+ toolName: toolCall.outerNameAttr
4845
+ });
4340
4846
  }
4341
4847
  } else {
4342
- reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
4848
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw, {
4849
+ toolName: toolCall.outerNameAttr
4850
+ });
4343
4851
  }
4344
4852
  toolCall = null;
4345
4853
  }
@@ -4357,7 +4865,8 @@ var qwen3CoderProtocol = () => ({
4357
4865
  if (!result.ok && openTag) {
4358
4866
  reportUnfinishedImplicitCallAtFinish(
4359
4867
  controller,
4360
- callState.raw || openTag + callState.buffer
4868
+ callState.raw || openTag + callState.buffer,
4869
+ callState
4361
4870
  );
4362
4871
  }
4363
4872
  } else {
@@ -4736,26 +5245,28 @@ function findToolCalls2(text, toolNames) {
4736
5245
  );
4737
5246
  return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
4738
5247
  }
4739
- function parseYamlContent(yamlContent, options) {
4740
- var _a, _b;
5248
+ function yamlFailureCause(failure) {
5249
+ if (failure.kind === "yaml-parse-error") {
5250
+ return { kind: "yaml-parse-error", errors: failure.errors };
5251
+ }
5252
+ return { kind: "yaml-non-mapping" };
5253
+ }
5254
+ function parseYamlContent(yamlContent) {
4741
5255
  const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
4742
5256
  if (nonEmptyLines.length === 0) {
4743
- return {};
5257
+ return { ok: true, value: {} };
4744
5258
  }
4745
5259
  const parsed = parseYamlDocumentAsMapping(normalized);
4746
5260
  if (parsed.errors.length > 0) {
4747
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "YAML parse error", {
4748
- errors: parsed.errors
4749
- });
4750
- return null;
5261
+ return {
5262
+ ok: false,
5263
+ failure: { kind: "yaml-parse-error", errors: parsed.errors }
5264
+ };
4751
5265
  }
4752
5266
  if (parsed.value === null) {
4753
- (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
4754
- got: "non-mapping"
4755
- });
4756
- return null;
5267
+ return { ok: false, failure: { kind: "yaml-non-mapping" } };
4757
5268
  }
4758
- return parsed.value;
5269
+ return { ok: true, value: parsed.value };
4759
5270
  }
4760
5271
  function parseYamlContentForStreamProgress(yamlContent) {
4761
5272
  const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
@@ -4787,11 +5298,16 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
4787
5298
  return currentIndex;
4788
5299
  }
4789
5300
  addTextSegment(text.slice(currentIndex, tc.startIndex), processedElements);
4790
- const parsedArgs = parseYamlContent(tc.content, options);
4791
- if (parsedArgs === null) {
5301
+ const result = parseYamlContent(tc.content);
5302
+ if (!result.ok) {
4792
5303
  const originalText = text.slice(tc.startIndex, tc.endIndex);
5304
+ const cause = yamlFailureCause(result.failure);
4793
5305
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse YAML tool call", {
4794
- toolCall: originalText
5306
+ toolCall: originalText,
5307
+ toolName: tc.toolName,
5308
+ toolCallId: generateToolCallId(),
5309
+ dropReason: "malformed-tool-call-body",
5310
+ cause
4795
5311
  });
4796
5312
  processedElements.push({ type: "text", text: originalText });
4797
5313
  } else {
@@ -4799,7 +5315,7 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
4799
5315
  type: "tool-call",
4800
5316
  toolCallId: generateToolCallId(),
4801
5317
  toolName: tc.toolName,
4802
- input: JSON.stringify(parsedArgs)
5318
+ input: JSON.stringify(result.value)
4803
5319
  });
4804
5320
  }
4805
5321
  return tc.endIndex;
@@ -4922,9 +5438,9 @@ ${yamlContent}</${toolCall.toolName}>`;
4922
5438
  };
4923
5439
  const processToolCallEnd = (controller, toolContent, toolName, toolCallId) => {
4924
5440
  var _a;
4925
- const parsedArgs = parseYamlContent(toolContent, options);
5441
+ const result = parseYamlContent(toolContent);
4926
5442
  flushText(controller);
4927
- if (parsedArgs === null) {
5443
+ if (!result.ok) {
4928
5444
  const original = `<${toolName}>${toolContent}</${toolName}>`;
4929
5445
  const emitRawFallback = shouldEmitRawToolCallTextOnError(options);
4930
5446
  emitFailedToolInputLifecycle({
@@ -4937,12 +5453,16 @@ ${yamlContent}</${toolCall.toolName}>`;
4937
5453
  }
4938
5454
  });
4939
5455
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
4940
- toolCall: original
5456
+ toolCall: original,
5457
+ toolName,
5458
+ toolCallId,
5459
+ dropReason: "malformed-tool-call-body",
5460
+ cause: yamlFailureCause(result.failure)
4941
5461
  });
4942
5462
  } else {
4943
5463
  const finalInput = stringifyToolInputWithSchema({
4944
5464
  toolName,
4945
- args: parsedArgs,
5465
+ args: result.value,
4946
5466
  tools
4947
5467
  });
4948
5468
  if (currentToolCall && currentToolCall.toolCallId === toolCallId) {
@@ -4972,9 +5492,9 @@ ${yamlContent}</${toolCall.toolName}>`;
4972
5492
  emitToolInputProgress2(controller, buffer);
4973
5493
  const { name: toolName, toolCallId } = currentToolCall;
4974
5494
  const reconciledBuffer = stripTrailingPartialCloseTag(buffer, toolName);
4975
- const parsedArgs = parseYamlContent(reconciledBuffer, options);
5495
+ const result = parseYamlContent(reconciledBuffer);
4976
5496
  flushText(controller);
4977
- if (parsedArgs === null) {
5497
+ if (!result.ok) {
4978
5498
  const unfinishedContent = `<${toolName}>${buffer}`;
4979
5499
  const emitRawFallback = shouldEmitRawToolCallTextOnError(options);
4980
5500
  emitFailedToolInputLifecycle({
@@ -4989,12 +5509,18 @@ ${yamlContent}</${toolCall.toolName}>`;
4989
5509
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
4990
5510
  options,
4991
5511
  "Could not complete streaming YAML tool call at finish.",
4992
- { toolCall: unfinishedContent }
5512
+ {
5513
+ toolCall: unfinishedContent,
5514
+ toolCallId,
5515
+ toolName,
5516
+ dropReason: "unfinished-tool-call",
5517
+ cause: yamlFailureCause(result.failure)
5518
+ }
4993
5519
  );
4994
5520
  } else {
4995
5521
  const finalInput = stringifyToolInputWithSchema({
4996
5522
  toolName,
4997
- args: parsedArgs,
5523
+ args: result.value,
4998
5524
  tools
4999
5525
  });
5000
5526
  emitFinalizedToolInputLifecycle({
@@ -7327,4 +7853,4 @@ export {
7327
7853
  morphXmlToolMiddleware,
7328
7854
  yamlXmlToolMiddleware
7329
7855
  };
7330
- //# sourceMappingURL=chunk-AELRIRO2.js.map
7856
+ //# sourceMappingURL=chunk-GAJX7HXU.js.map