@bman654/clodex 2.8.0 → 2.8.2

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/README.md CHANGED
@@ -205,6 +205,10 @@ Enabling this feature executes that JavaScript with your full user permissions;
205
205
 
206
206
  The module must default-export an array. Each site has a unique lowercase `id` and an `apply` function that returns the complete source and emits the generated `marker` exactly once when it applies:
207
207
 
208
+ The `source` your `apply` receives is every JavaScript module in the binary joined together, with a ``/*clodex:module-boundary`;{}"]*/`` line between them. This is true of every Claude Code version — a pre-2.1.242 binary carries the bundle plus five small helper modules; a 2.1.242-or-later one carries the bundle split across roughly 1,370. Match and replace as you always have; just do not add or remove one of those lines, or the whole patch is refused. (The punctuation in the marker is there so that a wildcard bounded by a character class cannot run across a module boundary.)
209
+
210
+ If your transform works by **position** rather than by matching an anchor, mind where it lands: text prepended to `source` goes into the first module and text appended to it goes into the last, and neither is necessarily the module that runs at startup. Anchor your edit to text you match, the way the examples below do.
211
+
208
212
  ```js
209
213
  export default [
210
214
  {
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.0",
385
+ version: "2.8.2",
386
386
  publishConfig: {
387
387
  access: "public"
388
388
  },
@@ -924,6 +924,7 @@ async function startCallbackServer(options) {
924
924
  let codeResolve;
925
925
  let codeReject;
926
926
  let buffered;
927
+ let ignoredStateMismatchCount = 0;
927
928
  const { path, redirectHost } = options;
928
929
  const server = http.createServer((req, res) => {
929
930
  const u = new URL(req.url ?? "/", "http://localhost");
@@ -936,6 +937,7 @@ async function startCallbackServer(options) {
936
937
  const state = u.searchParams.get("state") ?? "";
937
938
  const error = u.searchParams.get("error") ?? "";
938
939
  if (options.expectedState !== void 0 && state !== options.expectedState) {
940
+ ignoredStateMismatchCount++;
939
941
  res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
940
942
  res.end("Invalid OAuth state");
941
943
  return;
@@ -976,7 +978,9 @@ async function startCallbackServer(options) {
976
978
  return;
977
979
  }
978
980
  const timer = setTimeout(
979
- () => reject(new Error("OAuth timeout \u2014 browser closed without completing sign-in")),
981
+ () => reject(new Error(
982
+ ignoredStateMismatchCount > 0 ? `OAuth timeout \u2014 ignored ${ignoredStateMismatchCount} callback(s) carrying a different sign-in state; you probably completed an older browser tab. Run the command again and use the newest tab.` : "OAuth timeout \u2014 browser closed without completing sign-in"
983
+ )),
980
984
  timeoutMs
981
985
  );
982
986
  codeResolve = (params) => {
@@ -1136,7 +1140,7 @@ async function runOpenAiBrowserFlow(onAuthorizeUrl, opts) {
1136
1140
  } catch (error) {
1137
1141
  if (error.code === "EADDRINUSE") {
1138
1142
  throw new Error(
1139
- `Ports ${ports.join(" and ")} are in use \u2014 close any other OpenAI sign-in (e.g. codex login) and try again.`
1143
+ `Ports ${ports.join(" and ")} are in use \u2014 browser sign-in needs one free. Check for another OpenAI sign-in (e.g. \`codex login\`), or any other process holding them, then try again.`
1140
1144
  );
1141
1145
  }
