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