@ai-sdk-tool/parser 3.0.0-canary.3 → 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.
@@ -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