@ai-sdk-tool/parser 4.1.20 → 4.1.22

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.
@@ -2862,7 +2862,7 @@ function handleOpeningTagSegment(src, lt, out, stack) {
2862
2862
  function extractSchemaProperties(schema) {
2863
2863
  const unwrapped = unwrapJsonSchema(schema);
2864
2864
  if (!unwrapped || typeof unwrapped !== "object") {
2865
- return void 0;
2865
+ return;
2866
2866
  }
2867
2867
  return unwrapped.properties;
2868
2868
  }
@@ -4645,13 +4645,312 @@ function shouldEmitRawToolCallTextOnError(options) {
4645
4645
  }
4646
4646
 
4647
4647
  // src/core/protocols/hermes-protocol.ts
4648
+ var RJSON_IDENTIFIER_CHAR_REGEX = /[$a-zA-Z0-9_\-+.*?!|&%^/#\\]/;
4649
+ var RJSON_NUMBER_TOKEN_REGEX = /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
4650
+ function validateNonEmptyDelimiters(toolCallStart, toolCallEnd) {
4651
+ if (toolCallStart.length === 0) {
4652
+ throw new TypeError("hermesProtocol toolCallStart must not be empty");
4653
+ }
4654
+ if (toolCallEnd.length === 0) {
4655
+ throw new TypeError("hermesProtocol toolCallEnd must not be empty");
4656
+ }
4657
+ return {};
4658
+ }
4659
+ function isRjsonIdentifierChar(ch) {
4660
+ return ch != null && RJSON_IDENTIFIER_CHAR_REGEX.test(ch);
4661
+ }
4662
+ function isRjsonPropertyLikeDelimiter(startTag) {
4663
+ const key = startTag.endsWith(":") ? startTag.slice(0, -1) : "";
4664
+ return key.length > 0 && [...key].every((ch) => isRjsonIdentifierChar(ch));
4665
+ }
4666
+ function previousRjsonToken(json, index, minIndex = 0) {
4667
+ let start = index - 1;
4668
+ while (start >= minIndex && isRjsonIdentifierChar(json[start])) {
4669
+ start -= 1;
4670
+ }
4671
+ return json.slice(start + 1, index);
4672
+ }
4673
+ function previousTokenAllowsComment(json, index, minIndex = 0) {
4674
+ const previous = previousRjsonToken(json, index, minIndex);
4675
+ if (previous.length === 0) {
4676
+ return true;
4677
+ }
4678
+ return RJSON_NUMBER_TOKEN_REGEX.test(previous) || previous === "true" || previous === "false" || previous === "null";
4679
+ }
4680
+ function startsRjsonComment(json, index, minIndex = 0) {
4681
+ if (!(json[index] === "/" && json[index + 1] === "/" || json[index] === "/" && json[index + 1] === "*")) {
4682
+ return false;
4683
+ }
4684
+ if (index > minIndex && isRjsonIdentifierChar(json[index - 1])) {
4685
+ return previousTokenAllowsComment(json, index, minIndex);
4686
+ }
4687
+ return true;
4688
+ }
4689
+ function hasNestedStartBoundary(segment, startIndex) {
4690
+ const previous = segment[startIndex - 1];
4691
+ return previous == null || WHITESPACE_JSON_REGEX.test(previous) || previous === "}";
4692
+ }
4693
+ function isLikelyNestedToolCallStart(segment, startIndex, startTag) {
4694
+ if (isRjsonPropertyLikeDelimiter(startTag)) {
4695
+ return false;
4696
+ }
4697
+ const jsonStart = skipJsonWhitespace(segment, startIndex + startTag.length);
4698
+ return segment[jsonStart] === "{" && hasNestedStartBoundary(segment, startIndex);
4699
+ }
4700
+ function findToolCallBoundaryOutsideRjsonSyntax(text, scanFrom, startTag, endTag) {
4701
+ let quote = null;
4702
+ let esc = false;
4703
+ let inLineComment = false;
4704
+ let inBlockComment = false;
4705
+ let lineCommentSawEndTag = false;
4706
+ let blockCommentSawEndTag = false;
4707
+ let nestedStartIndex = null;
4708
+ for (let index = scanFrom; index < text.length; index += 1) {
4709
+ const ch = text[index];
4710
+ if (esc) {
4711
+ esc = false;
4712
+ continue;
4713
+ }
4714
+ if (quote !== null) {
4715
+ if (ch === "\\") {
4716
+ esc = true;
4717
+ continue;
4718
+ }
4719
+ if (ch === quote) {
4720
+ quote = null;
4721
+ }
4722
+ continue;
4723
+ }
4724
+ if (inLineComment) {
4725
+ if (ch === "\n" || ch === "\r") {
4726
+ inLineComment = false;
4727
+ lineCommentSawEndTag = false;
4728
+ continue;
4729
+ }
4730
+ if (text.startsWith(endTag, index)) {
4731
+ lineCommentSawEndTag = true;
4732
+ index += endTag.length - 1;
4733
+ continue;
4734
+ }
4735
+ if (lineCommentSawEndTag && text.startsWith(startTag, index) && text[skipJsonWhitespace(text, index + startTag.length)] === "{") {
4736
+ nestedStartIndex = index;
4737
+ inLineComment = false;
4738
+ lineCommentSawEndTag = false;
4739
+ index += startTag.length - 1;
4740
+ continue;
4741
+ }
4742
+ continue;
4743
+ }
4744
+ if (inBlockComment) {
4745
+ if (ch === "*" && text[index + 1] === "/") {
4746
+ inBlockComment = false;
4747
+ blockCommentSawEndTag = false;
4748
+ index += 1;
4749
+ continue;
4750
+ }
4751
+ if (text.startsWith(endTag, index)) {
4752
+ blockCommentSawEndTag = true;
4753
+ index += endTag.length - 1;
4754
+ continue;
4755
+ }
4756
+ if (blockCommentSawEndTag && text.startsWith(startTag, index) && text[skipJsonWhitespace(text, index + startTag.length)] === "{") {
4757
+ nestedStartIndex = index;
4758
+ inBlockComment = false;
4759
+ blockCommentSawEndTag = false;
4760
+ index += startTag.length - 1;
4761
+ continue;
4762
+ }
4763
+ continue;
4764
+ }
4765
+ if (startsRjsonComment(text, index, scanFrom)) {
4766
+ if (text[index + 1] === "/") {
4767
+ inLineComment = true;
4768
+ lineCommentSawEndTag = false;
4769
+ index += 1;
4770
+ continue;
4771
+ }
4772
+ if (text[index + 1] === "*") {
4773
+ inBlockComment = true;
4774
+ blockCommentSawEndTag = false;
4775
+ index += 1;
4776
+ continue;
4777
+ }
4778
+ }
4779
+ if (text.startsWith(endTag, index)) {
4780
+ return nestedStartIndex == null ? { kind: "end", endIdx: index } : { kind: "nested", endIdx: index, nestedStartIndex };
4781
+ }
4782
+ if (nestedStartIndex == null && text.startsWith(startTag, index) && isLikelyNestedToolCallStart(text, index, startTag)) {
4783
+ nestedStartIndex = index;
4784
+ index += startTag.length - 1;
4785
+ continue;
4786
+ }
4787
+ if (ch === '"' || ch === "'") {
4788
+ quote = ch;
4789
+ }
4790
+ }
4791
+ return null;
4792
+ }
4793
+ function findNextToolCallSpan(text, searchFrom, startTag, endTag) {
4794
+ const startIdx = text.indexOf(startTag, searchFrom);
4795
+ if (startIdx === -1) {
4796
+ return null;
4797
+ }
4798
+ const jsonStart = startIdx + startTag.length;
4799
+ const boundary = findToolCallBoundaryOutsideRjsonSyntax(
4800
+ text,
4801
+ jsonStart,
4802
+ startTag,
4803
+ endTag
4804
+ );
4805
+ if (boundary == null) {
4806
+ return { startIdx, found: false };
4807
+ }
4808
+ if (boundary.kind === "nested") {
4809
+ return { startIdx, found: false };
4810
+ }
4811
+ return { startIdx, found: true, jsonStart, endIdx: boundary.endIdx };
4812
+ }
4648
4813
  function canonicalizeToolInput(argumentsValue) {
4649
4814
  return JSON.stringify(argumentsValue != null ? argumentsValue : {});
4650
4815
  }
4816
+ var CHAR_CODE_BACKSLASH = 92;
4817
+ var CHAR_CODE_QUOTE = 34;
4818
+ var CHAR_CODE_LF = 10;
4819
+ var CHAR_CODE_CR = 13;
4820
+ var CHAR_CODE_TAB = 9;
4821
+ var CHAR_CODE_SLASH = 47;
4822
+ var CHAR_CODE_STAR = 42;
4823
+ var CHAR_CODE_CONTROL_UPPER = 31;
4824
+ var CHAR_CODE_SINGLE_QUOTE = 39;
4825
+ function hasControlCharInString(json) {
4826
+ let quote = null;
4827
+ let esc = false;
4828
+ for (let i = 0; i < json.length; i += 1) {
4829
+ const code = json.charCodeAt(i);
4830
+ if (esc) {
4831
+ esc = false;
4832
+ if (code <= CHAR_CODE_CONTROL_UPPER) {
4833
+ return true;
4834
+ }
4835
+ continue;
4836
+ }
4837
+ if (quote !== null && code === CHAR_CODE_BACKSLASH) {
4838
+ esc = true;
4839
+ continue;
4840
+ }
4841
+ if (quote !== null) {
4842
+ if (code === quote) {
4843
+ quote = null;
4844
+ continue;
4845
+ }
4846
+ if (code <= CHAR_CODE_CONTROL_UPPER) {
4847
+ return true;
4848
+ }
4849
+ continue;
4850
+ }
4851
+ if (code === CHAR_CODE_SLASH && json.charCodeAt(i + 1) === CHAR_CODE_SLASH) {
4852
+ i += 2;
4853
+ while (i < json.length && json.charCodeAt(i) !== CHAR_CODE_LF && json.charCodeAt(i) !== CHAR_CODE_CR) {
4854
+ i += 1;
4855
+ }
4856
+ continue;
4857
+ }
4858
+ if (code === CHAR_CODE_SLASH && json.charCodeAt(i + 1) === CHAR_CODE_STAR) {
4859
+ i += 2;
4860
+ while (i + 1 < json.length && !(json.charCodeAt(i) === CHAR_CODE_STAR && json.charCodeAt(i + 1) === CHAR_CODE_SLASH)) {
4861
+ i += 1;
4862
+ }
4863
+ i += 1;
4864
+ continue;
4865
+ }
4866
+ if (code === CHAR_CODE_QUOTE || code === CHAR_CODE_SINGLE_QUOTE) {
4867
+ quote = code;
4868
+ }
4869
+ }
4870
+ return false;
4871
+ }
4872
+ function normalizeJsonStringCtrl(json) {
4873
+ if (!hasControlCharInString(json)) {
4874
+ return json;
4875
+ }
4876
+ const parts = [];
4877
+ let chunkStart = 0;
4878
+ let quote = null;
4879
+ let esc = false;
4880
+ const flushUpTo = (end) => {
4881
+ if (chunkStart < end) {
4882
+ parts.push(json.slice(chunkStart, end));
4883
+ }
4884
+ };
4885
+ const escapeForCode = (code) => {
4886
+ switch (code) {
4887
+ case CHAR_CODE_LF:
4888
+ return "\\n";
4889
+ case CHAR_CODE_CR:
4890
+ return "\\r";
4891
+ case CHAR_CODE_TAB:
4892
+ return "\\t";
4893
+ default:
4894
+ return `\\u${code.toString(16).padStart(4, "0")}`;
4895
+ }
4896
+ };
4897
+ for (let i = 0; i < json.length; i += 1) {
4898
+ const code = json.charCodeAt(i);
4899
+ if (esc) {
4900
+ esc = false;
4901
+ if (code <= CHAR_CODE_CONTROL_UPPER) {
4902
+ flushUpTo(i - 1);
4903
+ parts.push(escapeForCode(code));
4904
+ chunkStart = i + 1;
4905
+ }
4906
+ continue;
4907
+ }
4908
+ if (quote !== null && code === CHAR_CODE_BACKSLASH) {
4909
+ esc = true;
4910
+ continue;
4911
+ }
4912
+ if (quote !== null) {
4913
+ if (code === quote) {
4914
+ quote = null;
4915
+ continue;
4916
+ }
4917
+ if (code <= CHAR_CODE_CONTROL_UPPER) {
4918
+ flushUpTo(i);
4919
+ parts.push(escapeForCode(code));
4920
+ chunkStart = i + 1;
4921
+ }
4922
+ continue;
4923
+ }
4924
+ if (code === CHAR_CODE_SLASH && json.charCodeAt(i + 1) === CHAR_CODE_SLASH) {
4925
+ i += 2;
4926
+ while (i < json.length && json.charCodeAt(i) !== CHAR_CODE_LF && json.charCodeAt(i) !== CHAR_CODE_CR) {
4927
+ i += 1;
4928
+ }
4929
+ continue;
4930
+ }
4931
+ if (code === CHAR_CODE_SLASH && json.charCodeAt(i + 1) === CHAR_CODE_STAR) {
4932
+ i += 2;
4933
+ while (i + 1 < json.length && !(json.charCodeAt(i) === CHAR_CODE_STAR && json.charCodeAt(i + 1) === CHAR_CODE_SLASH)) {
4934
+ i += 1;
4935
+ }
4936
+ i += 1;
4937
+ continue;
4938
+ }
4939
+ if (code === CHAR_CODE_QUOTE || code === CHAR_CODE_SINGLE_QUOTE) {
4940
+ quote = code;
4941
+ }
4942
+ }
4943
+ if (chunkStart < json.length) {
4944
+ parts.push(json.slice(chunkStart));
4945
+ }
4946
+ return parts.join("");
4947
+ }
4651
4948
  function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
4652
4949
  var _a;
4653
4950
  try {
4654
- const parsedToolCall = parse3(toolCallJson);
4951
+ const parsedToolCall = parse3(
4952
+ normalizeJsonStringCtrl(toolCallJson)
4953
+ );
4655
4954
  processedElements.push({
4656
4955
  type: "tool-call",
4657
4956
  toolCallId: generateToolCallId(),
@@ -4659,6 +4958,8 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
4659
4958
  input: canonicalizeToolInput(parsedToolCall.arguments)
4660
4959
  });
4661
4960
  } catch (error) {
4961
+ const salvagedToolName = extractStreamingToolCallProgress(toolCallJson).toolName;
4962
+ const salvagedToolCallId = generateToolCallId();
4662
4963
  logParseFailure({
4663
4964
  phase: "generated-text",
4664
4965
  reason: "Failed to parse tool call JSON segment",
@@ -4668,24 +4969,17 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
4668
4969
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
4669
4970
  options,
4670
4971
  "Could not process JSON tool call, keeping original text.",
4671
- { toolCall: fullMatch, error }
4972
+ {
4973
+ toolCall: fullMatch,
4974
+ error,
4975
+ toolName: salvagedToolName,
4976
+ toolCallId: salvagedToolCallId,
4977
+ dropReason: "malformed-tool-call-body"
4978
+ }
4672
4979
  );
4673
4980
  processedElements.push({ type: "text", text: fullMatch });
4674
4981
  }
4675
4982
  }
4676
- function processMatchedToolCall(context) {
4677
- const { match, text, currentIndex, processedElements, options } = context;
4678
- const startIndex = match.index;
4679
- const toolCallJson = match[1];
4680
- if (startIndex > currentIndex) {
4681
- const textSegment = text.slice(currentIndex, startIndex);
4682
- addTextSegment(textSegment, processedElements);
4683
- }
4684
- if (toolCallJson) {
4685
- processToolCallJson(toolCallJson, match[0], processedElements, options);
4686
- }
4687
- return startIndex + match[0].length;
4688
- }
4689
4983
  var WHITESPACE_JSON_REGEX = /\s/;
4690
4984
  function skipJsonWhitespace(text, fromIndex) {
4691
4985
  let index = fromIndex;
@@ -4767,10 +5061,10 @@ function findTopLevelPropertyValueStart(text, property) {
4767
5061
  function extractTopLevelStringProperty(text, property) {
4768
5062
  const valueStart = findTopLevelPropertyValueStart(text, property);
4769
5063
  if (valueStart == null || valueStart >= text.length) {
4770
- return void 0;
5064
+ return;
4771
5065
  }
4772
5066
  if (text.charAt(valueStart) !== '"') {
4773
- return void 0;
5067
+ return;
4774
5068
  }
4775
5069
  let valueEnd = valueStart + 1;
4776
5070
  let escaped = false;
@@ -4785,7 +5079,7 @@ function extractTopLevelStringProperty(text, property) {
4785
5079
  }
4786
5080
  valueEnd += 1;
4787
5081
  }
4788
- return void 0;
5082
+ return;
4789
5083
  }
4790
5084
  function extractJsonValueSlice(text, valueStart) {
4791
5085
  if (valueStart >= text.length) {
@@ -4949,10 +5243,12 @@ function emitToolCallFromParsed(state, controller, parsedToolCall, tools) {
4949
5243
  }
4950
5244
  function canonicalizeArgumentsProgressInput(progress, toolName, tools) {
4951
5245
  if (progress.argumentsText === void 0 || !progress.argumentsComplete) {
4952
- return void 0;
5246
+ return;
4953
5247
  }
4954
5248
  try {
4955
- const parsedArguments = parse3(progress.argumentsText);
5249
+ const parsedArguments = parse3(
5250
+ normalizeJsonStringCtrl(progress.argumentsText)
5251
+ );
4956
5252
  return stringifyToolInputWithSchema({
4957
5253
  toolName,
4958
5254
  args: parsedArguments,
@@ -4960,7 +5256,7 @@ function canonicalizeArgumentsProgressInput(progress, toolName, tools) {
4960
5256
  fallback: canonicalizeToolInput
4961
5257
  });
4962
5258
  } catch (e) {
4963
- return void 0;
5259
+ return;
4964
5260
  }
4965
5261
  }
4966
5262
  function emitToolInputProgress(state, controller, tools) {
@@ -5012,14 +5308,16 @@ function closeTextBlock(state, controller) {
5012
5308
  }
5013
5309
  }
5014
5310
  function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer, tools, options) {
5015
- var _a;
5311
+ var _a, _b, _c, _d;
5016
5312
  if (!state.currentToolCallJson && trailingBuffer.length === 0) {
5017
5313
  state.isInsideToolCall = false;
5018
5314
  return;
5019
5315
  }
5020
5316
  if (state.currentToolCallJson) {
5021
5317
  try {
5022
- const parsedToolCall = parse3(state.currentToolCallJson);
5318
+ const parsedToolCall = parse3(
5319
+ normalizeJsonStringCtrl(state.currentToolCallJson)
5320
+ );
5023
5321
  emitToolCallFromParsed(state, controller, parsedToolCall, tools);
5024
5322
  state.currentToolCallJson = "";
5025
5323
  state.isInsideToolCall = false;
@@ -5051,11 +5349,19 @@ function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer
5051
5349
  id: errorId
5052
5350
  });
5053
5351
  }
5352
+ const streamingToolCallId = (_b = (_a = state.activeToolInput) == null ? void 0 : _a.id) != null ? _b : generateToolCallId();
5353
+ const streamingToolName = (_c = state.activeToolInput) == null ? void 0 : _c.toolName;
5054
5354
  closeToolInput(state, controller);
5055
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
5355
+ const toolName = streamingToolName != null ? streamingToolName : state.currentToolCallJson ? extractStreamingToolCallProgress(state.currentToolCallJson).toolName : void 0;
5356
+ (_d = options == null ? void 0 : options.onError) == null ? void 0 : _d.call(
5056
5357
  options,
5057
5358
  shouldEmitRawFallback ? "Could not complete streaming JSON tool call at finish; emitting original text." : "Could not complete streaming JSON tool call at finish.",
5058
- { toolCall: errorContent }
5359
+ {
5360
+ toolCall: errorContent,
5361
+ toolCallId: streamingToolCallId,
5362
+ toolName,
5363
+ dropReason: "unfinished-tool-call"
5364
+ }
5059
5365
  );
5060
5366
  state.currentToolCallJson = "";
5061
5367
  state.isInsideToolCall = false;
@@ -5100,14 +5406,18 @@ function publishText(text, state, controller, tools) {
5100
5406
  }
5101
5407
  }
5102
5408
  function emitToolCall(context) {
5103
- var _a;
5409
+ var _a, _b, _c, _d, _e;
5104
5410
  const { state, controller, toolCallStart, toolCallEnd, options, tools } = context;
5105
5411
  try {
5106
- const parsedToolCall = parse3(state.currentToolCallJson);
5412
+ const parsedToolCall = parse3(
5413
+ normalizeJsonStringCtrl(state.currentToolCallJson)
5414
+ );
5107
5415
  emitToolCallFromParsed(state, controller, parsedToolCall, tools);
5108
5416
  } catch (error) {
5109
5417
  const errorContent = `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`;
5110
5418
  const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
5419
+ const streamingToolCallId = (_b = (_a = state.activeToolInput) == null ? void 0 : _a.id) != null ? _b : generateToolCallId();
5420
+ const streamingToolName = (_d = (_c = state.activeToolInput) == null ? void 0 : _c.toolName) != null ? _d : extractStreamingToolCallProgress(state.currentToolCallJson).toolName;
5111
5421
  logParseFailure({
5112
5422
  phase: "stream",
5113
5423
  reason: "Failed to parse streaming tool call JSON segment",
@@ -5131,11 +5441,15 @@ function emitToolCall(context) {
5131
5441
  });
5132
5442
  }
5133
5443
  closeToolInput(state, controller);
5134
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
5444
+ (_e = options == null ? void 0 : options.onError) == null ? void 0 : _e.call(
5135
5445
  options,
5136
5446
  shouldEmitRawFallback ? "Could not process streaming JSON tool call; emitting original text." : "Could not process streaming JSON tool call.",
5137
5447
  {
5138
- toolCall: errorContent
5448
+ toolCall: errorContent,
5449
+ error,
5450
+ toolCallId: streamingToolCallId,
5451
+ toolName: streamingToolName,
5452
+ dropReason: "malformed-tool-call-body"
5139
5453
  }
5140
5454
  );
5141
5455
  }
@@ -5152,24 +5466,118 @@ function processTagMatch(context) {
5152
5466
  state.activeToolInput = null;
5153
5467
  }
5154
5468
  }
5155
- function processBufferTags(context) {
5469
+ function recoverNestedStreamingToolCall(options) {
5470
+ var _a, _b, _c, _d;
5471
+ const { context, jsonSoFar, nestedStartIndex, startIndex, tag } = options;
5472
+ const {
5473
+ state,
5474
+ controller,
5475
+ toolCallStart,
5476
+ toolCallEnd,
5477
+ options: parserOptions
5478
+ } = context;
5479
+ const droppedToolCall = `${toolCallStart}${jsonSoFar.slice(
5480
+ 0,
5481
+ nestedStartIndex
5482
+ )}`;
5483
+ const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(parserOptions);
5484
+ const streamingToolCallId = (_a = state.activeToolInput) == null ? void 0 : _a.id;
5485
+ const streamingToolName = (_c = (_b = state.activeToolInput) == null ? void 0 : _b.toolName) != null ? _c : extractStreamingToolCallProgress(jsonSoFar.slice(0, nestedStartIndex)).toolName;
5486
+ logParseFailure({
5487
+ phase: "stream",
5488
+ reason: "Abandoning malformed streaming tool call before nested start tag",
5489
+ snippet: droppedToolCall
5490
+ });
5491
+ if (shouldEmitRawFallback) {
5492
+ const errorId = generateId();
5493
+ controller.enqueue({
5494
+ type: "text-start",
5495
+ id: errorId
5496
+ });
5497
+ controller.enqueue({
5498
+ type: "text-delta",
5499
+ id: errorId,
5500
+ delta: droppedToolCall
5501
+ });
5502
+ controller.enqueue({
5503
+ type: "text-end",
5504
+ id: errorId
5505
+ });
5506
+ }
5507
+ closeToolInput(state, controller);
5508
+ (_d = parserOptions == null ? void 0 : parserOptions.onError) == null ? void 0 : _d.call(
5509
+ parserOptions,
5510
+ 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.",
5511
+ {
5512
+ toolCall: droppedToolCall,
5513
+ toolCallId: streamingToolCallId,
5514
+ toolName: streamingToolName,
5515
+ dropReason: "malformed-nested-tool-call"
5516
+ }
5517
+ );
5518
+ state.currentToolCallJson = "";
5519
+ state.isInsideToolCall = false;
5520
+ state.buffer = jsonSoFar.slice(nestedStartIndex) + toolCallEnd + state.buffer.slice(startIndex + tag.length);
5521
+ return getPotentialStartIndex(state.buffer, toolCallStart);
5522
+ }
5523
+ function processInsideToolCallBoundary(context) {
5156
5524
  const { state, controller, toolCallStart, toolCallEnd, tools } = context;
5157
- let startIndex = getPotentialStartIndex(
5158
- state.buffer,
5159
- state.isInsideToolCall ? toolCallEnd : toolCallStart
5525
+ const currentLength = state.currentToolCallJson.length;
5526
+ const combined = state.currentToolCallJson + state.buffer;
5527
+ const boundary = findToolCallBoundaryOutsideRjsonSyntax(
5528
+ combined,
5529
+ 0,
5530
+ toolCallStart,
5531
+ toolCallEnd
5532
+ );
5533
+ if (boundary == null) {
5534
+ return false;
5535
+ }
5536
+ const relativeEndIndex = boundary.endIdx - currentLength;
5537
+ if (relativeEndIndex < 0) {
5538
+ return false;
5539
+ }
5540
+ if (boundary.kind === "nested") {
5541
+ recoverNestedStreamingToolCall({
5542
+ context,
5543
+ jsonSoFar: combined.slice(0, boundary.endIdx),
5544
+ nestedStartIndex: boundary.nestedStartIndex,
5545
+ startIndex: relativeEndIndex,
5546
+ tag: toolCallEnd
5547
+ });
5548
+ return true;
5549
+ }
5550
+ publishText(
5551
+ state.buffer.slice(0, relativeEndIndex),
5552
+ state,
5553
+ controller,
5554
+ tools
5160
5555
  );
5556
+ state.buffer = state.buffer.slice(relativeEndIndex + toolCallEnd.length);
5557
+ processTagMatch(context);
5558
+ return true;
5559
+ }
5560
+ function processBufferTags(context) {
5561
+ const { state, controller, toolCallStart, tools } = context;
5562
+ while (state.isInsideToolCall) {
5563
+ if (!processInsideToolCallBoundary(context)) {
5564
+ return;
5565
+ }
5566
+ }
5567
+ let startIndex = getPotentialStartIndex(state.buffer, toolCallStart);
5161
5568
  while (startIndex != null) {
5162
- const tag = state.isInsideToolCall ? toolCallEnd : toolCallStart;
5163
- if (startIndex + tag.length > state.buffer.length) {
5569
+ if (startIndex + toolCallStart.length > state.buffer.length) {
5164
5570
  break;
5165
5571
  }
5166
5572
  publishText(state.buffer.slice(0, startIndex), state, controller, tools);
5167
- state.buffer = state.buffer.slice(startIndex + tag.length);
5573
+ state.buffer = state.buffer.slice(startIndex + toolCallStart.length);
5168
5574
  processTagMatch(context);
5169
- startIndex = getPotentialStartIndex(
5170
- state.buffer,
5171
- state.isInsideToolCall ? toolCallEnd : toolCallStart
5172
- );
5575
+ while (state.isInsideToolCall) {
5576
+ if (!processInsideToolCallBoundary(context)) {
5577
+ return;
5578
+ }
5579
+ }
5580
+ startIndex = getPotentialStartIndex(state.buffer, toolCallStart);
5173
5581
  }
5174
5582
  }
5175
5583
  function handlePartialTag(state, controller, toolCallStart, toolCallEnd, tools) {
@@ -5207,6 +5615,7 @@ var hermesProtocol = ({
5207
5615
  toolCallStart = "<tool_call>",
5208
5616
  toolCallEnd = "</tool_call>"
5209
5617
  } = {}) => ({
5618
+ ...validateNonEmptyDelimiters(toolCallStart, toolCallEnd),
5210
5619
  formatTools({
5211
5620
  tools,
5212
5621
  toolSystemPromptTemplate
@@ -5231,24 +5640,42 @@ var hermesProtocol = ({
5231
5640
  text,
5232
5641
  options
5233
5642
  }) {
5234
- const startEsc = escapeRegExp(toolCallStart);
5235
- const endEsc = escapeRegExp(toolCallEnd);
5236
- const toolCallRegex = new RegExp(
5237
- `${startEsc}([\0-\uFFFF]*?)${endEsc}`,
5238
- "gs"
5239
- );
5240
5643
  const processedElements = [];
5241
5644
  let currentIndex = 0;
5242
- let match = toolCallRegex.exec(text);
5243
- while (match !== null) {
5244
- currentIndex = processMatchedToolCall({
5245
- match,
5645
+ let searchFrom = 0;
5646
+ while (searchFrom < text.length) {
5647
+ const span = findNextToolCallSpan(
5246
5648
  text,
5247
- currentIndex,
5248
- processedElements,
5249
- options
5250
- });
5251
- match = toolCallRegex.exec(text);
5649
+ searchFrom,
5650
+ toolCallStart,
5651
+ toolCallEnd
5652
+ );
5653
+ if (span === null) {
5654
+ break;
5655
+ }
5656
+ if (!span.found) {
5657
+ const skipTo = span.startIdx + toolCallStart.length;
5658
+ if (skipTo > currentIndex) {
5659
+ addTextSegment(text.slice(currentIndex, skipTo), processedElements);
5660
+ currentIndex = skipTo;
5661
+ }
5662
+ searchFrom = skipTo;
5663
+ continue;
5664
+ }
5665
+ const toolCallJson = text.slice(span.jsonStart, span.endIdx);
5666
+ const fullMatch = text.slice(
5667
+ span.startIdx,
5668
+ span.endIdx + toolCallEnd.length
5669
+ );
5670
+ if (span.startIdx > currentIndex) {
5671
+ addTextSegment(
5672
+ text.slice(currentIndex, span.startIdx),
5673
+ processedElements
5674
+ );
5675
+ }
5676
+ processToolCallJson(toolCallJson, fullMatch, processedElements, options);
5677
+ currentIndex = span.endIdx + toolCallEnd.length;
5678
+ searchFrom = currentIndex;
5252
5679
  }
5253
5680
  if (currentIndex < text.length) {
5254
5681
  const remainingText = text.slice(currentIndex);
@@ -5301,14 +5728,26 @@ var hermesProtocol = ({
5301
5728
  });
5302
5729
  },
5303
5730
  extractToolCallSegments({ text }) {
5304
- const startEsc = escapeRegExp(toolCallStart);
5305
- const endEsc = escapeRegExp(toolCallEnd);
5306
- const regex = new RegExp(`${startEsc}([\0-\uFFFF]*?)${endEsc}`, "gs");
5307
5731
  const segments = [];
5308
- let m = regex.exec(text);
5309
- while (m != null) {
5310
- segments.push(m[0]);
5311
- m = regex.exec(text);
5732
+ let searchFrom = 0;
5733
+ while (searchFrom < text.length) {
5734
+ const span = findNextToolCallSpan(
5735
+ text,
5736
+ searchFrom,
5737
+ toolCallStart,
5738
+ toolCallEnd
5739
+ );
5740
+ if (span === null) {
5741
+ break;
5742
+ }
5743
+ if (!span.found) {
5744
+ searchFrom = span.startIdx + toolCallStart.length;
5745
+ continue;
5746
+ }
5747
+ segments.push(
5748
+ text.slice(span.startIdx, span.endIdx + toolCallEnd.length)
5749
+ );
5750
+ searchFrom = span.endIdx + toolCallEnd.length;
5312
5751
  }
5313
5752
  return segments;
5314
5753
  }
@@ -5597,7 +6036,13 @@ function processToolCall(params) {
5597
6036
  (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
5598
6037
  options,
5599
6038
  `Could not process XML tool call: ${toolCall.toolName}`,
5600
- { toolCall: originalCallText, error }
6039
+ {
6040
+ toolCall: originalCallText,
6041
+ error,
6042
+ toolName: toolCall.toolName,
6043
+ toolCallId: generateToolCallId(),
6044
+ dropReason: "malformed-tool-call-body"
6045
+ }
5601
6046
  );
5602
6047
  processedElements.push({ type: "text", text: originalCallText });
5603
6048
  }
@@ -6039,7 +6484,10 @@ function handleStreamingToolCallEnd(params) {
6039
6484
  });
6040
6485
  (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
6041
6486
  toolCall: original,
6042
- error
6487
+ error,
6488
+ toolName: currentToolCall.name,
6489
+ toolCallId: currentToolCall.toolCallId,
6490
+ dropReason: "malformed-tool-call-body"
6043
6491
  });
6044
6492
  }
6045
6493
  }
@@ -6601,7 +7049,13 @@ var morphXmlProtocol = (protocolOptions) => {
6601
7049
  (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
6602
7050
  options,
6603
7051
  "Could not complete streaming XML tool call at finish.",
6604
- { toolCall: unfinishedContent, error }
7052
+ {
7053
+ toolCall: unfinishedContent,
7054
+ toolCallId: currentToolCall.toolCallId,
7055
+ toolName: currentToolCall.name,
7056
+ dropReason: "unfinished-tool-call",
7057
+ error
7058
+ }
6605
7059
  );
6606
7060
  }
6607
7061
  buffer = "";
@@ -6827,7 +7281,8 @@ var QWEN3CODER_TOOL_PARSER_CALL_TAG_NAMES = /* @__PURE__ */ new Set([
6827
7281
  "invoke",
6828
7282
  "tool_call"
6829
7283
  ]);
6830
- var CALL_SHORTHAND_VALUE_RE = /^<\s*(call|function|tool|invoke)\b\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>/]+))/i;
7284
+ var CALL_SHORTHAND_VALUE_RE = /^<\s*(call|function|tool|invoke)\b\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>/<]+))/i;
7285
+ var NESTED_CALL_SHORTHAND_VALUE_RE = /<\s*(?:call|function|tool|invoke)\b\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>/<]+))/i;
6831
7286
  var QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_START_RE = /<\s*(?!\/)\s*(call|function|tool|invoke)\b/i;
6832
7287
  var QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_TAG_RE = /<\s*(?!\/)\s*(call|function|tool|invoke)\b[^>]*>/i;
6833
7288
  var QWEN3CODER_TOOL_PARSER_STREAM_TOOL_CALL_CLOSE_TAG_RE = /<\s*\/\s*tool_call\s*>/i;
@@ -7226,6 +7681,12 @@ function getShorthandValue(openTag) {
7226
7681
  }
7227
7682
  return unescapeXml(value);
7228
7683
  }
7684
+ function extractShorthandToolNameFromRaw(rawText) {
7685
+ var _a, _b;
7686
+ const match = NESTED_CALL_SHORTHAND_VALUE_RE.exec(rawText);
7687
+ 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];
7688
+ return value ? unescapeXml(value) : null;
7689
+ }
7229
7690
  function extractFirstTagText(xml, tagName) {
7230
7691
  var _a;
7231
7692
  const lower = xml.toLowerCase();
@@ -7508,7 +7969,7 @@ function parseQwen3CoderToolParserClosedMatches(inner, outerNameAttr) {
7508
7969
  var _a, _b;
7509
7970
  const callBlockMatches = Array.from(inner.matchAll(CALL_BLOCK_RE));
7510
7971
  if (callBlockMatches.length === 0) {
7511
- return void 0;
7972
+ return;
7512
7973
  }
7513
7974
  const closedBlocks = [];
7514
7975
  let lastClosedEnd = 0;
@@ -7547,6 +8008,20 @@ function parseQwen3CoderToolParserClosedMatches(inner, outerNameAttr) {
7547
8008
  }
7548
8009
  return closedCalls.concat(trailingCalls);
7549
8010
  }
8011
+ 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;
8012
+ function extractQwen3CoderToolNameFromMarkup(markup) {
8013
+ var _a, _b, _c, _d, _e;
8014
+ const match = markup.match(QWEN3CODER_TOOL_NAME_SALVAGE_REGEX);
8015
+ if (!match) {
8016
+ return;
8017
+ }
8018
+ 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];
8019
+ if (!name) {
8020
+ return;
8021
+ }
8022
+ const trimmed = name.trim();
8023
+ return trimmed.length > 0 ? trimmed : void 0;
8024
+ }
7550
8025
  function parseQwen3CoderToolParserToolCallSegment(segment) {
7551
8026
  var _a;
7552
8027
  const extracted = extractToolCallInnerXml(segment);
@@ -7671,7 +8146,12 @@ var qwen3CoderProtocol = () => ({
7671
8146
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
7672
8147
  options,
7673
8148
  "Could not process Qwen3CoderToolParser XML tool call; keeping original text.",
7674
- { toolCall: fallbackText }
8149
+ {
8150
+ toolCall: fallbackText,
8151
+ toolName: extractQwen3CoderToolNameFromMarkup(segment),
8152
+ toolCallId: generateToolCallId(),
8153
+ dropReason: "malformed-tool-call-body"
8154
+ }
7675
8155
  );
7676
8156
  processedElements.push({ type: "text", text: fallbackText });
7677
8157
  return false;
@@ -7684,7 +8164,12 @@ var qwen3CoderProtocol = () => ({
7684
8164
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
7685
8165
  options,
7686
8166
  "Could not process Qwen3CoderToolParser <function> call; keeping original text.",
7687
- { toolCall: raw }
8167
+ {
8168
+ toolCall: raw,
8169
+ toolName: extractQwen3CoderToolNameFromMarkup(raw),
8170
+ toolCallId: generateToolCallId(),
8171
+ dropReason: "malformed-tool-call-body"
8172
+ }
7688
8173
  );
7689
8174
  processedElements.push({ type: "text", text: raw });
7690
8175
  };
@@ -7830,9 +8315,7 @@ var qwen3CoderProtocol = () => ({
7830
8315
  tryEmitToolCallSegment(synthetic, trailing);
7831
8316
  return true;
7832
8317
  };
7833
- const tryParseCallBlocksWithoutWrapper = () => {
7834
- return tryParseCallBlocksWithoutWrapperText(text);
7835
- };
8318
+ const tryParseCallBlocksWithoutWrapper = () => tryParseCallBlocksWithoutWrapperText(text);
7836
8319
  const tryParseSingleFunctionCall = () => {
7837
8320
  const lowerText = text.toLowerCase();
7838
8321
  const startIndex = lowerText.indexOf("<function");
@@ -7934,7 +8417,7 @@ var qwen3CoderProtocol = () => ({
7934
8417
  });
7935
8418
  };
7936
8419
  const finalizeCall = (controller, callState, fallbackToolName, rawToolCallText = null) => {
7937
- var _a, _b;
8420
+ var _a, _b, _c, _d;
7938
8421
  const resolvedToolName = (_a = callState.toolName) != null ? _a : fallbackToolName;
7939
8422
  if (!resolvedToolName || resolvedToolName.trim().length === 0) {
7940
8423
  const shouldEmitRaw = shouldEmitRawToolCallTextOnError(options);
@@ -7948,12 +8431,14 @@ var qwen3CoderProtocol = () => ({
7948
8431
  flushText(controller, rawText);
7949
8432
  }
7950
8433
  });
7951
- (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
8434
+ (_d = options == null ? void 0 : options.onError) == null ? void 0 : _d.call(
7952
8435
  options,
7953
8436
  shouldEmitRaw && rawToolCallText ? "Could not resolve Qwen3CoderToolParser tool name for tool call; emitting original text." : "Could not resolve Qwen3CoderToolParser tool name for tool call",
7954
8437
  {
7955
8438
  toolCallId: callState.toolCallId,
7956
- toolCall: rawToolCallText
8439
+ toolCall: rawToolCallText,
8440
+ toolName: (_c = (_b = callState.toolName) != null ? _b : fallbackToolName) != null ? _c : void 0,
8441
+ dropReason: "unresolved-tool-name"
7957
8442
  }
7958
8443
  );
7959
8444
  return false;
@@ -8409,25 +8894,36 @@ var qwen3CoderProtocol = () => ({
8409
8894
  }
8410
8895
  }
8411
8896
  };
8412
- const reportUnfinishedToolCallAtFinish = (controller, rawToolCall) => {
8413
- var _a;
8897
+ const reportUnfinishedToolCallAtFinish = (controller, rawToolCall, metadata = {}) => {
8898
+ var _a, _b;
8414
8899
  const shouldEmitRaw = shouldEmitRawToolCallTextOnError(options);
8415
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
8900
+ const toolName = (_a = metadata.toolName) != null ? _a : extractShorthandToolNameFromRaw(rawToolCall);
8901
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
8416
8902
  options,
8417
8903
  shouldEmitRaw ? "Could not complete streaming Qwen3CoderToolParser XML tool call at finish; emitting original text." : "Could not complete streaming Qwen3CoderToolParser XML tool call at finish.",
8418
- { toolCall: rawToolCall }
8904
+ {
8905
+ toolCall: rawToolCall,
8906
+ ...metadata.toolCallId ? { toolCallId: metadata.toolCallId } : {},
8907
+ ...toolName ? { toolName } : {},
8908
+ dropReason: "unfinished-tool-call"
8909
+ }
8419
8910
  );
8420
8911
  if (shouldEmitRaw) {
8421
8912
  flushText(controller, rawToolCall);
8422
8913
  }
8423
8914
  };
8424
- const reportUnfinishedImplicitCallAtFinish = (controller, rawCallText) => {
8915
+ const reportUnfinishedImplicitCallAtFinish = (controller, rawCallText, callState) => {
8425
8916
  var _a;
8426
8917
  const shouldEmitRaw = shouldEmitRawToolCallTextOnError(options);
8427
8918
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
8428
8919
  options,
8429
8920
  shouldEmitRaw ? "Could not complete streaming Qwen3CoderToolParser call block at finish; emitting original text." : "Could not complete streaming Qwen3CoderToolParser call block at finish.",
8430
- { toolCall: rawCallText }
8921
+ {
8922
+ toolCall: rawCallText,
8923
+ toolCallId: callState.toolCallId,
8924
+ ...callState.toolName ? { toolName: callState.toolName } : {},
8925
+ dropReason: "unfinished-tool-call"
8926
+ }
8431
8927
  );
8432
8928
  if (shouldEmitRaw) {
8433
8929
  flushText(controller, rawCallText);
@@ -8478,7 +8974,10 @@ var qwen3CoderProtocol = () => ({
8478
8974
  flushText(controller, result.trailingText);
8479
8975
  }
8480
8976
  if (!result.ok && toolCall.emittedToolCallCount === 0) {
8481
- reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
8977
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw, {
8978
+ toolCallId: toolCall.activeCall.toolCallId,
8979
+ ...toolCall.activeCall.toolName ? { toolName: toolCall.activeCall.toolName } : {}
8980
+ });
8482
8981
  }
8483
8982
  } else if (toolCall.mode === "multi") {
8484
8983
  if (toolCall.activeCall) {
@@ -8495,14 +8994,21 @@ var qwen3CoderProtocol = () => ({
8495
8994
  flushText(controller, result.trailingText);
8496
8995
  }
8497
8996
  if (!result.ok && toolCall.emittedToolCallCount === 0) {
8498
- reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
8997
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw, {
8998
+ toolCallId: toolCall.activeCall.toolCallId,
8999
+ ...toolCall.activeCall.toolName ? { toolName: toolCall.activeCall.toolName } : {}
9000
+ });
8499
9001
  }
8500
9002
  toolCall.activeCall = null;
8501
9003
  } else if (toolCall.emittedToolCallCount === 0) {
8502
- reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
9004
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw, {
9005
+ toolName: toolCall.outerNameAttr
9006
+ });
8503
9007
  }
8504
9008
  } else {
8505
- reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
9009
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw, {
9010
+ toolName: toolCall.outerNameAttr
9011
+ });
8506
9012
  }
8507
9013
  toolCall = null;
8508
9014
  }
@@ -8520,7 +9026,8 @@ var qwen3CoderProtocol = () => ({
8520
9026
  if (!result.ok && openTag) {
8521
9027
  reportUnfinishedImplicitCallAtFinish(
8522
9028
  controller,
8523
- callState.raw || openTag + callState.buffer
9029
+ callState.raw || openTag + callState.buffer,
9030
+ callState
8524
9031
  );
8525
9032
  }
8526
9033
  } else {
@@ -8898,26 +9405,28 @@ function findToolCalls2(text, toolNames) {
8898
9405
  );
8899
9406
  return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
8900
9407
  }
8901
- function parseYamlContent(yamlContent, options) {
8902
- var _a, _b;
9408
+ function yamlFailureCause(failure) {
9409
+ if (failure.kind === "yaml-parse-error") {
9410
+ return { kind: "yaml-parse-error", errors: failure.errors };
9411
+ }
9412
+ return { kind: "yaml-non-mapping" };
9413
+ }
9414
+ function parseYamlContent(yamlContent) {
8903
9415
  const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
8904
9416
  if (nonEmptyLines.length === 0) {
8905
- return {};
9417
+ return { ok: true, value: {} };
8906
9418
  }
8907
9419
  const parsed = parseYamlDocumentAsMapping(normalized);
8908
9420
  if (parsed.errors.length > 0) {
8909
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "YAML parse error", {
8910
- errors: parsed.errors
8911
- });
8912
- return null;
9421
+ return {
9422
+ ok: false,
9423
+ failure: { kind: "yaml-parse-error", errors: parsed.errors }
9424
+ };
8913
9425
  }
8914
9426
  if (parsed.value === null) {
8915
- (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
8916
- got: "non-mapping"
8917
- });
8918
- return null;
9427
+ return { ok: false, failure: { kind: "yaml-non-mapping" } };
8919
9428
  }
8920
- return parsed.value;
9429
+ return { ok: true, value: parsed.value };
8921
9430
  }
8922
9431
  function parseYamlContentForStreamProgress(yamlContent) {
8923
9432
  const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
@@ -8949,20 +9458,25 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
8949
9458
  return currentIndex;
8950
9459
  }
8951
9460
  addTextSegment(text.slice(currentIndex, tc.startIndex), processedElements);
8952
- const parsedArgs = parseYamlContent(tc.content, options);
8953
- if (parsedArgs === null) {
8954
- const originalText = text.slice(tc.startIndex, tc.endIndex);
8955
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse YAML tool call", {
8956
- toolCall: originalText
8957
- });
8958
- processedElements.push({ type: "text", text: originalText });
8959
- } else {
9461
+ const result = parseYamlContent(tc.content);
9462
+ if (result.ok) {
8960
9463
  processedElements.push({
8961
9464
  type: "tool-call",
8962
9465
  toolCallId: generateToolCallId(),
8963
9466
  toolName: tc.toolName,
8964
- input: JSON.stringify(parsedArgs)
9467
+ input: JSON.stringify(result.value)
9468
+ });
9469
+ } else {
9470
+ const originalText = text.slice(tc.startIndex, tc.endIndex);
9471
+ const cause = yamlFailureCause(result.failure);
9472
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse YAML tool call", {
9473
+ toolCall: originalText,
9474
+ toolName: tc.toolName,
9475
+ toolCallId: generateToolCallId(),
9476
+ dropReason: "malformed-tool-call-body",
9477
+ cause
8965
9478
  });
