@jambonz/llm 0.3.4 → 0.4.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, P as PromptRequest, a as AdapterFactory, b as AdapterManifest, C as CreateLlmArgs, L as LlmAdapter } from './types-4d2QrlAe.cjs';
2
- export { c as ApiKeyAuth, d as AuthKind, e as AuthKindSchema, B as BedrockApiKeyAuth, f as BedrockIamAuth, g as ClientOptions, h as ContentBlock, F as FinishReason, i as FormField, j as FormFieldType, G as GoogleApiKeyAuth, k as GoogleServiceAccountAuth, J as JsonSchema, l as LlmEvent, M as Message, m as ModelCapabilities, n as ModelInfo, R as Role, T as Tool, o as ToolCallEvent, U as Usage, V as VertexServiceAccountAuth } from './types-4d2QrlAe.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-DxknK0Rc.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-DxknK0Rc.cjs';
3
3
 
4
4
  /**
5
5
  * The loose "DB-shape" input accepted by `normalizeAuth`.
@@ -21,18 +21,46 @@ interface RawCredential {
21
21
  api_url?: string | null;
22
22
  project_id?: string | null;
23
23
  location?: string | null;
24
+ /** Azure OpenAI resource endpoint, e.g. `https://my-resource.openai.azure.com`. */
25
+ endpoint?: string | null;
26
+ /** Azure OpenAI deployment name (the user-created deployment, not the model id). */
27
+ deployment?: string | null;
28
+ /** Azure OpenAI data-plane api-version, e.g. `2024-10-21`. */
29
+ api_version?: string | null;
24
30
  }
25
31
  /**
26
32
  * Convert a vendor + raw credential into an `AuthSpec` discriminated union member.
27
33
  *
28
34
  * Supported vendors: openai, deepseek, anthropic, google, vertex (alias for
29
35
  * vertex-gemini + vertex-openai — both accept the same auth shape), vertex-gemini,
30
- * vertex-openai, bedrock.
36
+ * vertex-openai, bedrock, azure-openai.
31
37
  *
32
38
  * Throws with a clear message if the raw credential is missing required fields.
33
39
  */
34
40
  declare function normalizeAuth(vendor: string, raw: RawCredential): AuthSpec;
35
41
 
42
+ /**
43
+ * Given a vendor id and a raw snake_case credential blob, return the
44
+ * `AuthKindSchema` from the vendor's manifest that matches the blob.
45
+ *
46
+ * Purpose: let credential-handling consumers (api-server's `encryptCredential`
47
+ * in particular) validate and serialize the *right* set of fields for a
48
+ * credential without carrying a per-vendor switch of their own. The
49
+ * discriminator logic that distinguishes e.g. `bedrockApiKey` from
50
+ * `bedrockIam` lives here, in the library, right next to `normalizeAuth`.
51
+ *
52
+ * Rules:
53
+ * - Vendor with a single `authKind`: that kind is returned unconditionally.
54
+ * - Bedrock: `access_key_id` + `secret_access_key` → `bedrockIam`; else `bedrockApiKey`.
55
+ * - Google: `service_key` present → `googleServiceAccount`; `api_key` present → `googleApiKey`.
56
+ *
57
+ * Throws if the vendor is unknown or if no declared authKind matches the blob.
58
+ */
59
+ interface RawCredentialLoose extends RawCredential {
60
+ [key: string]: unknown;
61
+ }
62
+ declare function pickAuthKind(vendor: string, raw: RawCredentialLoose): AuthKindSchema;
63
+
36
64
  /**
37
65
  * Validate a PromptRequest against the library's universal preconditions.
38
66
  *
@@ -92,9 +120,11 @@ declare function getManifest(): {
92
120
  * - `createLlm({vendor, auth, client?})` to get a ready-to-stream adapter instance.
93
121
  * - `getManifest()` to enumerate registered vendors (used by api-server).
94
122
  * - `normalizeAuth(vendor, rawCred)` to convert DB-shape creds to AuthSpec.
123
+ * - `pickAuthKind(vendor, rawCred)` to pick the right manifest authKind for
124
+ * a raw credential (used by api-server's `encryptCredential`).
95
125
  * - `registerAdapter(factory)` to add a custom adapter at runtime.
96
126
  */
97
127
 
98
128
  declare function createLlm<A extends AuthSpec = AuthSpec>(args: CreateLlmArgs<A>): Promise<LlmAdapter<A>>;
99
129
 
