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