9479
+ processedElements.push({ type: "text", text: originalText });
8966
9480
  }
8967
9481
  return tc.endIndex;
8968
9482
  }
@@ -8989,327 +9503,335 @@ function stripTrailingPartialCloseTag(content, toolName) {
8989
9503
  )}${preservedLeadingWhitespace}`;
8990
9504
  return contentWithoutPartial.trimEnd();
8991
9505
  }
8992
- var yamlXmlProtocol = (_protocolOptions) => {
8993
- return {
8994
- formatTools({ tools, toolSystemPromptTemplate }) {
8995
- return formatToolsWithPromptTemplate({ tools, toolSystemPromptTemplate });
8996
- },
8997
- formatToolCall(toolCall) {
8998
- let args = {};
8999
- if (toolCall.input != null) {
9000
- try {
9001
- args = JSON.parse(toolCall.input);
9002
- } catch (e) {
9003
- args = { value: toolCall.input };
9004
- }
9506
+ var yamlXmlProtocol = (_protocolOptions) => ({
9507
+ formatTools({ tools, toolSystemPromptTemplate }) {
9508
+ return formatToolsWithPromptTemplate({ tools, toolSystemPromptTemplate });
9509
+ },
9510
+ formatToolCall(toolCall) {
9511
+ let args = {};
9512
+ if (toolCall.input != null) {
9513
+ try {
9514
+ args = JSON.parse(toolCall.input);
9515
+ } catch (e) {
9516
+ args = { value: toolCall.input };
9005
9517
  }
9006
- const yamlContent = import_yaml.default.stringify(args);
9007
- return `<${toolCall.toolName}>
9518
+ }
9519
+ const yamlContent = import_yaml.default.stringify(args);
9520
+ return `<${toolCall.toolName}>
9008
9521
  ${yamlContent}</${toolCall.toolName}>`;
