@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/community.cjs
CHANGED
|
@@ -847,7 +847,25 @@ function getPotentialStartIndex(text, searchedText) {
|
|
|
847
847
|
|
|
848
848
|
// src/core/utils/id.ts
|
|
849
849
|
function generateId() {
|
|
850
|
-
return
|
|
850
|
+
return crypto.randomUUID().replace(/-/g, "").slice(0, 13);
|
|
851
|
+
}
|
|
852
|
+
var TOOL_CALL_ID_PREFIX = "call_";
|
|
853
|
+
var TOOL_CALL_ID_BODY_LENGTH = 24;
|
|
854
|
+
var TOOL_CALL_ID_ALPHANUM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
855
|
+
function randomAlphaNumeric(length) {
|
|
856
|
+
var _a;
|
|
857
|
+
const bytes = new Uint8Array(length);
|
|
858
|
+
crypto.getRandomValues(bytes);
|
|
859
|
+
let out = "";
|
|
860
|
+
for (let i = 0; i < length; i += 1) {
|
|
861
|
+
const byte = bytes[i];
|
|
862
|
+
const index = (byte != null ? byte : 0) % TOOL_CALL_ID_ALPHANUM.length;
|
|
863
|
+
out += (_a = TOOL_CALL_ID_ALPHANUM[index]) != null ? _a : "0";
|
|
864
|
+
}
|
|
865
|
+
return out;
|
|
866
|
+
}
|
|
867
|
+
function generateToolCallId() {
|
|
868
|
+
return `${TOOL_CALL_ID_PREFIX}${randomAlphaNumeric(TOOL_CALL_ID_BODY_LENGTH)}`;
|
|
851
869
|
}
|
|
852
870
|
|
|
853
871
|
// src/core/utils/protocol-utils.ts
|
|
@@ -856,6 +874,38 @@ function addTextSegment(text, processedElements) {
|
|
|
856
874
|
processedElements.push({ type: "text", text });
|
|
857
875
|
}
|
|
858
876
|
}
|
|
877
|
+
function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
878
|
+
return (controller, text) => {
|
|
879
|
+
const content = text;
|
|
880
|
+
if (content) {
|
|
881
|
+
if (!getCurrentTextId()) {
|
|
882
|
+
const newId = generateId();
|
|
883
|
+
setCurrentTextId(newId);
|
|
884
|
+
controller.enqueue({
|
|
885
|
+
type: "text-start",
|
|
886
|
+
id: newId
|
|
887
|
+
});
|
|
888
|
+
setHasEmittedTextStart(true);
|
|
889
|
+
}
|
|
890
|
+
controller.enqueue({
|
|
891
|
+
type: "text-delta",
|
|
892
|
+
id: getCurrentTextId(),
|
|
893
|
+
delta: content
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
const currentTextId = getCurrentTextId();
|
|
897
|
+
if (currentTextId && !text) {
|
|
898
|
+
if (getHasEmittedTextStart()) {
|
|
899
|
+
controller.enqueue({
|
|
900
|
+
type: "text-end",
|
|
901
|
+
id: currentTextId
|
|
902
|
+
});
|
|
903
|
+
setHasEmittedTextStart(false);
|
|
904
|
+
}
|
|
905
|
+
setCurrentTextId(null);
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
}
|
|
859
909
|
|
|
860
910
|
// src/core/utils/regex.ts
|
|
861
911
|
function escapeRegExp(literal) {
|
|
@@ -863,15 +913,21 @@ function escapeRegExp(literal) {
|
|
|
863
913
|
}
|
|
864
914
|
|
|
865
915
|
// src/core/protocols/json-protocol.ts
|
|
916
|
+
function shouldEmitRawToolCallTextOnError(options) {
|
|
917
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
918
|
+
}
|
|
919
|
+
function canonicalizeToolInput(argumentsValue) {
|
|
920
|
+
return JSON.stringify(argumentsValue != null ? argumentsValue : {});
|
|
921
|
+
}
|
|
866
922
|
function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
|
|
867
|
-
var _a
|
|
923
|
+
var _a;
|
|
868
924
|
try {
|
|
869
925
|
const parsedToolCall = parse(toolCallJson);
|
|
870
926
|
processedElements.push({
|
|
871
927
|
type: "tool-call",
|
|
872
|
-
toolCallId:
|
|
928
|
+
toolCallId: generateToolCallId(),
|
|
873
929
|
toolName: parsedToolCall.name,
|
|
874
|
-
input:
|
|
930
|
+
input: canonicalizeToolInput(parsedToolCall.arguments)
|
|
875
931
|
});
|
|
876
932
|
} catch (error) {
|
|
877
933
|
logParseFailure({
|
|
@@ -880,7 +936,7 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
|
|
|
880
936
|
snippet: fullMatch,
|
|
881
937
|
error
|
|
882
938
|
});
|
|
883
|
-
(
|
|
939
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
884
940
|
options,
|
|
885
941
|
"Could not process JSON tool call, keeping original text.",
|
|
886
942
|
{ toolCall: fullMatch, error }
|
|
@@ -901,6 +957,293 @@ function processMatchedToolCall(context) {
|
|
|
901
957
|
}
|
|
902
958
|
return startIndex + match[0].length;
|
|
903
959
|
}
|
|
960
|
+
var WHITESPACE_JSON_REGEX = /\s/;
|
|
961
|
+
function skipJsonWhitespace(text, fromIndex) {
|
|
962
|
+
let index = fromIndex;
|
|
963
|
+
while (index < text.length && WHITESPACE_JSON_REGEX.test(text[index])) {
|
|
964
|
+
index += 1;
|
|
965
|
+
}
|
|
966
|
+
return index;
|
|
967
|
+
}
|
|
968
|
+
function findTopLevelPropertyValueStart(text, property) {
|
|
969
|
+
const objectStart = skipJsonWhitespace(text, 0);
|
|
970
|
+
if (objectStart >= text.length || text.charAt(objectStart) !== "{") {
|
|
971
|
+
return null;
|
|
972
|
+
}
|
|
973
|
+
let depth = 0;
|
|
974
|
+
let inString = false;
|
|
975
|
+
let escaping = false;
|
|
976
|
+
for (let index = objectStart; index < text.length; index += 1) {
|
|
977
|
+
const char = text.charAt(index);
|
|
978
|
+
if (inString) {
|
|
979
|
+
if (escaping) {
|
|
980
|
+
escaping = false;
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
if (char === "\\") {
|
|
984
|
+
escaping = true;
|
|
985
|
+
continue;
|
|
986
|
+
}
|
|
987
|
+
if (char === '"') {
|
|
988
|
+
inString = false;
|
|
989
|
+
}
|
|
990
|
+
continue;
|
|
991
|
+
}
|
|
992
|
+
if (char === "{") {
|
|
993
|
+
depth += 1;
|
|
994
|
+
continue;
|
|
995
|
+
}
|
|
996
|
+
if (char === "}") {
|
|
997
|
+
depth = Math.max(0, depth - 1);
|
|
998
|
+
continue;
|
|
999
|
+
}
|
|
1000
|
+
if (char !== '"') {
|
|
1001
|
+
continue;
|
|
1002
|
+
}
|
|
1003
|
+
if (depth !== 1) {
|
|
1004
|
+
inString = true;
|
|
1005
|
+
continue;
|
|
1006
|
+
}
|
|
1007
|
+
const keyStart = index + 1;
|
|
1008
|
+
let keyEnd = keyStart;
|
|
1009
|
+
let keyEscaped = false;
|
|
1010
|
+
while (keyEnd < text.length) {
|
|
1011
|
+
const keyChar = text.charAt(keyEnd);
|
|
1012
|
+
if (keyEscaped) {
|
|
1013
|
+
keyEscaped = false;
|
|
1014
|
+
} else if (keyChar === "\\") {
|
|
1015
|
+
keyEscaped = true;
|
|
1016
|
+
} else if (keyChar === '"') {
|
|
1017
|
+
break;
|
|
1018
|
+
}
|
|
1019
|
+
keyEnd += 1;
|
|
1020
|
+
}
|
|
1021
|
+
if (keyEnd >= text.length || text.charAt(keyEnd) !== '"') {
|
|
1022
|
+
return null;
|
|
1023
|
+
}
|
|
1024
|
+
const key = text.slice(keyStart, keyEnd);
|
|
1025
|
+
let valueCursor = skipJsonWhitespace(text, keyEnd + 1);
|
|
1026
|
+
if (valueCursor >= text.length || text.charAt(valueCursor) !== ":") {
|
|
1027
|
+
index = keyEnd;
|
|
1028
|
+
continue;
|
|
1029
|
+
}
|
|
1030
|
+
valueCursor = skipJsonWhitespace(text, valueCursor + 1);
|
|
1031
|
+
if (key === property) {
|
|
1032
|
+
return valueCursor < text.length ? valueCursor : null;
|
|
1033
|
+
}
|
|
1034
|
+
index = valueCursor - 1;
|
|
1035
|
+
}
|
|
1036
|
+
return null;
|
|
1037
|
+
}
|
|
1038
|
+
function extractTopLevelStringProperty(text, property) {
|
|
1039
|
+
const valueStart = findTopLevelPropertyValueStart(text, property);
|
|
1040
|
+
if (valueStart == null || valueStart >= text.length) {
|
|
1041
|
+
return void 0;
|
|
1042
|
+
}
|
|
1043
|
+
if (text.charAt(valueStart) !== '"') {
|
|
1044
|
+
return void 0;
|
|
1045
|
+
}
|
|
1046
|
+
let valueEnd = valueStart + 1;
|
|
1047
|
+
let escaped = false;
|
|
1048
|
+
while (valueEnd < text.length) {
|
|
1049
|
+
const char = text.charAt(valueEnd);
|
|
1050
|
+
if (escaped) {
|
|
1051
|
+
escaped = false;
|
|
1052
|
+
} else if (char === "\\") {
|
|
1053
|
+
escaped = true;
|
|
1054
|
+
} else if (char === '"') {
|
|
1055
|
+
return text.slice(valueStart + 1, valueEnd);
|
|
1056
|
+
}
|
|
1057
|
+
valueEnd += 1;
|
|
1058
|
+
}
|
|
1059
|
+
return void 0;
|
|
1060
|
+
}
|
|
1061
|
+
function extractJsonValueSlice(text, valueStart) {
|
|
1062
|
+
if (valueStart >= text.length) {
|
|
1063
|
+
return null;
|
|
1064
|
+
}
|
|
1065
|
+
const first = text.charAt(valueStart);
|
|
1066
|
+
if (first === "{" || first === "[") {
|
|
1067
|
+
const stack = [first];
|
|
1068
|
+
let inString = false;
|
|
1069
|
+
let escaped = false;
|
|
1070
|
+
for (let index2 = valueStart + 1; index2 < text.length; index2 += 1) {
|
|
1071
|
+
const char = text.charAt(index2);
|
|
1072
|
+
if (inString) {
|
|
1073
|
+
if (escaped) {
|
|
1074
|
+
escaped = false;
|
|
1075
|
+
} else if (char === "\\") {
|
|
1076
|
+
escaped = true;
|
|
1077
|
+
} else if (char === '"') {
|
|
1078
|
+
inString = false;
|
|
1079
|
+
}
|
|
1080
|
+
continue;
|
|
1081
|
+
}
|
|
1082
|
+
if (char === '"') {
|
|
1083
|
+
inString = true;
|
|
1084
|
+
continue;
|
|
1085
|
+
}
|
|
1086
|
+
if (char === "{" || char === "[") {
|
|
1087
|
+
stack.push(char);
|
|
1088
|
+
continue;
|
|
1089
|
+
}
|
|
1090
|
+
if (char === "}" || char === "]") {
|
|
1091
|
+
const open = stack.at(-1);
|
|
1092
|
+
if (open === "{" && char === "}" || open === "[" && char === "]") {
|
|
1093
|
+
stack.pop();
|
|
1094
|
+
if (stack.length === 0) {
|
|
1095
|
+
return {
|
|
1096
|
+
text: text.slice(valueStart, index2 + 1),
|
|
1097
|
+
complete: true
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
return {
|
|
1104
|
+
text: text.slice(valueStart),
|
|
1105
|
+
complete: false
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
if (first === '"') {
|
|
1109
|
+
let escaped = false;
|
|
1110
|
+
for (let index2 = valueStart + 1; index2 < text.length; index2 += 1) {
|
|
1111
|
+
const char = text.charAt(index2);
|
|
1112
|
+
if (escaped) {
|
|
1113
|
+
escaped = false;
|
|
1114
|
+
} else if (char === "\\") {
|
|
1115
|
+
escaped = true;
|
|
1116
|
+
} else if (char === '"') {
|
|
1117
|
+
return {
|
|
1118
|
+
text: text.slice(valueStart, index2 + 1),
|
|
1119
|
+
complete: true
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
return {
|
|
1124
|
+
text: text.slice(valueStart),
|
|
1125
|
+
complete: false
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
let index = valueStart;
|
|
1129
|
+
while (index < text.length) {
|
|
1130
|
+
const char = text.charAt(index);
|
|
1131
|
+
if (char === "," || char === "}" || WHITESPACE_JSON_REGEX.test(char)) {
|
|
1132
|
+
break;
|
|
1133
|
+
}
|
|
1134
|
+
index += 1;
|
|
1135
|
+
}
|
|
1136
|
+
return {
|
|
1137
|
+
text: text.slice(valueStart, index),
|
|
1138
|
+
complete: index < text.length
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
function extractStreamingToolCallProgress(toolCallJson) {
|
|
1142
|
+
var _a;
|
|
1143
|
+
const toolName = extractTopLevelStringProperty(toolCallJson, "name");
|
|
1144
|
+
const argsValueStart = findTopLevelPropertyValueStart(
|
|
1145
|
+
toolCallJson,
|
|
1146
|
+
"arguments"
|
|
1147
|
+
);
|
|
1148
|
+
if (argsValueStart == null) {
|
|
1149
|
+
return {
|
|
1150
|
+
toolName,
|
|
1151
|
+
argumentsText: void 0,
|
|
1152
|
+
argumentsComplete: false
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
const argsSlice = extractJsonValueSlice(toolCallJson, argsValueStart);
|
|
1156
|
+
return {
|
|
1157
|
+
toolName,
|
|
1158
|
+
argumentsText: argsSlice == null ? void 0 : argsSlice.text,
|
|
1159
|
+
argumentsComplete: (_a = argsSlice == null ? void 0 : argsSlice.complete) != null ? _a : false
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
function ensureToolInputStart(state, controller, toolName) {
|
|
1163
|
+
if (!state.activeToolInput) {
|
|
1164
|
+
const id = generateToolCallId();
|
|
1165
|
+
state.activeToolInput = {
|
|
1166
|
+
id,
|
|
1167
|
+
toolName,
|
|
1168
|
+
emittedInput: ""
|
|
1169
|
+
};
|
|
1170
|
+
controller.enqueue({
|
|
1171
|
+
type: "tool-input-start",
|
|
1172
|
+
id,
|
|
1173
|
+
toolName
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
function emitToolInputDelta(state, controller, fullInput) {
|
|
1178
|
+
const active = state.activeToolInput;
|
|
1179
|
+
if (!active) {
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
if (!fullInput.startsWith(active.emittedInput)) {
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
1185
|
+
const delta = fullInput.slice(active.emittedInput.length);
|
|
1186
|
+
if (delta.length === 0) {
|
|
1187
|
+
return;
|
|
1188
|
+
}
|
|
1189
|
+
controller.enqueue({
|
|
1190
|
+
type: "tool-input-delta",
|
|
1191
|
+
id: active.id,
|
|
1192
|
+
delta
|
|
1193
|
+
});
|
|
1194
|
+
active.emittedInput = fullInput;
|
|
1195
|
+
}
|
|
1196
|
+
function closeToolInput(state, controller) {
|
|
1197
|
+
if (!state.activeToolInput) {
|
|
1198
|
+
return;
|
|
1199
|
+
}
|
|
1200
|
+
controller.enqueue({
|
|
1201
|
+
type: "tool-input-end",
|
|
1202
|
+
id: state.activeToolInput.id
|
|
1203
|
+
});
|
|
1204
|
+
state.activeToolInput = null;
|
|
1205
|
+
}
|
|
1206
|
+
function emitToolCallFromParsed(state, controller, parsedToolCall) {
|
|
1207
|
+
var _a, _b, _c, _d;
|
|
1208
|
+
closeTextBlock(state, controller);
|
|
1209
|
+
const toolName = typeof parsedToolCall.name === "string" ? parsedToolCall.name : (_b = (_a = state.activeToolInput) == null ? void 0 : _a.toolName) != null ? _b : "unknown";
|
|
1210
|
+
const input = canonicalizeToolInput(parsedToolCall.arguments);
|
|
1211
|
+
ensureToolInputStart(state, controller, toolName);
|
|
1212
|
+
emitToolInputDelta(state, controller, input);
|
|
1213
|
+
const toolCallId = (_d = (_c = state.activeToolInput) == null ? void 0 : _c.id) != null ? _d : generateToolCallId();
|
|
1214
|
+
closeToolInput(state, controller);
|
|
1215
|
+
controller.enqueue({
|
|
1216
|
+
type: "tool-call",
|
|
1217
|
+
toolCallId,
|
|
1218
|
+
toolName,
|
|
1219
|
+
input
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
function canonicalizeArgumentsProgressInput(progress) {
|
|
1223
|
+
if (progress.argumentsText === void 0 || !progress.argumentsComplete) {
|
|
1224
|
+
return void 0;
|
|
1225
|
+
}
|
|
1226
|
+
try {
|
|
1227
|
+
const parsedArguments = parse(progress.argumentsText);
|
|
1228
|
+
return canonicalizeToolInput(parsedArguments);
|
|
1229
|
+
} catch (e) {
|
|
1230
|
+
return void 0;
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
function emitToolInputProgress(state, controller) {
|
|
1234
|
+
if (!(state.isInsideToolCall && state.currentToolCallJson)) {
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
const progress = extractStreamingToolCallProgress(state.currentToolCallJson);
|
|
1238
|
+
if (!progress.toolName) {
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
ensureToolInputStart(state, controller, progress.toolName);
|
|
1242
|
+
const canonicalProgressInput = canonicalizeArgumentsProgressInput(progress);
|
|
1243
|
+
if (canonicalProgressInput !== void 0) {
|
|
1244
|
+
emitToolInputDelta(state, controller, canonicalProgressInput);
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
904
1247
|
function flushBuffer(state, controller, toolCallStart) {
|
|
905
1248
|
if (state.buffer.length === 0) {
|
|
906
1249
|
return;
|
|
@@ -931,44 +1274,77 @@ function closeTextBlock(state, controller) {
|
|
|
931
1274
|
state.hasEmittedTextStart = false;
|
|
932
1275
|
}
|
|
933
1276
|
}
|
|
934
|
-
function emitIncompleteToolCall(state, controller, toolCallStart) {
|
|
935
|
-
|
|
1277
|
+
function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer, options) {
|
|
1278
|
+
var _a;
|
|
1279
|
+
if (!state.currentToolCallJson && trailingBuffer.length === 0) {
|
|
1280
|
+
state.isInsideToolCall = false;
|
|
936
1281
|
return;
|
|
937
1282
|
}
|
|
1283
|
+
if (state.currentToolCallJson) {
|
|
1284
|
+
try {
|
|
1285
|
+
const parsedToolCall = parse(state.currentToolCallJson);
|
|
1286
|
+
emitToolCallFromParsed(state, controller, parsedToolCall);
|
|
1287
|
+
state.currentToolCallJson = "";
|
|
1288
|
+
state.isInsideToolCall = false;
|
|
1289
|
+
return;
|
|
1290
|
+
} catch (e) {
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
const rawToolCallContent = `${state.currentToolCallJson}${trailingBuffer}`;
|
|
1294
|
+
const errorContent = `${toolCallStart}${rawToolCallContent}`;
|
|
1295
|
+
const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
|
|
938
1296
|
logParseFailure({
|
|
939
1297
|
phase: "stream",
|
|
940
|
-
reason: "Incomplete streaming tool call segment emitted as text",
|
|
941
|
-
snippet:
|
|
942
|
-
});
|
|
943
|
-
const errorId = generateId();
|
|
944
|
-
const errorContent = `${toolCallStart}${state.currentToolCallJson}`;
|
|
945
|
-
controller.enqueue({
|
|
946
|
-
type: "text-start",
|
|
947
|
-
id: errorId
|
|
948
|
-
});
|
|
949
|
-
controller.enqueue({
|
|
950
|
-
type: "text-delta",
|
|
951
|
-
id: errorId,
|
|
952
|
-
delta: errorContent
|
|
953
|
-
});
|
|
954
|
-
controller.enqueue({
|
|
955
|
-
type: "text-end",
|
|
956
|
-
id: errorId
|
|
1298
|
+
reason: shouldEmitRawFallback ? "Incomplete streaming tool call segment emitted as text" : "Incomplete streaming tool call segment suppressed without raw text fallback",
|
|
1299
|
+
snippet: errorContent
|
|
957
1300
|
});
|
|
1301
|
+
if (shouldEmitRawFallback) {
|
|
1302
|
+
const errorId = generateId();
|
|
1303
|
+
controller.enqueue({
|
|
1304
|
+
type: "text-start",
|
|
1305
|
+
id: errorId
|
|
1306
|
+
});
|
|
1307
|
+
controller.enqueue({
|
|
1308
|
+
type: "text-delta",
|
|
1309
|
+
id: errorId,
|
|
1310
|
+
delta: errorContent
|
|
1311
|
+
});
|
|
1312
|
+
controller.enqueue({
|
|
1313
|
+
type: "text-end",
|
|
1314
|
+
id: errorId
|
|
1315
|
+
});
|
|
1316
|
+
}
|
|
1317
|
+
closeToolInput(state, controller);
|
|
1318
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1319
|
+
options,
|
|
1320
|
+
shouldEmitRawFallback ? "Could not complete streaming JSON tool call at finish; emitting original text." : "Could not complete streaming JSON tool call at finish.",
|
|
1321
|
+
{ toolCall: errorContent }
|
|
1322
|
+
);
|
|
958
1323
|
state.currentToolCallJson = "";
|
|
1324
|
+
state.isInsideToolCall = false;
|
|
959
1325
|
}
|
|
960
|
-
function handleFinishChunk(state, controller, toolCallStart, chunk) {
|
|
961
|
-
if (state.
|
|
1326
|
+
function handleFinishChunk(state, controller, toolCallStart, options, chunk) {
|
|
1327
|
+
if (state.isInsideToolCall) {
|
|
1328
|
+
const trailingBuffer = state.buffer;
|
|
1329
|
+
state.buffer = "";
|
|
1330
|
+
emitIncompleteToolCall(
|
|
1331
|
+
state,
|
|
1332
|
+
controller,
|
|
1333
|
+
toolCallStart,
|
|
1334
|
+
trailingBuffer,
|
|
1335
|
+
options
|
|
1336
|
+
);
|
|
1337
|
+
} else if (state.buffer.length > 0) {
|
|
962
1338
|
flushBuffer(state, controller, toolCallStart);
|
|
963
1339
|
}
|
|
964
1340
|
closeTextBlock(state, controller);
|
|
965
|
-
emitIncompleteToolCall(state, controller, toolCallStart);
|
|
966
1341
|
controller.enqueue(chunk);
|
|
967
1342
|
}
|
|
968
1343
|
function publishText(text, state, controller) {
|
|
969
1344
|
if (state.isInsideToolCall) {
|
|
970
1345
|
closeTextBlock(state, controller);
|
|
971
1346
|
state.currentToolCallJson += text;
|
|
1347
|
+
emitToolInputProgress(state, controller);
|
|
972
1348
|
} else if (text.length > 0) {
|
|
973
1349
|
if (!state.currentTextId) {
|
|
974
1350
|
state.currentTextId = generateId();
|
|
@@ -986,42 +1362,40 @@ function publishText(text, state, controller) {
|
|
|
986
1362
|
}
|
|
987
1363
|
}
|
|
988
1364
|
function emitToolCall(context) {
|
|
989
|
-
var _a
|
|
1365
|
+
var _a;
|
|
990
1366
|
const { state, controller, toolCallStart, toolCallEnd, options } = context;
|
|
991
1367
|
try {
|
|
992
1368
|
const parsedToolCall = parse(state.currentToolCallJson);
|
|
993
|
-
|
|
994
|
-
controller.enqueue({
|
|
995
|
-
type: "tool-call",
|
|
996
|
-
toolCallId: generateId(),
|
|
997
|
-
toolName: parsedToolCall.name,
|
|
998
|
-
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
999
|
-
});
|
|
1369
|
+
emitToolCallFromParsed(state, controller, parsedToolCall);
|
|
1000
1370
|
} catch (error) {
|
|
1371
|
+
const errorContent = `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`;
|
|
1372
|
+
const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
|
|
1001
1373
|
logParseFailure({
|
|
1002
1374
|
phase: "stream",
|
|
1003
1375
|
reason: "Failed to parse streaming tool call JSON segment",
|
|
1004
|
-
snippet:
|
|
1376
|
+
snippet: errorContent,
|
|
1005
1377
|
error
|
|
1006
1378
|
});
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1379
|
+
if (shouldEmitRawFallback) {
|
|
1380
|
+
const errorId = generateId();
|
|
1381
|
+
controller.enqueue({
|
|
1382
|
+
type: "text-start",
|
|
1383
|
+
id: errorId
|
|
1384
|
+
});
|
|
1385
|
+
controller.enqueue({
|
|
1386
|
+
type: "text-delta",
|
|
1387
|
+
id: errorId,
|
|
1388
|
+
delta: errorContent
|
|
1389
|
+
});
|
|
1390
|
+
controller.enqueue({
|
|
1391
|
+
type: "text-end",
|
|
1392
|
+
id: errorId
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
closeToolInput(state, controller);
|
|
1396
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1023
1397
|
options,
|
|
1024
|
-
"Could not process streaming JSON tool call; emitting original text.",
|
|
1398
|
+
shouldEmitRawFallback ? "Could not process streaming JSON tool call; emitting original text." : "Could not process streaming JSON tool call.",
|
|
1025
1399
|
{
|
|
1026
1400
|
toolCall: errorContent
|
|
1027
1401
|
}
|
|
@@ -1037,6 +1411,7 @@ function processTagMatch(context) {
|
|
|
1037
1411
|
} else {
|
|
1038
1412
|
state.currentToolCallJson = "";
|
|
1039
1413
|
state.isInsideToolCall = true;
|
|
1414
|
+
state.activeToolInput = null;
|
|
1040
1415
|
}
|
|
1041
1416
|
}
|
|
1042
1417
|
function processBufferTags(context) {
|
|
@@ -1059,8 +1434,16 @@ function processBufferTags(context) {
|
|
|
1059
1434
|
);
|
|
1060
1435
|
}
|
|
1061
1436
|
}
|
|
1062
|
-
function handlePartialTag(state, controller, toolCallStart) {
|
|
1437
|
+
function handlePartialTag(state, controller, toolCallStart, toolCallEnd) {
|
|
1063
1438
|
if (state.isInsideToolCall) {
|
|
1439
|
+
const potentialEndIndex = getPotentialStartIndex(state.buffer, toolCallEnd);
|
|
1440
|
+
if (potentialEndIndex != null && potentialEndIndex + toolCallEnd.length > state.buffer.length) {
|
|
1441
|
+
publishText(state.buffer.slice(0, potentialEndIndex), state, controller);
|
|
1442
|
+
state.buffer = state.buffer.slice(potentialEndIndex);
|
|
1443
|
+
} else {
|
|
1444
|
+
publishText(state.buffer, state, controller);
|
|
1445
|
+
state.buffer = "";
|
|
1446
|
+
}
|
|
1064
1447
|
return;
|
|
1065
1448
|
}
|
|
1066
1449
|
const potentialIndex = getPotentialStartIndex(state.buffer, toolCallStart);
|
|
@@ -1133,13 +1516,14 @@ var jsonProtocol = ({
|
|
|
1133
1516
|
buffer: "",
|
|
1134
1517
|
currentToolCallJson: "",
|
|
1135
1518
|
currentTextId: null,
|
|
1136
|
-
hasEmittedTextStart: false
|
|
1519
|
+
hasEmittedTextStart: false,
|
|
1520
|
+
activeToolInput: null
|
|
1137
1521
|
};
|
|
1138
1522
|
return new TransformStream({
|
|
1139
1523
|
transform(chunk, controller) {
|
|
1140
1524
|
var _a;
|
|
1141
1525
|
if (chunk.type === "finish") {
|
|
1142
|
-
handleFinishChunk(state, controller, toolCallStart, chunk);
|
|
1526
|
+
handleFinishChunk(state, controller, toolCallStart, options, chunk);
|
|
1143
1527
|
return;
|
|
1144
1528
|
}
|
|
1145
1529
|
if (chunk.type !== "text-delta") {
|
|
@@ -1155,7 +1539,7 @@ var jsonProtocol = ({
|
|
|
1155
1539
|
toolCallEnd,
|
|
1156
1540
|
options
|
|
1157
1541
|
});
|
|
1158
|
-
handlePartialTag(state, controller, toolCallStart);
|
|
1542
|
+
handlePartialTag(state, controller, toolCallStart, toolCallEnd);
|
|
1159
1543
|
}
|
|
1160
1544
|
});
|
|
1161
1545
|
},
|
|
@@ -4132,35 +4516,112 @@ function parse3(xml, schema, options = {}) {
|
|
|
4132
4516
|
var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
|
|
4133
4517
|
var WHITESPACE_REGEX5 = /\s/;
|
|
4134
4518
|
|
|
4135
|
-
// src/core/utils/
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4519
|
+
// src/core/utils/streamed-tool-input-delta.ts
|
|
4520
|
+
function emitDelta({
|
|
4521
|
+
controller,
|
|
4522
|
+
id,
|
|
4523
|
+
state,
|
|
4524
|
+
nextInput
|
|
4525
|
+
}) {
|
|
4526
|
+
if (!nextInput.startsWith(state.emittedInput)) {
|
|
4527
|
+
return false;
|
|
4141
4528
|
}
|
|
4142
|
-
const
|
|
4143
|
-
if (
|
|
4144
|
-
return
|
|
4529
|
+
const delta = nextInput.slice(state.emittedInput.length);
|
|
4530
|
+
if (delta.length === 0) {
|
|
4531
|
+
return false;
|
|
4145
4532
|
}
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4533
|
+
controller.enqueue({
|
|
4534
|
+
type: "tool-input-delta",
|
|
4535
|
+
id,
|
|
4536
|
+
delta
|
|
4537
|
+
});
|
|
4538
|
+
state.emittedInput = nextInput;
|
|
4539
|
+
return true;
|
|
4540
|
+
}
|
|
4541
|
+
function toIncompleteJsonPrefix(fullJson) {
|
|
4542
|
+
const trimmed = fullJson.trim();
|
|
4543
|
+
let prefix = trimmed;
|
|
4544
|
+
while (prefix.endsWith("}") || prefix.endsWith("]")) {
|
|
4545
|
+
prefix = prefix.slice(0, -1);
|
|
4149
4546
|
}
|
|
4150
|
-
|
|
4151
|
-
if (
|
|
4152
|
-
|
|
4547
|
+
prefix = prefix.trimEnd();
|
|
4548
|
+
if (prefix.endsWith('"')) {
|
|
4549
|
+
prefix = prefix.slice(0, -1);
|
|
4153
4550
|
}
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
}
|
|
4158
|
-
|
|
4551
|
+
if (prefix.length === 0) {
|
|
4552
|
+
if (trimmed.startsWith("[") || trimmed.startsWith("{")) {
|
|
4553
|
+
return trimmed.startsWith("{") ? "{" : "[";
|
|
4554
|
+
}
|
|
4555
|
+
if (trimmed.startsWith("]")) {
|
|
4556
|
+
return "[";
|
|
4557
|
+
}
|
|
4558
|
+
if (trimmed.startsWith("}")) {
|
|
4559
|
+
return "{";
|
|
4560
|
+
}
|
|
4561
|
+
if (trimmed.startsWith('"')) {
|
|
4562
|
+
return '"';
|
|
4563
|
+
}
|
|
4564
|
+
return "{";
|
|
4565
|
+
}
|
|
4566
|
+
return prefix;
|
|
4567
|
+
}
|
|
4568
|
+
function emitPrefixDelta(params) {
|
|
4569
|
+
return emitDelta({
|
|
4570
|
+
...params,
|
|
4571
|
+
nextInput: params.candidate
|
|
4572
|
+
});
|
|
4573
|
+
}
|
|
4574
|
+
function emitFinalRemainder(params) {
|
|
4575
|
+
var _a;
|
|
4576
|
+
const result = emitDelta({
|
|
4577
|
+
...params,
|
|
4578
|
+
nextInput: params.finalFullJson
|
|
4579
|
+
});
|
|
4580
|
+
if (!result && params.state.emittedInput.length > 0) {
|
|
4581
|
+
(_a = params.onMismatch) == null ? void 0 : _a.call(
|
|
4582
|
+
params,
|
|
4583
|
+
"Final JSON does not extend emitted tool-input prefix",
|
|
4584
|
+
{
|
|
4585
|
+
emittedLength: params.state.emittedInput.length,
|
|
4586
|
+
finalLength: params.finalFullJson.length
|
|
4587
|
+
}
|
|
4588
|
+
);
|
|
4589
|
+
}
|
|
4590
|
+
return result;
|
|
4591
|
+
}
|
|
4592
|
+
|
|
4593
|
+
// src/core/utils/xml-root-repair.ts
|
|
4594
|
+
var XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX = /^<([A-Za-z_][A-Za-z0-9_-]*)\s*\r?\n([\s\S]+?)\r?\n\s*\/>\s*$/;
|
|
4595
|
+
function tryRepairXmlSelfClosingRootWithBody(rawText, toolNames) {
|
|
4596
|
+
const trimmed = rawText.trim();
|
|
4597
|
+
if (trimmed.length === 0) {
|
|
4598
|
+
return null;
|
|
4599
|
+
}
|
|
4600
|
+
const match = trimmed.match(XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX);
|
|
4601
|
+
if (!match) {
|
|
4602
|
+
return null;
|
|
4603
|
+
}
|
|
4604
|
+
const rootTag = match[1];
|
|
4605
|
+
if (!toolNames.includes(rootTag)) {
|
|
4606
|
+
return null;
|
|
4607
|
+
}
|
|
4608
|
+
const body = match[2].trimEnd();
|
|
4609
|
+
if (body.trim().length === 0 || body.includes(`</${rootTag}>`)) {
|
|
4610
|
+
return null;
|
|
4611
|
+
}
|
|
4612
|
+
return `<${rootTag}>
|
|
4613
|
+
${body}
|
|
4614
|
+
</${rootTag}>`;
|
|
4615
|
+
}
|
|
4616
|
+
|
|
4159
4617
|
// src/core/protocols/xml-protocol.ts
|
|
4160
4618
|
function getToolSchema(tools, toolName) {
|
|
4161
4619
|
var _a;
|
|
4162
4620
|
return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
4163
4621
|
}
|
|
4622
|
+
function shouldEmitRawToolCallTextOnError2(options) {
|
|
4623
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
4624
|
+
}
|
|
4164
4625
|
function processToolCall(params) {
|
|
4165
4626
|
var _a, _b;
|
|
4166
4627
|
const { toolCall, tools, options, text, processedElements, parseOptions } = params;
|
|
@@ -4173,7 +4634,7 @@ function processToolCall(params) {
|
|
|
4173
4634
|
const parsed = parse3(toolCall.content, toolSchema, parseConfig);
|
|
4174
4635
|
processedElements.push({
|
|
4175
4636
|
type: "tool-call",
|
|
4176
|
-
toolCallId:
|
|
4637
|
+
toolCallId: generateToolCallId(),
|
|
4177
4638
|
toolName: toolCall.toolName,
|
|
4178
4639
|
input: JSON.stringify(parsed)
|
|
4179
4640
|
});
|
|
@@ -4190,6 +4651,299 @@ function processToolCall(params) {
|
|
|
4190
4651
|
processedElements.push({ type: "text", text: originalCallText });
|
|
4191
4652
|
}
|
|
4192
4653
|
}
|
|
4654
|
+
function parseXmlTagName(rawTagBody) {
|
|
4655
|
+
let index = 0;
|
|
4656
|
+
while (index < rawTagBody.length && WHITESPACE_REGEX5.test(rawTagBody[index])) {
|
|
4657
|
+
index += 1;
|
|
4658
|
+
}
|
|
4659
|
+
const nameStart = index;
|
|
4660
|
+
while (index < rawTagBody.length && NAME_CHAR_RE2.test(rawTagBody.charAt(index))) {
|
|
4661
|
+
index += 1;
|
|
4662
|
+
}
|
|
4663
|
+
return rawTagBody.slice(nameStart, index);
|
|
4664
|
+
}
|
|
4665
|
+
function consumeXmlSpecialSection(fragment, ltIndex) {
|
|
4666
|
+
if (fragment.startsWith("<!--", ltIndex)) {
|
|
4667
|
+
const commentEnd = fragment.indexOf("-->", ltIndex + 4);
|
|
4668
|
+
return commentEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: commentEnd + 3 };
|
|
4669
|
+
}
|
|
4670
|
+
if (fragment.startsWith("<![CDATA[", ltIndex)) {
|
|
4671
|
+
const cdataEnd = fragment.indexOf("]]>", ltIndex + 9);
|
|
4672
|
+
return cdataEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: cdataEnd + 3 };
|
|
4673
|
+
}
|
|
4674
|
+
if (fragment.startsWith("<?", ltIndex)) {
|
|
4675
|
+
const processingEnd = fragment.indexOf("?>", ltIndex + 2);
|
|
4676
|
+
return processingEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: processingEnd + 2 };
|
|
4677
|
+
}
|
|
4678
|
+
if (fragment.startsWith("<!", ltIndex)) {
|
|
4679
|
+
const declarationEnd = fragment.indexOf(">", ltIndex + 2);
|
|
4680
|
+
return declarationEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: declarationEnd + 1 };
|
|
4681
|
+
}
|
|
4682
|
+
return { kind: "none" };
|
|
4683
|
+
}
|
|
4684
|
+
function parseXmlTagToken(fragment, ltIndex) {
|
|
4685
|
+
const gtIndex = fragment.indexOf(">", ltIndex + 1);
|
|
4686
|
+
if (gtIndex === -1) {
|
|
4687
|
+
return null;
|
|
4688
|
+
}
|
|
4689
|
+
const tagBody = fragment.slice(ltIndex + 1, gtIndex).trim();
|
|
4690
|
+
if (tagBody.length === 0) {
|
|
4691
|
+
return null;
|
|
4692
|
+
}
|
|
4693
|
+
if (tagBody.startsWith("/")) {
|
|
4694
|
+
const closeName = parseXmlTagName(tagBody.slice(1));
|
|
4695
|
+
if (closeName.length === 0) {
|
|
4696
|
+
return null;
|
|
4697
|
+
}
|
|
4698
|
+
return { kind: "close", name: closeName, nextPos: gtIndex + 1 };
|
|
4699
|
+
}
|
|
4700
|
+
const selfClosing = tagBody.endsWith("/");
|
|
4701
|
+
const openBody = selfClosing ? tagBody.slice(0, -1).trimEnd() : tagBody;
|
|
4702
|
+
const openName = parseXmlTagName(openBody);
|
|
4703
|
+
if (openName.length === 0) {
|
|
4704
|
+
return null;
|
|
4705
|
+
}
|
|
4706
|
+
return {
|
|
4707
|
+
kind: "open",
|
|
4708
|
+
name: openName,
|
|
4709
|
+
selfClosing,
|
|
4710
|
+
nextPos: gtIndex + 1
|
|
4711
|
+
};
|
|
4712
|
+
}
|
|
4713
|
+
function analyzeXmlFragmentForProgress(fragment) {
|
|
4714
|
+
const stack = [];
|
|
4715
|
+
const topLevelTagNames = [];
|
|
4716
|
+
let position = 0;
|
|
4717
|
+
while (position < fragment.length) {
|
|
4718
|
+
const ltIndex = fragment.indexOf("<", position);
|
|
4719
|
+
if (ltIndex === -1) {
|
|
4720
|
+
break;
|
|
4721
|
+
}
|
|
4722
|
+
const special = consumeXmlSpecialSection(fragment, ltIndex);
|
|
4723
|
+
if (special.kind === "incomplete") {
|
|
4724
|
+
return null;
|
|
4725
|
+
}
|
|
4726
|
+
if (special.kind === "consumed") {
|
|
4727
|
+
position = special.nextPos;
|
|
4728
|
+
continue;
|
|
4729
|
+
}
|
|
4730
|
+
const token = parseXmlTagToken(fragment, ltIndex);
|
|
4731
|
+
if (token === null) {
|
|
4732
|
+
return null;
|
|
4733
|
+
}
|
|
4734
|
+
if (token.kind === "close") {
|
|
4735
|
+
const openName = stack.pop();
|
|
4736
|
+
if (!openName || openName !== token.name) {
|
|
4737
|
+
return null;
|
|
4738
|
+
}
|
|
4739
|
+
position = token.nextPos;
|
|
4740
|
+
continue;
|
|
4741
|
+
}
|
|
4742
|
+
if (stack.length === 0) {
|
|
4743
|
+
topLevelTagNames.push(token.name);
|
|
4744
|
+
}
|
|
4745
|
+
if (!token.selfClosing) {
|
|
4746
|
+
stack.push(token.name);
|
|
4747
|
+
}
|
|
4748
|
+
position = token.nextPos;
|
|
4749
|
+
}
|
|
4750
|
+
if (stack.length > 0) {
|
|
4751
|
+
return null;
|
|
4752
|
+
}
|
|
4753
|
+
return { topLevelTagNames };
|
|
4754
|
+
}
|
|
4755
|
+
function scanXmlFragmentTopLevelTextStep(options) {
|
|
4756
|
+
const { fragment, position, stack } = options;
|
|
4757
|
+
const ltIndex = fragment.indexOf("<", position);
|
|
4758
|
+
if (ltIndex === -1) {
|
|
4759
|
+
const trailingText = fragment.slice(position);
|
|
4760
|
+
return {
|
|
4761
|
+
kind: "done",
|
|
4762
|
+
value: stack.length === 0 && trailingText.trim().length > 0
|
|
4763
|
+
};
|
|
4764
|
+
}
|
|
4765
|
+
const textBetweenTags = fragment.slice(position, ltIndex);
|
|
4766
|
+
if (stack.length === 0 && textBetweenTags.trim().length > 0) {
|
|
4767
|
+
return { kind: "found" };
|
|
4768
|
+
}
|
|
4769
|
+
const special = consumeXmlSpecialSection(fragment, ltIndex);
|
|
4770
|
+
if (special.kind === "incomplete") {
|
|
4771
|
+
return { kind: "invalid" };
|
|
4772
|
+
}
|
|
4773
|
+
if (special.kind === "consumed") {
|
|
4774
|
+
return { kind: "next", nextPos: special.nextPos };
|
|
4775
|
+
}
|
|
4776
|
+
const token = parseXmlTagToken(fragment, ltIndex);
|
|
4777
|
+
if (token === null) {
|
|
4778
|
+
return { kind: "invalid" };
|
|
4779
|
+
}
|
|
4780
|
+
if (token.kind === "close") {
|
|
4781
|
+
const openName = stack.pop();
|
|
4782
|
+
if (!openName || openName !== token.name) {
|
|
4783
|
+
return { kind: "invalid" };
|
|
4784
|
+
}
|
|
4785
|
+
} else if (!token.selfClosing) {
|
|
4786
|
+
stack.push(token.name);
|
|
4787
|
+
}
|
|
4788
|
+
return { kind: "next", nextPos: token.nextPos };
|
|
4789
|
+
}
|
|
4790
|
+
function hasNonWhitespaceTopLevelText(fragment) {
|
|
4791
|
+
if (!fragment.includes("<")) {
|
|
4792
|
+
return fragment.trim().length > 0;
|
|
4793
|
+
}
|
|
4794
|
+
const stack = [];
|
|
4795
|
+
let position = 0;
|
|
4796
|
+
while (position < fragment.length) {
|
|
4797
|
+
const step = scanXmlFragmentTopLevelTextStep({ fragment, position, stack });
|
|
4798
|
+
if (step.kind === "found") {
|
|
4799
|
+
return true;
|
|
4800
|
+
}
|
|
4801
|
+
if (step.kind === "invalid") {
|
|
4802
|
+
return false;
|
|
4803
|
+
}
|
|
4804
|
+
if (step.kind === "done") {
|
|
4805
|
+
return step.value;
|
|
4806
|
+
}
|
|
4807
|
+
position = step.nextPos;
|
|
4808
|
+
}
|
|
4809
|
+
return false;
|
|
4810
|
+
}
|
|
4811
|
+
function getObjectSchemaPropertyNames(schema) {
|
|
4812
|
+
if (!schema || typeof schema !== "object") {
|
|
4813
|
+
return null;
|
|
4814
|
+
}
|
|
4815
|
+
const schemaObject = schema;
|
|
4816
|
+
const typeValue = schemaObject.type;
|
|
4817
|
+
if (typeValue != null) {
|
|
4818
|
+
const isObjectType = typeValue === "object" || Array.isArray(typeValue) && typeValue.includes("object");
|
|
4819
|
+
if (!isObjectType) {
|
|
4820
|
+
return null;
|
|
4821
|
+
}
|
|
4822
|
+
}
|
|
4823
|
+
if (!schemaObject.properties || typeof schemaObject.properties !== "object") {
|
|
4824
|
+
return /* @__PURE__ */ new Set();
|
|
4825
|
+
}
|
|
4826
|
+
return new Set(
|
|
4827
|
+
Object.keys(schemaObject.properties)
|
|
4828
|
+
);
|
|
4829
|
+
}
|
|
4830
|
+
function schemaAllowsArrayType(schema) {
|
|
4831
|
+
if (!schema || typeof schema !== "object") {
|
|
4832
|
+
return false;
|
|
4833
|
+
}
|
|
4834
|
+
const schemaRecord = schema;
|
|
4835
|
+
const typeValue = schemaRecord.type;
|
|
4836
|
+
if (typeValue === "array") {
|
|
4837
|
+
return true;
|
|
4838
|
+
}
|
|
4839
|
+
if (Array.isArray(typeValue) && typeValue.includes("array")) {
|
|
4840
|
+
return true;
|
|
4841
|
+
}
|
|
4842
|
+
const unions = [schemaRecord.anyOf, schemaRecord.oneOf, schemaRecord.allOf];
|
|
4843
|
+
for (const union of unions) {
|
|
4844
|
+
if (!Array.isArray(union)) {
|
|
4845
|
+
continue;
|
|
4846
|
+
}
|
|
4847
|
+
if (union.some((entry) => schemaAllowsArrayType(entry))) {
|
|
4848
|
+
return true;
|
|
4849
|
+
}
|
|
4850
|
+
}
|
|
4851
|
+
return false;
|
|
4852
|
+
}
|
|
4853
|
+
function getSchemaObjectProperty(schema, propertyName) {
|
|
4854
|
+
if (!schema || typeof schema !== "object") {
|
|
4855
|
+
return null;
|
|
4856
|
+
}
|
|
4857
|
+
const schemaObject = schema;
|
|
4858
|
+
const properties = schemaObject.properties;
|
|
4859
|
+
if (!properties || typeof properties !== "object") {
|
|
4860
|
+
return null;
|
|
4861
|
+
}
|
|
4862
|
+
const property = properties[propertyName];
|
|
4863
|
+
if (!property) {
|
|
4864
|
+
return null;
|
|
4865
|
+
}
|
|
4866
|
+
return property;
|
|
4867
|
+
}
|
|
4868
|
+
function isStableXmlProgressCandidate(options) {
|
|
4869
|
+
const { candidate, parsed, toolSchema } = options;
|
|
4870
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4871
|
+
return false;
|
|
4872
|
+
}
|
|
4873
|
+
const structure = analyzeXmlFragmentForProgress(candidate);
|
|
4874
|
+
if (!structure) {
|
|
4875
|
+
return false;
|
|
4876
|
+
}
|
|
4877
|
+
const schemaProperties = getObjectSchemaPropertyNames(toolSchema);
|
|
4878
|
+
if (!schemaProperties || schemaProperties.size === 0) {
|
|
4879
|
+
return false;
|
|
4880
|
+
}
|
|
4881
|
+
const parsedObject = parsed;
|
|
4882
|
+
const uniqueTopLevelTags = new Set(structure.topLevelTagNames);
|
|
4883
|
+
for (const tagName of uniqueTopLevelTags) {
|
|
4884
|
+
if (!schemaProperties.has(tagName)) {
|
|
4885
|
+
continue;
|
|
4886
|
+
}
|
|
4887
|
+
const schemaProperty = getSchemaObjectProperty(toolSchema, tagName);
|
|
4888
|
+
if (schemaProperty && schemaAllowsArrayType(schemaProperty) && !Array.isArray(parsedObject[tagName])) {
|
|
4889
|
+
return false;
|
|
4890
|
+
}
|
|
4891
|
+
}
|
|
4892
|
+
if (structure.topLevelTagNames.length === 1) {
|
|
4893
|
+
const onlyTopLevelTag = structure.topLevelTagNames[0];
|
|
4894
|
+
if (!schemaProperties || schemaProperties.size === 0 || !schemaProperties.has(onlyTopLevelTag)) {
|
|
4895
|
+
return false;
|
|
4896
|
+
}
|
|
4897
|
+
}
|
|
4898
|
+
return true;
|
|
4899
|
+
}
|
|
4900
|
+
function parseXmlContentForStreamProgress({
|
|
4901
|
+
toolContent,
|
|
4902
|
+
toolSchema,
|
|
4903
|
+
parseOptions
|
|
4904
|
+
}) {
|
|
4905
|
+
const tryParse = (content) => {
|
|
4906
|
+
try {
|
|
4907
|
+
return parse3(content, toolSchema, {
|
|
4908
|
+
...parseOptions != null ? parseOptions : {},
|
|
4909
|
+
repair: false,
|
|
4910
|
+
onError: void 0
|
|
4911
|
+
});
|
|
4912
|
+
} catch (e) {
|
|
4913
|
+
return null;
|
|
4914
|
+
}
|
|
4915
|
+
};
|
|
4916
|
+
const strictFull = tryParse(toolContent);
|
|
4917
|
+
if (strictFull !== null && isStableXmlProgressCandidate({
|
|
4918
|
+
candidate: toolContent,
|
|
4919
|
+
parsed: strictFull,
|
|
4920
|
+
toolSchema
|
|
4921
|
+
})) {
|
|
4922
|
+
return JSON.stringify(strictFull);
|
|
4923
|
+
}
|
|
4924
|
+
let searchEnd = toolContent.length;
|
|
4925
|
+
while (searchEnd > 0) {
|
|
4926
|
+
const gtIndex = toolContent.lastIndexOf(">", searchEnd - 1);
|
|
4927
|
+
if (gtIndex === -1) {
|
|
4928
|
+
break;
|
|
4929
|
+
}
|
|
4930
|
+
const candidate = toolContent.slice(0, gtIndex + 1);
|
|
4931
|
+
if (!analyzeXmlFragmentForProgress(candidate)) {
|
|
4932
|
+
searchEnd = gtIndex;
|
|
4933
|
+
continue;
|
|
4934
|
+
}
|
|
4935
|
+
const parsedCandidate = tryParse(candidate);
|
|
4936
|
+
if (parsedCandidate !== null && isStableXmlProgressCandidate({
|
|
4937
|
+
candidate,
|
|
4938
|
+
parsed: parsedCandidate,
|
|
4939
|
+
toolSchema
|
|
4940
|
+
})) {
|
|
4941
|
+
return JSON.stringify(parsedCandidate);
|
|
4942
|
+
}
|
|
4943
|
+
searchEnd = gtIndex;
|
|
4944
|
+
}
|
|
4945
|
+
return null;
|
|
4946
|
+
}
|
|
4193
4947
|
function handleStreamingToolCallEnd(params) {
|
|
4194
4948
|
var _a, _b;
|
|
4195
4949
|
const {
|
|
@@ -4209,19 +4963,37 @@ function handleStreamingToolCallEnd(params) {
|
|
|
4209
4963
|
flushText(ctrl);
|
|
4210
4964
|
try {
|
|
4211
4965
|
const parsedResult = parse3(toolContent, toolSchema, parseConfig);
|
|
4966
|
+
const finalInput = JSON.stringify(parsedResult);
|
|
4967
|
+
emitFinalRemainder({
|
|
4968
|
+
controller: ctrl,
|
|
4969
|
+
id: currentToolCall.toolCallId,
|
|
4970
|
+
state: currentToolCall,
|
|
4971
|
+
finalFullJson: finalInput,
|
|
4972
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
4973
|
+
});
|
|
4974
|
+
ctrl.enqueue({
|
|
4975
|
+
type: "tool-input-end",
|
|
4976
|
+
id: currentToolCall.toolCallId
|
|
4977
|
+
});
|
|
4212
4978
|
ctrl.enqueue({
|
|
4213
4979
|
type: "tool-call",
|
|
4214
|
-
toolCallId:
|
|
4980
|
+
toolCallId: currentToolCall.toolCallId,
|
|
4215
4981
|
toolName: currentToolCall.name,
|
|
4216
|
-
input:
|
|
4982
|
+
input: finalInput
|
|
4217
4983
|
});
|
|
4218
4984
|
} catch (error) {
|
|
4985
|
+
ctrl.enqueue({
|
|
4986
|
+
type: "tool-input-end",
|
|
4987
|
+
id: currentToolCall.toolCallId
|
|
4988
|
+
});
|
|
4219
4989
|
const original = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
|
|
4220
4990
|
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
|
|
4221
4991
|
toolCall: original,
|
|
4222
4992
|
error
|
|
4223
4993
|
});
|
|
4224
|
-
|
|
4994
|
+
if (shouldEmitRawToolCallTextOnError2(options)) {
|
|
4995
|
+
flushText(ctrl, original);
|
|
4996
|
+
}
|
|
4225
4997
|
}
|
|
4226
4998
|
}
|
|
4227
4999
|
function findClosingTagEndFlexible(text, contentStart, toolName) {
|
|
@@ -4643,38 +5415,6 @@ function findPotentialToolTagStart(buffer, toolNames) {
|
|
|
4643
5415
|
}
|
|
4644
5416
|
return -1;
|
|
4645
5417
|
}
|
|
4646
|
-
function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
4647
|
-
return (controller, text) => {
|
|
4648
|
-
const content = text;
|
|
4649
|
-
if (content) {
|
|
4650
|
-
if (!getCurrentTextId()) {
|
|
4651
|
-
const newId = generateId();
|
|
4652
|
-
setCurrentTextId(newId);
|
|
4653
|
-
controller.enqueue({
|
|
4654
|
-
type: "text-start",
|
|
4655
|
-
id: newId
|
|
4656
|
-
});
|
|
4657
|
-
setHasEmittedTextStart(true);
|
|
4658
|
-
}
|
|
4659
|
-
controller.enqueue({
|
|
4660
|
-
type: "text-delta",
|
|
4661
|
-
id: getCurrentTextId(),
|
|
4662
|
-
delta: content
|
|
4663
|
-
});
|
|
4664
|
-
}
|
|
4665
|
-
const currentTextId = getCurrentTextId();
|
|
4666
|
-
if (currentTextId && !text) {
|
|
4667
|
-
if (getHasEmittedTextStart()) {
|
|
4668
|
-
controller.enqueue({
|
|
4669
|
-
type: "text-end",
|
|
4670
|
-
id: currentTextId
|
|
4671
|
-
});
|
|
4672
|
-
setHasEmittedTextStart(false);
|
|
4673
|
-
}
|
|
4674
|
-
setCurrentTextId(null);
|
|
4675
|
-
}
|
|
4676
|
-
};
|
|
4677
|
-
}
|
|
4678
5418
|
function processToolCallInBuffer(params) {
|
|
4679
5419
|
const {
|
|
4680
5420
|
buffer,
|
|
@@ -4684,18 +5424,21 @@ function processToolCallInBuffer(params) {
|
|
|
4684
5424
|
controller,
|
|
4685
5425
|
flushText,
|
|
4686
5426
|
setBuffer,
|
|
4687
|
-
parseOptions
|
|
5427
|
+
parseOptions,
|
|
5428
|
+
emitToolInputProgress: emitToolInputProgress2
|
|
4688
5429
|
} = params;
|
|
4689
5430
|
const endTagPattern = new RegExp(
|
|
4690
5431
|
`</\\s*${escapeRegExp(currentToolCall.name)}\\s*>`
|
|
4691
5432
|
);
|
|
4692
5433
|
const endMatch = endTagPattern.exec(buffer);
|
|
4693
5434
|
if (!endMatch || endMatch.index === void 0) {
|
|
5435
|
+
emitToolInputProgress2(controller, currentToolCall, buffer);
|
|
4694
5436
|
return { buffer, currentToolCall, shouldBreak: true };
|
|
4695
5437
|
}
|
|
4696
5438
|
const endIdx = endMatch.index;
|
|
4697
5439
|
const endPos = endIdx + endMatch[0].length;
|
|
4698
5440
|
const content = buffer.substring(0, endIdx);
|
|
5441
|
+
emitToolInputProgress2(controller, currentToolCall, content);
|
|
4699
5442
|
const remainder = buffer.substring(endPos);
|
|
4700
5443
|
setBuffer(remainder);
|
|
4701
5444
|
handleStreamingToolCallEnd({
|
|
@@ -4722,7 +5465,8 @@ function processNoToolCallInBuffer(params) {
|
|
|
4722
5465
|
tools,
|
|
4723
5466
|
options,
|
|
4724
5467
|
parseOptions,
|
|
4725
|
-
setBuffer
|
|
5468
|
+
setBuffer,
|
|
5469
|
+
emitToolInputStart
|
|
4726
5470
|
} = params;
|
|
4727
5471
|
const {
|
|
4728
5472
|
index: earliestStartTagIndex,
|
|
@@ -4752,9 +5496,10 @@ function processNoToolCallInBuffer(params) {
|
|
|
4752
5496
|
if (selfClosing) {
|
|
4753
5497
|
const newBuffer2 = buffer.substring(earliestStartTagIndex + tagLength);
|
|
4754
5498
|
setBuffer(newBuffer2);
|
|
5499
|
+
const currentToolCall = emitToolInputStart(controller, earliestToolName);
|
|
4755
5500
|
handleStreamingToolCallEnd({
|
|
4756
5501
|
toolContent: "",
|
|
4757
|
-
currentToolCall
|
|
5502
|
+
currentToolCall,
|
|
4758
5503
|
tools,
|
|
4759
5504
|
options,
|
|
4760
5505
|
ctrl: controller,
|
|
@@ -4773,12 +5518,12 @@ function processNoToolCallInBuffer(params) {
|
|
|
4773
5518
|
setBuffer(newBuffer);
|
|
4774
5519
|
return {
|
|
4775
5520
|
buffer: newBuffer,
|
|
4776
|
-
currentToolCall:
|
|
5521
|
+
currentToolCall: emitToolInputStart(controller, earliestToolName),
|
|
4777
5522
|
shouldBreak: false,
|
|
4778
5523
|
shouldContinue: true
|
|
4779
5524
|
};
|
|
4780
5525
|
}
|
|
4781
|
-
function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions) {
|
|
5526
|
+
function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions, emitToolInputProgress2, emitToolInputStart) {
|
|
4782
5527
|
return (controller) => {
|
|
4783
5528
|
while (true) {
|
|
4784
5529
|
const currentToolCall = getCurrentToolCall();
|
|
@@ -4791,7 +5536,8 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
4791
5536
|
controller,
|
|
4792
5537
|
flushText,
|
|
4793
5538
|
setBuffer,
|
|
4794
|
-
parseOptions
|
|
5539
|
+
parseOptions,
|
|
5540
|
+
emitToolInputProgress: emitToolInputProgress2
|
|
4795
5541
|
});
|
|
4796
5542
|
setBuffer(result.buffer);
|
|
4797
5543
|
setCurrentToolCall(result.currentToolCall);
|
|
@@ -4807,7 +5553,8 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
4807
5553
|
tools,
|
|
4808
5554
|
options,
|
|
4809
5555
|
parseOptions,
|
|
4810
|
-
setBuffer
|
|
5556
|
+
setBuffer,
|
|
5557
|
+
emitToolInputStart
|
|
4811
5558
|
});
|
|
4812
5559
|
setBuffer(result.buffer);
|
|
4813
5560
|
setCurrentToolCall(result.currentToolCall);
|
|
@@ -4921,6 +5668,118 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4921
5668
|
hasEmittedTextStart = value;
|
|
4922
5669
|
}
|
|
4923
5670
|
);
|
|
5671
|
+
const emitToolInputStart = (controller, toolName) => {
|
|
5672
|
+
flushText(controller);
|
|
5673
|
+
const next = {
|
|
5674
|
+
name: toolName,
|
|
5675
|
+
toolCallId: generateToolCallId(),
|
|
5676
|
+
emittedInput: "",
|
|
5677
|
+
lastProgressGtIndex: null,
|
|
5678
|
+
lastProgressFullInput: null
|
|
5679
|
+
};
|
|
5680
|
+
controller.enqueue({
|
|
5681
|
+
type: "tool-input-start",
|
|
5682
|
+
id: next.toolCallId,
|
|
5683
|
+
toolName
|
|
5684
|
+
});
|
|
5685
|
+
return next;
|
|
5686
|
+
};
|
|
5687
|
+
const emitToolInputProgress2 = (controller, toolCall, toolContent) => {
|
|
5688
|
+
const progressGtIndex = toolContent.lastIndexOf(">");
|
|
5689
|
+
if (toolCall.lastProgressGtIndex === progressGtIndex) {
|
|
5690
|
+
const cached = toolCall.lastProgressFullInput;
|
|
5691
|
+
if (cached == null) {
|
|
5692
|
+
return;
|
|
5693
|
+
}
|
|
5694
|
+
if (cached === "{}" && toolContent.trim().length === 0) {
|
|
5695
|
+
return;
|
|
5696
|
+
}
|
|
5697
|
+
const prefixCandidate2 = toIncompleteJsonPrefix(cached);
|
|
5698
|
+
emitPrefixDelta({
|
|
5699
|
+
controller,
|
|
5700
|
+
id: toolCall.toolCallId,
|
|
5701
|
+
state: toolCall,
|
|
5702
|
+
candidate: prefixCandidate2
|
|
5703
|
+
});
|
|
5704
|
+
return;
|
|
5705
|
+
}
|
|
5706
|
+
const toolSchema = getToolSchema(tools, toolCall.name);
|
|
5707
|
+
const fullInput = parseXmlContentForStreamProgress({
|
|
5708
|
+
toolContent,
|
|
5709
|
+
toolSchema,
|
|
5710
|
+
parseOptions
|
|
5711
|
+
});
|
|
5712
|
+
toolCall.lastProgressGtIndex = progressGtIndex;
|
|
5713
|
+
toolCall.lastProgressFullInput = fullInput;
|
|
5714
|
+
if (fullInput == null) {
|
|
5715
|
+
return;
|
|
5716
|
+
}
|
|
5717
|
+
if (fullInput === "{}" && toolContent.trim().length === 0) {
|
|
5718
|
+
return;
|
|
5719
|
+
}
|
|
5720
|
+
const prefixCandidate = toIncompleteJsonPrefix(fullInput);
|
|
5721
|
+
emitPrefixDelta({
|
|
5722
|
+
controller,
|
|
5723
|
+
id: toolCall.toolCallId,
|
|
5724
|
+
state: toolCall,
|
|
5725
|
+
candidate: prefixCandidate
|
|
5726
|
+
});
|
|
5727
|
+
};
|
|
5728
|
+
const finalizeUnclosedToolCall = (controller) => {
|
|
5729
|
+
var _a2, _b;
|
|
5730
|
+
if (!currentToolCall) {
|
|
5731
|
+
return;
|
|
5732
|
+
}
|
|
5733
|
+
emitToolInputProgress2(controller, currentToolCall, buffer);
|
|
5734
|
+
const parseConfig = {
|
|
5735
|
+
...parseOptions,
|
|
5736
|
+
onError: (_a2 = options == null ? void 0 : options.onError) != null ? _a2 : parseOptions == null ? void 0 : parseOptions.onError
|
|
5737
|
+
};
|
|
5738
|
+
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
5739
|
+
flushText(controller);
|
|
5740
|
+
try {
|
|
5741
|
+
if (hasNonWhitespaceTopLevelText(buffer)) {
|
|
5742
|
+
throw new Error(
|
|
5743
|
+
"Cannot reconcile unclosed XML tool call with top-level plain text."
|
|
5744
|
+
);
|
|
5745
|
+
}
|
|
5746
|
+
const parsedResult = parse3(buffer, toolSchema, parseConfig);
|
|
5747
|
+
const finalInput = JSON.stringify(parsedResult);
|
|
5748
|
+
emitFinalRemainder({
|
|
5749
|
+
controller,
|
|
5750
|
+
id: currentToolCall.toolCallId,
|
|
5751
|
+
state: currentToolCall,
|
|
5752
|
+
finalFullJson: finalInput,
|
|
5753
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
5754
|
+
});
|
|
5755
|
+
controller.enqueue({
|
|
5756
|
+
type: "tool-input-end",
|
|
5757
|
+
id: currentToolCall.toolCallId
|
|
5758
|
+
});
|
|
5759
|
+
controller.enqueue({
|
|
5760
|
+
type: "tool-call",
|
|
5761
|
+
toolCallId: currentToolCall.toolCallId,
|
|
5762
|
+
toolName: currentToolCall.name,
|
|
5763
|
+
input: finalInput
|
|
5764
|
+
});
|
|
5765
|
+
} catch (error) {
|
|
5766
|
+
controller.enqueue({
|
|
5767
|
+
type: "tool-input-end",
|
|
5768
|
+
id: currentToolCall.toolCallId
|
|
5769
|
+
});
|
|
5770
|
+
const unfinishedContent = `<${currentToolCall.name}>${buffer}`;
|
|
5771
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
5772
|
+
options,
|
|
5773
|
+
"Could not complete streaming XML tool call at finish.",
|
|
5774
|
+
{ toolCall: unfinishedContent, error }
|
|
5775
|
+
);
|
|
5776
|
+
if (shouldEmitRawToolCallTextOnError2(options)) {
|
|
5777
|
+
flushText(controller, unfinishedContent);
|
|
5778
|
+
}
|
|
5779
|
+
}
|
|
5780
|
+
buffer = "";
|
|
5781
|
+
currentToolCall = null;
|
|
5782
|
+
};
|
|
4924
5783
|
const processBuffer = createProcessBufferHandler(
|
|
4925
5784
|
() => buffer,
|
|
4926
5785
|
(newBuffer) => {
|
|
@@ -4934,17 +5793,17 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4934
5793
|
options,
|
|
4935
5794
|
toolNames,
|
|
4936
5795
|
flushText,
|
|
4937
|
-
parseOptions
|
|
5796
|
+
parseOptions,
|
|
5797
|
+
emitToolInputProgress2,
|
|
5798
|
+
emitToolInputStart
|
|
4938
5799
|
);
|
|
4939
5800
|
return new TransformStream({
|
|
5801
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Stateful stream parsing requires branching over chunk lifecycle and parser states.
|
|
4940
5802
|
transform(chunk, controller) {
|
|
4941
5803
|
var _a2;
|
|
4942
5804
|
if (chunk.type === "finish") {
|
|
4943
5805
|
if (currentToolCall) {
|
|
4944
|
-
|
|
4945
|
-
flushText(controller, unfinishedContent);
|
|
4946
|
-
buffer = "";
|
|
4947
|
-
currentToolCall = null;
|
|
5806
|
+
finalizeUnclosedToolCall(controller);
|
|
4948
5807
|
} else if (buffer) {
|
|
4949
5808
|
flushText(controller, buffer);
|
|
4950
5809
|
buffer = "";
|
|
@@ -4954,7 +5813,8 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4954
5813
|
return;
|
|
4955
5814
|
}
|
|
4956
5815
|
if (chunk.type !== "text-delta") {
|
|
4957
|
-
if (
|
|
5816
|
+
if (currentToolCall) {
|
|
5817
|
+
} else if (buffer) {
|
|
4958
5818
|
flushText(controller, buffer);
|
|
4959
5819
|
buffer = "";
|
|
4960
5820
|
}
|
|
@@ -4967,10 +5827,7 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4967
5827
|
},
|
|
4968
5828
|
flush(controller) {
|
|
4969
5829
|
if (currentToolCall) {
|
|
4970
|
-
|
|
4971
|
-
flushText(controller, unfinishedContent);
|
|
4972
|
-
buffer = "";
|
|
4973
|
-
currentToolCall = null;
|
|
5830
|
+
finalizeUnclosedToolCall(controller);
|
|
4974
5831
|
} else if (buffer) {
|
|
4975
5832
|
flushText(controller, buffer);
|
|
4976
5833
|
buffer = "";
|
|
@@ -4998,7 +5855,205 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4998
5855
|
|
|
4999
5856
|
// src/core/protocols/yaml-protocol.ts
|
|
5000
5857
|
var import_yaml = __toESM(require("yaml"), 1);
|
|
5858
|
+
function shouldEmitRawToolCallTextOnError3(options) {
|
|
5859
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
5860
|
+
}
|
|
5861
|
+
var selfClosingTagCache2 = /* @__PURE__ */ new Map();
|
|
5862
|
+
function getSelfClosingTagPattern2(toolName) {
|
|
5863
|
+
let pattern = selfClosingTagCache2.get(toolName);
|
|
5864
|
+
if (!pattern) {
|
|
5865
|
+
pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
|
|
5866
|
+
selfClosingTagCache2.set(toolName, pattern);
|
|
5867
|
+
}
|
|
5868
|
+
return pattern;
|
|
5869
|
+
}
|
|
5001
5870
|
var LEADING_WHITESPACE_RE = /^(\s*)/;
|
|
5871
|
+
var INCOMPLETE_MAPPING_TAIL_RE = /^[^:[\]{}-][^:]*:\s*$/;
|
|
5872
|
+
var INCOMPLETE_SEQUENCE_TAIL_RE = /^-\s*$/;
|
|
5873
|
+
var BLOCK_SCALAR_KEY_RE = /:\s*[|>][-+0-9]*\s*$/;
|
|
5874
|
+
var PLAIN_MAPPING_VALUE_RE = /^[^:[\]{}-][^:]*:\s*(.+)$/;
|
|
5875
|
+
var PLAIN_SEQUENCE_VALUE_RE = /^-\s+(.+)$/;
|
|
5876
|
+
function normalizeYamlContent(yamlContent) {
|
|
5877
|
+
let normalized = yamlContent;
|
|
5878
|
+
if (normalized.startsWith("\n")) {
|
|
5879
|
+
normalized = normalized.slice(1);
|
|
5880
|
+
}
|
|
5881
|
+
const lines = normalized.split("\n");
|
|
5882
|
+
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
|
5883
|
+
if (nonEmptyLines.length === 0) {
|
|
5884
|
+
return { normalized: "", nonEmptyLines };
|
|
5885
|
+
}
|
|
5886
|
+
const minIndent = Math.min(
|
|
5887
|
+
...nonEmptyLines.map((line) => {
|
|
5888
|
+
const match = line.match(LEADING_WHITESPACE_RE);
|
|
5889
|
+
return match ? match[1].length : 0;
|
|
5890
|
+
})
|
|
5891
|
+
);
|
|
5892
|
+
if (minIndent > 0) {
|
|
5893
|
+
normalized = lines.map((line) => line.slice(minIndent)).join("\n");
|
|
5894
|
+
}
|
|
5895
|
+
return { normalized, nonEmptyLines };
|
|
5896
|
+
}
|
|
5897
|
+
function parseYamlDocumentAsMapping(normalized) {
|
|
5898
|
+
try {
|
|
5899
|
+
const doc = import_yaml.default.parseDocument(normalized);
|
|
5900
|
+
const errors = doc.errors.map((e) => e.message);
|
|
5901
|
+
const result = doc.toJSON();
|
|
5902
|
+
if (result === null) {
|
|
5903
|
+
return { value: {}, errors };
|
|
5904
|
+
}
|
|
5905
|
+
if (typeof result !== "object" || Array.isArray(result)) {
|
|
5906
|
+
return { value: null, errors };
|
|
5907
|
+
}
|
|
5908
|
+
return { value: result, errors };
|
|
5909
|
+
} catch (error) {
|
|
5910
|
+
return {
|
|
5911
|
+
value: null,
|
|
5912
|
+
errors: [
|
|
5913
|
+
error instanceof Error ? error.message : "Unknown YAML parsing error"
|
|
5914
|
+
]
|
|
5915
|
+
};
|
|
5916
|
+
}
|
|
5917
|
+
}
|
|
5918
|
+
function getLastMeaningfulLineInfo(input) {
|
|
5919
|
+
var _a;
|
|
5920
|
+
const lines = input.split("\n");
|
|
5921
|
+
let index = lines.length - 1;
|
|
5922
|
+
while (index >= 0) {
|
|
5923
|
+
const raw = (_a = lines[index]) != null ? _a : "";
|
|
5924
|
+
const trimmed = raw.trim();
|
|
5925
|
+
if (trimmed.length > 0 && !trimmed.startsWith("#")) {
|
|
5926
|
+
return {
|
|
5927
|
+
index,
|
|
5928
|
+
raw,
|
|
5929
|
+
trimmed,
|
|
5930
|
+
indent: raw.length - raw.trimStart().length
|
|
5931
|
+
};
|
|
5932
|
+
}
|
|
5933
|
+
index -= 1;
|
|
5934
|
+
}
|
|
5935
|
+
return null;
|
|
5936
|
+
}
|
|
5937
|
+
function dropLastMeaningfulLine(input) {
|
|
5938
|
+
const lineInfo = getLastMeaningfulLineInfo(input);
|
|
5939
|
+
if (!lineInfo) {
|
|
5940
|
+
return null;
|
|
5941
|
+
}
|
|
5942
|
+
return input.split("\n").slice(0, lineInfo.index).join("\n").trimEnd();
|
|
5943
|
+
}
|
|
5944
|
+
function hasIncompleteMappingTail(normalized) {
|
|
5945
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
5946
|
+
if (!lineInfo) {
|
|
5947
|
+
return false;
|
|
5948
|
+
}
|
|
5949
|
+
return INCOMPLETE_MAPPING_TAIL_RE.test(lineInfo.trimmed);
|
|
5950
|
+
}
|
|
5951
|
+
function hasIncompleteSequenceTail(normalized) {
|
|
5952
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
5953
|
+
if (!lineInfo) {
|
|
5954
|
+
return false;
|
|
5955
|
+
}
|
|
5956
|
+
return INCOMPLETE_SEQUENCE_TAIL_RE.test(lineInfo.trimmed);
|
|
5957
|
+
}
|
|
5958
|
+
function hasSplitNestedKeyTail(normalized) {
|
|
5959
|
+
var _a;
|
|
5960
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
5961
|
+
if (!lineInfo) {
|
|
5962
|
+
return false;
|
|
5963
|
+
}
|
|
5964
|
+
const { trimmed, indent, index } = lineInfo;
|
|
5965
|
+
if (indent === 0) {
|
|
5966
|
+
return false;
|
|
5967
|
+
}
|
|
5968
|
+
if (trimmed.startsWith("#") || trimmed.startsWith("-") || trimmed.includes(":")) {
|
|
5969
|
+
return false;
|
|
5970
|
+
}
|
|
5971
|
+
const lines = normalized.split("\n");
|
|
5972
|
+
let parentIndex = index - 1;
|
|
5973
|
+
while (parentIndex >= 0) {
|
|
5974
|
+
const parentRaw = (_a = lines[parentIndex]) != null ? _a : "";
|
|
5975
|
+
const parentTrimmed = parentRaw.trim();
|
|
5976
|
+
if (parentTrimmed.length === 0 || parentTrimmed.startsWith("#")) {
|
|
5977
|
+
parentIndex -= 1;
|
|
5978
|
+
continue;
|
|
5979
|
+
}
|
|
5980
|
+
const parentIndent = parentRaw.length - parentRaw.trimStart().length;
|
|
5981
|
+
if (parentIndent >= indent) {
|
|
5982
|
+
parentIndex -= 1;
|
|
5983
|
+
continue;
|
|
5984
|
+
}
|
|
5985
|
+
if (!parentTrimmed.endsWith(":")) {
|
|
5986
|
+
return false;
|
|
5987
|
+
}
|
|
5988
|
+
if (BLOCK_SCALAR_KEY_RE.test(parentTrimmed)) {
|
|
5989
|
+
return false;
|
|
5990
|
+
}
|
|
5991
|
+
return true;
|
|
5992
|
+
}
|
|
5993
|
+
return false;
|
|
5994
|
+
}
|
|
5995
|
+
function extractTrailingPlainScalarValue(line) {
|
|
5996
|
+
var _a;
|
|
5997
|
+
if (BLOCK_SCALAR_KEY_RE.test(line)) {
|
|
5998
|
+
return null;
|
|
5999
|
+
}
|
|
6000
|
+
const mappingMatch = line.match(PLAIN_MAPPING_VALUE_RE);
|
|
6001
|
+
const sequenceMatch = line.match(PLAIN_SEQUENCE_VALUE_RE);
|
|
6002
|
+
const value = (_a = mappingMatch == null ? void 0 : mappingMatch[1]) != null ? _a : sequenceMatch == null ? void 0 : sequenceMatch[1];
|
|
6003
|
+
if (!value) {
|
|
6004
|
+
return null;
|
|
6005
|
+
}
|
|
6006
|
+
const trimmedValue = value.trim();
|
|
6007
|
+
if (trimmedValue.length === 0) {
|
|
6008
|
+
return null;
|
|
6009
|
+
}
|
|
6010
|
+
if (trimmedValue.startsWith('"') || trimmedValue.startsWith("'")) {
|
|
6011
|
+
return null;
|
|
6012
|
+
}
|
|
6013
|
+
if (trimmedValue.startsWith("{") || trimmedValue.startsWith("[") || trimmedValue.startsWith("|") || trimmedValue.startsWith(">")) {
|
|
6014
|
+
return null;
|
|
6015
|
+
}
|
|
6016
|
+
return trimmedValue;
|
|
6017
|
+
}
|
|
6018
|
+
function hasUnterminatedPlainScalarTail(normalized) {
|
|
6019
|
+
if (normalized.endsWith("\n")) {
|
|
6020
|
+
return false;
|
|
6021
|
+
}
|
|
6022
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6023
|
+
if (!lineInfo) {
|
|
6024
|
+
return false;
|
|
6025
|
+
}
|
|
6026
|
+
return extractTrailingPlainScalarValue(lineInfo.trimmed) != null;
|
|
6027
|
+
}
|
|
6028
|
+
function hasUnstableProgressTail(normalized) {
|
|
6029
|
+
return hasIncompleteMappingTail(normalized) || hasIncompleteSequenceTail(normalized) || hasSplitNestedKeyTail(normalized) || hasUnterminatedPlainScalarTail(normalized);
|
|
6030
|
+
}
|
|
6031
|
+
function trimTrailingNewlineInUnknown(value) {
|
|
6032
|
+
if (typeof value === "string") {
|
|
6033
|
+
if (value.endsWith("\n")) {
|
|
6034
|
+
return value.slice(0, -1);
|
|
6035
|
+
}
|
|
6036
|
+
return value;
|
|
6037
|
+
}
|
|
6038
|
+
if (Array.isArray(value)) {
|
|
6039
|
+
return value.map((item) => trimTrailingNewlineInUnknown(item));
|
|
6040
|
+
}
|
|
6041
|
+
if (value && typeof value === "object") {
|
|
6042
|
+
return Object.fromEntries(
|
|
6043
|
+
Object.entries(value).map(([key, item]) => [
|
|
6044
|
+
key,
|
|
6045
|
+
trimTrailingNewlineInUnknown(item)
|
|
6046
|
+
])
|
|
6047
|
+
);
|
|
6048
|
+
}
|
|
6049
|
+
return value;
|
|
6050
|
+
}
|
|
6051
|
+
function stabilizeParsedValueForStreamProgress(value, source) {
|
|
6052
|
+
if (source.endsWith("\n")) {
|
|
6053
|
+
return value;
|
|
6054
|
+
}
|
|
6055
|
+
return trimTrailingNewlineInUnknown(value);
|
|
6056
|
+
}
|
|
5002
6057
|
function findClosingTagEnd(text, contentStart, toolName) {
|
|
5003
6058
|
let pos = contentStart;
|
|
5004
6059
|
let depth = 1;
|
|
@@ -5070,7 +6125,7 @@ function findEarliestTagPosition(openIdx, selfIdx) {
|
|
|
5070
6125
|
function collectToolCallsForName(text, toolName) {
|
|
5071
6126
|
const toolCalls = [];
|
|
5072
6127
|
let searchIndex = 0;
|
|
5073
|
-
const selfTagRegex =
|
|
6128
|
+
const selfTagRegex = getSelfClosingTagPattern2(toolName);
|
|
5074
6129
|
while (searchIndex < text.length) {
|
|
5075
6130
|
const startTag = `<${toolName}>`;
|
|
5076
6131
|
const openIdx = text.indexOf(startTag, searchIndex);
|
|
@@ -5122,47 +6177,48 @@ function findToolCalls2(text, toolNames) {
|
|
|
5122
6177
|
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
5123
6178
|
}
|
|
5124
6179
|
function parseYamlContent(yamlContent, options) {
|
|
5125
|
-
var _a, _b
|
|
5126
|
-
|
|
5127
|
-
if (normalized.startsWith("\n")) {
|
|
5128
|
-
normalized = normalized.slice(1);
|
|
5129
|
-
}
|
|
5130
|
-
const lines = normalized.split("\n");
|
|
5131
|
-
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
|
6180
|
+
var _a, _b;
|
|
6181
|
+
const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
|
|
5132
6182
|
if (nonEmptyLines.length === 0) {
|
|
5133
6183
|
return {};
|
|
5134
6184
|
}
|
|
5135
|
-
const
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
})
|
|
5140
|
-
|
|
5141
|
-
if (minIndent > 0) {
|
|
5142
|
-
normalized = lines.map((line) => line.slice(minIndent)).join("\n");
|
|
6185
|
+
const parsed = parseYamlDocumentAsMapping(normalized);
|
|
6186
|
+
if (parsed.errors.length > 0) {
|
|
6187
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "YAML parse error", {
|
|
6188
|
+
errors: parsed.errors
|
|
6189
|
+
});
|
|
6190
|
+
return null;
|
|
5143
6191
|
}
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
6192
|
+
if (parsed.value === null) {
|
|
6193
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
|
|
6194
|
+
got: "non-mapping"
|
|
6195
|
+
});
|
|
6196
|
+
return null;
|
|
6197
|
+
}
|
|
6198
|
+
return parsed.value;
|
|
6199
|
+
}
|
|
6200
|
+
function parseYamlContentForStreamProgress(yamlContent) {
|
|
6201
|
+
const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
|
|
6202
|
+
if (nonEmptyLines.length === 0) {
|
|
6203
|
+
return {};
|
|
6204
|
+
}
|
|
6205
|
+
let candidate = normalized;
|
|
6206
|
+
while (true) {
|
|
6207
|
+
const parsed = parseYamlDocumentAsMapping(candidate);
|
|
6208
|
+
if (parsed.errors.length === 0 && !hasUnstableProgressTail(candidate)) {
|
|
6209
|
+
if (candidate.trim().length === 0 && normalized.trim().length > 0) {
|
|
6210
|
+
return null;
|
|
6211
|
+
}
|
|
6212
|
+
return stabilizeParsedValueForStreamProgress(parsed.value, candidate);
|
|
5151
6213
|
}
|
|
5152
|
-
const
|
|
5153
|
-
if (
|
|
5154
|
-
return
|
|
6214
|
+
const truncated = dropLastMeaningfulLine(candidate);
|
|
6215
|
+
if (truncated == null) {
|
|
6216
|
+
return null;
|
|
5155
6217
|
}
|
|
5156
|
-
if (
|
|
5157
|
-
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
|
|
5158
|
-
got: typeof result
|
|
5159
|
-
});
|
|
6218
|
+
if (truncated === candidate) {
|
|
5160
6219
|
return null;
|
|
5161
6220
|
}
|
|
5162
|
-
|
|
5163
|
-
} catch (error) {
|
|
5164
|
-
(_c = options == null ? void 0 : options.onError) == null ? void 0 : _c.call(options, "Failed to parse YAML content", { error });
|
|
5165
|
-
return null;
|
|
6221
|
+
candidate = truncated;
|
|
5166
6222
|
}
|
|
5167
6223
|
}
|
|
5168
6224
|
function processToolCallMatch(text, tc, currentIndex, processedElements, options) {
|
|
@@ -5178,7 +6234,7 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
|
|
|
5178
6234
|
if (parsedArgs !== null) {
|
|
5179
6235
|
processedElements.push({
|
|
5180
6236
|
type: "tool-call",
|
|
5181
|
-
toolCallId:
|
|
6237
|
+
toolCallId: generateToolCallId(),
|
|
5182
6238
|
toolName: tc.toolName,
|
|
5183
6239
|
input: JSON.stringify(parsedArgs)
|
|
5184
6240
|
});
|
|
@@ -5191,38 +6247,6 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
|
|
|
5191
6247
|
}
|
|
5192
6248
|
return tc.endIndex;
|
|
5193
6249
|
}
|
|
5194
|
-
function createFlushTextHandler2(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
5195
|
-
return (controller, text) => {
|
|
5196
|
-
const content = text;
|
|
5197
|
-
if (content) {
|
|
5198
|
-
if (!getCurrentTextId()) {
|
|
5199
|
-
const newId = generateId();
|
|
5200
|
-
setCurrentTextId(newId);
|
|
5201
|
-
controller.enqueue({
|
|
5202
|
-
type: "text-start",
|
|
5203
|
-
id: newId
|
|
5204
|
-
});
|
|
5205
|
-
setHasEmittedTextStart(true);
|
|
5206
|
-
}
|
|
5207
|
-
controller.enqueue({
|
|
5208
|
-
type: "text-delta",
|
|
5209
|
-
id: getCurrentTextId(),
|
|
5210
|
-
delta: content
|
|
5211
|
-
});
|
|
5212
|
-
}
|
|
5213
|
-
const currentTextId = getCurrentTextId();
|
|
5214
|
-
if (currentTextId && !text) {
|
|
5215
|
-
if (getHasEmittedTextStart()) {
|
|
5216
|
-
controller.enqueue({
|
|
5217
|
-
type: "text-end",
|
|
5218
|
-
id: currentTextId
|
|
5219
|
-
});
|
|
5220
|
-
setHasEmittedTextStart(false);
|
|
5221
|
-
}
|
|
5222
|
-
setCurrentTextId(null);
|
|
5223
|
-
}
|
|
5224
|
-
};
|
|
5225
|
-
}
|
|
5226
6250
|
function findEarliestToolTag2(buffer, toolNames) {
|
|
5227
6251
|
let bestIndex = -1;
|
|
5228
6252
|
let bestName = "";
|
|
@@ -5230,8 +6254,9 @@ function findEarliestToolTag2(buffer, toolNames) {
|
|
|
5230
6254
|
let bestTagLength = 0;
|
|
5231
6255
|
for (const name of toolNames) {
|
|
5232
6256
|
const openTag = `<${name}>`;
|
|
5233
|
-
const selfTagRegex =
|
|
6257
|
+
const selfTagRegex = getSelfClosingTagPattern2(name);
|
|
5234
6258
|
const idxOpen = buffer.indexOf(openTag);
|
|
6259
|
+
selfTagRegex.lastIndex = 0;
|
|
5235
6260
|
const selfMatch = selfTagRegex.exec(buffer);
|
|
5236
6261
|
const idxSelf = selfMatch ? selfMatch.index : -1;
|
|
5237
6262
|
if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
|
|
@@ -5254,6 +6279,29 @@ function findEarliestToolTag2(buffer, toolNames) {
|
|
|
5254
6279
|
tagLength: bestTagLength
|
|
5255
6280
|
};
|
|
5256
6281
|
}
|
|
6282
|
+
function stripTrailingPartialCloseTag(content, toolName) {
|
|
6283
|
+
const closeTag = `</${toolName}>`;
|
|
6284
|
+
const lastLineBreakIndex = Math.max(
|
|
6285
|
+
content.lastIndexOf("\n"),
|
|
6286
|
+
content.lastIndexOf("\r")
|
|
6287
|
+
);
|
|
6288
|
+
const lineStartIndex = lastLineBreakIndex === -1 ? 0 : lastLineBreakIndex + 1;
|
|
6289
|
+
const trailingLine = content.slice(lineStartIndex);
|
|
6290
|
+
const trimmedTrailingLine = trailingLine.trim();
|
|
6291
|
+
if (trimmedTrailingLine.length === 0 || !trimmedTrailingLine.startsWith("</") || trimmedTrailingLine === closeTag || !closeTag.startsWith(trimmedTrailingLine)) {
|
|
6292
|
+
return content;
|
|
6293
|
+
}
|
|
6294
|
+
const leadingWhitespaceLength = trailingLine.length - trailingLine.trimStart().length;
|
|
6295
|
+
const preservedLeadingWhitespace = trailingLine.slice(
|
|
6296
|
+
0,
|
|
6297
|
+
leadingWhitespaceLength
|
|
6298
|
+
);
|
|
6299
|
+
const contentWithoutPartial = `${content.slice(
|
|
6300
|
+
0,
|
|
6301
|
+
lineStartIndex
|
|
6302
|
+
)}${preservedLeadingWhitespace}`;
|
|
6303
|
+
return contentWithoutPartial.trimEnd();
|
|
6304
|
+
}
|
|
5257
6305
|
var yamlProtocol = (_protocolOptions) => {
|
|
5258
6306
|
return {
|
|
5259
6307
|
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
@@ -5314,7 +6362,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5314
6362
|
let currentToolCall = null;
|
|
5315
6363
|
let currentTextId = null;
|
|
5316
6364
|
let hasEmittedTextStart = false;
|
|
5317
|
-
const flushText =
|
|
6365
|
+
const flushText = createFlushTextHandler(
|
|
5318
6366
|
() => currentTextId,
|
|
5319
6367
|
(newId) => {
|
|
5320
6368
|
currentTextId = newId;
|
|
@@ -5324,33 +6372,128 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5324
6372
|
hasEmittedTextStart = value;
|
|
5325
6373
|
}
|
|
5326
6374
|
);
|
|
5327
|
-
const
|
|
6375
|
+
const emitToolInputProgress2 = (controller, toolContent) => {
|
|
6376
|
+
if (!currentToolCall) {
|
|
6377
|
+
return;
|
|
6378
|
+
}
|
|
6379
|
+
const parsedArgs = parseYamlContentForStreamProgress(toolContent);
|
|
6380
|
+
if (parsedArgs === null) {
|
|
6381
|
+
return;
|
|
6382
|
+
}
|
|
6383
|
+
const fullInput = JSON.stringify(parsedArgs);
|
|
6384
|
+
if (fullInput === "{}" && toolContent.trim().length === 0) {
|
|
6385
|
+
return;
|
|
6386
|
+
}
|
|
6387
|
+
const prefixCandidate = toIncompleteJsonPrefix(fullInput);
|
|
6388
|
+
emitPrefixDelta({
|
|
6389
|
+
controller,
|
|
6390
|
+
id: currentToolCall.toolCallId,
|
|
6391
|
+
state: currentToolCall,
|
|
6392
|
+
candidate: prefixCandidate
|
|
6393
|
+
});
|
|
6394
|
+
};
|
|
6395
|
+
const processToolCallEnd = (controller, toolContent, toolName, toolCallId) => {
|
|
5328
6396
|
var _a;
|
|
5329
6397
|
const parsedArgs = parseYamlContent(toolContent, options);
|
|
5330
6398
|
flushText(controller);
|
|
5331
6399
|
if (parsedArgs !== null) {
|
|
6400
|
+
const finalInput = JSON.stringify(parsedArgs);
|
|
6401
|
+
if (currentToolCall && currentToolCall.toolCallId === toolCallId) {
|
|
6402
|
+
emitFinalRemainder({
|
|
6403
|
+
controller,
|
|
6404
|
+
id: toolCallId,
|
|
6405
|
+
state: currentToolCall,
|
|
6406
|
+
finalFullJson: finalInput,
|
|
6407
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
6408
|
+
});
|
|
6409
|
+
}
|
|
6410
|
+
controller.enqueue({
|
|
6411
|
+
type: "tool-input-end",
|
|
6412
|
+
id: toolCallId
|
|
6413
|
+
});
|
|
5332
6414
|
controller.enqueue({
|
|
5333
6415
|
type: "tool-call",
|
|
5334
|
-
toolCallId
|
|
6416
|
+
toolCallId,
|
|
5335
6417
|
toolName,
|
|
5336
|
-
input:
|
|
6418
|
+
input: finalInput
|
|
5337
6419
|
});
|
|
5338
6420
|
} else {
|
|
6421
|
+
controller.enqueue({
|
|
6422
|
+
type: "tool-input-end",
|
|
6423
|
+
id: toolCallId
|
|
6424
|
+
});
|
|
5339
6425
|
const original = `<${toolName}>${toolContent}</${toolName}>`;
|
|
5340
6426
|
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
|
|
5341
6427
|
toolCall: original
|
|
5342
6428
|
});
|
|
5343
|
-
|
|
6429
|
+
if (shouldEmitRawToolCallTextOnError3(options)) {
|
|
6430
|
+
flushText(controller, original);
|
|
6431
|
+
}
|
|
5344
6432
|
}
|
|
5345
6433
|
};
|
|
6434
|
+
const finalizeUnclosedToolCall = (controller) => {
|
|
6435
|
+
var _a;
|
|
6436
|
+
if (!currentToolCall) {
|
|
6437
|
+
return;
|
|
6438
|
+
}
|
|
6439
|
+
emitToolInputProgress2(controller, buffer);
|
|
6440
|
+
const { name: toolName, toolCallId } = currentToolCall;
|
|
6441
|
+
const reconciledBuffer = stripTrailingPartialCloseTag(buffer, toolName);
|
|
6442
|
+
const parsedArgs = parseYamlContent(reconciledBuffer, options);
|
|
6443
|
+
flushText(controller);
|
|
6444
|
+
if (parsedArgs !== null) {
|
|
6445
|
+
const finalInput = JSON.stringify(parsedArgs);
|
|
6446
|
+
emitFinalRemainder({
|
|
6447
|
+
controller,
|
|
6448
|
+
id: toolCallId,
|
|
6449
|
+
state: currentToolCall,
|
|
6450
|
+
finalFullJson: finalInput,
|
|
6451
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
6452
|
+
});
|
|
6453
|
+
controller.enqueue({
|
|
6454
|
+
type: "tool-input-end",
|
|
6455
|
+
id: toolCallId
|
|
6456
|
+
});
|
|
6457
|
+
controller.enqueue({
|
|
6458
|
+
type: "tool-call",
|
|
6459
|
+
toolCallId,
|
|
6460
|
+
toolName,
|
|
6461
|
+
input: finalInput
|
|
6462
|
+
});
|
|
6463
|
+
} else {
|
|
6464
|
+
controller.enqueue({
|
|
6465
|
+
type: "tool-input-end",
|
|
6466
|
+
id: toolCallId
|
|
6467
|
+
});
|
|
6468
|
+
const unfinishedContent = `<${toolName}>${buffer}`;
|
|
6469
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
6470
|
+
options,
|
|
6471
|
+
"Could not complete streaming YAML tool call at finish.",
|
|
6472
|
+
{ toolCall: unfinishedContent }
|
|
6473
|
+
);
|
|
6474
|
+
if (shouldEmitRawToolCallTextOnError3(options)) {
|
|
6475
|
+
flushText(controller, unfinishedContent);
|
|
6476
|
+
}
|
|
6477
|
+
}
|
|
6478
|
+
buffer = "";
|
|
6479
|
+
currentToolCall = null;
|
|
6480
|
+
};
|
|
5346
6481
|
const handlePendingToolCall = (controller, endTag, toolName) => {
|
|
6482
|
+
var _a;
|
|
5347
6483
|
const endIdx = buffer.indexOf(endTag);
|
|
5348
6484
|
if (endIdx === -1) {
|
|
6485
|
+
emitToolInputProgress2(controller, buffer);
|
|
5349
6486
|
return false;
|
|
5350
6487
|
}
|
|
5351
6488
|
const content = buffer.substring(0, endIdx);
|
|
6489
|
+
emitToolInputProgress2(controller, content);
|
|
5352
6490
|
buffer = buffer.substring(endIdx + endTag.length);
|
|
5353
|
-
processToolCallEnd(
|
|
6491
|
+
processToolCallEnd(
|
|
6492
|
+
controller,
|
|
6493
|
+
content,
|
|
6494
|
+
toolName,
|
|
6495
|
+
(_a = currentToolCall == null ? void 0 : currentToolCall.toolCallId) != null ? _a : generateToolCallId()
|
|
6496
|
+
);
|
|
5354
6497
|
currentToolCall = null;
|
|
5355
6498
|
return true;
|
|
5356
6499
|
};
|
|
@@ -5367,13 +6510,35 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5367
6510
|
if (tagIndex > 0) {
|
|
5368
6511
|
flushText(controller, buffer.substring(0, tagIndex));
|
|
5369
6512
|
}
|
|
6513
|
+
flushText(controller);
|
|
5370
6514
|
if (selfClosing) {
|
|
5371
6515
|
buffer = buffer.substring(tagIndex + tagLength);
|
|
5372
|
-
|
|
6516
|
+
const toolCallId = generateToolCallId();
|
|
6517
|
+
currentToolCall = {
|
|
6518
|
+
name: tagName,
|
|
6519
|
+
toolCallId,
|
|
6520
|
+
emittedInput: ""
|
|
6521
|
+
};
|
|
6522
|
+
controller.enqueue({
|
|
6523
|
+
type: "tool-input-start",
|
|
6524
|
+
id: toolCallId,
|
|
6525
|
+
toolName: tagName
|
|
6526
|
+
});
|
|
6527
|
+
processToolCallEnd(controller, "", tagName, toolCallId);
|
|
6528
|
+
currentToolCall = null;
|
|
5373
6529
|
} else {
|
|
5374
6530
|
const startTag = `<${tagName}>`;
|
|
5375
6531
|
buffer = buffer.substring(tagIndex + startTag.length);
|
|
5376
|
-
currentToolCall = {
|
|
6532
|
+
currentToolCall = {
|
|
6533
|
+
name: tagName,
|
|
6534
|
+
toolCallId: generateToolCallId(),
|
|
6535
|
+
emittedInput: ""
|
|
6536
|
+
};
|
|
6537
|
+
controller.enqueue({
|
|
6538
|
+
type: "tool-input-start",
|
|
6539
|
+
id: currentToolCall.toolCallId,
|
|
6540
|
+
toolName: tagName
|
|
6541
|
+
});
|
|
5377
6542
|
}
|
|
5378
6543
|
};
|
|
5379
6544
|
const processBuffer = (controller) => {
|
|
@@ -5402,10 +6567,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5402
6567
|
var _a;
|
|
5403
6568
|
if (chunk.type === "finish") {
|
|
5404
6569
|
if (currentToolCall) {
|
|
5405
|
-
|
|
5406
|
-
flushText(controller, unfinishedContent);
|
|
5407
|
-
buffer = "";
|
|
5408
|
-
currentToolCall = null;
|
|
6570
|
+
finalizeUnclosedToolCall(controller);
|
|
5409
6571
|
} else if (buffer) {
|
|
5410
6572
|
flushText(controller, buffer);
|
|
5411
6573
|
buffer = "";
|
|
@@ -5415,7 +6577,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5415
6577
|
return;
|
|
5416
6578
|
}
|
|
5417
6579
|
if (chunk.type !== "text-delta") {
|
|
5418
|
-
if (buffer) {
|
|
6580
|
+
if (!currentToolCall && buffer) {
|
|
5419
6581
|
flushText(controller, buffer);
|
|
5420
6582
|
buffer = "";
|
|
5421
6583
|
}
|
|
@@ -5428,10 +6590,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5428
6590
|
},
|
|
5429
6591
|
flush(controller) {
|
|
5430
6592
|
if (currentToolCall) {
|
|
5431
|
-
|
|
5432
|
-
flushText(controller, unfinishedContent);
|
|
5433
|
-
buffer = "";
|
|
5434
|
-
currentToolCall = null;
|
|
6593
|
+
finalizeUnclosedToolCall(controller);
|
|
5435
6594
|
} else if (buffer) {
|
|
5436
6595
|
flushText(controller, buffer);
|
|
5437
6596
|
buffer = "";
|
|
@@ -5594,9 +6753,6 @@ function isToolChoiceActive(params) {
|
|
|
5594
6753
|
return !!(typeof params.providerOptions === "object" && params.providerOptions !== null && typeof ((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) === "object" && toolChoice && typeof toolChoice === "object" && (toolChoice.type === "tool" || toolChoice.type === "required"));
|
|
5595
6754
|
}
|
|
5596
6755
|
|
|
5597
|
-
// src/generate-handler.ts
|
|
5598
|
-
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
5599
|
-
|
|
5600
6756
|
// src/core/utils/generated-text-json-recovery.ts
|
|
5601
6757
|
function isRecord(value) {
|
|
5602
6758
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -5735,7 +6891,7 @@ function mergeJsonCandidatesByStart(tagged, codeBlocks, balanced) {
|
|
|
5735
6891
|
function toToolCallPart(candidate) {
|
|
5736
6892
|
return {
|
|
5737
6893
|
type: "tool-call",
|
|
5738
|
-
toolCallId:
|
|
6894
|
+
toolCallId: generateToolCallId(),
|
|
5739
6895
|
toolName: candidate.toolName,
|
|
5740
6896
|
input: candidate.input
|
|
5741
6897
|
};
|
|
@@ -5962,7 +7118,7 @@ async function handleToolChoice(doGenerate, params, tools) {
|
|
|
5962
7118
|
}
|
|
5963
7119
|
const toolCall = {
|
|
5964
7120
|
type: "tool-call",
|
|
5965
|
-
toolCallId: (
|
|
7121
|
+
toolCallId: generateToolCallId(),
|
|
5966
7122
|
toolName,
|
|
5967
7123
|
input
|
|
5968
7124
|
};
|
|
@@ -6472,7 +7628,6 @@ unit: celsius
|
|
|
6472
7628
|
}
|
|
6473
7629
|
|
|
6474
7630
|
// src/stream-handler.ts
|
|
6475
|
-
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
6476
7631
|
async function wrapStream({
|
|
6477
7632
|
protocol,
|
|
6478
7633
|
doStream,
|
|
@@ -6510,10 +7665,22 @@ async function wrapStream({
|
|
|
6510
7665
|
}
|
|
6511
7666
|
)
|
|
6512
7667
|
).pipeThrough(protocol.createStreamParser({ tools, options }));
|
|
7668
|
+
let seenToolCall = false;
|
|
6513
7669
|
const v3Stream = coreStream.pipeThrough(
|
|
6514
7670
|
new TransformStream({
|
|
6515
7671
|
transform(part, controller) {
|
|
6516
|
-
|
|
7672
|
+
let normalizedPart = part.type === "tool-call" ? coerceToolCallPart(part, tools) : part;
|
|
7673
|
+
if (normalizedPart.type === "tool-call") {
|
|
7674
|
+
seenToolCall = true;
|
|
7675
|
+
}
|
|
7676
|
+
if (normalizedPart.type === "finish" && seenToolCall && normalizedPart.finishReason.unified === "stop") {
|
|
7677
|
+
normalizedPart = {
|
|
7678
|
+
...normalizedPart,
|
|
7679
|
+
finishReason: normalizeToolCallsFinishReason(
|
|
7680
|
+
normalizedPart.finishReason
|
|
7681
|
+
)
|
|
7682
|
+
};
|
|
7683
|
+
}
|
|
6517
7684
|
if (debugLevel === "stream") {
|
|
6518
7685
|
logParsedChunk(normalizedPart);
|
|
6519
7686
|
}
|
|
@@ -6550,7 +7717,7 @@ async function toolChoiceStream({
|
|
|
6550
7717
|
start(controller) {
|
|
6551
7718
|
controller.enqueue({
|
|
6552
7719
|
type: "tool-call",
|
|
6553
|
-
toolCallId: (
|
|
7720
|
+
toolCallId: generateToolCallId(),
|
|
6554
7721
|
toolName,
|
|
6555
7722
|
input
|
|
6556
7723
|
});
|