@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.
@@ -1,473 +1,6 @@
1
1
  // src/index.ts
2
2
  export * from "@ai-sdk-tool/rjson";
3
3
 
4
- // src/core/heuristics/engine.ts
5
- function applyRawSegmentUpdate(current, result) {
6
- if (result.rawSegment !== void 0) {
7
- return { ...current, rawSegment: result.rawSegment };
8
- }
9
- return current;
10
- }
11
- function applyParsedUpdate(current, result) {
12
- if (result.parsed !== void 0) {
13
- return { ...current, parsed: result.parsed };
14
- }
15
- return current;
16
- }
17
- function applyWarningsUpdate(current, result) {
18
- var _a, _b;
19
- if (result.warnings && result.warnings.length > 0) {
20
- const meta = (_a = current.meta) != null ? _a : {};
21
- const existingWarnings = (_b = meta.warnings) != null ? _b : [];
22
- return {
23
- ...current,
24
- meta: { ...meta, warnings: [...existingWarnings, ...result.warnings] }
25
- };
26
- }
27
- return current;
28
- }
29
- function attemptReparse(current, result, reparseCount, maxReparses, parse3) {
30
- if (!result.reparse || result.rawSegment === void 0 || reparseCount >= maxReparses) {
31
- return { state: current, newCount: reparseCount };
32
- }
33
- try {
34
- const reparsed = parse3(result.rawSegment, current.schema);
35
- return {
36
- state: { ...current, parsed: reparsed, errors: [] },
37
- newCount: reparseCount + 1
38
- };
39
- } catch (error) {
40
- return {
41
- state: { ...current, errors: [...current.errors, error] },
42
- newCount: reparseCount + 1
43
- };
44
- }
45
- }
46
- function executePhase(ctx, heuristics, options) {
47
- var _a;
48
- let current = ctx;
49
- let reparseCount = 0;
50
- const maxReparses = (_a = options.maxReparses) != null ? _a : 2;
51
- for (const heuristic of heuristics) {
52
- if (!heuristic.applies(current)) {
53
- continue;
54
- }
55
- const result = heuristic.run(current);
56
- current = applyRawSegmentUpdate(current, result);
57
- current = applyParsedUpdate(current, result);
58
- current = applyWarningsUpdate(current, result);
59
- const reparseResult = attemptReparse(
60
- current,
61
- result,
62
- reparseCount,
63
- maxReparses,
64
- options.parse
65
- );
66
- current = reparseResult.state;
67
- reparseCount = reparseResult.newCount;
68
- if (result.stop) {
69
- break;
70
- }
71
- }
72
- return current;
73
- }
74
- function applyHeuristicPipeline(ctx, config, options) {
75
- let current = ctx;
76
- if (config.preParse && config.preParse.length > 0) {
77
- current = executePhase(current, config.preParse, options);
78
- }
79
- if (current.parsed === null && current.errors.length === 0) {
80
- try {
81
- const parsed = options.parse(current.rawSegment, current.schema);
82
- current = { ...current, parsed, errors: [] };
83
- } catch (error) {
84
- current = { ...current, errors: [error] };
85
- }
86
- }
87
- if (current.errors.length > 0 && config.fallbackReparse && config.fallbackReparse.length > 0) {
88
- current = executePhase(current, config.fallbackReparse, options);
89
- }
90
- if (current.parsed !== null && config.postParse && config.postParse.length > 0) {
91
- current = executePhase(current, config.postParse, options);
92
- }
93
- return current;
94
- }
95
- function createIntermediateCall(toolName, rawSegment, schema) {
96
- return {
97
- toolName,
98
- schema,
99
- rawSegment,
100
- parsed: null,
101
- errors: [],
102
- meta: { originalContent: rawSegment }
103
- };
104
- }
105
- function mergePipelineConfigs(...configs) {
106
- var _a, _b, _c;
107
- const result = {
108
- preParse: [],
109
- fallbackReparse: [],
110
- postParse: []
111
- };
112
- for (const config of configs) {
113
- if (config.preParse) {
114
- result.preParse = [...(_a = result.preParse) != null ? _a : [], ...config.preParse];
115
- }
116
- if (config.fallbackReparse) {
117
- result.fallbackReparse = [
118
- ...(_b = result.fallbackReparse) != null ? _b : [],
119
- ...config.fallbackReparse
120
- ];
121
- }
122
- if (config.postParse) {
123
- result.postParse = [...(_c = result.postParse) != null ? _c : [], ...config.postParse];
124
- }
125
- }
126
- return result;
127
- }
128
-
129
- // src/core/heuristics/xml-defaults.ts
130
- import { parse, unwrapJsonSchema } from "@ai-sdk-tool/rxml";
131
- var MALFORMED_CLOSE_RE_G = /<\/\s+([A-Za-z0-9_:-]+)\s*>/g;
132
- var MALFORMED_CLOSE_RE = /<\/\s+([A-Za-z0-9_:-]+)\s*>/;
133
- var STATUS_TO_STEP_BOUNDARY_RE = /<\/status>\s*<step>/g;
134
- var WHITESPACE_REGEX = /\s/;
135
- var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
136
- var NAME_START_CHAR_RE = /[A-Za-z_:]/;
137
- var STEP_TAG_RE = /<step>([\s\S]*?)<\/step>/i;
138
- var STATUS_TAG_RE = /<status>([\s\S]*?)<\/status>/i;
139
- var normalizeCloseTagsHeuristic = {
140
- id: "normalize-close-tags",
141
- phase: "pre-parse",
142
- applies: () => true,
143
- run: (ctx) => {
144
- const normalized = ctx.rawSegment.replace(MALFORMED_CLOSE_RE_G, "</$1>");
145
- if (normalized !== ctx.rawSegment) {
146
- return { rawSegment: normalized };
147
- }
148
- return {};
149
- }
150
- };
151
- var escapeInvalidLtHeuristic = {
152
- id: "escape-invalid-lt",
153
- phase: "pre-parse",
154
- applies: () => true,
155
- run: (ctx) => {
156
- const escaped = escapeInvalidLt(ctx.rawSegment);
157
- if (escaped !== ctx.rawSegment) {
158
- return { rawSegment: escaped };
159
- }
160
- return {};
161
- }
162
- };
163
- var balanceTagsHeuristic = {
164
- id: "balance-tags",
165
- phase: "fallback-reparse",
166
- applies: (ctx) => {
167
- var _a;
168
- const original = ((_a = ctx.meta) == null ? void 0 : _a.originalContent) || ctx.rawSegment;
169
- const normalized = original.replace(MALFORMED_CLOSE_RE_G, "</$1>");
170
- const balanced = balanceTags(original);
171
- const hasMalformedClose = MALFORMED_CLOSE_RE.test(original);
172
- if (!hasMalformedClose && balanced.length > normalized.length) {
173
- return false;
174
- }
175
- return balanced !== normalized;
176
- },
177
- run: (ctx) => {
178
- var _a;
179
- const original = ((_a = ctx.meta) == null ? void 0 : _a.originalContent) || ctx.rawSegment;
180
- const balanced = balanceTags(original);
181
- const escaped = escapeInvalidLt(balanced);
182
- return { rawSegment: escaped, reparse: true };
183
- }
184
- };
185
- var dedupeShellStringTagsHeuristic = {
186
- id: "dedupe-shell-string-tags",
187
- phase: "fallback-reparse",
188
- applies: (ctx) => shouldDeduplicateStringTags(ctx.schema),
189
- run: (ctx) => {
190
- const names = getStringPropertyNames(ctx.schema);
191
- let deduped = ctx.rawSegment;
192
- for (const key of names) {
193
- deduped = dedupeSingleTag(deduped, key);
194
- }
195
- if (deduped !== ctx.rawSegment) {
196
- return { rawSegment: deduped, reparse: true };
197
- }
198
- return {};
199
- }
200
- };
201
- var repairAgainstSchemaHeuristic = {
202
- id: "repair-against-schema",
203
- phase: "post-parse",
204
- applies: (ctx) => ctx.parsed !== null && typeof ctx.parsed === "object",
205
- run: (ctx) => {
206
- const repaired = repairParsedAgainstSchema(ctx.parsed, ctx.schema);
207
- if (repaired !== ctx.parsed) {
208
- return { parsed: repaired };
209
- }
210
- return {};
211
- }
212
- };
213
- var defaultPipelineConfig = {
214
- preParse: [normalizeCloseTagsHeuristic, escapeInvalidLtHeuristic],
215
- fallbackReparse: [balanceTagsHeuristic, dedupeShellStringTagsHeuristic],
216
- postParse: [repairAgainstSchemaHeuristic]
217
- };
218
- var INDEX_TAG_RE = /^<(\d+)(?:>|\/?>)/;
219
- function isIndexTagAt(xml, pos) {
220
- const remaining = xml.slice(pos);
221
- return INDEX_TAG_RE.test(remaining);
222
- }
223
- function escapeInvalidLt(xml) {
224
- const len = xml.length;
225
- let out = "";
226
- for (let i = 0; i < len; i += 1) {
227
- const ch = xml[i];
228
- if (ch === "<") {
229
- const next = i + 1 < len ? xml[i + 1] : "";
230
- const isValidStart = NAME_START_CHAR_RE.test(next) || next === "/" || next === "!" || next === "?";
231
- const isIndexTag = !isValidStart && isIndexTagAt(xml, i);
232
- if (!(isValidStart || isIndexTag)) {
233
- out += "&lt;";
234
- continue;
235
- }
236
- }
237
- out += ch;
238
- }
239
- return out;
240
- }
241
- function balanceTags(xml) {
242
- const src = xml.replace(MALFORMED_CLOSE_RE_G, "</$1>").replace(STATUS_TO_STEP_BOUNDARY_RE, "</status></step><step>");
243
- let i = 0;
244
- const len = src.length;
245
- const out = [];
246
- const stack = [];
247
- while (i < len) {
248
- const lt = src.indexOf("<", i);
249
- if (lt === -1) {
250
- out.push(src.slice(i));
251
- break;
252
- }
253
- out.push(src.slice(i, lt));
254
- if (lt + 1 >= len) {
255
- break;
256
- }
257
- const next = src[lt + 1];
258
- if (next === "!" || next === "?") {
259
- i = handleSpecialTagSegment(src, lt, out);
260
- continue;
261
- }
262
- if (next === "/") {
263
- i = handleClosingTagSegment(src, lt, out, stack);
264
- continue;
265
- }
266
- i = handleOpeningTagSegment(src, lt, out, stack);
267
- }
268
- for (let k = stack.length - 1; k >= 0; k -= 1) {
269
- out.push(`</${stack[k]}>`);
270
- }
271
- return out.join("");
272
- }
273
- function skipWs(s, p, len) {
274
- let idx = p;
275
- while (idx < len && WHITESPACE_REGEX.test(s[idx])) {
276
- idx += 1;
277
- }
278
- return idx;
279
- }
280
- function parseTagNameAt(s, p, len) {
281
- let idx = p;
282
- const start = idx;
283
- while (idx < len && NAME_CHAR_RE.test(s[idx])) {
284
- idx += 1;
285
- }
286
- return { name: s.slice(start, idx), pos: idx };
287
- }
288
- function handleSpecialTagSegment(src, lt, out) {
289
- const gt = src.indexOf(">", lt + 1);
290
- if (gt === -1) {
291
- out.push(src.slice(lt));
292
- return src.length;
293
- }
294
- out.push(src.slice(lt, gt + 1));
295
- return gt + 1;
296
- }
297
- function handleClosingTagSegment(src, lt, out, stack) {
298
- const len = src.length;
299
- let p = skipWs(src, lt + 2, len);
300
- const { name, pos } = parseTagNameAt(src, p, len);
301
- p = pos;
302
- const gt = src.indexOf(">", p);
303
- const closingText = gt === -1 ? src.slice(lt) : src.slice(lt, gt + 1);
304
- const idx = stack.lastIndexOf(name);
305
- if (idx !== -1) {
306
- for (let k = stack.length - 1; k > idx; k -= 1) {
307
- out.push(`</${stack[k]}>`);
308
- stack.pop();
309
- }
310
- out.push(closingText);
311
- stack.pop();
312
- }
313
- return gt === -1 ? len : gt + 1;
314
- }
315
- function handleOpeningTagSegment(src, lt, out, stack) {
316
- const len = src.length;
317
- let p = skipWs(src, lt + 1, len);
318
- const nameStart = p;
319
- const parsed = parseTagNameAt(src, p, len);
320
- p = parsed.pos;
321
- const name = src.slice(nameStart, p);
322
- const q = src.indexOf(">", p);
323
- if (q === -1) {
324
- out.push(src.slice(lt));
325
- return len;
326
- }
327
- let r = q - 1;
328
- while (r >= nameStart && WHITESPACE_REGEX.test(src[r])) {
329
- r -= 1;
330
- }
331
- const selfClosing = src[r] === "/";
332
- out.push(src.slice(lt, q + 1));
333
- if (!selfClosing && name) {
334
- stack.push(name);
335
- }
336
- return q + 1;
337
- }
338
- function extractSchemaProperties(schema) {
339
- const unwrapped = unwrapJsonSchema(schema);
340
- if (!unwrapped || typeof unwrapped !== "object") {
341
- return void 0;
342
- }
343
- return unwrapped.properties;
344
- }
345
- function shouldDeduplicateStringTags(schema) {
346
- const props = extractSchemaProperties(schema);
347
- if (!props) {
348
- return false;
349
- }
350
- const commandRaw = props.command;
351
- if (!commandRaw) {
352
- return false;
353
- }
354
- const command = unwrapJsonSchema(commandRaw);
355
- return (command == null ? void 0 : command.type) === "array";
356
- }
357
- function getStringPropertyNames(schema) {
358
- const props = extractSchemaProperties(schema);
359
- if (!props) {
360
- return [];
361
- }
362
- const names = [];
363
- for (const key of Object.keys(props)) {
364
- const prop = unwrapJsonSchema(props[key]);
365
- if ((prop == null ? void 0 : prop.type) === "string") {
366
- names.push(key);
367
- }
368
- }
369
- return names;
370
- }
371
- function escapeRegExp(s) {
372
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
373
- }
374
- function dedupeSingleTag(xml, key) {
375
- var _a, _b;
376
- const escaped = escapeRegExp(key);
377
- const re = new RegExp(`<${escaped}>([\\s\\S]*?)<\\/${escaped}>`, "g");
378
- const matches = Array.from(xml.matchAll(re));
379
- if (matches.length <= 1) {
380
- return xml;
381
- }
382
- const last = matches.at(-1);
383
- let result = "";
384
- let cursor = 0;
385
- for (const m of matches) {
386
- const idx = (_a = m.index) != null ? _a : 0;
387
- result += xml.slice(cursor, idx);
388
- if (last && idx === ((_b = last.index) != null ? _b : -1)) {
389
- result += m[0];
390
- }
391
- cursor = idx + m[0].length;
392
- }
393
- result += xml.slice(cursor);
394
- return result;
395
- }
396
- function repairParsedAgainstSchema(input, schema) {
397
- if (!input || typeof input !== "object") {
398
- return input;
399
- }
400
- const properties = extractSchemaProperties(schema);
401
- if (!properties) {
402
- return input;
403
- }
404
- applySchemaProps(input, properties);
405
- return input;
406
- }
407
- function applySchemaProps(obj, properties) {
408
- for (const key of Object.keys(obj)) {
409
- const propSchema = properties[key];
410
- if (!propSchema) {
411
- continue;
412
- }
413
- const prop = unwrapJsonSchema(propSchema);
414
- if ((prop == null ? void 0 : prop.type) === "array" && prop.items) {
415
- const itemSchema = unwrapJsonSchema(prop.items);
416
- obj[key] = coerceArrayItems(obj[key], itemSchema);
417
- continue;
418
- }
419
- if ((prop == null ? void 0 : prop.type) === "object") {
420
- const val = obj[key];
421
- if (val && typeof val === "object") {
422
- obj[key] = repairParsedAgainstSchema(val, prop);
423
- }
424
- }
425
- }
426
- }
427
- function coerceArrayItems(val, itemSchema) {
428
- if (!Array.isArray(val)) {
429
- return val;
430
- }
431
- return val.map((v) => coerceArrayItem(v, itemSchema));
432
- }
433
- function coerceArrayItem(v, itemSchema) {
434
- const itemType = itemSchema == null ? void 0 : itemSchema.type;
435
- if (typeof v === "string" && itemType === "object") {
436
- const parsed = tryParseStringToSchemaObject(v, itemSchema);
437
- if (parsed !== null) {
438
- return parsed;
439
- }
440
- const fallback = extractStepStatusFromString(
441
- v.replace(MALFORMED_CLOSE_RE_G, "</$1>")
442
- );
443
- if (fallback) {
444
- return fallback;
445
- }
446
- return v;
447
- }
448
- if (v && typeof v === "object" && itemType === "object") {
449
- return repairParsedAgainstSchema(v, itemSchema);
450
- }
451
- return v;
452
- }
453
- function tryParseStringToSchemaObject(xml, itemSchema) {
454
- try {
455
- const normalized = xml.replace(MALFORMED_CLOSE_RE_G, "</$1>");
456
- const fixed = parse(normalized, itemSchema, { noChildNodes: [] });
457
- return typeof fixed === "string" ? null : fixed;
458
- } catch (e) {
459
- return null;
460
- }
461
- }
462
- function extractStepStatusFromString(normXml) {
463
- const stepMatch = normXml.match(STEP_TAG_RE);
464
- const statusMatch = normXml.match(STATUS_TAG_RE);
465
- if (stepMatch && statusMatch) {
466
- return { step: stepMatch[1], status: statusMatch[1] };
467
- }
468
- return null;
469
- }
470
-
471
4
  // src/core/protocols/json-protocol.ts