1142
1146
  throw new Error(
@@ -3419,7 +3423,7 @@ function savedStopsAfter(current, assignments) {
3419
3423
  }
3420
3424
 
3421
3425
  // src/patch-transforms.ts
3422
- var PATCH_TRANSFORMS_VERSION = 8;
3426
+ var PATCH_TRANSFORMS_VERSION = 10;
3423
3427
  var NATIVE_EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"];
3424
3428
  var BASE_EFFORT_LEVELS = ["low", "medium", "high"];
3425
3429
  function projectNativeEffort(effort) {
@@ -3622,7 +3626,7 @@ function applyClodexPatches(source, config) {
3622
3626
  }).join("; ");
3623
3627
  applyOnce(
3624
3628
  "PATCH 4: Agent tool model description",
3625
- /(describe\(`Optional model override for this agent[^`]*?)(`\))/,
3629
+ /(describe\(`Optional model override for this agent(?:[^`\\]|\\.)*?)(`)/,
3626
3630
  (_m, body, close) => body.includes("Additional custom models") ? body + close : body + " Additional custom models: " + listing + "." + close,
3627
3631
  { required: false, noopIsSkip: true }
3628
3632
  );
@@ -3840,8 +3844,8 @@ import {
3840
3844
  statSync as statSync6,
3841
3845
  unlinkSync as unlinkSync3,
3842
3846
  writeFileSync as writeFileSync5,
3843
- openSync as openSync4,
3844
- closeSync as closeSync4,
3847
+ openSync as openSync5,
3848
+ closeSync as closeSync5,
3845
3849
  realpathSync
3846
3850
  } from "fs";
3847
3851
  import { homedir as homedir3 } from "os";
@@ -4169,7 +4173,7 @@ function captureBuiltInPatchProofs(source, config, results) {
4169
4173
  );
4170
4174
  addPattern(
4171
4175
  "PATCH 4: Agent tool model description",
4172
- /describe\(`Optional model override for this agent[^`]*?`\)/
4176
+ /describe\(`Optional model override for this agent(?:[^`\\]|\\.)*?`/
4173
4177
  );
4174
4178
  const aliases = configuredAliases(config);
4175
4179
  if (protectsResult(results, "PATCH 6: alias resolver switch")) {
@@ -6800,6 +6804,23 @@ var BUN_OFFSETS_BYTES = 32;
6800
6804
  var TAIL_SCAN_BYTES = 16 * 1024 * 1024;
6801
6805
  var MODULE_STRUCT_BYTES_CURRENT = 52;
6802
6806
  var MODULE_STRUCT_BYTES_LEGACY = 36;
6807
+ var CONTENTS_FIELD_AT = 8;
6808
+ var SOURCEMAP_FIELD_AT = 16;
6809
+ var BYTECODE_FIELD_AT = 24;
6810
+ var MODULE_INFO_FIELD_AT = 32;
6811
+ var BYTECODE_ORIGIN_PATH_FIELD_AT = 40;
6812
+ var BUN_BLOB_FLAGS = {
6813
+ /** Every module's source text lies in one run no other region falls inside. */
6814
+ SOURCE_TEXT_CONTIGUOUS: 1 << 4,
6815
+ /** A `[u32; modules]` of each module's source hash follows the module table. */
6816
+ HAS_SOURCE_HASHES: 1 << 5,
6817
+ /** After the source hashes: `u32 count`, then `count` x `{ u32 id, offset, length }`. */
6818
+ HAS_BUILTIN_BYTECODE: 1 << 6,
6819
+ /** After the builtin-bytecode table: one `{ offset, length }` for the shared string table. */
6820
+ HAS_BYTECODE_STRING_TABLE: 1 << 7
6821
+ };
6822
+ var LOADER_FROM_END = 3;
6823
+ var BUN_JAVASCRIPT_LOADER = 1;
6803
6824
  var MAX_MODULE_NAME_BYTES = 4096;
6804
6825
  var MIN_SHIMMABLE_NAME_BYTES = 7;
6805
6826
  function tweakccRecognizesModuleName(name) {
@@ -6844,6 +6865,9 @@ function parseBunModuleNamesAtUnchecked(fd, offsetsAt) {
6844
6865
  const modulesOffset = offsets.readUInt32LE(8);
6845
6866
  const modulesLength = offsets.readUInt32LE(12);
6846
6867
  const entryPointId = offsets.readUInt32LE(16);
6868
+ const compileExecArgvOffset = offsets.readUInt32LE(20);
6869
+ const compileExecArgvLength = offsets.readUInt32LE(24);
6870
+ const flags = offsets.readUInt32LE(28);
6847
6871
  if (byteCount <= 0n || byteCount > BigInt(offsetsAt)) return null;
6848
6872
  const blobAt = offsetsAt - Number(byteCount);
6849
6873
  if (modulesLength <= 0 || BigInt(modulesOffset) + BigInt(modulesLength) > byteCount) return null;
@@ -6854,6 +6878,12 @@ function parseBunModuleNamesAtUnchecked(fd, offsetsAt) {
6854
6878
  if (!modules) return null;
6855
6879
  const names = [];
6856
6880
  const nameOffsets = [];
6881
+ const contents = [];
6882
+ const sourcemap = [];
6883
+ const bytecode = [];
6884
+ const moduleInfo = [];
6885
+ const bytecodeOriginPath = [];
6886
+ const loaders = [];
6857
6887
  for (let index = 0; index < moduleCount; index++) {
6858
6888
  const nameOffset = modules.readUInt32LE(index * structBytes);
6859
6889
  const nameLength = modules.readUInt32LE(index * structBytes + 4);
@@ -6865,8 +6895,39 @@ function parseBunModuleNamesAtUnchecked(fd, offsetsAt) {
6865
6895
  if (!/^[\x20-\x7e]+$/.test(name)) return null;
6866
6896
  names.push(name);
6867
6897
  nameOffsets.push(blobAt + nameOffset);
6898
+ const pairAt = (field) => ({
6899
+ offset: modules.readUInt32LE(index * structBytes + field),
6900
+ length: modules.readUInt32LE(index * structBytes + field + 4)
6901
+ });
6902
+ contents.push(pairAt(CONTENTS_FIELD_AT));
6903
+ sourcemap.push(pairAt(SOURCEMAP_FIELD_AT));
6904
+ bytecode.push(pairAt(BYTECODE_FIELD_AT));
6905
+ const current = structBytes === MODULE_STRUCT_BYTES_CURRENT;
6906
+ moduleInfo.push(current ? pairAt(MODULE_INFO_FIELD_AT) : { offset: 0, length: 0 });
6907
+ bytecodeOriginPath.push(
6908
+ current ? pairAt(BYTECODE_ORIGIN_PATH_FIELD_AT) : { offset: 0, length: 0 }
6909
+ );
6910
+ loaders.push(modules.readUInt8(index * structBytes + structBytes - LOADER_FROM_END));
6868
6911
  }
6869
- return { names, entryPointId, offsets: nameOffsets };
6912
+ return {
6913
+ names,
6914
+ entryPointId,
6915
+ offsets: nameOffsets,
6916
+ contents,
6917
+ sourcemap,
6918
+ bytecode,
6919
+ moduleInfo,
6920
+ bytecodeOriginPath,
6921
+ loaders,
6922
+ blobAt,
6923
+ modulesAt: blobAt + modulesOffset,
6924
+ modulesOffset,
6925
+ modulesLength,
6926
+ structBytes,
6927
+ byteCount: Number(byteCount),
6928
+ compileExecArgv: { offset: compileExecArgvOffset, length: compileExecArgvLength },
6929
+ flags
6930
+ };
6870
6931
  }
6871
6932
  function findStandIn(fd, fileSize, marker) {
6872
6933
  const needle = Buffer.from(marker);
@@ -6912,6 +6973,40 @@ function isMachO(fd) {
6912
6973
  const value = magic.readUInt32BE(0);
6913
6974
  return value === 4277009102 || value === 4277009103 || value === 3472551422 || value === 3489328638 || value === 3405691582 || value === 3405691583;
6914
6975
  }
6976
+ function readBunModuleTable(path) {
6977
+ const fd = openSync2(path, "r");
6978
+ try {
6979
+ return readBunModuleNames(fd, statSync4(path).size);
6980
+ } finally {
6981
+ closeSync2(fd);
6982
+ }
6983
+ }
6984
+ function readBunJavaScriptModules(path) {
6985
+ const fd = openSync2(path, "r");
6986
+ try {
6987
+ const parsed = readBunModuleNames(fd, statSync4(path).size);
6988
+ if (!parsed) return null;
6989
+ const modules = [];
6990
+ for (let index = 0; index < parsed.names.length; index++) {
6991
+ if (parsed.loaders[index] !== BUN_JAVASCRIPT_LOADER) continue;
6992
+ const range = parsed.contents[index];
6993
+ if (range.offset < 0 || range.length < 0 || range.offset + range.length > parsed.byteCount) {
6994
+ return null;
6995
+ }
6996
+ const bytes = range.length === 0 ? Buffer.alloc(0) : readAt(fd, range.length, parsed.blobAt + range.offset);
6997
+ if (!bytes) return null;
6998
+ modules.push({
6999
+ index,
7000
+ name: parsed.names[index],
7001
+ source: bytes.toString("utf8"),
7002
+ byteLength: bytes.length
7003
+ });
7004
+ }
7005
+ return modules;
7006
+ } finally {
7007
+ closeSync2(fd);
7008
+ }
7009
+ }
6915
7010
  function shimEntryModuleName(path) {
6916
7011
  const fd = openSync2(path, "r+");
6917
7012
  try {
@@ -6944,7 +7039,17 @@ function restoreEntryModuleName(path, shim, { resign }) {
6944
7039
  }
6945
7040
  writeNameBytes(fd, shim.original, offset);
6946
7041
  restoreEveryStandIn(fd, statSync4(path).size, shim);
6947
- machO = resign && isMachO(fd);
7042
+ machO = resign;
7043
+ } finally {
7044
+ closeSync2(fd);
7045
+ }
7046
+ if (machO) resignMachOBinary(path);
7047
+ }
7048
+ function resignMachOBinary(path) {
7049
+ const fd = openSync2(path, "r");
7050
+ let machO;
7051
+ try {
7052
+ machO = isMachO(fd);
6948
7053
  } finally {
6949
7054
  closeSync2(fd);
6950
7055
  }
@@ -6953,6 +7058,228 @@ function restoreEntryModuleName(path, shim, { resign }) {
6953
7058
  }
6954
7059
  }
6955
7060
 
7061
+ // src/bun-bundle.ts
7062
+ import { closeSync as closeSync3, openSync as openSync3, readSync as readSync2, writeSync as writeSync3 } from "fs";
7063
+ function writableModuleIndex(path) {
7064
+ const table = readBunModuleTable(path);
7065
+ if (!table) return null;
7066
+ const index = table.names.findIndex(tweakccRecognizesModuleName);
7067
+ return index < 0 ? null : index;
7068
+ }
7069
+ var BUNDLE_MODULE_SEPARATOR = '\n/*clodex:module-boundary`;{}"]*/\n';
7070
+ function readClaudeBundle(path) {
7071
+ const modules = readBunJavaScriptModules(path);
7072
+ if (!modules || modules.length === 0) return null;
7073
+ if (modules.some((module) => module.source.includes(BUNDLE_MODULE_SEPARATOR))) return null;
7074
+ if (modules.some((module) => !roundTripsAsUtf8(module.source, module.byteLength))) return null;
7075
+ return { modules, source: modules.map((module) => module.source).join(BUNDLE_MODULE_SEPARATOR) };
7076
+ }
7077
+ function roundTripsAsUtf8(source, byteLength) {
7078
+ return Buffer.byteLength(source, "utf8") === byteLength && !source.includes("\uFFFD");
7079
+ }
7080
+ function splitBundleSource(bundle, patched) {
7081
+ const parts = patched.split(BUNDLE_MODULE_SEPARATOR);
7082
+ if (parts.length !== bundle.modules.length) {
7083
+ throw new Error(
7084
+ `the patched bundle has ${parts.length} module boundaries, expected ${bundle.modules.length}`
7085
+ );
7086
+ }
7087
+ return parts;
7088
+ }
7089
+ var BUN_TRAILER2 = Buffer.from("\n---- Bun! ----\n");
7090
+ var BUN_OFFSETS_BYTES2 = 32;
7091
+ var PLACEHOLDER_SLACK_BYTES = 64 * 1024;
7092
+ var BYTECODE_ALIGNMENT = 128;
7093
+ var APPEND_ALIGNMENT = 8;
7094
+ function repackedBlobBytes(table, writableIndex, contentBytes) {
7095
+ let total = 0;
7096
+ for (let index = 0; index < table.names.length; index++) {
7097
+ const fields = [
7098
+ Buffer.byteLength(table.names[index], "utf8"),
7099
+ index === writableIndex ? contentBytes : table.contents[index].length,
7100
+ table.sourcemap[index].length,
7101
+ table.bytecode[index].length
7102
+ ];
7103
+ if (table.structBytes === 52) {
7104
+ fields.push(table.moduleInfo[index].length, table.bytecodeOriginPath[index].length);
7105
+ }
7106
+ for (const length of fields) total += length + 1;
7107
+ }
7108
+ return total + table.modulesLength + table.compileExecArgv.length + 1 + BUN_OFFSETS_BYTES2 + BUN_TRAILER2.length;
7109
+ }
7110
+ function planBundleWrite(path, bundle, patchedSources, writableIndex) {
7111
+ if (patchedSources.length !== bundle.modules.length) {
7112
+ throw new Error(
7113
+ `expected ${bundle.modules.length} patched module sources, got ${patchedSources.length}`
7114
+ );
7115
+ }
7116
+ const table = readBunModuleTable(path);
7117
+ if (!table) throw new Error(`cannot read the Bun module table of ${path}`);
7118
+ const recognized = table.names.filter(tweakccRecognizesModuleName);
7119
+ if (recognized.length !== 1) {
7120
+ throw new Error(
7121
+ `${path} has ${recognized.length} modules tweakcc would write to; the patch was planned around exactly one`
7122
+ );
7123
+ }
7124
+ if (!table.names[writableIndex] || !tweakccRecognizesModuleName(table.names[writableIndex])) {
7125
+ throw new Error(`module ${writableIndex} of ${path} is not the one tweakcc writes to`);
7126
+ }
7127
+ const appends = [];
7128
+ const sources = [];
7129
+ let cursor = table.byteCount;
7130
+ for (let at = 0; at < bundle.modules.length; at++) {
7131
+ const module = bundle.modules[at];
7132
+ const source = patchedSources[at];
7133
+ if (source === module.source) continue;
7134
+ cursor += (APPEND_ALIGNMENT - cursor % APPEND_ALIGNMENT) % APPEND_ALIGNMENT;
7135
+ const bytes = Buffer.from(source, "utf8");
7136
+ appends.push({ index: module.index, range: { offset: cursor, length: bytes.length }, expected: source });
7137
+ sources.push(bytes);
7138
+ cursor += bytes.length + 1;
7139
+ }
7140
+ if (cursor > 4294967295) {
7141
+ throw new Error(`the patched blob of ${path} would be ${cursor} bytes, past the 4 GiB a Bun offset can address`);
7142
+ }
7143
+ const data = Buffer.alloc(cursor);
7144
+ readBlobData(path, table, data);
7145
+ appends.forEach((append, at) => sources[at].copy(data, append.range.offset));
7146
+ for (const append of appends) repointModule(data, table, append);
7147
+ const offsets = Buffer.alloc(BUN_OFFSETS_BYTES2);
7148
+ offsets.writeUInt32LE(table.modulesOffset, 8);
7149
+ offsets.writeUInt32LE(table.modulesLength, 12);
7150
+ offsets.writeUInt32LE(table.entryPointId, 16);
7151
+ offsets.writeUInt32LE(table.compileExecArgv.offset, 20);
7152
+ offsets.writeUInt32LE(table.compileExecArgv.length, 24);
7153
+ offsets.writeUInt32LE(table.flags & ~BUN_BLOB_FLAGS.SOURCE_TEXT_CONTIGUOUS, 28);
7154
+ const wanted = data.length + BUN_OFFSETS_BYTES2 + BUN_TRAILER2.length + PLACEHOLDER_SLACK_BYTES;
7155
+ const empty = repackedBlobBytes(table, writableIndex, 0);
7156
+ if (wanted < empty) {
7157
+ throw new Error(
7158
+ `repacking ${path} is predicted to make a blob of at least ${empty} bytes, more than the ${wanted} the placeholder is sized against; clodex is reading overlapping payload ranges out of this binary's module table`
7159
+ );
7160
+ }
7161
+ return {
7162
+ content: placeholderOf(wanted - empty),
7163
+ data,
7164
+ offsets,
7165
+ writableIndex,
7166
+ names: table.names,
7167
+ entryPointId: table.entryPointId,
7168
+ flags: table.flags & ~BUN_BLOB_FLAGS.SOURCE_TEXT_CONTIGUOUS,
7169
+ blobAt: table.blobAt,
7170
+ appends
7171
+ };
7172
+ }
7173
+ var PLACEHOLDER_TEXT = "/*clodex:placeholder*/\n";
7174
+ function placeholderOf(byteLength) {
7175
+ return PLACEHOLDER_TEXT.repeat(Math.ceil(byteLength / PLACEHOLDER_TEXT.length)).slice(0, byteLength);
7176
+ }
7177
+ function readBlobData(path, table, into) {
7178
+ const fd = openSync3(path, "r");
7179
+ try {
7180
+ let read = 0;
7181
+ while (read < table.byteCount) {
7182
+ const got = readSync2(fd, into, read, table.byteCount - read, table.blobAt + read);
7183
+ if (got <= 0) {
7184
+ throw new Error(`read ${read} of the ${table.byteCount} blob bytes of ${path}`);
7185
+ }
7186
+ read += got;
7187
+ }
7188
+ } finally {
7189
+ closeSync3(fd);
7190
+ }
7191
+ }
7192
+ function repointModule(data, table, append) {
7193
+ const structAt = table.modulesOffset + append.index * table.structBytes;
7194
+ data.writeUInt32LE(append.range.offset, structAt + 8);
7195
+ data.writeUInt32LE(append.range.length, structAt + 12);
7196
+ data.writeUInt32LE(0, structAt + 24);
7197
+ data.writeUInt32LE(0, structAt + 28);
7198
+ if (table.structBytes === 52) {
7199
+ data.writeUInt32LE(0, structAt + 32);
7200
+ data.writeUInt32LE(0, structAt + 36);
7201
+ data.writeUInt32LE(0, structAt + 40);
7202
+ data.writeUInt32LE(0, structAt + 44);
7203
+ }
7204
+ if ((table.flags & BUN_BLOB_FLAGS.HAS_SOURCE_HASHES) === 0) return;
7205
+ const hashAt = table.modulesOffset + table.modulesLength + append.index * 4;
7206
+ if (hashAt + 4 > table.byteCount) {
7207
+ throw new Error(
7208
+ `the blob claims a source hash per module but the table is followed by only ${table.byteCount - table.modulesOffset - table.modulesLength} bytes`
7209
+ );
7210
+ }
7211
+ data.writeUInt32LE(0, hashAt);
7212
+ }
7213
+ function applyBundleWritePlan(path, plan) {
7214
+ const repacked = readBunModuleTable(path);
7215
+ if (!repacked) throw new Error(`cannot read the Bun module table of ${path} after repacking`);
7216
+ const placeholderBytes = Buffer.byteLength(plan.content, "utf8");
7217
+ const written = repacked.contents[plan.writableIndex];
7218
+ if (!written || written.length !== placeholderBytes) {
7219
+ throw new Error(
7220
+ `${path} holds ${written ? written.length : "no"} bytes where the ${placeholderBytes} bytes clodex wrote should be; refusing to publish a blob addressed against it`
7221
+ );
7222
+ }
7223
+ if (repacked.names.length !== plan.names.length || repacked.names.some((name, index) => name !== plan.names[index])) {
7224
+ throw new Error(
7225
+ `${path} exposes a different module table after repacking than the patch was planned around`
7226
+ );
7227
+ }
7228
+ if (repacked.blobAt % BYTECODE_ALIGNMENT !== plan.blobAt % BYTECODE_ALIGNMENT) {
7229
+ throw new Error(
7230
+ `repacking ${path} moved its Bun blob from ${plan.blobAt} to ${repacked.blobAt}, which is a different offset modulo ${BYTECODE_ALIGNMENT}; every unpatched module's cached bytecode would be misaligned`
7231
+ );
7232
+ }
7233
+ const byteCount = repacked.byteCount;
7234
+ if (byteCount < plan.data.length) {
7235
+ throw new Error(
7236
+ `repacking ${path} left ${byteCount} bytes for a blob that needs ${plan.data.length}; refusing to publish a truncated one`
7237
+ );
7238
+ }
7239
+ const offsets = Buffer.from(plan.offsets);
7240
+ offsets.writeBigUInt64LE(BigInt(byteCount), 0);
7241
+ const fd = openSync3(path, "r+");
7242
+ try {
7243
+ writeAll(fd, plan.data, repacked.blobAt, path);
7244
+ const padding = byteCount - plan.data.length;
7245
+ if (padding > 0) writeAll(fd, Buffer.alloc(padding), repacked.blobAt + plan.data.length, path);
7246
+ writeAll(fd, offsets, repacked.blobAt + byteCount, path);
7247
+ writeAll(fd, BUN_TRAILER2, repacked.blobAt + byteCount + BUN_OFFSETS_BYTES2, path);
7248
+ } finally {
7249
+ closeSync3(fd);
7250
+ }
7251
+ const published = readBunModuleTable(path);
7252
+ if (!published) throw new Error(`cannot re-read the Bun module table of ${path} after publishing its blob`);
7253
+ if (published.byteCount !== byteCount || published.entryPointId !== plan.entryPointId || published.flags !== plan.flags || published.names.length !== plan.names.length || published.names.some((name, index) => name !== plan.names[index])) {
7254
+ throw new Error(`the blob published into ${path} does not read back as the one that was planned`);
7255
+ }
7256
+ const after = readBunJavaScriptModules(path);
7257
+ if (!after) throw new Error(`cannot re-read the modules of ${path} after publishing its blob`);
7258
+ const expected = new Map(plan.appends.map((append) => [append.index, append.expected]));
7259
+ let matched = 0;
7260
+ for (const module of after) {
7261
+ const want = expected.get(module.index);
7262
+ if (want === void 0) continue;
7263
+ if (module.source !== want) {
7264
+ throw new Error(`module ${module.index} of ${path} did not read back as the patched source`);
7265
+ }
7266
+ matched++;
7267
+ }
7268
+ if (matched !== expected.size) {
7269
+ throw new Error(
7270
+ `${matched} of the ${expected.size} patched modules of ${path} came back as JavaScript Bun will execute`
7271
+ );
7272
+ }
7273
+ }
7274
+ function writeAll(fd, bytes, position, path) {
7275
+ let written = 0;
7276
+ while (written < bytes.length) {
7277
+ const wrote = writeSync3(fd, bytes, written, bytes.length - written, position + written);
7278
+ if (wrote <= 0) throw new Error(`wrote ${written} of ${bytes.length} blob bytes to ${path}`);
7279
+ written += wrote;
7280
+ }
7281
+ }
7282
+
6956
7283
  // src/patch-backup.ts
6957
7284
  import { createHash as createHash5 } from "crypto";
6958
7285
  import { existsSync as existsSync4, readFileSync as readFileSync7, readdirSync, statSync as statSync5 } from "fs";
@@ -9832,7 +10159,7 @@ function thinkingProviderOptions(npm) {
9832
10159
 
9833
10160
  // src/proxy.ts
9834
10161
  import { createServer } from "http";
9835
- import { appendFileSync as appendFileSync2, openSync as openSync3, writeSync as writeSync3, closeSync as closeSync3 } from "fs";
10162
+ import { appendFileSync as appendFileSync2, openSync as openSync4, writeSync as writeSync4, closeSync as closeSync4 } from "fs";
9836
10163
 
9837
10164
  // src/http-utils.ts
9838
10165
  import * as zlib from "zlib";
@@ -11286,12 +11613,12 @@ function createTranslationLifecycle(logPath, requestId, claudeSessionId, modelId
11286
11613
  function appendSecureLog(logPath, line) {
11287
11614
  const redacted = redactTraceLine(line);
11288
11615
  try {
11289
- const fd = openSync3(logPath, "a", 384);
11616
+ const fd = openSync4(logPath, "a", 384);
11290
11617
  try {
11291
- writeSync3(fd, `${(/* @__PURE__ */ new Date()).toISOString()} ${redacted}
11618
+ writeSync4(fd, `${(/* @__PURE__ */ new Date()).toISOString()} ${redacted}
11292
11619
  `);
11293
11620
  } finally {
11294
- closeSync3(fd);
11621
+ closeSync4(fd);
11295
11622
  }
11296
11623
  } catch {
11297
11624
  try {
@@ -12154,10 +12481,10 @@ function tryAcquirePatchLock(lockPath = getPatchLockPath(), opts = {}) {
12154
12481
  mkdirSync5(join7(lockPath, ".."), { recursive: true, mode: 448 });
12155
12482
  for (let attempt = 0; attempt < 2; attempt++) {
12156
12483
  try {
12157
- const fd = openSync4(lockPath, "wx");
12484
+ const fd = openSync5(lockPath, "wx");
12158
12485
  const content = { pid: process.pid, startedAt: now };
12159
12486
  writeFileSync5(fd, JSON.stringify(content));
12160
- closeSync4(fd);
12487
+ closeSync5(fd);
12161
12488
  return () => {
12162
12489
  try {
12163
12490
  unlinkSync3(lockPath);
@@ -12304,9 +12631,15 @@ async function applyPatch(binaryPath, version, desired, configHash, opts) {
12304
12631
  copyFileSync(from, candidatePath);
12305
12632
  const shim = shimEntryModuleName(candidatePath);
12306
12633
  const installation = await tryDetectInstallation({ path: candidatePath });
12307
- const source = await readContent(installation);
12634
+ const bundle = readClaudeBundle(candidatePath);
12635
+ if (!bundle && installation.kind === "native") {
12636
+ p2.log.warn(
12637
+ `Could not read ${candidatePath} as a Bun module table, so only the module tweakcc names is being patched. On Claude Code 2.1.242 and later that module is a stub holding none of the code clodex patches, and the patch below will fail at its first required site \u2014 the cause is this read, not a changed anchor.`
12638
+ );
12639
+ }
12640
+ const source = bundle ? bundle.source : await readContent(installation);
12308
12641
  if (shim) restoreEntryModuleName(candidatePath, shim, { resign: false });
12309
- return { installation, source };
12642
+ return { installation, source, bundle };
12310
12643
  };
12311
12644
  const facts = collectPristineFacts({
12312
12645
  version,
@@ -12399,8 +12732,26 @@ async function applyPatch(binaryPath, version, desired, configHash, opts) {
12399
12732
  }
12400
12733
  results = [...results, ...local.results];
12401
12734
  const writeShim = shimEntryModuleName(candidatePath);
12402
- await writeContent(loaded.installation, local.content);
12735
+ let publishedBlob = false;
12736
+ if (loaded.bundle) {
12737
+ const writable = writableModuleIndex(candidatePath);
12738
+ if (writable === null) {
12739
+ throw new Error("no module of the patch candidate carries a name tweakcc can write to");
12740
+ }
12741
+ const plan2 = planBundleWrite(
12742
+ candidatePath,
12743
+ loaded.bundle,
12744
+ splitBundleSource(loaded.bundle, local.content),
12745
+ writable
12746
+ );
12747
+ await writeContent(loaded.installation, plan2.content);
12748
+ applyBundleWritePlan(candidatePath, plan2);
12749
+ publishedBlob = true;
12750
+ } else {
12751
+ await writeContent(loaded.installation, local.content);
12752
+ }
12403
12753
  if (writeShim) restoreEntryModuleName(candidatePath, writeShim, { resign: true });
12754
+ else if (publishedBlob) resignMachOBinary(candidatePath);
12404
12755
  patchedSize = statSync6(candidatePath).size;
12405
12756
  patchedSha256 = sha256File(candidatePath);
12406
12757
  renameSync2(candidatePath, binaryPath);
@@ -12918,13 +13269,13 @@ function localProvidersToServerModels(localProviders) {
12918
13269
  // src/registry/credential-cleanup-journal.ts
12919
13270
  import { randomUUID as randomUUID4 } from "crypto";
12920
13271
  import {
12921
- closeSync as closeSync5,
13272
+ closeSync as closeSync6,
12922
13273
  existsSync as existsSync6,
12923
13274
  fstatSync,
12924
13275
  fsyncSync as fsyncSync2,
12925
13276
  lstatSync,
12926
13277
  mkdirSync as mkdirSync6,
12927
- openSync as openSync5,
13278
+ openSync as openSync6,
12928
13279
  readFileSync as readFileSync9,
12929
13280
  renameSync as renameSync3,
12930
13281
  unlinkSync as unlinkSync4,
@@ -13016,7 +13367,7 @@ function readJournalUnlocked(path) {
13016
13367
  if (before.isSymbolicLink() || !before.isFile()) {
13017
13368
  throw new Error("Credential cleanup journal must be a regular file.");
13018
13369
  }
13019
- fd = openSync5(path, "r");
13370
+ fd = openSync6(path, "r");
13020
13371
  const opened = fstatSync(fd);
13021
13372
  if (before.dev !== opened.dev || before.ino !== opened.ino) {
13022
13373
  throw new Error("Credential cleanup journal changed while opening.");
@@ -13037,19 +13388,19 @@ function readJournalUnlocked(path) {
13037
13388
  const message = error instanceof Error ? error.message : String(error);
13038
13389
  throw new Error(`Could not read credential cleanup journal: ${message}`);
13039
13390
  } finally {
13040
- if (fd !== void 0) closeSync5(fd);
13391
+ if (fd !== void 0) closeSync6(fd);
13041
13392
  }
13042
13393
  }
13043
13394
  function syncParentDirectory(path) {
13044
13395
  let fd;
13045
13396
  try {
13046
- fd = openSync5(dirname4(path), "r");
13397
+ fd = openSync6(dirname4(path), "r");
13047
13398
  fsyncSync2(fd);
13048
13399
  } catch (error) {
13049
13400
  const code = error.code;
13050
13401
  if (code !== "EINVAL" && code !== "ENOTSUP" && code !== "EPERM") throw error;
13051
13402
  } finally {
13052
- if (fd !== void 0) closeSync5(fd);
13403
+ if (fd !== void 0) closeSync6(fd);
13053
13404
  }
13054
13405
  }
13055
13406
  function writeJournalUnlocked(journal, path) {
@@ -13059,17 +13410,17 @@ function writeJournalUnlocked(journal, path) {
13059
13410
  const tmp = `${path}.${process.pid}.${randomUUID4()}.tmp`;
13060
13411
  let fd;
13061
13412
  try {
13062
- fd = openSync5(tmp, "wx", FILE_MODE4);
13413
+ fd = openSync6(tmp, "wx", FILE_MODE4);
13063
13414
  writeFileSync6(fd, `${JSON.stringify(journal, null, 2)}
13064
13415
  `);
13065
13416
  fsyncSync2(fd);
13066
- closeSync5(fd);
13417
+ closeSync6(fd);
13067
13418
  fd = void 0;
13068
13419
  assertRegistryWriteOwnership(path);
13069
13420
  renameSync3(tmp, path);
13070
13421
  syncParentDirectory(path);
13071
13422
  } finally {
13072
- if (fd !== void 0) closeSync5(fd);
13423
+ if (fd !== void 0) closeSync6(fd);
13073
13424
  try {
13074
13425
  unlinkSync4(tmp);
13075
13426
  } catch (error) {