@ai-sdk-tool/parser 2.0.16 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -22,98 +22,16 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  createToolMiddleware: () => createToolMiddleware,
24
24
  gemmaToolMiddleware: () => gemmaToolMiddleware,
25
- hermesToolMiddleware: () => hermesToolMiddleware
25
+ hermesToolMiddleware: () => hermesToolMiddleware,
26
+ jsonMixProtocol: () => jsonMixProtocol,
27
+ xmlProtocol: () => xmlProtocol,
28
+ xmlToolMiddleware: () => xmlToolMiddleware
26
29
  });
27
30
  module.exports = __toCommonJS(index_exports);
28
31
 
29
32
  // src/tool-call-middleware.ts
30
33
  var import_provider_utils2 = require("@ai-sdk/provider-utils");
31
34
 
32
- // src/utils/conv-tool-prompt.ts
33
- function convertToolPrompt({
34
- paramsPrompt,
35
- paramsTools,
36
- toolSystemPromptTemplate,
37
- toolCallTag,
38
- toolCallEndTag,
39
- toolResponseTag,
40
- toolResponseEndTag
41
- }) {
42
- const processedPrompt = paramsPrompt.map((message) => {
43
- if (message.role === "assistant") {
44
- const mergedContents = [];
45
- for (const content of message.content) {
46
- if (content.type === "tool-call") {
47
- mergedContents.push({
48
- type: "text",
49
- text: `${toolCallTag}${JSON.stringify({
50
- arguments: content.input,
51
- name: content.toolName
52
- })}${toolCallEndTag}`
53
- });
54
- } else {
55
- mergedContents.push(content);
56
- }
57
- }
58
- const finalContents = [];
59
- for (const item of mergedContents) {
60
- if (finalContents.length > 0 && item.type === "text" && finalContents[finalContents.length - 1].type === "text") {
61
- const last = finalContents[finalContents.length - 1];
62
- if (last.type === "text" && item.type === "text") {
63
- finalContents[finalContents.length - 1] = {
64
- type: "text",
65
- text: last.text + "\n" + item.text
66
- };
67
- }
68
- } else {
69
- finalContents.push(item);
70
- }
71
- }
72
- return {
73
- role: "assistant",
74
- content: finalContents
75
- };
76
- } else if (message.role === "tool") {
77
- return {
78
- role: "user",
79
- content: [
80
- {
81
- type: "text",
82
- text: message.content.map(
83
- (content) => `${toolResponseTag}${JSON.stringify({
84
- toolName: content.toolName,
85
- // TODO: If the tool result part contains content, modify to respect and include it.
86
- result: content.output
87
- })}${toolResponseEndTag}`
88
- ).join("\n")
89
- }
90
- ]
91
- };
92
- }
93
- return message;
94
- });
95
- const toolsForPrompt = (paramsTools || []).filter((tool) => tool.type === "function").map((tool) => ({
96
- name: tool.name,
97
- description: tool.type === "function" && typeof tool.description === "string" ? tool.description : void 0,
98
- parameters: tool.inputSchema
99
- }));
100
- const HermesPrompt = toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
101
- const toolSystemPrompt = processedPrompt[0].role === "system" ? [
102
- {
103
- role: "system",
104
- content: HermesPrompt + "\n\n" + processedPrompt[0].content
105
- },
106
- ...processedPrompt.slice(1)
107
- ] : [
108
- {
109
- role: "system",
110
- content: HermesPrompt
111
- },
112
- ...processedPrompt
113
- ];
114
- return toolSystemPrompt;
115
- }
116
-
117
35
  // src/utils/dynamic-tool-schema.ts
