@bman654/clodex 2.11.4 → 2.11.6
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
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
withProviderMutationLock,
|
|
53
53
|
withRegistryWriteLock,
|
|
54
54
|
withRegistryWriteLockSync
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-ZM2KYLPH.js";
|
|
56
56
|
|
|
57
57
|
// src/cli.ts
|
|
58
58
|
import pc13 from "picocolors";
|
|
@@ -227,7 +227,7 @@ function printFavoritesOnlyPanel() {
|
|
|
227
227
|
|
|
228
228
|
// src/cli.ts
|
|
229
229
|
import * as p12 from "@clack/prompts";
|
|
230
|
-
import { realpathSync as
|
|
230
|
+
import { realpathSync as realpathSync3 } from "fs";
|
|
231
231
|
import { fileURLToPath } from "url";
|
|
232
232
|
|
|
233
233
|
// src/launch.ts
|
|
@@ -297,7 +297,7 @@ function buildClaudeArgs(model, extraArgs) {
|
|
|
297
297
|
return model ? ["--model", model, ...extraArgs] : [...extraArgs];
|
|
298
298
|
}
|
|
299
299
|
function launchClaude(env, model, extraArgs) {
|
|
300
|
-
return new Promise((
|
|
300
|
+
return new Promise((resolve4) => {
|
|
301
301
|
const claudePath = findClaudeBinary();
|
|
302
302
|
const args = buildClaudeArgs(model, extraArgs);
|
|
303
303
|
const debugFileIdx = extraArgs.indexOf("--debug-file");
|
|
@@ -366,11 +366,11 @@ function launchClaude(env, model, extraArgs) {
|
|
|
366
366
|
process.once("SIGTERM", () => forward("SIGTERM"));
|
|
367
367
|
child.on("exit", (code) => {
|
|
368
368
|
restore();
|
|
369
|
-
|
|
369
|
+
resolve4(code ?? 0);
|
|
370
370
|
});
|
|
371
371
|
child.on("error", (err) => {
|
|
372
372
|
restore();
|
|
373
|
-
|
|
373
|
+
resolve4(1);
|
|
374
374
|
});
|
|
375
375
|
});
|
|
376
376
|
}
|
|
@@ -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.11.
|
|
385
|
+
version: "2.11.6",
|
|
386
386
|
publishConfig: {
|
|
387
387
|
access: "public"
|
|
388
388
|
},
|
|
@@ -584,7 +584,7 @@ async function runCredentialHelper(operation, account, input, expectedHelperId)
|
|
|
584
584
|
`${CREDENTIAL_HELPER_ENV} does not match the helper that owns this credential; restore the prior helper or reauthenticate`
|
|
585
585
|
);
|
|
586
586
|
}
|
|
587
|
-
return new Promise((
|
|
587
|
+
return new Promise((resolve4, reject) => {
|
|
588
588
|
const child = spawn2(
|
|
589
589
|
helper.path,
|
|
590
590
|
[operation, CREDENTIAL_HELPER_SERVICE, account],
|
|
@@ -625,7 +625,7 @@ async function runCredentialHelper(operation, account, input, expectedHelperId)
|
|
|
625
625
|
if (settled) return;
|
|
626
626
|
settled = true;
|
|
627
627
|
clearTimeout(timer);
|
|
628
|
-
|
|
628
|
+
resolve4({ code: code ?? 1, stdout: Buffer.concat(stdout).toString("utf8") });
|
|
629
629
|
});
|
|
630
630
|
if (input !== void 0) child.stdin.end(input);
|
|
631
631
|
else child.stdin.end();
|
|
@@ -852,7 +852,7 @@ function positiveSecondsToMs(value, defaultMs) {
|
|
|
852
852
|
return Number.isFinite(seconds) && seconds > 0 ? seconds * 1e3 : defaultMs;
|
|
853
853
|
}
|
|
854
854
|
async function sleepMs(ms) {
|
|
855
|
-
await new Promise((
|
|
855
|
+
await new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
856
856
|
}
|
|
857
857
|
|
|
858
858
|
// src/oauth/refresh-http.ts
|
|
@@ -979,9 +979,9 @@ async function startCallbackServer(options) {
|
|
|
979
979
|
port: address.port,
|
|
980
980
|
redirectUri: `http://${redirectHost}:${address.port}${path}`,
|
|
981
981
|
waitForCallback(timeoutMs = 3e5) {
|
|
982
|
-
return new Promise((
|
|
982
|
+
return new Promise((resolve4, reject) => {
|
|
983
983
|
if (buffered) {
|
|
984
|
-
|
|
984
|
+
resolve4(buffered);
|
|
985
985
|
buffered = void 0;
|
|
986
986
|
return;
|
|
987
987
|
}
|
|
@@ -993,7 +993,7 @@ async function startCallbackServer(options) {
|
|
|
993
993
|
);
|
|
994
994
|
codeResolve = (params) => {
|
|
995
995
|
clearTimeout(timer);
|
|
996
|
-
|
|
996
|
+
resolve4(params);
|
|
997
997
|
};
|
|
998
998
|
codeReject = (err) => {
|
|
999
999
|
clearTimeout(timer);
|
|
@@ -3888,18 +3888,18 @@ import {
|
|
|
3888
3888
|
existsSync as existsSync5,
|
|
3889
3889
|
mkdtempSync,
|
|
3890
3890
|
mkdirSync as mkdirSync5,
|
|
3891
|
-
readFileSync as
|
|
3891
|
+
readFileSync as readFileSync10,
|
|
3892
3892
|
renameSync as renameSync2,
|
|
3893
3893
|
rmSync,
|
|
3894
|
-
statSync as
|
|
3894
|
+
statSync as statSync8,
|
|
3895
3895
|
unlinkSync as unlinkSync3,
|
|
3896
3896
|
writeFileSync as writeFileSync5,
|
|
3897
|
-
openSync as
|
|
3898
|
-
closeSync as
|
|
3899
|
-
realpathSync
|
|
3897
|
+
openSync as openSync7,
|
|
3898
|
+
closeSync as closeSync7,
|
|
3899
|
+
realpathSync as realpathSync2
|
|
3900
3900
|
} from "fs";
|
|
3901
3901
|
import { homedir as homedir3 } from "os";
|
|
3902
|
-
import { basename, dirname as
|
|
3902
|
+
import { basename, dirname as dirname5, join as join8 } from "path";
|
|
3903
3903
|
import pc3 from "picocolors";
|
|
3904
3904
|
import * as p2 from "@clack/prompts";
|
|
3905
3905
|
|
|
@@ -6874,8 +6874,203 @@ function materializeRegistry(registry, resolveCredential, opts) {
|
|
|
6874
6874
|
return result;
|
|
6875
6875
|
}
|
|
6876
6876
|
|
|
6877
|
+
// src/npm-shim.ts
|
|
6878
|
+
import { readFileSync as readFileSync7, realpathSync, statSync as statSync4 } from "fs";
|
|
6879
|
+
import { dirname as dirname3, resolve as resolve2 } from "path";
|
|
6880
|
+
var MAX_LAUNCHER_BYTES = 64 * 1024;
|
|
6881
|
+
var MAX_LAUNCHER_HOPS = 4;
|
|
6882
|
+
var COMMENT_LINE = {
|
|
6883
|
+
cmd: /^[\s@]*(?:rem\b|::)/i,
|
|
6884
|
+
powershell: /^\s*#/,
|
|
6885
|
+
sh: /^\s*#/
|
|
6886
|
+
};
|
|
6887
|
+
var TARGET_PATTERN = {
|
|
6888
|
+
cmd: /"%(?:~dp0|dp0%)\\([^"]+?)"\s+%\*/g,
|
|
6889
|
+
powershell: /"\$basedir\/([^"]+?)"\s+\$args/g,
|
|
6890
|
+
sh: /"\$basedir(?:_win)?\/([^"]+?)"\s+"\$@"/g
|
|
6891
|
+
};
|
|
6892
|
+
function launcherKind(shimPath) {
|
|
6893
|
+
const lower = shimPath.toLowerCase();
|
|
6894
|
+
if (lower.endsWith(".cmd")) return "cmd";
|
|
6895
|
+
if (lower.endsWith(".ps1")) return "powershell";
|
|
6896
|
+
return "sh";
|
|
6897
|
+
}
|
|
6898
|
+
function readLauncherText(path) {
|
|
6899
|
+
try {
|
|
6900
|
+
if (statSync4(path).size > MAX_LAUNCHER_BYTES) return null;
|
|
6901
|
+
return readFileSync7(path, "utf8");
|
|
6902
|
+
} catch {
|
|
6903
|
+
return null;
|
|
6904
|
+
}
|
|
6905
|
+
}
|
|
6906
|
+
function isLiteralPath(relativeTarget) {
|
|
6907
|
+
return relativeTarget.length > 0 && !/[%$]/.test(relativeTarget);
|
|
6908
|
+
}
|
|
6909
|
+
function collectTargets(contents, kind) {
|
|
6910
|
+
const comment = COMMENT_LINE[kind];
|
|
6911
|
+
const pattern = TARGET_PATTERN[kind];
|
|
6912
|
+
const targets = [];
|
|
6913
|
+
for (const line of contents.split(/\r?\n/)) {
|
|
6914
|
+
if (comment.test(line)) continue;
|
|
6915
|
+
for (const match of line.matchAll(pattern)) targets.push(match[1]);
|
|
6916
|
+
}
|
|
6917
|
+
return targets;
|
|
6918
|
+
}
|
|
6919
|
+
function readNpmShim(shimPath) {
|
|
6920
|
+
const kind = launcherKind(shimPath);
|
|
6921
|
+
const unreadable = kind === "sh" ? { kind: "not-a-shim" } : { kind: "unreadable-launcher" };
|
|
6922
|
+
const text5 = readLauncherText(shimPath);
|
|
6923
|
+
if (text5 === null) return unreadable;
|
|
6924
|
+
const rawTargets = collectTargets(text5, kind);
|
|
6925
|
+
if (rawTargets.length === 0) return unreadable;
|
|
6926
|
+
if (!rawTargets.every(isLiteralPath)) return unreadable;
|
|
6927
|
+
const absolute = rawTargets.map((target) => resolve2(
|
|
6928
|
+
dirname3(shimPath),
|
|
6929
|
+
kind === "cmd" ? target.replace(/\\/g, "/") : target
|
|
6930
|
+
));
|
|
6931
|
+
const distinct = [...new Set(absolute)];
|
|
6932
|
+
if (distinct.length > 1) return { kind: "ambiguous-launcher", targets: distinct };
|
|
6933
|
+
return { kind: "target", target: distinct[0] };
|
|
6934
|
+
}
|
|
6935
|
+
function resolveThroughNpmShims(startPath) {
|
|
6936
|
+
let current = startPath;
|
|
6937
|
+
for (let hop = 0; hop <= MAX_LAUNCHER_HOPS; hop++) {
|
|
6938
|
+
const reading = readNpmShim(current);
|
|
6939
|
+
if (reading.kind === "not-a-shim") return { ok: true, path: current };
|
|
6940
|
+
if (reading.kind === "unreadable-launcher") {
|
|
6941
|
+
return {
|
|
6942
|
+
ok: false,
|
|
6943
|
+
shimPath: current,
|
|
6944
|
+
declaredTarget: null,
|
|
6945
|
+
detail: "it is a launcher script rather than the program itself, and clodex could not read which file it starts"
|
|
6946
|
+
};
|
|
6947
|
+
}
|
|
6948
|
+
if (reading.kind === "ambiguous-launcher") {
|
|
6949
|
+
return {
|
|
6950
|
+
ok: false,
|
|
6951
|
+
shimPath: current,
|
|
6952
|
+
declaredTarget: null,
|
|
6953
|
+
detail: `it names more than one program (${reading.targets.join(", ")}), so clodex cannot tell which one it starts`
|
|
6954
|
+
};
|
|
6955
|
+
}
|
|
6956
|
+
let hopped;
|
|
6957
|
+
try {
|
|
6958
|
+
hopped = realpathSync(reading.target);
|
|
6959
|
+
} catch {
|
|
6960
|
+
return {
|
|
6961
|
+
ok: false,
|
|
6962
|
+
shimPath: current,
|
|
6963
|
+
declaredTarget: reading.target,
|
|
6964
|
+
detail: `it starts ${reading.target}, which does not exist`
|
|
6965
|
+
};
|
|
6966
|
+
}
|
|
6967
|
+
current = hopped;
|
|
6968
|
+
}
|
|
6969
|
+
return {
|
|
6970
|
+
ok: false,
|
|
6971
|
+
shimPath: startPath,
|
|
6972
|
+
declaredTarget: null,
|
|
6973
|
+
detail: `it starts another launcher script, more than ${MAX_LAUNCHER_HOPS} deep`
|
|
6974
|
+
};
|
|
6975
|
+
}
|
|
6976
|
+
|
|
6977
|
+
// src/claude-native-placeholder.ts
|
|
6978
|
+
import { spawnSync } from "child_process";
|
|
6979
|
+
import {
|
|
6980
|
+
closeSync as closeSync2,
|
|
6981
|
+
fstatSync,
|
|
6982
|
+
openSync as openSync2,
|
|
6983
|
+
readFileSync as readFileSync8,
|
|
6984
|
+
readSync,
|
|
6985
|
+
statSync as statSync5
|
|
6986
|
+
} from "fs";
|
|
6987
|
+
import { createRequire } from "module";
|
|
6988
|
+
import { arch } from "os";
|
|
6989
|
+
import { dirname as dirname4, join as join6 } from "path";
|
|
6990
|
+
var MAX_PLACEHOLDER_BYTES = 64 * 1024;
|
|
6991
|
+
var CLAUDE_PACKAGE = "@anthropic-ai/claude-code";
|
|
6992
|
+
var MISSING_BINARY_MARKER = "claude native binary not installed";
|
|
6993
|
+
var INSTALL_SCRIPT_MARKER = "node_modules/@anthropic-ai/claude-code/install.cjs";
|
|
6994
|
+
var OMIT_OPTIONAL_MARKER = "--omit=optional";
|
|
6995
|
+
var IGNORE_SCRIPTS_MARKER = "--ignore-scripts";
|
|
6996
|
+
function detectMusl() {
|
|
6997
|
+
if (process.platform !== "linux") return false;
|
|
6998
|
+
const report = typeof process.report?.getReport === "function" ? process.report.getReport() : null;
|
|
6999
|
+
return report != null && report.header?.glibcVersionRuntime === void 0;
|
|
7000
|
+
}
|
|
7001
|
+
function getPlatformKey() {
|
|
7002
|
+
const platform = process.platform;
|
|
7003
|
+
let cpu = arch();
|
|
7004
|
+
if (platform === "android") return `linux-${cpu}-android`;
|
|
7005
|
+
if (platform === "linux") return `linux-${cpu}${detectMusl() ? "-musl" : ""}`;
|
|
7006
|
+
if (platform === "darwin" && cpu === "x64") {
|
|
7007
|
+
const translated = spawnSync("sysctl", ["-n", "sysctl.proc_translated"], {
|
|
7008
|
+
encoding: "utf8"
|
|
7009
|
+
});
|
|
7010
|
+
if (translated.stdout?.trim() === "1") cpu = "arm64";
|
|
7011
|
+
}
|
|
7012
|
+
return `${platform}-${cpu}`;
|
|
7013
|
+
}
|
|
7014
|
+
function inspectNativePackage(binaryPath) {
|
|
7015
|
+
const packageRoot = dirname4(dirname4(binaryPath));
|
|
7016
|
+
const packageJsonPath = join6(packageRoot, "package.json");
|
|
7017
|
+
const installScriptPath = join6(packageRoot, "install.cjs");
|
|
7018
|
+
let manifest;
|
|
7019
|
+
try {
|
|
7020
|
+
manifest = JSON.parse(readFileSync8(packageJsonPath, "utf8"));
|
|
7021
|
+
if (manifest.name !== CLAUDE_PACKAGE || !statSync5(installScriptPath).isFile()) {
|
|
7022
|
+
return { nativePackageState: "unknown", installScriptPath: null };
|
|
7023
|
+
}
|
|
7024
|
+
} catch {
|
|
7025
|
+
return { nativePackageState: "unknown", installScriptPath: null };
|
|
7026
|
+
}
|
|
7027
|
+
const nativePackage = `${CLAUDE_PACKAGE}-${getPlatformKey()}`;
|
|
7028
|
+
if (manifest.optionalDependencies === null || typeof manifest.optionalDependencies !== "object" || typeof manifest.optionalDependencies[nativePackage] !== "string") {
|
|
7029
|
+
return { nativePackageState: "unknown", installScriptPath };
|
|
7030
|
+
}
|
|
7031
|
+
try {
|
|
7032
|
+
createRequire(installScriptPath).resolve(`${nativePackage}/package.json`);
|
|
7033
|
+
return { nativePackageState: "present", installScriptPath };
|
|
7034
|
+
} catch {
|
|
7035
|
+
return { nativePackageState: "missing", installScriptPath };
|
|
7036
|
+
}
|
|
7037
|
+
}
|
|
7038
|
+
function inspectClaudeNativeBinaryPlaceholder(path) {
|
|
7039
|
+
let fd;
|
|
7040
|
+
try {
|
|
7041
|
+
fd = openSync2(path, "r");
|
|
7042
|
+
const size = fstatSync(fd).size;
|
|
7043
|
+
if (size <= 0 || size > MAX_PLACEHOLDER_BYTES) return null;
|
|
7044
|
+
const bytes = Buffer.allocUnsafe(size);
|
|
7045
|
+
let offset = 0;
|
|
7046
|
+
while (offset < size) {
|
|
7047
|
+
const bytesRead = readSync(fd, bytes, offset, size - offset, offset);
|
|
7048
|
+
if (bytesRead === 0) break;
|
|
7049
|
+
offset += bytesRead;
|
|
7050
|
+
}
|
|
7051
|
+
if (offset !== size) return null;
|
|
7052
|
+
const text5 = bytes.toString("utf8");
|
|
7053
|
+
const signals = [
|
|
7054
|
+
text5.includes(MISSING_BINARY_MARKER),
|
|
7055
|
+
text5.includes(INSTALL_SCRIPT_MARKER),
|
|
7056
|
+
text5.includes(OMIT_OPTIONAL_MARKER) && text5.includes(IGNORE_SCRIPTS_MARKER)
|
|
7057
|
+
];
|
|
7058
|
+
if (signals.filter(Boolean).length < 2) return null;
|
|
7059
|
+
return inspectNativePackage(path);
|
|
7060
|
+
} catch {
|
|
7061
|
+
return null;
|
|
7062
|
+
} finally {
|
|
7063
|
+
if (fd !== void 0) {
|
|
7064
|
+
try {
|
|
7065
|
+
closeSync2(fd);
|
|
7066
|
+
} catch {
|
|
7067
|
+
}
|
|
7068
|
+
}
|
|
7069
|
+
}
|
|
7070
|
+
}
|
|
7071
|
+
|
|
6877
7072
|
// src/bun-entry-module.ts
|
|
6878
|
-
import { closeSync as
|
|
7073
|
+
import { closeSync as closeSync3, openSync as openSync3, readSync as readSync2, statSync as statSync6, writeSync as writeSync2 } from "fs";
|
|
6879
7074
|
import { execFileSync } from "child_process";
|
|
6880
7075
|
var BUN_TRAILER = Buffer.from("\n---- Bun! ----\n");
|
|
6881
7076
|
var BUN_OFFSETS_BYTES = 32;
|
|
@@ -6912,7 +7107,7 @@ function entryModuleShimName(byteLength) {
|
|
|
6912
7107
|
function readAt(fd, length, position) {
|
|
6913
7108
|
if (length <= 0 || position < 0) return null;
|
|
6914
7109
|
const buffer = Buffer.alloc(length);
|
|
6915
|
-
const read =
|
|
7110
|
+
const read = readSync2(fd, buffer, 0, length, position);
|
|
6916
7111
|
return read === length ? buffer : null;
|
|
6917
7112
|
}
|
|
6918
7113
|
function readBunModuleNames(fd, fileSize) {
|
|
@@ -7052,17 +7247,17 @@ function isMachO(fd) {
|
|
|
7052
7247
|
return value === 4277009102 || value === 4277009103 || value === 3472551422 || value === 3489328638 || value === 3405691582 || value === 3405691583;
|
|
7053
7248
|
}
|
|
7054
7249
|
function readBunModuleTable(path) {
|
|
7055
|
-
const fd =
|
|
7250
|
+
const fd = openSync3(path, "r");
|
|
7056
7251
|
try {
|
|
7057
|
-
return readBunModuleNames(fd,
|
|
7252
|
+
return readBunModuleNames(fd, statSync6(path).size);
|
|
7058
7253
|
} finally {
|
|
7059
|
-
|
|
7254
|
+
closeSync3(fd);
|
|
7060
7255
|
}
|
|
7061
7256
|
}
|
|
7062
7257
|
function readBunJavaScriptModules(path) {
|
|
7063
|
-
const fd =
|
|
7258
|
+
const fd = openSync3(path, "r");
|
|
7064
7259
|
try {
|
|
7065
|
-
const parsed = readBunModuleNames(fd,
|
|
7260
|
+
const parsed = readBunModuleNames(fd, statSync6(path).size);
|
|
7066
7261
|
if (!parsed) return null;
|
|
7067
7262
|
const modules = [];
|
|
7068
7263
|
for (let index = 0; index < parsed.names.length; index++) {
|
|
@@ -7082,33 +7277,33 @@ function readBunJavaScriptModules(path) {
|
|
|
7082
7277
|
}
|
|
7083
7278
|
return modules;
|
|
7084
7279
|
} finally {
|
|
7085
|
-
|
|
7280
|
+
closeSync3(fd);
|
|
7086
7281
|
}
|
|
7087
7282
|
}
|
|
7088
7283
|
function shimEntryModuleName(path) {
|
|
7089
|
-
const fd =
|
|
7284
|
+
const fd = openSync3(path, "r+");
|
|
7090
7285
|
try {
|
|
7091
|
-
const parsed = readBunModuleNames(fd,
|
|
7286
|
+
const parsed = readBunModuleNames(fd, statSync6(path).size);
|
|
7092
7287
|
if (!parsed) return null;
|
|
7093
7288
|
if (parsed.names.some(tweakccRecognizesModuleName)) return null;
|
|
7094
7289
|
const original = parsed.names[parsed.entryPointId];
|
|
7095
7290
|
const offset = parsed.offsets[parsed.entryPointId];
|
|
7096
7291
|
const marker = entryModuleShimName(Buffer.byteLength(original));
|
|
7097
7292
|
if (marker === null) return null;
|
|
7098
|
-
if (findStandIn(fd,
|
|
7293
|
+
if (findStandIn(fd, statSync6(path).size, marker).some((offset2) => isModuleNameAt(fd, offset2, marker))) {
|
|
7099
7294
|
return null;
|
|
7100
7295
|
}
|
|
7101
7296
|
writeNameBytes(fd, marker, offset);
|
|
7102
7297
|
return { offset, original, marker };
|
|
7103
7298
|
} finally {
|
|
7104
|
-
|
|
7299
|
+
closeSync3(fd);
|
|
7105
7300
|
}
|
|
7106
7301
|
}
|
|
7107
7302
|
function restoreEntryModuleName(path, shim, { resign }) {
|
|
7108
|
-
const fd =
|
|
7303
|
+
const fd = openSync3(path, "r+");
|
|
7109
7304
|
let machO;
|
|
7110
7305
|
try {
|
|
7111
|
-
const parsed = readBunModuleNames(fd,
|
|
7306
|
+
const parsed = readBunModuleNames(fd, statSync6(path).size);
|
|
7112
7307
|
const offset = parsed?.offsets[parsed.entryPointId];
|
|
7113
7308
|
if (!parsed || offset === void 0 || parsed.names[parsed.entryPointId] !== shim.marker) {
|
|
7114
7309
|
throw new Error(
|
|
@@ -7116,20 +7311,20 @@ function restoreEntryModuleName(path, shim, { resign }) {
|
|
|
7116
7311
|
);
|
|
7117
7312
|
}
|
|
7118
7313
|
writeNameBytes(fd, shim.original, offset);
|
|
7119
|
-
restoreEveryStandIn(fd,
|
|
7314
|
+
restoreEveryStandIn(fd, statSync6(path).size, shim);
|
|
7120
7315
|
machO = resign;
|
|
7121
7316
|
} finally {
|
|
7122
|
-
|
|
7317
|
+
closeSync3(fd);
|
|
7123
7318
|
}
|
|
7124
7319
|
if (machO) resignMachOBinary(path);
|
|
7125
7320
|
}
|
|
7126
7321
|
function resignMachOBinary(path) {
|
|
7127
|
-
const fd =
|
|
7322
|
+
const fd = openSync3(path, "r");
|
|
7128
7323
|
let machO;
|
|
7129
7324
|
try {
|
|
7130
7325
|
machO = isMachO(fd);
|
|
7131
7326
|
} finally {
|
|
7132
|
-
|
|
7327
|
+
closeSync3(fd);
|
|
7133
7328
|
}
|
|
7134
7329
|
if (machO && process.platform === "darwin") {
|
|
7135
7330
|
execFileSync("codesign", ["-s", "-", "-f", path], { stdio: "ignore" });
|
|
@@ -7137,7 +7332,7 @@ function resignMachOBinary(path) {
|
|
|
7137
7332
|
}
|
|
7138
7333
|
|
|
7139
7334
|
// src/bun-compiled-pointer.ts
|
|
7140
|
-
import { closeSync as
|
|
7335
|
+
import { closeSync as closeSync4, fstatSync as fstatSync2, openSync as openSync4, readSync as readSync3, writeSync as writeSync3 } from "fs";
|
|
7141
7336
|
var TWEAKCC_SCAN_STRIDE = 16384n;
|
|
7142
7337
|
var SCAN_CHUNK = 1 << 20;
|
|
7143
7338
|
var ELF_MAGIC = 1179403647;
|
|
@@ -7149,7 +7344,7 @@ function readAt2(fd, length, position) {
|
|
|
7149
7344
|
const buf = Buffer.alloc(length);
|
|
7150
7345
|
let read = 0;
|
|
7151
7346
|
while (read < length) {
|
|
7152
|
-
const n =
|
|
7347
|
+
const n = readSync3(fd, buf, read, length - read, position + read);
|
|
7153
7348
|
if (n <= 0) break;
|
|
7154
7349
|
read += n;
|
|
7155
7350
|
}
|
|
@@ -7169,7 +7364,7 @@ function readElfLayout(fd) {
|
|
|
7169
7364
|
const shstrndx = ident.readUInt16LE(62);
|
|
7170
7365
|
if (shnum === 0 || phnum === 65535) return null;
|
|
7171
7366
|
if (shstrndx >= shnum || shentsize < 64 || phentsize < 56) return null;
|
|
7172
|
-
const fileSize =
|
|
7367
|
+
const fileSize = fstatSync2(fd).size;
|
|
7173
7368
|
const fits = (offset, length) => Number.isSafeInteger(offset) && offset >= 0 && length >= 0 && offset + length <= fileSize;
|
|
7174
7369
|
if (!fits(Number(shoff), shnum * shentsize)) return null;
|
|
7175
7370
|
const shTable = readAt2(fd, shnum * shentsize, Number(shoff));
|
|
@@ -7258,7 +7453,7 @@ function scanForNeedle(fd, from, to, needle, skipFrom, skipTo) {
|
|
|
7258
7453
|
return hits;
|
|
7259
7454
|
}
|
|
7260
7455
|
function shimBunCompiledPointer(path) {
|
|
7261
|
-
const fd =
|
|
7456
|
+
const fd = openSync4(path, "r+");
|
|
7262
7457
|
try {
|
|
7263
7458
|
const layout = readElfLayout(fd);
|
|
7264
7459
|
if (!layout) return null;
|
|
@@ -7308,11 +7503,11 @@ function shimBunCompiledPointer(path) {
|
|
|
7308
7503
|
writeSync3(fd, needle, 0, 8, standInOffset);
|
|
7309
7504
|
return { pointerVaddr, standInVaddr, displaced, bunVaddr: bun.addr };
|
|
7310
7505
|
} finally {
|
|
7311
|
-
|
|
7506
|
+
closeSync4(fd);
|
|
7312
7507
|
}
|
|
7313
7508
|
}
|
|
7314
7509
|
function restoreBunCompiledPointer(path, shim) {
|
|
7315
|
-
const fd =
|
|
7510
|
+
const fd = openSync4(path, "r+");
|
|
7316
7511
|
try {
|
|
7317
7512
|
const layout = readElfLayout(fd);
|
|
7318
7513
|
if (!layout) throw new Error("the repacked binary is no longer a 64-bit little-endian ELF");
|
|
@@ -7349,12 +7544,12 @@ function restoreBunCompiledPointer(path, shim) {
|
|
|
7349
7544
|
throw new Error("the bytes the stand-in displaced were not restored");
|
|
7350
7545
|
}
|
|
7351
7546
|
} finally {
|
|
7352
|
-
|
|
7547
|
+
closeSync4(fd);
|
|
7353
7548
|
}
|
|
7354
7549
|
}
|
|
7355
7550
|
|
|
7356
7551
|
// src/bun-bundle.ts
|
|
7357
|
-
import { closeSync as
|
|
7552
|
+
import { closeSync as closeSync5, openSync as openSync5, readSync as readSync4, writeSync as writeSync4 } from "fs";
|
|
7358
7553
|
function writableModuleIndex(path) {
|
|
7359
7554
|
const table = readBunModuleTable(path);
|
|
7360
7555
|
if (!table) return null;
|
|
@@ -7470,18 +7665,18 @@ function placeholderOf(byteLength) {
|
|
|
7470
7665
|
return PLACEHOLDER_TEXT.repeat(Math.ceil(byteLength / PLACEHOLDER_TEXT.length)).slice(0, byteLength);
|
|
7471
7666
|
}
|
|
7472
7667
|
function readBlobData(path, table, into) {
|
|
7473
|
-
const fd =
|
|
7668
|
+
const fd = openSync5(path, "r");
|
|
7474
7669
|
try {
|
|
7475
7670
|
let read = 0;
|
|
7476
7671
|
while (read < table.byteCount) {
|
|
7477
|
-
const got =
|
|
7672
|
+
const got = readSync4(fd, into, read, table.byteCount - read, table.blobAt + read);
|
|
7478
7673
|
if (got <= 0) {
|
|
7479
7674
|
throw new Error(`read ${read} of the ${table.byteCount} blob bytes of ${path}`);
|
|
7480
7675
|
}
|
|
7481
7676
|
read += got;
|
|
7482
7677
|
}
|
|
7483
7678
|
} finally {
|
|
7484
|
-
|
|
7679
|
+
closeSync5(fd);
|
|
7485
7680
|
}
|
|
7486
7681
|
}
|
|
7487
7682
|
function repointModule(data, table, append) {
|
|
@@ -7533,7 +7728,7 @@ function applyBundleWritePlan(path, plan) {
|
|
|
7533
7728
|
}
|
|
7534
7729
|
const offsets = Buffer.from(plan.offsets);
|
|
7535
7730
|
offsets.writeBigUInt64LE(BigInt(byteCount), 0);
|
|
7536
|
-
const fd =
|
|
7731
|
+
const fd = openSync5(path, "r+");
|
|
7537
7732
|
try {
|
|
7538
7733
|
writeAll(fd, plan.data, repacked.blobAt, path);
|
|
7539
7734
|
const padding = byteCount - plan.data.length;
|
|
@@ -7541,7 +7736,7 @@ function applyBundleWritePlan(path, plan) {
|
|
|
7541
7736
|
writeAll(fd, offsets, repacked.blobAt + byteCount, path);
|
|
7542
7737
|
writeAll(fd, BUN_TRAILER2, repacked.blobAt + byteCount + BUN_OFFSETS_BYTES2, path);
|
|
7543
7738
|
} finally {
|
|
7544
|
-
|
|
7739
|
+
closeSync5(fd);
|
|
7545
7740
|
}
|
|
7546
7741
|
const published = readBunModuleTable(path);
|
|
7547
7742
|
if (!published) throw new Error(`cannot re-read the Bun module table of ${path} after publishing its blob`);
|
|
@@ -7577,15 +7772,15 @@ function writeAll(fd, bytes, position, path) {
|
|
|
7577
7772
|
|
|
7578
7773
|
// src/patch-backup.ts
|
|
7579
7774
|
import { createHash as createHash5 } from "crypto";
|
|
7580
|
-
import { existsSync as existsSync4, readFileSync as
|
|
7775
|
+
import { existsSync as existsSync4, readFileSync as readFileSync9, readdirSync, statSync as statSync7 } from "fs";
|
|
7581
7776
|
import { homedir as homedir2 } from "os";
|
|
7582
|
-
import { join as
|
|
7777
|
+
import { join as join7 } from "path";
|
|
7583
7778
|
var BACKUP_SHA_PREFIX_LENGTH = 16;
|
|
7584
7779
|
function backupDir() {
|
|
7585
|
-
return process.env["TWEAKCC_CONFIG_DIR"]?.trim() ||
|
|
7780
|
+
return process.env["TWEAKCC_CONFIG_DIR"]?.trim() || join7(homedir2(), ".tweakcc");
|
|
7586
7781
|
}
|
|
7587
7782
|
function sha256File(path) {
|
|
7588
|
-
return createHash5("sha256").update(
|
|
7783
|
+
return createHash5("sha256").update(readFileSync9(path)).digest("hex");
|
|
7589
7784
|
}
|
|
7590
7785
|
function backupVersionTag(version) {
|
|
7591
7786
|
const tag = version.trim().replace(/[^\w.-]+/g, "_");
|
|
@@ -7593,10 +7788,10 @@ function backupVersionTag(version) {
|
|
|
7593
7788
|
return tag;
|
|
7594
7789
|
}
|
|
7595
7790
|
function contentAddressedBackupPath(version, sha256, dir = backupDir()) {
|
|
7596
|
-
return
|
|
7791
|
+
return join7(dir, `claude-${backupVersionTag(version)}-${sha256.slice(0, BACKUP_SHA_PREFIX_LENGTH)}.orig`);
|
|
7597
7792
|
}
|
|
7598
7793
|
function tweakccMirrorBackupPath(dir = backupDir()) {
|
|
7599
|
-
return
|
|
7794
|
+
return join7(dir, "native-binary.backup");
|
|
7600
7795
|
}
|
|
7601
7796
|
function scanPristineBackups(version, dir = backupDir()) {
|
|
7602
7797
|
const tag = backupVersionTag(version);
|
|
@@ -7612,10 +7807,10 @@ function scanPristineBackups(version, dir = backupDir()) {
|
|
|
7612
7807
|
for (const entry of entries.sort()) {
|
|
7613
7808
|
const match = pattern.exec(entry);
|
|
7614
7809
|
if (!match) continue;
|
|
7615
|
-
const path =
|
|
7810
|
+
const path = join7(dir, entry);
|
|
7616
7811
|
let sha256;
|
|
7617
7812
|
try {
|
|
7618
|
-
if (!
|
|
7813
|
+
if (!statSync7(path).isFile()) continue;
|
|
7619
7814
|
sha256 = sha256File(path);
|
|
7620
7815
|
} catch {
|
|
7621
7816
|
corrupt.push(path);
|
|
@@ -7653,25 +7848,48 @@ function noBackupMessage(facts) {
|
|
|
7653
7848
|
const corrupt = facts.corruptBackups?.length ? ` (${facts.corruptBackups.length} backup file(s) for this version failed integrity checks and were ignored)` : "";
|
|
7654
7849
|
return `claude ${facts.version} is already patched and no trustworthy pristine backup for that version exists in ${backupDir()}${corrupt}. Reinstall Claude Code to get a pristine binary, then run \`clodex patch\`.`;
|
|
7655
7850
|
}
|
|
7851
|
+
function identifiesABackup(manifest) {
|
|
7852
|
+
return manifest.pristineSha256 !== void 0 || manifest.backupPath !== void 0;
|
|
7853
|
+
}
|
|
7854
|
+
function recordedBackupGoneMessage(facts, manifest) {
|
|
7855
|
+
const named = manifest.backupPath ?? `the backup holding sha256 ${manifest.pristineSha256}`;
|
|
7856
|
+
const corrupt = facts.corruptBackups?.length ? ` (${facts.corruptBackups.length} backup file(s) for this version failed integrity checks and were ignored)` : "";
|
|
7857
|
+
const others = facts.backups.length ? `The ${facts.backups.length} other pristine backup(s) tagged claude ${facts.version} there were made for some other install \u2014 two installs of one Claude Code version are different files, so restoring one of them would overwrite this install with bytes that were never its own. ` : "";
|
|
7858
|
+
return `The patch manifest records ${named} as the pristine content of ${facts.binaryPath}, and clodex cannot use it: it is missing from ${backupDir()}, failed its integrity check, or holds a different claude version${corrupt}. ${others}Reinstall Claude Code to get a pristine binary, then run \`clodex patch\`.`;
|
|
7859
|
+
}
|
|
7860
|
+
function otherInstallMessage(facts, otherBinaryPath) {
|
|
7861
|
+
return `The patch manifest records a different Claude Code install (${otherBinaryPath}), so nothing establishes that a pristine backup tagged claude ${facts.version} in ${backupDir()} belongs to ${facts.binaryPath}. Two installs of one Claude Code version are different files, so restoring by version tag alone would overwrite this install with another one's bytes. Set TWEAKCC_CC_INSTALLATION_PATH=${otherBinaryPath} to restore that install instead, or reinstall Claude Code to make this one pristine.`;
|
|
7862
|
+
}
|
|
7656
7863
|
function selectRestoreSource(facts) {
|
|
7657
7864
|
const notes = [];
|
|
7658
|
-
const
|
|
7865
|
+
const recorded = facts.manifest;
|
|
7866
|
+
const speaksForThisVersion = !recorded?.claudeVersion || recorded.claudeVersion === facts.version;
|
|
7867
|
+
const manifest = recorded && recorded.binaryPath === facts.binaryPath && speaksForThisVersion ? recorded : null;
|
|
7868
|
+
const other = recorded && recorded.binaryPath !== facts.binaryPath && speaksForThisVersion ? recorded : null;
|
|
7659
7869
|
let chosen = manifest?.pristineSha256 ? facts.backups.find((backup) => backup.sha256 === manifest.pristineSha256) : void 0;
|
|
7660
7870
|
if (!chosen && manifest?.backupPath) {
|
|
7661
7871
|
chosen = facts.backups.find((backup) => backup.path === manifest.backupPath);
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
}
|
|
7872
|
+
}
|
|
7873
|
+
if (!chosen && manifest && identifiesABackup(manifest)) {
|
|
7874
|
+
return { action: "error", message: recordedBackupGoneMessage(facts, manifest) };
|
|
7665
7875
|
}
|
|
7666
7876
|
if (!chosen) {
|
|
7877
|
+
if (other) {
|
|
7878
|
+
return facts.backups.length ? { action: "error", message: otherInstallMessage(facts, other.binaryPath) } : { action: "error", message: noBackupMessage(facts) };
|
|
7879
|
+
}
|
|
7667
7880
|
const distinct = [...new Set(facts.backups.map((backup) => backup.sha256))];
|
|
7668
7881
|
if (distinct.length > 1) {
|
|
7669
7882
|
return {
|
|
7670
7883
|
action: "error",
|
|
7671
|
-
message: `Found conflicting pristine backups for claude ${facts.version}: ${facts.backups.map((backup) => backup.path).join(", ")}. They do not hold the same bytes, so clodex cannot tell which one is pristine.
|
|
7884
|
+
message: `Found conflicting pristine backups for claude ${facts.version}: ${facts.backups.map((backup) => backup.path).join(", ")}. They do not hold the same bytes, so clodex cannot tell which one is pristine. If this machine has more than one Claude Code install, both are probably genuine \u2014 one per install \u2014 and deleting either one is a guess. Reinstall the Claude Code at ${facts.binaryPath} instead: a pristine install needs no backup, and \`clodex patch\` will record its own.`
|
|
7672
7885
|
};
|
|
7673
7886
|
}
|
|
7674
7887
|
chosen = facts.backups.find((backup) => backup.kind === "content-addressed") ?? facts.backups[0];
|
|
7888
|
+
if (chosen) {
|
|
7889
|
+
notes.push(
|
|
7890
|
+
`No patch manifest records ${facts.binaryPath}, so ${chosen.path} is being used as its pristine content on the strength of its claude ${facts.version} version tag alone. On a machine with more than one Claude Code install those bytes may belong to the other one \u2014 a clodex that had recorded this install would have refused rather than guess.`
|
|
7891
|
+
);
|
|
7892
|
+
}
|
|
7675
7893
|
}
|
|
7676
7894
|
if (!chosen) return { action: "error", message: noBackupMessage(facts) };
|
|
7677
7895
|
return {
|
|
@@ -8443,7 +8661,7 @@ var WsUpgradePacer = class {
|
|
|
8443
8661
|
* catch that, because an untested guard is not a guarantee.
|
|
8444
8662
|
*/
|
|
8445
8663
|
sleep(ms, signal) {
|
|
8446
|
-
return new Promise((
|
|
8664
|
+
return new Promise((resolve4, reject) => {
|
|
8447
8665
|
let settled = false;
|
|
8448
8666
|
let cancelTimer;
|
|
8449
8667
|
const onAbort = () => {
|
|
@@ -8456,7 +8674,7 @@ var WsUpgradePacer = class {
|
|
|
8456
8674
|
if (settled) return;
|
|
8457
8675
|
settled = true;
|
|
8458
8676
|
signal?.removeEventListener("abort", onAbort);
|
|
8459
|
-
|
|
8677
|
+
resolve4();
|
|
8460
8678
|
};
|
|
8461
8679
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
8462
8680
|
cancelTimer = this.schedule(ms, fire);
|
|
@@ -11043,7 +11261,7 @@ function thinkingProviderOptions(npm) {
|
|
|
11043
11261
|
|
|
11044
11262
|
// src/proxy.ts
|
|
11045
11263
|
import { createServer } from "http";
|
|
11046
|
-
import { appendFileSync as appendFileSync2, openSync as
|
|
11264
|
+
import { appendFileSync as appendFileSync2, openSync as openSync6, writeSync as writeSync5, closeSync as closeSync6 } from "fs";
|
|
11047
11265
|
|
|
11048
11266
|
// src/http-utils.ts
|
|
11049
11267
|
import * as zlib from "zlib";
|
|
@@ -11068,7 +11286,7 @@ function decodeRequestBody(raw, encoding) {
|
|
|
11068
11286
|
}
|
|
11069
11287
|
}
|
|
11070
11288
|
function readBody(req) {
|
|
11071
|
-
return new Promise((
|
|
11289
|
+
return new Promise((resolve4, reject) => {
|
|
11072
11290
|
const chunks = [];
|
|
11073
11291
|
let totalSize = 0;
|
|
11074
11292
|
req.on("data", (c) => {
|
|
@@ -11082,7 +11300,7 @@ function readBody(req) {
|
|
|
11082
11300
|
});
|
|
11083
11301
|
req.on("end", () => {
|
|
11084
11302
|
try {
|
|
11085
|
-
|
|
11303
|
+
resolve4(decodeRequestBody(Buffer.concat(chunks), req.headers["content-encoding"]));
|
|
11086
11304
|
} catch (err) {
|
|
11087
11305
|
reject(err);
|
|
11088
11306
|
}
|
|
@@ -11607,6 +11825,129 @@ function resolveUpstreamTools(tools, messages) {
|
|
|
11607
11825
|
return upstream;
|
|
11608
11826
|
}
|
|
11609
11827
|
|
|
11828
|
+
// src/tool-schema-sanitize.ts
|
|
11829
|
+
function isCompatiblePattern(pattern) {
|
|
11830
|
+
let inClass = false;
|
|
11831
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
11832
|
+
const ch = pattern[i];
|
|
11833
|
+
if (ch === "\\") {
|
|
11834
|
+
const next = pattern[i + 1];
|
|
11835
|
+
if ((next === "p" || next === "P" || next === "u" || next === "x") && pattern[i + 2] === "{") return false;
|
|
11836
|
+
if (next === "k" && pattern[i + 2] === "<") return false;
|
|
11837
|
+
i++;
|
|
11838
|
+
continue;
|
|
11839
|
+
}
|
|
11840
|
+
if (inClass) {
|
|
11841
|
+
if (ch === "]") inClass = false;
|
|
11842
|
+
continue;
|
|
11843
|
+
}
|
|
11844
|
+
if (ch === "[") {
|
|
11845
|
+
inClass = true;
|
|
11846
|
+
continue;
|
|
11847
|
+
}
|
|
11848
|
+
if (ch === "(" && pattern[i + 1] === "?" && pattern[i + 2] === "<" && pattern[i + 3] !== "=" && pattern[i + 3] !== "!") return false;
|
|
11849
|
+
}
|
|
11850
|
+
return true;
|
|
11851
|
+
}
|
|
11852
|
+
var SUBSCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
11853
|
+
"items",
|
|
11854
|
+
"prefixItems",
|
|
11855
|
+
"additionalItems",
|
|
11856
|
+
"unevaluatedItems",
|
|
11857
|
+
"additionalProperties",
|
|
11858
|
+
"unevaluatedProperties",
|
|
11859
|
+
"propertyNames",
|
|
11860
|
+
"contains",
|
|
11861
|
+
"anyOf",
|
|
11862
|
+
"oneOf",
|
|
11863
|
+
"allOf",
|
|
11864
|
+
"not",
|
|
11865
|
+
"if",
|
|
11866
|
+
"then",
|
|
11867
|
+
"else",
|
|
11868
|
+
"contentSchema"
|
|
11869
|
+
]);
|
|
11870
|
+
var SUBSCHEMA_MAP_KEYWORDS = /* @__PURE__ */ new Set([
|
|
11871
|
+
"properties",
|
|
11872
|
+
"$defs",
|
|
11873
|
+
"definitions",
|
|
11874
|
+
"dependentSchemas",
|
|
11875
|
+
"dependencies"
|
|
11876
|
+
]);
|
|
11877
|
+
function sanitizeToolSchema(schema) {
|
|
11878
|
+
return sanitizeSchema(schema);
|
|
11879
|
+
}
|
|
11880
|
+
function sanitizeSchema(node) {
|
|
11881
|
+
if (Array.isArray(node)) {
|
|
11882
|
+
let changed2 = false;
|
|
11883
|
+
const out = node.map((entry) => {
|
|
11884
|
+
const next = sanitizeSchema(entry);
|
|
11885
|
+
changed2 ||= next !== entry;
|
|
11886
|
+
return next;
|
|
11887
|
+
});
|
|
11888
|
+
return changed2 ? out : node;
|
|
11889
|
+
}
|
|
11890
|
+
if (!node || typeof node !== "object") return node;
|
|
11891
|
+
const record = node;
|
|
11892
|
+
const patternProps = "patternProperties" in record ? sanitizePatternProperties(record.patternProperties) : void 0;
|
|
11893
|
+
const openClosure = patternProps?.dropped === true;
|
|
11894
|
+
let changed = false;
|
|
11895
|
+
const entries = [];
|
|
11896
|
+
for (const [key, value] of Object.entries(record)) {
|
|
11897
|
+
if (key === "patternProperties" && patternProps) {
|
|
11898
|
+
changed ||= patternProps.value !== value;
|
|
11899
|
+
entries.push([key, patternProps.value]);
|
|
11900
|
+
continue;
|
|
11901
|
+
}
|
|
11902
|
+
if (openClosure && value !== true && (key === "additionalProperties" || key === "unevaluatedProperties")) {
|
|
11903
|
+
changed = true;
|
|
11904
|
+
continue;
|
|
11905
|
+
}
|
|
11906
|
+
if (key === "pattern") {
|
|
11907
|
+
if (typeof value === "string" && !isCompatiblePattern(value)) {
|
|
11908
|
+
changed = true;
|
|
11909
|
+
continue;
|
|
11910
|
+
}
|
|
11911
|
+
entries.push([key, value]);
|
|
11912
|
+
continue;
|
|
11913
|
+
}
|
|
11914
|
+
let next = value;
|
|
11915
|
+
if (SUBSCHEMA_KEYWORDS.has(key)) next = sanitizeSchema(value);
|
|
11916
|
+
else if (SUBSCHEMA_MAP_KEYWORDS.has(key)) next = sanitizeSchemaMap(value);
|
|
11917
|
+
changed ||= next !== value;
|
|
11918
|
+
entries.push([key, next]);
|
|
11919
|
+
}
|
|
11920
|
+
return changed ? Object.fromEntries(entries) : node;
|
|
11921
|
+
}
|
|
11922
|
+
function sanitizeSchemaMap(node) {
|
|
11923
|
+
if (!node || typeof node !== "object" || Array.isArray(node)) return node;
|
|
11924
|
+
let changed = false;
|
|
11925
|
+
const entries = [];
|
|
11926
|
+
for (const [key, value] of Object.entries(node)) {
|
|
11927
|
+
const next = sanitizeSchema(value);
|
|
11928
|
+
changed ||= next !== value;
|
|
11929
|
+
entries.push([key, next]);
|
|
11930
|
+
}
|
|
11931
|
+
return changed ? Object.fromEntries(entries) : node;
|
|
11932
|
+
}
|
|
11933
|
+
function sanitizePatternProperties(node) {
|
|
11934
|
+
if (!node || typeof node !== "object" || Array.isArray(node)) return { value: node, dropped: false };
|
|
11935
|
+
let changed = false;
|
|
11936
|
+
let dropped = false;
|
|
11937
|
+
const entries = [];
|
|
11938
|
+
for (const [key, value] of Object.entries(node)) {
|
|
11939
|
+
if (!isCompatiblePattern(key)) {
|
|
11940
|
+
changed = true;
|
|
11941
|
+
dropped = true;
|
|
11942
|
+
continue;
|
|
11943
|
+
}
|
|
11944
|
+
const next = sanitizeSchema(value);
|
|
11945
|
+
changed ||= next !== value;
|
|
11946
|
+
entries.push([key, next]);
|
|
11947
|
+
}
|
|
11948
|
+
return { value: changed ? Object.fromEntries(entries) : node, dropped };
|
|
11949
|
+
}
|
|
11950
|
+
|
|
11610
11951
|
// src/upstream-attempts.ts
|
|
11611
11952
|
import { APICallError as APICallError2, RetryError as RetryError2, wrapLanguageModel as wrapLanguageModel2 } from "ai";
|
|
11612
11953
|
function restoreSyntheticRetryAfterHeader(error) {
|
|
@@ -11992,12 +12333,13 @@ function toolRequiredProps(tools) {
|
|
|
11992
12333
|
}
|
|
11993
12334
|
function translateTools(anthropicTools, npm) {
|
|
11994
12335
|
if (!anthropicTools?.length) return void 0;
|
|
12336
|
+
const anthropicFormat = npm === "@ai-sdk/anthropic" || npm === VERTEX_ANTHROPIC_NPM;
|
|
11995
12337
|
const tools = {};
|
|
11996
12338
|
for (const t of anthropicTools) {
|
|
11997
12339
|
if (!t.name || !t.input_schema) continue;
|
|
11998
12340
|
tools[t.name] = tool({
|
|
11999
12341
|
description: t.description ?? "",
|
|
12000
|
-
inputSchema: jsonSchema(t.input_schema),
|
|
12342
|
+
inputSchema: jsonSchema(anthropicFormat ? t.input_schema : sanitizeToolSchema(t.input_schema)),
|
|
12001
12343
|
strict: npm === "@ai-sdk/openai" ? false : void 0
|
|
12002
12344
|
});
|
|
12003
12345
|
}
|
|
@@ -12705,12 +13047,12 @@ function createTranslationLifecycle(logPath, requestId, claudeSessionId, modelId
|
|
|
12705
13047
|
function appendSecureLog(logPath, line) {
|
|
12706
13048
|
const redacted = redactTraceLine(line);
|
|
12707
13049
|
try {
|
|
12708
|
-
const fd =
|
|
13050
|
+
const fd = openSync6(logPath, "a", 384);
|
|
12709
13051
|
try {
|
|
12710
13052
|
writeSync5(fd, `${(/* @__PURE__ */ new Date()).toISOString()} ${redacted}
|
|
12711
13053
|
`);
|
|
12712
13054
|
} finally {
|
|
12713
|
-
|
|
13055
|
+
closeSync6(fd);
|
|
12714
13056
|
}
|
|
12715
13057
|
} catch {
|
|
12716
13058
|
try {
|
|
@@ -13394,14 +13736,14 @@ function buildHttpProxyRoutes(providers, favorites, modelAliases = void 0, max =
|
|
|
13394
13736
|
|
|
13395
13737
|
// src/patcher.ts
|
|
13396
13738
|
function getPatchManifestPath() {
|
|
13397
|
-
return
|
|
13739
|
+
return join8(getAppHome(), "patch-state.json");
|
|
13398
13740
|
}
|
|
13399
13741
|
function getPatchLockPath() {
|
|
13400
|
-
return
|
|
13742
|
+
return join8(getAppHome(), "patch.lock");
|
|
13401
13743
|
}
|
|
13402
13744
|
function readPatchManifest(path = getPatchManifestPath()) {
|
|
13403
13745
|
try {
|
|
13404
|
-
const parsed = JSON.parse(
|
|
13746
|
+
const parsed = JSON.parse(readFileSync10(path, "utf8"));
|
|
13405
13747
|
if (parsed && typeof parsed.binaryPath === "string" && typeof parsed.configHash === "string") {
|
|
13406
13748
|
return parsed;
|
|
13407
13749
|
}
|
|
@@ -13564,13 +13906,13 @@ function pidIsAlive(pid) {
|
|
|
13564
13906
|
function tryAcquirePatchLock(lockPath = getPatchLockPath(), opts = {}) {
|
|
13565
13907
|
const now = opts.now ?? Date.now();
|
|
13566
13908
|
const isAlive = opts.isAlive ?? pidIsAlive;
|
|
13567
|
-
mkdirSync5(
|
|
13909
|
+
mkdirSync5(join8(lockPath, ".."), { recursive: true, mode: 448 });
|
|
13568
13910
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
13569
13911
|
try {
|
|
13570
|
-
const fd =
|
|
13912
|
+
const fd = openSync7(lockPath, "wx");
|
|
13571
13913
|
const content = { pid: process.pid, startedAt: now };
|
|
13572
13914
|
writeFileSync5(fd, JSON.stringify(content));
|
|
13573
|
-
|
|
13915
|
+
closeSync7(fd);
|
|
13574
13916
|
return () => {
|
|
13575
13917
|
try {
|
|
13576
13918
|
unlinkSync3(lockPath);
|
|
@@ -13580,7 +13922,7 @@ function tryAcquirePatchLock(lockPath = getPatchLockPath(), opts = {}) {
|
|
|
13580
13922
|
} catch {
|
|
13581
13923
|
let stale = false;
|
|
13582
13924
|
try {
|
|
13583
|
-
const existing = JSON.parse(
|
|
13925
|
+
const existing = JSON.parse(readFileSync10(lockPath, "utf8"));
|
|
13584
13926
|
stale = !existing.pid || !isAlive(existing.pid) || typeof existing.startedAt === "number" && now - existing.startedAt > PATCH_LOCK_STALE_MS;
|
|
13585
13927
|
} catch {
|
|
13586
13928
|
stale = true;
|
|
@@ -13596,25 +13938,59 @@ function tryAcquirePatchLock(lockPath = getPatchLockPath(), opts = {}) {
|
|
|
13596
13938
|
}
|
|
13597
13939
|
function resolveClaudeBinaryForPatch() {
|
|
13598
13940
|
const envOverride = process.env["TWEAKCC_CC_INSTALLATION_PATH"];
|
|
13599
|
-
const nativeSymlink =
|
|
13941
|
+
const nativeSymlink = join8(homedir3(), ".local", "bin", "claude");
|
|
13600
13942
|
const source = envOverride?.trim() || (existsSync5(nativeSymlink) ? nativeSymlink : null) || findClaudeBinary();
|
|
13601
13943
|
if (!source) return { ok: false, reason: "binary-not-found" };
|
|
13602
13944
|
let resolved;
|
|
13603
13945
|
try {
|
|
13604
|
-
resolved =
|
|
13946
|
+
resolved = realpathSync2(source);
|
|
13605
13947
|
} catch {
|
|
13606
13948
|
return { ok: false, reason: "binary-not-found" };
|
|
13607
13949
|
}
|
|
13950
|
+
const followed = resolveThroughNpmShims(resolved);
|
|
13951
|
+
if (!followed.ok) {
|
|
13952
|
+
return {
|
|
13953
|
+
ok: false,
|
|
13954
|
+
reason: "launcher-unresolved",
|
|
13955
|
+
binaryPath: followed.declaredTarget ?? followed.shimPath,
|
|
13956
|
+
shimPath: followed.shimPath,
|
|
13957
|
+
declaredTarget: followed.declaredTarget,
|
|
13958
|
+
detail: followed.detail
|
|
13959
|
+
};
|
|
13960
|
+
}
|
|
13961
|
+
resolved = followed.path;
|
|
13608
13962
|
try {
|
|
13609
|
-
if (!
|
|
13963
|
+
if (!statSync8(resolved).isFile()) return { ok: false, reason: "binary-not-found" };
|
|
13610
13964
|
} catch {
|
|
13611
13965
|
return { ok: false, reason: "binary-not-found" };
|
|
13612
13966
|
}
|
|
13967
|
+
const placeholder = inspectClaudeNativeBinaryPlaceholder(resolved);
|
|
13968
|
+
if (placeholder) {
|
|
13969
|
+
return {
|
|
13970
|
+
ok: false,
|
|
13971
|
+
reason: "native-binary-missing",
|
|
13972
|
+
binaryPath: resolved,
|
|
13973
|
+
...placeholder
|
|
13974
|
+
};
|
|
13975
|
+
}
|
|
13613
13976
|
const version = getClaudeVersionForBinary(resolved);
|
|
13614
13977
|
if (!version) return { ok: false, reason: "version-unknown", binaryPath: resolved };
|
|
13615
13978
|
return { ok: true, binaryPath: resolved, version };
|
|
13616
13979
|
}
|
|
13617
|
-
function
|
|
13980
|
+
function installScriptCommand(path) {
|
|
13981
|
+
return path === null ? "`node node_modules/@anthropic-ai/claude-code/install.cjs` (adjust the path for a local or global install)" : `\`node "${path}"\``;
|
|
13982
|
+
}
|
|
13983
|
+
function describePatchTargetFailure(target, command = "patch") {
|
|
13984
|
+
if (target.reason === "launcher-unresolved") {
|
|
13985
|
+
return `${target.shimPath} starts Claude Code but is not Claude Code itself, and clodex could not follow it: ${target.detail}. clodex will not patch a launcher script \u2014 that fails with "Unable to detect installation type". Set CLODEX_CLAUDE_PATH to the Claude Code program itself (for an npm install on Windows that is node_modules\\@anthropic-ai\\claude-code\\bin\\claude.exe under the directory holding the launcher), then run the command again.`;
|
|
13986
|
+
}
|
|
13987
|
+
if (target.reason === "native-binary-missing") {
|
|
13988
|
+
const installer = installScriptCommand(target.installScriptPath);
|
|
13989
|
+
const remedy = target.nativePackageState === "present" ? `The platform-native package is installed, so run ${installer} to finish the installation.` : target.nativePackageState === "missing" ? "The platform-native optional package is missing, so `install.cjs` cannot repair this state. Reinstall Claude Code without `--ignore-scripts` / `--omit=optional`." : `clodex could not determine whether the platform-native package is installed. If it is, run ${installer}; otherwise reinstall Claude Code without \`--ignore-scripts\` / \`--omit=optional\`.`;
|
|
13990
|
+
const retry = command === "restore" ? "Then run `clodex patch --restore` again." : command === "launch" ? "Then run the command again." : "Then run `clodex patch` again.";
|
|
13991
|
+
const restore = command === "restore" ? ` If you need to restore by hand, pristine backups are in ${backupDir()}.` : "";
|
|
13992
|
+
return `${target.binaryPath} is Claude Code's npm placeholder, not its native binary, so the npm install is incomplete. ${remedy} ${retry}${restore} If this is a custom wrapper rather than the npm placeholder, set TWEAKCC_CC_INSTALLATION_PATH to the native Claude Code binary.`;
|
|
13993
|
+
}
|
|
13618
13994
|
return target.reason === "binary-not-found" ? "claude binary not found. Install Claude Code or set TWEAKCC_CC_INSTALLATION_PATH." : `Could not determine the version of ${target.binaryPath} (\`claude --version\` failed). clodex will not patch a binary whose version it cannot read, because the version selects the pristine backup it patches from. If a previous patch left the install broken, \`clodex patch --restore\` still works \u2014 it reads the version from the patch manifest.`;
|
|
13619
13995
|
}
|
|
13620
13996
|
function summarizePatchResults(results) {
|
|
@@ -13711,8 +14087,8 @@ async function applyPatch(binaryPath, version, desired, configHash, opts) {
|
|
|
13711
14087
|
try {
|
|
13712
14088
|
mkdirSync5(backupDir(), { recursive: true });
|
|
13713
14089
|
const { tryDetectInstallation, readContent, writeContent } = await import("tweakcc");
|
|
13714
|
-
candidateDir = mkdtempSync(
|
|
13715
|
-
const candidatePath =
|
|
14090
|
+
candidateDir = mkdtempSync(join8(dirname5(binaryPath), ".clodex-patch-"));
|
|
14091
|
+
const candidatePath = join8(candidateDir, basename(binaryPath));
|
|
13716
14092
|
const seedCandidate = async (from) => {
|
|
13717
14093
|
copyFileSync(from, candidatePath);
|
|
13718
14094
|
const shim = shimEntryModuleName(candidatePath);
|
|
@@ -13842,7 +14218,7 @@ async function applyPatch(binaryPath, version, desired, configHash, opts) {
|
|
|
13842
14218
|
}
|
|
13843
14219
|
if (writeShim) restoreEntryModuleName(candidatePath, writeShim, { resign: true });
|
|
13844
14220
|
else if (publishedBlob) resignMachOBinary(candidatePath);
|
|
13845
|
-
patchedSize =
|
|
14221
|
+
patchedSize = statSync8(candidatePath).size;
|
|
13846
14222
|
patchedSha256 = sha256File(candidatePath);
|
|
13847
14223
|
renameSync2(candidatePath, binaryPath);
|
|
13848
14224
|
} catch (err) {
|
|
@@ -13895,8 +14271,12 @@ async function applyPatch(binaryPath, version, desired, configHash, opts) {
|
|
|
13895
14271
|
};
|
|
13896
14272
|
}
|
|
13897
14273
|
function runRestoreCommand(target) {
|
|
13898
|
-
if (!target.ok && target.reason === "binary-not-found") {
|
|
13899
|
-
p2.log.error(describePatchTargetFailure(target));
|
|
14274
|
+
if (!target.ok && (target.reason === "binary-not-found" || target.reason === "native-binary-missing")) {
|
|
14275
|
+
p2.log.error(describePatchTargetFailure(target, "restore"));
|
|
14276
|
+
return 1;
|
|
14277
|
+
}
|
|
14278
|
+
if (!target.ok && target.reason === "launcher-unresolved" && target.declaredTarget === null) {
|
|
14279
|
+
p2.log.error(describePatchTargetFailure(target, "restore"));
|
|
13900
14280
|
return 1;
|
|
13901
14281
|
}
|
|
13902
14282
|
const binaryPath = target.binaryPath;
|
|
@@ -13967,7 +14347,7 @@ async function runPatchCommand(opts = {}) {
|
|
|
13967
14347
|
binaryPath,
|
|
13968
14348
|
claudeVersion: version,
|
|
13969
14349
|
configHash,
|
|
13970
|
-
binarySize:
|
|
14350
|
+
binarySize: statSync8(binaryPath).size
|
|
13971
14351
|
});
|
|
13972
14352
|
if (state === "current") {
|
|
13973
14353
|
p2.log.success(`claude ${version} is already patched with the current model config \u2014 nothing to do.`);
|
|
@@ -14004,8 +14384,8 @@ async function runLaunchPatchCheck(opts = {}) {
|
|
|
14004
14384
|
if (Object.keys(desired.config).length === 0) return;
|
|
14005
14385
|
const target = resolveClaudeBinaryForPatch();
|
|
14006
14386
|
if (!target.ok) {
|
|
14007
|
-
if (target.reason
|
|
14008
|
-
console.error(pc3.dim(`clodex: ${describePatchTargetFailure(target)}`));
|
|
14387
|
+
if (target.reason !== "binary-not-found" && !opts.agentStdout) {
|
|
14388
|
+
console.error(pc3.dim(`clodex: ${describePatchTargetFailure(target, "launch")}`));
|
|
14009
14389
|
}
|
|
14010
14390
|
return;
|
|
14011
14391
|
}
|
|
@@ -14023,7 +14403,7 @@ async function runLaunchPatchCheck(opts = {}) {
|
|
|
14023
14403
|
binaryPath: resolved.binaryPath,
|
|
14024
14404
|
claudeVersion: resolved.version,
|
|
14025
14405
|
configHash,
|
|
14026
|
-
binarySize:
|
|
14406
|
+
binarySize: statSync8(resolved.binaryPath).size
|
|
14027
14407
|
});
|
|
14028
14408
|
if (state === "current") return;
|
|
14029
14409
|
const interactive = !opts.dryRun && !opts.agentStdout && process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
@@ -14359,19 +14739,19 @@ function localProvidersToServerModels(localProviders) {
|
|
|
14359
14739
|
// src/registry/credential-cleanup-journal.ts
|
|
14360
14740
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
14361
14741
|
import {
|
|
14362
|
-
closeSync as
|
|
14742
|
+
closeSync as closeSync8,
|
|
14363
14743
|
existsSync as existsSync6,
|
|
14364
|
-
fstatSync as
|
|
14744
|
+
fstatSync as fstatSync3,
|
|
14365
14745
|
fsyncSync as fsyncSync2,
|
|
14366
14746
|
lstatSync,
|
|
14367
14747
|
mkdirSync as mkdirSync6,
|
|
14368
|
-
openSync as
|
|
14369
|
-
readFileSync as
|
|
14748
|
+
openSync as openSync8,
|
|
14749
|
+
readFileSync as readFileSync11,
|
|
14370
14750
|
renameSync as renameSync3,
|
|
14371
14751
|
unlinkSync as unlinkSync4,
|
|
14372
14752
|
writeFileSync as writeFileSync6
|
|
14373
14753
|
} from "fs";
|
|
14374
|
-
import { dirname as
|
|
14754
|
+
import { dirname as dirname6 } from "path";
|
|
14375
14755
|
var JOURNAL_SCHEMA_VERSION = 1;
|
|
14376
14756
|
var DIR_MODE2 = 448;
|
|
14377
14757
|
var FILE_MODE4 = 384;
|
|
@@ -14457,8 +14837,8 @@ function readJournalUnlocked(path) {
|
|
|
14457
14837
|
if (before.isSymbolicLink() || !before.isFile()) {
|
|
14458
14838
|
throw new Error("Credential cleanup journal must be a regular file.");
|
|
14459
14839
|
}
|
|
14460
|
-
fd =
|
|
14461
|
-
const opened =
|
|
14840
|
+
fd = openSync8(path, "r");
|
|
14841
|
+
const opened = fstatSync3(fd);
|
|
14462
14842
|
if (before.dev !== opened.dev || before.ino !== opened.ino) {
|
|
14463
14843
|
throw new Error("Credential cleanup journal changed while opening.");
|
|
14464
14844
|
}
|
|
@@ -14473,44 +14853,44 @@ function readJournalUnlocked(path) {
|
|
|
14473
14853
|
if (opened.size > MAX_JOURNAL_BYTES) {
|
|
14474
14854
|
throw new Error("Credential cleanup journal is too large.");
|
|
14475
14855
|
}
|
|
14476
|
-
return parseJournal(JSON.parse(
|
|
14856
|
+
return parseJournal(JSON.parse(readFileSync11(fd, "utf8")));
|
|
14477
14857
|
} catch (error) {
|
|
14478
14858
|
const message = error instanceof Error ? error.message : String(error);
|
|
14479
14859
|
throw new Error(`Could not read credential cleanup journal: ${message}`);
|
|
14480
14860
|
} finally {
|
|
14481
|
-
if (fd !== void 0)
|
|
14861
|
+
if (fd !== void 0) closeSync8(fd);
|
|
14482
14862
|
}
|
|
14483
14863
|
}
|
|
14484
14864
|
function syncParentDirectory(path) {
|
|
14485
14865
|
let fd;
|
|
14486
14866
|
try {
|
|
14487
|
-
fd =
|
|
14867
|
+
fd = openSync8(dirname6(path), "r");
|
|
14488
14868
|
fsyncSync2(fd);
|
|
14489
14869
|
} catch (error) {
|
|
14490
14870
|
const code = error.code;
|
|
14491
14871
|
if (code !== "EINVAL" && code !== "ENOTSUP" && code !== "EPERM") throw error;
|
|
14492
14872
|
} finally {
|
|
14493
|
-
if (fd !== void 0)
|
|
14873
|
+
if (fd !== void 0) closeSync8(fd);
|
|
14494
14874
|
}
|
|
14495
14875
|
}
|
|
14496
14876
|
function writeJournalUnlocked(journal, path) {
|
|
14497
14877
|
assertRegistryWriteOwnership(path);
|
|
14498
14878
|
ensureSecureAppHome();
|
|
14499
|
-
mkdirSync6(
|
|
14879
|
+
mkdirSync6(dirname6(path), { recursive: true, mode: DIR_MODE2 });
|
|
14500
14880
|
const tmp = `${path}.${process.pid}.${randomUUID4()}.tmp`;
|
|
14501
14881
|
let fd;
|
|
14502
14882
|
try {
|
|
14503
|
-
fd =
|
|
14883
|
+
fd = openSync8(tmp, "wx", FILE_MODE4);
|
|
14504
14884
|
writeFileSync6(fd, `${JSON.stringify(journal, null, 2)}
|
|
14505
14885
|
`);
|
|
14506
14886
|
fsyncSync2(fd);
|
|
14507
|
-
|
|
14887
|
+
closeSync8(fd);
|
|
14508
14888
|
fd = void 0;
|
|
14509
14889
|
assertRegistryWriteOwnership(path);
|
|
14510
14890
|
renameSync3(tmp, path);
|
|
14511
14891
|
syncParentDirectory(path);
|
|
14512
14892
|
} finally {
|
|
14513
|
-
if (fd !== void 0)
|
|
14893
|
+
if (fd !== void 0) closeSync8(fd);
|
|
14514
14894
|
try {
|
|
14515
14895
|
unlinkSync4(tmp);
|
|
14516
14896
|
} catch (error) {
|
|
@@ -17739,8 +18119,8 @@ async function startServer(options) {
|
|
|
17739
18119
|
url: `http://${tcpListenerUrlHost(address.address)}:${address.port}`,
|
|
17740
18120
|
server,
|
|
17741
18121
|
inferenceLogPath: options.inferenceLogPath,
|
|
17742
|
-
close: () => new Promise((
|
|
17743
|
-
server.close((err) => err ? reject(err) :
|
|
18122
|
+
close: () => new Promise((resolve4, reject) => {
|
|
18123
|
+
server.close((err) => err ? reject(err) : resolve4());
|
|
17744
18124
|
})
|
|
17745
18125
|
};
|
|
17746
18126
|
}
|
|
@@ -18479,8 +18859,8 @@ import { createBrotliDecompress, createGunzip, createInflate } from "zlib";
|
|
|
18479
18859
|
|
|
18480
18860
|
// src/http-proxy/ca.ts
|
|
18481
18861
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
18482
|
-
import { chmodSync as chmodSync4, existsSync as existsSync7, mkdirSync as mkdirSync7, readFileSync as
|
|
18483
|
-
import { dirname as
|
|
18862
|
+
import { chmodSync as chmodSync4, existsSync as existsSync7, mkdirSync as mkdirSync7, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "fs";
|
|
18863
|
+
import { dirname as dirname7, join as join9, resolve as resolve3 } from "path";
|
|
18484
18864
|
import forge from "node-forge";
|
|
18485
18865
|
var CERT_DIR = "http-proxy";
|
|
18486
18866
|
var CA_CERT_FILE = "clodex-ca.pem";
|
|
@@ -18495,14 +18875,14 @@ function serialNumber() {
|
|
|
18495
18875
|
return bytes.toString("hex");
|
|
18496
18876
|
}
|
|
18497
18877
|
function certPaths() {
|
|
18498
|
-
const dir =
|
|
18878
|
+
const dir = join9(getAppHome(), CERT_DIR);
|
|
18499
18879
|
return {
|
|
18500
18880
|
dir,
|
|
18501
|
-
caCert:
|
|
18502
|
-
caKey:
|
|
18503
|
-
serverCert:
|
|
18504
|
-
serverKey:
|
|
18505
|
-
version:
|
|
18881
|
+
caCert: join9(dir, CA_CERT_FILE),
|
|
18882
|
+
caKey: join9(dir, CA_KEY_FILE),
|
|
18883
|
+
serverCert: join9(dir, SERVER_CERT_FILE),
|
|
18884
|
+
serverKey: join9(dir, SERVER_KEY_FILE),
|
|
18885
|
+
version: join9(dir, CERT_VERSION_FILE)
|
|
18506
18886
|
};
|
|
18507
18887
|
}
|
|
18508
18888
|
function writePrivate(path, value) {
|
|
@@ -18555,8 +18935,8 @@ function generateCertificates(paths) {
|
|
|
18555
18935
|
}
|
|
18556
18936
|
function storedCertificatesAreCurrent(paths) {
|
|
18557
18937
|
try {
|
|
18558
|
-
const ca = forge.pki.certificateFromPem(
|
|
18559
|
-
const server = forge.pki.certificateFromPem(
|
|
18938
|
+
const ca = forge.pki.certificateFromPem(readFileSync12(paths.caCert, "utf8"));
|
|
18939
|
+
const server = forge.pki.certificateFromPem(readFileSync12(paths.serverCert, "utf8"));
|
|
18560
18940
|
const now = Date.now();
|
|
18561
18941
|
const renewalBuffer = 7 * 24 * 60 * 60 * 1e3;
|
|
18562
18942
|
return ca.validity.notBefore.getTime() <= now && ca.validity.notAfter.getTime() > now + renewalBuffer && server.validity.notBefore.getTime() <= now && server.validity.notAfter.getTime() > now + renewalBuffer && ca.verify(ca) && ca.verify(server);
|
|
@@ -18567,13 +18947,13 @@ function storedCertificatesAreCurrent(paths) {
|
|
|
18567
18947
|
function ensureHttpProxyCertificates() {
|
|
18568
18948
|
const paths = certPaths();
|
|
18569
18949
|
const required = [paths.caCert, paths.caKey, paths.serverCert, paths.serverKey, paths.version];
|
|
18570
|
-
const current = required.every(existsSync7) &&
|
|
18950
|
+
const current = required.every(existsSync7) && readFileSync12(paths.version, "utf8") === CERT_VERSION && storedCertificatesAreCurrent(paths);
|
|
18571
18951
|
if (!current) generateCertificates(paths);
|
|
18572
18952
|
return {
|
|
18573
18953
|
caCertPath: paths.caCert,
|
|
18574
|
-
caCert:
|
|
18575
|
-
serverCert:
|
|
18576
|
-
serverKey:
|
|
18954
|
+
caCert: readFileSync12(paths.caCert, "utf8"),
|
|
18955
|
+
serverCert: readFileSync12(paths.serverCert, "utf8"),
|
|
18956
|
+
serverKey: readFileSync12(paths.serverKey, "utf8")
|
|
18577
18957
|
};
|
|
18578
18958
|
}
|
|
18579
18959
|
function ensureHttpProxyCaBundle(relayCaCertPath, additionalCaCertPath, onWarning) {
|
|
@@ -18586,8 +18966,8 @@ function ensureHttpProxyCaBundle(relayCaCertPath, additionalCaCertPath, onWarnin
|
|
|
18586
18966
|
};
|
|
18587
18967
|
let additionalCa;
|
|
18588
18968
|
try {
|
|
18589
|
-
if (
|
|
18590
|
-
additionalCa =
|
|
18969
|
+
if (resolve3(additionalCaCertPath) === resolve3(relayCaCertPath)) return relayCaCertPath;
|
|
18970
|
+
additionalCa = readFileSync12(additionalCaCertPath, "utf8").trim();
|
|
18591
18971
|
} catch (err) {
|
|
18592
18972
|
return warn(
|
|
18593
18973
|
`NODE_EXTRA_CA_CERTS=${additionalCaCertPath} cannot be read (${err instanceof Error ? err.message : String(err)}), so it is not part of the proxy CA bundle. Where node reports this itself it says only "Ignoring extra certs ... load failed", without naming the variable. Clear or correct it.`
|
|
@@ -18597,15 +18977,15 @@ function ensureHttpProxyCaBundle(relayCaCertPath, additionalCaCertPath, onWarnin
|
|
|
18597
18977
|
return warn(`NODE_EXTRA_CA_CERTS=${additionalCaCertPath} is empty, so it adds nothing.`);
|
|
18598
18978
|
}
|
|
18599
18979
|
try {
|
|
18600
|
-
const relayCa =
|
|
18601
|
-
const combinedPath =
|
|
18980
|
+
const relayCa = readFileSync12(relayCaCertPath, "utf8").trimEnd();
|
|
18981
|
+
const combinedPath = join9(dirname7(relayCaCertPath), "combined-ca.pem");
|
|
18602
18982
|
writePublic(combinedPath, `${relayCa}
|
|
18603
18983
|
${additionalCa}
|
|
18604
18984
|
`);
|
|
18605
18985
|
return combinedPath;
|
|
18606
18986
|
} catch (err) {
|
|
18607
18987
|
return warn(
|
|
18608
|
-
`clodex could not build the combined CA bundle in ${
|
|
18988
|
+
`clodex could not build the combined CA bundle in ${dirname7(relayCaCertPath)} (${err instanceof Error ? err.message : String(err)}), so the readable, non-empty NODE_EXTRA_CA_CERTS=${additionalCaCertPath} was left out of it. Fix the reported error and restart clodex.`
|
|
18609
18989
|
);
|
|
18610
18990
|
}
|
|
18611
18991
|
}
|
|
@@ -18708,7 +19088,7 @@ function shouldInterceptConnect(authority) {
|
|
|
18708
19088
|
return Boolean(target && target.port === 443 && target.host.replace(/\.$/, "").toLowerCase() === ANTHROPIC_HOST);
|
|
18709
19089
|
}
|
|
18710
19090
|
function readRawBody(req) {
|
|
18711
|
-
return new Promise((
|
|
19091
|
+
return new Promise((resolve4, reject) => {
|
|
18712
19092
|
const chunks = [];
|
|
18713
19093
|
let size = 0;
|
|
18714
19094
|
req.on("data", (chunk) => {
|
|
@@ -18720,7 +19100,7 @@ function readRawBody(req) {
|
|
|
18720
19100
|
}
|
|
18721
19101
|
chunks.push(chunk);
|
|
18722
19102
|
});
|
|
18723
|
-
req.on("end", () =>
|
|
19103
|
+
req.on("end", () => resolve4(Buffer.concat(chunks)));
|
|
18724
19104
|
req.on("error", reject);
|
|
18725
19105
|
});
|
|
18726
19106
|
}
|
|
@@ -18771,7 +19151,7 @@ function requestHeadersWithoutProxyHeaders(req) {
|
|
|
18771
19151
|
return headers;
|
|
18772
19152
|
}
|
|
18773
19153
|
function forwardRawAnthropicRequest(req, res, rawBody, origin, rejectUnauthorized, agent, onErrorResponse, onResponseUsage, lifecycle, isLocalShutdown = () => false) {
|
|
18774
|
-
return new Promise((
|
|
19154
|
+
return new Promise((resolve4) => {
|
|
18775
19155
|
const startedAt = Date.now();
|
|
18776
19156
|
const retryBudget = passthroughUpstreamRetries();
|
|
18777
19157
|
let lastActivityAt = startedAt;
|
|
@@ -18820,7 +19200,7 @@ function forwardRawAnthropicRequest(req, res, rawBody, origin, rejectUnauthorize
|
|
|
18820
19200
|
const done = () => {
|
|
18821
19201
|
if (settled) return;
|
|
18822
19202
|
settled = true;
|
|
18823
|
-
|
|
19203
|
+
resolve4();
|
|
18824
19204
|
};
|
|
18825
19205
|
const errorType = (err) => err.code ?? err.name;
|
|
18826
19206
|
let upstream;
|
|
@@ -18969,7 +19349,7 @@ function forwardRawAnthropicRequest(req, res, rawBody, origin, rejectUnauthorize
|
|
|
18969
19349
|
});
|
|
18970
19350
|
}
|
|
18971
19351
|
function forwardToAdapter(req, res, rawBody, adapter, adapterRequest = http2.request, adapterAgent, lifecycle, isLocalShutdown = () => false) {
|
|
18972
|
-
return new Promise((
|
|
19352
|
+
return new Promise((resolve4) => {
|
|
18973
19353
|
const startedAt = Date.now();
|
|
18974
19354
|
let lastActivityAt = startedAt;
|
|
18975
19355
|
let headersReceived = false;
|
|
@@ -19044,11 +19424,11 @@ function forwardToAdapter(req, res, rawBody, adapter, adapterRequest = http2.req
|
|
|
19044
19424
|
});
|
|
19045
19425
|
adapterResponse?.destroy(new Error("Client disconnected"));
|
|
19046
19426
|
upstream?.destroy(new Error("Client disconnected"));
|
|
19047
|
-
|
|
19427
|
+
resolve4();
|
|
19048
19428
|
});
|
|
19049
19429
|
const failAdapterRequest = (err, failureSource) => {
|
|
19050
19430
|
if (clientDisconnected2) {
|
|
19051
|
-
|
|
19431
|
+
resolve4();
|
|
19052
19432
|
return;
|
|
19053
19433
|
}
|
|
19054
19434
|
if (headersReceived || failed) return;
|
|
@@ -19069,7 +19449,7 @@ function forwardToAdapter(req, res, rawBody, adapter, adapterRequest = http2.req
|
|
|
19069
19449
|
});
|
|
19070
19450
|
if (!res.headersSent) res.writeHead(502, { "Content-Type": "text/plain" });
|
|
19071
19451
|
res.end(`Relay adapter unreachable: ${err.message}`);
|
|
19072
|
-
|
|
19452
|
+
resolve4();
|
|
19073
19453
|
};
|
|
19074
19454
|
upstream = adapterRequest({
|
|
19075
19455
|
hostname: "127.0.0.1",
|
|
@@ -19106,7 +19486,7 @@ function forwardToAdapter(req, res, rawBody, adapter, adapterRequest = http2.req
|
|
|
19106
19486
|
copyResponse(upstreamRes, res, void 0, lifecycle ? (usage) => writeLifecycle("response_usage", usage) : void 0);
|
|
19107
19487
|
const failAdapterResponse = (err, failureSource) => {
|
|
19108
19488
|
if (clientDisconnected2) {
|
|
19109
|
-
|
|
19489
|
+
resolve4();
|
|
19110
19490
|
return;
|
|
19111
19491
|
}
|
|
19112
19492
|
if (adapterEnded || failed) return;
|
|
@@ -19127,12 +19507,12 @@ function forwardToAdapter(req, res, rawBody, adapter, adapterRequest = http2.req
|
|
|
19127
19507
|
terminationSource: "upstream_failure"
|
|
19128
19508
|
});
|
|
19129
19509
|
if (!res.writableEnded) res.destroy(err);
|
|
19130
|
-
|
|
19510
|
+
resolve4();
|
|
19131
19511
|
};
|
|
19132
19512
|
upstreamRes.once("end", () => {
|
|
19133
19513
|
adapterEnded = true;
|
|
19134
19514
|
lastActivityAt = Date.now();
|
|
19135
|
-
|
|
19515
|
+
resolve4();
|
|
19136
19516
|
});
|
|
19137
19517
|
upstreamRes.once("error", (err) => failAdapterResponse(err, "adapter_response_error"));
|
|
19138
19518
|
upstreamRes.once("aborted", () => failAdapterResponse(
|
|
@@ -19558,7 +19938,7 @@ async function startHttpProxy(options) {
|
|
|
19558
19938
|
close: async () => {
|
|
19559
19939
|
shuttingDown = true;
|
|
19560
19940
|
for (const socket of sockets) socket.destroy();
|
|
19561
|
-
await new Promise((
|
|
19941
|
+
await new Promise((resolve4) => proxyServer.close(() => resolve4()));
|
|
19562
19942
|
mitmServer.close();
|
|
19563
19943
|
anthropicAgent?.destroy();
|
|
19564
19944
|
adapter?.close();
|
|
@@ -19689,11 +20069,11 @@ async function startConfiguredHttpProxy(port, debug = false, inferenceLogPath =
|
|
|
19689
20069
|
return { handle, loaded, ...caWarning ? { caWarning } : {} };
|
|
19690
20070
|
}
|
|
19691
20071
|
function waitForShutdown() {
|
|
19692
|
-
return new Promise((
|
|
20072
|
+
return new Promise((resolve4) => {
|
|
19693
20073
|
const done = () => {
|
|
19694
20074
|
process.off("SIGINT", done);
|
|
19695
20075
|
process.off("SIGTERM", done);
|
|
19696
|
-
|
|
20076
|
+
resolve4();
|
|
19697
20077
|
};
|
|
19698
20078
|
process.once("SIGINT", done);
|
|
19699
20079
|
process.once("SIGTERM", done);
|
|
@@ -19867,14 +20247,14 @@ function enrichServerModelReasoning(model) {
|
|
|
19867
20247
|
return { ...model, defaultEffort: caps.defaultLevel };
|
|
19868
20248
|
}
|
|
19869
20249
|
function waitForShutdown2() {
|
|
19870
|
-
return new Promise((
|
|
20250
|
+
return new Promise((resolve4) => {
|
|
19871
20251
|
const cleanup = () => {
|
|
19872
20252
|
process.off("SIGINT", onSignal);
|
|
19873
20253
|
process.off("SIGTERM", onSignal);
|
|
19874
20254
|
};
|
|
19875
20255
|
const onSignal = () => {
|
|
19876
20256
|
cleanup();
|
|
19877
|
-
|
|
20257
|
+
resolve4();
|
|
19878
20258
|
};
|
|
19879
20259
|
process.once("SIGINT", onSignal);
|
|
19880
20260
|
process.once("SIGTERM", onSignal);
|
|
@@ -21853,7 +22233,7 @@ Error: ${resolved.error}
|
|
|
21853
22233
|
function isCliEntryPoint() {
|
|
21854
22234
|
if (!process.argv[1]) return false;
|
|
21855
22235
|
try {
|
|
21856
|
-
return
|
|
22236
|
+
return realpathSync3(fileURLToPath(import.meta.url)) === realpathSync3(process.argv[1]);
|
|
21857
22237
|
} catch {
|
|
21858
22238
|
return false;
|
|
21859
22239
|
}
|