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