9009
- },
9010
- parseGeneratedText({ text, tools, options }) {
9011
- const toolNames = extractToolNames(tools);
9012
- if (toolNames.length === 0) {
9013
- return [{ type: "text", text }];
9014
- }
9015
- const processedElements = [];
9016
- let currentIndex = 0;
9017
- let parseText = text;
9018
- let toolCalls = findToolCalls2(parseText, toolNames);
9019
- if (toolCalls.length === 0) {
9020
- const repaired = tryRepairXmlSelfClosingRootWithBody(
9021
- parseText,
9022
- toolNames
9023
- );
9024
- if (repaired) {
9025
- const repairedCalls = findToolCalls2(repaired, toolNames);
9026
- if (repairedCalls.length > 0) {
9027
- parseText = repaired;
9028
- toolCalls = repairedCalls;
9029
- }
9522
+ },
9523
+ parseGeneratedText({ text, tools, options }) {
9524
+ const toolNames = extractToolNames(tools);
9525
+ if (toolNames.length === 0) {
9526
+ return [{ type: "text", text }];
9527
+ }
9528
+ const processedElements = [];
9529
+ let currentIndex = 0;
9530
+ let parseText = text;
9531
+ let toolCalls = findToolCalls2(parseText, toolNames);
9532
+ if (toolCalls.length === 0) {
9533
+ const repaired = tryRepairXmlSelfClosingRootWithBody(
9534
+ parseText,
9535
+ toolNames
9536
+ );
9537
+ if (repaired) {
9538
+ const repairedCalls = findToolCalls2(repaired, toolNames);
9539
+ if (repairedCalls.length > 0) {
9540
+ parseText = repaired;
9541
+ toolCalls = repairedCalls;
9030
9542
  }
9031
9543
  }
9032
- for (const tc of toolCalls) {
9033
- currentIndex = processToolCallMatch(
9034
- parseText,
9035
- tc,
9036
- currentIndex,
9037
- processedElements,
9038
- options
9039
- );
9544
+ }
9545
+ for (const tc of toolCalls) {
9546
+ currentIndex = processToolCallMatch(
9547
+ parseText,
9548
+ tc,
9549
+ currentIndex,
9550
+ processedElements,
9551
+ options
9552
+ );
9553
+ }
9554
+ if (currentIndex < parseText.length) {
9555
+ addTextSegment(parseText.slice(currentIndex), processedElements);
9556
+ }
9557
+ return processedElements;
9558
+ },
9559
+ createStreamParser({ tools, options }) {
9560
+ const toolNames = extractToolNames(tools);
9561
+ let buffer = "";
9562
+ let currentToolCall = null;
9563
+ let currentTextId = null;
9564
+ let hasEmittedTextStart = false;
9565
+ const flushText = createFlushTextHandler(
9566
+ () => currentTextId,
9567
+ (newId) => {
9568
+ currentTextId = newId;
9569
+ },
9570
+ () => hasEmittedTextStart,
9571
+ (value) => {
9572
+ hasEmittedTextStart = value;
9040
9573
  }
9041
- if (currentIndex < parseText.length) {
9042
- addTextSegment(parseText.slice(currentIndex), processedElements);
9574
+ );
9575
+ const emitToolInputProgress2 = (controller, toolContent) => {
9576
+ if (!currentToolCall) {
9577
+ return;
9043
9578
  }
9044
- return processedElements;
9045
- },
9046
- createStreamParser({ tools, options }) {
9047
- const toolNames = extractToolNames(tools);
9048
- let buffer = "";
9049
- let currentToolCall = null;
9050
- let currentTextId = null;
9051
- let hasEmittedTextStart = false;
9052
- const flushText = createFlushTextHandler(
9053
- () => currentTextId,
9054
- (newId) => {
9055
- currentTextId = newId;
9056
- },
9057
- () => hasEmittedTextStart,
9058
- (value) => {
9059
- hasEmittedTextStart = value;
9060
- }
9061
- );
9062
- const emitToolInputProgress2 = (controller, toolContent) => {
9063
- if (!currentToolCall) {
9064
- return;
9065
- }
9066
- const parsedArgs = parseYamlContentForStreamProgress(toolContent);
9067
- if (parsedArgs === null) {
9068
- return;
9069
- }
9070
- const fullInput = stringifyToolInputWithSchema({
9071
- toolName: currentToolCall.name,
9072
- args: parsedArgs,
9579
+ const parsedArgs = parseYamlContentForStreamProgress(toolContent);
9580
+ if (parsedArgs === null) {
9581
+ return;
9582
+ }
9583
+ const fullInput = stringifyToolInputWithSchema({
9584
+ toolName: currentToolCall.name,
9585
+ args: parsedArgs,
9586
+ tools
9587
+ });
9588
+ if (fullInput === "{}" && toolContent.trim().length === 0) {
9589
+ return;
9590
+ }
9591
+ emitToolInputProgressDelta({
9592
+ controller,
9593
+ id: currentToolCall.toolCallId,
9594
+ state: currentToolCall,
9595
+ fullInput
9596
+ });
9597
+ };
9598
+ const processToolCallEnd = (controller, toolContent, toolName, toolCallId) => {
9599
+ var _a;
9600
+ const result = parseYamlContent(toolContent);
9601
+ flushText(controller);
9602
+ if (result.ok) {
9603
+ const finalInput = stringifyToolInputWithSchema({
9604
+ toolName,
9605
+ args: result.value,
9073
9606
  tools
9074
9607
  });
9075
- if (fullInput === "{}" && toolContent.trim().length === 0) {
9076
- return;
9077
- }
9078
- emitToolInputProgressDelta({
9079
- controller,
9080
- id: currentToolCall.toolCallId,
9081
- state: currentToolCall,
9082
- fullInput
9083
- });
9084
- };
9085
- const processToolCallEnd = (controller, toolContent, toolName, toolCallId) => {
9086
- var _a;
9087
- const parsedArgs = parseYamlContent(toolContent, options);
9088
- flushText(controller);
9089
- if (parsedArgs === null) {
9090
- const original = `<${toolName}>${toolContent}</${toolName}>`;
9091
- const emitRawFallback = shouldEmitRawToolCallTextOnError(options);
9092
- emitFailedToolInputLifecycle({
9608
+ if (currentToolCall && currentToolCall.toolCallId === toolCallId) {
9609
+ emitFinalizedToolInputLifecycle({
9093
9610
  controller,
9094
9611
  id: toolCallId,
9095
- emitRawToolCallTextOnError: emitRawFallback,
9096
- rawToolCallText: original,
9097
- emitRawText: (rawText) => {
9098
- flushText(controller, rawText);
9099
- }
9100
- });
9101
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
9102
- toolCall: original
9103
- });
9104
- } else {
9105
- const finalInput = stringifyToolInputWithSchema({
9612
+ state: currentToolCall,
9106
9613
  toolName,
9107
- args: parsedArgs,
9108
- tools
9109
- });
9110
- if (currentToolCall && currentToolCall.toolCallId === toolCallId) {
9111
- emitFinalizedToolInputLifecycle({
9112
- controller,
9113
- id: toolCallId,
9114
- state: currentToolCall,
9115
- toolName,
9116
- finalInput,
9117
- onMismatch: options == null ? void 0 : options.onError
9118
- });
9119
- } else {
9120
- enqueueToolInputEndAndCall({
9121
- controller,
9122
- id: toolCallId,
9123
- toolName,
9124
- input: finalInput
9125
- });
9126
- }
9127
- }
9128
- };
9129
- const finalizeUnclosedToolCall = (controller) => {
9130
- var _a;
9131
- if (!currentToolCall) {
9132
- return;
9133
- }
9134
- emitToolInputProgress2(controller, buffer);
9135
- const { name: toolName, toolCallId } = currentToolCall;
9136
- const reconciledBuffer = stripTrailingPartialCloseTag(buffer, toolName);
9137
- const parsedArgs = parseYamlContent(reconciledBuffer, options);
9138
- flushText(controller);
9139
- if (parsedArgs === null) {
9140
- const unfinishedContent = `<${toolName}>${buffer}`;
9141
- const emitRawFallback = shouldEmitRawToolCallTextOnError(options);
9142
- emitFailedToolInputLifecycle({
9143
- controller,
9144
- id: toolCallId,
9145
- emitRawToolCallTextOnError: emitRawFallback,
9146
- rawToolCallText: unfinishedContent,
9147
- emitRawText: (rawText) => {
9148
- flushText(controller, rawText);
9149
- }
9614
+ finalInput,
9615
+ onMismatch: options == null ? void 0 : options.onError
9150
9616
  });
9151
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
9152
- options,
9153
- "Could not complete streaming YAML tool call at finish.",
9154
- { toolCall: unfinishedContent }
9155
- );
9156
9617
  } else {
9157
- const finalInput = stringifyToolInputWithSchema({
9158
- toolName,
9159
- args: parsedArgs,
9160
- tools
9161
- });
9162
- emitFinalizedToolInputLifecycle({
9618
+ enqueueToolInputEndAndCall({
9163
9619
  controller,
9164
9620
  id: toolCallId,
9165
- state: currentToolCall,
9166
9621
  toolName,
9167
- finalInput,
9168
- onMismatch: options == null ? void 0 : options.onError
9622
+ input: finalInput
9169
9623
  });
9170
9624
  }
9171
- buffer = "";
9172
- currentToolCall = null;
9173
- };
9174
- const handlePendingToolCall = (controller, endTag, toolName) => {
9175
- var _a;
9176
- const endIdx = buffer.indexOf(endTag);
9177
- if (endIdx === -1) {
9178
- emitToolInputProgress2(controller, buffer);
9179
- return false;
9180
- }
9181
- const content = buffer.slice(0, endIdx);
9182
- emitToolInputProgress2(controller, content);
9183
- buffer = buffer.slice(endIdx + endTag.length);
9184
- processToolCallEnd(
9625
+ } else {
9626
+ const original = `<${toolName}>${toolContent}</${toolName}>`;
9627
+ const emitRawFallback = shouldEmitRawToolCallTextOnError(options);
9628
+ emitFailedToolInputLifecycle({
9629
+ controller,
9630
+ id: toolCallId,
9631
+ emitRawToolCallTextOnError: emitRawFallback,
9632
+ rawToolCallText: original,
9633
+ emitRawText: (rawText) => {
9634
+ flushText(controller, rawText);
9635
+ }
9636
+ });
9637
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
9638
+ toolCall: original,
9639
+ toolName,
9640
+ toolCallId,
9641
+ dropReason: "malformed-tool-call-body",
9642
+ cause: yamlFailureCause(result.failure)
9643
+ });
9644
+ }
9645
+ };
9646
+ const finalizeUnclosedToolCall = (controller) => {
9647
+ var _a;
9648
+ if (!currentToolCall) {
9649
+ return;
9650
+ }
9651
+ emitToolInputProgress2(controller, buffer);
9652
+ const { name: toolName, toolCallId } = currentToolCall;
9653
+ const reconciledBuffer = stripTrailingPartialCloseTag(buffer, toolName);
9654
+ const result = parseYamlContent(reconciledBuffer);
9655
+ flushText(controller);
9656
+ if (result.ok) {
9657
+ const finalInput = stringifyToolInputWithSchema({
9658
+ toolName,
9659
+ args: result.value,
9660
+ tools
9661
+ });
9662
+ emitFinalizedToolInputLifecycle({
9185
9663
  controller,
9186
- content,
9664
+ id: toolCallId,
9665
+ state: currentToolCall,
9187
9666
  toolName,
9188
- (_a = currentToolCall == null ? void 0 : currentToolCall.toolCallId) != null ? _a : generateToolCallId()
9667
+ finalInput,
9668
+ onMismatch: options == null ? void 0 : options.onError
9669
+ });
9670
+ } else {
9671
+ const unfinishedContent = `<${toolName}>${buffer}`;
9672
+ const emitRawFallback = shouldEmitRawToolCallTextOnError(options);
9673
+ emitFailedToolInputLifecycle({
9674
+ controller,
9675
+ id: toolCallId,
9676
+ emitRawToolCallTextOnError: emitRawFallback,
9677
+ rawToolCallText: unfinishedContent,
9678
+ emitRawText: (rawText) => {
9679
+ flushText(controller, rawText);
9680
+ }
9681
+ });
9682
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
9683
+ options,
9684
+ "Could not complete streaming YAML tool call at finish.",
9685
+ {
9686
+ toolCall: unfinishedContent,
9687
+ toolCallId,
9688
+ toolName,
9689
+ dropReason: "unfinished-tool-call",
9690
+ cause: yamlFailureCause(result.failure)
9691
+ }
9189
9692
  );
9693
+ }
9694
+ buffer = "";
9695
+ currentToolCall = null;
9696
+ };
9697
+ const handlePendingToolCall = (controller, endTag, toolName) => {
9698
+ var _a;
9699
+ const endIdx = buffer.indexOf(endTag);
9700
+ if (endIdx === -1) {
9701
+ emitToolInputProgress2(controller, buffer);
9702
+ return false;
9703
+ }
9704
+ const content = buffer.slice(0, endIdx);
9705
+ emitToolInputProgress2(controller, content);
9706
+ buffer = buffer.slice(endIdx + endTag.length);
9707
+ processToolCallEnd(
9708
+ controller,
9709
+ content,
9710
+ toolName,
9711
+ (_a = currentToolCall == null ? void 0 : currentToolCall.toolCallId) != null ? _a : generateToolCallId()
9712
+ );
9713
+ currentToolCall = null;
9714
+ return true;
9715
+ };
9716
+ const flushSafeText = (controller) => {
9717
+ const maxTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n} />`.length)) : 0;
9718
+ const tail = Math.max(0, maxTagLen - 1);
9719
+ const safeLen = Math.max(0, buffer.length - tail);
9720
+ if (safeLen > 0) {
9721
+ flushText(controller, buffer.slice(0, safeLen));
9722
+ buffer = buffer.slice(safeLen);
9723
+ }
9724
+ };
9725
+ const handleNewToolTag = (controller, tagIndex, tagName, selfClosing, tagLength) => {
9726
+ if (tagIndex > 0) {
9727
+ flushText(controller, buffer.slice(0, tagIndex));
9728
+ }
9729
+ flushText(controller);
9730
+ if (selfClosing) {
9731
+ buffer = buffer.slice(tagIndex + tagLength);
9732
+ const toolCallId = generateToolCallId();
9733
+ currentToolCall = {
9734
+ name: tagName,
9735
+ toolCallId,
9736
+ emittedInput: ""
9737
+ };
9738
+ controller.enqueue({
9739
+ type: "tool-input-start",
9740
+ id: toolCallId,
9741
+ toolName: tagName
9742
+ });
9743
+ processToolCallEnd(controller, "", tagName, toolCallId);
9190
9744
  currentToolCall = null;
9191
- return true;
9192
- };
9193
- const flushSafeText = (controller) => {
9194
- const maxTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n} />`.length)) : 0;
9195
- const tail = Math.max(0, maxTagLen - 1);
9196
- const safeLen = Math.max(0, buffer.length - tail);
9197
- if (safeLen > 0) {
9198
- flushText(controller, buffer.slice(0, safeLen));
9199
- buffer = buffer.slice(safeLen);
9200
- }
9201
- };
9202
- const handleNewToolTag = (controller, tagIndex, tagName, selfClosing, tagLength) => {
9203
- if (tagIndex > 0) {
9204
- flushText(controller, buffer.slice(0, tagIndex));
9205
- }
9206
- flushText(controller);
9207
- if (selfClosing) {
9208
- buffer = buffer.slice(tagIndex + tagLength);
9209
- const toolCallId = generateToolCallId();
9210
- currentToolCall = {
9211
- name: tagName,
9212
- toolCallId,
9213
- emittedInput: ""
9214
- };
9215
- controller.enqueue({
9216
- type: "tool-input-start",
9217
- id: toolCallId,
9218
- toolName: tagName
9219
- });
9220
- processToolCallEnd(controller, "", tagName, toolCallId);
9221
- currentToolCall = null;
9745
+ } else {
9746
+ const startTag = `<${tagName}>`;
9747
+ buffer = buffer.slice(tagIndex + startTag.length);
9748
+ currentToolCall = {
9749
+ name: tagName,
9750
+ toolCallId: generateToolCallId(),
9751
+ emittedInput: ""
9752
+ };
9753
+ controller.enqueue({
9754
+ type: "tool-input-start",
9755
+ id: currentToolCall.toolCallId,
9756
+ toolName: tagName
9757
+ });
9758
+ }
9759
+ };
9760
+ const processBuffer = (controller) => {
9761
+ while (true) {
9762
+ if (currentToolCall) {
9763
+ const toolName = currentToolCall.name;
9764
+ const endTag = `</${toolName}>`;
9765
+ if (!handlePendingToolCall(controller, endTag, toolName)) {
9766
+ break;
9767
+ }
9222
9768
  } else {
9223
- const startTag = `<${tagName}>`;
9224
- buffer = buffer.slice(tagIndex + startTag.length);
9225
- currentToolCall = {
9226
- name: tagName,
9227
- toolCallId: generateToolCallId(),
9228
- emittedInput: ""
9229
- };
9230
- controller.enqueue({
9231
- type: "tool-input-start",
9232
- id: currentToolCall.toolCallId,
9233
- toolName: tagName
9234
- });
9235
- }
9236
- };
9237
- const processBuffer = (controller) => {
9238
- while (true) {
9239
- if (currentToolCall) {
9240
- const toolName = currentToolCall.name;
9241
- const endTag = `</${toolName}>`;
9242
- if (!handlePendingToolCall(controller, endTag, toolName)) {
9243
- break;
9244
- }
9245
- } else {
9246
- const { index, name, selfClosing, tagLength } = findEarliestToolTag(
9247
- buffer,
9248
- toolNames
9249
- );
9250
- if (index === -1) {
9251
- flushSafeText(controller);
9252
- break;
9253
- }
9254
- handleNewToolTag(controller, index, name, selfClosing, tagLength);
9769
+ const { index, name, selfClosing, tagLength } = findEarliestToolTag(
9770
+ buffer,
9771
+ toolNames
9772
+ );
9773
+ if (index === -1) {
9774
+ flushSafeText(controller);
9775
+ break;
9255
9776
  }
9777
+ handleNewToolTag(controller, index, name, selfClosing, tagLength);
9256
9778
  }
9257
- };
9258
- return new TransformStream({
9259
- transform(chunk, controller) {
9260
- var _a;
9261
- if (chunk.type === "finish") {
9262
- if (currentToolCall) {
9263
- finalizeUnclosedToolCall(controller);
9264
- } else if (buffer) {
9265
- flushText(controller, buffer);
9266
- buffer = "";
9267
- }
9268
- flushText(controller);
9269
- controller.enqueue(chunk);
9270
- return;
9271
- }
9272
- if (chunk.type !== "text-delta") {
9273
- if (!currentToolCall && buffer) {
9274
- flushText(controller, buffer);
9275
- buffer = "";
9276
- }
9277
- controller.enqueue(chunk);
9278
- return;
9279
- }
9280
- const textContent = (_a = chunk.delta) != null ? _a : "";
9281
- buffer += textContent;
9282
- processBuffer(controller);
9283
- },
9284
- flush(controller) {
9779
+ }
9780
+ };
9781
+ return new TransformStream({
9782
+ transform(chunk, controller) {
9783
+ var _a;
9784
+ if (chunk.type === "finish") {
9285
9785
  if (currentToolCall) {
9286
9786
  finalizeUnclosedToolCall(controller);
9287
9787
  } else if (buffer) {
9288
9788
  flushText(controller, buffer);
9289
9789
  buffer = "";
9290
9790
  }
9291
- if (currentTextId && hasEmittedTextStart) {
9292
- controller.enqueue({
9293
- type: "text-end",
9294
- id: currentTextId
9295
- });
9296
- hasEmittedTextStart = false;
9297
- currentTextId = null;
9791
+ flushText(controller);
9792
+ controller.enqueue(chunk);
9793
+ return;
9794
+ }
9795
+ if (chunk.type !== "text-delta") {
9796
+ if (!currentToolCall && buffer) {
9797
+ flushText(controller, buffer);
9798
+ buffer = "";
9298
9799
  }
9800
+ controller.enqueue(chunk);
9801
+ return;
9802
+ }
9803
+ const textContent = (_a = chunk.delta) != null ? _a : "";
9804
+ buffer += textContent;
9805
+ processBuffer(controller);
9806
+ },
9807
+ flush(controller) {
9808
+ if (currentToolCall) {
9809
+ finalizeUnclosedToolCall(controller);
9810
+ } else if (buffer) {
9811
+ flushText(controller, buffer);
9812
+ buffer = "";
9813
+ }
9814
+ if (currentTextId && hasEmittedTextStart) {
9815
+ controller.enqueue({
9816
+ type: "text-end",
9817
+ id: currentTextId
9818
+ });
9819
+ hasEmittedTextStart = false;
9820
+ currentTextId = null;
9299
9821
  }
9300
- });
9301
- },
9302
- extractToolCallSegments({ text, tools }) {
9303
- const toolNames = tools.map((t) => t.name).filter(Boolean);
9304
- if (toolNames.length === 0) {
9305
- return [];
9306
9822
  }
9307
- return findToolCalls2(text, toolNames).map(
9308
- (tc) => `<${tc.toolName}>${tc.content}</${tc.toolName}>`
9309
- );
9823
+ });
9824
+ },
9825
+ extractToolCallSegments({ text, tools }) {
9826
+ const toolNames = tools.map((t) => t.name).filter(Boolean);
9827
+ if (toolNames.length === 0) {
9828
+ return [];
9310
9829
  }
9311
- };
9312
- };
9830
+ return findToolCalls2(text, toolNames).map(
9831
+ (tc) => `<${tc.toolName}>${tc.content}</${tc.toolName}>`
9832
+ );
9833
+ }
9834
+ });
9313
9835
 
9314
9836
  // src/core/utils/dynamic-tool-schema.ts
9315
9837
  function createDynamicIfThenElseSchema(tools) {
@@ -9490,7 +10012,7 @@ function parseJsonCandidate(candidateText) {
9490
10012
  try {
9491
10013
  return parse3(candidateText);
9492
10014
  } catch (e) {
9493
- return void 0;
10015
+ return;
9494
10016
  }
9495
10017
  }
9496
10018
  function extractCodeBlockCandidates(text) {