@ai-sdk-tool/parser 2.1.7 → 3.0.0-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-L4X363EL.js +3168 -0
- package/dist/chunk-L4X363EL.js.map +1 -0
- package/dist/community.cjs +2073 -1020
- package/dist/community.cjs.map +1 -1
- package/dist/community.d.cts +2 -2
- package/dist/community.d.ts +2 -2
- package/dist/community.js +2 -2
- package/dist/community.js.map +1 -1
- package/dist/index.cjs +2095 -1004
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +91 -91
- package/dist/index.d.ts +91 -91
- package/dist/index.js +10 -4
- package/package.json +23 -22
- package/dist/chunk-GSD5HDOQ.js +0 -2068
- package/dist/chunk-GSD5HDOQ.js.map +0 -1
package/dist/community.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// src/community/index.ts
|
|
@@ -35,66 +25,162 @@ __export(community_exports, {
|
|
|
35
25
|
});
|
|
36
26
|
module.exports = __toCommonJS(community_exports);
|
|
37
27
|
|
|
38
|
-
// src/protocols/dummy-protocol.ts
|
|
39
|
-
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
40
|
-
|
|
41
28
|
// src/protocols/json-mix-protocol.ts
|
|
42
|
-
var
|
|
29
|
+
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
43
30
|
|
|
44
|
-
// src/utils/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
31
|
+
// src/utils/debug.ts
|
|
32
|
+
var LINE_SPLIT_REGEX = /\r?\n/;
|
|
33
|
+
function normalizeBooleanString(value) {
|
|
34
|
+
const normalized = value.trim().toLowerCase();
|
|
35
|
+
if (normalized === "1" || normalized === "true" || normalized === "yes") {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
if (normalized === "0" || normalized === "false" || normalized === "no") {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
function getDebugLevel() {
|
|
44
|
+
const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW || "off";
|
|
45
|
+
const envLower = String(envVal).toLowerCase();
|
|
46
|
+
if (envLower === "stream" || envLower === "parse" || envLower === "off") {
|
|
47
|
+
return envLower;
|
|
48
|
+
}
|
|
49
|
+
const boolEnv = normalizeBooleanString(envLower);
|
|
50
|
+
if (boolEnv === true) {
|
|
51
|
+
return "stream";
|
|
52
|
+
}
|
|
53
|
+
if (envLower === "2") {
|
|
54
|
+
return "parse";
|
|
55
|
+
}
|
|
56
|
+
return "off";
|
|
57
|
+
}
|
|
58
|
+
function color(code) {
|
|
59
|
+
return (text) => `\x1B[${code}m${text}\x1B[0m`;
|
|
60
|
+
}
|
|
61
|
+
var ANSI_GRAY = 90;
|
|
62
|
+
var ANSI_YELLOW = 33;
|
|
63
|
+
var ANSI_CYAN = 36;
|
|
64
|
+
var ANSI_BG_BLUE = 44;
|
|
65
|
+
var ANSI_BG_GREEN = 42;
|
|
66
|
+
var ANSI_INVERSE = 7;
|
|
67
|
+
var ANSI_UNDERLINE = 4;
|
|
68
|
+
var ANSI_BOLD = 1;
|
|
69
|
+
var cGray = color(ANSI_GRAY);
|
|
70
|
+
var cYellow = color(ANSI_YELLOW);
|
|
71
|
+
var cCyan = color(ANSI_CYAN);
|
|
72
|
+
var cBgBlue = color(ANSI_BG_BLUE);
|
|
73
|
+
var cBgGreen = color(ANSI_BG_GREEN);
|
|
74
|
+
var cInverse = color(ANSI_INVERSE);
|
|
75
|
+
var cUnderline = color(ANSI_UNDERLINE);
|
|
76
|
+
var cBold = color(ANSI_BOLD);
|
|
77
|
+
var MAX_SNIPPET_LENGTH = 800;
|
|
78
|
+
function safeStringify(value) {
|
|
79
|
+
try {
|
|
80
|
+
return `
|
|
81
|
+
${typeof value === "string" ? value : JSON.stringify(value, null, 2)}`;
|
|
82
|
+
} catch (e) {
|
|
83
|
+
return String(value);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function formatError(error) {
|
|
87
|
+
if (error instanceof Error) {
|
|
88
|
+
const stack = error.stack ? `
|
|
89
|
+
${error.stack}` : "";
|
|
90
|
+
return `
|
|
91
|
+
${error.name}: ${error.message}${stack}`;
|
|
92
|
+
}
|
|
93
|
+
return safeStringify(error);
|
|
94
|
+
}
|
|
95
|
+
function truncateSnippet(snippet) {
|
|
96
|
+
if (snippet.length <= MAX_SNIPPET_LENGTH) {
|
|
97
|
+
return snippet;
|
|
98
|
+
}
|
|
99
|
+
return `${snippet.slice(0, MAX_SNIPPET_LENGTH)}
|
|
100
|
+
\u2026[truncated ${snippet.length - MAX_SNIPPET_LENGTH} chars]`;
|
|
101
|
+
}
|
|
102
|
+
function logParseFailure({
|
|
103
|
+
phase,
|
|
104
|
+
reason,
|
|
105
|
+
snippet,
|
|
106
|
+
error
|
|
107
|
+
}) {
|
|
108
|
+
if (getDebugLevel() !== "parse") {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const label = cBgBlue(`[${phase}]`);
|
|
112
|
+
console.log(cGray("[debug:mw:fail]"), label, cYellow(reason));
|
|
113
|
+
if (snippet) {
|
|
114
|
+
const formatted = truncateSnippet(snippet);
|
|
115
|
+
console.log(cGray("[debug:mw:fail:snippet]"), formatted);
|
|
116
|
+
}
|
|
117
|
+
if (error) {
|
|
118
|
+
console.log(cGray("[debug:mw:fail:error]"), cCyan(formatError(error)));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function logRawChunk(part) {
|
|
122
|
+
console.log(cGray("[debug:mw:raw]"), cYellow(safeStringify(part)));
|
|
123
|
+
}
|
|
124
|
+
function logParsedChunk(part) {
|
|
125
|
+
console.log(cGray("[debug:mw:out]"), cCyan(safeStringify(part)));
|
|
126
|
+
}
|
|
127
|
+
function getHighlightStyle() {
|
|
128
|
+
const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW_STYLE || "bg";
|
|
129
|
+
const normalized = String(envVal).trim().toLowerCase();
|
|
130
|
+
if (normalized === "inverse" || normalized === "invert") {
|
|
131
|
+
return "inverse";
|
|
132
|
+
}
|
|
133
|
+
if (normalized === "underline" || normalized === "ul") {
|
|
134
|
+
return "underline";
|
|
135
|
+
}
|
|
136
|
+
if (normalized === "bold") {
|
|
137
|
+
return "bold";
|
|
138
|
+
}
|
|
139
|
+
if (normalized === "bg" || normalized === "background") {
|
|
140
|
+
return "bg";
|
|
141
|
+
}
|
|
142
|
+
const asBool = normalizeBooleanString(normalized);
|
|
143
|
+
if (asBool === true) {
|
|
144
|
+
return "bg";
|
|
145
|
+
}
|
|
146
|
+
return "bg";
|
|
147
|
+
}
|
|
148
|
+
function getHighlightFunction(style) {
|
|
149
|
+
if (style === "inverse") {
|
|
150
|
+
return cInverse;
|
|
151
|
+
}
|
|
152
|
+
if (style === "underline") {
|
|
153
|
+
return cUnderline;
|
|
154
|
+
}
|
|
155
|
+
if (style === "bold") {
|
|
156
|
+
return cBold;
|
|
157
|
+
}
|
|
158
|
+
if (style === "bg") {
|
|
159
|
+
return cBgGreen;
|
|
160
|
+
}
|
|
161
|
+
return cYellow;
|
|
162
|
+
}
|
|
163
|
+
function renderHighlightedText(originalText, style, highlight) {
|
|
164
|
+
if (style === "bg" || style === "inverse" || style === "underline" || style === "bold") {
|
|
165
|
+
return originalText.split(LINE_SPLIT_REGEX).map((line) => line.length ? highlight(line) : line).join("\n");
|
|
166
|
+
}
|
|
167
|
+
return highlight(originalText);
|
|
168
|
+
}
|
|
169
|
+
function logParsedSummary({
|
|
170
|
+
toolCalls,
|
|
171
|
+
originalText
|
|
172
|
+
}) {
|
|
173
|
+
if (originalText) {
|
|
174
|
+
const style = getHighlightStyle();
|
|
175
|
+
const highlight = getHighlightFunction(style);
|
|
176
|
+
const rendered = renderHighlightedText(originalText, style, highlight);
|
|
177
|
+
console.log(cGray("[debug:mw:origin]"), `
|
|
178
|
+
${rendered}`);
|
|
179
|
+
}
|
|
180
|
+
if (toolCalls.length > 0) {
|
|
181
|
+
const styledSummary = safeStringify(toolCalls).split(LINE_SPLIT_REGEX).map((line) => line.length ? cBgBlue(line) : line).join("\n");
|
|
182
|
+
console.log(cGray("[debug:mw:summary]"), styledSummary);
|
|
79
183
|
}
|
|
80
|
-
return {
|
|
81
|
-
type: "object",
|
|
82
|
-
// Explicitly specify type as "object"
|
|
83
|
-
properties: {
|
|
84
|
-
name: {
|
|
85
|
-
type: "string",
|
|
86
|
-
description: "Name of the tool to call",
|
|
87
|
-
enum: toolNames
|
|
88
|
-
},
|
|
89
|
-
arguments: {
|
|
90
|
-
type: "object",
|
|
91
|
-
// By default, arguments is also specified as object type
|
|
92
|
-
description: "Argument object to be passed to the tool"
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
required: ["name", "arguments"],
|
|
96
|
-
...currentSchema
|
|
97
|
-
};
|
|
98
184
|
}
|
|
99
185
|
|
|
100
186
|
// src/utils/get-potential-start-index.ts
|
|
@@ -106,7 +192,7 @@ function getPotentialStartIndex(text, searchedText) {
|
|
|
106
192
|
if (directIndex !== -1) {
|
|
107
193
|
return directIndex;
|
|
108
194
|
}
|
|
109
|
-
for (let i = text.length - 1; i >= 0; i
|
|
195
|
+
for (let i = text.length - 1; i >= 0; i -= 1) {
|
|
110
196
|
const suffix = text.substring(i);
|
|
111
197
|
if (searchedText.startsWith(suffix)) {
|
|
112
198
|
return i;
|
|
@@ -121,15 +207,24 @@ function escapeRegExp(literal) {
|
|
|
121
207
|
}
|
|
122
208
|
|
|
123
209
|
// src/utils/robust-json.ts
|
|
124
|
-
var
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
210
|
+
var WHITESPACE_TEST_REGEX = /\s/;
|
|
211
|
+
var WHITESPACE_REGEX = /^\s+/;
|
|
212
|
+
var OBJECT_START_REGEX = /^\{/;
|
|
213
|
+
var OBJECT_END_REGEX = /^\}/;
|
|
214
|
+
var ARRAY_START_REGEX = /^\[/;
|
|
215
|
+
var ARRAY_END_REGEX = /^\]/;
|
|
216
|
+
var COMMA_REGEX = /^,/;
|
|
217
|
+
var COLON_REGEX = /^:/;
|
|
218
|
+
var KEYWORD_REGEX = /^(?:true|false|null)/;
|
|
219
|
+
var NUMBER_REGEX = /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/;
|
|
220
|
+
var STRING_DOUBLE_REGEX = /^"(?:[^"\\]|\\["bnrtf\\/]|\\u[0-9a-fA-F]{4})*"/;
|
|
221
|
+
var STRING_SINGLE_REGEX = /^'((?:[^'\\]|\\['bnrtf\\/]|\\u[0-9a-fA-F]{4})*)'/;
|
|
222
|
+
var COMMENT_SINGLE_REGEX = /^\/\/.*?(?:\r\n|\r|\n)/;
|
|
223
|
+
var COMMENT_MULTI_REGEX = /^\/\*[\s\S]*?\*\//;
|
|
224
|
+
var IDENTIFIER_REGEX = /^[$a-zA-Z0-9_\-+.*?!|&%^/#\\]+/;
|
|
130
225
|
function some(array, f) {
|
|
131
226
|
let acc = false;
|
|
132
|
-
for (let i = 0; i < array.length; i
|
|
227
|
+
for (let i = 0; i < array.length; i += 1) {
|
|
133
228
|
const result = f(array[i], i, array);
|
|
134
229
|
acc = result === void 0 ? false : result;
|
|
135
230
|
if (acc) {
|
|
@@ -139,31 +234,31 @@ function some(array, f) {
|
|
|
139
234
|
return acc;
|
|
140
235
|
}
|
|
141
236
|
function makeLexer(tokenSpecs) {
|
|
142
|
-
return
|
|
237
|
+
return (contents) => {
|
|
143
238
|
const tokens = [];
|
|
144
239
|
let line = 1;
|
|
240
|
+
let remainingContents = contents;
|
|
145
241
|
function findToken() {
|
|
146
242
|
const result = some(tokenSpecs, (tokenSpec) => {
|
|
147
|
-
const m = tokenSpec.re.exec(
|
|
243
|
+
const m = tokenSpec.re.exec(remainingContents);
|
|
148
244
|
if (m) {
|
|
149
245
|
const raw = m[0];
|
|
150
|
-
|
|
246
|
+
remainingContents = remainingContents.slice(raw.length);
|
|
151
247
|
return {
|
|
152
248
|
raw,
|
|
153
249
|
matched: tokenSpec.f(m)
|
|
154
250
|
// Process the match using the spec's function
|
|
155
251
|
};
|
|
156
|
-
} else {
|
|
157
|
-
return void 0;
|
|
158
252
|
}
|
|
253
|
+
return;
|
|
159
254
|
});
|
|
160
255
|
return result === false ? void 0 : result;
|
|
161
256
|
}
|
|
162
|
-
while (
|
|
257
|
+
while (remainingContents !== "") {
|
|
163
258
|
const matched = findToken();
|
|
164
259
|
if (!matched) {
|
|
165
260
|
const err = new SyntaxError(
|
|
166
|
-
`Unexpected character: ${
|
|
261
|
+
`Unexpected character: ${remainingContents[0]}; input: ${remainingContents.substr(
|
|
167
262
|
0,
|
|
168
263
|
100
|
|
169
264
|
)}`
|
|
@@ -185,11 +280,11 @@ function fStringSingle(m) {
|
|
|
185
280
|
(mm) => {
|
|
186
281
|
if (mm === '"') {
|
|
187
282
|
return '\\"';
|
|
188
|
-
}
|
|
283
|
+
}
|
|
284
|
+
if (mm === "\\'") {
|
|
189
285
|
return "'";
|
|
190
|
-
} else {
|
|
191
|
-
return mm;
|
|
192
286
|
}
|
|
287
|
+
return mm;
|
|
193
288
|
}
|
|
194
289
|
);
|
|
195
290
|
const match = `"${content}"`;
|
|
@@ -224,7 +319,10 @@ function fIdentifier(m) {
|
|
|
224
319
|
};
|
|
225
320
|
}
|
|
226
321
|
function fComment(m) {
|
|
227
|
-
const match = m[0].replace(
|
|
322
|
+
const match = m[0].replace(
|
|
323
|
+
/./g,
|
|
324
|
+
(c) => WHITESPACE_TEST_REGEX.test(c) ? c : " "
|
|
325
|
+
);
|
|
228
326
|
return {
|
|
229
327
|
type: " ",
|
|
230
328
|
// Represent comments as whitespace tokens
|
|
@@ -239,7 +337,7 @@ function fNumber(m) {
|
|
|
239
337
|
type: "number",
|
|
240
338
|
match: m[0],
|
|
241
339
|
// The raw matched number string
|
|
242
|
-
value: parseFloat(m[0])
|
|
340
|
+
value: Number.parseFloat(m[0])
|
|
243
341
|
// Convert string to number
|
|
244
342
|
};
|
|
245
343
|
}
|
|
@@ -269,46 +367,46 @@ function fKeyword(m) {
|
|
|
269
367
|
}
|
|
270
368
|
function makeTokenSpecs(relaxed) {
|
|
271
369
|
function f(type) {
|
|
272
|
-
return
|
|
370
|
+
return (m) => {
|
|
273
371
|
return { type, match: m[0], value: void 0 };
|
|
274
372
|
};
|
|
275
373
|
}
|
|
276
374
|
let tokenSpecs = [
|
|
277
|
-
{ re:
|
|
375
|
+
{ re: WHITESPACE_REGEX, f: f(" ") },
|
|
278
376
|
// Whitespace
|
|
279
|
-
{ re:
|
|
377
|
+
{ re: OBJECT_START_REGEX, f: f("{") },
|
|
280
378
|
// Object start
|
|
281
|
-
{ re:
|
|
379
|
+
{ re: OBJECT_END_REGEX, f: f("}") },
|
|
282
380
|
// Object end
|
|
283
|
-
{ re:
|
|
381
|
+
{ re: ARRAY_START_REGEX, f: f("[") },
|
|
284
382
|
// Array start
|
|
285
|
-
{ re:
|
|
383
|
+
{ re: ARRAY_END_REGEX, f: f("]") },
|
|
286
384
|
// Array end
|
|
287
|
-
{ re:
|
|
385
|
+
{ re: COMMA_REGEX, f: f(",") },
|
|
288
386
|
// Comma separator
|
|
289
|
-
{ re:
|
|
387
|
+
{ re: COLON_REGEX, f: f(":") },
|
|
290
388
|
// Key-value separator
|
|
291
|
-
{ re:
|
|
389
|
+
{ re: KEYWORD_REGEX, f: fKeyword },
|
|
292
390
|
// Keywords
|
|
293
391
|
// Number: optional sign, digits, optional decimal part, optional exponent
|
|
294
|
-
{ re:
|
|
392
|
+
{ re: NUMBER_REGEX, f: fNumber },
|
|
295
393
|
// String: double-quoted, handles escapes
|
|
296
|
-
{ re:
|
|
394
|
+
{ re: STRING_DOUBLE_REGEX, f: fStringDouble }
|
|
297
395
|
];
|
|
298
396
|
if (relaxed) {
|
|
299
397
|
tokenSpecs = tokenSpecs.concat([
|
|
300
398
|
// Single-quoted strings
|
|
301
399
|
{
|
|
302
|
-
re:
|
|
400
|
+
re: STRING_SINGLE_REGEX,
|
|
303
401
|
f: fStringSingle
|
|
304
402
|
},
|
|
305
403
|
// Single-line comments (// ...)
|
|
306
|
-
{ re:
|
|
404
|
+
{ re: COMMENT_SINGLE_REGEX, f: fComment },
|
|
307
405
|
// Multi-line comments (/* ... */)
|
|
308
|
-
{ re:
|
|
406
|
+
{ re: COMMENT_MULTI_REGEX, f: fComment },
|
|
309
407
|
// Unquoted identifiers (treated as strings)
|
|
310
408
|
// Allows letters, numbers, _, -, +, ., *, ?, !, |, &, %, ^, /, #, \
|
|
311
|
-
{ re:
|
|
409
|
+
{ re: IDENTIFIER_REGEX, f: fIdentifier }
|
|
312
410
|
// Note: The order matters here. Identifiers are checked after keywords/numbers.
|
|
313
411
|
]);
|
|
314
412
|
}
|
|
@@ -317,12 +415,13 @@ function makeTokenSpecs(relaxed) {
|
|
|
317
415
|
var lexer = makeLexer(makeTokenSpecs(true));
|
|
318
416
|
var strictLexer = makeLexer(makeTokenSpecs(false));
|
|
319
417
|
function previousNWSToken(tokens, index) {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
418
|
+
let currentIndex = index;
|
|
419
|
+
for (; currentIndex >= 0; currentIndex -= 1) {
|
|
420
|
+
if (tokens[currentIndex].type !== " ") {
|
|
421
|
+
return currentIndex;
|
|
323
422
|
}
|
|
324
423
|
}
|
|
325
|
-
return
|
|
424
|
+
return;
|
|
326
425
|
}
|
|
327
426
|
function stripTrailingComma(tokens) {
|
|
328
427
|
const res = [];
|
|
@@ -348,18 +447,12 @@ function stripTrailingComma(tokens) {
|
|
|
348
447
|
});
|
|
349
448
|
return res;
|
|
350
449
|
}
|
|
351
|
-
function transform(text) {
|
|
352
|
-
let tokens = lexer(text);
|
|
353
|
-
tokens = stripTrailingComma(tokens);
|
|
354
|
-
return tokens.reduce((str, token) => {
|
|
355
|
-
return str + token.match;
|
|
356
|
-
}, "");
|
|
357
|
-
}
|
|
358
450
|
function popToken(tokens, state) {
|
|
451
|
+
var _a, _b;
|
|
359
452
|
const token = tokens[state.pos];
|
|
360
453
|
state.pos += 1;
|
|
361
454
|
if (!token) {
|
|
362
|
-
const lastLine = tokens.length !== 0 ? tokens
|
|
455
|
+
const lastLine = tokens.length !== 0 ? (_b = (_a = tokens.at(-1)) == null ? void 0 : _a.line) != null ? _b : 1 : 1;
|
|
363
456
|
return { type: "eof", match: "", value: void 0, line: lastLine };
|
|
364
457
|
}
|
|
365
458
|
return token;
|
|
@@ -397,11 +490,13 @@ function skipPunctuation(tokens, state, valid) {
|
|
|
397
490
|
const punctuation = [",", ":", "]", "}"];
|
|
398
491
|
let token = popToken(tokens, state);
|
|
399
492
|
while (true) {
|
|
400
|
-
if (valid
|
|
493
|
+
if (valid == null ? void 0 : valid.includes(token.type)) {
|
|
401
494
|
return token;
|
|
402
|
-
}
|
|
495
|
+
}
|
|
496
|
+
if (token.type === "eof") {
|
|
403
497
|
return token;
|
|
404
|
-
}
|
|
498
|
+
}
|
|
499
|
+
if (punctuation.includes(token.type)) {
|
|
405
500
|
const message = `Unexpected token: ${strToken(
|
|
406
501
|
token
|
|
407
502
|
)}, expected '[', '{', number, string or atom`;
|
|
@@ -442,7 +537,7 @@ function raiseUnexpected(state, token, expected) {
|
|
|
442
537
|
}
|
|
443
538
|
function checkDuplicates(state, obj, token) {
|
|
444
539
|
const key = String(token.value);
|
|
445
|
-
if (!state.duplicate && Object.
|
|
540
|
+
if (!state.duplicate && Object.hasOwn(obj, key)) {
|
|
446
541
|
raiseError(state, token, `Duplicate key: ${key}`);
|
|
447
542
|
}
|
|
448
543
|
}
|
|
@@ -539,51 +634,84 @@ function parseArray(tokens, state) {
|
|
|
539
634
|
// The closing token for an array
|
|
540
635
|
});
|
|
541
636
|
}
|
|
542
|
-
function
|
|
543
|
-
|
|
544
|
-
if (
|
|
545
|
-
|
|
546
|
-
if (state.tolerant) {
|
|
547
|
-
return result;
|
|
548
|
-
} else {
|
|
637
|
+
function handleInvalidToken(token, state, opts, result) {
|
|
638
|
+
raiseUnexpected(state, token, `',' or '${opts.endSymbol}'`);
|
|
639
|
+
if (state.tolerant) {
|
|
640
|
+
if (token.type === "eof") {
|
|
549
641
|
return result;
|
|
550
642
|
}
|
|
643
|
+
state.pos -= 1;
|
|
644
|
+
return null;
|
|
645
|
+
}
|
|
646
|
+
return result;
|
|
647
|
+
}
|
|
648
|
+
function handleCommaToken(params) {
|
|
649
|
+
const { token, tokens, state, opts, result } = params;
|
|
650
|
+
const nextToken = tokens[state.pos];
|
|
651
|
+
if (state.tolerant && nextToken && nextToken.type === opts.endSymbol) {
|
|
652
|
+
raiseError(state, token, `Trailing comma before '${opts.endSymbol}'`);
|
|
653
|
+
popToken(tokens, state);
|
|
654
|
+
return result;
|
|
655
|
+
}
|
|
656
|
+
opts.elementParser(tokens, state, result);
|
|
657
|
+
return null;
|
|
658
|
+
}
|
|
659
|
+
function parseManyInitialElement(tokens, state, result, opts) {
|
|
660
|
+
const token = skipPunctuation(tokens, state, opts.skip);
|
|
661
|
+
if (token.type === "eof") {
|
|
662
|
+
raiseUnexpected(state, token, `'${opts.endSymbol}' or ${opts.elementName}`);
|
|
663
|
+
return result;
|
|
551
664
|
}
|
|
552
665
|
if (token.type === opts.endSymbol) {
|
|
553
666
|
return result;
|
|
554
667
|
}
|
|
555
668
|
state.pos -= 1;
|
|
556
669
|
opts.elementParser(tokens, state, result);
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
state.pos -= 1;
|
|
566
|
-
} else {
|
|
567
|
-
return result;
|
|
568
|
-
}
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
function parseManyProcessToken(params) {
|
|
673
|
+
const { token, tokens, state, opts, result } = params;
|
|
674
|
+
if (token.type !== opts.endSymbol && token.type !== ",") {
|
|
675
|
+
const handledResult = handleInvalidToken(token, state, opts, result);
|
|
676
|
+
if (handledResult !== null) {
|
|
677
|
+
return handledResult;
|
|
569
678
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
679
|
+
}
|
|
680
|
+
if (token.type === opts.endSymbol) {
|
|
681
|
+
return result;
|
|
682
|
+
}
|
|
683
|
+
if (token.type === ",") {
|
|
684
|
+
const handledResult = handleCommaToken({
|
|
685
|
+
token,
|
|
686
|
+
tokens,
|
|
687
|
+
state,
|
|
688
|
+
opts,
|
|
689
|
+
result
|
|
690
|
+
});
|
|
691
|
+
if (handledResult !== null) {
|
|
692
|
+
return handledResult;
|
|
693
|
+
}
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
opts.elementParser(tokens, state, result);
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
function parseMany(tokens, state, result, opts) {
|
|
700
|
+
const initialResult = parseManyInitialElement(tokens, state, result, opts);
|
|
701
|
+
if (initialResult !== void 0) {
|
|
702
|
+
return initialResult;
|
|
703
|
+
}
|
|
704
|
+
while (true) {
|
|
705
|
+
const token = popToken(tokens, state);
|
|
706
|
+
const processedResult = parseManyProcessToken({
|
|
707
|
+
token,
|
|
708
|
+
tokens,
|
|
709
|
+
state,
|
|
710
|
+
opts,
|
|
711
|
+
result
|
|
712
|
+
});
|
|
713
|
+
if (processedResult !== void 0) {
|
|
714
|
+
return processedResult;
|
|
587
715
|
}
|
|
588
716
|
}
|
|
589
717
|
}
|
|
@@ -617,7 +745,7 @@ function parseAny(tokens, state, end = false) {
|
|
|
617
745
|
raiseUnexpected(state, token, "json value");
|
|
618
746
|
}
|
|
619
747
|
raiseUnexpected(state, token, "json value");
|
|
620
|
-
return
|
|
748
|
+
return;
|
|
621
749
|
}
|
|
622
750
|
switch (token.type) {
|
|
623
751
|
case "{":
|
|
@@ -638,7 +766,7 @@ function parseAny(tokens, state, end = false) {
|
|
|
638
766
|
if (state.tolerant) {
|
|
639
767
|
ret = null;
|
|
640
768
|
} else {
|
|
641
|
-
return
|
|
769
|
+
return;
|
|
642
770
|
}
|
|
643
771
|
}
|
|
644
772
|
if (end) {
|
|
@@ -647,7 +775,7 @@ function parseAny(tokens, state, end = false) {
|
|
|
647
775
|
}
|
|
648
776
|
return ret;
|
|
649
777
|
}
|
|
650
|
-
function
|
|
778
|
+
function normalizeParseOptions(optsOrReviver) {
|
|
651
779
|
var _a;
|
|
652
780
|
let options = {};
|
|
653
781
|
if (typeof optsOrReviver === "function") {
|
|
@@ -668,218 +796,247 @@ function parse(text, optsOrReviver) {
|
|
|
668
796
|
options.relaxed = true;
|
|
669
797
|
}
|
|
670
798
|
}
|
|
671
|
-
options.tolerant = options.tolerant || options.warnings
|
|
672
|
-
options.warnings = options.warnings || false;
|
|
799
|
+
options.tolerant = options.tolerant || options.warnings;
|
|
673
800
|
options.duplicate = (_a = options.duplicate) != null ? _a : false;
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
801
|
+
return options;
|
|
802
|
+
}
|
|
803
|
+
function createParseState(options) {
|
|
804
|
+
var _a, _b;
|
|
805
|
+
return {
|
|
806
|
+
pos: 0,
|
|
807
|
+
reviver: options.reviver,
|
|
808
|
+
tolerant: (_a = options.tolerant) != null ? _a : false,
|
|
809
|
+
duplicate: (_b = options.duplicate) != null ? _b : false,
|
|
810
|
+
warnings: []
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
function parseWithCustomParser(text, options) {
|
|
683
814
|
const lexerToUse = options.relaxed ? lexer : strictLexer;
|
|
684
815
|
let tokens = lexerToUse(text);
|
|
685
816
|
if (options.relaxed) {
|
|
686
817
|
tokens = stripTrailingComma(tokens);
|
|
687
818
|
}
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
pos: 0,
|
|
692
|
-
reviver: options.reviver,
|
|
693
|
-
tolerant: options.tolerant,
|
|
694
|
-
duplicate: options.duplicate,
|
|
695
|
-
// true = allow duplicate keys, false = reject duplicates
|
|
696
|
-
warnings: []
|
|
697
|
-
};
|
|
698
|
-
return parseAny(tokens, state, true);
|
|
699
|
-
} else {
|
|
700
|
-
tokens.reduce((str, token) => {
|
|
701
|
-
return str + token.match;
|
|
702
|
-
}, "");
|
|
703
|
-
if (!options.relaxed && !options.warnings && !options.tolerant && options.duplicate) {
|
|
704
|
-
return JSON.parse(text, options.reviver);
|
|
705
|
-
} else if (options.warnings || options.tolerant || !options.duplicate) {
|
|
706
|
-
tokens = lexerToUse(text);
|
|
707
|
-
if (options.relaxed) {
|
|
708
|
-
tokens = stripTrailingComma(tokens);
|
|
709
|
-
}
|
|
710
|
-
tokens = tokens.filter((token) => token.type !== " ");
|
|
711
|
-
const state = {
|
|
712
|
-
pos: 0,
|
|
713
|
-
reviver: options.reviver,
|
|
714
|
-
tolerant: options.tolerant || false,
|
|
715
|
-
// Ensure boolean
|
|
716
|
-
duplicate: options.duplicate,
|
|
717
|
-
// true = allow duplicate keys, false = reject duplicates
|
|
718
|
-
warnings: []
|
|
719
|
-
};
|
|
720
|
-
return parseAny(tokens, state, true);
|
|
721
|
-
} else {
|
|
722
|
-
tokens = lexer(text);
|
|
723
|
-
tokens = stripTrailingComma(tokens);
|
|
724
|
-
const newtext = tokens.reduce((str, token) => str + token.match, "");
|
|
725
|
-
return JSON.parse(
|
|
726
|
-
newtext,
|
|
727
|
-
options.reviver
|
|
728
|
-
);
|
|
729
|
-
}
|
|
730
|
-
}
|
|
819
|
+
tokens = tokens.filter((token) => token.type !== " ");
|
|
820
|
+
const state = createParseState(options);
|
|
821
|
+
return parseAny(tokens, state, true);
|
|
731
822
|
}
|
|
732
|
-
function
|
|
733
|
-
|
|
823
|
+
function parseWithTransform(text, options) {
|
|
824
|
+
let tokens = lexer(text);
|
|
825
|
+
tokens = stripTrailingComma(tokens);
|
|
826
|
+
const newtext = tokens.reduce((str, token) => str + token.match, "");
|
|
827
|
+
return JSON.parse(
|
|
828
|
+
newtext,
|
|
829
|
+
options.reviver
|
|
830
|
+
);
|
|
734
831
|
}
|
|
735
|
-
function
|
|
736
|
-
const
|
|
737
|
-
if (
|
|
738
|
-
return JSON.
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
}
|
|
743
|
-
if (Array.isArray(obj)) {
|
|
744
|
-
const elements = obj.map(stringify).join(",");
|
|
745
|
-
return "[" + elements + "]";
|
|
832
|
+
function parse(text, optsOrReviver) {
|
|
833
|
+
const options = normalizeParseOptions(optsOrReviver);
|
|
834
|
+
if (!(options.relaxed || options.warnings || options.tolerant) && options.duplicate) {
|
|
835
|
+
return JSON.parse(
|
|
836
|
+
text,
|
|
837
|
+
options.reviver
|
|
838
|
+
);
|
|
746
839
|
}
|
|
747
|
-
if (
|
|
748
|
-
|
|
749
|
-
keys.sort();
|
|
750
|
-
const pairs = keys.map((key) => stringifyPair(obj, key)).join(",");
|
|
751
|
-
return "{" + pairs + "}";
|
|
840
|
+
if (options.warnings || options.tolerant || !options.duplicate) {
|
|
841
|
+
return parseWithCustomParser(text, options);
|
|
752
842
|
}
|
|
753
|
-
return
|
|
843
|
+
return parseWithTransform(text, options);
|
|
754
844
|
}
|
|
755
845
|
|
|
756
|
-
// src/
|
|
757
|
-
function
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
846
|
+
// src/protocols/json-mix-protocol.ts
|
|
847
|
+
function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
|
|
848
|
+
var _a;
|
|
849
|
+
try {
|
|
850
|
+
const parsedToolCall = parse(toolCallJson);
|
|
851
|
+
processedElements.push({
|
|
852
|
+
type: "tool-call",
|
|
853
|
+
toolCallId: (0, import_provider_utils.generateId)(),
|
|
854
|
+
toolName: parsedToolCall.name,
|
|
855
|
+
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
856
|
+
});
|
|
857
|
+
} catch (error) {
|
|
858
|
+
logParseFailure({
|
|
859
|
+
phase: "generated-text",
|
|
860
|
+
reason: "Failed to parse tool call JSON segment",
|
|
861
|
+
snippet: fullMatch,
|
|
862
|
+
error
|
|
863
|
+
});
|
|
864
|
+
if (options == null ? void 0 : options.onError) {
|
|
865
|
+
options.onError(
|
|
866
|
+
"Could not process JSON tool call, keeping original text.",
|
|
867
|
+
{ toolCall: fullMatch, error }
|
|
868
|
+
);
|
|
869
|
+
}
|
|
870
|
+
processedElements.push({ type: "text", text: fullMatch });
|
|
764
871
|
}
|
|
765
|
-
return void 0;
|
|
766
872
|
}
|
|
767
|
-
function
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
if (envLower === "stream" || envLower === "parse" || envLower === "off") {
|
|
771
|
-
return envLower;
|
|
873
|
+
function addTextSegment(text, processedElements) {
|
|
874
|
+
if (text.trim()) {
|
|
875
|
+
processedElements.push({ type: "text", text });
|
|
772
876
|
}
|
|
773
|
-
const boolEnv = normalizeBooleanString(envLower);
|
|
774
|
-
if (boolEnv === true) return "stream";
|
|
775
|
-
if (envLower === "2") return "parse";
|
|
776
|
-
return "off";
|
|
777
877
|
}
|
|
778
|
-
function
|
|
779
|
-
|
|
878
|
+
function processMatchedToolCall(context) {
|
|
879
|
+
const { match, text, currentIndex, processedElements, options } = context;
|
|
880
|
+
const startIndex = match.index;
|
|
881
|
+
const toolCallJson = match[1];
|
|
882
|
+
if (startIndex > currentIndex) {
|
|
883
|
+
const textSegment = text.substring(currentIndex, startIndex);
|
|
884
|
+
addTextSegment(textSegment, processedElements);
|
|
885
|
+
}
|
|
886
|
+
if (toolCallJson) {
|
|
887
|
+
processToolCallJson(toolCallJson, match[0], processedElements, options);
|
|
888
|
+
}
|
|
889
|
+
return startIndex + match[0].length;
|
|
780
890
|
}
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
}
|
|
891
|
+
function flushBuffer(state, controller, toolCallStart) {
|
|
892
|
+
if (state.buffer.length === 0) {
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
if (!state.currentTextId) {
|
|
896
|
+
state.currentTextId = (0, import_provider_utils.generateId)();
|
|
897
|
+
controller.enqueue({ type: "text-start", id: state.currentTextId });
|
|
898
|
+
state.hasEmittedTextStart = true;
|
|
899
|
+
}
|
|
900
|
+
const delta = state.isInsideToolCall ? `${toolCallStart}${state.buffer}` : state.buffer;
|
|
901
|
+
controller.enqueue({
|
|
902
|
+
type: "text-delta",
|
|
903
|
+
id: state.currentTextId,
|
|
904
|
+
delta
|
|
905
|
+
});
|
|
906
|
+
state.buffer = "";
|
|
796
907
|
}
|
|
797
|
-
function
|
|
798
|
-
|
|
908
|
+
function closeTextBlock(state, controller) {
|
|
909
|
+
if (state.currentTextId && state.hasEmittedTextStart) {
|
|
910
|
+
controller.enqueue({ type: "text-end", id: state.currentTextId });
|
|
911
|
+
state.currentTextId = null;
|
|
912
|
+
state.hasEmittedTextStart = false;
|
|
913
|
+
}
|
|
799
914
|
}
|
|
800
|
-
function
|
|
801
|
-
|
|
915
|
+
function emitIncompleteToolCall(state, controller, toolCallStart) {
|
|
916
|
+
if (!state.currentToolCallJson) {
|
|
917
|
+
return;
|
|
918
|
+
}
|
|
919
|
+
logParseFailure({
|
|
920
|
+
phase: "stream",
|
|
921
|
+
reason: "Incomplete streaming tool call segment emitted as text",
|
|
922
|
+
snippet: `${toolCallStart}${state.currentToolCallJson}`
|
|
923
|
+
});
|
|
924
|
+
const errorId = (0, import_provider_utils.generateId)();
|
|
925
|
+
controller.enqueue({ type: "text-start", id: errorId });
|
|
926
|
+
controller.enqueue({
|
|
927
|
+
type: "text-delta",
|
|
928
|
+
id: errorId,
|
|
929
|
+
delta: `${toolCallStart}${state.currentToolCallJson}`
|
|
930
|
+
});
|
|
931
|
+
controller.enqueue({ type: "text-end", id: errorId });
|
|
932
|
+
state.currentToolCallJson = "";
|
|
802
933
|
}
|
|
803
|
-
function
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
}) {
|
|
807
|
-
if (originalText) {
|
|
808
|
-
const style = (() => {
|
|
809
|
-
const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW_STYLE || "bg";
|
|
810
|
-
const normalized = String(envVal).trim().toLowerCase();
|
|
811
|
-
if (normalized === "inverse" || normalized === "invert")
|
|
812
|
-
return "inverse";
|
|
813
|
-
if (normalized === "underline" || normalized === "ul")
|
|
814
|
-
return "underline";
|
|
815
|
-
if (normalized === "bold") return "bold";
|
|
816
|
-
if (normalized === "bg" || normalized === "background")
|
|
817
|
-
return "bg";
|
|
818
|
-
const asBool = normalizeBooleanString(normalized);
|
|
819
|
-
if (asBool === true) return "bg";
|
|
820
|
-
return "bg";
|
|
821
|
-
})();
|
|
822
|
-
const highlight = style === "inverse" ? cInverse : style === "underline" ? cUnderline : style === "bold" ? cBold : style === "bg" ? cBgGreen : cYellow;
|
|
823
|
-
const rendered = style === "bg" || style === "inverse" || style === "underline" || style === "bold" ? originalText.split(/\r?\n/).map((line) => line.length ? highlight(line) : line).join("\n") : highlight(originalText);
|
|
824
|
-
console.log(cGray("[debug:mw:origin]"), `
|
|
825
|
-
${rendered}`);
|
|
934
|
+
function handleFinishChunk(state, controller, toolCallStart, chunk) {
|
|
935
|
+
if (state.buffer.length > 0) {
|
|
936
|
+
flushBuffer(state, controller, toolCallStart);
|
|
826
937
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
938
|
+
closeTextBlock(state, controller);
|
|
939
|
+
emitIncompleteToolCall(state, controller, toolCallStart);
|
|
940
|
+
controller.enqueue(chunk);
|
|
941
|
+
}
|
|
942
|
+
function publishText(text, state, controller) {
|
|
943
|
+
if (state.isInsideToolCall) {
|
|
944
|
+
closeTextBlock(state, controller);
|
|
945
|
+
state.currentToolCallJson += text;
|
|
946
|
+
} else if (text.length > 0) {
|
|
947
|
+
if (!state.currentTextId) {
|
|
948
|
+
state.currentTextId = (0, import_provider_utils.generateId)();
|
|
949
|
+
controller.enqueue({ type: "text-start", id: state.currentTextId });
|
|
950
|
+
state.hasEmittedTextStart = true;
|
|
951
|
+
}
|
|
952
|
+
controller.enqueue({
|
|
953
|
+
type: "text-delta",
|
|
954
|
+
id: state.currentTextId,
|
|
955
|
+
delta: text
|
|
956
|
+
});
|
|
830
957
|
}
|
|
831
958
|
}
|
|
832
|
-
|
|
833
|
-
// src/utils/on-error.ts
|
|
834
|
-
function extractOnErrorOption(providerOptions) {
|
|
959
|
+
function emitToolCall(context) {
|
|
835
960
|
var _a;
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
961
|
+
const { state, controller, toolCallStart, toolCallEnd, options } = context;
|
|
962
|
+
try {
|
|
963
|
+
const parsedToolCall = parse(state.currentToolCallJson);
|
|
964
|
+
closeTextBlock(state, controller);
|
|
965
|
+
controller.enqueue({
|
|
966
|
+
type: "tool-call",
|
|
967
|
+
toolCallId: (0, import_provider_utils.generateId)(),
|
|
968
|
+
toolName: parsedToolCall.name,
|
|
969
|
+
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
970
|
+
});
|
|
971
|
+
} catch (error) {
|
|
972
|
+
logParseFailure({
|
|
973
|
+
phase: "stream",
|
|
974
|
+
reason: "Failed to parse streaming tool call JSON segment",
|
|
975
|
+
snippet: `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`,
|
|
976
|
+
error
|
|
977
|
+
});
|
|
978
|
+
const errorId = (0, import_provider_utils.generateId)();
|
|
979
|
+
controller.enqueue({ type: "text-start", id: errorId });
|
|
980
|
+
controller.enqueue({
|
|
981
|
+
type: "text-delta",
|
|
982
|
+
id: errorId,
|
|
983
|
+
delta: `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`
|
|
984
|
+
});
|
|
985
|
+
controller.enqueue({ type: "text-end", id: errorId });
|
|
986
|
+
if (options == null ? void 0 : options.onError) {
|
|
987
|
+
options.onError(
|
|
988
|
+
"Could not process streaming JSON tool call; emitting original text.",
|
|
989
|
+
{
|
|
990
|
+
toolCall: `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`
|
|
991
|
+
}
|
|
992
|
+
);
|
|
993
|
+
}
|
|
839
994
|
}
|
|
840
|
-
return void 0;
|
|
841
995
|
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
}))) || [];
|
|
853
|
-
}
|
|
854
|
-
function decodeOriginalTools(originalTools) {
|
|
855
|
-
const tools = (originalTools == null ? void 0 : originalTools.map(
|
|
856
|
-
(t) => ({
|
|
857
|
-
name: t.name,
|
|
858
|
-
inputSchema: JSON.parse(t.inputSchema)
|
|
859
|
-
})
|
|
860
|
-
)) || [];
|
|
861
|
-
return tools;
|
|
862
|
-
}
|
|
863
|
-
function isToolChoiceActive(params) {
|
|
864
|
-
var _a, _b, _c;
|
|
865
|
-
const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
|
|
866
|
-
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"));
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
// src/utils/type-guards.ts
|
|
870
|
-
function isToolCallContent(content) {
|
|
871
|
-
return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
|
|
872
|
-
(typeof content.input === "string" || typeof content.input === "object");
|
|
996
|
+
function processTagMatch(context) {
|
|
997
|
+
const { state } = context;
|
|
998
|
+
if (state.isInsideToolCall) {
|
|
999
|
+
emitToolCall(context);
|
|
1000
|
+
state.currentToolCallJson = "";
|
|
1001
|
+
state.isInsideToolCall = false;
|
|
1002
|
+
} else {
|
|
1003
|
+
state.currentToolCallJson = "";
|
|
1004
|
+
state.isInsideToolCall = true;
|
|
1005
|
+
}
|
|
873
1006
|
}
|
|
874
|
-
function
|
|
875
|
-
const
|
|
876
|
-
|
|
1007
|
+
function processBufferTags(context) {
|
|
1008
|
+
const { state, controller, toolCallStart, toolCallEnd } = context;
|
|
1009
|
+
let startIndex = getPotentialStartIndex(
|
|
1010
|
+
state.buffer,
|
|
1011
|
+
state.isInsideToolCall ? toolCallEnd : toolCallStart
|
|
1012
|
+
);
|
|
1013
|
+
while (startIndex != null) {
|
|
1014
|
+
const tag = state.isInsideToolCall ? toolCallEnd : toolCallStart;
|
|
1015
|
+
if (startIndex + tag.length > state.buffer.length) {
|
|
1016
|
+
break;
|
|
1017
|
+
}
|
|
1018
|
+
publishText(state.buffer.slice(0, startIndex), state, controller);
|
|
1019
|
+
state.buffer = state.buffer.slice(startIndex + tag.length);
|
|
1020
|
+
processTagMatch(context);
|
|
1021
|
+
startIndex = getPotentialStartIndex(
|
|
1022
|
+
state.buffer,
|
|
1023
|
+
state.isInsideToolCall ? toolCallEnd : toolCallStart
|
|
1024
|
+
);
|
|
1025
|
+
}
|
|
877
1026
|
}
|
|
878
|
-
function
|
|
879
|
-
|
|
1027
|
+
function handlePartialTag(state, controller, toolCallStart) {
|
|
1028
|
+
if (state.isInsideToolCall) {
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
const potentialIndex = getPotentialStartIndex(state.buffer, toolCallStart);
|
|
1032
|
+
if (potentialIndex != null && potentialIndex + toolCallStart.length > state.buffer.length) {
|
|
1033
|
+
publishText(state.buffer.slice(0, potentialIndex), state, controller);
|
|
1034
|
+
state.buffer = state.buffer.slice(potentialIndex);
|
|
1035
|
+
} else {
|
|
1036
|
+
publishText(state.buffer, state, controller);
|
|
1037
|
+
state.buffer = "";
|
|
1038
|
+
}
|
|
880
1039
|
}
|
|
881
|
-
|
|
882
|
-
// src/protocols/json-mix-protocol.ts
|
|
883
1040
|
var jsonMixProtocol = ({
|
|
884
1041
|
toolCallStart = "<tool_call>",
|
|
885
1042
|
toolCallEnd = "</tool_call>",
|
|
@@ -913,7 +1070,6 @@ var jsonMixProtocol = ({
|
|
|
913
1070
|
})}${toolResponseEnd}`;
|
|
914
1071
|
},
|
|
915
1072
|
parseGeneratedText({ text, options }) {
|
|
916
|
-
var _a;
|
|
917
1073
|
const startEsc = escapeRegExp(toolCallStart);
|
|
918
1074
|
const endEsc = escapeRegExp(toolCallEnd);
|
|
919
1075
|
const toolCallRegex = new RegExp(
|
|
@@ -922,185 +1078,50 @@ var jsonMixProtocol = ({
|
|
|
922
1078
|
);
|
|
923
1079
|
const processedElements = [];
|
|
924
1080
|
let currentIndex = 0;
|
|
925
|
-
let match;
|
|
926
|
-
while (
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
if (toolCallJson) {
|
|
936
|
-
try {
|
|
937
|
-
const parsedToolCall = robust_json_exports.parse(toolCallJson);
|
|
938
|
-
processedElements.push({
|
|
939
|
-
type: "tool-call",
|
|
940
|
-
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
941
|
-
toolName: parsedToolCall.name,
|
|
942
|
-
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
943
|
-
});
|
|
944
|
-
} catch (error) {
|
|
945
|
-
if (options == null ? void 0 : options.onError) {
|
|
946
|
-
options.onError(
|
|
947
|
-
"Could not process JSON tool call, keeping original text.",
|
|
948
|
-
{ toolCall: match[0], error }
|
|
949
|
-
);
|
|
950
|
-
}
|
|
951
|
-
processedElements.push({ type: "text", text: match[0] });
|
|
952
|
-
}
|
|
953
|
-
}
|
|
954
|
-
currentIndex = startIndex + match[0].length;
|
|
1081
|
+
let match = toolCallRegex.exec(text);
|
|
1082
|
+
while (match !== null) {
|
|
1083
|
+
currentIndex = processMatchedToolCall({
|
|
1084
|
+
match,
|
|
1085
|
+
text,
|
|
1086
|
+
currentIndex,
|
|
1087
|
+
processedElements,
|
|
1088
|
+
options
|
|
1089
|
+
});
|
|
1090
|
+
match = toolCallRegex.exec(text);
|
|
955
1091
|
}
|
|
956
1092
|
if (currentIndex < text.length) {
|
|
957
1093
|
const remainingText = text.substring(currentIndex);
|
|
958
|
-
|
|
959
|
-
processedElements.push({ type: "text", text: remainingText });
|
|
960
|
-
}
|
|
1094
|
+
addTextSegment(remainingText, processedElements);
|
|
961
1095
|
}
|
|
962
1096
|
return processedElements;
|
|
963
1097
|
},
|
|
964
1098
|
createStreamParser({ tools: _tools, options } = { tools: [] }) {
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1099
|
+
const state = {
|
|
1100
|
+
isInsideToolCall: false,
|
|
1101
|
+
buffer: "",
|
|
1102
|
+
currentToolCallJson: "",
|
|
1103
|
+
currentTextId: null,
|
|
1104
|
+
hasEmittedTextStart: false
|
|
1105
|
+
};
|
|
970
1106
|
return new TransformStream({
|
|
971
1107
|
transform(chunk, controller) {
|
|
972
|
-
var _a;
|
|
973
1108
|
if (chunk.type === "finish") {
|
|
974
|
-
|
|
975
|
-
if (!currentTextId) {
|
|
976
|
-
currentTextId = (0, import_provider_utils2.generateId)();
|
|
977
|
-
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
978
|
-
hasEmittedTextStart = true;
|
|
979
|
-
}
|
|
980
|
-
controller.enqueue({
|
|
981
|
-
type: "text-delta",
|
|
982
|
-
id: currentTextId,
|
|
983
|
-
delta: `${toolCallStart}${buffer}`
|
|
984
|
-
});
|
|
985
|
-
buffer = "";
|
|
986
|
-
} else if (!isInsideToolCall && buffer.length > 0) {
|
|
987
|
-
if (!currentTextId) {
|
|
988
|
-
currentTextId = (0, import_provider_utils2.generateId)();
|
|
989
|
-
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
990
|
-
hasEmittedTextStart = true;
|
|
991
|
-
}
|
|
992
|
-
controller.enqueue({
|
|
993
|
-
type: "text-delta",
|
|
994
|
-
id: currentTextId,
|
|
995
|
-
delta: buffer
|
|
996
|
-
});
|
|
997
|
-
buffer = "";
|
|
998
|
-
}
|
|
999
|
-
if (currentTextId && hasEmittedTextStart) {
|
|
1000
|
-
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1001
|
-
currentTextId = null;
|
|
1002
|
-
hasEmittedTextStart = false;
|
|
1003
|
-
}
|
|
1004
|
-
if (currentToolCallJson) {
|
|
1005
|
-
const errorId = (0, import_provider_utils2.generateId)();
|
|
1006
|
-
controller.enqueue({ type: "text-start", id: errorId });
|
|
1007
|
-
controller.enqueue({
|
|
1008
|
-
type: "text-delta",
|
|
1009
|
-
id: errorId,
|
|
1010
|
-
delta: `${toolCallStart}${currentToolCallJson}`
|
|
1011
|
-
});
|
|
1012
|
-
controller.enqueue({ type: "text-end", id: errorId });
|
|
1013
|
-
currentToolCallJson = "";
|
|
1014
|
-
}
|
|
1015
|
-
controller.enqueue(chunk);
|
|
1109
|
+
handleFinishChunk(state, controller, toolCallStart, chunk);
|
|
1016
1110
|
return;
|
|
1017
1111
|
}
|
|
1018
1112
|
if (chunk.type !== "text-delta") {
|
|
1019
1113
|
controller.enqueue(chunk);
|
|
1020
1114
|
return;
|
|
1021
1115
|
}
|
|
1022
|
-
buffer += chunk.delta;
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
} else if (text.length > 0) {
|
|
1032
|
-
if (!currentTextId) {
|
|
1033
|
-
currentTextId = (0, import_provider_utils2.generateId)();
|
|
1034
|
-
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
1035
|
-
hasEmittedTextStart = true;
|
|
1036
|
-
}
|
|
1037
|
-
controller.enqueue({
|
|
1038
|
-
type: "text-delta",
|
|
1039
|
-
id: currentTextId,
|
|
1040
|
-
delta: text
|
|
1041
|
-
});
|
|
1042
|
-
}
|
|
1043
|
-
};
|
|
1044
|
-
let startIndex;
|
|
1045
|
-
while ((startIndex = getPotentialStartIndex(
|
|
1046
|
-
buffer,
|
|
1047
|
-
isInsideToolCall ? toolCallEnd : toolCallStart
|
|
1048
|
-
)) != null) {
|
|
1049
|
-
const tag = isInsideToolCall ? toolCallEnd : toolCallStart;
|
|
1050
|
-
if (startIndex + tag.length > buffer.length) {
|
|
1051
|
-
break;
|
|
1052
|
-
}
|
|
1053
|
-
publish(buffer.slice(0, startIndex));
|
|
1054
|
-
buffer = buffer.slice(startIndex + tag.length);
|
|
1055
|
-
if (!isInsideToolCall) {
|
|
1056
|
-
currentToolCallJson = "";
|
|
1057
|
-
isInsideToolCall = true;
|
|
1058
|
-
} else {
|
|
1059
|
-
try {
|
|
1060
|
-
const parsedToolCall = robust_json_exports.parse(currentToolCallJson);
|
|
1061
|
-
if (currentTextId && hasEmittedTextStart) {
|
|
1062
|
-
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1063
|
-
currentTextId = null;
|
|
1064
|
-
hasEmittedTextStart = false;
|
|
1065
|
-
}
|
|
1066
|
-
controller.enqueue({
|
|
1067
|
-
type: "tool-call",
|
|
1068
|
-
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1069
|
-
toolName: parsedToolCall.name,
|
|
1070
|
-
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1071
|
-
});
|
|
1072
|
-
} catch (e) {
|
|
1073
|
-
const errorId = (0, import_provider_utils2.generateId)();
|
|
1074
|
-
controller.enqueue({ type: "text-start", id: errorId });
|
|
1075
|
-
controller.enqueue({
|
|
1076
|
-
type: "text-delta",
|
|
1077
|
-
id: errorId,
|
|
1078
|
-
delta: `${toolCallStart}${currentToolCallJson}${toolCallEnd}`
|
|
1079
|
-
});
|
|
1080
|
-
controller.enqueue({ type: "text-end", id: errorId });
|
|
1081
|
-
if (options == null ? void 0 : options.onError) {
|
|
1082
|
-
options.onError(
|
|
1083
|
-
"Could not process streaming JSON tool call; emitting original text.",
|
|
1084
|
-
{
|
|
1085
|
-
toolCall: `${toolCallStart}${currentToolCallJson}${toolCallEnd}`
|
|
1086
|
-
}
|
|
1087
|
-
);
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
currentToolCallJson = "";
|
|
1091
|
-
isInsideToolCall = false;
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
if (!isInsideToolCall) {
|
|
1095
|
-
const potentialIndex = getPotentialStartIndex(buffer, toolCallStart);
|
|
1096
|
-
if (potentialIndex != null && potentialIndex + toolCallStart.length > buffer.length) {
|
|
1097
|
-
publish(buffer.slice(0, potentialIndex));
|
|
1098
|
-
buffer = buffer.slice(potentialIndex);
|
|
1099
|
-
} else {
|
|
1100
|
-
publish(buffer);
|
|
1101
|
-
buffer = "";
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1116
|
+
state.buffer += chunk.delta;
|
|
1117
|
+
processBufferTags({
|
|
1118
|
+
state,
|
|
1119
|
+
controller,
|
|
1120
|
+
toolCallStart,
|
|
1121
|
+
toolCallEnd,
|
|
1122
|
+
options
|
|
1123
|
+
});
|
|
1124
|
+
handlePartialTag(state, controller, toolCallStart);
|
|
1104
1125
|
}
|
|
1105
1126
|
});
|
|
1106
1127
|
},
|
|
@@ -1109,23 +1130,706 @@ var jsonMixProtocol = ({
|
|
|
1109
1130
|
const endEsc = escapeRegExp(toolCallEnd);
|
|
1110
1131
|
const regex = new RegExp(`${startEsc}([\0-\uFFFF]*?)${endEsc}`, "gs");
|
|
1111
1132
|
const segments = [];
|
|
1112
|
-
let m;
|
|
1113
|
-
while (
|
|
1133
|
+
let m = regex.exec(text);
|
|
1134
|
+
while (m != null) {
|
|
1114
1135
|
segments.push(m[0]);
|
|
1136
|
+
m = regex.exec(text);
|
|
1115
1137
|
}
|
|
1116
1138
|
return segments;
|
|
1117
1139
|
}
|
|
1118
1140
|
});
|
|
1119
1141
|
|
|
1120
1142
|
// src/protocols/morph-xml-protocol.ts
|
|
1121
|
-
var
|
|
1122
|
-
var
|
|
1143
|
+
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
1144
|
+
var import_rxml = require("@ai-sdk-tool/rxml");
|
|
1145
|
+
|
|
1146
|
+
// src/utils/type-guards.ts
|
|
1147
|
+
function isToolCallContent(content) {
|
|
1148
|
+
return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
|
|
1149
|
+
(typeof content.input === "string" || typeof content.input === "object");
|
|
1150
|
+
}
|
|
1151
|
+
function hasInputProperty(obj) {
|
|
1152
|
+
return typeof obj === "object" && obj !== null && "input" in obj;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
// src/protocols/morph-xml-protocol.ts
|
|
1156
|
+
var WHITESPACE_REGEX2 = /\s/;
|
|
1157
|
+
var MALFORMED_CLOSE_RE = /<\/\s+([A-Za-z0-9_:-]+)\s*>/;
|
|
1158
|
+
var MALFORMED_CLOSE_RE_G = /<\/\s+([A-Za-z0-9_:-]+)\s*>/g;
|
|
1159
|
+
var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
|
|
1160
|
+
var STATUS_TO_STEP_BOUNDARY_RE = /<\/status>\s*<step>/g;
|
|
1161
|
+
var STEP_TAG_RE = /<step>([\s\S]*?)<\/step>/i;
|
|
1162
|
+
var STATUS_TAG_RE = /<status>([\s\S]*?)<\/status>/i;
|
|
1163
|
+
function normalizeCloseTags(xml) {
|
|
1164
|
+
return xml.replace(MALFORMED_CLOSE_RE_G, "</$1>");
|
|
1165
|
+
}
|
|
1166
|
+
function escapeInvalidLt(xml) {
|
|
1167
|
+
const len = xml.length;
|
|
1168
|
+
let out = "";
|
|
1169
|
+
for (let i = 0; i < len; i += 1) {
|
|
1170
|
+
const ch = xml[i];
|
|
1171
|
+
if (ch === "<") {
|
|
1172
|
+
const next = i + 1 < len ? xml[i + 1] : "";
|
|
1173
|
+
if (!(NAME_CHAR_RE.test(next) || next === "/" || next === "!" || next === "?")) {
|
|
1174
|
+
out += "<";
|
|
1175
|
+
continue;
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
out += ch;
|
|
1179
|
+
}
|
|
1180
|
+
return out;
|
|
1181
|
+
}
|
|
1182
|
+
function shouldDeduplicateStringTags(schema) {
|
|
1183
|
+
const unwrapped = (0, import_rxml.unwrapJsonSchema)(schema);
|
|
1184
|
+
if (!unwrapped || typeof unwrapped !== "object") {
|
|
1185
|
+
return false;
|
|
1186
|
+
}
|
|
1187
|
+
const props = unwrapped.properties;
|
|
1188
|
+
if (!props) {
|
|
1189
|
+
return false;
|
|
1190
|
+
}
|
|
1191
|
+
const commandRaw = props.command;
|
|
1192
|
+
if (!commandRaw) {
|
|
1193
|
+
return false;
|
|
1194
|
+
}
|
|
1195
|
+
const command = (0, import_rxml.unwrapJsonSchema)(commandRaw);
|
|
1196
|
+
return (command == null ? void 0 : command.type) === "array";
|
|
1197
|
+
}
|
|
1198
|
+
function tryParseSecondaryXml(content, toolSchema, options) {
|
|
1199
|
+
const normalized = normalizeCloseTags(content);
|
|
1200
|
+
const balanced = balanceTags(content);
|
|
1201
|
+
const hasMalformedClose = MALFORMED_CLOSE_RE.test(content);
|
|
1202
|
+
if (!hasMalformedClose && balanced.length > normalized.length) {
|
|
1203
|
+
return null;
|
|
1204
|
+
}
|
|
1205
|
+
try {
|
|
1206
|
+
let parsed = (0, import_rxml.parse)(balanced, toolSchema, {
|
|
1207
|
+
onError: options == null ? void 0 : options.onError,
|
|
1208
|
+
noChildNodes: []
|
|
1209
|
+
});
|
|
1210
|
+
parsed = repairParsedAgainstSchema(parsed, toolSchema, options);
|
|
1211
|
+
return parsed;
|
|
1212
|
+
} catch (_e) {
|
|
1213
|
+
if (shouldDeduplicateStringTags(toolSchema)) {
|
|
1214
|
+
const deduped = dedupeStringTagsAgainstSchema(balanced, toolSchema);
|
|
1215
|
+
if (deduped !== balanced) {
|
|
1216
|
+
try {
|
|
1217
|
+
let reparsed = (0, import_rxml.parse)(deduped, toolSchema, {
|
|
1218
|
+
onError: options == null ? void 0 : options.onError,
|
|
1219
|
+
noChildNodes: []
|
|
1220
|
+
});
|
|
1221
|
+
reparsed = repairParsedAgainstSchema(reparsed, toolSchema, options);
|
|
1222
|
+
return reparsed;
|
|
1223
|
+
} catch (_) {
|
|
1224
|
+
return null;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
return null;
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
function balanceTags(xml) {
|
|
1232
|
+
const src = normalizeCloseTags(xml).replace(
|
|
1233
|
+
STATUS_TO_STEP_BOUNDARY_RE,
|
|
1234
|
+
"</status></step><step>"
|
|
1235
|
+
);
|
|
1236
|
+
let i = 0;
|
|
1237
|
+
const len = src.length;
|
|
1238
|
+
const out = [];
|
|
1239
|
+
const stack = [];
|
|
1240
|
+
while (i < len) {
|
|
1241
|
+
const lt = src.indexOf("<", i);
|
|
1242
|
+
if (lt === -1) {
|
|
1243
|
+
out.push(src.slice(i));
|
|
1244
|
+
break;
|
|
1245
|
+
}
|
|
1246
|
+
out.push(src.slice(i, lt));
|
|
1247
|
+
if (lt + 1 >= len) {
|
|
1248
|
+
break;
|
|
1249
|
+
}
|
|
1250
|
+
const next = src[lt + 1];
|
|
1251
|
+
if (next === "!" || next === "?") {
|
|
1252
|
+
i = handleSpecialTagSegment(src, lt, out);
|
|
1253
|
+
continue;
|
|
1254
|
+
}
|
|
1255
|
+
if (next === "/") {
|
|
1256
|
+
i = handleClosingTagSegment(src, lt, out, stack);
|
|
1257
|
+
continue;
|
|
1258
|
+
}
|
|
1259
|
+
i = handleOpeningTagSegment(src, lt, out, stack);
|
|
1260
|
+
}
|
|
1261
|
+
for (let k = stack.length - 1; k >= 0; k -= 1) {
|
|
1262
|
+
out.push(`</${stack[k]}>`);
|
|
1263
|
+
}
|
|
1264
|
+
return out.join("");
|
|
1265
|
+
}
|
|
1266
|
+
function skipWs(s, p, len) {
|
|
1267
|
+
let idx = p;
|
|
1268
|
+
while (idx < len && WHITESPACE_REGEX2.test(s[idx])) {
|
|
1269
|
+
idx += 1;
|
|
1270
|
+
}
|
|
1271
|
+
return idx;
|
|
1272
|
+
}
|
|
1273
|
+
function parseTagNameAt(s, p, len) {
|
|
1274
|
+
let idx = p;
|
|
1275
|
+
const start = idx;
|
|
1276
|
+
while (idx < len && NAME_CHAR_RE.test(s[idx])) {
|
|
1277
|
+
idx += 1;
|
|
1278
|
+
}
|
|
1279
|
+
return { name: s.slice(start, idx), pos: idx };
|
|
1280
|
+
}
|
|
1281
|
+
function handleSpecialTagSegment(src, lt, out) {
|
|
1282
|
+
const gt = src.indexOf(">", lt + 1);
|
|
1283
|
+
if (gt === -1) {
|
|
1284
|
+
out.push(src.slice(lt));
|
|
1285
|
+
return src.length;
|
|
1286
|
+
}
|
|
1287
|
+
out.push(src.slice(lt, gt + 1));
|
|
1288
|
+
return gt + 1;
|
|
1289
|
+
}
|
|
1290
|
+
function handleClosingTagSegment(src, lt, out, stack) {
|
|
1291
|
+
const len = src.length;
|
|
1292
|
+
let p = skipWs(src, lt + 2, len);
|
|
1293
|
+
const { name, pos } = parseTagNameAt(src, p, len);
|
|
1294
|
+
p = pos;
|
|
1295
|
+
const gt = src.indexOf(">", p);
|
|
1296
|
+
const closingText = gt === -1 ? src.slice(lt) : src.slice(lt, gt + 1);
|
|
1297
|
+
const idx = stack.lastIndexOf(name);
|
|
1298
|
+
if (idx !== -1) {
|
|
1299
|
+
for (let k = stack.length - 1; k > idx; k -= 1) {
|
|
1300
|
+
out.push(`</${stack[k]}>`);
|
|
1301
|
+
stack.pop();
|
|
1302
|
+
}
|
|
1303
|
+
out.push(closingText);
|
|
1304
|
+
stack.pop();
|
|
1305
|
+
}
|
|
1306
|
+
return gt === -1 ? len : gt + 1;
|
|
1307
|
+
}
|
|
1308
|
+
function handleOpeningTagSegment(src, lt, out, stack) {
|
|
1309
|
+
const len = src.length;
|
|
1310
|
+
let p = skipWs(src, lt + 1, len);
|
|
1311
|
+
const nameStart = p;
|
|
1312
|
+
const parsed = parseTagNameAt(src, p, len);
|
|
1313
|
+
p = parsed.pos;
|
|
1314
|
+
const name = src.slice(nameStart, p);
|
|
1315
|
+
const q = src.indexOf(">", p);
|
|
1316
|
+
if (q === -1) {
|
|
1317
|
+
out.push(src.slice(lt));
|
|
1318
|
+
return len;
|
|
1319
|
+
}
|
|
1320
|
+
let r = q - 1;
|
|
1321
|
+
while (r >= nameStart && WHITESPACE_REGEX2.test(src[r])) {
|
|
1322
|
+
r -= 1;
|
|
1323
|
+
}
|
|
1324
|
+
const selfClosing = src[r] === "/";
|
|
1325
|
+
out.push(src.slice(lt, q + 1));
|
|
1326
|
+
if (!selfClosing && name) {
|
|
1327
|
+
stack.push(name);
|
|
1328
|
+
}
|
|
1329
|
+
return q + 1;
|
|
1330
|
+
}
|
|
1331
|
+
function repairParsedAgainstSchema(input, schema, options) {
|
|
1332
|
+
if (!input || typeof input !== "object") {
|
|
1333
|
+
return input;
|
|
1334
|
+
}
|
|
1335
|
+
const unwrapped = (0, import_rxml.unwrapJsonSchema)(schema);
|
|
1336
|
+
if (!unwrapped || typeof unwrapped !== "object") {
|
|
1337
|
+
return input;
|
|
1338
|
+
}
|
|
1339
|
+
const properties = unwrapped.properties;
|
|
1340
|
+
if (!properties) {
|
|
1341
|
+
return input;
|
|
1342
|
+
}
|
|
1343
|
+
applySchemaProps(input, properties, options);
|
|
1344
|
+
return input;
|
|
1345
|
+
}
|
|
1346
|
+
function applySchemaProps(obj, properties, options) {
|
|
1347
|
+
for (const key of Object.keys(obj)) {
|
|
1348
|
+
const propSchema = properties[key];
|
|
1349
|
+
if (!propSchema) {
|
|
1350
|
+
continue;
|
|
1351
|
+
}
|
|
1352
|
+
const prop = (0, import_rxml.unwrapJsonSchema)(propSchema);
|
|
1353
|
+
const propType = prop.type;
|
|
1354
|
+
if (propType === "array" && prop.items) {
|
|
1355
|
+
const itemSchemaRaw = prop.items;
|
|
1356
|
+
const itemSchema = (0, import_rxml.unwrapJsonSchema)(itemSchemaRaw);
|
|
1357
|
+
obj[key] = coerceArrayItems(obj[key], itemSchema, options);
|
|
1358
|
+
continue;
|
|
1359
|
+
}
|
|
1360
|
+
if (propType === "object") {
|
|
1361
|
+
const val = obj[key];
|
|
1362
|
+
if (val && typeof val === "object") {
|
|
1363
|
+
obj[key] = repairParsedAgainstSchema(
|
|
1364
|
+
val,
|
|
1365
|
+
prop,
|
|
1366
|
+
options
|
|
1367
|
+
);
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
function coerceArrayItems(val, itemSchema, options) {
|
|
1373
|
+
if (!Array.isArray(val)) {
|
|
1374
|
+
return val;
|
|
1375
|
+
}
|
|
1376
|
+
return val.map((v) => coerceArrayItem(v, itemSchema, options));
|
|
1377
|
+
}
|
|
1378
|
+
function coerceArrayItem(v, itemSchema, options) {
|
|
1379
|
+
const itemType = itemSchema == null ? void 0 : itemSchema.type;
|
|
1380
|
+
if (typeof v === "string" && itemType === "object") {
|
|
1381
|
+
const parsed = tryParseStringToSchemaObject(v, itemSchema, options);
|
|
1382
|
+
if (parsed !== null) {
|
|
1383
|
+
return parsed;
|
|
1384
|
+
}
|
|
1385
|
+
const fallback = extractStepStatusFromString(normalizeCloseTags(v));
|
|
1386
|
+
if (fallback) {
|
|
1387
|
+
return fallback;
|
|
1388
|
+
}
|
|
1389
|
+
return v;
|
|
1390
|
+
}
|
|
1391
|
+
if (v && typeof v === "object" && itemType === "object") {
|
|
1392
|
+
return repairParsedAgainstSchema(
|
|
1393
|
+
v,
|
|
1394
|
+
itemSchema,
|
|
1395
|
+
options
|
|
1396
|
+
);
|
|
1397
|
+
}
|
|
1398
|
+
return v;
|
|
1399
|
+
}
|
|
1400
|
+
function getStringPropertyNames(schema) {
|
|
1401
|
+
const unwrapped = (0, import_rxml.unwrapJsonSchema)(schema);
|
|
1402
|
+
if (!unwrapped || typeof unwrapped !== "object") {
|
|
1403
|
+
return [];
|
|
1404
|
+
}
|
|
1405
|
+
const props = unwrapped.properties;
|
|
1406
|
+
if (!props) {
|
|
1407
|
+
return [];
|
|
1408
|
+
}
|
|
1409
|
+
const names = [];
|
|
1410
|
+
for (const key of Object.keys(props)) {
|
|
1411
|
+
const prop = (0, import_rxml.unwrapJsonSchema)(
|
|
1412
|
+
props[key]
|
|
1413
|
+
);
|
|
1414
|
+
const type = prop.type;
|
|
1415
|
+
if (type === "string") {
|
|
1416
|
+
names.push(key);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
return names;
|
|
1420
|
+
}
|
|
1421
|
+
function escapeRegExp2(s) {
|
|
1422
|
+
return s.replace(/[.*+?^${}()|[\\]\\]/g, "\\$&");
|
|
1423
|
+
}
|
|
1424
|
+
function dedupeStringTagsAgainstSchema(xml, schema) {
|
|
1425
|
+
const names = getStringPropertyNames(schema);
|
|
1426
|
+
let out = xml;
|
|
1427
|
+
for (const key of names) {
|
|
1428
|
+
out = dedupeSingleTag(out, key);
|
|
1429
|
+
}
|
|
1430
|
+
return out;
|
|
1431
|
+
}
|
|
1432
|
+
function dedupeSingleTag(xml, key) {
|
|
1433
|
+
var _a, _b;
|
|
1434
|
+
const escaped = escapeRegExp2(key);
|
|
1435
|
+
const re = new RegExp(`<${escaped}>([\\s\\S]*?)<\\/${escaped}>`, "g");
|
|
1436
|
+
const matches = Array.from(xml.matchAll(re));
|
|
1437
|
+
if (matches.length <= 1) {
|
|
1438
|
+
return xml;
|
|
1439
|
+
}
|
|
1440
|
+
const last = matches.at(-1);
|
|
1441
|
+
let result = "";
|
|
1442
|
+
let cursor = 0;
|
|
1443
|
+
for (const m of matches) {
|
|
1444
|
+
const idx = (_a = m.index) != null ? _a : 0;
|
|
1445
|
+
result += xml.slice(cursor, idx);
|
|
1446
|
+
if (last && idx === ((_b = last.index) != null ? _b : -1)) {
|
|
1447
|
+
result += m[0];
|
|
1448
|
+
}
|
|
1449
|
+
cursor = idx + m[0].length;
|
|
1450
|
+
}
|
|
1451
|
+
result += xml.slice(cursor);
|
|
1452
|
+
return result;
|
|
1453
|
+
}
|
|
1454
|
+
function tryParseStringToSchemaObject(xml, itemSchema, options) {
|
|
1455
|
+
try {
|
|
1456
|
+
const fixed = (0, import_rxml.parse)(normalizeCloseTags(xml), itemSchema, {
|
|
1457
|
+
onError: options == null ? void 0 : options.onError,
|
|
1458
|
+
noChildNodes: []
|
|
1459
|
+
});
|
|
1460
|
+
return typeof fixed === "string" ? null : fixed;
|
|
1461
|
+
} catch (e) {
|
|
1462
|
+
return null;
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
function extractStepStatusFromString(normXml) {
|
|
1466
|
+
const stepMatch = normXml.match(STEP_TAG_RE);
|
|
1467
|
+
const statusMatch = normXml.match(STATUS_TAG_RE);
|
|
1468
|
+
if (stepMatch && statusMatch) {
|
|
1469
|
+
return { step: stepMatch[1], status: statusMatch[1] };
|
|
1470
|
+
}
|
|
1471
|
+
return null;
|
|
1472
|
+
}
|
|
1473
|
+
function processTextBeforeToolCall(text, currentIndex, toolCallStartIndex, processedElements) {
|
|
1474
|
+
if (toolCallStartIndex > currentIndex) {
|
|
1475
|
+
const textSegment = text.substring(currentIndex, toolCallStartIndex);
|
|
1476
|
+
if (textSegment.trim()) {
|
|
1477
|
+
processedElements.push({ type: "text", text: textSegment });
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
return currentIndex;
|
|
1481
|
+
}
|
|
1482
|
+
function processToolCall(params) {
|
|
1483
|
+
var _a;
|
|
1484
|
+
const { toolCall, tools, options, text, processedElements } = params;
|
|
1485
|
+
const toolSchema = getToolSchema(tools, toolCall.toolName);
|
|
1486
|
+
try {
|
|
1487
|
+
const primary = escapeInvalidLt(normalizeCloseTags(toolCall.content));
|
|
1488
|
+
let parsed = (0, import_rxml.parse)(primary, toolSchema, {
|
|
1489
|
+
onError: options == null ? void 0 : options.onError,
|
|
1490
|
+
// Disable HTML self-closing tag behavior to allow base, meta, link etc. as regular tags
|
|
1491
|
+
noChildNodes: []
|
|
1492
|
+
});
|
|
1493
|
+
parsed = repairParsedAgainstSchema(parsed, toolSchema, options);
|
|
1494
|
+
processedElements.push({
|
|
1495
|
+
type: "tool-call",
|
|
1496
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1497
|
+
toolName: toolCall.toolName,
|
|
1498
|
+
input: JSON.stringify(parsed)
|
|
1499
|
+
});
|
|
1500
|
+
} catch (error) {
|
|
1501
|
+
const reparsed = tryParseSecondaryXml(
|
|
1502
|
+
toolCall.content,
|
|
1503
|
+
toolSchema,
|
|
1504
|
+
options
|
|
1505
|
+
);
|
|
1506
|
+
if (reparsed !== null) {
|
|
1507
|
+
processedElements.push({
|
|
1508
|
+
type: "tool-call",
|
|
1509
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1510
|
+
toolName: toolCall.toolName,
|
|
1511
|
+
input: JSON.stringify(reparsed)
|
|
1512
|
+
});
|
|
1513
|
+
return;
|
|
1514
|
+
}
|
|
1515
|
+
const originalCallText = text.substring(
|
|
1516
|
+
toolCall.startIndex,
|
|
1517
|
+
toolCall.endIndex
|
|
1518
|
+
);
|
|
1519
|
+
const message = `Could not process XML tool call, keeping original text: ${originalCallText}`;
|
|
1520
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
|
|
1521
|
+
toolCall: originalCallText,
|
|
1522
|
+
toolName: toolCall.toolName,
|
|
1523
|
+
error
|
|
1524
|
+
});
|
|
1525
|
+
processedElements.push({ type: "text", text: originalCallText });
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
function addRemainingText(text, currentIndex, processedElements) {
|
|
1529
|
+
if (currentIndex < text.length) {
|
|
1530
|
+
const remainingText = text.substring(currentIndex);
|
|
1531
|
+
if (remainingText.trim()) {
|
|
1532
|
+
processedElements.push({ type: "text", text: remainingText });
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
function handleStreamingToolCallEnd(params) {
|
|
1537
|
+
const { toolContent, currentToolCall, tools, options, ctrl, flushText } = params;
|
|
1538
|
+
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
1539
|
+
try {
|
|
1540
|
+
const primary = escapeInvalidLt(normalizeCloseTags(toolContent));
|
|
1541
|
+
let parsed = (0, import_rxml.parse)(primary, toolSchema, {
|
|
1542
|
+
onError: options == null ? void 0 : options.onError,
|
|
1543
|
+
noChildNodes: []
|
|
1544
|
+
});
|
|
1545
|
+
parsed = repairParsedAgainstSchema(parsed, toolSchema, options);
|
|
1546
|
+
flushText(ctrl);
|
|
1547
|
+
ctrl.enqueue({
|
|
1548
|
+
type: "tool-call",
|
|
1549
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1550
|
+
toolName: currentToolCall.name,
|
|
1551
|
+
input: JSON.stringify(parsed)
|
|
1552
|
+
});
|
|
1553
|
+
} catch (error) {
|
|
1554
|
+
const parsed = tryParseSecondaryXml(toolContent, toolSchema, options);
|
|
1555
|
+
if (parsed !== null) {
|
|
1556
|
+
flushText(ctrl);
|
|
1557
|
+
ctrl.enqueue({
|
|
1558
|
+
type: "tool-call",
|
|
1559
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1560
|
+
toolName: currentToolCall.name,
|
|
1561
|
+
input: JSON.stringify(parsed)
|
|
1562
|
+
});
|
|
1563
|
+
return;
|
|
1564
|
+
}
|
|
1565
|
+
handleStreamingToolCallError({
|
|
1566
|
+
error,
|
|
1567
|
+
currentToolCall,
|
|
1568
|
+
toolContent,
|
|
1569
|
+
options,
|
|
1570
|
+
ctrl,
|
|
1571
|
+
flushText
|
|
1572
|
+
});
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
function handleStreamingToolCallError(params) {
|
|
1576
|
+
var _a;
|
|
1577
|
+
const { error, currentToolCall, toolContent, options, ctrl, flushText } = params;
|
|
1578
|
+
const endTag = `</${currentToolCall.name}>`;
|
|
1579
|
+
const originalCallText = `<${currentToolCall.name}>${toolContent}${endTag}`;
|
|
1580
|
+
let message = "Could not process streaming XML tool call; emitting original text.";
|
|
1581
|
+
if (error instanceof import_rxml.RXMLDuplicateStringTagError) {
|
|
1582
|
+
message = `Duplicate string tags detected in streaming tool call '${currentToolCall.name}'; emitting original text.`;
|
|
1583
|
+
} else if (error instanceof import_rxml.RXMLCoercionError) {
|
|
1584
|
+
message = `Failed to coerce arguments for streaming tool call '${currentToolCall.name}'; emitting original text.`;
|
|
1585
|
+
} else if (error instanceof import_rxml.RXMLParseError) {
|
|
1586
|
+
message = `Failed to parse XML for streaming tool call '${currentToolCall.name}'; emitting original text.`;
|
|
1587
|
+
}
|
|
1588
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
|
|
1589
|
+
toolCall: originalCallText,
|
|
1590
|
+
toolName: currentToolCall.name,
|
|
1591
|
+
error
|
|
1592
|
+
});
|
|
1593
|
+
flushText(ctrl, originalCallText);
|
|
1594
|
+
}
|
|
1595
|
+
function findEarliestToolTag(buffer, toolNames) {
|
|
1596
|
+
let bestIndex = -1;
|
|
1597
|
+
let bestName = "";
|
|
1598
|
+
let bestSelfClosing = false;
|
|
1599
|
+
if (toolNames.length > 0) {
|
|
1600
|
+
for (const name of toolNames) {
|
|
1601
|
+
const openTag = `<${name}>`;
|
|
1602
|
+
const selfTag = `<${name}/>`;
|
|
1603
|
+
const idxOpen = buffer.indexOf(openTag);
|
|
1604
|
+
const idxSelf = buffer.indexOf(selfTag);
|
|
1605
|
+
if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
|
|
1606
|
+
bestIndex = idxOpen;
|
|
1607
|
+
bestName = name;
|
|
1608
|
+
bestSelfClosing = false;
|
|
1609
|
+
}
|
|
1610
|
+
if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
|
|
1611
|
+
bestIndex = idxSelf;
|
|
1612
|
+
bestName = name;
|
|
1613
|
+
bestSelfClosing = true;
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
return { index: bestIndex, name: bestName, selfClosing: bestSelfClosing };
|
|
1618
|
+
}
|
|
1619
|
+
function handleNoToolTagInBuffer(buffer, maxStartTagLen, controller, flushText) {
|
|
1620
|
+
const tail = Math.max(0, maxStartTagLen - 1);
|
|
1621
|
+
const safeLen = Math.max(0, buffer.length - tail);
|
|
1622
|
+
if (safeLen > 0) {
|
|
1623
|
+
const textToFlush = buffer.slice(0, safeLen);
|
|
1624
|
+
flushText(controller, textToFlush);
|
|
1625
|
+
return { buffer: buffer.slice(safeLen), shouldContinue: true };
|
|
1626
|
+
}
|
|
1627
|
+
return { buffer, shouldContinue: false };
|
|
1628
|
+
}
|
|
1629
|
+
function processToolCallInBuffer(params) {
|
|
1630
|
+
const {
|
|
1631
|
+
buffer,
|
|
1632
|
+
currentToolCall,
|
|
1633
|
+
tools,
|
|
1634
|
+
options,
|
|
1635
|
+
controller,
|
|
1636
|
+
flushText,
|
|
1637
|
+
setBuffer
|
|
1638
|
+
} = params;
|
|
1639
|
+
const endTag = `</${currentToolCall.name}>`;
|
|
1640
|
+
const normalized = normalizeCloseTags(buffer);
|
|
1641
|
+
const effectiveBuffer = normalized;
|
|
1642
|
+
const endTagIndex = effectiveBuffer.indexOf(endTag);
|
|
1643
|
+
if (endTagIndex !== -1) {
|
|
1644
|
+
const toolContent = effectiveBuffer.substring(0, endTagIndex);
|
|
1645
|
+
const newBuffer = effectiveBuffer.substring(endTagIndex + endTag.length);
|
|
1646
|
+
setBuffer("");
|
|
1647
|
+
handleStreamingToolCallEnd({
|
|
1648
|
+
toolContent,
|
|
1649
|
+
currentToolCall,
|
|
1650
|
+
tools,
|
|
1651
|
+
options,
|
|
1652
|
+
ctrl: controller,
|
|
1653
|
+
flushText
|
|
1654
|
+
});
|
|
1655
|
+
setBuffer(newBuffer);
|
|
1656
|
+
return { buffer: newBuffer, currentToolCall: null, shouldBreak: false };
|
|
1657
|
+
}
|
|
1658
|
+
return { buffer: effectiveBuffer, currentToolCall, shouldBreak: true };
|
|
1659
|
+
}
|
|
1660
|
+
function processNoToolCallInBuffer(params) {
|
|
1661
|
+
const {
|
|
1662
|
+
buffer,
|
|
1663
|
+
toolNames,
|
|
1664
|
+
maxStartTagLen,
|
|
1665
|
+
controller,
|
|
1666
|
+
flushText,
|
|
1667
|
+
tools,
|
|
1668
|
+
options
|
|
1669
|
+
} = params;
|
|
1670
|
+
const {
|
|
1671
|
+
index: earliestStartTagIndex,
|
|
1672
|
+
name: earliestToolName,
|
|
1673
|
+
selfClosing
|
|
1674
|
+
} = findEarliestToolTag(buffer, toolNames);
|
|
1675
|
+
if (earliestStartTagIndex !== -1) {
|
|
1676
|
+
const textBeforeTag = buffer.substring(0, earliestStartTagIndex);
|
|
1677
|
+
flushText(controller, textBeforeTag);
|
|
1678
|
+
if (selfClosing) {
|
|
1679
|
+
const selfTag = `<${earliestToolName}/>`;
|
|
1680
|
+
const newBuffer2 = buffer.substring(
|
|
1681
|
+
earliestStartTagIndex + selfTag.length
|
|
1682
|
+
);
|
|
1683
|
+
handleStreamingToolCallEnd({
|
|
1684
|
+
toolContent: "",
|
|
1685
|
+
currentToolCall: { name: earliestToolName, content: "" },
|
|
1686
|
+
tools,
|
|
1687
|
+
options,
|
|
1688
|
+
ctrl: controller,
|
|
1689
|
+
flushText
|
|
1690
|
+
});
|
|
1691
|
+
return {
|
|
1692
|
+
buffer: newBuffer2,
|
|
1693
|
+
currentToolCall: null,
|
|
1694
|
+
shouldBreak: false,
|
|
1695
|
+
shouldContinue: false
|
|
1696
|
+
};
|
|
1697
|
+
}
|
|
1698
|
+
const startTag = `<${earliestToolName}>`;
|
|
1699
|
+
const newBuffer = buffer.substring(earliestStartTagIndex + startTag.length);
|
|
1700
|
+
return {
|
|
1701
|
+
buffer: newBuffer,
|
|
1702
|
+
currentToolCall: { name: earliestToolName, content: "" },
|
|
1703
|
+
shouldBreak: false,
|
|
1704
|
+
shouldContinue: false
|
|
1705
|
+
};
|
|
1706
|
+
}
|
|
1707
|
+
const result = handleNoToolTagInBuffer(
|
|
1708
|
+
buffer,
|
|
1709
|
+
maxStartTagLen,
|
|
1710
|
+
controller,
|
|
1711
|
+
flushText
|
|
1712
|
+
);
|
|
1713
|
+
return {
|
|
1714
|
+
buffer: result.buffer,
|
|
1715
|
+
currentToolCall: null,
|
|
1716
|
+
shouldBreak: !result.shouldContinue,
|
|
1717
|
+
shouldContinue: result.shouldContinue
|
|
1718
|
+
};
|
|
1719
|
+
}
|
|
1720
|
+
function createFlushTextHandler(getBuffer, setBuffer, getCurrentTextId, setCurrentTextId) {
|
|
1721
|
+
return (controller, text) => {
|
|
1722
|
+
const content = text != null ? text : getBuffer();
|
|
1723
|
+
if (content) {
|
|
1724
|
+
const currentTextId2 = getCurrentTextId();
|
|
1725
|
+
if (!currentTextId2) {
|
|
1726
|
+
const newId = (0, import_provider_utils2.generateId)();
|
|
1727
|
+
setCurrentTextId(newId);
|
|
1728
|
+
controller.enqueue({ type: "text-start", id: newId });
|
|
1729
|
+
}
|
|
1730
|
+
controller.enqueue({
|
|
1731
|
+
type: "text-delta",
|
|
1732
|
+
id: getCurrentTextId(),
|
|
1733
|
+
delta: content
|
|
1734
|
+
});
|
|
1735
|
+
if (text === void 0) {
|
|
1736
|
+
setBuffer("");
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
const currentTextId = getCurrentTextId();
|
|
1740
|
+
if (currentTextId && !text) {
|
|
1741
|
+
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1742
|
+
setCurrentTextId(null);
|
|
1743
|
+
}
|
|
1744
|
+
};
|
|
1745
|
+
}
|
|
1746
|
+
function processBufferWithToolCall(params, controller) {
|
|
1747
|
+
const {
|
|
1748
|
+
getBuffer,
|
|
1749
|
+
setBuffer,
|
|
1750
|
+
getCurrentToolCall,
|
|
1751
|
+
setCurrentToolCall,
|
|
1752
|
+
tools,
|
|
1753
|
+
options,
|
|
1754
|
+
flushText
|
|
1755
|
+
} = params;
|
|
1756
|
+
const currentToolCall = getCurrentToolCall();
|
|
1757
|
+
if (!currentToolCall) {
|
|
1758
|
+
return true;
|
|
1759
|
+
}
|
|
1760
|
+
const result = processToolCallInBuffer({
|
|
1761
|
+
buffer: getBuffer(),
|
|
1762
|
+
currentToolCall,
|
|
1763
|
+
tools,
|
|
1764
|
+
options,
|
|
1765
|
+
controller,
|
|
1766
|
+
flushText,
|
|
1767
|
+
setBuffer
|
|
1768
|
+
});
|
|
1769
|
+
setBuffer(result.buffer);
|
|
1770
|
+
setCurrentToolCall(result.currentToolCall);
|
|
1771
|
+
return result.shouldBreak;
|
|
1772
|
+
}
|
|
1773
|
+
function processBufferWithoutToolCall(params, controller) {
|
|
1774
|
+
const {
|
|
1775
|
+
getBuffer,
|
|
1776
|
+
setBuffer,
|
|
1777
|
+
setCurrentToolCall,
|
|
1778
|
+
tools,
|
|
1779
|
+
options,
|
|
1780
|
+
toolNames,
|
|
1781
|
+
maxStartTagLen,
|
|
1782
|
+
flushText
|
|
1783
|
+
} = params;
|
|
1784
|
+
const result = processNoToolCallInBuffer({
|
|
1785
|
+
buffer: getBuffer(),
|
|
1786
|
+
toolNames,
|
|
1787
|
+
maxStartTagLen,
|
|
1788
|
+
controller,
|
|
1789
|
+
flushText,
|
|
1790
|
+
tools,
|
|
1791
|
+
options
|
|
1792
|
+
});
|
|
1793
|
+
setBuffer(result.buffer);
|
|
1794
|
+
setCurrentToolCall(result.currentToolCall);
|
|
1795
|
+
return {
|
|
1796
|
+
shouldBreak: result.shouldBreak,
|
|
1797
|
+
shouldContinue: result.shouldContinue
|
|
1798
|
+
};
|
|
1799
|
+
}
|
|
1800
|
+
function processBufferLoop(params, controller) {
|
|
1801
|
+
while (true) {
|
|
1802
|
+
const currentToolCall = params.getCurrentToolCall();
|
|
1803
|
+
if (currentToolCall) {
|
|
1804
|
+
const shouldBreak = processBufferWithToolCall(params, controller);
|
|
1805
|
+
if (shouldBreak) {
|
|
1806
|
+
break;
|
|
1807
|
+
}
|
|
1808
|
+
} else {
|
|
1809
|
+
const { shouldBreak, shouldContinue } = processBufferWithoutToolCall(
|
|
1810
|
+
params,
|
|
1811
|
+
controller
|
|
1812
|
+
);
|
|
1813
|
+
if (shouldContinue) {
|
|
1814
|
+
continue;
|
|
1815
|
+
}
|
|
1816
|
+
if (shouldBreak) {
|
|
1817
|
+
break;
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
function createProcessBufferHandler(params) {
|
|
1823
|
+
return (controller) => {
|
|
1824
|
+
processBufferLoop(params, controller);
|
|
1825
|
+
};
|
|
1826
|
+
}
|
|
1123
1827
|
var morphXmlProtocol = () => ({
|
|
1124
1828
|
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
1125
1829
|
const toolsForPrompt = (tools || []).map((tool) => ({
|
|
1126
1830
|
name: tool.name,
|
|
1127
1831
|
description: tool.description,
|
|
1128
|
-
parameters:
|
|
1832
|
+
parameters: (0, import_rxml.unwrapJsonSchema)(tool.inputSchema)
|
|
1129
1833
|
}));
|
|
1130
1834
|
return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
|
|
1131
1835
|
},
|
|
@@ -1141,67 +1845,46 @@ var morphXmlProtocol = () => ({
|
|
|
1141
1845
|
} else {
|
|
1142
1846
|
args = inputValue;
|
|
1143
1847
|
}
|
|
1144
|
-
return
|
|
1848
|
+
return (0, import_rxml.stringify)(toolCall.toolName, args, {
|
|
1145
1849
|
suppressEmptyNode: false,
|
|
1146
1850
|
format: false
|
|
1147
1851
|
});
|
|
1148
1852
|
},
|
|
1149
1853
|
formatToolResponse(toolResult) {
|
|
1150
|
-
return
|
|
1854
|
+
return (0, import_rxml.stringify)("tool_response", {
|
|
1151
1855
|
tool_name: toolResult.toolName,
|
|
1152
1856
|
result: toolResult.output
|
|
1153
1857
|
});
|
|
1154
1858
|
},
|
|
1155
1859
|
parseGeneratedText({ text, tools, options }) {
|
|
1156
|
-
var _a;
|
|
1157
1860
|
const toolNames = tools.map((t) => t.name).filter((name) => name != null);
|
|
1158
1861
|
if (toolNames.length === 0) {
|
|
1159
1862
|
return [{ type: "text", text }];
|
|
1160
1863
|
}
|
|
1161
1864
|
const processedElements = [];
|
|
1162
1865
|
let currentIndex = 0;
|
|
1163
|
-
const
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
}
|
|
1171
|
-
try {
|
|
1172
|
-
const toolSchema = getToolSchema(tools, toolCall.toolName);
|
|
1173
|
-
const parsed = RXML.parse(toolCall.content, toolSchema, {
|
|
1174
|
-
onError: options == null ? void 0 : options.onError,
|
|
1175
|
-
// Disable HTML self-closing tag behavior to allow base, meta, link etc. as regular tags
|
|
1176
|
-
noChildNodes: []
|
|
1177
|
-
});
|
|
1178
|
-
processedElements.push({
|
|
1179
|
-
type: "tool-call",
|
|
1180
|
-
toolCallId: (0, import_provider_utils3.generateId)(),
|
|
1181
|
-
toolName: toolCall.toolName,
|
|
1182
|
-
input: JSON.stringify(parsed)
|
|
1183
|
-
});
|
|
1184
|
-
} catch (error) {
|
|
1185
|
-
const originalCallText = text.substring(
|
|
1186
|
-
toolCall.startIndex,
|
|
1187
|
-
toolCall.endIndex
|
|
1188
|
-
);
|
|
1189
|
-
const message = `Could not process XML tool call, keeping original text: ${originalCallText}`;
|
|
1190
|
-
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
|
|
1191
|
-
toolCall: originalCallText,
|
|
1192
|
-
toolName: toolCall.toolName,
|
|
1193
|
-
error
|
|
1194
|
-
});
|
|
1195
|
-
processedElements.push({ type: "text", text: originalCallText });
|
|
1866
|
+
const toolCallsRaw = findToolCalls(text, toolNames);
|
|
1867
|
+
const toolCallsNorm = collectToolCallsFromNormalizedText(text, toolNames);
|
|
1868
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1869
|
+
const toolCalls = [...toolCallsRaw, ...toolCallsNorm].filter((tc) => {
|
|
1870
|
+
const key = `${tc.toolName}:${tc.startIndex}:${tc.endIndex}`;
|
|
1871
|
+
if (seen.has(key)) {
|
|
1872
|
+
return false;
|
|
1196
1873
|
}
|
|
1874
|
+
seen.add(key);
|
|
1875
|
+
return true;
|
|
1876
|
+
}).sort((a, b) => a.startIndex - b.startIndex);
|
|
1877
|
+
for (const toolCall of toolCalls) {
|
|
1878
|
+
currentIndex = processTextBeforeToolCall(
|
|
1879
|
+
text,
|
|
1880
|
+
currentIndex,
|
|
1881
|
+
toolCall.startIndex,
|
|
1882
|
+
processedElements
|
|
1883
|
+
);
|
|
1884
|
+
processToolCall({ toolCall, tools, options, text, processedElements });
|
|
1197
1885
|
currentIndex = toolCall.endIndex;
|
|
1198
1886
|
}
|
|
1199
|
-
|
|
1200
|
-
const remainingText = text.substring(currentIndex);
|
|
1201
|
-
if (remainingText.trim()) {
|
|
1202
|
-
processedElements.push({ type: "text", text: remainingText });
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1887
|
+
addRemainingText(text, currentIndex, processedElements);
|
|
1205
1888
|
return processedElements;
|
|
1206
1889
|
},
|
|
1207
1890
|
createStreamParser({ tools, options }) {
|
|
@@ -1210,129 +1893,67 @@ var morphXmlProtocol = () => ({
|
|
|
1210
1893
|
let buffer = "";
|
|
1211
1894
|
let currentToolCall = null;
|
|
1212
1895
|
let currentTextId = null;
|
|
1213
|
-
const flushText = (
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
if (
|
|
1226
|
-
|
|
1896
|
+
const flushText = createFlushTextHandler(
|
|
1897
|
+
() => buffer,
|
|
1898
|
+
(newBuffer) => {
|
|
1899
|
+
buffer = newBuffer;
|
|
1900
|
+
},
|
|
1901
|
+
() => currentTextId,
|
|
1902
|
+
(newId) => {
|
|
1903
|
+
currentTextId = newId;
|
|
1904
|
+
}
|
|
1905
|
+
);
|
|
1906
|
+
const processChunk = (chunk, controller) => {
|
|
1907
|
+
if (chunk.type !== "text-delta") {
|
|
1908
|
+
if (buffer) {
|
|
1909
|
+
flushText(controller);
|
|
1227
1910
|
}
|
|
1911
|
+
controller.enqueue(chunk);
|
|
1912
|
+
return;
|
|
1913
|
+
}
|
|
1914
|
+
buffer += chunk.delta;
|
|
1915
|
+
processBuffer(controller);
|
|
1916
|
+
};
|
|
1917
|
+
const processBuffer = createProcessBufferHandler({
|
|
1918
|
+
getBuffer: () => buffer,
|
|
1919
|
+
setBuffer: (newBuffer) => {
|
|
1920
|
+
buffer = newBuffer;
|
|
1921
|
+
},
|
|
1922
|
+
getCurrentToolCall: () => currentToolCall,
|
|
1923
|
+
setCurrentToolCall: (newToolCall) => {
|
|
1924
|
+
currentToolCall = newToolCall;
|
|
1925
|
+
},
|
|
1926
|
+
tools,
|
|
1927
|
+
options,
|
|
1928
|
+
toolNames,
|
|
1929
|
+
maxStartTagLen,
|
|
1930
|
+
flushText
|
|
1931
|
+
});
|
|
1932
|
+
const flushBuffer2 = (controller) => {
|
|
1933
|
+
if (currentToolCall) {
|
|
1934
|
+
const unfinishedCall = `<${currentToolCall.name}>${buffer}`;
|
|
1935
|
+
flushText(controller, unfinishedCall);
|
|
1936
|
+
} else if (buffer) {
|
|
1937
|
+
flushText(controller);
|
|
1228
1938
|
}
|
|
1229
|
-
if (currentTextId
|
|
1939
|
+
if (currentTextId) {
|
|
1230
1940
|
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1231
|
-
currentTextId = null;
|
|
1232
1941
|
}
|
|
1233
1942
|
};
|
|
1234
1943
|
return new TransformStream({
|
|
1235
1944
|
transform(chunk, controller) {
|
|
1236
|
-
|
|
1237
|
-
if (chunk.type !== "text-delta") {
|
|
1238
|
-
if (buffer) flushText(controller);
|
|
1239
|
-
controller.enqueue(chunk);
|
|
1240
|
-
return;
|
|
1241
|
-
}
|
|
1242
|
-
buffer += chunk.delta;
|
|
1243
|
-
while (true) {
|
|
1244
|
-
if (currentToolCall) {
|
|
1245
|
-
const endTag = `</${currentToolCall.name}>`;
|
|
1246
|
-
const endTagIndex = buffer.indexOf(endTag);
|
|
1247
|
-
if (endTagIndex !== -1) {
|
|
1248
|
-
const toolContent = buffer.substring(0, endTagIndex);
|
|
1249
|
-
buffer = buffer.substring(endTagIndex + endTag.length);
|
|
1250
|
-
try {
|
|
1251
|
-
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
1252
|
-
const parsed = RXML.parse(toolContent, toolSchema, {
|
|
1253
|
-
onError: options == null ? void 0 : options.onError,
|
|
1254
|
-
// Disable HTML self-closing tag behavior to allow base, meta, link etc. as regular tags
|
|
1255
|
-
noChildNodes: []
|
|
1256
|
-
});
|
|
1257
|
-
flushText(controller);
|
|
1258
|
-
controller.enqueue({
|
|
1259
|
-
type: "tool-call",
|
|
1260
|
-
toolCallId: (0, import_provider_utils3.generateId)(),
|
|
1261
|
-
toolName: currentToolCall.name,
|
|
1262
|
-
input: JSON.stringify(parsed)
|
|
1263
|
-
});
|
|
1264
|
-
} catch (error) {
|
|
1265
|
-
const originalCallText = `<${currentToolCall.name}>${toolContent}${endTag}`;
|
|
1266
|
-
let message = "Could not process streaming XML tool call; emitting original text.";
|
|
1267
|
-
if (error instanceof RXML.RXMLDuplicateStringTagError) {
|
|
1268
|
-
message = `Duplicate string tags detected in streaming tool call '${currentToolCall.name}'; emitting original text.`;
|
|
1269
|
-
} else if (error instanceof RXML.RXMLCoercionError) {
|
|
1270
|
-
message = `Failed to coerce arguments for streaming tool call '${currentToolCall.name}'; emitting original text.`;
|
|
1271
|
-
} else if (error instanceof RXML.RXMLParseError) {
|
|
1272
|
-
message = `Failed to parse XML for streaming tool call '${currentToolCall.name}'; emitting original text.`;
|
|
1273
|
-
}
|
|
1274
|
-
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
|
|
1275
|
-
toolCall: originalCallText,
|
|
1276
|
-
toolName: currentToolCall.name,
|
|
1277
|
-
error
|
|
1278
|
-
});
|
|
1279
|
-
flushText(controller, originalCallText);
|
|
1280
|
-
}
|
|
1281
|
-
currentToolCall = null;
|
|
1282
|
-
} else {
|
|
1283
|
-
break;
|
|
1284
|
-
}
|
|
1285
|
-
} else {
|
|
1286
|
-
let earliestStartTagIndex = -1;
|
|
1287
|
-
let earliestToolName = "";
|
|
1288
|
-
if (toolNames.length > 0) {
|
|
1289
|
-
for (const name of toolNames) {
|
|
1290
|
-
const startTag = `<${name}>`;
|
|
1291
|
-
const index = buffer.indexOf(startTag);
|
|
1292
|
-
if (index !== -1 && (earliestStartTagIndex === -1 || index < earliestStartTagIndex)) {
|
|
1293
|
-
earliestStartTagIndex = index;
|
|
1294
|
-
earliestToolName = name;
|
|
1295
|
-
}
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
if (earliestStartTagIndex !== -1) {
|
|
1299
|
-
const textBeforeTag = buffer.substring(0, earliestStartTagIndex);
|
|
1300
|
-
flushText(controller, textBeforeTag);
|
|
1301
|
-
const startTag = `<${earliestToolName}>`;
|
|
1302
|
-
buffer = buffer.substring(
|
|
1303
|
-
earliestStartTagIndex + startTag.length
|
|
1304
|
-
);
|
|
1305
|
-
currentToolCall = { name: earliestToolName, content: "" };
|
|
1306
|
-
} else {
|
|
1307
|
-
const tail = Math.max(0, maxStartTagLen - 1);
|
|
1308
|
-
const safeLen = Math.max(0, buffer.length - tail);
|
|
1309
|
-
if (safeLen > 0) {
|
|
1310
|
-
const textToFlush = buffer.slice(0, safeLen);
|
|
1311
|
-
flushText(controller, textToFlush);
|
|
1312
|
-
buffer = buffer.slice(safeLen);
|
|
1313
|
-
continue;
|
|
1314
|
-
}
|
|
1315
|
-
break;
|
|
1316
|
-
}
|
|
1317
|
-
}
|
|
1318
|
-
}
|
|
1945
|
+
processChunk(chunk, controller);
|
|
1319
1946
|
},
|
|
1320
1947
|
flush(controller) {
|
|
1321
|
-
|
|
1322
|
-
const unfinishedCall = `<${currentToolCall.name}>${buffer}`;
|
|
1323
|
-
flushText(controller, unfinishedCall);
|
|
1324
|
-
} else if (buffer) {
|
|
1325
|
-
flushText(controller);
|
|
1326
|
-
}
|
|
1327
|
-
if (currentTextId) {
|
|
1328
|
-
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1329
|
-
}
|
|
1948
|
+
flushBuffer2(controller);
|
|
1330
1949
|
}
|
|
1331
1950
|
});
|
|
1332
1951
|
},
|
|
1333
1952
|
extractToolCallSegments({ text, tools }) {
|
|
1334
1953
|
const toolNames = tools.map((t) => t.name).filter(Boolean);
|
|
1335
|
-
if (toolNames.length === 0)
|
|
1954
|
+
if (toolNames.length === 0) {
|
|
1955
|
+
return [];
|
|
1956
|
+
}
|
|
1336
1957
|
return findToolCalls(text, toolNames).map((tc) => tc.segment);
|
|
1337
1958
|
}
|
|
1338
1959
|
});
|
|
@@ -1340,140 +1961,368 @@ function getToolSchema(tools, toolName) {
|
|
|
1340
1961
|
var _a;
|
|
1341
1962
|
return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
1342
1963
|
}
|
|
1343
|
-
function
|
|
1964
|
+
function findClosingTagEndFlexible(text, contentStart, toolName) {
|
|
1965
|
+
let pos = contentStart;
|
|
1966
|
+
let depth = 1;
|
|
1967
|
+
while (pos < text.length) {
|
|
1968
|
+
const tok = nextTagToken(text, pos);
|
|
1969
|
+
if (tok.kind === "eof") {
|
|
1970
|
+
break;
|
|
1971
|
+
}
|
|
1972
|
+
const result = updateDepthWithToken(tok, toolName, depth);
|
|
1973
|
+
depth = result.depth;
|
|
1974
|
+
if (result.closedAt !== void 0) {
|
|
1975
|
+
return result.closedAt;
|
|
1976
|
+
}
|
|
1977
|
+
pos = tok.nextPos;
|
|
1978
|
+
}
|
|
1979
|
+
return -1;
|
|
1980
|
+
}
|
|
1981
|
+
function skipSpecialSegment(text, lt) {
|
|
1982
|
+
const next = text[lt + 1];
|
|
1983
|
+
if (next !== "!" && next !== "?") {
|
|
1984
|
+
return null;
|
|
1985
|
+
}
|
|
1986
|
+
const gt = text.indexOf(">", lt + 1);
|
|
1987
|
+
if (gt === -1) {
|
|
1988
|
+
return null;
|
|
1989
|
+
}
|
|
1990
|
+
return gt + 1;
|
|
1991
|
+
}
|
|
1992
|
+
function consumeClosingTag(text, lt, toolName) {
|
|
1993
|
+
let p = lt + 2;
|
|
1994
|
+
while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
|
|
1995
|
+
p += 1;
|
|
1996
|
+
}
|
|
1997
|
+
if (text.slice(p, p + toolName.length) === toolName) {
|
|
1998
|
+
p += toolName.length;
|
|
1999
|
+
while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
|
|
2000
|
+
p += 1;
|
|
2001
|
+
}
|
|
2002
|
+
if (text[p] === ">") {
|
|
2003
|
+
const endPos2 = p + 1;
|
|
2004
|
+
return { matched: true, endPos: endPos2 };
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
const gt = text.indexOf(">", lt + 1);
|
|
2008
|
+
const endPos = gt === -1 ? text.length : gt + 1;
|
|
2009
|
+
return { matched: false, endPos };
|
|
2010
|
+
}
|
|
2011
|
+
function consumeOpenTag(text, lt) {
|
|
2012
|
+
let p = lt + 1;
|
|
2013
|
+
while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
|
|
2014
|
+
p += 1;
|
|
2015
|
+
}
|
|
2016
|
+
const nameStart = p;
|
|
2017
|
+
while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
|
|
2018
|
+
p += 1;
|
|
2019
|
+
}
|
|
2020
|
+
const name = text.slice(nameStart, p);
|
|
2021
|
+
const q = text.indexOf(">", p);
|
|
2022
|
+
if (q === -1) {
|
|
2023
|
+
return null;
|
|
2024
|
+
}
|
|
2025
|
+
let r = q - 1;
|
|
2026
|
+
while (r >= nameStart && WHITESPACE_REGEX2.test(text[r])) {
|
|
2027
|
+
r -= 1;
|
|
2028
|
+
}
|
|
2029
|
+
const selfClosing = text[r] === "/";
|
|
2030
|
+
return { name, selfClosing, nextPos: q + 1 };
|
|
2031
|
+
}
|
|
2032
|
+
function updateDepthWithToken(tok, toolName, depth) {
|
|
2033
|
+
if (tok.kind === "close" && tok.name === toolName) {
|
|
2034
|
+
const newDepth = depth - 1;
|
|
2035
|
+
return newDepth === 0 ? { depth: newDepth, closedAt: tok.nextPos } : { depth: newDepth };
|
|
2036
|
+
}
|
|
2037
|
+
if (tok.kind === "open" && tok.name === toolName && !tok.selfClosing) {
|
|
2038
|
+
return { depth: depth + 1 };
|
|
2039
|
+
}
|
|
2040
|
+
return { depth };
|
|
2041
|
+
}
|
|
2042
|
+
function nextTagToken(text, fromPos) {
|
|
2043
|
+
const lt = text.indexOf("<", fromPos);
|
|
2044
|
+
if (lt === -1 || lt + 1 >= text.length) {
|
|
2045
|
+
return { kind: "eof", nextPos: text.length };
|
|
2046
|
+
}
|
|
2047
|
+
const next = text[lt + 1];
|
|
2048
|
+
const specialEnd = skipSpecialSegment(text, lt);
|
|
2049
|
+
if (specialEnd !== null) {
|
|
2050
|
+
return { kind: "special", nextPos: specialEnd };
|
|
2051
|
+
}
|
|
2052
|
+
if (next === "/") {
|
|
2053
|
+
const closing = consumeClosingTag(text, lt, "");
|
|
2054
|
+
let p = lt + 2;
|
|
2055
|
+
while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
|
|
2056
|
+
p += 1;
|
|
2057
|
+
}
|
|
2058
|
+
const nameStart = p;
|
|
2059
|
+
while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
|
|
2060
|
+
p += 1;
|
|
2061
|
+
}
|
|
2062
|
+
const name = text.slice(nameStart, p);
|
|
2063
|
+
return { kind: "close", name, nextPos: closing.endPos };
|
|
2064
|
+
}
|
|
2065
|
+
const open = consumeOpenTag(text, lt);
|
|
2066
|
+
if (open === null) {
|
|
2067
|
+
return { kind: "eof", nextPos: text.length };
|
|
2068
|
+
}
|
|
2069
|
+
return {
|
|
2070
|
+
kind: "open",
|
|
2071
|
+
name: open.name,
|
|
2072
|
+
selfClosing: open.selfClosing,
|
|
2073
|
+
nextPos: open.nextPos
|
|
2074
|
+
};
|
|
2075
|
+
}
|
|
2076
|
+
function collectToolCallsFromNormalizedText(text, toolNames) {
|
|
1344
2077
|
var _a;
|
|
1345
|
-
const
|
|
2078
|
+
const normalizedText = normalizeCloseTags(text);
|
|
2079
|
+
const collected = [];
|
|
1346
2080
|
for (const toolName of toolNames) {
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
2081
|
+
const startTag = `<${toolName}>`;
|
|
2082
|
+
let idx = 0;
|
|
2083
|
+
let lastOrigIdx = 0;
|
|
2084
|
+
while (idx < normalizedText.length) {
|
|
2085
|
+
const tagStartNorm = normalizedText.indexOf(startTag, idx);
|
|
2086
|
+
if (tagStartNorm === -1) {
|
|
2087
|
+
break;
|
|
2088
|
+
}
|
|
2089
|
+
const contentStartNorm = tagStartNorm + startTag.length;
|
|
2090
|
+
const endNorm = findClosingTagEndFlexible(
|
|
2091
|
+
normalizedText,
|
|
2092
|
+
contentStartNorm,
|
|
2093
|
+
toolName
|
|
2094
|
+
);
|
|
2095
|
+
if (endNorm > contentStartNorm) {
|
|
2096
|
+
const tagStartOrig = text.indexOf(startTag, lastOrigIdx);
|
|
2097
|
+
const contentStartOrig = tagStartOrig + startTag.length;
|
|
2098
|
+
let endOrig = findClosingTagEndFlexible(
|
|
2099
|
+
text,
|
|
2100
|
+
contentStartOrig,
|
|
2101
|
+
toolName
|
|
2102
|
+
);
|
|
2103
|
+
if (endOrig === -1) {
|
|
2104
|
+
const approxLen = endNorm - tagStartNorm;
|
|
2105
|
+
endOrig = Math.min(text.length, tagStartOrig + approxLen);
|
|
1363
2106
|
}
|
|
1364
|
-
const segment = text.substring(
|
|
1365
|
-
const
|
|
1366
|
-
|
|
2107
|
+
const segment = text.substring(tagStartOrig, endOrig);
|
|
2108
|
+
const inner = (_a = (0, import_rxml.extractRawInner)(segment, toolName)) != null ? _a : segment.substring(startTag.length, segment.lastIndexOf("<"));
|
|
2109
|
+
collected.push({
|
|
1367
2110
|
toolName,
|
|
1368
|
-
startIndex:
|
|
1369
|
-
endIndex:
|
|
1370
|
-
content,
|
|
2111
|
+
startIndex: tagStartOrig,
|
|
2112
|
+
endIndex: endOrig,
|
|
2113
|
+
content: inner,
|
|
1371
2114
|
segment
|
|
1372
2115
|
});
|
|
1373
|
-
|
|
2116
|
+
lastOrigIdx = endOrig;
|
|
2117
|
+
idx = endNorm;
|
|
1374
2118
|
} else {
|
|
1375
|
-
|
|
2119
|
+
idx = contentStartNorm;
|
|
1376
2120
|
}
|
|
1377
2121
|
}
|
|
1378
2122
|
}
|
|
2123
|
+
return collected.sort((a, b) => a.startIndex - b.startIndex);
|
|
2124
|
+
}
|
|
2125
|
+
function getNextTagInfo(text, toolName, fromIndex) {
|
|
2126
|
+
const startTag = `<${toolName}>`;
|
|
2127
|
+
const selfTag = `<${toolName}/>`;
|
|
2128
|
+
const openIdx = text.indexOf(startTag, fromIndex);
|
|
2129
|
+
const selfIdx = text.indexOf(selfTag, fromIndex);
|
|
2130
|
+
const hasOpen = openIdx !== -1;
|
|
2131
|
+
const hasSelf = selfIdx !== -1;
|
|
2132
|
+
if (!(hasOpen || hasSelf)) {
|
|
2133
|
+
return {
|
|
2134
|
+
found: false,
|
|
2135
|
+
tagStart: -1,
|
|
2136
|
+
selfClosing: false,
|
|
2137
|
+
startTag,
|
|
2138
|
+
selfTag
|
|
2139
|
+
};
|
|
2140
|
+
}
|
|
2141
|
+
const pickSelf = hasSelf && (!hasOpen || selfIdx < openIdx);
|
|
2142
|
+
const tagStart = pickSelf ? selfIdx : openIdx;
|
|
2143
|
+
return { found: true, tagStart, selfClosing: pickSelf, startTag, selfTag };
|
|
2144
|
+
}
|
|
2145
|
+
function findToolCallsForName(text, toolName) {
|
|
2146
|
+
var _a;
|
|
2147
|
+
const toolCalls = [];
|
|
2148
|
+
let searchIndex = 0;
|
|
2149
|
+
while (searchIndex < text.length) {
|
|
2150
|
+
const info = getNextTagInfo(text, toolName, searchIndex);
|
|
2151
|
+
if (!info.found) {
|
|
2152
|
+
break;
|
|
2153
|
+
}
|
|
2154
|
+
const { tagStart, selfClosing, startTag, selfTag } = info;
|
|
2155
|
+
if (selfClosing) {
|
|
2156
|
+
const endIndex = tagStart + selfTag.length;
|
|
2157
|
+
const segment = text.substring(tagStart, endIndex);
|
|
2158
|
+
toolCalls.push({
|
|
2159
|
+
toolName,
|
|
2160
|
+
startIndex: tagStart,
|
|
2161
|
+
endIndex,
|
|
2162
|
+
content: "",
|
|
2163
|
+
segment
|
|
2164
|
+
});
|
|
2165
|
+
searchIndex = endIndex;
|
|
2166
|
+
continue;
|
|
2167
|
+
}
|
|
2168
|
+
const contentStart = tagStart + startTag.length;
|
|
2169
|
+
const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
|
|
2170
|
+
if (fullTagEnd !== -1 && fullTagEnd > contentStart) {
|
|
2171
|
+
const segment = text.substring(tagStart, fullTagEnd);
|
|
2172
|
+
const inner = (_a = (0, import_rxml.extractRawInner)(segment, toolName)) != null ? _a : segment.substring(startTag.length, segment.lastIndexOf("<"));
|
|
2173
|
+
toolCalls.push({
|
|
2174
|
+
toolName,
|
|
2175
|
+
startIndex: tagStart,
|
|
2176
|
+
endIndex: fullTagEnd,
|
|
2177
|
+
content: inner,
|
|
2178
|
+
segment
|
|
2179
|
+
});
|
|
2180
|
+
searchIndex = fullTagEnd;
|
|
2181
|
+
} else {
|
|
2182
|
+
searchIndex = contentStart;
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
return toolCalls;
|
|
2186
|
+
}
|
|
2187
|
+
function findToolCalls(text, toolNames) {
|
|
2188
|
+
const toolCalls = [];
|
|
2189
|
+
for (const toolName of toolNames) {
|
|
2190
|
+
const calls = findToolCallsForName(text, toolName);
|
|
2191
|
+
toolCalls.push(...calls);
|
|
2192
|
+
}
|
|
1379
2193
|
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
1380
2194
|
}
|
|
1381
2195
|
|
|
1382
|
-
// src/
|
|
1383
|
-
|
|
1384
|
-
|
|
2196
|
+
// src/generate-handler.ts
|
|
2197
|
+
var import_provider_utils3 = require("@ai-sdk/provider-utils");
|
|
2198
|
+
var import_rxml2 = require("@ai-sdk-tool/rxml");
|
|
2199
|
+
|
|
2200
|
+
// src/utils/on-error.ts
|
|
2201
|
+
function extractOnErrorOption(providerOptions) {
|
|
2202
|
+
var _a;
|
|
2203
|
+
if (providerOptions && typeof providerOptions === "object") {
|
|
2204
|
+
const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
|
|
2205
|
+
return onError ? { onError } : void 0;
|
|
2206
|
+
}
|
|
2207
|
+
return;
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2210
|
+
// src/utils/provider-options.ts
|
|
2211
|
+
var originalToolsSchema = {
|
|
2212
|
+
encode: encodeOriginalTools,
|
|
2213
|
+
decode: decodeOriginalTools
|
|
2214
|
+
};
|
|
2215
|
+
function encodeOriginalTools(tools) {
|
|
2216
|
+
return (tools == null ? void 0 : tools.map((t) => ({
|
|
2217
|
+
name: t.name,
|
|
2218
|
+
inputSchema: JSON.stringify(t.inputSchema)
|
|
2219
|
+
}))) || [];
|
|
2220
|
+
}
|
|
2221
|
+
function decodeOriginalTools(originalTools) {
|
|
2222
|
+
if (!originalTools) {
|
|
2223
|
+
return [];
|
|
2224
|
+
}
|
|
2225
|
+
return originalTools.map(
|
|
2226
|
+
(t) => ({
|
|
2227
|
+
type: "function",
|
|
2228
|
+
name: t.name,
|
|
2229
|
+
inputSchema: JSON.parse(t.inputSchema)
|
|
2230
|
+
})
|
|
2231
|
+
);
|
|
2232
|
+
}
|
|
2233
|
+
function isToolChoiceActive(params) {
|
|
2234
|
+
var _a, _b, _c;
|
|
2235
|
+
const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
|
|
2236
|
+
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"));
|
|
1385
2237
|
}
|
|
1386
2238
|
|
|
1387
2239
|
// src/generate-handler.ts
|
|
1388
|
-
|
|
1389
|
-
var
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
if (first && first.type === "text") {
|
|
1401
|
-
const debugLevel2 = getDebugLevel();
|
|
1402
|
-
if (debugLevel2 === "parse") {
|
|
1403
|
-
logRawChunk(first.text);
|
|
1404
|
-
}
|
|
1405
|
-
try {
|
|
1406
|
-
parsed2 = JSON.parse(first.text);
|
|
1407
|
-
} catch (error) {
|
|
1408
|
-
const options = extractOnErrorOption(params.providerOptions);
|
|
1409
|
-
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
1410
|
-
options,
|
|
1411
|
-
"Failed to parse toolChoice JSON from generated model output",
|
|
1412
|
-
{
|
|
1413
|
-
text: first.text,
|
|
1414
|
-
error: error instanceof Error ? error.message : String(error)
|
|
1415
|
-
}
|
|
1416
|
-
);
|
|
1417
|
-
parsed2 = {};
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1420
|
-
const toolCall = {
|
|
1421
|
-
type: "tool-call",
|
|
1422
|
-
toolCallId: (0, import_provider_utils4.generateId)(),
|
|
1423
|
-
toolName: parsed2.name || "unknown",
|
|
1424
|
-
input: JSON.stringify(parsed2.arguments || {})
|
|
1425
|
-
};
|
|
1426
|
-
const debugLevelToolChoice = getDebugLevel();
|
|
1427
|
-
const originText = first && first.type === "text" ? first.text : "";
|
|
1428
|
-
const dbg2 = (_d = (_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) == null ? void 0 : _d.debugSummary;
|
|
1429
|
-
if (dbg2) {
|
|
1430
|
-
dbg2.originalText = originText;
|
|
1431
|
-
try {
|
|
1432
|
-
dbg2.toolCalls = JSON.stringify([
|
|
1433
|
-
{ toolName: toolCall.toolName, input: toolCall.input }
|
|
1434
|
-
]);
|
|
1435
|
-
} catch (e) {
|
|
2240
|
+
function parseToolChoiceJson(text, providerOptions) {
|
|
2241
|
+
var _a;
|
|
2242
|
+
try {
|
|
2243
|
+
return JSON.parse(text);
|
|
2244
|
+
} catch (error) {
|
|
2245
|
+
const options = extractOnErrorOption(providerOptions);
|
|
2246
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
2247
|
+
options,
|
|
2248
|
+
"Failed to parse toolChoice JSON from generated model output",
|
|
2249
|
+
{
|
|
2250
|
+
text,
|
|
2251
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1436
2252
|
}
|
|
1437
|
-
|
|
1438
|
-
|
|
2253
|
+
);
|
|
2254
|
+
return {};
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
function logDebugSummary(debugSummary, toolCall, originText) {
|
|
2258
|
+
if (debugSummary) {
|
|
2259
|
+
debugSummary.originalText = originText;
|
|
2260
|
+
try {
|
|
2261
|
+
debugSummary.toolCalls = JSON.stringify([
|
|
2262
|
+
{ toolName: toolCall.toolName, input: toolCall.input }
|
|
2263
|
+
]);
|
|
2264
|
+
} catch (e) {
|
|
1439
2265
|
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
content: [toolCall]
|
|
1443
|
-
};
|
|
2266
|
+
} else if (getDebugLevel() === "parse") {
|
|
2267
|
+
logParsedSummary({ toolCalls: [toolCall], originalText: originText });
|
|
1444
2268
|
}
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
2269
|
+
}
|
|
2270
|
+
async function handleToolChoice(doGenerate, params) {
|
|
2271
|
+
var _a, _b, _c;
|
|
1448
2272
|
const result = await doGenerate();
|
|
1449
|
-
|
|
1450
|
-
|
|
2273
|
+
const first = (_a = result.content) == null ? void 0 : _a[0];
|
|
2274
|
+
let parsed = {};
|
|
2275
|
+
if (first && first.type === "text") {
|
|
2276
|
+
if (getDebugLevel() === "parse") {
|
|
2277
|
+
logRawChunk(first.text);
|
|
2278
|
+
}
|
|
2279
|
+
parsed = parseToolChoiceJson(first.text, params.providerOptions);
|
|
1451
2280
|
}
|
|
1452
|
-
const
|
|
1453
|
-
|
|
2281
|
+
const toolCall = {
|
|
2282
|
+
type: "tool-call",
|
|
2283
|
+
toolCallId: (0, import_provider_utils3.generateId)(),
|
|
2284
|
+
toolName: parsed.name || "unknown",
|
|
2285
|
+
input: JSON.stringify(parsed.arguments || {})
|
|
2286
|
+
};
|
|
2287
|
+
const originText = first && first.type === "text" ? first.text : "";
|
|
2288
|
+
const debugSummary = (_c = (_b = params.providerOptions) == null ? void 0 : _b.toolCallMiddleware) == null ? void 0 : _c.debugSummary;
|
|
2289
|
+
logDebugSummary(debugSummary, toolCall, originText);
|
|
2290
|
+
return {
|
|
2291
|
+
...result,
|
|
2292
|
+
content: [toolCall]
|
|
2293
|
+
};
|
|
2294
|
+
}
|
|
2295
|
+
function parseContent(content, protocol, tools, providerOptions) {
|
|
2296
|
+
const parsed = content.flatMap((contentItem) => {
|
|
1454
2297
|
if (contentItem.type !== "text") {
|
|
1455
2298
|
return [contentItem];
|
|
1456
2299
|
}
|
|
1457
|
-
|
|
1458
|
-
if (debugLevel2 === "stream") {
|
|
2300
|
+
if (getDebugLevel() === "stream") {
|
|
1459
2301
|
logRawChunk(contentItem.text);
|
|
1460
2302
|
}
|
|
1461
2303
|
return protocol.parseGeneratedText({
|
|
1462
2304
|
text: contentItem.text,
|
|
1463
2305
|
tools,
|
|
1464
2306
|
options: {
|
|
1465
|
-
...extractOnErrorOption(
|
|
1466
|
-
...
|
|
2307
|
+
...extractOnErrorOption(providerOptions),
|
|
2308
|
+
...providerOptions == null ? void 0 : providerOptions.toolCallMiddleware
|
|
1467
2309
|
}
|
|
1468
2310
|
});
|
|
1469
2311
|
});
|
|
1470
|
-
|
|
2312
|
+
return parsed.map(
|
|
1471
2313
|
(part) => fixToolCallWithSchema(part, tools)
|
|
1472
2314
|
);
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
2315
|
+
}
|
|
2316
|
+
function logParsedContent(content) {
|
|
2317
|
+
if (getDebugLevel() === "stream") {
|
|
2318
|
+
for (const part of content) {
|
|
2319
|
+
logParsedChunk(part);
|
|
2320
|
+
}
|
|
1476
2321
|
}
|
|
2322
|
+
}
|
|
2323
|
+
function computeDebugSummary(options) {
|
|
2324
|
+
var _a;
|
|
2325
|
+
const { result, newContent, protocol, tools, providerOptions } = options;
|
|
1477
2326
|
const allText = result.content.filter(
|
|
1478
2327
|
(c) => c.type === "text"
|
|
1479
2328
|
).map((c) => c.text).join("\n\n");
|
|
@@ -1482,7 +2331,7 @@ async function wrapGenerate({
|
|
|
1482
2331
|
const toolCalls = newContent.filter(
|
|
1483
2332
|
(p) => p.type === "tool-call"
|
|
1484
2333
|
);
|
|
1485
|
-
const dbg = (
|
|
2334
|
+
const dbg = (_a = providerOptions == null ? void 0 : providerOptions.toolCallMiddleware) == null ? void 0 : _a.debugSummary;
|
|
1486
2335
|
if (dbg) {
|
|
1487
2336
|
dbg.originalText = originalText;
|
|
1488
2337
|
try {
|
|
@@ -1494,9 +2343,40 @@ async function wrapGenerate({
|
|
|
1494
2343
|
);
|
|
1495
2344
|
} catch (e) {
|
|
1496
2345
|
}
|
|
1497
|
-
} else if (
|
|
2346
|
+
} else if (getDebugLevel() === "parse") {
|
|
1498
2347
|
logParsedSummary({ toolCalls, originalText });
|
|
1499
2348
|
}
|
|
2349
|
+
}
|
|
2350
|
+
async function wrapGenerate({
|
|
2351
|
+
protocol,
|
|
2352
|
+
doGenerate,
|
|
2353
|
+
params
|
|
2354
|
+
}) {
|
|
2355
|
+
var _a, _b;
|
|
2356
|
+
if (isToolChoiceActive(params)) {
|
|
2357
|
+
return handleToolChoice(doGenerate, params);
|
|
2358
|
+
}
|
|
2359
|
+
const tools = originalToolsSchema.decode(
|
|
2360
|
+
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools
|
|
2361
|
+
);
|
|
2362
|
+
const result = await doGenerate();
|
|
2363
|
+
if (result.content.length === 0) {
|
|
2364
|
+
return result;
|
|
2365
|
+
}
|
|
2366
|
+
const newContent = parseContent(
|
|
2367
|
+
result.content,
|
|
2368
|
+
protocol,
|
|
2369
|
+
tools,
|
|
2370
|
+
params.providerOptions
|
|
2371
|
+
);
|
|
2372
|
+
logParsedContent(newContent);
|
|
2373
|
+
computeDebugSummary({
|
|
2374
|
+
result,
|
|
2375
|
+
newContent,
|
|
2376
|
+
protocol,
|
|
2377
|
+
tools,
|
|
2378
|
+
providerOptions: params.providerOptions
|
|
2379
|
+
});
|
|
1500
2380
|
return {
|
|
1501
2381
|
...result,
|
|
1502
2382
|
content: newContent
|
|
@@ -1504,7 +2384,9 @@ async function wrapGenerate({
|
|
|
1504
2384
|
}
|
|
1505
2385
|
function fixToolCallWithSchema(part, tools) {
|
|
1506
2386
|
var _a;
|
|
1507
|
-
if (part.type !== "tool-call")
|
|
2387
|
+
if (part.type !== "tool-call") {
|
|
2388
|
+
return part;
|
|
2389
|
+
}
|
|
1508
2390
|
const tc = part;
|
|
1509
2391
|
let args = {};
|
|
1510
2392
|
if (typeof tc.input === "string") {
|
|
@@ -1517,15 +2399,81 @@ function fixToolCallWithSchema(part, tools) {
|
|
|
1517
2399
|
args = tc.input;
|
|
1518
2400
|
}
|
|
1519
2401
|
const schema = (_a = tools.find((t) => t.name === tc.toolName)) == null ? void 0 : _a.inputSchema;
|
|
1520
|
-
const coerced =
|
|
2402
|
+
const coerced = (0, import_rxml2.coerceBySchema)(args, schema);
|
|
1521
2403
|
return {
|
|
1522
2404
|
...part,
|
|
1523
2405
|
input: JSON.stringify(coerced != null ? coerced : {})
|
|
1524
2406
|
};
|
|
1525
2407
|
}
|
|
1526
|
-
|
|
1527
|
-
// src/
|
|
1528
|
-
|
|
2408
|
+
|
|
2409
|
+
// src/protocols/tool-call-protocol.ts
|
|
2410
|
+
function isProtocolFactory(protocol) {
|
|
2411
|
+
return typeof protocol === "function";
|
|
2412
|
+
}
|
|
2413
|
+
|
|
2414
|
+
// src/stream-handler.ts
|
|
2415
|
+
var import_provider_utils4 = require("@ai-sdk/provider-utils");
|
|
2416
|
+
function extractToolCallSegments(protocol, fullRawText, tools) {
|
|
2417
|
+
const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({
|
|
2418
|
+
text: fullRawText,
|
|
2419
|
+
tools
|
|
2420
|
+
}) : [];
|
|
2421
|
+
return segments.join("\n\n");
|
|
2422
|
+
}
|
|
2423
|
+
function serializeToolCalls(parsedToolCalls) {
|
|
2424
|
+
const toolCallParts = parsedToolCalls.filter(
|
|
2425
|
+
(p) => p.type === "tool-call"
|
|
2426
|
+
);
|
|
2427
|
+
return JSON.stringify(
|
|
2428
|
+
toolCallParts.map((tc) => ({
|
|
2429
|
+
toolName: tc.toolName,
|
|
2430
|
+
input: tc.input
|
|
2431
|
+
}))
|
|
2432
|
+
);
|
|
2433
|
+
}
|
|
2434
|
+
function handleDebugSummary(parsedToolCalls, origin, params) {
|
|
2435
|
+
var _a, _b;
|
|
2436
|
+
const dbg = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.debugSummary;
|
|
2437
|
+
if (dbg) {
|
|
2438
|
+
dbg.originalText = origin;
|
|
2439
|
+
try {
|
|
2440
|
+
dbg.toolCalls = serializeToolCalls(parsedToolCalls);
|
|
2441
|
+
} catch (e) {
|
|
2442
|
+
}
|
|
2443
|
+
} else {
|
|
2444
|
+
logParsedSummary({
|
|
2445
|
+
toolCalls: parsedToolCalls,
|
|
2446
|
+
originalText: origin
|
|
2447
|
+
});
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
function createDebugSummaryTransform({
|
|
2451
|
+
protocol,
|
|
2452
|
+
getFullRawText,
|
|
2453
|
+
tools,
|
|
2454
|
+
params
|
|
2455
|
+
}) {
|
|
2456
|
+
return new TransformStream({
|
|
2457
|
+
transform: /* @__PURE__ */ (() => {
|
|
2458
|
+
const parsedToolCalls = [];
|
|
2459
|
+
return (part, controller) => {
|
|
2460
|
+
if (part.type === "tool-call") {
|
|
2461
|
+
parsedToolCalls.push(part);
|
|
2462
|
+
}
|
|
2463
|
+
if (part.type === "finish") {
|
|
2464
|
+
try {
|
|
2465
|
+
const raw = getFullRawText();
|
|
2466
|
+
logRawChunk(raw);
|
|
2467
|
+
const origin = extractToolCallSegments(protocol, raw, tools);
|
|
2468
|
+
handleDebugSummary(parsedToolCalls, origin, params);
|
|
2469
|
+
} catch (e) {
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
controller.enqueue(part);
|
|
2473
|
+
};
|
|
2474
|
+
})()
|
|
2475
|
+
});
|
|
2476
|
+
}
|
|
1529
2477
|
async function wrapStream({
|
|
1530
2478
|
protocol,
|
|
1531
2479
|
doStream,
|
|
@@ -1612,48 +2560,11 @@ async function wrapStream({
|
|
|
1612
2560
|
})
|
|
1613
2561
|
);
|
|
1614
2562
|
const withSummary = parsed.pipeThrough(
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
if (part.type === "tool-call") {
|
|
1621
|
-
parsedToolCalls.push(part);
|
|
1622
|
-
}
|
|
1623
|
-
if (part.type === "finish") {
|
|
1624
|
-
try {
|
|
1625
|
-
const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({
|
|
1626
|
-
text: fullRawText,
|
|
1627
|
-
tools
|
|
1628
|
-
}) : [];
|
|
1629
|
-
const origin = segments.join("\n\n");
|
|
1630
|
-
const dbg = (_b2 = (_a2 = params.providerOptions) == null ? void 0 : _a2.toolCallMiddleware) == null ? void 0 : _b2.debugSummary;
|
|
1631
|
-
if (dbg) {
|
|
1632
|
-
dbg.originalText = origin;
|
|
1633
|
-
try {
|
|
1634
|
-
const toolCallParts = parsedToolCalls.filter(
|
|
1635
|
-
(p) => p.type === "tool-call"
|
|
1636
|
-
);
|
|
1637
|
-
dbg.toolCalls = JSON.stringify(
|
|
1638
|
-
toolCallParts.map((tc) => ({
|
|
1639
|
-
toolName: tc.toolName,
|
|
1640
|
-
input: tc.input
|
|
1641
|
-
}))
|
|
1642
|
-
);
|
|
1643
|
-
} catch (e) {
|
|
1644
|
-
}
|
|
1645
|
-
} else {
|
|
1646
|
-
logParsedSummary({
|
|
1647
|
-
toolCalls: parsedToolCalls,
|
|
1648
|
-
originalText: origin
|
|
1649
|
-
});
|
|
1650
|
-
}
|
|
1651
|
-
} catch (e) {
|
|
1652
|
-
}
|
|
1653
|
-
}
|
|
1654
|
-
controller.enqueue(part);
|
|
1655
|
-
};
|
|
1656
|
-
})()
|
|
2563
|
+
createDebugSummaryTransform({
|
|
2564
|
+
protocol,
|
|
2565
|
+
getFullRawText: () => fullRawText,
|
|
2566
|
+
tools,
|
|
2567
|
+
params
|
|
1657
2568
|
})
|
|
1658
2569
|
);
|
|
1659
2570
|
return {
|
|
@@ -1665,7 +2576,7 @@ async function toolChoiceStream({
|
|
|
1665
2576
|
doGenerate,
|
|
1666
2577
|
options
|
|
1667
2578
|
}) {
|
|
1668
|
-
var _a, _b;
|
|
2579
|
+
var _a, _b, _c;
|
|
1669
2580
|
const result = await doGenerate();
|
|
1670
2581
|
let toolJson = {};
|
|
1671
2582
|
if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
|
|
@@ -1685,19 +2596,26 @@ async function toolChoiceStream({
|
|
|
1685
2596
|
}
|
|
1686
2597
|
const toolCallChunk = {
|
|
1687
2598
|
type: "tool-call",
|
|
1688
|
-
toolCallId: (0,
|
|
2599
|
+
toolCallId: (0, import_provider_utils4.generateId)(),
|
|
1689
2600
|
toolName: toolJson.name || "unknown",
|
|
1690
2601
|
input: JSON.stringify(toolJson.arguments || {})
|
|
1691
2602
|
};
|
|
1692
2603
|
const finishChunk = {
|
|
1693
2604
|
type: "finish",
|
|
1694
|
-
usage: (result == null ? void 0 : result.usage) ||
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
2605
|
+
usage: (result == null ? void 0 : result.usage) || {
|
|
2606
|
+
inputTokens: {
|
|
2607
|
+
total: 0,
|
|
2608
|
+
noCache: void 0,
|
|
2609
|
+
cacheRead: void 0,
|
|
2610
|
+
cacheWrite: void 0
|
|
2611
|
+
},
|
|
2612
|
+
outputTokens: {
|
|
2613
|
+
total: 0,
|
|
2614
|
+
text: void 0,
|
|
2615
|
+
reasoning: void 0
|
|
2616
|
+
}
|
|
1699
2617
|
},
|
|
1700
|
-
finishReason: "tool-calls"
|
|
2618
|
+
finishReason: { unified: "tool-calls", raw: void 0 }
|
|
1701
2619
|
};
|
|
1702
2620
|
const stream = new ReadableStream({
|
|
1703
2621
|
start(controller) {
|
|
@@ -1707,7 +2625,7 @@ async function toolChoiceStream({
|
|
|
1707
2625
|
}
|
|
1708
2626
|
});
|
|
1709
2627
|
const debugLevel = getDebugLevel();
|
|
1710
|
-
const firstText = (result == null ? void 0 : result.content)
|
|
2628
|
+
const firstText = ((_c = result == null ? void 0 : result.content) == null ? void 0 : _c[0]) && result.content[0].type === "text" && result.content[0].text || "";
|
|
1711
2629
|
const streamWithSummary = debugLevel === "parse" ? stream.pipeThrough(
|
|
1712
2630
|
new TransformStream({
|
|
1713
2631
|
transform(part, controller) {
|
|
@@ -1731,40 +2649,110 @@ async function toolChoiceStream({
|
|
|
1731
2649
|
};
|
|
1732
2650
|
}
|
|
1733
2651
|
|
|
1734
|
-
// src/
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
2652
|
+
// src/utils/dynamic-tool-schema.ts
|
|
2653
|
+
function createDynamicIfThenElseSchema(tools) {
|
|
2654
|
+
let currentSchema = {};
|
|
2655
|
+
const toolNames = [];
|
|
2656
|
+
for (let i = tools.length - 1; i >= 0; i -= 1) {
|
|
2657
|
+
const tool = tools[i];
|
|
2658
|
+
if (tool.type === "provider") {
|
|
2659
|
+
throw new Error(
|
|
2660
|
+
"Provider tools are not supported by this middleware. Please use function tools."
|
|
2661
|
+
);
|
|
2662
|
+
}
|
|
2663
|
+
toolNames.unshift(tool.name);
|
|
2664
|
+
const toolCondition = {
|
|
2665
|
+
if: {
|
|
2666
|
+
properties: {
|
|
2667
|
+
name: {
|
|
2668
|
+
const: tool.name
|
|
2669
|
+
}
|
|
2670
|
+
},
|
|
2671
|
+
required: ["name"]
|
|
2672
|
+
},
|
|
2673
|
+
// biome-ignore lint/suspicious/noThenProperty: JSON Schema uses 'then' as a keyword
|
|
2674
|
+
then: {
|
|
2675
|
+
properties: {
|
|
2676
|
+
name: {
|
|
2677
|
+
const: tool.name
|
|
2678
|
+
},
|
|
2679
|
+
arguments: tool.inputSchema
|
|
2680
|
+
},
|
|
2681
|
+
required: ["name", "arguments"]
|
|
2682
|
+
}
|
|
2683
|
+
};
|
|
2684
|
+
if (Object.keys(currentSchema).length > 0) {
|
|
2685
|
+
toolCondition.else = currentSchema;
|
|
2686
|
+
}
|
|
2687
|
+
currentSchema = toolCondition;
|
|
2688
|
+
}
|
|
2689
|
+
return {
|
|
2690
|
+
type: "object",
|
|
2691
|
+
// Explicitly specify type as "object"
|
|
2692
|
+
properties: {
|
|
2693
|
+
name: {
|
|
2694
|
+
type: "string",
|
|
2695
|
+
description: "Name of the tool to call",
|
|
2696
|
+
enum: toolNames
|
|
2697
|
+
},
|
|
2698
|
+
arguments: {
|
|
2699
|
+
type: "object",
|
|
2700
|
+
// By default, arguments is also specified as object type
|
|
2701
|
+
description: "Argument object to be passed to the tool"
|
|
2702
|
+
}
|
|
1758
2703
|
},
|
|
1759
|
-
|
|
1760
|
-
|
|
2704
|
+
required: ["name", "arguments"],
|
|
2705
|
+
...currentSchema
|
|
2706
|
+
};
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
// src/transform-handler.ts
|
|
2710
|
+
function buildFinalPrompt(systemPrompt, processedPrompt, placement) {
|
|
2711
|
+
const systemIndex = processedPrompt.findIndex((m) => m.role === "system");
|
|
2712
|
+
if (systemIndex !== -1) {
|
|
2713
|
+
const existing = processedPrompt[systemIndex].content;
|
|
2714
|
+
let existingText = "";
|
|
2715
|
+
if (typeof existing === "string") {
|
|
2716
|
+
existingText = existing;
|
|
2717
|
+
} else if (Array.isArray(existing)) {
|
|
2718
|
+
existingText = existing.map((p) => {
|
|
2719
|
+
var _a;
|
|
2720
|
+
return (p == null ? void 0 : p.type) === "text" ? (_a = p.text) != null ? _a : "" : "";
|
|
2721
|
+
}).filter(Boolean).join("\n");
|
|
2722
|
+
} else {
|
|
2723
|
+
existingText = String(existing != null ? existing : "");
|
|
2724
|
+
}
|
|
2725
|
+
const mergedContent = placement === "first" ? `${systemPrompt}
|
|
2726
|
+
|
|
2727
|
+
${existingText}` : `${existingText}
|
|
2728
|
+
|
|
2729
|
+
${systemPrompt}`;
|
|
2730
|
+
return processedPrompt.map(
|
|
2731
|
+
(m, idx) => idx === systemIndex ? {
|
|
2732
|
+
...m,
|
|
2733
|
+
content: mergedContent
|
|
2734
|
+
} : m
|
|
2735
|
+
);
|
|
2736
|
+
}
|
|
2737
|
+
if (placement === "first") {
|
|
2738
|
+
return [
|
|
2739
|
+
{
|
|
2740
|
+
role: "system",
|
|
2741
|
+
content: systemPrompt
|
|
2742
|
+
},
|
|
2743
|
+
...processedPrompt
|
|
2744
|
+
];
|
|
2745
|
+
}
|
|
2746
|
+
return [
|
|
2747
|
+
...processedPrompt,
|
|
1761
2748
|
{
|
|
1762
2749
|
role: "system",
|
|
1763
2750
|
content: systemPrompt
|
|
1764
|
-
}
|
|
1765
|
-
...processedPrompt
|
|
2751
|
+
}
|
|
1766
2752
|
];
|
|
1767
|
-
|
|
2753
|
+
}
|
|
2754
|
+
function buildBaseReturnParams(params, finalPrompt, functionTools) {
|
|
2755
|
+
return {
|
|
1768
2756
|
...params,
|
|
1769
2757
|
prompt: finalPrompt,
|
|
1770
2758
|
tools: [],
|
|
@@ -1773,184 +2761,242 @@ async function transformParams({
|
|
|
1773
2761
|
...params.providerOptions || {},
|
|
1774
2762
|
toolCallMiddleware: {
|
|
1775
2763
|
...params.providerOptions && typeof params.providerOptions === "object" && params.providerOptions.toolCallMiddleware || {},
|
|
1776
|
-
// INTERNAL: used by the middleware so downstream parsers can access
|
|
1777
|
-
// the original tool schemas even if providers strip `params.tools`.
|
|
1778
|
-
// Not a stable public API.
|
|
1779
2764
|
originalTools: originalToolsSchema.encode(functionTools)
|
|
1780
2765
|
}
|
|
1781
2766
|
}
|
|
1782
2767
|
};
|
|
1783
|
-
|
|
2768
|
+
}
|
|
2769
|
+
function findProviderDefinedTool(tools, selectedToolName) {
|
|
2770
|
+
return tools.find((t) => {
|
|
2771
|
+
if (t.type === "function") {
|
|
2772
|
+
return false;
|
|
2773
|
+
}
|
|
2774
|
+
const anyTool = t;
|
|
2775
|
+
return anyTool.id === selectedToolName || anyTool.name === selectedToolName;
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
function handleToolChoiceTool(params, baseReturnParams) {
|
|
2779
|
+
var _a, _b, _c;
|
|
2780
|
+
const selectedToolName = (_a = params.toolChoice) == null ? void 0 : _a.toolName;
|
|
2781
|
+
if (!selectedToolName) {
|
|
2782
|
+
throw new Error("Tool name is required for 'tool' toolChoice type.");
|
|
2783
|
+
}
|
|
2784
|
+
const providerDefinedMatch = findProviderDefinedTool(
|
|
2785
|
+
(_b = params.tools) != null ? _b : [],
|
|
2786
|
+
selectedToolName
|
|
2787
|
+
);
|
|
2788
|
+
if (providerDefinedMatch) {
|
|
1784
2789
|
throw new Error(
|
|
1785
|
-
"
|
|
2790
|
+
"Provider-defined tools are not supported by this middleware. Please use custom tools."
|
|
1786
2791
|
);
|
|
1787
2792
|
}
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
});
|
|
1795
|
-
if (providerDefinedMatch) {
|
|
1796
|
-
throw new Error(
|
|
1797
|
-
"Provider-defined tools are not supported by this middleware. Please use custom tools."
|
|
1798
|
-
);
|
|
1799
|
-
}
|
|
1800
|
-
const selectedTool = ((_g = params.tools) != null ? _g : []).find(
|
|
1801
|
-
(t) => t.type === "function" && t.name === selectedToolName
|
|
2793
|
+
const selectedTool = ((_c = params.tools) != null ? _c : []).find(
|
|
2794
|
+
(t) => t.type === "function" && t.name === selectedToolName
|
|
2795
|
+
);
|
|
2796
|
+
if (!selectedTool) {
|
|
2797
|
+
throw new Error(
|
|
2798
|
+
`Tool with name '${selectedToolName}' not found in params.tools.`
|
|
1802
2799
|
);
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
type: "object",
|
|
1814
|
-
properties: {
|
|
1815
|
-
name: {
|
|
1816
|
-
const: selectedTool.name
|
|
1817
|
-
},
|
|
1818
|
-
arguments: selectedTool.inputSchema
|
|
2800
|
+
}
|
|
2801
|
+
return {
|
|
2802
|
+
...baseReturnParams,
|
|
2803
|
+
responseFormat: {
|
|
2804
|
+
type: "json",
|
|
2805
|
+
schema: {
|
|
2806
|
+
type: "object",
|
|
2807
|
+
properties: {
|
|
2808
|
+
name: {
|
|
2809
|
+
const: selectedTool.name
|
|
1819
2810
|
},
|
|
1820
|
-
|
|
2811
|
+
arguments: selectedTool.inputSchema
|
|
1821
2812
|
},
|
|
1822
|
-
|
|
1823
|
-
description: typeof selectedTool.description === "string" ? selectedTool.description : void 0
|
|
2813
|
+
required: ["name", "arguments"]
|
|
1824
2814
|
},
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
}
|
|
2815
|
+
name: selectedTool.name,
|
|
2816
|
+
description: typeof selectedTool.description === "string" ? selectedTool.description : void 0
|
|
2817
|
+
},
|
|
2818
|
+
providerOptions: {
|
|
2819
|
+
...baseReturnParams.providerOptions || {},
|
|
2820
|
+
toolCallMiddleware: {
|
|
2821
|
+
...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
|
|
2822
|
+
...params.toolChoice ? { toolChoice: params.toolChoice } : {}
|
|
1833
2823
|
}
|
|
1834
|
-
}
|
|
2824
|
+
}
|
|
2825
|
+
};
|
|
2826
|
+
}
|
|
2827
|
+
function handleToolChoiceRequired(params, baseReturnParams, functionTools) {
|
|
2828
|
+
if (!params.tools || params.tools.length === 0) {
|
|
2829
|
+
throw new Error(
|
|
2830
|
+
"Tool choice type 'required' is set, but no tools are provided in params.tools."
|
|
2831
|
+
);
|
|
1835
2832
|
}
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
2833
|
+
return {
|
|
2834
|
+
...baseReturnParams,
|
|
2835
|
+
responseFormat: {
|
|
2836
|
+
type: "json",
|
|
2837
|
+
schema: createDynamicIfThenElseSchema(functionTools)
|
|
2838
|
+
},
|
|
2839
|
+
providerOptions: {
|
|
2840
|
+
...baseReturnParams.providerOptions || {},
|
|
2841
|
+
toolCallMiddleware: {
|
|
2842
|
+
...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
|
|
2843
|
+
toolChoice: { type: "required" }
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2846
|
+
};
|
|
2847
|
+
}
|
|
2848
|
+
function transformParams({
|
|
2849
|
+
params,
|
|
2850
|
+
protocol,
|
|
2851
|
+
toolSystemPromptTemplate,
|
|
2852
|
+
placement = "first"
|
|
2853
|
+
}) {
|
|
2854
|
+
var _a, _b, _c, _d, _e;
|
|
2855
|
+
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
2856
|
+
const functionTools = ((_a = params.tools) != null ? _a : []).filter(
|
|
2857
|
+
(t) => t.type === "function"
|
|
2858
|
+
);
|
|
2859
|
+
const systemPrompt = resolvedProtocol.formatTools({
|
|
2860
|
+
tools: functionTools,
|
|
2861
|
+
toolSystemPromptTemplate
|
|
2862
|
+
});
|
|
2863
|
+
const processedPrompt = convertToolPrompt(
|
|
2864
|
+
(_b = params.prompt) != null ? _b : [],
|
|
2865
|
+
resolvedProtocol,
|
|
2866
|
+
extractOnErrorOption(params.providerOptions)
|
|
2867
|
+
);
|
|
2868
|
+
const finalPrompt = buildFinalPrompt(
|
|
2869
|
+
systemPrompt,
|
|
2870
|
+
processedPrompt,
|
|
2871
|
+
placement
|
|
2872
|
+
);
|
|
2873
|
+
const baseReturnParams = buildBaseReturnParams(
|
|
2874
|
+
params,
|
|
2875
|
+
finalPrompt,
|
|
2876
|
+
functionTools
|
|
2877
|
+
);
|
|
2878
|
+
if (((_c = params.toolChoice) == null ? void 0 : _c.type) === "none") {
|
|
2879
|
+
throw new Error(
|
|
2880
|
+
"The 'none' toolChoice type is not supported by this middleware. Please use 'auto', 'required', or specify a tool name."
|
|
2881
|
+
);
|
|
2882
|
+
}
|
|
2883
|
+
if (((_d = params.toolChoice) == null ? void 0 : _d.type) === "tool") {
|
|
2884
|
+
return handleToolChoiceTool(params, baseReturnParams);
|
|
2885
|
+
}
|
|
2886
|
+
if (((_e = params.toolChoice) == null ? void 0 : _e.type) === "required") {
|
|
2887
|
+
return handleToolChoiceRequired(params, baseReturnParams, functionTools);
|
|
2888
|
+
}
|
|
2889
|
+
return baseReturnParams;
|
|
2890
|
+
}
|
|
2891
|
+
function processAssistantContent(content, resolvedProtocol, providerOptions) {
|
|
2892
|
+
var _a;
|
|
2893
|
+
const newContent = [];
|
|
2894
|
+
for (const item of content) {
|
|
2895
|
+
if (isToolCallContent(item)) {
|
|
2896
|
+
newContent.push({
|
|
2897
|
+
type: "text",
|
|
2898
|
+
text: resolvedProtocol.formatToolCall(item)
|
|
2899
|
+
});
|
|
2900
|
+
} else if (item.type === "text") {
|
|
2901
|
+
newContent.push(item);
|
|
2902
|
+
} else if (item.type === "reasoning") {
|
|
2903
|
+
newContent.push(item);
|
|
2904
|
+
} else {
|
|
2905
|
+
const options = extractOnErrorOption(providerOptions);
|
|
2906
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
2907
|
+
options,
|
|
2908
|
+
"tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
|
|
2909
|
+
{ content: item }
|
|
1840
2910
|
);
|
|
2911
|
+
newContent.push({
|
|
2912
|
+
type: "text",
|
|
2913
|
+
text: JSON.stringify(item)
|
|
2914
|
+
});
|
|
1841
2915
|
}
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
2916
|
+
}
|
|
2917
|
+
const onlyText = newContent.every((c) => c.type === "text");
|
|
2918
|
+
return onlyText ? [
|
|
2919
|
+
{
|
|
2920
|
+
type: "text",
|
|
2921
|
+
text: newContent.map((c) => c.text).join("\n")
|
|
2922
|
+
}
|
|
2923
|
+
] : newContent;
|
|
2924
|
+
}
|
|
2925
|
+
function processToolMessage(content, resolvedProtocol) {
|
|
2926
|
+
return {
|
|
2927
|
+
role: "user",
|
|
2928
|
+
content: [
|
|
2929
|
+
{
|
|
2930
|
+
type: "text",
|
|
2931
|
+
text: content.map((toolResult) => resolvedProtocol.formatToolResponse(toolResult)).join("\n")
|
|
1856
2932
|
}
|
|
2933
|
+
]
|
|
2934
|
+
};
|
|
2935
|
+
}
|
|
2936
|
+
function processMessage(message, resolvedProtocol, providerOptions) {
|
|
2937
|
+
if (message.role === "assistant") {
|
|
2938
|
+
const condensedContent = processAssistantContent(
|
|
2939
|
+
message.content,
|
|
2940
|
+
resolvedProtocol,
|
|
2941
|
+
providerOptions
|
|
2942
|
+
);
|
|
2943
|
+
return {
|
|
2944
|
+
role: "assistant",
|
|
2945
|
+
content: condensedContent
|
|
1857
2946
|
};
|
|
1858
2947
|
}
|
|
1859
|
-
|
|
2948
|
+
if (message.role === "tool") {
|
|
2949
|
+
const toolResultParts = message.content.filter(
|
|
2950
|
+
(part) => part.type === "tool-result"
|
|
2951
|
+
);
|
|
2952
|
+
return processToolMessage(toolResultParts, resolvedProtocol);
|
|
2953
|
+
}
|
|
2954
|
+
return message;
|
|
1860
2955
|
}
|
|
1861
|
-
function
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
text: JSON.stringify(content)
|
|
1886
|
-
});
|
|
1887
|
-
}
|
|
2956
|
+
function isAllTextContent(content) {
|
|
2957
|
+
if (!Array.isArray(content)) {
|
|
2958
|
+
return false;
|
|
2959
|
+
}
|
|
2960
|
+
return content.every(
|
|
2961
|
+
(c) => (c == null ? void 0 : c.type) === "text"
|
|
2962
|
+
);
|
|
2963
|
+
}
|
|
2964
|
+
function joinTextContent(content) {
|
|
2965
|
+
return content.map((c) => c.text).join("\n");
|
|
2966
|
+
}
|
|
2967
|
+
function createCondensedMessage(role, joinedText) {
|
|
2968
|
+
if (role === "system") {
|
|
2969
|
+
return {
|
|
2970
|
+
role: "system",
|
|
2971
|
+
content: joinedText
|
|
2972
|
+
};
|
|
2973
|
+
}
|
|
2974
|
+
return {
|
|
2975
|
+
role,
|
|
2976
|
+
content: [
|
|
2977
|
+
{
|
|
2978
|
+
type: "text",
|
|
2979
|
+
text: joinedText
|
|
1888
2980
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
}
|
|
1895
|
-
] : newContent;
|
|
1896
|
-
return { role: "assistant", content: condensedAssistant };
|
|
1897
|
-
}
|
|
1898
|
-
if (message.role === "tool") {
|
|
1899
|
-
return {
|
|
1900
|
-
role: "user",
|
|
1901
|
-
// Map tool results to text response blocks, then condense into a single text block
|
|
1902
|
-
content: [
|
|
1903
|
-
{
|
|
1904
|
-
type: "text",
|
|
1905
|
-
text: message.content.map(
|
|
1906
|
-
(toolResult) => isToolResultPart(toolResult) ? resolvedProtocol.formatToolResponse(toolResult) : resolvedProtocol.formatToolResponse(
|
|
1907
|
-
toolResult
|
|
1908
|
-
)
|
|
1909
|
-
).join("\n")
|
|
1910
|
-
}
|
|
1911
|
-
]
|
|
1912
|
-
};
|
|
1913
|
-
}
|
|
1914
|
-
return message;
|
|
1915
|
-
});
|
|
1916
|
-
for (let i = 0; i < processedPrompt.length; i++) {
|
|
2981
|
+
]
|
|
2982
|
+
};
|
|
2983
|
+
}
|
|
2984
|
+
function condenseTextContent(processedPrompt) {
|
|
2985
|
+
for (let i = 0; i < processedPrompt.length; i += 1) {
|
|
1917
2986
|
const msg = processedPrompt[i];
|
|
1918
|
-
if (Array.isArray(msg.content)) {
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
processedPrompt[i] = {
|
|
1926
|
-
role: "system",
|
|
1927
|
-
content: joinedText
|
|
1928
|
-
};
|
|
1929
|
-
} else if (msg.role === "assistant") {
|
|
1930
|
-
processedPrompt[i] = {
|
|
1931
|
-
role: "assistant",
|
|
1932
|
-
content: [
|
|
1933
|
-
{
|
|
1934
|
-
type: "text",
|
|
1935
|
-
text: joinedText
|
|
1936
|
-
}
|
|
1937
|
-
]
|
|
1938
|
-
};
|
|
1939
|
-
} else {
|
|
1940
|
-
processedPrompt[i] = {
|
|
1941
|
-
role: "user",
|
|
1942
|
-
content: [
|
|
1943
|
-
{
|
|
1944
|
-
type: "text",
|
|
1945
|
-
text: joinedText
|
|
1946
|
-
}
|
|
1947
|
-
]
|
|
1948
|
-
};
|
|
1949
|
-
}
|
|
1950
|
-
}
|
|
2987
|
+
if (!Array.isArray(msg.content)) {
|
|
2988
|
+
continue;
|
|
2989
|
+
}
|
|
2990
|
+
const shouldCondense = isAllTextContent(msg.content) && msg.content.length > 1;
|
|
2991
|
+
if (shouldCondense) {
|
|
2992
|
+
const joinedText = joinTextContent(msg.content);
|
|
2993
|
+
processedPrompt[i] = createCondensedMessage(msg.role, joinedText);
|
|
1951
2994
|
}
|
|
1952
2995
|
}
|
|
1953
|
-
|
|
2996
|
+
return processedPrompt;
|
|
2997
|
+
}
|
|
2998
|
+
function mergeConsecutiveUserMessages(processedPrompt) {
|
|
2999
|
+
for (let i = processedPrompt.length - 1; i > 0; i -= 1) {
|
|
1954
3000
|
const current = processedPrompt[i];
|
|
1955
3001
|
const prev = processedPrompt[i - 1];
|
|
1956
3002
|
if (current.role === "user" && prev.role === "user") {
|
|
@@ -1958,51 +3004,57 @@ function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
|
|
|
1958
3004
|
const currentContent = current.content.map((c) => c.type === "text" ? c.text : "").join("\n");
|
|
1959
3005
|
processedPrompt[i - 1] = {
|
|
1960
3006
|
role: "user",
|
|
1961
|
-
content: [{ type: "text", text: prevContent
|
|
3007
|
+
content: [{ type: "text", text: `${prevContent}
|
|
3008
|
+
${currentContent}` }]
|
|
1962
3009
|
};
|
|
1963
3010
|
processedPrompt.splice(i, 1);
|
|
1964
3011
|
}
|
|
1965
3012
|
}
|
|
1966
3013
|
return processedPrompt;
|
|
1967
3014
|
}
|
|
3015
|
+
function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
|
|
3016
|
+
let processedPrompt = prompt.map(
|
|
3017
|
+
(message) => processMessage(message, resolvedProtocol, providerOptions)
|
|
3018
|
+
);
|
|
3019
|
+
processedPrompt = condenseTextContent(processedPrompt);
|
|
3020
|
+
processedPrompt = mergeConsecutiveUserMessages(processedPrompt);
|
|
3021
|
+
return processedPrompt;
|
|
3022
|
+
}
|
|
1968
3023
|
|
|
1969
3024
|
// src/tool-call-middleware.ts
|
|
1970
3025
|
function createToolMiddleware({
|
|
1971
3026
|
protocol,
|
|
1972
|
-
toolSystemPromptTemplate
|
|
3027
|
+
toolSystemPromptTemplate,
|
|
3028
|
+
placement = "last"
|
|
1973
3029
|
}) {
|
|
1974
3030
|
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
1975
3031
|
return {
|
|
1976
|
-
|
|
1977
|
-
wrapStream:
|
|
3032
|
+
specificationVersion: "v3",
|
|
3033
|
+
wrapStream: ({ doStream, doGenerate, params }) => {
|
|
1978
3034
|
if (isToolChoiceActive(params)) {
|
|
1979
3035
|
return toolChoiceStream({
|
|
1980
3036
|
doGenerate,
|
|
1981
3037
|
options: extractOnErrorOption(params.providerOptions)
|
|
1982
3038
|
});
|
|
1983
|
-
} else {
|
|
1984
|
-
return wrapStream({
|
|
1985
|
-
protocol: resolvedProtocol,
|
|
1986
|
-
doStream,
|
|
1987
|
-
doGenerate,
|
|
1988
|
-
params
|
|
1989
|
-
});
|
|
1990
3039
|
}
|
|
3040
|
+
return wrapStream({
|
|
3041
|
+
protocol: resolvedProtocol,
|
|
3042
|
+
doStream,
|
|
3043
|
+
doGenerate,
|
|
3044
|
+
params
|
|
3045
|
+
});
|
|
1991
3046
|
},
|
|
1992
3047
|
wrapGenerate: async ({ doGenerate, params }) => wrapGenerate({
|
|
1993
3048
|
protocol: resolvedProtocol,
|
|
1994
3049
|
doGenerate,
|
|
1995
3050
|
params
|
|
1996
3051
|
}),
|
|
1997
|
-
transformParams: async ({
|
|
3052
|
+
transformParams: async ({ params }) => transformParams({
|
|
3053
|
+
protocol: resolvedProtocol,
|
|
3054
|
+
toolSystemPromptTemplate,
|
|
3055
|
+
placement,
|
|
1998
3056
|
params
|
|
1999
|
-
})
|
|
2000
|
-
return transformParams({
|
|
2001
|
-
protocol: resolvedProtocol,
|
|
2002
|
-
toolSystemPromptTemplate,
|
|
2003
|
-
params
|
|
2004
|
-
});
|
|
2005
|
-
}
|
|
3057
|
+
})
|
|
2006
3058
|
};
|
|
2007
3059
|
}
|
|
2008
3060
|
|
|
@@ -2046,6 +3098,7 @@ For each function call return a json object with function name and arguments wit
|
|
|
2046
3098
|
});
|
|
2047
3099
|
var morphXmlToolMiddleware = createToolMiddleware({
|
|
2048
3100
|
protocol: morphXmlProtocol,
|
|
3101
|
+
placement: "last",
|
|
2049
3102
|
toolSystemPromptTemplate(tools) {
|
|
2050
3103
|
return `You are a function calling AI model.
|
|
2051
3104
|
|
|
@@ -2068,7 +3121,7 @@ Available functions are listed inside <tools></tools>.
|
|
|
2068
3121
|
}
|
|
2069
3122
|
});
|
|
2070
3123
|
|
|
2071
|
-
// src/community/
|
|
3124
|
+
// src/community/sijawara.ts
|
|
2072
3125
|
var sijawaraDetailedXmlToolMiddleware = createToolMiddleware({
|
|
2073
3126
|
protocol: morphXmlProtocol,
|
|
2074
3127
|
toolSystemPromptTemplate(tools) {
|