100
- export { AdapterFactory, AdapterManifest, AuthSpec, CreateLlmArgs, LlmAdapter, PromptRequest, type RawCredential, ServiceAccountJson, assertValidRequest, createLlm, getAdapterFactory, getManifest, listVendors, normalizeAuth, registerAdapter, replaceAdapter, unregisterAdapter };
130
+ export { AdapterFactory, AdapterManifest, AuthKindSchema, AuthSpec, CreateLlmArgs, LlmAdapter, PromptRequest, type RawCredential, type RawCredentialLoose, ServiceAccountJson, assertValidRequest, createLlm, getAdapterFactory, getManifest, listVendors, normalizeAuth, pickAuthKind, registerAdapter, replaceAdapter, unregisterAdapter };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as ServiceAccountJson, A as AuthSpec, P as PromptRequest, a as AdapterFactory, b as AdapterManifest, C as CreateLlmArgs, L as LlmAdapter } from './types-4d2QrlAe.js';
2
- export { c as ApiKeyAuth, d as AuthKind, e as AuthKindSchema, B as BedrockApiKeyAuth, f as BedrockIamAuth, g as ClientOptions, h as ContentBlock, F as FinishReason, i as FormField, j as FormFieldType, G as GoogleApiKeyAuth, k as GoogleServiceAccountAuth, J as JsonSchema, l as LlmEvent, M as Message, m as ModelCapabilities, n as ModelInfo, R as Role, T as Tool, o as ToolCallEvent, U as Usage, V as VertexServiceAccountAuth } from './types-4d2QrlAe.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-DxknK0Rc.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-DxknK0Rc.js';
3
3
 
4
4
  /**
5
5
  * The loose "DB-shape" input accepted by `normalizeAuth`.
@@ -21,18 +21,46 @@ interface RawCredential {
21
21
  api_url?: string | null;
22
22
  project_id?: string | null;
23
23
  location?: string | null;
24
+ /** Azure OpenAI resource endpoint, e.g. `https://my-resource.openai.azure.com`. */
25
+ endpoint?: string | null;
26
+ /** Azure OpenAI deployment name (the user-created deployment, not the model id). */
27
+ deployment?: string | null;
28
+ /** Azure OpenAI data-plane api-version, e.g. `2024-10-21`. */
29
+ api_version?: string | null;
24
30
  }
25
31
  /**
26
32
  * Convert a vendor + raw credential into an `AuthSpec` discriminated union member.
27
33
  *
28
34
  * Supported vendors: openai, deepseek, anthropic, google, vertex (alias for
29
35
  * vertex-gemini + vertex-openai — both accept the same auth shape), vertex-gemini,
30
- * vertex-openai, bedrock.
36
+ * vertex-openai, bedrock, azure-openai.
31
37
  *
32
38
  * Throws with a clear message if the raw credential is missing required fields.
33
39
  */
34
40
  declare function normalizeAuth(vendor: string, raw: RawCredential): AuthSpec;
35
41
 
42
+ /**
43
+ * Given a vendor id and a raw snake_case credential blob, return the
44
+ * `AuthKindSchema` from the vendor's manifest that matches the blob.
45
+ *
46
+ * Purpose: let credential-handling consumers (api-server's `encryptCredential`
47
+ * in particular) validate and serialize the *right* set of fields for a
48
+ * credential without carrying a per-vendor switch of their own. The
49
+ * discriminator logic that distinguishes e.g. `bedrockApiKey` from
50
+ * `bedrockIam` lives here, in the library, right next to `normalizeAuth`.
51
+ *
52
+ * Rules:
53
+ * - Vendor with a single `authKind`: that kind is returned unconditionally.
54
+ * - Bedrock: `access_key_id` + `secret_access_key` → `bedrockIam`; else `bedrockApiKey`.
55
+ * - Google: `service_key` present → `googleServiceAccount`; `api_key` present → `googleApiKey`.
56
+ *
57
+ * Throws if the vendor is unknown or if no declared authKind matches the blob.
58
+ */
59
+ interface RawCredentialLoose extends RawCredential {
60
+ [key: string]: unknown;
61
+ }
62
+ declare function pickAuthKind(vendor: string, raw: RawCredentialLoose): AuthKindSchema;
63
+
36
64
  /**
37
65
  * Validate a PromptRequest against the library's universal preconditions.
38
66
  *
@@ -92,9 +120,11 @@ declare function getManifest(): {
92
120
  * - `createLlm({vendor, auth, client?})` to get a ready-to-stream adapter instance.
93
121
  * - `getManifest()` to enumerate registered vendors (used by api-server).
94
122
  * - `normalizeAuth(vendor, rawCred)` to convert DB-shape creds to AuthSpec.
123
+ * - `pickAuthKind(vendor, rawCred)` to pick the right manifest authKind for
124
+ * a raw credential (used by api-server's `encryptCredential`).
95
125
  * - `registerAdapter(factory)` to add a custom adapter at runtime.
96
126
  */
