@ai-sdk-tool/parser 2.1.1 → 2.1.3
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 +129 -0
- package/dist/index.cjs +1688 -963
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -14
- package/dist/index.d.ts +15 -14
- package/dist/index.js +1687 -958
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20,22 +20,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
coerceBySchema: () => coerceBySchema,
|
|
24
23
|
createToolMiddleware: () => createToolMiddleware,
|
|
25
|
-
fixToolCallWithSchema: () => fixToolCallWithSchema,
|
|
26
24
|
gemmaToolMiddleware: () => gemmaToolMiddleware,
|
|
27
|
-
getSchemaType: () => getSchemaType,
|
|
28
25
|
hermesToolMiddleware: () => hermesToolMiddleware,
|
|
29
26
|
jsonMixProtocol: () => jsonMixProtocol,
|
|
30
|
-
|
|
31
|
-
xmlProtocol: () => xmlProtocol,
|
|
27
|
+
morphXmlProtocol: () => morphXmlProtocol,
|
|
32
28
|
xmlToolMiddleware: () => xmlToolMiddleware
|
|
33
29
|
});
|
|
34
30
|
module.exports = __toCommonJS(index_exports);
|
|
35
31
|
|
|
36
|
-
// src/
|
|
32
|
+
// src/protocols/dummy-protocol.ts
|
|
37
33
|
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
38
34
|
|
|
35
|
+
// src/protocols/json-mix-protocol.ts
|
|
36
|
+
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
37
|
+
|
|
39
38
|
// src/utils/dynamic-tool-schema.ts
|
|
40
39
|
function createDynamicIfThenElseSchema(tools) {
|
|
41
40
|
let currentSchema = {};
|
|
@@ -110,6 +109,11 @@ function getPotentialStartIndex(text, searchedText) {
|
|
|
110
109
|
return null;
|
|
111
110
|
}
|
|
112
111
|
|
|
112
|
+
// src/utils/regex.ts
|
|
113
|
+
function escapeRegExp(literal) {
|
|
114
|
+
return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
115
|
+
}
|
|
116
|
+
|
|
113
117
|
// src/utils/relaxed-json.ts
|
|
114
118
|
var relaxed_json_exports = {};
|
|
115
119
|
__export(relaxed_json_exports, {
|
|
@@ -743,62 +747,6 @@ function stringify(obj) {
|
|
|
743
747
|
return "null";
|
|
744
748
|
}
|
|
745
749
|
|
|
746
|
-
// src/utils/regex.ts
|
|
747
|
-
function escapeRegExp(literal) {
|
|
748
|
-
return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
// src/utils/type-guards.ts
|
|
752
|
-
function isToolCallContent(content) {
|
|
753
|
-
return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
|
|
754
|
-
(typeof content.input === "string" || typeof content.input === "object");
|
|
755
|
-
}
|
|
756
|
-
function isToolResultPart(content) {
|
|
757
|
-
const c = content;
|
|
758
|
-
return !!c && c.type === "tool-result" && typeof c.toolName === "string" && typeof c.toolCallId === "string" && "output" in c;
|
|
759
|
-
}
|
|
760
|
-
function hasInputProperty(obj) {
|
|
761
|
-
return typeof obj === "object" && obj !== null && "input" in obj;
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
// src/utils/tools.ts
|
|
765
|
-
function isToolChoiceActive(params) {
|
|
766
|
-
var _a, _b, _c;
|
|
767
|
-
const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
|
|
768
|
-
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"));
|
|
769
|
-
}
|
|
770
|
-
function getFunctionTools(params) {
|
|
771
|
-
var _a, _b;
|
|
772
|
-
const functionTools = ((_a = params.tools) != null ? _a : []).filter(
|
|
773
|
-
(t) => t.type === "function"
|
|
774
|
-
);
|
|
775
|
-
if (functionTools.length > 0) return functionTools;
|
|
776
|
-
const rawToolNames = params.providerOptions && typeof params.providerOptions === "object" && ((_b = params.providerOptions.toolCallMiddleware) == null ? void 0 : _b.toolNames) || [];
|
|
777
|
-
const toStringArray = (val) => Array.isArray(val) ? val.filter(
|
|
778
|
-
(item) => typeof item === "string"
|
|
779
|
-
) : [];
|
|
780
|
-
const toolNames = toStringArray(rawToolNames);
|
|
781
|
-
if (toolNames.length > 0) {
|
|
782
|
-
return toolNames.map((name) => ({
|
|
783
|
-
type: "function",
|
|
784
|
-
name,
|
|
785
|
-
description: "",
|
|
786
|
-
inputSchema: { type: "object" }
|
|
787
|
-
}));
|
|
788
|
-
}
|
|
789
|
-
return [];
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
// src/utils/on-error.ts
|
|
793
|
-
function extractOnErrorOption(providerOptions) {
|
|
794
|
-
var _a;
|
|
795
|
-
if (providerOptions && typeof providerOptions === "object") {
|
|
796
|
-
const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
|
|
797
|
-
return onError ? { onError } : void 0;
|
|
798
|
-
}
|
|
799
|
-
return void 0;
|
|
800
|
-
}
|
|
801
|
-
|
|
802
750
|
// src/utils/coercion.ts
|
|
803
751
|
function unwrapJsonSchema(schema) {
|
|
804
752
|
if (!schema || typeof schema !== "object") return schema;
|
|
@@ -1003,498 +951,1080 @@ function coerceToolCallInput(part, tools) {
|
|
|
1003
951
|
return fixToolCallWithSchema(part, tools);
|
|
1004
952
|
}
|
|
1005
953
|
|
|
1006
|
-
// src/utils/
|
|
1007
|
-
function
|
|
1008
|
-
|
|
954
|
+
// src/utils/debug.ts
|
|
955
|
+
function normalizeBooleanString(value) {
|
|
956
|
+
const normalized = value.trim().toLowerCase();
|
|
957
|
+
if (normalized === "1" || normalized === "true" || normalized === "yes") {
|
|
958
|
+
return true;
|
|
959
|
+
}
|
|
960
|
+
if (normalized === "0" || normalized === "false" || normalized === "no") {
|
|
961
|
+
return false;
|
|
962
|
+
}
|
|
963
|
+
return void 0;
|
|
1009
964
|
}
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
doGenerate,
|
|
1016
|
-
params
|
|
1017
|
-
}) {
|
|
1018
|
-
var _a;
|
|
1019
|
-
if (isToolChoiceActive(params)) {
|
|
1020
|
-
return toolChoiceStream({
|
|
1021
|
-
doGenerate,
|
|
1022
|
-
options: extractOnErrorOption(params.providerOptions)
|
|
1023
|
-
});
|
|
965
|
+
function getDebugLevel() {
|
|
966
|
+
const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW || "off";
|
|
967
|
+
const envLower = String(envVal).toLowerCase();
|
|
968
|
+
if (envLower === "stream" || envLower === "parse" || envLower === "off") {
|
|
969
|
+
return envLower;
|
|
1024
970
|
}
|
|
1025
|
-
const
|
|
1026
|
-
return
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
tools: getFunctionTools(params),
|
|
1030
|
-
options: {
|
|
1031
|
-
...extractOnErrorOption(params.providerOptions),
|
|
1032
|
-
...(_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware
|
|
1033
|
-
}
|
|
1034
|
-
})
|
|
1035
|
-
),
|
|
1036
|
-
...rest
|
|
1037
|
-
};
|
|
971
|
+
const boolEnv = normalizeBooleanString(envLower);
|
|
972
|
+
if (boolEnv === true) return "stream";
|
|
973
|
+
if (envLower === "2") return "parse";
|
|
974
|
+
return "off";
|
|
1038
975
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
}
|
|
1057
|
-
);
|
|
1058
|
-
toolJson = {};
|
|
1059
|
-
}
|
|
976
|
+
function color(code) {
|
|
977
|
+
return (text) => `\x1B[${code}m${text}\x1B[0m`;
|
|
978
|
+
}
|
|
979
|
+
var cGray = color(90);
|
|
980
|
+
var cYellow = color(33);
|
|
981
|
+
var cCyan = color(36);
|
|
982
|
+
var cBgBlue = color(44);
|
|
983
|
+
var cBgGreen = color(42);
|
|
984
|
+
var cInverse = color(7);
|
|
985
|
+
var cUnderline = color(4);
|
|
986
|
+
var cBold = color(1);
|
|
987
|
+
function safeStringify(value) {
|
|
988
|
+
try {
|
|
989
|
+
return `
|
|
990
|
+
${typeof value === "string" ? value : JSON.stringify(value, null, 2)}`;
|
|
991
|
+
} catch (e) {
|
|
992
|
+
return String(value);
|
|
1060
993
|
}
|
|
1061
|
-
const toolCallChunk = {
|
|
1062
|
-
type: "tool-call",
|
|
1063
|
-
toolCallId: (0, import_provider_utils.generateId)(),
|
|
1064
|
-
toolName: toolJson.name || "unknown",
|
|
1065
|
-
input: JSON.stringify(toolJson.arguments || {})
|
|
1066
|
-
};
|
|
1067
|
-
const finishChunk = {
|
|
1068
|
-
type: "finish",
|
|
1069
|
-
usage: (result == null ? void 0 : result.usage) || // TODO: If possible, try to return a certain amount of LLM usage.
|
|
1070
|
-
{
|
|
1071
|
-
inputTokens: 0,
|
|
1072
|
-
outputTokens: 0,
|
|
1073
|
-
totalTokens: 0
|
|
1074
|
-
},
|
|
1075
|
-
finishReason: "tool-calls"
|
|
1076
|
-
};
|
|
1077
|
-
const stream = new ReadableStream({
|
|
1078
|
-
start(controller) {
|
|
1079
|
-
controller.enqueue(toolCallChunk);
|
|
1080
|
-
controller.enqueue(finishChunk);
|
|
1081
|
-
controller.close();
|
|
1082
|
-
}
|
|
1083
|
-
});
|
|
1084
|
-
return {
|
|
1085
|
-
request: (result == null ? void 0 : result.request) || {},
|
|
1086
|
-
response: (result == null ? void 0 : result.response) || {},
|
|
1087
|
-
stream
|
|
1088
|
-
};
|
|
1089
994
|
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
995
|
+
function logRawChunk(part) {
|
|
996
|
+
console.log(cGray("[debug:mw:raw]"), cYellow(safeStringify(part)));
|
|
997
|
+
}
|
|
998
|
+
function logParsedChunk(part) {
|
|
999
|
+
console.log(cGray("[debug:mw:out]"), cCyan(safeStringify(part)));
|
|
1000
|
+
}
|
|
1001
|
+
function logParsedSummary({
|
|
1002
|
+
toolCalls,
|
|
1003
|
+
originalText
|
|
1097
1004
|
}) {
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
|
-
const toolCall = {
|
|
1120
|
-
type: "tool-call",
|
|
1121
|
-
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1122
|
-
toolName: parsed2.name || "unknown",
|
|
1123
|
-
input: JSON.stringify(parsed2.arguments || {})
|
|
1124
|
-
};
|
|
1125
|
-
return {
|
|
1126
|
-
...result2,
|
|
1127
|
-
content: [toolCall]
|
|
1128
|
-
};
|
|
1005
|
+
if (originalText) {
|
|
1006
|
+
const style = (() => {
|
|
1007
|
+
const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW_STYLE || "bg";
|
|
1008
|
+
const normalized = String(envVal).trim().toLowerCase();
|
|
1009
|
+
if (normalized === "inverse" || normalized === "invert")
|
|
1010
|
+
return "inverse";
|
|
1011
|
+
if (normalized === "underline" || normalized === "ul")
|
|
1012
|
+
return "underline";
|
|
1013
|
+
if (normalized === "bold") return "bold";
|
|
1014
|
+
if (normalized === "bg" || normalized === "background")
|
|
1015
|
+
return "bg";
|
|
1016
|
+
const asBool = normalizeBooleanString(normalized);
|
|
1017
|
+
if (asBool === true) return "bg";
|
|
1018
|
+
return "bg";
|
|
1019
|
+
})();
|
|
1020
|
+
const highlight = style === "inverse" ? cInverse : style === "underline" ? cUnderline : style === "bold" ? cBold : style === "bg" ? cBgGreen : cYellow;
|
|
1021
|
+
const rendered = style === "bg" || style === "inverse" || style === "underline" || style === "bold" ? originalText.split(/\r?\n/).map((line) => line.length ? highlight(line) : line).join("\n") : highlight(originalText);
|
|
1022
|
+
console.log(cGray("[debug:mw:origin]"), `
|
|
1023
|
+
${rendered}`);
|
|
1129
1024
|
}
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1025
|
+
if (toolCalls.length > 0) {
|
|
1026
|
+
const styledSummary = safeStringify(toolCalls).split(/\r?\n/).map((line) => line.length ? cBgBlue(line) : line).join("\n");
|
|
1027
|
+
console.log(cGray("[debug:mw:summary]"), styledSummary);
|
|
1133
1028
|
}
|
|
1134
|
-
const parsed = result.content.flatMap((contentItem) => {
|
|
1135
|
-
var _a2;
|
|
1136
|
-
if (contentItem.type !== "text") {
|
|
1137
|
-
return [contentItem];
|
|
1138
|
-
}
|
|
1139
|
-
return protocol.parseGeneratedText({
|
|
1140
|
-
text: contentItem.text,
|
|
1141
|
-
tools: getFunctionTools(params),
|
|
1142
|
-
options: {
|
|
1143
|
-
...extractOnErrorOption(params.providerOptions),
|
|
1144
|
-
...(_a2 = params.providerOptions) == null ? void 0 : _a2.toolCallMiddleware
|
|
1145
|
-
}
|
|
1146
|
-
});
|
|
1147
|
-
});
|
|
1148
|
-
const tools = getFunctionTools(params);
|
|
1149
|
-
const newContent = parsed.map(
|
|
1150
|
-
(part) => coerceToolCallInput(part, tools)
|
|
1151
|
-
);
|
|
1152
|
-
return {
|
|
1153
|
-
...result,
|
|
1154
|
-
content: newContent
|
|
1155
|
-
};
|
|
1156
1029
|
}
|
|
1157
1030
|
|
|
1158
|
-
// src/
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
|
|
1031
|
+
// src/utils/on-error.ts
|
|
1032
|
+
function extractOnErrorOption(providerOptions) {
|
|
1033
|
+
var _a;
|
|
1034
|
+
if (providerOptions && typeof providerOptions === "object") {
|
|
1035
|
+
const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
|
|
1036
|
+
return onError ? { onError } : void 0;
|
|
1037
|
+
}
|
|
1038
|
+
return void 0;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
// src/utils/protocol.ts
|
|
1042
|
+
function isProtocolFactory(protocol) {
|
|
1043
|
+
return typeof protocol === "function";
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
// src/utils/tools.ts
|
|
1047
|
+
function isToolChoiceActive(params) {
|
|
1048
|
+
var _a, _b, _c;
|
|
1049
|
+
const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
|
|
1050
|
+
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"));
|
|
1051
|
+
}
|
|
1052
|
+
function getFunctionTools(params) {
|
|
1053
|
+
var _a, _b;
|
|
1166
1054
|
const functionTools = ((_a = params.tools) != null ? _a : []).filter(
|
|
1167
1055
|
(t) => t.type === "function"
|
|
1168
1056
|
);
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
},
|
|
1183
|
-
...processedPrompt.slice(1)
|
|
1184
|
-
] : [
|
|
1185
|
-
{
|
|
1186
|
-
role: "system",
|
|
1187
|
-
content: systemPrompt
|
|
1188
|
-
},
|
|
1189
|
-
...processedPrompt
|
|
1190
|
-
];
|
|
1191
|
-
const baseReturnParams = {
|
|
1192
|
-
...params,
|
|
1193
|
-
prompt: finalPrompt,
|
|
1194
|
-
tools: [],
|
|
1195
|
-
toolChoice: void 0,
|
|
1196
|
-
providerOptions: {
|
|
1197
|
-
...params.providerOptions || {},
|
|
1198
|
-
toolCallMiddleware: {
|
|
1199
|
-
...params.providerOptions && typeof params.providerOptions === "object" && params.providerOptions.toolCallMiddleware || {},
|
|
1200
|
-
toolNames: functionTools.map((t) => t.name)
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
};
|
|
1204
|
-
if (((_d = params.toolChoice) == null ? void 0 : _d.type) === "none") {
|
|
1205
|
-
throw new Error(
|
|
1206
|
-
"The 'none' toolChoice type is not supported by this middleware. Please use 'auto', 'required', or specify a tool name."
|
|
1207
|
-
);
|
|
1057
|
+
if (functionTools.length > 0) return functionTools;
|
|
1058
|
+
const rawToolNames = params.providerOptions && typeof params.providerOptions === "object" && ((_b = params.providerOptions.toolCallMiddleware) == null ? void 0 : _b.toolNames) || [];
|
|
1059
|
+
const toStringArray = (val) => Array.isArray(val) ? val.filter(
|
|
1060
|
+
(item) => typeof item === "string"
|
|
1061
|
+
) : [];
|
|
1062
|
+
const toolNames = toStringArray(rawToolNames);
|
|
1063
|
+
if (toolNames.length > 0) {
|
|
1064
|
+
return toolNames.map((name) => ({
|
|
1065
|
+
type: "function",
|
|
1066
|
+
name,
|
|
1067
|
+
description: "",
|
|
1068
|
+
inputSchema: { type: "object" }
|
|
1069
|
+
}));
|
|
1208
1070
|
}
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1071
|
+
return [];
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// src/utils/type-guards.ts
|
|
1075
|
+
function isToolCallContent(content) {
|
|
1076
|
+
return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
|
|
1077
|
+
(typeof content.input === "string" || typeof content.input === "object");
|
|
1078
|
+
}
|
|
1079
|
+
function isToolResultPart(content) {
|
|
1080
|
+
const c = content;
|
|
1081
|
+
return !!c && c.type === "tool-result" && typeof c.toolName === "string" && typeof c.toolCallId === "string" && "output" in c;
|
|
1082
|
+
}
|
|
1083
|
+
function hasInputProperty(obj) {
|
|
1084
|
+
return typeof obj === "object" && obj !== null && "input" in obj;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
// src/protocols/json-mix-protocol.ts
|
|
1088
|
+
var jsonMixProtocol = ({
|
|
1089
|
+
toolCallStart = "<tool_call>",
|
|
1090
|
+
toolCallEnd = "</tool_call>",
|
|
1091
|
+
toolResponseStart = "<tool_response>",
|
|
1092
|
+
toolResponseEnd = "</tool_response>"
|
|
1093
|
+
} = {}) => ({
|
|
1094
|
+
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
1095
|
+
const toolsForPrompt = (tools || []).filter((tool) => tool.type === "function").map((tool) => ({
|
|
1096
|
+
name: tool.name,
|
|
1097
|
+
description: tool.type === "function" && typeof tool.description === "string" ? tool.description : void 0,
|
|
1098
|
+
parameters: tool.inputSchema
|
|
1099
|
+
}));
|
|
1100
|
+
return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
|
|
1101
|
+
},
|
|
1102
|
+
formatToolCall(toolCall) {
|
|
1103
|
+
let args = {};
|
|
1104
|
+
try {
|
|
1105
|
+
args = JSON.parse(toolCall.input);
|
|
1106
|
+
} catch (e) {
|
|
1107
|
+
args = toolCall.input;
|
|
1220
1108
|
}
|
|
1221
|
-
|
|
1222
|
-
|
|
1109
|
+
return `${toolCallStart}${JSON.stringify({
|
|
1110
|
+
name: toolCall.toolName,
|
|
1111
|
+
arguments: args
|
|
1112
|
+
})}${toolCallEnd}`;
|
|
1113
|
+
},
|
|
1114
|
+
formatToolResponse(toolResult) {
|
|
1115
|
+
return `${toolResponseStart}${JSON.stringify({
|
|
1116
|
+
toolName: toolResult.toolName,
|
|
1117
|
+
result: toolResult.output
|
|
1118
|
+
})}${toolResponseEnd}`;
|
|
1119
|
+
},
|
|
1120
|
+
parseGeneratedText({ text, options }) {
|
|
1121
|
+
var _a;
|
|
1122
|
+
const startEsc = escapeRegExp(toolCallStart);
|
|
1123
|
+
const endEsc = escapeRegExp(toolCallEnd);
|
|
1124
|
+
const toolCallRegex = new RegExp(
|
|
1125
|
+
`${startEsc}([\0-\uFFFF]*?)${endEsc}`,
|
|
1126
|
+
"gs"
|
|
1223
1127
|
);
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
type: "object",
|
|
1235
|
-
properties: {
|
|
1236
|
-
name: {
|
|
1237
|
-
const: selectedTool.name
|
|
1238
|
-
},
|
|
1239
|
-
arguments: selectedTool.inputSchema
|
|
1240
|
-
},
|
|
1241
|
-
required: ["name", "arguments"]
|
|
1242
|
-
},
|
|
1243
|
-
name: selectedTool.name,
|
|
1244
|
-
description: typeof selectedTool.description === "string" ? selectedTool.description : void 0
|
|
1245
|
-
},
|
|
1246
|
-
providerOptions: {
|
|
1247
|
-
...baseReturnParams.providerOptions || {},
|
|
1248
|
-
toolCallMiddleware: {
|
|
1249
|
-
...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
|
|
1250
|
-
toolChoice: params.toolChoice
|
|
1128
|
+
const processedElements = [];
|
|
1129
|
+
let currentIndex = 0;
|
|
1130
|
+
let match;
|
|
1131
|
+
while ((match = toolCallRegex.exec(text)) !== null) {
|
|
1132
|
+
const startIndex = match.index;
|
|
1133
|
+
const toolCallJson = match[1];
|
|
1134
|
+
if (startIndex > currentIndex) {
|
|
1135
|
+
const textSegment = text.substring(currentIndex, startIndex);
|
|
1136
|
+
if (textSegment.trim()) {
|
|
1137
|
+
processedElements.push({ type: "text", text: textSegment });
|
|
1251
1138
|
}
|
|
1252
1139
|
}
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1140
|
+
if (toolCallJson) {
|
|
1141
|
+
try {
|
|
1142
|
+
const parsedToolCall = relaxed_json_exports.parse(toolCallJson);
|
|
1143
|
+
processedElements.push({
|
|
1144
|
+
type: "tool-call",
|
|
1145
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1146
|
+
toolName: parsedToolCall.name,
|
|
1147
|
+
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1148
|
+
});
|
|
1149
|
+
} catch (error) {
|
|
1150
|
+
if (options == null ? void 0 : options.onError) {
|
|
1151
|
+
options.onError(
|
|
1152
|
+
"Could not process JSON tool call, keeping original text.",
|
|
1153
|
+
{ toolCall: match[0], error }
|
|
1154
|
+
);
|
|
1155
|
+
}
|
|
1156
|
+
processedElements.push({ type: "text", text: match[0] });
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
currentIndex = startIndex + match[0].length;
|
|
1260
1160
|
}
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
type: "
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1161
|
+
if (currentIndex < text.length) {
|
|
1162
|
+
const remainingText = text.substring(currentIndex);
|
|
1163
|
+
if (remainingText.trim()) {
|
|
1164
|
+
processedElements.push({ type: "text", text: remainingText });
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
return processedElements;
|
|
1168
|
+
},
|
|
1169
|
+
createStreamParser({ tools: _tools, options } = { tools: [] }) {
|
|
1170
|
+
let isInsideToolCall = false;
|
|
1171
|
+
let buffer = "";
|
|
1172
|
+
let currentToolCallJson = "";
|
|
1173
|
+
let currentTextId = null;
|
|
1174
|
+
let hasEmittedTextStart = false;
|
|
1175
|
+
return new TransformStream({
|
|
1176
|
+
transform(chunk, controller) {
|
|
1177
|
+
var _a;
|
|
1178
|
+
if (chunk.type === "finish") {
|
|
1179
|
+
if (isInsideToolCall && buffer.length > 0) {
|
|
1180
|
+
if (!currentTextId) {
|
|
1181
|
+
currentTextId = (0, import_provider_utils2.generateId)();
|
|
1182
|
+
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
1183
|
+
hasEmittedTextStart = true;
|
|
1184
|
+
}
|
|
1185
|
+
controller.enqueue({
|
|
1186
|
+
type: "text-delta",
|
|
1187
|
+
id: currentTextId,
|
|
1188
|
+
delta: `${toolCallStart}${buffer}`
|
|
1189
|
+
});
|
|
1190
|
+
buffer = "";
|
|
1191
|
+
} else if (!isInsideToolCall && buffer.length > 0) {
|
|
1192
|
+
if (!currentTextId) {
|
|
1193
|
+
currentTextId = (0, import_provider_utils2.generateId)();
|
|
1194
|
+
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
1195
|
+
hasEmittedTextStart = true;
|
|
1196
|
+
}
|
|
1197
|
+
controller.enqueue({
|
|
1198
|
+
type: "text-delta",
|
|
1199
|
+
id: currentTextId,
|
|
1200
|
+
delta: buffer
|
|
1201
|
+
});
|
|
1202
|
+
buffer = "";
|
|
1203
|
+
}
|
|
1204
|
+
if (currentTextId && hasEmittedTextStart) {
|
|
1205
|
+
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1206
|
+
currentTextId = null;
|
|
1207
|
+
hasEmittedTextStart = false;
|
|
1208
|
+
}
|
|
1209
|
+
if (currentToolCallJson) {
|
|
1210
|
+
const errorId = (0, import_provider_utils2.generateId)();
|
|
1211
|
+
controller.enqueue({ type: "text-start", id: errorId });
|
|
1212
|
+
controller.enqueue({
|
|
1213
|
+
type: "text-delta",
|
|
1214
|
+
id: errorId,
|
|
1215
|
+
delta: `${toolCallStart}${currentToolCallJson}`
|
|
1216
|
+
});
|
|
1217
|
+
controller.enqueue({ type: "text-end", id: errorId });
|
|
1218
|
+
currentToolCallJson = "";
|
|
1219
|
+
}
|
|
1220
|
+
controller.enqueue(chunk);
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1223
|
+
if (chunk.type !== "text-delta") {
|
|
1224
|
+
controller.enqueue(chunk);
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1227
|
+
buffer += chunk.delta;
|
|
1228
|
+
const publish = (text) => {
|
|
1229
|
+
if (isInsideToolCall) {
|
|
1230
|
+
if (currentTextId && hasEmittedTextStart) {
|
|
1231
|
+
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1232
|
+
currentTextId = null;
|
|
1233
|
+
hasEmittedTextStart = false;
|
|
1234
|
+
}
|
|
1235
|
+
currentToolCallJson += text;
|
|
1236
|
+
} else if (text.length > 0) {
|
|
1237
|
+
if (!currentTextId) {
|
|
1238
|
+
currentTextId = (0, import_provider_utils2.generateId)();
|
|
1239
|
+
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
1240
|
+
hasEmittedTextStart = true;
|
|
1241
|
+
}
|
|
1242
|
+
controller.enqueue({
|
|
1243
|
+
type: "text-delta",
|
|
1244
|
+
id: currentTextId,
|
|
1245
|
+
delta: text
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
};
|
|
1249
|
+
let startIndex;
|
|
1250
|
+
while ((startIndex = getPotentialStartIndex(
|
|
1251
|
+
buffer,
|
|
1252
|
+
isInsideToolCall ? toolCallEnd : toolCallStart
|
|
1253
|
+
)) != null) {
|
|
1254
|
+
const tag = isInsideToolCall ? toolCallEnd : toolCallStart;
|
|
1255
|
+
if (startIndex + tag.length > buffer.length) {
|
|
1256
|
+
break;
|
|
1257
|
+
}
|
|
1258
|
+
publish(buffer.slice(0, startIndex));
|
|
1259
|
+
buffer = buffer.slice(startIndex + tag.length);
|
|
1260
|
+
if (!isInsideToolCall) {
|
|
1261
|
+
currentToolCallJson = "";
|
|
1262
|
+
isInsideToolCall = true;
|
|
1263
|
+
} else {
|
|
1264
|
+
try {
|
|
1265
|
+
const parsedToolCall = relaxed_json_exports.parse(currentToolCallJson);
|
|
1266
|
+
if (currentTextId && hasEmittedTextStart) {
|
|
1267
|
+
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1268
|
+
currentTextId = null;
|
|
1269
|
+
hasEmittedTextStart = false;
|
|
1270
|
+
}
|
|
1271
|
+
controller.enqueue({
|
|
1272
|
+
type: "tool-call",
|
|
1273
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1274
|
+
toolName: parsedToolCall.name,
|
|
1275
|
+
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1276
|
+
});
|
|
1277
|
+
} catch (e) {
|
|
1278
|
+
const errorId = (0, import_provider_utils2.generateId)();
|
|
1279
|
+
controller.enqueue({ type: "text-start", id: errorId });
|
|
1280
|
+
controller.enqueue({
|
|
1281
|
+
type: "text-delta",
|
|
1282
|
+
id: errorId,
|
|
1283
|
+
delta: `${toolCallStart}${currentToolCallJson}${toolCallEnd}`
|
|
1284
|
+
});
|
|
1285
|
+
controller.enqueue({ type: "text-end", id: errorId });
|
|
1286
|
+
if (options == null ? void 0 : options.onError) {
|
|
1287
|
+
options.onError(
|
|
1288
|
+
"Could not process streaming JSON tool call; emitting original text.",
|
|
1289
|
+
{
|
|
1290
|
+
toolCall: `${toolCallStart}${currentToolCallJson}${toolCallEnd}`
|
|
1291
|
+
}
|
|
1292
|
+
);
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
currentToolCallJson = "";
|
|
1296
|
+
isInsideToolCall = false;
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
if (!isInsideToolCall) {
|
|
1300
|
+
const potentialIndex = getPotentialStartIndex(buffer, toolCallStart);
|
|
1301
|
+
if (potentialIndex != null && potentialIndex + toolCallStart.length > buffer.length) {
|
|
1302
|
+
publish(buffer.slice(0, potentialIndex));
|
|
1303
|
+
buffer = buffer.slice(potentialIndex);
|
|
1304
|
+
} else {
|
|
1305
|
+
publish(buffer);
|
|
1306
|
+
buffer = "";
|
|
1307
|
+
}
|
|
1272
1308
|
}
|
|
1273
1309
|
}
|
|
1274
|
-
};
|
|
1310
|
+
});
|
|
1311
|
+
},
|
|
1312
|
+
extractToolCallSegments({ text }) {
|
|
1313
|
+
const startEsc = escapeRegExp(toolCallStart);
|
|
1314
|
+
const endEsc = escapeRegExp(toolCallEnd);
|
|
1315
|
+
const regex = new RegExp(`${startEsc}([\0-\uFFFF]*?)${endEsc}`, "gs");
|
|
1316
|
+
const segments = [];
|
|
1317
|
+
let m;
|
|
1318
|
+
while ((m = regex.exec(text)) != null) {
|
|
1319
|
+
segments.push(m[0]);
|
|
1320
|
+
}
|
|
1321
|
+
return segments;
|
|
1275
1322
|
}
|
|
1276
|
-
|
|
1323
|
+
});
|
|
1324
|
+
|
|
1325
|
+
// src/protocols/morph-xml-protocol.ts
|
|
1326
|
+
var import_provider_utils3 = require("@ai-sdk/provider-utils");
|
|
1327
|
+
var import_fast_xml_parser = require("fast-xml-parser");
|
|
1328
|
+
var WARN_ON_DUPLICATE_STRING_TAGS = true;
|
|
1329
|
+
function getToolSchema(tools, originalSchemas, toolName) {
|
|
1330
|
+
var _a;
|
|
1331
|
+
const original = originalSchemas[toolName];
|
|
1332
|
+
if (original) return original;
|
|
1333
|
+
const fallback = (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
1334
|
+
return fallback;
|
|
1277
1335
|
}
|
|
1278
|
-
function
|
|
1279
|
-
const
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1336
|
+
function getPropertySchema(toolSchema, key) {
|
|
1337
|
+
const unwrapped = unwrapJsonSchema(toolSchema);
|
|
1338
|
+
if (!unwrapped || typeof unwrapped !== "object") return void 0;
|
|
1339
|
+
const u = unwrapped;
|
|
1340
|
+
const props = u.properties;
|
|
1341
|
+
if (props && Object.prototype.hasOwnProperty.call(props, key)) {
|
|
1342
|
+
return props[key];
|
|
1343
|
+
}
|
|
1344
|
+
return void 0;
|
|
1345
|
+
}
|
|
1346
|
+
function extractRawInner(xmlContent, tagName) {
|
|
1347
|
+
const isNameStartChar = (ch) => /[A-Za-z_:]/.test(ch);
|
|
1348
|
+
const isNameChar = (ch) => /[A-Za-z0-9_.:-]/.test(ch);
|
|
1349
|
+
const len = xmlContent.length;
|
|
1350
|
+
const target = tagName;
|
|
1351
|
+
let bestStart = -1;
|
|
1352
|
+
let bestEnd = -1;
|
|
1353
|
+
let bestDepth = Number.POSITIVE_INFINITY;
|
|
1354
|
+
const skipQuoted = (s, i2) => {
|
|
1355
|
+
const quote = s[i2];
|
|
1356
|
+
i2++;
|
|
1357
|
+
while (i2 < s.length) {
|
|
1358
|
+
const ch = s[i2];
|
|
1359
|
+
if (ch === "\\") {
|
|
1360
|
+
i2 += 2;
|
|
1361
|
+
continue;
|
|
1362
|
+
}
|
|
1363
|
+
if (ch === quote) {
|
|
1364
|
+
return i2 + 1;
|
|
1365
|
+
}
|
|
1366
|
+
i2++;
|
|
1367
|
+
}
|
|
1368
|
+
return i2;
|
|
1369
|
+
};
|
|
1370
|
+
let i = 0;
|
|
1371
|
+
let depth = 0;
|
|
1372
|
+
while (i < len) {
|
|
1373
|
+
const lt = xmlContent.indexOf("<", i);
|
|
1374
|
+
if (lt === -1) return void 0;
|
|
1375
|
+
i = lt + 1;
|
|
1376
|
+
if (i >= len) return void 0;
|
|
1377
|
+
const ch = xmlContent[i];
|
|
1378
|
+
if (ch === "!") {
|
|
1379
|
+
if (xmlContent.startsWith("!--", i + 1)) {
|
|
1380
|
+
const close = xmlContent.indexOf("-->", i + 4);
|
|
1381
|
+
i = close === -1 ? len : close + 3;
|
|
1382
|
+
continue;
|
|
1383
|
+
}
|
|
1384
|
+
if (xmlContent.startsWith("![CDATA[", i + 1)) {
|
|
1385
|
+
const close = xmlContent.indexOf("]]>", i + 9);
|
|
1386
|
+
i = close === -1 ? len : close + 3;
|
|
1387
|
+
continue;
|
|
1388
|
+
}
|
|
1389
|
+
const gt = xmlContent.indexOf(">", i + 1);
|
|
1390
|
+
i = gt === -1 ? len : gt + 1;
|
|
1391
|
+
continue;
|
|
1392
|
+
} else if (ch === "?") {
|
|
1393
|
+
const close = xmlContent.indexOf("?>", i + 1);
|
|
1394
|
+
i = close === -1 ? len : close + 2;
|
|
1395
|
+
continue;
|
|
1396
|
+
} else if (ch === "/") {
|
|
1397
|
+
let j = i + 1;
|
|
1398
|
+
if (j < len && isNameStartChar(xmlContent[j])) {
|
|
1399
|
+
j++;
|
|
1400
|
+
while (j < len && isNameChar(xmlContent[j])) j++;
|
|
1401
|
+
}
|
|
1402
|
+
const gt = xmlContent.indexOf(">", j);
|
|
1403
|
+
i = gt === -1 ? len : gt + 1;
|
|
1404
|
+
depth = Math.max(0, depth - 1);
|
|
1405
|
+
continue;
|
|
1406
|
+
} else {
|
|
1407
|
+
let j = i;
|
|
1408
|
+
if (j < len && isNameStartChar(xmlContent[j])) {
|
|
1409
|
+
j++;
|
|
1410
|
+
while (j < len && isNameChar(xmlContent[j])) j++;
|
|
1411
|
+
}
|
|
1412
|
+
const name = xmlContent.slice(i, j);
|
|
1413
|
+
let k = j;
|
|
1414
|
+
let isSelfClosing = false;
|
|
1415
|
+
while (k < len) {
|
|
1416
|
+
const c = xmlContent[k];
|
|
1417
|
+
if (c === '"' || c === "'") {
|
|
1418
|
+
k = skipQuoted(xmlContent, k);
|
|
1419
|
+
continue;
|
|
1420
|
+
}
|
|
1421
|
+
if (c === ">") {
|
|
1422
|
+
break;
|
|
1304
1423
|
}
|
|
1424
|
+
if (c === "/" && xmlContent[k + 1] === ">") {
|
|
1425
|
+
isSelfClosing = true;
|
|
1426
|
+
k++;
|
|
1427
|
+
break;
|
|
1428
|
+
}
|
|
1429
|
+
k++;
|
|
1305
1430
|
}
|
|
1306
|
-
const
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1431
|
+
const tagEnd = k;
|
|
1432
|
+
if (name === target) {
|
|
1433
|
+
const contentStart = xmlContent[tagEnd] === ">" ? tagEnd + 1 : tagEnd + 1;
|
|
1434
|
+
if (isSelfClosing) {
|
|
1435
|
+
if (depth < bestDepth) {
|
|
1436
|
+
bestStart = contentStart;
|
|
1437
|
+
bestEnd = contentStart;
|
|
1438
|
+
bestDepth = depth;
|
|
1439
|
+
if (bestDepth === 0) {
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
} else {
|
|
1443
|
+
let pos = contentStart;
|
|
1444
|
+
let sameDepth = 1;
|
|
1445
|
+
while (pos < len) {
|
|
1446
|
+
const nextLt = xmlContent.indexOf("<", pos);
|
|
1447
|
+
if (nextLt === -1) break;
|
|
1448
|
+
const nx = nextLt + 1;
|
|
1449
|
+
if (nx >= len) break;
|
|
1450
|
+
const h = xmlContent[nx];
|
|
1451
|
+
if (h === "!") {
|
|
1452
|
+
if (xmlContent.startsWith("!--", nx + 1)) {
|
|
1453
|
+
const close = xmlContent.indexOf("-->", nx + 4);
|
|
1454
|
+
pos = close === -1 ? len : close + 3;
|
|
1455
|
+
continue;
|
|
1456
|
+
}
|
|
1457
|
+
if (xmlContent.startsWith("![CDATA[", nx + 1)) {
|
|
1458
|
+
const close = xmlContent.indexOf("]]>", nx + 9);
|
|
1459
|
+
pos = close === -1 ? len : close + 3;
|
|
1460
|
+
continue;
|
|
1461
|
+
}
|
|
1462
|
+
const gt2 = xmlContent.indexOf(">", nx + 1);
|
|
1463
|
+
pos = gt2 === -1 ? len : gt2 + 1;
|
|
1464
|
+
continue;
|
|
1465
|
+
} else if (h === "?") {
|
|
1466
|
+
const close = xmlContent.indexOf("?>", nx + 1);
|
|
1467
|
+
pos = close === -1 ? len : close + 2;
|
|
1468
|
+
continue;
|
|
1469
|
+
} else if (h === "/") {
|
|
1470
|
+
let t = nx + 1;
|
|
1471
|
+
if (t < len && isNameStartChar(xmlContent[t])) {
|
|
1472
|
+
t++;
|
|
1473
|
+
while (t < len && isNameChar(xmlContent[t])) t++;
|
|
1474
|
+
}
|
|
1475
|
+
const endName = xmlContent.slice(nx + 1, t);
|
|
1476
|
+
const gt2 = xmlContent.indexOf(">", t);
|
|
1477
|
+
if (endName === target) {
|
|
1478
|
+
sameDepth--;
|
|
1479
|
+
if (sameDepth === 0) {
|
|
1480
|
+
if (depth < bestDepth) {
|
|
1481
|
+
bestStart = contentStart;
|
|
1482
|
+
bestEnd = nextLt;
|
|
1483
|
+
bestDepth = depth;
|
|
1484
|
+
if (bestDepth === 0) {
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
break;
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
pos = gt2 === -1 ? len : gt2 + 1;
|
|
1491
|
+
continue;
|
|
1492
|
+
} else {
|
|
1493
|
+
let t = nx;
|
|
1494
|
+
if (t < len && isNameStartChar(xmlContent[t])) {
|
|
1495
|
+
t++;
|
|
1496
|
+
while (t < len && isNameChar(xmlContent[t])) t++;
|
|
1497
|
+
}
|
|
1498
|
+
const startName = xmlContent.slice(nx, t);
|
|
1499
|
+
let u = t;
|
|
1500
|
+
let selfClose = false;
|
|
1501
|
+
while (u < len) {
|
|
1502
|
+
const cu = xmlContent[u];
|
|
1503
|
+
if (cu === '"' || cu === "'") {
|
|
1504
|
+
u = skipQuoted(xmlContent, u);
|
|
1505
|
+
continue;
|
|
1506
|
+
}
|
|
1507
|
+
if (cu === ">") break;
|
|
1508
|
+
if (cu === "/" && xmlContent[u + 1] === ">") {
|
|
1509
|
+
selfClose = true;
|
|
1510
|
+
u++;
|
|
1511
|
+
break;
|
|
1512
|
+
}
|
|
1513
|
+
u++;
|
|
1514
|
+
}
|
|
1515
|
+
if (startName === target && !selfClose) {
|
|
1516
|
+
sameDepth++;
|
|
1517
|
+
}
|
|
1518
|
+
pos = xmlContent[u] === ">" ? u + 1 : u + 1;
|
|
1519
|
+
continue;
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1311
1522
|
}
|
|
1312
|
-
|
|
1313
|
-
|
|
1523
|
+
}
|
|
1524
|
+
i = xmlContent[tagEnd] === ">" ? tagEnd + 1 : tagEnd + 1;
|
|
1525
|
+
depth += isSelfClosing ? 0 : 1;
|
|
1526
|
+
continue;
|
|
1314
1527
|
}
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1528
|
+
}
|
|
1529
|
+
if (bestStart !== -1) {
|
|
1530
|
+
return xmlContent.slice(bestStart, bestEnd);
|
|
1531
|
+
}
|
|
1532
|
+
return void 0;
|
|
1533
|
+
}
|
|
1534
|
+
function findFirstTopLevelRange(xmlContent, tagName) {
|
|
1535
|
+
const isNameStartChar = (ch) => /[A-Za-z_:]/.test(ch);
|
|
1536
|
+
const isNameChar = (ch) => /[A-Za-z0-9_.:-]/.test(ch);
|
|
1537
|
+
const len = xmlContent.length;
|
|
1538
|
+
const target = tagName;
|
|
1539
|
+
const skipQuoted = (s, i2) => {
|
|
1540
|
+
const quote = s[i2];
|
|
1541
|
+
i2++;
|
|
1542
|
+
while (i2 < s.length) {
|
|
1543
|
+
const ch = s[i2];
|
|
1544
|
+
if (ch === "\\") {
|
|
1545
|
+
i2 += 2;
|
|
1546
|
+
continue;
|
|
1547
|
+
}
|
|
1548
|
+
if (ch === quote) return i2 + 1;
|
|
1549
|
+
i2++;
|
|
1330
1550
|
}
|
|
1331
|
-
return
|
|
1332
|
-
}
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1551
|
+
return i2;
|
|
1552
|
+
};
|
|
1553
|
+
let i = 0;
|
|
1554
|
+
let depth = 0;
|
|
1555
|
+
while (i < len) {
|
|
1556
|
+
const lt = xmlContent.indexOf("<", i);
|
|
1557
|
+
if (lt === -1) return void 0;
|
|
1558
|
+
i = lt + 1;
|
|
1559
|
+
if (i >= len) return void 0;
|
|
1560
|
+
const ch = xmlContent[i];
|
|
1561
|
+
if (ch === "!") {
|
|
1562
|
+
if (xmlContent.startsWith("!--", i + 1)) {
|
|
1563
|
+
const close = xmlContent.indexOf("-->", i + 4);
|
|
1564
|
+
i = close === -1 ? len : close + 3;
|
|
1565
|
+
continue;
|
|
1566
|
+
}
|
|
1567
|
+
if (xmlContent.startsWith("![CDATA[", i + 1)) {
|
|
1568
|
+
const close = xmlContent.indexOf("]]>", i + 9);
|
|
1569
|
+
i = close === -1 ? len : close + 3;
|
|
1570
|
+
continue;
|
|
1571
|
+
}
|
|
1572
|
+
const gt = xmlContent.indexOf(">", i + 1);
|
|
1573
|
+
i = gt === -1 ? len : gt + 1;
|
|
1574
|
+
continue;
|
|
1575
|
+
} else if (ch === "?") {
|
|
1576
|
+
const close = xmlContent.indexOf("?>", i + 1);
|
|
1577
|
+
i = close === -1 ? len : close + 2;
|
|
1578
|
+
continue;
|
|
1579
|
+
} else if (ch === "/") {
|
|
1580
|
+
const gt = xmlContent.indexOf(">", i + 1);
|
|
1581
|
+
i = gt === -1 ? len : gt + 1;
|
|
1582
|
+
depth = Math.max(0, depth - 1);
|
|
1583
|
+
continue;
|
|
1584
|
+
} else {
|
|
1585
|
+
let j = i;
|
|
1586
|
+
if (j < len && isNameStartChar(xmlContent[j])) {
|
|
1587
|
+
j++;
|
|
1588
|
+
while (j < len && isNameChar(xmlContent[j])) j++;
|
|
1589
|
+
}
|
|
1590
|
+
const name = xmlContent.slice(i, j);
|
|
1591
|
+
let k = j;
|
|
1592
|
+
let isSelfClosing = false;
|
|
1593
|
+
while (k < len) {
|
|
1594
|
+
const c = xmlContent[k];
|
|
1595
|
+
if (c === '"' || c === "'") {
|
|
1596
|
+
k = skipQuoted(xmlContent, k);
|
|
1597
|
+
continue;
|
|
1598
|
+
}
|
|
1599
|
+
if (c === ">") break;
|
|
1600
|
+
if (c === "/" && xmlContent[k + 1] === ">") {
|
|
1601
|
+
isSelfClosing = true;
|
|
1602
|
+
k++;
|
|
1603
|
+
break;
|
|
1604
|
+
}
|
|
1605
|
+
k++;
|
|
1606
|
+
}
|
|
1607
|
+
const tagEnd = k;
|
|
1608
|
+
if (depth === 0 && name === target) {
|
|
1609
|
+
const contentStart = xmlContent[tagEnd] === ">" ? tagEnd + 1 : tagEnd + 1;
|
|
1610
|
+
if (isSelfClosing) return { start: contentStart, end: contentStart };
|
|
1611
|
+
let pos = contentStart;
|
|
1612
|
+
let sameDepth = 1;
|
|
1613
|
+
while (pos < len) {
|
|
1614
|
+
const nextLt = xmlContent.indexOf("<", pos);
|
|
1615
|
+
if (nextLt === -1) break;
|
|
1616
|
+
const nx = nextLt + 1;
|
|
1617
|
+
if (nx >= len) break;
|
|
1618
|
+
const h = xmlContent[nx];
|
|
1619
|
+
if (h === "!") {
|
|
1620
|
+
if (xmlContent.startsWith("!--", nx + 1)) {
|
|
1621
|
+
const close = xmlContent.indexOf("-->", nx + 4);
|
|
1622
|
+
pos = close === -1 ? len : close + 3;
|
|
1623
|
+
continue;
|
|
1624
|
+
}
|
|
1625
|
+
if (xmlContent.startsWith("![CDATA[", nx + 1)) {
|
|
1626
|
+
const close = xmlContent.indexOf("]]>", nx + 9);
|
|
1627
|
+
pos = close === -1 ? len : close + 3;
|
|
1628
|
+
continue;
|
|
1629
|
+
}
|
|
1630
|
+
const gt2 = xmlContent.indexOf(">", nx + 1);
|
|
1631
|
+
pos = gt2 === -1 ? len : gt2 + 1;
|
|
1632
|
+
continue;
|
|
1633
|
+
} else if (h === "?") {
|
|
1634
|
+
const close = xmlContent.indexOf("?>", nx + 1);
|
|
1635
|
+
pos = close === -1 ? len : close + 2;
|
|
1636
|
+
continue;
|
|
1637
|
+
} else if (h === "/") {
|
|
1638
|
+
let t = nx + 1;
|
|
1639
|
+
if (t < len && isNameStartChar(xmlContent[t])) {
|
|
1640
|
+
t++;
|
|
1641
|
+
while (t < len && isNameChar(xmlContent[t])) t++;
|
|
1642
|
+
}
|
|
1643
|
+
const endName = xmlContent.slice(nx + 1, t);
|
|
1644
|
+
const gt2 = xmlContent.indexOf(">", t);
|
|
1645
|
+
if (endName === target) {
|
|
1646
|
+
sameDepth--;
|
|
1647
|
+
if (sameDepth === 0) {
|
|
1648
|
+
return { start: contentStart, end: nextLt };
|
|
1353
1649
|
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1650
|
+
}
|
|
1651
|
+
pos = gt2 === -1 ? len : gt2 + 1;
|
|
1652
|
+
continue;
|
|
1653
|
+
} else {
|
|
1654
|
+
let t = nx;
|
|
1655
|
+
if (t < len && isNameStartChar(xmlContent[t])) {
|
|
1656
|
+
t++;
|
|
1657
|
+
while (t < len && isNameChar(xmlContent[t])) t++;
|
|
1658
|
+
}
|
|
1659
|
+
let u = t;
|
|
1660
|
+
let selfClose = false;
|
|
1661
|
+
while (u < len) {
|
|
1662
|
+
const cu = xmlContent[u];
|
|
1663
|
+
if (cu === '"' || cu === "'") {
|
|
1664
|
+
u = skipQuoted(xmlContent, u);
|
|
1665
|
+
continue;
|
|
1363
1666
|
}
|
|
1364
|
-
|
|
1365
|
-
|
|
1667
|
+
if (cu === ">") break;
|
|
1668
|
+
if (cu === "/" && xmlContent[u + 1] === ">") {
|
|
1669
|
+
selfClose = true;
|
|
1670
|
+
u++;
|
|
1671
|
+
break;
|
|
1672
|
+
}
|
|
1673
|
+
u++;
|
|
1674
|
+
}
|
|
1675
|
+
if (!selfClose) {
|
|
1676
|
+
}
|
|
1677
|
+
pos = xmlContent[u] === ">" ? u + 1 : u + 1;
|
|
1678
|
+
continue;
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
return void 0;
|
|
1682
|
+
}
|
|
1683
|
+
i = xmlContent[tagEnd] === ">" ? tagEnd + 1 : tagEnd + 1;
|
|
1684
|
+
depth += isSelfClosing ? 0 : 1;
|
|
1685
|
+
continue;
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
return void 0;
|
|
1689
|
+
}
|
|
1690
|
+
function countTagOccurrences(xmlContent, tagName, excludeRanges, skipFirst = true) {
|
|
1691
|
+
const isNameStartChar = (ch) => /[A-Za-z_:]/.test(ch);
|
|
1692
|
+
const isNameChar = (ch) => /[A-Za-z0-9_.:-]/.test(ch);
|
|
1693
|
+
const len = xmlContent.length;
|
|
1694
|
+
const target = tagName;
|
|
1695
|
+
const skipQuoted = (s, i2) => {
|
|
1696
|
+
const quote = s[i2];
|
|
1697
|
+
i2++;
|
|
1698
|
+
while (i2 < s.length) {
|
|
1699
|
+
const ch = s[i2];
|
|
1700
|
+
if (ch === "\\") {
|
|
1701
|
+
i2 += 2;
|
|
1702
|
+
continue;
|
|
1703
|
+
}
|
|
1704
|
+
if (ch === quote) return i2 + 1;
|
|
1705
|
+
i2++;
|
|
1706
|
+
}
|
|
1707
|
+
return i2;
|
|
1708
|
+
};
|
|
1709
|
+
let i = 0;
|
|
1710
|
+
let count = 0;
|
|
1711
|
+
const isExcluded = (pos) => {
|
|
1712
|
+
if (!excludeRanges || excludeRanges.length === 0) return false;
|
|
1713
|
+
for (const r of excludeRanges) {
|
|
1714
|
+
if (pos >= r.start && pos < r.end) return true;
|
|
1715
|
+
}
|
|
1716
|
+
return false;
|
|
1717
|
+
};
|
|
1718
|
+
while (i < len) {
|
|
1719
|
+
const lt = xmlContent.indexOf("<", i);
|
|
1720
|
+
if (lt === -1) break;
|
|
1721
|
+
i = lt + 1;
|
|
1722
|
+
if (i >= len) break;
|
|
1723
|
+
const ch = xmlContent[i];
|
|
1724
|
+
if (ch === "!") {
|
|
1725
|
+
if (xmlContent.startsWith("!--", i + 1)) {
|
|
1726
|
+
const close = xmlContent.indexOf("-->", i + 4);
|
|
1727
|
+
i = close === -1 ? len : close + 3;
|
|
1728
|
+
continue;
|
|
1729
|
+
}
|
|
1730
|
+
if (xmlContent.startsWith("![CDATA[", i + 1)) {
|
|
1731
|
+
const close = xmlContent.indexOf("]]>", i + 9);
|
|
1732
|
+
i = close === -1 ? len : close + 3;
|
|
1733
|
+
continue;
|
|
1734
|
+
}
|
|
1735
|
+
const gt = xmlContent.indexOf(">", i + 1);
|
|
1736
|
+
i = gt === -1 ? len : gt + 1;
|
|
1737
|
+
continue;
|
|
1738
|
+
} else if (ch === "?") {
|
|
1739
|
+
const close = xmlContent.indexOf("?>", i + 1);
|
|
1740
|
+
i = close === -1 ? len : close + 2;
|
|
1741
|
+
continue;
|
|
1742
|
+
} else if (ch === "/") {
|
|
1743
|
+
const gt = xmlContent.indexOf(">", i + 1);
|
|
1744
|
+
i = gt === -1 ? len : gt + 1;
|
|
1745
|
+
continue;
|
|
1746
|
+
} else {
|
|
1747
|
+
let j = i;
|
|
1748
|
+
if (j < len && isNameStartChar(xmlContent[j])) {
|
|
1749
|
+
j++;
|
|
1750
|
+
while (j < len && isNameChar(xmlContent[j])) j++;
|
|
1751
|
+
}
|
|
1752
|
+
const name = xmlContent.slice(i, j);
|
|
1753
|
+
let k = j;
|
|
1754
|
+
while (k < len) {
|
|
1755
|
+
const c = xmlContent[k];
|
|
1756
|
+
if (c === '"' || c === "'") {
|
|
1757
|
+
k = skipQuoted(xmlContent, k);
|
|
1758
|
+
continue;
|
|
1759
|
+
}
|
|
1760
|
+
if (c === ">") break;
|
|
1761
|
+
if (c === "/" && xmlContent[k + 1] === ">") {
|
|
1762
|
+
k++;
|
|
1763
|
+
break;
|
|
1366
1764
|
}
|
|
1765
|
+
k++;
|
|
1367
1766
|
}
|
|
1767
|
+
if (name === target && !isExcluded(lt)) {
|
|
1768
|
+
if (skipFirst) {
|
|
1769
|
+
skipFirst = false;
|
|
1770
|
+
} else {
|
|
1771
|
+
count++;
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
i = k + 1;
|
|
1775
|
+
continue;
|
|
1368
1776
|
}
|
|
1369
1777
|
}
|
|
1370
|
-
|
|
1371
|
-
const current = processedPrompt[i];
|
|
1372
|
-
const prev = processedPrompt[i - 1];
|
|
1373
|
-
if (current.role === "user" && prev.role === "user") {
|
|
1374
|
-
const prevContent = prev.content.map((c) => c.type === "text" ? c.text : "").join("\n");
|
|
1375
|
-
const currentContent = current.content.map((c) => c.type === "text" ? c.text : "").join("\n");
|
|
1376
|
-
processedPrompt[i - 1] = {
|
|
1377
|
-
role: "user",
|
|
1378
|
-
content: [{ type: "text", text: prevContent + "\n" + currentContent }]
|
|
1379
|
-
};
|
|
1380
|
-
processedPrompt.splice(i, 1);
|
|
1381
|
-
}
|
|
1382
|
-
}
|
|
1383
|
-
return processedPrompt;
|
|
1778
|
+
return count;
|
|
1384
1779
|
}
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
if (
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1780
|
+
function processParsedArgs(parsedArgs, toolSchema, toolContent, toolName, options) {
|
|
1781
|
+
var _a, _b, _c;
|
|
1782
|
+
const args = {};
|
|
1783
|
+
let cancelToolCall = false;
|
|
1784
|
+
const stringTypedProps = (() => {
|
|
1785
|
+
const set = /* @__PURE__ */ new Set();
|
|
1786
|
+
const unwrapped = unwrapJsonSchema(toolSchema);
|
|
1787
|
+
if (unwrapped && typeof unwrapped === "object") {
|
|
1788
|
+
const u = unwrapped;
|
|
1789
|
+
const props = u.properties;
|
|
1790
|
+
if (props && typeof props === "object") {
|
|
1791
|
+
for (const key of Object.keys(props)) {
|
|
1792
|
+
const t = getSchemaType(props[key]);
|
|
1793
|
+
if (t === "string") set.add(key);
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
return set;
|
|
1798
|
+
})();
|
|
1799
|
+
for (const k of Object.keys(parsedArgs || {})) {
|
|
1800
|
+
const v = parsedArgs[k];
|
|
1801
|
+
let val = v;
|
|
1802
|
+
const propSchema = getPropertySchema(toolSchema, k);
|
|
1803
|
+
const propType = getSchemaType(propSchema);
|
|
1804
|
+
if (propType === "string" && !Array.isArray(v)) {
|
|
1805
|
+
const excludeRanges = [];
|
|
1806
|
+
for (const other of stringTypedProps) {
|
|
1807
|
+
if (other === k) continue;
|
|
1808
|
+
const range = findFirstTopLevelRange(toolContent, other);
|
|
1809
|
+
if (range) excludeRanges.push(range);
|
|
1810
|
+
}
|
|
1811
|
+
const occurrences = countTagOccurrences(
|
|
1812
|
+
toolContent,
|
|
1813
|
+
k,
|
|
1814
|
+
excludeRanges,
|
|
1815
|
+
true
|
|
1816
|
+
);
|
|
1817
|
+
if (occurrences > 0) {
|
|
1818
|
+
if (WARN_ON_DUPLICATE_STRING_TAGS) {
|
|
1819
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1820
|
+
options,
|
|
1821
|
+
`Duplicate string tags for <${k}> detected; cancelling tool call`,
|
|
1822
|
+
{
|
|
1823
|
+
toolName,
|
|
1824
|
+
toolCall: `<${toolName}>${toolContent}</${toolName}>`
|
|
1825
|
+
}
|
|
1826
|
+
);
|
|
1827
|
+
}
|
|
1828
|
+
cancelToolCall = true;
|
|
1829
|
+
break;
|
|
1830
|
+
}
|
|
1831
|
+
const raw = extractRawInner(toolContent, k);
|
|
1832
|
+
if (typeof raw === "string") {
|
|
1833
|
+
args[k] = raw;
|
|
1834
|
+
continue;
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
if (v && typeof v === "object" && Object.prototype.hasOwnProperty.call(v, "#text")) {
|
|
1838
|
+
val = v == null ? void 0 : v["#text"];
|
|
1839
|
+
}
|
|
1840
|
+
if (Array.isArray(v)) {
|
|
1841
|
+
if (propType === "string") {
|
|
1842
|
+
const mapped = v.map((item) => {
|
|
1843
|
+
if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
|
|
1844
|
+
const textVal = item == null ? void 0 : item["#text"];
|
|
1845
|
+
return typeof textVal === "string" ? textVal : String(textVal);
|
|
1846
|
+
}
|
|
1847
|
+
return typeof item === "string" ? item : String(item);
|
|
1399
1848
|
});
|
|
1849
|
+
if (mapped.length > 1 && WARN_ON_DUPLICATE_STRING_TAGS) {
|
|
1850
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
1851
|
+
options,
|
|
1852
|
+
`Duplicate string tags for <${k}> detected; cancelling tool call`,
|
|
1853
|
+
{
|
|
1854
|
+
toolName,
|
|
1855
|
+
toolCall: `<${toolName}>${toolContent}</${toolName}>`
|
|
1856
|
+
}
|
|
1857
|
+
);
|
|
1858
|
+
}
|
|
1859
|
+
if (mapped.length > 1) {
|
|
1860
|
+
cancelToolCall = true;
|
|
1861
|
+
break;
|
|
1862
|
+
} else {
|
|
1863
|
+
args[k] = (_c = mapped[0]) != null ? _c : "";
|
|
1864
|
+
continue;
|
|
1865
|
+
}
|
|
1400
1866
|
} else {
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1867
|
+
val = v.map((item) => {
|
|
1868
|
+
if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
|
|
1869
|
+
const textVal = item == null ? void 0 : item["#text"];
|
|
1870
|
+
return typeof textVal === "string" ? textVal.trim() : textVal;
|
|
1871
|
+
}
|
|
1872
|
+
return typeof item === "string" ? item.trim() : item;
|
|
1406
1873
|
});
|
|
1407
1874
|
}
|
|
1408
|
-
},
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1875
|
+
} else if (v && typeof v === "object" && !Object.prototype.hasOwnProperty.call(v, "#text")) {
|
|
1876
|
+
const obj = v;
|
|
1877
|
+
const keys = Object.keys(obj);
|
|
1878
|
+
if (keys.length === 1 && keys[0] === "item") {
|
|
1879
|
+
const itemValue = obj.item;
|
|
1880
|
+
if (Array.isArray(itemValue)) {
|
|
1881
|
+
val = itemValue.map((item) => {
|
|
1882
|
+
let currentVal = item;
|
|
1883
|
+
if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
|
|
1884
|
+
currentVal = item == null ? void 0 : item["#text"];
|
|
1885
|
+
}
|
|
1886
|
+
const trimmed = typeof currentVal === "string" ? currentVal.trim() : currentVal;
|
|
1887
|
+
if (typeof trimmed === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed)) {
|
|
1888
|
+
const num = Number(trimmed);
|
|
1889
|
+
if (Number.isFinite(num)) return num;
|
|
1890
|
+
}
|
|
1891
|
+
return trimmed;
|
|
1892
|
+
});
|
|
1893
|
+
} else {
|
|
1894
|
+
const trimmed = typeof itemValue === "string" ? itemValue.trim() : itemValue;
|
|
1895
|
+
if (typeof trimmed === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed)) {
|
|
1896
|
+
const num = Number(trimmed);
|
|
1897
|
+
val = Number.isFinite(num) ? num : trimmed;
|
|
1898
|
+
} else {
|
|
1899
|
+
val = trimmed;
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
} else {
|
|
1903
|
+
let isIndexedTuple = false;
|
|
1904
|
+
if (keys.length > 0 && keys.every((key) => /^\d+$/.test(key))) {
|
|
1905
|
+
const indices = keys.map((k2) => parseInt(k2, 10)).sort((a, b) => a - b);
|
|
1906
|
+
isIndexedTuple = indices[0] === 0 && indices.every((val2, idx) => val2 === idx);
|
|
1907
|
+
}
|
|
1908
|
+
if (isIndexedTuple) {
|
|
1909
|
+
const sortedKeys = keys.sort(
|
|
1910
|
+
(a, b) => parseInt(a, 10) - parseInt(b, 10)
|
|
1911
|
+
);
|
|
1912
|
+
val = sortedKeys.map((key) => {
|
|
1913
|
+
const item = obj[key];
|
|
1914
|
+
if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
|
|
1915
|
+
const textVal = item == null ? void 0 : item["#text"];
|
|
1916
|
+
return typeof textVal === "string" ? textVal.trim() : textVal;
|
|
1917
|
+
}
|
|
1918
|
+
return typeof item === "string" ? item.trim() : item;
|
|
1919
|
+
});
|
|
1920
|
+
} else {
|
|
1921
|
+
val = v;
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1422
1924
|
}
|
|
1423
|
-
|
|
1925
|
+
args[k] = typeof val === "string" ? val.trim() : val;
|
|
1926
|
+
}
|
|
1927
|
+
return { args, cancelToolCall };
|
|
1424
1928
|
}
|
|
1425
|
-
|
|
1426
|
-
// src/protocols/json-mix-protocol.ts
|
|
1427
|
-
var import_provider_utils3 = require("@ai-sdk/provider-utils");
|
|
1428
|
-
var jsonMixProtocol = ({
|
|
1429
|
-
toolCallStart = "<tool_call>",
|
|
1430
|
-
toolCallEnd = "</tool_call>",
|
|
1431
|
-
toolResponseStart = "<tool_response>",
|
|
1432
|
-
toolResponseEnd = "</tool_response>"
|
|
1433
|
-
} = {}) => ({
|
|
1929
|
+
var morphXmlProtocol = () => ({
|
|
1434
1930
|
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
1435
|
-
const toolsForPrompt = (tools || []).
|
|
1931
|
+
const toolsForPrompt = (tools || []).map((tool) => ({
|
|
1436
1932
|
name: tool.name,
|
|
1437
|
-
description: tool.
|
|
1438
|
-
parameters: tool.inputSchema
|
|
1933
|
+
description: tool.description,
|
|
1934
|
+
parameters: unwrapJsonSchema(tool.inputSchema)
|
|
1439
1935
|
}));
|
|
1440
1936
|
return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
|
|
1441
1937
|
},
|
|
1442
1938
|
formatToolCall(toolCall) {
|
|
1939
|
+
const builder = new import_fast_xml_parser.XMLBuilder({ format: true, suppressEmptyNode: true });
|
|
1443
1940
|
let args = {};
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1941
|
+
const inputValue = hasInputProperty(toolCall) ? toolCall.input : void 0;
|
|
1942
|
+
if (typeof inputValue === "string") {
|
|
1943
|
+
try {
|
|
1944
|
+
args = JSON.parse(inputValue);
|
|
1945
|
+
} catch (e) {
|
|
1946
|
+
args = inputValue;
|
|
1947
|
+
}
|
|
1948
|
+
} else {
|
|
1949
|
+
args = inputValue;
|
|
1448
1950
|
}
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1951
|
+
const xmlContent = builder.build({
|
|
1952
|
+
[toolCall.toolName]: args
|
|
1953
|
+
});
|
|
1954
|
+
return xmlContent;
|
|
1453
1955
|
},
|
|
1454
1956
|
formatToolResponse(toolResult) {
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1957
|
+
const builder = new import_fast_xml_parser.XMLBuilder({ format: true });
|
|
1958
|
+
const xmlContent = builder.build({
|
|
1959
|
+
tool_response: {
|
|
1960
|
+
tool_name: toolResult.toolName,
|
|
1961
|
+
result: toolResult.output
|
|
1962
|
+
}
|
|
1963
|
+
});
|
|
1964
|
+
return xmlContent;
|
|
1459
1965
|
},
|
|
1460
|
-
parseGeneratedText({ text, options }) {
|
|
1461
|
-
var _a;
|
|
1462
|
-
const
|
|
1463
|
-
const
|
|
1966
|
+
parseGeneratedText({ text, tools, options }) {
|
|
1967
|
+
var _a, _b, _c;
|
|
1968
|
+
const originalSchemas = (options == null ? void 0 : options.originalToolSchemas) || {};
|
|
1969
|
+
const toolNames = tools.map((t) => t.name).filter((name) => name != null);
|
|
1970
|
+
if (toolNames.length === 0) {
|
|
1971
|
+
return [{ type: "text", text }];
|
|
1972
|
+
}
|
|
1973
|
+
const toolNamesPattern = toolNames.map((n) => escapeRegExp(n)).join("|");
|
|
1464
1974
|
const toolCallRegex = new RegExp(
|
|
1465
|
-
|
|
1466
|
-
"
|
|
1975
|
+
String.raw`<(${toolNamesPattern})>([\s\S]*?)<\/\1>`,
|
|
1976
|
+
"g"
|
|
1467
1977
|
);
|
|
1468
1978
|
const processedElements = [];
|
|
1469
1979
|
let currentIndex = 0;
|
|
1470
1980
|
let match;
|
|
1471
1981
|
while ((match = toolCallRegex.exec(text)) !== null) {
|
|
1472
1982
|
const startIndex = match.index;
|
|
1473
|
-
const
|
|
1983
|
+
const toolName = match[1];
|
|
1984
|
+
const toolContent = match[2].trim();
|
|
1474
1985
|
if (startIndex > currentIndex) {
|
|
1475
1986
|
const textSegment = text.substring(currentIndex, startIndex);
|
|
1476
1987
|
if (textSegment.trim()) {
|
|
1477
1988
|
processedElements.push({ type: "text", text: textSegment });
|
|
1478
1989
|
}
|
|
1479
1990
|
}
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1991
|
+
try {
|
|
1992
|
+
const parser = new import_fast_xml_parser.XMLParser({
|
|
1993
|
+
ignoreAttributes: false,
|
|
1994
|
+
parseTagValue: false,
|
|
1995
|
+
ignoreDeclaration: true,
|
|
1996
|
+
textNodeName: "#text"
|
|
1997
|
+
});
|
|
1998
|
+
const parsedArgs = ((_a = parser.parse(`<root>${toolContent}</root>`)) == null ? void 0 : _a.root) || {};
|
|
1999
|
+
const toolSchema = getToolSchema(tools, originalSchemas, toolName);
|
|
2000
|
+
const { args, cancelToolCall } = processParsedArgs(
|
|
2001
|
+
parsedArgs,
|
|
2002
|
+
toolSchema,
|
|
2003
|
+
toolContent,
|
|
2004
|
+
toolName,
|
|
2005
|
+
options
|
|
2006
|
+
);
|
|
2007
|
+
if (cancelToolCall) {
|
|
2008
|
+
const originalCallText = match[0];
|
|
2009
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
2010
|
+
options,
|
|
2011
|
+
`Duplicate string tags detected; cancelling tool call`,
|
|
2012
|
+
{ toolCall: originalCallText, toolName }
|
|
2013
|
+
);
|
|
2014
|
+
processedElements.push({ type: "text", text: originalCallText });
|
|
2015
|
+
} else {
|
|
2016
|
+
const coercedArgs = coerceBySchema(args, toolSchema);
|
|
1483
2017
|
processedElements.push({
|
|
1484
2018
|
type: "tool-call",
|
|
1485
2019
|
toolCallId: (0, import_provider_utils3.generateId)(),
|
|
1486
|
-
toolName
|
|
1487
|
-
input: JSON.stringify(
|
|
2020
|
+
toolName,
|
|
2021
|
+
input: JSON.stringify(coercedArgs)
|
|
1488
2022
|
});
|
|
1489
|
-
} catch (error) {
|
|
1490
|
-
if (options == null ? void 0 : options.onError) {
|
|
1491
|
-
options.onError(
|
|
1492
|
-
"Could not process JSON tool call, keeping original text.",
|
|
1493
|
-
{ toolCall: match[0], error }
|
|
1494
|
-
);
|
|
1495
|
-
}
|
|
1496
|
-
processedElements.push({ type: "text", text: match[0] });
|
|
1497
2023
|
}
|
|
2024
|
+
} catch (error) {
|
|
2025
|
+
const message = `Could not process XML tool call, keeping original text: ${match[0]}`;
|
|
2026
|
+
(_c = options == null ? void 0 : options.onError) == null ? void 0 : _c.call(options, message, { toolCall: match[0], toolName, error });
|
|
2027
|
+
processedElements.push({ type: "text", text: match[0] });
|
|
1498
2028
|
}
|
|
1499
2029
|
currentIndex = startIndex + match[0].length;
|
|
1500
2030
|
}
|
|
@@ -1506,524 +2036,722 @@ var jsonMixProtocol = ({
|
|
|
1506
2036
|
}
|
|
1507
2037
|
return processedElements;
|
|
1508
2038
|
},
|
|
1509
|
-
createStreamParser({ tools
|
|
1510
|
-
|
|
2039
|
+
createStreamParser({ tools, options }) {
|
|
2040
|
+
const originalSchemas = (options == null ? void 0 : options.originalToolSchemas) || {};
|
|
2041
|
+
const toolNames = tools.map((t) => t.name).filter((name) => name != null);
|
|
1511
2042
|
let buffer = "";
|
|
1512
|
-
let
|
|
2043
|
+
let currentToolCall = null;
|
|
1513
2044
|
let currentTextId = null;
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
delta: `${toolCallStart}${buffer}`
|
|
1529
|
-
});
|
|
1530
|
-
buffer = "";
|
|
1531
|
-
} else if (!isInsideToolCall && buffer.length > 0) {
|
|
1532
|
-
if (!currentTextId) {
|
|
1533
|
-
currentTextId = (0, import_provider_utils3.generateId)();
|
|
1534
|
-
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
1535
|
-
hasEmittedTextStart = true;
|
|
1536
|
-
}
|
|
1537
|
-
controller.enqueue({
|
|
1538
|
-
type: "text-delta",
|
|
1539
|
-
id: currentTextId,
|
|
1540
|
-
delta: buffer
|
|
1541
|
-
});
|
|
1542
|
-
buffer = "";
|
|
1543
|
-
}
|
|
1544
|
-
if (currentTextId && hasEmittedTextStart) {
|
|
1545
|
-
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1546
|
-
currentTextId = null;
|
|
1547
|
-
hasEmittedTextStart = false;
|
|
1548
|
-
}
|
|
1549
|
-
if (currentToolCallJson) {
|
|
1550
|
-
const errorId = (0, import_provider_utils3.generateId)();
|
|
1551
|
-
controller.enqueue({ type: "text-start", id: errorId });
|
|
1552
|
-
controller.enqueue({
|
|
1553
|
-
type: "text-delta",
|
|
1554
|
-
id: errorId,
|
|
1555
|
-
delta: `${toolCallStart}${currentToolCallJson}`
|
|
1556
|
-
});
|
|
1557
|
-
controller.enqueue({ type: "text-end", id: errorId });
|
|
1558
|
-
currentToolCallJson = "";
|
|
1559
|
-
}
|
|
1560
|
-
controller.enqueue(chunk);
|
|
1561
|
-
return;
|
|
2045
|
+
const flushText = (controller, text) => {
|
|
2046
|
+
const content = text != null ? text : buffer;
|
|
2047
|
+
if (content) {
|
|
2048
|
+
if (!currentTextId) {
|
|
2049
|
+
currentTextId = (0, import_provider_utils3.generateId)();
|
|
2050
|
+
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
2051
|
+
}
|
|
2052
|
+
controller.enqueue({
|
|
2053
|
+
type: "text-delta",
|
|
2054
|
+
id: currentTextId,
|
|
2055
|
+
delta: content
|
|
2056
|
+
});
|
|
2057
|
+
if (text === void 0) {
|
|
2058
|
+
buffer = "";
|
|
1562
2059
|
}
|
|
2060
|
+
}
|
|
2061
|
+
if (currentTextId && !text) {
|
|
2062
|
+
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
2063
|
+
currentTextId = null;
|
|
2064
|
+
}
|
|
2065
|
+
};
|
|
2066
|
+
return new TransformStream({
|
|
2067
|
+
transform(chunk, controller) {
|
|
2068
|
+
var _a;
|
|
1563
2069
|
if (chunk.type !== "text-delta") {
|
|
2070
|
+
if (buffer) flushText(controller);
|
|
1564
2071
|
controller.enqueue(chunk);
|
|
1565
2072
|
return;
|
|
1566
2073
|
}
|
|
1567
2074
|
buffer += chunk.delta;
|
|
1568
|
-
|
|
1569
|
-
if (
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
2075
|
+
while (true) {
|
|
2076
|
+
if (currentToolCall) {
|
|
2077
|
+
const endTag = `</${currentToolCall.name}>`;
|
|
2078
|
+
const endTagIndex = buffer.indexOf(endTag);
|
|
2079
|
+
if (endTagIndex !== -1) {
|
|
2080
|
+
const toolContent = buffer.substring(0, endTagIndex);
|
|
2081
|
+
buffer = buffer.substring(endTagIndex + endTag.length);
|
|
2082
|
+
try {
|
|
2083
|
+
const parser = new import_fast_xml_parser.XMLParser({
|
|
2084
|
+
ignoreAttributes: false,
|
|
2085
|
+
parseTagValue: false,
|
|
2086
|
+
ignoreDeclaration: true,
|
|
2087
|
+
textNodeName: "#text"
|
|
2088
|
+
});
|
|
2089
|
+
const parsedArgs = ((_a = parser.parse(`<root>${toolContent}</root>`)) == null ? void 0 : _a.root) || {};
|
|
2090
|
+
const toolSchema = getToolSchema(
|
|
2091
|
+
tools,
|
|
2092
|
+
originalSchemas,
|
|
2093
|
+
currentToolCall.name
|
|
2094
|
+
);
|
|
2095
|
+
const { args, cancelToolCall } = processParsedArgs(
|
|
2096
|
+
parsedArgs,
|
|
2097
|
+
toolSchema,
|
|
2098
|
+
toolContent,
|
|
2099
|
+
currentToolCall.name,
|
|
2100
|
+
options
|
|
2101
|
+
);
|
|
2102
|
+
if (cancelToolCall) {
|
|
2103
|
+
const originalCallText = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
|
|
2104
|
+
if (options == null ? void 0 : options.onError) {
|
|
2105
|
+
options.onError(
|
|
2106
|
+
"Duplicate string tags detected; cancelling tool call",
|
|
2107
|
+
{
|
|
2108
|
+
toolCall: originalCallText,
|
|
2109
|
+
toolName: currentToolCall.name
|
|
2110
|
+
}
|
|
2111
|
+
);
|
|
2112
|
+
}
|
|
2113
|
+
flushText(controller, originalCallText);
|
|
2114
|
+
} else {
|
|
2115
|
+
const coercedArgs = coerceBySchema(
|
|
2116
|
+
args,
|
|
2117
|
+
toolSchema
|
|
2118
|
+
);
|
|
2119
|
+
flushText(controller);
|
|
2120
|
+
controller.enqueue({
|
|
2121
|
+
type: "tool-call",
|
|
2122
|
+
toolCallId: (0, import_provider_utils3.generateId)(),
|
|
2123
|
+
toolName: currentToolCall.name,
|
|
2124
|
+
input: JSON.stringify(coercedArgs)
|
|
2125
|
+
});
|
|
2126
|
+
}
|
|
2127
|
+
} catch (e) {
|
|
2128
|
+
const originalCallText = `<${currentToolCall.name}>${toolContent}${endTag}`;
|
|
2129
|
+
if (options == null ? void 0 : options.onError) {
|
|
2130
|
+
options.onError(
|
|
2131
|
+
"Could not process streaming XML tool call; emitting original text.",
|
|
2132
|
+
{
|
|
2133
|
+
toolCall: originalCallText,
|
|
2134
|
+
toolName: currentToolCall.name
|
|
2135
|
+
}
|
|
2136
|
+
);
|
|
2137
|
+
}
|
|
2138
|
+
flushText(controller, originalCallText);
|
|
2139
|
+
}
|
|
2140
|
+
currentToolCall = null;
|
|
2141
|
+
} else {
|
|
2142
|
+
break;
|
|
1581
2143
|
}
|
|
1582
|
-
controller.enqueue({
|
|
1583
|
-
type: "text-delta",
|
|
1584
|
-
id: currentTextId,
|
|
1585
|
-
delta: text
|
|
1586
|
-
});
|
|
1587
|
-
}
|
|
1588
|
-
};
|
|
1589
|
-
let startIndex;
|
|
1590
|
-
while ((startIndex = getPotentialStartIndex(
|
|
1591
|
-
buffer,
|
|
1592
|
-
isInsideToolCall ? toolCallEnd : toolCallStart
|
|
1593
|
-
)) != null) {
|
|
1594
|
-
const tag = isInsideToolCall ? toolCallEnd : toolCallStart;
|
|
1595
|
-
if (startIndex + tag.length > buffer.length) {
|
|
1596
|
-
break;
|
|
1597
|
-
}
|
|
1598
|
-
publish(buffer.slice(0, startIndex));
|
|
1599
|
-
buffer = buffer.slice(startIndex + tag.length);
|
|
1600
|
-
if (!isInsideToolCall) {
|
|
1601
|
-
currentToolCallJson = "";
|
|
1602
|
-
isInsideToolCall = true;
|
|
1603
2144
|
} else {
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
toolName: parsedToolCall.name,
|
|
1615
|
-
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1616
|
-
});
|
|
1617
|
-
} catch (e) {
|
|
1618
|
-
const errorId = (0, import_provider_utils3.generateId)();
|
|
1619
|
-
controller.enqueue({ type: "text-start", id: errorId });
|
|
1620
|
-
controller.enqueue({
|
|
1621
|
-
type: "text-delta",
|
|
1622
|
-
id: errorId,
|
|
1623
|
-
delta: `${toolCallStart}${currentToolCallJson}${toolCallEnd}`
|
|
1624
|
-
});
|
|
1625
|
-
controller.enqueue({ type: "text-end", id: errorId });
|
|
1626
|
-
if (options == null ? void 0 : options.onError) {
|
|
1627
|
-
options.onError(
|
|
1628
|
-
"Could not process streaming JSON tool call; emitting original text.",
|
|
1629
|
-
{
|
|
1630
|
-
toolCall: `${toolCallStart}${currentToolCallJson}${toolCallEnd}`
|
|
1631
|
-
}
|
|
1632
|
-
);
|
|
2145
|
+
let earliestStartTagIndex = -1;
|
|
2146
|
+
let earliestToolName = "";
|
|
2147
|
+
if (toolNames.length > 0) {
|
|
2148
|
+
for (const name of toolNames) {
|
|
2149
|
+
const startTag = `<${name}>`;
|
|
2150
|
+
const index = buffer.indexOf(startTag);
|
|
2151
|
+
if (index !== -1 && (earliestStartTagIndex === -1 || index < earliestStartTagIndex)) {
|
|
2152
|
+
earliestStartTagIndex = index;
|
|
2153
|
+
earliestToolName = name;
|
|
2154
|
+
}
|
|
1633
2155
|
}
|
|
1634
2156
|
}
|
|
1635
|
-
|
|
1636
|
-
|
|
2157
|
+
if (earliestStartTagIndex !== -1) {
|
|
2158
|
+
const textBeforeTag = buffer.substring(0, earliestStartTagIndex);
|
|
2159
|
+
flushText(controller, textBeforeTag);
|
|
2160
|
+
const startTag = `<${earliestToolName}>`;
|
|
2161
|
+
buffer = buffer.substring(
|
|
2162
|
+
earliestStartTagIndex + startTag.length
|
|
2163
|
+
);
|
|
2164
|
+
currentToolCall = { name: earliestToolName, content: "" };
|
|
2165
|
+
} else {
|
|
2166
|
+
break;
|
|
2167
|
+
}
|
|
1637
2168
|
}
|
|
1638
2169
|
}
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
2170
|
+
},
|
|
2171
|
+
flush(controller) {
|
|
2172
|
+
if (currentToolCall) {
|
|
2173
|
+
const unfinishedCall = `<${currentToolCall.name}>${buffer}`;
|
|
2174
|
+
flushText(controller, unfinishedCall);
|
|
2175
|
+
} else if (buffer) {
|
|
2176
|
+
flushText(controller);
|
|
2177
|
+
}
|
|
2178
|
+
if (currentTextId) {
|
|
2179
|
+
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1648
2180
|
}
|
|
1649
2181
|
}
|
|
1650
2182
|
});
|
|
2183
|
+
},
|
|
2184
|
+
extractToolCallSegments({ text, tools }) {
|
|
2185
|
+
const toolNames = tools.map((t) => t.name).filter(Boolean);
|
|
2186
|
+
if (toolNames.length === 0) return [];
|
|
2187
|
+
const names = toolNames.map((n) => escapeRegExp(String(n))).join("|");
|
|
2188
|
+
if (!names) return [];
|
|
2189
|
+
const regex = new RegExp(`<(${names})>[\\s\\S]*?<\\/\\1>`, "g");
|
|
2190
|
+
const segments = [];
|
|
2191
|
+
let m;
|
|
2192
|
+
while ((m = regex.exec(text)) != null) {
|
|
2193
|
+
segments.push(m[0]);
|
|
2194
|
+
}
|
|
2195
|
+
return segments;
|
|
1651
2196
|
}
|
|
1652
2197
|
});
|
|
1653
2198
|
|
|
1654
|
-
// src/
|
|
2199
|
+
// src/generate-handler.ts
|
|
1655
2200
|
var import_provider_utils4 = require("@ai-sdk/provider-utils");
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
2201
|
+
async function wrapGenerate({
|
|
2202
|
+
protocol,
|
|
2203
|
+
doGenerate,
|
|
2204
|
+
params
|
|
2205
|
+
}) {
|
|
2206
|
+
var _a, _b;
|
|
2207
|
+
if (isToolChoiceActive(params)) {
|
|
2208
|
+
const result2 = await doGenerate();
|
|
2209
|
+
let parsed2 = {};
|
|
2210
|
+
const first = (_a = result2.content) == null ? void 0 : _a[0];
|
|
2211
|
+
if (first && first.type === "text") {
|
|
2212
|
+
const debugLevel2 = getDebugLevel();
|
|
2213
|
+
if (debugLevel2 === "parse") {
|
|
2214
|
+
logRawChunk(first.text);
|
|
2215
|
+
}
|
|
1671
2216
|
try {
|
|
1672
|
-
|
|
1673
|
-
} catch (
|
|
1674
|
-
|
|
2217
|
+
parsed2 = JSON.parse(first.text);
|
|
2218
|
+
} catch (error) {
|
|
2219
|
+
const options = extractOnErrorOption(params.providerOptions);
|
|
2220
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
2221
|
+
options,
|
|
2222
|
+
"Failed to parse toolChoice JSON from generated model output",
|
|
2223
|
+
{
|
|
2224
|
+
text: first.text,
|
|
2225
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2226
|
+
}
|
|
2227
|
+
);
|
|
2228
|
+
parsed2 = {};
|
|
1675
2229
|
}
|
|
1676
|
-
} else {
|
|
1677
|
-
args = inputValue;
|
|
1678
2230
|
}
|
|
1679
|
-
const
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
const
|
|
1686
|
-
const
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
2231
|
+
const toolCall = {
|
|
2232
|
+
type: "tool-call",
|
|
2233
|
+
toolCallId: (0, import_provider_utils4.generateId)(),
|
|
2234
|
+
toolName: parsed2.name || "unknown",
|
|
2235
|
+
input: JSON.stringify(parsed2.arguments || {})
|
|
2236
|
+
};
|
|
2237
|
+
const debugLevelToolChoice = getDebugLevel();
|
|
2238
|
+
const originText = first && first.type === "text" ? first.text : "";
|
|
2239
|
+
if (debugLevelToolChoice === "parse") {
|
|
2240
|
+
logParsedSummary({ toolCalls: [toolCall], originalText: originText });
|
|
2241
|
+
}
|
|
2242
|
+
return {
|
|
2243
|
+
...result2,
|
|
2244
|
+
content: [toolCall]
|
|
2245
|
+
};
|
|
2246
|
+
}
|
|
2247
|
+
const result = await doGenerate();
|
|
2248
|
+
if (result.content.length === 0) {
|
|
2249
|
+
return result;
|
|
2250
|
+
}
|
|
2251
|
+
const parsed = result.content.flatMap((contentItem) => {
|
|
2252
|
+
var _a2;
|
|
2253
|
+
if (contentItem.type !== "text") {
|
|
2254
|
+
return [contentItem];
|
|
2255
|
+
}
|
|
2256
|
+
const debugLevel2 = getDebugLevel();
|
|
2257
|
+
if (debugLevel2 === "stream") {
|
|
2258
|
+
logRawChunk(contentItem.text);
|
|
2259
|
+
}
|
|
2260
|
+
return protocol.parseGeneratedText({
|
|
2261
|
+
text: contentItem.text,
|
|
2262
|
+
tools: getFunctionTools(params),
|
|
2263
|
+
options: {
|
|
2264
|
+
...extractOnErrorOption(params.providerOptions),
|
|
2265
|
+
...(_a2 = params.providerOptions) == null ? void 0 : _a2.toolCallMiddleware
|
|
1690
2266
|
}
|
|
1691
2267
|
});
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
const
|
|
1703
|
-
|
|
1704
|
-
|
|
2268
|
+
});
|
|
2269
|
+
const tools = getFunctionTools(params);
|
|
2270
|
+
const newContent = parsed.map(
|
|
2271
|
+
(part) => coerceToolCallInput(part, tools)
|
|
2272
|
+
);
|
|
2273
|
+
const debugLevel = getDebugLevel();
|
|
2274
|
+
if (debugLevel === "stream") {
|
|
2275
|
+
newContent.forEach((part) => logParsedChunk(part));
|
|
2276
|
+
}
|
|
2277
|
+
if (debugLevel === "parse") {
|
|
2278
|
+
const allText = result.content.filter(
|
|
2279
|
+
(c) => c.type === "text"
|
|
2280
|
+
).map((c) => c.text).join("\n\n");
|
|
2281
|
+
const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({ text: allText, tools }) : [];
|
|
2282
|
+
const originalText = segments.join("\n\n");
|
|
2283
|
+
const toolCalls = newContent.filter(
|
|
2284
|
+
(p) => p.type === "tool-call"
|
|
2285
|
+
);
|
|
2286
|
+
logParsedSummary({ toolCalls, originalText });
|
|
2287
|
+
}
|
|
2288
|
+
return {
|
|
2289
|
+
...result,
|
|
2290
|
+
content: newContent
|
|
2291
|
+
};
|
|
2292
|
+
}
|
|
2293
|
+
|
|
2294
|
+
// src/stream-handler.ts
|
|
2295
|
+
var import_provider_utils5 = require("@ai-sdk/provider-utils");
|
|
2296
|
+
async function wrapStream({
|
|
2297
|
+
protocol,
|
|
2298
|
+
doStream,
|
|
2299
|
+
doGenerate,
|
|
2300
|
+
params
|
|
2301
|
+
}) {
|
|
2302
|
+
var _a;
|
|
2303
|
+
if (isToolChoiceActive(params)) {
|
|
2304
|
+
return toolChoiceStream({
|
|
2305
|
+
doGenerate,
|
|
2306
|
+
options: extractOnErrorOption(params.providerOptions)
|
|
2307
|
+
});
|
|
2308
|
+
}
|
|
2309
|
+
const { stream, ...rest } = await doStream();
|
|
2310
|
+
const debugLevel = getDebugLevel();
|
|
2311
|
+
const tools = getFunctionTools(params);
|
|
2312
|
+
const options = {
|
|
2313
|
+
...extractOnErrorOption(params.providerOptions),
|
|
2314
|
+
...(_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware
|
|
2315
|
+
};
|
|
2316
|
+
if (debugLevel === "off") {
|
|
2317
|
+
return {
|
|
2318
|
+
stream: stream.pipeThrough(
|
|
2319
|
+
protocol.createStreamParser({
|
|
2320
|
+
tools,
|
|
2321
|
+
options
|
|
2322
|
+
})
|
|
2323
|
+
),
|
|
2324
|
+
...rest
|
|
2325
|
+
};
|
|
2326
|
+
}
|
|
2327
|
+
if (debugLevel === "stream") {
|
|
2328
|
+
const withRawTap2 = stream.pipeThrough(
|
|
2329
|
+
new TransformStream(
|
|
2330
|
+
{
|
|
2331
|
+
transform(part, controller) {
|
|
2332
|
+
logRawChunk(part);
|
|
2333
|
+
controller.enqueue(part);
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
)
|
|
1705
2337
|
);
|
|
1706
|
-
const
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
2338
|
+
const parsed2 = withRawTap2.pipeThrough(
|
|
2339
|
+
protocol.createStreamParser({
|
|
2340
|
+
tools,
|
|
2341
|
+
options
|
|
2342
|
+
})
|
|
2343
|
+
);
|
|
2344
|
+
const withParsedTap = parsed2.pipeThrough(
|
|
2345
|
+
new TransformStream(
|
|
2346
|
+
{
|
|
2347
|
+
transform(part, controller) {
|
|
2348
|
+
logParsedChunk(part);
|
|
2349
|
+
controller.enqueue(part);
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
)
|
|
2353
|
+
);
|
|
2354
|
+
return {
|
|
2355
|
+
stream: withParsedTap,
|
|
2356
|
+
...rest
|
|
2357
|
+
};
|
|
2358
|
+
}
|
|
2359
|
+
let fullRawText = "";
|
|
2360
|
+
const withRawTap = stream.pipeThrough(
|
|
2361
|
+
new TransformStream({
|
|
2362
|
+
transform(part, controller) {
|
|
2363
|
+
if (part.type === "text-delta") {
|
|
2364
|
+
const delta = part.delta;
|
|
2365
|
+
if (typeof delta === "string" && delta.length > 0) {
|
|
2366
|
+
fullRawText += delta;
|
|
2367
|
+
}
|
|
1717
2368
|
}
|
|
2369
|
+
controller.enqueue(part);
|
|
1718
2370
|
}
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
2371
|
+
})
|
|
2372
|
+
);
|
|
2373
|
+
const parsed = withRawTap.pipeThrough(
|
|
2374
|
+
protocol.createStreamParser({
|
|
2375
|
+
tools,
|
|
2376
|
+
options
|
|
2377
|
+
})
|
|
2378
|
+
);
|
|
2379
|
+
const withSummary = parsed.pipeThrough(
|
|
2380
|
+
new TransformStream({
|
|
2381
|
+
transform: /* @__PURE__ */ (() => {
|
|
2382
|
+
const parsedToolCalls = [];
|
|
2383
|
+
return (part, controller) => {
|
|
2384
|
+
if (part.type === "tool-call") {
|
|
2385
|
+
parsedToolCalls.push(part);
|
|
1733
2386
|
}
|
|
1734
|
-
if (
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
}
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
const itemValue = obj.item;
|
|
1747
|
-
if (Array.isArray(itemValue)) {
|
|
1748
|
-
val = itemValue.map((item) => {
|
|
1749
|
-
if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
|
|
1750
|
-
const textVal = item == null ? void 0 : item["#text"];
|
|
1751
|
-
const trimmed2 = typeof textVal === "string" ? textVal.trim() : textVal;
|
|
1752
|
-
if (typeof trimmed2 === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed2)) {
|
|
1753
|
-
const num = Number(trimmed2);
|
|
1754
|
-
if (Number.isFinite(num)) return num;
|
|
1755
|
-
}
|
|
1756
|
-
return trimmed2;
|
|
1757
|
-
}
|
|
1758
|
-
const trimmed = typeof item === "string" ? item.trim() : item;
|
|
1759
|
-
if (typeof trimmed === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed)) {
|
|
1760
|
-
const num = Number(trimmed);
|
|
1761
|
-
if (Number.isFinite(num)) return num;
|
|
1762
|
-
}
|
|
1763
|
-
return trimmed;
|
|
1764
|
-
});
|
|
1765
|
-
} else {
|
|
1766
|
-
const trimmed = typeof itemValue === "string" ? itemValue.trim() : itemValue;
|
|
1767
|
-
if (typeof trimmed === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed)) {
|
|
1768
|
-
const num = Number(trimmed);
|
|
1769
|
-
if (Number.isFinite(num)) {
|
|
1770
|
-
val = num;
|
|
1771
|
-
} else {
|
|
1772
|
-
val = trimmed;
|
|
1773
|
-
}
|
|
1774
|
-
} else {
|
|
1775
|
-
val = trimmed;
|
|
1776
|
-
}
|
|
1777
|
-
}
|
|
1778
|
-
} else {
|
|
1779
|
-
const isIndexedTuple = keys.length > 0 && keys.every((key) => /^\d+$/.test(key)) && (() => {
|
|
1780
|
-
const indices = keys.map((k2) => parseInt(k2)).sort((a, b) => a - b);
|
|
1781
|
-
return indices[0] === 0 && indices.every((val2, idx) => val2 === idx);
|
|
1782
|
-
})();
|
|
1783
|
-
if (isIndexedTuple) {
|
|
1784
|
-
const sortedKeys = keys.sort(
|
|
1785
|
-
(a, b) => parseInt(a) - parseInt(b)
|
|
1786
|
-
);
|
|
1787
|
-
val = sortedKeys.map((key) => {
|
|
1788
|
-
const item = obj[key];
|
|
1789
|
-
if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
|
|
1790
|
-
const textVal = item == null ? void 0 : item["#text"];
|
|
1791
|
-
return typeof textVal === "string" ? textVal.trim() : textVal;
|
|
1792
|
-
}
|
|
1793
|
-
return typeof item === "string" ? item.trim() : item;
|
|
1794
|
-
});
|
|
1795
|
-
} else {
|
|
1796
|
-
val = v;
|
|
1797
|
-
}
|
|
2387
|
+
if (part.type === "finish") {
|
|
2388
|
+
try {
|
|
2389
|
+
const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({
|
|
2390
|
+
text: fullRawText,
|
|
2391
|
+
tools
|
|
2392
|
+
}) : [];
|
|
2393
|
+
const origin = segments.join("\n\n");
|
|
2394
|
+
logParsedSummary({
|
|
2395
|
+
toolCalls: parsedToolCalls,
|
|
2396
|
+
originalText: origin
|
|
2397
|
+
});
|
|
2398
|
+
} catch (e) {
|
|
1798
2399
|
}
|
|
1799
2400
|
}
|
|
1800
|
-
|
|
2401
|
+
controller.enqueue(part);
|
|
2402
|
+
};
|
|
2403
|
+
})()
|
|
2404
|
+
})
|
|
2405
|
+
);
|
|
2406
|
+
return {
|
|
2407
|
+
stream: withSummary,
|
|
2408
|
+
...rest
|
|
2409
|
+
};
|
|
2410
|
+
}
|
|
2411
|
+
async function toolChoiceStream({
|
|
2412
|
+
doGenerate,
|
|
2413
|
+
options
|
|
2414
|
+
}) {
|
|
2415
|
+
var _a, _b;
|
|
2416
|
+
const result = await doGenerate();
|
|
2417
|
+
let toolJson = {};
|
|
2418
|
+
if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
|
|
2419
|
+
try {
|
|
2420
|
+
toolJson = JSON.parse(result.content[0].text);
|
|
2421
|
+
} catch (error) {
|
|
2422
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
2423
|
+
options,
|
|
2424
|
+
"Failed to parse toolChoice JSON from streamed model output",
|
|
2425
|
+
{
|
|
2426
|
+
text: result.content[0].text,
|
|
2427
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1801
2428
|
}
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
const schema = originalSchema || fallbackSchema;
|
|
1805
|
-
const coercedArgs = coerceBySchema(args, schema);
|
|
1806
|
-
processedElements.push({
|
|
1807
|
-
type: "tool-call",
|
|
1808
|
-
toolCallId: (0, import_provider_utils4.generateId)(),
|
|
1809
|
-
toolName,
|
|
1810
|
-
input: JSON.stringify(coercedArgs)
|
|
1811
|
-
});
|
|
1812
|
-
} catch (error) {
|
|
1813
|
-
const message = `Could not process XML tool call, keeping original text: ${match[0]}`;
|
|
1814
|
-
(_c = options == null ? void 0 : options.onError) == null ? void 0 : _c.call(options, message, { toolCall: match[0], toolName, error });
|
|
1815
|
-
processedElements.push({ type: "text", text: match[0] });
|
|
1816
|
-
}
|
|
1817
|
-
currentIndex = startIndex + match[0].length;
|
|
2429
|
+
);
|
|
2430
|
+
toolJson = {};
|
|
1818
2431
|
}
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
2432
|
+
}
|
|
2433
|
+
const toolCallChunk = {
|
|
2434
|
+
type: "tool-call",
|
|
2435
|
+
toolCallId: (0, import_provider_utils5.generateId)(),
|
|
2436
|
+
toolName: toolJson.name || "unknown",
|
|
2437
|
+
input: JSON.stringify(toolJson.arguments || {})
|
|
2438
|
+
};
|
|
2439
|
+
const finishChunk = {
|
|
2440
|
+
type: "finish",
|
|
2441
|
+
usage: (result == null ? void 0 : result.usage) || // TODO: If possible, try to return a certain amount of LLM usage.
|
|
2442
|
+
{
|
|
2443
|
+
inputTokens: 0,
|
|
2444
|
+
outputTokens: 0,
|
|
2445
|
+
totalTokens: 0
|
|
2446
|
+
},
|
|
2447
|
+
finishReason: "tool-calls"
|
|
2448
|
+
};
|
|
2449
|
+
const stream = new ReadableStream({
|
|
2450
|
+
start(controller) {
|
|
2451
|
+
controller.enqueue(toolCallChunk);
|
|
2452
|
+
controller.enqueue(finishChunk);
|
|
2453
|
+
controller.close();
|
|
1824
2454
|
}
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
2455
|
+
});
|
|
2456
|
+
const debugLevel = getDebugLevel();
|
|
2457
|
+
const firstText = (result == null ? void 0 : result.content) && result.content[0] && result.content[0].type === "text" && result.content[0].text || "";
|
|
2458
|
+
const streamWithSummary = debugLevel === "parse" ? stream.pipeThrough(
|
|
2459
|
+
new TransformStream({
|
|
2460
|
+
transform(part, controller) {
|
|
2461
|
+
if (part.type === "finish") {
|
|
2462
|
+
try {
|
|
2463
|
+
logParsedSummary({
|
|
2464
|
+
toolCalls: [toolCallChunk],
|
|
2465
|
+
originalText: typeof firstText === "string" ? firstText : ""
|
|
2466
|
+
});
|
|
2467
|
+
} catch (e) {
|
|
2468
|
+
}
|
|
1839
2469
|
}
|
|
1840
|
-
controller.enqueue(
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
2470
|
+
controller.enqueue(part);
|
|
2471
|
+
}
|
|
2472
|
+
})
|
|
2473
|
+
) : stream;
|
|
2474
|
+
return {
|
|
2475
|
+
request: (result == null ? void 0 : result.request) || {},
|
|
2476
|
+
response: (result == null ? void 0 : result.response) || {},
|
|
2477
|
+
stream: streamWithSummary
|
|
2478
|
+
};
|
|
2479
|
+
}
|
|
2480
|
+
|
|
2481
|
+
// src/transform-handler.ts
|
|
2482
|
+
async function transformParams({
|
|
2483
|
+
params,
|
|
2484
|
+
protocol,
|
|
2485
|
+
toolSystemPromptTemplate
|
|
2486
|
+
}) {
|
|
2487
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
2488
|
+
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
2489
|
+
const functionTools = ((_a = params.tools) != null ? _a : []).filter(
|
|
2490
|
+
(t) => t.type === "function"
|
|
2491
|
+
);
|
|
2492
|
+
const systemPrompt = resolvedProtocol.formatTools({
|
|
2493
|
+
tools: functionTools,
|
|
2494
|
+
toolSystemPromptTemplate
|
|
2495
|
+
});
|
|
2496
|
+
const processedPrompt = convertToolPrompt(
|
|
2497
|
+
(_b = params.prompt) != null ? _b : [],
|
|
2498
|
+
resolvedProtocol,
|
|
2499
|
+
extractOnErrorOption(params.providerOptions)
|
|
2500
|
+
);
|
|
2501
|
+
const finalPrompt = ((_c = processedPrompt[0]) == null ? void 0 : _c.role) === "system" ? [
|
|
2502
|
+
{
|
|
2503
|
+
role: "system",
|
|
2504
|
+
content: systemPrompt + "\n\n" + processedPrompt[0].content
|
|
2505
|
+
},
|
|
2506
|
+
...processedPrompt.slice(1)
|
|
2507
|
+
] : [
|
|
2508
|
+
{
|
|
2509
|
+
role: "system",
|
|
2510
|
+
content: systemPrompt
|
|
2511
|
+
},
|
|
2512
|
+
...processedPrompt
|
|
2513
|
+
];
|
|
2514
|
+
const baseReturnParams = {
|
|
2515
|
+
...params,
|
|
2516
|
+
prompt: finalPrompt,
|
|
2517
|
+
tools: [],
|
|
2518
|
+
toolChoice: void 0,
|
|
2519
|
+
providerOptions: {
|
|
2520
|
+
...params.providerOptions || {},
|
|
2521
|
+
toolCallMiddleware: {
|
|
2522
|
+
...params.providerOptions && typeof params.providerOptions === "object" && params.providerOptions.toolCallMiddleware || {},
|
|
2523
|
+
// INTERNAL: used by the middleware to propagate the names of custom
|
|
2524
|
+
// function tools into downstream handlers (stream/generate) when
|
|
2525
|
+
// providers strip or ignore `params.tools`. Not a stable public API.
|
|
2526
|
+
toolNames: functionTools.map((t) => t.name)
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
};
|
|
2530
|
+
if (((_d = params.toolChoice) == null ? void 0 : _d.type) === "none") {
|
|
2531
|
+
throw new Error(
|
|
2532
|
+
"The 'none' toolChoice type is not supported by this middleware. Please use 'auto', 'required', or specify a tool name."
|
|
2533
|
+
);
|
|
2534
|
+
}
|
|
2535
|
+
if (((_e = params.toolChoice) == null ? void 0 : _e.type) === "tool") {
|
|
2536
|
+
const selectedToolName = params.toolChoice.toolName;
|
|
2537
|
+
const providerDefinedMatch = ((_f = params.tools) != null ? _f : []).find((t) => {
|
|
2538
|
+
if (t.type === "function") return false;
|
|
2539
|
+
const anyTool = t;
|
|
2540
|
+
return anyTool.id === selectedToolName || anyTool.name === selectedToolName;
|
|
2541
|
+
});
|
|
2542
|
+
if (providerDefinedMatch) {
|
|
2543
|
+
throw new Error(
|
|
2544
|
+
"Provider-defined tools are not supported by this middleware. Please use custom tools."
|
|
2545
|
+
);
|
|
2546
|
+
}
|
|
2547
|
+
const selectedTool = ((_g = params.tools) != null ? _g : []).find(
|
|
2548
|
+
(t) => t.type === "function" && t.name === selectedToolName
|
|
2549
|
+
);
|
|
2550
|
+
if (!selectedTool) {
|
|
2551
|
+
throw new Error(
|
|
2552
|
+
`Tool with name '${selectedToolName}' not found in params.tools.`
|
|
2553
|
+
);
|
|
2554
|
+
}
|
|
2555
|
+
return {
|
|
2556
|
+
...baseReturnParams,
|
|
2557
|
+
responseFormat: {
|
|
2558
|
+
type: "json",
|
|
2559
|
+
schema: {
|
|
2560
|
+
type: "object",
|
|
2561
|
+
properties: {
|
|
2562
|
+
name: {
|
|
2563
|
+
const: selectedTool.name
|
|
2564
|
+
},
|
|
2565
|
+
arguments: selectedTool.inputSchema
|
|
2566
|
+
},
|
|
2567
|
+
required: ["name", "arguments"]
|
|
2568
|
+
},
|
|
2569
|
+
name: selectedTool.name,
|
|
2570
|
+
description: typeof selectedTool.description === "string" ? selectedTool.description : void 0
|
|
2571
|
+
},
|
|
2572
|
+
providerOptions: {
|
|
2573
|
+
...baseReturnParams.providerOptions || {},
|
|
2574
|
+
toolCallMiddleware: {
|
|
2575
|
+
...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
|
|
2576
|
+
// INTERNAL: used by the middleware to activate the tool-choice
|
|
2577
|
+
// fast-path in handlers. Not a stable public API.
|
|
2578
|
+
toolChoice: params.toolChoice
|
|
1847
2579
|
}
|
|
1848
2580
|
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
2581
|
+
};
|
|
2582
|
+
}
|
|
2583
|
+
if (((_h = params.toolChoice) == null ? void 0 : _h.type) === "required") {
|
|
2584
|
+
if (!params.tools || params.tools.length === 0) {
|
|
2585
|
+
throw new Error(
|
|
2586
|
+
"Tool choice type 'required' is set, but no tools are provided in params.tools."
|
|
2587
|
+
);
|
|
2588
|
+
}
|
|
2589
|
+
return {
|
|
2590
|
+
...baseReturnParams,
|
|
2591
|
+
responseFormat: {
|
|
2592
|
+
type: "json",
|
|
2593
|
+
schema: createDynamicIfThenElseSchema(functionTools)
|
|
2594
|
+
},
|
|
2595
|
+
providerOptions: {
|
|
2596
|
+
...baseReturnParams.providerOptions || {},
|
|
2597
|
+
toolCallMiddleware: {
|
|
2598
|
+
...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
|
|
2599
|
+
// INTERNAL: used by the middleware to activate the tool-choice
|
|
2600
|
+
// fast-path in handlers. Not a stable public API.
|
|
2601
|
+
toolChoice: { type: "required" }
|
|
2602
|
+
}
|
|
1852
2603
|
}
|
|
1853
2604
|
};
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
2605
|
+
}
|
|
2606
|
+
return baseReturnParams;
|
|
2607
|
+
}
|
|
2608
|
+
function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
|
|
2609
|
+
const processedPrompt = prompt.map((message) => {
|
|
2610
|
+
var _a;
|
|
2611
|
+
if (message.role === "assistant") {
|
|
2612
|
+
const newContent = [];
|
|
2613
|
+
for (const content of message.content) {
|
|
2614
|
+
if (isToolCallContent(content)) {
|
|
2615
|
+
newContent.push({
|
|
2616
|
+
type: "text",
|
|
2617
|
+
text: resolvedProtocol.formatToolCall(content)
|
|
2618
|
+
});
|
|
2619
|
+
} else if (content.type === "text") {
|
|
2620
|
+
newContent.push(content);
|
|
2621
|
+
} else if (content.type === "reasoning") {
|
|
2622
|
+
newContent.push(content);
|
|
2623
|
+
} else {
|
|
2624
|
+
const options = extractOnErrorOption(providerOptions);
|
|
2625
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
2626
|
+
options,
|
|
2627
|
+
"tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
|
|
2628
|
+
{ content }
|
|
2629
|
+
);
|
|
2630
|
+
newContent.push({
|
|
2631
|
+
type: "text",
|
|
2632
|
+
text: JSON.stringify(content)
|
|
2633
|
+
});
|
|
1861
2634
|
}
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
if (typeof trimmed === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed)) {
|
|
1911
|
-
const num = Number(trimmed);
|
|
1912
|
-
if (Number.isFinite(num)) return num;
|
|
1913
|
-
}
|
|
1914
|
-
return trimmed;
|
|
1915
|
-
});
|
|
1916
|
-
} else {
|
|
1917
|
-
const trimmed = typeof itemValue === "string" ? itemValue.trim() : itemValue;
|
|
1918
|
-
if (typeof trimmed === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed)) {
|
|
1919
|
-
const num = Number(trimmed);
|
|
1920
|
-
if (Number.isFinite(num)) {
|
|
1921
|
-
val = num;
|
|
1922
|
-
} else {
|
|
1923
|
-
val = trimmed;
|
|
1924
|
-
}
|
|
1925
|
-
} else {
|
|
1926
|
-
val = trimmed;
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
} else {
|
|
1930
|
-
const isIndexedTuple = keys.length > 0 && keys.every((key) => /^\d+$/.test(key)) && (() => {
|
|
1931
|
-
const indices = keys.map((k2) => parseInt(k2)).sort((a, b) => a - b);
|
|
1932
|
-
return indices[0] === 0 && indices.every((val2, idx) => val2 === idx);
|
|
1933
|
-
})();
|
|
1934
|
-
if (isIndexedTuple) {
|
|
1935
|
-
const sortedKeys = keys.sort(
|
|
1936
|
-
(a, b) => parseInt(a) - parseInt(b)
|
|
1937
|
-
);
|
|
1938
|
-
val = sortedKeys.map((key) => {
|
|
1939
|
-
const item = obj[key];
|
|
1940
|
-
if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
|
|
1941
|
-
const textVal = item == null ? void 0 : item["#text"];
|
|
1942
|
-
return typeof textVal === "string" ? textVal.trim() : textVal;
|
|
1943
|
-
}
|
|
1944
|
-
return typeof item === "string" ? item.trim() : item;
|
|
1945
|
-
});
|
|
1946
|
-
} else {
|
|
1947
|
-
val = v;
|
|
1948
|
-
}
|
|
1949
|
-
}
|
|
1950
|
-
}
|
|
1951
|
-
args[k] = typeof val === "string" ? val.trim() : val;
|
|
1952
|
-
}
|
|
1953
|
-
const originalSchema = originalSchemas[currentToolCall.name];
|
|
1954
|
-
const fallbackSchema = (_b = tools.find(
|
|
1955
|
-
(t) => t.name === currentToolCall.name
|
|
1956
|
-
)) == null ? void 0 : _b.inputSchema;
|
|
1957
|
-
const toolSchema = originalSchema || fallbackSchema;
|
|
1958
|
-
const coercedArgs = coerceBySchema(args, toolSchema);
|
|
1959
|
-
flushText(controller);
|
|
1960
|
-
controller.enqueue({
|
|
1961
|
-
type: "tool-call",
|
|
1962
|
-
toolCallId: (0, import_provider_utils4.generateId)(),
|
|
1963
|
-
toolName: currentToolCall.name,
|
|
1964
|
-
input: JSON.stringify(coercedArgs)
|
|
1965
|
-
});
|
|
1966
|
-
} catch (e) {
|
|
1967
|
-
const originalCallText = `<${currentToolCall.name}>${toolContent}${endTag}`;
|
|
1968
|
-
if (options == null ? void 0 : options.onError) {
|
|
1969
|
-
options.onError(
|
|
1970
|
-
"Could not process streaming XML tool call; emitting original text.",
|
|
1971
|
-
{
|
|
1972
|
-
toolCall: originalCallText,
|
|
1973
|
-
toolName: currentToolCall.name
|
|
1974
|
-
}
|
|
1975
|
-
);
|
|
1976
|
-
}
|
|
1977
|
-
flushText(controller, originalCallText);
|
|
2635
|
+
}
|
|
2636
|
+
const onlyText = newContent.every((c) => c.type === "text");
|
|
2637
|
+
const condensedAssistant = onlyText ? [
|
|
2638
|
+
{
|
|
2639
|
+
type: "text",
|
|
2640
|
+
text: newContent.map((c) => c.text).join("\n")
|
|
2641
|
+
}
|
|
2642
|
+
] : newContent;
|
|
2643
|
+
return { role: "assistant", content: condensedAssistant };
|
|
2644
|
+
}
|
|
2645
|
+
if (message.role === "tool") {
|
|
2646
|
+
return {
|
|
2647
|
+
role: "user",
|
|
2648
|
+
// Map tool results to text response blocks, then condense into a single text block
|
|
2649
|
+
content: [
|
|
2650
|
+
{
|
|
2651
|
+
type: "text",
|
|
2652
|
+
text: message.content.map(
|
|
2653
|
+
(toolResult) => isToolResultPart(toolResult) ? resolvedProtocol.formatToolResponse(toolResult) : resolvedProtocol.formatToolResponse(
|
|
2654
|
+
toolResult
|
|
2655
|
+
)
|
|
2656
|
+
).join("\n")
|
|
2657
|
+
}
|
|
2658
|
+
]
|
|
2659
|
+
};
|
|
2660
|
+
}
|
|
2661
|
+
return message;
|
|
2662
|
+
});
|
|
2663
|
+
for (let i = 0; i < processedPrompt.length; i++) {
|
|
2664
|
+
const msg = processedPrompt[i];
|
|
2665
|
+
if (Array.isArray(msg.content)) {
|
|
2666
|
+
const allText = msg.content.every(
|
|
2667
|
+
(c) => (c == null ? void 0 : c.type) === "text"
|
|
2668
|
+
);
|
|
2669
|
+
if (allText && msg.content.length > 1) {
|
|
2670
|
+
const joinedText = msg.content.map((c) => c.text).join("\n");
|
|
2671
|
+
if (msg.role === "system") {
|
|
2672
|
+
processedPrompt[i] = {
|
|
2673
|
+
role: "system",
|
|
2674
|
+
content: joinedText
|
|
2675
|
+
};
|
|
2676
|
+
} else if (msg.role === "assistant") {
|
|
2677
|
+
processedPrompt[i] = {
|
|
2678
|
+
role: "assistant",
|
|
2679
|
+
content: [
|
|
2680
|
+
{
|
|
2681
|
+
type: "text",
|
|
2682
|
+
text: joinedText
|
|
1978
2683
|
}
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
const startTag = `<${name}>`;
|
|
1989
|
-
const index = buffer.indexOf(startTag);
|
|
1990
|
-
if (index !== -1 && (earliestStartTagIndex === -1 || index < earliestStartTagIndex)) {
|
|
1991
|
-
earliestStartTagIndex = index;
|
|
1992
|
-
earliestToolName = name;
|
|
1993
|
-
}
|
|
2684
|
+
]
|
|
2685
|
+
};
|
|
2686
|
+
} else {
|
|
2687
|
+
processedPrompt[i] = {
|
|
2688
|
+
role: "user",
|
|
2689
|
+
content: [
|
|
2690
|
+
{
|
|
2691
|
+
type: "text",
|
|
2692
|
+
text: joinedText
|
|
1994
2693
|
}
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
const textBeforeTag = buffer.substring(0, earliestStartTagIndex);
|
|
1998
|
-
flushText(controller, textBeforeTag);
|
|
1999
|
-
const startTag = `<${earliestToolName}>`;
|
|
2000
|
-
buffer = buffer.substring(
|
|
2001
|
-
earliestStartTagIndex + startTag.length
|
|
2002
|
-
);
|
|
2003
|
-
currentToolCall = { name: earliestToolName, content: "" };
|
|
2004
|
-
} else {
|
|
2005
|
-
break;
|
|
2006
|
-
}
|
|
2007
|
-
}
|
|
2008
|
-
}
|
|
2009
|
-
},
|
|
2010
|
-
flush(controller) {
|
|
2011
|
-
if (currentToolCall) {
|
|
2012
|
-
const unfinishedCall = `<${currentToolCall.name}>${buffer}`;
|
|
2013
|
-
flushText(controller, unfinishedCall);
|
|
2014
|
-
} else if (buffer) {
|
|
2015
|
-
flushText(controller);
|
|
2016
|
-
}
|
|
2017
|
-
if (currentTextId) {
|
|
2018
|
-
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
2694
|
+
]
|
|
2695
|
+
};
|
|
2019
2696
|
}
|
|
2020
2697
|
}
|
|
2021
|
-
}
|
|
2698
|
+
}
|
|
2022
2699
|
}
|
|
2023
|
-
|
|
2700
|
+
for (let i = processedPrompt.length - 1; i > 0; i--) {
|
|
2701
|
+
const current = processedPrompt[i];
|
|
2702
|
+
const prev = processedPrompt[i - 1];
|
|
2703
|
+
if (current.role === "user" && prev.role === "user") {
|
|
2704
|
+
const prevContent = prev.content.map((c) => c.type === "text" ? c.text : "").join("\n");
|
|
2705
|
+
const currentContent = current.content.map((c) => c.type === "text" ? c.text : "").join("\n");
|
|
2706
|
+
processedPrompt[i - 1] = {
|
|
2707
|
+
role: "user",
|
|
2708
|
+
content: [{ type: "text", text: prevContent + "\n" + currentContent }]
|
|
2709
|
+
};
|
|
2710
|
+
processedPrompt.splice(i, 1);
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
return processedPrompt;
|
|
2714
|
+
}
|
|
2024
2715
|
|
|
2025
|
-
// src/
|
|
2026
|
-
|
|
2716
|
+
// src/tool-call-middleware.ts
|
|
2717
|
+
function createToolMiddleware({
|
|
2718
|
+
protocol,
|
|
2719
|
+
toolSystemPromptTemplate
|
|
2720
|
+
}) {
|
|
2721
|
+
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
2722
|
+
return {
|
|
2723
|
+
middlewareVersion: "v2",
|
|
2724
|
+
wrapStream: async ({ doStream, doGenerate, params }) => {
|
|
2725
|
+
if (isToolChoiceActive(params)) {
|
|
2726
|
+
return toolChoiceStream({
|
|
2727
|
+
doGenerate,
|
|
2728
|
+
options: extractOnErrorOption(params.providerOptions)
|
|
2729
|
+
});
|
|
2730
|
+
} else {
|
|
2731
|
+
return wrapStream({
|
|
2732
|
+
protocol: resolvedProtocol,
|
|
2733
|
+
doStream,
|
|
2734
|
+
doGenerate,
|
|
2735
|
+
params
|
|
2736
|
+
});
|
|
2737
|
+
}
|
|
2738
|
+
},
|
|
2739
|
+
wrapGenerate: async ({ doGenerate, params }) => wrapGenerate({
|
|
2740
|
+
protocol: resolvedProtocol,
|
|
2741
|
+
doGenerate,
|
|
2742
|
+
params
|
|
2743
|
+
}),
|
|
2744
|
+
transformParams: async ({
|
|
2745
|
+
params
|
|
2746
|
+
}) => {
|
|
2747
|
+
return transformParams({
|
|
2748
|
+
protocol: resolvedProtocol,
|
|
2749
|
+
toolSystemPromptTemplate,
|
|
2750
|
+
params
|
|
2751
|
+
});
|
|
2752
|
+
}
|
|
2753
|
+
};
|
|
2754
|
+
}
|
|
2027
2755
|
|
|
2028
2756
|
// src/index.ts
|
|
2029
2757
|
var gemmaToolMiddleware = createToolMiddleware({
|
|
@@ -2031,8 +2759,9 @@ var gemmaToolMiddleware = createToolMiddleware({
|
|
|
2031
2759
|
// Customize the tool call delimiters to use markdown code fences
|
|
2032
2760
|
{
|
|
2033
2761
|
toolCallStart: "```tool_call\n",
|
|
2034
|
-
|
|
2035
|
-
//
|
|
2762
|
+
// TODO: Support specifying multiple possible tags,
|
|
2763
|
+
// e.g., for gemma, it would be nice to be able to set both `` and ``` at the same time.
|
|
2764
|
+
toolCallEnd: "\n```",
|
|
2036
2765
|
toolResponseStart: "```tool_response\n",
|
|
2037
2766
|
toolResponseEnd: "\n```"
|
|
2038
2767
|
}
|
|
@@ -2063,7 +2792,7 @@ For each function call return a json object with function name and arguments wit
|
|
|
2063
2792
|
}
|
|
2064
2793
|
});
|
|
2065
2794
|
var xmlToolMiddleware = createToolMiddleware({
|
|
2066
|
-
protocol:
|
|
2795
|
+
protocol: morphXmlProtocol,
|
|
2067
2796
|
toolSystemPromptTemplate(tools) {
|
|
2068
2797
|
return `You are a function calling AI model.
|
|
2069
2798
|
You are provided with function signatures within <tools></tools> XML tags.
|
|
@@ -2082,15 +2811,11 @@ San Fransisco
|
|
|
2082
2811
|
});
|
|
2083
2812
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2084
2813
|
0 && (module.exports = {
|
|
2085
|
-
coerceBySchema,
|
|
2086
2814
|
createToolMiddleware,
|
|
2087
|
-
fixToolCallWithSchema,
|
|
2088
2815
|
gemmaToolMiddleware,
|
|
2089
|
-
getSchemaType,
|
|
2090
2816
|
hermesToolMiddleware,
|
|
2091
2817
|
jsonMixProtocol,
|
|
2092
|
-
|
|
2093
|
-
xmlProtocol,
|
|
2818
|
+
morphXmlProtocol,
|
|
2094
2819
|
xmlToolMiddleware
|
|
2095
2820
|
});
|
|
2096
2821
|
//# sourceMappingURL=index.cjs.map
|