@ai-sdk-tool/parser 2.1.6 → 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/README.md +2 -2
- package/dist/chunk-FOANBZRH.js +2514 -0
- package/dist/chunk-FOANBZRH.js.map +1 -0
- package/dist/community.cjs +2584 -0
- package/dist/community.cjs.map +1 -0
- package/dist/community.d.cts +20 -0
- package/dist/community.d.ts +20 -0
- package/dist/community.js +98 -0
- package/dist/community.js.map +1 -0
- package/dist/index.cjs +1376 -941
- 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 +32 -2037
- package/dist/index.js.map +1 -1
- package/package.json +20 -14
|
@@ -0,0 +1,2584 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/community/index.ts
|
|
21
|
+
var community_exports = {};
|
|
22
|
+
__export(community_exports, {
|
|
23
|
+
sijawaraConciseXmlToolMiddleware: () => sijawaraConciseXmlToolMiddleware,
|
|
24
|
+
sijawaraDetailedXmlToolMiddleware: () => sijawaraDetailedXmlToolMiddleware
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(community_exports);
|
|
27
|
+
|
|
28
|
+
// src/protocols/dummy-protocol.ts
|
|
29
|
+
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
30
|
+
|
|
31
|
+
// src/protocols/json-mix-protocol.ts
|
|
32
|
+
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
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
|
+
|
|
153
|
+
// src/utils/dynamic-tool-schema.ts
|
|
154
|
+
function createDynamicIfThenElseSchema(tools) {
|
|
155
|
+
let currentSchema = {};
|
|
156
|
+
const toolNames = [];
|
|
157
|
+
for (let i = tools.length - 1; i >= 0; i -= 1) {
|
|
158
|
+
const tool = tools[i];
|
|
159
|
+
if (tool.type === "provider-defined") {
|
|
160
|
+
throw new Error(
|
|
161
|
+
"Provider-defined tools are not supported by this middleware. Please use custom tools."
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
toolNames.unshift(tool.name);
|
|
165
|
+
const toolCondition = {
|
|
166
|
+
if: {
|
|
167
|
+
properties: {
|
|
168
|
+
name: {
|
|
169
|
+
const: tool.name
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
required: ["name"]
|
|
173
|
+
},
|
|
174
|
+
// biome-ignore lint/suspicious/noThenProperty: JSON Schema uses 'then' as a keyword
|
|
175
|
+
then: {
|
|
176
|
+
properties: {
|
|
177
|
+
name: {
|
|
178
|
+
const: tool.name
|
|
179
|
+
},
|
|
180
|
+
arguments: tool.inputSchema
|
|
181
|
+
},
|
|
182
|
+
required: ["name", "arguments"]
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
if (Object.keys(currentSchema).length > 0) {
|
|
186
|
+
toolCondition.else = currentSchema;
|
|
187
|
+
}
|
|
188
|
+
currentSchema = toolCondition;
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
type: "object",
|
|
192
|
+
// Explicitly specify type as "object"
|
|
193
|
+
properties: {
|
|
194
|
+
name: {
|
|
195
|
+
type: "string",
|
|
196
|
+
description: "Name of the tool to call",
|
|
197
|
+
enum: toolNames
|
|
198
|
+
},
|
|
199
|
+
arguments: {
|
|
200
|
+
type: "object",
|
|
201
|
+
// By default, arguments is also specified as object type
|
|
202
|
+
description: "Argument object to be passed to the tool"
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
required: ["name", "arguments"],
|
|
206
|
+
...currentSchema
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/utils/get-potential-start-index.ts
|
|
211
|
+
function getPotentialStartIndex(text, searchedText) {
|
|
212
|
+
if (searchedText.length === 0) {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
const directIndex = text.indexOf(searchedText);
|
|
216
|
+
if (directIndex !== -1) {
|
|
217
|
+
return directIndex;
|
|
218
|
+
}
|
|
219
|
+
for (let i = text.length - 1; i >= 0; i -= 1) {
|
|
220
|
+
const suffix = text.substring(i);
|
|
221
|
+
if (searchedText.startsWith(suffix)) {
|
|
222
|
+
return i;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
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
|
+
|
|
267
|
+
// src/utils/regex.ts
|
|
268
|
+
function escapeRegExp(literal) {
|
|
269
|
+
return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/utils/robust-json.ts
|
|
273
|
+
var robust_json_exports = {};
|
|
274
|
+
__export(robust_json_exports, {
|
|
275
|
+
parse: () => parse,
|
|
276
|
+
stringify: () => stringify,
|
|
277
|
+
transform: () => transform
|
|
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_\-+.*?!|&%^/#\\]+/;
|
|
294
|
+
function some(array, f) {
|
|
295
|
+
let acc = false;
|
|
296
|
+
for (let i = 0; i < array.length; i += 1) {
|
|
297
|
+
const result = f(array[i], i, array);
|
|
298
|
+
acc = result === void 0 ? false : result;
|
|
299
|
+
if (acc) {
|
|
300
|
+
return acc;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return acc;
|
|
304
|
+
}
|
|
305
|
+
function makeLexer(tokenSpecs) {
|
|
306
|
+
return (contents) => {
|
|
307
|
+
const tokens = [];
|
|
308
|
+
let line = 1;
|
|
309
|
+
let remainingContents = contents;
|
|
310
|
+
function findToken() {
|
|
311
|
+
const result = some(tokenSpecs, (tokenSpec) => {
|
|
312
|
+
const m = tokenSpec.re.exec(remainingContents);
|
|
313
|
+
if (m) {
|
|
314
|
+
const raw = m[0];
|
|
315
|
+
remainingContents = remainingContents.slice(raw.length);
|
|
316
|
+
return {
|
|
317
|
+
raw,
|
|
318
|
+
matched: tokenSpec.f(m)
|
|
319
|
+
// Process the match using the spec's function
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
return;
|
|
323
|
+
});
|
|
324
|
+
return result === false ? void 0 : result;
|
|
325
|
+
}
|
|
326
|
+
while (remainingContents !== "") {
|
|
327
|
+
const matched = findToken();
|
|
328
|
+
if (!matched) {
|
|
329
|
+
const err = new SyntaxError(
|
|
330
|
+
`Unexpected character: ${remainingContents[0]}; input: ${remainingContents.substr(
|
|
331
|
+
0,
|
|
332
|
+
100
|
|
333
|
+
)}`
|
|
334
|
+
);
|
|
335
|
+
err.line = line;
|
|
336
|
+
throw err;
|
|
337
|
+
}
|
|
338
|
+
const tokenWithLine = matched.matched;
|
|
339
|
+
tokenWithLine.line = line;
|
|
340
|
+
line += matched.raw.replace(/[^\n]/g, "").length;
|
|
341
|
+
tokens.push(tokenWithLine);
|
|
342
|
+
}
|
|
343
|
+
return tokens;
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
function fStringSingle(m) {
|
|
347
|
+
const content = m[1].replace(
|
|
348
|
+
/([^'\\]|\\['bnrtf\\]|\\u[0-9a-fA-F]{4})/g,
|
|
349
|
+
(mm) => {
|
|
350
|
+
if (mm === '"') {
|
|
351
|
+
return '\\"';
|
|
352
|
+
}
|
|
353
|
+
if (mm === "\\'") {
|
|
354
|
+
return "'";
|
|
355
|
+
}
|
|
356
|
+
return mm;
|
|
357
|
+
}
|
|
358
|
+
);
|
|
359
|
+
const match = `"${content}"`;
|
|
360
|
+
return {
|
|
361
|
+
type: "string",
|
|
362
|
+
match,
|
|
363
|
+
// The transformed, double-quoted string representation
|
|
364
|
+
// Use JSON.parse on the transformed string to handle escape sequences correctly
|
|
365
|
+
value: JSON.parse(match)
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
function fStringDouble(m) {
|
|
369
|
+
return {
|
|
370
|
+
type: "string",
|
|
371
|
+
match: m[0],
|
|
372
|
+
// The raw matched string (including quotes)
|
|
373
|
+
value: JSON.parse(m[0])
|
|
374
|
+
// Use JSON.parse to handle escapes and get the value
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
function fIdentifier(m) {
|
|
378
|
+
const value = m[0];
|
|
379
|
+
const match = '"' + value.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + // Escape backslashes and quotes
|
|
380
|
+
'"';
|
|
381
|
+
return {
|
|
382
|
+
type: "string",
|
|
383
|
+
// Treat identifiers as strings
|
|
384
|
+
value,
|
|
385
|
+
// The original identifier name
|
|
386
|
+
match
|
|
387
|
+
// The double-quoted string representation
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
function fComment(m) {
|
|
391
|
+
const match = m[0].replace(
|
|
392
|
+
/./g,
|
|
393
|
+
(c) => WHITESPACE_TEST_REGEX.test(c) ? c : " "
|
|
394
|
+
);
|
|
395
|
+
return {
|
|
396
|
+
type: " ",
|
|
397
|
+
// Represent comments as whitespace tokens
|
|
398
|
+
match,
|
|
399
|
+
// String containing original newlines and spaces for other chars
|
|
400
|
+
value: void 0
|
|
401
|
+
// Comments don't have a semantic value
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
function fNumber(m) {
|
|
405
|
+
return {
|
|
406
|
+
type: "number",
|
|
407
|
+
match: m[0],
|
|
408
|
+
// The raw matched number string
|
|
409
|
+
value: Number.parseFloat(m[0])
|
|
410
|
+
// Convert string to number
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
function fKeyword(m) {
|
|
414
|
+
let value;
|
|
415
|
+
switch (m[0]) {
|
|
416
|
+
case "null":
|
|
417
|
+
value = null;
|
|
418
|
+
break;
|
|
419
|
+
case "true":
|
|
420
|
+
value = true;
|
|
421
|
+
break;
|
|
422
|
+
case "false":
|
|
423
|
+
value = false;
|
|
424
|
+
break;
|
|
425
|
+
default:
|
|
426
|
+
throw new Error(`Unexpected keyword: ${m[0]}`);
|
|
427
|
+
}
|
|
428
|
+
return {
|
|
429
|
+
type: "atom",
|
|
430
|
+
// Use 'atom' type for these literals
|
|
431
|
+
match: m[0],
|
|
432
|
+
// The raw matched keyword
|
|
433
|
+
value
|
|
434
|
+
// The corresponding JavaScript value
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
function makeTokenSpecs(relaxed) {
|
|
438
|
+
function f(type) {
|
|
439
|
+
return (m) => {
|
|
440
|
+
return { type, match: m[0], value: void 0 };
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
let tokenSpecs = [
|
|
444
|
+
{ re: WHITESPACE_REGEX, f: f(" ") },
|
|
445
|
+
// Whitespace
|
|
446
|
+
{ re: OBJECT_START_REGEX, f: f("{") },
|
|
447
|
+
// Object start
|
|
448
|
+
{ re: OBJECT_END_REGEX, f: f("}") },
|
|
449
|
+
// Object end
|
|
450
|
+
{ re: ARRAY_START_REGEX, f: f("[") },
|
|
451
|
+
// Array start
|
|
452
|
+
{ re: ARRAY_END_REGEX, f: f("]") },
|
|
453
|
+
// Array end
|
|
454
|
+
{ re: COMMA_REGEX, f: f(",") },
|
|
455
|
+
// Comma separator
|
|
456
|
+
{ re: COLON_REGEX, f: f(":") },
|
|
457
|
+
// Key-value separator
|
|
458
|
+
{ re: KEYWORD_REGEX, f: fKeyword },
|
|
459
|
+
// Keywords
|
|
460
|
+
// Number: optional sign, digits, optional decimal part, optional exponent
|
|
461
|
+
{ re: NUMBER_REGEX, f: fNumber },
|
|
462
|
+
// String: double-quoted, handles escapes
|
|
463
|
+
{ re: STRING_DOUBLE_REGEX, f: fStringDouble }
|
|
464
|
+
];
|
|
465
|
+
if (relaxed) {
|
|
466
|
+
tokenSpecs = tokenSpecs.concat([
|
|
467
|
+
// Single-quoted strings
|
|
468
|
+
{
|
|
469
|
+
re: STRING_SINGLE_REGEX,
|
|
470
|
+
f: fStringSingle
|
|
471
|
+
},
|
|
472
|
+
// Single-line comments (// ...)
|
|
473
|
+
{ re: COMMENT_SINGLE_REGEX, f: fComment },
|
|
474
|
+
// Multi-line comments (/* ... */)
|
|
475
|
+
{ re: COMMENT_MULTI_REGEX, f: fComment },
|
|
476
|
+
// Unquoted identifiers (treated as strings)
|
|
477
|
+
// Allows letters, numbers, _, -, +, ., *, ?, !, |, &, %, ^, /, #, \
|
|
478
|
+
{ re: IDENTIFIER_REGEX, f: fIdentifier }
|
|
479
|
+
// Note: The order matters here. Identifiers are checked after keywords/numbers.
|
|
480
|
+
]);
|
|
481
|
+
}
|
|
482
|
+
return tokenSpecs;
|
|
483
|
+
}
|
|
484
|
+
var lexer = makeLexer(makeTokenSpecs(true));
|
|
485
|
+
var strictLexer = makeLexer(makeTokenSpecs(false));
|
|
486
|
+
function previousNWSToken(tokens, index) {
|
|
487
|
+
let currentIndex = index;
|
|
488
|
+
for (; currentIndex >= 0; currentIndex -= 1) {
|
|
489
|
+
if (tokens[currentIndex].type !== " ") {
|
|
490
|
+
return currentIndex;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
function stripTrailingComma(tokens) {
|
|
496
|
+
const res = [];
|
|
497
|
+
tokens.forEach((token, index) => {
|
|
498
|
+
if (index > 0 && (token.type === "]" || token.type === "}")) {
|
|
499
|
+
const prevNWSTokenIndex = previousNWSToken(res, res.length - 1);
|
|
500
|
+
if (prevNWSTokenIndex !== void 0 && res[prevNWSTokenIndex].type === ",") {
|
|
501
|
+
const preCommaIndex = previousNWSToken(res, prevNWSTokenIndex - 1);
|
|
502
|
+
if (preCommaIndex !== void 0 && res[preCommaIndex].type !== "[" && res[preCommaIndex].type !== "{") {
|
|
503
|
+
res[prevNWSTokenIndex] = {
|
|
504
|
+
type: " ",
|
|
505
|
+
match: " ",
|
|
506
|
+
// Represent as a single space
|
|
507
|
+
value: void 0,
|
|
508
|
+
// Whitespace has no value
|
|
509
|
+
line: res[prevNWSTokenIndex].line
|
|
510
|
+
// Preserve original line number
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
res.push(token);
|
|
516
|
+
});
|
|
517
|
+
return res;
|
|
518
|
+
}
|
|
519
|
+
function transform(text) {
|
|
520
|
+
let tokens = lexer(text);
|
|
521
|
+
tokens = stripTrailingComma(tokens);
|
|
522
|
+
return tokens.reduce((str, token) => str + token.match, "");
|
|
523
|
+
}
|
|
524
|
+
function popToken(tokens, state) {
|
|
525
|
+
var _a, _b;
|
|
526
|
+
const token = tokens[state.pos];
|
|
527
|
+
state.pos += 1;
|
|
528
|
+
if (!token) {
|
|
529
|
+
const lastLine = tokens.length !== 0 ? (_b = (_a = tokens.at(-1)) == null ? void 0 : _a.line) != null ? _b : 1 : 1;
|
|
530
|
+
return { type: "eof", match: "", value: void 0, line: lastLine };
|
|
531
|
+
}
|
|
532
|
+
return token;
|
|
533
|
+
}
|
|
534
|
+
function strToken(token) {
|
|
535
|
+
switch (token.type) {
|
|
536
|
+
case "atom":
|
|
537
|
+
case "string":
|
|
538
|
+
case "number":
|
|
539
|
+
return `${token.type} ${token.match}`;
|
|
540
|
+
case "eof":
|
|
541
|
+
return "end-of-file";
|
|
542
|
+
default:
|
|
543
|
+
return `'${token.type}'`;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
function skipColon(tokens, state) {
|
|
547
|
+
const colon = popToken(tokens, state);
|
|
548
|
+
if (colon.type !== ":") {
|
|
549
|
+
const message = `Unexpected token: ${strToken(colon)}, expected ':'`;
|
|
550
|
+
if (state.tolerant) {
|
|
551
|
+
state.warnings.push({
|
|
552
|
+
message,
|
|
553
|
+
line: colon.line
|
|
554
|
+
});
|
|
555
|
+
state.pos -= 1;
|
|
556
|
+
} else {
|
|
557
|
+
const err = new SyntaxError(message);
|
|
558
|
+
err.line = colon.line;
|
|
559
|
+
throw err;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
function skipPunctuation(tokens, state, valid) {
|
|
564
|
+
const punctuation = [",", ":", "]", "}"];
|
|
565
|
+
let token = popToken(tokens, state);
|
|
566
|
+
while (true) {
|
|
567
|
+
if (valid == null ? void 0 : valid.includes(token.type)) {
|
|
568
|
+
return token;
|
|
569
|
+
}
|
|
570
|
+
if (token.type === "eof") {
|
|
571
|
+
return token;
|
|
572
|
+
}
|
|
573
|
+
if (punctuation.includes(token.type)) {
|
|
574
|
+
const message = `Unexpected token: ${strToken(
|
|
575
|
+
token
|
|
576
|
+
)}, expected '[', '{', number, string or atom`;
|
|
577
|
+
if (state.tolerant) {
|
|
578
|
+
state.warnings.push({
|
|
579
|
+
message,
|
|
580
|
+
line: token.line
|
|
581
|
+
});
|
|
582
|
+
token = popToken(tokens, state);
|
|
583
|
+
} else {
|
|
584
|
+
const err = new SyntaxError(message);
|
|
585
|
+
err.line = token.line;
|
|
586
|
+
throw err;
|
|
587
|
+
}
|
|
588
|
+
} else {
|
|
589
|
+
return token;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
function raiseError(state, token, message) {
|
|
594
|
+
if (state.tolerant) {
|
|
595
|
+
state.warnings.push({
|
|
596
|
+
message,
|
|
597
|
+
line: token.line
|
|
598
|
+
});
|
|
599
|
+
} else {
|
|
600
|
+
const err = new SyntaxError(message);
|
|
601
|
+
err.line = token.line;
|
|
602
|
+
throw err;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
function raiseUnexpected(state, token, expected) {
|
|
606
|
+
raiseError(
|
|
607
|
+
state,
|
|
608
|
+
token,
|
|
609
|
+
`Unexpected token: ${strToken(token)}, expected ${expected}`
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
function checkDuplicates(state, obj, token) {
|
|
613
|
+
const key = String(token.value);
|
|
614
|
+
if (!state.duplicate && Object.hasOwn(obj, key)) {
|
|
615
|
+
raiseError(state, token, `Duplicate key: ${key}`);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
function appendPair(state, obj, key, value) {
|
|
619
|
+
const finalValue = state.reviver ? state.reviver(key, value) : value;
|
|
620
|
+
if (finalValue !== void 0) {
|
|
621
|
+
obj[key] = finalValue;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
function parsePair(tokens, state, obj) {
|
|
625
|
+
let token = skipPunctuation(tokens, state, [":", "string", "number", "atom"]);
|
|
626
|
+
let value;
|
|
627
|
+
if (token.type !== "string") {
|
|
628
|
+
raiseUnexpected(state, token, "string key");
|
|
629
|
+
if (state.tolerant) {
|
|
630
|
+
switch (token.type) {
|
|
631
|
+
case ":":
|
|
632
|
+
token = {
|
|
633
|
+
type: "string",
|
|
634
|
+
value: "null",
|
|
635
|
+
match: '"null"',
|
|
636
|
+
line: token.line
|
|
637
|
+
};
|
|
638
|
+
state.pos -= 1;
|
|
639
|
+
break;
|
|
640
|
+
case "number":
|
|
641
|
+
// Use number as string key
|
|
642
|
+
case "atom":
|
|
643
|
+
token = {
|
|
644
|
+
type: "string",
|
|
645
|
+
value: String(token.value),
|
|
646
|
+
match: `"${token.value}"`,
|
|
647
|
+
line: token.line
|
|
648
|
+
};
|
|
649
|
+
break;
|
|
650
|
+
case "[":
|
|
651
|
+
// Assume missing key before an array
|
|
652
|
+
case "{":
|
|
653
|
+
state.pos -= 1;
|
|
654
|
+
value = parseAny(tokens, state);
|
|
655
|
+
checkDuplicates(state, obj, {
|
|
656
|
+
type: "string",
|
|
657
|
+
value: "null",
|
|
658
|
+
match: '"null"',
|
|
659
|
+
line: token.line
|
|
660
|
+
});
|
|
661
|
+
appendPair(state, obj, "null", value);
|
|
662
|
+
return;
|
|
663
|
+
// Finished parsing this "pair"
|
|
664
|
+
case "eof":
|
|
665
|
+
return;
|
|
666
|
+
// Cannot recover
|
|
667
|
+
default:
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
} else {
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
checkDuplicates(state, obj, token);
|
|
675
|
+
const key = String(token.value);
|
|
676
|
+
skipColon(tokens, state);
|
|
677
|
+
value = parseAny(tokens, state);
|
|
678
|
+
appendPair(state, obj, key, value);
|
|
679
|
+
}
|
|
680
|
+
function parseElement(tokens, state, arr) {
|
|
681
|
+
const key = arr.length;
|
|
682
|
+
const value = parseAny(tokens, state);
|
|
683
|
+
arr[key] = state.reviver ? state.reviver(String(key), value) : value;
|
|
684
|
+
}
|
|
685
|
+
function parseObject(tokens, state) {
|
|
686
|
+
const obj = {};
|
|
687
|
+
return parseMany(tokens, state, obj, {
|
|
688
|
+
skip: [":", "}"],
|
|
689
|
+
// Initially skip over colon or closing brace (for empty/tolerant cases)
|
|
690
|
+
elementParser: parsePair,
|
|
691
|
+
// Use parsePair to parse each key-value element
|
|
692
|
+
elementName: "string key",
|
|
693
|
+
// Expected element type for errors
|
|
694
|
+
endSymbol: "}"
|
|
695
|
+
// The closing token for an object
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
function parseArray(tokens, state) {
|
|
699
|
+
const arr = [];
|
|
700
|
+
return parseMany(tokens, state, arr, {
|
|
701
|
+
skip: ["]"],
|
|
702
|
+
// Initially skip over closing bracket (for empty/tolerant cases)
|
|
703
|
+
elementParser: parseElement,
|
|
704
|
+
// Use parseElement to parse each array item
|
|
705
|
+
elementName: "json value",
|
|
706
|
+
// Expected element type for errors
|
|
707
|
+
endSymbol: "]"
|
|
708
|
+
// The closing token for an array
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
function handleInvalidToken(token, state, opts, result) {
|
|
712
|
+
raiseUnexpected(state, token, `',' or '${opts.endSymbol}'`);
|
|
713
|
+
if (state.tolerant) {
|
|
714
|
+
if (token.type === "eof") {
|
|
715
|
+
return result;
|
|
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;
|
|
738
|
+
}
|
|
739
|
+
if (token.type === opts.endSymbol) {
|
|
740
|
+
return result;
|
|
741
|
+
}
|
|
742
|
+
state.pos -= 1;
|
|
743
|
+
opts.elementParser(tokens, state, result);
|
|
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;
|
|
752
|
+
}
|
|
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;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
function endChecks(tokens, state, ret) {
|
|
793
|
+
if (state.pos < tokens.length) {
|
|
794
|
+
if (state.tolerant) {
|
|
795
|
+
skipPunctuation(tokens, state);
|
|
796
|
+
}
|
|
797
|
+
if (state.pos < tokens.length) {
|
|
798
|
+
raiseError(
|
|
799
|
+
state,
|
|
800
|
+
tokens[state.pos],
|
|
801
|
+
`Unexpected token: ${strToken(tokens[state.pos])}, expected end-of-input`
|
|
802
|
+
);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
if (state.tolerant && state.warnings.length > 0) {
|
|
806
|
+
const message = state.warnings.length === 1 ? state.warnings[0].message : `${state.warnings.length} parse warnings`;
|
|
807
|
+
const err = new SyntaxError(message);
|
|
808
|
+
err.line = state.warnings[0].line;
|
|
809
|
+
err.warnings = state.warnings;
|
|
810
|
+
err.obj = ret;
|
|
811
|
+
throw err;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
function parseAny(tokens, state, end = false) {
|
|
815
|
+
const token = skipPunctuation(tokens, state);
|
|
816
|
+
let ret;
|
|
817
|
+
if (token.type === "eof") {
|
|
818
|
+
if (end) {
|
|
819
|
+
raiseUnexpected(state, token, "json value");
|
|
820
|
+
}
|
|
821
|
+
raiseUnexpected(state, token, "json value");
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
switch (token.type) {
|
|
825
|
+
case "{":
|
|
826
|
+
ret = parseObject(tokens, state);
|
|
827
|
+
break;
|
|
828
|
+
case "[":
|
|
829
|
+
ret = parseArray(tokens, state);
|
|
830
|
+
break;
|
|
831
|
+
case "string":
|
|
832
|
+
// String literal
|
|
833
|
+
case "number":
|
|
834
|
+
// Number literal
|
|
835
|
+
case "atom":
|
|
836
|
+
ret = token.value;
|
|
837
|
+
break;
|
|
838
|
+
default:
|
|
839
|
+
raiseUnexpected(state, token, "json value");
|
|
840
|
+
if (state.tolerant) {
|
|
841
|
+
ret = null;
|
|
842
|
+
} else {
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
if (end) {
|
|
847
|
+
ret = state.reviver ? state.reviver("", ret) : ret;
|
|
848
|
+
endChecks(tokens, state, ret);
|
|
849
|
+
}
|
|
850
|
+
return ret;
|
|
851
|
+
}
|
|
852
|
+
function normalizeParseOptions(optsOrReviver) {
|
|
853
|
+
var _a;
|
|
854
|
+
let options = {};
|
|
855
|
+
if (typeof optsOrReviver === "function") {
|
|
856
|
+
options.reviver = optsOrReviver;
|
|
857
|
+
} else if (optsOrReviver !== null && typeof optsOrReviver === "object") {
|
|
858
|
+
options = { ...optsOrReviver };
|
|
859
|
+
} else if (optsOrReviver !== void 0) {
|
|
860
|
+
throw new TypeError(
|
|
861
|
+
"Second argument must be a reviver function or an options object."
|
|
862
|
+
);
|
|
863
|
+
}
|
|
864
|
+
if (options.relaxed === void 0) {
|
|
865
|
+
if (options.warnings === true || options.tolerant === true) {
|
|
866
|
+
options.relaxed = true;
|
|
867
|
+
} else if (options.warnings === false && options.tolerant === false) {
|
|
868
|
+
options.relaxed = false;
|
|
869
|
+
} else {
|
|
870
|
+
options.relaxed = true;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
options.tolerant = options.tolerant || options.warnings;
|
|
874
|
+
options.duplicate = (_a = options.duplicate) != null ? _a : false;
|
|
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) {
|
|
888
|
+
const lexerToUse = options.relaxed ? lexer : strictLexer;
|
|
889
|
+
let tokens = lexerToUse(text);
|
|
890
|
+
if (options.relaxed) {
|
|
891
|
+
tokens = stripTrailingComma(tokens);
|
|
892
|
+
}
|
|
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);
|
|
916
|
+
}
|
|
917
|
+
return parseWithTransform(text, options);
|
|
918
|
+
}
|
|
919
|
+
function stringifyPair(obj, key) {
|
|
920
|
+
return `${JSON.stringify(key)}:${stringify(obj[key])}`;
|
|
921
|
+
}
|
|
922
|
+
function stringify(obj) {
|
|
923
|
+
const type = typeof obj;
|
|
924
|
+
if (type === "string" || type === "number" || type === "boolean" || obj === null) {
|
|
925
|
+
return JSON.stringify(obj);
|
|
926
|
+
}
|
|
927
|
+
if (type === "undefined") {
|
|
928
|
+
return "null";
|
|
929
|
+
}
|
|
930
|
+
if (Array.isArray(obj)) {
|
|
931
|
+
const elements = obj.map(stringify).join(",");
|
|
932
|
+
return `[${elements}]`;
|
|
933
|
+
}
|
|
934
|
+
if (type === "object") {
|
|
935
|
+
const keys = Object.keys(obj);
|
|
936
|
+
keys.sort();
|
|
937
|
+
const pairs = keys.map((key) => stringifyPair(obj, key)).join(",");
|
|
938
|
+
return `{${pairs}}`;
|
|
939
|
+
}
|
|
940
|
+
return "null";
|
|
941
|
+
}
|
|
942
|
+
|
|
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 });
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
function addTextSegment(text, processedElements) {
|
|
974
|
+
if (text.trim()) {
|
|
975
|
+
processedElements.push({ type: "text", text });
|
|
976
|
+
}
|
|
977
|
+
}
|
|
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;
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
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 = "";
|
|
1028
|
+
}
|
|
1029
|
+
function handleFinishChunk(state, controller, toolCallStart, chunk) {
|
|
1030
|
+
if (state.buffer.length > 0) {
|
|
1031
|
+
flushBuffer(state, controller, toolCallStart);
|
|
1032
|
+
}
|
|
1033
|
+
closeTextBlock(state, controller);
|
|
1034
|
+
emitIncompleteToolCall(state, controller, toolCallStart);
|
|
1035
|
+
controller.enqueue(chunk);
|
|
1036
|
+
}
|
|
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
|
+
}
|
|
1053
|
+
}
|
|
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
|
+
}
|
|
1084
|
+
}
|
|
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;
|
|
1094
|
+
}
|
|
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
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
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 = "";
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
var jsonMixProtocol = ({
|
|
1130
|
+
toolCallStart = "<tool_call>",
|
|
1131
|
+
toolCallEnd = "</tool_call>",
|
|
1132
|
+
toolResponseStart = "<tool_response>",
|
|
1133
|
+
toolResponseEnd = "</tool_response>"
|
|
1134
|
+
} = {}) => ({
|
|
1135
|
+
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
1136
|
+
const toolsForPrompt = (tools || []).filter((tool) => tool.type === "function").map((tool) => ({
|
|
1137
|
+
name: tool.name,
|
|
1138
|
+
description: tool.type === "function" && typeof tool.description === "string" ? tool.description : void 0,
|
|
1139
|
+
parameters: tool.inputSchema
|
|
1140
|
+
}));
|
|
1141
|
+
return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
|
|
1142
|
+
},
|
|
1143
|
+
formatToolCall(toolCall) {
|
|
1144
|
+
let args = {};
|
|
1145
|
+
try {
|
|
1146
|
+
args = JSON.parse(toolCall.input);
|
|
1147
|
+
} catch (e) {
|
|
1148
|
+
args = toolCall.input;
|
|
1149
|
+
}
|
|
1150
|
+
return `${toolCallStart}${JSON.stringify({
|
|
1151
|
+
name: toolCall.toolName,
|
|
1152
|
+
arguments: args
|
|
1153
|
+
})}${toolCallEnd}`;
|
|
1154
|
+
},
|
|
1155
|
+
formatToolResponse(toolResult) {
|
|
1156
|
+
return `${toolResponseStart}${JSON.stringify({
|
|
1157
|
+
toolName: toolResult.toolName,
|
|
1158
|
+
result: toolResult.output
|
|
1159
|
+
})}${toolResponseEnd}`;
|
|
1160
|
+
},
|
|
1161
|
+
parseGeneratedText({ text, options }) {
|
|
1162
|
+
const startEsc = escapeRegExp(toolCallStart);
|
|
1163
|
+
const endEsc = escapeRegExp(toolCallEnd);
|
|
1164
|
+
const toolCallRegex = new RegExp(
|
|
1165
|
+
`${startEsc}([\0-\uFFFF]*?)${endEsc}`,
|
|
1166
|
+
"gs"
|
|
1167
|
+
);
|
|
1168
|
+
const processedElements = [];
|
|
1169
|
+
let currentIndex = 0;
|
|
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);
|
|
1180
|
+
}
|
|
1181
|
+
if (currentIndex < text.length) {
|
|
1182
|
+
const remainingText = text.substring(currentIndex);
|
|
1183
|
+
addTextSegment(remainingText, processedElements);
|
|
1184
|
+
}
|
|
1185
|
+
return processedElements;
|
|
1186
|
+
},
|
|
1187
|
+
createStreamParser({ tools: _tools, options } = { tools: [] }) {
|
|
1188
|
+
const state = {
|
|
1189
|
+
isInsideToolCall: false,
|
|
1190
|
+
buffer: "",
|
|
1191
|
+
currentToolCallJson: "",
|
|
1192
|
+
currentTextId: null,
|
|
1193
|
+
hasEmittedTextStart: false
|
|
1194
|
+
};
|
|
1195
|
+
return new TransformStream({
|
|
1196
|
+
transform(chunk, controller) {
|
|
1197
|
+
if (chunk.type === "finish") {
|
|
1198
|
+
handleFinishChunk(state, controller, toolCallStart, chunk);
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
if (chunk.type !== "text-delta") {
|
|
1202
|
+
controller.enqueue(chunk);
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
state.buffer += chunk.delta;
|
|
1206
|
+
processBufferTags({
|
|
1207
|
+
state,
|
|
1208
|
+
controller,
|
|
1209
|
+
toolCallStart,
|
|
1210
|
+
toolCallEnd,
|
|
1211
|
+
options
|
|
1212
|
+
});
|
|
1213
|
+
handlePartialTag(state, controller, toolCallStart);
|
|
1214
|
+
}
|
|
1215
|
+
});
|
|
1216
|
+
},
|
|
1217
|
+
extractToolCallSegments({ text }) {
|
|
1218
|
+
const startEsc = escapeRegExp(toolCallStart);
|
|
1219
|
+
const endEsc = escapeRegExp(toolCallEnd);
|
|
1220
|
+
const regex = new RegExp(`${startEsc}([\0-\uFFFF]*?)${endEsc}`, "gs");
|
|
1221
|
+
const segments = [];
|
|
1222
|
+
let m = regex.exec(text);
|
|
1223
|
+
while (m != null) {
|
|
1224
|
+
segments.push(m[0]);
|
|
1225
|
+
m = regex.exec(text);
|
|
1226
|
+
}
|
|
1227
|
+
return segments;
|
|
1228
|
+
}
|
|
1229
|
+
});
|
|
1230
|
+
|
|
1231
|
+
// src/protocols/morph-xml-protocol.ts
|
|
1232
|
+
var import_provider_utils3 = require("@ai-sdk/provider-utils");
|
|
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
|
+
}
|
|
1513
|
+
var morphXmlProtocol = () => ({
|
|
1514
|
+
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
1515
|
+
const toolsForPrompt = (tools || []).map((tool) => ({
|
|
1516
|
+
name: tool.name,
|
|
1517
|
+
description: tool.description,
|
|
1518
|
+
parameters: (0, import_rxml.unwrapJsonSchema)(tool.inputSchema)
|
|
1519
|
+
}));
|
|
1520
|
+
return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
|
|
1521
|
+
},
|
|
1522
|
+
formatToolCall(toolCall) {
|
|
1523
|
+
let args = {};
|
|
1524
|
+
const inputValue = hasInputProperty(toolCall) ? toolCall.input : void 0;
|
|
1525
|
+
if (typeof inputValue === "string") {
|
|
1526
|
+
try {
|
|
1527
|
+
args = JSON.parse(inputValue);
|
|
1528
|
+
} catch (e) {
|
|
1529
|
+
args = inputValue;
|
|
1530
|
+
}
|
|
1531
|
+
} else {
|
|
1532
|
+
args = inputValue;
|
|
1533
|
+
}
|
|
1534
|
+
return (0, import_rxml.stringify)(toolCall.toolName, args, {
|
|
1535
|
+
suppressEmptyNode: false,
|
|
1536
|
+
format: false
|
|
1537
|
+
});
|
|
1538
|
+
},
|
|
1539
|
+
formatToolResponse(toolResult) {
|
|
1540
|
+
return (0, import_rxml.stringify)("tool_response", {
|
|
1541
|
+
tool_name: toolResult.toolName,
|
|
1542
|
+
result: toolResult.output
|
|
1543
|
+
});
|
|
1544
|
+
},
|
|
1545
|
+
parseGeneratedText({ text, tools, options }) {
|
|
1546
|
+
const toolNames = tools.map((t) => t.name).filter((name) => name != null);
|
|
1547
|
+
if (toolNames.length === 0) {
|
|
1548
|
+
return [{ type: "text", text }];
|
|
1549
|
+
}
|
|
1550
|
+
const processedElements = [];
|
|
1551
|
+
let currentIndex = 0;
|
|
1552
|
+
const toolCalls = findToolCalls(text, toolNames);
|
|
1553
|
+
for (const toolCall of toolCalls) {
|
|
1554
|
+
currentIndex = processTextBeforeToolCall(
|
|
1555
|
+
text,
|
|
1556
|
+
currentIndex,
|
|
1557
|
+
toolCall.startIndex,
|
|
1558
|
+
processedElements
|
|
1559
|
+
);
|
|
1560
|
+
processToolCall({ toolCall, tools, options, text, processedElements });
|
|
1561
|
+
currentIndex = toolCall.endIndex;
|
|
1562
|
+
}
|
|
1563
|
+
addRemainingText(text, currentIndex, processedElements);
|
|
1564
|
+
return processedElements;
|
|
1565
|
+
},
|
|
1566
|
+
createStreamParser({ tools, options }) {
|
|
1567
|
+
const toolNames = tools.map((t) => t.name).filter((name) => name != null);
|
|
1568
|
+
const maxStartTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n}>`.length)) : 0;
|
|
1569
|
+
let buffer = "";
|
|
1570
|
+
let currentToolCall = null;
|
|
1571
|
+
let currentTextId = null;
|
|
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);
|
|
1586
|
+
}
|
|
1587
|
+
controller.enqueue(chunk);
|
|
1588
|
+
return;
|
|
1589
|
+
}
|
|
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) {
|
|
1616
|
+
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1617
|
+
}
|
|
1618
|
+
};
|
|
1619
|
+
return new TransformStream({
|
|
1620
|
+
transform(chunk, controller) {
|
|
1621
|
+
processChunk(chunk, controller);
|
|
1622
|
+
},
|
|
1623
|
+
flush(controller) {
|
|
1624
|
+
flushBuffer2(controller);
|
|
1625
|
+
}
|
|
1626
|
+
});
|
|
1627
|
+
},
|
|
1628
|
+
extractToolCallSegments({ text, tools }) {
|
|
1629
|
+
const toolNames = tools.map((t) => t.name).filter(Boolean);
|
|
1630
|
+
if (toolNames.length === 0) {
|
|
1631
|
+
return [];
|
|
1632
|
+
}
|
|
1633
|
+
return findToolCalls(text, toolNames).map((tc) => tc.segment);
|
|
1634
|
+
}
|
|
1635
|
+
});
|
|
1636
|
+
function getToolSchema(tools, toolName) {
|
|
1637
|
+
var _a;
|
|
1638
|
+
return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
1639
|
+
}
|
|
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) {
|
|
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) {
|
|
1671
|
+
const toolCalls = [];
|
|
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;
|
|
1687
|
+
}
|
|
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
|
+
}
|
|
1697
|
+
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
// src/protocols/tool-call-protocol.ts
|
|
1701
|
+
function isProtocolFactory(protocol) {
|
|
1702
|
+
return typeof protocol === "function";
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
// src/generate-handler.ts
|
|
1706
|
+
var import_provider_utils4 = require("@ai-sdk/provider-utils");
|
|
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)
|
|
1720
|
+
}
|
|
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) {
|
|
1733
|
+
}
|
|
1734
|
+
} else if (getDebugLevel() === "parse") {
|
|
1735
|
+
logParsedSummary({ toolCalls: [toolCall], originalText: originText });
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
async function handleToolChoice(doGenerate, params) {
|
|
1739
|
+
var _a, _b, _c;
|
|
1740
|
+
const result = await doGenerate();
|
|
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);
|
|
1748
|
+
}
|
|
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) => {
|
|
1765
|
+
if (contentItem.type !== "text") {
|
|
1766
|
+
return [contentItem];
|
|
1767
|
+
}
|
|
1768
|
+
if (getDebugLevel() === "stream") {
|
|
1769
|
+
logRawChunk(contentItem.text);
|
|
1770
|
+
}
|
|
1771
|
+
return protocol.parseGeneratedText({
|
|
1772
|
+
text: contentItem.text,
|
|
1773
|
+
tools,
|
|
1774
|
+
options: {
|
|
1775
|
+
...extractOnErrorOption(providerOptions),
|
|
1776
|
+
...providerOptions == null ? void 0 : providerOptions.toolCallMiddleware
|
|
1777
|
+
}
|
|
1778
|
+
});
|
|
1779
|
+
});
|
|
1780
|
+
return parsed.map(
|
|
1781
|
+
(part) => fixToolCallWithSchema(part, tools)
|
|
1782
|
+
);
|
|
1783
|
+
}
|
|
1784
|
+
function logParsedContent(content) {
|
|
1785
|
+
if (getDebugLevel() === "stream") {
|
|
1786
|
+
for (const part of content) {
|
|
1787
|
+
logParsedChunk(part);
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
function computeDebugSummary(options) {
|
|
1792
|
+
var _a;
|
|
1793
|
+
const { result, newContent, protocol, tools, providerOptions } = options;
|
|
1794
|
+
const allText = result.content.filter(
|
|
1795
|
+
(c) => c.type === "text"
|
|
1796
|
+
).map((c) => c.text).join("\n\n");
|
|
1797
|
+
const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({ text: allText, tools }) : [];
|
|
1798
|
+
const originalText = segments.join("\n\n");
|
|
1799
|
+
const toolCalls = newContent.filter(
|
|
1800
|
+
(p) => p.type === "tool-call"
|
|
1801
|
+
);
|
|
1802
|
+
const dbg = (_a = providerOptions == null ? void 0 : providerOptions.toolCallMiddleware) == null ? void 0 : _a.debugSummary;
|
|
1803
|
+
if (dbg) {
|
|
1804
|
+
dbg.originalText = originalText;
|
|
1805
|
+
try {
|
|
1806
|
+
dbg.toolCalls = JSON.stringify(
|
|
1807
|
+
toolCalls.map((tc) => ({
|
|
1808
|
+
toolName: tc.toolName,
|
|
1809
|
+
input: tc.input
|
|
1810
|
+
}))
|
|
1811
|
+
);
|
|
1812
|
+
} catch (e) {
|
|
1813
|
+
}
|
|
1814
|
+
} else if (getDebugLevel() === "parse") {
|
|
1815
|
+
logParsedSummary({ toolCalls, originalText });
|
|
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
|
+
});
|
|
1848
|
+
return {
|
|
1849
|
+
...result,
|
|
1850
|
+
content: newContent
|
|
1851
|
+
};
|
|
1852
|
+
}
|
|
1853
|
+
function fixToolCallWithSchema(part, tools) {
|
|
1854
|
+
var _a;
|
|
1855
|
+
if (part.type !== "tool-call") {
|
|
1856
|
+
return part;
|
|
1857
|
+
}
|
|
1858
|
+
const tc = part;
|
|
1859
|
+
let args = {};
|
|
1860
|
+
if (typeof tc.input === "string") {
|
|
1861
|
+
try {
|
|
1862
|
+
args = JSON.parse(tc.input);
|
|
1863
|
+
} catch (e) {
|
|
1864
|
+
return part;
|
|
1865
|
+
}
|
|
1866
|
+
} else if (tc.input && typeof tc.input === "object") {
|
|
1867
|
+
args = tc.input;
|
|
1868
|
+
}
|
|
1869
|
+
const schema = (_a = tools.find((t) => t.name === tc.toolName)) == null ? void 0 : _a.inputSchema;
|
|
1870
|
+
const coerced = (0, import_rxml2.coerceBySchema)(args, schema);
|
|
1871
|
+
return {
|
|
1872
|
+
...part,
|
|
1873
|
+
input: JSON.stringify(coerced != null ? coerced : {})
|
|
1874
|
+
};
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
// src/stream-handler.ts
|
|
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
|
+
}
|
|
1942
|
+
async function wrapStream({
|
|
1943
|
+
protocol,
|
|
1944
|
+
doStream,
|
|
1945
|
+
doGenerate,
|
|
1946
|
+
params
|
|
1947
|
+
}) {
|
|
1948
|
+
var _a, _b, _c;
|
|
1949
|
+
if (isToolChoiceActive(params)) {
|
|
1950
|
+
return toolChoiceStream({
|
|
1951
|
+
doGenerate,
|
|
1952
|
+
options: extractOnErrorOption(params.providerOptions)
|
|
1953
|
+
});
|
|
1954
|
+
}
|
|
1955
|
+
const { stream, ...rest } = await doStream();
|
|
1956
|
+
const debugLevel = getDebugLevel();
|
|
1957
|
+
const tools = originalToolsSchema.decode(
|
|
1958
|
+
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools
|
|
1959
|
+
);
|
|
1960
|
+
const options = {
|
|
1961
|
+
...extractOnErrorOption(params.providerOptions),
|
|
1962
|
+
...(_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware
|
|
1963
|
+
};
|
|
1964
|
+
if (debugLevel === "off") {
|
|
1965
|
+
return {
|
|
1966
|
+
stream: stream.pipeThrough(
|
|
1967
|
+
protocol.createStreamParser({
|
|
1968
|
+
tools,
|
|
1969
|
+
options
|
|
1970
|
+
})
|
|
1971
|
+
),
|
|
1972
|
+
...rest
|
|
1973
|
+
};
|
|
1974
|
+
}
|
|
1975
|
+
if (debugLevel === "stream") {
|
|
1976
|
+
const withRawTap2 = stream.pipeThrough(
|
|
1977
|
+
new TransformStream(
|
|
1978
|
+
{
|
|
1979
|
+
transform(part, controller) {
|
|
1980
|
+
logRawChunk(part);
|
|
1981
|
+
controller.enqueue(part);
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
)
|
|
1985
|
+
);
|
|
1986
|
+
const parsed2 = withRawTap2.pipeThrough(
|
|
1987
|
+
protocol.createStreamParser({
|
|
1988
|
+
tools,
|
|
1989
|
+
options
|
|
1990
|
+
})
|
|
1991
|
+
);
|
|
1992
|
+
const withParsedTap = parsed2.pipeThrough(
|
|
1993
|
+
new TransformStream(
|
|
1994
|
+
{
|
|
1995
|
+
transform(part, controller) {
|
|
1996
|
+
logParsedChunk(part);
|
|
1997
|
+
controller.enqueue(part);
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
)
|
|
2001
|
+
);
|
|
2002
|
+
return {
|
|
2003
|
+
stream: withParsedTap,
|
|
2004
|
+
...rest
|
|
2005
|
+
};
|
|
2006
|
+
}
|
|
2007
|
+
let fullRawText = "";
|
|
2008
|
+
const withRawTap = stream.pipeThrough(
|
|
2009
|
+
new TransformStream({
|
|
2010
|
+
transform(part, controller) {
|
|
2011
|
+
if (part.type === "text-delta") {
|
|
2012
|
+
const delta = part.delta;
|
|
2013
|
+
if (typeof delta === "string" && delta.length > 0) {
|
|
2014
|
+
fullRawText += delta;
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
controller.enqueue(part);
|
|
2018
|
+
}
|
|
2019
|
+
})
|
|
2020
|
+
);
|
|
2021
|
+
const parsed = withRawTap.pipeThrough(
|
|
2022
|
+
protocol.createStreamParser({
|
|
2023
|
+
tools,
|
|
2024
|
+
options
|
|
2025
|
+
})
|
|
2026
|
+
);
|
|
2027
|
+
const withSummary = parsed.pipeThrough(
|
|
2028
|
+
createDebugSummaryTransform({
|
|
2029
|
+
protocol,
|
|
2030
|
+
fullRawText,
|
|
2031
|
+
tools,
|
|
2032
|
+
params
|
|
2033
|
+
})
|
|
2034
|
+
);
|
|
2035
|
+
return {
|
|
2036
|
+
stream: withSummary,
|
|
2037
|
+
...rest
|
|
2038
|
+
};
|
|
2039
|
+
}
|
|
2040
|
+
async function toolChoiceStream({
|
|
2041
|
+
doGenerate,
|
|
2042
|
+
options
|
|
2043
|
+
}) {
|
|
2044
|
+
var _a, _b, _c;
|
|
2045
|
+
const result = await doGenerate();
|
|
2046
|
+
let toolJson = {};
|
|
2047
|
+
if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
|
|
2048
|
+
try {
|
|
2049
|
+
toolJson = JSON.parse(result.content[0].text);
|
|
2050
|
+
} catch (error) {
|
|
2051
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
2052
|
+
options,
|
|
2053
|
+
"Failed to parse toolChoice JSON from streamed model output",
|
|
2054
|
+
{
|
|
2055
|
+
text: result.content[0].text,
|
|
2056
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2057
|
+
}
|
|
2058
|
+
);
|
|
2059
|
+
toolJson = {};
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
const toolCallChunk = {
|
|
2063
|
+
type: "tool-call",
|
|
2064
|
+
toolCallId: (0, import_provider_utils5.generateId)(),
|
|
2065
|
+
toolName: toolJson.name || "unknown",
|
|
2066
|
+
input: JSON.stringify(toolJson.arguments || {})
|
|
2067
|
+
};
|
|
2068
|
+
const finishChunk = {
|
|
2069
|
+
type: "finish",
|
|
2070
|
+
usage: (result == null ? void 0 : result.usage) || // TODO: If possible, try to return a certain amount of LLM usage.
|
|
2071
|
+
{
|
|
2072
|
+
inputTokens: 0,
|
|
2073
|
+
outputTokens: 0,
|
|
2074
|
+
totalTokens: 0
|
|
2075
|
+
},
|
|
2076
|
+
finishReason: "tool-calls"
|
|
2077
|
+
};
|
|
2078
|
+
const stream = new ReadableStream({
|
|
2079
|
+
start(controller) {
|
|
2080
|
+
controller.enqueue(toolCallChunk);
|
|
2081
|
+
controller.enqueue(finishChunk);
|
|
2082
|
+
controller.close();
|
|
2083
|
+
}
|
|
2084
|
+
});
|
|
2085
|
+
const debugLevel = getDebugLevel();
|
|
2086
|
+
const firstText = ((_c = result == null ? void 0 : result.content) == null ? void 0 : _c[0]) && result.content[0].type === "text" && result.content[0].text || "";
|
|
2087
|
+
const streamWithSummary = debugLevel === "parse" ? stream.pipeThrough(
|
|
2088
|
+
new TransformStream({
|
|
2089
|
+
transform(part, controller) {
|
|
2090
|
+
if (part.type === "finish") {
|
|
2091
|
+
try {
|
|
2092
|
+
logParsedSummary({
|
|
2093
|
+
toolCalls: [toolCallChunk],
|
|
2094
|
+
originalText: typeof firstText === "string" ? firstText : ""
|
|
2095
|
+
});
|
|
2096
|
+
} catch (e) {
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
controller.enqueue(part);
|
|
2100
|
+
}
|
|
2101
|
+
})
|
|
2102
|
+
) : stream;
|
|
2103
|
+
return {
|
|
2104
|
+
request: (result == null ? void 0 : result.request) || {},
|
|
2105
|
+
response: (result == null ? void 0 : result.response) || {},
|
|
2106
|
+
stream: streamWithSummary
|
|
2107
|
+
};
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
// src/transform-handler.ts
|
|
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 [
|
|
2125
|
+
{
|
|
2126
|
+
role: "system",
|
|
2127
|
+
content: systemPrompt
|
|
2128
|
+
},
|
|
2129
|
+
...processedPrompt
|
|
2130
|
+
];
|
|
2131
|
+
}
|
|
2132
|
+
function buildBaseReturnParams(params, finalPrompt, functionTools) {
|
|
2133
|
+
return {
|
|
2134
|
+
...params,
|
|
2135
|
+
prompt: finalPrompt,
|
|
2136
|
+
tools: [],
|
|
2137
|
+
toolChoice: void 0,
|
|
2138
|
+
providerOptions: {
|
|
2139
|
+
...params.providerOptions || {},
|
|
2140
|
+
toolCallMiddleware: {
|
|
2141
|
+
...params.providerOptions && typeof params.providerOptions === "object" && params.providerOptions.toolCallMiddleware || {},
|
|
2142
|
+
originalTools: originalToolsSchema.encode(functionTools)
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
};
|
|
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) {
|
|
2167
|
+
throw new Error(
|
|
2168
|
+
"Provider-defined tools are not supported by this middleware. Please use custom tools."
|
|
2169
|
+
);
|
|
2170
|
+
}
|
|
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.`
|
|
2177
|
+
);
|
|
2178
|
+
}
|
|
2179
|
+
return {
|
|
2180
|
+
...baseReturnParams,
|
|
2181
|
+
responseFormat: {
|
|
2182
|
+
type: "json",
|
|
2183
|
+
schema: {
|
|
2184
|
+
type: "object",
|
|
2185
|
+
properties: {
|
|
2186
|
+
name: {
|
|
2187
|
+
const: selectedTool.name
|
|
2188
|
+
},
|
|
2189
|
+
arguments: selectedTool.inputSchema
|
|
2190
|
+
},
|
|
2191
|
+
required: ["name", "arguments"]
|
|
2192
|
+
},
|
|
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 } : {}
|
|
2201
|
+
}
|
|
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
|
+
);
|
|
2210
|
+
}
|
|
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 }
|
|
2283
|
+
);
|
|
2284
|
+
newContent.push({
|
|
2285
|
+
type: "text",
|
|
2286
|
+
text: JSON.stringify(item)
|
|
2287
|
+
});
|
|
2288
|
+
}
|
|
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")
|
|
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
|
|
2319
|
+
};
|
|
2320
|
+
}
|
|
2321
|
+
if (message.role === "tool") {
|
|
2322
|
+
return processToolMessage(message.content, resolvedProtocol);
|
|
2323
|
+
}
|
|
2324
|
+
return message;
|
|
2325
|
+
}
|
|
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
|
|
2350
|
+
}
|
|
2351
|
+
]
|
|
2352
|
+
};
|
|
2353
|
+
}
|
|
2354
|
+
function condenseTextContent(processedPrompt) {
|
|
2355
|
+
for (let i = 0; i < processedPrompt.length; i += 1) {
|
|
2356
|
+
const msg = processedPrompt[i];
|
|
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);
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
return processedPrompt;
|
|
2367
|
+
}
|
|
2368
|
+
function mergeConsecutiveUserMessages(processedPrompt) {
|
|
2369
|
+
for (let i = processedPrompt.length - 1; i > 0; i -= 1) {
|
|
2370
|
+
const current = processedPrompt[i];
|
|
2371
|
+
const prev = processedPrompt[i - 1];
|
|
2372
|
+
if (current.role === "user" && prev.role === "user") {
|
|
2373
|
+
const prevContent = prev.content.map((c) => c.type === "text" ? c.text : "").join("\n");
|
|
2374
|
+
const currentContent = current.content.map((c) => c.type === "text" ? c.text : "").join("\n");
|
|
2375
|
+
processedPrompt[i - 1] = {
|
|
2376
|
+
role: "user",
|
|
2377
|
+
content: [{ type: "text", text: `${prevContent}
|
|
2378
|
+
${currentContent}` }]
|
|
2379
|
+
};
|
|
2380
|
+
processedPrompt.splice(i, 1);
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
return processedPrompt;
|
|
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
|
+
}
|
|
2393
|
+
|
|
2394
|
+
// src/tool-call-middleware.ts
|
|
2395
|
+
function createToolMiddleware({
|
|
2396
|
+
protocol,
|
|
2397
|
+
toolSystemPromptTemplate
|
|
2398
|
+
}) {
|
|
2399
|
+
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
2400
|
+
return {
|
|
2401
|
+
specificationVersion: "v3",
|
|
2402
|
+
wrapStream: ({ doStream, doGenerate, params }) => {
|
|
2403
|
+
if (isToolChoiceActive(params)) {
|
|
2404
|
+
return toolChoiceStream({
|
|
2405
|
+
doGenerate,
|
|
2406
|
+
options: extractOnErrorOption(params.providerOptions)
|
|
2407
|
+
});
|
|
2408
|
+
}
|
|
2409
|
+
return wrapStream({
|
|
2410
|
+
protocol: resolvedProtocol,
|
|
2411
|
+
doStream,
|
|
2412
|
+
doGenerate,
|
|
2413
|
+
params
|
|
2414
|
+
});
|
|
2415
|
+
},
|
|
2416
|
+
wrapGenerate: async ({ doGenerate, params }) => wrapGenerate({
|
|
2417
|
+
protocol: resolvedProtocol,
|
|
2418
|
+
doGenerate,
|
|
2419
|
+
params
|
|
2420
|
+
}),
|
|
2421
|
+
transformParams: async ({ params }) => transformParams({
|
|
2422
|
+
protocol: resolvedProtocol,
|
|
2423
|
+
toolSystemPromptTemplate,
|
|
2424
|
+
params
|
|
2425
|
+
})
|
|
2426
|
+
};
|
|
2427
|
+
}
|
|
2428
|
+
|
|
2429
|
+
// src/index.ts
|
|
2430
|
+
var gemmaToolMiddleware = createToolMiddleware({
|
|
2431
|
+
protocol: jsonMixProtocol(
|
|
2432
|
+
// Customize the tool call delimiters to use markdown code fences
|
|
2433
|
+
{
|
|
2434
|
+
toolCallStart: "```tool_call\n",
|
|
2435
|
+
// TODO: Support specifying multiple possible tags,
|
|
2436
|
+
// e.g., for gemma, it would be nice to be able to set both `` and ``` at the same time.
|
|
2437
|
+
toolCallEnd: "\n```",
|
|
2438
|
+
toolResponseStart: "```tool_response\n",
|
|
2439
|
+
toolResponseEnd: "\n```"
|
|
2440
|
+
}
|
|
2441
|
+
),
|
|
2442
|
+
toolSystemPromptTemplate(tools) {
|
|
2443
|
+
return `You have access to functions. If you decide to invoke any of the function(s),
|
|
2444
|
+
you MUST put it in the format of markdown code fence block with the language name of tool_call , e.g.
|
|
2445
|
+
\`\`\`tool_call
|
|
2446
|
+
{'name': <function-name>, 'arguments': <args-dict>}
|
|
2447
|
+
\`\`\`
|
|
2448
|
+
You SHOULD NOT include any other text in the response if you call a function
|
|
2449
|
+
${tools}`;
|
|
2450
|
+
}
|
|
2451
|
+
});
|
|
2452
|
+
var hermesToolMiddleware = createToolMiddleware({
|
|
2453
|
+
protocol: jsonMixProtocol,
|
|
2454
|
+
toolSystemPromptTemplate(tools) {
|
|
2455
|
+
return `You are a function calling AI model.
|
|
2456
|
+
You are provided with function signatures within <tools></tools> XML tags.
|
|
2457
|
+
You may call one or more functions to assist with the user query.
|
|
2458
|
+
Don't make assumptions about what values to plug into functions.
|
|
2459
|
+
Here are the available tools: <tools>${tools}</tools>
|
|
2460
|
+
Use the following pydantic model json schema for each tool call you will make: {"title": "FunctionCall", "type": "object", "properties": {"arguments": {"title": "Arguments", "type": "object"}, "name": {"title": "Name", "type": "string"}}, "required": ["arguments", "name"]}
|
|
2461
|
+
For each function call return a json object with function name and arguments within <tool_call></tool_call> XML tags as follows:
|
|
2462
|
+
<tool_call>
|
|
2463
|
+
{"name": "<function-name>", "arguments": <args-dict>}
|
|
2464
|
+
</tool_call>`;
|
|
2465
|
+
}
|
|
2466
|
+
});
|
|
2467
|
+
var morphXmlToolMiddleware = createToolMiddleware({
|
|
2468
|
+
protocol: morphXmlProtocol,
|
|
2469
|
+
toolSystemPromptTemplate(tools) {
|
|
2470
|
+
return `You are a function calling AI model.
|
|
2471
|
+
|
|
2472
|
+
Available functions are listed inside <tools></tools>.
|
|
2473
|
+
<tools>${tools}</tools>
|
|
2474
|
+
|
|
2475
|
+
# Rules
|
|
2476
|
+
- Use exactly one XML element whose tag name is the function name.
|
|
2477
|
+
- Put each parameter as a child element.
|
|
2478
|
+
- Values must follow the schema exactly (numbers, arrays, objects, enums \u2192 copy as-is).
|
|
2479
|
+
- Do not add or remove functions or parameters.
|
|
2480
|
+
- Each required parameter must appear once.
|
|
2481
|
+
- Output nothing before or after the function call.
|
|
2482
|
+
|
|
2483
|
+
# Example
|
|
2484
|
+
<get_weather>
|
|
2485
|
+
<location>New York</location>
|
|
2486
|
+
<unit>celsius</unit>
|
|
2487
|
+
</get_weather>`;
|
|
2488
|
+
}
|
|
2489
|
+
});
|
|
2490
|
+
|
|
2491
|
+
// src/community/index.ts
|
|
2492
|
+
var sijawaraDetailedXmlToolMiddleware = createToolMiddleware({
|
|
2493
|
+
protocol: morphXmlProtocol,
|
|
2494
|
+
toolSystemPromptTemplate(tools) {
|
|
2495
|
+
return `You have access to callable functions (tools).
|
|
2496
|
+
Tool list/context:
|
|
2497
|
+
${tools}
|
|
2498
|
+
|
|
2499
|
+
===============================
|
|
2500
|
+
TOOL CALLING FORMAT
|
|
2501
|
+
===============================
|
|
2502
|
+
- Use the XML-like format for tool calls:
|
|
2503
|
+
<tool_name>
|
|
2504
|
+
<parameter_name>
|
|
2505
|
+
value
|
|
2506
|
+
</parameter_name>
|
|
2507
|
+
...
|
|
2508
|
+
</tool_name>
|
|
2509
|
+
|
|
2510
|
+
===============================
|
|
2511
|
+
ARRAY PARAMETERS
|
|
2512
|
+
===============================
|
|
2513
|
+
- For array/multiple values, repeat the parameter for each value.
|
|
2514
|
+
- Example:
|
|
2515
|
+
<send_messages>
|
|
2516
|
+
<recipient>
|
|
2517
|
+
alice@example.com
|
|
2518
|
+
</recipient>
|
|
2519
|
+
<recipient>
|
|
2520
|
+
bob@example.com
|
|
2521
|
+
</recipient>
|
|
2522
|
+
<message>
|
|
2523
|
+
Hello!
|
|
2524
|
+
</message>
|
|
2525
|
+
</send_messages>
|
|
2526
|
+
|
|
2527
|
+
===============================
|
|
2528
|
+
SINGLE VALUE PARAMETERS
|
|
2529
|
+
===============================
|
|
2530
|
+
- For single values, use one parameter block.
|
|
2531
|
+
- Example:
|
|
2532
|
+
<get_weather>
|
|
2533
|
+
<location>
|
|
2534
|
+
San Francisco
|
|
2535
|
+
</location>
|
|
2536
|
+
</get_weather>
|
|
2537
|
+
|
|
2538
|
+
===============================
|
|
2539
|
+
GENERAL RULES
|
|
2540
|
+
===============================
|
|
2541
|
+
- First line: tool (function) name in angle brackets.
|
|
2542
|
+
- Parameters: each on their own line, in angle brackets, with name and value.
|
|
2543
|
+
- Include all required parameters. If info is missing, ask the user.
|
|
2544
|
+
- Do NOT use JSON\u2014use only the specified XML-like format for tool calls.
|
|
2545
|
+
- If no call is needed, reply without a tool call.`;
|
|
2546
|
+
}
|
|
2547
|
+
});
|
|
2548
|
+
var sijawaraConciseXmlToolMiddleware = createToolMiddleware({
|
|
2549
|
+
protocol: morphXmlProtocol,
|
|
2550
|
+
toolSystemPromptTemplate(tools) {
|
|
2551
|
+
return `You have access to callable functions (tools).
|
|
2552
|
+
Tool list/context:
|
|
2553
|
+
${tools}
|
|
2554
|
+
|
|
2555
|
+
STRICT CALLING RULES:
|
|
2556
|
+
- Use the XML-like format for tool calls:
|
|
2557
|
+
|
|
2558
|
+
<tool_name>
|
|
2559
|
+
<parameter_name>
|
|
2560
|
+
value
|
|
2561
|
+
</parameter_name>
|
|
2562
|
+
...
|
|
2563
|
+
</tool_name>
|
|
2564
|
+
|
|
2565
|
+
- First line: the tool (function) name in angle brackets.
|
|
2566
|
+
- Parameters: each in their own angle brackets with name and value.
|
|
2567
|
+
- Include all required parameters. If info is missing, ask the user.
|
|
2568
|
+
- Do NOT use JSON. Use only the specified XML-like format.
|
|
2569
|
+
- If no call is needed, reply without a tool call.
|
|
2570
|
+
|
|
2571
|
+
Example:
|
|
2572
|
+
<get_weather>
|
|
2573
|
+
<location>
|
|
2574
|
+
San Francisco
|
|
2575
|
+
</location>
|
|
2576
|
+
</get_weather>`;
|
|
2577
|
+
}
|
|
2578
|
+
});
|
|
2579
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2580
|
+
0 && (module.exports = {
|
|
2581
|
+
sijawaraConciseXmlToolMiddleware,
|
|
2582
|
+
sijawaraDetailedXmlToolMiddleware
|
|
2583
|
+
});
|
|
2584
|
+
//# sourceMappingURL=community.cjs.map
|