97
127
 
98
128
  declare function createLlm<A extends AuthSpec = AuthSpec>(args: CreateLlmArgs<A>): Promise<LlmAdapter<A>>;
99
129
 
100
- export { AdapterFactory, AdapterManifest, AuthSpec, CreateLlmArgs, LlmAdapter, PromptRequest, type RawCredential, ServiceAccountJson, assertValidRequest, createLlm, getAdapterFactory, getManifest, listVendors, normalizeAuth, registerAdapter, replaceAdapter, unregisterAdapter };
130
+ export { AdapterFactory, AdapterManifest, AuthKindSchema, AuthSpec, CreateLlmArgs, LlmAdapter, PromptRequest, type RawCredential, type RawCredentialLoose, ServiceAccountJson, assertValidRequest, createLlm, getAdapterFactory, getManifest, listVendors, normalizeAuth, pickAuthKind, registerAdapter, replaceAdapter, unregisterAdapter };
package/dist/index.js CHANGED
@@ -81,7 +81,10 @@ async function* streamFromOpenAI(client, req, options) {
81
81
  }
82
82
  if (req.temperature !== void 0) body.temperature = req.temperature;
83
83
  const effectiveMaxTokens = req.maxTokens ?? options.defaultMaxTokens;
84
- if (effectiveMaxTokens !== void 0) body.max_tokens = effectiveMaxTokens;
84
+ if (effectiveMaxTokens !== void 0) {
85
+ const param = options.tokensParam ?? (needsMaxCompletionTokens(req.model) ? "max_completion_tokens" : "max_tokens");
86
+ body[param] = effectiveMaxTokens;
87
+ }
85
88
  let stream;
