@ai-sdk-tool/parser 3.0.0-canary.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-DFOXAWP6.js +1 -0
- package/dist/chunk-DFOXAWP6.js.map +1 -0
- package/dist/chunk-NOYHOQOL.js +2489 -0
- package/dist/chunk-NOYHOQOL.js.map +1 -0
- package/dist/chunk-QPJA5CS6.js +1289 -0
- package/dist/chunk-QPJA5CS6.js.map +1 -0
- package/dist/community.cjs +2665 -2493
- package/dist/community.cjs.map +1 -1
- package/dist/community.js +5 -2
- package/dist/community.js.map +1 -1
- package/dist/index.cjs +2691 -2485
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -132
- package/dist/index.d.ts +25 -132
- package/dist/index.js +19 -8
- package/dist/tool-call-protocol-Bn2CBcD-.d.cts +84 -0
- package/dist/tool-call-protocol-Bn2CBcD-.d.ts +84 -0
- package/dist/v5.cjs +2816 -0
- package/dist/v5.cjs.map +1 -0
- package/dist/v5.d.cts +14 -0
- package/dist/v5.d.ts +14 -0
- package/dist/v5.js +476 -0
- package/dist/v5.js.map +1 -0
- package/dist/{chunk-LB5ALTRD.js → v6.cjs} +1198 -1067
- package/dist/v6.cjs.map +1 -0
- package/dist/v6.d.cts +16 -0
- package/dist/v6.d.ts +16 -0
- package/dist/v6.js +16 -0
- package/dist/v6.js.map +1 -0
- package/package.json +23 -8
- package/dist/chunk-LB5ALTRD.js.map +0 -1
|
@@ -0,0 +1,1289 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createDynamicIfThenElseSchema,
|
|
3
|
+
extractOnErrorOption,
|
|
4
|
+
generateId,
|
|
5
|
+
getDebugLevel,
|
|
6
|
+
isProtocolFactory,
|
|
7
|
+
isToolCallContent,
|
|
8
|
+
isToolChoiceActive,
|
|
9
|
+
jsonMixProtocol,
|
|
10
|
+
logParsedChunk,
|
|
11
|
+
logParsedSummary,
|
|
12
|
+
logRawChunk,
|
|
13
|
+
morphXmlProtocol,
|
|
14
|
+
originalToolsSchema
|
|
15
|
+
} from "./chunk-NOYHOQOL.js";
|
|
16
|
+
|
|
17
|
+
// src/core/protocols/yaml-xml-protocol.ts
|
|
18
|
+
import { unwrapJsonSchema, stringify as xmlStringify } from "@ai-sdk-tool/rxml";
|
|
19
|
+
import YAML from "yaml";
|
|
20
|
+
var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
|
|
21
|
+
var WHITESPACE_REGEX = /\s/;
|
|
22
|
+
var LEADING_WHITESPACE_RE = /^(\s*)/;
|
|
23
|
+
function findClosingTagEnd(text, contentStart, toolName) {
|
|
24
|
+
let pos = contentStart;
|
|
25
|
+
let depth = 1;
|
|
26
|
+
while (pos < text.length) {
|
|
27
|
+
const ltIdx = text.indexOf("<", pos);
|
|
28
|
+
if (ltIdx === -1) {
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
const next = text[ltIdx + 1];
|
|
32
|
+
if (next === "/") {
|
|
33
|
+
const gtIdx = text.indexOf(">", ltIdx);
|
|
34
|
+
if (gtIdx === -1) {
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
let p = ltIdx + 2;
|
|
38
|
+
while (p < gtIdx && WHITESPACE_REGEX.test(text[p])) {
|
|
39
|
+
p++;
|
|
40
|
+
}
|
|
41
|
+
const nameStart = p;
|
|
42
|
+
while (p < gtIdx && NAME_CHAR_RE.test(text.charAt(p))) {
|
|
43
|
+
p++;
|
|
44
|
+
}
|
|
45
|
+
const name = text.slice(nameStart, p);
|
|
46
|
+
if (name === toolName) {
|
|
47
|
+
depth--;
|
|
48
|
+
if (depth === 0) {
|
|
49
|
+
return gtIdx + 1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
pos = gtIdx + 1;
|
|
53
|
+
} else if (next === "!" || next === "?") {
|
|
54
|
+
const gtIdx = text.indexOf(">", ltIdx);
|
|
55
|
+
pos = gtIdx === -1 ? text.length : gtIdx + 1;
|
|
56
|
+
} else {
|
|
57
|
+
let p = ltIdx + 1;
|
|
58
|
+
while (p < text.length && WHITESPACE_REGEX.test(text[p])) {
|
|
59
|
+
p++;
|
|
60
|
+
}
|
|
61
|
+
const nameStart = p;
|
|
62
|
+
while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
|
|
63
|
+
p++;
|
|
64
|
+
}
|
|
65
|
+
const name = text.slice(nameStart, p);
|
|
66
|
+
const gtIdx = text.indexOf(">", p);
|
|
67
|
+
if (gtIdx === -1) {
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
let r = gtIdx - 1;
|
|
71
|
+
while (r >= nameStart && WHITESPACE_REGEX.test(text[r])) {
|
|
72
|
+
r--;
|
|
73
|
+
}
|
|
74
|
+
const selfClosing = text[r] === "/";
|
|
75
|
+
if (name === toolName && !selfClosing) {
|
|
76
|
+
depth++;
|
|
77
|
+
}
|
|
78
|
+
pos = gtIdx + 1;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return -1;
|
|
82
|
+
}
|
|
83
|
+
function findEarliestTagPosition(openIdx, selfIdx) {
|
|
84
|
+
const hasSelf = selfIdx !== -1;
|
|
85
|
+
const hasOpen = openIdx !== -1;
|
|
86
|
+
if (hasSelf && (!hasOpen || selfIdx < openIdx)) {
|
|
87
|
+
return { tagStart: selfIdx, isSelfClosing: true };
|
|
88
|
+
}
|
|
89
|
+
return { tagStart: openIdx, isSelfClosing: false };
|
|
90
|
+
}
|
|
91
|
+
function collectToolCallsForName(text, toolName) {
|
|
92
|
+
const toolCalls = [];
|
|
93
|
+
let searchIndex = 0;
|
|
94
|
+
const selfTagRegex = new RegExp(`<${toolName}\\s*/>`, "g");
|
|
95
|
+
while (searchIndex < text.length) {
|
|
96
|
+
const startTag = `<${toolName}>`;
|
|
97
|
+
const openIdx = text.indexOf(startTag, searchIndex);
|
|
98
|
+
selfTagRegex.lastIndex = searchIndex;
|
|
99
|
+
const selfMatch = selfTagRegex.exec(text);
|
|
100
|
+
const selfIdx = selfMatch ? selfMatch.index : -1;
|
|
101
|
+
const selfTagLength = selfMatch ? selfMatch[0].length : 0;
|
|
102
|
+
if (openIdx === -1 && selfIdx === -1) {
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
const { tagStart, isSelfClosing } = findEarliestTagPosition(
|
|
106
|
+
openIdx,
|
|
107
|
+
selfIdx
|
|
108
|
+
);
|
|
109
|
+
if (isSelfClosing) {
|
|
110
|
+
const endIndex = tagStart + selfTagLength;
|
|
111
|
+
toolCalls.push({
|
|
112
|
+
toolName,
|
|
113
|
+
startIndex: tagStart,
|
|
114
|
+
endIndex,
|
|
115
|
+
content: ""
|
|
116
|
+
});
|
|
117
|
+
searchIndex = endIndex;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const contentStart = tagStart + startTag.length;
|
|
121
|
+
const fullTagEnd = findClosingTagEnd(text, contentStart, toolName);
|
|
122
|
+
if (fullTagEnd !== -1 && fullTagEnd > contentStart) {
|
|
123
|
+
const endTag = `</${toolName}>`;
|
|
124
|
+
const endTagStart = fullTagEnd - endTag.length;
|
|
125
|
+
const content = text.substring(contentStart, endTagStart);
|
|
126
|
+
toolCalls.push({
|
|
127
|
+
toolName,
|
|
128
|
+
startIndex: tagStart,
|
|
129
|
+
endIndex: fullTagEnd,
|
|
130
|
+
content
|
|
131
|
+
});
|
|
132
|
+
searchIndex = fullTagEnd;
|
|
133
|
+
} else {
|
|
134
|
+
searchIndex = contentStart;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return toolCalls;
|
|
138
|
+
}
|
|
139
|
+
function findToolCalls(text, toolNames) {
|
|
140
|
+
const toolCalls = toolNames.flatMap(
|
|
141
|
+
(toolName) => collectToolCallsForName(text, toolName)
|
|
142
|
+
);
|
|
143
|
+
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
144
|
+
}
|
|
145
|
+
function parseYamlContent(yamlContent, options) {
|
|
146
|
+
var _a, _b, _c;
|
|
147
|
+
let normalized = yamlContent;
|
|
148
|
+
if (normalized.startsWith("\n")) {
|
|
149
|
+
normalized = normalized.slice(1);
|
|
150
|
+
}
|
|
151
|
+
const lines = normalized.split("\n");
|
|
152
|
+
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
|
153
|
+
if (nonEmptyLines.length === 0) {
|
|
154
|
+
return {};
|
|
155
|
+
}
|
|
156
|
+
const minIndent = Math.min(
|
|
157
|
+
...nonEmptyLines.map((line) => {
|
|
158
|
+
const match = line.match(LEADING_WHITESPACE_RE);
|
|
159
|
+
return match ? match[1].length : 0;
|
|
160
|
+
})
|
|
161
|
+
);
|
|
162
|
+
if (minIndent > 0) {
|
|
163
|
+
normalized = lines.map((line) => line.slice(minIndent)).join("\n");
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
const doc = YAML.parseDocument(normalized);
|
|
167
|
+
if (doc.errors && doc.errors.length > 0) {
|
|
168
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "YAML parse error", {
|
|
169
|
+
errors: doc.errors.map((e) => e.message)
|
|
170
|
+
});
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
const result = doc.toJSON();
|
|
174
|
+
if (result === null) {
|
|
175
|
+
return {};
|
|
176
|
+
}
|
|
177
|
+
if (typeof result !== "object" || Array.isArray(result)) {
|
|
178
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
|
|
179
|
+
got: typeof result
|
|
180
|
+
});
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
return result;
|
|
184
|
+
} catch (error) {
|
|
185
|
+
(_c = options == null ? void 0 : options.onError) == null ? void 0 : _c.call(options, "Failed to parse YAML content", { error });
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function appendTextPart(processedElements, textPart) {
|
|
190
|
+
if (textPart.trim()) {
|
|
191
|
+
processedElements.push({
|
|
192
|
+
type: "text",
|
|
193
|
+
text: textPart
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function processToolCallMatch(text, tc, currentIndex, processedElements, options) {
|
|
198
|
+
var _a;
|
|
199
|
+
if (tc.startIndex < currentIndex) {
|
|
200
|
+
return currentIndex;
|
|
201
|
+
}
|
|
202
|
+
appendTextPart(
|
|
203
|
+
processedElements,
|
|
204
|
+
text.substring(currentIndex, tc.startIndex)
|
|
205
|
+
);
|
|
206
|
+
const parsedArgs = parseYamlContent(tc.content, options);
|
|
207
|
+
if (parsedArgs !== null) {
|
|
208
|
+
processedElements.push({
|
|
209
|
+
type: "tool-call",
|
|
210
|
+
toolCallId: generateId(),
|
|
211
|
+
toolName: tc.toolName,
|
|
212
|
+
input: JSON.stringify(parsedArgs)
|
|
213
|
+
});
|
|
214
|
+
} else {
|
|
215
|
+
const originalText = text.substring(tc.startIndex, tc.endIndex);
|
|
216
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse YAML tool call", {
|
|
217
|
+
toolCall: originalText
|
|
218
|
+
});
|
|
219
|
+
processedElements.push({ type: "text", text: originalText });
|
|
220
|
+
}
|
|
221
|
+
return tc.endIndex;
|
|
222
|
+
}
|
|
223
|
+
function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
224
|
+
return (controller, text) => {
|
|
225
|
+
const content = text;
|
|
226
|
+
if (content) {
|
|
227
|
+
if (!getCurrentTextId()) {
|
|
228
|
+
const newId = generateId();
|
|
229
|
+
setCurrentTextId(newId);
|
|
230
|
+
controller.enqueue({
|
|
231
|
+
type: "text-start",
|
|
232
|
+
id: newId
|
|
233
|
+
});
|
|
234
|
+
setHasEmittedTextStart(true);
|
|
235
|
+
}
|
|
236
|
+
controller.enqueue({
|
|
237
|
+
type: "text-delta",
|
|
238
|
+
id: getCurrentTextId(),
|
|
239
|
+
textDelta: content,
|
|
240
|
+
delta: content
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
const currentTextId = getCurrentTextId();
|
|
244
|
+
if (currentTextId && !text) {
|
|
245
|
+
if (getHasEmittedTextStart()) {
|
|
246
|
+
controller.enqueue({
|
|
247
|
+
type: "text-end",
|
|
248
|
+
id: currentTextId
|
|
249
|
+
});
|
|
250
|
+
setHasEmittedTextStart(false);
|
|
251
|
+
}
|
|
252
|
+
setCurrentTextId(null);
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function findEarliestToolTag(buffer, toolNames) {
|
|
257
|
+
let bestIndex = -1;
|
|
258
|
+
let bestName = "";
|
|
259
|
+
let bestSelfClosing = false;
|
|
260
|
+
let bestTagLength = 0;
|
|
261
|
+
for (const name of toolNames) {
|
|
262
|
+
const openTag = `<${name}>`;
|
|
263
|
+
const selfTagRegex = new RegExp(`<${name}\\s*/>`);
|
|
264
|
+
const idxOpen = buffer.indexOf(openTag);
|
|
265
|
+
const selfMatch = selfTagRegex.exec(buffer);
|
|
266
|
+
const idxSelf = selfMatch ? selfMatch.index : -1;
|
|
267
|
+
if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
|
|
268
|
+
bestIndex = idxOpen;
|
|
269
|
+
bestName = name;
|
|
270
|
+
bestSelfClosing = false;
|
|
271
|
+
bestTagLength = openTag.length;
|
|
272
|
+
}
|
|
273
|
+
if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
|
|
274
|
+
bestIndex = idxSelf;
|
|
275
|
+
bestName = name;
|
|
276
|
+
bestSelfClosing = true;
|
|
277
|
+
bestTagLength = selfMatch ? selfMatch[0].length : 0;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return {
|
|
281
|
+
index: bestIndex,
|
|
282
|
+
name: bestName,
|
|
283
|
+
selfClosing: bestSelfClosing,
|
|
284
|
+
tagLength: bestTagLength
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
var yamlXmlProtocol = (_protocolOptions) => {
|
|
288
|
+
return {
|
|
289
|
+
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
290
|
+
const toolsForPrompt = (tools || []).map((tool) => ({
|
|
291
|
+
name: tool.name,
|
|
292
|
+
description: tool.description,
|
|
293
|
+
parameters: unwrapJsonSchema(tool.inputSchema)
|
|
294
|
+
}));
|
|
295
|
+
return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
|
|
296
|
+
},
|
|
297
|
+
formatToolCall(toolCall) {
|
|
298
|
+
let args = {};
|
|
299
|
+
try {
|
|
300
|
+
args = JSON.parse(toolCall.input);
|
|
301
|
+
} catch (e) {
|
|
302
|
+
args = { value: toolCall.input };
|
|
303
|
+
}
|
|
304
|
+
const yamlContent = YAML.stringify(args);
|
|
305
|
+
return `<${toolCall.toolName}>
|
|
306
|
+
${yamlContent}</${toolCall.toolName}>`;
|
|
307
|
+
},
|
|
308
|
+
formatToolResponse(toolResult) {
|
|
309
|
+
let result = toolResult.result;
|
|
310
|
+
if (result && typeof result === "object" && "type" in result && result.type === "json" && "value" in result) {
|
|
311
|
+
result = result.value;
|
|
312
|
+
}
|
|
313
|
+
const xml = xmlStringify(
|
|
314
|
+
"tool_response",
|
|
315
|
+
{
|
|
316
|
+
tool_name: toolResult.toolName,
|
|
317
|
+
result
|
|
318
|
+
},
|
|
319
|
+
{ declaration: false }
|
|
320
|
+
);
|
|
321
|
+
return xml;
|
|
322
|
+
},
|
|
323
|
+
parseGeneratedText({ text, tools, options }) {
|
|
324
|
+
const toolNames = tools.map((t) => t.name).filter(Boolean);
|
|
325
|
+
if (toolNames.length === 0) {
|
|
326
|
+
return [{ type: "text", text }];
|
|
327
|
+
}
|
|
328
|
+
const processedElements = [];
|
|
329
|
+
let currentIndex = 0;
|
|
330
|
+
const toolCalls = findToolCalls(text, toolNames);
|
|
331
|
+
for (const tc of toolCalls) {
|
|
332
|
+
currentIndex = processToolCallMatch(
|
|
333
|
+
text,
|
|
334
|
+
tc,
|
|
335
|
+
currentIndex,
|
|
336
|
+
processedElements,
|
|
337
|
+
options
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
if (currentIndex < text.length) {
|
|
341
|
+
appendTextPart(processedElements, text.substring(currentIndex));
|
|
342
|
+
}
|
|
343
|
+
return processedElements;
|
|
344
|
+
},
|
|
345
|
+
createStreamParser({ tools, options }) {
|
|
346
|
+
const toolNames = tools.map((t) => t.name).filter(Boolean);
|
|
347
|
+
let buffer = "";
|
|
348
|
+
let currentToolCall = null;
|
|
349
|
+
let currentTextId = null;
|
|
350
|
+
let hasEmittedTextStart = false;
|
|
351
|
+
const flushText = createFlushTextHandler(
|
|
352
|
+
() => currentTextId,
|
|
353
|
+
(newId) => {
|
|
354
|
+
currentTextId = newId;
|
|
355
|
+
},
|
|
356
|
+
() => hasEmittedTextStart,
|
|
357
|
+
(value) => {
|
|
358
|
+
hasEmittedTextStart = value;
|
|
359
|
+
}
|
|
360
|
+
);
|
|
361
|
+
const processToolCallEnd = (controller, toolContent, toolName) => {
|
|
362
|
+
var _a;
|
|
363
|
+
const parsedArgs = parseYamlContent(toolContent, options);
|
|
364
|
+
flushText(controller);
|
|
365
|
+
if (parsedArgs !== null) {
|
|
366
|
+
controller.enqueue({
|
|
367
|
+
type: "tool-call",
|
|
368
|
+
toolCallId: generateId(),
|
|
369
|
+
toolName,
|
|
370
|
+
input: JSON.stringify(parsedArgs)
|
|
371
|
+
});
|
|
372
|
+
} else {
|
|
373
|
+
const original = `<${toolName}>${toolContent}</${toolName}>`;
|
|
374
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
|
|
375
|
+
toolCall: original
|
|
376
|
+
});
|
|
377
|
+
flushText(controller, original);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
const handlePendingToolCall = (controller, endTag, toolName) => {
|
|
381
|
+
const endIdx = buffer.indexOf(endTag);
|
|
382
|
+
if (endIdx === -1) {
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
const content = buffer.substring(0, endIdx);
|
|
386
|
+
buffer = buffer.substring(endIdx + endTag.length);
|
|
387
|
+
processToolCallEnd(controller, content, toolName);
|
|
388
|
+
currentToolCall = null;
|
|
389
|
+
return true;
|
|
390
|
+
};
|
|
391
|
+
const flushSafeText = (controller) => {
|
|
392
|
+
const maxTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n} />`.length)) : 0;
|
|
393
|
+
const tail = Math.max(0, maxTagLen - 1);
|
|
394
|
+
const safeLen = Math.max(0, buffer.length - tail);
|
|
395
|
+
if (safeLen > 0) {
|
|
396
|
+
flushText(controller, buffer.slice(0, safeLen));
|
|
397
|
+
buffer = buffer.slice(safeLen);
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
const handleNewToolTag = (controller, tagIndex, tagName, selfClosing, tagLength) => {
|
|
401
|
+
if (tagIndex > 0) {
|
|
402
|
+
flushText(controller, buffer.substring(0, tagIndex));
|
|
403
|
+
}
|
|
404
|
+
if (selfClosing) {
|
|
405
|
+
buffer = buffer.substring(tagIndex + tagLength);
|
|
406
|
+
processToolCallEnd(controller, "", tagName);
|
|
407
|
+
} else {
|
|
408
|
+
const startTag = `<${tagName}>`;
|
|
409
|
+
buffer = buffer.substring(tagIndex + startTag.length);
|
|
410
|
+
currentToolCall = { name: tagName, content: "" };
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
const processBuffer = (controller) => {
|
|
414
|
+
while (true) {
|
|
415
|
+
if (currentToolCall) {
|
|
416
|
+
const toolName = currentToolCall.name;
|
|
417
|
+
const endTag = `</${toolName}>`;
|
|
418
|
+
if (!handlePendingToolCall(controller, endTag, toolName)) {
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
} else {
|
|
422
|
+
const { index, name, selfClosing, tagLength } = findEarliestToolTag(
|
|
423
|
+
buffer,
|
|
424
|
+
toolNames
|
|
425
|
+
);
|
|
426
|
+
if (index === -1) {
|
|
427
|
+
flushSafeText(controller);
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
handleNewToolTag(controller, index, name, selfClosing, tagLength);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
return new TransformStream({
|
|
435
|
+
transform(chunk, controller) {
|
|
436
|
+
var _a, _b;
|
|
437
|
+
if (chunk.type !== "text-delta") {
|
|
438
|
+
if (buffer) {
|
|
439
|
+
flushText(controller, buffer);
|
|
440
|
+
buffer = "";
|
|
441
|
+
}
|
|
442
|
+
controller.enqueue(chunk);
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const textContent = (_b = (_a = chunk.textDelta) != null ? _a : chunk.delta) != null ? _b : "";
|
|
446
|
+
buffer += textContent;
|
|
447
|
+
processBuffer(controller);
|
|
448
|
+
},
|
|
449
|
+
flush(controller) {
|
|
450
|
+
if (currentToolCall) {
|
|
451
|
+
const unfinishedContent = `<${currentToolCall.name}>${buffer}`;
|
|
452
|
+
flushText(controller, unfinishedContent);
|
|
453
|
+
buffer = "";
|
|
454
|
+
currentToolCall = null;
|
|
455
|
+
} else if (buffer) {
|
|
456
|
+
flushText(controller, buffer);
|
|
457
|
+
buffer = "";
|
|
458
|
+
}
|
|
459
|
+
if (currentTextId && hasEmittedTextStart) {
|
|
460
|
+
controller.enqueue({
|
|
461
|
+
type: "text-end",
|
|
462
|
+
id: currentTextId
|
|
463
|
+
});
|
|
464
|
+
hasEmittedTextStart = false;
|
|
465
|
+
currentTextId = null;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
},
|
|
470
|
+
extractToolCallSegments({ text, tools }) {
|
|
471
|
+
const toolNames = tools.map((t) => t.name).filter(Boolean);
|
|
472
|
+
if (toolNames.length === 0) {
|
|
473
|
+
return [];
|
|
474
|
+
}
|
|
475
|
+
return findToolCalls(text, toolNames).map(
|
|
476
|
+
(tc) => `<${tc.toolName}>${tc.content}</${tc.toolName}>`
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
};
|
|
481
|
+
function orchestratorSystemPromptTemplate(tools, includeMultilineExample = true) {
|
|
482
|
+
const multilineExample = includeMultilineExample ? `
|
|
483
|
+
|
|
484
|
+
For multiline values, use YAML's literal block syntax:
|
|
485
|
+
<write_file>
|
|
486
|
+
file_path: /tmp/example.txt
|
|
487
|
+
contents: |
|
|
488
|
+
First line
|
|
489
|
+
Second line
|
|
490
|
+
Third line
|
|
491
|
+
</write_file>` : "";
|
|
492
|
+
return `# Tools
|
|
493
|
+
|
|
494
|
+
You may call one or more functions to assist with the user query.
|
|
495
|
+
|
|
496
|
+
You are provided with function signatures within <tools></tools> XML tags:
|
|
497
|
+
<tools>${tools}</tools>
|
|
498
|
+
|
|
499
|
+
# Format
|
|
500
|
+
|
|
501
|
+
Use exactly one XML element whose tag name is the function name.
|
|
502
|
+
Inside the XML element, specify parameters using YAML syntax (key: value pairs).
|
|
503
|
+
|
|
504
|
+
# Example
|
|
505
|
+
<get_weather>
|
|
506
|
+
location: New York
|
|
507
|
+
unit: celsius
|
|
508
|
+
</get_weather>${multilineExample}
|
|
509
|
+
|
|
510
|
+
# Rules
|
|
511
|
+
- Parameter names and values must follow the schema exactly.
|
|
512
|
+
- Use proper YAML syntax for values (strings, numbers, booleans, arrays, objects).
|
|
513
|
+
- Each required parameter must appear once.
|
|
514
|
+
- Do not add functions or parameters not in the schema.
|
|
515
|
+
- After calling a tool, you will receive a response. Use this result to answer the user.
|
|
516
|
+
- Do NOT ask clarifying questions. Use reasonable defaults for optional parameters.
|
|
517
|
+
- If a task requires multiple function calls, make ALL of them at once.`;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// src/v6/generate-handler.ts
|
|
521
|
+
import { generateId as generateId2 } from "@ai-sdk/provider-utils";
|
|
522
|
+
import { coerceBySchema } from "@ai-sdk-tool/rxml";
|
|
523
|
+
function parseToolChoiceJson(text, providerOptions) {
|
|
524
|
+
var _a;
|
|
525
|
+
try {
|
|
526
|
+
return JSON.parse(text);
|
|
527
|
+
} catch (error) {
|
|
528
|
+
const options = extractOnErrorOption(providerOptions);
|
|
529
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
530
|
+
options,
|
|
531
|
+
"Failed to parse toolChoice JSON from generated model output",
|
|
532
|
+
{
|
|
533
|
+
text,
|
|
534
|
+
error: error instanceof Error ? error.message : String(error)
|
|
535
|
+
}
|
|
536
|
+
);
|
|
537
|
+
return {};
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
function logDebugSummary(debugSummary, toolCall, originText) {
|
|
541
|
+
if (debugSummary) {
|
|
542
|
+
debugSummary.originalText = originText;
|
|
543
|
+
try {
|
|
544
|
+
debugSummary.toolCalls = JSON.stringify([
|
|
545
|
+
{ toolName: toolCall.toolName, input: toolCall.input }
|
|
546
|
+
]);
|
|
547
|
+
} catch (e) {
|
|
548
|
+
}
|
|
549
|
+
} else if (getDebugLevel() === "parse") {
|
|
550
|
+
logParsedSummary({ toolCalls: [toolCall], originalText: originText });
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
async function handleToolChoice(doGenerate, params) {
|
|
554
|
+
var _a, _b, _c;
|
|
555
|
+
const result = await doGenerate();
|
|
556
|
+
const first = (_a = result.content) == null ? void 0 : _a[0];
|
|
557
|
+
let parsed = {};
|
|
558
|
+
if (first && first.type === "text") {
|
|
559
|
+
if (getDebugLevel() === "parse") {
|
|
560
|
+
logRawChunk(first.text);
|
|
561
|
+
}
|
|
562
|
+
parsed = parseToolChoiceJson(first.text, params.providerOptions);
|
|
563
|
+
}
|
|
564
|
+
const toolCall = {
|
|
565
|
+
type: "tool-call",
|
|
566
|
+
toolCallId: generateId2(),
|
|
567
|
+
toolName: parsed.name || "unknown",
|
|
568
|
+
input: JSON.stringify(parsed.arguments || {})
|
|
569
|
+
};
|
|
570
|
+
const originText = first && first.type === "text" ? first.text : "";
|
|
571
|
+
const debugSummary = (_c = (_b = params.providerOptions) == null ? void 0 : _b.toolCallMiddleware) == null ? void 0 : _c.debugSummary;
|
|
572
|
+
logDebugSummary(debugSummary, toolCall, originText);
|
|
573
|
+
return {
|
|
574
|
+
...result,
|
|
575
|
+
content: [toolCall]
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
function parseContent(content, protocol, tools, providerOptions) {
|
|
579
|
+
const parsed = content.flatMap((contentItem) => {
|
|
580
|
+
if (contentItem.type !== "text") {
|
|
581
|
+
return [contentItem];
|
|
582
|
+
}
|
|
583
|
+
if (getDebugLevel() === "stream") {
|
|
584
|
+
logRawChunk(contentItem.text);
|
|
585
|
+
}
|
|
586
|
+
return protocol.parseGeneratedText({
|
|
587
|
+
text: contentItem.text,
|
|
588
|
+
tools,
|
|
589
|
+
options: {
|
|
590
|
+
...extractOnErrorOption(providerOptions),
|
|
591
|
+
...providerOptions == null ? void 0 : providerOptions.toolCallMiddleware
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
});
|
|
595
|
+
return parsed.map(
|
|
596
|
+
(part) => fixToolCallWithSchema(part, tools)
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
function logParsedContent(content) {
|
|
600
|
+
if (getDebugLevel() === "stream") {
|
|
601
|
+
for (const part of content) {
|
|
602
|
+
logParsedChunk(part);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
function computeDebugSummary(options) {
|
|
607
|
+
var _a;
|
|
608
|
+
const { result, newContent, protocol, tools, providerOptions } = options;
|
|
609
|
+
const allText = result.content.filter(
|
|
610
|
+
(c) => c.type === "text"
|
|
611
|
+
).map((c) => c.text).join("\n\n");
|
|
612
|
+
const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({ text: allText, tools }) : [];
|
|
613
|
+
const originalText = segments.join("\n\n");
|
|
614
|
+
const toolCalls = newContent.filter(
|
|
615
|
+
(p) => p.type === "tool-call"
|
|
616
|
+
);
|
|
617
|
+
const dbg = (_a = providerOptions == null ? void 0 : providerOptions.toolCallMiddleware) == null ? void 0 : _a.debugSummary;
|
|
618
|
+
if (dbg) {
|
|
619
|
+
dbg.originalText = originalText;
|
|
620
|
+
try {
|
|
621
|
+
dbg.toolCalls = JSON.stringify(
|
|
622
|
+
toolCalls.map((tc) => ({
|
|
623
|
+
toolName: tc.toolName,
|
|
624
|
+
input: tc.input
|
|
625
|
+
}))
|
|
626
|
+
);
|
|
627
|
+
} catch (e) {
|
|
628
|
+
}
|
|
629
|
+
} else if (getDebugLevel() === "parse") {
|
|
630
|
+
logParsedSummary({ toolCalls, originalText });
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
async function wrapGenerate({
|
|
634
|
+
protocol,
|
|
635
|
+
doGenerate,
|
|
636
|
+
params
|
|
637
|
+
}) {
|
|
638
|
+
var _a, _b;
|
|
639
|
+
if (isToolChoiceActive(params)) {
|
|
640
|
+
return handleToolChoice(doGenerate, params);
|
|
641
|
+
}
|
|
642
|
+
const tools = originalToolsSchema.decode(
|
|
643
|
+
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools
|
|
644
|
+
);
|
|
645
|
+
const result = await doGenerate();
|
|
646
|
+
if (result.content.length === 0) {
|
|
647
|
+
return result;
|
|
648
|
+
}
|
|
649
|
+
const newContent = parseContent(
|
|
650
|
+
result.content,
|
|
651
|
+
protocol,
|
|
652
|
+
tools,
|
|
653
|
+
params.providerOptions
|
|
654
|
+
);
|
|
655
|
+
logParsedContent(newContent);
|
|
656
|
+
computeDebugSummary({
|
|
657
|
+
result,
|
|
658
|
+
newContent,
|
|
659
|
+
protocol,
|
|
660
|
+
tools,
|
|
661
|
+
providerOptions: params.providerOptions
|
|
662
|
+
});
|
|
663
|
+
return {
|
|
664
|
+
...result,
|
|
665
|
+
content: newContent
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
function fixToolCallWithSchema(part, tools) {
|
|
669
|
+
var _a;
|
|
670
|
+
if (part.type !== "tool-call") {
|
|
671
|
+
return part;
|
|
672
|
+
}
|
|
673
|
+
const tc = part;
|
|
674
|
+
let args = {};
|
|
675
|
+
if (typeof tc.input === "string") {
|
|
676
|
+
try {
|
|
677
|
+
args = JSON.parse(tc.input);
|
|
678
|
+
} catch (e) {
|
|
679
|
+
return part;
|
|
680
|
+
}
|
|
681
|
+
} else if (tc.input && typeof tc.input === "object") {
|
|
682
|
+
args = tc.input;
|
|
683
|
+
}
|
|
684
|
+
const schema = (_a = tools.find((t) => t.name === tc.toolName)) == null ? void 0 : _a.inputSchema;
|
|
685
|
+
const coerced = coerceBySchema(args, schema);
|
|
686
|
+
return {
|
|
687
|
+
...part,
|
|
688
|
+
input: JSON.stringify(coerced != null ? coerced : {})
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// src/v6/stream-handler.ts
|
|
693
|
+
import { generateId as generateId3 } from "@ai-sdk/provider-utils";
|
|
694
|
+
function mapCorePartToV3(part) {
|
|
695
|
+
switch (part.type) {
|
|
696
|
+
case "text-delta":
|
|
697
|
+
return {
|
|
698
|
+
type: "text-delta",
|
|
699
|
+
id: part.id || generateId3(),
|
|
700
|
+
delta: part.textDelta
|
|
701
|
+
};
|
|
702
|
+
case "tool-call":
|
|
703
|
+
return {
|
|
704
|
+
type: "tool-call",
|
|
705
|
+
toolCallId: part.toolCallId,
|
|
706
|
+
toolName: part.toolName,
|
|
707
|
+
input: part.input
|
|
708
|
+
};
|
|
709
|
+
case "tool-call-delta":
|
|
710
|
+
return {
|
|
711
|
+
type: "tool-call-delta",
|
|
712
|
+
toolCallId: part.toolCallId,
|
|
713
|
+
toolName: part.toolName,
|
|
714
|
+
argsTextDelta: part.argsTextDelta
|
|
715
|
+
};
|
|
716
|
+
case "finish":
|
|
717
|
+
return {
|
|
718
|
+
type: "finish",
|
|
719
|
+
finishReason: part.finishReason,
|
|
720
|
+
usage: part.usage
|
|
721
|
+
};
|
|
722
|
+
case "error":
|
|
723
|
+
return {
|
|
724
|
+
type: "error",
|
|
725
|
+
error: part.error
|
|
726
|
+
};
|
|
727
|
+
default:
|
|
728
|
+
return part;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
function mapV3PartToCore(part) {
|
|
732
|
+
const p = part;
|
|
733
|
+
switch (p.type) {
|
|
734
|
+
case "text-delta":
|
|
735
|
+
return {
|
|
736
|
+
type: "text-delta",
|
|
737
|
+
id: p.id,
|
|
738
|
+
textDelta: p.delta || p.textDelta || ""
|
|
739
|
+
};
|
|
740
|
+
case "tool-call":
|
|
741
|
+
return {
|
|
742
|
+
type: "tool-call",
|
|
743
|
+
toolCallId: p.toolCallId,
|
|
744
|
+
toolName: p.toolName,
|
|
745
|
+
input: p.input
|
|
746
|
+
};
|
|
747
|
+
case "finish": {
|
|
748
|
+
const finishReason = p.finishReason;
|
|
749
|
+
return {
|
|
750
|
+
type: "finish",
|
|
751
|
+
finishReason: (typeof finishReason === "object" ? finishReason == null ? void 0 : finishReason.unified : finishReason) || "stop",
|
|
752
|
+
usage: p.usage
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
default:
|
|
756
|
+
return p;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
async function wrapStream({
|
|
760
|
+
protocol,
|
|
761
|
+
doStream,
|
|
762
|
+
doGenerate,
|
|
763
|
+
params
|
|
764
|
+
}) {
|
|
765
|
+
var _a, _b, _c;
|
|
766
|
+
if (isToolChoiceActive(params)) {
|
|
767
|
+
return toolChoiceStream({
|
|
768
|
+
doGenerate,
|
|
769
|
+
options: extractOnErrorOption(params.providerOptions)
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
const { stream, ...rest } = await doStream();
|
|
773
|
+
const debugLevel = getDebugLevel();
|
|
774
|
+
const tools = originalToolsSchema.decode(
|
|
775
|
+
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools
|
|
776
|
+
);
|
|
777
|
+
const options = {
|
|
778
|
+
...extractOnErrorOption(params.providerOptions),
|
|
779
|
+
...((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) || {}
|
|
780
|
+
};
|
|
781
|
+
const coreStream = stream.pipeThrough(
|
|
782
|
+
new TransformStream({
|
|
783
|
+
transform(part, controller) {
|
|
784
|
+
if (debugLevel === "stream") {
|
|
785
|
+
logRawChunk(part);
|
|
786
|
+
}
|
|
787
|
+
controller.enqueue(mapV3PartToCore(part));
|
|
788
|
+
}
|
|
789
|
+
})
|
|
790
|
+
).pipeThrough(protocol.createStreamParser({ tools, options }));
|
|
791
|
+
const v3Stream = coreStream.pipeThrough(
|
|
792
|
+
new TransformStream({
|
|
793
|
+
transform(part, controller) {
|
|
794
|
+
const v3Part = mapCorePartToV3(part);
|
|
795
|
+
if (debugLevel === "stream") {
|
|
796
|
+
logParsedChunk(v3Part);
|
|
797
|
+
}
|
|
798
|
+
controller.enqueue(v3Part);
|
|
799
|
+
}
|
|
800
|
+
})
|
|
801
|
+
);
|
|
802
|
+
return {
|
|
803
|
+
...rest,
|
|
804
|
+
stream: v3Stream
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
async function toolChoiceStream({
|
|
808
|
+
doGenerate,
|
|
809
|
+
options
|
|
810
|
+
}) {
|
|
811
|
+
var _a, _b;
|
|
812
|
+
const result = await doGenerate();
|
|
813
|
+
let toolJson = {};
|
|
814
|
+
if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
|
|
815
|
+
try {
|
|
816
|
+
toolJson = JSON.parse(result.content[0].text);
|
|
817
|
+
} catch (error) {
|
|
818
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
819
|
+
options,
|
|
820
|
+
"Failed to parse toolChoice JSON from streamed model output",
|
|
821
|
+
{
|
|
822
|
+
text: result.content[0].text,
|
|
823
|
+
error: error instanceof Error ? error.message : String(error)
|
|
824
|
+
}
|
|
825
|
+
);
|
|
826
|
+
toolJson = {};
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
const stream = new ReadableStream({
|
|
830
|
+
start(controller) {
|
|
831
|
+
controller.enqueue({
|
|
832
|
+
type: "tool-call",
|
|
833
|
+
toolCallId: generateId3(),
|
|
834
|
+
toolName: toolJson.name || "unknown",
|
|
835
|
+
input: JSON.stringify(toolJson.arguments || {})
|
|
836
|
+
});
|
|
837
|
+
controller.enqueue({
|
|
838
|
+
type: "finish",
|
|
839
|
+
usage: (result == null ? void 0 : result.usage) || {
|
|
840
|
+
inputTokens: 0,
|
|
841
|
+
outputTokens: 0
|
|
842
|
+
},
|
|
843
|
+
finishReason: "tool-calls"
|
|
844
|
+
});
|
|
845
|
+
controller.close();
|
|
846
|
+
}
|
|
847
|
+
});
|
|
848
|
+
return {
|
|
849
|
+
request: (result == null ? void 0 : result.request) || {},
|
|
850
|
+
response: (result == null ? void 0 : result.response) || {},
|
|
851
|
+
stream
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// src/v6/transform-handler.ts
|
|
856
|
+
function buildFinalPrompt(systemPrompt, processedPrompt, placement) {
|
|
857
|
+
const systemIndex = processedPrompt.findIndex((m) => m.role === "system");
|
|
858
|
+
if (systemIndex !== -1) {
|
|
859
|
+
const existing = processedPrompt[systemIndex].content;
|
|
860
|
+
let existingText = "";
|
|
861
|
+
if (typeof existing === "string") {
|
|
862
|
+
existingText = existing;
|
|
863
|
+
} else if (Array.isArray(existing)) {
|
|
864
|
+
existingText = existing.map((p) => {
|
|
865
|
+
var _a;
|
|
866
|
+
return (p == null ? void 0 : p.type) === "text" ? (_a = p.text) != null ? _a : "" : "";
|
|
867
|
+
}).filter(Boolean).join("\n");
|
|
868
|
+
} else {
|
|
869
|
+
existingText = String(existing != null ? existing : "");
|
|
870
|
+
}
|
|
871
|
+
const mergedContent = placement === "first" ? `${systemPrompt}
|
|
872
|
+
|
|
873
|
+
${existingText}` : `${existingText}
|
|
874
|
+
|
|
875
|
+
${systemPrompt}`;
|
|
876
|
+
return processedPrompt.map(
|
|
877
|
+
(m, idx) => idx === systemIndex ? {
|
|
878
|
+
...m,
|
|
879
|
+
content: mergedContent
|
|
880
|
+
} : m
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
if (placement === "first") {
|
|
884
|
+
return [
|
|
885
|
+
{
|
|
886
|
+
role: "system",
|
|
887
|
+
content: systemPrompt
|
|
888
|
+
},
|
|
889
|
+
...processedPrompt
|
|
890
|
+
];
|
|
891
|
+
}
|
|
892
|
+
return [
|
|
893
|
+
...processedPrompt,
|
|
894
|
+
{
|
|
895
|
+
role: "system",
|
|
896
|
+
content: systemPrompt
|
|
897
|
+
}
|
|
898
|
+
];
|
|
899
|
+
}
|
|
900
|
+
function buildBaseReturnParams(params, finalPrompt, functionTools) {
|
|
901
|
+
return {
|
|
902
|
+
...params,
|
|
903
|
+
prompt: finalPrompt,
|
|
904
|
+
tools: [],
|
|
905
|
+
toolChoice: void 0,
|
|
906
|
+
providerOptions: {
|
|
907
|
+
...params.providerOptions || {},
|
|
908
|
+
toolCallMiddleware: {
|
|
909
|
+
...params.providerOptions && typeof params.providerOptions === "object" && params.providerOptions.toolCallMiddleware || {},
|
|
910
|
+
originalTools: originalToolsSchema.encode(functionTools)
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
};
|
|
914
|
+
}
|
|
915
|
+
function findProviderDefinedTool(tools, selectedToolName) {
|
|
916
|
+
return tools.find((t) => {
|
|
917
|
+
if (t.type === "function") {
|
|
918
|
+
return false;
|
|
919
|
+
}
|
|
920
|
+
const anyTool = t;
|
|
921
|
+
return anyTool.id === selectedToolName || anyTool.name === selectedToolName;
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
function handleToolChoiceTool(params, baseReturnParams) {
|
|
925
|
+
var _a, _b, _c;
|
|
926
|
+
const selectedToolName = (_a = params.toolChoice) == null ? void 0 : _a.toolName;
|
|
927
|
+
if (!selectedToolName) {
|
|
928
|
+
throw new Error("Tool name is required for 'tool' toolChoice type.");
|
|
929
|
+
}
|
|
930
|
+
const providerDefinedMatch = findProviderDefinedTool(
|
|
931
|
+
(_b = params.tools) != null ? _b : [],
|
|
932
|
+
selectedToolName
|
|
933
|
+
);
|
|
934
|
+
if (providerDefinedMatch) {
|
|
935
|
+
throw new Error(
|
|
936
|
+
"Provider-defined tools are not supported by this middleware. Please use custom tools."
|
|
937
|
+
);
|
|
938
|
+
}
|
|
939
|
+
const selectedTool = ((_c = params.tools) != null ? _c : []).find(
|
|
940
|
+
(t) => t.type === "function" && t.name === selectedToolName
|
|
941
|
+
);
|
|
942
|
+
if (!selectedTool) {
|
|
943
|
+
throw new Error(
|
|
944
|
+
`Tool with name '${selectedToolName}' not found in params.tools.`
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
return {
|
|
948
|
+
...baseReturnParams,
|
|
949
|
+
responseFormat: {
|
|
950
|
+
type: "json",
|
|
951
|
+
schema: {
|
|
952
|
+
type: "object",
|
|
953
|
+
properties: {
|
|
954
|
+
name: {
|
|
955
|
+
const: selectedTool.name
|
|
956
|
+
},
|
|
957
|
+
arguments: selectedTool.inputSchema
|
|
958
|
+
},
|
|
959
|
+
required: ["name", "arguments"]
|
|
960
|
+
},
|
|
961
|
+
name: selectedTool.name,
|
|
962
|
+
description: typeof selectedTool.description === "string" ? selectedTool.description : void 0
|
|
963
|
+
},
|
|
964
|
+
providerOptions: {
|
|
965
|
+
...baseReturnParams.providerOptions || {},
|
|
966
|
+
toolCallMiddleware: {
|
|
967
|
+
...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
|
|
968
|
+
...params.toolChoice ? { toolChoice: params.toolChoice } : {}
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
function handleToolChoiceRequired(params, baseReturnParams, functionTools) {
|
|
974
|
+
if (!params.tools || params.tools.length === 0) {
|
|
975
|
+
throw new Error(
|
|
976
|
+
"Tool choice type 'required' is set, but no tools are provided in params.tools."
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
return {
|
|
980
|
+
...baseReturnParams,
|
|
981
|
+
responseFormat: {
|
|
982
|
+
type: "json",
|
|
983
|
+
schema: createDynamicIfThenElseSchema(functionTools)
|
|
984
|
+
},
|
|
985
|
+
providerOptions: {
|
|
986
|
+
...baseReturnParams.providerOptions || {},
|
|
987
|
+
toolCallMiddleware: {
|
|
988
|
+
...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
|
|
989
|
+
toolChoice: { type: "required" }
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
};
|
|
993
|
+
}
|
|
994
|
+
function transformParams({
|
|
995
|
+
params,
|
|
996
|
+
protocol,
|
|
997
|
+
toolSystemPromptTemplate,
|
|
998
|
+
placement = "first"
|
|
999
|
+
}) {
|
|
1000
|
+
var _a, _b, _c, _d, _e;
|
|
1001
|
+
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
1002
|
+
const functionTools = ((_a = params.tools) != null ? _a : []).filter(
|
|
1003
|
+
(t) => t.type === "function"
|
|
1004
|
+
);
|
|
1005
|
+
const systemPrompt = resolvedProtocol.formatTools({
|
|
1006
|
+
tools: functionTools,
|
|
1007
|
+
toolSystemPromptTemplate
|
|
1008
|
+
});
|
|
1009
|
+
const processedPrompt = convertToolPrompt(
|
|
1010
|
+
(_b = params.prompt) != null ? _b : [],
|
|
1011
|
+
resolvedProtocol,
|
|
1012
|
+
extractOnErrorOption(params.providerOptions)
|
|
1013
|
+
);
|
|
1014
|
+
const finalPrompt = buildFinalPrompt(
|
|
1015
|
+
systemPrompt,
|
|
1016
|
+
processedPrompt,
|
|
1017
|
+
placement
|
|
1018
|
+
);
|
|
1019
|
+
const baseReturnParams = buildBaseReturnParams(
|
|
1020
|
+
params,
|
|
1021
|
+
finalPrompt,
|
|
1022
|
+
functionTools
|
|
1023
|
+
);
|
|
1024
|
+
if (((_c = params.toolChoice) == null ? void 0 : _c.type) === "none") {
|
|
1025
|
+
throw new Error(
|
|
1026
|
+
"The 'none' toolChoice type is not supported by this middleware. Please use 'auto', 'required', or specify a tool name."
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
1029
|
+
if (((_d = params.toolChoice) == null ? void 0 : _d.type) === "tool") {
|
|
1030
|
+
return handleToolChoiceTool(params, baseReturnParams);
|
|
1031
|
+
}
|
|
1032
|
+
if (((_e = params.toolChoice) == null ? void 0 : _e.type) === "required") {
|
|
1033
|
+
return handleToolChoiceRequired(params, baseReturnParams, functionTools);
|
|
1034
|
+
}
|
|
1035
|
+
return baseReturnParams;
|
|
1036
|
+
}
|
|
1037
|
+
function processAssistantContent(content, resolvedProtocol, providerOptions) {
|
|
1038
|
+
var _a;
|
|
1039
|
+
const newContent = [];
|
|
1040
|
+
for (const item of content) {
|
|
1041
|
+
if (isToolCallContent(item)) {
|
|
1042
|
+
newContent.push({
|
|
1043
|
+
type: "text",
|
|
1044
|
+
text: resolvedProtocol.formatToolCall(item)
|
|
1045
|
+
});
|
|
1046
|
+
} else if (item.type === "text") {
|
|
1047
|
+
newContent.push(item);
|
|
1048
|
+
} else if (item.type === "reasoning") {
|
|
1049
|
+
newContent.push(item);
|
|
1050
|
+
} else {
|
|
1051
|
+
const options = extractOnErrorOption(providerOptions);
|
|
1052
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1053
|
+
options,
|
|
1054
|
+
"tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
|
|
1055
|
+
{ content: item }
|
|
1056
|
+
);
|
|
1057
|
+
newContent.push({
|
|
1058
|
+
type: "text",
|
|
1059
|
+
text: JSON.stringify(item)
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
const onlyText = newContent.every((c) => c.type === "text");
|
|
1064
|
+
return onlyText ? [
|
|
1065
|
+
{
|
|
1066
|
+
type: "text",
|
|
1067
|
+
text: newContent.map((c) => c.text).join("\n")
|
|
1068
|
+
}
|
|
1069
|
+
] : newContent;
|
|
1070
|
+
}
|
|
1071
|
+
function processToolMessage(content, resolvedProtocol) {
|
|
1072
|
+
return {
|
|
1073
|
+
role: "user",
|
|
1074
|
+
content: [
|
|
1075
|
+
{
|
|
1076
|
+
type: "text",
|
|
1077
|
+
text: content.map((toolResult) => {
|
|
1078
|
+
var _a, _b;
|
|
1079
|
+
const tr = toolResult;
|
|
1080
|
+
return resolvedProtocol.formatToolResponse({
|
|
1081
|
+
...toolResult,
|
|
1082
|
+
result: (_b = (_a = tr.result) != null ? _a : tr.content) != null ? _b : tr.output
|
|
1083
|
+
});
|
|
1084
|
+
}).join("\n")
|
|
1085
|
+
}
|
|
1086
|
+
]
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
1089
|
+
function processMessage(message, resolvedProtocol, providerOptions) {
|
|
1090
|
+
if (message.role === "assistant") {
|
|
1091
|
+
const condensedContent = processAssistantContent(
|
|
1092
|
+
message.content,
|
|
1093
|
+
resolvedProtocol,
|
|
1094
|
+
providerOptions
|
|
1095
|
+
);
|
|
1096
|
+
return {
|
|
1097
|
+
role: "assistant",
|
|
1098
|
+
content: condensedContent
|
|
1099
|
+
};
|
|
1100
|
+
}
|
|
1101
|
+
if (message.role === "tool") {
|
|
1102
|
+
const toolResultParts = message.content.filter(
|
|
1103
|
+
(part) => part.type === "tool-result"
|
|
1104
|
+
);
|
|
1105
|
+
return processToolMessage(toolResultParts, resolvedProtocol);
|
|
1106
|
+
}
|
|
1107
|
+
return message;
|
|
1108
|
+
}
|
|
1109
|
+
function isAllTextContent(content) {
|
|
1110
|
+
if (!Array.isArray(content)) {
|
|
1111
|
+
return false;
|
|
1112
|
+
}
|
|
1113
|
+
return content.every(
|
|
1114
|
+
(c) => (c == null ? void 0 : c.type) === "text"
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
function joinTextContent(content) {
|
|
1118
|
+
return content.map((c) => c.text).join("\n");
|
|
1119
|
+
}
|
|
1120
|
+
function createCondensedMessage(role, joinedText) {
|
|
1121
|
+
if (role === "system") {
|
|
1122
|
+
return {
|
|
1123
|
+
role: "system",
|
|
1124
|
+
content: joinedText
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
return {
|
|
1128
|
+
role,
|
|
1129
|
+
content: [
|
|
1130
|
+
{
|
|
1131
|
+
type: "text",
|
|
1132
|
+
text: joinedText
|
|
1133
|
+
}
|
|
1134
|
+
]
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
function condenseTextContent(processedPrompt) {
|
|
1138
|
+
for (let i = 0; i < processedPrompt.length; i += 1) {
|
|
1139
|
+
const msg = processedPrompt[i];
|
|
1140
|
+
if (!Array.isArray(msg.content)) {
|
|
1141
|
+
continue;
|
|
1142
|
+
}
|
|
1143
|
+
const shouldCondense = isAllTextContent(msg.content) && msg.content.length > 1;
|
|
1144
|
+
if (shouldCondense) {
|
|
1145
|
+
const joinedText = joinTextContent(msg.content);
|
|
1146
|
+
processedPrompt[i] = createCondensedMessage(msg.role, joinedText);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
return processedPrompt;
|
|
1150
|
+
}
|
|
1151
|
+
function mergeConsecutiveUserMessages(processedPrompt) {
|
|
1152
|
+
for (let i = processedPrompt.length - 1; i > 0; i -= 1) {
|
|
1153
|
+
const current = processedPrompt[i];
|
|
1154
|
+
const prev = processedPrompt[i - 1];
|
|
1155
|
+
if (current.role === "user" && prev.role === "user") {
|
|
1156
|
+
const prevContent = prev.content.map((c) => c.type === "text" ? c.text : "").join("\n");
|
|
1157
|
+
const currentContent = current.content.map((c) => c.type === "text" ? c.text : "").join("\n");
|
|
1158
|
+
processedPrompt[i - 1] = {
|
|
1159
|
+
role: "user",
|
|
1160
|
+
content: [{ type: "text", text: `${prevContent}
|
|
1161
|
+
${currentContent}` }]
|
|
1162
|
+
};
|
|
1163
|
+
processedPrompt.splice(i, 1);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
return processedPrompt;
|
|
1167
|
+
}
|
|
1168
|
+
function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
|
|
1169
|
+
let processedPrompt = prompt.map(
|
|
1170
|
+
(message) => processMessage(message, resolvedProtocol, providerOptions)
|
|
1171
|
+
);
|
|
1172
|
+
processedPrompt = condenseTextContent(processedPrompt);
|
|
1173
|
+
processedPrompt = mergeConsecutiveUserMessages(processedPrompt);
|
|
1174
|
+
return processedPrompt;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
// src/v6/tool-call-middleware.ts
|
|
1178
|
+
function createToolMiddleware({
|
|
1179
|
+
protocol,
|
|
1180
|
+
toolSystemPromptTemplate,
|
|
1181
|
+
placement = "last"
|
|
1182
|
+
}) {
|
|
1183
|
+
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
1184
|
+
return {
|
|
1185
|
+
specificationVersion: "v3",
|
|
1186
|
+
wrapStream: ({ doStream, doGenerate, params }) => {
|
|
1187
|
+
if (isToolChoiceActive(params)) {
|
|
1188
|
+
return toolChoiceStream({
|
|
1189
|
+
doGenerate,
|
|
1190
|
+
options: extractOnErrorOption(params.providerOptions)
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1193
|
+
return wrapStream({
|
|
1194
|
+
protocol: resolvedProtocol,
|
|
1195
|
+
doStream,
|
|
1196
|
+
doGenerate,
|
|
1197
|
+
params
|
|
1198
|
+
});
|
|
1199
|
+
},
|
|
1200
|
+
wrapGenerate: async ({ doGenerate, params }) => wrapGenerate({
|
|
1201
|
+
protocol: resolvedProtocol,
|
|
1202
|
+
doGenerate,
|
|
1203
|
+
params
|
|
1204
|
+
}),
|
|
1205
|
+
transformParams: async ({ params }) => transformParams({
|
|
1206
|
+
protocol: resolvedProtocol,
|
|
1207
|
+
toolSystemPromptTemplate,
|
|
1208
|
+
placement,
|
|
1209
|
+
params
|
|
1210
|
+
})
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
// src/v6/index.ts
|
|
1215
|
+
var gemmaToolMiddleware = createToolMiddleware({
|
|
1216
|
+
protocol: jsonMixProtocol({
|
|
1217
|
+
toolCallStart: "```tool_call\n",
|
|
1218
|
+
toolCallEnd: "\n```",
|
|
1219
|
+
toolResponseStart: "```tool_response\n",
|
|
1220
|
+
toolResponseEnd: "\n```"
|
|
1221
|
+
}),
|
|
1222
|
+
toolSystemPromptTemplate(tools) {
|
|
1223
|
+
return `You have access to functions. If you decide to invoke any of the function(s),
|
|
1224
|
+
you MUST put it in the format of markdown code fence block with the language name of tool_call , e.g.
|
|
1225
|
+
\`\`\`tool_call
|
|
1226
|
+
{'name': <function-name>, 'arguments': <args-dict>}
|
|
1227
|
+
\`\`\`
|
|
1228
|
+
You SHOULD NOT include any other text in the response if you call a function
|
|
1229
|
+
${tools}`;
|
|
1230
|
+
}
|
|
1231
|
+
});
|
|
1232
|
+
var hermesToolMiddleware = createToolMiddleware({
|
|
1233
|
+
protocol: jsonMixProtocol,
|
|
1234
|
+
toolSystemPromptTemplate(tools) {
|
|
1235
|
+
return `You are a function calling AI model.
|
|
1236
|
+
You are provided with function signatures within <tools></tools> XML tags.
|
|
1237
|
+
You may call one or more functions to assist with the user query.
|
|
1238
|
+
Don't make assumptions about what values to plug into functions.
|
|
1239
|
+
Here are the available tools: <tools>${tools}</tools>
|
|
1240
|
+
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"]}
|
|
1241
|
+
For each function call return a json object with function name and arguments within <tool_call></tool_call> XML tags as follows:
|
|
1242
|
+
<tool_call>
|
|
1243
|
+
{"name": "<function-name>", "arguments": <args-dict>}
|
|
1244
|
+
</tool_call>`;
|
|
1245
|
+
}
|
|
1246
|
+
});
|
|
1247
|
+
var morphXmlToolMiddleware = createToolMiddleware({
|
|
1248
|
+
protocol: morphXmlProtocol,
|
|
1249
|
+
placement: "first",
|
|
1250
|
+
toolSystemPromptTemplate(tools) {
|
|
1251
|
+
return `# Tools
|
|
1252
|
+
|
|
1253
|
+
You may call one or more functions to assist with the user query.
|
|
1254
|
+
|
|
1255
|
+
You are provided with function signatures within <tools></tools> XML tags:
|
|
1256
|
+
<tools>${tools}</tools>
|
|
1257
|
+
|
|
1258
|
+
# Rules
|
|
1259
|
+
- Use exactly one XML element whose tag name is the function name.
|
|
1260
|
+
- Put each parameter as a child element.
|
|
1261
|
+
- Values must follow the schema exactly (numbers, arrays, objects, enums \u2192 copy as-is).
|
|
1262
|
+
- Do not add or remove functions or parameters.
|
|
1263
|
+
- Each required parameter must appear once.
|
|
1264
|
+
- Output nothing before or after the function call.
|
|
1265
|
+
- After calling a tool, you will receive a response in the format: <tool_response><tool_name>NAME</tool_name><result>RESULT</result></tool_response>. Use this result to answer the user.
|
|
1266
|
+
|
|
1267
|
+
# Example
|
|
1268
|
+
<get_weather>
|
|
1269
|
+
<location>New York</location>
|
|
1270
|
+
<unit>celsius</unit>
|
|
1271
|
+
</get_weather>`;
|
|
1272
|
+
}
|
|
1273
|
+
});
|
|
1274
|
+
var orchestratorToolMiddleware = createToolMiddleware({
|
|
1275
|
+
protocol: yamlXmlProtocol(),
|
|
1276
|
+
placement: "first",
|
|
1277
|
+
toolSystemPromptTemplate: orchestratorSystemPromptTemplate
|
|
1278
|
+
});
|
|
1279
|
+
|
|
1280
|
+
export {
|
|
1281
|
+
yamlXmlProtocol,
|
|
1282
|
+
orchestratorSystemPromptTemplate,
|
|
1283
|
+
createToolMiddleware,
|
|
1284
|
+
gemmaToolMiddleware,
|
|
1285
|
+
hermesToolMiddleware,
|
|
1286
|
+
morphXmlToolMiddleware,
|
|
1287
|
+
orchestratorToolMiddleware
|
|
1288
|
+
};
|
|
1289
|
+
//# sourceMappingURL=chunk-QPJA5CS6.js.map
|