@ai-sdk-tool/parser 2.1.7 → 3.0.0-canary.0

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
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // src/index.ts
@@ -52,7 +42,10 @@ __export(src_exports, {
52
42
  logRawChunk: () => logRawChunk,
53
43
  morphXmlProtocol: () => morphXmlProtocol,
54
44
  morphXmlToolMiddleware: () => morphXmlToolMiddleware,
55
- originalToolsSchema: () => originalToolsSchema
45
+ originalToolsSchema: () => originalToolsSchema,
46
+ parseRJSON: () => parse,
47
+ stringifyRJSON: () => stringify,
48
+ transformRJSON: () => transform
56
49
  });
57
50
  module.exports = __toCommonJS(src_exports);
58
51
 
@@ -62,11 +55,130 @@ var import_provider_utils = require("@ai-sdk/provider-utils");
62
55
  // src/protocols/json-mix-protocol.ts
63
56
  var import_provider_utils2 = require("@ai-sdk/provider-utils");
64
57
 
58
+ // src/utils/debug.ts
59
+ var LINE_SPLIT_REGEX = /\r?\n/;
60
+ function normalizeBooleanString(value) {
61
+ const normalized = value.trim().toLowerCase();
62
+ if (normalized === "1" || normalized === "true" || normalized === "yes") {
63
+ return true;
64
+ }
65
+ if (normalized === "0" || normalized === "false" || normalized === "no") {
66
+ return false;
67
+ }
68
+ return;
69
+ }
70
+ function getDebugLevel() {
71
+ const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW || "off";
72
+ const envLower = String(envVal).toLowerCase();
73
+ if (envLower === "stream" || envLower === "parse" || envLower === "off") {
74
+ return envLower;
75
+ }
76
+ const boolEnv = normalizeBooleanString(envLower);
77
+ if (boolEnv === true) {
78
+ return "stream";
79
+ }
80
+ if (envLower === "2") {
81
+ return "parse";
82
+ }
83
+ return "off";
84
+ }
85
+ function color(code) {
86
+ return (text) => `\x1B[${code}m${text}\x1B[0m`;
87
+ }
88
+ var ANSI_GRAY = 90;
89
+ var ANSI_YELLOW = 33;
90
+ var ANSI_CYAN = 36;
91
+ var ANSI_BG_BLUE = 44;
92
+ var ANSI_BG_GREEN = 42;
93
+ var ANSI_INVERSE = 7;
94
+ var ANSI_UNDERLINE = 4;
95
+ var ANSI_BOLD = 1;
96
+ var cGray = color(ANSI_GRAY);
97
+ var cYellow = color(ANSI_YELLOW);
98
+ var cCyan = color(ANSI_CYAN);
99
+ var cBgBlue = color(ANSI_BG_BLUE);
100
+ var cBgGreen = color(ANSI_BG_GREEN);
101
+ var cInverse = color(ANSI_INVERSE);
102
+ var cUnderline = color(ANSI_UNDERLINE);
103
+ var cBold = color(ANSI_BOLD);
104
+ function safeStringify(value) {
105
+ try {
106
+ return `
107
+ ${typeof value === "string" ? value : JSON.stringify(value, null, 2)}`;
108
+ } catch (e) {
109
+ return String(value);
110
+ }
111
+ }
112
+ function logRawChunk(part) {
113
+ console.log(cGray("[debug:mw:raw]"), cYellow(safeStringify(part)));
114
+ }
115
+ function logParsedChunk(part) {
116
+ console.log(cGray("[debug:mw:out]"), cCyan(safeStringify(part)));
117
+ }
118
+ function getHighlightStyle() {
119
+ const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW_STYLE || "bg";
120
+ const normalized = String(envVal).trim().toLowerCase();
121
+ if (normalized === "inverse" || normalized === "invert") {
122
+ return "inverse";
123
+ }
124
+ if (normalized === "underline" || normalized === "ul") {
125
+ return "underline";
126
+ }
127
+ if (normalized === "bold") {
128
+ return "bold";
129
+ }
130
+ if (normalized === "bg" || normalized === "background") {
131
+ return "bg";
132
+ }
133
+ const asBool = normalizeBooleanString(normalized);
134
+ if (asBool === true) {
135
+ return "bg";
136
+ }
137
+ return "bg";
138
+ }
139
+ function getHighlightFunction(style) {
140
+ if (style === "inverse") {
141
+ return cInverse;
142
+ }
143
+ if (style === "underline") {
144
+ return cUnderline;
145
+ }
146
+ if (style === "bold") {
147
+ return cBold;
148
+ }
149
+ if (style === "bg") {
150
+ return cBgGreen;
151
+ }
152
+ return cYellow;
153
+ }
154
+ function renderHighlightedText(originalText, style, highlight) {
155
+ if (style === "bg" || style === "inverse" || style === "underline" || style === "bold") {
156
+ return originalText.split(LINE_SPLIT_REGEX).map((line) => line.length ? highlight(line) : line).join("\n");
157
+ }
158
+ return highlight(originalText);
159
+ }
160
+ function logParsedSummary({
161
+ toolCalls,
162
+ originalText
163
+ }) {
164
+ if (originalText) {
165
+ const style = getHighlightStyle();
166
+ const highlight = getHighlightFunction(style);
167
+ const rendered = renderHighlightedText(originalText, style, highlight);
168
+ console.log(cGray("[debug:mw:origin]"), `
169
+ ${rendered}`);
170
+ }
171
+ if (toolCalls.length > 0) {
172
+ const styledSummary = safeStringify(toolCalls).split(LINE_SPLIT_REGEX).map((line) => line.length ? cBgBlue(line) : line).join("\n");
173
+ console.log(cGray("[debug:mw:summary]"), styledSummary);
174
+ }
175
+ }
176
+
65
177
  // src/utils/dynamic-tool-schema.ts
