@ai-sdk-tool/parser 2.1.1 → 2.1.2

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/dist/index.cjs CHANGED
@@ -20,22 +20,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- coerceBySchema: () => coerceBySchema,
24
23
  createToolMiddleware: () => createToolMiddleware,
25
- fixToolCallWithSchema: () => fixToolCallWithSchema,
26
24
  gemmaToolMiddleware: () => gemmaToolMiddleware,
27
- getSchemaType: () => getSchemaType,
28
25
  hermesToolMiddleware: () => hermesToolMiddleware,
29
26
  jsonMixProtocol: () => jsonMixProtocol,
30
- unwrapJsonSchema: () => unwrapJsonSchema,
31
- xmlProtocol: () => xmlProtocol,
27
+ morphXmlProtocol: () => morphXmlProtocol,
32
28
  xmlToolMiddleware: () => xmlToolMiddleware
33
29
  });
34
30
  module.exports = __toCommonJS(index_exports);
35
31
 
36
- // src/stream-handler.ts
32
+ // src/protocols/dummy-protocol.ts
37
33
  var import_provider_utils = require("@ai-sdk/provider-utils");
38
34
 
35
+ // src/protocols/json-mix-protocol.ts
36
+ var import_provider_utils2 = require("@ai-sdk/provider-utils");
37
+
39
38
  // src/utils/dynamic-tool-schema.ts
