@omnicross/core 0.1.8 → 0.1.10

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.
Files changed (113) hide show
  1. package/dist/auth/GeminiCodeAssistProjectResolver.cjs +5 -3
  2. package/dist/auth/GeminiCodeAssistProjectResolver.js +4 -2
  3. package/dist/{chunk-N5T4M4GU.js → chunk-2UTGX6FM.js} +2 -2
  4. package/dist/{chunk-32O35CIF.js → chunk-45FHEOKW.js} +22 -7
  5. package/dist/{chunk-LVUCAWMK.js → chunk-55FMGZ3L.js} +13 -5
  6. package/dist/{chunk-OF3BECU2.cjs → chunk-56QD3YW6.cjs} +18 -5
  7. package/dist/{chunk-V4TXMEJS.cjs → chunk-5LNYGCIW.cjs} +15 -7
  8. package/dist/{chunk-EPN67EGP.cjs → chunk-5UK3KLE2.cjs} +9 -1
  9. package/dist/chunk-6D4W22P4.js +150 -0
  10. package/dist/chunk-77USGNRW.cjs +37 -0
  11. package/dist/chunk-AOFWNWLT.cjs +203 -0
  12. package/dist/{chunk-UAPBLNN2.js → chunk-AQDON6MB.js} +8 -0
  13. package/dist/{chunk-LB6EBS6Y.js → chunk-CCVRRJOX.js} +17 -4
  14. package/dist/{chunk-OVQBNVSV.cjs → chunk-CMVXX7ON.cjs} +42 -27
  15. package/dist/{chunk-QYC54PMG.js → chunk-FEBAQI5A.js} +255 -92
  16. package/dist/{chunk-7C7DET6S.js → chunk-GXEZ2R3E.js} +156 -1
  17. package/dist/{chunk-PEGTIPB3.js → chunk-HKB656B4.js} +37 -43
  18. package/dist/chunk-N2EIM2XJ.js +203 -0
  19. package/dist/{chunk-MYYR3HZL.js → chunk-NGYOO5TO.js} +5 -5
  20. package/dist/{chunk-OKMJLEXX.cjs → chunk-OC6DOOFX.cjs} +5 -5
  21. package/dist/{chunk-2Z4XM3H5.cjs → chunk-P7EM6BND.cjs} +10 -10
  22. package/dist/chunk-QUSEZNYS.cjs +150 -0
  23. package/dist/{chunk-KBM2W6UY.cjs → chunk-RICPANBY.cjs} +41 -24
  24. package/dist/{chunk-TOVPMMHM.js → chunk-S3DYFEBE.js} +37 -20
  25. package/dist/{chunk-26K6T2YS.cjs → chunk-TIT74RIL.cjs} +407 -244
  26. package/dist/{chunk-XPIOJQS2.cjs → chunk-UWDW6PN3.cjs} +159 -4
  27. package/dist/chunk-WYVGULTQ.js +37 -0
  28. package/dist/{chunk-OXHNSZ53.cjs → chunk-ZQQUD66M.cjs} +54 -60
  29. package/dist/completion/CompletionService.cjs +15 -13
  30. package/dist/completion/CompletionService.js +14 -12
  31. package/dist/completion.cjs +15 -13
  32. package/dist/completion.js +14 -12
  33. package/dist/index.cjs +15 -13
  34. package/dist/index.d.cts +2 -2
  35. package/dist/index.d.ts +2 -2
  36. package/dist/index.js +14 -12
  37. package/dist/outbound-api/auditCapture.cjs +2 -2
  38. package/dist/outbound-api/auditCapture.d.cts +6 -0
  39. package/dist/outbound-api/auditCapture.d.ts +6 -0
  40. package/dist/outbound-api/auditCapture.js +1 -1
  41. package/dist/outbound-api/routeResolver.d.cts +1 -1
  42. package/dist/outbound-api/routeResolver.d.ts +1 -1
  43. package/dist/outbound-api/types.d.cts +1 -1
  44. package/dist/outbound-api/types.d.ts +1 -1
  45. package/dist/outbound-api.cjs +15 -13
  46. package/dist/outbound-api.d.cts +3 -2
  47. package/dist/outbound-api.d.ts +3 -2
  48. package/dist/outbound-api.js +14 -12
  49. package/dist/pipeline/AccountAllowanceScheduling.d.cts +1 -1
  50. package/dist/pipeline/AccountAllowanceScheduling.d.ts +1 -1
  51. package/dist/pipeline/executeProviderCall.d.cts +2 -0
  52. package/dist/pipeline/executeProviderCall.d.ts +2 -0
  53. package/dist/pipeline/resolveProviderChain.d.cts +1 -0
  54. package/dist/pipeline/resolveProviderChain.d.ts +1 -0
  55. package/dist/pipeline/resolveSubscriptionChain.d.cts +2 -0
  56. package/dist/pipeline/resolveSubscriptionChain.d.ts +2 -0
  57. package/dist/ports/provider-config-source.d.cts +1 -0
  58. package/dist/ports/provider-config-source.d.ts +1 -0
  59. package/dist/ports.d.cts +1 -1
  60. package/dist/ports.d.ts +1 -1
  61. package/dist/provider-proxy/ProviderProxy.cjs +15 -13
  62. package/dist/provider-proxy/ProviderProxy.js +14 -12
  63. package/dist/provider-proxy/ingress/providerProxyShared.cjs +15 -13
  64. package/dist/provider-proxy/ingress/providerProxyShared.js +14 -12
  65. package/dist/provider-proxy.cjs +15 -13
  66. package/dist/provider-proxy.js +14 -12
  67. package/dist/transformer/TransformerChainExecutor.d.cts +2 -0
  68. package/dist/transformer/TransformerChainExecutor.d.ts +2 -0
  69. package/dist/transformer/TransformerService.d.cts +2 -0
  70. package/dist/transformer/TransformerService.d.ts +2 -0
  71. package/dist/transformer/transformers/AnthropicTransformer.cjs +4 -2
  72. package/dist/transformer/transformers/AnthropicTransformer.d.cts +7 -2
  73. package/dist/transformer/transformers/AnthropicTransformer.d.ts +7 -2
  74. package/dist/transformer/transformers/AnthropicTransformer.js +3 -1
  75. package/dist/transformer/transformers/GeminiCodeAssistTransformer.cjs +5 -3
  76. package/dist/transformer/transformers/GeminiCodeAssistTransformer.d.cts +2 -0
  77. package/dist/transformer/transformers/GeminiCodeAssistTransformer.d.ts +2 -0
  78. package/dist/transformer/transformers/GeminiCodeAssistTransformer.js +4 -2
  79. package/dist/transformer/transformers/GeminiTransformer.cjs +5 -3
  80. package/dist/transformer/transformers/GeminiTransformer.d.cts +4 -2
  81. package/dist/transformer/transformers/GeminiTransformer.d.ts +4 -2
  82. package/dist/transformer/transformers/GeminiTransformer.js +4 -2
  83. package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +3 -2
  84. package/dist/transformer/transformers/OpenAIResponseTransformer.d.cts +4 -2
  85. package/dist/transformer/transformers/OpenAIResponseTransformer.d.ts +4 -2
  86. package/dist/transformer/transformers/OpenAIResponseTransformer.js +2 -1
  87. package/dist/transformer/transformers/OpenAITransformer.cjs +3 -2
  88. package/dist/transformer/transformers/OpenAITransformer.d.cts +3 -1
  89. package/dist/transformer/transformers/OpenAITransformer.d.ts +3 -1
  90. package/dist/transformer/transformers/OpenAITransformer.js +2 -1
  91. package/dist/transformer/transformers.cjs +10 -8
  92. package/dist/transformer/transformers.d.cts +2 -0
  93. package/dist/transformer/transformers.d.ts +2 -0
  94. package/dist/transformer/transformers.js +9 -7
  95. package/dist/transformer/types.d.cts +16 -5
  96. package/dist/transformer/types.d.ts +16 -5
  97. package/dist/transformer.cjs +28 -9
  98. package/dist/transformer.d.cts +76 -1
  99. package/dist/transformer.d.ts +76 -1
  100. package/dist/transformer.js +28 -9
  101. package/dist/usage/usage-recorder.cjs +2 -2
  102. package/dist/usage/usage-recorder.d.cts +12 -2
  103. package/dist/usage/usage-recorder.d.ts +12 -2
  104. package/dist/usage/usage-recorder.js +1 -1
  105. package/dist/usage.cjs +20 -3
  106. package/dist/usage.d.cts +149 -0
  107. package/dist/usage.d.ts +149 -0
  108. package/dist/usage.js +20 -3
  109. package/package.json +2 -2
  110. package/dist/chunk-7VU7V2E4.js +0 -0
  111. package/dist/chunk-FZ46M34D.cjs +0 -1
  112. /package/dist/{chunk-EYZYXJTJ.cjs → chunk-QVOB2DNX.cjs} +0 -0
  113. /package/dist/{chunk-46RLHI7D.js → chunk-WTQMX2Q6.js} +0 -0
