@bman654/clodex 2.8.2 → 2.8.4

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.8.2",
385
+ version: "2.8.4",
386
386
  publishConfig: {
387
387
  access: "public"
388
388
  },
@@ -3423,7 +3423,7 @@ function savedStopsAfter(current, assignments) {
3423
3423
  }
3424
3424
 
3425
3425
  // src/patch-transforms.ts
3426
- var PATCH_TRANSFORMS_VERSION = 10;
3426
+ var PATCH_TRANSFORMS_VERSION = 11;
3427
3427
  var NATIVE_EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"];
3428
3428
  var BASE_EFFORT_LEVELS = ["low", "medium", "high"];
3429
3429
  function projectNativeEffort(effort) {
@@ -3633,19 +3633,19 @@ function applyClodexPatches(source, config) {
3633
3633
  }
3634
3634
  if (Object.keys(CONTEXT_BY_KEY).length) {
3635
3635
  const MARKER = "/*ccpatch:ctx*/";
3636
- const SNIPPET = MARKER + "var _ccw=(" + JSON.stringify(CONTEXT_BY_KEY) + ')[String(e||"").trim().toLowerCase()];if(_ccw!==void 0)return _ccw;';
3636
+ const snippetFor = (modelParam) => MARKER + "var _ccw=(" + JSON.stringify(CONTEXT_BY_KEY) + ")[String(" + modelParam + '||"").trim().toLowerCase()];if(_ccw!==void 0)return _ccw;';
3637
3637
  if (js.includes(MARKER)) {
3638
3638
  applyOnce(
3639
3639
  "PATCH 7: per-model context window (refresh)",
3640
- /\/\*ccpatch:ctx\*\/var _ccw=\(\{[^{}]*\}\)\[[^\]]*\];if\(_ccw!==void 0\)return _ccw;/,
3641
- () => SNIPPET,
3640
+ /\/\*ccpatch:ctx\*\/var _ccw=\(\{[^{}]*\}\)\[String\(([\w$]+)\|\|""\)\.trim\(\)\.toLowerCase\(\)\];if\(_ccw!==void 0\)return _ccw;/,
3641
+ (_m, modelParam) => snippetFor(modelParam),
3642
3642
  { required: true, noopIsSkip: true }
3643
3643
  );
3644
3644
  } else {
3645
3645
  applyOnce(
3646
3646
  "PATCH 7: per-model context window",
3647
- /(function [\w$]+\(e,t\)\{)(let [\w$]+=[\w$]+\(\);if\([\w$]+!==void 0\)return [\w$]+;if\([\w$]+\(e,t\)\)return [\w$]+;return [\w$]+\(e,t\)\})/,
3648
- (_m, head, body) => head + SNIPPET + body,
3647
+ /(function [\w$]+\(([\w$]+),([\w$]+)\)\{)(let [\w$]+=[\w$]+\(\);if\([\w$]+!==void 0\)return [\w$]+;if\([\w$]+\(\2,\3\)\)return [\w$]+;return [\w$]+\(\2,\3\)\})/,
3648
+ (_m, head, modelParam, _windowParam, body) => head + snippetFor(modelParam) + body,
3649
3649
  { required: true }
3650
3650
  );
3651
3651
  }
@@ -3727,15 +3727,15 @@ function applyClodexPatches(source, config) {
3727
3727
  const marker = "/*ccpatch:child-network-env*/";
3728
3728
  const contractVar = q(NETWORK_ENV_CONTRACT_VAR);
3729
3729
  const networkVars = JSON.stringify(CHILD_NETWORK_ENV_VARS);
3730
- const requiredBodyLiterals = [
3731
- "{...process.env",
3732
- "CLAUDE_CODE_REMOTE",
3730
+ const requiredBodyLiterals = ["{...process.env"];
3731
+ const scrubbedEnvNames = [
3733
3732
  "CLAUDE_CODE_OAUTH_TOKEN",
3734
3733
  "CLAUDE_CODE_SUBSCRIPTION_TYPE",
3735
3734
  "CLAUDE_BG_PTY_AUTH",
3736
3735
  '"OTEL_"',
3737
3736
  "CLAUDE_CODE_OTEL_DIAG_STDERR"
3738
3737
  ];
3738
+ const MIN_SCRUBBED_ENV_NAMES = 1;
3739
3739
  const blockEndIndex = (text5, open2) => {
3740
3740
  const depths = [0];
3741
3741
  const templates = [false];
@@ -3815,11 +3815,15 @@ function applyClodexPatches(source, config) {
3815
3815
  /(function [\w$]+\(\)\{)(let (?:[^;{}]|\{[^;{}]*\})*?[\w$]+\(process\.env\.CLAUDE_CODE_REMOTE\)\?(?:(?!\}\s*function )[\s\S])*?\)return process\.env;let ([\w$]+)=\{(?:(?!\}\s*function )[\s\S])*?return \3)(\})/,
3816
3816
  (match, head, body, _copyVar, tail) => {
3817
3817
  const at = js.indexOf(match);
3818
- const bound = at < 0 ? -1 : blockEndIndex(js, at + head.length - 1) - at - (match.length - 1);
3819
- const targetIsValid = requiredBodyLiterals.every((literal) => body.includes(literal)) && !/\bfunction\s*[\w$]*\(/.test(body) && bound === 0;
3820
- if (!targetIsValid) {
3821
- log12("FAIL", patchName, "target validation failed");
3822
- fail("clodex patch: child network environment target validation failed");
3818
+ const closingBrace = at < 0 ? -1 : blockEndIndex(js, at + head.length - 1);
3819
+ const braceScanFailed = at < 0 || closingBrace < 0;
3820
+ const bound = braceScanFailed ? 0 : closingBrace - at - (match.length - 1);
3821
+ const missingLiteral = requiredBodyLiterals.find((literal) => !body.includes(literal));
3822
+ const scrubbedSeen = scrubbedEnvNames.filter((name) => body.includes(name));
3823
+ const why = missingLiteral !== void 0 ? "body does not contain " + missingLiteral : scrubbedSeen.length < MIN_SCRUBBED_ENV_NAMES ? "body scrubs only " + scrubbedSeen.length + " of the " + scrubbedEnvNames.length + " known child-env names (expected at least " + MIN_SCRUBBED_ENV_NAMES + ")" : /\bfunction\s*[\w$]*\(/.test(body) ? "body declares a nested function" : braceScanFailed ? "the brace walk never reached the function's closing brace" : bound !== 0 ? "match ends " + bound + " characters from the function it started in" : void 0;
3824
+ if (why !== void 0) {
3825
+ log12("FAIL", patchName, "target validation failed: " + why);
3826
+ fail("clodex patch: child network environment target validation failed: " + why);
3823
3827
  }
3824
3828
  const restoredBody = body.replace(/process\.env/g, "_clodexChildEnv");
3825
3829
  const restore = marker + "let _clodexChildEnv=process.env,_clodexNetworkRaw=_clodexChildEnv[" + contractVar + "];if(_clodexNetworkRaw!==void 0){_clodexChildEnv={..._clodexChildEnv};delete _clodexChildEnv[" + contractVar + '];try{let _clodexNetwork=JSON.parse(_clodexNetworkRaw);if(_clodexNetwork&&typeof _clodexNetwork==="object"&&!Array.isArray(_clodexNetwork)&&_clodexNetwork.version===1&&_clodexNetwork.original&&typeof _clodexNetwork.original==="object"&&!Array.isArray(_clodexNetwork.original)&&_clodexNetwork.injected&&typeof _clodexNetwork.injected==="object"&&!Array.isArray(_clodexNetwork.injected)&&Object.keys(_clodexNetwork.original).every(_clodexKey=>' + networkVars + '.includes(_clodexKey)&&(typeof _clodexNetwork.original[_clodexKey]==="string"||_clodexNetwork.original[_clodexKey]===null)&&Object.prototype.hasOwnProperty.call(_clodexNetwork.injected,_clodexKey))&&Object.keys(_clodexNetwork.injected).every(_clodexKey=>' + networkVars + '.includes(_clodexKey)&&(typeof _clodexNetwork.injected[_clodexKey]==="string"||_clodexNetwork.injected[_clodexKey]===null)&&Object.prototype.hasOwnProperty.call(_clodexNetwork.original,_clodexKey)))for(let _clodexKey of ' + networkVars + '){if(Object.prototype.hasOwnProperty.call(_clodexNetwork.original,_clodexKey)&&Object.prototype.hasOwnProperty.call(_clodexNetwork.injected,_clodexKey)){let _clodexOriginal=_clodexNetwork.original[_clodexKey],_clodexInjected=_clodexNetwork.injected[_clodexKey],_clodexCurrent=_clodexChildEnv[_clodexKey]===void 0?null:_clodexChildEnv[_clodexKey];if((typeof _clodexOriginal==="string"||_clodexOriginal===null)&&(typeof _clodexInjected==="string"||_clodexInjected===null)&&_clodexCurrent===_clodexInjected){if(_clodexOriginal===null)delete _clodexChildEnv[_clodexKey];else _clodexChildEnv[_clodexKey]=_clodexOriginal}}}}catch(_clodexError){}}';
@@ -3844,8 +3848,8 @@ import {
3844
3848
  statSync as statSync6,
3845
3849
  unlinkSync as unlinkSync3,
3846
3850
  writeFileSync as writeFileSync5,
3847
- openSync as openSync5,
3848
- closeSync as closeSync5,
3851
+ openSync as openSync6,
3852
+ closeSync as closeSync6,
3849
3853
  realpathSync
3850
3854
  } from "fs";
3851
3855
  import { homedir as homedir3 } from "os";
@@ -6201,6 +6205,7 @@ function writeInferenceResponseLifecycleLog(path, entry) {
6201
6205
  const outputTokens = nonNegativeInteger(entry.outputTokens);
6202
6206
  const cacheCreationInputTokens = nonNegativeInteger(entry.cacheCreationInputTokens);
6203
6207
  const cacheReadInputTokens = nonNegativeInteger(entry.cacheReadInputTokens);
6208
+ const attempt = nonNegativeInteger(entry.attempt);
6204
6209
  writeSecureLogLine(path, JSON.stringify({
6205
6210
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6206
6211
  event: entry.event,
@@ -6231,7 +6236,9 @@ function writeInferenceResponseLifecycleLog(path, entry) {
6231
6236
  ...entry.errorCode ? { errorCode: compactLogValue(entry.errorCode, 100) } : {},
6232
6237
  ...entry.errorSignature ? { errorSignature: compactLogValue(entry.errorSignature, 100) } : {},
6233
6238
  ...entry.failureSource ? { failureSource: entry.failureSource } : {},
6234
- ...entry.terminationSource ? { terminationSource: entry.terminationSource } : {}
6239
+ ...entry.terminationSource ? { terminationSource: entry.terminationSource } : {},
6240
+ ...attempt !== void 0 ? { attempt } : {},
6241
+ ...entry.reusedSocket !== void 0 ? { reusedSocket: entry.reusedSocket } : {}
6235
6242
  }));
6236
6243
  }
6237
6244
  function writeProxyLifecycleLog(path, entry) {
@@ -7058,8 +7065,208 @@ function resignMachOBinary(path) {
7058
7065
  }
7059
7066
  }
7060
7067
 
7061
- // src/bun-bundle.ts
7068
+ // src/bun-compiled-pointer.ts
7062
7069
  import { closeSync as closeSync3, openSync as openSync3, readSync as readSync2, writeSync as writeSync3 } from "fs";
7070
+ var TWEAKCC_SCAN_STRIDE = 16384n;
7071
+ var SCAN_CHUNK = 1 << 20;
7072
+ var ELF_MAGIC = 1179403647;
7073
+ var ELFCLASS64 = 2;
7074
+ var ELFDATA2LSB = 1;
7075
+ var PT_LOAD = 1;
7076
+ var PF_W = 2;
7077
+ function readAt2(fd, length, position) {
7078
+ const buf = Buffer.alloc(length);
7079
+ let read = 0;
7080
+ while (read < length) {
7081
+ const n = readSync2(fd, buf, read, length - read, position + read);
7082
+ if (n <= 0) break;
7083
+ read += n;
7084
+ }
7085
+ return read === length ? buf : buf.subarray(0, read);
7086
+ }
7087
+ function readElfLayout(fd) {
7088
+ const ident = readAt2(fd, 64, 0);
7089
+ if (ident.length < 64) return null;
7090
+ if (ident.readUInt32LE(0) !== ELF_MAGIC) return null;
7091
+ if (ident[4] !== ELFCLASS64 || ident[5] !== ELFDATA2LSB) return null;
7092
+ const phoff = ident.readBigUInt64LE(32);
7093
+ const shoff = ident.readBigUInt64LE(40);
7094
+ const phentsize = ident.readUInt16LE(54);
7095
+ const phnum = ident.readUInt16LE(56);
7096
+ const shentsize = ident.readUInt16LE(58);
7097
+ const shnum = ident.readUInt16LE(60);
7098
+ const shstrndx = ident.readUInt16LE(62);
7099
+ if (shnum === 0 || phnum === 65535) return null;
7100
+ if (shstrndx >= shnum || shentsize < 64 || phentsize < 56) return null;
7101
+ const shTable = readAt2(fd, shnum * shentsize, Number(shoff));
7102
+ if (shTable.length !== shnum * shentsize) return null;
7103
+ const raw = [];
7104
+ for (let i = 0; i < shnum; i++) {
7105
+ const at = i * shentsize;
7106
+ raw.push({
7107
+ nameOffset: shTable.readUInt32LE(at),
7108
+ addr: shTable.readBigUInt64LE(at + 16),
7109
+ offset: shTable.readBigUInt64LE(at + 24),
7110
+ size: shTable.readBigUInt64LE(at + 32)
7111
+ });
7112
+ }
7113
+ const strtab = raw[shstrndx];
7114
+ const names = readAt2(fd, Number(strtab.size), Number(strtab.offset));
7115
+ const sections = raw.map((section) => {
7116
+ const start = section.nameOffset;
7117
+ let end = start;
7118
+ while (end < names.length && names[end] !== 0) end++;
7119
+ return {
7120
+ name: names.toString("utf8", start, end),
7121
+ addr: section.addr,
7122
+ offset: section.offset,
7123
+ size: section.size
7124
+ };
7125
+ });
7126
+ const phTable = readAt2(fd, phnum * phentsize, Number(phoff));
7127
+ if (phTable.length !== phnum * phentsize) return null;
7128
+ const segments = [];
7129
+ for (let i = 0; i < phnum; i++) {
7130
+ const at = i * phentsize;
7131
+ segments.push({
7132
+ type: phTable.readUInt32LE(at),
7133
+ flags: phTable.readUInt32LE(at + 4),
7134
+ offset: phTable.readBigUInt64LE(at + 8),
7135
+ vaddr: phTable.readBigUInt64LE(at + 16),
7136
+ filesz: phTable.readBigUInt64LE(at + 32)
7137
+ });
7138
+ }
7139
+ return { sections, segments };
7140
+ }
7141
+ function alignUp(value, to) {
7142
+ return (value + to - 1n) / to * to;
7143
+ }
7144
+ function writableLoad(layout) {
7145
+ return layout.segments.find((segment) => segment.type === PT_LOAD && (segment.flags & PF_W) !== 0);
7146
+ }
7147
+ function fileOffsetOf(layout, vaddr, length) {
7148
+ let found = null;
7149
+ for (const segment of layout.segments) {
7150
+ if (segment.type !== PT_LOAD) continue;
7151
+ if (vaddr < segment.vaddr) continue;
7152
+ if (vaddr + length > segment.vaddr + segment.filesz) continue;
7153
+ if (found !== null) return null;
7154
+ found = Number(segment.offset + (vaddr - segment.vaddr));
7155
+ }
7156
+ return found;
7157
+ }
7158
+ function tweakccWouldFind(fd, segment, needle) {
7159
+ const first = alignUp(segment.vaddr, TWEAKCC_SCAN_STRIDE);
7160
+ const last = segment.vaddr + segment.filesz - 8n;
7161
+ for (let vaddr = first; vaddr <= last; vaddr += TWEAKCC_SCAN_STRIDE) {
7162
+ const at = Number(segment.offset + (vaddr - segment.vaddr));
7163
+ if (readAt2(fd, 8, at).equals(needle)) return vaddr;
7164
+ }
7165
+ return null;
7166
+ }
7167
+ function scanForNeedle(fd, from, to, needle, skipFrom, skipTo) {
7168
+ const hits = [];
7169
+ for (let start = from; start < to; start += SCAN_CHUNK - 7) {
7170
+ const length = Math.min(SCAN_CHUNK, to - start);
7171
+ if (length < 8) break;
7172
+ const chunk = readAt2(fd, length, start);
7173
+ let at = 0;
7174
+ for (; ; ) {
7175
+ const found = chunk.indexOf(needle, at);
7176
+ if (found < 0) break;
7177
+ const offset = start + found;
7178
+ if (offset < skipFrom || offset >= skipTo) hits.push(offset);
7179
+ at = found + 1;
7180
+ }
7181
+ }
7182
+ return hits;
7183
+ }
7184
+ function shimBunCompiledPointer(path) {
7185
+ const fd = openSync3(path, "r+");
7186
+ try {
7187
+ const layout = readElfLayout(fd);
7188
+ if (!layout) return null;
7189
+ const bun = layout.sections.find((section) => section.name === ".bun");
7190
+ if (!bun || bun.size === 0n) return null;
7191
+ const segment = writableLoad(layout);
7192
+ if (!segment) return null;
7193
+ const needle = Buffer.alloc(8);
7194
+ needle.writeBigUInt64LE(bun.addr);
7195
+ if (tweakccWouldFind(fd, segment, needle) !== null) return null;
7196
+ const segmentStart = Number(segment.offset);
7197
+ const segmentEnd = Number(segment.offset + segment.filesz);
7198
+ const bunStart = Number(bun.offset);
7199
+ const bunEnd = Number(bun.offset + bun.size);
7200
+ const candidates = scanForNeedle(fd, segmentStart, segmentEnd, needle, bunStart, bunEnd);
7201
+ if (candidates.length !== 1) {
7202
+ throw new Error(
7203
+ `cannot locate Bun's blob pointer: ${candidates.length} candidates in the writable segment (expected 1). Refusing to repack a binary whose Bun global would be left stale.`
7204
+ );
7205
+ }
7206
+ const pointerOffset = candidates[0];
7207
+ const pointerVaddr = segment.vaddr + BigInt(pointerOffset) - segment.offset;
7208
+ const first = alignUp(segment.vaddr, TWEAKCC_SCAN_STRIDE);
7209
+ const last = segment.vaddr + segment.filesz - 8n;
7210
+ let standInVaddr = null;
7211
+ for (let vaddr = first; vaddr <= last; vaddr += TWEAKCC_SCAN_STRIDE) {
7212
+ const at = Number(segment.offset + (vaddr - segment.vaddr));
7213
+ if (at + 8 > bunStart && at < bunEnd) continue;
7214
+ if (at + 8 > pointerOffset && at < pointerOffset + 8) continue;
7215
+ standInVaddr = vaddr;
7216
+ break;
7217
+ }
7218
+ if (standInVaddr === null) {
7219
+ throw new Error("no address tweakcc's ELF repack scans is usable for Bun's blob pointer");
7220
+ }
7221
+ const standInOffset = Number(segment.offset + (standInVaddr - segment.vaddr));
7222
+ const displaced = readAt2(fd, 8, standInOffset);
7223
+ if (displaced.length !== 8) throw new Error("could not read the bytes Bun's blob pointer displaces");
7224
+ writeSync3(fd, needle, 0, 8, standInOffset);
7225
+ return { pointerVaddr, standInVaddr, displaced, bunVaddr: bun.addr };
7226
+ } finally {
7227
+ closeSync3(fd);
7228
+ }
7229
+ }
7230
+ function restoreBunCompiledPointer(path, shim) {
7231
+ const fd = openSync3(path, "r+");
7232
+ try {
7233
+ const layout = readElfLayout(fd);
7234
+ if (!layout) throw new Error("the repacked binary is no longer a 64-bit little-endian ELF");
7235
+ const bun = layout.sections.find((section) => section.name === ".bun");
7236
+ if (!bun) throw new Error("the repacked binary has no .bun section");
7237
+ const standInOffset = fileOffsetOf(layout, shim.standInVaddr, 8n);
7238
+ const pointerOffset = fileOffsetOf(layout, shim.pointerVaddr, 8n);
7239
+ if (standInOffset === null || pointerOffset === null) {
7240
+ throw new Error(
7241
+ "the repack left Bun's blob pointer outside the loaded image, or in more than one segment of it"
7242
+ );
7243
+ }
7244
+ const written = readAt2(fd, 8, standInOffset).readBigUInt64LE(0);
7245
+ if (written === shim.bunVaddr) {
7246
+ throw new Error("the repack did not rewrite Bun's blob pointer \u2014 the stand-in was not used");
7247
+ }
7248
+ if (written !== bun.addr) {
7249
+ throw new Error(
7250
+ `the repack pointed Bun at 0x${written.toString(16)} but put .bun at 0x${bun.addr.toString(16)}`
7251
+ );
7252
+ }
7253
+ const value = Buffer.alloc(8);
7254
+ value.writeBigUInt64LE(written);
7255
+ writeSync3(fd, value, 0, 8, pointerOffset);
7256
+ writeSync3(fd, shim.displaced, 0, 8, standInOffset);
7257
+ if (!readAt2(fd, 8, pointerOffset).equals(value)) {
7258
+ throw new Error("Bun's blob pointer did not take the repacked address");
7259
+ }
7260
+ if (!readAt2(fd, 8, standInOffset).equals(shim.displaced)) {
7261
+ throw new Error("the bytes the stand-in displaced were not restored");
7262
+ }
7263
+ } finally {
7264
+ closeSync3(fd);
7265
+ }
7266
+ }
7267
+
7268
+ // src/bun-bundle.ts
7269
+ import { closeSync as closeSync4, openSync as openSync4, readSync as readSync3, writeSync as writeSync4 } from "fs";
7063
7270
  function writableModuleIndex(path) {
7064
7271
  const table = readBunModuleTable(path);
7065
7272
  if (!table) return null;
@@ -7175,18 +7382,18 @@ function placeholderOf(byteLength) {
7175
7382
  return PLACEHOLDER_TEXT.repeat(Math.ceil(byteLength / PLACEHOLDER_TEXT.length)).slice(0, byteLength);
7176
7383
  }
7177
7384
  function readBlobData(path, table, into) {
7178
- const fd = openSync3(path, "r");
7385
+ const fd = openSync4(path, "r");
7179
7386
  try {
7180
7387
  let read = 0;
7181
7388
  while (read < table.byteCount) {
7182
- const got = readSync2(fd, into, read, table.byteCount - read, table.blobAt + read);
7389
+ const got = readSync3(fd, into, read, table.byteCount - read, table.blobAt + read);
7183
7390
  if (got <= 0) {
7184
7391
  throw new Error(`read ${read} of the ${table.byteCount} blob bytes of ${path}`);
7185
7392
  }
7186
7393
  read += got;
7187
7394
  }
7188
7395
  } finally {
7189
- closeSync3(fd);
7396
+ closeSync4(fd);
7190
7397
  }
7191
7398
  }
7192
7399
  function repointModule(data, table, append) {
@@ -7238,7 +7445,7 @@ function applyBundleWritePlan(path, plan) {
7238
7445
  }
7239
7446
  const offsets = Buffer.from(plan.offsets);
7240
7447
  offsets.writeBigUInt64LE(BigInt(byteCount), 0);
7241
- const fd = openSync3(path, "r+");
7448
+ const fd = openSync4(path, "r+");
7242
7449
  try {
7243
7450
  writeAll(fd, plan.data, repacked.blobAt, path);
7244
7451
  const padding = byteCount - plan.data.length;
@@ -7246,7 +7453,7 @@ function applyBundleWritePlan(path, plan) {
7246
7453
  writeAll(fd, offsets, repacked.blobAt + byteCount, path);
7247
7454
  writeAll(fd, BUN_TRAILER2, repacked.blobAt + byteCount + BUN_OFFSETS_BYTES2, path);
7248
7455
  } finally {
7249
- closeSync3(fd);
7456
+ closeSync4(fd);
7250
7457
  }
7251
7458
  const published = readBunModuleTable(path);
7252
7459
  if (!published) throw new Error(`cannot re-read the Bun module table of ${path} after publishing its blob`);
@@ -7274,7 +7481,7 @@ function applyBundleWritePlan(path, plan) {
7274
7481
  function writeAll(fd, bytes, position, path) {
7275
7482
  let written = 0;
7276
7483
  while (written < bytes.length) {
7277
- const wrote = writeSync3(fd, bytes, written, bytes.length - written, position + written);
7484
+ const wrote = writeSync4(fd, bytes, written, bytes.length - written, position + written);
7278
7485
  if (wrote <= 0) throw new Error(`wrote ${written} of ${bytes.length} blob bytes to ${path}`);
7279
7486
  written += wrote;
7280
7487
  }
@@ -7775,6 +7982,7 @@ function sanitizeMessage(message) {
7775
7982
 
7776
7983
  // src/tool-input-sanitize.ts
7777
7984
  function sanitizeToolInput(input, requiredProps) {
7985
+ if (!input || typeof input !== "object" || Array.isArray(input)) return input;
7778
7986
  const out = /* @__PURE__ */ Object.create(null);
7779
7987
  for (const [k, v] of Object.entries(input)) {
7780
7988
  if (v === null) continue;
@@ -10159,7 +10367,7 @@ function thinkingProviderOptions(npm) {
10159
10367
 
10160
10368
  // src/proxy.ts
10161
10369
  import { createServer } from "http";
10162
- import { appendFileSync as appendFileSync2, openSync as openSync4, writeSync as writeSync4, closeSync as closeSync4 } from "fs";
10370
+ import { appendFileSync as appendFileSync2, openSync as openSync5, writeSync as writeSync5, closeSync as closeSync5 } from "fs";
10163
10371
 
10164
10372
  // src/http-utils.ts
10165
10373
  import * as zlib from "zlib";
@@ -10735,6 +10943,18 @@ function upstreamMaxRetries(env = process.env, warn = (message) => emitParentNot
10735
10943
  }
10736
10944
  return value;
10737
10945
  }
10946
+ var CLIENT_MAX_RETRIES_ENV = "CLAUDE_CODE_MAX_RETRIES";
10947
+ var DEFAULT_PASSTHROUGH_RETRIES = 1;
10948
+ function passthroughUpstreamRetries(env = process.env) {
10949
+ const explicit = upstreamMaxRetries(env);
10950
+ if (explicit !== void 0) return explicit;
10951
+ const raw = env[CLIENT_MAX_RETRIES_ENV]?.trim();
10952
+ if (raw !== void 0 && raw !== "") {
10953
+ const clientRetries = Number(raw);
10954
+ if (Number.isFinite(clientRetries) && clientRetries === 0) return 0;
10955
+ }
10956
+ return DEFAULT_PASSTHROUGH_RETRIES;
10957
+ }
10738
10958
 
10739
10959
  // src/sdk-adapter.ts
10740
10960
  function sdkTranslationErrorSignature(error) {
@@ -10959,6 +11179,22 @@ function translateMessages(messages, npm, openAiPromptCacheBreakpoints = false)
10959
11179
  }
10960
11180
  return out;
10961
11181
  }
11182
+ function isPlainObject(value) {
11183
+ return value !== null && typeof value === "object" && !Array.isArray(value);
11184
+ }
11185
+ function parsesAsJson(text5) {
11186
+ if (text5.trim() === "") return true;
11187
+ try {
11188
+ JSON.parse(text5);
11189
+ return true;
11190
+ } catch {
11191
+ return false;
11192
+ }
11193
+ }
11194
+ function representableToolInput(input) {
11195
+ if (typeof input === "string") return input;
11196
+ return isPlainObject(input) || Array.isArray(input) ? input : {};
11197
+ }
10962
11198
  function toolRequiredProps(tools) {
10963
11199
  const map = /* @__PURE__ */ new Map();
10964
11200
  for (const [name, t] of Object.entries(tools ?? {})) {
@@ -10968,12 +11204,16 @@ function toolRequiredProps(tools) {
10968
11204
  }
10969
11205
  return map;
10970
11206
  }
10971
- function translateTools(anthropicTools) {
11207
+ function translateTools(anthropicTools, npm) {
10972
11208
  if (!anthropicTools?.length) return void 0;
10973
11209
  const tools = {};
10974
11210
  for (const t of anthropicTools) {
10975
11211
  if (!t.name || !t.input_schema) continue;
10976
- tools[t.name] = tool({ description: t.description ?? "", inputSchema: jsonSchema(t.input_schema) });
11212
+ tools[t.name] = tool({
11213
+ description: t.description ?? "",
11214
+ inputSchema: jsonSchema(t.input_schema),
11215
+ strict: npm === "@ai-sdk/openai" ? false : void 0
11216
+ });
10977
11217
  }
10978
11218
  return Object.keys(tools).length ? tools : void 0;
10979
11219
  }
@@ -11037,7 +11277,7 @@ function translateRequest(body, npm, options) {
11037
11277
  ...translateMessages(messages, npm, supportsExplicitOpenAiCaching)
11038
11278
  ],
11039
11279
  allowSystemInMessages: true,
11040
- tools: translateTools(upstreamTools.length ? upstreamTools : void 0),
11280
+ tools: translateTools(upstreamTools.length ? upstreamTools : void 0, npm),
11041
11281
  toolChoice: compactRequest ? "none" : translateToolChoice(body.tool_choice),
11042
11282
  maxOutputTokens: options?.openAiOAuth ? void 0 : body.max_tokens,
11043
11283
  temperature: body.temperature,
@@ -11254,7 +11494,8 @@ async function writeAnthropicStream(stream, modelId, write, log12, observer, too
11254
11494
  const id = part.toolCallId ?? "";
11255
11495
  if (idToBlock.has(id)) {
11256
11496
  if (!flushedTools.has(id)) {
11257
- const json = part.input !== void 0 && part.input !== null ? JSON.stringify(sanitizeToolInput(part.input, requiredProps.get(part.toolName ?? ""))) : toolJsonBuffer.get(id) ?? "";
11497
+ const buffered = toolJsonBuffer.get(id);
11498
+ const json = buffered !== void 0 && !isPlainObject(part.input) && !parsesAsJson(buffered) ? buffered : part.input !== void 0 && part.input !== null ? JSON.stringify(sanitizeToolInput(part.input, requiredProps.get(part.toolName ?? ""))) : buffered ?? "";
11258
11499
  if (json) {
11259
11500
  emit("content_block_delta", {
11260
11501
  type: "content_block_delta",
@@ -11459,7 +11700,7 @@ async function generateAnthropicResponse(model, params, modelId, options) {
11459
11700
  type: "tool_use",
11460
11701
  id: encodeToolUseId(tc.toolCallId, grabRoundTripSignature(tc)),
11461
11702
  name: tc.toolName,
11462
- input: sanitizeToolInput(tc.input ?? {}, requiredProps.get(tc.toolName))
11703
+ input: representableToolInput(sanitizeToolInput(tc.input ?? {}, requiredProps.get(tc.toolName)))
11463
11704
  }))
11464
11705
  ],
11465
11706
  stop_reason: finishReason === "tool-calls" ? "tool_use" : "end_turn",
@@ -11613,12 +11854,12 @@ function createTranslationLifecycle(logPath, requestId, claudeSessionId, modelId
11613
11854
  function appendSecureLog(logPath, line) {
11614
11855
  const redacted = redactTraceLine(line);
11615
11856
  try {
11616
- const fd = openSync4(logPath, "a", 384);
11857
+ const fd = openSync5(logPath, "a", 384);
11617
11858
  try {
11618
- writeSync4(fd, `${(/* @__PURE__ */ new Date()).toISOString()} ${redacted}
11859
+ writeSync5(fd, `${(/* @__PURE__ */ new Date()).toISOString()} ${redacted}
11619
11860
  `);
11620
11861
  } finally {
11621
- closeSync4(fd);
11862
+ closeSync5(fd);
11622
11863
  }
11623
11864
  } catch {
11624
11865
  try {
@@ -12481,10 +12722,10 @@ function tryAcquirePatchLock(lockPath = getPatchLockPath(), opts = {}) {
12481
12722
  mkdirSync5(join7(lockPath, ".."), { recursive: true, mode: 448 });
12482
12723
  for (let attempt = 0; attempt < 2; attempt++) {
12483
12724
  try {
12484
- const fd = openSync5(lockPath, "wx");
12725
+ const fd = openSync6(lockPath, "wx");
12485
12726
  const content = { pid: process.pid, startedAt: now };
12486
12727
  writeFileSync5(fd, JSON.stringify(content));
12487
- closeSync5(fd);
12728
+ closeSync6(fd);
12488
12729
  return () => {
12489
12730
  try {
12490
12731
  unlinkSync3(lockPath);
@@ -12744,11 +12985,15 @@ async function applyPatch(binaryPath, version, desired, configHash, opts) {
12744
12985
  splitBundleSource(loaded.bundle, local.content),
12745
12986
  writable
12746
12987
  );
12988
+ const bunPointerShim = shimBunCompiledPointer(candidatePath);
12747
12989
  await writeContent(loaded.installation, plan2.content);
12990
+ if (bunPointerShim) restoreBunCompiledPointer(candidatePath, bunPointerShim);
12748
12991
  applyBundleWritePlan(candidatePath, plan2);
12749
12992
  publishedBlob = true;
12750
12993
  } else {
12994
+ const bunPointerShim = shimBunCompiledPointer(candidatePath);
12751
12995
  await writeContent(loaded.installation, local.content);
12996
+ if (bunPointerShim) restoreBunCompiledPointer(candidatePath, bunPointerShim);
12752
12997
  }
12753
12998
  if (writeShim) restoreEntryModuleName(candidatePath, writeShim, { resign: true });
12754
12999
  else if (publishedBlob) resignMachOBinary(candidatePath);
@@ -13269,13 +13514,13 @@ function localProvidersToServerModels(localProviders) {
13269
13514
  // src/registry/credential-cleanup-journal.ts
13270
13515
  import { randomUUID as randomUUID4 } from "crypto";
13271
13516
  import {
13272
- closeSync as closeSync6,
13517
+ closeSync as closeSync7,
13273
13518
  existsSync as existsSync6,
13274
13519
  fstatSync,
13275
13520
  fsyncSync as fsyncSync2,
13276
13521
  lstatSync,
13277
13522
  mkdirSync as mkdirSync6,
13278
- openSync as openSync6,
13523
+ openSync as openSync7,
13279
13524
  readFileSync as readFileSync9,
13280
13525
  renameSync as renameSync3,
13281
13526
  unlinkSync as unlinkSync4,
@@ -13367,7 +13612,7 @@ function readJournalUnlocked(path) {
13367
13612
  if (before.isSymbolicLink() || !before.isFile()) {
13368
13613
  throw new Error("Credential cleanup journal must be a regular file.");
13369
13614
  }
13370
- fd = openSync6(path, "r");
13615
+ fd = openSync7(path, "r");
13371
13616
  const opened = fstatSync(fd);
13372
13617
  if (before.dev !== opened.dev || before.ino !== opened.ino) {
13373
13618
  throw new Error("Credential cleanup journal changed while opening.");
@@ -13388,19 +13633,19 @@ function readJournalUnlocked(path) {
13388
13633
  const message = error instanceof Error ? error.message : String(error);
13389
13634
  throw new Error(`Could not read credential cleanup journal: ${message}`);
13390
13635
  } finally {
13391
- if (fd !== void 0) closeSync6(fd);
13636
+ if (fd !== void 0) closeSync7(fd);
13392
13637
  }
13393
13638
  }
13394
13639
  function syncParentDirectory(path) {
13395
13640
  let fd;
13396
13641
  try {
13397
- fd = openSync6(dirname4(path), "r");
13642
+ fd = openSync7(dirname4(path), "r");
13398
13643
  fsyncSync2(fd);
13399
13644
  } catch (error) {
13400
13645
  const code = error.code;
13401
13646
  if (code !== "EINVAL" && code !== "ENOTSUP" && code !== "EPERM") throw error;
13402
13647
  } finally {
13403
- if (fd !== void 0) closeSync6(fd);
13648
+ if (fd !== void 0) closeSync7(fd);
13404
13649
  }
13405
13650
  }
13406
13651
  function writeJournalUnlocked(journal, path) {
@@ -13410,17 +13655,17 @@ function writeJournalUnlocked(journal, path) {
13410
13655
  const tmp = `${path}.${process.pid}.${randomUUID4()}.tmp`;
13411
13656
  let fd;
13412
13657
  try {
13413
- fd = openSync6(tmp, "wx", FILE_MODE4);
13658
+ fd = openSync7(tmp, "wx", FILE_MODE4);
13414
13659
  writeFileSync6(fd, `${JSON.stringify(journal, null, 2)}
13415
13660
  `);
13416
13661
  fsyncSync2(fd);
13417
- closeSync6(fd);
13662
+ closeSync7(fd);
13418
13663
  fd = void 0;
13419
13664
  assertRegistryWriteOwnership(path);
13420
13665
  renameSync3(tmp, path);
13421
13666
  syncParentDirectory(path);
13422
13667
  } finally {
13423
- if (fd !== void 0) closeSync6(fd);
13668
+ if (fd !== void 0) closeSync7(fd);
13424
13669
  try {
13425
13670
  unlinkSync4(tmp);
13426
13671
  } catch (error) {
@@ -17369,20 +17614,37 @@ function ensureHttpProxyCertificates() {
17369
17614
  serverKey: readFileSync10(paths.serverKey, "utf8")
17370
17615
  };
17371
17616
  }
17372
- function ensureHttpProxyCaBundle(relayCaCertPath, additionalCaCertPath) {
17617
+ function ensureHttpProxyCaBundle(relayCaCertPath, additionalCaCertPath, onWarning) {
17373
17618
  if (!additionalCaCertPath?.trim()) return relayCaCertPath;
17619
+ const warn = (detail) => {
17620
+ onWarning?.(
17621
+ `${detail} The CA bundle handed to the child is ${relayCaCertPath}; node's built-in roots are unaffected.`
17622
+ );
17623
+ return relayCaCertPath;
17624
+ };
17625
+ let additionalCa;
17374
17626
  try {
17375
17627
  if (resolve2(additionalCaCertPath) === resolve2(relayCaCertPath)) return relayCaCertPath;
17628
+ additionalCa = readFileSync10(additionalCaCertPath, "utf8").trim();
17629
+ } catch (err) {
17630
+ return warn(
17631
+ `NODE_EXTRA_CA_CERTS=${additionalCaCertPath} cannot be read (${err instanceof Error ? err.message : String(err)}), so it is not part of the proxy CA bundle. Where node reports this itself it says only "Ignoring extra certs ... load failed", without naming the variable. Clear or correct it.`
17632
+ );
17633
+ }
17634
+ if (!additionalCa) {
17635
+ return warn(`NODE_EXTRA_CA_CERTS=${additionalCaCertPath} is empty, so it adds nothing.`);
17636
+ }
17637
+ try {
17376
17638
  const relayCa = readFileSync10(relayCaCertPath, "utf8").trimEnd();
17377
- const additionalCa = readFileSync10(additionalCaCertPath, "utf8").trim();
17378
- if (!additionalCa) return relayCaCertPath;
17379
17639
  const combinedPath = join8(dirname5(relayCaCertPath), "combined-ca.pem");
17380
17640
  writePublic(combinedPath, `${relayCa}
17381
17641
  ${additionalCa}
17382
17642
  `);
17383
17643
  return combinedPath;
17384
- } catch {
17385
- return relayCaCertPath;
17644
+ } catch (err) {
17645
+ return warn(
17646
+ `clodex could not build the combined CA bundle in ${dirname5(relayCaCertPath)} (${err instanceof Error ? err.message : String(err)}), so the readable, non-empty NODE_EXTRA_CA_CERTS=${additionalCaCertPath} was left out of it. Fix the reported error and restart clodex.`
17647
+ );
17386
17648
  }
17387
17649
  }
17388
17650
 
@@ -17391,6 +17653,16 @@ var ANTHROPIC_HOST = "api.anthropic.com";
17391
17653
  var MAX_BODY_BYTES = 50 * 1024 * 1024;
17392
17654
  var MAX_ERROR_BODY_BYTES = 64 * 1024;
17393
17655
  var MAX_USAGE_SSE_BLOCK_BYTES = 64 * 1024;
17656
+ var RETRYABLE_PASSTHROUGH_CODE = "ECONNRESET";
17657
+ function upstreamUnreachableDetail(err) {
17658
+ return err.message || err.code || err.name || "connection failed";
17659
+ }
17660
+ function createPassthroughAgent() {
17661
+ return new https.Agent({
17662
+ keepAlive: true,
17663
+ timeout: https.globalAgent.options.timeout ?? 5e3
17664
+ });
17665
+ }
17394
17666
  function numericUsage(value) {
17395
17667
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
17396
17668
  }
@@ -17539,6 +17811,7 @@ function requestHeadersWithoutProxyHeaders(req) {
17539
17811
  function forwardRawAnthropicRequest(req, res, rawBody, origin, rejectUnauthorized, agent, onErrorResponse, onResponseUsage, lifecycle, isLocalShutdown = () => false) {
17540
17812
  return new Promise((resolve3) => {
17541
17813
  const startedAt = Date.now();
17814
+ const retryBudget = passthroughUpstreamRetries();
17542
17815
  let lastActivityAt = startedAt;
17543
17816
  let headersReceived = false;
17544
17817
  let firstByteAt;
@@ -17588,42 +17861,91 @@ function forwardRawAnthropicRequest(req, res, rawBody, origin, rejectUnauthorize
17588
17861
  resolve3();
17589
17862
  };
17590
17863
  const errorType = (err) => err.code ?? err.name;
17591
- const upstream = https.request({
17592
- protocol: "https:",
17593
- hostname: origin.hostname,
17594
- port: origin.port || 443,
17595
- method: req.method,
17596
- path: req.url,
17597
- headers: requestHeadersWithoutProxyHeaders(req),
17598
- servername: net.isIP(origin.hostname) ? void 0 : origin.hostname,
17599
- rejectUnauthorized,
17600
- agent
17601
- }, (upstreamRes) => {
17602
- headersReceived = true;
17603
- statusCode = upstreamRes.statusCode ?? 502;
17604
- lastActivityAt = Date.now();
17605
- upstreamRes.on("data", (chunk) => {
17606
- const now = Date.now();
17607
- if (firstByteAt === void 0) {
17608
- firstByteAt = now;
17609
- writeLifecycle("response_started", {
17864
+ let upstream;
17865
+ let attempt = 0;
17866
+ const isRetryableUpstreamFailure = (err, request3) => attempt <= retryBudget && !headersReceived && !failed && !clientDisconnected && !isLocalShutdown() && request3.reusedSocket === true && err.code === RETRYABLE_PASSTHROUGH_CODE;
17867
+ const sendAttempt = () => {
17868
+ attempt += 1;
17869
+ const request3 = https.request({
17870
+ protocol: "https:",
17871
+ hostname: origin.hostname,
17872
+ port: origin.port || 443,
17873
+ method: req.method,
17874
+ path: req.url,
17875
+ headers: requestHeadersWithoutProxyHeaders(req),
17876
+ servername: net.isIP(origin.hostname) ? void 0 : origin.hostname,
17877
+ rejectUnauthorized,
17878
+ agent
17879
+ }, (upstreamRes) => {
17880
+ headersReceived = true;
17881
+ statusCode = upstreamRes.statusCode ?? 502;
17882
+ lastActivityAt = Date.now();
17883
+ upstreamRes.on("data", (chunk) => {
17884
+ const now = Date.now();
17885
+ if (firstByteAt === void 0) {
17886
+ firstByteAt = now;
17887
+ writeLifecycle("response_started", {
17888
+ statusCode,
17889
+ durationMs: now - startedAt,
17890
+ timeToFirstByteMs: now - startedAt,
17891
+ ...attempt > 1 ? { attempt } : {}
17892
+ });
17893
+ }
17894
+ lastActivityAt = now;
17895
+ bytes += chunk.length;
17896
+ chunks += 1;
17897
+ });
17898
+ copyResponse(upstreamRes, res, onErrorResponse, onResponseUsage);
17899
+ upstreamRes.once("end", () => {
17900
+ responseEnded = true;
17901
+ lastActivityAt = Date.now();
17902
+ done();
17903
+ });
17904
+ upstreamRes.once("error", (err) => {
17905
+ if (clientDisconnected || failed) {
17906
+ done();
17907
+ return;
17908
+ }
17909
+ failed = true;
17910
+ stopProgress();
17911
+ const now = Date.now();
17912
+ writeLifecycle("response_failed", {
17610
17913
  statusCode,
17914
+ phase: responsePhase(),
17611
17915
  durationMs: now - startedAt,
17612
- timeToFirstByteMs: now - startedAt
17916
+ ...firstByteAt !== void 0 ? { timeToFirstByteMs: firstByteAt - startedAt } : {},
17917
+ idleMs: now - lastActivityAt,
17918
+ bytes,
17919
+ chunks,
17920
+ errorType: errorType(err),
17921
+ terminationSource: "upstream_failure",
17922
+ attempt
17613
17923
  });
17614
- }
17615
- lastActivityAt = now;
17616
- bytes += chunk.length;
17617
- chunks += 1;
17618
- });
17619
- copyResponse(upstreamRes, res, onErrorResponse, onResponseUsage);
17620
- upstreamRes.once("end", () => {
17621
- responseEnded = true;
17622
- lastActivityAt = Date.now();
17623
- done();
17924
+ done();
17925
+ });
17624
17926
  });
17625
- upstreamRes.once("error", (err) => {
17626
- if (clientDisconnected || failed) {
17927
+ upstream = request3;
17928
+ request3.once("error", (err) => {
17929
+ if (clientDisconnected) {
17930
+ done();
17931
+ return;
17932
+ }
17933
+ if (isRetryableUpstreamFailure(err, request3)) {
17934
+ const retriedAt = Date.now();
17935
+ writeLifecycle("response_retried", {
17936
+ phase: responsePhase(),
17937
+ durationMs: retriedAt - startedAt,
17938
+ idleMs: retriedAt - lastActivityAt,
17939
+ errorType: errorType(err),
17940
+ terminationSource: "upstream_failure",
17941
+ attempt,
17942
+ reusedSocket: true
17943
+ });
17944
+ lastActivityAt = retriedAt;
17945
+ sendAttempt();
17946
+ return;
17947
+ }
17948
+ if (failed) {
17627
17949
  done();
17628
17950
  return;
17629
17951
  }
@@ -17631,19 +17953,25 @@ function forwardRawAnthropicRequest(req, res, rawBody, origin, rejectUnauthorize
17631
17953
  stopProgress();
17632
17954
  const now = Date.now();
17633
17955
  writeLifecycle("response_failed", {
17634
- statusCode,
17956
+ statusCode: 502,
17635
17957
  phase: responsePhase(),
17636
17958
  durationMs: now - startedAt,
17637
- ...firstByteAt !== void 0 ? { timeToFirstByteMs: firstByteAt - startedAt } : {},
17638
17959
  idleMs: now - lastActivityAt,
17639
17960
  bytes,
17640
17961
  chunks,
17641
17962
  errorType: errorType(err),
17642
- terminationSource: "upstream_failure"
17963
+ terminationSource: isLocalShutdown() ? "local_shutdown" : "upstream_failure",
17964
+ attempt,
17965
+ reusedSocket: request3.reusedSocket === true
17643
17966
  });
17967
+ const detail = upstreamUnreachableDetail(err);
17968
+ onErrorResponse?.(502, `Anthropic upstream unreachable: ${detail}`);
17969
+ if (!res.headersSent) res.writeHead(502, { "Content-Type": "text/plain" });
17970
+ res.end(`Anthropic upstream unreachable: ${detail}`);
17644
17971
  done();
17645
17972
  });
17646
- });
17973
+ request3.end(rawBody);
17974
+ };
17647
17975
  res.once("finish", () => {
17648
17976
  stopProgress();
17649
17977
  if (failed || clientDisconnected) return;
@@ -17653,7 +17981,8 @@ function forwardRawAnthropicRequest(req, res, rawBody, origin, rejectUnauthorize
17653
17981
  durationMs: now - startedAt,
17654
17982
  ...firstByteAt !== void 0 ? { timeToFirstByteMs: firstByteAt - startedAt } : {},
17655
17983
  bytes,
17656
- chunks
17984
+ chunks,
17985
+ ...attempt > 1 ? { attempt } : {}
17657
17986
  });
17658
17987
  });
17659
17988
  res.once("close", () => {
@@ -17671,33 +18000,10 @@ function forwardRawAnthropicRequest(req, res, rawBody, origin, rejectUnauthorize
17671
18000
  chunks,
17672
18001
  terminationSource: isLocalShutdown() ? "local_shutdown" : "downstream_client"
17673
18002
  });
17674
- upstream.destroy(new Error("Client disconnected"));
17675
- done();
17676
- });
17677
- upstream.once("error", (err) => {
17678
- if (clientDisconnected) {
17679
- done();
17680
- return;
17681
- }
17682
- failed = true;
17683
- stopProgress();
17684
- const now = Date.now();
17685
- writeLifecycle("response_failed", {
17686
- statusCode: 502,
17687
- phase: responsePhase(),
17688
- durationMs: now - startedAt,
17689
- idleMs: now - lastActivityAt,
17690
- bytes,
17691
- chunks,
17692
- errorType: errorType(err),
17693
- terminationSource: "upstream_failure"
17694
- });
17695
- onErrorResponse?.(502, `Anthropic upstream unreachable: ${err.message}`);
17696
- if (!res.headersSent) res.writeHead(502, { "Content-Type": "text/plain" });
17697
- res.end(`Anthropic upstream unreachable: ${err.message}`);
18003
+ upstream?.destroy(new Error("Client disconnected"));
17698
18004
  done();
17699
18005
  });
17700
- upstream.end(rawBody);
18006
+ sendAttempt();
17701
18007
  });
17702
18008
  }
17703
18009
  function forwardToAdapter(req, res, rawBody, adapter, adapterRequest = http2.request, adapterAgent, lifecycle, isLocalShutdown = () => false) {
@@ -18174,6 +18480,7 @@ async function startHttpProxy(options) {
18174
18480
  } else {
18175
18481
  anthropicAgent = outboundHttpProxyAgent(anthropicOrigin.href);
18176
18482
  }
18483
+ anthropicAgent ??= createPassthroughAgent();
18177
18484
  return {
18178
18485
  host: options.host ?? "127.0.0.1",
18179
18486
  port: address.port,
@@ -18307,11 +18614,15 @@ async function startConfiguredHttpProxy(port, debug = false, inferenceLogPath =
18307
18614
  debugLogPath,
18308
18615
  webSocketDiagnosticsLogPath
18309
18616
  ));
18617
+ let caWarning;
18310
18618
  handle.caCertPath = ensureHttpProxyCaBundle(
18311
18619
  handle.caCertPath,
18312
- process.env["NODE_EXTRA_CA_CERTS"]
18620
+ process.env["NODE_EXTRA_CA_CERTS"],
18621
+ (message) => {
18622
+ caWarning = message;
18623
+ }
18313
18624
  );
18314
- return { handle, loaded };
18625
+ return { handle, loaded, ...caWarning ? { caWarning } : {} };
18315
18626
  }
18316
18627
  function waitForShutdown() {
18317
18628
  return new Promise((resolve3) => {
@@ -18340,7 +18651,7 @@ async function runHttpProxyServerCommand(debug = false, webSocketDiagnostics = f
18340
18651
  p9.log.error(`Failed to start HTTP proxy: ${err instanceof Error ? err.message : String(err)}`);
18341
18652
  return 1;
18342
18653
  }
18343
- const { handle, loaded } = started;
18654
+ const { handle, loaded, caWarning } = started;
18344
18655
  writeProxyLifecycleLog(inferenceLogPath, {
18345
18656
  event: "proxy_started",
18346
18657
  pid: process.pid,
@@ -18352,6 +18663,10 @@ async function runHttpProxyServerCommand(debug = false, webSocketDiagnostics = f
18352
18663
  console.log(pc10.bold(pc10.green("clodex proxy-mode server running")));
18353
18664
  for (const line of formatHttpProxyEnvironmentLines(handle)) console.log(line);
18354
18665
  console.log(` Request log: ${handle.inferenceLogPath}`);
18666
+ if (caWarning) {
18667
+ console.log("");
18668
+ console.log(pc10.yellow(` clodex: ${caWarning}`));
18669
+ }
18355
18670
  if (handle.webSocketDiagnosticsLogPath) {
18356
18671
  console.log(` WebSocket diagnostics: ${handle.webSocketDiagnosticsLogPath}`);
18357
18672
  console.log(pc10.yellow(" Diagnostic mode records request headers and metadata; credential headers are redacted."));
@@ -19937,7 +20252,11 @@ async function runClaudeHttpProxyCommand(parsed, claudeArgs, agentStdout) {
19937
20252
  p12.log.error(`Failed to start proxy: ${err instanceof Error ? err.message : String(err)}`);
19938
20253
  return 1;
19939
20254
  }
19940
- const { handle, loaded } = started;
20255
+ const { handle, loaded, caWarning } = started;
20256
+ if (caWarning) {
20257
+ if (agentStdout) emitParentNotice(`clodex: ${caWarning}`);
20258
+ else p12.log.warn(caWarning);
20259
+ }
19941
20260
  const inheritedProxyPort = (() => {
19942
20261
  const value = process.env["HTTPS_PROXY"] ?? process.env["HTTP_PROXY"] ?? process.env["https_proxy"] ?? process.env["http_proxy"];
19943
20262
  if (!value) return void 0;