@ai-sdk-tool/parser 3.3.1 → 3.3.3
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-OUGMLYAW.js → chunk-2KK5BDZF.js} +373 -8
- package/dist/chunk-2KK5BDZF.js.map +1 -0
- package/dist/{chunk-EW3A6Y7O.js → chunk-CXWS24JX.js} +8 -5
- package/dist/chunk-CXWS24JX.js.map +1 -0
- package/dist/{chunk-7E6UFDFQ.js → chunk-NAQSTPDQ.js} +713 -125
- package/dist/chunk-NAQSTPDQ.js.map +1 -0
- package/dist/community.cjs +1088 -135
- package/dist/community.cjs.map +1 -1
- package/dist/community.js +3 -3
- package/dist/index.cjs +1088 -135
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -8
- package/dist/index.d.ts +20 -8
- package/dist/index.js +5 -4
- package/dist/rxml.cjs +382 -15
- package/dist/rxml.cjs.map +1 -1
- package/dist/rxml.js +2 -2
- package/dist/schema-coerce.cjs +372 -7
- package/dist/schema-coerce.cjs.map +1 -1
- package/dist/schema-coerce.js +1 -1
- package/package.json +13 -12
- package/dist/chunk-7E6UFDFQ.js.map +0 -1
- package/dist/chunk-EW3A6Y7O.js.map +0 -1
- package/dist/chunk-OUGMLYAW.js.map +0 -1
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
+
escapeRegExp,
|
|
2
3
|
parse as parse2,
|
|
3
4
|
stringify
|
|
4
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-CXWS24JX.js";
|
|
5
6
|
import {
|
|
6
7
|
parse
|
|
7
8
|
} from "./chunk-IX4FJELL.js";
|
|
8
9
|
import {
|
|
9
|
-
coerceBySchema
|
|
10
|
-
|
|
10
|
+
coerceBySchema,
|
|
11
|
+
getSchemaType,
|
|
12
|
+
unwrapJsonSchema
|
|
13
|
+
} from "./chunk-2KK5BDZF.js";
|
|
11
14
|
|
|
12
15
|
// src/core/utils/debug.ts
|
|
13
16
|
var LINE_SPLIT_REGEX = /\r?\n/;
|
|
@@ -187,9 +190,11 @@ function generateId() {
|
|
|
187
190
|
return Math.random().toString(36).substring(2, 15);
|
|
188
191
|
}
|
|
189
192
|
|
|
190
|
-
// src/core/utils/
|
|
191
|
-
function
|
|
192
|
-
|
|
193
|
+
// src/core/utils/protocol-utils.ts
|
|
194
|
+
function addTextSegment(text, processedElements) {
|
|
195
|
+
if (text.trim()) {
|
|
196
|
+
processedElements.push({ type: "text", text });
|
|
197
|
+
}
|
|
193
198
|
}
|
|
194
199
|
|
|
195
200
|
// src/core/protocols/json-protocol.ts
|
|
@@ -218,11 +223,6 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
|
|
|
218
223
|
processedElements.push({ type: "text", text: fullMatch });
|
|
219
224
|
}
|
|
220
225
|
}
|
|
221
|
-
function addTextSegment(text, processedElements) {
|
|
222
|
-
if (text.trim()) {
|
|
223
|
-
processedElements.push({ type: "text", text });
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
226
|
function processMatchedToolCall(context) {
|
|
227
227
|
const { match, text, currentIndex, processedElements, options } = context;
|
|
228
228
|
const startIndex = match.index;
|
|
@@ -516,9 +516,35 @@ function isTCMProtocolFactory(protocol) {
|
|
|
516
516
|
return typeof protocol === "function";
|
|
517
517
|
}
|
|
518
518
|
|
|
519
|
-
// src/core/
|
|
519
|
+
// src/core/utils/regex-constants.ts
|
|
520
520
|
var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
|
|
521
521
|
var WHITESPACE_REGEX = /\s/;
|
|
522
|
+
|
|
523
|
+
// src/core/utils/xml-root-repair.ts
|
|
524
|
+
var XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX = /^<([A-Za-z_][A-Za-z0-9_-]*)\s*\r?\n([\s\S]+?)\r?\n\s*\/>\s*$/;
|
|
525
|
+
function tryRepairXmlSelfClosingRootWithBody(rawText, toolNames) {
|
|
526
|
+
const trimmed = rawText.trim();
|
|
527
|
+
if (trimmed.length === 0) {
|
|
528
|
+
return null;
|
|
529
|
+
}
|
|
530
|
+
const match = trimmed.match(XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX);
|
|
531
|
+
if (!match) {
|
|
532
|
+
return null;
|
|
533
|
+
}
|
|
534
|
+
const rootTag = match[1];
|
|
535
|
+
if (!toolNames.includes(rootTag)) {
|
|
536
|
+
return null;
|
|
537
|
+
}
|
|
538
|
+
const body = match[2].trimEnd();
|
|
539
|
+
if (body.trim().length === 0 || body.includes(`</${rootTag}>`)) {
|
|
540
|
+
return null;
|
|
541
|
+
}
|
|
542
|
+
return `<${rootTag}>
|
|
543
|
+
${body}
|
|
544
|
+
</${rootTag}>`;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// src/core/protocols/xml-protocol.ts
|
|
522
548
|
function getToolSchema(tools, toolName) {
|
|
523
549
|
var _a;
|
|
524
550
|
return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
@@ -799,6 +825,102 @@ function findToolCalls(text, toolNames) {
|
|
|
799
825
|
}
|
|
800
826
|
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
801
827
|
}
|
|
828
|
+
function handleSpecialToken(depth) {
|
|
829
|
+
return { depth, lastCompleteEnd: -1, shouldBreak: false };
|
|
830
|
+
}
|
|
831
|
+
function handleOpenToken(token, depth, lastCompleteEnd) {
|
|
832
|
+
if (token.selfClosing) {
|
|
833
|
+
return {
|
|
834
|
+
depth,
|
|
835
|
+
lastCompleteEnd: depth === 0 ? token.nextPos : lastCompleteEnd,
|
|
836
|
+
shouldBreak: false
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
return { depth: depth + 1, lastCompleteEnd, shouldBreak: false };
|
|
840
|
+
}
|
|
841
|
+
function handleCloseToken(token, depth) {
|
|
842
|
+
if (depth <= 0) {
|
|
843
|
+
return { depth, lastCompleteEnd: -1, shouldBreak: true };
|
|
844
|
+
}
|
|
845
|
+
const newDepth = depth - 1;
|
|
846
|
+
return {
|
|
847
|
+
depth: newDepth,
|
|
848
|
+
lastCompleteEnd: newDepth === 0 ? token.nextPos : -1,
|
|
849
|
+
shouldBreak: false
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
function findLinePrefixedXmlBodyEnd(text, bodyStartIndex) {
|
|
853
|
+
let cursor = bodyStartIndex;
|
|
854
|
+
let depth = 0;
|
|
855
|
+
let lastCompleteEnd = -1;
|
|
856
|
+
while (cursor < text.length) {
|
|
857
|
+
if (depth === 0) {
|
|
858
|
+
cursor = consumeWhitespace(text, cursor);
|
|
859
|
+
if (cursor >= text.length || text.charAt(cursor) !== "<") {
|
|
860
|
+
break;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
const token = nextTagToken(text, cursor);
|
|
864
|
+
if (token.kind === "eof") {
|
|
865
|
+
break;
|
|
866
|
+
}
|
|
867
|
+
let result;
|
|
868
|
+
if (token.kind === "special") {
|
|
869
|
+
result = handleSpecialToken(depth);
|
|
870
|
+
} else if (token.kind === "open") {
|
|
871
|
+
result = handleOpenToken(token, depth, lastCompleteEnd);
|
|
872
|
+
} else {
|
|
873
|
+
result = handleCloseToken(token, depth);
|
|
874
|
+
}
|
|
875
|
+
depth = result.depth;
|
|
876
|
+
if (result.lastCompleteEnd !== -1) {
|
|
877
|
+
lastCompleteEnd = result.lastCompleteEnd;
|
|
878
|
+
}
|
|
879
|
+
if (result.shouldBreak) {
|
|
880
|
+
break;
|
|
881
|
+
}
|
|
882
|
+
cursor = token.nextPos;
|
|
883
|
+
}
|
|
884
|
+
return lastCompleteEnd;
|
|
885
|
+
}
|
|
886
|
+
function findLinePrefixedToolCall(text, toolNames) {
|
|
887
|
+
var _a;
|
|
888
|
+
let best = null;
|
|
889
|
+
for (const toolName of toolNames) {
|
|
890
|
+
const linePattern = new RegExp(
|
|
891
|
+
`(^|\\n)[\\t ]*${escapeRegExp(toolName)}[\\t ]*:?[\\t ]*(?:\\r?\\n|$)`,
|
|
892
|
+
"g"
|
|
893
|
+
);
|
|
894
|
+
let match = linePattern.exec(text);
|
|
895
|
+
while (match !== null) {
|
|
896
|
+
const prefix = (_a = match[1]) != null ? _a : "";
|
|
897
|
+
const startIndex = match.index + prefix.length;
|
|
898
|
+
const contentStart = consumeWhitespace(text, linePattern.lastIndex);
|
|
899
|
+
if (contentStart >= text.length || text.charAt(contentStart) !== "<") {
|
|
900
|
+
match = linePattern.exec(text);
|
|
901
|
+
continue;
|
|
902
|
+
}
|
|
903
|
+
const contentEnd = findLinePrefixedXmlBodyEnd(text, contentStart);
|
|
904
|
+
if (contentEnd === -1 || contentEnd <= contentStart) {
|
|
905
|
+
match = linePattern.exec(text);
|
|
906
|
+
continue;
|
|
907
|
+
}
|
|
908
|
+
const content = text.slice(contentStart, contentEnd);
|
|
909
|
+
const candidate = {
|
|
910
|
+
toolName,
|
|
911
|
+
startIndex,
|
|
912
|
+
endIndex: contentEnd,
|
|
913
|
+
content,
|
|
914
|
+
segment: text.slice(startIndex, contentEnd)
|
|
915
|
+
};
|
|
916
|
+
if (best === null || candidate.startIndex < best.startIndex) {
|
|
917
|
+
best = candidate;
|
|
918
|
+
}
|
|
919
|
+
break;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
return best;
|
|
923
|
+
}
|
|
802
924
|
function findEarliestToolTag(buffer, toolNames) {
|
|
803
925
|
var _a, _b;
|
|
804
926
|
let bestIndex = -1;
|
|
@@ -1088,6 +1210,27 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
1088
1210
|
}
|
|
1089
1211
|
};
|
|
1090
1212
|
}
|
|
1213
|
+
function findToolCallsWithFallbacks(text, toolNames) {
|
|
1214
|
+
let parseText = text;
|
|
1215
|
+
let toolCalls = findToolCalls(parseText, toolNames);
|
|
1216
|
+
if (toolCalls.length === 0) {
|
|
1217
|
+
const fallbackToolCall = findLinePrefixedToolCall(parseText, toolNames);
|
|
1218
|
+
if (fallbackToolCall !== null) {
|
|
1219
|
+
toolCalls.push(fallbackToolCall);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
if (toolCalls.length === 0) {
|
|
1223
|
+
const repaired = tryRepairXmlSelfClosingRootWithBody(parseText, toolNames);
|
|
1224
|
+
if (repaired) {
|
|
1225
|
+
const repairedCalls = findToolCalls(repaired, toolNames);
|
|
1226
|
+
if (repairedCalls.length > 0) {
|
|
1227
|
+
parseText = repaired;
|
|
1228
|
+
toolCalls = repairedCalls;
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
return { parseText, toolCalls };
|
|
1233
|
+
}
|
|
1091
1234
|
var xmlProtocol = (protocolOptions) => {
|
|
1092
1235
|
var _a;
|
|
1093
1236
|
const parseOptions = {
|
|
@@ -1121,28 +1264,31 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
1121
1264
|
}
|
|
1122
1265
|
const processedElements = [];
|
|
1123
1266
|
let currentIndex = 0;
|
|
1124
|
-
const toolCalls =
|
|
1267
|
+
const { parseText, toolCalls } = findToolCallsWithFallbacks(
|
|
1268
|
+
text,
|
|
1269
|
+
toolNames
|
|
1270
|
+
);
|
|
1125
1271
|
for (const tc of toolCalls) {
|
|
1126
1272
|
if (tc.startIndex > currentIndex) {
|
|
1127
1273
|
processedElements.push({
|
|
1128
1274
|
type: "text",
|
|
1129
|
-
text:
|
|
1275
|
+
text: parseText.substring(currentIndex, tc.startIndex)
|
|
1130
1276
|
});
|
|
1131
1277
|
}
|
|
1132
1278
|
processToolCall({
|
|
1133
1279
|
toolCall: tc,
|
|
1134
1280
|
tools,
|
|
1135
1281
|
options,
|
|
1136
|
-
text,
|
|
1282
|
+
text: parseText,
|
|
1137
1283
|
processedElements,
|
|
1138
1284
|
parseOptions
|
|
1139
1285
|
});
|
|
1140
1286
|
currentIndex = tc.endIndex;
|
|
1141
1287
|
}
|
|
1142
|
-
if (currentIndex <
|
|
1288
|
+
if (currentIndex < parseText.length) {
|
|
1143
1289
|
processedElements.push({
|
|
1144
1290
|
type: "text",
|
|
1145
|
-
text:
|
|
1291
|
+
text: parseText.substring(currentIndex)
|
|
1146
1292
|
});
|
|
1147
1293
|
}
|
|
1148
1294
|
return processedElements;
|
|
@@ -1181,6 +1327,20 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
1181
1327
|
return new TransformStream({
|
|
1182
1328
|
transform(chunk, controller) {
|
|
1183
1329
|
var _a2;
|
|
1330
|
+
if (chunk.type === "finish") {
|
|
1331
|
+
if (currentToolCall) {
|
|
1332
|
+
const unfinishedContent = `<${currentToolCall.name}>${currentToolCall.content}${buffer}`;
|
|
1333
|
+
flushText(controller, unfinishedContent);
|
|
1334
|
+
buffer = "";
|
|
1335
|
+
currentToolCall = null;
|
|
1336
|
+
} else if (buffer) {
|
|
1337
|
+
flushText(controller, buffer);
|
|
1338
|
+
buffer = "";
|
|
1339
|
+
}
|
|
1340
|
+
flushText(controller);
|
|
1341
|
+
controller.enqueue(chunk);
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1184
1344
|
if (chunk.type !== "text-delta") {
|
|
1185
1345
|
if (buffer) {
|
|
1186
1346
|
flushText(controller, buffer);
|
|
@@ -1226,8 +1386,6 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
1226
1386
|
|
|
1227
1387
|
// src/core/protocols/yaml-protocol.ts
|
|
1228
1388
|
import YAML from "yaml";
|
|
1229
|
-
var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
|
|
1230
|
-
var WHITESPACE_REGEX2 = /\s/;
|
|
1231
1389
|
var LEADING_WHITESPACE_RE = /^(\s*)/;
|
|
1232
1390
|
function findClosingTagEnd(text, contentStart, toolName) {
|
|
1233
1391
|
let pos = contentStart;
|
|
@@ -1244,11 +1402,11 @@ function findClosingTagEnd(text, contentStart, toolName) {
|
|
|
1244
1402
|
break;
|
|
1245
1403
|
}
|
|
1246
1404
|
let p = ltIdx + 2;
|
|
1247
|
-
while (p < gtIdx &&
|
|
1405
|
+
while (p < gtIdx && WHITESPACE_REGEX.test(text[p])) {
|
|
1248
1406
|
p++;
|
|
1249
1407
|
}
|
|
1250
1408
|
const nameStart = p;
|
|
1251
|
-
while (p < gtIdx &&
|
|
1409
|
+
while (p < gtIdx && NAME_CHAR_RE.test(text.charAt(p))) {
|
|
1252
1410
|
p++;
|
|
1253
1411
|
}
|
|
1254
1412
|
const name = text.slice(nameStart, p);
|
|
@@ -1264,11 +1422,11 @@ function findClosingTagEnd(text, contentStart, toolName) {
|
|
|
1264
1422
|
pos = gtIdx === -1 ? text.length : gtIdx + 1;
|
|
1265
1423
|
} else {
|
|
1266
1424
|
let p = ltIdx + 1;
|
|
1267
|
-
while (p < text.length &&
|
|
1425
|
+
while (p < text.length && WHITESPACE_REGEX.test(text[p])) {
|
|
1268
1426
|
p++;
|
|
1269
1427
|
}
|
|
1270
1428
|
const nameStart = p;
|
|
1271
|
-
while (p < text.length &&
|
|
1429
|
+
while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
|
|
1272
1430
|
p++;
|
|
1273
1431
|
}
|
|
1274
1432
|
const name = text.slice(nameStart, p);
|
|
@@ -1277,7 +1435,7 @@ function findClosingTagEnd(text, contentStart, toolName) {
|
|
|
1277
1435
|
break;
|
|
1278
1436
|
}
|
|
1279
1437
|
let r = gtIdx - 1;
|
|
1280
|
-
while (r >= nameStart &&
|
|
1438
|
+
while (r >= nameStart && WHITESPACE_REGEX.test(text[r])) {
|
|
1281
1439
|
r--;
|
|
1282
1440
|
}
|
|
1283
1441
|
const selfClosing = text[r] === "/";
|
|
@@ -1395,22 +1553,14 @@ function parseYamlContent(yamlContent, options) {
|
|
|
1395
1553
|
return null;
|
|
1396
1554
|
}
|
|
1397
1555
|
}
|
|
1398
|
-
function appendTextPart(processedElements, textPart) {
|
|
1399
|
-
if (textPart.trim()) {
|
|
1400
|
-
processedElements.push({
|
|
1401
|
-
type: "text",
|
|
1402
|
-
text: textPart
|
|
1403
|
-
});
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1406
1556
|
function processToolCallMatch(text, tc, currentIndex, processedElements, options) {
|
|
1407
1557
|
var _a;
|
|
1408
1558
|
if (tc.startIndex < currentIndex) {
|
|
1409
1559
|
return currentIndex;
|
|
1410
1560
|
}
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1561
|
+
addTextSegment(
|
|
1562
|
+
text.substring(currentIndex, tc.startIndex),
|
|
1563
|
+
processedElements
|
|
1414
1564
|
);
|
|
1415
1565
|
const parsedArgs = parseYamlContent(tc.content, options);
|
|
1416
1566
|
if (parsedArgs !== null) {
|
|
@@ -1517,18 +1667,32 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
1517
1667
|
}
|
|
1518
1668
|
const processedElements = [];
|
|
1519
1669
|
let currentIndex = 0;
|
|
1520
|
-
|
|
1670
|
+
let parseText = text;
|
|
1671
|
+
let toolCalls = findToolCalls2(parseText, toolNames);
|
|
1672
|
+
if (toolCalls.length === 0) {
|
|
1673
|
+
const repaired = tryRepairXmlSelfClosingRootWithBody(
|
|
1674
|
+
parseText,
|
|
1675
|
+
toolNames
|
|
1676
|
+
);
|
|
1677
|
+
if (repaired) {
|
|
1678
|
+
const repairedCalls = findToolCalls2(repaired, toolNames);
|
|
1679
|
+
if (repairedCalls.length > 0) {
|
|
1680
|
+
parseText = repaired;
|
|
1681
|
+
toolCalls = repairedCalls;
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1521
1685
|
for (const tc of toolCalls) {
|
|
1522
1686
|
currentIndex = processToolCallMatch(
|
|
1523
|
-
|
|
1687
|
+
parseText,
|
|
1524
1688
|
tc,
|
|
1525
1689
|
currentIndex,
|
|
1526
1690
|
processedElements,
|
|
1527
1691
|
options
|
|
1528
1692
|
);
|
|
1529
1693
|
}
|
|
1530
|
-
if (currentIndex <
|
|
1531
|
-
|
|
1694
|
+
if (currentIndex < parseText.length) {
|
|
1695
|
+
addTextSegment(parseText.substring(currentIndex), processedElements);
|
|
1532
1696
|
}
|
|
1533
1697
|
return processedElements;
|
|
1534
1698
|
},
|
|
@@ -1624,6 +1788,20 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
1624
1788
|
return new TransformStream({
|
|
1625
1789
|
transform(chunk, controller) {
|
|
1626
1790
|
var _a;
|
|
1791
|
+
if (chunk.type === "finish") {
|
|
1792
|
+
if (currentToolCall) {
|
|
1793
|
+
const unfinishedContent = `<${currentToolCall.name}>${buffer}`;
|
|
1794
|
+
flushText(controller, unfinishedContent);
|
|
1795
|
+
buffer = "";
|
|
1796
|
+
currentToolCall = null;
|
|
1797
|
+
} else if (buffer) {
|
|
1798
|
+
flushText(controller, buffer);
|
|
1799
|
+
buffer = "";
|
|
1800
|
+
}
|
|
1801
|
+
flushText(controller);
|
|
1802
|
+
controller.enqueue(chunk);
|
|
1803
|
+
return;
|
|
1804
|
+
}
|
|
1627
1805
|
if (chunk.type !== "text-delta") {
|
|
1628
1806
|
if (buffer) {
|
|
1629
1807
|
flushText(controller, buffer);
|
|
@@ -1747,17 +1925,56 @@ function encodeOriginalTools(tools) {
|
|
|
1747
1925
|
inputSchema: JSON.stringify(t.inputSchema)
|
|
1748
1926
|
}))) || [];
|
|
1749
1927
|
}
|
|
1750
|
-
function decodeOriginalTools(originalTools) {
|
|
1928
|
+
function decodeOriginalTools(originalTools, options) {
|
|
1929
|
+
var _a, _b, _c;
|
|
1751
1930
|
if (!originalTools) {
|
|
1752
1931
|
return [];
|
|
1753
1932
|
}
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1933
|
+
const decodedTools = [];
|
|
1934
|
+
for (const [index, tool] of originalTools.entries()) {
|
|
1935
|
+
if (!tool || typeof tool.name !== "string") {
|
|
1936
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Invalid originalTools entry: missing tool name", {
|
|
1937
|
+
index,
|
|
1938
|
+
tool
|
|
1939
|
+
});
|
|
1940
|
+
continue;
|
|
1941
|
+
}
|
|
1942
|
+
if (typeof tool.inputSchema !== "string") {
|
|
1943
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
1944
|
+
options,
|
|
1945
|
+
"Invalid originalTools entry: inputSchema must be a string",
|
|
1946
|
+
{
|
|
1947
|
+
index,
|
|
1948
|
+
toolName: tool.name
|
|
1949
|
+
}
|
|
1950
|
+
);
|
|
1951
|
+
continue;
|
|
1952
|
+
}
|
|
1953
|
+
try {
|
|
1954
|
+
decodedTools.push({
|
|
1955
|
+
type: "function",
|
|
1956
|
+
name: tool.name,
|
|
1957
|
+
inputSchema: JSON.parse(tool.inputSchema)
|
|
1958
|
+
});
|
|
1959
|
+
} catch (error) {
|
|
1960
|
+
(_c = options == null ? void 0 : options.onError) == null ? void 0 : _c.call(
|
|
1961
|
+
options,
|
|
1962
|
+
"Failed to decode originalTools input schema, using permissive fallback schema",
|
|
1963
|
+
{
|
|
1964
|
+
index,
|
|
1965
|
+
toolName: tool.name,
|
|
1966
|
+
inputSchema: tool.inputSchema,
|
|
1967
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1968
|
+
}
|
|
1969
|
+
);
|
|
1970
|
+
decodedTools.push({
|
|
1971
|
+
type: "function",
|
|
1972
|
+
name: tool.name,
|
|
1973
|
+
inputSchema: { type: "object" }
|
|
1974
|
+
});
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
return decodedTools;
|
|
1761
1978
|
}
|
|
1762
1979
|
function extractToolNamesFromOriginalTools(originalTools) {
|
|
1763
1980
|
return (originalTools == null ? void 0 : originalTools.map((t) => t.name)) || [];
|
|
@@ -1782,23 +1999,337 @@ function hasInputProperty(obj) {
|
|
|
1782
1999
|
|
|
1783
2000
|
// src/generate-handler.ts
|
|
1784
2001
|
import { generateId as generateId2 } from "@ai-sdk/provider-utils";
|
|
1785
|
-
|
|
2002
|
+
|
|
2003
|
+
// src/core/utils/generated-text-json-recovery.ts
|
|
2004
|
+
function isRecord(value) {
|
|
2005
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2006
|
+
}
|
|
2007
|
+
function safeStringify2(value) {
|
|
2008
|
+
try {
|
|
2009
|
+
return JSON.stringify(value != null ? value : {});
|
|
2010
|
+
} catch (e) {
|
|
2011
|
+
return "{}";
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
function parseJsonCandidate(candidateText) {
|
|
2015
|
+
try {
|
|
2016
|
+
return parse(candidateText);
|
|
2017
|
+
} catch (e) {
|
|
2018
|
+
return void 0;
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
function extractCodeBlockCandidates(text) {
|
|
2022
|
+
var _a, _b;
|
|
2023
|
+
const codeBlockRegex = /```(?:json|yaml|xml)?\s*([\s\S]*?)```/gi;
|
|
2024
|
+
const candidates = [];
|
|
2025
|
+
let match;
|
|
2026
|
+
while (true) {
|
|
2027
|
+
match = codeBlockRegex.exec(text);
|
|
2028
|
+
if (!match) {
|
|
2029
|
+
break;
|
|
2030
|
+
}
|
|
2031
|
+
const body = (_a = match[1]) == null ? void 0 : _a.trim();
|
|
2032
|
+
if (body) {
|
|
2033
|
+
const startIndex = (_b = match.index) != null ? _b : 0;
|
|
2034
|
+
const endIndex = startIndex + match[0].length;
|
|
2035
|
+
candidates.push({
|
|
2036
|
+
text: body,
|
|
2037
|
+
startIndex,
|
|
2038
|
+
endIndex
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
return candidates;
|
|
2043
|
+
}
|
|
2044
|
+
function scanJsonChar(state, char) {
|
|
2045
|
+
if (state.inString) {
|
|
2046
|
+
if (state.escaping) {
|
|
2047
|
+
return { ...state, escaping: false };
|
|
2048
|
+
}
|
|
2049
|
+
if (char === "\\") {
|
|
2050
|
+
return { ...state, escaping: true };
|
|
2051
|
+
}
|
|
2052
|
+
if (char === '"') {
|
|
2053
|
+
return { ...state, inString: false };
|
|
2054
|
+
}
|
|
2055
|
+
return state;
|
|
2056
|
+
}
|
|
2057
|
+
if (char === '"') {
|
|
2058
|
+
return { ...state, inString: true };
|
|
2059
|
+
}
|
|
2060
|
+
if (char === "{") {
|
|
2061
|
+
return { ...state, depth: state.depth + 1 };
|
|
2062
|
+
}
|
|
2063
|
+
if (char === "}") {
|
|
2064
|
+
return { ...state, depth: Math.max(0, state.depth - 1) };
|
|
2065
|
+
}
|
|
2066
|
+
return state;
|
|
2067
|
+
}
|
|
2068
|
+
function extractBalancedJsonObjects(text) {
|
|
2069
|
+
const maxCandidateLength = 1e4;
|
|
2070
|
+
const candidates = [];
|
|
2071
|
+
let state = { depth: 0, inString: false, escaping: false };
|
|
2072
|
+
let currentStart = null;
|
|
2073
|
+
let ignoreCurrent = false;
|
|
2074
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
2075
|
+
const char = text[index];
|
|
2076
|
+
if (!state.inString && char === "{" && state.depth === 0) {
|
|
2077
|
+
currentStart = index;
|
|
2078
|
+
ignoreCurrent = false;
|
|
2079
|
+
}
|
|
2080
|
+
state = scanJsonChar(state, char);
|
|
2081
|
+
if (currentStart !== null && !ignoreCurrent && index - currentStart + 1 > maxCandidateLength) {
|
|
2082
|
+
ignoreCurrent = true;
|
|
2083
|
+
}
|
|
2084
|
+
if (!state.inString && char === "}" && state.depth === 0) {
|
|
2085
|
+
if (currentStart !== null && !ignoreCurrent) {
|
|
2086
|
+
const endIndex = index + 1;
|
|
2087
|
+
const candidate = text.slice(currentStart, endIndex);
|
|
2088
|
+
if (candidate.length > 1) {
|
|
2089
|
+
candidates.push({
|
|
2090
|
+
text: candidate,
|
|
2091
|
+
startIndex: currentStart,
|
|
2092
|
+
endIndex
|
|
2093
|
+
});
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
currentStart = null;
|
|
2097
|
+
ignoreCurrent = false;
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
return candidates;
|
|
2101
|
+
}
|
|
2102
|
+
function extractTaggedToolCallCandidates(rawText) {
|
|
2103
|
+
var _a, _b;
|
|
2104
|
+
const toolCallRegex = /<tool_call>([\s\S]*?)<\/tool_call>/gi;
|
|
2105
|
+
const candidates = [];
|
|
2106
|
+
let match;
|
|
2107
|
+
while (true) {
|
|
2108
|
+
match = toolCallRegex.exec(rawText);
|
|
2109
|
+
if (!match) {
|
|
2110
|
+
break;
|
|
2111
|
+
}
|
|
2112
|
+
const body = (_a = match[1]) == null ? void 0 : _a.trim();
|
|
2113
|
+
if (!body) {
|
|
2114
|
+
continue;
|
|
2115
|
+
}
|
|
2116
|
+
const startIndex = (_b = match.index) != null ? _b : 0;
|
|
2117
|
+
const endIndex = startIndex + match[0].length;
|
|
2118
|
+
candidates.push({
|
|
2119
|
+
text: body,
|
|
2120
|
+
startIndex,
|
|
2121
|
+
endIndex
|
|
2122
|
+
});
|
|
2123
|
+
}
|
|
2124
|
+
return candidates;
|
|
2125
|
+
}
|
|
2126
|
+
function extractJsonLikeCandidates(rawText) {
|
|
2127
|
+
return mergeJsonCandidatesByStart(
|
|
2128
|
+
extractTaggedToolCallCandidates(rawText),
|
|
2129
|
+
extractCodeBlockCandidates(rawText),
|
|
2130
|
+
extractBalancedJsonObjects(rawText)
|
|
2131
|
+
);
|
|
2132
|
+
}
|
|
2133
|
+
function mergeJsonCandidatesByStart(tagged, codeBlocks, balanced) {
|
|
2134
|
+
return [...tagged, ...codeBlocks, ...balanced].sort(
|
|
2135
|
+
(a, b) => a.startIndex !== b.startIndex ? a.startIndex - b.startIndex : b.endIndex - a.endIndex
|
|
2136
|
+
);
|
|
2137
|
+
}
|
|
2138
|
+
function toToolCallPart(candidate) {
|
|
2139
|
+
return {
|
|
2140
|
+
type: "tool-call",
|
|
2141
|
+
toolCallId: generateId(),
|
|
2142
|
+
toolName: candidate.toolName,
|
|
2143
|
+
input: candidate.input
|
|
2144
|
+
};
|
|
2145
|
+
}
|
|
2146
|
+
function toRecoveredParts(text, candidate, toolCallPart) {
|
|
2147
|
+
const out = [];
|
|
2148
|
+
const prefix = text.slice(0, candidate.startIndex);
|
|
2149
|
+
if (prefix.length > 0) {
|
|
2150
|
+
out.push({ type: "text", text: prefix });
|
|
2151
|
+
}
|
|
2152
|
+
out.push(toolCallPart);
|
|
2153
|
+
const suffix = text.slice(candidate.endIndex);
|
|
2154
|
+
if (suffix.length > 0) {
|
|
2155
|
+
out.push({ type: "text", text: suffix });
|
|
2156
|
+
}
|
|
2157
|
+
return out;
|
|
2158
|
+
}
|
|
2159
|
+
function parseAsToolPayload(payload, tools) {
|
|
2160
|
+
if (!isRecord(payload)) {
|
|
2161
|
+
return null;
|
|
2162
|
+
}
|
|
2163
|
+
const toolName = typeof payload.name === "string" && payload.name.trim().length > 0 ? payload.name.trim() : null;
|
|
2164
|
+
if (!toolName) {
|
|
2165
|
+
return null;
|
|
2166
|
+
}
|
|
2167
|
+
if (!tools.some((tool) => tool.name === toolName)) {
|
|
2168
|
+
return null;
|
|
2169
|
+
}
|
|
2170
|
+
const rawArgs = Object.hasOwn(payload, "arguments") ? payload.arguments : {};
|
|
2171
|
+
if (!isRecord(rawArgs)) {
|
|
2172
|
+
return null;
|
|
2173
|
+
}
|
|
2174
|
+
return {
|
|
2175
|
+
toolName,
|
|
2176
|
+
input: safeStringify2(rawArgs)
|
|
2177
|
+
};
|
|
2178
|
+
}
|
|
2179
|
+
function isLikelyArgumentsShapeForTool(args, tool) {
|
|
2180
|
+
const unwrapped = unwrapJsonSchema(tool.inputSchema);
|
|
2181
|
+
if (!isRecord(unwrapped)) {
|
|
2182
|
+
return false;
|
|
2183
|
+
}
|
|
2184
|
+
if (getSchemaType(unwrapped) !== "object") {
|
|
2185
|
+
return false;
|
|
2186
|
+
}
|
|
2187
|
+
const properties = unwrapped.properties;
|
|
2188
|
+
if (!isRecord(properties)) {
|
|
2189
|
+
return false;
|
|
2190
|
+
}
|
|
2191
|
+
const keys = Object.keys(args);
|
|
2192
|
+
if (keys.length === 0) {
|
|
2193
|
+
return false;
|
|
2194
|
+
}
|
|
2195
|
+
const knownKeys = keys.filter((key) => Object.hasOwn(properties, key));
|
|
2196
|
+
if (knownKeys.length === 0) {
|
|
2197
|
+
return false;
|
|
2198
|
+
}
|
|
2199
|
+
if (unwrapped.additionalProperties === false && knownKeys.length !== keys.length) {
|
|
2200
|
+
return false;
|
|
2201
|
+
}
|
|
2202
|
+
return true;
|
|
2203
|
+
}
|
|
2204
|
+
function parseAsArgumentsOnly(payload, tools) {
|
|
2205
|
+
if (tools.length !== 1) {
|
|
2206
|
+
return null;
|
|
2207
|
+
}
|
|
2208
|
+
if (!isRecord(payload)) {
|
|
2209
|
+
return null;
|
|
2210
|
+
}
|
|
2211
|
+
const hasNameEnvelope = Object.hasOwn(payload, "name") && typeof payload.name === "string" && payload.name.length > 0;
|
|
2212
|
+
const hasArgumentsEnvelope = Object.hasOwn(payload, "arguments") && (typeof payload.arguments === "string" || isRecord(payload.arguments));
|
|
2213
|
+
if (hasNameEnvelope || hasArgumentsEnvelope) {
|
|
2214
|
+
return null;
|
|
2215
|
+
}
|
|
2216
|
+
const tool = tools[0];
|
|
2217
|
+
if (!isLikelyArgumentsShapeForTool(payload, tool)) {
|
|
2218
|
+
return null;
|
|
2219
|
+
}
|
|
2220
|
+
return {
|
|
2221
|
+
toolName: tool.name,
|
|
2222
|
+
input: safeStringify2(payload)
|
|
2223
|
+
};
|
|
2224
|
+
}
|
|
2225
|
+
function recoverToolCallFromJsonCandidates(text, tools) {
|
|
2226
|
+
if (tools.length === 0) {
|
|
2227
|
+
return null;
|
|
2228
|
+
}
|
|
2229
|
+
const jsonCandidates = extractJsonLikeCandidates(text);
|
|
2230
|
+
for (const jsonCandidate of jsonCandidates) {
|
|
2231
|
+
const parsed = parseJsonCandidate(jsonCandidate.text);
|
|
2232
|
+
if (parsed === void 0) {
|
|
2233
|
+
continue;
|
|
2234
|
+
}
|
|
2235
|
+
const toolPayload = parseAsToolPayload(parsed, tools);
|
|
2236
|
+
if (toolPayload) {
|
|
2237
|
+
return toRecoveredParts(text, jsonCandidate, toToolCallPart(toolPayload));
|
|
2238
|
+
}
|
|
2239
|
+
const argsPayload = parseAsArgumentsOnly(parsed, tools);
|
|
2240
|
+
if (argsPayload) {
|
|
2241
|
+
return toRecoveredParts(text, jsonCandidate, toToolCallPart(argsPayload));
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
return null;
|
|
2245
|
+
}
|
|
2246
|
+
|
|
2247
|
+
// src/core/utils/tool-call-coercion.ts
|
|
2248
|
+
function coerceToolCallInput(toolName, input, tools) {
|
|
1786
2249
|
var _a;
|
|
2250
|
+
let args = {};
|
|
2251
|
+
if (typeof input === "string") {
|
|
2252
|
+
try {
|
|
2253
|
+
args = JSON.parse(input);
|
|
2254
|
+
} catch (e) {
|
|
2255
|
+
return;
|
|
2256
|
+
}
|
|
2257
|
+
} else if (input && typeof input === "object") {
|
|
2258
|
+
args = input;
|
|
2259
|
+
} else {
|
|
2260
|
+
return;
|
|
2261
|
+
}
|
|
2262
|
+
const schema = (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
2263
|
+
const coerced = coerceBySchema(args, schema);
|
|
2264
|
+
return JSON.stringify(coerced != null ? coerced : {});
|
|
2265
|
+
}
|
|
2266
|
+
function coerceToolCallPart(part, tools) {
|
|
2267
|
+
const coercedInput = coerceToolCallInput(part.toolName, part.input, tools);
|
|
2268
|
+
if (coercedInput === void 0) {
|
|
2269
|
+
return part;
|
|
2270
|
+
}
|
|
2271
|
+
return {
|
|
2272
|
+
...part,
|
|
2273
|
+
input: coercedInput
|
|
2274
|
+
};
|
|
2275
|
+
}
|
|
2276
|
+
|
|
2277
|
+
// src/core/utils/tool-choice.ts
|
|
2278
|
+
function ensureNonEmptyToolName(name) {
|
|
2279
|
+
if (typeof name !== "string") {
|
|
2280
|
+
return "unknown";
|
|
2281
|
+
}
|
|
2282
|
+
const trimmed = name.trim();
|
|
2283
|
+
return trimmed.length > 0 ? trimmed : "unknown";
|
|
2284
|
+
}
|
|
2285
|
+
function safeStringify3(value) {
|
|
1787
2286
|
try {
|
|
1788
|
-
return JSON.
|
|
2287
|
+
return JSON.stringify(value != null ? value : {});
|
|
2288
|
+
} catch (e) {
|
|
2289
|
+
return "{}";
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
function parseToolChoicePayload({
|
|
2293
|
+
text,
|
|
2294
|
+
tools,
|
|
2295
|
+
onError,
|
|
2296
|
+
errorMessage
|
|
2297
|
+
}) {
|
|
2298
|
+
let parsed;
|
|
2299
|
+
try {
|
|
2300
|
+
parsed = JSON.parse(text);
|
|
1789
2301
|
} catch (error) {
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
2302
|
+
onError == null ? void 0 : onError(errorMessage, {
|
|
2303
|
+
text,
|
|
2304
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2305
|
+
});
|
|
2306
|
+
return { toolName: "unknown", input: "{}" };
|
|
2307
|
+
}
|
|
2308
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
2309
|
+
onError == null ? void 0 : onError("toolChoice JSON payload must be an object", {
|
|
2310
|
+
parsedType: typeof parsed,
|
|
2311
|
+
parsed
|
|
2312
|
+
});
|
|
2313
|
+
return { toolName: "unknown", input: "{}" };
|
|
2314
|
+
}
|
|
2315
|
+
const payload = parsed;
|
|
2316
|
+
const toolName = ensureNonEmptyToolName(payload.name);
|
|
2317
|
+
const rawArgs = Object.hasOwn(payload, "arguments") ? payload.arguments : {};
|
|
2318
|
+
if (rawArgs == null || typeof rawArgs !== "object" || Array.isArray(rawArgs)) {
|
|
2319
|
+
onError == null ? void 0 : onError("toolChoice arguments must be a JSON object", {
|
|
2320
|
+
toolName,
|
|
2321
|
+
arguments: rawArgs
|
|
2322
|
+
});
|
|
2323
|
+
return { toolName, input: "{}" };
|
|
1800
2324
|
}
|
|
2325
|
+
const coercedInput = coerceToolCallInput(toolName, rawArgs, tools);
|
|
2326
|
+
return {
|
|
2327
|
+
toolName,
|
|
2328
|
+
input: coercedInput != null ? coercedInput : safeStringify3(rawArgs)
|
|
2329
|
+
};
|
|
1801
2330
|
}
|
|
2331
|
+
|
|
2332
|
+
// src/generate-handler.ts
|
|
1802
2333
|
function logDebugSummary(debugSummary, toolCall, originText) {
|
|
1803
2334
|
if (debugSummary) {
|
|
1804
2335
|
debugSummary.originalText = originText;
|
|
@@ -1812,25 +2343,34 @@ function logDebugSummary(debugSummary, toolCall, originText) {
|
|
|
1812
2343
|
logParsedSummary({ toolCalls: [toolCall], originalText: originText });
|
|
1813
2344
|
}
|
|
1814
2345
|
}
|
|
1815
|
-
async function handleToolChoice(doGenerate, params) {
|
|
1816
|
-
var _a, _b, _c;
|
|
2346
|
+
async function handleToolChoice(doGenerate, params, tools) {
|
|
2347
|
+
var _a, _b, _c, _d;
|
|
1817
2348
|
const result = await doGenerate();
|
|
1818
2349
|
const first = (_a = result.content) == null ? void 0 : _a[0];
|
|
1819
|
-
|
|
2350
|
+
const onError = (_b = extractOnErrorOption(params.providerOptions)) == null ? void 0 : _b.onError;
|
|
2351
|
+
let toolName = "unknown";
|
|
2352
|
+
let input = "{}";
|
|
1820
2353
|
if (first && first.type === "text") {
|
|
1821
2354
|
if (getDebugLevel() === "parse") {
|
|
1822
2355
|
logRawChunk(first.text);
|
|
1823
2356
|
}
|
|
1824
|
-
parsed =
|
|
2357
|
+
const parsed = parseToolChoicePayload({
|
|
2358
|
+
text: first.text,
|
|
2359
|
+
tools,
|
|
2360
|
+
onError,
|
|
2361
|
+
errorMessage: "Failed to parse toolChoice JSON from generated model output"
|
|
2362
|
+
});
|
|
2363
|
+
toolName = parsed.toolName;
|
|
2364
|
+
input = parsed.input;
|
|
1825
2365
|
}
|
|
1826
2366
|
const toolCall = {
|
|
1827
2367
|
type: "tool-call",
|
|
1828
2368
|
toolCallId: generateId2(),
|
|
1829
|
-
toolName
|
|
1830
|
-
input
|
|
2369
|
+
toolName,
|
|
2370
|
+
input
|
|
1831
2371
|
};
|
|
1832
2372
|
const originText = first && first.type === "text" ? first.text : "";
|
|
1833
|
-
const debugSummary = (
|
|
2373
|
+
const debugSummary = (_d = (_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) == null ? void 0 : _d.debugSummary;
|
|
1834
2374
|
logDebugSummary(debugSummary, toolCall, originText);
|
|
1835
2375
|
return {
|
|
1836
2376
|
...result,
|
|
@@ -1845,7 +2385,7 @@ function parseContent(content, protocol, tools, providerOptions) {
|
|
|
1845
2385
|
if (getDebugLevel() === "stream") {
|
|
1846
2386
|
logRawChunk(contentItem.text);
|
|
1847
2387
|
}
|
|
1848
|
-
|
|
2388
|
+
const parsedByProtocol = protocol.parseGeneratedText({
|
|
1849
2389
|
text: contentItem.text,
|
|
1850
2390
|
tools,
|
|
1851
2391
|
options: {
|
|
@@ -1853,9 +2393,20 @@ function parseContent(content, protocol, tools, providerOptions) {
|
|
|
1853
2393
|
...providerOptions == null ? void 0 : providerOptions.toolCallMiddleware
|
|
1854
2394
|
}
|
|
1855
2395
|
});
|
|
2396
|
+
const hasToolCall = parsedByProtocol.some(
|
|
2397
|
+
(part) => part.type === "tool-call"
|
|
2398
|
+
);
|
|
2399
|
+
if (hasToolCall) {
|
|
2400
|
+
return parsedByProtocol;
|
|
2401
|
+
}
|
|
2402
|
+
const recoveredFromJson = recoverToolCallFromJsonCandidates(
|
|
2403
|
+
contentItem.text,
|
|
2404
|
+
tools
|
|
2405
|
+
);
|
|
2406
|
+
return recoveredFromJson != null ? recoveredFromJson : parsedByProtocol;
|
|
1856
2407
|
});
|
|
1857
2408
|
return parsed.map(
|
|
1858
|
-
(part) =>
|
|
2409
|
+
(part) => part.type === "tool-call" ? coerceToolCallPart(part, tools) : part
|
|
1859
2410
|
);
|
|
1860
2411
|
}
|
|
1861
2412
|
function logParsedContent(content) {
|
|
@@ -1898,12 +2449,14 @@ async function wrapGenerate({
|
|
|
1898
2449
|
params
|
|
1899
2450
|
}) {
|
|
1900
2451
|
var _a, _b;
|
|
1901
|
-
|
|
1902
|
-
return handleToolChoice(doGenerate, params);
|
|
1903
|
-
}
|
|
2452
|
+
const onError = extractOnErrorOption(params.providerOptions);
|
|
1904
2453
|
const tools = originalToolsSchema.decode(
|
|
1905
|
-
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools
|
|
2454
|
+
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools,
|
|
2455
|
+
onError
|
|
1906
2456
|
);
|
|
2457
|
+
if (isToolChoiceActive(params)) {
|
|
2458
|
+
return handleToolChoice(doGenerate, params, tools);
|
|
2459
|
+
}
|
|
1907
2460
|
const result = await doGenerate();
|
|
1908
2461
|
if (result.content.length === 0) {
|
|
1909
2462
|
return result;
|
|
@@ -1927,28 +2480,6 @@ async function wrapGenerate({
|
|
|
1927
2480
|
content: newContent
|
|
1928
2481
|
};
|
|
1929
2482
|
}
|
|
1930
|
-
function fixToolCallWithSchema(part, tools) {
|
|
1931
|
-
var _a;
|
|
1932
|
-
if (part.type !== "tool-call") {
|
|
1933
|
-
return part;
|
|
1934
|
-
}
|
|
1935
|
-
let args = {};
|
|
1936
|
-
if (typeof part.input === "string") {
|
|
1937
|
-
try {
|
|
1938
|
-
args = JSON.parse(part.input);
|
|
1939
|
-
} catch (e) {
|
|
1940
|
-
return part;
|
|
1941
|
-
}
|
|
1942
|
-
} else if (part.input && typeof part.input === "object") {
|
|
1943
|
-
args = part.input;
|
|
1944
|
-
}
|
|
1945
|
-
const schema = (_a = tools.find((t) => t.name === part.toolName)) == null ? void 0 : _a.inputSchema;
|
|
1946
|
-
const coerced = coerceBySchema(args, schema);
|
|
1947
|
-
return {
|
|
1948
|
-
...part,
|
|
1949
|
-
input: JSON.stringify(coerced != null ? coerced : {})
|
|
1950
|
-
};
|
|
1951
|
-
}
|
|
1952
2483
|
|
|
1953
2484
|
// src/core/prompts/hermes-system-prompt.ts
|
|
1954
2485
|
function hermesSystemPromptTemplate(tools) {
|
|
@@ -2352,19 +2883,22 @@ async function wrapStream({
|
|
|
2352
2883
|
params
|
|
2353
2884
|
}) {
|
|
2354
2885
|
var _a, _b, _c;
|
|
2886
|
+
const onErrorOptions = extractOnErrorOption(params.providerOptions);
|
|
2887
|
+
const tools = originalToolsSchema.decode(
|
|
2888
|
+
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools,
|
|
2889
|
+
onErrorOptions
|
|
2890
|
+
);
|
|
2355
2891
|
if (isToolChoiceActive(params)) {
|
|
2356
2892
|
return toolChoiceStream({
|
|
2357
2893
|
doGenerate,
|
|
2358
|
-
|
|
2894
|
+
tools,
|
|
2895
|
+
options: onErrorOptions
|
|
2359
2896
|
});
|
|
2360
2897
|
}
|
|
2361
2898
|
const { stream, ...rest } = await doStream();
|
|
2362
2899
|
const debugLevel = getDebugLevel();
|
|
2363
|
-
const tools = originalToolsSchema.decode(
|
|
2364
|
-
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools
|
|
2365
|
-
);
|
|
2366
2900
|
const options = {
|
|
2367
|
-
...
|
|
2901
|
+
...onErrorOptions,
|
|
2368
2902
|
...((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) || {}
|
|
2369
2903
|
};
|
|
2370
2904
|
const coreStream = stream.pipeThrough(
|
|
@@ -2382,10 +2916,11 @@ async function wrapStream({
|
|
|
2382
2916
|
const v3Stream = coreStream.pipeThrough(
|
|
2383
2917
|
new TransformStream({
|
|
2384
2918
|
transform(part, controller) {
|
|
2919
|
+
const normalizedPart = part.type === "tool-call" ? coerceToolCallPart(part, tools) : part;
|
|
2385
2920
|
if (debugLevel === "stream") {
|
|
2386
|
-
logParsedChunk(
|
|
2921
|
+
logParsedChunk(normalizedPart);
|
|
2387
2922
|
}
|
|
2388
|
-
controller.enqueue(
|
|
2923
|
+
controller.enqueue(normalizedPart);
|
|
2389
2924
|
}
|
|
2390
2925
|
})
|
|
2391
2926
|
);
|
|
@@ -2396,41 +2931,36 @@ async function wrapStream({
|
|
|
2396
2931
|
}
|
|
2397
2932
|
async function toolChoiceStream({
|
|
2398
2933
|
doGenerate,
|
|
2934
|
+
tools,
|
|
2399
2935
|
options
|
|
2400
2936
|
}) {
|
|
2401
|
-
var _a
|
|
2937
|
+
var _a;
|
|
2938
|
+
const normalizedTools = Array.isArray(tools) ? tools : [];
|
|
2402
2939
|
const result = await doGenerate();
|
|
2403
|
-
let
|
|
2940
|
+
let toolName = "unknown";
|
|
2941
|
+
let input = "{}";
|
|
2404
2942
|
if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
error: error instanceof Error ? error.message : String(error)
|
|
2414
|
-
}
|
|
2415
|
-
);
|
|
2416
|
-
toolJson = {};
|
|
2417
|
-
}
|
|
2943
|
+
const parsed = parseToolChoicePayload({
|
|
2944
|
+
text: result.content[0].text,
|
|
2945
|
+
tools: normalizedTools,
|
|
2946
|
+
onError: options == null ? void 0 : options.onError,
|
|
2947
|
+
errorMessage: "Failed to parse toolChoice JSON from streamed model output"
|
|
2948
|
+
});
|
|
2949
|
+
toolName = parsed.toolName;
|
|
2950
|
+
input = parsed.input;
|
|
2418
2951
|
}
|
|
2419
2952
|
const stream = new ReadableStream({
|
|
2420
2953
|
start(controller) {
|
|
2421
2954
|
controller.enqueue({
|
|
2422
2955
|
type: "tool-call",
|
|
2423
2956
|
toolCallId: generateId3(),
|
|
2424
|
-
toolName
|
|
2425
|
-
input
|
|
2957
|
+
toolName,
|
|
2958
|
+
input
|
|
2426
2959
|
});
|
|
2427
2960
|
controller.enqueue({
|
|
2428
2961
|
type: "finish",
|
|
2429
|
-
usage: (result == null ? void 0 : result.usage)
|
|
2430
|
-
|
|
2431
|
-
outputTokens: 0
|
|
2432
|
-
},
|
|
2433
|
-
finishReason: "tool-calls"
|
|
2962
|
+
usage: normalizeUsage(result == null ? void 0 : result.usage),
|
|
2963
|
+
finishReason: normalizeToolCallsFinishReason(result == null ? void 0 : result.finishReason)
|
|
2434
2964
|
});
|
|
2435
2965
|
controller.close();
|
|
2436
2966
|
}
|
|
@@ -2441,6 +2971,60 @@ async function toolChoiceStream({
|
|
|
2441
2971
|
stream
|
|
2442
2972
|
};
|
|
2443
2973
|
}
|
|
2974
|
+
var ZERO_USAGE = {
|
|
2975
|
+
inputTokens: {
|
|
2976
|
+
total: 0,
|
|
2977
|
+
noCache: void 0,
|
|
2978
|
+
cacheRead: void 0,
|
|
2979
|
+
cacheWrite: void 0
|
|
2980
|
+
},
|
|
2981
|
+
outputTokens: {
|
|
2982
|
+
total: 0,
|
|
2983
|
+
text: void 0,
|
|
2984
|
+
reasoning: void 0
|
|
2985
|
+
}
|
|
2986
|
+
};
|
|
2987
|
+
function normalizeToolCallsFinishReason(finishReason) {
|
|
2988
|
+
let raw = "tool-calls";
|
|
2989
|
+
if (typeof finishReason === "string") {
|
|
2990
|
+
raw = finishReason;
|
|
2991
|
+
} else if (finishReason && typeof finishReason === "object" && "raw" in finishReason && typeof finishReason.raw === "string") {
|
|
2992
|
+
raw = finishReason.raw;
|
|
2993
|
+
} else if (finishReason && typeof finishReason === "object" && "unified" in finishReason && typeof finishReason.unified === "string") {
|
|
2994
|
+
raw = finishReason.unified;
|
|
2995
|
+
}
|
|
2996
|
+
return {
|
|
2997
|
+
unified: "tool-calls",
|
|
2998
|
+
raw
|
|
2999
|
+
};
|
|
3000
|
+
}
|
|
3001
|
+
function normalizeUsage(usage) {
|
|
3002
|
+
if (!usage || typeof usage !== "object") {
|
|
3003
|
+
return ZERO_USAGE;
|
|
3004
|
+
}
|
|
3005
|
+
const usageRecord = usage;
|
|
3006
|
+
const input = usageRecord.inputTokens;
|
|
3007
|
+
const output = usageRecord.outputTokens;
|
|
3008
|
+
if (input && typeof input === "object" && output && typeof output === "object") {
|
|
3009
|
+
return usage;
|
|
3010
|
+
}
|
|
3011
|
+
if (typeof input === "number" && typeof output === "number") {
|
|
3012
|
+
return {
|
|
3013
|
+
inputTokens: {
|
|
3014
|
+
total: input,
|
|
3015
|
+
noCache: void 0,
|
|
3016
|
+
cacheRead: void 0,
|
|
3017
|
+
cacheWrite: void 0
|
|
3018
|
+
},
|
|
3019
|
+
outputTokens: {
|
|
3020
|
+
total: output,
|
|
3021
|
+
text: void 0,
|
|
3022
|
+
reasoning: void 0
|
|
3023
|
+
}
|
|
3024
|
+
};
|
|
3025
|
+
}
|
|
3026
|
+
return ZERO_USAGE;
|
|
3027
|
+
}
|
|
2444
3028
|
|
|
2445
3029
|
// src/transform-handler.ts
|
|
2446
3030
|
function buildFinalPrompt(systemPrompt, processedPrompt, placement) {
|
|
@@ -2566,6 +3150,11 @@ function handleToolChoiceRequired(params, baseReturnParams, functionTools) {
|
|
|
2566
3150
|
"Tool choice type 'required' is set, but no tools are provided in params.tools."
|
|
2567
3151
|
);
|
|
2568
3152
|
}
|
|
3153
|
+
if (functionTools.length === 0) {
|
|
3154
|
+
throw new Error(
|
|
3155
|
+
"Tool choice type 'required' is set, but no function tools are provided. Provider-defined tools are not supported by this middleware."
|
|
3156
|
+
);
|
|
3157
|
+
}
|
|
2569
3158
|
return {
|
|
2570
3159
|
...baseReturnParams,
|
|
2571
3160
|
responseFormat: {
|
|
@@ -2853,7 +3442,6 @@ export {
|
|
|
2853
3442
|
logParsedChunk,
|
|
2854
3443
|
logParsedSummary,
|
|
2855
3444
|
getPotentialStartIndex,
|
|
2856
|
-
escapeRegExp,
|
|
2857
3445
|
jsonProtocol,
|
|
2858
3446
|
isProtocolFactory,
|
|
2859
3447
|
isTCMProtocolFactory,
|
|
@@ -2877,4 +3465,4 @@ export {
|
|
|
2877
3465
|
xmlToolMiddleware,
|
|
2878
3466
|
yamlToolMiddleware
|
|
2879
3467
|
};
|
|
2880
|
-
//# sourceMappingURL=chunk-
|
|
3468
|
+
//# sourceMappingURL=chunk-NAQSTPDQ.js.map
|