@ai-sdk-tool/parser 3.1.3 → 3.2.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.
@@ -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,48 @@ 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/;
588
+ var REGEX_ESCAPE_RE = /[.*+?^${}()|[\]\\]/g;
589
+ function escapeRegExp2(value) {
590
+ return value.replace(REGEX_ESCAPE_RE, "\\$&");
591
+ }
1065
592
  function getToolSchema(tools, toolName) {
1066
593
  var _a;
1067
594
  return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
1068
595
  }
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;
596
+ function processToolCall(params) {
597
+ var _a, _b;
598
+ const { toolCall, tools, options, text, processedElements, parseOptions } = params;
1115
599
  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) {
600
+ const parseConfig = {
601
+ ...parseOptions != null ? parseOptions : {},
602
+ onError: (_a = options == null ? void 0 : options.onError) != null ? _a : parseOptions == null ? void 0 : parseOptions.onError
603
+ };
604
+ try {
605
+ const parsed = (0, import_rxml.parse)(toolCall.content, toolSchema, parseConfig);
1127
606
  processedElements.push({
1128
607
  type: "tool-call",
1129
608
  toolCallId: generateId(),
1130
609
  toolName: toolCall.toolName,
1131
- input: JSON.stringify(result.parsed)
610
+ input: JSON.stringify(parsed)
1132
611
  });
1133
- } else {
612
+ } catch (error) {
1134
613
  const originalCallText = text.substring(
1135
614
  toolCall.startIndex,
1136
615
  toolCall.endIndex
1137
616
  );
1138
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
617
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
1139
618
  options,
1140
619
  `Could not process XML tool call: ${toolCall.toolName}`,
1141
- { toolCall: originalCallText, error: result.errors[0] }
620
+ { toolCall: originalCallText, error }
1142
621
  );
1143
622
  processedElements.push({ type: "text", text: originalCallText });
1144
623
  }
1145
624
  }
1146
625
  function handleStreamingToolCallEnd(params) {
1147
- var _a;
626
+ var _a, _b;
1148
627
  const {
1149
628
  toolContent,
1150
629
  currentToolCall,
@@ -1152,51 +631,27 @@ function handleStreamingToolCallEnd(params) {
1152
631
  options,
1153
632
  ctrl,
1154
633
  flushText,
1155
- pipelineConfig,
1156
- maxReparses
634
+ parseOptions
1157
635
  } = params;
1158
636
  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
- }
637
+ const parseConfig = {
638
+ ...parseOptions != null ? parseOptions : {},
639
+ onError: (_a = options == null ? void 0 : options.onError) != null ? _a : parseOptions == null ? void 0 : parseOptions.onError
640
+ };
1188
641
  flushText(ctrl);
1189
- if (parsedResult !== null) {
642
+ try {
643
+ const parsedResult = (0, import_rxml.parse)(toolContent, toolSchema, parseConfig);
1190
644
  ctrl.enqueue({
1191
645
  type: "tool-call",
1192
646
  toolCallId: generateId(),
1193
647
  toolName: currentToolCall.name,
1194
648
  input: JSON.stringify(parsedResult)
1195
649
  });
1196
- } else {
650
+ } catch (error) {
1197
651
  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
652
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
653
+ toolCall: original,
654
+ error
1200
655
  });
1201
656
  flushText(ctrl, original);
1202
657
  }
@@ -1235,11 +690,11 @@ function consumeClosingTag(text, lt) {
1235
690
  }
1236
691
  function consumeOpenTag(text, lt) {
1237
692
  let p = lt + 1;
1238
- while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
693
+ while (p < text.length && WHITESPACE_REGEX.test(text[p])) {
1239
694
  p += 1;
1240
695
  }
1241
696
  const nameStart = p;
1242
- while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
697
+ while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
1243
698
  p += 1;
1244
699
  }
1245
700
  const name = text.slice(nameStart, p);
@@ -1248,7 +703,7 @@ function consumeOpenTag(text, lt) {
1248
703
  return null;
1249
704
  }
1250
705
  let r = q - 1;
