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