@ai-sdk-tool/parser 3.3.2 → 4.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/README.md +7 -0
- package/dist/{chunk-OUGMLYAW.js → chunk-2KK5BDZF.js} +373 -8
- package/dist/chunk-2KK5BDZF.js.map +1 -0
- package/dist/{chunk-ZDBNJWLY.js → chunk-CXWS24JX.js} +2 -2
- package/dist/{chunk-5WKXBBCU.js → chunk-ERJKQKCR.js} +2059 -293
- package/dist/chunk-ERJKQKCR.js.map +1 -0
- package/dist/community.cjs +2496 -367
- package/dist/community.cjs.map +1 -1
- package/dist/community.js +3 -3
- package/dist/index.cjs +2496 -367
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -14
- package/dist/index.d.ts +22 -14
- package/dist/index.js +3 -3
- package/dist/rxml.cjs +377 -12
- 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 +9 -9
- package/dist/chunk-5WKXBBCU.js.map +0 -1
- package/dist/chunk-OUGMLYAW.js.map +0 -1
- /package/dist/{chunk-ZDBNJWLY.js.map → chunk-CXWS24JX.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -905,7 +905,25 @@ function getPotentialStartIndex(text, searchedText) {
|
|
|
905
905
|
|
|
906
906
|
// src/core/utils/id.ts
|
|
907
907
|
function generateId() {
|
|
908
|
-
return
|
|
908
|
+
return crypto.randomUUID().replace(/-/g, "").slice(0, 13);
|
|
909
|
+
}
|
|
910
|
+
var TOOL_CALL_ID_PREFIX = "call_";
|
|
911
|
+
var TOOL_CALL_ID_BODY_LENGTH = 24;
|
|
912
|
+
var TOOL_CALL_ID_ALPHANUM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
913
|
+
function randomAlphaNumeric(length) {
|
|
914
|
+
var _a;
|
|
915
|
+
const bytes = new Uint8Array(length);
|
|
916
|
+
crypto.getRandomValues(bytes);
|
|
917
|
+
let out = "";
|
|
918
|
+
for (let i = 0; i < length; i += 1) {
|
|
919
|
+
const byte = bytes[i];
|
|
920
|
+
const index = (byte != null ? byte : 0) % TOOL_CALL_ID_ALPHANUM.length;
|
|
921
|
+
out += (_a = TOOL_CALL_ID_ALPHANUM[index]) != null ? _a : "0";
|
|
922
|
+
}
|
|
923
|
+
return out;
|
|
924
|
+
}
|
|
925
|
+
function generateToolCallId() {
|
|
926
|
+
return `${TOOL_CALL_ID_PREFIX}${randomAlphaNumeric(TOOL_CALL_ID_BODY_LENGTH)}`;
|
|
909
927
|
}
|
|
910
928
|
|
|
911
929
|
// src/core/utils/protocol-utils.ts
|
|
@@ -914,6 +932,38 @@ function addTextSegment(text, processedElements) {
|
|
|
914
932
|
processedElements.push({ type: "text", text });
|
|
915
933
|
}
|
|
916
934
|
}
|
|
935
|
+
function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
936
|
+
return (controller, text) => {
|
|
937
|
+
const content = text;
|
|
938
|
+
if (content) {
|
|
939
|
+
if (!getCurrentTextId()) {
|
|
940
|
+
const newId = generateId();
|
|
941
|
+
setCurrentTextId(newId);
|
|
942
|
+
controller.enqueue({
|
|
943
|
+
type: "text-start",
|
|
944
|
+
id: newId
|
|
945
|
+
});
|
|
946
|
+
setHasEmittedTextStart(true);
|
|
947
|
+
}
|
|
948
|
+
controller.enqueue({
|
|
949
|
+
type: "text-delta",
|
|
950
|
+
id: getCurrentTextId(),
|
|
951
|
+
delta: content
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
const currentTextId = getCurrentTextId();
|
|
955
|
+
if (currentTextId && !text) {
|
|
956
|
+
if (getHasEmittedTextStart()) {
|
|
957
|
+
controller.enqueue({
|
|
958
|
+
type: "text-end",
|
|
959
|
+
id: currentTextId
|
|
960
|
+
});
|
|
961
|
+
setHasEmittedTextStart(false);
|
|
962
|
+
}
|
|
963
|
+
setCurrentTextId(null);
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
}
|
|
917
967
|
|
|
918
968
|
// src/core/utils/regex.ts
|
|
919
969
|
function escapeRegExp(literal) {
|
|
@@ -921,15 +971,21 @@ function escapeRegExp(literal) {
|
|
|
921
971
|
}
|
|
922
972
|
|
|
923
973
|
// src/core/protocols/json-protocol.ts
|
|
974
|
+
function shouldEmitRawToolCallTextOnError(options) {
|
|
975
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
976
|
+
}
|
|
977
|
+
function canonicalizeToolInput(argumentsValue) {
|
|
978
|
+
return JSON.stringify(argumentsValue != null ? argumentsValue : {});
|
|
979
|
+
}
|
|
924
980
|
function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
|
|
925
|
-
var _a
|
|
981
|
+
var _a;
|
|
926
982
|
try {
|
|
927
983
|
const parsedToolCall = parse(toolCallJson);
|
|
928
984
|
processedElements.push({
|
|
929
985
|
type: "tool-call",
|
|
930
|
-
toolCallId:
|
|
986
|
+
toolCallId: generateToolCallId(),
|
|
931
987
|
toolName: parsedToolCall.name,
|
|
932
|
-
input:
|
|
988
|
+
input: canonicalizeToolInput(parsedToolCall.arguments)
|
|
933
989
|
});
|
|
934
990
|
} catch (error) {
|
|
935
991
|
logParseFailure({
|
|
@@ -938,7 +994,7 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
|
|
|
938
994
|
snippet: fullMatch,
|
|
939
995
|
error
|
|
940
996
|
});
|
|
941
|
-
(
|
|
997
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
942
998
|
options,
|
|
943
999
|
"Could not process JSON tool call, keeping original text.",
|
|
944
1000
|
{ toolCall: fullMatch, error }
|
|
@@ -959,6 +1015,293 @@ function processMatchedToolCall(context) {
|
|
|
959
1015
|
}
|
|
960
1016
|
return startIndex + match[0].length;
|
|
961
1017
|
}
|
|
1018
|
+
var WHITESPACE_JSON_REGEX = /\s/;
|
|
1019
|
+
function skipJsonWhitespace(text, fromIndex) {
|
|
1020
|
+
let index = fromIndex;
|
|
1021
|
+
while (index < text.length && WHITESPACE_JSON_REGEX.test(text[index])) {
|
|
1022
|
+
index += 1;
|
|
1023
|
+
}
|
|
1024
|
+
return index;
|
|
1025
|
+
}
|
|
1026
|
+
function findTopLevelPropertyValueStart(text, property) {
|
|
1027
|
+
const objectStart = skipJsonWhitespace(text, 0);
|
|
1028
|
+
if (objectStart >= text.length || text.charAt(objectStart) !== "{") {
|
|
1029
|
+
return null;
|
|
1030
|
+
}
|
|
1031
|
+
let depth = 0;
|
|
1032
|
+
let inString = false;
|
|
1033
|
+
let escaping = false;
|
|
1034
|
+
for (let index = objectStart; index < text.length; index += 1) {
|
|
1035
|
+
const char = text.charAt(index);
|
|
1036
|
+
if (inString) {
|
|
1037
|
+
if (escaping) {
|
|
1038
|
+
escaping = false;
|
|
1039
|
+
continue;
|
|
1040
|
+
}
|
|
1041
|
+
if (char === "\\") {
|
|
1042
|
+
escaping = true;
|
|
1043
|
+
continue;
|
|
1044
|
+
}
|
|
1045
|
+
if (char === '"') {
|
|
1046
|
+
inString = false;
|
|
1047
|
+
}
|
|
1048
|
+
continue;
|
|
1049
|
+
}
|
|
1050
|
+
if (char === "{") {
|
|
1051
|
+
depth += 1;
|
|
1052
|
+
continue;
|
|
1053
|
+
}
|
|
1054
|
+
if (char === "}") {
|
|
1055
|
+
depth = Math.max(0, depth - 1);
|
|
1056
|
+
continue;
|
|
1057
|
+
}
|
|
1058
|
+
if (char !== '"') {
|
|
1059
|
+
continue;
|
|
1060
|
+
}
|
|
1061
|
+
if (depth !== 1) {
|
|
1062
|
+
inString = true;
|
|
1063
|
+
continue;
|
|
1064
|
+
}
|
|
1065
|
+
const keyStart = index + 1;
|
|
1066
|
+
let keyEnd = keyStart;
|
|
1067
|
+
let keyEscaped = false;
|
|
1068
|
+
while (keyEnd < text.length) {
|
|
1069
|
+
const keyChar = text.charAt(keyEnd);
|
|
1070
|
+
if (keyEscaped) {
|
|
1071
|
+
keyEscaped = false;
|
|
1072
|
+
} else if (keyChar === "\\") {
|
|
1073
|
+
keyEscaped = true;
|
|
1074
|
+
} else if (keyChar === '"') {
|
|
1075
|
+
break;
|
|
1076
|
+
}
|
|
1077
|
+
keyEnd += 1;
|
|
1078
|
+
}
|
|
1079
|
+
if (keyEnd >= text.length || text.charAt(keyEnd) !== '"') {
|
|
1080
|
+
return null;
|
|
1081
|
+
}
|
|
1082
|
+
const key = text.slice(keyStart, keyEnd);
|
|
1083
|
+
let valueCursor = skipJsonWhitespace(text, keyEnd + 1);
|
|
1084
|
+
if (valueCursor >= text.length || text.charAt(valueCursor) !== ":") {
|
|
1085
|
+
index = keyEnd;
|
|
1086
|
+
continue;
|
|
1087
|
+
}
|
|
1088
|
+
valueCursor = skipJsonWhitespace(text, valueCursor + 1);
|
|
1089
|
+
if (key === property) {
|
|
1090
|
+
return valueCursor < text.length ? valueCursor : null;
|
|
1091
|
+
}
|
|
1092
|
+
index = valueCursor - 1;
|
|
1093
|
+
}
|
|
1094
|
+
return null;
|
|
1095
|
+
}
|
|
1096
|
+
function extractTopLevelStringProperty(text, property) {
|
|
1097
|
+
const valueStart = findTopLevelPropertyValueStart(text, property);
|
|
1098
|
+
if (valueStart == null || valueStart >= text.length) {
|
|
1099
|
+
return void 0;
|
|
1100
|
+
}
|
|
1101
|
+
if (text.charAt(valueStart) !== '"') {
|
|
1102
|
+
return void 0;
|
|
1103
|
+
}
|
|
1104
|
+
let valueEnd = valueStart + 1;
|
|
1105
|
+
let escaped = false;
|
|
1106
|
+
while (valueEnd < text.length) {
|
|
1107
|
+
const char = text.charAt(valueEnd);
|
|
1108
|
+
if (escaped) {
|
|
1109
|
+
escaped = false;
|
|
1110
|
+
} else if (char === "\\") {
|
|
1111
|
+
escaped = true;
|
|
1112
|
+
} else if (char === '"') {
|
|
1113
|
+
return text.slice(valueStart + 1, valueEnd);
|
|
1114
|
+
}
|
|
1115
|
+
valueEnd += 1;
|
|
1116
|
+
}
|
|
1117
|
+
return void 0;
|
|
1118
|
+
}
|
|
1119
|
+
function extractJsonValueSlice(text, valueStart) {
|
|
1120
|
+
if (valueStart >= text.length) {
|
|
1121
|
+
return null;
|
|
1122
|
+
}
|
|
1123
|
+
const first = text.charAt(valueStart);
|
|
1124
|
+
if (first === "{" || first === "[") {
|
|
1125
|
+
const stack = [first];
|
|
1126
|
+
let inString = false;
|
|
1127
|
+
let escaped = false;
|
|
1128
|
+
for (let index2 = valueStart + 1; index2 < text.length; index2 += 1) {
|
|
1129
|
+
const char = text.charAt(index2);
|
|
1130
|
+
if (inString) {
|
|
1131
|
+
if (escaped) {
|
|
1132
|
+
escaped = false;
|
|
1133
|
+
} else if (char === "\\") {
|
|
1134
|
+
escaped = true;
|
|
1135
|
+
} else if (char === '"') {
|
|
1136
|
+
inString = false;
|
|
1137
|
+
}
|
|
1138
|
+
continue;
|
|
1139
|
+
}
|
|
1140
|
+
if (char === '"') {
|
|
1141
|
+
inString = true;
|
|
1142
|
+
continue;
|
|
1143
|
+
}
|
|
1144
|
+
if (char === "{" || char === "[") {
|
|
1145
|
+
stack.push(char);
|
|
1146
|
+
continue;
|
|
1147
|
+
}
|
|
1148
|
+
if (char === "}" || char === "]") {
|
|
1149
|
+
const open = stack.at(-1);
|
|
1150
|
+
if (open === "{" && char === "}" || open === "[" && char === "]") {
|
|
1151
|
+
stack.pop();
|
|
1152
|
+
if (stack.length === 0) {
|
|
1153
|
+
return {
|
|
1154
|
+
text: text.slice(valueStart, index2 + 1),
|
|
1155
|
+
complete: true
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
return {
|
|
1162
|
+
text: text.slice(valueStart),
|
|
1163
|
+
complete: false
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
if (first === '"') {
|
|
1167
|
+
let escaped = false;
|
|
1168
|
+
for (let index2 = valueStart + 1; index2 < text.length; index2 += 1) {
|
|
1169
|
+
const char = text.charAt(index2);
|
|
1170
|
+
if (escaped) {
|
|
1171
|
+
escaped = false;
|
|
1172
|
+
} else if (char === "\\") {
|
|
1173
|
+
escaped = true;
|
|
1174
|
+
} else if (char === '"') {
|
|
1175
|
+
return {
|
|
1176
|
+
text: text.slice(valueStart, index2 + 1),
|
|
1177
|
+
complete: true
|
|
1178
|
+
};
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
return {
|
|
1182
|
+
text: text.slice(valueStart),
|
|
1183
|
+
complete: false
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
1186
|
+
let index = valueStart;
|
|
1187
|
+
while (index < text.length) {
|
|
1188
|
+
const char = text.charAt(index);
|
|
1189
|
+
if (char === "," || char === "}" || WHITESPACE_JSON_REGEX.test(char)) {
|
|
1190
|
+
break;
|
|
1191
|
+
}
|
|
1192
|
+
index += 1;
|
|
1193
|
+
}
|
|
1194
|
+
return {
|
|
1195
|
+
text: text.slice(valueStart, index),
|
|
1196
|
+
complete: index < text.length
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
function extractStreamingToolCallProgress(toolCallJson) {
|
|
1200
|
+
var _a;
|
|
1201
|
+
const toolName = extractTopLevelStringProperty(toolCallJson, "name");
|
|
1202
|
+
const argsValueStart = findTopLevelPropertyValueStart(
|
|
1203
|
+
toolCallJson,
|
|
1204
|
+
"arguments"
|
|
1205
|
+
);
|
|
1206
|
+
if (argsValueStart == null) {
|
|
1207
|
+
return {
|
|
1208
|
+
toolName,
|
|
1209
|
+
argumentsText: void 0,
|
|
1210
|
+
argumentsComplete: false
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
const argsSlice = extractJsonValueSlice(toolCallJson, argsValueStart);
|
|
1214
|
+
return {
|
|
1215
|
+
toolName,
|
|
1216
|
+
argumentsText: argsSlice == null ? void 0 : argsSlice.text,
|
|
1217
|
+
argumentsComplete: (_a = argsSlice == null ? void 0 : argsSlice.complete) != null ? _a : false
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
function ensureToolInputStart(state, controller, toolName) {
|
|
1221
|
+
if (!state.activeToolInput) {
|
|
1222
|
+
const id = generateToolCallId();
|
|
1223
|
+
state.activeToolInput = {
|
|
1224
|
+
id,
|
|
1225
|
+
toolName,
|
|
1226
|
+
emittedInput: ""
|
|
1227
|
+
};
|
|
1228
|
+
controller.enqueue({
|
|
1229
|
+
type: "tool-input-start",
|
|
1230
|
+
id,
|
|
1231
|
+
toolName
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
function emitToolInputDelta(state, controller, fullInput) {
|
|
1236
|
+
const active = state.activeToolInput;
|
|
1237
|
+
if (!active) {
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
if (!fullInput.startsWith(active.emittedInput)) {
|
|
1241
|
+
return;
|
|
1242
|
+
}
|
|
1243
|
+
const delta = fullInput.slice(active.emittedInput.length);
|
|
1244
|
+
if (delta.length === 0) {
|
|
1245
|
+
return;
|
|
1246
|
+
}
|
|
1247
|
+
controller.enqueue({
|
|
1248
|
+
type: "tool-input-delta",
|
|
1249
|
+
id: active.id,
|
|
1250
|
+
delta
|
|
1251
|
+
});
|
|
1252
|
+
active.emittedInput = fullInput;
|
|
1253
|
+
}
|
|
1254
|
+
function closeToolInput(state, controller) {
|
|
1255
|
+
if (!state.activeToolInput) {
|
|
1256
|
+
return;
|
|
1257
|
+
}
|
|
1258
|
+
controller.enqueue({
|
|
1259
|
+
type: "tool-input-end",
|
|
1260
|
+
id: state.activeToolInput.id
|
|
1261
|
+
});
|
|
1262
|
+
state.activeToolInput = null;
|
|
1263
|
+
}
|
|
1264
|
+
function emitToolCallFromParsed(state, controller, parsedToolCall) {
|
|
1265
|
+
var _a, _b, _c, _d;
|
|
1266
|
+
closeTextBlock(state, controller);
|
|
1267
|
+
const toolName = typeof parsedToolCall.name === "string" ? parsedToolCall.name : (_b = (_a = state.activeToolInput) == null ? void 0 : _a.toolName) != null ? _b : "unknown";
|
|
1268
|
+
const input = canonicalizeToolInput(parsedToolCall.arguments);
|
|
1269
|
+
ensureToolInputStart(state, controller, toolName);
|
|
1270
|
+
emitToolInputDelta(state, controller, input);
|
|
1271
|
+
const toolCallId = (_d = (_c = state.activeToolInput) == null ? void 0 : _c.id) != null ? _d : generateToolCallId();
|
|
1272
|
+
closeToolInput(state, controller);
|
|
1273
|
+
controller.enqueue({
|
|
1274
|
+
type: "tool-call",
|
|
1275
|
+
toolCallId,
|
|
1276
|
+
toolName,
|
|
1277
|
+
input
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
function canonicalizeArgumentsProgressInput(progress) {
|
|
1281
|
+
if (progress.argumentsText === void 0 || !progress.argumentsComplete) {
|
|
1282
|
+
return void 0;
|
|
1283
|
+
}
|
|
1284
|
+
try {
|
|
1285
|
+
const parsedArguments = parse(progress.argumentsText);
|
|
1286
|
+
return canonicalizeToolInput(parsedArguments);
|
|
1287
|
+
} catch (e) {
|
|
1288
|
+
return void 0;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
function emitToolInputProgress(state, controller) {
|
|
1292
|
+
if (!(state.isInsideToolCall && state.currentToolCallJson)) {
|
|
1293
|
+
return;
|
|
1294
|
+
}
|
|
1295
|
+
const progress = extractStreamingToolCallProgress(state.currentToolCallJson);
|
|
1296
|
+
if (!progress.toolName) {
|
|
1297
|
+
return;
|
|
1298
|
+
}
|
|
1299
|
+
ensureToolInputStart(state, controller, progress.toolName);
|
|
1300
|
+
const canonicalProgressInput = canonicalizeArgumentsProgressInput(progress);
|
|
1301
|
+
if (canonicalProgressInput !== void 0) {
|
|
1302
|
+
emitToolInputDelta(state, controller, canonicalProgressInput);
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
962
1305
|
function flushBuffer(state, controller, toolCallStart) {
|
|
963
1306
|
if (state.buffer.length === 0) {
|
|
964
1307
|
return;
|
|
@@ -989,44 +1332,77 @@ function closeTextBlock(state, controller) {
|
|
|
989
1332
|
state.hasEmittedTextStart = false;
|
|
990
1333
|
}
|
|
991
1334
|
}
|
|
992
|
-
function emitIncompleteToolCall(state, controller, toolCallStart) {
|
|
993
|
-
|
|
1335
|
+
function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer, options) {
|
|
1336
|
+
var _a;
|
|
1337
|
+
if (!state.currentToolCallJson && trailingBuffer.length === 0) {
|
|
1338
|
+
state.isInsideToolCall = false;
|
|
994
1339
|
return;
|
|
995
1340
|
}
|
|
1341
|
+
if (state.currentToolCallJson) {
|
|
1342
|
+
try {
|
|
1343
|
+
const parsedToolCall = parse(state.currentToolCallJson);
|
|
1344
|
+
emitToolCallFromParsed(state, controller, parsedToolCall);
|
|
1345
|
+
state.currentToolCallJson = "";
|
|
1346
|
+
state.isInsideToolCall = false;
|
|
1347
|
+
return;
|
|
1348
|
+
} catch (e) {
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
const rawToolCallContent = `${state.currentToolCallJson}${trailingBuffer}`;
|
|
1352
|
+
const errorContent = `${toolCallStart}${rawToolCallContent}`;
|
|
1353
|
+
const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
|
|
996
1354
|
logParseFailure({
|
|
997
1355
|
phase: "stream",
|
|
998
|
-
reason: "Incomplete streaming tool call segment emitted as text",
|
|
999
|
-
snippet:
|
|
1000
|
-
});
|
|
1001
|
-
const errorId = generateId();
|
|
1002
|
-
const errorContent = `${toolCallStart}${state.currentToolCallJson}`;
|
|
1003
|
-
controller.enqueue({
|
|
1004
|
-
type: "text-start",
|
|
1005
|
-
id: errorId
|
|
1006
|
-
});
|
|
1007
|
-
controller.enqueue({
|
|
1008
|
-
type: "text-delta",
|
|
1009
|
-
id: errorId,
|
|
1010
|
-
delta: errorContent
|
|
1011
|
-
});
|
|
1012
|
-
controller.enqueue({
|
|
1013
|
-
type: "text-end",
|
|
1014
|
-
id: errorId
|
|
1356
|
+
reason: shouldEmitRawFallback ? "Incomplete streaming tool call segment emitted as text" : "Incomplete streaming tool call segment suppressed without raw text fallback",
|
|
1357
|
+
snippet: errorContent
|
|
1015
1358
|
});
|
|
1359
|
+
if (shouldEmitRawFallback) {
|
|
1360
|
+
const errorId = generateId();
|
|
1361
|
+
controller.enqueue({
|
|
1362
|
+
type: "text-start",
|
|
1363
|
+
id: errorId
|
|
1364
|
+
});
|
|
1365
|
+
controller.enqueue({
|
|
1366
|
+
type: "text-delta",
|
|
1367
|
+
id: errorId,
|
|
1368
|
+
delta: errorContent
|
|
1369
|
+
});
|
|
1370
|
+
controller.enqueue({
|
|
1371
|
+
type: "text-end",
|
|
1372
|
+
id: errorId
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
closeToolInput(state, controller);
|
|
1376
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1377
|
+
options,
|
|
1378
|
+
shouldEmitRawFallback ? "Could not complete streaming JSON tool call at finish; emitting original text." : "Could not complete streaming JSON tool call at finish.",
|
|
1379
|
+
{ toolCall: errorContent }
|
|
1380
|
+
);
|
|
1016
1381
|
state.currentToolCallJson = "";
|
|
1382
|
+
state.isInsideToolCall = false;
|
|
1017
1383
|
}
|
|
1018
|
-
function handleFinishChunk(state, controller, toolCallStart, chunk) {
|
|
1019
|
-
if (state.
|
|
1384
|
+
function handleFinishChunk(state, controller, toolCallStart, options, chunk) {
|
|
1385
|
+
if (state.isInsideToolCall) {
|
|
1386
|
+
const trailingBuffer = state.buffer;
|
|
1387
|
+
state.buffer = "";
|
|
1388
|
+
emitIncompleteToolCall(
|
|
1389
|
+
state,
|
|
1390
|
+
controller,
|
|
1391
|
+
toolCallStart,
|
|
1392
|
+
trailingBuffer,
|
|
1393
|
+
options
|
|
1394
|
+
);
|
|
1395
|
+
} else if (state.buffer.length > 0) {
|
|
1020
1396
|
flushBuffer(state, controller, toolCallStart);
|
|
1021
1397
|
}
|
|
1022
1398
|
closeTextBlock(state, controller);
|
|
1023
|
-
emitIncompleteToolCall(state, controller, toolCallStart);
|
|
1024
1399
|
controller.enqueue(chunk);
|
|
1025
1400
|
}
|
|
1026
1401
|
function publishText(text, state, controller) {
|
|
1027
1402
|
if (state.isInsideToolCall) {
|
|
1028
1403
|
closeTextBlock(state, controller);
|
|
1029
1404
|
state.currentToolCallJson += text;
|
|
1405
|
+
emitToolInputProgress(state, controller);
|
|
1030
1406
|
} else if (text.length > 0) {
|
|
1031
1407
|
if (!state.currentTextId) {
|
|
1032
1408
|
state.currentTextId = generateId();
|
|
@@ -1044,42 +1420,40 @@ function publishText(text, state, controller) {
|
|
|
1044
1420
|
}
|
|
1045
1421
|
}
|
|
1046
1422
|
function emitToolCall(context) {
|
|
1047
|
-
var _a
|
|
1423
|
+
var _a;
|
|
1048
1424
|
const { state, controller, toolCallStart, toolCallEnd, options } = context;
|
|
1049
1425
|
try {
|
|
1050
1426
|
const parsedToolCall = parse(state.currentToolCallJson);
|
|
1051
|
-
|
|
1052
|
-
controller.enqueue({
|
|
1053
|
-
type: "tool-call",
|
|
1054
|
-
toolCallId: generateId(),
|
|
1055
|
-
toolName: parsedToolCall.name,
|
|
1056
|
-
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1057
|
-
});
|
|
1427
|
+
emitToolCallFromParsed(state, controller, parsedToolCall);
|
|
1058
1428
|
} catch (error) {
|
|
1429
|
+
const errorContent = `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`;
|
|
1430
|
+
const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
|
|
1059
1431
|
logParseFailure({
|
|
1060
1432
|
phase: "stream",
|
|
1061
1433
|
reason: "Failed to parse streaming tool call JSON segment",
|
|
1062
|
-
snippet:
|
|
1434
|
+
snippet: errorContent,
|
|
1063
1435
|
error
|
|
1064
1436
|
});
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1437
|
+
if (shouldEmitRawFallback) {
|
|
1438
|
+
const errorId = generateId();
|
|
1439
|
+
controller.enqueue({
|
|
1440
|
+
type: "text-start",
|
|
1441
|
+
id: errorId
|
|
1442
|
+
});
|
|
1443
|
+
controller.enqueue({
|
|
1444
|
+
type: "text-delta",
|
|
1445
|
+
id: errorId,
|
|
1446
|
+
delta: errorContent
|
|
1447
|
+
});
|
|
1448
|
+
controller.enqueue({
|
|
1449
|
+
type: "text-end",
|
|
1450
|
+
id: errorId
|
|
1451
|
+
});
|
|
1452
|
+
}
|
|
1453
|
+
closeToolInput(state, controller);
|
|
1454
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1081
1455
|
options,
|
|
1082
|
-
"Could not process streaming JSON tool call; emitting original text.",
|
|
1456
|
+
shouldEmitRawFallback ? "Could not process streaming JSON tool call; emitting original text." : "Could not process streaming JSON tool call.",
|
|
1083
1457
|
{
|
|
1084
1458
|
toolCall: errorContent
|
|
1085
1459
|
}
|
|
@@ -1095,6 +1469,7 @@ function processTagMatch(context) {
|
|
|
1095
1469
|
} else {
|
|
1096
1470
|
state.currentToolCallJson = "";
|
|
1097
1471
|
state.isInsideToolCall = true;
|
|
1472
|
+
state.activeToolInput = null;
|
|
1098
1473
|
}
|
|
1099
1474
|
}
|
|
1100
1475
|
function processBufferTags(context) {
|
|
@@ -1117,8 +1492,16 @@ function processBufferTags(context) {
|
|
|
1117
1492
|
);
|
|
1118
1493
|
}
|
|
1119
1494
|
}
|
|
1120
|
-
function handlePartialTag(state, controller, toolCallStart) {
|
|
1495
|
+
function handlePartialTag(state, controller, toolCallStart, toolCallEnd) {
|
|
1121
1496
|
if (state.isInsideToolCall) {
|
|
1497
|
+
const potentialEndIndex = getPotentialStartIndex(state.buffer, toolCallEnd);
|
|
1498
|
+
if (potentialEndIndex != null && potentialEndIndex + toolCallEnd.length > state.buffer.length) {
|
|
1499
|
+
publishText(state.buffer.slice(0, potentialEndIndex), state, controller);
|
|
1500
|
+
state.buffer = state.buffer.slice(potentialEndIndex);
|
|
1501
|
+
} else {
|
|
1502
|
+
publishText(state.buffer, state, controller);
|
|
1503
|
+
state.buffer = "";
|
|
1504
|
+
}
|
|
1122
1505
|
return;
|
|
1123
1506
|
}
|
|
1124
1507
|
const potentialIndex = getPotentialStartIndex(state.buffer, toolCallStart);
|
|
@@ -1191,13 +1574,14 @@ var jsonProtocol = ({
|
|
|
1191
1574
|
buffer: "",
|
|
1192
1575
|
currentToolCallJson: "",
|
|
1193
1576
|
currentTextId: null,
|
|
1194
|
-
hasEmittedTextStart: false
|
|
1577
|
+
hasEmittedTextStart: false,
|
|
1578
|
+
activeToolInput: null
|
|
1195
1579
|
};
|
|
1196
1580
|
return new TransformStream({
|
|
1197
1581
|
transform(chunk, controller) {
|
|
1198
1582
|
var _a;
|
|
1199
1583
|
if (chunk.type === "finish") {
|
|
1200
|
-
handleFinishChunk(state, controller, toolCallStart, chunk);
|
|
1584
|
+
handleFinishChunk(state, controller, toolCallStart, options, chunk);
|
|
1201
1585
|
return;
|
|
1202
1586
|
}
|
|
1203
1587
|
if (chunk.type !== "text-delta") {
|
|
@@ -1213,7 +1597,7 @@ var jsonProtocol = ({
|
|
|
1213
1597
|
toolCallEnd,
|
|
1214
1598
|
options
|
|
1215
1599
|
});
|
|
1216
|
-
handlePartialTag(state, controller, toolCallStart);
|
|
1600
|
+
handlePartialTag(state, controller, toolCallStart, toolCallEnd);
|
|
1217
1601
|
}
|
|
1218
1602
|
});
|
|
1219
1603
|
},
|
|
@@ -1577,6 +1961,13 @@ var EMPTY_OBJECT_REGEX = /^\{\s*\}$/s;
|
|
|
1577
1961
|
var NEWLINE_SPLIT_REGEX = /\n+/;
|
|
1578
1962
|
var COMMA_SPLIT_REGEX = /,\s*/;
|
|
1579
1963
|
var DIGIT_KEY_REGEX = /^\d+$/;
|
|
1964
|
+
var WHITESPACE_REGEX2 = /\s+/g;
|
|
1965
|
+
var HAS_WHITESPACE_REGEX = /\s/;
|
|
1966
|
+
var SINGLE_QUOTE = "'";
|
|
1967
|
+
var DOUBLE_QUOTE = '"';
|
|
1968
|
+
var SNAKE_SEGMENT_REGEX = /_([a-zA-Z0-9])/g;
|
|
1969
|
+
var CAMEL_BOUNDARY_REGEX = /([a-z0-9])([A-Z])/g;
|
|
1970
|
+
var LEADING_UNDERSCORES_REGEX = /^_+/;
|
|
1580
1971
|
function unwrapJsonSchema(schema) {
|
|
1581
1972
|
if (!schema || typeof schema !== "object") {
|
|
1582
1973
|
return schema;
|
|
@@ -1825,39 +2216,299 @@ function coerceStringToArray(s, unwrapped) {
|
|
|
1825
2216
|
}
|
|
1826
2217
|
return null;
|
|
1827
2218
|
}
|
|
1828
|
-
function
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
out[k] = coerceValueForKey(v, k, unwrapped);
|
|
2219
|
+
function getStrictObjectSchemaInfo(unwrapped) {
|
|
2220
|
+
if (getSchemaType(unwrapped) !== "object") {
|
|
2221
|
+
return null;
|
|
1832
2222
|
}
|
|
1833
|
-
|
|
2223
|
+
if (unwrapped.additionalProperties !== false) {
|
|
2224
|
+
return null;
|
|
2225
|
+
}
|
|
2226
|
+
const properties = unwrapped.properties;
|
|
2227
|
+
if (!properties || typeof properties !== "object" || Array.isArray(properties)) {
|
|
2228
|
+
return null;
|
|
2229
|
+
}
|
|
2230
|
+
const propertyMap = properties;
|
|
2231
|
+
const required = Array.isArray(unwrapped.required) ? unwrapped.required.filter(
|
|
2232
|
+
(value) => typeof value === "string" && value.length > 0
|
|
2233
|
+
) : [];
|
|
2234
|
+
const patternProps = unwrapped.patternProperties;
|
|
2235
|
+
const patternProperties = patternProps && typeof patternProps === "object" && !Array.isArray(patternProps) ? patternProps : void 0;
|
|
2236
|
+
return {
|
|
2237
|
+
properties: propertyMap,
|
|
2238
|
+
required,
|
|
2239
|
+
patternProperties
|
|
2240
|
+
};
|
|
1834
2241
|
}
|
|
1835
|
-
function
|
|
1836
|
-
|
|
1837
|
-
|
|
2242
|
+
function isSingularPluralPair(left, right) {
|
|
2243
|
+
return left.length > 1 && right.length > 1 && (left === `${right}s` || right === `${left}s`);
|
|
2244
|
+
}
|
|
2245
|
+
function snakeToCamel(value) {
|
|
2246
|
+
const trimmed = value.replace(LEADING_UNDERSCORES_REGEX, "");
|
|
2247
|
+
if (trimmed.length === 0) {
|
|
2248
|
+
return value;
|
|
1838
2249
|
}
|
|
1839
|
-
|
|
2250
|
+
const camelized = trimmed.replace(
|
|
2251
|
+
SNAKE_SEGMENT_REGEX,
|
|
2252
|
+
(_, c) => c.toUpperCase()
|
|
2253
|
+
);
|
|
2254
|
+
return camelized.charAt(0).toLowerCase() + camelized.slice(1);
|
|
1840
2255
|
}
|
|
1841
|
-
function
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
2256
|
+
function camelToSnake(value) {
|
|
2257
|
+
return value.replace(CAMEL_BOUNDARY_REGEX, "$1_$2").toLowerCase();
|
|
2258
|
+
}
|
|
2259
|
+
function isCaseStylePair(targetKey, sourceKey) {
|
|
2260
|
+
if (targetKey === sourceKey) {
|
|
2261
|
+
return false;
|
|
2262
|
+
}
|
|
2263
|
+
const sourceLooksSnake = sourceKey.includes("_");
|
|
2264
|
+
const targetLooksSnake = targetKey.includes("_");
|
|
2265
|
+
if (sourceLooksSnake && snakeToCamel(sourceKey) === targetKey) {
|
|
2266
|
+
return true;
|
|
2267
|
+
}
|
|
2268
|
+
if (!sourceLooksSnake && targetLooksSnake && camelToSnake(sourceKey) === targetKey) {
|
|
2269
|
+
return true;
|
|
2270
|
+
}
|
|
2271
|
+
return false;
|
|
2272
|
+
}
|
|
2273
|
+
function isUnexpectedKey(key, schemaInfo) {
|
|
2274
|
+
if (Object.hasOwn(schemaInfo.properties, key)) {
|
|
2275
|
+
return false;
|
|
2276
|
+
}
|
|
2277
|
+
const patternSchemas = getPatternSchemasForKey(
|
|
2278
|
+
schemaInfo.patternProperties,
|
|
2279
|
+
key
|
|
2280
|
+
);
|
|
2281
|
+
if (patternSchemas.length > 0) {
|
|
2282
|
+
return patternSchemas.every((schema) => schema === false);
|
|
2283
|
+
}
|
|
2284
|
+
return true;
|
|
2285
|
+
}
|
|
2286
|
+
function computeMissingAndUnexpectedKeys(input, schemaInfo) {
|
|
2287
|
+
const missingRequired = schemaInfo.required.filter(
|
|
2288
|
+
(key) => !Object.hasOwn(input, key)
|
|
2289
|
+
);
|
|
2290
|
+
const unexpectedKeys = Object.keys(input).filter(
|
|
2291
|
+
(key) => isUnexpectedKey(key, schemaInfo)
|
|
2292
|
+
);
|
|
2293
|
+
return { missingRequired, unexpectedKeys };
|
|
2294
|
+
}
|
|
2295
|
+
function applySingularPluralRequiredKeyRename(input, schemaInfo) {
|
|
2296
|
+
const { missingRequired, unexpectedKeys } = computeMissingAndUnexpectedKeys(
|
|
2297
|
+
input,
|
|
2298
|
+
schemaInfo
|
|
2299
|
+
);
|
|
2300
|
+
if (missingRequired.length !== 1 || unexpectedKeys.length !== 1) {
|
|
2301
|
+
return null;
|
|
2302
|
+
}
|
|
2303
|
+
const targetKey = missingRequired[0];
|
|
2304
|
+
const sourceKey = unexpectedKeys[0];
|
|
2305
|
+
if (!Object.hasOwn(schemaInfo.properties, targetKey)) {
|
|
2306
|
+
return null;
|
|
2307
|
+
}
|
|
2308
|
+
if (!isSingularPluralPair(targetKey, sourceKey)) {
|
|
2309
|
+
return null;
|
|
2310
|
+
}
|
|
2311
|
+
if (getSchemaType(schemaInfo.properties[targetKey]) !== "array") {
|
|
2312
|
+
return null;
|
|
2313
|
+
}
|
|
2314
|
+
if (!Array.isArray(input[sourceKey])) {
|
|
2315
|
+
return null;
|
|
2316
|
+
}
|
|
2317
|
+
if (!Object.hasOwn(input, sourceKey) || Object.hasOwn(input, targetKey)) {
|
|
2318
|
+
return null;
|
|
2319
|
+
}
|
|
2320
|
+
const output = { ...input };
|
|
2321
|
+
output[targetKey] = output[sourceKey];
|
|
2322
|
+
delete output[sourceKey];
|
|
2323
|
+
return output;
|
|
2324
|
+
}
|
|
2325
|
+
function applyCaseStyleRequiredKeyRename(input, schemaInfo) {
|
|
2326
|
+
const { missingRequired, unexpectedKeys } = computeMissingAndUnexpectedKeys(
|
|
2327
|
+
input,
|
|
2328
|
+
schemaInfo
|
|
2329
|
+
);
|
|
2330
|
+
if (missingRequired.length !== 1 || unexpectedKeys.length !== 1) {
|
|
2331
|
+
return null;
|
|
2332
|
+
}
|
|
2333
|
+
const targetKey = missingRequired[0];
|
|
2334
|
+
const sourceKey = unexpectedKeys[0];
|
|
2335
|
+
if (!Object.hasOwn(schemaInfo.properties, targetKey)) {
|
|
2336
|
+
return null;
|
|
2337
|
+
}
|
|
2338
|
+
if (!isCaseStylePair(targetKey, sourceKey)) {
|
|
2339
|
+
return null;
|
|
2340
|
+
}
|
|
2341
|
+
if (!Object.hasOwn(input, sourceKey) || Object.hasOwn(input, targetKey)) {
|
|
2342
|
+
return null;
|
|
2343
|
+
}
|
|
2344
|
+
const output = { ...input };
|
|
2345
|
+
output[targetKey] = output[sourceKey];
|
|
2346
|
+
delete output[sourceKey];
|
|
2347
|
+
return output;
|
|
2348
|
+
}
|
|
2349
|
+
function applyStrictRequiredKeyRename(input, unwrapped) {
|
|
2350
|
+
const schemaInfo = getStrictObjectSchemaInfo(unwrapped);
|
|
2351
|
+
if (!schemaInfo) {
|
|
2352
|
+
return input;
|
|
2353
|
+
}
|
|
2354
|
+
const singularPlural = applySingularPluralRequiredKeyRename(
|
|
2355
|
+
input,
|
|
2356
|
+
schemaInfo
|
|
2357
|
+
);
|
|
2358
|
+
if (singularPlural) {
|
|
2359
|
+
return singularPlural;
|
|
2360
|
+
}
|
|
2361
|
+
const caseStyle = applyCaseStyleRequiredKeyRename(input, schemaInfo);
|
|
2362
|
+
if (caseStyle) {
|
|
2363
|
+
return caseStyle;
|
|
2364
|
+
}
|
|
2365
|
+
return input;
|
|
2366
|
+
}
|
|
2367
|
+
function coerceObjectToObject(value, unwrapped) {
|
|
2368
|
+
const normalizedInput = applyStrictRequiredKeyRename(value, unwrapped);
|
|
2369
|
+
const out = {};
|
|
2370
|
+
for (const [k, v] of Object.entries(normalizedInput)) {
|
|
2371
|
+
out[k] = coerceValueForKey(v, k, unwrapped);
|
|
2372
|
+
}
|
|
2373
|
+
return out;
|
|
2374
|
+
}
|
|
2375
|
+
function coerceArrayToArray(value, prefixItems, itemsSchema) {
|
|
2376
|
+
if (prefixItems && value.length === prefixItems.length) {
|
|
2377
|
+
return value.map((v, i) => coerceBySchema(v, prefixItems[i]));
|
|
2378
|
+
}
|
|
2379
|
+
return value.map((v) => coerceBySchema(v, itemsSchema));
|
|
2380
|
+
}
|
|
2381
|
+
function isPrimitiveSchemaType(schemaType) {
|
|
2382
|
+
return schemaType === "string" || schemaType === "number" || schemaType === "integer" || schemaType === "boolean";
|
|
2383
|
+
}
|
|
2384
|
+
function isPrimitiveMatchForSchemaType(value, schemaType) {
|
|
2385
|
+
if (schemaType === "string") {
|
|
2386
|
+
return typeof value === "string";
|
|
2387
|
+
}
|
|
2388
|
+
if (schemaType === "number") {
|
|
2389
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
2390
|
+
}
|
|
2391
|
+
if (schemaType === "integer") {
|
|
2392
|
+
return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value);
|
|
2393
|
+
}
|
|
2394
|
+
return typeof value === "boolean";
|
|
2395
|
+
}
|
|
2396
|
+
function coercePrimitiveWrappedObject(value, itemsSchema) {
|
|
2397
|
+
const schemaType = getSchemaType(itemsSchema);
|
|
2398
|
+
if (!isPrimitiveSchemaType(schemaType)) {
|
|
2399
|
+
return null;
|
|
2400
|
+
}
|
|
2401
|
+
const keys = Object.keys(value);
|
|
2402
|
+
if (keys.length !== 1) {
|
|
2403
|
+
return null;
|
|
2404
|
+
}
|
|
2405
|
+
const singleValue = value[keys[0]];
|
|
2406
|
+
if (singleValue && typeof singleValue === "object") {
|
|
2407
|
+
return null;
|
|
2408
|
+
}
|
|
2409
|
+
const coerced = coerceBySchema(singleValue, itemsSchema);
|
|
2410
|
+
return isPrimitiveMatchForSchemaType(coerced, schemaType) ? coerced : null;
|
|
2411
|
+
}
|
|
2412
|
+
function coerceParallelArraysObjectToArray(maybe, prefixItems, itemsSchema) {
|
|
2413
|
+
if (prefixItems && prefixItems.length > 0) {
|
|
2414
|
+
return null;
|
|
2415
|
+
}
|
|
2416
|
+
const unwrappedItems = unwrapJsonSchema(itemsSchema);
|
|
2417
|
+
if (!unwrappedItems || typeof unwrappedItems !== "object" || Array.isArray(unwrappedItems)) {
|
|
2418
|
+
return null;
|
|
2419
|
+
}
|
|
2420
|
+
const itemSchema = unwrappedItems;
|
|
2421
|
+
if (getSchemaType(itemSchema) !== "object") {
|
|
2422
|
+
return null;
|
|
2423
|
+
}
|
|
2424
|
+
if (itemSchema.additionalProperties !== false) {
|
|
2425
|
+
return null;
|
|
2426
|
+
}
|
|
2427
|
+
const properties = itemSchema.properties;
|
|
2428
|
+
if (!properties || typeof properties !== "object" || Array.isArray(properties)) {
|
|
2429
|
+
return null;
|
|
2430
|
+
}
|
|
2431
|
+
const propertyMap = properties;
|
|
2432
|
+
const entries = Object.entries(maybe);
|
|
2433
|
+
if (entries.length < 2) {
|
|
2434
|
+
return null;
|
|
2435
|
+
}
|
|
2436
|
+
if (!entries.every(([, value]) => Array.isArray(value))) {
|
|
2437
|
+
return null;
|
|
2438
|
+
}
|
|
2439
|
+
if (!entries.every(([key]) => Object.hasOwn(propertyMap, key))) {
|
|
2440
|
+
return null;
|
|
2441
|
+
}
|
|
2442
|
+
if (!entries.every(([key]) => {
|
|
2443
|
+
const schemaType = getSchemaType(propertyMap[key]);
|
|
2444
|
+
return schemaType !== "array" && schemaType !== "object";
|
|
2445
|
+
})) {
|
|
2446
|
+
return null;
|
|
2447
|
+
}
|
|
2448
|
+
const lengths = [
|
|
2449
|
+
...new Set(entries.map(([, value]) => value.length))
|
|
2450
|
+
];
|
|
2451
|
+
if (lengths.length !== 1) {
|
|
2452
|
+
return null;
|
|
2453
|
+
}
|
|
2454
|
+
const length = lengths[0];
|
|
2455
|
+
if (length < 2) {
|
|
2456
|
+
return null;
|
|
2457
|
+
}
|
|
2458
|
+
const zipped = [];
|
|
2459
|
+
for (let index = 0; index < length; index += 1) {
|
|
2460
|
+
const item = {};
|
|
2461
|
+
for (const [key, value] of entries) {
|
|
2462
|
+
item[key] = value[index];
|
|
2463
|
+
}
|
|
2464
|
+
zipped.push(item);
|
|
2465
|
+
}
|
|
2466
|
+
return coerceArrayToArray(zipped, prefixItems, itemsSchema);
|
|
2467
|
+
}
|
|
2468
|
+
function coerceSingleKeyObjectToArray(singleValue, itemsSchema) {
|
|
2469
|
+
if (Array.isArray(singleValue)) {
|
|
2470
|
+
return singleValue.map((v) => coerceBySchema(v, itemsSchema));
|
|
2471
|
+
}
|
|
2472
|
+
if (singleValue && typeof singleValue === "object") {
|
|
2473
|
+
const primitiveWrapped = coercePrimitiveWrappedObject(
|
|
2474
|
+
singleValue,
|
|
2475
|
+
itemsSchema
|
|
2476
|
+
);
|
|
2477
|
+
if (primitiveWrapped !== null) {
|
|
2478
|
+
return [primitiveWrapped];
|
|
2479
|
+
}
|
|
2480
|
+
return [coerceBySchema(singleValue, itemsSchema)];
|
|
2481
|
+
}
|
|
2482
|
+
return null;
|
|
2483
|
+
}
|
|
2484
|
+
function coerceObjectToArray(maybe, prefixItems, itemsSchema) {
|
|
2485
|
+
if (Object.hasOwn(maybe, "item")) {
|
|
2486
|
+
const items = maybe.item;
|
|
2487
|
+
const arr = Array.isArray(items) ? items : [items];
|
|
2488
|
+
return coerceArrayToArray(arr, prefixItems, itemsSchema);
|
|
1846
2489
|
}
|
|
1847
2490
|
const keys = Object.keys(maybe);
|
|
1848
2491
|
if (keys.length > 0 && keys.every((k) => DIGIT_KEY_REGEX.test(k))) {
|
|
1849
2492
|
const arr = keys.sort((a, b) => Number(a) - Number(b)).map((k) => maybe[k]);
|
|
1850
2493
|
return coerceArrayToArray(arr, prefixItems, itemsSchema);
|
|
1851
2494
|
}
|
|
2495
|
+
const parallelArrays = coerceParallelArraysObjectToArray(
|
|
2496
|
+
maybe,
|
|
2497
|
+
prefixItems,
|
|
2498
|
+
itemsSchema
|
|
2499
|
+
);
|
|
2500
|
+
if (parallelArrays !== null) {
|
|
2501
|
+
return parallelArrays;
|
|
2502
|
+
}
|
|
1852
2503
|
if (keys.length === 1) {
|
|
1853
2504
|
const singleKey = keys[0];
|
|
1854
2505
|
if (!(schemaIsUnconstrained(itemsSchema) || schemaHasProperty(itemsSchema, singleKey))) {
|
|
1855
|
-
const
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
if (
|
|
1860
|
-
return
|
|
2506
|
+
const result = coerceSingleKeyObjectToArray(
|
|
2507
|
+
maybe[singleKey],
|
|
2508
|
+
itemsSchema
|
|
2509
|
+
);
|
|
2510
|
+
if (result !== null) {
|
|
2511
|
+
return result;
|
|
1861
2512
|
}
|
|
1862
2513
|
}
|
|
1863
2514
|
}
|
|
@@ -1887,6 +2538,86 @@ function coerceStringToPrimitive(s, schemaType) {
|
|
|
1887
2538
|
}
|
|
1888
2539
|
return null;
|
|
1889
2540
|
}
|
|
2541
|
+
function coercePrimitiveToString(value, schemaType) {
|
|
2542
|
+
if (schemaType !== "string") {
|
|
2543
|
+
return null;
|
|
2544
|
+
}
|
|
2545
|
+
if (typeof value === "boolean") {
|
|
2546
|
+
return value ? "true" : "false";
|
|
2547
|
+
}
|
|
2548
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2549
|
+
return String(value);
|
|
2550
|
+
}
|
|
2551
|
+
return null;
|
|
2552
|
+
}
|
|
2553
|
+
function coerceStringByEnumWhitespace(rawValue, unwrapped) {
|
|
2554
|
+
const enumValues = unwrapped.enum;
|
|
2555
|
+
if (!Array.isArray(enumValues) || enumValues.length === 0) {
|
|
2556
|
+
return null;
|
|
2557
|
+
}
|
|
2558
|
+
if (!enumValues.every((item) => typeof item === "string")) {
|
|
2559
|
+
return null;
|
|
2560
|
+
}
|
|
2561
|
+
const normalizedEnumValues = enumValues;
|
|
2562
|
+
if (normalizedEnumValues.includes(rawValue)) {
|
|
2563
|
+
return null;
|
|
2564
|
+
}
|
|
2565
|
+
const unquoted = unwrapMatchingQuotes(rawValue);
|
|
2566
|
+
if (unquoted !== null) {
|
|
2567
|
+
const exactMatches = normalizedEnumValues.filter(
|
|
2568
|
+
(item) => item === unquoted
|
|
2569
|
+
);
|
|
2570
|
+
if (exactMatches.length === 1) {
|
|
2571
|
+
return exactMatches[0];
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
const candidates = [rawValue, unquoted].filter(
|
|
2575
|
+
(item) => item !== null
|
|
2576
|
+
);
|
|
2577
|
+
for (const candidate of candidates) {
|
|
2578
|
+
if (!HAS_WHITESPACE_REGEX.test(candidate)) {
|
|
2579
|
+
continue;
|
|
2580
|
+
}
|
|
2581
|
+
const normalizedInput = candidate.replace(WHITESPACE_REGEX2, "");
|
|
2582
|
+
const matches = normalizedEnumValues.filter(
|
|
2583
|
+
(item) => item.replace(WHITESPACE_REGEX2, "") === normalizedInput
|
|
2584
|
+
);
|
|
2585
|
+
if (matches.length === 1) {
|
|
2586
|
+
return matches[0];
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
return null;
|
|
2590
|
+
}
|
|
2591
|
+
function unwrapMatchingQuotes(value) {
|
|
2592
|
+
if (value.length < 2) {
|
|
2593
|
+
return null;
|
|
2594
|
+
}
|
|
2595
|
+
const first = value[0];
|
|
2596
|
+
const last = value.at(-1);
|
|
2597
|
+
const isQuote = (first === SINGLE_QUOTE || first === DOUBLE_QUOTE) && first === last;
|
|
2598
|
+
if (!isQuote) {
|
|
2599
|
+
return null;
|
|
2600
|
+
}
|
|
2601
|
+
return value.slice(1, -1);
|
|
2602
|
+
}
|
|
2603
|
+
function coerceObjectToPrimitive(value, schemaType, fullSchema) {
|
|
2604
|
+
if (!isPrimitiveSchemaType(schemaType)) {
|
|
2605
|
+
return null;
|
|
2606
|
+
}
|
|
2607
|
+
const keys = Object.keys(value);
|
|
2608
|
+
if (keys.length !== 1) {
|
|
2609
|
+
return null;
|
|
2610
|
+
}
|
|
2611
|
+
const singleValue = value[keys[0]];
|
|
2612
|
+
if (singleValue && typeof singleValue === "object") {
|
|
2613
|
+
return null;
|
|
2614
|
+
}
|
|
2615
|
+
const coerced = coerceBySchema(
|
|
2616
|
+
singleValue,
|
|
2617
|
+
fullSchema != null ? fullSchema : { type: schemaType }
|
|
2618
|
+
);
|
|
2619
|
+
return isPrimitiveMatchForSchemaType(coerced, schemaType) ? coerced : null;
|
|
2620
|
+
}
|
|
1890
2621
|
function coerceStringValue(value, schemaType, u) {
|
|
1891
2622
|
const s = value.trim();
|
|
1892
2623
|
if (schemaType === "object") {
|
|
@@ -1905,6 +2636,10 @@ function coerceStringValue(value, schemaType, u) {
|
|
|
1905
2636
|
if (primitiveResult !== null) {
|
|
1906
2637
|
return primitiveResult;
|
|
1907
2638
|
}
|
|
2639
|
+
const enumWhitespaceCanonical = coerceStringByEnumWhitespace(s, u);
|
|
2640
|
+
if (enumWhitespaceCanonical !== null) {
|
|
2641
|
+
return enumWhitespaceCanonical;
|
|
2642
|
+
}
|
|
1908
2643
|
return value;
|
|
1909
2644
|
}
|
|
1910
2645
|
function coerceArrayValue(value, prefixItems, itemsSchema) {
|
|
@@ -1943,9 +2678,23 @@ function coerceBySchema(value, schema) {
|
|
|
1943
2678
|
if (typeof value === "string") {
|
|
1944
2679
|
return coerceStringValue(value, schemaType, u);
|
|
1945
2680
|
}
|
|
2681
|
+
const primitiveString = coercePrimitiveToString(value, schemaType);
|
|
2682
|
+
if (primitiveString !== null) {
|
|
2683
|
+
return primitiveString;
|
|
2684
|
+
}
|
|
1946
2685
|
if (schemaType === "object" && value && typeof value === "object" && !Array.isArray(value)) {
|
|
1947
2686
|
return coerceObjectToObject(value, u);
|
|
1948
2687
|
}
|
|
2688
|
+
if (value && typeof value === "object" && !Array.isArray(value) && isPrimitiveSchemaType(schemaType)) {
|
|
2689
|
+
const primitiveResult = coerceObjectToPrimitive(
|
|
2690
|
+
value,
|
|
2691
|
+
schemaType,
|
|
2692
|
+
u
|
|
2693
|
+
);
|
|
2694
|
+
if (primitiveResult !== null) {
|
|
2695
|
+
return primitiveResult;
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
1949
2698
|
if (schemaType === "array") {
|
|
1950
2699
|
const prefixItems = Array.isArray(u.prefixItems) ? u.prefixItems : void 0;
|
|
1951
2700
|
const itemsSchema = u.items;
|
|
@@ -2960,7 +3709,7 @@ var XMLTokenizer = class {
|
|
|
2960
3709
|
};
|
|
2961
3710
|
|
|
2962
3711
|
// src/rxml/core/parser.ts
|
|
2963
|
-
var
|
|
3712
|
+
var WHITESPACE_REGEX3 = /\s/;
|
|
2964
3713
|
var NUMERIC_STRING_REGEX = /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
|
|
2965
3714
|
var DIGIT_KEY_REGEX2 = /^\d+$/;
|
|
2966
3715
|
function getTopLevelStringProps(s) {
|
|
@@ -3130,7 +3879,7 @@ function parse2(xmlInner, schema, options = {}) {
|
|
|
3130
3879
|
const closeHead = s.indexOf(`</${rootName}`, range.end);
|
|
3131
3880
|
if (closeHead === range.end) {
|
|
3132
3881
|
let p = closeHead + 2 + rootName.length;
|
|
3133
|
-
while (p < s.length &&
|
|
3882
|
+
while (p < s.length && WHITESPACE_REGEX3.test(s[p])) {
|
|
3134
3883
|
p += 1;
|
|
3135
3884
|
}
|
|
3136
3885
|
if (s[p] === ">") {
|
|
@@ -3468,7 +4217,7 @@ function createIntermediateCall(toolName, rawSegment, schema) {
|
|
|
3468
4217
|
var MALFORMED_CLOSE_RE_G = /<\/\s+([A-Za-z0-9_:-]+)\s*>/g;
|
|
3469
4218
|
var MALFORMED_CLOSE_RE = /<\/\s+([A-Za-z0-9_:-]+)\s*>/;
|
|
3470
4219
|
var STATUS_TO_STEP_BOUNDARY_RE = /<\/status>\s*<step>/g;
|
|
3471
|
-
var
|
|
4220
|
+
var WHITESPACE_REGEX4 = /\s/;
|
|
3472
4221
|
var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
|
|
3473
4222
|
var NAME_START_CHAR_RE = /[A-Za-z_:]/;
|
|
3474
4223
|
var STEP_TAG_RE = /<step>([\s\S]*?)<\/step>/i;
|
|
@@ -3609,7 +4358,7 @@ function balanceTags(xml) {
|
|
|
3609
4358
|
}
|
|
3610
4359
|
function skipWs(s, p, len) {
|
|
3611
4360
|
let idx = p;
|
|
3612
|
-
while (idx < len &&
|
|
4361
|
+
while (idx < len && WHITESPACE_REGEX4.test(s[idx])) {
|
|
3613
4362
|
idx += 1;
|
|
3614
4363
|
}
|
|
3615
4364
|
return idx;
|
|
@@ -3662,7 +4411,7 @@ function handleOpeningTagSegment(src, lt, out, stack) {
|
|
|
3662
4411
|
return len;
|
|
3663
4412
|
}
|
|
3664
4413
|
let r = q - 1;
|
|
3665
|
-
while (r >= nameStart &&
|
|
4414
|
+
while (r >= nameStart && WHITESPACE_REGEX4.test(src[r])) {
|
|
3666
4415
|
r -= 1;
|
|
3667
4416
|
}
|
|
3668
4417
|
const selfClosing = src[r] === "/";
|
|
@@ -3826,13 +4575,114 @@ function parse3(xml, schema, options = {}) {
|
|
|
3826
4575
|
|
|
3827
4576
|
// src/core/utils/regex-constants.ts
|
|
3828
4577
|
var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
|
|
3829
|
-
var
|
|
4578
|
+
var WHITESPACE_REGEX5 = /\s/;
|
|
4579
|
+
|
|
4580
|
+
// src/core/utils/streamed-tool-input-delta.ts
|
|
4581
|
+
function emitDelta({
|
|
4582
|
+
controller,
|
|
4583
|
+
id,
|
|
4584
|
+
state,
|
|
4585
|
+
nextInput
|
|
4586
|
+
}) {
|
|
4587
|
+
if (!nextInput.startsWith(state.emittedInput)) {
|
|
4588
|
+
return false;
|
|
4589
|
+
}
|
|
4590
|
+
const delta = nextInput.slice(state.emittedInput.length);
|
|
4591
|
+
if (delta.length === 0) {
|
|
4592
|
+
return false;
|
|
4593
|
+
}
|
|
4594
|
+
controller.enqueue({
|
|
4595
|
+
type: "tool-input-delta",
|
|
4596
|
+
id,
|
|
4597
|
+
delta
|
|
4598
|
+
});
|
|
4599
|
+
state.emittedInput = nextInput;
|
|
4600
|
+
return true;
|
|
4601
|
+
}
|
|
4602
|
+
function toIncompleteJsonPrefix(fullJson) {
|
|
4603
|
+
const trimmed = fullJson.trim();
|
|
4604
|
+
let prefix = trimmed;
|
|
4605
|
+
while (prefix.endsWith("}") || prefix.endsWith("]")) {
|
|
4606
|
+
prefix = prefix.slice(0, -1);
|
|
4607
|
+
}
|
|
4608
|
+
prefix = prefix.trimEnd();
|
|
4609
|
+
if (prefix.endsWith('"')) {
|
|
4610
|
+
prefix = prefix.slice(0, -1);
|
|
4611
|
+
}
|
|
4612
|
+
if (prefix.length === 0) {
|
|
4613
|
+
if (trimmed.startsWith("[") || trimmed.startsWith("{")) {
|
|
4614
|
+
return trimmed.startsWith("{") ? "{" : "[";
|
|
4615
|
+
}
|
|
4616
|
+
if (trimmed.startsWith("]")) {
|
|
4617
|
+
return "[";
|
|
4618
|
+
}
|
|
4619
|
+
if (trimmed.startsWith("}")) {
|
|
4620
|
+
return "{";
|
|
4621
|
+
}
|
|
4622
|
+
if (trimmed.startsWith('"')) {
|
|
4623
|
+
return '"';
|
|
4624
|
+
}
|
|
4625
|
+
return "{";
|
|
4626
|
+
}
|
|
4627
|
+
return prefix;
|
|
4628
|
+
}
|
|
4629
|
+
function emitPrefixDelta(params) {
|
|
4630
|
+
return emitDelta({
|
|
4631
|
+
...params,
|
|
4632
|
+
nextInput: params.candidate
|
|
4633
|
+
});
|
|
4634
|
+
}
|
|
4635
|
+
function emitFinalRemainder(params) {
|
|
4636
|
+
var _a;
|
|
4637
|
+
const result = emitDelta({
|
|
4638
|
+
...params,
|
|
4639
|
+
nextInput: params.finalFullJson
|
|
4640
|
+
});
|
|
4641
|
+
if (!result && params.state.emittedInput.length > 0) {
|
|
4642
|
+
(_a = params.onMismatch) == null ? void 0 : _a.call(
|
|
4643
|
+
params,
|
|
4644
|
+
"Final JSON does not extend emitted tool-input prefix",
|
|
4645
|
+
{
|
|
4646
|
+
emittedLength: params.state.emittedInput.length,
|
|
4647
|
+
finalLength: params.finalFullJson.length
|
|
4648
|
+
}
|
|
4649
|
+
);
|
|
4650
|
+
}
|
|
4651
|
+
return result;
|
|
4652
|
+
}
|
|
4653
|
+
|
|
4654
|
+
// src/core/utils/xml-root-repair.ts
|
|
4655
|
+
var XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX = /^<([A-Za-z_][A-Za-z0-9_-]*)\s*\r?\n([\s\S]+?)\r?\n\s*\/>\s*$/;
|
|
4656
|
+
function tryRepairXmlSelfClosingRootWithBody(rawText, toolNames) {
|
|
4657
|
+
const trimmed = rawText.trim();
|
|
4658
|
+
if (trimmed.length === 0) {
|
|
4659
|
+
return null;
|
|
4660
|
+
}
|
|
4661
|
+
const match = trimmed.match(XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX);
|
|
4662
|
+
if (!match) {
|
|
4663
|
+
return null;
|
|
4664
|
+
}
|
|
4665
|
+
const rootTag = match[1];
|
|
4666
|
+
if (!toolNames.includes(rootTag)) {
|
|
4667
|
+
return null;
|
|
4668
|
+
}
|
|
4669
|
+
const body = match[2].trimEnd();
|
|
4670
|
+
if (body.trim().length === 0 || body.includes(`</${rootTag}>`)) {
|
|
4671
|
+
return null;
|
|
4672
|
+
}
|
|
4673
|
+
return `<${rootTag}>
|
|
4674
|
+
${body}
|
|
4675
|
+
</${rootTag}>`;
|
|
4676
|
+
}
|
|
3830
4677
|
|
|
3831
4678
|
// src/core/protocols/xml-protocol.ts
|
|
3832
4679
|
function getToolSchema(tools, toolName) {
|
|
3833
4680
|
var _a;
|
|
3834
4681
|
return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
3835
4682
|
}
|
|
4683
|
+
function shouldEmitRawToolCallTextOnError2(options) {
|
|
4684
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
4685
|
+
}
|
|
3836
4686
|
function processToolCall(params) {
|
|
3837
4687
|
var _a, _b;
|
|
3838
4688
|
const { toolCall, tools, options, text, processedElements, parseOptions } = params;
|
|
@@ -3845,7 +4695,7 @@ function processToolCall(params) {
|
|
|
3845
4695
|
const parsed = parse3(toolCall.content, toolSchema, parseConfig);
|
|
3846
4696
|
processedElements.push({
|
|
3847
4697
|
type: "tool-call",
|
|
3848
|
-
toolCallId:
|
|
4698
|
+
toolCallId: generateToolCallId(),
|
|
3849
4699
|
toolName: toolCall.toolName,
|
|
3850
4700
|
input: JSON.stringify(parsed)
|
|
3851
4701
|
});
|
|
@@ -3862,60 +4712,371 @@ function processToolCall(params) {
|
|
|
3862
4712
|
processedElements.push({ type: "text", text: originalCallText });
|
|
3863
4713
|
}
|
|
3864
4714
|
}
|
|
3865
|
-
function
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
currentToolCall,
|
|
3870
|
-
tools,
|
|
3871
|
-
options,
|
|
3872
|
-
ctrl,
|
|
3873
|
-
flushText,
|
|
3874
|
-
parseOptions
|
|
3875
|
-
} = params;
|
|
3876
|
-
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
3877
|
-
const parseConfig = {
|
|
3878
|
-
...parseOptions != null ? parseOptions : {},
|
|
3879
|
-
onError: (_a = options == null ? void 0 : options.onError) != null ? _a : parseOptions == null ? void 0 : parseOptions.onError
|
|
3880
|
-
};
|
|
3881
|
-
flushText(ctrl);
|
|
3882
|
-
try {
|
|
3883
|
-
const parsedResult = parse3(toolContent, toolSchema, parseConfig);
|
|
3884
|
-
ctrl.enqueue({
|
|
3885
|
-
type: "tool-call",
|
|
3886
|
-
toolCallId: generateId(),
|
|
3887
|
-
toolName: currentToolCall.name,
|
|
3888
|
-
input: JSON.stringify(parsedResult)
|
|
3889
|
-
});
|
|
3890
|
-
} catch (error) {
|
|
3891
|
-
const original = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
|
|
3892
|
-
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
|
|
3893
|
-
toolCall: original,
|
|
3894
|
-
error
|
|
3895
|
-
});
|
|
3896
|
-
flushText(ctrl, original);
|
|
4715
|
+
function parseXmlTagName(rawTagBody) {
|
|
4716
|
+
let index = 0;
|
|
4717
|
+
while (index < rawTagBody.length && WHITESPACE_REGEX5.test(rawTagBody[index])) {
|
|
4718
|
+
index += 1;
|
|
3897
4719
|
}
|
|
4720
|
+
const nameStart = index;
|
|
4721
|
+
while (index < rawTagBody.length && NAME_CHAR_RE2.test(rawTagBody.charAt(index))) {
|
|
4722
|
+
index += 1;
|
|
4723
|
+
}
|
|
4724
|
+
return rawTagBody.slice(nameStart, index);
|
|
3898
4725
|
}
|
|
3899
|
-
function
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
const tok = nextTagToken(text, pos);
|
|
3904
|
-
if (tok.kind === "eof") {
|
|
3905
|
-
break;
|
|
3906
|
-
}
|
|
3907
|
-
const result = updateDepthWithToken(tok, toolName, depth);
|
|
3908
|
-
depth = result.depth;
|
|
3909
|
-
if (result.closedAt !== void 0) {
|
|
3910
|
-
return result.closedAt;
|
|
3911
|
-
}
|
|
3912
|
-
pos = tok.nextPos;
|
|
4726
|
+
function consumeXmlSpecialSection(fragment, ltIndex) {
|
|
4727
|
+
if (fragment.startsWith("<!--", ltIndex)) {
|
|
4728
|
+
const commentEnd = fragment.indexOf("-->", ltIndex + 4);
|
|
4729
|
+
return commentEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: commentEnd + 3 };
|
|
3913
4730
|
}
|
|
3914
|
-
|
|
4731
|
+
if (fragment.startsWith("<![CDATA[", ltIndex)) {
|
|
4732
|
+
const cdataEnd = fragment.indexOf("]]>", ltIndex + 9);
|
|
4733
|
+
return cdataEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: cdataEnd + 3 };
|
|
4734
|
+
}
|
|
4735
|
+
if (fragment.startsWith("<?", ltIndex)) {
|
|
4736
|
+
const processingEnd = fragment.indexOf("?>", ltIndex + 2);
|
|
4737
|
+
return processingEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: processingEnd + 2 };
|
|
4738
|
+
}
|
|
4739
|
+
if (fragment.startsWith("<!", ltIndex)) {
|
|
4740
|
+
const declarationEnd = fragment.indexOf(">", ltIndex + 2);
|
|
4741
|
+
return declarationEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: declarationEnd + 1 };
|
|
4742
|
+
}
|
|
4743
|
+
return { kind: "none" };
|
|
3915
4744
|
}
|
|
3916
|
-
function
|
|
3917
|
-
const
|
|
3918
|
-
if (
|
|
4745
|
+
function parseXmlTagToken(fragment, ltIndex) {
|
|
4746
|
+
const gtIndex = fragment.indexOf(">", ltIndex + 1);
|
|
4747
|
+
if (gtIndex === -1) {
|
|
4748
|
+
return null;
|
|
4749
|
+
}
|
|
4750
|
+
const tagBody = fragment.slice(ltIndex + 1, gtIndex).trim();
|
|
4751
|
+
if (tagBody.length === 0) {
|
|
4752
|
+
return null;
|
|
4753
|
+
}
|
|
4754
|
+
if (tagBody.startsWith("/")) {
|
|
4755
|
+
const closeName = parseXmlTagName(tagBody.slice(1));
|
|
4756
|
+
if (closeName.length === 0) {
|
|
4757
|
+
return null;
|
|
4758
|
+
}
|
|
4759
|
+
return { kind: "close", name: closeName, nextPos: gtIndex + 1 };
|
|
4760
|
+
}
|
|
4761
|
+
const selfClosing = tagBody.endsWith("/");
|
|
4762
|
+
const openBody = selfClosing ? tagBody.slice(0, -1).trimEnd() : tagBody;
|
|
4763
|
+
const openName = parseXmlTagName(openBody);
|
|
4764
|
+
if (openName.length === 0) {
|
|
4765
|
+
return null;
|
|
4766
|
+
}
|
|
4767
|
+
return {
|
|
4768
|
+
kind: "open",
|
|
4769
|
+
name: openName,
|
|
4770
|
+
selfClosing,
|
|
4771
|
+
nextPos: gtIndex + 1
|
|
4772
|
+
};
|
|
4773
|
+
}
|
|
4774
|
+
function analyzeXmlFragmentForProgress(fragment) {
|
|
4775
|
+
const stack = [];
|
|
4776
|
+
const topLevelTagNames = [];
|
|
4777
|
+
let position = 0;
|
|
4778
|
+
while (position < fragment.length) {
|
|
4779
|
+
const ltIndex = fragment.indexOf("<", position);
|
|
4780
|
+
if (ltIndex === -1) {
|
|
4781
|
+
break;
|
|
4782
|
+
}
|
|
4783
|
+
const special = consumeXmlSpecialSection(fragment, ltIndex);
|
|
4784
|
+
if (special.kind === "incomplete") {
|
|
4785
|
+
return null;
|
|
4786
|
+
}
|
|
4787
|
+
if (special.kind === "consumed") {
|
|
4788
|
+
position = special.nextPos;
|
|
4789
|
+
continue;
|
|
4790
|
+
}
|
|
4791
|
+
const token = parseXmlTagToken(fragment, ltIndex);
|
|
4792
|
+
if (token === null) {
|
|
4793
|
+
return null;
|
|
4794
|
+
}
|
|
4795
|
+
if (token.kind === "close") {
|
|
4796
|
+
const openName = stack.pop();
|
|
4797
|
+
if (!openName || openName !== token.name) {
|
|
4798
|
+
return null;
|
|
4799
|
+
}
|
|
4800
|
+
position = token.nextPos;
|
|
4801
|
+
continue;
|
|
4802
|
+
}
|
|
4803
|
+
if (stack.length === 0) {
|
|
4804
|
+
topLevelTagNames.push(token.name);
|
|
4805
|
+
}
|
|
4806
|
+
if (!token.selfClosing) {
|
|
4807
|
+
stack.push(token.name);
|
|
4808
|
+
}
|
|
4809
|
+
position = token.nextPos;
|
|
4810
|
+
}
|
|
4811
|
+
if (stack.length > 0) {
|
|
4812
|
+
return null;
|
|
4813
|
+
}
|
|
4814
|
+
return { topLevelTagNames };
|
|
4815
|
+
}
|
|
4816
|
+
function scanXmlFragmentTopLevelTextStep(options) {
|
|
4817
|
+
const { fragment, position, stack } = options;
|
|
4818
|
+
const ltIndex = fragment.indexOf("<", position);
|
|
4819
|
+
if (ltIndex === -1) {
|
|
4820
|
+
const trailingText = fragment.slice(position);
|
|
4821
|
+
return {
|
|
4822
|
+
kind: "done",
|
|
4823
|
+
value: stack.length === 0 && trailingText.trim().length > 0
|
|
4824
|
+
};
|
|
4825
|
+
}
|
|
4826
|
+
const textBetweenTags = fragment.slice(position, ltIndex);
|
|
4827
|
+
if (stack.length === 0 && textBetweenTags.trim().length > 0) {
|
|
4828
|
+
return { kind: "found" };
|
|
4829
|
+
}
|
|
4830
|
+
const special = consumeXmlSpecialSection(fragment, ltIndex);
|
|
4831
|
+
if (special.kind === "incomplete") {
|
|
4832
|
+
return { kind: "invalid" };
|
|
4833
|
+
}
|
|
4834
|
+
if (special.kind === "consumed") {
|
|
4835
|
+
return { kind: "next", nextPos: special.nextPos };
|
|
4836
|
+
}
|
|
4837
|
+
const token = parseXmlTagToken(fragment, ltIndex);
|
|
4838
|
+
if (token === null) {
|
|
4839
|
+
return { kind: "invalid" };
|
|
4840
|
+
}
|
|
4841
|
+
if (token.kind === "close") {
|
|
4842
|
+
const openName = stack.pop();
|
|
4843
|
+
if (!openName || openName !== token.name) {
|
|
4844
|
+
return { kind: "invalid" };
|
|
4845
|
+
}
|
|
4846
|
+
} else if (!token.selfClosing) {
|
|
4847
|
+
stack.push(token.name);
|
|
4848
|
+
}
|
|
4849
|
+
return { kind: "next", nextPos: token.nextPos };
|
|
4850
|
+
}
|
|
4851
|
+
function hasNonWhitespaceTopLevelText(fragment) {
|
|
4852
|
+
if (!fragment.includes("<")) {
|
|
4853
|
+
return fragment.trim().length > 0;
|
|
4854
|
+
}
|
|
4855
|
+
const stack = [];
|
|
4856
|
+
let position = 0;
|
|
4857
|
+
while (position < fragment.length) {
|
|
4858
|
+
const step = scanXmlFragmentTopLevelTextStep({ fragment, position, stack });
|
|
4859
|
+
if (step.kind === "found") {
|
|
4860
|
+
return true;
|
|
4861
|
+
}
|
|
4862
|
+
if (step.kind === "invalid") {
|
|
4863
|
+
return false;
|
|
4864
|
+
}
|
|
4865
|
+
if (step.kind === "done") {
|
|
4866
|
+
return step.value;
|
|
4867
|
+
}
|
|
4868
|
+
position = step.nextPos;
|
|
4869
|
+
}
|
|
4870
|
+
return false;
|
|
4871
|
+
}
|
|
4872
|
+
function getObjectSchemaPropertyNames(schema) {
|
|
4873
|
+
if (!schema || typeof schema !== "object") {
|
|
4874
|
+
return null;
|
|
4875
|
+
}
|
|
4876
|
+
const schemaObject = schema;
|
|
4877
|
+
const typeValue = schemaObject.type;
|
|
4878
|
+
if (typeValue != null) {
|
|
4879
|
+
const isObjectType = typeValue === "object" || Array.isArray(typeValue) && typeValue.includes("object");
|
|
4880
|
+
if (!isObjectType) {
|
|
4881
|
+
return null;
|
|
4882
|
+
}
|
|
4883
|
+
}
|
|
4884
|
+
if (!schemaObject.properties || typeof schemaObject.properties !== "object") {
|
|
4885
|
+
return /* @__PURE__ */ new Set();
|
|
4886
|
+
}
|
|
4887
|
+
return new Set(
|
|
4888
|
+
Object.keys(schemaObject.properties)
|
|
4889
|
+
);
|
|
4890
|
+
}
|
|
4891
|
+
function schemaAllowsArrayType(schema) {
|
|
4892
|
+
if (!schema || typeof schema !== "object") {
|
|
4893
|
+
return false;
|
|
4894
|
+
}
|
|
4895
|
+
const schemaRecord = schema;
|
|
4896
|
+
const typeValue = schemaRecord.type;
|
|
4897
|
+
if (typeValue === "array") {
|
|
4898
|
+
return true;
|
|
4899
|
+
}
|
|
4900
|
+
if (Array.isArray(typeValue) && typeValue.includes("array")) {
|
|
4901
|
+
return true;
|
|
4902
|
+
}
|
|
4903
|
+
const unions = [schemaRecord.anyOf, schemaRecord.oneOf, schemaRecord.allOf];
|
|
4904
|
+
for (const union of unions) {
|
|
4905
|
+
if (!Array.isArray(union)) {
|
|
4906
|
+
continue;
|
|
4907
|
+
}
|
|
4908
|
+
if (union.some((entry) => schemaAllowsArrayType(entry))) {
|
|
4909
|
+
return true;
|
|
4910
|
+
}
|
|
4911
|
+
}
|
|
4912
|
+
return false;
|
|
4913
|
+
}
|
|
4914
|
+
function getSchemaObjectProperty(schema, propertyName) {
|
|
4915
|
+
if (!schema || typeof schema !== "object") {
|
|
4916
|
+
return null;
|
|
4917
|
+
}
|
|
4918
|
+
const schemaObject = schema;
|
|
4919
|
+
const properties = schemaObject.properties;
|
|
4920
|
+
if (!properties || typeof properties !== "object") {
|
|
4921
|
+
return null;
|
|
4922
|
+
}
|
|
4923
|
+
const property = properties[propertyName];
|
|
4924
|
+
if (!property) {
|
|
4925
|
+
return null;
|
|
4926
|
+
}
|
|
4927
|
+
return property;
|
|
4928
|
+
}
|
|
4929
|
+
function isStableXmlProgressCandidate(options) {
|
|
4930
|
+
const { candidate, parsed, toolSchema } = options;
|
|
4931
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4932
|
+
return false;
|
|
4933
|
+
}
|
|
4934
|
+
const structure = analyzeXmlFragmentForProgress(candidate);
|
|
4935
|
+
if (!structure) {
|
|
4936
|
+
return false;
|
|
4937
|
+
}
|
|
4938
|
+
const schemaProperties = getObjectSchemaPropertyNames(toolSchema);
|
|
4939
|
+
if (!schemaProperties || schemaProperties.size === 0) {
|
|
4940
|
+
return false;
|
|
4941
|
+
}
|
|
4942
|
+
const parsedObject = parsed;
|
|
4943
|
+
const uniqueTopLevelTags = new Set(structure.topLevelTagNames);
|
|
4944
|
+
for (const tagName of uniqueTopLevelTags) {
|
|
4945
|
+
if (!schemaProperties.has(tagName)) {
|
|
4946
|
+
continue;
|
|
4947
|
+
}
|
|
4948
|
+
const schemaProperty = getSchemaObjectProperty(toolSchema, tagName);
|
|
4949
|
+
if (schemaProperty && schemaAllowsArrayType(schemaProperty) && !Array.isArray(parsedObject[tagName])) {
|
|
4950
|
+
return false;
|
|
4951
|
+
}
|
|
4952
|
+
}
|
|
4953
|
+
if (structure.topLevelTagNames.length === 1) {
|
|
4954
|
+
const onlyTopLevelTag = structure.topLevelTagNames[0];
|
|
4955
|
+
if (!schemaProperties || schemaProperties.size === 0 || !schemaProperties.has(onlyTopLevelTag)) {
|
|
4956
|
+
return false;
|
|
4957
|
+
}
|
|
4958
|
+
}
|
|
4959
|
+
return true;
|
|
4960
|
+
}
|
|
4961
|
+
function parseXmlContentForStreamProgress({
|
|
4962
|
+
toolContent,
|
|
4963
|
+
toolSchema,
|
|
4964
|
+
parseOptions
|
|
4965
|
+
}) {
|
|
4966
|
+
const tryParse = (content) => {
|
|
4967
|
+
try {
|
|
4968
|
+
return parse3(content, toolSchema, {
|
|
4969
|
+
...parseOptions != null ? parseOptions : {},
|
|
4970
|
+
repair: false,
|
|
4971
|
+
onError: void 0
|
|
4972
|
+
});
|
|
4973
|
+
} catch (e) {
|
|
4974
|
+
return null;
|
|
4975
|
+
}
|
|
4976
|
+
};
|
|
4977
|
+
const strictFull = tryParse(toolContent);
|
|
4978
|
+
if (strictFull !== null && isStableXmlProgressCandidate({
|
|
4979
|
+
candidate: toolContent,
|
|
4980
|
+
parsed: strictFull,
|
|
4981
|
+
toolSchema
|
|
4982
|
+
})) {
|
|
4983
|
+
return JSON.stringify(strictFull);
|
|
4984
|
+
}
|
|
4985
|
+
let searchEnd = toolContent.length;
|
|
4986
|
+
while (searchEnd > 0) {
|
|
4987
|
+
const gtIndex = toolContent.lastIndexOf(">", searchEnd - 1);
|
|
4988
|
+
if (gtIndex === -1) {
|
|
4989
|
+
break;
|
|
4990
|
+
}
|
|
4991
|
+
const candidate = toolContent.slice(0, gtIndex + 1);
|
|
4992
|
+
if (!analyzeXmlFragmentForProgress(candidate)) {
|
|
4993
|
+
searchEnd = gtIndex;
|
|
4994
|
+
continue;
|
|
4995
|
+
}
|
|
4996
|
+
const parsedCandidate = tryParse(candidate);
|
|
4997
|
+
if (parsedCandidate !== null && isStableXmlProgressCandidate({
|
|
4998
|
+
candidate,
|
|
4999
|
+
parsed: parsedCandidate,
|
|
5000
|
+
toolSchema
|
|
5001
|
+
})) {
|
|
5002
|
+
return JSON.stringify(parsedCandidate);
|
|
5003
|
+
}
|
|
5004
|
+
searchEnd = gtIndex;
|
|
5005
|
+
}
|
|
5006
|
+
return null;
|
|
5007
|
+
}
|
|
5008
|
+
function handleStreamingToolCallEnd(params) {
|
|
5009
|
+
var _a, _b;
|
|
5010
|
+
const {
|
|
5011
|
+
toolContent,
|
|
5012
|
+
currentToolCall,
|
|
5013
|
+
tools,
|
|
5014
|
+
options,
|
|
5015
|
+
ctrl,
|
|
5016
|
+
flushText,
|
|
5017
|
+
parseOptions
|
|
5018
|
+
} = params;
|
|
5019
|
+
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
5020
|
+
const parseConfig = {
|
|
5021
|
+
...parseOptions != null ? parseOptions : {},
|
|
5022
|
+
onError: (_a = options == null ? void 0 : options.onError) != null ? _a : parseOptions == null ? void 0 : parseOptions.onError
|
|
5023
|
+
};
|
|
5024
|
+
flushText(ctrl);
|
|
5025
|
+
try {
|
|
5026
|
+
const parsedResult = parse3(toolContent, toolSchema, parseConfig);
|
|
5027
|
+
const finalInput = JSON.stringify(parsedResult);
|
|
5028
|
+
emitFinalRemainder({
|
|
5029
|
+
controller: ctrl,
|
|
5030
|
+
id: currentToolCall.toolCallId,
|
|
5031
|
+
state: currentToolCall,
|
|
5032
|
+
finalFullJson: finalInput,
|
|
5033
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
5034
|
+
});
|
|
5035
|
+
ctrl.enqueue({
|
|
5036
|
+
type: "tool-input-end",
|
|
5037
|
+
id: currentToolCall.toolCallId
|
|
5038
|
+
});
|
|
5039
|
+
ctrl.enqueue({
|
|
5040
|
+
type: "tool-call",
|
|
5041
|
+
toolCallId: currentToolCall.toolCallId,
|
|
5042
|
+
toolName: currentToolCall.name,
|
|
5043
|
+
input: finalInput
|
|
5044
|
+
});
|
|
5045
|
+
} catch (error) {
|
|
5046
|
+
ctrl.enqueue({
|
|
5047
|
+
type: "tool-input-end",
|
|
5048
|
+
id: currentToolCall.toolCallId
|
|
5049
|
+
});
|
|
5050
|
+
const original = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
|
|
5051
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
|
|
5052
|
+
toolCall: original,
|
|
5053
|
+
error
|
|
5054
|
+
});
|
|
5055
|
+
if (shouldEmitRawToolCallTextOnError2(options)) {
|
|
5056
|
+
flushText(ctrl, original);
|
|
5057
|
+
}
|
|
5058
|
+
}
|
|
5059
|
+
}
|
|
5060
|
+
function findClosingTagEndFlexible(text, contentStart, toolName) {
|
|
5061
|
+
let pos = contentStart;
|
|
5062
|
+
let depth = 1;
|
|
5063
|
+
while (pos < text.length) {
|
|
5064
|
+
const tok = nextTagToken(text, pos);
|
|
5065
|
+
if (tok.kind === "eof") {
|
|
5066
|
+
break;
|
|
5067
|
+
}
|
|
5068
|
+
const result = updateDepthWithToken(tok, toolName, depth);
|
|
5069
|
+
depth = result.depth;
|
|
5070
|
+
if (result.closedAt !== void 0) {
|
|
5071
|
+
return result.closedAt;
|
|
5072
|
+
}
|
|
5073
|
+
pos = tok.nextPos;
|
|
5074
|
+
}
|
|
5075
|
+
return -1;
|
|
5076
|
+
}
|
|
5077
|
+
function skipSpecialSegment(text, lt) {
|
|
5078
|
+
const next = text[lt + 1];
|
|
5079
|
+
if (next === "!" || next === "?") {
|
|
3919
5080
|
const gt = text.indexOf(">", lt + 1);
|
|
3920
5081
|
if (gt !== -1) {
|
|
3921
5082
|
return gt + 1;
|
|
@@ -3930,7 +5091,7 @@ function consumeClosingTag(text, lt) {
|
|
|
3930
5091
|
}
|
|
3931
5092
|
function consumeOpenTag(text, lt) {
|
|
3932
5093
|
let p = lt + 1;
|
|
3933
|
-
while (p < text.length &&
|
|
5094
|
+
while (p < text.length && WHITESPACE_REGEX5.test(text[p])) {
|
|
3934
5095
|
p += 1;
|
|
3935
5096
|
}
|
|
3936
5097
|
const nameStart = p;
|
|
@@ -3943,7 +5104,7 @@ function consumeOpenTag(text, lt) {
|
|
|
3943
5104
|
return null;
|
|
3944
5105
|
}
|
|
3945
5106
|
let r = q - 1;
|
|
3946
|
-
while (r >= nameStart &&
|
|
5107
|
+
while (r >= nameStart && WHITESPACE_REGEX5.test(text[r])) {
|
|
3947
5108
|
r -= 1;
|
|
3948
5109
|
}
|
|
3949
5110
|
const selfClosing = text[r] === "/";
|
|
@@ -3972,7 +5133,7 @@ function nextTagToken(text, fromPos) {
|
|
|
3972
5133
|
if (next === "/") {
|
|
3973
5134
|
const closing = consumeClosingTag(text, lt);
|
|
3974
5135
|
let p = lt + 2;
|
|
3975
|
-
while (p < text.length &&
|
|
5136
|
+
while (p < text.length && WHITESPACE_REGEX5.test(text[p])) {
|
|
3976
5137
|
p += 1;
|
|
3977
5138
|
}
|
|
3978
5139
|
const nameStart = p;
|
|
@@ -4109,6 +5270,102 @@ function findToolCalls(text, toolNames) {
|
|
|
4109
5270
|
}
|
|
4110
5271
|
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
4111
5272
|
}
|
|
5273
|
+
function handleSpecialToken(depth) {
|
|
5274
|
+
return { depth, lastCompleteEnd: -1, shouldBreak: false };
|
|
5275
|
+
}
|
|
5276
|
+
function handleOpenToken(token, depth, lastCompleteEnd) {
|
|
5277
|
+
if (token.selfClosing) {
|
|
5278
|
+
return {
|
|
5279
|
+
depth,
|
|
5280
|
+
lastCompleteEnd: depth === 0 ? token.nextPos : lastCompleteEnd,
|
|
5281
|
+
shouldBreak: false
|
|
5282
|
+
};
|
|
5283
|
+
}
|
|
5284
|
+
return { depth: depth + 1, lastCompleteEnd, shouldBreak: false };
|
|
5285
|
+
}
|
|
5286
|
+
function handleCloseToken(token, depth) {
|
|
5287
|
+
if (depth <= 0) {
|
|
5288
|
+
return { depth, lastCompleteEnd: -1, shouldBreak: true };
|
|
5289
|
+
}
|
|
5290
|
+
const newDepth = depth - 1;
|
|
5291
|
+
return {
|
|
5292
|
+
depth: newDepth,
|
|
5293
|
+
lastCompleteEnd: newDepth === 0 ? token.nextPos : -1,
|
|
5294
|
+
shouldBreak: false
|
|
5295
|
+
};
|
|
5296
|
+
}
|
|
5297
|
+
function findLinePrefixedXmlBodyEnd(text, bodyStartIndex) {
|
|
5298
|
+
let cursor = bodyStartIndex;
|
|
5299
|
+
let depth = 0;
|
|
5300
|
+
let lastCompleteEnd = -1;
|
|
5301
|
+
while (cursor < text.length) {
|
|
5302
|
+
if (depth === 0) {
|
|
5303
|
+
cursor = consumeWhitespace(text, cursor);
|
|
5304
|
+
if (cursor >= text.length || text.charAt(cursor) !== "<") {
|
|
5305
|
+
break;
|
|
5306
|
+
}
|
|
5307
|
+
}
|
|
5308
|
+
const token = nextTagToken(text, cursor);
|
|
5309
|
+
if (token.kind === "eof") {
|
|
5310
|
+
break;
|
|
5311
|
+
}
|
|
5312
|
+
let result;
|
|
5313
|
+
if (token.kind === "special") {
|
|
5314
|
+
result = handleSpecialToken(depth);
|
|
5315
|
+
} else if (token.kind === "open") {
|
|
5316
|
+
result = handleOpenToken(token, depth, lastCompleteEnd);
|
|
5317
|
+
} else {
|
|
5318
|
+
result = handleCloseToken(token, depth);
|
|
5319
|
+
}
|
|
5320
|
+
depth = result.depth;
|
|
5321
|
+
if (result.lastCompleteEnd !== -1) {
|
|
5322
|
+
lastCompleteEnd = result.lastCompleteEnd;
|
|
5323
|
+
}
|
|
5324
|
+
if (result.shouldBreak) {
|
|
5325
|
+
break;
|
|
5326
|
+
}
|
|
5327
|
+
cursor = token.nextPos;
|
|
5328
|
+
}
|
|
5329
|
+
return lastCompleteEnd;
|
|
5330
|
+
}
|
|
5331
|
+
function findLinePrefixedToolCall(text, toolNames) {
|
|
5332
|
+
var _a;
|
|
5333
|
+
let best = null;
|
|
5334
|
+
for (const toolName of toolNames) {
|
|
5335
|
+
const linePattern = new RegExp(
|
|
5336
|
+
`(^|\\n)[\\t ]*${escapeRegExp(toolName)}[\\t ]*:?[\\t ]*(?:\\r?\\n|$)`,
|
|
5337
|
+
"g"
|
|
5338
|
+
);
|
|
5339
|
+
let match = linePattern.exec(text);
|
|
5340
|
+
while (match !== null) {
|
|
5341
|
+
const prefix = (_a = match[1]) != null ? _a : "";
|
|
5342
|
+
const startIndex = match.index + prefix.length;
|
|
5343
|
+
const contentStart = consumeWhitespace(text, linePattern.lastIndex);
|
|
5344
|
+
if (contentStart >= text.length || text.charAt(contentStart) !== "<") {
|
|
5345
|
+
match = linePattern.exec(text);
|
|
5346
|
+
continue;
|
|
5347
|
+
}
|
|
5348
|
+
const contentEnd = findLinePrefixedXmlBodyEnd(text, contentStart);
|
|
5349
|
+
if (contentEnd === -1 || contentEnd <= contentStart) {
|
|
5350
|
+
match = linePattern.exec(text);
|
|
5351
|
+
continue;
|
|
5352
|
+
}
|
|
5353
|
+
const content = text.slice(contentStart, contentEnd);
|
|
5354
|
+
const candidate = {
|
|
5355
|
+
toolName,
|
|
5356
|
+
startIndex,
|
|
5357
|
+
endIndex: contentEnd,
|
|
5358
|
+
content,
|
|
5359
|
+
segment: text.slice(startIndex, contentEnd)
|
|
5360
|
+
};
|
|
5361
|
+
if (best === null || candidate.startIndex < best.startIndex) {
|
|
5362
|
+
best = candidate;
|
|
5363
|
+
}
|
|
5364
|
+
break;
|
|
5365
|
+
}
|
|
5366
|
+
}
|
|
5367
|
+
return best;
|
|
5368
|
+
}
|
|
4112
5369
|
function findEarliestToolTag(buffer, toolNames) {
|
|
4113
5370
|
var _a, _b;
|
|
4114
5371
|
let bestIndex = -1;
|
|
@@ -4147,7 +5404,7 @@ function isOpenTagPrefix(suffix, toolName) {
|
|
|
4147
5404
|
}
|
|
4148
5405
|
function consumeWhitespace(text, index) {
|
|
4149
5406
|
let i = index;
|
|
4150
|
-
while (i < text.length &&
|
|
5407
|
+
while (i < text.length && WHITESPACE_REGEX5.test(text.charAt(i))) {
|
|
4151
5408
|
i += 1;
|
|
4152
5409
|
}
|
|
4153
5410
|
return i;
|
|
@@ -4219,38 +5476,6 @@ function findPotentialToolTagStart(buffer, toolNames) {
|
|
|
4219
5476
|
}
|
|
4220
5477
|
return -1;
|
|
4221
5478
|
}
|
|
4222
|
-
function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
4223
|
-
return (controller, text) => {
|
|
4224
|
-
const content = text;
|
|
4225
|
-
if (content) {
|
|
4226
|
-
if (!getCurrentTextId()) {
|
|
4227
|
-
const newId = generateId();
|
|
4228
|
-
setCurrentTextId(newId);
|
|
4229
|
-
controller.enqueue({
|
|
4230
|
-
type: "text-start",
|
|
4231
|
-
id: newId
|
|
4232
|
-
});
|
|
4233
|
-
setHasEmittedTextStart(true);
|
|
4234
|
-
}
|
|
4235
|
-
controller.enqueue({
|
|
4236
|
-
type: "text-delta",
|
|
4237
|
-
id: getCurrentTextId(),
|
|
4238
|
-
delta: content
|
|
4239
|
-
});
|
|
4240
|
-
}
|
|
4241
|
-
const currentTextId = getCurrentTextId();
|
|
4242
|
-
if (currentTextId && !text) {
|
|
4243
|
-
if (getHasEmittedTextStart()) {
|
|
4244
|
-
controller.enqueue({
|
|
4245
|
-
type: "text-end",
|
|
4246
|
-
id: currentTextId
|
|
4247
|
-
});
|
|
4248
|
-
setHasEmittedTextStart(false);
|
|
4249
|
-
}
|
|
4250
|
-
setCurrentTextId(null);
|
|
4251
|
-
}
|
|
4252
|
-
};
|
|
4253
|
-
}
|
|
4254
5479
|
function processToolCallInBuffer(params) {
|
|
4255
5480
|
const {
|
|
4256
5481
|
buffer,
|
|
@@ -4260,18 +5485,21 @@ function processToolCallInBuffer(params) {
|
|
|
4260
5485
|
controller,
|
|
4261
5486
|
flushText,
|
|
4262
5487
|
setBuffer,
|
|
4263
|
-
parseOptions
|
|
5488
|
+
parseOptions,
|
|
5489
|
+
emitToolInputProgress: emitToolInputProgress2
|
|
4264
5490
|
} = params;
|
|
4265
5491
|
const endTagPattern = new RegExp(
|
|
4266
5492
|
`</\\s*${escapeRegExp(currentToolCall.name)}\\s*>`
|
|
4267
5493
|
);
|
|
4268
5494
|
const endMatch = endTagPattern.exec(buffer);
|
|
4269
5495
|
if (!endMatch || endMatch.index === void 0) {
|
|
5496
|
+
emitToolInputProgress2(controller, currentToolCall, buffer);
|
|
4270
5497
|
return { buffer, currentToolCall, shouldBreak: true };
|
|
4271
5498
|
}
|
|
4272
5499
|
const endIdx = endMatch.index;
|
|
4273
5500
|
const endPos = endIdx + endMatch[0].length;
|
|
4274
5501
|
const content = buffer.substring(0, endIdx);
|
|
5502
|
+
emitToolInputProgress2(controller, currentToolCall, content);
|
|
4275
5503
|
const remainder = buffer.substring(endPos);
|
|
4276
5504
|
setBuffer(remainder);
|
|
4277
5505
|
handleStreamingToolCallEnd({
|
|
@@ -4298,7 +5526,8 @@ function processNoToolCallInBuffer(params) {
|
|
|
4298
5526
|
tools,
|
|
4299
5527
|
options,
|
|
4300
5528
|
parseOptions,
|
|
4301
|
-
setBuffer
|
|
5529
|
+
setBuffer,
|
|
5530
|
+
emitToolInputStart
|
|
4302
5531
|
} = params;
|
|
4303
5532
|
const {
|
|
4304
5533
|
index: earliestStartTagIndex,
|
|
@@ -4328,9 +5557,10 @@ function processNoToolCallInBuffer(params) {
|
|
|
4328
5557
|
if (selfClosing) {
|
|
4329
5558
|
const newBuffer2 = buffer.substring(earliestStartTagIndex + tagLength);
|
|
4330
5559
|
setBuffer(newBuffer2);
|
|
5560
|
+
const currentToolCall = emitToolInputStart(controller, earliestToolName);
|
|
4331
5561
|
handleStreamingToolCallEnd({
|
|
4332
5562
|
toolContent: "",
|
|
4333
|
-
currentToolCall
|
|
5563
|
+
currentToolCall,
|
|
4334
5564
|
tools,
|
|
4335
5565
|
options,
|
|
4336
5566
|
ctrl: controller,
|
|
@@ -4349,12 +5579,12 @@ function processNoToolCallInBuffer(params) {
|
|
|
4349
5579
|
setBuffer(newBuffer);
|
|
4350
5580
|
return {
|
|
4351
5581
|
buffer: newBuffer,
|
|
4352
|
-
currentToolCall:
|
|
5582
|
+
currentToolCall: emitToolInputStart(controller, earliestToolName),
|
|
4353
5583
|
shouldBreak: false,
|
|
4354
5584
|
shouldContinue: true
|
|
4355
5585
|
};
|
|
4356
5586
|
}
|
|
4357
|
-
function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions) {
|
|
5587
|
+
function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions, emitToolInputProgress2, emitToolInputStart) {
|
|
4358
5588
|
return (controller) => {
|
|
4359
5589
|
while (true) {
|
|
4360
5590
|
const currentToolCall = getCurrentToolCall();
|
|
@@ -4367,7 +5597,8 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
4367
5597
|
controller,
|
|
4368
5598
|
flushText,
|
|
4369
5599
|
setBuffer,
|
|
4370
|
-
parseOptions
|
|
5600
|
+
parseOptions,
|
|
5601
|
+
emitToolInputProgress: emitToolInputProgress2
|
|
4371
5602
|
});
|
|
4372
5603
|
setBuffer(result.buffer);
|
|
4373
5604
|
setCurrentToolCall(result.currentToolCall);
|
|
@@ -4383,7 +5614,8 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
4383
5614
|
tools,
|
|
4384
5615
|
options,
|
|
4385
5616
|
parseOptions,
|
|
4386
|
-
setBuffer
|
|
5617
|
+
setBuffer,
|
|
5618
|
+
emitToolInputStart
|
|
4387
5619
|
});
|
|
4388
5620
|
setBuffer(result.buffer);
|
|
4389
5621
|
setCurrentToolCall(result.currentToolCall);
|
|
@@ -4398,6 +5630,27 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
4398
5630
|
}
|
|
4399
5631
|
};
|
|
4400
5632
|
}
|
|
5633
|
+
function findToolCallsWithFallbacks(text, toolNames) {
|
|
5634
|
+
let parseText = text;
|
|
5635
|
+
let toolCalls = findToolCalls(parseText, toolNames);
|
|
5636
|
+
if (toolCalls.length === 0) {
|
|
5637
|
+
const fallbackToolCall = findLinePrefixedToolCall(parseText, toolNames);
|
|
5638
|
+
if (fallbackToolCall !== null) {
|
|
5639
|
+
toolCalls.push(fallbackToolCall);
|
|
5640
|
+
}
|
|
5641
|
+
}
|
|
5642
|
+
if (toolCalls.length === 0) {
|
|
5643
|
+
const repaired = tryRepairXmlSelfClosingRootWithBody(parseText, toolNames);
|
|
5644
|
+
if (repaired) {
|
|
5645
|
+
const repairedCalls = findToolCalls(repaired, toolNames);
|
|
5646
|
+
if (repairedCalls.length > 0) {
|
|
5647
|
+
parseText = repaired;
|
|
5648
|
+
toolCalls = repairedCalls;
|
|
5649
|
+
}
|
|
5650
|
+
}
|
|
5651
|
+
}
|
|
5652
|
+
return { parseText, toolCalls };
|
|
5653
|
+
}
|
|
4401
5654
|
var xmlProtocol = (protocolOptions) => {
|
|
4402
5655
|
var _a;
|
|
4403
5656
|
const parseOptions = {
|
|
@@ -4431,28 +5684,31 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4431
5684
|
}
|
|
4432
5685
|
const processedElements = [];
|
|
4433
5686
|
let currentIndex = 0;
|
|
4434
|
-
const toolCalls =
|
|
5687
|
+
const { parseText, toolCalls } = findToolCallsWithFallbacks(
|
|
5688
|
+
text,
|
|
5689
|
+
toolNames
|
|
5690
|
+
);
|
|
4435
5691
|
for (const tc of toolCalls) {
|
|
4436
5692
|
if (tc.startIndex > currentIndex) {
|
|
4437
5693
|
processedElements.push({
|
|
4438
5694
|
type: "text",
|
|
4439
|
-
text:
|
|
5695
|
+
text: parseText.substring(currentIndex, tc.startIndex)
|
|
4440
5696
|
});
|
|
4441
5697
|
}
|
|
4442
5698
|
processToolCall({
|
|
4443
5699
|
toolCall: tc,
|
|
4444
5700
|
tools,
|
|
4445
5701
|
options,
|
|
4446
|
-
text,
|
|
5702
|
+
text: parseText,
|
|
4447
5703
|
processedElements,
|
|
4448
5704
|
parseOptions
|
|
4449
5705
|
});
|
|
4450
5706
|
currentIndex = tc.endIndex;
|
|
4451
5707
|
}
|
|
4452
|
-
if (currentIndex <
|
|
5708
|
+
if (currentIndex < parseText.length) {
|
|
4453
5709
|
processedElements.push({
|
|
4454
5710
|
type: "text",
|
|
4455
|
-
text:
|
|
5711
|
+
text: parseText.substring(currentIndex)
|
|
4456
5712
|
});
|
|
4457
5713
|
}
|
|
4458
5714
|
return processedElements;
|
|
@@ -4473,8 +5729,120 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4473
5729
|
hasEmittedTextStart = value;
|
|
4474
5730
|
}
|
|
4475
5731
|
);
|
|
4476
|
-
const
|
|
4477
|
-
()
|
|
5732
|
+
const emitToolInputStart = (controller, toolName) => {
|
|
5733
|
+
flushText(controller);
|
|
5734
|
+
const next = {
|
|
5735
|
+
name: toolName,
|
|
5736
|
+
toolCallId: generateToolCallId(),
|
|
5737
|
+
emittedInput: "",
|
|
5738
|
+
lastProgressGtIndex: null,
|
|
5739
|
+
lastProgressFullInput: null
|
|
5740
|
+
};
|
|
5741
|
+
controller.enqueue({
|
|
5742
|
+
type: "tool-input-start",
|
|
5743
|
+
id: next.toolCallId,
|
|
5744
|
+
toolName
|
|
5745
|
+
});
|
|
5746
|
+
return next;
|
|
5747
|
+
};
|
|
5748
|
+
const emitToolInputProgress2 = (controller, toolCall, toolContent) => {
|
|
5749
|
+
const progressGtIndex = toolContent.lastIndexOf(">");
|
|
5750
|
+
if (toolCall.lastProgressGtIndex === progressGtIndex) {
|
|
5751
|
+
const cached = toolCall.lastProgressFullInput;
|
|
5752
|
+
if (cached == null) {
|
|
5753
|
+
return;
|
|
5754
|
+
}
|
|
5755
|
+
if (cached === "{}" && toolContent.trim().length === 0) {
|
|
5756
|
+
return;
|
|
5757
|
+
}
|
|
5758
|
+
const prefixCandidate2 = toIncompleteJsonPrefix(cached);
|
|
5759
|
+
emitPrefixDelta({
|
|
5760
|
+
controller,
|
|
5761
|
+
id: toolCall.toolCallId,
|
|
5762
|
+
state: toolCall,
|
|
5763
|
+
candidate: prefixCandidate2
|
|
5764
|
+
});
|
|
5765
|
+
return;
|
|
5766
|
+
}
|
|
5767
|
+
const toolSchema = getToolSchema(tools, toolCall.name);
|
|
5768
|
+
const fullInput = parseXmlContentForStreamProgress({
|
|
5769
|
+
toolContent,
|
|
5770
|
+
toolSchema,
|
|
5771
|
+
parseOptions
|
|
5772
|
+
});
|
|
5773
|
+
toolCall.lastProgressGtIndex = progressGtIndex;
|
|
5774
|
+
toolCall.lastProgressFullInput = fullInput;
|
|
5775
|
+
if (fullInput == null) {
|
|
5776
|
+
return;
|
|
5777
|
+
}
|
|
5778
|
+
if (fullInput === "{}" && toolContent.trim().length === 0) {
|
|
5779
|
+
return;
|
|
5780
|
+
}
|
|
5781
|
+
const prefixCandidate = toIncompleteJsonPrefix(fullInput);
|
|
5782
|
+
emitPrefixDelta({
|
|
5783
|
+
controller,
|
|
5784
|
+
id: toolCall.toolCallId,
|
|
5785
|
+
state: toolCall,
|
|
5786
|
+
candidate: prefixCandidate
|
|
5787
|
+
});
|
|
5788
|
+
};
|
|
5789
|
+
const finalizeUnclosedToolCall = (controller) => {
|
|
5790
|
+
var _a2, _b;
|
|
5791
|
+
if (!currentToolCall) {
|
|
5792
|
+
return;
|
|
5793
|
+
}
|
|
5794
|
+
emitToolInputProgress2(controller, currentToolCall, buffer);
|
|
5795
|
+
const parseConfig = {
|
|
5796
|
+
...parseOptions,
|
|
5797
|
+
onError: (_a2 = options == null ? void 0 : options.onError) != null ? _a2 : parseOptions == null ? void 0 : parseOptions.onError
|
|
5798
|
+
};
|
|
5799
|
+
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
5800
|
+
flushText(controller);
|
|
5801
|
+
try {
|
|
5802
|
+
if (hasNonWhitespaceTopLevelText(buffer)) {
|
|
5803
|
+
throw new Error(
|
|
5804
|
+
"Cannot reconcile unclosed XML tool call with top-level plain text."
|
|
5805
|
+
);
|
|
5806
|
+
}
|
|
5807
|
+
const parsedResult = parse3(buffer, toolSchema, parseConfig);
|
|
5808
|
+
const finalInput = JSON.stringify(parsedResult);
|
|
5809
|
+
emitFinalRemainder({
|
|
5810
|
+
controller,
|
|
5811
|
+
id: currentToolCall.toolCallId,
|
|
5812
|
+
state: currentToolCall,
|
|
5813
|
+
finalFullJson: finalInput,
|
|
5814
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
5815
|
+
});
|
|
5816
|
+
controller.enqueue({
|
|
5817
|
+
type: "tool-input-end",
|
|
5818
|
+
id: currentToolCall.toolCallId
|
|
5819
|
+
});
|
|
5820
|
+
controller.enqueue({
|
|
5821
|
+
type: "tool-call",
|
|
5822
|
+
toolCallId: currentToolCall.toolCallId,
|
|
5823
|
+
toolName: currentToolCall.name,
|
|
5824
|
+
input: finalInput
|
|
5825
|
+
});
|
|
5826
|
+
} catch (error) {
|
|
5827
|
+
controller.enqueue({
|
|
5828
|
+
type: "tool-input-end",
|
|
5829
|
+
id: currentToolCall.toolCallId
|
|
5830
|
+
});
|
|
5831
|
+
const unfinishedContent = `<${currentToolCall.name}>${buffer}`;
|
|
5832
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
5833
|
+
options,
|
|
5834
|
+
"Could not complete streaming XML tool call at finish.",
|
|
5835
|
+
{ toolCall: unfinishedContent, error }
|
|
5836
|
+
);
|
|
5837
|
+
if (shouldEmitRawToolCallTextOnError2(options)) {
|
|
5838
|
+
flushText(controller, unfinishedContent);
|
|
5839
|
+
}
|
|
5840
|
+
}
|
|
5841
|
+
buffer = "";
|
|
5842
|
+
currentToolCall = null;
|
|
5843
|
+
};
|
|
5844
|
+
const processBuffer = createProcessBufferHandler(
|
|
5845
|
+
() => buffer,
|
|
4478
5846
|
(newBuffer) => {
|
|
4479
5847
|
buffer = newBuffer;
|
|
4480
5848
|
},
|
|
@@ -4486,13 +5854,28 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4486
5854
|
options,
|
|
4487
5855
|
toolNames,
|
|
4488
5856
|
flushText,
|
|
4489
|
-
parseOptions
|
|
5857
|
+
parseOptions,
|
|
5858
|
+
emitToolInputProgress2,
|
|
5859
|
+
emitToolInputStart
|
|
4490
5860
|
);
|
|
4491
5861
|
return new TransformStream({
|
|
5862
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Stateful stream parsing requires branching over chunk lifecycle and parser states.
|
|
4492
5863
|
transform(chunk, controller) {
|
|
4493
5864
|
var _a2;
|
|
5865
|
+
if (chunk.type === "finish") {
|
|
5866
|
+
if (currentToolCall) {
|
|
5867
|
+
finalizeUnclosedToolCall(controller);
|
|
5868
|
+
} else if (buffer) {
|
|
5869
|
+
flushText(controller, buffer);
|
|
5870
|
+
buffer = "";
|
|
5871
|
+
}
|
|
5872
|
+
flushText(controller);
|
|
5873
|
+
controller.enqueue(chunk);
|
|
5874
|
+
return;
|
|
5875
|
+
}
|
|
4494
5876
|
if (chunk.type !== "text-delta") {
|
|
4495
|
-
if (
|
|
5877
|
+
if (currentToolCall) {
|
|
5878
|
+
} else if (buffer) {
|
|
4496
5879
|
flushText(controller, buffer);
|
|
4497
5880
|
buffer = "";
|
|
4498
5881
|
}
|
|
@@ -4505,10 +5888,7 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4505
5888
|
},
|
|
4506
5889
|
flush(controller) {
|
|
4507
5890
|
if (currentToolCall) {
|
|
4508
|
-
|
|
4509
|
-
flushText(controller, unfinishedContent);
|
|
4510
|
-
buffer = "";
|
|
4511
|
-
currentToolCall = null;
|
|
5891
|
+
finalizeUnclosedToolCall(controller);
|
|
4512
5892
|
} else if (buffer) {
|
|
4513
5893
|
flushText(controller, buffer);
|
|
4514
5894
|
buffer = "";
|
|
@@ -4536,7 +5916,205 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4536
5916
|
|
|
4537
5917
|
// src/core/protocols/yaml-protocol.ts
|
|
4538
5918
|
var import_yaml = __toESM(require("yaml"), 1);
|
|
5919
|
+
function shouldEmitRawToolCallTextOnError3(options) {
|
|
5920
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
5921
|
+
}
|
|
5922
|
+
var selfClosingTagCache2 = /* @__PURE__ */ new Map();
|
|
5923
|
+
function getSelfClosingTagPattern2(toolName) {
|
|
5924
|
+
let pattern = selfClosingTagCache2.get(toolName);
|
|
5925
|
+
if (!pattern) {
|
|
5926
|
+
pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
|
|
5927
|
+
selfClosingTagCache2.set(toolName, pattern);
|
|
5928
|
+
}
|
|
5929
|
+
return pattern;
|
|
5930
|
+
}
|
|
4539
5931
|
var LEADING_WHITESPACE_RE = /^(\s*)/;
|
|
5932
|
+
var INCOMPLETE_MAPPING_TAIL_RE = /^[^:[\]{}-][^:]*:\s*$/;
|
|
5933
|
+
var INCOMPLETE_SEQUENCE_TAIL_RE = /^-\s*$/;
|
|
5934
|
+
var BLOCK_SCALAR_KEY_RE = /:\s*[|>][-+0-9]*\s*$/;
|
|
5935
|
+
var PLAIN_MAPPING_VALUE_RE = /^[^:[\]{}-][^:]*:\s*(.+)$/;
|
|
5936
|
+
var PLAIN_SEQUENCE_VALUE_RE = /^-\s+(.+)$/;
|
|
5937
|
+
function normalizeYamlContent(yamlContent) {
|
|
5938
|
+
let normalized = yamlContent;
|
|
5939
|
+
if (normalized.startsWith("\n")) {
|
|
5940
|
+
normalized = normalized.slice(1);
|
|
5941
|
+
}
|
|
5942
|
+
const lines = normalized.split("\n");
|
|
5943
|
+
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
|
5944
|
+
if (nonEmptyLines.length === 0) {
|
|
5945
|
+
return { normalized: "", nonEmptyLines };
|
|
5946
|
+
}
|
|
5947
|
+
const minIndent = Math.min(
|
|
5948
|
+
...nonEmptyLines.map((line) => {
|
|
5949
|
+
const match = line.match(LEADING_WHITESPACE_RE);
|
|
5950
|
+
return match ? match[1].length : 0;
|
|
5951
|
+
})
|
|
5952
|
+
);
|
|
5953
|
+
if (minIndent > 0) {
|
|
5954
|
+
normalized = lines.map((line) => line.slice(minIndent)).join("\n");
|
|
5955
|
+
}
|
|
5956
|
+
return { normalized, nonEmptyLines };
|
|
5957
|
+
}
|
|
5958
|
+
function parseYamlDocumentAsMapping(normalized) {
|
|
5959
|
+
try {
|
|
5960
|
+
const doc = import_yaml.default.parseDocument(normalized);
|
|
5961
|
+
const errors = doc.errors.map((e) => e.message);
|
|
5962
|
+
const result = doc.toJSON();
|
|
5963
|
+
if (result === null) {
|
|
5964
|
+
return { value: {}, errors };
|
|
5965
|
+
}
|
|
5966
|
+
if (typeof result !== "object" || Array.isArray(result)) {
|
|
5967
|
+
return { value: null, errors };
|
|
5968
|
+
}
|
|
5969
|
+
return { value: result, errors };
|
|
5970
|
+
} catch (error) {
|
|
5971
|
+
return {
|
|
5972
|
+
value: null,
|
|
5973
|
+
errors: [
|
|
5974
|
+
error instanceof Error ? error.message : "Unknown YAML parsing error"
|
|
5975
|
+
]
|
|
5976
|
+
};
|
|
5977
|
+
}
|
|
5978
|
+
}
|
|
5979
|
+
function getLastMeaningfulLineInfo(input) {
|
|
5980
|
+
var _a;
|
|
5981
|
+
const lines = input.split("\n");
|
|
5982
|
+
let index = lines.length - 1;
|
|
5983
|
+
while (index >= 0) {
|
|
5984
|
+
const raw = (_a = lines[index]) != null ? _a : "";
|
|
5985
|
+
const trimmed = raw.trim();
|
|
5986
|
+
if (trimmed.length > 0 && !trimmed.startsWith("#")) {
|
|
5987
|
+
return {
|
|
5988
|
+
index,
|
|
5989
|
+
raw,
|
|
5990
|
+
trimmed,
|
|
5991
|
+
indent: raw.length - raw.trimStart().length
|
|
5992
|
+
};
|
|
5993
|
+
}
|
|
5994
|
+
index -= 1;
|
|
5995
|
+
}
|
|
5996
|
+
return null;
|
|
5997
|
+
}
|
|
5998
|
+
function dropLastMeaningfulLine(input) {
|
|
5999
|
+
const lineInfo = getLastMeaningfulLineInfo(input);
|
|
6000
|
+
if (!lineInfo) {
|
|
6001
|
+
return null;
|
|
6002
|
+
}
|
|
6003
|
+
return input.split("\n").slice(0, lineInfo.index).join("\n").trimEnd();
|
|
6004
|
+
}
|
|
6005
|
+
function hasIncompleteMappingTail(normalized) {
|
|
6006
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6007
|
+
if (!lineInfo) {
|
|
6008
|
+
return false;
|
|
6009
|
+
}
|
|
6010
|
+
return INCOMPLETE_MAPPING_TAIL_RE.test(lineInfo.trimmed);
|
|
6011
|
+
}
|
|
6012
|
+
function hasIncompleteSequenceTail(normalized) {
|
|
6013
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6014
|
+
if (!lineInfo) {
|
|
6015
|
+
return false;
|
|
6016
|
+
}
|
|
6017
|
+
return INCOMPLETE_SEQUENCE_TAIL_RE.test(lineInfo.trimmed);
|
|
6018
|
+
}
|
|
6019
|
+
function hasSplitNestedKeyTail(normalized) {
|
|
6020
|
+
var _a;
|
|
6021
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6022
|
+
if (!lineInfo) {
|
|
6023
|
+
return false;
|
|
6024
|
+
}
|
|
6025
|
+
const { trimmed, indent, index } = lineInfo;
|
|
6026
|
+
if (indent === 0) {
|
|
6027
|
+
return false;
|
|
6028
|
+
}
|
|
6029
|
+
if (trimmed.startsWith("#") || trimmed.startsWith("-") || trimmed.includes(":")) {
|
|
6030
|
+
return false;
|
|
6031
|
+
}
|
|
6032
|
+
const lines = normalized.split("\n");
|
|
6033
|
+
let parentIndex = index - 1;
|
|
6034
|
+
while (parentIndex >= 0) {
|
|
6035
|
+
const parentRaw = (_a = lines[parentIndex]) != null ? _a : "";
|
|
6036
|
+
const parentTrimmed = parentRaw.trim();
|
|
6037
|
+
if (parentTrimmed.length === 0 || parentTrimmed.startsWith("#")) {
|
|
6038
|
+
parentIndex -= 1;
|
|
6039
|
+
continue;
|
|
6040
|
+
}
|
|
6041
|
+
const parentIndent = parentRaw.length - parentRaw.trimStart().length;
|
|
6042
|
+
if (parentIndent >= indent) {
|
|
6043
|
+
parentIndex -= 1;
|
|
6044
|
+
continue;
|
|
6045
|
+
}
|
|
6046
|
+
if (!parentTrimmed.endsWith(":")) {
|
|
6047
|
+
return false;
|
|
6048
|
+
}
|
|
6049
|
+
if (BLOCK_SCALAR_KEY_RE.test(parentTrimmed)) {
|
|
6050
|
+
return false;
|
|
6051
|
+
}
|
|
6052
|
+
return true;
|
|
6053
|
+
}
|
|
6054
|
+
return false;
|
|
6055
|
+
}
|
|
6056
|
+
function extractTrailingPlainScalarValue(line) {
|
|
6057
|
+
var _a;
|
|
6058
|
+
if (BLOCK_SCALAR_KEY_RE.test(line)) {
|
|
6059
|
+
return null;
|
|
6060
|
+
}
|
|
6061
|
+
const mappingMatch = line.match(PLAIN_MAPPING_VALUE_RE);
|
|
6062
|
+
const sequenceMatch = line.match(PLAIN_SEQUENCE_VALUE_RE);
|
|
6063
|
+
const value = (_a = mappingMatch == null ? void 0 : mappingMatch[1]) != null ? _a : sequenceMatch == null ? void 0 : sequenceMatch[1];
|
|
6064
|
+
if (!value) {
|
|
6065
|
+
return null;
|
|
6066
|
+
}
|
|
6067
|
+
const trimmedValue = value.trim();
|
|
6068
|
+
if (trimmedValue.length === 0) {
|
|
6069
|
+
return null;
|
|
6070
|
+
}
|
|
6071
|
+
if (trimmedValue.startsWith('"') || trimmedValue.startsWith("'")) {
|
|
6072
|
+
return null;
|
|
6073
|
+
}
|
|
6074
|
+
if (trimmedValue.startsWith("{") || trimmedValue.startsWith("[") || trimmedValue.startsWith("|") || trimmedValue.startsWith(">")) {
|
|
6075
|
+
return null;
|
|
6076
|
+
}
|
|
6077
|
+
return trimmedValue;
|
|
6078
|
+
}
|
|
6079
|
+
function hasUnterminatedPlainScalarTail(normalized) {
|
|
6080
|
+
if (normalized.endsWith("\n")) {
|
|
6081
|
+
return false;
|
|
6082
|
+
}
|
|
6083
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6084
|
+
if (!lineInfo) {
|
|
6085
|
+
return false;
|
|
6086
|
+
}
|
|
6087
|
+
return extractTrailingPlainScalarValue(lineInfo.trimmed) != null;
|
|
6088
|
+
}
|
|
6089
|
+
function hasUnstableProgressTail(normalized) {
|
|
6090
|
+
return hasIncompleteMappingTail(normalized) || hasIncompleteSequenceTail(normalized) || hasSplitNestedKeyTail(normalized) || hasUnterminatedPlainScalarTail(normalized);
|
|
6091
|
+
}
|
|
6092
|
+
function trimTrailingNewlineInUnknown(value) {
|
|
6093
|
+
if (typeof value === "string") {
|
|
6094
|
+
if (value.endsWith("\n")) {
|
|
6095
|
+
return value.slice(0, -1);
|
|
6096
|
+
}
|
|
6097
|
+
return value;
|
|
6098
|
+
}
|
|
6099
|
+
if (Array.isArray(value)) {
|
|
6100
|
+
return value.map((item) => trimTrailingNewlineInUnknown(item));
|
|
6101
|
+
}
|
|
6102
|
+
if (value && typeof value === "object") {
|
|
6103
|
+
return Object.fromEntries(
|
|
6104
|
+
Object.entries(value).map(([key, item]) => [
|
|
6105
|
+
key,
|
|
6106
|
+
trimTrailingNewlineInUnknown(item)
|
|
6107
|
+
])
|
|
6108
|
+
);
|
|
6109
|
+
}
|
|
6110
|
+
return value;
|
|
6111
|
+
}
|
|
6112
|
+
function stabilizeParsedValueForStreamProgress(value, source) {
|
|
6113
|
+
if (source.endsWith("\n")) {
|
|
6114
|
+
return value;
|
|
6115
|
+
}
|
|
6116
|
+
return trimTrailingNewlineInUnknown(value);
|
|
6117
|
+
}
|
|
4540
6118
|
function findClosingTagEnd(text, contentStart, toolName) {
|
|
4541
6119
|
let pos = contentStart;
|
|
4542
6120
|
let depth = 1;
|
|
@@ -4552,7 +6130,7 @@ function findClosingTagEnd(text, contentStart, toolName) {
|
|
|
4552
6130
|
break;
|
|
4553
6131
|
}
|
|
4554
6132
|
let p = ltIdx + 2;
|
|
4555
|
-
while (p < gtIdx &&
|
|
6133
|
+
while (p < gtIdx && WHITESPACE_REGEX5.test(text[p])) {
|
|
4556
6134
|
p++;
|
|
4557
6135
|
}
|
|
4558
6136
|
const nameStart = p;
|
|
@@ -4572,7 +6150,7 @@ function findClosingTagEnd(text, contentStart, toolName) {
|
|
|
4572
6150
|
pos = gtIdx === -1 ? text.length : gtIdx + 1;
|
|
4573
6151
|
} else {
|
|
4574
6152
|
let p = ltIdx + 1;
|
|
4575
|
-
while (p < text.length &&
|
|
6153
|
+
while (p < text.length && WHITESPACE_REGEX5.test(text[p])) {
|
|
4576
6154
|
p++;
|
|
4577
6155
|
}
|
|
4578
6156
|
const nameStart = p;
|
|
@@ -4585,7 +6163,7 @@ function findClosingTagEnd(text, contentStart, toolName) {
|
|
|
4585
6163
|
break;
|
|
4586
6164
|
}
|
|
4587
6165
|
let r = gtIdx - 1;
|
|
4588
|
-
while (r >= nameStart &&
|
|
6166
|
+
while (r >= nameStart && WHITESPACE_REGEX5.test(text[r])) {
|
|
4589
6167
|
r--;
|
|
4590
6168
|
}
|
|
4591
6169
|
const selfClosing = text[r] === "/";
|
|
@@ -4608,7 +6186,7 @@ function findEarliestTagPosition(openIdx, selfIdx) {
|
|
|
4608
6186
|
function collectToolCallsForName(text, toolName) {
|
|
4609
6187
|
const toolCalls = [];
|
|
4610
6188
|
let searchIndex = 0;
|
|
4611
|
-
const selfTagRegex =
|
|
6189
|
+
const selfTagRegex = getSelfClosingTagPattern2(toolName);
|
|
4612
6190
|
while (searchIndex < text.length) {
|
|
4613
6191
|
const startTag = `<${toolName}>`;
|
|
4614
6192
|
const openIdx = text.indexOf(startTag, searchIndex);
|
|
@@ -4660,47 +6238,48 @@ function findToolCalls2(text, toolNames) {
|
|
|
4660
6238
|
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
4661
6239
|
}
|
|
4662
6240
|
function parseYamlContent(yamlContent, options) {
|
|
4663
|
-
var _a, _b
|
|
4664
|
-
|
|
4665
|
-
if (normalized.startsWith("\n")) {
|
|
4666
|
-
normalized = normalized.slice(1);
|
|
4667
|
-
}
|
|
4668
|
-
const lines = normalized.split("\n");
|
|
4669
|
-
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
|
6241
|
+
var _a, _b;
|
|
6242
|
+
const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
|
|
4670
6243
|
if (nonEmptyLines.length === 0) {
|
|
4671
6244
|
return {};
|
|
4672
6245
|
}
|
|
4673
|
-
const
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
})
|
|
4678
|
-
|
|
4679
|
-
if (minIndent > 0) {
|
|
4680
|
-
normalized = lines.map((line) => line.slice(minIndent)).join("\n");
|
|
6246
|
+
const parsed = parseYamlDocumentAsMapping(normalized);
|
|
6247
|
+
if (parsed.errors.length > 0) {
|
|
6248
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "YAML parse error", {
|
|
6249
|
+
errors: parsed.errors
|
|
6250
|
+
});
|
|
6251
|
+
return null;
|
|
4681
6252
|
}
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
6253
|
+
if (parsed.value === null) {
|
|
6254
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
|
|
6255
|
+
got: "non-mapping"
|
|
6256
|
+
});
|
|
6257
|
+
return null;
|
|
6258
|
+
}
|
|
6259
|
+
return parsed.value;
|
|
6260
|
+
}
|
|
6261
|
+
function parseYamlContentForStreamProgress(yamlContent) {
|
|
6262
|
+
const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
|
|
6263
|
+
if (nonEmptyLines.length === 0) {
|
|
6264
|
+
return {};
|
|
6265
|
+
}
|
|
6266
|
+
let candidate = normalized;
|
|
6267
|
+
while (true) {
|
|
6268
|
+
const parsed = parseYamlDocumentAsMapping(candidate);
|
|
6269
|
+
if (parsed.errors.length === 0 && !hasUnstableProgressTail(candidate)) {
|
|
6270
|
+
if (candidate.trim().length === 0 && normalized.trim().length > 0) {
|
|
6271
|
+
return null;
|
|
6272
|
+
}
|
|
6273
|
+
return stabilizeParsedValueForStreamProgress(parsed.value, candidate);
|
|
4689
6274
|
}
|
|
4690
|
-
const
|
|
4691
|
-
if (
|
|
4692
|
-
return
|
|
6275
|
+
const truncated = dropLastMeaningfulLine(candidate);
|
|
6276
|
+
if (truncated == null) {
|
|
6277
|
+
return null;
|
|
4693
6278
|
}
|
|
4694
|
-
if (
|
|
4695
|
-
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
|
|
4696
|
-
got: typeof result
|
|
4697
|
-
});
|
|
6279
|
+
if (truncated === candidate) {
|
|
4698
6280
|
return null;
|
|
4699
6281
|
}
|
|
4700
|
-
|
|
4701
|
-
} catch (error) {
|
|
4702
|
-
(_c = options == null ? void 0 : options.onError) == null ? void 0 : _c.call(options, "Failed to parse YAML content", { error });
|
|
4703
|
-
return null;
|
|
6282
|
+
candidate = truncated;
|
|
4704
6283
|
}
|
|
4705
6284
|
}
|
|
4706
6285
|
function processToolCallMatch(text, tc, currentIndex, processedElements, options) {
|
|
@@ -4716,7 +6295,7 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
|
|
|
4716
6295
|
if (parsedArgs !== null) {
|
|
4717
6296
|
processedElements.push({
|
|
4718
6297
|
type: "tool-call",
|
|
4719
|
-
toolCallId:
|
|
6298
|
+
toolCallId: generateToolCallId(),
|
|
4720
6299
|
toolName: tc.toolName,
|
|
4721
6300
|
input: JSON.stringify(parsedArgs)
|
|
4722
6301
|
});
|
|
@@ -4729,38 +6308,6 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
|
|
|
4729
6308
|
}
|
|
4730
6309
|
return tc.endIndex;
|
|
4731
6310
|
}
|
|
4732
|
-
function createFlushTextHandler2(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
4733
|
-
return (controller, text) => {
|
|
4734
|
-
const content = text;
|
|
4735
|
-
if (content) {
|
|
4736
|
-
if (!getCurrentTextId()) {
|
|
4737
|
-
const newId = generateId();
|
|
4738
|
-
setCurrentTextId(newId);
|
|
4739
|
-
controller.enqueue({
|
|
4740
|
-
type: "text-start",
|
|
4741
|
-
id: newId
|
|
4742
|
-
});
|
|
4743
|
-
setHasEmittedTextStart(true);
|
|
4744
|
-
}
|
|
4745
|
-
controller.enqueue({
|
|
4746
|
-
type: "text-delta",
|
|
4747
|
-
id: getCurrentTextId(),
|
|
4748
|
-
delta: content
|
|
4749
|
-
});
|
|
4750
|
-
}
|
|
4751
|
-
const currentTextId = getCurrentTextId();
|
|
4752
|
-
if (currentTextId && !text) {
|
|
4753
|
-
if (getHasEmittedTextStart()) {
|
|
4754
|
-
controller.enqueue({
|
|
4755
|
-
type: "text-end",
|
|
4756
|
-
id: currentTextId
|
|
4757
|
-
});
|
|
4758
|
-
setHasEmittedTextStart(false);
|
|
4759
|
-
}
|
|
4760
|
-
setCurrentTextId(null);
|
|
4761
|
-
}
|
|
4762
|
-
};
|
|
4763
|
-
}
|
|
4764
6311
|
function findEarliestToolTag2(buffer, toolNames) {
|
|
4765
6312
|
let bestIndex = -1;
|
|
4766
6313
|
let bestName = "";
|
|
@@ -4768,8 +6315,9 @@ function findEarliestToolTag2(buffer, toolNames) {
|
|
|
4768
6315
|
let bestTagLength = 0;
|
|
4769
6316
|
for (const name of toolNames) {
|
|
4770
6317
|
const openTag = `<${name}>`;
|
|
4771
|
-
const selfTagRegex =
|
|
6318
|
+
const selfTagRegex = getSelfClosingTagPattern2(name);
|
|
4772
6319
|
const idxOpen = buffer.indexOf(openTag);
|
|
6320
|
+
selfTagRegex.lastIndex = 0;
|
|
4773
6321
|
const selfMatch = selfTagRegex.exec(buffer);
|
|
4774
6322
|
const idxSelf = selfMatch ? selfMatch.index : -1;
|
|
4775
6323
|
if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
|
|
@@ -4792,6 +6340,29 @@ function findEarliestToolTag2(buffer, toolNames) {
|
|
|
4792
6340
|
tagLength: bestTagLength
|
|
4793
6341
|
};
|
|
4794
6342
|
}
|
|
6343
|
+
function stripTrailingPartialCloseTag(content, toolName) {
|
|
6344
|
+
const closeTag = `</${toolName}>`;
|
|
6345
|
+
const lastLineBreakIndex = Math.max(
|
|
6346
|
+
content.lastIndexOf("\n"),
|
|
6347
|
+
content.lastIndexOf("\r")
|
|
6348
|
+
);
|
|
6349
|
+
const lineStartIndex = lastLineBreakIndex === -1 ? 0 : lastLineBreakIndex + 1;
|
|
6350
|
+
const trailingLine = content.slice(lineStartIndex);
|
|
6351
|
+
const trimmedTrailingLine = trailingLine.trim();
|
|
6352
|
+
if (trimmedTrailingLine.length === 0 || !trimmedTrailingLine.startsWith("</") || trimmedTrailingLine === closeTag || !closeTag.startsWith(trimmedTrailingLine)) {
|
|
6353
|
+
return content;
|
|
6354
|
+
}
|
|
6355
|
+
const leadingWhitespaceLength = trailingLine.length - trailingLine.trimStart().length;
|
|
6356
|
+
const preservedLeadingWhitespace = trailingLine.slice(
|
|
6357
|
+
0,
|
|
6358
|
+
leadingWhitespaceLength
|
|
6359
|
+
);
|
|
6360
|
+
const contentWithoutPartial = `${content.slice(
|
|
6361
|
+
0,
|
|
6362
|
+
lineStartIndex
|
|
6363
|
+
)}${preservedLeadingWhitespace}`;
|
|
6364
|
+
return contentWithoutPartial.trimEnd();
|
|
6365
|
+
}
|
|
4795
6366
|
var yamlProtocol = (_protocolOptions) => {
|
|
4796
6367
|
return {
|
|
4797
6368
|
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
@@ -4817,18 +6388,32 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
4817
6388
|
}
|
|
4818
6389
|
const processedElements = [];
|
|
4819
6390
|
let currentIndex = 0;
|
|
4820
|
-
|
|
6391
|
+
let parseText = text;
|
|
6392
|
+
let toolCalls = findToolCalls2(parseText, toolNames);
|
|
6393
|
+
if (toolCalls.length === 0) {
|
|
6394
|
+
const repaired = tryRepairXmlSelfClosingRootWithBody(
|
|
6395
|
+
parseText,
|
|
6396
|
+
toolNames
|
|
6397
|
+
);
|
|
6398
|
+
if (repaired) {
|
|
6399
|
+
const repairedCalls = findToolCalls2(repaired, toolNames);
|
|
6400
|
+
if (repairedCalls.length > 0) {
|
|
6401
|
+
parseText = repaired;
|
|
6402
|
+
toolCalls = repairedCalls;
|
|
6403
|
+
}
|
|
6404
|
+
}
|
|
6405
|
+
}
|
|
4821
6406
|
for (const tc of toolCalls) {
|
|
4822
6407
|
currentIndex = processToolCallMatch(
|
|
4823
|
-
|
|
6408
|
+
parseText,
|
|
4824
6409
|
tc,
|
|
4825
6410
|
currentIndex,
|
|
4826
6411
|
processedElements,
|
|
4827
6412
|
options
|
|
4828
6413
|
);
|
|
4829
6414
|
}
|
|
4830
|
-
if (currentIndex <
|
|
4831
|
-
addTextSegment(
|
|
6415
|
+
if (currentIndex < parseText.length) {
|
|
6416
|
+
addTextSegment(parseText.substring(currentIndex), processedElements);
|
|
4832
6417
|
}
|
|
4833
6418
|
return processedElements;
|
|
4834
6419
|
},
|
|
@@ -4838,7 +6423,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
4838
6423
|
let currentToolCall = null;
|
|
4839
6424
|
let currentTextId = null;
|
|
4840
6425
|
let hasEmittedTextStart = false;
|
|
4841
|
-
const flushText =
|
|
6426
|
+
const flushText = createFlushTextHandler(
|
|
4842
6427
|
() => currentTextId,
|
|
4843
6428
|
(newId) => {
|
|
4844
6429
|
currentTextId = newId;
|
|
@@ -4848,33 +6433,128 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
4848
6433
|
hasEmittedTextStart = value;
|
|
4849
6434
|
}
|
|
4850
6435
|
);
|
|
4851
|
-
const
|
|
6436
|
+
const emitToolInputProgress2 = (controller, toolContent) => {
|
|
6437
|
+
if (!currentToolCall) {
|
|
6438
|
+
return;
|
|
6439
|
+
}
|
|
6440
|
+
const parsedArgs = parseYamlContentForStreamProgress(toolContent);
|
|
6441
|
+
if (parsedArgs === null) {
|
|
6442
|
+
return;
|
|
6443
|
+
}
|
|
6444
|
+
const fullInput = JSON.stringify(parsedArgs);
|
|
6445
|
+
if (fullInput === "{}" && toolContent.trim().length === 0) {
|
|
6446
|
+
return;
|
|
6447
|
+
}
|
|
6448
|
+
const prefixCandidate = toIncompleteJsonPrefix(fullInput);
|
|
6449
|
+
emitPrefixDelta({
|
|
6450
|
+
controller,
|
|
6451
|
+
id: currentToolCall.toolCallId,
|
|
6452
|
+
state: currentToolCall,
|
|
6453
|
+
candidate: prefixCandidate
|
|
6454
|
+
});
|
|
6455
|
+
};
|
|
6456
|
+
const processToolCallEnd = (controller, toolContent, toolName, toolCallId) => {
|
|
4852
6457
|
var _a;
|
|
4853
6458
|
const parsedArgs = parseYamlContent(toolContent, options);
|
|
4854
6459
|
flushText(controller);
|
|
4855
6460
|
if (parsedArgs !== null) {
|
|
6461
|
+
const finalInput = JSON.stringify(parsedArgs);
|
|
6462
|
+
if (currentToolCall && currentToolCall.toolCallId === toolCallId) {
|
|
6463
|
+
emitFinalRemainder({
|
|
6464
|
+
controller,
|
|
6465
|
+
id: toolCallId,
|
|
6466
|
+
state: currentToolCall,
|
|
6467
|
+
finalFullJson: finalInput,
|
|
6468
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
6469
|
+
});
|
|
6470
|
+
}
|
|
6471
|
+
controller.enqueue({
|
|
6472
|
+
type: "tool-input-end",
|
|
6473
|
+
id: toolCallId
|
|
6474
|
+
});
|
|
4856
6475
|
controller.enqueue({
|
|
4857
6476
|
type: "tool-call",
|
|
4858
|
-
toolCallId
|
|
6477
|
+
toolCallId,
|
|
4859
6478
|
toolName,
|
|
4860
|
-
input:
|
|
6479
|
+
input: finalInput
|
|
4861
6480
|
});
|
|
4862
6481
|
} else {
|
|
6482
|
+
controller.enqueue({
|
|
6483
|
+
type: "tool-input-end",
|
|
6484
|
+
id: toolCallId
|
|
6485
|
+
});
|
|
4863
6486
|
const original = `<${toolName}>${toolContent}</${toolName}>`;
|
|
4864
6487
|
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
|
|
4865
6488
|
toolCall: original
|
|
4866
6489
|
});
|
|
4867
|
-
|
|
6490
|
+
if (shouldEmitRawToolCallTextOnError3(options)) {
|
|
6491
|
+
flushText(controller, original);
|
|
6492
|
+
}
|
|
6493
|
+
}
|
|
6494
|
+
};
|
|
6495
|
+
const finalizeUnclosedToolCall = (controller) => {
|
|
6496
|
+
var _a;
|
|
6497
|
+
if (!currentToolCall) {
|
|
6498
|
+
return;
|
|
4868
6499
|
}
|
|
6500
|
+
emitToolInputProgress2(controller, buffer);
|
|
6501
|
+
const { name: toolName, toolCallId } = currentToolCall;
|
|
6502
|
+
const reconciledBuffer = stripTrailingPartialCloseTag(buffer, toolName);
|
|
6503
|
+
const parsedArgs = parseYamlContent(reconciledBuffer, options);
|
|
6504
|
+
flushText(controller);
|
|
6505
|
+
if (parsedArgs !== null) {
|
|
6506
|
+
const finalInput = JSON.stringify(parsedArgs);
|
|
6507
|
+
emitFinalRemainder({
|
|
6508
|
+
controller,
|
|
6509
|
+
id: toolCallId,
|
|
6510
|
+
state: currentToolCall,
|
|
6511
|
+
finalFullJson: finalInput,
|
|
6512
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
6513
|
+
});
|
|
6514
|
+
controller.enqueue({
|
|
6515
|
+
type: "tool-input-end",
|
|
6516
|
+
id: toolCallId
|
|
6517
|
+
});
|
|
6518
|
+
controller.enqueue({
|
|
6519
|
+
type: "tool-call",
|
|
6520
|
+
toolCallId,
|
|
6521
|
+
toolName,
|
|
6522
|
+
input: finalInput
|
|
6523
|
+
});
|
|
6524
|
+
} else {
|
|
6525
|
+
controller.enqueue({
|
|
6526
|
+
type: "tool-input-end",
|
|
6527
|
+
id: toolCallId
|
|
6528
|
+
});
|
|
6529
|
+
const unfinishedContent = `<${toolName}>${buffer}`;
|
|
6530
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
6531
|
+
options,
|
|
6532
|
+
"Could not complete streaming YAML tool call at finish.",
|
|
6533
|
+
{ toolCall: unfinishedContent }
|
|
6534
|
+
);
|
|
6535
|
+
if (shouldEmitRawToolCallTextOnError3(options)) {
|
|
6536
|
+
flushText(controller, unfinishedContent);
|
|
6537
|
+
}
|
|
6538
|
+
}
|
|
6539
|
+
buffer = "";
|
|
6540
|
+
currentToolCall = null;
|
|
4869
6541
|
};
|
|
4870
6542
|
const handlePendingToolCall = (controller, endTag, toolName) => {
|
|
6543
|
+
var _a;
|
|
4871
6544
|
const endIdx = buffer.indexOf(endTag);
|
|
4872
6545
|
if (endIdx === -1) {
|
|
6546
|
+
emitToolInputProgress2(controller, buffer);
|
|
4873
6547
|
return false;
|
|
4874
6548
|
}
|
|
4875
6549
|
const content = buffer.substring(0, endIdx);
|
|
6550
|
+
emitToolInputProgress2(controller, content);
|
|
4876
6551
|
buffer = buffer.substring(endIdx + endTag.length);
|
|
4877
|
-
processToolCallEnd(
|
|
6552
|
+
processToolCallEnd(
|
|
6553
|
+
controller,
|
|
6554
|
+
content,
|
|
6555
|
+
toolName,
|
|
6556
|
+
(_a = currentToolCall == null ? void 0 : currentToolCall.toolCallId) != null ? _a : generateToolCallId()
|
|
6557
|
+
);
|
|
4878
6558
|
currentToolCall = null;
|
|
4879
6559
|
return true;
|
|
4880
6560
|
};
|
|
@@ -4891,13 +6571,35 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
4891
6571
|
if (tagIndex > 0) {
|
|
4892
6572
|
flushText(controller, buffer.substring(0, tagIndex));
|
|
4893
6573
|
}
|
|
6574
|
+
flushText(controller);
|
|
4894
6575
|
if (selfClosing) {
|
|
4895
6576
|
buffer = buffer.substring(tagIndex + tagLength);
|
|
4896
|
-
|
|
6577
|
+
const toolCallId = generateToolCallId();
|
|
6578
|
+
currentToolCall = {
|
|
6579
|
+
name: tagName,
|
|
6580
|
+
toolCallId,
|
|
6581
|
+
emittedInput: ""
|
|
6582
|
+
};
|
|
6583
|
+
controller.enqueue({
|
|
6584
|
+
type: "tool-input-start",
|
|
6585
|
+
id: toolCallId,
|
|
6586
|
+
toolName: tagName
|
|
6587
|
+
});
|
|
6588
|
+
processToolCallEnd(controller, "", tagName, toolCallId);
|
|
6589
|
+
currentToolCall = null;
|
|
4897
6590
|
} else {
|
|
4898
6591
|
const startTag = `<${tagName}>`;
|
|
4899
6592
|
buffer = buffer.substring(tagIndex + startTag.length);
|
|
4900
|
-
currentToolCall = {
|
|
6593
|
+
currentToolCall = {
|
|
6594
|
+
name: tagName,
|
|
6595
|
+
toolCallId: generateToolCallId(),
|
|
6596
|
+
emittedInput: ""
|
|
6597
|
+
};
|
|
6598
|
+
controller.enqueue({
|
|
6599
|
+
type: "tool-input-start",
|
|
6600
|
+
id: currentToolCall.toolCallId,
|
|
6601
|
+
toolName: tagName
|
|
6602
|
+
});
|
|
4901
6603
|
}
|
|
4902
6604
|
};
|
|
4903
6605
|
const processBuffer = (controller) => {
|
|
@@ -4924,8 +6626,19 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
4924
6626
|
return new TransformStream({
|
|
4925
6627
|
transform(chunk, controller) {
|
|
4926
6628
|
var _a;
|
|
6629
|
+
if (chunk.type === "finish") {
|
|
6630
|
+
if (currentToolCall) {
|
|
6631
|
+
finalizeUnclosedToolCall(controller);
|
|
6632
|
+
} else if (buffer) {
|
|
6633
|
+
flushText(controller, buffer);
|
|
6634
|
+
buffer = "";
|
|
6635
|
+
}
|
|
6636
|
+
flushText(controller);
|
|
6637
|
+
controller.enqueue(chunk);
|
|
6638
|
+
return;
|
|
6639
|
+
}
|
|
4927
6640
|
if (chunk.type !== "text-delta") {
|
|
4928
|
-
if (buffer) {
|
|
6641
|
+
if (!currentToolCall && buffer) {
|
|
4929
6642
|
flushText(controller, buffer);
|
|
4930
6643
|
buffer = "";
|
|
4931
6644
|
}
|
|
@@ -4938,10 +6651,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
4938
6651
|
},
|
|
4939
6652
|
flush(controller) {
|
|
4940
6653
|
if (currentToolCall) {
|
|
4941
|
-
|
|
4942
|
-
flushText(controller, unfinishedContent);
|
|
4943
|
-
buffer = "";
|
|
4944
|
-
currentToolCall = null;
|
|
6654
|
+
finalizeUnclosedToolCall(controller);
|
|
4945
6655
|
} else if (buffer) {
|
|
4946
6656
|
flushText(controller, buffer);
|
|
4947
6657
|
buffer = "";
|
|
@@ -5047,17 +6757,56 @@ function encodeOriginalTools(tools) {
|
|
|
5047
6757
|
inputSchema: JSON.stringify(t.inputSchema)
|
|
5048
6758
|
}))) || [];
|
|
5049
6759
|
}
|
|
5050
|
-
function decodeOriginalTools(originalTools) {
|
|
6760
|
+
function decodeOriginalTools(originalTools, options) {
|
|
6761
|
+
var _a, _b, _c;
|
|
5051
6762
|
if (!originalTools) {
|
|
5052
6763
|
return [];
|
|
5053
6764
|
}
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
6765
|
+
const decodedTools = [];
|
|
6766
|
+
for (const [index, tool] of originalTools.entries()) {
|
|
6767
|
+
if (!tool || typeof tool.name !== "string") {
|
|
6768
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Invalid originalTools entry: missing tool name", {
|
|
6769
|
+
index,
|
|
6770
|
+
tool
|
|
6771
|
+
});
|
|
6772
|
+
continue;
|
|
6773
|
+
}
|
|
6774
|
+
if (typeof tool.inputSchema !== "string") {
|
|
6775
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
6776
|
+
options,
|
|
6777
|
+
"Invalid originalTools entry: inputSchema must be a string",
|
|
6778
|
+
{
|
|
6779
|
+
index,
|
|
6780
|
+
toolName: tool.name
|
|
6781
|
+
}
|
|
6782
|
+
);
|
|
6783
|
+
continue;
|
|
6784
|
+
}
|
|
6785
|
+
try {
|
|
6786
|
+
decodedTools.push({
|
|
6787
|
+
type: "function",
|
|
6788
|
+
name: tool.name,
|
|
6789
|
+
inputSchema: JSON.parse(tool.inputSchema)
|
|
6790
|
+
});
|
|
6791
|
+
} catch (error) {
|
|
6792
|
+
(_c = options == null ? void 0 : options.onError) == null ? void 0 : _c.call(
|
|
6793
|
+
options,
|
|
6794
|
+
"Failed to decode originalTools input schema, using permissive fallback schema",
|
|
6795
|
+
{
|
|
6796
|
+
index,
|
|
6797
|
+
toolName: tool.name,
|
|
6798
|
+
inputSchema: tool.inputSchema,
|
|
6799
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6800
|
+
}
|
|
6801
|
+
);
|
|
6802
|
+
decodedTools.push({
|
|
6803
|
+
type: "function",
|
|
6804
|
+
name: tool.name,
|
|
6805
|
+
inputSchema: { type: "object" }
|
|
6806
|
+
});
|
|
6807
|
+
}
|
|
6808
|
+
}
|
|
6809
|
+
return decodedTools;
|
|
5061
6810
|
}
|
|
5062
6811
|
function extractToolNamesFromOriginalTools(originalTools) {
|
|
5063
6812
|
return (originalTools == null ? void 0 : originalTools.map((t) => t.name)) || [];
|
|
@@ -5080,25 +6829,336 @@ function hasInputProperty(obj) {
|
|
|
5080
6829
|
return typeof obj === "object" && obj !== null && "input" in obj;
|
|
5081
6830
|
}
|
|
5082
6831
|
|
|
5083
|
-
// src/
|
|
5084
|
-
|
|
5085
|
-
|
|
6832
|
+
// src/core/utils/generated-text-json-recovery.ts
|
|
6833
|
+
function isRecord(value) {
|
|
6834
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6835
|
+
}
|
|
6836
|
+
function safeStringify2(value) {
|
|
6837
|
+
try {
|
|
6838
|
+
return JSON.stringify(value != null ? value : {});
|
|
6839
|
+
} catch (e) {
|
|
6840
|
+
return "{}";
|
|
6841
|
+
}
|
|
6842
|
+
}
|
|
6843
|
+
function parseJsonCandidate(candidateText) {
|
|
6844
|
+
try {
|
|
6845
|
+
return parse(candidateText);
|
|
6846
|
+
} catch (e) {
|
|
6847
|
+
return void 0;
|
|
6848
|
+
}
|
|
6849
|
+
}
|
|
6850
|
+
function extractCodeBlockCandidates(text) {
|
|
6851
|
+
var _a, _b;
|
|
6852
|
+
const codeBlockRegex = /```(?:json|yaml|xml)?\s*([\s\S]*?)```/gi;
|
|
6853
|
+
const candidates = [];
|
|
6854
|
+
let match;
|
|
6855
|
+
while (true) {
|
|
6856
|
+
match = codeBlockRegex.exec(text);
|
|
6857
|
+
if (!match) {
|
|
6858
|
+
break;
|
|
6859
|
+
}
|
|
6860
|
+
const body = (_a = match[1]) == null ? void 0 : _a.trim();
|
|
6861
|
+
if (body) {
|
|
6862
|
+
const startIndex = (_b = match.index) != null ? _b : 0;
|
|
6863
|
+
const endIndex = startIndex + match[0].length;
|
|
6864
|
+
candidates.push({
|
|
6865
|
+
text: body,
|
|
6866
|
+
startIndex,
|
|
6867
|
+
endIndex
|
|
6868
|
+
});
|
|
6869
|
+
}
|
|
6870
|
+
}
|
|
6871
|
+
return candidates;
|
|
6872
|
+
}
|
|
6873
|
+
function scanJsonChar(state, char) {
|
|
6874
|
+
if (state.inString) {
|
|
6875
|
+
if (state.escaping) {
|
|
6876
|
+
return { ...state, escaping: false };
|
|
6877
|
+
}
|
|
6878
|
+
if (char === "\\") {
|
|
6879
|
+
return { ...state, escaping: true };
|
|
6880
|
+
}
|
|
6881
|
+
if (char === '"') {
|
|
6882
|
+
return { ...state, inString: false };
|
|
6883
|
+
}
|
|
6884
|
+
return state;
|
|
6885
|
+
}
|
|
6886
|
+
if (char === '"') {
|
|
6887
|
+
return { ...state, inString: true };
|
|
6888
|
+
}
|
|
6889
|
+
if (char === "{") {
|
|
6890
|
+
return { ...state, depth: state.depth + 1 };
|
|
6891
|
+
}
|
|
6892
|
+
if (char === "}") {
|
|
6893
|
+
return { ...state, depth: Math.max(0, state.depth - 1) };
|
|
6894
|
+
}
|
|
6895
|
+
return state;
|
|
6896
|
+
}
|
|
6897
|
+
function extractBalancedJsonObjects(text) {
|
|
6898
|
+
const maxCandidateLength = 1e4;
|
|
6899
|
+
const candidates = [];
|
|
6900
|
+
let state = { depth: 0, inString: false, escaping: false };
|
|
6901
|
+
let currentStart = null;
|
|
6902
|
+
let ignoreCurrent = false;
|
|
6903
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
6904
|
+
const char = text[index];
|
|
6905
|
+
if (!state.inString && char === "{" && state.depth === 0) {
|
|
6906
|
+
currentStart = index;
|
|
6907
|
+
ignoreCurrent = false;
|
|
6908
|
+
}
|
|
6909
|
+
state = scanJsonChar(state, char);
|
|
6910
|
+
if (currentStart !== null && !ignoreCurrent && index - currentStart + 1 > maxCandidateLength) {
|
|
6911
|
+
ignoreCurrent = true;
|
|
6912
|
+
}
|
|
6913
|
+
if (!state.inString && char === "}" && state.depth === 0) {
|
|
6914
|
+
if (currentStart !== null && !ignoreCurrent) {
|
|
6915
|
+
const endIndex = index + 1;
|
|
6916
|
+
const candidate = text.slice(currentStart, endIndex);
|
|
6917
|
+
if (candidate.length > 1) {
|
|
6918
|
+
candidates.push({
|
|
6919
|
+
text: candidate,
|
|
6920
|
+
startIndex: currentStart,
|
|
6921
|
+
endIndex
|
|
6922
|
+
});
|
|
6923
|
+
}
|
|
6924
|
+
}
|
|
6925
|
+
currentStart = null;
|
|
6926
|
+
ignoreCurrent = false;
|
|
6927
|
+
}
|
|
6928
|
+
}
|
|
6929
|
+
return candidates;
|
|
6930
|
+
}
|
|
6931
|
+
function extractTaggedToolCallCandidates(rawText) {
|
|
6932
|
+
var _a, _b;
|
|
6933
|
+
const toolCallRegex = /<tool_call>([\s\S]*?)<\/tool_call>/gi;
|
|
6934
|
+
const candidates = [];
|
|
6935
|
+
let match;
|
|
6936
|
+
while (true) {
|
|
6937
|
+
match = toolCallRegex.exec(rawText);
|
|
6938
|
+
if (!match) {
|
|
6939
|
+
break;
|
|
6940
|
+
}
|
|
6941
|
+
const body = (_a = match[1]) == null ? void 0 : _a.trim();
|
|
6942
|
+
if (!body) {
|
|
6943
|
+
continue;
|
|
6944
|
+
}
|
|
6945
|
+
const startIndex = (_b = match.index) != null ? _b : 0;
|
|
6946
|
+
const endIndex = startIndex + match[0].length;
|
|
6947
|
+
candidates.push({
|
|
6948
|
+
text: body,
|
|
6949
|
+
startIndex,
|
|
6950
|
+
endIndex
|
|
6951
|
+
});
|
|
6952
|
+
}
|
|
6953
|
+
return candidates;
|
|
6954
|
+
}
|
|
6955
|
+
function extractJsonLikeCandidates(rawText) {
|
|
6956
|
+
return mergeJsonCandidatesByStart(
|
|
6957
|
+
extractTaggedToolCallCandidates(rawText),
|
|
6958
|
+
extractCodeBlockCandidates(rawText),
|
|
6959
|
+
extractBalancedJsonObjects(rawText)
|
|
6960
|
+
);
|
|
6961
|
+
}
|
|
6962
|
+
function mergeJsonCandidatesByStart(tagged, codeBlocks, balanced) {
|
|
6963
|
+
return [...tagged, ...codeBlocks, ...balanced].sort(
|
|
6964
|
+
(a, b) => a.startIndex !== b.startIndex ? a.startIndex - b.startIndex : b.endIndex - a.endIndex
|
|
6965
|
+
);
|
|
6966
|
+
}
|
|
6967
|
+
function toToolCallPart(candidate) {
|
|
6968
|
+
return {
|
|
6969
|
+
type: "tool-call",
|
|
6970
|
+
toolCallId: generateToolCallId(),
|
|
6971
|
+
toolName: candidate.toolName,
|
|
6972
|
+
input: candidate.input
|
|
6973
|
+
};
|
|
6974
|
+
}
|
|
6975
|
+
function toRecoveredParts(text, candidate, toolCallPart) {
|
|
6976
|
+
const out = [];
|
|
6977
|
+
const prefix = text.slice(0, candidate.startIndex);
|
|
6978
|
+
if (prefix.length > 0) {
|
|
6979
|
+
out.push({ type: "text", text: prefix });
|
|
6980
|
+
}
|
|
6981
|
+
out.push(toolCallPart);
|
|
6982
|
+
const suffix = text.slice(candidate.endIndex);
|
|
6983
|
+
if (suffix.length > 0) {
|
|
6984
|
+
out.push({ type: "text", text: suffix });
|
|
6985
|
+
}
|
|
6986
|
+
return out;
|
|
6987
|
+
}
|
|
6988
|
+
function parseAsToolPayload(payload, tools) {
|
|
6989
|
+
if (!isRecord(payload)) {
|
|
6990
|
+
return null;
|
|
6991
|
+
}
|
|
6992
|
+
const toolName = typeof payload.name === "string" && payload.name.trim().length > 0 ? payload.name.trim() : null;
|
|
6993
|
+
if (!toolName) {
|
|
6994
|
+
return null;
|
|
6995
|
+
}
|
|
6996
|
+
if (!tools.some((tool) => tool.name === toolName)) {
|
|
6997
|
+
return null;
|
|
6998
|
+
}
|
|
6999
|
+
const rawArgs = Object.hasOwn(payload, "arguments") ? payload.arguments : {};
|
|
7000
|
+
if (!isRecord(rawArgs)) {
|
|
7001
|
+
return null;
|
|
7002
|
+
}
|
|
7003
|
+
return {
|
|
7004
|
+
toolName,
|
|
7005
|
+
input: safeStringify2(rawArgs)
|
|
7006
|
+
};
|
|
7007
|
+
}
|
|
7008
|
+
function isLikelyArgumentsShapeForTool(args, tool) {
|
|
7009
|
+
const unwrapped = unwrapJsonSchema(tool.inputSchema);
|
|
7010
|
+
if (!isRecord(unwrapped)) {
|
|
7011
|
+
return false;
|
|
7012
|
+
}
|
|
7013
|
+
if (getSchemaType(unwrapped) !== "object") {
|
|
7014
|
+
return false;
|
|
7015
|
+
}
|
|
7016
|
+
const properties = unwrapped.properties;
|
|
7017
|
+
if (!isRecord(properties)) {
|
|
7018
|
+
return false;
|
|
7019
|
+
}
|
|
7020
|
+
const keys = Object.keys(args);
|
|
7021
|
+
if (keys.length === 0) {
|
|
7022
|
+
return false;
|
|
7023
|
+
}
|
|
7024
|
+
const knownKeys = keys.filter((key) => Object.hasOwn(properties, key));
|
|
7025
|
+
if (knownKeys.length === 0) {
|
|
7026
|
+
return false;
|
|
7027
|
+
}
|
|
7028
|
+
if (unwrapped.additionalProperties === false && knownKeys.length !== keys.length) {
|
|
7029
|
+
return false;
|
|
7030
|
+
}
|
|
7031
|
+
return true;
|
|
7032
|
+
}
|
|
7033
|
+
function parseAsArgumentsOnly(payload, tools) {
|
|
7034
|
+
if (tools.length !== 1) {
|
|
7035
|
+
return null;
|
|
7036
|
+
}
|
|
7037
|
+
if (!isRecord(payload)) {
|
|
7038
|
+
return null;
|
|
7039
|
+
}
|
|
7040
|
+
const hasNameEnvelope = Object.hasOwn(payload, "name") && typeof payload.name === "string" && payload.name.length > 0;
|
|
7041
|
+
const hasArgumentsEnvelope = Object.hasOwn(payload, "arguments") && (typeof payload.arguments === "string" || isRecord(payload.arguments));
|
|
7042
|
+
if (hasNameEnvelope || hasArgumentsEnvelope) {
|
|
7043
|
+
return null;
|
|
7044
|
+
}
|
|
7045
|
+
const tool = tools[0];
|
|
7046
|
+
if (!isLikelyArgumentsShapeForTool(payload, tool)) {
|
|
7047
|
+
return null;
|
|
7048
|
+
}
|
|
7049
|
+
return {
|
|
7050
|
+
toolName: tool.name,
|
|
7051
|
+
input: safeStringify2(payload)
|
|
7052
|
+
};
|
|
7053
|
+
}
|
|
7054
|
+
function recoverToolCallFromJsonCandidates(text, tools) {
|
|
7055
|
+
if (tools.length === 0) {
|
|
7056
|
+
return null;
|
|
7057
|
+
}
|
|
7058
|
+
const jsonCandidates = extractJsonLikeCandidates(text);
|
|
7059
|
+
for (const jsonCandidate of jsonCandidates) {
|
|
7060
|
+
const parsed = parseJsonCandidate(jsonCandidate.text);
|
|
7061
|
+
if (parsed === void 0) {
|
|
7062
|
+
continue;
|
|
7063
|
+
}
|
|
7064
|
+
const toolPayload = parseAsToolPayload(parsed, tools);
|
|
7065
|
+
if (toolPayload) {
|
|
7066
|
+
return toRecoveredParts(text, jsonCandidate, toToolCallPart(toolPayload));
|
|
7067
|
+
}
|
|
7068
|
+
const argsPayload = parseAsArgumentsOnly(parsed, tools);
|
|
7069
|
+
if (argsPayload) {
|
|
7070
|
+
return toRecoveredParts(text, jsonCandidate, toToolCallPart(argsPayload));
|
|
7071
|
+
}
|
|
7072
|
+
}
|
|
7073
|
+
return null;
|
|
7074
|
+
}
|
|
7075
|
+
|
|
7076
|
+
// src/core/utils/tool-call-coercion.ts
|
|
7077
|
+
function coerceToolCallInput(toolName, input, tools) {
|
|
5086
7078
|
var _a;
|
|
7079
|
+
let args = {};
|
|
7080
|
+
if (typeof input === "string") {
|
|
7081
|
+
try {
|
|
7082
|
+
args = JSON.parse(input);
|
|
7083
|
+
} catch (e) {
|
|
7084
|
+
return;
|
|
7085
|
+
}
|
|
7086
|
+
} else if (input && typeof input === "object") {
|
|
7087
|
+
args = input;
|
|
7088
|
+
} else {
|
|
7089
|
+
return;
|
|
7090
|
+
}
|
|
7091
|
+
const schema = (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
7092
|
+
const coerced = coerceBySchema(args, schema);
|
|
7093
|
+
return JSON.stringify(coerced != null ? coerced : {});
|
|
7094
|
+
}
|
|
7095
|
+
function coerceToolCallPart(part, tools) {
|
|
7096
|
+
const coercedInput = coerceToolCallInput(part.toolName, part.input, tools);
|
|
7097
|
+
if (coercedInput === void 0) {
|
|
7098
|
+
return part;
|
|
7099
|
+
}
|
|
7100
|
+
return {
|
|
7101
|
+
...part,
|
|
7102
|
+
input: coercedInput
|
|
7103
|
+
};
|
|
7104
|
+
}
|
|
7105
|
+
|
|
7106
|
+
// src/core/utils/tool-choice.ts
|
|
7107
|
+
function ensureNonEmptyToolName(name) {
|
|
7108
|
+
if (typeof name !== "string") {
|
|
7109
|
+
return "unknown";
|
|
7110
|
+
}
|
|
7111
|
+
const trimmed = name.trim();
|
|
7112
|
+
return trimmed.length > 0 ? trimmed : "unknown";
|
|
7113
|
+
}
|
|
7114
|
+
function safeStringify3(value) {
|
|
7115
|
+
try {
|
|
7116
|
+
return JSON.stringify(value != null ? value : {});
|
|
7117
|
+
} catch (e) {
|
|
7118
|
+
return "{}";
|
|
7119
|
+
}
|
|
7120
|
+
}
|
|
7121
|
+
function parseToolChoicePayload({
|
|
7122
|
+
text,
|
|
7123
|
+
tools,
|
|
7124
|
+
onError,
|
|
7125
|
+
errorMessage
|
|
7126
|
+
}) {
|
|
7127
|
+
let parsed;
|
|
5087
7128
|
try {
|
|
5088
|
-
|
|
7129
|
+
parsed = JSON.parse(text);
|
|
5089
7130
|
} catch (error) {
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
7131
|
+
onError == null ? void 0 : onError(errorMessage, {
|
|
7132
|
+
text,
|
|
7133
|
+
error: error instanceof Error ? error.message : String(error)
|
|
7134
|
+
});
|
|
7135
|
+
return { toolName: "unknown", input: "{}" };
|
|
7136
|
+
}
|
|
7137
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
7138
|
+
onError == null ? void 0 : onError("toolChoice JSON payload must be an object", {
|
|
7139
|
+
parsedType: typeof parsed,
|
|
7140
|
+
parsed
|
|
7141
|
+
});
|
|
7142
|
+
return { toolName: "unknown", input: "{}" };
|
|
7143
|
+
}
|
|
7144
|
+
const payload = parsed;
|
|
7145
|
+
const toolName = ensureNonEmptyToolName(payload.name);
|
|
7146
|
+
const rawArgs = Object.hasOwn(payload, "arguments") ? payload.arguments : {};
|
|
7147
|
+
if (rawArgs == null || typeof rawArgs !== "object" || Array.isArray(rawArgs)) {
|
|
7148
|
+
onError == null ? void 0 : onError("toolChoice arguments must be a JSON object", {
|
|
7149
|
+
toolName,
|
|
7150
|
+
arguments: rawArgs
|
|
7151
|
+
});
|
|
7152
|
+
return { toolName, input: "{}" };
|
|
5100
7153
|
}
|
|
7154
|
+
const coercedInput = coerceToolCallInput(toolName, rawArgs, tools);
|
|
7155
|
+
return {
|
|
7156
|
+
toolName,
|
|
7157
|
+
input: coercedInput != null ? coercedInput : safeStringify3(rawArgs)
|
|
7158
|
+
};
|
|
5101
7159
|
}
|
|
7160
|
+
|
|
7161
|
+
// src/generate-handler.ts
|
|
5102
7162
|
function logDebugSummary(debugSummary, toolCall, originText) {
|
|
5103
7163
|
if (debugSummary) {
|
|
5104
7164
|
debugSummary.originalText = originText;
|
|
@@ -5112,25 +7172,34 @@ function logDebugSummary(debugSummary, toolCall, originText) {
|
|
|
5112
7172
|
logParsedSummary({ toolCalls: [toolCall], originalText: originText });
|
|
5113
7173
|
}
|
|
5114
7174
|
}
|
|
5115
|
-
async function handleToolChoice(doGenerate, params) {
|
|
5116
|
-
var _a, _b, _c;
|
|
7175
|
+
async function handleToolChoice(doGenerate, params, tools) {
|
|
7176
|
+
var _a, _b, _c, _d;
|
|
5117
7177
|
const result = await doGenerate();
|
|
5118
7178
|
const first = (_a = result.content) == null ? void 0 : _a[0];
|
|
5119
|
-
|
|
7179
|
+
const onError = (_b = extractOnErrorOption(params.providerOptions)) == null ? void 0 : _b.onError;
|
|
7180
|
+
let toolName = "unknown";
|
|
7181
|
+
let input = "{}";
|
|
5120
7182
|
if (first && first.type === "text") {
|
|
5121
7183
|
if (getDebugLevel() === "parse") {
|
|
5122
7184
|
logRawChunk(first.text);
|
|
5123
7185
|
}
|
|
5124
|
-
parsed =
|
|
7186
|
+
const parsed = parseToolChoicePayload({
|
|
7187
|
+
text: first.text,
|
|
7188
|
+
tools,
|
|
7189
|
+
onError,
|
|
7190
|
+
errorMessage: "Failed to parse toolChoice JSON from generated model output"
|
|
7191
|
+
});
|
|
7192
|
+
toolName = parsed.toolName;
|
|
7193
|
+
input = parsed.input;
|
|
5125
7194
|
}
|
|
5126
7195
|
const toolCall = {
|
|
5127
7196
|
type: "tool-call",
|
|
5128
|
-
toolCallId: (
|
|
5129
|
-
toolName
|
|
5130
|
-
input
|
|
7197
|
+
toolCallId: generateToolCallId(),
|
|
7198
|
+
toolName,
|
|
7199
|
+
input
|
|
5131
7200
|
};
|
|
5132
7201
|
const originText = first && first.type === "text" ? first.text : "";
|
|
5133
|
-
const debugSummary = (
|
|
7202
|
+
const debugSummary = (_d = (_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) == null ? void 0 : _d.debugSummary;
|
|
5134
7203
|
logDebugSummary(debugSummary, toolCall, originText);
|
|
5135
7204
|
return {
|
|
5136
7205
|
...result,
|
|
@@ -5145,7 +7214,7 @@ function parseContent(content, protocol, tools, providerOptions) {
|
|
|
5145
7214
|
if (getDebugLevel() === "stream") {
|
|
5146
7215
|
logRawChunk(contentItem.text);
|
|
5147
7216
|
}
|
|
5148
|
-
|
|
7217
|
+
const parsedByProtocol = protocol.parseGeneratedText({
|
|
5149
7218
|
text: contentItem.text,
|
|
5150
7219
|
tools,
|
|
5151
7220
|
options: {
|
|
@@ -5153,9 +7222,20 @@ function parseContent(content, protocol, tools, providerOptions) {
|
|
|
5153
7222
|
...providerOptions == null ? void 0 : providerOptions.toolCallMiddleware
|
|
5154
7223
|
}
|
|
5155
7224
|
});
|
|
7225
|
+
const hasToolCall = parsedByProtocol.some(
|
|
7226
|
+
(part) => part.type === "tool-call"
|
|
7227
|
+
);
|
|
7228
|
+
if (hasToolCall) {
|
|
7229
|
+
return parsedByProtocol;
|
|
7230
|
+
}
|
|
7231
|
+
const recoveredFromJson = recoverToolCallFromJsonCandidates(
|
|
7232
|
+
contentItem.text,
|
|
7233
|
+
tools
|
|
7234
|
+
);
|
|
7235
|
+
return recoveredFromJson != null ? recoveredFromJson : parsedByProtocol;
|
|
5156
7236
|
});
|
|
5157
7237
|
return parsed.map(
|
|
5158
|
-
(part) =>
|
|
7238
|
+
(part) => part.type === "tool-call" ? coerceToolCallPart(part, tools) : part
|
|
5159
7239
|
);
|
|
5160
7240
|
}
|
|
5161
7241
|
function logParsedContent(content) {
|
|
@@ -5198,12 +7278,14 @@ async function wrapGenerate({
|
|
|
5198
7278
|
params
|
|
5199
7279
|
}) {
|
|
5200
7280
|
var _a, _b;
|
|
5201
|
-
|
|
5202
|
-
return handleToolChoice(doGenerate, params);
|
|
5203
|
-
}
|
|
7281
|
+
const onError = extractOnErrorOption(params.providerOptions);
|
|
5204
7282
|
const tools = originalToolsSchema.decode(
|
|
5205
|
-
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools
|
|
7283
|
+
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools,
|
|
7284
|
+
onError
|
|
5206
7285
|
);
|
|
7286
|
+
if (isToolChoiceActive(params)) {
|
|
7287
|
+
return handleToolChoice(doGenerate, params, tools);
|
|
7288
|
+
}
|
|
5207
7289
|
const result = await doGenerate();
|
|
5208
7290
|
if (result.content.length === 0) {
|
|
5209
7291
|
return result;
|
|
@@ -5227,28 +7309,6 @@ async function wrapGenerate({
|
|
|
5227
7309
|
content: newContent
|
|
5228
7310
|
};
|
|
5229
7311
|
}
|
|
5230
|
-
function fixToolCallWithSchema(part, tools) {
|
|
5231
|
-
var _a;
|
|
5232
|
-
if (part.type !== "tool-call") {
|
|
5233
|
-
return part;
|
|
5234
|
-
}
|
|
5235
|
-
let args = {};
|
|
5236
|
-
if (typeof part.input === "string") {
|
|
5237
|
-
try {
|
|
5238
|
-
args = JSON.parse(part.input);
|
|
5239
|
-
} catch (e) {
|
|
5240
|
-
return part;
|
|
5241
|
-
}
|
|
5242
|
-
} else if (part.input && typeof part.input === "object") {
|
|
5243
|
-
args = part.input;
|
|
5244
|
-
}
|
|
5245
|
-
const schema = (_a = tools.find((t) => t.name === part.toolName)) == null ? void 0 : _a.inputSchema;
|
|
5246
|
-
const coerced = coerceBySchema(args, schema);
|
|
5247
|
-
return {
|
|
5248
|
-
...part,
|
|
5249
|
-
input: JSON.stringify(coerced != null ? coerced : {})
|
|
5250
|
-
};
|
|
5251
|
-
}
|
|
5252
7312
|
|
|
5253
7313
|
// src/core/prompts/hermes-system-prompt.ts
|
|
5254
7314
|
function hermesSystemPromptTemplate(tools) {
|
|
@@ -5644,7 +7704,6 @@ unit: celsius
|
|
|
5644
7704
|
}
|
|
5645
7705
|
|
|
5646
7706
|
// src/stream-handler.ts
|
|
5647
|
-
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
5648
7707
|
async function wrapStream({
|
|
5649
7708
|
protocol,
|
|
5650
7709
|
doStream,
|
|
@@ -5652,19 +7711,22 @@ async function wrapStream({
|
|
|
5652
7711
|
params
|
|
5653
7712
|
}) {
|
|
5654
7713
|
var _a, _b, _c;
|
|
7714
|
+
const onErrorOptions = extractOnErrorOption(params.providerOptions);
|
|
7715
|
+
const tools = originalToolsSchema.decode(
|
|
7716
|
+
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools,
|
|
7717
|
+
onErrorOptions
|
|
7718
|
+
);
|
|
5655
7719
|
if (isToolChoiceActive(params)) {
|
|
5656
7720
|
return toolChoiceStream({
|
|
5657
7721
|
doGenerate,
|
|
5658
|
-
|
|
7722
|
+
tools,
|
|
7723
|
+
options: onErrorOptions
|
|
5659
7724
|
});
|
|
5660
7725
|
}
|
|
5661
7726
|
const { stream, ...rest } = await doStream();
|
|
5662
7727
|
const debugLevel = getDebugLevel();
|
|
5663
|
-
const tools = originalToolsSchema.decode(
|
|
5664
|
-
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools
|
|
5665
|
-
);
|
|
5666
7728
|
const options = {
|
|
5667
|
-
...
|
|
7729
|
+
...onErrorOptions,
|
|
5668
7730
|
...((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) || {}
|
|
5669
7731
|
};
|
|
5670
7732
|
const coreStream = stream.pipeThrough(
|
|
@@ -5679,13 +7741,26 @@ async function wrapStream({
|
|
|
5679
7741
|
}
|
|
5680
7742
|
)
|
|
5681
7743
|
).pipeThrough(protocol.createStreamParser({ tools, options }));
|
|
7744
|
+
let seenToolCall = false;
|
|
5682
7745
|
const v3Stream = coreStream.pipeThrough(
|
|
5683
7746
|
new TransformStream({
|
|
5684
7747
|
transform(part, controller) {
|
|
7748
|
+
let normalizedPart = part.type === "tool-call" ? coerceToolCallPart(part, tools) : part;
|
|
7749
|
+
if (normalizedPart.type === "tool-call") {
|
|
7750
|
+
seenToolCall = true;
|
|
7751
|
+
}
|
|
7752
|
+
if (normalizedPart.type === "finish" && seenToolCall && normalizedPart.finishReason.unified === "stop") {
|
|
7753
|
+
normalizedPart = {
|
|
7754
|
+
...normalizedPart,
|
|
7755
|
+
finishReason: normalizeToolCallsFinishReason(
|
|
7756
|
+
normalizedPart.finishReason
|
|
7757
|
+
)
|
|
7758
|
+
};
|
|
7759
|
+
}
|
|
5685
7760
|
if (debugLevel === "stream") {
|
|
5686
|
-
logParsedChunk(
|
|
7761
|
+
logParsedChunk(normalizedPart);
|
|
5687
7762
|
}
|
|
5688
|
-
controller.enqueue(
|
|
7763
|
+
controller.enqueue(normalizedPart);
|
|
5689
7764
|
}
|
|
5690
7765
|
})
|
|
5691
7766
|
);
|
|
@@ -5696,41 +7771,36 @@ async function wrapStream({
|
|
|
5696
7771
|
}
|
|
5697
7772
|
async function toolChoiceStream({
|
|
5698
7773
|
doGenerate,
|
|
7774
|
+
tools,
|
|
5699
7775
|
options
|
|
5700
7776
|
}) {
|
|
5701
|
-
var _a
|
|
7777
|
+
var _a;
|
|
7778
|
+
const normalizedTools = Array.isArray(tools) ? tools : [];
|
|
5702
7779
|
const result = await doGenerate();
|
|
5703
|
-
let
|
|
7780
|
+
let toolName = "unknown";
|
|
7781
|
+
let input = "{}";
|
|
5704
7782
|
if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
error: error instanceof Error ? error.message : String(error)
|
|
5714
|
-
}
|
|
5715
|
-
);
|
|
5716
|
-
toolJson = {};
|
|
5717
|
-
}
|
|
7783
|
+
const parsed = parseToolChoicePayload({
|
|
7784
|
+
text: result.content[0].text,
|
|
7785
|
+
tools: normalizedTools,
|
|
7786
|
+
onError: options == null ? void 0 : options.onError,
|
|
7787
|
+
errorMessage: "Failed to parse toolChoice JSON from streamed model output"
|
|
7788
|
+
});
|
|
7789
|
+
toolName = parsed.toolName;
|
|
7790
|
+
input = parsed.input;
|
|
5718
7791
|
}
|
|
5719
7792
|
const stream = new ReadableStream({
|
|
5720
7793
|
start(controller) {
|
|
5721
7794
|
controller.enqueue({
|
|
5722
7795
|
type: "tool-call",
|
|
5723
|
-
toolCallId: (
|
|
5724
|
-
toolName
|
|
5725
|
-
input
|
|
7796
|
+
toolCallId: generateToolCallId(),
|
|
7797
|
+
toolName,
|
|
7798
|
+
input
|
|
5726
7799
|
});
|
|
5727
7800
|
controller.enqueue({
|
|
5728
7801
|
type: "finish",
|
|
5729
|
-
usage: (result == null ? void 0 : result.usage)
|
|
5730
|
-
|
|
5731
|
-
outputTokens: 0
|
|
5732
|
-
},
|
|
5733
|
-
finishReason: "tool-calls"
|
|
7802
|
+
usage: normalizeUsage(result == null ? void 0 : result.usage),
|
|
7803
|
+
finishReason: normalizeToolCallsFinishReason(result == null ? void 0 : result.finishReason)
|
|
5734
7804
|
});
|
|
5735
7805
|
controller.close();
|
|
5736
7806
|
}
|
|
@@ -5741,6 +7811,60 @@ async function toolChoiceStream({
|
|
|
5741
7811
|
stream
|
|
5742
7812
|
};
|
|
5743
7813
|
}
|
|
7814
|
+
var ZERO_USAGE = {
|
|
7815
|
+
inputTokens: {
|
|
7816
|
+
total: 0,
|
|
7817
|
+
noCache: void 0,
|
|
7818
|
+
cacheRead: void 0,
|
|
7819
|
+
cacheWrite: void 0
|
|
7820
|
+
},
|
|
7821
|
+
outputTokens: {
|
|
7822
|
+
total: 0,
|
|
7823
|
+
text: void 0,
|
|
7824
|
+
reasoning: void 0
|
|
7825
|
+
}
|
|
7826
|
+
};
|
|
7827
|
+
function normalizeToolCallsFinishReason(finishReason) {
|
|
7828
|
+
let raw = "tool-calls";
|
|
7829
|
+
if (typeof finishReason === "string") {
|
|
7830
|
+
raw = finishReason;
|
|
7831
|
+
} else if (finishReason && typeof finishReason === "object" && "raw" in finishReason && typeof finishReason.raw === "string") {
|
|
7832
|
+
raw = finishReason.raw;
|
|
7833
|
+
} else if (finishReason && typeof finishReason === "object" && "unified" in finishReason && typeof finishReason.unified === "string") {
|
|
7834
|
+
raw = finishReason.unified;
|
|
7835
|
+
}
|
|
7836
|
+
return {
|
|
7837
|
+
unified: "tool-calls",
|
|
7838
|
+
raw
|
|
7839
|
+
};
|
|
7840
|
+
}
|
|
7841
|
+
function normalizeUsage(usage) {
|
|
7842
|
+
if (!usage || typeof usage !== "object") {
|
|
7843
|
+
return ZERO_USAGE;
|
|
7844
|
+
}
|
|
7845
|
+
const usageRecord = usage;
|
|
7846
|
+
const input = usageRecord.inputTokens;
|
|
7847
|
+
const output = usageRecord.outputTokens;
|
|
7848
|
+
if (input && typeof input === "object" && output && typeof output === "object") {
|
|
7849
|
+
return usage;
|
|
7850
|
+
}
|
|
7851
|
+
if (typeof input === "number" && typeof output === "number") {
|
|
7852
|
+
return {
|
|
7853
|
+
inputTokens: {
|
|
7854
|
+
total: input,
|
|
7855
|
+
noCache: void 0,
|
|
7856
|
+
cacheRead: void 0,
|
|
7857
|
+
cacheWrite: void 0
|
|
7858
|
+
},
|
|
7859
|
+
outputTokens: {
|
|
7860
|
+
total: output,
|
|
7861
|
+
text: void 0,
|
|
7862
|
+
reasoning: void 0
|
|
7863
|
+
}
|
|
7864
|
+
};
|
|
7865
|
+
}
|
|
7866
|
+
return ZERO_USAGE;
|
|
7867
|
+
}
|
|
5744
7868
|
|
|
5745
7869
|
// src/transform-handler.ts
|
|
5746
7870
|
function buildFinalPrompt(systemPrompt, processedPrompt, placement) {
|
|
@@ -5866,6 +7990,11 @@ function handleToolChoiceRequired(params, baseReturnParams, functionTools) {
|
|
|
5866
7990
|
"Tool choice type 'required' is set, but no tools are provided in params.tools."
|
|
5867
7991
|
);
|
|
5868
7992
|
}
|
|
7993
|
+
if (functionTools.length === 0) {
|
|
7994
|
+
throw new Error(
|
|
7995
|
+
"Tool choice type 'required' is set, but no function tools are provided. Provider-defined tools are not supported by this middleware."
|
|
7996
|
+
);
|
|
7997
|
+
}
|
|
5869
7998
|
return {
|
|
5870
7999
|
...baseReturnParams,
|
|
5871
8000
|
responseFormat: {
|