@bman654/clodex 2.8.3 → 2.8.5
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 +8 -1
- package/dist/cli.js +427 -113
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -382,7 +382,7 @@ import { join } from "path";
|
|
|
382
382
|
// package.json
|
|
383
383
|
var package_default = {
|
|
384
384
|
name: "@bman654/clodex",
|
|
385
|
-
version: "2.8.
|
|
385
|
+
version: "2.8.5",
|
|
386
386
|
publishConfig: {
|
|
387
387
|
access: "public"
|
|
388
388
|
},
|
|
@@ -3423,7 +3423,7 @@ function savedStopsAfter(current, assignments) {
|
|
|
3423
3423
|
}
|
|
3424
3424
|
|
|
3425
3425
|
// src/patch-transforms.ts
|
|
3426
|
-
var PATCH_TRANSFORMS_VERSION =
|
|
3426
|
+
var PATCH_TRANSFORMS_VERSION = 11;
|
|
3427
3427
|
var NATIVE_EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"];
|
|
3428
3428
|
var BASE_EFFORT_LEVELS = ["low", "medium", "high"];
|
|
3429
3429
|
function projectNativeEffort(effort) {
|
|
@@ -3633,19 +3633,19 @@ function applyClodexPatches(source, config) {
|
|
|
3633
3633
|
}
|
|
3634
3634
|
if (Object.keys(CONTEXT_BY_KEY).length) {
|
|
3635
3635
|
const MARKER = "/*ccpatch:ctx*/";
|
|
3636
|
-
const
|
|
3636
|
+
const snippetFor = (modelParam) => MARKER + "var _ccw=(" + JSON.stringify(CONTEXT_BY_KEY) + ")[String(" + modelParam + '||"").trim().toLowerCase()];if(_ccw!==void 0)return _ccw;';
|
|
3637
3637
|
if (js.includes(MARKER)) {
|
|
3638
3638
|
applyOnce(
|
|
3639
3639
|
"PATCH 7: per-model context window (refresh)",
|
|
3640
|
-
/\/\*ccpatch:ctx\*\/var _ccw=\(\{[^{}]*\}\)\[[
|
|
3641
|
-
() =>
|
|
3640
|
+
/\/\*ccpatch:ctx\*\/var _ccw=\(\{[^{}]*\}\)\[String\(([\w$]+)\|\|""\)\.trim\(\)\.toLowerCase\(\)\];if\(_ccw!==void 0\)return _ccw;/,
|
|
3641
|
+
(_m, modelParam) => snippetFor(modelParam),
|
|
3642
3642
|
{ required: true, noopIsSkip: true }
|
|
3643
3643
|
);
|
|
3644
3644
|
} else {
|
|
3645
3645
|
applyOnce(
|
|
3646
3646
|
"PATCH 7: per-model context window",
|
|
3647
|
-
/(function [\w$]+\(
|
|
3648
|
-
(_m, head, body) => head +
|
|
3647
|
+
/(function [\w$]+\(([\w$]+),([\w$]+)\)\{)(let [\w$]+=[\w$]+\(\);if\([\w$]+!==void 0\)return [\w$]+;if\([\w$]+\(\2,\3\)\)return [\w$]+;return [\w$]+\(\2,\3\)\})/,
|
|
3648
|
+
(_m, head, modelParam, _windowParam, body) => head + snippetFor(modelParam) + body,
|
|
3649
3649
|
{ required: true }
|
|
3650
3650
|
);
|
|
3651
3651
|
}
|
|
@@ -3727,15 +3727,15 @@ function applyClodexPatches(source, config) {
|
|
|
3727
3727
|
const marker = "/*ccpatch:child-network-env*/";
|
|
3728
3728
|
const contractVar = q(NETWORK_ENV_CONTRACT_VAR);
|
|
3729
3729
|
const networkVars = JSON.stringify(CHILD_NETWORK_ENV_VARS);
|
|
3730
|
-
const requiredBodyLiterals = [
|
|
3731
|
-
|
|
3732
|
-
"CLAUDE_CODE_REMOTE",
|
|
3730
|
+
const requiredBodyLiterals = ["{...process.env"];
|
|
3731
|
+
const scrubbedEnvNames = [
|
|
3733
3732
|
"CLAUDE_CODE_OAUTH_TOKEN",
|
|
3734
3733
|
"CLAUDE_CODE_SUBSCRIPTION_TYPE",
|
|
3735
3734
|
"CLAUDE_BG_PTY_AUTH",
|
|
3736
3735
|
'"OTEL_"',
|
|
3737
3736
|
"CLAUDE_CODE_OTEL_DIAG_STDERR"
|
|
3738
3737
|
];
|
|
3738
|
+
const MIN_SCRUBBED_ENV_NAMES = 1;
|
|
3739
3739
|
const blockEndIndex = (text5, open2) => {
|
|
3740
3740
|
const depths = [0];
|
|
3741
3741
|
const templates = [false];
|
|
@@ -3815,11 +3815,15 @@ function applyClodexPatches(source, config) {
|
|
|
3815
3815
|
/(function [\w$]+\(\)\{)(let (?:[^;{}]|\{[^;{}]*\})*?[\w$]+\(process\.env\.CLAUDE_CODE_REMOTE\)\?(?:(?!\}\s*function )[\s\S])*?\)return process\.env;let ([\w$]+)=\{(?:(?!\}\s*function )[\s\S])*?return \3)(\})/,
|
|
3816
3816
|
(match, head, body, _copyVar, tail) => {
|
|
3817
3817
|
const at = js.indexOf(match);
|
|
3818
|
-
const
|
|
3819
|
-
const
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3818
|
+
const closingBrace = at < 0 ? -1 : blockEndIndex(js, at + head.length - 1);
|
|
3819
|
+
const braceScanFailed = at < 0 || closingBrace < 0;
|
|
3820
|
+
const bound = braceScanFailed ? 0 : closingBrace - at - (match.length - 1);
|
|
3821
|
+
const missingLiteral = requiredBodyLiterals.find((literal) => !body.includes(literal));
|
|
3822
|
+
const scrubbedSeen = scrubbedEnvNames.filter((name) => body.includes(name));
|
|
3823
|
+
const why = missingLiteral !== void 0 ? "body does not contain " + missingLiteral : scrubbedSeen.length < MIN_SCRUBBED_ENV_NAMES ? "body spells only " + scrubbedSeen.length + " of the " + scrubbedEnvNames.length + " known child-env names (expected at least " + MIN_SCRUBBED_ENV_NAMES + ")" : /\bfunction\s*[\w$]*\(/.test(body) ? "body declares a nested function" : braceScanFailed ? "the brace walk never reached the function's closing brace" : bound !== 0 ? "match ends " + Math.abs(bound) + " characters " + (bound > 0 ? "before" : "after") + " the end of the function it started in" : void 0;
|
|
3824
|
+
if (why !== void 0) {
|
|
3825
|
+
log12("FAIL", patchName, "target validation failed: " + why);
|
|
3826
|
+
fail("clodex patch: child network environment target validation failed: " + why);
|
|
3823
3827
|
}
|
|
3824
3828
|
const restoredBody = body.replace(/process\.env/g, "_clodexChildEnv");
|
|
3825
3829
|
const restore = marker + "let _clodexChildEnv=process.env,_clodexNetworkRaw=_clodexChildEnv[" + contractVar + "];if(_clodexNetworkRaw!==void 0){_clodexChildEnv={..._clodexChildEnv};delete _clodexChildEnv[" + contractVar + '];try{let _clodexNetwork=JSON.parse(_clodexNetworkRaw);if(_clodexNetwork&&typeof _clodexNetwork==="object"&&!Array.isArray(_clodexNetwork)&&_clodexNetwork.version===1&&_clodexNetwork.original&&typeof _clodexNetwork.original==="object"&&!Array.isArray(_clodexNetwork.original)&&_clodexNetwork.injected&&typeof _clodexNetwork.injected==="object"&&!Array.isArray(_clodexNetwork.injected)&&Object.keys(_clodexNetwork.original).every(_clodexKey=>' + networkVars + '.includes(_clodexKey)&&(typeof _clodexNetwork.original[_clodexKey]==="string"||_clodexNetwork.original[_clodexKey]===null)&&Object.prototype.hasOwnProperty.call(_clodexNetwork.injected,_clodexKey))&&Object.keys(_clodexNetwork.injected).every(_clodexKey=>' + networkVars + '.includes(_clodexKey)&&(typeof _clodexNetwork.injected[_clodexKey]==="string"||_clodexNetwork.injected[_clodexKey]===null)&&Object.prototype.hasOwnProperty.call(_clodexNetwork.original,_clodexKey)))for(let _clodexKey of ' + networkVars + '){if(Object.prototype.hasOwnProperty.call(_clodexNetwork.original,_clodexKey)&&Object.prototype.hasOwnProperty.call(_clodexNetwork.injected,_clodexKey)){let _clodexOriginal=_clodexNetwork.original[_clodexKey],_clodexInjected=_clodexNetwork.injected[_clodexKey],_clodexCurrent=_clodexChildEnv[_clodexKey]===void 0?null:_clodexChildEnv[_clodexKey];if((typeof _clodexOriginal==="string"||_clodexOriginal===null)&&(typeof _clodexInjected==="string"||_clodexInjected===null)&&_clodexCurrent===_clodexInjected){if(_clodexOriginal===null)delete _clodexChildEnv[_clodexKey];else _clodexChildEnv[_clodexKey]=_clodexOriginal}}}}catch(_clodexError){}}';
|
|
@@ -3844,8 +3848,8 @@ import {
|
|
|
3844
3848
|
statSync as statSync6,
|
|
3845
3849
|
unlinkSync as unlinkSync3,
|
|
3846
3850
|
writeFileSync as writeFileSync5,
|
|
3847
|
-
openSync as
|
|
3848
|
-
closeSync as
|
|
3851
|
+
openSync as openSync6,
|
|
3852
|
+
closeSync as closeSync6,
|
|
3849
3853
|
realpathSync
|
|
3850
3854
|
} from "fs";
|
|
3851
3855
|
import { homedir as homedir3 } from "os";
|
|
@@ -6201,6 +6205,7 @@ function writeInferenceResponseLifecycleLog(path, entry) {
|
|
|
6201
6205
|
const outputTokens = nonNegativeInteger(entry.outputTokens);
|
|
6202
6206
|
const cacheCreationInputTokens = nonNegativeInteger(entry.cacheCreationInputTokens);
|
|
6203
6207
|
const cacheReadInputTokens = nonNegativeInteger(entry.cacheReadInputTokens);
|
|
6208
|
+
const attempt = nonNegativeInteger(entry.attempt);
|
|
6204
6209
|
writeSecureLogLine(path, JSON.stringify({
|
|
6205
6210
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6206
6211
|
event: entry.event,
|
|
@@ -6231,7 +6236,9 @@ function writeInferenceResponseLifecycleLog(path, entry) {
|
|
|
6231
6236
|
...entry.errorCode ? { errorCode: compactLogValue(entry.errorCode, 100) } : {},
|
|
6232
6237
|
...entry.errorSignature ? { errorSignature: compactLogValue(entry.errorSignature, 100) } : {},
|
|
6233
6238
|
...entry.failureSource ? { failureSource: entry.failureSource } : {},
|
|
6234
|
-
...entry.terminationSource ? { terminationSource: entry.terminationSource } : {}
|
|
6239
|
+
...entry.terminationSource ? { terminationSource: entry.terminationSource } : {},
|
|
6240
|
+
...attempt !== void 0 ? { attempt } : {},
|
|
6241
|
+
...entry.reusedSocket !== void 0 ? { reusedSocket: entry.reusedSocket } : {}
|
|
6235
6242
|
}));
|
|
6236
6243
|
}
|
|
6237
6244
|
function writeProxyLifecycleLog(path, entry) {
|
|
@@ -7058,8 +7065,225 @@ function resignMachOBinary(path) {
|
|
|
7058
7065
|
}
|
|
7059
7066
|
}
|
|
7060
7067
|
|
|
7068
|
+
// src/bun-compiled-pointer.ts
|
|
7069
|
+
import { closeSync as closeSync3, fstatSync, openSync as openSync3, readSync as readSync2, writeSync as writeSync3 } from "fs";
|
|
7070
|
+
var TWEAKCC_SCAN_STRIDE = 16384n;
|
|
7071
|
+
var SCAN_CHUNK = 1 << 20;
|
|
7072
|
+
var ELF_MAGIC = 1179403647;
|
|
7073
|
+
var ELFCLASS64 = 2;
|
|
7074
|
+
var ELFDATA2LSB = 1;
|
|
7075
|
+
var PT_LOAD = 1;
|
|
7076
|
+
var PF_W = 2;
|
|
7077
|
+
function readAt2(fd, length, position) {
|
|
7078
|
+
const buf = Buffer.alloc(length);
|
|
7079
|
+
let read = 0;
|
|
7080
|
+
while (read < length) {
|
|
7081
|
+
const n = readSync2(fd, buf, read, length - read, position + read);
|
|
7082
|
+
if (n <= 0) break;
|
|
7083
|
+
read += n;
|
|
7084
|
+
}
|
|
7085
|
+
return read === length ? buf : buf.subarray(0, read);
|
|
7086
|
+
}
|
|
7087
|
+
function readElfLayout(fd) {
|
|
7088
|
+
const ident = readAt2(fd, 64, 0);
|
|
7089
|
+
if (ident.length < 64) return null;
|
|
7090
|
+
if (ident.readUInt32LE(0) !== ELF_MAGIC) return null;
|
|
7091
|
+
if (ident[4] !== ELFCLASS64 || ident[5] !== ELFDATA2LSB) return null;
|
|
7092
|
+
const phoff = ident.readBigUInt64LE(32);
|
|
7093
|
+
const shoff = ident.readBigUInt64LE(40);
|
|
7094
|
+
const phentsize = ident.readUInt16LE(54);
|
|
7095
|
+
const phnum = ident.readUInt16LE(56);
|
|
7096
|
+
const shentsize = ident.readUInt16LE(58);
|
|
7097
|
+
const shnum = ident.readUInt16LE(60);
|
|
7098
|
+
const shstrndx = ident.readUInt16LE(62);
|
|
7099
|
+
if (shnum === 0 || phnum === 65535) return null;
|
|
7100
|
+
if (shstrndx >= shnum || shentsize < 64 || phentsize < 56) return null;
|
|
7101
|
+
const fileSize = fstatSync(fd).size;
|
|
7102
|
+
const fits = (offset, length) => Number.isSafeInteger(offset) && offset >= 0 && length >= 0 && offset + length <= fileSize;
|
|
7103
|
+
if (!fits(Number(shoff), shnum * shentsize)) return null;
|
|
7104
|
+
const shTable = readAt2(fd, shnum * shentsize, Number(shoff));
|
|
7105
|
+
if (shTable.length !== shnum * shentsize) return null;
|
|
7106
|
+
const raw = [];
|
|
7107
|
+
for (let i = 0; i < shnum; i++) {
|
|
7108
|
+
const at = i * shentsize;
|
|
7109
|
+
raw.push({
|
|
7110
|
+
nameOffset: shTable.readUInt32LE(at),
|
|
7111
|
+
addr: shTable.readBigUInt64LE(at + 16),
|
|
7112
|
+
offset: shTable.readBigUInt64LE(at + 24),
|
|
7113
|
+
size: shTable.readBigUInt64LE(at + 32)
|
|
7114
|
+
});
|
|
7115
|
+
}
|
|
7116
|
+
const strtab = raw[shstrndx];
|
|
7117
|
+
if (!fits(Number(strtab.offset), Number(strtab.size))) return null;
|
|
7118
|
+
const names = readAt2(fd, Number(strtab.size), Number(strtab.offset));
|
|
7119
|
+
const sections = raw.map((section) => {
|
|
7120
|
+
const start = section.nameOffset;
|
|
7121
|
+
let end = start;
|
|
7122
|
+
while (end < names.length && names[end] !== 0) end++;
|
|
7123
|
+
return {
|
|
7124
|
+
name: names.toString("utf8", start, end),
|
|
7125
|
+
addr: section.addr,
|
|
7126
|
+
offset: section.offset,
|
|
7127
|
+
size: section.size
|
|
7128
|
+
};
|
|
7129
|
+
});
|
|
7130
|
+
if (!fits(Number(phoff), phnum * phentsize)) return null;
|
|
7131
|
+
const phTable = readAt2(fd, phnum * phentsize, Number(phoff));
|
|
7132
|
+
if (phTable.length !== phnum * phentsize) return null;
|
|
7133
|
+
const segments = [];
|
|
7134
|
+
for (let i = 0; i < phnum; i++) {
|
|
7135
|
+
const at = i * phentsize;
|
|
7136
|
+
segments.push({
|
|
7137
|
+
type: phTable.readUInt32LE(at),
|
|
7138
|
+
flags: phTable.readUInt32LE(at + 4),
|
|
7139
|
+
offset: phTable.readBigUInt64LE(at + 8),
|
|
7140
|
+
vaddr: phTable.readBigUInt64LE(at + 16),
|
|
7141
|
+
filesz: phTable.readBigUInt64LE(at + 32)
|
|
7142
|
+
});
|
|
7143
|
+
}
|
|
7144
|
+
return { sections, segments };
|
|
7145
|
+
}
|
|
7146
|
+
function alignUp(value, to) {
|
|
7147
|
+
return (value + to - 1n) / to * to;
|
|
7148
|
+
}
|
|
7149
|
+
function writableLoad(layout) {
|
|
7150
|
+
return layout.segments.find((segment) => segment.type === PT_LOAD && (segment.flags & PF_W) !== 0);
|
|
7151
|
+
}
|
|
7152
|
+
function fileOffsetOf(layout, vaddr, length) {
|
|
7153
|
+
let found = null;
|
|
7154
|
+
for (const segment of layout.segments) {
|
|
7155
|
+
if (segment.type !== PT_LOAD) continue;
|
|
7156
|
+
if (vaddr < segment.vaddr) continue;
|
|
7157
|
+
if (vaddr + length > segment.vaddr + segment.filesz) continue;
|
|
7158
|
+
if (found !== null) return null;
|
|
7159
|
+
found = Number(segment.offset + (vaddr - segment.vaddr));
|
|
7160
|
+
}
|
|
7161
|
+
return found;
|
|
7162
|
+
}
|
|
7163
|
+
function tweakccWouldFind(fd, segment, needle) {
|
|
7164
|
+
const first = alignUp(segment.vaddr, TWEAKCC_SCAN_STRIDE);
|
|
7165
|
+
const last = segment.vaddr + segment.filesz - 8n;
|
|
7166
|
+
for (let vaddr = first; vaddr <= last; vaddr += TWEAKCC_SCAN_STRIDE) {
|
|
7167
|
+
const at = Number(segment.offset + (vaddr - segment.vaddr));
|
|
7168
|
+
if (readAt2(fd, 8, at).equals(needle)) return vaddr;
|
|
7169
|
+
}
|
|
7170
|
+
return null;
|
|
7171
|
+
}
|
|
7172
|
+
function scanForNeedle(fd, from, to, needle, skipFrom, skipTo) {
|
|
7173
|
+
const hits = [];
|
|
7174
|
+
for (let start = from; start < to; start += SCAN_CHUNK - 7) {
|
|
7175
|
+
const length = Math.min(SCAN_CHUNK, to - start);
|
|
7176
|
+
if (length < 8) break;
|
|
7177
|
+
const chunk = readAt2(fd, length, start);
|
|
7178
|
+
let at = 0;
|
|
7179
|
+
for (; ; ) {
|
|
7180
|
+
const found = chunk.indexOf(needle, at);
|
|
7181
|
+
if (found < 0) break;
|
|
7182
|
+
const offset = start + found;
|
|
7183
|
+
if (offset < skipFrom || offset >= skipTo) hits.push(offset);
|
|
7184
|
+
at = found + 1;
|
|
7185
|
+
}
|
|
7186
|
+
}
|
|
7187
|
+
return hits;
|
|
7188
|
+
}
|
|
7189
|
+
function shimBunCompiledPointer(path) {
|
|
7190
|
+
const fd = openSync3(path, "r+");
|
|
7191
|
+
try {
|
|
7192
|
+
const layout = readElfLayout(fd);
|
|
7193
|
+
if (!layout) return null;
|
|
7194
|
+
const bun = layout.sections.find((section) => section.name === ".bun");
|
|
7195
|
+
if (!bun || bun.size === 0n) return null;
|
|
7196
|
+
const segment = writableLoad(layout);
|
|
7197
|
+
if (!segment) return null;
|
|
7198
|
+
const needle = Buffer.alloc(8);
|
|
7199
|
+
needle.writeBigUInt64LE(bun.addr);
|
|
7200
|
+
const segmentStart = Number(segment.offset);
|
|
7201
|
+
const segmentEnd = Number(segment.offset + segment.filesz);
|
|
7202
|
+
const bunStart = Number(bun.offset);
|
|
7203
|
+
const bunEnd = Number(bun.offset + bun.size);
|
|
7204
|
+
const candidates = scanForNeedle(fd, segmentStart, segmentEnd, needle, bunStart, bunEnd);
|
|
7205
|
+
if (candidates.length !== 1) {
|
|
7206
|
+
throw new Error(
|
|
7207
|
+
`cannot locate Bun's blob pointer: ${candidates.length} candidates in the writable segment (expected 1). Refusing to repack a binary whose Bun global would be left stale.`
|
|
7208
|
+
);
|
|
7209
|
+
}
|
|
7210
|
+
const pointerOffset = candidates[0];
|
|
7211
|
+
const pointerVaddr = segment.vaddr + BigInt(pointerOffset) - segment.offset;
|
|
7212
|
+
const wouldFind = tweakccWouldFind(fd, segment, needle);
|
|
7213
|
+
if (wouldFind !== null) {
|
|
7214
|
+
if (wouldFind !== pointerVaddr) {
|
|
7215
|
+
throw new Error(
|
|
7216
|
+
`tweakcc's ELF repack would rewrite 0x${wouldFind.toString(16)}, which is not Bun's blob pointer at 0x${pointerVaddr.toString(16)}. Refusing to repack a binary whose Bun global would be left stale.`
|
|
7217
|
+
);
|
|
7218
|
+
}
|
|
7219
|
+
return null;
|
|
7220
|
+
}
|
|
7221
|
+
const first = alignUp(segment.vaddr, TWEAKCC_SCAN_STRIDE);
|
|
7222
|
+
const last = segment.vaddr + segment.filesz - 8n;
|
|
7223
|
+
let standInVaddr = null;
|
|
7224
|
+
for (let vaddr = first; vaddr <= last; vaddr += TWEAKCC_SCAN_STRIDE) {
|
|
7225
|
+
const at = Number(segment.offset + (vaddr - segment.vaddr));
|
|
7226
|
+
if (at + 8 > bunStart && at < bunEnd) continue;
|
|
7227
|
+
if (at + 8 > pointerOffset && at < pointerOffset + 8) continue;
|
|
7228
|
+
standInVaddr = vaddr;
|
|
7229
|
+
break;
|
|
7230
|
+
}
|
|
7231
|
+
if (standInVaddr === null) {
|
|
7232
|
+
throw new Error("no address tweakcc's ELF repack scans is usable for Bun's blob pointer");
|
|
7233
|
+
}
|
|
7234
|
+
const standInOffset = Number(segment.offset + (standInVaddr - segment.vaddr));
|
|
7235
|
+
const displaced = readAt2(fd, 8, standInOffset);
|
|
7236
|
+
if (displaced.length !== 8) throw new Error("could not read the bytes Bun's blob pointer displaces");
|
|
7237
|
+
writeSync3(fd, needle, 0, 8, standInOffset);
|
|
7238
|
+
return { pointerVaddr, standInVaddr, displaced, bunVaddr: bun.addr };
|
|
7239
|
+
} finally {
|
|
7240
|
+
closeSync3(fd);
|
|
7241
|
+
}
|
|
7242
|
+
}
|
|
7243
|
+
function restoreBunCompiledPointer(path, shim) {
|
|
7244
|
+
const fd = openSync3(path, "r+");
|
|
7245
|
+
try {
|
|
7246
|
+
const layout = readElfLayout(fd);
|
|
7247
|
+
if (!layout) throw new Error("the repacked binary is no longer a 64-bit little-endian ELF");
|
|
7248
|
+
const bun = layout.sections.find((section) => section.name === ".bun");
|
|
7249
|
+
if (!bun) throw new Error("the repacked binary has no .bun section");
|
|
7250
|
+
const standInOffset = fileOffsetOf(layout, shim.standInVaddr, 8n);
|
|
7251
|
+
const pointerOffset = fileOffsetOf(layout, shim.pointerVaddr, 8n);
|
|
7252
|
+
if (standInOffset === null || pointerOffset === null) {
|
|
7253
|
+
throw new Error(
|
|
7254
|
+
"the repack left Bun's blob pointer outside the loaded image, or in more than one segment of it"
|
|
7255
|
+
);
|
|
7256
|
+
}
|
|
7257
|
+
const standIn = readAt2(fd, 8, standInOffset);
|
|
7258
|
+
if (standIn.length !== 8) {
|
|
7259
|
+
throw new Error("the repacked binary ends before the stand-in for Bun's blob pointer");
|
|
7260
|
+
}
|
|
7261
|
+
const written = standIn.readBigUInt64LE(0);
|
|
7262
|
+
if (written === shim.bunVaddr) {
|
|
7263
|
+
throw new Error("the repack did not rewrite Bun's blob pointer \u2014 the stand-in was not used");
|
|
7264
|
+
}
|
|
7265
|
+
if (written !== bun.addr) {
|
|
7266
|
+
throw new Error(
|
|
7267
|
+
`the repack pointed Bun at 0x${written.toString(16)} but put .bun at 0x${bun.addr.toString(16)}`
|
|
7268
|
+
);
|
|
7269
|
+
}
|
|
7270
|
+
const value = Buffer.alloc(8);
|
|
7271
|
+
value.writeBigUInt64LE(written);
|
|
7272
|
+
writeSync3(fd, value, 0, 8, pointerOffset);
|
|
7273
|
+
writeSync3(fd, shim.displaced, 0, 8, standInOffset);
|
|
7274
|
+
if (!readAt2(fd, 8, pointerOffset).equals(value)) {
|
|
7275
|
+
throw new Error("Bun's blob pointer did not take the repacked address");
|
|
7276
|
+
}
|
|
7277
|
+
if (!readAt2(fd, 8, standInOffset).equals(shim.displaced)) {
|
|
7278
|
+
throw new Error("the bytes the stand-in displaced were not restored");
|
|
7279
|
+
}
|
|
7280
|
+
} finally {
|
|
7281
|
+
closeSync3(fd);
|
|
7282
|
+
}
|
|
7283
|
+
}
|
|
7284
|
+
|
|
7061
7285
|
// src/bun-bundle.ts
|
|
7062
|
-
import { closeSync as
|
|
7286
|
+
import { closeSync as closeSync4, openSync as openSync4, readSync as readSync3, writeSync as writeSync4 } from "fs";
|
|
7063
7287
|
function writableModuleIndex(path) {
|
|
7064
7288
|
const table = readBunModuleTable(path);
|
|
7065
7289
|
if (!table) return null;
|
|
@@ -7175,18 +7399,18 @@ function placeholderOf(byteLength) {
|
|
|
7175
7399
|
return PLACEHOLDER_TEXT.repeat(Math.ceil(byteLength / PLACEHOLDER_TEXT.length)).slice(0, byteLength);
|
|
7176
7400
|
}
|
|
7177
7401
|
function readBlobData(path, table, into) {
|
|
7178
|
-
const fd =
|
|
7402
|
+
const fd = openSync4(path, "r");
|
|
7179
7403
|
try {
|
|
7180
7404
|
let read = 0;
|
|
7181
7405
|
while (read < table.byteCount) {
|
|
7182
|
-
const got =
|
|
7406
|
+
const got = readSync3(fd, into, read, table.byteCount - read, table.blobAt + read);
|
|
7183
7407
|
if (got <= 0) {
|
|
7184
7408
|
throw new Error(`read ${read} of the ${table.byteCount} blob bytes of ${path}`);
|
|
7185
7409
|
}
|
|
7186
7410
|
read += got;
|
|
7187
7411
|
}
|
|
7188
7412
|
} finally {
|
|
7189
|
-
|
|
7413
|
+
closeSync4(fd);
|
|
7190
7414
|
}
|
|
7191
7415
|
}
|
|
7192
7416
|
function repointModule(data, table, append) {
|
|
@@ -7238,7 +7462,7 @@ function applyBundleWritePlan(path, plan) {
|
|
|
7238
7462
|
}
|
|
7239
7463
|
const offsets = Buffer.from(plan.offsets);
|
|
7240
7464
|
offsets.writeBigUInt64LE(BigInt(byteCount), 0);
|
|
7241
|
-
const fd =
|
|
7465
|
+
const fd = openSync4(path, "r+");
|
|
7242
7466
|
try {
|
|
7243
7467
|
writeAll(fd, plan.data, repacked.blobAt, path);
|
|
7244
7468
|
const padding = byteCount - plan.data.length;
|
|
@@ -7246,7 +7470,7 @@ function applyBundleWritePlan(path, plan) {
|
|
|
7246
7470
|
writeAll(fd, offsets, repacked.blobAt + byteCount, path);
|
|
7247
7471
|
writeAll(fd, BUN_TRAILER2, repacked.blobAt + byteCount + BUN_OFFSETS_BYTES2, path);
|
|
7248
7472
|
} finally {
|
|
7249
|
-
|
|
7473
|
+
closeSync4(fd);
|
|
7250
7474
|
}
|
|
7251
7475
|
const published = readBunModuleTable(path);
|
|
7252
7476
|
if (!published) throw new Error(`cannot re-read the Bun module table of ${path} after publishing its blob`);
|
|
@@ -7274,7 +7498,7 @@ function applyBundleWritePlan(path, plan) {
|
|
|
7274
7498
|
function writeAll(fd, bytes, position, path) {
|
|
7275
7499
|
let written = 0;
|
|
7276
7500
|
while (written < bytes.length) {
|
|
7277
|
-
const wrote =
|
|
7501
|
+
const wrote = writeSync4(fd, bytes, written, bytes.length - written, position + written);
|
|
7278
7502
|
if (wrote <= 0) throw new Error(`wrote ${written} of ${bytes.length} blob bytes to ${path}`);
|
|
7279
7503
|
written += wrote;
|
|
7280
7504
|
}
|
|
@@ -10160,7 +10384,7 @@ function thinkingProviderOptions(npm) {
|
|
|
10160
10384
|
|
|
10161
10385
|
// src/proxy.ts
|
|
10162
10386
|
import { createServer } from "http";
|
|
10163
|
-
import { appendFileSync as appendFileSync2, openSync as
|
|
10387
|
+
import { appendFileSync as appendFileSync2, openSync as openSync5, writeSync as writeSync5, closeSync as closeSync5 } from "fs";
|
|
10164
10388
|
|
|
10165
10389
|
// src/http-utils.ts
|
|
10166
10390
|
import * as zlib from "zlib";
|
|
@@ -10736,6 +10960,18 @@ function upstreamMaxRetries(env = process.env, warn = (message) => emitParentNot
|
|
|
10736
10960
|
}
|
|
10737
10961
|
return value;
|
|
10738
10962
|
}
|
|
10963
|
+
var CLIENT_MAX_RETRIES_ENV = "CLAUDE_CODE_MAX_RETRIES";
|
|
10964
|
+
var DEFAULT_PASSTHROUGH_RETRIES = 1;
|
|
10965
|
+
function passthroughUpstreamRetries(env = process.env) {
|
|
10966
|
+
const explicit = upstreamMaxRetries(env);
|
|
10967
|
+
if (explicit !== void 0) return explicit;
|
|
10968
|
+
const raw = env[CLIENT_MAX_RETRIES_ENV]?.trim();
|
|
10969
|
+
if (raw !== void 0 && raw !== "") {
|
|
10970
|
+
const clientRetries = Number(raw);
|
|
10971
|
+
if (Number.isFinite(clientRetries) && clientRetries === 0) return 0;
|
|
10972
|
+
}
|
|
10973
|
+
return DEFAULT_PASSTHROUGH_RETRIES;
|
|
10974
|
+
}
|
|
10739
10975
|
|
|
10740
10976
|
// src/sdk-adapter.ts
|
|
10741
10977
|
function sdkTranslationErrorSignature(error) {
|
|
@@ -11635,12 +11871,12 @@ function createTranslationLifecycle(logPath, requestId, claudeSessionId, modelId
|
|
|
11635
11871
|
function appendSecureLog(logPath, line) {
|
|
11636
11872
|
const redacted = redactTraceLine(line);
|
|
11637
11873
|
try {
|
|
11638
|
-
const fd =
|
|
11874
|
+
const fd = openSync5(logPath, "a", 384);
|
|
11639
11875
|
try {
|
|
11640
|
-
|
|
11876
|
+
writeSync5(fd, `${(/* @__PURE__ */ new Date()).toISOString()} ${redacted}
|
|
11641
11877
|
`);
|
|
11642
11878
|
} finally {
|
|
11643
|
-
|
|
11879
|
+
closeSync5(fd);
|
|
11644
11880
|
}
|
|
11645
11881
|
} catch {
|
|
11646
11882
|
try {
|
|
@@ -12503,10 +12739,10 @@ function tryAcquirePatchLock(lockPath = getPatchLockPath(), opts = {}) {
|
|
|
12503
12739
|
mkdirSync5(join7(lockPath, ".."), { recursive: true, mode: 448 });
|
|
12504
12740
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
12505
12741
|
try {
|
|
12506
|
-
const fd =
|
|
12742
|
+
const fd = openSync6(lockPath, "wx");
|
|
12507
12743
|
const content = { pid: process.pid, startedAt: now };
|
|
12508
12744
|
writeFileSync5(fd, JSON.stringify(content));
|
|
12509
|
-
|
|
12745
|
+
closeSync6(fd);
|
|
12510
12746
|
return () => {
|
|
12511
12747
|
try {
|
|
12512
12748
|
unlinkSync3(lockPath);
|
|
@@ -12766,11 +13002,15 @@ async function applyPatch(binaryPath, version, desired, configHash, opts) {
|
|
|
12766
13002
|
splitBundleSource(loaded.bundle, local.content),
|
|
12767
13003
|
writable
|
|
12768
13004
|
);
|
|
13005
|
+
const bunPointerShim = shimBunCompiledPointer(candidatePath);
|
|
12769
13006
|
await writeContent(loaded.installation, plan2.content);
|
|
13007
|
+
if (bunPointerShim) restoreBunCompiledPointer(candidatePath, bunPointerShim);
|
|
12770
13008
|
applyBundleWritePlan(candidatePath, plan2);
|
|
12771
13009
|
publishedBlob = true;
|
|
12772
13010
|
} else {
|
|
13011
|
+
const bunPointerShim = shimBunCompiledPointer(candidatePath);
|
|
12773
13012
|
await writeContent(loaded.installation, local.content);
|
|
13013
|
+
if (bunPointerShim) restoreBunCompiledPointer(candidatePath, bunPointerShim);
|
|
12774
13014
|
}
|
|
12775
13015
|
if (writeShim) restoreEntryModuleName(candidatePath, writeShim, { resign: true });
|
|
12776
13016
|
else if (publishedBlob) resignMachOBinary(candidatePath);
|
|
@@ -13291,13 +13531,13 @@ function localProvidersToServerModels(localProviders) {
|
|
|
13291
13531
|
// src/registry/credential-cleanup-journal.ts
|
|
13292
13532
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
13293
13533
|
import {
|
|
13294
|
-
closeSync as
|
|
13534
|
+
closeSync as closeSync7,
|
|
13295
13535
|
existsSync as existsSync6,
|
|
13296
|
-
fstatSync,
|
|
13536
|
+
fstatSync as fstatSync2,
|
|
13297
13537
|
fsyncSync as fsyncSync2,
|
|
13298
13538
|
lstatSync,
|
|
13299
13539
|
mkdirSync as mkdirSync6,
|
|
13300
|
-
openSync as
|
|
13540
|
+
openSync as openSync7,
|
|
13301
13541
|
readFileSync as readFileSync9,
|
|
13302
13542
|
renameSync as renameSync3,
|
|
13303
13543
|
unlinkSync as unlinkSync4,
|
|
@@ -13389,8 +13629,8 @@ function readJournalUnlocked(path) {
|
|
|
13389
13629
|
if (before.isSymbolicLink() || !before.isFile()) {
|
|
13390
13630
|
throw new Error("Credential cleanup journal must be a regular file.");
|
|
13391
13631
|
}
|
|
13392
|
-
fd =
|
|
13393
|
-
const opened =
|
|
13632
|
+
fd = openSync7(path, "r");
|
|
13633
|
+
const opened = fstatSync2(fd);
|
|
13394
13634
|
if (before.dev !== opened.dev || before.ino !== opened.ino) {
|
|
13395
13635
|
throw new Error("Credential cleanup journal changed while opening.");
|
|
13396
13636
|
}
|
|
@@ -13410,19 +13650,19 @@ function readJournalUnlocked(path) {
|
|
|
13410
13650
|
const message = error instanceof Error ? error.message : String(error);
|
|
13411
13651
|
throw new Error(`Could not read credential cleanup journal: ${message}`);
|
|
13412
13652
|
} finally {
|
|
13413
|
-
if (fd !== void 0)
|
|
13653
|
+
if (fd !== void 0) closeSync7(fd);
|
|
13414
13654
|
}
|
|
13415
13655
|
}
|
|
13416
13656
|
function syncParentDirectory(path) {
|
|
13417
13657
|
let fd;
|
|
13418
13658
|
try {
|
|
13419
|
-
fd =
|
|
13659
|
+
fd = openSync7(dirname4(path), "r");
|
|
13420
13660
|
fsyncSync2(fd);
|
|
13421
13661
|
} catch (error) {
|
|
13422
13662
|
const code = error.code;
|
|
13423
13663
|
if (code !== "EINVAL" && code !== "ENOTSUP" && code !== "EPERM") throw error;
|
|
13424
13664
|
} finally {
|
|
13425
|
-
if (fd !== void 0)
|
|
13665
|
+
if (fd !== void 0) closeSync7(fd);
|
|
13426
13666
|
}
|
|
13427
13667
|
}
|
|
13428
13668
|
function writeJournalUnlocked(journal, path) {
|
|
@@ -13432,17 +13672,17 @@ function writeJournalUnlocked(journal, path) {
|
|
|
13432
13672
|
const tmp = `${path}.${process.pid}.${randomUUID4()}.tmp`;
|
|
13433
13673
|
let fd;
|
|
13434
13674
|
try {
|
|
13435
|
-
fd =
|
|
13675
|
+
fd = openSync7(tmp, "wx", FILE_MODE4);
|
|
13436
13676
|
writeFileSync6(fd, `${JSON.stringify(journal, null, 2)}
|
|
13437
13677
|
`);
|
|
13438
13678
|
fsyncSync2(fd);
|
|
13439
|
-
|
|
13679
|
+
closeSync7(fd);
|
|
13440
13680
|
fd = void 0;
|
|
13441
13681
|
assertRegistryWriteOwnership(path);
|
|
13442
13682
|
renameSync3(tmp, path);
|
|
13443
13683
|
syncParentDirectory(path);
|
|
13444
13684
|
} finally {
|
|
13445
|
-
if (fd !== void 0)
|
|
13685
|
+
if (fd !== void 0) closeSync7(fd);
|
|
13446
13686
|
try {
|
|
13447
13687
|
unlinkSync4(tmp);
|
|
13448
13688
|
} catch (error) {
|
|
@@ -17391,20 +17631,37 @@ function ensureHttpProxyCertificates() {
|
|
|
17391
17631
|
serverKey: readFileSync10(paths.serverKey, "utf8")
|
|
17392
17632
|
};
|
|
17393
17633
|
}
|
|
17394
|
-
function ensureHttpProxyCaBundle(relayCaCertPath, additionalCaCertPath) {
|
|
17634
|
+
function ensureHttpProxyCaBundle(relayCaCertPath, additionalCaCertPath, onWarning) {
|
|
17395
17635
|
if (!additionalCaCertPath?.trim()) return relayCaCertPath;
|
|
17636
|
+
const warn = (detail) => {
|
|
17637
|
+
onWarning?.(
|
|
17638
|
+
`${detail} The CA bundle handed to the child is ${relayCaCertPath}; node's built-in roots are unaffected.`
|
|
17639
|
+
);
|
|
17640
|
+
return relayCaCertPath;
|
|
17641
|
+
};
|
|
17642
|
+
let additionalCa;
|
|
17396
17643
|
try {
|
|
17397
17644
|
if (resolve2(additionalCaCertPath) === resolve2(relayCaCertPath)) return relayCaCertPath;
|
|
17645
|
+
additionalCa = readFileSync10(additionalCaCertPath, "utf8").trim();
|
|
17646
|
+
} catch (err) {
|
|
17647
|
+
return warn(
|
|
17648
|
+
`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.`
|
|
17649
|
+
);
|
|
17650
|
+
}
|
|
17651
|
+
if (!additionalCa) {
|
|
17652
|
+
return warn(`NODE_EXTRA_CA_CERTS=${additionalCaCertPath} is empty, so it adds nothing.`);
|
|
17653
|
+
}
|
|
17654
|
+
try {
|
|
17398
17655
|
const relayCa = readFileSync10(relayCaCertPath, "utf8").trimEnd();
|
|
17399
|
-
const additionalCa = readFileSync10(additionalCaCertPath, "utf8").trim();
|
|
17400
|
-
if (!additionalCa) return relayCaCertPath;
|
|
17401
17656
|
const combinedPath = join8(dirname5(relayCaCertPath), "combined-ca.pem");
|
|
17402
17657
|
writePublic(combinedPath, `${relayCa}
|
|
17403
17658
|
${additionalCa}
|
|
17404
17659
|
`);
|
|
17405
17660
|
return combinedPath;
|
|
17406
|
-
} catch {
|
|
17407
|
-
return
|
|
17661
|
+
} catch (err) {
|
|
17662
|
+
return warn(
|
|
17663
|
+
`clodex could not build the combined CA bundle in ${dirname5(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.`
|
|
17664
|
+
);
|
|
17408
17665
|
}
|
|
17409
17666
|
}
|
|
17410
17667
|
|
|
@@ -17413,6 +17670,16 @@ var ANTHROPIC_HOST = "api.anthropic.com";
|
|
|
17413
17670
|
var MAX_BODY_BYTES = 50 * 1024 * 1024;
|
|
17414
17671
|
var MAX_ERROR_BODY_BYTES = 64 * 1024;
|
|
17415
17672
|
var MAX_USAGE_SSE_BLOCK_BYTES = 64 * 1024;
|
|
17673
|
+
var RETRYABLE_PASSTHROUGH_CODE = "ECONNRESET";
|
|
17674
|
+
function upstreamUnreachableDetail(err) {
|
|
17675
|
+
return err.message || err.code || err.name || "connection failed";
|
|
17676
|
+
}
|
|
17677
|
+
function createPassthroughAgent() {
|
|
17678
|
+
return new https.Agent({
|
|
17679
|
+
keepAlive: true,
|
|
17680
|
+
timeout: https.globalAgent.options.timeout ?? 5e3
|
|
17681
|
+
});
|
|
17682
|
+
}
|
|
17416
17683
|
function numericUsage(value) {
|
|
17417
17684
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
17418
17685
|
}
|
|
@@ -17561,6 +17828,7 @@ function requestHeadersWithoutProxyHeaders(req) {
|
|
|
17561
17828
|
function forwardRawAnthropicRequest(req, res, rawBody, origin, rejectUnauthorized, agent, onErrorResponse, onResponseUsage, lifecycle, isLocalShutdown = () => false) {
|
|
17562
17829
|
return new Promise((resolve3) => {
|
|
17563
17830
|
const startedAt = Date.now();
|
|
17831
|
+
const retryBudget = passthroughUpstreamRetries();
|
|
17564
17832
|
let lastActivityAt = startedAt;
|
|
17565
17833
|
let headersReceived = false;
|
|
17566
17834
|
let firstByteAt;
|
|
@@ -17610,42 +17878,91 @@ function forwardRawAnthropicRequest(req, res, rawBody, origin, rejectUnauthorize
|
|
|
17610
17878
|
resolve3();
|
|
17611
17879
|
};
|
|
17612
17880
|
const errorType = (err) => err.code ?? err.name;
|
|
17613
|
-
|
|
17614
|
-
|
|
17615
|
-
|
|
17616
|
-
|
|
17617
|
-
|
|
17618
|
-
|
|
17619
|
-
|
|
17620
|
-
|
|
17621
|
-
|
|
17622
|
-
|
|
17623
|
-
|
|
17624
|
-
|
|
17625
|
-
|
|
17626
|
-
|
|
17627
|
-
|
|
17628
|
-
|
|
17629
|
-
|
|
17630
|
-
|
|
17631
|
-
|
|
17881
|
+
let upstream;
|
|
17882
|
+
let attempt = 0;
|
|
17883
|
+
const isRetryableUpstreamFailure = (err, request3) => attempt <= retryBudget && !headersReceived && !failed && !clientDisconnected && !isLocalShutdown() && request3.reusedSocket === true && err.code === RETRYABLE_PASSTHROUGH_CODE;
|
|
17884
|
+
const sendAttempt = () => {
|
|
17885
|
+
attempt += 1;
|
|
17886
|
+
const request3 = https.request({
|
|
17887
|
+
protocol: "https:",
|
|
17888
|
+
hostname: origin.hostname,
|
|
17889
|
+
port: origin.port || 443,
|
|
17890
|
+
method: req.method,
|
|
17891
|
+
path: req.url,
|
|
17892
|
+
headers: requestHeadersWithoutProxyHeaders(req),
|
|
17893
|
+
servername: net.isIP(origin.hostname) ? void 0 : origin.hostname,
|
|
17894
|
+
rejectUnauthorized,
|
|
17895
|
+
agent
|
|
17896
|
+
}, (upstreamRes) => {
|
|
17897
|
+
headersReceived = true;
|
|
17898
|
+
statusCode = upstreamRes.statusCode ?? 502;
|
|
17899
|
+
lastActivityAt = Date.now();
|
|
17900
|
+
upstreamRes.on("data", (chunk) => {
|
|
17901
|
+
const now = Date.now();
|
|
17902
|
+
if (firstByteAt === void 0) {
|
|
17903
|
+
firstByteAt = now;
|
|
17904
|
+
writeLifecycle("response_started", {
|
|
17905
|
+
statusCode,
|
|
17906
|
+
durationMs: now - startedAt,
|
|
17907
|
+
timeToFirstByteMs: now - startedAt,
|
|
17908
|
+
...attempt > 1 ? { attempt } : {}
|
|
17909
|
+
});
|
|
17910
|
+
}
|
|
17911
|
+
lastActivityAt = now;
|
|
17912
|
+
bytes += chunk.length;
|
|
17913
|
+
chunks += 1;
|
|
17914
|
+
});
|
|
17915
|
+
copyResponse(upstreamRes, res, onErrorResponse, onResponseUsage);
|
|
17916
|
+
upstreamRes.once("end", () => {
|
|
17917
|
+
responseEnded = true;
|
|
17918
|
+
lastActivityAt = Date.now();
|
|
17919
|
+
done();
|
|
17920
|
+
});
|
|
17921
|
+
upstreamRes.once("error", (err) => {
|
|
17922
|
+
if (clientDisconnected || failed) {
|
|
17923
|
+
done();
|
|
17924
|
+
return;
|
|
17925
|
+
}
|
|
17926
|
+
failed = true;
|
|
17927
|
+
stopProgress();
|
|
17928
|
+
const now = Date.now();
|
|
17929
|
+
writeLifecycle("response_failed", {
|
|
17632
17930
|
statusCode,
|
|
17931
|
+
phase: responsePhase(),
|
|
17633
17932
|
durationMs: now - startedAt,
|
|
17634
|
-
timeToFirstByteMs:
|
|
17933
|
+
...firstByteAt !== void 0 ? { timeToFirstByteMs: firstByteAt - startedAt } : {},
|
|
17934
|
+
idleMs: now - lastActivityAt,
|
|
17935
|
+
bytes,
|
|
17936
|
+
chunks,
|
|
17937
|
+
errorType: errorType(err),
|
|
17938
|
+
terminationSource: "upstream_failure",
|
|
17939
|
+
attempt
|
|
17635
17940
|
});
|
|
17636
|
-
|
|
17637
|
-
|
|
17638
|
-
bytes += chunk.length;
|
|
17639
|
-
chunks += 1;
|
|
17640
|
-
});
|
|
17641
|
-
copyResponse(upstreamRes, res, onErrorResponse, onResponseUsage);
|
|
17642
|
-
upstreamRes.once("end", () => {
|
|
17643
|
-
responseEnded = true;
|
|
17644
|
-
lastActivityAt = Date.now();
|
|
17645
|
-
done();
|
|
17941
|
+
done();
|
|
17942
|
+
});
|
|
17646
17943
|
});
|
|
17647
|
-
|
|
17648
|
-
|
|
17944
|
+
upstream = request3;
|
|
17945
|
+
request3.once("error", (err) => {
|
|
17946
|
+
if (clientDisconnected) {
|
|
17947
|
+
done();
|
|
17948
|
+
return;
|
|
17949
|
+
}
|
|
17950
|
+
if (isRetryableUpstreamFailure(err, request3)) {
|
|
17951
|
+
const retriedAt = Date.now();
|
|
17952
|
+
writeLifecycle("response_retried", {
|
|
17953
|
+
phase: responsePhase(),
|
|
17954
|
+
durationMs: retriedAt - startedAt,
|
|
17955
|
+
idleMs: retriedAt - lastActivityAt,
|
|
17956
|
+
errorType: errorType(err),
|
|
17957
|
+
terminationSource: "upstream_failure",
|
|
17958
|
+
attempt,
|
|
17959
|
+
reusedSocket: true
|
|
17960
|
+
});
|
|
17961
|
+
lastActivityAt = retriedAt;
|
|
17962
|
+
sendAttempt();
|
|
17963
|
+
return;
|
|
17964
|
+
}
|
|
17965
|
+
if (failed) {
|
|
17649
17966
|
done();
|
|
17650
17967
|
return;
|
|
17651
17968
|
}
|
|
@@ -17653,19 +17970,25 @@ function forwardRawAnthropicRequest(req, res, rawBody, origin, rejectUnauthorize
|
|
|
17653
17970
|
stopProgress();
|
|
17654
17971
|
const now = Date.now();
|
|
17655
17972
|
writeLifecycle("response_failed", {
|
|
17656
|
-
statusCode,
|
|
17973
|
+
statusCode: 502,
|
|
17657
17974
|
phase: responsePhase(),
|
|
17658
17975
|
durationMs: now - startedAt,
|
|
17659
|
-
...firstByteAt !== void 0 ? { timeToFirstByteMs: firstByteAt - startedAt } : {},
|
|
17660
17976
|
idleMs: now - lastActivityAt,
|
|
17661
17977
|
bytes,
|
|
17662
17978
|
chunks,
|
|
17663
17979
|
errorType: errorType(err),
|
|
17664
|
-
terminationSource: "upstream_failure"
|
|
17980
|
+
terminationSource: isLocalShutdown() ? "local_shutdown" : "upstream_failure",
|
|
17981
|
+
attempt,
|
|
17982
|
+
reusedSocket: request3.reusedSocket === true
|
|
17665
17983
|
});
|
|
17984
|
+
const detail = upstreamUnreachableDetail(err);
|
|
17985
|
+
onErrorResponse?.(502, `Anthropic upstream unreachable: ${detail}`);
|
|
17986
|
+
if (!res.headersSent) res.writeHead(502, { "Content-Type": "text/plain" });
|
|
17987
|
+
res.end(`Anthropic upstream unreachable: ${detail}`);
|
|
17666
17988
|
done();
|
|
17667
17989
|
});
|
|
17668
|
-
|
|
17990
|
+
request3.end(rawBody);
|
|
17991
|
+
};
|
|
17669
17992
|
res.once("finish", () => {
|
|
17670
17993
|
stopProgress();
|
|
17671
17994
|
if (failed || clientDisconnected) return;
|
|
@@ -17675,7 +17998,8 @@ function forwardRawAnthropicRequest(req, res, rawBody, origin, rejectUnauthorize
|
|
|
17675
17998
|
durationMs: now - startedAt,
|
|
17676
17999
|
...firstByteAt !== void 0 ? { timeToFirstByteMs: firstByteAt - startedAt } : {},
|
|
17677
18000
|
bytes,
|
|
17678
|
-
chunks
|
|
18001
|
+
chunks,
|
|
18002
|
+
...attempt > 1 ? { attempt } : {}
|
|
17679
18003
|
});
|
|
17680
18004
|
});
|
|
17681
18005
|
res.once("close", () => {
|
|
@@ -17693,33 +18017,10 @@ function forwardRawAnthropicRequest(req, res, rawBody, origin, rejectUnauthorize
|
|
|
17693
18017
|
chunks,
|
|
17694
18018
|
terminationSource: isLocalShutdown() ? "local_shutdown" : "downstream_client"
|
|
17695
18019
|
});
|
|
17696
|
-
upstream
|
|
17697
|
-
done();
|
|
17698
|
-
});
|
|
17699
|
-
upstream.once("error", (err) => {
|
|
17700
|
-
if (clientDisconnected) {
|
|
17701
|
-
done();
|
|
17702
|
-
return;
|
|
17703
|
-
}
|
|
17704
|
-
failed = true;
|
|
17705
|
-
stopProgress();
|
|
17706
|
-
const now = Date.now();
|
|
17707
|
-
writeLifecycle("response_failed", {
|
|
17708
|
-
statusCode: 502,
|
|
17709
|
-
phase: responsePhase(),
|
|
17710
|
-
durationMs: now - startedAt,
|
|
17711
|
-
idleMs: now - lastActivityAt,
|
|
17712
|
-
bytes,
|
|
17713
|
-
chunks,
|
|
17714
|
-
errorType: errorType(err),
|
|
17715
|
-
terminationSource: "upstream_failure"
|
|
17716
|
-
});
|
|
17717
|
-
onErrorResponse?.(502, `Anthropic upstream unreachable: ${err.message}`);
|
|
17718
|
-
if (!res.headersSent) res.writeHead(502, { "Content-Type": "text/plain" });
|
|
17719
|
-
res.end(`Anthropic upstream unreachable: ${err.message}`);
|
|
18020
|
+
upstream?.destroy(new Error("Client disconnected"));
|
|
17720
18021
|
done();
|
|
17721
18022
|
});
|
|
17722
|
-
|
|
18023
|
+
sendAttempt();
|
|
17723
18024
|
});
|
|
17724
18025
|
}
|
|
17725
18026
|
function forwardToAdapter(req, res, rawBody, adapter, adapterRequest = http2.request, adapterAgent, lifecycle, isLocalShutdown = () => false) {
|
|
@@ -18196,6 +18497,7 @@ async function startHttpProxy(options) {
|
|
|
18196
18497
|
} else {
|
|
18197
18498
|
anthropicAgent = outboundHttpProxyAgent(anthropicOrigin.href);
|
|
18198
18499
|
}
|
|
18500
|
+
anthropicAgent ??= createPassthroughAgent();
|
|
18199
18501
|
return {
|
|
18200
18502
|
host: options.host ?? "127.0.0.1",
|
|
18201
18503
|
port: address.port,
|
|
@@ -18329,11 +18631,15 @@ async function startConfiguredHttpProxy(port, debug = false, inferenceLogPath =
|
|
|
18329
18631
|
debugLogPath,
|
|
18330
18632
|
webSocketDiagnosticsLogPath
|
|
18331
18633
|
));
|
|
18634
|
+
let caWarning;
|
|
18332
18635
|
handle.caCertPath = ensureHttpProxyCaBundle(
|
|
18333
18636
|
handle.caCertPath,
|
|
18334
|
-
process.env["NODE_EXTRA_CA_CERTS"]
|
|
18637
|
+
process.env["NODE_EXTRA_CA_CERTS"],
|
|
18638
|
+
(message) => {
|
|
18639
|
+
caWarning = message;
|
|
18640
|
+
}
|
|
18335
18641
|
);
|
|
18336
|
-
return { handle, loaded };
|
|
18642
|
+
return { handle, loaded, ...caWarning ? { caWarning } : {} };
|
|
18337
18643
|
}
|
|
18338
18644
|
function waitForShutdown() {
|
|
18339
18645
|
return new Promise((resolve3) => {
|
|
@@ -18362,7 +18668,7 @@ async function runHttpProxyServerCommand(debug = false, webSocketDiagnostics = f
|
|
|
18362
18668
|
p9.log.error(`Failed to start HTTP proxy: ${err instanceof Error ? err.message : String(err)}`);
|
|
18363
18669
|
return 1;
|
|
18364
18670
|
}
|
|
18365
|
-
const { handle, loaded } = started;
|
|
18671
|
+
const { handle, loaded, caWarning } = started;
|
|
18366
18672
|
writeProxyLifecycleLog(inferenceLogPath, {
|
|
18367
18673
|
event: "proxy_started",
|
|
18368
18674
|
pid: process.pid,
|
|
@@ -18374,6 +18680,10 @@ async function runHttpProxyServerCommand(debug = false, webSocketDiagnostics = f
|
|
|
18374
18680
|
console.log(pc10.bold(pc10.green("clodex proxy-mode server running")));
|
|
18375
18681
|
for (const line of formatHttpProxyEnvironmentLines(handle)) console.log(line);
|
|
18376
18682
|
console.log(` Request log: ${handle.inferenceLogPath}`);
|
|
18683
|
+
if (caWarning) {
|
|
18684
|
+
console.log("");
|
|
18685
|
+
console.log(pc10.yellow(` clodex: ${caWarning}`));
|
|
18686
|
+
}
|
|
18377
18687
|
if (handle.webSocketDiagnosticsLogPath) {
|
|
18378
18688
|
console.log(` WebSocket diagnostics: ${handle.webSocketDiagnosticsLogPath}`);
|
|
18379
18689
|
console.log(pc10.yellow(" Diagnostic mode records request headers and metadata; credential headers are redacted."));
|
|
@@ -19959,7 +20269,11 @@ async function runClaudeHttpProxyCommand(parsed, claudeArgs, agentStdout) {
|
|
|
19959
20269
|
p12.log.error(`Failed to start proxy: ${err instanceof Error ? err.message : String(err)}`);
|
|
19960
20270
|
return 1;
|
|
19961
20271
|
}
|
|
19962
|
-
const { handle, loaded } = started;
|
|
20272
|
+
const { handle, loaded, caWarning } = started;
|
|
20273
|
+
if (caWarning) {
|
|
20274
|
+
if (agentStdout) emitParentNotice(`clodex: ${caWarning}`);
|
|
20275
|
+
else p12.log.warn(caWarning);
|
|
20276
|
+
}
|
|
19963
20277
|
const inheritedProxyPort = (() => {
|
|
19964
20278
|
const value = process.env["HTTPS_PROXY"] ?? process.env["HTTP_PROXY"] ?? process.env["https_proxy"] ?? process.env["http_proxy"];
|
|
19965
20279
|
if (!value) return void 0;
|