86
89
  try {
87
90
  stream = await client.chat.completions.create(body, { signal: req.signal });
@@ -264,6 +267,9 @@ function capabilitiesFor(modelId, knownModels) {
264
267
  if (known) return known.capabilities;
265
268
  return defaultCapabilitiesForUnknown(modelId);
266
269
  }
270
+ function needsMaxCompletionTokens(modelId) {
271
+ return /^(o\d|gpt-5)/i.test(modelId);
272
+ }
267
273
  function defaultCapabilitiesForUnknown(modelId) {
268
274
  const isReasoning = /^o[13]([-/]|$)/i.test(modelId);
269
275
  if (isReasoning) {
@@ -1641,7 +1647,12 @@ var VertexOpenAIAdapter = class {
1641
1647
  stream(req) {
1642
1648
  return streamFromOpenAI(this.ensureClient(), req, {
1643
1649
  knownModels: vertexOpenAIManifest.knownModels,
1644
- defaultMaxTokens: 4096
1650
+ defaultMaxTokens: 4096,
1651
+ // Pin legacy `max_tokens`: Vertex's OpenAI-compat partner-model
1652
+ // endpoint predates `max_completion_tokens` and may not recognize it.
1653
+ // The model-id heuristic wouldn't catch a partner model named in the
1654
+ // OpenAI style (unlikely today, but defensive).
1655
+ tokensParam: "max_tokens"
1645
1656
  });
1646
1657
  }
1647
1658
  appendAssistantToolCall(history, toolCalls) {
@@ -2232,6 +2243,211 @@ var bedrockFactory = {
2232
2243
  create: () => new BedrockAdapter()
2233
2244
  };
2234
2245
 
2246
+ // src/adapters/azure-openai/adapter.ts
2247
+ import { AzureOpenAI } from "openai";
2248
+
2249
+ // src/adapters/azure-openai/manifest.ts
2250
+ var AZURE_OPENAI_KNOWN_MODELS = [
2251
+ {
2252
+ id: "gpt-4o",
2253
+ displayName: "GPT-4o (on Azure)",
2254
+ capabilities: {
2255
+ streaming: true,
2256
+ tools: true,
2257
+ vision: true,
2258
+ systemPrompt: true,
2259
+ maxContextTokens: 128e3
2260
+ }
2261
+ },
2262
+ {
2263
+ id: "gpt-4o-mini",
2264
+ displayName: "GPT-4o mini (on Azure)",
2265
+ capabilities: {
2266
+ streaming: true,
2267
+ tools: true,
2268
+ vision: true,
2269
+ systemPrompt: true,
2270
+ maxContextTokens: 128e3
2271
+ }
2272
+ },
2273
+ {
2274
+ id: "gpt-4-turbo",
2275
+ displayName: "GPT-4 Turbo (on Azure)",
2276
+ capabilities: {
2277
+ streaming: true,
2278
+ tools: true,
2279
+ vision: true,
2280
+ systemPrompt: true,
2281
+ maxContextTokens: 128e3
2282
+ }
2283
+ },
2284
+ {
2285
+ // Azure spells it `gpt-35-turbo` (no dot). Keep their spelling for the id
2286
+ // so capability lookups against deployment names that echo the Azure id
2287
+ // hit.
2288
+ id: "gpt-35-turbo",
2289
+ displayName: "GPT-3.5 Turbo (on Azure)",
2290
+ capabilities: {
2291
+ streaming: true,
2292
+ tools: true,
2293
+ vision: false,
2294
+ systemPrompt: true,
2295
+ maxContextTokens: 16385
2296
+ }
2297
+ },
2298
+ {
2299
+ id: "o1-preview",
2300
+ displayName: "o1 preview \u2014 reasoning (on Azure)",
2301
+ capabilities: {
2302
+ streaming: false,
2303
+ tools: false,
2304
+ vision: false,
2305
+ systemPrompt: false,
2306
+ maxContextTokens: 128e3
2307
+ }
2308
+ },
2309
+ {
2310
+ id: "o1-mini",
2311
+ displayName: "o1 mini \u2014 reasoning (on Azure)",
2312
+ capabilities: {
2313
+ streaming: false,
2314
+ tools: false,
2315
+ vision: false,
2316
+ systemPrompt: false,
2317
+ maxContextTokens: 128e3
2318
+ }
2319
+ }
2320
+ ];
2321
+ var azureOpenAIManifest = {
2322
+ vendor: "azure-openai",
2323
+ displayName: "Azure OpenAI",
2324
+ authKinds: [
2325
+ {
2326
+ kind: "azureOpenAIApiKey",
2327
+ displayName: "API Key",
2328
+ fields: [
2329
+ {
2330
+ name: "apiKey",
2331
+ label: "API Key",
2332
+ type: "password",
2333
+ required: true,
2334
+ help: "Azure OpenAI resource key. Find it in the Azure portal under your OpenAI resource \u2192 Keys and Endpoint."
2335
+ },
2336
+ {
2337
+ name: "endpoint",
2338
+ label: "Endpoint",
2339
+ type: "url",
2340
+ required: true,
2341
+ help: "Resource endpoint URL, e.g. https://my-resource.openai.azure.com. Shown in the Azure portal alongside the keys."
2342
+ },
2343
+ {
2344
+ name: "deployment",
2345
+ label: "Deployment Name",
2346
+ type: "text",
2347
+ required: true,
2348
+ help: "The name you chose for the deployment in Azure AI Studio (NOT the underlying model id \u2014 deployments can be named anything)."
2349
+ },
2350
+ {
2351
+ name: "apiVersion",
2352
+ label: "API Version",
2353
+ type: "text",
2354
+ required: true,
2355
+ default: "2024-10-21",
2356
+ help: "Data-plane api-version, e.g. 2024-10-21. Microsoft rolls these frequently; see Azure OpenAI API reference docs for the current stable GA version."
2357
+ }
2358
+ ]
2359
+ }
2360
+ ],
2361
+ knownModels: AZURE_OPENAI_KNOWN_MODELS,
2362
+ // Azure's list-deployments endpoint is on the control plane (ARM) and
2363
+ // requires AAD credentials the data-plane API key doesn't carry. Return
2364
+ // the curated set from the manifest.
2365
+ supportsModelListing: false,
2366
+ docsUrl: "https://learn.microsoft.com/en-us/azure/ai-services/openai/reference"
2367
+ };
2368
+
2369
+ // src/adapters/azure-openai/adapter.ts
2370
+ var AzureOpenAIAdapter = class {
2371
+ vendor = azureOpenAIManifest.vendor;
2372
+ acceptedAuth = ["azureOpenAIApiKey"];
2373
+ client;
2374
+ init(auth, client) {
2375
+ if (auth.kind !== "azureOpenAIApiKey") {
2376
+ throw new Error(
2377
+ `AzureOpenAIAdapter: unsupported auth kind '${auth.kind}'`
2378
+ );
2379
+ }
2380
+ if (!auth.apiKey) {
2381
+ throw new Error("AzureOpenAIAdapter: apiKey is required");
2382
+ }
2383
+ if (!auth.endpoint) {
2384
+ throw new Error("AzureOpenAIAdapter: endpoint is required");
2385
+ }
2386
+ if (!auth.deployment) {
2387
+ throw new Error("AzureOpenAIAdapter: deployment is required");
2388
+ }
2389
+ if (!auth.apiVersion) {
2390
+ throw new Error("AzureOpenAIAdapter: apiVersion is required");
2391
+ }
2392
+ this.client = new AzureOpenAI({
2393
+ apiKey: auth.apiKey,
2394
+ endpoint: auth.endpoint,
2395
+ apiVersion: auth.apiVersion,
2396
+ deployment: auth.deployment,
2397
+ ...client?.timeout !== void 0 ? { timeout: client.timeout } : {},
2398
+ ...client?.maxRetries !== void 0 ? { maxRetries: client.maxRetries } : {}
2399
+ });
2400
+ }
2401
+ stream(req) {
2402
+ return streamFromOpenAI(this.ensureClient(), req, {
2403
+ knownModels: azureOpenAIManifest.knownModels,
2404
+ tokensParam: "max_completion_tokens"
2405
+ });
2406
+ }
2407
+ appendAssistantToolCall(history, toolCalls) {
2408
+ return appendOpenAIAssistantToolCall(history, toolCalls);
2409
+ }
2410
+ appendToolResult(history, toolCallId, result) {
2411
+ return appendOpenAIToolResult(history, toolCallId, result);
2412
+ }
2413
+ async listAvailableModels() {
2414
+ return [...azureOpenAIManifest.knownModels];
2415
+ }
2416
+ async testCredential() {
2417
+ const client = this.ensureClient();
2418
+ await client.chat.completions.create({
2419
+ // Azure ignores `model` when a deployment is in the URL, but the SDK
2420
+ // still requires it as a parameter.
2421
+ model: "probe",
2422
+ messages: [{ role: "user", content: "ping" }],
2423
+ // Use `max_completion_tokens` (not legacy `max_tokens`): gpt-5 family
2424
+ // and o-series reasoning models return 400 on the legacy parameter.
2425
+ // The newer name is a superset — also accepted by gpt-4o, gpt-4-turbo,
2426
+ // and gpt-3.5-turbo deployments — so it's the safe choice for a probe
2427
+ // that has to work regardless of the underlying deployment model.
2428
+ max_completion_tokens: 1,
2429
+ stream: false
2430
+ });
2431
+ }
2432
+ async warmup() {
2433
+ }
2434
+ ensureClient() {
2435
+ if (!this.client) {
2436
+ throw new Error(
2437
+ "AzureOpenAIAdapter: init() must be called before stream()/listAvailableModels()"
2438
+ );
2439
+ }
2440
+ return this.client;
2441
+ }
2442
+ };
2443
+
2444
+ // src/adapters/azure-openai/factory.ts
2445
+ var azureOpenAIFactory = {
2446
+ vendor: azureOpenAIManifest.vendor,
2447
+ manifest: azureOpenAIManifest,
2448
+ create: () => new AzureOpenAIAdapter()
2449
+ };
2450
+
2235
2451
  // src/adapters/index.ts
2236
2452
  registerAdapter(openAIFactory);
2237
2453
  registerAdapter(deepseekFactory);
@@ -2240,6 +2456,7 @@ registerAdapter(googleFactory);
2240
2456
  registerAdapter(vertexGeminiFactory);
2241
2457
  registerAdapter(vertexOpenAIFactory);
2242
2458
  registerAdapter(bedrockFactory);
2459
+ registerAdapter(azureOpenAIFactory);
2243
2460
 
2244
2461
  // src/normalize-auth.ts
2245
2462
  function normalizeAuth(vendor, raw) {
@@ -2260,6 +2477,8 @@ function normalizeAuth(vendor, raw) {
2260
2477
  return normalizeVertex(vendor, raw);
2261
2478
  case "bedrock":
2262
2479
  return normalizeBedrock(raw);
2480
+ case "azure-openai":
2481
+ return normalizeAzureOpenAI(raw);
2263
2482
  default:
2264
2483
  throw new Error(
2265
2484
  `normalizeAuth: unknown vendor '${vendor}'. If this is a custom adapter, construct the AuthSpec directly.`
@@ -2339,6 +2558,27 @@ function normalizeBedrock(raw) {
2339
2558
  `normalizeAuth: vendor 'bedrock' requires either (access_key_id + secret_access_key) or api_key`
2340
2559
  );
2341
2560
  }
2561
+ function normalizeAzureOpenAI(raw) {
2562
+ if (!raw.api_key) {
2563
+ throw new Error(`normalizeAuth: vendor 'azure-openai' requires 'api_key'`);
2564
+ }
2565
+ if (!raw.endpoint) {
2566
+ throw new Error(`normalizeAuth: vendor 'azure-openai' requires 'endpoint'`);
2567
+ }
2568
+ if (!raw.deployment) {
2569
+ throw new Error(`normalizeAuth: vendor 'azure-openai' requires 'deployment'`);
2570
+ }
2571
+ if (!raw.api_version) {
2572
+ throw new Error(`normalizeAuth: vendor 'azure-openai' requires 'api_version'`);
2573
+ }
2574
+ return {
2575
+ kind: "azureOpenAIApiKey",
2576
+ apiKey: raw.api_key,
2577
+ endpoint: raw.endpoint,
2578
+ deployment: raw.deployment,
2579
+ apiVersion: raw.api_version
2580
+ };
2581
+ }
2342
2582
  function parseServiceKey(value) {
2343
2583
  if (typeof value === "string") {
2344
2584
  try {
@@ -2350,6 +2590,51 @@ function parseServiceKey(value) {
2350
2590
  return value;
2351
2591
  }
2352
2592
 
2593
+ // src/pick-auth-kind.ts
2594
+ function pickAuthKind(vendor, raw) {
2595
+ const factory = getAdapterFactory(vendor);
2596
+ const { authKinds } = factory.manifest;
2597
+ if (authKinds.length === 1) {
2598
+ return authKinds[0];
2599
+ }
2600
+ switch (vendor) {
2601
+ case "bedrock": {
2602
+ const iam = authKinds.find((k) => k.kind === "bedrockIam");
2603
+ const apiKey = authKinds.find((k) => k.kind === "bedrockApiKey");
2604
+ if (raw.access_key_id && raw.secret_access_key) {
2605
+ if (!iam) throw new Error(`pickAuthKind: bedrock manifest missing 'bedrockIam'`);
2606
+ return iam;
2607
+ }
2608
+ if (raw.api_key) {
2609
+ if (!apiKey) throw new Error(`pickAuthKind: bedrock manifest missing 'bedrockApiKey'`);
2610
+ return apiKey;
2611
+ }
2612
+ throw new Error(
2613
+ `pickAuthKind: bedrock credential missing both 'api_key' and ('access_key_id' + 'secret_access_key')`
2614
+ );
2615
+ }
2616
+ case "google": {
2617
+ const svc = authKinds.find((k) => k.kind === "googleServiceAccount");
2618
+ const apiKey = authKinds.find((k) => k.kind === "googleApiKey");
2619
+ if (raw.service_key) {
2620
+ if (!svc) throw new Error(`pickAuthKind: google manifest missing 'googleServiceAccount'`);
2621
+ return svc;
2622
+ }
2623
+ if (raw.api_key) {
2624
+ if (!apiKey) throw new Error(`pickAuthKind: google manifest missing 'googleApiKey'`);
2625
+ return apiKey;
2626
+ }
2627
+ throw new Error(
2628
+ `pickAuthKind: google credential missing both 'api_key' and 'service_key'`
2629
+ );
2630
+ }
2631
+ default:
2632
+ throw new Error(
2633
+ `pickAuthKind: vendor '${vendor}' declares ${authKinds.length} authKinds but has no discriminator rule. Add one in src/pick-auth-kind.ts.`
2634
+ );
2635
+ }
2636
+ }
2637
+
2353
2638
  // src/index.ts
2354
2639
  async function createLlm(args) {
2355
2640
  const factory = getAdapterFactory(args.vendor);
@@ -2370,6 +2655,7 @@ export {
2370
2655
  getManifest,
2371
2656
  listVendors,
2372
2657
  normalizeAuth,
2658
+ pickAuthKind,
2373
2659
  registerAdapter,
2374
2660
  replaceAdapter,
2375
2661
  unregisterAdapter