@jambonz/llm 0.3.4 → 0.4.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 CHANGED
@@ -36,6 +36,7 @@ __export(src_exports, {
36
36
  getManifest: () => getManifest,
37
37
  listVendors: () => listVendors,
38
38
  normalizeAuth: () => normalizeAuth,
39
+ pickAuthKind: () => pickAuthKind,
39
40
  registerAdapter: () => registerAdapter,
40
41
  replaceAdapter: () => replaceAdapter,
41
42
  unregisterAdapter: () => unregisterAdapter
@@ -2270,6 +2271,205 @@ var bedrockFactory = {
2270
2271
  create: () => new BedrockAdapter()
2271
2272
  };
2272
2273
 
2274
+ // src/adapters/azure-openai/adapter.ts
2275
+ var import_openai3 = require("openai");
2276
+
2277
+ // src/adapters/azure-openai/manifest.ts
2278
+ var AZURE_OPENAI_KNOWN_MODELS = [
2279
+ {
2280
+ id: "gpt-4o",
2281
+ displayName: "GPT-4o (on Azure)",
2282
+ capabilities: {
2283
+ streaming: true,
2284
+ tools: true,
2285
+ vision: true,
2286
+ systemPrompt: true,
2287
+ maxContextTokens: 128e3
2288
+ }
2289
+ },
2290
+ {
2291
+ id: "gpt-4o-mini",
2292
+ displayName: "GPT-4o mini (on Azure)",
2293
+ capabilities: {
2294
+ streaming: true,
2295
+ tools: true,
2296
+ vision: true,
2297
+ systemPrompt: true,
2298
+ maxContextTokens: 128e3
2299
+ }
2300
+ },
2301
+ {
2302
+ id: "gpt-4-turbo",
2303
+ displayName: "GPT-4 Turbo (on Azure)",
2304
+ capabilities: {
2305
+ streaming: true,
2306
+ tools: true,
2307
+ vision: true,
2308
+ systemPrompt: true,
2309
+ maxContextTokens: 128e3
2310
+ }
2311
+ },
2312
+ {
2313
+ // Azure spells it `gpt-35-turbo` (no dot). Keep their spelling for the id
2314
+ // so capability lookups against deployment names that echo the Azure id
2315
+ // hit.
2316
+ id: "gpt-35-turbo",
2317
+ displayName: "GPT-3.5 Turbo (on Azure)",
2318
+ capabilities: {
2319
+ streaming: true,
2320
+ tools: true,
2321
+ vision: false,
2322
+ systemPrompt: true,
2323
+ maxContextTokens: 16385
2324
+ }
2325
+ },
2326
+ {
2327
+ id: "o1-preview",
2328
+ displayName: "o1 preview \u2014 reasoning (on Azure)",
2329
+ capabilities: {
2330
+ streaming: false,
2331
+ tools: false,
2332
+ vision: false,
2333
+ systemPrompt: false,
2334
+ maxContextTokens: 128e3
2335
+ }
2336
+ },
2337
+ {
2338
+ id: "o1-mini",
2339
+ displayName: "o1 mini \u2014 reasoning (on Azure)",
2340
+ capabilities: {
2341
+ streaming: false,
2342
+ tools: false,
2343
+ vision: false,
2344
+ systemPrompt: false,
2345
+ maxContextTokens: 128e3
2346
+ }
2347
+ }
2348
+ ];
2349
+ var azureOpenAIManifest = {
2350
+ vendor: "azure-openai",
2351
+ displayName: "Azure OpenAI",
2352
+ authKinds: [
2353
+ {
2354
+ kind: "azureOpenAIApiKey",
2355
+ displayName: "API Key",
2356
+ fields: [
2357
+ {
2358
+ name: "apiKey",
2359
+ label: "API Key",
2360
+ type: "password",
2361
+ required: true,
2362
+ help: "Azure OpenAI resource key. Find it in the Azure portal under your OpenAI resource \u2192 Keys and Endpoint."
2363
+ },
2364
+ {
2365
+ name: "endpoint",
2366
+ label: "Endpoint",
2367
+ type: "url",
2368
+ required: true,
2369
+ help: "Resource endpoint URL, e.g. https://my-resource.openai.azure.com. Shown in the Azure portal alongside the keys."
2370
+ },
2371
+ {
2372
+ name: "deployment",
2373
+ label: "Deployment Name",
2374
+ type: "text",
2375
+ required: true,
2376
+ help: "The name you chose for the deployment in Azure AI Studio (NOT the underlying model id \u2014 deployments can be named anything)."
2377
+ },
2378
+ {
2379
+ name: "apiVersion",
2380
+ label: "API Version",
2381
+ type: "text",
2382
+ required: true,
2383
+ default: "2024-10-21",
2384
+ 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."
2385
+ }
2386
+ ]
2387
+ }
2388
+ ],
2389
+ knownModels: AZURE_OPENAI_KNOWN_MODELS,
2390
+ // Azure's list-deployments endpoint is on the control plane (ARM) and
2391
+ // requires AAD credentials the data-plane API key doesn't carry. Return
2392
+ // the curated set from the manifest.
2393
+ supportsModelListing: false,
2394
+ docsUrl: "https://learn.microsoft.com/en-us/azure/ai-services/openai/reference"
2395
+ };
2396
+
2397
+ // src/adapters/azure-openai/adapter.ts
2398
+ var AzureOpenAIAdapter = class {
2399
+ vendor = azureOpenAIManifest.vendor;
2400
+ acceptedAuth = ["azureOpenAIApiKey"];
2401
+ client;
2402
+ init(auth, client) {
2403
+ if (auth.kind !== "azureOpenAIApiKey") {
2404
+ throw new Error(
2405
+ `AzureOpenAIAdapter: unsupported auth kind '${auth.kind}'`
2406
+ );
2407
+ }
2408
+ if (!auth.apiKey) {
2409
+ throw new Error("AzureOpenAIAdapter: apiKey is required");
2410
+ }
2411
+ if (!auth.endpoint) {
2412
+ throw new Error("AzureOpenAIAdapter: endpoint is required");
2413
+ }
2414
+ if (!auth.deployment) {
2415
+ throw new Error("AzureOpenAIAdapter: deployment is required");
2416
+ }
2417
+ if (!auth.apiVersion) {
2418
+ throw new Error("AzureOpenAIAdapter: apiVersion is required");
2419
+ }
2420
+ this.client = new import_openai3.AzureOpenAI({
2421
+ apiKey: auth.apiKey,
2422
+ endpoint: auth.endpoint,
2423
+ apiVersion: auth.apiVersion,
2424
+ deployment: auth.deployment,
2425
+ ...client?.timeout !== void 0 ? { timeout: client.timeout } : {},
2426
+ ...client?.maxRetries !== void 0 ? { maxRetries: client.maxRetries } : {}
2427
+ });
2428
+ }
2429
+ stream(req) {
2430
+ return streamFromOpenAI(this.ensureClient(), req, {
2431
+ knownModels: azureOpenAIManifest.knownModels
2432
+ });
2433
+ }
2434
+ appendAssistantToolCall(history, toolCalls) {
2435
+ return appendOpenAIAssistantToolCall(history, toolCalls);
2436
+ }
2437
+ appendToolResult(history, toolCallId, result) {
2438
+ return appendOpenAIToolResult(history, toolCallId, result);
2439
+ }
2440
+ async listAvailableModels() {
2441
+ return [...azureOpenAIManifest.knownModels];
2442
+ }
2443
+ async testCredential() {
2444
+ const client = this.ensureClient();
2445
+ await client.chat.completions.create({
2446
+ // Azure ignores `model` when a deployment is in the URL, but the SDK
2447
+ // still requires it as a parameter.
2448
+ model: "probe",
2449
+ messages: [{ role: "user", content: "ping" }],
2450
+ max_tokens: 1,
2451
+ stream: false
2452
+ });
2453
+ }
2454
+ async warmup() {
2455
+ }
2456
+ ensureClient() {
2457
+ if (!this.client) {
2458
+ throw new Error(
2459
+ "AzureOpenAIAdapter: init() must be called before stream()/listAvailableModels()"
2460
+ );
2461
+ }
2462
+ return this.client;
2463
+ }
2464
+ };
2465
+
2466
+ // src/adapters/azure-openai/factory.ts
2467
+ var azureOpenAIFactory = {
2468
+ vendor: azureOpenAIManifest.vendor,
2469
+ manifest: azureOpenAIManifest,
2470
+ create: () => new AzureOpenAIAdapter()
2471
+ };
2472
+
2273
2473
  // src/adapters/index.ts
2274
2474
  registerAdapter(openAIFactory);
2275
2475
  registerAdapter(deepseekFactory);
@@ -2278,6 +2478,7 @@ registerAdapter(googleFactory);
2278
2478
  registerAdapter(vertexGeminiFactory);
2279
2479
  registerAdapter(vertexOpenAIFactory);
2280
2480
  registerAdapter(bedrockFactory);
2481
+ registerAdapter(azureOpenAIFactory);
2281
2482
 
2282
2483
  // src/normalize-auth.ts
2283
2484
  function normalizeAuth(vendor, raw) {
@@ -2298,6 +2499,8 @@ function normalizeAuth(vendor, raw) {
2298
2499
  return normalizeVertex(vendor, raw);
2299
2500
  case "bedrock":
2300
2501
  return normalizeBedrock(raw);
2502
+ case "azure-openai":
2503
+ return normalizeAzureOpenAI(raw);
2301
2504
  default:
2302
2505
  throw new Error(
2303
2506
  `normalizeAuth: unknown vendor '${vendor}'. If this is a custom adapter, construct the AuthSpec directly.`
@@ -2377,6 +2580,27 @@ function normalizeBedrock(raw) {
2377
2580
  `normalizeAuth: vendor 'bedrock' requires either (access_key_id + secret_access_key) or api_key`
2378
2581
  );
2379
2582
  }
2583
+ function normalizeAzureOpenAI(raw) {
2584
+ if (!raw.api_key) {
2585
+ throw new Error(`normalizeAuth: vendor 'azure-openai' requires 'api_key'`);
2586
+ }
2587
+ if (!raw.endpoint) {
2588
+ throw new Error(`normalizeAuth: vendor 'azure-openai' requires 'endpoint'`);
2589
+ }
2590
+ if (!raw.deployment) {
2591
+ throw new Error(`normalizeAuth: vendor 'azure-openai' requires 'deployment'`);
2592
+ }
2593
+ if (!raw.api_version) {
2594
+ throw new Error(`normalizeAuth: vendor 'azure-openai' requires 'api_version'`);
2595
+ }
2596
+ return {
2597
+ kind: "azureOpenAIApiKey",
2598
+ apiKey: raw.api_key,
2599
+ endpoint: raw.endpoint,
2600
+ deployment: raw.deployment,
2601
+ apiVersion: raw.api_version
2602
+ };
2603
+ }
2380
2604
  function parseServiceKey(value) {
2381
2605
  if (typeof value === "string") {
2382
2606
  try {
@@ -2388,6 +2612,51 @@ function parseServiceKey(value) {
2388
2612
  return value;
2389
2613
  }
2390
2614
 
2615
+ // src/pick-auth-kind.ts
2616
+ function pickAuthKind(vendor, raw) {
2617
+ const factory = getAdapterFactory(vendor);
2618
+ const { authKinds } = factory.manifest;
2619
+ if (authKinds.length === 1) {
2620
+ return authKinds[0];
2621
+ }
2622
+ switch (vendor) {
2623
+ case "bedrock": {
2624
+ const iam = authKinds.find((k) => k.kind === "bedrockIam");
2625
+ const apiKey = authKinds.find((k) => k.kind === "bedrockApiKey");
2626
+ if (raw.access_key_id && raw.secret_access_key) {
2627
+ if (!iam) throw new Error(`pickAuthKind: bedrock manifest missing 'bedrockIam'`);
2628
+ return iam;
2629
+ }
2630
+ if (raw.api_key) {
2631
+ if (!apiKey) throw new Error(`pickAuthKind: bedrock manifest missing 'bedrockApiKey'`);
2632
+ return apiKey;
2633
+ }
2634
+ throw new Error(
2635
+ `pickAuthKind: bedrock credential missing both 'api_key' and ('access_key_id' + 'secret_access_key')`
2636
+ );
2637
+ }
2638
+ case "google": {
2639
+ const svc = authKinds.find((k) => k.kind === "googleServiceAccount");
2640
+ const apiKey = authKinds.find((k) => k.kind === "googleApiKey");
2641
+ if (raw.service_key) {
2642
+ if (!svc) throw new Error(`pickAuthKind: google manifest missing 'googleServiceAccount'`);
2643
+ return svc;
2644
+ }
2645
+ if (raw.api_key) {
2646
+ if (!apiKey) throw new Error(`pickAuthKind: google manifest missing 'googleApiKey'`);
2647
+ return apiKey;
2648
+ }
2649
+ throw new Error(
2650
+ `pickAuthKind: google credential missing both 'api_key' and 'service_key'`
2651
+ );
2652
+ }
2653
+ default:
2654
+ throw new Error(
2655
+ `pickAuthKind: vendor '${vendor}' declares ${authKinds.length} authKinds but has no discriminator rule. Add one in src/pick-auth-kind.ts.`
2656
+ );
2657
+ }
2658
+ }
2659
+
2391
2660
  // src/index.ts
2392
2661
  async function createLlm(args) {
2393
2662
  const factory = getAdapterFactory(args.vendor);
@@ -2409,6 +2678,7 @@ async function createLlm(args) {
2409
2678
  getManifest,
2410
2679
  listVendors,
2411
2680
  normalizeAuth,
2681
+ pickAuthKind,
2412
2682
  registerAdapter,
2413
2683
  replaceAdapter,
2414
2684
  unregisterAdapter