@ai-sdk-tool/parser 3.1.3 → 3.2.1

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.
@@ -39,17 +39,11 @@ module.exports = __toCommonJS(community_exports);
39
39
  // src/index.ts
40
40
  var src_exports = {};
41
41
  __export(src_exports, {
42
- applyHeuristicPipeline: () => applyHeuristicPipeline,
43
- balanceTagsHeuristic: () => balanceTagsHeuristic,
44
42
  createDynamicIfThenElseSchema: () => createDynamicIfThenElseSchema,
45
- createIntermediateCall: () => createIntermediateCall,
46
43
  createToolMiddleware: () => createToolMiddleware,
47
44
  decodeOriginalTools: () => decodeOriginalTools,
48
- dedupeShellStringTagsHeuristic: () => dedupeShellStringTagsHeuristic,
49
- defaultPipelineConfig: () => defaultPipelineConfig,
50
45
  encodeOriginalTools: () => encodeOriginalTools,
51
- escapeInvalidLtHeuristic: () => escapeInvalidLtHeuristic,
52
- escapeRegExp: () => escapeRegExp2,
46
+ escapeRegExp: () => escapeRegExp,
53
47
  extractOnErrorOption: () => extractOnErrorOption,
54
48
  extractToolNamesFromOriginalTools: () => extractToolNamesFromOriginalTools,
55
49
  getDebugLevel: () => getDebugLevel,
@@ -65,10 +59,7 @@ __export(src_exports, {
65
59
  logParsedChunk: () => logParsedChunk,
66
60
  logParsedSummary: () => logParsedSummary,
67
61
  logRawChunk: () => logRawChunk,
68
- mergePipelineConfigs: () => mergePipelineConfigs,
69
- normalizeCloseTagsHeuristic: () => normalizeCloseTagsHeuristic,
70
62
  originalToolsSchema: () => originalToolsSchema,
71
- repairAgainstSchemaHeuristic: () => repairAgainstSchemaHeuristic,
72
63
  toolChoiceStream: () => toolChoiceStream,
73
64
  transformParams: () => transformParams,
74
65
  wrapGenerate: () => wrapGenerate,
@@ -80,473 +71,6 @@ __export(src_exports, {
80
71
  });
81
72
  __reExport(src_exports, require("@ai-sdk-tool/rjson"));
82
73
 
83
- // src/core/heuristics/engine.ts
84
- function applyRawSegmentUpdate(current, result) {
85
- if (result.rawSegment !== void 0) {
86
- return { ...current, rawSegment: result.rawSegment };
87
- }
88
- return current;
89
- }
90
- function applyParsedUpdate(current, result) {
91
- if (result.parsed !== void 0) {
92
- return { ...current, parsed: result.parsed };
93
- }
94
- return current;
95
- }
96
- function applyWarningsUpdate(current, result) {
97
- var _a, _b;
98
- if (result.warnings && result.warnings.length > 0) {
99
- const meta = (_a = current.meta) != null ? _a : {};
100
- const existingWarnings = (_b = meta.warnings) != null ? _b : [];
101
- return {
102
- ...current,
103
- meta: { ...meta, warnings: [...existingWarnings, ...result.warnings] }
104
- };
105
- }
106
- return current;
107
- }
108
- function attemptReparse(current, result, reparseCount, maxReparses, parse3) {
109
- if (!result.reparse || result.rawSegment === void 0 || reparseCount >= maxReparses) {
110
- return { state: current, newCount: reparseCount };
111
- }
112
- try {
113
- const reparsed = parse3(result.rawSegment, current.schema);
114
- return {
115
- state: { ...current, parsed: reparsed, errors: [] },
116
- newCount: reparseCount + 1
117
- };
118
- } catch (error) {
119
- return {
120
- state: { ...current, errors: [...current.errors, error] },
121
- newCount: reparseCount + 1
122
- };
123
- }
124
- }
125
- function executePhase(ctx, heuristics, options) {
126
- var _a;
127
- let current = ctx;
128
- let reparseCount = 0;
129
- const maxReparses = (_a = options.maxReparses) != null ? _a : 2;
130
- for (const heuristic of heuristics) {
131
- if (!heuristic.applies(current)) {
132
- continue;
133
- }
134
- const result = heuristic.run(current);
135
- current = applyRawSegmentUpdate(current, result);
136
- current = applyParsedUpdate(current, result);
137
- current = applyWarningsUpdate(current, result);
138
- const reparseResult = attemptReparse(
139
- current,
140
- result,
141
- reparseCount,
142
- maxReparses,
143
- options.parse
144
- );
145
- current = reparseResult.state;
146
- reparseCount = reparseResult.newCount;
147
- if (result.stop) {
148
- break;
149
- }
150
- }
151
- return current;
152
- }
153
- function applyHeuristicPipeline(ctx, config, options) {
154
- let current = ctx;
155
- if (config.preParse && config.preParse.length > 0) {
156
- current = executePhase(current, config.preParse, options);
157
- }
158
- if (current.parsed === null && current.errors.length === 0) {
159
- try {
160
- const parsed = options.parse(current.rawSegment, current.schema);
161
- current = { ...current, parsed, errors: [] };
162
- } catch (error) {
163
- current = { ...current, errors: [error] };
164
- }
165
- }
166
- if (current.errors.length > 0 && config.fallbackReparse && config.fallbackReparse.length > 0) {
167
- current = executePhase(current, config.fallbackReparse, options);
168
- }
169
- if (current.parsed !== null && config.postParse && config.postParse.length > 0) {
170
- current = executePhase(current, config.postParse, options);
171
- }
172
- return current;
173
- }
174
- function createIntermediateCall(toolName, rawSegment, schema) {
175
- return {
176
- toolName,
177
- schema,
178
- rawSegment,
179
- parsed: null,
180
- errors: [],
181
- meta: { originalContent: rawSegment }
182
- };
183
- }
184
- function mergePipelineConfigs(...configs) {
185
- var _a, _b, _c;
186
- const result = {
187
- preParse: [],
188
- fallbackReparse: [],
189
- postParse: []
190
- };
191
- for (const config of configs) {
192
- if (config.preParse) {
193
- result.preParse = [...(_a = result.preParse) != null ? _a : [], ...config.preParse];
194
- }
195
- if (config.fallbackReparse) {
196
- result.fallbackReparse = [
197
- ...(_b = result.fallbackReparse) != null ? _b : [],
198
- ...config.fallbackReparse
199
- ];
200
- }
201
- if (config.postParse) {
202
- result.postParse = [...(_c = result.postParse) != null ? _c : [], ...config.postParse];
203
- }
204
- }
205
- return result;
206
- }
207
-
208
- // src/core/heuristics/xml-defaults.ts
209
- var import_rxml = require("@ai-sdk-tool/rxml");
210
- var MALFORMED_CLOSE_RE_G = /<\/\s+([A-Za-z0-9_:-]+)\s*>/g;
211
- var MALFORMED_CLOSE_RE = /<\/\s+([A-Za-z0-9_:-]+)\s*>/;
212
- var STATUS_TO_STEP_BOUNDARY_RE = /<\/status>\s*<step>/g;
213
- var WHITESPACE_REGEX = /\s/;
214
- var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
215
- var NAME_START_CHAR_RE = /[A-Za-z_:]/;
216
- var STEP_TAG_RE = /<step>([\s\S]*?)<\/step>/i;
217
- var STATUS_TAG_RE = /<status>([\s\S]*?)<\/status>/i;
218
- var normalizeCloseTagsHeuristic = {
219
- id: "normalize-close-tags",
220
- phase: "pre-parse",
221
- applies: () => true,
222
- run: (ctx) => {
223
- const normalized = ctx.rawSegment.replace(MALFORMED_CLOSE_RE_G, "</$1>");
224
- if (normalized !== ctx.rawSegment) {
225
- return { rawSegment: normalized };
226
- }
227
- return {};
228
- }
229
- };
230
- var escapeInvalidLtHeuristic = {
231
- id: "escape-invalid-lt",
232
- phase: "pre-parse",
233
- applies: () => true,
234
- run: (ctx) => {
235
- const escaped = escapeInvalidLt(ctx.rawSegment);
236
- if (escaped !== ctx.rawSegment) {
237
- return { rawSegment: escaped };
238
- }
239
- return {};
240
- }
241
- };
242
- var balanceTagsHeuristic = {
243
- id: "balance-tags",
244
- phase: "fallback-reparse",
245
- applies: (ctx) => {
246
- var _a;
247
- const original = ((_a = ctx.meta) == null ? void 0 : _a.originalContent) || ctx.rawSegment;
248
- const normalized = original.replace(MALFORMED_CLOSE_RE_G, "</$1>");
249
- const balanced = balanceTags(original);
250
- const hasMalformedClose = MALFORMED_CLOSE_RE.test(original);
251
- if (!hasMalformedClose && balanced.length > normalized.length) {
252
- return false;
253
- }
254
- return balanced !== normalized;
255
- },
256
- run: (ctx) => {
257
- var _a;
258
- const original = ((_a = ctx.meta) == null ? void 0 : _a.originalContent) || ctx.rawSegment;
259
- const balanced = balanceTags(original);
260
- const escaped = escapeInvalidLt(balanced);
261
- return { rawSegment: escaped, reparse: true };
262
- }
263
- };
264
- var dedupeShellStringTagsHeuristic = {
265
- id: "dedupe-shell-string-tags",
266
- phase: "fallback-reparse",
267
- applies: (ctx) => shouldDeduplicateStringTags(ctx.schema),
268
- run: (ctx) => {
269
- const names = getStringPropertyNames(ctx.schema);
270
- let deduped = ctx.rawSegment;
271
- for (const key of names) {
272
- deduped = dedupeSingleTag(deduped, key);
273
- }
274
- if (deduped !== ctx.rawSegment) {
275
- return { rawSegment: deduped, reparse: true };
276
- }
277
- return {};
278
- }
279
- };
280
- var repairAgainstSchemaHeuristic = {
281
- id: "repair-against-schema",
282
- phase: "post-parse",
283
- applies: (ctx) => ctx.parsed !== null && typeof ctx.parsed === "object",
284
- run: (ctx) => {
285
- const repaired = repairParsedAgainstSchema(ctx.parsed, ctx.schema);
286
- if (repaired !== ctx.parsed) {
287
- return { parsed: repaired };
288
- }
289
- return {};
290
- }
291
- };
292
- var defaultPipelineConfig = {
293
- preParse: [normalizeCloseTagsHeuristic, escapeInvalidLtHeuristic],
294
- fallbackReparse: [balanceTagsHeuristic, dedupeShellStringTagsHeuristic],
295
- postParse: [repairAgainstSchemaHeuristic]
296
- };
297
- var INDEX_TAG_RE = /^<(\d+)(?:>|\/?>)/;
298
- function isIndexTagAt(xml, pos) {
299
- const remaining = xml.slice(pos);
300
- return INDEX_TAG_RE.test(remaining);
301
- }
302
- function escapeInvalidLt(xml) {
303
- const len = xml.length;
304
- let out = "";
305
- for (let i = 0; i < len; i += 1) {
306
- const ch = xml[i];
307
- if (ch === "<") {
308
- const next = i + 1 < len ? xml[i + 1] : "";
309
- const isValidStart = NAME_START_CHAR_RE.test(next) || next === "/" || next === "!" || next === "?";
310
- const isIndexTag = !isValidStart && isIndexTagAt(xml, i);
311
- if (!(isValidStart || isIndexTag)) {
312
- out += "&lt;";
313
- continue;
314
- }
315
- }
316
- out += ch;
317
- }
318
- return out;
319
- }
320
- function balanceTags(xml) {
321
- const src = xml.replace(MALFORMED_CLOSE_RE_G, "</$1>").replace(STATUS_TO_STEP_BOUNDARY_RE, "</status></step><step>");
322
- let i = 0;
323
- const len = src.length;
324
- const out = [];
325
- const stack = [];
326
- while (i < len) {
327
- const lt = src.indexOf("<", i);
328
- if (lt === -1) {
329
- out.push(src.slice(i));
330
- break;
331
- }
332
- out.push(src.slice(i, lt));
333
- if (lt + 1 >= len) {
334
- break;
335
- }
336
- const next = src[lt + 1];
337
- if (next === "!" || next === "?") {
338
- i = handleSpecialTagSegment(src, lt, out);
339
- continue;
340
- }
341
- if (next === "/") {
342
- i = handleClosingTagSegment(src, lt, out, stack);
343
- continue;
344
- }
345
- i = handleOpeningTagSegment(src, lt, out, stack);
346
- }
347
- for (let k = stack.length - 1; k >= 0; k -= 1) {
348
- out.push(`</${stack[k]}>`);
349
- }
350
- return out.join("");
351
- }
352
- function skipWs(s, p, len) {
353
- let idx = p;
354
- while (idx < len && WHITESPACE_REGEX.test(s[idx])) {
355
- idx += 1;
356
- }
357
- return idx;
358
- }
359
- function parseTagNameAt(s, p, len) {
360
- let idx = p;
361
- const start = idx;
362
- while (idx < len && NAME_CHAR_RE.test(s[idx])) {
363
- idx += 1;
364
- }
365
- return { name: s.slice(start, idx), pos: idx };
366
- }
367
- function handleSpecialTagSegment(src, lt, out) {
368
- const gt = src.indexOf(">", lt + 1);
369
- if (gt === -1) {
370
- out.push(src.slice(lt));
371
- return src.length;
372
- }
373
- out.push(src.slice(lt, gt + 1));
374
- return gt + 1;
375
- }
376
- function handleClosingTagSegment(src, lt, out, stack) {
377
- const len = src.length;
378
- let p = skipWs(src, lt + 2, len);
379
- const { name, pos } = parseTagNameAt(src, p, len);
380
- p = pos;
381
- const gt = src.indexOf(">", p);
382
- const closingText = gt === -1 ? src.slice(lt) : src.slice(lt, gt + 1);
383
- const idx = stack.lastIndexOf(name);
384
- if (idx !== -1) {
385
- for (let k = stack.length - 1; k > idx; k -= 1) {
386
- out.push(`</${stack[k]}>`);
387
- stack.pop();
388
- }
389
- out.push(closingText);
390
- stack.pop();
391
- }
392
- return gt === -1 ? len : gt + 1;
393
- }
394
- function handleOpeningTagSegment(src, lt, out, stack) {
395
- const len = src.length;
396
- let p = skipWs(src, lt + 1, len);
397
- const nameStart = p;
398
- const parsed = parseTagNameAt(src, p, len);
399
- p = parsed.pos;
400
- const name = src.slice(nameStart, p);
401
- const q = src.indexOf(">", p);
402
- if (q === -1) {
403
- out.push(src.slice(lt));
404
- return len;
405
- }
406
- let r = q - 1;
407
- while (r >= nameStart && WHITESPACE_REGEX.test(src[r])) {
408
- r -= 1;
409
- }
410
- const selfClosing = src[r] === "/";
411
- out.push(src.slice(lt, q + 1));
412
- if (!selfClosing && name) {
413
- stack.push(name);
414
- }
415
- return q + 1;
416
- }
417
- function extractSchemaProperties(schema) {
418
- const unwrapped = (0, import_rxml.unwrapJsonSchema)(schema);
419
- if (!unwrapped || typeof unwrapped !== "object") {
420
- return void 0;
421
- }
422
- return unwrapped.properties;
423
- }
424
- function shouldDeduplicateStringTags(schema) {
425
- const props = extractSchemaProperties(schema);
426
- if (!props) {
427
- return false;
428
- }
429
- const commandRaw = props.command;
430
- if (!commandRaw) {
431
- return false;
432
- }
433
- const command = (0, import_rxml.unwrapJsonSchema)(commandRaw);
434
- return (command == null ? void 0 : command.type) === "array";
435
- }
436
- function getStringPropertyNames(schema) {
437
- const props = extractSchemaProperties(schema);
438
- if (!props) {
439
- return [];
440
- }
441
- const names = [];
442
- for (const key of Object.keys(props)) {
443
- const prop = (0, import_rxml.unwrapJsonSchema)(props[key]);
444
- if ((prop == null ? void 0 : prop.type) === "string") {
445
- names.push(key);
446
- }
447
- }
448
- return names;
449
- }
450
- function escapeRegExp(s) {
451
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
452
- }
453
- function dedupeSingleTag(xml, key) {
454
- var _a, _b;
455
- const escaped = escapeRegExp(key);
456
- const re = new RegExp(`<${escaped}>([\\s\\S]*?)<\\/${escaped}>`, "g");
457
- const matches = Array.from(xml.matchAll(re));
458
- if (matches.length <= 1) {
459
- return xml;
460
- }
461
- const last = matches.at(-1);
462
- let result = "";
463
- let cursor = 0;
464
- for (const m of matches) {
465
- const idx = (_a = m.index) != null ? _a : 0;
466
- result += xml.slice(cursor, idx);
467
- if (last && idx === ((_b = last.index) != null ? _b : -1)) {
468
- result += m[0];
469
- }
470
- cursor = idx + m[0].length;
471
- }
472
- result += xml.slice(cursor);
473
- return result;
474
- }
475
- function repairParsedAgainstSchema(input, schema) {
476
- if (!input || typeof input !== "object") {
477
- return input;
478
- }
479
- const properties = extractSchemaProperties(schema);
480
- if (!properties) {
481
- return input;
482
- }
483
- applySchemaProps(input, properties);
484
- return input;
485
- }
486
- function applySchemaProps(obj, properties) {
487
- for (const key of Object.keys(obj)) {
488
- const propSchema = properties[key];
489
- if (!propSchema) {
490
- continue;
491
- }
492
- const prop = (0, import_rxml.unwrapJsonSchema)(propSchema);
493
- if ((prop == null ? void 0 : prop.type) === "array" && prop.items) {
494
- const itemSchema = (0, import_rxml.unwrapJsonSchema)(prop.items);
495
- obj[key] = coerceArrayItems(obj[key], itemSchema);
496
- continue;
497
- }
498
- if ((prop == null ? void 0 : prop.type) === "object") {
499
- const val = obj[key];
500
- if (val && typeof val === "object") {
501
- obj[key] = repairParsedAgainstSchema(val, prop);
502
- }
503
- }
504
- }
505
- }
506
- function coerceArrayItems(val, itemSchema) {
507
- if (!Array.isArray(val)) {
508
- return val;
509
- }
510
- return val.map((v) => coerceArrayItem(v, itemSchema));
511
- }
512
- function coerceArrayItem(v, itemSchema) {
513
- const itemType = itemSchema == null ? void 0 : itemSchema.type;
514
- if (typeof v === "string" && itemType === "object") {
515
- const parsed = tryParseStringToSchemaObject(v, itemSchema);
516
- if (parsed !== null) {
517
- return parsed;
518
- }
519
- const fallback = extractStepStatusFromString(
520
- v.replace(MALFORMED_CLOSE_RE_G, "</$1>")
521
- );
522
- if (fallback) {
523
- return fallback;
524
- }
525
- return v;
526
- }
527
- if (v && typeof v === "object" && itemType === "object") {
528
- return repairParsedAgainstSchema(v, itemSchema);
529
- }
530
- return v;
531
- }
532
- function tryParseStringToSchemaObject(xml, itemSchema) {
533
- try {
534
- const normalized = xml.replace(MALFORMED_CLOSE_RE_G, "</$1>");
535
- const fixed = (0, import_rxml.parse)(normalized, itemSchema, { noChildNodes: [] });
536
- return typeof fixed === "string" ? null : fixed;
537
- } catch (e) {
538
- return null;
539
- }
540
- }
541
- function extractStepStatusFromString(normXml) {
542
- const stepMatch = normXml.match(STEP_TAG_RE);
543
- const statusMatch = normXml.match(STATUS_TAG_RE);
544
- if (stepMatch && statusMatch) {
545
- return { step: stepMatch[1], status: statusMatch[1] };
546
- }
547
- return null;
548
- }
549
-
550
74
  // src/core/protocols/json-protocol.ts
551
75
  var import_rjson = require("@ai-sdk-tool/rjson");
552
76
 
@@ -729,7 +253,7 @@ function generateId() {
729
253
  }
730
254
 
731
255
  // src/core/utils/regex.ts
732
- function escapeRegExp2(literal) {
256
+ function escapeRegExp(literal) {
733
257
  return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
734
258
  }
735
259
 
@@ -976,8 +500,8 @@ var jsonProtocol = ({
976
500
  text,
977
501
  options
978
502
  }) {
979
- const startEsc = escapeRegExp2(toolCallStart);
980
- const endEsc = escapeRegExp2(toolCallEnd);
503
+ const startEsc = escapeRegExp(toolCallStart);
504
+ const endEsc = escapeRegExp(toolCallEnd);
981
505
  const toolCallRegex = new RegExp(
982
506
  `${startEsc}([\0-\uFFFF]*?)${endEsc}`,
983
507
  "gs"
@@ -1036,8 +560,8 @@ var jsonProtocol = ({
1036
560
  });
1037
561
  },
1038
562
  extractToolCallSegments({ text }) {
1039
- const startEsc = escapeRegExp2(toolCallStart);
1040
- const endEsc = escapeRegExp2(toolCallEnd);
563
+ const startEsc = escapeRegExp(toolCallStart);
564
+ const endEsc = escapeRegExp(toolCallEnd);
1041
565
  const regex = new RegExp(`${startEsc}([\0-\uFFFF]*?)${endEsc}`, "gs");
1042
566
  const segments = [];
1043
567
  let m = regex.exec(text);
@@ -1058,93 +582,44 @@ function isTCMProtocolFactory(protocol) {
1058
582
  }
1059
583
 
1060
584
  // src/core/protocols/xml-protocol.ts
1061
- var import_rxml2 = require("@ai-sdk-tool/rxml");
1062
- var defaultPipelineConfig2 = defaultPipelineConfig;
1063
- var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
1064
- var WHITESPACE_REGEX2 = /\s/;
585
+ var import_rxml = require("@ai-sdk-tool/rxml");
586
+ var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
587
+ var WHITESPACE_REGEX = /\s/;
1065
588
  function getToolSchema(tools, toolName) {
1066
589
  var _a;
1067
590
  return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
1068
591
  }
1069
- function normalizeCloseTags(xml) {
1070
- return xml.replace(/<\/\s+([A-Za-z0-9_:-]+)\s*>/g, "</$1>");
1071
- }
1072
- function tryParseSecondaryXml(content, toolSchema, options) {
1073
- const balanced = balanceTags(content);
1074
- try {
1075
- let parsed = (0, import_rxml2.parse)(balanced, toolSchema, {
1076
- onError: options == null ? void 0 : options.onError,
1077
- noChildNodes: []
1078
- });
1079
- parsed = repairParsedAgainstSchema(parsed, toolSchema);
1080
- return parsed;
1081
- } catch (e) {
1082
- if (shouldDeduplicateStringTags(toolSchema)) {
1083
- const names = getStringPropertyNames(toolSchema);
1084
- let deduped = balanced;
1085
- for (const key of names) {
1086
- deduped = dedupeSingleTag(deduped, key);
1087
- }
1088
- if (deduped !== balanced) {
1089
- try {
1090
- let reparsed = (0, import_rxml2.parse)(deduped, toolSchema, {
1091
- onError: options == null ? void 0 : options.onError,
1092
- noChildNodes: []
1093
- });
1094
- reparsed = repairParsedAgainstSchema(reparsed, toolSchema);
1095
- return reparsed;
1096
- } catch (e2) {
1097
- return null;
1098
- }
1099
- }
1100
- }
1101
- return null;
1102
- }
1103
- }
1104
- function processToolCallWithPipeline(params) {
1105
- var _a;
1106
- const {
1107
- toolCall,
1108
- tools,
1109
- options,
1110
- text,
1111
- processedElements,
1112
- pipelineConfig = defaultPipelineConfig2,
1113
- maxReparses
1114
- } = params;
592
+ function processToolCall(params) {
593
+ var _a, _b;
594
+ const { toolCall, tools, options, text, processedElements, parseOptions } = params;
1115
595
  const toolSchema = getToolSchema(tools, toolCall.toolName);
1116
- const ctx = createIntermediateCall(
1117
- toolCall.toolName,
1118
- toolCall.content,
1119
- toolSchema
1120
- );
1121
- const result = applyHeuristicPipeline(ctx, pipelineConfig, {
1122
- parse: (xml, schema) => (0, import_rxml2.parse)(xml, schema, { onError: options == null ? void 0 : options.onError, noChildNodes: [] }),
1123
- onError: options == null ? void 0 : options.onError,
1124
- maxReparses
1125
- });
1126
- if (result.parsed !== null) {
596
+ const parseConfig = {
597
+ ...parseOptions != null ? parseOptions : {},
598
+ onError: (_a = options == null ? void 0 : options.onError) != null ? _a : parseOptions == null ? void 0 : parseOptions.onError
599
+ };
600
+ try {
601
+ const parsed = (0, import_rxml.parse)(toolCall.content, toolSchema, parseConfig);
1127
602
  processedElements.push({
1128
603
  type: "tool-call",
1129
604
  toolCallId: generateId(),
1130
605
  toolName: toolCall.toolName,
1131
- input: JSON.stringify(result.parsed)
606
+ input: JSON.stringify(parsed)
1132
607
  });
1133
- } else {
608
+ } catch (error) {
1134
609
  const originalCallText = text.substring(
1135
610
  toolCall.startIndex,
1136
611
  toolCall.endIndex
1137
612
  );
1138
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
613
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
1139
614
  options,
1140
615
  `Could not process XML tool call: ${toolCall.toolName}`,
1141
- { toolCall: originalCallText, error: result.errors[0] }
616
+ { toolCall: originalCallText, error }
1142
617
  );
1143
618
  processedElements.push({ type: "text", text: originalCallText });
1144
619
  }
1145
620
  }
1146
621
  function handleStreamingToolCallEnd(params) {
1147
- var _a;
622
+ var _a, _b;
1148
623
  const {
1149
624
  toolContent,
1150
625
  currentToolCall,
@@ -1152,51 +627,27 @@ function handleStreamingToolCallEnd(params) {
1152
627
  options,
1153
628
  ctrl,
1154
629
  flushText,
1155
- pipelineConfig,
1156
- maxReparses
630
+ parseOptions
1157
631
  } = params;
1158
632
  const toolSchema = getToolSchema(tools, currentToolCall.name);
1159
- let parsedResult = null;
1160
- if (pipelineConfig) {
1161
- const ctx = createIntermediateCall(
1162
- currentToolCall.name,
1163
- toolContent,
1164
- toolSchema
1165
- );
1166
- const result = applyHeuristicPipeline(ctx, pipelineConfig, {
1167
- parse: (xml, schema) => (0, import_rxml2.parse)(xml, schema, { onError: options == null ? void 0 : options.onError, noChildNodes: [] }),
1168
- onError: options == null ? void 0 : options.onError,
1169
- maxReparses
1170
- });
1171
- parsedResult = result.parsed;
1172
- } else {
1173
- try {
1174
- const primary = escapeInvalidLt(normalizeCloseTags(toolContent));
1175
- const parsed = (0, import_rxml2.parse)(primary, toolSchema, {
1176
- onError: options == null ? void 0 : options.onError,
1177
- noChildNodes: []
1178
- });
1179
- parsedResult = repairParsedAgainstSchema(parsed, toolSchema);
1180
- } catch (e) {
1181
- parsedResult = tryParseSecondaryXml(
1182
- toolContent,
1183
- toolSchema,
1184
- options != null ? options : {}
1185
- );
1186
- }
1187
- }
633
+ const parseConfig = {
634
+ ...parseOptions != null ? parseOptions : {},
635
+ onError: (_a = options == null ? void 0 : options.onError) != null ? _a : parseOptions == null ? void 0 : parseOptions.onError
636
+ };
1188
637
  flushText(ctrl);
1189
- if (parsedResult !== null) {
638
+ try {
639
+ const parsedResult = (0, import_rxml.parse)(toolContent, toolSchema, parseConfig);
1190
640
  ctrl.enqueue({
1191
641
  type: "tool-call",
1192
642
  toolCallId: generateId(),
1193
643
  toolName: currentToolCall.name,
1194
644
  input: JSON.stringify(parsedResult)
1195
645
  });
1196
- } else {
646
+ } catch (error) {
1197
647
  const original = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
1198
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not process streaming XML tool call", {
1199
- toolCall: original
648
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
649
+ toolCall: original,
650
+ error
1200
651
  });
1201
652
  flushText(ctrl, original);
1202
653
  }
@@ -1235,11 +686,11 @@ function consumeClosingTag(text, lt) {
1235
686
  }
1236
687
  function consumeOpenTag(text, lt) {
1237
688
  let p = lt + 1;
1238
- while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
689
+ while (p < text.length && WHITESPACE_REGEX.test(text[p])) {
1239
690
  p += 1;
1240
691
  }
1241
692
  const nameStart = p;
1242
- while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
693
+ while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
1243
694
  p += 1;
1244
695
  }
1245
696
  const name = text.slice(nameStart, p);
@@ -1248,7 +699,7 @@ function consumeOpenTag(text, lt) {
1248
699
  return null;
1249
700
  }
1250
701
  let r = q - 1;
1251
- while (r >= nameStart && WHITESPACE_REGEX2.test(text[r])) {
702
+ while (r >= nameStart && WHITESPACE_REGEX.test(text[r])) {
1252
703
  r -= 1;
1253
704
  }
1254
705
  const selfClosing = text[r] === "/";
@@ -1277,11 +728,11 @@ function nextTagToken(text, fromPos) {
1277
728
  if (next === "/") {
1278
729
  const closing = consumeClosingTag(text, lt);
1279
730
  let p = lt + 2;
1280
- while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
731
+ while (p < text.length && WHITESPACE_REGEX.test(text[p])) {
1281
732
  p += 1;
1282
733
  }
1283
734
  const nameStart = p;
1284
- while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
735
+ while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
1285
736
  p += 1;
1286
737
  }
1287
738
  const name = text.slice(nameStart, p);
@@ -1298,49 +749,111 @@ function nextTagToken(text, fromPos) {
1298
749
  nextPos: open.nextPos
1299
750
  };
1300
751
  }
752
+ function findNextToolTag(text, searchIndex, toolName) {
753
+ var _a, _b;
754
+ const startTag = `<${toolName}>`;
755
+ const openIdx = text.indexOf(startTag, searchIndex);
756
+ const selfMatch = findSelfClosingTag(text, toolName, searchIndex);
757
+ const selfIdx = (_a = selfMatch == null ? void 0 : selfMatch.index) != null ? _a : -1;
758
+ if (openIdx === -1 && selfIdx === -1) {
759
+ return null;
760
+ }
761
+ const isSelfClosing = selfIdx !== -1 && (openIdx === -1 || selfIdx < openIdx);
762
+ return {
763
+ tagStart: isSelfClosing ? selfIdx : openIdx,
764
+ isSelfClosing,
765
+ tagLength: isSelfClosing ? (_b = selfMatch == null ? void 0 : selfMatch.length) != null ? _b : 0 : startTag.length
766
+ };
767
+ }
768
+ function findLastCloseTagStart(segment, toolName) {
769
+ const closeTagPattern = new RegExp(
770
+ `</\\s*${escapeRegExp(toolName)}\\s*>`,
771
+ "g"
772
+ );
773
+ let closeTagStart = -1;
774
+ let match = closeTagPattern.exec(segment);
775
+ while (match !== null) {
776
+ closeTagStart = match.index;
777
+ match = closeTagPattern.exec(segment);
778
+ }
779
+ if (closeTagStart === -1) {
780
+ return segment.lastIndexOf("<");
781
+ }
782
+ return closeTagStart;
783
+ }
784
+ function pushSelfClosingToolCall(toolCalls, toolName, text, tagStart, tagLength) {
785
+ const endIndex = tagStart + tagLength;
786
+ toolCalls.push({
787
+ toolName,
788
+ startIndex: tagStart,
789
+ endIndex,
790
+ content: "",
791
+ segment: text.substring(tagStart, endIndex)
792
+ });
793
+ return endIndex;
794
+ }
795
+ var selfClosingTagCache = /* @__PURE__ */ new Map();
796
+ function getSelfClosingTagPattern(toolName) {
797
+ let pattern = selfClosingTagCache.get(toolName);
798
+ if (!pattern) {
799
+ pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
800
+ selfClosingTagCache.set(toolName, pattern);
801
+ }
802
+ return pattern;
803
+ }
804
+ function findSelfClosingTag(text, toolName, fromIndex) {
805
+ const pattern = getSelfClosingTagPattern(toolName);
806
+ pattern.lastIndex = fromIndex;
807
+ const match = pattern.exec(text);
808
+ if (!match || match.index === void 0) {
809
+ return null;
810
+ }
811
+ return { index: match.index, length: match[0].length };
812
+ }
813
+ function appendOpenToolCallIfComplete(toolCalls, text, toolName, tagStart, startTag) {
814
+ const contentStart = tagStart + startTag.length;
815
+ const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
816
+ if (fullTagEnd === -1 || fullTagEnd <= contentStart) {
817
+ return contentStart;
818
+ }
819
+ const segment = text.substring(tagStart, fullTagEnd);
820
+ const closeTagStart = findLastCloseTagStart(segment, toolName);
821
+ const inner = closeTagStart === -1 ? segment.slice(startTag.length) : segment.slice(startTag.length, closeTagStart);
822
+ toolCalls.push({
823
+ toolName,
824
+ startIndex: tagStart,
825
+ endIndex: fullTagEnd,
826
+ content: inner,
827
+ segment
828
+ });
829
+ return fullTagEnd;
830
+ }
1301
831
  function findToolCallsForName(text, toolName) {
1302
- var _a;
1303
832
  const toolCalls = [];
833
+ const startTag = `<${toolName}>`;
1304
834
  let searchIndex = 0;
1305
835
  while (searchIndex < text.length) {
1306
- const startTag = `<${toolName}>`;
1307
- const selfTag = `<${toolName}/>`;
1308
- const openIdx = text.indexOf(startTag, searchIndex);
1309
- const selfIdx = text.indexOf(selfTag, searchIndex);
1310
- if (openIdx === -1 && selfIdx === -1) {
836
+ const match = findNextToolTag(text, searchIndex, toolName);
837
+ if (match === null) {
1311
838
  break;
1312
839
  }
1313
- const tagStart = selfIdx !== -1 && (openIdx === -1 || selfIdx < openIdx) ? selfIdx : openIdx;
1314
- const isSelfClosing = tagStart === selfIdx;
1315
- if (isSelfClosing) {
1316
- const endIndex = tagStart + selfTag.length;
1317
- const segment = text.substring(tagStart, endIndex);
1318
- toolCalls.push({
840
+ if (match.isSelfClosing) {
841
+ searchIndex = pushSelfClosingToolCall(
842
+ toolCalls,
1319
843
  toolName,
1320
- startIndex: tagStart,
1321
- endIndex,
1322
- content: "",
1323
- segment
1324
- });
1325
- searchIndex = endIndex;
844
+ text,
845
+ match.tagStart,
846
+ match.tagLength
847
+ );
1326
848
  continue;
1327
849
  }
1328
- const contentStart = tagStart + startTag.length;
1329
- const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
1330
- if (fullTagEnd !== -1 && fullTagEnd > contentStart) {
1331
- const segment = text.substring(tagStart, fullTagEnd);
1332
- const inner = (_a = (0, import_rxml2.extractRawInner)(segment, toolName)) != null ? _a : segment.substring(startTag.length, segment.lastIndexOf("<"));
1333
- toolCalls.push({
1334
- toolName,
1335
- startIndex: tagStart,
1336
- endIndex: fullTagEnd,
1337
- content: inner,
1338
- segment
1339
- });
1340
- searchIndex = fullTagEnd;
1341
- } else {
1342
- searchIndex = contentStart;
1343
- }
850
+ searchIndex = appendOpenToolCallIfComplete(
851
+ toolCalls,
852
+ text,
853
+ toolName,
854
+ match.tagStart,
855
+ startTag
856
+ );
1344
857
  }
1345
858
  return toolCalls;
1346
859
  }
@@ -1353,28 +866,114 @@ function findToolCalls(text, toolNames) {
1353
866
  return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
1354
867
  }
1355
868
  function findEarliestToolTag(buffer, toolNames) {
869
+ var _a, _b;
1356
870
  let bestIndex = -1;
1357
871
  let bestName = "";
1358
872
  let bestSelfClosing = false;
873
+ let bestTagLength = 0;
1359
874
  if (toolNames.length > 0) {
1360
875
  for (const name of toolNames) {
1361
876
  const openTag = `<${name}>`;
1362
- const selfTag = `<${name}/>`;
1363
877
  const idxOpen = buffer.indexOf(openTag);
1364
- const idxSelf = buffer.indexOf(selfTag);
878
+ const selfMatch = findSelfClosingTag(buffer, name, 0);
879
+ const idxSelf = (_a = selfMatch == null ? void 0 : selfMatch.index) != null ? _a : -1;
1365
880
  if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
1366
881
  bestIndex = idxOpen;
1367
882
  bestName = name;
1368
883
  bestSelfClosing = false;
884
+ bestTagLength = openTag.length;
1369
885
  }
1370
886
  if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
1371
887
  bestIndex = idxSelf;
1372
888
  bestName = name;
1373
889
  bestSelfClosing = true;
890
+ bestTagLength = (_b = selfMatch == null ? void 0 : selfMatch.length) != null ? _b : 0;
1374
891
  }
1375
892
  }
1376
893
  }
1377
- return { index: bestIndex, name: bestName, selfClosing: bestSelfClosing };
894
+ return {
895
+ index: bestIndex,
896
+ name: bestName,
897
+ selfClosing: bestSelfClosing,
898
+ tagLength: bestTagLength
899
+ };
900
+ }
901
+ function isOpenTagPrefix(suffix, toolName) {
902
+ return `${toolName}>`.startsWith(suffix);
903
+ }
904
+ function consumeWhitespace(text, index) {
905
+ let i = index;
906
+ while (i < text.length && WHITESPACE_REGEX.test(text.charAt(i))) {
907
+ i += 1;
908
+ }
909
+ return i;
910
+ }
911
+ function consumeToolNamePrefix(text, index, toolName) {
912
+ let i = index;
913
+ let nameIndex = 0;
914
+ while (i < text.length && nameIndex < toolName.length) {
915
+ if (text.charAt(i) !== toolName.charAt(nameIndex)) {
916
+ return { index: i, done: false, valid: false };
917
+ }
918
+ i += 1;
919
+ nameIndex += 1;
920
+ }
921
+ return { index: i, done: nameIndex === toolName.length, valid: true };
922
+ }
923
+ function isSelfClosingSuffixRemainder(text, index) {
924
+ if (text.charAt(index) !== "/") {
925
+ return false;
926
+ }
927
+ if (index + 1 >= text.length) {
928
+ return true;
929
+ }
930
+ return index + 1 === text.length - 1 && text.charAt(index + 1) === ">";
931
+ }
932
+ function isSelfClosingTagPrefix(suffix, toolName) {
933
+ let i = consumeWhitespace(suffix, 0);
934
+ if (i >= suffix.length) {
935
+ return true;
936
+ }
937
+ const nameRemainder = suffix.slice(i);
938
+ if (toolName.startsWith(nameRemainder)) {
939
+ return true;
940
+ }
941
+ const nameResult = consumeToolNamePrefix(suffix, i, toolName);
942
+ if (!nameResult.valid) {
943
+ return false;
944
+ }
945
+ i = nameResult.index;
946
+ if (i >= suffix.length) {
947
+ return true;
948
+ }
949
+ if (!nameResult.done) {
950
+ return false;
951
+ }
952
+ i = consumeWhitespace(suffix, i);
953
+ if (i >= suffix.length) {
954
+ return true;
955
+ }
956
+ return isSelfClosingSuffixRemainder(suffix, i);
957
+ }
958
+ function findPotentialToolTagStart(buffer, toolNames) {
959
+ if (toolNames.length === 0 || buffer.length === 0) {
960
+ return -1;
961
+ }
962
+ const lastGt = buffer.lastIndexOf(">");
963
+ const offset = lastGt === -1 ? 0 : lastGt + 1;
964
+ const trailing = buffer.slice(offset);
965
+ for (let i = trailing.length - 1; i >= 0; i -= 1) {
966
+ if (trailing.charAt(i) !== "<") {
967
+ continue;
968
+ }
969
+ const suffix = trailing.slice(i + 1);
970
+ for (const name of toolNames) {
971
+ if (isOpenTagPrefix(suffix, name) || isSelfClosingTagPrefix(suffix, name)) {
972
+ return offset + i;
973
+ }
974
+ }
975
+ }
976
+ return -1;
1378
977
  }
1379
978
  function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
1380
979
  return (controller, text) => {
@@ -1417,16 +1016,20 @@ function processToolCallInBuffer(params) {
1417
1016
  controller,
1418
1017
  flushText,
1419
1018
  setBuffer,
1420
- pipelineConfig,
1421
- maxReparses
1019
+ parseOptions
1422
1020
  } = params;
1423
- const endTag = `</${currentToolCall.name}>`;
1424
- const endIdx = buffer.indexOf(endTag);
1425
- if (endIdx === -1) {
1021
+ const endTagPattern = new RegExp(
1022
+ `</\\s*${escapeRegExp(currentToolCall.name)}\\s*>`
1023
+ );
1024
+ const endMatch = endTagPattern.exec(buffer);
1025
+ if (!endMatch || endMatch.index === void 0) {
1426
1026
  return { buffer, currentToolCall, shouldBreak: true };
1427
1027
  }
1028
+ const endIdx = endMatch.index;
1029
+ const endPos = endIdx + endMatch[0].length;
1428
1030
  const content = buffer.substring(0, endIdx);
1429
- setBuffer(buffer.substring(endIdx + endTag.length));
1031
+ const remainder = buffer.substring(endPos);
1032
+ setBuffer(remainder);
1430
1033
  handleStreamingToolCallEnd({
1431
1034
  toolContent: content,
1432
1035
  currentToolCall,
@@ -1434,11 +1037,10 @@ function processToolCallInBuffer(params) {
1434
1037
  options,
1435
1038
  ctrl: controller,
1436
1039
  flushText,
1437
- pipelineConfig,
1438
- maxReparses
1040
+ parseOptions
1439
1041
  });
1440
1042
  return {
1441
- buffer: buffer.substring(endIdx + endTag.length),
1043
+ buffer: remainder,
1442
1044
  currentToolCall: null,
1443
1045
  shouldBreak: false
1444
1046
  };
@@ -1451,25 +1053,28 @@ function processNoToolCallInBuffer(params) {
1451
1053
  flushText,
1452
1054
  tools,
1453
1055
  options,
1454
- pipelineConfig,
1455
- maxReparses,
1056
+ parseOptions,
1456
1057
  setBuffer
1457
1058
  } = params;
1458
1059
  const {
1459
1060
  index: earliestStartTagIndex,
1460
1061
  name: earliestToolName,
1461
- selfClosing
1062
+ selfClosing,
1063
+ tagLength
1462
1064
  } = findEarliestToolTag(buffer, toolNames);
1463
1065
  if (earliestStartTagIndex === -1) {
1464
- const maxTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n}>`.length)) : 0;
1465
- const tail = Math.max(0, maxTagLen - 1);
1466
- const safeLen = Math.max(0, buffer.length - tail);
1066
+ const potentialStart = findPotentialToolTagStart(buffer, toolNames);
1067
+ const safeLen = Math.max(
1068
+ 0,
1069
+ potentialStart === -1 ? buffer.length : potentialStart
1070
+ );
1071
+ const remaining = buffer.slice(safeLen);
1467
1072
  if (safeLen > 0) {
1468
1073
  flushText(controller, buffer.slice(0, safeLen));
1469
- setBuffer(buffer.slice(safeLen));
1074
+ setBuffer(remaining);
1470
1075
  }
1471
1076
  return {
1472
- buffer: buffer.slice(safeLen),
1077
+ buffer: remaining,
1473
1078
  currentToolCall: null,
1474
1079
  shouldBreak: true,
1475
1080
  shouldContinue: false
@@ -1477,8 +1082,7 @@ function processNoToolCallInBuffer(params) {
1477
1082
  }
1478
1083
  flushText(controller, buffer.substring(0, earliestStartTagIndex));
1479
1084
  if (selfClosing) {
1480
- const selfTag = `<${earliestToolName}/>`;
1481
- const newBuffer2 = buffer.substring(earliestStartTagIndex + selfTag.length);
1085
+ const newBuffer2 = buffer.substring(earliestStartTagIndex + tagLength);
1482
1086
  setBuffer(newBuffer2);
1483
1087
  handleStreamingToolCallEnd({
1484
1088
  toolContent: "",
@@ -1487,8 +1091,7 @@ function processNoToolCallInBuffer(params) {
1487
1091
  options,
1488
1092
  ctrl: controller,
1489
1093
  flushText,
1490
- pipelineConfig,
1491
- maxReparses
1094
+ parseOptions
1492
1095
  });
1493
1096
  return {
1494
1097
  buffer: newBuffer2,
@@ -1507,7 +1110,7 @@ function processNoToolCallInBuffer(params) {
1507
1110
  shouldContinue: true
1508
1111
  };
1509
1112
  }
1510
- function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, pipelineConfig, maxReparses) {
1113
+ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions) {
1511
1114
  return (controller) => {
1512
1115
  while (true) {
1513
1116
  const currentToolCall = getCurrentToolCall();
@@ -1520,8 +1123,7 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
1520
1123
  controller,
1521
1124
  flushText,
1522
1125
  setBuffer,
1523
- pipelineConfig,
1524
- maxReparses
1126
+ parseOptions
1525
1127
  });
1526
1128
  setBuffer(result.buffer);
1527
1129
  setCurrentToolCall(result.currentToolCall);
@@ -1536,8 +1138,7 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
1536
1138
  flushText,
1537
1139
  tools,
1538
1140
  options,
1539
- pipelineConfig,
1540
- maxReparses,
1141
+ parseOptions,
1541
1142
  setBuffer
1542
1143
  });
1543
1144
  setBuffer(result.buffer);
@@ -1554,43 +1155,12 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
1554
1155
  };
1555
1156
  }
1556
1157
  var xmlProtocol = (protocolOptions) => {
1557
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1558
- let pipelineConfig = protocolOptions == null ? void 0 : protocolOptions.pipeline;
1559
- const maxReparses = protocolOptions == null ? void 0 : protocolOptions.maxReparses;
1560
- if ((protocolOptions == null ? void 0 : protocolOptions.heuristics) && protocolOptions.heuristics.length > 0) {
1561
- const heuristicsConfig = {
1562
- preParse: [],
1563
- fallbackReparse: [],
1564
- postParse: []
1565
- };
1566
- for (const h of protocolOptions.heuristics) {
1567
- if (h.phase === "pre-parse") {
1568
- (_a = heuristicsConfig.preParse) == null ? void 0 : _a.push(h);
1569
- } else if (h.phase === "fallback-reparse") {
1570
- (_b = heuristicsConfig.fallbackReparse) == null ? void 0 : _b.push(h);
1571
- } else if (h.phase === "post-parse") {
1572
- (_c = heuristicsConfig.postParse) == null ? void 0 : _c.push(h);
1573
- }
1574
- }
1575
- if (pipelineConfig) {
1576
- pipelineConfig = {
1577
- preParse: [
1578
- ...(_d = pipelineConfig.preParse) != null ? _d : [],
1579
- ...(_e = heuristicsConfig.preParse) != null ? _e : []
1580
- ],
1581
- fallbackReparse: [
1582
- ...(_f = pipelineConfig.fallbackReparse) != null ? _f : [],
1583
- ...(_g = heuristicsConfig.fallbackReparse) != null ? _g : []
1584
- ],
1585
- postParse: [
1586
- ...(_h = pipelineConfig.postParse) != null ? _h : [],
1587
- ...(_i = heuristicsConfig.postParse) != null ? _i : []
1588
- ]
1589
- };
1590
- } else {
1591
- pipelineConfig = heuristicsConfig;
1592
- }
1593
- }
1158
+ var _a;
1159
+ const parseOptions = {
1160
+ repair: true,
1161
+ noChildNodes: [],
1162
+ ...(_a = protocolOptions == null ? void 0 : protocolOptions.parseOptions) != null ? _a : {}
1163
+ };
1594
1164
  return {
1595
1165
  formatTools({ tools, toolSystemPromptTemplate }) {
1596
1166
  return toolSystemPromptTemplate(tools || []);
@@ -1604,7 +1174,7 @@ var xmlProtocol = (protocolOptions) => {
1604
1174
  args = toolCall.input;
1605
1175
  }
1606
1176
  }
1607
- return (0, import_rxml2.stringify)(toolCall.toolName, args, {
1177
+ return (0, import_rxml.stringify)(toolCall.toolName, args, {
1608
1178
  suppressEmptyNode: false,
1609
1179
  format: true,
1610
1180
  minimalEscaping: true
@@ -1625,14 +1195,13 @@ var xmlProtocol = (protocolOptions) => {
1625
1195
  text: text.substring(currentIndex, tc.startIndex)
1626
1196
  });
1627
1197
  }
1628
- processToolCallWithPipeline({
1198
+ processToolCall({
1629
1199
  toolCall: tc,
1630
1200
  tools,
1631
1201
  options,
1632
1202
  text,
1633
1203
  processedElements,
1634
- pipelineConfig,
1635
- maxReparses
1204
+ parseOptions
1636
1205
  });
1637
1206
  currentIndex = tc.endIndex;
1638
1207
  }
@@ -1673,8 +1242,7 @@ var xmlProtocol = (protocolOptions) => {
1673
1242
  options,
1674
1243
  toolNames,
1675
1244
  flushText,
1676
- pipelineConfig,
1677
- maxReparses
1245
+ parseOptions
1678
1246
  );
1679
1247
  return new TransformStream({
1680
1248
  transform(chunk, controller) {
@@ -1724,8 +1292,8 @@ var xmlProtocol = (protocolOptions) => {
1724
1292
 
1725
1293
  // src/core/protocols/yaml-protocol.ts
1726
1294
  var import_yaml = __toESM(require("yaml"), 1);
1727
- var NAME_CHAR_RE3 = /[A-Za-z0-9_:-]/;
1728
- var WHITESPACE_REGEX3 = /\s/;
1295
+ var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
1296
+ var WHITESPACE_REGEX2 = /\s/;
1729
1297
  var LEADING_WHITESPACE_RE = /^(\s*)/;
1730
1298
  function findClosingTagEnd(text, contentStart, toolName) {
1731
1299
  let pos = contentStart;
@@ -1742,11 +1310,11 @@ function findClosingTagEnd(text, contentStart, toolName) {
1742
1310
  break;
1743
1311
  }
1744
1312
  let p = ltIdx + 2;
1745
- while (p < gtIdx && WHITESPACE_REGEX3.test(text[p])) {
1313
+ while (p < gtIdx && WHITESPACE_REGEX2.test(text[p])) {
1746
1314
  p++;
1747
1315
  }
1748
1316
  const nameStart = p;
1749
- while (p < gtIdx && NAME_CHAR_RE3.test(text.charAt(p))) {
1317
+ while (p < gtIdx && NAME_CHAR_RE2.test(text.charAt(p))) {
1750
1318
  p++;
1751
1319
  }
1752
1320
  const name = text.slice(nameStart, p);
@@ -1762,11 +1330,11 @@ function findClosingTagEnd(text, contentStart, toolName) {
1762
1330
  pos = gtIdx === -1 ? text.length : gtIdx + 1;
1763
1331
  } else {
1764
1332
  let p = ltIdx + 1;
1765
- while (p < text.length && WHITESPACE_REGEX3.test(text[p])) {
1333
+ while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
1766
1334
  p++;
1767
1335
  }
1768
1336
  const nameStart = p;
1769
- while (p < text.length && NAME_CHAR_RE3.test(text.charAt(p))) {
1337
+ while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
1770
1338
  p++;
1771
1339
  }
1772
1340
  const name = text.slice(nameStart, p);
@@ -1775,7 +1343,7 @@ function findClosingTagEnd(text, contentStart, toolName) {
1775
1343
  break;
1776
1344
  }
1777
1345
  let r = gtIdx - 1;
1778
- while (r >= nameStart && WHITESPACE_REGEX3.test(text[r])) {
1346
+ while (r >= nameStart && WHITESPACE_REGEX2.test(text[r])) {
1779
1347
  r--;
1780
1348
  }
1781
1349
  const selfClosing = text[r] === "/";
@@ -2280,7 +1848,7 @@ function hasInputProperty(obj) {
2280
1848
 
2281
1849
  // src/generate-handler.ts
2282
1850
  var import_provider_utils = require("@ai-sdk/provider-utils");
2283
- var import_rxml3 = require("@ai-sdk-tool/rxml");
1851
+ var import_schema_coerce = require("@ai-sdk-tool/schema-coerce");
2284
1852
  function parseToolChoiceJson(text, providerOptions) {
2285
1853
  var _a;
2286
1854
  try {
@@ -2442,7 +2010,7 @@ function fixToolCallWithSchema(part, tools) {
2442
2010
  args = part.input;
2443
2011
  }
2444
2012
  const schema = (_a = tools.find((t) => t.name === part.toolName)) == null ? void 0 : _a.inputSchema;
2445
- const coerced = (0, import_rxml3.coerceBySchema)(args, schema);
2013
+ const coerced = (0, import_schema_coerce.coerceBySchema)(args, schema);
2446
2014
  return {
2447
2015
  ...part,
2448
2016
  input: JSON.stringify(coerced != null ? coerced : {})
@@ -2575,29 +2143,230 @@ function formatXmlNode(tagName, value, depth) {
2575
2143
  }
2576
2144
 
2577
2145
  // src/core/prompts/xml-system-prompt.ts
2146
+ var import_dedent = __toESM(require("dedent"), 1);
2578
2147
  function xmlSystemPromptTemplate(tools) {
2579
- const toolsJson = JSON.stringify(tools);
2580
- return `# Tools
2581
-
2582
- You may call one or more functions to assist with the user query.
2583
-
2584
- You are provided with function signatures within <tools></tools> XML tags:
2585
- <tools>${toolsJson}</tools>
2586
-
2587
- # Rules
2588
- - Use exactly one XML element whose tag name is the function name.
2589
- - Put each parameter as a child element.
2590
- - Values must follow the schema exactly (numbers, arrays, objects, enums \u2192 copy as-is).
2591
- - Do not add or remove functions or parameters.
2592
- - Each required parameter must appear once.
2593
- - Output nothing before or after the function call.
2594
- - After calling a tool, you will receive a response in the format: <tool_response><tool_name>NAME</tool_name><result>RESULT</result></tool_response>. Use this result to answer the user.
2595
-
2596
- # Example
2597
- <get_weather>
2598
- <location>New York</location>
2599
- <unit>celsius</unit>
2600
- </get_weather>`;
2148
+ const toolsText = renderToolsForXmlPrompt(tools);
2149
+ const header = import_dedent.default`
2150
+ # Tools
2151
+ You may call one or more functions to assist with the user query.
2152
+ `;
2153
+ const definitions = [
2154
+ "You have access to the following functions:",
2155
+ "<tools>",
2156
+ toolsText,
2157
+ "</tools>"
2158
+ ].join("\n");
2159
+ const rules = import_dedent.default`
2160
+ <rules>
2161
+ - Use exactly one XML element whose tag name is the function name.
2162
+ - Put each parameter as a child element.
2163
+ - Values must follow the schema exactly (numbers, arrays, objects, enums copy as-is).
2164
+ - Do not add or remove functions or parameters.
2165
+ - Each required parameter must appear once.
2166
+ - Output nothing before or after the function call.
2167
+ - It is also possible to call multiple types of functions in one turn or to call a single function multiple times.
2168
+ </rules>
2169
+ `;
2170
+ const examples = import_dedent.default`
2171
+ For each function call, output the function name and parameter in the following format:
2172
+ <example_function_name>
2173
+ <example_parameter_1>value_1</example_parameter_1>
2174
+ <example_parameter_2>This is the value for the second parameter
2175
+ that can span
2176
+ multiple lines</example_parameter_2>
2177
+ </example_function_name>
2178
+ `;
2179
+ return [header, definitions, rules, examples].join("\n\n");
2180
+ }
2181
+ var INDENT = " ";
2182
+ function renderToolsForXmlPrompt(tools) {
2183
+ if (!tools.length) {
2184
+ return "none";
2185
+ }
2186
+ return tools.map(renderToolForXmlPrompt).join("\n\n");
2187
+ }
2188
+ function renderToolForXmlPrompt(tool) {
2189
+ const lines = [`name: ${tool.name}`];
2190
+ if (tool.description) {
2191
+ lines.push(`description: ${tool.description}`);
2192
+ }
2193
+ lines.push("parameters:");
2194
+ const normalizedSchema = normalizeSchema(tool.inputSchema);
2195
+ lines.push(...renderParametersSummary(normalizedSchema, 1));
2196
+ lines.push(`schema: ${stringifySchema(normalizedSchema)}`);
2197
+ return lines.join("\n");
2198
+ }
2199
+ function normalizeSchema(schema) {
2200
+ if (typeof schema === "string") {
2201
+ try {
2202
+ return JSON.parse(schema);
2203
+ } catch (e) {
2204
+ return { type: "string", const: schema };
2205
+ }
2206
+ }
2207
+ return schema;
2208
+ }
2209
+ function renderParametersSummary(schema, indentLevel) {
2210
+ var _a, _b;
2211
+ const indent = INDENT.repeat(indentLevel);
2212
+ if (schema === void 0 || schema === null) {
2213
+ return [`${indent}(none)`];
2214
+ }
2215
+ if (schema === true) {
2216
+ return [`${indent}(any)`];
2217
+ }
2218
+ if (schema === false) {
2219
+ return [`${indent}(no valid parameters)`];
2220
+ }
2221
+ if (typeof schema !== "object") {
2222
+ return [`${indent}- value (${String(schema)})`];
2223
+ }
2224
+ const schemaType = [];
2225
+ if (Array.isArray(schema.type)) {
2226
+ schemaType.push(...schema.type);
2227
+ } else if (schema.type) {
2228
+ schemaType.push(schema.type);
2229
+ }
2230
+ const isObjectLike = schemaType.includes("object") || !!schema.properties;
2231
+ if (isObjectLike) {
2232
+ const properties = (_a = schema.properties) != null ? _a : {};
2233
+ const requiredSet = new Set((_b = schema.required) != null ? _b : []);
2234
+ const propertyNames = Object.keys(properties).sort();
2235
+ if (propertyNames.length === 0) {
2236
+ return [`${indent}(no named parameters)`];
2237
+ }
2238
+ const lines = [];
2239
+ for (const propName of propertyNames) {
2240
+ const propSchema = properties[propName];
2241
+ lines.push(
2242
+ renderPropertySummaryLine({
2243
+ indent,
2244
+ propName,
2245
+ propSchema,
2246
+ required: requiredSet.has(propName)
2247
+ })
2248
+ );
2249
+ }
2250
+ return lines.length ? lines : [`${indent}(no parameters)`];
2251
+ }
2252
+ return [`${indent}- value (${summarizeType(schema)})`];
2253
+ }
2254
+ function renderPropertySummaryLine({
2255
+ indent,
2256
+ propName,
2257
+ propSchema,
2258
+ required
2259
+ }) {
2260
+ const typeLabel = summarizeType(propSchema);
2261
+ const requiredLabel = required ? "required" : "optional";
2262
+ const extras = collectPropertyExtras(propSchema);
2263
+ const extraText = extras.length ? ` - ${extras.join("; ")}` : "";
2264
+ return `${indent}- ${propName} (${typeLabel}, ${requiredLabel})${extraText}`;
2265
+ }
2266
+ function collectPropertyExtras(propSchema) {
2267
+ if (!propSchema || typeof propSchema !== "object") {
2268
+ return [];
2269
+ }
2270
+ const extras = [];
2271
+ if (propSchema.enum) {
2272
+ extras.push(`enum: ${formatEnumForSummary(propSchema.enum)}`);
2273
+ }
2274
+ if (propSchema.default !== void 0) {
2275
+ extras.push(`default: ${formatValue(propSchema.default)}`);
2276
+ }
2277
+ if (propSchema.description) {
2278
+ extras.push(propSchema.description);
2279
+ }
2280
+ return extras;
2281
+ }
2282
+ function summarizeType(schema) {
2283
+ var _a;
2284
+ if (schema === void 0 || schema === null) {
2285
+ return "unknown";
2286
+ }
2287
+ if (schema === true) {
2288
+ return "any";
2289
+ }
2290
+ if (schema === false) {
2291
+ return "never";
2292
+ }
2293
+ if (typeof schema !== "object") {
2294
+ return String(schema);
2295
+ }
2296
+ const schemaType = schema.type;
2297
+ let baseType = "";
2298
+ if (Array.isArray(schemaType) && schemaType.length) {
2299
+ baseType = schemaType.join(" | ");
2300
+ } else if (typeof schemaType === "string") {
2301
+ baseType = schemaType;
2302
+ } else if (schema.enum) {
2303
+ const inferred = Array.from(
2304
+ new Set(schema.enum.map((value) => typeof value))
2305
+ );
2306
+ if (inferred.length === 1) {
2307
+ baseType = (_a = inferred[0]) != null ? _a : "";
2308
+ }
2309
+ } else if (schema.const !== void 0) {
2310
+ baseType = typeof schema.const;
2311
+ }
2312
+ if (!baseType) {
2313
+ baseType = "any";
2314
+ }
2315
+ if (baseType === "array" && schema.items) {
2316
+ const itemType = Array.isArray(schema.items) ? schema.items.map((item) => summarizeType(item)).join(" | ") : summarizeType(schema.items);
2317
+ return `array<${itemType}>`;
2318
+ }
2319
+ if (baseType === "string" && schema.format) {
2320
+ return `string (${schema.format})`;
2321
+ }
2322
+ return baseType;
2323
+ }
2324
+ var ENUM_MAX_INLINE = 6;
2325
+ var ENUM_PREVIEW_LIMIT = 5;
2326
+ function formatEnumForSummary(values) {
2327
+ if (values.length <= ENUM_MAX_INLINE) {
2328
+ return formatValue(values);
2329
+ }
2330
+ const preview = values.slice(0, ENUM_PREVIEW_LIMIT).map((value) => formatValue(value));
2331
+ return `[${preview.join(", ")}, ... (${values.length} total)]`;
2332
+ }
2333
+ function formatValue(value) {
2334
+ if (typeof value === "string") {
2335
+ return JSON.stringify(value);
2336
+ }
2337
+ if (typeof value === "number" || typeof value === "boolean") {
2338
+ return String(value);
2339
+ }
2340
+ if (value === null) {
2341
+ return "null";
2342
+ }
2343
+ if (Array.isArray(value)) {
2344
+ return `[${value.map(formatValue).join(", ")}]`;
2345
+ }
2346
+ return JSON.stringify(value);
2347
+ }
2348
+ function stringifySchema(schema) {
2349
+ if (schema === void 0) {
2350
+ return "null";
2351
+ }
2352
+ return JSON.stringify(stripSchemaKeys(schema));
2353
+ }
2354
+ function stripSchemaKeys(value) {
2355
+ if (Array.isArray(value)) {
2356
+ return value.map((entry) => stripSchemaKeys(entry));
2357
+ }
2358
+ if (value && typeof value === "object") {
2359
+ const record = value;
2360
+ const cleaned = {};
2361
+ for (const [key, entry] of Object.entries(record)) {
2362
+ if (key === "$schema") {
2363
+ continue;
2364
+ }
2365
+ cleaned[key] = stripSchemaKeys(entry);
2366
+ }
2367
+ return cleaned;
2368
+ }
2369
+ return value;
2601
2370
  }
2602
2371
 
2603
2372
  // src/core/prompts/yaml-system-prompt.ts
@@ -3106,20 +2875,12 @@ function createToolMiddleware({
3106
2875
  const resolvedProtocol = isTCMProtocolFactory(protocol) ? protocol() : protocol;
3107
2876
  return {
3108
2877
  specificationVersion: "v3",
3109
- wrapStream: ({ doStream, doGenerate, params }) => {
3110
- if (isToolChoiceActive(params)) {
3111
- return toolChoiceStream({
3112
- doGenerate,
3113
- options: extractOnErrorOption(params.providerOptions)
3114
- });
3115
- }
3116
- return wrapStream({
3117
- protocol: resolvedProtocol,
3118
- doStream,
3119
- doGenerate,
3120
- params
3121
- });
3122
- },
2878
+ wrapStream: ({ doStream, doGenerate, params }) => wrapStream({
2879
+ protocol: resolvedProtocol,
2880
+ doStream,
2881
+ doGenerate,
2882
+ params
2883
+ }),
3123
2884
  wrapGenerate: async ({ doGenerate, params }) => wrapGenerate({
3124
2885
  protocol: resolvedProtocol,
3125
2886
  doGenerate,