@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.
package/dist/index.cjs CHANGED
@@ -988,11 +988,6 @@ function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmitte
988
988
  };
989
989
  }
990
990
 
991
- // src/core/utils/regex.ts
992
- function escapeRegExp(literal) {
993
- return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
994
- }
995
-
996
991
  // src/core/utils/streamed-tool-input-delta.ts
997
992
  function emitDelta({
998
993
  controller,
@@ -1974,13 +1969,312 @@ function shouldEmitRawToolCallTextOnError(options) {
1974
1969
  }
1975
1970
 
1976
1971
  // src/core/protocols/hermes-protocol.ts
1972
+ var RJSON_IDENTIFIER_CHAR_REGEX = /[$a-zA-Z0-9_\-+.*?!|&%^/#\\]/;
1973
+ var RJSON_NUMBER_TOKEN_REGEX = /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
1974
+ function validateNonEmptyDelimiters(toolCallStart, toolCallEnd) {
1975
+ if (toolCallStart.length === 0) {
1976
+ throw new TypeError("hermesProtocol toolCallStart must not be empty");
1977
+ }
1978
+ if (toolCallEnd.length === 0) {
1979
+ throw new TypeError("hermesProtocol toolCallEnd must not be empty");
1980
+ }
1981
+ return {};
1982
+ }
1983
+ function isRjsonIdentifierChar(ch) {
1984
+ return ch != null && RJSON_IDENTIFIER_CHAR_REGEX.test(ch);
1985
+ }
1986
+ function isRjsonPropertyLikeDelimiter(startTag) {
1987
+ const key = startTag.endsWith(":") ? startTag.slice(0, -1) : "";
1988
+ return key.length > 0 && [...key].every((ch) => isRjsonIdentifierChar(ch));
1989
+ }
1990
+ function previousRjsonToken(json, index, minIndex = 0) {
1991
+ let start = index - 1;
1992
+ while (start >= minIndex && isRjsonIdentifierChar(json[start])) {
1993
+ start -= 1;
1994
+ }
1995
+ return json.slice(start + 1, index);
1996
+ }
1997
+ function previousTokenAllowsComment(json, index, minIndex = 0) {
1998
+ const previous = previousRjsonToken(json, index, minIndex);
1999
+ if (previous.length === 0) {
2000
+ return true;
2001
+ }
2002
+ return RJSON_NUMBER_TOKEN_REGEX.test(previous) || previous === "true" || previous === "false" || previous === "null";
2003
+ }
2004
+ function startsRjsonComment(json, index, minIndex = 0) {
2005
+ if (!(json[index] === "/" && json[index + 1] === "/" || json[index] === "/" && json[index + 1] === "*")) {
2006
+ return false;
2007
+ }
2008
+ if (index > minIndex && isRjsonIdentifierChar(json[index - 1])) {
2009
+ return previousTokenAllowsComment(json, index, minIndex);
2010
+ }
2011
+ return true;
2012
+ }
2013
+ function hasNestedStartBoundary(segment, startIndex) {
2014
+ const previous = segment[startIndex - 1];
2015
+ return previous == null || WHITESPACE_JSON_REGEX.test(previous) || previous === "}";
2016
+ }
2017
+ function isLikelyNestedToolCallStart(segment, startIndex, startTag) {
2018
+ if (isRjsonPropertyLikeDelimiter(startTag)) {
2019
+ return false;
2020
+ }
2021
+ const jsonStart = skipJsonWhitespace(segment, startIndex + startTag.length);
2022
+ return segment[jsonStart] === "{" && hasNestedStartBoundary(segment, startIndex);
2023
+ }
2024
+ function findToolCallBoundaryOutsideRjsonSyntax(text, scanFrom, startTag, endTag) {
2025
+ let quote = null;
2026
+ let esc = false;
2027
+ let inLineComment = false;
2028
+ let inBlockComment = false;
2029
+ let lineCommentSawEndTag = false;
2030
+ let blockCommentSawEndTag = false;
2031
+ let nestedStartIndex = null;
2032
+ for (let index = scanFrom; index < text.length; index += 1) {
2033
+ const ch = text[index];
2034
+ if (esc) {
2035
+ esc = false;
2036
+ continue;
2037
+ }
2038
+ if (quote !== null) {
2039
+ if (ch === "\\") {
2040
+ esc = true;
2041
+ continue;
2042
+ }
2043
+ if (ch === quote) {
2044
+ quote = null;
2045
+ }
2046
+ continue;
2047
+ }
2048
+ if (inLineComment) {
2049
+ if (ch === "\n" || ch === "\r") {
2050
+ inLineComment = false;
2051
+ lineCommentSawEndTag = false;
2052
+ continue;
2053
+ }
2054
+ if (text.startsWith(endTag, index)) {
2055
+ lineCommentSawEndTag = true;
2056
+ index += endTag.length - 1;
2057
+ continue;
2058
+ }
2059
+ if (lineCommentSawEndTag && text.startsWith(startTag, index) && text[skipJsonWhitespace(text, index + startTag.length)] === "{") {
2060
+ nestedStartIndex = index;
2061
+ inLineComment = false;
2062
+ lineCommentSawEndTag = false;
2063
+ index += startTag.length - 1;
2064
+ continue;
2065
+ }
2066
+ continue;
2067
+ }
2068
+ if (inBlockComment) {
2069
+ if (ch === "*" && text[index + 1] === "/") {
2070
+ inBlockComment = false;
2071
+ blockCommentSawEndTag = false;
2072
+ index += 1;
2073
+ continue;
2074
+ }
2075
+ if (text.startsWith(endTag, index)) {
2076
+ blockCommentSawEndTag = true;
2077
+ index += endTag.length - 1;
2078
+ continue;
2079
+ }
2080
+ if (blockCommentSawEndTag && text.startsWith(startTag, index) && text[skipJsonWhitespace(text, index + startTag.length)] === "{") {
2081
+ nestedStartIndex = index;
2082
+ inBlockComment = false;
2083
+ blockCommentSawEndTag = false;
2084
+ index += startTag.length - 1;
2085
+ continue;
2086
+ }
2087
+ continue;
2088
+ }
2089
+ if (startsRjsonComment(text, index, scanFrom)) {
2090
+ if (text[index + 1] === "/") {
2091
+ inLineComment = true;
2092
+ lineCommentSawEndTag = false;
2093
+ index += 1;
2094
+ continue;
2095
+ }
2096
+ if (text[index + 1] === "*") {
2097
+ inBlockComment = true;
2098
+ blockCommentSawEndTag = false;
2099
+ index += 1;
2100
+ continue;
2101
+ }
2102
+ }
2103
+ if (text.startsWith(endTag, index)) {
2104
+ return nestedStartIndex == null ? { kind: "end", endIdx: index } : { kind: "nested", endIdx: index, nestedStartIndex };
2105
+ }
2106
+ if (nestedStartIndex == null && text.startsWith(startTag, index) && isLikelyNestedToolCallStart(text, index, startTag)) {
2107
+ nestedStartIndex = index;
2108
+ index += startTag.length - 1;
2109
+ continue;
2110
+ }
2111
+ if (ch === '"' || ch === "'") {
2112
+ quote = ch;
2113
+ }
2114
+ }
2115
+ return null;
2116
+ }
2117
+ function findNextToolCallSpan(text, searchFrom, startTag, endTag) {
2118
+ const startIdx = text.indexOf(startTag, searchFrom);
2119
+ if (startIdx === -1) {
2120
+ return null;
2121
+ }
2122
+ const jsonStart = startIdx + startTag.length;
2123
+ const boundary = findToolCallBoundaryOutsideRjsonSyntax(
2124
+ text,
2125
+ jsonStart,
2126
+ startTag,
2127
+ endTag
2128
+ );
2129
+ if (boundary == null) {
2130
+ return { startIdx, found: false };
2131
+ }
2132
+ if (boundary.kind === "nested") {
2133
+ return { startIdx, found: false };
2134
+ }
2135
+ return { startIdx, found: true, jsonStart, endIdx: boundary.endIdx };
2136
+ }
1977
2137
  function canonicalizeToolInput(argumentsValue) {
1978
2138
  return JSON.stringify(argumentsValue != null ? argumentsValue : {});
1979
2139
  }
2140
+ var CHAR_CODE_BACKSLASH = 92;
2141
+ var CHAR_CODE_QUOTE = 34;
2142
+ var CHAR_CODE_LF = 10;
2143
+ var CHAR_CODE_CR = 13;
2144
+ var CHAR_CODE_TAB = 9;
2145
+ var CHAR_CODE_SLASH = 47;
2146
+ var CHAR_CODE_STAR = 42;
2147
+ var CHAR_CODE_CONTROL_UPPER = 31;
2148
+ var CHAR_CODE_SINGLE_QUOTE = 39;
2149
+ function hasControlCharInString(json) {
2150
+ let quote = null;
2151
+ let esc = false;
2152
+ for (let i = 0; i < json.length; i += 1) {
2153
+ const code = json.charCodeAt(i);
2154
+ if (esc) {
2155
+ esc = false;
2156
+ if (code <= CHAR_CODE_CONTROL_UPPER) {
2157
+ return true;
2158
+ }
2159
+ continue;
2160
+ }
2161
+ if (quote !== null && code === CHAR_CODE_BACKSLASH) {
2162
+ esc = true;
2163
+ continue;
2164
+ }
2165
+ if (quote !== null) {
2166
+ if (code === quote) {
2167
+ quote = null;
2168
+ continue;
2169
+ }
2170
+ if (code <= CHAR_CODE_CONTROL_UPPER) {
2171
+ return true;
2172
+ }
2173
+ continue;
2174
+ }
2175
+ if (code === CHAR_CODE_SLASH && json.charCodeAt(i + 1) === CHAR_CODE_SLASH) {
2176
+ i += 2;
2177
+ while (i < json.length && json.charCodeAt(i) !== CHAR_CODE_LF && json.charCodeAt(i) !== CHAR_CODE_CR) {
2178
+ i += 1;
2179
+ }
2180
+ continue;
2181
+ }
2182
+ if (code === CHAR_CODE_SLASH && json.charCodeAt(i + 1) === CHAR_CODE_STAR) {
2183
+ i += 2;
2184
+ while (i + 1 < json.length && !(json.charCodeAt(i) === CHAR_CODE_STAR && json.charCodeAt(i + 1) === CHAR_CODE_SLASH)) {
2185
+ i += 1;
2186
+ }
2187
+ i += 1;
2188
+ continue;
2189
+ }
2190
+ if (code === CHAR_CODE_QUOTE || code === CHAR_CODE_SINGLE_QUOTE) {
2191
+ quote = code;
2192
+ }
2193
+ }
2194
+ return false;
2195
+ }
2196
+ function normalizeJsonStringCtrl(json) {
2197
+ if (!hasControlCharInString(json)) {
2198
+ return json;
2199
+ }
2200
+ const parts = [];
2201
+ let chunkStart = 0;
2202
+ let quote = null;
2203
+ let esc = false;
2204
+ const flushUpTo = (end) => {
2205
+ if (chunkStart < end) {
2206
+ parts.push(json.slice(chunkStart, end));
2207
+ }
2208
+ };
2209
+ const escapeForCode = (code) => {
2210
+ switch (code) {
2211
+ case CHAR_CODE_LF:
2212
+ return "\\n";
2213
+ case CHAR_CODE_CR:
2214
+ return "\\r";
2215
+ case CHAR_CODE_TAB:
2216
+ return "\\t";
2217
+ default:
2218
+ return `\\u${code.toString(16).padStart(4, "0")}`;
2219
+ }
2220
+ };
2221
+ for (let i = 0; i < json.length; i += 1) {
2222
+ const code = json.charCodeAt(i);
2223
+ if (esc) {
2224
+ esc = false;
2225
+ if (code <= CHAR_CODE_CONTROL_UPPER) {
2226
+ flushUpTo(i - 1);
2227
+ parts.push(escapeForCode(code));
2228
+ chunkStart = i + 1;
2229
+ }
2230
+ continue;
2231
+ }
2232
+ if (quote !== null && code === CHAR_CODE_BACKSLASH) {
2233
+ esc = true;
2234
+ continue;
2235
+ }
2236
+ if (quote !== null) {
2237
+ if (code === quote) {
2238
+ quote = null;
2239
+ continue;
2240
+ }
2241
+ if (code <= CHAR_CODE_CONTROL_UPPER) {
2242
+ flushUpTo(i);
2243
+ parts.push(escapeForCode(code));
2244
+ chunkStart = i + 1;
2245
+ }
2246
+ continue;
2247
+ }
2248
+ if (code === CHAR_CODE_SLASH && json.charCodeAt(i + 1) === CHAR_CODE_SLASH) {
2249
+ i += 2;
2250
+ while (i < json.length && json.charCodeAt(i) !== CHAR_CODE_LF && json.charCodeAt(i) !== CHAR_CODE_CR) {
2251
+ i += 1;
2252
+ }
2253
+ continue;
2254
+ }
2255
+ if (code === CHAR_CODE_SLASH && json.charCodeAt(i + 1) === CHAR_CODE_STAR) {
2256
+ i += 2;
2257
+ while (i + 1 < json.length && !(json.charCodeAt(i) === CHAR_CODE_STAR && json.charCodeAt(i + 1) === CHAR_CODE_SLASH)) {
2258
+ i += 1;
2259
+ }
2260
+ i += 1;
2261
+ continue;
2262
+ }
2263
+ if (code === CHAR_CODE_QUOTE || code === CHAR_CODE_SINGLE_QUOTE) {
2264
+ quote = code;
2265
+ }
2266
+ }
2267
+ if (chunkStart < json.length) {
2268
+ parts.push(json.slice(chunkStart));
2269
+ }
2270
+ return parts.join("");
2271
+ }
1980
2272
  function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
1981
2273
  var _a;
1982
2274
  try {
1983
- const parsedToolCall = parse(toolCallJson);
2275
+ const parsedToolCall = parse(
2276
+ normalizeJsonStringCtrl(toolCallJson)
2277
+ );
1984
2278
  processedElements.push({
1985
2279
  type: "tool-call",
1986
2280
  toolCallId: generateToolCallId(),
@@ -1988,6 +2282,8 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
1988
2282
  input: canonicalizeToolInput(parsedToolCall.arguments)
1989
2283
  });
1990
2284
  } catch (error) {
2285
+ const salvagedToolName = extractStreamingToolCallProgress(toolCallJson).toolName;
2286
+ const salvagedToolCallId = generateToolCallId();
1991
2287
  logParseFailure({
1992
2288
  phase: "generated-text",
1993
2289
  reason: "Failed to parse tool call JSON segment",
@@ -1997,24 +2293,17 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
1997
2293
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
1998
2294
  options,
1999
2295
  "Could not process JSON tool call, keeping original text.",
2000
- { toolCall: fullMatch, error }
2296
+ {
2297
+ toolCall: fullMatch,
2298
+ error,
2299
+ toolName: salvagedToolName,
2300
+ toolCallId: salvagedToolCallId,
2301
+ dropReason: "malformed-tool-call-body"
2302
+ }
2001
2303
  );
2002
2304
  processedElements.push({ type: "text", text: fullMatch });
2003
2305
  }
2004
2306
  }
2005
- function processMatchedToolCall(context) {
2006
- const { match, text, currentIndex, processedElements, options } = context;
2007
- const startIndex = match.index;
2008
- const toolCallJson = match[1];
2009
- if (startIndex > currentIndex) {
2010
- const textSegment = text.slice(currentIndex, startIndex);
2011
- addTextSegment(textSegment, processedElements);
2012
- }
2013
- if (toolCallJson) {
2014
- processToolCallJson(toolCallJson, match[0], processedElements, options);
2015
- }
2016
- return startIndex + match[0].length;
2017
- }
2018
2307
  var WHITESPACE_JSON_REGEX = /\s/;
2019
2308
  function skipJsonWhitespace(text, fromIndex) {
2020
2309
  let index = fromIndex;
@@ -2096,10 +2385,10 @@ function findTopLevelPropertyValueStart(text, property) {
2096
2385
  function extractTopLevelStringProperty(text, property) {
2097
2386
  const valueStart = findTopLevelPropertyValueStart(text, property);
2098
2387
  if (valueStart == null || valueStart >= text.length) {
2099
- return void 0;
2388
+ return;
2100
2389
  }
2101
2390
  if (text.charAt(valueStart) !== '"') {
2102
- return void 0;
2391
+ return;
2103
2392
  }
2104
2393
  let valueEnd = valueStart + 1;
2105
2394
  let escaped = false;
@@ -2114,7 +2403,7 @@ function extractTopLevelStringProperty(text, property) {
2114
2403
  }
2115
2404
  valueEnd += 1;
2116
2405
  }
2117
- return void 0;
2406
+ return;
2118
2407
  }
2119
2408
  function extractJsonValueSlice(text, valueStart) {
2120
2409
  if (valueStart >= text.length) {
@@ -2278,10 +2567,12 @@ function emitToolCallFromParsed(state, controller, parsedToolCall, tools) {
2278
2567
  }
2279
2568
  function canonicalizeArgumentsProgressInput(progress, toolName, tools) {
2280
2569
  if (progress.argumentsText === void 0 || !progress.argumentsComplete) {
2281
- return void 0;
2570
+ return;
2282
2571
  }
2283
2572
  try {
2284
- const parsedArguments = parse(progress.argumentsText);
2573
+ const parsedArguments = parse(
2574
+ normalizeJsonStringCtrl(progress.argumentsText)
2575
+ );
2285
2576
  return stringifyToolInputWithSchema({
2286
2577
  toolName,
2287
2578
  args: parsedArguments,
@@ -2289,7 +2580,7 @@ function canonicalizeArgumentsProgressInput(progress, toolName, tools) {
2289
2580
  fallback: canonicalizeToolInput
2290
2581
  });
2291
2582
  } catch (e) {
2292
- return void 0;
2583
+ return;
2293
2584
  }
2294
2585
  }
2295
2586
  function emitToolInputProgress(state, controller, tools) {
@@ -2341,14 +2632,16 @@ function closeTextBlock(state, controller) {
2341
2632
  }
2342
2633
  }
2343
2634
  function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer, tools, options) {
2344
- var _a;
2635
+ var _a, _b, _c, _d;
2345
2636
  if (!state.currentToolCallJson && trailingBuffer.length === 0) {
2346
2637
  state.isInsideToolCall = false;
2347
2638
  return;
2348
2639
  }
2349
2640
  if (state.currentToolCallJson) {
2350
2641
  try {
2351
- const parsedToolCall = parse(state.currentToolCallJson);
2642
+ const parsedToolCall = parse(
2643
+ normalizeJsonStringCtrl(state.currentToolCallJson)
2644
+ );
2352
2645
  emitToolCallFromParsed(state, controller, parsedToolCall, tools);
2353
2646
  state.currentToolCallJson = "";
2354
2647
  state.isInsideToolCall = false;
@@ -2380,11 +2673,19 @@ function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer
2380
2673
  id: errorId
2381
2674
  });
2382
2675
  }
2676
+ const streamingToolCallId = (_b = (_a = state.activeToolInput) == null ? void 0 : _a.id) != null ? _b : generateToolCallId();
2677
+ const streamingToolName = (_c = state.activeToolInput) == null ? void 0 : _c.toolName;
2383
2678
  closeToolInput(state, controller);
2384
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
2679
+ const toolName = streamingToolName != null ? streamingToolName : state.currentToolCallJson ? extractStreamingToolCallProgress(state.currentToolCallJson).toolName : void 0;
2680
+ (_d = options == null ? void 0 : options.onError) == null ? void 0 : _d.call(
2385
2681
  options,
2386
2682
  shouldEmitRawFallback ? "Could not complete streaming JSON tool call at finish; emitting original text." : "Could not complete streaming JSON tool call at finish.",
2387
- { toolCall: errorContent }
2683
+ {
2684
+ toolCall: errorContent,
2685
+ toolCallId: streamingToolCallId,
2686
+ toolName,
2687
+ dropReason: "unfinished-tool-call"
2688
+ }
2388
2689
  );
2389
2690
  state.currentToolCallJson = "";
2390
2691
  state.isInsideToolCall = false;
@@ -2429,14 +2730,18 @@ function publishText(text, state, controller, tools) {
2429
2730
  }
2430
2731
  }
2431
2732
  function emitToolCall(context) {
2432
- var _a;
2733
+ var _a, _b, _c, _d, _e;
2433
2734
  const { state, controller, toolCallStart, toolCallEnd, options, tools } = context;
2434
2735
  try {
2435
- const parsedToolCall = parse(state.currentToolCallJson);
2736
+ const parsedToolCall = parse(
2737
+ normalizeJsonStringCtrl(state.currentToolCallJson)
2738
+ );
2436
2739
  emitToolCallFromParsed(state, controller, parsedToolCall, tools);
2437
2740
  } catch (error) {
2438
2741
  const errorContent = `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`;
2439
2742
  const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
2743
+ const streamingToolCallId = (_b = (_a = state.activeToolInput) == null ? void 0 : _a.id) != null ? _b : generateToolCallId();
2744
+ const streamingToolName = (_d = (_c = state.activeToolInput) == null ? void 0 : _c.toolName) != null ? _d : extractStreamingToolCallProgress(state.currentToolCallJson).toolName;
2440
2745
  logParseFailure({
2441
2746
  phase: "stream",
2442
2747
  reason: "Failed to parse streaming tool call JSON segment",
@@ -2460,11 +2765,15 @@ function emitToolCall(context) {
2460
2765
  });
2461
2766
  }
2462
2767
  closeToolInput(state, controller);
2463
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
2768
+ (_e = options == null ? void 0 : options.onError) == null ? void 0 : _e.call(
2464
2769
  options,
2465
2770
  shouldEmitRawFallback ? "Could not process streaming JSON tool call; emitting original text." : "Could not process streaming JSON tool call.",
2466
2771
  {
2467
- toolCall: errorContent
2772
+ toolCall: errorContent,
2773
+ error,
2774
+ toolCallId: streamingToolCallId,
2775
+ toolName: streamingToolName,
2776
+ dropReason: "malformed-tool-call-body"
2468
2777
  }
2469
2778
  );
2470
2779
  }
@@ -2481,24 +2790,118 @@ function processTagMatch(context) {
2481
2790
  state.activeToolInput = null;
2482
2791
  }
2483
2792
  }
2484
- function processBufferTags(context) {
2793
+ function recoverNestedStreamingToolCall(options) {
2794
+ var _a, _b, _c, _d;
2795
+ const { context, jsonSoFar, nestedStartIndex, startIndex, tag } = options;
2796
+ const {
2797
+ state,
2798
+ controller,
2799
+ toolCallStart,
2800
+ toolCallEnd,
2801
+ options: parserOptions
2802
+ } = context;
2803
+ const droppedToolCall = `${toolCallStart}${jsonSoFar.slice(
2804
+ 0,
2805
+ nestedStartIndex
2806
+ )}`;
2807
+ const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(parserOptions);
2808
+ const streamingToolCallId = (_a = state.activeToolInput) == null ? void 0 : _a.id;
2809
+ const streamingToolName = (_c = (_b = state.activeToolInput) == null ? void 0 : _b.toolName) != null ? _c : extractStreamingToolCallProgress(jsonSoFar.slice(0, nestedStartIndex)).toolName;
2810
+ logParseFailure({
2811
+ phase: "stream",
2812
+ reason: "Abandoning malformed streaming tool call before nested start tag",
2813
+ snippet: droppedToolCall
2814
+ });
2815
+ if (shouldEmitRawFallback) {
2816
+ const errorId = generateId();
2817
+ controller.enqueue({
2818
+ type: "text-start",
2819
+ id: errorId
2820
+ });
2821
+ controller.enqueue({
2822
+ type: "text-delta",
2823
+ id: errorId,
2824
+ delta: droppedToolCall
2825
+ });
2826
+ controller.enqueue({
2827
+ type: "text-end",
2828
+ id: errorId
2829
+ });
2830
+ }
2831
+ closeToolInput(state, controller);
2832
+ (_d = parserOptions == null ? void 0 : parserOptions.onError) == null ? void 0 : _d.call(
2833
+ parserOptions,
2834
+ 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.",
2835
+ {
2836
+ toolCall: droppedToolCall,
2837
+ toolCallId: streamingToolCallId,
2838
+ toolName: streamingToolName,
2839
+ dropReason: "malformed-nested-tool-call"
2840
+ }
2841
+ );
2842
+ state.currentToolCallJson = "";
2843
+ state.isInsideToolCall = false;
2844
+ state.buffer = jsonSoFar.slice(nestedStartIndex) + toolCallEnd + state.buffer.slice(startIndex + tag.length);
2845
+ return getPotentialStartIndex(state.buffer, toolCallStart);
2846
+ }
2847
+ function processInsideToolCallBoundary(context) {
2485
2848
  const { state, controller, toolCallStart, toolCallEnd, tools } = context;
2486
- let startIndex = getPotentialStartIndex(
2487
- state.buffer,
2488
- state.isInsideToolCall ? toolCallEnd : toolCallStart
2849
+ const currentLength = state.currentToolCallJson.length;
2850
+ const combined = state.currentToolCallJson + state.buffer;
2851
+ const boundary = findToolCallBoundaryOutsideRjsonSyntax(
2852
+ combined,
2853
+ 0,
2854
+ toolCallStart,
2855
+ toolCallEnd
2856
+ );
2857
+ if (boundary == null) {
2858
+ return false;
2859
+ }
2860
+ const relativeEndIndex = boundary.endIdx - currentLength;
2861
+ if (relativeEndIndex < 0) {
2862
+ return false;
2863
+ }
2864
+ if (boundary.kind === "nested") {
2865
+ recoverNestedStreamingToolCall({
2866
+ context,
2867
+ jsonSoFar: combined.slice(0, boundary.endIdx),
2868
+ nestedStartIndex: boundary.nestedStartIndex,
2869
+ startIndex: relativeEndIndex,
2870
+ tag: toolCallEnd
2871
+ });
2872
+ return true;
2873
+ }
2874
+ publishText(
2875
+ state.buffer.slice(0, relativeEndIndex),
2876
+ state,
2877
+ controller,
2878
+ tools
2489
2879
  );
2880
+ state.buffer = state.buffer.slice(relativeEndIndex + toolCallEnd.length);
2881
+ processTagMatch(context);
2882
+ return true;
2883
+ }
2884
+ function processBufferTags(context) {
2885
+ const { state, controller, toolCallStart, tools } = context;
2886
+ while (state.isInsideToolCall) {
2887
+ if (!processInsideToolCallBoundary(context)) {
2888
+ return;
2889
+ }
2890
+ }
2891
+ let startIndex = getPotentialStartIndex(state.buffer, toolCallStart);
2490
2892
  while (startIndex != null) {
2491
- const tag = state.isInsideToolCall ? toolCallEnd : toolCallStart;
2492
- if (startIndex + tag.length > state.buffer.length) {
2893
+ if (startIndex + toolCallStart.length > state.buffer.length) {
2493
2894
  break;
2494
2895
  }
2495
2896
  publishText(state.buffer.slice(0, startIndex), state, controller, tools);
2496
- state.buffer = state.buffer.slice(startIndex + tag.length);
2897
+ state.buffer = state.buffer.slice(startIndex + toolCallStart.length);
2497
2898
  processTagMatch(context);
2498
- startIndex = getPotentialStartIndex(
2499
- state.buffer,
2500
- state.isInsideToolCall ? toolCallEnd : toolCallStart
2501
- );
2899
+ while (state.isInsideToolCall) {
2900
+ if (!processInsideToolCallBoundary(context)) {
2901
+ return;
2902
+ }
2903
+ }
2904
+ startIndex = getPotentialStartIndex(state.buffer, toolCallStart);
2502
2905
  }
2503
2906
  }
2504
2907
  function handlePartialTag(state, controller, toolCallStart, toolCallEnd, tools) {
@@ -2536,6 +2939,7 @@ var hermesProtocol = ({
2536
2939
  toolCallStart = "<tool_call>",
2537
2940
  toolCallEnd = "</tool_call>"
2538
2941
  } = {}) => ({
2942
+ ...validateNonEmptyDelimiters(toolCallStart, toolCallEnd),
2539
2943
  formatTools({
2540
2944
  tools,
2541
2945
  toolSystemPromptTemplate
@@ -2560,24 +2964,42 @@ var hermesProtocol = ({
2560
2964
  text,
2561
2965
  options
2562
2966
  }) {
2563
- const startEsc = escapeRegExp(toolCallStart);
2564
- const endEsc = escapeRegExp(toolCallEnd);
2565
- const toolCallRegex = new RegExp(
2566
- `${startEsc}([\0-\uFFFF]*?)${endEsc}`,
2567
- "gs"
2568
- );
2569
2967
  const processedElements = [];
2570
2968
  let currentIndex = 0;
2571
- let match = toolCallRegex.exec(text);
2572
- while (match !== null) {
2573
- currentIndex = processMatchedToolCall({
2574
- match,
2969
+ let searchFrom = 0;
2970
+ while (searchFrom < text.length) {
2971
+ const span = findNextToolCallSpan(
2575
2972
  text,
2576
- currentIndex,
2577
- processedElements,
2578
- options
2579
- });
2580
- match = toolCallRegex.exec(text);
2973
+ searchFrom,
2974
+ toolCallStart,
2975
+ toolCallEnd
2976
+ );
2977
+ if (span === null) {
2978
+ break;
2979
+ }
2980
+ if (!span.found) {
2981
+ const skipTo = span.startIdx + toolCallStart.length;
2982
+ if (skipTo > currentIndex) {
2983
+ addTextSegment(text.slice(currentIndex, skipTo), processedElements);
2984
+ currentIndex = skipTo;
2985
+ }
2986
+ searchFrom = skipTo;
2987
+ continue;
2988
+ }
2989
+ const toolCallJson = text.slice(span.jsonStart, span.endIdx);
2990
+ const fullMatch = text.slice(
2991
+ span.startIdx,
2992
+ span.endIdx + toolCallEnd.length
2993
+ );
2994
+ if (span.startIdx > currentIndex) {
2995
+ addTextSegment(
2996
+ text.slice(currentIndex, span.startIdx),
2997
+ processedElements
2998
+ );
2999
+ }
3000
+ processToolCallJson(toolCallJson, fullMatch, processedElements, options);
3001
+ currentIndex = span.endIdx + toolCallEnd.length;
3002
+ searchFrom = currentIndex;
2581
3003
  }
2582
3004
  if (currentIndex < text.length) {
2583
3005
  const remainingText = text.slice(currentIndex);
@@ -2630,14 +3052,26 @@ var hermesProtocol = ({
2630
3052
  });
2631
3053
  },
2632
3054
  extractToolCallSegments({ text }) {
2633
- const startEsc = escapeRegExp(toolCallStart);
2634
- const endEsc = escapeRegExp(toolCallEnd);
2635
- const regex = new RegExp(`${startEsc}([\0-\uFFFF]*?)${endEsc}`, "gs");
2636
3055
  const segments = [];
2637
- let m = regex.exec(text);
2638
- while (m != null) {
2639
- segments.push(m[0]);
2640
- m = regex.exec(text);
3056
+ let searchFrom = 0;
3057
+ while (searchFrom < text.length) {
3058
+ const span = findNextToolCallSpan(
3059
+ text,
3060
+ searchFrom,
3061
+ toolCallStart,
3062
+ toolCallEnd
3063
+ );
3064
+ if (span === null) {
3065
+ break;
3066
+ }
3067
+ if (!span.found) {
3068
+ searchFrom = span.startIdx + toolCallStart.length;
3069
+ continue;
3070
+ }
3071
+ segments.push(
3072
+ text.slice(span.startIdx, span.endIdx + toolCallEnd.length)
3073
+ );
3074
+ searchFrom = span.endIdx + toolCallEnd.length;
2641
3075
  }
2642
3076
  return segments;
2643
3077
  }
@@ -4485,6 +4919,11 @@ function createIntermediateCall(toolName, rawSegment, schema) {
4485
4919
  };
4486
4920
  }
4487
4921
 
4922
+ // src/core/utils/regex.ts
4923
+ function escapeRegExp(literal) {
4924
+ return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4925
+ }
4926
+
4488
4927
  // src/rxml/heuristics/xml-defaults.ts
4489
4928
  var MALFORMED_CLOSE_RE_G = /<\/\s+([A-Za-z0-9_:-]+)\s*>/g;
4490
4929
  var MALFORMED_CLOSE_RE = /<\/\s+([A-Za-z0-9_:-]+)\s*>/;
@@ -4696,7 +5135,7 @@ function handleOpeningTagSegment(src, lt, out, stack) {
4696
5135
  function extractSchemaProperties(schema) {
4697
5136
  const unwrapped = unwrapJsonSchema(schema);
4698
5137
  if (!unwrapped || typeof unwrapped !== "object") {
4699
- return void 0;
5138
+ return;
4700
5139
  }
4701
5140
  return unwrapped.properties;
4702
5141
  }
@@ -5128,7 +5567,13 @@ function processToolCall(params) {
5128
5567
  (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
5129
5568
  options,
5130
5569
  `Could not process XML tool call: ${toolCall.toolName}`,
5131
- { toolCall: originalCallText, error }
5570
+ {
5571
+ toolCall: originalCallText,
5572
+ error,
5573
+ toolName: toolCall.toolName,
5574
+ toolCallId: generateToolCallId(),
5575
+ dropReason: "malformed-tool-call-body"
5576
+ }
5132
5577
  );
5133
5578
  processedElements.push({ type: "text", text: originalCallText });
5134
5579
  }
@@ -5570,7 +6015,10 @@ function handleStreamingToolCallEnd(params) {
5570
6015
  });
5571
6016
  (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
5572
6017
  toolCall: original,
5573
- error
6018
+ error,
6019
+ toolName: currentToolCall.name,
6020
+ toolCallId: currentToolCall.toolCallId,
6021
+ dropReason: "malformed-tool-call-body"
5574
6022
  });
5575
6023
  }
5576
6024
  }
@@ -6132,7 +6580,13 @@ var morphXmlProtocol = (protocolOptions) => {
6132
6580
  (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
6133
6581
  options,
6134
6582
  "Could not complete streaming XML tool call at finish.",
6135
- { toolCall: unfinishedContent, error }
6583
+ {
6584
+ toolCall: unfinishedContent,
6585
+ toolCallId: currentToolCall.toolCallId,
6586
+ toolName: currentToolCall.name,
6587
+ dropReason: "unfinished-tool-call",
6588
+ error
6589
+ }
6136
6590
  );
6137
6591
  }
6138
6592
  buffer = "";
@@ -6358,7 +6812,8 @@ var QWEN3CODER_TOOL_PARSER_CALL_TAG_NAMES = /* @__PURE__ */ new Set([
6358
6812
  "invoke",
6359
6813
  "tool_call"
6360
6814
  ]);
6361
- var CALL_SHORTHAND_VALUE_RE = /^<\s*(call|function|tool|invoke)\b\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>/]+))/i;
6815
+ var CALL_SHORTHAND_VALUE_RE = /^<\s*(call|function|tool|invoke)\b\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>/<]+))/i;
6816
+ var NESTED_CALL_SHORTHAND_VALUE_RE = /<\s*(?:call|function|tool|invoke)\b\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>/<]+))/i;
6362
6817
  var QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_START_RE = /<\s*(?!\/)\s*(call|function|tool|invoke)\b/i;
6363
6818
  var QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_TAG_RE = /<\s*(?!\/)\s*(call|function|tool|invoke)\b[^>]*>/i;
6364
6819
  var QWEN3CODER_TOOL_PARSER_STREAM_TOOL_CALL_CLOSE_TAG_RE = /<\s*\/\s*tool_call\s*>/i;
@@ -6757,6 +7212,12 @@ function getShorthandValue(openTag) {
6757
7212
  }
6758
7213
  return unescapeXml(value);
6759
7214
  }
7215
+ function extractShorthandToolNameFromRaw(rawText) {
7216
+ var _a, _b;
7217
+ const match = NESTED_CALL_SHORTHAND_VALUE_RE.exec(rawText);
7218
+ 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];
7219
+ return value ? unescapeXml(value) : null;
7220
+ }
6760
7221
  function extractFirstTagText(xml, tagName) {
6761
7222
  var _a;
6762
7223
  const lower = xml.toLowerCase();
@@ -7039,7 +7500,7 @@ function parseQwen3CoderToolParserClosedMatches(inner, outerNameAttr) {
7039
7500
  var _a, _b;
7040
7501
  const callBlockMatches = Array.from(inner.matchAll(CALL_BLOCK_RE));
7041
7502
  if (callBlockMatches.length === 0) {
7042
- return void 0;
7503
+ return;
7043
7504
  }
7044
7505
  const closedBlocks = [];
7045
7506
  let lastClosedEnd = 0;
@@ -7078,6 +7539,20 @@ function parseQwen3CoderToolParserClosedMatches(inner, outerNameAttr) {
7078
7539
  }
7079
7540
  return closedCalls.concat(trailingCalls);
7080
7541
  }
7542
+ 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;
7543
+ function extractQwen3CoderToolNameFromMarkup(markup) {
7544
+ var _a, _b, _c, _d, _e;
7545
+ const match = markup.match(QWEN3CODER_TOOL_NAME_SALVAGE_REGEX);
7546
+ if (!match) {
7547
+ return;
7548
+ }
7549
+ 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];
7550
+ if (!name) {
7551
+ return;
7552
+ }
7553
+ const trimmed = name.trim();
7554
+ return trimmed.length > 0 ? trimmed : void 0;
7555
+ }
7081
7556
  function parseQwen3CoderToolParserToolCallSegment(segment) {
7082
7557
  var _a;
7083
7558
  const extracted = extractToolCallInnerXml(segment);
@@ -7202,7 +7677,12 @@ var qwen3CoderProtocol = () => ({
7202
7677
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
7203
7678
  options,
7204
7679
  "Could not process Qwen3CoderToolParser XML tool call; keeping original text.",
7205
- { toolCall: fallbackText }
7680
+ {
7681
+ toolCall: fallbackText,
7682
+ toolName: extractQwen3CoderToolNameFromMarkup(segment),
7683
+ toolCallId: generateToolCallId(),
7684
+ dropReason: "malformed-tool-call-body"
7685
+ }
7206
7686
  );
7207
7687
  processedElements.push({ type: "text", text: fallbackText });
7208
7688
  return false;
@@ -7215,7 +7695,12 @@ var qwen3CoderProtocol = () => ({
7215
7695
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
7216
7696
  options,
7217
7697
  "Could not process Qwen3CoderToolParser <function> call; keeping original text.",
7218
- { toolCall: raw }
7698
+ {
7699
+ toolCall: raw,
7700
+ toolName: extractQwen3CoderToolNameFromMarkup(raw),
7701
+ toolCallId: generateToolCallId(),
7702
+ dropReason: "malformed-tool-call-body"
7703
+ }
7219
7704
  );
7220
7705
  processedElements.push({ type: "text", text: raw });
7221
7706
  };
@@ -7361,9 +7846,7 @@ var qwen3CoderProtocol = () => ({
7361
7846
  tryEmitToolCallSegment(synthetic, trailing);
7362
7847
  return true;
7363
7848
  };
7364
- const tryParseCallBlocksWithoutWrapper = () => {
7365
- return tryParseCallBlocksWithoutWrapperText(text);
7366
- };
7849
+ const tryParseCallBlocksWithoutWrapper = () => tryParseCallBlocksWithoutWrapperText(text);
7367
7850
  const tryParseSingleFunctionCall = () => {
7368
7851
  const lowerText = text.toLowerCase();
7369
7852
  const startIndex = lowerText.indexOf("<function");
@@ -7465,7 +7948,7 @@ var qwen3CoderProtocol = () => ({
7465
7948
  });
7466
7949
  };
7467
7950
  const finalizeCall = (controller, callState, fallbackToolName, rawToolCallText = null) => {
7468
- var _a, _b;
7951
+ var _a, _b, _c, _d;
7469
7952
  const resolvedToolName = (_a = callState.toolName) != null ? _a : fallbackToolName;
7470
7953
  if (!resolvedToolName || resolvedToolName.trim().length === 0) {
7471
7954
  const shouldEmitRaw = shouldEmitRawToolCallTextOnError(options);
@@ -7479,12 +7962,14 @@ var qwen3CoderProtocol = () => ({
7479
7962
  flushText(controller, rawText);
7480
7963
  }
7481
7964
  });
7482
- (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
7965
+ (_d = options == null ? void 0 : options.onError) == null ? void 0 : _d.call(
7483
7966
  options,
7484
7967
  shouldEmitRaw && rawToolCallText ? "Could not resolve Qwen3CoderToolParser tool name for tool call; emitting original text." : "Could not resolve Qwen3CoderToolParser tool name for tool call",
7485
7968
  {
7486
7969
  toolCallId: callState.toolCallId,
7487
- toolCall: rawToolCallText
7970
+ toolCall: rawToolCallText,
7971
+ toolName: (_c = (_b = callState.toolName) != null ? _b : fallbackToolName) != null ? _c : void 0,
7972
+ dropReason: "unresolved-tool-name"
7488
7973
  }
7489
7974
  );
7490
7975
  return false;
@@ -7940,25 +8425,36 @@ var qwen3CoderProtocol = () => ({
7940
8425
  }
7941
8426
  }
7942
8427
  };
7943
- const reportUnfinishedToolCallAtFinish = (controller, rawToolCall) => {
7944
- var _a;
8428
+ const reportUnfinishedToolCallAtFinish = (controller, rawToolCall, metadata = {}) => {
8429
+ var _a, _b;
7945
8430
  const shouldEmitRaw = shouldEmitRawToolCallTextOnError(options);
7946
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
8431
+ const toolName = (_a = metadata.toolName) != null ? _a : extractShorthandToolNameFromRaw(rawToolCall);
8432
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
7947
8433
  options,
7948
8434
  shouldEmitRaw ? "Could not complete streaming Qwen3CoderToolParser XML tool call at finish; emitting original text." : "Could not complete streaming Qwen3CoderToolParser XML tool call at finish.",
7949
- { toolCall: rawToolCall }
8435
+ {
8436
+ toolCall: rawToolCall,
8437
+ ...metadata.toolCallId ? { toolCallId: metadata.toolCallId } : {},
8438
+ ...toolName ? { toolName } : {},
8439
+ dropReason: "unfinished-tool-call"
8440
+ }
7950
8441
  );
7951
8442
  if (shouldEmitRaw) {
7952
8443
  flushText(controller, rawToolCall);
7953
8444
  }
7954
8445
  };
7955
- const reportUnfinishedImplicitCallAtFinish = (controller, rawCallText) => {
8446
+ const reportUnfinishedImplicitCallAtFinish = (controller, rawCallText, callState) => {
7956
8447
  var _a;
7957
8448
  const shouldEmitRaw = shouldEmitRawToolCallTextOnError(options);
7958
8449
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
7959
8450
  options,
7960
8451
  shouldEmitRaw ? "Could not complete streaming Qwen3CoderToolParser call block at finish; emitting original text." : "Could not complete streaming Qwen3CoderToolParser call block at finish.",
7961
- { toolCall: rawCallText }
8452
+ {
8453
+ toolCall: rawCallText,
8454
+ toolCallId: callState.toolCallId,
8455
+ ...callState.toolName ? { toolName: callState.toolName } : {},
8456
+ dropReason: "unfinished-tool-call"
8457
+ }
7962
8458
  );
7963
8459
  if (shouldEmitRaw) {
7964
8460
  flushText(controller, rawCallText);
@@ -8009,7 +8505,10 @@ var qwen3CoderProtocol = () => ({
8009
8505
  flushText(controller, result.trailingText);
8010
8506
  }
8011
8507
  if (!result.ok && toolCall.emittedToolCallCount === 0) {
8012
- reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
8508
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw, {
8509
+ toolCallId: toolCall.activeCall.toolCallId,
8510
+ ...toolCall.activeCall.toolName ? { toolName: toolCall.activeCall.toolName } : {}
8511
+ });
8013
8512
  }
8014
8513
  } else if (toolCall.mode === "multi") {
8015
8514
  if (toolCall.activeCall) {
@@ -8026,14 +8525,21 @@ var qwen3CoderProtocol = () => ({
8026
8525
  flushText(controller, result.trailingText);
8027
8526
  }
8028
8527
  if (!result.ok && toolCall.emittedToolCallCount === 0) {
8029
- reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
8528
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw, {
8529
+ toolCallId: toolCall.activeCall.toolCallId,
8530
+ ...toolCall.activeCall.toolName ? { toolName: toolCall.activeCall.toolName } : {}
8531
+ });
8030
8532
  }
8031
8533
  toolCall.activeCall = null;
8032
8534
  } else if (toolCall.emittedToolCallCount === 0) {
8033
- reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
8535
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw, {
8536
+ toolName: toolCall.outerNameAttr
8537
+ });
8034
8538
  }
8035
8539
  } else {
8036
- reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
8540
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw, {
8541
+ toolName: toolCall.outerNameAttr
8542
+ });
8037
8543
  }
8038
8544
  toolCall = null;
8039
8545
  }
@@ -8051,7 +8557,8 @@ var qwen3CoderProtocol = () => ({
8051
8557
  if (!result.ok && openTag) {
8052
8558
  reportUnfinishedImplicitCallAtFinish(
8053
8559
  controller,
8054
- callState.raw || openTag + callState.buffer
8560
+ callState.raw || openTag + callState.buffer,
8561
+ callState
8055
8562
  );
8056
8563
  }
8057
8564
  } else {
@@ -8430,26 +8937,28 @@ function findToolCalls2(text, toolNames) {
8430
8937
  );
8431
8938
  return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
8432
8939
  }
8433
- function parseYamlContent(yamlContent, options) {
8434
- var _a, _b;
8940
+ function yamlFailureCause(failure) {
8941
+ if (failure.kind === "yaml-parse-error") {
8942
+ return { kind: "yaml-parse-error", errors: failure.errors };
8943
+ }
8944
+ return { kind: "yaml-non-mapping" };
8945
+ }
8946
+ function parseYamlContent(yamlContent) {
8435
8947
  const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
8436
8948
  if (nonEmptyLines.length === 0) {
8437
- return {};
8949
+ return { ok: true, value: {} };
8438
8950
  }
8439
8951
  const parsed = parseYamlDocumentAsMapping(normalized);
8440
8952
  if (parsed.errors.length > 0) {
8441
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "YAML parse error", {
8442
- errors: parsed.errors
8443
- });
8444
- return null;
8953
+ return {
8954
+ ok: false,
8955
+ failure: { kind: "yaml-parse-error", errors: parsed.errors }
8956
+ };
8445
8957
  }
8446
8958
  if (parsed.value === null) {
8447
- (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
8448
- got: "non-mapping"
8449
- });
8450
- return null;
8959
+ return { ok: false, failure: { kind: "yaml-non-mapping" } };
8451
8960
  }
8452
- return parsed.value;
8961
+ return { ok: true, value: parsed.value };
8453
8962
  }
8454
8963
  function parseYamlContentForStreamProgress(yamlContent) {
8455
8964
  const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
@@ -8481,20 +8990,25 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
8481
8990
  return currentIndex;
8482
8991
  }
8483
8992
  addTextSegment(text.slice(currentIndex, tc.startIndex), processedElements);
8484
- const parsedArgs = parseYamlContent(tc.content, options);
8485
- if (parsedArgs === null) {
8486
- const originalText = text.slice(tc.startIndex, tc.endIndex);
8487
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse YAML tool call", {
8488
- toolCall: originalText
8489
- });
8490
- processedElements.push({ type: "text", text: originalText });
8491
- } else {
8993
+ const result = parseYamlContent(tc.content);
8994
+ if (result.ok) {
8492
8995
  processedElements.push({
8493
8996
  type: "tool-call",
8494
8997
  toolCallId: generateToolCallId(),
8495
8998
  toolName: tc.toolName,
8496
- input: JSON.stringify(parsedArgs)
8999
+ input: JSON.stringify(result.value)
8497
9000
  });
9001
+ } else {
9002
+ const originalText = text.slice(tc.startIndex, tc.endIndex);
9003
+ const cause = yamlFailureCause(result.failure);
9004
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse YAML tool call", {
9005
+ toolCall: originalText,
9006
+ toolName: tc.toolName,
9007
+ toolCallId: generateToolCallId(),
9008
+ dropReason: "malformed-tool-call-body",
9009
+ cause
9010
+ });
9011
+ processedElements.push({ type: "text", text: originalText });
8498
9012
  }
