@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.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as ServiceAccountJson, A as AuthSpec, a as AuthKindSchema, P as PromptRequest, b as AdapterFactory, c as AdapterManifest, C as CreateLlmArgs, L as LlmAdapter } from './types-DbqWrdT6.cjs';
2
- export { d as ApiKeyAuth, e as AuthKind, f as AzureOpenAIApiKeyAuth, B as BedrockApiKeyAuth, g as BedrockIamAuth, h as ClientOptions, i as ContentBlock, F as FinishReason, j as FormField, k as FormFieldType, G as GoogleApiKeyAuth, l as GoogleServiceAccountAuth, J as JsonSchema, m as LlmEvent, M as Message, n as ModelCapabilities, o as ModelInfo, R as Role, T as Tool, p as ToolCallEvent, U as Usage, V as VertexServiceAccountAuth } from './types-DbqWrdT6.cjs';
1
+ import { S as ServiceAccountJson, A as AuthSpec, a as AuthKindSchema, P as PromptRequest, b as AdapterFactory, c as AdapterManifest, C as CreateLlmArgs, L as LlmAdapter } from './types-BEgQaQIb.cjs';
2
+ export { d as ApiKeyAuth, e as AuthKind, f as AzureOpenAIApiKeyAuth, B as BedrockApiKeyAuth, g as BedrockIamAuth, h as ClientOptions, i as ContentBlock, F as FinishReason, j as FormField, k as FormFieldType, G as GoogleApiKeyAuth, l as GoogleServiceAccountAuth, J as JsonSchema, m as LlmEvent, M as Message, n as ModelCapabilities, o as ModelInfo, R as Role, T as Tool, p as ToolCallEvent, U as Usage, V as VertexServiceAccountAuth } from './types-BEgQaQIb.cjs';
3
3
 
