@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 +4 -0
- package/dist/cli.js +379 -28
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
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.
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
|
3844
|
-
closeSync as
|
|
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 {
|
|
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
|
|
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
|
|
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 =
|
|
11616
|
+
const fd = openSync4(logPath, "a", 384);
|
|
11290
11617
|
try {
|
|
11291
|
-
|
|
11618
|
+
writeSync4(fd, `${(/* @__PURE__ */ new Date()).toISOString()} ${redacted}
|
|
11292
11619
|
`);
|
|
11293
11620
|
} finally {
|
|
11294
|
-
|
|
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 =
|
|
12484
|
+
const fd = openSync5(lockPath, "wx");
|
|
12158
12485
|
const content = { pid: process.pid, startedAt: now };
|
|
12159
12486
|
writeFileSync5(fd, JSON.stringify(content));
|
|
12160
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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)
|
|
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 =
|
|
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)
|
|
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 =
|
|
13413
|
+
fd = openSync6(tmp, "wx", FILE_MODE4);
|
|
13063
13414
|
writeFileSync6(fd, `${JSON.stringify(journal, null, 2)}
|
|
13064
13415
|
`);
|
|
13065
13416
|
fsyncSync2(fd);
|
|
13066
|
-
|
|
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)
|
|
13423
|
+
if (fd !== void 0) closeSync6(fd);
|
|
13073
13424
|
try {
|
|
13074
13425
|
unlinkSync4(tmp);
|
|
13075
13426
|
} catch (error) {
|