@ai-sdk-tool/parser 3.3.3 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/dist/{chunk-CXWS24JX.js → chunk-76E6H46R.js} +2 -2
- package/dist/{chunk-2KK5BDZF.js → chunk-DJB4DAZO.js} +23 -6
- package/dist/chunk-DJB4DAZO.js.map +1 -0
- package/dist/{chunk-NAQSTPDQ.js → chunk-DPGORNPB.js} +1388 -211
- package/dist/chunk-DPGORNPB.js.map +1 -0
- package/dist/community.cjs +1420 -226
- package/dist/community.cjs.map +1 -1
- package/dist/community.js +3 -3
- package/dist/index.cjs +1420 -226
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -6
- package/dist/index.d.ts +8 -6
- package/dist/index.js +3 -3
- package/dist/rxml.cjs +22 -5
- package/dist/rxml.cjs.map +1 -1
- package/dist/rxml.js +2 -2
- package/dist/schema-coerce.cjs +22 -5
- package/dist/schema-coerce.cjs.map +1 -1
- package/dist/schema-coerce.js +1 -1
- package/package.json +7 -7
- package/dist/chunk-2KK5BDZF.js.map +0 -1
- package/dist/chunk-NAQSTPDQ.js.map +0 -1
- /package/dist/{chunk-CXWS24JX.js.map → chunk-76E6H46R.js.map} +0 -0
package/dist/community.cjs
CHANGED
|
@@ -836,9 +836,19 @@ function getPotentialStartIndex(text, searchedText) {
|
|
|
836
836
|
if (directIndex !== -1) {
|
|
837
837
|
return directIndex;
|
|
838
838
|
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
839
|
+
const textLength = text.length;
|
|
840
|
+
const searchedTextLength = searchedText.length;
|
|
841
|
+
const startAt = Math.max(0, textLength - searchedTextLength + 1);
|
|
842
|
+
for (let i = startAt; i < textLength; i++) {
|
|
843
|
+
let match = true;
|
|
844
|
+
const currentSuffixLength = textLength - i;
|
|
845
|
+
for (let j = 0; j < currentSuffixLength; j++) {
|
|
846
|
+
if (text[i + j] !== searchedText[j]) {
|
|
847
|
+
match = false;
|
|
848
|
+
break;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
if (match) {
|
|
842
852
|
return i;
|
|
843
853
|
}
|
|
844
854
|
}
|
|
@@ -847,7 +857,25 @@ function getPotentialStartIndex(text, searchedText) {
|
|
|
847
857
|
|
|
848
858
|
// src/core/utils/id.ts
|
|
849
859
|
function generateId() {
|
|
850
|
-
return
|
|
860
|
+
return crypto.randomUUID().replace(/-/g, "").slice(0, 13);
|
|
861
|
+
}
|
|
862
|
+
var TOOL_CALL_ID_PREFIX = "call_";
|
|
863
|
+
var TOOL_CALL_ID_BODY_LENGTH = 24;
|
|
864
|
+
var TOOL_CALL_ID_ALPHANUM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
865
|
+
function randomAlphaNumeric(length) {
|
|
866
|
+
var _a;
|
|
867
|
+
const bytes = new Uint8Array(length);
|
|
868
|
+
crypto.getRandomValues(bytes);
|
|
869
|
+
let out = "";
|
|
870
|
+
for (let i = 0; i < length; i += 1) {
|
|
871
|
+
const byte = bytes[i];
|
|
872
|
+
const index = (byte != null ? byte : 0) % TOOL_CALL_ID_ALPHANUM.length;
|
|
873
|
+
out += (_a = TOOL_CALL_ID_ALPHANUM[index]) != null ? _a : "0";
|
|
874
|
+
}
|
|
875
|
+
return out;
|
|
876
|
+
}
|
|
877
|
+
function generateToolCallId() {
|
|
878
|
+
return `${TOOL_CALL_ID_PREFIX}${randomAlphaNumeric(TOOL_CALL_ID_BODY_LENGTH)}`;
|
|
851
879
|
}
|
|
852
880
|
|
|
853
881
|
// src/core/utils/protocol-utils.ts
|
|
@@ -856,6 +884,38 @@ function addTextSegment(text, processedElements) {
|
|
|
856
884
|
processedElements.push({ type: "text", text });
|
|
857
885
|
}
|
|
858
886
|
}
|
|
887
|
+
function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
|
|
888
|
+
return (controller, text) => {
|
|
889
|
+
const content = text;
|
|
890
|
+
if (content) {
|
|
891
|
+
if (!getCurrentTextId()) {
|
|
892
|
+
const newId = generateId();
|
|
893
|
+
setCurrentTextId(newId);
|
|
894
|
+
controller.enqueue({
|
|
895
|
+
type: "text-start",
|
|
896
|
+
id: newId
|
|
897
|
+
});
|
|
898
|
+
setHasEmittedTextStart(true);
|
|
899
|
+
}
|
|
900
|
+
controller.enqueue({
|
|
901
|
+
type: "text-delta",
|
|
902
|
+
id: getCurrentTextId(),
|
|
903
|
+
delta: content
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
const currentTextId = getCurrentTextId();
|
|
907
|
+
if (currentTextId && !text) {
|
|
908
|
+
if (getHasEmittedTextStart()) {
|
|
909
|
+
controller.enqueue({
|
|
910
|
+
type: "text-end",
|
|
911
|
+
id: currentTextId
|
|
912
|
+
});
|
|
913
|
+
setHasEmittedTextStart(false);
|
|
914
|
+
}
|
|
915
|
+
setCurrentTextId(null);
|
|
916
|
+
}
|
|
917
|
+
};
|
|
918
|
+
}
|
|
859
919
|
|
|
860
920
|
// src/core/utils/regex.ts
|
|
861
921
|
function escapeRegExp(literal) {
|
|
@@ -863,15 +923,21 @@ function escapeRegExp(literal) {
|
|
|
863
923
|
}
|
|
864
924
|
|
|
865
925
|
// src/core/protocols/json-protocol.ts
|
|
926
|
+
function shouldEmitRawToolCallTextOnError(options) {
|
|
927
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
928
|
+
}
|
|
929
|
+
function canonicalizeToolInput(argumentsValue) {
|
|
930
|
+
return JSON.stringify(argumentsValue != null ? argumentsValue : {});
|
|
931
|
+
}
|
|
866
932
|
function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
|
|
867
|
-
var _a
|
|
933
|
+
var _a;
|
|
868
934
|
try {
|
|
869
935
|
const parsedToolCall = parse(toolCallJson);
|
|
870
936
|
processedElements.push({
|
|
871
937
|
type: "tool-call",
|
|
872
|
-
toolCallId:
|
|
938
|
+
toolCallId: generateToolCallId(),
|
|
873
939
|
toolName: parsedToolCall.name,
|
|
874
|
-
input:
|
|
940
|
+
input: canonicalizeToolInput(parsedToolCall.arguments)
|
|
875
941
|
});
|
|
876
942
|
} catch (error) {
|
|
877
943
|
logParseFailure({
|
|
@@ -880,7 +946,7 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
|
|
|
880
946
|
snippet: fullMatch,
|
|
881
947
|
error
|
|
882
948
|
});
|
|
883
|
-
(
|
|
949
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
884
950
|
options,
|
|
885
951
|
"Could not process JSON tool call, keeping original text.",
|
|
886
952
|
{ toolCall: fullMatch, error }
|
|
@@ -901,6 +967,293 @@ function processMatchedToolCall(context) {
|
|
|
901
967
|
}
|
|
902
968
|
return startIndex + match[0].length;
|
|
903
969
|
}
|
|
970
|
+
var WHITESPACE_JSON_REGEX = /\s/;
|
|
971
|
+
function skipJsonWhitespace(text, fromIndex) {
|
|
972
|
+
let index = fromIndex;
|
|
973
|
+
while (index < text.length && WHITESPACE_JSON_REGEX.test(text[index])) {
|
|
974
|
+
index += 1;
|
|
975
|
+
}
|
|
976
|
+
return index;
|
|
977
|
+
}
|
|
978
|
+
function findTopLevelPropertyValueStart(text, property) {
|
|
979
|
+
const objectStart = skipJsonWhitespace(text, 0);
|
|
980
|
+
if (objectStart >= text.length || text.charAt(objectStart) !== "{") {
|
|
981
|
+
return null;
|
|
982
|
+
}
|
|
983
|
+
let depth = 0;
|
|
984
|
+
let inString = false;
|
|
985
|
+
let escaping = false;
|
|
986
|
+
for (let index = objectStart; index < text.length; index += 1) {
|
|
987
|
+
const char = text.charAt(index);
|
|
988
|
+
if (inString) {
|
|
989
|
+
if (escaping) {
|
|
990
|
+
escaping = false;
|
|
991
|
+
continue;
|
|
992
|
+
}
|
|
993
|
+
if (char === "\\") {
|
|
994
|
+
escaping = true;
|
|
995
|
+
continue;
|
|
996
|
+
}
|
|
997
|
+
if (char === '"') {
|
|
998
|
+
inString = false;
|
|
999
|
+
}
|
|
1000
|
+
continue;
|
|
1001
|
+
}
|
|
1002
|
+
if (char === "{") {
|
|
1003
|
+
depth += 1;
|
|
1004
|
+
continue;
|
|
1005
|
+
}
|
|
1006
|
+
if (char === "}") {
|
|
1007
|
+
depth = Math.max(0, depth - 1);
|
|
1008
|
+
continue;
|
|
1009
|
+
}
|
|
1010
|
+
if (char !== '"') {
|
|
1011
|
+
continue;
|
|
1012
|
+
}
|
|
1013
|
+
if (depth !== 1) {
|
|
1014
|
+
inString = true;
|
|
1015
|
+
continue;
|
|
1016
|
+
}
|
|
1017
|
+
const keyStart = index + 1;
|
|
1018
|
+
let keyEnd = keyStart;
|
|
1019
|
+
let keyEscaped = false;
|
|
1020
|
+
while (keyEnd < text.length) {
|
|
1021
|
+
const keyChar = text.charAt(keyEnd);
|
|
1022
|
+
if (keyEscaped) {
|
|
1023
|
+
keyEscaped = false;
|
|
1024
|
+
} else if (keyChar === "\\") {
|
|
1025
|
+
keyEscaped = true;
|
|
1026
|
+
} else if (keyChar === '"') {
|
|
1027
|
+
break;
|
|
1028
|
+
}
|
|
1029
|
+
keyEnd += 1;
|
|
1030
|
+
}
|
|
1031
|
+
if (keyEnd >= text.length || text.charAt(keyEnd) !== '"') {
|
|
1032
|
+
return null;
|
|
1033
|
+
}
|
|
1034
|
+
const key = text.slice(keyStart, keyEnd);
|
|
1035
|
+
let valueCursor = skipJsonWhitespace(text, keyEnd + 1);
|
|
1036
|
+
if (valueCursor >= text.length || text.charAt(valueCursor) !== ":") {
|
|
1037
|
+
index = keyEnd;
|
|
1038
|
+
continue;
|
|
1039
|
+
}
|
|
1040
|
+
valueCursor = skipJsonWhitespace(text, valueCursor + 1);
|
|
1041
|
+
if (key === property) {
|
|
1042
|
+
return valueCursor < text.length ? valueCursor : null;
|
|
1043
|
+
}
|
|
1044
|
+
index = valueCursor - 1;
|
|
1045
|
+
}
|
|
1046
|
+
return null;
|
|
1047
|
+
}
|
|
1048
|
+
function extractTopLevelStringProperty(text, property) {
|
|
1049
|
+
const valueStart = findTopLevelPropertyValueStart(text, property);
|
|
1050
|
+
if (valueStart == null || valueStart >= text.length) {
|
|
1051
|
+
return void 0;
|
|
1052
|
+
}
|
|
1053
|
+
if (text.charAt(valueStart) !== '"') {
|
|
1054
|
+
return void 0;
|
|
1055
|
+
}
|
|
1056
|
+
let valueEnd = valueStart + 1;
|
|
1057
|
+
let escaped = false;
|
|
1058
|
+
while (valueEnd < text.length) {
|
|
1059
|
+
const char = text.charAt(valueEnd);
|
|
1060
|
+
if (escaped) {
|
|
1061
|
+
escaped = false;
|
|
1062
|
+
} else if (char === "\\") {
|
|
1063
|
+
escaped = true;
|
|
1064
|
+
} else if (char === '"') {
|
|
1065
|
+
return text.slice(valueStart + 1, valueEnd);
|
|
1066
|
+
}
|
|
1067
|
+
valueEnd += 1;
|
|
1068
|
+
}
|
|
1069
|
+
return void 0;
|
|
1070
|
+
}
|
|
1071
|
+
function extractJsonValueSlice(text, valueStart) {
|
|
1072
|
+
if (valueStart >= text.length) {
|
|
1073
|
+
return null;
|
|
1074
|
+
}
|
|
1075
|
+
const first = text.charAt(valueStart);
|
|
1076
|
+
if (first === "{" || first === "[") {
|
|
1077
|
+
const stack = [first];
|
|
1078
|
+
let inString = false;
|
|
1079
|
+
let escaped = false;
|
|
1080
|
+
for (let index2 = valueStart + 1; index2 < text.length; index2 += 1) {
|
|
1081
|
+
const char = text.charAt(index2);
|
|
1082
|
+
if (inString) {
|
|
1083
|
+
if (escaped) {
|
|
1084
|
+
escaped = false;
|
|
1085
|
+
} else if (char === "\\") {
|
|
1086
|
+
escaped = true;
|
|
1087
|
+
} else if (char === '"') {
|
|
1088
|
+
inString = false;
|
|
1089
|
+
}
|
|
1090
|
+
continue;
|
|
1091
|
+
}
|
|
1092
|
+
if (char === '"') {
|
|
1093
|
+
inString = true;
|
|
1094
|
+
continue;
|
|
1095
|
+
}
|
|
1096
|
+
if (char === "{" || char === "[") {
|
|
1097
|
+
stack.push(char);
|
|
1098
|
+
continue;
|
|
1099
|
+
}
|
|
1100
|
+
if (char === "}" || char === "]") {
|
|
1101
|
+
const open = stack.at(-1);
|
|
1102
|
+
if (open === "{" && char === "}" || open === "[" && char === "]") {
|
|
1103
|
+
stack.pop();
|
|
1104
|
+
if (stack.length === 0) {
|
|
1105
|
+
return {
|
|
1106
|
+
text: text.slice(valueStart, index2 + 1),
|
|
1107
|
+
complete: true
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
return {
|
|
1114
|
+
text: text.slice(valueStart),
|
|
1115
|
+
complete: false
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
if (first === '"') {
|
|
1119
|
+
let escaped = false;
|
|
1120
|
+
for (let index2 = valueStart + 1; index2 < text.length; index2 += 1) {
|
|
1121
|
+
const char = text.charAt(index2);
|
|
1122
|
+
if (escaped) {
|
|
1123
|
+
escaped = false;
|
|
1124
|
+
} else if (char === "\\") {
|
|
1125
|
+
escaped = true;
|
|
1126
|
+
} else if (char === '"') {
|
|
1127
|
+
return {
|
|
1128
|
+
text: text.slice(valueStart, index2 + 1),
|
|
1129
|
+
complete: true
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
return {
|
|
1134
|
+
text: text.slice(valueStart),
|
|
1135
|
+
complete: false
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
let index = valueStart;
|
|
1139
|
+
while (index < text.length) {
|
|
1140
|
+
const char = text.charAt(index);
|
|
1141
|
+
if (char === "," || char === "}" || WHITESPACE_JSON_REGEX.test(char)) {
|
|
1142
|
+
break;
|
|
1143
|
+
}
|
|
1144
|
+
index += 1;
|
|
1145
|
+
}
|
|
1146
|
+
return {
|
|
1147
|
+
text: text.slice(valueStart, index),
|
|
1148
|
+
complete: index < text.length
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
function extractStreamingToolCallProgress(toolCallJson) {
|
|
1152
|
+
var _a;
|
|
1153
|
+
const toolName = extractTopLevelStringProperty(toolCallJson, "name");
|
|
1154
|
+
const argsValueStart = findTopLevelPropertyValueStart(
|
|
1155
|
+
toolCallJson,
|
|
1156
|
+
"arguments"
|
|
1157
|
+
);
|
|
1158
|
+
if (argsValueStart == null) {
|
|
1159
|
+
return {
|
|
1160
|
+
toolName,
|
|
1161
|
+
argumentsText: void 0,
|
|
1162
|
+
argumentsComplete: false
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1165
|
+
const argsSlice = extractJsonValueSlice(toolCallJson, argsValueStart);
|
|
1166
|
+
return {
|
|
1167
|
+
toolName,
|
|
1168
|
+
argumentsText: argsSlice == null ? void 0 : argsSlice.text,
|
|
1169
|
+
argumentsComplete: (_a = argsSlice == null ? void 0 : argsSlice.complete) != null ? _a : false
|
|
1170
|
+
};
|
|
1171
|
+
}
|
|
1172
|
+
function ensureToolInputStart(state, controller, toolName) {
|
|
1173
|
+
if (!state.activeToolInput) {
|
|
1174
|
+
const id = generateToolCallId();
|
|
1175
|
+
state.activeToolInput = {
|
|
1176
|
+
id,
|
|
1177
|
+
toolName,
|
|
1178
|
+
emittedInput: ""
|
|
1179
|
+
};
|
|
1180
|
+
controller.enqueue({
|
|
1181
|
+
type: "tool-input-start",
|
|
1182
|
+
id,
|
|
1183
|
+
toolName
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
function emitToolInputDelta(state, controller, fullInput) {
|
|
1188
|
+
const active = state.activeToolInput;
|
|
1189
|
+
if (!active) {
|
|
1190
|
+
return;
|
|
1191
|
+
}
|
|
1192
|
+
if (!fullInput.startsWith(active.emittedInput)) {
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
const delta = fullInput.slice(active.emittedInput.length);
|
|
1196
|
+
if (delta.length === 0) {
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
controller.enqueue({
|
|
1200
|
+
type: "tool-input-delta",
|
|
1201
|
+
id: active.id,
|
|
1202
|
+
delta
|
|
1203
|
+
});
|
|
1204
|
+
active.emittedInput = fullInput;
|
|
1205
|
+
}
|
|
1206
|
+
function closeToolInput(state, controller) {
|
|
1207
|
+
if (!state.activeToolInput) {
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
1210
|
+
controller.enqueue({
|
|
1211
|
+
type: "tool-input-end",
|
|
1212
|
+
id: state.activeToolInput.id
|
|
1213
|
+
});
|
|
1214
|
+
state.activeToolInput = null;
|
|
1215
|
+
}
|
|
1216
|
+
function emitToolCallFromParsed(state, controller, parsedToolCall) {
|
|
1217
|
+
var _a, _b, _c, _d;
|
|
1218
|
+
closeTextBlock(state, controller);
|
|
1219
|
+
const toolName = typeof parsedToolCall.name === "string" ? parsedToolCall.name : (_b = (_a = state.activeToolInput) == null ? void 0 : _a.toolName) != null ? _b : "unknown";
|
|
1220
|
+
const input = canonicalizeToolInput(parsedToolCall.arguments);
|
|
1221
|
+
ensureToolInputStart(state, controller, toolName);
|
|
1222
|
+
emitToolInputDelta(state, controller, input);
|
|
1223
|
+
const toolCallId = (_d = (_c = state.activeToolInput) == null ? void 0 : _c.id) != null ? _d : generateToolCallId();
|
|
1224
|
+
closeToolInput(state, controller);
|
|
1225
|
+
controller.enqueue({
|
|
1226
|
+
type: "tool-call",
|
|
1227
|
+
toolCallId,
|
|
1228
|
+
toolName,
|
|
1229
|
+
input
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
function canonicalizeArgumentsProgressInput(progress) {
|
|
1233
|
+
if (progress.argumentsText === void 0 || !progress.argumentsComplete) {
|
|
1234
|
+
return void 0;
|
|
1235
|
+
}
|
|
1236
|
+
try {
|
|
1237
|
+
const parsedArguments = parse(progress.argumentsText);
|
|
1238
|
+
return canonicalizeToolInput(parsedArguments);
|
|
1239
|
+
} catch (e) {
|
|
1240
|
+
return void 0;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
function emitToolInputProgress(state, controller) {
|
|
1244
|
+
if (!(state.isInsideToolCall && state.currentToolCallJson)) {
|
|
1245
|
+
return;
|
|
1246
|
+
}
|
|
1247
|
+
const progress = extractStreamingToolCallProgress(state.currentToolCallJson);
|
|
1248
|
+
if (!progress.toolName) {
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
ensureToolInputStart(state, controller, progress.toolName);
|
|
1252
|
+
const canonicalProgressInput = canonicalizeArgumentsProgressInput(progress);
|
|
1253
|
+
if (canonicalProgressInput !== void 0) {
|
|
1254
|
+
emitToolInputDelta(state, controller, canonicalProgressInput);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
904
1257
|
function flushBuffer(state, controller, toolCallStart) {
|
|
905
1258
|
if (state.buffer.length === 0) {
|
|
906
1259
|
return;
|
|
@@ -931,44 +1284,77 @@ function closeTextBlock(state, controller) {
|
|
|
931
1284
|
state.hasEmittedTextStart = false;
|
|
932
1285
|
}
|
|
933
1286
|
}
|
|
934
|
-
function emitIncompleteToolCall(state, controller, toolCallStart) {
|
|
935
|
-
|
|
1287
|
+
function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer, options) {
|
|
1288
|
+
var _a;
|
|
1289
|
+
if (!state.currentToolCallJson && trailingBuffer.length === 0) {
|
|
1290
|
+
state.isInsideToolCall = false;
|
|
936
1291
|
return;
|
|
937
1292
|
}
|
|
1293
|
+
if (state.currentToolCallJson) {
|
|
1294
|
+
try {
|
|
1295
|
+
const parsedToolCall = parse(state.currentToolCallJson);
|
|
1296
|
+
emitToolCallFromParsed(state, controller, parsedToolCall);
|
|
1297
|
+
state.currentToolCallJson = "";
|
|
1298
|
+
state.isInsideToolCall = false;
|
|
1299
|
+
return;
|
|
1300
|
+
} catch (e) {
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
const rawToolCallContent = `${state.currentToolCallJson}${trailingBuffer}`;
|
|
1304
|
+
const errorContent = `${toolCallStart}${rawToolCallContent}`;
|
|
1305
|
+
const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
|
|
938
1306
|
logParseFailure({
|
|
939
1307
|
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
|
|
1308
|
+
reason: shouldEmitRawFallback ? "Incomplete streaming tool call segment emitted as text" : "Incomplete streaming tool call segment suppressed without raw text fallback",
|
|
1309
|
+
snippet: errorContent
|
|
957
1310
|
});
|
|
1311
|
+
if (shouldEmitRawFallback) {
|
|
1312
|
+
const errorId = generateId();
|
|
1313
|
+
controller.enqueue({
|
|
1314
|
+
type: "text-start",
|
|
1315
|
+
id: errorId
|
|
1316
|
+
});
|
|
1317
|
+
controller.enqueue({
|
|
1318
|
+
type: "text-delta",
|
|
1319
|
+
id: errorId,
|
|
1320
|
+
delta: errorContent
|
|
1321
|
+
});
|
|
1322
|
+
controller.enqueue({
|
|
1323
|
+
type: "text-end",
|
|
1324
|
+
id: errorId
|
|
1325
|
+
});
|
|
1326
|
+
}
|
|
1327
|
+
closeToolInput(state, controller);
|
|
1328
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1329
|
+
options,
|
|
1330
|
+
shouldEmitRawFallback ? "Could not complete streaming JSON tool call at finish; emitting original text." : "Could not complete streaming JSON tool call at finish.",
|
|
1331
|
+
{ toolCall: errorContent }
|
|
1332
|
+
);
|
|
958
1333
|
state.currentToolCallJson = "";
|
|
1334
|
+
state.isInsideToolCall = false;
|
|
959
1335
|
}
|
|
960
|
-
function handleFinishChunk(state, controller, toolCallStart, chunk) {
|
|
961
|
-
if (state.
|
|
1336
|
+
function handleFinishChunk(state, controller, toolCallStart, options, chunk) {
|
|
1337
|
+
if (state.isInsideToolCall) {
|
|
1338
|
+
const trailingBuffer = state.buffer;
|
|
1339
|
+
state.buffer = "";
|
|
1340
|
+
emitIncompleteToolCall(
|
|
1341
|
+
state,
|
|
1342
|
+
controller,
|
|
1343
|
+
toolCallStart,
|
|
1344
|
+
trailingBuffer,
|
|
1345
|
+
options
|
|
1346
|
+
);
|
|
1347
|
+
} else if (state.buffer.length > 0) {
|
|
962
1348
|
flushBuffer(state, controller, toolCallStart);
|
|
963
1349
|
}
|
|
964
1350
|
closeTextBlock(state, controller);
|
|
965
|
-
emitIncompleteToolCall(state, controller, toolCallStart);
|
|
966
1351
|
controller.enqueue(chunk);
|
|
967
1352
|
}
|
|
968
1353
|
function publishText(text, state, controller) {
|
|
969
1354
|
if (state.isInsideToolCall) {
|
|
970
1355
|
closeTextBlock(state, controller);
|
|
971
1356
|
state.currentToolCallJson += text;
|
|
1357
|
+
emitToolInputProgress(state, controller);
|
|
972
1358
|
} else if (text.length > 0) {
|
|
973
1359
|
if (!state.currentTextId) {
|
|
974
1360
|
state.currentTextId = generateId();
|
|
@@ -986,42 +1372,40 @@ function publishText(text, state, controller) {
|
|
|
986
1372
|
}
|
|
987
1373
|
}
|
|
988
1374
|
function emitToolCall(context) {
|
|
989
|
-
var _a
|
|
1375
|
+
var _a;
|
|
990
1376
|
const { state, controller, toolCallStart, toolCallEnd, options } = context;
|
|
991
1377
|
try {
|
|
992
1378
|
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
|
-
});
|
|
1379
|
+
emitToolCallFromParsed(state, controller, parsedToolCall);
|
|
1000
1380
|
} catch (error) {
|
|
1381
|
+
const errorContent = `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`;
|
|
1382
|
+
const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
|
|
1001
1383
|
logParseFailure({
|
|
1002
1384
|
phase: "stream",
|
|
1003
1385
|
reason: "Failed to parse streaming tool call JSON segment",
|
|
1004
|
-
snippet:
|
|
1386
|
+
snippet: errorContent,
|
|
1005
1387
|
error
|
|
1006
1388
|
});
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1389
|
+
if (shouldEmitRawFallback) {
|
|
1390
|
+
const errorId = generateId();
|
|
1391
|
+
controller.enqueue({
|
|
1392
|
+
type: "text-start",
|
|
1393
|
+
id: errorId
|
|
1394
|
+
});
|
|
1395
|
+
controller.enqueue({
|
|
1396
|
+
type: "text-delta",
|
|
1397
|
+
id: errorId,
|
|
1398
|
+
delta: errorContent
|
|
1399
|
+
});
|
|
1400
|
+
controller.enqueue({
|
|
1401
|
+
type: "text-end",
|
|
1402
|
+
id: errorId
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
closeToolInput(state, controller);
|
|
1406
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1023
1407
|
options,
|
|
1024
|
-
"Could not process streaming JSON tool call; emitting original text.",
|
|
1408
|
+
shouldEmitRawFallback ? "Could not process streaming JSON tool call; emitting original text." : "Could not process streaming JSON tool call.",
|
|
1025
1409
|
{
|
|
1026
1410
|
toolCall: errorContent
|
|
1027
1411
|
}
|
|
@@ -1037,6 +1421,7 @@ function processTagMatch(context) {
|
|
|
1037
1421
|
} else {
|
|
1038
1422
|
state.currentToolCallJson = "";
|
|
1039
1423
|
state.isInsideToolCall = true;
|
|
1424
|
+
state.activeToolInput = null;
|
|
1040
1425
|
}
|
|
1041
1426
|
}
|
|
1042
1427
|
function processBufferTags(context) {
|
|
@@ -1059,8 +1444,16 @@ function processBufferTags(context) {
|
|
|
1059
1444
|
);
|
|
1060
1445
|
}
|
|
1061
1446
|
}
|
|
1062
|
-
function handlePartialTag(state, controller, toolCallStart) {
|
|
1447
|
+
function handlePartialTag(state, controller, toolCallStart, toolCallEnd) {
|
|
1063
1448
|
if (state.isInsideToolCall) {
|
|
1449
|
+
const potentialEndIndex = getPotentialStartIndex(state.buffer, toolCallEnd);
|
|
1450
|
+
if (potentialEndIndex != null && potentialEndIndex + toolCallEnd.length > state.buffer.length) {
|
|
1451
|
+
publishText(state.buffer.slice(0, potentialEndIndex), state, controller);
|
|
1452
|
+
state.buffer = state.buffer.slice(potentialEndIndex);
|
|
1453
|
+
} else {
|
|
1454
|
+
publishText(state.buffer, state, controller);
|
|
1455
|
+
state.buffer = "";
|
|
1456
|
+
}
|
|
1064
1457
|
return;
|
|
1065
1458
|
}
|
|
1066
1459
|
const potentialIndex = getPotentialStartIndex(state.buffer, toolCallStart);
|
|
@@ -1133,13 +1526,14 @@ var jsonProtocol = ({
|
|
|
1133
1526
|
buffer: "",
|
|
1134
1527
|
currentToolCallJson: "",
|
|
1135
1528
|
currentTextId: null,
|
|
1136
|
-
hasEmittedTextStart: false
|
|
1529
|
+
hasEmittedTextStart: false,
|
|
1530
|
+
activeToolInput: null
|
|
1137
1531
|
};
|
|
1138
1532
|
return new TransformStream({
|
|
1139
1533
|
transform(chunk, controller) {
|
|
1140
1534
|
var _a;
|
|
1141
1535
|
if (chunk.type === "finish") {
|
|
1142
|
-
handleFinishChunk(state, controller, toolCallStart, chunk);
|
|
1536
|
+
handleFinishChunk(state, controller, toolCallStart, options, chunk);
|
|
1143
1537
|
return;
|
|
1144
1538
|
}
|
|
1145
1539
|
if (chunk.type !== "text-delta") {
|
|
@@ -1155,7 +1549,7 @@ var jsonProtocol = ({
|
|
|
1155
1549
|
toolCallEnd,
|
|
1156
1550
|
options
|
|
1157
1551
|
});
|
|
1158
|
-
handlePartialTag(state, controller, toolCallStart);
|
|
1552
|
+
handlePartialTag(state, controller, toolCallStart, toolCallEnd);
|
|
1159
1553
|
}
|
|
1160
1554
|
});
|
|
1161
1555
|
},
|
|
@@ -1739,13 +2133,20 @@ function coerceStringWithoutSchema(value) {
|
|
|
1739
2133
|
}
|
|
1740
2134
|
function coerceStringToObject(s, unwrapped) {
|
|
1741
2135
|
try {
|
|
1742
|
-
|
|
1743
|
-
normalized = normalized.replace(EMPTY_OBJECT_REGEX, "{}");
|
|
1744
|
-
const obj = JSON.parse(normalized);
|
|
2136
|
+
const obj = JSON.parse(s);
|
|
1745
2137
|
if (obj && typeof obj === "object" && !Array.isArray(obj)) {
|
|
1746
2138
|
return coerceObjectToObject(obj, unwrapped);
|
|
1747
2139
|
}
|
|
1748
2140
|
} catch (e) {
|
|
2141
|
+
try {
|
|
2142
|
+
let normalized = s.replace(/'/g, '"');
|
|
2143
|
+
normalized = normalized.replace(EMPTY_OBJECT_REGEX, "{}");
|
|
2144
|
+
const obj = JSON.parse(normalized);
|
|
2145
|
+
if (obj && typeof obj === "object" && !Array.isArray(obj)) {
|
|
2146
|
+
return coerceObjectToObject(obj, unwrapped);
|
|
2147
|
+
}
|
|
2148
|
+
} catch (e2) {
|
|
2149
|
+
}
|
|
1749
2150
|
}
|
|
1750
2151
|
return null;
|
|
1751
2152
|
}
|
|
@@ -1753,8 +2154,7 @@ function coerceStringToArray(s, unwrapped) {
|
|
|
1753
2154
|
const prefixItems = Array.isArray(unwrapped.prefixItems) ? unwrapped.prefixItems : void 0;
|
|
1754
2155
|
const itemsSchema = unwrapped.items;
|
|
1755
2156
|
try {
|
|
1756
|
-
const
|
|
1757
|
-
const arr = JSON.parse(normalized);
|
|
2157
|
+
const arr = JSON.parse(s);
|
|
1758
2158
|
if (Array.isArray(arr)) {
|
|
1759
2159
|
if (prefixItems && arr.length === prefixItems.length) {
|
|
1760
2160
|
return arr.map((v, i) => coerceBySchema(v, prefixItems[i]));
|
|
@@ -1762,6 +2162,17 @@ function coerceStringToArray(s, unwrapped) {
|
|
|
1762
2162
|
return arr.map((v) => coerceBySchema(v, itemsSchema));
|
|
1763
2163
|
}
|
|
1764
2164
|
} catch (e) {
|
|
2165
|
+
try {
|
|
2166
|
+
const normalized = s.replace(/'/g, '"');
|
|
2167
|
+
const arr = JSON.parse(normalized);
|
|
2168
|
+
if (Array.isArray(arr)) {
|
|
2169
|
+
if (prefixItems && arr.length === prefixItems.length) {
|
|
2170
|
+
return arr.map((v, i) => coerceBySchema(v, prefixItems[i]));
|
|
2171
|
+
}
|
|
2172
|
+
return arr.map((v) => coerceBySchema(v, itemsSchema));
|
|
2173
|
+
}
|
|
2174
|
+
} catch (e2) {
|
|
2175
|
+
}
|
|
1765
2176
|
const csv = s.includes("\n") ? s.split(NEWLINE_SPLIT_REGEX) : s.split(COMMA_SPLIT_REGEX);
|
|
1766
2177
|
const trimmed = csv.map((x) => x.trim()).filter((x) => x.length > 0);
|
|
1767
2178
|
if (prefixItems && trimmed.length === prefixItems.length) {
|
|
@@ -4132,22 +4543,96 @@ function parse3(xml, schema, options = {}) {
|
|
|
4132
4543
|
var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
|
|
4133
4544
|
var WHITESPACE_REGEX5 = /\s/;
|
|
4134
4545
|
|
|
4135
|
-
// src/core/utils/
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
return null;
|
|
4546
|
+
// src/core/utils/streamed-tool-input-delta.ts
|
|
4547
|
+
function emitDelta({
|
|
4548
|
+
controller,
|
|
4549
|
+
id,
|
|
4550
|
+
state,
|
|
4551
|
+
nextInput
|
|
4552
|
+
}) {
|
|
4553
|
+
if (!nextInput.startsWith(state.emittedInput)) {
|
|
4554
|
+
return false;
|
|
4145
4555
|
}
|
|
4146
|
-
const
|
|
4147
|
-
if (
|
|
4148
|
-
return
|
|
4556
|
+
const delta = nextInput.slice(state.emittedInput.length);
|
|
4557
|
+
if (delta.length === 0) {
|
|
4558
|
+
return false;
|
|
4149
4559
|
}
|
|
4150
|
-
|
|
4560
|
+
controller.enqueue({
|
|
4561
|
+
type: "tool-input-delta",
|
|
4562
|
+
id,
|
|
4563
|
+
delta
|
|
4564
|
+
});
|
|
4565
|
+
state.emittedInput = nextInput;
|
|
4566
|
+
return true;
|
|
4567
|
+
}
|
|
4568
|
+
function toIncompleteJsonPrefix(fullJson) {
|
|
4569
|
+
const trimmed = fullJson.trim();
|
|
4570
|
+
let prefix = trimmed;
|
|
4571
|
+
while (prefix.endsWith("}") || prefix.endsWith("]")) {
|
|
4572
|
+
prefix = prefix.slice(0, -1);
|
|
4573
|
+
}
|
|
4574
|
+
prefix = prefix.trimEnd();
|
|
4575
|
+
if (prefix.endsWith('"')) {
|
|
4576
|
+
prefix = prefix.slice(0, -1);
|
|
4577
|
+
}
|
|
4578
|
+
if (prefix.length === 0) {
|
|
4579
|
+
if (trimmed.startsWith("[") || trimmed.startsWith("{")) {
|
|
4580
|
+
return trimmed.startsWith("{") ? "{" : "[";
|
|
4581
|
+
}
|
|
4582
|
+
if (trimmed.startsWith("]")) {
|
|
4583
|
+
return "[";
|
|
4584
|
+
}
|
|
4585
|
+
if (trimmed.startsWith("}")) {
|
|
4586
|
+
return "{";
|
|
4587
|
+
}
|
|
4588
|
+
if (trimmed.startsWith('"')) {
|
|
4589
|
+
return '"';
|
|
4590
|
+
}
|
|
4591
|
+
return "{";
|
|
4592
|
+
}
|
|
4593
|
+
return prefix;
|
|
4594
|
+
}
|
|
4595
|
+
function emitPrefixDelta(params) {
|
|
4596
|
+
return emitDelta({
|
|
4597
|
+
...params,
|
|
4598
|
+
nextInput: params.candidate
|
|
4599
|
+
});
|
|
4600
|
+
}
|
|
4601
|
+
function emitFinalRemainder(params) {
|
|
4602
|
+
var _a;
|
|
4603
|
+
const result = emitDelta({
|
|
4604
|
+
...params,
|
|
4605
|
+
nextInput: params.finalFullJson
|
|
4606
|
+
});
|
|
4607
|
+
if (!result && params.state.emittedInput.length > 0) {
|
|
4608
|
+
(_a = params.onMismatch) == null ? void 0 : _a.call(
|
|
4609
|
+
params,
|
|
4610
|
+
"Final JSON does not extend emitted tool-input prefix",
|
|
4611
|
+
{
|
|
4612
|
+
emittedLength: params.state.emittedInput.length,
|
|
4613
|
+
finalLength: params.finalFullJson.length
|
|
4614
|
+
}
|
|
4615
|
+
);
|
|
4616
|
+
}
|
|
4617
|
+
return result;
|
|
4618
|
+
}
|
|
4619
|
+
|
|
4620
|
+
// src/core/utils/xml-root-repair.ts
|
|
4621
|
+
var XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX = /^<([A-Za-z_][A-Za-z0-9_-]*)\s*\r?\n([\s\S]+?)\r?\n\s*\/>\s*$/;
|
|
4622
|
+
function tryRepairXmlSelfClosingRootWithBody(rawText, toolNames) {
|
|
4623
|
+
const trimmed = rawText.trim();
|
|
4624
|
+
if (trimmed.length === 0) {
|
|
4625
|
+
return null;
|
|
4626
|
+
}
|
|
4627
|
+
const match = trimmed.match(XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX);
|
|
4628
|
+
if (!match) {
|
|
4629
|
+
return null;
|
|
4630
|
+
}
|
|
4631
|
+
const rootTag = match[1];
|
|
4632
|
+
if (!toolNames.includes(rootTag)) {
|
|
4633
|
+
return null;
|
|
4634
|
+
}
|
|
4635
|
+
const body = match[2].trimEnd();
|
|
4151
4636
|
if (body.trim().length === 0 || body.includes(`</${rootTag}>`)) {
|
|
4152
4637
|
return null;
|
|
4153
4638
|
}
|
|
@@ -4161,6 +4646,9 @@ function getToolSchema(tools, toolName) {
|
|
|
4161
4646
|
var _a;
|
|
4162
4647
|
return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
4163
4648
|
}
|
|
4649
|
+
function shouldEmitRawToolCallTextOnError2(options) {
|
|
4650
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
4651
|
+
}
|
|
4164
4652
|
function processToolCall(params) {
|
|
4165
4653
|
var _a, _b;
|
|
4166
4654
|
const { toolCall, tools, options, text, processedElements, parseOptions } = params;
|
|
@@ -4173,7 +4661,7 @@ function processToolCall(params) {
|
|
|
4173
4661
|
const parsed = parse3(toolCall.content, toolSchema, parseConfig);
|
|
4174
4662
|
processedElements.push({
|
|
4175
4663
|
type: "tool-call",
|
|
4176
|
-
toolCallId:
|
|
4664
|
+
toolCallId: generateToolCallId(),
|
|
4177
4665
|
toolName: toolCall.toolName,
|
|
4178
4666
|
input: JSON.stringify(parsed)
|
|
4179
4667
|
});
|
|
@@ -4190,6 +4678,299 @@ function processToolCall(params) {
|
|
|
4190
4678
|
processedElements.push({ type: "text", text: originalCallText });
|
|
4191
4679
|
}
|
|
4192
4680
|
}
|
|
4681
|
+
function parseXmlTagName(rawTagBody) {
|
|
4682
|
+
let index = 0;
|
|
4683
|
+
while (index < rawTagBody.length && WHITESPACE_REGEX5.test(rawTagBody[index])) {
|
|
4684
|
+
index += 1;
|
|
4685
|
+
}
|
|
4686
|
+
const nameStart = index;
|
|
4687
|
+
while (index < rawTagBody.length && NAME_CHAR_RE2.test(rawTagBody.charAt(index))) {
|
|
4688
|
+
index += 1;
|
|
4689
|
+
}
|
|
4690
|
+
return rawTagBody.slice(nameStart, index);
|
|
4691
|
+
}
|
|
4692
|
+
function consumeXmlSpecialSection(fragment, ltIndex) {
|
|
4693
|
+
if (fragment.startsWith("<!--", ltIndex)) {
|
|
4694
|
+
const commentEnd = fragment.indexOf("-->", ltIndex + 4);
|
|
4695
|
+
return commentEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: commentEnd + 3 };
|
|
4696
|
+
}
|
|
4697
|
+
if (fragment.startsWith("<![CDATA[", ltIndex)) {
|
|
4698
|
+
const cdataEnd = fragment.indexOf("]]>", ltIndex + 9);
|
|
4699
|
+
return cdataEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: cdataEnd + 3 };
|
|
4700
|
+
}
|
|
4701
|
+
if (fragment.startsWith("<?", ltIndex)) {
|
|
4702
|
+
const processingEnd = fragment.indexOf("?>", ltIndex + 2);
|
|
4703
|
+
return processingEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: processingEnd + 2 };
|
|
4704
|
+
}
|
|
4705
|
+
if (fragment.startsWith("<!", ltIndex)) {
|
|
4706
|
+
const declarationEnd = fragment.indexOf(">", ltIndex + 2);
|
|
4707
|
+
return declarationEnd === -1 ? { kind: "incomplete" } : { kind: "consumed", nextPos: declarationEnd + 1 };
|
|
4708
|
+
}
|
|
4709
|
+
return { kind: "none" };
|
|
4710
|
+
}
|
|
4711
|
+
function parseXmlTagToken(fragment, ltIndex) {
|
|
4712
|
+
const gtIndex = fragment.indexOf(">", ltIndex + 1);
|
|
4713
|
+
if (gtIndex === -1) {
|
|
4714
|
+
return null;
|
|
4715
|
+
}
|
|
4716
|
+
const tagBody = fragment.slice(ltIndex + 1, gtIndex).trim();
|
|
4717
|
+
if (tagBody.length === 0) {
|
|
4718
|
+
return null;
|
|
4719
|
+
}
|
|
4720
|
+
if (tagBody.startsWith("/")) {
|
|
4721
|
+
const closeName = parseXmlTagName(tagBody.slice(1));
|
|
4722
|
+
if (closeName.length === 0) {
|
|
4723
|
+
return null;
|
|
4724
|
+
}
|
|
4725
|
+
return { kind: "close", name: closeName, nextPos: gtIndex + 1 };
|
|
4726
|
+
}
|
|
4727
|
+
const selfClosing = tagBody.endsWith("/");
|
|
4728
|
+
const openBody = selfClosing ? tagBody.slice(0, -1).trimEnd() : tagBody;
|
|
4729
|
+
const openName = parseXmlTagName(openBody);
|
|
4730
|
+
if (openName.length === 0) {
|
|
4731
|
+
return null;
|
|
4732
|
+
}
|
|
4733
|
+
return {
|
|
4734
|
+
kind: "open",
|
|
4735
|
+
name: openName,
|
|
4736
|
+
selfClosing,
|
|
4737
|
+
nextPos: gtIndex + 1
|
|
4738
|
+
};
|
|
4739
|
+
}
|
|
4740
|
+
function analyzeXmlFragmentForProgress(fragment) {
|
|
4741
|
+
const stack = [];
|
|
4742
|
+
const topLevelTagNames = [];
|
|
4743
|
+
let position = 0;
|
|
4744
|
+
while (position < fragment.length) {
|
|
4745
|
+
const ltIndex = fragment.indexOf("<", position);
|
|
4746
|
+
if (ltIndex === -1) {
|
|
4747
|
+
break;
|
|
4748
|
+
}
|
|
4749
|
+
const special = consumeXmlSpecialSection(fragment, ltIndex);
|
|
4750
|
+
if (special.kind === "incomplete") {
|
|
4751
|
+
return null;
|
|
4752
|
+
}
|
|
4753
|
+
if (special.kind === "consumed") {
|
|
4754
|
+
position = special.nextPos;
|
|
4755
|
+
continue;
|
|
4756
|
+
}
|
|
4757
|
+
const token = parseXmlTagToken(fragment, ltIndex);
|
|
4758
|
+
if (token === null) {
|
|
4759
|
+
return null;
|
|
4760
|
+
}
|
|
4761
|
+
if (token.kind === "close") {
|
|
4762
|
+
const openName = stack.pop();
|
|
4763
|
+
if (!openName || openName !== token.name) {
|
|
4764
|
+
return null;
|
|
4765
|
+
}
|
|
4766
|
+
position = token.nextPos;
|
|
4767
|
+
continue;
|
|
4768
|
+
}
|
|
4769
|
+
if (stack.length === 0) {
|
|
4770
|
+
topLevelTagNames.push(token.name);
|
|
4771
|
+
}
|
|
4772
|
+
if (!token.selfClosing) {
|
|
4773
|
+
stack.push(token.name);
|
|
4774
|
+
}
|
|
4775
|
+
position = token.nextPos;
|
|
4776
|
+
}
|
|
4777
|
+
if (stack.length > 0) {
|
|
4778
|
+
return null;
|
|
4779
|
+
}
|
|
4780
|
+
return { topLevelTagNames };
|
|
4781
|
+
}
|
|
4782
|
+
function scanXmlFragmentTopLevelTextStep(options) {
|
|
4783
|
+
const { fragment, position, stack } = options;
|
|
4784
|
+
const ltIndex = fragment.indexOf("<", position);
|
|
4785
|
+
if (ltIndex === -1) {
|
|
4786
|
+
const trailingText = fragment.slice(position);
|
|
4787
|
+
return {
|
|
4788
|
+
kind: "done",
|
|
4789
|
+
value: stack.length === 0 && trailingText.trim().length > 0
|
|
4790
|
+
};
|
|
4791
|
+
}
|
|
4792
|
+
const textBetweenTags = fragment.slice(position, ltIndex);
|
|
4793
|
+
if (stack.length === 0 && textBetweenTags.trim().length > 0) {
|
|
4794
|
+
return { kind: "found" };
|
|
4795
|
+
}
|
|
4796
|
+
const special = consumeXmlSpecialSection(fragment, ltIndex);
|
|
4797
|
+
if (special.kind === "incomplete") {
|
|
4798
|
+
return { kind: "invalid" };
|
|
4799
|
+
}
|
|
4800
|
+
if (special.kind === "consumed") {
|
|
4801
|
+
return { kind: "next", nextPos: special.nextPos };
|
|
4802
|
+
}
|
|
4803
|
+
const token = parseXmlTagToken(fragment, ltIndex);
|
|
4804
|
+
if (token === null) {
|
|
4805
|
+
return { kind: "invalid" };
|
|
4806
|
+
}
|
|
4807
|
+
if (token.kind === "close") {
|
|
4808
|
+
const openName = stack.pop();
|
|
4809
|
+
if (!openName || openName !== token.name) {
|
|
4810
|
+
return { kind: "invalid" };
|
|
4811
|
+
}
|
|
4812
|
+
} else if (!token.selfClosing) {
|
|
4813
|
+
stack.push(token.name);
|
|
4814
|
+
}
|
|
4815
|
+
return { kind: "next", nextPos: token.nextPos };
|
|
4816
|
+
}
|
|
4817
|
+
function hasNonWhitespaceTopLevelText(fragment) {
|
|
4818
|
+
if (!fragment.includes("<")) {
|
|
4819
|
+
return fragment.trim().length > 0;
|
|
4820
|
+
}
|
|
4821
|
+
const stack = [];
|
|
4822
|
+
let position = 0;
|
|
4823
|
+
while (position < fragment.length) {
|
|
4824
|
+
const step = scanXmlFragmentTopLevelTextStep({ fragment, position, stack });
|
|
4825
|
+
if (step.kind === "found") {
|
|
4826
|
+
return true;
|
|
4827
|
+
}
|
|
4828
|
+
if (step.kind === "invalid") {
|
|
4829
|
+
return false;
|
|
4830
|
+
}
|
|
4831
|
+
if (step.kind === "done") {
|
|
4832
|
+
return step.value;
|
|
4833
|
+
}
|
|
4834
|
+
position = step.nextPos;
|
|
4835
|
+
}
|
|
4836
|
+
return false;
|
|
4837
|
+
}
|
|
4838
|
+
function getObjectSchemaPropertyNames(schema) {
|
|
4839
|
+
if (!schema || typeof schema !== "object") {
|
|
4840
|
+
return null;
|
|
4841
|
+
}
|
|
4842
|
+
const schemaObject = schema;
|
|
4843
|
+
const typeValue = schemaObject.type;
|
|
4844
|
+
if (typeValue != null) {
|
|
4845
|
+
const isObjectType = typeValue === "object" || Array.isArray(typeValue) && typeValue.includes("object");
|
|
4846
|
+
if (!isObjectType) {
|
|
4847
|
+
return null;
|
|
4848
|
+
}
|
|
4849
|
+
}
|
|
4850
|
+
if (!schemaObject.properties || typeof schemaObject.properties !== "object") {
|
|
4851
|
+
return /* @__PURE__ */ new Set();
|
|
4852
|
+
}
|
|
4853
|
+
return new Set(
|
|
4854
|
+
Object.keys(schemaObject.properties)
|
|
4855
|
+
);
|
|
4856
|
+
}
|
|
4857
|
+
function schemaAllowsArrayType(schema) {
|
|
4858
|
+
if (!schema || typeof schema !== "object") {
|
|
4859
|
+
return false;
|
|
4860
|
+
}
|
|
4861
|
+
const schemaRecord = schema;
|
|
4862
|
+
const typeValue = schemaRecord.type;
|
|
4863
|
+
if (typeValue === "array") {
|
|
4864
|
+
return true;
|
|
4865
|
+
}
|
|
4866
|
+
if (Array.isArray(typeValue) && typeValue.includes("array")) {
|
|
4867
|
+
return true;
|
|
4868
|
+
}
|
|
4869
|
+
const unions = [schemaRecord.anyOf, schemaRecord.oneOf, schemaRecord.allOf];
|
|
4870
|
+
for (const union of unions) {
|
|
4871
|
+
if (!Array.isArray(union)) {
|
|
4872
|
+
continue;
|
|
4873
|
+
}
|
|
4874
|
+
if (union.some((entry) => schemaAllowsArrayType(entry))) {
|
|
4875
|
+
return true;
|
|
4876
|
+
}
|
|
4877
|
+
}
|
|
4878
|
+
return false;
|
|
4879
|
+
}
|
|
4880
|
+
function getSchemaObjectProperty(schema, propertyName) {
|
|
4881
|
+
if (!schema || typeof schema !== "object") {
|
|
4882
|
+
return null;
|
|
4883
|
+
}
|
|
4884
|
+
const schemaObject = schema;
|
|
4885
|
+
const properties = schemaObject.properties;
|
|
4886
|
+
if (!properties || typeof properties !== "object") {
|
|
4887
|
+
return null;
|
|
4888
|
+
}
|
|
4889
|
+
const property = properties[propertyName];
|
|
4890
|
+
if (!property) {
|
|
4891
|
+
return null;
|
|
4892
|
+
}
|
|
4893
|
+
return property;
|
|
4894
|
+
}
|
|
4895
|
+
function isStableXmlProgressCandidate(options) {
|
|
4896
|
+
const { candidate, parsed, toolSchema } = options;
|
|
4897
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4898
|
+
return false;
|
|
4899
|
+
}
|
|
4900
|
+
const structure = analyzeXmlFragmentForProgress(candidate);
|
|
4901
|
+
if (!structure) {
|
|
4902
|
+
return false;
|
|
4903
|
+
}
|
|
4904
|
+
const schemaProperties = getObjectSchemaPropertyNames(toolSchema);
|
|
4905
|
+
if (!schemaProperties || schemaProperties.size === 0) {
|
|
4906
|
+
return false;
|
|
4907
|
+
}
|
|
4908
|
+
const parsedObject = parsed;
|
|
4909
|
+
const uniqueTopLevelTags = new Set(structure.topLevelTagNames);
|
|
4910
|
+
for (const tagName of uniqueTopLevelTags) {
|
|
4911
|
+
if (!schemaProperties.has(tagName)) {
|
|
4912
|
+
continue;
|
|
4913
|
+
}
|
|
4914
|
+
const schemaProperty = getSchemaObjectProperty(toolSchema, tagName);
|
|
4915
|
+
if (schemaProperty && schemaAllowsArrayType(schemaProperty) && !Array.isArray(parsedObject[tagName])) {
|
|
4916
|
+
return false;
|
|
4917
|
+
}
|
|
4918
|
+
}
|
|
4919
|
+
if (structure.topLevelTagNames.length === 1) {
|
|
4920
|
+
const onlyTopLevelTag = structure.topLevelTagNames[0];
|
|
4921
|
+
if (!schemaProperties || schemaProperties.size === 0 || !schemaProperties.has(onlyTopLevelTag)) {
|
|
4922
|
+
return false;
|
|
4923
|
+
}
|
|
4924
|
+
}
|
|
4925
|
+
return true;
|
|
4926
|
+
}
|
|
4927
|
+
function parseXmlContentForStreamProgress({
|
|
4928
|
+
toolContent,
|
|
4929
|
+
toolSchema,
|
|
4930
|
+
parseOptions
|
|
4931
|
+
}) {
|
|
4932
|
+
const tryParse = (content) => {
|
|
4933
|
+
try {
|
|
4934
|
+
return parse3(content, toolSchema, {
|
|
4935
|
+
...parseOptions != null ? parseOptions : {},
|
|
4936
|
+
repair: false,
|
|
4937
|
+
onError: void 0
|
|
4938
|
+
});
|
|
4939
|
+
} catch (e) {
|
|
4940
|
+
return null;
|
|
4941
|
+
}
|
|
4942
|
+
};
|
|
4943
|
+
const strictFull = tryParse(toolContent);
|
|
4944
|
+
if (strictFull !== null && isStableXmlProgressCandidate({
|
|
4945
|
+
candidate: toolContent,
|
|
4946
|
+
parsed: strictFull,
|
|
4947
|
+
toolSchema
|
|
4948
|
+
})) {
|
|
4949
|
+
return JSON.stringify(strictFull);
|
|
4950
|
+
}
|
|
4951
|
+
let searchEnd = toolContent.length;
|
|
4952
|
+
while (searchEnd > 0) {
|
|
4953
|
+
const gtIndex = toolContent.lastIndexOf(">", searchEnd - 1);
|
|
4954
|
+
if (gtIndex === -1) {
|
|
4955
|
+
break;
|
|
4956
|
+
}
|
|
4957
|
+
const candidate = toolContent.slice(0, gtIndex + 1);
|
|
4958
|
+
if (!analyzeXmlFragmentForProgress(candidate)) {
|
|
4959
|
+
searchEnd = gtIndex;
|
|
4960
|
+
continue;
|
|
4961
|
+
}
|
|
4962
|
+
const parsedCandidate = tryParse(candidate);
|
|
4963
|
+
if (parsedCandidate !== null && isStableXmlProgressCandidate({
|
|
4964
|
+
candidate,
|
|
4965
|
+
parsed: parsedCandidate,
|
|
4966
|
+
toolSchema
|
|
4967
|
+
})) {
|
|
4968
|
+
return JSON.stringify(parsedCandidate);
|
|
4969
|
+
}
|
|
4970
|
+
searchEnd = gtIndex;
|
|
4971
|
+
}
|
|
4972
|
+
return null;
|
|
4973
|
+
}
|
|
4193
4974
|
function handleStreamingToolCallEnd(params) {
|
|
4194
4975
|
var _a, _b;
|
|
4195
4976
|
const {
|
|
@@ -4209,19 +4990,37 @@ function handleStreamingToolCallEnd(params) {
|
|
|
4209
4990
|
flushText(ctrl);
|
|
4210
4991
|
try {
|
|
4211
4992
|
const parsedResult = parse3(toolContent, toolSchema, parseConfig);
|
|
4993
|
+
const finalInput = JSON.stringify(parsedResult);
|
|
4994
|
+
emitFinalRemainder({
|
|
4995
|
+
controller: ctrl,
|
|
4996
|
+
id: currentToolCall.toolCallId,
|
|
4997
|
+
state: currentToolCall,
|
|
4998
|
+
finalFullJson: finalInput,
|
|
4999
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
5000
|
+
});
|
|
5001
|
+
ctrl.enqueue({
|
|
5002
|
+
type: "tool-input-end",
|
|
5003
|
+
id: currentToolCall.toolCallId
|
|
5004
|
+
});
|
|
4212
5005
|
ctrl.enqueue({
|
|
4213
5006
|
type: "tool-call",
|
|
4214
|
-
toolCallId:
|
|
5007
|
+
toolCallId: currentToolCall.toolCallId,
|
|
4215
5008
|
toolName: currentToolCall.name,
|
|
4216
|
-
input:
|
|
5009
|
+
input: finalInput
|
|
4217
5010
|
});
|
|
4218
5011
|
} catch (error) {
|
|
5012
|
+
ctrl.enqueue({
|
|
5013
|
+
type: "tool-input-end",
|
|
5014
|
+
id: currentToolCall.toolCallId
|
|
5015
|
+
});
|
|
4219
5016
|
const original = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
|
|
4220
5017
|
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
|
|
4221
5018
|
toolCall: original,
|
|
4222
5019
|
error
|
|
4223
5020
|
});
|
|
4224
|
-
|
|
5021
|
+
if (shouldEmitRawToolCallTextOnError2(options)) {
|
|
5022
|
+
flushText(ctrl, original);
|
|
5023
|
+
}
|
|
4225
5024
|
}
|
|
4226
5025
|
}
|
|
4227
5026
|
function findClosingTagEndFlexible(text, contentStart, toolName) {
|
|
@@ -4643,38 +5442,6 @@ function findPotentialToolTagStart(buffer, toolNames) {
|
|
|
4643
5442
|
}
|
|
4644
5443
|
return -1;
|
|
4645
5444
|
}
|
|
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
5445
|
function processToolCallInBuffer(params) {
|
|
4679
5446
|
const {
|
|
4680
5447
|
buffer,
|
|
@@ -4684,18 +5451,21 @@ function processToolCallInBuffer(params) {
|
|
|
4684
5451
|
controller,
|
|
4685
5452
|
flushText,
|
|
4686
5453
|
setBuffer,
|
|
4687
|
-
parseOptions
|
|
5454
|
+
parseOptions,
|
|
5455
|
+
emitToolInputProgress: emitToolInputProgress2
|
|
4688
5456
|
} = params;
|
|
4689
5457
|
const endTagPattern = new RegExp(
|
|
4690
5458
|
`</\\s*${escapeRegExp(currentToolCall.name)}\\s*>`
|
|
4691
5459
|
);
|
|
4692
5460
|
const endMatch = endTagPattern.exec(buffer);
|
|
4693
5461
|
if (!endMatch || endMatch.index === void 0) {
|
|
5462
|
+
emitToolInputProgress2(controller, currentToolCall, buffer);
|
|
4694
5463
|
return { buffer, currentToolCall, shouldBreak: true };
|
|
4695
5464
|
}
|
|
4696
5465
|
const endIdx = endMatch.index;
|
|
4697
5466
|
const endPos = endIdx + endMatch[0].length;
|
|
4698
5467
|
const content = buffer.substring(0, endIdx);
|
|
5468
|
+
emitToolInputProgress2(controller, currentToolCall, content);
|
|
4699
5469
|
const remainder = buffer.substring(endPos);
|
|
4700
5470
|
setBuffer(remainder);
|
|
4701
5471
|
handleStreamingToolCallEnd({
|
|
@@ -4722,7 +5492,8 @@ function processNoToolCallInBuffer(params) {
|
|
|
4722
5492
|
tools,
|
|
4723
5493
|
options,
|
|
4724
5494
|
parseOptions,
|
|
4725
|
-
setBuffer
|
|
5495
|
+
setBuffer,
|
|
5496
|
+
emitToolInputStart
|
|
4726
5497
|
} = params;
|
|
4727
5498
|
const {
|
|
4728
5499
|
index: earliestStartTagIndex,
|
|
@@ -4752,9 +5523,10 @@ function processNoToolCallInBuffer(params) {
|
|
|
4752
5523
|
if (selfClosing) {
|
|
4753
5524
|
const newBuffer2 = buffer.substring(earliestStartTagIndex + tagLength);
|
|
4754
5525
|
setBuffer(newBuffer2);
|
|
5526
|
+
const currentToolCall = emitToolInputStart(controller, earliestToolName);
|
|
4755
5527
|
handleStreamingToolCallEnd({
|
|
4756
5528
|
toolContent: "",
|
|
4757
|
-
currentToolCall
|
|
5529
|
+
currentToolCall,
|
|
4758
5530
|
tools,
|
|
4759
5531
|
options,
|
|
4760
5532
|
ctrl: controller,
|
|
@@ -4773,12 +5545,12 @@ function processNoToolCallInBuffer(params) {
|
|
|
4773
5545
|
setBuffer(newBuffer);
|
|
4774
5546
|
return {
|
|
4775
5547
|
buffer: newBuffer,
|
|
4776
|
-
currentToolCall:
|
|
5548
|
+
currentToolCall: emitToolInputStart(controller, earliestToolName),
|
|
4777
5549
|
shouldBreak: false,
|
|
4778
5550
|
shouldContinue: true
|
|
4779
5551
|
};
|
|
4780
5552
|
}
|
|
4781
|
-
function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions) {
|
|
5553
|
+
function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions, emitToolInputProgress2, emitToolInputStart) {
|
|
4782
5554
|
return (controller) => {
|
|
4783
5555
|
while (true) {
|
|
4784
5556
|
const currentToolCall = getCurrentToolCall();
|
|
@@ -4791,7 +5563,8 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
4791
5563
|
controller,
|
|
4792
5564
|
flushText,
|
|
4793
5565
|
setBuffer,
|
|
4794
|
-
parseOptions
|
|
5566
|
+
parseOptions,
|
|
5567
|
+
emitToolInputProgress: emitToolInputProgress2
|
|
4795
5568
|
});
|
|
4796
5569
|
setBuffer(result.buffer);
|
|
4797
5570
|
setCurrentToolCall(result.currentToolCall);
|
|
@@ -4807,7 +5580,8 @@ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, se
|
|
|
4807
5580
|
tools,
|
|
4808
5581
|
options,
|
|
4809
5582
|
parseOptions,
|
|
4810
|
-
setBuffer
|
|
5583
|
+
setBuffer,
|
|
5584
|
+
emitToolInputStart
|
|
4811
5585
|
});
|
|
4812
5586
|
setBuffer(result.buffer);
|
|
4813
5587
|
setCurrentToolCall(result.currentToolCall);
|
|
@@ -4921,6 +5695,118 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4921
5695
|
hasEmittedTextStart = value;
|
|
4922
5696
|
}
|
|
4923
5697
|
);
|
|
5698
|
+
const emitToolInputStart = (controller, toolName) => {
|
|
5699
|
+
flushText(controller);
|
|
5700
|
+
const next = {
|
|
5701
|
+
name: toolName,
|
|
5702
|
+
toolCallId: generateToolCallId(),
|
|
5703
|
+
emittedInput: "",
|
|
5704
|
+
lastProgressGtIndex: null,
|
|
5705
|
+
lastProgressFullInput: null
|
|
5706
|
+
};
|
|
5707
|
+
controller.enqueue({
|
|
5708
|
+
type: "tool-input-start",
|
|
5709
|
+
id: next.toolCallId,
|
|
5710
|
+
toolName
|
|
5711
|
+
});
|
|
5712
|
+
return next;
|
|
5713
|
+
};
|
|
5714
|
+
const emitToolInputProgress2 = (controller, toolCall, toolContent) => {
|
|
5715
|
+
const progressGtIndex = toolContent.lastIndexOf(">");
|
|
5716
|
+
if (toolCall.lastProgressGtIndex === progressGtIndex) {
|
|
5717
|
+
const cached = toolCall.lastProgressFullInput;
|
|
5718
|
+
if (cached == null) {
|
|
5719
|
+
return;
|
|
5720
|
+
}
|
|
5721
|
+
if (cached === "{}" && toolContent.trim().length === 0) {
|
|
5722
|
+
return;
|
|
5723
|
+
}
|
|
5724
|
+
const prefixCandidate2 = toIncompleteJsonPrefix(cached);
|
|
5725
|
+
emitPrefixDelta({
|
|
5726
|
+
controller,
|
|
5727
|
+
id: toolCall.toolCallId,
|
|
5728
|
+
state: toolCall,
|
|
5729
|
+
candidate: prefixCandidate2
|
|
5730
|
+
});
|
|
5731
|
+
return;
|
|
5732
|
+
}
|
|
5733
|
+
const toolSchema = getToolSchema(tools, toolCall.name);
|
|
5734
|
+
const fullInput = parseXmlContentForStreamProgress({
|
|
5735
|
+
toolContent,
|
|
5736
|
+
toolSchema,
|
|
5737
|
+
parseOptions
|
|
5738
|
+
});
|
|
5739
|
+
toolCall.lastProgressGtIndex = progressGtIndex;
|
|
5740
|
+
toolCall.lastProgressFullInput = fullInput;
|
|
5741
|
+
if (fullInput == null) {
|
|
5742
|
+
return;
|
|
5743
|
+
}
|
|
5744
|
+
if (fullInput === "{}" && toolContent.trim().length === 0) {
|
|
5745
|
+
return;
|
|
5746
|
+
}
|
|
5747
|
+
const prefixCandidate = toIncompleteJsonPrefix(fullInput);
|
|
5748
|
+
emitPrefixDelta({
|
|
5749
|
+
controller,
|
|
5750
|
+
id: toolCall.toolCallId,
|
|
5751
|
+
state: toolCall,
|
|
5752
|
+
candidate: prefixCandidate
|
|
5753
|
+
});
|
|
5754
|
+
};
|
|
5755
|
+
const finalizeUnclosedToolCall = (controller) => {
|
|
5756
|
+
var _a2, _b;
|
|
5757
|
+
if (!currentToolCall) {
|
|
5758
|
+
return;
|
|
5759
|
+
}
|
|
5760
|
+
emitToolInputProgress2(controller, currentToolCall, buffer);
|
|
5761
|
+
const parseConfig = {
|
|
5762
|
+
...parseOptions,
|
|
5763
|
+
onError: (_a2 = options == null ? void 0 : options.onError) != null ? _a2 : parseOptions == null ? void 0 : parseOptions.onError
|
|
5764
|
+
};
|
|
5765
|
+
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
5766
|
+
flushText(controller);
|
|
5767
|
+
try {
|
|
5768
|
+
if (hasNonWhitespaceTopLevelText(buffer)) {
|
|
5769
|
+
throw new Error(
|
|
5770
|
+
"Cannot reconcile unclosed XML tool call with top-level plain text."
|
|
5771
|
+
);
|
|
5772
|
+
}
|
|
5773
|
+
const parsedResult = parse3(buffer, toolSchema, parseConfig);
|
|
5774
|
+
const finalInput = JSON.stringify(parsedResult);
|
|
5775
|
+
emitFinalRemainder({
|
|
5776
|
+
controller,
|
|
5777
|
+
id: currentToolCall.toolCallId,
|
|
5778
|
+
state: currentToolCall,
|
|
5779
|
+
finalFullJson: finalInput,
|
|
5780
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
5781
|
+
});
|
|
5782
|
+
controller.enqueue({
|
|
5783
|
+
type: "tool-input-end",
|
|
5784
|
+
id: currentToolCall.toolCallId
|
|
5785
|
+
});
|
|
5786
|
+
controller.enqueue({
|
|
5787
|
+
type: "tool-call",
|
|
5788
|
+
toolCallId: currentToolCall.toolCallId,
|
|
5789
|
+
toolName: currentToolCall.name,
|
|
5790
|
+
input: finalInput
|
|
5791
|
+
});
|
|
5792
|
+
} catch (error) {
|
|
5793
|
+
controller.enqueue({
|
|
5794
|
+
type: "tool-input-end",
|
|
5795
|
+
id: currentToolCall.toolCallId
|
|
5796
|
+
});
|
|
5797
|
+
const unfinishedContent = `<${currentToolCall.name}>${buffer}`;
|
|
5798
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
5799
|
+
options,
|
|
5800
|
+
"Could not complete streaming XML tool call at finish.",
|
|
5801
|
+
{ toolCall: unfinishedContent, error }
|
|
5802
|
+
);
|
|
5803
|
+
if (shouldEmitRawToolCallTextOnError2(options)) {
|
|
5804
|
+
flushText(controller, unfinishedContent);
|
|
5805
|
+
}
|
|
5806
|
+
}
|
|
5807
|
+
buffer = "";
|
|
5808
|
+
currentToolCall = null;
|
|
5809
|
+
};
|
|
4924
5810
|
const processBuffer = createProcessBufferHandler(
|
|
4925
5811
|
() => buffer,
|
|
4926
5812
|
(newBuffer) => {
|
|
@@ -4934,17 +5820,17 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4934
5820
|
options,
|
|
4935
5821
|
toolNames,
|
|
4936
5822
|
flushText,
|
|
4937
|
-
parseOptions
|
|
5823
|
+
parseOptions,
|
|
5824
|
+
emitToolInputProgress2,
|
|
5825
|
+
emitToolInputStart
|
|
4938
5826
|
);
|
|
4939
5827
|
return new TransformStream({
|
|
5828
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Stateful stream parsing requires branching over chunk lifecycle and parser states.
|
|
4940
5829
|
transform(chunk, controller) {
|
|
4941
5830
|
var _a2;
|
|
4942
5831
|
if (chunk.type === "finish") {
|
|
4943
5832
|
if (currentToolCall) {
|
|
4944
|
-
|
|
4945
|
-
flushText(controller, unfinishedContent);
|
|
4946
|
-
buffer = "";
|
|
4947
|
-
currentToolCall = null;
|
|
5833
|
+
finalizeUnclosedToolCall(controller);
|
|
4948
5834
|
} else if (buffer) {
|
|
4949
5835
|
flushText(controller, buffer);
|
|
4950
5836
|
buffer = "";
|
|
@@ -4954,7 +5840,8 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4954
5840
|
return;
|
|
4955
5841
|
}
|
|
4956
5842
|
if (chunk.type !== "text-delta") {
|
|
4957
|
-
if (
|
|
5843
|
+
if (currentToolCall) {
|
|
5844
|
+
} else if (buffer) {
|
|
4958
5845
|
flushText(controller, buffer);
|
|
4959
5846
|
buffer = "";
|
|
4960
5847
|
}
|
|
@@ -4967,10 +5854,7 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4967
5854
|
},
|
|
4968
5855
|
flush(controller) {
|
|
4969
5856
|
if (currentToolCall) {
|
|
4970
|
-
|
|
4971
|
-
flushText(controller, unfinishedContent);
|
|
4972
|
-
buffer = "";
|
|
4973
|
-
currentToolCall = null;
|
|
5857
|
+
finalizeUnclosedToolCall(controller);
|
|
4974
5858
|
} else if (buffer) {
|
|
4975
5859
|
flushText(controller, buffer);
|
|
4976
5860
|
buffer = "";
|
|
@@ -4998,7 +5882,205 @@ var xmlProtocol = (protocolOptions) => {
|
|
|
4998
5882
|
|
|
4999
5883
|
// src/core/protocols/yaml-protocol.ts
|
|
5000
5884
|
var import_yaml = __toESM(require("yaml"), 1);
|
|
5885
|
+
function shouldEmitRawToolCallTextOnError3(options) {
|
|
5886
|
+
return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
|
|
5887
|
+
}
|
|
5888
|
+
var selfClosingTagCache2 = /* @__PURE__ */ new Map();
|
|
5889
|
+
function getSelfClosingTagPattern2(toolName) {
|
|
5890
|
+
let pattern = selfClosingTagCache2.get(toolName);
|
|
5891
|
+
if (!pattern) {
|
|
5892
|
+
pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
|
|
5893
|
+
selfClosingTagCache2.set(toolName, pattern);
|
|
5894
|
+
}
|
|
5895
|
+
return pattern;
|
|
5896
|
+
}
|
|
5001
5897
|
var LEADING_WHITESPACE_RE = /^(\s*)/;
|
|
5898
|
+
var INCOMPLETE_MAPPING_TAIL_RE = /^[^:[\]{}-][^:]*:\s*$/;
|
|
5899
|
+
var INCOMPLETE_SEQUENCE_TAIL_RE = /^-\s*$/;
|
|
5900
|
+
var BLOCK_SCALAR_KEY_RE = /:\s*[|>][-+0-9]*\s*$/;
|
|
5901
|
+
var PLAIN_MAPPING_VALUE_RE = /^[^:[\]{}-][^:]*:\s*(.+)$/;
|
|
5902
|
+
var PLAIN_SEQUENCE_VALUE_RE = /^-\s+(.+)$/;
|
|
5903
|
+
function normalizeYamlContent(yamlContent) {
|
|
5904
|
+
let normalized = yamlContent;
|
|
5905
|
+
if (normalized.startsWith("\n")) {
|
|
5906
|
+
normalized = normalized.slice(1);
|
|
5907
|
+
}
|
|
5908
|
+
const lines = normalized.split("\n");
|
|
5909
|
+
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
|
5910
|
+
if (nonEmptyLines.length === 0) {
|
|
5911
|
+
return { normalized: "", nonEmptyLines };
|
|
5912
|
+
}
|
|
5913
|
+
const minIndent = Math.min(
|
|
5914
|
+
...nonEmptyLines.map((line) => {
|
|
5915
|
+
const match = line.match(LEADING_WHITESPACE_RE);
|
|
5916
|
+
return match ? match[1].length : 0;
|
|
5917
|
+
})
|
|
5918
|
+
);
|
|
5919
|
+
if (minIndent > 0) {
|
|
5920
|
+
normalized = lines.map((line) => line.slice(minIndent)).join("\n");
|
|
5921
|
+
}
|
|
5922
|
+
return { normalized, nonEmptyLines };
|
|
5923
|
+
}
|
|
5924
|
+
function parseYamlDocumentAsMapping(normalized) {
|
|
5925
|
+
try {
|
|
5926
|
+
const doc = import_yaml.default.parseDocument(normalized);
|
|
5927
|
+
const errors = doc.errors.map((e) => e.message);
|
|
5928
|
+
const result = doc.toJSON();
|
|
5929
|
+
if (result === null) {
|
|
5930
|
+
return { value: {}, errors };
|
|
5931
|
+
}
|
|
5932
|
+
if (typeof result !== "object" || Array.isArray(result)) {
|
|
5933
|
+
return { value: null, errors };
|
|
5934
|
+
}
|
|
5935
|
+
return { value: result, errors };
|
|
5936
|
+
} catch (error) {
|
|
5937
|
+
return {
|
|
5938
|
+
value: null,
|
|
5939
|
+
errors: [
|
|
5940
|
+
error instanceof Error ? error.message : "Unknown YAML parsing error"
|
|
5941
|
+
]
|
|
5942
|
+
};
|
|
5943
|
+
}
|
|
5944
|
+
}
|
|
5945
|
+
function getLastMeaningfulLineInfo(input) {
|
|
5946
|
+
var _a;
|
|
5947
|
+
const lines = input.split("\n");
|
|
5948
|
+
let index = lines.length - 1;
|
|
5949
|
+
while (index >= 0) {
|
|
5950
|
+
const raw = (_a = lines[index]) != null ? _a : "";
|
|
5951
|
+
const trimmed = raw.trim();
|
|
5952
|
+
if (trimmed.length > 0 && !trimmed.startsWith("#")) {
|
|
5953
|
+
return {
|
|
5954
|
+
index,
|
|
5955
|
+
raw,
|
|
5956
|
+
trimmed,
|
|
5957
|
+
indent: raw.length - raw.trimStart().length
|
|
5958
|
+
};
|
|
5959
|
+
}
|
|
5960
|
+
index -= 1;
|
|
5961
|
+
}
|
|
5962
|
+
return null;
|
|
5963
|
+
}
|
|
5964
|
+
function dropLastMeaningfulLine(input) {
|
|
5965
|
+
const lineInfo = getLastMeaningfulLineInfo(input);
|
|
5966
|
+
if (!lineInfo) {
|
|
5967
|
+
return null;
|
|
5968
|
+
}
|
|
5969
|
+
return input.split("\n").slice(0, lineInfo.index).join("\n").trimEnd();
|
|
5970
|
+
}
|
|
5971
|
+
function hasIncompleteMappingTail(normalized) {
|
|
5972
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
5973
|
+
if (!lineInfo) {
|
|
5974
|
+
return false;
|
|
5975
|
+
}
|
|
5976
|
+
return INCOMPLETE_MAPPING_TAIL_RE.test(lineInfo.trimmed);
|
|
5977
|
+
}
|
|
5978
|
+
function hasIncompleteSequenceTail(normalized) {
|
|
5979
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
5980
|
+
if (!lineInfo) {
|
|
5981
|
+
return false;
|
|
5982
|
+
}
|
|
5983
|
+
return INCOMPLETE_SEQUENCE_TAIL_RE.test(lineInfo.trimmed);
|
|
5984
|
+
}
|
|
5985
|
+
function hasSplitNestedKeyTail(normalized) {
|
|
5986
|
+
var _a;
|
|
5987
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
5988
|
+
if (!lineInfo) {
|
|
5989
|
+
return false;
|
|
5990
|
+
}
|
|
5991
|
+
const { trimmed, indent, index } = lineInfo;
|
|
5992
|
+
if (indent === 0) {
|
|
5993
|
+
return false;
|
|
5994
|
+
}
|
|
5995
|
+
if (trimmed.startsWith("#") || trimmed.startsWith("-") || trimmed.includes(":")) {
|
|
5996
|
+
return false;
|
|
5997
|
+
}
|
|
5998
|
+
const lines = normalized.split("\n");
|
|
5999
|
+
let parentIndex = index - 1;
|
|
6000
|
+
while (parentIndex >= 0) {
|
|
6001
|
+
const parentRaw = (_a = lines[parentIndex]) != null ? _a : "";
|
|
6002
|
+
const parentTrimmed = parentRaw.trim();
|
|
6003
|
+
if (parentTrimmed.length === 0 || parentTrimmed.startsWith("#")) {
|
|
6004
|
+
parentIndex -= 1;
|
|
6005
|
+
continue;
|
|
6006
|
+
}
|
|
6007
|
+
const parentIndent = parentRaw.length - parentRaw.trimStart().length;
|
|
6008
|
+
if (parentIndent >= indent) {
|
|
6009
|
+
parentIndex -= 1;
|
|
6010
|
+
continue;
|
|
6011
|
+
}
|
|
6012
|
+
if (!parentTrimmed.endsWith(":")) {
|
|
6013
|
+
return false;
|
|
6014
|
+
}
|
|
6015
|
+
if (BLOCK_SCALAR_KEY_RE.test(parentTrimmed)) {
|
|
6016
|
+
return false;
|
|
6017
|
+
}
|
|
6018
|
+
return true;
|
|
6019
|
+
}
|
|
6020
|
+
return false;
|
|
6021
|
+
}
|
|
6022
|
+
function extractTrailingPlainScalarValue(line) {
|
|
6023
|
+
var _a;
|
|
6024
|
+
if (BLOCK_SCALAR_KEY_RE.test(line)) {
|
|
6025
|
+
return null;
|
|
6026
|
+
}
|
|
6027
|
+
const mappingMatch = line.match(PLAIN_MAPPING_VALUE_RE);
|
|
6028
|
+
const sequenceMatch = line.match(PLAIN_SEQUENCE_VALUE_RE);
|
|
6029
|
+
const value = (_a = mappingMatch == null ? void 0 : mappingMatch[1]) != null ? _a : sequenceMatch == null ? void 0 : sequenceMatch[1];
|
|
6030
|
+
if (!value) {
|
|
6031
|
+
return null;
|
|
6032
|
+
}
|
|
6033
|
+
const trimmedValue = value.trim();
|
|
6034
|
+
if (trimmedValue.length === 0) {
|
|
6035
|
+
return null;
|
|
6036
|
+
}
|
|
6037
|
+
if (trimmedValue.startsWith('"') || trimmedValue.startsWith("'")) {
|
|
6038
|
+
return null;
|
|
6039
|
+
}
|
|
6040
|
+
if (trimmedValue.startsWith("{") || trimmedValue.startsWith("[") || trimmedValue.startsWith("|") || trimmedValue.startsWith(">")) {
|
|
6041
|
+
return null;
|
|
6042
|
+
}
|
|
6043
|
+
return trimmedValue;
|
|
6044
|
+
}
|
|
6045
|
+
function hasUnterminatedPlainScalarTail(normalized) {
|
|
6046
|
+
if (normalized.endsWith("\n")) {
|
|
6047
|
+
return false;
|
|
6048
|
+
}
|
|
6049
|
+
const lineInfo = getLastMeaningfulLineInfo(normalized);
|
|
6050
|
+
if (!lineInfo) {
|
|
6051
|
+
return false;
|
|
6052
|
+
}
|
|
6053
|
+
return extractTrailingPlainScalarValue(lineInfo.trimmed) != null;
|
|
6054
|
+
}
|
|
6055
|
+
function hasUnstableProgressTail(normalized) {
|
|
6056
|
+
return hasIncompleteMappingTail(normalized) || hasIncompleteSequenceTail(normalized) || hasSplitNestedKeyTail(normalized) || hasUnterminatedPlainScalarTail(normalized);
|
|
6057
|
+
}
|
|
6058
|
+
function trimTrailingNewlineInUnknown(value) {
|
|
6059
|
+
if (typeof value === "string") {
|
|
6060
|
+
if (value.endsWith("\n")) {
|
|
6061
|
+
return value.slice(0, -1);
|
|
6062
|
+
}
|
|
6063
|
+
return value;
|
|
6064
|
+
}
|
|
6065
|
+
if (Array.isArray(value)) {
|
|
6066
|
+
return value.map((item) => trimTrailingNewlineInUnknown(item));
|
|
6067
|
+
}
|
|
6068
|
+
if (value && typeof value === "object") {
|
|
6069
|
+
return Object.fromEntries(
|
|
6070
|
+
Object.entries(value).map(([key, item]) => [
|
|
6071
|
+
key,
|
|
6072
|
+
trimTrailingNewlineInUnknown(item)
|
|
6073
|
+
])
|
|
6074
|
+
);
|
|
6075
|
+
}
|
|
6076
|
+
return value;
|
|
6077
|
+
}
|
|
6078
|
+
function stabilizeParsedValueForStreamProgress(value, source) {
|
|
6079
|
+
if (source.endsWith("\n")) {
|
|
6080
|
+
return value;
|
|
6081
|
+
}
|
|
6082
|
+
return trimTrailingNewlineInUnknown(value);
|
|
6083
|
+
}
|
|
5002
6084
|
function findClosingTagEnd(text, contentStart, toolName) {
|
|
5003
6085
|
let pos = contentStart;
|
|
5004
6086
|
let depth = 1;
|
|
@@ -5070,9 +6152,9 @@ function findEarliestTagPosition(openIdx, selfIdx) {
|
|
|
5070
6152
|
function collectToolCallsForName(text, toolName) {
|
|
5071
6153
|
const toolCalls = [];
|
|
5072
6154
|
let searchIndex = 0;
|
|
5073
|
-
const
|
|
6155
|
+
const startTag = `<${toolName}>`;
|
|
6156
|
+
const selfTagRegex = getSelfClosingTagPattern2(toolName);
|
|
5074
6157
|
while (searchIndex < text.length) {
|
|
5075
|
-
const startTag = `<${toolName}>`;
|
|
5076
6158
|
const openIdx = text.indexOf(startTag, searchIndex);
|
|
5077
6159
|
selfTagRegex.lastIndex = searchIndex;
|
|
5078
6160
|
const selfMatch = selfTagRegex.exec(text);
|
|
@@ -5122,47 +6204,48 @@ function findToolCalls2(text, toolNames) {
|
|
|
5122
6204
|
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
5123
6205
|
}
|
|
5124
6206
|
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);
|
|
6207
|
+
var _a, _b;
|
|
6208
|
+
const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
|
|
5132
6209
|
if (nonEmptyLines.length === 0) {
|
|
5133
6210
|
return {};
|
|
5134
6211
|
}
|
|
5135
|
-
const
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
})
|
|
5140
|
-
|
|
5141
|
-
if (minIndent > 0) {
|
|
5142
|
-
normalized = lines.map((line) => line.slice(minIndent)).join("\n");
|
|
6212
|
+
const parsed = parseYamlDocumentAsMapping(normalized);
|
|
6213
|
+
if (parsed.errors.length > 0) {
|
|
6214
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "YAML parse error", {
|
|
6215
|
+
errors: parsed.errors
|
|
6216
|
+
});
|
|
6217
|
+
return null;
|
|
5143
6218
|
}
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
6219
|
+
if (parsed.value === null) {
|
|
6220
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
|
|
6221
|
+
got: "non-mapping"
|
|
6222
|
+
});
|
|
6223
|
+
return null;
|
|
6224
|
+
}
|
|
6225
|
+
return parsed.value;
|
|
6226
|
+
}
|
|
6227
|
+
function parseYamlContentForStreamProgress(yamlContent) {
|
|
6228
|
+
const { normalized, nonEmptyLines } = normalizeYamlContent(yamlContent);
|
|
6229
|
+
if (nonEmptyLines.length === 0) {
|
|
6230
|
+
return {};
|
|
6231
|
+
}
|
|
6232
|
+
let candidate = normalized;
|
|
6233
|
+
while (true) {
|
|
6234
|
+
const parsed = parseYamlDocumentAsMapping(candidate);
|
|
6235
|
+
if (parsed.errors.length === 0 && !hasUnstableProgressTail(candidate)) {
|
|
6236
|
+
if (candidate.trim().length === 0 && normalized.trim().length > 0) {
|
|
6237
|
+
return null;
|
|
6238
|
+
}
|
|
6239
|
+
return stabilizeParsedValueForStreamProgress(parsed.value, candidate);
|
|
5151
6240
|
}
|
|
5152
|
-
const
|
|
5153
|
-
if (
|
|
5154
|
-
return
|
|
6241
|
+
const truncated = dropLastMeaningfulLine(candidate);
|
|
6242
|
+
if (truncated == null) {
|
|
6243
|
+
return null;
|
|
5155
6244
|
}
|
|
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
|
-
});
|
|
6245
|
+
if (truncated === candidate) {
|
|
5160
6246
|
return null;
|
|
5161
6247
|
}
|
|
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;
|
|
6248
|
+
candidate = truncated;
|
|
5166
6249
|
}
|
|
5167
6250
|
}
|
|
5168
6251
|
function processToolCallMatch(text, tc, currentIndex, processedElements, options) {
|
|
@@ -5178,7 +6261,7 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
|
|
|
5178
6261
|
if (parsedArgs !== null) {
|
|
5179
6262
|
processedElements.push({
|
|
5180
6263
|
type: "tool-call",
|
|
5181
|
-
toolCallId:
|
|
6264
|
+
toolCallId: generateToolCallId(),
|
|
5182
6265
|
toolName: tc.toolName,
|
|
5183
6266
|
input: JSON.stringify(parsedArgs)
|
|
5184
6267
|
});
|
|
@@ -5191,38 +6274,6 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
|
|
|
5191
6274
|
}
|
|
5192
6275
|
return tc.endIndex;
|
|
5193
6276
|
}
|
|
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
6277
|
function findEarliestToolTag2(buffer, toolNames) {
|
|
5227
6278
|
let bestIndex = -1;
|
|
5228
6279
|
let bestName = "";
|
|
@@ -5230,8 +6281,9 @@ function findEarliestToolTag2(buffer, toolNames) {
|
|
|
5230
6281
|
let bestTagLength = 0;
|
|
5231
6282
|
for (const name of toolNames) {
|
|
5232
6283
|
const openTag = `<${name}>`;
|
|
5233
|
-
const selfTagRegex =
|
|
6284
|
+
const selfTagRegex = getSelfClosingTagPattern2(name);
|
|
5234
6285
|
const idxOpen = buffer.indexOf(openTag);
|
|
6286
|
+
selfTagRegex.lastIndex = 0;
|
|
5235
6287
|
const selfMatch = selfTagRegex.exec(buffer);
|
|
5236
6288
|
const idxSelf = selfMatch ? selfMatch.index : -1;
|
|
5237
6289
|
if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
|
|
@@ -5254,6 +6306,29 @@ function findEarliestToolTag2(buffer, toolNames) {
|
|
|
5254
6306
|
tagLength: bestTagLength
|
|
5255
6307
|
};
|
|
5256
6308
|
}
|
|
6309
|
+
function stripTrailingPartialCloseTag(content, toolName) {
|
|
6310
|
+
const closeTag = `</${toolName}>`;
|
|
6311
|
+
const lastLineBreakIndex = Math.max(
|
|
6312
|
+
content.lastIndexOf("\n"),
|
|
6313
|
+
content.lastIndexOf("\r")
|
|
6314
|
+
);
|
|
6315
|
+
const lineStartIndex = lastLineBreakIndex === -1 ? 0 : lastLineBreakIndex + 1;
|
|
6316
|
+
const trailingLine = content.slice(lineStartIndex);
|
|
6317
|
+
const trimmedTrailingLine = trailingLine.trim();
|
|
6318
|
+
if (trimmedTrailingLine.length === 0 || !trimmedTrailingLine.startsWith("</") || trimmedTrailingLine === closeTag || !closeTag.startsWith(trimmedTrailingLine)) {
|
|
6319
|
+
return content;
|
|
6320
|
+
}
|
|
6321
|
+
const leadingWhitespaceLength = trailingLine.length - trailingLine.trimStart().length;
|
|
6322
|
+
const preservedLeadingWhitespace = trailingLine.slice(
|
|
6323
|
+
0,
|
|
6324
|
+
leadingWhitespaceLength
|
|
6325
|
+
);
|
|
6326
|
+
const contentWithoutPartial = `${content.slice(
|
|
6327
|
+
0,
|
|
6328
|
+
lineStartIndex
|
|
6329
|
+
)}${preservedLeadingWhitespace}`;
|
|
6330
|
+
return contentWithoutPartial.trimEnd();
|
|
6331
|
+
}
|
|
5257
6332
|
var yamlProtocol = (_protocolOptions) => {
|
|
5258
6333
|
return {
|
|
5259
6334
|
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
@@ -5314,7 +6389,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5314
6389
|
let currentToolCall = null;
|
|
5315
6390
|
let currentTextId = null;
|
|
5316
6391
|
let hasEmittedTextStart = false;
|
|
5317
|
-
const flushText =
|
|
6392
|
+
const flushText = createFlushTextHandler(
|
|
5318
6393
|
() => currentTextId,
|
|
5319
6394
|
(newId) => {
|
|
5320
6395
|
currentTextId = newId;
|
|
@@ -5324,33 +6399,128 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5324
6399
|
hasEmittedTextStart = value;
|
|
5325
6400
|
}
|
|
5326
6401
|
);
|
|
5327
|
-
const
|
|
6402
|
+
const emitToolInputProgress2 = (controller, toolContent) => {
|
|
6403
|
+
if (!currentToolCall) {
|
|
6404
|
+
return;
|
|
6405
|
+
}
|
|
6406
|
+
const parsedArgs = parseYamlContentForStreamProgress(toolContent);
|
|
6407
|
+
if (parsedArgs === null) {
|
|
6408
|
+
return;
|
|
6409
|
+
}
|
|
6410
|
+
const fullInput = JSON.stringify(parsedArgs);
|
|
6411
|
+
if (fullInput === "{}" && toolContent.trim().length === 0) {
|
|
6412
|
+
return;
|
|
6413
|
+
}
|
|
6414
|
+
const prefixCandidate = toIncompleteJsonPrefix(fullInput);
|
|
6415
|
+
emitPrefixDelta({
|
|
6416
|
+
controller,
|
|
6417
|
+
id: currentToolCall.toolCallId,
|
|
6418
|
+
state: currentToolCall,
|
|
6419
|
+
candidate: prefixCandidate
|
|
6420
|
+
});
|
|
6421
|
+
};
|
|
6422
|
+
const processToolCallEnd = (controller, toolContent, toolName, toolCallId) => {
|
|
5328
6423
|
var _a;
|
|
5329
6424
|
const parsedArgs = parseYamlContent(toolContent, options);
|
|
5330
6425
|
flushText(controller);
|
|
5331
6426
|
if (parsedArgs !== null) {
|
|
6427
|
+
const finalInput = JSON.stringify(parsedArgs);
|
|
6428
|
+
if (currentToolCall && currentToolCall.toolCallId === toolCallId) {
|
|
6429
|
+
emitFinalRemainder({
|
|
6430
|
+
controller,
|
|
6431
|
+
id: toolCallId,
|
|
6432
|
+
state: currentToolCall,
|
|
6433
|
+
finalFullJson: finalInput,
|
|
6434
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
6435
|
+
});
|
|
6436
|
+
}
|
|
6437
|
+
controller.enqueue({
|
|
6438
|
+
type: "tool-input-end",
|
|
6439
|
+
id: toolCallId
|
|
6440
|
+
});
|
|
5332
6441
|
controller.enqueue({
|
|
5333
6442
|
type: "tool-call",
|
|
5334
|
-
toolCallId
|
|
6443
|
+
toolCallId,
|
|
5335
6444
|
toolName,
|
|
5336
|
-
input:
|
|
6445
|
+
input: finalInput
|
|
5337
6446
|
});
|
|
5338
6447
|
} else {
|
|
6448
|
+
controller.enqueue({
|
|
6449
|
+
type: "tool-input-end",
|
|
6450
|
+
id: toolCallId
|
|
6451
|
+
});
|
|
5339
6452
|
const original = `<${toolName}>${toolContent}</${toolName}>`;
|
|
5340
6453
|
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
|
|
5341
6454
|
toolCall: original
|
|
5342
6455
|
});
|
|
5343
|
-
|
|
6456
|
+
if (shouldEmitRawToolCallTextOnError3(options)) {
|
|
6457
|
+
flushText(controller, original);
|
|
6458
|
+
}
|
|
5344
6459
|
}
|
|
5345
6460
|
};
|
|
6461
|
+
const finalizeUnclosedToolCall = (controller) => {
|
|
6462
|
+
var _a;
|
|
6463
|
+
if (!currentToolCall) {
|
|
6464
|
+
return;
|
|
6465
|
+
}
|
|
6466
|
+
emitToolInputProgress2(controller, buffer);
|
|
6467
|
+
const { name: toolName, toolCallId } = currentToolCall;
|
|
6468
|
+
const reconciledBuffer = stripTrailingPartialCloseTag(buffer, toolName);
|
|
6469
|
+
const parsedArgs = parseYamlContent(reconciledBuffer, options);
|
|
6470
|
+
flushText(controller);
|
|
6471
|
+
if (parsedArgs !== null) {
|
|
6472
|
+
const finalInput = JSON.stringify(parsedArgs);
|
|
6473
|
+
emitFinalRemainder({
|
|
6474
|
+
controller,
|
|
6475
|
+
id: toolCallId,
|
|
6476
|
+
state: currentToolCall,
|
|
6477
|
+
finalFullJson: finalInput,
|
|
6478
|
+
onMismatch: options == null ? void 0 : options.onError
|
|
6479
|
+
});
|
|
6480
|
+
controller.enqueue({
|
|
6481
|
+
type: "tool-input-end",
|
|
6482
|
+
id: toolCallId
|
|
6483
|
+
});
|
|
6484
|
+
controller.enqueue({
|
|
6485
|
+
type: "tool-call",
|
|
6486
|
+
toolCallId,
|
|
6487
|
+
toolName,
|
|
6488
|
+
input: finalInput
|
|
6489
|
+
});
|
|
6490
|
+
} else {
|
|
6491
|
+
controller.enqueue({
|
|
6492
|
+
type: "tool-input-end",
|
|
6493
|
+
id: toolCallId
|
|
6494
|
+
});
|
|
6495
|
+
const unfinishedContent = `<${toolName}>${buffer}`;
|
|
6496
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
6497
|
+
options,
|
|
6498
|
+
"Could not complete streaming YAML tool call at finish.",
|
|
6499
|
+
{ toolCall: unfinishedContent }
|
|
6500
|
+
);
|
|
6501
|
+
if (shouldEmitRawToolCallTextOnError3(options)) {
|
|
6502
|
+
flushText(controller, unfinishedContent);
|
|
6503
|
+
}
|
|
6504
|
+
}
|
|
6505
|
+
buffer = "";
|
|
6506
|
+
currentToolCall = null;
|
|
6507
|
+
};
|
|
5346
6508
|
const handlePendingToolCall = (controller, endTag, toolName) => {
|
|
6509
|
+
var _a;
|
|
5347
6510
|
const endIdx = buffer.indexOf(endTag);
|
|
5348
6511
|
if (endIdx === -1) {
|
|
6512
|
+
emitToolInputProgress2(controller, buffer);
|
|
5349
6513
|
return false;
|
|
5350
6514
|
}
|
|
5351
6515
|
const content = buffer.substring(0, endIdx);
|
|
6516
|
+
emitToolInputProgress2(controller, content);
|
|
5352
6517
|
buffer = buffer.substring(endIdx + endTag.length);
|
|
5353
|
-
processToolCallEnd(
|
|
6518
|
+
processToolCallEnd(
|
|
6519
|
+
controller,
|
|
6520
|
+
content,
|
|
6521
|
+
toolName,
|
|
6522
|
+
(_a = currentToolCall == null ? void 0 : currentToolCall.toolCallId) != null ? _a : generateToolCallId()
|
|
6523
|
+
);
|
|
5354
6524
|
currentToolCall = null;
|
|
5355
6525
|
return true;
|
|
5356
6526
|
};
|
|
@@ -5367,13 +6537,35 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5367
6537
|
if (tagIndex > 0) {
|
|
5368
6538
|
flushText(controller, buffer.substring(0, tagIndex));
|
|
5369
6539
|
}
|
|
6540
|
+
flushText(controller);
|
|
5370
6541
|
if (selfClosing) {
|
|
5371
6542
|
buffer = buffer.substring(tagIndex + tagLength);
|
|
5372
|
-
|
|
6543
|
+
const toolCallId = generateToolCallId();
|
|
6544
|
+
currentToolCall = {
|
|
6545
|
+
name: tagName,
|
|
6546
|
+
toolCallId,
|
|
6547
|
+
emittedInput: ""
|
|
6548
|
+
};
|
|
6549
|
+
controller.enqueue({
|
|
6550
|
+
type: "tool-input-start",
|
|
6551
|
+
id: toolCallId,
|
|
6552
|
+
toolName: tagName
|
|
6553
|
+
});
|
|
6554
|
+
processToolCallEnd(controller, "", tagName, toolCallId);
|
|
6555
|
+
currentToolCall = null;
|
|
5373
6556
|
} else {
|
|
5374
6557
|
const startTag = `<${tagName}>`;
|
|
5375
6558
|
buffer = buffer.substring(tagIndex + startTag.length);
|
|
5376
|
-
currentToolCall = {
|
|
6559
|
+
currentToolCall = {
|
|
6560
|
+
name: tagName,
|
|
6561
|
+
toolCallId: generateToolCallId(),
|
|
6562
|
+
emittedInput: ""
|
|
6563
|
+
};
|
|
6564
|
+
controller.enqueue({
|
|
6565
|
+
type: "tool-input-start",
|
|
6566
|
+
id: currentToolCall.toolCallId,
|
|
6567
|
+
toolName: tagName
|
|
6568
|
+
});
|
|
5377
6569
|
}
|
|
5378
6570
|
};
|
|
5379
6571
|
const processBuffer = (controller) => {
|
|
@@ -5402,10 +6594,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5402
6594
|
var _a;
|
|
5403
6595
|
if (chunk.type === "finish") {
|
|
5404
6596
|
if (currentToolCall) {
|
|
5405
|
-
|
|
5406
|
-
flushText(controller, unfinishedContent);
|
|
5407
|
-
buffer = "";
|
|
5408
|
-
currentToolCall = null;
|
|
6597
|
+
finalizeUnclosedToolCall(controller);
|
|
5409
6598
|
} else if (buffer) {
|
|
5410
6599
|
flushText(controller, buffer);
|
|
5411
6600
|
buffer = "";
|
|
@@ -5415,7 +6604,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5415
6604
|
return;
|
|
5416
6605
|
}
|
|
5417
6606
|
if (chunk.type !== "text-delta") {
|
|
5418
|
-
if (buffer) {
|
|
6607
|
+
if (!currentToolCall && buffer) {
|
|
5419
6608
|
flushText(controller, buffer);
|
|
5420
6609
|
buffer = "";
|
|
5421
6610
|
}
|
|
@@ -5428,10 +6617,7 @@ ${yamlContent}</${toolCall.toolName}>`;
|
|
|
5428
6617
|
},
|
|
5429
6618
|
flush(controller) {
|
|
5430
6619
|
if (currentToolCall) {
|
|
5431
|
-
|
|
5432
|
-
flushText(controller, unfinishedContent);
|
|
5433
|
-
buffer = "";
|
|
5434
|
-
currentToolCall = null;
|
|
6620
|
+
finalizeUnclosedToolCall(controller);
|
|
5435
6621
|
} else if (buffer) {
|
|
5436
6622
|
flushText(controller, buffer);
|
|
5437
6623
|
buffer = "";
|
|
@@ -5594,9 +6780,6 @@ function isToolChoiceActive(params) {
|
|
|
5594
6780
|
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
6781
|
}
|
|
5596
6782
|
|
|
5597
|
-
// src/generate-handler.ts
|
|
5598
|
-
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
5599
|
-
|
|
5600
6783
|
// src/core/utils/generated-text-json-recovery.ts
|
|
5601
6784
|
function isRecord(value) {
|
|
5602
6785
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -5735,7 +6918,7 @@ function mergeJsonCandidatesByStart(tagged, codeBlocks, balanced) {
|
|
|
5735
6918
|
function toToolCallPart(candidate) {
|
|
5736
6919
|
return {
|
|
5737
6920
|
type: "tool-call",
|
|
5738
|
-
toolCallId:
|
|
6921
|
+
toolCallId: generateToolCallId(),
|
|
5739
6922
|
toolName: candidate.toolName,
|
|
5740
6923
|
input: candidate.input
|
|
5741
6924
|
};
|
|
@@ -5962,7 +7145,7 @@ async function handleToolChoice(doGenerate, params, tools) {
|
|
|
5962
7145
|
}
|
|
5963
7146
|
const toolCall = {
|
|
5964
7147
|
type: "tool-call",
|
|
5965
|
-
toolCallId: (
|
|
7148
|
+
toolCallId: generateToolCallId(),
|
|
5966
7149
|
toolName,
|
|
5967
7150
|
input
|
|
5968
7151
|
};
|
|
@@ -6472,7 +7655,6 @@ unit: celsius
|
|
|
6472
7655
|
}
|
|
6473
7656
|
|
|
6474
7657
|
// src/stream-handler.ts
|
|
6475
|
-
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
6476
7658
|
async function wrapStream({
|
|
6477
7659
|
protocol,
|
|
6478
7660
|
doStream,
|
|
@@ -6510,10 +7692,22 @@ async function wrapStream({
|
|
|
6510
7692
|
}
|
|
6511
7693
|
)
|
|
6512
7694
|
).pipeThrough(protocol.createStreamParser({ tools, options }));
|
|
7695
|
+
let seenToolCall = false;
|
|
6513
7696
|
const v3Stream = coreStream.pipeThrough(
|
|
6514
7697
|
new TransformStream({
|
|
6515
7698
|
transform(part, controller) {
|
|
6516
|
-
|
|
7699
|
+
let normalizedPart = part.type === "tool-call" ? coerceToolCallPart(part, tools) : part;
|
|
7700
|
+
if (normalizedPart.type === "tool-call") {
|
|
7701
|
+
seenToolCall = true;
|
|
7702
|
+
}
|
|
7703
|
+
if (normalizedPart.type === "finish" && seenToolCall && normalizedPart.finishReason.unified === "stop") {
|
|
7704
|
+
normalizedPart = {
|
|
7705
|
+
...normalizedPart,
|
|
7706
|
+
finishReason: normalizeToolCallsFinishReason(
|
|
7707
|
+
normalizedPart.finishReason
|
|
7708
|
+
)
|
|
7709
|
+
};
|
|
7710
|
+
}
|
|
6517
7711
|
if (debugLevel === "stream") {
|
|
6518
7712
|
logParsedChunk(normalizedPart);
|
|
6519
7713
|
}
|
|
@@ -6550,7 +7744,7 @@ async function toolChoiceStream({
|
|
|
6550
7744
|
start(controller) {
|
|
6551
7745
|
controller.enqueue({
|
|
6552
7746
|
type: "tool-call",
|
|
6553
|
-
toolCallId: (
|
|
7747
|
+
toolCallId: generateToolCallId(),
|
|
6554
7748
|
toolName,
|
|
6555
7749
|
input
|
|
6556
7750
|
});
|