@agentskit/adapters 0.11.0 → 0.12.2
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 +94 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +94 -39
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ConfigError, ErrorCodes, AdapterError } from '@agentskit/core';
|
|
2
|
+
|
|
1
3
|
// src/createAdapter.ts
|
|
2
4
|
function createAdapter(config) {
|
|
3
5
|
return {
|
|
@@ -1094,8 +1096,6 @@ function vertex(config) {
|
|
|
1094
1096
|
};
|
|
1095
1097
|
}
|
|
1096
1098
|
var vertexAdapter = vertex;
|
|
1097
|
-
|
|
1098
|
-
// src/bedrock.ts
|
|
1099
1099
|
var cachedSdk = null;
|
|
1100
1100
|
async function loadSdk() {
|
|
1101
1101
|
if (!cachedSdk) {
|
|
@@ -1107,9 +1107,11 @@ async function loadSdk() {
|
|
|
1107
1107
|
moduleId
|
|
1108
1108
|
);
|
|
1109
1109
|
} catch {
|
|
1110
|
-
throw new
|
|
1111
|
-
|
|
1112
|
-
|
|
1110
|
+
throw new AdapterError({
|
|
1111
|
+
code: ErrorCodes.AK_ADAPTER_MISSING,
|
|
1112
|
+
message: "Install @aws-sdk/client-bedrock-runtime to use the bedrock adapter: npm install @aws-sdk/client-bedrock-runtime",
|
|
1113
|
+
hint: "bedrock depends on the optional peer @aws-sdk/client-bedrock-runtime."
|
|
1114
|
+
});
|
|
1113
1115
|
}
|
|
1114
1116
|
})();
|
|
1115
1117
|
}
|
|
@@ -1210,9 +1212,11 @@ async function* parseAnthropicBedrockEvents(events) {
|
|
|
1210
1212
|
function bedrock(config) {
|
|
1211
1213
|
const { model, region, maxTokens = 4096 } = config;
|
|
1212
1214
|
if (!isAnthropicModel(model)) {
|
|
1213
|
-
throw new
|
|
1214
|
-
|
|
1215
|
-
|
|
1215
|
+
throw new ConfigError({
|
|
1216
|
+
code: ErrorCodes.AK_CONFIG_INVALID,
|
|
1217
|
+
message: `bedrock: model "${model}" is not supported in v1. Only anthropic.* models are wired up; Titan + others are tracked as a follow-up.`,
|
|
1218
|
+
hint: 'Pass an anthropic.* model id like "anthropic.claude-3-5-sonnet-20241022-v2:0".'
|
|
1219
|
+
});
|
|
1216
1220
|
}
|
|
1217
1221
|
let clientPromise = null;
|
|
1218
1222
|
const getClient = async () => {
|
|
@@ -1271,8 +1275,6 @@ function bedrock(config) {
|
|
|
1271
1275
|
};
|
|
1272
1276
|
}
|
|
1273
1277
|
var bedrockAdapter = bedrock;
|
|
1274
|
-
|
|
1275
|
-
// src/webllm.ts
|
|
1276
1278
|
var cachedSdk2 = null;
|
|
1277
1279
|
async function loadSdk2() {
|
|
1278
1280
|
if (!cachedSdk2) {
|
|
@@ -1284,7 +1286,11 @@ async function loadSdk2() {
|
|
|
1284
1286
|
moduleId
|
|
1285
1287
|
);
|
|
1286
1288
|
} catch {
|
|
1287
|
-
throw new
|
|
1289
|
+
throw new AdapterError({
|
|
1290
|
+
code: ErrorCodes.AK_ADAPTER_MISSING,
|
|
1291
|
+
message: "Install @mlc-ai/web-llm to use the webllm adapter: npm install @mlc-ai/web-llm",
|
|
1292
|
+
hint: "webllm is browser-only and depends on the optional peer @mlc-ai/web-llm."
|
|
1293
|
+
});
|
|
1288
1294
|
}
|
|
1289
1295
|
})();
|
|
1290
1296
|
}
|
|
@@ -1334,8 +1340,6 @@ function webllm(config) {
|
|
|
1334
1340
|
};
|
|
1335
1341
|
}
|
|
1336
1342
|
var webllmAdapter = webllm;
|
|
1337
|
-
|
|
1338
|
-
// src/router.ts
|
|
1339
1343
|
function requireCapabilities(request) {
|
|
1340
1344
|
const needs = {};
|
|
1341
1345
|
if (request.context?.tools && request.context.tools.length > 0) needs.tools = true;
|
|
@@ -1362,7 +1366,13 @@ function pickSyncPolicy(pool, policy) {
|
|
|
1362
1366
|
}
|
|
1363
1367
|
function createRouter(options) {
|
|
1364
1368
|
const { candidates } = options;
|
|
1365
|
-
if (candidates.length === 0)
|
|
1369
|
+
if (candidates.length === 0) {
|
|
1370
|
+
throw new ConfigError({
|
|
1371
|
+
code: ErrorCodes.AK_CONFIG_INVALID,
|
|
1372
|
+
message: "createRouter requires at least one candidate",
|
|
1373
|
+
hint: "Pass at least one candidate, e.g. createRouter({ candidates: [{ id, adapter, capabilities }] })."
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1366
1376
|
const policy = options.policy ?? "cheapest";
|
|
1367
1377
|
return {
|
|
1368
1378
|
createSource: (request) => {
|
|
@@ -1385,7 +1395,13 @@ function createRouter(options) {
|
|
|
1385
1395
|
pickedBy = "classify:tags";
|
|
1386
1396
|
}
|
|
1387
1397
|
}
|
|
1388
|
-
if (pool.length === 0)
|
|
1398
|
+
if (pool.length === 0) {
|
|
1399
|
+
throw new AdapterError({
|
|
1400
|
+
code: ErrorCodes.AK_ADAPTER_STREAM_FAILED,
|
|
1401
|
+
message: "no candidate satisfies the request",
|
|
1402
|
+
hint: "Ensure at least one candidate declares the required capabilities (tools, json, etc.)."
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1389
1405
|
if (typeof policy === "function") {
|
|
1390
1406
|
const maybe = policy({ request, candidates: pool });
|
|
1391
1407
|
if (maybe instanceof Promise) {
|
|
@@ -1395,14 +1411,26 @@ function createRouter(options) {
|
|
|
1395
1411
|
stream: async function* () {
|
|
1396
1412
|
const id = await maybe;
|
|
1397
1413
|
const c3 = pool.find((x) => x.id === id);
|
|
1398
|
-
if (!c3)
|
|
1414
|
+
if (!c3) {
|
|
1415
|
+
throw new ConfigError({
|
|
1416
|
+
code: ErrorCodes.AK_CONFIG_INVALID,
|
|
1417
|
+
message: `policy returned unknown id: ${id}`,
|
|
1418
|
+
hint: "Custom policy functions must return one of the candidate ids."
|
|
1419
|
+
});
|
|
1420
|
+
}
|
|
1399
1421
|
options.onRoute?.({ id: c3.id, reason: pickedBy ?? "custom policy", request });
|
|
1400
1422
|
for await (const chunk of c3.adapter.createSource(request).stream()) yield chunk;
|
|
1401
1423
|
}
|
|
1402
1424
|
};
|
|
1403
1425
|
}
|
|
1404
1426
|
const c2 = pool.find((x) => x.id === maybe);
|
|
1405
|
-
if (!c2)
|
|
1427
|
+
if (!c2) {
|
|
1428
|
+
throw new ConfigError({
|
|
1429
|
+
code: ErrorCodes.AK_CONFIG_INVALID,
|
|
1430
|
+
message: `policy returned unknown id: ${maybe}`,
|
|
1431
|
+
hint: "Custom policy functions must return one of the candidate ids."
|
|
1432
|
+
});
|
|
1433
|
+
}
|
|
1406
1434
|
options.onRoute?.({ id: c2.id, reason: pickedBy ?? "custom policy", request });
|
|
1407
1435
|
return c2.adapter.createSource(request);
|
|
1408
1436
|
}
|
|
@@ -1412,8 +1440,6 @@ function createRouter(options) {
|
|
|
1412
1440
|
}
|
|
1413
1441
|
};
|
|
1414
1442
|
}
|
|
1415
|
-
|
|
1416
|
-
// src/ensemble.ts
|
|
1417
1443
|
async function drain(source, timeoutMs) {
|
|
1418
1444
|
const chunks = [];
|
|
1419
1445
|
let text = "";
|
|
@@ -1458,7 +1484,11 @@ function majorityVote(branches, candidates) {
|
|
|
1458
1484
|
}
|
|
1459
1485
|
function createEnsembleAdapter(options) {
|
|
1460
1486
|
if (options.candidates.length === 0) {
|
|
1461
|
-
throw new
|
|
1487
|
+
throw new ConfigError({
|
|
1488
|
+
code: ErrorCodes.AK_CONFIG_INVALID,
|
|
1489
|
+
message: "createEnsembleAdapter requires at least one candidate",
|
|
1490
|
+
hint: "Pass at least one candidate, e.g. createEnsembleAdapter({ candidates: [{ id, adapter }] })."
|
|
1491
|
+
});
|
|
1462
1492
|
}
|
|
1463
1493
|
const aggregate = options.aggregate ?? "majority-vote";
|
|
1464
1494
|
return {
|
|
@@ -1498,7 +1528,14 @@ function createEnsembleAdapter(options) {
|
|
|
1498
1528
|
if (aborted) return;
|
|
1499
1529
|
const text = await finalText(branches);
|
|
1500
1530
|
if (!text && branches.every((b) => b.error)) {
|
|
1501
|
-
|
|
1531
|
+
const summary = branches.map((b) => `${b.id}: ${b.error?.message ?? "unknown"}`).join("; ");
|
|
1532
|
+
const err = new AdapterError({
|
|
1533
|
+
code: ErrorCodes.AK_ADAPTER_STREAM_FAILED,
|
|
1534
|
+
message: `all ensemble branches failed (${summary})`,
|
|
1535
|
+
hint: "Inspect each branch error via options.onBranches or the err.branchErrors field."
|
|
1536
|
+
});
|
|
1537
|
+
err.branchErrors = branches.map((b) => ({ id: b.id, error: b.error }));
|
|
1538
|
+
throw err;
|
|
1502
1539
|
}
|
|
1503
1540
|
yield { type: "text", content: text, metadata: { ensemble: branches.map((b) => ({ id: b.id, bytes: b.text.length, error: b.error?.message })) } };
|
|
1504
1541
|
yield { type: "done" };
|
|
@@ -1507,11 +1544,13 @@ function createEnsembleAdapter(options) {
|
|
|
1507
1544
|
}
|
|
1508
1545
|
};
|
|
1509
1546
|
}
|
|
1510
|
-
|
|
1511
|
-
// src/fallback.ts
|
|
1512
1547
|
function createFallbackAdapter(candidates, options = {}) {
|
|
1513
1548
|
if (candidates.length === 0) {
|
|
1514
|
-
throw new
|
|
1549
|
+
throw new ConfigError({
|
|
1550
|
+
code: ErrorCodes.AK_CONFIG_INVALID,
|
|
1551
|
+
message: "createFallbackAdapter requires at least one candidate",
|
|
1552
|
+
hint: 'Pass at least one candidate, e.g. createFallbackAdapter([{ id: "primary", adapter }]).'
|
|
1553
|
+
});
|
|
1515
1554
|
}
|
|
1516
1555
|
return {
|
|
1517
1556
|
createSource: (request) => {
|
|
@@ -1566,14 +1605,16 @@ function createFallbackAdapter(candidates, options = {}) {
|
|
|
1566
1605
|
}
|
|
1567
1606
|
}
|
|
1568
1607
|
const summary = errors.map((e) => `${e.id}: ${e.error.message}`).join("; ");
|
|
1569
|
-
throw new
|
|
1608
|
+
throw new AdapterError({
|
|
1609
|
+
code: ErrorCodes.AK_ADAPTER_STREAM_FAILED,
|
|
1610
|
+
message: `all fallback candidates failed (${summary})`,
|
|
1611
|
+
hint: "Check each candidate adapter's configuration and provider keys."
|
|
1612
|
+
});
|
|
1570
1613
|
}
|
|
1571
1614
|
};
|
|
1572
1615
|
}
|
|
1573
1616
|
};
|
|
1574
1617
|
}
|
|
1575
|
-
|
|
1576
|
-
// src/mock.ts
|
|
1577
1618
|
function mockAdapter(options) {
|
|
1578
1619
|
const { response, delayMs = 0, history } = options;
|
|
1579
1620
|
let callIndex = 0;
|
|
@@ -1658,7 +1699,11 @@ function inMemorySink() {
|
|
|
1658
1699
|
}
|
|
1659
1700
|
function replayAdapter(fixture) {
|
|
1660
1701
|
if (fixture.length === 0) {
|
|
1661
|
-
throw new
|
|
1702
|
+
throw new ConfigError({
|
|
1703
|
+
code: ErrorCodes.AK_CONFIG_INVALID,
|
|
1704
|
+
message: "replayAdapter: fixture is empty",
|
|
1705
|
+
hint: "Pass a non-empty fixture; record one with recordingAdapter() first."
|
|
1706
|
+
});
|
|
1662
1707
|
}
|
|
1663
1708
|
return mockAdapter({
|
|
1664
1709
|
response: fixture.map((turn) => turn.chunks)
|
|
@@ -1667,11 +1712,13 @@ function replayAdapter(fixture) {
|
|
|
1667
1712
|
|
|
1668
1713
|
// src/embedders/openai.ts
|
|
1669
1714
|
async function fetchAvailableModels(baseUrl, apiKey) {
|
|
1670
|
-
const
|
|
1715
|
+
const url = `${baseUrl}/v1/models`;
|
|
1716
|
+
const response = await fetch(url, {
|
|
1671
1717
|
headers: { "Authorization": `Bearer ${apiKey}` }
|
|
1672
1718
|
});
|
|
1673
1719
|
if (!response.ok) {
|
|
1674
|
-
|
|
1720
|
+
const body = await response.text().catch(() => "");
|
|
1721
|
+
throw new Error(`HTTP ${response.status} from ${url}: ${body.slice(0, 200)}`);
|
|
1675
1722
|
}
|
|
1676
1723
|
const data = await response.json();
|
|
1677
1724
|
return data.data.map((m) => m.id).filter((id) => id.includes("embed")).sort();
|
|
@@ -1712,9 +1759,11 @@ function openaiEmbedder(config) {
|
|
|
1712
1759
|
|
|
1713
1760
|
// src/embedders/gemini.ts
|
|
1714
1761
|
async function fetchAvailableModels2(baseUrl, apiKey) {
|
|
1715
|
-
const
|
|
1762
|
+
const url = `${baseUrl}/v1beta/models?key=${apiKey}`;
|
|
1763
|
+
const response = await fetch(url);
|
|
1716
1764
|
if (!response.ok) {
|
|
1717
|
-
|
|
1765
|
+
const body = await response.text().catch(() => "");
|
|
1766
|
+
throw new Error(`HTTP ${response.status} from gemini ${baseUrl}/v1beta/models: ${body.slice(0, 200)}`);
|
|
1718
1767
|
}
|
|
1719
1768
|
const data = await response.json();
|
|
1720
1769
|
return data.models.filter((m) => m.supportedGenerationMethods.includes("embedContent")).map((m) => m.name.replace("models/", "")).sort();
|
|
@@ -1762,9 +1811,11 @@ function geminiEmbedder(config) {
|
|
|
1762
1811
|
|
|
1763
1812
|
// src/embedders/ollama.ts
|
|
1764
1813
|
async function fetchAvailableModels3(baseUrl) {
|
|
1765
|
-
const
|
|
1814
|
+
const url = `${baseUrl}/api/tags`;
|
|
1815
|
+
const response = await fetch(url);
|
|
1766
1816
|
if (!response.ok) {
|
|
1767
|
-
|
|
1817
|
+
const body = await response.text().catch(() => "");
|
|
1818
|
+
throw new Error(`HTTP ${response.status} from ollama ${url}: ${body.slice(0, 200)}`);
|
|
1768
1819
|
}
|
|
1769
1820
|
const data = await response.json();
|
|
1770
1821
|
return data.models.map((m) => m.name).filter((name) => name.includes("embed")).sort();
|
|
@@ -1799,14 +1850,14 @@ function ollamaEmbedder(config) {
|
|
|
1799
1850
|
return data.embeddings[0];
|
|
1800
1851
|
};
|
|
1801
1852
|
}
|
|
1802
|
-
|
|
1803
|
-
// src/embedders/openai-compatible.ts
|
|
1804
1853
|
async function fetchAvailableModels4(baseUrl, apiKey) {
|
|
1805
|
-
const
|
|
1854
|
+
const url = `${baseUrl}/v1/models`;
|
|
1855
|
+
const response = await fetch(url, {
|
|
1806
1856
|
headers: { "Authorization": `Bearer ${apiKey}` }
|
|
1807
1857
|
});
|
|
1808
1858
|
if (!response.ok) {
|
|
1809
|
-
|
|
1859
|
+
const body = await response.text().catch(() => "");
|
|
1860
|
+
throw new Error(`HTTP ${response.status} from ${url}: ${body.slice(0, 200)}`);
|
|
1810
1861
|
}
|
|
1811
1862
|
const data = await response.json();
|
|
1812
1863
|
return data.data.map((m) => m.id).filter((id) => id.includes("embed")).sort();
|
|
@@ -1827,7 +1878,11 @@ async function buildModelError4(provider, baseUrl, apiKey, originalError) {
|
|
|
1827
1878
|
function createOpenAICompatibleEmbedder(provider, defaultBaseUrl) {
|
|
1828
1879
|
return function embedder(config) {
|
|
1829
1880
|
if (!config.model) {
|
|
1830
|
-
throw new
|
|
1881
|
+
throw new ConfigError({
|
|
1882
|
+
code: ErrorCodes.AK_CONFIG_INVALID,
|
|
1883
|
+
message: `Model is required for ${provider}. Pass { model: "<model-name>" }.`,
|
|
1884
|
+
hint: `${provider} does not infer a default; pick a recent embedding model and pass it explicitly.`
|
|
1885
|
+
});
|
|
1831
1886
|
}
|
|
1832
1887
|
const { apiKey, model, baseUrl = defaultBaseUrl } = config;
|
|
1833
1888
|
return async (text) => {
|