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