472
5
  import { parse as parseRJSON } from "@ai-sdk-tool/rjson";
473
6
 
@@ -650,7 +183,7 @@ function generateId() {
650
183
  }
651
184
 
652
185
  // src/core/utils/regex.ts
653
- function escapeRegExp2(literal) {
186
+ function escapeRegExp(literal) {
654
187
  return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
655
188
  }
656
189
 
@@ -897,8 +430,8 @@ var jsonProtocol = ({
897
430
  text,
898
431
  options
899
432
  }) {
900
- const startEsc = escapeRegExp2(toolCallStart);
901
- const endEsc = escapeRegExp2(toolCallEnd);
433
+ const startEsc = escapeRegExp(toolCallStart);
434
+ const endEsc = escapeRegExp(toolCallEnd);
902
435
  const toolCallRegex = new RegExp(
903
436
  `${startEsc}([\0-\uFFFF]*?)${endEsc}`,
904
437
  "gs"
@@ -957,8 +490,8 @@ var jsonProtocol = ({
957
490
  });
958
491
  },
959
492
  extractToolCallSegments({ text }) {
960
- const startEsc = escapeRegExp2(toolCallStart);
961
- const endEsc = escapeRegExp2(toolCallEnd);
493
+ const startEsc = escapeRegExp(toolCallStart);
494
+ const endEsc = escapeRegExp(toolCallEnd);
962
495
  const regex = new RegExp(`${startEsc}([\0-\uFFFF]*?)${endEsc}`, "gs");
963
496
  const segments = [];
964
497
  let m = regex.exec(text);
@@ -979,93 +512,48 @@ function isTCMProtocolFactory(protocol) {
979
512
  }
980
513
 
981
514
  // src/core/protocols/xml-protocol.ts
982
- import { extractRawInner, parse as parse2, stringify } from "@ai-sdk-tool/rxml";
983
- var defaultPipelineConfig2 = defaultPipelineConfig;
984
- var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
985
- var WHITESPACE_REGEX2 = /\s/;
515
+ import { parse, stringify } from "@ai-sdk-tool/rxml";
516
+ var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
517
+ var WHITESPACE_REGEX = /\s/;
518
+ var REGEX_ESCAPE_RE = /[.*+?^${}()|[\]\\]/g;
519
+ function escapeRegExp2(value) {
520
+ return value.replace(REGEX_ESCAPE_RE, "\\$&");
521
+ }
986
522
  function getToolSchema(tools, toolName) {
987
523
  var _a;
988
524
  return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
989
525
  }
990
- function normalizeCloseTags(xml) {
991
- return xml.replace(/<\/\s+([A-Za-z0-9_:-]+)\s*>/g, "</$1>");
992
- }
993
- function tryParseSecondaryXml(content, toolSchema, options) {
994
- const balanced = balanceTags(content);
995
- try {
996
- let parsed = parse2(balanced, toolSchema, {
997
- onError: options == null ? void 0 : options.onError,
998
- noChildNodes: []
999
- });
1000
- parsed = repairParsedAgainstSchema(parsed, toolSchema);
1001
- return parsed;
1002
- } catch (e) {
1003
- if (shouldDeduplicateStringTags(toolSchema)) {
1004
- const names = getStringPropertyNames(toolSchema);
1005
- let deduped = balanced;
1006
- for (const key of names) {
1007
- deduped = dedupeSingleTag(deduped, key);
1008
- }
1009
- if (deduped !== balanced) {
1010
- try {
1011
- let reparsed = parse2(deduped, toolSchema, {
1012
- onError: options == null ? void 0 : options.onError,
1013
- noChildNodes: []
1014
- });
1015
- reparsed = repairParsedAgainstSchema(reparsed, toolSchema);
1016
- return reparsed;
1017
- } catch (e2) {
1018
- return null;
1019
- }
1020
- }
1021
- }
1022
- return null;
1023
- }
1024
- }
1025
- function processToolCallWithPipeline(params) {
1026
- var _a;
1027
- const {
1028
- toolCall,
1029
- tools,
1030
- options,
1031
- text,
1032
- processedElements,
1033
- pipelineConfig = defaultPipelineConfig2,
1034
- maxReparses
1035
- } = params;
526
+ function processToolCall(params) {
527
+ var _a, _b;
528
+ const { toolCall, tools, options, text, processedElements, parseOptions } = params;
1036
529
  const toolSchema = getToolSchema(tools, toolCall.toolName);
1037
- const ctx = createIntermediateCall(
1038
- toolCall.toolName,
1039
- toolCall.content,
1040
- toolSchema
1041
- );
1042
- const result = applyHeuristicPipeline(ctx, pipelineConfig, {
1043
- parse: (xml, schema) => parse2(xml, schema, { onError: options == null ? void 0 : options.onError, noChildNodes: [] }),
1044
- onError: options == null ? void 0 : options.onError,
1045
- maxReparses
1046
- });
1047
- if (result.parsed !== null) {
530
+ const parseConfig = {
531
+ ...parseOptions != null ? parseOptions : {},
532
+ onError: (_a = options == null ? void 0 : options.onError) != null ? _a : parseOptions == null ? void 0 : parseOptions.onError
533
+ };
534
+ try {
535
+ const parsed = parse(toolCall.content, toolSchema, parseConfig);
1048
536
  processedElements.push({
1049
537
  type: "tool-call",
1050
538
  toolCallId: generateId(),
1051
539
  toolName: toolCall.toolName,
1052
- input: JSON.stringify(result.parsed)
540
+ input: JSON.stringify(parsed)
1053
541
  });
1054
- } else {
542
+ } catch (error) {
1055
543
  const originalCallText = text.substring(
1056
544
  toolCall.startIndex,
1057
545
  toolCall.endIndex
1058
546
  );
1059
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
547
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
1060
548
  options,
1061
549
  `Could not process XML tool call: ${toolCall.toolName}`,
1062
- { toolCall: originalCallText, error: result.errors[0] }
550
+ { toolCall: originalCallText, error }
1063
551
  );
1064
552
  processedElements.push({ type: "text", text: originalCallText });
1065
553
  }
1066
554
  }
1067
555
  function handleStreamingToolCallEnd(params) {
1068
- var _a;
556
+ var _a, _b;
1069
557
  const {
1070
558
  toolContent,
1071
559
  currentToolCall,
@@ -1073,51 +561,27 @@ function handleStreamingToolCallEnd(params) {
1073
561
  options,
1074
562
  ctrl,
1075
563
  flushText,
1076
- pipelineConfig,
1077
- maxReparses
564
+ parseOptions
1078
565
  } = params;
1079
566
  const toolSchema = getToolSchema(tools, currentToolCall.name);
1080
- let parsedResult = null;
1081
- if (pipelineConfig) {
1082
- const ctx = createIntermediateCall(
1083
- currentToolCall.name,
1084
- toolContent,
1085
- toolSchema
1086
- );
1087
- const result = applyHeuristicPipeline(ctx, pipelineConfig, {
1088
- parse: (xml, schema) => parse2(xml, schema, { onError: options == null ? void 0 : options.onError, noChildNodes: [] }),
1089
- onError: options == null ? void 0 : options.onError,
1090
- maxReparses
1091
- });
1092
- parsedResult = result.parsed;
1093
- } else {
1094
- try {
1095
- const primary = escapeInvalidLt(normalizeCloseTags(toolContent));
1096
- const parsed = parse2(primary, toolSchema, {
1097
- onError: options == null ? void 0 : options.onError,
1098
- noChildNodes: []
1099
- });
1100
- parsedResult = repairParsedAgainstSchema(parsed, toolSchema);
1101
- } catch (e) {
1102
- parsedResult = tryParseSecondaryXml(
1103
- toolContent,
1104
- toolSchema,
1105
- options != null ? options : {}
1106
- );
1107
- }
1108
- }
567
+ const parseConfig = {
568
+ ...parseOptions != null ? parseOptions : {},
569
+ onError: (_a = options == null ? void 0 : options.onError) != null ? _a : parseOptions == null ? void 0 : parseOptions.onError
570
+ };
1109
571
  flushText(ctrl);
1110
- if (parsedResult !== null) {
572
+ try {
573
+ const parsedResult = parse(toolContent, toolSchema, parseConfig);
1111
574
  ctrl.enqueue({
1112
575
  type: "tool-call",
1113
576
  toolCallId: generateId(),
1114
577
  toolName: currentToolCall.name,
1115
578
  input: JSON.stringify(parsedResult)
1116
579
  });
1117
- } else {
580
+ } catch (error) {
1118
581
  const original = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
1119
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not process streaming XML tool call", {
1120
- toolCall: original
582
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
583
+ toolCall: original,
584
+ error
1121
585
  });
1122
586
  flushText(ctrl, original);
1123
587
  }
@@ -1156,11 +620,11 @@ function consumeClosingTag(text, lt) {
1156
620
  }
1157
621
  function consumeOpenTag(text, lt) {
1158
622
  let p = lt + 1;
1159
- while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
623
+ while (p < text.length && WHITESPACE_REGEX.test(text[p])) {
1160
624
  p += 1;
1161
625
  }
1162
626
  const nameStart = p;
1163
- while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
627
+ while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
1164
628
  p += 1;
1165
629
  }
1166
630
  const name = text.slice(nameStart, p);
@@ -1169,7 +633,7 @@ function consumeOpenTag(text, lt) {
1169
633
  return null;
1170
634
  }
1171
635
  let r = q - 1;
1172
- while (r >= nameStart && WHITESPACE_REGEX2.test(text[r])) {
636
+ while (r >= nameStart && WHITESPACE_REGEX.test(text[r])) {
1173
637
  r -= 1;
1174
638
  }
1175
639
  const selfClosing = text[r] === "/";
@@ -1198,11 +662,11 @@ function nextTagToken(text, fromPos) {
1198
662
  if (next === "/") {
1199
663
  const closing = consumeClosingTag(text, lt);
1200
664
  let p = lt + 2;
1201
- while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
665
+ while (p < text.length && WHITESPACE_REGEX.test(text[p])) {
1202
666
  p += 1;
1203
667
  }
1204
668
  const nameStart = p;
1205
- while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
669
+ while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
1206
670
  p += 1;
1207
671
  }
1208
672
  const name = text.slice(nameStart, p);
@@ -1219,49 +683,90 @@ function nextTagToken(text, fromPos) {
1219
683
  nextPos: open.nextPos
1220
684
  };
1221
685
  }
686
+ function findNextToolTag(text, searchIndex, startTag, selfTag) {
687
+ const openIdx = text.indexOf(startTag, searchIndex);
688
+ const selfIdx = text.indexOf(selfTag, searchIndex);
689
+ if (openIdx === -1 && selfIdx === -1) {
690
+ return null;
691
+ }
692
+ const isSelfClosing = selfIdx !== -1 && (openIdx === -1 || selfIdx < openIdx);
693
+ return {
694
+ tagStart: isSelfClosing ? selfIdx : openIdx,
695
+ isSelfClosing
696
+ };
697
+ }
698
+ function findLastCloseTagStart(segment, toolName) {
699
+ const closeTagPattern = new RegExp(
700
+ `</\\s*${escapeRegExp2(toolName)}\\s*>`,
701
+ "g"
702
+ );
703
+ let closeTagStart = -1;
704
+ let match = closeTagPattern.exec(segment);
705
+ while (match !== null) {
706
+ closeTagStart = match.index;
707
+ match = closeTagPattern.exec(segment);
708
+ }
709
+ if (closeTagStart === -1) {
710
+ return segment.lastIndexOf("<");
711
+ }
712
+ return closeTagStart;
713
+ }
714
+ function pushSelfClosingToolCall(toolCalls, toolName, text, tagStart, selfTag) {
715
+ const endIndex = tagStart + selfTag.length;
716
+ toolCalls.push({
717
+ toolName,
718
+ startIndex: tagStart,
719
+ endIndex,
720
+ content: "",
721
+ segment: text.substring(tagStart, endIndex)
722
+ });
723
+ return endIndex;
724
+ }
725
+ function appendOpenToolCallIfComplete(toolCalls, text, toolName, tagStart, startTag) {
726
+ const contentStart = tagStart + startTag.length;
727
+ const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
728
+ if (fullTagEnd === -1 || fullTagEnd <= contentStart) {
729
+ return contentStart;
730
+ }
731
+ const segment = text.substring(tagStart, fullTagEnd);
732
+ const closeTagStart = findLastCloseTagStart(segment, toolName);
733
+ const inner = closeTagStart === -1 ? segment.slice(startTag.length) : segment.slice(startTag.length, closeTagStart);
734
+ toolCalls.push({
735
+ toolName,
736
+ startIndex: tagStart,
737
+ endIndex: fullTagEnd,
738
+ content: inner,
739
+ segment
740
+ });
741
+ return fullTagEnd;
742
+ }
1222
743
  function findToolCallsForName(text, toolName) {
1223
- var _a;
1224
744
  const toolCalls = [];
745
+ const startTag = `<${toolName}>`;
746
+ const selfTag = `<${toolName}/>`;
1225
747
  let searchIndex = 0;
1226
748
  while (searchIndex < text.length) {
1227
- const startTag = `<${toolName}>`;
1228
- const selfTag = `<${toolName}/>`;
1229
- const openIdx = text.indexOf(startTag, searchIndex);
1230
- const selfIdx = text.indexOf(selfTag, searchIndex);
1231
- if (openIdx === -1 && selfIdx === -1) {
749
+ const match = findNextToolTag(text, searchIndex, startTag, selfTag);
750
+ if (match === null) {
1232
751
  break;
1233
752
  }
1234
- const tagStart = selfIdx !== -1 && (openIdx === -1 || selfIdx < openIdx) ? selfIdx : openIdx;
1235
- const isSelfClosing = tagStart === selfIdx;
1236
- if (isSelfClosing) {
1237
- const endIndex = tagStart + selfTag.length;
1238
- const segment = text.substring(tagStart, endIndex);
1239
- toolCalls.push({
753
+ if (match.isSelfClosing) {
754
+ searchIndex = pushSelfClosingToolCall(
755
+ toolCalls,
1240
756
  toolName,
1241
- startIndex: tagStart,
1242
- endIndex,
1243
- content: "",
1244
- segment
1245
- });
1246
- searchIndex = endIndex;
757
+ text,
758
+ match.tagStart,
759
+ selfTag
760
+ );
1247
761
  continue;
1248
762
  }
1249
- const contentStart = tagStart + startTag.length;
1250
- const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
1251
- if (fullTagEnd !== -1 && fullTagEnd > contentStart) {
1252
- const segment = text.substring(tagStart, fullTagEnd);
1253
- const inner = (_a = extractRawInner(segment, toolName)) != null ? _a : segment.substring(startTag.length, segment.lastIndexOf("<"));
1254
- toolCalls.push({
1255
- toolName,
1256
- startIndex: tagStart,
1257
- endIndex: fullTagEnd,
1258
- content: inner,
1259
- segment
1260
- });
1261
- searchIndex = fullTagEnd;
1262
- } else {
1263
- searchIndex = contentStart;
1264
- }
763
+ searchIndex = appendOpenToolCallIfComplete(
764
+ toolCalls,
765
+ text,
766
+ toolName,
767
+ match.tagStart,
768
+ startTag
769
+ );
1265
770
  }
1266
771
  return toolCalls;
1267
772
  }
@@ -1338,16 +843,20 @@ function processToolCallInBuffer(params) {
1338
843
  controller,
1339
844
  flushText,
1340
845
  setBuffer,
1341
- pipelineConfig,
1342
- maxReparses
846
+ parseOptions
1343
847
  } = params;
1344
- const endTag = `</${currentToolCall.name}>`;
1345
- const endIdx = buffer.indexOf(endTag);
1346
- if (endIdx === -1) {
848
+ const endTagPattern = new RegExp(
849
+ `</\\s*${escapeRegExp2(currentToolCall.name)}\\s*>`
850
+ );
851
+ const endMatch = endTagPattern.exec(buffer);
852
+ if (!endMatch || endMatch.index === void 0) {
1347
853
  return { buffer, currentToolCall, shouldBreak: true };
1348
854
  }
855
+ const endIdx = endMatch.index;
856
+ const endPos = endIdx + endMatch[0].length;
1349
857
  const content = buffer.substring(0, endIdx);
1350
- setBuffer(buffer.substring(endIdx + endTag.length));
858
+ const remainder = buffer.substring(endPos);
859
+ setBuffer(remainder);
1351
860
  handleStreamingToolCallEnd({
1352
861
  toolContent: content,
1353
862
  currentToolCall,
@@ -1355,11 +864,10 @@ function processToolCallInBuffer(params) {
1355
864
  options,
1356
865
  ctrl: controller,
1357
866
  flushText,
1358
- pipelineConfig,
1359
- maxReparses
867
+ parseOptions
1360
868
  });
1361
869
  return {
1362
- buffer: buffer.substring(endIdx + endTag.length),
870
+ buffer: remainder,
1363
871
  currentToolCall: null,
1364
872
  shouldBreak: false
1365
873
  };
@@ -1372,8 +880,7 @@ function processNoToolCallInBuffer(params) {
1372
880
  flushText,
1373
881
  tools,
1374
882
  options,
1375
- pipelineConfig,
1376
- maxReparses,
883
+ parseOptions,
1377
884
  setBuffer
1378
885
  } = params;
1379
886
  const {
@@ -1408,8 +915,7 @@ function processNoToolCallInBuffer(params) {
1408
915
  options,
1409
916
  ctrl: controller,
1410
917
  flushText,
1411
- pipelineConfig,
1412
- maxReparses
918
+ parseOptions
1413
919
  });
1414
920
  return {
1415
921
  buffer: newBuffer2,
@@ -1428,7 +934,7 @@ function processNoToolCallInBuffer(params) {
1428
934
  shouldContinue: true
1429
935
  };
1430
936
  }
1431
- function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, pipelineConfig, maxReparses) {
937
+ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions) {
1432
938
  return (controller) => {
1433
939
  while (true) {
1434
940
  const currentToolCall = getCurrentToolCall();
@@ -1441,8 +947,7 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
1441
947
  controller,
1442
948
  flushText,
1443
949
  setBuffer,
1444
- pipelineConfig,
1445
- maxReparses
950
+ parseOptions
1446
951
  });
1447
952
  setBuffer(result.buffer);
1448
953
  setCurrentToolCall(result.currentToolCall);
@@ -1457,8 +962,7 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
1457
962
  flushText,
1458
963
  tools,
1459
964
  options,
1460
- pipelineConfig,
1461
- maxReparses,
965
+ parseOptions,
1462
966
  setBuffer
1463
967
  });
1464
968
  setBuffer(result.buffer);
@@ -1475,43 +979,12 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
1475
979
  };
1476
980
  }
1477
981
  var xmlProtocol = (protocolOptions) => {
1478
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1479
- let pipelineConfig = protocolOptions == null ? void 0 : protocolOptions.pipeline;
1480
- const maxReparses = protocolOptions == null ? void 0 : protocolOptions.maxReparses;
1481
- if ((protocolOptions == null ? void 0 : protocolOptions.heuristics) && protocolOptions.heuristics.length > 0) {
1482
- const heuristicsConfig = {
1483
- preParse: [],
1484
- fallbackReparse: [],
1485
- postParse: []
1486
- };
1487
- for (const h of protocolOptions.heuristics) {
1488
- if (h.phase === "pre-parse") {
1489
- (_a = heuristicsConfig.preParse) == null ? void 0 : _a.push(h);
1490
- } else if (h.phase === "fallback-reparse") {
1491
- (_b = heuristicsConfig.fallbackReparse) == null ? void 0 : _b.push(h);
1492
- } else if (h.phase === "post-parse") {
1493
- (_c = heuristicsConfig.postParse) == null ? void 0 : _c.push(h);
1494
- }
1495
- }
1496
- if (pipelineConfig) {
1497
- pipelineConfig = {
1498
- preParse: [
1499
- ...(_d = pipelineConfig.preParse) != null ? _d : [],
1500
- ...(_e = heuristicsConfig.preParse) != null ? _e : []
1501
- ],
1502
- fallbackReparse: [
1503
- ...(_f = pipelineConfig.fallbackReparse) != null ? _f : [],
1504
- ...(_g = heuristicsConfig.fallbackReparse) != null ? _g : []
1505
- ],
1506
- postParse: [
1507
- ...(_h = pipelineConfig.postParse) != null ? _h : [],
1508
- ...(_i = heuristicsConfig.postParse) != null ? _i : []
1509
- ]
1510
- };
1511
- } else {
1512
- pipelineConfig = heuristicsConfig;
1513
- }
1514
- }
982
+ var _a;
983
+ const parseOptions = {
984
+ repair: true,
985
+ noChildNodes: [],
986
+ ...(_a = protocolOptions == null ? void 0 : protocolOptions.parseOptions) != null ? _a : {}
987
+ };
1515
988
  return {
1516
989
  formatTools({ tools, toolSystemPromptTemplate }) {
1517
990
  return toolSystemPromptTemplate(tools || []);
@@ -1546,14 +1019,13 @@ var xmlProtocol = (protocolOptions) => {
1546
1019
  text: text.substring(currentIndex, tc.startIndex)
1547
1020
  });
1548
1021
  }
1549
- processToolCallWithPipeline({
1022
+ processToolCall({
1550
1023
  toolCall: tc,
1551
1024
  tools,
1552
1025
  options,
1553
1026
  text,
1554
1027
  processedElements,
1555
- pipelineConfig,
1556
- maxReparses
1028
+ parseOptions
1557
1029
  });
1558
1030
  currentIndex = tc.endIndex;
1559
1031
  }
@@ -1594,8 +1066,7 @@ var xmlProtocol = (protocolOptions) => {
1594
1066
  options,
1595
1067
  toolNames,
1596
1068
  flushText,
1597
- pipelineConfig,
1598
- maxReparses
1069
+ parseOptions
1599
1070
  );
1600
1071
  return new TransformStream({
1601
1072
  transform(chunk, controller) {
@@ -1645,8 +1116,8 @@ var xmlProtocol = (protocolOptions) => {
1645
1116
 
1646
1117
  // src/core/protocols/yaml-protocol.ts
1647
1118
  import YAML from "yaml";
1648
- var NAME_CHAR_RE3 = /[A-Za-z0-9_:-]/;
1649
- var WHITESPACE_REGEX3 = /\s/;
1119
+ var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
1120
+ var WHITESPACE_REGEX2 = /\s/;
1650
1121
  var LEADING_WHITESPACE_RE = /^(\s*)/;
1651
1122
  function findClosingTagEnd(text, contentStart, toolName) {
1652
1123
  let pos = contentStart;
@@ -1663,11 +1134,11 @@ function findClosingTagEnd(text, contentStart, toolName) {
1663
1134
  break;
1664
1135
  }
1665
1136
  let p = ltIdx + 2;
1666
- while (p < gtIdx && WHITESPACE_REGEX3.test(text[p])) {
1137
+ while (p < gtIdx && WHITESPACE_REGEX2.test(text[p])) {
1667
1138
  p++;
1668
1139
  }
1669
1140
  const nameStart = p;
1670
- while (p < gtIdx && NAME_CHAR_RE3.test(text.charAt(p))) {
1141
+ while (p < gtIdx && NAME_CHAR_RE2.test(text.charAt(p))) {
1671
1142
  p++;
1672
1143
  }
1673
1144
  const name = text.slice(nameStart, p);
@@ -1683,11 +1154,11 @@ function findClosingTagEnd(text, contentStart, toolName) {
1683
1154
  pos = gtIdx === -1 ? text.length : gtIdx + 1;
1684
1155
  } else {
1685
1156
  let p = ltIdx + 1;
1686
- while (p < text.length && WHITESPACE_REGEX3.test(text[p])) {
1157
+ while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
1687
1158
  p++;
1688
1159
  }
1689
1160
  const nameStart = p;
1690
- while (p < text.length && NAME_CHAR_RE3.test(text.charAt(p))) {
1161
+ while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
1691
1162
  p++;
1692
1163
  }
1693
1164
  const name = text.slice(nameStart, p);
@@ -1696,7 +1167,7 @@ function findClosingTagEnd(text, contentStart, toolName) {
1696
1167
  break;
1697
1168
  }
1698
1169
  let r = gtIdx - 1;
1699
- while (r >= nameStart && WHITESPACE_REGEX3.test(text[r])) {
1170
+ while (r >= nameStart && WHITESPACE_REGEX2.test(text[r])) {
1700
1171
  r--;
1701
1172
  }
1702
1173
  const selfClosing = text[r] === "/";
@@ -2201,7 +1672,7 @@ function hasInputProperty(obj) {
2201
1672
 
2202
1673
  // src/generate-handler.ts
2203
1674
  import { generateId as generateId2 } from "@ai-sdk/provider-utils";
2204
- import { coerceBySchema } from "@ai-sdk-tool/rxml";
1675
+ import { coerceBySchema } from "@ai-sdk-tool/schema-coerce";
2205
1676
  function parseToolChoiceJson(text, providerOptions) {
2206
1677
  var _a;
2207
1678
  try {
@@ -3027,20 +2498,12 @@ function createToolMiddleware({
3027
2498
  const resolvedProtocol = isTCMProtocolFactory(protocol) ? protocol() : protocol;
3028
2499
  return {
3029
2500
  specificationVersion: "v3",
3030
- wrapStream: ({ doStream, doGenerate, params }) => {
3031
- if (isToolChoiceActive(params)) {
3032
- return toolChoiceStream({
3033
- doGenerate,
3034
- options: extractOnErrorOption(params.providerOptions)
3035
- });
3036
- }
3037
- return wrapStream({
3038
- protocol: resolvedProtocol,
3039
- doStream,
3040
- doGenerate,
3041
- params
3042
- });
3043
- },
2501
+ wrapStream: ({ doStream, doGenerate, params }) => wrapStream({
2502
+ protocol: resolvedProtocol,
2503
+ doStream,
2504
+ doGenerate,
2505
+ params
2506
+ }),
3044
2507
  wrapGenerate: async ({ doGenerate, params }) => wrapGenerate({
3045
2508
  protocol: resolvedProtocol,
3046
2509
  doGenerate,
@@ -3074,22 +2537,13 @@ var yamlToolMiddleware = createToolMiddleware({
3074
2537
  });
3075
2538
 
3076
2539
  export {
3077
- applyHeuristicPipeline,
3078
- createIntermediateCall,
3079
- mergePipelineConfigs,
3080
- normalizeCloseTagsHeuristic,
3081
- escapeInvalidLtHeuristic,
3082
- balanceTagsHeuristic,
3083
- dedupeShellStringTagsHeuristic,
3084
- repairAgainstSchemaHeuristic,
3085
- defaultPipelineConfig,
3086
2540
  getDebugLevel,
3087
2541
  logParseFailure,
3088
2542
  logRawChunk,
3089
2543
  logParsedChunk,
3090
2544
  logParsedSummary,
3091
2545
  getPotentialStartIndex,
3092
- escapeRegExp2 as escapeRegExp,
2546
+ escapeRegExp,
3093
2547
  jsonProtocol,
3094
2548
  isProtocolFactory,
3095
2549
  isTCMProtocolFactory,
@@ -3113,4 +2567,4 @@ export {
3113
2567
  xmlToolMiddleware,
3114
2568
  yamlToolMiddleware
3115
2569
  };
3116
- //# sourceMappingURL=chunk-3KQVEBKO.js.map
2570
+ //# sourceMappingURL=chunk-PIUBQRFC.js.map