@agentskit/adapters 0.7.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -5
- package/dist/index.cjs +763 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +335 -2
- package/dist/index.d.ts +335 -2
- package/dist/index.js +736 -1
- package/dist/index.js.map +1 -1
- package/package.json +23 -4
package/dist/index.cjs
CHANGED
|
@@ -777,6 +777,741 @@ function vercelAI(config) {
|
|
|
777
777
|
};
|
|
778
778
|
}
|
|
779
779
|
|
|
780
|
+
// src/mistral.ts
|
|
781
|
+
var mistral = createOpenAICompatibleAdapter("https://api.mistral.ai/v1");
|
|
782
|
+
|
|
783
|
+
// src/cohere.ts
|
|
784
|
+
var COHERE_BASE_URL = "https://api.cohere.com/compatibility/v1";
|
|
785
|
+
var DEFAULT_MODEL = "command-r-plus";
|
|
786
|
+
var baseFactory = createOpenAICompatibleAdapter(COHERE_BASE_URL);
|
|
787
|
+
function cohere(config) {
|
|
788
|
+
const factory = baseFactory({
|
|
789
|
+
model: DEFAULT_MODEL,
|
|
790
|
+
...config
|
|
791
|
+
});
|
|
792
|
+
return {
|
|
793
|
+
...factory,
|
|
794
|
+
capabilities: {
|
|
795
|
+
streaming: true,
|
|
796
|
+
tools: true,
|
|
797
|
+
usage: true
|
|
798
|
+
}
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
var cohereAdapter = cohere;
|
|
802
|
+
|
|
803
|
+
// src/together.ts
|
|
804
|
+
var together = createOpenAICompatibleAdapter("https://api.together.xyz/v1");
|
|
805
|
+
|
|
806
|
+
// src/groq.ts
|
|
807
|
+
var GROQ_BASE_URL = "https://api.groq.com/openai/v1";
|
|
808
|
+
var DEFAULT_MODEL2 = "llama-3.3-70b-versatile";
|
|
809
|
+
var baseFactory2 = createOpenAICompatibleAdapter(GROQ_BASE_URL);
|
|
810
|
+
function groq(config) {
|
|
811
|
+
const factory = baseFactory2({
|
|
812
|
+
model: DEFAULT_MODEL2,
|
|
813
|
+
...config
|
|
814
|
+
});
|
|
815
|
+
return {
|
|
816
|
+
...factory,
|
|
817
|
+
capabilities: {
|
|
818
|
+
streaming: true,
|
|
819
|
+
tools: true,
|
|
820
|
+
usage: true
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
var groqAdapter = groq;
|
|
825
|
+
|
|
826
|
+
// src/fireworks.ts
|
|
827
|
+
var fireworks = createOpenAICompatibleAdapter("https://api.fireworks.ai/inference/v1");
|
|
828
|
+
|
|
829
|
+
// src/openrouter.ts
|
|
830
|
+
var openrouter = createOpenAICompatibleAdapter("https://openrouter.ai/api/v1");
|
|
831
|
+
|
|
832
|
+
// src/huggingface.ts
|
|
833
|
+
var huggingface = createOpenAICompatibleAdapter("https://router.huggingface.co/v1");
|
|
834
|
+
|
|
835
|
+
// src/lmstudio.ts
|
|
836
|
+
var lmstudio = createOpenAICompatibleAdapter("http://localhost:1234/v1");
|
|
837
|
+
|
|
838
|
+
// src/vllm.ts
|
|
839
|
+
var vllm = createOpenAICompatibleAdapter("http://localhost:8000/v1");
|
|
840
|
+
|
|
841
|
+
// src/llamacpp.ts
|
|
842
|
+
var llamacpp = createOpenAICompatibleAdapter("http://localhost:8080/v1");
|
|
843
|
+
|
|
844
|
+
// src/cerebras.ts
|
|
845
|
+
var CEREBRAS_BASE_URL = "https://api.cerebras.ai/v1";
|
|
846
|
+
var DEFAULT_MODEL3 = "llama-3.3-70b";
|
|
847
|
+
var baseFactory3 = createOpenAICompatibleAdapter(CEREBRAS_BASE_URL);
|
|
848
|
+
function cerebras(config) {
|
|
849
|
+
const factory = baseFactory3({
|
|
850
|
+
model: DEFAULT_MODEL3,
|
|
851
|
+
...config
|
|
852
|
+
});
|
|
853
|
+
return {
|
|
854
|
+
...factory,
|
|
855
|
+
capabilities: {
|
|
856
|
+
streaming: true,
|
|
857
|
+
tools: true,
|
|
858
|
+
usage: true
|
|
859
|
+
}
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
var cerebrasAdapter = cerebras;
|
|
863
|
+
|
|
864
|
+
// src/azure-openai.ts
|
|
865
|
+
var DEFAULT_API_VERSION = "2024-10-21";
|
|
866
|
+
function azureOpenAI(config) {
|
|
867
|
+
const { apiKey, endpoint, deployment, apiVersion = DEFAULT_API_VERSION, retry } = config;
|
|
868
|
+
const includeUsage = config.includeUsage ?? true;
|
|
869
|
+
const url = `${endpoint.replace(/\/$/, "")}/openai/deployments/${encodeURIComponent(deployment)}/chat/completions?api-version=${encodeURIComponent(apiVersion)}`;
|
|
870
|
+
return {
|
|
871
|
+
capabilities: {
|
|
872
|
+
streaming: true,
|
|
873
|
+
tools: true,
|
|
874
|
+
usage: true
|
|
875
|
+
},
|
|
876
|
+
createSource: (request) => {
|
|
877
|
+
const body = {
|
|
878
|
+
messages: toProviderMessages(request.messages),
|
|
879
|
+
tools: request.context?.tools?.map((tool) => ({
|
|
880
|
+
type: "function",
|
|
881
|
+
function: {
|
|
882
|
+
name: tool.name,
|
|
883
|
+
description: tool.description,
|
|
884
|
+
parameters: tool.schema
|
|
885
|
+
}
|
|
886
|
+
})),
|
|
887
|
+
temperature: request.context?.temperature,
|
|
888
|
+
max_tokens: request.context?.maxTokens,
|
|
889
|
+
stream: true
|
|
890
|
+
};
|
|
891
|
+
if (includeUsage) body.stream_options = { include_usage: true };
|
|
892
|
+
return createStreamSource(
|
|
893
|
+
(signal) => fetch(url, {
|
|
894
|
+
method: "POST",
|
|
895
|
+
headers: {
|
|
896
|
+
"Content-Type": "application/json",
|
|
897
|
+
"api-key": apiKey
|
|
898
|
+
},
|
|
899
|
+
body: JSON.stringify(body),
|
|
900
|
+
signal
|
|
901
|
+
}),
|
|
902
|
+
parseOpenAIStream,
|
|
903
|
+
"Azure OpenAI API",
|
|
904
|
+
retry
|
|
905
|
+
);
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
var azureOpenAIAdapter = azureOpenAI;
|
|
910
|
+
|
|
911
|
+
// src/replicate.ts
|
|
912
|
+
var DEFAULT_BASE_URL = "https://api.replicate.com";
|
|
913
|
+
function defaultPrompt(request) {
|
|
914
|
+
return request.messages.map((m) => {
|
|
915
|
+
if (m.role === "system") return `[SYSTEM] ${m.content}`;
|
|
916
|
+
if (m.role === "assistant") return `[ASSISTANT] ${m.content}`;
|
|
917
|
+
return `[USER] ${m.content}`;
|
|
918
|
+
}).join("\n\n") + "\n\n[ASSISTANT] ";
|
|
919
|
+
}
|
|
920
|
+
async function* parseReplicateStream(stream) {
|
|
921
|
+
const reader = stream.getReader();
|
|
922
|
+
const decoder = new TextDecoder();
|
|
923
|
+
let buffer = "";
|
|
924
|
+
let currentEvent = "";
|
|
925
|
+
try {
|
|
926
|
+
while (true) {
|
|
927
|
+
const { done, value } = await reader.read();
|
|
928
|
+
if (done) break;
|
|
929
|
+
buffer += decoder.decode(value, { stream: true });
|
|
930
|
+
const lines = buffer.split("\n");
|
|
931
|
+
buffer = lines.pop() ?? "";
|
|
932
|
+
for (const line of lines) {
|
|
933
|
+
if (line.startsWith("event: ")) {
|
|
934
|
+
currentEvent = line.slice(7).trim();
|
|
935
|
+
continue;
|
|
936
|
+
}
|
|
937
|
+
if (!line.startsWith("data: ")) continue;
|
|
938
|
+
const data = line.slice(6);
|
|
939
|
+
if (currentEvent === "output" && data) {
|
|
940
|
+
yield { type: "text", content: data };
|
|
941
|
+
} else if (currentEvent === "done") {
|
|
942
|
+
yield { type: "done" };
|
|
943
|
+
return;
|
|
944
|
+
} else if (currentEvent === "error") {
|
|
945
|
+
yield { type: "error", content: data || "replicate stream error" };
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
} finally {
|
|
951
|
+
reader.releaseLock();
|
|
952
|
+
}
|
|
953
|
+
yield { type: "done" };
|
|
954
|
+
}
|
|
955
|
+
function replicate(config) {
|
|
956
|
+
const { apiKey, model, version, baseUrl = DEFAULT_BASE_URL, toInput = (r) => ({ prompt: defaultPrompt(r) }) } = config;
|
|
957
|
+
const predictionUrl = version ? `${baseUrl}/v1/predictions` : `${baseUrl}/v1/models/${model}/predictions`;
|
|
958
|
+
return {
|
|
959
|
+
capabilities: {
|
|
960
|
+
streaming: true,
|
|
961
|
+
tools: false
|
|
962
|
+
},
|
|
963
|
+
createSource: (request) => {
|
|
964
|
+
const controller = new AbortController();
|
|
965
|
+
let aborted = false;
|
|
966
|
+
return {
|
|
967
|
+
stream: async function* () {
|
|
968
|
+
if (aborted) return;
|
|
969
|
+
try {
|
|
970
|
+
const body = {
|
|
971
|
+
input: toInput(request),
|
|
972
|
+
stream: true
|
|
973
|
+
};
|
|
974
|
+
if (version) body.version = version;
|
|
975
|
+
const response = await fetch(predictionUrl, {
|
|
976
|
+
method: "POST",
|
|
977
|
+
headers: {
|
|
978
|
+
"Content-Type": "application/json",
|
|
979
|
+
"Authorization": `Bearer ${apiKey}`
|
|
980
|
+
},
|
|
981
|
+
body: JSON.stringify(body),
|
|
982
|
+
signal: controller.signal
|
|
983
|
+
});
|
|
984
|
+
if (!response.ok) {
|
|
985
|
+
yield { type: "error", content: `Replicate API error: ${response.status}` };
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
const prediction = await response.json();
|
|
989
|
+
if (prediction.error) {
|
|
990
|
+
yield { type: "error", content: prediction.error };
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
const streamUrl = prediction.urls?.stream;
|
|
994
|
+
if (!streamUrl) {
|
|
995
|
+
yield { type: "error", content: "Replicate prediction has no stream URL" };
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
998
|
+
const streamResponse = await fetch(streamUrl, {
|
|
999
|
+
method: "GET",
|
|
1000
|
+
headers: { Accept: "text/event-stream" },
|
|
1001
|
+
signal: controller.signal
|
|
1002
|
+
});
|
|
1003
|
+
if (!streamResponse.ok || !streamResponse.body) {
|
|
1004
|
+
yield { type: "error", content: `Replicate stream error: ${streamResponse.status}` };
|
|
1005
|
+
return;
|
|
1006
|
+
}
|
|
1007
|
+
for await (const chunk of parseReplicateStream(streamResponse.body)) {
|
|
1008
|
+
if (aborted) return;
|
|
1009
|
+
yield chunk;
|
|
1010
|
+
}
|
|
1011
|
+
} catch (err) {
|
|
1012
|
+
if (err instanceof DOMException && err.name === "AbortError") return;
|
|
1013
|
+
yield { type: "error", content: err instanceof Error ? err.message : String(err) };
|
|
1014
|
+
}
|
|
1015
|
+
},
|
|
1016
|
+
abort: () => {
|
|
1017
|
+
aborted = true;
|
|
1018
|
+
controller.abort();
|
|
1019
|
+
}
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
1024
|
+
var replicateAdapter = replicate;
|
|
1025
|
+
|
|
1026
|
+
// src/bail.ts
|
|
1027
|
+
var BAIL_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1";
|
|
1028
|
+
var DEFAULT_MODEL4 = "qwen-max";
|
|
1029
|
+
var baseFactory4 = createOpenAICompatibleAdapter(BAIL_BASE_URL);
|
|
1030
|
+
function bail(config) {
|
|
1031
|
+
const factory = baseFactory4({
|
|
1032
|
+
model: DEFAULT_MODEL4,
|
|
1033
|
+
...config
|
|
1034
|
+
});
|
|
1035
|
+
return {
|
|
1036
|
+
...factory,
|
|
1037
|
+
capabilities: {
|
|
1038
|
+
streaming: true,
|
|
1039
|
+
tools: true,
|
|
1040
|
+
multiModal: true,
|
|
1041
|
+
usage: true
|
|
1042
|
+
}
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
var bailAdapter = bail;
|
|
1046
|
+
var qwen = bail;
|
|
1047
|
+
|
|
1048
|
+
// src/vertex.ts
|
|
1049
|
+
function vertex(config) {
|
|
1050
|
+
const { project, region, model, accessToken, publisher = "google", retry } = config;
|
|
1051
|
+
const url = `https://${region}-aiplatform.googleapis.com/v1/projects/${project}/locations/${region}/publishers/${publisher}/models/${model}:streamGenerateContent?alt=sse`;
|
|
1052
|
+
return {
|
|
1053
|
+
capabilities: {
|
|
1054
|
+
streaming: true,
|
|
1055
|
+
tools: true,
|
|
1056
|
+
multiModal: true,
|
|
1057
|
+
usage: true,
|
|
1058
|
+
reasoning: model.includes("pro")
|
|
1059
|
+
},
|
|
1060
|
+
createSource: (request) => {
|
|
1061
|
+
const body = {
|
|
1062
|
+
contents: request.messages.filter((message) => message.role !== "system").map((message) => ({
|
|
1063
|
+
role: message.role === "assistant" ? "model" : "user",
|
|
1064
|
+
parts: [{ text: message.content }]
|
|
1065
|
+
})),
|
|
1066
|
+
systemInstruction: request.messages.find((message) => message.role === "system") ? {
|
|
1067
|
+
role: "system",
|
|
1068
|
+
parts: [{ text: request.messages.find((message) => message.role === "system").content }]
|
|
1069
|
+
} : void 0,
|
|
1070
|
+
tools: request.context?.tools && request.context.tools.length > 0 ? [{
|
|
1071
|
+
functionDeclarations: request.context.tools.map((tool) => ({
|
|
1072
|
+
name: tool.name,
|
|
1073
|
+
description: tool.description,
|
|
1074
|
+
parameters: tool.schema
|
|
1075
|
+
}))
|
|
1076
|
+
}] : void 0
|
|
1077
|
+
};
|
|
1078
|
+
return createStreamSource(
|
|
1079
|
+
async (signal) => {
|
|
1080
|
+
const token = typeof accessToken === "string" ? accessToken : await accessToken();
|
|
1081
|
+
return fetch(url, {
|
|
1082
|
+
method: "POST",
|
|
1083
|
+
headers: {
|
|
1084
|
+
"Content-Type": "application/json",
|
|
1085
|
+
"Authorization": `Bearer ${token}`
|
|
1086
|
+
},
|
|
1087
|
+
body: JSON.stringify(body),
|
|
1088
|
+
signal
|
|
1089
|
+
});
|
|
1090
|
+
},
|
|
1091
|
+
parseGeminiStream,
|
|
1092
|
+
"Vertex AI",
|
|
1093
|
+
retry
|
|
1094
|
+
);
|
|
1095
|
+
}
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
var vertexAdapter = vertex;
|
|
1099
|
+
|
|
1100
|
+
// src/bedrock.ts
|
|
1101
|
+
var cachedSdk = null;
|
|
1102
|
+
async function loadSdk() {
|
|
1103
|
+
if (!cachedSdk) {
|
|
1104
|
+
cachedSdk = (async () => {
|
|
1105
|
+
try {
|
|
1106
|
+
const moduleId = "@aws-sdk/client-bedrock-runtime";
|
|
1107
|
+
return await import(
|
|
1108
|
+
/* @vite-ignore */
|
|
1109
|
+
moduleId
|
|
1110
|
+
);
|
|
1111
|
+
} catch {
|
|
1112
|
+
throw new Error(
|
|
1113
|
+
"Install @aws-sdk/client-bedrock-runtime to use the bedrock adapter: npm install @aws-sdk/client-bedrock-runtime"
|
|
1114
|
+
);
|
|
1115
|
+
}
|
|
1116
|
+
})();
|
|
1117
|
+
}
|
|
1118
|
+
return cachedSdk;
|
|
1119
|
+
}
|
|
1120
|
+
function isAnthropicModel(model) {
|
|
1121
|
+
return model.startsWith("anthropic.");
|
|
1122
|
+
}
|
|
1123
|
+
function buildAnthropicBody(request, maxTokens) {
|
|
1124
|
+
const messages = request.messages.filter((m) => m.role !== "system").map((m) => ({ role: m.role, content: m.content }));
|
|
1125
|
+
const system = request.messages.find((m) => m.role === "system")?.content;
|
|
1126
|
+
const tools = request.context?.tools?.map((tool) => ({
|
|
1127
|
+
name: tool.name,
|
|
1128
|
+
description: tool.description,
|
|
1129
|
+
input_schema: tool.schema
|
|
1130
|
+
}));
|
|
1131
|
+
const body = {
|
|
1132
|
+
anthropic_version: "bedrock-2023-05-31",
|
|
1133
|
+
max_tokens: request.context?.maxTokens ?? maxTokens,
|
|
1134
|
+
messages
|
|
1135
|
+
};
|
|
1136
|
+
if (system) body.system = system;
|
|
1137
|
+
if (tools && tools.length > 0) body.tools = tools;
|
|
1138
|
+
return JSON.stringify(body);
|
|
1139
|
+
}
|
|
1140
|
+
async function* parseAnthropicBedrockEvents(events) {
|
|
1141
|
+
const decoder = new TextDecoder();
|
|
1142
|
+
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
1143
|
+
for await (const item of events) {
|
|
1144
|
+
const bytes = item.chunk?.bytes;
|
|
1145
|
+
if (!bytes) continue;
|
|
1146
|
+
let event;
|
|
1147
|
+
try {
|
|
1148
|
+
event = JSON.parse(decoder.decode(bytes));
|
|
1149
|
+
} catch {
|
|
1150
|
+
continue;
|
|
1151
|
+
}
|
|
1152
|
+
const type = event.type;
|
|
1153
|
+
if (type === "content_block_delta") {
|
|
1154
|
+
const delta = event.delta;
|
|
1155
|
+
if (delta?.type === "text_delta" && delta.text) {
|
|
1156
|
+
yield { type: "text", content: delta.text };
|
|
1157
|
+
} else if (delta?.type === "input_json_delta") {
|
|
1158
|
+
const index = event.index ?? 0;
|
|
1159
|
+
const existing = pendingToolCalls.get(index);
|
|
1160
|
+
if (existing) existing.args += delta.partial_json ?? "";
|
|
1161
|
+
}
|
|
1162
|
+
} else if (type === "content_block_start") {
|
|
1163
|
+
const index = event.index ?? 0;
|
|
1164
|
+
const block = event.content_block;
|
|
1165
|
+
if (block?.type === "tool_use" && block.id && block.name) {
|
|
1166
|
+
pendingToolCalls.set(index, { id: block.id, name: block.name, args: "" });
|
|
1167
|
+
}
|
|
1168
|
+
} else if (type === "content_block_stop") {
|
|
1169
|
+
const index = event.index ?? 0;
|
|
1170
|
+
const tc = pendingToolCalls.get(index);
|
|
1171
|
+
if (tc) {
|
|
1172
|
+
yield { type: "tool_call", toolCall: { id: tc.id, name: tc.name, args: tc.args || "{}" } };
|
|
1173
|
+
pendingToolCalls.delete(index);
|
|
1174
|
+
}
|
|
1175
|
+
} else if (type === "message_delta") {
|
|
1176
|
+
const usage = event.usage;
|
|
1177
|
+
if (usage) {
|
|
1178
|
+
const promptTokens = usage.input_tokens ?? 0;
|
|
1179
|
+
const completionTokens = usage.output_tokens ?? 0;
|
|
1180
|
+
yield {
|
|
1181
|
+
type: "usage",
|
|
1182
|
+
usage: { promptTokens, completionTokens, totalTokens: promptTokens + completionTokens }
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
} else if (type === "message_start") {
|
|
1186
|
+
const usage = event.message?.usage;
|
|
1187
|
+
if (usage) {
|
|
1188
|
+
yield {
|
|
1189
|
+
type: "usage",
|
|
1190
|
+
usage: {
|
|
1191
|
+
promptTokens: usage.input_tokens ?? 0,
|
|
1192
|
+
completionTokens: 0,
|
|
1193
|
+
totalTokens: usage.input_tokens ?? 0
|
|
1194
|
+
}
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
} else if (type === "message_stop") {
|
|
1198
|
+
for (const [, tc] of pendingToolCalls) {
|
|
1199
|
+
yield { type: "tool_call", toolCall: { id: tc.id, name: tc.name, args: tc.args || "{}" } };
|
|
1200
|
+
}
|
|
1201
|
+
pendingToolCalls.clear();
|
|
1202
|
+
yield { type: "done" };
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
for (const [, tc] of pendingToolCalls) {
|
|
1207
|
+
yield { type: "tool_call", toolCall: { id: tc.id, name: tc.name, args: tc.args || "{}" } };
|
|
1208
|
+
}
|
|
1209
|
+
pendingToolCalls.clear();
|
|
1210
|
+
yield { type: "done" };
|
|
1211
|
+
}
|
|
1212
|
+
function bedrock(config) {
|
|
1213
|
+
const { model, region, maxTokens = 4096 } = config;
|
|
1214
|
+
if (!isAnthropicModel(model)) {
|
|
1215
|
+
throw new Error(
|
|
1216
|
+
`bedrock: model "${model}" is not supported in v1. Only anthropic.* models are wired up; Titan + others are tracked as a follow-up.`
|
|
1217
|
+
);
|
|
1218
|
+
}
|
|
1219
|
+
let clientPromise = null;
|
|
1220
|
+
const getClient = async () => {
|
|
1221
|
+
if (config.client) return config.client;
|
|
1222
|
+
if (!clientPromise) {
|
|
1223
|
+
clientPromise = (async () => {
|
|
1224
|
+
const sdk = await loadSdk();
|
|
1225
|
+
return new sdk.BedrockRuntimeClient({ region });
|
|
1226
|
+
})();
|
|
1227
|
+
}
|
|
1228
|
+
return clientPromise;
|
|
1229
|
+
};
|
|
1230
|
+
return {
|
|
1231
|
+
capabilities: {
|
|
1232
|
+
streaming: true,
|
|
1233
|
+
tools: true,
|
|
1234
|
+
reasoning: model.includes("sonnet") || model.includes("opus"),
|
|
1235
|
+
multiModal: true,
|
|
1236
|
+
usage: true
|
|
1237
|
+
},
|
|
1238
|
+
createSource: (request) => {
|
|
1239
|
+
const controller = new AbortController();
|
|
1240
|
+
let aborted = false;
|
|
1241
|
+
return {
|
|
1242
|
+
stream: async function* () {
|
|
1243
|
+
if (aborted) return;
|
|
1244
|
+
try {
|
|
1245
|
+
const client = await getClient();
|
|
1246
|
+
const sdk = config.client ? null : await loadSdk();
|
|
1247
|
+
const input = {
|
|
1248
|
+
modelId: model,
|
|
1249
|
+
contentType: "application/json",
|
|
1250
|
+
accept: "application/json",
|
|
1251
|
+
body: buildAnthropicBody(request, maxTokens)
|
|
1252
|
+
};
|
|
1253
|
+
const command = sdk ? new sdk.InvokeModelWithResponseStreamCommand(input) : { input };
|
|
1254
|
+
const response = await client.send(command);
|
|
1255
|
+
if (!response.body) {
|
|
1256
|
+
yield { type: "error", content: "Bedrock: empty response body" };
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1259
|
+
for await (const chunk of parseAnthropicBedrockEvents(response.body)) {
|
|
1260
|
+
if (aborted) return;
|
|
1261
|
+
yield chunk;
|
|
1262
|
+
}
|
|
1263
|
+
} catch (err) {
|
|
1264
|
+
yield { type: "error", content: err instanceof Error ? err.message : String(err) };
|
|
1265
|
+
}
|
|
1266
|
+
},
|
|
1267
|
+
abort: () => {
|
|
1268
|
+
aborted = true;
|
|
1269
|
+
controller.abort();
|
|
1270
|
+
}
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
};
|
|
1274
|
+
}
|
|
1275
|
+
var bedrockAdapter = bedrock;
|
|
1276
|
+
|
|
1277
|
+
// src/router.ts
|
|
1278
|
+
function requireCapabilities(request) {
|
|
1279
|
+
const needs = {};
|
|
1280
|
+
if (request.context?.tools && request.context.tools.length > 0) needs.tools = true;
|
|
1281
|
+
return needs;
|
|
1282
|
+
}
|
|
1283
|
+
function matchesCapabilities(need, have) {
|
|
1284
|
+
if (!have) return true;
|
|
1285
|
+
for (const key of Object.keys(need)) {
|
|
1286
|
+
if (key === "extensions") continue;
|
|
1287
|
+
if (need[key] && have[key] === false) return false;
|
|
1288
|
+
}
|
|
1289
|
+
return true;
|
|
1290
|
+
}
|
|
1291
|
+
function pickSyncPolicy(pool, policy) {
|
|
1292
|
+
if (policy === "cheapest") {
|
|
1293
|
+
const c = pool.reduce((best, x) => (x.cost ?? Infinity) < (best.cost ?? Infinity) ? x : best, pool[0]);
|
|
1294
|
+
return { c, reason: "cheapest" };
|
|
1295
|
+
}
|
|
1296
|
+
if (policy === "fastest") {
|
|
1297
|
+
const c = pool.reduce((best, x) => (x.latencyMs ?? Infinity) < (best.latencyMs ?? Infinity) ? x : best, pool[0]);
|
|
1298
|
+
return { c, reason: "fastest" };
|
|
1299
|
+
}
|
|
1300
|
+
return { c: pool[0], reason: "capability-match" };
|
|
1301
|
+
}
|
|
1302
|
+
function createRouter(options) {
|
|
1303
|
+
const { candidates } = options;
|
|
1304
|
+
if (candidates.length === 0) throw new Error("createRouter requires at least one candidate");
|
|
1305
|
+
const policy = options.policy ?? "cheapest";
|
|
1306
|
+
return {
|
|
1307
|
+
createSource: (request) => {
|
|
1308
|
+
const need = requireCapabilities(request);
|
|
1309
|
+
const capable = candidates.filter((c2) => matchesCapabilities(need, c2.capabilities ?? c2.adapter.capabilities));
|
|
1310
|
+
const classified = options.classify?.(request);
|
|
1311
|
+
if (typeof classified === "string") {
|
|
1312
|
+
const c2 = capable.find((x) => x.id === classified);
|
|
1313
|
+
if (c2) {
|
|
1314
|
+
options.onRoute?.({ id: c2.id, reason: "classify:id", request });
|
|
1315
|
+
return c2.adapter.createSource(request);
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
let pool = capable;
|
|
1319
|
+
let pickedBy;
|
|
1320
|
+
if (Array.isArray(classified) && classified.length > 0) {
|
|
1321
|
+
const filtered = capable.filter((c2) => c2.tags && classified.every((t) => c2.tags.includes(t)));
|
|
1322
|
+
if (filtered.length > 0) {
|
|
1323
|
+
pool = filtered;
|
|
1324
|
+
pickedBy = "classify:tags";
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
if (pool.length === 0) throw new Error("no candidate satisfies the request");
|
|
1328
|
+
if (typeof policy === "function") {
|
|
1329
|
+
const maybe = policy({ request, candidates: pool });
|
|
1330
|
+
if (maybe instanceof Promise) {
|
|
1331
|
+
return {
|
|
1332
|
+
abort: () => {
|
|
1333
|
+
},
|
|
1334
|
+
stream: async function* () {
|
|
1335
|
+
const id = await maybe;
|
|
1336
|
+
const c3 = pool.find((x) => x.id === id);
|
|
1337
|
+
if (!c3) throw new Error(`policy returned unknown id: ${id}`);
|
|
1338
|
+
options.onRoute?.({ id: c3.id, reason: pickedBy ?? "custom policy", request });
|
|
1339
|
+
for await (const chunk of c3.adapter.createSource(request).stream()) yield chunk;
|
|
1340
|
+
}
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
const c2 = pool.find((x) => x.id === maybe);
|
|
1344
|
+
if (!c2) throw new Error(`policy returned unknown id: ${maybe}`);
|
|
1345
|
+
options.onRoute?.({ id: c2.id, reason: pickedBy ?? "custom policy", request });
|
|
1346
|
+
return c2.adapter.createSource(request);
|
|
1347
|
+
}
|
|
1348
|
+
const { c, reason } = pickSyncPolicy(pool, policy);
|
|
1349
|
+
options.onRoute?.({ id: c.id, reason: pickedBy ?? reason, request });
|
|
1350
|
+
return c.adapter.createSource(request);
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
// src/ensemble.ts
|
|
1356
|
+
async function drain(source, timeoutMs) {
|
|
1357
|
+
const chunks = [];
|
|
1358
|
+
let text = "";
|
|
1359
|
+
let timer;
|
|
1360
|
+
let timedOut = false;
|
|
1361
|
+
let error;
|
|
1362
|
+
if (timeoutMs !== void 0) {
|
|
1363
|
+
timer = setTimeout(() => {
|
|
1364
|
+
timedOut = true;
|
|
1365
|
+
source.abort();
|
|
1366
|
+
}, timeoutMs);
|
|
1367
|
+
}
|
|
1368
|
+
try {
|
|
1369
|
+
for await (const chunk of source.stream()) {
|
|
1370
|
+
chunks.push(chunk);
|
|
1371
|
+
if (chunk.type === "text" && typeof chunk.content === "string") text += chunk.content;
|
|
1372
|
+
}
|
|
1373
|
+
} catch (err) {
|
|
1374
|
+
error = err instanceof Error ? err : new Error(String(err));
|
|
1375
|
+
} finally {
|
|
1376
|
+
if (timer) clearTimeout(timer);
|
|
1377
|
+
}
|
|
1378
|
+
if (timedOut) error = new Error(`timeout after ${timeoutMs}ms`);
|
|
1379
|
+
return { chunks, text, error };
|
|
1380
|
+
}
|
|
1381
|
+
function majorityVote(branches, candidates) {
|
|
1382
|
+
const counts = /* @__PURE__ */ new Map();
|
|
1383
|
+
const weightById = new Map(candidates.map((c) => [c.id, c.weight ?? 1]));
|
|
1384
|
+
for (const b of branches) {
|
|
1385
|
+
if (b.error) continue;
|
|
1386
|
+
counts.set(b.text, (counts.get(b.text) ?? 0) + (weightById.get(b.id) ?? 1));
|
|
1387
|
+
}
|
|
1388
|
+
let best = "";
|
|
1389
|
+
let bestScore = -1;
|
|
1390
|
+
for (const [text, score] of counts) {
|
|
1391
|
+
if (score > bestScore) {
|
|
1392
|
+
bestScore = score;
|
|
1393
|
+
best = text;
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
return best;
|
|
1397
|
+
}
|
|
1398
|
+
function createEnsembleAdapter(options) {
|
|
1399
|
+
if (options.candidates.length === 0) {
|
|
1400
|
+
throw new Error("createEnsembleAdapter requires at least one candidate");
|
|
1401
|
+
}
|
|
1402
|
+
const aggregate = options.aggregate ?? "majority-vote";
|
|
1403
|
+
return {
|
|
1404
|
+
createSource: (request) => {
|
|
1405
|
+
let aborted = false;
|
|
1406
|
+
const sources = [];
|
|
1407
|
+
const run = async () => {
|
|
1408
|
+
const tasks = options.candidates.map(async (c, i) => {
|
|
1409
|
+
const source = c.adapter.createSource(request);
|
|
1410
|
+
sources[i] = source;
|
|
1411
|
+
const { chunks, text, error } = await drain(source, options.timeoutMs);
|
|
1412
|
+
return { id: c.id, chunks, text, error };
|
|
1413
|
+
});
|
|
1414
|
+
return Promise.all(tasks);
|
|
1415
|
+
};
|
|
1416
|
+
const finalText = async (branches) => {
|
|
1417
|
+
if (typeof aggregate === "function") return aggregate(branches);
|
|
1418
|
+
if (aggregate === "concat") {
|
|
1419
|
+
return branches.filter((b) => !b.error).map((b) => b.text).join("\n---\n");
|
|
1420
|
+
}
|
|
1421
|
+
if (aggregate === "longest") {
|
|
1422
|
+
return branches.filter((b) => !b.error).reduce(
|
|
1423
|
+
(best, b) => b.text.length > best.length ? b.text : best,
|
|
1424
|
+
""
|
|
1425
|
+
);
|
|
1426
|
+
}
|
|
1427
|
+
return majorityVote(branches, options.candidates);
|
|
1428
|
+
};
|
|
1429
|
+
return {
|
|
1430
|
+
abort: () => {
|
|
1431
|
+
aborted = true;
|
|
1432
|
+
for (const s of sources) s?.abort();
|
|
1433
|
+
},
|
|
1434
|
+
stream: async function* () {
|
|
1435
|
+
const branches = await run();
|
|
1436
|
+
options.onBranches?.(branches);
|
|
1437
|
+
if (aborted) return;
|
|
1438
|
+
const text = await finalText(branches);
|
|
1439
|
+
if (!text && branches.every((b) => b.error)) {
|
|
1440
|
+
throw new Error("all ensemble branches failed");
|
|
1441
|
+
}
|
|
1442
|
+
yield { type: "text", content: text, metadata: { ensemble: branches.map((b) => ({ id: b.id, bytes: b.text.length, error: b.error?.message })) } };
|
|
1443
|
+
yield { type: "done" };
|
|
1444
|
+
}
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
};
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
// src/fallback.ts
|
|
1451
|
+
function createFallbackAdapter(candidates, options = {}) {
|
|
1452
|
+
if (candidates.length === 0) {
|
|
1453
|
+
throw new Error("createFallbackAdapter requires at least one candidate");
|
|
1454
|
+
}
|
|
1455
|
+
return {
|
|
1456
|
+
createSource: (request) => {
|
|
1457
|
+
let active;
|
|
1458
|
+
let aborted = false;
|
|
1459
|
+
return {
|
|
1460
|
+
abort: () => {
|
|
1461
|
+
aborted = true;
|
|
1462
|
+
active?.abort();
|
|
1463
|
+
},
|
|
1464
|
+
stream: async function* () {
|
|
1465
|
+
const errors = [];
|
|
1466
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
1467
|
+
if (aborted) return;
|
|
1468
|
+
const candidate = candidates[i];
|
|
1469
|
+
let source;
|
|
1470
|
+
try {
|
|
1471
|
+
source = candidate.adapter.createSource(request);
|
|
1472
|
+
} catch (err) {
|
|
1473
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1474
|
+
errors.push({ id: candidate.id, error });
|
|
1475
|
+
options.onFallback?.({ id: candidate.id, index: i, error });
|
|
1476
|
+
if (options.shouldRetry && !options.shouldRetry(error, i)) throw error;
|
|
1477
|
+
continue;
|
|
1478
|
+
}
|
|
1479
|
+
active = source;
|
|
1480
|
+
const iter = source.stream()[Symbol.asyncIterator]();
|
|
1481
|
+
let first;
|
|
1482
|
+
try {
|
|
1483
|
+
first = await iter.next();
|
|
1484
|
+
} catch (err) {
|
|
1485
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1486
|
+
errors.push({ id: candidate.id, error });
|
|
1487
|
+
options.onFallback?.({ id: candidate.id, index: i, error });
|
|
1488
|
+
if (options.shouldRetry && !options.shouldRetry(error, i)) throw error;
|
|
1489
|
+
active = void 0;
|
|
1490
|
+
continue;
|
|
1491
|
+
}
|
|
1492
|
+
if (first.done) {
|
|
1493
|
+
const error = new Error(`candidate ${candidate.id} emitted no chunks`);
|
|
1494
|
+
errors.push({ id: candidate.id, error });
|
|
1495
|
+
options.onFallback?.({ id: candidate.id, index: i, error });
|
|
1496
|
+
if (options.shouldRetry && !options.shouldRetry(error, i)) throw error;
|
|
1497
|
+
active = void 0;
|
|
1498
|
+
continue;
|
|
1499
|
+
}
|
|
1500
|
+
yield first.value;
|
|
1501
|
+
while (true) {
|
|
1502
|
+
const next = await iter.next();
|
|
1503
|
+
if (next.done) return;
|
|
1504
|
+
yield next.value;
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
const summary = errors.map((e) => `${e.id}: ${e.error.message}`).join("; ");
|
|
1508
|
+
throw new Error(`all fallback candidates failed (${summary})`);
|
|
1509
|
+
}
|
|
1510
|
+
};
|
|
1511
|
+
}
|
|
1512
|
+
};
|
|
1513
|
+
}
|
|
1514
|
+
|
|
780
1515
|
// src/mock.ts
|
|
781
1516
|
function mockAdapter(options) {
|
|
782
1517
|
const { response, delayMs = 0, history } = options;
|
|
@@ -1064,30 +1799,58 @@ var grokEmbedder = createOpenAICompatibleEmbedder("Grok", "https://api.x.ai");
|
|
|
1064
1799
|
var kimiEmbedder = createOpenAICompatibleEmbedder("Kimi", "https://api.moonshot.ai");
|
|
1065
1800
|
|
|
1066
1801
|
exports.anthropic = anthropic;
|
|
1802
|
+
exports.azureOpenAI = azureOpenAI;
|
|
1803
|
+
exports.azureOpenAIAdapter = azureOpenAIAdapter;
|
|
1804
|
+
exports.bail = bail;
|
|
1805
|
+
exports.bailAdapter = bailAdapter;
|
|
1806
|
+
exports.bedrock = bedrock;
|
|
1807
|
+
exports.bedrockAdapter = bedrockAdapter;
|
|
1808
|
+
exports.cerebras = cerebras;
|
|
1809
|
+
exports.cerebrasAdapter = cerebrasAdapter;
|
|
1067
1810
|
exports.chunkText = chunkText;
|
|
1811
|
+
exports.cohere = cohere;
|
|
1812
|
+
exports.cohereAdapter = cohereAdapter;
|
|
1068
1813
|
exports.createAdapter = createAdapter;
|
|
1814
|
+
exports.createEnsembleAdapter = createEnsembleAdapter;
|
|
1815
|
+
exports.createFallbackAdapter = createFallbackAdapter;
|
|
1069
1816
|
exports.createOpenAICompatibleEmbedder = createOpenAICompatibleEmbedder;
|
|
1817
|
+
exports.createRouter = createRouter;
|
|
1070
1818
|
exports.deepseek = deepseek;
|
|
1071
1819
|
exports.deepseekEmbedder = deepseekEmbedder;
|
|
1072
1820
|
exports.fetchWithRetry = fetchWithRetry;
|
|
1821
|
+
exports.fireworks = fireworks;
|
|
1073
1822
|
exports.gemini = gemini;
|
|
1074
1823
|
exports.geminiEmbedder = geminiEmbedder;
|
|
1075
1824
|
exports.generic = generic;
|
|
1076
1825
|
exports.grok = grok;
|
|
1077
1826
|
exports.grokEmbedder = grokEmbedder;
|
|
1827
|
+
exports.groq = groq;
|
|
1828
|
+
exports.groqAdapter = groqAdapter;
|
|
1829
|
+
exports.huggingface = huggingface;
|
|
1078
1830
|
exports.inMemorySink = inMemorySink;
|
|
1079
1831
|
exports.kimi = kimi;
|
|
1080
1832
|
exports.kimiEmbedder = kimiEmbedder;
|
|
1081
1833
|
exports.langchain = langchain;
|
|
1082
1834
|
exports.langgraph = langgraph;
|
|
1835
|
+
exports.llamacpp = llamacpp;
|
|
1836
|
+
exports.lmstudio = lmstudio;
|
|
1837
|
+
exports.mistral = mistral;
|
|
1083
1838
|
exports.mockAdapter = mockAdapter;
|
|
1084
1839
|
exports.ollama = ollama;
|
|
1085
1840
|
exports.ollamaEmbedder = ollamaEmbedder;
|
|
1086
1841
|
exports.openai = openai;
|
|
1087
1842
|
exports.openaiEmbedder = openaiEmbedder;
|
|
1843
|
+
exports.openrouter = openrouter;
|
|
1844
|
+
exports.qwen = qwen;
|
|
1088
1845
|
exports.recordingAdapter = recordingAdapter;
|
|
1089
1846
|
exports.replayAdapter = replayAdapter;
|
|
1847
|
+
exports.replicate = replicate;
|
|
1848
|
+
exports.replicateAdapter = replicateAdapter;
|
|
1090
1849
|
exports.simulateStream = simulateStream;
|
|
1850
|
+
exports.together = together;
|
|
1091
1851
|
exports.vercelAI = vercelAI;
|
|
1852
|
+
exports.vertex = vertex;
|
|
1853
|
+
exports.vertexAdapter = vertexAdapter;
|
|
1854
|
+
exports.vllm = vllm;
|
|
1092
1855
|
//# sourceMappingURL=index.cjs.map
|
|
1093
1856
|
//# sourceMappingURL=index.cjs.map
|