@cognipeer/agent-sdk 0.10.6 → 0.13.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.mjs CHANGED
@@ -2431,6 +2431,15 @@ function estimatePayloadBytes(value) {
2431
2431
  }
2432
2432
  }
2433
2433
  }
2434
+ function toMessageUsage(u) {
2435
+ return {
2436
+ prompt_tokens: u.inputTokens,
2437
+ completion_tokens: u.outputTokens,
2438
+ total_tokens: u.totalTokens,
2439
+ prompt_tokens_details: { cached_tokens: u.cachedInputTokens, cache_write_tokens: u.cachedWriteTokens },
2440
+ completion_tokens_details: { reasoning_tokens: u.reasoningTokens }
2441
+ };
2442
+ }
2434
2443
  function fromNativeProvider(provider, options) {
2435
2444
  let boundTools = options?.__tools;
2436
2445
  const modelName = options?.model ?? provider.defaultModel ?? provider.providerName;
@@ -2440,8 +2449,9 @@ function fromNativeProvider(provider, options) {
2440
2449
  invoke: async (messages, _invokeOptions) => {
2441
2450
  const link = linkAbortSignal(_invokeOptions);
2442
2451
  try {
2443
- const request = buildRequest(messages, boundTools, options, _invokeOptions);
2452
+ let request = buildRequest(messages, boundTools, options, _invokeOptions);
2444
2453
  if (link.signal) request.signal = link.signal;
2454
+ request = await applyTransform(request);
2445
2455
  const response = await provider.complete(request);
2446
2456
  return toBaseChatMessage(response);
2447
2457
  } finally {
@@ -2451,33 +2461,46 @@ function fromNativeProvider(provider, options) {
2451
2461
  stream: async function* (messages, _invokeOptions) {
2452
2462
  const link = linkAbortSignal(_invokeOptions);
2453
2463
  try {
2454
- const request = buildRequest(messages, boundTools, options, _invokeOptions);
2464
+ let request = buildRequest(messages, boundTools, options, _invokeOptions);
2455
2465
  request.stream = true;
2456
2466
  if (link.signal) request.signal = link.signal;
2467
+ request = await applyTransform(request);
2457
2468
  let fullContent = "";
2458
2469
  let allToolCalls = [];
2459
2470
  let lastUsage;
2460
2471
  let reasoningBlocks;
2472
+ let reasoningText = "";
2473
+ let finishReason;
2474
+ let responseModel;
2461
2475
  const toolCallBuffers = /* @__PURE__ */ new Map();
2462
2476
  for await (const chunk of provider.completeStream(request)) {
2463
2477
  if (chunk.delta.content) {
2464
2478
  fullContent += chunk.delta.content;
2465
2479
  yield chunk.delta.content;
2466
2480
  }
2481
+ if (chunk.model) responseModel = chunk.model;
2482
+ if (chunk.finishReason) finishReason = chunk.finishReason;
2467
2483
  if (chunk.delta.reasoning?.blocks?.length) {
2468
2484
  reasoningBlocks = chunk.delta.reasoning.blocks;
2469
2485
  }
2486
+ const reasoningDelta = chunk.delta.reasoning?.summary;
2487
+ if (reasoningDelta) {
2488
+ reasoningText += reasoningDelta;
2489
+ yield { type: "reasoning", reasoning_content: reasoningDelta };
2490
+ }
2470
2491
  if (chunk.delta.toolCalls) {
2471
2492
  for (const tc of chunk.delta.toolCalls) {
2472
2493
  if (tc.id) {
2473
2494
  const existing = toolCallBuffers.get(tc.id);
2474
2495
  if (existing) {
2475
2496
  if (tc.arguments) existing.arguments += tc.arguments;
2497
+ if (tc.thoughtSignature) existing.thoughtSignature = tc.thoughtSignature;
2476
2498
  } else {
2477
2499
  toolCallBuffers.set(tc.id, {
2478
2500
  id: tc.id,
2479
2501
  name: tc.name ?? "",
2480
- arguments: tc.arguments ?? ""
2502
+ arguments: tc.arguments ?? "",
2503
+ ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
2481
2504
  });
2482
2505
  }
2483
2506
  }
@@ -2488,8 +2511,18 @@ function fromNativeProvider(provider, options) {
2488
2511
  if (link.signal?.aborted) return;
2489
2512
  allToolCalls = [...toolCallBuffers.values()];
2490
2513
  const finalMessage = assembleMessage(fullContent, allToolCalls, lastUsage);
2491
- if (reasoningBlocks?.length) {
2492
- finalMessage.reasoning = { blocks: reasoningBlocks };
2514
+ if (reasoningBlocks?.length || reasoningText) {
2515
+ finalMessage.reasoning = {
2516
+ ...reasoningBlocks?.length ? { blocks: reasoningBlocks } : {},
2517
+ ...reasoningText ? { summary: reasoningText } : {}
2518
+ };
2519
+ }
2520
+ if (finishReason || responseModel) {
2521
+ finalMessage.response_metadata = {
2522
+ ...finalMessage.response_metadata ?? {},
2523
+ ...finishReason ? { finish_reason: finishReason } : {},
2524
+ ...responseModel ? { model_name: responseModel } : {}
2525
+ };
2493
2526
  }
2494
2527
  yield finalMessage;
2495
2528
  } finally {
@@ -2503,6 +2536,11 @@ function fromNativeProvider(provider, options) {
2503
2536
  }
2504
2537
  };
2505
2538
  return adapted;
2539
+ async function applyTransform(req) {
2540
+ if (!options?.transformRequest) return req;
2541
+ const out = await options.transformRequest(req);
2542
+ return out ?? req;
2543
+ }
2506
2544
  function buildRequest(messages, tools, opts, invokeOptions) {
2507
2545
  const req = {
2508
2546
  model: opts?.model ?? modelName,
@@ -2510,6 +2548,10 @@ function fromNativeProvider(provider, options) {
2510
2548
  };
2511
2549
  if (opts?.temperature != null) req.temperature = opts.temperature;
2512
2550
  if (opts?.maxTokens != null) req.maxTokens = opts.maxTokens;
2551
+ if (opts?.topP != null) req.topP = opts.topP;
2552
+ if (opts?.stop?.length) req.stop = opts.stop;
2553
+ if (opts?.presencePenalty != null) req.presencePenalty = opts.presencePenalty;
2554
+ if (opts?.frequencyPenalty != null) req.frequencyPenalty = opts.frequencyPenalty;
2513
2555
  if (tools?.length) req.tools = tools;
2514
2556
  if (opts?.extra) req.extra = opts.extra;
2515
2557
  const reasoningOverride = invokeOptions?.reasoning;
@@ -2562,7 +2604,8 @@ function toUnifiedMessage(msg) {
2562
2604
  unified.toolCalls = msg.tool_calls.map((tc) => ({
2563
2605
  id: tc.id,
2564
2606
  name: tc.function?.name ?? tc.name ?? "",
2565
- arguments: tc.function?.arguments ?? tc.arguments ?? "{}"
2607
+ arguments: tc.function?.arguments ?? tc.arguments ?? "{}",
2608
+ ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
2566
2609
  }));
2567
2610
  }
2568
2611
  const reasoning = msg.reasoning;
@@ -2836,29 +2879,16 @@ function toToolDefinition(tool, strict) {
2836
2879
  }
2837
2880
  return { name, description, parameters, ...useStrict ? { strict: true } : {} };
2838
2881
  }
2882
+ function legacyTokenUsage(u) {
2883
+ return { ...toMessageUsage(u), cached_tokens: u.cachedInputTokens, cache_write_tokens: u.cachedWriteTokens };
2884
+ }
2839
2885
  function toBaseChatMessage(response) {
2840
2886
  const msg = {
2841
2887
  role: "assistant",
2842
2888
  content: response.content ?? "",
2843
- usage: {
2844
- prompt_tokens: response.usage.inputTokens,
2845
- completion_tokens: response.usage.outputTokens,
2846
- total_tokens: response.usage.totalTokens,
2847
- prompt_tokens_details: {
2848
- cached_tokens: response.usage.cachedInputTokens
2849
- },
2850
- completion_tokens_details: {
2851
- reasoning_tokens: response.usage.reasoningTokens
2852
- }
2853
- },
2889
+ usage: toMessageUsage(response.usage),
2854
2890
  response_metadata: {
2855
- token_usage: {
2856
- prompt_tokens: response.usage.inputTokens,
2857
- completion_tokens: response.usage.outputTokens,
2858
- total_tokens: response.usage.totalTokens,
2859
- cached_tokens: response.usage.cachedInputTokens,
2860
- cache_write_tokens: response.usage.cachedWriteTokens
2861
- },
2891
+ token_usage: legacyTokenUsage(response.usage),
2862
2892
  finish_reason: response.finishReason,
2863
2893
  model_name: response.model
2864
2894
  }
@@ -2867,7 +2897,8 @@ function toBaseChatMessage(response) {
2867
2897
  msg.tool_calls = response.toolCalls.map((tc) => ({
2868
2898
  id: tc.id,
2869
2899
  type: "function",
2870
- function: { name: tc.name, arguments: tc.arguments }
2900
+ function: { name: tc.name, arguments: tc.arguments },
2901
+ ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
2871
2902
  }));
2872
2903
  }
2873
2904
  if (response.reasoning && (response.reasoning.blocks?.length || response.reasoning.summary)) {
@@ -2881,32 +2912,15 @@ function assembleMessage(content, toolCalls, usage) {
2881
2912
  content
2882
2913
  };
2883
2914
  if (usage) {
2884
- msg.usage = {
2885
- prompt_tokens: usage.inputTokens,
2886
- completion_tokens: usage.outputTokens,
2887
- total_tokens: usage.totalTokens,
2888
- prompt_tokens_details: {
2889
- cached_tokens: usage.cachedInputTokens
2890
- },
2891
- completion_tokens_details: {
2892
- reasoning_tokens: usage.reasoningTokens
2893
- }
2894
- };
2895
- msg.response_metadata = {
2896
- token_usage: {
2897
- prompt_tokens: usage.inputTokens,
2898
- completion_tokens: usage.outputTokens,
2899
- total_tokens: usage.totalTokens,
2900
- cached_tokens: usage.cachedInputTokens,
2901
- cache_write_tokens: usage.cachedWriteTokens
2902
- }
2903
- };
2915
+ msg.usage = toMessageUsage(usage);
2916
+ msg.response_metadata = { token_usage: legacyTokenUsage(usage) };
2904
2917
  }
2905
2918
  if (toolCalls.length > 0) {
2906
2919
  msg.tool_calls = toolCalls.map((tc) => ({
2907
2920
  id: tc.id,
2908
2921
  type: "function",
2909
- function: { name: tc.name, arguments: tc.arguments }
2922
+ function: { name: tc.name, arguments: tc.arguments },
2923
+ ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
2910
2924
  }));
2911
2925
  }
2912
2926
  return msg;
@@ -2939,8 +2953,8 @@ function resolveCapabilities(provider) {
2939
2953
  return {
2940
2954
  structuredOutput: "tool_based",
2941
2955
  strictToolCalling: false,
2942
- streaming: false,
2943
- // streaming uses binary protocol
2956
+ streaming: true,
2957
+ // ConverseStream (AWS event-stream frames)
2944
2958
  provider: "bedrock"
2945
2959
  };
2946
2960
  case "vertex":
@@ -4646,6 +4660,10 @@ ${append}`;
4646
4660
  if (chunk && typeof chunk === "object" && chunk.role) {
4647
4661
  streamedMessage = chunk;
4648
4662
  }
4663
+ if (chunk && typeof chunk === "object" && chunk.type === "reasoning" && typeof chunk.reasoning_content === "string") {
4664
+ onEvent?.({ type: "reasoning", text: chunk.reasoning_content });
4665
+ continue;
4666
+ }
4649
4667
  const text = extractText2(chunk);
4650
4668
  const isAssembledMessage = Boolean(chunk && typeof chunk === "object" && chunk.role) && text.length > 0 && text === streamedText;
4651
4669
  if (text && !isAssembledMessage) {
@@ -5077,10 +5095,10 @@ function createToolsNode(initialTools, opts) {
5077
5095
  const toolCallId = tc.id || `${tc.name}_${toolCount + 1}`;
5078
5096
  const validatedArgs = validateToolArgs(tool, args);
5079
5097
  if (!validatedArgs.ok && resolved.toolResponses.schemaValidation === "strict") {
5080
- const errorMessage = `Tool argument validation failed for ${tc.name}: ${validatedArgs.message}`;
5081
- push({ role: "tool", content: errorMessage, tool_call_id: toolCallId, name: tc.name });
5082
- markToolFailure(errorMessage, tc.name, toolCallId);
5083
- onEvent?.({ type: "tool_call", phase: "error", name: tc.name, id: tc.id, args, error: { message: errorMessage } });
5098
+ const errorMessage2 = `Tool argument validation failed for ${tc.name}: ${validatedArgs.message}`;
5099
+ push({ role: "tool", content: errorMessage2, tool_call_id: toolCallId, name: tc.name });
5100
+ markToolFailure(errorMessage2, tc.name, toolCallId);
5101
+ onEvent?.({ type: "tool_call", phase: "error", name: tc.name, id: tc.id, args, error: { message: errorMessage2 } });
5084
5102
  toolCount += 1;
5085
5103
  return { status: "error" };
5086
5104
  }
@@ -6091,7 +6109,7 @@ var LEVEL_DEFAULTS = {
6091
6109
  };
6092
6110
  var VALID_LEVELS = ["minimal", "low", "medium", "high"];
6093
6111
  var VALID_CADENCES = ["off", "every_turn", "after_tool", "on_branch", "initial_then_after_tool"];
6094
- var VALID_EFFORTS = ["none", "minimal", "low", "medium", "high"];
6112
+ var VALID_EFFORTS = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
6095
6113
  function validateReasoningConfig(input) {
6096
6114
  if (!input) return;
6097
6115
  if (input.level !== void 0 && !VALID_LEVELS.includes(input.level)) {
@@ -11526,6 +11544,28 @@ async function runSmartAgentEvalHarness(params) {
11526
11544
  return results;
11527
11545
  }
11528
11546
 
11547
+ // src/providers/types.ts
11548
+ function emptyUsage() {
11549
+ return {
11550
+ inputTokens: 0,
11551
+ outputTokens: 0,
11552
+ totalTokens: 0,
11553
+ cachedInputTokens: 0,
11554
+ cachedWriteTokens: 0,
11555
+ cachedOutputTokens: 0,
11556
+ reasoningTokens: 0
11557
+ };
11558
+ }
11559
+ var ProviderError = class extends Error {
11560
+ constructor(message, provider, statusCode, responseBody) {
11561
+ super(message);
11562
+ this.provider = provider;
11563
+ this.statusCode = statusCode;
11564
+ this.responseBody = responseBody;
11565
+ this.name = "ProviderError";
11566
+ }
11567
+ };
11568
+
11529
11569
  // src/providers/base.ts
11530
11570
  var DEFAULT_RETRY = {
11531
11571
  maxRetries: 3,
@@ -11536,6 +11576,56 @@ var BaseProvider = class {
11536
11576
  constructor() {
11537
11577
  this.retryPolicy = DEFAULT_RETRY;
11538
11578
  }
11579
+ /** Applies the transport options shared by every provider config. */
11580
+ configureTransport(config) {
11581
+ this.fetchImpl = config.fetch;
11582
+ this.onModelRuleLearned = config.onModelRuleLearned;
11583
+ this.timeoutMs = typeof config.timeoutMs === "number" && config.timeoutMs > 0 ? config.timeoutMs : void 0;
11584
+ }
11585
+ /**
11586
+ * The single HTTP entry point for every provider call site. Uses the
11587
+ * configured `fetch` and applies `timeoutMs`: the timer covers the time until
11588
+ * the response HEADERS arrive and is cleared after that, so a long-running
11589
+ * stream is never cut by it (use the request `signal` to cancel a stream).
11590
+ * A timeout surfaces as a `ProviderError` with status 408. The caller's
11591
+ * `signal` still aborts the request as before.
11592
+ */
11593
+ async httpFetch(url, init = {}) {
11594
+ const doFetch = this.fetchImpl ?? fetch;
11595
+ const timeoutMs = this.timeoutMs;
11596
+ if (!timeoutMs) return doFetch(url, init);
11597
+ const controller = new AbortController();
11598
+ const outer = init.signal ?? void 0;
11599
+ let timedOut = false;
11600
+ const onOuterAbort = () => controller.abort(outer?.reason);
11601
+ if (outer) {
11602
+ if (outer.aborted) controller.abort(outer.reason);
11603
+ else outer.addEventListener("abort", onOuterAbort, { once: true });
11604
+ }
11605
+ const timer = setTimeout(() => {
11606
+ timedOut = true;
11607
+ controller.abort(new Error(`timed out after ${timeoutMs}ms`));
11608
+ }, timeoutMs);
11609
+ try {
11610
+ const res = await doFetch(url, { ...init, signal: controller.signal });
11611
+ return res;
11612
+ } catch (err) {
11613
+ if (timedOut) {
11614
+ throw new ProviderError(`${this.providerName} request timed out after ${timeoutMs}ms`, this.providerName, 408);
11615
+ }
11616
+ throw err;
11617
+ } finally {
11618
+ clearTimeout(timer);
11619
+ }
11620
+ }
11621
+ /**
11622
+ * Embeds `request.input`. Implemented by the providers that have an
11623
+ * embeddings endpoint (OpenAI, Azure, openai-compatible, Bedrock, Vertex);
11624
+ * the others reject with a 400 ProviderError.
11625
+ */
11626
+ async embed(_request) {
11627
+ throw new ProviderError(`${this.providerName} does not support embeddings`, this.providerName, 400);
11628
+ }
11539
11629
  /**
11540
11630
  * Helper concrete providers can wrap their fetch with. Retries 429/5xx
11541
11631
  * with exponential backoff and respects Retry-After if the response
@@ -11577,34 +11667,13 @@ var BaseProvider = class {
11577
11667
  }
11578
11668
  };
11579
11669
 
11580
- // src/providers/types.ts
11581
- function emptyUsage() {
11582
- return {
11583
- inputTokens: 0,
11584
- outputTokens: 0,
11585
- totalTokens: 0,
11586
- cachedInputTokens: 0,
11587
- cachedWriteTokens: 0,
11588
- cachedOutputTokens: 0,
11589
- reasoningTokens: 0
11590
- };
11591
- }
11592
- var ProviderError = class extends Error {
11593
- constructor(message, provider, statusCode, responseBody) {
11594
- super(message);
11595
- this.provider = provider;
11596
- this.statusCode = statusCode;
11597
- this.responseBody = responseBody;
11598
- this.name = "ProviderError";
11599
- }
11600
- };
11601
-
11602
11670
  // src/providers/jev.ts
11603
11671
  var JEV_DEFAULT_BASE_URL = "https://api.typesafe.ai";
11604
11672
  var JevProvider = class extends BaseProvider {
11605
11673
  constructor(config) {
11606
11674
  super();
11607
11675
  this.providerName = "jev";
11676
+ this.configureTransport(config);
11608
11677
  this.apiKey = config.apiKey;
11609
11678
  this.baseURL = (config.baseURL ?? JEV_DEFAULT_BASE_URL).replace(/\/$/, "");
11610
11679
  this.defaultModel = config.defaultModel;
@@ -11620,7 +11689,7 @@ var JevProvider = class extends BaseProvider {
11620
11689
  questions: request.questions
11621
11690
  };
11622
11691
  const res = await this.doFetchWithRetry(
11623
- () => fetch(`${this.baseURL}/v1/systemone`, {
11692
+ () => this.httpFetch(`${this.baseURL}/v1/systemone`, {
11624
11693
  method: "POST",
11625
11694
  headers: {
11626
11695
  "Content-Type": "application/json",
@@ -13856,12 +13925,12 @@ function responseCache(config = {}) {
13856
13925
  };
13857
13926
  }
13858
13927
  function signRequest(req) {
13859
- const now = /* @__PURE__ */ new Date();
13928
+ const now = req.now ?? /* @__PURE__ */ new Date();
13860
13929
  const dateStamp = toDateStamp(now);
13861
13930
  const amzDate = toAmzDate(now);
13862
13931
  const parsed = new URL(req.url);
13863
13932
  const host = parsed.host;
13864
- const canonicalUri = parsed.pathname || "/";
13933
+ const canonicalUri = (parsed.pathname || "/").split("/").map((seg) => encodeURIComponent(seg).replace(/[!'()*]/g, (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase())).join("/");
13865
13934
  const canonicalQuerystring = sortQueryParams(parsed.searchParams);
13866
13935
  const headers = {
13867
13936
  ...req.headers,
@@ -15178,98 +15247,805 @@ function languageGuard(config) {
15178
15247
  // src/index.ts
15179
15248
  init_content();
15180
15249
 
15181
- // src/providers/utils/sse.ts
15182
- async function* parseSSEStream(body, signal) {
15183
- const reader = body.getReader();
15184
- const decoder = new TextDecoder();
15185
- let buffer = "";
15186
- try {
15187
- while (true) {
15188
- if (signal?.aborted) throw abortReason(signal);
15189
- const { done, value } = await reader.read();
15190
- if (done) break;
15191
- buffer += decoder.decode(value, { stream: true });
15192
- const parts = buffer.split(/\r?\n\r?\n/);
15193
- buffer = parts.pop() ?? "";
15194
- for (const part of parts) {
15195
- if (!part.trim()) continue;
15196
- const event = parseSSEBlock(part);
15197
- if (event) yield event;
15198
- }
15250
+ // src/models/model-rules.json
15251
+ var model_rules_default = {
15252
+ version: 1,
15253
+ effortLadder: [
15254
+ "none",
15255
+ "minimal",
15256
+ "low",
15257
+ "medium",
15258
+ "high",
15259
+ "xhigh",
15260
+ "max"
15261
+ ],
15262
+ budgets: {
15263
+ minimal: 1024,
15264
+ low: 2048,
15265
+ medium: 8192,
15266
+ high: 16384,
15267
+ xhigh: 24576,
15268
+ max: 32768
15269
+ },
15270
+ geminiBudgets: {
15271
+ minimal: 512,
15272
+ low: 1024,
15273
+ medium: 4096,
15274
+ high: 12e3,
15275
+ xhigh: 24576,
15276
+ max: 24576
15277
+ },
15278
+ rules: [
15279
+ {
15280
+ id: "openai-chat-models",
15281
+ family: "openai",
15282
+ match: "^(?:chatgpt|gpt-[\\d.]+[a-z0-9.-]*?-chat)",
15283
+ reasoning: {
15284
+ style: "none",
15285
+ efforts: [],
15286
+ off: null
15287
+ },
15288
+ sampling: {
15289
+ temperature: "any",
15290
+ topP: true,
15291
+ topK: true,
15292
+ penalties: true,
15293
+ logprobs: true
15294
+ },
15295
+ maxTokensParam: "max_completion_tokens",
15296
+ chatTools: {
15297
+ reasoning: "any"
15298
+ },
15299
+ source: "docs",
15300
+ note: "Chat-tuned *-chat variants are not reasoning models: ordinary sampling, no reasoning field."
15301
+ },
15302
+ {
15303
+ id: "openai-gpt-6-plus",
15304
+ family: "openai",
15305
+ match: "^gpt-?(?:[6-9]|(?!35(?!\\d))[1-9]\\d+)(?:[.-]|$)",
15306
+ reasoning: {
15307
+ style: "effort",
15308
+ efforts: [
15309
+ "none",
15310
+ "low",
15311
+ "medium",
15312
+ "high",
15313
+ "xhigh"
15314
+ ],
15315
+ off: "none",
15316
+ responsesEfforts: [
15317
+ "none",
15318
+ "low",
15319
+ "medium",
15320
+ "high",
15321
+ "xhigh",
15322
+ "max"
15323
+ ]
15324
+ },
15325
+ sampling: {
15326
+ temperature: "default-only",
15327
+ topP: false,
15328
+ topK: false,
15329
+ penalties: false,
15330
+ logprobs: false
15331
+ },
15332
+ maxTokensParam: "max_completion_tokens",
15333
+ chatTools: {
15334
+ reasoning: "force-none"
15335
+ },
15336
+ source: "verified-2026-10-14",
15337
+ note: "gpt-N, N>=6. Chat Completions takes none/low/medium/high/xhigh (minimal and max are 400s); Responses also takes max. Function tools with an effort other than none are a 400 on Chat Completions and the default effort is not none, so none is sent explicitly. Rejects max_tokens, temperature != 1, top_p, penalties, logprobs."
15338
+ },
15339
+ {
15340
+ id: "openai-gpt-5x",
15341
+ family: "openai",
15342
+ match: "^gpt-?5\\.[1-9]",
15343
+ reasoning: {
15344
+ style: "effort",
15345
+ efforts: [
15346
+ "none",
15347
+ "low",
15348
+ "medium",
15349
+ "high",
15350
+ "xhigh"
15351
+ ],
15352
+ off: "none",
15353
+ responsesEfforts: [
15354
+ "none",
15355
+ "low",
15356
+ "medium",
15357
+ "high",
15358
+ "xhigh",
15359
+ "max"
15360
+ ]
15361
+ },
15362
+ sampling: {
15363
+ temperature: "default-only",
15364
+ topP: false,
15365
+ topK: false,
15366
+ penalties: false,
15367
+ logprobs: false
15368
+ },
15369
+ maxTokensParam: "max_completion_tokens",
15370
+ chatTools: {
15371
+ reasoning: "force-none"
15372
+ },
15373
+ source: "verified-2026-10-14",
15374
+ note: "gpt-5.1 and newer 5.x. Same wire rules as gpt-6: no minimal/max on Chat Completions (Responses takes max), function tools need reasoning_effort none on Chat Completions."
15375
+ },
15376
+ {
15377
+ id: "openai-gpt-5-base",
15378
+ family: "openai",
15379
+ match: "^gpt-?5(?![.\\d])",
15380
+ reasoning: {
15381
+ style: "effort",
15382
+ efforts: [
15383
+ "minimal",
15384
+ "low",
15385
+ "medium",
15386
+ "high"
15387
+ ],
15388
+ off: null
15389
+ },
15390
+ sampling: {
15391
+ temperature: "default-only",
15392
+ topP: false,
15393
+ topK: false,
15394
+ penalties: false,
15395
+ logprobs: false
15396
+ },
15397
+ maxTokensParam: "max_completion_tokens",
15398
+ chatTools: {
15399
+ reasoning: "any"
15400
+ },
15401
+ source: "docs",
15402
+ note: "gpt-5, -mini, -nano, -codex: minimal/low/medium/high, reasoning cannot be turned off (none maps to minimal)."
15403
+ },
15404
+ {
15405
+ id: "openai-o-series",
15406
+ family: "openai",
15407
+ match: "^o[1-9]\\d?(?![a-z0-9])",
15408
+ reasoning: {
15409
+ style: "effort",
15410
+ efforts: [
15411
+ "low",
15412
+ "medium",
15413
+ "high"
15414
+ ],
15415
+ off: null
15416
+ },
15417
+ sampling: {
15418
+ temperature: "default-only",
15419
+ topP: false,
15420
+ topK: false,
15421
+ penalties: false,
15422
+ logprobs: false
15423
+ },
15424
+ maxTokensParam: "max_completion_tokens",
15425
+ chatTools: {
15426
+ reasoning: "any"
15427
+ },
15428
+ source: "docs",
15429
+ note: "o1/o3/o4 family: low/medium/high, no sampling overrides."
15430
+ },
15431
+ {
15432
+ id: "openai-gpt-oss",
15433
+ family: "openai",
15434
+ match: "^gpt-?oss",
15435
+ reasoning: {
15436
+ style: "effort",
15437
+ efforts: [
15438
+ "low",
15439
+ "medium",
15440
+ "high"
15441
+ ],
15442
+ off: null
15443
+ },
15444
+ sampling: {
15445
+ temperature: "any",
15446
+ topP: true,
15447
+ topK: true,
15448
+ penalties: true,
15449
+ logprobs: true
15450
+ },
15451
+ maxTokensParam: "max_tokens",
15452
+ chatTools: {
15453
+ reasoning: "any"
15454
+ },
15455
+ source: "docs",
15456
+ note: "Open-weight gpt-oss: low/medium/high; sampling and max_tokens behave like an ordinary chat model."
15457
+ },
15458
+ {
15459
+ id: "openai-legacy-gpt",
15460
+ family: "openai",
15461
+ match: "^(?:gpt-?(?:[0-4]|35)(?![0-9])|text-|davinci|babbage)",
15462
+ reasoning: {
15463
+ style: "none",
15464
+ efforts: [],
15465
+ off: null
15466
+ },
15467
+ sampling: {
15468
+ temperature: "any",
15469
+ topP: true,
15470
+ topK: true,
15471
+ penalties: true,
15472
+ logprobs: true
15473
+ },
15474
+ maxTokensParam: "max_tokens",
15475
+ chatTools: {
15476
+ reasoning: "any"
15477
+ },
15478
+ source: "docs",
15479
+ note: "gpt-4o, gpt-4.1, gpt-3.5 and older: no reasoning, ordinary sampling."
15480
+ },
15481
+ {
15482
+ id: "openai-compatible-toggle",
15483
+ family: "openai",
15484
+ match: "^(?:deepseek-(?:r\\d|reasoner)|qwq|qwen-?3)",
15485
+ reasoning: {
15486
+ style: "toggle",
15487
+ efforts: [
15488
+ "none",
15489
+ "minimal",
15490
+ "low",
15491
+ "medium",
15492
+ "high",
15493
+ "xhigh",
15494
+ "max"
15495
+ ],
15496
+ off: "none"
15497
+ },
15498
+ sampling: {
15499
+ temperature: "any",
15500
+ topP: true,
15501
+ topK: true,
15502
+ penalties: true,
15503
+ logprobs: true
15504
+ },
15505
+ maxTokensParam: "max_tokens",
15506
+ chatTools: {
15507
+ reasoning: "any"
15508
+ },
15509
+ source: "docs",
15510
+ note: "DeepSeek R/reasoner, QwQ, Qwen3: on/off style hosts. The effort is forwarded as-is (including none, which switches thinking off on thinking-by-default models)."
15511
+ },
15512
+ {
15513
+ id: "openai-default",
15514
+ family: "openai",
15515
+ match: ".*",
15516
+ reasoning: {
15517
+ style: "effort",
15518
+ efforts: [
15519
+ "none",
15520
+ "minimal",
15521
+ "low",
15522
+ "medium",
15523
+ "high",
15524
+ "xhigh",
15525
+ "max"
15526
+ ],
15527
+ off: "none"
15528
+ },
15529
+ sampling: {
15530
+ temperature: "any",
15531
+ topP: true,
15532
+ topK: true,
15533
+ penalties: true,
15534
+ logprobs: true
15535
+ },
15536
+ maxTokensParam: "max_tokens",
15537
+ chatTools: {
15538
+ reasoning: "any"
15539
+ },
15540
+ source: "docs",
15541
+ note: "Permissive default for unknown OpenAI-wire models: pass what the caller asked; the provider learns from 400s."
15542
+ },
15543
+ {
15544
+ id: "claude-haiku-5",
15545
+ family: "anthropic",
15546
+ match: "^claude-(?:haiku-5|5(?:-\\d+)?-haiku)(?!\\d)",
15547
+ reasoning: {
15548
+ style: "adaptive",
15549
+ efforts: [
15550
+ "low",
15551
+ "medium",
15552
+ "high",
15553
+ "xhigh",
15554
+ "max"
15555
+ ],
15556
+ off: "disabled"
15557
+ },
15558
+ sampling: {
15559
+ temperature: "unsupported",
15560
+ topP: false,
15561
+ topK: false,
15562
+ penalties: false,
15563
+ logprobs: false
15564
+ },
15565
+ maxTokensParam: "max_tokens",
15566
+ chatTools: {
15567
+ reasoning: "any"
15568
+ },
15569
+ source: "verified-2026-10-14",
15570
+ note: "Claude Haiku 5.x: thinking:{type:adaptive} + output_config.effort; thinking:{type:enabled,budget_tokens} is rejected. Off = thinking:{type:disabled}. Sampling params are rejected."
15571
+ },
15572
+ {
15573
+ id: "claude-sonnet-5",
15574
+ family: "anthropic",
15575
+ match: "^claude-(?:sonnet-5|5(?:-\\d+)?-sonnet)(?!\\d)",
15576
+ reasoning: {
15577
+ style: "adaptive",
15578
+ efforts: [
15579
+ "low",
15580
+ "medium",
15581
+ "high",
15582
+ "xhigh",
15583
+ "max"
15584
+ ],
15585
+ off: "between_tools"
15586
+ },
15587
+ sampling: {
15588
+ temperature: "unsupported",
15589
+ topP: false,
15590
+ topK: false,
15591
+ penalties: false,
15592
+ logprobs: false
15593
+ },
15594
+ maxTokensParam: "max_tokens",
15595
+ chatTools: {
15596
+ reasoning: "any"
15597
+ },
15598
+ source: "verified-2026-10-14",
15599
+ note: "Claude Sonnet 5.x: adaptive + output_config.effort. thinking:{type:disabled} is rejected; off = thinking:{type:between_tools}. Sampling params are rejected."
15600
+ },
15601
+ {
15602
+ id: "claude-opus-5",
15603
+ family: "anthropic",
15604
+ match: "^claude-(?:opus-5|5(?:-\\d+)?-opus)(?!\\d)",
15605
+ reasoning: {
15606
+ style: "adaptive",
15607
+ efforts: [
15608
+ "low",
15609
+ "medium",
15610
+ "high",
15611
+ "xhigh",
15612
+ "max"
15613
+ ],
15614
+ off: null
15615
+ },
15616
+ sampling: {
15617
+ temperature: "unsupported",
15618
+ topP: false,
15619
+ topK: false,
15620
+ penalties: false,
15621
+ logprobs: false
15622
+ },
15623
+ maxTokensParam: "max_tokens",
15624
+ chatTools: {
15625
+ reasoning: "any"
15626
+ },
15627
+ source: "verified-2026-10-14",
15628
+ note: "Claude Opus 5.x: adaptive + output_config.effort; thinking cannot be turned off (none maps to the lowest effort). Sampling params are rejected."
15629
+ },
15630
+ {
15631
+ id: "claude-fable",
15632
+ family: "anthropic",
15633
+ match: "^claude-fable",
15634
+ reasoning: {
15635
+ style: "adaptive",
15636
+ efforts: [
15637
+ "low",
15638
+ "medium",
15639
+ "high",
15640
+ "xhigh",
15641
+ "max"
15642
+ ],
15643
+ off: null
15644
+ },
15645
+ sampling: {
15646
+ temperature: "unsupported",
15647
+ topP: false,
15648
+ topK: false,
15649
+ penalties: false,
15650
+ logprobs: false
15651
+ },
15652
+ maxTokensParam: "max_tokens",
15653
+ chatTools: {
15654
+ reasoning: "any"
15655
+ },
15656
+ source: "docs",
15657
+ note: "Claude Fable line: treated like the 5.x adaptive models."
15658
+ },
15659
+ {
15660
+ id: "claude-4-7",
15661
+ family: "anthropic",
15662
+ match: "^claude-(?:(?:opus|sonnet|haiku)-4[-.]7|4[-.]7-(?:opus|sonnet|haiku))(?!\\d)",
15663
+ reasoning: {
15664
+ style: "adaptive",
15665
+ efforts: [
15666
+ "low",
15667
+ "medium",
15668
+ "high",
15669
+ "xhigh",
15670
+ "max"
15671
+ ],
15672
+ off: "disabled"
15673
+ },
15674
+ sampling: {
15675
+ temperature: "thinking-requires-1",
15676
+ topP: true,
15677
+ topK: true,
15678
+ penalties: true,
15679
+ logprobs: true
15680
+ },
15681
+ maxTokensParam: "max_tokens",
15682
+ chatTools: {
15683
+ reasoning: "any"
15684
+ },
15685
+ source: "docs",
15686
+ note: "Claude 4.7: adaptive thinking, low/medium/high/xhigh/max."
15687
+ },
15688
+ {
15689
+ id: "claude-4-6",
15690
+ family: "anthropic",
15691
+ match: "^claude-(?:(?:opus|sonnet|haiku)-4[-.]6|4[-.]6-(?:opus|sonnet|haiku))(?!\\d)",
15692
+ reasoning: {
15693
+ style: "adaptive",
15694
+ efforts: [
15695
+ "low",
15696
+ "medium",
15697
+ "high",
15698
+ "max"
15699
+ ],
15700
+ off: "disabled"
15701
+ },
15702
+ sampling: {
15703
+ temperature: "thinking-requires-1",
15704
+ topP: true,
15705
+ topK: true,
15706
+ penalties: true,
15707
+ logprobs: true
15708
+ },
15709
+ maxTokensParam: "max_tokens",
15710
+ chatTools: {
15711
+ reasoning: "any"
15712
+ },
15713
+ source: "docs",
15714
+ note: "Claude 4.6: adaptive thinking, low/medium/high/max (no xhigh)."
15715
+ },
15716
+ {
15717
+ id: "claude-legacy-budget",
15718
+ family: "anthropic",
15719
+ match: "^claude-(?:3|4-|(?:opus|sonnet|haiku)-4)",
15720
+ reasoning: {
15721
+ style: "budget",
15722
+ efforts: [
15723
+ "none",
15724
+ "minimal",
15725
+ "low",
15726
+ "medium",
15727
+ "high",
15728
+ "xhigh",
15729
+ "max"
15730
+ ],
15731
+ off: null
15732
+ },
15733
+ sampling: {
15734
+ temperature: "thinking-requires-1",
15735
+ topP: true,
15736
+ topK: true,
15737
+ penalties: true,
15738
+ logprobs: true
15739
+ },
15740
+ maxTokensParam: "max_tokens",
15741
+ chatTools: {
15742
+ reasoning: "any"
15743
+ },
15744
+ source: "docs",
15745
+ note: "Claude 3.7 and 4.0-4.5: thinking:{type:enabled,budget_tokens}; every effort maps to a budget; sampling overrides are not allowed while thinking."
15746
+ },
15747
+ {
15748
+ id: "anthropic-default",
15749
+ family: "anthropic",
15750
+ match: ".*",
15751
+ reasoning: {
15752
+ style: "budget",
15753
+ efforts: [
15754
+ "none",
15755
+ "minimal",
15756
+ "low",
15757
+ "medium",
15758
+ "high",
15759
+ "xhigh",
15760
+ "max"
15761
+ ],
15762
+ off: null
15763
+ },
15764
+ sampling: {
15765
+ temperature: "thinking-requires-1",
15766
+ topP: true,
15767
+ topK: true,
15768
+ penalties: true,
15769
+ logprobs: true
15770
+ },
15771
+ maxTokensParam: "max_tokens",
15772
+ chatTools: {
15773
+ reasoning: "any"
15774
+ },
15775
+ source: "docs",
15776
+ note: "Permissive default for unknown Anthropic-wire models: budget style (the long-standing form); the provider flips the thinking form when the API says so."
15777
+ },
15778
+ {
15779
+ id: "gemini-budget",
15780
+ family: "gemini",
15781
+ match: "^gemini",
15782
+ reasoning: {
15783
+ style: "budget",
15784
+ efforts: [
15785
+ "none",
15786
+ "minimal",
15787
+ "low",
15788
+ "medium",
15789
+ "high",
15790
+ "xhigh",
15791
+ "max"
15792
+ ],
15793
+ off: "none"
15794
+ },
15795
+ sampling: {
15796
+ temperature: "any",
15797
+ topP: true,
15798
+ topK: true,
15799
+ penalties: true,
15800
+ logprobs: true
15801
+ },
15802
+ maxTokensParam: "max_tokens",
15803
+ chatTools: {
15804
+ reasoning: "any"
15805
+ },
15806
+ source: "docs",
15807
+ note: "Gemini 2.5-style thinkingBudget; effort maps to a token budget, none = budget 0."
15808
+ },
15809
+ {
15810
+ id: "gemini-default",
15811
+ family: "gemini",
15812
+ match: ".*",
15813
+ reasoning: {
15814
+ style: "budget",
15815
+ efforts: [
15816
+ "none",
15817
+ "minimal",
15818
+ "low",
15819
+ "medium",
15820
+ "high",
15821
+ "xhigh",
15822
+ "max"
15823
+ ],
15824
+ off: "none"
15825
+ },
15826
+ sampling: {
15827
+ temperature: "any",
15828
+ topP: true,
15829
+ topK: true,
15830
+ penalties: true,
15831
+ logprobs: true
15832
+ },
15833
+ maxTokensParam: "max_tokens",
15834
+ chatTools: {
15835
+ reasoning: "any"
15836
+ },
15837
+ source: "docs",
15838
+ note: "Permissive default for unknown Gemini-wire models."
15839
+ },
15840
+ {
15841
+ id: "other-default",
15842
+ family: "other",
15843
+ match: ".*",
15844
+ reasoning: {
15845
+ style: "effort",
15846
+ efforts: [
15847
+ "none",
15848
+ "minimal",
15849
+ "low",
15850
+ "medium",
15851
+ "high",
15852
+ "xhigh",
15853
+ "max"
15854
+ ],
15855
+ off: "none"
15856
+ },
15857
+ sampling: {
15858
+ temperature: "any",
15859
+ topP: true,
15860
+ topK: true,
15861
+ penalties: true,
15862
+ logprobs: true
15863
+ },
15864
+ maxTokensParam: "max_tokens",
15865
+ chatTools: {
15866
+ reasoning: "any"
15867
+ },
15868
+ source: "docs",
15869
+ note: "Permissive default for model families the SDK has no rules for."
15199
15870
  }
15200
- if (buffer.trim()) {
15201
- const event = parseSSEBlock(buffer);
15202
- if (event) yield event;
15871
+ ]
15872
+ };
15873
+
15874
+ // src/models/rules.ts
15875
+ var MODEL_RULES = model_rules_default;
15876
+ var LADDER = MODEL_RULES.effortLadder;
15877
+ var compiled = /* @__PURE__ */ new Map();
15878
+ function regexFor(rule) {
15879
+ let re = compiled.get(rule.id);
15880
+ if (!re) {
15881
+ re = new RegExp(rule.match, "i");
15882
+ compiled.set(rule.id, re);
15883
+ }
15884
+ return re;
15885
+ }
15886
+ var GATEWAY_PREFIX = /^(?:(?:global|us|eu|apac|jp|au|ca|us-gov)\.)?(?:(?:openai|anthropic|google|meta|amazon|deepseek|qwen|mistral|cohere|ai21)\.)?/;
15887
+ function modelIdCandidates(model) {
15888
+ if (!model) return [];
15889
+ const lower = String(model).trim().toLowerCase();
15890
+ const last = lower.split("/").pop() ?? lower;
15891
+ const out = [];
15892
+ for (const id of [lower, last]) {
15893
+ for (const c of [id, id.replace(GATEWAY_PREFIX, "")]) {
15894
+ if (c && !out.includes(c)) out.push(c);
15203
15895
  }
15204
- } finally {
15205
- reader.cancel().catch(() => void 0);
15206
- reader.releaseLock();
15207
15896
  }
15897
+ return out;
15208
15898
  }
15209
- function parseSSEBlock(block) {
15210
- let event;
15211
- let id;
15212
- let retry;
15213
- const dataLines = [];
15214
- for (const line of block.split(/\r?\n/)) {
15215
- if (line.startsWith(":")) continue;
15216
- const colonIdx = line.indexOf(":");
15217
- let field;
15218
- let value;
15219
- if (colonIdx === -1) {
15220
- field = line;
15221
- value = "";
15222
- } else {
15223
- field = line.slice(0, colonIdx);
15224
- value = line.slice(colonIdx + 1);
15225
- if (value.startsWith(" ")) value = value.slice(1);
15226
- }
15227
- switch (field) {
15228
- case "event":
15229
- event = value;
15230
- break;
15231
- case "data":
15232
- dataLines.push(value);
15233
- break;
15234
- case "id":
15235
- id = value;
15236
- break;
15237
- case "retry": {
15238
- const n = parseInt(value, 10);
15239
- if (!isNaN(n)) retry = n;
15240
- break;
15241
- }
15899
+ var OPENAI_WIRE = /* @__PURE__ */ new Set(["openai", "azure", "openai-compatible", "together", "openrouter", "groq", "fireworks", "ollama", "vllm", "litellm", "mistral", "deepseek", "xai", "jev"]);
15900
+ function familiesFor(provider) {
15901
+ const p = (provider ?? "").toLowerCase();
15902
+ if (OPENAI_WIRE.has(p)) return ["openai"];
15903
+ if (p === "anthropic") return ["anthropic"];
15904
+ if (p === "bedrock") return ["anthropic", "openai", "other"];
15905
+ if (p === "vertex" || p === "gemini" || p === "google") return ["gemini", "anthropic"];
15906
+ return ["openai", "anthropic", "gemini", "other"];
15907
+ }
15908
+ function matchRule(family, ids, allowDefault) {
15909
+ for (const rule of MODEL_RULES.rules) {
15910
+ if (rule.family !== family) continue;
15911
+ if (rule.match === ".*") {
15912
+ if (allowDefault) return rule;
15913
+ continue;
15242
15914
  }
15915
+ const re = regexFor(rule);
15916
+ if (ids.some((id) => re.test(id))) return rule;
15243
15917
  }
15244
- if (dataLines.length === 0) return null;
15245
- return { event, data: dataLines.join("\n"), id, retry };
15918
+ return void 0;
15246
15919
  }
15247
-
15248
- // src/providers/utils/reasoning.ts
15249
- var ANTHROPIC_EFFORT_BUDGET = {
15250
- // 0 = off. `applyAnthropicReasoning` bails on a falsy budget and emits no
15251
- // thinking block, which on Anthropic IS off — thinking there is opt-in.
15920
+ function mergeRulePatch(base, patch) {
15921
+ if (!patch) return base;
15922
+ const out = { ...base };
15923
+ if (patch.reasoning) out.reasoning = { ...base.reasoning ?? {}, ...patch.reasoning };
15924
+ if (patch.sampling) out.sampling = { ...base.sampling ?? {}, ...patch.sampling };
15925
+ if (patch.chatTools) out.chatTools = { ...base.chatTools ?? {}, ...patch.chatTools };
15926
+ if (patch.maxTokensParam) out.maxTokensParam = patch.maxTokensParam;
15927
+ if (patch.dropParams) out.dropParams = [.../* @__PURE__ */ new Set([...base.dropParams ?? [], ...patch.dropParams])];
15928
+ return out;
15929
+ }
15930
+ var LEARNED_MAX = 500;
15931
+ var learned = /* @__PURE__ */ new Map();
15932
+ function learnedKey(provider, model, scope) {
15933
+ return `${(provider ?? "").toLowerCase()}@${scope ?? ""}::${(model ?? "").trim().toLowerCase()}`;
15934
+ }
15935
+ function rememberModelRulePatch(provider, model, patch, scope) {
15936
+ const key = learnedKey(provider, model, scope);
15937
+ const merged = mergeRulePatch(learned.get(key)?.patch ?? {}, patch);
15938
+ learned.delete(key);
15939
+ learned.set(key, { provider: provider.toLowerCase(), model: model.trim().toLowerCase(), scope, patch: merged });
15940
+ if (learned.size > LEARNED_MAX) learned.delete(learned.keys().next().value);
15941
+ }
15942
+ function getLearnedModelRulePatch(provider, model, scope) {
15943
+ return learned.get(learnedKey(provider, model, scope))?.patch;
15944
+ }
15945
+ function listLearnedModelRules() {
15946
+ return [...learned.values()].map((e) => ({ ...e }));
15947
+ }
15948
+ function clearLearnedModelRules() {
15949
+ learned.clear();
15950
+ }
15951
+ function resolveModelRule(opts) {
15952
+ const families = familiesFor(opts.provider);
15953
+ const ids = modelIdCandidates(opts.model);
15954
+ let rule;
15955
+ for (const family of families) {
15956
+ rule = matchRule(family, ids, false);
15957
+ if (rule) break;
15958
+ }
15959
+ let isDefault = false;
15960
+ if (!rule) {
15961
+ isDefault = true;
15962
+ rule = matchRule(families[0], ids, true) ?? MODEL_RULES.rules[MODEL_RULES.rules.length - 1];
15963
+ }
15964
+ let effective = rule;
15965
+ const known = opts.model ? learned.get(learnedKey(opts.provider, opts.model, opts.scope))?.patch : void 0;
15966
+ if (known) effective = mergeRulePatch(effective, known);
15967
+ if (opts.patch) effective = mergeRulePatch(effective, opts.patch);
15968
+ return { ...effective, matchedRuleId: rule.id, isDefault, learned: !!known };
15969
+ }
15970
+ function mapReasoningEffort(rule, effort, endpoint = "chat") {
15971
+ const efforts = endpoint === "responses" && rule.reasoning.responsesEfforts || rule.reasoning.efforts;
15972
+ if (rule.reasoning.style === "none" || efforts.length === 0) return { mapped: true };
15973
+ const supported = LADDER.filter((e) => efforts.includes(e));
15974
+ if (supported.includes(effort)) return { effort, mapped: false };
15975
+ if (effort === "none") {
15976
+ const off = rule.reasoning.off;
15977
+ if (off && off !== "none") return { off, mapped: true };
15978
+ const lowest = supported.find((e) => e !== "none");
15979
+ return lowest ? { effort: lowest, mapped: true } : { mapped: true };
15980
+ }
15981
+ const at = LADDER.indexOf(effort);
15982
+ if (at < 0) return { mapped: true };
15983
+ for (let i = at - 1; i >= 1; i--) if (supported.includes(LADDER[i])) return { effort: LADDER[i], mapped: true };
15984
+ for (let i = at + 1; i < LADDER.length; i++) if (supported.includes(LADDER[i])) return { effort: LADDER[i], mapped: true };
15985
+ return supported.includes("none") ? { effort: "none", mapped: true } : { mapped: true };
15986
+ }
15987
+ function allowsSampling(rule, field, value, thinkingOn = false) {
15988
+ const s = rule.sampling;
15989
+ switch (field) {
15990
+ case "temperature":
15991
+ switch (s.temperature) {
15992
+ case "any":
15993
+ return true;
15994
+ case "unsupported":
15995
+ return false;
15996
+ // The default is what the server applies anyway, so it is never sent.
15997
+ case "default-only":
15998
+ return false;
15999
+ case "thinking-requires-1":
16000
+ return !thinkingOn || value === 1;
16001
+ }
16002
+ return true;
16003
+ // Anthropic's thinking restriction covers top_p / top_k as well as temperature.
16004
+ case "topP":
16005
+ return s.topP && !(thinkingOn && s.temperature === "thinking-requires-1");
16006
+ case "topK":
16007
+ return s.topK && !(thinkingOn && s.temperature === "thinking-requires-1");
16008
+ case "presencePenalty":
16009
+ case "frequencyPenalty":
16010
+ return s.penalties;
16011
+ case "logprobs":
16012
+ return s.logprobs;
16013
+ }
16014
+ }
16015
+ function applyDropParams(body, rule) {
16016
+ for (const p of rule.dropParams ?? []) {
16017
+ const dot = p.indexOf(".");
16018
+ if (dot < 0) delete body[p];
16019
+ else if (body[p.slice(0, dot)] && typeof body[p.slice(0, dot)] === "object") delete body[p.slice(0, dot)][p.slice(dot + 1)];
16020
+ }
16021
+ }
16022
+ function effortBudget(effort, table = "anthropic") {
16023
+ if (effort === "none") return 0;
16024
+ return (table === "gemini" ? MODEL_RULES.geminiBudgets : MODEL_RULES.budgets)[effort] ?? 0;
16025
+ }
16026
+
16027
+ // src/providers/utils/reasoning.ts
16028
+ var ANTHROPIC_EFFORT_BUDGET = {
16029
+ // 0 = off. `applyAnthropicReasoning` bails on a falsy budget and emits no
16030
+ // thinking block, which on Anthropic IS off — thinking there is opt-in.
15252
16031
  none: 0,
15253
- minimal: 1024,
15254
- low: 2048,
15255
- medium: 8192,
15256
- high: 16384
16032
+ ...MODEL_RULES.budgets
15257
16033
  };
15258
16034
  var GEMINI_EFFORT_BUDGET = {
15259
16035
  // 0 is Gemini's own documented spelling for "do not think", and unlike
15260
16036
  // Anthropic it has to be SENT — hence `applyGeminiReasoning` testing for null
15261
16037
  // rather than falsiness.
15262
16038
  none: 0,
15263
- minimal: 512,
15264
- low: 1024,
15265
- medium: 4096,
15266
- high: 12e3
16039
+ ...MODEL_RULES.geminiBudgets
15267
16040
  };
15268
16041
  var THINKING_OUTPUT_RESERVE = 1024;
16042
+ var MIN_THINKING_BUDGET = 1024;
15269
16043
  var THINKING_MIN_MAX_TOKENS = 4096;
15270
- function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
16044
+ function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort", model, rule) {
15271
16045
  if (!reasoning) return;
15272
- const effort = normalizeEffort(reasoning.effort);
16046
+ const requested = normalizeEffort(reasoning.effort);
16047
+ const r = rule ?? resolveModelRule({ provider: "openai", model: model ?? body.model });
16048
+ const effort = requested && mapReasoningEffort(r, requested, mode === "responses" ? "responses" : "chat").effort;
15273
16049
  if (mode === "responses") {
15274
16050
  const obj = {};
15275
16051
  if (effort) obj.effort = effort;
@@ -15281,52 +16057,107 @@ function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
15281
16057
  if (reasoning.providerExtras) Object.assign(body, reasoning.providerExtras);
15282
16058
  }
15283
16059
  }
15284
- function applyAnthropicReasoning(body, reasoning) {
15285
- if (!reasoning) return;
15286
- let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
15287
- if (!budget) return;
16060
+ function supportsAdaptiveThinking(model) {
16061
+ if (typeof model !== "string") return false;
16062
+ return resolveModelRule({ provider: "anthropic", model }).reasoning.style === "adaptive";
16063
+ }
16064
+ function resolveThinkingForm(model, mode, rule) {
16065
+ if (mode === "adaptive" || mode === "budget") return mode;
16066
+ if (rule) return rule.reasoning.style === "adaptive" ? "adaptive" : "budget";
16067
+ return supportsAdaptiveThinking(model) ? "adaptive" : "budget";
16068
+ }
16069
+ function enforceAnthropicSampling(target, rule, thinkingOn, bedrock = false) {
16070
+ const fields = bedrock ? [["temperature", "temperature"], ["topP", "topP"]] : [["temperature", "temperature"], ["top_p", "topP"], ["top_k", "topK"]];
16071
+ for (const [key, field] of fields) {
16072
+ if (key in target && !allowsSampling(rule, field, target[key], thinkingOn)) delete target[key];
16073
+ }
16074
+ }
16075
+ function applyAdaptiveThinking(reasoning, rule, setThinking, setOutputConfig) {
16076
+ let requested = normalizeEffort(reasoning.effort);
16077
+ if (!requested && typeof reasoning.budgetTokens === "number" && reasoning.budgetTokens > 0) {
16078
+ requested = reasoning.budgetTokens <= ANTHROPIC_EFFORT_BUDGET.low ? "low" : reasoning.budgetTokens <= ANTHROPIC_EFFORT_BUDGET.medium ? "medium" : "high";
16079
+ }
16080
+ if (!requested) return false;
16081
+ const mapped = mapReasoningEffort(rule, requested);
16082
+ if (mapped.off) {
16083
+ setThinking({ type: mapped.off });
16084
+ return false;
16085
+ }
16086
+ if (!mapped.effort || mapped.effort === "none") return false;
16087
+ const thinking = { type: "adaptive" };
16088
+ if (reasoning.includeThoughts !== false) thinking.display = "summarized";
16089
+ if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
16090
+ setThinking(thinking);
16091
+ setOutputConfig({ effort: mapped.effort });
16092
+ return true;
16093
+ }
16094
+ function applyAnthropicReasoning(body, reasoning, opts) {
16095
+ const rule = opts?.rule ?? resolveModelRule({ provider: "anthropic", model: opts?.model ?? body.model });
16096
+ if (!reasoning) {
16097
+ enforceAnthropicSampling(body, rule, false);
16098
+ return;
16099
+ }
16100
+ if (resolveThinkingForm(opts?.model ?? body.model, opts?.mode, rule) === "adaptive") {
16101
+ const on = applyAdaptiveThinking(reasoning, rule, (t) => body.thinking = t, (o) => body.output_config = { ...body.output_config ?? {}, ...o });
16102
+ enforceAnthropicSampling(body, rule, on);
16103
+ return;
16104
+ }
16105
+ let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET, rule);
16106
+ if (!budget) {
16107
+ enforceAnthropicSampling(body, rule, false);
16108
+ return;
16109
+ }
15288
16110
  const currentMax = typeof body.max_tokens === "number" ? body.max_tokens : 0;
15289
16111
  const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
15290
16112
  if (currentMax < requiredMax) {
15291
16113
  body.max_tokens = requiredMax;
15292
16114
  }
15293
- budget = clampBudget(budget, body.max_tokens);
16115
+ budget = Math.max(MIN_THINKING_BUDGET, clampBudget(budget, body.max_tokens));
15294
16116
  const thinking = { type: "enabled", budget_tokens: budget };
15295
16117
  if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
15296
16118
  body.thinking = thinking;
15297
- stripSamplingParams(body, ["temperature", "top_p", "top_k"]);
16119
+ enforceAnthropicSampling(body, rule, true);
15298
16120
  }
15299
- function applyBedrockReasoning(body, reasoning) {
15300
- if (!reasoning) return;
15301
- let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
15302
- if (!budget) return;
16121
+ function applyBedrockReasoning(body, reasoning, opts) {
16122
+ const rule = opts?.rule ?? resolveModelRule({ provider: "bedrock", model: opts?.model ?? body.modelId });
16123
+ if (!reasoning) {
16124
+ if (body.inferenceConfig) enforceAnthropicSampling(body.inferenceConfig, rule, false, true);
16125
+ return;
16126
+ }
16127
+ if (resolveThinkingForm(opts?.model ?? body.modelId, opts?.mode, rule) === "adaptive") {
16128
+ const fields = () => body.additionalModelRequestFields ?? (body.additionalModelRequestFields = {});
16129
+ const on = applyAdaptiveThinking(reasoning, rule, (t) => fields().thinking = t, (o) => fields().output_config = { ...fields().output_config ?? {}, ...o });
16130
+ if (body.inferenceConfig) enforceAnthropicSampling(body.inferenceConfig, rule, on, true);
16131
+ return;
16132
+ }
16133
+ let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET, rule);
16134
+ if (!budget) {
16135
+ if (body.inferenceConfig) enforceAnthropicSampling(body.inferenceConfig, rule, false, true);
16136
+ return;
16137
+ }
15303
16138
  const inference = body.inferenceConfig ?? (body.inferenceConfig = {});
15304
16139
  const currentMax = typeof inference.maxTokens === "number" ? inference.maxTokens : 0;
15305
16140
  const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
15306
16141
  if (currentMax < requiredMax) {
15307
16142
  inference.maxTokens = requiredMax;
15308
16143
  }
15309
- budget = clampBudget(budget, inference.maxTokens);
16144
+ budget = Math.max(MIN_THINKING_BUDGET, clampBudget(budget, inference.maxTokens));
15310
16145
  const extra = body.additionalModelRequestFields ?? (body.additionalModelRequestFields = {});
15311
16146
  const thinking = { type: "enabled", budget_tokens: budget };
15312
16147
  if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
15313
16148
  extra.thinking = thinking;
15314
- stripSamplingParams(inference, ["temperature", "topP"]);
16149
+ enforceAnthropicSampling(inference, rule, true, true);
15315
16150
  }
15316
16151
  function applyGeminiReasoning(generationConfig, reasoning) {
15317
16152
  if (!reasoning) return;
15318
16153
  const budget = resolveBudget(reasoning, GEMINI_EFFORT_BUDGET);
15319
- if (budget == null) return;
15320
- const thinkingConfig = { thinkingBudget: budget };
16154
+ const level = typeof reasoning.thinkingLevel === "string" && reasoning.thinkingLevel ? reasoning.thinkingLevel : void 0;
16155
+ if (budget == null && !level) return;
16156
+ const thinkingConfig = level && budget !== 0 ? { thinkingLevel: level } : { thinkingBudget: budget ?? 0 };
15321
16157
  if (reasoning.includeThoughts) thinkingConfig.includeThoughts = true;
15322
16158
  if (reasoning.providerExtras) Object.assign(thinkingConfig, reasoning.providerExtras);
15323
16159
  generationConfig.thinkingConfig = thinkingConfig;
15324
16160
  }
15325
- function stripSamplingParams(target, keys) {
15326
- for (const k of keys) {
15327
- if (k in target) delete target[k];
15328
- }
15329
- }
15330
16161
  function clampBudget(budget, maxTokens) {
15331
16162
  if (typeof maxTokens !== "number" || maxTokens <= 0) return budget;
15332
16163
  const ceiling = maxTokens - THINKING_OUTPUT_RESERVE;
@@ -15335,19 +16166,292 @@ function clampBudget(budget, maxTokens) {
15335
16166
  }
15336
16167
  function normalizeEffort(effort) {
15337
16168
  if (!effort) return void 0;
15338
- const allowed = ["none", "minimal", "low", "medium", "high"];
16169
+ const allowed = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
15339
16170
  return allowed.includes(effort) ? effort : void 0;
15340
16171
  }
15341
- function resolveBudget(reasoning, effortBudget) {
16172
+ function resolveBudget(reasoning, effortBudget2, rule) {
15342
16173
  const effort = normalizeEffort(reasoning.effort);
15343
16174
  if (effort === "none") return 0;
15344
16175
  if (typeof reasoning.budgetTokens === "number" && reasoning.budgetTokens > 0) {
15345
16176
  return Math.floor(reasoning.budgetTokens);
15346
16177
  }
15347
- if (effort && effortBudget[effort]) return effortBudget[effort];
16178
+ const mapped = effort && rule ? mapReasoningEffort(rule, effort).effort : effort;
16179
+ if (mapped && effortBudget2[mapped]) return effortBudget2[mapped];
15348
16180
  return void 0;
15349
16181
  }
15350
16182
 
16183
+ // src/providers/utils/sse.ts
16184
+ async function* parseSSEStream(body, signal) {
16185
+ const reader = body.getReader();
16186
+ const decoder = new TextDecoder();
16187
+ let buffer = "";
16188
+ try {
16189
+ while (true) {
16190
+ if (signal?.aborted) throw abortReason(signal);
16191
+ const { done, value } = await reader.read();
16192
+ if (done) break;
16193
+ buffer += decoder.decode(value, { stream: true });
16194
+ const parts = buffer.split(/\r?\n\r?\n/);
16195
+ buffer = parts.pop() ?? "";
16196
+ for (const part of parts) {
16197
+ if (!part.trim()) continue;
16198
+ const event = parseSSEBlock(part);
16199
+ if (event) yield event;
16200
+ }
16201
+ }
16202
+ if (buffer.trim()) {
16203
+ const event = parseSSEBlock(buffer);
16204
+ if (event) yield event;
16205
+ }
16206
+ } finally {
16207
+ reader.cancel().catch(() => void 0);
16208
+ reader.releaseLock();
16209
+ }
16210
+ }
16211
+ function parseSSEBlock(block) {
16212
+ let event;
16213
+ let id;
16214
+ let retry;
16215
+ const dataLines = [];
16216
+ for (const line of block.split(/\r?\n/)) {
16217
+ if (line.startsWith(":")) continue;
16218
+ const colonIdx = line.indexOf(":");
16219
+ let field;
16220
+ let value;
16221
+ if (colonIdx === -1) {
16222
+ field = line;
16223
+ value = "";
16224
+ } else {
16225
+ field = line.slice(0, colonIdx);
16226
+ value = line.slice(colonIdx + 1);
16227
+ if (value.startsWith(" ")) value = value.slice(1);
16228
+ }
16229
+ switch (field) {
16230
+ case "event":
16231
+ event = value;
16232
+ break;
16233
+ case "data":
16234
+ dataLines.push(value);
16235
+ break;
16236
+ case "id":
16237
+ id = value;
16238
+ break;
16239
+ case "retry": {
16240
+ const n = parseInt(value, 10);
16241
+ if (!isNaN(n)) retry = n;
16242
+ break;
16243
+ }
16244
+ }
16245
+ }
16246
+ if (dataLines.length === 0) return null;
16247
+ return { event, data: dataLines.join("\n"), id, retry };
16248
+ }
16249
+
16250
+ // src/models/errors.ts
16251
+ var ModelRequestError = class extends ProviderError {
16252
+ constructor(init) {
16253
+ super(init.message, init.provider, init.status ?? 400, init.responseBody);
16254
+ this.status = init.status ?? 400;
16255
+ this.code = init.code;
16256
+ this.param = init.param;
16257
+ this.value = init.value;
16258
+ this.supportedValues = init.supportedValues;
16259
+ this.model = init.model;
16260
+ }
16261
+ };
16262
+
16263
+ // src/models/adjust.ts
16264
+ var MAX_ADJUSTMENTS = 3;
16265
+ var Q = "['\"`]";
16266
+ function errorMessage(text) {
16267
+ try {
16268
+ const j = JSON.parse(text);
16269
+ const e = j?.error ?? j;
16270
+ const message = typeof e?.message === "string" ? e.message : typeof j?.message === "string" ? j.message : text;
16271
+ return { message, param: typeof e?.param === "string" ? e.param : void 0, code: typeof e?.code === "string" ? e.code : void 0 };
16272
+ } catch {
16273
+ return { message: text };
16274
+ }
16275
+ }
16276
+ function quotedList(s) {
16277
+ const quoted = [...s.matchAll(new RegExp(`${Q}([^'"\`]+)${Q}`, "g"))].map((m) => m[1]);
16278
+ if (quoted.length > 0) return quoted;
16279
+ return s.split(/[,\s]+/).map((x) => x.replace(/[.\s]+$/, "")).filter(Boolean);
16280
+ }
16281
+ function parseModelError(text) {
16282
+ const { message, param: errParam } = errorMessage(String(text ?? ""));
16283
+ const m = message.toLowerCase();
16284
+ if (m.includes("function tools with reasoning_effort") && m.includes("not supported")) {
16285
+ return { kind: "chat_tools_effort", message };
16286
+ }
16287
+ if (m.includes("between_tools") && m.includes("thinking")) return { kind: "thinking_off_between_tools", message };
16288
+ if (m.includes("thinking.type.enabled") && m.includes("not supported")) return { kind: "thinking_enabled_unsupported", message };
16289
+ if (m.includes("thinking.type.adaptive") && m.includes("not supported")) return { kind: "thinking_adaptive_unsupported", message };
16290
+ if (m.includes("thinking.type.disabled") && m.includes("not supported")) return { kind: "thinking_disabled_unsupported", message };
16291
+ const tt = new RegExp(`${Q}?(temperature|top_p|top_k)${Q}?\\s+may only be set to 1 when thinking is enabled`, "i").exec(message);
16292
+ if (tt) return { kind: "temperature_thinking", param: tt[1].toLowerCase(), message };
16293
+ const dep = new RegExp(`${Q}([\\w.]+)${Q}\\s+is deprecated for this model`, "i").exec(message);
16294
+ if (dep) return { kind: "unsupported_parameter", param: dep[1], message };
16295
+ const rename = new RegExp(`use ${Q}(max_completion_tokens|max_tokens)${Q} instead`, "i").exec(message);
16296
+ if (rename) return { kind: "max_tokens_rename", renameTo: rename[1].toLowerCase(), param: rename[1].toLowerCase() === "max_tokens" ? "max_completion_tokens" : "max_tokens", message };
16297
+ const val = new RegExp(`unsupported value:?\\s*${Q}?([\\w.]+)${Q}?\\s+does not support\\s+(${Q}[^'"\`]*${Q}|[^\\s]+)`, "i").exec(message);
16298
+ if (val) {
16299
+ const param = val[1];
16300
+ const value = val[2].replace(/^['"`]|['"`]$/g, "");
16301
+ if (m.includes("only the default") && m.includes("value is supported")) return { kind: "default_only", param, value, message };
16302
+ const sup = /supported values? (?:are|is):?\s*([^\n]*)/i.exec(message);
16303
+ return { kind: "unsupported_value", param, value, supportedValues: sup ? quotedList(sup[1]) : void 0, message };
16304
+ }
16305
+ if (m.includes("only the default") && m.includes("value is supported")) {
16306
+ return { kind: "default_only", param: errParam ?? "temperature", message };
16307
+ }
16308
+ const prm = new RegExp(`unsupported parameter:?\\s*${Q}?([\\w.]+)${Q}?`, "i").exec(message);
16309
+ if (prm) return { kind: "unsupported_parameter", param: prm[1], message };
16310
+ return void 0;
16311
+ }
16312
+ var normParam = (p) => p.toLowerCase().replace(/[-\s]/g, "_");
16313
+ var LADDER2 = new Set(MODEL_RULES.effortLadder);
16314
+ function patchFromParsedError(parsed, endpoint = "chat") {
16315
+ const param = parsed.param ? normParam(parsed.param) : "";
16316
+ switch (parsed.kind) {
16317
+ case "chat_tools_effort":
16318
+ return { patch: { chatTools: { reasoning: "force-none" } }, adjustment: "chat-tools:force-effort-none" };
16319
+ case "max_tokens_rename":
16320
+ return { patch: { maxTokensParam: parsed.renameTo }, adjustment: `${parsed.param}->${parsed.renameTo}` };
16321
+ case "thinking_enabled_unsupported":
16322
+ return { patch: { reasoning: { style: "adaptive" } }, adjustment: "thinking:adaptive" };
16323
+ case "thinking_adaptive_unsupported":
16324
+ return { patch: { reasoning: { style: "budget" } }, adjustment: "thinking:budget" };
16325
+ case "thinking_off_between_tools":
16326
+ return { patch: { reasoning: { off: "between_tools" } }, adjustment: "thinking-off:between_tools" };
16327
+ case "thinking_disabled_unsupported":
16328
+ return { patch: { reasoning: { off: null } }, adjustment: "thinking-off:none" };
16329
+ case "temperature_thinking":
16330
+ return { patch: { sampling: { temperature: "unsupported" } }, adjustment: "drop:temperature" };
16331
+ case "default_only":
16332
+ if (param === "temperature") return { patch: { sampling: { temperature: "default-only" } }, adjustment: "temperature:default-only" };
16333
+ return { patch: { dropParams: [parsed.param ?? param] }, adjustment: `drop:${parsed.param ?? param}` };
16334
+ case "unsupported_value": {
16335
+ if (/^(reasoning_effort|reasoning\.effort|effort|output_config\.effort)$/.test(param)) {
16336
+ const list = (parsed.supportedValues ?? []).map((v) => v.toLowerCase()).filter((v) => LADDER2.has(v));
16337
+ if (list.length === 0) return void 0;
16338
+ const reasoning = endpoint === "responses" ? { responsesEfforts: list } : { efforts: list };
16339
+ return { patch: { reasoning }, adjustment: `efforts:${list.join("|")}` };
16340
+ }
16341
+ return paramDropPatch(param, parsed);
16342
+ }
16343
+ case "unsupported_parameter":
16344
+ return paramDropPatch(param, parsed);
16345
+ }
16346
+ }
16347
+ function paramDropPatch(param, parsed) {
16348
+ if (!param) return void 0;
16349
+ const label = `drop:${parsed.param ?? param}`;
16350
+ switch (param) {
16351
+ case "temperature":
16352
+ return { patch: { sampling: { temperature: "unsupported" } }, adjustment: label };
16353
+ case "top_p":
16354
+ return { patch: { sampling: { topP: false } }, adjustment: label };
16355
+ case "top_k":
16356
+ return { patch: { sampling: { topK: false } }, adjustment: label };
16357
+ case "presence_penalty":
16358
+ case "frequency_penalty":
16359
+ return { patch: { sampling: { penalties: false } }, adjustment: label };
16360
+ case "logprobs":
16361
+ case "top_logprobs":
16362
+ return { patch: { sampling: { logprobs: false } }, adjustment: label };
16363
+ case "max_tokens":
16364
+ return { patch: { maxTokensParam: "max_completion_tokens" }, adjustment: "max_tokens->max_completion_tokens" };
16365
+ case "max_completion_tokens":
16366
+ return { patch: { maxTokensParam: "max_tokens" }, adjustment: "max_completion_tokens->max_tokens" };
16367
+ case "reasoning_effort":
16368
+ case "reasoning.effort":
16369
+ case "reasoning":
16370
+ return { patch: { reasoning: { style: "none", efforts: [], responsesEfforts: [] }, dropParams: [param] }, adjustment: label };
16371
+ default:
16372
+ return { patch: { dropParams: [parsed.param ?? param] }, adjustment: label };
16373
+ }
16374
+ }
16375
+ function codeFor(parsed) {
16376
+ if (!parsed) return "model_request_invalid";
16377
+ if (parsed.kind === "unsupported_value" || parsed.kind === "default_only") return "unsupported_value";
16378
+ if (parsed.kind === "unsupported_parameter" || parsed.kind === "max_tokens_rename" || parsed.kind === "temperature_thinking") return "unsupported_parameter";
16379
+ return "model_request_invalid";
16380
+ }
16381
+ function toModelRequestError(err, parsed, provider, model) {
16382
+ return new ModelRequestError({
16383
+ status: err.statusCode ?? 400,
16384
+ code: codeFor(parsed),
16385
+ param: parsed?.param,
16386
+ value: parsed?.value,
16387
+ supportedValues: parsed?.supportedValues,
16388
+ provider: err.provider || provider,
16389
+ model,
16390
+ message: err.message,
16391
+ responseBody: err.responseBody
16392
+ });
16393
+ }
16394
+ var SameRequest = class extends Error {
16395
+ };
16396
+ function withoutCallerParams(step, callerParams) {
16397
+ const drops = step.patch.dropParams;
16398
+ if (!callerParams?.length || !drops) return step;
16399
+ const mine = (p) => callerParams.includes(p.split(".")[0]);
16400
+ if (!drops.some(mine)) return step;
16401
+ const { dropParams: _ignored, ...rest } = step.patch;
16402
+ const kept = drops.filter((p) => !mine(p));
16403
+ const patch = kept.length ? { ...rest, dropParams: kept } : rest;
16404
+ return Object.keys(patch).length ? { ...step, patch } : void 0;
16405
+ }
16406
+ async function runWithModelAdjustments(opts) {
16407
+ let overlay = {};
16408
+ const steps = [];
16409
+ let previous;
16410
+ let lastError;
16411
+ let lastParsed;
16412
+ for (; ; ) {
16413
+ const guard = (body) => {
16414
+ let json;
16415
+ try {
16416
+ json = JSON.stringify(body);
16417
+ } catch {
16418
+ return;
16419
+ }
16420
+ if (previous !== void 0 && json === previous) throw new SameRequest();
16421
+ previous = json;
16422
+ };
16423
+ try {
16424
+ const result = await opts.run(overlay, guard);
16425
+ for (const step of steps) {
16426
+ const s = withoutCallerParams(step, opts.callerParams);
16427
+ if (!s) continue;
16428
+ rememberModelRulePatch(opts.provider, opts.model, s.patch, opts.scope);
16429
+ if (opts.onLearned) {
16430
+ try {
16431
+ opts.onLearned({ provider: opts.provider, model: opts.model, adjustment: s.adjustment, patch: s.patch, reason: s.reason });
16432
+ } catch {
16433
+ }
16434
+ }
16435
+ }
16436
+ return result;
16437
+ } catch (err) {
16438
+ if (err instanceof SameRequest) throw toModelRequestError(lastError, lastParsed, opts.provider, opts.model);
16439
+ if (!(err instanceof ProviderError) || err instanceof ModelRequestError || err.statusCode !== 400) throw err;
16440
+ const parsed = parseModelError(String(err.responseBody ?? err.message));
16441
+ const fix = parsed ? patchFromParsedError(parsed, opts.endpoint) : void 0;
16442
+ lastError = err;
16443
+ lastParsed = parsed;
16444
+ if (!fix || steps.length >= MAX_ADJUSTMENTS) throw toModelRequestError(err, parsed, opts.provider, opts.model);
16445
+ overlay = mergeRulePatch(overlay, fix.patch);
16446
+ steps.push({ ...fix, reason: parsed.message });
16447
+ }
16448
+ }
16449
+ }
16450
+ function asModelRequestError(err, provider, model) {
16451
+ if (!(err instanceof ProviderError) || err instanceof ModelRequestError || err.statusCode !== 400) return err;
16452
+ return toModelRequestError(err, parseModelError(String(err.responseBody ?? err.message)), provider, model);
16453
+ }
16454
+
15351
16455
  // src/providers/utils/media.ts
15352
16456
  var EXTENSION_MIME = {
15353
16457
  jpg: "image/jpeg",
@@ -15539,11 +16643,64 @@ function isObject2(value) {
15539
16643
  return typeof value === "object" && value !== null && !Array.isArray(value);
15540
16644
  }
15541
16645
 
16646
+ // src/providers/utils/embeddings.ts
16647
+ function chunkArray(items, size) {
16648
+ const n = Math.max(1, Math.floor(size));
16649
+ const out = [];
16650
+ for (let i = 0; i < items.length; i += n) out.push(items.slice(i, i + n));
16651
+ return out;
16652
+ }
16653
+ async function mapWithConcurrency(items, limit, fn, signal) {
16654
+ const results = new Array(items.length);
16655
+ let next = 0;
16656
+ let failure;
16657
+ let failed = false;
16658
+ const worker = async () => {
16659
+ while (!failed) {
16660
+ if (signal?.aborted) throw signal.reason ?? new Error("aborted");
16661
+ const i = next++;
16662
+ if (i >= items.length) return;
16663
+ try {
16664
+ results[i] = await fn(items[i], i);
16665
+ } catch (err) {
16666
+ failed = true;
16667
+ failure = err;
16668
+ return;
16669
+ }
16670
+ }
16671
+ };
16672
+ await Promise.all(Array.from({ length: Math.min(Math.max(1, limit), items.length) }, worker));
16673
+ if (failed) throw failure;
16674
+ return results;
16675
+ }
16676
+ function decodeBase64Vector(b64) {
16677
+ const buf = Buffer.from(b64, "base64");
16678
+ const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
16679
+ const out = new Array(Math.floor(buf.byteLength / 4));
16680
+ for (let i = 0; i < out.length; i++) out[i] = view.getFloat32(i * 4, true);
16681
+ return out;
16682
+ }
16683
+ function assertVectorCount(provider, vectors, expected) {
16684
+ if (vectors.length !== expected) {
16685
+ throw new ProviderError(
16686
+ `${provider} embeddings returned ${vectors.length} vectors for ${expected} inputs`,
16687
+ provider,
16688
+ 502
16689
+ );
16690
+ }
16691
+ }
16692
+ function requireEmbeddingModel(provider, model) {
16693
+ if (!model) throw new ProviderError(`${provider} embeddings require a model`, provider, 400);
16694
+ return model;
16695
+ }
16696
+
15542
16697
  // src/providers/openai.ts
15543
- var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
16698
+ var OpenAIProvider = class extends BaseProvider {
15544
16699
  constructor(config) {
15545
16700
  super();
15546
16701
  this.providerName = "openai";
16702
+ this.configureTransport(config);
16703
+ this.maxTokensParam = config.maxTokensParam ?? "auto";
15547
16704
  this.apiKey = config.apiKey;
15548
16705
  this.baseURL = (config.baseURL ?? "https://api.openai.com/v1").replace(/\/$/, "");
15549
16706
  this.defaultModel = config.defaultModel ?? "gpt-4o";
@@ -15551,10 +16708,14 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
15551
16708
  ...config.defaultHeaders,
15552
16709
  ...config.organization ? { "OpenAI-Organization": config.organization } : {}
15553
16710
  };
15554
- this.responsesApi = config.responsesApi ?? "auto";
15555
- const ownInstance = new.target === _OpenAIProvider;
15556
- this.responsesApiModels = ownInstance ? [...config.responsesApiModels ?? []] : [];
15557
- this.responsesStreaming = ownInstance && config.responsesStreaming === true;
16711
+ const legacy = config.responsesApi;
16712
+ const explicit = config.api === "chat" || config.api === "responses" ? config.api : void 0;
16713
+ this.responsesApi = explicit === "responses" ? "always" : explicit === "chat" ? "never" : legacy ?? (config._autoMeansChat ? "never" : "auto");
16714
+ this.apiExplicitChat = explicit === "chat" || explicit === void 0 && legacy === "never";
16715
+ this.apiExplicitResponses = this.responsesApi === "always";
16716
+ this.apiResponsesNative = explicit === "responses";
16717
+ this.responsesApiModels = [...config.responsesApiModels ?? []];
16718
+ this.responsesStreaming = config.responsesStreaming ?? this.apiResponsesNative;
15558
16719
  if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
15559
16720
  }
15560
16721
  /** True when the caller listed this request's model in `responsesApiModels`. */
@@ -15580,9 +16741,10 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
15580
16741
  * A model listed in `responsesApiModels` is the caller stating the answer
15581
16742
  * for that model alone; `never` still overrides it. */
15582
16743
  useResponsesApi(request) {
15583
- if (this.responsesApi === "never") return false;
15584
- if (this.responsesApi === "always") return true;
16744
+ if (this.apiExplicitChat) return false;
16745
+ if (this.apiExplicitResponses) return true;
15585
16746
  if (this.isResponsesApiModel(request)) return true;
16747
+ if (this.responsesApi !== "auto") return false;
15586
16748
  if (!request.reasoning) return false;
15587
16749
  return isReasoningModel(request.model || this.defaultModel);
15588
16750
  }
@@ -15590,14 +16752,13 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
15590
16752
  if (this.useResponsesApi(request)) {
15591
16753
  return this.completeResponses(request);
15592
16754
  }
15593
- const body = this.buildRequestBody(request, false);
15594
- const res = await this.doFetch(body, request.signal);
16755
+ const res = await this.fetchChat(request, false);
15595
16756
  const json = await res.json();
15596
16757
  return this.parseResponse(json);
15597
16758
  }
15598
16759
  async *completeStream(request) {
15599
16760
  if (this.useResponsesApi(request)) {
15600
- if (this.responsesStreaming && this.isResponsesApiModel(request)) {
16761
+ if (this.responsesStreaming && (this.apiResponsesNative || this.isResponsesApiModel(request))) {
15601
16762
  yield* this.streamResponses(request);
15602
16763
  return;
15603
16764
  }
@@ -15615,8 +16776,7 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
15615
16776
  };
15616
16777
  return;
15617
16778
  }
15618
- const body = this.buildRequestBody(request, true);
15619
- const res = await this.doFetch(body, request.signal);
16779
+ const res = await this.fetchChat(request, true);
15620
16780
  if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
15621
16781
  let id = "";
15622
16782
  let model = "";
@@ -15647,9 +16807,14 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
15647
16807
  delta: {},
15648
16808
  finishReason: mapFinishReason(choice.finish_reason)
15649
16809
  };
16810
+ if (typeof choice.finish_reason === "string") out.rawFinishReason = choice.finish_reason;
16811
+ const fields = pickProviderFields(chunk, delta, choice);
16812
+ if (fields) out.providerFields = fields;
15650
16813
  if (delta.content) {
15651
16814
  out.delta.content = delta.content;
15652
16815
  }
16816
+ const reasoningDelta = extractReasoningText(delta);
16817
+ if (reasoningDelta) out.delta.reasoning = { summary: reasoningDelta };
15653
16818
  if (delta.tool_calls) {
15654
16819
  const partials = [];
15655
16820
  for (const tc of delta.tool_calls) {
@@ -15661,7 +16826,7 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
15661
16826
  if (tc.id) buf.id = tc.id;
15662
16827
  if (tc.function?.name) buf.name = tc.function.name;
15663
16828
  if (tc.function?.arguments) buf.arguments += tc.function.arguments;
15664
- partials.push({ id: buf.id, name: buf.name || void 0, arguments: tc.function?.arguments });
16829
+ partials.push({ id: buf.id, name: buf.name || void 0, arguments: tc.function?.arguments, index: idx });
15665
16830
  }
15666
16831
  out.delta.toolCalls = partials;
15667
16832
  }
@@ -15669,22 +16834,115 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
15669
16834
  yield out;
15670
16835
  }
15671
16836
  }
16837
+ // ─── Embeddings ──────────────────────────────────────────────────────────
16838
+ /** POST /embeddings, batched (default 2048 inputs per request, the OpenAI cap). */
16839
+ async embed(request) {
16840
+ const model = requireEmbeddingModel(this.providerName, request.model);
16841
+ const batches = chunkArray(request.input, request.batchSize ?? 2048);
16842
+ const vectors = [];
16843
+ const raw = [];
16844
+ let inputTokens = 0;
16845
+ let totalTokens = 0;
16846
+ let responseModel = model;
16847
+ for (const batch of batches) {
16848
+ const body = { model, input: batch };
16849
+ if (request.dimensions != null) body.dimensions = request.dimensions;
16850
+ if (request.encodingFormat) body.encoding_format = request.encodingFormat;
16851
+ if (request.extra) Object.assign(body, request.extra);
16852
+ const res = await this.embeddingsFetch(body, request.signal);
16853
+ const json = await res.json();
16854
+ raw.push(json);
16855
+ const data = Array.isArray(json.data) ? [...json.data] : [];
16856
+ data.sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
16857
+ for (const d of data) {
16858
+ vectors.push(typeof d.embedding === "string" ? decodeBase64Vector(d.embedding) : d.embedding);
16859
+ }
16860
+ inputTokens += json.usage?.prompt_tokens ?? 0;
16861
+ totalTokens += json.usage?.total_tokens ?? json.usage?.prompt_tokens ?? 0;
16862
+ responseModel = json.model ?? responseModel;
16863
+ }
16864
+ assertVectorCount(this.providerName, vectors, request.input.length);
16865
+ return { model: responseModel, vectors, usage: { inputTokens, totalTokens }, raw };
16866
+ }
16867
+ async embeddingsFetch(body, signal) {
16868
+ const url = `${this.baseURL}/embeddings`;
16869
+ const headers = {
16870
+ "Content-Type": "application/json",
16871
+ Authorization: `Bearer ${this.apiKey}`,
16872
+ ...this.defaultHeaders
16873
+ };
16874
+ const payload = JSON.stringify(body);
16875
+ const res = await this.doFetchWithRetry(() => this.httpFetch(url, { method: "POST", headers, body: payload, signal }), signal);
16876
+ if (!res.ok) {
16877
+ const text = await res.text().catch(() => "");
16878
+ throw new ProviderError(`OpenAI embeddings API error ${res.status}: ${text}`, this.providerName, res.status, text);
16879
+ }
16880
+ return res;
16881
+ }
15672
16882
  // ─── Internals ───────────────────────────────────────────────────────────
15673
- buildRequestBody(request, stream) {
16883
+ /** Chat Completions call that corrects itself from the provider's own 400s (see models/adjust.ts). */
16884
+ fetchChat(request, stream) {
16885
+ const model = request.model || this.defaultModel;
16886
+ return runWithModelAdjustments({
16887
+ provider: this.providerName,
16888
+ model,
16889
+ endpoint: "chat",
16890
+ scope: this.baseURL,
16891
+ callerParams: request.extra ? Object.keys(request.extra) : void 0,
16892
+ onLearned: this.onModelRuleLearned,
16893
+ run: (overlay, guard) => {
16894
+ const body = this.buildRequestBody(request, stream, overlay);
16895
+ guard(body);
16896
+ return this.doFetch(body, request.signal);
16897
+ }
16898
+ });
16899
+ }
16900
+ /** Same for the Responses API. */
16901
+ fetchResponses(request, adaptExtras, stream = false) {
16902
+ const model = request.model || this.defaultModel;
16903
+ return runWithModelAdjustments({
16904
+ provider: this.providerName,
16905
+ model,
16906
+ endpoint: "responses",
16907
+ scope: this.baseURL,
16908
+ callerParams: request.extra ? Object.keys(request.extra) : void 0,
16909
+ onLearned: this.onModelRuleLearned,
16910
+ run: (overlay, guard) => {
16911
+ const body = this.buildResponsesBody(request, overlay);
16912
+ if (adaptExtras) adaptChatExtrasForResponses(body, request.extra);
16913
+ if (stream) body.stream = true;
16914
+ guard(body);
16915
+ return this.responsesFetch(body, request.signal);
16916
+ }
16917
+ });
16918
+ }
16919
+ buildRequestBody(request, stream, overlay) {
15674
16920
  const body = {
15675
16921
  model: request.model || this.defaultModel,
15676
16922
  messages: request.messages.map((m) => this.toOpenAIMessage(m)),
15677
16923
  stream
15678
16924
  };
15679
- if (stream) {
16925
+ if (stream && request.streamUsage !== false) {
15680
16926
  body.stream_options = { include_usage: true };
15681
16927
  }
15682
- if (request.temperature != null) body.temperature = request.temperature;
15683
- if (request.maxTokens != null) body.max_tokens = request.maxTokens;
15684
- if (request.topP != null) body.top_p = request.topP;
16928
+ const modelId = String(body.model);
16929
+ const rule = resolveModelRule({ provider: this.providerName, model: modelId, patch: overlay, scope: this.baseURL });
16930
+ if (request.temperature != null && allowsSampling(rule, "temperature", request.temperature)) body.temperature = request.temperature;
16931
+ if (request.maxTokens != null) {
16932
+ const param = this.maxTokensParam === "auto" ? rule.maxTokensParam : this.maxTokensParam;
16933
+ body[param] = request.maxTokens;
16934
+ }
16935
+ if (request.topP != null && allowsSampling(rule, "topP")) body.top_p = request.topP;
15685
16936
  if (request.stop) body.stop = request.stop;
16937
+ if (request.presencePenalty != null && allowsSampling(rule, "presencePenalty")) body.presence_penalty = request.presencePenalty;
16938
+ if (request.frequencyPenalty != null && allowsSampling(rule, "frequencyPenalty")) body.frequency_penalty = request.frequencyPenalty;
16939
+ if (request.seed != null) body.seed = request.seed;
16940
+ if (request.n != null) body.n = request.n;
16941
+ if (request.logprobs != null && allowsSampling(rule, "logprobs")) body.logprobs = request.logprobs;
16942
+ if (request.topLogprobs != null && allowsSampling(rule, "logprobs")) body.top_logprobs = request.topLogprobs;
15686
16943
  if (request.tools?.length) {
15687
16944
  body.tools = request.tools.map((t) => this.toOpenAITool(t));
16945
+ if (request.parallelToolCalls != null) body.parallel_tool_calls = request.parallelToolCalls;
15688
16946
  }
15689
16947
  if (request.toolChoice != null && request.tools?.length) {
15690
16948
  if (typeof request.toolChoice === "string") {
@@ -15710,14 +16968,17 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
15710
16968
  if (request.extra) {
15711
16969
  Object.assign(body, request.extra);
15712
16970
  }
15713
- applyOpenAIReasoning(body, request.reasoning, "legacy_effort");
16971
+ applyOpenAIReasoning(body, request.reasoning, "legacy_effort", modelId, rule);
16972
+ if (body.tools?.length && rule.chatTools.reasoning === "force-none" && rule.reasoning.style !== "none") {
16973
+ body.reasoning_effort = "none";
16974
+ }
16975
+ applyDropParams(body, rule);
15714
16976
  return body;
15715
16977
  }
15716
16978
  // ─── Responses API (reasoning models) ──────────────────────────────────────
15717
16979
  async completeResponses(request) {
15718
- const body = this.buildResponsesBody(request);
15719
- if (this.isResponsesApiModel(request)) adaptChatExtrasForResponses(body, request.extra);
15720
- const res = await this.responsesFetch(body, request.signal);
16980
+ const adapt = this.apiResponsesNative || this.isResponsesApiModel(request);
16981
+ const res = await this.fetchResponses(request, adapt);
15721
16982
  const json = await res.json();
15722
16983
  return this.parseResponsesResponse(json, request.model || this.defaultModel);
15723
16984
  }
@@ -15730,15 +16991,13 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
15730
16991
  * reads it). */
15731
16992
  async *streamResponses(request) {
15732
16993
  const modelId = request.model || this.defaultModel;
15733
- const body = this.buildResponsesBody(request);
15734
- adaptChatExtrasForResponses(body, request.extra);
15735
- body.stream = true;
15736
- const res = await this.responsesFetch(body, request.signal);
16994
+ const res = await this.fetchResponses(request, true, true);
15737
16995
  if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
15738
16996
  let id = "";
15739
16997
  let model = modelId;
15740
16998
  const calls = /* @__PURE__ */ new Map();
15741
16999
  let final;
17000
+ let streamedSummary = false;
15742
17001
  for await (const event of parseSSEStream(res.body, request.signal)) {
15743
17002
  if (event.data === "[DONE]") break;
15744
17003
  let data;
@@ -15756,19 +17015,28 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
15756
17015
  case "response.output_text.delta":
15757
17016
  if (data.delta) yield { id, model, delta: { content: data.delta } };
15758
17017
  break;
17018
+ case "response.reasoning_summary_part.added":
17019
+ if (streamedSummary) yield { id, model, delta: { reasoning: { summary: "\n\n" } } };
17020
+ break;
17021
+ case "response.reasoning_summary_text.delta":
17022
+ if (typeof data.delta === "string" && data.delta) {
17023
+ streamedSummary = true;
17024
+ yield { id, model, delta: { reasoning: { summary: data.delta } } };
17025
+ }
17026
+ break;
15759
17027
  case "response.output_item.added": {
15760
17028
  const item = data.item;
15761
17029
  if (item?.type !== "function_call") break;
15762
- const call = { callId: item.call_id ?? item.id ?? "", name: item.name ?? "", arguments: item.arguments ?? "" };
17030
+ const call = { callId: item.call_id ?? item.id ?? "", name: item.name ?? "", arguments: item.arguments ?? "", index: calls.size };
15763
17031
  calls.set(item.id ?? call.callId, call);
15764
- yield { id, model, delta: { toolCalls: [{ id: call.callId, name: call.name, arguments: call.arguments }] } };
17032
+ yield { id, model, delta: { toolCalls: [{ id: call.callId, name: call.name, arguments: call.arguments, index: call.index }] } };
15765
17033
  break;
15766
17034
  }
15767
17035
  case "response.function_call_arguments.delta": {
15768
17036
  const call = calls.get(data.item_id);
15769
17037
  if (!call || !data.delta) break;
15770
17038
  call.arguments += data.delta;
15771
- yield { id, model, delta: { toolCalls: [{ id: call.callId, arguments: data.delta }] } };
17039
+ yield { id, model, delta: { toolCalls: [{ id: call.callId, arguments: data.delta, index: call.index }] } };
15772
17040
  break;
15773
17041
  }
15774
17042
  case "response.output_item.done": {
@@ -15777,13 +17045,13 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
15777
17045
  const full = typeof item.arguments === "string" ? item.arguments : "";
15778
17046
  const call = calls.get(item.id ?? item.call_id);
15779
17047
  if (!call) {
15780
- const added = { callId: item.call_id ?? item.id ?? "", name: item.name ?? "", arguments: full };
17048
+ const added = { callId: item.call_id ?? item.id ?? "", name: item.name ?? "", arguments: full, index: calls.size };
15781
17049
  calls.set(item.id ?? added.callId, added);
15782
- yield { id, model, delta: { toolCalls: [{ id: added.callId, name: added.name, arguments: full }] } };
17050
+ yield { id, model, delta: { toolCalls: [{ id: added.callId, name: added.name, arguments: full, index: added.index }] } };
15783
17051
  } else if (full.length > call.arguments.length && full.startsWith(call.arguments)) {
15784
17052
  const rest = full.slice(call.arguments.length);
15785
17053
  call.arguments = full;
15786
- yield { id, model, delta: { toolCalls: [{ id: call.callId, arguments: rest }] } };
17054
+ yield { id, model, delta: { toolCalls: [{ id: call.callId, arguments: rest, index: call.index }] } };
15787
17055
  }
15788
17056
  break;
15789
17057
  }
@@ -15806,18 +17074,20 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
15806
17074
  yield {
15807
17075
  id: final?.id || id,
15808
17076
  model: final?.model || model,
15809
- delta: final?.reasoning ? { reasoning: final.reasoning } : {},
17077
+ // Summary text already went out as deltas; do not repeat it.
17078
+ delta: final?.reasoning && !streamedSummary ? { reasoning: final.reasoning } : {},
15810
17079
  usage: final?.usage,
15811
17080
  finishReason: final?.finishReason ?? (calls.size > 0 ? "tool_calls" : "stop")
15812
17081
  };
15813
17082
  }
15814
- buildResponsesBody(request) {
17083
+ buildResponsesBody(request, overlay) {
15815
17084
  const body = {
15816
17085
  model: request.model || this.defaultModel,
15817
17086
  input: request.messages.map((m) => this.toResponsesInput(m))
15818
17087
  };
15819
17088
  if (request.maxTokens != null) body.max_output_tokens = request.maxTokens;
15820
- if (request.topP != null) body.top_p = request.topP;
17089
+ const rule = resolveModelRule({ provider: this.providerName, model: String(body.model), patch: overlay, scope: this.baseURL });
17090
+ if (request.topP != null && allowsSampling(rule, "topP")) body.top_p = request.topP;
15821
17091
  if (request.tools?.length) {
15822
17092
  body.tools = request.tools.map((t) => ({
15823
17093
  type: "function",
@@ -15849,7 +17119,8 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
15849
17119
  }
15850
17120
  }
15851
17121
  if (request.extra) Object.assign(body, request.extra);
15852
- applyOpenAIReasoning(body, request.reasoning, "responses");
17122
+ applyOpenAIReasoning(body, request.reasoning, "responses", String(body.model), rule);
17123
+ applyDropParams(body, rule);
15853
17124
  return body;
15854
17125
  }
15855
17126
  /** Maps a unified message to a Responses API `input` item. */
@@ -15916,7 +17187,7 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
15916
17187
  ...this.defaultHeaders
15917
17188
  };
15918
17189
  const payload = JSON.stringify(body);
15919
- const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload, signal }), signal);
17190
+ const res = await this.doFetchWithRetry(() => this.httpFetch(url, { method: "POST", headers, body: payload, signal }), signal);
15920
17191
  if (!res.ok) {
15921
17192
  const text = await res.text().catch(() => "");
15922
17193
  throw new ProviderError(
@@ -16045,7 +17316,7 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
16045
17316
  ...this.defaultHeaders
16046
17317
  };
16047
17318
  const payload = JSON.stringify(body);
16048
- const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload, signal }), signal);
17319
+ const res = await this.doFetchWithRetry(() => this.httpFetch(url, { method: "POST", headers, body: payload, signal }), signal);
16049
17320
  if (!res.ok) {
16050
17321
  const text = await res.text().catch(() => "");
16051
17322
  throw new ProviderError(
@@ -16065,6 +17336,8 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
16065
17336
  name: tc.function?.name ?? "",
16066
17337
  arguments: tc.function?.arguments ?? "{}"
16067
17338
  }));
17339
+ const reasoningText = extractReasoningText(message);
17340
+ const providerFields = pickProviderFields(json, message, choice);
16068
17341
  return {
16069
17342
  id: json.id ?? "",
16070
17343
  model: json.model ?? "",
@@ -16072,6 +17345,9 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
16072
17345
  toolCalls,
16073
17346
  usage: this.extractUsage(json.usage),
16074
17347
  finishReason: mapFinishReason(choice?.finish_reason),
17348
+ ...typeof choice?.finish_reason === "string" ? { rawFinishReason: choice.finish_reason } : {},
17349
+ ...providerFields ? { providerFields } : {},
17350
+ ...reasoningText ? { reasoning: { summary: reasoningText } } : {},
16075
17351
  raw: json
16076
17352
  };
16077
17353
  }
@@ -16090,10 +17366,27 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
16090
17366
  };
16091
17367
  }
16092
17368
  };
17369
+ function extractReasoningText(src) {
17370
+ if (!src || typeof src !== "object") return void 0;
17371
+ for (const key of ["reasoning_content", "reasoning"]) {
17372
+ const v = src[key];
17373
+ if (typeof v === "string" && v.length > 0) return v;
17374
+ }
17375
+ return void 0;
17376
+ }
17377
+ function pickProviderFields(top, message, choice) {
17378
+ const out = {};
17379
+ if (top?.system_fingerprint != null) out.system_fingerprint = top.system_fingerprint;
17380
+ if (top?.service_tier != null) out.service_tier = top.service_tier;
17381
+ if (message?.annotations != null) out.annotations = message.annotations;
17382
+ if (message?.refusal != null) out.refusal = message.refusal;
17383
+ if (choice?.logprobs != null) out.logprobs = choice.logprobs;
17384
+ return Object.keys(out).length > 0 ? out : void 0;
17385
+ }
16093
17386
  function isReasoningModel(model) {
16094
17387
  if (!model) return false;
16095
- const m = model.toLowerCase();
16096
- return /(^|[/_-])o[0-9]/.test(m) || m.startsWith("o1") || m.startsWith("o3") || m.startsWith("o4") || m.includes("gpt-5") || m.includes("gpt5");
17388
+ const rule = resolveModelRule({ provider: "openai", model });
17389
+ return !rule.isDefault && rule.reasoning.style === "effort" && rule.sampling.temperature !== "any";
16097
17390
  }
16098
17391
  function adaptChatExtrasForResponses(body, extra) {
16099
17392
  const native = extra ?? {};
@@ -16166,36 +17459,80 @@ function mapFinishReason(reason) {
16166
17459
  }
16167
17460
  }
16168
17461
 
17462
+ // src/providers/utils/toolChoice.ts
17463
+ function supportsForcedToolChoice(model) {
17464
+ if (typeof model !== "string") return true;
17465
+ const id = model.toLowerCase();
17466
+ const at = id.indexOf("claude-");
17467
+ if (at < 0) return true;
17468
+ const toks = id.slice(at + 7).split("-");
17469
+ let family = false;
17470
+ for (const tok of toks) {
17471
+ if (tok === "sonnet" || tok === "opus") {
17472
+ family = true;
17473
+ continue;
17474
+ }
17475
+ const m = /^(\d+)(?:@|:|$)/.exec(tok);
17476
+ if (m) {
17477
+ if (m[1].length > 2) continue;
17478
+ if (Number(m[1]) < 5) return true;
17479
+ if (family) return false;
17480
+ return !toks.some((t) => t === "sonnet" || t === "opus");
17481
+ }
17482
+ }
17483
+ return true;
17484
+ }
17485
+ function forcedToolChoiceRejected(text) {
17486
+ const t = text.toLowerCase();
17487
+ return t.indexOf("tool_choice") >= 0 && t.indexOf("not supported for this model") >= 0;
17488
+ }
17489
+
16169
17490
  // src/providers/anthropic.ts
17491
+ var DEFAULT_MAX_TOKENS = 4096;
17492
+ function normalizeExplicitThinking(body) {
17493
+ const t = body.thinking;
17494
+ if (t == null) {
17495
+ delete body.thinking;
17496
+ return;
17497
+ }
17498
+ if (t.type !== "enabled") return;
17499
+ const budget = typeof t.budget_tokens === "number" ? t.budget_tokens : 0;
17500
+ if (budget > 0 && (typeof body.max_tokens !== "number" || body.max_tokens <= budget)) {
17501
+ body.max_tokens = budget + 1024;
17502
+ }
17503
+ for (const k of ["temperature", "top_p", "top_k"]) delete body[k];
17504
+ }
16170
17505
  var AnthropicProvider = class extends BaseProvider {
16171
17506
  constructor(config) {
16172
17507
  super();
16173
17508
  this.providerName = "anthropic";
17509
+ this.configureTransport(config);
16174
17510
  this.apiKey = config.apiKey;
16175
17511
  this.baseURL = (config.baseURL ?? "https://api.anthropic.com").replace(/\/$/, "");
16176
17512
  this.defaultModel = config.defaultModel ?? "claude-sonnet-4-20250514";
16177
17513
  this.defaultHeaders = config.defaultHeaders ?? {};
16178
17514
  this.anthropicVersion = config.anthropicVersion ?? "2023-06-01";
17515
+ this.thinkingMode = config.thinkingMode ?? "auto";
16179
17516
  this.promptCachingEnabled = config.prompt_caching?.enabled === true;
16180
17517
  if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
16181
17518
  }
16182
17519
  async complete(request) {
16183
- const body = this.buildRequestBody(request, false);
16184
- const res = await this.doFetch(body, request.signal);
17520
+ const res = await this.send(request, false);
16185
17521
  const json = await res.json();
16186
17522
  return this.parseResponse(json);
16187
17523
  }
16188
17524
  async *completeStream(request) {
16189
- const body = this.buildRequestBody(request, true);
16190
- const res = await this.doFetch(body, request.signal);
17525
+ const res = await this.send(request, true);
16191
17526
  if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
16192
17527
  let id = "";
16193
17528
  let model = "";
16194
17529
  let inputTokens = 0;
16195
17530
  let outputTokens = 0;
17531
+ let thinkingTokens = 0;
16196
17532
  let cacheReadInputTokens = 0;
16197
17533
  let cacheCreationInputTokens = 0;
16198
17534
  const currentToolCalls = /* @__PURE__ */ new Map();
17535
+ let toolOrdinal = 0;
16199
17536
  const reasoningBlocks = /* @__PURE__ */ new Map();
16200
17537
  for await (const event of parseSSEStream(res.body, request.signal)) {
16201
17538
  let data;
@@ -16224,8 +17561,11 @@ var AnthropicProvider = class extends BaseProvider {
16224
17561
  currentToolCalls.set(idx, {
16225
17562
  id: block.id ?? "",
16226
17563
  name: block.name ?? "",
16227
- arguments: ""
17564
+ arguments: "",
17565
+ ordinal: toolOrdinal++
16228
17566
  });
17567
+ const opened = currentToolCalls.get(idx);
17568
+ yield { id, model, delta: { toolCalls: [{ id: opened.id, name: opened.name, arguments: "", index: opened.ordinal }] } };
16229
17569
  } else if (block?.type === "thinking") {
16230
17570
  reasoningBlocks.set(idx, { type: "thinking", text: block.thinking ?? "", signature: block.signature });
16231
17571
  } else if (block?.type === "redacted_thinking") {
@@ -16263,7 +17603,7 @@ var AnthropicProvider = class extends BaseProvider {
16263
17603
  id,
16264
17604
  model,
16265
17605
  delta: {
16266
- toolCalls: [{ id: tc.id, name: tc.name, arguments: delta.partial_json }]
17606
+ toolCalls: [{ id: tc.id, name: tc.name, arguments: delta.partial_json, index: tc.ordinal }]
16267
17607
  }
16268
17608
  };
16269
17609
  }
@@ -16276,8 +17616,10 @@ var AnthropicProvider = class extends BaseProvider {
16276
17616
  const delta = data.delta;
16277
17617
  if (data.usage) {
16278
17618
  outputTokens = data.usage.output_tokens ?? outputTokens;
17619
+ thinkingTokens = data.usage.output_tokens_details?.thinking_tokens ?? thinkingTokens;
16279
17620
  }
16280
17621
  const finishReason = mapAnthropicStopReason(delta?.stop_reason);
17622
+ const rawFinishReason = typeof delta?.stop_reason === "string" ? delta.stop_reason : void 0;
16281
17623
  const usage = {
16282
17624
  inputTokens,
16283
17625
  outputTokens,
@@ -16285,7 +17627,7 @@ var AnthropicProvider = class extends BaseProvider {
16285
17627
  cachedInputTokens: cacheReadInputTokens,
16286
17628
  cachedWriteTokens: cacheCreationInputTokens,
16287
17629
  cachedOutputTokens: 0,
16288
- reasoningTokens: 0
17630
+ reasoningTokens: thinkingTokens
16289
17631
  };
16290
17632
  const blocks = [...reasoningBlocks.values()].filter(
16291
17633
  (b) => b.type === "thinking" && b.signature || b.type === "redacted_thinking" && b.data
@@ -16295,6 +17637,7 @@ var AnthropicProvider = class extends BaseProvider {
16295
17637
  model,
16296
17638
  delta: blocks.length > 0 ? { reasoning: { blocks } } : {},
16297
17639
  finishReason,
17640
+ ...rawFinishReason ? { rawFinishReason } : {},
16298
17641
  usage
16299
17642
  };
16300
17643
  break;
@@ -16309,12 +17652,12 @@ var AnthropicProvider = class extends BaseProvider {
16309
17652
  }
16310
17653
  }
16311
17654
  // ─── Internals ───────────────────────────────────────────────────────────
16312
- buildRequestBody(request, stream) {
17655
+ buildRequestBody(request, stream, overlay, downgradeToolChoice = false) {
16313
17656
  const { system, messages } = this.splitSystemMessages(request.messages);
16314
17657
  const body = {
16315
17658
  model: request.model || this.defaultModel,
16316
17659
  messages: this.toAnthropicMessages(messages),
16317
- max_tokens: request.maxTokens ?? 4096,
17660
+ max_tokens: request.maxTokens ?? DEFAULT_MAX_TOKENS,
16318
17661
  stream
16319
17662
  };
16320
17663
  if (system) {
@@ -16324,6 +17667,7 @@ var AnthropicProvider = class extends BaseProvider {
16324
17667
  body.system = system;
16325
17668
  }
16326
17669
  }
17670
+ const rule = resolveModelRule({ provider: this.providerName, model: String(body.model), patch: overlay });
16327
17671
  if (request.temperature != null) body.temperature = request.temperature;
16328
17672
  if (request.topP != null) body.top_p = request.topP;
16329
17673
  if (request.stop) body.stop_sequences = request.stop;
@@ -16335,18 +17679,29 @@ var AnthropicProvider = class extends BaseProvider {
16335
17679
  body.tools = tools;
16336
17680
  }
16337
17681
  if (request.toolChoice != null) {
17682
+ const forceOk = !downgradeToolChoice && supportsForcedToolChoice(body.model);
16338
17683
  if (request.toolChoice === "auto") {
16339
17684
  body.tool_choice = { type: "auto" };
16340
17685
  } else if (request.toolChoice === "required") {
16341
- body.tool_choice = { type: "any" };
17686
+ body.tool_choice = forceOk ? { type: "any" } : { type: "auto" };
16342
17687
  } else if (request.toolChoice === "none") ; else {
16343
- body.tool_choice = { type: "tool", name: request.toolChoice.name };
17688
+ body.tool_choice = forceOk ? { type: "tool", name: request.toolChoice.name } : { type: "auto" };
16344
17689
  }
16345
17690
  }
16346
17691
  if (request.extra) {
16347
17692
  Object.assign(body, request.extra);
16348
17693
  }
16349
- applyAnthropicReasoning(body, request.reasoning);
17694
+ const explicitThinking = request.extra && typeof request.extra === "object" && "thinking" in request.extra;
17695
+ if (explicitThinking) {
17696
+ normalizeExplicitThinking(body);
17697
+ enforceAnthropicSampling(body, rule, body.thinking?.type === "enabled" || body.thinking?.type === "adaptive");
17698
+ } else {
17699
+ applyAnthropicReasoning(body, request.reasoning, { model: body.model, mode: this.thinkingMode, rule });
17700
+ }
17701
+ applyDropParams(body, rule);
17702
+ if (typeof body.max_tokens !== "number" || !(body.max_tokens > 0)) {
17703
+ body.max_tokens = DEFAULT_MAX_TOKENS;
17704
+ }
16350
17705
  return body;
16351
17706
  }
16352
17707
  splitSystemMessages(messages) {
@@ -16477,6 +17832,31 @@ var AnthropicProvider = class extends BaseProvider {
16477
17832
  input_schema: t.parameters
16478
17833
  };
16479
17834
  }
17835
+ /** Builds and sends the request; retries once with the other thinking form
17836
+ * when the upstream rejects the one we picked. */
17837
+ send(request, stream) {
17838
+ let downgrade = false;
17839
+ return runWithModelAdjustments({
17840
+ provider: this.providerName,
17841
+ model: request.model || this.defaultModel,
17842
+ endpoint: "messages",
17843
+ callerParams: request.extra ? Object.keys(request.extra) : void 0,
17844
+ onLearned: this.onModelRuleLearned,
17845
+ run: async (overlay, guard) => {
17846
+ for (; ; ) {
17847
+ const body = this.buildRequestBody(request, stream, overlay, downgrade);
17848
+ guard(body);
17849
+ try {
17850
+ return await this.doFetch(body, request.signal);
17851
+ } catch (err) {
17852
+ const rejected = err instanceof ProviderError && err.statusCode === 400 && !downgrade && body.tool_choice && body.tool_choice.type !== "auto" && forcedToolChoiceRejected(String(err.responseBody ?? err.message));
17853
+ if (!rejected) throw err;
17854
+ downgrade = true;
17855
+ }
17856
+ }
17857
+ }
17858
+ });
17859
+ }
16480
17860
  async doFetch(body, signal) {
16481
17861
  const url = `${this.baseURL}/v1/messages`;
16482
17862
  const headers = {
@@ -16486,7 +17866,7 @@ var AnthropicProvider = class extends BaseProvider {
16486
17866
  ...this.defaultHeaders
16487
17867
  };
16488
17868
  const payload = JSON.stringify(body);
16489
- const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload, signal }), signal);
17869
+ const res = await this.doFetchWithRetry(() => this.httpFetch(url, { method: "POST", headers, body: payload, signal }), signal);
16490
17870
  if (!res.ok) {
16491
17871
  const text = await res.text().catch(() => "");
16492
17872
  throw new ProviderError(
@@ -16531,10 +17911,9 @@ var AnthropicProvider = class extends BaseProvider {
16531
17911
  cachedInputTokens: usage.cache_read_input_tokens ?? 0,
16532
17912
  cachedWriteTokens: usage.cache_creation_input_tokens ?? 0,
16533
17913
  cachedOutputTokens: 0,
16534
- // Anthropic bills thinking tokens inside `output_tokens` and does not
16535
- // expose a separate count, so reasoningTokens stays 0 here (cost is still
16536
- // captured via outputTokens). See docs for the limitation.
16537
- reasoningTokens: 0
17914
+ // Thinking tokens are billed inside `output_tokens`; newer models also
17915
+ // report the split as `output_tokens_details.thinking_tokens`.
17916
+ reasoningTokens: usage.output_tokens_details?.thinking_tokens ?? 0
16538
17917
  };
16539
17918
  return {
16540
17919
  id: json.id ?? "",
@@ -16543,6 +17922,7 @@ var AnthropicProvider = class extends BaseProvider {
16543
17922
  toolCalls,
16544
17923
  usage: tokenUsage,
16545
17924
  finishReason: mapAnthropicStopReason(json.stop_reason),
17925
+ ...typeof json.stop_reason === "string" ? { rawFinishReason: json.stop_reason } : {},
16546
17926
  reasoning: reasoningBlocks.length > 0 ? { blocks: reasoningBlocks, summary: summaryParts.join("\n").trim() || void 0 } : void 0,
16547
17927
  raw: json
16548
17928
  };
@@ -16588,7 +17968,16 @@ var AzureProvider = class extends OpenAIProvider {
16588
17968
  provider: "openai",
16589
17969
  apiKey: config.apiKey,
16590
17970
  defaultModel: config.defaultModel ?? config.deploymentName ?? "gpt-4o",
16591
- defaultHeaders: config.defaultHeaders
17971
+ defaultHeaders: config.defaultHeaders,
17972
+ retry: config.retry,
17973
+ fetch: config.fetch,
17974
+ timeoutMs: config.timeoutMs,
17975
+ onModelRuleLearned: config.onModelRuleLearned,
17976
+ maxTokensParam: config.maxTokensParam,
17977
+ api: config.api,
17978
+ responsesApi: config.responsesApi,
17979
+ responsesApiModels: config.responsesApiModels,
17980
+ responsesStreaming: config.responsesStreaming
16592
17981
  });
16593
17982
  this.providerName = "azure";
16594
17983
  this.endpoint = config.endpoint.replace(/\/$/, "");
@@ -16603,16 +17992,17 @@ var AzureProvider = class extends OpenAIProvider {
16603
17992
  }
16604
17993
  const url = `${this.endpoint}/openai/deployments/${deployment}/chat/completions?api-version=${this.apiVersion}`;
16605
17994
  const { model: _model, ...bodyWithoutModel } = body;
16606
- const res = await fetch(url, {
17995
+ const payload = JSON.stringify(bodyWithoutModel);
17996
+ const res = await this.doFetchWithRetry(() => this.httpFetch(url, {
16607
17997
  method: "POST",
16608
17998
  headers: {
16609
17999
  "Content-Type": "application/json",
16610
18000
  "api-key": this.azureApiKey,
16611
18001
  ...this.defaultHeaders
16612
18002
  },
16613
- body: JSON.stringify(bodyWithoutModel),
18003
+ body: payload,
16614
18004
  signal
16615
- });
18005
+ }), signal);
16616
18006
  if (!res.ok) {
16617
18007
  const text = await res.text().catch(() => "");
16618
18008
  throw new ProviderError(
@@ -16624,6 +18014,32 @@ var AzureProvider = class extends OpenAIProvider {
16624
18014
  }
16625
18015
  return res;
16626
18016
  }
18017
+ /** Azure embeddings: the deployment named by the request's model (falling back
18018
+ * to the configured deployment) in the path, api-key auth. */
18019
+ async embeddingsFetch(body, signal) {
18020
+ const deployment = body.model || this.deploymentName;
18021
+ if (!deployment) {
18022
+ throw new ProviderError("Azure embeddings require a deployment name or model", this.providerName, 400);
18023
+ }
18024
+ const url = `${this.endpoint}/openai/deployments/${deployment}/embeddings?api-version=${this.apiVersion}`;
18025
+ const { model: _model, ...bodyWithoutModel } = body;
18026
+ const payload = JSON.stringify(bodyWithoutModel);
18027
+ const res = await this.doFetchWithRetry(() => this.httpFetch(url, {
18028
+ method: "POST",
18029
+ headers: {
18030
+ "Content-Type": "application/json",
18031
+ "api-key": this.azureApiKey,
18032
+ ...this.defaultHeaders
18033
+ },
18034
+ body: payload,
18035
+ signal
18036
+ }), signal);
18037
+ if (!res.ok) {
18038
+ const text = await res.text().catch(() => "");
18039
+ throw new ProviderError(`Azure OpenAI embeddings API error ${res.status}: ${text}`, this.providerName, res.status, text);
18040
+ }
18041
+ return res;
18042
+ }
16627
18043
  /** Azure exposes the Responses API at /openai/responses with api-key auth.
16628
18044
  * Reasoning summaries require a preview api-version; callers can override via
16629
18045
  * the `apiVersion` config. */
@@ -16635,7 +18051,7 @@ var AzureProvider = class extends OpenAIProvider {
16635
18051
  }
16636
18052
  const url = `${this.endpoint}/openai/responses?api-version=${this.apiVersion}`;
16637
18053
  const payload = JSON.stringify({ ...body, model: deployment });
16638
- const res = await fetch(url, {
18054
+ const res = await this.doFetchWithRetry(() => this.httpFetch(url, {
16639
18055
  method: "POST",
16640
18056
  headers: {
16641
18057
  "Content-Type": "application/json",
@@ -16644,7 +18060,7 @@ var AzureProvider = class extends OpenAIProvider {
16644
18060
  },
16645
18061
  body: payload,
16646
18062
  signal
16647
- });
18063
+ }), signal);
16648
18064
  if (!res.ok) {
16649
18065
  const text = await res.text().catch(() => "");
16650
18066
  throw new ProviderError(
@@ -16680,20 +18096,156 @@ var OpenAICompatibleProvider = class extends OpenAIProvider {
16680
18096
  apiKey: config.apiKey,
16681
18097
  baseURL: config.baseURL,
16682
18098
  defaultModel: config.defaultModel,
16683
- defaultHeaders: config.defaultHeaders
18099
+ defaultHeaders: config.defaultHeaders,
18100
+ organization: config.organization,
18101
+ retry: config.retry,
18102
+ fetch: config.fetch,
18103
+ timeoutMs: config.timeoutMs,
18104
+ onModelRuleLearned: config.onModelRuleLearned,
18105
+ maxTokensParam: config.maxTokensParam,
18106
+ api: config.api,
18107
+ // Unlike OpenAI / Azure, "auto" on a compatible server means Chat
18108
+ // Completions (the 0.11 default): the model name is the operator's.
18109
+ // `responsesApiModels` still applies; `responsesApi: "auto"` opts in.
18110
+ _autoMeansChat: true,
18111
+ responsesApi: config.responsesApi,
18112
+ responsesApiModels: config.responsesApiModels,
18113
+ responsesStreaming: config.responsesStreaming
16684
18114
  });
16685
18115
  this.providerName = "openai-compatible";
16686
18116
  }
16687
18117
  };
16688
18118
 
18119
+ // src/providers/utils/eventStream.ts
18120
+ var EventStreamError = class extends Error {
18121
+ constructor(message) {
18122
+ super(message);
18123
+ this.name = "EventStreamError";
18124
+ }
18125
+ };
18126
+ var CRC_TABLE = (() => {
18127
+ const table = new Uint32Array(256);
18128
+ for (let n = 0; n < 256; n++) {
18129
+ let c = n;
18130
+ for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
18131
+ table[n] = c >>> 0;
18132
+ }
18133
+ return table;
18134
+ })();
18135
+ function crc32(bytes, start = 0, end = bytes.length) {
18136
+ let c = 4294967295;
18137
+ for (let i = start; i < end; i++) c = CRC_TABLE[(c ^ bytes[i]) & 255] ^ c >>> 8;
18138
+ return (c ^ 4294967295) >>> 0;
18139
+ }
18140
+ function decodeFrame(frame) {
18141
+ const view = new DataView(frame.buffer, frame.byteOffset, frame.byteLength);
18142
+ const total = view.getUint32(0);
18143
+ const headersLen = view.getUint32(4);
18144
+ if (total !== frame.byteLength) throw new EventStreamError("event-stream frame length mismatch");
18145
+ if (crc32(frame, 0, 8) !== view.getUint32(8)) throw new EventStreamError("event-stream prelude CRC mismatch");
18146
+ if (crc32(frame, 0, total - 4) !== view.getUint32(total - 4)) throw new EventStreamError("event-stream message CRC mismatch");
18147
+ if (12 + headersLen > total - 4) throw new EventStreamError("event-stream headers overflow frame");
18148
+ const headers = {};
18149
+ const td = new TextDecoder();
18150
+ let o = 12;
18151
+ const headersEnd = 12 + headersLen;
18152
+ while (o < headersEnd) {
18153
+ const nameLen = frame[o++];
18154
+ const name = td.decode(frame.subarray(o, o + nameLen));
18155
+ o += nameLen;
18156
+ const type = frame[o++];
18157
+ switch (type) {
18158
+ case 0:
18159
+ headers[name] = true;
18160
+ break;
18161
+ case 1:
18162
+ headers[name] = false;
18163
+ break;
18164
+ case 2:
18165
+ headers[name] = view.getInt8(o);
18166
+ o += 1;
18167
+ break;
18168
+ case 3:
18169
+ headers[name] = view.getInt16(o);
18170
+ o += 2;
18171
+ break;
18172
+ case 4:
18173
+ headers[name] = view.getInt32(o);
18174
+ o += 4;
18175
+ break;
18176
+ case 5:
18177
+ headers[name] = view.getBigInt64(o);
18178
+ o += 8;
18179
+ break;
18180
+ case 6: {
18181
+ const len = view.getUint16(o);
18182
+ o += 2;
18183
+ headers[name] = frame.slice(o, o + len);
18184
+ o += len;
18185
+ break;
18186
+ }
18187
+ case 7: {
18188
+ const len = view.getUint16(o);
18189
+ o += 2;
18190
+ headers[name] = td.decode(frame.subarray(o, o + len));
18191
+ o += len;
18192
+ break;
18193
+ }
18194
+ case 8:
18195
+ headers[name] = view.getBigInt64(o);
18196
+ o += 8;
18197
+ break;
18198
+ case 9:
18199
+ headers[name] = frame.slice(o, o + 16);
18200
+ o += 16;
18201
+ break;
18202
+ default:
18203
+ throw new EventStreamError(`unknown event-stream header type ${type}`);
18204
+ }
18205
+ }
18206
+ return { headers, payload: frame.slice(headersEnd, total - 4) };
18207
+ }
18208
+ async function* parseEventStream(body, signal) {
18209
+ const reader = body.getReader();
18210
+ let buf = new Uint8Array(0);
18211
+ try {
18212
+ while (true) {
18213
+ if (signal?.aborted) throw abortReason(signal);
18214
+ const { done, value } = await reader.read();
18215
+ if (done) break;
18216
+ if (!value?.length) continue;
18217
+ const merged = new Uint8Array(buf.length + value.length);
18218
+ merged.set(buf, 0);
18219
+ merged.set(value, buf.length);
18220
+ buf = merged;
18221
+ while (buf.length >= 12) {
18222
+ const total = new DataView(buf.buffer, buf.byteOffset, buf.byteLength).getUint32(0);
18223
+ if (total < 16) throw new EventStreamError("invalid event-stream frame length");
18224
+ if (buf.length < total) break;
18225
+ yield decodeFrame(buf.subarray(0, total));
18226
+ buf = buf.subarray(total);
18227
+ }
18228
+ }
18229
+ if (buf.length > 0) throw new EventStreamError("event-stream ended inside a frame");
18230
+ } finally {
18231
+ reader.cancel().catch(() => void 0);
18232
+ try {
18233
+ reader.releaseLock();
18234
+ } catch {
18235
+ }
18236
+ }
18237
+ }
18238
+
16689
18239
  // src/providers/bedrock.ts
16690
18240
  var BedrockProvider = class extends BaseProvider {
16691
18241
  constructor(config) {
16692
18242
  super();
16693
18243
  this.providerName = "bedrock";
18244
+ this.configureTransport(config);
16694
18245
  this.region = config.region;
16695
18246
  this.defaultModel = config.defaultModel ?? "anthropic.claude-sonnet-4-20250514-v1:0";
16696
18247
  this.defaultHeaders = config.defaultHeaders ?? {};
18248
+ this.thinkingMode = config.thinkingMode ?? "auto";
16697
18249
  this.promptCachingEnabled = config.prompt_caching?.enabled === true;
16698
18250
  if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
16699
18251
  this.credentials = {
@@ -16710,25 +18262,202 @@ var BedrockProvider = class extends BaseProvider {
16710
18262
  }
16711
18263
  async complete(request) {
16712
18264
  const modelId = request.model || this.defaultModel;
16713
- const body = this.buildConverseBody(request);
16714
- const json = await this.doFetch(modelId, body, request.signal);
16715
- return this.parseResponse(json, modelId);
18265
+ const res = await this.converseFetch(modelId, request, false);
18266
+ return this.parseResponse(await res.json(), modelId);
16716
18267
  }
18268
+ /**
18269
+ * Real streaming over ConverseStream. The response is an AWS event-stream
18270
+ * (binary frames); each frame carries one JSON event: messageStart,
18271
+ * contentBlockStart/Delta/Stop (text, toolUse, reasoningContent),
18272
+ * messageStop and, last, metadata (usage). Text, tool-call argument and
18273
+ * reasoning deltas are yielded as they arrive; one closing chunk carries the
18274
+ * finish reason, usage and the signed reasoning blocks.
18275
+ */
16717
18276
  async *completeStream(request) {
16718
- const response = await this.complete(request);
18277
+ const modelId = request.model || this.defaultModel;
18278
+ const res = await this.converseFetch(modelId, request, true);
18279
+ if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
18280
+ const id = res.headers.get("x-amzn-requestid") ?? "";
18281
+ const toolsByIndex = /* @__PURE__ */ new Map();
18282
+ const reasoningByIndex = /* @__PURE__ */ new Map();
18283
+ let finishReason;
18284
+ let rawFinishReason;
18285
+ let toolOrdinal = 0;
18286
+ let usage;
18287
+ for await (const msg of parseEventStream(res.body, request.signal)) {
18288
+ const messageType = String(msg.headers[":message-type"] ?? "event");
18289
+ const eventType = String(msg.headers[":event-type"] ?? msg.headers[":exception-type"] ?? "");
18290
+ let data = {};
18291
+ const text = new TextDecoder().decode(msg.payload);
18292
+ if (text) {
18293
+ try {
18294
+ data = JSON.parse(text);
18295
+ } catch {
18296
+ data = { message: text };
18297
+ }
18298
+ }
18299
+ if (messageType === "exception" || messageType === "error") {
18300
+ const code = String(msg.headers[":exception-type"] ?? msg.headers[":error-code"] ?? eventType);
18301
+ throw new ProviderError(
18302
+ `Bedrock stream error ${code}: ${data.message ?? text}`,
18303
+ this.providerName,
18304
+ bedrockExceptionStatus(code),
18305
+ data
18306
+ );
18307
+ }
18308
+ switch (eventType) {
18309
+ case "contentBlockStart": {
18310
+ const idx = data.contentBlockIndex ?? 0;
18311
+ const tu = data.start?.toolUse;
18312
+ if (tu) {
18313
+ const ordinal = toolOrdinal++;
18314
+ toolsByIndex.set(idx, { id: tu.toolUseId ?? "", name: tu.name ?? "", ordinal });
18315
+ yield { id, model: modelId, delta: { toolCalls: [{ id: tu.toolUseId, name: tu.name, arguments: "", index: ordinal }] } };
18316
+ }
18317
+ break;
18318
+ }
18319
+ case "contentBlockDelta": {
18320
+ const idx = data.contentBlockIndex ?? 0;
18321
+ const d = data.delta ?? {};
18322
+ if (typeof d.text === "string" && d.text) {
18323
+ yield { id, model: modelId, delta: { content: d.text } };
18324
+ } else if (d.toolUse) {
18325
+ const tc = toolsByIndex.get(idx);
18326
+ if (tc && typeof d.toolUse.input === "string" && d.toolUse.input) {
18327
+ yield { id, model: modelId, delta: { toolCalls: [{ id: tc.id, name: tc.name, arguments: d.toolUse.input, index: tc.ordinal }] } };
18328
+ }
18329
+ } else if (d.reasoningContent) {
18330
+ const rc = d.reasoningContent;
18331
+ const blk = reasoningByIndex.get(idx) ?? { type: "thinking", text: "" };
18332
+ if (typeof rc.text === "string" && rc.text) {
18333
+ blk.text = (blk.text ?? "") + rc.text;
18334
+ reasoningByIndex.set(idx, blk);
18335
+ yield { id, model: modelId, delta: { reasoning: { summary: rc.text } } };
18336
+ }
18337
+ if (typeof rc.signature === "string" && rc.signature) {
18338
+ blk.signature = (blk.signature ?? "") + rc.signature;
18339
+ reasoningByIndex.set(idx, blk);
18340
+ }
18341
+ if (rc.redactedContent) {
18342
+ reasoningByIndex.set(idx, { type: "redacted_thinking", data: rc.redactedContent });
18343
+ }
18344
+ }
18345
+ break;
18346
+ }
18347
+ case "messageStop":
18348
+ finishReason = mapBedrockStopReason(data.stopReason);
18349
+ if (typeof data.stopReason === "string") rawFinishReason = data.stopReason;
18350
+ break;
18351
+ case "metadata": {
18352
+ const u = data.usage ?? {};
18353
+ usage = {
18354
+ inputTokens: u.inputTokens ?? 0,
18355
+ outputTokens: u.outputTokens ?? 0,
18356
+ totalTokens: u.totalTokens ?? (u.inputTokens ?? 0) + (u.outputTokens ?? 0),
18357
+ cachedInputTokens: u.cacheReadInputTokens ?? u.cacheReadInputTokenCount ?? 0,
18358
+ cachedWriteTokens: u.cacheWriteInputTokens ?? u.cacheWriteInputTokenCount ?? 0,
18359
+ cachedOutputTokens: 0,
18360
+ reasoningTokens: 0
18361
+ };
18362
+ break;
18363
+ }
18364
+ }
18365
+ }
18366
+ const blocks = [...reasoningByIndex.values()].filter(
18367
+ (b) => b.type === "thinking" && b.signature || b.type === "redacted_thinking" && b.data
18368
+ );
16719
18369
  yield {
16720
- id: response.id,
16721
- model: response.model,
16722
- delta: {
16723
- content: response.content ?? void 0,
16724
- toolCalls: response.toolCalls.length > 0 ? response.toolCalls : void 0
16725
- },
16726
- usage: response.usage,
16727
- finishReason: response.finishReason
18370
+ id,
18371
+ model: modelId,
18372
+ delta: blocks.length > 0 ? { reasoning: { blocks } } : {},
18373
+ finishReason: finishReason ?? "stop",
18374
+ ...rawFinishReason ? { rawFinishReason } : {},
18375
+ usage
16728
18376
  };
16729
18377
  }
18378
+ // ─── Embeddings ──────────────────────────────────────────────────────────
18379
+ /**
18380
+ * InvokeModel embeddings. Supported families (by model id, inference-profile
18381
+ * prefixes such as `us.` allowed):
18382
+ * - Amazon Titan Text Embeddings (v1, v2): one text per call, `dimensions`
18383
+ * (v2: 256/512/1024) and `normalize` via `extra`.
18384
+ * - Cohere Embed (v3, v4): a batch of texts per call (default 96), `inputType`
18385
+ * maps to `input_type`, `dimensions` to `output_dimension` (v4).
18386
+ */
18387
+ async embed(request) {
18388
+ const model = requireEmbeddingModel(this.providerName, request.model);
18389
+ const id = model.toLowerCase();
18390
+ const raw = [];
18391
+ let inputTokens = 0;
18392
+ let vectors = [];
18393
+ if (id.includes("titan-embed")) {
18394
+ const results = await mapWithConcurrency(request.input, 4, async (text) => {
18395
+ const body = { inputText: text };
18396
+ if (request.dimensions != null && !id.includes("titan-embed-text-v1")) body.dimensions = request.dimensions;
18397
+ if (request.extra) Object.assign(body, request.extra);
18398
+ const res = await this.invokeModel(model, body, request.signal);
18399
+ const json = await res.json();
18400
+ return { json, tokens: json.inputTextTokenCount ?? Number(res.headers.get("x-amzn-bedrock-input-token-count") ?? 0) };
18401
+ }, request.signal);
18402
+ for (const r of results) {
18403
+ raw.push(r.json);
18404
+ inputTokens += r.tokens || 0;
18405
+ vectors.push(r.json.embedding ?? r.json.embeddingsByType?.float);
18406
+ }
18407
+ } else if (id.includes("cohere.embed")) {
18408
+ for (const batch of chunkArray(request.input, request.batchSize ?? 96)) {
18409
+ const body = {
18410
+ texts: batch,
18411
+ input_type: request.inputType ?? "search_document",
18412
+ embedding_types: ["float"]
18413
+ };
18414
+ if (request.dimensions != null) body.output_dimension = request.dimensions;
18415
+ if (request.extra) Object.assign(body, request.extra);
18416
+ const res = await this.invokeModel(model, body, request.signal);
18417
+ const json = await res.json();
18418
+ raw.push(json);
18419
+ const emb = Array.isArray(json.embeddings) ? json.embeddings : json.embeddings?.float;
18420
+ vectors.push(...emb ?? []);
18421
+ inputTokens += Number(res.headers.get("x-amzn-bedrock-input-token-count") ?? 0) || 0;
18422
+ }
18423
+ } else {
18424
+ throw new ProviderError(
18425
+ `Bedrock embeddings are supported for Amazon Titan and Cohere Embed models, not "${model}"`,
18426
+ this.providerName,
18427
+ 400
18428
+ );
18429
+ }
18430
+ assertVectorCount(this.providerName, vectors, request.input.length);
18431
+ return { model, vectors, usage: { inputTokens, totalTokens: inputTokens }, raw };
18432
+ }
18433
+ async invokeModel(modelId, body, signal) {
18434
+ const host = `bedrock-runtime.${this.region}.amazonaws.com`;
18435
+ const url = `https://${host}/model/${encodeURIComponent(modelId)}/invoke`;
18436
+ const bodyStr = JSON.stringify(body);
18437
+ const res = await this.doFetchWithRetry(() => {
18438
+ const headers = signRequest({
18439
+ method: "POST",
18440
+ url,
18441
+ headers: {
18442
+ "Content-Type": "application/json",
18443
+ Accept: "application/json",
18444
+ ...this.defaultHeaders
18445
+ },
18446
+ body: bodyStr,
18447
+ region: this.region,
18448
+ service: "bedrock",
18449
+ credentials: this.credentials
18450
+ });
18451
+ return this.httpFetch(url, { method: "POST", headers, body: bodyStr, signal });
18452
+ }, signal);
18453
+ if (!res.ok) {
18454
+ const text = await res.text().catch(() => "");
18455
+ throw new ProviderError(`Bedrock API error ${res.status}: ${text}`, this.providerName, res.status, text);
18456
+ }
18457
+ return res;
18458
+ }
16730
18459
  // ─── Internals ───────────────────────────────────────────────────────────
16731
- buildConverseBody(request) {
18460
+ buildConverseBody(request, downgradeToolChoice = false, overlay) {
16732
18461
  const { system, messages } = this.splitSystemMessages(request.messages);
16733
18462
  const body = {
16734
18463
  messages: this.toBedrockMessages(messages)
@@ -16752,8 +18481,9 @@ var BedrockProvider = class extends BaseProvider {
16752
18481
  body.toolConfig = {
16753
18482
  tools
16754
18483
  };
18484
+ const forceOk = !downgradeToolChoice && supportsForcedToolChoice(request.model || this.defaultModel);
16755
18485
  if (request.toolChoice != null) {
16756
- if (request.toolChoice === "auto") {
18486
+ if (request.toolChoice === "auto" || !forceOk && request.toolChoice !== "none") {
16757
18487
  body.toolConfig.toolChoice = { auto: {} };
16758
18488
  } else if (request.toolChoice === "required") {
16759
18489
  body.toolConfig.toolChoice = { any: {} };
@@ -16763,9 +18493,22 @@ var BedrockProvider = class extends BaseProvider {
16763
18493
  }
16764
18494
  }
16765
18495
  if (request.extra) {
16766
- Object.assign(body, request.extra);
16767
- }
16768
- applyBedrockReasoning(body, request.reasoning);
18496
+ const fields = { ...request.extra.additionalModelRequestFields ?? {} };
18497
+ const topLevel = { ...request.extra.__top ?? {} };
18498
+ for (const [key, value] of Object.entries(request.extra)) {
18499
+ if (key === "additionalModelRequestFields" || key === "__top") continue;
18500
+ if (CONVERSE_TOP_LEVEL_FIELDS.has(key)) body[key] = value;
18501
+ else fields[key] = value;
18502
+ }
18503
+ Object.assign(body, topLevel);
18504
+ if (Object.keys(fields).length > 0) body.additionalModelRequestFields = fields;
18505
+ }
18506
+ const rule = resolveModelRule({ provider: this.providerName, model: request.model || this.defaultModel, patch: overlay });
18507
+ applyBedrockReasoning(body, request.reasoning, { model: request.model || this.defaultModel, mode: this.thinkingMode, rule });
18508
+ if (body.inferenceConfig && rule.dropParams?.length) {
18509
+ for (const p of rule.dropParams) delete body.inferenceConfig[p === "top_p" ? "topP" : p === "max_tokens" ? "maxTokens" : p];
18510
+ }
18511
+ applyDropParams(body, rule);
16769
18512
  return body;
16770
18513
  }
16771
18514
  splitSystemMessages(messages) {
@@ -16888,9 +18631,35 @@ var BedrockProvider = class extends BaseProvider {
16888
18631
  }
16889
18632
  };
16890
18633
  }
16891
- async doFetch(modelId, body, signal) {
18634
+ /** Sends the Converse call; retries once with toolChoice auto when the
18635
+ * model rejects forced tool use. */
18636
+ converseFetch(modelId, request, stream) {
18637
+ let downgrade = false;
18638
+ return runWithModelAdjustments({
18639
+ provider: this.providerName,
18640
+ model: modelId,
18641
+ endpoint: "converse",
18642
+ callerParams: request.extra ? Object.keys(request.extra) : void 0,
18643
+ onLearned: this.onModelRuleLearned,
18644
+ run: async (overlay, guard) => {
18645
+ for (; ; ) {
18646
+ const body = this.buildConverseBody(request, downgrade, overlay);
18647
+ guard(body);
18648
+ try {
18649
+ return await this.doFetch(modelId, body, request.signal, stream);
18650
+ } catch (err) {
18651
+ const tc = body.toolConfig?.toolChoice;
18652
+ const rejected = err instanceof ProviderError && err.statusCode === 400 && !downgrade && !!tc && !tc.auto && forcedToolChoiceRejected(String(err.responseBody ?? err.message));
18653
+ if (!rejected) throw err;
18654
+ downgrade = true;
18655
+ }
18656
+ }
18657
+ }
18658
+ });
18659
+ }
18660
+ async doFetch(modelId, body, signal, stream) {
16892
18661
  const host = `bedrock-runtime.${this.region}.amazonaws.com`;
16893
- const url = `https://${host}/model/${encodeURIComponent(modelId)}/converse`;
18662
+ const url = `https://${host}/model/${encodeURIComponent(modelId)}/${stream ? "converse-stream" : "converse"}`;
16894
18663
  const bodyStr = JSON.stringify(body);
16895
18664
  const res = await this.doFetchWithRetry(() => {
16896
18665
  const headers = signRequest({
@@ -16898,7 +18667,7 @@ var BedrockProvider = class extends BaseProvider {
16898
18667
  url,
16899
18668
  headers: {
16900
18669
  "Content-Type": "application/json",
16901
- Accept: "application/json",
18670
+ Accept: stream ? "application/vnd.amazon.eventstream" : "application/json",
16902
18671
  ...this.defaultHeaders
16903
18672
  },
16904
18673
  body: bodyStr,
@@ -16906,7 +18675,7 @@ var BedrockProvider = class extends BaseProvider {
16906
18675
  service: "bedrock",
16907
18676
  credentials: this.credentials
16908
18677
  });
16909
- return fetch(url, { method: "POST", headers, body: bodyStr, signal });
18678
+ return this.httpFetch(url, { method: "POST", headers, body: bodyStr, signal });
16910
18679
  }, signal);
16911
18680
  if (!res.ok) {
16912
18681
  const text = await res.text().catch(() => "");
@@ -16917,7 +18686,7 @@ var BedrockProvider = class extends BaseProvider {
16917
18686
  text
16918
18687
  );
16919
18688
  }
16920
- return res.json();
18689
+ return res;
16921
18690
  }
16922
18691
  parseResponse(json, modelId) {
16923
18692
  const output = json.output?.message;
@@ -16953,8 +18722,8 @@ var BedrockProvider = class extends BaseProvider {
16953
18722
  inputTokens: usage.inputTokens ?? 0,
16954
18723
  outputTokens: usage.outputTokens ?? 0,
16955
18724
  totalTokens: usage.totalTokens ?? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0),
16956
- cachedInputTokens: usage.cacheReadInputTokenCount ?? 0,
16957
- cachedWriteTokens: usage.cacheWriteInputTokenCount ?? 0,
18725
+ cachedInputTokens: usage.cacheReadInputTokens ?? usage.cacheReadInputTokenCount ?? 0,
18726
+ cachedWriteTokens: usage.cacheWriteInputTokens ?? usage.cacheWriteInputTokenCount ?? 0,
16958
18727
  cachedOutputTokens: 0,
16959
18728
  // Bedrock bills thinking tokens inside outputTokens; no separate count.
16960
18729
  reasoningTokens: 0
@@ -16966,11 +18735,26 @@ var BedrockProvider = class extends BaseProvider {
16966
18735
  toolCalls,
16967
18736
  usage: tokenUsage,
16968
18737
  finishReason: mapBedrockStopReason(json.stopReason),
18738
+ ...typeof json.stopReason === "string" ? { rawFinishReason: json.stopReason } : {},
16969
18739
  reasoning: reasoningBlocks.length > 0 ? { blocks: reasoningBlocks, summary: summaryParts.join("\n").trim() || void 0 } : void 0,
16970
18740
  raw: json
16971
18741
  };
16972
18742
  }
16973
18743
  };
18744
+ var CONVERSE_TOP_LEVEL_FIELDS = /* @__PURE__ */ new Set([
18745
+ "messages",
18746
+ "system",
18747
+ "inferenceConfig",
18748
+ "toolConfig",
18749
+ "guardrailConfig",
18750
+ "additionalModelRequestFields",
18751
+ "additionalModelResponseFieldPaths",
18752
+ "promptVariables",
18753
+ "requestMetadata",
18754
+ "performanceConfig",
18755
+ "serviceTier",
18756
+ "outputConfig"
18757
+ ]);
16974
18758
  function appendBedrockReasoning(content, blocks) {
16975
18759
  if (!blocks?.length) return;
16976
18760
  for (const b of blocks) {
@@ -16985,6 +18769,23 @@ function appendBedrockReasoning(content, blocks) {
16985
18769
  }
16986
18770
  }
16987
18771
  }
18772
+ function bedrockExceptionStatus(code) {
18773
+ switch (code) {
18774
+ case "throttlingException":
18775
+ return 429;
18776
+ case "validationException":
18777
+ return 400;
18778
+ case "modelTimeoutException":
18779
+ return 408;
18780
+ case "serviceUnavailableException":
18781
+ return 503;
18782
+ case "internalServerException":
18783
+ case "modelStreamErrorException":
18784
+ return 500;
18785
+ default:
18786
+ return void 0;
18787
+ }
18788
+ }
16988
18789
  function mapBedrockStopReason(reason) {
16989
18790
  switch (reason) {
16990
18791
  case "end_turn":
@@ -16993,8 +18794,10 @@ function mapBedrockStopReason(reason) {
16993
18794
  case "tool_use":
16994
18795
  return "tool_calls";
16995
18796
  case "max_tokens":
18797
+ case "model_context_window_exceeded":
16996
18798
  return "length";
16997
18799
  case "content_filtered":
18800
+ case "guardrail_intervened":
16998
18801
  case "guardrail":
16999
18802
  return "content_filter";
17000
18803
  default:
@@ -17024,10 +18827,12 @@ var VertexProvider = class extends BaseProvider {
17024
18827
  super();
17025
18828
  this.providerName = "vertex";
17026
18829
  this.tokenExpiry = 0;
18830
+ this.configureTransport(config);
17027
18831
  this.projectId = config.projectId;
17028
18832
  this.location = config.location ?? "us-central1";
17029
18833
  this.defaultModel = config.defaultModel ?? "gemini-2.0-flash";
17030
18834
  this.defaultHeaders = config.defaultHeaders ?? {};
18835
+ if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
17031
18836
  if (config.accessToken) {
17032
18837
  this.accessToken = config.accessToken;
17033
18838
  this.tokenExpiry = Date.now() + 36e5;
@@ -17040,7 +18845,7 @@ var VertexProvider = class extends BaseProvider {
17040
18845
  const modelId = request.model || this.defaultModel;
17041
18846
  const body = this.buildGeminiBody(request);
17042
18847
  const url = this.buildUrl(modelId, false);
17043
- const res = await this.doFetch(url, body, request.signal);
18848
+ const res = await this.doFetch(url, body, request.signal, modelId);
17044
18849
  const json = await res.json();
17045
18850
  return this.parseResponse(json, modelId);
17046
18851
  }
@@ -17048,8 +18853,9 @@ var VertexProvider = class extends BaseProvider {
17048
18853
  const modelId = request.model || this.defaultModel;
17049
18854
  const body = this.buildGeminiBody(request);
17050
18855
  const url = this.buildUrl(modelId, true);
17051
- const res = await this.doFetch(url, body, request.signal);
18856
+ const res = await this.doFetch(url, body, request.signal, modelId);
17052
18857
  if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
18858
+ const counter = { next: 0 };
17053
18859
  const contentType = res.headers.get("content-type") ?? "";
17054
18860
  if (contentType.includes("text/event-stream")) {
17055
18861
  for await (const event of parseSSEStream(res.body, request.signal)) {
@@ -17060,7 +18866,7 @@ var VertexProvider = class extends BaseProvider {
17060
18866
  } catch {
17061
18867
  continue;
17062
18868
  }
17063
- yield this.parseStreamChunk(chunk, modelId);
18869
+ yield this.parseStreamChunk(chunk, modelId, counter);
17064
18870
  }
17065
18871
  } else {
17066
18872
  const reader = res.body.getReader();
@@ -17078,7 +18884,7 @@ var VertexProvider = class extends BaseProvider {
17078
18884
  if (!trimmed || trimmed === "[" || trimmed === "]") continue;
17079
18885
  try {
17080
18886
  const chunk = JSON.parse(trimmed);
17081
- yield this.parseStreamChunk(chunk, modelId);
18887
+ yield this.parseStreamChunk(chunk, modelId, counter);
17082
18888
  } catch {
17083
18889
  buffer = line + "\n" + buffer;
17084
18890
  break;
@@ -17089,7 +18895,7 @@ var VertexProvider = class extends BaseProvider {
17089
18895
  if (remaining && remaining !== "[" && remaining !== "]") {
17090
18896
  try {
17091
18897
  const chunk = JSON.parse(remaining);
17092
- yield this.parseStreamChunk(chunk, modelId);
18898
+ yield this.parseStreamChunk(chunk, modelId, counter);
17093
18899
  } catch {
17094
18900
  }
17095
18901
  }
@@ -17100,6 +18906,48 @@ var VertexProvider = class extends BaseProvider {
17100
18906
  }
17101
18907
  }
17102
18908
  // ─── Internals ───────────────────────────────────────────────────────────
18909
+ /**
18910
+ * Vertex `:predict` embeddings (text-embedding-00x, text-multilingual-embedding,
18911
+ * gemini-embedding-001). `inputType` maps to the task type; `dimensions` to
18912
+ * `outputDimensionality`. gemini-embedding takes one instance per request, the
18913
+ * text-embedding models up to `batchSize` (default 100).
18914
+ */
18915
+ async embed(request) {
18916
+ const model = requireEmbeddingModel(this.providerName, request.model);
18917
+ const perRequest = request.batchSize ?? (/gemini-embedding/i.test(model) ? 1 : 100);
18918
+ const url = `https://${this.location}-aiplatform.googleapis.com/v1/projects/${this.projectId}/locations/${this.location}/publishers/google/models/${model}:predict`;
18919
+ const taskType = request.inputType ? Object.prototype.hasOwnProperty.call(GEMINI_TASK_TYPES, request.inputType) ? GEMINI_TASK_TYPES[request.inputType] : request.inputType.toUpperCase() : void 0;
18920
+ const vectors = [];
18921
+ const raw = [];
18922
+ let inputTokens = 0;
18923
+ for (const batch of chunkArray(request.input, perRequest)) {
18924
+ const body = {
18925
+ instances: batch.map((content) => ({ content, ...taskType ? { task_type: taskType } : {} }))
18926
+ };
18927
+ const { parameters: extraParameters, ...extraRest } = request.extra ?? {};
18928
+ const parameters = {
18929
+ ...request.dimensions != null ? { outputDimensionality: request.dimensions } : {},
18930
+ // Caller-supplied parameters are merged in, not replacing the above (an
18931
+ // explicit extra.parameters.outputDimensionality still wins).
18932
+ ...extraParameters && typeof extraParameters === "object" ? extraParameters : {}
18933
+ };
18934
+ if (Object.keys(parameters).length > 0) body.parameters = parameters;
18935
+ Object.assign(body, extraRest);
18936
+ const res = await this.doFetch(url, body, request.signal, model);
18937
+ const json = await res.json();
18938
+ raw.push(json);
18939
+ for (const p of json.predictions ?? []) {
18940
+ const values = p.embeddings?.values;
18941
+ if (!Array.isArray(values)) {
18942
+ throw new ProviderError("Vertex embeddings response has a prediction without an embeddings.values array", this.providerName, void 0, json);
18943
+ }
18944
+ vectors.push(values);
18945
+ inputTokens += p.embeddings?.statistics?.token_count ?? 0;
18946
+ }
18947
+ }
18948
+ assertVectorCount(this.providerName, vectors, request.input.length);
18949
+ return { model, vectors, usage: { inputTokens, totalTokens: inputTokens }, raw };
18950
+ }
17103
18951
  buildUrl(modelId, stream) {
17104
18952
  const base = `https://${this.location}-aiplatform.googleapis.com/v1`;
17105
18953
  const path2 = `projects/${this.projectId}/locations/${this.location}/publishers/google/models/${modelId}`;
@@ -17197,7 +19045,9 @@ var VertexProvider = class extends BaseProvider {
17197
19045
  functionCall: {
17198
19046
  name: tc.name,
17199
19047
  args: safeJsonParse3(tc.arguments)
17200
- }
19048
+ },
19049
+ // Gemini 3 requires the signature of each functionCall echoed back.
19050
+ ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
17201
19051
  });
17202
19052
  }
17203
19053
  return { role: "model", parts: parts2 };
@@ -17294,7 +19144,7 @@ var VertexProvider = class extends BaseProvider {
17294
19144
  sign.update(signingInput);
17295
19145
  const signature = sign.sign(sa.private_key, "base64url");
17296
19146
  const jwt = `${signingInput}.${signature}`;
17297
- const tokenRes = await fetch("https://oauth2.googleapis.com/token", {
19147
+ const tokenRes = await this.httpFetch("https://oauth2.googleapis.com/token", {
17298
19148
  method: "POST",
17299
19149
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
17300
19150
  body: `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=${jwt}`
@@ -17306,20 +19156,38 @@ var VertexProvider = class extends BaseProvider {
17306
19156
  const tokenJson = await tokenRes.json();
17307
19157
  return tokenJson.access_token;
17308
19158
  }
17309
- async doFetch(url, body, signal) {
19159
+ async doFetch(url, body, signal, model = "") {
17310
19160
  const token = await this.getAccessToken();
17311
- const res = await fetch(url, {
17312
- method: "POST",
17313
- headers: {
17314
- "Content-Type": "application/json",
17315
- Authorization: `Bearer ${token}`,
17316
- ...this.defaultHeaders
17317
- },
17318
- body: JSON.stringify(body),
19161
+ const bodyStr = JSON.stringify(body);
19162
+ const res = await this.doFetchWithRetry(
19163
+ () => this.httpFetch(url, {
19164
+ method: "POST",
19165
+ headers: {
19166
+ "Content-Type": "application/json",
19167
+ Authorization: `Bearer ${token}`,
19168
+ ...this.defaultHeaders
19169
+ },
19170
+ body: bodyStr,
19171
+ signal
19172
+ }),
17319
19173
  signal
17320
- });
19174
+ );
17321
19175
  if (!res.ok) {
17322
19176
  const text = await res.text().catch(() => "");
19177
+ if (res.status === 400) {
19178
+ const parsed = parseModelError(text);
19179
+ throw new ModelRequestError({
19180
+ status: 400,
19181
+ code: parsed?.kind === "unsupported_value" ? "unsupported_value" : parsed?.kind === "unsupported_parameter" ? "unsupported_parameter" : "model_request_invalid",
19182
+ param: parsed?.param,
19183
+ value: parsed?.value,
19184
+ supportedValues: parsed?.supportedValues,
19185
+ provider: this.providerName,
19186
+ model,
19187
+ message: `Vertex AI API error ${res.status}: ${text}`,
19188
+ responseBody: text
19189
+ });
19190
+ }
17323
19191
  throw new ProviderError(
17324
19192
  `Vertex AI API error ${res.status}: ${text}`,
17325
19193
  this.providerName,
@@ -17347,7 +19215,8 @@ var VertexProvider = class extends BaseProvider {
17347
19215
  toolCalls.push({
17348
19216
  id: `call_${toolCallIdx++}`,
17349
19217
  name: part.functionCall.name,
17350
- arguments: JSON.stringify(part.functionCall.args ?? {})
19218
+ arguments: JSON.stringify(part.functionCall.args ?? {}),
19219
+ ...part.thoughtSignature ? { thoughtSignature: part.thoughtSignature } : {}
17351
19220
  });
17352
19221
  }
17353
19222
  }
@@ -17368,11 +19237,12 @@ var VertexProvider = class extends BaseProvider {
17368
19237
  toolCalls,
17369
19238
  usage: tokenUsage,
17370
19239
  finishReason: mapGeminiFinishReason(candidate?.finishReason),
19240
+ ...typeof candidate?.finishReason === "string" ? { rawFinishReason: candidate.finishReason } : {},
17371
19241
  reasoning: thoughtParts.length > 0 ? { summary: thoughtParts.join("\n").trim() || void 0 } : void 0,
17372
19242
  raw: json
17373
19243
  };
17374
19244
  }
17375
- parseStreamChunk(chunk, modelId) {
19245
+ parseStreamChunk(chunk, modelId, counter) {
17376
19246
  const candidate = chunk.candidates?.[0];
17377
19247
  const parts = candidate?.content?.parts ?? [];
17378
19248
  const delta = {};
@@ -17386,9 +19256,12 @@ var VertexProvider = class extends BaseProvider {
17386
19256
  } else if (part.functionCall) {
17387
19257
  if (!delta.toolCalls) delta.toolCalls = [];
17388
19258
  delta.toolCalls.push({
17389
- id: `call_${delta.toolCalls.length}`,
19259
+ // Unique across the whole stream: the adapter merges chunks by id.
19260
+ id: `call_${counter.next}`,
19261
+ index: counter.next++,
17390
19262
  name: part.functionCall.name,
17391
- arguments: JSON.stringify(part.functionCall.args ?? {})
19263
+ arguments: JSON.stringify(part.functionCall.args ?? {}),
19264
+ ...part.thoughtSignature ? { thoughtSignature: part.thoughtSignature } : {}
17392
19265
  });
17393
19266
  }
17394
19267
  }
@@ -17410,10 +19283,21 @@ var VertexProvider = class extends BaseProvider {
17410
19283
  model: modelId,
17411
19284
  delta,
17412
19285
  usage,
17413
- finishReason: mapGeminiFinishReason(candidate?.finishReason)
19286
+ finishReason: mapGeminiFinishReason(candidate?.finishReason),
19287
+ ...typeof candidate?.finishReason === "string" ? { rawFinishReason: candidate.finishReason } : {}
17414
19288
  };
17415
19289
  }
17416
19290
  };
19291
+ var GEMINI_TASK_TYPES = {
19292
+ search_document: "RETRIEVAL_DOCUMENT",
19293
+ search_query: "RETRIEVAL_QUERY",
19294
+ classification: "CLASSIFICATION",
19295
+ clustering: "CLUSTERING",
19296
+ semantic_similarity: "SEMANTIC_SIMILARITY",
19297
+ question_answering: "QUESTION_ANSWERING",
19298
+ fact_verification: "FACT_VERIFICATION",
19299
+ code_retrieval_query: "CODE_RETRIEVAL_QUERY"
19300
+ };
17417
19301
  function mapGeminiFinishReason(reason) {
17418
19302
  switch (reason) {
17419
19303
  case "STOP":
@@ -17462,6 +19346,6 @@ function createProvider(config) {
17462
19346
  }
17463
19347
  }
17464
19348
 
17465
- export { ASK_USER_TOOL_NAME, AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, CCRStore, CONSOLE_HOOK_MAP, CONTEXT_PILOT_JSON_MARKER_KEY, CONTROL_PLANE_TOOL_NAMES, DEFAULT_MAX_TOOL_INPUT_FIELD_CHARS, DEFAULT_PROFILE_CONFIGS, DEFAULT_SKILL_POLICY, DEFAULT_SUBAGENT_POLICY, DEFAULT_SUBAGENT_TOOL_NAMES, DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS, DELEGATION_TOOL_NAMES, DedupTracker, GuardrailPhase, HOOK_CONTRACT_VERSION, HOOK_NAMES, HookTimeoutError, InMemoryMemoryStore, JevProvider, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, PREOPEN_TOOL_CALL_PREFIX, ProviderError, SMALL_TIER_SKILL_POLICY, StructuredOutputManager, TOOL_INPUT_DIGEST_KEY, ToolBasedStrategy, VertexProvider, agentVerdictRule, appendBoundTools, auditLog, azureContentSafety, bedrockGuardrail, budgetGuard, buildHandoffTools, buildResponseFormatSection, buildSkillHeaderBlock, buildSubagentCatalogBlock, buildSystemPrompt, buildToolDefinitionsSection, canOpenSkill, canSpawn, captureSnapshot, checkpointing, codePresenceRule, coerceToolArgs, cognipeerGuardrail, cognipeerSink, collectAttachments, collectToolRetentionDeclarations, composeToolSets, compressDiffOutput, compressJsonOutput, compressLogOutput, compressSearchOutput, compressTextOutput, compressToolOutput, contentPartToText, contentToString, conversationHistory, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createBindSkillToolsTool, createCodeGuardrail, createContextPilotRuntime, createContextSummarizeNode, createContextTools, createDelegateTool, createGetToolResponseTool, createGuardrail, createGuardrailPlugin, createJsonGuardrail, createManageTodoListAliasTool, createManageTodoTool, createOpenSkillTool, createParallelTool, createPluginHost, createProvider, createRegexGuardrail, createResolverNode, createSearchSkillsTool, createSkillRegistryRef, createSkillTools, createSmartAgent, createSpawnTool, createSubagentRegistryRef, createSubagentTools, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customGuardrail, customSink, dedupeToolsByName, defaultTokenCounter, defineHook, definePlugin, describeContentPart, detectLanguage, detectTextFormat, detectVolatileContent, digestToolInputArguments, digestToolInputValue, emptyUsage, evaluateGuardrails, extractLatestUserQuery, extractMessageText, fileCheckpointStore, fileSink, findSubagent, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasMediaPart, hasToolResponseRecoveryReference, httpGuardrail, httpSink, inMemoryCheckpointStore, inMemoryConversationStore, isHookImplemented, isOpenAIHostedEndpoint, isSmartModel, isValidIban, isValidLuhn, isValidTckn, jsonSchemaRule, defaultBuildPayload as langfuseDefaultPayload, langfuseTracing, languageGuard, loadSkillsFromDisk, mapConsoleHookVerdict, mapTextParts, mcp, mediaKindOf, mediaPolicy, normalizeSmartAgentOptions, normalizeVerdicts, openAIModeration, otelTracing, otlpSink, outputGuard, parseApprovalDecision, parseSkillFrontmatter, pathSandbox, piiRedaction, pluginCapabilities, portkeyGateway, portkeyGuardrail, preopenSkills, preopenToolCallId, prepareStrictToolMenu, promptInjectionGuard, rateLimit, readMemoryFacts, redactText, regexGuardrail, regexRule, replaceTextContent, resolveAvailableSkills, resolveAvailableSubagents, resolveInputRetention, resolveMemoryStore, resolveReasoning, resolveStrategy, resolveSubagentTools, resolveSummarizationRetention, resolveToolApprovalState, resolveUserQuestionState, responseCache, restoreSnapshot, restoreToolCalls, runSmartAgentEvalHarness, scoreItemsByRelevance, searchSkills, seedChildMessages, selectTopIndicesInOrder, sessionMetrics, setTokenCounter, startStreamingSession, summarizeObject, textFromContent, toStrictCompatible, toStrictToolSchema, tokenize, toolPolicy, traceSessionToOtlp, validateReasoningConfig, validateToolArgs, webhookApproval, withTools, withinDepth, writeSummaryFactsToMemory };
19349
+ export { ASK_USER_TOOL_NAME, AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, CCRStore, CONSOLE_HOOK_MAP, CONTEXT_PILOT_JSON_MARKER_KEY, CONTROL_PLANE_TOOL_NAMES, DEFAULT_MAX_TOOL_INPUT_FIELD_CHARS, DEFAULT_PROFILE_CONFIGS, DEFAULT_SKILL_POLICY, DEFAULT_SUBAGENT_POLICY, DEFAULT_SUBAGENT_TOOL_NAMES, DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS, DELEGATION_TOOL_NAMES, DedupTracker, GuardrailPhase, HOOK_CONTRACT_VERSION, HOOK_NAMES, HookTimeoutError, InMemoryMemoryStore, JevProvider, MAX_ADJUSTMENTS, MODEL_RULES, ModelRequestError, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, PREOPEN_TOOL_CALL_PREFIX, ProviderError, SMALL_TIER_SKILL_POLICY, StructuredOutputManager, TOOL_INPUT_DIGEST_KEY, ToolBasedStrategy, VertexProvider, agentVerdictRule, allowsSampling, appendBoundTools, applyDropParams, asModelRequestError, auditLog, azureContentSafety, bedrockGuardrail, budgetGuard, buildHandoffTools, buildResponseFormatSection, buildSkillHeaderBlock, buildSubagentCatalogBlock, buildSystemPrompt, buildToolDefinitionsSection, canOpenSkill, canSpawn, captureSnapshot, checkpointing, clearLearnedModelRules, codePresenceRule, coerceToolArgs, cognipeerGuardrail, cognipeerSink, collectAttachments, collectToolRetentionDeclarations, composeToolSets, compressDiffOutput, compressJsonOutput, compressLogOutput, compressSearchOutput, compressTextOutput, compressToolOutput, contentPartToText, contentToString, conversationHistory, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createBindSkillToolsTool, createCodeGuardrail, createContextPilotRuntime, createContextSummarizeNode, createContextTools, createDelegateTool, createGetToolResponseTool, createGuardrail, createGuardrailPlugin, createJsonGuardrail, createManageTodoListAliasTool, createManageTodoTool, createOpenSkillTool, createParallelTool, createPluginHost, createProvider, createRegexGuardrail, createResolverNode, createSearchSkillsTool, createSkillRegistryRef, createSkillTools, createSmartAgent, createSpawnTool, createSubagentRegistryRef, createSubagentTools, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customGuardrail, customSink, dedupeToolsByName, defaultTokenCounter, defineHook, definePlugin, describeContentPart, detectLanguage, detectTextFormat, detectVolatileContent, digestToolInputArguments, digestToolInputValue, effortBudget, emptyUsage, evaluateGuardrails, extractLatestUserQuery, extractMessageText, fileCheckpointStore, fileSink, findSubagent, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getLearnedModelRulePatch, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasMediaPart, hasToolResponseRecoveryReference, httpGuardrail, httpSink, inMemoryCheckpointStore, inMemoryConversationStore, isHookImplemented, isOpenAIHostedEndpoint, isSmartModel, isValidIban, isValidLuhn, isValidTckn, jsonSchemaRule, defaultBuildPayload as langfuseDefaultPayload, langfuseTracing, languageGuard, listLearnedModelRules, loadSkillsFromDisk, mapConsoleHookVerdict, mapReasoningEffort, mapTextParts, mcp, mediaKindOf, mediaPolicy, mergeRulePatch, modelIdCandidates, normalizeSmartAgentOptions, normalizeVerdicts, openAIModeration, otelTracing, otlpSink, outputGuard, parseApprovalDecision, parseModelError, parseSkillFrontmatter, pathSandbox, piiRedaction, pluginCapabilities, portkeyGateway, portkeyGuardrail, preopenSkills, preopenToolCallId, prepareStrictToolMenu, promptInjectionGuard, rateLimit, readMemoryFacts, redactText, regexGuardrail, regexRule, rememberModelRulePatch, replaceTextContent, resolveAvailableSkills, resolveAvailableSubagents, resolveInputRetention, resolveMemoryStore, resolveModelRule, resolveReasoning, resolveStrategy, resolveSubagentTools, resolveSummarizationRetention, resolveToolApprovalState, resolveUserQuestionState, responseCache, restoreSnapshot, restoreToolCalls, runSmartAgentEvalHarness, runWithModelAdjustments, scoreItemsByRelevance, searchSkills, seedChildMessages, selectTopIndicesInOrder, sessionMetrics, setTokenCounter, startStreamingSession, summarizeObject, supportsAdaptiveThinking, textFromContent, toMessageUsage, toStrictCompatible, toStrictToolSchema, tokenize, toolPolicy, traceSessionToOtlp, validateReasoningConfig, validateToolArgs, webhookApproval, withTools, withinDepth, writeSummaryFactsToMemory };
17466
19350
  //# sourceMappingURL=index.mjs.map
17467
19351
  //# sourceMappingURL=index.mjs.map