@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.
@@ -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,44 @@ 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/;
986
518
  function getToolSchema(tools, toolName) {
987
519
  var _a;
988
520
  return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
989
521
  }
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;
522
+ function processToolCall(params) {
523
+ var _a, _b;
524
+ const { toolCall, tools, options, text, processedElements, parseOptions } = params;
1036
525
  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) {
526
+ const parseConfig = {
527
+ ...parseOptions != null ? parseOptions : {},
528
+ onError: (_a = options == null ? void 0 : options.onError) != null ? _a : parseOptions == null ? void 0 : parseOptions.onError
529
+ };
530
+ try {
531
+ const parsed = parse(toolCall.content, toolSchema, parseConfig);
1048
532
  processedElements.push({
1049
533
  type: "tool-call",
1050
534
  toolCallId: generateId(),
1051
535
  toolName: toolCall.toolName,
1052
- input: JSON.stringify(result.parsed)
536
+ input: JSON.stringify(parsed)
1053
537
  });
1054
- } else {
538
+ } catch (error) {
1055
539
  const originalCallText = text.substring(
1056
540
  toolCall.startIndex,
1057
541
  toolCall.endIndex
1058
542
  );
1059
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
543
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
1060
544
  options,
1061
545
  `Could not process XML tool call: ${toolCall.toolName}`,
1062
- { toolCall: originalCallText, error: result.errors[0] }
546
+ { toolCall: originalCallText, error }
1063
547
  );
1064
548
  processedElements.push({ type: "text", text: originalCallText });
1065
549
  }
1066
550
  }
1067
551
  function handleStreamingToolCallEnd(params) {
1068
- var _a;
552
+ var _a, _b;
1069
553
  const {
1070
554
  toolContent,
1071
555
  currentToolCall,
@@ -1073,51 +557,27 @@ function handleStreamingToolCallEnd(params) {
1073
557
  options,
1074
558
  ctrl,
1075
559
  flushText,
1076
- pipelineConfig,
1077
- maxReparses
560
+ parseOptions
1078
561
  } = params;
1079
562
  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
- }
563
+ const parseConfig = {
564
+ ...parseOptions != null ? parseOptions : {},
565
+ onError: (_a = options == null ? void 0 : options.onError) != null ? _a : parseOptions == null ? void 0 : parseOptions.onError
566
+ };
1109
567
  flushText(ctrl);
1110
- if (parsedResult !== null) {
568
+ try {
569
+ const parsedResult = parse(toolContent, toolSchema, parseConfig);
1111
570
  ctrl.enqueue({
1112
571
  type: "tool-call",
1113
572
  toolCallId: generateId(),
1114
573
  toolName: currentToolCall.name,
1115
574
  input: JSON.stringify(parsedResult)
1116
575
  });
1117
- } else {
576
+ } catch (error) {
1118
577
  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
578
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
579
+ toolCall: original,
580
+ error
1121
581
  });
1122
582
  flushText(ctrl, original);
1123
583
  }
@@ -1156,11 +616,11 @@ function consumeClosingTag(text, lt) {
1156
616
  }
1157
617
  function consumeOpenTag(text, lt) {
1158
618
  let p = lt + 1;
1159
- while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
619
+ while (p < text.length && WHITESPACE_REGEX.test(text[p])) {
1160
620
  p += 1;
1161
621
  }
1162
622
  const nameStart = p;
1163
- while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
623
+ while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
1164
624
  p += 1;
1165
625
  }
1166
626
  const name = text.slice(nameStart, p);
@@ -1169,7 +629,7 @@ function consumeOpenTag(text, lt) {
1169
629
  return null;
1170
630
  }
1171
631
  let r = q - 1;