@@ -4,13 +4,13 @@ import {
4
4
  import {
5
5
  AnthropicTransformer,
6
6
  resolveAnthropicMaxTokens
7
- } from "./chunk-PEGTIPB3.js";
7
+ } from "./chunk-HKB656B4.js";
8
8
  import {
9
9
  GeminiTransformer
10
- } from "./chunk-LVUCAWMK.js";
10
+ } from "./chunk-55FMGZ3L.js";
11
11
  import {
12
12
  OpenAIResponseTransformer
13
- } from "./chunk-32O35CIF.js";
13
+ } from "./chunk-45FHEOKW.js";
14
14
  import {
15
15
  TransformerChainExecutor
16
16
  } from "./chunk-WNKWAEUR.js";
@@ -33,9 +33,11 @@ import {
33
33
  captureCallerIdentity
34
34
  } from "./chunk-XX6NQJMA.js";
35
35
  import {
36
+ MATCH_TEXT_PER_MESSAGE_CAP,
36
37
  collectMatchText,
37
38
  deriveGatewaySessionKey,
38
- deriveSubscriptionSessionKey
39
+ deriveSubscriptionSessionKey,
40
+ flattenMatchText
39
41
  } from "./chunk-GFIZ6LQI.js";
40
42
  import {
41
43
  emitWebhookEvent
@@ -104,11 +106,14 @@ import {
104
106
  } from "./chunk-H5JUT3KV.js";
105
107
  import {
106
108
  beginAuditCapture
107
- } from "./chunk-7C7DET6S.js";
109
+ } from "./chunk-GXEZ2R3E.js";
108
110
  import {
109
111
  convertAnthropicToOpenAI,
110
112
  convertOpenAIToAnthropic
111
113
  } from "./chunk-5NJLQ6T6.js";
114
+ import {
115
+ resolveReasoningPlan
116
+ } from "./chunk-N2EIM2XJ.js";
112
117
  import {
113
118
  fetchUpstream
114
119
  } from "./chunk-RJ5ZGNI3.js";
@@ -413,9 +418,6 @@ function addOpenRouterProviderToRequest(requestBody, provider, modelId) {
413
418
  };
414
419
  }
415
420
 
416
- // src/completion/DirectApiHandler.ts
417
- import { getOpenAIReasoningEffort } from "@omnicross/contracts/thinking-config";
418
-
419
421
  // src/provider-proxy/ProviderProxy.ts
420
422
  import http from "http";
421
423
 
@@ -1432,7 +1434,8 @@ async function buildByoPlan(res, route, deps, resolvedModel, isStream) {
1432
1434
  name: provider.name,
1433
1435
  baseUrl: provider.api_base_url,
1434
1436
  apiKey,
1435
- models: provider.models || []
1437
+ models: provider.models || [],
1438
+ modelConfigs: provider.modelConfigs
1436
1439
  };
