@bman654/clodex 2.5.1 → 2.5.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/dist/cli.js +166 -13
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -374,7 +374,7 @@ import { join } from "path";
|
|
|
374
374
|
// package.json
|
|
375
375
|
var package_default = {
|
|
376
376
|
name: "@bman654/clodex",
|
|
377
|
-
version: "2.5.
|
|
377
|
+
version: "2.5.2",
|
|
378
378
|
publishConfig: {
|
|
379
379
|
access: "public"
|
|
380
380
|
},
|
|
@@ -15600,11 +15600,11 @@ import {
|
|
|
15600
15600
|
readFileSync as readFileSync10,
|
|
15601
15601
|
renameSync as renameSync3,
|
|
15602
15602
|
rmSync,
|
|
15603
|
-
statSync as
|
|
15603
|
+
statSync as statSync6,
|
|
15604
15604
|
unlinkSync as unlinkSync4,
|
|
15605
15605
|
writeFileSync as writeFileSync7,
|
|
15606
|
-
openSync as
|
|
15607
|
-
closeSync as
|
|
15606
|
+
openSync as openSync5,
|
|
15607
|
+
closeSync as closeSync5,
|
|
15608
15608
|
realpathSync
|
|
15609
15609
|
} from "fs";
|
|
15610
15610
|
import { homedir as homedir3 } from "os";
|
|
@@ -15987,9 +15987,152 @@ function builtInPatchProofsChanged(source, proofs) {
|
|
|
15987
15987
|
);
|
|
15988
15988
|
}
|
|
15989
15989
|
|
|
15990
|
+
// src/bun-entry-module.ts
|
|
15991
|
+
import { closeSync as closeSync4, openSync as openSync4, readSync, statSync as statSync4, writeSync as writeSync3 } from "fs";
|
|
15992
|
+
import { execFileSync } from "child_process";
|
|
15993
|
+
var BUN_TRAILER = Buffer.from("\n---- Bun! ----\n");
|
|
15994
|
+
var BUN_OFFSETS_BYTES = 32;
|
|
15995
|
+
var TAIL_SCAN_BYTES = 16 * 1024 * 1024;
|
|
15996
|
+
var MODULE_STRUCT_BYTES_CURRENT = 52;
|
|
15997
|
+
var MODULE_STRUCT_BYTES_LEGACY = 36;
|
|
15998
|
+
var MAX_MODULE_NAME_BYTES = 4096;
|
|
15999
|
+
var MIN_SHIMMABLE_NAME_BYTES = 7;
|
|
16000
|
+
function tweakccRecognizesModuleName(name) {
|
|
16001
|
+
return name.endsWith("/claude") || name === "claude" || name.endsWith("/claude.exe") || name === "claude.exe" || name.endsWith("/src/entrypoints/cli.js") || name === "src/entrypoints/cli.js";
|
|
16002
|
+
}
|
|
16003
|
+
function entryModuleShimName(byteLength) {
|
|
16004
|
+
if (byteLength < MIN_SHIMMABLE_NAME_BYTES) return null;
|
|
16005
|
+
const padding = byteLength - MIN_SHIMMABLE_NAME_BYTES;
|
|
16006
|
+
return "/clodex".padEnd(padding, "-").slice(0, padding) + "/claude";
|
|
16007
|
+
}
|
|
16008
|
+
function readAt(fd, length, position) {
|
|
16009
|
+
if (length <= 0 || position < 0) return null;
|
|
16010
|
+
const buffer = Buffer.alloc(length);
|
|
16011
|
+
const read = readSync(fd, buffer, 0, length, position);
|
|
16012
|
+
return read === length ? buffer : null;
|
|
16013
|
+
}
|
|
16014
|
+
function readBunModuleNames(fd, fileSize) {
|
|
16015
|
+
const tailLength = Math.min(fileSize, TAIL_SCAN_BYTES);
|
|
16016
|
+
const tail = readAt(fd, tailLength, fileSize - tailLength);
|
|
16017
|
+
if (!tail) return null;
|
|
16018
|
+
const tailAt = fileSize - tailLength;
|
|
16019
|
+
for (let searchFrom = tail.length - 1; searchFrom >= 0; ) {
|
|
16020
|
+
const trailerInTail = tail.lastIndexOf(BUN_TRAILER, searchFrom);
|
|
16021
|
+
if (trailerInTail < 0) return null;
|
|
16022
|
+
const parsed = parseBunModuleNamesAt(fd, tailAt + trailerInTail - BUN_OFFSETS_BYTES);
|
|
16023
|
+
if (parsed) return parsed;
|
|
16024
|
+
searchFrom = trailerInTail - 1;
|
|
16025
|
+
}
|
|
16026
|
+
return null;
|
|
16027
|
+
}
|
|
16028
|
+
function parseBunModuleNamesAt(fd, offsetsAt) {
|
|
16029
|
+
try {
|
|
16030
|
+
return parseBunModuleNamesAtUnchecked(fd, offsetsAt);
|
|
16031
|
+
} catch {
|
|
16032
|
+
return null;
|
|
16033
|
+
}
|
|
16034
|
+
}
|
|
16035
|
+
function parseBunModuleNamesAtUnchecked(fd, offsetsAt) {
|
|
16036
|
+
const offsets = readAt(fd, BUN_OFFSETS_BYTES, offsetsAt);
|
|
16037
|
+
if (!offsets) return null;
|
|
16038
|
+
const byteCount = offsets.readBigUInt64LE(0);
|
|
16039
|
+
const modulesOffset = offsets.readUInt32LE(8);
|
|
16040
|
+
const modulesLength = offsets.readUInt32LE(12);
|
|
16041
|
+
const entryPointId = offsets.readUInt32LE(16);
|
|
16042
|
+
if (byteCount <= 0n || byteCount > BigInt(offsetsAt)) return null;
|
|
16043
|
+
const blobAt = offsetsAt - Number(byteCount);
|
|
16044
|
+
if (modulesLength <= 0 || BigInt(modulesOffset) + BigInt(modulesLength) > byteCount) return null;
|
|
16045
|
+
const structBytes = modulesLength % MODULE_STRUCT_BYTES_LEGACY === 0 && modulesLength % MODULE_STRUCT_BYTES_CURRENT !== 0 ? MODULE_STRUCT_BYTES_LEGACY : MODULE_STRUCT_BYTES_CURRENT;
|
|
16046
|
+
const moduleCount = Math.floor(modulesLength / structBytes);
|
|
16047
|
+
if (moduleCount <= 0 || entryPointId >= moduleCount) return null;
|
|
16048
|
+
const modules = readAt(fd, moduleCount * structBytes, blobAt + modulesOffset);
|
|
16049
|
+
if (!modules) return null;
|
|
16050
|
+
const names = [];
|
|
16051
|
+
const nameOffsets = [];
|
|
16052
|
+
for (let index = 0; index < moduleCount; index++) {
|
|
16053
|
+
const nameOffset = modules.readUInt32LE(index * structBytes);
|
|
16054
|
+
const nameLength = modules.readUInt32LE(index * structBytes + 4);
|
|
16055
|
+
if (nameLength <= 0 || nameLength > MAX_MODULE_NAME_BYTES) return null;
|
|
16056
|
+
if (BigInt(nameOffset) + BigInt(nameLength) > byteCount) return null;
|
|
16057
|
+
const bytes = readAt(fd, nameLength + 1, blobAt + nameOffset);
|
|
16058
|
+
if (!bytes || bytes[nameLength] !== 0) return null;
|
|
16059
|
+
const name = bytes.subarray(0, nameLength).toString("utf8");
|
|
16060
|
+
if (!/^[\x20-\x7e]+$/.test(name)) return null;
|
|
16061
|
+
names.push(name);
|
|
16062
|
+
nameOffsets.push(blobAt + nameOffset);
|
|
16063
|
+
}
|
|
16064
|
+
return { names, entryPointId, offsets: nameOffsets };
|
|
16065
|
+
}
|
|
16066
|
+
function assertShimGone(fd, fileSize, marker) {
|
|
16067
|
+
const needle = Buffer.from(marker);
|
|
16068
|
+
const chunkBytes = 8 * 1024 * 1024;
|
|
16069
|
+
let carry = Buffer.alloc(0);
|
|
16070
|
+
for (let position = 0; position < fileSize; ) {
|
|
16071
|
+
const length = Math.min(chunkBytes, fileSize - position);
|
|
16072
|
+
const chunk = readAt(fd, length, position);
|
|
16073
|
+
if (!chunk) throw new Error("could not re-read the candidate to verify the entry-module name");
|
|
16074
|
+
const window = carry.length > 0 ? Buffer.concat([carry, chunk]) : chunk;
|
|
16075
|
+
if (window.includes(needle)) {
|
|
16076
|
+
throw new Error(`the entry-module stand-in ${marker} survived restoration`);
|
|
16077
|
+
}
|
|
16078
|
+
carry = Buffer.from(window.subarray(Math.max(0, window.length - (needle.length - 1))));
|
|
16079
|
+
position += length;
|
|
16080
|
+
}
|
|
16081
|
+
}
|
|
16082
|
+
function writeNameBytes(fd, name, offset) {
|
|
16083
|
+
const bytes = Buffer.from(name);
|
|
16084
|
+
const written = writeSync3(fd, bytes, 0, bytes.length, offset);
|
|
16085
|
+
if (written !== bytes.length) {
|
|
16086
|
+
throw new Error(`wrote ${written} of ${bytes.length} entry-module name bytes at ${offset}`);
|
|
16087
|
+
}
|
|
16088
|
+
}
|
|
16089
|
+
function isMachO(fd) {
|
|
16090
|
+
const magic = readAt(fd, 4, 0);
|
|
16091
|
+
if (!magic) return false;
|
|
16092
|
+
const value = magic.readUInt32BE(0);
|
|
16093
|
+
return value === 4277009102 || value === 4277009103 || value === 3472551422 || value === 3489328638 || value === 3405691582 || value === 3405691583;
|
|
16094
|
+
}
|
|
16095
|
+
function shimEntryModuleName(path) {
|
|
16096
|
+
const fd = openSync4(path, "r+");
|
|
16097
|
+
try {
|
|
16098
|
+
const parsed = readBunModuleNames(fd, statSync4(path).size);
|
|
16099
|
+
if (!parsed) return null;
|
|
16100
|
+
if (parsed.names.some(tweakccRecognizesModuleName)) return null;
|
|
16101
|
+
const original = parsed.names[parsed.entryPointId];
|
|
16102
|
+
const offset = parsed.offsets[parsed.entryPointId];
|
|
16103
|
+
const marker = entryModuleShimName(Buffer.byteLength(original));
|
|
16104
|
+
if (marker === null) return null;
|
|
16105
|
+
writeNameBytes(fd, marker, offset);
|
|
16106
|
+
return { offset, original, marker };
|
|
16107
|
+
} finally {
|
|
16108
|
+
closeSync4(fd);
|
|
16109
|
+
}
|
|
16110
|
+
}
|
|
16111
|
+
function restoreEntryModuleName(path, shim, { resign }) {
|
|
16112
|
+
const fd = openSync4(path, "r+");
|
|
16113
|
+
let machO;
|
|
16114
|
+
try {
|
|
16115
|
+
const parsed = readBunModuleNames(fd, statSync4(path).size);
|
|
16116
|
+
const offset = parsed?.offsets[parsed.entryPointId];
|
|
16117
|
+
if (!parsed || offset === void 0 || parsed.names[parsed.entryPointId] !== shim.marker) {
|
|
16118
|
+
throw new Error(
|
|
16119
|
+
`expected the entry module of ${path} to be named ${shim.marker}, found ${parsed ? JSON.stringify(parsed.names[parsed.entryPointId]) : "no readable Bun module list"}`
|
|
16120
|
+
);
|
|
16121
|
+
}
|
|
16122
|
+
writeNameBytes(fd, shim.original, offset);
|
|
16123
|
+
assertShimGone(fd, statSync4(path).size, shim.marker);
|
|
16124
|
+
machO = resign && isMachO(fd);
|
|
16125
|
+
} finally {
|
|
16126
|
+
closeSync4(fd);
|
|
16127
|
+
}
|
|
16128
|
+
if (machO && process.platform === "darwin") {
|
|
16129
|
+
execFileSync("codesign", ["-s", "-", "-f", path], { stdio: "ignore" });
|
|
16130
|
+
}
|
|
16131
|
+
}
|
|
16132
|
+
|
|
15990
16133
|
// src/patch-backup.ts
|
|
15991
16134
|
import { createHash as createHash8 } from "crypto";
|
|
15992
|
-
import { existsSync as existsSync6, readFileSync as readFileSync9, readdirSync, statSync as
|
|
16135
|
+
import { existsSync as existsSync6, readFileSync as readFileSync9, readdirSync, statSync as statSync5 } from "fs";
|
|
15993
16136
|
import { homedir as homedir2 } from "os";
|
|
15994
16137
|
import { join as join7 } from "path";
|
|
15995
16138
|
var BACKUP_SHA_PREFIX_LENGTH = 16;
|
|
@@ -16027,7 +16170,7 @@ function scanPristineBackups(version, dir = backupDir()) {
|
|
|
16027
16170
|
const path = join7(dir, entry);
|
|
16028
16171
|
let sha256;
|
|
16029
16172
|
try {
|
|
16030
|
-
if (!
|
|
16173
|
+
if (!statSync5(path).isFile()) continue;
|
|
16031
16174
|
sha256 = sha256File(path);
|
|
16032
16175
|
} catch {
|
|
16033
16176
|
corrupt.push(path);
|
|
@@ -16619,10 +16762,10 @@ function tryAcquirePatchLock(lockPath = getPatchLockPath(), opts = {}) {
|
|
|
16619
16762
|
mkdirSync7(join8(lockPath, ".."), { recursive: true, mode: 448 });
|
|
16620
16763
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
16621
16764
|
try {
|
|
16622
|
-
const fd =
|
|
16765
|
+
const fd = openSync5(lockPath, "wx");
|
|
16623
16766
|
const content = { pid: process.pid, startedAt: now };
|
|
16624
16767
|
writeFileSync7(fd, JSON.stringify(content));
|
|
16625
|
-
|
|
16768
|
+
closeSync5(fd);
|
|
16626
16769
|
return () => {
|
|
16627
16770
|
try {
|
|
16628
16771
|
unlinkSync4(lockPath);
|
|
@@ -16658,7 +16801,7 @@ function resolveClaudeBinaryForPatch() {
|
|
|
16658
16801
|
return { ok: false, reason: "binary-not-found" };
|
|
16659
16802
|
}
|
|
16660
16803
|
try {
|
|
16661
|
-
if (!
|
|
16804
|
+
if (!statSync6(resolved).isFile()) return { ok: false, reason: "binary-not-found" };
|
|
16662
16805
|
} catch {
|
|
16663
16806
|
return { ok: false, reason: "binary-not-found" };
|
|
16664
16807
|
}
|
|
@@ -16767,8 +16910,11 @@ async function applyPatch(binaryPath, version, desired, configHash, opts) {
|
|
|
16767
16910
|
const candidatePath = join8(candidateDir, basename(binaryPath));
|
|
16768
16911
|
const seedCandidate = async (from) => {
|
|
16769
16912
|
copyFileSync(from, candidatePath);
|
|
16913
|
+
const shim = shimEntryModuleName(candidatePath);
|
|
16770
16914
|
const installation = await tryDetectInstallation({ path: candidatePath });
|
|
16771
|
-
|
|
16915
|
+
const source = await readContent(installation);
|
|
16916
|
+
if (shim) restoreEntryModuleName(candidatePath, shim, { resign: false });
|
|
16917
|
+
return { installation, source };
|
|
16772
16918
|
};
|
|
16773
16919
|
const facts = collectPristineFacts({
|
|
16774
16920
|
version,
|
|
@@ -16805,6 +16951,11 @@ async function applyPatch(binaryPath, version, desired, configHash, opts) {
|
|
|
16805
16951
|
return { ok: false, message: describePoisonedPristineSource(backup, version) };
|
|
16806
16952
|
}
|
|
16807
16953
|
} else if (plan.action === "snapshot") {
|
|
16954
|
+
if (sha256File(candidatePath) !== plan.pristineSha256) {
|
|
16955
|
+
throw new Error(
|
|
16956
|
+
`the patch candidate no longer matches the pristine bytes it was seeded from; refusing to publish it as ${plan.backupPath}`
|
|
16957
|
+
);
|
|
16958
|
+
}
|
|
16808
16959
|
publishBackupFile(candidatePath, plan.backupPath);
|
|
16809
16960
|
}
|
|
16810
16961
|
const canonical = contentAddressedBackupPath(version, pristineSha256);
|
|
@@ -16855,8 +17006,10 @@ async function applyPatch(binaryPath, version, desired, configHash, opts) {
|
|
|
16855
17006
|
local = discardLocalPatchOutcome(builtIn.content, local.results);
|
|
16856
17007
|
}
|
|
16857
17008
|
results = [...results, ...local.results];
|
|
17009
|
+
const writeShim = shimEntryModuleName(candidatePath);
|
|
16858
17010
|
await writeContent(loaded.installation, local.content);
|
|
16859
|
-
|
|
17011
|
+
if (writeShim) restoreEntryModuleName(candidatePath, writeShim, { resign: true });
|
|
17012
|
+
patchedSize = statSync6(candidatePath).size;
|
|
16860
17013
|
patchedSha256 = sha256File(candidatePath);
|
|
16861
17014
|
renameSync3(candidatePath, binaryPath);
|
|
16862
17015
|
} catch (err) {
|
|
@@ -16981,7 +17134,7 @@ async function runPatchCommand(opts = {}) {
|
|
|
16981
17134
|
binaryPath,
|
|
16982
17135
|
claudeVersion: version,
|
|
16983
17136
|
configHash,
|
|
16984
|
-
binarySize:
|
|
17137
|
+
binarySize: statSync6(binaryPath).size
|
|
16985
17138
|
});
|
|
16986
17139
|
if (state === "current") {
|
|
16987
17140
|
p11.log.success(`claude ${version} is already patched with the current model config \u2014 nothing to do.`);
|
|
@@ -17037,7 +17190,7 @@ async function runLaunchPatchCheck(opts = {}) {
|
|
|
17037
17190
|
binaryPath: resolved.binaryPath,
|
|
17038
17191
|
claudeVersion: resolved.version,
|
|
17039
17192
|
configHash,
|
|
17040
|
-
binarySize:
|
|
17193
|
+
binarySize: statSync6(resolved.binaryPath).size
|
|
17041
17194
|
});
|
|
17042
17195
|
if (state === "current") return;
|
|
17043
17196
|
const interactive = !opts.dryRun && !opts.agentStdout && process.stdin.isTTY === true && process.stdout.isTTY === true;
|