1172
- while (r >= nameStart && WHITESPACE_REGEX2.test(text[r])) {
632
+ while (r >= nameStart && WHITESPACE_REGEX.test(text[r])) {
1173
633
  r -= 1;
1174
634
  }
1175
635
  const selfClosing = text[r] === "/";
@@ -1198,11 +658,11 @@ function nextTagToken(text, fromPos) {
1198
658
  if (next === "/") {
1199
659
  const closing = consumeClosingTag(text, lt);
1200
660
  let p = lt + 2;
1201
- while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
661
+ while (p < text.length && WHITESPACE_REGEX.test(text[p])) {
1202
662
  p += 1;
1203
663
  }
1204
664
  const nameStart = p;
1205
- while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
665
+ while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
1206
666
  p += 1;
1207
667
  }
1208
668
  const name = text.slice(nameStart, p);
@@ -1219,49 +679,111 @@ function nextTagToken(text, fromPos) {
1219
679
  nextPos: open.nextPos
1220
680
  };
1221
681
  }
682
+ function findNextToolTag(text, searchIndex, toolName) {
683
+ var _a, _b;
684
+ const startTag = `<${toolName}>`;
685
+ const openIdx = text.indexOf(startTag, searchIndex);
686
+ const selfMatch = findSelfClosingTag(text, toolName, searchIndex);
687
+ const selfIdx = (_a = selfMatch == null ? void 0 : selfMatch.index) != null ? _a : -1;
688
+ if (openIdx === -1 && selfIdx === -1) {
689
+ return null;
690
+ }
691
+ const isSelfClosing = selfIdx !== -1 && (openIdx === -1 || selfIdx < openIdx);
692
+ return {
693
+ tagStart: isSelfClosing ? selfIdx : openIdx,
694
+ isSelfClosing,
695
+ tagLength: isSelfClosing ? (_b = selfMatch == null ? void 0 : selfMatch.length) != null ? _b : 0 : startTag.length
696
+ };
697
+ }
698
+ function findLastCloseTagStart(segment, toolName) {
699
+ const closeTagPattern = new RegExp(
700
+ `</\\s*${escapeRegExp(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, tagLength) {
715
+ const endIndex = tagStart + tagLength;
716
+ toolCalls.push({
717
+ toolName,
718
+ startIndex: tagStart,
719
+ endIndex,
720
+ content: "",
721
+ segment: text.substring(tagStart, endIndex)
722
+ });
723
+ return endIndex;
724
+ }
725
+ var selfClosingTagCache = /* @__PURE__ */ new Map();
726
+ function getSelfClosingTagPattern(toolName) {
727
+ let pattern = selfClosingTagCache.get(toolName);
728
+ if (!pattern) {
729
+ pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
730
+ selfClosingTagCache.set(toolName, pattern);
731
+ }
732
+ return pattern;
733
+ }
734
+ function findSelfClosingTag(text, toolName, fromIndex) {
735
+ const pattern = getSelfClosingTagPattern(toolName);
736
+ pattern.lastIndex = fromIndex;
737
+ const match = pattern.exec(text);
738
+ if (!match || match.index === void 0) {
739
+ return null;
740
+ }
741
+ return { index: match.index, length: match[0].length };
742
+ }
743
+ function appendOpenToolCallIfComplete(toolCalls, text, toolName, tagStart, startTag) {
744
+ const contentStart = tagStart + startTag.length;
745
+ const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
746
+ if (fullTagEnd === -1 || fullTagEnd <= contentStart) {
747
+ return contentStart;
748
+ }
749
+ const segment = text.substring(tagStart, fullTagEnd);
750
+ const closeTagStart = findLastCloseTagStart(segment, toolName);
751
+ const inner = closeTagStart === -1 ? segment.slice(startTag.length) : segment.slice(startTag.length, closeTagStart);
752
+ toolCalls.push({
753
+ toolName,
754
+ startIndex: tagStart,
755
+ endIndex: fullTagEnd,
756
+ content: inner,
757
+ segment
758
+ });
759
+ return fullTagEnd;
760
+ }
1222
761
  function findToolCallsForName(text, toolName) {
1223
- var _a;
1224
762
  const toolCalls = [];
763
+ const startTag = `<${toolName}>`;
1225
764
  let searchIndex = 0;
1226
765
  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) {
766
+ const match = findNextToolTag(text, searchIndex, toolName);
767
+ if (match === null) {
1232
768
  break;
1233
769
  }
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({
770
+ if (match.isSelfClosing) {
771
+ searchIndex = pushSelfClosingToolCall(
772
+ toolCalls,
1240
773
  toolName,
1241
- startIndex: tagStart,
1242
- endIndex,
1243
- content: "",
1244
- segment
1245
- });
1246
- searchIndex = endIndex;
774
+ text,
775
+ match.tagStart,
776
+ match.tagLength
777
+ );
1247
778
  continue;
1248
779
  }
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
- }
780
+ searchIndex = appendOpenToolCallIfComplete(
781
+ toolCalls,
782
+ text,
783
+ toolName,
784
+ match.tagStart,
785
+ startTag
786
+ );
1265
787
  }
1266
788
  return toolCalls;
1267
789
  }
@@ -1274,28 +796,114 @@ function findToolCalls(text, toolNames) {
1274
796
  return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
1275
797
  }
1276
798
  function findEarliestToolTag(buffer, toolNames) {
799
+ var _a, _b;
1277
800
  let bestIndex = -1;
1278
801
  let bestName = "";
1279
802
  let bestSelfClosing = false;
803
+ let bestTagLength = 0;
1280
804
  if (toolNames.length > 0) {
1281
805
  for (const name of toolNames) {
1282
806
  const openTag = `<${name}>`;
1283
- const selfTag = `<${name}/>`;
1284
807
  const idxOpen = buffer.indexOf(openTag);
1285
- const idxSelf = buffer.indexOf(selfTag);
808
+ const selfMatch = findSelfClosingTag(buffer, name, 0);
809
+ const idxSelf = (_a = selfMatch == null ? void 0 : selfMatch.index) != null ? _a : -1;
1286
810
  if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
1287
811
  bestIndex = idxOpen;
1288
812
  bestName = name;
1289
813
  bestSelfClosing = false;
814
+ bestTagLength = openTag.length;
1290
815
  }
1291
816
  if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
1292
817
  bestIndex = idxSelf;
1293
818
  bestName = name;
1294
819
  bestSelfClosing = true;
820
+ bestTagLength = (_b = selfMatch == null ? void 0 : selfMatch.length) != null ? _b : 0;
821
+ }
822
+ }
823
+ }
824
+ return {
825
+ index: bestIndex,
826
+ name: bestName,
827
+ selfClosing: bestSelfClosing,
828
+ tagLength: bestTagLength
829
+ };
830
+ }
831
+ function isOpenTagPrefix(suffix, toolName) {
832
+ return `${toolName}>`.startsWith(suffix);
833
+ }
834
+ function consumeWhitespace(text, index) {
835
+ let i = index;
836
+ while (i < text.length && WHITESPACE_REGEX.test(text.charAt(i))) {
837
+ i += 1;
838
+ }
839
+ return i;
840
+ }
841
+ function consumeToolNamePrefix(text, index, toolName) {
842
+ let i = index;
843
+ let nameIndex = 0;
844
+ while (i < text.length && nameIndex < toolName.length) {
845
+ if (text.charAt(i) !== toolName.charAt(nameIndex)) {
846
+ return { index: i, done: false, valid: false };
847
+ }
848
+ i += 1;
849
+ nameIndex += 1;
850
+ }
851
+ return { index: i, done: nameIndex === toolName.length, valid: true };
852
+ }
853
+ function isSelfClosingSuffixRemainder(text, index) {
854
+ if (text.charAt(index) !== "/") {
855
+ return false;
856
+ }
857
+ if (index + 1 >= text.length) {
858
+ return true;
859
+ }
860
+ return index + 1 === text.length - 1 && text.charAt(index + 1) === ">";
861
+ }
862
+ function isSelfClosingTagPrefix(suffix, toolName) {
863
+ let i = consumeWhitespace(suffix, 0);
864
+ if (i >= suffix.length) {
865
+ return true;
866
+ }
867
+ const nameRemainder = suffix.slice(i);
868
+ if (toolName.startsWith(nameRemainder)) {
869
+ return true;
870
+ }
871
+ const nameResult = consumeToolNamePrefix(suffix, i, toolName);
872
+ if (!nameResult.valid) {
873
+ return false;
874
+ }
875
+ i = nameResult.index;
876
+ if (i >= suffix.length) {
877
+ return true;
878
+ }
879
+ if (!nameResult.done) {
880
+ return false;
881
+ }
882
+ i = consumeWhitespace(suffix, i);
883
+ if (i >= suffix.length) {
884
+ return true;
885
+ }
886
+ return isSelfClosingSuffixRemainder(suffix, i);
887
+ }
888
+ function findPotentialToolTagStart(buffer, toolNames) {
889
+ if (toolNames.length === 0 || buffer.length === 0) {
890
+ return -1;
891
+ }
892
+ const lastGt = buffer.lastIndexOf(">");
893
+ const offset = lastGt === -1 ? 0 : lastGt + 1;
894
+ const trailing = buffer.slice(offset);
895
+ for (let i = trailing.length - 1; i >= 0; i -= 1) {
896
+ if (trailing.charAt(i) !== "<") {
897
+ continue;
898
+ }
899
+ const suffix = trailing.slice(i + 1);
900
+ for (const name of toolNames) {
901
+ if (isOpenTagPrefix(suffix, name) || isSelfClosingTagPrefix(suffix, name)) {
902
+ return offset + i;
1295
903
  }
1296
904
  }
1297
905
  }
1298
- return { index: bestIndex, name: bestName, selfClosing: bestSelfClosing };
906
+ return -1;
1299
907
  }
1300
908
  function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
1301
909
  return (controller, text) => {
@@ -1338,16 +946,20 @@ function processToolCallInBuffer(params) {
1338
946
  controller,
1339
947
  flushText,
1340
948
  setBuffer,
1341
- pipelineConfig,
1342
- maxReparses
949
+ parseOptions
1343
950
  } = params;
1344
- const endTag = `</${currentToolCall.name}>`;
1345
- const endIdx = buffer.indexOf(endTag);
1346
- if (endIdx === -1) {
951
+ const endTagPattern = new RegExp(
952
+ `</\\s*${escapeRegExp(currentToolCall.name)}\\s*>`
953
+ );
954
+ const endMatch = endTagPattern.exec(buffer);
955
+ if (!endMatch || endMatch.index === void 0) {
1347
956
  return { buffer, currentToolCall, shouldBreak: true };
1348
957
  }
958
+ const endIdx = endMatch.index;
959
+ const endPos = endIdx + endMatch[0].length;
1349
960
  const content = buffer.substring(0, endIdx);
1350
- setBuffer(buffer.substring(endIdx + endTag.length));
961
+ const remainder = buffer.substring(endPos);
962
+ setBuffer(remainder);
1351
963
  handleStreamingToolCallEnd({
1352
964
  toolContent: content,
1353
965
  currentToolCall,
@@ -1355,11 +967,10 @@ function processToolCallInBuffer(params) {
1355
967
  options,
1356
968
  ctrl: controller,
1357
969
  flushText,
1358
- pipelineConfig,
1359
- maxReparses
970
+ parseOptions
1360
971
  });
1361
972
  return {
1362
- buffer: buffer.substring(endIdx + endTag.length),
973
+ buffer: remainder,
1363
974
  currentToolCall: null,
1364
975
  shouldBreak: false
1365
976
  };
@@ -1372,25 +983,28 @@ function processNoToolCallInBuffer(params) {
1372
983
  flushText,
1373
984
  tools,
1374
985
  options,
1375
- pipelineConfig,
1376
- maxReparses,
986
+ parseOptions,
1377
987
  setBuffer
1378
988
  } = params;
1379
989
  const {
1380
990
  index: earliestStartTagIndex,
1381
991
  name: earliestToolName,
1382
- selfClosing
992
+ selfClosing,
993
+ tagLength
1383
994
  } = findEarliestToolTag(buffer, toolNames);
1384
995
  if (earliestStartTagIndex === -1) {
1385
- const maxTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n}>`.length)) : 0;
1386
- const tail = Math.max(0, maxTagLen - 1);
1387
- const safeLen = Math.max(0, buffer.length - tail);
996
+ const potentialStart = findPotentialToolTagStart(buffer, toolNames);
997
+ const safeLen = Math.max(
998
+ 0,
999
+ potentialStart === -1 ? buffer.length : potentialStart
1000
+ );
1001
+ const remaining = buffer.slice(safeLen);
1388
1002
  if (safeLen > 0) {
1389
1003
  flushText(controller, buffer.slice(0, safeLen));
1390
- setBuffer(buffer.slice(safeLen));
1004
+ setBuffer(remaining);
1391
1005
  }
1392
1006
  return {
1393
- buffer: buffer.slice(safeLen),
1007
+ buffer: remaining,
1394
1008
  currentToolCall: null,
1395
1009
  shouldBreak: true,
1396
1010
  shouldContinue: false
@@ -1398,8 +1012,7 @@ function processNoToolCallInBuffer(params) {
1398
1012
  }
1399
1013
  flushText(controller, buffer.substring(0, earliestStartTagIndex));
1400
1014
  if (selfClosing) {
1401
- const selfTag = `<${earliestToolName}/>`;
1402
- const newBuffer2 = buffer.substring(earliestStartTagIndex + selfTag.length);
1015
+ const newBuffer2 = buffer.substring(earliestStartTagIndex + tagLength);
1403
1016
  setBuffer(newBuffer2);
1404
1017
  handleStreamingToolCallEnd({
1405
1018
  toolContent: "",
@@ -1408,8 +1021,7 @@ function processNoToolCallInBuffer(params) {
1408
1021
  options,
1409
1022
  ctrl: controller,
1410
1023
  flushText,
1411
- pipelineConfig,
1412
- maxReparses
1024
+ parseOptions
1413
1025
  });
1414
1026
  return {
1415
1027
  buffer: newBuffer2,
@@ -1428,7 +1040,7 @@ function processNoToolCallInBuffer(params) {
1428
1040
  shouldContinue: true
1429
1041
  };
1430
1042
  }
1431
- function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, pipelineConfig, maxReparses) {
1043
+ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions) {
1432
1044
  return (controller) => {
1433
1045
  while (true) {
1434
1046
  const currentToolCall = getCurrentToolCall();
@@ -1441,8 +1053,7 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
1441
1053
  controller,
1442
1054
  flushText,
1443
1055
  setBuffer,
1444
- pipelineConfig,
1445
- maxReparses
1056
+ parseOptions
1446
1057
  });
1447
1058
  setBuffer(result.buffer);
1448
1059
  setCurrentToolCall(result.currentToolCall);
@@ -1457,8 +1068,7 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
1457
1068
  flushText,
1458
1069
  tools,
1459
1070
  options,
1460
- pipelineConfig,
1461
- maxReparses,
1071
+ parseOptions,
1462
1072
  setBuffer
1463
1073
  });
1464
1074
  setBuffer(result.buffer);
@@ -1475,43 +1085,12 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
1475
1085
  };
1476
1086
  }
