@ai-sdk-tool/parser 3.2.0 → 3.3.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.
@@ -17,7 +17,6 @@ var __copyProps = (to, from, except, desc) => {
17
17
  }
18
18
  return to;
19
19
  };
20
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
21
20
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
21
  // If the importer is in node compatibility mode or this is not an ESM
23
22
  // file that has been converted to a CommonJS file using a Babel-
@@ -36,43 +35,642 @@ __export(community_exports, {
36
35
  });
37
36
  module.exports = __toCommonJS(community_exports);
38
37
 
39
- // src/index.ts
40
- var src_exports = {};
41
- __export(src_exports, {
42
- createDynamicIfThenElseSchema: () => createDynamicIfThenElseSchema,
43
- createToolMiddleware: () => createToolMiddleware,
44
- decodeOriginalTools: () => decodeOriginalTools,
45
- encodeOriginalTools: () => encodeOriginalTools,
46
- escapeRegExp: () => escapeRegExp,
47
- extractOnErrorOption: () => extractOnErrorOption,
48
- extractToolNamesFromOriginalTools: () => extractToolNamesFromOriginalTools,
49
- getDebugLevel: () => getDebugLevel,
50
- getPotentialStartIndex: () => getPotentialStartIndex,
51
- hasInputProperty: () => hasInputProperty,
52
- hermesToolMiddleware: () => hermesToolMiddleware,
53
- isProtocolFactory: () => isProtocolFactory,
54
- isTCMProtocolFactory: () => isTCMProtocolFactory,
55
- isToolChoiceActive: () => isToolChoiceActive,
56
- isToolResultPart: () => isToolResultPart,
57
- jsonProtocol: () => jsonProtocol,
58
- logParseFailure: () => logParseFailure,
59
- logParsedChunk: () => logParsedChunk,
60
- logParsedSummary: () => logParsedSummary,
61
- logRawChunk: () => logRawChunk,
62
- originalToolsSchema: () => originalToolsSchema,
63
- toolChoiceStream: () => toolChoiceStream,
64
- transformParams: () => transformParams,
65
- wrapGenerate: () => wrapGenerate,
66
- wrapStream: () => wrapStream,
67
- xmlProtocol: () => xmlProtocol,
68
- xmlToolMiddleware: () => xmlToolMiddleware,
69
- yamlProtocol: () => yamlProtocol,
70
- yamlToolMiddleware: () => yamlToolMiddleware
71
- });
72
- __reExport(src_exports, require("@ai-sdk-tool/rjson"));
73
-
74
- // src/core/protocols/json-protocol.ts
75
- var import_rjson = require("@ai-sdk-tool/rjson");
38
+ // src/rjson/index.ts
39
+ var WHITESPACE_TEST_REGEX = /\s/;
40
+ var WHITESPACE_REGEX = /^\s+/;
41
+ var OBJECT_START_REGEX = /^\{/;
42
+ var OBJECT_END_REGEX = /^\}/;
43
+ var ARRAY_START_REGEX = /^\[/;
44
+ var ARRAY_END_REGEX = /^\]/;
45
+ var COMMA_REGEX = /^,/;
46
+ var COLON_REGEX = /^:/;
47
+ var KEYWORD_REGEX = /^(?:true|false|null)/;
48
+ var NUMBER_REGEX = /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/;
49
+ var STRING_DOUBLE_REGEX = /^"(?:[^"\\]|\\["bnrtf\\/]|\\u[0-9a-fA-F]{4})*"/;
50
+ var STRING_SINGLE_REGEX = /^'((?:[^'\\]|\\['bnrtf\\/]|\\u[0-9a-fA-F]{4})*)'/;
51
+ var COMMENT_SINGLE_REGEX = /^\/\/.*?(?:\r\n|\r|\n)/;
52
+ var COMMENT_MULTI_REGEX = /^\/\*[\s\S]*?\*\//;
53
+ var IDENTIFIER_REGEX = /^[$a-zA-Z0-9_\-+.*?!|&%^/#\\]+/;
54
+ function some(array, f) {
55
+ let acc = false;
56
+ for (let i = 0; i < array.length; i += 1) {
57
+ const result = f(array[i], i, array);
58
+ acc = result === void 0 ? false : result;
59
+ if (acc) {
60
+ return acc;
61
+ }
62
+ }
63
+ return acc;
64
+ }
65
+ function makeLexer(tokenSpecs) {
66
+ return (contents) => {
67
+ const tokens = [];
68
+ let line = 1;
69
+ let remainingContents = contents;
70
+ function findToken() {
71
+ const result = some(tokenSpecs, (tokenSpec) => {
72
+ const m = tokenSpec.re.exec(remainingContents);
73
+ if (m) {
74
+ const raw = m[0];
75
+ remainingContents = remainingContents.slice(raw.length);
76
+ return {
77
+ raw,
78
+ matched: tokenSpec.f(m)
79
+ // Process the match using the spec's function
80
+ };
81
+ }
82
+ return;
83
+ });
84
+ return result === false ? void 0 : result;
85
+ }
86
+ while (remainingContents !== "") {
87
+ const matched = findToken();
88
+ if (!matched) {
89
+ const err = new SyntaxError(
90
+ `Unexpected character: ${remainingContents[0]}; input: ${remainingContents.substr(
91
+ 0,
92
+ 100
93
+ )}`
94
+ );
95
+ err.line = line;
96
+ throw err;
97
+ }
98
+ const tokenWithLine = matched.matched;
99
+ tokenWithLine.line = line;
100
+ line += matched.raw.replace(/[^\n]/g, "").length;
101
+ tokens.push(tokenWithLine);
102
+ }
103
+ return tokens;
104
+ };
105
+ }
106
+ function fStringSingle(m) {
107
+ const content = m[1].replace(
108
+ /([^'\\]|\\['bnrtf\\]|\\u[0-9a-fA-F]{4})/g,
109
+ (mm) => {
110
+ if (mm === '"') {
111
+ return '\\"';
112
+ }
113
+ if (mm === "\\'") {
114
+ return "'";
115
+ }
116
+ return mm;
117
+ }
118
+ );
119
+ const match = `"${content}"`;
120
+ return {
121
+ type: "string",
122
+ match,
123
+ // The transformed, double-quoted string representation
124
+ // Use JSON.parse on the transformed string to handle escape sequences correctly
125
+ value: JSON.parse(match)
126
+ };
127
+ }
128
+ function fStringDouble(m) {
129
+ return {
130
+ type: "string",
131
+ match: m[0],
132
+ // The raw matched string (including quotes)
133
+ value: JSON.parse(m[0])
134
+ // Use JSON.parse to handle escapes and get the value
135
+ };
136
+ }
137
+ function fIdentifier(m) {
138
+ const value = m[0];
139
+ const match = '"' + value.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + // Escape backslashes and quotes
140
+ '"';
141
+ return {
142
+ type: "string",
143
+ // Treat identifiers as strings
144
+ value,
145
+ // The original identifier name
146
+ match
147
+ // The double-quoted string representation
148
+ };
149
+ }
150
+ function fComment(m) {
151
+ const match = m[0].replace(
152
+ /./g,
153
+ (c) => WHITESPACE_TEST_REGEX.test(c) ? c : " "
154
+ );
155
+ return {
156
+ type: " ",
157
+ // Represent comments as whitespace tokens
158
+ match,
159
+ // String containing original newlines and spaces for other chars
160
+ value: void 0
161
+ // Comments don't have a semantic value
162
+ };
163
+ }
164
+ function fNumber(m) {
165
+ return {
166
+ type: "number",
167
+ match: m[0],
168
+ // The raw matched number string
169
+ value: Number.parseFloat(m[0])
170
+ // Convert string to number
171
+ };
172
+ }
173
+ function fKeyword(m) {
174
+ let value;
175
+ switch (m[0]) {
176
+ case "null":
177
+ value = null;
178
+ break;
179
+ case "true":
180
+ value = true;
181
+ break;
182
+ case "false":
183
+ value = false;
184
+ break;
185
+ default:
186
+ throw new Error(`Unexpected keyword: ${m[0]}`);
187
+ }
188
+ return {
189
+ type: "atom",
190
+ // Use 'atom' type for these literals
191
+ match: m[0],
192
+ // The raw matched keyword
193
+ value
194
+ // The corresponding JavaScript value
195
+ };
196
+ }
197
+ function makeTokenSpecs(relaxed) {
198
+ function f(type) {
199
+ return (m) => {
200
+ return { type, match: m[0], value: void 0 };
201
+ };
202
+ }
203
+ let tokenSpecs = [
204
+ { re: WHITESPACE_REGEX, f: f(" ") },
205
+ // Whitespace
206
+ { re: OBJECT_START_REGEX, f: f("{") },
207
+ // Object start
208
+ { re: OBJECT_END_REGEX, f: f("}") },
209
+ // Object end
210
+ { re: ARRAY_START_REGEX, f: f("[") },
211
+ // Array start
212
+ { re: ARRAY_END_REGEX, f: f("]") },
213
+ // Array end
214
+ { re: COMMA_REGEX, f: f(",") },
215
+ // Comma separator
216
+ { re: COLON_REGEX, f: f(":") },
217
+ // Key-value separator
218
+ { re: KEYWORD_REGEX, f: fKeyword },
219
+ // Keywords
220
+ // Number: optional sign, digits, optional decimal part, optional exponent
221
+ { re: NUMBER_REGEX, f: fNumber },
222
+ // String: double-quoted, handles escapes
223
+ { re: STRING_DOUBLE_REGEX, f: fStringDouble }
224
+ ];
225
+ if (relaxed) {
226
+ tokenSpecs = tokenSpecs.concat([
227
+ // Single-quoted strings
228
+ {
229
+ re: STRING_SINGLE_REGEX,
230
+ f: fStringSingle
231
+ },
232
+ // Single-line comments (// ...)
233
+ { re: COMMENT_SINGLE_REGEX, f: fComment },
234
+ // Multi-line comments (/* ... */)
235
+ { re: COMMENT_MULTI_REGEX, f: fComment },
236
+ // Unquoted identifiers (treated as strings)
237
+ // Allows letters, numbers, _, -, +, ., *, ?, !, |, &, %, ^, /, #, \
238
+ { re: IDENTIFIER_REGEX, f: fIdentifier }
239
+ // Note: The order matters here. Identifiers are checked after keywords/numbers.
240
+ ]);
241
+ }
242
+ return tokenSpecs;
243
+ }
244
+ var lexer = makeLexer(makeTokenSpecs(true));
245
+ var strictLexer = makeLexer(makeTokenSpecs(false));
246
+ function previousNWSToken(tokens, index) {
247
+ let currentIndex = index;
248
+ for (; currentIndex >= 0; currentIndex -= 1) {
249
+ if (tokens[currentIndex].type !== " ") {
250
+ return currentIndex;
251
+ }
252
+ }
253
+ return;
254
+ }
255
+ function stripTrailingComma(tokens) {
256
+ const res = [];
257
+ tokens.forEach((token, index) => {
258
+ if (index > 0 && (token.type === "]" || token.type === "}")) {
259
+ const prevNWSTokenIndex = previousNWSToken(res, res.length - 1);
260
+ if (prevNWSTokenIndex !== void 0 && res[prevNWSTokenIndex].type === ",") {
261
+ const preCommaIndex = previousNWSToken(res, prevNWSTokenIndex - 1);
262
+ if (preCommaIndex !== void 0 && res[preCommaIndex].type !== "[" && res[preCommaIndex].type !== "{") {
263
+ res[prevNWSTokenIndex] = {
264
+ type: " ",
265
+ match: " ",
266
+ // Represent as a single space
267
+ value: void 0,
268
+ // Whitespace has no value
269
+ line: res[prevNWSTokenIndex].line
270
+ // Preserve original line number
271
+ };
272
+ }
273
+ }
274
+ }
275
+ res.push(token);
276
+ });
277
+ return res;
278
+ }
279
+ function popToken(tokens, state) {
280
+ var _a, _b;
281
+ const token = tokens[state.pos];
282
+ state.pos += 1;
283
+ if (!token) {
284
+ const lastLine = tokens.length !== 0 ? (_b = (_a = tokens.at(-1)) == null ? void 0 : _a.line) != null ? _b : 1 : 1;
285
+ return { type: "eof", match: "", value: void 0, line: lastLine };
286
+ }
287
+ return token;
288
+ }
289
+ function strToken(token) {
290
+ switch (token.type) {
291
+ case "atom":
292
+ case "string":
293
+ case "number":
294
+ return `${token.type} ${token.match}`;
295
+ case "eof":
296
+ return "end-of-file";
297
+ default:
298
+ return `'${token.type}'`;
299
+ }
300
+ }
301
+ function skipColon(tokens, state) {
302
+ const colon = popToken(tokens, state);
303
+ if (colon.type !== ":") {
304
+ const message = `Unexpected token: ${strToken(colon)}, expected ':'`;
305
+ if (state.tolerant) {
306
+ state.warnings.push({
307
+ message,
308
+ line: colon.line
309
+ });
310
+ state.pos -= 1;
311
+ } else {
312
+ const err = new SyntaxError(message);
313
+ err.line = colon.line;
314
+ throw err;
315
+ }
316
+ }
317
+ }
318
+ function skipPunctuation(tokens, state, valid) {
319
+ const punctuation = [",", ":", "]", "}"];
320
+ let token = popToken(tokens, state);
321
+ while (true) {
322
+ if (valid == null ? void 0 : valid.includes(token.type)) {
323
+ return token;
324
+ }
325
+ if (token.type === "eof") {
326
+ return token;
327
+ }
328
+ if (punctuation.includes(token.type)) {
329
+ const message = `Unexpected token: ${strToken(
330
+ token
331
+ )}, expected '[', '{', number, string or atom`;
332
+ if (state.tolerant) {
333
+ state.warnings.push({
334
+ message,
335
+ line: token.line
336
+ });
337
+ token = popToken(tokens, state);
338
+ } else {
339
+ const err = new SyntaxError(message);
340
+ err.line = token.line;
341
+ throw err;
342
+ }
343
+ } else {
344
+ return token;
345
+ }
346
+ }
347
+ }
348
+ function raiseError(state, token, message) {
349
+ if (state.tolerant) {
350
+ state.warnings.push({
351
+ message,
352
+ line: token.line
353
+ });
354
+ } else {
355
+ const err = new SyntaxError(message);
356
+ err.line = token.line;
357
+ throw err;
358
+ }
359
+ }
360
+ function raiseUnexpected(state, token, expected) {
361
+ raiseError(
362
+ state,
363
+ token,
364
+ `Unexpected token: ${strToken(token)}, expected ${expected}`
365
+ );
366
+ }
367
+ function checkDuplicates(state, obj, token) {
368
+ const key = String(token.value);
369
+ if (!state.duplicate && Object.hasOwn(obj, key)) {
370
+ raiseError(state, token, `Duplicate key: ${key}`);
371
+ }
372
+ }
373
+ function appendPair(state, obj, key, value) {
374
+ const finalValue = state.reviver ? state.reviver(key, value) : value;
375
+ if (finalValue !== void 0) {
376
+ obj[key] = finalValue;
377
+ }
378
+ }
379
+ function parsePair(tokens, state, obj) {
380
+ let token = skipPunctuation(tokens, state, [":", "string", "number", "atom"]);
381
+ let value;
382
+ if (token.type !== "string") {
383
+ raiseUnexpected(state, token, "string key");
384
+ if (state.tolerant) {
385
+ switch (token.type) {
386
+ case ":":
387
+ token = {
388
+ type: "string",
389
+ value: "null",
390
+ match: '"null"',
391
+ line: token.line
392
+ };
393
+ state.pos -= 1;
394
+ break;
395
+ case "number":
396
+ // Use number as string key
397
+ case "atom":
398
+ token = {
399
+ type: "string",
400
+ value: String(token.value),
401
+ match: `"${token.value}"`,
402
+ line: token.line
403
+ };
404
+ break;
405
+ case "[":
406
+ // Assume missing key before an array
407
+ case "{":
408
+ state.pos -= 1;
409
+ value = parseAny(tokens, state);
410
+ checkDuplicates(state, obj, {
411
+ type: "string",
412
+ value: "null",
413
+ match: '"null"',
414
+ line: token.line
415
+ });
416
+ appendPair(state, obj, "null", value);
417
+ return;
418
+ // Finished parsing this "pair"
419
+ case "eof":
420
+ return;
421
+ // Cannot recover
422
+ default:
423
+ return;
424
+ }
425
+ } else {
426
+ return;
427
+ }
428
+ }
429
+ checkDuplicates(state, obj, token);
430
+ const key = String(token.value);
431
+ skipColon(tokens, state);
432
+ value = parseAny(tokens, state);
433
+ appendPair(state, obj, key, value);
434
+ }
435
+ function parseElement(tokens, state, arr) {
436
+ const key = arr.length;
437
+ const value = parseAny(tokens, state);
438
+ arr[key] = state.reviver ? state.reviver(String(key), value) : value;
439
+ }
440
+ function parseObject(tokens, state) {
441
+ const obj = {};
442
+ return parseMany(tokens, state, obj, {
443
+ skip: [":", "}"],
444
+ // Initially skip over colon or closing brace (for empty/tolerant cases)
445
+ elementParser: parsePair,
446
+ // Use parsePair to parse each key-value element
447
+ elementName: "string key",
448
+ // Expected element type for errors
449
+ endSymbol: "}"
450
+ // The closing token for an object
451
+ });
452
+ }
453
+ function parseArray(tokens, state) {
454
+ const arr = [];
455
+ return parseMany(tokens, state, arr, {
456
+ skip: ["]"],
457
+ // Initially skip over closing bracket (for empty/tolerant cases)
458
+ elementParser: parseElement,
459
+ // Use parseElement to parse each array item
460
+ elementName: "json value",
461
+ // Expected element type for errors
462
+ endSymbol: "]"
463
+ // The closing token for an array
464
+ });
465
+ }
466
+ function handleInvalidToken(token, state, opts, result) {
467
+ raiseUnexpected(state, token, `',' or '${opts.endSymbol}'`);
468
+ if (state.tolerant) {
469
+ if (token.type === "eof") {
470
+ return result;
471
+ }
472
+ state.pos -= 1;
473
+ return null;
474
+ }
475
+ return result;
476
+ }
477
+ function handleCommaToken(params) {
478
+ const { token, tokens, state, opts, result } = params;
479
+ const nextToken = tokens[state.pos];
480
+ if (state.tolerant && nextToken && nextToken.type === opts.endSymbol) {
481
+ raiseError(state, token, `Trailing comma before '${opts.endSymbol}'`);
482
+ popToken(tokens, state);
483
+ return result;
484
+ }
485
+ opts.elementParser(tokens, state, result);
486
+ return null;
487
+ }
488
+ function parseManyInitialElement(tokens, state, result, opts) {
489
+ const token = skipPunctuation(tokens, state, opts.skip);
490
+ if (token.type === "eof") {
491
+ raiseUnexpected(state, token, `'${opts.endSymbol}' or ${opts.elementName}`);
492
+ return result;
493
+ }
494
+ if (token.type === opts.endSymbol) {
495
+ return result;
496
+ }
497
+ state.pos -= 1;
498
+ opts.elementParser(tokens, state, result);
499
+ return;
500
+ }
501
+ function parseManyProcessToken(params) {
502
+ const { token, tokens, state, opts, result } = params;
503
+ if (token.type !== opts.endSymbol && token.type !== ",") {
504
+ const handledResult = handleInvalidToken(token, state, opts, result);
505
+ if (handledResult !== null) {
506
+ return handledResult;
507
+ }
508
+ }
509
+ if (token.type === opts.endSymbol) {
510
+ return result;
511
+ }
512
+ if (token.type === ",") {
513
+ const handledResult = handleCommaToken({
514
+ token,
515
+ tokens,
516
+ state,
517
+ opts,
518
+ result
519
+ });
520
+ if (handledResult !== null) {
521
+ return handledResult;
522
+ }
523
+ return;
524
+ }
525
+ opts.elementParser(tokens, state, result);
526
+ return;
527
+ }
528
+ function parseMany(tokens, state, result, opts) {
529
+ const initialResult = parseManyInitialElement(tokens, state, result, opts);
530
+ if (initialResult !== void 0) {
531
+ return initialResult;
532
+ }
533
+ while (true) {
534
+ const token = popToken(tokens, state);
535
+ const processedResult = parseManyProcessToken({
536
+ token,
537
+ tokens,
538
+ state,
539
+ opts,
540
+ result
541
+ });
542
+ if (processedResult !== void 0) {
543
+ return processedResult;
544
+ }
545
+ }
546
+ }
547
+ function endChecks(tokens, state, ret) {
548
+ if (state.pos < tokens.length) {
549
+ if (state.tolerant) {
550
+ skipPunctuation(tokens, state);
551
+ }
552
+ if (state.pos < tokens.length) {
553
+ raiseError(
554
+ state,
555
+ tokens[state.pos],
556
+ `Unexpected token: ${strToken(tokens[state.pos])}, expected end-of-input`
557
+ );
558
+ }
559
+ }
560
+ if (state.tolerant && state.warnings.length > 0) {
561
+ const message = state.warnings.length === 1 ? state.warnings[0].message : `${state.warnings.length} parse warnings`;
562
+ const err = new SyntaxError(message);
563
+ err.line = state.warnings[0].line;
564
+ err.warnings = state.warnings;
565
+ err.obj = ret;
566
+ throw err;
567
+ }
568
+ }
569
+ function parseAny(tokens, state, end = false) {
570
+ const token = skipPunctuation(tokens, state);
571
+ let ret;
572
+ if (token.type === "eof") {
573
+ if (end) {
574
+ raiseUnexpected(state, token, "json value");
575
+ }
576
+ raiseUnexpected(state, token, "json value");
577
+ return;
578
+ }
579
+ switch (token.type) {
580
+ case "{":
581
+ ret = parseObject(tokens, state);
582
+ break;
583
+ case "[":
584
+ ret = parseArray(tokens, state);
585
+ break;
586
+ case "string":
587
+ // String literal
588
+ case "number":
589
+ // Number literal
590
+ case "atom":
591
+ ret = token.value;
592
+ break;
593
+ default:
594
+ raiseUnexpected(state, token, "json value");
595
+ if (state.tolerant) {
596
+ ret = null;
597
+ } else {
598
+ return;
599
+ }
600
+ }
601
+ if (end) {
602
+ ret = state.reviver ? state.reviver("", ret) : ret;
603
+ endChecks(tokens, state, ret);
604
+ }
605
+ return ret;
606
+ }
607
+ function normalizeParseOptions(optsOrReviver) {
608
+ var _a;
609
+ let options = {};
610
+ if (typeof optsOrReviver === "function") {
611
+ options.reviver = optsOrReviver;
612
+ } else if (optsOrReviver !== null && typeof optsOrReviver === "object") {
613
+ options = { ...optsOrReviver };
614
+ } else if (optsOrReviver !== void 0) {
615
+ throw new TypeError(
616
+ "Second argument must be a reviver function or an options object."
617
+ );
618
+ }
619
+ if (options.relaxed === void 0) {
620
+ if (options.warnings === true || options.tolerant === true) {
621
+ options.relaxed = true;
622
+ } else if (options.warnings === false && options.tolerant === false) {
623
+ options.relaxed = false;
624
+ } else {
625
+ options.relaxed = true;
626
+ }
627
+ }
628
+ options.tolerant = options.tolerant || options.warnings;
629
+ options.duplicate = (_a = options.duplicate) != null ? _a : false;
630
+ return options;
631
+ }
632
+ function createParseState(options) {
633
+ var _a, _b;
634
+ return {
635
+ pos: 0,
636
+ reviver: options.reviver,
637
+ tolerant: (_a = options.tolerant) != null ? _a : false,
638
+ duplicate: (_b = options.duplicate) != null ? _b : false,
639
+ warnings: []
640
+ };
641
+ }
642
+ function parseWithCustomParser(text, options) {
643
+ const lexerToUse = options.relaxed ? lexer : strictLexer;
644
+ let tokens = lexerToUse(text);
645
+ if (options.relaxed) {
646
+ tokens = stripTrailingComma(tokens);
647
+ }
648
+ tokens = tokens.filter((token) => token.type !== " ");
649
+ const state = createParseState(options);
650
+ return parseAny(tokens, state, true);
651
+ }
652
+ function parseWithTransform(text, options) {
653
+ let tokens = lexer(text);
654
+ tokens = stripTrailingComma(tokens);
655
+ const newtext = tokens.reduce((str, token) => str + token.match, "");
656
+ return JSON.parse(
657
+ newtext,
658
+ options.reviver
659
+ );
660
+ }
661
+ function parse(text, optsOrReviver) {
662
+ const options = normalizeParseOptions(optsOrReviver);
663
+ if (!(options.relaxed || options.warnings || options.tolerant) && options.duplicate) {
664
+ return JSON.parse(
665
+ text,
666
+ options.reviver
667
+ );
668
+ }
669
+ if (options.warnings || options.tolerant || !options.duplicate) {
670
+ return parseWithCustomParser(text, options);
671
+ }
672
+ return parseWithTransform(text, options);
673
+ }
76
674
 
77
675
  // src/core/utils/debug.ts
78
676
  var LINE_SPLIT_REGEX = /\r?\n/;
@@ -261,7 +859,7 @@ function escapeRegExp(literal) {
261
859
  function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
262
860
  var _a, _b;
263
861
  try {
264
- const parsedToolCall = (0, import_rjson.parse)(toolCallJson);
862
+ const parsedToolCall = parse(toolCallJson);
265
863
  processedElements.push({
266
864
  type: "tool-call",
267
865
  toolCallId: generateId(),
@@ -389,7 +987,7 @@ function emitToolCall(context) {
389
987
  var _a, _b;
390
988
  const { state, controller, toolCallStart, toolCallEnd, options } = context;
391
989
  try {
392
- const parsedToolCall = (0, import_rjson.parse)(state.currentToolCallJson);
990
+ const parsedToolCall = parse(state.currentToolCallJson);
393
991
  closeTextBlock(state, controller);
394
992
  controller.enqueue({
395
993
  type: "tool-call",
@@ -472,123 +1070,2554 @@ function handlePartialTag(state, controller, toolCallStart) {
472
1070
  state.buffer = "";
473
1071
  }
474
1072
  }
475
- var jsonProtocol = ({
476
- toolCallStart = "<tool_call>",
477
- toolCallEnd = "</tool_call>"
478
- } = {}) => ({
479
- formatTools({
480
- tools,
481
- toolSystemPromptTemplate
482
- }) {
483
- return toolSystemPromptTemplate(tools || []);
484
- },
485
- formatToolCall(toolCall) {
486
- let args = {};
487
- if (toolCall.input != null) {
488
- try {
489
- args = JSON.parse(toolCall.input);
490
- } catch (e) {
491
- args = toolCall.input;
492
- }
493
- }
494
- return `${toolCallStart}${JSON.stringify({
495
- name: toolCall.toolName,
496
- arguments: args
497
- })}${toolCallEnd}`;
498
- },
499
- parseGeneratedText({
500
- text,
501
- options
502
- }) {
503
- const startEsc = escapeRegExp(toolCallStart);
504
- const endEsc = escapeRegExp(toolCallEnd);
505
- const toolCallRegex = new RegExp(
506
- `${startEsc}([\0-\uFFFF]*?)${endEsc}`,
507
- "gs"
508
- );
509
- const processedElements = [];
510
- let currentIndex = 0;
511
- let match = toolCallRegex.exec(text);
512
- while (match !== null) {
513
- currentIndex = processMatchedToolCall({
514
- match,
515
- text,
516
- currentIndex,
517
- processedElements,
518
- options
519
- });
520
- match = toolCallRegex.exec(text);
1073
+ var jsonProtocol = ({
1074
+ toolCallStart = "<tool_call>",
1075
+ toolCallEnd = "</tool_call>"
1076
+ } = {}) => ({
1077
+ formatTools({
1078
+ tools,
1079
+ toolSystemPromptTemplate
1080
+ }) {
1081
+ return toolSystemPromptTemplate(tools || []);
1082
+ },
1083
+ formatToolCall(toolCall) {
1084
+ let args = {};
1085
+ if (toolCall.input != null) {
1086
+ try {
1087
+ args = JSON.parse(toolCall.input);
1088
+ } catch (e) {
1089
+ args = toolCall.input;
1090
+ }
1091
+ }
1092
+ return `${toolCallStart}${JSON.stringify({
1093
+ name: toolCall.toolName,
1094
+ arguments: args
1095
+ })}${toolCallEnd}`;
1096
+ },
1097
+ parseGeneratedText({
1098
+ text,
1099
+ options
1100
+ }) {
1101
+ const startEsc = escapeRegExp(toolCallStart);
1102
+ const endEsc = escapeRegExp(toolCallEnd);
1103
+ const toolCallRegex = new RegExp(
1104
+ `${startEsc}([\0-\uFFFF]*?)${endEsc}`,
1105
+ "gs"
1106
+ );
1107
+ const processedElements = [];
1108
+ let currentIndex = 0;
1109
+ let match = toolCallRegex.exec(text);
1110
+ while (match !== null) {
1111
+ currentIndex = processMatchedToolCall({
1112
+ match,
1113
+ text,
1114
+ currentIndex,
1115
+ processedElements,
1116
+ options
1117
+ });
1118
+ match = toolCallRegex.exec(text);
1119
+ }
1120
+ if (currentIndex < text.length) {
1121
+ const remainingText = text.substring(currentIndex);
1122
+ addTextSegment(remainingText, processedElements);
1123
+ }
1124
+ return processedElements;
1125
+ },
1126
+ createStreamParser({
1127
+ options
1128
+ }) {
1129
+ const state = {
1130
+ isInsideToolCall: false,
1131
+ buffer: "",
1132
+ currentToolCallJson: "",
1133
+ currentTextId: null,
1134
+ hasEmittedTextStart: false
1135
+ };
1136
+ return new TransformStream({
1137
+ transform(chunk, controller) {
1138
+ var _a;
1139
+ if (chunk.type === "finish") {
1140
+ handleFinishChunk(state, controller, toolCallStart, chunk);
1141
+ return;
1142
+ }
1143
+ if (chunk.type !== "text-delta") {
1144
+ controller.enqueue(chunk);
1145
+ return;
1146
+ }
1147
+ const textContent = (_a = chunk.delta) != null ? _a : "";
1148
+ state.buffer += textContent;
1149
+ processBufferTags({
1150
+ state,
1151
+ controller,
1152
+ toolCallStart,
1153
+ toolCallEnd,
1154
+ options
1155
+ });
1156
+ handlePartialTag(state, controller, toolCallStart);
1157
+ }
1158
+ });
1159
+ },
1160
+ extractToolCallSegments({ text }) {
1161
+ const startEsc = escapeRegExp(toolCallStart);
1162
+ const endEsc = escapeRegExp(toolCallEnd);
1163
+ const regex = new RegExp(`${startEsc}([\0-\uFFFF]*?)${endEsc}`, "gs");
1164
+ const segments = [];
1165
+ let m = regex.exec(text);
1166
+ while (m != null) {
1167
+ segments.push(m[0]);
1168
+ m = regex.exec(text);
1169
+ }
1170
+ return segments;
1171
+ }
1172
+ });
1173
+
1174
+ // src/core/protocols/protocol-interface.ts
1175
+ function isTCMProtocolFactory(protocol) {
1176
+ return typeof protocol === "function";
1177
+ }
1178
+
1179
+ // src/rxml/errors/types.ts
1180
+ var RXMLParseError = class extends Error {
1181
+ constructor(message, cause, line, column) {
1182
+ super(message);
1183
+ this.name = "RXMLParseError";
1184
+ this.cause = cause;
1185
+ this.line = line;
1186
+ this.column = column;
1187
+ }
1188
+ };
1189
+ var RXMLDuplicateStringTagError = class extends Error {
1190
+ constructor(message) {
1191
+ super(message);
1192
+ this.name = "RXMLDuplicateStringTagError";
1193
+ }
1194
+ };
1195
+ var RXMLCoercionError = class extends Error {
1196
+ constructor(message, cause) {
1197
+ super(message);
1198
+ this.name = "RXMLCoercionError";
1199
+ this.cause = cause;
1200
+ }
1201
+ };
1202
+ var RXMLStringifyError = class extends Error {
1203
+ constructor(message, cause) {
1204
+ super(message);
1205
+ this.name = "RXMLStringifyError";
1206
+ this.cause = cause;
1207
+ }
1208
+ };
1209
+
1210
+ // src/rxml/core/types.ts
1211
+ var CharCodes = {
1212
+ OPEN_BRACKET: "<".charCodeAt(0),
1213
+ CLOSE_BRACKET: ">".charCodeAt(0),
1214
+ MINUS: "-".charCodeAt(0),
1215
+ SLASH: "/".charCodeAt(0),
1216
+ EXCLAMATION: "!".charCodeAt(0),
1217
+ QUESTION: "?".charCodeAt(0),
1218
+ SINGLE_QUOTE: "'".charCodeAt(0),
1219
+ DOUBLE_QUOTE: '"'.charCodeAt(0),
1220
+ OPEN_CORNER_BRACKET: "[".charCodeAt(0),
1221
+ CLOSE_CORNER_BRACKET: "]".charCodeAt(0),
1222
+ SPACE: " ".charCodeAt(0),
1223
+ TAB: " ".charCodeAt(0),
1224
+ NEWLINE: "\n".charCodeAt(0),
1225
+ CARRIAGE_RETURN: "\r".charCodeAt(0)
1226
+ };
1227
+ var DEFAULT_NO_CHILD_NODES = [
1228
+ "img",
1229
+ "br",
1230
+ "input",
1231
+ "meta",
1232
+ "link",
1233
+ "hr",
1234
+ "area",
1235
+ "base",
1236
+ "col",
1237
+ "embed",
1238
+ "param",
1239
+ "source",
1240
+ "track",
1241
+ "wbr"
1242
+ ];
1243
+ var NAME_SPACER = "\r\n >/= ";
1244
+
1245
+ // src/rxml/utils/helpers.ts
1246
+ var NAME_START_CHAR_REGEX = /[A-Za-z_:]/;
1247
+ var NAME_CHAR_REGEX = /[A-Za-z0-9_.:-]/;
1248
+ function isNameStartChar(ch) {
1249
+ return NAME_START_CHAR_REGEX.test(ch);
1250
+ }
1251
+ function isNameChar(ch) {
1252
+ return NAME_CHAR_REGEX.test(ch);
1253
+ }
1254
+ function skipQuoted(s, i) {
1255
+ const quote = s[i];
1256
+ let pos = i + 1;
1257
+ while (pos < s.length) {
1258
+ const ch = s[pos];
1259
+ if (ch === "\\") {
1260
+ pos += 2;
1261
+ continue;
1262
+ }
1263
+ if (ch === quote) {
1264
+ return pos + 1;
1265
+ }
1266
+ pos += 1;
1267
+ }
1268
+ return pos;
1269
+ }
1270
+ function parseName(s, pos) {
1271
+ const start = pos;
1272
+ let currentPos = pos;
1273
+ while (NAME_SPACER.indexOf(s[currentPos]) === -1 && s[currentPos]) {
1274
+ currentPos += 1;
1275
+ }
1276
+ return { name: s.slice(start, currentPos), newPos: currentPos };
1277
+ }
1278
+ function parseString(s, pos) {
1279
+ const startChar = s[pos];
1280
+ const startPos = pos + 1;
1281
+ const endPos = s.indexOf(startChar, startPos);
1282
+ if (endPos === -1) {
1283
+ const tagEnd = s.indexOf(">", startPos);
1284
+ if (tagEnd !== -1) {
1285
+ return { value: s.slice(startPos, tagEnd), newPos: tagEnd };
1286
+ }
1287
+ return { value: s.slice(startPos), newPos: s.length };
1288
+ }
1289
+ return { value: s.slice(startPos, endPos), newPos: endPos + 1 };
1290
+ }
1291
+ function getLineColumn(s, pos) {
1292
+ let line = 1;
1293
+ let column = 1;
1294
+ for (let i = 0; i < pos && i < s.length; i += 1) {
1295
+ if (s[i] === "\n") {
1296
+ line += 1;
1297
+ column = 1;
1298
+ } else {
1299
+ column += 1;
1300
+ }
1301
+ }
1302
+ return { line, column };
1303
+ }
1304
+ function escapeXml(text) {
1305
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
1306
+ }
1307
+ function escapeXmlMinimalText(text) {
1308
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/]]>/g, "]]&gt;");
1309
+ }
1310
+ function escapeXmlMinimalAttr(value, wrapper = '"') {
1311
+ let escaped = value.replace(/&/g, "&amp;").replace(/</g, "&lt;");
1312
+ if (wrapper === '"') {
1313
+ escaped = escaped.replace(/"/g, "&quot;");
1314
+ } else {
1315
+ escaped = escaped.replace(/'/g, "&apos;");
1316
+ }
1317
+ return escaped;
1318
+ }
1319
+ function unescapeXml(text) {
1320
+ return text.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&amp;/g, "&");
1321
+ }
1322
+
1323
+ // src/rxml/builders/stringify.ts
1324
+ function stringify(rootTag, obj, options = {}) {
1325
+ var _a, _b, _c, _d, _e;
1326
+ try {
1327
+ const format = (_a = options.format) != null ? _a : true;
1328
+ const declaration = (_b = options.declaration) != null ? _b : false;
1329
+ const minimalEscaping = (_c = options.minimalEscaping) != null ? _c : false;
1330
+ const suppressEmptyNode = (_d = options.suppressEmptyNode) != null ? _d : false;
1331
+ const strictBooleanAttributes = (_e = options.strictBooleanAttributes) != null ? _e : false;
1332
+ let result = "";
1333
+ if (declaration) {
1334
+ result += '<?xml version="1.0" encoding="UTF-8"?>\n';
1335
+ }
1336
+ result += stringifyValue(rootTag, obj, {
1337
+ depth: 0,
1338
+ format,
1339
+ suppressEmptyNode,
1340
+ minimalEscaping,
1341
+ strictBooleanAttributes
1342
+ });
1343
+ if (result.endsWith("\n")) {
1344
+ return result.slice(0, -1);
1345
+ }
1346
+ return result;
1347
+ } catch (error) {
1348
+ throw new RXMLStringifyError("Failed to stringify XML", error);
1349
+ }
1350
+ }
1351
+ function escapeContent(content, minimalEscaping) {
1352
+ return minimalEscaping ? escapeXmlMinimalText(content) : escapeXml(content);
1353
+ }
1354
+ function createSelfClosingTag(tagName, indent, newline) {
1355
+ return `${indent}<${tagName}/>${newline}`;
1356
+ }
1357
+ function createTextElement(tagName, content, indent, newline) {
1358
+ return `${indent}<${tagName}>${content}</${tagName}>${newline}`;
1359
+ }
1360
+ function isPrimitive(value) {
1361
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
1362
+ }
1363
+ function stringifyPrimitive(tagName, value, context, format) {
1364
+ const { minimalEscaping, suppressEmptyNode } = context;
1365
+ const content = escapeContent(String(value), minimalEscaping);
1366
+ if (content === "" && suppressEmptyNode) {
1367
+ return "";
1368
+ }
1369
+ return createTextElement(tagName, content, format.indent, format.newline);
1370
+ }
1371
+ function stringifyArray(tagName, value, context) {
1372
+ let result = "";
1373
+ for (const item of value) {
1374
+ result += stringifyValue(tagName, item, context);
1375
+ }
1376
+ return result;
1377
+ }
1378
+ function stringifyValue(tagName, value, context) {
1379
+ const { format, suppressEmptyNode, minimalEscaping } = context;
1380
+ const indent = format ? " ".repeat(context.depth) : "";
1381
+ const newline = format ? "\n" : "";
1382
+ if (value === null || value === void 0) {
1383
+ if (suppressEmptyNode) {
1384
+ return "";
1385
+ }
1386
+ return createSelfClosingTag(tagName, indent, newline);
1387
+ }
1388
+ if (isPrimitive(value)) {
1389
+ return stringifyPrimitive(tagName, value, context, { indent, newline });
1390
+ }
1391
+ if (Array.isArray(value)) {
1392
+ return stringifyArray(tagName, value, context);
1393
+ }
1394
+ if (typeof value === "object") {
1395
+ return stringifyObject(tagName, value, context);
1396
+ }
1397
+ const content = escapeContent(String(value), minimalEscaping);
1398
+ if (content === "" && suppressEmptyNode) {
1399
+ return "";
1400
+ }
1401
+ return createTextElement(tagName, content, indent, newline);
1402
+ }
1403
+ function extractObjectParts(obj) {
1404
+ const attributes = {};
1405
+ const elements = {};
1406
+ let textContent;
1407
+ for (const [key, value] of Object.entries(obj)) {
1408
+ if (key.startsWith("@")) {
1409
+ attributes[key.substring(1)] = value;
1410
+ } else if (key === "#text" || key === "_text") {
1411
+ textContent = String(value);
1412
+ } else if (key === "_attributes") {
1413
+ if (typeof value === "object" && value !== null) {
1414
+ Object.assign(attributes, value);
1415
+ }
1416
+ } else {
1417
+ elements[key] = value;
1418
+ }
1419
+ }
1420
+ return { attributes, elements, textContent };
1421
+ }
1422
+ function formatAttribute(attrName, attrValue, minimalEscaping, strictBooleanAttributes) {
1423
+ if (attrValue === null) {
1424
+ return strictBooleanAttributes ? ` ${attrName}="${attrName}"` : ` ${attrName}`;
1425
+ }
1426
+ const valueStr = String(attrValue);
1427
+ if (valueStr.indexOf('"') === -1) {
1428
+ const escaped2 = minimalEscaping ? escapeXmlMinimalAttr(valueStr, '"') : escapeXml(valueStr);
1429
+ return ` ${attrName}="${escaped2}"`;
1430
+ }
1431
+ const escaped = minimalEscaping ? escapeXmlMinimalAttr(valueStr, "'") : escapeXml(valueStr);
1432
+ return ` ${attrName}='${escaped}'`;
1433
+ }
1434
+ function buildOpeningTag(tagName, attributes, context) {
1435
+ let openTag = `<${tagName}`;
1436
+ const { minimalEscaping, strictBooleanAttributes } = context;
1437
+ for (const [attrName, attrValue] of Object.entries(attributes)) {
1438
+ openTag += formatAttribute(
1439
+ attrName,
1440
+ attrValue,
1441
+ minimalEscaping,
1442
+ strictBooleanAttributes
1443
+ );
1444
+ }
1445
+ return openTag;
1446
+ }
1447
+ function stringifyTextOnlyContent(options) {
1448
+ const { tagName, textContent, openTag, format, minimalEscaping } = options;
1449
+ const content = escapeContent(textContent, minimalEscaping);
1450
+ return `${format.indent}${openTag}${content}</${tagName}>${format.newline}`;
1451
+ }
1452
+ function stringifyComplexContent(tagName, parts, context, options) {
1453
+ const { format, minimalEscaping, depth } = context;
1454
+ const { textContent, elements } = parts;
1455
+ const hasElements = Object.keys(elements).length > 0;
1456
+ let result = `${options.indent}${options.openTag}`;
1457
+ if (textContent) {
1458
+ const content = escapeContent(textContent, minimalEscaping);
1459
+ result += format ? `${options.newline}${options.childIndent}${content}` : content;
1460
+ }
1461
+ if (hasElements) {
1462
+ if (format) {
1463
+ result += options.newline;
1464
+ }
1465
+ for (const [elementName, elementValue] of Object.entries(elements)) {
1466
+ result += stringifyValue(elementName, elementValue, {
1467
+ ...context,
1468
+ depth: depth + 1
1469
+ });
1470
+ }
1471
+ if (format) {
1472
+ result += options.indent;
1473
+ }
1474
+ }
1475
+ result += `</${tagName}>${options.newline}`;
1476
+ return result;
1477
+ }
1478
+ function stringifyObject(tagName, obj, context) {
1479
+ const { depth, format, suppressEmptyNode } = context;
1480
+ const indent = format ? " ".repeat(depth) : "";
1481
+ const newline = format ? "\n" : "";
1482
+ const childIndent = format ? " ".repeat(depth + 1) : "";
1483
+ const parts = extractObjectParts(obj);
1484
+ const openTag = buildOpeningTag(tagName, parts.attributes, context);
1485
+ const hasElements = Object.keys(parts.elements).length > 0;
1486
+ const hasTextContent = parts.textContent !== void 0 && parts.textContent !== "";
1487
+ if (!(hasElements || hasTextContent)) {
1488
+ if (suppressEmptyNode) {
1489
+ return "";
1490
+ }
1491
+ return `${indent}${openTag}/>${newline}`;
1492
+ }
1493
+ const fullOpenTag = `${openTag}>`;
1494
+ if (!hasElements && hasTextContent && parts.textContent) {
1495
+ return stringifyTextOnlyContent({
1496
+ tagName,
1497
+ textContent: parts.textContent,
1498
+ openTag: fullOpenTag,
1499
+ format: { indent, newline },
1500
+ minimalEscaping: context.minimalEscaping
1501
+ });
1502
+ }
1503
+ return stringifyComplexContent(tagName, parts, context, {
1504
+ indent,
1505
+ newline,
1506
+ childIndent,
1507
+ openTag: fullOpenTag
1508
+ });
1509
+ }
1510
+
1511
+ // src/schema-coerce/index.ts
1512
+ var NUMERIC_REGEX = /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
1513
+ var EMPTY_OBJECT_REGEX = /^\{\s*\}$/s;
1514
+ var NEWLINE_SPLIT_REGEX = /\n+/;
1515
+ var COMMA_SPLIT_REGEX = /,\s*/;
1516
+ var DIGIT_KEY_REGEX = /^\d+$/;
1517
+ function unwrapJsonSchema(schema) {
1518
+ if (!schema || typeof schema !== "object") {
1519
+ return schema;
1520
+ }
1521
+ const s = schema;
1522
+ if (s.jsonSchema && typeof s.jsonSchema === "object") {
1523
+ return unwrapJsonSchema(s.jsonSchema);
1524
+ }
1525
+ return schema;
1526
+ }
1527
+ function getSchemaType(schema) {
1528
+ const unwrapped = unwrapJsonSchema(schema);
1529
+ if (!unwrapped || typeof unwrapped !== "object") {
1530
+ return;
1531
+ }
1532
+ const t = unwrapped.type;
1533
+ if (typeof t === "string") {
1534
+ return t;
1535
+ }
1536
+ if (Array.isArray(t)) {
1537
+ const preferred = [
1538
+ "object",
1539
+ "array",
1540
+ "boolean",
1541
+ "number",
1542
+ "integer",
1543
+ "string"
1544
+ ];
1545
+ for (const p of preferred) {
1546
+ if (t.includes(p)) {
1547
+ return p;
1548
+ }
1549
+ }
1550
+ }
1551
+ const s = unwrapped;
1552
+ if (s && typeof s === "object" && (s.properties || s.additionalProperties)) {
1553
+ return "object";
1554
+ }
1555
+ if (s && typeof s === "object" && (s.items || s.prefixItems)) {
1556
+ return "array";
1557
+ }
1558
+ return;
1559
+ }
1560
+ function coerceStringWithoutSchema(value) {
1561
+ const s = value.trim();
1562
+ const lower = s.toLowerCase();
1563
+ if (lower === "true") {
1564
+ return true;
1565
+ }
1566
+ if (lower === "false") {
1567
+ return false;
1568
+ }
1569
+ if (NUMERIC_REGEX.test(s)) {
1570
+ const num = Number(s);
1571
+ if (Number.isFinite(num)) {
1572
+ return num;
1573
+ }
1574
+ }
1575
+ if (s.startsWith("{") && s.endsWith("}") || s.startsWith("[") && s.endsWith("]")) {
1576
+ try {
1577
+ const parsed = JSON.parse(s);
1578
+ return coerceBySchema(parsed, void 0);
1579
+ } catch (e) {
1580
+ }
1581
+ }
1582
+ return value;
1583
+ }
1584
+ function coerceStringToObject(s, unwrapped) {
1585
+ try {
1586
+ let normalized = s.replace(/'/g, '"');
1587
+ normalized = normalized.replace(EMPTY_OBJECT_REGEX, "{}");
1588
+ const obj = JSON.parse(normalized);
1589
+ if (obj && typeof obj === "object" && !Array.isArray(obj)) {
1590
+ const props = unwrapped.properties;
1591
+ const out = {};
1592
+ for (const [k, v] of Object.entries(obj)) {
1593
+ const propSchema = props ? props[k] : void 0;
1594
+ out[k] = typeof propSchema === "boolean" ? v : coerceBySchema(v, propSchema);
1595
+ }
1596
+ return out;
1597
+ }
1598
+ } catch (e) {
1599
+ }
1600
+ return null;
1601
+ }
1602
+ function coerceStringToArray(s, unwrapped) {
1603
+ const prefixItems = Array.isArray(unwrapped.prefixItems) ? unwrapped.prefixItems : void 0;
1604
+ const itemsSchema = unwrapped.items;
1605
+ try {
1606
+ const normalized = s.replace(/'/g, '"');
1607
+ const arr = JSON.parse(normalized);
1608
+ if (Array.isArray(arr)) {
1609
+ if (prefixItems && arr.length === prefixItems.length) {
1610
+ return arr.map((v, i) => coerceBySchema(v, prefixItems[i]));
1611
+ }
1612
+ return arr.map((v) => coerceBySchema(v, itemsSchema));
1613
+ }
1614
+ } catch (e) {
1615
+ const csv = s.includes("\n") ? s.split(NEWLINE_SPLIT_REGEX) : s.split(COMMA_SPLIT_REGEX);
1616
+ const trimmed = csv.map((x) => x.trim()).filter((x) => x.length > 0);
1617
+ if (prefixItems && trimmed.length === prefixItems.length) {
1618
+ return trimmed.map((x, i) => coerceBySchema(x, prefixItems[i]));
1619
+ }
1620
+ return trimmed.map((x) => coerceBySchema(x, itemsSchema));
1621
+ }
1622
+ return null;
1623
+ }
1624
+ function coerceObjectToObject(value, unwrapped) {
1625
+ const out = {};
1626
+ const props = unwrapped.properties;
1627
+ for (const [k, v] of Object.entries(value)) {
1628
+ const propSchema = props ? props[k] : void 0;
1629
+ out[k] = typeof propSchema === "boolean" ? v : coerceBySchema(v, propSchema);
1630
+ }
1631
+ return out;
1632
+ }
1633
+ function coerceArrayToArray(value, prefixItems, itemsSchema) {
1634
+ if (prefixItems && value.length === prefixItems.length) {
1635
+ return value.map((v, i) => coerceBySchema(v, prefixItems[i]));
1636
+ }
1637
+ return value.map((v) => coerceBySchema(v, itemsSchema));
1638
+ }
1639
+ function coerceObjectToArray(maybe, prefixItems, itemsSchema) {
1640
+ if (Object.hasOwn(maybe, "item")) {
1641
+ const items = maybe.item;
1642
+ const arr = Array.isArray(items) ? items : [items];
1643
+ return coerceArrayToArray(arr, prefixItems, itemsSchema);
1644
+ }
1645
+ const keys = Object.keys(maybe);
1646
+ if (keys.length === 1) {
1647
+ const singleValue = maybe[keys[0]];
1648
+ if (Array.isArray(singleValue)) {
1649
+ return singleValue.map((v) => coerceBySchema(v, itemsSchema));
1650
+ }
1651
+ }
1652
+ if (keys.length > 0 && keys.every((k) => DIGIT_KEY_REGEX.test(k))) {
1653
+ const arr = keys.sort((a, b) => Number(a) - Number(b)).map((k) => maybe[k]);
1654
+ return coerceArrayToArray(arr, prefixItems, itemsSchema);
1655
+ }
1656
+ return null;
1657
+ }
1658
+ function coercePrimitiveToArray(value, prefixItems, itemsSchema) {
1659
+ if (prefixItems && prefixItems.length > 0) {
1660
+ return [coerceBySchema(value, prefixItems[0])];
1661
+ }
1662
+ return [coerceBySchema(value, itemsSchema)];
1663
+ }
1664
+ function coerceStringToPrimitive(s, schemaType) {
1665
+ if (schemaType === "boolean") {
1666
+ const lower = s.toLowerCase();
1667
+ if (lower === "true") {
1668
+ return true;
1669
+ }
1670
+ if (lower === "false") {
1671
+ return false;
1672
+ }
1673
+ }
1674
+ if ((schemaType === "number" || schemaType === "integer") && NUMERIC_REGEX.test(s)) {
1675
+ const num = Number(s);
1676
+ if (Number.isFinite(num)) {
1677
+ return num;
1678
+ }
1679
+ }
1680
+ return null;
1681
+ }
1682
+ function coerceStringValue(value, schemaType, u) {
1683
+ const s = value.trim();
1684
+ if (schemaType === "object") {
1685
+ const result = coerceStringToObject(s, u);
1686
+ if (result !== null) {
1687
+ return result;
1688
+ }
1689
+ }
1690
+ if (schemaType === "array") {
1691
+ const result = coerceStringToArray(s, u);
1692
+ if (result !== null) {
1693
+ return result;
1694
+ }
1695
+ }
1696
+ const primitiveResult = coerceStringToPrimitive(s, schemaType);
1697
+ if (primitiveResult !== null) {
1698
+ return primitiveResult;
1699
+ }
1700
+ return value;
1701
+ }
1702
+ function coerceArrayValue(value, prefixItems, itemsSchema) {
1703
+ if (Array.isArray(value)) {
1704
+ return coerceArrayToArray(value, prefixItems, itemsSchema);
1705
+ }
1706
+ if (value && typeof value === "object") {
1707
+ const result = coerceObjectToArray(
1708
+ value,
1709
+ prefixItems,
1710
+ itemsSchema
1711
+ );
1712
+ if (result !== null) {
1713
+ return result;
1714
+ }
1715
+ }
1716
+ if (value == null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1717
+ return coercePrimitiveToArray(value, prefixItems, itemsSchema);
1718
+ }
1719
+ return value;
1720
+ }
1721
+ function coerceBySchema(value, schema) {
1722
+ const unwrapped = unwrapJsonSchema(schema);
1723
+ if (!unwrapped || typeof unwrapped !== "object") {
1724
+ if (typeof value === "string") {
1725
+ return coerceStringWithoutSchema(value);
1726
+ }
1727
+ return value;
1728
+ }
1729
+ const schemaType = getSchemaType(unwrapped);
1730
+ const u = unwrapped;
1731
+ if (typeof value === "string") {
1732
+ return coerceStringValue(value, schemaType, u);
1733
+ }
1734
+ if (schemaType === "object" && value && typeof value === "object" && !Array.isArray(value)) {
1735
+ return coerceObjectToObject(value, u);
1736
+ }
1737
+ if (schemaType === "array") {
1738
+ const prefixItems = Array.isArray(u.prefixItems) ? u.prefixItems : void 0;
1739
+ const itemsSchema = u.items;
1740
+ return coerceArrayValue(value, prefixItems, itemsSchema);
1741
+ }
1742
+ return value;
1743
+ }
1744
+
1745
+ // src/rxml/schema/coercion.ts
1746
+ function getPropertySchema(toolSchema, key) {
1747
+ const unwrapped = unwrapJsonSchema(toolSchema);
1748
+ if (!unwrapped || typeof unwrapped !== "object") {
1749
+ return;
1750
+ }
1751
+ const u = unwrapped;
1752
+ const props = u.properties;
1753
+ if (props && Object.hasOwn(props, key)) {
1754
+ return props[key];
1755
+ }
1756
+ return;
1757
+ }
1758
+ function getNodeValue(children, schema, tagName, textNodeName) {
1759
+ if (children.length === 0) {
1760
+ return "";
1761
+ }
1762
+ if (children.length === 1 && typeof children[0] === "string") {
1763
+ return children[0];
1764
+ }
1765
+ return processComplexContent(
1766
+ children,
1767
+ getPropertySchema(schema, tagName),
1768
+ textNodeName
1769
+ );
1770
+ }
1771
+ function addAttributesToValue(value, attributes, textNodeName) {
1772
+ if (Object.keys(attributes).length === 0) {
1773
+ return value;
1774
+ }
1775
+ if (typeof value === "string") {
1776
+ const valueResult = { [textNodeName]: value };
1777
+ for (const [attrName, attrValue] of Object.entries(attributes)) {
1778
+ valueResult[`@_${attrName}`] = attrValue;
1779
+ }
1780
+ return valueResult;
1781
+ }
1782
+ if (value && typeof value === "object" && !Array.isArray(value)) {
1783
+ for (const [attrName, attrValue] of Object.entries(attributes)) {
1784
+ value[`@_${attrName}`] = attrValue;
1785
+ }
1786
+ }
1787
+ return value;
1788
+ }
1789
+ function addToResult(result, tagName, value) {
1790
+ if (result[tagName]) {
1791
+ if (!Array.isArray(result[tagName])) {
1792
+ result[tagName] = [result[tagName]];
1793
+ }
1794
+ result[tagName].push(value);
1795
+ } else {
1796
+ result[tagName] = value;
1797
+ }
1798
+ }
1799
+ function domToObject(nodes, schema, textNodeName = "#text") {
1800
+ const result = {};
1801
+ for (const node of nodes) {
1802
+ if (typeof node === "string") {
1803
+ continue;
1804
+ }
1805
+ const { tagName, children, attributes } = node;
1806
+ let value = getNodeValue(children, schema, tagName, textNodeName);
1807
+ value = addAttributesToValue(value, attributes, textNodeName);
1808
+ addToResult(result, tagName, value);
1809
+ }
1810
+ return result;
1811
+ }
1812
+ function processChildElement(child, schema, textNodeName) {
1813
+ let childValue;
1814
+ if (child.children.length === 0) {
1815
+ childValue = "";
1816
+ } else if (child.children.length === 1 && typeof child.children[0] === "string") {
1817
+ childValue = child.children[0];
1818
+ } else {
1819
+ childValue = processComplexContent(
1820
+ child.children,
1821
+ getPropertySchema(schema, child.tagName),
1822
+ textNodeName
1823
+ );
1824
+ }
1825
+ return addAttributesToValue(childValue, child.attributes, textNodeName);
1826
+ }
1827
+ function combineContent(textContent, elements, textNodeName) {
1828
+ const hasText = textContent.length > 0;
1829
+ const hasElements = Object.keys(elements).length > 0;
1830
+ if (hasText && hasElements) {
1831
+ return {
1832
+ [textNodeName]: textContent.join("").trim(),
1833
+ ...elements
1834
+ };
1835
+ }
1836
+ if (hasText) {
1837
+ return textContent.join("").trim();
1838
+ }
1839
+ if (hasElements) {
1840
+ return elements;
1841
+ }
1842
+ return "";
1843
+ }
1844
+ function processComplexContent(children, schema, textNodeName) {
1845
+ const textContent = [];
1846
+ const elements = {};
1847
+ for (const child of children) {
1848
+ if (typeof child === "string") {
1849
+ textContent.push(child);
1850
+ } else {
1851
+ const childValue = processChildElement(child, schema, textNodeName);
1852
+ addToResult(elements, child.tagName, childValue);
1853
+ }
1854
+ }
1855
+ return combineContent(textContent, elements, textNodeName);
1856
+ }
1857
+ function coerceDomBySchema(domObject, schema) {
1858
+ try {
1859
+ return coerceBySchema(domObject, schema);
1860
+ } catch (error) {
1861
+ throw new RXMLCoercionError("Failed to coerce DOM object by schema", error);
1862
+ }
1863
+ }
1864
+ function visitObjectProperties(props, collected, visit) {
1865
+ for (const [key, propSchema] of Object.entries(props)) {
1866
+ const t = getSchemaType(propSchema);
1867
+ if (t === "string") {
1868
+ collected.add(key);
1869
+ } else if (t === "object" || t === "array") {
1870
+ visit(propSchema);
1871
+ }
1872
+ }
1873
+ }
1874
+ function visitArrayItems(u, visit) {
1875
+ const items = u.items;
1876
+ if (items) {
1877
+ visit(items);
1878
+ }
1879
+ const prefix = u.prefixItems;
1880
+ if (Array.isArray(prefix)) {
1881
+ for (const item of prefix) {
1882
+ visit(item);
1883
+ }
1884
+ }
1885
+ }
1886
+ function getStringTypedProperties(schema) {
1887
+ const collected = /* @__PURE__ */ new Set();
1888
+ const visit = (s) => {
1889
+ const unwrapped = unwrapJsonSchema(s);
1890
+ if (!unwrapped || typeof unwrapped !== "object") {
1891
+ return;
1892
+ }
1893
+ const u = unwrapped;
1894
+ const type = getSchemaType(unwrapped);
1895
+ if (type === "object") {
1896
+ const props = u.properties;
1897
+ if (props && typeof props === "object") {
1898
+ visitObjectProperties(props, collected, visit);
1899
+ }
1900
+ } else if (type === "array") {
1901
+ visitArrayItems(u, visit);
1902
+ }
1903
+ };
1904
+ visit(schema);
1905
+ return collected;
1906
+ }
1907
+ function processArrayContent(value, schema, textNodeName) {
1908
+ if (!Array.isArray(value)) {
1909
+ return value;
1910
+ }
1911
+ const schemaType = getSchemaType(schema);
1912
+ if (schemaType === "string") {
1913
+ return value.map((item) => {
1914
+ if (typeof item === "string") {
1915
+ return item.trim();
1916
+ }
1917
+ if (item && typeof item === "object" && textNodeName in item) {
1918
+ const textVal = item[textNodeName];
1919
+ return typeof textVal === "string" ? textVal.trim() : String(textVal);
1920
+ }
1921
+ return String(item);
1922
+ });
1923
+ }
1924
+ return value.map((item) => {
1925
+ if (typeof item === "string") {
1926
+ return item.trim();
1927
+ }
1928
+ if (item && typeof item === "object" && textNodeName in item) {
1929
+ const textVal = item[textNodeName];
1930
+ return typeof textVal === "string" ? textVal.trim() : textVal;
1931
+ }
1932
+ return item;
1933
+ });
1934
+ }
1935
+ function processIndexedTuple(obj, textNodeName) {
1936
+ const keys = Object.keys(obj);
1937
+ const indices = keys.map((k) => Number.parseInt(k, 10)).sort((a, b) => a - b);
1938
+ const isValidTuple = indices[0] === 0 && indices.every((val, idx) => val === idx);
1939
+ if (!isValidTuple) {
1940
+ return [obj];
1941
+ }
1942
+ const sortedKeys = keys.sort(
1943
+ (a, b) => Number.parseInt(a, 10) - Number.parseInt(b, 10)
1944
+ );
1945
+ return sortedKeys.map((key) => {
1946
+ const item = obj[key];
1947
+ if (item && typeof item === "object" && textNodeName in item) {
1948
+ const textVal = item[textNodeName];
1949
+ return typeof textVal === "string" ? textVal.trim() : textVal;
1950
+ }
1951
+ return typeof item === "string" ? item.trim() : item;
1952
+ });
1953
+ }
1954
+
1955
+ // src/rxml/schema/extraction.ts
1956
+ function skipDoctype(xmlContent, i, len) {
1957
+ const gt = xmlContent.indexOf(">", i + 1);
1958
+ return gt === -1 ? len : gt + 1;
1959
+ }
1960
+ function skipComment(xmlContent, i, len) {
1961
+ const close = xmlContent.indexOf("-->", i + 4);
1962
+ return close === -1 ? len : close + 3;
1963
+ }
1964
+ function skipCdata(xmlContent, i, len) {
1965
+ const close = xmlContent.indexOf("]]>", i + 9);
1966
+ return close === -1 ? len : close + 3;
1967
+ }
1968
+ function skipProcessingInstruction(xmlContent, i, len) {
1969
+ const close = xmlContent.indexOf("?>", i + 1);
1970
+ return close === -1 ? len : close + 2;
1971
+ }
1972
+ function skipSpecialConstruct(xmlContent, i, len) {
1973
+ const ch = xmlContent[i];
1974
+ if (ch === "!") {
1975
+ if (xmlContent.startsWith("!DOCTYPE", i + 1)) {
1976
+ return skipDoctype(xmlContent, i, len);
1977
+ }
1978
+ if (xmlContent.startsWith("!--", i + 1)) {
1979
+ return skipComment(xmlContent, i, len);
1980
+ }
1981
+ if (xmlContent.startsWith("![CDATA[", i + 1)) {
1982
+ return skipCdata(xmlContent, i, len);
1983
+ }
1984
+ const gt = xmlContent.indexOf(">", i + 1);
1985
+ return gt === -1 ? len : gt + 1;
1986
+ }
1987
+ if (ch === "?") {
1988
+ return skipProcessingInstruction(xmlContent, i, len);
1989
+ }
1990
+ return -1;
1991
+ }
1992
+ function parseTagName(xmlContent, i, len) {
1993
+ let j = i;
1994
+ if (j < len && isNameStartChar(xmlContent[j])) {
1995
+ j += 1;
1996
+ while (j < len && isNameChar(xmlContent[j])) {
1997
+ j += 1;
1998
+ }
1999
+ }
2000
+ return { name: xmlContent.slice(i, j), pos: j };
2001
+ }
2002
+ function skipToTagEnd(xmlContent, start, len) {
2003
+ let k = start;
2004
+ let isSelfClosing = false;
2005
+ while (k < len) {
2006
+ const c = xmlContent[k];
2007
+ if (c === '"' || c === "'") {
2008
+ k = skipQuoted(xmlContent, k);
2009
+ continue;
2010
+ }
2011
+ if (c === ">") {
2012
+ break;
2013
+ }
2014
+ if (c === "/" && xmlContent[k + 1] === ">") {
2015
+ isSelfClosing = true;
2016
+ k += 1;
2017
+ break;
2018
+ }
2019
+ k += 1;
2020
+ }
2021
+ return { pos: k, isSelfClosing };
2022
+ }
2023
+ function processClosingTagMatch(options) {
2024
+ const { xmlContent, nx, len, tagName, depth, nextLt } = options;
2025
+ const tagInfo = parseTagName(xmlContent, nx + 1, len);
2026
+ const gt = xmlContent.indexOf(">", tagInfo.pos);
2027
+ if (tagInfo.name === tagName) {
2028
+ const newDepth = depth - 1;
2029
+ if (newDepth === 0) {
2030
+ return { newPos: nextLt, newDepth, found: true };
2031
+ }
2032
+ return { newPos: gt === -1 ? len : gt + 1, newDepth, found: false };
2033
+ }
2034
+ return { newPos: gt === -1 ? len : gt + 1, newDepth: depth, found: false };
2035
+ }
2036
+ function processOpeningTagMatch(options) {
2037
+ const { xmlContent, nx, len, tagName, depth } = options;
2038
+ const tagInfo = parseTagName(xmlContent, nx, len);
2039
+ const tagEndInfo = skipToTagEnd(xmlContent, tagInfo.pos, len);
2040
+ const newDepth = tagInfo.name === tagName && !tagEndInfo.isSelfClosing ? depth + 1 : depth;
2041
+ const newPos = xmlContent[tagEndInfo.pos] === ">" ? tagEndInfo.pos + 1 : tagEndInfo.pos + 1;
2042
+ return { newPos, newDepth };
2043
+ }
2044
+ function findMatchingCloseTag(xmlContent, startPos, tagName, len) {
2045
+ let pos = startPos;
2046
+ let depth = 1;
2047
+ while (pos < len) {
2048
+ const nextLt = xmlContent.indexOf("<", pos);
2049
+ if (nextLt === -1 || nextLt + 1 >= len) {
2050
+ break;
2051
+ }
2052
+ const nx = nextLt + 1;
2053
+ const h = xmlContent[nx];
2054
+ const specialPos = skipSpecialConstruct(xmlContent, nx, len);
2055
+ if (specialPos !== -1) {
2056
+ pos = specialPos;
2057
+ continue;
2058
+ }
2059
+ if (h === "/") {
2060
+ const result = processClosingTagMatch({
2061
+ xmlContent,
2062
+ nx,
2063
+ len,
2064
+ tagName,
2065
+ depth,
2066
+ nextLt
2067
+ });
2068
+ if (result.found) {
2069
+ return result.newPos;
2070
+ }
2071
+ pos = result.newPos;
2072
+ depth = result.newDepth;
2073
+ } else {
2074
+ const result = processOpeningTagMatch({
2075
+ xmlContent,
2076
+ nx,
2077
+ len,
2078
+ tagName,
2079
+ depth
2080
+ });
2081
+ pos = result.newPos;
2082
+ depth = result.newDepth;
2083
+ }
2084
+ }
2085
+ return -1;
2086
+ }
2087
+ function updateBestMatch(depth, bestDepth, contentStart, contentEnd) {
2088
+ if (depth < bestDepth) {
2089
+ return { start: contentStart, end: contentEnd, depth };
2090
+ }
2091
+ return null;
2092
+ }
2093
+ function processTargetTag(options) {
2094
+ const { xmlContent, tagEnd, isSelfClosing, target, len, depth, bestDepth } = options;
2095
+ const contentStart = xmlContent[tagEnd] === ">" ? tagEnd + 1 : tagEnd + 1;
2096
+ if (isSelfClosing) {
2097
+ return updateBestMatch(depth, bestDepth, contentStart, contentStart);
2098
+ }
2099
+ const closePos = findMatchingCloseTag(xmlContent, contentStart, target, len);
2100
+ if (closePos !== -1) {
2101
+ return updateBestMatch(depth, bestDepth, contentStart, closePos);
2102
+ }
2103
+ return null;
2104
+ }
2105
+ function handleClosingTagInExtract(xmlContent, i, len, depth) {
2106
+ const gt = xmlContent.indexOf(">", i + 1);
2107
+ return {
2108
+ newPos: gt === -1 ? len : gt + 1,
2109
+ newDepth: Math.max(0, depth - 1)
2110
+ };
2111
+ }
2112
+ function processOpeningTagInExtract(options) {
2113
+ const { xmlContent, i, len, target, depth, bestDepth } = options;
2114
+ const tagInfo = parseTagName(xmlContent, i, len);
2115
+ const tagEndInfo = skipToTagEnd(xmlContent, tagInfo.pos, len);
2116
+ const tagEnd = tagEndInfo.pos;
2117
+ const isSelfClosing = tagEndInfo.isSelfClosing;
2118
+ let bestMatch = null;
2119
+ if (tagInfo.name === target) {
2120
+ bestMatch = processTargetTag({
2121
+ xmlContent,
2122
+ tagEnd,
2123
+ isSelfClosing,
2124
+ target,
2125
+ len,
2126
+ depth,
2127
+ bestDepth
2128
+ });
2129
+ }
2130
+ return {
2131
+ newPos: xmlContent[tagEnd] === ">" ? tagEnd + 1 : tagEnd + 1,
2132
+ newDepth: depth + (isSelfClosing ? 0 : 1),
2133
+ bestMatch
2134
+ };
2135
+ }
2136
+ function extractRawInner(xmlContent, tagName) {
2137
+ const len = xmlContent.length;
2138
+ const target = tagName;
2139
+ let bestStart = -1;
2140
+ let bestEnd = -1;
2141
+ let bestDepth = Number.POSITIVE_INFINITY;
2142
+ let i = 0;
2143
+ let depth = 0;
2144
+ while (i < len) {
2145
+ const lt = xmlContent.indexOf("<", i);
2146
+ if (lt === -1 || lt + 1 >= len) {
2147
+ return;
2148
+ }
2149
+ i = lt + 1;
2150
+ const ch = xmlContent[i];
2151
+ const specialPos = skipSpecialConstruct(xmlContent, i, len);
2152
+ if (specialPos !== -1) {
2153
+ i = specialPos;
2154
+ continue;
2155
+ }
2156
+ if (ch === "/") {
2157
+ const result2 = handleClosingTagInExtract(xmlContent, i, len, depth);
2158
+ i = result2.newPos;
2159
+ depth = result2.newDepth;
2160
+ continue;
2161
+ }
2162
+ const result = processOpeningTagInExtract({
2163
+ xmlContent,
2164
+ i,
2165
+ len,
2166
+ target,
2167
+ depth,
2168
+ bestDepth
2169
+ });
2170
+ if (result.bestMatch) {
2171
+ bestStart = result.bestMatch.start;
2172
+ bestEnd = result.bestMatch.end;
2173
+ bestDepth = result.bestMatch.depth;
2174
+ }
2175
+ i = result.newPos;
2176
+ depth = result.newDepth;
2177
+ }
2178
+ if (bestStart !== -1) {
2179
+ return xmlContent.slice(bestStart, bestEnd);
2180
+ }
2181
+ return;
2182
+ }
2183
+ function processOpeningTag(options) {
2184
+ const { xmlContent, tagEnd, isSelfClosing, target, len, ranges } = options;
2185
+ const contentStart = xmlContent[tagEnd] === ">" ? tagEnd + 1 : tagEnd + 1;
2186
+ if (isSelfClosing) {
2187
+ ranges.push({ start: contentStart, end: contentStart });
2188
+ return contentStart;
2189
+ }
2190
+ const closePos = findMatchingCloseTag(xmlContent, contentStart, target, len);
2191
+ if (closePos !== -1) {
2192
+ ranges.push({ start: contentStart, end: closePos });
2193
+ const gt = xmlContent.indexOf(">", closePos);
2194
+ return gt === -1 ? len : gt + 1;
2195
+ }
2196
+ return -1;
2197
+ }
2198
+ function handleClosingTagInFindAll(xmlContent, i, len) {
2199
+ const gt = xmlContent.indexOf(">", i + 1);
2200
+ return gt === -1 ? len : gt + 1;
2201
+ }
2202
+ function findAllInnerRanges(xmlContent, tagName) {
2203
+ const len = xmlContent.length;
2204
+ const target = tagName;
2205
+ const ranges = [];
2206
+ let i = 0;
2207
+ while (i < len) {
2208
+ const lt = xmlContent.indexOf("<", i);
2209
+ if (lt === -1 || lt + 1 >= len) {
2210
+ break;
2211
+ }
2212
+ i = lt + 1;
2213
+ const ch = xmlContent[i];
2214
+ const specialPos = skipSpecialConstruct(xmlContent, i, len);
2215
+ if (specialPos !== -1) {
2216
+ i = specialPos;
2217
+ continue;
2218
+ }
2219
+ if (ch === "/") {
2220
+ i = handleClosingTagInFindAll(xmlContent, i, len);
2221
+ continue;
2222
+ }
2223
+ const tagInfo = parseTagName(xmlContent, i, len);
2224
+ const tagEndInfo = skipToTagEnd(xmlContent, tagInfo.pos, len);
2225
+ const tagEnd = tagEndInfo.pos;
2226
+ const isSelfClosing = tagEndInfo.isSelfClosing;
2227
+ if (tagInfo.name !== target) {
2228
+ i = xmlContent[tagEnd] === ">" ? tagEnd + 1 : tagEnd + 1;
2229
+ continue;
2230
+ }
2231
+ const nextPos = processOpeningTag({
2232
+ xmlContent,
2233
+ tagEnd,
2234
+ isSelfClosing,
2235
+ target,
2236
+ len,
2237
+ ranges
2238
+ });
2239
+ if (nextPos === -1) {
2240
+ break;
2241
+ }
2242
+ i = nextPos;
2243
+ }
2244
+ return ranges;
2245
+ }
2246
+ function findTopLevelTargetRange(options) {
2247
+ const { xmlContent, tagEnd, isSelfClosing, target, len } = options;
2248
+ const contentStart = xmlContent[tagEnd] === ">" ? tagEnd + 1 : tagEnd + 1;
2249
+ if (isSelfClosing) {
2250
+ return { start: contentStart, end: contentStart };
2251
+ }
2252
+ const closePos = findMatchingCloseTag(xmlContent, contentStart, target, len);
2253
+ if (closePos !== -1) {
2254
+ return { start: contentStart, end: closePos };
2255
+ }
2256
+ return;
2257
+ }
2258
+ function handleClosingTagInFindFirst(xmlContent, i, len, depth) {
2259
+ const gt = xmlContent.indexOf(">", i + 1);
2260
+ return {
2261
+ newPos: gt === -1 ? len : gt + 1,
2262
+ newDepth: Math.max(0, depth - 1)
2263
+ };
2264
+ }
2265
+ function findFirstTopLevelRange(xmlContent, tagName) {
2266
+ const len = xmlContent.length;
2267
+ const target = tagName;
2268
+ let i = 0;
2269
+ let depth = 0;
2270
+ while (i < len) {
2271
+ const lt = xmlContent.indexOf("<", i);
2272
+ if (lt === -1 || lt + 1 >= len) {
2273
+ return;
2274
+ }
2275
+ i = lt + 1;
2276
+ const ch = xmlContent[i];
2277
+ const specialPos = skipSpecialConstruct(xmlContent, i, len);
2278
+ if (specialPos !== -1) {
2279
+ i = specialPos;
2280
+ continue;
2281
+ }
2282
+ if (ch === "/") {
2283
+ const result = handleClosingTagInFindFirst(xmlContent, i, len, depth);
2284
+ i = result.newPos;
2285
+ depth = result.newDepth;
2286
+ continue;
2287
+ }
2288
+ const tagInfo = parseTagName(xmlContent, i, len);
2289
+ const tagEndInfo = skipToTagEnd(xmlContent, tagInfo.pos, len);
2290
+ const tagEnd = tagEndInfo.pos;
2291
+ const isSelfClosing = tagEndInfo.isSelfClosing;
2292
+ if (depth === 0 && tagInfo.name === target) {
2293
+ return findTopLevelTargetRange({
2294
+ xmlContent,
2295
+ tagEnd,
2296
+ isSelfClosing,
2297
+ target,
2298
+ len
2299
+ });
2300
+ }
2301
+ i = xmlContent[tagEnd] === ">" ? tagEnd + 1 : tagEnd + 1;
2302
+ depth += isSelfClosing ? 0 : 1;
2303
+ }
2304
+ return;
2305
+ }
2306
+ function isPositionExcluded(pos, excludeRanges) {
2307
+ if (!excludeRanges || excludeRanges.length === 0) {
2308
+ return false;
2309
+ }
2310
+ for (const r of excludeRanges) {
2311
+ if (pos >= r.start && pos < r.end) {
2312
+ return true;
2313
+ }
2314
+ }
2315
+ return false;
2316
+ }
2317
+ function skipCommentInCounting(xmlContent, i, len) {
2318
+ const close = xmlContent.indexOf("-->", i + 4);
2319
+ return close === -1 ? len : close + 3;
2320
+ }
2321
+ function skipCdataInCounting(xmlContent, i, len) {
2322
+ const close = xmlContent.indexOf("]]>", i + 9);
2323
+ return close === -1 ? len : close + 3;
2324
+ }
2325
+ function skipSpecialInCounting(xmlContent, ch, i, len) {
2326
+ if (ch === "!") {
2327
+ if (xmlContent.startsWith("!--", i + 1)) {
2328
+ return skipCommentInCounting(xmlContent, i, len);
2329
+ }
2330
+ if (xmlContent.startsWith("![CDATA[", i + 1)) {
2331
+ return skipCdataInCounting(xmlContent, i, len);
2332
+ }
2333
+ const gt = xmlContent.indexOf(">", i + 1);
2334
+ return gt === -1 ? len : gt + 1;
2335
+ }
2336
+ if (ch === "?") {
2337
+ const close = xmlContent.indexOf("?>", i + 1);
2338
+ return close === -1 ? len : close + 2;
2339
+ }
2340
+ if (ch === "/") {
2341
+ const gt = xmlContent.indexOf(">", i + 1);
2342
+ return gt === -1 ? len : gt + 1;
2343
+ }
2344
+ return -1;
2345
+ }
2346
+ function parseAndCountTag(options) {
2347
+ const { xmlContent, i, len, target, lt, excludeRanges } = options;
2348
+ let j = i;
2349
+ if (j < len && isNameStartChar(xmlContent[j])) {
2350
+ j += 1;
2351
+ while (j < len && isNameChar(xmlContent[j])) {
2352
+ j += 1;
2353
+ }
2354
+ }
2355
+ const name = xmlContent.slice(i, j);
2356
+ let k = j;
2357
+ while (k < len) {
2358
+ const c = xmlContent[k];
2359
+ if (c === '"' || c === "'") {
2360
+ k = skipQuoted(xmlContent, k);
2361
+ continue;
2362
+ }
2363
+ if (c === ">") {
2364
+ break;
2365
+ }
2366
+ if (c === "/" && xmlContent[k + 1] === ">") {
2367
+ k += 1;
2368
+ break;
2369
+ }
2370
+ k += 1;
2371
+ }
2372
+ const shouldCount = name === target && !isPositionExcluded(lt, excludeRanges);
2373
+ return { nextPos: k + 1, shouldCount };
2374
+ }
2375
+ function countTagOccurrences(xmlContent, tagName, excludeRanges, shouldSkipFirst = true) {
2376
+ const len = xmlContent.length;
2377
+ const target = tagName;
2378
+ let i = 0;
2379
+ let count = 0;
2380
+ let skipFirstLocal = shouldSkipFirst;
2381
+ while (i < len) {
2382
+ const lt = xmlContent.indexOf("<", i);
2383
+ if (lt === -1) {
2384
+ break;
2385
+ }
2386
+ i = lt + 1;
2387
+ if (i >= len) {
2388
+ break;
2389
+ }
2390
+ const ch = xmlContent[i];
2391
+ const skipPos = skipSpecialInCounting(xmlContent, ch, i, len);
2392
+ if (skipPos !== -1) {
2393
+ i = skipPos;
2394
+ continue;
2395
+ }
2396
+ const result = parseAndCountTag({
2397
+ xmlContent,
2398
+ i,
2399
+ len,
2400
+ target,
2401
+ lt,
2402
+ excludeRanges
2403
+ });
2404
+ if (result.shouldCount) {
2405
+ if (skipFirstLocal) {
2406
+ skipFirstLocal = false;
2407
+ } else {
2408
+ count += 1;
2409
+ }
2410
+ }
2411
+ i = result.nextPos;
2412
+ }
2413
+ return count;
2414
+ }
2415
+
2416
+ // src/rxml/core/tokenizer.ts
2417
+ var XMLTokenizer = class {
2418
+ constructor(xmlString, options = {}) {
2419
+ this.pos = 0;
2420
+ this.xmlString = xmlString;
2421
+ this.options = {
2422
+ keepComments: false,
2423
+ keepWhitespace: false,
2424
+ noChildNodes: DEFAULT_NO_CHILD_NODES.slice(),
2425
+ textNodeName: "#text",
2426
+ throwOnDuplicateStringTags: true,
2427
+ ...options
2428
+ };
2429
+ this.pos = options.pos || 0;
2430
+ }
2431
+ /**
2432
+ * Handle closing tag parsing
2433
+ */
2434
+ handleClosingTag(tagName, children) {
2435
+ const closeStart = this.pos + 2;
2436
+ this.pos = this.xmlString.indexOf(">", this.pos);
2437
+ const closeTag = this.xmlString.substring(closeStart, this.pos);
2438
+ if (tagName && closeTag.trim() !== tagName) {
2439
+ const { line, column } = getLineColumn(this.xmlString, this.pos);
2440
+ throw new RXMLParseError(
2441
+ `Unexpected close tag at line ${line}, column ${column}. Expected </${tagName}>, found </${closeTag}>`,
2442
+ void 0,
2443
+ line,
2444
+ column
2445
+ );
2446
+ }
2447
+ if (this.pos !== -1) {
2448
+ this.pos += 1;
2449
+ }
2450
+ return children;
2451
+ }
2452
+ /**
2453
+ * Check if we're at end of string and should throw unclosed tag error
2454
+ */
2455
+ checkUnclosedTag(tagName, consumedToEnd) {
2456
+ if (tagName && this.pos >= this.xmlString.length && !consumedToEnd) {
2457
+ const { line, column } = getLineColumn(this.xmlString, this.pos - 1);
2458
+ throw new RXMLParseError(
2459
+ `Unclosed tag at line ${line}, column ${column}. Expected closing tag </${tagName}>`,
2460
+ void 0,
2461
+ line,
2462
+ column
2463
+ );
2464
+ }
2465
+ }
2466
+ /**
2467
+ * Process special content (comments, CDATA, DOCTYPE) and track if we consumed to end
2468
+ */
2469
+ processSpecialContent(children) {
2470
+ const prevPos = this.pos;
2471
+ this.handleSpecialContent(children);
2472
+ return this.pos >= this.xmlString.length && prevPos < this.xmlString.length;
2473
+ }
2474
+ /**
2475
+ * Handle text content parsing
2476
+ */
2477
+ handleTextContent(children) {
2478
+ const text = this.parseText();
2479
+ if (this.options.keepWhitespace) {
2480
+ if (text.length > 0) {
2481
+ children.push(text);
2482
+ }
2483
+ } else {
2484
+ const trimmed = text.trim();
2485
+ if (trimmed.length > 0) {
2486
+ children.push(trimmed);
2487
+ }
2488
+ }
2489
+ this.pos += 1;
2490
+ }
2491
+ /**
2492
+ * Handle regular element parsing
2493
+ */
2494
+ handleRegularElement(children) {
2495
+ const node = this.parseNode();
2496
+ children.push(node);
2497
+ if (node.tagName[0] === "?") {
2498
+ children.push(...node.children);
2499
+ node.children = [];
2500
+ }
2501
+ }
2502
+ /**
2503
+ * Process a single child element based on the current character
2504
+ */
2505
+ processSingleChild(children, tagName) {
2506
+ if (this.xmlString.charCodeAt(this.pos) !== CharCodes.OPEN_BRACKET) {
2507
+ this.handleTextContent(children);
2508
+ return { shouldReturn: false, consumedToEnd: false };
2509
+ }
2510
+ const nextChar = this.xmlString.charCodeAt(this.pos + 1);
2511
+ if (nextChar === CharCodes.SLASH) {
2512
+ const result = this.handleClosingTag(tagName, children);
2513
+ if (result !== null) {
2514
+ return { shouldReturn: true, consumedToEnd: false };
2515
+ }
2516
+ return { shouldReturn: false, consumedToEnd: false };
2517
+ }
2518
+ if (nextChar === CharCodes.EXCLAMATION) {
2519
+ const wasConsumedToEnd = this.processSpecialContent(children);
2520
+ return { shouldReturn: false, consumedToEnd: wasConsumedToEnd };
2521
+ }
2522
+ this.handleRegularElement(children);
2523
+ return { shouldReturn: false, consumedToEnd: false };
2524
+ }
2525
+ /**
2526
+ * Parse XML children recursively
2527
+ */
2528
+ parseChildren(tagName) {
2529
+ const children = [];
2530
+ let consumedToEnd = false;
2531
+ while (this.xmlString[this.pos]) {
2532
+ const result = this.processSingleChild(children, tagName);
2533
+ if (result.shouldReturn) {
2534
+ return children;
2535
+ }
2536
+ if (result.consumedToEnd) {
2537
+ consumedToEnd = true;
2538
+ }
2539
+ }
2540
+ this.checkUnclosedTag(tagName, consumedToEnd);
2541
+ return children;
2542
+ }
2543
+ /**
2544
+ * Check if character is whitespace
2545
+ */
2546
+ isWhitespace(code) {
2547
+ return code === CharCodes.SPACE || code === CharCodes.TAB || code === CharCodes.NEWLINE || code === CharCodes.CARRIAGE_RETURN;
2548
+ }
2549
+ /**
2550
+ * Skip whitespace characters
2551
+ */
2552
+ skipWhitespace() {
2553
+ while (this.pos < this.xmlString.length && this.isWhitespace(this.xmlString.charCodeAt(this.pos))) {
2554
+ this.pos += 1;
2555
+ }
2556
+ }
2557
+ /**
2558
+ * Parse attribute value
2559
+ */
2560
+ parseAttributeValue() {
2561
+ if (this.pos >= this.xmlString.length || this.xmlString[this.pos] !== "=") {
2562
+ return null;
2563
+ }
2564
+ this.pos += 1;
2565
+ this.skipWhitespace();
2566
+ const code = this.xmlString.charCodeAt(this.pos);
2567
+ if (code === CharCodes.SINGLE_QUOTE || code === CharCodes.DOUBLE_QUOTE) {
2568
+ const { value: parsedValue, newPos: valueEnd } = parseString(
2569
+ this.xmlString,
2570
+ this.pos
2571
+ );
2572
+ this.pos = valueEnd;
2573
+ return parsedValue;
2574
+ }
2575
+ return null;
2576
+ }
2577
+ /**
2578
+ * Parse single attribute
2579
+ */
2580
+ parseAttribute(attributes) {
2581
+ const { name: attrName, newPos: nameEnd } = parseName(
2582
+ this.xmlString,
2583
+ this.pos
2584
+ );
2585
+ this.pos = nameEnd;
2586
+ this.skipWhitespace();
2587
+ const value = this.parseAttributeValue();
2588
+ attributes[attrName] = value;
2589
+ }
2590
+ /**
2591
+ * Parse all attributes
2592
+ */
2593
+ parseAttributes() {
2594
+ const attributes = {};
2595
+ while (this.xmlString.charCodeAt(this.pos) !== CharCodes.CLOSE_BRACKET && this.xmlString[this.pos]) {
2596
+ const c = this.xmlString.charCodeAt(this.pos);
2597
+ if (this.isWhitespace(c)) {
2598
+ this.pos += 1;
2599
+ continue;
2600
+ }
2601
+ if (c > 64 && c < 91 || c > 96 && c < 123) {
2602
+ this.parseAttribute(attributes);
2603
+ } else {
2604
+ this.pos += 1;
2605
+ }
2606
+ }
2607
+ return attributes;
2608
+ }
2609
+ /**
2610
+ * Parse special tag content (script, style)
2611
+ */
2612
+ parseSpecialTagContent(_tagName, closingTag) {
2613
+ const start = this.pos + 1;
2614
+ this.pos = this.xmlString.indexOf(closingTag, this.pos);
2615
+ if (this.pos === -1) {
2616
+ const children2 = [this.xmlString.slice(start)];
2617
+ this.pos = this.xmlString.length;
2618
+ return children2;
2619
+ }
2620
+ const children = [this.xmlString.slice(start, this.pos)];
2621
+ this.pos += closingTag.length;
2622
+ return children;
2623
+ }
2624
+ /**
2625
+ * Parse node children based on tag type
2626
+ */
2627
+ parseNodeChildren(tagName, isSelfClosing) {
2628
+ var _a;
2629
+ if (isSelfClosing) {
2630
+ this.pos += 1;
2631
+ return [];
2632
+ }
2633
+ if (tagName === "script") {
2634
+ return this.parseSpecialTagContent(tagName, "</script>");
2635
+ }
2636
+ if (tagName === "style") {
2637
+ return this.parseSpecialTagContent(tagName, "</style>");
2638
+ }
2639
+ if (((_a = this.options.noChildNodes) == null ? void 0 : _a.indexOf(tagName)) === -1) {
2640
+ this.pos += 1;
2641
+ return this.parseChildren(tagName);
2642
+ }
2643
+ this.pos += 1;
2644
+ if (DEFAULT_NO_CHILD_NODES.includes(tagName)) {
2645
+ return [];
2646
+ }
2647
+ const closingTag = `</${tagName}>`;
2648
+ const closingPos = this.xmlString.indexOf(closingTag, this.pos);
2649
+ if (closingPos !== -1) {
2650
+ this.pos = closingPos + closingTag.length;
2651
+ }
2652
+ return [];
2653
+ }
2654
+ /**
2655
+ * Parse a single XML node
2656
+ */
2657
+ parseNode() {
2658
+ this.pos += 1;
2659
+ const { name: tagName, newPos } = parseName(this.xmlString, this.pos);
2660
+ this.pos = newPos;
2661
+ const attributes = this.parseAttributes();
2662
+ const isSelfClosing = this.xmlString.charCodeAt(this.pos - 1) === CharCodes.SLASH || tagName[0] === "?" && this.xmlString.charCodeAt(this.pos - 1) === CharCodes.QUESTION;
2663
+ const children = this.parseNodeChildren(tagName, isSelfClosing);
2664
+ return { tagName, attributes, children };
2665
+ }
2666
+ /**
2667
+ * Parse text content until next tag
2668
+ */
2669
+ parseText() {
2670
+ const start = this.pos;
2671
+ this.pos = this.xmlString.indexOf("<", this.pos) - 1;
2672
+ if (this.pos === -2) {
2673
+ this.pos = this.xmlString.length;
2674
+ }
2675
+ return this.xmlString.slice(start, this.pos + 1);
2676
+ }
2677
+ /**
2678
+ * Handle comments, CDATA, and DOCTYPE declarations
2679
+ */
2680
+ handleSpecialContent(children) {
2681
+ if (this.xmlString.charCodeAt(this.pos + 2) === CharCodes.MINUS) {
2682
+ this.handleComment(children);
2683
+ } else if (this.xmlString.charCodeAt(this.pos + 2) === CharCodes.OPEN_CORNER_BRACKET && this.xmlString.charCodeAt(this.pos + 8) === CharCodes.OPEN_CORNER_BRACKET && this.xmlString.substr(this.pos + 3, 5).toLowerCase() === "cdata") {
2684
+ this.handleCData(children);
2685
+ } else {
2686
+ this.handleDoctype(children);
2687
+ }
2688
+ }
2689
+ /**
2690
+ * Handle XML comments
2691
+ */
2692
+ handleComment(children) {
2693
+ const startCommentPos = this.pos;
2694
+ while (this.pos !== -1 && !(this.xmlString.charCodeAt(this.pos) === CharCodes.CLOSE_BRACKET && this.xmlString.charCodeAt(this.pos - 1) === CharCodes.MINUS && this.xmlString.charCodeAt(this.pos - 2) === CharCodes.MINUS)) {
2695
+ this.pos = this.xmlString.indexOf(">", this.pos + 1);
2696
+ }
2697
+ if (this.pos === -1) {
2698
+ this.pos = this.xmlString.length;
2699
+ }
2700
+ if (this.options.keepComments) {
2701
+ children.push(this.xmlString.substring(startCommentPos, this.pos + 1));
2702
+ }
2703
+ this.pos += 1;
2704
+ }
2705
+ /**
2706
+ * Handle CDATA sections
2707
+ */
2708
+ handleCData(children) {
2709
+ const cdataEndIndex = this.xmlString.indexOf("]]>", this.pos);
2710
+ if (cdataEndIndex === -1) {
2711
+ children.push(this.xmlString.substr(this.pos + 9));
2712
+ this.pos = this.xmlString.length;
2713
+ } else {
2714
+ children.push(this.xmlString.substring(this.pos + 9, cdataEndIndex));
2715
+ this.pos = cdataEndIndex + 3;
2716
+ }
2717
+ }
2718
+ /**
2719
+ * Handle DOCTYPE declarations
2720
+ */
2721
+ handleDoctype(children) {
2722
+ const startDoctype = this.pos + 1;
2723
+ this.pos += 2;
2724
+ let encapsulated = false;
2725
+ while ((this.xmlString.charCodeAt(this.pos) !== CharCodes.CLOSE_BRACKET || encapsulated) && this.xmlString[this.pos]) {
2726
+ if (this.xmlString.charCodeAt(this.pos) === CharCodes.OPEN_CORNER_BRACKET) {
2727
+ encapsulated = true;
2728
+ } else if (encapsulated && this.xmlString.charCodeAt(this.pos) === CharCodes.CLOSE_CORNER_BRACKET) {
2729
+ encapsulated = false;
2730
+ }
2731
+ this.pos += 1;
2732
+ }
2733
+ children.push(this.xmlString.substring(startDoctype, this.pos));
2734
+ this.pos += 1;
2735
+ }
2736
+ /**
2737
+ * Get current position
2738
+ */
2739
+ getPosition() {
2740
+ return this.pos;
2741
+ }
2742
+ /**
2743
+ * Set position
2744
+ */
2745
+ setPosition(pos) {
2746
+ this.pos = pos;
2747
+ }
2748
+ };
2749
+
2750
+ // src/rxml/core/parser.ts
2751
+ var WHITESPACE_REGEX2 = /\s/;
2752
+ var NUMERIC_STRING_REGEX = /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
2753
+ var DIGIT_KEY_REGEX2 = /^\d+$/;
2754
+ function getTopLevelStringProps(s) {
2755
+ const set = /* @__PURE__ */ new Set();
2756
+ const unwrapped = unwrapJsonSchema(s);
2757
+ if (unwrapped && typeof unwrapped === "object") {
2758
+ const props = unwrapped.properties;
2759
+ if (props && typeof props === "object") {
2760
+ for (const [k, v] of Object.entries(props)) {
2761
+ if (getSchemaType(v) === "string") {
2762
+ set.add(k);
2763
+ }
2764
+ }
2765
+ }
2766
+ }
2767
+ return set;
2768
+ }
2769
+ function restorePlaceholderString(val, placeholderMap) {
2770
+ if (val.startsWith("__RXML_PLACEHOLDER_")) {
2771
+ const orig = placeholderMap.get(val);
2772
+ return orig !== void 0 ? orig : val;
2773
+ }
2774
+ return val;
2775
+ }
2776
+ function restorePlaceholdersInObject(obj, _placeholderMap, textNodeName, restorer) {
2777
+ const out = {};
2778
+ for (const [k, v] of Object.entries(obj)) {
2779
+ const restored = restorer(v);
2780
+ if (k === textNodeName && typeof restored === "string") {
2781
+ out[k] = restored.trim();
2782
+ } else {
2783
+ out[k] = restored;
2784
+ }
2785
+ }
2786
+ return out;
2787
+ }
2788
+ function createPlaceholderRestorer(placeholderMap, textNodeName) {
2789
+ const restorer = (val) => {
2790
+ if (val == null) {
2791
+ return val;
2792
+ }
2793
+ if (typeof val === "string") {
2794
+ return restorePlaceholderString(val, placeholderMap);
2795
+ }
2796
+ if (Array.isArray(val)) {
2797
+ return val.map(restorer);
2798
+ }
2799
+ if (typeof val === "object") {
2800
+ return restorePlaceholdersInObject(
2801
+ val,
2802
+ placeholderMap,
2803
+ textNodeName,
2804
+ restorer
2805
+ );
2806
+ }
2807
+ return val;
2808
+ };
2809
+ return restorer;
2810
+ }
2811
+ function tryConvertToNumber(val) {
2812
+ if (typeof val !== "string") {
2813
+ return val;
2814
+ }
2815
+ const trimmed = val.trim();
2816
+ if (NUMERIC_STRING_REGEX.test(trimmed)) {
2817
+ const num = Number(trimmed);
2818
+ if (Number.isFinite(num)) {
2819
+ return num;
2820
+ }
2821
+ }
2822
+ return trimmed;
2823
+ }
2824
+ function processItemValue(item, textNodeName) {
2825
+ let currentVal = item;
2826
+ if (item && typeof item === "object" && Object.hasOwn(item, textNodeName)) {
2827
+ currentVal = item[textNodeName];
2828
+ }
2829
+ const trimmed = typeof currentVal === "string" ? currentVal.trim() : currentVal;
2830
+ return tryConvertToNumber(trimmed);
2831
+ }
2832
+ function processItemWrapper(itemValue, textNodeName) {
2833
+ if (Array.isArray(itemValue)) {
2834
+ return itemValue.map((item) => processItemValue(item, textNodeName));
2835
+ }
2836
+ const trimmed = typeof itemValue === "string" ? itemValue.trim() : itemValue;
2837
+ return tryConvertToNumber(trimmed);
2838
+ }
2839
+ function deepDecodeStringsBySchema(input, schema) {
2840
+ var _a;
2841
+ if (input == null || schema == null) {
2842
+ return input;
2843
+ }
2844
+ const type = getSchemaType(schema);
2845
+ if (type === "string" && typeof input === "string") {
2846
+ return unescapeXml(input);
2847
+ }
2848
+ if (type === "array" && Array.isArray(input)) {
2849
+ const unwrapped = unwrapJsonSchema(schema);
2850
+ const itemSchema = (_a = unwrapped == null ? void 0 : unwrapped.items) != null ? _a : {};
2851
+ return input.map((item) => deepDecodeStringsBySchema(item, itemSchema));
2852
+ }
2853
+ if (type === "object" && input && typeof input === "object") {
2854
+ const obj = input;
2855
+ const out = {};
2856
+ for (const key of Object.keys(obj)) {
2857
+ const childSchema = getPropertySchema(schema, key);
2858
+ out[key] = deepDecodeStringsBySchema(obj[key], childSchema);
2859
+ }
2860
+ return out;
2861
+ }
2862
+ if (typeof input === "string") {
2863
+ return unescapeXml(input);
2864
+ }
2865
+ return input;
2866
+ }
2867
+ function parse2(xmlInner, schema, options = {}) {
2868
+ var _a, _b, _c;
2869
+ const textNodeName = (_a = options.textNodeName) != null ? _a : "#text";
2870
+ const throwDup = (_b = options.throwOnDuplicateStringTags) != null ? _b : true;
2871
+ let actualXmlInner = xmlInner.trim();
2872
+ if (actualXmlInner.startsWith("<") && actualXmlInner.endsWith(">")) {
2873
+ const s = actualXmlInner;
2874
+ let i = 0;
2875
+ let rootStart = -1;
2876
+ let rootName = "";
2877
+ while (i < s.length) {
2878
+ const lt = s.indexOf("<", i);
2879
+ if (lt === -1) {
2880
+ break;
2881
+ }
2882
+ const next = s[lt + 1];
2883
+ if (next === "?") {
2884
+ const end = s.indexOf("?>", lt + 2);
2885
+ i = end === -1 ? s.length : end + 2;
2886
+ continue;
2887
+ }
2888
+ if (next === "!") {
2889
+ if (s.startsWith("!--", lt + 2)) {
2890
+ const end2 = s.indexOf("-->", lt + 5);
2891
+ i = end2 === -1 ? s.length : end2 + 3;
2892
+ continue;
2893
+ }
2894
+ if (s.startsWith("![CDATA[", lt + 2)) {
2895
+ const end2 = s.indexOf("]]>", lt + 9);
2896
+ i = end2 === -1 ? s.length : end2 + 3;
2897
+ continue;
2898
+ }
2899
+ const end = s.indexOf(">", lt + 2);
2900
+ i = end === -1 ? s.length : end + 1;
2901
+ continue;
2902
+ }
2903
+ if (next === "/") {
2904
+ break;
2905
+ }
2906
+ let j = lt + 1;
2907
+ while (j < s.length && s[j] !== " " && s[j] !== "\n" && s[j] !== "\r" && s[j] !== " " && s[j] !== "/" && s[j] !== ">") {
2908
+ j += 1;
2909
+ }
2910
+ rootStart = lt;
2911
+ rootName = s.slice(lt + 1, j);
2912
+ break;
2913
+ }
2914
+ if (rootStart === 0 && rootName) {
2915
+ const range = findFirstTopLevelRange(s, rootName);
2916
+ if (range) {
2917
+ let fullEnd = range.end + `</${rootName}>`.length;
2918
+ const closeHead = s.indexOf(`</${rootName}`, range.end);
2919
+ if (closeHead === range.end) {
2920
+ let p = closeHead + 2 + rootName.length;
2921
+ while (p < s.length && WHITESPACE_REGEX2.test(s[p])) {
2922
+ p += 1;
2923
+ }
2924
+ if (s[p] === ">") {
2925
+ fullEnd = p + 1;
2926
+ }
2927
+ }
2928
+ if (fullEnd === s.length) {
2929
+ const unwrapped = unwrapJsonSchema(schema);
2930
+ const schemaProps = unwrapped && typeof unwrapped === "object" ? unwrapped.properties : void 0;
2931
+ if (schemaProps && !Object.hasOwn(schemaProps, rootName)) {
2932
+ actualXmlInner = s.slice(range.start, range.end);
2933
+ }
2934
+ }
2935
+ }
2936
+ }
2937
+ }
2938
+ const topLevelStringProps = getTopLevelStringProps(schema);
2939
+ const deepStringTypedProps = getStringTypedProperties(schema);
2940
+ const duplicateKeys = /* @__PURE__ */ new Set();
2941
+ for (const key of topLevelStringProps) {
2942
+ const excludeRanges = [];
2943
+ for (const other of topLevelStringProps) {
2944
+ if (other === key) {
2945
+ continue;
2946
+ }
2947
+ const range = findFirstTopLevelRange(actualXmlInner, other);
2948
+ if (range) {
2949
+ excludeRanges.push(range);
2950
+ }
2951
+ }
2952
+ const occurrences = countTagOccurrences(
2953
+ actualXmlInner,
2954
+ key,
2955
+ excludeRanges,
2956
+ true
2957
+ );
2958
+ if (occurrences > 0 && throwDup) {
2959
+ throw new RXMLDuplicateStringTagError(
2960
+ `Duplicate string tags for <${key}> detected`
2961
+ );
2962
+ }
2963
+ if (occurrences > 0 && !throwDup) {
2964
+ duplicateKeys.add(key);
2965
+ if (options.onError) {
2966
+ options.onError(
2967
+ `RXML: Duplicate string tags for <${key}> detected; using first occurrence.`,
2968
+ { tag: key, occurrences }
2969
+ );
2970
+ }
2971
+ }
2972
+ }
2973
+ let xmlInnerForParsing = actualXmlInner;
2974
+ const originalContentMap = /* @__PURE__ */ new Map();
2975
+ try {
2976
+ const ranges = [];
2977
+ for (const key of deepStringTypedProps) {
2978
+ const innerRanges = findAllInnerRanges(actualXmlInner, key);
2979
+ for (const r of innerRanges) {
2980
+ if (r.end > r.start) {
2981
+ ranges.push({ ...r, key });
2982
+ }
2983
+ }
2984
+ }
2985
+ if (ranges.length > 0) {
2986
+ const sorted = [...ranges].sort((a, b) => a.start - b.start);
2987
+ let rebuilt = "";
2988
+ let cursor = 0;
2989
+ for (const r of sorted) {
2990
+ if (r.start < cursor) {
2991
+ continue;
2992
+ }
2993
+ if (cursor < r.start) {
2994
+ rebuilt += actualXmlInner.slice(cursor, r.start);
2995
+ }
2996
+ const placeholder = `__RXML_PLACEHOLDER_${r.key}_${r.start}_${r.end}__`;
2997
+ const originalContent = actualXmlInner.slice(r.start, r.end);
2998
+ originalContentMap.set(placeholder, originalContent);
2999
+ rebuilt += placeholder;
3000
+ cursor = r.end;
3001
+ }
3002
+ if (cursor < actualXmlInner.length) {
3003
+ rebuilt += actualXmlInner.slice(cursor);
3004
+ }
3005
+ xmlInnerForParsing = rebuilt;
3006
+ }
3007
+ } catch (error) {
3008
+ if (options.onError) {
3009
+ options.onError(
3010
+ "RXML: Failed to replace string placeholders, falling back to original XML.",
3011
+ { error }
3012
+ );
3013
+ }
3014
+ xmlInnerForParsing = actualXmlInner;
3015
+ }
3016
+ let parsedNodes;
3017
+ try {
3018
+ const wrappedXml = `<root>${xmlInnerForParsing}</root>`;
3019
+ const tokenizer = new XMLTokenizer(wrappedXml, {
3020
+ ...options,
3021
+ textNodeName
3022
+ });
3023
+ const rootNode = tokenizer.parseNode();
3024
+ parsedNodes = rootNode.children;
3025
+ } catch (cause) {
3026
+ throw new RXMLParseError("Failed to parse XML", cause);
3027
+ }
3028
+ const parsedArgs = domToObject(parsedNodes, schema, textNodeName);
3029
+ const restorePlaceholdersDeep = createPlaceholderRestorer(
3030
+ originalContentMap,
3031
+ textNodeName
3032
+ );
3033
+ const parsedArgsRestored = restorePlaceholdersDeep(parsedArgs);
3034
+ const args = {};
3035
+ for (const k of Object.keys(parsedArgsRestored || {})) {
3036
+ const v = parsedArgsRestored[k];
3037
+ let val = v;
3038
+ const propSchema = getPropertySchema(schema, k);
3039
+ const propType = getSchemaType(propSchema);
3040
+ if (propType === "string" && duplicateKeys.has(k) && Array.isArray(v)) {
3041
+ const firstValue = v[0];
3042
+ if (typeof firstValue === "string" && firstValue.startsWith("__RXML_PLACEHOLDER_")) {
3043
+ const originalContent = originalContentMap.get(firstValue);
3044
+ if (originalContent !== void 0) {
3045
+ args[k] = originalContent;
3046
+ continue;
3047
+ }
3048
+ } else {
3049
+ args[k] = firstValue;
3050
+ continue;
3051
+ }
3052
+ }
3053
+ if (propType === "string" && !Array.isArray(v)) {
3054
+ const placeholderUsed = typeof v === "string" && v.startsWith("__RXML_PLACEHOLDER_") || v && typeof v === "object" && Object.hasOwn(v, textNodeName) && typeof v[textNodeName] === "string" && v[textNodeName].startsWith(
3055
+ "__RXML_PLACEHOLDER_"
3056
+ );
3057
+ if (placeholderUsed) {
3058
+ let placeholderKey;
3059
+ if (typeof v === "string") {
3060
+ placeholderKey = v;
3061
+ } else {
3062
+ placeholderKey = v[textNodeName];
3063
+ }
3064
+ const originalContent = originalContentMap.get(placeholderKey);
3065
+ if (originalContent !== void 0) {
3066
+ args[k] = originalContent;
3067
+ continue;
3068
+ }
3069
+ }
3070
+ const raw = extractRawInner(actualXmlInner, k);
3071
+ if (typeof raw === "string") {
3072
+ args[k] = raw;
3073
+ continue;
3074
+ }
3075
+ }
3076
+ if (v && typeof v === "object" && Object.hasOwn(v, textNodeName)) {
3077
+ val = v[textNodeName];
3078
+ }
3079
+ if (Array.isArray(v)) {
3080
+ if (propType === "string") {
3081
+ const mapped = v.map((item) => {
3082
+ if (item && typeof item === "object" && Object.hasOwn(item, textNodeName)) {
3083
+ const textVal = item[textNodeName];
3084
+ return typeof textVal === "string" ? textVal : String(textVal);
3085
+ }
3086
+ return typeof item === "string" ? item : String(item);
3087
+ });
3088
+ if (mapped.length > 1 && throwDup) {
3089
+ throw new RXMLDuplicateStringTagError(
3090
+ `Duplicate string tags for <${k}> detected`
3091
+ );
3092
+ }
3093
+ if (mapped.length > 1 && !throwDup && options.onError) {
3094
+ options.onError(
3095
+ `RXML: Duplicate string tags for <${k}> detected; using first occurrence.`,
3096
+ { tag: k, occurrences: mapped.length }
3097
+ );
3098
+ }
3099
+ args[k] = (_c = mapped[0]) != null ? _c : "";
3100
+ continue;
3101
+ }
3102
+ val = processArrayContent(v, propSchema, textNodeName);
3103
+ } else if (v && typeof v === "object" && !Object.hasOwn(v, textNodeName)) {
3104
+ const obj = v;
3105
+ const keys2 = Object.keys(obj);
3106
+ if (keys2.length === 1 && keys2[0] === "item") {
3107
+ val = processItemWrapper(obj.item, textNodeName);
3108
+ } else {
3109
+ let isIndexedTuple = false;
3110
+ if (keys2.length > 0 && keys2.every((key) => DIGIT_KEY_REGEX2.test(key))) {
3111
+ const indices = keys2.map((keyStr) => Number.parseInt(keyStr, 10)).sort((a, b) => a - b);
3112
+ isIndexedTuple = indices[0] === 0 && indices.every((indexVal, idx) => indexVal === idx);
3113
+ }
3114
+ if (isIndexedTuple) {
3115
+ val = processIndexedTuple(obj, textNodeName);
3116
+ } else {
3117
+ val = v;
3118
+ }
3119
+ }
3120
+ }
3121
+ args[k] = typeof val === "string" ? val.trim() : val;
3122
+ }
3123
+ for (const key of topLevelStringProps) {
3124
+ if (!Object.hasOwn(args, key)) {
3125
+ const raw = extractRawInner(actualXmlInner, key);
3126
+ if (typeof raw === "string") {
3127
+ args[key] = raw;
3128
+ }
3129
+ }
3130
+ }
3131
+ let dataToCoerce = args;
3132
+ const keys = Object.keys(args);
3133
+ if (keys.length === 1) {
3134
+ const rootKey = keys[0];
3135
+ const rootValue = args[rootKey];
3136
+ const unwrapped = unwrapJsonSchema(schema);
3137
+ if (unwrapped && typeof unwrapped === "object") {
3138
+ const schemaProps = unwrapped.properties;
3139
+ if (schemaProps && !Object.hasOwn(schemaProps, rootKey)) {
3140
+ dataToCoerce = rootValue;
3141
+ }
3142
+ }
3143
+ }
3144
+ try {
3145
+ const coerced = coerceDomBySchema(dataToCoerce, schema);
3146
+ const decoded = deepDecodeStringsBySchema(coerced, schema);
3147
+ return decoded;
3148
+ } catch (error) {
3149
+ throw new RXMLCoercionError("Failed to coerce by schema", error);
3150
+ }
3151
+ }
3152
+
3153
+ // src/rxml/heuristics/engine.ts
3154
+ function applyRawSegmentUpdate(current, result) {
3155
+ if (result.rawSegment !== void 0) {
3156
+ return { ...current, rawSegment: result.rawSegment };
3157
+ }
3158
+ return current;
3159
+ }
3160
+ function applyParsedUpdate(current, result) {
3161
+ if (result.parsed !== void 0) {
3162
+ return { ...current, parsed: result.parsed };
3163
+ }
3164
+ return current;
3165
+ }
3166
+ function applyWarningsUpdate(current, result) {
3167
+ var _a, _b;
3168
+ if (result.warnings && result.warnings.length > 0) {
3169
+ const meta = (_a = current.meta) != null ? _a : {};
3170
+ const existingWarnings = (_b = meta.warnings) != null ? _b : [];
3171
+ return {
3172
+ ...current,
3173
+ meta: { ...meta, warnings: [...existingWarnings, ...result.warnings] }
3174
+ };
3175
+ }
3176
+ return current;
3177
+ }
3178
+ function attemptReparse(current, result, reparseCount, maxReparses, parse4) {
3179
+ if (!result.reparse || result.rawSegment === void 0 || reparseCount >= maxReparses) {
3180
+ return { state: current, newCount: reparseCount };
3181
+ }
3182
+ try {
3183
+ const reparsed = parse4(result.rawSegment, current.schema);
3184
+ return {
3185
+ state: { ...current, parsed: reparsed, errors: [] },
3186
+ newCount: reparseCount + 1
3187
+ };
3188
+ } catch (error) {
3189
+ return {
3190
+ state: { ...current, errors: [...current.errors, error] },
3191
+ newCount: reparseCount + 1
3192
+ };
3193
+ }
3194
+ }
3195
+ function executePhase(ctx, heuristics, options) {
3196
+ var _a;
3197
+ let current = ctx;
3198
+ let reparseCount = 0;
3199
+ const maxReparses = (_a = options.maxReparses) != null ? _a : 2;
3200
+ for (const heuristic of heuristics) {
3201
+ if (!heuristic.applies(current)) {
3202
+ continue;
3203
+ }
3204
+ const result = heuristic.run(current);
3205
+ current = applyRawSegmentUpdate(current, result);
3206
+ current = applyParsedUpdate(current, result);
3207
+ current = applyWarningsUpdate(current, result);
3208
+ const reparseResult = attemptReparse(
3209
+ current,
3210
+ result,
3211
+ reparseCount,
3212
+ maxReparses,
3213
+ options.parse
3214
+ );
3215
+ current = reparseResult.state;
3216
+ reparseCount = reparseResult.newCount;
3217
+ if (result.stop) {
3218
+ break;
3219
+ }
3220
+ }
3221
+ return current;
3222
+ }
3223
+ function applyHeuristicPipeline(ctx, config, options) {
3224
+ let current = ctx;
3225
+ if (config.preParse && config.preParse.length > 0) {
3226
+ current = executePhase(current, config.preParse, options);
3227
+ }
3228
+ if (current.parsed === null && current.errors.length === 0) {
3229
+ try {
3230
+ const parsed = options.parse(current.rawSegment, current.schema);
3231
+ current = { ...current, parsed, errors: [] };
3232
+ } catch (error) {
3233
+ current = { ...current, errors: [error] };
3234
+ }
3235
+ }
3236
+ if (current.errors.length > 0 && config.fallbackReparse && config.fallbackReparse.length > 0) {
3237
+ current = executePhase(current, config.fallbackReparse, options);
3238
+ }
3239
+ if (current.parsed !== null && config.postParse && config.postParse.length > 0) {
3240
+ current = executePhase(current, config.postParse, options);
3241
+ }
3242
+ return current;
3243
+ }
3244
+ function createIntermediateCall(toolName, rawSegment, schema) {
3245
+ return {
3246
+ toolName,
3247
+ schema,
3248
+ rawSegment,
3249
+ parsed: null,
3250
+ errors: [],
3251
+ meta: { originalContent: rawSegment }
3252
+ };
3253
+ }
3254
+
3255
+ // src/rxml/heuristics/xml-defaults.ts
3256
+ var MALFORMED_CLOSE_RE_G = /<\/\s+([A-Za-z0-9_:-]+)\s*>/g;
3257
+ var MALFORMED_CLOSE_RE = /<\/\s+([A-Za-z0-9_:-]+)\s*>/;
3258
+ var STATUS_TO_STEP_BOUNDARY_RE = /<\/status>\s*<step>/g;
3259
+ var WHITESPACE_REGEX3 = /\s/;
3260
+ var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
3261
+ var NAME_START_CHAR_RE = /[A-Za-z_:]/;
3262
+ var STEP_TAG_RE = /<step>([\s\S]*?)<\/step>/i;
3263
+ var STATUS_TAG_RE = /<status>([\s\S]*?)<\/status>/i;
3264
+ var normalizeCloseTagsHeuristic = {
3265
+ id: "normalize-close-tags",
3266
+ phase: "pre-parse",
3267
+ applies: () => true,
3268
+ run: (ctx) => {
3269
+ const normalized = ctx.rawSegment.replace(MALFORMED_CLOSE_RE_G, "</$1>");
3270
+ if (normalized !== ctx.rawSegment) {
3271
+ return { rawSegment: normalized };
3272
+ }
3273
+ return {};
3274
+ }
3275
+ };
3276
+ var escapeInvalidLtHeuristic = {
3277
+ id: "escape-invalid-lt",
3278
+ phase: "pre-parse",
3279
+ applies: () => true,
3280
+ run: (ctx) => {
3281
+ const escaped = escapeInvalidLt(ctx.rawSegment);
3282
+ if (escaped !== ctx.rawSegment) {
3283
+ return { rawSegment: escaped };
3284
+ }
3285
+ return {};
3286
+ }
3287
+ };
3288
+ var balanceTagsHeuristic = {
3289
+ id: "balance-tags",
3290
+ phase: "fallback-reparse",
3291
+ applies: (ctx) => {
3292
+ var _a;
3293
+ const original = ((_a = ctx.meta) == null ? void 0 : _a.originalContent) || ctx.rawSegment;
3294
+ const normalized = original.replace(MALFORMED_CLOSE_RE_G, "</$1>");
3295
+ const balanced = balanceTags(original);
3296
+ const hasMalformedClose = MALFORMED_CLOSE_RE.test(original);
3297
+ if (!hasMalformedClose && balanced.length > normalized.length && ctx.errors.length === 0) {
3298
+ return false;
3299
+ }
3300
+ return balanced !== normalized;
3301
+ },
3302
+ run: (ctx) => {
3303
+ var _a;
3304
+ const original = ((_a = ctx.meta) == null ? void 0 : _a.originalContent) || ctx.rawSegment;
3305
+ const balanced = balanceTags(original);
3306
+ const escaped = escapeInvalidLt(balanced);
3307
+ return { rawSegment: escaped, reparse: true };
3308
+ }
3309
+ };
3310
+ var dedupeShellStringTagsHeuristic = {
3311
+ id: "dedupe-shell-string-tags",
3312
+ phase: "fallback-reparse",
3313
+ applies: (ctx) => shouldDeduplicateStringTags(ctx.schema),
3314
+ run: (ctx) => {
3315
+ const names = getStringPropertyNames(ctx.schema);
3316
+ let deduped = ctx.rawSegment;
3317
+ for (const key of names) {
3318
+ deduped = dedupeSingleTag(deduped, key);
3319
+ }
3320
+ if (deduped !== ctx.rawSegment) {
3321
+ return { rawSegment: deduped, reparse: true };
3322
+ }
3323
+ return {};
3324
+ }
3325
+ };
3326
+ var repairAgainstSchemaHeuristic = {
3327
+ id: "repair-against-schema",
3328
+ phase: "post-parse",
3329
+ applies: (ctx) => ctx.parsed !== null && typeof ctx.parsed === "object",
3330
+ run: (ctx) => {
3331
+ const repaired = repairParsedAgainstSchema(ctx.parsed, ctx.schema);
3332
+ if (repaired !== ctx.parsed) {
3333
+ return { parsed: repaired };
3334
+ }
3335
+ return {};
3336
+ }
3337
+ };
3338
+ var defaultPipelineConfig = {
3339
+ preParse: [normalizeCloseTagsHeuristic, escapeInvalidLtHeuristic],
3340
+ fallbackReparse: [balanceTagsHeuristic, dedupeShellStringTagsHeuristic],
3341
+ postParse: [repairAgainstSchemaHeuristic]
3342
+ };
3343
+ var INDEX_TAG_RE = /^<(\d+)(?:>|\/?>)/;
3344
+ function isIndexTagAt(xml, pos) {
3345
+ const remaining = xml.slice(pos);
3346
+ return INDEX_TAG_RE.test(remaining);
3347
+ }
3348
+ function escapeInvalidLt(xml) {
3349
+ const len = xml.length;
3350
+ let out = "";
3351
+ for (let i = 0; i < len; i += 1) {
3352
+ const ch = xml[i];
3353
+ if (ch === "<") {
3354
+ const next = i + 1 < len ? xml[i + 1] : "";
3355
+ const isValidStart = NAME_START_CHAR_RE.test(next) || next === "/" || next === "!" || next === "?";
3356
+ const isIndexTag = !isValidStart && isIndexTagAt(xml, i);
3357
+ if (!(isValidStart || isIndexTag)) {
3358
+ out += "&lt;";
3359
+ continue;
3360
+ }
3361
+ }
3362
+ out += ch;
3363
+ }
3364
+ return out;
3365
+ }
3366
+ function balanceTags(xml) {
3367
+ const src = xml.replace(MALFORMED_CLOSE_RE_G, "</$1>").replace(STATUS_TO_STEP_BOUNDARY_RE, "</status></step><step>");
3368
+ let i = 0;
3369
+ const len = src.length;
3370
+ const out = [];
3371
+ const stack = [];
3372
+ while (i < len) {
3373
+ const lt = src.indexOf("<", i);
3374
+ if (lt === -1) {
3375
+ out.push(src.slice(i));
3376
+ break;
3377
+ }
3378
+ out.push(src.slice(i, lt));
3379
+ if (lt + 1 >= len) {
3380
+ break;
3381
+ }
3382
+ const next = src[lt + 1];
3383
+ if (next === "!" || next === "?") {
3384
+ i = handleSpecialTagSegment(src, lt, out);
3385
+ continue;
3386
+ }
3387
+ if (next === "/") {
3388
+ i = handleClosingTagSegment(src, lt, out, stack);
3389
+ continue;
3390
+ }
3391
+ i = handleOpeningTagSegment(src, lt, out, stack);
3392
+ }
3393
+ for (let k = stack.length - 1; k >= 0; k -= 1) {
3394
+ out.push(`</${stack[k]}>`);
3395
+ }
3396
+ return out.join("");
3397
+ }
3398
+ function skipWs(s, p, len) {
3399
+ let idx = p;
3400
+ while (idx < len && WHITESPACE_REGEX3.test(s[idx])) {
3401
+ idx += 1;
3402
+ }
3403
+ return idx;
3404
+ }
3405
+ function parseTagNameAt(s, p, len) {
3406
+ let idx = p;
3407
+ const start = idx;
3408
+ while (idx < len && NAME_CHAR_RE.test(s[idx])) {
3409
+ idx += 1;
3410
+ }
3411
+ return { name: s.slice(start, idx), pos: idx };
3412
+ }
3413
+ function handleSpecialTagSegment(src, lt, out) {
3414
+ const gt = src.indexOf(">", lt + 1);
3415
+ if (gt === -1) {
3416
+ out.push(src.slice(lt));
3417
+ return src.length;
3418
+ }
3419
+ out.push(src.slice(lt, gt + 1));
3420
+ return gt + 1;
3421
+ }
3422
+ function handleClosingTagSegment(src, lt, out, stack) {
3423
+ const len = src.length;
3424
+ let p = skipWs(src, lt + 2, len);
3425
+ const { name, pos } = parseTagNameAt(src, p, len);
3426
+ p = pos;
3427
+ const gt = src.indexOf(">", p);
3428
+ const closingText = gt === -1 ? src.slice(lt) : src.slice(lt, gt + 1);
3429
+ const idx = stack.lastIndexOf(name);
3430
+ if (idx !== -1) {
3431
+ for (let k = stack.length - 1; k > idx; k -= 1) {
3432
+ out.push(`</${stack[k]}>`);
3433
+ stack.pop();
3434
+ }
3435
+ out.push(closingText);
3436
+ stack.pop();
3437
+ }
3438
+ return gt === -1 ? len : gt + 1;
3439
+ }
3440
+ function handleOpeningTagSegment(src, lt, out, stack) {
3441
+ const len = src.length;
3442
+ let p = skipWs(src, lt + 1, len);
3443
+ const nameStart = p;
3444
+ const parsed = parseTagNameAt(src, p, len);
3445
+ p = parsed.pos;
3446
+ const name = src.slice(nameStart, p);
3447
+ const q = src.indexOf(">", p);
3448
+ if (q === -1) {
3449
+ out.push(src.slice(lt));
3450
+ return len;
3451
+ }
3452
+ let r = q - 1;
3453
+ while (r >= nameStart && WHITESPACE_REGEX3.test(src[r])) {
3454
+ r -= 1;
3455
+ }
3456
+ const selfClosing = src[r] === "/";
3457
+ out.push(src.slice(lt, q + 1));
3458
+ if (!selfClosing && name) {
3459
+ stack.push(name);
3460
+ }
3461
+ return q + 1;
3462
+ }
3463
+ function extractSchemaProperties(schema) {
3464
+ const unwrapped = unwrapJsonSchema(schema);
3465
+ if (!unwrapped || typeof unwrapped !== "object") {
3466
+ return void 0;
3467
+ }
3468
+ return unwrapped.properties;
3469
+ }
3470
+ function shouldDeduplicateStringTags(schema) {
3471
+ const props = extractSchemaProperties(schema);
3472
+ if (!props) {
3473
+ return false;
3474
+ }
3475
+ const commandRaw = props.command;
3476
+ if (!commandRaw) {
3477
+ return false;
3478
+ }
3479
+ const command = unwrapJsonSchema(commandRaw);
3480
+ return (command == null ? void 0 : command.type) === "array";
3481
+ }
3482
+ function getStringPropertyNames(schema) {
3483
+ const props = extractSchemaProperties(schema);
3484
+ if (!props) {
3485
+ return [];
3486
+ }
3487
+ const names = [];
3488
+ for (const key of Object.keys(props)) {
3489
+ const prop = unwrapJsonSchema(props[key]);
3490
+ if ((prop == null ? void 0 : prop.type) === "string") {
3491
+ names.push(key);
3492
+ }
3493
+ }
3494
+ return names;
3495
+ }
3496
+ function escapeRegExp2(s) {
3497
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3498
+ }
3499
+ function dedupeSingleTag(xml, key) {
3500
+ var _a, _b;
3501
+ const escaped = escapeRegExp2(key);
3502
+ const re = new RegExp(`<${escaped}>([\\s\\S]*?)<\\/${escaped}>`, "g");
3503
+ const matches = Array.from(xml.matchAll(re));
3504
+ if (matches.length <= 1) {
3505
+ return xml;
3506
+ }
3507
+ const last = matches.at(-1);
3508
+ let result = "";
3509
+ let cursor = 0;
3510
+ for (const m of matches) {
3511
+ const idx = (_a = m.index) != null ? _a : 0;
3512
+ result += xml.slice(cursor, idx);
3513
+ if (last && idx === ((_b = last.index) != null ? _b : -1)) {
3514
+ result += m[0];
3515
+ }
3516
+ cursor = idx + m[0].length;
3517
+ }
3518
+ result += xml.slice(cursor);
3519
+ return result;
3520
+ }
3521
+ function repairParsedAgainstSchema(input, schema) {
3522
+ if (!input || typeof input !== "object") {
3523
+ return input;
3524
+ }
3525
+ const properties = extractSchemaProperties(schema);
3526
+ if (!properties) {
3527
+ return input;
3528
+ }
3529
+ applySchemaProps(input, properties);
3530
+ return input;
3531
+ }
3532
+ function applySchemaProps(obj, properties) {
3533
+ for (const key of Object.keys(obj)) {
3534
+ const propSchema = properties[key];
3535
+ if (!propSchema) {
3536
+ continue;
521
3537
  }
522
- if (currentIndex < text.length) {
523
- const remainingText = text.substring(currentIndex);
524
- addTextSegment(remainingText, processedElements);
3538
+ const prop = unwrapJsonSchema(propSchema);
3539
+ if ((prop == null ? void 0 : prop.type) === "array" && prop.items) {
3540
+ const itemSchema = unwrapJsonSchema(prop.items);
3541
+ obj[key] = coerceArrayItems(obj[key], itemSchema);
3542
+ continue;
525
3543
  }
526
- return processedElements;
527
- },
528
- createStreamParser({
529
- options
530
- }) {
531
- const state = {
532
- isInsideToolCall: false,
533
- buffer: "",
534
- currentToolCallJson: "",
535
- currentTextId: null,
536
- hasEmittedTextStart: false
537
- };
538
- return new TransformStream({
539
- transform(chunk, controller) {
540
- var _a;
541
- if (chunk.type === "finish") {
542
- handleFinishChunk(state, controller, toolCallStart, chunk);
543
- return;
544
- }
545
- if (chunk.type !== "text-delta") {
546
- controller.enqueue(chunk);
547
- return;
548
- }
549
- const textContent = (_a = chunk.delta) != null ? _a : "";
550
- state.buffer += textContent;
551
- processBufferTags({
552
- state,
553
- controller,
554
- toolCallStart,
555
- toolCallEnd,
556
- options
557
- });
558
- handlePartialTag(state, controller, toolCallStart);
3544
+ if ((prop == null ? void 0 : prop.type) === "object") {
3545
+ const val = obj[key];
3546
+ if (val && typeof val === "object") {
3547
+ obj[key] = repairParsedAgainstSchema(val, prop);
559
3548
  }
560
- });
561
- },
562
- extractToolCallSegments({ text }) {
563
- const startEsc = escapeRegExp(toolCallStart);
564
- const endEsc = escapeRegExp(toolCallEnd);
565
- const regex = new RegExp(`${startEsc}([\0-\uFFFF]*?)${endEsc}`, "gs");
566
- const segments = [];
567
- let m = regex.exec(text);
568
- while (m != null) {
569
- segments.push(m[0]);
570
- m = regex.exec(text);
571
3549
  }
572
- return segments;
573
3550
  }
574
- });
575
-
576
- // src/core/protocols/protocol-interface.ts
577
- function isProtocolFactory(protocol) {
578
- return typeof protocol === "function";
579
3551
  }
580
- function isTCMProtocolFactory(protocol) {
581
- return typeof protocol === "function";
3552
+ function coerceArrayItems(val, itemSchema) {
3553
+ if (!Array.isArray(val)) {
3554
+ return val;
3555
+ }
3556
+ return val.map((v) => coerceArrayItem(v, itemSchema));
3557
+ }
3558
+ function coerceArrayItem(v, itemSchema) {
3559
+ const itemType = itemSchema == null ? void 0 : itemSchema.type;
3560
+ if (typeof v === "string" && itemType === "object") {
3561
+ const parsed = tryParseStringToSchemaObject(v, itemSchema);
3562
+ if (parsed !== null) {
3563
+ return parsed;
3564
+ }
3565
+ const fallback = extractStepStatusFromString(
3566
+ v.replace(MALFORMED_CLOSE_RE_G, "</$1>")
3567
+ );
3568
+ if (fallback) {
3569
+ return fallback;
3570
+ }
3571
+ return v;
3572
+ }
3573
+ if (v && typeof v === "object" && itemType === "object") {
3574
+ return repairParsedAgainstSchema(v, itemSchema);
3575
+ }
3576
+ return v;
3577
+ }
3578
+ function tryParseStringToSchemaObject(xml, itemSchema) {
3579
+ try {
3580
+ const normalized = xml.replace(MALFORMED_CLOSE_RE_G, "</$1>");
3581
+ const fixed = parse2(normalized, itemSchema, { noChildNodes: [] });
3582
+ return typeof fixed === "string" ? null : fixed;
3583
+ } catch (e) {
3584
+ return null;
3585
+ }
3586
+ }
3587
+ function extractStepStatusFromString(normXml) {
3588
+ const stepMatch = normXml.match(STEP_TAG_RE);
3589
+ const statusMatch = normXml.match(STATUS_TAG_RE);
3590
+ if (stepMatch && statusMatch) {
3591
+ return { step: stepMatch[1], status: statusMatch[1] };
3592
+ }
3593
+ return null;
582
3594
  }
583
3595
 
584
- // src/core/protocols/xml-protocol.ts
585
- var import_rxml = require("@ai-sdk-tool/rxml");
586
- var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
587
- var WHITESPACE_REGEX = /\s/;
588
- var REGEX_ESCAPE_RE = /[.*+?^${}()|[\]\\]/g;
589
- function escapeRegExp2(value) {
590
- return value.replace(REGEX_ESCAPE_RE, "\\$&");
3596
+ // src/rxml/parse.ts
3597
+ function parse3(xml, schema, options = {}) {
3598
+ if (!options.repair) {
3599
+ return parse2(xml, schema, options);
3600
+ }
3601
+ const baseOptions = {
3602
+ ...options,
3603
+ repair: false
3604
+ };
3605
+ const ctx = createIntermediateCall("", xml, schema);
3606
+ const result = applyHeuristicPipeline(ctx, defaultPipelineConfig, {
3607
+ parse: (raw, s) => parse2(raw, s, baseOptions),
3608
+ onError: options.onError,
3609
+ maxReparses: options.maxReparses
3610
+ });
3611
+ if (result.parsed !== null) {
3612
+ return result.parsed;
3613
+ }
3614
+ const error = result.errors[0];
3615
+ throw new RXMLParseError("Failed to parse XML with repair heuristics", error);
591
3616
  }
3617
+
3618
+ // src/core/protocols/xml-protocol.ts
3619
+ var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
3620
+ var WHITESPACE_REGEX4 = /\s/;
592
3621
  function getToolSchema(tools, toolName) {
593
3622
  var _a;
594
3623
  return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
@@ -602,7 +3631,7 @@ function processToolCall(params) {
602
3631
  onError: (_a = options == null ? void 0 : options.onError) != null ? _a : parseOptions == null ? void 0 : parseOptions.onError
603
3632
  };
604
3633
  try {
605
- const parsed = (0, import_rxml.parse)(toolCall.content, toolSchema, parseConfig);
3634
+ const parsed = parse3(toolCall.content, toolSchema, parseConfig);
606
3635
  processedElements.push({
607
3636
  type: "tool-call",
608
3637
  toolCallId: generateId(),
@@ -640,7 +3669,7 @@ function handleStreamingToolCallEnd(params) {
640
3669
  };
641
3670
  flushText(ctrl);
642
3671
  try {
643
- const parsedResult = (0, import_rxml.parse)(toolContent, toolSchema, parseConfig);
3672
+ const parsedResult = parse3(toolContent, toolSchema, parseConfig);
644
3673
  ctrl.enqueue({
645
3674
  type: "tool-call",
646
3675
  toolCallId: generateId(),
@@ -690,11 +3719,11 @@ function consumeClosingTag(text, lt) {
690
3719
  }
691
3720
  function consumeOpenTag(text, lt) {
692
3721
  let p = lt + 1;
693
- while (p < text.length && WHITESPACE_REGEX.test(text[p])) {
3722
+ while (p < text.length && WHITESPACE_REGEX4.test(text[p])) {
694
3723
  p += 1;
695
3724
  }
696
3725
  const nameStart = p;
697
- while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
3726
+ while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
698
3727
  p += 1;
699
3728
  }
700
3729
  const name = text.slice(nameStart, p);
@@ -703,7 +3732,7 @@ function consumeOpenTag(text, lt) {
703
3732
  return null;
704
3733
  }
705
3734
  let r = q - 1;
706
- while (r >= nameStart && WHITESPACE_REGEX.test(text[r])) {
3735
+ while (r >= nameStart && WHITESPACE_REGEX4.test(text[r])) {
707
3736
  r -= 1;
708
3737
  }
709
3738
  const selfClosing = text[r] === "/";
@@ -732,11 +3761,11 @@ function nextTagToken(text, fromPos) {
732
3761
  if (next === "/") {
733
3762
  const closing = consumeClosingTag(text, lt);
734
3763
  let p = lt + 2;
735
- while (p < text.length && WHITESPACE_REGEX.test(text[p])) {
3764
+ while (p < text.length && WHITESPACE_REGEX4.test(text[p])) {
736
3765
  p += 1;
737
3766
  }
738
3767
  const nameStart = p;
739
- while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
3768
+ while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
740
3769
  p += 1;
741
3770
  }
742
3771
  const name = text.slice(nameStart, p);
@@ -753,21 +3782,25 @@ function nextTagToken(text, fromPos) {
753
3782
  nextPos: open.nextPos
754
3783
  };
755
3784
  }
756
- function findNextToolTag(text, searchIndex, startTag, selfTag) {
3785
+ function findNextToolTag(text, searchIndex, toolName) {
3786
+ var _a, _b;
3787
+ const startTag = `<${toolName}>`;
757
3788
  const openIdx = text.indexOf(startTag, searchIndex);
758
- const selfIdx = text.indexOf(selfTag, searchIndex);
3789
+ const selfMatch = findSelfClosingTag(text, toolName, searchIndex);
3790
+ const selfIdx = (_a = selfMatch == null ? void 0 : selfMatch.index) != null ? _a : -1;
759
3791
  if (openIdx === -1 && selfIdx === -1) {
760
3792
  return null;
761
3793
  }
762
3794
  const isSelfClosing = selfIdx !== -1 && (openIdx === -1 || selfIdx < openIdx);
763
3795
  return {
764
3796
  tagStart: isSelfClosing ? selfIdx : openIdx,
765
- isSelfClosing
3797
+ isSelfClosing,
3798
+ tagLength: isSelfClosing ? (_b = selfMatch == null ? void 0 : selfMatch.length) != null ? _b : 0 : startTag.length
766
3799
  };
767
3800
  }
768
3801
  function findLastCloseTagStart(segment, toolName) {
769
3802
  const closeTagPattern = new RegExp(
770
- `</\\s*${escapeRegExp2(toolName)}\\s*>`,
3803
+ `</\\s*${escapeRegExp(toolName)}\\s*>`,
771
3804
  "g"
772
3805
  );
773
3806
  let closeTagStart = -1;
@@ -781,8 +3814,8 @@ function findLastCloseTagStart(segment, toolName) {
781
3814
  }
782
3815
  return closeTagStart;
783
3816
  }
784
- function pushSelfClosingToolCall(toolCalls, toolName, text, tagStart, selfTag) {
785
- const endIndex = tagStart + selfTag.length;
3817
+ function pushSelfClosingToolCall(toolCalls, toolName, text, tagStart, tagLength) {
3818
+ const endIndex = tagStart + tagLength;
786
3819
  toolCalls.push({
787
3820
  toolName,
788
3821
  startIndex: tagStart,
@@ -792,6 +3825,24 @@ function pushSelfClosingToolCall(toolCalls, toolName, text, tagStart, selfTag) {
792
3825
  });
793
3826
  return endIndex;
794
3827
  }
3828
+ var selfClosingTagCache = /* @__PURE__ */ new Map();
3829
+ function getSelfClosingTagPattern(toolName) {
3830
+ let pattern = selfClosingTagCache.get(toolName);
3831
+ if (!pattern) {
3832
+ pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
3833
+ selfClosingTagCache.set(toolName, pattern);
3834
+ }
3835
+ return pattern;
3836
+ }
3837
+ function findSelfClosingTag(text, toolName, fromIndex) {
3838
+ const pattern = getSelfClosingTagPattern(toolName);
3839
+ pattern.lastIndex = fromIndex;
3840
+ const match = pattern.exec(text);
3841
+ if (!match || match.index === void 0) {
3842
+ return null;
3843
+ }
3844
+ return { index: match.index, length: match[0].length };
3845
+ }
795
3846
  function appendOpenToolCallIfComplete(toolCalls, text, toolName, tagStart, startTag) {
796
3847
  const contentStart = tagStart + startTag.length;
797
3848
  const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
@@ -813,10 +3864,9 @@ function appendOpenToolCallIfComplete(toolCalls, text, toolName, tagStart, start
813
3864
  function findToolCallsForName(text, toolName) {
814
3865
  const toolCalls = [];
815
3866
  const startTag = `<${toolName}>`;
816
- const selfTag = `<${toolName}/>`;
817
3867
  let searchIndex = 0;
818
3868
  while (searchIndex < text.length) {
819
- const match = findNextToolTag(text, searchIndex, startTag, selfTag);
3869
+ const match = findNextToolTag(text, searchIndex, toolName);
820
3870
  if (match === null) {
821
3871
  break;
822
3872
  }
@@ -826,7 +3876,7 @@ function findToolCallsForName(text, toolName) {
826
3876
  toolName,
827
3877
  text,
828
3878
  match.tagStart,
829
- selfTag
3879
+ match.tagLength
830
3880
  );
831
3881
  continue;
832
3882
  }
@@ -849,28 +3899,114 @@ function findToolCalls(text, toolNames) {
849
3899
  return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
850
3900
  }
851
3901
  function findEarliestToolTag(buffer, toolNames) {
3902
+ var _a, _b;
852
3903
  let bestIndex = -1;
853
3904
  let bestName = "";
854
3905
  let bestSelfClosing = false;
3906
+ let bestTagLength = 0;
855
3907
  if (toolNames.length > 0) {
856
3908
  for (const name of toolNames) {
857
3909
  const openTag = `<${name}>`;
858
- const selfTag = `<${name}/>`;
859
3910
  const idxOpen = buffer.indexOf(openTag);
860
- const idxSelf = buffer.indexOf(selfTag);
3911
+ const selfMatch = findSelfClosingTag(buffer, name, 0);
3912
+ const idxSelf = (_a = selfMatch == null ? void 0 : selfMatch.index) != null ? _a : -1;
861
3913
  if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
862
3914
  bestIndex = idxOpen;
863
3915
  bestName = name;
864
3916
  bestSelfClosing = false;
3917
+ bestTagLength = openTag.length;
865
3918
  }
866
3919
  if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
867
3920
  bestIndex = idxSelf;
868
3921
  bestName = name;
869
3922
  bestSelfClosing = true;
3923
+ bestTagLength = (_b = selfMatch == null ? void 0 : selfMatch.length) != null ? _b : 0;
3924
+ }
3925
+ }
3926
+ }
3927
+ return {
3928
+ index: bestIndex,
3929
+ name: bestName,
3930
+ selfClosing: bestSelfClosing,
3931
+ tagLength: bestTagLength
3932
+ };
3933
+ }
3934
+ function isOpenTagPrefix(suffix, toolName) {
3935
+ return `${toolName}>`.startsWith(suffix);
3936
+ }
3937
+ function consumeWhitespace(text, index) {
3938
+ let i = index;
3939
+ while (i < text.length && WHITESPACE_REGEX4.test(text.charAt(i))) {
3940
+ i += 1;
3941
+ }
3942
+ return i;
3943
+ }
3944
+ function consumeToolNamePrefix(text, index, toolName) {
3945
+ let i = index;
3946
+ let nameIndex = 0;
3947
+ while (i < text.length && nameIndex < toolName.length) {
3948
+ if (text.charAt(i) !== toolName.charAt(nameIndex)) {
3949
+ return { index: i, done: false, valid: false };
3950
+ }
3951
+ i += 1;
3952
+ nameIndex += 1;
3953
+ }
3954
+ return { index: i, done: nameIndex === toolName.length, valid: true };
3955
+ }
3956
+ function isSelfClosingSuffixRemainder(text, index) {
3957
+ if (text.charAt(index) !== "/") {
3958
+ return false;
3959
+ }
3960
+ if (index + 1 >= text.length) {
3961
+ return true;
3962
+ }
3963
+ return index + 1 === text.length - 1 && text.charAt(index + 1) === ">";
3964
+ }
3965
+ function isSelfClosingTagPrefix(suffix, toolName) {
3966
+ let i = consumeWhitespace(suffix, 0);
3967
+ if (i >= suffix.length) {
3968
+ return true;
3969
+ }
3970
+ const nameRemainder = suffix.slice(i);
3971
+ if (toolName.startsWith(nameRemainder)) {
3972
+ return true;
3973
+ }
3974
+ const nameResult = consumeToolNamePrefix(suffix, i, toolName);
3975
+ if (!nameResult.valid) {
3976
+ return false;
3977
+ }
3978
+ i = nameResult.index;
3979
+ if (i >= suffix.length) {
3980
+ return true;
3981
+ }
3982
+ if (!nameResult.done) {
3983
+ return false;
3984
+ }
3985
+ i = consumeWhitespace(suffix, i);
3986
+ if (i >= suffix.length) {
3987
+ return true;
3988
+ }
3989
+ return isSelfClosingSuffixRemainder(suffix, i);
3990
+ }
3991
+ function findPotentialToolTagStart(buffer, toolNames) {
3992
+ if (toolNames.length === 0 || buffer.length === 0) {
3993
+ return -1;
3994
+ }
3995
+ const lastGt = buffer.lastIndexOf(">");
3996
+ const offset = lastGt === -1 ? 0 : lastGt + 1;
3997
+ const trailing = buffer.slice(offset);
3998
+ for (let i = trailing.length - 1; i >= 0; i -= 1) {
3999
+ if (trailing.charAt(i) !== "<") {
4000
+ continue;
4001
+ }
4002
+ const suffix = trailing.slice(i + 1);
4003
+ for (const name of toolNames) {
4004
+ if (isOpenTagPrefix(suffix, name) || isSelfClosingTagPrefix(suffix, name)) {
4005
+ return offset + i;
870
4006
  }
871
4007
  }
872
4008
  }
873
- return { index: bestIndex, name: bestName, selfClosing: bestSelfClosing };
4009
+ return -1;
874
4010
  }
875
4011
  function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
876
4012
  return (controller, text) => {
@@ -916,7 +4052,7 @@ function processToolCallInBuffer(params) {
916
4052
  parseOptions
917
4053
  } = params;
918
4054
  const endTagPattern = new RegExp(
919
- `</\\s*${escapeRegExp2(currentToolCall.name)}\\s*>`
4055
+ `</\\s*${escapeRegExp(currentToolCall.name)}\\s*>`
920
4056
  );
921
4057
  const endMatch = endTagPattern.exec(buffer);
922
4058
  if (!endMatch || endMatch.index === void 0) {
@@ -956,18 +4092,22 @@ function processNoToolCallInBuffer(params) {
956
4092
  const {
957
4093
  index: earliestStartTagIndex,
958
4094
  name: earliestToolName,
959
- selfClosing
4095
+ selfClosing,
4096
+ tagLength
960
4097
  } = findEarliestToolTag(buffer, toolNames);
961
4098
  if (earliestStartTagIndex === -1) {
962
- const maxTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n}>`.length)) : 0;
963
- const tail = Math.max(0, maxTagLen - 1);
964
- const safeLen = Math.max(0, buffer.length - tail);
4099
+ const potentialStart = findPotentialToolTagStart(buffer, toolNames);
4100
+ const safeLen = Math.max(
4101
+ 0,
4102
+ potentialStart === -1 ? buffer.length : potentialStart
4103
+ );
4104
+ const remaining = buffer.slice(safeLen);
965
4105
  if (safeLen > 0) {
966
4106
  flushText(controller, buffer.slice(0, safeLen));
967
- setBuffer(buffer.slice(safeLen));
4107
+ setBuffer(remaining);
968
4108
  }
969
4109
  return {
970
- buffer: buffer.slice(safeLen),
4110
+ buffer: remaining,
971
4111
  currentToolCall: null,
972
4112
  shouldBreak: true,
973
4113
  shouldContinue: false
@@ -975,8 +4115,7 @@ function processNoToolCallInBuffer(params) {
975
4115
  }
976
4116
  flushText(controller, buffer.substring(0, earliestStartTagIndex));
977
4117
  if (selfClosing) {
978
- const selfTag = `<${earliestToolName}/>`;
979
- const newBuffer2 = buffer.substring(earliestStartTagIndex + selfTag.length);
4118
+ const newBuffer2 = buffer.substring(earliestStartTagIndex + tagLength);
980
4119
  setBuffer(newBuffer2);
981
4120
  handleStreamingToolCallEnd({
982
4121
  toolContent: "",
@@ -1068,7 +4207,7 @@ var xmlProtocol = (protocolOptions) => {
1068
4207
  args = toolCall.input;
1069
4208
  }
1070
4209
  }
1071
- return (0, import_rxml.stringify)(toolCall.toolName, args, {
4210
+ return stringify(toolCall.toolName, args, {
1072
4211
  suppressEmptyNode: false,
1073
4212
  format: true,
1074
4213
  minimalEscaping: true
@@ -1186,8 +4325,8 @@ var xmlProtocol = (protocolOptions) => {
1186
4325
 
1187
4326
  // src/core/protocols/yaml-protocol.ts
1188
4327
  var import_yaml = __toESM(require("yaml"), 1);
1189
- var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
1190
- var WHITESPACE_REGEX2 = /\s/;
4328
+ var NAME_CHAR_RE3 = /[A-Za-z0-9_:-]/;
4329
+ var WHITESPACE_REGEX5 = /\s/;
1191
4330
  var LEADING_WHITESPACE_RE = /^(\s*)/;
1192
4331
  function findClosingTagEnd(text, contentStart, toolName) {
1193
4332
  let pos = contentStart;
@@ -1204,11 +4343,11 @@ function findClosingTagEnd(text, contentStart, toolName) {
1204
4343
  break;
1205
4344
  }
1206
4345
  let p = ltIdx + 2;
1207
- while (p < gtIdx && WHITESPACE_REGEX2.test(text[p])) {
4346
+ while (p < gtIdx && WHITESPACE_REGEX5.test(text[p])) {
1208
4347
  p++;
1209
4348
  }
1210
4349
  const nameStart = p;
1211
- while (p < gtIdx && NAME_CHAR_RE2.test(text.charAt(p))) {
4350
+ while (p < gtIdx && NAME_CHAR_RE3.test(text.charAt(p))) {
1212
4351
  p++;
1213
4352
  }
1214
4353
  const name = text.slice(nameStart, p);
@@ -1224,11 +4363,11 @@ function findClosingTagEnd(text, contentStart, toolName) {
1224
4363
  pos = gtIdx === -1 ? text.length : gtIdx + 1;
1225
4364
  } else {
1226
4365
  let p = ltIdx + 1;
1227
- while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
4366
+ while (p < text.length && WHITESPACE_REGEX5.test(text[p])) {
1228
4367
  p++;
1229
4368
  }
1230
4369
  const nameStart = p;
1231
- while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
4370
+ while (p < text.length && NAME_CHAR_RE3.test(text.charAt(p))) {
1232
4371
  p++;
1233
4372
  }
1234
4373
  const name = text.slice(nameStart, p);
@@ -1237,7 +4376,7 @@ function findClosingTagEnd(text, contentStart, toolName) {
1237
4376
  break;
1238
4377
  }
1239
4378
  let r = gtIdx - 1;
1240
- while (r >= nameStart && WHITESPACE_REGEX2.test(text[r])) {
4379
+ while (r >= nameStart && WHITESPACE_REGEX5.test(text[r])) {
1241
4380
  r--;
1242
4381
  }
1243
4382
  const selfClosing = text[r] === "/";
@@ -1719,30 +4858,14 @@ function decodeOriginalTools(originalTools) {
1719
4858
  })
1720
4859
  );
1721
4860
  }
1722
- function extractToolNamesFromOriginalTools(originalTools) {
1723
- return (originalTools == null ? void 0 : originalTools.map((t) => t.name)) || [];
1724
- }
1725
4861
  function isToolChoiceActive(params) {
1726
4862
  var _a, _b, _c;
1727
4863
  const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
1728
4864
  return !!(typeof params.providerOptions === "object" && params.providerOptions !== null && typeof ((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) === "object" && toolChoice && typeof toolChoice === "object" && (toolChoice.type === "tool" || toolChoice.type === "required"));
1729
4865
  }
1730
4866
 
1731
- // src/core/utils/type-guards.ts
1732
- function isToolResultPart(content) {
1733
- if (!content || typeof content !== "object") {
1734
- return false;
1735
- }
1736
- const c = content;
1737
- return c.type === "tool-result" && typeof c.toolName === "string" && typeof c.toolCallId === "string" && "output" in c;
1738
- }
1739
- function hasInputProperty(obj) {
1740
- return typeof obj === "object" && obj !== null && "input" in obj;
1741
- }
1742
-
1743
4867
  // src/generate-handler.ts
1744
4868
  var import_provider_utils = require("@ai-sdk/provider-utils");
1745
- var import_schema_coerce = require("@ai-sdk-tool/schema-coerce");
1746
4869
  function parseToolChoiceJson(text, providerOptions) {
1747
4870
  var _a;
1748
4871
  try {
@@ -1904,7 +5027,7 @@ function fixToolCallWithSchema(part, tools) {
1904
5027
  args = part.input;
1905
5028
  }
1906
5029
  const schema = (_a = tools.find((t) => t.name === part.toolName)) == null ? void 0 : _a.inputSchema;
1907
- const coerced = (0, import_schema_coerce.coerceBySchema)(args, schema);
5030
+ const coerced = coerceBySchema(args, schema);
1908
5031
  return {
1909
5032
  ...part,
1910
5033
  input: JSON.stringify(coerced != null ? coerced : {})
@@ -2037,29 +5160,230 @@ function formatXmlNode(tagName, value, depth) {
2037
5160
  }
2038
5161
 
2039
5162
  // src/core/prompts/xml-system-prompt.ts
5163
+ var import_dedent = __toESM(require("dedent"), 1);
2040
5164
  function xmlSystemPromptTemplate(tools) {
2041
- const toolsJson = JSON.stringify(tools);
2042
- return `# Tools
2043
-
2044
- You may call one or more functions to assist with the user query.
2045
-
2046
- You are provided with function signatures within <tools></tools> XML tags:
2047
- <tools>${toolsJson}</tools>
2048
-
2049
- # Rules
2050
- - Use exactly one XML element whose tag name is the function name.
2051
- - Put each parameter as a child element.
2052
- - Values must follow the schema exactly (numbers, arrays, objects, enums \u2192 copy as-is).
2053
- - Do not add or remove functions or parameters.
2054
- - Each required parameter must appear once.
2055
- - Output nothing before or after the function call.
2056
- - 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.
2057
-
2058
- # Example
2059
- <get_weather>
2060
- <location>New York</location>
2061
- <unit>celsius</unit>
2062
- </get_weather>`;
5165
+ const toolsText = renderToolsForXmlPrompt(tools);
5166
+ const header = import_dedent.default`
5167
+ # Tools
5168
+ You may call one or more functions to assist with the user query.
5169
+ `;
5170
+ const definitions = [
5171
+ "You have access to the following functions:",
5172
+ "<tools>",
5173
+ toolsText,
5174
+ "</tools>"
5175
+ ].join("\n");
5176
+ const rules = import_dedent.default`
5177
+ <rules>
5178
+ - Use exactly one XML element whose tag name is the function name.
5179
+ - Put each parameter as a child element.
5180
+ - Values must follow the schema exactly (numbers, arrays, objects, enums copy as-is).
5181
+ - Do not add or remove functions or parameters.
5182
+ - Each required parameter must appear once.
5183
+ - Output nothing before or after the function call.
5184
+ - It is also possible to call multiple types of functions in one turn or to call a single function multiple times.
5185
+ </rules>
5186
+ `;
5187
+ const examples = import_dedent.default`
5188
+ For each function call, output the function name and parameter in the following format:
5189
+ <example_function_name>
5190
+ <example_parameter_1>value_1</example_parameter_1>
5191
+ <example_parameter_2>This is the value for the second parameter
5192
+ that can span
5193
+ multiple lines</example_parameter_2>
5194
+ </example_function_name>
5195
+ `;
5196
+ return [header, definitions, rules, examples].join("\n\n");
5197
+ }
5198
+ var INDENT = " ";
5199
+ function renderToolsForXmlPrompt(tools) {
5200
+ if (!tools.length) {
5201
+ return "none";
5202
+ }
5203
+ return tools.map(renderToolForXmlPrompt).join("\n\n");
5204
+ }
5205
+ function renderToolForXmlPrompt(tool) {
5206
+ const lines = [`name: ${tool.name}`];
5207
+ if (tool.description) {
5208
+ lines.push(`description: ${tool.description}`);
5209
+ }
5210
+ lines.push("parameters:");
5211
+ const normalizedSchema = normalizeSchema(tool.inputSchema);
5212
+ lines.push(...renderParametersSummary(normalizedSchema, 1));
5213
+ lines.push(`schema: ${stringifySchema(normalizedSchema)}`);
5214
+ return lines.join("\n");
5215
+ }
5216
+ function normalizeSchema(schema) {
5217
+ if (typeof schema === "string") {
5218
+ try {
5219
+ return JSON.parse(schema);
5220
+ } catch (e) {
5221
+ return { type: "string", const: schema };
5222
+ }
5223
+ }
5224
+ return schema;
5225
+ }
5226
+ function renderParametersSummary(schema, indentLevel) {
5227
+ var _a, _b;
5228
+ const indent = INDENT.repeat(indentLevel);
5229
+ if (schema === void 0 || schema === null) {
5230
+ return [`${indent}(none)`];
5231
+ }
5232
+ if (schema === true) {
5233
+ return [`${indent}(any)`];
5234
+ }
5235
+ if (schema === false) {
5236
+ return [`${indent}(no valid parameters)`];
5237
+ }
5238
+ if (typeof schema !== "object") {
5239
+ return [`${indent}- value (${String(schema)})`];
5240
+ }
5241
+ const schemaType = [];
5242
+ if (Array.isArray(schema.type)) {
5243
+ schemaType.push(...schema.type);
5244
+ } else if (schema.type) {
5245
+ schemaType.push(schema.type);
5246
+ }
5247
+ const isObjectLike = schemaType.includes("object") || !!schema.properties;
5248
+ if (isObjectLike) {
5249
+ const properties = (_a = schema.properties) != null ? _a : {};
5250
+ const requiredSet = new Set((_b = schema.required) != null ? _b : []);
5251
+ const propertyNames = Object.keys(properties).sort();
5252
+ if (propertyNames.length === 0) {
5253
+ return [`${indent}(no named parameters)`];
5254
+ }
5255
+ const lines = [];
5256
+ for (const propName of propertyNames) {
5257
+ const propSchema = properties[propName];
5258
+ lines.push(
5259
+ renderPropertySummaryLine({
5260
+ indent,
5261
+ propName,
5262
+ propSchema,
5263
+ required: requiredSet.has(propName)
5264
+ })
5265
+ );
5266
+ }
5267
+ return lines.length ? lines : [`${indent}(no parameters)`];
5268
+ }
5269
+ return [`${indent}- value (${summarizeType(schema)})`];
5270
+ }
5271
+ function renderPropertySummaryLine({
5272
+ indent,
5273
+ propName,
5274
+ propSchema,
5275
+ required
5276
+ }) {
5277
+ const typeLabel = summarizeType(propSchema);
5278
+ const requiredLabel = required ? "required" : "optional";
5279
+ const extras = collectPropertyExtras(propSchema);
5280
+ const extraText = extras.length ? ` - ${extras.join("; ")}` : "";
5281
+ return `${indent}- ${propName} (${typeLabel}, ${requiredLabel})${extraText}`;
5282
+ }
5283
+ function collectPropertyExtras(propSchema) {
5284
+ if (!propSchema || typeof propSchema !== "object") {
5285
+ return [];
5286
+ }
5287
+ const extras = [];
5288
+ if (propSchema.enum) {
5289
+ extras.push(`enum: ${formatEnumForSummary(propSchema.enum)}`);
5290
+ }
5291
+ if (propSchema.default !== void 0) {
5292
+ extras.push(`default: ${formatValue(propSchema.default)}`);
5293
+ }
5294
+ if (propSchema.description) {
5295
+ extras.push(propSchema.description);
5296
+ }
5297
+ return extras;
5298
+ }
5299
+ function summarizeType(schema) {
5300
+ var _a;
5301
+ if (schema === void 0 || schema === null) {
5302
+ return "unknown";
5303
+ }
5304
+ if (schema === true) {
5305
+ return "any";
5306
+ }
5307
+ if (schema === false) {
5308
+ return "never";
5309
+ }
5310
+ if (typeof schema !== "object") {
5311
+ return String(schema);
5312
+ }
5313
+ const schemaType = schema.type;
5314
+ let baseType = "";
5315
+ if (Array.isArray(schemaType) && schemaType.length) {
5316
+ baseType = schemaType.join(" | ");
5317
+ } else if (typeof schemaType === "string") {
5318
+ baseType = schemaType;
5319
+ } else if (schema.enum) {
5320
+ const inferred = Array.from(
5321
+ new Set(schema.enum.map((value) => typeof value))
5322
+ );
5323
+ if (inferred.length === 1) {
5324
+ baseType = (_a = inferred[0]) != null ? _a : "";
5325
+ }
5326
+ } else if (schema.const !== void 0) {
5327
+ baseType = typeof schema.const;
5328
+ }
5329
+ if (!baseType) {
5330
+ baseType = "any";
5331
+ }
5332
+ if (baseType === "array" && schema.items) {
5333
+ const itemType = Array.isArray(schema.items) ? schema.items.map((item) => summarizeType(item)).join(" | ") : summarizeType(schema.items);
5334
+ return `array<${itemType}>`;
5335
+ }
5336
+ if (baseType === "string" && schema.format) {
5337
+ return `string (${schema.format})`;
5338
+ }
5339
+ return baseType;
5340
+ }
5341
+ var ENUM_MAX_INLINE = 6;
5342
+ var ENUM_PREVIEW_LIMIT = 5;
5343
+ function formatEnumForSummary(values) {
5344
+ if (values.length <= ENUM_MAX_INLINE) {
5345
+ return formatValue(values);
5346
+ }
5347
+ const preview = values.slice(0, ENUM_PREVIEW_LIMIT).map((value) => formatValue(value));
5348
+ return `[${preview.join(", ")}, ... (${values.length} total)]`;
5349
+ }
5350
+ function formatValue(value) {
5351
+ if (typeof value === "string") {
5352
+ return JSON.stringify(value);
5353
+ }
5354
+ if (typeof value === "number" || typeof value === "boolean") {
5355
+ return String(value);
5356
+ }
5357
+ if (value === null) {
5358
+ return "null";
5359
+ }
5360
+ if (Array.isArray(value)) {
5361
+ return `[${value.map(formatValue).join(", ")}]`;
5362
+ }
5363
+ return JSON.stringify(value);
5364
+ }
5365
+ function stringifySchema(schema) {
5366
+ if (schema === void 0) {
5367
+ return "null";
5368
+ }
5369
+ return JSON.stringify(stripSchemaKeys(schema));
5370
+ }
5371
+ function stripSchemaKeys(value) {
5372
+ if (Array.isArray(value)) {
5373
+ return value.map((entry) => stripSchemaKeys(entry));
5374
+ }
5375
+ if (value && typeof value === "object") {
5376
+ const record = value;
5377
+ const cleaned = {};
5378
+ for (const [key, entry] of Object.entries(record)) {
5379
+ if (key === "$schema") {
5380
+ continue;
5381
+ }
5382
+ cleaned[key] = stripSchemaKeys(entry);
5383
+ }
5384
+ return cleaned;
5385
+ }
5386
+ return value;
2063
5387
  }
2064
5388
 
2065
5389
  // src/core/prompts/yaml-system-prompt.ts