1251
- while (r >= nameStart && WHITESPACE_REGEX2.test(text[r])) {
706
+ while (r >= nameStart && WHITESPACE_REGEX.test(text[r])) {
1252
707
  r -= 1;
1253
708
  }
1254
709
  const selfClosing = text[r] === "/";
@@ -1277,11 +732,11 @@ function nextTagToken(text, fromPos) {
1277
732
  if (next === "/") {
1278
733
  const closing = consumeClosingTag(text, lt);
1279
734
  let p = lt + 2;
1280
- while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
735
+ while (p < text.length && WHITESPACE_REGEX.test(text[p])) {
1281
736
  p += 1;
1282
737
  }
1283
738
  const nameStart = p;
1284
- while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
739
+ while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
1285
740
  p += 1;
1286
741
  }
1287
742
  const name = text.slice(nameStart, p);
@@ -1298,49 +753,90 @@ function nextTagToken(text, fromPos) {
1298
753
  nextPos: open.nextPos
1299
754
  };
1300
755
  }
756
+ function findNextToolTag(text, searchIndex, startTag, selfTag) {
757
+ const openIdx = text.indexOf(startTag, searchIndex);
758
+ const selfIdx = text.indexOf(selfTag, searchIndex);
759
+ if (openIdx === -1 && selfIdx === -1) {
760
+ return null;
761
+ }
762
+ const isSelfClosing = selfIdx !== -1 && (openIdx === -1 || selfIdx < openIdx);
763
+ return {
764
+ tagStart: isSelfClosing ? selfIdx : openIdx,
765
+ isSelfClosing
766
+ };
767
+ }
768
+ function findLastCloseTagStart(segment, toolName) {
769
+ const closeTagPattern = new RegExp(
770
+ `</\\s*${escapeRegExp2(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, selfTag) {
785
+ const endIndex = tagStart + selfTag.length;
786
+ toolCalls.push({
787
+ toolName,
788
+ startIndex: tagStart,
789
+ endIndex,
790
+ content: "",
791
+ segment: text.substring(tagStart, endIndex)
792
+ });
793
+ return endIndex;
794
+ }
795
+ function appendOpenToolCallIfComplete(toolCalls, text, toolName, tagStart, startTag) {
796
+ const contentStart = tagStart + startTag.length;
797
+ const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
798
+ if (fullTagEnd === -1 || fullTagEnd <= contentStart) {
799
+ return contentStart;
800
+ }
801
+ const segment = text.substring(tagStart, fullTagEnd);
802
+ const closeTagStart = findLastCloseTagStart(segment, toolName);
803
+ const inner = closeTagStart === -1 ? segment.slice(startTag.length) : segment.slice(startTag.length, closeTagStart);
804
+ toolCalls.push({
805
+ toolName,
806
+ startIndex: tagStart,
807
+ endIndex: fullTagEnd,
808
+ content: inner,
809
+ segment
810
+ });
811
+ return fullTagEnd;
812
+ }
1301
813
  function findToolCallsForName(text, toolName) {
1302
- var _a;
1303
814
  const toolCalls = [];
815
+ const startTag = `<${toolName}>`;
816
+ const selfTag = `<${toolName}/>`;
1304
817
  let searchIndex = 0;
1305
818
  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) {
819
+ const match = findNextToolTag(text, searchIndex, startTag, selfTag);
820
+ if (match === null) {
1311
821
  break;
1312
822
  }
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({
823
+ if (match.isSelfClosing) {
824
+ searchIndex = pushSelfClosingToolCall(
825
+ toolCalls,
1319
826
  toolName,
1320
- startIndex: tagStart,
1321
- endIndex,
1322
- content: "",
1323
- segment
1324
- });
1325
- searchIndex = endIndex;
827
+ text,
828
+ match.tagStart,
829
+ selfTag
830
+ );
1326
831
  continue;
1327
832
  }
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
- }
833
+ searchIndex = appendOpenToolCallIfComplete(
834
+ toolCalls,
835
+ text,
836
+ toolName,
837
+ match.tagStart,
838
+ startTag
839
+ );
1344
840
  }
1345
841
  return toolCalls;
1346
842
  }
@@ -1417,16 +913,20 @@ function processToolCallInBuffer(params) {
1417
913
  controller,
1418
914
  flushText,
1419
915
  setBuffer,
1420
- pipelineConfig,
1421
- maxReparses
916
+ parseOptions
1422
917
  } = params;
1423
- const endTag = `</${currentToolCall.name}>`;
1424
- const endIdx = buffer.indexOf(endTag);
1425
- if (endIdx === -1) {
918
+ const endTagPattern = new RegExp(
919
+ `</\\s*${escapeRegExp2(currentToolCall.name)}\\s*>`
920
+ );
921
+ const endMatch = endTagPattern.exec(buffer);
922
+ if (!endMatch || endMatch.index === void 0) {
1426
923
  return { buffer, currentToolCall, shouldBreak: true };
1427
924
  }
925
+ const endIdx = endMatch.index;
926
+ const endPos = endIdx + endMatch[0].length;
1428
927
  const content = buffer.substring(0, endIdx);
1429
- setBuffer(buffer.substring(endIdx + endTag.length));
928
+ const remainder = buffer.substring(endPos);
929
+ setBuffer(remainder);
1430
930
  handleStreamingToolCallEnd({
1431
931
  toolContent: content,
1432
932
  currentToolCall,
@@ -1434,11 +934,10 @@ function processToolCallInBuffer(params) {
1434
934
  options,
1435
935
  ctrl: controller,
1436
936
  flushText,
1437
- pipelineConfig,
1438
- maxReparses
937
+ parseOptions
1439
938
  });
1440
939
  return {
1441
- buffer: buffer.substring(endIdx + endTag.length),
940
+ buffer: remainder,
1442
941
  currentToolCall: null,
1443
942
  shouldBreak: false
1444
943
  };
@@ -1451,8 +950,7 @@ function processNoToolCallInBuffer(params) {
1451
950
  flushText,
1452
951
  tools,
1453
952
  options,
1454
- pipelineConfig,
1455
- maxReparses,
953
+ parseOptions,
1456
954
  setBuffer
1457
955
  } = params;
1458
956
  const {
@@ -1487,8 +985,7 @@ function processNoToolCallInBuffer(params) {
1487
985
  options,
1488
986
  ctrl: controller,
1489
987
  flushText,
1490
- pipelineConfig,
1491
- maxReparses
988
+ parseOptions
1492
989
  });
1493
990
  return {
1494
991
  buffer: newBuffer2,
@@ -1507,7 +1004,7 @@ function processNoToolCallInBuffer(params) {
1507
1004
  shouldContinue: true
1508
1005
  };
1509
1006
  }
1510
- function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, pipelineConfig, maxReparses) {
1007
+ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions) {
1511
1008
  return (controller) => {
1512
1009
  while (true) {
1513
1010
  const currentToolCall = getCurrentToolCall();
@@ -1520,8 +1017,7 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
1520
1017
  controller,
1521
1018
  flushText,
1522
1019
  setBuffer,
1523
- pipelineConfig,
1524
- maxReparses
1020
+ parseOptions
1525
1021
  });
1526
1022
  setBuffer(result.buffer);
1527
1023
  setCurrentToolCall(result.currentToolCall);
@@ -1536,8 +1032,7 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
1536
1032
  flushText,
1537
1033
  tools,
1538
1034
  options,
1539
- pipelineConfig,
1540
- maxReparses,
1035
+ parseOptions,
1541
1036
  setBuffer
1542
1037
  });
1543
1038
  setBuffer(result.buffer);
@@ -1554,43 +1049,12 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
1554
1049
  };
1555
1050
  }
1556
1051
  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
- }
1052
+ var _a;
1053
+ const parseOptions = {
1054
+ repair: true,
1055
+ noChildNodes: [],
1056
+ ...(_a = protocolOptions == null ? void 0 : protocolOptions.parseOptions) != null ? _a : {}
1057
+ };
1594
1058
  return {
1595
1059
  formatTools({ tools, toolSystemPromptTemplate }) {
1596
1060
  return toolSystemPromptTemplate(tools || []);
@@ -1604,7 +1068,7 @@ var xmlProtocol = (protocolOptions) => {
1604
1068
  args = toolCall.input;
1605
1069
  }
1606
1070
  }
1607
- return (0, import_rxml2.stringify)(toolCall.toolName, args, {
1071
+ return (0, import_rxml.stringify)(toolCall.toolName, args, {
1608
1072
  suppressEmptyNode: false,
1609
1073
  format: true,
1610
1074
  minimalEscaping: true
@@ -1625,14 +1089,13 @@ var xmlProtocol = (protocolOptions) => {
1625
1089
  text: text.substring(currentIndex, tc.startIndex)
1626
1090
  });
1627
1091
  }
1628
- processToolCallWithPipeline({
1092
+ processToolCall({
1629
1093
  toolCall: tc,
1630
1094
  tools,
1631
1095
  options,
1632
1096
  text,
1633
1097
  processedElements,
1634
- pipelineConfig,
1635
- maxReparses
1098
+ parseOptions
1636
1099
  });
1637
1100
  currentIndex = tc.endIndex;
1638
1101
  }
@@ -1673,8 +1136,7 @@ var xmlProtocol = (protocolOptions) => {
1673
1136
  options,
1674
1137
  toolNames,
1675
1138
  flushText,
1676
- pipelineConfig,
1677
- maxReparses
1139
+ parseOptions
1678
1140
  );
1679
1141
  return new TransformStream({
1680
1142
  transform(chunk, controller) {
@@ -1724,8 +1186,8 @@ var xmlProtocol = (protocolOptions) => {
1724
1186
 
1725
1187
  // src/core/protocols/yaml-protocol.ts
1726
1188
  var import_yaml = __toESM(require("yaml"), 1);
1727
- var NAME_CHAR_RE3 = /[A-Za-z0-9_:-]/;
1728
- var WHITESPACE_REGEX3 = /\s/;
1189
+ var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
1190
+ var WHITESPACE_REGEX2 = /\s/;
1729
1191
  var LEADING_WHITESPACE_RE = /^(\s*)/;
1730
1192
  function findClosingTagEnd(text, contentStart, toolName) {
1731
1193
  let pos = contentStart;
@@ -1742,11 +1204,11 @@ function findClosingTagEnd(text, contentStart, toolName) {
1742
1204
  break;
1743
1205
  }
1744
1206
  let p = ltIdx + 2;
1745
- while (p < gtIdx && WHITESPACE_REGEX3.test(text[p])) {
1207
+ while (p < gtIdx && WHITESPACE_REGEX2.test(text[p])) {
1746
1208
  p++;
1747
1209
  }
1748
1210
  const nameStart = p;
1749
- while (p < gtIdx && NAME_CHAR_RE3.test(text.charAt(p))) {
1211
+ while (p < gtIdx && NAME_CHAR_RE2.test(text.charAt(p))) {
1750
1212
  p++;
1751
1213
  }
1752
1214
  const name = text.slice(nameStart, p);
@@ -1762,11 +1224,11 @@ function findClosingTagEnd(text, contentStart, toolName) {
1762
1224
  pos = gtIdx === -1 ? text.length : gtIdx + 1;
1763
1225
  } else {
1764
1226
  let p = ltIdx + 1;
1765
- while (p < text.length && WHITESPACE_REGEX3.test(text[p])) {
1227
+ while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
1766
1228
  p++;
1767
1229
  }
1768
1230
  const nameStart = p;
1769
- while (p < text.length && NAME_CHAR_RE3.test(text.charAt(p))) {
1231
+ while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
1770
1232
  p++;
1771
1233
  }
1772
1234
  const name = text.slice(nameStart, p);
@@ -1775,7 +1237,7 @@ function findClosingTagEnd(text, contentStart, toolName) {
1775
1237
  break;
1776
1238
  }
1777
1239
  let r = gtIdx - 1;
1778
- while (r >= nameStart && WHITESPACE_REGEX3.test(text[r])) {
1240
+ while (r >= nameStart && WHITESPACE_REGEX2.test(text[r])) {
1779
1241
  r--;
1780
1242
  }
1781
1243
  const selfClosing = text[r] === "/";
@@ -2280,7 +1742,7 @@ function hasInputProperty(obj) {
2280
1742
 
2281
1743
  // src/generate-handler.ts
2282
1744
  var import_provider_utils = require("@ai-sdk/provider-utils");
2283
- var import_rxml3 = require("@ai-sdk-tool/rxml");
1745
+ var import_schema_coerce = require("@ai-sdk-tool/schema-coerce");
2284
1746
  function parseToolChoiceJson(text, providerOptions) {
2285
1747
  var _a;
2286
1748
  try {
@@ -2442,7 +1904,7 @@ function fixToolCallWithSchema(part, tools) {
2442
1904
  args = part.input;
2443
1905
  }
2444
1906
  const schema = (_a = tools.find((t) => t.name === part.toolName)) == null ? void 0 : _a.inputSchema;
2445
- const coerced = (0, import_rxml3.coerceBySchema)(args, schema);
1907
+ const coerced = (0, import_schema_coerce.coerceBySchema)(args, schema);
2446
1908
  return {
2447
1909
  ...part,
2448
1910
  input: JSON.stringify(coerced != null ? coerced : {})
@@ -3106,20 +2568,12 @@ function createToolMiddleware({
3106
2568
  const resolvedProtocol = isTCMProtocolFactory(protocol) ? protocol() : protocol;
3107
2569
  return {
3108
2570
  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
- },
2571
+ wrapStream: ({ doStream, doGenerate, params }) => wrapStream({
2572
+ protocol: resolvedProtocol,
2573
+ doStream,
2574
+ doGenerate,
2575
+ params
2576
+ }),
3123
2577
  wrapGenerate: async ({ doGenerate, params }) => wrapGenerate({
3124
2578
  protocol: resolvedProtocol,
3125
2579
  doGenerate,