@ai-sdk-tool/parser 2.1.7 → 3.0.0-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-FOANBZRH.js +2514 -0
- package/dist/chunk-FOANBZRH.js.map +1 -0
- package/dist/community.cjs +1345 -925
- 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 +1 -1
- package/dist/index.cjs +1357 -927
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +80 -79
- package/dist/index.d.ts +80 -79
- package/dist/index.js +9 -3
- package/package.json +8 -14
- package/dist/chunk-GSD5HDOQ.js +0 -2068
- package/dist/chunk-GSD5HDOQ.js.map +0 -1
package/dist/community.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// src/community/index.ts
|
|
@@ -41,11 +31,130 @@ var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
|
41
31
|
// src/protocols/json-mix-protocol.ts
|
|
42
32
|
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
43
33
|
|
|
34
|
+
// src/utils/debug.ts
|
|
35
|
+
var LINE_SPLIT_REGEX = /\r?\n/;
|
|
36
|
+
function normalizeBooleanString(value) {
|
|
37
|
+
const normalized = value.trim().toLowerCase();
|
|
38
|
+
if (normalized === "1" || normalized === "true" || normalized === "yes") {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
if (normalized === "0" || normalized === "false" || normalized === "no") {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
function getDebugLevel() {
|
|
47
|
+
const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW || "off";
|
|
48
|
+
const envLower = String(envVal).toLowerCase();
|
|
49
|
+
if (envLower === "stream" || envLower === "parse" || envLower === "off") {
|
|
50
|
+
return envLower;
|
|
51
|
+
}
|
|
52
|
+
const boolEnv = normalizeBooleanString(envLower);
|
|
53
|
+
if (boolEnv === true) {
|
|
54
|
+
return "stream";
|
|
55
|
+
}
|
|
56
|
+
if (envLower === "2") {
|
|
57
|
+
return "parse";
|
|
58
|
+
}
|
|
59
|
+
return "off";
|
|
60
|
+
}
|
|
61
|
+
function color(code) {
|
|
62
|
+
return (text) => `\x1B[${code}m${text}\x1B[0m`;
|
|
63
|
+
}
|
|
64
|
+
var ANSI_GRAY = 90;
|
|
65
|
+
var ANSI_YELLOW = 33;
|
|
66
|
+
var ANSI_CYAN = 36;
|
|
67
|
+
var ANSI_BG_BLUE = 44;
|
|
68
|
+
var ANSI_BG_GREEN = 42;
|
|
69
|
+
var ANSI_INVERSE = 7;
|
|
70
|
+
var ANSI_UNDERLINE = 4;
|
|
71
|
+
var ANSI_BOLD = 1;
|
|
72
|
+
var cGray = color(ANSI_GRAY);
|
|
73
|
+
var cYellow = color(ANSI_YELLOW);
|
|
74
|
+
var cCyan = color(ANSI_CYAN);
|
|
75
|
+
var cBgBlue = color(ANSI_BG_BLUE);
|
|
76
|
+
var cBgGreen = color(ANSI_BG_GREEN);
|
|
77
|
+
var cInverse = color(ANSI_INVERSE);
|
|
78
|
+
var cUnderline = color(ANSI_UNDERLINE);
|
|
79
|
+
var cBold = color(ANSI_BOLD);
|
|
80
|
+
function safeStringify(value) {
|
|
81
|
+
try {
|
|
82
|
+
return `
|
|
83
|
+
${typeof value === "string" ? value : JSON.stringify(value, null, 2)}`;
|
|
84
|
+
} catch (e) {
|
|
85
|
+
return String(value);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function logRawChunk(part) {
|
|
89
|
+
console.log(cGray("[debug:mw:raw]"), cYellow(safeStringify(part)));
|
|
90
|
+
}
|
|
91
|
+
function logParsedChunk(part) {
|
|
92
|
+
console.log(cGray("[debug:mw:out]"), cCyan(safeStringify(part)));
|
|
93
|
+
}
|
|
94
|
+
function getHighlightStyle() {
|
|
95
|
+
const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW_STYLE || "bg";
|
|
96
|
+
const normalized = String(envVal).trim().toLowerCase();
|
|
97
|
+
if (normalized === "inverse" || normalized === "invert") {
|
|
98
|
+
return "inverse";
|
|
99
|
+
}
|
|
100
|
+
if (normalized === "underline" || normalized === "ul") {
|
|
101
|
+
return "underline";
|
|
102
|
+
}
|
|
103
|
+
if (normalized === "bold") {
|
|
104
|
+
return "bold";
|
|
105
|
+
}
|
|
106
|
+
if (normalized === "bg" || normalized === "background") {
|
|
107
|
+
return "bg";
|
|
108
|
+
}
|
|
109
|
+
const asBool = normalizeBooleanString(normalized);
|
|
110
|
+
if (asBool === true) {
|
|
111
|
+
return "bg";
|
|
112
|
+
}
|
|
113
|
+
return "bg";
|
|
114
|
+
}
|
|
115
|
+
function getHighlightFunction(style) {
|
|
116
|
+
if (style === "inverse") {
|
|
117
|
+
return cInverse;
|
|
118
|
+
}
|
|
119
|
+
if (style === "underline") {
|
|
120
|
+
return cUnderline;
|
|
121
|
+
}
|
|
122
|
+
if (style === "bold") {
|
|
123
|
+
return cBold;
|
|
124
|
+
}
|
|
125
|
+
if (style === "bg") {
|
|
126
|
+
return cBgGreen;
|
|
127
|
+
}
|
|
128
|
+
return cYellow;
|
|
129
|
+
}
|
|
130
|
+
function renderHighlightedText(originalText, style, highlight) {
|
|
131
|
+
if (style === "bg" || style === "inverse" || style === "underline" || style === "bold") {
|
|
132
|
+
return originalText.split(LINE_SPLIT_REGEX).map((line) => line.length ? highlight(line) : line).join("\n");
|
|
133
|
+
}
|
|
134
|
+
return highlight(originalText);
|
|
135
|
+
}
|
|
136
|
+
function logParsedSummary({
|
|
137
|
+
toolCalls,
|
|
138
|
+
originalText
|
|
139
|
+
}) {
|
|
140
|
+
if (originalText) {
|
|
141
|
+
const style = getHighlightStyle();
|
|
142
|
+
const highlight = getHighlightFunction(style);
|
|
143
|
+
const rendered = renderHighlightedText(originalText, style, highlight);
|
|
144
|
+
console.log(cGray("[debug:mw:origin]"), `
|
|
145
|
+
${rendered}`);
|
|
146
|
+
}
|
|
147
|
+
if (toolCalls.length > 0) {
|
|
148
|
+
const styledSummary = safeStringify(toolCalls).split(LINE_SPLIT_REGEX).map((line) => line.length ? cBgBlue(line) : line).join("\n");
|
|
149
|
+
console.log(cGray("[debug:mw:summary]"), styledSummary);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
44
153
|
// src/utils/dynamic-tool-schema.ts
|
|
45
154
|
function createDynamicIfThenElseSchema(tools) {
|
|
46
155
|
let currentSchema = {};
|
|
47
156
|
const toolNames = [];
|
|
48
|
-
for (let i = tools.length - 1; i >= 0; i
|
|
157
|
+
for (let i = tools.length - 1; i >= 0; i -= 1) {
|
|
49
158
|
const tool = tools[i];
|
|
50
159
|
if (tool.type === "provider-defined") {
|
|
51
160
|
throw new Error(
|
|
@@ -62,6 +171,7 @@ function createDynamicIfThenElseSchema(tools) {
|
|
|
62
171
|
},
|
|
63
172
|
required: ["name"]
|
|
64
173
|
},
|
|
174
|
+
// biome-ignore lint/suspicious/noThenProperty: JSON Schema uses 'then' as a keyword
|
|
65
175
|
then: {
|
|
66
176
|
properties: {
|
|
67
177
|
name: {
|
|
@@ -106,7 +216,7 @@ function getPotentialStartIndex(text, searchedText) {
|
|
|
106
216
|
if (directIndex !== -1) {
|
|
107
217
|
return directIndex;
|
|
108
218
|
}
|
|
109
|
-
for (let i = text.length - 1; i >= 0; i
|
|
219
|
+
for (let i = text.length - 1; i >= 0; i -= 1) {
|
|
110
220
|
const suffix = text.substring(i);
|
|
111
221
|
if (searchedText.startsWith(suffix)) {
|
|
112
222
|
return i;
|
|
@@ -115,6 +225,45 @@ function getPotentialStartIndex(text, searchedText) {
|
|
|
115
225
|
return null;
|
|
116
226
|
}
|
|
117
227
|
|
|
228
|
+
// src/utils/on-error.ts
|
|
229
|
+
function extractOnErrorOption(providerOptions) {
|
|
230
|
+
var _a;
|
|
231
|
+
if (providerOptions && typeof providerOptions === "object") {
|
|
232
|
+
const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
|
|
233
|
+
return onError ? { onError } : void 0;
|
|
234
|
+
}
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/utils/provider-options.ts
|
|
239
|
+
var originalToolsSchema = {
|
|
240
|
+
encode: encodeOriginalTools,
|
|
241
|
+
decode: decodeOriginalTools
|
|
242
|
+
};
|
|
243
|
+
function encodeOriginalTools(tools) {
|
|
244
|
+
return (tools == null ? void 0 : tools.map((t) => ({
|
|
245
|
+
name: t.name,
|
|
246
|
+
inputSchema: JSON.stringify(t.inputSchema)
|
|
247
|
+
}))) || [];
|
|
248
|
+
}
|
|
249
|
+
function decodeOriginalTools(originalTools) {
|
|
250
|
+
if (!originalTools) {
|
|
251
|
+
return [];
|
|
252
|
+
}
|
|
253
|
+
return originalTools.map(
|
|
254
|
+
(t) => ({
|
|
255
|
+
type: "function",
|
|
256
|
+
name: t.name,
|
|
257
|
+
inputSchema: JSON.parse(t.inputSchema)
|
|
258
|
+
})
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
function isToolChoiceActive(params) {
|
|
262
|
+
var _a, _b, _c;
|
|
263
|
+
const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
|
|
264
|
+
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"));
|
|
265
|
+
}
|
|
266
|
+
|
|
118
267
|
// src/utils/regex.ts
|
|
119
268
|
function escapeRegExp(literal) {
|
|
120
269
|
return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -127,9 +276,24 @@ __export(robust_json_exports, {
|
|
|
127
276
|
stringify: () => stringify,
|
|
128
277
|
transform: () => transform
|
|
129
278
|
});
|
|
279
|
+
var WHITESPACE_TEST_REGEX = /\s/;
|
|
280
|
+
var WHITESPACE_REGEX = /^\s+/;
|
|
281
|
+
var OBJECT_START_REGEX = /^\{/;
|
|
282
|
+
var OBJECT_END_REGEX = /^\}/;
|
|
283
|
+
var ARRAY_START_REGEX = /^\[/;
|
|
284
|
+
var ARRAY_END_REGEX = /^\]/;
|
|
285
|
+
var COMMA_REGEX = /^,/;
|
|
286
|
+
var COLON_REGEX = /^:/;
|
|
287
|
+
var KEYWORD_REGEX = /^(?:true|false|null)/;
|
|
288
|
+
var NUMBER_REGEX = /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/;
|
|
289
|
+
var STRING_DOUBLE_REGEX = /^"(?:[^"\\]|\\["bnrtf\\/]|\\u[0-9a-fA-F]{4})*"/;
|
|
290
|
+
var STRING_SINGLE_REGEX = /^'((?:[^'\\]|\\['bnrtf\\/]|\\u[0-9a-fA-F]{4})*)'/;
|
|
291
|
+
var COMMENT_SINGLE_REGEX = /^\/\/.*?(?:\r\n|\r|\n)/;
|
|
292
|
+
var COMMENT_MULTI_REGEX = /^\/\*[\s\S]*?\*\//;
|
|
293
|
+
var IDENTIFIER_REGEX = /^[$a-zA-Z0-9_\-+.*?!|&%^/#\\]+/;
|
|
130
294
|
function some(array, f) {
|
|
131
295
|
let acc = false;
|
|
132
|
-
for (let i = 0; i < array.length; i
|
|
296
|
+
for (let i = 0; i < array.length; i += 1) {
|
|
133
297
|
const result = f(array[i], i, array);
|
|
134
298
|
acc = result === void 0 ? false : result;
|
|
135
299
|
if (acc) {
|
|
@@ -139,31 +303,31 @@ function some(array, f) {
|
|
|
139
303
|
return acc;
|
|
140
304
|
}
|
|
141
305
|
function makeLexer(tokenSpecs) {
|
|
142
|
-
return
|
|
306
|
+
return (contents) => {
|
|
143
307
|
const tokens = [];
|
|
144
308
|
let line = 1;
|
|
309
|
+
let remainingContents = contents;
|
|
145
310
|
function findToken() {
|
|
146
311
|
const result = some(tokenSpecs, (tokenSpec) => {
|
|
147
|
-
const m = tokenSpec.re.exec(
|
|
312
|
+
const m = tokenSpec.re.exec(remainingContents);
|
|
148
313
|
if (m) {
|
|
149
314
|
const raw = m[0];
|
|
150
|
-
|
|
315
|
+
remainingContents = remainingContents.slice(raw.length);
|
|
151
316
|
return {
|
|
152
317
|
raw,
|
|
153
318
|
matched: tokenSpec.f(m)
|
|
154
319
|
// Process the match using the spec's function
|
|
155
320
|
};
|
|
156
|
-
} else {
|
|
157
|
-
return void 0;
|
|
158
321
|
}
|
|
322
|
+
return;
|
|
159
323
|
});
|
|
160
324
|
return result === false ? void 0 : result;
|
|
161
325
|
}
|
|
162
|
-
while (
|
|
326
|
+
while (remainingContents !== "") {
|
|
163
327
|
const matched = findToken();
|
|
164
328
|
if (!matched) {
|
|
165
329
|
const err = new SyntaxError(
|
|
166
|
-
`Unexpected character: ${
|
|
330
|
+
`Unexpected character: ${remainingContents[0]}; input: ${remainingContents.substr(
|
|
167
331
|
0,
|
|
168
332
|
100
|
|
169
333
|
)}`
|
|
@@ -185,11 +349,11 @@ function fStringSingle(m) {
|
|
|
185
349
|
(mm) => {
|
|
186
350
|
if (mm === '"') {
|
|
187
351
|
return '\\"';
|
|
188
|
-
}
|
|
352
|
+
}
|
|
353
|
+
if (mm === "\\'") {
|
|
189
354
|
return "'";
|
|
190
|
-
} else {
|
|
191
|
-
return mm;
|
|
192
355
|
}
|
|
356
|
+
return mm;
|
|
193
357
|
}
|
|
194
358
|
);
|
|
195
359
|
const match = `"${content}"`;
|
|
@@ -224,7 +388,10 @@ function fIdentifier(m) {
|
|
|
224
388
|
};
|
|
225
389
|
}
|
|
226
390
|
function fComment(m) {
|
|
227
|
-
const match = m[0].replace(
|
|
391
|
+
const match = m[0].replace(
|
|
392
|
+
/./g,
|
|
393
|
+
(c) => WHITESPACE_TEST_REGEX.test(c) ? c : " "
|
|
394
|
+
);
|
|
228
395
|
return {
|
|
229
396
|
type: " ",
|
|
230
397
|
// Represent comments as whitespace tokens
|
|
@@ -239,7 +406,7 @@ function fNumber(m) {
|
|
|
239
406
|
type: "number",
|
|
240
407
|
match: m[0],
|
|
241
408
|
// The raw matched number string
|
|
242
|
-
value: parseFloat(m[0])
|
|
409
|
+
value: Number.parseFloat(m[0])
|
|
243
410
|
// Convert string to number
|
|
244
411
|
};
|
|
245
412
|
}
|
|
@@ -269,46 +436,46 @@ function fKeyword(m) {
|
|
|
269
436
|
}
|
|
270
437
|
function makeTokenSpecs(relaxed) {
|
|
271
438
|
function f(type) {
|
|
272
|
-
return
|
|
439
|
+
return (m) => {
|
|
273
440
|
return { type, match: m[0], value: void 0 };
|
|
274
441
|
};
|
|
275
442
|
}
|
|
276
443
|
let tokenSpecs = [
|
|
277
|
-
{ re:
|
|
444
|
+
{ re: WHITESPACE_REGEX, f: f(" ") },
|
|
278
445
|
// Whitespace
|
|
279
|
-
{ re:
|
|
446
|
+
{ re: OBJECT_START_REGEX, f: f("{") },
|
|
280
447
|
// Object start
|
|
281
|
-
{ re:
|
|
448
|
+
{ re: OBJECT_END_REGEX, f: f("}") },
|
|
282
449
|
// Object end
|
|
283
|
-
{ re:
|
|
450
|
+
{ re: ARRAY_START_REGEX, f: f("[") },
|
|
284
451
|
// Array start
|
|
285
|
-
{ re:
|
|
452
|
+
{ re: ARRAY_END_REGEX, f: f("]") },
|
|
286
453
|
// Array end
|
|
287
|
-
{ re:
|
|
454
|
+
{ re: COMMA_REGEX, f: f(",") },
|
|
288
455
|
// Comma separator
|
|
289
|
-
{ re:
|
|
456
|
+
{ re: COLON_REGEX, f: f(":") },
|
|
290
457
|
// Key-value separator
|
|
291
|
-
{ re:
|
|
458
|
+
{ re: KEYWORD_REGEX, f: fKeyword },
|
|
292
459
|
// Keywords
|
|
293
460
|
// Number: optional sign, digits, optional decimal part, optional exponent
|
|
294
|
-
{ re:
|
|
461
|
+
{ re: NUMBER_REGEX, f: fNumber },
|
|
295
462
|
// String: double-quoted, handles escapes
|
|
296
|
-
{ re:
|
|
463
|
+
{ re: STRING_DOUBLE_REGEX, f: fStringDouble }
|
|
297
464
|
];
|
|
298
465
|
if (relaxed) {
|
|
299
466
|
tokenSpecs = tokenSpecs.concat([
|
|
300
467
|
// Single-quoted strings
|
|
301
468
|
{
|
|
302
|
-
re:
|
|
469
|
+
re: STRING_SINGLE_REGEX,
|
|
303
470
|
f: fStringSingle
|
|
304
471
|
},
|
|
305
472
|
// Single-line comments (// ...)
|
|
306
|
-
{ re:
|
|
473
|
+
{ re: COMMENT_SINGLE_REGEX, f: fComment },
|
|
307
474
|
// Multi-line comments (/* ... */)
|
|
308
|
-
{ re:
|
|
475
|
+
{ re: COMMENT_MULTI_REGEX, f: fComment },
|
|
309
476
|
// Unquoted identifiers (treated as strings)
|
|
310
477
|
// Allows letters, numbers, _, -, +, ., *, ?, !, |, &, %, ^, /, #, \
|
|
311
|
-
{ re:
|
|
478
|
+
{ re: IDENTIFIER_REGEX, f: fIdentifier }
|
|
312
479
|
// Note: The order matters here. Identifiers are checked after keywords/numbers.
|
|
313
480
|
]);
|
|
314
481
|
}
|
|
@@ -317,12 +484,13 @@ function makeTokenSpecs(relaxed) {
|
|
|
317
484
|
var lexer = makeLexer(makeTokenSpecs(true));
|
|
318
485
|
var strictLexer = makeLexer(makeTokenSpecs(false));
|
|
319
486
|
function previousNWSToken(tokens, index) {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
487
|
+
let currentIndex = index;
|
|
488
|
+
for (; currentIndex >= 0; currentIndex -= 1) {
|
|
489
|
+
if (tokens[currentIndex].type !== " ") {
|
|
490
|
+
return currentIndex;
|
|
323
491
|
}
|
|
324
492
|
}
|
|
325
|
-
return
|
|
493
|
+
return;
|
|
326
494
|
}
|
|
327
495
|
function stripTrailingComma(tokens) {
|
|
328
496
|
const res = [];
|
|
@@ -351,15 +519,14 @@ function stripTrailingComma(tokens) {
|
|
|
351
519
|
function transform(text) {
|
|
352
520
|
let tokens = lexer(text);
|
|
353
521
|
tokens = stripTrailingComma(tokens);
|
|
354
|
-
return tokens.reduce((str, token) =>
|
|
355
|
-
return str + token.match;
|
|
356
|
-
}, "");
|
|
522
|
+
return tokens.reduce((str, token) => str + token.match, "");
|
|
357
523
|
}
|
|
358
524
|
function popToken(tokens, state) {
|
|
525
|
+
var _a, _b;
|
|
359
526
|
const token = tokens[state.pos];
|
|
360
527
|
state.pos += 1;
|
|
361
528
|
if (!token) {
|
|
362
|
-
const lastLine = tokens.length !== 0 ? tokens
|
|
529
|
+
const lastLine = tokens.length !== 0 ? (_b = (_a = tokens.at(-1)) == null ? void 0 : _a.line) != null ? _b : 1 : 1;
|
|
363
530
|
return { type: "eof", match: "", value: void 0, line: lastLine };
|
|
364
531
|
}
|
|
365
532
|
return token;
|
|
@@ -397,11 +564,13 @@ function skipPunctuation(tokens, state, valid) {
|
|
|
397
564
|
const punctuation = [",", ":", "]", "}"];
|
|
398
565
|
let token = popToken(tokens, state);
|
|
399
566
|
while (true) {
|
|
400
|
-
if (valid
|
|
567
|
+
if (valid == null ? void 0 : valid.includes(token.type)) {
|
|
401
568
|
return token;
|
|
402
|
-
}
|
|
569
|
+
}
|
|
570
|
+
if (token.type === "eof") {
|
|
403
571
|
return token;
|
|
404
|
-
}
|
|
572
|
+
}
|
|
573
|
+
if (punctuation.includes(token.type)) {
|
|
405
574
|
const message = `Unexpected token: ${strToken(
|
|
406
575
|
token
|
|
407
576
|
)}, expected '[', '{', number, string or atom`;
|
|
@@ -442,7 +611,7 @@ function raiseUnexpected(state, token, expected) {
|
|
|
442
611
|
}
|
|
443
612
|
function checkDuplicates(state, obj, token) {
|
|
444
613
|
const key = String(token.value);
|
|
445
|
-
if (!state.duplicate && Object.
|
|
614
|
+
if (!state.duplicate && Object.hasOwn(obj, key)) {
|
|
446
615
|
raiseError(state, token, `Duplicate key: ${key}`);
|
|
447
616
|
}
|
|
448
617
|
}
|
|
@@ -539,51 +708,84 @@ function parseArray(tokens, state) {
|
|
|
539
708
|
// The closing token for an array
|
|
540
709
|
});
|
|
541
710
|
}
|
|
542
|
-
function
|
|
543
|
-
|
|
544
|
-
if (
|
|
545
|
-
|
|
546
|
-
if (state.tolerant) {
|
|
547
|
-
return result;
|
|
548
|
-
} else {
|
|
711
|
+
function handleInvalidToken(token, state, opts, result) {
|
|
712
|
+
raiseUnexpected(state, token, `',' or '${opts.endSymbol}'`);
|
|
713
|
+
if (state.tolerant) {
|
|
714
|
+
if (token.type === "eof") {
|
|
549
715
|
return result;
|
|
550
716
|
}
|
|
717
|
+
state.pos -= 1;
|
|
718
|
+
return null;
|
|
719
|
+
}
|
|
720
|
+
return result;
|
|
721
|
+
}
|
|
722
|
+
function handleCommaToken(params) {
|
|
723
|
+
const { token, tokens, state, opts, result } = params;
|
|
724
|
+
const nextToken = tokens[state.pos];
|
|
725
|
+
if (state.tolerant && nextToken && nextToken.type === opts.endSymbol) {
|
|
726
|
+
raiseError(state, token, `Trailing comma before '${opts.endSymbol}'`);
|
|
727
|
+
popToken(tokens, state);
|
|
728
|
+
return result;
|
|
729
|
+
}
|
|
730
|
+
opts.elementParser(tokens, state, result);
|
|
731
|
+
return null;
|
|
732
|
+
}
|
|
733
|
+
function parseManyInitialElement(tokens, state, result, opts) {
|
|
734
|
+
const token = skipPunctuation(tokens, state, opts.skip);
|
|
735
|
+
if (token.type === "eof") {
|
|
736
|
+
raiseUnexpected(state, token, `'${opts.endSymbol}' or ${opts.elementName}`);
|
|
737
|
+
return result;
|
|
551
738
|
}
|
|
552
739
|
if (token.type === opts.endSymbol) {
|
|
553
740
|
return result;
|
|
554
741
|
}
|
|
555
742
|
state.pos -= 1;
|
|
556
743
|
opts.elementParser(tokens, state, result);
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
state.pos -= 1;
|
|
566
|
-
} else {
|
|
567
|
-
return result;
|
|
568
|
-
}
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
function parseManyProcessToken(params) {
|
|
747
|
+
const { token, tokens, state, opts, result } = params;
|
|
748
|
+
if (token.type !== opts.endSymbol && token.type !== ",") {
|
|
749
|
+
const handledResult = handleInvalidToken(token, state, opts, result);
|
|
750
|
+
if (handledResult !== null) {
|
|
751
|
+
return handledResult;
|
|
569
752
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
753
|
+
}
|
|
754
|
+
if (token.type === opts.endSymbol) {
|
|
755
|
+
return result;
|
|
756
|
+
}
|
|
757
|
+
if (token.type === ",") {
|
|
758
|
+
const handledResult = handleCommaToken({
|
|
759
|
+
token,
|
|
760
|
+
tokens,
|
|
761
|
+
state,
|
|
762
|
+
opts,
|
|
763
|
+
result
|
|
764
|
+
});
|
|
765
|
+
if (handledResult !== null) {
|
|
766
|
+
return handledResult;
|
|
767
|
+
}
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
opts.elementParser(tokens, state, result);
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
function parseMany(tokens, state, result, opts) {
|
|
774
|
+
const initialResult = parseManyInitialElement(tokens, state, result, opts);
|
|
775
|
+
if (initialResult !== void 0) {
|
|
776
|
+
return initialResult;
|
|
777
|
+
}
|
|
778
|
+
while (true) {
|
|
779
|
+
const token = popToken(tokens, state);
|
|
780
|
+
const processedResult = parseManyProcessToken({
|
|
781
|
+
token,
|
|
782
|
+
tokens,
|
|
783
|
+
state,
|
|
784
|
+
opts,
|
|
785
|
+
result
|
|
786
|
+
});
|
|
787
|
+
if (processedResult !== void 0) {
|
|
788
|
+
return processedResult;
|
|
587
789
|
}
|
|
588
790
|
}
|
|
589
791
|
}
|
|
@@ -617,7 +819,7 @@ function parseAny(tokens, state, end = false) {
|
|
|
617
819
|
raiseUnexpected(state, token, "json value");
|
|
618
820
|
}
|
|
619
821
|
raiseUnexpected(state, token, "json value");
|
|
620
|
-
return
|
|
822
|
+
return;
|
|
621
823
|
}
|
|
622
824
|
switch (token.type) {
|
|
623
825
|
case "{":
|
|
@@ -638,7 +840,7 @@ function parseAny(tokens, state, end = false) {
|
|
|
638
840
|
if (state.tolerant) {
|
|
639
841
|
ret = null;
|
|
640
842
|
} else {
|
|
641
|
-
return
|
|
843
|
+
return;
|
|
642
844
|
}
|
|
643
845
|
}
|
|
644
846
|
if (end) {
|
|
@@ -647,7 +849,7 @@ function parseAny(tokens, state, end = false) {
|
|
|
647
849
|
}
|
|
648
850
|
return ret;
|
|
649
851
|
}
|
|
650
|
-
function
|
|
852
|
+
function normalizeParseOptions(optsOrReviver) {
|
|
651
853
|
var _a;
|
|
652
854
|
let options = {};
|
|
653
855
|
if (typeof optsOrReviver === "function") {
|
|
@@ -668,69 +870,54 @@ function parse(text, optsOrReviver) {
|
|
|
668
870
|
options.relaxed = true;
|
|
669
871
|
}
|
|
670
872
|
}
|
|
671
|
-
options.tolerant = options.tolerant || options.warnings
|
|
672
|
-
options.warnings = options.warnings || false;
|
|
873
|
+
options.tolerant = options.tolerant || options.warnings;
|
|
673
874
|
options.duplicate = (_a = options.duplicate) != null ? _a : false;
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
875
|
+
return options;
|
|
876
|
+
}
|
|
877
|
+
function createParseState(options) {
|
|
878
|
+
var _a, _b;
|
|
879
|
+
return {
|
|
880
|
+
pos: 0,
|
|
881
|
+
reviver: options.reviver,
|
|
882
|
+
tolerant: (_a = options.tolerant) != null ? _a : false,
|
|
883
|
+
duplicate: (_b = options.duplicate) != null ? _b : false,
|
|
884
|
+
warnings: []
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
function parseWithCustomParser(text, options) {
|
|
683
888
|
const lexerToUse = options.relaxed ? lexer : strictLexer;
|
|
684
889
|
let tokens = lexerToUse(text);
|
|
685
890
|
if (options.relaxed) {
|
|
686
891
|
tokens = stripTrailingComma(tokens);
|
|
687
892
|
}
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
const state = {
|
|
712
|
-
pos: 0,
|
|
713
|
-
reviver: options.reviver,
|
|
714
|
-
tolerant: options.tolerant || false,
|
|
715
|
-
// Ensure boolean
|
|
716
|
-
duplicate: options.duplicate,
|
|
717
|
-
// true = allow duplicate keys, false = reject duplicates
|
|
718
|
-
warnings: []
|
|
719
|
-
};
|
|
720
|
-
return parseAny(tokens, state, true);
|
|
721
|
-
} else {
|
|
722
|
-
tokens = lexer(text);
|
|
723
|
-
tokens = stripTrailingComma(tokens);
|
|
724
|
-
const newtext = tokens.reduce((str, token) => str + token.match, "");
|
|
725
|
-
return JSON.parse(
|
|
726
|
-
newtext,
|
|
727
|
-
options.reviver
|
|
728
|
-
);
|
|
729
|
-
}
|
|
893
|
+
tokens = tokens.filter((token) => token.type !== " ");
|
|
894
|
+
const state = createParseState(options);
|
|
895
|
+
return parseAny(tokens, state, true);
|
|
896
|
+
}
|
|
897
|
+
function parseWithTransform(text, options) {
|
|
898
|
+
let tokens = lexer(text);
|
|
899
|
+
tokens = stripTrailingComma(tokens);
|
|
900
|
+
const newtext = tokens.reduce((str, token) => str + token.match, "");
|
|
901
|
+
return JSON.parse(
|
|
902
|
+
newtext,
|
|
903
|
+
options.reviver
|
|
904
|
+
);
|
|
905
|
+
}
|
|
906
|
+
function parse(text, optsOrReviver) {
|
|
907
|
+
const options = normalizeParseOptions(optsOrReviver);
|
|
908
|
+
if (!(options.relaxed || options.warnings || options.tolerant) && options.duplicate) {
|
|
909
|
+
return JSON.parse(
|
|
910
|
+
text,
|
|
911
|
+
options.reviver
|
|
912
|
+
);
|
|
913
|
+
}
|
|
914
|
+
if (options.warnings || options.tolerant || !options.duplicate) {
|
|
915
|
+
return parseWithCustomParser(text, options);
|
|
730
916
|
}
|
|
917
|
+
return parseWithTransform(text, options);
|
|
731
918
|
}
|
|
732
919
|
function stringifyPair(obj, key) {
|
|
733
|
-
return JSON.stringify(key)
|
|
920
|
+
return `${JSON.stringify(key)}:${stringify(obj[key])}`;
|
|
734
921
|
}
|
|
735
922
|
function stringify(obj) {
|
|
736
923
|
const type = typeof obj;
|
|
@@ -742,144 +929,203 @@ function stringify(obj) {
|
|
|
742
929
|
}
|
|
743
930
|
if (Array.isArray(obj)) {
|
|
744
931
|
const elements = obj.map(stringify).join(",");
|
|
745
|
-
return
|
|
932
|
+
return `[${elements}]`;
|
|
746
933
|
}
|
|
747
934
|
if (type === "object") {
|
|
748
935
|
const keys = Object.keys(obj);
|
|
749
936
|
keys.sort();
|
|
750
937
|
const pairs = keys.map((key) => stringifyPair(obj, key)).join(",");
|
|
751
|
-
return
|
|
938
|
+
return `{${pairs}}`;
|
|
752
939
|
}
|
|
753
940
|
return "null";
|
|
754
941
|
}
|
|
755
942
|
|
|
756
|
-
// src/utils/
|
|
757
|
-
function
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
943
|
+
// src/utils/type-guards.ts
|
|
944
|
+
function isToolCallContent(content) {
|
|
945
|
+
return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
|
|
946
|
+
(typeof content.input === "string" || typeof content.input === "object");
|
|
947
|
+
}
|
|
948
|
+
function hasInputProperty(obj) {
|
|
949
|
+
return typeof obj === "object" && obj !== null && "input" in obj;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
// src/protocols/json-mix-protocol.ts
|
|
953
|
+
function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
|
|
954
|
+
var _a;
|
|
955
|
+
try {
|
|
956
|
+
const parsedToolCall = parse(toolCallJson);
|
|
957
|
+
processedElements.push({
|
|
958
|
+
type: "tool-call",
|
|
959
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
960
|
+
toolName: parsedToolCall.name,
|
|
961
|
+
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
962
|
+
});
|
|
963
|
+
} catch (error) {
|
|
964
|
+
if (options == null ? void 0 : options.onError) {
|
|
965
|
+
options.onError(
|
|
966
|
+
"Could not process JSON tool call, keeping original text.",
|
|
967
|
+
{ toolCall: fullMatch, error }
|
|
968
|
+
);
|
|
969
|
+
}
|
|
970
|
+
processedElements.push({ type: "text", text: fullMatch });
|
|
761
971
|
}
|
|
762
|
-
|
|
763
|
-
|
|
972
|
+
}
|
|
973
|
+
function addTextSegment(text, processedElements) {
|
|
974
|
+
if (text.trim()) {
|
|
975
|
+
processedElements.push({ type: "text", text });
|
|
764
976
|
}
|
|
765
|
-
return void 0;
|
|
766
977
|
}
|
|
767
|
-
function
|
|
768
|
-
const
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
|
|
978
|
+
function processMatchedToolCall(context) {
|
|
979
|
+
const { match, text, currentIndex, processedElements, options } = context;
|
|
980
|
+
const startIndex = match.index;
|
|
981
|
+
const toolCallJson = match[1];
|
|
982
|
+
if (startIndex > currentIndex) {
|
|
983
|
+
const textSegment = text.substring(currentIndex, startIndex);
|
|
984
|
+
addTextSegment(textSegment, processedElements);
|
|
985
|
+
}
|
|
986
|
+
if (toolCallJson) {
|
|
987
|
+
processToolCallJson(toolCallJson, match[0], processedElements, options);
|
|
988
|
+
}
|
|
989
|
+
return startIndex + match[0].length;
|
|
990
|
+
}
|
|
991
|
+
function flushBuffer(state, controller, toolCallStart) {
|
|
992
|
+
if (state.buffer.length === 0) {
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
if (!state.currentTextId) {
|
|
996
|
+
state.currentTextId = (0, import_provider_utils2.generateId)();
|
|
997
|
+
controller.enqueue({ type: "text-start", id: state.currentTextId });
|
|
998
|
+
state.hasEmittedTextStart = true;
|
|
999
|
+
}
|
|
1000
|
+
const delta = state.isInsideToolCall ? `${toolCallStart}${state.buffer}` : state.buffer;
|
|
1001
|
+
controller.enqueue({
|
|
1002
|
+
type: "text-delta",
|
|
1003
|
+
id: state.currentTextId,
|
|
1004
|
+
delta
|
|
1005
|
+
});
|
|
1006
|
+
state.buffer = "";
|
|
1007
|
+
}
|
|
1008
|
+
function closeTextBlock(state, controller) {
|
|
1009
|
+
if (state.currentTextId && state.hasEmittedTextStart) {
|
|
1010
|
+
controller.enqueue({ type: "text-end", id: state.currentTextId });
|
|
1011
|
+
state.currentTextId = null;
|
|
1012
|
+
state.hasEmittedTextStart = false;
|
|
772
1013
|
}
|
|
773
|
-
const boolEnv = normalizeBooleanString(envLower);
|
|
774
|
-
if (boolEnv === true) return "stream";
|
|
775
|
-
if (envLower === "2") return "parse";
|
|
776
|
-
return "off";
|
|
777
1014
|
}
|
|
778
|
-
function
|
|
779
|
-
|
|
1015
|
+
function emitIncompleteToolCall(state, controller, toolCallStart) {
|
|
1016
|
+
if (!state.currentToolCallJson) {
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
const errorId = (0, import_provider_utils2.generateId)();
|
|
1020
|
+
controller.enqueue({ type: "text-start", id: errorId });
|
|
1021
|
+
controller.enqueue({
|
|
1022
|
+
type: "text-delta",
|
|
1023
|
+
id: errorId,
|
|
1024
|
+
delta: `${toolCallStart}${state.currentToolCallJson}`
|
|
1025
|
+
});
|
|
1026
|
+
controller.enqueue({ type: "text-end", id: errorId });
|
|
1027
|
+
state.currentToolCallJson = "";
|
|
780
1028
|
}
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
var cBgBlue = color(44);
|
|
785
|
-
var cBgGreen = color(42);
|
|
786
|
-
var cInverse = color(7);
|
|
787
|
-
var cUnderline = color(4);
|
|
788
|
-
var cBold = color(1);
|
|
789
|
-
function safeStringify(value) {
|
|
790
|
-
try {
|
|
791
|
-
return `
|
|
792
|
-
${typeof value === "string" ? value : JSON.stringify(value, null, 2)}`;
|
|
793
|
-
} catch (e) {
|
|
794
|
-
return String(value);
|
|
1029
|
+
function handleFinishChunk(state, controller, toolCallStart, chunk) {
|
|
1030
|
+
if (state.buffer.length > 0) {
|
|
1031
|
+
flushBuffer(state, controller, toolCallStart);
|
|
795
1032
|
}
|
|
1033
|
+
closeTextBlock(state, controller);
|
|
1034
|
+
emitIncompleteToolCall(state, controller, toolCallStart);
|
|
1035
|
+
controller.enqueue(chunk);
|
|
796
1036
|
}
|
|
797
|
-
function
|
|
798
|
-
|
|
1037
|
+
function publishText(text, state, controller) {
|
|
1038
|
+
if (state.isInsideToolCall) {
|
|
1039
|
+
closeTextBlock(state, controller);
|
|
1040
|
+
state.currentToolCallJson += text;
|
|
1041
|
+
} else if (text.length > 0) {
|
|
1042
|
+
if (!state.currentTextId) {
|
|
1043
|
+
state.currentTextId = (0, import_provider_utils2.generateId)();
|
|
1044
|
+
controller.enqueue({ type: "text-start", id: state.currentTextId });
|
|
1045
|
+
state.hasEmittedTextStart = true;
|
|
1046
|
+
}
|
|
1047
|
+
controller.enqueue({
|
|
1048
|
+
type: "text-delta",
|
|
1049
|
+
id: state.currentTextId,
|
|
1050
|
+
delta: text
|
|
1051
|
+
});
|
|
1052
|
+
}
|
|
799
1053
|
}
|
|
800
|
-
function
|
|
801
|
-
|
|
1054
|
+
function emitToolCall(context) {
|
|
1055
|
+
var _a;
|
|
1056
|
+
const { state, controller, toolCallStart, toolCallEnd, options } = context;
|
|
1057
|
+
try {
|
|
1058
|
+
const parsedToolCall = robust_json_exports.parse(state.currentToolCallJson);
|
|
1059
|
+
closeTextBlock(state, controller);
|
|
1060
|
+
controller.enqueue({
|
|
1061
|
+
type: "tool-call",
|
|
1062
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1063
|
+
toolName: parsedToolCall.name,
|
|
1064
|
+
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1065
|
+
});
|
|
1066
|
+
} catch (e) {
|
|
1067
|
+
const errorId = (0, import_provider_utils2.generateId)();
|
|
1068
|
+
controller.enqueue({ type: "text-start", id: errorId });
|
|
1069
|
+
controller.enqueue({
|
|
1070
|
+
type: "text-delta",
|
|
1071
|
+
id: errorId,
|
|
1072
|
+
delta: `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`
|
|
1073
|
+
});
|
|
1074
|
+
controller.enqueue({ type: "text-end", id: errorId });
|
|
1075
|
+
if (options == null ? void 0 : options.onError) {
|
|
1076
|
+
options.onError(
|
|
1077
|
+
"Could not process streaming JSON tool call; emitting original text.",
|
|
1078
|
+
{
|
|
1079
|
+
toolCall: `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`
|
|
1080
|
+
}
|
|
1081
|
+
);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
802
1084
|
}
|
|
803
|
-
function
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
return "inverse";
|
|
813
|
-
if (normalized === "underline" || normalized === "ul")
|
|
814
|
-
return "underline";
|
|
815
|
-
if (normalized === "bold") return "bold";
|
|
816
|
-
if (normalized === "bg" || normalized === "background")
|
|
817
|
-
return "bg";
|
|
818
|
-
const asBool = normalizeBooleanString(normalized);
|
|
819
|
-
if (asBool === true) return "bg";
|
|
820
|
-
return "bg";
|
|
821
|
-
})();
|
|
822
|
-
const highlight = style === "inverse" ? cInverse : style === "underline" ? cUnderline : style === "bold" ? cBold : style === "bg" ? cBgGreen : cYellow;
|
|
823
|
-
const rendered = style === "bg" || style === "inverse" || style === "underline" || style === "bold" ? originalText.split(/\r?\n/).map((line) => line.length ? highlight(line) : line).join("\n") : highlight(originalText);
|
|
824
|
-
console.log(cGray("[debug:mw:origin]"), `
|
|
825
|
-
${rendered}`);
|
|
1085
|
+
function processTagMatch(context) {
|
|
1086
|
+
const { state } = context;
|
|
1087
|
+
if (state.isInsideToolCall) {
|
|
1088
|
+
emitToolCall(context);
|
|
1089
|
+
state.currentToolCallJson = "";
|
|
1090
|
+
state.isInsideToolCall = false;
|
|
1091
|
+
} else {
|
|
1092
|
+
state.currentToolCallJson = "";
|
|
1093
|
+
state.isInsideToolCall = true;
|
|
826
1094
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
1095
|
+
}
|
|
1096
|
+
function processBufferTags(context) {
|
|
1097
|
+
const { state, controller, toolCallStart, toolCallEnd } = context;
|
|
1098
|
+
let startIndex = getPotentialStartIndex(
|
|
1099
|
+
state.buffer,
|
|
1100
|
+
state.isInsideToolCall ? toolCallEnd : toolCallStart
|
|
1101
|
+
);
|
|
1102
|
+
while (startIndex != null) {
|
|
1103
|
+
const tag = state.isInsideToolCall ? toolCallEnd : toolCallStart;
|
|
1104
|
+
if (startIndex + tag.length > state.buffer.length) {
|
|
1105
|
+
break;
|
|
1106
|
+
}
|
|
1107
|
+
publishText(state.buffer.slice(0, startIndex), state, controller);
|
|
1108
|
+
state.buffer = state.buffer.slice(startIndex + tag.length);
|
|
1109
|
+
processTagMatch(context);
|
|
1110
|
+
startIndex = getPotentialStartIndex(
|
|
1111
|
+
state.buffer,
|
|
1112
|
+
state.isInsideToolCall ? toolCallEnd : toolCallStart
|
|
1113
|
+
);
|
|
830
1114
|
}
|
|
831
1115
|
}
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
1116
|
+
function handlePartialTag(state, controller, toolCallStart) {
|
|
1117
|
+
if (state.isInsideToolCall) {
|
|
1118
|
+
return;
|
|
1119
|
+
}
|
|
1120
|
+
const potentialIndex = getPotentialStartIndex(state.buffer, toolCallStart);
|
|
1121
|
+
if (potentialIndex != null && potentialIndex + toolCallStart.length > state.buffer.length) {
|
|
1122
|
+
publishText(state.buffer.slice(0, potentialIndex), state, controller);
|
|
1123
|
+
state.buffer = state.buffer.slice(potentialIndex);
|
|
1124
|
+
} else {
|
|
1125
|
+
publishText(state.buffer, state, controller);
|
|
1126
|
+
state.buffer = "";
|
|
839
1127
|
}
|
|
840
|
-
return void 0;
|
|
841
1128
|
}
|
|
842
|
-
|
|
843
|
-
// src/utils/provider-options.ts
|
|
844
|
-
var originalToolsSchema = {
|
|
845
|
-
encode: encodeOriginalTools,
|
|
846
|
-
decode: decodeOriginalTools
|
|
847
|
-
};
|
|
848
|
-
function encodeOriginalTools(tools) {
|
|
849
|
-
return (tools == null ? void 0 : tools.map((t) => ({
|
|
850
|
-
name: t.name,
|
|
851
|
-
inputSchema: JSON.stringify(t.inputSchema)
|
|
852
|
-
}))) || [];
|
|
853
|
-
}
|
|
854
|
-
function decodeOriginalTools(originalTools) {
|
|
855
|
-
const tools = (originalTools == null ? void 0 : originalTools.map(
|
|
856
|
-
(t) => ({
|
|
857
|
-
name: t.name,
|
|
858
|
-
inputSchema: JSON.parse(t.inputSchema)
|
|
859
|
-
})
|
|
860
|
-
)) || [];
|
|
861
|
-
return tools;
|
|
862
|
-
}
|
|
863
|
-
function isToolChoiceActive(params) {
|
|
864
|
-
var _a, _b, _c;
|
|
865
|
-
const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
|
|
866
|
-
return !!(typeof params.providerOptions === "object" && params.providerOptions !== null && typeof ((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) === "object" && toolChoice && typeof toolChoice === "object" && (toolChoice.type === "tool" || toolChoice.type === "required"));
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
// src/utils/type-guards.ts
|
|
870
|
-
function isToolCallContent(content) {
|
|
871
|
-
return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
|
|
872
|
-
(typeof content.input === "string" || typeof content.input === "object");
|
|
873
|
-
}
|
|
874
|
-
function isToolResultPart(content) {
|
|
875
|
-
const c = content;
|
|
876
|
-
return !!c && c.type === "tool-result" && typeof c.toolName === "string" && typeof c.toolCallId === "string" && "output" in c;
|
|
877
|
-
}
|
|
878
|
-
function hasInputProperty(obj) {
|
|
879
|
-
return typeof obj === "object" && obj !== null && "input" in obj;
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
// src/protocols/json-mix-protocol.ts
|
|
883
1129
|
var jsonMixProtocol = ({
|
|
884
1130
|
toolCallStart = "<tool_call>",
|
|
885
1131
|
toolCallEnd = "</tool_call>",
|
|
@@ -913,7 +1159,6 @@ var jsonMixProtocol = ({
|
|
|
913
1159
|
})}${toolResponseEnd}`;
|
|
914
1160
|
},
|
|
915
1161
|
parseGeneratedText({ text, options }) {
|
|
916
|
-
var _a;
|
|
917
1162
|
const startEsc = escapeRegExp(toolCallStart);
|
|
918
1163
|
const endEsc = escapeRegExp(toolCallEnd);
|
|
919
1164
|
const toolCallRegex = new RegExp(
|
|
@@ -922,185 +1167,50 @@ var jsonMixProtocol = ({
|
|
|
922
1167
|
);
|
|
923
1168
|
const processedElements = [];
|
|
924
1169
|
let currentIndex = 0;
|
|
925
|
-
let match;
|
|
926
|
-
while (
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
if (toolCallJson) {
|
|
936
|
-
try {
|
|
937
|
-
const parsedToolCall = robust_json_exports.parse(toolCallJson);
|
|
938
|
-
processedElements.push({
|
|
939
|
-
type: "tool-call",
|
|
940
|
-
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
941
|
-
toolName: parsedToolCall.name,
|
|
942
|
-
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
943
|
-
});
|
|
944
|
-
} catch (error) {
|
|
945
|
-
if (options == null ? void 0 : options.onError) {
|
|
946
|
-
options.onError(
|
|
947
|
-
"Could not process JSON tool call, keeping original text.",
|
|
948
|
-
{ toolCall: match[0], error }
|
|
949
|
-
);
|
|
950
|
-
}
|
|
951
|
-
processedElements.push({ type: "text", text: match[0] });
|
|
952
|
-
}
|
|
953
|
-
}
|
|
954
|
-
currentIndex = startIndex + match[0].length;
|
|
1170
|
+
let match = toolCallRegex.exec(text);
|
|
1171
|
+
while (match !== null) {
|
|
1172
|
+
currentIndex = processMatchedToolCall({
|
|
1173
|
+
match,
|
|
1174
|
+
text,
|
|
1175
|
+
currentIndex,
|
|
1176
|
+
processedElements,
|
|
1177
|
+
options
|
|
1178
|
+
});
|
|
1179
|
+
match = toolCallRegex.exec(text);
|
|
955
1180
|
}
|
|
956
1181
|
if (currentIndex < text.length) {
|
|
957
1182
|
const remainingText = text.substring(currentIndex);
|
|
958
|
-
|
|
959
|
-
processedElements.push({ type: "text", text: remainingText });
|
|
960
|
-
}
|
|
1183
|
+
addTextSegment(remainingText, processedElements);
|
|
961
1184
|
}
|
|
962
1185
|
return processedElements;
|
|
963
1186
|
},
|
|
964
1187
|
createStreamParser({ tools: _tools, options } = { tools: [] }) {
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1188
|
+
const state = {
|
|
1189
|
+
isInsideToolCall: false,
|
|
1190
|
+
buffer: "",
|
|
1191
|
+
currentToolCallJson: "",
|
|
1192
|
+
currentTextId: null,
|
|
1193
|
+
hasEmittedTextStart: false
|
|
1194
|
+
};
|
|
970
1195
|
return new TransformStream({
|
|
971
1196
|
transform(chunk, controller) {
|
|
972
|
-
var _a;
|
|
973
1197
|
if (chunk.type === "finish") {
|
|
974
|
-
|
|
975
|
-
if (!currentTextId) {
|
|
976
|
-
currentTextId = (0, import_provider_utils2.generateId)();
|
|
977
|
-
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
978
|
-
hasEmittedTextStart = true;
|
|
979
|
-
}
|
|
980
|
-
controller.enqueue({
|
|
981
|
-
type: "text-delta",
|
|
982
|
-
id: currentTextId,
|
|
983
|
-
delta: `${toolCallStart}${buffer}`
|
|
984
|
-
});
|
|
985
|
-
buffer = "";
|
|
986
|
-
} else if (!isInsideToolCall && buffer.length > 0) {
|
|
987
|
-
if (!currentTextId) {
|
|
988
|
-
currentTextId = (0, import_provider_utils2.generateId)();
|
|
989
|
-
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
990
|
-
hasEmittedTextStart = true;
|
|
991
|
-
}
|
|
992
|
-
controller.enqueue({
|
|
993
|
-
type: "text-delta",
|
|
994
|
-
id: currentTextId,
|
|
995
|
-
delta: buffer
|
|
996
|
-
});
|
|
997
|
-
buffer = "";
|
|
998
|
-
}
|
|
999
|
-
if (currentTextId && hasEmittedTextStart) {
|
|
1000
|
-
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1001
|
-
currentTextId = null;
|
|
1002
|
-
hasEmittedTextStart = false;
|
|
1003
|
-
}
|
|
1004
|
-
if (currentToolCallJson) {
|
|
1005
|
-
const errorId = (0, import_provider_utils2.generateId)();
|
|
1006
|
-
controller.enqueue({ type: "text-start", id: errorId });
|
|
1007
|
-
controller.enqueue({
|
|
1008
|
-
type: "text-delta",
|
|
1009
|
-
id: errorId,
|
|
1010
|
-
delta: `${toolCallStart}${currentToolCallJson}`
|
|
1011
|
-
});
|
|
1012
|
-
controller.enqueue({ type: "text-end", id: errorId });
|
|
1013
|
-
currentToolCallJson = "";
|
|
1014
|
-
}
|
|
1015
|
-
controller.enqueue(chunk);
|
|
1198
|
+
handleFinishChunk(state, controller, toolCallStart, chunk);
|
|
1016
1199
|
return;
|
|
1017
1200
|
}
|
|
1018
1201
|
if (chunk.type !== "text-delta") {
|
|
1019
1202
|
controller.enqueue(chunk);
|
|
1020
1203
|
return;
|
|
1021
1204
|
}
|
|
1022
|
-
buffer += chunk.delta;
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
} else if (text.length > 0) {
|
|
1032
|
-
if (!currentTextId) {
|
|
1033
|
-
currentTextId = (0, import_provider_utils2.generateId)();
|
|
1034
|
-
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
1035
|
-
hasEmittedTextStart = true;
|
|
1036
|
-
}
|
|
1037
|
-
controller.enqueue({
|
|
1038
|
-
type: "text-delta",
|
|
1039
|
-
id: currentTextId,
|
|
1040
|
-
delta: text
|
|
1041
|
-
});
|
|
1042
|
-
}
|
|
1043
|
-
};
|
|
1044
|
-
let startIndex;
|
|
1045
|
-
while ((startIndex = getPotentialStartIndex(
|
|
1046
|
-
buffer,
|
|
1047
|
-
isInsideToolCall ? toolCallEnd : toolCallStart
|
|
1048
|
-
)) != null) {
|
|
1049
|
-
const tag = isInsideToolCall ? toolCallEnd : toolCallStart;
|
|
1050
|
-
if (startIndex + tag.length > buffer.length) {
|
|
1051
|
-
break;
|
|
1052
|
-
}
|
|
1053
|
-
publish(buffer.slice(0, startIndex));
|
|
1054
|
-
buffer = buffer.slice(startIndex + tag.length);
|
|
1055
|
-
if (!isInsideToolCall) {
|
|
1056
|
-
currentToolCallJson = "";
|
|
1057
|
-
isInsideToolCall = true;
|
|
1058
|
-
} else {
|
|
1059
|
-
try {
|
|
1060
|
-
const parsedToolCall = robust_json_exports.parse(currentToolCallJson);
|
|
1061
|
-
if (currentTextId && hasEmittedTextStart) {
|
|
1062
|
-
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1063
|
-
currentTextId = null;
|
|
1064
|
-
hasEmittedTextStart = false;
|
|
1065
|
-
}
|
|
1066
|
-
controller.enqueue({
|
|
1067
|
-
type: "tool-call",
|
|
1068
|
-
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1069
|
-
toolName: parsedToolCall.name,
|
|
1070
|
-
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1071
|
-
});
|
|
1072
|
-
} catch (e) {
|
|
1073
|
-
const errorId = (0, import_provider_utils2.generateId)();
|
|
1074
|
-
controller.enqueue({ type: "text-start", id: errorId });
|
|
1075
|
-
controller.enqueue({
|
|
1076
|
-
type: "text-delta",
|
|
1077
|
-
id: errorId,
|
|
1078
|
-
delta: `${toolCallStart}${currentToolCallJson}${toolCallEnd}`
|
|
1079
|
-
});
|
|
1080
|
-
controller.enqueue({ type: "text-end", id: errorId });
|
|
1081
|
-
if (options == null ? void 0 : options.onError) {
|
|
1082
|
-
options.onError(
|
|
1083
|
-
"Could not process streaming JSON tool call; emitting original text.",
|
|
1084
|
-
{
|
|
1085
|
-
toolCall: `${toolCallStart}${currentToolCallJson}${toolCallEnd}`
|
|
1086
|
-
}
|
|
1087
|
-
);
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
currentToolCallJson = "";
|
|
1091
|
-
isInsideToolCall = false;
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
if (!isInsideToolCall) {
|
|
1095
|
-
const potentialIndex = getPotentialStartIndex(buffer, toolCallStart);
|
|
1096
|
-
if (potentialIndex != null && potentialIndex + toolCallStart.length > buffer.length) {
|
|
1097
|
-
publish(buffer.slice(0, potentialIndex));
|
|
1098
|
-
buffer = buffer.slice(potentialIndex);
|
|
1099
|
-
} else {
|
|
1100
|
-
publish(buffer);
|
|
1101
|
-
buffer = "";
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1205
|
+
state.buffer += chunk.delta;
|
|
1206
|
+
processBufferTags({
|
|
1207
|
+
state,
|
|
1208
|
+
controller,
|
|
1209
|
+
toolCallStart,
|
|
1210
|
+
toolCallEnd,
|
|
1211
|
+
options
|
|
1212
|
+
});
|
|
1213
|
+
handlePartialTag(state, controller, toolCallStart);
|
|
1104
1214
|
}
|
|
1105
1215
|
});
|
|
1106
1216
|
},
|
|
@@ -1109,9 +1219,10 @@ var jsonMixProtocol = ({
|
|
|
1109
1219
|
const endEsc = escapeRegExp(toolCallEnd);
|
|
1110
1220
|
const regex = new RegExp(`${startEsc}([\0-\uFFFF]*?)${endEsc}`, "gs");
|
|
1111
1221
|
const segments = [];
|
|
1112
|
-
let m;
|
|
1113
|
-
while (
|
|
1222
|
+
let m = regex.exec(text);
|
|
1223
|
+
while (m != null) {
|
|
1114
1224
|
segments.push(m[0]);
|
|
1225
|
+
m = regex.exec(text);
|
|
1115
1226
|
}
|
|
1116
1227
|
return segments;
|
|
1117
1228
|
}
|
|
@@ -1119,13 +1230,292 @@ var jsonMixProtocol = ({
|
|
|
1119
1230
|
|
|
1120
1231
|
// src/protocols/morph-xml-protocol.ts
|
|
1121
1232
|
var import_provider_utils3 = require("@ai-sdk/provider-utils");
|
|
1122
|
-
var
|
|
1233
|
+
var import_rxml = require("@ai-sdk-tool/rxml");
|
|
1234
|
+
var WHITESPACE_REGEX2 = /\s/;
|
|
1235
|
+
function processTextBeforeToolCall(text, currentIndex, toolCallStartIndex, processedElements) {
|
|
1236
|
+
if (toolCallStartIndex > currentIndex) {
|
|
1237
|
+
const textSegment = text.substring(currentIndex, toolCallStartIndex);
|
|
1238
|
+
if (textSegment.trim()) {
|
|
1239
|
+
processedElements.push({ type: "text", text: textSegment });
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
return currentIndex;
|
|
1243
|
+
}
|
|
1244
|
+
function processToolCall(params) {
|
|
1245
|
+
var _a;
|
|
1246
|
+
const { toolCall, tools, options, text, processedElements } = params;
|
|
1247
|
+
try {
|
|
1248
|
+
const toolSchema = getToolSchema(tools, toolCall.toolName);
|
|
1249
|
+
const parsed = (0, import_rxml.parse)(toolCall.content, toolSchema, {
|
|
1250
|
+
onError: options == null ? void 0 : options.onError,
|
|
1251
|
+
// Disable HTML self-closing tag behavior to allow base, meta, link etc. as regular tags
|
|
1252
|
+
noChildNodes: []
|
|
1253
|
+
});
|
|
1254
|
+
processedElements.push({
|
|
1255
|
+
type: "tool-call",
|
|
1256
|
+
toolCallId: (0, import_provider_utils3.generateId)(),
|
|
1257
|
+
toolName: toolCall.toolName,
|
|
1258
|
+
input: JSON.stringify(parsed)
|
|
1259
|
+
});
|
|
1260
|
+
} catch (error) {
|
|
1261
|
+
const originalCallText = text.substring(
|
|
1262
|
+
toolCall.startIndex,
|
|
1263
|
+
toolCall.endIndex
|
|
1264
|
+
);
|
|
1265
|
+
const message = `Could not process XML tool call, keeping original text: ${originalCallText}`;
|
|
1266
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
|
|
1267
|
+
toolCall: originalCallText,
|
|
1268
|
+
toolName: toolCall.toolName,
|
|
1269
|
+
error
|
|
1270
|
+
});
|
|
1271
|
+
processedElements.push({ type: "text", text: originalCallText });
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
function addRemainingText(text, currentIndex, processedElements) {
|
|
1275
|
+
if (currentIndex < text.length) {
|
|
1276
|
+
const remainingText = text.substring(currentIndex);
|
|
1277
|
+
if (remainingText.trim()) {
|
|
1278
|
+
processedElements.push({ type: "text", text: remainingText });
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
function handleStreamingToolCallEnd(params) {
|
|
1283
|
+
const { toolContent, currentToolCall, tools, options, ctrl, flushText } = params;
|
|
1284
|
+
try {
|
|
1285
|
+
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
1286
|
+
const parsed = (0, import_rxml.parse)(toolContent, toolSchema, {
|
|
1287
|
+
onError: options == null ? void 0 : options.onError,
|
|
1288
|
+
noChildNodes: []
|
|
1289
|
+
});
|
|
1290
|
+
flushText(ctrl);
|
|
1291
|
+
ctrl.enqueue({
|
|
1292
|
+
type: "tool-call",
|
|
1293
|
+
toolCallId: (0, import_provider_utils3.generateId)(),
|
|
1294
|
+
toolName: currentToolCall.name,
|
|
1295
|
+
input: JSON.stringify(parsed)
|
|
1296
|
+
});
|
|
1297
|
+
} catch (error) {
|
|
1298
|
+
handleStreamingToolCallError({
|
|
1299
|
+
error,
|
|
1300
|
+
currentToolCall,
|
|
1301
|
+
toolContent,
|
|
1302
|
+
options,
|
|
1303
|
+
ctrl,
|
|
1304
|
+
flushText
|
|
1305
|
+
});
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
function handleStreamingToolCallError(params) {
|
|
1309
|
+
var _a;
|
|
1310
|
+
const { error, currentToolCall, toolContent, options, ctrl, flushText } = params;
|
|
1311
|
+
const endTag = `</${currentToolCall.name}>`;
|
|
1312
|
+
const originalCallText = `<${currentToolCall.name}>${toolContent}${endTag}`;
|
|
1313
|
+
let message = "Could not process streaming XML tool call; emitting original text.";
|
|
1314
|
+
if (error instanceof import_rxml.RXMLDuplicateStringTagError) {
|
|
1315
|
+
message = `Duplicate string tags detected in streaming tool call '${currentToolCall.name}'; emitting original text.`;
|
|
1316
|
+
} else if (error instanceof import_rxml.RXMLCoercionError) {
|
|
1317
|
+
message = `Failed to coerce arguments for streaming tool call '${currentToolCall.name}'; emitting original text.`;
|
|
1318
|
+
} else if (error instanceof import_rxml.RXMLParseError) {
|
|
1319
|
+
message = `Failed to parse XML for streaming tool call '${currentToolCall.name}'; emitting original text.`;
|
|
1320
|
+
}
|
|
1321
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
|
|
1322
|
+
toolCall: originalCallText,
|
|
1323
|
+
toolName: currentToolCall.name,
|
|
1324
|
+
error
|
|
1325
|
+
});
|
|
1326
|
+
flushText(ctrl, originalCallText);
|
|
1327
|
+
}
|
|
1328
|
+
function findEarliestToolTag(buffer, toolNames) {
|
|
1329
|
+
let earliestStartTagIndex = -1;
|
|
1330
|
+
let earliestToolName = "";
|
|
1331
|
+
if (toolNames.length > 0) {
|
|
1332
|
+
for (const name of toolNames) {
|
|
1333
|
+
const startTag = `<${name}>`;
|
|
1334
|
+
const index = buffer.indexOf(startTag);
|
|
1335
|
+
if (index !== -1 && (earliestStartTagIndex === -1 || index < earliestStartTagIndex)) {
|
|
1336
|
+
earliestStartTagIndex = index;
|
|
1337
|
+
earliestToolName = name;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
return { index: earliestStartTagIndex, name: earliestToolName };
|
|
1342
|
+
}
|
|
1343
|
+
function handleNoToolTagInBuffer(buffer, maxStartTagLen, controller, flushText) {
|
|
1344
|
+
const tail = Math.max(0, maxStartTagLen - 1);
|
|
1345
|
+
const safeLen = Math.max(0, buffer.length - tail);
|
|
1346
|
+
if (safeLen > 0) {
|
|
1347
|
+
const textToFlush = buffer.slice(0, safeLen);
|
|
1348
|
+
flushText(controller, textToFlush);
|
|
1349
|
+
return { buffer: buffer.slice(safeLen), shouldContinue: true };
|
|
1350
|
+
}
|
|
1351
|
+
return { buffer, shouldContinue: false };
|
|
1352
|
+
}
|
|
1353
|
+
function processToolCallInBuffer(params) {
|
|
1354
|
+
const {
|
|
1355
|
+
buffer,
|
|
1356
|
+
currentToolCall,
|
|
1357
|
+
tools,
|
|
1358
|
+
options,
|
|
1359
|
+
controller,
|
|
1360
|
+
flushText,
|
|
1361
|
+
setBuffer
|
|
1362
|
+
} = params;
|
|
1363
|
+
const endTag = `</${currentToolCall.name}>`;
|
|
1364
|
+
const endTagIndex = buffer.indexOf(endTag);
|
|
1365
|
+
if (endTagIndex !== -1) {
|
|
1366
|
+
const toolContent = buffer.substring(0, endTagIndex);
|
|
1367
|
+
const newBuffer = buffer.substring(endTagIndex + endTag.length);
|
|
1368
|
+
setBuffer("");
|
|
1369
|
+
handleStreamingToolCallEnd({
|
|
1370
|
+
toolContent,
|
|
1371
|
+
currentToolCall,
|
|
1372
|
+
tools,
|
|
1373
|
+
options,
|
|
1374
|
+
ctrl: controller,
|
|
1375
|
+
flushText
|
|
1376
|
+
});
|
|
1377
|
+
setBuffer(newBuffer);
|
|
1378
|
+
return { buffer: newBuffer, currentToolCall: null, shouldBreak: false };
|
|
1379
|
+
}
|
|
1380
|
+
return { buffer, currentToolCall, shouldBreak: true };
|
|
1381
|
+
}
|
|
1382
|
+
function processNoToolCallInBuffer(params) {
|
|
1383
|
+
const { buffer, toolNames, maxStartTagLen, controller, flushText } = params;
|
|
1384
|
+
const { index: earliestStartTagIndex, name: earliestToolName } = findEarliestToolTag(buffer, toolNames);
|
|
1385
|
+
if (earliestStartTagIndex !== -1) {
|
|
1386
|
+
const textBeforeTag = buffer.substring(0, earliestStartTagIndex);
|
|
1387
|
+
flushText(controller, textBeforeTag);
|
|
1388
|
+
const startTag = `<${earliestToolName}>`;
|
|
1389
|
+
const newBuffer = buffer.substring(earliestStartTagIndex + startTag.length);
|
|
1390
|
+
return {
|
|
1391
|
+
buffer: newBuffer,
|
|
1392
|
+
currentToolCall: { name: earliestToolName, content: "" },
|
|
1393
|
+
shouldBreak: false,
|
|
1394
|
+
shouldContinue: false
|
|
1395
|
+
};
|
|
1396
|
+
}
|
|
1397
|
+
const result = handleNoToolTagInBuffer(
|
|
1398
|
+
buffer,
|
|
1399
|
+
maxStartTagLen,
|
|
1400
|
+
controller,
|
|
1401
|
+
flushText
|
|
1402
|
+
);
|
|
1403
|
+
return {
|
|
1404
|
+
buffer: result.buffer,
|
|
1405
|
+
currentToolCall: null,
|
|
1406
|
+
shouldBreak: !result.shouldContinue,
|
|
1407
|
+
shouldContinue: result.shouldContinue
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1410
|
+
function createFlushTextHandler(getBuffer, setBuffer, getCurrentTextId, setCurrentTextId) {
|
|
1411
|
+
return (controller, text) => {
|
|
1412
|
+
const content = text != null ? text : getBuffer();
|
|
1413
|
+
if (content) {
|
|
1414
|
+
const currentTextId2 = getCurrentTextId();
|
|
1415
|
+
if (!currentTextId2) {
|
|
1416
|
+
const newId = (0, import_provider_utils3.generateId)();
|
|
1417
|
+
setCurrentTextId(newId);
|
|
1418
|
+
controller.enqueue({ type: "text-start", id: newId });
|
|
1419
|
+
}
|
|
1420
|
+
controller.enqueue({
|
|
1421
|
+
type: "text-delta",
|
|
1422
|
+
id: getCurrentTextId(),
|
|
1423
|
+
delta: content
|
|
1424
|
+
});
|
|
1425
|
+
if (text === void 0) {
|
|
1426
|
+
setBuffer("");
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
const currentTextId = getCurrentTextId();
|
|
1430
|
+
if (currentTextId && !text) {
|
|
1431
|
+
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1432
|
+
setCurrentTextId(null);
|
|
1433
|
+
}
|
|
1434
|
+
};
|
|
1435
|
+
}
|
|
1436
|
+
function processBufferWithToolCall(params, controller) {
|
|
1437
|
+
const {
|
|
1438
|
+
getBuffer,
|
|
1439
|
+
setBuffer,
|
|
1440
|
+
getCurrentToolCall,
|
|
1441
|
+
setCurrentToolCall,
|
|
1442
|
+
tools,
|
|
1443
|
+
options,
|
|
1444
|
+
flushText
|
|
1445
|
+
} = params;
|
|
1446
|
+
const currentToolCall = getCurrentToolCall();
|
|
1447
|
+
if (!currentToolCall) {
|
|
1448
|
+
return true;
|
|
1449
|
+
}
|
|
1450
|
+
const result = processToolCallInBuffer({
|
|
1451
|
+
buffer: getBuffer(),
|
|
1452
|
+
currentToolCall,
|
|
1453
|
+
tools,
|
|
1454
|
+
options,
|
|
1455
|
+
controller,
|
|
1456
|
+
flushText,
|
|
1457
|
+
setBuffer
|
|
1458
|
+
});
|
|
1459
|
+
setBuffer(result.buffer);
|
|
1460
|
+
setCurrentToolCall(result.currentToolCall);
|
|
1461
|
+
return result.shouldBreak;
|
|
1462
|
+
}
|
|
1463
|
+
function processBufferWithoutToolCall(params, controller) {
|
|
1464
|
+
const {
|
|
1465
|
+
getBuffer,
|
|
1466
|
+
setBuffer,
|
|
1467
|
+
setCurrentToolCall,
|
|
1468
|
+
toolNames,
|
|
1469
|
+
maxStartTagLen,
|
|
1470
|
+
flushText
|
|
1471
|
+
} = params;
|
|
1472
|
+
const result = processNoToolCallInBuffer({
|
|
1473
|
+
buffer: getBuffer(),
|
|
1474
|
+
toolNames,
|
|
1475
|
+
maxStartTagLen,
|
|
1476
|
+
controller,
|
|
1477
|
+
flushText
|
|
1478
|
+
});
|
|
1479
|
+
setBuffer(result.buffer);
|
|
1480
|
+
setCurrentToolCall(result.currentToolCall);
|
|
1481
|
+
return {
|
|
1482
|
+
shouldBreak: result.shouldBreak,
|
|
1483
|
+
shouldContinue: result.shouldContinue
|
|
1484
|
+
};
|
|
1485
|
+
}
|
|
1486
|
+
function processBufferLoop(params, controller) {
|
|
1487
|
+
while (true) {
|
|
1488
|
+
const currentToolCall = params.getCurrentToolCall();
|
|
1489
|
+
if (currentToolCall) {
|
|
1490
|
+
const shouldBreak = processBufferWithToolCall(params, controller);
|
|
1491
|
+
if (shouldBreak) {
|
|
1492
|
+
break;
|
|
1493
|
+
}
|
|
1494
|
+
} else {
|
|
1495
|
+
const { shouldBreak, shouldContinue } = processBufferWithoutToolCall(
|
|
1496
|
+
params,
|
|
1497
|
+
controller
|
|
1498
|
+
);
|
|
1499
|
+
if (shouldContinue) {
|
|
1500
|
+
continue;
|
|
1501
|
+
}
|
|
1502
|
+
if (shouldBreak) {
|
|
1503
|
+
break;
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
function createProcessBufferHandler(params) {
|
|
1509
|
+
return (controller) => {
|
|
1510
|
+
processBufferLoop(params, controller);
|
|
1511
|
+
};
|
|
1512
|
+
}
|
|
1123
1513
|
var morphXmlProtocol = () => ({
|
|
1124
1514
|
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
1125
1515
|
const toolsForPrompt = (tools || []).map((tool) => ({
|
|
1126
1516
|
name: tool.name,
|
|
1127
1517
|
description: tool.description,
|
|
1128
|
-
parameters:
|
|
1518
|
+
parameters: (0, import_rxml.unwrapJsonSchema)(tool.inputSchema)
|
|
1129
1519
|
}));
|
|
1130
1520
|
return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
|
|
1131
1521
|
},
|
|
@@ -1141,19 +1531,18 @@ var morphXmlProtocol = () => ({
|
|
|
1141
1531
|
} else {
|
|
1142
1532
|
args = inputValue;
|
|
1143
1533
|
}
|
|
1144
|
-
return
|
|
1534
|
+
return (0, import_rxml.stringify)(toolCall.toolName, args, {
|
|
1145
1535
|
suppressEmptyNode: false,
|
|
1146
1536
|
format: false
|
|
1147
1537
|
});
|
|
1148
1538
|
},
|
|
1149
1539
|
formatToolResponse(toolResult) {
|
|
1150
|
-
return
|
|
1540
|
+
return (0, import_rxml.stringify)("tool_response", {
|
|
1151
1541
|
tool_name: toolResult.toolName,
|
|
1152
1542
|
result: toolResult.output
|
|
1153
1543
|
});
|
|
1154
1544
|
},
|
|
1155
1545
|
parseGeneratedText({ text, tools, options }) {
|
|
1156
|
-
var _a;
|
|
1157
1546
|
const toolNames = tools.map((t) => t.name).filter((name) => name != null);
|
|
1158
1547
|
if (toolNames.length === 0) {
|
|
1159
1548
|
return [{ type: "text", text }];
|
|
@@ -1162,46 +1551,16 @@ var morphXmlProtocol = () => ({
|
|
|
1162
1551
|
let currentIndex = 0;
|
|
1163
1552
|
const toolCalls = findToolCalls(text, toolNames);
|
|
1164
1553
|
for (const toolCall of toolCalls) {
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
const toolSchema = getToolSchema(tools, toolCall.toolName);
|
|
1173
|
-
const parsed = RXML.parse(toolCall.content, toolSchema, {
|
|
1174
|
-
onError: options == null ? void 0 : options.onError,
|
|
1175
|
-
// Disable HTML self-closing tag behavior to allow base, meta, link etc. as regular tags
|
|
1176
|
-
noChildNodes: []
|
|
1177
|
-
});
|
|
1178
|
-
processedElements.push({
|
|
1179
|
-
type: "tool-call",
|
|
1180
|
-
toolCallId: (0, import_provider_utils3.generateId)(),
|
|
1181
|
-
toolName: toolCall.toolName,
|
|
1182
|
-
input: JSON.stringify(parsed)
|
|
1183
|
-
});
|
|
1184
|
-
} catch (error) {
|
|
1185
|
-
const originalCallText = text.substring(
|
|
1186
|
-
toolCall.startIndex,
|
|
1187
|
-
toolCall.endIndex
|
|
1188
|
-
);
|
|
1189
|
-
const message = `Could not process XML tool call, keeping original text: ${originalCallText}`;
|
|
1190
|
-
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
|
|
1191
|
-
toolCall: originalCallText,
|
|
1192
|
-
toolName: toolCall.toolName,
|
|
1193
|
-
error
|
|
1194
|
-
});
|
|
1195
|
-
processedElements.push({ type: "text", text: originalCallText });
|
|
1196
|
-
}
|
|
1554
|
+
currentIndex = processTextBeforeToolCall(
|
|
1555
|
+
text,
|
|
1556
|
+
currentIndex,
|
|
1557
|
+
toolCall.startIndex,
|
|
1558
|
+
processedElements
|
|
1559
|
+
);
|
|
1560
|
+
processToolCall({ toolCall, tools, options, text, processedElements });
|
|
1197
1561
|
currentIndex = toolCall.endIndex;
|
|
1198
1562
|
}
|
|
1199
|
-
|
|
1200
|
-
const remainingText = text.substring(currentIndex);
|
|
1201
|
-
if (remainingText.trim()) {
|
|
1202
|
-
processedElements.push({ type: "text", text: remainingText });
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1563
|
+
addRemainingText(text, currentIndex, processedElements);
|
|
1205
1564
|
return processedElements;
|
|
1206
1565
|
},
|
|
1207
1566
|
createStreamParser({ tools, options }) {
|
|
@@ -1210,129 +1569,67 @@ var morphXmlProtocol = () => ({
|
|
|
1210
1569
|
let buffer = "";
|
|
1211
1570
|
let currentToolCall = null;
|
|
1212
1571
|
let currentTextId = null;
|
|
1213
|
-
const flushText = (
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
if (
|
|
1226
|
-
|
|
1572
|
+
const flushText = createFlushTextHandler(
|
|
1573
|
+
() => buffer,
|
|
1574
|
+
(newBuffer) => {
|
|
1575
|
+
buffer = newBuffer;
|
|
1576
|
+
},
|
|
1577
|
+
() => currentTextId,
|
|
1578
|
+
(newId) => {
|
|
1579
|
+
currentTextId = newId;
|
|
1580
|
+
}
|
|
1581
|
+
);
|
|
1582
|
+
const processChunk = (chunk, controller) => {
|
|
1583
|
+
if (chunk.type !== "text-delta") {
|
|
1584
|
+
if (buffer) {
|
|
1585
|
+
flushText(controller);
|
|
1227
1586
|
}
|
|
1587
|
+
controller.enqueue(chunk);
|
|
1588
|
+
return;
|
|
1228
1589
|
}
|
|
1229
|
-
|
|
1590
|
+
buffer += chunk.delta;
|
|
1591
|
+
processBuffer(controller);
|
|
1592
|
+
};
|
|
1593
|
+
const processBuffer = createProcessBufferHandler({
|
|
1594
|
+
getBuffer: () => buffer,
|
|
1595
|
+
setBuffer: (newBuffer) => {
|
|
1596
|
+
buffer = newBuffer;
|
|
1597
|
+
},
|
|
1598
|
+
getCurrentToolCall: () => currentToolCall,
|
|
1599
|
+
setCurrentToolCall: (newToolCall) => {
|
|
1600
|
+
currentToolCall = newToolCall;
|
|
1601
|
+
},
|
|
1602
|
+
tools,
|
|
1603
|
+
options,
|
|
1604
|
+
toolNames,
|
|
1605
|
+
maxStartTagLen,
|
|
1606
|
+
flushText
|
|
1607
|
+
});
|
|
1608
|
+
const flushBuffer2 = (controller) => {
|
|
1609
|
+
if (currentToolCall) {
|
|
1610
|
+
const unfinishedCall = `<${currentToolCall.name}>${buffer}`;
|
|
1611
|
+
flushText(controller, unfinishedCall);
|
|
1612
|
+
} else if (buffer) {
|
|
1613
|
+
flushText(controller);
|
|
1614
|
+
}
|
|
1615
|
+
if (currentTextId) {
|
|
1230
1616
|
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1231
|
-
currentTextId = null;
|
|
1232
1617
|
}
|
|
1233
1618
|
};
|
|
1234
1619
|
return new TransformStream({
|
|
1235
1620
|
transform(chunk, controller) {
|
|
1236
|
-
|
|
1237
|
-
if (chunk.type !== "text-delta") {
|
|
1238
|
-
if (buffer) flushText(controller);
|
|
1239
|
-
controller.enqueue(chunk);
|
|
1240
|
-
return;
|
|
1241
|
-
}
|
|
1242
|
-
buffer += chunk.delta;
|
|
1243
|
-
while (true) {
|
|
1244
|
-
if (currentToolCall) {
|
|
1245
|
-
const endTag = `</${currentToolCall.name}>`;
|
|
1246
|
-
const endTagIndex = buffer.indexOf(endTag);
|
|
1247
|
-
if (endTagIndex !== -1) {
|
|
1248
|
-
const toolContent = buffer.substring(0, endTagIndex);
|
|
1249
|
-
buffer = buffer.substring(endTagIndex + endTag.length);
|
|
1250
|
-
try {
|
|
1251
|
-
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
1252
|
-
const parsed = RXML.parse(toolContent, toolSchema, {
|
|
1253
|
-
onError: options == null ? void 0 : options.onError,
|
|
1254
|
-
// Disable HTML self-closing tag behavior to allow base, meta, link etc. as regular tags
|
|
1255
|
-
noChildNodes: []
|
|
1256
|
-
});
|
|
1257
|
-
flushText(controller);
|
|
1258
|
-
controller.enqueue({
|
|
1259
|
-
type: "tool-call",
|
|
1260
|
-
toolCallId: (0, import_provider_utils3.generateId)(),
|
|
1261
|
-
toolName: currentToolCall.name,
|
|
1262
|
-
input: JSON.stringify(parsed)
|
|
1263
|
-
});
|
|
1264
|
-
} catch (error) {
|
|
1265
|
-
const originalCallText = `<${currentToolCall.name}>${toolContent}${endTag}`;
|
|
1266
|
-
let message = "Could not process streaming XML tool call; emitting original text.";
|
|
1267
|
-
if (error instanceof RXML.RXMLDuplicateStringTagError) {
|
|
1268
|
-
message = `Duplicate string tags detected in streaming tool call '${currentToolCall.name}'; emitting original text.`;
|
|
1269
|
-
} else if (error instanceof RXML.RXMLCoercionError) {
|
|
1270
|
-
message = `Failed to coerce arguments for streaming tool call '${currentToolCall.name}'; emitting original text.`;
|
|
1271
|
-
} else if (error instanceof RXML.RXMLParseError) {
|
|
1272
|
-
message = `Failed to parse XML for streaming tool call '${currentToolCall.name}'; emitting original text.`;
|
|
1273
|
-
}
|
|
1274
|
-
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
|
|
1275
|
-
toolCall: originalCallText,
|
|
1276
|
-
toolName: currentToolCall.name,
|
|
1277
|
-
error
|
|
1278
|
-
});
|
|
1279
|
-
flushText(controller, originalCallText);
|
|
1280
|
-
}
|
|
1281
|
-
currentToolCall = null;
|
|
1282
|
-
} else {
|
|
1283
|
-
break;
|
|
1284
|
-
}
|
|
1285
|
-
} else {
|
|
1286
|
-
let earliestStartTagIndex = -1;
|
|
1287
|
-
let earliestToolName = "";
|
|
1288
|
-
if (toolNames.length > 0) {
|
|
1289
|
-
for (const name of toolNames) {
|
|
1290
|
-
const startTag = `<${name}>`;
|
|
1291
|
-
const index = buffer.indexOf(startTag);
|
|
1292
|
-
if (index !== -1 && (earliestStartTagIndex === -1 || index < earliestStartTagIndex)) {
|
|
1293
|
-
earliestStartTagIndex = index;
|
|
1294
|
-
earliestToolName = name;
|
|
1295
|
-
}
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
if (earliestStartTagIndex !== -1) {
|
|
1299
|
-
const textBeforeTag = buffer.substring(0, earliestStartTagIndex);
|
|
1300
|
-
flushText(controller, textBeforeTag);
|
|
1301
|
-
const startTag = `<${earliestToolName}>`;
|
|
1302
|
-
buffer = buffer.substring(
|
|
1303
|
-
earliestStartTagIndex + startTag.length
|
|
1304
|
-
);
|
|
1305
|
-
currentToolCall = { name: earliestToolName, content: "" };
|
|
1306
|
-
} else {
|
|
1307
|
-
const tail = Math.max(0, maxStartTagLen - 1);
|
|
1308
|
-
const safeLen = Math.max(0, buffer.length - tail);
|
|
1309
|
-
if (safeLen > 0) {
|
|
1310
|
-
const textToFlush = buffer.slice(0, safeLen);
|
|
1311
|
-
flushText(controller, textToFlush);
|
|
1312
|
-
buffer = buffer.slice(safeLen);
|
|
1313
|
-
continue;
|
|
1314
|
-
}
|
|
1315
|
-
break;
|
|
1316
|
-
}
|
|
1317
|
-
}
|
|
1318
|
-
}
|
|
1621
|
+
processChunk(chunk, controller);
|
|
1319
1622
|
},
|
|
1320
1623
|
flush(controller) {
|
|
1321
|
-
|
|
1322
|
-
const unfinishedCall = `<${currentToolCall.name}>${buffer}`;
|
|
1323
|
-
flushText(controller, unfinishedCall);
|
|
1324
|
-
} else if (buffer) {
|
|
1325
|
-
flushText(controller);
|
|
1326
|
-
}
|
|
1327
|
-
if (currentTextId) {
|
|
1328
|
-
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1329
|
-
}
|
|
1624
|
+
flushBuffer2(controller);
|
|
1330
1625
|
}
|
|
1331
1626
|
});
|
|
1332
1627
|
},
|
|
1333
1628
|
extractToolCallSegments({ text, tools }) {
|
|
1334
1629
|
const toolNames = tools.map((t) => t.name).filter(Boolean);
|
|
1335
|
-
if (toolNames.length === 0)
|
|
1630
|
+
if (toolNames.length === 0) {
|
|
1631
|
+
return [];
|
|
1632
|
+
}
|
|
1336
1633
|
return findToolCalls(text, toolNames).map((tc) => tc.segment);
|
|
1337
1634
|
}
|
|
1338
1635
|
});
|
|
@@ -1340,42 +1637,63 @@ function getToolSchema(tools, toolName) {
|
|
|
1340
1637
|
var _a;
|
|
1341
1638
|
return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
1342
1639
|
}
|
|
1343
|
-
function
|
|
1640
|
+
function computeFullTagEnd(text, contentEnd, toolName) {
|
|
1641
|
+
let fullTagEnd = contentEnd + `</${toolName}>`.length;
|
|
1642
|
+
const closeHead = text.indexOf(`</${toolName}`, contentEnd);
|
|
1643
|
+
if (closeHead === contentEnd) {
|
|
1644
|
+
let p = closeHead + 2 + toolName.length;
|
|
1645
|
+
while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
|
|
1646
|
+
p += 1;
|
|
1647
|
+
}
|
|
1648
|
+
if (text[p] === ">") {
|
|
1649
|
+
fullTagEnd = p + 1;
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
return fullTagEnd;
|
|
1653
|
+
}
|
|
1654
|
+
function extractToolCallInfo(text, tagStart, toolName, range) {
|
|
1344
1655
|
var _a;
|
|
1656
|
+
const startTag = `<${toolName}>`;
|
|
1657
|
+
const contentStart = tagStart + startTag.length;
|
|
1658
|
+
const contentEnd = contentStart + (range.end - range.start);
|
|
1659
|
+
const fullTagEnd = computeFullTagEnd(text, contentEnd, toolName);
|
|
1660
|
+
const segment = text.substring(tagStart, fullTagEnd);
|
|
1661
|
+
const content = (_a = (0, import_rxml.extractRawInner)(segment, toolName)) != null ? _a : text.substring(contentStart, contentEnd);
|
|
1662
|
+
return {
|
|
1663
|
+
toolName,
|
|
1664
|
+
startIndex: tagStart,
|
|
1665
|
+
endIndex: fullTagEnd,
|
|
1666
|
+
content,
|
|
1667
|
+
segment
|
|
1668
|
+
};
|
|
1669
|
+
}
|
|
1670
|
+
function findToolCallsForName(text, toolName) {
|
|
1345
1671
|
const toolCalls = [];
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
while (p < text.length && /\s/.test(text[p])) p++;
|
|
1362
|
-
if (text[p] === ">") fullTagEnd = p + 1;
|
|
1363
|
-
}
|
|
1364
|
-
const segment = text.substring(tagStart, fullTagEnd);
|
|
1365
|
-
const content = (_a = RXML.extractRawInner(segment, toolName)) != null ? _a : text.substring(contentStart, contentEnd);
|
|
1366
|
-
toolCalls.push({
|
|
1367
|
-
toolName,
|
|
1368
|
-
startIndex: tagStart,
|
|
1369
|
-
endIndex: fullTagEnd,
|
|
1370
|
-
content,
|
|
1371
|
-
segment
|
|
1372
|
-
});
|
|
1373
|
-
searchIndex = fullTagEnd;
|
|
1374
|
-
} else {
|
|
1375
|
-
searchIndex = tagStart + startTag.length;
|
|
1376
|
-
}
|
|
1672
|
+
const startTag = `<${toolName}>`;
|
|
1673
|
+
let searchIndex = 0;
|
|
1674
|
+
while (searchIndex < text.length) {
|
|
1675
|
+
const tagStart = text.indexOf(startTag, searchIndex);
|
|
1676
|
+
if (tagStart === -1) {
|
|
1677
|
+
break;
|
|
1678
|
+
}
|
|
1679
|
+
const remainingText = text.substring(tagStart);
|
|
1680
|
+
const range = (0, import_rxml.findFirstTopLevelRange)(remainingText, toolName);
|
|
1681
|
+
if (range) {
|
|
1682
|
+
const toolCallInfo = extractToolCallInfo(text, tagStart, toolName, range);
|
|
1683
|
+
toolCalls.push(toolCallInfo);
|
|
1684
|
+
searchIndex = toolCallInfo.endIndex;
|
|
1685
|
+
} else {
|
|
1686
|
+
searchIndex = tagStart + startTag.length;
|
|
1377
1687
|
}
|
|
1378
1688
|
}
|
|
1689
|
+
return toolCalls;
|
|
1690
|
+
}
|
|
1691
|
+
function findToolCalls(text, toolNames) {
|
|
1692
|
+
const toolCalls = [];
|
|
1693
|
+
for (const toolName of toolNames) {
|
|
1694
|
+
const calls = findToolCallsForName(text, toolName);
|
|
1695
|
+
toolCalls.push(...calls);
|
|
1696
|
+
}
|
|
1379
1697
|
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
1380
1698
|
}
|
|
1381
1699
|
|
|
@@ -1386,94 +1704,93 @@ function isProtocolFactory(protocol) {
|
|
|
1386
1704
|
|
|
1387
1705
|
// src/generate-handler.ts
|
|
1388
1706
|
var import_provider_utils4 = require("@ai-sdk/provider-utils");
|
|
1389
|
-
var
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
}) {
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
if (debugLevel2 === "parse") {
|
|
1403
|
-
logRawChunk(first.text);
|
|
1404
|
-
}
|
|
1405
|
-
try {
|
|
1406
|
-
parsed2 = JSON.parse(first.text);
|
|
1407
|
-
} catch (error) {
|
|
1408
|
-
const options = extractOnErrorOption(params.providerOptions);
|
|
1409
|
-
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
1410
|
-
options,
|
|
1411
|
-
"Failed to parse toolChoice JSON from generated model output",
|
|
1412
|
-
{
|
|
1413
|
-
text: first.text,
|
|
1414
|
-
error: error instanceof Error ? error.message : String(error)
|
|
1415
|
-
}
|
|
1416
|
-
);
|
|
1417
|
-
parsed2 = {};
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1420
|
-
const toolCall = {
|
|
1421
|
-
type: "tool-call",
|
|
1422
|
-
toolCallId: (0, import_provider_utils4.generateId)(),
|
|
1423
|
-
toolName: parsed2.name || "unknown",
|
|
1424
|
-
input: JSON.stringify(parsed2.arguments || {})
|
|
1425
|
-
};
|
|
1426
|
-
const debugLevelToolChoice = getDebugLevel();
|
|
1427
|
-
const originText = first && first.type === "text" ? first.text : "";
|
|
1428
|
-
const dbg2 = (_d = (_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) == null ? void 0 : _d.debugSummary;
|
|
1429
|
-
if (dbg2) {
|
|
1430
|
-
dbg2.originalText = originText;
|
|
1431
|
-
try {
|
|
1432
|
-
dbg2.toolCalls = JSON.stringify([
|
|
1433
|
-
{ toolName: toolCall.toolName, input: toolCall.input }
|
|
1434
|
-
]);
|
|
1435
|
-
} catch (e) {
|
|
1707
|
+
var import_rxml2 = require("@ai-sdk-tool/rxml");
|
|
1708
|
+
function parseToolChoiceJson(text, providerOptions) {
|
|
1709
|
+
var _a;
|
|
1710
|
+
try {
|
|
1711
|
+
return JSON.parse(text);
|
|
1712
|
+
} catch (error) {
|
|
1713
|
+
const options = extractOnErrorOption(providerOptions);
|
|
1714
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1715
|
+
options,
|
|
1716
|
+
"Failed to parse toolChoice JSON from generated model output",
|
|
1717
|
+
{
|
|
1718
|
+
text,
|
|
1719
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1436
1720
|
}
|
|
1437
|
-
|
|
1438
|
-
|
|
1721
|
+
);
|
|
1722
|
+
return {};
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
function logDebugSummary(debugSummary, toolCall, originText) {
|
|
1726
|
+
if (debugSummary) {
|
|
1727
|
+
debugSummary.originalText = originText;
|
|
1728
|
+
try {
|
|
1729
|
+
debugSummary.toolCalls = JSON.stringify([
|
|
1730
|
+
{ toolName: toolCall.toolName, input: toolCall.input }
|
|
1731
|
+
]);
|
|
1732
|
+
} catch (e) {
|
|
1439
1733
|
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
content: [toolCall]
|
|
1443
|
-
};
|
|
1734
|
+
} else if (getDebugLevel() === "parse") {
|
|
1735
|
+
logParsedSummary({ toolCalls: [toolCall], originalText: originText });
|
|
1444
1736
|
}
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1737
|
+
}
|
|
1738
|
+
async function handleToolChoice(doGenerate, params) {
|
|
1739
|
+
var _a, _b, _c;
|
|
1448
1740
|
const result = await doGenerate();
|
|
1449
|
-
|
|
1450
|
-
|
|
1741
|
+
const first = (_a = result.content) == null ? void 0 : _a[0];
|
|
1742
|
+
let parsed = {};
|
|
1743
|
+
if (first && first.type === "text") {
|
|
1744
|
+
if (getDebugLevel() === "parse") {
|
|
1745
|
+
logRawChunk(first.text);
|
|
1746
|
+
}
|
|
1747
|
+
parsed = parseToolChoiceJson(first.text, params.providerOptions);
|
|
1451
1748
|
}
|
|
1452
|
-
const
|
|
1453
|
-
|
|
1749
|
+
const toolCall = {
|
|
1750
|
+
type: "tool-call",
|
|
1751
|
+
toolCallId: (0, import_provider_utils4.generateId)(),
|
|
1752
|
+
toolName: parsed.name || "unknown",
|
|
1753
|
+
input: JSON.stringify(parsed.arguments || {})
|
|
1754
|
+
};
|
|
1755
|
+
const originText = first && first.type === "text" ? first.text : "";
|
|
1756
|
+
const debugSummary = (_c = (_b = params.providerOptions) == null ? void 0 : _b.toolCallMiddleware) == null ? void 0 : _c.debugSummary;
|
|
1757
|
+
logDebugSummary(debugSummary, toolCall, originText);
|
|
1758
|
+
return {
|
|
1759
|
+
...result,
|
|
1760
|
+
content: [toolCall]
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
function parseContent(content, protocol, tools, providerOptions) {
|
|
1764
|
+
const parsed = content.flatMap((contentItem) => {
|
|
1454
1765
|
if (contentItem.type !== "text") {
|
|
1455
1766
|
return [contentItem];
|
|
1456
1767
|
}
|
|
1457
|
-
|
|
1458
|
-
if (debugLevel2 === "stream") {
|
|
1768
|
+
if (getDebugLevel() === "stream") {
|
|
1459
1769
|
logRawChunk(contentItem.text);
|
|
1460
1770
|
}
|
|
1461
1771
|
return protocol.parseGeneratedText({
|
|
1462
1772
|
text: contentItem.text,
|
|
1463
1773
|
tools,
|
|
1464
1774
|
options: {
|
|
1465
|
-
...extractOnErrorOption(
|
|
1466
|
-
...
|
|
1775
|
+
...extractOnErrorOption(providerOptions),
|
|
1776
|
+
...providerOptions == null ? void 0 : providerOptions.toolCallMiddleware
|
|
1467
1777
|
}
|
|
1468
1778
|
});
|
|
1469
1779
|
});
|
|
1470
|
-
|
|
1780
|
+
return parsed.map(
|
|
1471
1781
|
(part) => fixToolCallWithSchema(part, tools)
|
|
1472
1782
|
);
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1783
|
+
}
|
|
1784
|
+
function logParsedContent(content) {
|
|
1785
|
+
if (getDebugLevel() === "stream") {
|
|
1786
|
+
for (const part of content) {
|
|
1787
|
+
logParsedChunk(part);
|
|
1788
|
+
}
|
|
1476
1789
|
}
|
|
1790
|
+
}
|
|
1791
|
+
function computeDebugSummary(options) {
|
|
1792
|
+
var _a;
|
|
1793
|
+
const { result, newContent, protocol, tools, providerOptions } = options;
|
|
1477
1794
|
const allText = result.content.filter(
|
|
1478
1795
|
(c) => c.type === "text"
|
|
1479
1796
|
).map((c) => c.text).join("\n\n");
|
|
@@ -1482,7 +1799,7 @@ async function wrapGenerate({
|
|
|
1482
1799
|
const toolCalls = newContent.filter(
|
|
1483
1800
|
(p) => p.type === "tool-call"
|
|
1484
1801
|
);
|
|
1485
|
-
const dbg = (
|
|
1802
|
+
const dbg = (_a = providerOptions == null ? void 0 : providerOptions.toolCallMiddleware) == null ? void 0 : _a.debugSummary;
|
|
1486
1803
|
if (dbg) {
|
|
1487
1804
|
dbg.originalText = originalText;
|
|
1488
1805
|
try {
|
|
@@ -1494,9 +1811,40 @@ async function wrapGenerate({
|
|
|
1494
1811
|
);
|
|
1495
1812
|
} catch (e) {
|
|
1496
1813
|
}
|
|
1497
|
-
} else if (
|
|
1814
|
+
} else if (getDebugLevel() === "parse") {
|
|
1498
1815
|
logParsedSummary({ toolCalls, originalText });
|
|
1499
1816
|
}
|
|
1817
|
+
}
|
|
1818
|
+
async function wrapGenerate({
|
|
1819
|
+
protocol,
|
|
1820
|
+
doGenerate,
|
|
1821
|
+
params
|
|
1822
|
+
}) {
|
|
1823
|
+
var _a, _b;
|
|
1824
|
+
if (isToolChoiceActive(params)) {
|
|
1825
|
+
return handleToolChoice(doGenerate, params);
|
|
1826
|
+
}
|
|
1827
|
+
const tools = originalToolsSchema.decode(
|
|
1828
|
+
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools
|
|
1829
|
+
);
|
|
1830
|
+
const result = await doGenerate();
|
|
1831
|
+
if (result.content.length === 0) {
|
|
1832
|
+
return result;
|
|
1833
|
+
}
|
|
1834
|
+
const newContent = parseContent(
|
|
1835
|
+
result.content,
|
|
1836
|
+
protocol,
|
|
1837
|
+
tools,
|
|
1838
|
+
params.providerOptions
|
|
1839
|
+
);
|
|
1840
|
+
logParsedContent(newContent);
|
|
1841
|
+
computeDebugSummary({
|
|
1842
|
+
result,
|
|
1843
|
+
newContent,
|
|
1844
|
+
protocol,
|
|
1845
|
+
tools,
|
|
1846
|
+
providerOptions: params.providerOptions
|
|
1847
|
+
});
|
|
1500
1848
|
return {
|
|
1501
1849
|
...result,
|
|
1502
1850
|
content: newContent
|
|
@@ -1504,7 +1852,9 @@ async function wrapGenerate({
|
|
|
1504
1852
|
}
|
|
1505
1853
|
function fixToolCallWithSchema(part, tools) {
|
|
1506
1854
|
var _a;
|
|
1507
|
-
if (part.type !== "tool-call")
|
|
1855
|
+
if (part.type !== "tool-call") {
|
|
1856
|
+
return part;
|
|
1857
|
+
}
|
|
1508
1858
|
const tc = part;
|
|
1509
1859
|
let args = {};
|
|
1510
1860
|
if (typeof tc.input === "string") {
|
|
@@ -1517,7 +1867,7 @@ function fixToolCallWithSchema(part, tools) {
|
|
|
1517
1867
|
args = tc.input;
|
|
1518
1868
|
}
|
|
1519
1869
|
const schema = (_a = tools.find((t) => t.name === tc.toolName)) == null ? void 0 : _a.inputSchema;
|
|
1520
|
-
const coerced =
|
|
1870
|
+
const coerced = (0, import_rxml2.coerceBySchema)(args, schema);
|
|
1521
1871
|
return {
|
|
1522
1872
|
...part,
|
|
1523
1873
|
input: JSON.stringify(coerced != null ? coerced : {})
|
|
@@ -1526,6 +1876,69 @@ function fixToolCallWithSchema(part, tools) {
|
|
|
1526
1876
|
|
|
1527
1877
|
// src/stream-handler.ts
|
|
1528
1878
|
var import_provider_utils5 = require("@ai-sdk/provider-utils");
|
|
1879
|
+
function extractToolCallSegments(protocol, fullRawText, tools) {
|
|
1880
|
+
const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({
|
|
1881
|
+
text: fullRawText,
|
|
1882
|
+
tools
|
|
1883
|
+
}) : [];
|
|
1884
|
+
return segments.join("\n\n");
|
|
1885
|
+
}
|
|
1886
|
+
function serializeToolCalls(parsedToolCalls) {
|
|
1887
|
+
const toolCallParts = parsedToolCalls.filter(
|
|
1888
|
+
(p) => p.type === "tool-call"
|
|
1889
|
+
);
|
|
1890
|
+
return JSON.stringify(
|
|
1891
|
+
toolCallParts.map((tc) => ({
|
|
1892
|
+
toolName: tc.toolName,
|
|
1893
|
+
input: tc.input
|
|
1894
|
+
}))
|
|
1895
|
+
);
|
|
1896
|
+
}
|
|
1897
|
+
function handleDebugSummary(parsedToolCalls, origin, params) {
|
|
1898
|
+
var _a, _b;
|
|
1899
|
+
const dbg = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.debugSummary;
|
|
1900
|
+
if (dbg) {
|
|
1901
|
+
dbg.originalText = origin;
|
|
1902
|
+
try {
|
|
1903
|
+
dbg.toolCalls = serializeToolCalls(parsedToolCalls);
|
|
1904
|
+
} catch (e) {
|
|
1905
|
+
}
|
|
1906
|
+
} else {
|
|
1907
|
+
logParsedSummary({
|
|
1908
|
+
toolCalls: parsedToolCalls,
|
|
1909
|
+
originalText: origin
|
|
1910
|
+
});
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
function createDebugSummaryTransform({
|
|
1914
|
+
protocol,
|
|
1915
|
+
fullRawText,
|
|
1916
|
+
tools,
|
|
1917
|
+
params
|
|
1918
|
+
}) {
|
|
1919
|
+
return new TransformStream({
|
|
1920
|
+
transform: /* @__PURE__ */ (() => {
|
|
1921
|
+
const parsedToolCalls = [];
|
|
1922
|
+
return (part, controller) => {
|
|
1923
|
+
if (part.type === "tool-call") {
|
|
1924
|
+
parsedToolCalls.push(part);
|
|
1925
|
+
}
|
|
1926
|
+
if (part.type === "finish") {
|
|
1927
|
+
try {
|
|
1928
|
+
const origin = extractToolCallSegments(
|
|
1929
|
+
protocol,
|
|
1930
|
+
fullRawText,
|
|
1931
|
+
tools
|
|
1932
|
+
);
|
|
1933
|
+
handleDebugSummary(parsedToolCalls, origin, params);
|
|
1934
|
+
} catch (e) {
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
controller.enqueue(part);
|
|
1938
|
+
};
|
|
1939
|
+
})()
|
|
1940
|
+
});
|
|
1941
|
+
}
|
|
1529
1942
|
async function wrapStream({
|
|
1530
1943
|
protocol,
|
|
1531
1944
|
doStream,
|
|
@@ -1612,48 +2025,11 @@ async function wrapStream({
|
|
|
1612
2025
|
})
|
|
1613
2026
|
);
|
|
1614
2027
|
const withSummary = parsed.pipeThrough(
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
if (part.type === "tool-call") {
|
|
1621
|
-
parsedToolCalls.push(part);
|
|
1622
|
-
}
|
|
1623
|
-
if (part.type === "finish") {
|
|
1624
|
-
try {
|
|
1625
|
-
const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({
|
|
1626
|
-
text: fullRawText,
|
|
1627
|
-
tools
|
|
1628
|
-
}) : [];
|
|
1629
|
-
const origin = segments.join("\n\n");
|
|
1630
|
-
const dbg = (_b2 = (_a2 = params.providerOptions) == null ? void 0 : _a2.toolCallMiddleware) == null ? void 0 : _b2.debugSummary;
|
|
1631
|
-
if (dbg) {
|
|
1632
|
-
dbg.originalText = origin;
|
|
1633
|
-
try {
|
|
1634
|
-
const toolCallParts = parsedToolCalls.filter(
|
|
1635
|
-
(p) => p.type === "tool-call"
|
|
1636
|
-
);
|
|
1637
|
-
dbg.toolCalls = JSON.stringify(
|
|
1638
|
-
toolCallParts.map((tc) => ({
|
|
1639
|
-
toolName: tc.toolName,
|
|
1640
|
-
input: tc.input
|
|
1641
|
-
}))
|
|
1642
|
-
);
|
|
1643
|
-
} catch (e) {
|
|
1644
|
-
}
|
|
1645
|
-
} else {
|
|
1646
|
-
logParsedSummary({
|
|
1647
|
-
toolCalls: parsedToolCalls,
|
|
1648
|
-
originalText: origin
|
|
1649
|
-
});
|
|
1650
|
-
}
|
|
1651
|
-
} catch (e) {
|
|
1652
|
-
}
|
|
1653
|
-
}
|
|
1654
|
-
controller.enqueue(part);
|
|
1655
|
-
};
|
|
1656
|
-
})()
|
|
2028
|
+
createDebugSummaryTransform({
|
|
2029
|
+
protocol,
|
|
2030
|
+
fullRawText,
|
|
2031
|
+
tools,
|
|
2032
|
+
params
|
|
1657
2033
|
})
|
|
1658
2034
|
);
|
|
1659
2035
|
return {
|
|
@@ -1665,7 +2041,7 @@ async function toolChoiceStream({
|
|
|
1665
2041
|
doGenerate,
|
|
1666
2042
|
options
|
|
1667
2043
|
}) {
|
|
1668
|
-
var _a, _b;
|
|
2044
|
+
var _a, _b, _c;
|
|
1669
2045
|
const result = await doGenerate();
|
|
1670
2046
|
let toolJson = {};
|
|
1671
2047
|
if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
|
|
@@ -1707,7 +2083,7 @@ async function toolChoiceStream({
|
|
|
1707
2083
|
}
|
|
1708
2084
|
});
|
|
1709
2085
|
const debugLevel = getDebugLevel();
|
|
1710
|
-
const firstText = (result == null ? void 0 : result.content)
|
|
2086
|
+
const firstText = ((_c = result == null ? void 0 : result.content) == null ? void 0 : _c[0]) && result.content[0].type === "text" && result.content[0].text || "";
|
|
1711
2087
|
const streamWithSummary = debugLevel === "parse" ? stream.pipeThrough(
|
|
1712
2088
|
new TransformStream({
|
|
1713
2089
|
transform(part, controller) {
|
|
@@ -1732,39 +2108,29 @@ async function toolChoiceStream({
|
|
|
1732
2108
|
}
|
|
1733
2109
|
|
|
1734
2110
|
// src/transform-handler.ts
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
const processedPrompt = convertToolPrompt(
|
|
1750
|
-
(_b = params.prompt) != null ? _b : [],
|
|
1751
|
-
resolvedProtocol,
|
|
1752
|
-
extractOnErrorOption(params.providerOptions)
|
|
1753
|
-
);
|
|
1754
|
-
const finalPrompt = ((_c = processedPrompt[0]) == null ? void 0 : _c.role) === "system" ? [
|
|
1755
|
-
{
|
|
1756
|
-
role: "system",
|
|
1757
|
-
content: systemPrompt + "\n\n" + processedPrompt[0].content
|
|
1758
|
-
},
|
|
1759
|
-
...processedPrompt.slice(1)
|
|
1760
|
-
] : [
|
|
2111
|
+
function buildFinalPrompt(systemPrompt, processedPrompt) {
|
|
2112
|
+
var _a;
|
|
2113
|
+
if (((_a = processedPrompt[0]) == null ? void 0 : _a.role) === "system") {
|
|
2114
|
+
return [
|
|
2115
|
+
{
|
|
2116
|
+
role: "system",
|
|
2117
|
+
content: `${systemPrompt}
|
|
2118
|
+
|
|
2119
|
+
${processedPrompt[0].content}`
|
|
2120
|
+
},
|
|
2121
|
+
...processedPrompt.slice(1)
|
|
2122
|
+
];
|
|
2123
|
+
}
|
|
2124
|
+
return [
|
|
1761
2125
|
{
|
|
1762
2126
|
role: "system",
|
|
1763
2127
|
content: systemPrompt
|
|
1764
2128
|
},
|
|
1765
2129
|
...processedPrompt
|
|
1766
2130
|
];
|
|
1767
|
-
|
|
2131
|
+
}
|
|
2132
|
+
function buildBaseReturnParams(params, finalPrompt, functionTools) {
|
|
2133
|
+
return {
|
|
1768
2134
|
...params,
|
|
1769
2135
|
prompt: finalPrompt,
|
|
1770
2136
|
tools: [],
|
|
@@ -1773,184 +2139,234 @@ async function transformParams({
|
|
|
1773
2139
|
...params.providerOptions || {},
|
|
1774
2140
|
toolCallMiddleware: {
|
|
1775
2141
|
...params.providerOptions && typeof params.providerOptions === "object" && params.providerOptions.toolCallMiddleware || {},
|
|
1776
|
-
// INTERNAL: used by the middleware so downstream parsers can access
|
|
1777
|
-
// the original tool schemas even if providers strip `params.tools`.
|
|
1778
|
-
// Not a stable public API.
|
|
1779
2142
|
originalTools: originalToolsSchema.encode(functionTools)
|
|
1780
2143
|
}
|
|
1781
2144
|
}
|
|
1782
2145
|
};
|
|
1783
|
-
|
|
2146
|
+
}
|
|
2147
|
+
function findProviderDefinedTool(tools, selectedToolName) {
|
|
2148
|
+
return tools.find((t) => {
|
|
2149
|
+
if (t.type === "function") {
|
|
2150
|
+
return false;
|
|
2151
|
+
}
|
|
2152
|
+
const anyTool = t;
|
|
2153
|
+
return anyTool.id === selectedToolName || anyTool.name === selectedToolName;
|
|
2154
|
+
});
|
|
2155
|
+
}
|
|
2156
|
+
function handleToolChoiceTool(params, baseReturnParams) {
|
|
2157
|
+
var _a, _b, _c;
|
|
2158
|
+
const selectedToolName = (_a = params.toolChoice) == null ? void 0 : _a.toolName;
|
|
2159
|
+
if (!selectedToolName) {
|
|
2160
|
+
throw new Error("Tool name is required for 'tool' toolChoice type.");
|
|
2161
|
+
}
|
|
2162
|
+
const providerDefinedMatch = findProviderDefinedTool(
|
|
2163
|
+
(_b = params.tools) != null ? _b : [],
|
|
2164
|
+
selectedToolName
|
|
2165
|
+
);
|
|
2166
|
+
if (providerDefinedMatch) {
|
|
1784
2167
|
throw new Error(
|
|
1785
|
-
"
|
|
2168
|
+
"Provider-defined tools are not supported by this middleware. Please use custom tools."
|
|
1786
2169
|
);
|
|
1787
2170
|
}
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
});
|
|
1795
|
-
if (providerDefinedMatch) {
|
|
1796
|
-
throw new Error(
|
|
1797
|
-
"Provider-defined tools are not supported by this middleware. Please use custom tools."
|
|
1798
|
-
);
|
|
1799
|
-
}
|
|
1800
|
-
const selectedTool = ((_g = params.tools) != null ? _g : []).find(
|
|
1801
|
-
(t) => t.type === "function" && t.name === selectedToolName
|
|
2171
|
+
const selectedTool = ((_c = params.tools) != null ? _c : []).find(
|
|
2172
|
+
(t) => t.type === "function" && t.name === selectedToolName
|
|
2173
|
+
);
|
|
2174
|
+
if (!selectedTool) {
|
|
2175
|
+
throw new Error(
|
|
2176
|
+
`Tool with name '${selectedToolName}' not found in params.tools.`
|
|
1802
2177
|
);
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
type: "object",
|
|
1814
|
-
properties: {
|
|
1815
|
-
name: {
|
|
1816
|
-
const: selectedTool.name
|
|
1817
|
-
},
|
|
1818
|
-
arguments: selectedTool.inputSchema
|
|
2178
|
+
}
|
|
2179
|
+
return {
|
|
2180
|
+
...baseReturnParams,
|
|
2181
|
+
responseFormat: {
|
|
2182
|
+
type: "json",
|
|
2183
|
+
schema: {
|
|
2184
|
+
type: "object",
|
|
2185
|
+
properties: {
|
|
2186
|
+
name: {
|
|
2187
|
+
const: selectedTool.name
|
|
1819
2188
|
},
|
|
1820
|
-
|
|
2189
|
+
arguments: selectedTool.inputSchema
|
|
1821
2190
|
},
|
|
1822
|
-
|
|
1823
|
-
description: typeof selectedTool.description === "string" ? selectedTool.description : void 0
|
|
2191
|
+
required: ["name", "arguments"]
|
|
1824
2192
|
},
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
}
|
|
2193
|
+
name: selectedTool.name,
|
|
2194
|
+
description: typeof selectedTool.description === "string" ? selectedTool.description : void 0
|
|
2195
|
+
},
|
|
2196
|
+
providerOptions: {
|
|
2197
|
+
...baseReturnParams.providerOptions || {},
|
|
2198
|
+
toolCallMiddleware: {
|
|
2199
|
+
...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
|
|
2200
|
+
...params.toolChoice ? { toolChoice: params.toolChoice } : {}
|
|
1833
2201
|
}
|
|
1834
|
-
}
|
|
2202
|
+
}
|
|
2203
|
+
};
|
|
2204
|
+
}
|
|
2205
|
+
function handleToolChoiceRequired(params, baseReturnParams, functionTools) {
|
|
2206
|
+
if (!params.tools || params.tools.length === 0) {
|
|
2207
|
+
throw new Error(
|
|
2208
|
+
"Tool choice type 'required' is set, but no tools are provided in params.tools."
|
|
2209
|
+
);
|
|
1835
2210
|
}
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
2211
|
+
return {
|
|
2212
|
+
...baseReturnParams,
|
|
2213
|
+
responseFormat: {
|
|
2214
|
+
type: "json",
|
|
2215
|
+
schema: createDynamicIfThenElseSchema(functionTools)
|
|
2216
|
+
},
|
|
2217
|
+
providerOptions: {
|
|
2218
|
+
...baseReturnParams.providerOptions || {},
|
|
2219
|
+
toolCallMiddleware: {
|
|
2220
|
+
...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
|
|
2221
|
+
toolChoice: { type: "required" }
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
};
|
|
2225
|
+
}
|
|
2226
|
+
function transformParams({
|
|
2227
|
+
params,
|
|
2228
|
+
protocol,
|
|
2229
|
+
toolSystemPromptTemplate
|
|
2230
|
+
}) {
|
|
2231
|
+
var _a, _b, _c, _d, _e;
|
|
2232
|
+
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
2233
|
+
const functionTools = ((_a = params.tools) != null ? _a : []).filter(
|
|
2234
|
+
(t) => t.type === "function"
|
|
2235
|
+
);
|
|
2236
|
+
const systemPrompt = resolvedProtocol.formatTools({
|
|
2237
|
+
tools: functionTools,
|
|
2238
|
+
toolSystemPromptTemplate
|
|
2239
|
+
});
|
|
2240
|
+
const processedPrompt = convertToolPrompt(
|
|
2241
|
+
(_b = params.prompt) != null ? _b : [],
|
|
2242
|
+
resolvedProtocol,
|
|
2243
|
+
extractOnErrorOption(params.providerOptions)
|
|
2244
|
+
);
|
|
2245
|
+
const finalPrompt = buildFinalPrompt(systemPrompt, processedPrompt);
|
|
2246
|
+
const baseReturnParams = buildBaseReturnParams(
|
|
2247
|
+
params,
|
|
2248
|
+
finalPrompt,
|
|
2249
|
+
functionTools
|
|
2250
|
+
);
|
|
2251
|
+
if (((_c = params.toolChoice) == null ? void 0 : _c.type) === "none") {
|
|
2252
|
+
throw new Error(
|
|
2253
|
+
"The 'none' toolChoice type is not supported by this middleware. Please use 'auto', 'required', or specify a tool name."
|
|
2254
|
+
);
|
|
2255
|
+
}
|
|
2256
|
+
if (((_d = params.toolChoice) == null ? void 0 : _d.type) === "tool") {
|
|
2257
|
+
return handleToolChoiceTool(params, baseReturnParams);
|
|
2258
|
+
}
|
|
2259
|
+
if (((_e = params.toolChoice) == null ? void 0 : _e.type) === "required") {
|
|
2260
|
+
return handleToolChoiceRequired(params, baseReturnParams, functionTools);
|
|
2261
|
+
}
|
|
2262
|
+
return baseReturnParams;
|
|
2263
|
+
}
|
|
2264
|
+
function processAssistantContent(content, resolvedProtocol, providerOptions) {
|
|
2265
|
+
var _a;
|
|
2266
|
+
const newContent = [];
|
|
2267
|
+
for (const item of content) {
|
|
2268
|
+
if (isToolCallContent(item)) {
|
|
2269
|
+
newContent.push({
|
|
2270
|
+
type: "text",
|
|
2271
|
+
text: resolvedProtocol.formatToolCall(item)
|
|
2272
|
+
});
|
|
2273
|
+
} else if (item.type === "text") {
|
|
2274
|
+
newContent.push(item);
|
|
2275
|
+
} else if (item.type === "reasoning") {
|
|
2276
|
+
newContent.push(item);
|
|
2277
|
+
} else {
|
|
2278
|
+
const options = extractOnErrorOption(providerOptions);
|
|
2279
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
2280
|
+
options,
|
|
2281
|
+
"tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
|
|
2282
|
+
{ content: item }
|
|
1840
2283
|
);
|
|
2284
|
+
newContent.push({
|
|
2285
|
+
type: "text",
|
|
2286
|
+
text: JSON.stringify(item)
|
|
2287
|
+
});
|
|
1841
2288
|
}
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
2289
|
+
}
|
|
2290
|
+
const onlyText = newContent.every((c) => c.type === "text");
|
|
2291
|
+
return onlyText ? [
|
|
2292
|
+
{
|
|
2293
|
+
type: "text",
|
|
2294
|
+
text: newContent.map((c) => c.text).join("\n")
|
|
2295
|
+
}
|
|
2296
|
+
] : newContent;
|
|
2297
|
+
}
|
|
2298
|
+
function processToolMessage(content, resolvedProtocol) {
|
|
2299
|
+
return {
|
|
2300
|
+
role: "user",
|
|
2301
|
+
content: [
|
|
2302
|
+
{
|
|
2303
|
+
type: "text",
|
|
2304
|
+
text: content.map((toolResult) => resolvedProtocol.formatToolResponse(toolResult)).join("\n")
|
|
1856
2305
|
}
|
|
2306
|
+
]
|
|
2307
|
+
};
|
|
2308
|
+
}
|
|
2309
|
+
function processMessage(message, resolvedProtocol, providerOptions) {
|
|
2310
|
+
if (message.role === "assistant") {
|
|
2311
|
+
const condensedContent = processAssistantContent(
|
|
2312
|
+
message.content,
|
|
2313
|
+
resolvedProtocol,
|
|
2314
|
+
providerOptions
|
|
2315
|
+
);
|
|
2316
|
+
return {
|
|
2317
|
+
role: "assistant",
|
|
2318
|
+
content: condensedContent
|
|
1857
2319
|
};
|
|
1858
2320
|
}
|
|
1859
|
-
|
|
2321
|
+
if (message.role === "tool") {
|
|
2322
|
+
return processToolMessage(message.content, resolvedProtocol);
|
|
2323
|
+
}
|
|
2324
|
+
return message;
|
|
1860
2325
|
}
|
|
1861
|
-
function
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
text: JSON.stringify(content)
|
|
1886
|
-
});
|
|
1887
|
-
}
|
|
2326
|
+
function isAllTextContent(content) {
|
|
2327
|
+
if (!Array.isArray(content)) {
|
|
2328
|
+
return false;
|
|
2329
|
+
}
|
|
2330
|
+
return content.every(
|
|
2331
|
+
(c) => (c == null ? void 0 : c.type) === "text"
|
|
2332
|
+
);
|
|
2333
|
+
}
|
|
2334
|
+
function joinTextContent(content) {
|
|
2335
|
+
return content.map((c) => c.text).join("\n");
|
|
2336
|
+
}
|
|
2337
|
+
function createCondensedMessage(role, joinedText) {
|
|
2338
|
+
if (role === "system") {
|
|
2339
|
+
return {
|
|
2340
|
+
role: "system",
|
|
2341
|
+
content: joinedText
|
|
2342
|
+
};
|
|
2343
|
+
}
|
|
2344
|
+
return {
|
|
2345
|
+
role,
|
|
2346
|
+
content: [
|
|
2347
|
+
{
|
|
2348
|
+
type: "text",
|
|
2349
|
+
text: joinedText
|
|
1888
2350
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
}
|
|
1895
|
-
] : newContent;
|
|
1896
|
-
return { role: "assistant", content: condensedAssistant };
|
|
1897
|
-
}
|
|
1898
|
-
if (message.role === "tool") {
|
|
1899
|
-
return {
|
|
1900
|
-
role: "user",
|
|
1901
|
-
// Map tool results to text response blocks, then condense into a single text block
|
|
1902
|
-
content: [
|
|
1903
|
-
{
|
|
1904
|
-
type: "text",
|
|
1905
|
-
text: message.content.map(
|
|
1906
|
-
(toolResult) => isToolResultPart(toolResult) ? resolvedProtocol.formatToolResponse(toolResult) : resolvedProtocol.formatToolResponse(
|
|
1907
|
-
toolResult
|
|
1908
|
-
)
|
|
1909
|
-
).join("\n")
|
|
1910
|
-
}
|
|
1911
|
-
]
|
|
1912
|
-
};
|
|
1913
|
-
}
|
|
1914
|
-
return message;
|
|
1915
|
-
});
|
|
1916
|
-
for (let i = 0; i < processedPrompt.length; i++) {
|
|
2351
|
+
]
|
|
2352
|
+
};
|
|
2353
|
+
}
|
|
2354
|
+
function condenseTextContent(processedPrompt) {
|
|
2355
|
+
for (let i = 0; i < processedPrompt.length; i += 1) {
|
|
1917
2356
|
const msg = processedPrompt[i];
|
|
1918
|
-
if (Array.isArray(msg.content)) {
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
processedPrompt[i] = {
|
|
1926
|
-
role: "system",
|
|
1927
|
-
content: joinedText
|
|
1928
|
-
};
|
|
1929
|
-
} else if (msg.role === "assistant") {
|
|
1930
|
-
processedPrompt[i] = {
|
|
1931
|
-
role: "assistant",
|
|
1932
|
-
content: [
|
|
1933
|
-
{
|
|
1934
|
-
type: "text",
|
|
1935
|
-
text: joinedText
|
|
1936
|
-
}
|
|
1937
|
-
]
|
|
1938
|
-
};
|
|
1939
|
-
} else {
|
|
1940
|
-
processedPrompt[i] = {
|
|
1941
|
-
role: "user",
|
|
1942
|
-
content: [
|
|
1943
|
-
{
|
|
1944
|
-
type: "text",
|
|
1945
|
-
text: joinedText
|
|
1946
|
-
}
|
|
1947
|
-
]
|
|
1948
|
-
};
|
|
1949
|
-
}
|
|
1950
|
-
}
|
|
2357
|
+
if (!Array.isArray(msg.content)) {
|
|
2358
|
+
continue;
|
|
2359
|
+
}
|
|
2360
|
+
const shouldCondense = isAllTextContent(msg.content) && msg.content.length > 1;
|
|
2361
|
+
if (shouldCondense) {
|
|
2362
|
+
const joinedText = joinTextContent(msg.content);
|
|
2363
|
+
processedPrompt[i] = createCondensedMessage(msg.role, joinedText);
|
|
1951
2364
|
}
|
|
1952
2365
|
}
|
|
1953
|
-
|
|
2366
|
+
return processedPrompt;
|
|
2367
|
+
}
|
|
2368
|
+
function mergeConsecutiveUserMessages(processedPrompt) {
|
|
2369
|
+
for (let i = processedPrompt.length - 1; i > 0; i -= 1) {
|
|
1954
2370
|
const current = processedPrompt[i];
|
|
1955
2371
|
const prev = processedPrompt[i - 1];
|
|
1956
2372
|
if (current.role === "user" && prev.role === "user") {
|
|
@@ -1958,13 +2374,22 @@ function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
|
|
|
1958
2374
|
const currentContent = current.content.map((c) => c.type === "text" ? c.text : "").join("\n");
|
|
1959
2375
|
processedPrompt[i - 1] = {
|
|
1960
2376
|
role: "user",
|
|
1961
|
-
content: [{ type: "text", text: prevContent
|
|
2377
|
+
content: [{ type: "text", text: `${prevContent}
|
|
2378
|
+
${currentContent}` }]
|
|
1962
2379
|
};
|
|
1963
2380
|
processedPrompt.splice(i, 1);
|
|
1964
2381
|
}
|
|
1965
2382
|
}
|
|
1966
2383
|
return processedPrompt;
|
|
1967
2384
|
}
|
|
2385
|
+
function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
|
|
2386
|
+
let processedPrompt = prompt.map(
|
|
2387
|
+
(message) => processMessage(message, resolvedProtocol, providerOptions)
|
|
2388
|
+
);
|
|
2389
|
+
processedPrompt = condenseTextContent(processedPrompt);
|
|
2390
|
+
processedPrompt = mergeConsecutiveUserMessages(processedPrompt);
|
|
2391
|
+
return processedPrompt;
|
|
2392
|
+
}
|
|
1968
2393
|
|
|
1969
2394
|
// src/tool-call-middleware.ts
|
|
1970
2395
|
function createToolMiddleware({
|
|
@@ -1973,36 +2398,31 @@ function createToolMiddleware({
|
|
|
1973
2398
|
}) {
|
|
1974
2399
|
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
1975
2400
|
return {
|
|
1976
|
-
|
|
1977
|
-
wrapStream:
|
|
2401
|
+
specificationVersion: "v3",
|
|
2402
|
+
wrapStream: ({ doStream, doGenerate, params }) => {
|
|
1978
2403
|
if (isToolChoiceActive(params)) {
|
|
1979
2404
|
return toolChoiceStream({
|
|
1980
2405
|
doGenerate,
|
|
1981
2406
|
options: extractOnErrorOption(params.providerOptions)
|
|
1982
2407
|
});
|
|
1983
|
-
} else {
|
|
1984
|
-
return wrapStream({
|
|
1985
|
-
protocol: resolvedProtocol,
|
|
1986
|
-
doStream,
|
|
1987
|
-
doGenerate,
|
|
1988
|
-
params
|
|
1989
|
-
});
|
|
1990
2408
|
}
|
|
2409
|
+
return wrapStream({
|
|
2410
|
+
protocol: resolvedProtocol,
|
|
2411
|
+
doStream,
|
|
2412
|
+
doGenerate,
|
|
2413
|
+
params
|
|
2414
|
+
});
|
|
1991
2415
|
},
|
|
1992
2416
|
wrapGenerate: async ({ doGenerate, params }) => wrapGenerate({
|
|
1993
2417
|
protocol: resolvedProtocol,
|
|
1994
2418
|
doGenerate,
|
|
1995
2419
|
params
|
|
1996
2420
|
}),
|
|
1997
|
-
transformParams: async ({
|
|
2421
|
+
transformParams: async ({ params }) => transformParams({
|
|
2422
|
+
protocol: resolvedProtocol,
|
|
2423
|
+
toolSystemPromptTemplate,
|
|
1998
2424
|
params
|
|
1999
|
-
})
|
|
2000
|
-
return transformParams({
|
|
2001
|
-
protocol: resolvedProtocol,
|
|
2002
|
-
toolSystemPromptTemplate,
|
|
2003
|
-
params
|
|
2004
|
-
});
|
|
2005
|
-
}
|
|
2425
|
+
})
|
|
2006
2426
|
};
|
|
2007
2427
|
}
|
|
2008
2428
|
|