1477
1087
  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
- }
1088
+ var _a;
1089
+ const parseOptions = {
1090
+ repair: true,
1091
+ noChildNodes: [],
1092
+ ...(_a = protocolOptions == null ? void 0 : protocolOptions.parseOptions) != null ? _a : {}
1093
+ };
1515
1094
  return {
1516
1095
  formatTools({ tools, toolSystemPromptTemplate }) {
1517
1096
  return toolSystemPromptTemplate(tools || []);
@@ -1546,14 +1125,13 @@ var xmlProtocol = (protocolOptions) => {
1546
1125
  text: text.substring(currentIndex, tc.startIndex)
1547
1126
  });
1548
1127
  }
1549
- processToolCallWithPipeline({
1128
+ processToolCall({
1550
1129
  toolCall: tc,
1551
1130
  tools,
1552
1131
  options,
1553
1132
  text,
1554
1133
  processedElements,
1555
- pipelineConfig,
1556
- maxReparses
1134
+ parseOptions
1557
1135
  });
1558
1136
  currentIndex = tc.endIndex;
1559
1137
  }
@@ -1594,8 +1172,7 @@ var xmlProtocol = (protocolOptions) => {
1594
1172
  options,
1595
1173
  toolNames,
1596
1174
  flushText,
1597
- pipelineConfig,
1598
- maxReparses
1175
+ parseOptions
1599
1176
  );
1600
1177
  return new TransformStream({
1601
1178
  transform(chunk, controller) {
@@ -1645,8 +1222,8 @@ var xmlProtocol = (protocolOptions) => {
1645
1222
 
1646
1223
  // src/core/protocols/yaml-protocol.ts
1647
1224
  import YAML from "yaml";
1648
- var NAME_CHAR_RE3 = /[A-Za-z0-9_:-]/;
1649
- var WHITESPACE_REGEX3 = /\s/;
1225
+ var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
1226
+ var WHITESPACE_REGEX2 = /\s/;
1650
1227
  var LEADING_WHITESPACE_RE = /^(\s*)/;
1651
1228
  function findClosingTagEnd(text, contentStart, toolName) {
1652
1229
  let pos = contentStart;
@@ -1663,11 +1240,11 @@ function findClosingTagEnd(text, contentStart, toolName) {
1663
1240
  break;
1664
1241
  }
1665
1242
  let p = ltIdx + 2;
1666
- while (p < gtIdx && WHITESPACE_REGEX3.test(text[p])) {
1243
+ while (p < gtIdx && WHITESPACE_REGEX2.test(text[p])) {
1667
1244
  p++;
1668
1245
  }
1669
1246
  const nameStart = p;
1670
- while (p < gtIdx && NAME_CHAR_RE3.test(text.charAt(p))) {
1247
+ while (p < gtIdx && NAME_CHAR_RE2.test(text.charAt(p))) {
1671
1248
  p++;
1672
1249
  }
1673
1250
  const name = text.slice(nameStart, p);
@@ -1683,11 +1260,11 @@ function findClosingTagEnd(text, contentStart, toolName) {
1683
1260
  pos = gtIdx === -1 ? text.length : gtIdx + 1;
1684
1261
  } else {
1685
1262
  let p = ltIdx + 1;
1686
- while (p < text.length && WHITESPACE_REGEX3.test(text[p])) {
1263
+ while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
1687
1264
  p++;
1688
1265
  }
1689
1266
  const nameStart = p;
1690
- while (p < text.length && NAME_CHAR_RE3.test(text.charAt(p))) {
1267
+ while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
1691
1268
  p++;
1692
1269
  }
1693
1270
  const name = text.slice(nameStart, p);
@@ -1696,7 +1273,7 @@ function findClosingTagEnd(text, contentStart, toolName) {
1696
1273
  break;
1697
1274
  }
1698
1275
  let r = gtIdx - 1;
1699
- while (r >= nameStart && WHITESPACE_REGEX3.test(text[r])) {
1276
+ while (r >= nameStart && WHITESPACE_REGEX2.test(text[r])) {
1700
1277
  r--;
1701
1278
  }
1702
1279
  const selfClosing = text[r] === "/";
@@ -2201,7 +1778,7 @@ function hasInputProperty(obj) {
2201
1778
 
2202
1779
  // src/generate-handler.ts
2203
1780
  import { generateId as generateId2 } from "@ai-sdk/provider-utils";
2204
- import { coerceBySchema } from "@ai-sdk-tool/rxml";
1781
+ import { coerceBySchema } from "@ai-sdk-tool/schema-coerce";
2205
1782
  function parseToolChoiceJson(text, providerOptions) {
2206
1783
  var _a;
2207
1784
  try {
@@ -2496,29 +2073,230 @@ function formatXmlNode(tagName, value, depth) {
2496
2073
  }
2497
2074
 
2498
2075
  // src/core/prompts/xml-system-prompt.ts
2076
+ import dedent from "dedent";
2499
2077
  function xmlSystemPromptTemplate(tools) {
2500
- const toolsJson = JSON.stringify(tools);
2501
- return `# Tools
2502
-
2503
- You may call one or more functions to assist with the user query.
2504
-
2505
- You are provided with function signatures within <tools></tools> XML tags:
2506
- <tools>${toolsJson}</tools>
2507
-
2508
- # Rules
2509
- - Use exactly one XML element whose tag name is the function name.
2510
- - Put each parameter as a child element.
2511
- - Values must follow the schema exactly (numbers, arrays, objects, enums \u2192 copy as-is).
2512
- - Do not add or remove functions or parameters.
2513
- - Each required parameter must appear once.
2514
- - Output nothing before or after the function call.
2515
- - 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.
2516
-
2517
- # Example
2518
- <get_weather>
2519
- <location>New York</location>
2520
- <unit>celsius</unit>
2521
- </get_weather>`;
2078
+ const toolsText = renderToolsForXmlPrompt(tools);
2079
+ const header = dedent`
2080
+ # Tools
2081
+ You may call one or more functions to assist with the user query.
2082
+ `;
2083
+ const definitions = [
2084
+ "You have access to the following functions:",
2085
+ "<tools>",
2086
+ toolsText,
2087
+ "</tools>"
2088
+ ].join("\n");
2089
+ const rules = dedent`
2090
+ <rules>
2091
+ - Use exactly one XML element whose tag name is the function name.
2092
+ - Put each parameter as a child element.
2093
+ - Values must follow the schema exactly (numbers, arrays, objects, enums copy as-is).
2094
+ - Do not add or remove functions or parameters.
2095
+ - Each required parameter must appear once.
2096
+ - Output nothing before or after the function call.
2097
+ - It is also possible to call multiple types of functions in one turn or to call a single function multiple times.
2098
+ </rules>
2099
+ `;
2100
+ const examples = dedent`
2101
+ For each function call, output the function name and parameter in the following format:
2102
+ <example_function_name>
2103
+ <example_parameter_1>value_1</example_parameter_1>
2104
+ <example_parameter_2>This is the value for the second parameter
2105
+ that can span
2106
+ multiple lines</example_parameter_2>
2107
+ </example_function_name>
2108
+ `;
2109
+ return [header, definitions, rules, examples].join("\n\n");
2110
+ }
2111
+ var INDENT = " ";
2112
+ function renderToolsForXmlPrompt(tools) {
2113
+ if (!tools.length) {
2114
+ return "none";
2115
+ }
2116
+ return tools.map(renderToolForXmlPrompt).join("\n\n");
2117
+ }
2118
+ function renderToolForXmlPrompt(tool) {
2119
+ const lines = [`name: ${tool.name}`];
2120
+ if (tool.description) {
2121
+ lines.push(`description: ${tool.description}`);
2122
+ }
2123
+ lines.push("parameters:");
2124
+ const normalizedSchema = normalizeSchema(tool.inputSchema);
2125
+ lines.push(...renderParametersSummary(normalizedSchema, 1));
2126
+ lines.push(`schema: ${stringifySchema(normalizedSchema)}`);
2127
+ return lines.join("\n");
2128
+ }
2129
+ function normalizeSchema(schema) {
2130
+ if (typeof schema === "string") {
2131
+ try {
2132
+ return JSON.parse(schema);
2133
+ } catch (e) {
2134
+ return { type: "string", const: schema };
2135
+ }
2136
+ }
2137
+ return schema;
2138
+ }
2139
+ function renderParametersSummary(schema, indentLevel) {
2140
+ var _a, _b;
2141
+ const indent = INDENT.repeat(indentLevel);
2142
+ if (schema === void 0 || schema === null) {
2143
+ return [`${indent}(none)`];
2144
+ }
2145
+ if (schema === true) {
2146
+ return [`${indent}(any)`];
2147
+ }
2148
+ if (schema === false) {
2149
+ return [`${indent}(no valid parameters)`];
2150
+ }
2151
+ if (typeof schema !== "object") {
2152
+ return [`${indent}- value (${String(schema)})`];
2153
+ }
2154
+ const schemaType = [];
2155
+ if (Array.isArray(schema.type)) {
2156
+ schemaType.push(...schema.type);
2157
+ } else if (schema.type) {
2158
+ schemaType.push(schema.type);
2159
+ }
2160
+ const isObjectLike = schemaType.includes("object") || !!schema.properties;
2161
+ if (isObjectLike) {
2162
+ const properties = (_a = schema.properties) != null ? _a : {};
2163
+ const requiredSet = new Set((_b = schema.required) != null ? _b : []);
2164
+ const propertyNames = Object.keys(properties).sort();
2165
+ if (propertyNames.length === 0) {
2166
+ return [`${indent}(no named parameters)`];
2167
+ }
2168
+ const lines = [];
2169
+ for (const propName of propertyNames) {
2170
+ const propSchema = properties[propName];
2171
+ lines.push(
2172
+ renderPropertySummaryLine({
2173
+ indent,
2174
+ propName,
2175
+ propSchema,
2176
+ required: requiredSet.has(propName)
2177
+ })
2178
+ );
2179
+ }
2180
+ return lines.length ? lines : [`${indent}(no parameters)`];
2181
+ }
2182
+ return [`${indent}- value (${summarizeType(schema)})`];
2183
+ }
2184
+ function renderPropertySummaryLine({
2185
+ indent,
2186
+ propName,
2187
+ propSchema,
2188
+ required
2189
+ }) {
2190
+ const typeLabel = summarizeType(propSchema);
2191
+ const requiredLabel = required ? "required" : "optional";
2192
+ const extras = collectPropertyExtras(propSchema);
2193
+ const extraText = extras.length ? ` - ${extras.join("; ")}` : "";
2194
+ return `${indent}- ${propName} (${typeLabel}, ${requiredLabel})${extraText}`;
2195
+ }
2196
+ function collectPropertyExtras(propSchema) {
2197
+ if (!propSchema || typeof propSchema !== "object") {
2198
+ return [];
2199
+ }
2200
+ const extras = [];
2201
+ if (propSchema.enum) {
2202
+ extras.push(`enum: ${formatEnumForSummary(propSchema.enum)}`);
2203
+ }
2204
+ if (propSchema.default !== void 0) {
2205
+ extras.push(`default: ${formatValue(propSchema.default)}`);
2206
+ }
2207
+ if (propSchema.description) {
2208
+ extras.push(propSchema.description);
2209
+ }
2210
+ return extras;
2211
+ }
2212
+ function summarizeType(schema) {
2213
+ var _a;
2214
+ if (schema === void 0 || schema === null) {
2215
+ return "unknown";
2216
+ }
2217
+ if (schema === true) {
2218
+ return "any";
2219
+ }
2220
+ if (schema === false) {
2221
+ return "never";
2222
+ }
2223
+ if (typeof schema !== "object") {
2224
+ return String(schema);
2225
+ }
2226
+ const schemaType = schema.type;
2227
+ let baseType = "";
2228
+ if (Array.isArray(schemaType) && schemaType.length) {
2229
+ baseType = schemaType.join(" | ");
2230
+ } else if (typeof schemaType === "string") {
2231
+ baseType = schemaType;
2232
+ } else if (schema.enum) {
2233
+ const inferred = Array.from(
2234
+ new Set(schema.enum.map((value) => typeof value))
2235
+ );
2236
+ if (inferred.length === 1) {
2237
+ baseType = (_a = inferred[0]) != null ? _a : "";
2238
+ }
2239
+ } else if (schema.const !== void 0) {
2240
+ baseType = typeof schema.const;
2241
+ }
2242
+ if (!baseType) {
2243
+ baseType = "any";
2244
+ }
2245
+ if (baseType === "array" && schema.items) {
2246
+ const itemType = Array.isArray(schema.items) ? schema.items.map((item) => summarizeType(item)).join(" | ") : summarizeType(schema.items);
2247
+ return `array<${itemType}>`;
2248
+ }
2249
+ if (baseType === "string" && schema.format) {
2250
+ return `string (${schema.format})`;
2251
+ }
2252
+ return baseType;
2253
+ }
2254
+ var ENUM_MAX_INLINE = 6;
2255
+ var ENUM_PREVIEW_LIMIT = 5;
2256
+ function formatEnumForSummary(values) {
2257
+ if (values.length <= ENUM_MAX_INLINE) {
2258
+ return formatValue(values);
2259
+ }
2260
+ const preview = values.slice(0, ENUM_PREVIEW_LIMIT).map((value) => formatValue(value));
2261
+ return `[${preview.join(", ")}, ... (${values.length} total)]`;
2262
+ }
2263
+ function formatValue(value) {
2264
+ if (typeof value === "string") {
2265
+ return JSON.stringify(value);
2266
+ }
2267
+ if (typeof value === "number" || typeof value === "boolean") {
2268
+ return String(value);
2269
+ }
2270
+ if (value === null) {
2271
+ return "null";
2272
+ }
2273
+ if (Array.isArray(value)) {
2274
+ return `[${value.map(formatValue).join(", ")}]`;
2275
+ }
2276
+ return JSON.stringify(value);
2277
+ }
2278
+ function stringifySchema(schema) {
2279
+ if (schema === void 0) {
2280
+ return "null";
2281
+ }
2282
+ return JSON.stringify(stripSchemaKeys(schema));
2283
+ }
2284
+ function stripSchemaKeys(value) {
2285
+ if (Array.isArray(value)) {
2286
+ return value.map((entry) => stripSchemaKeys(entry));
2287
+ }
2288
+ if (value && typeof value === "object") {
2289
+ const record = value;
2290
+ const cleaned = {};
2291
+ for (const [key, entry] of Object.entries(record)) {
2292
+ if (key === "$schema") {
2293
+ continue;
2294
+ }
2295
+ cleaned[key] = stripSchemaKeys(entry);
2296
+ }
2297
+ return cleaned;
2298
+ }
2299
+ return value;
2522
2300
  }
2523
2301
 
2524
2302
  // src/core/prompts/yaml-system-prompt.ts
@@ -3027,20 +2805,12 @@ function createToolMiddleware({
3027
2805
  const resolvedProtocol = isTCMProtocolFactory(protocol) ? protocol() : protocol;
3028
2806
  return {
3029
2807
  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
- },
2808
+ wrapStream: ({ doStream, doGenerate, params }) => wrapStream({
2809
+ protocol: resolvedProtocol,
2810
+ doStream,
2811
+ doGenerate,
2812
+ params
2813
+ }),
3044
2814
  wrapGenerate: async ({ doGenerate, params }) => wrapGenerate({
3045
2815
  protocol: resolvedProtocol,
3046
2816
  doGenerate,
@@ -3074,22 +2844,13 @@ var yamlToolMiddleware = createToolMiddleware({
3074
2844
  });
3075
2845
 
3076
2846
  export {
3077
- applyHeuristicPipeline,
3078
- createIntermediateCall,
3079
- mergePipelineConfigs,
3080
- normalizeCloseTagsHeuristic,
3081
- escapeInvalidLtHeuristic,
3082
- balanceTagsHeuristic,
3083
- dedupeShellStringTagsHeuristic,
3084
- repairAgainstSchemaHeuristic,
3085
- defaultPipelineConfig,
3086
2847
  getDebugLevel,
3087
2848
  logParseFailure,
3088
2849
  logRawChunk,
3089
2850
  logParsedChunk,
3090
2851
  logParsedSummary,
3091
2852
  getPotentialStartIndex,
3092
- escapeRegExp2 as escapeRegExp,
2853
+ escapeRegExp,
3093
2854
  jsonProtocol,
3094
2855
  isProtocolFactory,
3095
2856
  isTCMProtocolFactory,
@@ -3113,4 +2874,4 @@ export {
3113
2874
  xmlToolMiddleware,
3114
2875
  yamlToolMiddleware
3115
2876
  };
3116
- //# sourceMappingURL=chunk-3KQVEBKO.js.map
2877
+ //# sourceMappingURL=chunk-DCK5APVO.js.map