@ai-sdk-tool/parser 2.0.16 → 2.1.1
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 +1255 -415
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +126 -7
- package/dist/index.d.ts +126 -7
- package/dist/index.js +1247 -414
- package/dist/index.js.map +1 -1
- package/package.json +11 -6
package/dist/index.cjs
CHANGED
|
@@ -20,99 +20,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
coerceBySchema: () => coerceBySchema,
|
|
23
24
|
createToolMiddleware: () => createToolMiddleware,
|
|
25
|
+
fixToolCallWithSchema: () => fixToolCallWithSchema,
|
|
24
26
|
gemmaToolMiddleware: () => gemmaToolMiddleware,
|
|
25
|
-
|
|
27
|
+
getSchemaType: () => getSchemaType,
|
|
28
|
+
hermesToolMiddleware: () => hermesToolMiddleware,
|
|
29
|
+
jsonMixProtocol: () => jsonMixProtocol,
|
|
30
|
+
unwrapJsonSchema: () => unwrapJsonSchema,
|
|
31
|
+
xmlProtocol: () => xmlProtocol,
|
|
32
|
+
xmlToolMiddleware: () => xmlToolMiddleware
|
|
26
33
|
});
|
|
27
34
|
module.exports = __toCommonJS(index_exports);
|
|
28
35
|
|
|
29
|
-
// src/
|
|
30
|
-
var
|
|
31
|
-
|
|
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
|
-
}
|
|
36
|
+
// src/stream-handler.ts
|
|
37
|
+
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
116
38
|
|
|
117
39
|
// src/utils/dynamic-tool-schema.ts
|
|
118
40
|
function createDynamicIfThenElseSchema(tools) {
|
|
@@ -522,7 +444,6 @@ function appendPair(state, obj, key, value) {
|
|
|
522
444
|
}
|
|
523
445
|
function parsePair(tokens, state, obj) {
|
|
524
446
|
let token = skipPunctuation(tokens, state, [":", "string", "number", "atom"]);
|
|
525
|
-
let key;
|
|
526
447
|
let value;
|
|
527
448
|
if (token.type !== "string") {
|
|
528
449
|
raiseUnexpected(state, token, "string key");
|
|
@@ -572,7 +493,7 @@ function parsePair(tokens, state, obj) {
|
|
|
572
493
|
}
|
|
573
494
|
}
|
|
574
495
|
checkDuplicates(state, obj, token);
|
|
575
|
-
key = String(token.value);
|
|
496
|
+
const key = String(token.value);
|
|
576
497
|
skipColon(tokens, state);
|
|
577
498
|
value = parseAny(tokens, state);
|
|
578
499
|
appendPair(state, obj, key, value);
|
|
@@ -743,7 +664,10 @@ function parse(text, optsOrReviver) {
|
|
|
743
664
|
if (!options.relaxed && !options.warnings && !options.tolerant) {
|
|
744
665
|
if (!options.duplicate) {
|
|
745
666
|
} else {
|
|
746
|
-
return JSON.parse(
|
|
667
|
+
return JSON.parse(
|
|
668
|
+
text,
|
|
669
|
+
options.reviver
|
|
670
|
+
);
|
|
747
671
|
}
|
|
748
672
|
}
|
|
749
673
|
const lexerToUse = options.relaxed ? lexer : strictLexer;
|
|
@@ -763,7 +687,7 @@ function parse(text, optsOrReviver) {
|
|
|
763
687
|
};
|
|
764
688
|
return parseAny(tokens, state, true);
|
|
765
689
|
} else {
|
|
766
|
-
|
|
690
|
+
tokens.reduce((str, token) => {
|
|
767
691
|
return str + token.match;
|
|
768
692
|
}, "");
|
|
769
693
|
if (!options.relaxed && !options.warnings && !options.tolerant && options.duplicate) {
|
|
@@ -787,8 +711,11 @@ function parse(text, optsOrReviver) {
|
|
|
787
711
|
} else {
|
|
788
712
|
tokens = lexer(text);
|
|
789
713
|
tokens = stripTrailingComma(tokens);
|
|
790
|
-
const
|
|
791
|
-
return JSON.parse(
|
|
714
|
+
const newtext = tokens.reduce((str, token) => str + token.match, "");
|
|
715
|
+
return JSON.parse(
|
|
716
|
+
newtext,
|
|
717
|
+
options.reviver
|
|
718
|
+
);
|
|
792
719
|
}
|
|
793
720
|
}
|
|
794
721
|
}
|
|
@@ -816,161 +743,321 @@ function stringify(obj) {
|
|
|
816
743
|
return "null";
|
|
817
744
|
}
|
|
818
745
|
|
|
819
|
-
// src/
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
746
|
+
// src/utils/regex.ts
|
|
747
|
+
function escapeRegExp(literal) {
|
|
748
|
+
return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// src/utils/type-guards.ts
|
|
752
|
+
function isToolCallContent(content) {
|
|
753
|
+
return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
|
|
754
|
+
(typeof content.input === "string" || typeof content.input === "object");
|
|
755
|
+
}
|
|
756
|
+
function isToolResultPart(content) {
|
|
757
|
+
const c = content;
|
|
758
|
+
return !!c && c.type === "tool-result" && typeof c.toolName === "string" && typeof c.toolCallId === "string" && "output" in c;
|
|
759
|
+
}
|
|
760
|
+
function hasInputProperty(obj) {
|
|
761
|
+
return typeof obj === "object" && obj !== null && "input" in obj;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// src/utils/tools.ts
|
|
765
|
+
function isToolChoiceActive(params) {
|
|
766
|
+
var _a, _b, _c;
|
|
767
|
+
const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
|
|
768
|
+
return !!(typeof params.providerOptions === "object" && params.providerOptions !== null && typeof ((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) === "object" && toolChoice && typeof toolChoice === "object" && (toolChoice.type === "tool" || toolChoice.type === "required"));
|
|
769
|
+
}
|
|
770
|
+
function getFunctionTools(params) {
|
|
771
|
+
var _a, _b;
|
|
772
|
+
const functionTools = ((_a = params.tools) != null ? _a : []).filter(
|
|
773
|
+
(t) => t.type === "function"
|
|
774
|
+
);
|
|
775
|
+
if (functionTools.length > 0) return functionTools;
|
|
776
|
+
const rawToolNames = params.providerOptions && typeof params.providerOptions === "object" && ((_b = params.providerOptions.toolCallMiddleware) == null ? void 0 : _b.toolNames) || [];
|
|
777
|
+
const toStringArray = (val) => Array.isArray(val) ? val.filter(
|
|
778
|
+
(item) => typeof item === "string"
|
|
779
|
+
) : [];
|
|
780
|
+
const toolNames = toStringArray(rawToolNames);
|
|
781
|
+
if (toolNames.length > 0) {
|
|
782
|
+
return toolNames.map((name) => ({
|
|
783
|
+
type: "function",
|
|
784
|
+
name,
|
|
785
|
+
description: "",
|
|
786
|
+
inputSchema: { type: "object" }
|
|
787
|
+
}));
|
|
788
|
+
}
|
|
789
|
+
return [];
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// src/utils/on-error.ts
|
|
793
|
+
function extractOnErrorOption(providerOptions) {
|
|
826
794
|
var _a;
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
const
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
795
|
+
if (providerOptions && typeof providerOptions === "object") {
|
|
796
|
+
const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
|
|
797
|
+
return onError ? { onError } : void 0;
|
|
798
|
+
}
|
|
799
|
+
return void 0;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// src/utils/coercion.ts
|
|
803
|
+
function unwrapJsonSchema(schema) {
|
|
804
|
+
if (!schema || typeof schema !== "object") return schema;
|
|
805
|
+
const s = schema;
|
|
806
|
+
if (s.jsonSchema && typeof s.jsonSchema === "object") {
|
|
807
|
+
return unwrapJsonSchema(s.jsonSchema);
|
|
808
|
+
}
|
|
809
|
+
return schema;
|
|
810
|
+
}
|
|
811
|
+
function getSchemaType(schema) {
|
|
812
|
+
const unwrapped = unwrapJsonSchema(schema);
|
|
813
|
+
if (!unwrapped || typeof unwrapped !== "object") return void 0;
|
|
814
|
+
const t = unwrapped.type;
|
|
815
|
+
if (typeof t === "string") return t;
|
|
816
|
+
if (Array.isArray(t)) {
|
|
817
|
+
const preferred = [
|
|
818
|
+
"object",
|
|
819
|
+
"array",
|
|
820
|
+
"boolean",
|
|
821
|
+
"number",
|
|
822
|
+
"integer",
|
|
823
|
+
"string"
|
|
824
|
+
];
|
|
825
|
+
for (const p of preferred) if (t.includes(p)) return p;
|
|
826
|
+
}
|
|
827
|
+
const s = unwrapped;
|
|
828
|
+
if (s && typeof s === "object" && (s.properties || s.additionalProperties)) {
|
|
829
|
+
return "object";
|
|
830
|
+
}
|
|
831
|
+
if (s && typeof s === "object" && (s.items || s.prefixItems)) {
|
|
832
|
+
return "array";
|
|
833
|
+
}
|
|
834
|
+
return void 0;
|
|
835
|
+
}
|
|
836
|
+
function coerceBySchema(value, schema) {
|
|
837
|
+
const unwrapped = unwrapJsonSchema(schema);
|
|
838
|
+
if (!unwrapped || typeof unwrapped !== "object") {
|
|
839
|
+
if (typeof value === "string") {
|
|
840
|
+
const s = value.trim();
|
|
841
|
+
const lower = s.toLowerCase();
|
|
842
|
+
if (lower === "true") return true;
|
|
843
|
+
if (lower === "false") return false;
|
|
844
|
+
if (/^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(s)) {
|
|
845
|
+
const num = Number(s);
|
|
846
|
+
if (Number.isFinite(num)) return num;
|
|
847
|
+
}
|
|
848
|
+
if (s.startsWith("{") && s.endsWith("}") || s.startsWith("[") && s.endsWith("]")) {
|
|
849
|
+
try {
|
|
850
|
+
const parsed = JSON.parse(s);
|
|
851
|
+
return coerceBySchema(parsed, void 0);
|
|
852
|
+
} catch (e) {
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
return value;
|
|
857
|
+
}
|
|
858
|
+
const schemaType = getSchemaType(unwrapped);
|
|
859
|
+
if (typeof value === "string") {
|
|
860
|
+
const s = value.trim();
|
|
861
|
+
if (schemaType === "object") {
|
|
862
|
+
try {
|
|
863
|
+
let normalized = s.replace(/'/g, '"');
|
|
864
|
+
normalized = normalized.replace(/^\{\s*\}$/s, "{}");
|
|
865
|
+
const obj = JSON.parse(normalized);
|
|
866
|
+
if (obj && typeof obj === "object" && !Array.isArray(obj)) {
|
|
867
|
+
const props = unwrapped.properties;
|
|
868
|
+
const out = {};
|
|
869
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
870
|
+
const propSchema = props ? props[k] : void 0;
|
|
871
|
+
out[k] = typeof propSchema === "boolean" ? v : coerceBySchema(v, propSchema);
|
|
857
872
|
}
|
|
873
|
+
return out;
|
|
858
874
|
}
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
875
|
+
} catch (e) {
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
if (schemaType === "array") {
|
|
879
|
+
try {
|
|
880
|
+
const normalized = s.replace(/'/g, '"');
|
|
881
|
+
const arr = JSON.parse(normalized);
|
|
882
|
+
if (Array.isArray(arr)) {
|
|
883
|
+
const u = unwrapped;
|
|
884
|
+
const prefixItems = Array.isArray(
|
|
885
|
+
u.prefixItems
|
|
886
|
+
) ? u.prefixItems : void 0;
|
|
887
|
+
const itemsSchema = u.items;
|
|
888
|
+
if (prefixItems && arr.length === prefixItems.length) {
|
|
889
|
+
return arr.map((v, i) => coerceBySchema(v, prefixItems[i]));
|
|
890
|
+
}
|
|
891
|
+
return arr.map((v) => coerceBySchema(v, itemsSchema));
|
|
866
892
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
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
|
-
});
|
|
893
|
+
} catch (e) {
|
|
894
|
+
const csv = s.includes("\n") ? s.split(/\n+/) : s.split(/,\s*/);
|
|
895
|
+
const trimmed = csv.map((x) => x.trim()).filter((x) => x.length > 0);
|
|
896
|
+
const u = unwrapped;
|
|
897
|
+
const prefixItems = Array.isArray(
|
|
898
|
+
u.prefixItems
|
|
899
|
+
) ? u.prefixItems : void 0;
|
|
900
|
+
const itemsSchema = u.items;
|
|
901
|
+
if (prefixItems && trimmed.length === prefixItems.length) {
|
|
902
|
+
return trimmed.map((x, i) => coerceBySchema(x, prefixItems[i]));
|
|
895
903
|
}
|
|
896
|
-
|
|
897
|
-
return;
|
|
898
|
-
} else if (chunk.type !== "text-delta") {
|
|
899
|
-
controller.enqueue(chunk);
|
|
900
|
-
return;
|
|
904
|
+
return trimmed.map((x) => coerceBySchema(x, itemsSchema));
|
|
901
905
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
});
|
|
933
|
-
}
|
|
934
|
-
afterSwitch = false;
|
|
935
|
-
if (isToolCall) {
|
|
936
|
-
isFirstToolCall = false;
|
|
937
|
-
} else {
|
|
938
|
-
isFirstText = false;
|
|
939
|
-
}
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
if (schemaType === "object" && value && typeof value === "object" && !Array.isArray(value)) {
|
|
909
|
+
const out = {};
|
|
910
|
+
const props = unwrapped.properties;
|
|
911
|
+
for (const [k, v] of Object.entries(value)) {
|
|
912
|
+
const propSchema = props ? props[k] : void 0;
|
|
913
|
+
out[k] = typeof propSchema === "boolean" ? v : coerceBySchema(v, propSchema);
|
|
914
|
+
}
|
|
915
|
+
return out;
|
|
916
|
+
}
|
|
917
|
+
if (schemaType === "array") {
|
|
918
|
+
const u = unwrapped;
|
|
919
|
+
const itemsSchema = u.items;
|
|
920
|
+
const prefixItems = Array.isArray(
|
|
921
|
+
u.prefixItems
|
|
922
|
+
) ? u.prefixItems : void 0;
|
|
923
|
+
if (Array.isArray(value)) {
|
|
924
|
+
if (prefixItems && value.length === prefixItems.length) {
|
|
925
|
+
return value.map((v, i) => coerceBySchema(v, prefixItems[i]));
|
|
926
|
+
}
|
|
927
|
+
return value.map((v) => coerceBySchema(v, itemsSchema));
|
|
928
|
+
}
|
|
929
|
+
if (value && typeof value === "object") {
|
|
930
|
+
const maybe = value;
|
|
931
|
+
if (Object.prototype.hasOwnProperty.call(maybe, "item")) {
|
|
932
|
+
const items = maybe.item;
|
|
933
|
+
const arr = Array.isArray(items) ? items : [items];
|
|
934
|
+
if (prefixItems && arr.length === prefixItems.length) {
|
|
935
|
+
return arr.map((v, i) => coerceBySchema(v, prefixItems[i]));
|
|
940
936
|
}
|
|
937
|
+
return arr.map((v) => coerceBySchema(v, itemsSchema));
|
|
941
938
|
}
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
const
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
939
|
+
const keys = Object.keys(maybe);
|
|
940
|
+
if (keys.length === 1) {
|
|
941
|
+
const singleKey = keys[0];
|
|
942
|
+
const singleValue = maybe[singleKey];
|
|
943
|
+
if (Array.isArray(singleValue)) {
|
|
944
|
+
const coercedArray = singleValue.map(
|
|
945
|
+
(v) => coerceBySchema(v, itemsSchema)
|
|
946
|
+
);
|
|
947
|
+
return coercedArray;
|
|
949
948
|
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
isToolCall = !isToolCall;
|
|
956
|
-
afterSwitch = true;
|
|
957
|
-
} else {
|
|
958
|
-
break;
|
|
949
|
+
}
|
|
950
|
+
if (keys.length > 0 && keys.every((k) => /^\d+$/.test(k))) {
|
|
951
|
+
const arr = keys.sort((a, b) => Number(a) - Number(b)).map((k) => maybe[k]);
|
|
952
|
+
if (prefixItems && arr.length === prefixItems.length) {
|
|
953
|
+
return arr.map((v, i) => coerceBySchema(v, prefixItems[i]));
|
|
959
954
|
}
|
|
960
|
-
|
|
955
|
+
return arr.map((v) => coerceBySchema(v, itemsSchema));
|
|
956
|
+
}
|
|
961
957
|
}
|
|
962
|
-
|
|
958
|
+
if (value == null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
959
|
+
if (prefixItems && prefixItems.length > 0) {
|
|
960
|
+
return [coerceBySchema(value, prefixItems[0])];
|
|
961
|
+
}
|
|
962
|
+
return [coerceBySchema(value, itemsSchema)];
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
if (typeof value === "string") {
|
|
966
|
+
const s = value.trim();
|
|
967
|
+
if (schemaType === "boolean") {
|
|
968
|
+
const lower = s.toLowerCase();
|
|
969
|
+
if (lower === "true") return true;
|
|
970
|
+
if (lower === "false") return false;
|
|
971
|
+
}
|
|
972
|
+
if (schemaType === "number" || schemaType === "integer") {
|
|
973
|
+
if (/^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(s)) {
|
|
974
|
+
const num = Number(s);
|
|
975
|
+
if (Number.isFinite(num)) return num;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
return value;
|
|
980
|
+
}
|
|
981
|
+
function fixToolCallWithSchema(part, tools) {
|
|
982
|
+
var _a;
|
|
983
|
+
if (part.type !== "tool-call") return part;
|
|
984
|
+
const tc = part;
|
|
985
|
+
let args = {};
|
|
986
|
+
if (typeof tc.input === "string") {
|
|
987
|
+
try {
|
|
988
|
+
args = JSON.parse(tc.input);
|
|
989
|
+
} catch (e) {
|
|
990
|
+
return part;
|
|
991
|
+
}
|
|
992
|
+
} else if (tc.input && typeof tc.input === "object") {
|
|
993
|
+
args = tc.input;
|
|
994
|
+
}
|
|
995
|
+
const schema = (_a = tools.find((t) => t.name === tc.toolName)) == null ? void 0 : _a.inputSchema;
|
|
996
|
+
const coerced = coerceBySchema(args, schema);
|
|
997
|
+
return {
|
|
998
|
+
...part,
|
|
999
|
+
input: JSON.stringify(coerced != null ? coerced : {})
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1002
|
+
function coerceToolCallInput(part, tools) {
|
|
1003
|
+
return fixToolCallWithSchema(part, tools);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
// src/utils/protocol.ts
|
|
1007
|
+
function isProtocolFactory(protocol) {
|
|
1008
|
+
return typeof protocol === "function";
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
// src/stream-handler.ts
|
|
1012
|
+
async function wrapStream({
|
|
1013
|
+
protocol,
|
|
1014
|
+
doStream,
|
|
1015
|
+
doGenerate,
|
|
1016
|
+
params
|
|
1017
|
+
}) {
|
|
1018
|
+
var _a;
|
|
1019
|
+
if (isToolChoiceActive(params)) {
|
|
1020
|
+
return toolChoiceStream({
|
|
1021
|
+
doGenerate,
|
|
1022
|
+
options: extractOnErrorOption(params.providerOptions)
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
const { stream, ...rest } = await doStream();
|
|
963
1026
|
return {
|
|
964
|
-
stream:
|
|
1027
|
+
stream: stream.pipeThrough(
|
|
1028
|
+
protocol.createStreamParser({
|
|
1029
|
+
tools: getFunctionTools(params),
|
|
1030
|
+
options: {
|
|
1031
|
+
...extractOnErrorOption(params.providerOptions),
|
|
1032
|
+
...(_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware
|
|
1033
|
+
}
|
|
1034
|
+
})
|
|
1035
|
+
),
|
|
965
1036
|
...rest
|
|
966
1037
|
};
|
|
967
1038
|
}
|
|
968
1039
|
async function toolChoiceStream({
|
|
969
|
-
doGenerate
|
|
1040
|
+
doGenerate,
|
|
1041
|
+
options
|
|
970
1042
|
}) {
|
|
971
|
-
var _a;
|
|
1043
|
+
var _a, _b;
|
|
972
1044
|
const result = await doGenerate();
|
|
973
|
-
|
|
1045
|
+
let toolJson = {};
|
|
1046
|
+
if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
|
|
1047
|
+
try {
|
|
1048
|
+
toolJson = JSON.parse(result.content[0].text);
|
|
1049
|
+
} catch (error) {
|
|
1050
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
1051
|
+
options,
|
|
1052
|
+
"Failed to parse toolChoice JSON from streamed model output",
|
|
1053
|
+
{
|
|
1054
|
+
text: result.content[0].text,
|
|
1055
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1056
|
+
}
|
|
1057
|
+
);
|
|
1058
|
+
toolJson = {};
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
974
1061
|
const toolCallChunk = {
|
|
975
1062
|
type: "tool-call",
|
|
976
1063
|
toolCallId: (0, import_provider_utils.generateId)(),
|
|
@@ -1001,219 +1088,955 @@ async function toolChoiceStream({
|
|
|
1001
1088
|
};
|
|
1002
1089
|
}
|
|
1003
1090
|
|
|
1004
|
-
// src/
|
|
1005
|
-
|
|
1091
|
+
// src/generate-handler.ts
|
|
1092
|
+
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
1093
|
+
async function wrapGenerate({
|
|
1094
|
+
protocol,
|
|
1095
|
+
doGenerate,
|
|
1096
|
+
params
|
|
1097
|
+
}) {
|
|
1006
1098
|
var _a, _b;
|
|
1007
|
-
|
|
1008
|
-
|
|
1099
|
+
if (isToolChoiceActive(params)) {
|
|
1100
|
+
const result2 = await doGenerate();
|
|
1101
|
+
let parsed2 = {};
|
|
1102
|
+
const first = (_a = result2.content) == null ? void 0 : _a[0];
|
|
1103
|
+
if (first && first.type === "text") {
|
|
1104
|
+
try {
|
|
1105
|
+
parsed2 = JSON.parse(first.text);
|
|
1106
|
+
} catch (error) {
|
|
1107
|
+
const options = extractOnErrorOption(params.providerOptions);
|
|
1108
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
|
|
1109
|
+
options,
|
|
1110
|
+
"Failed to parse toolChoice JSON from generated model output",
|
|
1111
|
+
{
|
|
1112
|
+
text: first.text,
|
|
1113
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1114
|
+
}
|
|
1115
|
+
);
|
|
1116
|
+
parsed2 = {};
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
const toolCall = {
|
|
1120
|
+
type: "tool-call",
|
|
1121
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1122
|
+
toolName: parsed2.name || "unknown",
|
|
1123
|
+
input: JSON.stringify(parsed2.arguments || {})
|
|
1124
|
+
};
|
|
1125
|
+
return {
|
|
1126
|
+
...result2,
|
|
1127
|
+
content: [toolCall]
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
const result = await doGenerate();
|
|
1131
|
+
if (result.content.length === 0) {
|
|
1132
|
+
return result;
|
|
1133
|
+
}
|
|
1134
|
+
const parsed = result.content.flatMap((contentItem) => {
|
|
1135
|
+
var _a2;
|
|
1136
|
+
if (contentItem.type !== "text") {
|
|
1137
|
+
return [contentItem];
|
|
1138
|
+
}
|
|
1139
|
+
return protocol.parseGeneratedText({
|
|
1140
|
+
text: contentItem.text,
|
|
1141
|
+
tools: getFunctionTools(params),
|
|
1142
|
+
options: {
|
|
1143
|
+
...extractOnErrorOption(params.providerOptions),
|
|
1144
|
+
...(_a2 = params.providerOptions) == null ? void 0 : _a2.toolCallMiddleware
|
|
1145
|
+
}
|
|
1146
|
+
});
|
|
1147
|
+
});
|
|
1148
|
+
const tools = getFunctionTools(params);
|
|
1149
|
+
const newContent = parsed.map(
|
|
1150
|
+
(part) => coerceToolCallInput(part, tools)
|
|
1151
|
+
);
|
|
1152
|
+
return {
|
|
1153
|
+
...result,
|
|
1154
|
+
content: newContent
|
|
1155
|
+
};
|
|
1009
1156
|
}
|
|
1157
|
+
|
|
1158
|
+
// src/transform-handler.ts
|
|
1159
|
+
async function transformParams({
|
|
1160
|
+
params,
|
|
1161
|
+
protocol,
|
|
1162
|
+
toolSystemPromptTemplate
|
|
1163
|
+
}) {
|
|
1164
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1165
|
+
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
1166
|
+
const functionTools = ((_a = params.tools) != null ? _a : []).filter(
|
|
1167
|
+
(t) => t.type === "function"
|
|
1168
|
+
);
|
|
1169
|
+
const systemPrompt = resolvedProtocol.formatTools({
|
|
1170
|
+
tools: functionTools,
|
|
1171
|
+
toolSystemPromptTemplate
|
|
1172
|
+
});
|
|
1173
|
+
const processedPrompt = convertToolPrompt(
|
|
1174
|
+
(_b = params.prompt) != null ? _b : [],
|
|
1175
|
+
resolvedProtocol,
|
|
1176
|
+
extractOnErrorOption(params.providerOptions)
|
|
1177
|
+
);
|
|
1178
|
+
const finalPrompt = ((_c = processedPrompt[0]) == null ? void 0 : _c.role) === "system" ? [
|
|
1179
|
+
{
|
|
1180
|
+
role: "system",
|
|
1181
|
+
content: systemPrompt + "\n\n" + processedPrompt[0].content
|
|
1182
|
+
},
|
|
1183
|
+
...processedPrompt.slice(1)
|
|
1184
|
+
] : [
|
|
1185
|
+
{
|
|
1186
|
+
role: "system",
|
|
1187
|
+
content: systemPrompt
|
|
1188
|
+
},
|
|
1189
|
+
...processedPrompt
|
|
1190
|
+
];
|
|
1191
|
+
const baseReturnParams = {
|
|
1192
|
+
...params,
|
|
1193
|
+
prompt: finalPrompt,
|
|
1194
|
+
tools: [],
|
|
1195
|
+
toolChoice: void 0,
|
|
1196
|
+
providerOptions: {
|
|
1197
|
+
...params.providerOptions || {},
|
|
1198
|
+
toolCallMiddleware: {
|
|
1199
|
+
...params.providerOptions && typeof params.providerOptions === "object" && params.providerOptions.toolCallMiddleware || {},
|
|
1200
|
+
toolNames: functionTools.map((t) => t.name)
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
};
|
|
1204
|
+
if (((_d = params.toolChoice) == null ? void 0 : _d.type) === "none") {
|
|
1205
|
+
throw new Error(
|
|
1206
|
+
"The 'none' toolChoice type is not supported by this middleware. Please use 'auto', 'required', or specify a tool name."
|
|
1207
|
+
);
|
|
1208
|
+
}
|
|
1209
|
+
if (((_e = params.toolChoice) == null ? void 0 : _e.type) === "tool") {
|
|
1210
|
+
const selectedToolName = params.toolChoice.toolName;
|
|
1211
|
+
const providerDefinedMatch = ((_f = params.tools) != null ? _f : []).find((t) => {
|
|
1212
|
+
if (t.type === "function") return false;
|
|
1213
|
+
const anyTool = t;
|
|
1214
|
+
return anyTool.id === selectedToolName || anyTool.name === selectedToolName;
|
|
1215
|
+
});
|
|
1216
|
+
if (providerDefinedMatch) {
|
|
1217
|
+
throw new Error(
|
|
1218
|
+
"Provider-defined tools are not supported by this middleware. Please use custom tools."
|
|
1219
|
+
);
|
|
1220
|
+
}
|
|
1221
|
+
const selectedTool = ((_g = params.tools) != null ? _g : []).find(
|
|
1222
|
+
(t) => t.type === "function" && t.name === selectedToolName
|
|
1223
|
+
);
|
|
1224
|
+
if (!selectedTool) {
|
|
1225
|
+
throw new Error(
|
|
1226
|
+
`Tool with name '${selectedToolName}' not found in params.tools.`
|
|
1227
|
+
);
|
|
1228
|
+
}
|
|
1229
|
+
return {
|
|
1230
|
+
...baseReturnParams,
|
|
1231
|
+
responseFormat: {
|
|
1232
|
+
type: "json",
|
|
1233
|
+
schema: {
|
|
1234
|
+
type: "object",
|
|
1235
|
+
properties: {
|
|
1236
|
+
name: {
|
|
1237
|
+
const: selectedTool.name
|
|
1238
|
+
},
|
|
1239
|
+
arguments: selectedTool.inputSchema
|
|
1240
|
+
},
|
|
1241
|
+
required: ["name", "arguments"]
|
|
1242
|
+
},
|
|
1243
|
+
name: selectedTool.name,
|
|
1244
|
+
description: typeof selectedTool.description === "string" ? selectedTool.description : void 0
|
|
1245
|
+
},
|
|
1246
|
+
providerOptions: {
|
|
1247
|
+
...baseReturnParams.providerOptions || {},
|
|
1248
|
+
toolCallMiddleware: {
|
|
1249
|
+
...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
|
|
1250
|
+
toolChoice: params.toolChoice
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
};
|
|
1254
|
+
}
|
|
1255
|
+
if (((_h = params.toolChoice) == null ? void 0 : _h.type) === "required") {
|
|
1256
|
+
if (!params.tools || params.tools.length === 0) {
|
|
1257
|
+
throw new Error(
|
|
1258
|
+
"Tool choice type 'required' is set, but no tools are provided in params.tools."
|
|
1259
|
+
);
|
|
1260
|
+
}
|
|
1261
|
+
return {
|
|
1262
|
+
...baseReturnParams,
|
|
1263
|
+
responseFormat: {
|
|
1264
|
+
type: "json",
|
|
1265
|
+
schema: createDynamicIfThenElseSchema(functionTools)
|
|
1266
|
+
},
|
|
1267
|
+
providerOptions: {
|
|
1268
|
+
...baseReturnParams.providerOptions || {},
|
|
1269
|
+
toolCallMiddleware: {
|
|
1270
|
+
...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
|
|
1271
|
+
toolChoice: { type: "required" }
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
return baseReturnParams;
|
|
1277
|
+
}
|
|
1278
|
+
function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
|
|
1279
|
+
const processedPrompt = prompt.map((message) => {
|
|
1280
|
+
var _a;
|
|
1281
|
+
if (message.role === "assistant") {
|
|
1282
|
+
const newContent = [];
|
|
1283
|
+
for (const content of message.content) {
|
|
1284
|
+
if (isToolCallContent(content)) {
|
|
1285
|
+
newContent.push({
|
|
1286
|
+
type: "text",
|
|
1287
|
+
text: resolvedProtocol.formatToolCall(content)
|
|
1288
|
+
});
|
|
1289
|
+
} else if (content.type === "text") {
|
|
1290
|
+
newContent.push(content);
|
|
1291
|
+
} else if (content.type === "reasoning") {
|
|
1292
|
+
newContent.push(content);
|
|
1293
|
+
} else {
|
|
1294
|
+
const options = extractOnErrorOption(providerOptions);
|
|
1295
|
+
(_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
|
|
1296
|
+
options,
|
|
1297
|
+
"tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
|
|
1298
|
+
{ content }
|
|
1299
|
+
);
|
|
1300
|
+
newContent.push({
|
|
1301
|
+
type: "text",
|
|
1302
|
+
text: JSON.stringify(content)
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
const onlyText = newContent.every((c) => c.type === "text");
|
|
1307
|
+
const condensedAssistant = onlyText ? [
|
|
1308
|
+
{
|
|
1309
|
+
type: "text",
|
|
1310
|
+
text: newContent.map((c) => c.text).join("\n")
|
|
1311
|
+
}
|
|
1312
|
+
] : newContent;
|
|
1313
|
+
return { role: "assistant", content: condensedAssistant };
|
|
1314
|
+
}
|
|
1315
|
+
if (message.role === "tool") {
|
|
1316
|
+
return {
|
|
1317
|
+
role: "user",
|
|
1318
|
+
// Map tool results to text response blocks, then condense into a single text block
|
|
1319
|
+
content: [
|
|
1320
|
+
{
|
|
1321
|
+
type: "text",
|
|
1322
|
+
text: message.content.map(
|
|
1323
|
+
(toolResult) => isToolResultPart(toolResult) ? resolvedProtocol.formatToolResponse(toolResult) : resolvedProtocol.formatToolResponse(
|
|
1324
|
+
toolResult
|
|
1325
|
+
)
|
|
1326
|
+
).join("\n")
|
|
1327
|
+
}
|
|
1328
|
+
]
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
return message;
|
|
1332
|
+
});
|
|
1333
|
+
for (let i = 0; i < processedPrompt.length; i++) {
|
|
1334
|
+
const msg = processedPrompt[i];
|
|
1335
|
+
if (Array.isArray(msg.content)) {
|
|
1336
|
+
const allText = msg.content.every(
|
|
1337
|
+
(c) => (c == null ? void 0 : c.type) === "text"
|
|
1338
|
+
);
|
|
1339
|
+
if (allText && msg.content.length > 1) {
|
|
1340
|
+
const joinedText = msg.content.map((c) => c.text).join("\n");
|
|
1341
|
+
if (msg.role === "system") {
|
|
1342
|
+
processedPrompt[i] = {
|
|
1343
|
+
role: "system",
|
|
1344
|
+
content: joinedText
|
|
1345
|
+
};
|
|
1346
|
+
} else if (msg.role === "assistant") {
|
|
1347
|
+
processedPrompt[i] = {
|
|
1348
|
+
role: "assistant",
|
|
1349
|
+
content: [
|
|
1350
|
+
{
|
|
1351
|
+
type: "text",
|
|
1352
|
+
text: joinedText
|
|
1353
|
+
}
|
|
1354
|
+
]
|
|
1355
|
+
};
|
|
1356
|
+
} else {
|
|
1357
|
+
processedPrompt[i] = {
|
|
1358
|
+
role: "user",
|
|
1359
|
+
content: [
|
|
1360
|
+
{
|
|
1361
|
+
type: "text",
|
|
1362
|
+
text: joinedText
|
|
1363
|
+
}
|
|
1364
|
+
]
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
for (let i = processedPrompt.length - 1; i > 0; i--) {
|
|
1371
|
+
const current = processedPrompt[i];
|
|
1372
|
+
const prev = processedPrompt[i - 1];
|
|
1373
|
+
if (current.role === "user" && prev.role === "user") {
|
|
1374
|
+
const prevContent = prev.content.map((c) => c.type === "text" ? c.text : "").join("\n");
|
|
1375
|
+
const currentContent = current.content.map((c) => c.type === "text" ? c.text : "").join("\n");
|
|
1376
|
+
processedPrompt[i - 1] = {
|
|
1377
|
+
role: "user",
|
|
1378
|
+
content: [{ type: "text", text: prevContent + "\n" + currentContent }]
|
|
1379
|
+
};
|
|
1380
|
+
processedPrompt.splice(i, 1);
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
return processedPrompt;
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
// src/tool-call-middleware.ts
|
|
1010
1387
|
function createToolMiddleware({
|
|
1011
|
-
|
|
1012
|
-
toolCallEndTag,
|
|
1013
|
-
toolResponseTag,
|
|
1014
|
-
toolResponseEndTag,
|
|
1388
|
+
protocol,
|
|
1015
1389
|
toolSystemPromptTemplate
|
|
1016
1390
|
}) {
|
|
1391
|
+
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
1017
1392
|
return {
|
|
1018
1393
|
middlewareVersion: "v2",
|
|
1019
1394
|
wrapStream: async ({ doStream, doGenerate, params }) => {
|
|
1020
1395
|
if (isToolChoiceActive(params)) {
|
|
1021
1396
|
return toolChoiceStream({
|
|
1022
|
-
doGenerate
|
|
1397
|
+
doGenerate,
|
|
1398
|
+
options: extractOnErrorOption(params.providerOptions)
|
|
1023
1399
|
});
|
|
1024
1400
|
} else {
|
|
1025
|
-
return
|
|
1401
|
+
return wrapStream({
|
|
1402
|
+
protocol: resolvedProtocol,
|
|
1026
1403
|
doStream,
|
|
1027
|
-
|
|
1028
|
-
|
|
1404
|
+
doGenerate,
|
|
1405
|
+
params
|
|
1029
1406
|
});
|
|
1030
1407
|
}
|
|
1031
1408
|
},
|
|
1032
|
-
wrapGenerate: async ({ doGenerate, params }) => {
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1409
|
+
wrapGenerate: async ({ doGenerate, params }) => wrapGenerate({
|
|
1410
|
+
protocol: resolvedProtocol,
|
|
1411
|
+
doGenerate,
|
|
1412
|
+
params
|
|
1413
|
+
}),
|
|
1414
|
+
transformParams: async ({
|
|
1415
|
+
params
|
|
1416
|
+
}) => {
|
|
1417
|
+
return transformParams({
|
|
1418
|
+
protocol: resolvedProtocol,
|
|
1419
|
+
toolSystemPromptTemplate,
|
|
1420
|
+
params
|
|
1421
|
+
});
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
// src/protocols/json-mix-protocol.ts
|
|
1427
|
+
var import_provider_utils3 = require("@ai-sdk/provider-utils");
|
|
1428
|
+
var jsonMixProtocol = ({
|
|
1429
|
+
toolCallStart = "<tool_call>",
|
|
1430
|
+
toolCallEnd = "</tool_call>",
|
|
1431
|
+
toolResponseStart = "<tool_response>",
|
|
1432
|
+
toolResponseEnd = "</tool_response>"
|
|
1433
|
+
} = {}) => ({
|
|
1434
|
+
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
1435
|
+
const toolsForPrompt = (tools || []).filter((tool) => tool.type === "function").map((tool) => ({
|
|
1436
|
+
name: tool.name,
|
|
1437
|
+
description: tool.type === "function" && typeof tool.description === "string" ? tool.description : void 0,
|
|
1438
|
+
parameters: tool.inputSchema
|
|
1439
|
+
}));
|
|
1440
|
+
return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
|
|
1441
|
+
},
|
|
1442
|
+
formatToolCall(toolCall) {
|
|
1443
|
+
let args = {};
|
|
1444
|
+
try {
|
|
1445
|
+
args = JSON.parse(toolCall.input);
|
|
1446
|
+
} catch (e) {
|
|
1447
|
+
args = toolCall.input;
|
|
1448
|
+
}
|
|
1449
|
+
return `${toolCallStart}${JSON.stringify({
|
|
1450
|
+
name: toolCall.toolName,
|
|
1451
|
+
arguments: args
|
|
1452
|
+
})}${toolCallEnd}`;
|
|
1453
|
+
},
|
|
1454
|
+
formatToolResponse(toolResult) {
|
|
1455
|
+
return `${toolResponseStart}${JSON.stringify({
|
|
1456
|
+
toolName: toolResult.toolName,
|
|
1457
|
+
result: toolResult.output
|
|
1458
|
+
})}${toolResponseEnd}`;
|
|
1459
|
+
},
|
|
1460
|
+
parseGeneratedText({ text, options }) {
|
|
1461
|
+
var _a;
|
|
1462
|
+
const startEsc = escapeRegExp(toolCallStart);
|
|
1463
|
+
const endEsc = escapeRegExp(toolCallEnd);
|
|
1464
|
+
const toolCallRegex = new RegExp(
|
|
1465
|
+
`${startEsc}([\0-\uFFFF]*?)${endEsc}`,
|
|
1466
|
+
"gs"
|
|
1467
|
+
);
|
|
1468
|
+
const processedElements = [];
|
|
1469
|
+
let currentIndex = 0;
|
|
1470
|
+
let match;
|
|
1471
|
+
while ((match = toolCallRegex.exec(text)) !== null) {
|
|
1472
|
+
const startIndex = match.index;
|
|
1473
|
+
const toolCallJson = match[1];
|
|
1474
|
+
if (startIndex > currentIndex) {
|
|
1475
|
+
const textSegment = text.substring(currentIndex, startIndex);
|
|
1476
|
+
if (textSegment.trim()) {
|
|
1477
|
+
processedElements.push({ type: "text", text: textSegment });
|
|
1478
|
+
}
|
|
1036
1479
|
}
|
|
1037
|
-
if (
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1480
|
+
if (toolCallJson) {
|
|
1481
|
+
try {
|
|
1482
|
+
const parsedToolCall = relaxed_json_exports.parse(toolCallJson);
|
|
1483
|
+
processedElements.push({
|
|
1484
|
+
type: "tool-call",
|
|
1485
|
+
toolCallId: (0, import_provider_utils3.generateId)(),
|
|
1486
|
+
toolName: parsedToolCall.name,
|
|
1487
|
+
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1488
|
+
});
|
|
1489
|
+
} catch (error) {
|
|
1490
|
+
if (options == null ? void 0 : options.onError) {
|
|
1491
|
+
options.onError(
|
|
1492
|
+
"Could not process JSON tool call, keeping original text.",
|
|
1493
|
+
{ toolCall: match[0], error }
|
|
1494
|
+
);
|
|
1495
|
+
}
|
|
1496
|
+
processedElements.push({ type: "text", text: match[0] });
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
currentIndex = startIndex + match[0].length;
|
|
1500
|
+
}
|
|
1501
|
+
if (currentIndex < text.length) {
|
|
1502
|
+
const remainingText = text.substring(currentIndex);
|
|
1503
|
+
if (remainingText.trim()) {
|
|
1504
|
+
processedElements.push({ type: "text", text: remainingText });
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
return processedElements;
|
|
1508
|
+
},
|
|
1509
|
+
createStreamParser({ tools: _tools, options } = { tools: [] }) {
|
|
1510
|
+
let isInsideToolCall = false;
|
|
1511
|
+
let buffer = "";
|
|
1512
|
+
let currentToolCallJson = "";
|
|
1513
|
+
let currentTextId = null;
|
|
1514
|
+
let hasEmittedTextStart = false;
|
|
1515
|
+
return new TransformStream({
|
|
1516
|
+
transform(chunk, controller) {
|
|
1517
|
+
var _a;
|
|
1518
|
+
if (chunk.type === "finish") {
|
|
1519
|
+
if (isInsideToolCall && buffer.length > 0) {
|
|
1520
|
+
if (!currentTextId) {
|
|
1521
|
+
currentTextId = (0, import_provider_utils3.generateId)();
|
|
1522
|
+
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
1523
|
+
hasEmittedTextStart = true;
|
|
1524
|
+
}
|
|
1525
|
+
controller.enqueue({
|
|
1526
|
+
type: "text-delta",
|
|
1527
|
+
id: currentTextId,
|
|
1528
|
+
delta: `${toolCallStart}${buffer}`
|
|
1529
|
+
});
|
|
1530
|
+
buffer = "";
|
|
1531
|
+
} else if (!isInsideToolCall && buffer.length > 0) {
|
|
1532
|
+
if (!currentTextId) {
|
|
1533
|
+
currentTextId = (0, import_provider_utils3.generateId)();
|
|
1534
|
+
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
1535
|
+
hasEmittedTextStart = true;
|
|
1536
|
+
}
|
|
1537
|
+
controller.enqueue({
|
|
1538
|
+
type: "text-delta",
|
|
1539
|
+
id: currentTextId,
|
|
1540
|
+
delta: buffer
|
|
1541
|
+
});
|
|
1542
|
+
buffer = "";
|
|
1543
|
+
}
|
|
1544
|
+
if (currentTextId && hasEmittedTextStart) {
|
|
1545
|
+
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1546
|
+
currentTextId = null;
|
|
1547
|
+
hasEmittedTextStart = false;
|
|
1548
|
+
}
|
|
1549
|
+
if (currentToolCallJson) {
|
|
1550
|
+
const errorId = (0, import_provider_utils3.generateId)();
|
|
1551
|
+
controller.enqueue({ type: "text-start", id: errorId });
|
|
1552
|
+
controller.enqueue({
|
|
1553
|
+
type: "text-delta",
|
|
1554
|
+
id: errorId,
|
|
1555
|
+
delta: `${toolCallStart}${currentToolCallJson}`
|
|
1556
|
+
});
|
|
1557
|
+
controller.enqueue({ type: "text-end", id: errorId });
|
|
1558
|
+
currentToolCallJson = "";
|
|
1559
|
+
}
|
|
1560
|
+
controller.enqueue(chunk);
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
if (chunk.type !== "text-delta") {
|
|
1564
|
+
controller.enqueue(chunk);
|
|
1565
|
+
return;
|
|
1566
|
+
}
|
|
1567
|
+
buffer += chunk.delta;
|
|
1568
|
+
const publish = (text) => {
|
|
1569
|
+
if (isInsideToolCall) {
|
|
1570
|
+
if (currentTextId && hasEmittedTextStart) {
|
|
1571
|
+
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1572
|
+
currentTextId = null;
|
|
1573
|
+
hasEmittedTextStart = false;
|
|
1574
|
+
}
|
|
1575
|
+
currentToolCallJson += text;
|
|
1576
|
+
} else if (text.length > 0) {
|
|
1577
|
+
if (!currentTextId) {
|
|
1578
|
+
currentTextId = (0, import_provider_utils3.generateId)();
|
|
1579
|
+
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
1580
|
+
hasEmittedTextStart = true;
|
|
1048
1581
|
}
|
|
1049
|
-
|
|
1582
|
+
controller.enqueue({
|
|
1583
|
+
type: "text-delta",
|
|
1584
|
+
id: currentTextId,
|
|
1585
|
+
delta: text
|
|
1586
|
+
});
|
|
1587
|
+
}
|
|
1050
1588
|
};
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
return [contentItem];
|
|
1589
|
+
let startIndex;
|
|
1590
|
+
while ((startIndex = getPotentialStartIndex(
|
|
1591
|
+
buffer,
|
|
1592
|
+
isInsideToolCall ? toolCallEnd : toolCallStart
|
|
1593
|
+
)) != null) {
|
|
1594
|
+
const tag = isInsideToolCall ? toolCallEnd : toolCallStart;
|
|
1595
|
+
if (startIndex + tag.length > buffer.length) {
|
|
1596
|
+
break;
|
|
1060
1597
|
}
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1598
|
+
publish(buffer.slice(0, startIndex));
|
|
1599
|
+
buffer = buffer.slice(startIndex + tag.length);
|
|
1600
|
+
if (!isInsideToolCall) {
|
|
1601
|
+
currentToolCallJson = "";
|
|
1602
|
+
isInsideToolCall = true;
|
|
1603
|
+
} else {
|
|
1066
1604
|
try {
|
|
1067
|
-
const parsedToolCall = relaxed_json_exports.parse(
|
|
1068
|
-
if (
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
);
|
|
1073
|
-
return null;
|
|
1605
|
+
const parsedToolCall = relaxed_json_exports.parse(currentToolCallJson);
|
|
1606
|
+
if (currentTextId && hasEmittedTextStart) {
|
|
1607
|
+
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1608
|
+
currentTextId = null;
|
|
1609
|
+
hasEmittedTextStart = false;
|
|
1074
1610
|
}
|
|
1075
|
-
|
|
1611
|
+
controller.enqueue({
|
|
1076
1612
|
type: "tool-call",
|
|
1077
|
-
toolCallId: (0,
|
|
1613
|
+
toolCallId: (0, import_provider_utils3.generateId)(),
|
|
1078
1614
|
toolName: parsedToolCall.name,
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
);
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
const textSegment = text.substring(currentIndex, startIndex);
|
|
1098
|
-
if (textSegment.trim()) {
|
|
1099
|
-
processedElements.push({ type: "text", text: textSegment });
|
|
1615
|
+
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1616
|
+
});
|
|
1617
|
+
} catch (e) {
|
|
1618
|
+
const errorId = (0, import_provider_utils3.generateId)();
|
|
1619
|
+
controller.enqueue({ type: "text-start", id: errorId });
|
|
1620
|
+
controller.enqueue({
|
|
1621
|
+
type: "text-delta",
|
|
1622
|
+
id: errorId,
|
|
1623
|
+
delta: `${toolCallStart}${currentToolCallJson}${toolCallEnd}`
|
|
1624
|
+
});
|
|
1625
|
+
controller.enqueue({ type: "text-end", id: errorId });
|
|
1626
|
+
if (options == null ? void 0 : options.onError) {
|
|
1627
|
+
options.onError(
|
|
1628
|
+
"Could not process streaming JSON tool call; emitting original text.",
|
|
1629
|
+
{
|
|
1630
|
+
toolCall: `${toolCallStart}${currentToolCallJson}${toolCallEnd}`
|
|
1631
|
+
}
|
|
1632
|
+
);
|
|
1100
1633
|
}
|
|
1101
1634
|
}
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1635
|
+
currentToolCallJson = "";
|
|
1636
|
+
isInsideToolCall = false;
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
if (!isInsideToolCall) {
|
|
1640
|
+
const potentialIndex = getPotentialStartIndex(buffer, toolCallStart);
|
|
1641
|
+
if (potentialIndex != null && potentialIndex + toolCallStart.length > buffer.length) {
|
|
1642
|
+
publish(buffer.slice(0, potentialIndex));
|
|
1643
|
+
buffer = buffer.slice(potentialIndex);
|
|
1644
|
+
} else {
|
|
1645
|
+
publish(buffer);
|
|
1646
|
+
buffer = "";
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
});
|
|
1651
|
+
}
|
|
1652
|
+
});
|
|
1653
|
+
|
|
1654
|
+
// src/protocols/xml-protocol.ts
|
|
1655
|
+
var import_provider_utils4 = require("@ai-sdk/provider-utils");
|
|
1656
|
+
var import_fast_xml_parser = require("fast-xml-parser");
|
|
1657
|
+
var xmlProtocol = () => ({
|
|
1658
|
+
formatTools({ tools, toolSystemPromptTemplate }) {
|
|
1659
|
+
const toolsForPrompt = (tools || []).map((tool) => ({
|
|
1660
|
+
name: tool.name,
|
|
1661
|
+
description: tool.description,
|
|
1662
|
+
parameters: unwrapJsonSchema(tool.inputSchema)
|
|
1663
|
+
}));
|
|
1664
|
+
return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
|
|
1665
|
+
},
|
|
1666
|
+
formatToolCall(toolCall) {
|
|
1667
|
+
const builder = new import_fast_xml_parser.XMLBuilder({ format: true, suppressEmptyNode: true });
|
|
1668
|
+
let args = {};
|
|
1669
|
+
const inputValue = hasInputProperty(toolCall) ? toolCall.input : void 0;
|
|
1670
|
+
if (typeof inputValue === "string") {
|
|
1671
|
+
try {
|
|
1672
|
+
args = JSON.parse(inputValue);
|
|
1673
|
+
} catch (e) {
|
|
1674
|
+
args = inputValue;
|
|
1675
|
+
}
|
|
1676
|
+
} else {
|
|
1677
|
+
args = inputValue;
|
|
1678
|
+
}
|
|
1679
|
+
const xmlContent = builder.build({
|
|
1680
|
+
[toolCall.toolName]: args
|
|
1681
|
+
});
|
|
1682
|
+
return xmlContent;
|
|
1683
|
+
},
|
|
1684
|
+
formatToolResponse(toolResult) {
|
|
1685
|
+
const builder = new import_fast_xml_parser.XMLBuilder({ format: true });
|
|
1686
|
+
const xmlContent = builder.build({
|
|
1687
|
+
tool_response: {
|
|
1688
|
+
tool_name: toolResult.toolName,
|
|
1689
|
+
result: toolResult.output
|
|
1690
|
+
}
|
|
1691
|
+
});
|
|
1692
|
+
return xmlContent;
|
|
1693
|
+
},
|
|
1694
|
+
parseGeneratedText({ text, tools, options }) {
|
|
1695
|
+
var _a, _b, _c;
|
|
1696
|
+
const originalSchemas = (options == null ? void 0 : options.originalToolSchemas) || {};
|
|
1697
|
+
const toolNames = tools.map((t) => t.name).filter((name) => name != null);
|
|
1698
|
+
if (toolNames.length === 0) {
|
|
1699
|
+
return [{ type: "text", text }];
|
|
1700
|
+
}
|
|
1701
|
+
const toolNamesPattern = toolNames.map((n) => escapeRegExp(n)).join("|");
|
|
1702
|
+
const toolCallRegex = new RegExp(
|
|
1703
|
+
String.raw`<(${toolNamesPattern})>([\s\S]*?)<\/\1>`,
|
|
1704
|
+
"g"
|
|
1705
|
+
);
|
|
1706
|
+
const processedElements = [];
|
|
1707
|
+
let currentIndex = 0;
|
|
1708
|
+
let match;
|
|
1709
|
+
while ((match = toolCallRegex.exec(text)) !== null) {
|
|
1710
|
+
const startIndex = match.index;
|
|
1711
|
+
const toolName = match[1];
|
|
1712
|
+
const toolContent = match[2].trim();
|
|
1713
|
+
if (startIndex > currentIndex) {
|
|
1714
|
+
const textSegment = text.substring(currentIndex, startIndex);
|
|
1715
|
+
if (textSegment.trim()) {
|
|
1716
|
+
processedElements.push({ type: "text", text: textSegment });
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
try {
|
|
1720
|
+
const parser = new import_fast_xml_parser.XMLParser({
|
|
1721
|
+
ignoreAttributes: false,
|
|
1722
|
+
parseTagValue: false,
|
|
1723
|
+
ignoreDeclaration: true,
|
|
1724
|
+
textNodeName: "#text"
|
|
1725
|
+
});
|
|
1726
|
+
const parsedArgs = ((_a = parser.parse(`<root>${toolContent}</root>`)) == null ? void 0 : _a.root) || {};
|
|
1727
|
+
const args = {};
|
|
1728
|
+
for (const k of Object.keys(parsedArgs || {})) {
|
|
1729
|
+
const v = parsedArgs[k];
|
|
1730
|
+
let val = v;
|
|
1731
|
+
if (v && typeof v === "object" && Object.prototype.hasOwnProperty.call(v, "#text")) {
|
|
1732
|
+
val = v == null ? void 0 : v["#text"];
|
|
1733
|
+
}
|
|
1734
|
+
if (Array.isArray(v)) {
|
|
1735
|
+
val = v.map((item) => {
|
|
1736
|
+
if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
|
|
1737
|
+
const textVal = item == null ? void 0 : item["#text"];
|
|
1738
|
+
return typeof textVal === "string" ? textVal.trim() : textVal;
|
|
1739
|
+
}
|
|
1740
|
+
return typeof item === "string" ? item.trim() : item;
|
|
1741
|
+
});
|
|
1742
|
+
} else if (v && typeof v === "object" && !Object.prototype.hasOwnProperty.call(v, "#text")) {
|
|
1743
|
+
const obj = v;
|
|
1744
|
+
const keys = Object.keys(obj);
|
|
1745
|
+
if (keys.length === 1 && keys[0] === "item") {
|
|
1746
|
+
const itemValue = obj.item;
|
|
1747
|
+
if (Array.isArray(itemValue)) {
|
|
1748
|
+
val = itemValue.map((item) => {
|
|
1749
|
+
if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
|
|
1750
|
+
const textVal = item == null ? void 0 : item["#text"];
|
|
1751
|
+
const trimmed2 = typeof textVal === "string" ? textVal.trim() : textVal;
|
|
1752
|
+
if (typeof trimmed2 === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed2)) {
|
|
1753
|
+
const num = Number(trimmed2);
|
|
1754
|
+
if (Number.isFinite(num)) return num;
|
|
1755
|
+
}
|
|
1756
|
+
return trimmed2;
|
|
1757
|
+
}
|
|
1758
|
+
const trimmed = typeof item === "string" ? item.trim() : item;
|
|
1759
|
+
if (typeof trimmed === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed)) {
|
|
1760
|
+
const num = Number(trimmed);
|
|
1761
|
+
if (Number.isFinite(num)) return num;
|
|
1762
|
+
}
|
|
1763
|
+
return trimmed;
|
|
1764
|
+
});
|
|
1106
1765
|
} else {
|
|
1107
|
-
|
|
1108
|
-
|
|
1766
|
+
const trimmed = typeof itemValue === "string" ? itemValue.trim() : itemValue;
|
|
1767
|
+
if (typeof trimmed === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed)) {
|
|
1768
|
+
const num = Number(trimmed);
|
|
1769
|
+
if (Number.isFinite(num)) {
|
|
1770
|
+
val = num;
|
|
1771
|
+
} else {
|
|
1772
|
+
val = trimmed;
|
|
1773
|
+
}
|
|
1774
|
+
} else {
|
|
1775
|
+
val = trimmed;
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
} else {
|
|
1779
|
+
const isIndexedTuple = keys.length > 0 && keys.every((key) => /^\d+$/.test(key)) && (() => {
|
|
1780
|
+
const indices = keys.map((k2) => parseInt(k2)).sort((a, b) => a - b);
|
|
1781
|
+
return indices[0] === 0 && indices.every((val2, idx) => val2 === idx);
|
|
1782
|
+
})();
|
|
1783
|
+
if (isIndexedTuple) {
|
|
1784
|
+
const sortedKeys = keys.sort(
|
|
1785
|
+
(a, b) => parseInt(a) - parseInt(b)
|
|
1109
1786
|
);
|
|
1110
|
-
|
|
1787
|
+
val = sortedKeys.map((key) => {
|
|
1788
|
+
const item = obj[key];
|
|
1789
|
+
if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
|
|
1790
|
+
const textVal = item == null ? void 0 : item["#text"];
|
|
1791
|
+
return typeof textVal === "string" ? textVal.trim() : textVal;
|
|
1792
|
+
}
|
|
1793
|
+
return typeof item === "string" ? item.trim() : item;
|
|
1794
|
+
});
|
|
1795
|
+
} else {
|
|
1796
|
+
val = v;
|
|
1111
1797
|
}
|
|
1112
1798
|
}
|
|
1113
|
-
currentIndex = endIndex;
|
|
1114
|
-
}
|
|
1115
|
-
if (currentIndex < text.length) {
|
|
1116
|
-
const remainingText = text.substring(currentIndex);
|
|
1117
|
-
if (remainingText.trim()) {
|
|
1118
|
-
processedElements.push({ type: "text", text: remainingText });
|
|
1119
|
-
}
|
|
1120
1799
|
}
|
|
1121
|
-
|
|
1800
|
+
args[k] = typeof val === "string" ? val.trim() : val;
|
|
1122
1801
|
}
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
toolResponseTag,
|
|
1138
|
-
toolResponseEndTag
|
|
1139
|
-
});
|
|
1140
|
-
const baseReturnParams = {
|
|
1141
|
-
...params,
|
|
1142
|
-
prompt: toolSystemPrompt,
|
|
1143
|
-
// Reset tools and toolChoice to default after prompt transformation
|
|
1144
|
-
tools: [],
|
|
1145
|
-
toolChoice: void 0
|
|
1146
|
-
};
|
|
1147
|
-
if (((_a = params.toolChoice) == null ? void 0 : _a.type) === "none") {
|
|
1148
|
-
throw new Error(
|
|
1149
|
-
"The 'none' toolChoice type is not supported by this middleware. Please use 'auto', 'required', or specify a tool name."
|
|
1150
|
-
);
|
|
1802
|
+
const originalSchema = originalSchemas[toolName];
|
|
1803
|
+
const fallbackSchema = (_b = tools.find((t) => t.name === toolName)) == null ? void 0 : _b.inputSchema;
|
|
1804
|
+
const schema = originalSchema || fallbackSchema;
|
|
1805
|
+
const coercedArgs = coerceBySchema(args, schema);
|
|
1806
|
+
processedElements.push({
|
|
1807
|
+
type: "tool-call",
|
|
1808
|
+
toolCallId: (0, import_provider_utils4.generateId)(),
|
|
1809
|
+
toolName,
|
|
1810
|
+
input: JSON.stringify(coercedArgs)
|
|
1811
|
+
});
|
|
1812
|
+
} catch (error) {
|
|
1813
|
+
const message = `Could not process XML tool call, keeping original text: ${match[0]}`;
|
|
1814
|
+
(_c = options == null ? void 0 : options.onError) == null ? void 0 : _c.call(options, message, { toolCall: match[0], toolName, error });
|
|
1815
|
+
processedElements.push({ type: "text", text: match[0] });
|
|
1151
1816
|
}
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1817
|
+
currentIndex = startIndex + match[0].length;
|
|
1818
|
+
}
|
|
1819
|
+
if (currentIndex < text.length) {
|
|
1820
|
+
const remainingText = text.substring(currentIndex);
|
|
1821
|
+
if (remainingText.trim()) {
|
|
1822
|
+
processedElements.push({ type: "text", text: remainingText });
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
return processedElements;
|
|
1826
|
+
},
|
|
1827
|
+
createStreamParser({ tools, options }) {
|
|
1828
|
+
const originalSchemas = (options == null ? void 0 : options.originalToolSchemas) || {};
|
|
1829
|
+
const toolNames = tools.map((t) => t.name).filter((name) => name != null);
|
|
1830
|
+
let buffer = "";
|
|
1831
|
+
let currentToolCall = null;
|
|
1832
|
+
let currentTextId = null;
|
|
1833
|
+
const flushText = (controller, text) => {
|
|
1834
|
+
const content = text != null ? text : buffer;
|
|
1835
|
+
if (content) {
|
|
1836
|
+
if (!currentTextId) {
|
|
1837
|
+
currentTextId = (0, import_provider_utils4.generateId)();
|
|
1838
|
+
controller.enqueue({ type: "text-start", id: currentTextId });
|
|
1161
1839
|
}
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1840
|
+
controller.enqueue({
|
|
1841
|
+
type: "text-delta",
|
|
1842
|
+
id: currentTextId,
|
|
1843
|
+
delta: content
|
|
1844
|
+
});
|
|
1845
|
+
if (text === void 0) {
|
|
1846
|
+
buffer = "";
|
|
1166
1847
|
}
|
|
1167
|
-
return {
|
|
1168
|
-
...baseReturnParams,
|
|
1169
|
-
responseFormat: {
|
|
1170
|
-
type: "json",
|
|
1171
|
-
schema: {
|
|
1172
|
-
type: "object",
|
|
1173
|
-
properties: {
|
|
1174
|
-
name: {
|
|
1175
|
-
const: selectedTool.name
|
|
1176
|
-
},
|
|
1177
|
-
arguments: selectedTool.inputSchema
|
|
1178
|
-
},
|
|
1179
|
-
required: ["name", "arguments"]
|
|
1180
|
-
},
|
|
1181
|
-
name: selectedTool.name,
|
|
1182
|
-
description: selectedTool.type === "function" && typeof selectedTool.description === "string" ? selectedTool.description : void 0
|
|
1183
|
-
},
|
|
1184
|
-
providerOptions: {
|
|
1185
|
-
toolCallMiddleware: {
|
|
1186
|
-
toolChoice: params.toolChoice
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
};
|
|
1190
1848
|
}
|
|
1191
|
-
if (
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1849
|
+
if (currentTextId && !text) {
|
|
1850
|
+
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
1851
|
+
currentTextId = null;
|
|
1852
|
+
}
|
|
1853
|
+
};
|
|
1854
|
+
return new TransformStream({
|
|
1855
|
+
transform(chunk, controller) {
|
|
1856
|
+
var _a, _b;
|
|
1857
|
+
if (chunk.type !== "text-delta") {
|
|
1858
|
+
if (buffer) flushText(controller);
|
|
1859
|
+
controller.enqueue(chunk);
|
|
1860
|
+
return;
|
|
1196
1861
|
}
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1862
|
+
buffer += chunk.delta;
|
|
1863
|
+
while (true) {
|
|
1864
|
+
if (currentToolCall) {
|
|
1865
|
+
const endTag = `</${currentToolCall.name}>`;
|
|
1866
|
+
const endTagIndex = buffer.indexOf(endTag);
|
|
1867
|
+
if (endTagIndex !== -1) {
|
|
1868
|
+
const toolContent = buffer.substring(0, endTagIndex);
|
|
1869
|
+
buffer = buffer.substring(endTagIndex + endTag.length);
|
|
1870
|
+
try {
|
|
1871
|
+
const parser = new import_fast_xml_parser.XMLParser({
|
|
1872
|
+
ignoreAttributes: false,
|
|
1873
|
+
parseTagValue: false,
|
|
1874
|
+
ignoreDeclaration: true,
|
|
1875
|
+
textNodeName: "#text"
|
|
1876
|
+
});
|
|
1877
|
+
const parsedArgs = ((_a = parser.parse(`<root>${toolContent}</root>`)) == null ? void 0 : _a.root) || {};
|
|
1878
|
+
const args = {};
|
|
1879
|
+
for (const k of Object.keys(parsedArgs || {})) {
|
|
1880
|
+
const v = parsedArgs[k];
|
|
1881
|
+
let val = v;
|
|
1882
|
+
if (v && typeof v === "object" && Object.prototype.hasOwnProperty.call(v, "#text")) {
|
|
1883
|
+
val = v == null ? void 0 : v["#text"];
|
|
1884
|
+
}
|
|
1885
|
+
if (Array.isArray(v)) {
|
|
1886
|
+
val = v.map((item) => {
|
|
1887
|
+
if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
|
|
1888
|
+
const textVal = item == null ? void 0 : item["#text"];
|
|
1889
|
+
return typeof textVal === "string" ? textVal.trim() : textVal;
|
|
1890
|
+
}
|
|
1891
|
+
return typeof item === "string" ? item.trim() : item;
|
|
1892
|
+
});
|
|
1893
|
+
} else if (v && typeof v === "object" && !Object.prototype.hasOwnProperty.call(v, "#text")) {
|
|
1894
|
+
const obj = v;
|
|
1895
|
+
const keys = Object.keys(obj);
|
|
1896
|
+
if (keys.length === 1 && keys[0] === "item") {
|
|
1897
|
+
const itemValue = obj.item;
|
|
1898
|
+
if (Array.isArray(itemValue)) {
|
|
1899
|
+
val = itemValue.map((item) => {
|
|
1900
|
+
if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
|
|
1901
|
+
const textVal = item == null ? void 0 : item["#text"];
|
|
1902
|
+
const trimmed2 = typeof textVal === "string" ? textVal.trim() : textVal;
|
|
1903
|
+
if (typeof trimmed2 === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed2)) {
|
|
1904
|
+
const num = Number(trimmed2);
|
|
1905
|
+
if (Number.isFinite(num)) return num;
|
|
1906
|
+
}
|
|
1907
|
+
return trimmed2;
|
|
1908
|
+
}
|
|
1909
|
+
const trimmed = typeof item === "string" ? item.trim() : item;
|
|
1910
|
+
if (typeof trimmed === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed)) {
|
|
1911
|
+
const num = Number(trimmed);
|
|
1912
|
+
if (Number.isFinite(num)) return num;
|
|
1913
|
+
}
|
|
1914
|
+
return trimmed;
|
|
1915
|
+
});
|
|
1916
|
+
} else {
|
|
1917
|
+
const trimmed = typeof itemValue === "string" ? itemValue.trim() : itemValue;
|
|
1918
|
+
if (typeof trimmed === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed)) {
|
|
1919
|
+
const num = Number(trimmed);
|
|
1920
|
+
if (Number.isFinite(num)) {
|
|
1921
|
+
val = num;
|
|
1922
|
+
} else {
|
|
1923
|
+
val = trimmed;
|
|
1924
|
+
}
|
|
1925
|
+
} else {
|
|
1926
|
+
val = trimmed;
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
} else {
|
|
1930
|
+
const isIndexedTuple = keys.length > 0 && keys.every((key) => /^\d+$/.test(key)) && (() => {
|
|
1931
|
+
const indices = keys.map((k2) => parseInt(k2)).sort((a, b) => a - b);
|
|
1932
|
+
return indices[0] === 0 && indices.every((val2, idx) => val2 === idx);
|
|
1933
|
+
})();
|
|
1934
|
+
if (isIndexedTuple) {
|
|
1935
|
+
const sortedKeys = keys.sort(
|
|
1936
|
+
(a, b) => parseInt(a) - parseInt(b)
|
|
1937
|
+
);
|
|
1938
|
+
val = sortedKeys.map((key) => {
|
|
1939
|
+
const item = obj[key];
|
|
1940
|
+
if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
|
|
1941
|
+
const textVal = item == null ? void 0 : item["#text"];
|
|
1942
|
+
return typeof textVal === "string" ? textVal.trim() : textVal;
|
|
1943
|
+
}
|
|
1944
|
+
return typeof item === "string" ? item.trim() : item;
|
|
1945
|
+
});
|
|
1946
|
+
} else {
|
|
1947
|
+
val = v;
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
args[k] = typeof val === "string" ? val.trim() : val;
|
|
1952
|
+
}
|
|
1953
|
+
const originalSchema = originalSchemas[currentToolCall.name];
|
|
1954
|
+
const fallbackSchema = (_b = tools.find(
|
|
1955
|
+
(t) => t.name === currentToolCall.name
|
|
1956
|
+
)) == null ? void 0 : _b.inputSchema;
|
|
1957
|
+
const toolSchema = originalSchema || fallbackSchema;
|
|
1958
|
+
const coercedArgs = coerceBySchema(args, toolSchema);
|
|
1959
|
+
flushText(controller);
|
|
1960
|
+
controller.enqueue({
|
|
1961
|
+
type: "tool-call",
|
|
1962
|
+
toolCallId: (0, import_provider_utils4.generateId)(),
|
|
1963
|
+
toolName: currentToolCall.name,
|
|
1964
|
+
input: JSON.stringify(coercedArgs)
|
|
1965
|
+
});
|
|
1966
|
+
} catch (e) {
|
|
1967
|
+
const originalCallText = `<${currentToolCall.name}>${toolContent}${endTag}`;
|
|
1968
|
+
if (options == null ? void 0 : options.onError) {
|
|
1969
|
+
options.onError(
|
|
1970
|
+
"Could not process streaming XML tool call; emitting original text.",
|
|
1971
|
+
{
|
|
1972
|
+
toolCall: originalCallText,
|
|
1973
|
+
toolName: currentToolCall.name
|
|
1974
|
+
}
|
|
1975
|
+
);
|
|
1976
|
+
}
|
|
1977
|
+
flushText(controller, originalCallText);
|
|
1978
|
+
}
|
|
1979
|
+
currentToolCall = null;
|
|
1980
|
+
} else {
|
|
1981
|
+
break;
|
|
1982
|
+
}
|
|
1983
|
+
} else {
|
|
1984
|
+
let earliestStartTagIndex = -1;
|
|
1985
|
+
let earliestToolName = "";
|
|
1986
|
+
if (toolNames.length > 0) {
|
|
1987
|
+
for (const name of toolNames) {
|
|
1988
|
+
const startTag = `<${name}>`;
|
|
1989
|
+
const index = buffer.indexOf(startTag);
|
|
1990
|
+
if (index !== -1 && (earliestStartTagIndex === -1 || index < earliestStartTagIndex)) {
|
|
1991
|
+
earliestStartTagIndex = index;
|
|
1992
|
+
earliestToolName = name;
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
if (earliestStartTagIndex !== -1) {
|
|
1997
|
+
const textBeforeTag = buffer.substring(0, earliestStartTagIndex);
|
|
1998
|
+
flushText(controller, textBeforeTag);
|
|
1999
|
+
const startTag = `<${earliestToolName}>`;
|
|
2000
|
+
buffer = buffer.substring(
|
|
2001
|
+
earliestStartTagIndex + startTag.length
|
|
2002
|
+
);
|
|
2003
|
+
currentToolCall = { name: earliestToolName, content: "" };
|
|
2004
|
+
} else {
|
|
2005
|
+
break;
|
|
1206
2006
|
}
|
|
1207
2007
|
}
|
|
1208
|
-
}
|
|
2008
|
+
}
|
|
2009
|
+
},
|
|
2010
|
+
flush(controller) {
|
|
2011
|
+
if (currentToolCall) {
|
|
2012
|
+
const unfinishedCall = `<${currentToolCall.name}>${buffer}`;
|
|
2013
|
+
flushText(controller, unfinishedCall);
|
|
2014
|
+
} else if (buffer) {
|
|
2015
|
+
flushText(controller);
|
|
2016
|
+
}
|
|
2017
|
+
if (currentTextId) {
|
|
2018
|
+
controller.enqueue({ type: "text-end", id: currentTextId });
|
|
2019
|
+
}
|
|
1209
2020
|
}
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
2021
|
+
});
|
|
2022
|
+
}
|
|
2023
|
+
});
|
|
2024
|
+
|
|
2025
|
+
// src/protocols/dummy-protocol.ts
|
|
2026
|
+
var import_provider_utils5 = require("@ai-sdk/provider-utils");
|
|
1214
2027
|
|
|
1215
2028
|
// src/index.ts
|
|
1216
2029
|
var gemmaToolMiddleware = createToolMiddleware({
|
|
2030
|
+
protocol: jsonMixProtocol(
|
|
2031
|
+
// Customize the tool call delimiters to use markdown code fences
|
|
2032
|
+
{
|
|
2033
|
+
toolCallStart: "```tool_call\n",
|
|
2034
|
+
toolCallEnd: "\n``",
|
|
2035
|
+
// two backticks are more common in gemma output @
|
|
2036
|
+
toolResponseStart: "```tool_response\n",
|
|
2037
|
+
toolResponseEnd: "\n```"
|
|
2038
|
+
}
|
|
2039
|
+
),
|
|
1217
2040
|
toolSystemPromptTemplate(tools) {
|
|
1218
2041
|
return `You have access to functions. If you decide to invoke any of the function(s),
|
|
1219
2042
|
you MUST put it in the format of markdown code fence block with the language name of tool_call , e.g.
|
|
@@ -1222,35 +2045,52 @@ you MUST put it in the format of markdown code fence block with the language nam
|
|
|
1222
2045
|
\`\`\`
|
|
1223
2046
|
You SHOULD NOT include any other text in the response if you call a function
|
|
1224
2047
|
${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```"
|
|
2048
|
+
}
|
|
1231
2049
|
});
|
|
1232
2050
|
var hermesToolMiddleware = createToolMiddleware({
|
|
2051
|
+
protocol: jsonMixProtocol,
|
|
1233
2052
|
toolSystemPromptTemplate(tools) {
|
|
1234
2053
|
return `You are a function calling AI model.
|
|
1235
2054
|
You are provided with function signatures within <tools></tools> XML tags.
|
|
1236
2055
|
You may call one or more functions to assist with the user query.
|
|
1237
2056
|
Don't make assumptions about what values to plug into functions.
|
|
1238
2057
|
Here are the available tools: <tools>${tools}</tools>
|
|
1239
|
-
Use the following pydantic model json schema for each tool call you will make: {
|
|
2058
|
+
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
2059
|
For each function call return a json object with function name and arguments within <tool_call></tool_call> XML tags as follows:
|
|
1241
2060
|
<tool_call>
|
|
1242
|
-
{
|
|
2061
|
+
{"name": "<function-name>", "arguments": <args-dict>}
|
|
1243
2062
|
</tool_call>`;
|
|
1244
|
-
}
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
2063
|
+
}
|
|
2064
|
+
});
|
|
2065
|
+
var xmlToolMiddleware = createToolMiddleware({
|
|
2066
|
+
protocol: xmlProtocol,
|
|
2067
|
+
toolSystemPromptTemplate(tools) {
|
|
2068
|
+
return `You are a function calling AI model.
|
|
2069
|
+
You are provided with function signatures within <tools></tools> XML tags.
|
|
2070
|
+
You may call one or more functions to assist with the user query.
|
|
2071
|
+
Don't make assumptions about what values to plug into functions.
|
|
2072
|
+
Here are the available tools: <tools>${tools}</tools>
|
|
2073
|
+
For a function call, return exactly one XML element whose tag name matches the tool's name, and nothing else.
|
|
2074
|
+
When an argument is an array, write each item inside a single element on one line separated by commas (or provide a JSON-like list). When an argument is an object, provide a JSON-like value.
|
|
2075
|
+
Examples:
|
|
2076
|
+
<get_weather>
|
|
2077
|
+
<location>
|
|
2078
|
+
San Fransisco
|
|
2079
|
+
</location>
|
|
2080
|
+
</get_weather>`;
|
|
2081
|
+
}
|
|
1249
2082
|
});
|
|
1250
2083
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1251
2084
|
0 && (module.exports = {
|
|
2085
|
+
coerceBySchema,
|
|
1252
2086
|
createToolMiddleware,
|
|
2087
|
+
fixToolCallWithSchema,
|
|
1253
2088
|
gemmaToolMiddleware,
|
|
1254
|
-
|
|
2089
|
+
getSchemaType,
|
|
2090
|
+
hermesToolMiddleware,
|
|
2091
|
+
jsonMixProtocol,
|
|
2092
|
+
unwrapJsonSchema,
|
|
2093
|
+
xmlProtocol,
|
|
2094
|
+
xmlToolMiddleware
|
|
1255
2095
|
});
|
|
1256
2096
|
//# sourceMappingURL=index.cjs.map
|