@jambonz/llm 0.5.6 → 0.6.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 +162 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +162 -7
- package/dist/index.js.map +1 -1
- package/dist/test-kit/index.cjs +162 -7
- package/dist/test-kit/index.cjs.map +1 -1
- package/dist/test-kit/index.d.cts +1 -1
- package/dist/test-kit/index.d.ts +1 -1
- package/dist/test-kit/index.js +162 -7
- package/dist/test-kit/index.js.map +1 -1
- package/dist/{types-BEgQaQIb.d.cts → types-Y0o6rN3B.d.cts} +45 -0
- package/dist/{types-BEgQaQIb.d.ts → types-Y0o6rN3B.d.ts} +45 -0
- package/package.json +1 -1
package/dist/test-kit/index.cjs
CHANGED
|
@@ -88,6 +88,9 @@ function assertValidRequest(req) {
|
|
|
88
88
|
"PromptRequest.messages must not contain role: 'system'. Pass the system prompt via PromptRequest.system instead."
|
|
89
89
|
);
|
|
90
90
|
}
|
|
91
|
+
if (req.cacheKey !== void 0 && (typeof req.cacheKey !== "string" || req.cacheKey.length === 0)) {
|
|
92
|
+
throw new Error("PromptRequest.cacheKey must be a non-empty string");
|
|
93
|
+
}
|
|
91
94
|
}
|
|
92
95
|
|
|
93
96
|
// src/adapters/openai/_streaming.ts
|
|
@@ -112,11 +115,20 @@ async function* streamFromOpenAI(client, req, options) {
|
|
|
112
115
|
body.tool_choice = "auto";
|
|
113
116
|
}
|
|
114
117
|
if (req.temperature !== void 0) body.temperature = req.temperature;
|
|
118
|
+
if (req.cacheKey && options.includeCacheKey !== false) {
|
|
119
|
+
body.prompt_cache_key = req.cacheKey;
|
|
120
|
+
}
|
|
115
121
|
const effectiveMaxTokens = req.maxTokens ?? options.defaultMaxTokens;
|
|
116
122
|
if (effectiveMaxTokens !== void 0) {
|
|
117
123
|
const param = options.tokensParam ?? (needsMaxCompletionTokens(req.model) ? "max_completion_tokens" : "max_tokens");
|
|
118
124
|
body[param] = effectiveMaxTokens;
|
|
119
125
|
}
|
|
126
|
+
if (req.providerParams) {
|
|
127
|
+
const bodyRecord = body;
|
|
128
|
+
for (const [key, value] of Object.entries(req.providerParams)) {
|
|
129
|
+
if (!(key in bodyRecord)) bodyRecord[key] = value;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
120
132
|
const t0 = process.hrtime.bigint();
|
|
121
133
|
let t1;
|
|
122
134
|
let t2;
|
|
@@ -159,10 +171,12 @@ async function* streamFromOpenAI(client, req, options) {
|
|
|
159
171
|
throw new Error(`OpenAI-compatible stream returned an error: ${message}`);
|
|
160
172
|
}
|
|
161
173
|
if (chunk.usage) {
|
|
174
|
+
const cachedTokens = chunk.usage.prompt_tokens_details?.cached_tokens;
|
|
162
175
|
usage = {
|
|
163
|
-
...chunk.usage.prompt_tokens !== void 0 ? { inputTokens: chunk.usage.prompt_tokens } : {},
|
|
176
|
+
...chunk.usage.prompt_tokens !== void 0 ? { inputTokens: chunk.usage.prompt_tokens - (cachedTokens ?? 0) } : {},
|
|
164
177
|
...chunk.usage.completion_tokens !== void 0 ? { outputTokens: chunk.usage.completion_tokens } : {},
|
|
165
|
-
...chunk.usage.total_tokens !== void 0 ? { totalTokens: chunk.usage.total_tokens } : {}
|
|
178
|
+
...chunk.usage.total_tokens !== void 0 ? { totalTokens: chunk.usage.total_tokens } : {},
|
|
179
|
+
...cachedTokens !== void 0 ? { cacheReadTokens: cachedTokens } : {}
|
|
166
180
|
};
|
|
167
181
|
}
|
|
168
182
|
const choice = chunk.choices?.[0];
|
|
@@ -1215,6 +1229,16 @@ var AnthropicAdapter = class {
|
|
|
1215
1229
|
if (req.system) body.system = req.system;
|
|
1216
1230
|
if (tools) body.tools = tools;
|
|
1217
1231
|
if (req.temperature !== void 0) body.temperature = req.temperature;
|
|
1232
|
+
if (req.cacheKey) {
|
|
1233
|
+
if (req.system) {
|
|
1234
|
+
body.system = [{ type: "text", text: req.system, cache_control: { type: "ephemeral" } }];
|
|
1235
|
+
}
|
|
1236
|
+
if (tools) {
|
|
1237
|
+
const lastTool = tools[tools.length - 1];
|
|
1238
|
+
lastTool.cache_control = { type: "ephemeral" };
|
|
1239
|
+
}
|
|
1240
|
+
markLastMessageForCaching(messages);
|
|
1241
|
+
}
|
|
1218
1242
|
let stream;
|
|
1219
1243
|
let responseHeaders;
|
|
1220
1244
|
try {
|
|
@@ -1242,6 +1266,8 @@ var AnthropicAdapter = class {
|
|
|
1242
1266
|
let stopReason;
|
|
1243
1267
|
let inputTokens;
|
|
1244
1268
|
let outputTokens;
|
|
1269
|
+
let cacheReadTokens;
|
|
1270
|
+
let cacheWriteTokens;
|
|
1245
1271
|
try {
|
|
1246
1272
|
for await (const event of stream) {
|
|
1247
1273
|
if (req.signal?.aborted) {
|
|
@@ -1251,6 +1277,8 @@ var AnthropicAdapter = class {
|
|
|
1251
1277
|
switch (event.type) {
|
|
1252
1278
|
case "message_start":
|
|
1253
1279
|
inputTokens = event.message?.usage?.input_tokens;
|
|
1280
|
+
cacheReadTokens = event.message?.usage?.cache_read_input_tokens;
|
|
1281
|
+
cacheWriteTokens = event.message?.usage?.cache_creation_input_tokens;
|
|
1254
1282
|
break;
|
|
1255
1283
|
case "content_block_start": {
|
|
1256
1284
|
const block = event.content_block;
|
|
@@ -1332,7 +1360,11 @@ var AnthropicAdapter = class {
|
|
|
1332
1360
|
const usage = inputTokens !== void 0 || outputTokens !== void 0 ? {
|
|
1333
1361
|
...inputTokens !== void 0 ? { inputTokens } : {},
|
|
1334
1362
|
...outputTokens !== void 0 ? { outputTokens } : {},
|
|
1335
|
-
...inputTokens !== void 0 && outputTokens !== void 0 ? {
|
|
1363
|
+
...inputTokens !== void 0 && outputTokens !== void 0 ? {
|
|
1364
|
+
totalTokens: inputTokens + outputTokens + (cacheReadTokens ?? 0) + (cacheWriteTokens ?? 0)
|
|
1365
|
+
} : {},
|
|
1366
|
+
...cacheReadTokens !== void 0 ? { cacheReadTokens } : {},
|
|
1367
|
+
...cacheWriteTokens !== void 0 ? { cacheWriteTokens } : {}
|
|
1336
1368
|
} : void 0;
|
|
1337
1369
|
const endEvent = {
|
|
1338
1370
|
type: "end",
|
|
@@ -1431,6 +1463,23 @@ function buildWireMessages2(req) {
|
|
|
1431
1463
|
}
|
|
1432
1464
|
return out;
|
|
1433
1465
|
}
|
|
1466
|
+
function markLastMessageForCaching(messages) {
|
|
1467
|
+
if (messages.length === 0) return;
|
|
1468
|
+
const last = messages[messages.length - 1];
|
|
1469
|
+
const cacheControl = { cache_control: { type: "ephemeral" } };
|
|
1470
|
+
if (typeof last.content === "string" && last.content.length > 0) {
|
|
1471
|
+
messages[messages.length - 1] = {
|
|
1472
|
+
...last,
|
|
1473
|
+
content: [{ type: "text", text: last.content, ...cacheControl }]
|
|
1474
|
+
};
|
|
1475
|
+
} else if (Array.isArray(last.content) && last.content.length > 0) {
|
|
1476
|
+
const blocks = last.content;
|
|
1477
|
+
messages[messages.length - 1] = {
|
|
1478
|
+
...last,
|
|
1479
|
+
content: [...blocks.slice(0, -1), { ...blocks[blocks.length - 1], ...cacheControl }]
|
|
1480
|
+
};
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1434
1483
|
function formatTools2(tools) {
|
|
1435
1484
|
return tools.map((t) => ({
|
|
1436
1485
|
name: t.name,
|
|
@@ -1493,6 +1542,11 @@ async function* streamFromGemini(client, req) {
|
|
|
1493
1542
|
if (req.temperature !== void 0) config.temperature = req.temperature;
|
|
1494
1543
|
if (req.maxTokens !== void 0) config.maxOutputTokens = req.maxTokens;
|
|
1495
1544
|
if (req.signal) config.abortSignal = req.signal;
|
|
1545
|
+
if (req.providerParams) {
|
|
1546
|
+
for (const [key, value] of Object.entries(req.providerParams)) {
|
|
1547
|
+
if (!(key in config)) config[key] = value;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1496
1550
|
let stream;
|
|
1497
1551
|
try {
|
|
1498
1552
|
stream = await client.models.generateContentStream({
|
|
@@ -1513,6 +1567,7 @@ async function* streamFromGemini(client, req) {
|
|
|
1513
1567
|
let inputTokens;
|
|
1514
1568
|
let outputTokens;
|
|
1515
1569
|
let totalTokens;
|
|
1570
|
+
let cacheReadTokens;
|
|
1516
1571
|
try {
|
|
1517
1572
|
for await (const chunk of stream) {
|
|
1518
1573
|
if (req.signal?.aborted) {
|
|
@@ -1521,7 +1576,12 @@ async function* streamFromGemini(client, req) {
|
|
|
1521
1576
|
}
|
|
1522
1577
|
const usage2 = chunk.usageMetadata;
|
|
1523
1578
|
if (usage2) {
|
|
1524
|
-
if (usage2.
|
|
1579
|
+
if (usage2.cachedContentTokenCount !== void 0) {
|
|
1580
|
+
cacheReadTokens = usage2.cachedContentTokenCount;
|
|
1581
|
+
}
|
|
1582
|
+
if (usage2.promptTokenCount !== void 0) {
|
|
1583
|
+
inputTokens = usage2.promptTokenCount - (usage2.cachedContentTokenCount ?? 0);
|
|
1584
|
+
}
|
|
1525
1585
|
if (usage2.candidatesTokenCount !== void 0) outputTokens = usage2.candidatesTokenCount;
|
|
1526
1586
|
if (usage2.totalTokenCount !== void 0) totalTokens = usage2.totalTokenCount;
|
|
1527
1587
|
}
|
|
@@ -1575,7 +1635,8 @@ async function* streamFromGemini(client, req) {
|
|
|
1575
1635
|
const usage = inputTokens !== void 0 || outputTokens !== void 0 || totalTokens !== void 0 ? {
|
|
1576
1636
|
...inputTokens !== void 0 ? { inputTokens } : {},
|
|
1577
1637
|
...outputTokens !== void 0 ? { outputTokens } : {},
|
|
1578
|
-
...totalTokens !== void 0 ? { totalTokens } : {}
|
|
1638
|
+
...totalTokens !== void 0 ? { totalTokens } : {},
|
|
1639
|
+
...cacheReadTokens !== void 0 ? { cacheReadTokens } : {}
|
|
1579
1640
|
} : void 0;
|
|
1580
1641
|
const endEvent = {
|
|
1581
1642
|
type: "end",
|
|
@@ -1717,6 +1778,39 @@ function isAbortError3(err) {
|
|
|
1717
1778
|
|
|
1718
1779
|
// src/adapters/google/manifest.ts
|
|
1719
1780
|
var GOOGLE_KNOWN_MODELS = [
|
|
1781
|
+
{
|
|
1782
|
+
id: "gemini-3.6-flash",
|
|
1783
|
+
displayName: "Gemini 3.6 Flash",
|
|
1784
|
+
capabilities: {
|
|
1785
|
+
streaming: true,
|
|
1786
|
+
tools: true,
|
|
1787
|
+
vision: true,
|
|
1788
|
+
systemPrompt: true,
|
|
1789
|
+
maxContextTokens: 1e6
|
|
1790
|
+
}
|
|
1791
|
+
},
|
|
1792
|
+
{
|
|
1793
|
+
id: "gemini-3.5-flash",
|
|
1794
|
+
displayName: "Gemini 3.5 Flash",
|
|
1795
|
+
capabilities: {
|
|
1796
|
+
streaming: true,
|
|
1797
|
+
tools: true,
|
|
1798
|
+
vision: true,
|
|
1799
|
+
systemPrompt: true,
|
|
1800
|
+
maxContextTokens: 1e6
|
|
1801
|
+
}
|
|
1802
|
+
},
|
|
1803
|
+
{
|
|
1804
|
+
id: "gemini-3.5-flash-lite",
|
|
1805
|
+
displayName: "Gemini 3.5 Flash-Lite",
|
|
1806
|
+
capabilities: {
|
|
1807
|
+
streaming: true,
|
|
1808
|
+
tools: true,
|
|
1809
|
+
vision: true,
|
|
1810
|
+
systemPrompt: true,
|
|
1811
|
+
maxContextTokens: 1e6
|
|
1812
|
+
}
|
|
1813
|
+
},
|
|
1720
1814
|
{
|
|
1721
1815
|
id: "gemini-2.5-pro",
|
|
1722
1816
|
displayName: "Gemini 2.5 Pro",
|
|
@@ -1860,6 +1954,39 @@ var import_genai2 = require("@google/genai");
|
|
|
1860
1954
|
|
|
1861
1955
|
// src/adapters/vertex-gemini/manifest.ts
|
|
1862
1956
|
var VERTEX_GEMINI_KNOWN_MODELS = [
|
|
1957
|
+
{
|
|
1958
|
+
id: "gemini-3.6-flash",
|
|
1959
|
+
displayName: "Gemini 3.6 Flash",
|
|
1960
|
+
capabilities: {
|
|
1961
|
+
streaming: true,
|
|
1962
|
+
tools: true,
|
|
1963
|
+
vision: true,
|
|
1964
|
+
systemPrompt: true,
|
|
1965
|
+
maxContextTokens: 1e6
|
|
1966
|
+
}
|
|
1967
|
+
},
|
|
1968
|
+
{
|
|
1969
|
+
id: "gemini-3.5-flash",
|
|
1970
|
+
displayName: "Gemini 3.5 Flash",
|
|
1971
|
+
capabilities: {
|
|
1972
|
+
streaming: true,
|
|
1973
|
+
tools: true,
|
|
1974
|
+
vision: true,
|
|
1975
|
+
systemPrompt: true,
|
|
1976
|
+
maxContextTokens: 1e6
|
|
1977
|
+
}
|
|
1978
|
+
},
|
|
1979
|
+
{
|
|
1980
|
+
id: "gemini-3.5-flash-lite",
|
|
1981
|
+
displayName: "Gemini 3.5 Flash-Lite",
|
|
1982
|
+
capabilities: {
|
|
1983
|
+
streaming: true,
|
|
1984
|
+
tools: true,
|
|
1985
|
+
vision: true,
|
|
1986
|
+
systemPrompt: true,
|
|
1987
|
+
maxContextTokens: 1e6
|
|
1988
|
+
}
|
|
1989
|
+
},
|
|
1863
1990
|
{
|
|
1864
1991
|
id: "gemini-2.5-pro",
|
|
1865
1992
|
displayName: "Gemini 2.5 Pro",
|
|
@@ -2543,6 +2670,15 @@ var BedrockAdapter = class {
|
|
|
2543
2670
|
if (Object.keys(inferenceConfig).length > 0) {
|
|
2544
2671
|
commandInput.inferenceConfig = inferenceConfig;
|
|
2545
2672
|
}
|
|
2673
|
+
if (req.cacheKey) {
|
|
2674
|
+
if (commandInput.system) {
|
|
2675
|
+
commandInput.system.push({ cachePoint: { type: "default" } });
|
|
2676
|
+
}
|
|
2677
|
+
if (tools) {
|
|
2678
|
+
tools.tools.push({ cachePoint: { type: "default" } });
|
|
2679
|
+
}
|
|
2680
|
+
markLastMessageForCaching2(messages);
|
|
2681
|
+
}
|
|
2546
2682
|
const command = new import_client_bedrock_runtime.ConverseStreamCommand(
|
|
2547
2683
|
commandInput
|
|
2548
2684
|
);
|
|
@@ -2566,6 +2702,8 @@ var BedrockAdapter = class {
|
|
|
2566
2702
|
let inputTokens;
|
|
2567
2703
|
let outputTokens;
|
|
2568
2704
|
let totalTokens;
|
|
2705
|
+
let cacheReadTokens;
|
|
2706
|
+
let cacheWriteTokens;
|
|
2569
2707
|
try {
|
|
2570
2708
|
for await (const event of response.stream) {
|
|
2571
2709
|
if (req.signal?.aborted) {
|
|
@@ -2618,6 +2756,8 @@ var BedrockAdapter = class {
|
|
|
2618
2756
|
inputTokens = event.metadata.usage.inputTokens;
|
|
2619
2757
|
outputTokens = event.metadata.usage.outputTokens;
|
|
2620
2758
|
totalTokens = event.metadata.usage.totalTokens;
|
|
2759
|
+
cacheReadTokens = event.metadata.usage.cacheReadInputTokens;
|
|
2760
|
+
cacheWriteTokens = event.metadata.usage.cacheWriteInputTokens;
|
|
2621
2761
|
}
|
|
2622
2762
|
}
|
|
2623
2763
|
}
|
|
@@ -2644,7 +2784,9 @@ var BedrockAdapter = class {
|
|
|
2644
2784
|
const usage = inputTokens !== void 0 || outputTokens !== void 0 || totalTokens !== void 0 ? {
|
|
2645
2785
|
...inputTokens !== void 0 ? { inputTokens } : {},
|
|
2646
2786
|
...outputTokens !== void 0 ? { outputTokens } : {},
|
|
2647
|
-
...totalTokens !== void 0 ? { totalTokens } : {}
|
|
2787
|
+
...totalTokens !== void 0 ? { totalTokens } : {},
|
|
2788
|
+
...cacheReadTokens !== void 0 ? { cacheReadTokens } : {},
|
|
2789
|
+
...cacheWriteTokens !== void 0 ? { cacheWriteTokens } : {}
|
|
2648
2790
|
} : void 0;
|
|
2649
2791
|
const endEvent = {
|
|
2650
2792
|
type: "end",
|
|
@@ -2752,6 +2894,16 @@ function buildWireMessages3(req) {
|
|
|
2752
2894
|
}
|
|
2753
2895
|
return out;
|
|
2754
2896
|
}
|
|
2897
|
+
function markLastMessageForCaching2(messages) {
|
|
2898
|
+
if (messages.length === 0) return;
|
|
2899
|
+
const last = messages[messages.length - 1];
|
|
2900
|
+
if (Array.isArray(last.content) && last.content.length > 0) {
|
|
2901
|
+
messages[messages.length - 1] = {
|
|
2902
|
+
...last,
|
|
2903
|
+
content: [...last.content, { cachePoint: { type: "default" } }]
|
|
2904
|
+
};
|
|
2905
|
+
}
|
|
2906
|
+
}
|
|
2755
2907
|
function formatTools4(tools) {
|
|
2756
2908
|
return tools.map((t) => ({
|
|
2757
2909
|
toolSpec: {
|
|
@@ -3107,7 +3259,10 @@ var GroqAdapter = class extends OpenAIAdapter {
|
|
|
3107
3259
|
stream(req) {
|
|
3108
3260
|
return streamFromOpenAI(this.ensureClient(), req, {
|
|
3109
3261
|
knownModels: groqManifest.knownModels,
|
|
3110
|
-
vendorMetadataExtractor: GROQ_METADATA_EXTRACTOR
|
|
3262
|
+
vendorMetadataExtractor: GROQ_METADATA_EXTRACTOR,
|
|
3263
|
+
// Groq caches automatically server-side and rejects/ignores undocumented
|
|
3264
|
+
// OpenAI params — do not forward prompt_cache_key.
|
|
3265
|
+
includeCacheKey: false
|
|
3111
3266
|
});
|
|
3112
3267
|
}
|
|
3113
3268
|
};
|