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