@ai-sdk-tool/parser 3.3.3 → 4.0.1
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-CXWS24JX.js → chunk-76E6H46R.js} +2 -2
- package/dist/{chunk-2KK5BDZF.js → chunk-DJB4DAZO.js} +23 -6
- package/dist/chunk-DJB4DAZO.js.map +1 -0
- package/dist/{chunk-NAQSTPDQ.js → chunk-DPGORNPB.js} +1388 -211
- package/dist/chunk-DPGORNPB.js.map +1 -0
- package/dist/community.cjs +1420 -226
- package/dist/community.cjs.map +1 -1
- package/dist/community.js +3 -3
- package/dist/index.cjs +1420 -226
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -6
- package/dist/index.d.ts +8 -6
- package/dist/index.js +3 -3
- package/dist/rxml.cjs +22 -5
- package/dist/rxml.cjs.map +1 -1
- package/dist/rxml.js +2 -2
- package/dist/schema-coerce.cjs +22 -5
- package/dist/schema-coerce.cjs.map +1 -1
- package/dist/schema-coerce.js +1 -1
- package/package.json +7 -7
- package/dist/chunk-2KK5BDZF.js.map +0 -1
- package/dist/chunk-NAQSTPDQ.js.map +0 -1
- /package/dist/{chunk-CXWS24JX.js.map → chunk-76E6H46R.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -894,9 +894,19 @@ function getPotentialStartIndex(text, searchedText) {
|
|
|
894
894
|
if (directIndex !== -1) {
|
|
895
895
|
return directIndex;
|
|
896
896
|
}
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
897
|
+
const textLength = text.length;
|
|
898
|
+
const searchedTextLength = searchedText.length;
|
|
899
|
+
const startAt = Math.max(0, textLength - searchedTextLength + 1);
|
|
900
|
+
for (let i = startAt; i < textLength; i++) {
|
|
901
|
+
let match = true;
|
|
902
|
+
const currentSuffixLength = textLength - i;
|
|
903
|
+
for (let j = 0; j < currentSuffixLength; j++) {
|
|
904
|
+
if (text[i + j] !== searchedText[j]) {
|
|
905
|
+
match = false;
|
|
906
|
+
break;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
if (match) {
|
|
900
910
|
return i;
|
|
901
911
|
}
|
|
902
912
|
}
|
|
@@ -905,7 +915,25 @@ function getPotentialStartIndex(text, searchedText) {
|
|
|
905
915
|
|
|
906
916
|
// src/core/utils/id.ts
|
|
907
917
|
function generateId() {
|
|
908
|
-
return
|
|
918
|
+
return crypto.randomUUID().replace(/-/g, "").slice(0, 13);
|
|
919
|
+
}
|
|
920
|
+
var TOOL_CALL_ID_PREFIX = "call_";
|
|
921
|
+
var TOOL_CALL_ID_BODY_LENGTH = 24;
|
|
922
|
+
var TOOL_CALL_ID_ALPHANUM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
923
|
+
function randomAlphaNumeric(length) {
|
|
924
|
+
var _a;
|
|
925
|
+
const bytes = new Uint8Array(length);
|
|
926
|
+
crypto.getRandomValues(bytes);
|
|
927
|
+
let out = "";
|
|
928
|
+
for (let i = 0; i < length; i += 1) {
|
|
929
|
+
const byte = bytes[i];
|
|
930
|
+
const index = (byte != null ? byte : 0) % TOOL_CALL_ID_ALPHANUM.length;
|
|
931
|
+
out += (_a = TOOL_CALL_ID_ALPHANUM[index]) != null ? _a : "0";
|
|
932
|
+
}
|
|
933
|
+
return out;
|
|
934
|
+
}
|
|
935
|
+
function generateToolCallId() {
|
|
936
|
+
return `${TOOL_CALL_ID_PREFIX}${randomAlphaNumeric(TOOL_CALL_ID_BODY_LENGTH)}`;
|
|
909
937
|
}
|
|
910
938
|
|
|
911
939
|
// src/core/utils/protocol-utils.ts
|
|
@@ -914,6 +942,38 @@ function addTextSegment(text, processedElements) {
|
|
|
914
942
|
processedElements.push({ type: "text", text });
|
|
915
943
|
}
|
|
916
944
|
}
|
|
945
|
+
function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
946
|
+
return (controller, text) => {
|
|
947
|
+
const content = text;
|
|
948
|
+
if (content) {
|
|
949
|
+
if (!getCurrentTextId()) {
|
|
950
|
+
const newId = generateId();
|
|
951
|
+
setCurrentTextId(newId);
|
|
952
|
+
controller.enqueue({
|
|
953
|
+
type: "text-start",
|
|
954
|
+
id: newId
|
|
955
|
+
});
|
|
956
|
+
setHasEmittedTextStart(true);
|
|
957
|
+
}
|
|
958
|
+
controller.enqueue({
|
|
959
|
+
type: "text-delta",
|
|
960
|
+
id: getCurrentTextId(),
|
|
961
|
+
delta: content
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
const currentTextId = getCurrentTextId();
|
|
965
|
+
if (currentTextId && !text) {
|
|
966
|
+
if (getHasEmittedTextStart()) {
|
|
967
|
+
controller.enqueue({
|
|
968
|
+
type: "text-end",
|
|
969
|
+
id: currentTextId
|
|
970
|
+
});
|
|
971
|
+
setHasEmittedTextStart(false);
|
|
972
|
+
}
|
|
973
|
+
setCurrentTextId(null);
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
}
|
|
917
977
|
|
|
918
978
|
// src/core/utils/regex.ts
|
|
919
979
|
function escapeRegExp(literal) {
|
|
@@ -921,15 +981,21 @@ function escapeRegExp(literal) {
|
|
|
921
981
|
}
|
|
922
982
|
|
|
923
983
|
// src/core/protocols/json-protocol.ts
|
|
984
|
+
function shouldEmitRawToolCallTextOnError(options) {
|
|
985
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
986
|
+
}
|
|
987
|
+
function canonicalizeToolInput(argumentsValue) {
|
|
988
|
+
return JSON.stringify(argumentsValue != null ? argumentsValue : {});
|
|
989
|
+
}
|
|
924
990
|
function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
|
|
925
|
-
var _a
|
|
991
|
+
var _a;
|
|
926
992
|
try {
|
|
927
993
|
const parsedToolCall = parse(toolCallJson);
|
|
928
994
|
processedElements.push({
|
|
929
995
|
type: "tool-call",
|
|
930
|
-
toolCallId:
|
|
996
|
+
toolCallId: generateToolCallId(),
|
|
931
997
|
toolName: parsedToolCall.name,
|
|
932
|
-
input:
|
|
998
|
+
input: canonicalizeToolInput(parsedToolCall.arguments)
|
|
933
999
|
});
|
|
934
1000
|
} catch (error) {
|
|
935
1001
|
logParseFailure({
|
|
@@ -938,7 +1004,7 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
|
|
|
938
1004
|
snippet: fullMatch,
|
|
939
1005
|
error
|
|
940
1006
|
});
|
|
941
|
-
(
|
|
1007
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
942
1008
|
options,
|
|
943
1009
|
"Could not process JSON tool call, keeping original text.",
|
|
944
1010
|
{ toolCall: fullMatch, error }
|
|
@@ -959,6 +1025,293 @@ function processMatchedToolCall(context) {
|
|
|
959
1025
|
}
|
|
960
1026
|
return startIndex + match[0].length;
|
|
961
1027
|
}
|
|
1028
|
+
var WHITESPACE_JSON_REGEX = /\s/;
|
|
1029
|
+
function skipJsonWhitespace(text, fromIndex) {
|
|
1030
|
+
let index = fromIndex;
|
|
1031
|
+
while (index < text.length && WHITESPACE_JSON_REGEX.test(text[index])) {
|
|
1032
|
+
index += 1;
|
|
1033
|
+
}
|
|
1034
|
+
return index;
|
|
1035
|
+
}
|
|
1036
|
+
function findTopLevelPropertyValueStart(text, property) {
|
|
1037
|
+
const objectStart = skipJsonWhitespace(text, 0);
|
|
1038
|
+
if (objectStart >= text.length || text.charAt(objectStart) !== "{") {
|
|
1039
|
+
return null;
|
|
1040
|
+
}
|
|
1041
|
+
let depth = 0;
|
|
1042
|
+
let inString = false;
|
|
1043
|
+
let escaping = false;
|
|
1044
|
+
for (let index = objectStart; index < text.length; index += 1) {
|
|
1045
|
+
const char = text.charAt(index);
|
|
1046
|
+
if (inString) {
|
|
1047
|
+
if (escaping) {
|
|
1048
|
+
escaping = false;
|
|
1049
|
+
continue;
|
|
1050
|
+
}
|
|
1051
|
+
if (char === "\\") {
|
|
1052
|
+
escaping = true;
|
|
1053
|
+
continue;
|
|
1054
|
+
}
|
|
1055
|
+
if (char === '"') {
|
|
1056
|
+
inString = false;
|
|
1057
|
+
}
|
|
1058
|
+
continue;
|
|
1059
|
+
}
|
|
1060
|
+
if (char === "{") {
|
|
1061
|
+
depth += 1;
|
|
1062
|
+
continue;
|
|
1063
|
+
}
|
|
1064
|
+
if (char === "}") {
|
|
1065
|
+
depth = Math.max(0, depth - 1);
|
|
1066
|
+
continue;
|
|
1067
|
+
}
|
|
1068
|
+
if (char !== '"') {
|
|
1069
|
+
continue;
|
|
1070
|
+
}
|
|
1071
|
+
if (depth !== 1) {
|
|
1072
|
+
inString = true;
|
|
1073
|
+
continue;
|
|
1074
|
+
}
|
|
1075
|
+
const keyStart = index + 1;
|
|
1076
|
+
let keyEnd = keyStart;
|
|
1077
|
+
let keyEscaped = false;
|
|
1078
|
+
while (keyEnd < text.length) {
|
|
1079
|
+
const keyChar = text.charAt(keyEnd);
|
|
1080
|
+
if (keyEscaped) {
|
|
1081
|
+
keyEscaped = false;
|
|
1082
|
+
} else if (keyChar === "\\") {
|
|
1083
|
+
keyEscaped = true;
|
|
1084
|
+
} else if (keyChar === '"') {
|
|
1085
|
+
break;
|
|
1086
|
+
}
|
|
1087
|
+
keyEnd += 1;
|
|
1088
|
+
}
|
|
1089
|
+
if (keyEnd >= text.length || text.charAt(keyEnd) !== '"') {
|
|
1090
|
+
return null;
|
|
1091
|
+
}
|
|
1092
|
+
const key = text.slice(keyStart, keyEnd);
|
|
1093
|
+
let valueCursor = skipJsonWhitespace(text, keyEnd + 1);
|
|
1094
|
+
if (valueCursor >= text.length || text.charAt(valueCursor) !== ":") {
|
|
1095
|
+
index = keyEnd;
|
|
1096
|
+
continue;
|
|
1097
|
+
}
|
|
1098
|
+
valueCursor = skipJsonWhitespace(text, valueCursor + 1);
|
|
1099
|
+
if (key === property) {
|
|
1100
|
+
return valueCursor < text.length ? valueCursor : null;
|
|
1101
|
+
}
|
|
1102
|
+
index = valueCursor - 1;
|
|
1103
|
+
}
|
|
1104
|
+
return null;
|
|
1105
|
+
}
|
|
1106
|
+
function extractTopLevelStringProperty(text, property) {
|
|
1107
|
+
const valueStart = findTopLevelPropertyValueStart(text, property);
|
|
1108
|
+
if (valueStart == null || valueStart >= text.length) {
|
|
1109
|
+
return void 0;
|
|
1110
|
+
}
|
|
1111
|
+
if (text.charAt(valueStart) !== '"') {
|
|
1112
|
+
return void 0;
|
|
1113
|
+
}
|
|
1114
|
+
let valueEnd = valueStart + 1;
|
|
1115
|
+
let escaped = false;
|
|
1116
|
+
while (valueEnd < text.length) {
|
|
1117
|
+
const char = text.charAt(valueEnd);
|
|
1118
|
+
if (escaped) {
|
|
1119
|
+
escaped = false;
|
|
1120
|
+
} else if (char === "\\") {
|
|
1121
|
+
escaped = true;
|
|
1122
|
+
} else if (char === '"') {
|
|
1123
|
+
return text.slice(valueStart + 1, valueEnd);
|
|
1124
|
+
}
|
|
1125
|
+
valueEnd += 1;
|
|
1126
|
+
}
|
|
1127
|
+
return void 0;
|
|
1128
|
+
}
|
|
1129
|
+
function extractJsonValueSlice(text, valueStart) {
|
|
1130
|
+
if (valueStart >= text.length) {
|
|
1131
|
+
return null;
|
|
1132
|
+
}
|
|
1133
|
+
const first = text.charAt(valueStart);
|
|
1134
|
+
if (first === "{" || first === "[") {
|
|
1135
|
+
const stack = [first];
|
|
1136
|
+
let inString = false;
|
|
1137
|
+
let escaped = false;
|
|
1138
|
+
for (let index2 = valueStart + 1; index2 < text.length; index2 += 1) {
|
|
1139
|
+
const char = text.charAt(index2);
|
|
1140
|
+
if (inString) {
|
|
1141
|
+
if (escaped) {
|
|
1142
|
+
escaped = false;
|
|
1143
|
+
} else if (char === "\\") {
|
|
1144
|
+
escaped = true;
|
|
1145
|
+
} else if (char === '"') {
|
|
1146
|
+
inString = false;
|
|
1147
|
+
}
|
|
1148
|
+
continue;
|
|
1149
|
+
}
|
|
1150
|
+
if (char === '"') {
|
|
1151
|
+
inString = true;
|
|
1152
|
+
continue;
|
|
1153
|
+
}
|
|
1154
|
+
if (char === "{" || char === "[") {
|
|
1155
|
+
stack.push(char);
|
|
1156
|
+
continue;
|
|
1157
|
+
}
|
|
1158
|
+
if (char === "}" || char === "]") {
|
|
1159
|
+
const open = stack.at(-1);
|
|
1160
|
+
if (open === "{" && char === "}" || open === "[" && char === "]") {
|
|
1161
|
+
stack.pop();
|
|
1162
|
+
if (stack.length === 0) {
|
|
1163
|
+
return {
|
|
1164
|
+
text: text.slice(valueStart, index2 + 1),
|
|
1165
|
+
complete: true
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
return {
|
|
1172
|
+
text: text.slice(valueStart),
|
|
1173
|
+
complete: false
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1176
|
+
if (first === '"') {
|
|
1177
|
+
let escaped = false;
|
|
1178
|
+
for (let index2 = valueStart + 1; index2 < text.length; index2 += 1) {
|
|
1179
|
+
const char = text.charAt(index2);
|
|
1180
|
+
if (escaped) {
|
|
1181
|
+
escaped = false;
|
|
1182
|
+
} else if (char === "\\") {
|
|
1183
|
+
escaped = true;
|
|
1184
|
+
} else if (char === '"') {
|
|
1185
|
+
return {
|
|
1186
|
+
text: text.slice(valueStart, index2 + 1),
|
|
1187
|
+
complete: true
|
|
1188
|
+
};
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
return {
|
|
1192
|
+
text: text.slice(valueStart),
|
|
1193
|
+
complete: false
|
|
1194
|
+
};
|
|
1195
|
+
}
|
|
1196
|
+
let index = valueStart;
|
|
1197
|
+
while (index < text.length) {
|
|
1198
|
+
const char = text.charAt(index);
|
|
1199
|
+
if (char === "," || char === "}" || WHITESPACE_JSON_REGEX.test(char)) {
|
|
1200
|
+
break;
|
|
1201
|
+
}
|
|
1202
|
+
index += 1;
|
|
1203
|
+
}
|
|
1204
|
+
return {
|
|
1205
|
+
text: text.slice(valueStart, index),
|
|
1206
|
+
complete: index < text.length
|
|
1207
|
+
};
|
|
1208
|
+
}
|
|
1209
|
+
function extractStreamingToolCallProgress(toolCallJson) {
|
|
1210
|
+
var _a;
|
|
1211
|
+
const toolName = extractTopLevelStringProperty(toolCallJson, "name");
|
|
1212
|
+
const argsValueStart = findTopLevelPropertyValueStart(
|
|
1213
|
+
toolCallJson,
|
|
1214
|
+
"arguments"
|
|
1215
|
+
);
|
|
1216
|
+
if (argsValueStart == null) {
|
|
1217
|
+
return {
|
|
1218
|
+
toolName,
|
|
1219
|
+
argumentsText: void 0,
|
|
1220
|
+
argumentsComplete: false
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
const argsSlice = extractJsonValueSlice(toolCallJson, argsValueStart);
|
|
1224
|
+
return {
|
|
1225
|
+
toolName,
|
|
1226
|
+
argumentsText: argsSlice == null ? void 0 : argsSlice.text,
|
|
1227
|
+
argumentsComplete: (_a = argsSlice == null ? void 0 : argsSlice.complete) != null ? _a : false
|
|
1228
|
+
};
|
|
1229
|
+
}
|
|
1230
|
+
function ensureToolInputStart(state, controller, toolName) {
|
|
1231
|
+
if (!state.activeToolInput) {
|
|
1232
|
+
const id = generateToolCallId();
|
|
1233
|
+
state.activeToolInput = {
|
|
1234
|
+
id,
|
|
1235
|
+
toolName,
|
|
1236
|
+
emittedInput: ""
|
|
1237
|
+
};
|
|
1238
|
+
controller.enqueue({
|
|
1239
|
+
type: "tool-input-start",
|
|
1240
|
+
id,
|
|
1241
|
+
toolName
|
|
1242
|
+
});
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
function emitToolInputDelta(state, controller, fullInput) {
|
|
1246
|
+
const active = state.activeToolInput;
|
|
1247
|
+
if (!active) {
|
|
1248
|
+
return;
|
|
1249
|
+
}
|
|
1250
|
+
if (!fullInput.startsWith(active.emittedInput)) {
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
1253
|
+
const delta = fullInput.slice(active.emittedInput.length);
|
|
1254
|
+
if (delta.length === 0) {
|
|
1255
|
+
return;
|
|
1256
|
+
}
|
|
1257
|
+
controller.enqueue({
|
|
1258
|
+
type: "tool-input-delta",
|
|
1259
|
+
id: active.id,
|
|
1260
|
+
delta
|
|
1261
|
+
});
|
|
1262
|
+
active.emittedInput = fullInput;
|
|
1263
|
+
}
|
|
1264
|
+
function closeToolInput(state, controller) {
|
|
1265
|
+
if (!state.activeToolInput) {
|
|
1266
|
+
return;
|
|
1267
|
+
}
|
|
1268
|
+
controller.enqueue({
|
|
1269
|
+
type: "tool-input-end",
|
|
1270
|
+
id: state.activeToolInput.id
|
|
1271
|
+
});
|
|
1272
|
+
state.activeToolInput = null;
|
|
1273
|
+
}
|
|
1274
|
+
function emitToolCallFromParsed(state, controller, parsedToolCall) {
|
|
1275
|
+
var _a, _b, _c, _d;
|
|
1276
|
+
closeTextBlock(state, controller);
|
|
1277
|
+
const toolName = typeof parsedToolCall.name === "string" ? parsedToolCall.name : (_b = (_a = state.activeToolInput) == null ? void 0 : _a.toolName) != null ? _b : "unknown";
|
|
1278
|
+
const input = canonicalizeToolInput(parsedToolCall.arguments);
|
|
1279
|
+
ensureToolInputStart(state, controller, toolName);
|
|
1280
|
+
emitToolInputDelta(state, controller, input);
|
|
1281
|
+
const toolCallId = (_d = (_c = state.activeToolInput) == null ? void 0 : _c.id) != null ? _d : generateToolCallId();
|
|
1282
|
+
closeToolInput(state, controller);
|
|
1283
|
+
controller.enqueue({
|
|
1284
|
+
type: "tool-call",
|
|
1285
|
+
toolCallId,
|
|
1286
|
+
toolName,
|
|
1287
|
+
input
|
|
1288
|
+
});
|
|
1289
|
+
}
|
|
1290
|
+
function canonicalizeArgumentsProgressInput(progress) {
|
|
1291
|
+
if (progress.argumentsText === void 0 || !progress.argumentsComplete) {
|
|
1292
|
+
return void 0;
|
|
1293
|
+
}
|
|
1294
|
+
try {
|
|
1295
|
+
const parsedArguments = parse(progress.argumentsText);
|
|
1296
|
+
return canonicalizeToolInput(parsedArguments);
|
|
1297
|
+
} catch (e) {
|
|
1298
|
+
return void 0;
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
function emitToolInputProgress(state, controller) {
|
|
1302
|
+
if (!(state.isInsideToolCall && state.currentToolCallJson)) {
|
|
1303
|
+
return;
|
|
1304
|
+
}
|
|
1305
|
+
const progress = extractStreamingToolCallProgress(state.currentToolCallJson);
|
|
1306
|
+
if (!progress.toolName) {
|
|
1307
|
+
return;
|
|
1308
|
+
}
|
|
1309
|
+
ensureToolInputStart(state, controller, progress.toolName);
|
|
1310
|
+
const canonicalProgressInput = canonicalizeArgumentsProgressInput(progress);
|
|
1311
|
+
if (canonicalProgressInput !== void 0) {
|
|
1312
|
+
emitToolInputDelta(state, controller, canonicalProgressInput);
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
962
1315
|
function flushBuffer(state, controller, toolCallStart) {
|
|
963
1316
|
if (state.buffer.length === 0) {
|
|
964
1317
|
return;
|
|
@@ -989,44 +1342,77 @@ function closeTextBlock(state, controller) {
|
|
|
989
1342
|
state.hasEmittedTextStart = false;
|
|
990
1343
|
}
|
|
991
1344
|
}
|
|
992
|
-
function emitIncompleteToolCall(state, controller, toolCallStart) {
|
|
993
|
-
|
|
1345
|
+
function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer, options) {
|
|
1346
|
+
var _a;
|
|
1347
|
+
if (!state.currentToolCallJson && trailingBuffer.length === 0) {
|
|
1348
|
+
state.isInsideToolCall = false;
|
|
994
1349
|
return;
|
|
995
1350
|
}
|
|
1351
|
+
if (state.currentToolCallJson) {
|
|
1352
|
+
try {
|
|
1353
|
+
const parsedToolCall = parse(state.currentToolCallJson);
|
|
1354
|
+
emitToolCallFromParsed(state, controller, parsedToolCall);
|
|
1355
|
+
state.currentToolCallJson = "";
|
|
1356
|
+
state.isInsideToolCall = false;
|
|
1357
|
+
return;
|
|
1358
|
+
} catch (e) {
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
const rawToolCallContent = `${state.currentToolCallJson}${trailingBuffer}`;
|
|
1362
|
+
const errorContent = `${toolCallStart}${rawToolCallContent}`;
|
|
1363
|
+
const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
|
|
996
1364
|
logParseFailure({
|
|
997
1365
|
phase: "stream",
|
|
998
|
-
reason: "Incomplete streaming tool call segment emitted as text",
|
|
999
|
-
snippet:
|
|
1000
|
-
});
|
|
1001
|
-
const errorId = generateId();
|
|
1002
|
-
const errorContent = `${toolCallStart}${state.currentToolCallJson}`;
|
|
1003
|
-
controller.enqueue({
|
|
1004
|
-
type: "text-start",
|
|
1005
|
-
id: errorId
|
|
1006
|
-
});
|
|
1007
|
-
controller.enqueue({
|
|
1008
|
-
type: "text-delta",
|
|
1009
|
-
id: errorId,
|
|
1010
|
-
delta: errorContent
|
|
1011
|
-
});
|
|
1012
|
-
controller.enqueue({
|
|
1013
|
-
type: "text-end",
|
|
1014
|
-
id: errorId
|
|
1366
|
+
reason: shouldEmitRawFallback ? "Incomplete streaming tool call segment emitted as text" : "Incomplete streaming tool call segment suppressed without raw text fallback",
|
|
1367
|
+
snippet: errorContent
|
|
1015
1368
|
});
|
|
1369
|
+
if (shouldEmitRawFallback) {
|
|
1370
|
+
const errorId = generateId();
|
|
1371
|
+
controller.enqueue({
|
|
1372
|
+
type: "text-start",
|
|
1373
|
+
id: errorId
|
|
1374
|
+
});
|
|
1375
|
+
controller.enqueue({
|
|
1376
|
+
type: "text-delta",
|
|
1377
|
+
id: errorId,
|
|
1378
|
+
delta: errorContent
|
|
1379
|
+
});
|
|
1380
|
+
controller.enqueue({
|
|
1381
|
+
type: "text-end",
|
|
1382
|
+
id: errorId
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
closeToolInput(state, controller);
|
|
1386
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1387
|
+
options,
|
|
1388
|
+
shouldEmitRawFallback ? "Could not complete streaming JSON tool call at finish; emitting original text." : "Could not complete streaming JSON tool call at finish.",
|
|
1389
|
+
{ toolCall: errorContent }
|
|
1390
|
+
);
|
|
1016
1391
|
state.currentToolCallJson = "";
|
|
1392
|
+
state.isInsideToolCall = false;
|
|
1017
1393
|
}
|
|
1018
|
-
function handleFinishChunk(state, controller, toolCallStart, chunk) {
|
|
1019
|
-
if (state.
|
|
1394
|
+
function handleFinishChunk(state, controller, toolCallStart, options, chunk) {
|
|
1395
|
+
if (state.isInsideToolCall) {
|
|
1396
|
+
const trailingBuffer = state.buffer;
|
|
1397
|
+
state.buffer = "";
|
|
1398
|
+
emitIncompleteToolCall(
|
|
1399
|
+
state,
|
|
1400
|
+
controller,
|
|
1401
|
+
toolCallStart,
|
|
1402
|
+
trailingBuffer,
|
|
1403
|
+
options
|
|
1404
|
+
);
|
|
1405
|
+
} else if (state.buffer.length > 0) {
|
|
1020
1406
|
flushBuffer(state, controller, toolCallStart);
|
|
1021
1407
|
}
|
|
1022
1408
|
closeTextBlock(state, controller);
|
|
1023
|
-
emitIncompleteToolCall(state, controller, toolCallStart);
|
|
1024
1409
|
controller.enqueue(chunk);
|
|
1025
1410
|
}
|
|
1026
1411
|
function publishText(text, state, controller) {
|
|
1027
1412
|
if (state.isInsideToolCall) {
|
|
1028
1413
|
closeTextBlock(state, controller);
|
|
1029
1414
|
state.currentToolCallJson += text;
|
|
1415
|
+
emitToolInputProgress(state, controller);
|
|
1030
1416
|
} else if (text.length > 0) {
|
|
1031
1417
|
if (!state.currentTextId) {
|
|
1032
1418
|
state.currentTextId = generateId();
|
|
@@ -1044,42 +1430,40 @@ function publishText(text, state, controller) {
|
|
|
1044
1430
|
}
|
|
1045
1431
|
}
|
|
1046
1432
|
function emitToolCall(context) {
|
|
1047
|
-
var _a
|
|
1433
|
+
var _a;
|
|
1048
1434
|
const { state, controller, toolCallStart, toolCallEnd, options } = context;
|
|
1049
1435
|
try {
|
|
1050
1436
|
const parsedToolCall = parse(state.currentToolCallJson);
|
|
1051
|
-
|
|
1052
|
-
controller.enqueue({
|
|
1053
|
-
type: "tool-call",
|
|
1054
|
-
toolCallId: generateId(),
|
|
1055
|
-
toolName: parsedToolCall.name,
|
|
1056
|
-
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1057
|
-
});
|
|
1437
|
+
emitToolCallFromParsed(state, controller, parsedToolCall);
|
|
1058
1438
|
} catch (error) {
|
|
1439
|
+
const errorContent = `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`;
|
|
1440
|
+
const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
|
|
1059
1441
|
logParseFailure({
|
|
1060
1442
|
phase: "stream",
|
|
1061
1443
|
reason: "Failed to parse streaming tool call JSON segment",
|
|
1062
|
-
snippet:
|
|
1444
|
+
snippet: errorContent,
|
|
1063
1445
|
error
|
|
1064
1446
|
});
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1447
|
+
if (shouldEmitRawFallback) {
|
|
1448
|
+
const errorId = generateId();
|
|
1449
|
+
controller.enqueue({
|
|
1450
|
+
type: "text-start",
|
|
1451
|
+
id: errorId
|
|
1452
|
+
});
|
|
1453
|
+
controller.enqueue({
|
|
1454
|
+
type: "text-delta",
|
|
1455
|
+
id: errorId,
|
|
1456
|
+
delta: errorContent
|
|
1457
|
+
});
|
|
1458
|
+
controller.enqueue({
|
|
1459
|
+
type: "text-end",
|
|
1460
|
+
id: errorId
|
|
1461
|
+
});
|
|
1462
|
+
}
|
|
1463
|
+
closeToolInput(state, controller);
|
|
1464
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1081
1465
|
options,
|
|
1082
|
-
"Could not process streaming JSON tool call; emitting original text.",
|
|
1466
|
+
shouldEmitRawFallback ? "Could not process streaming JSON tool call; emitting original text." : "Could not process streaming JSON tool call.",
|
|
1083
1467
|
{
|
|
1084
1468
|
toolCall: errorContent
|
|
1085
1469
|
}
|
|
@@ -1095,6 +1479,7 @@ function processTagMatch(context) {
|
|
|
1095
1479
|
} else {
|
|
1096
1480
|
state.currentToolCallJson = "";
|
|
1097
1481
|
state.isInsideToolCall = true;
|
|
1482
|
+
state.activeToolInput = null;
|
|
1098
1483
|
}
|
|
1099
1484
|
}
|
|
1100
1485
|
function processBufferTags(context) {
|
|
@@ -1117,8 +1502,16 @@ function processBufferTags(context) {
|
|
|
1117
1502
|
);
|
|
1118
1503
|
}
|
|
1119
1504
|
}
|
|
1120
|
-
function handlePartialTag(state, controller, toolCallStart) {
|
|
1505
|
+
function handlePartialTag(state, controller, toolCallStart, toolCallEnd) {
|
|
1121
1506
|
if (state.isInsideToolCall) {
|
|
1507
|
+
const potentialEndIndex = getPotentialStartIndex(state.buffer, toolCallEnd);
|
|
1508
|
+
if (potentialEndIndex != null && potentialEndIndex + toolCallEnd.length > state.buffer.length) {
|
|
1509
|
+
publishText(state.buffer.slice(0, potentialEndIndex), state, controller);
|
|
1510
|
+
state.buffer = state.buffer.slice(potentialEndIndex);
|
|
1511
|
+
} else {
|
|
1512
|
+
publishText(state.buffer, state, controller);
|
|
1513
|
+
state.buffer = "";
|
|
1514
|
+
}
|
|
1122
1515
|
return;
|
|
1123
1516
|
}
|
|
1124
1517
|
const potentialIndex = getPotentialStartIndex(state.buffer, toolCallStart);
|
|
@@ -1191,13 +1584,14 @@ var jsonProtocol = ({
|
|
|
1191
1584
|
buffer: "",
|
|
1192
1585
|
currentToolCallJson: "",
|
|
1193
1586
|
currentTextId: null,
|
|
1194
|
-
hasEmittedTextStart: false
|
|
1587
|
+
hasEmittedTextStart: false,
|
|
1588
|
+
activeToolInput: null
|
|
1195
1589
|
};
|
|
1196
1590
|
return new TransformStream({
|
|
1197
1591
|
transform(chunk, controller) {
|
|
1198
1592
|
var _a;
|
|
1199
1593
|
if (chunk.type === "finish") {
|
|
1200
|
-
handleFinishChunk(state, controller, toolCallStart, chunk);
|
|
1594
|
+
handleFinishChunk(state, controller, toolCallStart, options, chunk);
|
|
1201
1595
|
return;
|
|
1202
1596
|
}
|
|
1203
1597
|
if (chunk.type !== "text-delta") {
|
|
@@ -1213,7 +1607,7 @@ var jsonProtocol = ({
|
|
|
1213
1607
|
toolCallEnd,
|
|
1214
1608
|
options
|
|
1215
1609
|
});
|
|
1216
|
-
handlePartialTag(state, controller, toolCallStart);
|
|
1610
|
+
handlePartialTag(state, controller, toolCallStart, toolCallEnd);
|
|
1217
1611
|
}
|
|
1218
1612
|
});
|
|
1219
1613
|
},
|
|
@@ -1800,13 +2194,20 @@ function coerceStringWithoutSchema(value) {
|
|
|
1800
2194
|
}
|
|
1801
2195
|
function coerceStringToObject(s, unwrapped) {
|
|
1802
2196
|
try {
|
|
1803
|
-
|
|
1804
|
-
normalized = normalized.replace(EMPTY_OBJECT_REGEX, "{}");
|
|
1805
|
-
const obj = JSON.parse(normalized);
|
|
2197
|
+
const obj = JSON.parse(s);
|
|
1806
2198
|
if (obj && typeof obj === "object" && !Array.isArray(obj)) {
|
|
1807
2199
|
return coerceObjectToObject(obj, unwrapped);
|
|
1808
2200
|
}
|
|
1809
2201
|
} catch (e) {
|
|
2202
|
+
try {
|
|
2203
|
+
let normalized = s.replace(/'/g, '"');
|
|
2204
|
+
normalized = normalized.replace(EMPTY_OBJECT_REGEX, "{}");
|
|
2205
|
+
const obj = JSON.parse(normalized);
|
|
2206
|
+
if (obj && typeof obj === "object" && !Array.isArray(obj)) {
|
|
2207
|
+
return coerceObjectToObject(obj, unwrapped);
|
|
2208
|
+
}
|
|
2209
|
+
} catch (e2) {
|
|
2210
|
+
}
|
|
1810
2211
|
}
|
|
1811
2212
|
return null;
|
|
1812
2213
|
}
|
|
@@ -1814,8 +2215,7 @@ function coerceStringToArray(s, unwrapped) {
|
|
|
1814
2215
|
const prefixItems = Array.isArray(unwrapped.prefixItems) ? unwrapped.prefixItems : void 0;
|
|
1815
2216
|
const itemsSchema = unwrapped.items;
|
|
1816
2217
|
try {
|
|
1817
|
-
const
|
|
1818
|
-
const arr = JSON.parse(normalized);
|
|
2218
|
+
const arr = JSON.parse(s);
|
|
1819
2219
|
if (Array.isArray(arr)) {
|
|
1820
2220
|
if (prefixItems && arr.length === prefixItems.length) {
|
|
1821
2221
|
return arr.map((v, i) => coerceBySchema(v, prefixItems[i]));
|
|
@@ -1823,6 +2223,17 @@ function coerceStringToArray(s, unwrapped) {
|
|
|
1823
2223
|
return arr.map((v) => coerceBySchema(v, itemsSchema));
|
|
1824
2224
|
}
|
|
1825
2225
|
} catch (e) {
|
|
2226
|
+
try {
|
|
2227
|
+
const normalized = s.replace(/'/g, '"');
|
|
2228
|
+
const arr = JSON.parse(normalized);
|
|
2229
|
+
if (Array.isArray(arr)) {
|
|
2230
|
+
if (prefixItems && arr.length === prefixItems.length) {
|
|
2231
|
+
return arr.map((v, i) => coerceBySchema(v, prefixItems[i]));
|
|
2232
|
+
}
|
|
2233
|
+
return arr.map((v) => coerceBySchema(v, itemsSchema));
|
|
2234
|
+
}
|
|
2235
|
+
} catch (e2) {
|
|
2236
|
+
}
|
|
1826
2237
|
const csv = s.includes("\n") ? s.split(NEWLINE_SPLIT_REGEX) : s.split(COMMA_SPLIT_REGEX);
|
|
1827
2238
|
const trimmed = csv.map((x) => x.trim()).filter((x) => x.length > 0);
|
|
1828
2239
|
if (prefixItems && trimmed.length === prefixItems.length) {
|
|
@@ -4193,22 +4604,96 @@ function parse3(xml, schema, options = {}) {
|
|
|
4193
4604
|
var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
|
|
4194
4605
|
var WHITESPACE_REGEX5 = /\s/;
|
|
4195
4606
|
|
|
4196
|
-
// src/core/utils/
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
return null;
|
|
4607
|
+
// src/core/utils/streamed-tool-input-delta.ts
|
|
4608
|
+
function emitDelta({
|
|
4609
|
+
controller,
|
|
4610
|
+
id,
|
|
4611
|
+
state,
|
|
4612
|
+
nextInput
|
|
4613
|
+
}) {
|
|
4614
|
+
if (!nextInput.startsWith(state.emittedInput)) {
|
|
4615
|
+
return false;
|
|
4206
4616
|
}
|
|
4207
|
-
const
|
|
4208
|
-
if (
|
|
4209
|
-
return
|
|
4617
|
+
const delta = nextInput.slice(state.emittedInput.length);
|
|
4618
|
+
if (delta.length === 0) {
|
|
4619
|
+
return false;
|
|
4210
4620
|
}
|
|
4211
|
-
|
|
4621
|
+
controller.enqueue({
|
|
4622
|
+
type: "tool-input-delta",
|
|
4623
|
+
id,
|
|
4624
|
+
delta
|
|
4625
|
+
});
|
|
4626
|
+
state.emittedInput = nextInput;
|
|
4627
|
+
return true;
|
|
4628
|
+
}
|
|
4629
|
+
function toIncompleteJsonPrefix(fullJson) {
|
|
4630
|
+
const trimmed = fullJson.trim();
|
|
4631
|
+
let prefix = trimmed;
|
|
4632
|
+
while (prefix.endsWith("}") || prefix.endsWith("]")) {
|
|
4633
|
+
prefix = prefix.slice(0, -1);
|
|
4634
|
+
}
|
|
4635
|
+
prefix = prefix.trimEnd();
|
|
4636
|
+
if (prefix.endsWith('"')) {
|
|
4637
|
+
prefix = prefix.slice(0, -1);
|
|
4638
|
+
}
|
|
4639
|
+
if (prefix.length === 0) {
|
|
4640
|
+
if (trimmed.startsWith("[") || trimmed.startsWith("{")) {
|
|
4641
|
+
return trimmed.startsWith("{") ? "{" : "[";
|
|
4642
|
+
}
|
|
4643
|
+
if (trimmed.startsWith("]")) {
|
|
4644
|
+
return "[";
|
|
4645
|
+
}
|
|
4646
|
+
if (trimmed.startsWith("}")) {
|
|
4647
|
+
return "{";
|
|
4648
|
+
}
|
|
4649
|
+
if (trimmed.startsWith('"')) {
|
|
4650
|
+
return '"';
|
|
4651
|
+
}
|
|
4652
|
+
return "{";
|
|
4653
|
+
}
|
|
4654
|
+
return prefix;
|
|
4655
|
+
}
|
|
4656
|
+
function emitPrefixDelta(params) {
|
|
4657
|
+
return emitDelta({
|
|
4658
|
+
...params,
|
|
4659
|
+
nextInput: params.candidate
|
|
4660
|
+
});
|
|
4661
|
+
}
|
|
4662
|
+
function emitFinalRemainder(params) {
|
|
4663
|
+
var _a;
|
|
4664
|
+
const result = emitDelta({
|
|
4665
|
+
...params,
|
|
4666
|
+
nextInput: params.finalFullJson
|
|
4667
|
+
});
|
|
4668
|
+
if (!result && params.state.emittedInput.length > 0) {
|
|
4669
|
+
(_a = params.onMismatch) == null ? void 0 : _a.call(
|
|
4670
|
+
params,
|
|
4671
|
+
"Final JSON does not extend emitted tool-input prefix",
|
|
4672
|
+
{
|
|
4673
|
+
emittedLength: params.state.emittedInput.length,
|
|
4674
|
+
finalLength: params.finalFullJson.length
|
|
4675
|
+
}
|
|
4676
|
+
);
|
|
4677
|
+
}
|
|
4678
|
+
return result;
|
|
4679
|
+
}
|
|
4680
|
+
|
|
4681
|
+
// src/core/utils/xml-root-repair.ts
|
|
4682
|
+
var XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX = /^<([A-Za-z_][A-Za-z0-9_-]*)\s*\r?\n([\s\S]+?)\r?\n\s*\/>\s*$/;
|
|
4683
|
+
function tryRepairXmlSelfClosingRootWithBody(rawText, toolNames) {
|
|
4684
|
+
const trimmed = rawText.trim();
|
|
4685
|
+
if (trimmed.length === 0) {
|
|
4686
|
+
return null;
|
|
4687
|
+
}
|
|
4688
|
+
const match = trimmed.match(XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX);
|
|
4689
|
+
if (!match) {
|
|
4690
|
+
return null;
|
|
4691
|
+
}
|
|
4692
|
+
const rootTag = match[1];
|
|
4693
|
+
if (!toolNames.includes(rootTag)) {
|
|
4694
|
+
return null;
|
|
4695
|
+
}
|
|
4696
|
+
const body = match[2].trimEnd();
|
|
4212
4697
|
if (body.trim().length === 0 || body.includes(`</${rootTag}>`)) {
|
|
4213
4698
|
return null;
|
|
4214
4699
|
}
|
|
@@ -4222,6 +4707,9 @@ function getToolSchema(tools, toolName) {
|
|
|
4222
4707
|
var _a;
|
|
4223
4708
|
return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
4224
4709
|
}
|
|
4710
|
+
function shouldEmitRawToolCallTextOnError2(options) {
|
|
4711
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
4712
|
+
}
|
|
4225
4713
|
function processToolCall(params) {
|
|
4226
4714
|
var _a, _b;
|
|
4227
4715
|
const { toolCall, tools, options, text, processedElements, parseOptions } = params;
|
|
@@ -4234,7 +4722,7 @@ function processToolCall(params) {
|
|
|
4234
4722
|
const parsed = parse3(toolCall.content, toolSchema, parseConfig);
|
|
4235
4723
|
processedElements.push({
|
|
4236
4724
|
type: "tool-call",
|
|
4237
|
-
toolCallId:
|
|
4725
|
+
toolCallId: generateToolCallId(),
|
|
4238
4726
|
toolName: toolCall.toolName,
|
|
4239
4727
|
input: JSON.stringify(parsed)
|
|
4240
4728
|
});
|
|
@@ -4251,6 +4739,299 @@ function processToolCall(params) {
|
|
|
4251
4739
|
processedElements.push({ type: "text", text: originalCallText });
|
|
4252
4740
|
}
|
|
4253
4741
|
}
|
|
4742
|
+
function parseXmlTagName(rawTagBody) {
|
|
4743
|
+
let index = 0;
|
|
4744
|
+
while (index < rawTagBody.length && WHITESPACE_REGEX5.test(rawTagBody[index])) {
|
|
4745
|
+
index += 1;
|
|
4746
|
+
}
|
|
4747
|
+
const nameStart = index;
|
|
4748
|
+
while (index < rawTagBody.length && NAME_CHAR_RE2.test(rawTagBody.charAt(index))) {
|
|
4749
|
+
index += 1;
|
|
4750
|
+
}
|
|
4751
|
+
return rawTagBody.slice(nameStart, index);
|
|
4752
|
+
}
|
|
4753
|
+
function consumeXmlSpecialSection(fragment, ltIndex) {
|
|
4754
|
+
if (fragment.startsWith("<!--", ltIndex)) {
|
|
4755
|
+
const commentEnd = fragment.indexOf("-->", ltIndex + 4);
|
|
4756
|
+
return commentEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: commentEnd + 3 };
|
|
4757
|
+
}
|
|
4758
|
+
if (fragment.startsWith("<![CDATA[", ltIndex)) {
|
|
4759
|
+
const cdataEnd = fragment.indexOf("]]>", ltIndex + 9);
|
|
4760
|
+
return cdataEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: cdataEnd + 3 };
|
|
4761
|
+
}
|
|
4762
|
+
if (fragment.startsWith("<?", ltIndex)) {
|
|
4763
|
+
const processingEnd = fragment.indexOf("?>", ltIndex + 2);
|
|
4764
|
+
return processingEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: processingEnd + 2 };
|
|
4765
|
+
}
|
|
4766
|
+
if (fragment.startsWith("<!", ltIndex)) {
|
|
4767
|
+
const declarationEnd = fragment.indexOf(">", ltIndex + 2);
|
|
4768
|
+
return declarationEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: declarationEnd + 1 };
|
|
4769
|
+
}
|
|
4770
|
+
return { kind: "none" };
|
|
4771
|
+
}
|
|
4772
|
+
function parseXmlTagToken(fragment, ltIndex) {
|
|
4773
|
+
const gtIndex = fragment.indexOf(">", ltIndex + 1);
|
|
4774
|
+
if (gtIndex === -1) {
|
|
4775
|
+
return null;
|
|
4776
|
+
}
|
|
4777
|
+
const tagBody = fragment.slice(ltIndex + 1, gtIndex).trim();
|
|
4778
|
+
if (tagBody.length === 0) {
|
|
4779
|
+
return null;
|
|
4780
|
+
}
|
|
4781
|
+
if (tagBody.startsWith("/")) {
|
|
4782
|
+
const closeName = parseXmlTagName(tagBody.slice(1));
|
|
4783
|
+
if (closeName.length === 0) {
|
|
4784
|
+
return null;
|
|
4785
|
+
}
|
|
4786
|
+
return { kind: "close", name: closeName, nextPos: gtIndex + 1 };
|
|
4787
|
+
}
|
|
4788
|
+
const selfClosing = tagBody.endsWith("/");
|
|
4789
|
+
const openBody = selfClosing ? tagBody.slice(0, -1).trimEnd() : tagBody;
|
|
4790
|
+
const openName = parseXmlTagName(openBody);
|
|
4791
|
+
if (openName.length === 0) {
|
|
4792
|
+
return null;
|
|
4793
|
+
}
|
|
4794
|
+
return {
|
|
4795
|
+
kind: "open",
|
|
4796
|
+
name: openName,
|
|
4797
|
+
selfClosing,
|
|
4798
|
+
nextPos: gtIndex + 1
|
|
4799
|
+
};
|
|
4800
|
+
}
|
|
4801
|
+
function analyzeXmlFragmentForProgress(fragment) {
|
|
4802
|
+
const stack = [];
|
|
4803
|
+
const topLevelTagNames = [];
|
|
4804
|
+
let position = 0;
|
|
4805
|
+
while (position < fragment.length) {
|
|
4806
|
+
const ltIndex = fragment.indexOf("<", position);
|
|
4807
|
+
if (ltIndex === -1) {
|
|
4808
|
+
break;
|
|
4809
|
+
}
|
|
4810
|
+
const special = consumeXmlSpecialSection(fragment, ltIndex);
|
|
4811
|
+
if (special.kind === "incomplete") {
|
|
4812
|
+
return null;
|
|
4813
|
+
}
|
|
4814
|
+
if (special.kind === "consumed") {
|
|
4815
|
+
position = special.nextPos;
|
|
4816
|
+
continue;
|
|
4817
|
+
}
|
|
4818
|
+
const token = parseXmlTagToken(fragment, ltIndex);
|
|
4819
|
+
if (token === null) {
|
|
4820
|
+
return null;
|
|
4821
|
+
}
|
|
4822
|
+
if (token.kind === "close") {
|
|
4823
|
+
const openName = stack.pop();
|
|
4824
|
+
if (!openName || openName !== token.name) {
|
|
4825
|
+
return null;
|
|
4826
|
+
}
|
|
4827
|
+
position = token.nextPos;
|
|
4828
|
+
continue;
|
|
4829
|
+
}
|
|
4830
|
+
if (stack.length === 0) {
|
|
4831
|
+
topLevelTagNames.push(token.name);
|
|
4832
|
+
}
|
|
4833
|
+
if (!token.selfClosing) {
|
|
4834
|
+
stack.push(token.name);
|
|
4835
|
+
}
|
|
4836
|
+
position = token.nextPos;
|
|
4837
|
+
}
|
|
4838
|
+
if (stack.length > 0) {
|
|
4839
|
+
return null;
|
|
4840
|
+
}
|
|
4841
|
+
return { topLevelTagNames };
|
|
4842
|
+
}
|
|
4843
|
+
function scanXmlFragmentTopLevelTextStep(options) {
|
|
4844
|
+
const { fragment, position, stack } = options;
|
|
4845
|
+
const ltIndex = fragment.indexOf("<", position);
|
|
4846
|
+
if (ltIndex === -1) {
|
|
4847
|
+
const trailingText = fragment.slice(position);
|
|
4848
|
+
return {
|
|
4849
|
+
kind: "done",
|
|
4850
|
+
value: stack.length === 0 && trailingText.trim().length > 0
|
|
4851
|
+
};
|
|
4852
|
+
}
|
|
4853
|
+
const textBetweenTags = fragment.slice(position, ltIndex);
|
|
4854
|
+
if (stack.length === 0 && textBetweenTags.trim().length > 0) {
|
|
4855
|
+
return { kind: "found" };
|
|
4856
|
+
}
|
|
4857
|
+
const special = consumeXmlSpecialSection(fragment, ltIndex);
|
|
4858
|
+
if (special.kind === "incomplete") {
|
|
4859
|
+
return { kind: "invalid" };
|
|
4860
|
+
}
|
|
4861
|
+
if (special.kind === "consumed") {
|
|
4862
|
+
return { kind: "next", nextPos: special.nextPos };
|
|
4863
|
+
}
|
|
4864
|
+
const token = parseXmlTagToken(fragment, ltIndex);
|
|
4865
|
+
if (token === null) {
|
|
4866
|
+
return { kind: "invalid" };
|
|
4867
|
+
}
|
|
4868
|
+
if (token.kind === "close") {
|
|
4869
|
+
const openName = stack.pop();
|
|
4870
|
+
if (!openName || openName !== token.name) {
|
|
4871
|
+
return { kind: "invalid" };
|
|
4872
|
+
}
|
|
4873
|
+
} else if (!token.selfClosing) {
|
|
4874
|
+
stack.push(token.name);
|
|
4875
|
+
}
|
|
4876
|
+
return { kind: "next", nextPos: token.nextPos };
|
|
4877
|
+
}
|
|
4878
|
+
function hasNonWhitespaceTopLevelText(fragment) {
|
|
4879
|
+
if (!fragment.includes("<")) {
|
|
4880
|
+
return fragment.trim().length > 0;
|
|
4881
|
+
}
|
|
4882
|
+
const stack = [];
|
|
4883
|
+
let position = 0;
|
|
4884
|
+
while (position < fragment.length) {
|
|
4885
|
+
const step = scanXmlFragmentTopLevelTextStep({ fragment, position, stack });
|
|
4886
|
+
if (step.kind === "found") {
|
|
4887
|
+
return true;
|
|
4888
|
+
}
|
|
4889
|
+
if (step.kind === "invalid") {
|
|
4890
|
+
return false;
|
|
4891
|
+
}
|
|
4892
|
+
if (step.kind === "done") {
|
|
4893
|
+
return step.value;
|
|
4894
|
+
}
|
|
4895
|
+
position = step.nextPos;
|
|
4896
|
+
}
|
|
4897
|
+
return false;
|
|
4898
|
+
}
|
|
4899
|
+
function getObjectSchemaPropertyNames(schema) {
|
|
4900
|
+
if (!schema || typeof schema !== "object") {
|
|
4901
|
+
return null;
|
|
4902
|
+
}
|
|
4903
|
+
const schemaObject = schema;
|
|
4904
|
+
const typeValue = schemaObject.type;
|
|
4905
|
+
if (typeValue != null) {
|
|
4906
|
+
const isObjectType = typeValue === "object" || Array.isArray(typeValue) && typeValue.includes("object");
|
|
4907
|
+
if (!isObjectType) {
|
|
4908
|
+
return null;
|
|
4909
|
+
}
|
|
4910
|
+
}
|
|
4911
|
+
if (!schemaObject.properties || typeof schemaObject.properties !== "object") {
|
|
4912
|
+
return /* @__PURE__ */ new Set();
|
|
4913
|
+
}
|
|
4914
|
+
return new Set(
|
|
4915
|
+
Object.keys(schemaObject.properties)
|
|
4916
|
+
);
|
|
4917
|
+
}
|
|
4918
|
+
function schemaAllowsArrayType(schema) {
|
|
4919
|
+
if (!schema || typeof schema !== "object") {
|
|
4920
|
+
return false;
|
|
4921
|
+
}
|
|
4922
|
+
const schemaRecord = schema;
|
|
4923
|
+
const typeValue = schemaRecord.type;
|
|
4924
|
+
if (typeValue === "array") {
|
|
4925
|
+
return true;
|
|
4926
|
+
}
|
|
4927
|
+
if (Array.isArray(typeValue) && typeValue.includes("array")) {
|
|
4928
|
+
return true;
|
|
4929
|
+
}
|
|
4930
|
+
const unions = [schemaRecord.anyOf, schemaRecord.oneOf, schemaRecord.allOf];
|
|
4931
|
+
for (const union of unions) {
|
|
4932
|
+
if (!Array.isArray(union)) {
|
|
4933
|
+
continue;
|
|
4934
|
+
}
|
|
4935
|
+
if (union.some((entry) => schemaAllowsArrayType(entry))) {
|
|
4936
|
+
return true;
|
|
4937
|
+
}
|
|
4938
|
+
}
|
|
4939
|
+
return false;
|
|
4940
|
+
}
|
|
4941
|
+
function getSchemaObjectProperty(schema, propertyName) {
|
|
4942
|
+
if (!schema || typeof schema !== "object") {
|
|
4943
|
+
return null;
|
|
4944
|
+
}
|
|
4945
|
+
const schemaObject = schema;
|
|
4946
|
+
const properties = schemaObject.properties;
|
|
4947
|
+
if (!properties || typeof properties !== "object") {
|
|
4948
|
+
return null;
|
|
4949
|
+
}
|
|
4950
|
+
const property = properties[propertyName];
|
|
4951
|
+
if (!property) {
|
|
4952
|
+
return null;
|
|
4953
|
+
}
|
|
4954
|
+
return property;
|
|
4955
|
+
}
|
|
4956
|
+
function isStableXmlProgressCandidate(options) {
|
|
4957
|
+
const { candidate, parsed, toolSchema } = options;
|
|
4958
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4959
|
+
return false;
|
|
4960
|
+
}
|
|
4961
|
+
const structure = analyzeXmlFragmentForProgress(candidate);
|
|
4962
|
+
if (!structure) {
|
|
4963
|
+
return false;
|
|
4964
|
+
}
|
|
4965
|
+
const schemaProperties = getObjectSchemaPropertyNames(toolSchema);
|
|
4966
|
+
if (!schemaProperties || schemaProperties.size === 0) {
|
|
4967
|
+
return false;
|
|
4968
|
+
}
|
|
4969
|
+
const parsedObject = parsed;
|
|
4970
|
+
const uniqueTopLevelTags = new Set(structure.topLevelTagNames);
|
|
4971
|
+
for (const tagName of uniqueTopLevelTags) {
|
|
4972
|
+
if (!schemaProperties.has(tagName)) {
|
|
4973
|
+
continue;
|
|
4974
|
+
}
|
|
4975
|
+
const schemaProperty = getSchemaObjectProperty(toolSchema, tagName);
|
|
4976
|
+
if (schemaProperty && schemaAllowsArrayType(schemaProperty) && !Array.isArray(parsedObject[tagName])) {
|
|
4977
|
+
return false;
|
|
4978
|
+
}
|
|
4979
|
+
}
|
|
4980
|
+
if (structure.topLevelTagNames.length === 1) {
|
|
4981
|
+
const onlyTopLevelTag = structure.topLevelTagNames[0];
|
|
4982
|
+
if (!schemaProperties || schemaProperties.size === 0 || !schemaProperties.has(onlyTopLevelTag)) {
|
|
4983
|
+
return false;
|
|
4984
|
+
}
|
|
4985
|
+
}
|
|
4986
|
+
return true;
|
|
4987
|
+
}
|
|
4988
|
+
function parseXmlContentForStreamProgress({
|
|
4989
|
+
toolContent,
|
|
4990
|
+
toolSchema,
|
|
4991
|
+
parseOptions
|
|
4992
|
+
}) {
|
|
4993
|
+
const tryParse = (content) => {
|
|
4994
|
+
try {
|
|
4995
|
+
return parse3(content, toolSchema, {
|
|
4996
|
+
...parseOptions != null ? parseOptions : {},
|
|
4997
|
+
repair: false,
|
|
4998
|
+
onError: void 0
|
|
4999
|
+
});
|
|
5000
|
+
} catch (e) {
|
|
5001
|
+
return null;
|
|
5002
|
+
}
|
|
5003
|
+
};
|
|
5004
|
+
const strictFull = tryParse(toolContent);
|
|
5005
|
+
if (strictFull !== null && isStableXmlProgressCandidate({
|
|
5006
|
+
candidate: toolContent,
|
|
5007
|
+
parsed: strictFull,
|
|
5008
|
+
toolSchema
|
|
5009
|
+
})) {
|
|
5010
|
+
return JSON.stringify(strictFull);
|
|
5011
|
+
}
|
|
5012
|
+
let searchEnd = toolContent.length;
|
|
5013
|
+
while (searchEnd > 0) {
|
|
5014
|
+
const gtIndex = toolContent.lastIndexOf(">", searchEnd - 1);
|
|
5015
|
+
if (gtIndex === -1) {
|
|
5016
|
+
break;
|
|
5017
|
+
}
|
|
5018
|
+
const candidate = toolContent.slice(0, gtIndex + 1);
|
|
5019
|
+
if (!analyzeXmlFragmentForProgress(candidate)) {
|
|
5020
|
+
searchEnd = gtIndex;
|
|
5021
|
+
continue;
|
|
5022
|
+
}
|
|
5023
|
+
const parsedCandidate = tryParse(candidate);
|
|
5024
|
+
if (parsedCandidate !== null && isStableXmlProgressCandidate({
|
|
5025
|
+
candidate,
|
|
5026
|
+
parsed: parsedCandidate,
|
|
5027
|
+
toolSchema
|
|
5028
|
+
})) {
|
|
5029
|
+
return JSON.stringify(parsedCandidate);
|
|
5030
|
+
}
|
|
5031
|
+
searchEnd = gtIndex;
|
|
5032
|
+
}
|
|
5033
|
+
return null;
|
|
5034
|
+
}
|
|
4254
5035
|
function handleStreamingToolCallEnd(params) {
|
|
4255
5036
|
var _a, _b;
|
|
4256
5037
|
const {
|
|
@@ -4270,19 +5051,37 @@ function handleStreamingToolCallEnd(params) {
|
|
|
4270
5051
|
flushText(ctrl);
|
|
4271
5052
|
try {
|
|
4272
5053
|
const parsedResult = parse3(toolContent, toolSchema, parseConfig);
|
|
5054
|
+
const finalInput = JSON.stringify(parsedResult);
|
|
5055
|
+
emitFinalRemainder({
|
|
5056
|
+
controller: ctrl,
|
|
5057
|
+
id: currentToolCall.toolCallId,
|
|
5058
|
+
state: currentToolCall,
|
|
5059
|
+
finalFullJson: finalInput,
|
|
5060
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
5061
|
+
});
|
|
5062
|
+
ctrl.enqueue({
|
|
5063
|
+
type: "tool-input-end",
|
|
5064
|
+
id: currentToolCall.toolCallId
|
|
5065
|
+
});
|
|
4273
5066
|
ctrl.enqueue({
|
|
4274
5067
|
type: "tool-call",
|
|
4275
|
-
toolCallId:
|
|
5068
|
+
toolCallId: currentToolCall.toolCallId,
|
|
4276
5069
|
toolName: currentToolCall.name,
|
|
4277
|
-
input:
|
|
5070
|
+
input: finalInput
|
|
4278
5071
|
});
|
|
4279
5072
|
} catch (error) {
|
|
5073
|
+
ctrl.enqueue({
|
|
5074
|
+
type: "tool-input-end",
|
|
5075
|
+
id: currentToolCall.toolCallId
|
|
5076
|
+
});
|
|
4280
5077
|
const original = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
|
|
4281
5078
|
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
|
|
4282
5079
|
toolCall: original,
|
|
4283
5080
|
error
|
|
4284
5081
|
});
|
|
4285
|
-
|
|
5082
|
+
if (shouldEmitRawToolCallTextOnError2(options)) {
|
|
5083
|
+
flushText(ctrl, original);
|
|
5084
|
+
}
|
|
4286
5085
|
}
|
|
4287
5086
|
}
|
|
4288
5087
|
function findClosingTagEndFlexible(text, contentStart, toolName) {
|
|
@@ -4704,38 +5503,6 @@ function findPotentialToolTagStart(buffer, toolNames) {
|
|
|
4704
5503
|
}
|
|
4705
5504
|
return -1;
|
|
4706
5505
|
}
|
|
4707
|
-
function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
4708
|
-
return (controller, text) => {
|
|
4709
|
-
const content = text;
|
|
4710
|
-
if (content) {
|
|
4711
|
-
if (!getCurrentTextId()) {
|
|
4712
|
-
const newId = generateId();
|
|
4713
|
-
setCurrentTextId(newId);
|
|
4714
|
-
controller.enqueue({
|
|
4715
|
-
type: "text-start",
|
|
4716
|
-
id: newId
|
|
4717
|
-
});
|
|
4718
|
-
setHasEmittedTextStart(true);
|
|
4719
|
-
}
|
|
4720
|
-
controller.enqueue({
|
|
4721
|
-
type: "text-delta",
|
|
4722
|
-
id: getCurrentTextId(),
|
|
4723
|
-
delta: content
|
|
4724
|
-
});
|
|
4725
|
-
}
|
|
4726
|
-
const currentTextId = getCurrentTextId();
|
|
4727
|
-
if (currentTextId && !text) {
|
|
4728
|
-
if (getHasEmittedTextStart()) {
|
|
4729
|
-
controller.enqueue({
|
|
4730
|
-
type: "text-end",
|
|
4731
|
-
id: currentTextId
|
|
4732
|
-
});
|
|
4733
|
-
setHasEmittedTextStart(false);
|
|
4734
|
-
}
|
|
4735
|
-
setCurrentTextId(null);
|
|
4736
|
-
}
|
|
4737
|
-
};
|
|
4738
|
-
}
|
|
4739
5506
|
function processToolCallInBuffer(params) {
|
|
4740
5507
|
const {
|
|
4741
5508
|
buffer,
|
|
@@ -4745,18 +5512,21 @@ function processToolCallInBuffer(params) {
|
|
|
4745
5512
|
controller,
|
|
4746
5513
|
flushText,
|
|
4747
5514
|
setBuffer,
|
|
4748
|
-
parseOptions
|
|
5515
|
+
parseOptions,
|
|
5516
|
+
emitToolInputProgress: emitToolInputProgress2
|
|
4749
5517
|
} = params;
|
|
4750
5518
|
const endTagPattern = new RegExp(
|
|
4751
5519
|
`</\\s*${escapeRegExp(currentToolCall.name)}\\s*>`
|
|
4752
5520
|
);
|
|
4753
5521
|
const endMatch = endTagPattern.exec(buffer);
|
|
4754
5522
|
if (!endMatch || endMatch.index === void 0) {
|
|
5523
|
+
emitToolInputProgress2(controller, currentToolCall, buffer);
|
|
4755
5524
|
return { buffer, currentToolCall, shouldBreak: true };
|
|
4756
5525
|
}
|
|
4757
5526
|
const endIdx = endMatch.index;
|
|
4758
5527
|
const endPos = endIdx + endMatch[0].length;
|
|
4759
5528
|
const content = buffer.substring(0, endIdx);
|
|
5529
|
+
emitToolInputProgress2(controller, currentToolCall, content);
|
|
4760
5530
|
const remainder = buffer.substring(endPos);
|
|
4761
5531
|
setBuffer(remainder);
|
|
4762
5532
|
handleStreamingToolCallEnd({
|
|
@@ -4783,7 +5553,8 @@ function processNoToolCallInBuffer(params) {
|
|
|
4783
5553
|
tools,
|
|
4784
5554
|
options,
|
|
4785
5555
|
parseOptions,
|
|
4786
|
-
setBuffer
|
|
5556
|
+
setBuffer,
|
|
5557
|
+
emitToolInputStart
|
|
4787
5558
|
} = params;
|
|
4788
5559
|
const {
|
|
4789
5560
|
index: earliestStartTagIndex,
|
|
@@ -4813,9 +5584,10 @@ function processNoToolCallInBuffer(params) {
|
|
|
4813
5584
|
if (selfClosing) {
|
|
4814
5585
|
const newBuffer2 = buffer.substring(earliestStartTagIndex + tagLength);
|
|
4815
5586
|
setBuffer(newBuffer2);
|
|
5587
|
+
const currentToolCall = emitToolInputStart(controller, earliestToolName);
|
|
4816
5588
|
handleStreamingToolCallEnd({
|
|
4817
5589
|
toolContent: "",
|
|
4818
|
-
currentToolCall
|
|
5590
|
+
currentToolCall,
|
|
4819
5591
|
tools,
|
|
4820
5592
|
options,
|
|
4821
5593
|
ctrl: controller,
|
|
@@ -4834,12 +5606,12 @@ function processNoToolCallInBuffer(params) {
|
|
|
4834
5606
|
setBuffer(newBuffer);
|
|
4835
5607
|
return {
|
|
4836
5608
|
buffer: newBuffer,
|
|
4837
|
-
currentToolCall:
|
|
5609
|
+
currentToolCall: emitToolInputStart(controller, earliestToolName),
|
|
4838
5610
|
shouldBreak: false,
|
|
4839
5611
|
shouldContinue: true
|
|
4840
5612
|
};
|
|
4841
5613
|
}
|
|
4842
|
-
function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions) {
|
|
5614
|
+
function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions, emitToolInputProgress2, emitToolInputStart) {
|
|
4843
5615
|
return (controller) => {
|
|
4844
5616
|
while (true) {
|
|
4845
5617
|
const currentToolCall = getCurrentToolCall();
|
|
@@ -4852,7 +5624,8 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
4852
5624
|
controller,
|
|
4853
5625
|
flushText,
|
|
4854
5626
|
setBuffer,
|
|
4855
|
-
parseOptions
|
|
5627
|
+
parseOptions,
|
|
5628
|
+
emitToolInputProgress: emitToolInputProgress2
|
|
4856
5629
|
});
|
|
4857
5630
|
setBuffer(result.buffer);
|
|
4858
5631
|
setCurrentToolCall(result.currentToolCall);
|
|
@@ -4868,7 +5641,8 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
4868
5641
|
tools,
|
|
4869
5642
|
options,
|
|
4870
5643
|
parseOptions,
|
|
4871
|
-
setBuffer
|
|
5644
|
+
setBuffer,
|
|
5645
|
+
emitToolInputStart
|
|
4872
5646
|
});
|
|
4873
5647
|
setBuffer(result.buffer);
|
|
4874
5648
|
setCurrentToolCall(result.currentToolCall);
|
|
@@ -4982,6 +5756,118 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4982
5756
|
hasEmittedTextStart = value;
|
|
4983
5757
|
}
|
|
4984
5758
|
);
|
|
5759
|
+
const emitToolInputStart = (controller, toolName) => {
|
|
5760
|
+
flushText(controller);
|
|
5761
|
+
const next = {
|
|
5762
|
+
name: toolName,
|
|
5763
|
+
toolCallId: generateToolCallId(),
|
|
5764
|
+
emittedInput: "",
|
|
5765
|
+
lastProgressGtIndex: null,
|
|
5766
|
+
lastProgressFullInput: null
|
|
5767
|
+
};
|
|
5768
|
+
controller.enqueue({
|
|
5769
|
+
type: "tool-input-start",
|
|
5770
|
+
id: next.toolCallId,
|
|
5771
|
+
toolName
|
|
5772
|
+
});
|
|
5773
|
+
return next;
|
|
5774
|
+
};
|
|
5775
|
+
const emitToolInputProgress2 = (controller, toolCall, toolContent) => {
|
|
5776
|
+
const progressGtIndex = toolContent.lastIndexOf(">");
|
|
5777
|
+
if (toolCall.lastProgressGtIndex === progressGtIndex) {
|
|
5778
|
+
const cached = toolCall.lastProgressFullInput;
|
|
5779
|
+
if (cached == null) {
|
|
5780
|
+
return;
|
|
5781
|
+
}
|
|
5782
|
+
if (cached === "{}" && toolContent.trim().length === 0) {
|
|
5783
|
+
return;
|
|
5784
|
+
}
|
|
5785
|
+
const prefixCandidate2 = toIncompleteJsonPrefix(cached);
|
|
5786
|
+
emitPrefixDelta({
|
|
5787
|
+
controller,
|
|
5788
|
+
id: toolCall.toolCallId,
|
|
5789
|
+
state: toolCall,
|
|
5790
|
+
candidate: prefixCandidate2
|
|
5791
|
+
});
|
|
5792
|
+
return;
|
|
5793
|
+
}
|
|
5794
|
+
const toolSchema = getToolSchema(tools, toolCall.name);
|
|
5795
|
+
const fullInput = parseXmlContentForStreamProgress({
|
|
5796
|
+
toolContent,
|
|
5797
|
+
toolSchema,
|
|
5798
|
+
parseOptions
|
|
5799
|
+
});
|
|
5800
|
+
toolCall.lastProgressGtIndex = progressGtIndex;
|
|
5801
|
+
toolCall.lastProgressFullInput = fullInput;
|
|
5802
|
+
if (fullInput == null) {
|
|
5803
|
+
return;
|
|
5804
|
+
}
|
|
5805
|
+
if (fullInput === "{}" && toolContent.trim().length === 0) {
|
|
5806
|
+
return;
|
|
5807
|
+
}
|
|
5808
|
+
const prefixCandidate = toIncompleteJsonPrefix(fullInput);
|
|
5809
|
+
emitPrefixDelta({
|
|
5810
|
+
controller,
|
|
5811
|
+
id: toolCall.toolCallId,
|
|
5812
|
+
state: toolCall,
|
|
5813
|
+
candidate: prefixCandidate
|
|
5814
|
+
});
|
|
5815
|
+
};
|
|
5816
|
+
const finalizeUnclosedToolCall = (controller) => {
|
|
5817
|
+
var _a2, _b;
|
|
5818
|
+
if (!currentToolCall) {
|
|
5819
|
+
return;
|
|
5820
|
+
}
|
|
5821
|
+
emitToolInputProgress2(controller, currentToolCall, buffer);
|
|
5822
|
+
const parseConfig = {
|
|
5823
|
+
...parseOptions,
|
|
5824
|
+
onError: (_a2 = options == null ? void 0 : options.onError) != null ? _a2 : parseOptions == null ? void 0 : parseOptions.onError
|
|
5825
|
+
};
|
|
5826
|
+
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
5827
|
+
flushText(controller);
|
|
5828
|
+
try {
|
|
5829
|
+
if (hasNonWhitespaceTopLevelText(buffer)) {
|
|
5830
|
+
throw new Error(
|
|
5831
|
+
"Cannot reconcile unclosed XML tool call with top-level plain text."
|
|
5832
|
+
);
|
|
5833
|
+
}
|
|
5834
|
+
const parsedResult = parse3(buffer, toolSchema, parseConfig);
|
|
5835
|
+
const finalInput = JSON.stringify(parsedResult);
|
|
5836
|
+
emitFinalRemainder({
|
|
5837
|
+
controller,
|
|
5838
|
+
id: currentToolCall.toolCallId,
|
|
5839
|
+
state: currentToolCall,
|
|
5840
|
+
finalFullJson: finalInput,
|
|
5841
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
5842
|
+
});
|
|
5843
|
+
controller.enqueue({
|
|
5844
|
+
type: "tool-input-end",
|
|
5845
|
+
id: currentToolCall.toolCallId
|
|
5846
|
+
});
|
|
5847
|
+
controller.enqueue({
|
|
5848
|
+
type: "tool-call",
|
|
5849
|
+
toolCallId: currentToolCall.toolCallId,
|
|
5850
|
+
toolName: currentToolCall.name,
|
|
5851
|
+
input: finalInput
|
|
5852
|
+
});
|
|
5853
|
+
} catch (error) {
|
|
5854
|
+
controller.enqueue({
|
|
5855
|
+
type: "tool-input-end",
|
|
5856
|
+
id: currentToolCall.toolCallId
|
|
5857
|
+
});
|
|
5858
|
+
const unfinishedContent = `<${currentToolCall.name}>${buffer}`;
|
|
5859
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
5860
|
+
options,
|
|
5861
|
+
"Could not complete streaming XML tool call at finish.",
|
|
5862
|
+
{ toolCall: unfinishedContent, error }
|
|
5863
|
+
);
|
|
5864
|
+
if (shouldEmitRawToolCallTextOnError2(options)) {
|
|
5865
|
+
flushText(controller, unfinishedContent);
|
|
5866
|
+
}
|
|
5867
|
+
}
|
|
5868
|
+
buffer = "";
|
|
5869
|
+
currentToolCall = null;
|
|
5870
|
+
};
|
|
4985
5871
|
const processBuffer = createProcessBufferHandler(
|
|
4986
5872
|
() => buffer,
|
|
4987
5873
|
(newBuffer) => {
|
|
@@ -4995,17 +5881,17 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4995
5881
|
options,
|
|
4996
5882
|
toolNames,
|
|
4997
5883
|
flushText,
|
|
4998
|
-
parseOptions
|
|
5884
|
+
parseOptions,
|
|
5885
|
+
emitToolInputProgress2,
|
|
5886
|
+
emitToolInputStart
|
|
4999
5887
|
);
|
|
5000
5888
|
return new TransformStream({
|
|
5889
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Stateful stream parsing requires branching over chunk lifecycle and parser states.
|
|
5001
5890
|
transform(chunk, controller) {
|
|
5002
5891
|
var _a2;
|
|
5003
5892
|
if (chunk.type === "finish") {
|
|
5004
5893
|
if (currentToolCall) {
|
|
5005
|
-
|
|
5006
|
-
flushText(controller, unfinishedContent);
|
|
5007
|
-
buffer = "";
|
|
5008
|
-
currentToolCall = null;
|
|
5894
|
+
finalizeUnclosedToolCall(controller);
|
|
5009
5895
|
} else if (buffer) {
|
|
5010
5896
|
flushText(controller, buffer);
|
|
5011
5897
|
buffer = "";
|
|
@@ -5015,7 +5901,8 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
5015
5901
|
return;
|
|
5016
5902
|
}
|
|
5017
5903
|
if (chunk.type !== "text-delta") {
|
|
5018
|
-
if (
|
|
5904
|
+
if (currentToolCall) {
|
|
5905
|
+
} else if (buffer) {
|
|
5019
5906
|
flushText(controller, buffer);
|
|
5020
5907
|
buffer = "";
|
|
5021
5908
|
}
|
|
@@ -5028,10 +5915,7 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
5028
5915
|
},
|
|
5029
5916
|
flush(controller) {
|
|
5030
5917
|
if (currentToolCall) {
|
|
5031
|
-
|
|
5032
|
-
flushText(controller, unfinishedContent);
|
|
5033
|
-
buffer = "";
|
|
5034
|
-
currentToolCall = null;
|
|
5918
|
+
finalizeUnclosedToolCall(controller);
|
|
5035
5919
|
} else if (buffer) {
|
|
5036
5920
|
flushText(controller, buffer);
|
|
5037
5921
|
buffer = "";
|
|
@@ -5059,7 +5943,205 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
5059
5943
|
|
|
5060
5944
|
// src/core/protocols/yaml-protocol.ts
|
|
5061
5945
|
var import_yaml = __toESM(require("yaml"), 1);
|
|
5946
|
+
function shouldEmitRawToolCallTextOnError3(options) {
|
|
5947
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
5948
|
+
}
|
|
5949
|
+
var selfClosingTagCache2 = /* @__PURE__ */ new Map();
|
|
5950
|
+
function getSelfClosingTagPattern2(toolName) {
|
|
5951
|
+
let pattern = selfClosingTagCache2.get(toolName);
|
|
5952
|
+
if (!pattern) {
|
|
5953
|
+
pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
|
|
5954
|
+
selfClosingTagCache2.set(toolName, pattern);
|
|
5955
|
+
}
|
|
5956
|
+
return pattern;
|
|
5957
|
+
}
|
|
5062
5958
|
var LEADING_WHITESPACE_RE = /^(\s*)/;
|
|
5959
|
+
var INCOMPLETE_MAPPING_TAIL_RE = /^[^:[\]{}-][^:]*:\s*$/;
|
|
5960
|
+
var INCOMPLETE_SEQUENCE_TAIL_RE = /^-\s*$/;
|
|
5961
|
+
var BLOCK_SCALAR_KEY_RE = /:\s*[|>][-+0-9]*\s*$/;
|
|
5962
|
+
var PLAIN_MAPPING_VALUE_RE = /^[^:[\]{}-][^:]*:\s*(.+)$/;
|
|
5963
|
+
var PLAIN_SEQUENCE_VALUE_RE = /^-\s+(.+)$/;
|
|
5964
|
+
function normalizeYamlContent(yamlContent) {
|
|
5965
|
+
let normalized = yamlContent;
|
|
5966
|
+
if (normalized.startsWith("\n")) {
|
|
5967
|
+
normalized = normalized.slice(1);
|
|
5968
|
+
}
|
|
5969
|
+
const lines = normalized.split("\n");
|
|
5970
|
+
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
|
5971
|
+
if (nonEmptyLines.length === 0) {
|
|
5972
|
+
return { normalized: "", nonEmptyLines };
|
|
5973
|
+
}
|
|
5974
|
+
const minIndent = Math.min(
|
|
5975
|
+
...nonEmptyLines.map((line) => {
|
|
5976
|
+
const match = line.match(LEADING_WHITESPACE_RE);
|
|
5977
|
+
return match ? match[1].length : 0;
|
|
5978
|
+
})
|
|
5979
|
+
);
|
|
5980
|
+
if (minIndent > 0) {
|
|
5981
|
+
normalized = lines.map((line) => line.slice(minIndent)).join("\n");
|
|
5982
|
+
}
|
|
5983
|
+
return { normalized, nonEmptyLines };
|
|
5984
|
+
}
|
|
5985
|
+
function parseYamlDocumentAsMapping(normalized) {
|
|
5986
|
+
try {
|
|
5987
|
+
const doc = import_yaml.default.parseDocument(normalized);
|
|
5988
|
+
const errors = doc.errors.map((e) => e.message);
|
|
5989
|
+
const result = doc.toJSON();
|
|
5990
|
+
if (result === null) {
|
|
5991
|
+
return { value: {}, errors };
|
|
5992
|
+
}
|
|
5993
|
+
if (typeof result !== "object" || Array.isArray(result)) {
|
|
5994
|
+
return { value: null, errors };
|
|
5995
|
+
}
|
|
5996
|
+
return { value: result, errors };
|
|
5997
|
+
} catch (error) {
|
|
5998
|
+
return {
|
|
5999
|
+
value: null,
|
|
6000
|
+
errors: [
|
|
6001
|
+
error instanceof Error ? error.message : "Unknown YAML parsing error"
|
|
6002
|
+
]
|
|
6003
|
+
};
|
|
6004
|
+
}
|
|
6005
|
+
}
|
|
6006
|
+
function getLastMeaningfulLineInfo(input) {
|
|
6007
|
+
var _a;
|
|
6008
|
+
const lines = input.split("\n");
|
|
6009
|
+
let index = lines.length - 1;
|
|
6010
|
+
while (index >= 0) {
|
|
6011
|
+
const raw = (_a = lines[index]) != null ? _a : "";
|
|
6012
|
+
const trimmed = raw.trim();
|
|
6013
|
+
if (trimmed.length > 0 && !trimmed.startsWith("#")) {
|
|
6014
|
+
return {
|
|
6015
|
+
index,
|
|
6016
|
+
raw,
|
|
6017
|
+
trimmed,
|
|
6018
|
+
indent: raw.length - raw.trimStart().length
|
|
6019
|
+
};
|
|
6020
|
+
}
|
|
6021
|
+
index -= 1;
|
|
6022
|
+
}
|
|
6023
|
+
return null;
|
|
6024
|
+
}
|
|
6025
|
+
function dropLastMeaningfulLine(input) {
|
|
6026
|
+
const lineInfo = getLastMeaningfulLineInfo(input);
|
|
6027
|
+
if (!lineInfo) {
|
|
6028
|
+
return null;
|
|
6029
|
+
}
|
|
6030
|
+
return input.split("\n").slice(0, lineInfo.index).join("\n").trimEnd();
|
|
6031
|
+
}
|
|
6032
|
+
function hasIncompleteMappingTail(normalized) {
|
|
6033
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6034
|
+
if (!lineInfo) {
|
|
6035
|
+
return false;
|
|
6036
|
+
}
|
|
6037
|
+
return INCOMPLETE_MAPPING_TAIL_RE.test(lineInfo.trimmed);
|
|
6038
|
+
}
|
|
6039
|
+
function hasIncompleteSequenceTail(normalized) {
|
|
6040
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6041
|
+
if (!lineInfo) {
|
|
6042
|
+
return false;
|
|
6043
|
+
}
|
|
6044
|
+
return INCOMPLETE_SEQUENCE_TAIL_RE.test(lineInfo.trimmed);
|
|
6045
|
+
}
|
|
6046
|
+
function hasSplitNestedKeyTail(normalized) {
|
|
6047
|
+
var _a;
|
|
6048
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6049
|
+
if (!lineInfo) {
|
|
6050
|
+
return false;
|
|
6051
|
+
}
|
|
6052
|
+
const { trimmed, indent, index } = lineInfo;
|
|
6053
|
+
if (indent === 0) {
|
|
6054
|
+
return false;
|
|
6055
|
+
}
|
|
6056
|
+
if (trimmed.startsWith("#") || trimmed.startsWith("-") || trimmed.includes(":")) {
|
|
6057
|
+
return false;
|
|
6058
|
+
}
|
|
6059
|
+
const lines = normalized.split("\n");
|
|
6060
|
+
let parentIndex = index - 1;
|
|
6061
|
+
while (parentIndex >= 0) {
|
|
6062
|
+
const parentRaw = (_a = lines[parentIndex]) != null ? _a : "";
|
|
6063
|
+
const parentTrimmed = parentRaw.trim();
|
|
6064
|
+
if (parentTrimmed.length === 0 || parentTrimmed.startsWith("#")) {
|
|
6065
|
+
parentIndex -= 1;
|
|
6066
|
+
continue;
|
|
6067
|
+
}
|
|
6068
|
+
const parentIndent = parentRaw.length - parentRaw.trimStart().length;
|
|
6069
|
+
if (parentIndent >= indent) {
|
|
6070
|
+
parentIndex -= 1;
|
|
6071
|
+
continue;
|
|
6072
|
+
}
|
|
6073
|
+
if (!parentTrimmed.endsWith(":")) {
|
|
6074
|
+
return false;
|
|
6075
|
+
}
|
|
6076
|
+
if (BLOCK_SCALAR_KEY_RE.test(parentTrimmed)) {
|
|
6077
|
+
return false;
|
|
6078
|
+
}
|
|
6079
|
+
return true;
|
|
6080
|
+
}
|
|
6081
|
+
return false;
|
|
6082
|
+
}
|
|
6083
|
+
function extractTrailingPlainScalarValue(line) {
|
|
6084
|
+
var _a;
|
|
6085
|
+
if (BLOCK_SCALAR_KEY_RE.test(line)) {
|
|
6086
|
+
return null;
|
|
6087
|
+
}
|
|
6088
|
+
const mappingMatch = line.match(PLAIN_MAPPING_VALUE_RE);
|
|
6089
|
+
const sequenceMatch = line.match(PLAIN_SEQUENCE_VALUE_RE);
|
|
6090
|
+
const value = (_a = mappingMatch == null ? void 0 : mappingMatch[1]) != null ? _a : sequenceMatch == null ? void 0 : sequenceMatch[1];
|
|
6091
|
+
if (!value) {
|
|
6092
|
+
return null;
|
|
6093
|
+
}
|
|
6094
|
+
const trimmedValue = value.trim();
|
|
6095
|
+
if (trimmedValue.length === 0) {
|
|
6096
|
+
return null;
|
|
6097
|
+
}
|
|
6098
|
+
if (trimmedValue.startsWith('"') || trimmedValue.startsWith("'")) {
|
|
6099
|
+
return null;
|
|
6100
|
+
}
|
|
6101
|
+
if (trimmedValue.startsWith("{") || trimmedValue.startsWith("[") || trimmedValue.startsWith("|") || trimmedValue.startsWith(">")) {
|
|
6102
|
+
return null;
|
|
6103
|
+
}
|
|
6104
|
+
return trimmedValue;
|
|
6105
|
+
}
|
|
6106
|
+
function hasUnterminatedPlainScalarTail(normalized) {
|
|
6107
|
+
if (normalized.endsWith("\n")) {
|
|
6108
|
+
return false;
|
|
6109
|
+
}
|
|
6110
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6111
|
+
if (!lineInfo) {
|
|
6112
|
+
return false;
|
|
6113
|
+
}
|
|
6114
|
+
return extractTrailingPlainScalarValue(lineInfo.trimmed) != null;
|
|
6115
|
+
}
|
|
6116
|
+
function hasUnstableProgressTail(normalized) {
|
|
6117
|
+
return hasIncompleteMappingTail(normalized) || hasIncompleteSequenceTail(normalized) || hasSplitNestedKeyTail(normalized) || hasUnterminatedPlainScalarTail(normalized);
|
|
6118
|
+
}
|
|
6119
|
+
function trimTrailingNewlineInUnknown(value) {
|
|
6120
|
+
if (typeof value === "string") {
|
|
6121
|
+
if (value.endsWith("\n")) {
|
|
6122
|
+
return value.slice(0, -1);
|
|
6123
|
+
}
|
|
6124
|
+
return value;
|
|
6125
|
+
}
|
|
6126
|
+
if (Array.isArray(value)) {
|
|
6127
|
+
return value.map((item) => trimTrailingNewlineInUnknown(item));
|
|
6128
|
+
}
|
|
6129
|
+
if (value && typeof value === "object") {
|
|
6130
|
+
return Object.fromEntries(
|
|
6131
|
+
Object.entries(value).map(([key, item]) => [
|
|
6132
|
+
key,
|
|
6133
|
+
trimTrailingNewlineInUnknown(item)
|
|
6134
|
+
])
|
|
6135
|
+
);
|
|
6136
|
+
}
|
|
6137
|
+
return value;
|
|
6138
|
+
}
|
|
6139
|
+
function stabilizeParsedValueForStreamProgress(value, source) {
|
|
6140
|
+
if (source.endsWith("\n")) {
|
|
6141
|
+
return value;
|
|
6142
|
+
}
|
|
6143
|
+
return trimTrailingNewlineInUnknown(value);
|
|
6144
|
+
}
|
|
5063
6145
|
function findClosingTagEnd(text, contentStart, toolName) {
|
|
5064
6146
|
let pos = contentStart;
|
|
5065
6147
|
let depth = 1;
|
|
@@ -5131,9 +6213,9 @@ function findEarliestTagPosition(openIdx, selfIdx) {
|
|
|
5131
6213
|
function collectToolCallsForName(text, toolName) {
|
|
5132
6214
|
const toolCalls = [];
|
|
5133
6215
|
let searchIndex = 0;
|
|
5134
|
-
const
|
|
6216
|
+
const startTag = `<${toolName}>`;
|
|
6217
|
+
const selfTagRegex = getSelfClosingTagPattern2(toolName);
|
|
5135
6218
|
while (searchIndex < text.length) {
|
|
5136
|
-
const startTag = `<${toolName}>`;
|
|
5137
6219
|
const openIdx = text.indexOf(startTag, searchIndex);
|
|
5138
6220
|
selfTagRegex.lastIndex = searchIndex;
|
|
5139
6221
|
const selfMatch = selfTagRegex.exec(text);
|
|
@@ -5183,47 +6265,48 @@ function findToolCalls2(text, toolNames) {
|
|
|
5183
6265
|
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
5184
6266
|
}
|
|
5185
6267
|
function parseYamlContent(yamlContent, options) {
|
|
5186
|
-
var _a, _b
|
|
5187
|
-
|
|
5188
|
-
if (normalized.startsWith("\n")) {
|
|
5189
|
-
normalized = normalized.slice(1);
|
|
5190
|
-
}
|
|
5191
|
-
const lines = normalized.split("\n");
|
|
5192
|
-
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
|
6268
|
+
var _a, _b;
|
|
6269
|
+
const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
|
|
5193
6270
|
if (nonEmptyLines.length === 0) {
|
|
5194
6271
|
return {};
|
|
5195
6272
|
}
|
|
5196
|
-
const
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
})
|
|
5201
|
-
|
|
5202
|
-
if (minIndent > 0) {
|
|
5203
|
-
normalized = lines.map((line) => line.slice(minIndent)).join("\n");
|
|
6273
|
+
const parsed = parseYamlDocumentAsMapping(normalized);
|
|
6274
|
+
if (parsed.errors.length > 0) {
|
|
6275
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "YAML parse error", {
|
|
6276
|
+
errors: parsed.errors
|
|
6277
|
+
});
|
|
6278
|
+
return null;
|
|
5204
6279
|
}
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
6280
|
+
if (parsed.value === null) {
|
|
6281
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
|
|
6282
|
+
got: "non-mapping"
|
|
6283
|
+
});
|
|
6284
|
+
return null;
|
|
6285
|
+
}
|
|
6286
|
+
return parsed.value;
|
|
6287
|
+
}
|
|
6288
|
+
function parseYamlContentForStreamProgress(yamlContent) {
|
|
6289
|
+
const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
|
|
6290
|
+
if (nonEmptyLines.length === 0) {
|
|
6291
|
+
return {};
|
|
6292
|
+
}
|
|
6293
|
+
let candidate = normalized;
|
|
6294
|
+
while (true) {
|
|
6295
|
+
const parsed = parseYamlDocumentAsMapping(candidate);
|
|
6296
|
+
if (parsed.errors.length === 0 && !hasUnstableProgressTail(candidate)) {
|
|
6297
|
+
if (candidate.trim().length === 0 && normalized.trim().length > 0) {
|
|
6298
|
+
return null;
|
|
6299
|
+
}
|
|
6300
|
+
return stabilizeParsedValueForStreamProgress(parsed.value, candidate);
|
|
5212
6301
|
}
|
|
5213
|
-
const
|
|
5214
|
-
if (
|
|
5215
|
-
return
|
|
6302
|
+
const truncated = dropLastMeaningfulLine(candidate);
|
|
6303
|
+
if (truncated == null) {
|
|
6304
|
+
return null;
|
|
5216
6305
|
}
|
|
5217
|
-
if (
|
|
5218
|
-
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
|
|
5219
|
-
got: typeof result
|
|
5220
|
-
});
|
|
6306
|
+
if (truncated === candidate) {
|
|
5221
6307
|
return null;
|
|
5222
6308
|
}
|
|
5223
|
-
|
|
5224
|
-
} catch (error) {
|
|
5225
|
-
(_c = options == null ? void 0 : options.onError) == null ? void 0 : _c.call(options, "Failed to parse YAML content", { error });
|
|
5226
|
-
return null;
|
|
6309
|
+
candidate = truncated;
|
|
5227
6310
|
}
|
|
5228
6311
|
}
|
|
5229
6312
|
function processToolCallMatch(text, tc, currentIndex, processedElements, options) {
|
|
@@ -5239,7 +6322,7 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
|
|
|
5239
6322
|
if (parsedArgs !== null) {
|
|
5240
6323
|
processedElements.push({
|
|
5241
6324
|
type: "tool-call",
|
|
5242
|
-
toolCallId:
|
|
6325
|
+
toolCallId: generateToolCallId(),
|
|
5243
6326
|
toolName: tc.toolName,
|
|
5244
6327
|
input: JSON.stringify(parsedArgs)
|
|
5245
6328
|
});
|
|
@@ -5252,38 +6335,6 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
|
|
|
5252
6335
|
}
|
|
5253
6336
|
return tc.endIndex;
|
|
5254
6337
|
}
|
|
5255
|
-
function createFlushTextHandler2(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
5256
|
-
return (controller, text) => {
|
|
5257
|
-
const content = text;
|
|
5258
|
-
if (content) {
|
|
5259
|
-
if (!getCurrentTextId()) {
|
|
5260
|
-
const newId = generateId();
|
|
5261
|
-
setCurrentTextId(newId);
|
|
5262
|
-
controller.enqueue({
|
|
5263
|
-
type: "text-start",
|
|
5264
|
-
id: newId
|
|
5265
|
-
});
|
|
5266
|
-
setHasEmittedTextStart(true);
|
|
5267
|
-
}
|
|
5268
|
-
controller.enqueue({
|
|
5269
|
-
type: "text-delta",
|
|
5270
|
-
id: getCurrentTextId(),
|
|
5271
|
-
delta: content
|
|
5272
|
-
});
|
|
5273
|
-
}
|
|
5274
|
-
const currentTextId = getCurrentTextId();
|
|
5275
|
-
if (currentTextId && !text) {
|
|
5276
|
-
if (getHasEmittedTextStart()) {
|
|
5277
|
-
controller.enqueue({
|
|
5278
|
-
type: "text-end",
|
|
5279
|
-
id: currentTextId
|
|
5280
|
-
});
|
|
5281
|
-
setHasEmittedTextStart(false);
|
|
5282
|
-
}
|
|
5283
|
-
setCurrentTextId(null);
|
|
5284
|
-
}
|
|
5285
|
-
};
|
|
5286
|
-
}
|
|
5287
6338
|
function findEarliestToolTag2(buffer, toolNames) {
|
|
5288
6339
|
let bestIndex = -1;
|
|
5289
6340
|
let bestName = "";
|
|
@@ -5291,8 +6342,9 @@ function findEarliestToolTag2(buffer, toolNames) {
|
|
|
5291
6342
|
let bestTagLength = 0;
|
|
5292
6343
|
for (const name of toolNames) {
|
|
5293
6344
|
const openTag = `<${name}>`;
|
|
5294
|
-
const selfTagRegex =
|
|
6345
|
+
const selfTagRegex = getSelfClosingTagPattern2(name);
|
|
5295
6346
|
const idxOpen = buffer.indexOf(openTag);
|
|
6347
|
+
selfTagRegex.lastIndex = 0;
|
|
5296
6348
|
const selfMatch = selfTagRegex.exec(buffer);
|
|
5297
6349
|
const idxSelf = selfMatch ? selfMatch.index : -1;
|
|
5298
6350
|
if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
|
|
@@ -5315,6 +6367,29 @@ function findEarliestToolTag2(buffer, toolNames) {
|
|
|
5315
6367
|
tagLength: bestTagLength
|
|
5316
6368
|
};
|
|
5317
6369
|
}
|
|
6370
|
+
function stripTrailingPartialCloseTag(content, toolName) {
|
|
6371
|
+
const closeTag = `</${toolName}>`;
|
|
6372
|
+
const lastLineBreakIndex = Math.max(
|
|
6373
|
+
content.lastIndexOf("\n"),
|
|
6374
|
+
content.lastIndexOf("\r")
|
|
6375
|
+
);
|
|
6376
|
+
const lineStartIndex = lastLineBreakIndex === -1 ? 0 : lastLineBreakIndex + 1;
|
|
6377
|
+
const trailingLine = content.slice(lineStartIndex);
|
|
6378
|
+
const trimmedTrailingLine = trailingLine.trim();
|
|
6379
|
+
if (trimmedTrailingLine.length === 0 || !trimmedTrailingLine.startsWith("</") || trimmedTrailingLine === closeTag || !closeTag.startsWith(trimmedTrailingLine)) {
|
|
6380
|
+
return content;
|
|
6381
|
+
}
|
|
6382
|
+
const leadingWhitespaceLength = trailingLine.length - trailingLine.trimStart().length;
|
|
6383
|
+
const preservedLeadingWhitespace = trailingLine.slice(
|
|
6384
|
+
0,
|
|
6385
|
+
leadingWhitespaceLength
|
|
6386
|
+
);
|
|
6387
|
+
const contentWithoutPartial = `${content.slice(
|
|
6388
|
+
0,
|
|
6389
|
+
lineStartIndex
|
|
6390
|
+
)}${preservedLeadingWhitespace}`;
|
|
6391
|
+
return contentWithoutPartial.trimEnd();
|
|
6392
|
+
}
|
|
5318
6393
|
var yamlProtocol = (_protocolOptions) => {
|
|
5319
6394
|
return {
|
|
5320
6395
|
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
@@ -5375,7 +6450,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5375
6450
|
let currentToolCall = null;
|
|
5376
6451
|
let currentTextId = null;
|
|
5377
6452
|
let hasEmittedTextStart = false;
|
|
5378
|
-
const flushText =
|
|
6453
|
+
const flushText = createFlushTextHandler(
|
|
5379
6454
|
() => currentTextId,
|
|
5380
6455
|
(newId) => {
|
|
5381
6456
|
currentTextId = newId;
|
|
@@ -5385,33 +6460,128 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5385
6460
|
hasEmittedTextStart = value;
|
|
5386
6461
|
}
|
|
5387
6462
|
);
|
|
5388
|
-
const
|
|
6463
|
+
const emitToolInputProgress2 = (controller, toolContent) => {
|
|
6464
|
+
if (!currentToolCall) {
|
|
6465
|
+
return;
|
|
6466
|
+
}
|
|
6467
|
+
const parsedArgs = parseYamlContentForStreamProgress(toolContent);
|
|
6468
|
+
if (parsedArgs === null) {
|
|
6469
|
+
return;
|
|
6470
|
+
}
|
|
6471
|
+
const fullInput = JSON.stringify(parsedArgs);
|
|
6472
|
+
if (fullInput === "{}" && toolContent.trim().length === 0) {
|
|
6473
|
+
return;
|
|
6474
|
+
}
|
|
6475
|
+
const prefixCandidate = toIncompleteJsonPrefix(fullInput);
|
|
6476
|
+
emitPrefixDelta({
|
|
6477
|
+
controller,
|
|
6478
|
+
id: currentToolCall.toolCallId,
|
|
6479
|
+
state: currentToolCall,
|
|
6480
|
+
candidate: prefixCandidate
|
|
6481
|
+
});
|
|
6482
|
+
};
|
|
6483
|
+
const processToolCallEnd = (controller, toolContent, toolName, toolCallId) => {
|
|
5389
6484
|
var _a;
|
|
5390
6485
|
const parsedArgs = parseYamlContent(toolContent, options);
|
|
5391
6486
|
flushText(controller);
|
|
5392
6487
|
if (parsedArgs !== null) {
|
|
6488
|
+
const finalInput = JSON.stringify(parsedArgs);
|
|
6489
|
+
if (currentToolCall && currentToolCall.toolCallId === toolCallId) {
|
|
6490
|
+
emitFinalRemainder({
|
|
6491
|
+
controller,
|
|
6492
|
+
id: toolCallId,
|
|
6493
|
+
state: currentToolCall,
|
|
6494
|
+
finalFullJson: finalInput,
|
|
6495
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
6496
|
+
});
|
|
6497
|
+
}
|
|
6498
|
+
controller.enqueue({
|
|
6499
|
+
type: "tool-input-end",
|
|
6500
|
+
id: toolCallId
|
|
6501
|
+
});
|
|
5393
6502
|
controller.enqueue({
|
|
5394
6503
|
type: "tool-call",
|
|
5395
|
-
toolCallId
|
|
6504
|
+
toolCallId,
|
|
5396
6505
|
toolName,
|
|
5397
|
-
input:
|
|
6506
|
+
input: finalInput
|
|
5398
6507
|
});
|
|
5399
6508
|
} else {
|
|
6509
|
+
controller.enqueue({
|
|
6510
|
+
type: "tool-input-end",
|
|
6511
|
+
id: toolCallId
|
|
6512
|
+
});
|
|
5400
6513
|
const original = `<${toolName}>${toolContent}</${toolName}>`;
|
|
5401
6514
|
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
|
|
5402
6515
|
toolCall: original
|
|
5403
6516
|
});
|
|
5404
|
-
|
|
6517
|
+
if (shouldEmitRawToolCallTextOnError3(options)) {
|
|
6518
|
+
flushText(controller, original);
|
|
6519
|
+
}
|
|
5405
6520
|
}
|
|
5406
6521
|
};
|
|
6522
|
+
const finalizeUnclosedToolCall = (controller) => {
|
|
6523
|
+
var _a;
|
|
6524
|
+
if (!currentToolCall) {
|
|
6525
|
+
return;
|
|
6526
|
+
}
|
|
6527
|
+
emitToolInputProgress2(controller, buffer);
|
|
6528
|
+
const { name: toolName, toolCallId } = currentToolCall;
|
|
6529
|
+
const reconciledBuffer = stripTrailingPartialCloseTag(buffer, toolName);
|
|
6530
|
+
const parsedArgs = parseYamlContent(reconciledBuffer, options);
|
|
6531
|
+
flushText(controller);
|
|
6532
|
+
if (parsedArgs !== null) {
|
|
6533
|
+
const finalInput = JSON.stringify(parsedArgs);
|
|
6534
|
+
emitFinalRemainder({
|
|
6535
|
+
controller,
|
|
6536
|
+
id: toolCallId,
|
|
6537
|
+
state: currentToolCall,
|
|
6538
|
+
finalFullJson: finalInput,
|
|
6539
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
6540
|
+
});
|
|
6541
|
+
controller.enqueue({
|
|
6542
|
+
type: "tool-input-end",
|
|
6543
|
+
id: toolCallId
|
|
6544
|
+
});
|
|
6545
|
+
controller.enqueue({
|
|
6546
|
+
type: "tool-call",
|
|
6547
|
+
toolCallId,
|
|
6548
|
+
toolName,
|
|
6549
|
+
input: finalInput
|
|
6550
|
+
});
|
|
6551
|
+
} else {
|
|
6552
|
+
controller.enqueue({
|
|
6553
|
+
type: "tool-input-end",
|
|
6554
|
+
id: toolCallId
|
|
6555
|
+
});
|
|
6556
|
+
const unfinishedContent = `<${toolName}>${buffer}`;
|
|
6557
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
6558
|
+
options,
|
|
6559
|
+
"Could not complete streaming YAML tool call at finish.",
|
|
6560
|
+
{ toolCall: unfinishedContent }
|
|
6561
|
+
);
|
|
6562
|
+
if (shouldEmitRawToolCallTextOnError3(options)) {
|
|
6563
|
+
flushText(controller, unfinishedContent);
|
|
6564
|
+
}
|
|
6565
|
+
}
|
|
6566
|
+
buffer = "";
|
|
6567
|
+
currentToolCall = null;
|
|
6568
|
+
};
|
|
5407
6569
|
const handlePendingToolCall = (controller, endTag, toolName) => {
|
|
6570
|
+
var _a;
|
|
5408
6571
|
const endIdx = buffer.indexOf(endTag);
|
|
5409
6572
|
if (endIdx === -1) {
|
|
6573
|
+
emitToolInputProgress2(controller, buffer);
|
|
5410
6574
|
return false;
|
|
5411
6575
|
}
|
|
5412
6576
|
const content = buffer.substring(0, endIdx);
|
|
6577
|
+
emitToolInputProgress2(controller, content);
|
|
5413
6578
|
buffer = buffer.substring(endIdx + endTag.length);
|
|
5414
|
-
processToolCallEnd(
|
|
6579
|
+
processToolCallEnd(
|
|
6580
|
+
controller,
|
|
6581
|
+
content,
|
|
6582
|
+
toolName,
|
|
6583
|
+
(_a = currentToolCall == null ? void 0 : currentToolCall.toolCallId) != null ? _a : generateToolCallId()
|
|
6584
|
+
);
|
|
5415
6585
|
currentToolCall = null;
|
|
5416
6586
|
return true;
|
|
5417
6587
|
};
|
|
@@ -5428,13 +6598,35 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5428
6598
|
if (tagIndex > 0) {
|
|
5429
6599
|
flushText(controller, buffer.substring(0, tagIndex));
|
|
5430
6600
|
}
|
|
6601
|
+
flushText(controller);
|
|
5431
6602
|
if (selfClosing) {
|
|
5432
6603
|
buffer = buffer.substring(tagIndex + tagLength);
|
|
5433
|
-
|
|
6604
|
+
const toolCallId = generateToolCallId();
|
|
6605
|
+
currentToolCall = {
|
|
6606
|
+
name: tagName,
|
|
6607
|
+
toolCallId,
|
|
6608
|
+
emittedInput: ""
|
|
6609
|
+
};
|
|
6610
|
+
controller.enqueue({
|
|
6611
|
+
type: "tool-input-start",
|
|
6612
|
+
id: toolCallId,
|
|
6613
|
+
toolName: tagName
|
|
6614
|
+
});
|
|
6615
|
+
processToolCallEnd(controller, "", tagName, toolCallId);
|
|
6616
|
+
currentToolCall = null;
|
|
5434
6617
|
} else {
|
|
5435
6618
|
const startTag = `<${tagName}>`;
|
|
5436
6619
|
buffer = buffer.substring(tagIndex + startTag.length);
|
|
5437
|
-
currentToolCall = {
|
|
6620
|
+
currentToolCall = {
|
|
6621
|
+
name: tagName,
|
|
6622
|
+
toolCallId: generateToolCallId(),
|
|
6623
|
+
emittedInput: ""
|
|
6624
|
+
};
|
|
6625
|
+
controller.enqueue({
|
|
6626
|
+
type: "tool-input-start",
|
|
6627
|
+
id: currentToolCall.toolCallId,
|
|
6628
|
+
toolName: tagName
|
|
6629
|
+
});
|
|
5438
6630
|
}
|
|
5439
6631
|
};
|
|
5440
6632
|
const processBuffer = (controller) => {
|
|
@@ -5463,10 +6655,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5463
6655
|
var _a;
|
|
5464
6656
|
if (chunk.type === "finish") {
|
|
5465
6657
|
if (currentToolCall) {
|
|
5466
|
-
|
|
5467
|
-
flushText(controller, unfinishedContent);
|
|
5468
|
-
buffer = "";
|
|
5469
|
-
currentToolCall = null;
|
|
6658
|
+
finalizeUnclosedToolCall(controller);
|
|
5470
6659
|
} else if (buffer) {
|
|
5471
6660
|
flushText(controller, buffer);
|
|
5472
6661
|
buffer = "";
|
|
@@ -5476,7 +6665,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5476
6665
|
return;
|
|
5477
6666
|
}
|
|
5478
6667
|
if (chunk.type !== "text-delta") {
|
|
5479
|
-
if (buffer) {
|
|
6668
|
+
if (!currentToolCall && buffer) {
|
|
5480
6669
|
flushText(controller, buffer);
|
|
5481
6670
|
buffer = "";
|
|
5482
6671
|
}
|
|
@@ -5489,10 +6678,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5489
6678
|
},
|
|
5490
6679
|
flush(controller) {
|
|
5491
6680
|
if (currentToolCall) {
|
|
5492
|
-
|
|
5493
|
-
flushText(controller, unfinishedContent);
|
|
5494
|
-
buffer = "";
|
|
5495
|
-
currentToolCall = null;
|
|
6681
|
+
finalizeUnclosedToolCall(controller);
|
|
5496
6682
|
} else if (buffer) {
|
|
5497
6683
|
flushText(controller, buffer);
|
|
5498
6684
|
buffer = "";
|
|
@@ -5670,9 +6856,6 @@ function hasInputProperty(obj) {
|
|
|
5670
6856
|
return typeof obj === "object" && obj !== null && "input" in obj;
|
|
5671
6857
|
}
|
|
5672
6858
|
|
|
5673
|
-
// src/generate-handler.ts
|
|
5674
|
-
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
5675
|
-
|
|
5676
6859
|
// src/core/utils/generated-text-json-recovery.ts
|
|
5677
6860
|
function isRecord(value) {
|
|
5678
6861
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -5811,7 +6994,7 @@ function mergeJsonCandidatesByStart(tagged, codeBlocks, balanced) {
|
|
|
5811
6994
|
function toToolCallPart(candidate) {
|
|
5812
6995
|
return {
|
|
5813
6996
|
type: "tool-call",
|
|
5814
|
-
toolCallId:
|
|
6997
|
+
toolCallId: generateToolCallId(),
|
|
5815
6998
|
toolName: candidate.toolName,
|
|
5816
6999
|
input: candidate.input
|
|
5817
7000
|
};
|
|
@@ -6038,7 +7221,7 @@ async function handleToolChoice(doGenerate, params, tools) {
|
|
|
6038
7221
|
}
|
|
6039
7222
|
const toolCall = {
|
|
6040
7223
|
type: "tool-call",
|
|
6041
|
-
toolCallId: (
|
|
7224
|
+
toolCallId: generateToolCallId(),
|
|
6042
7225
|
toolName,
|
|
6043
7226
|
input
|
|
6044
7227
|
};
|
|
@@ -6548,7 +7731,6 @@ unit: celsius
|
|
|
6548
7731
|
}
|
|
6549
7732
|
|
|
6550
7733
|
// src/stream-handler.ts
|
|
6551
|
-
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
6552
7734
|
async function wrapStream({
|
|
6553
7735
|
protocol,
|
|
6554
7736
|
doStream,
|
|
@@ -6586,10 +7768,22 @@ async function wrapStream({
|
|
|
6586
7768
|
}
|
|
6587
7769
|
)
|
|
6588
7770
|
).pipeThrough(protocol.createStreamParser({ tools, options }));
|
|
7771
|
+
let seenToolCall = false;
|
|
6589
7772
|
const v3Stream = coreStream.pipeThrough(
|
|
6590
7773
|
new TransformStream({
|
|
6591
7774
|
transform(part, controller) {
|
|
6592
|
-
|
|
7775
|
+
let normalizedPart = part.type === "tool-call" ? coerceToolCallPart(part, tools) : part;
|
|
7776
|
+
if (normalizedPart.type === "tool-call") {
|
|
7777
|
+
seenToolCall = true;
|
|
7778
|
+
}
|
|
7779
|
+
if (normalizedPart.type === "finish" && seenToolCall && normalizedPart.finishReason.unified === "stop") {
|
|
7780
|
+
normalizedPart = {
|
|
7781
|
+
...normalizedPart,
|
|
7782
|
+
finishReason: normalizeToolCallsFinishReason(
|
|
7783
|
+
normalizedPart.finishReason
|
|
7784
|
+
)
|
|
7785
|
+
};
|
|
7786
|
+
}
|
|
6593
7787
|
if (debugLevel === "stream") {
|
|
6594
7788
|
logParsedChunk(normalizedPart);
|
|
6595
7789
|
}
|
|
@@ -6626,7 +7820,7 @@ async function toolChoiceStream({
|
|
|
6626
7820
|
start(controller) {
|
|
6627
7821
|
controller.enqueue({
|
|
6628
7822
|
type: "tool-call",
|
|
6629
|
-
toolCallId: (
|
|
7823
|
+
toolCallId: generateToolCallId(),
|
|
6630
7824
|
toolName,
|
|
6631
7825
|
input
|
|
6632
7826
|
});
|