8499
9013
  return tc.endIndex;
8500
9014
  }
@@ -8521,327 +9035,335 @@ function stripTrailingPartialCloseTag(content, toolName) {
8521
9035
  )}${preservedLeadingWhitespace}`;
8522
9036
  return contentWithoutPartial.trimEnd();
8523
9037
  }
8524
- var yamlXmlProtocol = (_protocolOptions) => {
8525
- return {
8526
- formatTools({ tools, toolSystemPromptTemplate }) {
8527
- return formatToolsWithPromptTemplate({ tools, toolSystemPromptTemplate });
8528
- },
8529
- formatToolCall(toolCall) {
8530
- let args = {};
8531
- if (toolCall.input != null) {
8532
- try {
8533
- args = JSON.parse(toolCall.input);
8534
- } catch (e) {
8535
- args = { value: toolCall.input };
8536
- }
9038
+ var yamlXmlProtocol = (_protocolOptions) => ({
9039
+ formatTools({ tools, toolSystemPromptTemplate }) {
9040
+ return formatToolsWithPromptTemplate({ tools, toolSystemPromptTemplate });
9041
+ },
9042
+ formatToolCall(toolCall) {
9043
+ let args = {};
9044
+ if (toolCall.input != null) {
9045
+ try {
9046
+ args = JSON.parse(toolCall.input);
9047
+ } catch (e) {
9048
+ args = { value: toolCall.input };
8537
9049
  }
8538
- const yamlContent = import_yaml.default.stringify(args);
8539
- return `<${toolCall.toolName}>
9050
+ }
9051
+ const yamlContent = import_yaml.default.stringify(args);
9052
+ return `<${toolCall.toolName}>
8540
9053
  ${yamlContent}</${toolCall.toolName}>`;
