@jambonz/llm 0.4.6 → 0.5.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 +145 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +145 -5
- package/dist/index.js.map +1 -1
- package/dist/test-kit/index.cjs +145 -5
- 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 +145 -5
- package/dist/test-kit/index.js.map +1 -1
- package/dist/{types-DbqWrdT6.d.cts → types-BEgQaQIb.d.cts} +36 -0
- package/dist/{types-DbqWrdT6.d.ts → types-BEgQaQIb.d.ts} +36 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -130,9 +130,22 @@ async function* streamFromOpenAI(client, req, options) {
|
|
|
130
130
|
const param = options.tokensParam ?? (needsMaxCompletionTokens(req.model) ? "max_completion_tokens" : "max_tokens");
|
|
131
131
|
body[param] = effectiveMaxTokens;
|
|
132
132
|
}
|
|
133
|
+
const t0 = process.hrtime.bigint();
|
|
134
|
+
let t1;
|
|
135
|
+
let t2;
|
|
133
136
|
let stream;
|
|
137
|
+
let responseHeaders;
|
|
134
138
|
try {
|
|
135
|
-
|
|
139
|
+
const apiPromise = client.chat.completions.create(body, { signal: req.signal });
|
|
140
|
+
const maybeWithResponse = apiPromise.withResponse;
|
|
141
|
+
if (typeof maybeWithResponse === "function") {
|
|
142
|
+
const result = await maybeWithResponse.call(apiPromise);
|
|
143
|
+
stream = result.data;
|
|
144
|
+
responseHeaders = result.response?.headers;
|
|
145
|
+
} else {
|
|
146
|
+
stream = await apiPromise;
|
|
147
|
+
}
|
|
148
|
+
t1 = process.hrtime.bigint();
|
|
136
149
|
} catch (err) {
|
|
137
150
|
if (isAbortError(err)) {
|
|
138
151
|
yield { type: "end", finishReason: "aborted" };
|
|
@@ -164,6 +177,7 @@ async function* streamFromOpenAI(client, req, options) {
|
|
|
164
177
|
const delta = choice.delta;
|
|
165
178
|
const finishReason = choice.finish_reason;
|
|
166
179
|
if (delta?.content) {
|
|
180
|
+
if (t2 === void 0) t2 = process.hrtime.bigint();
|
|
167
181
|
yield { type: "token", text: delta.content };
|
|
168
182
|
}
|
|
169
183
|
if (delta?.tool_calls) {
|
|
@@ -227,6 +241,20 @@ async function* streamFromOpenAI(client, req, options) {
|
|
|
227
241
|
...usage ? { usage } : {},
|
|
228
242
|
...finalRawReason ? { rawReason: finalRawReason } : {}
|
|
229
243
|
};
|
|
244
|
+
if (options.vendorMetadataExtractor && responseHeaders) {
|
|
245
|
+
const metadata = options.vendorMetadataExtractor(responseHeaders);
|
|
246
|
+
if (metadata && Object.keys(metadata).length > 0) {
|
|
247
|
+
endEvent.vendorMetadata = metadata;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (t1 !== void 0) {
|
|
251
|
+
const t3 = process.hrtime.bigint();
|
|
252
|
+
endEvent.clientTiming = {
|
|
253
|
+
requestToHeadersMs: Number(t1 - t0) / 1e6,
|
|
254
|
+
...t2 !== void 0 ? { headersToFirstTokenMs: Number(t2 - t1) / 1e6 } : {},
|
|
255
|
+
totalMs: Number(t3 - t0) / 1e6
|
|
256
|
+
};
|
|
257
|
+
}
|
|
230
258
|
yield endEvent;
|
|
231
259
|
}
|
|
232
260
|
function appendOpenAIAssistantToolCall(history, toolCalls) {
|
|
@@ -354,6 +382,40 @@ function isAbortError(err) {
|
|
|
354
382
|
return e.name === "APIUserAbortError" || e.name === "AbortError" || e.code === "ABORT_ERR" || typeof e.message === "string" && /aborted/i.test(e.message);
|
|
355
383
|
}
|
|
356
384
|
|
|
385
|
+
// src/adapters/_metadata.ts
|
|
386
|
+
function makeMetadataExtractor(fields) {
|
|
387
|
+
return (headers) => {
|
|
388
|
+
const out = {};
|
|
389
|
+
for (const f of fields) {
|
|
390
|
+
const raw = headers.get(f.header);
|
|
391
|
+
if (raw === null || raw === void 0 || raw === "") continue;
|
|
392
|
+
if (f.numeric) {
|
|
393
|
+
const n = Number(raw);
|
|
394
|
+
if (Number.isFinite(n)) out[f.key] = n;
|
|
395
|
+
} else {
|
|
396
|
+
out[f.key] = raw;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return out;
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
function extractMetadata(fields, headers) {
|
|
403
|
+
const headersInstance = headers instanceof Headers ? headers : recordToHeaders(headers);
|
|
404
|
+
return makeMetadataExtractor(fields)(headersInstance);
|
|
405
|
+
}
|
|
406
|
+
function recordToHeaders(record) {
|
|
407
|
+
const h = new Headers();
|
|
408
|
+
for (const [name, value] of Object.entries(record)) {
|
|
409
|
+
if (value === void 0) continue;
|
|
410
|
+
if (Array.isArray(value)) {
|
|
411
|
+
for (const v of value) h.append(name, v);
|
|
412
|
+
} else {
|
|
413
|
+
h.set(name, value);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return h;
|
|
417
|
+
}
|
|
418
|
+
|
|
357
419
|
// src/adapters/openai/manifest.ts
|
|
358
420
|
var OPENAI_KNOWN_MODELS = [
|
|
359
421
|
{
|
|
@@ -455,6 +517,12 @@ var openAIManifest = {
|
|
|
455
517
|
};
|
|
456
518
|
|
|
457
519
|
// src/adapters/openai/adapter.ts
|
|
520
|
+
var OPENAI_METADATA_EXTRACTOR = makeMetadataExtractor([
|
|
521
|
+
{ header: "x-request-id", key: "request_id" },
|
|
522
|
+
{ header: "openai-processing-ms", key: "processing_ms", numeric: true },
|
|
523
|
+
{ header: "x-ratelimit-remaining-requests", key: "requests_remaining", numeric: true },
|
|
524
|
+
{ header: "x-ratelimit-remaining-tokens", key: "tokens_remaining", numeric: true }
|
|
525
|
+
]);
|
|
458
526
|
var OpenAIAdapter = class {
|
|
459
527
|
vendor = openAIManifest.vendor;
|
|
460
528
|
acceptedAuth = ["apiKey"];
|
|
@@ -472,7 +540,8 @@ var OpenAIAdapter = class {
|
|
|
472
540
|
}
|
|
473
541
|
stream(req) {
|
|
474
542
|
return streamFromOpenAI(this.ensureClient(), req, {
|
|
475
|
-
knownModels: openAIManifest.knownModels
|
|
543
|
+
knownModels: openAIManifest.knownModels,
|
|
544
|
+
vendorMetadataExtractor: OPENAI_METADATA_EXTRACTOR
|
|
476
545
|
});
|
|
477
546
|
}
|
|
478
547
|
appendAssistantToolCall(history, toolCalls) {
|
|
@@ -704,6 +773,12 @@ var anthropicManifest = {
|
|
|
704
773
|
};
|
|
705
774
|
|
|
706
775
|
// src/adapters/anthropic/adapter.ts
|
|
776
|
+
var ANTHROPIC_METADATA_EXTRACTOR = makeMetadataExtractor([
|
|
777
|
+
{ header: "request-id", key: "request_id" },
|
|
778
|
+
{ header: "anthropic-ratelimit-requests-remaining", key: "requests_remaining", numeric: true },
|
|
779
|
+
{ header: "anthropic-ratelimit-input-tokens-remaining", key: "input_tokens_remaining", numeric: true },
|
|
780
|
+
{ header: "anthropic-ratelimit-output-tokens-remaining", key: "output_tokens_remaining", numeric: true }
|
|
781
|
+
]);
|
|
707
782
|
var AnthropicAdapter = class {
|
|
708
783
|
vendor = anthropicManifest.vendor;
|
|
709
784
|
acceptedAuth = ["apiKey"];
|
|
@@ -738,11 +813,20 @@ var AnthropicAdapter = class {
|
|
|
738
813
|
if (tools) body.tools = tools;
|
|
739
814
|
if (req.temperature !== void 0) body.temperature = req.temperature;
|
|
740
815
|
let stream;
|
|
816
|
+
let responseHeaders;
|
|
741
817
|
try {
|
|
742
|
-
|
|
818
|
+
const apiPromise = client.messages.create(
|
|
743
819
|
body,
|
|
744
820
|
{ signal: req.signal }
|
|
745
821
|
);
|
|
822
|
+
const maybeWithResponse = apiPromise.withResponse;
|
|
823
|
+
if (typeof maybeWithResponse === "function") {
|
|
824
|
+
const result = await maybeWithResponse.call(apiPromise);
|
|
825
|
+
stream = result.data;
|
|
826
|
+
responseHeaders = result.response?.headers;
|
|
827
|
+
} else {
|
|
828
|
+
stream = await apiPromise;
|
|
829
|
+
}
|
|
746
830
|
} catch (err) {
|
|
747
831
|
if (isAbortError2(err)) {
|
|
748
832
|
yield { type: "end", finishReason: "aborted" };
|
|
@@ -853,6 +937,12 @@ var AnthropicAdapter = class {
|
|
|
853
937
|
...usage ? { usage } : {},
|
|
854
938
|
...stopReason ? { rawReason: stopReason } : {}
|
|
855
939
|
};
|
|
940
|
+
if (responseHeaders) {
|
|
941
|
+
const metadata = ANTHROPIC_METADATA_EXTRACTOR(responseHeaders);
|
|
942
|
+
if (Object.keys(metadata).length > 0) {
|
|
943
|
+
endEvent.vendorMetadata = metadata;
|
|
944
|
+
}
|
|
945
|
+
}
|
|
856
946
|
yield endEvent;
|
|
857
947
|
}
|
|
858
948
|
appendAssistantToolCall(history, toolCalls) {
|
|
@@ -1645,6 +1735,9 @@ var vertexOpenAIManifest = {
|
|
|
1645
1735
|
};
|
|
1646
1736
|
|
|
1647
1737
|
// src/adapters/vertex-openai/adapter.ts
|
|
1738
|
+
var VERTEX_OPENAI_METADATA_EXTRACTOR = makeMetadataExtractor([
|
|
1739
|
+
{ header: "x-request-id", key: "request_id" }
|
|
1740
|
+
]);
|
|
1648
1741
|
var VertexOpenAIAdapter = class {
|
|
1649
1742
|
vendor = vertexOpenAIManifest.vendor;
|
|
1650
1743
|
acceptedAuth = ["vertexServiceAccount"];
|
|
@@ -1697,7 +1790,8 @@ var VertexOpenAIAdapter = class {
|
|
|
1697
1790
|
// endpoint predates `max_completion_tokens` and may not recognize it.
|
|
1698
1791
|
// The model-id heuristic wouldn't catch a partner model named in the
|
|
1699
1792
|
// OpenAI style (unlikely today, but defensive).
|
|
1700
|
-
tokensParam: "max_tokens"
|
|
1793
|
+
tokensParam: "max_tokens",
|
|
1794
|
+
vendorMetadataExtractor: VERTEX_OPENAI_METADATA_EXTRACTOR
|
|
1701
1795
|
});
|
|
1702
1796
|
}
|
|
1703
1797
|
appendAssistantToolCall(history, toolCalls) {
|
|
@@ -2155,6 +2249,21 @@ var BedrockAdapter = class {
|
|
|
2155
2249
|
...usage ? { usage } : {},
|
|
2156
2250
|
...stopReason ? { rawReason: stopReason } : {}
|
|
2157
2251
|
};
|
|
2252
|
+
const httpHeaders = response.$metadata?.httpHeaders;
|
|
2253
|
+
if (httpHeaders) {
|
|
2254
|
+
const metadata = extractMetadata(
|
|
2255
|
+
[
|
|
2256
|
+
{ header: "x-amzn-bedrock-invocation-latency", key: "invocation_latency_ms", numeric: true },
|
|
2257
|
+
{ header: "x-amzn-bedrock-cache-read-input-token-count", key: "cache_read_input_tokens", numeric: true },
|
|
2258
|
+
{ header: "x-amzn-bedrock-cache-write-input-token-count", key: "cache_write_input_tokens", numeric: true },
|
|
2259
|
+
{ header: "x-amzn-bedrock-trace-id", key: "trace_id" }
|
|
2260
|
+
],
|
|
2261
|
+
httpHeaders
|
|
2262
|
+
);
|
|
2263
|
+
if (Object.keys(metadata).length > 0) {
|
|
2264
|
+
endEvent.vendorMetadata = metadata;
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2158
2267
|
yield endEvent;
|
|
2159
2268
|
}
|
|
2160
2269
|
appendAssistantToolCall(history, toolCalls) {
|
|
@@ -2406,6 +2515,14 @@ var azureOpenAIManifest = {
|
|
|
2406
2515
|
};
|
|
2407
2516
|
|
|
2408
2517
|
// src/adapters/azure-openai/adapter.ts
|
|
2518
|
+
var AZURE_OPENAI_METADATA_EXTRACTOR = makeMetadataExtractor([
|
|
2519
|
+
{ header: "x-ms-region", key: "region" },
|
|
2520
|
+
{ header: "x-ms-deployment-name", key: "deployment" },
|
|
2521
|
+
{ header: "apim-request-id", key: "request_id" },
|
|
2522
|
+
{ header: "azureml-model-session", key: "model_session" },
|
|
2523
|
+
{ header: "x-ratelimit-remaining-requests", key: "requests_remaining", numeric: true },
|
|
2524
|
+
{ header: "x-ratelimit-remaining-tokens", key: "tokens_remaining", numeric: true }
|
|
2525
|
+
]);
|
|
2409
2526
|
var AzureOpenAIAdapter = class {
|
|
2410
2527
|
vendor = azureOpenAIManifest.vendor;
|
|
2411
2528
|
acceptedAuth = ["azureOpenAIApiKey"];
|
|
@@ -2440,7 +2557,8 @@ var AzureOpenAIAdapter = class {
|
|
|
2440
2557
|
stream(req) {
|
|
2441
2558
|
return streamFromOpenAI(this.ensureClient(), req, {
|
|
2442
2559
|
knownModels: azureOpenAIManifest.knownModels,
|
|
2443
|
-
tokensParam: "max_completion_tokens"
|
|
2560
|
+
tokensParam: "max_completion_tokens",
|
|
2561
|
+
vendorMetadataExtractor: AZURE_OPENAI_METADATA_EXTRACTOR
|
|
2444
2562
|
});
|
|
2445
2563
|
}
|
|
2446
2564
|
appendAssistantToolCall(history, toolCalls) {
|
|
@@ -2565,6 +2683,12 @@ var groqManifest = {
|
|
|
2565
2683
|
};
|
|
2566
2684
|
|
|
2567
2685
|
// src/adapters/groq/adapter.ts
|
|
2686
|
+
var GROQ_METADATA_EXTRACTOR = makeMetadataExtractor([
|
|
2687
|
+
{ header: "x-request-id", key: "request_id" },
|
|
2688
|
+
{ header: "x-groq-region", key: "region" },
|
|
2689
|
+
{ header: "x-ratelimit-remaining-requests", key: "requests_remaining", numeric: true },
|
|
2690
|
+
{ header: "x-ratelimit-remaining-tokens", key: "tokens_remaining", numeric: true }
|
|
2691
|
+
]);
|
|
2568
2692
|
var GroqAdapter = class extends OpenAIAdapter {
|
|
2569
2693
|
vendor = groqManifest.vendor;
|
|
2570
2694
|
init(auth, client) {
|
|
@@ -2576,6 +2700,12 @@ var GroqAdapter = class extends OpenAIAdapter {
|
|
|
2576
2700
|
client
|
|
2577
2701
|
);
|
|
2578
2702
|
}
|
|
2703
|
+
stream(req) {
|
|
2704
|
+
return streamFromOpenAI(this.ensureClient(), req, {
|
|
2705
|
+
knownModels: groqManifest.knownModels,
|
|
2706
|
+
vendorMetadataExtractor: GROQ_METADATA_EXTRACTOR
|
|
2707
|
+
});
|
|
2708
|
+
}
|
|
2579
2709
|
};
|
|
2580
2710
|
|
|
2581
2711
|
// src/adapters/groq/factory.ts
|
|
@@ -2676,6 +2806,10 @@ var huggingfaceManifest = {
|
|
|
2676
2806
|
};
|
|
2677
2807
|
|
|
2678
2808
|
// src/adapters/huggingface/adapter.ts
|
|
2809
|
+
var HUGGINGFACE_METADATA_EXTRACTOR = makeMetadataExtractor([
|
|
2810
|
+
{ header: "x-inference-provider", key: "provider" },
|
|
2811
|
+
{ header: "x-request-id", key: "request_id" }
|
|
2812
|
+
]);
|
|
2679
2813
|
var HuggingfaceAdapter = class extends OpenAIAdapter {
|
|
2680
2814
|
vendor = huggingfaceManifest.vendor;
|
|
2681
2815
|
init(auth, client) {
|
|
@@ -2687,6 +2821,12 @@ var HuggingfaceAdapter = class extends OpenAIAdapter {
|
|
|
2687
2821
|
client
|
|
2688
2822
|
);
|
|
2689
2823
|
}
|
|
2824
|
+
stream(req) {
|
|
2825
|
+
return streamFromOpenAI(this.ensureClient(), req, {
|
|
2826
|
+
knownModels: huggingfaceManifest.knownModels,
|
|
2827
|
+
vendorMetadataExtractor: HUGGINGFACE_METADATA_EXTRACTOR
|
|
2828
|
+
});
|
|
2829
|
+
}
|
|
2690
2830
|
};
|
|
2691
2831
|
|
|
2692
2832
|
// src/adapters/huggingface/factory.ts
|