@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.
@@ -1,4 +1,4 @@
1
- import { a as AdapterFactory, d as AuthKind, A as AuthSpec, L as LlmAdapter, c as ApiKeyAuth, g as ClientOptions, P as PromptRequest, l as LlmEvent, M as Message, o as ToolCallEvent, n as ModelInfo, b as AdapterManifest } from '../types-4d2QrlAe.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-DxknK0Rc.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 { a as AdapterFactory, d as AuthKind, A as AuthSpec, L as LlmAdapter, c as ApiKeyAuth, g as ClientOptions, P as PromptRequest, l as LlmEvent, M as Message, o as ToolCallEvent, n as ModelInfo, b as AdapterManifest } from '../types-4d2QrlAe.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-DxknK0Rc.js';
2
2
 
3
3
  /**
4
4
  * Named scenarios the harness must be able to stage. Each scenario configures
@@ -74,7 +74,10 @@ async function* streamFromOpenAI(client, req, options) {
74
74
  }
75
75
  if (req.temperature !== void 0) body.temperature = req.temperature;
76
76
  const effectiveMaxTokens = req.maxTokens ?? options.defaultMaxTokens;
77
- if (effectiveMaxTokens !== void 0) body.max_tokens = effectiveMaxTokens;
77
+ if (effectiveMaxTokens !== void 0) {
78
+ const param = options.tokensParam ?? (needsMaxCompletionTokens(req.model) ? "max_completion_tokens" : "max_tokens");
79
+ body[param] = effectiveMaxTokens;
80
+ }
78
81
  let stream;
79
82
  try {
80
83
  stream = await client.chat.completions.create(body, { signal: req.signal });
@@ -257,6 +260,9 @@ function capabilitiesFor(modelId, knownModels) {
257
260
  if (known) return known.capabilities;
258
261
  return defaultCapabilitiesForUnknown(modelId);
259
262
  }
263
+ function needsMaxCompletionTokens(modelId) {
264
+ return /^(o\d|gpt-5)/i.test(modelId);
265
+ }
260
266
  function defaultCapabilitiesForUnknown(modelId) {
261
267
  const isReasoning = /^o[13]([-/]|$)/i.test(modelId);
262
268
  if (isReasoning) {
@@ -1634,7 +1640,12 @@ var VertexOpenAIAdapter = class {
1634
1640
  stream(req) {
1635
1641
  return streamFromOpenAI(this.ensureClient(), req, {
1636
1642
  knownModels: vertexOpenAIManifest.knownModels,
1637
- defaultMaxTokens: 4096
1643
+ defaultMaxTokens: 4096,
1644
+ // Pin legacy `max_tokens`: Vertex's OpenAI-compat partner-model
1645
+ // endpoint predates `max_completion_tokens` and may not recognize it.
1646
+ // The model-id heuristic wouldn't catch a partner model named in the
1647
+ // OpenAI style (unlikely today, but defensive).
1648
+ tokensParam: "max_tokens"
1638
1649
  });
1639
1650
  }
1640
1651
  appendAssistantToolCall(history, toolCalls) {
@@ -2225,6 +2236,211 @@ var bedrockFactory = {
2225
2236
  create: () => new BedrockAdapter()
2226
2237
  };
2227
2238
 
2239
+ // src/adapters/azure-openai/adapter.ts
2240
+ import { AzureOpenAI } from "openai";
2241
+
2242
+ // src/adapters/azure-openai/manifest.ts
2243
+ var AZURE_OPENAI_KNOWN_MODELS = [
2244
+ {
2245
+ id: "gpt-4o",
2246
+ displayName: "GPT-4o (on Azure)",
2247
+ capabilities: {
2248
+ streaming: true,
2249
+ tools: true,
2250
+ vision: true,
2251
+ systemPrompt: true,
2252
+ maxContextTokens: 128e3
2253
+ }
2254
+ },
2255
+ {
2256
+ id: "gpt-4o-mini",
2257
+ displayName: "GPT-4o mini (on Azure)",
2258
+ capabilities: {
2259
+ streaming: true,
2260
+ tools: true,
2261
+ vision: true,
2262
+ systemPrompt: true,
2263
+ maxContextTokens: 128e3
2264
+ }
2265
+ },
2266
+ {
2267
+ id: "gpt-4-turbo",
2268
+ displayName: "GPT-4 Turbo (on Azure)",
2269
+ capabilities: {
2270
+ streaming: true,
2271
+ tools: true,
2272
+ vision: true,
2273
+ systemPrompt: true,
2274
+ maxContextTokens: 128e3
2275
+ }
2276
+ },
2277
+ {
2278
+ // Azure spells it `gpt-35-turbo` (no dot). Keep their spelling for the id
2279
+ // so capability lookups against deployment names that echo the Azure id
2280
+ // hit.
2281
+ id: "gpt-35-turbo",
2282
+ displayName: "GPT-3.5 Turbo (on Azure)",
2283
+ capabilities: {
2284
+ streaming: true,
2285
+ tools: true,
2286
+ vision: false,
2287
+ systemPrompt: true,
2288
+ maxContextTokens: 16385
2289
+ }
2290
+ },
2291
+ {
2292
+ id: "o1-preview",
2293
+ displayName: "o1 preview \u2014 reasoning (on Azure)",
2294
+ capabilities: {
2295
+ streaming: false,
2296
+ tools: false,
2297
+ vision: false,
2298
+ systemPrompt: false,
2299
+ maxContextTokens: 128e3
2300
+ }
2301
+ },
2302
+ {
2303
+ id: "o1-mini",
2304
+ displayName: "o1 mini \u2014 reasoning (on Azure)",
2305
+ capabilities: {
2306
+ streaming: false,
2307
+ tools: false,
2308
+ vision: false,
2309
+ systemPrompt: false,
2310
+ maxContextTokens: 128e3
2311
+ }
2312
+ }
2313
+ ];
2314
+ var azureOpenAIManifest = {
2315
+ vendor: "azure-openai",
2316
+ displayName: "Azure OpenAI",
2317
+ authKinds: [
2318
+ {
2319
+ kind: "azureOpenAIApiKey",
2320
+ displayName: "API Key",
2321
+ fields: [
2322
+ {
2323
+ name: "apiKey",
2324
+ label: "API Key",
2325
+ type: "password",
2326
+ required: true,
2327
+ help: "Azure OpenAI resource key. Find it in the Azure portal under your OpenAI resource \u2192 Keys and Endpoint."
2328
+ },
2329
+ {
2330
+ name: "endpoint",
2331
+ label: "Endpoint",
2332
+ type: "url",
2333
+ required: true,
2334
+ help: "Resource endpoint URL, e.g. https://my-resource.openai.azure.com. Shown in the Azure portal alongside the keys."
2335
+ },
2336
+ {
2337
+ name: "deployment",
2338
+ label: "Deployment Name",
2339
+ type: "text",
2340
+ required: true,
2341
+ help: "The name you chose for the deployment in Azure AI Studio (NOT the underlying model id \u2014 deployments can be named anything)."
2342
+ },
2343
+ {
2344
+ name: "apiVersion",
2345
+ label: "API Version",
2346
+ type: "text",
2347
+ required: true,
2348
+ default: "2024-10-21",
2349
+ 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."
2350
+ }
2351
+ ]
2352
+ }
2353
+ ],
2354
+ knownModels: AZURE_OPENAI_KNOWN_MODELS,
2355
+ // Azure's list-deployments endpoint is on the control plane (ARM) and
2356
+ // requires AAD credentials the data-plane API key doesn't carry. Return
2357
+ // the curated set from the manifest.
2358
+ supportsModelListing: false,
2359
+ docsUrl: "https://learn.microsoft.com/en-us/azure/ai-services/openai/reference"
2360
+ };
2361
+
2362
+ // src/adapters/azure-openai/adapter.ts
2363
+ var AzureOpenAIAdapter = class {
2364
+ vendor = azureOpenAIManifest.vendor;
2365
+ acceptedAuth = ["azureOpenAIApiKey"];
2366
+ client;
2367
+ init(auth, client) {
2368
+ if (auth.kind !== "azureOpenAIApiKey") {
2369
+ throw new Error(
2370
+ `AzureOpenAIAdapter: unsupported auth kind '${auth.kind}'`
2371
+ );
2372
+ }
2373
+ if (!auth.apiKey) {
2374
+ throw new Error("AzureOpenAIAdapter: apiKey is required");
2375
+ }
2376
+ if (!auth.endpoint) {
2377
+ throw new Error("AzureOpenAIAdapter: endpoint is required");
2378
+ }
2379
+ if (!auth.deployment) {
2380
+ throw new Error("AzureOpenAIAdapter: deployment is required");
2381
+ }
2382
+ if (!auth.apiVersion) {
2383
+ throw new Error("AzureOpenAIAdapter: apiVersion is required");
2384
+ }
2385
+ this.client = new AzureOpenAI({
2386
+ apiKey: auth.apiKey,
2387
+ endpoint: auth.endpoint,
2388
+ apiVersion: auth.apiVersion,
2389
+ deployment: auth.deployment,
2390
+ ...client?.timeout !== void 0 ? { timeout: client.timeout } : {},
2391
+ ...client?.maxRetries !== void 0 ? { maxRetries: client.maxRetries } : {}
2392
+ });
2393
+ }
2394
+ stream(req) {
2395
+ return streamFromOpenAI(this.ensureClient(), req, {
2396
+ knownModels: azureOpenAIManifest.knownModels,
2397
+ tokensParam: "max_completion_tokens"
2398
+ });
2399
+ }
2400
+ appendAssistantToolCall(history, toolCalls) {
2401
+ return appendOpenAIAssistantToolCall(history, toolCalls);
2402
+ }
2403
+ appendToolResult(history, toolCallId, result) {
2404
+ return appendOpenAIToolResult(history, toolCallId, result);
2405
+ }
2406
+ async listAvailableModels() {
2407
+ return [...azureOpenAIManifest.knownModels];
2408
+ }
2409
+ async testCredential() {
2410
+ const client = this.ensureClient();
2411
+ await client.chat.completions.create({
2412
+ // Azure ignores `model` when a deployment is in the URL, but the SDK
2413
+ // still requires it as a parameter.
2414
+ model: "probe",
2415
+ messages: [{ role: "user", content: "ping" }],
2416
+ // Use `max_completion_tokens` (not legacy `max_tokens`): gpt-5 family
2417
+ // and o-series reasoning models return 400 on the legacy parameter.
2418
+ // The newer name is a superset — also accepted by gpt-4o, gpt-4-turbo,
2419
+ // and gpt-3.5-turbo deployments — so it's the safe choice for a probe
2420
+ // that has to work regardless of the underlying deployment model.
2421
+ max_completion_tokens: 1,
2422
+ stream: false
2423
+ });
2424
+ }
2425
+ async warmup() {
2426
+ }
2427
+ ensureClient() {
2428
+ if (!this.client) {
2429
+ throw new Error(
2430
+ "AzureOpenAIAdapter: init() must be called before stream()/listAvailableModels()"
2431
+ );
2432
+ }
2433
+ return this.client;
2434
+ }
2435
+ };
2436
+
2437
+ // src/adapters/azure-openai/factory.ts
2438
+ var azureOpenAIFactory = {
2439
+ vendor: azureOpenAIManifest.vendor,
2440
+ manifest: azureOpenAIManifest,
2441
+ create: () => new AzureOpenAIAdapter()
2442
+ };
2443
+
2228
2444
  // src/adapters/index.ts
2229
2445
  registerAdapter(openAIFactory);
2230
2446
  registerAdapter(deepseekFactory);
@@ -2233,6 +2449,7 @@ registerAdapter(googleFactory);
2233
2449
  registerAdapter(vertexGeminiFactory);
2234
2450
  registerAdapter(vertexOpenAIFactory);
2235
2451
  registerAdapter(bedrockFactory);
2452
+ registerAdapter(azureOpenAIFactory);
2236
2453
 
2237
2454
  // src/index.ts
2238
2455
  async function createLlm(args) {