8541
- },
8542
- parseGeneratedText({ text, tools, options }) {
8543
- const toolNames = extractToolNames(tools);
8544
- if (toolNames.length === 0) {
8545
- return [{ type: "text", text }];
8546
- }
8547
- const processedElements = [];
8548
- let currentIndex = 0;
8549
- let parseText = text;
8550
- let toolCalls = findToolCalls2(parseText, toolNames);
8551
- if (toolCalls.length === 0) {
8552
- const repaired = tryRepairXmlSelfClosingRootWithBody(
8553
- parseText,
8554
- toolNames
8555
- );
8556
- if (repaired) {
8557
- const repairedCalls = findToolCalls2(repaired, toolNames);
8558
- if (repairedCalls.length > 0) {
8559
- parseText = repaired;
8560
- toolCalls = repairedCalls;
8561
- }
9054
+ },
9055
+ parseGeneratedText({ text, tools, options }) {
9056
+ const toolNames = extractToolNames(tools);
9057
+ if (toolNames.length === 0) {
9058
+ return [{ type: "text", text }];
9059
+ }
9060
+ const processedElements = [];
9061
+ let currentIndex = 0;
9062
+ let parseText = text;
9063
+ let toolCalls = findToolCalls2(parseText, toolNames);
9064
+ if (toolCalls.length === 0) {
9065
+ const repaired = tryRepairXmlSelfClosingRootWithBody(
9066
+ parseText,
9067
+ toolNames
9068
+ );
9069
+ if (repaired) {
9070
+ const repairedCalls = findToolCalls2(repaired, toolNames);
9071
+ if (repairedCalls.length > 0) {
9072
+ parseText = repaired;
9073
+ toolCalls = repairedCalls;
8562
9074
  }
8563
9075
  }
8564
- for (const tc of toolCalls) {
8565
- currentIndex = processToolCallMatch(
8566
- parseText,
8567
- tc,
8568
- currentIndex,
8569
- processedElements,
8570
- options
8571
- );
9076
+ }
9077
+ for (const tc of toolCalls) {
9078
+ currentIndex = processToolCallMatch(
9079
+ parseText,
9080
+ tc,
9081
+ currentIndex,
9082
+ processedElements,
9083
+ options
9084
+ );
9085
+ }
9086
+ if (currentIndex < parseText.length) {
9087
+ addTextSegment(parseText.slice(currentIndex), processedElements);
9088
+ }
9089
+ return processedElements;
9090
+ },
9091
+ createStreamParser({ tools, options }) {
9092
+ const toolNames = extractToolNames(tools);
9093
+ let buffer = "";
9094
+ let currentToolCall = null;
9095
+ let currentTextId = null;
9096
+ let hasEmittedTextStart = false;
9097
+ const flushText = createFlushTextHandler(
9098
+ () => currentTextId,
9099
+ (newId) => {
9100
+ currentTextId = newId;
9101
+ },
9102
+ () => hasEmittedTextStart,
9103
+ (value) => {
9104
+ hasEmittedTextStart = value;
8572
9105
  }
8573
- if (currentIndex < parseText.length) {
8574
- addTextSegment(parseText.slice(currentIndex), processedElements);
9106
+ );
9107
+ const emitToolInputProgress2 = (controller, toolContent) => {
9108
+ if (!currentToolCall) {
9109
+ return;
8575
9110
  }
8576
- return processedElements;
8577
- },
8578
- createStreamParser({ tools, options }) {
8579
- const toolNames = extractToolNames(tools);
8580
- let buffer = "";
8581
- let currentToolCall = null;
8582
- let currentTextId = null;
8583
- let hasEmittedTextStart = false;
8584
- const flushText = createFlushTextHandler(
8585
- () => currentTextId,
8586
- (newId) => {
8587
- currentTextId = newId;
8588
- },
8589
- () => hasEmittedTextStart,
8590
- (value) => {
8591
- hasEmittedTextStart = value;
8592
- }
8593
- );
8594
- const emitToolInputProgress2 = (controller, toolContent) => {
8595
- if (!currentToolCall) {
8596
- return;
8597
- }
8598
- const parsedArgs = parseYamlContentForStreamProgress(toolContent);
8599
- if (parsedArgs === null) {
8600
- return;
8601
- }
8602
- const fullInput = stringifyToolInputWithSchema({
8603
- toolName: currentToolCall.name,
8604
- args: parsedArgs,
9111
+ const parsedArgs = parseYamlContentForStreamProgress(toolContent);
9112
+ if (parsedArgs === null) {
9113
+ return;
9114
+ }
9115
+ const fullInput = stringifyToolInputWithSchema({
9116
+ toolName: currentToolCall.name,
9117
+ args: parsedArgs,
9118
+ tools
9119
+ });
9120
+ if (fullInput === "{}" && toolContent.trim().length === 0) {
9121
+ return;
9122
+ }
9123
+ emitToolInputProgressDelta({
9124
+ controller,
9125
+ id: currentToolCall.toolCallId,
9126
+ state: currentToolCall,
9127
+ fullInput
9128
+ });
9129
+ };
9130
+ const processToolCallEnd = (controller, toolContent, toolName, toolCallId) => {
9131
+ var _a;
9132
+ const result = parseYamlContent(toolContent);
9133
+ flushText(controller);
9134
+ if (result.ok) {
9135
+ const finalInput = stringifyToolInputWithSchema({
9136
+ toolName,
9137
+ args: result.value,
8605
9138
  tools
8606
9139
  });
8607
- if (fullInput === "{}" && toolContent.trim().length === 0) {
8608
- return;
8609
- }
8610
- emitToolInputProgressDelta({
8611
- controller,
8612
- id: currentToolCall.toolCallId,
8613
- state: currentToolCall,
8614
- fullInput
8615
- });
8616
- };
8617
- const processToolCallEnd = (controller, toolContent, toolName, toolCallId) => {
8618
- var _a;
8619
- const parsedArgs = parseYamlContent(toolContent, options);
8620
- flushText(controller);
8621
- if (parsedArgs === null) {
8622
- const original = `<${toolName}>${toolContent}</${toolName}>`;
8623
- const emitRawFallback = shouldEmitRawToolCallTextOnError(options);
8624
- emitFailedToolInputLifecycle({
9140
+ if (currentToolCall && currentToolCall.toolCallId === toolCallId) {
9141
+ emitFinalizedToolInputLifecycle({
8625
9142
  controller,
8626
9143
  id: toolCallId,
8627
- emitRawToolCallTextOnError: emitRawFallback,
8628
- rawToolCallText: original,
8629
- emitRawText: (rawText) => {
8630
- flushText(controller, rawText);
8631
- }
8632
- });
8633
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
8634
- toolCall: original
8635
- });
8636
- } else {
8637
- const finalInput = stringifyToolInputWithSchema({
9144
+ state: currentToolCall,
8638
9145
  toolName,
8639
- args: parsedArgs,
8640
- tools
8641
- });
8642
- if (currentToolCall && currentToolCall.toolCallId === toolCallId) {
8643
- emitFinalizedToolInputLifecycle({
8644
- controller,
8645
- id: toolCallId,
8646
- state: currentToolCall,
8647
- toolName,
8648
- finalInput,
8649
- onMismatch: options == null ? void 0 : options.onError
8650
- });
8651
- } else {
8652
- enqueueToolInputEndAndCall({
8653
- controller,
8654
- id: toolCallId,
8655
- toolName,
8656
- input: finalInput
8657
- });
8658
- }
8659
- }
8660
- };
8661
- const finalizeUnclosedToolCall = (controller) => {
8662
- var _a;
8663
- if (!currentToolCall) {
8664
- return;
8665
- }
8666
- emitToolInputProgress2(controller, buffer);
8667
- const { name: toolName, toolCallId } = currentToolCall;
8668
- const reconciledBuffer = stripTrailingPartialCloseTag(buffer, toolName);
8669
- const parsedArgs = parseYamlContent(reconciledBuffer, options);
8670
- flushText(controller);
8671
- if (parsedArgs === null) {
8672
- const unfinishedContent = `<${toolName}>${buffer}`;
8673
- const emitRawFallback = shouldEmitRawToolCallTextOnError(options);
8674
- emitFailedToolInputLifecycle({
8675
- controller,
8676
- id: toolCallId,
8677
- emitRawToolCallTextOnError: emitRawFallback,
8678
- rawToolCallText: unfinishedContent,
8679
- emitRawText: (rawText) => {
8680
- flushText(controller, rawText);
8681
- }
9146
+ finalInput,
9147
+ onMismatch: options == null ? void 0 : options.onError
8682
9148
  });
8683
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
8684
- options,
8685
- "Could not complete streaming YAML tool call at finish.",
8686
- { toolCall: unfinishedContent }
8687
- );
8688
9149
  } else {
8689
- const finalInput = stringifyToolInputWithSchema({
8690
- toolName,
8691
- args: parsedArgs,
8692
- tools
8693
- });
8694
- emitFinalizedToolInputLifecycle({
9150
+ enqueueToolInputEndAndCall({
8695
9151
  controller,
8696
9152
  id: toolCallId,
8697
- state: currentToolCall,
8698
9153
  toolName,
8699
- finalInput,
8700
- onMismatch: options == null ? void 0 : options.onError
9154
+ input: finalInput
8701
9155
  });
8702
9156
  }
8703
- buffer = "";
8704
- currentToolCall = null;
8705
- };
8706
- const handlePendingToolCall = (controller, endTag, toolName) => {
8707
- var _a;
8708
- const endIdx = buffer.indexOf(endTag);
8709
- if (endIdx === -1) {
8710
- emitToolInputProgress2(controller, buffer);
8711
- return false;
8712
- }
8713
- const content = buffer.slice(0, endIdx);
8714
- emitToolInputProgress2(controller, content);
8715
- buffer = buffer.slice(endIdx + endTag.length);
8716
- processToolCallEnd(
9157
+ } else {
9158
+ const original = `<${toolName}>${toolContent}</${toolName}>`;
9159
+ const emitRawFallback = shouldEmitRawToolCallTextOnError(options);
9160
+ emitFailedToolInputLifecycle({
8717
9161
  controller,
8718
- content,
9162
+ id: toolCallId,
9163
+ emitRawToolCallTextOnError: emitRawFallback,
9164
+ rawToolCallText: original,
9165
+ emitRawText: (rawText) => {
9166
+ flushText(controller, rawText);
9167
+ }
9168
+ });
9169
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
9170
+ toolCall: original,
8719
9171
  toolName,
8720
- (_a = currentToolCall == null ? void 0 : currentToolCall.toolCallId) != null ? _a : generateToolCallId()
9172
+ toolCallId,
9173
+ dropReason: "malformed-tool-call-body",
9174
+ cause: yamlFailureCause(result.failure)
9175
+ });
9176
+ }
9177
+ };
9178
+ const finalizeUnclosedToolCall = (controller) => {
9179
+ var _a;
9180
+ if (!currentToolCall) {
9181
+ return;
9182
+ }
9183
+ emitToolInputProgress2(controller, buffer);
9184
+ const { name: toolName, toolCallId } = currentToolCall;
9185
+ const reconciledBuffer = stripTrailingPartialCloseTag(buffer, toolName);
9186
+ const result = parseYamlContent(reconciledBuffer);
9187
+ flushText(controller);
9188
+ if (result.ok) {
9189
+ const finalInput = stringifyToolInputWithSchema({
9190
+ toolName,
9191
+ args: result.value,
9192
+ tools
9193
+ });
9194
+ emitFinalizedToolInputLifecycle({
9195
+ controller,
9196
+ id: toolCallId,
9197
+ state: currentToolCall,
9198
+ toolName,
9199
+ finalInput,
9200
+ onMismatch: options == null ? void 0 : options.onError
9201
+ });
9202
+ } else {
9203
+ const unfinishedContent = `<${toolName}>${buffer}`;
9204
+ const emitRawFallback = shouldEmitRawToolCallTextOnError(options);
9205
+ emitFailedToolInputLifecycle({
9206
+ controller,
9207
+ id: toolCallId,
9208
+ emitRawToolCallTextOnError: emitRawFallback,
9209
+ rawToolCallText: unfinishedContent,
9210
+ emitRawText: (rawText) => {
9211
+ flushText(controller, rawText);
9212
+ }
9213
+ });
9214
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
9215
+ options,
9216
+ "Could not complete streaming YAML tool call at finish.",
9217
+ {
9218
+ toolCall: unfinishedContent,
9219
+ toolCallId,
9220
+ toolName,
9221
+ dropReason: "unfinished-tool-call",
9222
+ cause: yamlFailureCause(result.failure)
9223
+ }
8721
9224
  );
9225
+ }
9226
+ buffer = "";
9227
+ currentToolCall = null;
9228
+ };
9229
+ const handlePendingToolCall = (controller, endTag, toolName) => {
9230
+ var _a;
9231
+ const endIdx = buffer.indexOf(endTag);
9232
+ if (endIdx === -1) {
9233
+ emitToolInputProgress2(controller, buffer);
9234
+ return false;
9235
+ }
9236
+ const content = buffer.slice(0, endIdx);
9237
+ emitToolInputProgress2(controller, content);
9238
+ buffer = buffer.slice(endIdx + endTag.length);
9239
+ processToolCallEnd(
9240
+ controller,
9241
+ content,
9242
+ toolName,
9243
+ (_a = currentToolCall == null ? void 0 : currentToolCall.toolCallId) != null ? _a : generateToolCallId()
9244
+ );
9245
+ currentToolCall = null;
9246
+ return true;
9247
+ };
9248
+ const flushSafeText = (controller) => {
9249
+ const maxTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n} />`.length)) : 0;
9250
+ const tail = Math.max(0, maxTagLen - 1);
9251
+ const safeLen = Math.max(0, buffer.length - tail);
9252
+ if (safeLen > 0) {
9253
+ flushText(controller, buffer.slice(0, safeLen));
9254
+ buffer = buffer.slice(safeLen);
9255
+ }
9256
+ };
9257
+ const handleNewToolTag = (controller, tagIndex, tagName, selfClosing, tagLength) => {
9258
+ if (tagIndex > 0) {
9259
+ flushText(controller, buffer.slice(0, tagIndex));
9260
+ }
9261
+ flushText(controller);
9262
+ if (selfClosing) {
9263
+ buffer = buffer.slice(tagIndex + tagLength);
9264
+ const toolCallId = generateToolCallId();
9265
+ currentToolCall = {
9266
+ name: tagName,
9267
+ toolCallId,
9268
+ emittedInput: ""
9269
+ };
9270
+ controller.enqueue({
9271
+ type: "tool-input-start",
9272
+ id: toolCallId,
9273
+ toolName: tagName
9274
+ });
9275
+ processToolCallEnd(controller, "", tagName, toolCallId);
8722
9276
  currentToolCall = null;
8723
- return true;
8724
- };
8725
- const flushSafeText = (controller) => {
8726
- const maxTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n} />`.length)) : 0;
8727
- const tail = Math.max(0, maxTagLen - 1);
8728
- const safeLen = Math.max(0, buffer.length - tail);
8729
- if (safeLen > 0) {
8730
- flushText(controller, buffer.slice(0, safeLen));
8731
- buffer = buffer.slice(safeLen);
8732
- }
8733
- };
8734
- const handleNewToolTag = (controller, tagIndex, tagName, selfClosing, tagLength) => {
8735
- if (tagIndex > 0) {
8736
- flushText(controller, buffer.slice(0, tagIndex));
8737
- }
8738
- flushText(controller);
8739
- if (selfClosing) {
8740
- buffer = buffer.slice(tagIndex + tagLength);
8741
- const toolCallId = generateToolCallId();
8742
- currentToolCall = {
8743
- name: tagName,
8744
- toolCallId,
8745
- emittedInput: ""
8746
- };
8747
- controller.enqueue({
8748
- type: "tool-input-start",
8749
- id: toolCallId,
8750
- toolName: tagName
8751
- });
8752
- processToolCallEnd(controller, "", tagName, toolCallId);
8753
- currentToolCall = null;
9277
+ } else {
9278
+ const startTag = `<${tagName}>`;
9279
+ buffer = buffer.slice(tagIndex + startTag.length);
9280
+ currentToolCall = {
9281
+ name: tagName,
9282
+ toolCallId: generateToolCallId(),
9283
+ emittedInput: ""
9284
+ };
9285
+ controller.enqueue({
9286
+ type: "tool-input-start",
9287
+ id: currentToolCall.toolCallId,
9288
+ toolName: tagName
9289
+ });
9290
+ }
9291
+ };
9292
+ const processBuffer = (controller) => {
9293
+ while (true) {
9294
+ if (currentToolCall) {
9295
+ const toolName = currentToolCall.name;
9296
+ const endTag = `</${toolName}>`;
9297
+ if (!handlePendingToolCall(controller, endTag, toolName)) {
9298
+ break;
9299
+ }
8754
9300
  } else {
8755
- const startTag = `<${tagName}>`;
8756
- buffer = buffer.slice(tagIndex + startTag.length);
8757
- currentToolCall = {
8758
- name: tagName,
8759
- toolCallId: generateToolCallId(),
8760
- emittedInput: ""
8761
- };
8762
- controller.enqueue({
8763
- type: "tool-input-start",
8764
- id: currentToolCall.toolCallId,
8765
- toolName: tagName
8766
- });
8767
- }
8768
- };
8769
- const processBuffer = (controller) => {
8770
- while (true) {
8771
- if (currentToolCall) {
8772
- const toolName = currentToolCall.name;
8773
- const endTag = `</${toolName}>`;
8774
- if (!handlePendingToolCall(controller, endTag, toolName)) {
8775
- break;
8776
- }
8777
- } else {
8778
- const { index, name, selfClosing, tagLength } = findEarliestToolTag(
8779
- buffer,
8780
- toolNames
8781
- );
8782
- if (index === -1) {
8783
- flushSafeText(controller);
8784
- break;
8785
- }
8786
- handleNewToolTag(controller, index, name, selfClosing, tagLength);
9301
+ const { index, name, selfClosing, tagLength } = findEarliestToolTag(
9302
+ buffer,
9303
+ toolNames
9304
+ );
9305
+ if (index === -1) {
9306
+ flushSafeText(controller);
9307
+ break;
8787
9308
  }
9309
+ handleNewToolTag(controller, index, name, selfClosing, tagLength);
8788
9310
  }
8789
- };
8790
- return new TransformStream({
8791
- transform(chunk, controller) {
8792
- var _a;
8793
- if (chunk.type === "finish") {
8794
- if (currentToolCall) {
8795
- finalizeUnclosedToolCall(controller);
8796
- } else if (buffer) {
8797
- flushText(controller, buffer);
8798
- buffer = "";
8799
- }
8800
- flushText(controller);
8801
- controller.enqueue(chunk);
8802
- return;
8803
- }
8804
- if (chunk.type !== "text-delta") {
8805
- if (!currentToolCall && buffer) {
8806
- flushText(controller, buffer);
8807
- buffer = "";
8808
- }
8809
- controller.enqueue(chunk);
8810
- return;
8811
- }
8812
- const textContent = (_a = chunk.delta) != null ? _a : "";
8813
- buffer += textContent;
8814
- processBuffer(controller);
8815
- },
8816
- flush(controller) {
9311
+ }
9312
+ };
9313
+ return new TransformStream({
9314
+ transform(chunk, controller) {
9315
+ var _a;
9316
+ if (chunk.type === "finish") {
8817
9317
  if (currentToolCall) {
8818
9318
  finalizeUnclosedToolCall(controller);
8819
9319
  } else if (buffer) {
8820
9320
  flushText(controller, buffer);
8821
9321
  buffer = "";
8822
9322
  }
8823
- if (currentTextId && hasEmittedTextStart) {
8824
- controller.enqueue({
8825
- type: "text-end",
8826
- id: currentTextId
8827
- });
8828
- hasEmittedTextStart = false;
8829
- currentTextId = null;
9323
+ flushText(controller);
9324
+ controller.enqueue(chunk);
9325
+ return;
9326
+ }
9327
+ if (chunk.type !== "text-delta") {
9328
+ if (!currentToolCall && buffer) {
9329
+ flushText(controller, buffer);
9330
+ buffer = "";
8830
9331
  }
9332
+ controller.enqueue(chunk);
9333
+ return;
9334
+ }
9335
+ const textContent = (_a = chunk.delta) != null ? _a : "";
9336
+ buffer += textContent;
9337
+ processBuffer(controller);
9338
+ },
9339
+ flush(controller) {
9340
+ if (currentToolCall) {
9341
+ finalizeUnclosedToolCall(controller);
9342
+ } else if (buffer) {
9343
+ flushText(controller, buffer);
9344
+ buffer = "";
9345
+ }
9346
+ if (currentTextId && hasEmittedTextStart) {
9347
+ controller.enqueue({
9348
+ type: "text-end",
9349
+ id: currentTextId
9350
+ });
9351
+ hasEmittedTextStart = false;
9352
+ currentTextId = null;
8831
9353
  }
8832
- });
8833
- },
8834
- extractToolCallSegments({ text, tools }) {
8835
- const toolNames = tools.map((t) => t.name).filter(Boolean);
8836
- if (toolNames.length === 0) {
8837
- return [];
8838
9354
  }
8839
- return findToolCalls2(text, toolNames).map(
8840
- (tc) => `<${tc.toolName}>${tc.content}</${tc.toolName}>`
8841
- );
9355
+ });
9356
+ },
9357
+ extractToolCallSegments({ text, tools }) {
9358
+ const toolNames = tools.map((t) => t.name).filter(Boolean);
9359
+ if (toolNames.length === 0) {
9360
+ return [];
8842
9361
  }
8843
- };
8844
- };
9362
+ return findToolCalls2(text, toolNames).map(
9363
+ (tc) => `<${tc.toolName}>${tc.content}</${tc.toolName}>`
9364
+ );
9365
+ }
9366
+ });
8845
9367
 
8846
9368
  // src/core/utils/dynamic-tool-schema.ts
8847
9369
  function createDynamicIfThenElseSchema(tools) {
@@ -9037,7 +9559,7 @@ function parseJsonCandidate(candidateText) {
9037
9559
  try {
9038
9560
  return parse(candidateText);
9039
9561
  } catch (e) {
9040
- return void 0;
9562
+ return;
9041
9563
  }
9042
9564
  }
9043
9565
  function extractCodeBlockCandidates(text) {