@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/community.cjs
CHANGED
|
@@ -847,7 +847,25 @@ function getPotentialStartIndex(text, searchedText) {
|
|
|
847
847
|
|
|
848
848
|
// src/core/utils/id.ts
|
|
849
849
|
function generateId() {
|
|
850
|
-
return
|
|
850
|
+
return crypto.randomUUID().replace(/-/g, "").slice(0, 13);
|
|
851
|
+
}
|
|
852
|
+
var TOOL_CALL_ID_PREFIX = "call_";
|
|
853
|
+
var TOOL_CALL_ID_BODY_LENGTH = 24;
|
|
854
|
+
var TOOL_CALL_ID_ALPHANUM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
855
|
+
function randomAlphaNumeric(length) {
|
|
856
|
+
var _a;
|
|
857
|
+
const bytes = new Uint8Array(length);
|
|
858
|
+
crypto.getRandomValues(bytes);
|
|
859
|
+
let out = "";
|
|
860
|
+
for (let i = 0; i < length; i += 1) {
|
|
861
|
+
const byte = bytes[i];
|
|
862
|
+
const index = (byte != null ? byte : 0) % TOOL_CALL_ID_ALPHANUM.length;
|
|
863
|
+
out += (_a = TOOL_CALL_ID_ALPHANUM[index]) != null ? _a : "0";
|
|
864
|
+
}
|
|
865
|
+
return out;
|
|
866
|
+
}
|
|
867
|
+
function generateToolCallId() {
|
|
868
|
+
return `${TOOL_CALL_ID_PREFIX}${randomAlphaNumeric(TOOL_CALL_ID_BODY_LENGTH)}`;
|
|
851
869
|
}
|
|
852
870
|
|
|
853
871
|
// src/core/utils/protocol-utils.ts
|
|
@@ -856,6 +874,38 @@ function addTextSegment(text, processedElements) {
|
|
|
856
874
|
processedElements.push({ type: "text", text });
|
|
857
875
|
}
|
|
858
876
|
}
|
|
877
|
+
function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
878
|
+
return (controller, text) => {
|
|
879
|
+
const content = text;
|
|
880
|
+
if (content) {
|
|
881
|
+
if (!getCurrentTextId()) {
|
|
882
|
+
const newId = generateId();
|
|
883
|
+
setCurrentTextId(newId);
|
|
884
|
+
controller.enqueue({
|
|
885
|
+
type: "text-start",
|
|
886
|
+
id: newId
|
|
887
|
+
});
|
|
888
|
+
setHasEmittedTextStart(true);
|
|
889
|
+
}
|
|
890
|
+
controller.enqueue({
|
|
891
|
+
type: "text-delta",
|
|
892
|
+
id: getCurrentTextId(),
|
|
893
|
+
delta: content
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
const currentTextId = getCurrentTextId();
|
|
897
|
+
if (currentTextId && !text) {
|
|
898
|
+
if (getHasEmittedTextStart()) {
|
|
899
|
+
controller.enqueue({
|
|
900
|
+
type: "text-end",
|
|
901
|
+
id: currentTextId
|
|
902
|
+
});
|
|
903
|
+
setHasEmittedTextStart(false);
|
|
904
|
+
}
|
|
905
|
+
setCurrentTextId(null);
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
}
|
|
859
909
|
|
|
860
910
|
// src/core/utils/regex.ts
|
|
861
911
|
function escapeRegExp(literal) {
|
|
@@ -863,15 +913,21 @@ function escapeRegExp(literal) {
|
|
|
863
913
|
}
|
|
864
914
|
|
|
865
915
|
// src/core/protocols/json-protocol.ts
|
|
916
|
+
function shouldEmitRawToolCallTextOnError(options) {
|
|
917
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
918
|
+
}
|
|
919
|
+
function canonicalizeToolInput(argumentsValue) {
|
|
920
|
+
return JSON.stringify(argumentsValue != null ? argumentsValue : {});
|
|
921
|
+
}
|
|
866
922
|
function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
|
|
867
|
-
var _a
|
|
923
|
+
var _a;
|
|
868
924
|
try {
|
|
869
925
|
const parsedToolCall = parse(toolCallJson);
|
|
870
926
|
processedElements.push({
|
|
871
927
|
type: "tool-call",
|
|
872
|
-
toolCallId:
|
|
928
|
+
toolCallId: generateToolCallId(),
|
|
873
929
|
toolName: parsedToolCall.name,
|
|
874
|
-
input:
|
|
930
|
+
input: canonicalizeToolInput(parsedToolCall.arguments)
|
|
875
931
|
});
|
|
876
932
|
} catch (error) {
|
|
877
933
|
logParseFailure({
|
|
@@ -880,7 +936,7 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
|
|
|
880
936
|
snippet: fullMatch,
|
|
881
937
|
error
|
|
882
938
|
});
|
|
883
|
-
(
|
|
939
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
884
940
|
options,
|
|
885
941
|
"Could not process JSON tool call, keeping original text.",
|
|
886
942
|
{ toolCall: fullMatch, error }
|
|
@@ -901,6 +957,293 @@ function processMatchedToolCall(context) {
|
|
|
901
957
|
}
|
|
902
958
|
return startIndex + match[0].length;
|
|
903
959
|
}
|
|
960
|
+
var WHITESPACE_JSON_REGEX = /\s/;
|
|
961
|
+
function skipJsonWhitespace(text, fromIndex) {
|
|
962
|
+
let index = fromIndex;
|
|
963
|
+
while (index < text.length && WHITESPACE_JSON_REGEX.test(text[index])) {
|
|
964
|
+
index += 1;
|
|
965
|
+
}
|
|
966
|
+
return index;
|
|
967
|
+
}
|
|
968
|
+
function findTopLevelPropertyValueStart(text, property) {
|
|
969
|
+
const objectStart = skipJsonWhitespace(text, 0);
|
|
970
|
+
if (objectStart >= text.length || text.charAt(objectStart) !== "{") {
|
|
971
|
+
return null;
|
|
972
|
+
}
|
|
973
|
+
let depth = 0;
|
|
974
|
+
let inString = false;
|
|
975
|
+
let escaping = false;
|
|
976
|
+
for (let index = objectStart; index < text.length; index += 1) {
|
|
977
|
+
const char = text.charAt(index);
|
|
978
|
+
if (inString) {
|
|
979
|
+
if (escaping) {
|
|
980
|
+
escaping = false;
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
if (char === "\\") {
|
|
984
|
+
escaping = true;
|
|
985
|
+
continue;
|
|
986
|
+
}
|
|
987
|
+
if (char === '"') {
|
|
988
|
+
inString = false;
|
|
989
|
+
}
|
|
990
|
+
continue;
|
|
991
|
+
}
|
|
992
|
+
if (char === "{") {
|
|
993
|
+
depth += 1;
|
|
994
|
+
continue;
|
|
995
|
+
}
|
|
996
|
+
if (char === "}") {
|
|
997
|
+
depth = Math.max(0, depth - 1);
|
|
998
|
+
continue;
|
|
999
|
+
}
|
|
1000
|
+
if (char !== '"') {
|
|
1001
|
+
continue;
|
|
1002
|
+
}
|
|
1003
|
+
if (depth !== 1) {
|
|
1004
|
+
inString = true;
|
|
1005
|
+
continue;
|
|
1006
|
+
}
|
|
1007
|
+
const keyStart = index + 1;
|
|
1008
|
+
let keyEnd = keyStart;
|
|
1009
|
+
let keyEscaped = false;
|
|
1010
|
+
while (keyEnd < text.length) {
|
|
1011
|
+
const keyChar = text.charAt(keyEnd);
|
|
1012
|
+
if (keyEscaped) {
|
|
1013
|
+
keyEscaped = false;
|
|
1014
|
+
} else if (keyChar === "\\") {
|
|
1015
|
+
keyEscaped = true;
|
|
1016
|
+
} else if (keyChar === '"') {
|
|
1017
|
+
break;
|
|
1018
|
+
}
|
|
1019
|
+
keyEnd += 1;
|
|
1020
|
+
}
|
|
1021
|
+
if (keyEnd >= text.length || text.charAt(keyEnd) !== '"') {
|
|
1022
|
+
return null;
|
|
1023
|
+
}
|
|
1024
|
+
const key = text.slice(keyStart, keyEnd);
|
|
1025
|
+
let valueCursor = skipJsonWhitespace(text, keyEnd + 1);
|
|
1026
|
+
if (valueCursor >= text.length || text.charAt(valueCursor) !== ":") {
|
|
1027
|
+
index = keyEnd;
|
|
1028
|
+
continue;
|
|
1029
|
+
}
|
|
1030
|
+
valueCursor = skipJsonWhitespace(text, valueCursor + 1);
|
|
1031
|
+
if (key === property) {
|
|
1032
|
+
return valueCursor < text.length ? valueCursor : null;
|
|
1033
|
+
}
|
|
1034
|
+
index = valueCursor - 1;
|
|
1035
|
+
}
|
|
1036
|
+
return null;
|
|
1037
|
+
}
|
|
1038
|
+
function extractTopLevelStringProperty(text, property) {
|
|
1039
|
+
const valueStart = findTopLevelPropertyValueStart(text, property);
|
|
1040
|
+
if (valueStart == null || valueStart >= text.length) {
|
|
1041
|
+
return void 0;
|
|
1042
|
+
}
|
|
1043
|
+
if (text.charAt(valueStart) !== '"') {
|
|
1044
|
+
return void 0;
|
|
1045
|
+
}
|
|
1046
|
+
let valueEnd = valueStart + 1;
|
|
1047
|
+
let escaped = false;
|
|
1048
|
+
while (valueEnd < text.length) {
|
|
1049
|
+
const char = text.charAt(valueEnd);
|
|
1050
|
+
if (escaped) {
|
|
1051
|
+
escaped = false;
|
|
1052
|
+
} else if (char === "\\") {
|
|
1053
|
+
escaped = true;
|
|
1054
|
+
} else if (char === '"') {
|
|
1055
|
+
return text.slice(valueStart + 1, valueEnd);
|
|
1056
|
+
}
|
|
1057
|
+
valueEnd += 1;
|
|
1058
|
+
}
|
|
1059
|
+
return void 0;
|
|
1060
|
+
}
|
|
1061
|
+
function extractJsonValueSlice(text, valueStart) {
|
|
1062
|
+
if (valueStart >= text.length) {
|
|
1063
|
+
return null;
|
|
1064
|
+
}
|
|
1065
|
+
const first = text.charAt(valueStart);
|
|
1066
|
+
if (first === "{" || first === "[") {
|
|
1067
|
+
const stack = [first];
|
|
1068
|
+
let inString = false;
|
|
1069
|
+
let escaped = false;
|
|
1070
|
+
for (let index2 = valueStart + 1; index2 < text.length; index2 += 1) {
|
|
1071
|
+
const char = text.charAt(index2);
|
|
1072
|
+
if (inString) {
|
|
1073
|
+
if (escaped) {
|
|
1074
|
+
escaped = false;
|
|
1075
|
+
} else if (char === "\\") {
|
|
1076
|
+
escaped = true;
|
|
1077
|
+
} else if (char === '"') {
|
|
1078
|
+
inString = false;
|
|
1079
|
+
}
|
|
1080
|
+
continue;
|
|
1081
|
+
}
|
|
1082
|
+
if (char === '"') {
|
|
1083
|
+
inString = true;
|
|
1084
|
+
continue;
|
|
1085
|
+
}
|
|
1086
|
+
if (char === "{" || char === "[") {
|
|
1087
|
+
stack.push(char);
|
|
1088
|
+
continue;
|
|
1089
|
+
}
|
|
1090
|
+
if (char === "}" || char === "]") {
|
|
1091
|
+
const open = stack.at(-1);
|
|
1092
|
+
if (open === "{" && char === "}" || open === "[" && char === "]") {
|
|
1093
|
+
stack.pop();
|
|
1094
|
+
if (stack.length === 0) {
|
|
1095
|
+
return {
|
|
1096
|
+
text: text.slice(valueStart, index2 + 1),
|
|
1097
|
+
complete: true
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
return {
|
|
1104
|
+
text: text.slice(valueStart),
|
|
1105
|
+
complete: false
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
if (first === '"') {
|
|
1109
|
+
let escaped = false;
|
|
1110
|
+
for (let index2 = valueStart + 1; index2 < text.length; index2 += 1) {
|
|
1111
|
+
const char = text.charAt(index2);
|
|
1112
|
+
if (escaped) {
|
|
1113
|
+
escaped = false;
|
|
1114
|
+
} else if (char === "\\") {
|
|
1115
|
+
escaped = true;
|
|
1116
|
+
} else if (char === '"') {
|
|
1117
|
+
return {
|
|
1118
|
+
text: text.slice(valueStart, index2 + 1),
|
|
1119
|
+
complete: true
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
return {
|
|
1124
|
+
text: text.slice(valueStart),
|
|
1125
|
+
complete: false
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
let index = valueStart;
|
|
1129
|
+
while (index < text.length) {
|
|
1130
|
+
const char = text.charAt(index);
|
|
1131
|
+
if (char === "," || char === "}" || WHITESPACE_JSON_REGEX.test(char)) {
|
|
1132
|
+
break;
|
|
1133
|
+
}
|
|
1134
|
+
index += 1;
|
|
1135
|
+
}
|
|
1136
|
+
return {
|
|
1137
|
+
text: text.slice(valueStart, index),
|
|
1138
|
+
complete: index < text.length
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
function extractStreamingToolCallProgress(toolCallJson) {
|
|
1142
|
+
var _a;
|
|
1143
|
+
const toolName = extractTopLevelStringProperty(toolCallJson, "name");
|
|
1144
|
+
const argsValueStart = findTopLevelPropertyValueStart(
|
|
1145
|
+
toolCallJson,
|
|
1146
|
+
"arguments"
|
|
1147
|
+
);
|
|
1148
|
+
if (argsValueStart == null) {
|
|
1149
|
+
return {
|
|
1150
|
+
toolName,
|
|
1151
|
+
argumentsText: void 0,
|
|
1152
|
+
argumentsComplete: false
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
const argsSlice = extractJsonValueSlice(toolCallJson, argsValueStart);
|
|
1156
|
+
return {
|
|
1157
|
+
toolName,
|
|
1158
|
+
argumentsText: argsSlice == null ? void 0 : argsSlice.text,
|
|
1159
|
+
argumentsComplete: (_a = argsSlice == null ? void 0 : argsSlice.complete) != null ? _a : false
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
function ensureToolInputStart(state, controller, toolName) {
|
|
1163
|
+
if (!state.activeToolInput) {
|
|
1164
|
+
const id = generateToolCallId();
|
|
1165
|
+
state.activeToolInput = {
|
|
1166
|
+
id,
|
|
1167
|
+
toolName,
|
|
1168
|
+
emittedInput: ""
|
|
1169
|
+
};
|
|
1170
|
+
controller.enqueue({
|
|
1171
|
+
type: "tool-input-start",
|
|
1172
|
+
id,
|
|
1173
|
+
toolName
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
function emitToolInputDelta(state, controller, fullInput) {
|
|
1178
|
+
const active = state.activeToolInput;
|
|
1179
|
+
if (!active) {
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
if (!fullInput.startsWith(active.emittedInput)) {
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
1185
|
+
const delta = fullInput.slice(active.emittedInput.length);
|
|
1186
|
+
if (delta.length === 0) {
|
|
1187
|
+
return;
|
|
1188
|
+
}
|
|
1189
|
+
controller.enqueue({
|
|
1190
|
+
type: "tool-input-delta",
|
|
1191
|
+
id: active.id,
|
|
1192
|
+
delta
|
|
1193
|
+
});
|
|
1194
|
+
active.emittedInput = fullInput;
|
|
1195
|
+
}
|
|
1196
|
+
function closeToolInput(state, controller) {
|
|
1197
|
+
if (!state.activeToolInput) {
|
|
1198
|
+
return;
|
|
1199
|
+
}
|
|
1200
|
+
controller.enqueue({
|
|
1201
|
+
type: "tool-input-end",
|
|
1202
|
+
id: state.activeToolInput.id
|
|
1203
|
+
});
|
|
1204
|
+
state.activeToolInput = null;
|
|
1205
|
+
}
|
|
1206
|
+
function emitToolCallFromParsed(state, controller, parsedToolCall) {
|
|
1207
|
+
var _a, _b, _c, _d;
|
|
1208
|
+
closeTextBlock(state, controller);
|
|
1209
|
+
const toolName = typeof parsedToolCall.name === "string" ? parsedToolCall.name : (_b = (_a = state.activeToolInput) == null ? void 0 : _a.toolName) != null ? _b : "unknown";
|
|
1210
|
+
const input = canonicalizeToolInput(parsedToolCall.arguments);
|
|
1211
|
+
ensureToolInputStart(state, controller, toolName);
|
|
1212
|
+
emitToolInputDelta(state, controller, input);
|
|
1213
|
+
const toolCallId = (_d = (_c = state.activeToolInput) == null ? void 0 : _c.id) != null ? _d : generateToolCallId();
|
|
1214
|
+
closeToolInput(state, controller);
|
|
1215
|
+
controller.enqueue({
|
|
1216
|
+
type: "tool-call",
|
|
1217
|
+
toolCallId,
|
|
1218
|
+
toolName,
|
|
1219
|
+
input
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
function canonicalizeArgumentsProgressInput(progress) {
|
|
1223
|
+
if (progress.argumentsText === void 0 || !progress.argumentsComplete) {
|
|
1224
|
+
return void 0;
|
|
1225
|
+
}
|
|
1226
|
+
try {
|
|
1227
|
+
const parsedArguments = parse(progress.argumentsText);
|
|
1228
|
+
return canonicalizeToolInput(parsedArguments);
|
|
1229
|
+
} catch (e) {
|
|
1230
|
+
return void 0;
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
function emitToolInputProgress(state, controller) {
|
|
1234
|
+
if (!(state.isInsideToolCall && state.currentToolCallJson)) {
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
const progress = extractStreamingToolCallProgress(state.currentToolCallJson);
|
|
1238
|
+
if (!progress.toolName) {
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
ensureToolInputStart(state, controller, progress.toolName);
|
|
1242
|
+
const canonicalProgressInput = canonicalizeArgumentsProgressInput(progress);
|
|
1243
|
+
if (canonicalProgressInput !== void 0) {
|
|
1244
|
+
emitToolInputDelta(state, controller, canonicalProgressInput);
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
904
1247
|
function flushBuffer(state, controller, toolCallStart) {
|
|
905
1248
|
if (state.buffer.length === 0) {
|
|
906
1249
|
return;
|
|
@@ -931,44 +1274,77 @@ function closeTextBlock(state, controller) {
|
|
|
931
1274
|
state.hasEmittedTextStart = false;
|
|
932
1275
|
}
|
|
933
1276
|
}
|
|
934
|
-
function emitIncompleteToolCall(state, controller, toolCallStart) {
|
|
935
|
-
|
|
1277
|
+
function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer, options) {
|
|
1278
|
+
var _a;
|
|
1279
|
+
if (!state.currentToolCallJson && trailingBuffer.length === 0) {
|
|
1280
|
+
state.isInsideToolCall = false;
|
|
936
1281
|
return;
|
|
937
1282
|
}
|
|
1283
|
+
if (state.currentToolCallJson) {
|
|
1284
|
+
try {
|
|
1285
|
+
const parsedToolCall = parse(state.currentToolCallJson);
|
|
1286
|
+
emitToolCallFromParsed(state, controller, parsedToolCall);
|
|
1287
|
+
state.currentToolCallJson = "";
|
|
1288
|
+
state.isInsideToolCall = false;
|
|
1289
|
+
return;
|
|
1290
|
+
} catch (e) {
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
const rawToolCallContent = `${state.currentToolCallJson}${trailingBuffer}`;
|
|
1294
|
+
const errorContent = `${toolCallStart}${rawToolCallContent}`;
|
|
1295
|
+
const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
|
|
938
1296
|
logParseFailure({
|
|
939
1297
|
phase: "stream",
|
|
940
|
-
reason: "Incomplete streaming tool call segment emitted as text",
|
|
941
|
-
snippet:
|
|
942
|
-
});
|
|
943
|
-
const errorId = generateId();
|
|
944
|
-
const errorContent = `${toolCallStart}${state.currentToolCallJson}`;
|
|
945
|
-
controller.enqueue({
|
|
946
|
-
type: "text-start",
|
|
947
|
-
id: errorId
|
|
948
|
-
});
|
|
949
|
-
controller.enqueue({
|
|
950
|
-
type: "text-delta",
|
|
951
|
-
id: errorId,
|
|
952
|
-
delta: errorContent
|
|
953
|
-
});
|
|
954
|
-
controller.enqueue({
|
|
955
|
-
type: "text-end",
|
|
956
|
-
id: errorId
|
|
1298
|
+
reason: shouldEmitRawFallback ? "Incomplete streaming tool call segment emitted as text" : "Incomplete streaming tool call segment suppressed without raw text fallback",
|
|
1299
|
+
snippet: errorContent
|
|
957
1300
|
});
|
|
1301
|
+
if (shouldEmitRawFallback) {
|
|
1302
|
+
const errorId = generateId();
|
|
1303
|
+
controller.enqueue({
|
|
1304
|
+
type: "text-start",
|
|
1305
|
+
id: errorId
|
|
1306
|
+
});
|
|
1307
|
+
controller.enqueue({
|
|
1308
|
+
type: "text-delta",
|
|
1309
|
+
id: errorId,
|
|
1310
|
+
delta: errorContent
|
|
1311
|
+
});
|
|
1312
|
+
controller.enqueue({
|
|
1313
|
+
type: "text-end",
|
|
1314
|
+
id: errorId
|
|
1315
|
+
});
|
|
1316
|
+
}
|
|
1317
|
+
closeToolInput(state, controller);
|
|
1318
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1319
|
+
options,
|
|
1320
|
+
shouldEmitRawFallback ? "Could not complete streaming JSON tool call at finish; emitting original text." : "Could not complete streaming JSON tool call at finish.",
|
|
1321
|
+
{ toolCall: errorContent }
|
|
1322
|
+
);
|
|
958
1323
|
state.currentToolCallJson = "";
|
|
1324
|
+
state.isInsideToolCall = false;
|
|
959
1325
|
}
|
|
960
|
-
function handleFinishChunk(state, controller, toolCallStart, chunk) {
|
|
961
|
-
if (state.
|
|
1326
|
+
function handleFinishChunk(state, controller, toolCallStart, options, chunk) {
|
|
1327
|
+
if (state.isInsideToolCall) {
|
|
1328
|
+
const trailingBuffer = state.buffer;
|
|
1329
|
+
state.buffer = "";
|
|
1330
|
+
emitIncompleteToolCall(
|
|
1331
|
+
state,
|
|
1332
|
+
controller,
|
|
1333
|
+
toolCallStart,
|
|
1334
|
+
trailingBuffer,
|
|
1335
|
+
options
|
|
1336
|
+
);
|
|
1337
|
+
} else if (state.buffer.length > 0) {
|
|
962
1338
|
flushBuffer(state, controller, toolCallStart);
|
|
963
1339
|
}
|
|
964
1340
|
closeTextBlock(state, controller);
|
|
965
|
-
emitIncompleteToolCall(state, controller, toolCallStart);
|
|
966
1341
|
controller.enqueue(chunk);
|
|
967
1342
|
}
|
|
968
1343
|
function publishText(text, state, controller) {
|
|
969
1344
|
if (state.isInsideToolCall) {
|
|
970
1345
|
closeTextBlock(state, controller);
|
|
971
1346
|
state.currentToolCallJson += text;
|
|
1347
|
+
emitToolInputProgress(state, controller);
|
|
972
1348
|
} else if (text.length > 0) {
|
|
973
1349
|
if (!state.currentTextId) {
|
|
974
1350
|
state.currentTextId = generateId();
|
|
@@ -986,42 +1362,40 @@ function publishText(text, state, controller) {
|
|
|
986
1362
|
}
|
|
987
1363
|
}
|
|
988
1364
|
function emitToolCall(context) {
|
|
989
|
-
var _a
|
|
1365
|
+
var _a;
|
|
990
1366
|
const { state, controller, toolCallStart, toolCallEnd, options } = context;
|
|
991
1367
|
try {
|
|
992
1368
|
const parsedToolCall = parse(state.currentToolCallJson);
|
|
993
|
-
|
|
994
|
-
controller.enqueue({
|
|
995
|
-
type: "tool-call",
|
|
996
|
-
toolCallId: generateId(),
|
|
997
|
-
toolName: parsedToolCall.name,
|
|
998
|
-
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
999
|
-
});
|
|
1369
|
+
emitToolCallFromParsed(state, controller, parsedToolCall);
|
|
1000
1370
|
} catch (error) {
|
|
1371
|
+
const errorContent = `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`;
|
|
1372
|
+
const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
|
|
1001
1373
|
logParseFailure({
|
|
1002
1374
|
phase: "stream",
|
|
1003
1375
|
reason: "Failed to parse streaming tool call JSON segment",
|
|
1004
|
-
snippet:
|
|
1376
|
+
snippet: errorContent,
|
|
1005
1377
|
error
|
|
1006
1378
|
});
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1379
|
+
if (shouldEmitRawFallback) {
|
|
1380
|
+
const errorId = generateId();
|
|
1381
|
+
controller.enqueue({
|
|
1382
|
+
type: "text-start",
|
|
1383
|
+
id: errorId
|
|
1384
|
+
});
|
|
1385
|
+
controller.enqueue({
|
|
1386
|
+
type: "text-delta",
|
|
1387
|
+
id: errorId,
|
|
1388
|
+
delta: errorContent
|
|
1389
|
+
});
|
|
1390
|
+
controller.enqueue({
|
|
1391
|
+
type: "text-end",
|
|
1392
|
+
id: errorId
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
closeToolInput(state, controller);
|
|
1396
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1023
1397
|
options,
|
|
1024
|
-
"Could not process streaming JSON tool call; emitting original text.",
|
|
1398
|
+
shouldEmitRawFallback ? "Could not process streaming JSON tool call; emitting original text." : "Could not process streaming JSON tool call.",
|
|
1025
1399
|
{
|
|
1026
1400
|
toolCall: errorContent
|
|
1027
1401
|
}
|
|
@@ -1037,6 +1411,7 @@ function processTagMatch(context) {
|
|
|
1037
1411
|
} else {
|
|
1038
1412
|
state.currentToolCallJson = "";
|
|
1039
1413
|
state.isInsideToolCall = true;
|
|
1414
|
+
state.activeToolInput = null;
|
|
1040
1415
|
}
|
|
1041
1416
|
}
|
|
1042
1417
|
function processBufferTags(context) {
|
|
@@ -1059,8 +1434,16 @@ function processBufferTags(context) {
|
|
|
1059
1434
|
);
|
|
1060
1435
|
}
|
|
1061
1436
|
}
|
|
1062
|
-
function handlePartialTag(state, controller, toolCallStart) {
|
|
1437
|
+
function handlePartialTag(state, controller, toolCallStart, toolCallEnd) {
|
|
1063
1438
|
if (state.isInsideToolCall) {
|
|
1439
|
+
const potentialEndIndex = getPotentialStartIndex(state.buffer, toolCallEnd);
|
|
1440
|
+
if (potentialEndIndex != null && potentialEndIndex + toolCallEnd.length > state.buffer.length) {
|
|
1441
|
+
publishText(state.buffer.slice(0, potentialEndIndex), state, controller);
|
|
1442
|
+
state.buffer = state.buffer.slice(potentialEndIndex);
|
|
1443
|
+
} else {
|
|
1444
|
+
publishText(state.buffer, state, controller);
|
|
1445
|
+
state.buffer = "";
|
|
1446
|
+
}
|
|
1064
1447
|
return;
|
|
1065
1448
|
}
|
|
1066
1449
|
const potentialIndex = getPotentialStartIndex(state.buffer, toolCallStart);
|
|
@@ -1133,13 +1516,14 @@ var jsonProtocol = ({
|
|
|
1133
1516
|
buffer: "",
|
|
1134
1517
|
currentToolCallJson: "",
|
|
1135
1518
|
currentTextId: null,
|
|
1136
|
-
hasEmittedTextStart: false
|
|
1519
|
+
hasEmittedTextStart: false,
|
|
1520
|
+
activeToolInput: null
|
|
1137
1521
|
};
|
|
1138
1522
|
return new TransformStream({
|
|
1139
1523
|
transform(chunk, controller) {
|
|
1140
1524
|
var _a;
|
|
1141
1525
|
if (chunk.type === "finish") {
|
|
1142
|
-
handleFinishChunk(state, controller, toolCallStart, chunk);
|
|
1526
|
+
handleFinishChunk(state, controller, toolCallStart, options, chunk);
|
|
1143
1527
|
return;
|
|
1144
1528
|
}
|
|
1145
1529
|
if (chunk.type !== "text-delta") {
|
|
@@ -1155,7 +1539,7 @@ var jsonProtocol = ({
|
|
|
1155
1539
|
toolCallEnd,
|
|
1156
1540
|
options
|
|
1157
1541
|
});
|
|
1158
|
-
handlePartialTag(state, controller, toolCallStart);
|
|
1542
|
+
handlePartialTag(state, controller, toolCallStart, toolCallEnd);
|
|
1159
1543
|
}
|
|
1160
1544
|
});
|
|
1161
1545
|
},
|
|
@@ -1516,6 +1900,13 @@ var EMPTY_OBJECT_REGEX = /^\{\s*\}$/s;
|
|
|
1516
1900
|
var NEWLINE_SPLIT_REGEX = /\n+/;
|
|
1517
1901
|
var COMMA_SPLIT_REGEX = /,\s*/;
|
|
1518
1902
|
var DIGIT_KEY_REGEX = /^\d+$/;
|
|
1903
|
+
var WHITESPACE_REGEX2 = /\s+/g;
|
|
1904
|
+
var HAS_WHITESPACE_REGEX = /\s/;
|
|
1905
|
+
var SINGLE_QUOTE = "'";
|
|
1906
|
+
var DOUBLE_QUOTE = '"';
|
|
1907
|
+
var SNAKE_SEGMENT_REGEX = /_([a-zA-Z0-9])/g;
|
|
1908
|
+
var CAMEL_BOUNDARY_REGEX = /([a-z0-9])([A-Z])/g;
|
|
1909
|
+
var LEADING_UNDERSCORES_REGEX = /^_+/;
|
|
1519
1910
|
function unwrapJsonSchema(schema) {
|
|
1520
1911
|
if (!schema || typeof schema !== "object") {
|
|
1521
1912
|
return schema;
|
|
@@ -1764,39 +2155,299 @@ function coerceStringToArray(s, unwrapped) {
|
|
|
1764
2155
|
}
|
|
1765
2156
|
return null;
|
|
1766
2157
|
}
|
|
1767
|
-
function
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
out[k] = coerceValueForKey(v, k, unwrapped);
|
|
2158
|
+
function getStrictObjectSchemaInfo(unwrapped) {
|
|
2159
|
+
if (getSchemaType(unwrapped) !== "object") {
|
|
2160
|
+
return null;
|
|
1771
2161
|
}
|
|
1772
|
-
|
|
2162
|
+
if (unwrapped.additionalProperties !== false) {
|
|
2163
|
+
return null;
|
|
2164
|
+
}
|
|
2165
|
+
const properties = unwrapped.properties;
|
|
2166
|
+
if (!properties || typeof properties !== "object" || Array.isArray(properties)) {
|
|
2167
|
+
return null;
|
|
2168
|
+
}
|
|
2169
|
+
const propertyMap = properties;
|
|
2170
|
+
const required = Array.isArray(unwrapped.required) ? unwrapped.required.filter(
|
|
2171
|
+
(value) => typeof value === "string" && value.length > 0
|
|
2172
|
+
) : [];
|
|
2173
|
+
const patternProps = unwrapped.patternProperties;
|
|
2174
|
+
const patternProperties = patternProps && typeof patternProps === "object" && !Array.isArray(patternProps) ? patternProps : void 0;
|
|
2175
|
+
return {
|
|
2176
|
+
properties: propertyMap,
|
|
2177
|
+
required,
|
|
2178
|
+
patternProperties
|
|
2179
|
+
};
|
|
1773
2180
|
}
|
|
1774
|
-
function
|
|
1775
|
-
|
|
1776
|
-
|
|
2181
|
+
function isSingularPluralPair(left, right) {
|
|
2182
|
+
return left.length > 1 && right.length > 1 && (left === `${right}s` || right === `${left}s`);
|
|
2183
|
+
}
|
|
2184
|
+
function snakeToCamel(value) {
|
|
2185
|
+
const trimmed = value.replace(LEADING_UNDERSCORES_REGEX, "");
|
|
2186
|
+
if (trimmed.length === 0) {
|
|
2187
|
+
return value;
|
|
1777
2188
|
}
|
|
1778
|
-
|
|
2189
|
+
const camelized = trimmed.replace(
|
|
2190
|
+
SNAKE_SEGMENT_REGEX,
|
|
2191
|
+
(_, c) => c.toUpperCase()
|
|
2192
|
+
);
|
|
2193
|
+
return camelized.charAt(0).toLowerCase() + camelized.slice(1);
|
|
1779
2194
|
}
|
|
1780
|
-
function
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
2195
|
+
function camelToSnake(value) {
|
|
2196
|
+
return value.replace(CAMEL_BOUNDARY_REGEX, "$1_$2").toLowerCase();
|
|
2197
|
+
}
|
|
2198
|
+
function isCaseStylePair(targetKey, sourceKey) {
|
|
2199
|
+
if (targetKey === sourceKey) {
|
|
2200
|
+
return false;
|
|
2201
|
+
}
|
|
2202
|
+
const sourceLooksSnake = sourceKey.includes("_");
|
|
2203
|
+
const targetLooksSnake = targetKey.includes("_");
|
|
2204
|
+
if (sourceLooksSnake && snakeToCamel(sourceKey) === targetKey) {
|
|
2205
|
+
return true;
|
|
2206
|
+
}
|
|
2207
|
+
if (!sourceLooksSnake && targetLooksSnake && camelToSnake(sourceKey) === targetKey) {
|
|
2208
|
+
return true;
|
|
2209
|
+
}
|
|
2210
|
+
return false;
|
|
2211
|
+
}
|
|
2212
|
+
function isUnexpectedKey(key, schemaInfo) {
|
|
2213
|
+
if (Object.hasOwn(schemaInfo.properties, key)) {
|
|
2214
|
+
return false;
|
|
2215
|
+
}
|
|
2216
|
+
const patternSchemas = getPatternSchemasForKey(
|
|
2217
|
+
schemaInfo.patternProperties,
|
|
2218
|
+
key
|
|
2219
|
+
);
|
|
2220
|
+
if (patternSchemas.length > 0) {
|
|
2221
|
+
return patternSchemas.every((schema) => schema === false);
|
|
2222
|
+
}
|
|
2223
|
+
return true;
|
|
2224
|
+
}
|
|
2225
|
+
function computeMissingAndUnexpectedKeys(input, schemaInfo) {
|
|
2226
|
+
const missingRequired = schemaInfo.required.filter(
|
|
2227
|
+
(key) => !Object.hasOwn(input, key)
|
|
2228
|
+
);
|
|
2229
|
+
const unexpectedKeys = Object.keys(input).filter(
|
|
2230
|
+
(key) => isUnexpectedKey(key, schemaInfo)
|
|
2231
|
+
);
|
|
2232
|
+
return { missingRequired, unexpectedKeys };
|
|
2233
|
+
}
|
|
2234
|
+
function applySingularPluralRequiredKeyRename(input, schemaInfo) {
|
|
2235
|
+
const { missingRequired, unexpectedKeys } = computeMissingAndUnexpectedKeys(
|
|
2236
|
+
input,
|
|
2237
|
+
schemaInfo
|
|
2238
|
+
);
|
|
2239
|
+
if (missingRequired.length !== 1 || unexpectedKeys.length !== 1) {
|
|
2240
|
+
return null;
|
|
2241
|
+
}
|
|
2242
|
+
const targetKey = missingRequired[0];
|
|
2243
|
+
const sourceKey = unexpectedKeys[0];
|
|
2244
|
+
if (!Object.hasOwn(schemaInfo.properties, targetKey)) {
|
|
2245
|
+
return null;
|
|
2246
|
+
}
|
|
2247
|
+
if (!isSingularPluralPair(targetKey, sourceKey)) {
|
|
2248
|
+
return null;
|
|
2249
|
+
}
|
|
2250
|
+
if (getSchemaType(schemaInfo.properties[targetKey]) !== "array") {
|
|
2251
|
+
return null;
|
|
2252
|
+
}
|
|
2253
|
+
if (!Array.isArray(input[sourceKey])) {
|
|
2254
|
+
return null;
|
|
2255
|
+
}
|
|
2256
|
+
if (!Object.hasOwn(input, sourceKey) || Object.hasOwn(input, targetKey)) {
|
|
2257
|
+
return null;
|
|
2258
|
+
}
|
|
2259
|
+
const output = { ...input };
|
|
2260
|
+
output[targetKey] = output[sourceKey];
|
|
2261
|
+
delete output[sourceKey];
|
|
2262
|
+
return output;
|
|
2263
|
+
}
|
|
2264
|
+
function applyCaseStyleRequiredKeyRename(input, schemaInfo) {
|
|
2265
|
+
const { missingRequired, unexpectedKeys } = computeMissingAndUnexpectedKeys(
|
|
2266
|
+
input,
|
|
2267
|
+
schemaInfo
|
|
2268
|
+
);
|
|
2269
|
+
if (missingRequired.length !== 1 || unexpectedKeys.length !== 1) {
|
|
2270
|
+
return null;
|
|
2271
|
+
}
|
|
2272
|
+
const targetKey = missingRequired[0];
|
|
2273
|
+
const sourceKey = unexpectedKeys[0];
|
|
2274
|
+
if (!Object.hasOwn(schemaInfo.properties, targetKey)) {
|
|
2275
|
+
return null;
|
|
2276
|
+
}
|
|
2277
|
+
if (!isCaseStylePair(targetKey, sourceKey)) {
|
|
2278
|
+
return null;
|
|
2279
|
+
}
|
|
2280
|
+
if (!Object.hasOwn(input, sourceKey) || Object.hasOwn(input, targetKey)) {
|
|
2281
|
+
return null;
|
|
2282
|
+
}
|
|
2283
|
+
const output = { ...input };
|
|
2284
|
+
output[targetKey] = output[sourceKey];
|
|
2285
|
+
delete output[sourceKey];
|
|
2286
|
+
return output;
|
|
2287
|
+
}
|
|
2288
|
+
function applyStrictRequiredKeyRename(input, unwrapped) {
|
|
2289
|
+
const schemaInfo = getStrictObjectSchemaInfo(unwrapped);
|
|
2290
|
+
if (!schemaInfo) {
|
|
2291
|
+
return input;
|
|
2292
|
+
}
|
|
2293
|
+
const singularPlural = applySingularPluralRequiredKeyRename(
|
|
2294
|
+
input,
|
|
2295
|
+
schemaInfo
|
|
2296
|
+
);
|
|
2297
|
+
if (singularPlural) {
|
|
2298
|
+
return singularPlural;
|
|
2299
|
+
}
|
|
2300
|
+
const caseStyle = applyCaseStyleRequiredKeyRename(input, schemaInfo);
|
|
2301
|
+
if (caseStyle) {
|
|
2302
|
+
return caseStyle;
|
|
2303
|
+
}
|
|
2304
|
+
return input;
|
|
2305
|
+
}
|
|
2306
|
+
function coerceObjectToObject(value, unwrapped) {
|
|
2307
|
+
const normalizedInput = applyStrictRequiredKeyRename(value, unwrapped);
|
|
2308
|
+
const out = {};
|
|
2309
|
+
for (const [k, v] of Object.entries(normalizedInput)) {
|
|
2310
|
+
out[k] = coerceValueForKey(v, k, unwrapped);
|
|
2311
|
+
}
|
|
2312
|
+
return out;
|
|
2313
|
+
}
|
|
2314
|
+
function coerceArrayToArray(value, prefixItems, itemsSchema) {
|
|
2315
|
+
if (prefixItems && value.length === prefixItems.length) {
|
|
2316
|
+
return value.map((v, i) => coerceBySchema(v, prefixItems[i]));
|
|
2317
|
+
}
|
|
2318
|
+
return value.map((v) => coerceBySchema(v, itemsSchema));
|
|
2319
|
+
}
|
|
2320
|
+
function isPrimitiveSchemaType(schemaType) {
|
|
2321
|
+
return schemaType === "string" || schemaType === "number" || schemaType === "integer" || schemaType === "boolean";
|
|
2322
|
+
}
|
|
2323
|
+
function isPrimitiveMatchForSchemaType(value, schemaType) {
|
|
2324
|
+
if (schemaType === "string") {
|
|
2325
|
+
return typeof value === "string";
|
|
2326
|
+
}
|
|
2327
|
+
if (schemaType === "number") {
|
|
2328
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
2329
|
+
}
|
|
2330
|
+
if (schemaType === "integer") {
|
|
2331
|
+
return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value);
|
|
2332
|
+
}
|
|
2333
|
+
return typeof value === "boolean";
|
|
2334
|
+
}
|
|
2335
|
+
function coercePrimitiveWrappedObject(value, itemsSchema) {
|
|
2336
|
+
const schemaType = getSchemaType(itemsSchema);
|
|
2337
|
+
if (!isPrimitiveSchemaType(schemaType)) {
|
|
2338
|
+
return null;
|
|
2339
|
+
}
|
|
2340
|
+
const keys = Object.keys(value);
|
|
2341
|
+
if (keys.length !== 1) {
|
|
2342
|
+
return null;
|
|
2343
|
+
}
|
|
2344
|
+
const singleValue = value[keys[0]];
|
|
2345
|
+
if (singleValue && typeof singleValue === "object") {
|
|
2346
|
+
return null;
|
|
2347
|
+
}
|
|
2348
|
+
const coerced = coerceBySchema(singleValue, itemsSchema);
|
|
2349
|
+
return isPrimitiveMatchForSchemaType(coerced, schemaType) ? coerced : null;
|
|
2350
|
+
}
|
|
2351
|
+
function coerceParallelArraysObjectToArray(maybe, prefixItems, itemsSchema) {
|
|
2352
|
+
if (prefixItems && prefixItems.length > 0) {
|
|
2353
|
+
return null;
|
|
2354
|
+
}
|
|
2355
|
+
const unwrappedItems = unwrapJsonSchema(itemsSchema);
|
|
2356
|
+
if (!unwrappedItems || typeof unwrappedItems !== "object" || Array.isArray(unwrappedItems)) {
|
|
2357
|
+
return null;
|
|
2358
|
+
}
|
|
2359
|
+
const itemSchema = unwrappedItems;
|
|
2360
|
+
if (getSchemaType(itemSchema) !== "object") {
|
|
2361
|
+
return null;
|
|
2362
|
+
}
|
|
2363
|
+
if (itemSchema.additionalProperties !== false) {
|
|
2364
|
+
return null;
|
|
2365
|
+
}
|
|
2366
|
+
const properties = itemSchema.properties;
|
|
2367
|
+
if (!properties || typeof properties !== "object" || Array.isArray(properties)) {
|
|
2368
|
+
return null;
|
|
2369
|
+
}
|
|
2370
|
+
const propertyMap = properties;
|
|
2371
|
+
const entries = Object.entries(maybe);
|
|
2372
|
+
if (entries.length < 2) {
|
|
2373
|
+
return null;
|
|
2374
|
+
}
|
|
2375
|
+
if (!entries.every(([, value]) => Array.isArray(value))) {
|
|
2376
|
+
return null;
|
|
2377
|
+
}
|
|
2378
|
+
if (!entries.every(([key]) => Object.hasOwn(propertyMap, key))) {
|
|
2379
|
+
return null;
|
|
2380
|
+
}
|
|
2381
|
+
if (!entries.every(([key]) => {
|
|
2382
|
+
const schemaType = getSchemaType(propertyMap[key]);
|
|
2383
|
+
return schemaType !== "array" && schemaType !== "object";
|
|
2384
|
+
})) {
|
|
2385
|
+
return null;
|
|
2386
|
+
}
|
|
2387
|
+
const lengths = [
|
|
2388
|
+
...new Set(entries.map(([, value]) => value.length))
|
|
2389
|
+
];
|
|
2390
|
+
if (lengths.length !== 1) {
|
|
2391
|
+
return null;
|
|
2392
|
+
}
|
|
2393
|
+
const length = lengths[0];
|
|
2394
|
+
if (length < 2) {
|
|
2395
|
+
return null;
|
|
2396
|
+
}
|
|
2397
|
+
const zipped = [];
|
|
2398
|
+
for (let index = 0; index < length; index += 1) {
|
|
2399
|
+
const item = {};
|
|
2400
|
+
for (const [key, value] of entries) {
|
|
2401
|
+
item[key] = value[index];
|
|
2402
|
+
}
|
|
2403
|
+
zipped.push(item);
|
|
2404
|
+
}
|
|
2405
|
+
return coerceArrayToArray(zipped, prefixItems, itemsSchema);
|
|
2406
|
+
}
|
|
2407
|
+
function coerceSingleKeyObjectToArray(singleValue, itemsSchema) {
|
|
2408
|
+
if (Array.isArray(singleValue)) {
|
|
2409
|
+
return singleValue.map((v) => coerceBySchema(v, itemsSchema));
|
|
2410
|
+
}
|
|
2411
|
+
if (singleValue && typeof singleValue === "object") {
|
|
2412
|
+
const primitiveWrapped = coercePrimitiveWrappedObject(
|
|
2413
|
+
singleValue,
|
|
2414
|
+
itemsSchema
|
|
2415
|
+
);
|
|
2416
|
+
if (primitiveWrapped !== null) {
|
|
2417
|
+
return [primitiveWrapped];
|
|
2418
|
+
}
|
|
2419
|
+
return [coerceBySchema(singleValue, itemsSchema)];
|
|
2420
|
+
}
|
|
2421
|
+
return null;
|
|
2422
|
+
}
|
|
2423
|
+
function coerceObjectToArray(maybe, prefixItems, itemsSchema) {
|
|
2424
|
+
if (Object.hasOwn(maybe, "item")) {
|
|
2425
|
+
const items = maybe.item;
|
|
2426
|
+
const arr = Array.isArray(items) ? items : [items];
|
|
2427
|
+
return coerceArrayToArray(arr, prefixItems, itemsSchema);
|
|
1785
2428
|
}
|
|
1786
2429
|
const keys = Object.keys(maybe);
|
|
1787
2430
|
if (keys.length > 0 && keys.every((k) => DIGIT_KEY_REGEX.test(k))) {
|
|
1788
2431
|
const arr = keys.sort((a, b) => Number(a) - Number(b)).map((k) => maybe[k]);
|
|
1789
2432
|
return coerceArrayToArray(arr, prefixItems, itemsSchema);
|
|
1790
2433
|
}
|
|
2434
|
+
const parallelArrays = coerceParallelArraysObjectToArray(
|
|
2435
|
+
maybe,
|
|
2436
|
+
prefixItems,
|
|
2437
|
+
itemsSchema
|
|
2438
|
+
);
|
|
2439
|
+
if (parallelArrays !== null) {
|
|
2440
|
+
return parallelArrays;
|
|
2441
|
+
}
|
|
1791
2442
|
if (keys.length === 1) {
|
|
1792
2443
|
const singleKey = keys[0];
|
|
1793
2444
|
if (!(schemaIsUnconstrained(itemsSchema) || schemaHasProperty(itemsSchema, singleKey))) {
|
|
1794
|
-
const
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
if (
|
|
1799
|
-
return
|
|
2445
|
+
const result = coerceSingleKeyObjectToArray(
|
|
2446
|
+
maybe[singleKey],
|
|
2447
|
+
itemsSchema
|
|
2448
|
+
);
|
|
2449
|
+
if (result !== null) {
|
|
2450
|
+
return result;
|
|
1800
2451
|
}
|
|
1801
2452
|
}
|
|
1802
2453
|
}
|
|
@@ -1826,6 +2477,86 @@ function coerceStringToPrimitive(s, schemaType) {
|
|
|
1826
2477
|
}
|
|
1827
2478
|
return null;
|
|
1828
2479
|
}
|
|
2480
|
+
function coercePrimitiveToString(value, schemaType) {
|
|
2481
|
+
if (schemaType !== "string") {
|
|
2482
|
+
return null;
|
|
2483
|
+
}
|
|
2484
|
+
if (typeof value === "boolean") {
|
|
2485
|
+
return value ? "true" : "false";
|
|
2486
|
+
}
|
|
2487
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2488
|
+
return String(value);
|
|
2489
|
+
}
|
|
2490
|
+
return null;
|
|
2491
|
+
}
|
|
2492
|
+
function coerceStringByEnumWhitespace(rawValue, unwrapped) {
|
|
2493
|
+
const enumValues = unwrapped.enum;
|
|
2494
|
+
if (!Array.isArray(enumValues) || enumValues.length === 0) {
|
|
2495
|
+
return null;
|
|
2496
|
+
}
|
|
2497
|
+
if (!enumValues.every((item) => typeof item === "string")) {
|
|
2498
|
+
return null;
|
|
2499
|
+
}
|
|
2500
|
+
const normalizedEnumValues = enumValues;
|
|
2501
|
+
if (normalizedEnumValues.includes(rawValue)) {
|
|
2502
|
+
return null;
|
|
2503
|
+
}
|
|
2504
|
+
const unquoted = unwrapMatchingQuotes(rawValue);
|
|
2505
|
+
if (unquoted !== null) {
|
|
2506
|
+
const exactMatches = normalizedEnumValues.filter(
|
|
2507
|
+
(item) => item === unquoted
|
|
2508
|
+
);
|
|
2509
|
+
if (exactMatches.length === 1) {
|
|
2510
|
+
return exactMatches[0];
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
const candidates = [rawValue, unquoted].filter(
|
|
2514
|
+
(item) => item !== null
|
|
2515
|
+
);
|
|
2516
|
+
for (const candidate of candidates) {
|
|
2517
|
+
if (!HAS_WHITESPACE_REGEX.test(candidate)) {
|
|
2518
|
+
continue;
|
|
2519
|
+
}
|
|
2520
|
+
const normalizedInput = candidate.replace(WHITESPACE_REGEX2, "");
|
|
2521
|
+
const matches = normalizedEnumValues.filter(
|
|
2522
|
+
(item) => item.replace(WHITESPACE_REGEX2, "") === normalizedInput
|
|
2523
|
+
);
|
|
2524
|
+
if (matches.length === 1) {
|
|
2525
|
+
return matches[0];
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
return null;
|
|
2529
|
+
}
|
|
2530
|
+
function unwrapMatchingQuotes(value) {
|
|
2531
|
+
if (value.length < 2) {
|
|
2532
|
+
return null;
|
|
2533
|
+
}
|
|
2534
|
+
const first = value[0];
|
|
2535
|
+
const last = value.at(-1);
|
|
2536
|
+
const isQuote = (first === SINGLE_QUOTE || first === DOUBLE_QUOTE) && first === last;
|
|
2537
|
+
if (!isQuote) {
|
|
2538
|
+
return null;
|
|
2539
|
+
}
|
|
2540
|
+
return value.slice(1, -1);
|
|
2541
|
+
}
|
|
2542
|
+
function coerceObjectToPrimitive(value, schemaType, fullSchema) {
|
|
2543
|
+
if (!isPrimitiveSchemaType(schemaType)) {
|
|
2544
|
+
return null;
|
|
2545
|
+
}
|
|
2546
|
+
const keys = Object.keys(value);
|
|
2547
|
+
if (keys.length !== 1) {
|
|
2548
|
+
return null;
|
|
2549
|
+
}
|
|
2550
|
+
const singleValue = value[keys[0]];
|
|
2551
|
+
if (singleValue && typeof singleValue === "object") {
|
|
2552
|
+
return null;
|
|
2553
|
+
}
|
|
2554
|
+
const coerced = coerceBySchema(
|
|
2555
|
+
singleValue,
|
|
2556
|
+
fullSchema != null ? fullSchema : { type: schemaType }
|
|
2557
|
+
);
|
|
2558
|
+
return isPrimitiveMatchForSchemaType(coerced, schemaType) ? coerced : null;
|
|
2559
|
+
}
|
|
1829
2560
|
function coerceStringValue(value, schemaType, u) {
|
|
1830
2561
|
const s = value.trim();
|
|
1831
2562
|
if (schemaType === "object") {
|
|
@@ -1844,6 +2575,10 @@ function coerceStringValue(value, schemaType, u) {
|
|
|
1844
2575
|
if (primitiveResult !== null) {
|
|
1845
2576
|
return primitiveResult;
|
|
1846
2577
|
}
|
|
2578
|
+
const enumWhitespaceCanonical = coerceStringByEnumWhitespace(s, u);
|
|
2579
|
+
if (enumWhitespaceCanonical !== null) {
|
|
2580
|
+
return enumWhitespaceCanonical;
|
|
2581
|
+
}
|
|
1847
2582
|
return value;
|
|
1848
2583
|
}
|
|
1849
2584
|
function coerceArrayValue(value, prefixItems, itemsSchema) {
|
|
@@ -1882,9 +2617,23 @@ function coerceBySchema(value, schema) {
|
|
|
1882
2617
|
if (typeof value === "string") {
|
|
1883
2618
|
return coerceStringValue(value, schemaType, u);
|
|
1884
2619
|
}
|
|
2620
|
+
const primitiveString = coercePrimitiveToString(value, schemaType);
|
|
2621
|
+
if (primitiveString !== null) {
|
|
2622
|
+
return primitiveString;
|
|
2623
|
+
}
|
|
1885
2624
|
if (schemaType === "object" && value && typeof value === "object" && !Array.isArray(value)) {
|
|
1886
2625
|
return coerceObjectToObject(value, u);
|
|
1887
2626
|
}
|
|
2627
|
+
if (value && typeof value === "object" && !Array.isArray(value) && isPrimitiveSchemaType(schemaType)) {
|
|
2628
|
+
const primitiveResult = coerceObjectToPrimitive(
|
|
2629
|
+
value,
|
|
2630
|
+
schemaType,
|
|
2631
|
+
u
|
|
2632
|
+
);
|
|
2633
|
+
if (primitiveResult !== null) {
|
|
2634
|
+
return primitiveResult;
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
1888
2637
|
if (schemaType === "array") {
|
|
1889
2638
|
const prefixItems = Array.isArray(u.prefixItems) ? u.prefixItems : void 0;
|
|
1890
2639
|
const itemsSchema = u.items;
|
|
@@ -2899,7 +3648,7 @@ var XMLTokenizer = class {
|
|
|
2899
3648
|
};
|
|
2900
3649
|
|
|
2901
3650
|
// src/rxml/core/parser.ts
|
|
2902
|
-
var
|
|
3651
|
+
var WHITESPACE_REGEX3 = /\s/;
|
|
2903
3652
|
var NUMERIC_STRING_REGEX = /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
|
|
2904
3653
|
var DIGIT_KEY_REGEX2 = /^\d+$/;
|
|
2905
3654
|
function getTopLevelStringProps(s) {
|
|
@@ -3069,7 +3818,7 @@ function parse2(xmlInner, schema, options = {}) {
|
|
|
3069
3818
|
const closeHead = s.indexOf(`</${rootName}`, range.end);
|
|
3070
3819
|
if (closeHead === range.end) {
|
|
3071
3820
|
let p = closeHead + 2 + rootName.length;
|
|
3072
|
-
while (p < s.length &&
|
|
3821
|
+
while (p < s.length && WHITESPACE_REGEX3.test(s[p])) {
|
|
3073
3822
|
p += 1;
|
|
3074
3823
|
}
|
|
3075
3824
|
if (s[p] === ">") {
|
|
@@ -3407,7 +4156,7 @@ function createIntermediateCall(toolName, rawSegment, schema) {
|
|
|
3407
4156
|
var MALFORMED_CLOSE_RE_G = /<\/\s+([A-Za-z0-9_:-]+)\s*>/g;
|
|
3408
4157
|
var MALFORMED_CLOSE_RE = /<\/\s+([A-Za-z0-9_:-]+)\s*>/;
|
|
3409
4158
|
var STATUS_TO_STEP_BOUNDARY_RE = /<\/status>\s*<step>/g;
|
|
3410
|
-
var
|
|
4159
|
+
var WHITESPACE_REGEX4 = /\s/;
|
|
3411
4160
|
var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
|
|
3412
4161
|
var NAME_START_CHAR_RE = /[A-Za-z_:]/;
|
|
3413
4162
|
var STEP_TAG_RE = /<step>([\s\S]*?)<\/step>/i;
|
|
@@ -3548,7 +4297,7 @@ function balanceTags(xml) {
|
|
|
3548
4297
|
}
|
|
3549
4298
|
function skipWs(s, p, len) {
|
|
3550
4299
|
let idx = p;
|
|
3551
|
-
while (idx < len &&
|
|
4300
|
+
while (idx < len && WHITESPACE_REGEX4.test(s[idx])) {
|
|
3552
4301
|
idx += 1;
|
|
3553
4302
|
}
|
|
3554
4303
|
return idx;
|
|
@@ -3601,7 +4350,7 @@ function handleOpeningTagSegment(src, lt, out, stack) {
|
|
|
3601
4350
|
return len;
|
|
3602
4351
|
}
|
|
3603
4352
|
let r = q - 1;
|
|
3604
|
-
while (r >= nameStart &&
|
|
4353
|
+
while (r >= nameStart && WHITESPACE_REGEX4.test(src[r])) {
|
|
3605
4354
|
r -= 1;
|
|
3606
4355
|
}
|
|
3607
4356
|
const selfClosing = src[r] === "/";
|
|
@@ -3765,13 +4514,114 @@ function parse3(xml, schema, options = {}) {
|
|
|
3765
4514
|
|
|
3766
4515
|
// src/core/utils/regex-constants.ts
|
|
3767
4516
|
var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
|
|
3768
|
-
var
|
|
4517
|
+
var WHITESPACE_REGEX5 = /\s/;
|
|
4518
|
+
|
|
4519
|
+
// src/core/utils/streamed-tool-input-delta.ts
|
|
4520
|
+
function emitDelta({
|
|
4521
|
+
controller,
|
|
4522
|
+
id,
|
|
4523
|
+
state,
|
|
4524
|
+
nextInput
|
|
4525
|
+
}) {
|
|
4526
|
+
if (!nextInput.startsWith(state.emittedInput)) {
|
|
4527
|
+
return false;
|
|
4528
|
+
}
|
|
4529
|
+
const delta = nextInput.slice(state.emittedInput.length);
|
|
4530
|
+
if (delta.length === 0) {
|
|
4531
|
+
return false;
|
|
4532
|
+
}
|
|
4533
|
+
controller.enqueue({
|
|
4534
|
+
type: "tool-input-delta",
|
|
4535
|
+
id,
|
|
4536
|
+
delta
|
|
4537
|
+
});
|
|
4538
|
+
state.emittedInput = nextInput;
|
|
4539
|
+
return true;
|
|
4540
|
+
}
|
|
4541
|
+
function toIncompleteJsonPrefix(fullJson) {
|
|
4542
|
+
const trimmed = fullJson.trim();
|
|
4543
|
+
let prefix = trimmed;
|
|
4544
|
+
while (prefix.endsWith("}") || prefix.endsWith("]")) {
|
|
4545
|
+
prefix = prefix.slice(0, -1);
|
|
4546
|
+
}
|
|
4547
|
+
prefix = prefix.trimEnd();
|
|
4548
|
+
if (prefix.endsWith('"')) {
|
|
4549
|
+
prefix = prefix.slice(0, -1);
|
|
4550
|
+
}
|
|
4551
|
+
if (prefix.length === 0) {
|
|
4552
|
+
if (trimmed.startsWith("[") || trimmed.startsWith("{")) {
|
|
4553
|
+
return trimmed.startsWith("{") ? "{" : "[";
|
|
4554
|
+
}
|
|
4555
|
+
if (trimmed.startsWith("]")) {
|
|
4556
|
+
return "[";
|
|
4557
|
+
}
|
|
4558
|
+
if (trimmed.startsWith("}")) {
|
|
4559
|
+
return "{";
|
|
4560
|
+
}
|
|
4561
|
+
if (trimmed.startsWith('"')) {
|
|
4562
|
+
return '"';
|
|
4563
|
+
}
|
|
4564
|
+
return "{";
|
|
4565
|
+
}
|
|
4566
|
+
return prefix;
|
|
4567
|
+
}
|
|
4568
|
+
function emitPrefixDelta(params) {
|
|
4569
|
+
return emitDelta({
|
|
4570
|
+
...params,
|
|
4571
|
+
nextInput: params.candidate
|
|
4572
|
+
});
|
|
4573
|
+
}
|
|
4574
|
+
function emitFinalRemainder(params) {
|
|
4575
|
+
var _a;
|
|
4576
|
+
const result = emitDelta({
|
|
4577
|
+
...params,
|
|
4578
|
+
nextInput: params.finalFullJson
|
|
4579
|
+
});
|
|
4580
|
+
if (!result && params.state.emittedInput.length > 0) {
|
|
4581
|
+
(_a = params.onMismatch) == null ? void 0 : _a.call(
|
|
4582
|
+
params,
|
|
4583
|
+
"Final JSON does not extend emitted tool-input prefix",
|
|
4584
|
+
{
|
|
4585
|
+
emittedLength: params.state.emittedInput.length,
|
|
4586
|
+
finalLength: params.finalFullJson.length
|
|
4587
|
+
}
|
|
4588
|
+
);
|
|
4589
|
+
}
|
|
4590
|
+
return result;
|
|
4591
|
+
}
|
|
4592
|
+
|
|
4593
|
+
// src/core/utils/xml-root-repair.ts
|
|
4594
|
+
var XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX = /^<([A-Za-z_][A-Za-z0-9_-]*)\s*\r?\n([\s\S]+?)\r?\n\s*\/>\s*$/;
|
|
4595
|
+
function tryRepairXmlSelfClosingRootWithBody(rawText, toolNames) {
|
|
4596
|
+
const trimmed = rawText.trim();
|
|
4597
|
+
if (trimmed.length === 0) {
|
|
4598
|
+
return null;
|
|
4599
|
+
}
|
|
4600
|
+
const match = trimmed.match(XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX);
|
|
4601
|
+
if (!match) {
|
|
4602
|
+
return null;
|
|
4603
|
+
}
|
|
4604
|
+
const rootTag = match[1];
|
|
4605
|
+
if (!toolNames.includes(rootTag)) {
|
|
4606
|
+
return null;
|
|
4607
|
+
}
|
|
4608
|
+
const body = match[2].trimEnd();
|
|
4609
|
+
if (body.trim().length === 0 || body.includes(`</${rootTag}>`)) {
|
|
4610
|
+
return null;
|
|
4611
|
+
}
|
|
4612
|
+
return `<${rootTag}>
|
|
4613
|
+
${body}
|
|
4614
|
+
</${rootTag}>`;
|
|
4615
|
+
}
|
|
3769
4616
|
|
|
3770
4617
|
// src/core/protocols/xml-protocol.ts
|
|
3771
4618
|
function getToolSchema(tools, toolName) {
|
|
3772
4619
|
var _a;
|
|
3773
4620
|
return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
3774
4621
|
}
|
|
4622
|
+
function shouldEmitRawToolCallTextOnError2(options) {
|
|
4623
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
4624
|
+
}
|
|
3775
4625
|
function processToolCall(params) {
|
|
3776
4626
|
var _a, _b;
|
|
3777
4627
|
const { toolCall, tools, options, text, processedElements, parseOptions } = params;
|
|
@@ -3784,7 +4634,7 @@ function processToolCall(params) {
|
|
|
3784
4634
|
const parsed = parse3(toolCall.content, toolSchema, parseConfig);
|
|
3785
4635
|
processedElements.push({
|
|
3786
4636
|
type: "tool-call",
|
|
3787
|
-
toolCallId:
|
|
4637
|
+
toolCallId: generateToolCallId(),
|
|
3788
4638
|
toolName: toolCall.toolName,
|
|
3789
4639
|
input: JSON.stringify(parsed)
|
|
3790
4640
|
});
|
|
@@ -3801,60 +4651,371 @@ function processToolCall(params) {
|
|
|
3801
4651
|
processedElements.push({ type: "text", text: originalCallText });
|
|
3802
4652
|
}
|
|
3803
4653
|
}
|
|
3804
|
-
function
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
currentToolCall,
|
|
3809
|
-
tools,
|
|
3810
|
-
options,
|
|
3811
|
-
ctrl,
|
|
3812
|
-
flushText,
|
|
3813
|
-
parseOptions
|
|
3814
|
-
} = params;
|
|
3815
|
-
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
3816
|
-
const parseConfig = {
|
|
3817
|
-
...parseOptions != null ? parseOptions : {},
|
|
3818
|
-
onError: (_a = options == null ? void 0 : options.onError) != null ? _a : parseOptions == null ? void 0 : parseOptions.onError
|
|
3819
|
-
};
|
|
3820
|
-
flushText(ctrl);
|
|
3821
|
-
try {
|
|
3822
|
-
const parsedResult = parse3(toolContent, toolSchema, parseConfig);
|
|
3823
|
-
ctrl.enqueue({
|
|
3824
|
-
type: "tool-call",
|
|
3825
|
-
toolCallId: generateId(),
|
|
3826
|
-
toolName: currentToolCall.name,
|
|
3827
|
-
input: JSON.stringify(parsedResult)
|
|
3828
|
-
});
|
|
3829
|
-
} catch (error) {
|
|
3830
|
-
const original = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
|
|
3831
|
-
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
|
|
3832
|
-
toolCall: original,
|
|
3833
|
-
error
|
|
3834
|
-
});
|
|
3835
|
-
flushText(ctrl, original);
|
|
4654
|
+
function parseXmlTagName(rawTagBody) {
|
|
4655
|
+
let index = 0;
|
|
4656
|
+
while (index < rawTagBody.length && WHITESPACE_REGEX5.test(rawTagBody[index])) {
|
|
4657
|
+
index += 1;
|
|
3836
4658
|
}
|
|
4659
|
+
const nameStart = index;
|
|
4660
|
+
while (index < rawTagBody.length && NAME_CHAR_RE2.test(rawTagBody.charAt(index))) {
|
|
4661
|
+
index += 1;
|
|
4662
|
+
}
|
|
4663
|
+
return rawTagBody.slice(nameStart, index);
|
|
3837
4664
|
}
|
|
3838
|
-
function
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
const tok = nextTagToken(text, pos);
|
|
3843
|
-
if (tok.kind === "eof") {
|
|
3844
|
-
break;
|
|
3845
|
-
}
|
|
3846
|
-
const result = updateDepthWithToken(tok, toolName, depth);
|
|
3847
|
-
depth = result.depth;
|
|
3848
|
-
if (result.closedAt !== void 0) {
|
|
3849
|
-
return result.closedAt;
|
|
3850
|
-
}
|
|
3851
|
-
pos = tok.nextPos;
|
|
4665
|
+
function consumeXmlSpecialSection(fragment, ltIndex) {
|
|
4666
|
+
if (fragment.startsWith("<!--", ltIndex)) {
|
|
4667
|
+
const commentEnd = fragment.indexOf("-->", ltIndex + 4);
|
|
4668
|
+
return commentEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: commentEnd + 3 };
|
|
3852
4669
|
}
|
|
3853
|
-
|
|
4670
|
+
if (fragment.startsWith("<![CDATA[", ltIndex)) {
|
|
4671
|
+
const cdataEnd = fragment.indexOf("]]>", ltIndex + 9);
|
|
4672
|
+
return cdataEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: cdataEnd + 3 };
|
|
4673
|
+
}
|
|
4674
|
+
if (fragment.startsWith("<?", ltIndex)) {
|
|
4675
|
+
const processingEnd = fragment.indexOf("?>", ltIndex + 2);
|
|
4676
|
+
return processingEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: processingEnd + 2 };
|
|
4677
|
+
}
|
|
4678
|
+
if (fragment.startsWith("<!", ltIndex)) {
|
|
4679
|
+
const declarationEnd = fragment.indexOf(">", ltIndex + 2);
|
|
4680
|
+
return declarationEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: declarationEnd + 1 };
|
|
4681
|
+
}
|
|
4682
|
+
return { kind: "none" };
|
|
3854
4683
|
}
|
|
3855
|
-
function
|
|
3856
|
-
const
|
|
3857
|
-
if (
|
|
4684
|
+
function parseXmlTagToken(fragment, ltIndex) {
|
|
4685
|
+
const gtIndex = fragment.indexOf(">", ltIndex + 1);
|
|
4686
|
+
if (gtIndex === -1) {
|
|
4687
|
+
return null;
|
|
4688
|
+
}
|
|
4689
|
+
const tagBody = fragment.slice(ltIndex + 1, gtIndex).trim();
|
|
4690
|
+
if (tagBody.length === 0) {
|
|
4691
|
+
return null;
|
|
4692
|
+
}
|
|
4693
|
+
if (tagBody.startsWith("/")) {
|
|
4694
|
+
const closeName = parseXmlTagName(tagBody.slice(1));
|
|
4695
|
+
if (closeName.length === 0) {
|
|
4696
|
+
return null;
|
|
4697
|
+
}
|
|
4698
|
+
return { kind: "close", name: closeName, nextPos: gtIndex + 1 };
|
|
4699
|
+
}
|
|
4700
|
+
const selfClosing = tagBody.endsWith("/");
|
|
4701
|
+
const openBody = selfClosing ? tagBody.slice(0, -1).trimEnd() : tagBody;
|
|
4702
|
+
const openName = parseXmlTagName(openBody);
|
|
4703
|
+
if (openName.length === 0) {
|
|
4704
|
+
return null;
|
|
4705
|
+
}
|
|
4706
|
+
return {
|
|
4707
|
+
kind: "open",
|
|
4708
|
+
name: openName,
|
|
4709
|
+
selfClosing,
|
|
4710
|
+
nextPos: gtIndex + 1
|
|
4711
|
+
};
|
|
4712
|
+
}
|
|
4713
|
+
function analyzeXmlFragmentForProgress(fragment) {
|
|
4714
|
+
const stack = [];
|
|
4715
|
+
const topLevelTagNames = [];
|
|
4716
|
+
let position = 0;
|
|
4717
|
+
while (position < fragment.length) {
|
|
4718
|
+
const ltIndex = fragment.indexOf("<", position);
|
|
4719
|
+
if (ltIndex === -1) {
|
|
4720
|
+
break;
|
|
4721
|
+
}
|
|
4722
|
+
const special = consumeXmlSpecialSection(fragment, ltIndex);
|
|
4723
|
+
if (special.kind === "incomplete") {
|
|
4724
|
+
return null;
|
|
4725
|
+
}
|
|
4726
|
+
if (special.kind === "consumed") {
|
|
4727
|
+
position = special.nextPos;
|
|
4728
|
+
continue;
|
|
4729
|
+
}
|
|
4730
|
+
const token = parseXmlTagToken(fragment, ltIndex);
|
|
4731
|
+
if (token === null) {
|
|
4732
|
+
return null;
|
|
4733
|
+
}
|
|
4734
|
+
if (token.kind === "close") {
|
|
4735
|
+
const openName = stack.pop();
|
|
4736
|
+
if (!openName || openName !== token.name) {
|
|
4737
|
+
return null;
|
|
4738
|
+
}
|
|
4739
|
+
position = token.nextPos;
|
|
4740
|
+
continue;
|
|
4741
|
+
}
|
|
4742
|
+
if (stack.length === 0) {
|
|
4743
|
+
topLevelTagNames.push(token.name);
|
|
4744
|
+
}
|
|
4745
|
+
if (!token.selfClosing) {
|
|
4746
|
+
stack.push(token.name);
|
|
4747
|
+
}
|
|
4748
|
+
position = token.nextPos;
|
|
4749
|
+
}
|
|
4750
|
+
if (stack.length > 0) {
|
|
4751
|
+
return null;
|
|
4752
|
+
}
|
|
4753
|
+
return { topLevelTagNames };
|
|
4754
|
+
}
|
|
4755
|
+
function scanXmlFragmentTopLevelTextStep(options) {
|
|
4756
|
+
const { fragment, position, stack } = options;
|
|
4757
|
+
const ltIndex = fragment.indexOf("<", position);
|
|
4758
|
+
if (ltIndex === -1) {
|
|
4759
|
+
const trailingText = fragment.slice(position);
|
|
4760
|
+
return {
|
|
4761
|
+
kind: "done",
|
|
4762
|
+
value: stack.length === 0 && trailingText.trim().length > 0
|
|
4763
|
+
};
|
|
4764
|
+
}
|
|
4765
|
+
const textBetweenTags = fragment.slice(position, ltIndex);
|
|
4766
|
+
if (stack.length === 0 && textBetweenTags.trim().length > 0) {
|
|
4767
|
+
return { kind: "found" };
|
|
4768
|
+
}
|
|
4769
|
+
const special = consumeXmlSpecialSection(fragment, ltIndex);
|
|
4770
|
+
if (special.kind === "incomplete") {
|
|
4771
|
+
return { kind: "invalid" };
|
|
4772
|
+
}
|
|
4773
|
+
if (special.kind === "consumed") {
|
|
4774
|
+
return { kind: "next", nextPos: special.nextPos };
|
|
4775
|
+
}
|
|
4776
|
+
const token = parseXmlTagToken(fragment, ltIndex);
|
|
4777
|
+
if (token === null) {
|
|
4778
|
+
return { kind: "invalid" };
|
|
4779
|
+
}
|
|
4780
|
+
if (token.kind === "close") {
|
|
4781
|
+
const openName = stack.pop();
|
|
4782
|
+
if (!openName || openName !== token.name) {
|
|
4783
|
+
return { kind: "invalid" };
|
|
4784
|
+
}
|
|
4785
|
+
} else if (!token.selfClosing) {
|
|
4786
|
+
stack.push(token.name);
|
|
4787
|
+
}
|
|
4788
|
+
return { kind: "next", nextPos: token.nextPos };
|
|
4789
|
+
}
|
|
4790
|
+
function hasNonWhitespaceTopLevelText(fragment) {
|
|
4791
|
+
if (!fragment.includes("<")) {
|
|
4792
|
+
return fragment.trim().length > 0;
|
|
4793
|
+
}
|
|
4794
|
+
const stack = [];
|
|
4795
|
+
let position = 0;
|
|
4796
|
+
while (position < fragment.length) {
|
|
4797
|
+
const step = scanXmlFragmentTopLevelTextStep({ fragment, position, stack });
|
|
4798
|
+
if (step.kind === "found") {
|
|
4799
|
+
return true;
|
|
4800
|
+
}
|
|
4801
|
+
if (step.kind === "invalid") {
|
|
4802
|
+
return false;
|
|
4803
|
+
}
|
|
4804
|
+
if (step.kind === "done") {
|
|
4805
|
+
return step.value;
|
|
4806
|
+
}
|
|
4807
|
+
position = step.nextPos;
|
|
4808
|
+
}
|
|
4809
|
+
return false;
|
|
4810
|
+
}
|
|
4811
|
+
function getObjectSchemaPropertyNames(schema) {
|
|
4812
|
+
if (!schema || typeof schema !== "object") {
|
|
4813
|
+
return null;
|
|
4814
|
+
}
|
|
4815
|
+
const schemaObject = schema;
|
|
4816
|
+
const typeValue = schemaObject.type;
|
|
4817
|
+
if (typeValue != null) {
|
|
4818
|
+
const isObjectType = typeValue === "object" || Array.isArray(typeValue) && typeValue.includes("object");
|
|
4819
|
+
if (!isObjectType) {
|
|
4820
|
+
return null;
|
|
4821
|
+
}
|
|
4822
|
+
}
|
|
4823
|
+
if (!schemaObject.properties || typeof schemaObject.properties !== "object") {
|
|
4824
|
+
return /* @__PURE__ */ new Set();
|
|
4825
|
+
}
|
|
4826
|
+
return new Set(
|
|
4827
|
+
Object.keys(schemaObject.properties)
|
|
4828
|
+
);
|
|
4829
|
+
}
|
|
4830
|
+
function schemaAllowsArrayType(schema) {
|
|
4831
|
+
if (!schema || typeof schema !== "object") {
|
|
4832
|
+
return false;
|
|
4833
|
+
}
|
|
4834
|
+
const schemaRecord = schema;
|
|
4835
|
+
const typeValue = schemaRecord.type;
|
|
4836
|
+
if (typeValue === "array") {
|
|
4837
|
+
return true;
|
|
4838
|
+
}
|
|
4839
|
+
if (Array.isArray(typeValue) && typeValue.includes("array")) {
|
|
4840
|
+
return true;
|
|
4841
|
+
}
|
|
4842
|
+
const unions = [schemaRecord.anyOf, schemaRecord.oneOf, schemaRecord.allOf];
|
|
4843
|
+
for (const union of unions) {
|
|
4844
|
+
if (!Array.isArray(union)) {
|
|
4845
|
+
continue;
|
|
4846
|
+
}
|
|
4847
|
+
if (union.some((entry) => schemaAllowsArrayType(entry))) {
|
|
4848
|
+
return true;
|
|
4849
|
+
}
|
|
4850
|
+
}
|
|
4851
|
+
return false;
|
|
4852
|
+
}
|
|
4853
|
+
function getSchemaObjectProperty(schema, propertyName) {
|
|
4854
|
+
if (!schema || typeof schema !== "object") {
|
|
4855
|
+
return null;
|
|
4856
|
+
}
|
|
4857
|
+
const schemaObject = schema;
|
|
4858
|
+
const properties = schemaObject.properties;
|
|
4859
|
+
if (!properties || typeof properties !== "object") {
|
|
4860
|
+
return null;
|
|
4861
|
+
}
|
|
4862
|
+
const property = properties[propertyName];
|
|
4863
|
+
if (!property) {
|
|
4864
|
+
return null;
|
|
4865
|
+
}
|
|
4866
|
+
return property;
|
|
4867
|
+
}
|
|
4868
|
+
function isStableXmlProgressCandidate(options) {
|
|
4869
|
+
const { candidate, parsed, toolSchema } = options;
|
|
4870
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4871
|
+
return false;
|
|
4872
|
+
}
|
|
4873
|
+
const structure = analyzeXmlFragmentForProgress(candidate);
|
|
4874
|
+
if (!structure) {
|
|
4875
|
+
return false;
|
|
4876
|
+
}
|
|
4877
|
+
const schemaProperties = getObjectSchemaPropertyNames(toolSchema);
|
|
4878
|
+
if (!schemaProperties || schemaProperties.size === 0) {
|
|
4879
|
+
return false;
|
|
4880
|
+
}
|
|
4881
|
+
const parsedObject = parsed;
|
|
4882
|
+
const uniqueTopLevelTags = new Set(structure.topLevelTagNames);
|
|
4883
|
+
for (const tagName of uniqueTopLevelTags) {
|
|
4884
|
+
if (!schemaProperties.has(tagName)) {
|
|
4885
|
+
continue;
|
|
4886
|
+
}
|
|
4887
|
+
const schemaProperty = getSchemaObjectProperty(toolSchema, tagName);
|
|
4888
|
+
if (schemaProperty && schemaAllowsArrayType(schemaProperty) && !Array.isArray(parsedObject[tagName])) {
|
|
4889
|
+
return false;
|
|
4890
|
+
}
|
|
4891
|
+
}
|
|
4892
|
+
if (structure.topLevelTagNames.length === 1) {
|
|
4893
|
+
const onlyTopLevelTag = structure.topLevelTagNames[0];
|
|
4894
|
+
if (!schemaProperties || schemaProperties.size === 0 || !schemaProperties.has(onlyTopLevelTag)) {
|
|
4895
|
+
return false;
|
|
4896
|
+
}
|
|
4897
|
+
}
|
|
4898
|
+
return true;
|
|
4899
|
+
}
|
|
4900
|
+
function parseXmlContentForStreamProgress({
|
|
4901
|
+
toolContent,
|
|
4902
|
+
toolSchema,
|
|
4903
|
+
parseOptions
|
|
4904
|
+
}) {
|
|
4905
|
+
const tryParse = (content) => {
|
|
4906
|
+
try {
|
|
4907
|
+
return parse3(content, toolSchema, {
|
|
4908
|
+
...parseOptions != null ? parseOptions : {},
|
|
4909
|
+
repair: false,
|
|
4910
|
+
onError: void 0
|
|
4911
|
+
});
|
|
4912
|
+
} catch (e) {
|
|
4913
|
+
return null;
|
|
4914
|
+
}
|
|
4915
|
+
};
|
|
4916
|
+
const strictFull = tryParse(toolContent);
|
|
4917
|
+
if (strictFull !== null && isStableXmlProgressCandidate({
|
|
4918
|
+
candidate: toolContent,
|
|
4919
|
+
parsed: strictFull,
|
|
4920
|
+
toolSchema
|
|
4921
|
+
})) {
|
|
4922
|
+
return JSON.stringify(strictFull);
|
|
4923
|
+
}
|
|
4924
|
+
let searchEnd = toolContent.length;
|
|
4925
|
+
while (searchEnd > 0) {
|
|
4926
|
+
const gtIndex = toolContent.lastIndexOf(">", searchEnd - 1);
|
|
4927
|
+
if (gtIndex === -1) {
|
|
4928
|
+
break;
|
|
4929
|
+
}
|
|
4930
|
+
const candidate = toolContent.slice(0, gtIndex + 1);
|
|
4931
|
+
if (!analyzeXmlFragmentForProgress(candidate)) {
|
|
4932
|
+
searchEnd = gtIndex;
|
|
4933
|
+
continue;
|
|
4934
|
+
}
|
|
4935
|
+
const parsedCandidate = tryParse(candidate);
|
|
4936
|
+
if (parsedCandidate !== null && isStableXmlProgressCandidate({
|
|
4937
|
+
candidate,
|
|
4938
|
+
parsed: parsedCandidate,
|
|
4939
|
+
toolSchema
|
|
4940
|
+
})) {
|
|
4941
|
+
return JSON.stringify(parsedCandidate);
|
|
4942
|
+
}
|
|
4943
|
+
searchEnd = gtIndex;
|
|
4944
|
+
}
|
|
4945
|
+
return null;
|
|
4946
|
+
}
|
|
4947
|
+
function handleStreamingToolCallEnd(params) {
|
|
4948
|
+
var _a, _b;
|
|
4949
|
+
const {
|
|
4950
|
+
toolContent,
|
|
4951
|
+
currentToolCall,
|
|
4952
|
+
tools,
|
|
4953
|
+
options,
|
|
4954
|
+
ctrl,
|
|
4955
|
+
flushText,
|
|
4956
|
+
parseOptions
|
|
4957
|
+
} = params;
|
|
4958
|
+
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
4959
|
+
const parseConfig = {
|
|
4960
|
+
...parseOptions != null ? parseOptions : {},
|
|
4961
|
+
onError: (_a = options == null ? void 0 : options.onError) != null ? _a : parseOptions == null ? void 0 : parseOptions.onError
|
|
4962
|
+
};
|
|
4963
|
+
flushText(ctrl);
|
|
4964
|
+
try {
|
|
4965
|
+
const parsedResult = parse3(toolContent, toolSchema, parseConfig);
|
|
4966
|
+
const finalInput = JSON.stringify(parsedResult);
|
|
4967
|
+
emitFinalRemainder({
|
|
4968
|
+
controller: ctrl,
|
|
4969
|
+
id: currentToolCall.toolCallId,
|
|
4970
|
+
state: currentToolCall,
|
|
4971
|
+
finalFullJson: finalInput,
|
|
4972
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
4973
|
+
});
|
|
4974
|
+
ctrl.enqueue({
|
|
4975
|
+
type: "tool-input-end",
|
|
4976
|
+
id: currentToolCall.toolCallId
|
|
4977
|
+
});
|
|
4978
|
+
ctrl.enqueue({
|
|
4979
|
+
type: "tool-call",
|
|
4980
|
+
toolCallId: currentToolCall.toolCallId,
|
|
4981
|
+
toolName: currentToolCall.name,
|
|
4982
|
+
input: finalInput
|
|
4983
|
+
});
|
|
4984
|
+
} catch (error) {
|
|
4985
|
+
ctrl.enqueue({
|
|
4986
|
+
type: "tool-input-end",
|
|
4987
|
+
id: currentToolCall.toolCallId
|
|
4988
|
+
});
|
|
4989
|
+
const original = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
|
|
4990
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
|
|
4991
|
+
toolCall: original,
|
|
4992
|
+
error
|
|
4993
|
+
});
|
|
4994
|
+
if (shouldEmitRawToolCallTextOnError2(options)) {
|
|
4995
|
+
flushText(ctrl, original);
|
|
4996
|
+
}
|
|
4997
|
+
}
|
|
4998
|
+
}
|
|
4999
|
+
function findClosingTagEndFlexible(text, contentStart, toolName) {
|
|
5000
|
+
let pos = contentStart;
|
|
5001
|
+
let depth = 1;
|
|
5002
|
+
while (pos < text.length) {
|
|
5003
|
+
const tok = nextTagToken(text, pos);
|
|
5004
|
+
if (tok.kind === "eof") {
|
|
5005
|
+
break;
|
|
5006
|
+
}
|
|
5007
|
+
const result = updateDepthWithToken(tok, toolName, depth);
|
|
5008
|
+
depth = result.depth;
|
|
5009
|
+
if (result.closedAt !== void 0) {
|
|
5010
|
+
return result.closedAt;
|
|
5011
|
+
}
|
|
5012
|
+
pos = tok.nextPos;
|
|
5013
|
+
}
|
|
5014
|
+
return -1;
|
|
5015
|
+
}
|
|
5016
|
+
function skipSpecialSegment(text, lt) {
|
|
5017
|
+
const next = text[lt + 1];
|
|
5018
|
+
if (next === "!" || next === "?") {
|
|
3858
5019
|
const gt = text.indexOf(">", lt + 1);
|
|
3859
5020
|
if (gt !== -1) {
|
|
3860
5021
|
return gt + 1;
|
|
@@ -3869,7 +5030,7 @@ function consumeClosingTag(text, lt) {
|
|
|
3869
5030
|
}
|
|
3870
5031
|
function consumeOpenTag(text, lt) {
|
|
3871
5032
|
let p = lt + 1;
|
|
3872
|
-
while (p < text.length &&
|
|
5033
|
+
while (p < text.length && WHITESPACE_REGEX5.test(text[p])) {
|
|
3873
5034
|
p += 1;
|
|
3874
5035
|
}
|
|
3875
5036
|
const nameStart = p;
|
|
@@ -3882,7 +5043,7 @@ function consumeOpenTag(text, lt) {
|
|
|
3882
5043
|
return null;
|
|
3883
5044
|
}
|
|
3884
5045
|
let r = q - 1;
|
|
3885
|
-
while (r >= nameStart &&
|
|
5046
|
+
while (r >= nameStart && WHITESPACE_REGEX5.test(text[r])) {
|
|
3886
5047
|
r -= 1;
|
|
3887
5048
|
}
|
|
3888
5049
|
const selfClosing = text[r] === "/";
|
|
@@ -3911,7 +5072,7 @@ function nextTagToken(text, fromPos) {
|
|
|
3911
5072
|
if (next === "/") {
|
|
3912
5073
|
const closing = consumeClosingTag(text, lt);
|
|
3913
5074
|
let p = lt + 2;
|
|
3914
|
-
while (p < text.length &&
|
|
5075
|
+
while (p < text.length && WHITESPACE_REGEX5.test(text[p])) {
|
|
3915
5076
|
p += 1;
|
|
3916
5077
|
}
|
|
3917
5078
|
const nameStart = p;
|
|
@@ -4048,6 +5209,102 @@ function findToolCalls(text, toolNames) {
|
|
|
4048
5209
|
}
|
|
4049
5210
|
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
4050
5211
|
}
|
|
5212
|
+
function handleSpecialToken(depth) {
|
|
5213
|
+
return { depth, lastCompleteEnd: -1, shouldBreak: false };
|
|
5214
|
+
}
|
|
5215
|
+
function handleOpenToken(token, depth, lastCompleteEnd) {
|
|
5216
|
+
if (token.selfClosing) {
|
|
5217
|
+
return {
|
|
5218
|
+
depth,
|
|
5219
|
+
lastCompleteEnd: depth === 0 ? token.nextPos : lastCompleteEnd,
|
|
5220
|
+
shouldBreak: false
|
|
5221
|
+
};
|
|
5222
|
+
}
|
|
5223
|
+
return { depth: depth + 1, lastCompleteEnd, shouldBreak: false };
|
|
5224
|
+
}
|
|
5225
|
+
function handleCloseToken(token, depth) {
|
|
5226
|
+
if (depth <= 0) {
|
|
5227
|
+
return { depth, lastCompleteEnd: -1, shouldBreak: true };
|
|
5228
|
+
}
|
|
5229
|
+
const newDepth = depth - 1;
|
|
5230
|
+
return {
|
|
5231
|
+
depth: newDepth,
|
|
5232
|
+
lastCompleteEnd: newDepth === 0 ? token.nextPos : -1,
|
|
5233
|
+
shouldBreak: false
|
|
5234
|
+
};
|
|
5235
|
+
}
|
|
5236
|
+
function findLinePrefixedXmlBodyEnd(text, bodyStartIndex) {
|
|
5237
|
+
let cursor = bodyStartIndex;
|
|
5238
|
+
let depth = 0;
|
|
5239
|
+
let lastCompleteEnd = -1;
|
|
5240
|
+
while (cursor < text.length) {
|
|
5241
|
+
if (depth === 0) {
|
|
5242
|
+
cursor = consumeWhitespace(text, cursor);
|
|
5243
|
+
if (cursor >= text.length || text.charAt(cursor) !== "<") {
|
|
5244
|
+
break;
|
|
5245
|
+
}
|
|
5246
|
+
}
|
|
5247
|
+
const token = nextTagToken(text, cursor);
|
|
5248
|
+
if (token.kind === "eof") {
|
|
5249
|
+
break;
|
|
5250
|
+
}
|
|
5251
|
+
let result;
|
|
5252
|
+
if (token.kind === "special") {
|
|
5253
|
+
result = handleSpecialToken(depth);
|
|
5254
|
+
} else if (token.kind === "open") {
|
|
5255
|
+
result = handleOpenToken(token, depth, lastCompleteEnd);
|
|
5256
|
+
} else {
|
|
5257
|
+
result = handleCloseToken(token, depth);
|
|
5258
|
+
}
|
|
5259
|
+
depth = result.depth;
|
|
5260
|
+
if (result.lastCompleteEnd !== -1) {
|
|
5261
|
+
lastCompleteEnd = result.lastCompleteEnd;
|
|
5262
|
+
}
|
|
5263
|
+
if (result.shouldBreak) {
|
|
5264
|
+
break;
|
|
5265
|
+
}
|
|
5266
|
+
cursor = token.nextPos;
|
|
5267
|
+
}
|
|
5268
|
+
return lastCompleteEnd;
|
|
5269
|
+
}
|
|
5270
|
+
function findLinePrefixedToolCall(text, toolNames) {
|
|
5271
|
+
var _a;
|
|
5272
|
+
let best = null;
|
|
5273
|
+
for (const toolName of toolNames) {
|
|
5274
|
+
const linePattern = new RegExp(
|
|
5275
|
+
`(^|\\n)[\\t ]*${escapeRegExp(toolName)}[\\t ]*:?[\\t ]*(?:\\r?\\n|$)`,
|
|
5276
|
+
"g"
|
|
5277
|
+
);
|
|
5278
|
+
let match = linePattern.exec(text);
|
|
5279
|
+
while (match !== null) {
|
|
5280
|
+
const prefix = (_a = match[1]) != null ? _a : "";
|
|
5281
|
+
const startIndex = match.index + prefix.length;
|
|
5282
|
+
const contentStart = consumeWhitespace(text, linePattern.lastIndex);
|
|
5283
|
+
if (contentStart >= text.length || text.charAt(contentStart) !== "<") {
|
|
5284
|
+
match = linePattern.exec(text);
|
|
5285
|
+
continue;
|
|
5286
|
+
}
|
|
5287
|
+
const contentEnd = findLinePrefixedXmlBodyEnd(text, contentStart);
|
|
5288
|
+
if (contentEnd === -1 || contentEnd <= contentStart) {
|
|
5289
|
+
match = linePattern.exec(text);
|
|
5290
|
+
continue;
|
|
5291
|
+
}
|
|
5292
|
+
const content = text.slice(contentStart, contentEnd);
|
|
5293
|
+
const candidate = {
|
|
5294
|
+
toolName,
|
|
5295
|
+
startIndex,
|
|
5296
|
+
endIndex: contentEnd,
|
|
5297
|
+
content,
|
|
5298
|
+
segment: text.slice(startIndex, contentEnd)
|
|
5299
|
+
};
|
|
5300
|
+
if (best === null || candidate.startIndex < best.startIndex) {
|
|
5301
|
+
best = candidate;
|
|
5302
|
+
}
|
|
5303
|
+
break;
|
|
5304
|
+
}
|
|
5305
|
+
}
|
|
5306
|
+
return best;
|
|
5307
|
+
}
|
|
4051
5308
|
function findEarliestToolTag(buffer, toolNames) {
|
|
4052
5309
|
var _a, _b;
|
|
4053
5310
|
let bestIndex = -1;
|
|
@@ -4086,7 +5343,7 @@ function isOpenTagPrefix(suffix, toolName) {
|
|
|
4086
5343
|
}
|
|
4087
5344
|
function consumeWhitespace(text, index) {
|
|
4088
5345
|
let i = index;
|
|
4089
|
-
while (i < text.length &&
|
|
5346
|
+
while (i < text.length && WHITESPACE_REGEX5.test(text.charAt(i))) {
|
|
4090
5347
|
i += 1;
|
|
4091
5348
|
}
|
|
4092
5349
|
return i;
|
|
@@ -4158,38 +5415,6 @@ function findPotentialToolTagStart(buffer, toolNames) {
|
|
|
4158
5415
|
}
|
|
4159
5416
|
return -1;
|
|
4160
5417
|
}
|
|
4161
|
-
function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
4162
|
-
return (controller, text) => {
|
|
4163
|
-
const content = text;
|
|
4164
|
-
if (content) {
|
|
4165
|
-
if (!getCurrentTextId()) {
|
|
4166
|
-
const newId = generateId();
|
|
4167
|
-
setCurrentTextId(newId);
|
|
4168
|
-
controller.enqueue({
|
|
4169
|
-
type: "text-start",
|
|
4170
|
-
id: newId
|
|
4171
|
-
});
|
|
4172
|
-
setHasEmittedTextStart(true);
|
|
4173
|
-
}
|
|
4174
|
-
controller.enqueue({
|
|
4175
|
-
type: "text-delta",
|
|
4176
|
-
id: getCurrentTextId(),
|
|
4177
|
-
delta: content
|
|
4178
|
-
});
|
|
4179
|
-
}
|
|
4180
|
-
const currentTextId = getCurrentTextId();
|
|
4181
|
-
if (currentTextId && !text) {
|
|
4182
|
-
if (getHasEmittedTextStart()) {
|
|
4183
|
-
controller.enqueue({
|
|
4184
|
-
type: "text-end",
|
|
4185
|
-
id: currentTextId
|
|
4186
|
-
});
|
|
4187
|
-
setHasEmittedTextStart(false);
|
|
4188
|
-
}
|
|
4189
|
-
setCurrentTextId(null);
|
|
4190
|
-
}
|
|
4191
|
-
};
|
|
4192
|
-
}
|
|
4193
5418
|
function processToolCallInBuffer(params) {
|
|
4194
5419
|
const {
|
|
4195
5420
|
buffer,
|
|
@@ -4199,18 +5424,21 @@ function processToolCallInBuffer(params) {
|
|
|
4199
5424
|
controller,
|
|
4200
5425
|
flushText,
|
|
4201
5426
|
setBuffer,
|
|
4202
|
-
parseOptions
|
|
5427
|
+
parseOptions,
|
|
5428
|
+
emitToolInputProgress: emitToolInputProgress2
|
|
4203
5429
|
} = params;
|
|
4204
5430
|
const endTagPattern = new RegExp(
|
|
4205
5431
|
`</\\s*${escapeRegExp(currentToolCall.name)}\\s*>`
|
|
4206
5432
|
);
|
|
4207
5433
|
const endMatch = endTagPattern.exec(buffer);
|
|
4208
5434
|
if (!endMatch || endMatch.index === void 0) {
|
|
5435
|
+
emitToolInputProgress2(controller, currentToolCall, buffer);
|
|
4209
5436
|
return { buffer, currentToolCall, shouldBreak: true };
|
|
4210
5437
|
}
|
|
4211
5438
|
const endIdx = endMatch.index;
|
|
4212
5439
|
const endPos = endIdx + endMatch[0].length;
|
|
4213
5440
|
const content = buffer.substring(0, endIdx);
|
|
5441
|
+
emitToolInputProgress2(controller, currentToolCall, content);
|
|
4214
5442
|
const remainder = buffer.substring(endPos);
|
|
4215
5443
|
setBuffer(remainder);
|
|
4216
5444
|
handleStreamingToolCallEnd({
|
|
@@ -4237,7 +5465,8 @@ function processNoToolCallInBuffer(params) {
|
|
|
4237
5465
|
tools,
|
|
4238
5466
|
options,
|
|
4239
5467
|
parseOptions,
|
|
4240
|
-
setBuffer
|
|
5468
|
+
setBuffer,
|
|
5469
|
+
emitToolInputStart
|
|
4241
5470
|
} = params;
|
|
4242
5471
|
const {
|
|
4243
5472
|
index: earliestStartTagIndex,
|
|
@@ -4267,9 +5496,10 @@ function processNoToolCallInBuffer(params) {
|
|
|
4267
5496
|
if (selfClosing) {
|
|
4268
5497
|
const newBuffer2 = buffer.substring(earliestStartTagIndex + tagLength);
|
|
4269
5498
|
setBuffer(newBuffer2);
|
|
5499
|
+
const currentToolCall = emitToolInputStart(controller, earliestToolName);
|
|
4270
5500
|
handleStreamingToolCallEnd({
|
|
4271
5501
|
toolContent: "",
|
|
4272
|
-
currentToolCall
|
|
5502
|
+
currentToolCall,
|
|
4273
5503
|
tools,
|
|
4274
5504
|
options,
|
|
4275
5505
|
ctrl: controller,
|
|
@@ -4288,12 +5518,12 @@ function processNoToolCallInBuffer(params) {
|
|
|
4288
5518
|
setBuffer(newBuffer);
|
|
4289
5519
|
return {
|
|
4290
5520
|
buffer: newBuffer,
|
|
4291
|
-
currentToolCall:
|
|
5521
|
+
currentToolCall: emitToolInputStart(controller, earliestToolName),
|
|
4292
5522
|
shouldBreak: false,
|
|
4293
5523
|
shouldContinue: true
|
|
4294
5524
|
};
|
|
4295
5525
|
}
|
|
4296
|
-
function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions) {
|
|
5526
|
+
function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions, emitToolInputProgress2, emitToolInputStart) {
|
|
4297
5527
|
return (controller) => {
|
|
4298
5528
|
while (true) {
|
|
4299
5529
|
const currentToolCall = getCurrentToolCall();
|
|
@@ -4306,7 +5536,8 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
4306
5536
|
controller,
|
|
4307
5537
|
flushText,
|
|
4308
5538
|
setBuffer,
|
|
4309
|
-
parseOptions
|
|
5539
|
+
parseOptions,
|
|
5540
|
+
emitToolInputProgress: emitToolInputProgress2
|
|
4310
5541
|
});
|
|
4311
5542
|
setBuffer(result.buffer);
|
|
4312
5543
|
setCurrentToolCall(result.currentToolCall);
|
|
@@ -4322,7 +5553,8 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
4322
5553
|
tools,
|
|
4323
5554
|
options,
|
|
4324
5555
|
parseOptions,
|
|
4325
|
-
setBuffer
|
|
5556
|
+
setBuffer,
|
|
5557
|
+
emitToolInputStart
|
|
4326
5558
|
});
|
|
4327
5559
|
setBuffer(result.buffer);
|
|
4328
5560
|
setCurrentToolCall(result.currentToolCall);
|
|
@@ -4337,6 +5569,27 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
4337
5569
|
}
|
|
4338
5570
|
};
|
|
4339
5571
|
}
|
|
5572
|
+
function findToolCallsWithFallbacks(text, toolNames) {
|
|
5573
|
+
let parseText = text;
|
|
5574
|
+
let toolCalls = findToolCalls(parseText, toolNames);
|
|
5575
|
+
if (toolCalls.length === 0) {
|
|
5576
|
+
const fallbackToolCall = findLinePrefixedToolCall(parseText, toolNames);
|
|
5577
|
+
if (fallbackToolCall !== null) {
|
|
5578
|
+
toolCalls.push(fallbackToolCall);
|
|
5579
|
+
}
|
|
5580
|
+
}
|
|
5581
|
+
if (toolCalls.length === 0) {
|
|
5582
|
+
const repaired = tryRepairXmlSelfClosingRootWithBody(parseText, toolNames);
|
|
5583
|
+
if (repaired) {
|
|
5584
|
+
const repairedCalls = findToolCalls(repaired, toolNames);
|
|
5585
|
+
if (repairedCalls.length > 0) {
|
|
5586
|
+
parseText = repaired;
|
|
5587
|
+
toolCalls = repairedCalls;
|
|
5588
|
+
}
|
|
5589
|
+
}
|
|
5590
|
+
}
|
|
5591
|
+
return { parseText, toolCalls };
|
|
5592
|
+
}
|
|
4340
5593
|
var xmlProtocol = (protocolOptions) => {
|
|
4341
5594
|
var _a;
|
|
4342
5595
|
const parseOptions = {
|
|
@@ -4370,28 +5623,31 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4370
5623
|
}
|
|
4371
5624
|
const processedElements = [];
|
|
4372
5625
|
let currentIndex = 0;
|
|
4373
|
-
const toolCalls =
|
|
5626
|
+
const { parseText, toolCalls } = findToolCallsWithFallbacks(
|
|
5627
|
+
text,
|
|
5628
|
+
toolNames
|
|
5629
|
+
);
|
|
4374
5630
|
for (const tc of toolCalls) {
|
|
4375
5631
|
if (tc.startIndex > currentIndex) {
|
|
4376
5632
|
processedElements.push({
|
|
4377
5633
|
type: "text",
|
|
4378
|
-
text:
|
|
5634
|
+
text: parseText.substring(currentIndex, tc.startIndex)
|
|
4379
5635
|
});
|
|
4380
5636
|
}
|
|
4381
5637
|
processToolCall({
|
|
4382
5638
|
toolCall: tc,
|
|
4383
5639
|
tools,
|
|
4384
5640
|
options,
|
|
4385
|
-
text,
|
|
5641
|
+
text: parseText,
|
|
4386
5642
|
processedElements,
|
|
4387
5643
|
parseOptions
|
|
4388
5644
|
});
|
|
4389
5645
|
currentIndex = tc.endIndex;
|
|
4390
5646
|
}
|
|
4391
|
-
if (currentIndex <
|
|
5647
|
+
if (currentIndex < parseText.length) {
|
|
4392
5648
|
processedElements.push({
|
|
4393
5649
|
type: "text",
|
|
4394
|
-
text:
|
|
5650
|
+
text: parseText.substring(currentIndex)
|
|
4395
5651
|
});
|
|
4396
5652
|
}
|
|
4397
5653
|
return processedElements;
|
|
@@ -4412,8 +5668,120 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4412
5668
|
hasEmittedTextStart = value;
|
|
4413
5669
|
}
|
|
4414
5670
|
);
|
|
4415
|
-
const
|
|
4416
|
-
()
|
|
5671
|
+
const emitToolInputStart = (controller, toolName) => {
|
|
5672
|
+
flushText(controller);
|
|
5673
|
+
const next = {
|
|
5674
|
+
name: toolName,
|
|
5675
|
+
toolCallId: generateToolCallId(),
|
|
5676
|
+
emittedInput: "",
|
|
5677
|
+
lastProgressGtIndex: null,
|
|
5678
|
+
lastProgressFullInput: null
|
|
5679
|
+
};
|
|
5680
|
+
controller.enqueue({
|
|
5681
|
+
type: "tool-input-start",
|
|
5682
|
+
id: next.toolCallId,
|
|
5683
|
+
toolName
|
|
5684
|
+
});
|
|
5685
|
+
return next;
|
|
5686
|
+
};
|
|
5687
|
+
const emitToolInputProgress2 = (controller, toolCall, toolContent) => {
|
|
5688
|
+
const progressGtIndex = toolContent.lastIndexOf(">");
|
|
5689
|
+
if (toolCall.lastProgressGtIndex === progressGtIndex) {
|
|
5690
|
+
const cached = toolCall.lastProgressFullInput;
|
|
5691
|
+
if (cached == null) {
|
|
5692
|
+
return;
|
|
5693
|
+
}
|
|
5694
|
+
if (cached === "{}" && toolContent.trim().length === 0) {
|
|
5695
|
+
return;
|
|
5696
|
+
}
|
|
5697
|
+
const prefixCandidate2 = toIncompleteJsonPrefix(cached);
|
|
5698
|
+
emitPrefixDelta({
|
|
5699
|
+
controller,
|
|
5700
|
+
id: toolCall.toolCallId,
|
|
5701
|
+
state: toolCall,
|
|
5702
|
+
candidate: prefixCandidate2
|
|
5703
|
+
});
|
|
5704
|
+
return;
|
|
5705
|
+
}
|
|
5706
|
+
const toolSchema = getToolSchema(tools, toolCall.name);
|
|
5707
|
+
const fullInput = parseXmlContentForStreamProgress({
|
|
5708
|
+
toolContent,
|
|
5709
|
+
toolSchema,
|
|
5710
|
+
parseOptions
|
|
5711
|
+
});
|
|
5712
|
+
toolCall.lastProgressGtIndex = progressGtIndex;
|
|
5713
|
+
toolCall.lastProgressFullInput = fullInput;
|
|
5714
|
+
if (fullInput == null) {
|
|
5715
|
+
return;
|
|
5716
|
+
}
|
|
5717
|
+
if (fullInput === "{}" && toolContent.trim().length === 0) {
|
|
5718
|
+
return;
|
|
5719
|
+
}
|
|
5720
|
+
const prefixCandidate = toIncompleteJsonPrefix(fullInput);
|
|
5721
|
+
emitPrefixDelta({
|
|
5722
|
+
controller,
|
|
5723
|
+
id: toolCall.toolCallId,
|
|
5724
|
+
state: toolCall,
|
|
5725
|
+
candidate: prefixCandidate
|
|
5726
|
+
});
|
|
5727
|
+
};
|
|
5728
|
+
const finalizeUnclosedToolCall = (controller) => {
|
|
5729
|
+
var _a2, _b;
|
|
5730
|
+
if (!currentToolCall) {
|
|
5731
|
+
return;
|
|
5732
|
+
}
|
|
5733
|
+
emitToolInputProgress2(controller, currentToolCall, buffer);
|
|
5734
|
+
const parseConfig = {
|
|
5735
|
+
...parseOptions,
|
|
5736
|
+
onError: (_a2 = options == null ? void 0 : options.onError) != null ? _a2 : parseOptions == null ? void 0 : parseOptions.onError
|
|
5737
|
+
};
|
|
5738
|
+
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
5739
|
+
flushText(controller);
|
|
5740
|
+
try {
|
|
5741
|
+
if (hasNonWhitespaceTopLevelText(buffer)) {
|
|
5742
|
+
throw new Error(
|
|
5743
|
+
"Cannot reconcile unclosed XML tool call with top-level plain text."
|
|
5744
|
+
);
|
|
5745
|
+
}
|
|
5746
|
+
const parsedResult = parse3(buffer, toolSchema, parseConfig);
|
|
5747
|
+
const finalInput = JSON.stringify(parsedResult);
|
|
5748
|
+
emitFinalRemainder({
|
|
5749
|
+
controller,
|
|
5750
|
+
id: currentToolCall.toolCallId,
|
|
5751
|
+
state: currentToolCall,
|
|
5752
|
+
finalFullJson: finalInput,
|
|
5753
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
5754
|
+
});
|
|
5755
|
+
controller.enqueue({
|
|
5756
|
+
type: "tool-input-end",
|
|
5757
|
+
id: currentToolCall.toolCallId
|
|
5758
|
+
});
|
|
5759
|
+
controller.enqueue({
|
|
5760
|
+
type: "tool-call",
|
|
5761
|
+
toolCallId: currentToolCall.toolCallId,
|
|
5762
|
+
toolName: currentToolCall.name,
|
|
5763
|
+
input: finalInput
|
|
5764
|
+
});
|
|
5765
|
+
} catch (error) {
|
|
5766
|
+
controller.enqueue({
|
|
5767
|
+
type: "tool-input-end",
|
|
5768
|
+
id: currentToolCall.toolCallId
|
|
5769
|
+
});
|
|
5770
|
+
const unfinishedContent = `<${currentToolCall.name}>${buffer}`;
|
|
5771
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
5772
|
+
options,
|
|
5773
|
+
"Could not complete streaming XML tool call at finish.",
|
|
5774
|
+
{ toolCall: unfinishedContent, error }
|
|
5775
|
+
);
|
|
5776
|
+
if (shouldEmitRawToolCallTextOnError2(options)) {
|
|
5777
|
+
flushText(controller, unfinishedContent);
|
|
5778
|
+
}
|
|
5779
|
+
}
|
|
5780
|
+
buffer = "";
|
|
5781
|
+
currentToolCall = null;
|
|
5782
|
+
};
|
|
5783
|
+
const processBuffer = createProcessBufferHandler(
|
|
5784
|
+
() => buffer,
|
|
4417
5785
|
(newBuffer) => {
|
|
4418
5786
|
buffer = newBuffer;
|
|
4419
5787
|
},
|
|
@@ -4425,13 +5793,28 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4425
5793
|
options,
|
|
4426
5794
|
toolNames,
|
|
4427
5795
|
flushText,
|
|
4428
|
-
parseOptions
|
|
5796
|
+
parseOptions,
|
|
5797
|
+
emitToolInputProgress2,
|
|
5798
|
+
emitToolInputStart
|
|
4429
5799
|
);
|
|
4430
5800
|
return new TransformStream({
|
|
5801
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Stateful stream parsing requires branching over chunk lifecycle and parser states.
|
|
4431
5802
|
transform(chunk, controller) {
|
|
4432
5803
|
var _a2;
|
|
5804
|
+
if (chunk.type === "finish") {
|
|
5805
|
+
if (currentToolCall) {
|
|
5806
|
+
finalizeUnclosedToolCall(controller);
|
|
5807
|
+
} else if (buffer) {
|
|
5808
|
+
flushText(controller, buffer);
|
|
5809
|
+
buffer = "";
|
|
5810
|
+
}
|
|
5811
|
+
flushText(controller);
|
|
5812
|
+
controller.enqueue(chunk);
|
|
5813
|
+
return;
|
|
5814
|
+
}
|
|
4433
5815
|
if (chunk.type !== "text-delta") {
|
|
4434
|
-
if (
|
|
5816
|
+
if (currentToolCall) {
|
|
5817
|
+
} else if (buffer) {
|
|
4435
5818
|
flushText(controller, buffer);
|
|
4436
5819
|
buffer = "";
|
|
4437
5820
|
}
|
|
@@ -4444,10 +5827,7 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4444
5827
|
},
|
|
4445
5828
|
flush(controller) {
|
|
4446
5829
|
if (currentToolCall) {
|
|
4447
|
-
|
|
4448
|
-
flushText(controller, unfinishedContent);
|
|
4449
|
-
buffer = "";
|
|
4450
|
-
currentToolCall = null;
|
|
5830
|
+
finalizeUnclosedToolCall(controller);
|
|
4451
5831
|
} else if (buffer) {
|
|
4452
5832
|
flushText(controller, buffer);
|
|
4453
5833
|
buffer = "";
|
|
@@ -4475,7 +5855,205 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4475
5855
|
|
|
4476
5856
|
// src/core/protocols/yaml-protocol.ts
|
|
4477
5857
|
var import_yaml = __toESM(require("yaml"), 1);
|
|
5858
|
+
function shouldEmitRawToolCallTextOnError3(options) {
|
|
5859
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
5860
|
+
}
|
|
5861
|
+
var selfClosingTagCache2 = /* @__PURE__ */ new Map();
|
|
5862
|
+
function getSelfClosingTagPattern2(toolName) {
|
|
5863
|
+
let pattern = selfClosingTagCache2.get(toolName);
|
|
5864
|
+
if (!pattern) {
|
|
5865
|
+
pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
|
|
5866
|
+
selfClosingTagCache2.set(toolName, pattern);
|
|
5867
|
+
}
|
|
5868
|
+
return pattern;
|
|
5869
|
+
}
|
|
4478
5870
|
var LEADING_WHITESPACE_RE = /^(\s*)/;
|
|
5871
|
+
var INCOMPLETE_MAPPING_TAIL_RE = /^[^:[\]{}-][^:]*:\s*$/;
|
|
5872
|
+
var INCOMPLETE_SEQUENCE_TAIL_RE = /^-\s*$/;
|
|
5873
|
+
var BLOCK_SCALAR_KEY_RE = /:\s*[|>][-+0-9]*\s*$/;
|
|
5874
|
+
var PLAIN_MAPPING_VALUE_RE = /^[^:[\]{}-][^:]*:\s*(.+)$/;
|
|
5875
|
+
var PLAIN_SEQUENCE_VALUE_RE = /^-\s+(.+)$/;
|
|
5876
|
+
function normalizeYamlContent(yamlContent) {
|
|
5877
|
+
let normalized = yamlContent;
|
|
5878
|
+
if (normalized.startsWith("\n")) {
|
|
5879
|
+
normalized = normalized.slice(1);
|
|
5880
|
+
}
|
|
5881
|
+
const lines = normalized.split("\n");
|
|
5882
|
+
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
|
5883
|
+
if (nonEmptyLines.length === 0) {
|
|
5884
|
+
return { normalized: "", nonEmptyLines };
|
|
5885
|
+
}
|
|
5886
|
+
const minIndent = Math.min(
|
|
5887
|
+
...nonEmptyLines.map((line) => {
|
|
5888
|
+
const match = line.match(LEADING_WHITESPACE_RE);
|
|
5889
|
+
return match ? match[1].length : 0;
|
|
5890
|
+
})
|
|
5891
|
+
);
|
|
5892
|
+
if (minIndent > 0) {
|
|
5893
|
+
normalized = lines.map((line) => line.slice(minIndent)).join("\n");
|
|
5894
|
+
}
|
|
5895
|
+
return { normalized, nonEmptyLines };
|
|
5896
|
+
}
|
|
5897
|
+
function parseYamlDocumentAsMapping(normalized) {
|
|
5898
|
+
try {
|
|
5899
|
+
const doc = import_yaml.default.parseDocument(normalized);
|
|
5900
|
+
const errors = doc.errors.map((e) => e.message);
|
|
5901
|
+
const result = doc.toJSON();
|
|
5902
|
+
if (result === null) {
|
|
5903
|
+
return { value: {}, errors };
|
|
5904
|
+
}
|
|
5905
|
+
if (typeof result !== "object" || Array.isArray(result)) {
|
|
5906
|
+
return { value: null, errors };
|
|
5907
|
+
}
|
|
5908
|
+
return { value: result, errors };
|
|
5909
|
+
} catch (error) {
|
|
5910
|
+
return {
|
|
5911
|
+
value: null,
|
|
5912
|
+
errors: [
|
|
5913
|
+
error instanceof Error ? error.message : "Unknown YAML parsing error"
|
|
5914
|
+
]
|
|
5915
|
+
};
|
|
5916
|
+
}
|
|
5917
|
+
}
|
|
5918
|
+
function getLastMeaningfulLineInfo(input) {
|
|
5919
|
+
var _a;
|
|
5920
|
+
const lines = input.split("\n");
|
|
5921
|
+
let index = lines.length - 1;
|
|
5922
|
+
while (index >= 0) {
|
|
5923
|
+
const raw = (_a = lines[index]) != null ? _a : "";
|
|
5924
|
+
const trimmed = raw.trim();
|
|
5925
|
+
if (trimmed.length > 0 && !trimmed.startsWith("#")) {
|
|
5926
|
+
return {
|
|
5927
|
+
index,
|
|
5928
|
+
raw,
|
|
5929
|
+
trimmed,
|
|
5930
|
+
indent: raw.length - raw.trimStart().length
|
|
5931
|
+
};
|
|
5932
|
+
}
|
|
5933
|
+
index -= 1;
|
|
5934
|
+
}
|
|
5935
|
+
return null;
|
|
5936
|
+
}
|
|
5937
|
+
function dropLastMeaningfulLine(input) {
|
|
5938
|
+
const lineInfo = getLastMeaningfulLineInfo(input);
|
|
5939
|
+
if (!lineInfo) {
|
|
5940
|
+
return null;
|
|
5941
|
+
}
|
|
5942
|
+
return input.split("\n").slice(0, lineInfo.index).join("\n").trimEnd();
|
|
5943
|
+
}
|
|
5944
|
+
function hasIncompleteMappingTail(normalized) {
|
|
5945
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
5946
|
+
if (!lineInfo) {
|
|
5947
|
+
return false;
|
|
5948
|
+
}
|
|
5949
|
+
return INCOMPLETE_MAPPING_TAIL_RE.test(lineInfo.trimmed);
|
|
5950
|
+
}
|
|
5951
|
+
function hasIncompleteSequenceTail(normalized) {
|
|
5952
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
5953
|
+
if (!lineInfo) {
|
|
5954
|
+
return false;
|
|
5955
|
+
}
|
|
5956
|
+
return INCOMPLETE_SEQUENCE_TAIL_RE.test(lineInfo.trimmed);
|
|
5957
|
+
}
|
|
5958
|
+
function hasSplitNestedKeyTail(normalized) {
|
|
5959
|
+
var _a;
|
|
5960
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
5961
|
+
if (!lineInfo) {
|
|
5962
|
+
return false;
|
|
5963
|
+
}
|
|
5964
|
+
const { trimmed, indent, index } = lineInfo;
|
|
5965
|
+
if (indent === 0) {
|
|
5966
|
+
return false;
|
|
5967
|
+
}
|
|
5968
|
+
if (trimmed.startsWith("#") || trimmed.startsWith("-") || trimmed.includes(":")) {
|
|
5969
|
+
return false;
|
|
5970
|
+
}
|
|
5971
|
+
const lines = normalized.split("\n");
|
|
5972
|
+
let parentIndex = index - 1;
|
|
5973
|
+
while (parentIndex >= 0) {
|
|
5974
|
+
const parentRaw = (_a = lines[parentIndex]) != null ? _a : "";
|
|
5975
|
+
const parentTrimmed = parentRaw.trim();
|
|
5976
|
+
if (parentTrimmed.length === 0 || parentTrimmed.startsWith("#")) {
|
|
5977
|
+
parentIndex -= 1;
|
|
5978
|
+
continue;
|
|
5979
|
+
}
|
|
5980
|
+
const parentIndent = parentRaw.length - parentRaw.trimStart().length;
|
|
5981
|
+
if (parentIndent >= indent) {
|
|
5982
|
+
parentIndex -= 1;
|
|
5983
|
+
continue;
|
|
5984
|
+
}
|
|
5985
|
+
if (!parentTrimmed.endsWith(":")) {
|
|
5986
|
+
return false;
|
|
5987
|
+
}
|
|
5988
|
+
if (BLOCK_SCALAR_KEY_RE.test(parentTrimmed)) {
|
|
5989
|
+
return false;
|
|
5990
|
+
}
|
|
5991
|
+
return true;
|
|
5992
|
+
}
|
|
5993
|
+
return false;
|
|
5994
|
+
}
|
|
5995
|
+
function extractTrailingPlainScalarValue(line) {
|
|
5996
|
+
var _a;
|
|
5997
|
+
if (BLOCK_SCALAR_KEY_RE.test(line)) {
|
|
5998
|
+
return null;
|
|
5999
|
+
}
|
|
6000
|
+
const mappingMatch = line.match(PLAIN_MAPPING_VALUE_RE);
|
|
6001
|
+
const sequenceMatch = line.match(PLAIN_SEQUENCE_VALUE_RE);
|
|
6002
|
+
const value = (_a = mappingMatch == null ? void 0 : mappingMatch[1]) != null ? _a : sequenceMatch == null ? void 0 : sequenceMatch[1];
|
|
6003
|
+
if (!value) {
|
|
6004
|
+
return null;
|
|
6005
|
+
}
|
|
6006
|
+
const trimmedValue = value.trim();
|
|
6007
|
+
if (trimmedValue.length === 0) {
|
|
6008
|
+
return null;
|
|
6009
|
+
}
|
|
6010
|
+
if (trimmedValue.startsWith('"') || trimmedValue.startsWith("'")) {
|
|
6011
|
+
return null;
|
|
6012
|
+
}
|
|
6013
|
+
if (trimmedValue.startsWith("{") || trimmedValue.startsWith("[") || trimmedValue.startsWith("|") || trimmedValue.startsWith(">")) {
|
|
6014
|
+
return null;
|
|
6015
|
+
}
|
|
6016
|
+
return trimmedValue;
|
|
6017
|
+
}
|
|
6018
|
+
function hasUnterminatedPlainScalarTail(normalized) {
|
|
6019
|
+
if (normalized.endsWith("\n")) {
|
|
6020
|
+
return false;
|
|
6021
|
+
}
|
|
6022
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6023
|
+
if (!lineInfo) {
|
|
6024
|
+
return false;
|
|
6025
|
+
}
|
|
6026
|
+
return extractTrailingPlainScalarValue(lineInfo.trimmed) != null;
|
|
6027
|
+
}
|
|
6028
|
+
function hasUnstableProgressTail(normalized) {
|
|
6029
|
+
return hasIncompleteMappingTail(normalized) || hasIncompleteSequenceTail(normalized) || hasSplitNestedKeyTail(normalized) || hasUnterminatedPlainScalarTail(normalized);
|
|
6030
|
+
}
|
|
6031
|
+
function trimTrailingNewlineInUnknown(value) {
|
|
6032
|
+
if (typeof value === "string") {
|
|
6033
|
+
if (value.endsWith("\n")) {
|
|
6034
|
+
return value.slice(0, -1);
|
|
6035
|
+
}
|
|
6036
|
+
return value;
|
|
6037
|
+
}
|
|
6038
|
+
if (Array.isArray(value)) {
|
|
6039
|
+
return value.map((item) => trimTrailingNewlineInUnknown(item));
|
|
6040
|
+
}
|
|
6041
|
+
if (value && typeof value === "object") {
|
|
6042
|
+
return Object.fromEntries(
|
|
6043
|
+
Object.entries(value).map(([key, item]) => [
|
|
6044
|
+
key,
|
|
6045
|
+
trimTrailingNewlineInUnknown(item)
|
|
6046
|
+
])
|
|
6047
|
+
);
|
|
6048
|
+
}
|
|
6049
|
+
return value;
|
|
6050
|
+
}
|
|
6051
|
+
function stabilizeParsedValueForStreamProgress(value, source) {
|
|
6052
|
+
if (source.endsWith("\n")) {
|
|
6053
|
+
return value;
|
|
6054
|
+
}
|
|
6055
|
+
return trimTrailingNewlineInUnknown(value);
|
|
6056
|
+
}
|
|
4479
6057
|
function findClosingTagEnd(text, contentStart, toolName) {
|
|
4480
6058
|
let pos = contentStart;
|
|
4481
6059
|
let depth = 1;
|
|
@@ -4491,7 +6069,7 @@ function findClosingTagEnd(text, contentStart, toolName) {
|
|
|
4491
6069
|
break;
|
|
4492
6070
|
}
|
|
4493
6071
|
let p = ltIdx + 2;
|
|
4494
|
-
while (p < gtIdx &&
|
|
6072
|
+
while (p < gtIdx && WHITESPACE_REGEX5.test(text[p])) {
|
|
4495
6073
|
p++;
|
|
4496
6074
|
}
|
|
4497
6075
|
const nameStart = p;
|
|
@@ -4511,7 +6089,7 @@ function findClosingTagEnd(text, contentStart, toolName) {
|
|
|
4511
6089
|
pos = gtIdx === -1 ? text.length : gtIdx + 1;
|
|
4512
6090
|
} else {
|
|
4513
6091
|
let p = ltIdx + 1;
|
|
4514
|
-
while (p < text.length &&
|
|
6092
|
+
while (p < text.length && WHITESPACE_REGEX5.test(text[p])) {
|
|
4515
6093
|
p++;
|
|
4516
6094
|
}
|
|
4517
6095
|
const nameStart = p;
|
|
@@ -4524,7 +6102,7 @@ function findClosingTagEnd(text, contentStart, toolName) {
|
|
|
4524
6102
|
break;
|
|
4525
6103
|
}
|
|
4526
6104
|
let r = gtIdx - 1;
|
|
4527
|
-
while (r >= nameStart &&
|
|
6105
|
+
while (r >= nameStart && WHITESPACE_REGEX5.test(text[r])) {
|
|
4528
6106
|
r--;
|
|
4529
6107
|
}
|
|
4530
6108
|
const selfClosing = text[r] === "/";
|
|
@@ -4547,7 +6125,7 @@ function findEarliestTagPosition(openIdx, selfIdx) {
|
|
|
4547
6125
|
function collectToolCallsForName(text, toolName) {
|
|
4548
6126
|
const toolCalls = [];
|
|
4549
6127
|
let searchIndex = 0;
|
|
4550
|
-
const selfTagRegex =
|
|
6128
|
+
const selfTagRegex = getSelfClosingTagPattern2(toolName);
|
|
4551
6129
|
while (searchIndex < text.length) {
|
|
4552
6130
|
const startTag = `<${toolName}>`;
|
|
4553
6131
|
const openIdx = text.indexOf(startTag, searchIndex);
|
|
@@ -4599,47 +6177,48 @@ function findToolCalls2(text, toolNames) {
|
|
|
4599
6177
|
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
4600
6178
|
}
|
|
4601
6179
|
function parseYamlContent(yamlContent, options) {
|
|
4602
|
-
var _a, _b
|
|
4603
|
-
|
|
4604
|
-
if (normalized.startsWith("\n")) {
|
|
4605
|
-
normalized = normalized.slice(1);
|
|
4606
|
-
}
|
|
4607
|
-
const lines = normalized.split("\n");
|
|
4608
|
-
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
|
6180
|
+
var _a, _b;
|
|
6181
|
+
const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
|
|
4609
6182
|
if (nonEmptyLines.length === 0) {
|
|
4610
6183
|
return {};
|
|
4611
6184
|
}
|
|
4612
|
-
const
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
})
|
|
4617
|
-
|
|
4618
|
-
if (minIndent > 0) {
|
|
4619
|
-
normalized = lines.map((line) => line.slice(minIndent)).join("\n");
|
|
6185
|
+
const parsed = parseYamlDocumentAsMapping(normalized);
|
|
6186
|
+
if (parsed.errors.length > 0) {
|
|
6187
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "YAML parse error", {
|
|
6188
|
+
errors: parsed.errors
|
|
6189
|
+
});
|
|
6190
|
+
return null;
|
|
4620
6191
|
}
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
6192
|
+
if (parsed.value === null) {
|
|
6193
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
|
|
6194
|
+
got: "non-mapping"
|
|
6195
|
+
});
|
|
6196
|
+
return null;
|
|
6197
|
+
}
|
|
6198
|
+
return parsed.value;
|
|
6199
|
+
}
|
|
6200
|
+
function parseYamlContentForStreamProgress(yamlContent) {
|
|
6201
|
+
const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
|
|
6202
|
+
if (nonEmptyLines.length === 0) {
|
|
6203
|
+
return {};
|
|
6204
|
+
}
|
|
6205
|
+
let candidate = normalized;
|
|
6206
|
+
while (true) {
|
|
6207
|
+
const parsed = parseYamlDocumentAsMapping(candidate);
|
|
6208
|
+
if (parsed.errors.length === 0 && !hasUnstableProgressTail(candidate)) {
|
|
6209
|
+
if (candidate.trim().length === 0 && normalized.trim().length > 0) {
|
|
6210
|
+
return null;
|
|
6211
|
+
}
|
|
6212
|
+
return stabilizeParsedValueForStreamProgress(parsed.value, candidate);
|
|
4628
6213
|
}
|
|
4629
|
-
const
|
|
4630
|
-
if (
|
|
4631
|
-
return
|
|
6214
|
+
const truncated = dropLastMeaningfulLine(candidate);
|
|
6215
|
+
if (truncated == null) {
|
|
6216
|
+
return null;
|
|
4632
6217
|
}
|
|
4633
|
-
if (
|
|
4634
|
-
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
|
|
4635
|
-
got: typeof result
|
|
4636
|
-
});
|
|
6218
|
+
if (truncated === candidate) {
|
|
4637
6219
|
return null;
|
|
4638
6220
|
}
|
|
4639
|
-
|
|
4640
|
-
} catch (error) {
|
|
4641
|
-
(_c = options == null ? void 0 : options.onError) == null ? void 0 : _c.call(options, "Failed to parse YAML content", { error });
|
|
4642
|
-
return null;
|
|
6221
|
+
candidate = truncated;
|
|
4643
6222
|
}
|
|
4644
6223
|
}
|
|
4645
6224
|
function processToolCallMatch(text, tc, currentIndex, processedElements, options) {
|
|
@@ -4655,7 +6234,7 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
|
|
|
4655
6234
|
if (parsedArgs !== null) {
|
|
4656
6235
|
processedElements.push({
|
|
4657
6236
|
type: "tool-call",
|
|
4658
|
-
toolCallId:
|
|
6237
|
+
toolCallId: generateToolCallId(),
|
|
4659
6238
|
toolName: tc.toolName,
|
|
4660
6239
|
input: JSON.stringify(parsedArgs)
|
|
4661
6240
|
});
|
|
@@ -4668,38 +6247,6 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
|
|
|
4668
6247
|
}
|
|
4669
6248
|
return tc.endIndex;
|
|
4670
6249
|
}
|
|
4671
|
-
function createFlushTextHandler2(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
4672
|
-
return (controller, text) => {
|
|
4673
|
-
const content = text;
|
|
4674
|
-
if (content) {
|
|
4675
|
-
if (!getCurrentTextId()) {
|
|
4676
|
-
const newId = generateId();
|
|
4677
|
-
setCurrentTextId(newId);
|
|
4678
|
-
controller.enqueue({
|
|
4679
|
-
type: "text-start",
|
|
4680
|
-
id: newId
|
|
4681
|
-
});
|
|
4682
|
-
setHasEmittedTextStart(true);
|
|
4683
|
-
}
|
|
4684
|
-
controller.enqueue({
|
|
4685
|
-
type: "text-delta",
|
|
4686
|
-
id: getCurrentTextId(),
|
|
4687
|
-
delta: content
|
|
4688
|
-
});
|
|
4689
|
-
}
|
|
4690
|
-
const currentTextId = getCurrentTextId();
|
|
4691
|
-
if (currentTextId && !text) {
|
|
4692
|
-
if (getHasEmittedTextStart()) {
|
|
4693
|
-
controller.enqueue({
|
|
4694
|
-
type: "text-end",
|
|
4695
|
-
id: currentTextId
|
|
4696
|
-
});
|
|
4697
|
-
setHasEmittedTextStart(false);
|
|
4698
|
-
}
|
|
4699
|
-
setCurrentTextId(null);
|
|
4700
|
-
}
|
|
4701
|
-
};
|
|
4702
|
-
}
|
|
4703
6250
|
function findEarliestToolTag2(buffer, toolNames) {
|
|
4704
6251
|
let bestIndex = -1;
|
|
4705
6252
|
let bestName = "";
|
|
@@ -4707,8 +6254,9 @@ function findEarliestToolTag2(buffer, toolNames) {
|
|
|
4707
6254
|
let bestTagLength = 0;
|
|
4708
6255
|
for (const name of toolNames) {
|
|
4709
6256
|
const openTag = `<${name}>`;
|
|
4710
|
-
const selfTagRegex =
|
|
6257
|
+
const selfTagRegex = getSelfClosingTagPattern2(name);
|
|
4711
6258
|
const idxOpen = buffer.indexOf(openTag);
|
|
6259
|
+
selfTagRegex.lastIndex = 0;
|
|
4712
6260
|
const selfMatch = selfTagRegex.exec(buffer);
|
|
4713
6261
|
const idxSelf = selfMatch ? selfMatch.index : -1;
|
|
4714
6262
|
if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
|
|
@@ -4731,6 +6279,29 @@ function findEarliestToolTag2(buffer, toolNames) {
|
|
|
4731
6279
|
tagLength: bestTagLength
|
|
4732
6280
|
};
|
|
4733
6281
|
}
|
|
6282
|
+
function stripTrailingPartialCloseTag(content, toolName) {
|
|
6283
|
+
const closeTag = `</${toolName}>`;
|
|
6284
|
+
const lastLineBreakIndex = Math.max(
|
|
6285
|
+
content.lastIndexOf("\n"),
|
|
6286
|
+
content.lastIndexOf("\r")
|
|
6287
|
+
);
|
|
6288
|
+
const lineStartIndex = lastLineBreakIndex === -1 ? 0 : lastLineBreakIndex + 1;
|
|
6289
|
+
const trailingLine = content.slice(lineStartIndex);
|
|
6290
|
+
const trimmedTrailingLine = trailingLine.trim();
|
|
6291
|
+
if (trimmedTrailingLine.length === 0 || !trimmedTrailingLine.startsWith("</") || trimmedTrailingLine === closeTag || !closeTag.startsWith(trimmedTrailingLine)) {
|
|
6292
|
+
return content;
|
|
6293
|
+
}
|
|
6294
|
+
const leadingWhitespaceLength = trailingLine.length - trailingLine.trimStart().length;
|
|
6295
|
+
const preservedLeadingWhitespace = trailingLine.slice(
|
|
6296
|
+
0,
|
|
6297
|
+
leadingWhitespaceLength
|
|
6298
|
+
);
|
|
6299
|
+
const contentWithoutPartial = `${content.slice(
|
|
6300
|
+
0,
|
|
6301
|
+
lineStartIndex
|
|
6302
|
+
)}${preservedLeadingWhitespace}`;
|
|
6303
|
+
return contentWithoutPartial.trimEnd();
|
|
6304
|
+
}
|
|
4734
6305
|
var yamlProtocol = (_protocolOptions) => {
|
|
4735
6306
|
return {
|
|
4736
6307
|
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
@@ -4756,18 +6327,32 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
4756
6327
|
}
|
|
4757
6328
|
const processedElements = [];
|
|
4758
6329
|
let currentIndex = 0;
|
|
4759
|
-
|
|
6330
|
+
let parseText = text;
|
|
6331
|
+
let toolCalls = findToolCalls2(parseText, toolNames);
|
|
6332
|
+
if (toolCalls.length === 0) {
|
|
6333
|
+
const repaired = tryRepairXmlSelfClosingRootWithBody(
|
|
6334
|
+
parseText,
|
|
6335
|
+
toolNames
|
|
6336
|
+
);
|
|
6337
|
+
if (repaired) {
|
|
6338
|
+
const repairedCalls = findToolCalls2(repaired, toolNames);
|
|
6339
|
+
if (repairedCalls.length > 0) {
|
|
6340
|
+
parseText = repaired;
|
|
6341
|
+
toolCalls = repairedCalls;
|
|
6342
|
+
}
|
|
6343
|
+
}
|
|
6344
|
+
}
|
|
4760
6345
|
for (const tc of toolCalls) {
|
|
4761
6346
|
currentIndex = processToolCallMatch(
|
|
4762
|
-
|
|
6347
|
+
parseText,
|
|
4763
6348
|
tc,
|
|
4764
6349
|
currentIndex,
|
|
4765
6350
|
processedElements,
|
|
4766
6351
|
options
|
|
4767
6352
|
);
|
|
4768
6353
|
}
|
|
4769
|
-
if (currentIndex <
|
|
4770
|
-
addTextSegment(
|
|
6354
|
+
if (currentIndex < parseText.length) {
|
|
6355
|
+
addTextSegment(parseText.substring(currentIndex), processedElements);
|
|
4771
6356
|
}
|
|
4772
6357
|
return processedElements;
|
|
4773
6358
|
},
|
|
@@ -4777,7 +6362,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
4777
6362
|
let currentToolCall = null;
|
|
4778
6363
|
let currentTextId = null;
|
|
4779
6364
|
let hasEmittedTextStart = false;
|
|
4780
|
-
const flushText =
|
|
6365
|
+
const flushText = createFlushTextHandler(
|
|
4781
6366
|
() => currentTextId,
|
|
4782
6367
|
(newId) => {
|
|
4783
6368
|
currentTextId = newId;
|
|
@@ -4787,33 +6372,128 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
4787
6372
|
hasEmittedTextStart = value;
|
|
4788
6373
|
}
|
|
4789
6374
|
);
|
|
4790
|
-
const
|
|
6375
|
+
const emitToolInputProgress2 = (controller, toolContent) => {
|
|
6376
|
+
if (!currentToolCall) {
|
|
6377
|
+
return;
|
|
6378
|
+
}
|
|
6379
|
+
const parsedArgs = parseYamlContentForStreamProgress(toolContent);
|
|
6380
|
+
if (parsedArgs === null) {
|
|
6381
|
+
return;
|
|
6382
|
+
}
|
|
6383
|
+
const fullInput = JSON.stringify(parsedArgs);
|
|
6384
|
+
if (fullInput === "{}" && toolContent.trim().length === 0) {
|
|
6385
|
+
return;
|
|
6386
|
+
}
|
|
6387
|
+
const prefixCandidate = toIncompleteJsonPrefix(fullInput);
|
|
6388
|
+
emitPrefixDelta({
|
|
6389
|
+
controller,
|
|
6390
|
+
id: currentToolCall.toolCallId,
|
|
6391
|
+
state: currentToolCall,
|
|
6392
|
+
candidate: prefixCandidate
|
|
6393
|
+
});
|
|
6394
|
+
};
|
|
6395
|
+
const processToolCallEnd = (controller, toolContent, toolName, toolCallId) => {
|
|
4791
6396
|
var _a;
|
|
4792
6397
|
const parsedArgs = parseYamlContent(toolContent, options);
|
|
4793
6398
|
flushText(controller);
|
|
4794
6399
|
if (parsedArgs !== null) {
|
|
6400
|
+
const finalInput = JSON.stringify(parsedArgs);
|
|
6401
|
+
if (currentToolCall && currentToolCall.toolCallId === toolCallId) {
|
|
6402
|
+
emitFinalRemainder({
|
|
6403
|
+
controller,
|
|
6404
|
+
id: toolCallId,
|
|
6405
|
+
state: currentToolCall,
|
|
6406
|
+
finalFullJson: finalInput,
|
|
6407
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
6408
|
+
});
|
|
6409
|
+
}
|
|
6410
|
+
controller.enqueue({
|
|
6411
|
+
type: "tool-input-end",
|
|
6412
|
+
id: toolCallId
|
|
6413
|
+
});
|
|
4795
6414
|
controller.enqueue({
|
|
4796
6415
|
type: "tool-call",
|
|
4797
|
-
toolCallId
|
|
6416
|
+
toolCallId,
|
|
4798
6417
|
toolName,
|
|
4799
|
-
input:
|
|
6418
|
+
input: finalInput
|
|
4800
6419
|
});
|
|
4801
6420
|
} else {
|
|
6421
|
+
controller.enqueue({
|
|
6422
|
+
type: "tool-input-end",
|
|
6423
|
+
id: toolCallId
|
|
6424
|
+
});
|
|
4802
6425
|
const original = `<${toolName}>${toolContent}</${toolName}>`;
|
|
4803
6426
|
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
|
|
4804
6427
|
toolCall: original
|
|
4805
6428
|
});
|
|
4806
|
-
|
|
6429
|
+
if (shouldEmitRawToolCallTextOnError3(options)) {
|
|
6430
|
+
flushText(controller, original);
|
|
6431
|
+
}
|
|
6432
|
+
}
|
|
6433
|
+
};
|
|
6434
|
+
const finalizeUnclosedToolCall = (controller) => {
|
|
6435
|
+
var _a;
|
|
6436
|
+
if (!currentToolCall) {
|
|
6437
|
+
return;
|
|
4807
6438
|
}
|
|
6439
|
+
emitToolInputProgress2(controller, buffer);
|
|
6440
|
+
const { name: toolName, toolCallId } = currentToolCall;
|
|
6441
|
+
const reconciledBuffer = stripTrailingPartialCloseTag(buffer, toolName);
|
|
6442
|
+
const parsedArgs = parseYamlContent(reconciledBuffer, options);
|
|
6443
|
+
flushText(controller);
|
|
6444
|
+
if (parsedArgs !== null) {
|
|
6445
|
+
const finalInput = JSON.stringify(parsedArgs);
|
|
6446
|
+
emitFinalRemainder({
|
|
6447
|
+
controller,
|
|
6448
|
+
id: toolCallId,
|
|
6449
|
+
state: currentToolCall,
|
|
6450
|
+
finalFullJson: finalInput,
|
|
6451
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
6452
|
+
});
|
|
6453
|
+
controller.enqueue({
|
|
6454
|
+
type: "tool-input-end",
|
|
6455
|
+
id: toolCallId
|
|
6456
|
+
});
|
|
6457
|
+
controller.enqueue({
|
|
6458
|
+
type: "tool-call",
|
|
6459
|
+
toolCallId,
|
|
6460
|
+
toolName,
|
|
6461
|
+
input: finalInput
|
|
6462
|
+
});
|
|
6463
|
+
} else {
|
|
6464
|
+
controller.enqueue({
|
|
6465
|
+
type: "tool-input-end",
|
|
6466
|
+
id: toolCallId
|
|
6467
|
+
});
|
|
6468
|
+
const unfinishedContent = `<${toolName}>${buffer}`;
|
|
6469
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
6470
|
+
options,
|
|
6471
|
+
"Could not complete streaming YAML tool call at finish.",
|
|
6472
|
+
{ toolCall: unfinishedContent }
|
|
6473
|
+
);
|
|
6474
|
+
if (shouldEmitRawToolCallTextOnError3(options)) {
|
|
6475
|
+
flushText(controller, unfinishedContent);
|
|
6476
|
+
}
|
|
6477
|
+
}
|
|
6478
|
+
buffer = "";
|
|
6479
|
+
currentToolCall = null;
|
|
4808
6480
|
};
|
|
4809
6481
|
const handlePendingToolCall = (controller, endTag, toolName) => {
|
|
6482
|
+
var _a;
|
|
4810
6483
|
const endIdx = buffer.indexOf(endTag);
|
|
4811
6484
|
if (endIdx === -1) {
|
|
6485
|
+
emitToolInputProgress2(controller, buffer);
|
|
4812
6486
|
return false;
|
|
4813
6487
|
}
|
|
4814
6488
|
const content = buffer.substring(0, endIdx);
|
|
6489
|
+
emitToolInputProgress2(controller, content);
|
|
4815
6490
|
buffer = buffer.substring(endIdx + endTag.length);
|
|
4816
|
-
processToolCallEnd(
|
|
6491
|
+
processToolCallEnd(
|
|
6492
|
+
controller,
|
|
6493
|
+
content,
|
|
6494
|
+
toolName,
|
|
6495
|
+
(_a = currentToolCall == null ? void 0 : currentToolCall.toolCallId) != null ? _a : generateToolCallId()
|
|
6496
|
+
);
|
|
4817
6497
|
currentToolCall = null;
|
|
4818
6498
|
return true;
|
|
4819
6499
|
};
|
|
@@ -4830,13 +6510,35 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
4830
6510
|
if (tagIndex > 0) {
|
|
4831
6511
|
flushText(controller, buffer.substring(0, tagIndex));
|
|
4832
6512
|
}
|
|
6513
|
+
flushText(controller);
|
|
4833
6514
|
if (selfClosing) {
|
|
4834
6515
|
buffer = buffer.substring(tagIndex + tagLength);
|
|
4835
|
-
|
|
6516
|
+
const toolCallId = generateToolCallId();
|
|
6517
|
+
currentToolCall = {
|
|
6518
|
+
name: tagName,
|
|
6519
|
+
toolCallId,
|
|
6520
|
+
emittedInput: ""
|
|
6521
|
+
};
|
|
6522
|
+
controller.enqueue({
|
|
6523
|
+
type: "tool-input-start",
|
|
6524
|
+
id: toolCallId,
|
|
6525
|
+
toolName: tagName
|
|
6526
|
+
});
|
|
6527
|
+
processToolCallEnd(controller, "", tagName, toolCallId);
|
|
6528
|
+
currentToolCall = null;
|
|
4836
6529
|
} else {
|
|
4837
6530
|
const startTag = `<${tagName}>`;
|
|
4838
6531
|
buffer = buffer.substring(tagIndex + startTag.length);
|
|
4839
|
-
currentToolCall = {
|
|
6532
|
+
currentToolCall = {
|
|
6533
|
+
name: tagName,
|
|
6534
|
+
toolCallId: generateToolCallId(),
|
|
6535
|
+
emittedInput: ""
|
|
6536
|
+
};
|
|
6537
|
+
controller.enqueue({
|
|
6538
|
+
type: "tool-input-start",
|
|
6539
|
+
id: currentToolCall.toolCallId,
|
|
6540
|
+
toolName: tagName
|
|
6541
|
+
});
|
|
4840
6542
|
}
|
|
4841
6543
|
};
|
|
4842
6544
|
const processBuffer = (controller) => {
|
|
@@ -4863,8 +6565,19 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
4863
6565
|
return new TransformStream({
|
|
4864
6566
|
transform(chunk, controller) {
|
|
4865
6567
|
var _a;
|
|
6568
|
+
if (chunk.type === "finish") {
|
|
6569
|
+
if (currentToolCall) {
|
|
6570
|
+
finalizeUnclosedToolCall(controller);
|
|
6571
|
+
} else if (buffer) {
|
|
6572
|
+
flushText(controller, buffer);
|
|
6573
|
+
buffer = "";
|
|
6574
|
+
}
|
|
6575
|
+
flushText(controller);
|
|
6576
|
+
controller.enqueue(chunk);
|
|
6577
|
+
return;
|
|
6578
|
+
}
|
|
4866
6579
|
if (chunk.type !== "text-delta") {
|
|
4867
|
-
if (buffer) {
|
|
6580
|
+
if (!currentToolCall && buffer) {
|
|
4868
6581
|
flushText(controller, buffer);
|
|
4869
6582
|
buffer = "";
|
|
4870
6583
|
}
|
|
@@ -4877,10 +6590,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
4877
6590
|
},
|
|
4878
6591
|
flush(controller) {
|
|
4879
6592
|
if (currentToolCall) {
|
|
4880
|
-
|
|
4881
|
-
flushText(controller, unfinishedContent);
|
|
4882
|
-
buffer = "";
|
|
4883
|
-
currentToolCall = null;
|
|
6593
|
+
finalizeUnclosedToolCall(controller);
|
|
4884
6594
|
} else if (buffer) {
|
|
4885
6595
|
flushText(controller, buffer);
|
|
4886
6596
|
buffer = "";
|
|
@@ -4986,17 +6696,56 @@ function encodeOriginalTools(tools) {
|
|
|
4986
6696
|
inputSchema: JSON.stringify(t.inputSchema)
|
|
4987
6697
|
}))) || [];
|
|
4988
6698
|
}
|
|
4989
|
-
function decodeOriginalTools(originalTools) {
|
|
6699
|
+
function decodeOriginalTools(originalTools, options) {
|
|
6700
|
+
var _a, _b, _c;
|
|
4990
6701
|
if (!originalTools) {
|
|
4991
6702
|
return [];
|
|
4992
6703
|
}
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
6704
|
+
const decodedTools = [];
|
|
6705
|
+
for (const [index, tool] of originalTools.entries()) {
|
|
6706
|
+
if (!tool || typeof tool.name !== "string") {
|
|
6707
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Invalid originalTools entry: missing tool name", {
|
|
6708
|
+
index,
|
|
6709
|
+
tool
|
|
6710
|
+
});
|
|
6711
|
+
continue;
|
|
6712
|
+
}
|
|
6713
|
+
if (typeof tool.inputSchema !== "string") {
|
|
6714
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
6715
|
+
options,
|
|
6716
|
+
"Invalid originalTools entry: inputSchema must be a string",
|
|
6717
|
+
{
|
|
6718
|
+
index,
|
|
6719
|
+
toolName: tool.name
|
|
6720
|
+
}
|
|
6721
|
+
);
|
|
6722
|
+
continue;
|
|
6723
|
+
}
|
|
6724
|
+
try {
|
|
6725
|
+
decodedTools.push({
|
|
6726
|
+
type: "function",
|
|
6727
|
+
name: tool.name,
|
|
6728
|
+
inputSchema: JSON.parse(tool.inputSchema)
|
|
6729
|
+
});
|
|
6730
|
+
} catch (error) {
|
|
6731
|
+
(_c = options == null ? void 0 : options.onError) == null ? void 0 : _c.call(
|
|
6732
|
+
options,
|
|
6733
|
+
"Failed to decode originalTools input schema, using permissive fallback schema",
|
|
6734
|
+
{
|
|
6735
|
+
index,
|
|
6736
|
+
toolName: tool.name,
|
|
6737
|
+
inputSchema: tool.inputSchema,
|
|
6738
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6739
|
+
}
|
|
6740
|
+
);
|
|
6741
|
+
decodedTools.push({
|
|
6742
|
+
type: "function",
|
|
6743
|
+
name: tool.name,
|
|
6744
|
+
inputSchema: { type: "object" }
|
|
6745
|
+
});
|
|
6746
|
+
}
|
|
6747
|
+
}
|
|
6748
|
+
return decodedTools;
|
|
5000
6749
|
}
|
|
5001
6750
|
function isToolChoiceActive(params) {
|
|
5002
6751
|
var _a, _b, _c;
|
|
@@ -5004,25 +6753,336 @@ function isToolChoiceActive(params) {
|
|
|
5004
6753
|
return !!(typeof params.providerOptions === "object" && params.providerOptions !== null && typeof ((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) === "object" && toolChoice && typeof toolChoice === "object" && (toolChoice.type === "tool" || toolChoice.type === "required"));
|
|
5005
6754
|
}
|
|
5006
6755
|
|
|
5007
|
-
// src/
|
|
5008
|
-
|
|
5009
|
-
|
|
6756
|
+
// src/core/utils/generated-text-json-recovery.ts
|
|
6757
|
+
function isRecord(value) {
|
|
6758
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6759
|
+
}
|
|
6760
|
+
function safeStringify2(value) {
|
|
6761
|
+
try {
|
|
6762
|
+
return JSON.stringify(value != null ? value : {});
|
|
6763
|
+
} catch (e) {
|
|
6764
|
+
return "{}";
|
|
6765
|
+
}
|
|
6766
|
+
}
|
|
6767
|
+
function parseJsonCandidate(candidateText) {
|
|
6768
|
+
try {
|
|
6769
|
+
return parse(candidateText);
|
|
6770
|
+
} catch (e) {
|
|
6771
|
+
return void 0;
|
|
6772
|
+
}
|
|
6773
|
+
}
|
|
6774
|
+
function extractCodeBlockCandidates(text) {
|
|
6775
|
+
var _a, _b;
|
|
6776
|
+
const codeBlockRegex = /```(?:json|yaml|xml)?\s*([\s\S]*?)```/gi;
|
|
6777
|
+
const candidates = [];
|
|
6778
|
+
let match;
|
|
6779
|
+
while (true) {
|
|
6780
|
+
match = codeBlockRegex.exec(text);
|
|
6781
|
+
if (!match) {
|
|
6782
|
+
break;
|
|
6783
|
+
}
|
|
6784
|
+
const body = (_a = match[1]) == null ? void 0 : _a.trim();
|
|
6785
|
+
if (body) {
|
|
6786
|
+
const startIndex = (_b = match.index) != null ? _b : 0;
|
|
6787
|
+
const endIndex = startIndex + match[0].length;
|
|
6788
|
+
candidates.push({
|
|
6789
|
+
text: body,
|
|
6790
|
+
startIndex,
|
|
6791
|
+
endIndex
|
|
6792
|
+
});
|
|
6793
|
+
}
|
|
6794
|
+
}
|
|
6795
|
+
return candidates;
|
|
6796
|
+
}
|
|
6797
|
+
function scanJsonChar(state, char) {
|
|
6798
|
+
if (state.inString) {
|
|
6799
|
+
if (state.escaping) {
|
|
6800
|
+
return { ...state, escaping: false };
|
|
6801
|
+
}
|
|
6802
|
+
if (char === "\\") {
|
|
6803
|
+
return { ...state, escaping: true };
|
|
6804
|
+
}
|
|
6805
|
+
if (char === '"') {
|
|
6806
|
+
return { ...state, inString: false };
|
|
6807
|
+
}
|
|
6808
|
+
return state;
|
|
6809
|
+
}
|
|
6810
|
+
if (char === '"') {
|
|
6811
|
+
return { ...state, inString: true };
|
|
6812
|
+
}
|
|
6813
|
+
if (char === "{") {
|
|
6814
|
+
return { ...state, depth: state.depth + 1 };
|
|
6815
|
+
}
|
|
6816
|
+
if (char === "}") {
|
|
6817
|
+
return { ...state, depth: Math.max(0, state.depth - 1) };
|
|
6818
|
+
}
|
|
6819
|
+
return state;
|
|
6820
|
+
}
|
|
6821
|
+
function extractBalancedJsonObjects(text) {
|
|
6822
|
+
const maxCandidateLength = 1e4;
|
|
6823
|
+
const candidates = [];
|
|
6824
|
+
let state = { depth: 0, inString: false, escaping: false };
|
|
6825
|
+
let currentStart = null;
|
|
6826
|
+
let ignoreCurrent = false;
|
|
6827
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
6828
|
+
const char = text[index];
|
|
6829
|
+
if (!state.inString && char === "{" && state.depth === 0) {
|
|
6830
|
+
currentStart = index;
|
|
6831
|
+
ignoreCurrent = false;
|
|
6832
|
+
}
|
|
6833
|
+
state = scanJsonChar(state, char);
|
|
6834
|
+
if (currentStart !== null && !ignoreCurrent && index - currentStart + 1 > maxCandidateLength) {
|
|
6835
|
+
ignoreCurrent = true;
|
|
6836
|
+
}
|
|
6837
|
+
if (!state.inString && char === "}" && state.depth === 0) {
|
|
6838
|
+
if (currentStart !== null && !ignoreCurrent) {
|
|
6839
|
+
const endIndex = index + 1;
|
|
6840
|
+
const candidate = text.slice(currentStart, endIndex);
|
|
6841
|
+
if (candidate.length > 1) {
|
|
6842
|
+
candidates.push({
|
|
6843
|
+
text: candidate,
|
|
6844
|
+
startIndex: currentStart,
|
|
6845
|
+
endIndex
|
|
6846
|
+
});
|
|
6847
|
+
}
|
|
6848
|
+
}
|
|
6849
|
+
currentStart = null;
|
|
6850
|
+
ignoreCurrent = false;
|
|
6851
|
+
}
|
|
6852
|
+
}
|
|
6853
|
+
return candidates;
|
|
6854
|
+
}
|
|
6855
|
+
function extractTaggedToolCallCandidates(rawText) {
|
|
6856
|
+
var _a, _b;
|
|
6857
|
+
const toolCallRegex = /<tool_call>([\s\S]*?)<\/tool_call>/gi;
|
|
6858
|
+
const candidates = [];
|
|
6859
|
+
let match;
|
|
6860
|
+
while (true) {
|
|
6861
|
+
match = toolCallRegex.exec(rawText);
|
|
6862
|
+
if (!match) {
|
|
6863
|
+
break;
|
|
6864
|
+
}
|
|
6865
|
+
const body = (_a = match[1]) == null ? void 0 : _a.trim();
|
|
6866
|
+
if (!body) {
|
|
6867
|
+
continue;
|
|
6868
|
+
}
|
|
6869
|
+
const startIndex = (_b = match.index) != null ? _b : 0;
|
|
6870
|
+
const endIndex = startIndex + match[0].length;
|
|
6871
|
+
candidates.push({
|
|
6872
|
+
text: body,
|
|
6873
|
+
startIndex,
|
|
6874
|
+
endIndex
|
|
6875
|
+
});
|
|
6876
|
+
}
|
|
6877
|
+
return candidates;
|
|
6878
|
+
}
|
|
6879
|
+
function extractJsonLikeCandidates(rawText) {
|
|
6880
|
+
return mergeJsonCandidatesByStart(
|
|
6881
|
+
extractTaggedToolCallCandidates(rawText),
|
|
6882
|
+
extractCodeBlockCandidates(rawText),
|
|
6883
|
+
extractBalancedJsonObjects(rawText)
|
|
6884
|
+
);
|
|
6885
|
+
}
|
|
6886
|
+
function mergeJsonCandidatesByStart(tagged, codeBlocks, balanced) {
|
|
6887
|
+
return [...tagged, ...codeBlocks, ...balanced].sort(
|
|
6888
|
+
(a, b) => a.startIndex !== b.startIndex ? a.startIndex - b.startIndex : b.endIndex - a.endIndex
|
|
6889
|
+
);
|
|
6890
|
+
}
|
|
6891
|
+
function toToolCallPart(candidate) {
|
|
6892
|
+
return {
|
|
6893
|
+
type: "tool-call",
|
|
6894
|
+
toolCallId: generateToolCallId(),
|
|
6895
|
+
toolName: candidate.toolName,
|
|
6896
|
+
input: candidate.input
|
|
6897
|
+
};
|
|
6898
|
+
}
|
|
6899
|
+
function toRecoveredParts(text, candidate, toolCallPart) {
|
|
6900
|
+
const out = [];
|
|
6901
|
+
const prefix = text.slice(0, candidate.startIndex);
|
|
6902
|
+
if (prefix.length > 0) {
|
|
6903
|
+
out.push({ type: "text", text: prefix });
|
|
6904
|
+
}
|
|
6905
|
+
out.push(toolCallPart);
|
|
6906
|
+
const suffix = text.slice(candidate.endIndex);
|
|
6907
|
+
if (suffix.length > 0) {
|
|
6908
|
+
out.push({ type: "text", text: suffix });
|
|
6909
|
+
}
|
|
6910
|
+
return out;
|
|
6911
|
+
}
|
|
6912
|
+
function parseAsToolPayload(payload, tools) {
|
|
6913
|
+
if (!isRecord(payload)) {
|
|
6914
|
+
return null;
|
|
6915
|
+
}
|
|
6916
|
+
const toolName = typeof payload.name === "string" && payload.name.trim().length > 0 ? payload.name.trim() : null;
|
|
6917
|
+
if (!toolName) {
|
|
6918
|
+
return null;
|
|
6919
|
+
}
|
|
6920
|
+
if (!tools.some((tool) => tool.name === toolName)) {
|
|
6921
|
+
return null;
|
|
6922
|
+
}
|
|
6923
|
+
const rawArgs = Object.hasOwn(payload, "arguments") ? payload.arguments : {};
|
|
6924
|
+
if (!isRecord(rawArgs)) {
|
|
6925
|
+
return null;
|
|
6926
|
+
}
|
|
6927
|
+
return {
|
|
6928
|
+
toolName,
|
|
6929
|
+
input: safeStringify2(rawArgs)
|
|
6930
|
+
};
|
|
6931
|
+
}
|
|
6932
|
+
function isLikelyArgumentsShapeForTool(args, tool) {
|
|
6933
|
+
const unwrapped = unwrapJsonSchema(tool.inputSchema);
|
|
6934
|
+
if (!isRecord(unwrapped)) {
|
|
6935
|
+
return false;
|
|
6936
|
+
}
|
|
6937
|
+
if (getSchemaType(unwrapped) !== "object") {
|
|
6938
|
+
return false;
|
|
6939
|
+
}
|
|
6940
|
+
const properties = unwrapped.properties;
|
|
6941
|
+
if (!isRecord(properties)) {
|
|
6942
|
+
return false;
|
|
6943
|
+
}
|
|
6944
|
+
const keys = Object.keys(args);
|
|
6945
|
+
if (keys.length === 0) {
|
|
6946
|
+
return false;
|
|
6947
|
+
}
|
|
6948
|
+
const knownKeys = keys.filter((key) => Object.hasOwn(properties, key));
|
|
6949
|
+
if (knownKeys.length === 0) {
|
|
6950
|
+
return false;
|
|
6951
|
+
}
|
|
6952
|
+
if (unwrapped.additionalProperties === false && knownKeys.length !== keys.length) {
|
|
6953
|
+
return false;
|
|
6954
|
+
}
|
|
6955
|
+
return true;
|
|
6956
|
+
}
|
|
6957
|
+
function parseAsArgumentsOnly(payload, tools) {
|
|
6958
|
+
if (tools.length !== 1) {
|
|
6959
|
+
return null;
|
|
6960
|
+
}
|
|
6961
|
+
if (!isRecord(payload)) {
|
|
6962
|
+
return null;
|
|
6963
|
+
}
|
|
6964
|
+
const hasNameEnvelope = Object.hasOwn(payload, "name") && typeof payload.name === "string" && payload.name.length > 0;
|
|
6965
|
+
const hasArgumentsEnvelope = Object.hasOwn(payload, "arguments") && (typeof payload.arguments === "string" || isRecord(payload.arguments));
|
|
6966
|
+
if (hasNameEnvelope || hasArgumentsEnvelope) {
|
|
6967
|
+
return null;
|
|
6968
|
+
}
|
|
6969
|
+
const tool = tools[0];
|
|
6970
|
+
if (!isLikelyArgumentsShapeForTool(payload, tool)) {
|
|
6971
|
+
return null;
|
|
6972
|
+
}
|
|
6973
|
+
return {
|
|
6974
|
+
toolName: tool.name,
|
|
6975
|
+
input: safeStringify2(payload)
|
|
6976
|
+
};
|
|
6977
|
+
}
|
|
6978
|
+
function recoverToolCallFromJsonCandidates(text, tools) {
|
|
6979
|
+
if (tools.length === 0) {
|
|
6980
|
+
return null;
|
|
6981
|
+
}
|
|
6982
|
+
const jsonCandidates = extractJsonLikeCandidates(text);
|
|
6983
|
+
for (const jsonCandidate of jsonCandidates) {
|
|
6984
|
+
const parsed = parseJsonCandidate(jsonCandidate.text);
|
|
6985
|
+
if (parsed === void 0) {
|
|
6986
|
+
continue;
|
|
6987
|
+
}
|
|
6988
|
+
const toolPayload = parseAsToolPayload(parsed, tools);
|
|
6989
|
+
if (toolPayload) {
|
|
6990
|
+
return toRecoveredParts(text, jsonCandidate, toToolCallPart(toolPayload));
|
|
6991
|
+
}
|
|
6992
|
+
const argsPayload = parseAsArgumentsOnly(parsed, tools);
|
|
6993
|
+
if (argsPayload) {
|
|
6994
|
+
return toRecoveredParts(text, jsonCandidate, toToolCallPart(argsPayload));
|
|
6995
|
+
}
|
|
6996
|
+
}
|
|
6997
|
+
return null;
|
|
6998
|
+
}
|
|
6999
|
+
|
|
7000
|
+
// src/core/utils/tool-call-coercion.ts
|
|
7001
|
+
function coerceToolCallInput(toolName, input, tools) {
|
|
5010
7002
|
var _a;
|
|
7003
|
+
let args = {};
|
|
7004
|
+
if (typeof input === "string") {
|
|
7005
|
+
try {
|
|
7006
|
+
args = JSON.parse(input);
|
|
7007
|
+
} catch (e) {
|
|
7008
|
+
return;
|
|
7009
|
+
}
|
|
7010
|
+
} else if (input && typeof input === "object") {
|
|
7011
|
+
args = input;
|
|
7012
|
+
} else {
|
|
7013
|
+
return;
|
|
7014
|
+
}
|
|
7015
|
+
const schema = (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
7016
|
+
const coerced = coerceBySchema(args, schema);
|
|
7017
|
+
return JSON.stringify(coerced != null ? coerced : {});
|
|
7018
|
+
}
|
|
7019
|
+
function coerceToolCallPart(part, tools) {
|
|
7020
|
+
const coercedInput = coerceToolCallInput(part.toolName, part.input, tools);
|
|
7021
|
+
if (coercedInput === void 0) {
|
|
7022
|
+
return part;
|
|
7023
|
+
}
|
|
7024
|
+
return {
|
|
7025
|
+
...part,
|
|
7026
|
+
input: coercedInput
|
|
7027
|
+
};
|
|
7028
|
+
}
|
|
7029
|
+
|
|
7030
|
+
// src/core/utils/tool-choice.ts
|
|
7031
|
+
function ensureNonEmptyToolName(name) {
|
|
7032
|
+
if (typeof name !== "string") {
|
|
7033
|
+
return "unknown";
|
|
7034
|
+
}
|
|
7035
|
+
const trimmed = name.trim();
|
|
7036
|
+
return trimmed.length > 0 ? trimmed : "unknown";
|
|
7037
|
+
}
|
|
7038
|
+
function safeStringify3(value) {
|
|
7039
|
+
try {
|
|
7040
|
+
return JSON.stringify(value != null ? value : {});
|
|
7041
|
+
} catch (e) {
|
|
7042
|
+
return "{}";
|
|
7043
|
+
}
|
|
7044
|
+
}
|
|
7045
|
+
function parseToolChoicePayload({
|
|
7046
|
+
text,
|
|
7047
|
+
tools,
|
|
7048
|
+
onError,
|
|
7049
|
+
errorMessage
|
|
7050
|
+
}) {
|
|
7051
|
+
let parsed;
|
|
5011
7052
|
try {
|
|
5012
|
-
|
|
7053
|
+
parsed = JSON.parse(text);
|
|
5013
7054
|
} catch (error) {
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
7055
|
+
onError == null ? void 0 : onError(errorMessage, {
|
|
7056
|
+
text,
|
|
7057
|
+
error: error instanceof Error ? error.message : String(error)
|
|
7058
|
+
});
|
|
7059
|
+
return { toolName: "unknown", input: "{}" };
|
|
7060
|
+
}
|
|
7061
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
7062
|
+
onError == null ? void 0 : onError("toolChoice JSON payload must be an object", {
|
|
7063
|
+
parsedType: typeof parsed,
|
|
7064
|
+
parsed
|
|
7065
|
+
});
|
|
7066
|
+
return { toolName: "unknown", input: "{}" };
|
|
7067
|
+
}
|
|
7068
|
+
const payload = parsed;
|
|
7069
|
+
const toolName = ensureNonEmptyToolName(payload.name);
|
|
7070
|
+
const rawArgs = Object.hasOwn(payload, "arguments") ? payload.arguments : {};
|
|
7071
|
+
if (rawArgs == null || typeof rawArgs !== "object" || Array.isArray(rawArgs)) {
|
|
7072
|
+
onError == null ? void 0 : onError("toolChoice arguments must be a JSON object", {
|
|
7073
|
+
toolName,
|
|
7074
|
+
arguments: rawArgs
|
|
7075
|
+
});
|
|
7076
|
+
return { toolName, input: "{}" };
|
|
5024
7077
|
}
|
|
7078
|
+
const coercedInput = coerceToolCallInput(toolName, rawArgs, tools);
|
|
7079
|
+
return {
|
|
7080
|
+
toolName,
|
|
7081
|
+
input: coercedInput != null ? coercedInput : safeStringify3(rawArgs)
|
|
7082
|
+
};
|
|
5025
7083
|
}
|
|
7084
|
+
|
|
7085
|
+
// src/generate-handler.ts
|
|
5026
7086
|
function logDebugSummary(debugSummary, toolCall, originText) {
|
|
5027
7087
|
if (debugSummary) {
|
|
5028
7088
|
debugSummary.originalText = originText;
|
|
@@ -5036,25 +7096,34 @@ function logDebugSummary(debugSummary, toolCall, originText) {
|
|
|
5036
7096
|
logParsedSummary({ toolCalls: [toolCall], originalText: originText });
|
|
5037
7097
|
}
|
|
5038
7098
|
}
|
|
5039
|
-
async function handleToolChoice(doGenerate, params) {
|
|
5040
|
-
var _a, _b, _c;
|
|
7099
|
+
async function handleToolChoice(doGenerate, params, tools) {
|
|
7100
|
+
var _a, _b, _c, _d;
|
|
5041
7101
|
const result = await doGenerate();
|
|
5042
7102
|
const first = (_a = result.content) == null ? void 0 : _a[0];
|
|
5043
|
-
|
|
7103
|
+
const onError = (_b = extractOnErrorOption(params.providerOptions)) == null ? void 0 : _b.onError;
|
|
7104
|
+
let toolName = "unknown";
|
|
7105
|
+
let input = "{}";
|
|
5044
7106
|
if (first && first.type === "text") {
|
|
5045
7107
|
if (getDebugLevel() === "parse") {
|
|
5046
7108
|
logRawChunk(first.text);
|
|
5047
7109
|
}
|
|
5048
|
-
parsed =
|
|
7110
|
+
const parsed = parseToolChoicePayload({
|
|
7111
|
+
text: first.text,
|
|
7112
|
+
tools,
|
|
7113
|
+
onError,
|
|
7114
|
+
errorMessage: "Failed to parse toolChoice JSON from generated model output"
|
|
7115
|
+
});
|
|
7116
|
+
toolName = parsed.toolName;
|
|
7117
|
+
input = parsed.input;
|
|
5049
7118
|
}
|
|
5050
7119
|
const toolCall = {
|
|
5051
7120
|
type: "tool-call",
|
|
5052
|
-
toolCallId: (
|
|
5053
|
-
toolName
|
|
5054
|
-
input
|
|
7121
|
+
toolCallId: generateToolCallId(),
|
|
7122
|
+
toolName,
|
|
7123
|
+
input
|
|
5055
7124
|
};
|
|
5056
7125
|
const originText = first && first.type === "text" ? first.text : "";
|
|
5057
|
-
const debugSummary = (
|
|
7126
|
+
const debugSummary = (_d = (_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) == null ? void 0 : _d.debugSummary;
|
|
5058
7127
|
logDebugSummary(debugSummary, toolCall, originText);
|
|
5059
7128
|
return {
|
|
5060
7129
|
...result,
|
|
@@ -5069,7 +7138,7 @@ function parseContent(content, protocol, tools, providerOptions) {
|
|
|
5069
7138
|
if (getDebugLevel() === "stream") {
|
|
5070
7139
|
logRawChunk(contentItem.text);
|
|
5071
7140
|
}
|
|
5072
|
-
|
|
7141
|
+
const parsedByProtocol = protocol.parseGeneratedText({
|
|
5073
7142
|
text: contentItem.text,
|
|
5074
7143
|
tools,
|
|
5075
7144
|
options: {
|
|
@@ -5077,9 +7146,20 @@ function parseContent(content, protocol, tools, providerOptions) {
|
|
|
5077
7146
|
...providerOptions == null ? void 0 : providerOptions.toolCallMiddleware
|
|
5078
7147
|
}
|
|
5079
7148
|
});
|
|
7149
|
+
const hasToolCall = parsedByProtocol.some(
|
|
7150
|
+
(part) => part.type === "tool-call"
|
|
7151
|
+
);
|
|
7152
|
+
if (hasToolCall) {
|
|
7153
|
+
return parsedByProtocol;
|
|
7154
|
+
}
|
|
7155
|
+
const recoveredFromJson = recoverToolCallFromJsonCandidates(
|
|
7156
|
+
contentItem.text,
|
|
7157
|
+
tools
|
|
7158
|
+
);
|
|
7159
|
+
return recoveredFromJson != null ? recoveredFromJson : parsedByProtocol;
|
|
5080
7160
|
});
|
|
5081
7161
|
return parsed.map(
|
|
5082
|
-
(part) =>
|
|
7162
|
+
(part) => part.type === "tool-call" ? coerceToolCallPart(part, tools) : part
|
|
5083
7163
|
);
|
|
5084
7164
|
}
|
|
5085
7165
|
function logParsedContent(content) {
|
|
@@ -5122,12 +7202,14 @@ async function wrapGenerate({
|
|
|
5122
7202
|
params
|
|
5123
7203
|
}) {
|
|
5124
7204
|
var _a, _b;
|
|
5125
|
-
|
|
5126
|
-
return handleToolChoice(doGenerate, params);
|
|
5127
|
-
}
|
|
7205
|
+
const onError = extractOnErrorOption(params.providerOptions);
|
|
5128
7206
|
const tools = originalToolsSchema.decode(
|
|
5129
|
-
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools
|
|
7207
|
+
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools,
|
|
7208
|
+
onError
|
|
5130
7209
|
);
|
|
7210
|
+
if (isToolChoiceActive(params)) {
|
|
7211
|
+
return handleToolChoice(doGenerate, params, tools);
|
|
7212
|
+
}
|
|
5131
7213
|
const result = await doGenerate();
|
|
5132
7214
|
if (result.content.length === 0) {
|
|
5133
7215
|
return result;
|
|
@@ -5151,28 +7233,6 @@ async function wrapGenerate({
|
|
|
5151
7233
|
content: newContent
|
|
5152
7234
|
};
|
|
5153
7235
|
}
|
|
5154
|
-
function fixToolCallWithSchema(part, tools) {
|
|
5155
|
-
var _a;
|
|
5156
|
-
if (part.type !== "tool-call") {
|
|
5157
|
-
return part;
|
|
5158
|
-
}
|
|
5159
|
-
let args = {};
|
|
5160
|
-
if (typeof part.input === "string") {
|
|
5161
|
-
try {
|
|
5162
|
-
args = JSON.parse(part.input);
|
|
5163
|
-
} catch (e) {
|
|
5164
|
-
return part;
|
|
5165
|
-
}
|
|
5166
|
-
} else if (part.input && typeof part.input === "object") {
|
|
5167
|
-
args = part.input;
|
|
5168
|
-
}
|
|
5169
|
-
const schema = (_a = tools.find((t) => t.name === part.toolName)) == null ? void 0 : _a.inputSchema;
|
|
5170
|
-
const coerced = coerceBySchema(args, schema);
|
|
5171
|
-
return {
|
|
5172
|
-
...part,
|
|
5173
|
-
input: JSON.stringify(coerced != null ? coerced : {})
|
|
5174
|
-
};
|
|
5175
|
-
}
|
|
5176
7236
|
|
|
5177
7237
|
// src/core/prompts/hermes-system-prompt.ts
|
|
5178
7238
|
function hermesSystemPromptTemplate(tools) {
|
|
@@ -5568,7 +7628,6 @@ unit: celsius
|
|
|
5568
7628
|
}
|
|
5569
7629
|
|
|
5570
7630
|
// src/stream-handler.ts
|
|
5571
|
-
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
5572
7631
|
async function wrapStream({
|
|
5573
7632
|
protocol,
|
|
5574
7633
|
doStream,
|
|
@@ -5576,19 +7635,22 @@ async function wrapStream({
|
|
|
5576
7635
|
params
|
|
5577
7636
|
}) {
|
|
5578
7637
|
var _a, _b, _c;
|
|
7638
|
+
const onErrorOptions = extractOnErrorOption(params.providerOptions);
|
|
7639
|
+
const tools = originalToolsSchema.decode(
|
|
7640
|
+
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools,
|
|
7641
|
+
onErrorOptions
|
|
7642
|
+
);
|
|
5579
7643
|
if (isToolChoiceActive(params)) {
|
|
5580
7644
|
return toolChoiceStream({
|
|
5581
7645
|
doGenerate,
|
|
5582
|
-
|
|
7646
|
+
tools,
|
|
7647
|
+
options: onErrorOptions
|
|
5583
7648
|
});
|
|
5584
7649
|
}
|
|
5585
7650
|
const { stream, ...rest } = await doStream();
|
|
5586
7651
|
const debugLevel = getDebugLevel();
|
|
5587
|
-
const tools = originalToolsSchema.decode(
|
|
5588
|
-
(_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools
|
|
5589
|
-
);
|
|
5590
7652
|
const options = {
|
|
5591
|
-
...
|
|
7653
|
+
...onErrorOptions,
|
|
5592
7654
|
...((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) || {}
|
|
5593
7655
|
};
|
|
5594
7656
|
const coreStream = stream.pipeThrough(
|
|
@@ -5603,13 +7665,26 @@ async function wrapStream({
|
|
|
5603
7665
|
}
|
|
5604
7666
|
)
|
|
5605
7667
|
).pipeThrough(protocol.createStreamParser({ tools, options }));
|
|
7668
|
+
let seenToolCall = false;
|
|
5606
7669
|
const v3Stream = coreStream.pipeThrough(
|
|
5607
7670
|
new TransformStream({
|
|
5608
7671
|
transform(part, controller) {
|
|
7672
|
+
let normalizedPart = part.type === "tool-call" ? coerceToolCallPart(part, tools) : part;
|
|
7673
|
+
if (normalizedPart.type === "tool-call") {
|
|
7674
|
+
seenToolCall = true;
|
|
7675
|
+
}
|
|
7676
|
+
if (normalizedPart.type === "finish" && seenToolCall && normalizedPart.finishReason.unified === "stop") {
|
|
7677
|
+
normalizedPart = {
|
|
7678
|
+
...normalizedPart,
|
|
7679
|
+
finishReason: normalizeToolCallsFinishReason(
|
|
7680
|
+
normalizedPart.finishReason
|
|
7681
|
+
)
|
|
7682
|
+
};
|
|
7683
|
+
}
|
|
5609
7684
|
if (debugLevel === "stream") {
|
|
5610
|
-
logParsedChunk(
|
|
7685
|
+
logParsedChunk(normalizedPart);
|
|
5611
7686
|
}
|
|
5612
|
-
controller.enqueue(
|
|
7687
|
+
controller.enqueue(normalizedPart);
|
|
5613
7688
|
}
|
|
5614
7689
|
})
|
|
5615
7690
|
);
|
|
@@ -5620,41 +7695,36 @@ async function wrapStream({
|
|
|
5620
7695
|
}
|
|
5621
7696
|
async function toolChoiceStream({
|
|
5622
7697
|
doGenerate,
|
|
7698
|
+
tools,
|
|
5623
7699
|
options
|
|
5624
7700
|
}) {
|
|
5625
|
-
var _a
|
|
7701
|
+
var _a;
|
|
7702
|
+
const normalizedTools = Array.isArray(tools) ? tools : [];
|
|
5626
7703
|
const result = await doGenerate();
|
|
5627
|
-
let
|
|
7704
|
+
let toolName = "unknown";
|
|
7705
|
+
let input = "{}";
|
|
5628
7706
|
if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
error: error instanceof Error ? error.message : String(error)
|
|
5638
|
-
}
|
|
5639
|
-
);
|
|
5640
|
-
toolJson = {};
|
|
5641
|
-
}
|
|
7707
|
+
const parsed = parseToolChoicePayload({
|
|
7708
|
+
text: result.content[0].text,
|
|
7709
|
+
tools: normalizedTools,
|
|
7710
|
+
onError: options == null ? void 0 : options.onError,
|
|
7711
|
+
errorMessage: "Failed to parse toolChoice JSON from streamed model output"
|
|
7712
|
+
});
|
|
7713
|
+
toolName = parsed.toolName;
|
|
7714
|
+
input = parsed.input;
|
|
5642
7715
|
}
|
|
5643
7716
|
const stream = new ReadableStream({
|
|
5644
7717
|
start(controller) {
|
|
5645
7718
|
controller.enqueue({
|
|
5646
7719
|
type: "tool-call",
|
|
5647
|
-
toolCallId: (
|
|
5648
|
-
toolName
|
|
5649
|
-
input
|
|
7720
|
+
toolCallId: generateToolCallId(),
|
|
7721
|
+
toolName,
|
|
7722
|
+
input
|
|
5650
7723
|
});
|
|
5651
7724
|
controller.enqueue({
|
|
5652
7725
|
type: "finish",
|
|
5653
|
-
usage: (result == null ? void 0 : result.usage)
|
|
5654
|
-
|
|
5655
|
-
outputTokens: 0
|
|
5656
|
-
},
|
|
5657
|
-
finishReason: "tool-calls"
|
|
7726
|
+
usage: normalizeUsage(result == null ? void 0 : result.usage),
|
|
7727
|
+
finishReason: normalizeToolCallsFinishReason(result == null ? void 0 : result.finishReason)
|
|
5658
7728
|
});
|
|
5659
7729
|
controller.close();
|
|
5660
7730
|
}
|
|
@@ -5665,6 +7735,60 @@ async function toolChoiceStream({
|
|
|
5665
7735
|
stream
|
|
5666
7736
|
};
|
|
5667
7737
|
}
|
|
7738
|
+
var ZERO_USAGE = {
|
|
7739
|
+
inputTokens: {
|
|
7740
|
+
total: 0,
|
|
7741
|
+
noCache: void 0,
|
|
7742
|
+
cacheRead: void 0,
|
|
7743
|
+
cacheWrite: void 0
|
|
7744
|
+
},
|
|
7745
|
+
outputTokens: {
|
|
7746
|
+
total: 0,
|
|
7747
|
+
text: void 0,
|
|
7748
|
+
reasoning: void 0
|
|
7749
|
+
}
|
|
7750
|
+
};
|
|
7751
|
+
function normalizeToolCallsFinishReason(finishReason) {
|
|
7752
|
+
let raw = "tool-calls";
|
|
7753
|
+
if (typeof finishReason === "string") {
|
|
7754
|
+
raw = finishReason;
|
|
7755
|
+
} else if (finishReason && typeof finishReason === "object" && "raw" in finishReason && typeof finishReason.raw === "string") {
|
|
7756
|
+
raw = finishReason.raw;
|
|
7757
|
+
} else if (finishReason && typeof finishReason === "object" && "unified" in finishReason && typeof finishReason.unified === "string") {
|
|
7758
|
+
raw = finishReason.unified;
|
|
7759
|
+
}
|
|
7760
|
+
return {
|
|
7761
|
+
unified: "tool-calls",
|
|
7762
|
+
raw
|
|
7763
|
+
};
|
|
7764
|
+
}
|
|
7765
|
+
function normalizeUsage(usage) {
|
|
7766
|
+
if (!usage || typeof usage !== "object") {
|
|
7767
|
+
return ZERO_USAGE;
|
|
7768
|
+
}
|
|
7769
|
+
const usageRecord = usage;
|
|
7770
|
+
const input = usageRecord.inputTokens;
|
|
7771
|
+
const output = usageRecord.outputTokens;
|
|
7772
|
+
if (input && typeof input === "object" && output && typeof output === "object") {
|
|
7773
|
+
return usage;
|
|
7774
|
+
}
|
|
7775
|
+
if (typeof input === "number" && typeof output === "number") {
|
|
7776
|
+
return {
|
|
7777
|
+
inputTokens: {
|
|
7778
|
+
total: input,
|
|
7779
|
+
noCache: void 0,
|
|
7780
|
+
cacheRead: void 0,
|
|
7781
|
+
cacheWrite: void 0
|
|
7782
|
+
},
|
|
7783
|
+
outputTokens: {
|
|
7784
|
+
total: output,
|
|
7785
|
+
text: void 0,
|
|
7786
|
+
reasoning: void 0
|
|
7787
|
+
}
|
|
7788
|
+
};
|
|
7789
|
+
}
|
|
7790
|
+
return ZERO_USAGE;
|
|
7791
|
+
}
|
|
5668
7792
|
|
|
5669
7793
|
// src/transform-handler.ts
|
|
5670
7794
|
function buildFinalPrompt(systemPrompt, processedPrompt, placement) {
|
|
@@ -5790,6 +7914,11 @@ function handleToolChoiceRequired(params, baseReturnParams, functionTools) {
|
|
|
5790
7914
|
"Tool choice type 'required' is set, but no tools are provided in params.tools."
|
|
5791
7915
|
);
|
|
5792
7916
|
}
|
|
7917
|
+
if (functionTools.length === 0) {
|
|
7918
|
+
throw new Error(
|
|
7919
|
+
"Tool choice type 'required' is set, but no function tools are provided. Provider-defined tools are not supported by this middleware."
|
|
7920
|
+
);
|
|
7921
|
+
}
|
|
5793
7922
|
return {
|
|
5794
7923
|
...baseReturnParams,
|
|
5795
7924
|
responseFormat: {
|