66
178
  function createDynamicIfThenElseSchema(tools) {
67
179
  let currentSchema = {};
68
180
  const toolNames = [];
69
- for (let i = tools.length - 1; i >= 0; i--) {
181
+ for (let i = tools.length - 1; i >= 0; i -= 1) {
70
182
  const tool = tools[i];
71
183
  if (tool.type === "provider-defined") {
72
184
  throw new Error(
@@ -83,6 +195,7 @@ function createDynamicIfThenElseSchema(tools) {
83
195
  },
84
196
  required: ["name"]
85
197
  },
198
+ // biome-ignore lint/suspicious/noThenProperty: JSON Schema uses 'then' as a keyword
86
199
  then: {
87
200
  properties: {
88
201
  name: {
@@ -127,7 +240,7 @@ function getPotentialStartIndex(text, searchedText) {
127
240
  if (directIndex !== -1) {
128
241
  return directIndex;
129
242
  }
130
- for (let i = text.length - 1; i >= 0; i--) {
243
+ for (let i = text.length - 1; i >= 0; i -= 1) {
131
244
  const suffix = text.substring(i);
132
245
  if (searchedText.startsWith(suffix)) {
133
246
  return i;
@@ -136,6 +249,48 @@ function getPotentialStartIndex(text, searchedText) {
136
249
  return null;
137
250
  }
138
251
 
252
+ // src/utils/on-error.ts
253
+ function extractOnErrorOption(providerOptions) {
254
+ var _a;
255
+ if (providerOptions && typeof providerOptions === "object") {
256
+ const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
257
+ return onError ? { onError } : void 0;
258
+ }
259
+ return;
260
+ }
261
+
262
+ // src/utils/provider-options.ts
263
+ var originalToolsSchema = {
264
+ encode: encodeOriginalTools,
265
+ decode: decodeOriginalTools
266
+ };
267
+ function encodeOriginalTools(tools) {
268
+ return (tools == null ? void 0 : tools.map((t) => ({
269
+ name: t.name,
270
+ inputSchema: JSON.stringify(t.inputSchema)
271
+ }))) || [];
272
+ }
273
+ function decodeOriginalTools(originalTools) {
274
+ if (!originalTools) {
275
+ return [];
276
+ }
277
+ return originalTools.map(
278
+ (t) => ({
279
+ type: "function",
280
+ name: t.name,
281
+ inputSchema: JSON.parse(t.inputSchema)
282
+ })
283
+ );
284
+ }
285
+ function extractToolNamesFromOriginalTools(originalTools) {
286
+ return (originalTools == null ? void 0 : originalTools.map((t) => t.name)) || [];
287
+ }
288
+ function isToolChoiceActive(params) {
289
+ var _a, _b, _c;
290
+ const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
291
+ return !!(typeof params.providerOptions === "object" && params.providerOptions !== null && typeof ((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) === "object" && toolChoice && typeof toolChoice === "object" && (toolChoice.type === "tool" || toolChoice.type === "required"));
292
+ }
293
+
139
294
  // src/utils/regex.ts
140
295
  function escapeRegExp(literal) {
141
296
  return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -148,9 +303,24 @@ __export(robust_json_exports, {
148
303
  stringify: () => stringify,
149
304
  transform: () => transform
150
305
  });
306
+ var WHITESPACE_TEST_REGEX = /\s/;
307
+ var WHITESPACE_REGEX = /^\s+/;
308
+ var OBJECT_START_REGEX = /^\{/;
309
+ var OBJECT_END_REGEX = /^\}/;
310
+ var ARRAY_START_REGEX = /^\[/;
311
+ var ARRAY_END_REGEX = /^\]/;
312
+ var COMMA_REGEX = /^,/;
313
+ var COLON_REGEX = /^:/;
314
+ var KEYWORD_REGEX = /^(?:true|false|null)/;
315
+ var NUMBER_REGEX = /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/;
316
+ var STRING_DOUBLE_REGEX = /^"(?:[^"\\]|\\["bnrtf\\/]|\\u[0-9a-fA-F]{4})*"/;
317
+ var STRING_SINGLE_REGEX = /^'((?:[^'\\]|\\['bnrtf\\/]|\\u[0-9a-fA-F]{4})*)'/;
318
+ var COMMENT_SINGLE_REGEX = /^\/\/.*?(?:\r\n|\r|\n)/;
319
+ var COMMENT_MULTI_REGEX = /^\/\*[\s\S]*?\*\//;
320
+ var IDENTIFIER_REGEX = /^[$a-zA-Z0-9_\-+.*?!|&%^/#\\]+/;
151
321
  function some(array, f) {
152
322
  let acc = false;
153
- for (let i = 0; i < array.length; i++) {
323
+ for (let i = 0; i < array.length; i += 1) {
154
324
  const result = f(array[i], i, array);
155
325
  acc = result === void 0 ? false : result;
156
326
  if (acc) {
@@ -160,31 +330,31 @@ function some(array, f) {
160
330
  return acc;
161
331
  }
162
332
  function makeLexer(tokenSpecs) {
163
- return function(contents) {
333
+ return (contents) => {
164
334
  const tokens = [];
165
335
  let line = 1;
336
+ let remainingContents = contents;
166
337
  function findToken() {
167
338
  const result = some(tokenSpecs, (tokenSpec) => {
168
- const m = tokenSpec.re.exec(contents);
339
+ const m = tokenSpec.re.exec(remainingContents);
169
340
  if (m) {
170
341
  const raw = m[0];
171
- contents = contents.slice(raw.length);
342
+ remainingContents = remainingContents.slice(raw.length);
172
343
  return {
173
344
  raw,
174
345
  matched: tokenSpec.f(m)
175
346
  // Process the match using the spec's function
176
347
  };
177
- } else {
178
- return void 0;
179
348
  }
349
+ return;
180
350
  });
181
351
  return result === false ? void 0 : result;
182
352
  }
183
- while (contents !== "") {
353
+ while (remainingContents !== "") {
184
354
  const matched = findToken();
185
355
  if (!matched) {
186
356
  const err = new SyntaxError(
187
- `Unexpected character: ${contents[0]}; input: ${contents.substr(
357
+ `Unexpected character: ${remainingContents[0]}; input: ${remainingContents.substr(
188
358
  0,
189
359
  100
190
360
  )}`
@@ -206,11 +376,11 @@ function fStringSingle(m) {
206
376
  (mm) => {
207
377
  if (mm === '"') {
208
378
  return '\\"';
209
- } else if (mm === "\\'") {
379
+ }
380
+ if (mm === "\\'") {
210
381
  return "'";
211
- } else {
212
- return mm;
213
382
  }
383
+ return mm;
214
384
  }
215
385
  );
216
386
  const match = `"${content}"`;
@@ -245,7 +415,10 @@ function fIdentifier(m) {
245
415
  };
246
416
  }
247
417
  function fComment(m) {
248
- const match = m[0].replace(/./g, (c) => /\s/.test(c) ? c : " ");
418
+ const match = m[0].replace(
419
+ /./g,
420
+ (c) => WHITESPACE_TEST_REGEX.test(c) ? c : " "
421
+ );
249
422
  return {
250
423
  type: " ",
251
424
  // Represent comments as whitespace tokens
@@ -260,7 +433,7 @@ function fNumber(m) {
260
433
  type: "number",
261
434
  match: m[0],
262
435
  // The raw matched number string
263
- value: parseFloat(m[0])
436
+ value: Number.parseFloat(m[0])
264
437
  // Convert string to number
265
438
  };
266
439
  }
@@ -290,46 +463,46 @@ function fKeyword(m) {
290
463
  }
291
464
  function makeTokenSpecs(relaxed) {
292
465
  function f(type) {
293
- return function(m) {
466
+ return (m) => {
294
467
  return { type, match: m[0], value: void 0 };
295
468
  };
296
469
  }
297
470
  let tokenSpecs = [
298
- { re: /^\s+/, f: f(" ") },
471
+ { re: WHITESPACE_REGEX, f: f(" ") },
299
472
  // Whitespace
300
- { re: /^\{/, f: f("{") },
473
+ { re: OBJECT_START_REGEX, f: f("{") },
301
474
  // Object start
302
- { re: /^\}/, f: f("}") },
475
+ { re: OBJECT_END_REGEX, f: f("}") },
303
476
  // Object end
304
- { re: /^\[/, f: f("[") },
477
+ { re: ARRAY_START_REGEX, f: f("[") },
305
478
  // Array start
306
- { re: /^\]/, f: f("]") },
479
+ { re: ARRAY_END_REGEX, f: f("]") },
307
480
  // Array end
308
- { re: /^,/, f: f(",") },
481
+ { re: COMMA_REGEX, f: f(",") },
309
482
  // Comma separator
310
- { re: /^:/, f: f(":") },
483
+ { re: COLON_REGEX, f: f(":") },
311
484
  // Key-value separator
312
- { re: /^(?:true|false|null)/, f: fKeyword },
485
+ { re: KEYWORD_REGEX, f: fKeyword },
313
486
  // Keywords
314
487
  // Number: optional sign, digits, optional decimal part, optional exponent
315
- { re: /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/, f: fNumber },
488
+ { re: NUMBER_REGEX, f: fNumber },
316
489
  // String: double-quoted, handles escapes
317
- { re: /^"(?:[^"\\]|\\["bnrtf\\/]|\\u[0-9a-fA-F]{4})*"/, f: fStringDouble }
490
+ { re: STRING_DOUBLE_REGEX, f: fStringDouble }
318
491
  ];
319
492
  if (relaxed) {
320
493
  tokenSpecs = tokenSpecs.concat([
321
494
  // Single-quoted strings
322
495
  {
323
- re: /^'((?:[^'\\]|\\['bnrtf\\/]|\\u[0-9a-fA-F]{4})*)'/,
496
+ re: STRING_SINGLE_REGEX,
324
497
  f: fStringSingle
325
498
  },
326
499
  // Single-line comments (// ...)
327
- { re: /^\/\/.*?(?:\r\n|\r|\n)/, f: fComment },
500
+ { re: COMMENT_SINGLE_REGEX, f: fComment },
328
501
  // Multi-line comments (/* ... */)
329
- { re: /^\/\*[\s\S]*?\*\//, f: fComment },
502
+ { re: COMMENT_MULTI_REGEX, f: fComment },
330
503
  // Unquoted identifiers (treated as strings)
331
504
  // Allows letters, numbers, _, -, +, ., *, ?, !, |, &, %, ^, /, #, \
332
- { re: /^[$a-zA-Z0-9_\-+.*?!|&%^/#\\]+/, f: fIdentifier }
505
+ { re: IDENTIFIER_REGEX, f: fIdentifier }
333
506
  // Note: The order matters here. Identifiers are checked after keywords/numbers.
334
507
  ]);
335
508
  }
@@ -338,12 +511,13 @@ function makeTokenSpecs(relaxed) {
338
511
  var lexer = makeLexer(makeTokenSpecs(true));
339
512
  var strictLexer = makeLexer(makeTokenSpecs(false));
340
513
  function previousNWSToken(tokens, index) {
341
- for (; index >= 0; index--) {
342
- if (tokens[index].type !== " ") {
343
- return index;
514
+ let currentIndex = index;
515
+ for (; currentIndex >= 0; currentIndex -= 1) {
516
+ if (tokens[currentIndex].type !== " ") {
517
+ return currentIndex;
344
518
  }
345
519
  }
346
- return void 0;
520
+ return;
347
521
  }
348
522
  function stripTrailingComma(tokens) {
349
523
  const res = [];
@@ -372,15 +546,14 @@ function stripTrailingComma(tokens) {
372
546
  function transform(text) {
373
547
  let tokens = lexer(text);
374
548
  tokens = stripTrailingComma(tokens);
375
- return tokens.reduce((str, token) => {
376
- return str + token.match;
377
- }, "");
549
+ return tokens.reduce((str, token) => str + token.match, "");
378
550
  }
379
551
  function popToken(tokens, state) {
552
+ var _a, _b;
380
553
  const token = tokens[state.pos];
381
554
  state.pos += 1;
382
555
  if (!token) {
383
- const lastLine = tokens.length !== 0 ? tokens[tokens.length - 1].line : 1;
556
+ const lastLine = tokens.length !== 0 ? (_b = (_a = tokens.at(-1)) == null ? void 0 : _a.line) != null ? _b : 1 : 1;
384
557
  return { type: "eof", match: "", value: void 0, line: lastLine };
385
558
  }
386
559
  return token;
@@ -418,11 +591,13 @@ function skipPunctuation(tokens, state, valid) {
418
591
  const punctuation = [",", ":", "]", "}"];
419
592
  let token = popToken(tokens, state);
420
593
  while (true) {
421
- if (valid && valid.includes(token.type)) {
594
+ if (valid == null ? void 0 : valid.includes(token.type)) {
422
595
  return token;
423
- } else if (token.type === "eof") {
596
+ }
597
+ if (token.type === "eof") {
424
598
  return token;
425
- } else if (punctuation.includes(token.type)) {
599
+ }
600
+ if (punctuation.includes(token.type)) {
426
601
  const message = `Unexpected token: ${strToken(
427
602
  token
428
603
  )}, expected '[', '{', number, string or atom`;
@@ -463,7 +638,7 @@ function raiseUnexpected(state, token, expected) {
463
638
  }
464
639
  function checkDuplicates(state, obj, token) {
465
640
  const key = String(token.value);
466
- if (!state.duplicate && Object.prototype.hasOwnProperty.call(obj, key)) {
641
+ if (!state.duplicate && Object.hasOwn(obj, key)) {
467
642
  raiseError(state, token, `Duplicate key: ${key}`);
468
643
  }
469
644
  }
@@ -560,51 +735,84 @@ function parseArray(tokens, state) {
560
735
  // The closing token for an array
561
736
  });
562
737
  }
563
- function parseMany(tokens, state, result, opts) {
564
- let token = skipPunctuation(tokens, state, opts.skip);
565
- if (token.type === "eof") {
566
- raiseUnexpected(state, token, `'${opts.endSymbol}' or ${opts.elementName}`);
567
- if (state.tolerant) {
568
- return result;
569
- } else {
738
+ function handleInvalidToken(token, state, opts, result) {
739
+ raiseUnexpected(state, token, `',' or '${opts.endSymbol}'`);
740
+ if (state.tolerant) {
741
+ if (token.type === "eof") {
570
742
  return result;
571
743
  }
744
+ state.pos -= 1;
745
+ return null;
746
+ }
747
+ return result;
748
+ }
749
+ function handleCommaToken(params) {
750
+ const { token, tokens, state, opts, result } = params;
751
+ const nextToken = tokens[state.pos];
752
+ if (state.tolerant && nextToken && nextToken.type === opts.endSymbol) {
753
+ raiseError(state, token, `Trailing comma before '${opts.endSymbol}'`);
754
+ popToken(tokens, state);
755
+ return result;
756
+ }
757
+ opts.elementParser(tokens, state, result);
758
+ return null;
759
+ }
760
+ function parseManyInitialElement(tokens, state, result, opts) {
761
+ const token = skipPunctuation(tokens, state, opts.skip);
762
+ if (token.type === "eof") {
763
+ raiseUnexpected(state, token, `'${opts.endSymbol}' or ${opts.elementName}`);
764
+ return result;
572
765
  }
573
766
  if (token.type === opts.endSymbol) {
574
767
  return result;
575
768
  }
576
769
  state.pos -= 1;
577
770
  opts.elementParser(tokens, state, result);
578
- while (true) {
579
- token = popToken(tokens, state);
580
- if (token.type !== opts.endSymbol && token.type !== ",") {
581
- raiseUnexpected(state, token, `',' or '${opts.endSymbol}'`);
582
- if (state.tolerant) {
583
- if (token.type === "eof") {
584
- return result;
585
- }
586
- state.pos -= 1;
587
- } else {
588
- return result;
589
- }
771
+ return;
772
+ }
773
+ function parseManyProcessToken(params) {
774
+ const { token, tokens, state, opts, result } = params;
775
+ if (token.type !== opts.endSymbol && token.type !== ",") {
776
+ const handledResult = handleInvalidToken(token, state, opts, result);
777
+ if (handledResult !== null) {
778
+ return handledResult;
590
779
  }
591
- switch (token.type) {
592
- case opts.endSymbol:
593
- return result;
594
- case ",": {
595
- const nextToken = tokens[state.pos];
596
- if (state.tolerant && nextToken && nextToken.type === opts.endSymbol) {
597
- raiseError(state, token, `Trailing comma before '${opts.endSymbol}'`);
598
- popToken(tokens, state);
599
- return result;
600
- }
601
- opts.elementParser(tokens, state, result);
602
- break;
603
- }
604
- // Default case is only reachable in tolerant mode recovery above
605
- default:
606
- opts.elementParser(tokens, state, result);
607
- break;
780
+ }
781
+ if (token.type === opts.endSymbol) {
782
+ return result;
783
+ }
784
+ if (token.type === ",") {
785
+ const handledResult = handleCommaToken({
786
+ token,
787
+ tokens,
788
+ state,
789
+ opts,
790
+ result
791
+ });
792
+ if (handledResult !== null) {
793
+ return handledResult;
794
+ }
795
+ return;
796
+ }
797
+ opts.elementParser(tokens, state, result);
798
+ return;
799
+ }
800
+ function parseMany(tokens, state, result, opts) {
801
+ const initialResult = parseManyInitialElement(tokens, state, result, opts);
802
+ if (initialResult !== void 0) {
803
+ return initialResult;
804
+ }
805
+ while (true) {
806
+ const token = popToken(tokens, state);
807
+ const processedResult = parseManyProcessToken({
808
+ token,
809
+ tokens,
810
+ state,
811
+ opts,
812
+ result
813
+ });
814
+ if (processedResult !== void 0) {
815
+ return processedResult;
608
816
  }
609
817
  }
610
818
  }
@@ -638,7 +846,7 @@ function parseAny(tokens, state, end = false) {
638
846
  raiseUnexpected(state, token, "json value");
639
847
  }
640
848
  raiseUnexpected(state, token, "json value");
641
- return void 0;
849
+ return;
642
850
  }
643
851
  switch (token.type) {
644
852
  case "{":
@@ -659,7 +867,7 @@ function parseAny(tokens, state, end = false) {
659
867
  if (state.tolerant) {
660
868
  ret = null;
661
869
  } else {
662
- return void 0;
870
+ return;
663
871
  }
664
872
  }
665
873
  if (end) {
@@ -668,7 +876,7 @@ function parseAny(tokens, state, end = false) {
668
876
  }
669
877
  return ret;
670
878
  }
671
- function parse(text, optsOrReviver) {
879
+ function normalizeParseOptions(optsOrReviver) {
672
880
  var _a;
673
881
  let options = {};
674
882
  if (typeof optsOrReviver === "function") {
@@ -689,69 +897,54 @@ function parse(text, optsOrReviver) {
689
897
  options.relaxed = true;
690
898
  }
691
899
  }
692
- options.tolerant = options.tolerant || options.warnings || false;
693
- options.warnings = options.warnings || false;
900
+ options.tolerant = options.tolerant || options.warnings;
694
901
  options.duplicate = (_a = options.duplicate) != null ? _a : false;
695
- if (!options.relaxed && !options.warnings && !options.tolerant) {
696
- if (!options.duplicate) {
697
- } else {
698
- return JSON.parse(
699
- text,
700
- options.reviver
701
- );
702
- }
703
- }
902
+ return options;
903
+ }
904
+ function createParseState(options) {
905
+ var _a, _b;
906
+ return {
907
+ pos: 0,
908
+ reviver: options.reviver,
909
+ tolerant: (_a = options.tolerant) != null ? _a : false,
910
+ duplicate: (_b = options.duplicate) != null ? _b : false,
911
+ warnings: []
912
+ };
913
+ }
914
+ function parseWithCustomParser(text, options) {
704
915
  const lexerToUse = options.relaxed ? lexer : strictLexer;
705
916
  let tokens = lexerToUse(text);
706
917
  if (options.relaxed) {
707
918
  tokens = stripTrailingComma(tokens);
708
919
  }
709
- if (options.warnings || options.tolerant) {
710
- tokens = tokens.filter((token) => token.type !== " ");
711
- const state = {
712
- pos: 0,
713
- reviver: options.reviver,
714
- tolerant: options.tolerant,
715
- duplicate: options.duplicate,
716
- // true = allow duplicate keys, false = reject duplicates
717
- warnings: []
718
- };
719
- return parseAny(tokens, state, true);
720
- } else {
721
- tokens.reduce((str, token) => {
722
- return str + token.match;
723
- }, "");
724
- if (!options.relaxed && !options.warnings && !options.tolerant && options.duplicate) {
725
- return JSON.parse(text, options.reviver);
726
- } else if (options.warnings || options.tolerant || !options.duplicate) {
727
- tokens = lexerToUse(text);
728
- if (options.relaxed) {
729
- tokens = stripTrailingComma(tokens);
730
- }
731
- tokens = tokens.filter((token) => token.type !== " ");
732
- const state = {
733
- pos: 0,
734
- reviver: options.reviver,
735
- tolerant: options.tolerant || false,
736
- // Ensure boolean
737
- duplicate: options.duplicate,
738
- // true = allow duplicate keys, false = reject duplicates
739
- warnings: []
740
- };
741
- return parseAny(tokens, state, true);
742
- } else {
743
- tokens = lexer(text);
744
- tokens = stripTrailingComma(tokens);
745
- const newtext = tokens.reduce((str, token) => str + token.match, "");
746
- return JSON.parse(
747
- newtext,
748
- options.reviver
749
- );
750
- }
920
+ tokens = tokens.filter((token) => token.type !== " ");
921
+ const state = createParseState(options);
922
+ return parseAny(tokens, state, true);
923
+ }
924
+ function parseWithTransform(text, options) {
925
+ let tokens = lexer(text);
926
+ tokens = stripTrailingComma(tokens);
927
+ const newtext = tokens.reduce((str, token) => str + token.match, "");
928
+ return JSON.parse(
929
+ newtext,
930
+ options.reviver
931
+ );
932
+ }
933
+ function parse(text, optsOrReviver) {
934
+ const options = normalizeParseOptions(optsOrReviver);
935
+ if (!(options.relaxed || options.warnings || options.tolerant) && options.duplicate) {
936
+ return JSON.parse(
937
+ text,
938
+ options.reviver
939
+ );
751
940
  }
941
+ if (options.warnings || options.tolerant || !options.duplicate) {
942
+ return parseWithCustomParser(text, options);
943
+ }
944
+ return parseWithTransform(text, options);
752
945
  }
753
946
  function stringifyPair(obj, key) {
754
- return JSON.stringify(key) + ":" + stringify(obj[key]);
947
+ return `${JSON.stringify(key)}:${stringify(obj[key])}`;
755
948
  }
756
949
  function stringify(obj) {
757
950
  const type = typeof obj;
@@ -763,147 +956,207 @@ function stringify(obj) {
763
956
  }
764
957
  if (Array.isArray(obj)) {
765
958
  const elements = obj.map(stringify).join(",");
766
- return "[" + elements + "]";
959
+ return `[${elements}]`;
767
960
  }
768
961
  if (type === "object") {
769
962
  const keys = Object.keys(obj);
770
963
  keys.sort();
771
964
  const pairs = keys.map((key) => stringifyPair(obj, key)).join(",");
772
- return "{" + pairs + "}";
965
+ return `{${pairs}}`;
773
966
  }
774
967
  return "null";
775
968
  }
776
969
 
777
- // src/utils/debug.ts
778
- function normalizeBooleanString(value) {
779
- const normalized = value.trim().toLowerCase();
780
- if (normalized === "1" || normalized === "true" || normalized === "yes") {
781
- return true;
782
- }
783
- if (normalized === "0" || normalized === "false" || normalized === "no") {
784
- return false;
970
+ // src/utils/type-guards.ts
971
+ function isToolCallContent(content) {
972
+ return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
973
+ (typeof content.input === "string" || typeof content.input === "object");
974
+ }
975
+ function isToolResultPart(content) {
976
+ const c = content;
977
+ return !!c && c.type === "tool-result" && typeof c.toolName === "string" && typeof c.toolCallId === "string" && "output" in c;
978
+ }
979
+ function hasInputProperty(obj) {
980
+ return typeof obj === "object" && obj !== null && "input" in obj;
981
+ }
982
+
983
+ // src/protocols/json-mix-protocol.ts
984
+ function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
985
+ var _a;
986
+ try {
987
+ const parsedToolCall = parse(toolCallJson);
988
+ processedElements.push({
989
+ type: "tool-call",
990
+ toolCallId: (0, import_provider_utils2.generateId)(),
991
+ toolName: parsedToolCall.name,
992
+ input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
993
+ });
994
+ } catch (error) {
995
+ if (options == null ? void 0 : options.onError) {
996
+ options.onError(
997
+ "Could not process JSON tool call, keeping original text.",
998
+ { toolCall: fullMatch, error }
999
+ );
1000
+ }
1001
+ processedElements.push({ type: "text", text: fullMatch });
785
1002
  }
786
- return void 0;
787
1003
  }
788
- function getDebugLevel() {
789
- const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW || "off";
790
- const envLower = String(envVal).toLowerCase();
791
- if (envLower === "stream" || envLower === "parse" || envLower === "off") {
792
- return envLower;
1004
+ function addTextSegment(text, processedElements) {
1005
+ if (text.trim()) {
1006
+ processedElements.push({ type: "text", text });
793
1007
  }
794
- const boolEnv = normalizeBooleanString(envLower);
795
- if (boolEnv === true) return "stream";
796
- if (envLower === "2") return "parse";
797
- return "off";
798
1008
  }
799
- function color(code) {
800
- return (text) => `\x1B[${code}m${text}\x1B[0m`;
1009
+ function processMatchedToolCall(context) {
1010
+ const { match, text, currentIndex, processedElements, options } = context;
1011
+ const startIndex = match.index;
1012
+ const toolCallJson = match[1];
1013
+ if (startIndex > currentIndex) {
1014
+ const textSegment = text.substring(currentIndex, startIndex);
1015
+ addTextSegment(textSegment, processedElements);
1016
+ }
1017
+ if (toolCallJson) {
1018
+ processToolCallJson(toolCallJson, match[0], processedElements, options);
1019
+ }
1020
+ return startIndex + match[0].length;
801
1021
  }
802
- var cGray = color(90);
803
- var cYellow = color(33);
804
- var cCyan = color(36);
805
- var cBgBlue = color(44);
806
- var cBgGreen = color(42);
807
- var cInverse = color(7);
808
- var cUnderline = color(4);
809
- var cBold = color(1);
810
- function safeStringify(value) {
811
- try {
812
- return `
813
- ${typeof value === "string" ? value : JSON.stringify(value, null, 2)}`;
814
- } catch (e) {
815
- return String(value);
1022
+ function flushBuffer(state, controller, toolCallStart) {
1023
+ if (state.buffer.length === 0) {
1024
+ return;
816
1025
  }
1026
+ if (!state.currentTextId) {
1027
+ state.currentTextId = (0, import_provider_utils2.generateId)();
1028
+ controller.enqueue({ type: "text-start", id: state.currentTextId });
1029
+ state.hasEmittedTextStart = true;
1030
+ }
1031
+ const delta = state.isInsideToolCall ? `${toolCallStart}${state.buffer}` : state.buffer;
1032
+ controller.enqueue({
1033
+ type: "text-delta",
1034
+ id: state.currentTextId,
1035
+ delta
1036
+ });
1037
+ state.buffer = "";
817
1038
  }
818
- function logRawChunk(part) {
819
- console.log(cGray("[debug:mw:raw]"), cYellow(safeStringify(part)));
1039
+ function closeTextBlock(state, controller) {
1040
+ if (state.currentTextId && state.hasEmittedTextStart) {
1041
+ controller.enqueue({ type: "text-end", id: state.currentTextId });
1042
+ state.currentTextId = null;
1043
+ state.hasEmittedTextStart = false;
1044
+ }
820
1045
  }
821
- function logParsedChunk(part) {
822
- console.log(cGray("[debug:mw:out]"), cCyan(safeStringify(part)));
1046
+ function emitIncompleteToolCall(state, controller, toolCallStart) {
1047
+ if (!state.currentToolCallJson) {
1048
+ return;
1049
+ }
1050
+ const errorId = (0, import_provider_utils2.generateId)();
1051
+ controller.enqueue({ type: "text-start", id: errorId });
1052
+ controller.enqueue({
1053
+ type: "text-delta",
1054
+ id: errorId,
1055
+ delta: `${toolCallStart}${state.currentToolCallJson}`
1056
+ });
1057
+ controller.enqueue({ type: "text-end", id: errorId });
1058
+ state.currentToolCallJson = "";
823
1059
  }
824
- function logParsedSummary({
825
- toolCalls,
826
- originalText
827
- }) {
828
- if (originalText) {
829
- const style = (() => {
830
- const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW_STYLE || "bg";
831
- const normalized = String(envVal).trim().toLowerCase();
832
- if (normalized === "inverse" || normalized === "invert")
833
- return "inverse";
834
- if (normalized === "underline" || normalized === "ul")
835
- return "underline";
836
- if (normalized === "bold") return "bold";
837
- if (normalized === "bg" || normalized === "background")
838
- return "bg";
839
- const asBool = normalizeBooleanString(normalized);
840
- if (asBool === true) return "bg";
841
- return "bg";
842
- })();
843
- const highlight = style === "inverse" ? cInverse : style === "underline" ? cUnderline : style === "bold" ? cBold : style === "bg" ? cBgGreen : cYellow;
844
- const rendered = style === "bg" || style === "inverse" || style === "underline" || style === "bold" ? originalText.split(/\r?\n/).map((line) => line.length ? highlight(line) : line).join("\n") : highlight(originalText);
845
- console.log(cGray("[debug:mw:origin]"), `
846
- ${rendered}`);
1060
+ function handleFinishChunk(state, controller, toolCallStart, chunk) {
1061
+ if (state.buffer.length > 0) {
1062
+ flushBuffer(state, controller, toolCallStart);
847
1063
  }
848
- if (toolCalls.length > 0) {
849
- const styledSummary = safeStringify(toolCalls).split(/\r?\n/).map((line) => line.length ? cBgBlue(line) : line).join("\n");
850
- console.log(cGray("[debug:mw:summary]"), styledSummary);
1064
+ closeTextBlock(state, controller);
1065
+ emitIncompleteToolCall(state, controller, toolCallStart);
1066
+ controller.enqueue(chunk);
1067
+ }
1068
+ function publishText(text, state, controller) {
1069
+ if (state.isInsideToolCall) {
1070
+ closeTextBlock(state, controller);
1071
+ state.currentToolCallJson += text;
1072
+ } else if (text.length > 0) {
1073
+ if (!state.currentTextId) {
1074
+ state.currentTextId = (0, import_provider_utils2.generateId)();
1075
+ controller.enqueue({ type: "text-start", id: state.currentTextId });
1076
+ state.hasEmittedTextStart = true;
1077
+ }
1078
+ controller.enqueue({
1079
+ type: "text-delta",
1080
+ id: state.currentTextId,
1081
+ delta: text
1082
+ });
851
1083
  }
852
1084
  }
853
-
854
- // src/utils/on-error.ts
855
- function extractOnErrorOption(providerOptions) {
1085
+ function emitToolCall(context) {
856
1086
  var _a;
857
- if (providerOptions && typeof providerOptions === "object") {
858
- const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
859
- return onError ? { onError } : void 0;
1087
+ const { state, controller, toolCallStart, toolCallEnd, options } = context;
1088
+ try {
1089
+ const parsedToolCall = robust_json_exports.parse(state.currentToolCallJson);
1090
+ closeTextBlock(state, controller);
1091
+ controller.enqueue({
1092
+ type: "tool-call",
1093
+ toolCallId: (0, import_provider_utils2.generateId)(),
1094
+ toolName: parsedToolCall.name,
1095
+ input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
1096
+ });
1097
+ } catch (e) {
1098
+ const errorId = (0, import_provider_utils2.generateId)();
1099
+ controller.enqueue({ type: "text-start", id: errorId });
1100
+ controller.enqueue({
1101
+ type: "text-delta",
1102
+ id: errorId,
1103
+ delta: `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`
1104
+ });
1105
+ controller.enqueue({ type: "text-end", id: errorId });
1106
+ if (options == null ? void 0 : options.onError) {
1107
+ options.onError(
1108
+ "Could not process streaming JSON tool call; emitting original text.",
1109
+ {
1110
+ toolCall: `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`
1111
+ }
1112
+ );
1113
+ }
860
1114
  }
861
- return void 0;
862
1115
  }
863
-
864
- // src/utils/provider-options.ts
865
- var originalToolsSchema = {
866
- encode: encodeOriginalTools,
867
- decode: decodeOriginalTools
868
- };
869
- function encodeOriginalTools(tools) {
870
- return (tools == null ? void 0 : tools.map((t) => ({
871
- name: t.name,
872
- inputSchema: JSON.stringify(t.inputSchema)
873
- }))) || [];
874
- }
875
- function decodeOriginalTools(originalTools) {
876
- const tools = (originalTools == null ? void 0 : originalTools.map(
877
- (t) => ({
878
- name: t.name,
879
- inputSchema: JSON.parse(t.inputSchema)
880
- })
881
- )) || [];
882
- return tools;
883
- }
884
- function extractToolNamesFromOriginalTools(originalTools) {
885
- return (originalTools == null ? void 0 : originalTools.map((t) => t.name)) || [];
886
- }
887
- function isToolChoiceActive(params) {
888
- var _a, _b, _c;
889
- const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
890
- return !!(typeof params.providerOptions === "object" && params.providerOptions !== null && typeof ((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) === "object" && toolChoice && typeof toolChoice === "object" && (toolChoice.type === "tool" || toolChoice.type === "required"));
891
- }
892
-
893
- // src/utils/type-guards.ts
894
- function isToolCallContent(content) {
895
- return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
896
- (typeof content.input === "string" || typeof content.input === "object");
1116
+ function processTagMatch(context) {
1117
+ const { state } = context;
1118
+ if (state.isInsideToolCall) {
1119
+ emitToolCall(context);
1120
+ state.currentToolCallJson = "";
1121
+ state.isInsideToolCall = false;
1122
+ } else {
1123
+ state.currentToolCallJson = "";
1124
+ state.isInsideToolCall = true;
1125
+ }
897
1126
  }
898
- function isToolResultPart(content) {
899
- const c = content;
900
- return !!c && c.type === "tool-result" && typeof c.toolName === "string" && typeof c.toolCallId === "string" && "output" in c;
1127
+ function processBufferTags(context) {
1128
+ const { state, controller, toolCallStart, toolCallEnd } = context;
1129
+ let startIndex = getPotentialStartIndex(
1130
+ state.buffer,
1131
+ state.isInsideToolCall ? toolCallEnd : toolCallStart
1132
+ );
1133
+ while (startIndex != null) {
1134
+ const tag = state.isInsideToolCall ? toolCallEnd : toolCallStart;
1135
+ if (startIndex + tag.length > state.buffer.length) {
1136
+ break;
1137
+ }
1138
+ publishText(state.buffer.slice(0, startIndex), state, controller);
1139
+ state.buffer = state.buffer.slice(startIndex + tag.length);
1140
+ processTagMatch(context);
1141
+ startIndex = getPotentialStartIndex(
1142
+ state.buffer,
1143
+ state.isInsideToolCall ? toolCallEnd : toolCallStart
1144
+ );
1145
+ }
901
1146
  }
902
- function hasInputProperty(obj) {
903
- return typeof obj === "object" && obj !== null && "input" in obj;
1147
+ function handlePartialTag(state, controller, toolCallStart) {
1148
+ if (state.isInsideToolCall) {
1149
+ return;
1150
+ }
1151
+ const potentialIndex = getPotentialStartIndex(state.buffer, toolCallStart);
1152
+ if (potentialIndex != null && potentialIndex + toolCallStart.length > state.buffer.length) {
1153
+ publishText(state.buffer.slice(0, potentialIndex), state, controller);
1154
+ state.buffer = state.buffer.slice(potentialIndex);
1155
+ } else {
1156
+ publishText(state.buffer, state, controller);
1157
+ state.buffer = "";
1158
+ }
904
1159
  }
905
-
906
- // src/protocols/json-mix-protocol.ts
907
1160
  var jsonMixProtocol = ({
908
1161
  toolCallStart = "<tool_call>",
909
1162
  toolCallEnd = "</tool_call>",
@@ -937,7 +1190,6 @@ var jsonMixProtocol = ({
937
1190
  })}${toolResponseEnd}`;
938
1191
  },
939
1192
  parseGeneratedText({ text, options }) {
940
- var _a;
941
1193
  const startEsc = escapeRegExp(toolCallStart);
942
1194
  const endEsc = escapeRegExp(toolCallEnd);
943
1195
  const toolCallRegex = new RegExp(
@@ -946,185 +1198,50 @@ var jsonMixProtocol = ({
946
1198
  );
947
1199
  const processedElements = [];
948
1200
  let currentIndex = 0;
949
- let match;
950
- while ((match = toolCallRegex.exec(text)) !== null) {
951
- const startIndex = match.index;
952
- const toolCallJson = match[1];
953
- if (startIndex > currentIndex) {
954
- const textSegment = text.substring(currentIndex, startIndex);
955
- if (textSegment.trim()) {
956
- processedElements.push({ type: "text", text: textSegment });
957
- }
958
- }
959
- if (toolCallJson) {
960
- try {
961
- const parsedToolCall = robust_json_exports.parse(toolCallJson);
962
- processedElements.push({
963
- type: "tool-call",
964
- toolCallId: (0, import_provider_utils2.generateId)(),
965
- toolName: parsedToolCall.name,
966
- input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
967
- });
968
- } catch (error) {
969
- if (options == null ? void 0 : options.onError) {
970
- options.onError(
971
- "Could not process JSON tool call, keeping original text.",
972
- { toolCall: match[0], error }
973
- );
974
- }
975
- processedElements.push({ type: "text", text: match[0] });
976
- }
977
- }
978
- currentIndex = startIndex + match[0].length;
1201
+ let match = toolCallRegex.exec(text);
1202
+ while (match !== null) {
1203
+ currentIndex = processMatchedToolCall({
1204
+ match,
1205
+ text,
1206
+ currentIndex,
1207
+ processedElements,
1208
+ options
1209
+ });
1210
+ match = toolCallRegex.exec(text);
979
1211
  }
980
1212
  if (currentIndex < text.length) {
981
1213
  const remainingText = text.substring(currentIndex);
982
- if (remainingText.trim()) {
983
- processedElements.push({ type: "text", text: remainingText });
984
- }
1214
+ addTextSegment(remainingText, processedElements);
985
1215
  }
986
1216
  return processedElements;
987
1217
  },
988
1218
  createStreamParser({ tools: _tools, options } = { tools: [] }) {
989
- let isInsideToolCall = false;
990
- let buffer = "";
991
- let currentToolCallJson = "";
992
- let currentTextId = null;
993
- let hasEmittedTextStart = false;
1219
+ const state = {
1220
+ isInsideToolCall: false,
1221
+ buffer: "",
1222
+ currentToolCallJson: "",
1223
+ currentTextId: null,
1224
+ hasEmittedTextStart: false
1225
+ };
994
1226
  return new TransformStream({
995
1227
  transform(chunk, controller) {
996
- var _a;
997
1228
  if (chunk.type === "finish") {
998
- if (isInsideToolCall && buffer.length > 0) {
999
- if (!currentTextId) {
1000
- currentTextId = (0, import_provider_utils2.generateId)();
1001
- controller.enqueue({ type: "text-start", id: currentTextId });
1002
- hasEmittedTextStart = true;
1003
- }
1004
- controller.enqueue({
1005
- type: "text-delta",
1006
- id: currentTextId,
1007
- delta: `${toolCallStart}${buffer}`
1008
- });
1009
- buffer = "";
1010
- } else if (!isInsideToolCall && buffer.length > 0) {
1011
- if (!currentTextId) {
1012
- currentTextId = (0, import_provider_utils2.generateId)();
1013
- controller.enqueue({ type: "text-start", id: currentTextId });
1014
- hasEmittedTextStart = true;
1015
- }
1016
- controller.enqueue({
1017
- type: "text-delta",
1018
- id: currentTextId,
1019
- delta: buffer
1020
- });
1021
- buffer = "";
1022
- }
1023
- if (currentTextId && hasEmittedTextStart) {
1024
- controller.enqueue({ type: "text-end", id: currentTextId });
1025
- currentTextId = null;
1026
- hasEmittedTextStart = false;
1027
- }
1028
- if (currentToolCallJson) {
1029
- const errorId = (0, import_provider_utils2.generateId)();
1030
- controller.enqueue({ type: "text-start", id: errorId });
1031
- controller.enqueue({
1032
- type: "text-delta",
1033
- id: errorId,
1034
- delta: `${toolCallStart}${currentToolCallJson}`
1035
- });
1036
- controller.enqueue({ type: "text-end", id: errorId });
1037
- currentToolCallJson = "";
1038
- }
1039
- controller.enqueue(chunk);
1229
+ handleFinishChunk(state, controller, toolCallStart, chunk);
1040
1230
  return;
1041
1231
  }
1042
1232
  if (chunk.type !== "text-delta") {
1043
1233
  controller.enqueue(chunk);
1044
1234
  return;
1045
1235
  }
1046
- buffer += chunk.delta;
1047
- const publish = (text) => {
1048
- if (isInsideToolCall) {
1049
- if (currentTextId && hasEmittedTextStart) {
1050
- controller.enqueue({ type: "text-end", id: currentTextId });
1051
- currentTextId = null;
1052
- hasEmittedTextStart = false;
1053
- }
1054
- currentToolCallJson += text;
1055
- } else if (text.length > 0) {
1056
- if (!currentTextId) {
1057
- currentTextId = (0, import_provider_utils2.generateId)();
1058
- controller.enqueue({ type: "text-start", id: currentTextId });
1059
- hasEmittedTextStart = true;
1060
- }
1061
- controller.enqueue({
1062
- type: "text-delta",
1063
- id: currentTextId,
1064
- delta: text
1065
- });
1066
- }
1067
- };
1068
- let startIndex;
1069
- while ((startIndex = getPotentialStartIndex(
1070
- buffer,
1071
- isInsideToolCall ? toolCallEnd : toolCallStart
1072
- )) != null) {
1073
- const tag = isInsideToolCall ? toolCallEnd : toolCallStart;
1074
- if (startIndex + tag.length > buffer.length) {
1075
- break;
1076
- }
1077
- publish(buffer.slice(0, startIndex));
1078
- buffer = buffer.slice(startIndex + tag.length);
1079
- if (!isInsideToolCall) {
1080
- currentToolCallJson = "";
1081
- isInsideToolCall = true;
1082
- } else {
1083
- try {
1084
- const parsedToolCall = robust_json_exports.parse(currentToolCallJson);
1085
- if (currentTextId && hasEmittedTextStart) {
1086
- controller.enqueue({ type: "text-end", id: currentTextId });
1087
- currentTextId = null;
1088
- hasEmittedTextStart = false;
1089
- }
1090
- controller.enqueue({
1091
- type: "tool-call",
1092
- toolCallId: (0, import_provider_utils2.generateId)(),
1093
- toolName: parsedToolCall.name,
1094
- input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
1095
- });
1096
- } catch (e) {
1097
- const errorId = (0, import_provider_utils2.generateId)();
1098
- controller.enqueue({ type: "text-start", id: errorId });
1099
- controller.enqueue({
1100
- type: "text-delta",
1101
- id: errorId,
1102
- delta: `${toolCallStart}${currentToolCallJson}${toolCallEnd}`
1103
- });
1104
- controller.enqueue({ type: "text-end", id: errorId });
1105
- if (options == null ? void 0 : options.onError) {
1106
- options.onError(
1107
- "Could not process streaming JSON tool call; emitting original text.",
1108
- {
1109
- toolCall: `${toolCallStart}${currentToolCallJson}${toolCallEnd}`
1110
- }
1111
- );
1112
- }
1113
- }
1114
- currentToolCallJson = "";
1115
- isInsideToolCall = false;
1116
- }
1117
- }
1118
- if (!isInsideToolCall) {
1119
- const potentialIndex = getPotentialStartIndex(buffer, toolCallStart);
1120
- if (potentialIndex != null && potentialIndex + toolCallStart.length > buffer.length) {
1121
- publish(buffer.slice(0, potentialIndex));
1122
- buffer = buffer.slice(potentialIndex);
1123
- } else {
1124
- publish(buffer);
1125
- buffer = "";
1126
- }
1127
- }
1236
+ state.buffer += chunk.delta;
1237
+ processBufferTags({
1238
+ state,
1239
+ controller,
1240
+ toolCallStart,
1241
+ toolCallEnd,
1242
+ options
1243
+ });
1244
+ handlePartialTag(state, controller, toolCallStart);
1128
1245
  }
1129
1246
  });
1130
1247
  },
@@ -1133,9 +1250,10 @@ var jsonMixProtocol = ({
1133
1250
  const endEsc = escapeRegExp(toolCallEnd);
1134
1251
  const regex = new RegExp(`${startEsc}([\0-\uFFFF]*?)${endEsc}`, "gs");
1135
1252
  const segments = [];
1136
- let m;
1137
- while ((m = regex.exec(text)) != null) {
1253
+ let m = regex.exec(text);
1254
+ while (m != null) {
1138
1255
  segments.push(m[0]);
1256
+ m = regex.exec(text);
1139
1257
  }
1140
1258
  return segments;
1141
1259
  }
@@ -1143,13 +1261,292 @@ var jsonMixProtocol = ({
1143
1261
 
1144
1262
  // src/protocols/morph-xml-protocol.ts
1145
1263
  var import_provider_utils3 = require("@ai-sdk/provider-utils");
1146
- var RXML = __toESM(require("@ai-sdk-tool/rxml"), 1);
1264
+ var import_rxml = require("@ai-sdk-tool/rxml");
1265
+ var WHITESPACE_REGEX2 = /\s/;
1266
+ function processTextBeforeToolCall(text, currentIndex, toolCallStartIndex, processedElements) {
1267
+ if (toolCallStartIndex > currentIndex) {
1268
+ const textSegment = text.substring(currentIndex, toolCallStartIndex);
1269
+ if (textSegment.trim()) {
1270
+ processedElements.push({ type: "text", text: textSegment });
1271
+ }
1272
+ }
1273
+ return currentIndex;
1274
+ }
1275
+ function processToolCall(params) {
1276
+ var _a;
1277
+ const { toolCall, tools, options, text, processedElements } = params;
1278
+ try {
1279
+ const toolSchema = getToolSchema(tools, toolCall.toolName);
1280
+ const parsed = (0, import_rxml.parse)(toolCall.content, toolSchema, {
1281
+ onError: options == null ? void 0 : options.onError,
1282
+ // Disable HTML self-closing tag behavior to allow base, meta, link etc. as regular tags
1283
+ noChildNodes: []
1284
+ });
1285
+ processedElements.push({
1286
+ type: "tool-call",
1287
+ toolCallId: (0, import_provider_utils3.generateId)(),
1288
+ toolName: toolCall.toolName,
1289
+ input: JSON.stringify(parsed)
1290
+ });
1291
+ } catch (error) {
1292
+ const originalCallText = text.substring(
1293
+ toolCall.startIndex,
1294
+ toolCall.endIndex
1295
+ );
1296
+ const message = `Could not process XML tool call, keeping original text: ${originalCallText}`;
1297
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
1298
+ toolCall: originalCallText,
1299
+ toolName: toolCall.toolName,
1300
+ error
1301
+ });
1302
+ processedElements.push({ type: "text", text: originalCallText });
1303
+ }
1304
+ }
1305
+ function addRemainingText(text, currentIndex, processedElements) {
1306
+ if (currentIndex < text.length) {
1307
+ const remainingText = text.substring(currentIndex);
1308
+ if (remainingText.trim()) {
1309
+ processedElements.push({ type: "text", text: remainingText });
1310
+ }
1311
+ }
1312
+ }
1313
+ function handleStreamingToolCallEnd(params) {
1314
+ const { toolContent, currentToolCall, tools, options, ctrl, flushText } = params;
1315
+ try {
1316
+ const toolSchema = getToolSchema(tools, currentToolCall.name);
1317
+ const parsed = (0, import_rxml.parse)(toolContent, toolSchema, {
1318
+ onError: options == null ? void 0 : options.onError,
1319
+ noChildNodes: []
1320
+ });
1321
+ flushText(ctrl);
1322
+ ctrl.enqueue({
1323
+ type: "tool-call",
1324
+ toolCallId: (0, import_provider_utils3.generateId)(),
1325
+ toolName: currentToolCall.name,
1326
+ input: JSON.stringify(parsed)
1327
+ });
1328
+ } catch (error) {
1329
+ handleStreamingToolCallError({
1330
+ error,
1331
+ currentToolCall,
1332
+ toolContent,
1333
+ options,
1334
+ ctrl,
1335
+ flushText
1336
+ });
1337
+ }
1338
+ }
1339
+ function handleStreamingToolCallError(params) {
1340
+ var _a;
1341
+ const { error, currentToolCall, toolContent, options, ctrl, flushText } = params;
1342
+ const endTag = `</${currentToolCall.name}>`;
1343
+ const originalCallText = `<${currentToolCall.name}>${toolContent}${endTag}`;
1344
+ let message = "Could not process streaming XML tool call; emitting original text.";
1345
+ if (error instanceof import_rxml.RXMLDuplicateStringTagError) {
1346
+ message = `Duplicate string tags detected in streaming tool call '${currentToolCall.name}'; emitting original text.`;
1347
+ } else if (error instanceof import_rxml.RXMLCoercionError) {
1348
+ message = `Failed to coerce arguments for streaming tool call '${currentToolCall.name}'; emitting original text.`;
1349
+ } else if (error instanceof import_rxml.RXMLParseError) {
1350
+ message = `Failed to parse XML for streaming tool call '${currentToolCall.name}'; emitting original text.`;
1351
+ }
1352
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
1353
+ toolCall: originalCallText,
1354
+ toolName: currentToolCall.name,
1355
+ error
1356
+ });
1357
+ flushText(ctrl, originalCallText);
1358
+ }
1359
+ function findEarliestToolTag(buffer, toolNames) {
1360
+ let earliestStartTagIndex = -1;
1361
+ let earliestToolName = "";
1362
+ if (toolNames.length > 0) {
1363
+ for (const name of toolNames) {
1364
+ const startTag = `<${name}>`;
1365
+ const index = buffer.indexOf(startTag);
1366
+ if (index !== -1 && (earliestStartTagIndex === -1 || index < earliestStartTagIndex)) {
1367
+ earliestStartTagIndex = index;
1368
+ earliestToolName = name;
1369
+ }
1370
+ }
1371
+ }
1372
+ return { index: earliestStartTagIndex, name: earliestToolName };
1373
+ }
1374
+ function handleNoToolTagInBuffer(buffer, maxStartTagLen, controller, flushText) {
1375
+ const tail = Math.max(0, maxStartTagLen - 1);
1376
+ const safeLen = Math.max(0, buffer.length - tail);
1377
+ if (safeLen > 0) {
1378
+ const textToFlush = buffer.slice(0, safeLen);
1379
+ flushText(controller, textToFlush);
1380
+ return { buffer: buffer.slice(safeLen), shouldContinue: true };
1381
+ }
1382
+ return { buffer, shouldContinue: false };
1383
+ }
1384
+ function processToolCallInBuffer(params) {
1385
+ const {
1386
+ buffer,
1387
+ currentToolCall,
1388
+ tools,
1389
+ options,
1390
+ controller,
1391
+ flushText,
1392
+ setBuffer
1393
+ } = params;
1394
+ const endTag = `</${currentToolCall.name}>`;
1395
+ const endTagIndex = buffer.indexOf(endTag);
1396
+ if (endTagIndex !== -1) {
1397
+ const toolContent = buffer.substring(0, endTagIndex);
1398
+ const newBuffer = buffer.substring(endTagIndex + endTag.length);
1399
+ setBuffer("");
1400
+ handleStreamingToolCallEnd({
1401
+ toolContent,
1402
+ currentToolCall,
1403
+ tools,
1404
+ options,
1405
+ ctrl: controller,
1406
+ flushText
1407
+ });
1408
+ setBuffer(newBuffer);
1409
+ return { buffer: newBuffer, currentToolCall: null, shouldBreak: false };
1410
+ }
1411
+ return { buffer, currentToolCall, shouldBreak: true };
1412
+ }
1413
+ function processNoToolCallInBuffer(params) {
1414
+ const { buffer, toolNames, maxStartTagLen, controller, flushText } = params;
1415
+ const { index: earliestStartTagIndex, name: earliestToolName } = findEarliestToolTag(buffer, toolNames);
1416
+ if (earliestStartTagIndex !== -1) {
1417
+ const textBeforeTag = buffer.substring(0, earliestStartTagIndex);
1418
+ flushText(controller, textBeforeTag);
1419
+ const startTag = `<${earliestToolName}>`;
1420
+ const newBuffer = buffer.substring(earliestStartTagIndex + startTag.length);
1421
+ return {
1422
+ buffer: newBuffer,
1423
+ currentToolCall: { name: earliestToolName, content: "" },
1424
+ shouldBreak: false,
1425
+ shouldContinue: false
1426
+ };
1427
+ }
1428
+ const result = handleNoToolTagInBuffer(
1429
+ buffer,
1430
+ maxStartTagLen,
1431
+ controller,
1432
+ flushText
1433
+ );
1434
+ return {
1435
+ buffer: result.buffer,
1436
+ currentToolCall: null,
1437
+ shouldBreak: !result.shouldContinue,
1438
+ shouldContinue: result.shouldContinue
1439
+ };
1440
+ }
1441
+ function createFlushTextHandler(getBuffer, setBuffer, getCurrentTextId, setCurrentTextId) {
1442
+ return (controller, text) => {
1443
+ const content = text != null ? text : getBuffer();
1444
+ if (content) {
1445
+ const currentTextId2 = getCurrentTextId();
1446
+ if (!currentTextId2) {
1447
+ const newId = (0, import_provider_utils3.generateId)();
1448
+ setCurrentTextId(newId);
1449
+ controller.enqueue({ type: "text-start", id: newId });
1450
+ }
1451
+ controller.enqueue({
1452
+ type: "text-delta",
1453
+ id: getCurrentTextId(),
1454
+ delta: content
1455
+ });
1456
+ if (text === void 0) {
1457
+ setBuffer("");
1458
+ }
1459
+ }
1460
+ const currentTextId = getCurrentTextId();
1461
+ if (currentTextId && !text) {
1462
+ controller.enqueue({ type: "text-end", id: currentTextId });
1463
+ setCurrentTextId(null);
1464
+ }
1465
+ };
1466
+ }
1467
+ function processBufferWithToolCall(params, controller) {
1468
+ const {
1469
+ getBuffer,
1470
+ setBuffer,
1471
+ getCurrentToolCall,
1472
+ setCurrentToolCall,
1473
+ tools,
1474
+ options,
1475
+ flushText
1476
+ } = params;
1477
+ const currentToolCall = getCurrentToolCall();
1478
+ if (!currentToolCall) {
1479
+ return true;
1480
+ }
1481
+ const result = processToolCallInBuffer({
1482
+ buffer: getBuffer(),
1483
+ currentToolCall,
1484
+ tools,
1485
+ options,
1486
+ controller,
1487
+ flushText,
1488
+ setBuffer
1489
+ });
1490
+ setBuffer(result.buffer);
1491
+ setCurrentToolCall(result.currentToolCall);
1492
+ return result.shouldBreak;
1493
+ }
1494
+ function processBufferWithoutToolCall(params, controller) {
1495
+ const {
1496
+ getBuffer,
1497
+ setBuffer,
1498
+ setCurrentToolCall,
1499
+ toolNames,
1500
+ maxStartTagLen,
1501
+ flushText
1502
+ } = params;
1503
+ const result = processNoToolCallInBuffer({
1504
+ buffer: getBuffer(),
1505
+ toolNames,
1506
+ maxStartTagLen,
1507
+ controller,
1508
+ flushText
1509
+ });
1510
+ setBuffer(result.buffer);
1511
+ setCurrentToolCall(result.currentToolCall);
1512
+ return {
1513
+ shouldBreak: result.shouldBreak,
1514
+ shouldContinue: result.shouldContinue
1515
+ };
1516
+ }
1517
+ function processBufferLoop(params, controller) {
1518
+ while (true) {
1519
+ const currentToolCall = params.getCurrentToolCall();
1520
+ if (currentToolCall) {
1521
+ const shouldBreak = processBufferWithToolCall(params, controller);
1522
+ if (shouldBreak) {
1523
+ break;
1524
+ }
1525
+ } else {
1526
+ const { shouldBreak, shouldContinue } = processBufferWithoutToolCall(
1527
+ params,
1528
+ controller
1529
+ );
1530
+ if (shouldContinue) {
1531
+ continue;
1532
+ }
1533
+ if (shouldBreak) {
1534
+ break;
1535
+ }
1536
+ }
1537
+ }
1538
+ }
1539
+ function createProcessBufferHandler(params) {
1540
+ return (controller) => {
1541
+ processBufferLoop(params, controller);
1542
+ };
1543
+ }
1147
1544
  var morphXmlProtocol = () => ({
1148
1545
  formatTools({ tools, toolSystemPromptTemplate }) {
1149
1546
  const toolsForPrompt = (tools || []).map((tool) => ({
1150
1547
  name: tool.name,
1151
1548
  description: tool.description,
1152
- parameters: RXML.unwrapJsonSchema(tool.inputSchema)
1549
+ parameters: (0, import_rxml.unwrapJsonSchema)(tool.inputSchema)
1153
1550
  }));
1154
1551
  return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
1155
1552
  },
@@ -1165,19 +1562,18 @@ var morphXmlProtocol = () => ({
1165
1562
  } else {
1166
1563
  args = inputValue;
1167
1564
  }
1168
- return RXML.stringify(toolCall.toolName, args, {
1565
+ return (0, import_rxml.stringify)(toolCall.toolName, args, {
1169
1566
  suppressEmptyNode: false,
1170
1567
  format: false
1171
1568
  });
1172
1569
  },
1173
1570
  formatToolResponse(toolResult) {
1174
- return RXML.stringify("tool_response", {
1571
+ return (0, import_rxml.stringify)("tool_response", {
1175
1572
  tool_name: toolResult.toolName,
1176
1573
  result: toolResult.output
1177
1574
  });
1178
1575
  },
1179
1576
  parseGeneratedText({ text, tools, options }) {
1180
- var _a;
1181
1577
  const toolNames = tools.map((t) => t.name).filter((name) => name != null);
1182
1578
  if (toolNames.length === 0) {
1183
1579
  return [{ type: "text", text }];
@@ -1186,46 +1582,16 @@ var morphXmlProtocol = () => ({
1186
1582
  let currentIndex = 0;
1187
1583
  const toolCalls = findToolCalls(text, toolNames);
1188
1584
  for (const toolCall of toolCalls) {
1189
- if (toolCall.startIndex > currentIndex) {
1190
- const textSegment = text.substring(currentIndex, toolCall.startIndex);
1191
- if (textSegment.trim()) {
1192
- processedElements.push({ type: "text", text: textSegment });
1193
- }
1194
- }
1195
- try {
1196
- const toolSchema = getToolSchema(tools, toolCall.toolName);
1197
- const parsed = RXML.parse(toolCall.content, toolSchema, {
1198
- onError: options == null ? void 0 : options.onError,
1199
- // Disable HTML self-closing tag behavior to allow base, meta, link etc. as regular tags
1200
- noChildNodes: []
1201
- });
1202
- processedElements.push({
1203
- type: "tool-call",
1204
- toolCallId: (0, import_provider_utils3.generateId)(),
1205
- toolName: toolCall.toolName,
1206
- input: JSON.stringify(parsed)
1207
- });
1208
- } catch (error) {
1209
- const originalCallText = text.substring(
1210
- toolCall.startIndex,
1211
- toolCall.endIndex
1212
- );
1213
- const message = `Could not process XML tool call, keeping original text: ${originalCallText}`;
1214
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
1215
- toolCall: originalCallText,
1216
- toolName: toolCall.toolName,
1217
- error
1218
- });
1219
- processedElements.push({ type: "text", text: originalCallText });
1220
- }
1585
+ currentIndex = processTextBeforeToolCall(
1586
+ text,
1587
+ currentIndex,
1588
+ toolCall.startIndex,
1589
+ processedElements
1590
+ );
1591
+ processToolCall({ toolCall, tools, options, text, processedElements });
1221
1592
  currentIndex = toolCall.endIndex;
1222
1593
  }
1223
- if (currentIndex < text.length) {
1224
- const remainingText = text.substring(currentIndex);
1225
- if (remainingText.trim()) {
1226
- processedElements.push({ type: "text", text: remainingText });
1227
- }
1228
- }
1594
+ addRemainingText(text, currentIndex, processedElements);
1229
1595
  return processedElements;
1230
1596
  },
1231
1597
  createStreamParser({ tools, options }) {
@@ -1234,129 +1600,67 @@ var morphXmlProtocol = () => ({
1234
1600
  let buffer = "";
1235
1601
  let currentToolCall = null;
1236
1602
  let currentTextId = null;
1237
- const flushText = (controller, text) => {
1238
- const content = text != null ? text : buffer;
1239
- if (content) {
1240
- if (!currentTextId) {
1241
- currentTextId = (0, import_provider_utils3.generateId)();
1242
- controller.enqueue({ type: "text-start", id: currentTextId });
1243
- }
1244
- controller.enqueue({
1245
- type: "text-delta",
1246
- id: currentTextId,
1247
- delta: content
1248
- });
1249
- if (text === void 0) {
1250
- buffer = "";
1603
+ const flushText = createFlushTextHandler(
1604
+ () => buffer,
1605
+ (newBuffer) => {
1606
+ buffer = newBuffer;
1607
+ },
1608
+ () => currentTextId,
1609
+ (newId) => {
1610
+ currentTextId = newId;
1611
+ }
1612
+ );
1613
+ const processChunk = (chunk, controller) => {
1614
+ if (chunk.type !== "text-delta") {
1615
+ if (buffer) {
1616
+ flushText(controller);
1251
1617
  }
1618
+ controller.enqueue(chunk);
1619
+ return;
1252
1620
  }
1253
- if (currentTextId && !text) {
1621
+ buffer += chunk.delta;
1622
+ processBuffer(controller);
1623
+ };
1624
+ const processBuffer = createProcessBufferHandler({
1625
+ getBuffer: () => buffer,
1626
+ setBuffer: (newBuffer) => {
1627
+ buffer = newBuffer;
1628
+ },
1629
+ getCurrentToolCall: () => currentToolCall,
1630
+ setCurrentToolCall: (newToolCall) => {
1631
+ currentToolCall = newToolCall;
1632
+ },
1633
+ tools,
1634
+ options,
1635
+ toolNames,
1636
+ maxStartTagLen,
1637
+ flushText
1638
+ });
1639
+ const flushBuffer2 = (controller) => {
1640
+ if (currentToolCall) {
1641
+ const unfinishedCall = `<${currentToolCall.name}>${buffer}`;
1642
+ flushText(controller, unfinishedCall);
1643
+ } else if (buffer) {
1644
+ flushText(controller);
1645
+ }
1646
+ if (currentTextId) {
1254
1647
  controller.enqueue({ type: "text-end", id: currentTextId });
1255
- currentTextId = null;
1256
1648
  }
1257
1649
  };
1258
1650
  return new TransformStream({
1259
1651
  transform(chunk, controller) {
1260
- var _a;
1261
- if (chunk.type !== "text-delta") {
1262
- if (buffer) flushText(controller);
1263
- controller.enqueue(chunk);
1264
- return;
1265
- }
1266
- buffer += chunk.delta;
1267
- while (true) {
1268
- if (currentToolCall) {
1269
- const endTag = `</${currentToolCall.name}>`;
1270
- const endTagIndex = buffer.indexOf(endTag);
1271
- if (endTagIndex !== -1) {
1272
- const toolContent = buffer.substring(0, endTagIndex);
1273
- buffer = buffer.substring(endTagIndex + endTag.length);
1274
- try {
1275
- const toolSchema = getToolSchema(tools, currentToolCall.name);
1276
- const parsed = RXML.parse(toolContent, toolSchema, {
1277
- onError: options == null ? void 0 : options.onError,
1278
- // Disable HTML self-closing tag behavior to allow base, meta, link etc. as regular tags
1279
- noChildNodes: []
1280
- });
1281
- flushText(controller);
1282
- controller.enqueue({
1283
- type: "tool-call",
1284
- toolCallId: (0, import_provider_utils3.generateId)(),
1285
- toolName: currentToolCall.name,
1286
- input: JSON.stringify(parsed)
1287
- });
1288
- } catch (error) {
1289
- const originalCallText = `<${currentToolCall.name}>${toolContent}${endTag}`;
1290
- let message = "Could not process streaming XML tool call; emitting original text.";
1291
- if (error instanceof RXML.RXMLDuplicateStringTagError) {
1292
- message = `Duplicate string tags detected in streaming tool call '${currentToolCall.name}'; emitting original text.`;
1293
- } else if (error instanceof RXML.RXMLCoercionError) {
1294
- message = `Failed to coerce arguments for streaming tool call '${currentToolCall.name}'; emitting original text.`;
1295
- } else if (error instanceof RXML.RXMLParseError) {
1296
- message = `Failed to parse XML for streaming tool call '${currentToolCall.name}'; emitting original text.`;
1297
- }
1298
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
1299
- toolCall: originalCallText,
1300
- toolName: currentToolCall.name,
1301
- error
1302
- });
1303
- flushText(controller, originalCallText);
1304
- }
1305
- currentToolCall = null;
1306
- } else {
1307
- break;
1308
- }
1309
- } else {
1310
- let earliestStartTagIndex = -1;
1311
- let earliestToolName = "";
1312
- if (toolNames.length > 0) {
1313
- for (const name of toolNames) {
1314
- const startTag = `<${name}>`;
1315
- const index = buffer.indexOf(startTag);
1316
- if (index !== -1 && (earliestStartTagIndex === -1 || index < earliestStartTagIndex)) {
1317
- earliestStartTagIndex = index;
1318
- earliestToolName = name;
1319
- }
1320
- }
1321
- }
1322
- if (earliestStartTagIndex !== -1) {
1323
- const textBeforeTag = buffer.substring(0, earliestStartTagIndex);
1324
- flushText(controller, textBeforeTag);
1325
- const startTag = `<${earliestToolName}>`;
1326
- buffer = buffer.substring(
1327
- earliestStartTagIndex + startTag.length
1328
- );
1329
- currentToolCall = { name: earliestToolName, content: "" };
1330
- } else {
1331
- const tail = Math.max(0, maxStartTagLen - 1);
1332
- const safeLen = Math.max(0, buffer.length - tail);
1333
- if (safeLen > 0) {
1334
- const textToFlush = buffer.slice(0, safeLen);
1335
- flushText(controller, textToFlush);
1336
- buffer = buffer.slice(safeLen);
1337
- continue;
1338
- }
1339
- break;
1340
- }
1341
- }
1342
- }
1652
+ processChunk(chunk, controller);
1343
1653
  },
1344
1654
  flush(controller) {
1345
- if (currentToolCall) {
1346
- const unfinishedCall = `<${currentToolCall.name}>${buffer}`;
1347
- flushText(controller, unfinishedCall);
1348
- } else if (buffer) {
1349
- flushText(controller);
1350
- }
1351
- if (currentTextId) {
1352
- controller.enqueue({ type: "text-end", id: currentTextId });
1353
- }
1655
+ flushBuffer2(controller);
1354
1656
  }
1355
1657
  });
1356
1658
  },
1357
1659
  extractToolCallSegments({ text, tools }) {
1358
1660
  const toolNames = tools.map((t) => t.name).filter(Boolean);
1359
- if (toolNames.length === 0) return [];
1661
+ if (toolNames.length === 0) {
1662
+ return [];
1663
+ }
1360
1664
  return findToolCalls(text, toolNames).map((tc) => tc.segment);
1361
1665
  }
1362
1666
  });
@@ -1364,42 +1668,63 @@ function getToolSchema(tools, toolName) {
1364
1668
  var _a;
1365
1669
  return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
1366
1670
  }
1367
- function findToolCalls(text, toolNames) {
1671
+ function computeFullTagEnd(text, contentEnd, toolName) {
1672
+ let fullTagEnd = contentEnd + `</${toolName}>`.length;
1673
+ const closeHead = text.indexOf(`</${toolName}`, contentEnd);
1674
+ if (closeHead === contentEnd) {
1675
+ let p = closeHead + 2 + toolName.length;
1676
+ while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
1677
+ p += 1;
1678
+ }
1679
+ if (text[p] === ">") {
1680
+ fullTagEnd = p + 1;
1681
+ }
1682
+ }
1683
+ return fullTagEnd;
1684
+ }
1685
+ function extractToolCallInfo(text, tagStart, toolName, range) {
1368
1686
  var _a;
1687
+ const startTag = `<${toolName}>`;
1688
+ const contentStart = tagStart + startTag.length;
1689
+ const contentEnd = contentStart + (range.end - range.start);
1690
+ const fullTagEnd = computeFullTagEnd(text, contentEnd, toolName);
1691
+ const segment = text.substring(tagStart, fullTagEnd);
1692
+ const content = (_a = (0, import_rxml.extractRawInner)(segment, toolName)) != null ? _a : text.substring(contentStart, contentEnd);
1693
+ return {
1694
+ toolName,
1695
+ startIndex: tagStart,
1696
+ endIndex: fullTagEnd,
1697
+ content,
1698
+ segment
1699
+ };
1700
+ }
1701
+ function findToolCallsForName(text, toolName) {
1369
1702
  const toolCalls = [];
1370
- for (const toolName of toolNames) {
1371
- let searchIndex = 0;
1372
- while (searchIndex < text.length) {
1373
- const startTag = `<${toolName}>`;
1374
- const tagStart = text.indexOf(startTag, searchIndex);
1375
- if (tagStart === -1) break;
1376
- const remainingText = text.substring(tagStart);
1377
- const range = RXML.findFirstTopLevelRange(remainingText, toolName);
1378
- if (range) {
1379
- const contentStart = tagStart + startTag.length;
1380
- const contentEnd = contentStart + (range.end - range.start);
1381
- let fullTagEnd = contentEnd + `</${toolName}>`.length;
1382
- const closeHead = text.indexOf(`</${toolName}`, contentEnd);
1383
- if (closeHead === contentEnd) {
1384
- let p = closeHead + 2 + toolName.length;
1385
- while (p < text.length && /\s/.test(text[p])) p++;
1386
- if (text[p] === ">") fullTagEnd = p + 1;
1387
- }
1388
- const segment = text.substring(tagStart, fullTagEnd);
1389
- const content = (_a = RXML.extractRawInner(segment, toolName)) != null ? _a : text.substring(contentStart, contentEnd);
1390
- toolCalls.push({
1391
- toolName,
1392
- startIndex: tagStart,
1393
- endIndex: fullTagEnd,
1394
- content,
1395
- segment
1396
- });
1397
- searchIndex = fullTagEnd;
1398
- } else {
1399
- searchIndex = tagStart + startTag.length;
1400
- }
1703
+ const startTag = `<${toolName}>`;
1704
+ let searchIndex = 0;
1705
+ while (searchIndex < text.length) {
1706
+ const tagStart = text.indexOf(startTag, searchIndex);
1707
+ if (tagStart === -1) {
1708
+ break;
1709
+ }
1710
+ const remainingText = text.substring(tagStart);
1711
+ const range = (0, import_rxml.findFirstTopLevelRange)(remainingText, toolName);
1712
+ if (range) {
1713
+ const toolCallInfo = extractToolCallInfo(text, tagStart, toolName, range);
1714
+ toolCalls.push(toolCallInfo);
1715
+ searchIndex = toolCallInfo.endIndex;
1716
+ } else {
1717
+ searchIndex = tagStart + startTag.length;
1401
1718
  }
1402
1719
  }
1720
+ return toolCalls;
1721
+ }
1722
+ function findToolCalls(text, toolNames) {
1723
+ const toolCalls = [];
1724
+ for (const toolName of toolNames) {
1725
+ const calls = findToolCallsForName(text, toolName);
1726
+ toolCalls.push(...calls);
1727
+ }
1403
1728
  return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
1404
1729
  }
1405
1730
 
@@ -1410,94 +1735,93 @@ function isProtocolFactory(protocol) {
1410
1735
 
1411
1736
  // src/generate-handler.ts
1412
1737
  var import_provider_utils4 = require("@ai-sdk/provider-utils");
1413
- var RXML2 = __toESM(require("@ai-sdk-tool/rxml"), 1);
1414
- async function wrapGenerate({
1415
- protocol,
1416
- doGenerate,
1417
- params
1418
- }) {
1419
- var _a, _b, _c, _d, _e, _f, _g, _h;
1420
- if (isToolChoiceActive(params)) {
1421
- const result2 = await doGenerate();
1422
- let parsed2 = {};
1423
- const first = (_a = result2.content) == null ? void 0 : _a[0];
1424
- if (first && first.type === "text") {
1425
- const debugLevel2 = getDebugLevel();
1426
- if (debugLevel2 === "parse") {
1427
- logRawChunk(first.text);
1428
- }
1429
- try {
1430
- parsed2 = JSON.parse(first.text);
1431
- } catch (error) {
1432
- const options = extractOnErrorOption(params.providerOptions);
1433
- (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
1434
- options,
1435
- "Failed to parse toolChoice JSON from generated model output",
1436
- {
1437
- text: first.text,
1438
- error: error instanceof Error ? error.message : String(error)
1439
- }
1440
- );
1441
- parsed2 = {};
1442
- }
1443
- }
1444
- const toolCall = {
1445
- type: "tool-call",
1446
- toolCallId: (0, import_provider_utils4.generateId)(),
1447
- toolName: parsed2.name || "unknown",
1448
- input: JSON.stringify(parsed2.arguments || {})
1449
- };
1450
- const debugLevelToolChoice = getDebugLevel();
1451
- const originText = first && first.type === "text" ? first.text : "";
1452
- const dbg2 = (_d = (_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) == null ? void 0 : _d.debugSummary;
1453
- if (dbg2) {
1454
- dbg2.originalText = originText;
1455
- try {
1456
- dbg2.toolCalls = JSON.stringify([
1457
- { toolName: toolCall.toolName, input: toolCall.input }
1458
- ]);
1459
- } catch (e) {
1738
+ var import_rxml2 = require("@ai-sdk-tool/rxml");
1739
+ function parseToolChoiceJson(text, providerOptions) {
1740
+ var _a;
1741
+ try {
1742
+ return JSON.parse(text);
1743
+ } catch (error) {
1744
+ const options = extractOnErrorOption(providerOptions);
1745
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
1746
+ options,
1747
+ "Failed to parse toolChoice JSON from generated model output",
1748
+ {
1749
+ text,
1750
+ error: error instanceof Error ? error.message : String(error)
1460
1751
  }
1461
- } else if (debugLevelToolChoice === "parse") {
1462
- logParsedSummary({ toolCalls: [toolCall], originalText: originText });
1752
+ );
1753
+ return {};
1754
+ }
1755
+ }
1756
+ function logDebugSummary(debugSummary, toolCall, originText) {
1757
+ if (debugSummary) {
1758
+ debugSummary.originalText = originText;
1759
+ try {
1760
+ debugSummary.toolCalls = JSON.stringify([
1761
+ { toolName: toolCall.toolName, input: toolCall.input }
1762
+ ]);
1763
+ } catch (e) {
1463
1764
  }
1464
- return {
1465
- ...result2,
1466
- content: [toolCall]
1467
- };
1765
+ } else if (getDebugLevel() === "parse") {
1766
+ logParsedSummary({ toolCalls: [toolCall], originalText: originText });
1468
1767
  }
1469
- const tools = originalToolsSchema.decode(
1470
- (_f = (_e = params.providerOptions) == null ? void 0 : _e.toolCallMiddleware) == null ? void 0 : _f.originalTools
1471
- );
1768
+ }
1769
+ async function handleToolChoice(doGenerate, params) {
1770
+ var _a, _b, _c;
1472
1771
  const result = await doGenerate();
1473
- if (result.content.length === 0) {
1474
- return result;
1772
+ const first = (_a = result.content) == null ? void 0 : _a[0];
1773
+ let parsed = {};
1774
+ if (first && first.type === "text") {
1775
+ if (getDebugLevel() === "parse") {
1776
+ logRawChunk(first.text);
1777
+ }
1778
+ parsed = parseToolChoiceJson(first.text, params.providerOptions);
1475
1779
  }
1476
- const parsed = result.content.flatMap((contentItem) => {
1477
- var _a2;
1780
+ const toolCall = {
1781
+ type: "tool-call",
1782
+ toolCallId: (0, import_provider_utils4.generateId)(),
1783
+ toolName: parsed.name || "unknown",
1784
+ input: JSON.stringify(parsed.arguments || {})
1785
+ };
1786
+ const originText = first && first.type === "text" ? first.text : "";
1787
+ const debugSummary = (_c = (_b = params.providerOptions) == null ? void 0 : _b.toolCallMiddleware) == null ? void 0 : _c.debugSummary;
1788
+ logDebugSummary(debugSummary, toolCall, originText);
1789
+ return {
1790
+ ...result,
1791
+ content: [toolCall]
1792
+ };
1793
+ }
1794
+ function parseContent(content, protocol, tools, providerOptions) {
1795
+ const parsed = content.flatMap((contentItem) => {
1478
1796
  if (contentItem.type !== "text") {
1479
1797
  return [contentItem];
1480
1798
  }
1481
- const debugLevel2 = getDebugLevel();
1482
- if (debugLevel2 === "stream") {
1799
+ if (getDebugLevel() === "stream") {
1483
1800
  logRawChunk(contentItem.text);
1484
1801
  }
1485
1802
  return protocol.parseGeneratedText({
1486
1803
  text: contentItem.text,
1487
1804
  tools,
1488
1805
  options: {
1489
- ...extractOnErrorOption(params.providerOptions),
1490
- ...(_a2 = params.providerOptions) == null ? void 0 : _a2.toolCallMiddleware
1806
+ ...extractOnErrorOption(providerOptions),
1807
+ ...providerOptions == null ? void 0 : providerOptions.toolCallMiddleware
1491
1808
  }
1492
1809
  });
1493
1810
  });
1494
- const newContent = parsed.map(
1811
+ return parsed.map(
1495
1812
  (part) => fixToolCallWithSchema(part, tools)
1496
1813
  );
1497
- const debugLevel = getDebugLevel();
1498
- if (debugLevel === "stream") {
1499
- newContent.forEach((part) => logParsedChunk(part));
1814
+ }
1815
+ function logParsedContent(content) {
1816
+ if (getDebugLevel() === "stream") {
1817
+ for (const part of content) {
1818
+ logParsedChunk(part);
1819
+ }
1500
1820
  }
1821
+ }
1822
+ function computeDebugSummary(options) {
1823
+ var _a;
1824
+ const { result, newContent, protocol, tools, providerOptions } = options;
1501
1825
  const allText = result.content.filter(
1502
1826
  (c) => c.type === "text"
1503
1827
  ).map((c) => c.text).join("\n\n");
@@ -1506,7 +1830,7 @@ async function wrapGenerate({
1506
1830
  const toolCalls = newContent.filter(
1507
1831
  (p) => p.type === "tool-call"
1508
1832
  );
1509
- const dbg = (_h = (_g = params.providerOptions) == null ? void 0 : _g.toolCallMiddleware) == null ? void 0 : _h.debugSummary;
1833
+ const dbg = (_a = providerOptions == null ? void 0 : providerOptions.toolCallMiddleware) == null ? void 0 : _a.debugSummary;
1510
1834
  if (dbg) {
1511
1835
  dbg.originalText = originalText;
1512
1836
  try {
@@ -1518,9 +1842,40 @@ async function wrapGenerate({
1518
1842
  );
1519
1843
  } catch (e) {
1520
1844
  }
1521
- } else if (debugLevel === "parse") {
1845
+ } else if (getDebugLevel() === "parse") {
1522
1846
  logParsedSummary({ toolCalls, originalText });
1523
1847
  }
1848
+ }
1849
+ async function wrapGenerate({
1850
+ protocol,
1851
+ doGenerate,
1852
+ params
1853
+ }) {
1854
+ var _a, _b;
1855
+ if (isToolChoiceActive(params)) {
1856
+ return handleToolChoice(doGenerate, params);
1857
+ }
1858
+ const tools = originalToolsSchema.decode(
1859
+ (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools
1860
+ );
1861
+ const result = await doGenerate();
1862
+ if (result.content.length === 0) {
1863
+ return result;
1864
+ }
1865
+ const newContent = parseContent(
1866
+ result.content,
1867
+ protocol,
1868
+ tools,
1869
+ params.providerOptions
1870
+ );
1871
+ logParsedContent(newContent);
1872
+ computeDebugSummary({
1873
+ result,
1874
+ newContent,
1875
+ protocol,
1876
+ tools,
1877
+ providerOptions: params.providerOptions
1878
+ });
1524
1879
  return {
1525
1880
  ...result,
1526
1881
  content: newContent
@@ -1528,7 +1883,9 @@ async function wrapGenerate({
1528
1883
  }
1529
1884
  function fixToolCallWithSchema(part, tools) {
1530
1885
  var _a;
1531
- if (part.type !== "tool-call") return part;
1886
+ if (part.type !== "tool-call") {
1887
+ return part;
1888
+ }
1532
1889
  const tc = part;
1533
1890
  let args = {};
1534
1891
  if (typeof tc.input === "string") {
@@ -1541,7 +1898,7 @@ function fixToolCallWithSchema(part, tools) {
1541
1898
  args = tc.input;
1542
1899
  }
1543
1900
  const schema = (_a = tools.find((t) => t.name === tc.toolName)) == null ? void 0 : _a.inputSchema;
1544
- const coerced = RXML2.coerceBySchema(args, schema);
1901
+ const coerced = (0, import_rxml2.coerceBySchema)(args, schema);
1545
1902
  return {
1546
1903
  ...part,
1547
1904
  input: JSON.stringify(coerced != null ? coerced : {})
@@ -1550,6 +1907,69 @@ function fixToolCallWithSchema(part, tools) {
1550
1907
 
1551
1908
  // src/stream-handler.ts
1552
1909
  var import_provider_utils5 = require("@ai-sdk/provider-utils");
1910
+ function extractToolCallSegments(protocol, fullRawText, tools) {
1911
+ const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({
1912
+ text: fullRawText,
1913
+ tools
1914
+ }) : [];
1915
+ return segments.join("\n\n");
1916
+ }
1917
+ function serializeToolCalls(parsedToolCalls) {
1918
+ const toolCallParts = parsedToolCalls.filter(
1919
+ (p) => p.type === "tool-call"
1920
+ );
1921
+ return JSON.stringify(
1922
+ toolCallParts.map((tc) => ({
1923
+ toolName: tc.toolName,
1924
+ input: tc.input
1925
+ }))
1926
+ );
1927
+ }
1928
+ function handleDebugSummary(parsedToolCalls, origin, params) {
1929
+ var _a, _b;
1930
+ const dbg = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.debugSummary;
1931
+ if (dbg) {
1932
+ dbg.originalText = origin;
1933
+ try {
1934
+ dbg.toolCalls = serializeToolCalls(parsedToolCalls);
1935
+ } catch (e) {
1936
+ }
1937
+ } else {
1938
+ logParsedSummary({
1939
+ toolCalls: parsedToolCalls,
1940
+ originalText: origin
1941
+ });
1942
+ }
1943
+ }
1944
+ function createDebugSummaryTransform({
1945
+ protocol,
1946
+ fullRawText,
1947
+ tools,
1948
+ params
1949
+ }) {
1950
+ return new TransformStream({
1951
+ transform: /* @__PURE__ */ (() => {
1952
+ const parsedToolCalls = [];
1953
+ return (part, controller) => {
1954
+ if (part.type === "tool-call") {
1955
+ parsedToolCalls.push(part);
1956
+ }
1957
+ if (part.type === "finish") {
1958
+ try {
1959
+ const origin = extractToolCallSegments(
1960
+ protocol,
1961
+ fullRawText,
1962
+ tools
1963
+ );
1964
+ handleDebugSummary(parsedToolCalls, origin, params);
1965
+ } catch (e) {
1966
+ }
1967
+ }
1968
+ controller.enqueue(part);
1969
+ };
1970
+ })()
1971
+ });
1972
+ }
1553
1973
  async function wrapStream({
1554
1974
  protocol,
1555
1975
  doStream,
@@ -1636,48 +2056,11 @@ async function wrapStream({
1636
2056
  })
1637
2057
  );
1638
2058
  const withSummary = parsed.pipeThrough(
1639
- new TransformStream({
1640
- transform: /* @__PURE__ */ (() => {
1641
- const parsedToolCalls = [];
1642
- return (part, controller) => {
1643
- var _a2, _b2;
1644
- if (part.type === "tool-call") {
1645
- parsedToolCalls.push(part);
1646
- }
1647
- if (part.type === "finish") {
1648
- try {
1649
- const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({
1650
- text: fullRawText,
1651
- tools
1652
- }) : [];
1653
- const origin = segments.join("\n\n");
1654
- const dbg = (_b2 = (_a2 = params.providerOptions) == null ? void 0 : _a2.toolCallMiddleware) == null ? void 0 : _b2.debugSummary;
1655
- if (dbg) {
1656
- dbg.originalText = origin;
1657
- try {
1658
- const toolCallParts = parsedToolCalls.filter(
1659
- (p) => p.type === "tool-call"
1660
- );
1661
- dbg.toolCalls = JSON.stringify(
1662
- toolCallParts.map((tc) => ({
1663
- toolName: tc.toolName,
1664
- input: tc.input
1665
- }))
1666
- );
1667
- } catch (e) {
1668
- }
1669
- } else {
1670
- logParsedSummary({
1671
- toolCalls: parsedToolCalls,
1672
- originalText: origin
1673
- });
1674
- }
1675
- } catch (e) {
1676
- }
1677
- }
1678
- controller.enqueue(part);
1679
- };
1680
- })()
2059
+ createDebugSummaryTransform({
2060
+ protocol,
2061
+ fullRawText,
2062
+ tools,
2063
+ params
1681
2064
  })
1682
2065
  );
1683
2066
  return {
@@ -1689,7 +2072,7 @@ async function toolChoiceStream({
1689
2072
  doGenerate,
1690
2073
  options
1691
2074
  }) {
1692
- var _a, _b;
2075
+ var _a, _b, _c;
1693
2076
  const result = await doGenerate();
1694
2077
  let toolJson = {};
1695
2078
  if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
@@ -1731,7 +2114,7 @@ async function toolChoiceStream({
1731
2114
  }
1732
2115
  });
1733
2116
  const debugLevel = getDebugLevel();
1734
- const firstText = (result == null ? void 0 : result.content) && result.content[0] && result.content[0].type === "text" && result.content[0].text || "";
2117
+ const firstText = ((_c = result == null ? void 0 : result.content) == null ? void 0 : _c[0]) && result.content[0].type === "text" && result.content[0].text || "";
1735
2118
  const streamWithSummary = debugLevel === "parse" ? stream.pipeThrough(
1736
2119
  new TransformStream({
1737
2120
  transform(part, controller) {
@@ -1756,39 +2139,29 @@ async function toolChoiceStream({
1756
2139
  }
1757
2140
 
1758
2141
  // src/transform-handler.ts
1759
- async function transformParams({
1760
- params,
1761
- protocol,
1762
- toolSystemPromptTemplate
1763
- }) {
1764
- var _a, _b, _c, _d, _e, _f, _g, _h;
1765
- const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
1766
- const functionTools = ((_a = params.tools) != null ? _a : []).filter(
1767
- (t) => t.type === "function"
1768
- );
1769
- const systemPrompt = resolvedProtocol.formatTools({
1770
- tools: functionTools,
1771
- toolSystemPromptTemplate
1772
- });
1773
- const processedPrompt = convertToolPrompt(
1774
- (_b = params.prompt) != null ? _b : [],
1775
- resolvedProtocol,
1776
- extractOnErrorOption(params.providerOptions)
1777
- );
1778
- const finalPrompt = ((_c = processedPrompt[0]) == null ? void 0 : _c.role) === "system" ? [
1779
- {
1780
- role: "system",
1781
- content: systemPrompt + "\n\n" + processedPrompt[0].content
1782
- },
1783
- ...processedPrompt.slice(1)
1784
- ] : [
2142
+ function buildFinalPrompt(systemPrompt, processedPrompt) {
2143
+ var _a;
2144
+ if (((_a = processedPrompt[0]) == null ? void 0 : _a.role) === "system") {
2145
+ return [
2146
+ {
2147
+ role: "system",
2148
+ content: `${systemPrompt}
2149
+
2150
+ ${processedPrompt[0].content}`
2151
+ },
2152
+ ...processedPrompt.slice(1)
2153
+ ];
2154
+ }
2155
+ return [
1785
2156
  {
1786
2157
  role: "system",
1787
2158
  content: systemPrompt
1788
2159
  },
1789
2160
  ...processedPrompt
1790
2161
  ];
1791
- const baseReturnParams = {
2162
+ }
2163
+ function buildBaseReturnParams(params, finalPrompt, functionTools) {
2164
+ return {
1792
2165
  ...params,
1793
2166
  prompt: finalPrompt,
1794
2167
  tools: [],
@@ -1797,184 +2170,234 @@ async function transformParams({
1797
2170
  ...params.providerOptions || {},
1798
2171
  toolCallMiddleware: {
1799
2172
  ...params.providerOptions && typeof params.providerOptions === "object" && params.providerOptions.toolCallMiddleware || {},
1800
- // INTERNAL: used by the middleware so downstream parsers can access
1801
- // the original tool schemas even if providers strip `params.tools`.
1802
- // Not a stable public API.
1803
2173
  originalTools: originalToolsSchema.encode(functionTools)
1804
2174
  }
1805
2175
  }
1806
2176
  };
1807
- if (((_d = params.toolChoice) == null ? void 0 : _d.type) === "none") {
2177
+ }
2178
+ function findProviderDefinedTool(tools, selectedToolName) {
2179
+ return tools.find((t) => {
2180
+ if (t.type === "function") {
2181
+ return false;
2182
+ }
2183
+ const anyTool = t;
2184
+ return anyTool.id === selectedToolName || anyTool.name === selectedToolName;
2185
+ });
2186
+ }
2187
+ function handleToolChoiceTool(params, baseReturnParams) {
2188
+ var _a, _b, _c;
2189
+ const selectedToolName = (_a = params.toolChoice) == null ? void 0 : _a.toolName;
2190
+ if (!selectedToolName) {
2191
+ throw new Error("Tool name is required for 'tool' toolChoice type.");
2192
+ }
2193
+ const providerDefinedMatch = findProviderDefinedTool(
2194
+ (_b = params.tools) != null ? _b : [],
2195
+ selectedToolName
2196
+ );
2197
+ if (providerDefinedMatch) {
1808
2198
  throw new Error(
1809
- "The 'none' toolChoice type is not supported by this middleware. Please use 'auto', 'required', or specify a tool name."
2199
+ "Provider-defined tools are not supported by this middleware. Please use custom tools."
1810
2200
  );
1811
2201
  }
1812
- if (((_e = params.toolChoice) == null ? void 0 : _e.type) === "tool") {
1813
- const selectedToolName = params.toolChoice.toolName;
1814
- const providerDefinedMatch = ((_f = params.tools) != null ? _f : []).find((t) => {
1815
- if (t.type === "function") return false;
1816
- const anyTool = t;
1817
- return anyTool.id === selectedToolName || anyTool.name === selectedToolName;
1818
- });
1819
- if (providerDefinedMatch) {
1820
- throw new Error(
1821
- "Provider-defined tools are not supported by this middleware. Please use custom tools."
1822
- );
1823
- }
1824
- const selectedTool = ((_g = params.tools) != null ? _g : []).find(
1825
- (t) => t.type === "function" && t.name === selectedToolName
2202
+ const selectedTool = ((_c = params.tools) != null ? _c : []).find(
2203
+ (t) => t.type === "function" && t.name === selectedToolName
2204
+ );
2205
+ if (!selectedTool) {
2206
+ throw new Error(
2207
+ `Tool with name '${selectedToolName}' not found in params.tools.`
1826
2208
  );
1827
- if (!selectedTool) {
1828
- throw new Error(
1829
- `Tool with name '${selectedToolName}' not found in params.tools.`
1830
- );
1831
- }
1832
- return {
1833
- ...baseReturnParams,
1834
- responseFormat: {
1835
- type: "json",
1836
- schema: {
1837
- type: "object",
1838
- properties: {
1839
- name: {
1840
- const: selectedTool.name
1841
- },
1842
- arguments: selectedTool.inputSchema
2209
+ }
2210
+ return {
2211
+ ...baseReturnParams,
2212
+ responseFormat: {
2213
+ type: "json",
2214
+ schema: {
2215
+ type: "object",
2216
+ properties: {
2217
+ name: {
2218
+ const: selectedTool.name
1843
2219
  },
1844
- required: ["name", "arguments"]
2220
+ arguments: selectedTool.inputSchema
1845
2221
  },
1846
- name: selectedTool.name,
1847
- description: typeof selectedTool.description === "string" ? selectedTool.description : void 0
2222
+ required: ["name", "arguments"]
1848
2223
  },
1849
- providerOptions: {
1850
- ...baseReturnParams.providerOptions || {},
1851
- toolCallMiddleware: {
1852
- ...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
1853
- // INTERNAL: used by the middleware to activate the tool-choice
1854
- // fast-path in handlers. Not a stable public API.
1855
- toolChoice: params.toolChoice
1856
- }
2224
+ name: selectedTool.name,
2225
+ description: typeof selectedTool.description === "string" ? selectedTool.description : void 0
2226
+ },
2227
+ providerOptions: {
2228
+ ...baseReturnParams.providerOptions || {},
2229
+ toolCallMiddleware: {
2230
+ ...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
2231
+ ...params.toolChoice ? { toolChoice: params.toolChoice } : {}
1857
2232
  }
1858
- };
2233
+ }
2234
+ };
2235
+ }
2236
+ function handleToolChoiceRequired(params, baseReturnParams, functionTools) {
2237
+ if (!params.tools || params.tools.length === 0) {
2238
+ throw new Error(
2239
+ "Tool choice type 'required' is set, but no tools are provided in params.tools."
2240
+ );
1859
2241
  }
1860
- if (((_h = params.toolChoice) == null ? void 0 : _h.type) === "required") {
1861
- if (!params.tools || params.tools.length === 0) {
1862
- throw new Error(
1863
- "Tool choice type 'required' is set, but no tools are provided in params.tools."
2242
+ return {
2243
+ ...baseReturnParams,
2244
+ responseFormat: {
2245
+ type: "json",
2246
+ schema: createDynamicIfThenElseSchema(functionTools)
2247
+ },
2248
+ providerOptions: {
2249
+ ...baseReturnParams.providerOptions || {},
2250
+ toolCallMiddleware: {
2251
+ ...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
2252
+ toolChoice: { type: "required" }
2253
+ }
2254
+ }
2255
+ };
2256
+ }
2257
+ function transformParams({
2258
+ params,
2259
+ protocol,
2260
+ toolSystemPromptTemplate
2261
+ }) {
2262
+ var _a, _b, _c, _d, _e;
2263
+ const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
2264
+ const functionTools = ((_a = params.tools) != null ? _a : []).filter(
2265
+ (t) => t.type === "function"
2266
+ );
2267
+ const systemPrompt = resolvedProtocol.formatTools({
2268
+ tools: functionTools,
2269
+ toolSystemPromptTemplate
2270
+ });
2271
+ const processedPrompt = convertToolPrompt(
2272
+ (_b = params.prompt) != null ? _b : [],
2273
+ resolvedProtocol,
2274
+ extractOnErrorOption(params.providerOptions)
2275
+ );
2276
+ const finalPrompt = buildFinalPrompt(systemPrompt, processedPrompt);
2277
+ const baseReturnParams = buildBaseReturnParams(
2278
+ params,
2279
+ finalPrompt,
2280
+ functionTools
2281
+ );
2282
+ if (((_c = params.toolChoice) == null ? void 0 : _c.type) === "none") {
2283
+ throw new Error(
2284
+ "The 'none' toolChoice type is not supported by this middleware. Please use 'auto', 'required', or specify a tool name."
2285
+ );
2286
+ }
2287
+ if (((_d = params.toolChoice) == null ? void 0 : _d.type) === "tool") {
2288
+ return handleToolChoiceTool(params, baseReturnParams);
2289
+ }
2290
+ if (((_e = params.toolChoice) == null ? void 0 : _e.type) === "required") {
2291
+ return handleToolChoiceRequired(params, baseReturnParams, functionTools);
2292
+ }
2293
+ return baseReturnParams;
2294
+ }
2295
+ function processAssistantContent(content, resolvedProtocol, providerOptions) {
2296
+ var _a;
2297
+ const newContent = [];
2298
+ for (const item of content) {
2299
+ if (isToolCallContent(item)) {
2300
+ newContent.push({
2301
+ type: "text",
2302
+ text: resolvedProtocol.formatToolCall(item)
2303
+ });
2304
+ } else if (item.type === "text") {
2305
+ newContent.push(item);
2306
+ } else if (item.type === "reasoning") {
2307
+ newContent.push(item);
2308
+ } else {
2309
+ const options = extractOnErrorOption(providerOptions);
2310
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
2311
+ options,
2312
+ "tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
2313
+ { content: item }
1864
2314
  );
2315
+ newContent.push({
2316
+ type: "text",
2317
+ text: JSON.stringify(item)
2318
+ });
1865
2319
  }
1866
- return {
1867
- ...baseReturnParams,
1868
- responseFormat: {
1869
- type: "json",
1870
- schema: createDynamicIfThenElseSchema(functionTools)
1871
- },
1872
- providerOptions: {
1873
- ...baseReturnParams.providerOptions || {},
1874
- toolCallMiddleware: {
1875
- ...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
1876
- // INTERNAL: used by the middleware to activate the tool-choice
1877
- // fast-path in handlers. Not a stable public API.
1878
- toolChoice: { type: "required" }
1879
- }
2320
+ }
2321
+ const onlyText = newContent.every((c) => c.type === "text");
2322
+ return onlyText ? [
2323
+ {
2324
+ type: "text",
2325
+ text: newContent.map((c) => c.text).join("\n")
2326
+ }
2327
+ ] : newContent;
2328
+ }
2329
+ function processToolMessage(content, resolvedProtocol) {
2330
+ return {
2331
+ role: "user",
2332
+ content: [
2333
+ {
2334
+ type: "text",
2335
+ text: content.map((toolResult) => resolvedProtocol.formatToolResponse(toolResult)).join("\n")
1880
2336
  }
2337
+ ]
2338
+ };
2339
+ }
2340
+ function processMessage(message, resolvedProtocol, providerOptions) {
2341
+ if (message.role === "assistant") {
2342
+ const condensedContent = processAssistantContent(
2343
+ message.content,
2344
+ resolvedProtocol,
2345
+ providerOptions
2346
+ );
2347
+ return {
2348
+ role: "assistant",
2349
+ content: condensedContent
1881
2350
  };
1882
2351
  }
1883
- return baseReturnParams;
2352
+ if (message.role === "tool") {
2353
+ return processToolMessage(message.content, resolvedProtocol);
2354
+ }
2355
+ return message;
1884
2356
  }
1885
- function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
1886
- const processedPrompt = prompt.map((message) => {
1887
- var _a;
1888
- if (message.role === "assistant") {
1889
- const newContent = [];
1890
- for (const content of message.content) {
1891
- if (isToolCallContent(content)) {
1892
- newContent.push({
1893
- type: "text",
1894
- text: resolvedProtocol.formatToolCall(content)
1895
- });
1896
- } else if (content.type === "text") {
1897
- newContent.push(content);
1898
- } else if (content.type === "reasoning") {
1899
- newContent.push(content);
1900
- } else {
1901
- const options = extractOnErrorOption(providerOptions);
1902
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
1903
- options,
1904
- "tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
1905
- { content }
1906
- );
1907
- newContent.push({
1908
- type: "text",
1909
- text: JSON.stringify(content)
1910
- });
1911
- }
2357
+ function isAllTextContent(content) {
2358
+ if (!Array.isArray(content)) {
2359
+ return false;
2360
+ }
2361
+ return content.every(
2362
+ (c) => (c == null ? void 0 : c.type) === "text"
2363
+ );
2364
+ }
2365
+ function joinTextContent(content) {
2366
+ return content.map((c) => c.text).join("\n");
2367
+ }
2368
+ function createCondensedMessage(role, joinedText) {
2369
+ if (role === "system") {
2370
+ return {
2371
+ role: "system",
2372
+ content: joinedText
2373
+ };
2374
+ }
2375
+ return {
2376
+ role,
2377
+ content: [
2378
+ {
2379
+ type: "text",
2380
+ text: joinedText
1912
2381
  }
1913
- const onlyText = newContent.every((c) => c.type === "text");
1914
- const condensedAssistant = onlyText ? [
1915
- {
1916
- type: "text",
1917
- text: newContent.map((c) => c.text).join("\n")
1918
- }
1919
- ] : newContent;
1920
- return { role: "assistant", content: condensedAssistant };
1921
- }
1922
- if (message.role === "tool") {
1923
- return {
1924
- role: "user",
1925
- // Map tool results to text response blocks, then condense into a single text block
1926
- content: [
1927
- {
1928
- type: "text",
1929
- text: message.content.map(
1930
- (toolResult) => isToolResultPart(toolResult) ? resolvedProtocol.formatToolResponse(toolResult) : resolvedProtocol.formatToolResponse(
1931
- toolResult
1932
- )
1933
- ).join("\n")
1934
- }
1935
- ]
1936
- };
1937
- }
1938
- return message;
1939
- });
1940
- for (let i = 0; i < processedPrompt.length; i++) {
2382
+ ]
2383
+ };
2384
+ }
2385
+ function condenseTextContent(processedPrompt) {
2386
+ for (let i = 0; i < processedPrompt.length; i += 1) {
1941
2387
  const msg = processedPrompt[i];
1942
- if (Array.isArray(msg.content)) {
1943
- const allText = msg.content.every(
1944
- (c) => (c == null ? void 0 : c.type) === "text"
1945
- );
1946
- if (allText && msg.content.length > 1) {
1947
- const joinedText = msg.content.map((c) => c.text).join("\n");
1948
- if (msg.role === "system") {
1949
- processedPrompt[i] = {
1950
- role: "system",
1951
- content: joinedText
1952
- };
1953
- } else if (msg.role === "assistant") {
1954
- processedPrompt[i] = {
1955
- role: "assistant",
1956
- content: [
1957
- {
1958
- type: "text",
1959
- text: joinedText
1960
- }
1961
- ]
1962
- };
1963
- } else {
1964
- processedPrompt[i] = {
1965
- role: "user",
1966
- content: [
1967
- {
1968
- type: "text",
1969
- text: joinedText
1970
- }
1971
- ]
1972
- };
1973
- }
1974
- }
2388
+ if (!Array.isArray(msg.content)) {
2389
+ continue;
2390
+ }
2391
+ const shouldCondense = isAllTextContent(msg.content) && msg.content.length > 1;
2392
+ if (shouldCondense) {
2393
+ const joinedText = joinTextContent(msg.content);
2394
+ processedPrompt[i] = createCondensedMessage(msg.role, joinedText);
1975
2395
  }
1976
2396
  }
1977
- for (let i = processedPrompt.length - 1; i > 0; i--) {
2397
+ return processedPrompt;
2398
+ }
2399
+ function mergeConsecutiveUserMessages(processedPrompt) {
2400
+ for (let i = processedPrompt.length - 1; i > 0; i -= 1) {
1978
2401
  const current = processedPrompt[i];
1979
2402
  const prev = processedPrompt[i - 1];
1980
2403
  if (current.role === "user" && prev.role === "user") {
@@ -1982,13 +2405,22 @@ function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
1982
2405
  const currentContent = current.content.map((c) => c.type === "text" ? c.text : "").join("\n");
1983
2406
  processedPrompt[i - 1] = {
1984
2407
  role: "user",
1985
- content: [{ type: "text", text: prevContent + "\n" + currentContent }]
2408
+ content: [{ type: "text", text: `${prevContent}
2409
+ ${currentContent}` }]
1986
2410
  };
1987
2411
  processedPrompt.splice(i, 1);
1988
2412
  }
1989
2413
  }
1990
2414
  return processedPrompt;
1991
2415
  }
2416
+ function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
2417
+ let processedPrompt = prompt.map(
2418
+ (message) => processMessage(message, resolvedProtocol, providerOptions)
2419
+ );
2420
+ processedPrompt = condenseTextContent(processedPrompt);
2421
+ processedPrompt = mergeConsecutiveUserMessages(processedPrompt);
2422
+ return processedPrompt;
2423
+ }
1992
2424
 
1993
2425
  // src/tool-call-middleware.ts
1994
2426
  function createToolMiddleware({
@@ -1997,36 +2429,31 @@ function createToolMiddleware({
1997
2429
  }) {
1998
2430
  const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
1999
2431
  return {
2000
- middlewareVersion: "v2",
2001
- wrapStream: async ({ doStream, doGenerate, params }) => {
2432
+ specificationVersion: "v3",
2433
+ wrapStream: ({ doStream, doGenerate, params }) => {
2002
2434
  if (isToolChoiceActive(params)) {
2003
2435
  return toolChoiceStream({
2004
2436
  doGenerate,
2005
2437
  options: extractOnErrorOption(params.providerOptions)
2006
2438
  });
2007
- } else {
2008
- return wrapStream({
2009
- protocol: resolvedProtocol,
2010
- doStream,
2011
- doGenerate,
2012
- params
2013
- });
2014
2439
  }
2440
+ return wrapStream({
2441
+ protocol: resolvedProtocol,
2442
+ doStream,
2443
+ doGenerate,
2444
+ params
2445
+ });
2015
2446
  },
2016
2447
  wrapGenerate: async ({ doGenerate, params }) => wrapGenerate({
2017
2448
  protocol: resolvedProtocol,
2018
2449
  doGenerate,
2019
2450
  params
2020
2451
  }),
2021
- transformParams: async ({
2452
+ transformParams: async ({ params }) => transformParams({
2453
+ protocol: resolvedProtocol,
2454
+ toolSystemPromptTemplate,
2022
2455
  params
2023
- }) => {
2024
- return transformParams({
2025
- protocol: resolvedProtocol,
2026
- toolSystemPromptTemplate,
2027
- params
2028
- });
2029
- }
2456
+ })
2030
2457
  };
2031
2458
  }
2032
2459
 
@@ -2115,6 +2542,9 @@ Available functions are listed inside <tools></tools>.
2115
2542
  logRawChunk,
2116
2543
  morphXmlProtocol,
2117
2544
  morphXmlToolMiddleware,
2118
- originalToolsSchema
2545
+ originalToolsSchema,
2546
+ parseRJSON,
2547
+ stringifyRJSON,
2548
+ transformRJSON
2119
2549
  });
2120
2550
  //# sourceMappingURL=index.cjs.map