@ai-sdk-tool/parser 3.3.3 → 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-NAQSTPDQ.js → chunk-ERJKQKCR.js} +1372 -205
- package/dist/chunk-ERJKQKCR.js.map +1 -0
- package/dist/community.cjs +1390 -223
- package/dist/community.cjs.map +1 -1
- package/dist/community.js +1 -1
- package/dist/index.cjs +1390 -223
- 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 +1 -1
- package/package.json +7 -7
- package/dist/chunk-NAQSTPDQ.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -905,7 +905,25 @@ function getPotentialStartIndex(text, searchedText) {
|
|
|
905
905
|
|
|
906
906
|
// src/core/utils/id.ts
|
|
907
907
|
function generateId() {
|
|
908
|
-
return
|
|
908
|
+
return crypto.randomUUID().replace(/-/g, "").slice(0, 13);
|
|
909
|
+
}
|
|
910
|
+
var TOOL_CALL_ID_PREFIX = "call_";
|
|
911
|
+
var TOOL_CALL_ID_BODY_LENGTH = 24;
|
|
912
|
+
var TOOL_CALL_ID_ALPHANUM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
913
|
+
function randomAlphaNumeric(length) {
|
|
914
|
+
var _a;
|
|
915
|
+
const bytes = new Uint8Array(length);
|
|
916
|
+
crypto.getRandomValues(bytes);
|
|
917
|
+
let out = "";
|
|
918
|
+
for (let i = 0; i < length; i += 1) {
|
|
919
|
+
const byte = bytes[i];
|
|
920
|
+
const index = (byte != null ? byte : 0) % TOOL_CALL_ID_ALPHANUM.length;
|
|
921
|
+
out += (_a = TOOL_CALL_ID_ALPHANUM[index]) != null ? _a : "0";
|
|
922
|
+
}
|
|
923
|
+
return out;
|
|
924
|
+
}
|
|
925
|
+
function generateToolCallId() {
|
|
926
|
+
return `${TOOL_CALL_ID_PREFIX}${randomAlphaNumeric(TOOL_CALL_ID_BODY_LENGTH)}`;
|
|
909
927
|
}
|
|
910
928
|
|
|
911
929
|
// src/core/utils/protocol-utils.ts
|
|
@@ -914,6 +932,38 @@ function addTextSegment(text, processedElements) {
|
|
|
914
932
|
processedElements.push({ type: "text", text });
|
|
915
933
|
}
|
|
916
934
|
}
|
|
935
|
+
function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
936
|
+
return (controller, text) => {
|
|
937
|
+
const content = text;
|
|
938
|
+
if (content) {
|
|
939
|
+
if (!getCurrentTextId()) {
|
|
940
|
+
const newId = generateId();
|
|
941
|
+
setCurrentTextId(newId);
|
|
942
|
+
controller.enqueue({
|
|
943
|
+
type: "text-start",
|
|
944
|
+
id: newId
|
|
945
|
+
});
|
|
946
|
+
setHasEmittedTextStart(true);
|
|
947
|
+
}
|
|
948
|
+
controller.enqueue({
|
|
949
|
+
type: "text-delta",
|
|
950
|
+
id: getCurrentTextId(),
|
|
951
|
+
delta: content
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
const currentTextId = getCurrentTextId();
|
|
955
|
+
if (currentTextId && !text) {
|
|
956
|
+
if (getHasEmittedTextStart()) {
|
|
957
|
+
controller.enqueue({
|
|
958
|
+
type: "text-end",
|
|
959
|
+
id: currentTextId
|
|
960
|
+
});
|
|
961
|
+
setHasEmittedTextStart(false);
|
|
962
|
+
}
|
|
963
|
+
setCurrentTextId(null);
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
}
|
|
917
967
|
|
|
918
968
|
// src/core/utils/regex.ts
|
|
919
969
|
function escapeRegExp(literal) {
|
|
@@ -921,15 +971,21 @@ function escapeRegExp(literal) {
|
|
|
921
971
|
}
|
|
922
972
|
|
|
923
973
|
// src/core/protocols/json-protocol.ts
|
|
974
|
+
function shouldEmitRawToolCallTextOnError(options) {
|
|
975
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
976
|
+
}
|
|
977
|
+
function canonicalizeToolInput(argumentsValue) {
|
|
978
|
+
return JSON.stringify(argumentsValue != null ? argumentsValue : {});
|
|
979
|
+
}
|
|
924
980
|
function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
|
|
925
|
-
var _a
|
|
981
|
+
var _a;
|
|
926
982
|
try {
|
|
927
983
|
const parsedToolCall = parse(toolCallJson);
|
|
928
984
|
processedElements.push({
|
|
929
985
|
type: "tool-call",
|
|
930
|
-
toolCallId:
|
|
986
|
+
toolCallId: generateToolCallId(),
|
|
931
987
|
toolName: parsedToolCall.name,
|
|
932
|
-
input:
|
|
988
|
+
input: canonicalizeToolInput(parsedToolCall.arguments)
|
|
933
989
|
});
|
|
934
990
|
} catch (error) {
|
|
935
991
|
logParseFailure({
|
|
@@ -938,7 +994,7 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
|
|
|
938
994
|
snippet: fullMatch,
|
|
939
995
|
error
|
|
940
996
|
});
|
|
941
|
-
(
|
|
997
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
942
998
|
options,
|
|
943
999
|
"Could not process JSON tool call, keeping original text.",
|
|
944
1000
|
{ toolCall: fullMatch, error }
|
|
@@ -959,6 +1015,293 @@ function processMatchedToolCall(context) {
|
|
|
959
1015
|
}
|
|
960
1016
|
return startIndex + match[0].length;
|
|
961
1017
|
}
|
|
1018
|
+
var WHITESPACE_JSON_REGEX = /\s/;
|
|
1019
|
+
function skipJsonWhitespace(text, fromIndex) {
|
|
1020
|
+
let index = fromIndex;
|
|
1021
|
+
while (index < text.length && WHITESPACE_JSON_REGEX.test(text[index])) {
|
|
1022
|
+
index += 1;
|
|
1023
|
+
}
|
|
1024
|
+
return index;
|
|
1025
|
+
}
|
|
1026
|
+
function findTopLevelPropertyValueStart(text, property) {
|
|
1027
|
+
const objectStart = skipJsonWhitespace(text, 0);
|
|
1028
|
+
if (objectStart >= text.length || text.charAt(objectStart) !== "{") {
|
|
1029
|
+
return null;
|
|
1030
|
+
}
|
|
1031
|
+
let depth = 0;
|
|
1032
|
+
let inString = false;
|
|
1033
|
+
let escaping = false;
|
|
1034
|
+
for (let index = objectStart; index < text.length; index += 1) {
|
|
1035
|
+
const char = text.charAt(index);
|
|
1036
|
+
if (inString) {
|
|
1037
|
+
if (escaping) {
|
|
1038
|
+
escaping = false;
|
|
1039
|
+
continue;
|
|
1040
|
+
}
|
|
1041
|
+
if (char === "\\") {
|
|
1042
|
+
escaping = true;
|
|
1043
|
+
continue;
|
|
1044
|
+
}
|
|
1045
|
+
if (char === '"') {
|
|
1046
|
+
inString = false;
|
|
1047
|
+
}
|
|
1048
|
+
continue;
|
|
1049
|
+
}
|
|
1050
|
+
if (char === "{") {
|
|
1051
|
+
depth += 1;
|
|
1052
|
+
continue;
|
|
1053
|
+
}
|
|
1054
|
+
if (char === "}") {
|
|
1055
|
+
depth = Math.max(0, depth - 1);
|
|
1056
|
+
continue;
|
|
1057
|
+
}
|
|
1058
|
+
if (char !== '"') {
|
|
1059
|
+
continue;
|
|
1060
|
+
}
|
|
1061
|
+
if (depth !== 1) {
|
|
1062
|
+
inString = true;
|
|
1063
|
+
continue;
|
|
1064
|
+
}
|
|
1065
|
+
const keyStart = index + 1;
|
|
1066
|
+
let keyEnd = keyStart;
|
|
1067
|
+
let keyEscaped = false;
|
|
1068
|
+
while (keyEnd < text.length) {
|
|
1069
|
+
const keyChar = text.charAt(keyEnd);
|
|
1070
|
+
if (keyEscaped) {
|
|
1071
|
+
keyEscaped = false;
|
|
1072
|
+
} else if (keyChar === "\\") {
|
|
1073
|
+
keyEscaped = true;
|
|
1074
|
+
} else if (keyChar === '"') {
|
|
1075
|
+
break;
|
|
1076
|
+
}
|
|
1077
|
+
keyEnd += 1;
|
|
1078
|
+
}
|
|
1079
|
+
if (keyEnd >= text.length || text.charAt(keyEnd) !== '"') {
|
|
1080
|
+
return null;
|
|
1081
|
+
}
|
|
1082
|
+
const key = text.slice(keyStart, keyEnd);
|
|
1083
|
+
let valueCursor = skipJsonWhitespace(text, keyEnd + 1);
|
|
1084
|
+
if (valueCursor >= text.length || text.charAt(valueCursor) !== ":") {
|
|
1085
|
+
index = keyEnd;
|
|
1086
|
+
continue;
|
|
1087
|
+
}
|
|
1088
|
+
valueCursor = skipJsonWhitespace(text, valueCursor + 1);
|
|
1089
|
+
if (key === property) {
|
|
1090
|
+
return valueCursor < text.length ? valueCursor : null;
|
|
1091
|
+
}
|
|
1092
|
+
index = valueCursor - 1;
|
|
1093
|
+
}
|
|
1094
|
+
return null;
|
|
1095
|
+
}
|
|
1096
|
+
function extractTopLevelStringProperty(text, property) {
|
|
1097
|
+
const valueStart = findTopLevelPropertyValueStart(text, property);
|
|
1098
|
+
if (valueStart == null || valueStart >= text.length) {
|
|
1099
|
+
return void 0;
|
|
1100
|
+
}
|
|
1101
|
+
if (text.charAt(valueStart) !== '"') {
|
|
1102
|
+
return void 0;
|
|
1103
|
+
}
|
|
1104
|
+
let valueEnd = valueStart + 1;
|
|
1105
|
+
let escaped = false;
|
|
1106
|
+
while (valueEnd < text.length) {
|
|
1107
|
+
const char = text.charAt(valueEnd);
|
|
1108
|
+
if (escaped) {
|
|
1109
|
+
escaped = false;
|
|
1110
|
+
} else if (char === "\\") {
|
|
1111
|
+
escaped = true;
|
|
1112
|
+
} else if (char === '"') {
|
|
1113
|
+
return text.slice(valueStart + 1, valueEnd);
|
|
1114
|
+
}
|
|
1115
|
+
valueEnd += 1;
|
|
1116
|
+
}
|
|
1117
|
+
return void 0;
|
|
1118
|
+
}
|
|
1119
|
+
function extractJsonValueSlice(text, valueStart) {
|
|
1120
|
+
if (valueStart >= text.length) {
|
|
1121
|
+
return null;
|
|
1122
|
+
}
|
|
1123
|
+
const first = text.charAt(valueStart);
|
|
1124
|
+
if (first === "{" || first === "[") {
|
|
1125
|
+
const stack = [first];
|
|
1126
|
+
let inString = false;
|
|
1127
|
+
let escaped = false;
|
|
1128
|
+
for (let index2 = valueStart + 1; index2 < text.length; index2 += 1) {
|
|
1129
|
+
const char = text.charAt(index2);
|
|
1130
|
+
if (inString) {
|
|
1131
|
+
if (escaped) {
|
|
1132
|
+
escaped = false;
|
|
1133
|
+
} else if (char === "\\") {
|
|
1134
|
+
escaped = true;
|
|
1135
|
+
} else if (char === '"') {
|
|
1136
|
+
inString = false;
|
|
1137
|
+
}
|
|
1138
|
+
continue;
|
|
1139
|
+
}
|
|
1140
|
+
if (char === '"') {
|
|
1141
|
+
inString = true;
|
|
1142
|
+
continue;
|
|
1143
|
+
}
|
|
1144
|
+
if (char === "{" || char === "[") {
|
|
1145
|
+
stack.push(char);
|
|
1146
|
+
continue;
|
|
1147
|
+
}
|
|
1148
|
+
if (char === "}" || char === "]") {
|
|
1149
|
+
const open = stack.at(-1);
|
|
1150
|
+
if (open === "{" && char === "}" || open === "[" && char === "]") {
|
|
1151
|
+
stack.pop();
|
|
1152
|
+
if (stack.length === 0) {
|
|
1153
|
+
return {
|
|
1154
|
+
text: text.slice(valueStart, index2 + 1),
|
|
1155
|
+
complete: true
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
return {
|
|
1162
|
+
text: text.slice(valueStart),
|
|
1163
|
+
complete: false
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
if (first === '"') {
|
|
1167
|
+
let escaped = false;
|
|
1168
|
+
for (let index2 = valueStart + 1; index2 < text.length; index2 += 1) {
|
|
1169
|
+
const char = text.charAt(index2);
|
|
1170
|
+
if (escaped) {
|
|
1171
|
+
escaped = false;
|
|
1172
|
+
} else if (char === "\\") {
|
|
1173
|
+
escaped = true;
|
|
1174
|
+
} else if (char === '"') {
|
|
1175
|
+
return {
|
|
1176
|
+
text: text.slice(valueStart, index2 + 1),
|
|
1177
|
+
complete: true
|
|
1178
|
+
};
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
return {
|
|
1182
|
+
text: text.slice(valueStart),
|
|
1183
|
+
complete: false
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
1186
|
+
let index = valueStart;
|
|
1187
|
+
while (index < text.length) {
|
|
1188
|
+
const char = text.charAt(index);
|
|
1189
|
+
if (char === "," || char === "}" || WHITESPACE_JSON_REGEX.test(char)) {
|
|
1190
|
+
break;
|
|
1191
|
+
}
|
|
1192
|
+
index += 1;
|
|
1193
|
+
}
|
|
1194
|
+
return {
|
|
1195
|
+
text: text.slice(valueStart, index),
|
|
1196
|
+
complete: index < text.length
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
function extractStreamingToolCallProgress(toolCallJson) {
|
|
1200
|
+
var _a;
|
|
1201
|
+
const toolName = extractTopLevelStringProperty(toolCallJson, "name");
|
|
1202
|
+
const argsValueStart = findTopLevelPropertyValueStart(
|
|
1203
|
+
toolCallJson,
|
|
1204
|
+
"arguments"
|
|
1205
|
+
);
|
|
1206
|
+
if (argsValueStart == null) {
|
|
1207
|
+
return {
|
|
1208
|
+
toolName,
|
|
1209
|
+
argumentsText: void 0,
|
|
1210
|
+
argumentsComplete: false
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
const argsSlice = extractJsonValueSlice(toolCallJson, argsValueStart);
|
|
1214
|
+
return {
|
|
1215
|
+
toolName,
|
|
1216
|
+
argumentsText: argsSlice == null ? void 0 : argsSlice.text,
|
|
1217
|
+
argumentsComplete: (_a = argsSlice == null ? void 0 : argsSlice.complete) != null ? _a : false
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
function ensureToolInputStart(state, controller, toolName) {
|
|
1221
|
+
if (!state.activeToolInput) {
|
|
1222
|
+
const id = generateToolCallId();
|
|
1223
|
+
state.activeToolInput = {
|
|
1224
|
+
id,
|
|
1225
|
+
toolName,
|
|
1226
|
+
emittedInput: ""
|
|
1227
|
+
};
|
|
1228
|
+
controller.enqueue({
|
|
1229
|
+
type: "tool-input-start",
|
|
1230
|
+
id,
|
|
1231
|
+
toolName
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
function emitToolInputDelta(state, controller, fullInput) {
|
|
1236
|
+
const active = state.activeToolInput;
|
|
1237
|
+
if (!active) {
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
if (!fullInput.startsWith(active.emittedInput)) {
|
|
1241
|
+
return;
|
|
1242
|
+
}
|
|
1243
|
+
const delta = fullInput.slice(active.emittedInput.length);
|
|
1244
|
+
if (delta.length === 0) {
|
|
1245
|
+
return;
|
|
1246
|
+
}
|
|
1247
|
+
controller.enqueue({
|
|
1248
|
+
type: "tool-input-delta",
|
|
1249
|
+
id: active.id,
|
|
1250
|
+
delta
|
|
1251
|
+
});
|
|
1252
|
+
active.emittedInput = fullInput;
|
|
1253
|
+
}
|
|
1254
|
+
function closeToolInput(state, controller) {
|
|
1255
|
+
if (!state.activeToolInput) {
|
|
1256
|
+
return;
|
|
1257
|
+
}
|
|
1258
|
+
controller.enqueue({
|
|
1259
|
+
type: "tool-input-end",
|
|
1260
|
+
id: state.activeToolInput.id
|
|
1261
|
+
});
|
|
1262
|
+
state.activeToolInput = null;
|
|
1263
|
+
}
|
|
1264
|
+
function emitToolCallFromParsed(state, controller, parsedToolCall) {
|
|
1265
|
+
var _a, _b, _c, _d;
|
|
1266
|
+
closeTextBlock(state, controller);
|
|
1267
|
+
const toolName = typeof parsedToolCall.name === "string" ? parsedToolCall.name : (_b = (_a = state.activeToolInput) == null ? void 0 : _a.toolName) != null ? _b : "unknown";
|
|
1268
|
+
const input = canonicalizeToolInput(parsedToolCall.arguments);
|
|
1269
|
+
ensureToolInputStart(state, controller, toolName);
|
|
1270
|
+
emitToolInputDelta(state, controller, input);
|
|
1271
|
+
const toolCallId = (_d = (_c = state.activeToolInput) == null ? void 0 : _c.id) != null ? _d : generateToolCallId();
|
|
1272
|
+
closeToolInput(state, controller);
|
|
1273
|
+
controller.enqueue({
|
|
1274
|
+
type: "tool-call",
|
|
1275
|
+
toolCallId,
|
|
1276
|
+
toolName,
|
|
1277
|
+
input
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
function canonicalizeArgumentsProgressInput(progress) {
|
|
1281
|
+
if (progress.argumentsText === void 0 || !progress.argumentsComplete) {
|
|
1282
|
+
return void 0;
|
|
1283
|
+
}
|
|
1284
|
+
try {
|
|
1285
|
+
const parsedArguments = parse(progress.argumentsText);
|
|
1286
|
+
return canonicalizeToolInput(parsedArguments);
|
|
1287
|
+
} catch (e) {
|
|
1288
|
+
return void 0;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
function emitToolInputProgress(state, controller) {
|
|
1292
|
+
if (!(state.isInsideToolCall && state.currentToolCallJson)) {
|
|
1293
|
+
return;
|
|
1294
|
+
}
|
|
1295
|
+
const progress = extractStreamingToolCallProgress(state.currentToolCallJson);
|
|
1296
|
+
if (!progress.toolName) {
|
|
1297
|
+
return;
|
|
1298
|
+
}
|
|
1299
|
+
ensureToolInputStart(state, controller, progress.toolName);
|
|
1300
|
+
const canonicalProgressInput = canonicalizeArgumentsProgressInput(progress);
|
|
1301
|
+
if (canonicalProgressInput !== void 0) {
|
|
1302
|
+
emitToolInputDelta(state, controller, canonicalProgressInput);
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
962
1305
|
function flushBuffer(state, controller, toolCallStart) {
|
|
963
1306
|
if (state.buffer.length === 0) {
|
|
964
1307
|
return;
|
|
@@ -989,44 +1332,77 @@ function closeTextBlock(state, controller) {
|
|
|
989
1332
|
state.hasEmittedTextStart = false;
|
|
990
1333
|
}
|
|
991
1334
|
}
|
|
992
|
-
function emitIncompleteToolCall(state, controller, toolCallStart) {
|
|
993
|
-
|
|
1335
|
+
function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer, options) {
|
|
1336
|
+
var _a;
|
|
1337
|
+
if (!state.currentToolCallJson && trailingBuffer.length === 0) {
|
|
1338
|
+
state.isInsideToolCall = false;
|
|
994
1339
|
return;
|
|
995
1340
|
}
|
|
1341
|
+
if (state.currentToolCallJson) {
|
|
1342
|
+
try {
|
|
1343
|
+
const parsedToolCall = parse(state.currentToolCallJson);
|
|
1344
|
+
emitToolCallFromParsed(state, controller, parsedToolCall);
|
|
1345
|
+
state.currentToolCallJson = "";
|
|
1346
|
+
state.isInsideToolCall = false;
|
|
1347
|
+
return;
|
|
1348
|
+
} catch (e) {
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
const rawToolCallContent = `${state.currentToolCallJson}${trailingBuffer}`;
|
|
1352
|
+
const errorContent = `${toolCallStart}${rawToolCallContent}`;
|
|
1353
|
+
const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
|
|
996
1354
|
logParseFailure({
|
|
997
1355
|
phase: "stream",
|
|
998
|
-
reason: "Incomplete streaming tool call segment emitted as text",
|
|
999
|
-
snippet:
|
|
1000
|
-
});
|
|
1001
|
-
const errorId = generateId();
|
|
1002
|
-
const errorContent = `${toolCallStart}${state.currentToolCallJson}`;
|
|
1003
|
-
controller.enqueue({
|
|
1004
|
-
type: "text-start",
|
|
1005
|
-
id: errorId
|
|
1006
|
-
});
|
|
1007
|
-
controller.enqueue({
|
|
1008
|
-
type: "text-delta",
|
|
1009
|
-
id: errorId,
|
|
1010
|
-
delta: errorContent
|
|
1011
|
-
});
|
|
1012
|
-
controller.enqueue({
|
|
1013
|
-
type: "text-end",
|
|
1014
|
-
id: errorId
|
|
1356
|
+
reason: shouldEmitRawFallback ? "Incomplete streaming tool call segment emitted as text" : "Incomplete streaming tool call segment suppressed without raw text fallback",
|
|
1357
|
+
snippet: errorContent
|
|
1015
1358
|
});
|
|
1359
|
+
if (shouldEmitRawFallback) {
|
|
1360
|
+
const errorId = generateId();
|
|
1361
|
+
controller.enqueue({
|
|
1362
|
+
type: "text-start",
|
|
1363
|
+
id: errorId
|
|
1364
|
+
});
|
|
1365
|
+
controller.enqueue({
|
|
1366
|
+
type: "text-delta",
|
|
1367
|
+
id: errorId,
|
|
1368
|
+
delta: errorContent
|
|
1369
|
+
});
|
|
1370
|
+
controller.enqueue({
|
|
1371
|
+
type: "text-end",
|
|
1372
|
+
id: errorId
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
closeToolInput(state, controller);
|
|
1376
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1377
|
+
options,
|
|
1378
|
+
shouldEmitRawFallback ? "Could not complete streaming JSON tool call at finish; emitting original text." : "Could not complete streaming JSON tool call at finish.",
|
|
1379
|
+
{ toolCall: errorContent }
|
|
1380
|
+
);
|
|
1016
1381
|
state.currentToolCallJson = "";
|
|
1382
|
+
state.isInsideToolCall = false;
|
|
1017
1383
|
}
|
|
1018
|
-
function handleFinishChunk(state, controller, toolCallStart, chunk) {
|
|
1019
|
-
if (state.
|
|
1384
|
+
function handleFinishChunk(state, controller, toolCallStart, options, chunk) {
|
|
1385
|
+
if (state.isInsideToolCall) {
|
|
1386
|
+
const trailingBuffer = state.buffer;
|
|
1387
|
+
state.buffer = "";
|
|
1388
|
+
emitIncompleteToolCall(
|
|
1389
|
+
state,
|
|
1390
|
+
controller,
|
|
1391
|
+
toolCallStart,
|
|
1392
|
+
trailingBuffer,
|
|
1393
|
+
options
|
|
1394
|
+
);
|
|
1395
|
+
} else if (state.buffer.length > 0) {
|
|
1020
1396
|
flushBuffer(state, controller, toolCallStart);
|
|
1021
1397
|
}
|
|
1022
1398
|
closeTextBlock(state, controller);
|
|
1023
|
-
emitIncompleteToolCall(state, controller, toolCallStart);
|
|
1024
1399
|
controller.enqueue(chunk);
|
|
1025
1400
|
}
|
|
1026
1401
|
function publishText(text, state, controller) {
|
|
1027
1402
|
if (state.isInsideToolCall) {
|
|
1028
1403
|
closeTextBlock(state, controller);
|
|
1029
1404
|
state.currentToolCallJson += text;
|
|
1405
|
+
emitToolInputProgress(state, controller);
|
|
1030
1406
|
} else if (text.length > 0) {
|
|
1031
1407
|
if (!state.currentTextId) {
|
|
1032
1408
|
state.currentTextId = generateId();
|
|
@@ -1044,42 +1420,40 @@ function publishText(text, state, controller) {
|
|
|
1044
1420
|
}
|
|
1045
1421
|
}
|
|
1046
1422
|
function emitToolCall(context) {
|
|
1047
|
-
var _a
|
|
1423
|
+
var _a;
|
|
1048
1424
|
const { state, controller, toolCallStart, toolCallEnd, options } = context;
|
|
1049
1425
|
try {
|
|
1050
1426
|
const parsedToolCall = parse(state.currentToolCallJson);
|
|
1051
|
-
|
|
1052
|
-
controller.enqueue({
|
|
1053
|
-
type: "tool-call",
|
|
1054
|
-
toolCallId: generateId(),
|
|
1055
|
-
toolName: parsedToolCall.name,
|
|
1056
|
-
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1057
|
-
});
|
|
1427
|
+
emitToolCallFromParsed(state, controller, parsedToolCall);
|
|
1058
1428
|
} catch (error) {
|
|
1429
|
+
const errorContent = `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`;
|
|
1430
|
+
const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
|
|
1059
1431
|
logParseFailure({
|
|
1060
1432
|
phase: "stream",
|
|
1061
1433
|
reason: "Failed to parse streaming tool call JSON segment",
|
|
1062
|
-
snippet:
|
|
1434
|
+
snippet: errorContent,
|
|
1063
1435
|
error
|
|
1064
1436
|
});
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1437
|
+
if (shouldEmitRawFallback) {
|
|
1438
|
+
const errorId = generateId();
|
|
1439
|
+
controller.enqueue({
|
|
1440
|
+
type: "text-start",
|
|
1441
|
+
id: errorId
|
|
1442
|
+
});
|
|
1443
|
+
controller.enqueue({
|
|
1444
|
+
type: "text-delta",
|
|
1445
|
+
id: errorId,
|
|
1446
|
+
delta: errorContent
|
|
1447
|
+
});
|
|
1448
|
+
controller.enqueue({
|
|
1449
|
+
type: "text-end",
|
|
1450
|
+
id: errorId
|
|
1451
|
+
});
|
|
1452
|
+
}
|
|
1453
|
+
closeToolInput(state, controller);
|
|
1454
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1081
1455
|
options,
|
|
1082
|
-
"Could not process streaming JSON tool call; emitting original text.",
|
|
1456
|
+
shouldEmitRawFallback ? "Could not process streaming JSON tool call; emitting original text." : "Could not process streaming JSON tool call.",
|
|
1083
1457
|
{
|
|
1084
1458
|
toolCall: errorContent
|
|
1085
1459
|
}
|
|
@@ -1095,6 +1469,7 @@ function processTagMatch(context) {
|
|
|
1095
1469
|
} else {
|
|
1096
1470
|
state.currentToolCallJson = "";
|
|
1097
1471
|
state.isInsideToolCall = true;
|
|
1472
|
+
state.activeToolInput = null;
|
|
1098
1473
|
}
|
|
1099
1474
|
}
|
|
1100
1475
|
function processBufferTags(context) {
|
|
@@ -1117,8 +1492,16 @@ function processBufferTags(context) {
|
|
|
1117
1492
|
);
|
|
1118
1493
|
}
|
|
1119
1494
|
}
|
|
1120
|
-
function handlePartialTag(state, controller, toolCallStart) {
|
|
1495
|
+
function handlePartialTag(state, controller, toolCallStart, toolCallEnd) {
|
|
1121
1496
|
if (state.isInsideToolCall) {
|
|
1497
|
+
const potentialEndIndex = getPotentialStartIndex(state.buffer, toolCallEnd);
|
|
1498
|
+
if (potentialEndIndex != null && potentialEndIndex + toolCallEnd.length > state.buffer.length) {
|
|
1499
|
+
publishText(state.buffer.slice(0, potentialEndIndex), state, controller);
|
|
1500
|
+
state.buffer = state.buffer.slice(potentialEndIndex);
|
|
1501
|
+
} else {
|
|
1502
|
+
publishText(state.buffer, state, controller);
|
|
1503
|
+
state.buffer = "";
|
|
1504
|
+
}
|
|
1122
1505
|
return;
|
|
1123
1506
|
}
|
|
1124
1507
|
const potentialIndex = getPotentialStartIndex(state.buffer, toolCallStart);
|
|
@@ -1191,13 +1574,14 @@ var jsonProtocol = ({
|
|
|
1191
1574
|
buffer: "",
|
|
1192
1575
|
currentToolCallJson: "",
|
|
1193
1576
|
currentTextId: null,
|
|
1194
|
-
hasEmittedTextStart: false
|
|
1577
|
+
hasEmittedTextStart: false,
|
|
1578
|
+
activeToolInput: null
|
|
1195
1579
|
};
|
|
1196
1580
|
return new TransformStream({
|
|
1197
1581
|
transform(chunk, controller) {
|
|
1198
1582
|
var _a;
|
|
1199
1583
|
if (chunk.type === "finish") {
|
|
1200
|
-
handleFinishChunk(state, controller, toolCallStart, chunk);
|
|
1584
|
+
handleFinishChunk(state, controller, toolCallStart, options, chunk);
|
|
1201
1585
|
return;
|
|
1202
1586
|
}
|
|
1203
1587
|
if (chunk.type !== "text-delta") {
|
|
@@ -1213,7 +1597,7 @@ var jsonProtocol = ({
|
|
|
1213
1597
|
toolCallEnd,
|
|
1214
1598
|
options
|
|
1215
1599
|
});
|
|
1216
|
-
handlePartialTag(state, controller, toolCallStart);
|
|
1600
|
+
handlePartialTag(state, controller, toolCallStart, toolCallEnd);
|
|
1217
1601
|
}
|
|
1218
1602
|
});
|
|
1219
1603
|
},
|
|
@@ -4193,35 +4577,112 @@ function parse3(xml, schema, options = {}) {
|
|
|
4193
4577
|
var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
|
|
4194
4578
|
var WHITESPACE_REGEX5 = /\s/;
|
|
4195
4579
|
|
|
4196
|
-
// src/core/utils/
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4580
|
+
// src/core/utils/streamed-tool-input-delta.ts
|
|
4581
|
+
function emitDelta({
|
|
4582
|
+
controller,
|
|
4583
|
+
id,
|
|
4584
|
+
state,
|
|
4585
|
+
nextInput
|
|
4586
|
+
}) {
|
|
4587
|
+
if (!nextInput.startsWith(state.emittedInput)) {
|
|
4588
|
+
return false;
|
|
4202
4589
|
}
|
|
4203
|
-
const
|
|
4204
|
-
if (
|
|
4205
|
-
return
|
|
4590
|
+
const delta = nextInput.slice(state.emittedInput.length);
|
|
4591
|
+
if (delta.length === 0) {
|
|
4592
|
+
return false;
|
|
4206
4593
|
}
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4594
|
+
controller.enqueue({
|
|
4595
|
+
type: "tool-input-delta",
|
|
4596
|
+
id,
|
|
4597
|
+
delta
|
|
4598
|
+
});
|
|
4599
|
+
state.emittedInput = nextInput;
|
|
4600
|
+
return true;
|
|
4601
|
+
}
|
|
4602
|
+
function toIncompleteJsonPrefix(fullJson) {
|
|
4603
|
+
const trimmed = fullJson.trim();
|
|
4604
|
+
let prefix = trimmed;
|
|
4605
|
+
while (prefix.endsWith("}") || prefix.endsWith("]")) {
|
|
4606
|
+
prefix = prefix.slice(0, -1);
|
|
4210
4607
|
}
|
|
4211
|
-
|
|
4212
|
-
if (
|
|
4213
|
-
|
|
4608
|
+
prefix = prefix.trimEnd();
|
|
4609
|
+
if (prefix.endsWith('"')) {
|
|
4610
|
+
prefix = prefix.slice(0, -1);
|
|
4214
4611
|
}
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
}
|
|
4219
|
-
|
|
4612
|
+
if (prefix.length === 0) {
|
|
4613
|
+
if (trimmed.startsWith("[") || trimmed.startsWith("{")) {
|
|
4614
|
+
return trimmed.startsWith("{") ? "{" : "[";
|
|
4615
|
+
}
|
|
4616
|
+
if (trimmed.startsWith("]")) {
|
|
4617
|
+
return "[";
|
|
4618
|
+
}
|
|
4619
|
+
if (trimmed.startsWith("}")) {
|
|
4620
|
+
return "{";
|
|
4621
|
+
}
|
|
4622
|
+
if (trimmed.startsWith('"')) {
|
|
4623
|
+
return '"';
|
|
4624
|
+
}
|
|
4625
|
+
return "{";
|
|
4626
|
+
}
|
|
4627
|
+
return prefix;
|
|
4628
|
+
}
|
|
4629
|
+
function emitPrefixDelta(params) {
|
|
4630
|
+
return emitDelta({
|
|
4631
|
+
...params,
|
|
4632
|
+
nextInput: params.candidate
|
|
4633
|
+
});
|
|
4634
|
+
}
|
|
4635
|
+
function emitFinalRemainder(params) {
|
|
4636
|
+
var _a;
|
|
4637
|
+
const result = emitDelta({
|
|
4638
|
+
...params,
|
|
4639
|
+
nextInput: params.finalFullJson
|
|
4640
|
+
});
|
|
4641
|
+
if (!result && params.state.emittedInput.length > 0) {
|
|
4642
|
+
(_a = params.onMismatch) == null ? void 0 : _a.call(
|
|
4643
|
+
params,
|
|
4644
|
+
"Final JSON does not extend emitted tool-input prefix",
|
|
4645
|
+
{
|
|
4646
|
+
emittedLength: params.state.emittedInput.length,
|
|
4647
|
+
finalLength: params.finalFullJson.length
|
|
4648
|
+
}
|
|
4649
|
+
);
|
|
4650
|
+
}
|
|
4651
|
+
return result;
|
|
4652
|
+
}
|
|
4653
|
+
|
|
4654
|
+
// src/core/utils/xml-root-repair.ts
|
|
4655
|
+
var XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX = /^<([A-Za-z_][A-Za-z0-9_-]*)\s*\r?\n([\s\S]+?)\r?\n\s*\/>\s*$/;
|
|
4656
|
+
function tryRepairXmlSelfClosingRootWithBody(rawText, toolNames) {
|
|
4657
|
+
const trimmed = rawText.trim();
|
|
4658
|
+
if (trimmed.length === 0) {
|
|
4659
|
+
return null;
|
|
4660
|
+
}
|
|
4661
|
+
const match = trimmed.match(XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX);
|
|
4662
|
+
if (!match) {
|
|
4663
|
+
return null;
|
|
4664
|
+
}
|
|
4665
|
+
const rootTag = match[1];
|
|
4666
|
+
if (!toolNames.includes(rootTag)) {
|
|
4667
|
+
return null;
|
|
4668
|
+
}
|
|
4669
|
+
const body = match[2].trimEnd();
|
|
4670
|
+
if (body.trim().length === 0 || body.includes(`</${rootTag}>`)) {
|
|
4671
|
+
return null;
|
|
4672
|
+
}
|
|
4673
|
+
return `<${rootTag}>
|
|
4674
|
+
${body}
|
|
4675
|
+
</${rootTag}>`;
|
|
4676
|
+
}
|
|
4677
|
+
|
|
4220
4678
|
// src/core/protocols/xml-protocol.ts
|
|
4221
4679
|
function getToolSchema(tools, toolName) {
|
|
4222
4680
|
var _a;
|
|
4223
4681
|
return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
4224
4682
|
}
|
|
4683
|
+
function shouldEmitRawToolCallTextOnError2(options) {
|
|
4684
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
4685
|
+
}
|
|
4225
4686
|
function processToolCall(params) {
|
|
4226
4687
|
var _a, _b;
|
|
4227
4688
|
const { toolCall, tools, options, text, processedElements, parseOptions } = params;
|
|
@@ -4234,7 +4695,7 @@ function processToolCall(params) {
|
|
|
4234
4695
|
const parsed = parse3(toolCall.content, toolSchema, parseConfig);
|
|
4235
4696
|
processedElements.push({
|
|
4236
4697
|
type: "tool-call",
|
|
4237
|
-
toolCallId:
|
|
4698
|
+
toolCallId: generateToolCallId(),
|
|
4238
4699
|
toolName: toolCall.toolName,
|
|
4239
4700
|
input: JSON.stringify(parsed)
|
|
4240
4701
|
});
|
|
@@ -4251,6 +4712,299 @@ function processToolCall(params) {
|
|
|
4251
4712
|
processedElements.push({ type: "text", text: originalCallText });
|
|
4252
4713
|
}
|
|
4253
4714
|
}
|
|
4715
|
+
function parseXmlTagName(rawTagBody) {
|
|
4716
|
+
let index = 0;
|
|
4717
|
+
while (index < rawTagBody.length && WHITESPACE_REGEX5.test(rawTagBody[index])) {
|
|
4718
|
+
index += 1;
|
|
4719
|
+
}
|
|
4720
|
+
const nameStart = index;
|
|
4721
|
+
while (index < rawTagBody.length && NAME_CHAR_RE2.test(rawTagBody.charAt(index))) {
|
|
4722
|
+
index += 1;
|
|
4723
|
+
}
|
|
4724
|
+
return rawTagBody.slice(nameStart, index);
|
|
4725
|
+
}
|
|
4726
|
+
function consumeXmlSpecialSection(fragment, ltIndex) {
|
|
4727
|
+
if (fragment.startsWith("<!--", ltIndex)) {
|
|
4728
|
+
const commentEnd = fragment.indexOf("-->", ltIndex + 4);
|
|
4729
|
+
return commentEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: commentEnd + 3 };
|
|
4730
|
+
}
|
|
4731
|
+
if (fragment.startsWith("<![CDATA[", ltIndex)) {
|
|
4732
|
+
const cdataEnd = fragment.indexOf("]]>", ltIndex + 9);
|
|
4733
|
+
return cdataEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: cdataEnd + 3 };
|
|
4734
|
+
}
|
|
4735
|
+
if (fragment.startsWith("<?", ltIndex)) {
|
|
4736
|
+
const processingEnd = fragment.indexOf("?>", ltIndex + 2);
|
|
4737
|
+
return processingEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: processingEnd + 2 };
|
|
4738
|
+
}
|
|
4739
|
+
if (fragment.startsWith("<!", ltIndex)) {
|
|
4740
|
+
const declarationEnd = fragment.indexOf(">", ltIndex + 2);
|
|
4741
|
+
return declarationEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: declarationEnd + 1 };
|
|
4742
|
+
}
|
|
4743
|
+
return { kind: "none" };
|
|
4744
|
+
}
|
|
4745
|
+
function parseXmlTagToken(fragment, ltIndex) {
|
|
4746
|
+
const gtIndex = fragment.indexOf(">", ltIndex + 1);
|
|
4747
|
+
if (gtIndex === -1) {
|
|
4748
|
+
return null;
|
|
4749
|
+
}
|
|
4750
|
+
const tagBody = fragment.slice(ltIndex + 1, gtIndex).trim();
|
|
4751
|
+
if (tagBody.length === 0) {
|
|
4752
|
+
return null;
|
|
4753
|
+
}
|
|
4754
|
+
if (tagBody.startsWith("/")) {
|
|
4755
|
+
const closeName = parseXmlTagName(tagBody.slice(1));
|
|
4756
|
+
if (closeName.length === 0) {
|
|
4757
|
+
return null;
|
|
4758
|
+
}
|
|
4759
|
+
return { kind: "close", name: closeName, nextPos: gtIndex + 1 };
|
|
4760
|
+
}
|
|
4761
|
+
const selfClosing = tagBody.endsWith("/");
|
|
4762
|
+
const openBody = selfClosing ? tagBody.slice(0, -1).trimEnd() : tagBody;
|
|
4763
|
+
const openName = parseXmlTagName(openBody);
|
|
4764
|
+
if (openName.length === 0) {
|
|
4765
|
+
return null;
|
|
4766
|
+
}
|
|
4767
|
+
return {
|
|
4768
|
+
kind: "open",
|
|
4769
|
+
name: openName,
|
|
4770
|
+
selfClosing,
|
|
4771
|
+
nextPos: gtIndex + 1
|
|
4772
|
+
};
|
|
4773
|
+
}
|
|
4774
|
+
function analyzeXmlFragmentForProgress(fragment) {
|
|
4775
|
+
const stack = [];
|
|
4776
|
+
const topLevelTagNames = [];
|
|
4777
|
+
let position = 0;
|
|
4778
|
+
while (position < fragment.length) {
|
|
4779
|
+
const ltIndex = fragment.indexOf("<", position);
|
|
4780
|
+
if (ltIndex === -1) {
|
|
4781
|
+
break;
|
|
4782
|
+
}
|
|
4783
|
+
const special = consumeXmlSpecialSection(fragment, ltIndex);
|
|
4784
|
+
if (special.kind === "incomplete") {
|
|
4785
|
+
return null;
|
|
4786
|
+
}
|
|
4787
|
+
if (special.kind === "consumed") {
|
|
4788
|
+
position = special.nextPos;
|
|
4789
|
+
continue;
|
|
4790
|
+
}
|
|
4791
|
+
const token = parseXmlTagToken(fragment, ltIndex);
|
|
4792
|
+
if (token === null) {
|
|
4793
|
+
return null;
|
|
4794
|
+
}
|
|
4795
|
+
if (token.kind === "close") {
|
|
4796
|
+
const openName = stack.pop();
|
|
4797
|
+
if (!openName || openName !== token.name) {
|
|
4798
|
+
return null;
|
|
4799
|
+
}
|
|
4800
|
+
position = token.nextPos;
|
|
4801
|
+
continue;
|
|
4802
|
+
}
|
|
4803
|
+
if (stack.length === 0) {
|
|
4804
|
+
topLevelTagNames.push(token.name);
|
|
4805
|
+
}
|
|
4806
|
+
if (!token.selfClosing) {
|
|
4807
|
+
stack.push(token.name);
|
|
4808
|
+
}
|
|
4809
|
+
position = token.nextPos;
|
|
4810
|
+
}
|
|
4811
|
+
if (stack.length > 0) {
|
|
4812
|
+
return null;
|
|
4813
|
+
}
|
|
4814
|
+
return { topLevelTagNames };
|
|
4815
|
+
}
|
|
4816
|
+
function scanXmlFragmentTopLevelTextStep(options) {
|
|
4817
|
+
const { fragment, position, stack } = options;
|
|
4818
|
+
const ltIndex = fragment.indexOf("<", position);
|
|
4819
|
+
if (ltIndex === -1) {
|
|
4820
|
+
const trailingText = fragment.slice(position);
|
|
4821
|
+
return {
|
|
4822
|
+
kind: "done",
|
|
4823
|
+
value: stack.length === 0 && trailingText.trim().length > 0
|
|
4824
|
+
};
|
|
4825
|
+
}
|
|
4826
|
+
const textBetweenTags = fragment.slice(position, ltIndex);
|
|
4827
|
+
if (stack.length === 0 && textBetweenTags.trim().length > 0) {
|
|
4828
|
+
return { kind: "found" };
|
|
4829
|
+
}
|
|
4830
|
+
const special = consumeXmlSpecialSection(fragment, ltIndex);
|
|
4831
|
+
if (special.kind === "incomplete") {
|
|
4832
|
+
return { kind: "invalid" };
|
|
4833
|
+
}
|
|
4834
|
+
if (special.kind === "consumed") {
|
|
4835
|
+
return { kind: "next", nextPos: special.nextPos };
|
|
4836
|
+
}
|
|
4837
|
+
const token = parseXmlTagToken(fragment, ltIndex);
|
|
4838
|
+
if (token === null) {
|
|
4839
|
+
return { kind: "invalid" };
|
|
4840
|
+
}
|
|
4841
|
+
if (token.kind === "close") {
|
|
4842
|
+
const openName = stack.pop();
|
|
4843
|
+
if (!openName || openName !== token.name) {
|
|
4844
|
+
return { kind: "invalid" };
|
|
4845
|
+
}
|
|
4846
|
+
} else if (!token.selfClosing) {
|
|
4847
|
+
stack.push(token.name);
|
|
4848
|
+
}
|
|
4849
|
+
return { kind: "next", nextPos: token.nextPos };
|
|
4850
|
+
}
|
|
4851
|
+
function hasNonWhitespaceTopLevelText(fragment) {
|
|
4852
|
+
if (!fragment.includes("<")) {
|
|
4853
|
+
return fragment.trim().length > 0;
|
|
4854
|
+
}
|
|
4855
|
+
const stack = [];
|
|
4856
|
+
let position = 0;
|
|
4857
|
+
while (position < fragment.length) {
|
|
4858
|
+
const step = scanXmlFragmentTopLevelTextStep({ fragment, position, stack });
|
|
4859
|
+
if (step.kind === "found") {
|
|
4860
|
+
return true;
|
|
4861
|
+
}
|
|
4862
|
+
if (step.kind === "invalid") {
|
|
4863
|
+
return false;
|
|
4864
|
+
}
|
|
4865
|
+
if (step.kind === "done") {
|
|
4866
|
+
return step.value;
|
|
4867
|
+
}
|
|
4868
|
+
position = step.nextPos;
|
|
4869
|
+
}
|
|
4870
|
+
return false;
|
|
4871
|
+
}
|
|
4872
|
+
function getObjectSchemaPropertyNames(schema) {
|
|
4873
|
+
if (!schema || typeof schema !== "object") {
|
|
4874
|
+
return null;
|
|
4875
|
+
}
|
|
4876
|
+
const schemaObject = schema;
|
|
4877
|
+
const typeValue = schemaObject.type;
|
|
4878
|
+
if (typeValue != null) {
|
|
4879
|
+
const isObjectType = typeValue === "object" || Array.isArray(typeValue) && typeValue.includes("object");
|
|
4880
|
+
if (!isObjectType) {
|
|
4881
|
+
return null;
|
|
4882
|
+
}
|
|
4883
|
+
}
|
|
4884
|
+
if (!schemaObject.properties || typeof schemaObject.properties !== "object") {
|
|
4885
|
+
return /* @__PURE__ */ new Set();
|
|
4886
|
+
}
|
|
4887
|
+
return new Set(
|
|
4888
|
+
Object.keys(schemaObject.properties)
|
|
4889
|
+
);
|
|
4890
|
+
}
|
|
4891
|
+
function schemaAllowsArrayType(schema) {
|
|
4892
|
+
if (!schema || typeof schema !== "object") {
|
|
4893
|
+
return false;
|
|
4894
|
+
}
|
|
4895
|
+
const schemaRecord = schema;
|
|
4896
|
+
const typeValue = schemaRecord.type;
|
|
4897
|
+
if (typeValue === "array") {
|
|
4898
|
+
return true;
|
|
4899
|
+
}
|
|
4900
|
+
if (Array.isArray(typeValue) && typeValue.includes("array")) {
|
|
4901
|
+
return true;
|
|
4902
|
+
}
|
|
4903
|
+
const unions = [schemaRecord.anyOf, schemaRecord.oneOf, schemaRecord.allOf];
|
|
4904
|
+
for (const union of unions) {
|
|
4905
|
+
if (!Array.isArray(union)) {
|
|
4906
|
+
continue;
|
|
4907
|
+
}
|
|
4908
|
+
if (union.some((entry) => schemaAllowsArrayType(entry))) {
|
|
4909
|
+
return true;
|
|
4910
|
+
}
|
|
4911
|
+
}
|
|
4912
|
+
return false;
|
|
4913
|
+
}
|
|
4914
|
+
function getSchemaObjectProperty(schema, propertyName) {
|
|
4915
|
+
if (!schema || typeof schema !== "object") {
|
|
4916
|
+
return null;
|
|
4917
|
+
}
|
|
4918
|
+
const schemaObject = schema;
|
|
4919
|
+
const properties = schemaObject.properties;
|
|
4920
|
+
if (!properties || typeof properties !== "object") {
|
|
4921
|
+
return null;
|
|
4922
|
+
}
|
|
4923
|
+
const property = properties[propertyName];
|
|
4924
|
+
if (!property) {
|
|
4925
|
+
return null;
|
|
4926
|
+
}
|
|
4927
|
+
return property;
|
|
4928
|
+
}
|
|
4929
|
+
function isStableXmlProgressCandidate(options) {
|
|
4930
|
+
const { candidate, parsed, toolSchema } = options;
|
|
4931
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4932
|
+
return false;
|
|
4933
|
+
}
|
|
4934
|
+
const structure = analyzeXmlFragmentForProgress(candidate);
|
|
4935
|
+
if (!structure) {
|
|
4936
|
+
return false;
|
|
4937
|
+
}
|
|
4938
|
+
const schemaProperties = getObjectSchemaPropertyNames(toolSchema);
|
|
4939
|
+
if (!schemaProperties || schemaProperties.size === 0) {
|
|
4940
|
+
return false;
|
|
4941
|
+
}
|
|
4942
|
+
const parsedObject = parsed;
|
|
4943
|
+
const uniqueTopLevelTags = new Set(structure.topLevelTagNames);
|
|
4944
|
+
for (const tagName of uniqueTopLevelTags) {
|
|
4945
|
+
if (!schemaProperties.has(tagName)) {
|
|
4946
|
+
continue;
|
|
4947
|
+
}
|
|
4948
|
+
const schemaProperty = getSchemaObjectProperty(toolSchema, tagName);
|
|
4949
|
+
if (schemaProperty && schemaAllowsArrayType(schemaProperty) && !Array.isArray(parsedObject[tagName])) {
|
|
4950
|
+
return false;
|
|
4951
|
+
}
|
|
4952
|
+
}
|
|
4953
|
+
if (structure.topLevelTagNames.length === 1) {
|
|
4954
|
+
const onlyTopLevelTag = structure.topLevelTagNames[0];
|
|
4955
|
+
if (!schemaProperties || schemaProperties.size === 0 || !schemaProperties.has(onlyTopLevelTag)) {
|
|
4956
|
+
return false;
|
|
4957
|
+
}
|
|
4958
|
+
}
|
|
4959
|
+
return true;
|
|
4960
|
+
}
|
|
4961
|
+
function parseXmlContentForStreamProgress({
|
|
4962
|
+
toolContent,
|
|
4963
|
+
toolSchema,
|
|
4964
|
+
parseOptions
|
|
4965
|
+
}) {
|
|
4966
|
+
const tryParse = (content) => {
|
|
4967
|
+
try {
|
|
4968
|
+
return parse3(content, toolSchema, {
|
|
4969
|
+
...parseOptions != null ? parseOptions : {},
|
|
4970
|
+
repair: false,
|
|
4971
|
+
onError: void 0
|
|
4972
|
+
});
|
|
4973
|
+
} catch (e) {
|
|
4974
|
+
return null;
|
|
4975
|
+
}
|
|
4976
|
+
};
|
|
4977
|
+
const strictFull = tryParse(toolContent);
|
|
4978
|
+
if (strictFull !== null && isStableXmlProgressCandidate({
|
|
4979
|
+
candidate: toolContent,
|
|
4980
|
+
parsed: strictFull,
|
|
4981
|
+
toolSchema
|
|
4982
|
+
})) {
|
|
4983
|
+
return JSON.stringify(strictFull);
|
|
4984
|
+
}
|
|
4985
|
+
let searchEnd = toolContent.length;
|
|
4986
|
+
while (searchEnd > 0) {
|
|
4987
|
+
const gtIndex = toolContent.lastIndexOf(">", searchEnd - 1);
|
|
4988
|
+
if (gtIndex === -1) {
|
|
4989
|
+
break;
|
|
4990
|
+
}
|
|
4991
|
+
const candidate = toolContent.slice(0, gtIndex + 1);
|
|
4992
|
+
if (!analyzeXmlFragmentForProgress(candidate)) {
|
|
4993
|
+
searchEnd = gtIndex;
|
|
4994
|
+
continue;
|
|
4995
|
+
}
|
|
4996
|
+
const parsedCandidate = tryParse(candidate);
|
|
4997
|
+
if (parsedCandidate !== null && isStableXmlProgressCandidate({
|
|
4998
|
+
candidate,
|
|
4999
|
+
parsed: parsedCandidate,
|
|
5000
|
+
toolSchema
|
|
5001
|
+
})) {
|
|
5002
|
+
return JSON.stringify(parsedCandidate);
|
|
5003
|
+
}
|
|
5004
|
+
searchEnd = gtIndex;
|
|
5005
|
+
}
|
|
5006
|
+
return null;
|
|
5007
|
+
}
|
|
4254
5008
|
function handleStreamingToolCallEnd(params) {
|
|
4255
5009
|
var _a, _b;
|
|
4256
5010
|
const {
|
|
@@ -4270,19 +5024,37 @@ function handleStreamingToolCallEnd(params) {
|
|
|
4270
5024
|
flushText(ctrl);
|
|
4271
5025
|
try {
|
|
4272
5026
|
const parsedResult = parse3(toolContent, toolSchema, parseConfig);
|
|
5027
|
+
const finalInput = JSON.stringify(parsedResult);
|
|
5028
|
+
emitFinalRemainder({
|
|
5029
|
+
controller: ctrl,
|
|
5030
|
+
id: currentToolCall.toolCallId,
|
|
5031
|
+
state: currentToolCall,
|
|
5032
|
+
finalFullJson: finalInput,
|
|
5033
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
5034
|
+
});
|
|
5035
|
+
ctrl.enqueue({
|
|
5036
|
+
type: "tool-input-end",
|
|
5037
|
+
id: currentToolCall.toolCallId
|
|
5038
|
+
});
|
|
4273
5039
|
ctrl.enqueue({
|
|
4274
5040
|
type: "tool-call",
|
|
4275
|
-
toolCallId:
|
|
5041
|
+
toolCallId: currentToolCall.toolCallId,
|
|
4276
5042
|
toolName: currentToolCall.name,
|
|
4277
|
-
input:
|
|
5043
|
+
input: finalInput
|
|
4278
5044
|
});
|
|
4279
5045
|
} catch (error) {
|
|
5046
|
+
ctrl.enqueue({
|
|
5047
|
+
type: "tool-input-end",
|
|
5048
|
+
id: currentToolCall.toolCallId
|
|
5049
|
+
});
|
|
4280
5050
|
const original = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
|
|
4281
5051
|
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
|
|
4282
5052
|
toolCall: original,
|
|
4283
5053
|
error
|
|
4284
5054
|
});
|
|
4285
|
-
|
|
5055
|
+
if (shouldEmitRawToolCallTextOnError2(options)) {
|
|
5056
|
+
flushText(ctrl, original);
|
|
5057
|
+
}
|
|
4286
5058
|
}
|
|
4287
5059
|
}
|
|
4288
5060
|
function findClosingTagEndFlexible(text, contentStart, toolName) {
|
|
@@ -4704,38 +5476,6 @@ function findPotentialToolTagStart(buffer, toolNames) {
|
|
|
4704
5476
|
}
|
|
4705
5477
|
return -1;
|
|
4706
5478
|
}
|
|
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
5479
|
function processToolCallInBuffer(params) {
|
|
4740
5480
|
const {
|
|
4741
5481
|
buffer,
|
|
@@ -4745,18 +5485,21 @@ function processToolCallInBuffer(params) {
|
|
|
4745
5485
|
controller,
|
|
4746
5486
|
flushText,
|
|
4747
5487
|
setBuffer,
|
|
4748
|
-
parseOptions
|
|
5488
|
+
parseOptions,
|
|
5489
|
+
emitToolInputProgress: emitToolInputProgress2
|
|
4749
5490
|
} = params;
|
|
4750
5491
|
const endTagPattern = new RegExp(
|
|
4751
5492
|
`</\\s*${escapeRegExp(currentToolCall.name)}\\s*>`
|
|
4752
5493
|
);
|
|
4753
5494
|
const endMatch = endTagPattern.exec(buffer);
|
|
4754
5495
|
if (!endMatch || endMatch.index === void 0) {
|
|
5496
|
+
emitToolInputProgress2(controller, currentToolCall, buffer);
|
|
4755
5497
|
return { buffer, currentToolCall, shouldBreak: true };
|
|
4756
5498
|
}
|
|
4757
5499
|
const endIdx = endMatch.index;
|
|
4758
5500
|
const endPos = endIdx + endMatch[0].length;
|
|
4759
5501
|
const content = buffer.substring(0, endIdx);
|
|
5502
|
+
emitToolInputProgress2(controller, currentToolCall, content);
|
|
4760
5503
|
const remainder = buffer.substring(endPos);
|
|
4761
5504
|
setBuffer(remainder);
|
|
4762
5505
|
handleStreamingToolCallEnd({
|
|
@@ -4783,7 +5526,8 @@ function processNoToolCallInBuffer(params) {
|
|
|
4783
5526
|
tools,
|
|
4784
5527
|
options,
|
|
4785
5528
|
parseOptions,
|
|
4786
|
-
setBuffer
|
|
5529
|
+
setBuffer,
|
|
5530
|
+
emitToolInputStart
|
|
4787
5531
|
} = params;
|
|
4788
5532
|
const {
|
|
4789
5533
|
index: earliestStartTagIndex,
|
|
@@ -4813,9 +5557,10 @@ function processNoToolCallInBuffer(params) {
|
|
|
4813
5557
|
if (selfClosing) {
|
|
4814
5558
|
const newBuffer2 = buffer.substring(earliestStartTagIndex + tagLength);
|
|
4815
5559
|
setBuffer(newBuffer2);
|
|
5560
|
+
const currentToolCall = emitToolInputStart(controller, earliestToolName);
|
|
4816
5561
|
handleStreamingToolCallEnd({
|
|
4817
5562
|
toolContent: "",
|
|
4818
|
-
currentToolCall
|
|
5563
|
+
currentToolCall,
|
|
4819
5564
|
tools,
|
|
4820
5565
|
options,
|
|
4821
5566
|
ctrl: controller,
|
|
@@ -4834,12 +5579,12 @@ function processNoToolCallInBuffer(params) {
|
|
|
4834
5579
|
setBuffer(newBuffer);
|
|
4835
5580
|
return {
|
|
4836
5581
|
buffer: newBuffer,
|
|
4837
|
-
currentToolCall:
|
|
5582
|
+
currentToolCall: emitToolInputStart(controller, earliestToolName),
|
|
4838
5583
|
shouldBreak: false,
|
|
4839
5584
|
shouldContinue: true
|
|
4840
5585
|
};
|
|
4841
5586
|
}
|
|
4842
|
-
function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions) {
|
|
5587
|
+
function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions, emitToolInputProgress2, emitToolInputStart) {
|
|
4843
5588
|
return (controller) => {
|
|
4844
5589
|
while (true) {
|
|
4845
5590
|
const currentToolCall = getCurrentToolCall();
|
|
@@ -4852,7 +5597,8 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
4852
5597
|
controller,
|
|
4853
5598
|
flushText,
|
|
4854
5599
|
setBuffer,
|
|
4855
|
-
parseOptions
|
|
5600
|
+
parseOptions,
|
|
5601
|
+
emitToolInputProgress: emitToolInputProgress2
|
|
4856
5602
|
});
|
|
4857
5603
|
setBuffer(result.buffer);
|
|
4858
5604
|
setCurrentToolCall(result.currentToolCall);
|
|
@@ -4868,7 +5614,8 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
4868
5614
|
tools,
|
|
4869
5615
|
options,
|
|
4870
5616
|
parseOptions,
|
|
4871
|
-
setBuffer
|
|
5617
|
+
setBuffer,
|
|
5618
|
+
emitToolInputStart
|
|
4872
5619
|
});
|
|
4873
5620
|
setBuffer(result.buffer);
|
|
4874
5621
|
setCurrentToolCall(result.currentToolCall);
|
|
@@ -4982,6 +5729,118 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4982
5729
|
hasEmittedTextStart = value;
|
|
4983
5730
|
}
|
|
4984
5731
|
);
|
|
5732
|
+
const emitToolInputStart = (controller, toolName) => {
|
|
5733
|
+
flushText(controller);
|
|
5734
|
+
const next = {
|
|
5735
|
+
name: toolName,
|
|
5736
|
+
toolCallId: generateToolCallId(),
|
|
5737
|
+
emittedInput: "",
|
|
5738
|
+
lastProgressGtIndex: null,
|
|
5739
|
+
lastProgressFullInput: null
|
|
5740
|
+
};
|
|
5741
|
+
controller.enqueue({
|
|
5742
|
+
type: "tool-input-start",
|
|
5743
|
+
id: next.toolCallId,
|
|
5744
|
+
toolName
|
|
5745
|
+
});
|
|
5746
|
+
return next;
|
|
5747
|
+
};
|
|
5748
|
+
const emitToolInputProgress2 = (controller, toolCall, toolContent) => {
|
|
5749
|
+
const progressGtIndex = toolContent.lastIndexOf(">");
|
|
5750
|
+
if (toolCall.lastProgressGtIndex === progressGtIndex) {
|
|
5751
|
+
const cached = toolCall.lastProgressFullInput;
|
|
5752
|
+
if (cached == null) {
|
|
5753
|
+
return;
|
|
5754
|
+
}
|
|
5755
|
+
if (cached === "{}" && toolContent.trim().length === 0) {
|
|
5756
|
+
return;
|
|
5757
|
+
}
|
|
5758
|
+
const prefixCandidate2 = toIncompleteJsonPrefix(cached);
|
|
5759
|
+
emitPrefixDelta({
|
|
5760
|
+
controller,
|
|
5761
|
+
id: toolCall.toolCallId,
|
|
5762
|
+
state: toolCall,
|
|
5763
|
+
candidate: prefixCandidate2
|
|
5764
|
+
});
|
|
5765
|
+
return;
|
|
5766
|
+
}
|
|
5767
|
+
const toolSchema = getToolSchema(tools, toolCall.name);
|
|
5768
|
+
const fullInput = parseXmlContentForStreamProgress({
|
|
5769
|
+
toolContent,
|
|
5770
|
+
toolSchema,
|
|
5771
|
+
parseOptions
|
|
5772
|
+
});
|
|
5773
|
+
toolCall.lastProgressGtIndex = progressGtIndex;
|
|
5774
|
+
toolCall.lastProgressFullInput = fullInput;
|
|
5775
|
+
if (fullInput == null) {
|
|
5776
|
+
return;
|
|
5777
|
+
}
|
|
5778
|
+
if (fullInput === "{}" && toolContent.trim().length === 0) {
|
|
5779
|
+
return;
|
|
5780
|
+
}
|
|
5781
|
+
const prefixCandidate = toIncompleteJsonPrefix(fullInput);
|
|
5782
|
+
emitPrefixDelta({
|
|
5783
|
+
controller,
|
|
5784
|
+
id: toolCall.toolCallId,
|
|
5785
|
+
state: toolCall,
|
|
5786
|
+
candidate: prefixCandidate
|
|
5787
|
+
});
|
|
5788
|
+
};
|
|
5789
|
+
const finalizeUnclosedToolCall = (controller) => {
|
|
5790
|
+
var _a2, _b;
|
|
5791
|
+
if (!currentToolCall) {
|
|
5792
|
+
return;
|
|
5793
|
+
}
|
|
5794
|
+
emitToolInputProgress2(controller, currentToolCall, buffer);
|
|
5795
|
+
const parseConfig = {
|
|
5796
|
+
...parseOptions,
|
|
5797
|
+
onError: (_a2 = options == null ? void 0 : options.onError) != null ? _a2 : parseOptions == null ? void 0 : parseOptions.onError
|
|
5798
|
+
};
|
|
5799
|
+
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
5800
|
+
flushText(controller);
|
|
5801
|
+
try {
|
|
5802
|
+
if (hasNonWhitespaceTopLevelText(buffer)) {
|
|
5803
|
+
throw new Error(
|
|
5804
|
+
"Cannot reconcile unclosed XML tool call with top-level plain text."
|
|
5805
|
+
);
|
|
5806
|
+
}
|
|
5807
|
+
const parsedResult = parse3(buffer, toolSchema, parseConfig);
|
|
5808
|
+
const finalInput = JSON.stringify(parsedResult);
|
|
5809
|
+
emitFinalRemainder({
|
|
5810
|
+
controller,
|
|
5811
|
+
id: currentToolCall.toolCallId,
|
|
5812
|
+
state: currentToolCall,
|
|
5813
|
+
finalFullJson: finalInput,
|
|
5814
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
5815
|
+
});
|
|
5816
|
+
controller.enqueue({
|
|
5817
|
+
type: "tool-input-end",
|
|
5818
|
+
id: currentToolCall.toolCallId
|
|
5819
|
+
});
|
|
5820
|
+
controller.enqueue({
|
|
5821
|
+
type: "tool-call",
|
|
5822
|
+
toolCallId: currentToolCall.toolCallId,
|
|
5823
|
+
toolName: currentToolCall.name,
|
|
5824
|
+
input: finalInput
|
|
5825
|
+
});
|
|
5826
|
+
} catch (error) {
|
|
5827
|
+
controller.enqueue({
|
|
5828
|
+
type: "tool-input-end",
|
|
5829
|
+
id: currentToolCall.toolCallId
|
|
5830
|
+
});
|
|
5831
|
+
const unfinishedContent = `<${currentToolCall.name}>${buffer}`;
|
|
5832
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
5833
|
+
options,
|
|
5834
|
+
"Could not complete streaming XML tool call at finish.",
|
|
5835
|
+
{ toolCall: unfinishedContent, error }
|
|
5836
|
+
);
|
|
5837
|
+
if (shouldEmitRawToolCallTextOnError2(options)) {
|
|
5838
|
+
flushText(controller, unfinishedContent);
|
|
5839
|
+
}
|
|
5840
|
+
}
|
|
5841
|
+
buffer = "";
|
|
5842
|
+
currentToolCall = null;
|
|
5843
|
+
};
|
|
4985
5844
|
const processBuffer = createProcessBufferHandler(
|
|
4986
5845
|
() => buffer,
|
|
4987
5846
|
(newBuffer) => {
|
|
@@ -4995,17 +5854,17 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4995
5854
|
options,
|
|
4996
5855
|
toolNames,
|
|
4997
5856
|
flushText,
|
|
4998
|
-
parseOptions
|
|
5857
|
+
parseOptions,
|
|
5858
|
+
emitToolInputProgress2,
|
|
5859
|
+
emitToolInputStart
|
|
4999
5860
|
);
|
|
5000
5861
|
return new TransformStream({
|
|
5862
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Stateful stream parsing requires branching over chunk lifecycle and parser states.
|
|
5001
5863
|
transform(chunk, controller) {
|
|
5002
5864
|
var _a2;
|
|
5003
5865
|
if (chunk.type === "finish") {
|
|
5004
5866
|
if (currentToolCall) {
|
|
5005
|
-
|
|
5006
|
-
flushText(controller, unfinishedContent);
|
|
5007
|
-
buffer = "";
|
|
5008
|
-
currentToolCall = null;
|
|
5867
|
+
finalizeUnclosedToolCall(controller);
|
|
5009
5868
|
} else if (buffer) {
|
|
5010
5869
|
flushText(controller, buffer);
|
|
5011
5870
|
buffer = "";
|
|
@@ -5015,7 +5874,8 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
5015
5874
|
return;
|
|
5016
5875
|
}
|
|
5017
5876
|
if (chunk.type !== "text-delta") {
|
|
5018
|
-
if (
|
|
5877
|
+
if (currentToolCall) {
|
|
5878
|
+
} else if (buffer) {
|
|
5019
5879
|
flushText(controller, buffer);
|
|
5020
5880
|
buffer = "";
|
|
5021
5881
|
}
|
|
@@ -5028,10 +5888,7 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
5028
5888
|
},
|
|
5029
5889
|
flush(controller) {
|
|
5030
5890
|
if (currentToolCall) {
|
|
5031
|
-
|
|
5032
|
-
flushText(controller, unfinishedContent);
|
|
5033
|
-
buffer = "";
|
|
5034
|
-
currentToolCall = null;
|
|
5891
|
+
finalizeUnclosedToolCall(controller);
|
|
5035
5892
|
} else if (buffer) {
|
|
5036
5893
|
flushText(controller, buffer);
|
|
5037
5894
|
buffer = "";
|
|
@@ -5059,7 +5916,205 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
5059
5916
|
|
|
5060
5917
|
// src/core/protocols/yaml-protocol.ts
|
|
5061
5918
|
var import_yaml = __toESM(require("yaml"), 1);
|
|
5919
|
+
function shouldEmitRawToolCallTextOnError3(options) {
|
|
5920
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
5921
|
+
}
|
|
5922
|
+
var selfClosingTagCache2 = /* @__PURE__ */ new Map();
|
|
5923
|
+
function getSelfClosingTagPattern2(toolName) {
|
|
5924
|
+
let pattern = selfClosingTagCache2.get(toolName);
|
|
5925
|
+
if (!pattern) {
|
|
5926
|
+
pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
|
|
5927
|
+
selfClosingTagCache2.set(toolName, pattern);
|
|
5928
|
+
}
|
|
5929
|
+
return pattern;
|
|
5930
|
+
}
|
|
5062
5931
|
var LEADING_WHITESPACE_RE = /^(\s*)/;
|
|
5932
|
+
var INCOMPLETE_MAPPING_TAIL_RE = /^[^:[\]{}-][^:]*:\s*$/;
|
|
5933
|
+
var INCOMPLETE_SEQUENCE_TAIL_RE = /^-\s*$/;
|
|
5934
|
+
var BLOCK_SCALAR_KEY_RE = /:\s*[|>][-+0-9]*\s*$/;
|
|
5935
|
+
var PLAIN_MAPPING_VALUE_RE = /^[^:[\]{}-][^:]*:\s*(.+)$/;
|
|
5936
|
+
var PLAIN_SEQUENCE_VALUE_RE = /^-\s+(.+)$/;
|
|
5937
|
+
function normalizeYamlContent(yamlContent) {
|
|
5938
|
+
let normalized = yamlContent;
|
|
5939
|
+
if (normalized.startsWith("\n")) {
|
|
5940
|
+
normalized = normalized.slice(1);
|
|
5941
|
+
}
|
|
5942
|
+
const lines = normalized.split("\n");
|
|
5943
|
+
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
|
5944
|
+
if (nonEmptyLines.length === 0) {
|
|
5945
|
+
return { normalized: "", nonEmptyLines };
|
|
5946
|
+
}
|
|
5947
|
+
const minIndent = Math.min(
|
|
5948
|
+
...nonEmptyLines.map((line) => {
|
|
5949
|
+
const match = line.match(LEADING_WHITESPACE_RE);
|
|
5950
|
+
return match ? match[1].length : 0;
|
|
5951
|
+
})
|
|
5952
|
+
);
|
|
5953
|
+
if (minIndent > 0) {
|
|
5954
|
+
normalized = lines.map((line) => line.slice(minIndent)).join("\n");
|
|
5955
|
+
}
|
|
5956
|
+
return { normalized, nonEmptyLines };
|
|
5957
|
+
}
|
|
5958
|
+
function parseYamlDocumentAsMapping(normalized) {
|
|
5959
|
+
try {
|
|
5960
|
+
const doc = import_yaml.default.parseDocument(normalized);
|
|
5961
|
+
const errors = doc.errors.map((e) => e.message);
|
|
5962
|
+
const result = doc.toJSON();
|
|
5963
|
+
if (result === null) {
|
|
5964
|
+
return { value: {}, errors };
|
|
5965
|
+
}
|
|
5966
|
+
if (typeof result !== "object" || Array.isArray(result)) {
|
|
5967
|
+
return { value: null, errors };
|
|
5968
|
+
}
|
|
5969
|
+
return { value: result, errors };
|
|
5970
|
+
} catch (error) {
|
|
5971
|
+
return {
|
|
5972
|
+
value: null,
|
|
5973
|
+
errors: [
|
|
5974
|
+
error instanceof Error ? error.message : "Unknown YAML parsing error"
|
|
5975
|
+
]
|
|
5976
|
+
};
|
|
5977
|
+
}
|
|
5978
|
+
}
|
|
5979
|
+
function getLastMeaningfulLineInfo(input) {
|
|
5980
|
+
var _a;
|
|
5981
|
+
const lines = input.split("\n");
|
|
5982
|
+
let index = lines.length - 1;
|
|
5983
|
+
while (index >= 0) {
|
|
5984
|
+
const raw = (_a = lines[index]) != null ? _a : "";
|
|
5985
|
+
const trimmed = raw.trim();
|
|
5986
|
+
if (trimmed.length > 0 && !trimmed.startsWith("#")) {
|
|
5987
|
+
return {
|
|
5988
|
+
index,
|
|
5989
|
+
raw,
|
|
5990
|
+
trimmed,
|
|
5991
|
+
indent: raw.length - raw.trimStart().length
|
|
5992
|
+
};
|
|
5993
|
+
}
|
|
5994
|
+
index -= 1;
|
|
5995
|
+
}
|
|
5996
|
+
return null;
|
|
5997
|
+
}
|
|
5998
|
+
function dropLastMeaningfulLine(input) {
|
|
5999
|
+
const lineInfo = getLastMeaningfulLineInfo(input);
|
|
6000
|
+
if (!lineInfo) {
|
|
6001
|
+
return null;
|
|
6002
|
+
}
|
|
6003
|
+
return input.split("\n").slice(0, lineInfo.index).join("\n").trimEnd();
|
|
6004
|
+
}
|
|
6005
|
+
function hasIncompleteMappingTail(normalized) {
|
|
6006
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6007
|
+
if (!lineInfo) {
|
|
6008
|
+
return false;
|
|
6009
|
+
}
|
|
6010
|
+
return INCOMPLETE_MAPPING_TAIL_RE.test(lineInfo.trimmed);
|
|
6011
|
+
}
|
|
6012
|
+
function hasIncompleteSequenceTail(normalized) {
|
|
6013
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6014
|
+
if (!lineInfo) {
|
|
6015
|
+
return false;
|
|
6016
|
+
}
|
|
6017
|
+
return INCOMPLETE_SEQUENCE_TAIL_RE.test(lineInfo.trimmed);
|
|
6018
|
+
}
|
|
6019
|
+
function hasSplitNestedKeyTail(normalized) {
|
|
6020
|
+
var _a;
|
|
6021
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6022
|
+
if (!lineInfo) {
|
|
6023
|
+
return false;
|
|
6024
|
+
}
|
|
6025
|
+
const { trimmed, indent, index } = lineInfo;
|
|
6026
|
+
if (indent === 0) {
|
|
6027
|
+
return false;
|
|
6028
|
+
}
|
|
6029
|
+
if (trimmed.startsWith("#") || trimmed.startsWith("-") || trimmed.includes(":")) {
|
|
6030
|
+
return false;
|
|
6031
|
+
}
|
|
6032
|
+
const lines = normalized.split("\n");
|
|
6033
|
+
let parentIndex = index - 1;
|
|
6034
|
+
while (parentIndex >= 0) {
|
|
6035
|
+
const parentRaw = (_a = lines[parentIndex]) != null ? _a : "";
|
|
6036
|
+
const parentTrimmed = parentRaw.trim();
|
|
6037
|
+
if (parentTrimmed.length === 0 || parentTrimmed.startsWith("#")) {
|
|
6038
|
+
parentIndex -= 1;
|
|
6039
|
+
continue;
|
|
6040
|
+
}
|
|
6041
|
+
const parentIndent = parentRaw.length - parentRaw.trimStart().length;
|
|
6042
|
+
if (parentIndent >= indent) {
|
|
6043
|
+
parentIndex -= 1;
|
|
6044
|
+
continue;
|
|
6045
|
+
}
|
|
6046
|
+
if (!parentTrimmed.endsWith(":")) {
|
|
6047
|
+
return false;
|
|
6048
|
+
}
|
|
6049
|
+
if (BLOCK_SCALAR_KEY_RE.test(parentTrimmed)) {
|
|
6050
|
+
return false;
|
|
6051
|
+
}
|
|
6052
|
+
return true;
|
|
6053
|
+
}
|
|
6054
|
+
return false;
|
|
6055
|
+
}
|
|
6056
|
+
function extractTrailingPlainScalarValue(line) {
|
|
6057
|
+
var _a;
|
|
6058
|
+
if (BLOCK_SCALAR_KEY_RE.test(line)) {
|
|
6059
|
+
return null;
|
|
6060
|
+
}
|
|
6061
|
+
const mappingMatch = line.match(PLAIN_MAPPING_VALUE_RE);
|
|
6062
|
+
const sequenceMatch = line.match(PLAIN_SEQUENCE_VALUE_RE);
|
|
6063
|
+
const value = (_a = mappingMatch == null ? void 0 : mappingMatch[1]) != null ? _a : sequenceMatch == null ? void 0 : sequenceMatch[1];
|
|
6064
|
+
if (!value) {
|
|
6065
|
+
return null;
|
|
6066
|
+
}
|
|
6067
|
+
const trimmedValue = value.trim();
|
|
6068
|
+
if (trimmedValue.length === 0) {
|
|
6069
|
+
return null;
|
|
6070
|
+
}
|
|
6071
|
+
if (trimmedValue.startsWith('"') || trimmedValue.startsWith("'")) {
|
|
6072
|
+
return null;
|
|
6073
|
+
}
|
|
6074
|
+
if (trimmedValue.startsWith("{") || trimmedValue.startsWith("[") || trimmedValue.startsWith("|") || trimmedValue.startsWith(">")) {
|
|
6075
|
+
return null;
|
|
6076
|
+
}
|
|
6077
|
+
return trimmedValue;
|
|
6078
|
+
}
|
|
6079
|
+
function hasUnterminatedPlainScalarTail(normalized) {
|
|
6080
|
+
if (normalized.endsWith("\n")) {
|
|
6081
|
+
return false;
|
|
6082
|
+
}
|
|
6083
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6084
|
+
if (!lineInfo) {
|
|
6085
|
+
return false;
|
|
6086
|
+
}
|
|
6087
|
+
return extractTrailingPlainScalarValue(lineInfo.trimmed) != null;
|
|
6088
|
+
}
|
|
6089
|
+
function hasUnstableProgressTail(normalized) {
|
|
6090
|
+
return hasIncompleteMappingTail(normalized) || hasIncompleteSequenceTail(normalized) || hasSplitNestedKeyTail(normalized) || hasUnterminatedPlainScalarTail(normalized);
|
|
6091
|
+
}
|
|
6092
|
+
function trimTrailingNewlineInUnknown(value) {
|
|
6093
|
+
if (typeof value === "string") {
|
|
6094
|
+
if (value.endsWith("\n")) {
|
|
6095
|
+
return value.slice(0, -1);
|
|
6096
|
+
}
|
|
6097
|
+
return value;
|
|
6098
|
+
}
|
|
6099
|
+
if (Array.isArray(value)) {
|
|
6100
|
+
return value.map((item) => trimTrailingNewlineInUnknown(item));
|
|
6101
|
+
}
|
|
6102
|
+
if (value && typeof value === "object") {
|
|
6103
|
+
return Object.fromEntries(
|
|
6104
|
+
Object.entries(value).map(([key, item]) => [
|
|
6105
|
+
key,
|
|
6106
|
+
trimTrailingNewlineInUnknown(item)
|
|
6107
|
+
])
|
|
6108
|
+
);
|
|
6109
|
+
}
|
|
6110
|
+
return value;
|
|
6111
|
+
}
|
|
6112
|
+
function stabilizeParsedValueForStreamProgress(value, source) {
|
|
6113
|
+
if (source.endsWith("\n")) {
|
|
6114
|
+
return value;
|
|
6115
|
+
}
|
|
6116
|
+
return trimTrailingNewlineInUnknown(value);
|
|
6117
|
+
}
|
|
5063
6118
|
function findClosingTagEnd(text, contentStart, toolName) {
|
|
5064
6119
|
let pos = contentStart;
|
|
5065
6120
|
let depth = 1;
|
|
@@ -5131,7 +6186,7 @@ function findEarliestTagPosition(openIdx, selfIdx) {
|
|
|
5131
6186
|
function collectToolCallsForName(text, toolName) {
|
|
5132
6187
|
const toolCalls = [];
|
|
5133
6188
|
let searchIndex = 0;
|
|
5134
|
-
const selfTagRegex =
|
|
6189
|
+
const selfTagRegex = getSelfClosingTagPattern2(toolName);
|
|
5135
6190
|
while (searchIndex < text.length) {
|
|
5136
6191
|
const startTag = `<${toolName}>`;
|
|
5137
6192
|
const openIdx = text.indexOf(startTag, searchIndex);
|
|
@@ -5183,47 +6238,48 @@ function findToolCalls2(text, toolNames) {
|
|
|
5183
6238
|
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
5184
6239
|
}
|
|
5185
6240
|
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);
|
|
6241
|
+
var _a, _b;
|
|
6242
|
+
const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
|
|
5193
6243
|
if (nonEmptyLines.length === 0) {
|
|
5194
6244
|
return {};
|
|
5195
6245
|
}
|
|
5196
|
-
const
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
})
|
|
5201
|
-
|
|
5202
|
-
if (minIndent > 0) {
|
|
5203
|
-
normalized = lines.map((line) => line.slice(minIndent)).join("\n");
|
|
6246
|
+
const parsed = parseYamlDocumentAsMapping(normalized);
|
|
6247
|
+
if (parsed.errors.length > 0) {
|
|
6248
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "YAML parse error", {
|
|
6249
|
+
errors: parsed.errors
|
|
6250
|
+
});
|
|
6251
|
+
return null;
|
|
5204
6252
|
}
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
6253
|
+
if (parsed.value === null) {
|
|
6254
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
|
|
6255
|
+
got: "non-mapping"
|
|
6256
|
+
});
|
|
6257
|
+
return null;
|
|
6258
|
+
}
|
|
6259
|
+
return parsed.value;
|
|
6260
|
+
}
|
|
6261
|
+
function parseYamlContentForStreamProgress(yamlContent) {
|
|
6262
|
+
const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
|
|
6263
|
+
if (nonEmptyLines.length === 0) {
|
|
6264
|
+
return {};
|
|
6265
|
+
}
|
|
6266
|
+
let candidate = normalized;
|
|
6267
|
+
while (true) {
|
|
6268
|
+
const parsed = parseYamlDocumentAsMapping(candidate);
|
|
6269
|
+
if (parsed.errors.length === 0 && !hasUnstableProgressTail(candidate)) {
|
|
6270
|
+
if (candidate.trim().length === 0 && normalized.trim().length > 0) {
|
|
6271
|
+
return null;
|
|
6272
|
+
}
|
|
6273
|
+
return stabilizeParsedValueForStreamProgress(parsed.value, candidate);
|
|
5212
6274
|
}
|
|
5213
|
-
const
|
|
5214
|
-
if (
|
|
5215
|
-
return
|
|
6275
|
+
const truncated = dropLastMeaningfulLine(candidate);
|
|
6276
|
+
if (truncated == null) {
|
|
6277
|
+
return null;
|
|
5216
6278
|
}
|
|
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
|
-
});
|
|
6279
|
+
if (truncated === candidate) {
|
|
5221
6280
|
return null;
|
|
5222
6281
|
}
|
|
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;
|
|
6282
|
+
candidate = truncated;
|
|
5227
6283
|
}
|
|
5228
6284
|
}
|
|
5229
6285
|
function processToolCallMatch(text, tc, currentIndex, processedElements, options) {
|
|
@@ -5239,7 +6295,7 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
|
|
|
5239
6295
|
if (parsedArgs !== null) {
|
|
5240
6296
|
processedElements.push({
|
|
5241
6297
|
type: "tool-call",
|
|
5242
|
-
toolCallId:
|
|
6298
|
+
toolCallId: generateToolCallId(),
|
|
5243
6299
|
toolName: tc.toolName,
|
|
5244
6300
|
input: JSON.stringify(parsedArgs)
|
|
5245
6301
|
});
|
|
@@ -5252,38 +6308,6 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
|
|
|
5252
6308
|
}
|
|
5253
6309
|
return tc.endIndex;
|
|
5254
6310
|
}
|
|
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
6311
|
function findEarliestToolTag2(buffer, toolNames) {
|
|
5288
6312
|
let bestIndex = -1;
|
|
5289
6313
|
let bestName = "";
|
|
@@ -5291,8 +6315,9 @@ function findEarliestToolTag2(buffer, toolNames) {
|
|
|
5291
6315
|
let bestTagLength = 0;
|
|
5292
6316
|
for (const name of toolNames) {
|
|
5293
6317
|
const openTag = `<${name}>`;
|
|
5294
|
-
const selfTagRegex =
|
|
6318
|
+
const selfTagRegex = getSelfClosingTagPattern2(name);
|
|
5295
6319
|
const idxOpen = buffer.indexOf(openTag);
|
|
6320
|
+
selfTagRegex.lastIndex = 0;
|
|
5296
6321
|
const selfMatch = selfTagRegex.exec(buffer);
|
|
5297
6322
|
const idxSelf = selfMatch ? selfMatch.index : -1;
|
|
5298
6323
|
if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
|
|
@@ -5315,6 +6340,29 @@ function findEarliestToolTag2(buffer, toolNames) {
|
|
|
5315
6340
|
tagLength: bestTagLength
|
|
5316
6341
|
};
|
|
5317
6342
|
}
|
|
6343
|
+
function stripTrailingPartialCloseTag(content, toolName) {
|
|
6344
|
+
const closeTag = `</${toolName}>`;
|
|
6345
|
+
const lastLineBreakIndex = Math.max(
|
|
6346
|
+
content.lastIndexOf("\n"),
|
|
6347
|
+
content.lastIndexOf("\r")
|
|
6348
|
+
);
|
|
6349
|
+
const lineStartIndex = lastLineBreakIndex === -1 ? 0 : lastLineBreakIndex + 1;
|
|
6350
|
+
const trailingLine = content.slice(lineStartIndex);
|
|
6351
|
+
const trimmedTrailingLine = trailingLine.trim();
|
|
6352
|
+
if (trimmedTrailingLine.length === 0 || !trimmedTrailingLine.startsWith("</") || trimmedTrailingLine === closeTag || !closeTag.startsWith(trimmedTrailingLine)) {
|
|
6353
|
+
return content;
|
|
6354
|
+
}
|
|
6355
|
+
const leadingWhitespaceLength = trailingLine.length - trailingLine.trimStart().length;
|
|
6356
|
+
const preservedLeadingWhitespace = trailingLine.slice(
|
|
6357
|
+
0,
|
|
6358
|
+
leadingWhitespaceLength
|
|
6359
|
+
);
|
|
6360
|
+
const contentWithoutPartial = `${content.slice(
|
|
6361
|
+
0,
|
|
6362
|
+
lineStartIndex
|
|
6363
|
+
)}${preservedLeadingWhitespace}`;
|
|
6364
|
+
return contentWithoutPartial.trimEnd();
|
|
6365
|
+
}
|
|
5318
6366
|
var yamlProtocol = (_protocolOptions) => {
|
|
5319
6367
|
return {
|
|
5320
6368
|
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
@@ -5375,7 +6423,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5375
6423
|
let currentToolCall = null;
|
|
5376
6424
|
let currentTextId = null;
|
|
5377
6425
|
let hasEmittedTextStart = false;
|
|
5378
|
-
const flushText =
|
|
6426
|
+
const flushText = createFlushTextHandler(
|
|
5379
6427
|
() => currentTextId,
|
|
5380
6428
|
(newId) => {
|
|
5381
6429
|
currentTextId = newId;
|
|
@@ -5385,33 +6433,128 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5385
6433
|
hasEmittedTextStart = value;
|
|
5386
6434
|
}
|
|
5387
6435
|
);
|
|
5388
|
-
const
|
|
6436
|
+
const emitToolInputProgress2 = (controller, toolContent) => {
|
|
6437
|
+
if (!currentToolCall) {
|
|
6438
|
+
return;
|
|
6439
|
+
}
|
|
6440
|
+
const parsedArgs = parseYamlContentForStreamProgress(toolContent);
|
|
6441
|
+
if (parsedArgs === null) {
|
|
6442
|
+
return;
|
|
6443
|
+
}
|
|
6444
|
+
const fullInput = JSON.stringify(parsedArgs);
|
|
6445
|
+
if (fullInput === "{}" && toolContent.trim().length === 0) {
|
|
6446
|
+
return;
|
|
6447
|
+
}
|
|
6448
|
+
const prefixCandidate = toIncompleteJsonPrefix(fullInput);
|
|
6449
|
+
emitPrefixDelta({
|
|
6450
|
+
controller,
|
|
6451
|
+
id: currentToolCall.toolCallId,
|
|
6452
|
+
state: currentToolCall,
|
|
6453
|
+
candidate: prefixCandidate
|
|
6454
|
+
});
|
|
6455
|
+
};
|
|
6456
|
+
const processToolCallEnd = (controller, toolContent, toolName, toolCallId) => {
|
|
5389
6457
|
var _a;
|
|
5390
6458
|
const parsedArgs = parseYamlContent(toolContent, options);
|
|
5391
6459
|
flushText(controller);
|
|
5392
6460
|
if (parsedArgs !== null) {
|
|
6461
|
+
const finalInput = JSON.stringify(parsedArgs);
|
|
6462
|
+
if (currentToolCall && currentToolCall.toolCallId === toolCallId) {
|
|
6463
|
+
emitFinalRemainder({
|
|
6464
|
+
controller,
|
|
6465
|
+
id: toolCallId,
|
|
6466
|
+
state: currentToolCall,
|
|
6467
|
+
finalFullJson: finalInput,
|
|
6468
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
6469
|
+
});
|
|
6470
|
+
}
|
|
6471
|
+
controller.enqueue({
|
|
6472
|
+
type: "tool-input-end",
|
|
6473
|
+
id: toolCallId
|
|
6474
|
+
});
|
|
5393
6475
|
controller.enqueue({
|
|
5394
6476
|
type: "tool-call",
|
|
5395
|
-
toolCallId
|
|
6477
|
+
toolCallId,
|
|
5396
6478
|
toolName,
|
|
5397
|
-
input:
|
|
6479
|
+
input: finalInput
|
|
5398
6480
|
});
|
|
5399
6481
|
} else {
|
|
6482
|
+
controller.enqueue({
|
|
6483
|
+
type: "tool-input-end",
|
|
6484
|
+
id: toolCallId
|
|
6485
|
+
});
|
|
5400
6486
|
const original = `<${toolName}>${toolContent}</${toolName}>`;
|
|
5401
6487
|
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
|
|
5402
6488
|
toolCall: original
|
|
5403
6489
|
});
|
|
5404
|
-
|
|
6490
|
+
if (shouldEmitRawToolCallTextOnError3(options)) {
|
|
6491
|
+
flushText(controller, original);
|
|
6492
|
+
}
|
|
5405
6493
|
}
|
|
5406
6494
|
};
|
|
6495
|
+
const finalizeUnclosedToolCall = (controller) => {
|
|
6496
|
+
var _a;
|
|
6497
|
+
if (!currentToolCall) {
|
|
6498
|
+
return;
|
|
6499
|
+
}
|
|
6500
|
+
emitToolInputProgress2(controller, buffer);
|
|
6501
|
+
const { name: toolName, toolCallId } = currentToolCall;
|
|
6502
|
+
const reconciledBuffer = stripTrailingPartialCloseTag(buffer, toolName);
|
|
6503
|
+
const parsedArgs = parseYamlContent(reconciledBuffer, options);
|
|
6504
|
+
flushText(controller);
|
|
6505
|
+
if (parsedArgs !== null) {
|
|
6506
|
+
const finalInput = JSON.stringify(parsedArgs);
|
|
6507
|
+
emitFinalRemainder({
|
|
6508
|
+
controller,
|
|
6509
|
+
id: toolCallId,
|
|
6510
|
+
state: currentToolCall,
|
|
6511
|
+
finalFullJson: finalInput,
|
|
6512
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
6513
|
+
});
|
|
6514
|
+
controller.enqueue({
|
|
6515
|
+
type: "tool-input-end",
|
|
6516
|
+
id: toolCallId
|
|
6517
|
+
});
|
|
6518
|
+
controller.enqueue({
|
|
6519
|
+
type: "tool-call",
|
|
6520
|
+
toolCallId,
|
|
6521
|
+
toolName,
|
|
6522
|
+
input: finalInput
|
|
6523
|
+
});
|
|
6524
|
+
} else {
|
|
6525
|
+
controller.enqueue({
|
|
6526
|
+
type: "tool-input-end",
|
|
6527
|
+
id: toolCallId
|
|
6528
|
+
});
|
|
6529
|
+
const unfinishedContent = `<${toolName}>${buffer}`;
|
|
6530
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
6531
|
+
options,
|
|
6532
|
+
"Could not complete streaming YAML tool call at finish.",
|
|
6533
|
+
{ toolCall: unfinishedContent }
|
|
6534
|
+
);
|
|
6535
|
+
if (shouldEmitRawToolCallTextOnError3(options)) {
|
|
6536
|
+
flushText(controller, unfinishedContent);
|
|
6537
|
+
}
|
|
6538
|
+
}
|
|
6539
|
+
buffer = "";
|
|
6540
|
+
currentToolCall = null;
|
|
6541
|
+
};
|
|
5407
6542
|
const handlePendingToolCall = (controller, endTag, toolName) => {
|
|
6543
|
+
var _a;
|
|
5408
6544
|
const endIdx = buffer.indexOf(endTag);
|
|
5409
6545
|
if (endIdx === -1) {
|
|
6546
|
+
emitToolInputProgress2(controller, buffer);
|
|
5410
6547
|
return false;
|
|
5411
6548
|
}
|
|
5412
6549
|
const content = buffer.substring(0, endIdx);
|
|
6550
|
+
emitToolInputProgress2(controller, content);
|
|
5413
6551
|
buffer = buffer.substring(endIdx + endTag.length);
|
|
5414
|
-
processToolCallEnd(
|
|
6552
|
+
processToolCallEnd(
|
|
6553
|
+
controller,
|
|
6554
|
+
content,
|
|
6555
|
+
toolName,
|
|
6556
|
+
(_a = currentToolCall == null ? void 0 : currentToolCall.toolCallId) != null ? _a : generateToolCallId()
|
|
6557
|
+
);
|
|
5415
6558
|
currentToolCall = null;
|
|
5416
6559
|
return true;
|
|
5417
6560
|
};
|
|
@@ -5428,13 +6571,35 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5428
6571
|
if (tagIndex > 0) {
|
|
5429
6572
|
flushText(controller, buffer.substring(0, tagIndex));
|
|
5430
6573
|
}
|
|
6574
|
+
flushText(controller);
|
|
5431
6575
|
if (selfClosing) {
|
|
5432
6576
|
buffer = buffer.substring(tagIndex + tagLength);
|
|
5433
|
-
|
|
6577
|
+
const toolCallId = generateToolCallId();
|
|
6578
|
+
currentToolCall = {
|
|
6579
|
+
name: tagName,
|
|
6580
|
+
toolCallId,
|
|
6581
|
+
emittedInput: ""
|
|
6582
|
+
};
|
|
6583
|
+
controller.enqueue({
|
|
6584
|
+
type: "tool-input-start",
|
|
6585
|
+
id: toolCallId,
|
|
6586
|
+
toolName: tagName
|
|
6587
|
+
});
|
|
6588
|
+
processToolCallEnd(controller, "", tagName, toolCallId);
|
|
6589
|
+
currentToolCall = null;
|
|
5434
6590
|
} else {
|
|
5435
6591
|
const startTag = `<${tagName}>`;
|
|
5436
6592
|
buffer = buffer.substring(tagIndex + startTag.length);
|
|
5437
|
-
currentToolCall = {
|
|
6593
|
+
currentToolCall = {
|
|
6594
|
+
name: tagName,
|
|
6595
|
+
toolCallId: generateToolCallId(),
|
|
6596
|
+
emittedInput: ""
|
|
6597
|
+
};
|
|
6598
|
+
controller.enqueue({
|
|
6599
|
+
type: "tool-input-start",
|
|
6600
|
+
id: currentToolCall.toolCallId,
|
|
6601
|
+
toolName: tagName
|
|
6602
|
+
});
|
|
5438
6603
|
}
|
|
5439
6604
|
};
|
|
5440
6605
|
const processBuffer = (controller) => {
|
|
@@ -5463,10 +6628,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5463
6628
|
var _a;
|
|
5464
6629
|
if (chunk.type === "finish") {
|
|
5465
6630
|
if (currentToolCall) {
|
|
5466
|
-
|
|
5467
|
-
flushText(controller, unfinishedContent);
|
|
5468
|
-
buffer = "";
|
|
5469
|
-
currentToolCall = null;
|
|
6631
|
+
finalizeUnclosedToolCall(controller);
|
|
5470
6632
|
} else if (buffer) {
|
|
5471
6633
|
flushText(controller, buffer);
|
|
5472
6634
|
buffer = "";
|
|
@@ -5476,7 +6638,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5476
6638
|
return;
|
|
5477
6639
|
}
|
|
5478
6640
|
if (chunk.type !== "text-delta") {
|
|
5479
|
-
if (buffer) {
|
|
6641
|
+
if (!currentToolCall && buffer) {
|
|
5480
6642
|
flushText(controller, buffer);
|
|
5481
6643
|
buffer = "";
|
|
5482
6644
|
}
|
|
@@ -5489,10 +6651,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5489
6651
|
},
|
|
5490
6652
|
flush(controller) {
|
|
5491
6653
|
if (currentToolCall) {
|
|
5492
|
-
|
|
5493
|
-
flushText(controller, unfinishedContent);
|
|
5494
|
-
buffer = "";
|
|
5495
|
-
currentToolCall = null;
|
|
6654
|
+
finalizeUnclosedToolCall(controller);
|
|
5496
6655
|
} else if (buffer) {
|
|
5497
6656
|
flushText(controller, buffer);
|
|
5498
6657
|
buffer = "";
|
|
@@ -5670,9 +6829,6 @@ function hasInputProperty(obj) {
|
|
|
5670
6829
|
return typeof obj === "object" && obj !== null && "input" in obj;
|
|
5671
6830
|
}
|
|
5672
6831
|
|
|
5673
|
-
// src/generate-handler.ts
|
|
5674
|
-
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
5675
|
-
|
|
5676
6832
|
// src/core/utils/generated-text-json-recovery.ts
|
|
5677
6833
|
function isRecord(value) {
|
|
5678
6834
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -5811,7 +6967,7 @@ function mergeJsonCandidatesByStart(tagged, codeBlocks, balanced) {
|
|
|
5811
6967
|
function toToolCallPart(candidate) {
|
|
5812
6968
|
return {
|
|
5813
6969
|
type: "tool-call",
|
|
5814
|
-
toolCallId:
|
|
6970
|
+
toolCallId: generateToolCallId(),
|
|
5815
6971
|
toolName: candidate.toolName,
|
|
5816
6972
|
input: candidate.input
|
|
5817
6973
|
};
|
|
@@ -6038,7 +7194,7 @@ async function handleToolChoice(doGenerate, params, tools) {
|
|
|
6038
7194
|
}
|
|
6039
7195
|
const toolCall = {
|
|
6040
7196
|
type: "tool-call",
|
|
6041
|
-
toolCallId: (
|
|
7197
|
+
toolCallId: generateToolCallId(),
|
|
6042
7198
|
toolName,
|
|
6043
7199
|
input
|
|
6044
7200
|
};
|
|
@@ -6548,7 +7704,6 @@ unit: celsius
|
|
|
6548
7704
|
}
|
|
6549
7705
|
|
|
6550
7706
|
// src/stream-handler.ts
|
|
6551
|
-
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
6552
7707
|
async function wrapStream({
|
|
6553
7708
|
protocol,
|
|
6554
7709
|
doStream,
|
|
@@ -6586,10 +7741,22 @@ async function wrapStream({
|
|
|
6586
7741
|
}
|
|
6587
7742
|
)
|
|
6588
7743
|
).pipeThrough(protocol.createStreamParser({ tools, options }));
|
|
7744
|
+
let seenToolCall = false;
|
|
6589
7745
|
const v3Stream = coreStream.pipeThrough(
|
|
6590
7746
|
new TransformStream({
|
|
6591
7747
|
transform(part, controller) {
|
|
6592
|
-
|
|
7748
|
+
let normalizedPart = part.type === "tool-call" ? coerceToolCallPart(part, tools) : part;
|
|
7749
|
+
if (normalizedPart.type === "tool-call") {
|
|
7750
|
+
seenToolCall = true;
|
|
7751
|
+
}
|
|
7752
|
+
if (normalizedPart.type === "finish" && seenToolCall && normalizedPart.finishReason.unified === "stop") {
|
|
7753
|
+
normalizedPart = {
|
|
7754
|
+
...normalizedPart,
|
|
7755
|
+
finishReason: normalizeToolCallsFinishReason(
|
|
7756
|
+
normalizedPart.finishReason
|
|
7757
|
+
)
|
|
7758
|
+
};
|
|
7759
|
+
}
|
|
6593
7760
|
if (debugLevel === "stream") {
|
|
6594
7761
|
logParsedChunk(normalizedPart);
|
|
6595
7762
|
}
|
|
@@ -6626,7 +7793,7 @@ async function toolChoiceStream({
|
|
|
6626
7793
|
start(controller) {
|
|
6627
7794
|
controller.enqueue({
|
|
6628
7795
|
type: "tool-call",
|
|
6629
|
-
toolCallId: (
|
|
7796
|
+
toolCallId: generateToolCallId(),
|
|
6630
7797
|
toolName,
|
|
6631
7798
|
input
|
|
6632
7799
|
});
|