@ai-sdk-tool/parser 3.0.0-canary.3 → 3.0.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/dist/chunk-DFOXAWP6.js +1 -0
- package/dist/chunk-DFOXAWP6.js.map +1 -0
- package/dist/chunk-NOYHOQOL.js +2489 -0
- package/dist/chunk-NOYHOQOL.js.map +1 -0
- package/dist/chunk-QPJA5CS6.js +1289 -0
- package/dist/chunk-QPJA5CS6.js.map +1 -0
- package/dist/community.cjs +2665 -2513
- package/dist/community.cjs.map +1 -1
- package/dist/community.js +5 -2
- package/dist/community.js.map +1 -1
- package/dist/index.cjs +2690 -2504
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -132
- package/dist/index.d.ts +25 -132
- package/dist/index.js +19 -8
- package/dist/tool-call-protocol-Bn2CBcD-.d.cts +84 -0
- package/dist/tool-call-protocol-Bn2CBcD-.d.ts +84 -0
- package/dist/v5.cjs +2816 -0
- package/dist/v5.cjs.map +1 -0
- package/dist/v5.d.cts +14 -0
- package/dist/v5.d.ts +14 -0
- package/dist/v5.js +476 -0
- package/dist/v5.js.map +1 -0
- package/dist/{chunk-2B2YNKXY.js → v6.cjs} +1198 -1087
- package/dist/v6.cjs.map +1 -0
- package/dist/v6.d.cts +16 -0
- package/dist/v6.d.ts +16 -0
- package/dist/v6.js +16 -0
- package/dist/v6.js.map +1 -0
- package/package.json +23 -8
- package/dist/chunk-2B2YNKXY.js.map +0 -1
|
@@ -0,0 +1,2489 @@
|
|
|
1
|
+
// src/core/heuristics/engine.ts
|
|
2
|
+
function applyRawSegmentUpdate(current, result) {
|
|
3
|
+
if (result.rawSegment !== void 0) {
|
|
4
|
+
return { ...current, rawSegment: result.rawSegment };
|
|
5
|
+
}
|
|
6
|
+
return current;
|
|
7
|
+
}
|
|
8
|
+
function applyParsedUpdate(current, result) {
|
|
9
|
+
if (result.parsed !== void 0) {
|
|
10
|
+
return { ...current, parsed: result.parsed };
|
|
11
|
+
}
|
|
12
|
+
return current;
|
|
13
|
+
}
|
|
14
|
+
function applyWarningsUpdate(current, result) {
|
|
15
|
+
var _a, _b;
|
|
16
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
17
|
+
const meta = (_a = current.meta) != null ? _a : {};
|
|
18
|
+
const existingWarnings = (_b = meta.warnings) != null ? _b : [];
|
|
19
|
+
return {
|
|
20
|
+
...current,
|
|
21
|
+
meta: { ...meta, warnings: [...existingWarnings, ...result.warnings] }
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return current;
|
|
25
|
+
}
|
|
26
|
+
function attemptReparse(current, result, reparseCount, maxReparses, parse4) {
|
|
27
|
+
if (!result.reparse || result.rawSegment === void 0 || reparseCount >= maxReparses) {
|
|
28
|
+
return { state: current, newCount: reparseCount };
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const reparsed = parse4(result.rawSegment, current.schema);
|
|
32
|
+
return {
|
|
33
|
+
state: { ...current, parsed: reparsed, errors: [] },
|
|
34
|
+
newCount: reparseCount + 1
|
|
35
|
+
};
|
|
36
|
+
} catch (error) {
|
|
37
|
+
return {
|
|
38
|
+
state: { ...current, errors: [...current.errors, error] },
|
|
39
|
+
newCount: reparseCount + 1
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function executePhase(ctx, heuristics, options) {
|
|
44
|
+
var _a;
|
|
45
|
+
let current = ctx;
|
|
46
|
+
let reparseCount = 0;
|
|
47
|
+
const maxReparses = (_a = options.maxReparses) != null ? _a : 2;
|
|
48
|
+
for (const heuristic of heuristics) {
|
|
49
|
+
if (!heuristic.applies(current)) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const result = heuristic.run(current);
|
|
53
|
+
current = applyRawSegmentUpdate(current, result);
|
|
54
|
+
current = applyParsedUpdate(current, result);
|
|
55
|
+
current = applyWarningsUpdate(current, result);
|
|
56
|
+
const reparseResult = attemptReparse(
|
|
57
|
+
current,
|
|
58
|
+
result,
|
|
59
|
+
reparseCount,
|
|
60
|
+
maxReparses,
|
|
61
|
+
options.parse
|
|
62
|
+
);
|
|
63
|
+
current = reparseResult.state;
|
|
64
|
+
reparseCount = reparseResult.newCount;
|
|
65
|
+
if (result.stop) {
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return current;
|
|
70
|
+
}
|
|
71
|
+
function applyHeuristicPipeline(ctx, config, options) {
|
|
72
|
+
let current = ctx;
|
|
73
|
+
if (config.preParse && config.preParse.length > 0) {
|
|
74
|
+
current = executePhase(current, config.preParse, options);
|
|
75
|
+
}
|
|
76
|
+
if (current.parsed === null && current.errors.length === 0) {
|
|
77
|
+
try {
|
|
78
|
+
const parsed = options.parse(current.rawSegment, current.schema);
|
|
79
|
+
current = { ...current, parsed, errors: [] };
|
|
80
|
+
} catch (error) {
|
|
81
|
+
current = { ...current, errors: [error] };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (current.errors.length > 0 && config.fallbackReparse && config.fallbackReparse.length > 0) {
|
|
85
|
+
current = executePhase(current, config.fallbackReparse, options);
|
|
86
|
+
}
|
|
87
|
+
if (current.parsed !== null && config.postParse && config.postParse.length > 0) {
|
|
88
|
+
current = executePhase(current, config.postParse, options);
|
|
89
|
+
}
|
|
90
|
+
return current;
|
|
91
|
+
}
|
|
92
|
+
function createIntermediateCall(toolName, rawSegment, schema) {
|
|
93
|
+
return {
|
|
94
|
+
toolName,
|
|
95
|
+
schema,
|
|
96
|
+
rawSegment,
|
|
97
|
+
parsed: null,
|
|
98
|
+
errors: [],
|
|
99
|
+
meta: { originalContent: rawSegment }
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function mergePipelineConfigs(...configs) {
|
|
103
|
+
var _a, _b, _c;
|
|
104
|
+
const result = {
|
|
105
|
+
preParse: [],
|
|
106
|
+
fallbackReparse: [],
|
|
107
|
+
postParse: []
|
|
108
|
+
};
|
|
109
|
+
for (const config of configs) {
|
|
110
|
+
if (config.preParse) {
|
|
111
|
+
result.preParse = [...(_a = result.preParse) != null ? _a : [], ...config.preParse];
|
|
112
|
+
}
|
|
113
|
+
if (config.fallbackReparse) {
|
|
114
|
+
result.fallbackReparse = [
|
|
115
|
+
...(_b = result.fallbackReparse) != null ? _b : [],
|
|
116
|
+
...config.fallbackReparse
|
|
117
|
+
];
|
|
118
|
+
}
|
|
119
|
+
if (config.postParse) {
|
|
120
|
+
result.postParse = [...(_c = result.postParse) != null ? _c : [], ...config.postParse];
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/core/heuristics/xml-defaults.ts
|
|
127
|
+
import { parse, unwrapJsonSchema } from "@ai-sdk-tool/rxml";
|
|
128
|
+
var MALFORMED_CLOSE_RE_G = /<\/\s+([A-Za-z0-9_:-]+)\s*>/g;
|
|
129
|
+
var MALFORMED_CLOSE_RE = /<\/\s+([A-Za-z0-9_:-]+)\s*>/;
|
|
130
|
+
var STATUS_TO_STEP_BOUNDARY_RE = /<\/status>\s*<step>/g;
|
|
131
|
+
var WHITESPACE_REGEX = /\s/;
|
|
132
|
+
var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
|
|
133
|
+
var NAME_START_CHAR_RE = /[A-Za-z_:]/;
|
|
134
|
+
var STEP_TAG_RE = /<step>([\s\S]*?)<\/step>/i;
|
|
135
|
+
var STATUS_TAG_RE = /<status>([\s\S]*?)<\/status>/i;
|
|
136
|
+
var normalizeCloseTagsHeuristic = {
|
|
137
|
+
id: "normalize-close-tags",
|
|
138
|
+
phase: "pre-parse",
|
|
139
|
+
applies: () => true,
|
|
140
|
+
run: (ctx) => {
|
|
141
|
+
const normalized = ctx.rawSegment.replace(MALFORMED_CLOSE_RE_G, "</$1>");
|
|
142
|
+
if (normalized !== ctx.rawSegment) {
|
|
143
|
+
return { rawSegment: normalized };
|
|
144
|
+
}
|
|
145
|
+
return {};
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
var escapeInvalidLtHeuristic = {
|
|
149
|
+
id: "escape-invalid-lt",
|
|
150
|
+
phase: "pre-parse",
|
|
151
|
+
applies: () => true,
|
|
152
|
+
run: (ctx) => {
|
|
153
|
+
const escaped = escapeInvalidLt(ctx.rawSegment);
|
|
154
|
+
if (escaped !== ctx.rawSegment) {
|
|
155
|
+
return { rawSegment: escaped };
|
|
156
|
+
}
|
|
157
|
+
return {};
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
var balanceTagsHeuristic = {
|
|
161
|
+
id: "balance-tags",
|
|
162
|
+
phase: "fallback-reparse",
|
|
163
|
+
applies: (ctx) => {
|
|
164
|
+
var _a;
|
|
165
|
+
const original = ((_a = ctx.meta) == null ? void 0 : _a.originalContent) || ctx.rawSegment;
|
|
166
|
+
const normalized = original.replace(MALFORMED_CLOSE_RE_G, "</$1>");
|
|
167
|
+
const balanced = balanceTags(original);
|
|
168
|
+
const hasMalformedClose = MALFORMED_CLOSE_RE.test(original);
|
|
169
|
+
if (!hasMalformedClose && balanced.length > normalized.length) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
return balanced !== normalized;
|
|
173
|
+
},
|
|
174
|
+
run: (ctx) => {
|
|
175
|
+
var _a;
|
|
176
|
+
const original = ((_a = ctx.meta) == null ? void 0 : _a.originalContent) || ctx.rawSegment;
|
|
177
|
+
const balanced = balanceTags(original);
|
|
178
|
+
const escaped = escapeInvalidLt(balanced);
|
|
179
|
+
return { rawSegment: escaped, reparse: true };
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
var dedupeShellStringTagsHeuristic = {
|
|
183
|
+
id: "dedupe-shell-string-tags",
|
|
184
|
+
phase: "fallback-reparse",
|
|
185
|
+
applies: (ctx) => shouldDeduplicateStringTags(ctx.schema),
|
|
186
|
+
run: (ctx) => {
|
|
187
|
+
const names = getStringPropertyNames(ctx.schema);
|
|
188
|
+
let deduped = ctx.rawSegment;
|
|
189
|
+
for (const key of names) {
|
|
190
|
+
deduped = dedupeSingleTag(deduped, key);
|
|
191
|
+
}
|
|
192
|
+
if (deduped !== ctx.rawSegment) {
|
|
193
|
+
return { rawSegment: deduped, reparse: true };
|
|
194
|
+
}
|
|
195
|
+
return {};
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
var repairAgainstSchemaHeuristic = {
|
|
199
|
+
id: "repair-against-schema",
|
|
200
|
+
phase: "post-parse",
|
|
201
|
+
applies: (ctx) => ctx.parsed !== null && typeof ctx.parsed === "object",
|
|
202
|
+
run: (ctx) => {
|
|
203
|
+
const repaired = repairParsedAgainstSchema(ctx.parsed, ctx.schema);
|
|
204
|
+
if (repaired !== ctx.parsed) {
|
|
205
|
+
return { parsed: repaired };
|
|
206
|
+
}
|
|
207
|
+
return {};
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
var defaultPipelineConfig = {
|
|
211
|
+
preParse: [normalizeCloseTagsHeuristic, escapeInvalidLtHeuristic],
|
|
212
|
+
fallbackReparse: [balanceTagsHeuristic, dedupeShellStringTagsHeuristic],
|
|
213
|
+
postParse: [repairAgainstSchemaHeuristic]
|
|
214
|
+
};
|
|
215
|
+
var INDEX_TAG_RE = /^<(\d+)(?:>|\/?>)/;
|
|
216
|
+
function isIndexTagAt(xml, pos) {
|
|
217
|
+
const remaining = xml.slice(pos);
|
|
218
|
+
return INDEX_TAG_RE.test(remaining);
|
|
219
|
+
}
|
|
220
|
+
function escapeInvalidLt(xml) {
|
|
221
|
+
const len = xml.length;
|
|
222
|
+
let out = "";
|
|
223
|
+
for (let i = 0; i < len; i += 1) {
|
|
224
|
+
const ch = xml[i];
|
|
225
|
+
if (ch === "<") {
|
|
226
|
+
const next = i + 1 < len ? xml[i + 1] : "";
|
|
227
|
+
const isValidStart = NAME_START_CHAR_RE.test(next) || next === "/" || next === "!" || next === "?";
|
|
228
|
+
const isIndexTag = !isValidStart && isIndexTagAt(xml, i);
|
|
229
|
+
if (!(isValidStart || isIndexTag)) {
|
|
230
|
+
out += "<";
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
out += ch;
|
|
235
|
+
}
|
|
236
|
+
return out;
|
|
237
|
+
}
|
|
238
|
+
function balanceTags(xml) {
|
|
239
|
+
const src = xml.replace(MALFORMED_CLOSE_RE_G, "</$1>").replace(STATUS_TO_STEP_BOUNDARY_RE, "</status></step><step>");
|
|
240
|
+
let i = 0;
|
|
241
|
+
const len = src.length;
|
|
242
|
+
const out = [];
|
|
243
|
+
const stack = [];
|
|
244
|
+
while (i < len) {
|
|
245
|
+
const lt = src.indexOf("<", i);
|
|
246
|
+
if (lt === -1) {
|
|
247
|
+
out.push(src.slice(i));
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
out.push(src.slice(i, lt));
|
|
251
|
+
if (lt + 1 >= len) {
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
const next = src[lt + 1];
|
|
255
|
+
if (next === "!" || next === "?") {
|
|
256
|
+
i = handleSpecialTagSegment(src, lt, out);
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
if (next === "/") {
|
|
260
|
+
i = handleClosingTagSegment(src, lt, out, stack);
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
i = handleOpeningTagSegment(src, lt, out, stack);
|
|
264
|
+
}
|
|
265
|
+
for (let k = stack.length - 1; k >= 0; k -= 1) {
|
|
266
|
+
out.push(`</${stack[k]}>`);
|
|
267
|
+
}
|
|
268
|
+
return out.join("");
|
|
269
|
+
}
|
|
270
|
+
function skipWs(s, p, len) {
|
|
271
|
+
let idx = p;
|
|
272
|
+
while (idx < len && WHITESPACE_REGEX.test(s[idx])) {
|
|
273
|
+
idx += 1;
|
|
274
|
+
}
|
|
275
|
+
return idx;
|
|
276
|
+
}
|
|
277
|
+
function parseTagNameAt(s, p, len) {
|
|
278
|
+
let idx = p;
|
|
279
|
+
const start = idx;
|
|
280
|
+
while (idx < len && NAME_CHAR_RE.test(s[idx])) {
|
|
281
|
+
idx += 1;
|
|
282
|
+
}
|
|
283
|
+
return { name: s.slice(start, idx), pos: idx };
|
|
284
|
+
}
|
|
285
|
+
function handleSpecialTagSegment(src, lt, out) {
|
|
286
|
+
const gt = src.indexOf(">", lt + 1);
|
|
287
|
+
if (gt === -1) {
|
|
288
|
+
out.push(src.slice(lt));
|
|
289
|
+
return src.length;
|
|
290
|
+
}
|
|
291
|
+
out.push(src.slice(lt, gt + 1));
|
|
292
|
+
return gt + 1;
|
|
293
|
+
}
|
|
294
|
+
function handleClosingTagSegment(src, lt, out, stack) {
|
|
295
|
+
const len = src.length;
|
|
296
|
+
let p = skipWs(src, lt + 2, len);
|
|
297
|
+
const { name, pos } = parseTagNameAt(src, p, len);
|
|
298
|
+
p = pos;
|
|
299
|
+
const gt = src.indexOf(">", p);
|
|
300
|
+
const closingText = gt === -1 ? src.slice(lt) : src.slice(lt, gt + 1);
|
|
301
|
+
const idx = stack.lastIndexOf(name);
|
|
302
|
+
if (idx !== -1) {
|
|
303
|
+
for (let k = stack.length - 1; k > idx; k -= 1) {
|
|
304
|
+
out.push(`</${stack[k]}>`);
|
|
305
|
+
stack.pop();
|
|
306
|
+
}
|
|
307
|
+
out.push(closingText);
|
|
308
|
+
stack.pop();
|
|
309
|
+
}
|
|
310
|
+
return gt === -1 ? len : gt + 1;
|
|
311
|
+
}
|
|
312
|
+
function handleOpeningTagSegment(src, lt, out, stack) {
|
|
313
|
+
const len = src.length;
|
|
314
|
+
let p = skipWs(src, lt + 1, len);
|
|
315
|
+
const nameStart = p;
|
|
316
|
+
const parsed = parseTagNameAt(src, p, len);
|
|
317
|
+
p = parsed.pos;
|
|
318
|
+
const name = src.slice(nameStart, p);
|
|
319
|
+
const q = src.indexOf(">", p);
|
|
320
|
+
if (q === -1) {
|
|
321
|
+
out.push(src.slice(lt));
|
|
322
|
+
return len;
|
|
323
|
+
}
|
|
324
|
+
let r = q - 1;
|
|
325
|
+
while (r >= nameStart && WHITESPACE_REGEX.test(src[r])) {
|
|
326
|
+
r -= 1;
|
|
327
|
+
}
|
|
328
|
+
const selfClosing = src[r] === "/";
|
|
329
|
+
out.push(src.slice(lt, q + 1));
|
|
330
|
+
if (!selfClosing && name) {
|
|
331
|
+
stack.push(name);
|
|
332
|
+
}
|
|
333
|
+
return q + 1;
|
|
334
|
+
}
|
|
335
|
+
function shouldDeduplicateStringTags(schema) {
|
|
336
|
+
const unwrapped = unwrapJsonSchema(schema);
|
|
337
|
+
if (!unwrapped || typeof unwrapped !== "object") {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
const props = unwrapped.properties;
|
|
341
|
+
if (!props) {
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
const commandRaw = props.command;
|
|
345
|
+
if (!commandRaw) {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
const command = unwrapJsonSchema(commandRaw);
|
|
349
|
+
return (command == null ? void 0 : command.type) === "array";
|
|
350
|
+
}
|
|
351
|
+
function getStringPropertyNames(schema) {
|
|
352
|
+
const unwrapped = unwrapJsonSchema(schema);
|
|
353
|
+
if (!unwrapped || typeof unwrapped !== "object") {
|
|
354
|
+
return [];
|
|
355
|
+
}
|
|
356
|
+
const props = unwrapped.properties;
|
|
357
|
+
if (!props) {
|
|
358
|
+
return [];
|
|
359
|
+
}
|
|
360
|
+
const names = [];
|
|
361
|
+
for (const key of Object.keys(props)) {
|
|
362
|
+
const prop = unwrapJsonSchema(
|
|
363
|
+
props[key]
|
|
364
|
+
);
|
|
365
|
+
const type = prop.type;
|
|
366
|
+
if (type === "string") {
|
|
367
|
+
names.push(key);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return names;
|
|
371
|
+
}
|
|
372
|
+
function escapeRegExp(s) {
|
|
373
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
374
|
+
}
|
|
375
|
+
function dedupeSingleTag(xml, key) {
|
|
376
|
+
var _a, _b;
|
|
377
|
+
const escaped = escapeRegExp(key);
|
|
378
|
+
const re = new RegExp(`<${escaped}>([\\s\\S]*?)<\\/${escaped}>`, "g");
|
|
379
|
+
const matches = Array.from(xml.matchAll(re));
|
|
380
|
+
if (matches.length <= 1) {
|
|
381
|
+
return xml;
|
|
382
|
+
}
|
|
383
|
+
const last = matches.at(-1);
|
|
384
|
+
let result = "";
|
|
385
|
+
let cursor = 0;
|
|
386
|
+
for (const m of matches) {
|
|
387
|
+
const idx = (_a = m.index) != null ? _a : 0;
|
|
388
|
+
result += xml.slice(cursor, idx);
|
|
389
|
+
if (last && idx === ((_b = last.index) != null ? _b : -1)) {
|
|
390
|
+
result += m[0];
|
|
391
|
+
}
|
|
392
|
+
cursor = idx + m[0].length;
|
|
393
|
+
}
|
|
394
|
+
result += xml.slice(cursor);
|
|
395
|
+
return result;
|
|
396
|
+
}
|
|
397
|
+
function repairParsedAgainstSchema(input, schema) {
|
|
398
|
+
if (!input || typeof input !== "object") {
|
|
399
|
+
return input;
|
|
400
|
+
}
|
|
401
|
+
const unwrapped = unwrapJsonSchema(schema);
|
|
402
|
+
if (!unwrapped || typeof unwrapped !== "object") {
|
|
403
|
+
return input;
|
|
404
|
+
}
|
|
405
|
+
const properties = unwrapped.properties;
|
|
406
|
+
if (!properties) {
|
|
407
|
+
return input;
|
|
408
|
+
}
|
|
409
|
+
applySchemaProps(input, properties);
|
|
410
|
+
return input;
|
|
411
|
+
}
|
|
412
|
+
function applySchemaProps(obj, properties) {
|
|
413
|
+
for (const key of Object.keys(obj)) {
|
|
414
|
+
const propSchema = properties[key];
|
|
415
|
+
if (!propSchema) {
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
const prop = unwrapJsonSchema(propSchema);
|
|
419
|
+
const propType = prop.type;
|
|
420
|
+
if (propType === "array" && prop.items) {
|
|
421
|
+
const itemSchemaRaw = prop.items;
|
|
422
|
+
const itemSchema = unwrapJsonSchema(itemSchemaRaw);
|
|
423
|
+
obj[key] = coerceArrayItems(obj[key], itemSchema);
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
if (propType === "object") {
|
|
427
|
+
const val = obj[key];
|
|
428
|
+
if (val && typeof val === "object") {
|
|
429
|
+
obj[key] = repairParsedAgainstSchema(val, prop);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
function coerceArrayItems(val, itemSchema) {
|
|
435
|
+
if (!Array.isArray(val)) {
|
|
436
|
+
return val;
|
|
437
|
+
}
|
|
438
|
+
return val.map((v) => coerceArrayItem(v, itemSchema));
|
|
439
|
+
}
|
|
440
|
+
function coerceArrayItem(v, itemSchema) {
|
|
441
|
+
const itemType = itemSchema == null ? void 0 : itemSchema.type;
|
|
442
|
+
if (typeof v === "string" && itemType === "object") {
|
|
443
|
+
const parsed = tryParseStringToSchemaObject(v, itemSchema);
|
|
444
|
+
if (parsed !== null) {
|
|
445
|
+
return parsed;
|
|
446
|
+
}
|
|
447
|
+
const fallback = extractStepStatusFromString(
|
|
448
|
+
v.replace(MALFORMED_CLOSE_RE_G, "</$1>")
|
|
449
|
+
);
|
|
450
|
+
if (fallback) {
|
|
451
|
+
return fallback;
|
|
452
|
+
}
|
|
453
|
+
return v;
|
|
454
|
+
}
|
|
455
|
+
if (v && typeof v === "object" && itemType === "object") {
|
|
456
|
+
return repairParsedAgainstSchema(v, itemSchema);
|
|
457
|
+
}
|
|
458
|
+
return v;
|
|
459
|
+
}
|
|
460
|
+
function tryParseStringToSchemaObject(xml, itemSchema) {
|
|
461
|
+
try {
|
|
462
|
+
const normalized = xml.replace(MALFORMED_CLOSE_RE_G, "</$1>");
|
|
463
|
+
const fixed = parse(normalized, itemSchema, { noChildNodes: [] });
|
|
464
|
+
return typeof fixed === "string" ? null : fixed;
|
|
465
|
+
} catch (e) {
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
function extractStepStatusFromString(normXml) {
|
|
470
|
+
const stepMatch = normXml.match(STEP_TAG_RE);
|
|
471
|
+
const statusMatch = normXml.match(STATUS_TAG_RE);
|
|
472
|
+
if (stepMatch && statusMatch) {
|
|
473
|
+
return { step: stepMatch[1], status: statusMatch[1] };
|
|
474
|
+
}
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// src/core/utils/debug.ts
|
|
479
|
+
var LINE_SPLIT_REGEX = /\r?\n/;
|
|
480
|
+
function normalizeBooleanString(value) {
|
|
481
|
+
const normalized = value.trim().toLowerCase();
|
|
482
|
+
if (normalized === "1" || normalized === "true" || normalized === "yes") {
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
if (normalized === "0" || normalized === "false" || normalized === "no") {
|
|
486
|
+
return false;
|
|
487
|
+
}
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
function getDebugLevel() {
|
|
491
|
+
const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW || "off";
|
|
492
|
+
const envLower = String(envVal).toLowerCase();
|
|
493
|
+
if (envLower === "stream" || envLower === "parse" || envLower === "off") {
|
|
494
|
+
return envLower;
|
|
495
|
+
}
|
|
496
|
+
const boolEnv = normalizeBooleanString(envLower);
|
|
497
|
+
if (boolEnv === true) {
|
|
498
|
+
return "stream";
|
|
499
|
+
}
|
|
500
|
+
if (envLower === "2") {
|
|
501
|
+
return "parse";
|
|
502
|
+
}
|
|
503
|
+
return "off";
|
|
504
|
+
}
|
|
505
|
+
function color(code) {
|
|
506
|
+
return (text) => `\x1B[${code}m${text}\x1B[0m`;
|
|
507
|
+
}
|
|
508
|
+
var ANSI_GRAY = 90;
|
|
509
|
+
var ANSI_YELLOW = 33;
|
|
510
|
+
var ANSI_CYAN = 36;
|
|
511
|
+
var ANSI_BG_BLUE = 44;
|
|
512
|
+
var ANSI_BG_GREEN = 42;
|
|
513
|
+
var ANSI_INVERSE = 7;
|
|
514
|
+
var ANSI_UNDERLINE = 4;
|
|
515
|
+
var ANSI_BOLD = 1;
|
|
516
|
+
var cGray = color(ANSI_GRAY);
|
|
517
|
+
var cYellow = color(ANSI_YELLOW);
|
|
518
|
+
var cCyan = color(ANSI_CYAN);
|
|
519
|
+
var cBgBlue = color(ANSI_BG_BLUE);
|
|
520
|
+
var cBgGreen = color(ANSI_BG_GREEN);
|
|
521
|
+
var cInverse = color(ANSI_INVERSE);
|
|
522
|
+
var cUnderline = color(ANSI_UNDERLINE);
|
|
523
|
+
var cBold = color(ANSI_BOLD);
|
|
524
|
+
var MAX_SNIPPET_LENGTH = 800;
|
|
525
|
+
function safeStringify(value) {
|
|
526
|
+
try {
|
|
527
|
+
return `
|
|
528
|
+
${typeof value === "string" ? value : JSON.stringify(value, null, 2)}`;
|
|
529
|
+
} catch (e) {
|
|
530
|
+
return String(value);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
function formatError(error) {
|
|
534
|
+
if (error instanceof Error) {
|
|
535
|
+
const stack = error.stack ? `
|
|
536
|
+
${error.stack}` : "";
|
|
537
|
+
return `
|
|
538
|
+
${error.name}: ${error.message}${stack}`;
|
|
539
|
+
}
|
|
540
|
+
return safeStringify(error);
|
|
541
|
+
}
|
|
542
|
+
function truncateSnippet(snippet) {
|
|
543
|
+
if (snippet.length <= MAX_SNIPPET_LENGTH) {
|
|
544
|
+
return snippet;
|
|
545
|
+
}
|
|
546
|
+
return `${snippet.slice(0, MAX_SNIPPET_LENGTH)}
|
|
547
|
+
\u2026[truncated ${snippet.length - MAX_SNIPPET_LENGTH} chars]`;
|
|
548
|
+
}
|
|
549
|
+
function logParseFailure({
|
|
550
|
+
phase,
|
|
551
|
+
reason,
|
|
552
|
+
snippet,
|
|
553
|
+
error
|
|
554
|
+
}) {
|
|
555
|
+
if (getDebugLevel() !== "parse") {
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
const label = cBgBlue(`[${phase}]`);
|
|
559
|
+
console.log(cGray("[debug:mw:fail]"), label, cYellow(reason));
|
|
560
|
+
if (snippet) {
|
|
561
|
+
const formatted = truncateSnippet(snippet);
|
|
562
|
+
console.log(cGray("[debug:mw:fail:snippet]"), formatted);
|
|
563
|
+
}
|
|
564
|
+
if (error) {
|
|
565
|
+
console.log(cGray("[debug:mw:fail:error]"), cCyan(formatError(error)));
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
function logRawChunk(part) {
|
|
569
|
+
console.log(cGray("[debug:mw:raw]"), cYellow(safeStringify(part)));
|
|
570
|
+
}
|
|
571
|
+
function logParsedChunk(part) {
|
|
572
|
+
console.log(cGray("[debug:mw:out]"), cCyan(safeStringify(part)));
|
|
573
|
+
}
|
|
574
|
+
function getHighlightStyle() {
|
|
575
|
+
const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW_STYLE || "bg";
|
|
576
|
+
const normalized = String(envVal).trim().toLowerCase();
|
|
577
|
+
if (normalized === "inverse" || normalized === "invert") {
|
|
578
|
+
return "inverse";
|
|
579
|
+
}
|
|
580
|
+
if (normalized === "underline" || normalized === "ul") {
|
|
581
|
+
return "underline";
|
|
582
|
+
}
|
|
583
|
+
if (normalized === "bold") {
|
|
584
|
+
return "bold";
|
|
585
|
+
}
|
|
586
|
+
if (normalized === "bg" || normalized === "background") {
|
|
587
|
+
return "bg";
|
|
588
|
+
}
|
|
589
|
+
const asBool = normalizeBooleanString(normalized);
|
|
590
|
+
if (asBool === true) {
|
|
591
|
+
return "bg";
|
|
592
|
+
}
|
|
593
|
+
return "bg";
|
|
594
|
+
}
|
|
595
|
+
function getHighlightFunction(style) {
|
|
596
|
+
if (style === "inverse") {
|
|
597
|
+
return cInverse;
|
|
598
|
+
}
|
|
599
|
+
if (style === "underline") {
|
|
600
|
+
return cUnderline;
|
|
601
|
+
}
|
|
602
|
+
if (style === "bold") {
|
|
603
|
+
return cBold;
|
|
604
|
+
}
|
|
605
|
+
if (style === "bg") {
|
|
606
|
+
return cBgGreen;
|
|
607
|
+
}
|
|
608
|
+
return cYellow;
|
|
609
|
+
}
|
|
610
|
+
function renderHighlightedText(originalText, style, highlight) {
|
|
611
|
+
if (style === "bg" || style === "inverse" || style === "underline" || style === "bold") {
|
|
612
|
+
return originalText.split(LINE_SPLIT_REGEX).map((line) => line.length ? highlight(line) : line).join("\n");
|
|
613
|
+
}
|
|
614
|
+
return highlight(originalText);
|
|
615
|
+
}
|
|
616
|
+
function logParsedSummary({
|
|
617
|
+
toolCalls,
|
|
618
|
+
originalText
|
|
619
|
+
}) {
|
|
620
|
+
if (originalText) {
|
|
621
|
+
const style = getHighlightStyle();
|
|
622
|
+
const highlight = getHighlightFunction(style);
|
|
623
|
+
const rendered = renderHighlightedText(originalText, style, highlight);
|
|
624
|
+
console.log(cGray("[debug:mw:origin]"), `
|
|
625
|
+
${rendered}`);
|
|
626
|
+
}
|
|
627
|
+
if (toolCalls.length > 0) {
|
|
628
|
+
const styledSummary = safeStringify(toolCalls).split(LINE_SPLIT_REGEX).map((line) => line.length ? cBgBlue(line) : line).join("\n");
|
|
629
|
+
console.log(cGray("[debug:mw:summary]"), styledSummary);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// src/core/utils/get-potential-start-index.ts
|
|
634
|
+
function getPotentialStartIndex(text, searchedText) {
|
|
635
|
+
if (searchedText.length === 0) {
|
|
636
|
+
return null;
|
|
637
|
+
}
|
|
638
|
+
const directIndex = text.indexOf(searchedText);
|
|
639
|
+
if (directIndex !== -1) {
|
|
640
|
+
return directIndex;
|
|
641
|
+
}
|
|
642
|
+
for (let i = text.length - 1; i >= 0; i -= 1) {
|
|
643
|
+
const suffix = text.substring(i);
|
|
644
|
+
if (searchedText.startsWith(suffix)) {
|
|
645
|
+
return i;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
return null;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// src/core/utils/regex.ts
|
|
652
|
+
function escapeRegExp2(literal) {
|
|
653
|
+
return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// src/core/utils/robust-json.ts
|
|
657
|
+
var WHITESPACE_TEST_REGEX = /\s/;
|
|
658
|
+
var WHITESPACE_REGEX2 = /^\s+/;
|
|
659
|
+
var OBJECT_START_REGEX = /^\{/;
|
|
660
|
+
var OBJECT_END_REGEX = /^\}/;
|
|
661
|
+
var ARRAY_START_REGEX = /^\[/;
|
|
662
|
+
var ARRAY_END_REGEX = /^\]/;
|
|
663
|
+
var COMMA_REGEX = /^,/;
|
|
664
|
+
var COLON_REGEX = /^:/;
|
|
665
|
+
var KEYWORD_REGEX = /^(?:true|false|null)/;
|
|
666
|
+
var NUMBER_REGEX = /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/;
|
|
667
|
+
var STRING_DOUBLE_REGEX = /^"(?:[^"\\]|\\["bnrtf\\/]|\\u[0-9a-fA-F]{4})*"/;
|
|
668
|
+
var STRING_SINGLE_REGEX = /^'((?:[^'\\]|\\['bnrtf\\/]|\\u[0-9a-fA-F]{4})*)'/;
|
|
669
|
+
var COMMENT_SINGLE_REGEX = /^\/\/.*?(?:\r\n|\r|\n)/;
|
|
670
|
+
var COMMENT_MULTI_REGEX = /^\/\*[\s\S]*?\*\//;
|
|
671
|
+
var IDENTIFIER_REGEX = /^[$a-zA-Z0-9_\-+.*?!|&%^/#\\]+/;
|
|
672
|
+
function some(array, f) {
|
|
673
|
+
let acc = false;
|
|
674
|
+
for (let i = 0; i < array.length; i += 1) {
|
|
675
|
+
const result = f(array[i], i, array);
|
|
676
|
+
acc = result === void 0 ? false : result;
|
|
677
|
+
if (acc) {
|
|
678
|
+
return acc;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return acc;
|
|
682
|
+
}
|
|
683
|
+
function makeLexer(tokenSpecs) {
|
|
684
|
+
return (contents) => {
|
|
685
|
+
const tokens = [];
|
|
686
|
+
let line = 1;
|
|
687
|
+
let remainingContents = contents;
|
|
688
|
+
function findToken() {
|
|
689
|
+
const result = some(tokenSpecs, (tokenSpec) => {
|
|
690
|
+
const m = tokenSpec.re.exec(remainingContents);
|
|
691
|
+
if (m) {
|
|
692
|
+
const raw = m[0];
|
|
693
|
+
remainingContents = remainingContents.slice(raw.length);
|
|
694
|
+
return {
|
|
695
|
+
raw,
|
|
696
|
+
matched: tokenSpec.f(m)
|
|
697
|
+
// Process the match using the spec's function
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
return;
|
|
701
|
+
});
|
|
702
|
+
return result === false ? void 0 : result;
|
|
703
|
+
}
|
|
704
|
+
while (remainingContents !== "") {
|
|
705
|
+
const matched = findToken();
|
|
706
|
+
if (!matched) {
|
|
707
|
+
const err = new SyntaxError(
|
|
708
|
+
`Unexpected character: ${remainingContents[0]}; input: ${remainingContents.substr(
|
|
709
|
+
0,
|
|
710
|
+
100
|
|
711
|
+
)}`
|
|
712
|
+
);
|
|
713
|
+
err.line = line;
|
|
714
|
+
throw err;
|
|
715
|
+
}
|
|
716
|
+
const tokenWithLine = matched.matched;
|
|
717
|
+
tokenWithLine.line = line;
|
|
718
|
+
line += matched.raw.replace(/[^\n]/g, "").length;
|
|
719
|
+
tokens.push(tokenWithLine);
|
|
720
|
+
}
|
|
721
|
+
return tokens;
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
function fStringSingle(m) {
|
|
725
|
+
const content = m[1].replace(
|
|
726
|
+
/([^'\\]|\\['bnrtf\\]|\\u[0-9a-fA-F]{4})/g,
|
|
727
|
+
(mm) => {
|
|
728
|
+
if (mm === '"') {
|
|
729
|
+
return '\\"';
|
|
730
|
+
}
|
|
731
|
+
if (mm === "\\'") {
|
|
732
|
+
return "'";
|
|
733
|
+
}
|
|
734
|
+
return mm;
|
|
735
|
+
}
|
|
736
|
+
);
|
|
737
|
+
const match = `"${content}"`;
|
|
738
|
+
return {
|
|
739
|
+
type: "string",
|
|
740
|
+
match,
|
|
741
|
+
// The transformed, double-quoted string representation
|
|
742
|
+
// Use JSON.parse on the transformed string to handle escape sequences correctly
|
|
743
|
+
value: JSON.parse(match)
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
function fStringDouble(m) {
|
|
747
|
+
return {
|
|
748
|
+
type: "string",
|
|
749
|
+
match: m[0],
|
|
750
|
+
// The raw matched string (including quotes)
|
|
751
|
+
value: JSON.parse(m[0])
|
|
752
|
+
// Use JSON.parse to handle escapes and get the value
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
function fIdentifier(m) {
|
|
756
|
+
const value = m[0];
|
|
757
|
+
const match = '"' + value.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + // Escape backslashes and quotes
|
|
758
|
+
'"';
|
|
759
|
+
return {
|
|
760
|
+
type: "string",
|
|
761
|
+
// Treat identifiers as strings
|
|
762
|
+
value,
|
|
763
|
+
// The original identifier name
|
|
764
|
+
match
|
|
765
|
+
// The double-quoted string representation
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
function fComment(m) {
|
|
769
|
+
const match = m[0].replace(
|
|
770
|
+
/./g,
|
|
771
|
+
(c) => WHITESPACE_TEST_REGEX.test(c) ? c : " "
|
|
772
|
+
);
|
|
773
|
+
return {
|
|
774
|
+
type: " ",
|
|
775
|
+
// Represent comments as whitespace tokens
|
|
776
|
+
match,
|
|
777
|
+
// String containing original newlines and spaces for other chars
|
|
778
|
+
value: void 0
|
|
779
|
+
// Comments don't have a semantic value
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
function fNumber(m) {
|
|
783
|
+
return {
|
|
784
|
+
type: "number",
|
|
785
|
+
match: m[0],
|
|
786
|
+
// The raw matched number string
|
|
787
|
+
value: Number.parseFloat(m[0])
|
|
788
|
+
// Convert string to number
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
function fKeyword(m) {
|
|
792
|
+
let value;
|
|
793
|
+
switch (m[0]) {
|
|
794
|
+
case "null":
|
|
795
|
+
value = null;
|
|
796
|
+
break;
|
|
797
|
+
case "true":
|
|
798
|
+
value = true;
|
|
799
|
+
break;
|
|
800
|
+
case "false":
|
|
801
|
+
value = false;
|
|
802
|
+
break;
|
|
803
|
+
default:
|
|
804
|
+
throw new Error(`Unexpected keyword: ${m[0]}`);
|
|
805
|
+
}
|
|
806
|
+
return {
|
|
807
|
+
type: "atom",
|
|
808
|
+
// Use 'atom' type for these literals
|
|
809
|
+
match: m[0],
|
|
810
|
+
// The raw matched keyword
|
|
811
|
+
value
|
|
812
|
+
// The corresponding JavaScript value
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
function makeTokenSpecs(relaxed) {
|
|
816
|
+
function f(type) {
|
|
817
|
+
return (m) => {
|
|
818
|
+
return { type, match: m[0], value: void 0 };
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
let tokenSpecs = [
|
|
822
|
+
{ re: WHITESPACE_REGEX2, f: f(" ") },
|
|
823
|
+
// Whitespace
|
|
824
|
+
{ re: OBJECT_START_REGEX, f: f("{") },
|
|
825
|
+
// Object start
|
|
826
|
+
{ re: OBJECT_END_REGEX, f: f("}") },
|
|
827
|
+
// Object end
|
|
828
|
+
{ re: ARRAY_START_REGEX, f: f("[") },
|
|
829
|
+
// Array start
|
|
830
|
+
{ re: ARRAY_END_REGEX, f: f("]") },
|
|
831
|
+
// Array end
|
|
832
|
+
{ re: COMMA_REGEX, f: f(",") },
|
|
833
|
+
// Comma separator
|
|
834
|
+
{ re: COLON_REGEX, f: f(":") },
|
|
835
|
+
// Key-value separator
|
|
836
|
+
{ re: KEYWORD_REGEX, f: fKeyword },
|
|
837
|
+
// Keywords
|
|
838
|
+
// Number: optional sign, digits, optional decimal part, optional exponent
|
|
839
|
+
{ re: NUMBER_REGEX, f: fNumber },
|
|
840
|
+
// String: double-quoted, handles escapes
|
|
841
|
+
{ re: STRING_DOUBLE_REGEX, f: fStringDouble }
|
|
842
|
+
];
|
|
843
|
+
if (relaxed) {
|
|
844
|
+
tokenSpecs = tokenSpecs.concat([
|
|
845
|
+
// Single-quoted strings
|
|
846
|
+
{
|
|
847
|
+
re: STRING_SINGLE_REGEX,
|
|
848
|
+
f: fStringSingle
|
|
849
|
+
},
|
|
850
|
+
// Single-line comments (// ...)
|
|
851
|
+
{ re: COMMENT_SINGLE_REGEX, f: fComment },
|
|
852
|
+
// Multi-line comments (/* ... */)
|
|
853
|
+
{ re: COMMENT_MULTI_REGEX, f: fComment },
|
|
854
|
+
// Unquoted identifiers (treated as strings)
|
|
855
|
+
// Allows letters, numbers, _, -, +, ., *, ?, !, |, &, %, ^, /, #, \
|
|
856
|
+
{ re: IDENTIFIER_REGEX, f: fIdentifier }
|
|
857
|
+
// Note: The order matters here. Identifiers are checked after keywords/numbers.
|
|
858
|
+
]);
|
|
859
|
+
}
|
|
860
|
+
return tokenSpecs;
|
|
861
|
+
}
|
|
862
|
+
var lexer = makeLexer(makeTokenSpecs(true));
|
|
863
|
+
var strictLexer = makeLexer(makeTokenSpecs(false));
|
|
864
|
+
function previousNWSToken(tokens, index) {
|
|
865
|
+
let currentIndex = index;
|
|
866
|
+
for (; currentIndex >= 0; currentIndex -= 1) {
|
|
867
|
+
if (tokens[currentIndex].type !== " ") {
|
|
868
|
+
return currentIndex;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
function stripTrailingComma(tokens) {
|
|
874
|
+
const res = [];
|
|
875
|
+
tokens.forEach((token, index) => {
|
|
876
|
+
if (index > 0 && (token.type === "]" || token.type === "}")) {
|
|
877
|
+
const prevNWSTokenIndex = previousNWSToken(res, res.length - 1);
|
|
878
|
+
if (prevNWSTokenIndex !== void 0 && res[prevNWSTokenIndex].type === ",") {
|
|
879
|
+
const preCommaIndex = previousNWSToken(res, prevNWSTokenIndex - 1);
|
|
880
|
+
if (preCommaIndex !== void 0 && res[preCommaIndex].type !== "[" && res[preCommaIndex].type !== "{") {
|
|
881
|
+
res[prevNWSTokenIndex] = {
|
|
882
|
+
type: " ",
|
|
883
|
+
match: " ",
|
|
884
|
+
// Represent as a single space
|
|
885
|
+
value: void 0,
|
|
886
|
+
// Whitespace has no value
|
|
887
|
+
line: res[prevNWSTokenIndex].line
|
|
888
|
+
// Preserve original line number
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
res.push(token);
|
|
894
|
+
});
|
|
895
|
+
return res;
|
|
896
|
+
}
|
|
897
|
+
function transform(text) {
|
|
898
|
+
let tokens = lexer(text);
|
|
899
|
+
tokens = stripTrailingComma(tokens);
|
|
900
|
+
return tokens.reduce((str, token) => str + token.match, "");
|
|
901
|
+
}
|
|
902
|
+
function popToken(tokens, state) {
|
|
903
|
+
var _a, _b;
|
|
904
|
+
const token = tokens[state.pos];
|
|
905
|
+
state.pos += 1;
|
|
906
|
+
if (!token) {
|
|
907
|
+
const lastLine = tokens.length !== 0 ? (_b = (_a = tokens.at(-1)) == null ? void 0 : _a.line) != null ? _b : 1 : 1;
|
|
908
|
+
return { type: "eof", match: "", value: void 0, line: lastLine };
|
|
909
|
+
}
|
|
910
|
+
return token;
|
|
911
|
+
}
|
|
912
|
+
function strToken(token) {
|
|
913
|
+
switch (token.type) {
|
|
914
|
+
case "atom":
|
|
915
|
+
case "string":
|
|
916
|
+
case "number":
|
|
917
|
+
return `${token.type} ${token.match}`;
|
|
918
|
+
case "eof":
|
|
919
|
+
return "end-of-file";
|
|
920
|
+
default:
|
|
921
|
+
return `'${token.type}'`;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
function skipColon(tokens, state) {
|
|
925
|
+
const colon = popToken(tokens, state);
|
|
926
|
+
if (colon.type !== ":") {
|
|
927
|
+
const message = `Unexpected token: ${strToken(colon)}, expected ':'`;
|
|
928
|
+
if (state.tolerant) {
|
|
929
|
+
state.warnings.push({
|
|
930
|
+
message,
|
|
931
|
+
line: colon.line
|
|
932
|
+
});
|
|
933
|
+
state.pos -= 1;
|
|
934
|
+
} else {
|
|
935
|
+
const err = new SyntaxError(message);
|
|
936
|
+
err.line = colon.line;
|
|
937
|
+
throw err;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
function skipPunctuation(tokens, state, valid) {
|
|
942
|
+
const punctuation = [",", ":", "]", "}"];
|
|
943
|
+
let token = popToken(tokens, state);
|
|
944
|
+
while (true) {
|
|
945
|
+
if (valid == null ? void 0 : valid.includes(token.type)) {
|
|
946
|
+
return token;
|
|
947
|
+
}
|
|
948
|
+
if (token.type === "eof") {
|
|
949
|
+
return token;
|
|
950
|
+
}
|
|
951
|
+
if (punctuation.includes(token.type)) {
|
|
952
|
+
const message = `Unexpected token: ${strToken(
|
|
953
|
+
token
|
|
954
|
+
)}, expected '[', '{', number, string or atom`;
|
|
955
|
+
if (state.tolerant) {
|
|
956
|
+
state.warnings.push({
|
|
957
|
+
message,
|
|
958
|
+
line: token.line
|
|
959
|
+
});
|
|
960
|
+
token = popToken(tokens, state);
|
|
961
|
+
} else {
|
|
962
|
+
const err = new SyntaxError(message);
|
|
963
|
+
err.line = token.line;
|
|
964
|
+
throw err;
|
|
965
|
+
}
|
|
966
|
+
} else {
|
|
967
|
+
return token;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
function raiseError(state, token, message) {
|
|
972
|
+
if (state.tolerant) {
|
|
973
|
+
state.warnings.push({
|
|
974
|
+
message,
|
|
975
|
+
line: token.line
|
|
976
|
+
});
|
|
977
|
+
} else {
|
|
978
|
+
const err = new SyntaxError(message);
|
|
979
|
+
err.line = token.line;
|
|
980
|
+
throw err;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
function raiseUnexpected(state, token, expected) {
|
|
984
|
+
raiseError(
|
|
985
|
+
state,
|
|
986
|
+
token,
|
|
987
|
+
`Unexpected token: ${strToken(token)}, expected ${expected}`
|
|
988
|
+
);
|
|
989
|
+
}
|
|
990
|
+
function checkDuplicates(state, obj, token) {
|
|
991
|
+
const key = String(token.value);
|
|
992
|
+
if (!state.duplicate && Object.hasOwn(obj, key)) {
|
|
993
|
+
raiseError(state, token, `Duplicate key: ${key}`);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
function appendPair(state, obj, key, value) {
|
|
997
|
+
const finalValue = state.reviver ? state.reviver(key, value) : value;
|
|
998
|
+
if (finalValue !== void 0) {
|
|
999
|
+
obj[key] = finalValue;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
function parsePair(tokens, state, obj) {
|
|
1003
|
+
let token = skipPunctuation(tokens, state, [":", "string", "number", "atom"]);
|
|
1004
|
+
let value;
|
|
1005
|
+
if (token.type !== "string") {
|
|
1006
|
+
raiseUnexpected(state, token, "string key");
|
|
1007
|
+
if (state.tolerant) {
|
|
1008
|
+
switch (token.type) {
|
|
1009
|
+
case ":":
|
|
1010
|
+
token = {
|
|
1011
|
+
type: "string",
|
|
1012
|
+
value: "null",
|
|
1013
|
+
match: '"null"',
|
|
1014
|
+
line: token.line
|
|
1015
|
+
};
|
|
1016
|
+
state.pos -= 1;
|
|
1017
|
+
break;
|
|
1018
|
+
case "number":
|
|
1019
|
+
// Use number as string key
|
|
1020
|
+
case "atom":
|
|
1021
|
+
token = {
|
|
1022
|
+
type: "string",
|
|
1023
|
+
value: String(token.value),
|
|
1024
|
+
match: `"${token.value}"`,
|
|
1025
|
+
line: token.line
|
|
1026
|
+
};
|
|
1027
|
+
break;
|
|
1028
|
+
case "[":
|
|
1029
|
+
// Assume missing key before an array
|
|
1030
|
+
case "{":
|
|
1031
|
+
state.pos -= 1;
|
|
1032
|
+
value = parseAny(tokens, state);
|
|
1033
|
+
checkDuplicates(state, obj, {
|
|
1034
|
+
type: "string",
|
|
1035
|
+
value: "null",
|
|
1036
|
+
match: '"null"',
|
|
1037
|
+
line: token.line
|
|
1038
|
+
});
|
|
1039
|
+
appendPair(state, obj, "null", value);
|
|
1040
|
+
return;
|
|
1041
|
+
// Finished parsing this "pair"
|
|
1042
|
+
case "eof":
|
|
1043
|
+
return;
|
|
1044
|
+
// Cannot recover
|
|
1045
|
+
default:
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
} else {
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
checkDuplicates(state, obj, token);
|
|
1053
|
+
const key = String(token.value);
|
|
1054
|
+
skipColon(tokens, state);
|
|
1055
|
+
value = parseAny(tokens, state);
|
|
1056
|
+
appendPair(state, obj, key, value);
|
|
1057
|
+
}
|
|
1058
|
+
function parseElement(tokens, state, arr) {
|
|
1059
|
+
const key = arr.length;
|
|
1060
|
+
const value = parseAny(tokens, state);
|
|
1061
|
+
arr[key] = state.reviver ? state.reviver(String(key), value) : value;
|
|
1062
|
+
}
|
|
1063
|
+
function parseObject(tokens, state) {
|
|
1064
|
+
const obj = {};
|
|
1065
|
+
return parseMany(tokens, state, obj, {
|
|
1066
|
+
skip: [":", "}"],
|
|
1067
|
+
// Initially skip over colon or closing brace (for empty/tolerant cases)
|
|
1068
|
+
elementParser: parsePair,
|
|
1069
|
+
// Use parsePair to parse each key-value element
|
|
1070
|
+
elementName: "string key",
|
|
1071
|
+
// Expected element type for errors
|
|
1072
|
+
endSymbol: "}"
|
|
1073
|
+
// The closing token for an object
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
function parseArray(tokens, state) {
|
|
1077
|
+
const arr = [];
|
|
1078
|
+
return parseMany(tokens, state, arr, {
|
|
1079
|
+
skip: ["]"],
|
|
1080
|
+
// Initially skip over closing bracket (for empty/tolerant cases)
|
|
1081
|
+
elementParser: parseElement,
|
|
1082
|
+
// Use parseElement to parse each array item
|
|
1083
|
+
elementName: "json value",
|
|
1084
|
+
// Expected element type for errors
|
|
1085
|
+
endSymbol: "]"
|
|
1086
|
+
// The closing token for an array
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
function handleInvalidToken(token, state, opts, result) {
|
|
1090
|
+
raiseUnexpected(state, token, `',' or '${opts.endSymbol}'`);
|
|
1091
|
+
if (state.tolerant) {
|
|
1092
|
+
if (token.type === "eof") {
|
|
1093
|
+
return result;
|
|
1094
|
+
}
|
|
1095
|
+
state.pos -= 1;
|
|
1096
|
+
return null;
|
|
1097
|
+
}
|
|
1098
|
+
return result;
|
|
1099
|
+
}
|
|
1100
|
+
function handleCommaToken(params) {
|
|
1101
|
+
const { token, tokens, state, opts, result } = params;
|
|
1102
|
+
const nextToken = tokens[state.pos];
|
|
1103
|
+
if (state.tolerant && nextToken && nextToken.type === opts.endSymbol) {
|
|
1104
|
+
raiseError(state, token, `Trailing comma before '${opts.endSymbol}'`);
|
|
1105
|
+
popToken(tokens, state);
|
|
1106
|
+
return result;
|
|
1107
|
+
}
|
|
1108
|
+
opts.elementParser(tokens, state, result);
|
|
1109
|
+
return null;
|
|
1110
|
+
}
|
|
1111
|
+
function parseManyInitialElement(tokens, state, result, opts) {
|
|
1112
|
+
const token = skipPunctuation(tokens, state, opts.skip);
|
|
1113
|
+
if (token.type === "eof") {
|
|
1114
|
+
raiseUnexpected(state, token, `'${opts.endSymbol}' or ${opts.elementName}`);
|
|
1115
|
+
return result;
|
|
1116
|
+
}
|
|
1117
|
+
if (token.type === opts.endSymbol) {
|
|
1118
|
+
return result;
|
|
1119
|
+
}
|
|
1120
|
+
state.pos -= 1;
|
|
1121
|
+
opts.elementParser(tokens, state, result);
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
function parseManyProcessToken(params) {
|
|
1125
|
+
const { token, tokens, state, opts, result } = params;
|
|
1126
|
+
if (token.type !== opts.endSymbol && token.type !== ",") {
|
|
1127
|
+
const handledResult = handleInvalidToken(token, state, opts, result);
|
|
1128
|
+
if (handledResult !== null) {
|
|
1129
|
+
return handledResult;
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
if (token.type === opts.endSymbol) {
|
|
1133
|
+
return result;
|
|
1134
|
+
}
|
|
1135
|
+
if (token.type === ",") {
|
|
1136
|
+
const handledResult = handleCommaToken({
|
|
1137
|
+
token,
|
|
1138
|
+
tokens,
|
|
1139
|
+
state,
|
|
1140
|
+
opts,
|
|
1141
|
+
result
|
|
1142
|
+
});
|
|
1143
|
+
if (handledResult !== null) {
|
|
1144
|
+
return handledResult;
|
|
1145
|
+
}
|
|
1146
|
+
return;
|
|
1147
|
+
}
|
|
1148
|
+
opts.elementParser(tokens, state, result);
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
function parseMany(tokens, state, result, opts) {
|
|
1152
|
+
const initialResult = parseManyInitialElement(tokens, state, result, opts);
|
|
1153
|
+
if (initialResult !== void 0) {
|
|
1154
|
+
return initialResult;
|
|
1155
|
+
}
|
|
1156
|
+
while (true) {
|
|
1157
|
+
const token = popToken(tokens, state);
|
|
1158
|
+
const processedResult = parseManyProcessToken({
|
|
1159
|
+
token,
|
|
1160
|
+
tokens,
|
|
1161
|
+
state,
|
|
1162
|
+
opts,
|
|
1163
|
+
result
|
|
1164
|
+
});
|
|
1165
|
+
if (processedResult !== void 0) {
|
|
1166
|
+
return processedResult;
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
function endChecks(tokens, state, ret) {
|
|
1171
|
+
if (state.pos < tokens.length) {
|
|
1172
|
+
if (state.tolerant) {
|
|
1173
|
+
skipPunctuation(tokens, state);
|
|
1174
|
+
}
|
|
1175
|
+
if (state.pos < tokens.length) {
|
|
1176
|
+
raiseError(
|
|
1177
|
+
state,
|
|
1178
|
+
tokens[state.pos],
|
|
1179
|
+
`Unexpected token: ${strToken(tokens[state.pos])}, expected end-of-input`
|
|
1180
|
+
);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
if (state.tolerant && state.warnings.length > 0) {
|
|
1184
|
+
const message = state.warnings.length === 1 ? state.warnings[0].message : `${state.warnings.length} parse warnings`;
|
|
1185
|
+
const err = new SyntaxError(message);
|
|
1186
|
+
err.line = state.warnings[0].line;
|
|
1187
|
+
err.warnings = state.warnings;
|
|
1188
|
+
err.obj = ret;
|
|
1189
|
+
throw err;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
function parseAny(tokens, state, end = false) {
|
|
1193
|
+
const token = skipPunctuation(tokens, state);
|
|
1194
|
+
let ret;
|
|
1195
|
+
if (token.type === "eof") {
|
|
1196
|
+
if (end) {
|
|
1197
|
+
raiseUnexpected(state, token, "json value");
|
|
1198
|
+
}
|
|
1199
|
+
raiseUnexpected(state, token, "json value");
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1202
|
+
switch (token.type) {
|
|
1203
|
+
case "{":
|
|
1204
|
+
ret = parseObject(tokens, state);
|
|
1205
|
+
break;
|
|
1206
|
+
case "[":
|
|
1207
|
+
ret = parseArray(tokens, state);
|
|
1208
|
+
break;
|
|
1209
|
+
case "string":
|
|
1210
|
+
// String literal
|
|
1211
|
+
case "number":
|
|
1212
|
+
// Number literal
|
|
1213
|
+
case "atom":
|
|
1214
|
+
ret = token.value;
|
|
1215
|
+
break;
|
|
1216
|
+
default:
|
|
1217
|
+
raiseUnexpected(state, token, "json value");
|
|
1218
|
+
if (state.tolerant) {
|
|
1219
|
+
ret = null;
|
|
1220
|
+
} else {
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
if (end) {
|
|
1225
|
+
ret = state.reviver ? state.reviver("", ret) : ret;
|
|
1226
|
+
endChecks(tokens, state, ret);
|
|
1227
|
+
}
|
|
1228
|
+
return ret;
|
|
1229
|
+
}
|
|
1230
|
+
function normalizeParseOptions(optsOrReviver) {
|
|
1231
|
+
var _a;
|
|
1232
|
+
let options = {};
|
|
1233
|
+
if (typeof optsOrReviver === "function") {
|
|
1234
|
+
options.reviver = optsOrReviver;
|
|
1235
|
+
} else if (optsOrReviver !== null && typeof optsOrReviver === "object") {
|
|
1236
|
+
options = { ...optsOrReviver };
|
|
1237
|
+
} else if (optsOrReviver !== void 0) {
|
|
1238
|
+
throw new TypeError(
|
|
1239
|
+
"Second argument must be a reviver function or an options object."
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
if (options.relaxed === void 0) {
|
|
1243
|
+
if (options.warnings === true || options.tolerant === true) {
|
|
1244
|
+
options.relaxed = true;
|
|
1245
|
+
} else if (options.warnings === false && options.tolerant === false) {
|
|
1246
|
+
options.relaxed = false;
|
|
1247
|
+
} else {
|
|
1248
|
+
options.relaxed = true;
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
options.tolerant = options.tolerant || options.warnings;
|
|
1252
|
+
options.duplicate = (_a = options.duplicate) != null ? _a : false;
|
|
1253
|
+
return options;
|
|
1254
|
+
}
|
|
1255
|
+
function createParseState(options) {
|
|
1256
|
+
var _a, _b;
|
|
1257
|
+
return {
|
|
1258
|
+
pos: 0,
|
|
1259
|
+
reviver: options.reviver,
|
|
1260
|
+
tolerant: (_a = options.tolerant) != null ? _a : false,
|
|
1261
|
+
duplicate: (_b = options.duplicate) != null ? _b : false,
|
|
1262
|
+
warnings: []
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
function parseWithCustomParser(text, options) {
|
|
1266
|
+
const lexerToUse = options.relaxed ? lexer : strictLexer;
|
|
1267
|
+
let tokens = lexerToUse(text);
|
|
1268
|
+
if (options.relaxed) {
|
|
1269
|
+
tokens = stripTrailingComma(tokens);
|
|
1270
|
+
}
|
|
1271
|
+
tokens = tokens.filter((token) => token.type !== " ");
|
|
1272
|
+
const state = createParseState(options);
|
|
1273
|
+
return parseAny(tokens, state, true);
|
|
1274
|
+
}
|
|
1275
|
+
function parseWithTransform(text, options) {
|
|
1276
|
+
let tokens = lexer(text);
|
|
1277
|
+
tokens = stripTrailingComma(tokens);
|
|
1278
|
+
const newtext = tokens.reduce((str, token) => str + token.match, "");
|
|
1279
|
+
return JSON.parse(
|
|
1280
|
+
newtext,
|
|
1281
|
+
options.reviver
|
|
1282
|
+
);
|
|
1283
|
+
}
|
|
1284
|
+
function parse2(text, optsOrReviver) {
|
|
1285
|
+
const options = normalizeParseOptions(optsOrReviver);
|
|
1286
|
+
if (!(options.relaxed || options.warnings || options.tolerant) && options.duplicate) {
|
|
1287
|
+
return JSON.parse(
|
|
1288
|
+
text,
|
|
1289
|
+
options.reviver
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
if (options.warnings || options.tolerant || !options.duplicate) {
|
|
1293
|
+
return parseWithCustomParser(text, options);
|
|
1294
|
+
}
|
|
1295
|
+
return parseWithTransform(text, options);
|
|
1296
|
+
}
|
|
1297
|
+
function stringifyPair(obj, key) {
|
|
1298
|
+
return `${JSON.stringify(key)}:${stringify(obj[key])}`;
|
|
1299
|
+
}
|
|
1300
|
+
function stringify(obj) {
|
|
1301
|
+
const type = typeof obj;
|
|
1302
|
+
if (type === "string" || type === "number" || type === "boolean" || obj === null) {
|
|
1303
|
+
return JSON.stringify(obj);
|
|
1304
|
+
}
|
|
1305
|
+
if (type === "undefined") {
|
|
1306
|
+
return "null";
|
|
1307
|
+
}
|
|
1308
|
+
if (Array.isArray(obj)) {
|
|
1309
|
+
const elements = obj.map(stringify).join(",");
|
|
1310
|
+
return `[${elements}]`;
|
|
1311
|
+
}
|
|
1312
|
+
if (type === "object") {
|
|
1313
|
+
const keys = Object.keys(obj);
|
|
1314
|
+
keys.sort();
|
|
1315
|
+
const pairs = keys.map((key) => stringifyPair(obj, key)).join(",");
|
|
1316
|
+
return `{${pairs}}`;
|
|
1317
|
+
}
|
|
1318
|
+
return "null";
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
// src/core/utils/id.ts
|
|
1322
|
+
function generateId() {
|
|
1323
|
+
return Math.random().toString(36).substring(2, 15);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
// src/core/protocols/json-mix-protocol.ts
|
|
1327
|
+
function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
|
|
1328
|
+
var _a, _b;
|
|
1329
|
+
try {
|
|
1330
|
+
const parsedToolCall = parse2(toolCallJson);
|
|
1331
|
+
processedElements.push({
|
|
1332
|
+
type: "tool-call",
|
|
1333
|
+
toolCallId: generateId(),
|
|
1334
|
+
toolName: parsedToolCall.name,
|
|
1335
|
+
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1336
|
+
});
|
|
1337
|
+
} catch (error) {
|
|
1338
|
+
logParseFailure({
|
|
1339
|
+
phase: "generated-text",
|
|
1340
|
+
reason: "Failed to parse tool call JSON segment",
|
|
1341
|
+
snippet: fullMatch,
|
|
1342
|
+
error
|
|
1343
|
+
});
|
|
1344
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
1345
|
+
options,
|
|
1346
|
+
"Could not process JSON tool call, keeping original text.",
|
|
1347
|
+
{ toolCall: fullMatch, error }
|
|
1348
|
+
);
|
|
1349
|
+
processedElements.push({ type: "text", text: fullMatch });
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
function addTextSegment(text, processedElements) {
|
|
1353
|
+
if (text.trim()) {
|
|
1354
|
+
processedElements.push({ type: "text", text });
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
function processMatchedToolCall(context) {
|
|
1358
|
+
const { match, text, currentIndex, processedElements, options } = context;
|
|
1359
|
+
const startIndex = match.index;
|
|
1360
|
+
const toolCallJson = match[1];
|
|
1361
|
+
if (startIndex > currentIndex) {
|
|
1362
|
+
const textSegment = text.substring(currentIndex, startIndex);
|
|
1363
|
+
addTextSegment(textSegment, processedElements);
|
|
1364
|
+
}
|
|
1365
|
+
if (toolCallJson) {
|
|
1366
|
+
processToolCallJson(toolCallJson, match[0], processedElements, options);
|
|
1367
|
+
}
|
|
1368
|
+
return startIndex + match[0].length;
|
|
1369
|
+
}
|
|
1370
|
+
function flushBuffer(state, controller, toolCallStart) {
|
|
1371
|
+
if (state.buffer.length === 0) {
|
|
1372
|
+
return;
|
|
1373
|
+
}
|
|
1374
|
+
if (!state.currentTextId) {
|
|
1375
|
+
state.currentTextId = generateId();
|
|
1376
|
+
controller.enqueue({
|
|
1377
|
+
type: "text-start",
|
|
1378
|
+
id: state.currentTextId
|
|
1379
|
+
});
|
|
1380
|
+
state.hasEmittedTextStart = true;
|
|
1381
|
+
}
|
|
1382
|
+
const deltaContent = state.isInsideToolCall ? `${toolCallStart}${state.buffer}` : state.buffer;
|
|
1383
|
+
controller.enqueue({
|
|
1384
|
+
type: "text-delta",
|
|
1385
|
+
id: state.currentTextId,
|
|
1386
|
+
textDelta: deltaContent,
|
|
1387
|
+
delta: deltaContent
|
|
1388
|
+
});
|
|
1389
|
+
state.buffer = "";
|
|
1390
|
+
}
|
|
1391
|
+
function closeTextBlock(state, controller) {
|
|
1392
|
+
if (state.currentTextId && state.hasEmittedTextStart) {
|
|
1393
|
+
controller.enqueue({
|
|
1394
|
+
type: "text-end",
|
|
1395
|
+
id: state.currentTextId
|
|
1396
|
+
});
|
|
1397
|
+
state.currentTextId = null;
|
|
1398
|
+
state.hasEmittedTextStart = false;
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
function emitIncompleteToolCall(state, controller, toolCallStart) {
|
|
1402
|
+
if (!state.currentToolCallJson) {
|
|
1403
|
+
return;
|
|
1404
|
+
}
|
|
1405
|
+
logParseFailure({
|
|
1406
|
+
phase: "stream",
|
|
1407
|
+
reason: "Incomplete streaming tool call segment emitted as text",
|
|
1408
|
+
snippet: `${toolCallStart}${state.currentToolCallJson}`
|
|
1409
|
+
});
|
|
1410
|
+
const errorId = generateId();
|
|
1411
|
+
const errorContent = `${toolCallStart}${state.currentToolCallJson}`;
|
|
1412
|
+
controller.enqueue({
|
|
1413
|
+
type: "text-start",
|
|
1414
|
+
id: errorId
|
|
1415
|
+
});
|
|
1416
|
+
controller.enqueue({
|
|
1417
|
+
type: "text-delta",
|
|
1418
|
+
id: errorId,
|
|
1419
|
+
textDelta: errorContent,
|
|
1420
|
+
delta: errorContent
|
|
1421
|
+
});
|
|
1422
|
+
controller.enqueue({
|
|
1423
|
+
type: "text-end",
|
|
1424
|
+
id: errorId
|
|
1425
|
+
});
|
|
1426
|
+
state.currentToolCallJson = "";
|
|
1427
|
+
}
|
|
1428
|
+
function handleFinishChunk(state, controller, toolCallStart, chunk) {
|
|
1429
|
+
if (state.buffer.length > 0) {
|
|
1430
|
+
flushBuffer(state, controller, toolCallStart);
|
|
1431
|
+
}
|
|
1432
|
+
closeTextBlock(state, controller);
|
|
1433
|
+
emitIncompleteToolCall(state, controller, toolCallStart);
|
|
1434
|
+
controller.enqueue(chunk);
|
|
1435
|
+
}
|
|
1436
|
+
function publishText(text, state, controller) {
|
|
1437
|
+
if (state.isInsideToolCall) {
|
|
1438
|
+
closeTextBlock(state, controller);
|
|
1439
|
+
state.currentToolCallJson += text;
|
|
1440
|
+
} else if (text.length > 0) {
|
|
1441
|
+
if (!state.currentTextId) {
|
|
1442
|
+
state.currentTextId = generateId();
|
|
1443
|
+
controller.enqueue({
|
|
1444
|
+
type: "text-start",
|
|
1445
|
+
id: state.currentTextId
|
|
1446
|
+
});
|
|
1447
|
+
state.hasEmittedTextStart = true;
|
|
1448
|
+
}
|
|
1449
|
+
controller.enqueue({
|
|
1450
|
+
type: "text-delta",
|
|
1451
|
+
id: state.currentTextId,
|
|
1452
|
+
textDelta: text,
|
|
1453
|
+
delta: text
|
|
1454
|
+
});
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
function emitToolCall(context) {
|
|
1458
|
+
var _a, _b;
|
|
1459
|
+
const { state, controller, toolCallStart, toolCallEnd, options } = context;
|
|
1460
|
+
try {
|
|
1461
|
+
const parsedToolCall = parse2(state.currentToolCallJson);
|
|
1462
|
+
closeTextBlock(state, controller);
|
|
1463
|
+
controller.enqueue({
|
|
1464
|
+
type: "tool-call",
|
|
1465
|
+
toolCallId: generateId(),
|
|
1466
|
+
toolName: parsedToolCall.name,
|
|
1467
|
+
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1468
|
+
});
|
|
1469
|
+
} catch (error) {
|
|
1470
|
+
logParseFailure({
|
|
1471
|
+
phase: "stream",
|
|
1472
|
+
reason: "Failed to parse streaming tool call JSON segment",
|
|
1473
|
+
snippet: `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`,
|
|
1474
|
+
error
|
|
1475
|
+
});
|
|
1476
|
+
const errorId = generateId();
|
|
1477
|
+
const errorContent = `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`;
|
|
1478
|
+
controller.enqueue({
|
|
1479
|
+
type: "text-start",
|
|
1480
|
+
id: errorId
|
|
1481
|
+
});
|
|
1482
|
+
controller.enqueue({
|
|
1483
|
+
type: "text-delta",
|
|
1484
|
+
id: errorId,
|
|
1485
|
+
textDelta: errorContent,
|
|
1486
|
+
delta: errorContent
|
|
1487
|
+
});
|
|
1488
|
+
controller.enqueue({
|
|
1489
|
+
type: "text-end",
|
|
1490
|
+
id: errorId
|
|
1491
|
+
});
|
|
1492
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
1493
|
+
options,
|
|
1494
|
+
"Could not process streaming JSON tool call; emitting original text.",
|
|
1495
|
+
{
|
|
1496
|
+
toolCall: errorContent
|
|
1497
|
+
}
|
|
1498
|
+
);
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
function processTagMatch(context) {
|
|
1502
|
+
const { state } = context;
|
|
1503
|
+
if (state.isInsideToolCall) {
|
|
1504
|
+
emitToolCall(context);
|
|
1505
|
+
state.currentToolCallJson = "";
|
|
1506
|
+
state.isInsideToolCall = false;
|
|
1507
|
+
} else {
|
|
1508
|
+
state.currentToolCallJson = "";
|
|
1509
|
+
state.isInsideToolCall = true;
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
function processBufferTags(context) {
|
|
1513
|
+
const { state, controller, toolCallStart, toolCallEnd } = context;
|
|
1514
|
+
let startIndex = getPotentialStartIndex(
|
|
1515
|
+
state.buffer,
|
|
1516
|
+
state.isInsideToolCall ? toolCallEnd : toolCallStart
|
|
1517
|
+
);
|
|
1518
|
+
while (startIndex != null) {
|
|
1519
|
+
const tag = state.isInsideToolCall ? toolCallEnd : toolCallStart;
|
|
1520
|
+
if (startIndex + tag.length > state.buffer.length) {
|
|
1521
|
+
break;
|
|
1522
|
+
}
|
|
1523
|
+
publishText(state.buffer.slice(0, startIndex), state, controller);
|
|
1524
|
+
state.buffer = state.buffer.slice(startIndex + tag.length);
|
|
1525
|
+
processTagMatch(context);
|
|
1526
|
+
startIndex = getPotentialStartIndex(
|
|
1527
|
+
state.buffer,
|
|
1528
|
+
state.isInsideToolCall ? toolCallEnd : toolCallStart
|
|
1529
|
+
);
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
function handlePartialTag(state, controller, toolCallStart) {
|
|
1533
|
+
if (state.isInsideToolCall) {
|
|
1534
|
+
return;
|
|
1535
|
+
}
|
|
1536
|
+
const potentialIndex = getPotentialStartIndex(state.buffer, toolCallStart);
|
|
1537
|
+
if (potentialIndex != null && potentialIndex + toolCallStart.length > state.buffer.length) {
|
|
1538
|
+
publishText(state.buffer.slice(0, potentialIndex), state, controller);
|
|
1539
|
+
state.buffer = state.buffer.slice(potentialIndex);
|
|
1540
|
+
} else {
|
|
1541
|
+
publishText(state.buffer, state, controller);
|
|
1542
|
+
state.buffer = "";
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
var jsonMixProtocol = ({
|
|
1546
|
+
toolCallStart = "<tool_call>",
|
|
1547
|
+
toolCallEnd = "</tool_call>",
|
|
1548
|
+
toolResponseStart = "<tool_response>",
|
|
1549
|
+
toolResponseEnd = "</tool_response>"
|
|
1550
|
+
} = {}) => ({
|
|
1551
|
+
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
1552
|
+
const toolsForPrompt = (tools || []).filter((tool) => tool.type === "function").map((tool) => ({
|
|
1553
|
+
name: tool.name,
|
|
1554
|
+
description: tool.type === "function" && typeof tool.description === "string" ? tool.description : void 0,
|
|
1555
|
+
parameters: tool.inputSchema
|
|
1556
|
+
}));
|
|
1557
|
+
return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
|
|
1558
|
+
},
|
|
1559
|
+
formatToolCall(toolCall) {
|
|
1560
|
+
let args = {};
|
|
1561
|
+
try {
|
|
1562
|
+
args = JSON.parse(toolCall.input);
|
|
1563
|
+
} catch (e) {
|
|
1564
|
+
args = toolCall.input;
|
|
1565
|
+
}
|
|
1566
|
+
return `${toolCallStart}${JSON.stringify({
|
|
1567
|
+
name: toolCall.toolName,
|
|
1568
|
+
arguments: args
|
|
1569
|
+
})}${toolCallEnd}`;
|
|
1570
|
+
},
|
|
1571
|
+
formatToolResponse(toolResult) {
|
|
1572
|
+
return `${toolResponseStart}${JSON.stringify({
|
|
1573
|
+
toolName: toolResult.toolName,
|
|
1574
|
+
result: toolResult.result
|
|
1575
|
+
})}${toolResponseEnd}`;
|
|
1576
|
+
},
|
|
1577
|
+
parseGeneratedText({ text, options }) {
|
|
1578
|
+
const startEsc = escapeRegExp2(toolCallStart);
|
|
1579
|
+
const endEsc = escapeRegExp2(toolCallEnd);
|
|
1580
|
+
const toolCallRegex = new RegExp(
|
|
1581
|
+
`${startEsc}([\0-\uFFFF]*?)${endEsc}`,
|
|
1582
|
+
"gs"
|
|
1583
|
+
);
|
|
1584
|
+
const processedElements = [];
|
|
1585
|
+
let currentIndex = 0;
|
|
1586
|
+
let match = toolCallRegex.exec(text);
|
|
1587
|
+
while (match !== null) {
|
|
1588
|
+
currentIndex = processMatchedToolCall({
|
|
1589
|
+
match,
|
|
1590
|
+
text,
|
|
1591
|
+
currentIndex,
|
|
1592
|
+
processedElements,
|
|
1593
|
+
options
|
|
1594
|
+
});
|
|
1595
|
+
match = toolCallRegex.exec(text);
|
|
1596
|
+
}
|
|
1597
|
+
if (currentIndex < text.length) {
|
|
1598
|
+
const remainingText = text.substring(currentIndex);
|
|
1599
|
+
addTextSegment(remainingText, processedElements);
|
|
1600
|
+
}
|
|
1601
|
+
return processedElements;
|
|
1602
|
+
},
|
|
1603
|
+
createStreamParser({ options }) {
|
|
1604
|
+
const state = {
|
|
1605
|
+
isInsideToolCall: false,
|
|
1606
|
+
buffer: "",
|
|
1607
|
+
currentToolCallJson: "",
|
|
1608
|
+
currentTextId: null,
|
|
1609
|
+
hasEmittedTextStart: false
|
|
1610
|
+
};
|
|
1611
|
+
return new TransformStream({
|
|
1612
|
+
transform(chunk, controller) {
|
|
1613
|
+
var _a, _b;
|
|
1614
|
+
if (chunk.type === "finish") {
|
|
1615
|
+
handleFinishChunk(state, controller, toolCallStart, chunk);
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
if (chunk.type !== "text-delta") {
|
|
1619
|
+
controller.enqueue(chunk);
|
|
1620
|
+
return;
|
|
1621
|
+
}
|
|
1622
|
+
const textContent = (_b = (_a = chunk.textDelta) != null ? _a : chunk.delta) != null ? _b : "";
|
|
1623
|
+
state.buffer += textContent;
|
|
1624
|
+
processBufferTags({
|
|
1625
|
+
state,
|
|
1626
|
+
controller,
|
|
1627
|
+
toolCallStart,
|
|
1628
|
+
toolCallEnd,
|
|
1629
|
+
options
|
|
1630
|
+
});
|
|
1631
|
+
handlePartialTag(state, controller, toolCallStart);
|
|
1632
|
+
}
|
|
1633
|
+
});
|
|
1634
|
+
},
|
|
1635
|
+
extractToolCallSegments({ text }) {
|
|
1636
|
+
const startEsc = escapeRegExp2(toolCallStart);
|
|
1637
|
+
const endEsc = escapeRegExp2(toolCallEnd);
|
|
1638
|
+
const regex = new RegExp(`${startEsc}([\0-\uFFFF]*?)${endEsc}`, "gs");
|
|
1639
|
+
const segments = [];
|
|
1640
|
+
let m = regex.exec(text);
|
|
1641
|
+
while (m != null) {
|
|
1642
|
+
segments.push(m[0]);
|
|
1643
|
+
m = regex.exec(text);
|
|
1644
|
+
}
|
|
1645
|
+
return segments;
|
|
1646
|
+
}
|
|
1647
|
+
});
|
|
1648
|
+
|
|
1649
|
+
// src/core/protocols/morph-xml-protocol.ts
|
|
1650
|
+
import {
|
|
1651
|
+
extractRawInner,
|
|
1652
|
+
parse as parse3,
|
|
1653
|
+
stringify as stringify2,
|
|
1654
|
+
unwrapJsonSchema as unwrapJsonSchema2
|
|
1655
|
+
} from "@ai-sdk-tool/rxml";
|
|
1656
|
+
var defaultPipelineConfig2 = defaultPipelineConfig;
|
|
1657
|
+
var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
|
|
1658
|
+
var WHITESPACE_REGEX3 = /\s/;
|
|
1659
|
+
function getToolSchema(tools, toolName) {
|
|
1660
|
+
var _a;
|
|
1661
|
+
return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
1662
|
+
}
|
|
1663
|
+
function normalizeCloseTags(xml) {
|
|
1664
|
+
return xml.replace(/<\/\s+([A-Za-z0-9_:-]+)\s*>/g, "</$1>");
|
|
1665
|
+
}
|
|
1666
|
+
function tryParseSecondaryXml(content, toolSchema, options) {
|
|
1667
|
+
const balanced = balanceTags(content);
|
|
1668
|
+
try {
|
|
1669
|
+
let parsed = parse3(balanced, toolSchema, {
|
|
1670
|
+
onError: options == null ? void 0 : options.onError,
|
|
1671
|
+
noChildNodes: []
|
|
1672
|
+
});
|
|
1673
|
+
parsed = repairParsedAgainstSchema(parsed, toolSchema);
|
|
1674
|
+
return parsed;
|
|
1675
|
+
} catch (e) {
|
|
1676
|
+
if (shouldDeduplicateStringTags(toolSchema)) {
|
|
1677
|
+
const names = getStringPropertyNames(toolSchema);
|
|
1678
|
+
let deduped = balanced;
|
|
1679
|
+
for (const key of names) {
|
|
1680
|
+
deduped = dedupeSingleTag(deduped, key);
|
|
1681
|
+
}
|
|
1682
|
+
if (deduped !== balanced) {
|
|
1683
|
+
try {
|
|
1684
|
+
let reparsed = parse3(deduped, toolSchema, {
|
|
1685
|
+
onError: options == null ? void 0 : options.onError,
|
|
1686
|
+
noChildNodes: []
|
|
1687
|
+
});
|
|
1688
|
+
reparsed = repairParsedAgainstSchema(reparsed, toolSchema);
|
|
1689
|
+
return reparsed;
|
|
1690
|
+
} catch (e2) {
|
|
1691
|
+
return null;
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
return null;
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
function processToolCallWithPipeline(params) {
|
|
1699
|
+
var _a;
|
|
1700
|
+
const {
|
|
1701
|
+
toolCall,
|
|
1702
|
+
tools,
|
|
1703
|
+
options,
|
|
1704
|
+
text,
|
|
1705
|
+
processedElements,
|
|
1706
|
+
pipelineConfig = defaultPipelineConfig2,
|
|
1707
|
+
maxReparses
|
|
1708
|
+
} = params;
|
|
1709
|
+
const toolSchema = getToolSchema(tools, toolCall.toolName);
|
|
1710
|
+
const ctx = createIntermediateCall(
|
|
1711
|
+
toolCall.toolName,
|
|
1712
|
+
toolCall.content,
|
|
1713
|
+
toolSchema
|
|
1714
|
+
);
|
|
1715
|
+
const result = applyHeuristicPipeline(ctx, pipelineConfig, {
|
|
1716
|
+
parse: (xml, schema) => parse3(xml, schema, { onError: options == null ? void 0 : options.onError, noChildNodes: [] }),
|
|
1717
|
+
onError: options == null ? void 0 : options.onError,
|
|
1718
|
+
maxReparses
|
|
1719
|
+
});
|
|
1720
|
+
if (result.parsed !== null) {
|
|
1721
|
+
processedElements.push({
|
|
1722
|
+
type: "tool-call",
|
|
1723
|
+
toolCallId: generateId(),
|
|
1724
|
+
toolName: toolCall.toolName,
|
|
1725
|
+
input: JSON.stringify(result.parsed)
|
|
1726
|
+
});
|
|
1727
|
+
} else {
|
|
1728
|
+
const originalCallText = text.substring(
|
|
1729
|
+
toolCall.startIndex,
|
|
1730
|
+
toolCall.endIndex
|
|
1731
|
+
);
|
|
1732
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1733
|
+
options,
|
|
1734
|
+
`Could not process XML tool call: ${toolCall.toolName}`,
|
|
1735
|
+
{ toolCall: originalCallText, error: result.errors[0] }
|
|
1736
|
+
);
|
|
1737
|
+
processedElements.push({ type: "text", text: originalCallText });
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
function handleStreamingToolCallEnd(params) {
|
|
1741
|
+
var _a;
|
|
1742
|
+
const {
|
|
1743
|
+
toolContent,
|
|
1744
|
+
currentToolCall,
|
|
1745
|
+
tools,
|
|
1746
|
+
options,
|
|
1747
|
+
ctrl,
|
|
1748
|
+
flushText,
|
|
1749
|
+
pipelineConfig,
|
|
1750
|
+
maxReparses
|
|
1751
|
+
} = params;
|
|
1752
|
+
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
1753
|
+
let parsedResult = null;
|
|
1754
|
+
if (pipelineConfig) {
|
|
1755
|
+
const ctx = createIntermediateCall(
|
|
1756
|
+
currentToolCall.name,
|
|
1757
|
+
toolContent,
|
|
1758
|
+
toolSchema
|
|
1759
|
+
);
|
|
1760
|
+
const result = applyHeuristicPipeline(ctx, pipelineConfig, {
|
|
1761
|
+
parse: (xml, schema) => parse3(xml, schema, { onError: options == null ? void 0 : options.onError, noChildNodes: [] }),
|
|
1762
|
+
onError: options == null ? void 0 : options.onError,
|
|
1763
|
+
maxReparses
|
|
1764
|
+
});
|
|
1765
|
+
parsedResult = result.parsed;
|
|
1766
|
+
} else {
|
|
1767
|
+
try {
|
|
1768
|
+
const primary = escapeInvalidLt(normalizeCloseTags(toolContent));
|
|
1769
|
+
const parsed = parse3(primary, toolSchema, {
|
|
1770
|
+
onError: options == null ? void 0 : options.onError,
|
|
1771
|
+
noChildNodes: []
|
|
1772
|
+
});
|
|
1773
|
+
parsedResult = repairParsedAgainstSchema(parsed, toolSchema);
|
|
1774
|
+
} catch (e) {
|
|
1775
|
+
parsedResult = tryParseSecondaryXml(
|
|
1776
|
+
toolContent,
|
|
1777
|
+
toolSchema,
|
|
1778
|
+
options != null ? options : {}
|
|
1779
|
+
);
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
flushText(ctrl);
|
|
1783
|
+
if (parsedResult !== null) {
|
|
1784
|
+
ctrl.enqueue({
|
|
1785
|
+
type: "tool-call",
|
|
1786
|
+
toolCallId: generateId(),
|
|
1787
|
+
toolName: currentToolCall.name,
|
|
1788
|
+
input: JSON.stringify(parsedResult)
|
|
1789
|
+
});
|
|
1790
|
+
} else {
|
|
1791
|
+
const original = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
|
|
1792
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not process streaming XML tool call", {
|
|
1793
|
+
toolCall: original
|
|
1794
|
+
});
|
|
1795
|
+
flushText(ctrl, original);
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
function findClosingTagEndFlexible(text, contentStart, toolName) {
|
|
1799
|
+
let pos = contentStart;
|
|
1800
|
+
let depth = 1;
|
|
1801
|
+
while (pos < text.length) {
|
|
1802
|
+
const tok = nextTagToken(text, pos);
|
|
1803
|
+
if (tok.kind === "eof") {
|
|
1804
|
+
break;
|
|
1805
|
+
}
|
|
1806
|
+
const result = updateDepthWithToken(tok, toolName, depth);
|
|
1807
|
+
depth = result.depth;
|
|
1808
|
+
if (result.closedAt !== void 0) {
|
|
1809
|
+
return result.closedAt;
|
|
1810
|
+
}
|
|
1811
|
+
pos = tok.nextPos;
|
|
1812
|
+
}
|
|
1813
|
+
return -1;
|
|
1814
|
+
}
|
|
1815
|
+
function skipSpecialSegment(text, lt) {
|
|
1816
|
+
const next = text[lt + 1];
|
|
1817
|
+
if (next === "!" || next === "?") {
|
|
1818
|
+
const gt = text.indexOf(">", lt + 1);
|
|
1819
|
+
if (gt !== -1) {
|
|
1820
|
+
return gt + 1;
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
return null;
|
|
1824
|
+
}
|
|
1825
|
+
function consumeClosingTag(text, lt) {
|
|
1826
|
+
const gt = text.indexOf(">", lt + 1);
|
|
1827
|
+
const endPos = gt === -1 ? text.length : gt + 1;
|
|
1828
|
+
return { matched: false, endPos };
|
|
1829
|
+
}
|
|
1830
|
+
function consumeOpenTag(text, lt) {
|
|
1831
|
+
let p = lt + 1;
|
|
1832
|
+
while (p < text.length && WHITESPACE_REGEX3.test(text[p])) {
|
|
1833
|
+
p += 1;
|
|
1834
|
+
}
|
|
1835
|
+
const nameStart = p;
|
|
1836
|
+
while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
|
|
1837
|
+
p += 1;
|
|
1838
|
+
}
|
|
1839
|
+
const name = text.slice(nameStart, p);
|
|
1840
|
+
const q = text.indexOf(">", p);
|
|
1841
|
+
if (q === -1) {
|
|
1842
|
+
return null;
|
|
1843
|
+
}
|
|
1844
|
+
let r = q - 1;
|
|
1845
|
+
while (r >= nameStart && WHITESPACE_REGEX3.test(text[r])) {
|
|
1846
|
+
r -= 1;
|
|
1847
|
+
}
|
|
1848
|
+
const selfClosing = text[r] === "/";
|
|
1849
|
+
return { name, selfClosing, nextPos: q + 1 };
|
|
1850
|
+
}
|
|
1851
|
+
function updateDepthWithToken(tok, toolName, depth) {
|
|
1852
|
+
if (tok.kind === "close" && tok.name === toolName) {
|
|
1853
|
+
const newDepth = depth - 1;
|
|
1854
|
+
return newDepth === 0 ? { depth: newDepth, closedAt: tok.nextPos } : { depth: newDepth };
|
|
1855
|
+
}
|
|
1856
|
+
if (tok.kind === "open" && tok.name === toolName && !tok.selfClosing) {
|
|
1857
|
+
return { depth: depth + 1 };
|
|
1858
|
+
}
|
|
1859
|
+
return { depth };
|
|
1860
|
+
}
|
|
1861
|
+
function nextTagToken(text, fromPos) {
|
|
1862
|
+
const lt = text.indexOf("<", fromPos);
|
|
1863
|
+
if (lt === -1 || lt + 1 >= text.length) {
|
|
1864
|
+
return { kind: "eof", nextPos: text.length };
|
|
1865
|
+
}
|
|
1866
|
+
const next = text[lt + 1];
|
|
1867
|
+
const specialEnd = skipSpecialSegment(text, lt);
|
|
1868
|
+
if (specialEnd !== null) {
|
|
1869
|
+
return { kind: "special", nextPos: specialEnd };
|
|
1870
|
+
}
|
|
1871
|
+
if (next === "/") {
|
|
1872
|
+
const closing = consumeClosingTag(text, lt);
|
|
1873
|
+
let p = lt + 2;
|
|
1874
|
+
while (p < text.length && WHITESPACE_REGEX3.test(text[p])) {
|
|
1875
|
+
p += 1;
|
|
1876
|
+
}
|
|
1877
|
+
const nameStart = p;
|
|
1878
|
+
while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
|
|
1879
|
+
p += 1;
|
|
1880
|
+
}
|
|
1881
|
+
const name = text.slice(nameStart, p);
|
|
1882
|
+
return { kind: "close", name, nextPos: closing.endPos };
|
|
1883
|
+
}
|
|
1884
|
+
const open = consumeOpenTag(text, lt);
|
|
1885
|
+
if (open === null) {
|
|
1886
|
+
return { kind: "eof", nextPos: text.length };
|
|
1887
|
+
}
|
|
1888
|
+
return {
|
|
1889
|
+
kind: "open",
|
|
1890
|
+
name: open.name,
|
|
1891
|
+
selfClosing: open.selfClosing,
|
|
1892
|
+
nextPos: open.nextPos
|
|
1893
|
+
};
|
|
1894
|
+
}
|
|
1895
|
+
function findToolCallsForName(text, toolName) {
|
|
1896
|
+
var _a;
|
|
1897
|
+
const toolCalls = [];
|
|
1898
|
+
let searchIndex = 0;
|
|
1899
|
+
while (searchIndex < text.length) {
|
|
1900
|
+
const startTag = `<${toolName}>`;
|
|
1901
|
+
const selfTag = `<${toolName}/>`;
|
|
1902
|
+
const openIdx = text.indexOf(startTag, searchIndex);
|
|
1903
|
+
const selfIdx = text.indexOf(selfTag, searchIndex);
|
|
1904
|
+
if (openIdx === -1 && selfIdx === -1) {
|
|
1905
|
+
break;
|
|
1906
|
+
}
|
|
1907
|
+
const tagStart = selfIdx !== -1 && (openIdx === -1 || selfIdx < openIdx) ? selfIdx : openIdx;
|
|
1908
|
+
const isSelfClosing = tagStart === selfIdx;
|
|
1909
|
+
if (isSelfClosing) {
|
|
1910
|
+
const endIndex = tagStart + selfTag.length;
|
|
1911
|
+
const segment = text.substring(tagStart, endIndex);
|
|
1912
|
+
toolCalls.push({
|
|
1913
|
+
toolName,
|
|
1914
|
+
startIndex: tagStart,
|
|
1915
|
+
endIndex,
|
|
1916
|
+
content: "",
|
|
1917
|
+
segment
|
|
1918
|
+
});
|
|
1919
|
+
searchIndex = endIndex;
|
|
1920
|
+
continue;
|
|
1921
|
+
}
|
|
1922
|
+
const contentStart = tagStart + startTag.length;
|
|
1923
|
+
const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
|
|
1924
|
+
if (fullTagEnd !== -1 && fullTagEnd > contentStart) {
|
|
1925
|
+
const segment = text.substring(tagStart, fullTagEnd);
|
|
1926
|
+
const inner = (_a = extractRawInner(segment, toolName)) != null ? _a : segment.substring(startTag.length, segment.lastIndexOf("<"));
|
|
1927
|
+
toolCalls.push({
|
|
1928
|
+
toolName,
|
|
1929
|
+
startIndex: tagStart,
|
|
1930
|
+
endIndex: fullTagEnd,
|
|
1931
|
+
content: inner,
|
|
1932
|
+
segment
|
|
1933
|
+
});
|
|
1934
|
+
searchIndex = fullTagEnd;
|
|
1935
|
+
} else {
|
|
1936
|
+
searchIndex = contentStart;
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
return toolCalls;
|
|
1940
|
+
}
|
|
1941
|
+
function findToolCalls(text, toolNames) {
|
|
1942
|
+
const toolCalls = [];
|
|
1943
|
+
for (const toolName of toolNames) {
|
|
1944
|
+
const calls = findToolCallsForName(text, toolName);
|
|
1945
|
+
toolCalls.push(...calls);
|
|
1946
|
+
}
|
|
1947
|
+
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
1948
|
+
}
|
|
1949
|
+
function findEarliestToolTag(buffer, toolNames) {
|
|
1950
|
+
let bestIndex = -1;
|
|
1951
|
+
let bestName = "";
|
|
1952
|
+
let bestSelfClosing = false;
|
|
1953
|
+
if (toolNames.length > 0) {
|
|
1954
|
+
for (const name of toolNames) {
|
|
1955
|
+
const openTag = `<${name}>`;
|
|
1956
|
+
const selfTag = `<${name}/>`;
|
|
1957
|
+
const idxOpen = buffer.indexOf(openTag);
|
|
1958
|
+
const idxSelf = buffer.indexOf(selfTag);
|
|
1959
|
+
if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
|
|
1960
|
+
bestIndex = idxOpen;
|
|
1961
|
+
bestName = name;
|
|
1962
|
+
bestSelfClosing = false;
|
|
1963
|
+
}
|
|
1964
|
+
if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
|
|
1965
|
+
bestIndex = idxSelf;
|
|
1966
|
+
bestName = name;
|
|
1967
|
+
bestSelfClosing = true;
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
return { index: bestIndex, name: bestName, selfClosing: bestSelfClosing };
|
|
1972
|
+
}
|
|
1973
|
+
function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
1974
|
+
return (controller, text) => {
|
|
1975
|
+
const content = text;
|
|
1976
|
+
if (content) {
|
|
1977
|
+
if (!getCurrentTextId()) {
|
|
1978
|
+
const newId = generateId();
|
|
1979
|
+
setCurrentTextId(newId);
|
|
1980
|
+
controller.enqueue({
|
|
1981
|
+
type: "text-start",
|
|
1982
|
+
id: newId
|
|
1983
|
+
});
|
|
1984
|
+
setHasEmittedTextStart(true);
|
|
1985
|
+
}
|
|
1986
|
+
controller.enqueue({
|
|
1987
|
+
type: "text-delta",
|
|
1988
|
+
id: getCurrentTextId(),
|
|
1989
|
+
textDelta: content,
|
|
1990
|
+
delta: content
|
|
1991
|
+
});
|
|
1992
|
+
}
|
|
1993
|
+
const currentTextId = getCurrentTextId();
|
|
1994
|
+
if (currentTextId && !text) {
|
|
1995
|
+
if (getHasEmittedTextStart()) {
|
|
1996
|
+
controller.enqueue({
|
|
1997
|
+
type: "text-end",
|
|
1998
|
+
id: currentTextId
|
|
1999
|
+
});
|
|
2000
|
+
setHasEmittedTextStart(false);
|
|
2001
|
+
}
|
|
2002
|
+
setCurrentTextId(null);
|
|
2003
|
+
}
|
|
2004
|
+
};
|
|
2005
|
+
}
|
|
2006
|
+
function processToolCallInBuffer(params) {
|
|
2007
|
+
const {
|
|
2008
|
+
buffer,
|
|
2009
|
+
currentToolCall,
|
|
2010
|
+
tools,
|
|
2011
|
+
options,
|
|
2012
|
+
controller,
|
|
2013
|
+
flushText,
|
|
2014
|
+
setBuffer,
|
|
2015
|
+
pipelineConfig,
|
|
2016
|
+
maxReparses
|
|
2017
|
+
} = params;
|
|
2018
|
+
const endTag = `</${currentToolCall.name}>`;
|
|
2019
|
+
const endIdx = buffer.indexOf(endTag);
|
|
2020
|
+
if (endIdx === -1) {
|
|
2021
|
+
return { buffer, currentToolCall, shouldBreak: true };
|
|
2022
|
+
}
|
|
2023
|
+
const content = buffer.substring(0, endIdx);
|
|
2024
|
+
setBuffer(buffer.substring(endIdx + endTag.length));
|
|
2025
|
+
handleStreamingToolCallEnd({
|
|
2026
|
+
toolContent: content,
|
|
2027
|
+
currentToolCall,
|
|
2028
|
+
tools,
|
|
2029
|
+
options,
|
|
2030
|
+
ctrl: controller,
|
|
2031
|
+
flushText,
|
|
2032
|
+
pipelineConfig,
|
|
2033
|
+
maxReparses
|
|
2034
|
+
});
|
|
2035
|
+
return {
|
|
2036
|
+
buffer: buffer.substring(endIdx + endTag.length),
|
|
2037
|
+
currentToolCall: null,
|
|
2038
|
+
shouldBreak: false
|
|
2039
|
+
};
|
|
2040
|
+
}
|
|
2041
|
+
function processNoToolCallInBuffer(params) {
|
|
2042
|
+
const {
|
|
2043
|
+
buffer,
|
|
2044
|
+
toolNames,
|
|
2045
|
+
controller,
|
|
2046
|
+
flushText,
|
|
2047
|
+
tools,
|
|
2048
|
+
options,
|
|
2049
|
+
pipelineConfig,
|
|
2050
|
+
maxReparses,
|
|
2051
|
+
setBuffer
|
|
2052
|
+
} = params;
|
|
2053
|
+
const {
|
|
2054
|
+
index: earliestStartTagIndex,
|
|
2055
|
+
name: earliestToolName,
|
|
2056
|
+
selfClosing
|
|
2057
|
+
} = findEarliestToolTag(buffer, toolNames);
|
|
2058
|
+
if (earliestStartTagIndex === -1) {
|
|
2059
|
+
const maxTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n}>`.length)) : 0;
|
|
2060
|
+
const tail = Math.max(0, maxTagLen - 1);
|
|
2061
|
+
const safeLen = Math.max(0, buffer.length - tail);
|
|
2062
|
+
if (safeLen > 0) {
|
|
2063
|
+
flushText(controller, buffer.slice(0, safeLen));
|
|
2064
|
+
setBuffer(buffer.slice(safeLen));
|
|
2065
|
+
}
|
|
2066
|
+
return {
|
|
2067
|
+
buffer: buffer.slice(safeLen),
|
|
2068
|
+
currentToolCall: null,
|
|
2069
|
+
shouldBreak: true,
|
|
2070
|
+
shouldContinue: false
|
|
2071
|
+
};
|
|
2072
|
+
}
|
|
2073
|
+
flushText(controller, buffer.substring(0, earliestStartTagIndex));
|
|
2074
|
+
if (selfClosing) {
|
|
2075
|
+
const selfTag = `<${earliestToolName}/>`;
|
|
2076
|
+
const newBuffer2 = buffer.substring(earliestStartTagIndex + selfTag.length);
|
|
2077
|
+
setBuffer(newBuffer2);
|
|
2078
|
+
handleStreamingToolCallEnd({
|
|
2079
|
+
toolContent: "",
|
|
2080
|
+
currentToolCall: { name: earliestToolName, content: "" },
|
|
2081
|
+
tools,
|
|
2082
|
+
options,
|
|
2083
|
+
ctrl: controller,
|
|
2084
|
+
flushText,
|
|
2085
|
+
pipelineConfig,
|
|
2086
|
+
maxReparses
|
|
2087
|
+
});
|
|
2088
|
+
return {
|
|
2089
|
+
buffer: newBuffer2,
|
|
2090
|
+
currentToolCall: null,
|
|
2091
|
+
shouldBreak: false,
|
|
2092
|
+
shouldContinue: false
|
|
2093
|
+
};
|
|
2094
|
+
}
|
|
2095
|
+
const startTag = `<${earliestToolName}>`;
|
|
2096
|
+
const newBuffer = buffer.substring(earliestStartTagIndex + startTag.length);
|
|
2097
|
+
setBuffer(newBuffer);
|
|
2098
|
+
return {
|
|
2099
|
+
buffer: newBuffer,
|
|
2100
|
+
currentToolCall: { name: earliestToolName, content: "" },
|
|
2101
|
+
shouldBreak: false,
|
|
2102
|
+
shouldContinue: true
|
|
2103
|
+
};
|
|
2104
|
+
}
|
|
2105
|
+
function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, pipelineConfig, maxReparses) {
|
|
2106
|
+
return (controller) => {
|
|
2107
|
+
while (true) {
|
|
2108
|
+
const currentToolCall = getCurrentToolCall();
|
|
2109
|
+
if (currentToolCall) {
|
|
2110
|
+
const result = processToolCallInBuffer({
|
|
2111
|
+
buffer: getBuffer(),
|
|
2112
|
+
currentToolCall,
|
|
2113
|
+
tools,
|
|
2114
|
+
options,
|
|
2115
|
+
controller,
|
|
2116
|
+
flushText,
|
|
2117
|
+
setBuffer,
|
|
2118
|
+
pipelineConfig,
|
|
2119
|
+
maxReparses
|
|
2120
|
+
});
|
|
2121
|
+
setBuffer(result.buffer);
|
|
2122
|
+
setCurrentToolCall(result.currentToolCall);
|
|
2123
|
+
if (result.shouldBreak) {
|
|
2124
|
+
break;
|
|
2125
|
+
}
|
|
2126
|
+
} else {
|
|
2127
|
+
const result = processNoToolCallInBuffer({
|
|
2128
|
+
buffer: getBuffer(),
|
|
2129
|
+
toolNames,
|
|
2130
|
+
controller,
|
|
2131
|
+
flushText,
|
|
2132
|
+
tools,
|
|
2133
|
+
options,
|
|
2134
|
+
pipelineConfig,
|
|
2135
|
+
maxReparses,
|
|
2136
|
+
setBuffer
|
|
2137
|
+
});
|
|
2138
|
+
setBuffer(result.buffer);
|
|
2139
|
+
setCurrentToolCall(result.currentToolCall);
|
|
2140
|
+
if (result.shouldBreak) {
|
|
2141
|
+
break;
|
|
2142
|
+
}
|
|
2143
|
+
if (result.shouldContinue) {
|
|
2144
|
+
continue;
|
|
2145
|
+
}
|
|
2146
|
+
break;
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
};
|
|
2150
|
+
}
|
|
2151
|
+
var morphXmlProtocol = (protocolOptions) => {
|
|
2152
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
2153
|
+
let pipelineConfig = protocolOptions == null ? void 0 : protocolOptions.pipeline;
|
|
2154
|
+
const maxReparses = protocolOptions == null ? void 0 : protocolOptions.maxReparses;
|
|
2155
|
+
if ((protocolOptions == null ? void 0 : protocolOptions.heuristics) && protocolOptions.heuristics.length > 0) {
|
|
2156
|
+
const heuristicsConfig = {
|
|
2157
|
+
preParse: [],
|
|
2158
|
+
fallbackReparse: [],
|
|
2159
|
+
postParse: []
|
|
2160
|
+
};
|
|
2161
|
+
for (const h of protocolOptions.heuristics) {
|
|
2162
|
+
if (h.phase === "pre-parse") {
|
|
2163
|
+
(_a = heuristicsConfig.preParse) == null ? void 0 : _a.push(h);
|
|
2164
|
+
} else if (h.phase === "fallback-reparse") {
|
|
2165
|
+
(_b = heuristicsConfig.fallbackReparse) == null ? void 0 : _b.push(h);
|
|
2166
|
+
} else if (h.phase === "post-parse") {
|
|
2167
|
+
(_c = heuristicsConfig.postParse) == null ? void 0 : _c.push(h);
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
if (pipelineConfig) {
|
|
2171
|
+
pipelineConfig = {
|
|
2172
|
+
preParse: [
|
|
2173
|
+
...(_d = pipelineConfig.preParse) != null ? _d : [],
|
|
2174
|
+
...(_e = heuristicsConfig.preParse) != null ? _e : []
|
|
2175
|
+
],
|
|
2176
|
+
fallbackReparse: [
|
|
2177
|
+
...(_f = pipelineConfig.fallbackReparse) != null ? _f : [],
|
|
2178
|
+
...(_g = heuristicsConfig.fallbackReparse) != null ? _g : []
|
|
2179
|
+
],
|
|
2180
|
+
postParse: [
|
|
2181
|
+
...(_h = pipelineConfig.postParse) != null ? _h : [],
|
|
2182
|
+
...(_i = heuristicsConfig.postParse) != null ? _i : []
|
|
2183
|
+
]
|
|
2184
|
+
};
|
|
2185
|
+
} else {
|
|
2186
|
+
pipelineConfig = heuristicsConfig;
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
return {
|
|
2190
|
+
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
2191
|
+
const toolsForPrompt = (tools || []).map((tool) => ({
|
|
2192
|
+
name: tool.name,
|
|
2193
|
+
description: tool.description,
|
|
2194
|
+
parameters: unwrapJsonSchema2(tool.inputSchema)
|
|
2195
|
+
}));
|
|
2196
|
+
return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
|
|
2197
|
+
},
|
|
2198
|
+
formatToolCall(toolCall) {
|
|
2199
|
+
let args = {};
|
|
2200
|
+
try {
|
|
2201
|
+
args = JSON.parse(toolCall.input);
|
|
2202
|
+
} catch (e) {
|
|
2203
|
+
args = toolCall.input;
|
|
2204
|
+
}
|
|
2205
|
+
return stringify2(toolCall.toolName, args, {
|
|
2206
|
+
suppressEmptyNode: false,
|
|
2207
|
+
format: false
|
|
2208
|
+
});
|
|
2209
|
+
},
|
|
2210
|
+
formatToolResponse(toolResult) {
|
|
2211
|
+
let result = toolResult.result;
|
|
2212
|
+
if (result && typeof result === "object" && "type" in result && result.type === "json" && "value" in result) {
|
|
2213
|
+
result = result.value;
|
|
2214
|
+
}
|
|
2215
|
+
const xml = stringify2(
|
|
2216
|
+
"tool_response",
|
|
2217
|
+
{
|
|
2218
|
+
tool_name: toolResult.toolName,
|
|
2219
|
+
result
|
|
2220
|
+
},
|
|
2221
|
+
{ declaration: false }
|
|
2222
|
+
);
|
|
2223
|
+
return xml;
|
|
2224
|
+
},
|
|
2225
|
+
parseGeneratedText({ text, tools, options }) {
|
|
2226
|
+
const toolNames = tools.map((t) => t.name).filter(Boolean);
|
|
2227
|
+
if (toolNames.length === 0) {
|
|
2228
|
+
return [{ type: "text", text }];
|
|
2229
|
+
}
|
|
2230
|
+
const processedElements = [];
|
|
2231
|
+
let currentIndex = 0;
|
|
2232
|
+
const toolCalls = findToolCalls(text, toolNames);
|
|
2233
|
+
for (const tc of toolCalls) {
|
|
2234
|
+
if (tc.startIndex > currentIndex) {
|
|
2235
|
+
processedElements.push({
|
|
2236
|
+
type: "text",
|
|
2237
|
+
text: text.substring(currentIndex, tc.startIndex)
|
|
2238
|
+
});
|
|
2239
|
+
}
|
|
2240
|
+
processToolCallWithPipeline({
|
|
2241
|
+
toolCall: tc,
|
|
2242
|
+
tools,
|
|
2243
|
+
options,
|
|
2244
|
+
text,
|
|
2245
|
+
processedElements,
|
|
2246
|
+
pipelineConfig,
|
|
2247
|
+
maxReparses
|
|
2248
|
+
});
|
|
2249
|
+
currentIndex = tc.endIndex;
|
|
2250
|
+
}
|
|
2251
|
+
if (currentIndex < text.length) {
|
|
2252
|
+
processedElements.push({
|
|
2253
|
+
type: "text",
|
|
2254
|
+
text: text.substring(currentIndex)
|
|
2255
|
+
});
|
|
2256
|
+
}
|
|
2257
|
+
return processedElements;
|
|
2258
|
+
},
|
|
2259
|
+
createStreamParser({ tools, options }) {
|
|
2260
|
+
const toolNames = tools.map((t) => t.name).filter(Boolean);
|
|
2261
|
+
let buffer = "";
|
|
2262
|
+
let currentToolCall = null;
|
|
2263
|
+
let currentTextId = null;
|
|
2264
|
+
let hasEmittedTextStart = false;
|
|
2265
|
+
const flushText = createFlushTextHandler(
|
|
2266
|
+
() => currentTextId,
|
|
2267
|
+
(newId) => {
|
|
2268
|
+
currentTextId = newId;
|
|
2269
|
+
},
|
|
2270
|
+
() => hasEmittedTextStart,
|
|
2271
|
+
(value) => {
|
|
2272
|
+
hasEmittedTextStart = value;
|
|
2273
|
+
}
|
|
2274
|
+
);
|
|
2275
|
+
const processBuffer = createProcessBufferHandler(
|
|
2276
|
+
() => buffer,
|
|
2277
|
+
(newBuffer) => {
|
|
2278
|
+
buffer = newBuffer;
|
|
2279
|
+
},
|
|
2280
|
+
() => currentToolCall,
|
|
2281
|
+
(newToolCall) => {
|
|
2282
|
+
currentToolCall = newToolCall;
|
|
2283
|
+
},
|
|
2284
|
+
tools,
|
|
2285
|
+
options,
|
|
2286
|
+
toolNames,
|
|
2287
|
+
flushText,
|
|
2288
|
+
pipelineConfig,
|
|
2289
|
+
maxReparses
|
|
2290
|
+
);
|
|
2291
|
+
return new TransformStream({
|
|
2292
|
+
transform(chunk, controller) {
|
|
2293
|
+
var _a2, _b2;
|
|
2294
|
+
if (chunk.type !== "text-delta") {
|
|
2295
|
+
if (buffer) {
|
|
2296
|
+
flushText(controller, buffer);
|
|
2297
|
+
buffer = "";
|
|
2298
|
+
}
|
|
2299
|
+
controller.enqueue(chunk);
|
|
2300
|
+
return;
|
|
2301
|
+
}
|
|
2302
|
+
const textContent = (_b2 = (_a2 = chunk.textDelta) != null ? _a2 : chunk.delta) != null ? _b2 : "";
|
|
2303
|
+
buffer += textContent;
|
|
2304
|
+
processBuffer(controller);
|
|
2305
|
+
},
|
|
2306
|
+
flush(controller) {
|
|
2307
|
+
if (currentToolCall) {
|
|
2308
|
+
const unfinishedContent = `<${currentToolCall.name}>${currentToolCall.content || ""}${buffer}`;
|
|
2309
|
+
flushText(controller, unfinishedContent);
|
|
2310
|
+
buffer = "";
|
|
2311
|
+
currentToolCall = null;
|
|
2312
|
+
} else if (buffer) {
|
|
2313
|
+
flushText(controller, buffer);
|
|
2314
|
+
buffer = "";
|
|
2315
|
+
}
|
|
2316
|
+
if (currentTextId && hasEmittedTextStart) {
|
|
2317
|
+
controller.enqueue({
|
|
2318
|
+
type: "text-end",
|
|
2319
|
+
id: currentTextId
|
|
2320
|
+
});
|
|
2321
|
+
hasEmittedTextStart = false;
|
|
2322
|
+
currentTextId = null;
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
});
|
|
2326
|
+
},
|
|
2327
|
+
extractToolCallSegments({ text, tools }) {
|
|
2328
|
+
const toolNames = tools.map((t) => t.name).filter(Boolean);
|
|
2329
|
+
if (toolNames.length === 0) {
|
|
2330
|
+
return [];
|
|
2331
|
+
}
|
|
2332
|
+
return findToolCalls(text, toolNames).map((tc) => tc.segment);
|
|
2333
|
+
}
|
|
2334
|
+
};
|
|
2335
|
+
};
|
|
2336
|
+
|
|
2337
|
+
// src/core/protocols/tool-call-protocol.ts
|
|
2338
|
+
function isProtocolFactory(protocol) {
|
|
2339
|
+
return typeof protocol === "function";
|
|
2340
|
+
}
|
|
2341
|
+
|
|
2342
|
+
// src/core/utils/dynamic-tool-schema.ts
|
|
2343
|
+
function createDynamicIfThenElseSchema(tools) {
|
|
2344
|
+
let currentSchema = {};
|
|
2345
|
+
const toolNames = [];
|
|
2346
|
+
for (let i = tools.length - 1; i >= 0; i -= 1) {
|
|
2347
|
+
const tool = tools[i];
|
|
2348
|
+
if (tool.type === "provider") {
|
|
2349
|
+
throw new Error(
|
|
2350
|
+
"Provider tools are not supported by this middleware. Please use function tools."
|
|
2351
|
+
);
|
|
2352
|
+
}
|
|
2353
|
+
toolNames.unshift(tool.name);
|
|
2354
|
+
const toolCondition = {
|
|
2355
|
+
if: {
|
|
2356
|
+
properties: {
|
|
2357
|
+
name: {
|
|
2358
|
+
const: tool.name
|
|
2359
|
+
}
|
|
2360
|
+
},
|
|
2361
|
+
required: ["name"]
|
|
2362
|
+
},
|
|
2363
|
+
// biome-ignore lint/suspicious/noThenProperty: JSON Schema uses 'then' as a keyword
|
|
2364
|
+
then: {
|
|
2365
|
+
properties: {
|
|
2366
|
+
name: {
|
|
2367
|
+
const: tool.name
|
|
2368
|
+
},
|
|
2369
|
+
arguments: tool.inputSchema
|
|
2370
|
+
},
|
|
2371
|
+
required: ["name", "arguments"]
|
|
2372
|
+
}
|
|
2373
|
+
};
|
|
2374
|
+
if (Object.keys(currentSchema).length > 0) {
|
|
2375
|
+
toolCondition.else = currentSchema;
|
|
2376
|
+
}
|
|
2377
|
+
currentSchema = toolCondition;
|
|
2378
|
+
}
|
|
2379
|
+
return {
|
|
2380
|
+
type: "object",
|
|
2381
|
+
// Explicitly specify type as "object"
|
|
2382
|
+
properties: {
|
|
2383
|
+
name: {
|
|
2384
|
+
type: "string",
|
|
2385
|
+
description: "Name of the tool to call",
|
|
2386
|
+
enum: toolNames
|
|
2387
|
+
},
|
|
2388
|
+
arguments: {
|
|
2389
|
+
type: "object",
|
|
2390
|
+
// By default, arguments is also specified as object type
|
|
2391
|
+
description: "Argument object to be passed to the tool"
|
|
2392
|
+
}
|
|
2393
|
+
},
|
|
2394
|
+
required: ["name", "arguments"],
|
|
2395
|
+
...currentSchema
|
|
2396
|
+
};
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
// src/core/utils/on-error.ts
|
|
2400
|
+
function extractOnErrorOption(providerOptions) {
|
|
2401
|
+
var _a;
|
|
2402
|
+
if (providerOptions && typeof providerOptions === "object") {
|
|
2403
|
+
const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
|
|
2404
|
+
return onError ? { onError } : void 0;
|
|
2405
|
+
}
|
|
2406
|
+
return;
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2409
|
+
// src/core/utils/provider-options.ts
|
|
2410
|
+
var originalToolsSchema = {
|
|
2411
|
+
encode: encodeOriginalTools,
|
|
2412
|
+
decode: decodeOriginalTools
|
|
2413
|
+
};
|
|
2414
|
+
function encodeOriginalTools(tools) {
|
|
2415
|
+
return (tools == null ? void 0 : tools.map((t) => ({
|
|
2416
|
+
name: t.name,
|
|
2417
|
+
inputSchema: JSON.stringify(t.inputSchema)
|
|
2418
|
+
}))) || [];
|
|
2419
|
+
}
|
|
2420
|
+
function decodeOriginalTools(originalTools) {
|
|
2421
|
+
if (!originalTools) {
|
|
2422
|
+
return [];
|
|
2423
|
+
}
|
|
2424
|
+
return originalTools.map(
|
|
2425
|
+
(t) => ({
|
|
2426
|
+
type: "function",
|
|
2427
|
+
name: t.name,
|
|
2428
|
+
inputSchema: JSON.parse(t.inputSchema)
|
|
2429
|
+
})
|
|
2430
|
+
);
|
|
2431
|
+
}
|
|
2432
|
+
function extractToolNamesFromOriginalTools(originalTools) {
|
|
2433
|
+
return (originalTools == null ? void 0 : originalTools.map((t) => t.name)) || [];
|
|
2434
|
+
}
|
|
2435
|
+
function isToolChoiceActive(params) {
|
|
2436
|
+
var _a, _b, _c;
|
|
2437
|
+
const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
|
|
2438
|
+
return !!(typeof params.providerOptions === "object" && params.providerOptions !== null && typeof ((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) === "object" && toolChoice && typeof toolChoice === "object" && (toolChoice.type === "tool" || toolChoice.type === "required"));
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
// src/core/utils/type-guards.ts
|
|
2442
|
+
function isToolCallContent(content) {
|
|
2443
|
+
return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
|
|
2444
|
+
(typeof content.input === "string" || typeof content.input === "object");
|
|
2445
|
+
}
|
|
2446
|
+
function isToolResultPart(content) {
|
|
2447
|
+
const c = content;
|
|
2448
|
+
return !!c && c.type === "tool-result" && typeof c.toolName === "string" && typeof c.toolCallId === "string" && "output" in c;
|
|
2449
|
+
}
|
|
2450
|
+
function hasInputProperty(obj) {
|
|
2451
|
+
return typeof obj === "object" && obj !== null && "input" in obj;
|
|
2452
|
+
}
|
|
2453
|
+
|
|
2454
|
+
export {
|
|
2455
|
+
applyHeuristicPipeline,
|
|
2456
|
+
createIntermediateCall,
|
|
2457
|
+
mergePipelineConfigs,
|
|
2458
|
+
normalizeCloseTagsHeuristic,
|
|
2459
|
+
escapeInvalidLtHeuristic,
|
|
2460
|
+
balanceTagsHeuristic,
|
|
2461
|
+
dedupeShellStringTagsHeuristic,
|
|
2462
|
+
repairAgainstSchemaHeuristic,
|
|
2463
|
+
defaultPipelineConfig,
|
|
2464
|
+
getDebugLevel,
|
|
2465
|
+
logParseFailure,
|
|
2466
|
+
logRawChunk,
|
|
2467
|
+
logParsedChunk,
|
|
2468
|
+
logParsedSummary,
|
|
2469
|
+
getPotentialStartIndex,
|
|
2470
|
+
generateId,
|
|
2471
|
+
escapeRegExp2 as escapeRegExp,
|
|
2472
|
+
transform,
|
|
2473
|
+
parse2 as parse,
|
|
2474
|
+
stringify,
|
|
2475
|
+
jsonMixProtocol,
|
|
2476
|
+
morphXmlProtocol,
|
|
2477
|
+
isProtocolFactory,
|
|
2478
|
+
createDynamicIfThenElseSchema,
|
|
2479
|
+
extractOnErrorOption,
|
|
2480
|
+
originalToolsSchema,
|
|
2481
|
+
encodeOriginalTools,
|
|
2482
|
+
decodeOriginalTools,
|
|
2483
|
+
extractToolNamesFromOriginalTools,
|
|
2484
|
+
isToolChoiceActive,
|
|
2485
|
+
isToolCallContent,
|
|
2486
|
+
isToolResultPart,
|
|
2487
|
+
hasInputProperty
|
|
2488
|
+
};
|
|
2489
|
+
//# sourceMappingURL=chunk-NOYHOQOL.js.map
|