118
36
  function createDynamicIfThenElseSchema(tools) {
119
37
  let currentSchema = {};
@@ -816,161 +734,84 @@ function stringify(obj) {
816
734
  return "null";
817
735
  }
818
736
 
819
- // src/stream-handler.ts
820
- var import_provider_utils = require("@ai-sdk/provider-utils");
821
- async function normalToolStream({
822
- doStream,
823
- toolCallTag,
824
- toolCallEndTag
825
- }) {
737
+ // src/utils/regex.ts
738
+ function escapeRegExp(literal) {
739
+ return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
740
+ }
741
+
742
+ // src/utils/type-guards.ts
743
+ function isToolCallContent(content) {
744
+ return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
745
+ (typeof content.input === "string" || typeof content.input === "object");
746
+ }
747
+ function isToolResultPart(content) {
748
+ const c = content;
749
+ return !!c && c.type === "tool-result" && typeof c.toolName === "string" && typeof c.toolCallId === "string" && "output" in c;
750
+ }
751
+ function hasInputProperty(obj) {
752
+ return typeof obj === "object" && obj !== null && "input" in obj;
753
+ }
754
+
755
+ // src/utils/tools.ts
756
+ function isToolChoiceActive(params) {
757
+ var _a, _b, _c;
758
+ const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
759
+ 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"));
760
+ }
761
+ function getFunctionTools(params) {
762
+ var _a, _b;
763
+ const rawToolNames = params.providerOptions && typeof params.providerOptions === "object" && ((_a = params.providerOptions.toolCallMiddleware) == null ? void 0 : _a.toolNames) || [];
764
+ const toStringArray = (val) => Array.isArray(val) ? val.filter(
765
+ (item) => typeof item === "string"
766
+ ) : [];
767
+ const toolNames = toStringArray(rawToolNames);
768
+ if (toolNames.length > 0) {
769
+ return toolNames.map((name) => ({
770
+ type: "function",
771
+ name,
772
+ description: "",
773
+ inputSchema: { type: "object" }
774
+ }));
775
+ }
776
+ return ((_b = params.tools) != null ? _b : []).filter(
777
+ (t) => t.type === "function"
778
+ );
779
+ }
780
+
781
+ // src/utils/on-error.ts
782
+ function extractOnErrorOption(providerOptions) {
826
783
  var _a;
827
- const { stream, ...rest } = await doStream();
828
- let isFirstToolCall = true;
829
- let isFirstText = true;
830
- let afterSwitch = false;
831
- let isToolCall = false;
832
- let buffer = "";
833
- let toolCallIndex = -1;
834
- let toolCallBuffer = [];
835
- let currentTextId = null;
836
- let hasEmittedTextStart = false;
837
- const transformStream = new TransformStream({
838
- transform(chunk, controller) {
839
- if (chunk.type === "finish") {
840
- if (isToolCall && (buffer.length > 0 || toolCallIndex >= 0 && toolCallBuffer[toolCallIndex])) {
841
- if (!currentTextId) {
842
- currentTextId = (0, import_provider_utils.generateId)();
843
- controller.enqueue({
844
- type: "text-start",
845
- id: currentTextId
846
- });
847
- hasEmittedTextStart = true;
848
- }
849
- const incompleteContent = (toolCallBuffer[toolCallIndex] || "") + buffer;
850
- controller.enqueue({
851
- type: "text-delta",
852
- id: currentTextId,
853
- delta: toolCallTag + incompleteContent
854
- });
855
- if (toolCallIndex >= 0) {
856
- toolCallBuffer = toolCallBuffer.slice(0, toolCallIndex);
857
- }
858
- }
859
- if (currentTextId && hasEmittedTextStart) {
860
- controller.enqueue({
861
- type: "text-end",
862
- id: currentTextId
863
- });
864
- currentTextId = null;
865
- hasEmittedTextStart = false;
866
- }
867
- if (toolCallBuffer.length > 0) {
868
- toolCallBuffer.forEach((toolCall) => {
869
- try {
870
- const parsedToolCall = relaxed_json_exports.parse(toolCall);
871
- controller.enqueue({
872
- type: "tool-call",
873
- toolCallId: (0, import_provider_utils.generateId)(),
874
- toolName: parsedToolCall.name,
875
- input: JSON.stringify(parsedToolCall.arguments)
876
- });
877
- } catch (e) {
878
- console.error(`Error parsing tool call: ${toolCall}`, e);
879
- const errorId = (0, import_provider_utils.generateId)();
880
- controller.enqueue({
881
- type: "text-start",
882
- id: errorId
883
- });
884
- controller.enqueue({
885
- type: "text-delta",
886
- id: errorId,
887
- delta: `${toolCallTag}${toolCall}${toolCallEndTag}`
888
- });
889
- controller.enqueue({
890
- type: "text-end",
891
- id: errorId
892
- });
893
- }
894
- });
895
- }
896
- controller.enqueue(chunk);
897
- return;
898
- } else if (chunk.type !== "text-delta") {
899
- controller.enqueue(chunk);
900
- return;
901
- }
902
- buffer += chunk.delta;
903
- function publish(text) {
904
- if (text.length > 0 || isToolCall) {
905
- const prefix = afterSwitch && (isToolCall ? !isFirstToolCall : !isFirstText) ? "\n" : "";
906
- if (isToolCall) {
907
- if (currentTextId && hasEmittedTextStart) {
908
- controller.enqueue({
909
- type: "text-end",
910
- id: currentTextId
911
- });
912
- currentTextId = null;
913
- hasEmittedTextStart = false;
914
- }
915
- if (!toolCallBuffer[toolCallIndex]) {
916
- toolCallBuffer[toolCallIndex] = "";
917
- }
918
- toolCallBuffer[toolCallIndex] += text;
919
- } else if (text.length > 0) {
920
- if (!currentTextId) {
921
- currentTextId = (0, import_provider_utils.generateId)();
922
- controller.enqueue({
923
- type: "text-start",
924
- id: currentTextId
925
- });
926
- hasEmittedTextStart = true;
927
- }
928
- controller.enqueue({
929
- type: "text-delta",
930
- id: currentTextId,
931
- delta: prefix + text
932
- });
933
- }
934
- afterSwitch = false;
935
- if (isToolCall) {
936
- isFirstToolCall = false;
937
- } else {
938
- isFirstText = false;
939
- }
940
- }
941
- }
942
- do {
943
- const nextTag = isToolCall ? toolCallEndTag : toolCallTag;
944
- const startIndex = getPotentialStartIndex(buffer, nextTag);
945
- if (startIndex == null) {
946
- publish(buffer);
947
- buffer = "";
948
- break;
949
- }
950
- const foundFullMatch = startIndex + nextTag.length <= buffer.length;
951
- if (foundFullMatch) {
952
- publish(buffer.slice(0, startIndex));
953
- buffer = buffer.slice(startIndex + nextTag.length);
954
- toolCallIndex++;
955
- isToolCall = !isToolCall;
956
- afterSwitch = true;
957
- } else {
958
- break;
959
- }
960
- } while (true);
961
- }
962
- });
963
- return {
964
- stream: (_a = stream == null ? void 0 : stream.pipeThrough(transformStream)) != null ? _a : new ReadableStream(),
965
- ...rest
966
- };
784
+ if (providerOptions && typeof providerOptions === "object") {
785
+ const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
786
+ return onError ? { onError } : void 0;
787
+ }
788
+ return void 0;
967
789
  }
790
+
791
+ // src/stream-handler.ts
792
+ var import_provider_utils = require("@ai-sdk/provider-utils");
968
793
  async function toolChoiceStream({
969
- doGenerate
794
+ doGenerate,
795
+ options
970
796
  }) {
971
- var _a;
797
+ var _a, _b;
972
798
  const result = await doGenerate();
973
- const toolJson = (result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text" ? JSON.parse(result.content[0].text) : {};
799
+ let toolJson = {};
800
+ if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
801
+ try {
802
+ toolJson = JSON.parse(result.content[0].text);
803
+ } catch (error) {
804
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
805
+ options,
806
+ "Failed to parse toolChoice JSON from streamed model output",
807
+ {
808
+ text: result.content[0].text,
809
+ error: error instanceof Error ? error.message : String(error)
810
+ }
811
+ );
812
+ toolJson = {};
813
+ }
814
+ }
974
815
  const toolCallChunk = {
975
816
  type: "tool-call",
976
817
  toolCallId: (0, import_provider_utils.generateId)(),
@@ -1002,156 +843,220 @@ async function toolChoiceStream({
1002
843
  }
1003
844
 
1004
845
  // src/tool-call-middleware.ts
1005
- function isToolChoiceActive(params) {
1006
- var _a, _b;
1007
- const toolChoice = (_b = (_a = params == null ? void 0 : params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
1008
- return typeof params.providerOptions === "object" && params.providerOptions !== null && typeof params.providerOptions.toolCallMiddleware === "object" && toolChoice && typeof toolChoice === "object" && (toolChoice.type === "tool" || toolChoice.type === "required");
846
+ function isProtocolFactory(protocol) {
847
+ return typeof protocol === "function";
1009
848
  }
1010
849
  function createToolMiddleware({
1011
- toolCallTag,
1012
- toolCallEndTag,
1013
- toolResponseTag,
1014
- toolResponseEndTag,
850
+ protocol,
1015
851
  toolSystemPromptTemplate
1016
852
  }) {
853
+ const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
1017
854
  return {
1018
855
  middlewareVersion: "v2",
1019
856
  wrapStream: async ({ doStream, doGenerate, params }) => {
1020
857
  if (isToolChoiceActive(params)) {
1021
858
  return toolChoiceStream({
1022
- doGenerate
1023
- });
1024
- } else {
1025
- return normalToolStream({
1026
- doStream,
1027
- toolCallTag,
1028
- toolCallEndTag
859
+ doGenerate,
860
+ options: extractOnErrorOption(params.providerOptions)
1029
861
  });
1030
862
  }
863
+ const { stream, ...rest } = await doStream();
864
+ return {
865
+ stream: stream.pipeThrough(
866
+ resolvedProtocol.createStreamParser({
867
+ tools: getFunctionTools(params),
868
+ options: extractOnErrorOption(params.providerOptions)
869
+ })
870
+ ),
871
+ ...rest
872
+ };
1031
873
  },
1032
874
  wrapGenerate: async ({ doGenerate, params }) => {
1033
- const result = await doGenerate();
1034
- if (result.content.length === 0) {
1035
- return result;
1036
- }
875
+ var _a, _b;
1037
876
  if (isToolChoiceActive(params)) {
1038
- const toolJson = result.content[0].type === "text" ? JSON.parse(result.content[0].text) : {};
877
+ const result2 = await doGenerate();
878
+ let parsed = {};
879
+ const first = (_a = result2.content) == null ? void 0 : _a[0];
880
+ if (first && first.type === "text") {
881
+ try {
882
+ parsed = JSON.parse(first.text);
883
+ } catch (error) {
884
+ const options = extractOnErrorOption(params.providerOptions);
885
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
886
+ options,
887
+ "Failed to parse toolChoice JSON from generated model output",
888
+ {
889
+ text: first.text,
890
+ error: error instanceof Error ? error.message : String(error)
891
+ }
892
+ );
893
+ parsed = {};
894
+ }
895
+ }
1039
896
  return {
1040
- ...result,
897
+ ...result2,
1041
898
  content: [
1042
899
  {
1043
900
  type: "tool-call",
1044
- toolCallType: "function",
1045
901
  toolCallId: (0, import_provider_utils2.generateId)(),
1046
- toolName: toolJson.name || "unknown",
1047
- input: JSON.stringify(toolJson.arguments || {})
902
+ toolName: parsed.name || "unknown",
903
+ input: JSON.stringify(parsed.arguments || {})
1048
904
  }
1049
905
  ]
1050
906
  };
1051
907
  }
1052
- const toolCallRegex = new RegExp(
1053
- `${toolCallTag}(.*?)(?:${toolCallEndTag}|$)`,
1054
- "gs"
1055
- );
1056
- const newContent = result.content.flatMap(
1057
- (contentItem) => {
1058
- if (contentItem.type !== "text" || !contentItem.text.includes(toolCallTag)) {
1059
- return [contentItem];
1060
- }
1061
- const text = contentItem.text;
1062
- const processedElements = [];
1063
- let currentIndex = 0;
1064
- let match;
1065
- const parseAndCreateToolCall = (toolCallJson) => {
1066
- try {
1067
- const parsedToolCall = relaxed_json_exports.parse(toolCallJson);
1068
- if (!parsedToolCall || typeof parsedToolCall.name !== "string" || typeof parsedToolCall.arguments === "undefined") {
1069
- console.error(
1070
- "Failed to parse tool call: Invalid structure",
1071
- toolCallJson
1072
- );
1073
- return null;
1074
- }
1075
- return {
1076
- type: "tool-call",
1077
- toolCallId: (0, import_provider_utils2.generateId)(),
1078
- toolName: parsedToolCall.name,
1079
- // Ensure args is always a JSON string
1080
- input: typeof parsedToolCall.arguments === "string" ? parsedToolCall.arguments : JSON.stringify(parsedToolCall.arguments)
1081
- };
1082
- } catch (error) {
1083
- console.error(
1084
- "Failed to parse tool call JSON:",
1085
- error,
1086
- "JSON:",
1087
- toolCallJson
1088
- );
1089
- return null;
1090
- }
1091
- };
1092
- while ((match = toolCallRegex.exec(text)) !== null) {
1093
- const startIndex = match.index;
1094
- const endIndex = startIndex + match[0].length;
1095
- const toolCallJson = match[1];
1096
- if (startIndex > currentIndex) {
1097
- const textSegment = text.substring(currentIndex, startIndex);
1098
- if (textSegment.trim()) {
1099
- processedElements.push({ type: "text", text: textSegment });
1100
- }
1101
- }
1102
- if (toolCallJson) {
1103
- const toolCallObject = parseAndCreateToolCall(toolCallJson);
1104
- if (toolCallObject) {
1105
- processedElements.push(toolCallObject);
908
+ const result = await doGenerate();
909
+ if (result.content.length === 0) {
910
+ return result;
911
+ }
912
+ const newContent = result.content.flatMap((contentItem) => {
913
+ if (contentItem.type !== "text") {
914
+ return [contentItem];
915
+ }
916
+ return resolvedProtocol.parseGeneratedText({
917
+ text: contentItem.text,
918
+ tools: getFunctionTools(params),
919
+ options: extractOnErrorOption(params.providerOptions)
920
+ });
921
+ });
922
+ return {
923
+ ...result,
924
+ content: newContent
925
+ };
926
+ },
927
+ transformParams: async ({ params }) => {
928
+ var _a, _b, _c, _d, _e, _f;
929
+ const convertToolPrompt = (prompt) => {
930
+ const processedPrompt2 = prompt.map((message) => {
931
+ var _a2;
932
+ if (message.role === "assistant") {
933
+ const newContent = [];
934
+ for (const content of message.content) {
935
+ if (isToolCallContent(content)) {
936
+ newContent.push({
937
+ type: "text",
938
+ text: resolvedProtocol.formatToolCall(content)
939
+ });
940
+ } else if (content.type === "text") {
941
+ newContent.push(content);
942
+ } else if (content.type === "reasoning") {
943
+ newContent.push(content);
1106
944
  } else {
1107
- console.warn(
1108
- `Could not process tool call, keeping original text: ${match[0]}`
945
+ const options = extractOnErrorOption(params.providerOptions);
946
+ (_a2 = options == null ? void 0 : options.onError) == null ? void 0 : _a2.call(
947
+ options,
948
+ "tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
949
+ { content }
1109
950
  );
1110
- processedElements.push({ type: "text", text: match[0] });
951
+ newContent.push({
952
+ type: "text",
953
+ text: JSON.stringify(content)
954
+ });
1111
955
  }
1112
956
  }
1113
- currentIndex = endIndex;
957
+ const onlyText = newContent.every((c) => c.type === "text");
958
+ const condensedAssistant = onlyText ? [
959
+ {
960
+ type: "text",
961
+ text: newContent.map((c) => c.text).join("\n")
962
+ }
963
+ ] : newContent;
964
+ return { role: "assistant", content: condensedAssistant };
1114
965
  }
1115
- if (currentIndex < text.length) {
1116
- const remainingText = text.substring(currentIndex);
1117
- if (remainingText.trim()) {
1118
- processedElements.push({ type: "text", text: remainingText });
966
+ if (message.role === "tool") {
967
+ return {
968
+ role: "user",
969
+ // Map tool results to text response blocks, then condense into a single text block
970
+ content: [
971
+ {
972
+ type: "text",
973
+ text: message.content.map(
974
+ (toolResult) => isToolResultPart(toolResult) ? resolvedProtocol.formatToolResponse(toolResult) : resolvedProtocol.formatToolResponse(
975
+ toolResult
976
+ )
977
+ ).join("\n")
978
+ }
979
+ ]
980
+ };
981
+ }
982
+ return message;
983
+ });
984
+ for (let i = 0; i < processedPrompt2.length; i++) {
985
+ const msg = processedPrompt2[i];
986
+ if (Array.isArray(msg.content)) {
987
+ const allText = msg.content.every((c) => (c == null ? void 0 : c.type) === "text");
988
+ if (allText && msg.content.length > 1) {
989
+ processedPrompt2[i] = {
990
+ role: msg.role,
991
+ content: [
992
+ {
993
+ type: "text",
994
+ text: msg.content.map((c) => c.text).join("\n")
995
+ }
996
+ ]
997
+ };
1119
998
  }
1120
999
  }
1121
- return processedElements;
1122
1000
  }
1123
- );
1124
- return {
1125
- ...result,
1126
- content: newContent
1001
+ for (let i = processedPrompt2.length - 1; i > 0; i--) {
1002
+ const current = processedPrompt2[i];
1003
+ const prev = processedPrompt2[i - 1];
1004
+ if (current.role === "user" && prev.role === "user") {
1005
+ const prevContent = prev.content.map((c) => c.type === "text" ? c.text : "").join("\n");
1006
+ const currentContent = current.content.map((c) => c.type === "text" ? c.text : "").join("\n");
1007
+ processedPrompt2[i - 1] = {
1008
+ role: "user",
1009
+ content: [
1010
+ { type: "text", text: prevContent + "\n" + currentContent }
1011
+ ]
1012
+ };
1013
+ processedPrompt2.splice(i, 1);
1014
+ }
1015
+ }
1016
+ return processedPrompt2;
1127
1017
  };
1128
- },
1129
- transformParams: async ({ params }) => {
1130
- var _a, _b, _c, _d;
1131
- const toolSystemPrompt = convertToolPrompt({
1132
- paramsPrompt: params.prompt,
1133
- paramsTools: params.tools,
1134
- toolSystemPromptTemplate,
1135
- toolCallTag,
1136
- toolCallEndTag,
1137
- toolResponseTag,
1138
- toolResponseEndTag
1018
+ const functionTools = ((_a = params.tools) != null ? _a : []).filter(
1019
+ (t) => t.type === "function"
1020
+ );
1021
+ const systemPrompt = resolvedProtocol.formatTools({
1022
+ tools: functionTools,
1023
+ toolSystemPromptTemplate
1139
1024
  });
1025
+ const processedPrompt = convertToolPrompt(params.prompt);
1026
+ const finalPrompt = ((_b = processedPrompt[0]) == null ? void 0 : _b.role) === "system" ? [
1027
+ {
1028
+ role: "system",
1029
+ content: systemPrompt + "\n\n" + processedPrompt[0].content
1030
+ },
1031
+ ...processedPrompt.slice(1)
1032
+ ] : [
1033
+ {
1034
+ role: "system",
1035
+ content: systemPrompt
1036
+ },
1037
+ ...processedPrompt
1038
+ ];
1140
1039
  const baseReturnParams = {
1141
1040
  ...params,
1142
- prompt: toolSystemPrompt,
1143
- // Reset tools and toolChoice to default after prompt transformation
1041
+ prompt: finalPrompt,
1144
1042
  tools: [],
1145
- toolChoice: void 0
1043
+ toolChoice: void 0,
1044
+ providerOptions: {
1045
+ ...params.providerOptions || {},
1046
+ toolCallMiddleware: {
1047
+ ...params.providerOptions && typeof params.providerOptions === "object" && params.providerOptions.toolCallMiddleware || {},
1048
+ toolNames: functionTools.map((t) => t.name)
1049
+ }
1050
+ }
1146
1051
  };
1147
- if (((_a = params.toolChoice) == null ? void 0 : _a.type) === "none") {
1052
+ if (((_c = params.toolChoice) == null ? void 0 : _c.type) === "none") {
1148
1053
  throw new Error(
1149
1054
  "The 'none' toolChoice type is not supported by this middleware. Please use 'auto', 'required', or specify a tool name."
1150
1055
  );
1151
1056
  }
1152
- if (((_b = params.toolChoice) == null ? void 0 : _b.type) === "tool") {
1057
+ if (((_d = params.toolChoice) == null ? void 0 : _d.type) === "tool") {
1153
1058
  const selectedToolName = params.toolChoice.toolName;
1154
- const selectedTool = (_c = params.tools) == null ? void 0 : _c.find(
1059
+ const selectedTool = (_e = params.tools) == null ? void 0 : _e.find(
1155
1060
  (tool) => tool.type === "function" ? tool.name === selectedToolName : tool.id === selectedToolName
1156
1061
  );
1157
1062
  if (!selectedTool) {
@@ -1182,13 +1087,15 @@ function createToolMiddleware({
1182
1087
  description: selectedTool.type === "function" && typeof selectedTool.description === "string" ? selectedTool.description : void 0
1183
1088
  },
1184
1089
  providerOptions: {
1090
+ ...baseReturnParams.providerOptions || {},
1185
1091
  toolCallMiddleware: {
1092
+ ...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
1186
1093
  toolChoice: params.toolChoice
1187
1094
  }
1188
1095
  }
1189
1096
  };
1190
1097
  }
1191
- if (((_d = params.toolChoice) == null ? void 0 : _d.type) === "required") {
1098
+ if (((_f = params.toolChoice) == null ? void 0 : _f.type) === "required") {
1192
1099
  if (!params.tools || params.tools.length === 0) {
1193
1100
  throw new Error(
1194
1101
  "Tool choice type 'required' is set, but no tools are provided in params.tools."
@@ -1198,10 +1105,14 @@ function createToolMiddleware({
1198
1105
  ...baseReturnParams,
1199
1106
  responseFormat: {
1200
1107
  type: "json",
1201
- schema: createDynamicIfThenElseSchema(params.tools)
1108
+ schema: createDynamicIfThenElseSchema(
1109
+ params.tools.filter((t) => t.type === "function")
1110
+ )
1202
1111
  },
1203
1112
  providerOptions: {
1113
+ ...baseReturnParams.providerOptions || {},
1204
1114
  toolCallMiddleware: {
1115
+ ...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
1205
1116
  toolChoice: { type: "required" }
1206
1117
  }
1207
1118
  }
@@ -1212,8 +1123,476 @@ function createToolMiddleware({
1212
1123
  };
1213
1124
  }
1214
1125
 
1126
+ // src/protocols/json-mix-protocol.ts
1127
+ var import_provider_utils3 = require("@ai-sdk/provider-utils");
1128
+ var jsonMixProtocol = ({
1129
+ toolCallStart = "<tool_call>",
1130
+ toolCallEnd = "</tool_call>",
1131
+ toolResponseStart = "<tool_response>",
1132
+ toolResponseEnd = "</tool_response>"
1133
+ } = {}) => ({
1134
+ formatTools({ tools, toolSystemPromptTemplate }) {
1135
+ const toolsForPrompt = (tools || []).filter((tool) => tool.type === "function").map((tool) => ({
1136
+ name: tool.name,
1137
+ description: tool.type === "function" && typeof tool.description === "string" ? tool.description : void 0,
1138
+ parameters: tool.inputSchema
1139
+ }));
1140
+ return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
1141
+ },
1142
+ formatToolCall(toolCall) {
1143
+ let args = {};
1144
+ try {
1145
+ args = JSON.parse(toolCall.input);
1146
+ } catch (e) {
1147
+ args = toolCall.input;
1148
+ }
1149
+ return `${toolCallStart}${JSON.stringify({
1150
+ name: toolCall.toolName,
1151
+ arguments: args
1152
+ })}${toolCallEnd}`;
1153
+ },
1154
+ formatToolResponse(toolResult) {
1155
+ return `${toolResponseStart}${JSON.stringify({
1156
+ toolName: toolResult.toolName,
1157
+ result: toolResult.output
1158
+ })}${toolResponseEnd}`;
1159
+ },
1160
+ parseGeneratedText({ text, options }) {
1161
+ var _a;
1162
+ const startEsc = escapeRegExp(toolCallStart);
1163
+ const endEsc = escapeRegExp(toolCallEnd);
1164
+ const toolCallRegex = new RegExp(
1165
+ `${startEsc}([\0-\uFFFF]*?)${endEsc}`,
1166
+ "gs"
1167
+ );
1168
+ const processedElements = [];
1169
+ let currentIndex = 0;
1170
+ let match;
1171
+ while ((match = toolCallRegex.exec(text)) !== null) {
1172
+ const startIndex = match.index;
1173
+ const toolCallJson = match[1];
1174
+ if (startIndex > currentIndex) {
1175
+ const textSegment = text.substring(currentIndex, startIndex);
1176
+ if (textSegment.trim()) {
1177
+ processedElements.push({ type: "text", text: textSegment });
1178
+ }
1179
+ }
1180
+ if (toolCallJson) {
1181
+ try {
1182
+ const parsedToolCall = relaxed_json_exports.parse(toolCallJson);
1183
+ processedElements.push({
1184
+ type: "tool-call",
1185
+ toolCallId: (0, import_provider_utils3.generateId)(),
1186
+ toolName: parsedToolCall.name,
1187
+ input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
1188
+ });
1189
+ } catch (error) {
1190
+ if (options == null ? void 0 : options.onError) {
1191
+ options.onError(
1192
+ "Could not process JSON tool call, keeping original text.",
1193
+ { toolCall: match[0], error }
1194
+ );
1195
+ }
1196
+ processedElements.push({ type: "text", text: match[0] });
1197
+ }
1198
+ }
1199
+ currentIndex = startIndex + match[0].length;
1200
+ }
1201
+ if (currentIndex < text.length) {
1202
+ const remainingText = text.substring(currentIndex);
1203
+ if (remainingText.trim()) {
1204
+ processedElements.push({ type: "text", text: remainingText });
1205
+ }
1206
+ }
1207
+ return processedElements;
1208
+ },
1209
+ createStreamParser({ tools: _tools, options } = { tools: [] }) {
1210
+ let isInsideToolCall = false;
1211
+ let buffer = "";
1212
+ let currentToolCallJson = "";
1213
+ let currentTextId = null;
1214
+ let hasEmittedTextStart = false;
1215
+ return new TransformStream({
1216
+ transform(chunk, controller) {
1217
+ var _a;
1218
+ if (chunk.type === "finish") {
1219
+ if (isInsideToolCall && buffer.length > 0) {
1220
+ if (!currentTextId) {
1221
+ currentTextId = (0, import_provider_utils3.generateId)();
1222
+ controller.enqueue({ type: "text-start", id: currentTextId });
1223
+ hasEmittedTextStart = true;
1224
+ }
1225
+ controller.enqueue({
1226
+ type: "text-delta",
1227
+ id: currentTextId,
1228
+ delta: `${toolCallStart}${buffer}`
1229
+ });
1230
+ buffer = "";
1231
+ } else if (!isInsideToolCall && buffer.length > 0) {
1232
+ if (!currentTextId) {
1233
+ currentTextId = (0, import_provider_utils3.generateId)();
1234
+ controller.enqueue({ type: "text-start", id: currentTextId });
1235
+ hasEmittedTextStart = true;
1236
+ }
1237
+ controller.enqueue({
1238
+ type: "text-delta",
1239
+ id: currentTextId,
1240
+ delta: buffer
1241
+ });
1242
+ buffer = "";
1243
+ }
1244
+ if (currentTextId && hasEmittedTextStart) {
1245
+ controller.enqueue({ type: "text-end", id: currentTextId });
1246
+ currentTextId = null;
1247
+ hasEmittedTextStart = false;
1248
+ }
1249
+ if (currentToolCallJson) {
1250
+ const errorId = (0, import_provider_utils3.generateId)();
1251
+ controller.enqueue({ type: "text-start", id: errorId });
1252
+ controller.enqueue({
1253
+ type: "text-delta",
1254
+ id: errorId,
1255
+ delta: `${toolCallStart}${currentToolCallJson}`
1256
+ });
1257
+ controller.enqueue({ type: "text-end", id: errorId });
1258
+ currentToolCallJson = "";
1259
+ }
1260
+ controller.enqueue(chunk);
1261
+ return;
1262
+ }
1263
+ if (chunk.type !== "text-delta") {
1264
+ controller.enqueue(chunk);
1265
+ return;
1266
+ }
1267
+ buffer += chunk.delta;
1268
+ const publish = (text) => {
1269
+ if (isInsideToolCall) {
1270
+ if (currentTextId && hasEmittedTextStart) {
1271
+ controller.enqueue({ type: "text-end", id: currentTextId });
1272
+ currentTextId = null;
1273
+ hasEmittedTextStart = false;
1274
+ }
1275
+ currentToolCallJson += text;
1276
+ } else if (text.length > 0) {
1277
+ if (!currentTextId) {
1278
+ currentTextId = (0, import_provider_utils3.generateId)();
1279
+ controller.enqueue({ type: "text-start", id: currentTextId });
1280
+ hasEmittedTextStart = true;
1281
+ }
1282
+ controller.enqueue({
1283
+ type: "text-delta",
1284
+ id: currentTextId,
1285
+ delta: text
1286
+ });
1287
+ }
1288
+ };
1289
+ let startIndex;
1290
+ while ((startIndex = getPotentialStartIndex(
1291
+ buffer,
1292
+ isInsideToolCall ? toolCallEnd : toolCallStart
1293
+ )) != null) {
1294
+ const tag = isInsideToolCall ? toolCallEnd : toolCallStart;
1295
+ if (startIndex + tag.length > buffer.length) {
1296
+ break;
1297
+ }
1298
+ publish(buffer.slice(0, startIndex));
1299
+ buffer = buffer.slice(startIndex + tag.length);
1300
+ if (!isInsideToolCall) {
1301
+ currentToolCallJson = "";
1302
+ isInsideToolCall = true;
1303
+ } else {
1304
+ try {
1305
+ const parsedToolCall = relaxed_json_exports.parse(currentToolCallJson);
1306
+ if (currentTextId && hasEmittedTextStart) {
1307
+ controller.enqueue({ type: "text-end", id: currentTextId });
1308
+ currentTextId = null;
1309
+ hasEmittedTextStart = false;
1310
+ }
1311
+ controller.enqueue({
1312
+ type: "tool-call",
1313
+ toolCallId: (0, import_provider_utils3.generateId)(),
1314
+ toolName: parsedToolCall.name,
1315
+ input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
1316
+ });
1317
+ } catch (e) {
1318
+ const errorId = (0, import_provider_utils3.generateId)();
1319
+ controller.enqueue({ type: "text-start", id: errorId });
1320
+ controller.enqueue({
1321
+ type: "text-delta",
1322
+ id: errorId,
1323
+ delta: `${toolCallStart}${currentToolCallJson}${toolCallEnd}`
1324
+ });
1325
+ controller.enqueue({ type: "text-end", id: errorId });
1326
+ if (options == null ? void 0 : options.onError) {
1327
+ options.onError(
1328
+ "Could not process streaming JSON tool call; emitting original text.",
1329
+ {
1330
+ toolCall: `${toolCallStart}${currentToolCallJson}${toolCallEnd}`
1331
+ }
1332
+ );
1333
+ }
1334
+ }
1335
+ currentToolCallJson = "";
1336
+ isInsideToolCall = false;
1337
+ }
1338
+ }
1339
+ if (!isInsideToolCall) {
1340
+ const potentialIndex = getPotentialStartIndex(buffer, toolCallStart);
1341
+ if (potentialIndex != null && potentialIndex + toolCallStart.length > buffer.length) {
1342
+ publish(buffer.slice(0, potentialIndex));
1343
+ buffer = buffer.slice(potentialIndex);
1344
+ } else {
1345
+ publish(buffer);
1346
+ buffer = "";
1347
+ }
1348
+ }
1349
+ }
1350
+ });
1351
+ }
1352
+ });
1353
+
1354
+ // src/protocols/xml-protocol.ts
1355
+ var import_provider_utils4 = require("@ai-sdk/provider-utils");
1356
+ var import_fast_xml_parser = require("fast-xml-parser");
1357
+ var xmlProtocol = () => ({
1358
+ formatTools({ tools, toolSystemPromptTemplate }) {
1359
+ const toolsForPrompt = (tools || []).map((tool) => ({
1360
+ name: tool.name,
1361
+ description: tool.description,
1362
+ parameters: tool.inputSchema
1363
+ }));
1364
+ return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
1365
+ },
1366
+ formatToolCall(toolCall) {
1367
+ const builder = new import_fast_xml_parser.XMLBuilder({ format: true, suppressEmptyNode: true });
1368
+ let args = {};
1369
+ const inputValue = hasInputProperty(toolCall) ? toolCall.input : void 0;
1370
+ if (typeof inputValue === "string") {
1371
+ try {
1372
+ args = JSON.parse(inputValue);
1373
+ } catch (e) {
1374
+ args = inputValue;
1375
+ }
1376
+ } else {
1377
+ args = inputValue;
1378
+ }
1379
+ const xmlContent = builder.build({
1380
+ [toolCall.toolName]: args
1381
+ });
1382
+ return xmlContent;
1383
+ },
1384
+ formatToolResponse(toolResult) {
1385
+ const builder = new import_fast_xml_parser.XMLBuilder({ format: true });
1386
+ const xmlContent = builder.build({
1387
+ tool_response: {
1388
+ tool_name: toolResult.toolName,
1389
+ result: toolResult.output
1390
+ }
1391
+ });
1392
+ return xmlContent;
1393
+ },
1394
+ parseGeneratedText({ text, tools, options }) {
1395
+ var _a, _b;
1396
+ const toolNames = tools.map((t) => t.name).filter((name) => name != null);
1397
+ if (toolNames.length === 0) {
1398
+ return [{ type: "text", text }];
1399
+ }
1400
+ const toolNamesPattern = toolNames.map((n) => escapeRegExp(n)).join("|");
1401
+ const toolCallRegex = new RegExp(
1402
+ String.raw`<(${toolNamesPattern})>([\s\S]*?)<\/\1>`,
1403
+ "g"
1404
+ );
1405
+ const processedElements = [];
1406
+ let currentIndex = 0;
1407
+ let match;
1408
+ while ((match = toolCallRegex.exec(text)) !== null) {
1409
+ const startIndex = match.index;
1410
+ const toolName = match[1];
1411
+ const toolContent = match[2].trim();
1412
+ if (startIndex > currentIndex) {
1413
+ const textSegment = text.substring(currentIndex, startIndex);
1414
+ if (textSegment.trim()) {
1415
+ processedElements.push({ type: "text", text: textSegment });
1416
+ }
1417
+ }
1418
+ try {
1419
+ const parser = new import_fast_xml_parser.XMLParser({
1420
+ ignoreAttributes: false,
1421
+ parseTagValue: false,
1422
+ ignoreDeclaration: true,
1423
+ textNodeName: "#text"
1424
+ });
1425
+ const parsedArgs = ((_a = parser.parse(`<root>${toolContent}</root>`)) == null ? void 0 : _a.root) || {};
1426
+ const args = {};
1427
+ for (const k of Object.keys(parsedArgs || {})) {
1428
+ const v = parsedArgs[k];
1429
+ let val = v;
1430
+ if (v && typeof v === "object" && Object.prototype.hasOwnProperty.call(v, "#text")) {
1431
+ val = v == null ? void 0 : v["#text"];
1432
+ }
1433
+ args[k] = typeof val === "string" ? val.trim() : val;
1434
+ }
1435
+ processedElements.push({
1436
+ type: "tool-call",
1437
+ toolCallId: (0, import_provider_utils4.generateId)(),
1438
+ toolName,
1439
+ input: JSON.stringify(args)
1440
+ });
1441
+ } catch (error) {
1442
+ const message = `Could not process XML tool call, keeping original text: ${match[0]}`;
1443
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, message, { toolCall: match[0], toolName, error });
1444
+ processedElements.push({ type: "text", text: match[0] });
1445
+ }
1446
+ currentIndex = startIndex + match[0].length;
1447
+ }
1448
+ if (currentIndex < text.length) {
1449
+ const remainingText = text.substring(currentIndex);
1450
+ if (remainingText.trim()) {
1451
+ processedElements.push({ type: "text", text: remainingText });
1452
+ }
1453
+ }
1454
+ return processedElements;
1455
+ },
1456
+ createStreamParser({ tools, options }) {
1457
+ const toolNames = tools.map((t) => t.name).filter((name) => name != null);
1458
+ let buffer = "";
1459
+ let currentToolCall = null;
1460
+ let currentTextId = null;
1461
+ const flushText = (controller, text) => {
1462
+ const content = text != null ? text : buffer;
1463
+ if (content) {
1464
+ if (!currentTextId) {
1465
+ currentTextId = (0, import_provider_utils4.generateId)();
1466
+ controller.enqueue({ type: "text-start", id: currentTextId });
1467
+ }
1468
+ controller.enqueue({
1469
+ type: "text-delta",
1470
+ id: currentTextId,
1471
+ delta: content
1472
+ });
1473
+ if (text === void 0) {
1474
+ buffer = "";
1475
+ }
1476
+ }
1477
+ if (currentTextId && !text) {
1478
+ controller.enqueue({ type: "text-end", id: currentTextId });
1479
+ currentTextId = null;
1480
+ }
1481
+ };
1482
+ return new TransformStream({
1483
+ transform(chunk, controller) {
1484
+ var _a;
1485
+ if (chunk.type !== "text-delta") {
1486
+ if (buffer) flushText(controller);
1487
+ controller.enqueue(chunk);
1488
+ return;
1489
+ }
1490
+ buffer += chunk.delta;
1491
+ while (true) {
1492
+ if (currentToolCall) {
1493
+ const endTag = `</${currentToolCall.name}>`;
1494
+ const endTagIndex = buffer.indexOf(endTag);
1495
+ if (endTagIndex !== -1) {
1496
+ const toolContent = buffer.substring(0, endTagIndex);
1497
+ buffer = buffer.substring(endTagIndex + endTag.length);
1498
+ try {
1499
+ const parser = new import_fast_xml_parser.XMLParser({
1500
+ ignoreAttributes: false,
1501
+ parseTagValue: false,
1502
+ ignoreDeclaration: true,
1503
+ textNodeName: "#text"
1504
+ });
1505
+ const parsedArgs = ((_a = parser.parse(`<root>${toolContent}</root>`)) == null ? void 0 : _a.root) || {};
1506
+ const args = {};
1507
+ for (const k of Object.keys(parsedArgs || {})) {
1508
+ const v = parsedArgs[k];
1509
+ let val = v;
1510
+ if (v && typeof v === "object" && Object.prototype.hasOwnProperty.call(v, "#text")) {
1511
+ val = v == null ? void 0 : v["#text"];
1512
+ }
1513
+ args[k] = typeof val === "string" ? val.trim() : val;
1514
+ }
1515
+ flushText(controller);
1516
+ controller.enqueue({
1517
+ type: "tool-call",
1518
+ toolCallId: (0, import_provider_utils4.generateId)(),
1519
+ toolName: currentToolCall.name,
1520
+ input: JSON.stringify(args)
1521
+ });
1522
+ } catch (e) {
1523
+ const originalCallText = `<${currentToolCall.name}>${toolContent}${endTag}`;
1524
+ if (options == null ? void 0 : options.onError) {
1525
+ options.onError(
1526
+ "Could not process streaming XML tool call; emitting original text.",
1527
+ {
1528
+ toolCall: originalCallText,
1529
+ toolName: currentToolCall.name
1530
+ }
1531
+ );
1532
+ }
1533
+ flushText(controller, originalCallText);
1534
+ }
1535
+ currentToolCall = null;
1536
+ } else {
1537
+ break;
1538
+ }
1539
+ } else {
1540
+ let earliestStartTagIndex = -1;
1541
+ let earliestToolName = "";
1542
+ if (toolNames.length > 0) {
1543
+ for (const name of toolNames) {
1544
+ const startTag = `<${name}>`;
1545
+ const index = buffer.indexOf(startTag);
1546
+ if (index !== -1 && (earliestStartTagIndex === -1 || index < earliestStartTagIndex)) {
1547
+ earliestStartTagIndex = index;
1548
+ earliestToolName = name;
1549
+ }
1550
+ }
1551
+ }
1552
+ if (earliestStartTagIndex !== -1) {
1553
+ const textBeforeTag = buffer.substring(0, earliestStartTagIndex);
1554
+ flushText(controller, textBeforeTag);
1555
+ const startTag = `<${earliestToolName}>`;
1556
+ buffer = buffer.substring(
1557
+ earliestStartTagIndex + startTag.length
1558
+ );
1559
+ currentToolCall = { name: earliestToolName, content: "" };
1560
+ } else {
1561
+ break;
1562
+ }
1563
+ }
1564
+ }
1565
+ },
1566
+ flush(controller) {
1567
+ if (currentToolCall) {
1568
+ const unfinishedCall = `<${currentToolCall.name}>${buffer}`;
1569
+ flushText(controller, unfinishedCall);
1570
+ } else if (buffer) {
1571
+ flushText(controller);
1572
+ }
1573
+ if (currentTextId) {
1574
+ controller.enqueue({ type: "text-end", id: currentTextId });
1575
+ }
1576
+ }
1577
+ });
1578
+ }
1579
+ });
1580
+
1581
+ // src/protocols/dummy-protocol.ts
1582
+ var import_provider_utils5 = require("@ai-sdk/provider-utils");
1583
+
1215
1584
  // src/index.ts
1216
1585
  var gemmaToolMiddleware = createToolMiddleware({
1586
+ protocol: jsonMixProtocol(
1587
+ // Customize the tool call delimiters to use markdown code fences
1588
+ {
1589
+ toolCallStart: "```tool_call\n",
1590
+ toolCallEnd: "\n``",
1591
+ // two backticks are more common in gemma output @
1592
+ toolResponseStart: "```tool_response\n",
1593
+ toolResponseEnd: "\n```"
1594
+ }
1595
+ ),
1217
1596
  toolSystemPromptTemplate(tools) {
1218
1597
  return `You have access to functions. If you decide to invoke any of the function(s),
1219
1598
  you MUST put it in the format of markdown code fence block with the language name of tool_call , e.g.
@@ -1222,35 +1601,47 @@ you MUST put it in the format of markdown code fence block with the language nam
1222
1601
  \`\`\`
1223
1602
  You SHOULD NOT include any other text in the response if you call a function
1224
1603
  ${tools}`;
1225
- },
1226
- toolCallTag: "```tool_call\n",
1227
- toolCallEndTag: "\n``",
1228
- // two backticks are more common in gemma output
1229
- toolResponseTag: "```tool_response\n",
1230
- toolResponseEndTag: "\n```"
1604
+ }
1231
1605
  });
1232
1606
  var hermesToolMiddleware = createToolMiddleware({
1607
+ protocol: jsonMixProtocol,
1233
1608
  toolSystemPromptTemplate(tools) {
1234
1609
  return `You are a function calling AI model.
1235
1610
  You are provided with function signatures within <tools></tools> XML tags.
1236
1611
  You may call one or more functions to assist with the user query.
1237
1612
  Don't make assumptions about what values to plug into functions.
1238
1613
  Here are the available tools: <tools>${tools}</tools>
1239
- Use the following pydantic model json schema for each tool call you will make: {'title': 'FunctionCall', 'type': 'object', 'properties': {'arguments': {'title': 'Arguments', 'type': 'object'}, 'name': {'title': 'Name', 'type': 'string'}}, 'required': ['arguments', 'name']}
1614
+ Use the following pydantic model json schema for each tool call you will make: {"title": "FunctionCall", "type": "object", "properties": {"arguments": {"title": "Arguments", "type": "object"}, "name": {"title": "Name", "type": "string"}}, "required": ["arguments", "name"]}
1240
1615
  For each function call return a json object with function name and arguments within <tool_call></tool_call> XML tags as follows:
1241
1616
  <tool_call>
1242
- {'arguments': <args-dict>, 'name': <function-name>}
1617
+ {"name": "<function-name>", "arguments": <args-dict>}
1243
1618
  </tool_call>`;
1244
- },
1245
- toolCallTag: "<tool_call>",
1246
- toolCallEndTag: "</tool_call>",
1247
- toolResponseTag: "<tool_response>",
1248
- toolResponseEndTag: "</tool_response>"
1619
+ }
1620
+ });
1621
+ var xmlToolMiddleware = createToolMiddleware({
1622
+ protocol: xmlProtocol,
1623
+ toolSystemPromptTemplate(tools) {
1624
+ return `You are KorinAI, a function-calling AI model.
1625
+ You are provided with function signatures within <tools></tools> XML tags.
1626
+ You may call one or more functions to assist with the user query.
1627
+ Don't make assumptions about what values to plug into functions.
1628
+ Here are the available tools: <tools>${tools}</tools>
1629
+ For each function call return a tool call in an XML tag that matches the tool's name, and nothing else.
1630
+ Example KorinAI-style call (text form):
1631
+ <get_weather>
1632
+ <location>
1633
+ San Fransisco
1634
+ </location>
1635
+ </get_weather>`;
1636
+ }
1249
1637
  });
1250
1638
  // Annotate the CommonJS export names for ESM import in node:
1251
1639
  0 && (module.exports = {
1252
1640
  createToolMiddleware,
1253
1641
  gemmaToolMiddleware,
1254
- hermesToolMiddleware
1642
+ hermesToolMiddleware,
1643
+ jsonMixProtocol,
1644
+ xmlProtocol,
1645
+ xmlToolMiddleware
1255
1646
  });
1256
1647
  //# sourceMappingURL=index.cjs.map