1437
1440
  const byoUrl = buildProviderApiUrl(provider, { model: resolvedModel, stream: isStream });
1438
1441
  const sameFormat = route.targetProviderFormat === "anthropic" || resolveApiFormat(provider) === "anthropic";
@@ -1740,7 +1743,8 @@ async function buildByoPlan2(res, route, deps, resolvedModel, isStream) {
1740
1743
  name: provider.name,
1741
1744
  baseUrl: provider.api_base_url,
1742
1745
  apiKey,
1743
- models: provider.models || []
1746
+ models: provider.models || [],
1747
+ modelConfigs: provider.modelConfigs
1744
1748
  };
1745
1749
  const byoUrl = buildProviderApiUrl(provider, { model: resolvedModel, stream: isStream });
1746
1750
  return {
@@ -1957,7 +1961,8 @@ async function buildByoPlan3(res, route, deps, resolvedModel, isStream) {
1957
1961
  name: provider.name,
1958
1962
  baseUrl: provider.api_base_url,
1959
1963
  apiKey,
1960
- models: provider.models || []
1964
+ models: provider.models || [],
1965
+ modelConfigs: provider.modelConfigs
1961
1966
  };
1962
1967
  const byoUrl = buildProviderApiUrl(provider, { model: resolvedModel, stream: isStream });
1963
1968
  return {
@@ -2351,7 +2356,8 @@ async function buildByoPlan4(res, route, deps, resolvedModel, isStream) {
2351
2356
  name: provider.name,
2352
2357
  baseUrl: provider.api_base_url,
2353
2358
  apiKey,
2354
- models: provider.models || []
2359
+ models: provider.models || [],
2360
+ modelConfigs: provider.modelConfigs
2355
2361
  };
2356
2362
  const byoUrl = buildProviderApiUrl(provider, { model: resolvedModel, stream: isStream });
2357
2363
  return {
@@ -3562,6 +3568,7 @@ var KeyedMutex = class {
3562
3568
 
3563
3569
  // src/outbound-api/outboundApiRouter.ts
3564
3570
  import { Readable } from "stream";
3571
+ import { SUBSCRIPTION_MODEL_CATALOG } from "@omnicross/contracts/subscription-model-catalog";
3565
3572
 
3566
3573
  // src/outbound-api/apiServerConfig.ts
3567
3574
  import { DEFAULT_AUDIT_CONFIG } from "@omnicross/contracts/audit-types";
@@ -3659,6 +3666,7 @@ function normalizeAudit(raw) {
3659
3666
  retentionDays: Math.trunc(
3660
3667
  clampNumber(a?.retentionDays, 1, 365, DEFAULT_AUDIT_CONFIG.retentionDays)
3661
3668
  ),
3669
+ compactStreamingBodies: a?.compactStreamingBodies === true,
3662
3670
  trustForwardedFor: a?.trustForwardedFor === true
3663
3671
  };
3664
3672
  }
@@ -4126,8 +4134,62 @@ function mergeServerConfig(current, patch) {
4126
4134
  });
4127
4135
  }
4128
4136
 
4137
+ // src/outbound-api/auditSessionKey.ts
4138
+ import { createHash as createHash2 } from "crypto";
4139
+ var EXPLICIT_ID_SOURCES = /* @__PURE__ */ new Set([
4140
+ "session-header",
4141
+ "thread-header",
4142
+ "body-session-id",
4143
+ "body-thread-id",
4144
+ "prompt-cache-key"
4145
+ ]);
4146
+ var ANTHROPIC_SESSION_RE = /_session_([A-Za-z0-9][A-Za-z0-9_-]{7,})/;
4147
+ var DIGEST_HEX = 32;
4148
+ function stableDigest(value) {
4149
+ return createHash2("sha256").update(value, "utf8").digest("hex").slice(0, DIGEST_HEX);
4150
+ }
4151
+ function asObject(value) {
4152
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
4153
+ }
4154
+ function anthropicSessionId(body) {
4155
+ const userId = asObject(body["metadata"])?.["user_id"];
4156
+ if (typeof userId !== "string" || !userId) return void 0;
4157
+ const matched = ANTHROPIC_SESSION_RE.exec(userId);
4158
+ return matched?.[1];
4159
+ }
4160
+ function anthropicContentFingerprint(body) {
4161
+ const messages = body["messages"];
4162
+ if (!Array.isArray(messages) || messages.length === 0) return void 0;
4163
+ const parts = [];
4164
+ const system = flattenMatchText(body["system"]).trim();
4165
+ if (system) parts.push(system.slice(0, MATCH_TEXT_PER_MESSAGE_CAP));
4166
+ let firstUser = "";
4167
+ for (const entry of messages) {
4168
+ const message = asObject(entry);
4169
+ if (!message || message["role"] !== "user") continue;
4170
+ const text = flattenMatchText(message["content"]).trim();
4171
+ if (!text) continue;
4172
+ firstUser = text.slice(0, MATCH_TEXT_PER_MESSAGE_CAP);
4173
+ break;
4174
+ }
4175
+ if (parts.length === 0 && !firstUser) return void 0;
4176
+ return `${parts.join("\0")}\0${firstUser}`;
4177
+ }
4178
+ function deriveAuditSessionKey(body, headers = {}, options = {}) {
4179
+ const anthropicSession = anthropicSessionId(body);
4180
+ if (anthropicSession) return stableDigest(`anthropic-session\0${anthropicSession}`);
4181
+ const gateway = deriveGatewaySessionKey(body, headers, {
4182
+ ...options.fallbackKey !== void 0 ? { fallbackKey: options.fallbackKey } : {},
4183
+ ...options.endpoint !== void 0 ? { endpoint: options.endpoint } : {}
4184
+ });
4185
+ if (EXPLICIT_ID_SOURCES.has(gateway.source)) return gateway.key;
4186
+ const fingerprint = anthropicContentFingerprint(body);
4187
+ if (fingerprint) return stableDigest(`anthropic-content\0${fingerprint}`);
4188
+ return gateway.key;
4189
+ }
4190
+
4129
4191
  // src/outbound-api/outboundApiKeyAuth.ts
4130
- import { createHash as createHash2, randomBytes as randomBytes4 } from "crypto";
4192
+ import { createHash as createHash3, randomBytes as randomBytes4 } from "crypto";
4131
4193
 
4132
4194
  // src/outbound-api/keyPolicy.ts
4133
4195
  var DAY_MS = 864e5;
@@ -4192,7 +4254,7 @@ function generateSecret() {
4192
4254
  return KEY_PREFIX + randomBase62(SECRET_BYTES);
4193
4255
  }
4194
4256
  function hashKey(secret) {
4195
- return createHash2("sha256").update(secret, "utf8").digest("hex");
4257
+ return createHash3("sha256").update(secret, "utf8").digest("hex");
4196
4258
  }
4197
4259
  function keyPrefix(secret) {
4198
4260
  return secret.slice(0, PREFIX_LEN);
@@ -4520,7 +4582,7 @@ var OutboundRateLimiter = class {
4520
4582
  function asArray(v) {
4521
4583
  return Array.isArray(v) ? v : [];
4522
4584
  }
4523
- function asObject(v) {
4585
+ function asObject2(v) {
4524
4586
  return v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
4525
4587
  }
4526
4588
  function last(arr) {
@@ -4528,13 +4590,13 @@ function last(arr) {
4528
4590
  }
4529
4591
  function isUserMessageAnthropic(body) {
4530
4592
  const messages = asArray(body["messages"]);
4531
- const lastMsg = asObject(last(messages));
4593
+ const lastMsg = asObject2(last(messages));
4532
4594
  if (!lastMsg || lastMsg["role"] !== "user") return false;
4533
4595
  const content = lastMsg["content"];
4534
4596
  if (typeof content === "string") return true;
4535
4597
  if (Array.isArray(content)) {
4536
4598
  const hasToolResult = content.some(
4537
- (block) => asObject(block)?.["type"] === "tool_result"
4599
+ (block) => asObject2(block)?.["type"] === "tool_result"
4538
4600
  );
4539
4601
  return !hasToolResult;
4540
4602
  }
@@ -4544,7 +4606,7 @@ function isUserMessageResponses(body) {
4544
4606
  const input = body["input"];
4545
4607
  if (typeof input === "string") return input.length > 0;
4546
4608
  if (Array.isArray(input)) {
4547
- const lastItem = asObject(last(input));
4609
+ const lastItem = asObject2(last(input));
4548
4610
  if (!lastItem) return false;
4549
4611
  if (lastItem["type"] === "function_call_output") return false;
4550
4612
  return lastItem["role"] === "user";
@@ -4553,22 +4615,22 @@ function isUserMessageResponses(body) {
4553
4615
  }
4554
4616
  function isUserMessageChat(body) {
4555
4617
  const messages = asArray(body["messages"]);
4556
- const lastMsg = asObject(last(messages));
4618
+ const lastMsg = asObject2(last(messages));
4557
4619
  if (!lastMsg) return false;
4558
4620
  return lastMsg["role"] === "user";
4559
4621
  }
4560
4622
  function isUserMessageGemini(body) {
4561
4623
  const contents = asArray(body["contents"]);
4562
- const lastContent = asObject(last(contents));
4624
+ const lastContent = asObject2(last(contents));
4563
4625
  if (!lastContent || lastContent["role"] !== "user") return false;
4564
4626
  const parts = asArray(lastContent["parts"]);
4565
4627
  const hasFunctionResponse = parts.some(
4566
- (part) => asObject(part)?.["functionResponse"] !== void 0
4628
+ (part) => asObject2(part)?.["functionResponse"] !== void 0
4567
4629
  );
4568
4630
  return !hasFunctionResponse;
4569
4631
  }
4570
4632
  function isUserMessageRequest(endpoint, parsedBody) {
4571
- const body = asObject(parsedBody);
4633
+ const body = asObject2(parsedBody);
4572
4634
  if (!body) return false;
4573
4635
  switch (endpoint) {
4574
4636
  case "messages":
@@ -4718,7 +4780,7 @@ var UserMessageSerialQueue = class {
4718
4780
  };
4719
4781
 
4720
4782
  // src/outbound-api/voucher.ts
4721
- import { createHash as createHash3 } from "crypto";
4783
+ import { createHash as createHash4 } from "crypto";
4722
4784
  var CODE_ENTROPY_CHARS = 32;
4723
4785
  var CODE_PREFIX = "CC_";
4724
4786
  var DISPLAY_PREFIX_LEN = 8;
@@ -4727,7 +4789,7 @@ function generateVoucherCode() {
4727
4789
  return CODE_PREFIX + randomBase62(CODE_ENTROPY_CHARS);
4728
4790
  }
4729
4791
  function hashVoucherCode(code) {
4730
- return createHash3("sha256").update(code, "utf8").digest("hex");
4792
+ return createHash4("sha256").update(code, "utf8").digest("hex");
4731
4793
  }
4732
4794
  function voucherCodePrefix(code) {
4733
4795
  return code.slice(0, DISPLAY_PREFIX_LEN);
@@ -4987,33 +5049,51 @@ function isModelsListRequest(url) {
4987
5049
  const path = url.split("?")[0]?.replace(/\/+$/, "") ?? "";
4988
5050
  return path.endsWith("/models");
4989
5051
  }
4990
- function writeModelsList(res, config, apiKeyId, allowedEndpoints) {
4991
- const refs = [];
4992
- const endpointConfigs = [];
5052
+ async function writeModelsList(res, llmConfig, config, apiKeyId, allowedEndpoints) {
5053
+ const modelIds = [];
4993
5054
  for (const endpoint of ["chat", "responses", "messages", "gemini"]) {
4994
5055
  if (allowedEndpoints && !allowedEndpoints.includes(endpoint)) continue;
4995
- endpointConfigs.push(
4996
- ...candidateGatewayBindings(config.bindings, apiKeyId, endpoint).map(
4997
- (binding) => gatewayBindingToEndpointConfig(binding)
4998
- )
4999
- );
5000
- }
5001
- for (const endpoint of endpointConfigs) {
5002
- if (allowedEndpoints && !allowedEndpoints.includes(endpoint.endpoint)) continue;
5003
- if (endpoint.endpoint === "chat") refs.push(...endpoint.models ?? []);
5004
- else if (endpoint.endpoint === "messages" || endpoint.endpoint === "responses") {
5005
- refs.push(...Object.values(endpoint.modelMap ?? {}));
5006
- } else {
5007
- if (endpoint.defaultModel) refs.push(endpoint.defaultModel);
5008
- if (endpoint.backgroundModel) refs.push(endpoint.backgroundModel);
5056
+ for (const binding of candidateGatewayBindings(config.bindings, apiKeyId, endpoint)) {
5057
+ if (binding.modelMode === "passthrough") {
5058
+ if (binding.target.kind === "provider") {
5059
+ const provider = await llmConfig.getProvider(binding.target.providerId);
5060
+ modelIds.push(...provider?.models ?? []);
5061
+ } else if (Object.prototype.hasOwnProperty.call(
5062
+ SUBSCRIPTION_MODEL_CATALOG,
5063
+ binding.target.providerId
5064
+ )) {
5065
+ modelIds.push(
5066
+ ...SUBSCRIPTION_MODEL_CATALOG[binding.target.providerId]
5067
+ );
5068
+ }
5069
+ continue;
5070
+ }
5071
+ if (binding.modelMappings?.length) {
5072
+ modelIds.push(
5073
+ ...binding.modelMappings.map((mapping) => mapping.source.trim()).filter((source) => source !== "" && !source.includes("*"))
5074
+ );
5075
+ continue;
5076
+ }
5077
+ const endpointConfig = gatewayBindingToEndpointConfig(binding);
5078
+ const refs = [];
5079
+ if (endpointConfig.endpoint === "chat") refs.push(...endpointConfig.models ?? []);
5080
+ else if (endpointConfig.endpoint === "messages" || endpointConfig.endpoint === "responses") {
5081
+ refs.push(...Object.values(endpointConfig.modelMap ?? {}));
5082
+ } else {
5083
+ if (endpointConfig.defaultModel) refs.push(endpointConfig.defaultModel);
5084
+ if (endpointConfig.backgroundModel) refs.push(endpointConfig.backgroundModel);
5085
+ }
5086
+ modelIds.push(
5087
+ ...refs.map((ref) => parseModelRef(ref)?.modelId).filter((modelId) => modelId !== void 0)
5088
+ );
5009
5089
  }
5010
5090
  }
5011
5091
  const seen = /* @__PURE__ */ new Set();
5012
- const data = refs.map((ref) => parseModelRef(ref)).filter((p) => p !== null).filter((p) => {
5013
- if (seen.has(p.modelId)) return false;
5014
- seen.add(p.modelId);
5092
+ const data = modelIds.filter((modelId) => {
5093
+ if (seen.has(modelId)) return false;
5094
+ seen.add(modelId);
5015
5095
  return true;
5016
- }).map((p) => ({ id: p.modelId, object: "model", owned_by: "omnicross" }));
5096
+ }).map((modelId) => ({ id: modelId, object: "model", owned_by: "omnicross" }));
5017
5097
  res.writeHead(200, { "Content-Type": "application/json" });
5018
5098
  res.end(JSON.stringify({ object: "list", data }));
5019
5099
  }
@@ -5081,7 +5161,7 @@ async function handleOutboundRequest(req, res, deps, config, rateLimiter, serial
5081
5161
  writeJsonError(res, 403, "API key is not allowed to access this endpoint");
5082
5162
  return;
5083
5163
  }
5084
- writeModelsList(res, config, verified.id, verified.allowedEndpoints);
5164
+ await writeModelsList(res, deps.llmConfig, config, verified.id, verified.allowedEndpoints);
5085
5165
  return;
5086
5166
  }
5087
5167
  const endpoint = selectEndpoint(req.method, req.url);
@@ -5162,7 +5242,13 @@ async function handleOutboundRequest(req, res, deps, config, rateLimiter, serial
5162
5242
  writeJsonError(res, 400, "Invalid JSON in request body");
5163
5243
  return;
5164
5244
  }
5165
- if (audit) audit.setRequestBody(rawBody);
5245
+ if (audit) {
5246
+ audit.setRequestBody(rawBody);
5247
+ audit.sessionKey = deriveAuditSessionKey(parsedBody, req.headers, {
5248
+ fallbackKey: verified.id,
5249
+ endpoint
5250
+ });
5251
+ }
5166
5252
  if (endpoint === "gemini" && typeof parsedBody["model"] !== "string") {
5167
5253
  const urlModel = extractGeminiModelFromUrl(req.url);
5168
5254
  if (urlModel) parsedBody["model"] = urlModel;
@@ -5637,6 +5723,70 @@ function __resetOutboundApiServerForTests() {
5637
5723
  instance2 = null;
5638
5724
  }
5639
5725
 
5726
+ // src/completion/ReasoningRequestBuilder.ts
5727
+ var LEGACY_ANTHROPIC_MAX_TOKENS = 16384;
5728
+ function intentFromOptions(options) {
5729
+ return options.thinkLevel ? { effort: options.thinkLevel, enabled: options.thinkLevel !== "none" } : void 0;
5730
+ }
5731
+ function resolveCompletionReasoningPlan(provider, options, target, requestMaxTokens = options.maxTokens) {
5732
+ return resolveReasoningPlan({
5733
+ intent: intentFromOptions(options),
5734
+ model: options.model,
5735
+ provider,
5736
+ target,
5737
+ requestMaxTokens
5738
+ });
5739
+ }
5740
+ function resolveOpenAIEffort(provider, options, target) {
5741
+ const plan = resolveCompletionReasoningPlan(provider, options, target);
5742
+ return plan?.kind === "level" && plan.enabled ? plan.effort : void 0;
5743
+ }
5744
+ function buildAnthropicReasoningWire(provider, options) {
5745
+ const configuredMaxTokens = options.maxTokens ?? LEGACY_ANTHROPIC_MAX_TOKENS;
5746
+ const legacyBound = Math.min(configuredMaxTokens, LEGACY_ANTHROPIC_MAX_TOKENS);
5747
+ const plan = resolveCompletionReasoningPlan(
5748
+ provider,
5749
+ options,
5750
+ "anthropic",
5751
+ legacyBound
5752
+ );
5753
+ if (plan?.kind === "level" && plan.enabled) {
5754
+ return {
5755
+ effectiveMaxTokens: configuredMaxTokens,
5756
+ thinking: { type: "adaptive" },
5757
+ outputConfig: { effort: plan.effort },
5758
+ legacyBudgetEnabled: false
5759
+ };
5760
+ }
5761
+ if (plan?.kind === "budget" && plan.enabled) {
5762
+ return {
5763
+ effectiveMaxTokens: legacyBound,
5764
+ thinking: { type: "enabled", budget_tokens: plan.budgetTokens },
5765
+ legacyBudgetEnabled: true
5766
+ };
5767
+ }
5768
+ return {
5769
+ effectiveMaxTokens: configuredMaxTokens,
5770
+ legacyBudgetEnabled: false
5771
+ };
5772
+ }
5773
+ function buildGeminiThinkingConfig(provider, options) {
5774
+ const plan = resolveCompletionReasoningPlan(provider, options, "gemini");
5775
+ if (plan?.kind === "level") {
5776
+ return {
5777
+ includeThoughts: plan.enabled,
5778
+ thinkingLevel: plan.effort
5779
+ };
5780
+ }
5781
+ if (plan?.kind === "budget") {
5782
+ return {
5783
+ includeThoughts: plan.enabled,
5784
+ thinkingBudget: plan.budgetTokens
5785
+ };
5786
+ }
5787
+ return void 0;
5788
+ }
5789
+
5640
5790
  // src/completion/DirectApiHandler.ts
5641
5791
  async function callOpenAICompletion(provider, apiKey, options, logger) {
5642
5792
  const request = {
@@ -5648,11 +5798,9 @@ async function callOpenAICompletion(provider, apiKey, options, logger) {
5648
5798
  stream: false
5649
5799
  // For now, non-streaming only
5650
5800
  };
5651
- if (options.thinkLevel && options.thinkLevel !== "none") {
5652
- const effort = getOpenAIReasoningEffort(options.thinkLevel);
5653
- if (effort) {
5654
- request.reasoning_effort = effort;
5655
- }
5801
+ const effort = resolveOpenAIEffort(provider, options, "openai-chat");
5802
+ if (effort) {
5803
+ request.reasoning_effort = effort;
5656
5804
  }
5657
5805
  const apiUrl = buildProviderApiUrl(provider, { model: options.model, stream: false });
5658
5806
  const headers = getProviderHeaders(provider, apiKey);
@@ -5689,16 +5837,19 @@ async function callOpenAICompletion(provider, apiKey, options, logger) {
5689
5837
  }
5690
5838
  async function callAnthropicCompletion(provider, apiKey, options, logger) {
5691
5839
  const hasImages = options.messages.some((m) => m.images && m.images.length > 0);
5840
+ const reasoningWire = buildAnthropicReasoningWire(provider, options);
5692
5841
  if (hasImages) {
5693
5842
  const systemMessages = options.messages.filter((m) => m.role === "system");
5694
5843
  const nonSystemMessages = options.messages.filter((m) => m.role !== "system");
5695
5844
  const anthropicRequest2 = {
5696
5845
  model: options.model,
5697
- max_tokens: options.maxTokens ?? 16384,
5698
- temperature: options.temperature,
5846
+ max_tokens: reasoningWire.effectiveMaxTokens,
5847
+ ...reasoningWire.legacyBudgetEnabled ? {} : { temperature: options.temperature },
5699
5848
  ...systemMessages.length > 0 ? { system: systemMessages.map((m) => m.content).join("\n\n") } : {},
5700
5849
  messages: nonSystemMessages.map((m) => convertMessageToAnthropic(m)),
5701
- stream: false
5850
+ stream: false,
5851
+ ...reasoningWire.thinking ? { thinking: reasoningWire.thinking } : {},
5852
+ ...reasoningWire.outputConfig ? { output_config: reasoningWire.outputConfig } : {}
5702
5853
  };
5703
5854
  const apiUrl2 = buildProviderApiUrl(provider, { model: options.model, stream: false });
5704
5855
  const headers2 = getProviderHeaders(provider, apiKey);
@@ -5740,14 +5891,24 @@ async function callAnthropicCompletion(provider, apiKey, options, logger) {
5740
5891
  content: m.content
5741
5892
  })),
5742
5893
  // Anthropic requires max_tokens; use 16384 default if not explicitly set
5743
- max_tokens: options.maxTokens ?? 16384,
5744
- temperature: options.temperature,
5894
+ max_tokens: reasoningWire.effectiveMaxTokens,
5895
+ temperature: reasoningWire.legacyBudgetEnabled ? void 0 : options.temperature,
5745
5896
  stream: false
5746
5897
  };
5747
5898
  const config = {
5748
5899
  defaultModel: options.model
5749
5900
  };
5750
5901
  const anthropicRequest = convertOpenAIToAnthropic(openaiRequest, config);
5902
+ const anthropicRequestBody = anthropicRequest;
5903
+ if (reasoningWire.thinking) {
5904
+ anthropicRequestBody.thinking = reasoningWire.thinking;
5905
+ }
5906
+ if (reasoningWire.outputConfig) {
5907
+ anthropicRequestBody.output_config = reasoningWire.outputConfig;
5908
+ }
5909
+ if (reasoningWire.legacyBudgetEnabled) {
5910
+ delete anthropicRequestBody.temperature;
5911
+ }
5751
5912
  const apiUrl = buildProviderApiUrl(provider, { model: options.model, stream: false });
5752
5913
  const headers = getProviderHeaders(provider, apiKey);
5753
5914
  logger.info("Calling Anthropic completion API", { url: apiUrl, model: options.model });
@@ -5792,11 +5953,13 @@ async function callGeminiCompletion(provider, apiKey, options, logger) {
5792
5953
  contents.push(convertMessageToGemini(msg));
5793
5954
  }
5794
5955
  }
5956
+ const thinkingConfig = buildGeminiThinkingConfig(provider, options);
5795
5957
  const request = {
5796
5958
  contents,
5797
5959
  generationConfig: {
5798
5960
  ...options.maxTokens !== void 0 ? { maxOutputTokens: options.maxTokens } : {},
5799
- ...options.temperature !== void 0 ? { temperature: options.temperature } : {}
5961
+ ...options.temperature !== void 0 ? { temperature: options.temperature } : {},
5962
+ ...thinkingConfig ? { thinkingConfig } : {}
5800
5963
  }
5801
5964
  };
5802
5965
  if (systemInstruction) {
@@ -5867,11 +6030,9 @@ async function callOpenAIResponseCompletion(provider, apiKey, options, logger) {
5867
6030
  ...options.maxTokens !== void 0 ? { max_output_tokens: options.maxTokens } : {},
5868
6031
  ...options.temperature !== void 0 ? { temperature: options.temperature } : {}
5869
6032
  };
5870
- if (options.thinkLevel && options.thinkLevel !== "none") {
5871
- const effort = getOpenAIReasoningEffort(options.thinkLevel);
5872
- if (effort) {
5873
- request.reasoning = { effort, summary: "auto" };
5874
- }
6033
+ const responseEffort = resolveOpenAIEffort(provider, options, "openai-responses");
6034
+ if (responseEffort) {
6035
+ request.reasoning = { effort: responseEffort, summary: "auto" };
5875
6036
  }
5876
6037
  const apiUrl = buildProviderApiUrl(provider, { model: options.model, stream: false });
5877
6038
  const headers = getProviderHeaders(provider, apiKey);
@@ -5923,7 +6084,6 @@ async function callOpenAIResponseCompletion(provider, apiKey, options, logger) {
5923
6084
  }
5924
6085
 
5925
6086
  // src/completion/StreamHandler.ts
5926
- import { buildAnthropicThinking, getOpenAIReasoningEffort as getOpenAIReasoningEffort2 } from "@omnicross/contracts/thinking-config";
5927
6087
  async function streamOpenAICompletion(provider, apiKey, options, messageId, callbacks, logger) {
5928
6088
  const request = {
5929
6089
  model: options.model,
@@ -5933,11 +6093,9 @@ async function streamOpenAICompletion(provider, apiKey, options, messageId, call
5933
6093
  temperature: options.temperature,
5934
6094
  stream: true
5935
6095
  };
5936
- if (options.thinkLevel && options.thinkLevel !== "none") {
5937
- const effort = getOpenAIReasoningEffort2(options.thinkLevel);
5938
- if (effort) {
5939
- request.reasoning_effort = effort;
5940
- }
6096
+ const effort = resolveOpenAIEffort(provider, options, "openai-chat");
6097
+ if (effort) {
6098
+ request.reasoning_effort = effort;
5941
6099
  }
5942
6100
  const apiUrl = buildProviderApiUrl(provider, { model: options.model, stream: true });
5943
6101
  const headers = getProviderHeaders(provider, apiKey);
@@ -5987,16 +6145,11 @@ async function streamOpenAICompletion(provider, apiKey, options, messageId, call
5987
6145
  }
5988
6146
  async function streamAnthropicCompletion(provider, apiKey, options, messageId, callbacks, logger) {
5989
6147
  const hasImages = options.messages.some((m) => m.images && m.images.length > 0);
5990
- const MAX_TOKENS_FOR_THINKING = 16384;
5991
- let effectiveMaxTokens = options.maxTokens ?? 16384;
5992
- const thinkingMaxTokens = options.thinkLevel && options.thinkLevel !== "none" ? Math.min(effectiveMaxTokens, MAX_TOKENS_FOR_THINKING) : effectiveMaxTokens;
5993
- const thinkingConfig = options.thinkLevel && options.thinkLevel !== "none" ? buildAnthropicThinking(options.model, options.thinkLevel, thinkingMaxTokens) : void 0;
5994
- if (thinkingConfig) {
5995
- effectiveMaxTokens = thinkingMaxTokens;
5996
- }
6148
+ const reasoningWire = buildAnthropicReasoningWire(provider, options);
6149
+ const effectiveMaxTokens = reasoningWire.effectiveMaxTokens;
5997
6150
  logger.debug("Anthropic thinking configuration", {
5998
6151
  thinkLevel: options.thinkLevel,
5999
- thinkingConfig,
6152
+ thinkingConfig: reasoningWire.thinking,
6000
6153
  effectiveMaxTokens
6001
6154
  });
6002
6155
  let anthropicRequest;
@@ -6007,12 +6160,15 @@ async function streamAnthropicCompletion(provider, apiKey, options, messageId, c
6007
6160
  model: options.model,
6008
6161
  max_tokens: effectiveMaxTokens,
6009
6162
  // Omit temperature when thinking is enabled (Anthropic will use default temperature=1)
6010
- ...thinkingConfig ? {} : { temperature: options.temperature },
6163
+ ...reasoningWire.legacyBudgetEnabled ? {} : { temperature: options.temperature },
6011
6164
  ...systemMessages.length > 0 ? { system: systemMessages.map((m) => m.content).join("\n\n") } : {},
6012
6165
  messages: nonSystemMessages.map((m) => convertMessageToAnthropic(m)),
6013
6166
  stream: true,
6014
- ...thinkingConfig ? { thinking: thinkingConfig } : {}
6167
+ ...reasoningWire.thinking ? { thinking: reasoningWire.thinking } : {}
6015
6168
  };
6169
+ if (reasoningWire.outputConfig) {
6170
+ anthropicRequest.output_config = reasoningWire.outputConfig;
6171
+ }
6016
6172
  } else {
6017
6173
  const config = {
6018
6174
  defaultModel: options.model
@@ -6026,12 +6182,17 @@ async function streamAnthropicCompletion(provider, apiKey, options, messageId, c
6026
6182
  // Anthropic requires max_tokens; use adjusted value
6027
6183
  max_tokens: effectiveMaxTokens,
6028
6184
  // Omit temperature when thinking is enabled (Anthropic will use default temperature=1)
6029
- temperature: thinkingConfig ? void 0 : options.temperature,
6185
+ temperature: reasoningWire.legacyBudgetEnabled ? void 0 : options.temperature,
6030
6186
  stream: true
6031
6187
  };
6032
6188
  anthropicRequest = convertOpenAIToAnthropic(openaiRequest, config);
6033
- if (thinkingConfig) {
6034
- anthropicRequest.thinking = thinkingConfig;
6189
+ if (reasoningWire.thinking) {
6190
+ anthropicRequest.thinking = reasoningWire.thinking;
6191
+ }
6192
+ if (reasoningWire.outputConfig) {
6193
+ anthropicRequest.output_config = reasoningWire.outputConfig;
6194
+ }
6195
+ if (reasoningWire.legacyBudgetEnabled) {
6035
6196
  delete anthropicRequest.temperature;
6036
6197
  }
6037
6198
  }
@@ -6097,11 +6258,13 @@ async function streamGeminiCompletion(provider, apiKey, options, messageId, call
6097
6258
  contents.push(convertMessageToGemini(msg));
6098
6259
  }
6099
6260
  }
6261
+ const thinkingConfig = buildGeminiThinkingConfig(provider, options);
6100
6262
  const request = {
6101
6263
  contents,
6102
6264
  generationConfig: {
6103
6265
  ...options.maxTokens !== void 0 ? { maxOutputTokens: options.maxTokens } : {},
6104
- ...options.temperature !== void 0 ? { temperature: options.temperature } : {}
6266
+ ...options.temperature !== void 0 ? { temperature: options.temperature } : {},
6267
+ ...thinkingConfig ? { thinkingConfig } : {}
6105
6268
  }
6106
6269
  };
6107
6270
  if (systemInstruction) {
@@ -6167,11 +6330,9 @@ async function streamOpenAIResponseCompletion(provider, apiKey, options, message
6167
6330
  ...options.maxTokens !== void 0 ? { max_output_tokens: options.maxTokens } : {},
6168
6331
  ...options.temperature !== void 0 ? { temperature: options.temperature } : {}
6169
6332
  };
6170
- if (options.thinkLevel && options.thinkLevel !== "none") {
6171
- const effort = getOpenAIReasoningEffort2(options.thinkLevel);
6172
- if (effort) {
6173
- request.reasoning = { effort, summary: "auto" };
6174
- }
6333
+ const responseEffort = resolveOpenAIEffort(provider, options, "openai-responses");
6334
+ if (responseEffort) {
6335
+ request.reasoning = { effort: responseEffort, summary: "auto" };
6175
6336
  }
6176
6337
  const apiUrl = buildProviderApiUrl(provider, { model: options.model, stream: true });
6177
6338
  const headers = getProviderHeaders(provider, apiKey);
@@ -6215,7 +6376,7 @@ async function streamOpenAIResponseCompletion(provider, apiKey, options, message
6215
6376
 
6216
6377
  // src/completion/ThinkingResolver.ts
6217
6378
  import {
6218
- buildAnthropicThinking as buildAnthropicThinking2,
6379
+ buildAnthropicThinking,
6219
6380
  calculateThinkingBudget,
6220
6381
  DEFAULT_MAX_TOKENS,
6221
6382
  getClaudeMaxTokens,
@@ -6259,7 +6420,7 @@ async function resolveThinkingBudget(getProvider, logger, providerId, modelId, m
6259
6420
  const providerName = provider?.name?.toLowerCase() || "";
6260
6421
  const apiFormat = provider ? resolveApiFormat(provider) : "openai";
6261
6422
  if (apiFormat === "anthropic" || providerName === "anthropic" || providerName.includes("claude")) {
6262
- const thinkingConfig = buildAnthropicThinking2(modelId, thinkLevel, maxTokens);
6423
+ const thinkingConfig = buildAnthropicThinking(modelId, thinkLevel, maxTokens);
6263
6424
  const adjustedMaxTokens = getClaudeMaxTokens(maxTokens, thinkingBudget) || maxTokens;
6264
6425
  logger.debug("Claude model thinking budget", {
6265
6426
  thinkingBudget,
@@ -6914,7 +7075,8 @@ async function completeWithTransformers(options, llmConfig, getProvider, resolve
6914
7075
  name: provider.name,
6915
7076
  baseUrl: provider.api_base_url,
6916
7077
  apiKey,
6917
- models: provider.models || []
7078
+ models: provider.models || [],
7079
+ modelConfigs: provider.modelConfigs
6918
7080
  };
6919
7081
  const executor = getSharedExecutor2();
6920
7082
  const { response } = await executeProviderCall({
@@ -7044,7 +7206,8 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
7044
7206
  name: provider.name,
7045
7207
  baseUrl: provider.api_base_url,
7046
7208
  apiKey,
7047
- models: provider.models || []
7209
+ models: provider.models || [],
7210
+ modelConfigs: provider.modelConfigs
7048
7211
  };
7049
7212
  const executor = getSharedExecutor2();
7050
7213
  const { response } = await executeProviderCall({