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