@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/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