@jambonz/llm 0.4.5 → 0.5.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.
@@ -1,4 +1,4 @@
1
- import { b as AdapterFactory, e as AuthKind, A as AuthSpec, L as LlmAdapter, d as ApiKeyAuth, h as ClientOptions, P as PromptRequest, m as LlmEvent, M as Message, p as ToolCallEvent, o as ModelInfo, c as AdapterManifest } from '../types-DbqWrdT6.cjs';
1
+ import { b as AdapterFactory, e as AuthKind, A as AuthSpec, L as LlmAdapter, d as ApiKeyAuth, h as ClientOptions, P as PromptRequest, m as LlmEvent, M as Message, p as ToolCallEvent, o as ModelInfo, c as AdapterManifest } from '../types-BWsmVtXv.cjs';
2
2
 
3
3
  /**
4
4
  * Named scenarios the harness must be able to stage. Each scenario configures
@@ -1,4 +1,4 @@
1
- import { b as AdapterFactory, e as AuthKind, A as AuthSpec, L as LlmAdapter, d as ApiKeyAuth, h as ClientOptions, P as PromptRequest, m as LlmEvent, M as Message, p as ToolCallEvent, o as ModelInfo, c as AdapterManifest } from '../types-DbqWrdT6.js';
1
+ import { b as AdapterFactory, e as AuthKind, A as AuthSpec, L as LlmAdapter, d as ApiKeyAuth, h as ClientOptions, P as PromptRequest, m as LlmEvent, M as Message, p as ToolCallEvent, o as ModelInfo, c as AdapterManifest } from '../types-BWsmVtXv.js';
2
2
 
3
3
  /**
4
4
  * Named scenarios the harness must be able to stage. Each scenario configures
@@ -79,8 +79,17 @@ async function* streamFromOpenAI(client, req, options) {
79
79
  body[param] = effectiveMaxTokens;
80
80
  }
81
81
  let stream;
82
+ let responseHeaders;
82
83
  try {
83
- stream = await client.chat.completions.create(body, { signal: req.signal });
84
+ const apiPromise = client.chat.completions.create(body, { signal: req.signal });
85
+ const maybeWithResponse = apiPromise.withResponse;
86
+ if (typeof maybeWithResponse === "function") {
87
+ const result = await maybeWithResponse.call(apiPromise);
88
+ stream = result.data;
89
+ responseHeaders = result.response?.headers;
90
+ } else {
91
+ stream = await apiPromise;
92
+ }
84
93
  } catch (err) {
85
94
  if (isAbortError(err)) {
86
95
  yield { type: "end", finishReason: "aborted" };
@@ -175,6 +184,12 @@ async function* streamFromOpenAI(client, req, options) {
175
184
  ...usage ? { usage } : {},
176
185
  ...finalRawReason ? { rawReason: finalRawReason } : {}
177
186
  };
187
+ if (options.vendorMetadataExtractor && responseHeaders) {
188
+ const metadata = options.vendorMetadataExtractor(responseHeaders);
189
+ if (metadata && Object.keys(metadata).length > 0) {
190
+ endEvent.vendorMetadata = metadata;
191
+ }
192
+ }
178
193
  yield endEvent;
179
194
  }
180
195
  function appendOpenAIAssistantToolCall(history, toolCalls) {
@@ -302,6 +317,40 @@ function isAbortError(err) {
302
317
  return e.name === "APIUserAbortError" || e.name === "AbortError" || e.code === "ABORT_ERR" || typeof e.message === "string" && /aborted/i.test(e.message);
303
318
  }
304
319
 
320
+ // src/adapters/_metadata.ts
321
+ function makeMetadataExtractor(fields) {
322
+ return (headers) => {
323
+ const out = {};
324
+ for (const f of fields) {
325
+ const raw = headers.get(f.header);
326
+ if (raw === null || raw === void 0 || raw === "") continue;
327
+ if (f.numeric) {
328
+ const n = Number(raw);
329
+ if (Number.isFinite(n)) out[f.key] = n;
330
+ } else {
331
+ out[f.key] = raw;
332
+ }
333
+ }
334
+ return out;
335
+ };
336
+ }
337
+ function extractMetadata(fields, headers) {
338
+ const headersInstance = headers instanceof Headers ? headers : recordToHeaders(headers);
339
+ return makeMetadataExtractor(fields)(headersInstance);
340
+ }
341
+ function recordToHeaders(record) {
342
+ const h = new Headers();
343
+ for (const [name, value] of Object.entries(record)) {
344
+ if (value === void 0) continue;
345
+ if (Array.isArray(value)) {
346
+ for (const v of value) h.append(name, v);
347
+ } else {
348
+ h.set(name, value);
349
+ }
350
+ }
351
+ return h;
352
+ }
353
+
305
354
  // src/adapters/openai/manifest.ts
306
355
  var OPENAI_KNOWN_MODELS = [
307
356
  {
@@ -403,6 +452,12 @@ var openAIManifest = {
403
452
  };
404
453
 
405
454
  // src/adapters/openai/adapter.ts
455
+ var OPENAI_METADATA_EXTRACTOR = makeMetadataExtractor([
456
+ { header: "x-request-id", key: "request_id" },
457
+ { header: "openai-processing-ms", key: "processing_ms", numeric: true },
458
+ { header: "x-ratelimit-remaining-requests", key: "requests_remaining", numeric: true },
459
+ { header: "x-ratelimit-remaining-tokens", key: "tokens_remaining", numeric: true }
460
+ ]);
406
461
  var OpenAIAdapter = class {
407
462
  vendor = openAIManifest.vendor;
408
463
  acceptedAuth = ["apiKey"];
@@ -420,7 +475,8 @@ var OpenAIAdapter = class {
420
475
  }
421
476
  stream(req) {
422
477
  return streamFromOpenAI(this.ensureClient(), req, {
423
- knownModels: openAIManifest.knownModels
478
+ knownModels: openAIManifest.knownModels,
479
+ vendorMetadataExtractor: OPENAI_METADATA_EXTRACTOR
424
480
  });
425
481
  }
426
482
  appendAssistantToolCall(history, toolCalls) {
@@ -652,6 +708,12 @@ var anthropicManifest = {
652
708
  };
653
709
 
654
710
  // src/adapters/anthropic/adapter.ts
711
+ var ANTHROPIC_METADATA_EXTRACTOR = makeMetadataExtractor([
712
+ { header: "request-id", key: "request_id" },
713
+ { header: "anthropic-ratelimit-requests-remaining", key: "requests_remaining", numeric: true },
714
+ { header: "anthropic-ratelimit-input-tokens-remaining", key: "input_tokens_remaining", numeric: true },
715
+ { header: "anthropic-ratelimit-output-tokens-remaining", key: "output_tokens_remaining", numeric: true }
716
+ ]);
655
717
  var AnthropicAdapter = class {
656
718
  vendor = anthropicManifest.vendor;
657
719
  acceptedAuth = ["apiKey"];
@@ -686,11 +748,20 @@ var AnthropicAdapter = class {
686
748
  if (tools) body.tools = tools;
687
749
  if (req.temperature !== void 0) body.temperature = req.temperature;
688
750
  let stream;
751
+ let responseHeaders;
689
752
  try {
690
- stream = await client.messages.create(
753
+ const apiPromise = client.messages.create(
691
754
  body,
692
755
  { signal: req.signal }
693
756
  );
757
+ const maybeWithResponse = apiPromise.withResponse;
758
+ if (typeof maybeWithResponse === "function") {
759
+ const result = await maybeWithResponse.call(apiPromise);
760
+ stream = result.data;
761
+ responseHeaders = result.response?.headers;
762
+ } else {
763
+ stream = await apiPromise;
764
+ }
694
765
  } catch (err) {
695
766
  if (isAbortError2(err)) {
696
767
  yield { type: "end", finishReason: "aborted" };
@@ -801,6 +872,12 @@ var AnthropicAdapter = class {
801
872
  ...usage ? { usage } : {},
802
873
  ...stopReason ? { rawReason: stopReason } : {}
803
874
  };
875
+ if (responseHeaders) {
876
+ const metadata = ANTHROPIC_METADATA_EXTRACTOR(responseHeaders);
877
+ if (Object.keys(metadata).length > 0) {
878
+ endEvent.vendorMetadata = metadata;
879
+ }
880
+ }
804
881
  yield endEvent;
805
882
  }
806
883
  appendAssistantToolCall(history, toolCalls) {
@@ -1593,6 +1670,9 @@ var vertexOpenAIManifest = {
1593
1670
  };
1594
1671
 
1595
1672
  // src/adapters/vertex-openai/adapter.ts
1673
+ var VERTEX_OPENAI_METADATA_EXTRACTOR = makeMetadataExtractor([
1674
+ { header: "x-request-id", key: "request_id" }
1675
+ ]);
1596
1676
  var VertexOpenAIAdapter = class {
1597
1677
  vendor = vertexOpenAIManifest.vendor;
1598
1678
  acceptedAuth = ["vertexServiceAccount"];
@@ -1645,7 +1725,8 @@ var VertexOpenAIAdapter = class {
1645
1725
  // endpoint predates `max_completion_tokens` and may not recognize it.
1646
1726
  // The model-id heuristic wouldn't catch a partner model named in the
1647
1727
  // OpenAI style (unlikely today, but defensive).
1648
- tokensParam: "max_tokens"
1728
+ tokensParam: "max_tokens",
1729
+ vendorMetadataExtractor: VERTEX_OPENAI_METADATA_EXTRACTOR
1649
1730
  });
1650
1731
  }
1651
1732
  appendAssistantToolCall(history, toolCalls) {
@@ -2109,6 +2190,21 @@ var BedrockAdapter = class {
2109
2190
  ...usage ? { usage } : {},
2110
2191
  ...stopReason ? { rawReason: stopReason } : {}
2111
2192
  };
2193
+ const httpHeaders = response.$metadata?.httpHeaders;
2194
+ if (httpHeaders) {
2195
+ const metadata = extractMetadata(
2196
+ [
2197
+ { header: "x-amzn-bedrock-invocation-latency", key: "invocation_latency_ms", numeric: true },
2198
+ { header: "x-amzn-bedrock-cache-read-input-token-count", key: "cache_read_input_tokens", numeric: true },
2199
+ { header: "x-amzn-bedrock-cache-write-input-token-count", key: "cache_write_input_tokens", numeric: true },
2200
+ { header: "x-amzn-bedrock-trace-id", key: "trace_id" }
2201
+ ],
2202
+ httpHeaders
2203
+ );
2204
+ if (Object.keys(metadata).length > 0) {
2205
+ endEvent.vendorMetadata = metadata;
2206
+ }
2207
+ }
2112
2208
  yield endEvent;
2113
2209
  }
2114
2210
  appendAssistantToolCall(history, toolCalls) {
@@ -2360,6 +2456,14 @@ var azureOpenAIManifest = {
2360
2456
  };
2361
2457
 
2362
2458
  // src/adapters/azure-openai/adapter.ts
2459
+ var AZURE_OPENAI_METADATA_EXTRACTOR = makeMetadataExtractor([
2460
+ { header: "x-ms-region", key: "region" },
2461
+ { header: "x-ms-deployment-name", key: "deployment" },
2462
+ { header: "apim-request-id", key: "request_id" },
2463
+ { header: "azureml-model-session", key: "model_session" },
2464
+ { header: "x-ratelimit-remaining-requests", key: "requests_remaining", numeric: true },
2465
+ { header: "x-ratelimit-remaining-tokens", key: "tokens_remaining", numeric: true }
2466
+ ]);
2363
2467
  var AzureOpenAIAdapter = class {
2364
2468
  vendor = azureOpenAIManifest.vendor;
2365
2469
  acceptedAuth = ["azureOpenAIApiKey"];
@@ -2394,7 +2498,8 @@ var AzureOpenAIAdapter = class {
2394
2498
  stream(req) {
2395
2499
  return streamFromOpenAI(this.ensureClient(), req, {
2396
2500
  knownModels: azureOpenAIManifest.knownModels,
2397
- tokensParam: "max_completion_tokens"
2501
+ tokensParam: "max_completion_tokens",
2502
+ vendorMetadataExtractor: AZURE_OPENAI_METADATA_EXTRACTOR
2398
2503
  });
2399
2504
  }
2400
2505
  appendAssistantToolCall(history, toolCalls) {
@@ -2519,6 +2624,12 @@ var groqManifest = {
2519
2624
  };
2520
2625
 
2521
2626
  // src/adapters/groq/adapter.ts
2627
+ var GROQ_METADATA_EXTRACTOR = makeMetadataExtractor([
2628
+ { header: "x-request-id", key: "request_id" },
2629
+ { header: "x-groq-region", key: "region" },
2630
+ { header: "x-ratelimit-remaining-requests", key: "requests_remaining", numeric: true },
2631
+ { header: "x-ratelimit-remaining-tokens", key: "tokens_remaining", numeric: true }
2632
+ ]);
2522
2633
  var GroqAdapter = class extends OpenAIAdapter {
2523
2634
  vendor = groqManifest.vendor;
2524
2635
  init(auth, client) {
@@ -2530,6 +2641,12 @@ var GroqAdapter = class extends OpenAIAdapter {
2530
2641
  client
2531
2642
  );
2532
2643
  }
2644
+ stream(req) {
2645
+ return streamFromOpenAI(this.ensureClient(), req, {
2646
+ knownModels: groqManifest.knownModels,
2647
+ vendorMetadataExtractor: GROQ_METADATA_EXTRACTOR
2648
+ });
2649
+ }
2533
2650
  };
2534
2651
 
2535
2652
  // src/adapters/groq/factory.ts
@@ -2539,6 +2656,127 @@ var groqFactory = {
2539
2656
  create: () => new GroqAdapter()
2540
2657
  };
2541
2658
 
2659
+ // src/adapters/huggingface/manifest.ts
2660
+ var HF_KNOWN_MODELS = [
2661
+ {
2662
+ id: "meta-llama/Llama-3.3-70B-Instruct",
2663
+ displayName: "Llama 3.3 70B Instruct (HF Providers)",
2664
+ capabilities: {
2665
+ streaming: true,
2666
+ tools: true,
2667
+ vision: false,
2668
+ systemPrompt: true,
2669
+ maxContextTokens: 128e3
2670
+ }
2671
+ },
2672
+ {
2673
+ id: "meta-llama/Llama-3.1-8B-Instruct",
2674
+ displayName: "Llama 3.1 8B Instruct (HF Providers)",
2675
+ capabilities: {
2676
+ streaming: true,
2677
+ tools: true,
2678
+ vision: false,
2679
+ systemPrompt: true,
2680
+ maxContextTokens: 128e3
2681
+ }
2682
+ },
2683
+ {
2684
+ id: "Qwen/Qwen2.5-72B-Instruct",
2685
+ displayName: "Qwen 2.5 72B Instruct (HF Providers)",
2686
+ capabilities: {
2687
+ streaming: true,
2688
+ tools: true,
2689
+ vision: false,
2690
+ systemPrompt: true,
2691
+ maxContextTokens: 128e3
2692
+ }
2693
+ },
2694
+ {
2695
+ id: "mistralai/Mistral-7B-Instruct-v0.3",
2696
+ displayName: "Mistral 7B Instruct v0.3 (HF Providers)",
2697
+ capabilities: {
2698
+ streaming: true,
2699
+ tools: true,
2700
+ vision: false,
2701
+ systemPrompt: true,
2702
+ maxContextTokens: 32e3
2703
+ }
2704
+ },
2705
+ {
2706
+ id: "deepseek-ai/DeepSeek-V3",
2707
+ displayName: "DeepSeek V3 (HF Providers)",
2708
+ capabilities: {
2709
+ streaming: true,
2710
+ tools: true,
2711
+ vision: false,
2712
+ systemPrompt: true,
2713
+ maxContextTokens: 64e3
2714
+ }
2715
+ }
2716
+ ];
2717
+ var huggingfaceManifest = {
2718
+ vendor: "huggingface",
2719
+ displayName: "HuggingFace Inference Providers",
2720
+ authKinds: [
2721
+ {
2722
+ kind: "apiKey",
2723
+ displayName: "API Key",
2724
+ fields: [
2725
+ {
2726
+ name: "apiKey",
2727
+ label: "HuggingFace Token",
2728
+ type: "password",
2729
+ required: true,
2730
+ help: "Get a token from https://huggingface.co/settings/tokens (Read scope is sufficient). Inference Providers requires a credit balance \u2014 claim the free monthly tier or attach a payment method at https://huggingface.co/billing."
2731
+ },
2732
+ {
2733
+ name: "baseURL",
2734
+ label: "Base URL",
2735
+ type: "url",
2736
+ required: false,
2737
+ default: "https://router.huggingface.co/v1",
2738
+ help: "Override only for proxies. Default is the HF Providers router endpoint."
2739
+ }
2740
+ ]
2741
+ }
2742
+ ],
2743
+ knownModels: HF_KNOWN_MODELS,
2744
+ // The HF router exposes /v1/models with the same Bearer auth.
2745
+ supportsModelListing: true,
2746
+ docsUrl: "https://huggingface.co/docs/inference-providers"
2747
+ };
2748
+
2749
+ // src/adapters/huggingface/adapter.ts
2750
+ var HUGGINGFACE_METADATA_EXTRACTOR = makeMetadataExtractor([
2751
+ { header: "x-inference-provider", key: "provider" },
2752
+ { header: "x-request-id", key: "request_id" }
2753
+ ]);
2754
+ var HuggingfaceAdapter = class extends OpenAIAdapter {
2755
+ vendor = huggingfaceManifest.vendor;
2756
+ init(auth, client) {
2757
+ super.init(
2758
+ {
2759
+ ...auth,
2760
+ baseURL: auth.baseURL ?? "https://router.huggingface.co/v1"
2761
+ },
2762
+ client
2763
+ );
2764
+ }
2765
+ stream(req) {
2766
+ return streamFromOpenAI(this.ensureClient(), req, {
2767
+ knownModels: huggingfaceManifest.knownModels,
2768
+ vendorMetadataExtractor: HUGGINGFACE_METADATA_EXTRACTOR
2769
+ });
2770
+ }
2771
+ };
2772
+
2773
+ // src/adapters/huggingface/factory.ts
2774
+ var huggingfaceFactory = {
2775
+ vendor: huggingfaceManifest.vendor,
2776
+ manifest: huggingfaceManifest,
2777
+ create: () => new HuggingfaceAdapter()
2778
+ };
2779
+
2542
2780
  // src/adapters/index.ts
2543
2781
  registerAdapter(openAIFactory);
2544
2782
  registerAdapter(deepseekFactory);
@@ -2549,6 +2787,7 @@ registerAdapter(vertexOpenAIFactory);
2549
2787
  registerAdapter(bedrockFactory);
2550
2788
  registerAdapter(azureOpenAIFactory);
2551
2789
  registerAdapter(groqFactory);
2790
+ registerAdapter(huggingfaceFactory);
2552
2791
 
2553
2792
  // src/index.ts
2554
2793
  async function createLlm(args) {