4
4
  /**
5
5
  * The loose "DB-shape" input accepted by `normalizeAuth`.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as ServiceAccountJson, A as AuthSpec, a as AuthKindSchema, P as PromptRequest, b as AdapterFactory, c as AdapterManifest, C as CreateLlmArgs, L as LlmAdapter } from './types-DbqWrdT6.js';
2
- export { d as ApiKeyAuth, e as AuthKind, f as AzureOpenAIApiKeyAuth, B as BedrockApiKeyAuth, g as BedrockIamAuth, h as ClientOptions, i as ContentBlock, F as FinishReason, j as FormField, k as FormFieldType, G as GoogleApiKeyAuth, l as GoogleServiceAccountAuth, J as JsonSchema, m as LlmEvent, M as Message, n as ModelCapabilities, o as ModelInfo, R as Role, T as Tool, p as ToolCallEvent, U as Usage, V as VertexServiceAccountAuth } from './types-DbqWrdT6.js';
1
+ import { S as ServiceAccountJson, A as AuthSpec, a as AuthKindSchema, P as PromptRequest, b as AdapterFactory, c as AdapterManifest, C as CreateLlmArgs, L as LlmAdapter } from './types-BEgQaQIb.js';
2
+ export { d as ApiKeyAuth, e as AuthKind, f as AzureOpenAIApiKeyAuth, B as BedrockApiKeyAuth, g as BedrockIamAuth, h as ClientOptions, i as ContentBlock, F as FinishReason, j as FormField, k as FormFieldType, G as GoogleApiKeyAuth, l as GoogleServiceAccountAuth, J as JsonSchema, m as LlmEvent, M as Message, n as ModelCapabilities, o as ModelInfo, R as Role, T as Tool, p as ToolCallEvent, U as Usage, V as VertexServiceAccountAuth } from './types-BEgQaQIb.js';
3
3
 
4
4
  /**
5
5
  * The loose "DB-shape" input accepted by `normalizeAuth`.
package/dist/index.js CHANGED
@@ -85,9 +85,22 @@ async function* streamFromOpenAI(client, req, options) {
85
85
  const param = options.tokensParam ?? (needsMaxCompletionTokens(req.model) ? "max_completion_tokens" : "max_tokens");
86
86
  body[param] = effectiveMaxTokens;
87
87
  }
88
+ const t0 = process.hrtime.bigint();
89
+ let t1;
90
+ let t2;
88
91
  let stream;
92
+ let responseHeaders;
89
93
  try {
90
- stream = await client.chat.completions.create(body, { signal: req.signal });
94
+ const apiPromise = client.chat.completions.create(body, { signal: req.signal });
95
+ const maybeWithResponse = apiPromise.withResponse;
96
+ if (typeof maybeWithResponse === "function") {
97
+ const result = await maybeWithResponse.call(apiPromise);
98
+ stream = result.data;
99
+ responseHeaders = result.response?.headers;
100
+ } else {
101
+ stream = await apiPromise;
102
+ }
103
+ t1 = process.hrtime.bigint();
91
104
  } catch (err) {
92
105
  if (isAbortError(err)) {
93
106
  yield { type: "end", finishReason: "aborted" };
@@ -119,6 +132,7 @@ async function* streamFromOpenAI(client, req, options) {
119
132
  const delta = choice.delta;
120
133
  const finishReason = choice.finish_reason;
121
134
  if (delta?.content) {
135
+ if (t2 === void 0) t2 = process.hrtime.bigint();
122
136
  yield { type: "token", text: delta.content };
123
137
  }
124
138
  if (delta?.tool_calls) {
@@ -182,6 +196,20 @@ async function* streamFromOpenAI(client, req, options) {
182
196
  ...usage ? { usage } : {},
183
197
  ...finalRawReason ? { rawReason: finalRawReason } : {}
184
198
  };
199
+ if (options.vendorMetadataExtractor && responseHeaders) {
200
+ const metadata = options.vendorMetadataExtractor(responseHeaders);
201
+ if (metadata && Object.keys(metadata).length > 0) {
202
+ endEvent.vendorMetadata = metadata;
203
+ }
204
+ }
205
+ if (t1 !== void 0) {
206
+ const t3 = process.hrtime.bigint();
207
+ endEvent.clientTiming = {
208
+ requestToHeadersMs: Number(t1 - t0) / 1e6,
209
+ ...t2 !== void 0 ? { headersToFirstTokenMs: Number(t2 - t1) / 1e6 } : {},
210
+ totalMs: Number(t3 - t0) / 1e6
211
+ };
212
+ }
185
213
  yield endEvent;
186
214
  }
187
215
  function appendOpenAIAssistantToolCall(history, toolCalls) {
@@ -309,6 +337,40 @@ function isAbortError(err) {
309
337
  return e.name === "APIUserAbortError" || e.name === "AbortError" || e.code === "ABORT_ERR" || typeof e.message === "string" && /aborted/i.test(e.message);
310
338
  }
311
339
 
340
+ // src/adapters/_metadata.ts
341
+ function makeMetadataExtractor(fields) {
342
+ return (headers) => {
343
+ const out = {};
344
+ for (const f of fields) {
345
+ const raw = headers.get(f.header);
346
+ if (raw === null || raw === void 0 || raw === "") continue;
347
+ if (f.numeric) {
348
+ const n = Number(raw);
349
+ if (Number.isFinite(n)) out[f.key] = n;
350
+ } else {
351
+ out[f.key] = raw;
352
+ }
353
+ }
354
+ return out;
355
+ };
356
+ }
357
+ function extractMetadata(fields, headers) {
358
+ const headersInstance = headers instanceof Headers ? headers : recordToHeaders(headers);
359
+ return makeMetadataExtractor(fields)(headersInstance);
360
+ }
361
+ function recordToHeaders(record) {
362
+ const h = new Headers();
363
+ for (const [name, value] of Object.entries(record)) {
364
+ if (value === void 0) continue;
365
+ if (Array.isArray(value)) {
366
+ for (const v of value) h.append(name, v);
367
+ } else {
368
+ h.set(name, value);
369
+ }
370
+ }
371
+ return h;
372
+ }
373
+
312
374
  // src/adapters/openai/manifest.ts
313
375
  var OPENAI_KNOWN_MODELS = [
314
376
  {
@@ -410,6 +472,12 @@ var openAIManifest = {
410
472
  };
411
473
 
412
474
  // src/adapters/openai/adapter.ts
475
+ var OPENAI_METADATA_EXTRACTOR = makeMetadataExtractor([
476
+ { header: "x-request-id", key: "request_id" },
477
+ { header: "openai-processing-ms", key: "processing_ms", numeric: true },
478
+ { header: "x-ratelimit-remaining-requests", key: "requests_remaining", numeric: true },
479
+ { header: "x-ratelimit-remaining-tokens", key: "tokens_remaining", numeric: true }
480
+ ]);
413
481
  var OpenAIAdapter = class {
414
482
  vendor = openAIManifest.vendor;
415
483
  acceptedAuth = ["apiKey"];
@@ -427,7 +495,8 @@ var OpenAIAdapter = class {
427
495
  }
428
496
  stream(req) {
429
497
  return streamFromOpenAI(this.ensureClient(), req, {
430
- knownModels: openAIManifest.knownModels
498
+ knownModels: openAIManifest.knownModels,
499
+ vendorMetadataExtractor: OPENAI_METADATA_EXTRACTOR
431
500
  });
432
501
  }
433
502
  appendAssistantToolCall(history, toolCalls) {
@@ -659,6 +728,12 @@ var anthropicManifest = {
659
728
  };
660
729
 
661
730
  // src/adapters/anthropic/adapter.ts
731
+ var ANTHROPIC_METADATA_EXTRACTOR = makeMetadataExtractor([
732
+ { header: "request-id", key: "request_id" },
733
+ { header: "anthropic-ratelimit-requests-remaining", key: "requests_remaining", numeric: true },
734
+ { header: "anthropic-ratelimit-input-tokens-remaining", key: "input_tokens_remaining", numeric: true },
735
+ { header: "anthropic-ratelimit-output-tokens-remaining", key: "output_tokens_remaining", numeric: true }
736
+ ]);
662
737
  var AnthropicAdapter = class {
663
738
  vendor = anthropicManifest.vendor;
664
739
  acceptedAuth = ["apiKey"];
@@ -693,11 +768,20 @@ var AnthropicAdapter = class {
693
768
  if (tools) body.tools = tools;
694
769
  if (req.temperature !== void 0) body.temperature = req.temperature;
695
770
  let stream;
771
+ let responseHeaders;
696
772
  try {
697
- stream = await client.messages.create(
773
+ const apiPromise = client.messages.create(
698
774
  body,
699
775
  { signal: req.signal }
700
776
  );
777
+ const maybeWithResponse = apiPromise.withResponse;
778
+ if (typeof maybeWithResponse === "function") {
779
+ const result = await maybeWithResponse.call(apiPromise);
780
+ stream = result.data;
781
+ responseHeaders = result.response?.headers;
782
+ } else {
783
+ stream = await apiPromise;
784
+ }
701
785
  } catch (err) {
702
786
  if (isAbortError2(err)) {
703
787
  yield { type: "end", finishReason: "aborted" };
@@ -808,6 +892,12 @@ var AnthropicAdapter = class {
808
892
  ...usage ? { usage } : {},
809
893
  ...stopReason ? { rawReason: stopReason } : {}
810
894
  };
895
+ if (responseHeaders) {
896
+ const metadata = ANTHROPIC_METADATA_EXTRACTOR(responseHeaders);
897
+ if (Object.keys(metadata).length > 0) {
898
+ endEvent.vendorMetadata = metadata;
899
+ }
900
+ }
811
901
  yield endEvent;
812
902
  }
813
903
  appendAssistantToolCall(history, toolCalls) {
@@ -1600,6 +1690,9 @@ var vertexOpenAIManifest = {
1600
1690
  };
1601
1691
 
1602
1692
  // src/adapters/vertex-openai/adapter.ts
1693
+ var VERTEX_OPENAI_METADATA_EXTRACTOR = makeMetadataExtractor([
1694
+ { header: "x-request-id", key: "request_id" }
1695
+ ]);
1603
1696
  var VertexOpenAIAdapter = class {
1604
1697
  vendor = vertexOpenAIManifest.vendor;
1605
1698
  acceptedAuth = ["vertexServiceAccount"];
@@ -1652,7 +1745,8 @@ var VertexOpenAIAdapter = class {
1652
1745
  // endpoint predates `max_completion_tokens` and may not recognize it.
1653
1746
  // The model-id heuristic wouldn't catch a partner model named in the
1654
1747
  // OpenAI style (unlikely today, but defensive).
1655
- tokensParam: "max_tokens"
1748
+ tokensParam: "max_tokens",
1749
+ vendorMetadataExtractor: VERTEX_OPENAI_METADATA_EXTRACTOR
1656
1750
  });
1657
1751
  }
1658
1752
  appendAssistantToolCall(history, toolCalls) {
@@ -2116,6 +2210,21 @@ var BedrockAdapter = class {
2116
2210
  ...usage ? { usage } : {},
2117
2211
  ...stopReason ? { rawReason: stopReason } : {}
2118
2212
  };
2213
+ const httpHeaders = response.$metadata?.httpHeaders;
2214
+ if (httpHeaders) {
2215
+ const metadata = extractMetadata(
2216
+ [
2217
+ { header: "x-amzn-bedrock-invocation-latency", key: "invocation_latency_ms", numeric: true },
2218
+ { header: "x-amzn-bedrock-cache-read-input-token-count", key: "cache_read_input_tokens", numeric: true },
2219
+ { header: "x-amzn-bedrock-cache-write-input-token-count", key: "cache_write_input_tokens", numeric: true },
2220
+ { header: "x-amzn-bedrock-trace-id", key: "trace_id" }
2221
+ ],
2222
+ httpHeaders
2223
+ );
2224
+ if (Object.keys(metadata).length > 0) {
2225
+ endEvent.vendorMetadata = metadata;
2226
+ }
2227
+ }
2119
2228
  yield endEvent;
2120
2229
  }
2121
2230
  appendAssistantToolCall(history, toolCalls) {
@@ -2367,6 +2476,14 @@ var azureOpenAIManifest = {
2367
2476
  };
2368
2477
 
2369
2478
  // src/adapters/azure-openai/adapter.ts
2479
+ var AZURE_OPENAI_METADATA_EXTRACTOR = makeMetadataExtractor([
2480
+ { header: "x-ms-region", key: "region" },
2481
+ { header: "x-ms-deployment-name", key: "deployment" },
2482
+ { header: "apim-request-id", key: "request_id" },
2483
+ { header: "azureml-model-session", key: "model_session" },
2484
+ { header: "x-ratelimit-remaining-requests", key: "requests_remaining", numeric: true },
2485
+ { header: "x-ratelimit-remaining-tokens", key: "tokens_remaining", numeric: true }
2486
+ ]);
2370
2487
  var AzureOpenAIAdapter = class {
2371
2488
  vendor = azureOpenAIManifest.vendor;
2372
2489
  acceptedAuth = ["azureOpenAIApiKey"];
@@ -2401,7 +2518,8 @@ var AzureOpenAIAdapter = class {
2401
2518
  stream(req) {
2402
2519
  return streamFromOpenAI(this.ensureClient(), req, {
2403
2520
  knownModels: azureOpenAIManifest.knownModels,
2404
- tokensParam: "max_completion_tokens"
2521
+ tokensParam: "max_completion_tokens",
2522
+ vendorMetadataExtractor: AZURE_OPENAI_METADATA_EXTRACTOR
2405
2523
  });
2406
2524
  }
2407
2525
  appendAssistantToolCall(history, toolCalls) {
@@ -2526,6 +2644,12 @@ var groqManifest = {
2526
2644
  };
2527
2645
 
2528
2646
  // src/adapters/groq/adapter.ts
2647
+ var GROQ_METADATA_EXTRACTOR = makeMetadataExtractor([
2648
+ { header: "x-request-id", key: "request_id" },
2649
+ { header: "x-groq-region", key: "region" },
2650
+ { header: "x-ratelimit-remaining-requests", key: "requests_remaining", numeric: true },
2651
+ { header: "x-ratelimit-remaining-tokens", key: "tokens_remaining", numeric: true }
2652
+ ]);
2529
2653
  var GroqAdapter = class extends OpenAIAdapter {
2530
2654
  vendor = groqManifest.vendor;
2531
2655
  init(auth, client) {
@@ -2537,6 +2661,12 @@ var GroqAdapter = class extends OpenAIAdapter {
2537
2661
  client
2538
2662
  );
2539
2663
  }
2664
+ stream(req) {
2665
+ return streamFromOpenAI(this.ensureClient(), req, {
2666
+ knownModels: groqManifest.knownModels,
2667
+ vendorMetadataExtractor: GROQ_METADATA_EXTRACTOR
2668
+ });
2669
+ }
2540
2670
  };
2541
2671
 
2542
2672
  // src/adapters/groq/factory.ts
@@ -2637,6 +2767,10 @@ var huggingfaceManifest = {
2637
2767
  };
2638
2768
 
2639
2769
  // src/adapters/huggingface/adapter.ts
2770
+ var HUGGINGFACE_METADATA_EXTRACTOR = makeMetadataExtractor([
2771
+ { header: "x-inference-provider", key: "provider" },
2772
+ { header: "x-request-id", key: "request_id" }
2773
+ ]);
2640
2774
  var HuggingfaceAdapter = class extends OpenAIAdapter {
2641
2775
  vendor = huggingfaceManifest.vendor;
2642
2776
  init(auth, client) {
@@ -2648,6 +2782,12 @@ var HuggingfaceAdapter = class extends OpenAIAdapter {
2648
2782
  client
2649
2783
  );
2650
2784
  }
2785
+ stream(req) {
2786
+ return streamFromOpenAI(this.ensureClient(), req, {
2787
+ knownModels: huggingfaceManifest.knownModels,
2788
+ vendorMetadataExtractor: HUGGINGFACE_METADATA_EXTRACTOR
2789
+ });
2790
+ }
2651
2791
  };
2652
2792
 
2653
2793
  // src/adapters/huggingface/factory.ts