40
39
  function createDynamicIfThenElseSchema(tools) {
41
40
  let currentSchema = {};
@@ -110,6 +109,11 @@ function getPotentialStartIndex(text, searchedText) {
110
109
  return null;
111
110
  }
112
111
 
112
+ // src/utils/regex.ts
113
+ function escapeRegExp(literal) {
114
+ return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
115
+ }
116
+
113
117
  // src/utils/relaxed-json.ts
114
118
  var relaxed_json_exports = {};
115
119
  __export(relaxed_json_exports, {
@@ -743,62 +747,6 @@ function stringify(obj) {
743
747
  return "null";
744
748
  }
745
749
 
746
- // src/utils/regex.ts
747
- function escapeRegExp(literal) {
748
- return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
749
- }
750
-
751
- // src/utils/type-guards.ts
752
- function isToolCallContent(content) {
753
- return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
754
- (typeof content.input === "string" || typeof content.input === "object");
755
- }
756
- function isToolResultPart(content) {
757
- const c = content;
758
- return !!c && c.type === "tool-result" && typeof c.toolName === "string" && typeof c.toolCallId === "string" && "output" in c;
759
- }
760
- function hasInputProperty(obj) {
761
- return typeof obj === "object" && obj !== null && "input" in obj;
762
- }
763
-
764
- // src/utils/tools.ts
765
- function isToolChoiceActive(params) {
766
- var _a, _b, _c;
767
- const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
768
- return !!(typeof params.providerOptions === "object" && params.providerOptions !== null && typeof ((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) === "object" && toolChoice && typeof toolChoice === "object" && (toolChoice.type === "tool" || toolChoice.type === "required"));
769
- }
770
- function getFunctionTools(params) {
771
- var _a, _b;
772
- const functionTools = ((_a = params.tools) != null ? _a : []).filter(
773
- (t) => t.type === "function"
774
- );
775
- if (functionTools.length > 0) return functionTools;
776
- const rawToolNames = params.providerOptions && typeof params.providerOptions === "object" && ((_b = params.providerOptions.toolCallMiddleware) == null ? void 0 : _b.toolNames) || [];
777
- const toStringArray = (val) => Array.isArray(val) ? val.filter(
778
- (item) => typeof item === "string"
779
- ) : [];
780
- const toolNames = toStringArray(rawToolNames);
781
- if (toolNames.length > 0) {
782
- return toolNames.map((name) => ({
783
- type: "function",
784
- name,
785
- description: "",
786
- inputSchema: { type: "object" }
787
- }));
788
- }
789
- return [];
790
- }
791
-
792
- // src/utils/on-error.ts
793
- function extractOnErrorOption(providerOptions) {
794
- var _a;
795
- if (providerOptions && typeof providerOptions === "object") {
796
- const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
797
- return onError ? { onError } : void 0;
798
- }
799
- return void 0;
800
- }
801
-
802
750
  // src/utils/coercion.ts
803
751
  function unwrapJsonSchema(schema) {
804
752
  if (!schema || typeof schema !== "object") return schema;
@@ -1003,506 +951,218 @@ function coerceToolCallInput(part, tools) {
1003
951
  return fixToolCallWithSchema(part, tools);
1004
952
  }
1005
953
 
1006
- // src/utils/protocol.ts
1007
- function isProtocolFactory(protocol) {
1008
- return typeof protocol === "function";
954
+ // src/utils/debug.ts
955
+ function normalizeBooleanString(value) {
956
+ const normalized = value.trim().toLowerCase();
957
+ if (normalized === "1" || normalized === "true" || normalized === "yes") {
958
+ return true;
959
+ }
960
+ if (normalized === "0" || normalized === "false" || normalized === "no") {
961
+ return false;
962
+ }
963
+ return void 0;
1009
964
  }
1010
-
1011
- // src/stream-handler.ts
1012
- async function wrapStream({
1013
- protocol,
1014
- doStream,
1015
- doGenerate,
1016
- params
1017
- }) {
1018
- var _a;
1019
- if (isToolChoiceActive(params)) {
1020
- return toolChoiceStream({
1021
- doGenerate,
1022
- options: extractOnErrorOption(params.providerOptions)
1023
- });
965
+ function getDebugLevel() {
966
+ const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW || "off";
967
+ const envLower = String(envVal).toLowerCase();
968
+ if (envLower === "stream" || envLower === "parse" || envLower === "off") {
969
+ return envLower;
1024
970
  }
1025
- const { stream, ...rest } = await doStream();
1026
- return {
1027
- stream: stream.pipeThrough(
1028
- protocol.createStreamParser({
1029
- tools: getFunctionTools(params),
1030
- options: {
1031
- ...extractOnErrorOption(params.providerOptions),
1032
- ...(_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware
1033
- }
1034
- })
1035
- ),
1036
- ...rest
1037
- };
971
+ const boolEnv = normalizeBooleanString(envLower);
972
+ if (boolEnv === true) return "stream";
973
+ if (envLower === "2") return "parse";
974
+ return "off";
1038
975
  }
1039
- async function toolChoiceStream({
1040
- doGenerate,
1041
- options
1042
- }) {
1043
- var _a, _b;
1044
- const result = await doGenerate();
1045
- let toolJson = {};
1046
- if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
1047
- try {
1048
- toolJson = JSON.parse(result.content[0].text);
1049
- } catch (error) {
1050
- (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
1051
- options,
1052
- "Failed to parse toolChoice JSON from streamed model output",
1053
- {
1054
- text: result.content[0].text,
1055
- error: error instanceof Error ? error.message : String(error)
1056
- }
1057
- );
1058
- toolJson = {};
1059
- }
976
+ function color(code) {
977
+ return (text) => `\x1B[${code}m${text}\x1B[0m`;
978
+ }
979
+ var cGray = color(90);
980
+ var cYellow = color(33);
981
+ var cCyan = color(36);
982
+ var cBgBlue = color(44);
983
+ var cBgGreen = color(42);
984
+ var cInverse = color(7);
985
+ var cUnderline = color(4);
986
+ var cBold = color(1);
987
+ function safeStringify(value) {
988
+ try {
989
+ return `
990
+ ${typeof value === "string" ? value : JSON.stringify(value, null, 2)}`;
991
+ } catch (e) {
992
+ return String(value);
1060
993
  }
1061
- const toolCallChunk = {
1062
- type: "tool-call",
1063
- toolCallId: (0, import_provider_utils.generateId)(),
1064
- toolName: toolJson.name || "unknown",
1065
- input: JSON.stringify(toolJson.arguments || {})
1066
- };
1067
- const finishChunk = {
1068
- type: "finish",
1069
- usage: (result == null ? void 0 : result.usage) || // TODO: If possible, try to return a certain amount of LLM usage.
1070
- {
1071
- inputTokens: 0,
1072
- outputTokens: 0,
1073
- totalTokens: 0
1074
- },
1075
- finishReason: "tool-calls"
1076
- };
1077
- const stream = new ReadableStream({
1078
- start(controller) {
1079
- controller.enqueue(toolCallChunk);
1080
- controller.enqueue(finishChunk);
1081
- controller.close();
1082
- }
1083
- });
1084
- return {
1085
- request: (result == null ? void 0 : result.request) || {},
1086
- response: (result == null ? void 0 : result.response) || {},
1087
- stream
1088
- };
1089
994
  }
1090
-
1091
- // src/generate-handler.ts
1092
- var import_provider_utils2 = require("@ai-sdk/provider-utils");
1093
- async function wrapGenerate({
1094
- protocol,
1095
- doGenerate,
1096
- params
995
+ function logRawChunk(part) {
996
+ console.log(cGray("[debug:mw:raw]"), cYellow(safeStringify(part)));
997
+ }
998
+ function logParsedChunk(part) {
999
+ console.log(cGray("[debug:mw:out]"), cCyan(safeStringify(part)));
1000
+ }
1001
+ function logParsedSummary({
1002
+ toolCalls,
1003
+ originalText
1097
1004
  }) {
1098
- var _a, _b;
1099
- if (isToolChoiceActive(params)) {
1100
- const result2 = await doGenerate();
1101
- let parsed2 = {};
1102
- const first = (_a = result2.content) == null ? void 0 : _a[0];
1103
- if (first && first.type === "text") {
1104
- try {
1105
- parsed2 = JSON.parse(first.text);
1106
- } catch (error) {
1107
- const options = extractOnErrorOption(params.providerOptions);
1108
- (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
1109
- options,
1110
- "Failed to parse toolChoice JSON from generated model output",
1111
- {
1112
- text: first.text,
1113
- error: error instanceof Error ? error.message : String(error)
1114
- }
1115
- );
1116
- parsed2 = {};
1117
- }
1118
- }
1119
- const toolCall = {
1120
- type: "tool-call",
1121
- toolCallId: (0, import_provider_utils2.generateId)(),
1122
- toolName: parsed2.name || "unknown",
1123
- input: JSON.stringify(parsed2.arguments || {})
1124
- };
1125
- return {
1126
- ...result2,
1127
- content: [toolCall]
1128
- };
1005
+ if (originalText) {
1006
+ const style = (() => {
1007
+ const envVal = typeof process !== "undefined" && process.env && process.env.DEBUG_PARSER_MW_STYLE || "bg";
1008
+ const normalized = String(envVal).trim().toLowerCase();
1009
+ if (normalized === "inverse" || normalized === "invert")
1010
+ return "inverse";
1011
+ if (normalized === "underline" || normalized === "ul")
1012
+ return "underline";
1013
+ if (normalized === "bold") return "bold";
1014
+ if (normalized === "bg" || normalized === "background")
1015
+ return "bg";
1016
+ const asBool = normalizeBooleanString(normalized);
1017
+ if (asBool === true) return "bg";
1018
+ return "bg";
1019
+ })();
1020
+ const highlight = style === "inverse" ? cInverse : style === "underline" ? cUnderline : style === "bold" ? cBold : style === "bg" ? cBgGreen : cYellow;
1021
+ const rendered = style === "bg" || style === "inverse" || style === "underline" || style === "bold" ? originalText.split(/\r?\n/).map((line) => line.length ? highlight(line) : line).join("\n") : highlight(originalText);
1022
+ console.log(cGray("[debug:mw:origin]"), `
1023
+ ${rendered}`);
1129
1024
  }
1130
- const result = await doGenerate();
1131
- if (result.content.length === 0) {
1132
- return result;
1025
+ if (toolCalls.length > 0) {
1026
+ const styledSummary = safeStringify(toolCalls).split(/\r?\n/).map((line) => line.length ? cBgBlue(line) : line).join("\n");
1027
+ console.log(cGray("[debug:mw:summary]"), styledSummary);
1133
1028
  }
1134
- const parsed = result.content.flatMap((contentItem) => {
1135
- var _a2;
1136
- if (contentItem.type !== "text") {
1137
- return [contentItem];
1138
- }
1139
- return protocol.parseGeneratedText({
1140
- text: contentItem.text,
1141
- tools: getFunctionTools(params),
1142
- options: {
1143
- ...extractOnErrorOption(params.providerOptions),
1144
- ...(_a2 = params.providerOptions) == null ? void 0 : _a2.toolCallMiddleware
1145
- }
1146
- });
1147
- });
1148
- const tools = getFunctionTools(params);
1149
- const newContent = parsed.map(
1150
- (part) => coerceToolCallInput(part, tools)
1151
- );
1152
- return {
1153
- ...result,
1154
- content: newContent
1155
- };
1156
1029
  }
1157
1030
 
1158
- // src/transform-handler.ts
1159
- async function transformParams({
1160
- params,
1161
- protocol,
1162
- toolSystemPromptTemplate
1163
- }) {
1164
- var _a, _b, _c, _d, _e, _f, _g, _h;
1165
- const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
1031
+ // src/utils/on-error.ts
1032
+ function extractOnErrorOption(providerOptions) {
1033
+ var _a;
1034
+ if (providerOptions && typeof providerOptions === "object") {
1035
+ const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
1036
+ return onError ? { onError } : void 0;
1037
+ }
1038
+ return void 0;
1039
+ }
1040
+
1041
+ // src/utils/protocol.ts
1042
+ function isProtocolFactory(protocol) {
1043
+ return typeof protocol === "function";
1044
+ }
1045
+
1046
+ // src/utils/tools.ts
1047
+ function isToolChoiceActive(params) {
1048
+ var _a, _b, _c;
1049
+ const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
1050
+ return !!(typeof params.providerOptions === "object" && params.providerOptions !== null && typeof ((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) === "object" && toolChoice && typeof toolChoice === "object" && (toolChoice.type === "tool" || toolChoice.type === "required"));
1051
+ }
1052
+ function getFunctionTools(params) {
1053
+ var _a, _b;
1166
1054
  const functionTools = ((_a = params.tools) != null ? _a : []).filter(
1167
1055
  (t) => t.type === "function"
1168
1056
  );
1169
- const systemPrompt = resolvedProtocol.formatTools({
1170
- tools: functionTools,
1171
- toolSystemPromptTemplate
1172
- });
1173
- const processedPrompt = convertToolPrompt(
1174
- (_b = params.prompt) != null ? _b : [],
1175
- resolvedProtocol,
1176
- extractOnErrorOption(params.providerOptions)
1177
- );
1178
- const finalPrompt = ((_c = processedPrompt[0]) == null ? void 0 : _c.role) === "system" ? [
1179
- {
1180
- role: "system",
1181
- content: systemPrompt + "\n\n" + processedPrompt[0].content
1182
- },
1183
- ...processedPrompt.slice(1)
1184
- ] : [
1185
- {
1186
- role: "system",
1187
- content: systemPrompt
1188
- },
1189
- ...processedPrompt
1190
- ];
1191
- const baseReturnParams = {
1192
- ...params,
1193
- prompt: finalPrompt,
1194
- tools: [],
1195
- toolChoice: void 0,
1196
- providerOptions: {
1197
- ...params.providerOptions || {},
1198
- toolCallMiddleware: {
1199
- ...params.providerOptions && typeof params.providerOptions === "object" && params.providerOptions.toolCallMiddleware || {},
1200
- toolNames: functionTools.map((t) => t.name)
1201
- }
1202
- }
1203
- };
1204
- if (((_d = params.toolChoice) == null ? void 0 : _d.type) === "none") {
1205
- throw new Error(
1206
- "The 'none' toolChoice type is not supported by this middleware. Please use 'auto', 'required', or specify a tool name."
1207
- );
1057
+ if (functionTools.length > 0) return functionTools;
1058
+ const rawToolNames = params.providerOptions && typeof params.providerOptions === "object" && ((_b = params.providerOptions.toolCallMiddleware) == null ? void 0 : _b.toolNames) || [];
1059
+ const toStringArray = (val) => Array.isArray(val) ? val.filter(
1060
+ (item) => typeof item === "string"
1061
+ ) : [];
1062
+ const toolNames = toStringArray(rawToolNames);
1063
+ if (toolNames.length > 0) {
1064
+ return toolNames.map((name) => ({
1065
+ type: "function",
1066
+ name,
1067
+ description: "",
1068
+ inputSchema: { type: "object" }
1069
+ }));
1208
1070
  }
1209
- if (((_e = params.toolChoice) == null ? void 0 : _e.type) === "tool") {
1210
- const selectedToolName = params.toolChoice.toolName;
1211
- const providerDefinedMatch = ((_f = params.tools) != null ? _f : []).find((t) => {
1212
- if (t.type === "function") return false;
1213
- const anyTool = t;
1214
- return anyTool.id === selectedToolName || anyTool.name === selectedToolName;
1215
- });
1216
- if (providerDefinedMatch) {
1217
- throw new Error(
1218
- "Provider-defined tools are not supported by this middleware. Please use custom tools."
1219
- );
1071
+ return [];
1072
+ }
1073
+
1074
+ // src/utils/type-guards.ts
1075
+ function isToolCallContent(content) {
1076
+ return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
1077
+ (typeof content.input === "string" || typeof content.input === "object");
1078
+ }
1079
+ function isToolResultPart(content) {
1080
+ const c = content;
1081
+ return !!c && c.type === "tool-result" && typeof c.toolName === "string" && typeof c.toolCallId === "string" && "output" in c;
1082
+ }
1083
+ function hasInputProperty(obj) {
1084
+ return typeof obj === "object" && obj !== null && "input" in obj;
1085
+ }
1086
+
1087
+ // src/protocols/json-mix-protocol.ts
1088
+ var jsonMixProtocol = ({
1089
+ toolCallStart = "<tool_call>",
1090
+ toolCallEnd = "</tool_call>",
1091
+ toolResponseStart = "<tool_response>",
1092
+ toolResponseEnd = "</tool_response>"
1093
+ } = {}) => ({
1094
+ formatTools({ tools, toolSystemPromptTemplate }) {
1095
+ const toolsForPrompt = (tools || []).filter((tool) => tool.type === "function").map((tool) => ({
1096
+ name: tool.name,
1097
+ description: tool.type === "function" && typeof tool.description === "string" ? tool.description : void 0,
1098
+ parameters: tool.inputSchema
1099
+ }));
1100
+ return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
1101
+ },
1102
+ formatToolCall(toolCall) {
1103
+ let args = {};
1104
+ try {
1105
+ args = JSON.parse(toolCall.input);
1106
+ } catch (e) {
1107
+ args = toolCall.input;
1220
1108
  }
1221
- const selectedTool = ((_g = params.tools) != null ? _g : []).find(
1222
- (t) => t.type === "function" && t.name === selectedToolName
1109
+ return `${toolCallStart}${JSON.stringify({
1110
+ name: toolCall.toolName,
1111
+ arguments: args
1112
+ })}${toolCallEnd}`;
1113
+ },
1114
+ formatToolResponse(toolResult) {
1115
+ return `${toolResponseStart}${JSON.stringify({
1116
+ toolName: toolResult.toolName,
1117
+ result: toolResult.output
1118
+ })}${toolResponseEnd}`;
1119
+ },
1120
+ parseGeneratedText({ text, options }) {
1121
+ var _a;
1122
+ const startEsc = escapeRegExp(toolCallStart);
1123
+ const endEsc = escapeRegExp(toolCallEnd);
1124
+ const toolCallRegex = new RegExp(
1125
+ `${startEsc}([\0-\uFFFF]*?)${endEsc}`,
1126
+ "gs"
1223
1127
  );
1224
- if (!selectedTool) {
1225
- throw new Error(
1226
- `Tool with name '${selectedToolName}' not found in params.tools.`
1227
- );
1228
- }
1229
- return {
1230
- ...baseReturnParams,
1231
- responseFormat: {
1232
- type: "json",
1233
- schema: {
1234
- type: "object",
1235
- properties: {
1236
- name: {
1237
- const: selectedTool.name
1238
- },
1239
- arguments: selectedTool.inputSchema
1240
- },
1241
- required: ["name", "arguments"]
1242
- },
1243
- name: selectedTool.name,
1244
- description: typeof selectedTool.description === "string" ? selectedTool.description : void 0
1245
- },
1246
- providerOptions: {
1247
- ...baseReturnParams.providerOptions || {},
1248
- toolCallMiddleware: {
1249
- ...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
1250
- toolChoice: params.toolChoice
1251
- }
1252
- }
1253
- };
1254
- }
1255
- if (((_h = params.toolChoice) == null ? void 0 : _h.type) === "required") {
1256
- if (!params.tools || params.tools.length === 0) {
1257
- throw new Error(
1258
- "Tool choice type 'required' is set, but no tools are provided in params.tools."
1259
- );
1260
- }
1261
- return {
1262
- ...baseReturnParams,
1263
- responseFormat: {
1264
- type: "json",
1265
- schema: createDynamicIfThenElseSchema(functionTools)
1266
- },
1267
- providerOptions: {
1268
- ...baseReturnParams.providerOptions || {},
1269
- toolCallMiddleware: {
1270
- ...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
1271
- toolChoice: { type: "required" }
1128
+ const processedElements = [];
1129
+ let currentIndex = 0;
1130
+ let match;
1131
+ while ((match = toolCallRegex.exec(text)) !== null) {
1132
+ const startIndex = match.index;
1133
+ const toolCallJson = match[1];
1134
+ if (startIndex > currentIndex) {
1135
+ const textSegment = text.substring(currentIndex, startIndex);
1136
+ if (textSegment.trim()) {
1137
+ processedElements.push({ type: "text", text: textSegment });
1272
1138
  }
1273
1139
  }
1274
- };
1275
- }
1276
- return baseReturnParams;
1277
- }
1278
- function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
1279
- const processedPrompt = prompt.map((message) => {
1280
- var _a;
1281
- if (message.role === "assistant") {
1282
- const newContent = [];
1283
- for (const content of message.content) {
1284
- if (isToolCallContent(content)) {
1285
- newContent.push({
1286
- type: "text",
1287
- text: resolvedProtocol.formatToolCall(content)
1288
- });
1289
- } else if (content.type === "text") {
1290
- newContent.push(content);
1291
- } else if (content.type === "reasoning") {
1292
- newContent.push(content);
1293
- } else {
1294
- const options = extractOnErrorOption(providerOptions);
1295
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
1296
- options,
1297
- "tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
1298
- { content }
1299
- );
1300
- newContent.push({
1301
- type: "text",
1302
- text: JSON.stringify(content)
1140
+ if (toolCallJson) {
1141
+ try {
1142
+ const parsedToolCall = relaxed_json_exports.parse(toolCallJson);
1143
+ processedElements.push({
1144
+ type: "tool-call",
1145
+ toolCallId: (0, import_provider_utils2.generateId)(),
1146
+ toolName: parsedToolCall.name,
1147
+ input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
1303
1148
  });
1149
+ } catch (error) {
1150
+ if (options == null ? void 0 : options.onError) {
1151
+ options.onError(
1152
+ "Could not process JSON tool call, keeping original text.",
1153
+ { toolCall: match[0], error }
1154
+ );
1155
+ }
1156
+ processedElements.push({ type: "text", text: match[0] });
1304
1157
  }
1305
1158
  }
1306
- const onlyText = newContent.every((c) => c.type === "text");
1307
- const condensedAssistant = onlyText ? [
1308
- {
1309
- type: "text",
1310
- text: newContent.map((c) => c.text).join("\n")
1311
- }
1312
- ] : newContent;
1313
- return { role: "assistant", content: condensedAssistant };
1159
+ currentIndex = startIndex + match[0].length;
1314
1160
  }
1315
- if (message.role === "tool") {
1316
- return {
1317
- role: "user",
1318
- // Map tool results to text response blocks, then condense into a single text block
1319
- content: [
1320
- {
1321
- type: "text",
1322
- text: message.content.map(
1323
- (toolResult) => isToolResultPart(toolResult) ? resolvedProtocol.formatToolResponse(toolResult) : resolvedProtocol.formatToolResponse(
1324
- toolResult
1325
- )
1326
- ).join("\n")
1327
- }
1328
- ]
1329
- };
1330
- }
1331
- return message;
1332
- });
1333
- for (let i = 0; i < processedPrompt.length; i++) {
1334
- const msg = processedPrompt[i];
1335
- if (Array.isArray(msg.content)) {
1336
- const allText = msg.content.every(
1337
- (c) => (c == null ? void 0 : c.type) === "text"
1338
- );
1339
- if (allText && msg.content.length > 1) {
1340
- const joinedText = msg.content.map((c) => c.text).join("\n");
1341
- if (msg.role === "system") {
1342
- processedPrompt[i] = {
1343
- role: "system",
1344
- content: joinedText
1345
- };
1346
- } else if (msg.role === "assistant") {
1347
- processedPrompt[i] = {
1348
- role: "assistant",
1349
- content: [
1350
- {
1351
- type: "text",
1352
- text: joinedText
1353
- }
1354
- ]
1355
- };
1356
- } else {
1357
- processedPrompt[i] = {
1358
- role: "user",
1359
- content: [
1360
- {
1361
- type: "text",
1362
- text: joinedText
1363
- }
1364
- ]
1365
- };
1366
- }
1367
- }
1368
- }
1369
- }
1370
- for (let i = processedPrompt.length - 1; i > 0; i--) {
1371
- const current = processedPrompt[i];
1372
- const prev = processedPrompt[i - 1];
1373
- if (current.role === "user" && prev.role === "user") {
1374
- const prevContent = prev.content.map((c) => c.type === "text" ? c.text : "").join("\n");
1375
- const currentContent = current.content.map((c) => c.type === "text" ? c.text : "").join("\n");
1376
- processedPrompt[i - 1] = {
1377
- role: "user",
1378
- content: [{ type: "text", text: prevContent + "\n" + currentContent }]
1379
- };
1380
- processedPrompt.splice(i, 1);
1381
- }
1382
- }
1383
- return processedPrompt;
1384
- }
1385
-
1386
- // src/tool-call-middleware.ts
1387
- function createToolMiddleware({
1388
- protocol,
1389
- toolSystemPromptTemplate
1390
- }) {
1391
- const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
1392
- return {
1393
- middlewareVersion: "v2",
1394
- wrapStream: async ({ doStream, doGenerate, params }) => {
1395
- if (isToolChoiceActive(params)) {
1396
- return toolChoiceStream({
1397
- doGenerate,
1398
- options: extractOnErrorOption(params.providerOptions)
1399
- });
1400
- } else {
1401
- return wrapStream({
1402
- protocol: resolvedProtocol,
1403
- doStream,
1404
- doGenerate,
1405
- params
1406
- });
1407
- }
1408
- },
1409
- wrapGenerate: async ({ doGenerate, params }) => wrapGenerate({
1410
- protocol: resolvedProtocol,
1411
- doGenerate,
1412
- params
1413
- }),
1414
- transformParams: async ({
1415
- params
1416
- }) => {
1417
- return transformParams({
1418
- protocol: resolvedProtocol,
1419
- toolSystemPromptTemplate,
1420
- params
1421
- });
1422
- }
1423
- };
1424
- }
1425
-
1426
- // src/protocols/json-mix-protocol.ts
1427
- var import_provider_utils3 = require("@ai-sdk/provider-utils");
1428
- var jsonMixProtocol = ({
1429
- toolCallStart = "<tool_call>",
1430
- toolCallEnd = "</tool_call>",
1431
- toolResponseStart = "<tool_response>",
1432
- toolResponseEnd = "</tool_response>"
1433
- } = {}) => ({
1434
- formatTools({ tools, toolSystemPromptTemplate }) {
1435
- const toolsForPrompt = (tools || []).filter((tool) => tool.type === "function").map((tool) => ({
1436
- name: tool.name,
1437
- description: tool.type === "function" && typeof tool.description === "string" ? tool.description : void 0,
1438
- parameters: tool.inputSchema
1439
- }));
1440
- return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
1441
- },
1442
- formatToolCall(toolCall) {
1443
- let args = {};
1444
- try {
1445
- args = JSON.parse(toolCall.input);
1446
- } catch (e) {
1447
- args = toolCall.input;
1448
- }
1449
- return `${toolCallStart}${JSON.stringify({
1450
- name: toolCall.toolName,
1451
- arguments: args
1452
- })}${toolCallEnd}`;
1453
- },
1454
- formatToolResponse(toolResult) {
1455
- return `${toolResponseStart}${JSON.stringify({
1456
- toolName: toolResult.toolName,
1457
- result: toolResult.output
1458
- })}${toolResponseEnd}`;
1459
- },
1460
- parseGeneratedText({ text, options }) {
1461
- var _a;
1462
- const startEsc = escapeRegExp(toolCallStart);
1463
- const endEsc = escapeRegExp(toolCallEnd);
1464
- const toolCallRegex = new RegExp(
1465
- `${startEsc}([\0-\uFFFF]*?)${endEsc}`,
1466
- "gs"
1467
- );
1468
- const processedElements = [];
1469
- let currentIndex = 0;
1470
- let match;
1471
- while ((match = toolCallRegex.exec(text)) !== null) {
1472
- const startIndex = match.index;
1473
- const toolCallJson = match[1];
1474
- if (startIndex > currentIndex) {
1475
- const textSegment = text.substring(currentIndex, startIndex);
1476
- if (textSegment.trim()) {
1477
- processedElements.push({ type: "text", text: textSegment });
1478
- }
1479
- }
1480
- if (toolCallJson) {
1481
- try {
1482
- const parsedToolCall = relaxed_json_exports.parse(toolCallJson);
1483
- processedElements.push({
1484
- type: "tool-call",
1485
- toolCallId: (0, import_provider_utils3.generateId)(),
1486
- toolName: parsedToolCall.name,
1487
- input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
1488
- });
1489
- } catch (error) {
1490
- if (options == null ? void 0 : options.onError) {
1491
- options.onError(
1492
- "Could not process JSON tool call, keeping original text.",
1493
- { toolCall: match[0], error }
1494
- );
1495
- }
1496
- processedElements.push({ type: "text", text: match[0] });
1497
- }
1498
- }
1499
- currentIndex = startIndex + match[0].length;
1500
- }
1501
- if (currentIndex < text.length) {
1502
- const remainingText = text.substring(currentIndex);
1503
- if (remainingText.trim()) {
1504
- processedElements.push({ type: "text", text: remainingText });
1505
- }
1161
+ if (currentIndex < text.length) {
1162
+ const remainingText = text.substring(currentIndex);
1163
+ if (remainingText.trim()) {
1164
+ processedElements.push({ type: "text", text: remainingText });
1165
+ }
1506
1166
  }
1507
1167
  return processedElements;
1508
1168
  },
@@ -1518,7 +1178,7 @@ var jsonMixProtocol = ({
1518
1178
  if (chunk.type === "finish") {
1519
1179
  if (isInsideToolCall && buffer.length > 0) {
1520
1180
  if (!currentTextId) {
1521
- currentTextId = (0, import_provider_utils3.generateId)();
1181
+ currentTextId = (0, import_provider_utils2.generateId)();
1522
1182
  controller.enqueue({ type: "text-start", id: currentTextId });
1523
1183
  hasEmittedTextStart = true;
1524
1184
  }
@@ -1530,7 +1190,7 @@ var jsonMixProtocol = ({
1530
1190
  buffer = "";
1531
1191
  } else if (!isInsideToolCall && buffer.length > 0) {
1532
1192
  if (!currentTextId) {
1533
- currentTextId = (0, import_provider_utils3.generateId)();
1193
+ currentTextId = (0, import_provider_utils2.generateId)();
1534
1194
  controller.enqueue({ type: "text-start", id: currentTextId });
1535
1195
  hasEmittedTextStart = true;
1536
1196
  }
@@ -1547,7 +1207,7 @@ var jsonMixProtocol = ({
1547
1207
  hasEmittedTextStart = false;
1548
1208
  }
1549
1209
  if (currentToolCallJson) {
1550
- const errorId = (0, import_provider_utils3.generateId)();
1210
+ const errorId = (0, import_provider_utils2.generateId)();
1551
1211
  controller.enqueue({ type: "text-start", id: errorId });
1552
1212
  controller.enqueue({
1553
1213
  type: "text-delta",
@@ -1575,7 +1235,7 @@ var jsonMixProtocol = ({
1575
1235
  currentToolCallJson += text;
1576
1236
  } else if (text.length > 0) {
1577
1237
  if (!currentTextId) {
1578
- currentTextId = (0, import_provider_utils3.generateId)();
1238
+ currentTextId = (0, import_provider_utils2.generateId)();
1579
1239
  controller.enqueue({ type: "text-start", id: currentTextId });
1580
1240
  hasEmittedTextStart = true;
1581
1241
  }
@@ -1610,12 +1270,12 @@ var jsonMixProtocol = ({
1610
1270
  }
1611
1271
  controller.enqueue({
1612
1272
  type: "tool-call",
1613
- toolCallId: (0, import_provider_utils3.generateId)(),
1273
+ toolCallId: (0, import_provider_utils2.generateId)(),
1614
1274
  toolName: parsedToolCall.name,
1615
1275
  input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
1616
1276
  });
1617
1277
  } catch (e) {
1618
- const errorId = (0, import_provider_utils3.generateId)();
1278
+ const errorId = (0, import_provider_utils2.generateId)();
1619
1279
  controller.enqueue({ type: "text-start", id: errorId });
1620
1280
  controller.enqueue({
1621
1281
  type: "text-delta",
@@ -1648,13 +1308,24 @@ var jsonMixProtocol = ({
1648
1308
  }
1649
1309
  }
1650
1310
  });
1311
+ },
1312
+ extractToolCallSegments({ text }) {
1313
+ const startEsc = escapeRegExp(toolCallStart);
1314
+ const endEsc = escapeRegExp(toolCallEnd);
1315
+ const regex = new RegExp(`${startEsc}([\0-\uFFFF]*?)${endEsc}`, "gs");
1316
+ const segments = [];
1317
+ let m;
1318
+ while ((m = regex.exec(text)) != null) {
1319
+ segments.push(m[0]);
1320
+ }
1321
+ return segments;
1651
1322
  }
1652
1323
  });
1653
1324
 
1654
- // src/protocols/xml-protocol.ts
1655
- var import_provider_utils4 = require("@ai-sdk/provider-utils");
1325
+ // src/protocols/morph-xml-protocol.ts
1326
+ var import_provider_utils3 = require("@ai-sdk/provider-utils");
1656
1327
  var import_fast_xml_parser = require("fast-xml-parser");
1657
- var xmlProtocol = () => ({
1328
+ var morphXmlProtocol = () => ({
1658
1329
  formatTools({ tools, toolSystemPromptTemplate }) {
1659
1330
  const toolsForPrompt = (tools || []).map((tool) => ({
1660
1331
  name: tool.name,
@@ -1805,7 +1476,7 @@ var xmlProtocol = () => ({
1805
1476
  const coercedArgs = coerceBySchema(args, schema);
1806
1477
  processedElements.push({
1807
1478
  type: "tool-call",
1808
- toolCallId: (0, import_provider_utils4.generateId)(),
1479
+ toolCallId: (0, import_provider_utils3.generateId)(),
1809
1480
  toolName,
1810
1481
  input: JSON.stringify(coercedArgs)
1811
1482
  });
@@ -1834,7 +1505,7 @@ var xmlProtocol = () => ({
1834
1505
  const content = text != null ? text : buffer;
1835
1506
  if (content) {
1836
1507
  if (!currentTextId) {
1837
- currentTextId = (0, import_provider_utils4.generateId)();
1508
+ currentTextId = (0, import_provider_utils3.generateId)();
1838
1509
  controller.enqueue({ type: "text-start", id: currentTextId });
1839
1510
  }
1840
1511
  controller.enqueue({
@@ -1959,7 +1630,7 @@ var xmlProtocol = () => ({
1959
1630
  flushText(controller);
1960
1631
  controller.enqueue({
1961
1632
  type: "tool-call",
1962
- toolCallId: (0, import_provider_utils4.generateId)(),
1633
+ toolCallId: (0, import_provider_utils3.generateId)(),
1963
1634
  toolName: currentToolCall.name,
1964
1635
  input: JSON.stringify(coercedArgs)
1965
1636
  });
@@ -2019,11 +1690,578 @@ var xmlProtocol = () => ({
2019
1690
  }
2020
1691
  }
2021
1692
  });
1693
+ },
1694
+ extractToolCallSegments({ text, tools }) {
1695
+ const toolNames = tools.map((t) => t.name).filter(Boolean);
1696
+ if (toolNames.length === 0) return [];
1697
+ const names = toolNames.map((n) => escapeRegExp(String(n))).join("|");
1698
+ if (!names) return [];
1699
+ const regex = new RegExp(`<(${names})>[\\s\\S]*?<\\/\\1>`, "g");
1700
+ const segments = [];
1701
+ let m;
1702
+ while ((m = regex.exec(text)) != null) {
1703
+ segments.push(m[0]);
1704
+ }
1705
+ return segments;
2022
1706
  }
2023
1707
  });
2024
1708
 
2025
- // src/protocols/dummy-protocol.ts
1709
+ // src/generate-handler.ts
1710
+ var import_provider_utils4 = require("@ai-sdk/provider-utils");
1711
+ async function wrapGenerate({
1712
+ protocol,
1713
+ doGenerate,
1714
+ params
1715
+ }) {
1716
+ var _a, _b;
1717
+ if (isToolChoiceActive(params)) {
1718
+ const result2 = await doGenerate();
1719
+ let parsed2 = {};
1720
+ const first = (_a = result2.content) == null ? void 0 : _a[0];
1721
+ if (first && first.type === "text") {
1722
+ const debugLevel2 = getDebugLevel();
1723
+ if (debugLevel2 === "parse") {
1724
+ logRawChunk(first.text);
1725
+ }
1726
+ try {
1727
+ parsed2 = JSON.parse(first.text);
1728
+ } catch (error) {
1729
+ const options = extractOnErrorOption(params.providerOptions);
1730
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
1731
+ options,
1732
+ "Failed to parse toolChoice JSON from generated model output",
1733
+ {
1734
+ text: first.text,
1735
+ error: error instanceof Error ? error.message : String(error)
1736
+ }
1737
+ );
1738
+ parsed2 = {};
1739
+ }
1740
+ }
1741
+ const toolCall = {
1742
+ type: "tool-call",
1743
+ toolCallId: (0, import_provider_utils4.generateId)(),
1744
+ toolName: parsed2.name || "unknown",
1745
+ input: JSON.stringify(parsed2.arguments || {})
1746
+ };
1747
+ const debugLevelToolChoice = getDebugLevel();
1748
+ const originText = first && first.type === "text" ? first.text : "";
1749
+ if (debugLevelToolChoice === "parse") {
1750
+ logParsedSummary({ toolCalls: [toolCall], originalText: originText });
1751
+ }
1752
+ return {
1753
+ ...result2,
1754
+ content: [toolCall]
1755
+ };
1756
+ }
1757
+ const result = await doGenerate();
1758
+ if (result.content.length === 0) {
1759
+ return result;
1760
+ }
1761
+ const parsed = result.content.flatMap((contentItem) => {
1762
+ var _a2;
1763
+ if (contentItem.type !== "text") {
1764
+ return [contentItem];
1765
+ }
1766
+ const debugLevel2 = getDebugLevel();
1767
+ if (debugLevel2 === "stream") {
1768
+ logRawChunk(contentItem.text);
1769
+ }
1770
+ return protocol.parseGeneratedText({
1771
+ text: contentItem.text,
1772
+ tools: getFunctionTools(params),
1773
+ options: {
1774
+ ...extractOnErrorOption(params.providerOptions),
1775
+ ...(_a2 = params.providerOptions) == null ? void 0 : _a2.toolCallMiddleware
1776
+ }
1777
+ });
1778
+ });
1779
+ const tools = getFunctionTools(params);
1780
+ const newContent = parsed.map(
1781
+ (part) => coerceToolCallInput(part, tools)
1782
+ );
1783
+ const debugLevel = getDebugLevel();
1784
+ if (debugLevel === "stream") {
1785
+ newContent.forEach((part) => logParsedChunk(part));
1786
+ }
1787
+ if (debugLevel === "parse") {
1788
+ const allText = result.content.filter(
1789
+ (c) => c.type === "text"
1790
+ ).map((c) => c.text).join("\n\n");
1791
+ const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({ text: allText, tools }) : [];
1792
+ const originalText = segments.join("\n\n");
1793
+ const toolCalls = newContent.filter(
1794
+ (p) => p.type === "tool-call"
1795
+ );
1796
+ logParsedSummary({ toolCalls, originalText });
1797
+ }
1798
+ return {
1799
+ ...result,
1800
+ content: newContent
1801
+ };
1802
+ }
1803
+
1804
+ // src/stream-handler.ts
2026
1805
  var import_provider_utils5 = require("@ai-sdk/provider-utils");
1806
+ async function wrapStream({
1807
+ protocol,
1808
+ doStream,
1809
+ doGenerate,
1810
+ params
1811
+ }) {
1812
+ var _a;
1813
+ if (isToolChoiceActive(params)) {
1814
+ return toolChoiceStream({
1815
+ doGenerate,
1816
+ options: extractOnErrorOption(params.providerOptions)
1817
+ });
1818
+ }
1819
+ const { stream, ...rest } = await doStream();
1820
+ const debugLevel = getDebugLevel();
1821
+ const tools = getFunctionTools(params);
1822
+ const options = {
1823
+ ...extractOnErrorOption(params.providerOptions),
1824
+ ...(_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware
1825
+ };
1826
+ if (debugLevel === "off") {
1827
+ return {
1828
+ stream: stream.pipeThrough(
1829
+ protocol.createStreamParser({
1830
+ tools,
1831
+ options
1832
+ })
1833
+ ),
1834
+ ...rest
1835
+ };
1836
+ }
1837
+ if (debugLevel === "stream") {
1838
+ const withRawTap2 = stream.pipeThrough(
1839
+ new TransformStream(
1840
+ {
1841
+ transform(part, controller) {
1842
+ logRawChunk(part);
1843
+ controller.enqueue(part);
1844
+ }
1845
+ }
1846
+ )
1847
+ );
1848
+ const parsed2 = withRawTap2.pipeThrough(
1849
+ protocol.createStreamParser({
1850
+ tools,
1851
+ options
1852
+ })
1853
+ );
1854
+ const withParsedTap = parsed2.pipeThrough(
1855
+ new TransformStream(
1856
+ {
1857
+ transform(part, controller) {
1858
+ logParsedChunk(part);
1859
+ controller.enqueue(part);
1860
+ }
1861
+ }
1862
+ )
1863
+ );
1864
+ return {
1865
+ stream: withParsedTap,
1866
+ ...rest
1867
+ };
1868
+ }
1869
+ let fullRawText = "";
1870
+ const withRawTap = stream.pipeThrough(
1871
+ new TransformStream({
1872
+ transform(part, controller) {
1873
+ if (part.type === "text-delta") {
1874
+ const delta = part.delta;
1875
+ if (typeof delta === "string" && delta.length > 0) {
1876
+ fullRawText += delta;
1877
+ }
1878
+ }
1879
+ controller.enqueue(part);
1880
+ }
1881
+ })
1882
+ );
1883
+ const parsed = withRawTap.pipeThrough(
1884
+ protocol.createStreamParser({
1885
+ tools,
1886
+ options
1887
+ })
1888
+ );
1889
+ const withSummary = parsed.pipeThrough(
1890
+ new TransformStream({
1891
+ transform: /* @__PURE__ */ (() => {
1892
+ const parsedToolCalls = [];
1893
+ return (part, controller) => {
1894
+ if (part.type === "tool-call") {
1895
+ parsedToolCalls.push(part);
1896
+ }
1897
+ if (part.type === "finish") {
1898
+ try {
1899
+ const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({
1900
+ text: fullRawText,
1901
+ tools
1902
+ }) : [];
1903
+ const origin = segments.join("\n\n");
1904
+ logParsedSummary({
1905
+ toolCalls: parsedToolCalls,
1906
+ originalText: origin
1907
+ });
1908
+ } catch (e) {
1909
+ }
1910
+ }
1911
+ controller.enqueue(part);
1912
+ };
1913
+ })()
1914
+ })
1915
+ );
1916
+ return {
1917
+ stream: withSummary,
1918
+ ...rest
1919
+ };
1920
+ }
1921
+ async function toolChoiceStream({
1922
+ doGenerate,
1923
+ options
1924
+ }) {
1925
+ var _a, _b;
1926
+ const result = await doGenerate();
1927
+ let toolJson = {};
1928
+ if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
1929
+ try {
1930
+ toolJson = JSON.parse(result.content[0].text);
1931
+ } catch (error) {
1932
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
1933
+ options,
1934
+ "Failed to parse toolChoice JSON from streamed model output",
1935
+ {
1936
+ text: result.content[0].text,
1937
+ error: error instanceof Error ? error.message : String(error)
1938
+ }
1939
+ );
1940
+ toolJson = {};
1941
+ }
1942
+ }
1943
+ const toolCallChunk = {
1944
+ type: "tool-call",
1945
+ toolCallId: (0, import_provider_utils5.generateId)(),
1946
+ toolName: toolJson.name || "unknown",
1947
+ input: JSON.stringify(toolJson.arguments || {})
1948
+ };
1949
+ const finishChunk = {
1950
+ type: "finish",
1951
+ usage: (result == null ? void 0 : result.usage) || // TODO: If possible, try to return a certain amount of LLM usage.
1952
+ {
1953
+ inputTokens: 0,
1954
+ outputTokens: 0,
1955
+ totalTokens: 0
1956
+ },
1957
+ finishReason: "tool-calls"
1958
+ };
1959
+ const stream = new ReadableStream({
1960
+ start(controller) {
1961
+ controller.enqueue(toolCallChunk);
1962
+ controller.enqueue(finishChunk);
1963
+ controller.close();
1964
+ }
1965
+ });
1966
+ const debugLevel = getDebugLevel();
1967
+ const firstText = (result == null ? void 0 : result.content) && result.content[0] && result.content[0].type === "text" && result.content[0].text || "";
1968
+ const streamWithSummary = debugLevel === "parse" ? stream.pipeThrough(
1969
+ new TransformStream({
1970
+ transform(part, controller) {
1971
+ if (part.type === "finish") {
1972
+ try {
1973
+ logParsedSummary({
1974
+ toolCalls: [toolCallChunk],
1975
+ originalText: typeof firstText === "string" ? firstText : ""
1976
+ });
1977
+ } catch (e) {
1978
+ }
1979
+ }
1980
+ controller.enqueue(part);
1981
+ }
1982
+ })
1983
+ ) : stream;
1984
+ return {
1985
+ request: (result == null ? void 0 : result.request) || {},
1986
+ response: (result == null ? void 0 : result.response) || {},
1987
+ stream: streamWithSummary
1988
+ };
1989
+ }
1990
+
1991
+ // src/transform-handler.ts
1992
+ async function transformParams({
1993
+ params,
1994
+ protocol,
1995
+ toolSystemPromptTemplate
1996
+ }) {
1997
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1998
+ const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
1999
+ const functionTools = ((_a = params.tools) != null ? _a : []).filter(
2000
+ (t) => t.type === "function"
2001
+ );
2002
+ const systemPrompt = resolvedProtocol.formatTools({
2003
+ tools: functionTools,
2004
+ toolSystemPromptTemplate
2005
+ });
2006
+ const processedPrompt = convertToolPrompt(
2007
+ (_b = params.prompt) != null ? _b : [],
2008
+ resolvedProtocol,
2009
+ extractOnErrorOption(params.providerOptions)
2010
+ );
2011
+ const finalPrompt = ((_c = processedPrompt[0]) == null ? void 0 : _c.role) === "system" ? [
2012
+ {
2013
+ role: "system",
2014
+ content: systemPrompt + "\n\n" + processedPrompt[0].content
2015
+ },
2016
+ ...processedPrompt.slice(1)
2017
+ ] : [
2018
+ {
2019
+ role: "system",
2020
+ content: systemPrompt
2021
+ },
2022
+ ...processedPrompt
2023
+ ];
2024
+ const baseReturnParams = {
2025
+ ...params,
2026
+ prompt: finalPrompt,
2027
+ tools: [],
2028
+ toolChoice: void 0,
2029
+ providerOptions: {
2030
+ ...params.providerOptions || {},
2031
+ toolCallMiddleware: {
2032
+ ...params.providerOptions && typeof params.providerOptions === "object" && params.providerOptions.toolCallMiddleware || {},
2033
+ // INTERNAL: used by the middleware to propagate the names of custom
2034
+ // function tools into downstream handlers (stream/generate) when
2035
+ // providers strip or ignore `params.tools`. Not a stable public API.
2036
+ toolNames: functionTools.map((t) => t.name)
2037
+ }
2038
+ }
2039
+ };
2040
+ if (((_d = params.toolChoice) == null ? void 0 : _d.type) === "none") {
2041
+ throw new Error(
2042
+ "The 'none' toolChoice type is not supported by this middleware. Please use 'auto', 'required', or specify a tool name."
2043
+ );
2044
+ }
2045
+ if (((_e = params.toolChoice) == null ? void 0 : _e.type) === "tool") {
2046
+ const selectedToolName = params.toolChoice.toolName;
2047
+ const providerDefinedMatch = ((_f = params.tools) != null ? _f : []).find((t) => {
2048
+ if (t.type === "function") return false;
2049
+ const anyTool = t;
2050
+ return anyTool.id === selectedToolName || anyTool.name === selectedToolName;
2051
+ });
2052
+ if (providerDefinedMatch) {
2053
+ throw new Error(
2054
+ "Provider-defined tools are not supported by this middleware. Please use custom tools."
2055
+ );
2056
+ }
2057
+ const selectedTool = ((_g = params.tools) != null ? _g : []).find(
2058
+ (t) => t.type === "function" && t.name === selectedToolName
2059
+ );
2060
+ if (!selectedTool) {
2061
+ throw new Error(
2062
+ `Tool with name '${selectedToolName}' not found in params.tools.`
2063
+ );
2064
+ }
2065
+ return {
2066
+ ...baseReturnParams,
2067
+ responseFormat: {
2068
+ type: "json",
2069
+ schema: {
2070
+ type: "object",
2071
+ properties: {
2072
+ name: {
2073
+ const: selectedTool.name
2074
+ },
2075
+ arguments: selectedTool.inputSchema
2076
+ },
2077
+ required: ["name", "arguments"]
2078
+ },
2079
+ name: selectedTool.name,
2080
+ description: typeof selectedTool.description === "string" ? selectedTool.description : void 0
2081
+ },
2082
+ providerOptions: {
2083
+ ...baseReturnParams.providerOptions || {},
2084
+ toolCallMiddleware: {
2085
+ ...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
2086
+ // INTERNAL: used by the middleware to activate the tool-choice
2087
+ // fast-path in handlers. Not a stable public API.
2088
+ toolChoice: params.toolChoice
2089
+ }
2090
+ }
2091
+ };
2092
+ }
2093
+ if (((_h = params.toolChoice) == null ? void 0 : _h.type) === "required") {
2094
+ if (!params.tools || params.tools.length === 0) {
2095
+ throw new Error(
2096
+ "Tool choice type 'required' is set, but no tools are provided in params.tools."
2097
+ );
2098
+ }
2099
+ return {
2100
+ ...baseReturnParams,
2101
+ responseFormat: {
2102
+ type: "json",
2103
+ schema: createDynamicIfThenElseSchema(functionTools)
2104
+ },
2105
+ providerOptions: {
2106
+ ...baseReturnParams.providerOptions || {},
2107
+ toolCallMiddleware: {
2108
+ ...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
2109
+ // INTERNAL: used by the middleware to activate the tool-choice
2110
+ // fast-path in handlers. Not a stable public API.
2111
+ toolChoice: { type: "required" }
2112
+ }
2113
+ }
2114
+ };
2115
+ }
2116
+ return baseReturnParams;
2117
+ }
2118
+ function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
2119
+ const processedPrompt = prompt.map((message) => {
2120
+ var _a;
2121
+ if (message.role === "assistant") {
2122
+ const newContent = [];
2123
+ for (const content of message.content) {
2124
+ if (isToolCallContent(content)) {
2125
+ newContent.push({
2126
+ type: "text",
2127
+ text: resolvedProtocol.formatToolCall(content)
2128
+ });
2129
+ } else if (content.type === "text") {
2130
+ newContent.push(content);
2131
+ } else if (content.type === "reasoning") {
2132
+ newContent.push(content);
2133
+ } else {
2134
+ const options = extractOnErrorOption(providerOptions);
2135
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
2136
+ options,
2137
+ "tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
2138
+ { content }
2139
+ );
2140
+ newContent.push({
2141
+ type: "text",
2142
+ text: JSON.stringify(content)
2143
+ });
2144
+ }
2145
+ }
2146
+ const onlyText = newContent.every((c) => c.type === "text");
2147
+ const condensedAssistant = onlyText ? [
2148
+ {
2149
+ type: "text",
2150
+ text: newContent.map((c) => c.text).join("\n")
2151
+ }
2152
+ ] : newContent;
2153
+ return { role: "assistant", content: condensedAssistant };
2154
+ }
2155
+ if (message.role === "tool") {
2156
+ return {
2157
+ role: "user",
2158
+ // Map tool results to text response blocks, then condense into a single text block
2159
+ content: [
2160
+ {
2161
+ type: "text",
2162
+ text: message.content.map(
2163
+ (toolResult) => isToolResultPart(toolResult) ? resolvedProtocol.formatToolResponse(toolResult) : resolvedProtocol.formatToolResponse(
2164
+ toolResult
2165
+ )
2166
+ ).join("\n")
2167
+ }
2168
+ ]
2169
+ };
2170
+ }
2171
+ return message;
2172
+ });
2173
+ for (let i = 0; i < processedPrompt.length; i++) {
2174
+ const msg = processedPrompt[i];
2175
+ if (Array.isArray(msg.content)) {
2176
+ const allText = msg.content.every(
2177
+ (c) => (c == null ? void 0 : c.type) === "text"
2178
+ );
2179
+ if (allText && msg.content.length > 1) {
2180
+ const joinedText = msg.content.map((c) => c.text).join("\n");
2181
+ if (msg.role === "system") {
2182
+ processedPrompt[i] = {
2183
+ role: "system",
2184
+ content: joinedText
2185
+ };
2186
+ } else if (msg.role === "assistant") {
2187
+ processedPrompt[i] = {
2188
+ role: "assistant",
2189
+ content: [
2190
+ {
2191
+ type: "text",
2192
+ text: joinedText
2193
+ }
2194
+ ]
2195
+ };
2196
+ } else {
2197
+ processedPrompt[i] = {
2198
+ role: "user",
2199
+ content: [
2200
+ {
2201
+ type: "text",
2202
+ text: joinedText
2203
+ }
2204
+ ]
2205
+ };
2206
+ }
2207
+ }
2208
+ }
2209
+ }
2210
+ for (let i = processedPrompt.length - 1; i > 0; i--) {
2211
+ const current = processedPrompt[i];
2212
+ const prev = processedPrompt[i - 1];
2213
+ if (current.role === "user" && prev.role === "user") {
2214
+ const prevContent = prev.content.map((c) => c.type === "text" ? c.text : "").join("\n");
2215
+ const currentContent = current.content.map((c) => c.type === "text" ? c.text : "").join("\n");
2216
+ processedPrompt[i - 1] = {
2217
+ role: "user",
2218
+ content: [{ type: "text", text: prevContent + "\n" + currentContent }]
2219
+ };
2220
+ processedPrompt.splice(i, 1);
2221
+ }
2222
+ }
2223
+ return processedPrompt;
2224
+ }
2225
+
2226
+ // src/tool-call-middleware.ts
2227
+ function createToolMiddleware({
2228
+ protocol,
2229
+ toolSystemPromptTemplate
2230
+ }) {
2231
+ const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
2232
+ return {
2233
+ middlewareVersion: "v2",
2234
+ wrapStream: async ({ doStream, doGenerate, params }) => {
2235
+ if (isToolChoiceActive(params)) {
2236
+ return toolChoiceStream({
2237
+ doGenerate,
2238
+ options: extractOnErrorOption(params.providerOptions)
2239
+ });
2240
+ } else {
2241
+ return wrapStream({
2242
+ protocol: resolvedProtocol,
2243
+ doStream,
2244
+ doGenerate,
2245
+ params
2246
+ });
2247
+ }
2248
+ },
2249
+ wrapGenerate: async ({ doGenerate, params }) => wrapGenerate({
2250
+ protocol: resolvedProtocol,
2251
+ doGenerate,
2252
+ params
2253
+ }),
2254
+ transformParams: async ({
2255
+ params
2256
+ }) => {
2257
+ return transformParams({
2258
+ protocol: resolvedProtocol,
2259
+ toolSystemPromptTemplate,
2260
+ params
2261
+ });
2262
+ }
2263
+ };
2264
+ }
2027
2265
 
2028
2266
  // src/index.ts
2029
2267
  var gemmaToolMiddleware = createToolMiddleware({
@@ -2031,8 +2269,9 @@ var gemmaToolMiddleware = createToolMiddleware({
2031
2269
  // Customize the tool call delimiters to use markdown code fences
2032
2270
  {
2033
2271
  toolCallStart: "```tool_call\n",
2034
- toolCallEnd: "\n``",
2035
- // two backticks are more common in gemma output @
2272
+ // TODO: Support specifying multiple possible tags,
2273
+ // e.g., for gemma, it would be nice to be able to set both `` and ``` at the same time.
2274
+ toolCallEnd: "\n```",
2036
2275
  toolResponseStart: "```tool_response\n",
2037
2276
  toolResponseEnd: "\n```"
2038
2277
  }
@@ -2063,7 +2302,7 @@ For each function call return a json object with function name and arguments wit
2063
2302
  }
2064
2303
  });
2065
2304
  var xmlToolMiddleware = createToolMiddleware({
2066
- protocol: xmlProtocol,
2305
+ protocol: morphXmlProtocol,
2067
2306
  toolSystemPromptTemplate(tools) {
2068
2307
  return `You are a function calling AI model.
2069
2308
  You are provided with function signatures within <tools></tools> XML tags.
@@ -2082,15 +2321,11 @@ San Fransisco
2082
2321
  });
2083
2322
  // Annotate the CommonJS export names for ESM import in node:
2084
2323
  0 && (module.exports = {
2085
- coerceBySchema,
2086
2324
  createToolMiddleware,
2087
- fixToolCallWithSchema,
2088
2325
  gemmaToolMiddleware,
2089
- getSchemaType,
2090
2326
  hermesToolMiddleware,
2091
2327
  jsonMixProtocol,
2092
- unwrapJsonSchema,
2093
- xmlProtocol,
2328
+ morphXmlProtocol,
2094
2329
  xmlToolMiddleware
2095
2330
  });
2096
2331
  //# sourceMappingURL=index.cjs.map