@bman654/clodex 2.18.0 → 2.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -346,7 +346,7 @@ import { join } from "path";
346
346
  // package.json
347
347
  var package_default = {
348
348
  name: "@bman654/clodex",
349
- version: "2.18.0",
349
+ version: "2.18.1",
350
350
  publishConfig: {
351
351
  access: "public"
352
352
  },
@@ -401,10 +401,9 @@ var package_default = {
401
401
  "https-proxy-agent": "9.1.0",
402
402
  "ipaddr.js": "2.4.0",
403
403
  "node-forge": "1.4.0",
404
- "node-gyp-build": "4.8.4",
405
404
  open: "11.0.0",
406
405
  picocolors: "1.1.1",
407
- tweakcc: "4.3.0",
406
+ tweakcc: "4.3.3",
408
407
  undici: "7.29.0",
409
408
  ws: "8.21.0"
410
409
  },
@@ -3873,8 +3872,8 @@ import {
3873
3872
  statSync as statSync7,
3874
3873
  unlinkSync as unlinkSync3,
3875
3874
  writeFileSync as writeFileSync5,
3876
- openSync as openSync8,
3877
- closeSync as closeSync8,
3875
+ openSync as openSync9,
3876
+ closeSync as closeSync9,
3878
3877
  realpathSync as realpathSync3
3879
3878
  } from "fs";
3880
3879
  import { homedir as homedir3 } from "os";
@@ -6064,11 +6063,11 @@ var OPENAI_OAUTH_MODEL_SEEDS = [
6064
6063
  // program, so most installs will never see this id in their catalog.
6065
6064
  { id: "gpt-daybreak-blue-latest", name: "GPT Daybreak Blue", contextWindow: 272e3, maxContextWindow: 872e3, maxOutputTokens: 128e3, reasoning: true, useResponsesLite: true, preferWebSockets: true, minimalClientVersion: "0.144.0" },
6066
6065
  // GPT-5.6 family (Sol / Terra / Luna)
6067
- { id: "gpt-5.6-sol", name: "GPT-5.6 Sol", contextWindow: 272e3, maxContextWindow: 872e3, maxOutputTokens: 128e3, reasoning: true, minimalClientVersion: "0.144.0" },
6068
- { id: "gpt-5.6-terra", name: "GPT-5.6 Terra", contextWindow: 272e3, maxContextWindow: 872e3, maxOutputTokens: 128e3, reasoning: true, minimalClientVersion: "0.144.0" },
6066
+ { id: "gpt-5.6-sol", name: "GPT-5.6 Sol", contextWindow: 272e3, maxContextWindow: 872e3, maxOutputTokens: 128e3, reasoning: true, useResponsesLite: true, preferWebSockets: true, minimalClientVersion: "0.144.0" },
6067
+ { id: "gpt-5.6-terra", name: "GPT-5.6 Terra", contextWindow: 272e3, maxContextWindow: 872e3, maxOutputTokens: 128e3, reasoning: true, useResponsesLite: true, preferWebSockets: true, minimalClientVersion: "0.144.0" },
6069
6068
  { id: "gpt-5.6-luna", name: "GPT-5.6 Luna", contextWindow: 272e3, maxContextWindow: 872e3, maxOutputTokens: 128e3, reasoning: true, useResponsesLite: true, preferWebSockets: true, minimalClientVersion: "0.144.0" },
6070
6069
  // GPT-5.5 family (Pro)
6071
- { id: "gpt-5.5", name: "GPT-5.5", contextWindow: 272e3, maxOutputTokens: 128e3, reasoning: true },
6070
+ { id: "gpt-5.5", name: "GPT-5.5", contextWindow: 272e3, maxContextWindow: 272e3, maxOutputTokens: 128e3, reasoning: true, useResponsesLite: false, preferWebSockets: true, minimalClientVersion: "0.124.0" },
6072
6071
  // GPT-5.4 family
6073
6072
  { id: "gpt-5.4", name: "GPT-5.4", contextWindow: 272e3, maxContextWindow: 1e6 },
6074
6073
  { id: "gpt-5.4-mini", name: "GPT-5.4 Mini", contextWindow: 272e3 },
@@ -7380,270 +7379,44 @@ function inspectClaudeNativeBinaryPlaceholder(path) {
7380
7379
  }
7381
7380
  }
7382
7381
 
7383
- // src/bun-entry-module.ts
7384
- import { closeSync as closeSync3, openSync as openSync3, readSync as readSync2, statSync as statSync6, writeSync } from "fs";
7382
+ // src/patch-signature.ts
7385
7383
  import { execFileSync as execFileSync2 } from "child_process";
7386
- var BUN_TRAILER = Buffer.from("\n---- Bun! ----\n");
7387
- var BUN_OFFSETS_BYTES = 32;
7388
- var TAIL_SCAN_BYTES = 16 * 1024 * 1024;
7389
- var MODULE_STRUCT_BYTES_CURRENT = 52;
7390
- var MODULE_STRUCT_BYTES_LEGACY = 36;
7391
- var CONTENTS_FIELD_AT = 8;
7392
- var SOURCEMAP_FIELD_AT = 16;
7393
- var BYTECODE_FIELD_AT = 24;
7394
- var MODULE_INFO_FIELD_AT = 32;
7395
- var BYTECODE_ORIGIN_PATH_FIELD_AT = 40;
7396
- var BUN_BLOB_FLAGS = {
7397
- /** Every module's source text lies in one run no other region falls inside. */
7398
- SOURCE_TEXT_CONTIGUOUS: 1 << 4,
7399
- /** A `[u32; modules]` of each module's source hash follows the module table. */
7400
- HAS_SOURCE_HASHES: 1 << 5,
7401
- /** After the source hashes: `u32 count`, then `count` x `{ u32 id, offset, length }`. */
7402
- HAS_BUILTIN_BYTECODE: 1 << 6,
7403
- /** After the builtin-bytecode table: one `{ offset, length }` for the shared string table. */
7404
- HAS_BYTECODE_STRING_TABLE: 1 << 7
7405
- };
7406
- var LOADER_FROM_END = 3;
7407
- var BUN_JAVASCRIPT_LOADER = 1;
7408
- var MAX_MODULE_NAME_BYTES = 4096;
7409
- var MIN_SHIMMABLE_NAME_BYTES = 7;
7410
- function tweakccRecognizesModuleName(name) {
7411
- return name.endsWith("/claude") || name === "claude" || name.endsWith("/claude.exe") || name === "claude.exe" || name.endsWith("/src/entrypoints/cli.js") || name === "src/entrypoints/cli.js";
7412
- }
7413
- function entryModuleShimName(byteLength) {
7414
- if (byteLength < MIN_SHIMMABLE_NAME_BYTES) return null;
7415
- const padding = byteLength - MIN_SHIMMABLE_NAME_BYTES;
7416
- return "/clodex".padEnd(padding, "-").slice(0, padding) + "/claude";
7417
- }
7418
- function readAt(fd, length, position) {
7419
- if (length <= 0 || position < 0) return null;
7420
- const buffer = Buffer.alloc(length);
7421
- const read = readSync2(fd, buffer, 0, length, position);
7422
- return read === length ? buffer : null;
7423
- }
7424
- function readBunModuleNames(fd, fileSize) {
7425
- const tailLength = Math.min(fileSize, TAIL_SCAN_BYTES);
7426
- const tail = readAt(fd, tailLength, fileSize - tailLength);
7427
- if (!tail) return null;
7428
- const tailAt = fileSize - tailLength;
7429
- for (let searchFrom = tail.length - 1; searchFrom >= 0; ) {
7430
- const trailerInTail = tail.lastIndexOf(BUN_TRAILER, searchFrom);
7431
- if (trailerInTail < 0) return null;
7432
- const parsed = parseBunModuleNamesAt(fd, tailAt + trailerInTail - BUN_OFFSETS_BYTES);
7433
- if (parsed) return parsed;
7434
- searchFrom = trailerInTail - 1;
7435
- }
7436
- return null;
7437
- }
7438
- function parseBunModuleNamesAt(fd, offsetsAt) {
7439
- try {
7440
- return parseBunModuleNamesAtUnchecked(fd, offsetsAt);
7441
- } catch {
7442
- return null;
7443
- }
7444
- }
7445
- function parseBunModuleNamesAtUnchecked(fd, offsetsAt) {
7446
- const offsets = readAt(fd, BUN_OFFSETS_BYTES, offsetsAt);
7447
- if (!offsets) return null;
7448
- const byteCount = offsets.readBigUInt64LE(0);
7449
- const modulesOffset = offsets.readUInt32LE(8);
7450
- const modulesLength = offsets.readUInt32LE(12);
7451
- const entryPointId = offsets.readUInt32LE(16);
7452
- const compileExecArgvOffset = offsets.readUInt32LE(20);
7453
- const compileExecArgvLength = offsets.readUInt32LE(24);
7454
- const flags = offsets.readUInt32LE(28);
7455
- if (byteCount <= 0n || byteCount > BigInt(offsetsAt)) return null;
7456
- const blobAt = offsetsAt - Number(byteCount);
7457
- if (modulesLength <= 0 || BigInt(modulesOffset) + BigInt(modulesLength) > byteCount) return null;
7458
- const structBytes = modulesLength % MODULE_STRUCT_BYTES_LEGACY === 0 && modulesLength % MODULE_STRUCT_BYTES_CURRENT !== 0 ? MODULE_STRUCT_BYTES_LEGACY : MODULE_STRUCT_BYTES_CURRENT;
7459
- const moduleCount = Math.floor(modulesLength / structBytes);
7460
- if (moduleCount <= 0 || entryPointId >= moduleCount) return null;
7461
- const modules = readAt(fd, moduleCount * structBytes, blobAt + modulesOffset);
7462
- if (!modules) return null;
7463
- const names = [];
7464
- const nameOffsets = [];
7465
- const contents = [];
7466
- const sourcemap = [];
7467
- const bytecode = [];
7468
- const moduleInfo = [];
7469
- const bytecodeOriginPath = [];
7470
- const loaders = [];
7471
- for (let index = 0; index < moduleCount; index++) {
7472
- const nameOffset = modules.readUInt32LE(index * structBytes);
7473
- const nameLength = modules.readUInt32LE(index * structBytes + 4);
7474
- if (nameLength <= 0 || nameLength > MAX_MODULE_NAME_BYTES) return null;
7475
- if (BigInt(nameOffset) + BigInt(nameLength) > byteCount) return null;
7476
- const bytes = readAt(fd, nameLength + 1, blobAt + nameOffset);
7477
- if (!bytes || bytes[nameLength] !== 0) return null;
7478
- const name = bytes.subarray(0, nameLength).toString("utf8");
7479
- if (!/^[\x20-\x7e]+$/.test(name)) return null;
7480
- names.push(name);
7481
- nameOffsets.push(blobAt + nameOffset);
7482
- const pairAt = (field) => ({
7483
- offset: modules.readUInt32LE(index * structBytes + field),
7484
- length: modules.readUInt32LE(index * structBytes + field + 4)
7485
- });
7486
- contents.push(pairAt(CONTENTS_FIELD_AT));
7487
- sourcemap.push(pairAt(SOURCEMAP_FIELD_AT));
7488
- bytecode.push(pairAt(BYTECODE_FIELD_AT));
7489
- const current = structBytes === MODULE_STRUCT_BYTES_CURRENT;
7490
- moduleInfo.push(current ? pairAt(MODULE_INFO_FIELD_AT) : { offset: 0, length: 0 });
7491
- bytecodeOriginPath.push(
7492
- current ? pairAt(BYTECODE_ORIGIN_PATH_FIELD_AT) : { offset: 0, length: 0 }
7493
- );
7494
- loaders.push(modules.readUInt8(index * structBytes + structBytes - LOADER_FROM_END));
7495
- }
7496
- return {
7497
- names,
7498
- entryPointId,
7499
- offsets: nameOffsets,
7500
- contents,
7501
- sourcemap,
7502
- bytecode,
7503
- moduleInfo,
7504
- bytecodeOriginPath,
7505
- loaders,
7506
- blobAt,
7507
- modulesAt: blobAt + modulesOffset,
7508
- modulesOffset,
7509
- modulesLength,
7510
- structBytes,
7511
- byteCount: Number(byteCount),
7512
- compileExecArgv: { offset: compileExecArgvOffset, length: compileExecArgvLength },
7513
- flags
7514
- };
7515
- }
7516
- function findStandIn(fd, fileSize, marker) {
7517
- const needle = Buffer.from(marker);
7518
- const chunkBytes = 8 * 1024 * 1024;
7519
- const offsets = [];
7520
- let carry = Buffer.alloc(0);
7521
- for (let position = 0; position < fileSize; ) {
7522
- const length = Math.min(chunkBytes, fileSize - position);
7523
- const chunk = readAt(fd, length, position);
7524
- if (!chunk) throw new Error("could not re-read the candidate to verify the entry-module name");
7525
- const window = carry.length > 0 ? Buffer.concat([carry, chunk]) : chunk;
7526
- const windowAt = position - carry.length;
7527
- for (let at = window.indexOf(needle); at >= 0; at = window.indexOf(needle, at + 1)) {
7528
- offsets.push(windowAt + at);
7529
- }
7530
- carry = Buffer.from(window.subarray(Math.max(0, window.length - (needle.length - 1))));
7531
- position += length;
7532
- }
7533
- return offsets;
7534
- }
7535
- function restoreEveryStandIn(fd, fileSize, shim) {
7536
- const moduleNameCopies = () => findStandIn(fd, fileSize, shim.marker).filter((offset) => isModuleNameAt(fd, offset, shim.marker));
7537
- const found = moduleNameCopies();
7538
- for (const offset of found) writeNameBytes(fd, shim.original, offset);
7539
- if (found.length > 0 && moduleNameCopies().length > 0) {
7540
- throw new Error(`the entry-module stand-in ${shim.marker} survived restoration`);
7541
- }
7542
- }
7543
- function isModuleNameAt(fd, offset, marker) {
7544
- const after = readAt(fd, 1, offset + Buffer.byteLength(marker));
7545
- return after !== null && after[0] === 0;
7546
- }
7547
- function writeNameBytes(fd, name, offset) {
7548
- const bytes = Buffer.from(name);
7549
- const written = writeSync(fd, bytes, 0, bytes.length, offset);
7550
- if (written !== bytes.length) {
7551
- throw new Error(`wrote ${written} of ${bytes.length} entry-module name bytes at ${offset}`);
7552
- }
7553
- }
7554
- function isMachO(fd) {
7555
- const magic = readAt(fd, 4, 0);
7556
- if (!magic) return false;
7557
- const value = magic.readUInt32BE(0);
7558
- return value === 4277009102 || value === 4277009103 || value === 3472551422 || value === 3489328638 || value === 3405691582 || value === 3405691583;
7559
- }
7560
- function readBunModuleTable(path) {
7384
+ import { closeSync as closeSync3, openSync as openSync3, readSync as readSync2 } from "fs";
7385
+ function signAndVerifyMachOCandidate(path, installPath = path) {
7386
+ if (process.platform !== "darwin") return;
7561
7387
  const fd = openSync3(path, "r");
7388
+ let machO = false;
7562
7389
  try {
7563
- return readBunModuleNames(fd, statSync6(path).size);
7564
- } finally {
7565
- closeSync3(fd);
7566
- }
7567
- }
7568
- function readBunJavaScriptModules(path) {
7569
- const fd = openSync3(path, "r");
7570
- try {
7571
- const parsed = readBunModuleNames(fd, statSync6(path).size);
7572
- if (!parsed) return null;
7573
- const modules = [];
7574
- for (let index = 0; index < parsed.names.length; index++) {
7575
- if (parsed.loaders[index] !== BUN_JAVASCRIPT_LOADER) continue;
7576
- const range = parsed.contents[index];
7577
- if (range.offset < 0 || range.length < 0 || range.offset + range.length > parsed.byteCount) {
7578
- return null;
7579
- }
7580
- const bytes = range.length === 0 ? Buffer.alloc(0) : readAt(fd, range.length, parsed.blobAt + range.offset);
7581
- if (!bytes) return null;
7582
- modules.push({
7583
- index,
7584
- name: parsed.names[index],
7585
- source: bytes.toString("utf8"),
7586
- byteLength: bytes.length
7587
- });
7390
+ const magic = Buffer.alloc(4);
7391
+ if (readSync2(fd, magic, 0, 4, 0) === 4) {
7392
+ machO = [
7393
+ 4277009102,
7394
+ 4277009103,
7395
+ 3472551422,
7396
+ 3489328638,
7397
+ 3405691582,
7398
+ 3405691583,
7399
+ 3199925962
7400
+ ].includes(magic.readUInt32BE(0));
7588
7401
  }
7589
- return modules;
7590
7402
  } finally {
7591
7403
  closeSync3(fd);
7592
7404
  }
7593
- }
7594
- function shimEntryModuleName(path) {
7595
- const fd = openSync3(path, "r+");
7405
+ if (!machO) return;
7596
7406
  try {
7597
- const parsed = readBunModuleNames(fd, statSync6(path).size);
7598
- if (!parsed) return null;
7599
- if (parsed.names.some(tweakccRecognizesModuleName)) return null;
7600
- const original = parsed.names[parsed.entryPointId];
7601
- const offset = parsed.offsets[parsed.entryPointId];
7602
- const marker = entryModuleShimName(Buffer.byteLength(original));
7603
- if (marker === null) return null;
7604
- if (findStandIn(fd, statSync6(path).size, marker).some((offset2) => isModuleNameAt(fd, offset2, marker))) {
7605
- return null;
7606
- }
7607
- writeNameBytes(fd, marker, offset);
7608
- return { offset, original, marker };
7609
- } finally {
7610
- closeSync3(fd);
7611
- }
7612
- }
7613
- function restoreEntryModuleName(path, shim, { resign }) {
7614
- const fd = openSync3(path, "r+");
7615
- let machO;
7616
- try {
7617
- const parsed = readBunModuleNames(fd, statSync6(path).size);
7618
- const offset = parsed?.offsets[parsed.entryPointId];
7619
- if (!parsed || offset === void 0 || parsed.names[parsed.entryPointId] !== shim.marker) {
7620
- throw new Error(
7621
- `expected the entry module of ${path} to be named ${shim.marker}, found ${parsed ? JSON.stringify(parsed.names[parsed.entryPointId]) : "no readable Bun module list"}`
7622
- );
7623
- }
7624
- writeNameBytes(fd, shim.original, offset);
7625
- restoreEveryStandIn(fd, statSync6(path).size, shim);
7626
- machO = resign;
7627
- } finally {
7628
- closeSync3(fd);
7629
- }
7630
- if (machO) resignMachOBinary(path);
7631
- }
7632
- function resignMachOBinary(path) {
7633
- const fd = openSync3(path, "r");
7634
- let machO;
7635
- try {
7636
- machO = isMachO(fd);
7637
- } finally {
7638
- closeSync3(fd);
7639
- }
7640
- if (machO && process.platform === "darwin") {
7641
- execFileSync2("codesign", ["-s", "-", "-f", path], { stdio: "ignore" });
7407
+ execFileSync2("codesign", ["-s", "-", "-f", path], { stdio: "pipe" });
7408
+ execFileSync2("codesign", ["--verify", "--strict", path], { stdio: "pipe" });
7409
+ } catch (error) {
7410
+ const stderr = error?.stderr;
7411
+ const detail = String(stderr ?? "").trim().split(`${path}: `).join("").split(/\r?\n/).filter((line) => line !== "replacing existing signature").join("\n").trim() || (error instanceof Error ? error.message.trimEnd() : String(error).trimEnd());
7412
+ throw new Error(
7413
+ `Mach-O signing or verification failed for ${installPath}: ${detail}. Claude Code was left unchanged.`
7414
+ );
7642
7415
  }
7643
7416
  }
7644
7417
 
7645
7418
  // src/bun-compiled-pointer.ts
7646
- import { closeSync as closeSync4, fstatSync as fstatSync2, openSync as openSync4, readSync as readSync3, writeSync as writeSync2 } from "fs";
7419
+ import { closeSync as closeSync4, fstatSync as fstatSync2, openSync as openSync4, readSync as readSync3, writeSync } from "fs";
7647
7420
  var TWEAKCC_SCAN_STRIDE = 16384n;
7648
7421
  var SCAN_CHUNK = 1 << 20;
7649
7422
  var ELF_MAGIC = 1179403647;
@@ -7651,7 +7424,7 @@ var ELFCLASS64 = 2;
7651
7424
  var ELFDATA2LSB = 1;
7652
7425
  var PT_LOAD = 1;
7653
7426
  var PF_W = 2;
7654
- function readAt2(fd, length, position) {
7427
+ function readAt(fd, length, position) {
7655
7428
  const buf = Buffer.alloc(length);
7656
7429
  let read = 0;
7657
7430
  while (read < length) {
@@ -7662,7 +7435,7 @@ function readAt2(fd, length, position) {
7662
7435
  return read === length ? buf : buf.subarray(0, read);
7663
7436
  }
7664
7437
  function readElfLayout(fd) {
7665
- const ident = readAt2(fd, 64, 0);
7438
+ const ident = readAt(fd, 64, 0);
7666
7439
  if (ident.length < 64) return null;
7667
7440
  if (ident.readUInt32LE(0) !== ELF_MAGIC) return null;
7668
7441
  if (ident[4] !== ELFCLASS64 || ident[5] !== ELFDATA2LSB) return null;
@@ -7678,7 +7451,7 @@ function readElfLayout(fd) {
7678
7451
  const fileSize = fstatSync2(fd).size;
7679
7452
  const fits = (offset, length) => Number.isSafeInteger(offset) && offset >= 0 && length >= 0 && offset + length <= fileSize;
7680
7453
  if (!fits(Number(shoff), shnum * shentsize)) return null;
7681
- const shTable = readAt2(fd, shnum * shentsize, Number(shoff));
7454
+ const shTable = readAt(fd, shnum * shentsize, Number(shoff));
7682
7455
  if (shTable.length !== shnum * shentsize) return null;
7683
7456
  const raw = [];
7684
7457
  for (let i = 0; i < shnum; i++) {
@@ -7692,7 +7465,7 @@ function readElfLayout(fd) {
7692
7465
  }
7693
7466
  const strtab = raw[shstrndx];
7694
7467
  if (!fits(Number(strtab.offset), Number(strtab.size))) return null;
7695
- const names = readAt2(fd, Number(strtab.size), Number(strtab.offset));
7468
+ const names = readAt(fd, Number(strtab.size), Number(strtab.offset));
7696
7469
  const sections = raw.map((section) => {
7697
7470
  const start = section.nameOffset;
7698
7471
  let end = start;
@@ -7705,7 +7478,7 @@ function readElfLayout(fd) {
7705
7478
  };
7706
7479
  });
7707
7480
  if (!fits(Number(phoff), phnum * phentsize)) return null;
7708
- const phTable = readAt2(fd, phnum * phentsize, Number(phoff));
7481
+ const phTable = readAt(fd, phnum * phentsize, Number(phoff));
7709
7482
  if (phTable.length !== phnum * phentsize) return null;
7710
7483
  const segments = [];
7711
7484
  for (let i = 0; i < phnum; i++) {
@@ -7742,7 +7515,7 @@ function tweakccWouldFind(fd, segment, needle) {
7742
7515
  const last = segment.vaddr + segment.filesz - 8n;
7743
7516
  for (let vaddr = first; vaddr <= last; vaddr += TWEAKCC_SCAN_STRIDE) {
7744
7517
  const at = Number(segment.offset + (vaddr - segment.vaddr));
7745
- if (readAt2(fd, 8, at).equals(needle)) return vaddr;
7518
+ if (readAt(fd, 8, at).equals(needle)) return vaddr;
7746
7519
  }
7747
7520
  return null;
7748
7521
  }
@@ -7751,7 +7524,7 @@ function scanForNeedle(fd, from, to, needle, skipFrom, skipTo) {
7751
7524
  for (let start = from; start < to; start += SCAN_CHUNK - 7) {
7752
7525
  const length = Math.min(SCAN_CHUNK, to - start);
7753
7526
  if (length < 8) break;
7754
- const chunk = readAt2(fd, length, start);
7527
+ const chunk = readAt(fd, length, start);
7755
7528
  let at = 0;
7756
7529
  for (; ; ) {
7757
7530
  const found = chunk.indexOf(needle, at);
@@ -7809,9 +7582,9 @@ function shimBunCompiledPointer(path) {
7809
7582
  throw new Error("no address tweakcc's ELF repack scans is usable for Bun's blob pointer");
7810
7583
  }
7811
7584
  const standInOffset = Number(segment.offset + (standInVaddr - segment.vaddr));
7812
- const displaced = readAt2(fd, 8, standInOffset);
7585
+ const displaced = readAt(fd, 8, standInOffset);
7813
7586
  if (displaced.length !== 8) throw new Error("could not read the bytes Bun's blob pointer displaces");
7814
- writeSync2(fd, needle, 0, 8, standInOffset);
7587
+ writeSync(fd, needle, 0, 8, standInOffset);
7815
7588
  return { pointerVaddr, standInVaddr, displaced, bunVaddr: bun.addr };
7816
7589
  } finally {
7817
7590
  closeSync4(fd);
@@ -7831,7 +7604,7 @@ function restoreBunCompiledPointer(path, shim) {
7831
7604
  "the repack left Bun's blob pointer outside the loaded image, or in more than one segment of it"
7832
7605
  );
7833
7606
  }
7834
- const standIn = readAt2(fd, 8, standInOffset);
7607
+ const standIn = readAt(fd, 8, standInOffset);
7835
7608
  if (standIn.length !== 8) {
7836
7609
  throw new Error("the repacked binary ends before the stand-in for Bun's blob pointer");
7837
7610
  }
@@ -7846,12 +7619,12 @@ function restoreBunCompiledPointer(path, shim) {
7846
7619
  }
7847
7620
  const value = Buffer.alloc(8);
7848
7621
  value.writeBigUInt64LE(written);
7849
- writeSync2(fd, value, 0, 8, pointerOffset);
7850
- writeSync2(fd, shim.displaced, 0, 8, standInOffset);
7851
- if (!readAt2(fd, 8, pointerOffset).equals(value)) {
7622
+ writeSync(fd, value, 0, 8, pointerOffset);
7623
+ writeSync(fd, shim.displaced, 0, 8, standInOffset);
7624
+ if (!readAt(fd, 8, pointerOffset).equals(value)) {
7852
7625
  throw new Error("Bun's blob pointer did not take the repacked address");
7853
7626
  }
7854
- if (!readAt2(fd, 8, standInOffset).equals(shim.displaced)) {
7627
+ if (!readAt(fd, 8, standInOffset).equals(shim.displaced)) {
7855
7628
  throw new Error("the bytes the stand-in displaced were not restored");
7856
7629
  }
7857
7630
  } finally {
@@ -7860,13 +7633,185 @@ function restoreBunCompiledPointer(path, shim) {
7860
7633
  }
7861
7634
 
7862
7635
  // src/bun-bundle.ts
7863
- import { closeSync as closeSync5, openSync as openSync5, readSync as readSync4, writeSync as writeSync3 } from "fs";
7636
+ import { closeSync as closeSync6, openSync as openSync6, readSync as readSync5, writeSync as writeSync2 } from "fs";
7637
+
7638
+ // src/bun-module-table.ts
7639
+ import { closeSync as closeSync5, openSync as openSync5, readSync as readSync4, statSync as statSync6 } from "fs";
7640
+ var BUN_TRAILER = Buffer.from("\n---- Bun! ----\n");
7641
+ var BUN_OFFSETS_BYTES = 32;
7642
+ var TAIL_SCAN_BYTES = 16 * 1024 * 1024;
7643
+ var MODULE_STRUCT_BYTES_CURRENT = 52;
7644
+ var MODULE_STRUCT_BYTES_LEGACY = 36;
7645
+ var CONTENTS_FIELD_AT = 8;
7646
+ var SOURCEMAP_FIELD_AT = 16;
7647
+ var BYTECODE_FIELD_AT = 24;
7648
+ var MODULE_INFO_FIELD_AT = 32;
7649
+ var BYTECODE_ORIGIN_PATH_FIELD_AT = 40;
7650
+ var BUN_BLOB_FLAGS = {
7651
+ /** Every module's source text lies in one run no other region falls inside. */
7652
+ SOURCE_TEXT_CONTIGUOUS: 1 << 4,
7653
+ /** A `[u32; modules]` of each module's source hash follows the module table. */
7654
+ HAS_SOURCE_HASHES: 1 << 5,
7655
+ /** After the source hashes: `u32 count`, then `count` x `{ u32 id, offset, length }`. */
7656
+ HAS_BUILTIN_BYTECODE: 1 << 6,
7657
+ /** After the builtin-bytecode table: one `{ offset, length }` for the shared string table. */
7658
+ HAS_BYTECODE_STRING_TABLE: 1 << 7
7659
+ };
7660
+ var LOADER_FROM_END = 3;
7661
+ var BUN_JAVASCRIPT_LOADER = 1;
7662
+ var MAX_MODULE_NAME_BYTES = 4096;
7663
+ function tweakccRecognizesModuleName(name) {
7664
+ return name.endsWith("/claude") || name === "claude" || name.endsWith("/claude.exe") || name === "claude.exe" || name.endsWith("/src/entrypoints/cli.js") || name === "src/entrypoints/cli.js" || name.endsWith("/cli") || name === "cli";
7665
+ }
7666
+ function readAt2(fd, length, position) {
7667
+ if (length <= 0 || position < 0) return null;
7668
+ const buffer = Buffer.alloc(length);
7669
+ const read = readSync4(fd, buffer, 0, length, position);
7670
+ return read === length ? buffer : null;
7671
+ }
7672
+ function readBunModuleNames(fd, fileSize) {
7673
+ const tailLength = Math.min(fileSize, TAIL_SCAN_BYTES);
7674
+ const tail = readAt2(fd, tailLength, fileSize - tailLength);
7675
+ if (!tail) return null;
7676
+ const tailAt = fileSize - tailLength;
7677
+ for (let searchFrom = tail.length - 1; searchFrom >= 0; ) {
7678
+ const trailerInTail = tail.lastIndexOf(BUN_TRAILER, searchFrom);
7679
+ if (trailerInTail < 0) return null;
7680
+ const parsed = parseBunModuleNamesAt(fd, tailAt + trailerInTail - BUN_OFFSETS_BYTES);
7681
+ if (parsed) return parsed;
7682
+ searchFrom = trailerInTail - 1;
7683
+ }
7684
+ return null;
7685
+ }
7686
+ function parseBunModuleNamesAt(fd, offsetsAt) {
7687
+ try {
7688
+ return parseBunModuleNamesAtUnchecked(fd, offsetsAt);
7689
+ } catch {
7690
+ return null;
7691
+ }
7692
+ }
7693
+ function parseBunModuleNamesAtUnchecked(fd, offsetsAt) {
7694
+ const offsets = readAt2(fd, BUN_OFFSETS_BYTES, offsetsAt);
7695
+ if (!offsets) return null;
7696
+ const byteCount = offsets.readBigUInt64LE(0);
7697
+ const modulesOffset = offsets.readUInt32LE(8);
7698
+ const modulesLength = offsets.readUInt32LE(12);
7699
+ const entryPointId = offsets.readUInt32LE(16);
7700
+ const compileExecArgvOffset = offsets.readUInt32LE(20);
7701
+ const compileExecArgvLength = offsets.readUInt32LE(24);
7702
+ const flags = offsets.readUInt32LE(28);
7703
+ if (byteCount <= 0n || byteCount > BigInt(offsetsAt)) return null;
7704
+ const blobAt = offsetsAt - Number(byteCount);
7705
+ if (modulesLength <= 0 || BigInt(modulesOffset) + BigInt(modulesLength) > byteCount) return null;
7706
+ const structBytes = modulesLength % MODULE_STRUCT_BYTES_LEGACY === 0 && modulesLength % MODULE_STRUCT_BYTES_CURRENT !== 0 ? MODULE_STRUCT_BYTES_LEGACY : MODULE_STRUCT_BYTES_CURRENT;
7707
+ const moduleCount = Math.floor(modulesLength / structBytes);
7708
+ if (moduleCount <= 0 || entryPointId >= moduleCount) return null;
7709
+ const modules = readAt2(fd, moduleCount * structBytes, blobAt + modulesOffset);
7710
+ if (!modules) return null;
7711
+ const names = [];
7712
+ const nameOffsets = [];
7713
+ const contents = [];
7714
+ const sourcemap = [];
7715
+ const bytecode = [];
7716
+ const moduleInfo = [];
7717
+ const bytecodeOriginPath = [];
7718
+ const loaders = [];
7719
+ for (let index = 0; index < moduleCount; index++) {
7720
+ const nameOffset = modules.readUInt32LE(index * structBytes);
7721
+ const nameLength = modules.readUInt32LE(index * structBytes + 4);
7722
+ if (nameLength <= 0 || nameLength > MAX_MODULE_NAME_BYTES) return null;
7723
+ if (BigInt(nameOffset) + BigInt(nameLength) > byteCount) return null;
7724
+ const bytes = readAt2(fd, nameLength + 1, blobAt + nameOffset);
7725
+ if (!bytes || bytes[nameLength] !== 0) return null;
7726
+ const name = bytes.subarray(0, nameLength).toString("utf8");
7727
+ if (!/^[\x20-\x7e]+$/.test(name)) return null;
7728
+ names.push(name);
7729
+ nameOffsets.push(blobAt + nameOffset);
7730
+ const pairAt = (field) => ({
7731
+ offset: modules.readUInt32LE(index * structBytes + field),
7732
+ length: modules.readUInt32LE(index * structBytes + field + 4)
7733
+ });
7734
+ contents.push(pairAt(CONTENTS_FIELD_AT));
7735
+ sourcemap.push(pairAt(SOURCEMAP_FIELD_AT));
7736
+ bytecode.push(pairAt(BYTECODE_FIELD_AT));
7737
+ const current = structBytes === MODULE_STRUCT_BYTES_CURRENT;
7738
+ moduleInfo.push(current ? pairAt(MODULE_INFO_FIELD_AT) : { offset: 0, length: 0 });
7739
+ bytecodeOriginPath.push(
7740
+ current ? pairAt(BYTECODE_ORIGIN_PATH_FIELD_AT) : { offset: 0, length: 0 }
7741
+ );
7742
+ loaders.push(modules.readUInt8(index * structBytes + structBytes - LOADER_FROM_END));
7743
+ }
7744
+ return {
7745
+ names,
7746
+ entryPointId,
7747
+ offsets: nameOffsets,
7748
+ contents,
7749
+ sourcemap,
7750
+ bytecode,
7751
+ moduleInfo,
7752
+ bytecodeOriginPath,
7753
+ loaders,
7754
+ blobAt,
7755
+ modulesAt: blobAt + modulesOffset,
7756
+ modulesOffset,
7757
+ modulesLength,
7758
+ structBytes,
7759
+ byteCount: Number(byteCount),
7760
+ compileExecArgv: { offset: compileExecArgvOffset, length: compileExecArgvLength },
7761
+ flags
7762
+ };
7763
+ }
7764
+ function readBunModuleTable(path) {
7765
+ const fd = openSync5(path, "r");
7766
+ try {
7767
+ return readBunModuleNames(fd, statSync6(path).size);
7768
+ } finally {
7769
+ closeSync5(fd);
7770
+ }
7771
+ }
7772
+ function readBunJavaScriptModules(path) {
7773
+ const fd = openSync5(path, "r");
7774
+ try {
7775
+ const parsed = readBunModuleNames(fd, statSync6(path).size);
7776
+ if (!parsed) return null;
7777
+ const modules = [];
7778
+ for (let index = 0; index < parsed.names.length; index++) {
7779
+ if (parsed.loaders[index] !== BUN_JAVASCRIPT_LOADER) continue;
7780
+ const range = parsed.contents[index];
7781
+ if (range.offset < 0 || range.length < 0 || range.offset + range.length > parsed.byteCount) {
7782
+ return null;
7783
+ }
7784
+ const bytes = range.length === 0 ? Buffer.alloc(0) : readAt2(fd, range.length, parsed.blobAt + range.offset);
7785
+ if (!bytes) return null;
7786
+ modules.push({
7787
+ index,
7788
+ name: parsed.names[index],
7789
+ source: bytes.toString("utf8"),
7790
+ byteLength: bytes.length
7791
+ });
7792
+ }
7793
+ return modules;
7794
+ } finally {
7795
+ closeSync5(fd);
7796
+ }
7797
+ }
7798
+
7799
+ // src/bun-bundle.ts
7864
7800
  function writableModuleIndex(path) {
7865
7801
  const table = readBunModuleTable(path);
7866
7802
  if (!table) return null;
7867
7803
  const index = table.names.findIndex(tweakccRecognizesModuleName);
7868
7804
  return index < 0 ? null : index;
7869
7805
  }
7806
+ function assertRecognizedEntryModule(path) {
7807
+ const table = readBunModuleTable(path);
7808
+ if (table && !table.names.some(tweakccRecognizesModuleName)) {
7809
+ const entry = table.names[table.entryPointId];
7810
+ throw new Error(
7811
+ `Claude Code entry module ${JSON.stringify(entry)} is not recognized by tweakcc. Update clodex and try again. Claude Code was left unchanged.`
7812
+ );
7813
+ }
7814
+ }
7870
7815
  var BUNDLE_MODULE_SEPARATOR = '\n/*clodex:module-boundary`;{}"]*/\n';
7871
7816
  function readClaudeBundle(path) {
7872
7817
  const modules = readBunJavaScriptModules(path);
@@ -7976,18 +7921,18 @@ function placeholderOf(byteLength) {
7976
7921
  return PLACEHOLDER_TEXT.repeat(Math.ceil(byteLength / PLACEHOLDER_TEXT.length)).slice(0, byteLength);
7977
7922
  }
7978
7923
  function readBlobData(path, table, into) {
7979
- const fd = openSync5(path, "r");
7924
+ const fd = openSync6(path, "r");
7980
7925
  try {
7981
7926
  let read = 0;
7982
7927
  while (read < table.byteCount) {
7983
- const got = readSync4(fd, into, read, table.byteCount - read, table.blobAt + read);
7928
+ const got = readSync5(fd, into, read, table.byteCount - read, table.blobAt + read);
7984
7929
  if (got <= 0) {
7985
7930
  throw new Error(`read ${read} of the ${table.byteCount} blob bytes of ${path}`);
7986
7931
  }
7987
7932
  read += got;
7988
7933
  }
7989
7934
  } finally {
7990
- closeSync5(fd);
7935
+ closeSync6(fd);
7991
7936
  }
7992
7937
  }
7993
7938
  function repointModule(data, table, append) {
@@ -8039,7 +7984,7 @@ function applyBundleWritePlan(path, plan) {
8039
7984
  }
8040
7985
  const offsets = Buffer.from(plan.offsets);
8041
7986
  offsets.writeBigUInt64LE(BigInt(byteCount), 0);
8042
- const fd = openSync5(path, "r+");
7987
+ const fd = openSync6(path, "r+");
8043
7988
  try {
8044
7989
  writeAll(fd, plan.data, repacked.blobAt, path);
8045
7990
  const padding = byteCount - plan.data.length;
@@ -8047,7 +7992,7 @@ function applyBundleWritePlan(path, plan) {
8047
7992
  writeAll(fd, offsets, repacked.blobAt + byteCount, path);
8048
7993
  writeAll(fd, BUN_TRAILER2, repacked.blobAt + byteCount + BUN_OFFSETS_BYTES2, path);
8049
7994
  } finally {
8050
- closeSync5(fd);
7995
+ closeSync6(fd);
8051
7996
  }
8052
7997
  const published = readBunModuleTable(path);
8053
7998
  if (!published) throw new Error(`cannot re-read the Bun module table of ${path} after publishing its blob`);
@@ -8075,7 +8020,7 @@ function applyBundleWritePlan(path, plan) {
8075
8020
  function writeAll(fd, bytes, position, path) {
8076
8021
  let written = 0;
8077
8022
  while (written < bytes.length) {
8078
- const wrote = writeSync3(fd, bytes, written, bytes.length - written, position + written);
8023
+ const wrote = writeSync2(fd, bytes, written, bytes.length - written, position + written);
8079
8024
  if (wrote <= 0) throw new Error(`wrote ${written} of ${bytes.length} blob bytes to ${path}`);
8080
8025
  written += wrote;
8081
8026
  }
@@ -8086,13 +8031,20 @@ import { wrapLanguageModel, extractReasoningMiddleware } from "ai";
8086
8031
 
8087
8032
  // src/oauth/responses-websocket.ts
8088
8033
  import { createHash as createHash5 } from "crypto";
8089
- import { closeSync as closeSync6, openSync as openSync6 } from "fs";
8034
+ import { closeSync as closeSync7, openSync as openSync7 } from "fs";
8090
8035
  import { devNull } from "os";
8091
8036
  import { AsyncLocalStorage } from "async_hooks";
8092
8037
 
8093
8038
  // src/outbound-proxy.ts
8039
+ import { randomUUID as randomUUID3 } from "crypto";
8094
8040
  import { networkInterfaces } from "os";
8095
8041
  import { HttpsProxyAgent } from "https-proxy-agent";
8042
+ var OUTBOUND_PROXY_HOP_HEADER = "x-clodex-proxy-hop";
8043
+ var outboundProxyHopNonce = randomUUID3();
8044
+ function isOwnOutboundProxyHop(value) {
8045
+ return (Array.isArray(value) ? value : [value]).some((entry) => entry?.split(",").some((part) => part.trim() === outboundProxyHopNonce));
8046
+ }
8047
+ var proxyHopHeaders = { [OUTBOUND_PROXY_HOP_HEADER]: outboundProxyHopNonce };
8096
8048
  function hasOutboundProxyEnv(env = process.env) {
8097
8049
  return Boolean(
8098
8050
  env["HTTPS_PROXY"]?.trim() || env["https_proxy"]?.trim() || env["HTTP_PROXY"]?.trim() || env["http_proxy"]?.trim()
@@ -8139,7 +8091,16 @@ function proxyUrlTargetsListener(proxyUrl, listenerHost, listenerPort, localAddr
8139
8091
  }
8140
8092
  const proxyPort = parsed.port ? Number(parsed.port) : parsed.protocol === "https:" ? 443 : parsed.protocol === "http:" ? 80 : void 0;
8141
8093
  if (proxyPort !== listenerPort) return false;
8142
- const normalizeHost = (host) => host.toLowerCase().replace(/^\[|\]$/g, "");
8094
+ const normalizeHost = (host) => {
8095
+ const plain = host.toLowerCase().replace(/^\[|\]$/g, "");
8096
+ const mapped = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(plain);
8097
+ if (mapped) {
8098
+ const high = parseInt(mapped[1], 16);
8099
+ const low = parseInt(mapped[2], 16);
8100
+ return `${high >> 8}.${high & 255}.${low >> 8}.${low & 255}`;
8101
+ }
8102
+ return plain.replace(/^::ffff:(?=\d+\.)/, "").replace(/^localhost\.$/, "localhost");
8103
+ };
8143
8104
  const proxyHost = normalizeHost(parsed.hostname);
8144
8105
  const boundHost = normalizeHost(listenerHost);
8145
8106
  if (proxyHost === boundHost) return true;
@@ -8172,7 +8133,7 @@ function outboundHttpProxyAgent(targetUrl, env = process.env) {
8172
8133
  if (!parsedProxy.hostname || !["http:", "https:"].includes(parsedProxy.protocol)) {
8173
8134
  throw new TypeError("Invalid proxy URL");
8174
8135
  }
8175
- return new HttpsProxyAgent(parsedProxy, { keepAlive: true });
8136
+ return new HttpsProxyAgent(parsedProxy, { keepAlive: true, headers: { ...proxyHopHeaders } });
8176
8137
  } catch (err) {
8177
8138
  emitParentNotice(
8178
8139
  `clodex: HTTP(S)_PROXY cannot be used for a CONNECT tunnel; using a direct connection (${err instanceof Error ? err.message : String(err)})`
@@ -9888,7 +9849,7 @@ function descriptorExhaustionCode(error) {
9888
9849
  const code = error.code;
9889
9850
  if (isDescriptorExhaustion(code)) return code;
9890
9851
  try {
9891
- closeSync6(openSync6(devNull, "r"));
9852
+ closeSync7(openSync7(devNull, "r"));
9892
9853
  return void 0;
9893
9854
  } catch (probe) {
9894
9855
  const probeCode = probe.code;
@@ -10784,7 +10745,7 @@ function createResponsesWebSocketFetch(wsUrl, log13, options = {}) {
10784
10745
  }
10785
10746
 
10786
10747
  // src/oauth/claude-identity.ts
10787
- import { createHash as createHash6, randomUUID as randomUUID3 } from "crypto";
10748
+ import { createHash as createHash6, randomUUID as randomUUID4 } from "crypto";
10788
10749
  var CLAUDE_CODE_CLI_VERSION = "2.1.195";
10789
10750
  var CLAUDE_CODE_USER_AGENT = `claude-cli/${CLAUDE_CODE_CLI_VERSION} (external, cli)`;
10790
10751
  var CLAUDE_CODE_ENTRYPOINT = process.env.CLAUDE_CODE_ENTRYPOINT ?? "cli";
@@ -10793,7 +10754,7 @@ var sessionCache = /* @__PURE__ */ new Map();
10793
10754
  function getOrCreateSessionId(seed) {
10794
10755
  let id = sessionCache.get(seed);
10795
10756
  if (!id) {
10796
- id = randomUUID3();
10757
+ id = randomUUID4();
10797
10758
  sessionCache.set(seed, id);
10798
10759
  }
10799
10760
  return id;
@@ -11717,7 +11678,7 @@ function thinkingProviderOptions(npm) {
11717
11678
 
11718
11679
  // src/proxy.ts
11719
11680
  import { createServer } from "http";
11720
- import { appendFileSync as appendFileSync2, openSync as openSync7, writeSync as writeSync4, closeSync as closeSync7 } from "fs";
11681
+ import { appendFileSync as appendFileSync2, openSync as openSync8, writeSync as writeSync3, closeSync as closeSync8 } from "fs";
11721
11682
 
11722
11683
  // src/http-utils.ts
11723
11684
  import * as zlib from "zlib";
@@ -11949,7 +11910,7 @@ function routeUnavailableMessage(modelId, reason) {
11949
11910
  }
11950
11911
 
11951
11912
  // src/upstream-forward.ts
11952
- import { randomUUID as randomUUID4 } from "crypto";
11913
+ import { randomUUID as randomUUID5 } from "crypto";
11953
11914
  import { Readable, Transform } from "stream";
11954
11915
  import { StringDecoder } from "string_decoder";
11955
11916
 
@@ -12046,7 +12007,7 @@ function upstreamHoldsThreads(url) {
12046
12007
  }
12047
12008
  }
12048
12009
  function anchorSafeMessageId(id) {
12049
- return typeof id === "string" && id.startsWith("msg_") ? "clodex_" + randomUUID4().replace(/-/g, "") : id;
12010
+ return typeof id === "string" && id.startsWith("msg_") ? "clodex_" + randomUUID5().replace(/-/g, "") : id;
12050
12011
  }
12051
12012
  function isThreadContinuation(body) {
12052
12013
  const thread = body.thread;
@@ -12195,10 +12156,10 @@ async function relayAnthropicMessages(res, messagesUrl, body, apiKey, clientWant
12195
12156
  }
12196
12157
 
12197
12158
  // src/proxy.ts
12198
- import { randomUUID as randomUUID6 } from "crypto";
12159
+ import { randomUUID as randomUUID7 } from "crypto";
12199
12160
 
12200
12161
  // src/sdk-adapter.ts
12201
- import { createHash as createHash7, randomUUID as randomUUID5 } from "crypto";
12162
+ import { createHash as createHash7, randomUUID as randomUUID6 } from "crypto";
12202
12163
  import { streamText, generateText, tool, jsonSchema } from "ai";
12203
12164
 
12204
12165
  // src/proxy-shared.ts
@@ -13042,7 +13003,7 @@ function forwardAbortSignal(source, target) {
13042
13003
  return () => source.removeEventListener("abort", forward);
13043
13004
  }
13044
13005
  function translatedMessageId() {
13045
- return "clodex_" + randomUUID5().replace(/-/g, "");
13006
+ return "clodex_" + randomUUID6().replace(/-/g, "");
13046
13007
  }
13047
13008
  async function writeAnthropicStream(stream, modelId, write, log13, observer, tools) {
13048
13009
  const messageId = translatedMessageId();
@@ -13567,12 +13528,12 @@ function createTranslationLifecycle(logPath, requestId, claudeSessionId, modelId
13567
13528
  function appendSecureLog(logPath, line) {
13568
13529
  const redacted = redactTraceLine(line);
13569
13530
  try {
13570
- const fd = openSync7(logPath, "a", 384);
13531
+ const fd = openSync8(logPath, "a", 384);
13571
13532
  try {
13572
- writeSync4(fd, `${(/* @__PURE__ */ new Date()).toISOString()} ${redacted}
13533
+ writeSync3(fd, `${(/* @__PURE__ */ new Date()).toISOString()} ${redacted}
13573
13534
  `);
13574
13535
  } finally {
13575
- closeSync7(fd);
13536
+ closeSync8(fd);
13576
13537
  }
13577
13538
  } catch {
13578
13539
  try {
@@ -13619,7 +13580,7 @@ function configuredAliasLookupNames(alias) {
13619
13580
  }))].map(normalizeRouteLookupId);
13620
13581
  }
13621
13582
  async function startProxyCatalog(routes, defaultAliasId, debug = false, inferenceLogPath, debugLogPath, webSocketDiagnosticsLogPath, modelAliases) {
13622
- const proxyToken = randomUUID6();
13583
+ const proxyToken = randomUUID7();
13623
13584
  silenceSdkWarnings();
13624
13585
  if (routes.length === 0) {
13625
13586
  throw new Error("Proxy catalog requires at least one route");
@@ -14042,7 +14003,7 @@ async function startProxyCatalog(routes, defaultAliasId, debug = false, inferenc
14042
14003
  res,
14043
14004
  upstreamStatus === 500 ? 502 : upstreamStatus,
14044
14005
  clientMessage,
14045
- contextLengthExceeded ? relayRequestId ?? randomUUID6() : void 0
14006
+ contextLengthExceeded ? relayRequestId ?? randomUUID7() : void 0
14046
14007
  );
14047
14008
  } else {
14048
14009
  const errorType = anthropicErrorType(upstreamStatus, details?.transportCode);
@@ -14050,7 +14011,7 @@ async function startProxyCatalog(routes, defaultAliasId, debug = false, inferenc
14050
14011
  data: ${JSON.stringify({
14051
14012
  type: "error",
14052
14013
  error: { type: errorType, message: clientMessage },
14053
- ...contextLengthExceeded ? { request_id: relayRequestId ?? randomUUID6() } : {}
14014
+ ...contextLengthExceeded ? { request_id: relayRequestId ?? randomUUID7() } : {}
14054
14015
  })}
14055
14016
 
14056
14017
  `);
@@ -14440,10 +14401,10 @@ function tryAcquirePatchLock(lockPath = getPatchLockPath(), opts = {}) {
14440
14401
  mkdirSync5(join8(lockPath, ".."), { recursive: true, mode: 448 });
14441
14402
  for (let attempt = 0; attempt < 2; attempt++) {
14442
14403
  try {
14443
- const fd = openSync8(lockPath, "wx");
14404
+ const fd = openSync9(lockPath, "wx");
14444
14405
  const content = { pid: process.pid, startedAt: now };
14445
14406
  writeFileSync5(fd, JSON.stringify(content));
14446
- closeSync8(fd);
14407
+ closeSync9(fd);
14447
14408
  return () => {
14448
14409
  try {
14449
14410
  unlinkSync3(lockPath);
@@ -14647,7 +14608,7 @@ async function applyPatch(binaryPath, version, desired, configHash, opts) {
14647
14608
  const candidatePath = join8(candidateDir, basename(binaryPath));
14648
14609
  const seedCandidate = async (from) => {
14649
14610
  copyFileSync(from, candidatePath);
14650
- const shim = shimEntryModuleName(candidatePath);
14611
+ assertRecognizedEntryModule(candidatePath);
14651
14612
  const installation = await tryDetectInstallation({ path: candidatePath });
14652
14613
  const bundle = readClaudeBundle(candidatePath);
14653
14614
  if (!bundle && installation.kind === "native") {
@@ -14656,7 +14617,6 @@ async function applyPatch(binaryPath, version, desired, configHash, opts) {
14656
14617
  );
14657
14618
  }
14658
14619
  const source = bundle ? bundle.source : await readContent(installation);
14659
- if (shim) restoreEntryModuleName(candidatePath, shim, { resign: false });
14660
14620
  return { installation, source, bundle };
14661
14621
  };
14662
14622
  const facts = collectPristineFacts({
@@ -14766,8 +14726,6 @@ async function applyPatch(binaryPath, version, desired, configHash, opts) {
14766
14726
  local = discardLocalPatchOutcome(builtIn.content, local.results);
14767
14727
  }
14768
14728
  results = [...results, ...local.results];
14769
- const writeShim = shimEntryModuleName(candidatePath);
14770
- let publishedBlob = false;
14771
14729
  if (loaded.bundle) {
14772
14730
  const writable = writableModuleIndex(candidatePath);
14773
14731
  if (writable === null) {
@@ -14783,14 +14741,12 @@ async function applyPatch(binaryPath, version, desired, configHash, opts) {
14783
14741
  await writeContent(loaded.installation, plan2.content);
14784
14742
  if (bunPointerShim) restoreBunCompiledPointer(candidatePath, bunPointerShim);
14785
14743
  applyBundleWritePlan(candidatePath, plan2);
14786
- publishedBlob = true;
14787
14744
  } else {
14788
14745
  const bunPointerShim = shimBunCompiledPointer(candidatePath);
14789
14746
  await writeContent(loaded.installation, local.content);
14790
14747
  if (bunPointerShim) restoreBunCompiledPointer(candidatePath, bunPointerShim);
14791
14748
  }
14792
- if (writeShim) restoreEntryModuleName(candidatePath, writeShim, { resign: true });
14793
- else if (publishedBlob) resignMachOBinary(candidatePath);
14749
+ signAndVerifyMachOCandidate(candidatePath, binaryPath);
14794
14750
  patchedSize = statSync7(candidatePath).size;
14795
14751
  patchedSha256 = sha256File(candidatePath);
14796
14752
  renameSync2(candidatePath, binaryPath);
@@ -15380,15 +15336,15 @@ function localProvidersToServerModels(localProviders) {
15380
15336
  }
15381
15337
 
15382
15338
  // src/registry/credential-cleanup-journal.ts
15383
- import { randomUUID as randomUUID7 } from "crypto";
15339
+ import { randomUUID as randomUUID8 } from "crypto";
15384
15340
  import {
15385
- closeSync as closeSync9,
15341
+ closeSync as closeSync10,
15386
15342
  existsSync as existsSync5,
15387
15343
  fstatSync as fstatSync3,
15388
15344
  fsyncSync as fsyncSync2,
15389
15345
  lstatSync,
15390
15346
  mkdirSync as mkdirSync6,
15391
- openSync as openSync9,
15347
+ openSync as openSync10,
15392
15348
  readFileSync as readFileSync11,
15393
15349
  renameSync as renameSync3,
15394
15350
  unlinkSync as unlinkSync4,
@@ -15480,7 +15436,7 @@ function readJournalUnlocked(path) {
15480
15436
  if (before.isSymbolicLink() || !before.isFile()) {
15481
15437
  throw new Error("Credential cleanup journal must be a regular file.");
15482
15438
  }
15483
- fd = openSync9(path, "r");
15439
+ fd = openSync10(path, "r");
15484
15440
  const opened = fstatSync3(fd);
15485
15441
  if (before.dev !== opened.dev || before.ino !== opened.ino) {
15486
15442
  throw new Error("Credential cleanup journal changed while opening.");
@@ -15501,39 +15457,39 @@ function readJournalUnlocked(path) {
15501
15457
  const message = error instanceof Error ? error.message : String(error);
15502
15458
  throw new Error(`Could not read credential cleanup journal: ${message}`);
15503
15459
  } finally {
15504
- if (fd !== void 0) closeSync9(fd);
15460
+ if (fd !== void 0) closeSync10(fd);
15505
15461
  }
15506
15462
  }
15507
15463
  function syncParentDirectory(path) {
15508
15464
  let fd;
15509
15465
  try {
15510
- fd = openSync9(dirname6(path), "r");
15466
+ fd = openSync10(dirname6(path), "r");
15511
15467
  fsyncSync2(fd);
15512
15468
  } catch (error) {
15513
15469
  const code = error.code;
15514
15470
  if (code !== "EINVAL" && code !== "ENOTSUP" && code !== "EPERM") throw error;
15515
15471
  } finally {
15516
- if (fd !== void 0) closeSync9(fd);
15472
+ if (fd !== void 0) closeSync10(fd);
15517
15473
  }
15518
15474
  }
15519
15475
  function writeJournalUnlocked(journal, path) {
15520
15476
  assertRegistryWriteOwnership(path);
15521
15477
  ensureSecureAppHome();
15522
15478
  mkdirSync6(dirname6(path), { recursive: true, mode: DIR_MODE2 });
15523
- const tmp = `${path}.${process.pid}.${randomUUID7()}.tmp`;
15479
+ const tmp = `${path}.${process.pid}.${randomUUID8()}.tmp`;
15524
15480
  let fd;
15525
15481
  try {
15526
- fd = openSync9(tmp, "wx", FILE_MODE4);
15482
+ fd = openSync10(tmp, "wx", FILE_MODE4);
15527
15483
  writeFileSync6(fd, `${JSON.stringify(journal, null, 2)}
15528
15484
  `);
15529
15485
  fsyncSync2(fd);
15530
- closeSync9(fd);
15486
+ closeSync10(fd);
15531
15487
  fd = void 0;
15532
15488
  assertRegistryWriteOwnership(path);
15533
15489
  renameSync3(tmp, path);
15534
15490
  syncParentDirectory(path);
15535
15491
  } finally {
15536
- if (fd !== void 0) closeSync9(fd);
15492
+ if (fd !== void 0) closeSync10(fd);
15537
15493
  try {
15538
15494
  unlinkSync4(tmp);
15539
15495
  } catch (error) {
@@ -18637,7 +18593,7 @@ async function askSaveServerPassword() {
18637
18593
 
18638
18594
  // src/server/router.ts
18639
18595
  import { createServer as createServer2 } from "http";
18640
- import { randomUUID as randomUUID8 } from "crypto";
18596
+ import { randomUUID as randomUUID9 } from "crypto";
18641
18597
 
18642
18598
  // src/openai-adapter.ts
18643
18599
  import { tool as tool2, jsonSchema as jsonSchema2, streamText as streamText2, generateText as generateText2 } from "ai";
@@ -19053,7 +19009,7 @@ async function handleAnthropicMessages(req, res, options, modelCache, plog) {
19053
19009
  plog(`model not found: ${body.model}`);
19054
19010
  return;
19055
19011
  }
19056
- const requestId = randomUUID8();
19012
+ const requestId = randomUUID9();
19057
19013
  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"];
19058
19014
  const claudeSessionId = extractClaudeSessionId(body, claudeSessionIdHeader);
19059
19015
  const claudeAgentIds = extractClaudeAgentIds(req.headers);
@@ -19727,7 +19683,7 @@ import * as http2 from "http";
19727
19683
  import * as https from "https";
19728
19684
  import * as net from "net";
19729
19685
  import { PassThrough } from "stream";
19730
- import { randomUUID as randomUUID9 } from "crypto";
19686
+ import { randomUUID as randomUUID10 } from "crypto";
19731
19687
  import { URL as URL2 } from "url";
19732
19688
  import { createBrotliDecompress, createGunzip, createInflate } from "zlib";
19733
19689
 
@@ -20019,7 +19975,7 @@ function requestHeadersWithoutProxyHeaders(req) {
20019
19975
  const headers = [];
20020
19976
  for (let i = 0; i < req.rawHeaders.length; i += 2) {
20021
19977
  const name = req.rawHeaders[i];
20022
- if (/^proxy-(authorization|connection)$/i.test(name)) continue;
19978
+ if (/^proxy-(authorization|connection)$/i.test(name) || name.toLowerCase() === OUTBOUND_PROXY_HOP_HEADER) continue;
20023
19979
  headers.push(name, req.rawHeaders[i + 1] ?? "");
20024
19980
  }
20025
19981
  return headers;
@@ -20556,6 +20512,7 @@ async function startHttpProxy(options) {
20556
20512
  const anthropicOrigin = new URL2(options.anthropicOrigin ?? "https://api.anthropic.com");
20557
20513
  const anthropicProxyUrl = outboundProxyUrlForTarget(anthropicOrigin.href);
20558
20514
  let anthropicAgent;
20515
+ let anthropicViaProxy = false;
20559
20516
  let adapter = options.adapterHandle ?? null;
20560
20517
  if (options.routes.length > 0) {
20561
20518
  adapter ??= await startProxyCatalog(
@@ -20570,11 +20527,27 @@ async function startHttpProxy(options) {
20570
20527
  }
20571
20528
  const adapterAgent = adapter ? new http2.Agent({ keepAlive: true }) : void 0;
20572
20529
  let shuttingDown = false;
20530
+ let warnedProxyLoop = false;
20531
+ const rejectProxyLoop = (target) => {
20532
+ if (warnedProxyLoop) return;
20533
+ warnedProxyLoop = true;
20534
+ const secure = target.startsWith("https:");
20535
+ const candidates = secure ? ["HTTPS_PROXY", "https_proxy"] : ["HTTP_PROXY", "http_proxy"];
20536
+ const name = candidates.find((key) => process.env[key]?.trim()) ?? candidates[0];
20537
+ emitParentNotice(`clodex: outbound proxy loop detected; check ${name} (request returned to this proxy)`);
20538
+ };
20573
20539
  const mitmServer = https.createServer({
20574
20540
  key: certificates.serverKey,
20575
20541
  cert: certificates.serverCert,
20576
20542
  minVersion: "TLSv1.2"
20577
20543
  }, async (req, res) => {
20544
+ if (isOwnOutboundProxyHop(req.headers[OUTBOUND_PROXY_HOP_HEADER])) {
20545
+ rejectProxyLoop("https://api.anthropic.com");
20546
+ res.writeHead(508, { "Content-Type": "text/plain" });
20547
+ res.end("Outbound proxy loop detected");
20548
+ return;
20549
+ }
20550
+ delete req.headers[OUTBOUND_PROXY_HOP_HEADER];
20578
20551
  let rawBody;
20579
20552
  try {
20580
20553
  rawBody = await readRawBody(req);
@@ -20585,7 +20558,7 @@ async function startHttpProxy(options) {
20585
20558
  }
20586
20559
  const messagesEndpoint = anthropicMessagesEndpoint(req.url);
20587
20560
  if (req.method === "POST" && messagesEndpoint) {
20588
- const requestId = randomUUID9();
20561
+ const requestId = randomUUID10();
20589
20562
  let parsed = null;
20590
20563
  let route;
20591
20564
  let adapterBody = rawBody;
@@ -20733,6 +20706,12 @@ async function startHttpProxy(options) {
20733
20706
  return connectTunnelAgents.get(proxyUrl);
20734
20707
  };
20735
20708
  mitmServer.on("upgrade", (req, socket, head) => {
20709
+ if (isOwnOutboundProxyHop(req.headers[OUTBOUND_PROXY_HOP_HEADER])) {
20710
+ rejectProxyLoop("https://api.anthropic.com");
20711
+ socket.once("error", () => socket.destroy());
20712
+ socket.end("HTTP/1.1 508 Loop Detected\r\nConnection: close\r\n\r\n", () => socket.destroy());
20713
+ return;
20714
+ }
20736
20715
  forwardAnthropicUpgrade(
20737
20716
  req,
20738
20717
  socket,
@@ -20743,13 +20722,40 @@ async function startHttpProxy(options) {
20743
20722
  sockets
20744
20723
  );
20745
20724
  });
20746
- const proxyServer = http2.createServer(forwardPlainHttp);
20725
+ const proxyServer = http2.createServer((req, res) => {
20726
+ if (isOwnOutboundProxyHop(req.headers[OUTBOUND_PROXY_HOP_HEADER])) {
20727
+ rejectProxyLoop(req.url ?? "");
20728
+ res.writeHead(508, { "Content-Type": "text/plain" });
20729
+ res.end("Outbound proxy loop detected");
20730
+ return;
20731
+ }
20732
+ forwardPlainHttp(req, res);
20733
+ });
20747
20734
  proxyServer.on("connection", (socket) => {
20748
20735
  sockets.add(socket);
20749
20736
  socket.once("close", () => sockets.delete(socket));
20750
20737
  });
20751
20738
  proxyServer.on("connect", (req, clientSocket, head) => {
20739
+ const ownHop = isOwnOutboundProxyHop(req.headers[OUTBOUND_PROXY_HOP_HEADER]);
20740
+ const rejectOwnHop = () => {
20741
+ rejectProxyLoop(`https://${req.url ?? ""}`);
20742
+ clientSocket.once("error", () => clientSocket.destroy());
20743
+ const body = "Outbound proxy loop detected";
20744
+ clientSocket.end(
20745
+ `HTTP/1.1 508 Loop Detected\r
20746
+ Content-Type: text/plain\r
20747
+ Content-Length: ${Buffer.byteLength(body)}\r
20748
+ Connection: close\r
20749
+ \r
20750
+ ${body}`,
20751
+ () => clientSocket.destroy()
20752
+ );
20753
+ };
20752
20754
  if (shouldInterceptConnect(req.url ?? "")) {
20755
+ if (ownHop && anthropicViaProxy) {
20756
+ rejectOwnHop();
20757
+ return;
20758
+ }
20753
20759
  clientSocket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
20754
20760
  if (head.length > 0) clientSocket.unshift(head);
20755
20761
  mitmServer.emit("connection", clientSocket);
@@ -20772,6 +20778,10 @@ async function startHttpProxy(options) {
20772
20778
  );
20773
20779
  }
20774
20780
  const outboundAgent = outboundProxyUrl !== void 0 && !selfTargeting ? connectTunnelAgent(outboundProxyUrl, targetUrl) : void 0;
20781
+ if (ownHop && outboundAgent) {
20782
+ rejectOwnHop();
20783
+ return;
20784
+ }
20775
20785
  if (outboundAgent) {
20776
20786
  let upstream2;
20777
20787
  let proxyConnectStatus;
@@ -20790,7 +20800,7 @@ async function startHttpProxy(options) {
20790
20800
  if (proxyConnectStatus !== 200 || clientSocket.destroyed) {
20791
20801
  connected.destroy();
20792
20802
  if (!clientSocket.destroyed) {
20793
- clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n", () => clientSocket.destroy());
20803
+ clientSocket.end(proxyConnectStatus === 508 ? "HTTP/1.1 508 Loop Detected\r\n\r\n" : "HTTP/1.1 502 Bad Gateway\r\n\r\n", () => clientSocket.destroy());
20794
20804
  }
20795
20805
  return;
20796
20806
  }
@@ -20868,6 +20878,7 @@ async function startHttpProxy(options) {
20868
20878
  );
20869
20879
  } else {
20870
20880
  anthropicAgent = outboundHttpProxyAgent(anthropicOrigin.href);
20881
+ anthropicViaProxy = anthropicAgent !== void 0;
20871
20882
  }
20872
20883
  anthropicAgent ??= createPassthroughAgent();
20873
20884
  return {