@ai-sdk-tool/parser 2.0.15 → 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 +751 -360
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -7
- package/dist/index.d.ts +37 -7
- package/dist/index.js +747 -359
- package/dist/index.js.map +1 -1
- package/package.json +10 -4
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/
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
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
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
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
|
-
|
|
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
|
|
1006
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1034
|
-
if (result.content.length === 0) {
|
|
1035
|
-
return result;
|
|
1036
|
-
}
|
|
875
|
+
var _a, _b;
|
|
1037
876
|
if (isToolChoiceActive(params)) {
|
|
1038
|
-
const
|
|
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
|
-
...
|
|
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:
|
|
1047
|
-
input: JSON.stringify(
|
|
902
|
+
toolName: parsed.name || "unknown",
|
|
903
|
+
input: JSON.stringify(parsed.arguments || {})
|
|
1048
904
|
}
|
|
1049
905
|
]
|
|
1050
906
|
};
|
|
1051
907
|
}
|
|
1052
|
-
const
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
const newContent = result.content.flatMap(
|
|
1057
|
-
(contentItem)
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
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
|
-
|
|
1108
|
-
|
|
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
|
-
|
|
951
|
+
newContent.push({
|
|
952
|
+
type: "text",
|
|
953
|
+
text: JSON.stringify(content)
|
|
954
|
+
});
|
|
1111
955
|
}
|
|
1112
956
|
}
|
|
1113
|
-
|
|
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 (
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
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
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
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
|
-
|
|
1130
|
-
|
|
1131
|
-
const
|
|
1132
|
-
|
|
1133
|
-
|
|
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:
|
|
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 (((
|
|
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 (((
|
|
1057
|
+
if (((_d = params.toolChoice) == null ? void 0 : _d.type) === "tool") {
|
|
1153
1058
|
const selectedToolName = params.toolChoice.toolName;
|
|
1154
|
-
const selectedTool = (
|
|
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 (((
|
|
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(
|
|
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: {
|
|
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
|
-
{
|
|
1617
|
+
{"name": "<function-name>", "arguments": <args-dict>}
|
|
1243
1618
|
</tool_call>`;
|
|
1244
|
-
}
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
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
|