@bman654/clodex 2.12.1 → 2.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/cli.js CHANGED
@@ -382,7 +382,7 @@ import { join } from "path";
382
382
  // package.json
383
383
  var package_default = {
384
384
  name: "@bman654/clodex",
385
- version: "2.12.1",
385
+ version: "2.13.0",
386
386
  publishConfig: {
387
387
  access: "public"
388
388
  },
@@ -3895,8 +3895,8 @@ import {
3895
3895
  statSync as statSync8,
3896
3896
  unlinkSync as unlinkSync3,
3897
3897
  writeFileSync as writeFileSync6,
3898
- openSync as openSync7,
3899
- closeSync as closeSync7,
3898
+ openSync as openSync8,
3899
+ closeSync as closeSync8,
3900
3900
  realpathSync as realpathSync2
3901
3901
  } from "fs";
3902
3902
  import { homedir as homedir3 } from "os";
@@ -4821,16 +4821,19 @@ var pricing_cache_default = {
4821
4821
  ]
4822
4822
  };
4823
4823
 
4824
+ // src/data/opencode-go-models.ts
4825
+ import { randomUUID as randomUUID2 } from "crypto";
4826
+
4824
4827
  // src/data/opencode-go-models.json
4825
4828
  var opencode_go_models_default = [
4826
4829
  {
4827
4830
  id: "deepseek-v4-flash",
4828
- name: "DeepSeek V4 Flash (2x usage)",
4831
+ name: "DeepSeek V4 Flash",
4829
4832
  contextWindow: 1e6,
4830
4833
  cost: {
4831
- input: 0.07,
4832
- output: 0.14,
4833
- cache_read: 14e-4
4834
+ input: 0.15,
4835
+ output: 0.6,
4836
+ cache_read: 3e-3
4834
4837
  },
4835
4838
  modelFormat: "openai",
4836
4839
  npm: "@ai-sdk/openai-compatible",
@@ -4858,12 +4861,12 @@ var opencode_go_models_default = [
4858
4861
  },
4859
4862
  {
4860
4863
  id: "deepseek-v4-pro",
4861
- name: "DeepSeek V4 Pro",
4864
+ name: "DeepSeek V4 Pro (New)",
4862
4865
  contextWindow: 1e6,
4863
4866
  cost: {
4864
- input: 0.435,
4865
- output: 0.87,
4866
- cache_read: 3625e-6
4867
+ input: 0.66,
4868
+ output: 1.98,
4869
+ cache_read: 0.022
4867
4870
  },
4868
4871
  modelFormat: "openai",
4869
4872
  npm: "@ai-sdk/openai-compatible",
@@ -4889,6 +4892,30 @@ var opencode_go_models_default = [
4889
4892
  upstreamModelId: "deepseek-v4-pro",
4890
4893
  family: "deepseek"
4891
4894
  },
4895
+ {
4896
+ id: "deepseek-v4.1-flash",
4897
+ name: "DeepSeek V4.1 Flash",
4898
+ contextWindow: 1e6,
4899
+ cost: {
4900
+ input: 0.15,
4901
+ output: 0.6,
4902
+ cache_read: 3e-3
4903
+ },
4904
+ modelFormat: "anthropic",
4905
+ npm: "@ai-sdk/anthropic",
4906
+ apiUrl: "https://opencode.ai/zen/go",
4907
+ reasoning: true,
4908
+ modalities: [
4909
+ "text",
4910
+ "image"
4911
+ ],
4912
+ compatibility: {
4913
+ supportsCountTokens: false,
4914
+ supportsReasoningEffort: false
4915
+ },
4916
+ upstreamModelId: "deepseek-v4.1-flash",
4917
+ family: "deepseek"
4918
+ },
4892
4919
  {
4893
4920
  id: "glm-5.1",
4894
4921
  name: "GLM-5.1",
@@ -4906,10 +4933,10 @@ var opencode_go_models_default = [
4906
4933
  "text"
4907
4934
  ],
4908
4935
  compatibility: {
4936
+ supportsReasoningEffort: false,
4909
4937
  supportsStore: false,
4910
4938
  supportsDeveloperRole: false,
4911
- maxTokensField: "max_tokens",
4912
- supportsReasoningEffort: false
4939
+ maxTokensField: "max_tokens"
4913
4940
  },
4914
4941
  upstreamModelId: "glm-5.1",
4915
4942
  family: "glm"
@@ -4949,13 +4976,13 @@ var opencode_go_models_default = [
4949
4976
  },
4950
4977
  {
4951
4978
  id: "gpt-5.6-luna",
4952
- name: "GPT-5.6 Luna (2x usage)",
4979
+ name: "GPT-5.6 Luna",
4953
4980
  contextWindow: 105e4,
4954
4981
  cost: {
4955
- input: 0.1,
4956
- output: 0.6,
4957
- cache_read: 0.01,
4958
- cache_write: 0.125
4982
+ input: 0.2,
4983
+ output: 1.2,
4984
+ cache_read: 0.02,
4985
+ cache_write: 0.25
4959
4986
  },
4960
4987
  modelFormat: "openai",
4961
4988
  npm: "@ai-sdk/openai-compatible",
@@ -4965,8 +4992,6 @@ var opencode_go_models_default = [
4965
4992
  "text",
4966
4993
  "image"
4967
4994
  ],
4968
- upstreamModelId: "gpt-5.6-luna",
4969
- family: "gpt",
4970
4995
  compatibility: {
4971
4996
  reasoningEffortMap: {
4972
4997
  off: "none",
@@ -4980,7 +5005,9 @@ var opencode_go_models_default = [
4980
5005
  supportsStore: false,
4981
5006
  supportsDeveloperRole: false,
4982
5007
  maxTokensField: "max_tokens"
4983
- }
5008
+ },
5009
+ upstreamModelId: "gpt-5.6-luna",
5010
+ family: "gpt"
4984
5011
  },
4985
5012
  {
4986
5013
  id: "hy3",
@@ -5066,10 +5093,10 @@ var opencode_go_models_default = [
5066
5093
  "image"
5067
5094
  ],
5068
5095
  compatibility: {
5096
+ supportsReasoningEffort: false,
5069
5097
  supportsStore: false,
5070
5098
  supportsDeveloperRole: false,
5071
- maxTokensField: "max_tokens",
5072
- supportsReasoningEffort: false
5099
+ maxTokensField: "max_tokens"
5073
5100
  },
5074
5101
  upstreamModelId: "kimi-k2.7-code",
5075
5102
  family: "kimi"
@@ -5126,10 +5153,10 @@ var opencode_go_models_default = [
5126
5153
  "image"
5127
5154
  ],
5128
5155
  compatibility: {
5156
+ supportsReasoningEffort: false,
5129
5157
  supportsStore: false,
5130
5158
  supportsDeveloperRole: false,
5131
- maxTokensField: "max_tokens",
5132
- supportsReasoningEffort: false
5159
+ maxTokensField: "max_tokens"
5133
5160
  },
5134
5161
  upstreamModelId: "mimo-v2.5",
5135
5162
  family: "mimo"
@@ -5151,10 +5178,10 @@ var opencode_go_models_default = [
5151
5178
  "text"
5152
5179
  ],
5153
5180
  compatibility: {
5181
+ supportsReasoningEffort: false,
5154
5182
  supportsStore: false,
5155
5183
  supportsDeveloperRole: false,
5156
- maxTokensField: "max_tokens",
5157
- supportsReasoningEffort: false
5184
+ maxTokensField: "max_tokens"
5158
5185
  },
5159
5186
  upstreamModelId: "mimo-v2.5-pro",
5160
5187
  family: "mimo"
@@ -5176,10 +5203,10 @@ var opencode_go_models_default = [
5176
5203
  "text"
5177
5204
  ],
5178
5205
  compatibility: {
5206
+ supportsReasoningEffort: false,
5179
5207
  supportsStore: false,
5180
5208
  supportsDeveloperRole: false,
5181
- maxTokensField: "max_tokens",
5182
- supportsReasoningEffort: false
5209
+ maxTokensField: "max_tokens"
5183
5210
  },
5184
5211
  upstreamModelId: "minimax-m2.7",
5185
5212
  family: "minimax"
@@ -5201,12 +5228,12 @@ var opencode_go_models_default = [
5201
5228
  "text",
5202
5229
  "image"
5203
5230
  ],
5204
- upstreamModelId: "minimax-m3",
5205
- family: "minimax",
5206
5231
  compatibility: {
5207
5232
  supportsCountTokens: false,
5208
5233
  supportsReasoningEffort: false
5209
- }
5234
+ },
5235
+ upstreamModelId: "minimax-m3",
5236
+ family: "minimax"
5210
5237
  },
5211
5238
  {
5212
5239
  id: "qwen3.6-plus",
@@ -5227,10 +5254,6 @@ var opencode_go_models_default = [
5227
5254
  "image"
5228
5255
  ],
5229
5256
  compatibility: {
5230
- supportsStore: false,
5231
- supportsDeveloperRole: false,
5232
- thinkingFormat: "qwen",
5233
- maxTokensField: "max_tokens",
5234
5257
  reasoningEffortMap: {
5235
5258
  low: "low",
5236
5259
  medium: "medium",
@@ -5239,7 +5262,11 @@ var opencode_go_models_default = [
5239
5262
  max: "max",
5240
5263
  minimal: null,
5241
5264
  off: null
5242
- }
5265
+ },
5266
+ supportsStore: false,
5267
+ supportsDeveloperRole: false,
5268
+ thinkingFormat: "qwen",
5269
+ maxTokensField: "max_tokens"
5243
5270
  },
5244
5271
  upstreamModelId: "qwen3.6-plus",
5245
5272
  family: "qwen3.6"
@@ -5261,12 +5288,12 @@ var opencode_go_models_default = [
5261
5288
  modalities: [
5262
5289
  "text"
5263
5290
  ],
5264
- upstreamModelId: "qwen3.7-max",
5265
- family: "qwen3.7",
5266
5291
  compatibility: {
5267
5292
  supportsCountTokens: false,
5268
5293
  supportsReasoningEffort: false
5269
- }
5294
+ },
5295
+ upstreamModelId: "qwen3.7-max",
5296
+ family: "qwen3.7"
5270
5297
  },
5271
5298
  {
5272
5299
  id: "qwen3.7-plus",
@@ -5286,12 +5313,12 @@ var opencode_go_models_default = [
5286
5313
  "text",
5287
5314
  "image"
5288
5315
  ],
5289
- upstreamModelId: "qwen3.7-plus",
5290
- family: "qwen3.7",
5291
5316
  compatibility: {
5292
5317
  supportsCountTokens: false,
5293
5318
  supportsReasoningEffort: false
5294
- }
5319
+ },
5320
+ upstreamModelId: "qwen3.7-plus",
5321
+ family: "qwen3.7"
5295
5322
  },
5296
5323
  {
5297
5324
  id: "qwen3.8-max",
@@ -5311,12 +5338,12 @@ var opencode_go_models_default = [
5311
5338
  "text",
5312
5339
  "image"
5313
5340
  ],
5314
- upstreamModelId: "qwen3.8-max",
5315
- family: "qwen3.8",
5316
5341
  compatibility: {
5317
5342
  supportsCountTokens: false,
5318
5343
  supportsReasoningEffort: false
5319
- }
5344
+ },
5345
+ upstreamModelId: "qwen3.8-max",
5346
+ family: "qwen3.8"
5320
5347
  }
5321
5348
  ];
5322
5349
 
@@ -5328,6 +5355,13 @@ var OPENCODE_GO_ANTHROPIC_BASE_URL = "https://opencode.ai/zen/go";
5328
5355
  function buildOpenCodeGoModels() {
5329
5356
  return structuredClone(opencode_go_models_default);
5330
5357
  }
5358
+ var OPENCODE_GO_FALLBACK_SESSION_ID = randomUUID2();
5359
+ function openCodeGoSessionHeaders(model, claudeSessionId) {
5360
+ const url = String(model.apiBaseUrl ?? model.baseUrl ?? model.apiUrl ?? "");
5361
+ const isGo = model.providerId === OPENCODE_GO_PROVIDER_ID || /^https:\/\/opencode\.ai\/zen\/go(\/|$)/.test(url);
5362
+ if (!isGo) return void 0;
5363
+ return { "x-opencode-session": claudeSessionId ?? OPENCODE_GO_FALLBACK_SESSION_ID };
5364
+ }
5331
5365
 
5332
5366
  // src/provider-templates.ts
5333
5367
  async function verifyOpenCodeGoCredential(apiKey) {
@@ -5338,7 +5372,12 @@ async function verifyOpenCodeGoCredential(apiKey) {
5338
5372
  method: "POST",
5339
5373
  headers: {
5340
5374
  "Content-Type": "application/json",
5341
- Authorization: `Bearer ${apiKey}`
5375
+ Authorization: `Bearer ${apiKey}`,
5376
+ // Go answers `MissingSessionID` to any request without a session header,
5377
+ // and whether it validates the key BEFORE that check is not something we
5378
+ // have observed. Sending the header removes the question: the probe then
5379
+ // cannot mistake a missing-session rejection for a verdict on the key.
5380
+ ...openCodeGoSessionHeaders({ providerId: OPENCODE_GO_PROVIDER_ID }, void 0)
5342
5381
  },
5343
5382
  body: JSON.stringify({ model: model.upstreamModelId ?? model.id }),
5344
5383
  // This is the FIRST thing a user hits after pasting a key, and it runs
@@ -8081,6 +8120,8 @@ import { wrapLanguageModel, extractReasoningMiddleware } from "ai";
8081
8120
 
8082
8121
  // src/oauth/responses-websocket.ts
8083
8122
  import { createHash as createHash6 } from "crypto";
8123
+ import { closeSync as closeSync6, openSync as openSync6 } from "fs";
8124
+ import { devNull } from "os";
8084
8125
  import { AsyncLocalStorage } from "async_hooks";
8085
8126
 
8086
8127
  // src/outbound-proxy.ts
@@ -8847,8 +8888,8 @@ var FAILURE_EVENT_TYPES = /* @__PURE__ */ new Set(["error", "response.failed", "
8847
8888
  var RESPONSES_WS_HARD_TTL_MS = 55 * 6e4;
8848
8889
  var RESPONSES_WS_IDLE_TTL_MS = 30 * 6e4;
8849
8890
  var RESPONSES_WS_NURSERY_IDLE_TTL_MS = 5 * 6e4;
8850
- var RESPONSES_WS_MAX_CONNECTIONS = 64;
8851
- var RESPONSES_WS_MAX_NURSERY_CONNECTIONS = 48;
8891
+ var RESPONSES_WS_MAX_CONNECTIONS = Number.POSITIVE_INFINITY;
8892
+ var RESPONSES_WS_MAX_NURSERY_CONNECTIONS = Number.POSITIVE_INFINITY;
8852
8893
  var diagnosticContext = new AsyncLocalStorage();
8853
8894
  function withResponsesWebSocketDiagnosticContext(context, fn) {
8854
8895
  return diagnosticContext.run(context, fn);
@@ -8998,16 +9039,64 @@ function responsesWebSocketPartitionKey(wsUrl, payload, options = {}, authorizat
8998
9039
  function inputArray(payload) {
8999
9040
  return Array.isArray(payload.input) ? payload.input : [];
9000
9041
  }
9001
- function normalizeToolCallJson(value) {
9002
- if (Array.isArray(value)) return value.map(normalizeToolCallJson);
9042
+ function toolSchemaDefaults(payload) {
9043
+ const defaults = /* @__PURE__ */ new Map();
9044
+ const add = (tool3) => {
9045
+ if (!tool3 || typeof tool3 !== "object") return;
9046
+ const record = tool3;
9047
+ if (record.type === "namespace" && Array.isArray(record.tools)) {
9048
+ for (const nested of record.tools) add(nested);
9049
+ return;
9050
+ }
9051
+ if (record.type !== "function" || typeof record.name !== "string") return;
9052
+ const parameters = record.parameters;
9053
+ const properties = parameters && typeof parameters === "object" ? parameters.properties : void 0;
9054
+ if (!properties || typeof properties !== "object") return;
9055
+ const perTool = /* @__PURE__ */ new Map();
9056
+ for (const [prop, schema] of Object.entries(properties)) {
9057
+ if (schema && typeof schema === "object" && "default" in schema) {
9058
+ perTool.set(prop, canonicalJson(schema.default));
9059
+ }
9060
+ }
9061
+ if (perTool.size) defaults.set(record.name, perTool);
9062
+ };
9063
+ if (Array.isArray(payload.tools)) for (const tool3 of payload.tools) add(tool3);
9064
+ return defaults;
9065
+ }
9066
+ function toolSchemaDefaultsFingerprint(defaults) {
9067
+ if (!defaults.size) return "none";
9068
+ const tuples = [...defaults.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([name, perTool]) => [
9069
+ name,
9070
+ [...perTool.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)
9071
+ ]);
9072
+ return createHash6("sha256").update(JSON.stringify(tuples)).digest("hex").slice(0, 16);
9073
+ }
9074
+ function stripSchemaDefaults(name, args, defaults) {
9075
+ if (!defaults) return args;
9076
+ if (typeof name !== "string" || !args || typeof args !== "object" || Array.isArray(args)) return args;
9077
+ const perTool = defaults.get(name);
9078
+ if (!perTool) return args;
9079
+ const out = {};
9080
+ for (const [key, value] of Object.entries(args)) {
9081
+ const expected = perTool.get(key);
9082
+ if (expected !== void 0 && canonicalJson(value) === expected) continue;
9083
+ out[key] = value;
9084
+ }
9085
+ return out;
9086
+ }
9087
+ function normalizeToolCallJson(value, defaults) {
9088
+ if (Array.isArray(value)) return value.map((item) => normalizeToolCallJson(item, defaults));
9003
9089
  if (!value || typeof value !== "object") return value;
9004
9090
  const record = value;
9005
9091
  const out = {};
9006
- for (const [key, child] of Object.entries(record)) out[key] = normalizeToolCallJson(child);
9092
+ for (const [key, child] of Object.entries(record)) out[key] = normalizeToolCallJson(child, defaults);
9007
9093
  const jsonField = record.type === "function_call" ? "arguments" : record.type === "custom_tool_call" ? "input" : void 0;
9008
9094
  if (jsonField && typeof record[jsonField] === "string") {
9009
9095
  try {
9010
- out[jsonField] = canonicalJson(JSON.parse(record[jsonField]));
9096
+ const parsed = JSON.parse(record[jsonField]);
9097
+ out[jsonField] = canonicalJson(
9098
+ jsonField === "arguments" ? stripSchemaDefaults(record.name, parsed, defaults) : parsed
9099
+ );
9011
9100
  } catch {
9012
9101
  }
9013
9102
  }
@@ -9018,8 +9107,8 @@ function normalizeToolCallJson(value) {
9018
9107
  }
9019
9108
  return out;
9020
9109
  }
9021
- function arraysEqual(left, right) {
9022
- return canonicalJson(normalizeToolCallJson(left)) === canonicalJson(normalizeToolCallJson(right));
9110
+ function arraysEqual(left, right, defaults) {
9111
+ return canonicalJson(normalizeToolCallJson(left, defaults)) === canonicalJson(normalizeToolCallJson(right, defaults));
9023
9112
  }
9024
9113
  function conversationItemKind(value) {
9025
9114
  if (!value || typeof value !== "object") return typeof value;
@@ -9028,17 +9117,17 @@ function conversationItemKind(value) {
9028
9117
  if (typeof record.role === "string") return record.role;
9029
9118
  return "object";
9030
9119
  }
9031
- function conversationItemHash(value) {
9032
- return createHash6("sha256").update(canonicalJson(normalizeToolCallJson(value))).digest("hex").slice(0, 16);
9120
+ function conversationItemHash(value, defaults) {
9121
+ return createHash6("sha256").update(canonicalJson(normalizeToolCallJson(value, defaults))).digest("hex").slice(0, 16);
9033
9122
  }
9034
- function reasoningNormalizationGap(expected, actual) {
9123
+ function reasoningNormalizationGap(expected, actual, defaults) {
9035
9124
  if (conversationItemKind(expected) !== "reasoning" || conversationItemKind(actual) !== "reasoning") return void 0;
9036
9125
  const left = expected;
9037
9126
  const right = actual;
9038
9127
  const blob = left.encrypted_content;
9039
9128
  if (typeof blob !== "string" || !blob || blob !== right.encrypted_content) return void 0;
9040
- const normalizedLeft = normalizeToolCallJson(left);
9041
- const normalizedRight = normalizeToolCallJson(right);
9129
+ const normalizedLeft = normalizeToolCallJson(left, defaults);
9130
+ const normalizedRight = normalizeToolCallJson(right, defaults);
9042
9131
  const fields = [.../* @__PURE__ */ new Set([...Object.keys(normalizedLeft), ...Object.keys(normalizedRight)])].sort().filter((key) => canonicalJson(normalizedLeft[key]) !== canonicalJson(normalizedRight[key]));
9043
9132
  return fields.length ? fields : void 0;
9044
9133
  }
@@ -9086,7 +9175,7 @@ function warnReasoningNormalizationGap(fields, log12) {
9086
9175
  emitParentNotice("clodex: warning: further reasoning-normalization warnings suppressed.");
9087
9176
  }
9088
9177
  }
9089
- function toolArgumentNormalizationGap(expected, actual, requiredProps) {
9178
+ function toolArgumentNormalizationGap(expected, actual, defaults, requiredProps) {
9090
9179
  if (conversationItemKind(expected) !== "function_call") return void 0;
9091
9180
  if (conversationItemKind(actual) !== "function_call") return void 0;
9092
9181
  const left = expected;
@@ -9094,7 +9183,7 @@ function toolArgumentNormalizationGap(expected, actual, requiredProps) {
9094
9183
  const callId = left.call_id;
9095
9184
  if (typeof callId !== "string" || !callId || callId !== right.call_id) return void 0;
9096
9185
  if (typeof left.name !== "string" || left.name !== right.name) return void 0;
9097
- if (canonicalJson(normalizeToolCallJson(left)) === canonicalJson(normalizeToolCallJson(right))) {
9186
+ if (canonicalJson(normalizeToolCallJson(left, defaults)) === canonicalJson(normalizeToolCallJson(right, defaults))) {
9098
9187
  return void 0;
9099
9188
  }
9100
9189
  const required = requiredProps().get(left.name);
@@ -9105,8 +9194,8 @@ function toolArgumentNormalizationGap(expected, actual, requiredProps) {
9105
9194
  const parsed = raw === "" ? {} : JSON.parse(raw);
9106
9195
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
9107
9196
  return canonicalJson({
9108
- ...normalizeToolCallJson(item),
9109
- arguments: canonicalJson(sanitizeToolInput(parsed, required))
9197
+ ...normalizeToolCallJson(item, defaults),
9198
+ arguments: canonicalJson(stripSchemaDefaults(item.name, sanitizeToolInput(parsed, required), defaults))
9110
9199
  });
9111
9200
  } catch {
9112
9201
  return void 0;
@@ -9137,7 +9226,7 @@ function warnToolArgumentNormalizationGap(gap, log12) {
9137
9226
  emitParentNotice("clodex: warning: further tool-argument normalization warnings suppressed.");
9138
9227
  }
9139
9228
  }
9140
- function continuationMismatchDetails(entry, payload, log12, warnOnGap = false, deferWarnings) {
9229
+ function continuationMismatchDetails(entry, payload, defaults, log12, warnOnGap = false, deferWarnings) {
9141
9230
  const raise = (warn) => {
9142
9231
  if (deferWarnings) deferWarnings.push(warn);
9143
9232
  else warn();
@@ -9147,14 +9236,14 @@ function continuationMismatchDetails(entry, payload, log12, warnOnGap = false, d
9147
9236
  const comparable = Math.min(full.length, prefix.length);
9148
9237
  let mismatch = comparable;
9149
9238
  for (let index = 0; index < comparable; index += 1) {
9150
- if (!arraysEqual([full[index]], [prefix[index]])) {
9239
+ if (!arraysEqual([full[index]], [prefix[index]], defaults)) {
9151
9240
  mismatch = index;
9152
9241
  break;
9153
9242
  }
9154
9243
  }
9155
9244
  const expected = mismatch < prefix.length ? prefix[mismatch] : void 0;
9156
9245
  const actual = mismatch < full.length ? full[mismatch] : void 0;
9157
- const reasoningGap = reasoningNormalizationGap(expected, actual);
9246
+ const reasoningGap = reasoningNormalizationGap(expected, actual, defaults);
9158
9247
  if (reasoningGap && warnOnGap) raise(() => warnReasoningNormalizationGap(reasoningGap, log12));
9159
9248
  let gapExpected = expected;
9160
9249
  if (conversationItemKind(expected) === "reasoning" && conversationItemKind(actual) === "function_call") {
@@ -9170,6 +9259,7 @@ function continuationMismatchDetails(entry, payload, log12, warnOnGap = false, d
9170
9259
  toolArgumentGap = toolArgumentNormalizationGap(
9171
9260
  gapExpected,
9172
9261
  actual,
9262
+ defaults,
9173
9263
  // The head's own schema when it has one; the current turn's tools are only a
9174
9264
  // fallback for a head that predates the snapshot (see headRequiredToolProps).
9175
9265
  () => entry.headRequiredToolProps ?? requiredToolProps(payload)
@@ -9191,8 +9281,8 @@ function continuationMismatchDetails(entry, payload, log12, warnOnGap = false, d
9191
9281
  firstMismatch: mismatch,
9192
9282
  expectedKind: expected === void 0 ? "none" : conversationItemKind(expected),
9193
9283
  actualKind: actual === void 0 ? "none" : conversationItemKind(actual),
9194
- ...expected !== void 0 ? { expectedHash: conversationItemHash(expected) } : {},
9195
- ...actual !== void 0 ? { actualHash: conversationItemHash(actual) } : {},
9284
+ ...expected !== void 0 ? { expectedHash: conversationItemHash(expected, defaults) } : {},
9285
+ ...actual !== void 0 ? { actualHash: conversationItemHash(actual, defaults) } : {},
9196
9286
  ...reasoningGap ? {
9197
9287
  reasoningNormalizationGap: reasoningGap,
9198
9288
  reasoningGapShape: reasoningGapShape(
@@ -9206,8 +9296,8 @@ function continuationMismatchDetails(entry, payload, log12, warnOnGap = false, d
9206
9296
  ...toolArgumentGap ? { toolArgumentNormalizationGap: toolArgumentGap } : {}
9207
9297
  };
9208
9298
  }
9209
- function continuationMismatchSummary(entry, payload, log12, mismatchDump = false, precomputedDetails) {
9210
- const details = precomputedDetails ?? continuationMismatchDetails(entry, payload, log12, true);
9299
+ function continuationMismatchSummary(entry, payload, defaults, log12, mismatchDump = false, precomputedDetails) {
9300
+ const details = precomputedDetails ?? continuationMismatchDetails(entry, payload, defaults, log12, true);
9211
9301
  let summary = `full_items=${details.fullItems} expected_prefix_items=${details.expectedPrefixItems} first_mismatch=${details.firstMismatch} expected=${details.expectedKind} actual=${details.actualKind}`;
9212
9302
  if (details.expectedHash || details.actualHash) {
9213
9303
  summary += ` expected_hash=${details.expectedHash ?? "none"} actual_hash=${details.actualHash ?? "none"}`;
@@ -9215,21 +9305,21 @@ function continuationMismatchSummary(entry, payload, log12, mismatchDump = false
9215
9305
  const full = inputArray(payload);
9216
9306
  const prefix = [...entry.requestInput ?? [], ...entry.expectedAssistant ?? []];
9217
9307
  const index = details.firstMismatch;
9218
- log12(`mismatch dump expected[${index}]: ${mismatchDumpLine(prefix, index)}`);
9219
- log12(`mismatch dump actual[${index}]: ${mismatchDumpLine(full, index)}`);
9308
+ log12(`mismatch dump expected[${index}]: ${mismatchDumpLine(prefix, index, defaults)}`);
9309
+ log12(`mismatch dump actual[${index}]: ${mismatchDumpLine(full, index, defaults)}`);
9220
9310
  }
9221
9311
  }
9222
9312
  return summary;
9223
9313
  }
9224
- function mismatchDumpLine(items, index) {
9314
+ function mismatchDumpLine(items, index, defaults) {
9225
9315
  if (index >= items.length) return "(absent)";
9226
- const line = canonicalJson(normalizeToolCallJson(items[index]));
9316
+ const line = canonicalJson(normalizeToolCallJson(items[index], defaults));
9227
9317
  const max = 2e3;
9228
9318
  const marker = " [truncated]";
9229
9319
  return line.length <= max ? line : line.slice(0, max - marker.length) + marker;
9230
9320
  }
9231
- function canonicalItemStrings(items) {
9232
- return items.map((item) => canonicalJson(normalizeToolCallJson([item])));
9321
+ function canonicalItemStrings(items, defaults) {
9322
+ return items.map((item) => canonicalJson(normalizeToolCallJson([item], defaults)));
9233
9323
  }
9234
9324
  function isPrefixOrEqual(head, client) {
9235
9325
  if (client.length < head.length) return false;
@@ -9241,16 +9331,24 @@ function isPrefixOrEqual(head, client) {
9241
9331
  function isStrictPrefix(head, client) {
9242
9332
  return client.length > head.length && isPrefixOrEqual(head, client);
9243
9333
  }
9244
- function continuationMatch(entry, payload, clientItems) {
9334
+ function continuationMatch(entry, payload, clientItems, defaults, defaultsId) {
9245
9335
  if (!entry.responseId || !entry.requestInput || !entry.expectedAssistant) return void 0;
9246
9336
  const full = inputArray(payload);
9247
- entry.canonicalPrefix ??= canonicalItemStrings([...entry.requestInput, ...entry.expectedAssistant]);
9337
+ if (entry.canonicalToolDefaultsId !== defaultsId) {
9338
+ entry.canonicalPrefix = void 0;
9339
+ entry.canonicalEchoablePrefix = void 0;
9340
+ entry.canonicalToolDefaultsId = defaultsId;
9341
+ }
9342
+ entry.canonicalPrefix ??= canonicalItemStrings(
9343
+ [...entry.requestInput, ...entry.expectedAssistant],
9344
+ defaults
9345
+ );
9248
9346
  if (isStrictPrefix(entry.canonicalPrefix, clientItems)) {
9249
9347
  return { delta: full.slice(entry.canonicalPrefix.length), mode: "exact" };
9250
9348
  }
9251
9349
  const echoedAssistant = entry.expectedAssistant.filter((item) => conversationItemKind(item) !== "reasoning");
9252
9350
  if (echoedAssistant.length === entry.expectedAssistant.length) return void 0;
9253
- entry.canonicalEchoablePrefix ??= canonicalItemStrings([...entry.requestInput, ...echoedAssistant]);
9351
+ entry.canonicalEchoablePrefix ??= canonicalItemStrings([...entry.requestInput, ...echoedAssistant], defaults);
9254
9352
  if (!isStrictPrefix(entry.canonicalEchoablePrefix, clientItems)) return void 0;
9255
9353
  return { delta: full.slice(entry.canonicalEchoablePrefix.length), mode: "omitted_reasoning" };
9256
9354
  }
@@ -9749,6 +9847,64 @@ function evictOldestIdleGeneration(generation, maxConnections, reason) {
9749
9847
  }
9750
9848
  return evictions;
9751
9849
  }
9850
+ var DESCRIPTOR_EXHAUSTION_CODES = /* @__PURE__ */ new Set(["EMFILE", "ENFILE"]);
9851
+ function isDescriptorExhaustion(code) {
9852
+ return typeof code === "string" && DESCRIPTOR_EXHAUSTION_CODES.has(code);
9853
+ }
9854
+ function descriptorExhaustionCode(error) {
9855
+ const code = error.code;
9856
+ if (isDescriptorExhaustion(code)) return code;
9857
+ try {
9858
+ closeSync6(openSync6(devNull, "r"));
9859
+ return void 0;
9860
+ } catch (probe) {
9861
+ const probeCode = probe.code;
9862
+ return isDescriptorExhaustion(probeCode) ? probeCode : void 0;
9863
+ }
9864
+ }
9865
+ var descriptorExhaustionNoticed = false;
9866
+ function shedIdleConnectionsForDescriptors(failing, ctx, code, socketErrorCode) {
9867
+ const registered = connectionEntries().filter((entry) => entry !== failing);
9868
+ const idle = registered.filter((entry) => !entry.inFlight && entry.generation !== "isolated").sort((left, right) => left.lastUsedAt - right.lastUsedAt);
9869
+ for (const victim of idle) {
9870
+ const idleMs = Math.max(0, victim.options.now() - victim.lastUsedAt);
9871
+ victim.debug(
9872
+ `shedding idle ${victim.generation} connection after ${code}: connection=${victim.debugId} idle_ms=${idleMs} reason=descriptor_exhaustion`
9873
+ );
9874
+ victim.inFlight = false;
9875
+ victim.current = void 0;
9876
+ unregisterEntry(victim);
9877
+ try {
9878
+ victim.socket.terminate();
9879
+ } catch {
9880
+ }
9881
+ }
9882
+ failing.debug(
9883
+ `${code} opening connection=${failing.debugId}: registered=${registered.length} shed=${idle.length}` + (socketErrorCode && socketErrorCode !== code ? ` reported_as=${socketErrorCode}` : "")
9884
+ );
9885
+ emitContextDiagnostic(failing, ctx, {
9886
+ event: "ws_descriptor_exhaustion",
9887
+ code,
9888
+ detectedBy: socketErrorCode === code ? "error_code" : "descriptor_probe",
9889
+ socketErrorCode: boundedDiagnosticIdentifier(socketErrorCode),
9890
+ heldConnections: registered.length,
9891
+ shedConnections: idle.length
9892
+ });
9893
+ if (descriptorExhaustionNoticed) return;
9894
+ descriptorExhaustionNoticed = true;
9895
+ emitParentNotice(
9896
+ `clodex: warning: ${descriptorLimitName(code)} was reached (${code}) while opening a ChatGPT connection. clodex had ${registered.length} pooled connection(s) registered and closed ${idle.length} idle one(s) to recover; each parallel conversation keeps one open. ${descriptorLimitRemedy(code)} Further open-file warnings suppressed.`
9897
+ );
9898
+ }
9899
+ function descriptorLimitName(code) {
9900
+ return code === "ENFILE" ? "the system-wide open-file limit" : "this process's open-file limit";
9901
+ }
9902
+ function descriptorLimitRemedy(code) {
9903
+ return code === "ENFILE" ? "Close other programs holding many files, or raise the system-wide file limit, if this recurs." : "Raise it with `ulimit -n` in the shell that starts clodex (or the service limit for a launchd/systemd-managed server) if this recurs.";
9904
+ }
9905
+ function descriptorExhaustionMessage(code, registered) {
9906
+ return `${descriptorLimitName(code)} was reached (${code}) while opening a ChatGPT connection with ${registered} pooled connection(s) registered; ${descriptorLimitRemedy(code)}`;
9907
+ }
9752
9908
  function isModelDataEvent(type) {
9753
9909
  return Boolean(type && (type.includes(".delta") || type === "response.output_item.added" || type === "response.output_item.done"));
9754
9910
  }
@@ -10081,13 +10237,21 @@ function createConnection(WebSocket, wsUrl, headers, persistent, key, options, d
10081
10237
  socket.on("error", (error) => {
10082
10238
  const ctx = entry.current;
10083
10239
  if (ctx) {
10240
+ const socketErrorCode = error.code;
10084
10241
  const details = {
10085
10242
  source: "socket_error",
10086
10243
  socketErrorName: boundedDiagnosticIdentifier(error.name),
10087
- socketErrorCode: boundedDiagnosticIdentifier(error.code),
10244
+ socketErrorCode: boundedDiagnosticIdentifier(socketErrorCode),
10088
10245
  ...diagnosticTextFingerprint("errorMessage", error.message)
10089
10246
  };
10090
- handleTransportFailure(entry, ctx, error.message, details);
10247
+ let message = error.message;
10248
+ const exhaustion = entry.open ? void 0 : descriptorExhaustionCode(error);
10249
+ if (exhaustion) {
10250
+ const registered = connectionEntries().filter((other) => other !== entry).length;
10251
+ message = descriptorExhaustionMessage(exhaustion, registered);
10252
+ shedIdleConnectionsForDescriptors(entry, ctx, exhaustion, socketErrorCode);
10253
+ }
10254
+ handleTransportFailure(entry, ctx, message, details);
10091
10255
  } else deleteEntry(entry);
10092
10256
  });
10093
10257
  socket.on("close", (code, reason) => {
@@ -10108,13 +10272,16 @@ function createConnection(WebSocket, wsUrl, headers, persistent, key, options, d
10108
10272
  });
10109
10273
  return entry;
10110
10274
  }
10275
+ function diagnosticCap(cap) {
10276
+ return Number.isFinite(cap) ? cap : null;
10277
+ }
10111
10278
  function envConnectionCap(name, log12) {
10112
10279
  const raw = process.env[name];
10113
10280
  if (raw === void 0 || raw.trim() === "") return void 0;
10114
10281
  const value = Number(raw.trim());
10115
- if (!Number.isInteger(value) || value < 1 || value > 1024) {
10282
+ if (!Number.isInteger(value) || value < 1) {
10116
10283
  try {
10117
- log12?.(`ws: ignoring ${name}=${raw} (expected an integer between 1 and 1024)`);
10284
+ log12?.(`ws: ignoring ${name}=${raw} (expected a positive integer)`);
10118
10285
  } catch {
10119
10286
  }
10120
10287
  return void 0;
@@ -10159,13 +10326,15 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
10159
10326
  authorizationFingerprint,
10160
10327
  claudeAgentId
10161
10328
  );
10329
+ const requestToolDefaults = toolSchemaDefaults(payload);
10330
+ const requestToolDefaultsId = toolSchemaDefaultsFingerprint(requestToolDefaults);
10162
10331
  const promptFingerprint = responsesWebSocketPromptFingerprint(payload);
10163
10332
  const promptFieldHashes = responsesWebSocketPromptFieldHashes(payload);
10164
10333
  const instructionsSnapshot = instructionsFromPayload(payload);
10165
10334
  let now = resolvedOptions.now();
10166
10335
  const evictions = cleanupExpiredConnections(now);
10167
10336
  let canonicalClientItems;
10168
- const clientItems = () => canonicalClientItems ??= canonicalItemStrings(inputArray(payload));
10337
+ const clientItems = () => canonicalClientItems ??= canonicalItemStrings(inputArray(payload), requestToolDefaults);
10169
10338
  const scanForHeads = () => {
10170
10339
  const scanned = partitionKey ? connectionEntries(partitionKey) : [];
10171
10340
  const idle = scanned.filter((entry) => !entry.inFlight);
@@ -10173,16 +10342,32 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
10173
10342
  return {
10174
10343
  candidates: scanned,
10175
10344
  idleCandidates: idle,
10176
- matches: idle.map((entry) => ({ entry, match: continuationMatch(entry, payload, canonical) })).filter((candidate) => candidate.match !== void 0).sort((left, right) => left.match.delta.length - right.match.delta.length || (left.match.mode === right.match.mode ? 0 : left.match.mode === "exact" ? -1 : 1))
10345
+ matches: idle.map((entry) => ({
10346
+ entry,
10347
+ match: continuationMatch(entry, payload, canonical, requestToolDefaults, requestToolDefaultsId)
10348
+ })).filter((candidate) => candidate.match !== void 0).sort((left, right) => left.match.delta.length - right.match.delta.length || (left.match.mode === right.match.mode ? 0 : left.match.mode === "exact" ? -1 : 1))
10177
10349
  };
10178
10350
  };
10179
10351
  const couldPrecedeThisRequest = (entry) => {
10180
10352
  if (entry.responseId && entry.requestInput && entry.expectedAssistant) {
10181
- return continuationMatch(entry, payload, clientItems()) !== void 0;
10353
+ return continuationMatch(
10354
+ entry,
10355
+ payload,
10356
+ clientItems(),
10357
+ requestToolDefaults,
10358
+ requestToolDefaultsId
10359
+ ) !== void 0;
10182
10360
  }
10183
10361
  const streaming = entry.current;
10184
10362
  if (!streaming) return true;
10185
- streaming.canonicalInput ??= canonicalItemStrings(inputArray(streaming.originalPayload));
10363
+ if (streaming.canonicalInputToolDefaultsId !== requestToolDefaultsId) {
10364
+ streaming.canonicalInput = void 0;
10365
+ streaming.canonicalInputToolDefaultsId = requestToolDefaultsId;
10366
+ }
10367
+ streaming.canonicalInput ??= canonicalItemStrings(
10368
+ inputArray(streaming.originalPayload),
10369
+ requestToolDefaults
10370
+ );
10186
10371
  return isPrefixOrEqual(streaming.canonicalInput, clientItems());
10187
10372
  };
10188
10373
  const blockingHead = (entries) => entries.find((entry) => entry.inFlight && couldPrecedeThisRequest(entry));
@@ -10240,6 +10425,7 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
10240
10425
  const diagnosticMismatch = continuationMismatchDetails(
10241
10426
  diagnosticEntry,
10242
10427
  payload,
10428
+ requestToolDefaults,
10243
10429
  debug,
10244
10430
  true,
10245
10431
  deferredMismatchWarnings
@@ -10249,13 +10435,21 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
10249
10435
  if (candidate === diagnosticEntry) continue;
10250
10436
  candidateMismatchDetails.set(
10251
10437
  candidate,
10252
- continuationMismatchDetails(candidate, payload, debug, true, deferredMismatchWarnings)
10438
+ continuationMismatchDetails(
10439
+ candidate,
10440
+ payload,
10441
+ requestToolDefaults,
10442
+ debug,
10443
+ true,
10444
+ deferredMismatchWarnings
10445
+ )
10253
10446
  );
10254
10447
  }
10255
10448
  debug(
10256
10449
  `history mismatch starting an additional chain; retained ${candidates.length} existing head(s) (${continuationMismatchSummary(
10257
10450
  diagnosticEntry,
10258
10451
  payload,
10452
+ requestToolDefaults,
10259
10453
  debug,
10260
10454
  mismatchDump,
10261
10455
  diagnosticMismatch
@@ -10379,7 +10573,7 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
10379
10573
  input: {
10380
10574
  count: requestInput.length,
10381
10575
  kinds: requestInput.map(conversationItemKind),
10382
- hashes: requestInput.map(conversationItemHash)
10576
+ hashes: requestInput.map((item) => conversationItemHash(item, requestToolDefaults))
10383
10577
  },
10384
10578
  candidateCount: candidates.length,
10385
10579
  idleCandidateCount: idleCandidates.length,
@@ -10387,8 +10581,10 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
10387
10581
  activeConnectionCount: connectionCount(),
10388
10582
  nurseryConnectionCount: connectionCountByGeneration("nursery"),
10389
10583
  establishedConnectionCount: connectionCountByGeneration("established"),
10390
- maxConnections: resolvedOptions.maxConnections,
10391
- maxNurseryConnections: resolvedOptions.maxNurseryConnections,
10584
+ // `null` is unbounded, the shipped default. A number is a finite cap on
10585
+ // the idle pool from an env or programmatic override.
10586
+ maxConnections: diagnosticCap(resolvedOptions.maxConnections),
10587
+ maxNurseryConnections: diagnosticCap(resolvedOptions.maxNurseryConnections),
10392
10588
  selectedConnectionId: selected?.debugId,
10393
10589
  selectedGeneration: selected?.generation,
10394
10590
  continuationMatchMode: selectedMatch?.mode,
@@ -10412,7 +10608,7 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
10412
10608
  ttlPausedMs: entry.ttlPausedMs,
10413
10609
  idleMs: Math.max(0, now - entry.lastUsedAt),
10414
10610
  promptChanges: changedPromptFields(entry.promptFieldHashes, promptFieldHashes),
10415
- mismatch: candidateMismatchDetails?.get(entry) ?? continuationMismatchDetails(entry, payload, debug)
10611
+ mismatch: candidateMismatchDetails?.get(entry) ?? continuationMismatchDetails(entry, payload, requestToolDefaults, debug)
10416
10612
  })),
10417
10613
  evictions
10418
10614
  }, diagnosticCorrelation);
@@ -10492,7 +10688,7 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
10492
10688
  }
10493
10689
 
10494
10690
  // src/oauth/claude-identity.ts
10495
- import { createHash as createHash7, randomUUID as randomUUID2 } from "crypto";
10691
+ import { createHash as createHash7, randomUUID as randomUUID3 } from "crypto";
10496
10692
  var CLAUDE_CODE_CLI_VERSION = "2.1.195";
10497
10693
  var CLAUDE_CODE_USER_AGENT = `claude-cli/${CLAUDE_CODE_CLI_VERSION} (external, cli)`;
10498
10694
  var CLAUDE_CODE_ENTRYPOINT = process.env.CLAUDE_CODE_ENTRYPOINT ?? "cli";
@@ -10501,7 +10697,7 @@ var sessionCache = /* @__PURE__ */ new Map();
10501
10697
  function getOrCreateSessionId(seed) {
10502
10698
  let id = sessionCache.get(seed);
10503
10699
  if (!id) {
10504
- id = randomUUID2();
10700
+ id = randomUUID3();
10505
10701
  sessionCache.set(seed, id);
10506
10702
  }
10507
10703
  return id;
@@ -11425,7 +11621,7 @@ function thinkingProviderOptions(npm) {
11425
11621
 
11426
11622
  // src/proxy.ts
11427
11623
  import { createServer } from "http";
11428
- import { appendFileSync as appendFileSync2, openSync as openSync6, writeSync as writeSync5, closeSync as closeSync6 } from "fs";
11624
+ import { appendFileSync as appendFileSync2, openSync as openSync7, writeSync as writeSync5, closeSync as closeSync7 } from "fs";
11429
11625
 
11430
11626
  // src/http-utils.ts
11431
11627
  import * as zlib from "zlib";
@@ -11849,7 +12045,7 @@ async function relayAnthropicMessages(res, messagesUrl, body, apiKey, clientWant
11849
12045
  }
11850
12046
 
11851
12047
  // src/proxy.ts
11852
- import { randomUUID as randomUUID3 } from "crypto";
12048
+ import { randomUUID as randomUUID4 } from "crypto";
11853
12049
 
11854
12050
  // src/sdk-adapter.ts
11855
12051
  import { createHash as createHash8 } from "crypto";
@@ -13223,12 +13419,12 @@ function createTranslationLifecycle(logPath, requestId, claudeSessionId, modelId
13223
13419
  function appendSecureLog(logPath, line) {
13224
13420
  const redacted = redactTraceLine(line);
13225
13421
  try {
13226
- const fd = openSync6(logPath, "a", 384);
13422
+ const fd = openSync7(logPath, "a", 384);
13227
13423
  try {
13228
13424
  writeSync5(fd, `${(/* @__PURE__ */ new Date()).toISOString()} ${redacted}
13229
13425
  `);
13230
13426
  } finally {
13231
- closeSync6(fd);
13427
+ closeSync7(fd);
13232
13428
  }
13233
13429
  } catch {
13234
13430
  try {
@@ -13275,7 +13471,7 @@ function configuredAliasLookupNames(alias) {
13275
13471
  }))].map(normalizeRouteLookupId);
13276
13472
  }
13277
13473
  async function startProxyCatalog(routes, defaultAliasId, debug = false, inferenceLogPath, debugLogPath, webSocketDiagnosticsLogPath, modelAliases) {
13278
- const proxyToken = randomUUID3();
13474
+ const proxyToken = randomUUID4();
13279
13475
  silenceSdkWarnings();
13280
13476
  if (routes.length === 0) {
13281
13477
  throw new Error("Proxy catalog requires at least one route");
@@ -13439,6 +13635,14 @@ async function startProxyCatalog(routes, defaultAliasId, debug = false, inferenc
13439
13635
  const isOAuth = routeAuthType === "oauth";
13440
13636
  let effectiveBeta = inboundBeta;
13441
13637
  let claudeCodeSessionId;
13638
+ const inboundSessionRaw = req.headers["x-claude-code-session-id"];
13639
+ const goSessionHeaders = openCodeGoSessionHeaders(
13640
+ { providerId: route.providerId, baseUrl: upstreamUrl },
13641
+ extractClaudeSessionId(
13642
+ anthropicBody,
13643
+ Array.isArray(inboundSessionRaw) ? inboundSessionRaw[0] : inboundSessionRaw
13644
+ )
13645
+ );
13442
13646
  if (isOAuth) {
13443
13647
  const seed = route.providerId ?? route.realModelId;
13444
13648
  const identity = injectClaudeIdentity(forwardBody, route.providerData, seed);
@@ -13456,7 +13660,7 @@ async function startProxyCatalog(routes, defaultAliasId, debug = false, inferenc
13456
13660
  authType: routeAuthType,
13457
13661
  log: (message) => plog(message),
13458
13662
  claudeCodeSessionId,
13459
- extraHeaders: route.headers,
13663
+ extraHeaders: { ...route.headers, ...goSessionHeaders },
13460
13664
  refreshToken: route.refreshToken,
13461
13665
  onTokenRefreshed: (refreshed) => {
13462
13666
  route.apiKey = refreshed;
@@ -13516,6 +13720,11 @@ async function startProxyCatalog(routes, defaultAliasId, debug = false, inferenc
13516
13720
  upstreamModelId: route.realModelId
13517
13721
  }
13518
13722
  });
13723
+ const goSdkSessionHeaders = openCodeGoSessionHeaders(
13724
+ { providerId: route.providerId, baseUrl: route.baseURL },
13725
+ claudeSessionId
13726
+ );
13727
+ if (goSdkSessionHeaders) params.headers = { ...params.headers, ...goSdkSessionHeaders };
13519
13728
  plog(
13520
13729
  () => `sdk: npm=${route.npm} model=${route.realModelId}, stream=${clientWantsStream}, tools=${anthropicBody.tools?.length ?? 0}, msgs=${params.messages.length}`
13521
13730
  );
@@ -13675,7 +13884,7 @@ async function startProxyCatalog(routes, defaultAliasId, debug = false, inferenc
13675
13884
  res,
13676
13885
  upstreamStatus === 500 ? 502 : upstreamStatus,
13677
13886
  clientMessage,
13678
- contextLengthExceeded ? relayRequestId ?? randomUUID3() : void 0
13887
+ contextLengthExceeded ? relayRequestId ?? randomUUID4() : void 0
13679
13888
  );
13680
13889
  } else {
13681
13890
  const errorType = anthropicErrorType(upstreamStatus, details?.transportCode);
@@ -13683,7 +13892,7 @@ async function startProxyCatalog(routes, defaultAliasId, debug = false, inferenc
13683
13892
  data: ${JSON.stringify({
13684
13893
  type: "error",
13685
13894
  error: { type: errorType, message: clientMessage },
13686
- ...contextLengthExceeded ? { request_id: relayRequestId ?? randomUUID3() } : {}
13895
+ ...contextLengthExceeded ? { request_id: relayRequestId ?? randomUUID4() } : {}
13687
13896
  })}
13688
13897
 
13689
13898
  `);
@@ -14086,10 +14295,10 @@ function tryAcquirePatchLock(lockPath = getPatchLockPath(), opts = {}) {
14086
14295
  mkdirSync5(join8(lockPath, ".."), { recursive: true, mode: 448 });
14087
14296
  for (let attempt = 0; attempt < 2; attempt++) {
14088
14297
  try {
14089
- const fd = openSync7(lockPath, "wx");
14298
+ const fd = openSync8(lockPath, "wx");
14090
14299
  const content = { pid: process.pid, startedAt: now };
14091
14300
  writeFileSync6(fd, JSON.stringify(content));
14092
- closeSync7(fd);
14301
+ closeSync8(fd);
14093
14302
  return () => {
14094
14303
  try {
14095
14304
  unlinkSync3(lockPath);
@@ -15019,15 +15228,15 @@ function localProvidersToServerModels(localProviders) {
15019
15228
  }
15020
15229
 
15021
15230
  // src/registry/credential-cleanup-journal.ts
15022
- import { randomUUID as randomUUID4 } from "crypto";
15231
+ import { randomUUID as randomUUID5 } from "crypto";
15023
15232
  import {
15024
- closeSync as closeSync8,
15233
+ closeSync as closeSync9,
15025
15234
  existsSync as existsSync6,
15026
15235
  fstatSync as fstatSync3,
15027
15236
  fsyncSync as fsyncSync2,
15028
15237
  lstatSync,
15029
15238
  mkdirSync as mkdirSync6,
15030
- openSync as openSync8,
15239
+ openSync as openSync9,
15031
15240
  readFileSync as readFileSync11,
15032
15241
  renameSync as renameSync4,
15033
15242
  unlinkSync as unlinkSync4,
@@ -15119,7 +15328,7 @@ function readJournalUnlocked(path) {
15119
15328
  if (before.isSymbolicLink() || !before.isFile()) {
15120
15329
  throw new Error("Credential cleanup journal must be a regular file.");
15121
15330
  }
15122
- fd = openSync8(path, "r");
15331
+ fd = openSync9(path, "r");
15123
15332
  const opened = fstatSync3(fd);
15124
15333
  if (before.dev !== opened.dev || before.ino !== opened.ino) {
15125
15334
  throw new Error("Credential cleanup journal changed while opening.");
@@ -15140,39 +15349,39 @@ function readJournalUnlocked(path) {
15140
15349
  const message = error instanceof Error ? error.message : String(error);
15141
15350
  throw new Error(`Could not read credential cleanup journal: ${message}`);
15142
15351
  } finally {
15143
- if (fd !== void 0) closeSync8(fd);
15352
+ if (fd !== void 0) closeSync9(fd);
15144
15353
  }
15145
15354
  }
15146
15355
  function syncParentDirectory(path) {
15147
15356
  let fd;
15148
15357
  try {
15149
- fd = openSync8(dirname6(path), "r");
15358
+ fd = openSync9(dirname6(path), "r");
15150
15359
  fsyncSync2(fd);
15151
15360
  } catch (error) {
15152
15361
  const code = error.code;
15153
15362
  if (code !== "EINVAL" && code !== "ENOTSUP" && code !== "EPERM") throw error;
15154
15363
  } finally {
15155
- if (fd !== void 0) closeSync8(fd);
15364
+ if (fd !== void 0) closeSync9(fd);
15156
15365
  }
15157
15366
  }
15158
15367
  function writeJournalUnlocked(journal, path) {
15159
15368
  assertRegistryWriteOwnership(path);
15160
15369
  ensureSecureAppHome();
15161
15370
  mkdirSync6(dirname6(path), { recursive: true, mode: DIR_MODE2 });
15162
- const tmp = `${path}.${process.pid}.${randomUUID4()}.tmp`;
15371
+ const tmp = `${path}.${process.pid}.${randomUUID5()}.tmp`;
15163
15372
  let fd;
15164
15373
  try {
15165
- fd = openSync8(tmp, "wx", FILE_MODE4);
15374
+ fd = openSync9(tmp, "wx", FILE_MODE4);
15166
15375
  writeFileSync7(fd, `${JSON.stringify(journal, null, 2)}
15167
15376
  `);
15168
15377
  fsyncSync2(fd);
15169
- closeSync8(fd);
15378
+ closeSync9(fd);
15170
15379
  fd = void 0;
15171
15380
  assertRegistryWriteOwnership(path);
15172
15381
  renameSync4(tmp, path);
15173
15382
  syncParentDirectory(path);
15174
15383
  } finally {
15175
- if (fd !== void 0) closeSync8(fd);
15384
+ if (fd !== void 0) closeSync9(fd);
15176
15385
  try {
15177
15386
  unlinkSync4(tmp);
15178
15387
  } catch (error) {
@@ -18052,7 +18261,7 @@ async function askSaveServerPassword() {
18052
18261
 
18053
18262
  // src/server/router.ts
18054
18263
  import { createServer as createServer2 } from "http";
18055
- import { randomUUID as randomUUID5 } from "crypto";
18264
+ import { randomUUID as randomUUID6 } from "crypto";
18056
18265
 
18057
18266
  // src/openai-adapter.ts
18058
18267
  import { tool as tool2, jsonSchema as jsonSchema2, streamText as streamText2, generateText as generateText2 } from "ai";
@@ -18468,7 +18677,7 @@ async function handleAnthropicMessages(req, res, options, modelCache, plog) {
18468
18677
  plog(`model not found: ${body.model}`);
18469
18678
  return;
18470
18679
  }
18471
- const requestId = randomUUID5();
18680
+ const requestId = randomUUID6();
18472
18681
  const claudeSessionIdHeader = Array.isArray(req.headers["x-claude-code-session-id"]) ? req.headers["x-claude-code-session-id"][0] : req.headers["x-claude-code-session-id"];
18473
18682
  const claudeSessionId = extractClaudeSessionId(body, claudeSessionIdHeader);
18474
18683
  const claudeAgentIds = extractClaudeAgentIds(req.headers);
@@ -18508,6 +18717,7 @@ async function handleAnthropicMessages(req, res, options, modelCache, plog) {
18508
18717
  const forwardBody = { ...body, model: upstreamModelId(model) };
18509
18718
  const authType = model.authType ?? "api";
18510
18719
  const isOAuth = authType === "oauth";
18720
+ const goSessionHeaders = openCodeGoSessionHeaders(model, claudeSessionId);
18511
18721
  auditInference(options, {
18512
18722
  requestId,
18513
18723
  modelId: body.model,
@@ -18538,7 +18748,7 @@ async function handleAnthropicMessages(req, res, options, modelCache, plog) {
18538
18748
  authType,
18539
18749
  log: (message) => plog(message),
18540
18750
  claudeCodeSessionId,
18541
- extraHeaders: model.headers,
18751
+ extraHeaders: { ...model.headers, ...goSessionHeaders },
18542
18752
  refreshToken,
18543
18753
  onTokenRefreshed: (refreshed) => {
18544
18754
  model.apiKey = refreshed;
@@ -18610,6 +18820,8 @@ async function handleAnthropicMessages(req, res, options, modelCache, plog) {
18610
18820
  maxTools: npmMaxTools,
18611
18821
  log: plog
18612
18822
  });
18823
+ const goSdkSessionHeaders = openCodeGoSessionHeaders(model, claudeSessionId);
18824
+ if (goSdkSessionHeaders) params.headers = { ...params.headers, ...goSdkSessionHeaders };
18613
18825
  const clientWantsStream = Boolean(body.stream);
18614
18826
  const responseModelId = getResponseModelId(body.model, model, options);
18615
18827
  plog(() => `sdk npm=${model.npm} upstream=${upstreamModelId(model)} responseModel=${responseModelId} stream=${clientWantsStream}`);
@@ -18801,6 +19013,8 @@ async function handleOpenAIChatCompletions(req, res, options, modelCache, plog)
18801
19013
  }
18802
19014
  const model = lookupModel(res, options.catalog, body.model);
18803
19015
  if (!model) return;
19016
+ const openAiSessionIdHeader = Array.isArray(req.headers["x-claude-code-session-id"]) ? req.headers["x-claude-code-session-id"][0] : req.headers["x-claude-code-session-id"];
19017
+ const goSessionHeaders = openCodeGoSessionHeaders(model, openAiSessionIdHeader);
18804
19018
  if (supportsDirectOpenAIChatCompletions(model)) {
18805
19019
  if (model.completionsUrl && !/^https?:\/\//i.test(model.completionsUrl)) {
18806
19020
  sendJson(res, 400, { error: { message: `Invalid provider completionsUrl: must be http:// or https://` } });
@@ -18837,7 +19051,7 @@ async function handleOpenAIChatCompletions(req, res, options, modelCache, plog)
18837
19051
  try {
18838
19052
  await relayAnthropicMessages(res, completionsUrl, forwardBody, apiKey2, Boolean(body.stream), {
18839
19053
  authType: model.authType ?? "api",
18840
- extraHeaders: model.headers,
19054
+ extraHeaders: { ...model.headers, ...goSessionHeaders },
18841
19055
  refreshToken,
18842
19056
  onTokenRefreshed: (refreshed) => {
18843
19057
  model.apiKey = refreshed;
@@ -18882,6 +19096,7 @@ async function handleOpenAIChatCompletions(req, res, options, modelCache, plog)
18882
19096
  const baseURL = model.modelFormat === "anthropic" ? model.baseUrl : model.apiBaseUrl;
18883
19097
  const openAiOAuth = isOpenAiOAuthRoute(model);
18884
19098
  const params = translateOpenAiRequest(body, { openAiOAuth });
19099
+ if (goSessionHeaders) params.headers = { ...params.headers, ...goSessionHeaders };
18885
19100
  const clientWantsStream = Boolean(body.stream);
18886
19101
  const responseModelId = getResponseModelId(body.model, model, options);
18887
19102
  plog(() => `sdk-openai npm=${npm} upstream=${upstreamModelId(model)} responseModel=${responseModelId} stream=${clientWantsStream}`);
@@ -19136,7 +19351,7 @@ import * as http2 from "http";
19136
19351
  import * as https from "https";
19137
19352
  import * as net from "net";
19138
19353
  import { PassThrough } from "stream";
19139
- import { randomUUID as randomUUID6 } from "crypto";
19354
+ import { randomUUID as randomUUID7 } from "crypto";
19140
19355
  import { URL as URL2 } from "url";
19141
19356
  import { createBrotliDecompress, createGunzip, createInflate } from "zlib";
19142
19357
 
@@ -19994,7 +20209,7 @@ async function startHttpProxy(options) {
19994
20209
  }
19995
20210
  const messagesEndpoint = anthropicMessagesEndpoint(req.url);
19996
20211
  if (req.method === "POST" && messagesEndpoint) {
19997
- const requestId = randomUUID6();
20212
+ const requestId = randomUUID7();
19998
20213
  let parsed = null;
19999
20214
  let route;
20000
20215
  let adapterBody = rawBody;