@vacbo/opencode-anthropic-fix 0.0.43 → 0.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bun-proxy.mjs +1 -1
- package/dist/opencode-anthropic-auth-plugin.js +133 -34
- package/package.json +1 -1
- package/src/bun-fetch.ts +155 -33
- package/src/bun-proxy.ts +1 -1
package/dist/bun-proxy.mjs
CHANGED
|
@@ -6375,12 +6375,28 @@ function formatSwitchReason(status, reason) {
|
|
|
6375
6375
|
|
|
6376
6376
|
// src/bun-fetch.ts
|
|
6377
6377
|
import { execFileSync, spawn } from "node:child_process";
|
|
6378
|
-
import { existsSync as existsSync5 } from "node:fs";
|
|
6378
|
+
import { existsSync as existsSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync5, unlinkSync } from "node:fs";
|
|
6379
6379
|
import { dirname as dirname4, join as join6 } from "node:path";
|
|
6380
|
+
import { tmpdir } from "node:os";
|
|
6380
6381
|
import { fileURLToPath } from "node:url";
|
|
6381
6382
|
var proxyPort = null;
|
|
6382
6383
|
var proxyProcess = null;
|
|
6383
6384
|
var starting = null;
|
|
6385
|
+
var healthCheckFails = 0;
|
|
6386
|
+
var FIXED_PORT = 48372;
|
|
6387
|
+
var PID_FILE = join6(tmpdir(), "opencode-bun-proxy.pid");
|
|
6388
|
+
var MAX_HEALTH_FAILS = 2;
|
|
6389
|
+
var exitHandlerRegistered = false;
|
|
6390
|
+
function registerExitHandler() {
|
|
6391
|
+
if (exitHandlerRegistered) return;
|
|
6392
|
+
exitHandlerRegistered = true;
|
|
6393
|
+
const cleanup = () => {
|
|
6394
|
+
stopBunProxy();
|
|
6395
|
+
};
|
|
6396
|
+
process.on("exit", cleanup);
|
|
6397
|
+
process.on("SIGINT", cleanup);
|
|
6398
|
+
process.on("SIGTERM", cleanup);
|
|
6399
|
+
}
|
|
6384
6400
|
function findProxyScript() {
|
|
6385
6401
|
const dir = typeof __dirname !== "undefined" ? __dirname : dirname4(fileURLToPath(import.meta.url));
|
|
6386
6402
|
for (const candidate of [
|
|
@@ -6392,45 +6408,78 @@ function findProxyScript() {
|
|
|
6392
6408
|
}
|
|
6393
6409
|
return null;
|
|
6394
6410
|
}
|
|
6411
|
+
var _hasBun = null;
|
|
6395
6412
|
function hasBun() {
|
|
6413
|
+
if (_hasBun !== null) return _hasBun;
|
|
6396
6414
|
try {
|
|
6397
6415
|
execFileSync("which", ["bun"], { stdio: "ignore" });
|
|
6398
|
-
|
|
6416
|
+
_hasBun = true;
|
|
6417
|
+
} catch {
|
|
6418
|
+
_hasBun = false;
|
|
6419
|
+
}
|
|
6420
|
+
return _hasBun;
|
|
6421
|
+
}
|
|
6422
|
+
function killStaleProxy() {
|
|
6423
|
+
try {
|
|
6424
|
+
const raw = readFileSync6(PID_FILE, "utf-8").trim();
|
|
6425
|
+
const pid = parseInt(raw, 10);
|
|
6426
|
+
if (pid > 0) {
|
|
6427
|
+
try {
|
|
6428
|
+
process.kill(pid, "SIGTERM");
|
|
6429
|
+
} catch {
|
|
6430
|
+
}
|
|
6431
|
+
}
|
|
6432
|
+
unlinkSync(PID_FILE);
|
|
6433
|
+
} catch {
|
|
6434
|
+
}
|
|
6435
|
+
}
|
|
6436
|
+
async function isProxyHealthy(port) {
|
|
6437
|
+
try {
|
|
6438
|
+
const resp = await fetch(`http://127.0.0.1:${port}/__health`, {
|
|
6439
|
+
signal: AbortSignal.timeout(2e3)
|
|
6440
|
+
});
|
|
6441
|
+
return resp.ok;
|
|
6399
6442
|
} catch {
|
|
6400
6443
|
return false;
|
|
6401
6444
|
}
|
|
6402
6445
|
}
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
if (proxyPort) return proxyPort;
|
|
6406
|
-
if (starting) return starting;
|
|
6407
|
-
starting = new Promise((resolve2) => {
|
|
6446
|
+
function spawnProxy() {
|
|
6447
|
+
return new Promise((resolve2) => {
|
|
6408
6448
|
const script = findProxyScript();
|
|
6409
6449
|
if (!script || !hasBun()) {
|
|
6410
6450
|
resolve2(null);
|
|
6411
|
-
starting = null;
|
|
6412
6451
|
return;
|
|
6413
6452
|
}
|
|
6453
|
+
killStaleProxy();
|
|
6414
6454
|
try {
|
|
6415
|
-
const child = spawn("bun", ["run", script,
|
|
6416
|
-
stdio: ["ignore", "pipe", "
|
|
6455
|
+
const child = spawn("bun", ["run", script, String(FIXED_PORT)], {
|
|
6456
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
6417
6457
|
detached: false
|
|
6418
6458
|
});
|
|
6419
6459
|
proxyProcess = child;
|
|
6460
|
+
registerExitHandler();
|
|
6420
6461
|
let done = false;
|
|
6462
|
+
const finish = (port) => {
|
|
6463
|
+
if (done) return;
|
|
6464
|
+
done = true;
|
|
6465
|
+
if (port && child.pid) {
|
|
6466
|
+
try {
|
|
6467
|
+
writeFileSync5(PID_FILE, String(child.pid));
|
|
6468
|
+
} catch {
|
|
6469
|
+
}
|
|
6470
|
+
}
|
|
6471
|
+
resolve2(port);
|
|
6472
|
+
};
|
|
6421
6473
|
child.stdout?.on("data", (chunk) => {
|
|
6422
6474
|
const m = chunk.toString().match(/BUN_PROXY_PORT=(\d+)/);
|
|
6423
|
-
if (m
|
|
6424
|
-
done = true;
|
|
6475
|
+
if (m) {
|
|
6425
6476
|
proxyPort = parseInt(m[1], 10);
|
|
6426
|
-
|
|
6477
|
+
healthCheckFails = 0;
|
|
6478
|
+
finish(proxyPort);
|
|
6427
6479
|
}
|
|
6428
6480
|
});
|
|
6429
6481
|
child.on("error", () => {
|
|
6430
|
-
|
|
6431
|
-
done = true;
|
|
6432
|
-
resolve2(null);
|
|
6433
|
-
}
|
|
6482
|
+
finish(null);
|
|
6434
6483
|
proxyPort = null;
|
|
6435
6484
|
proxyProcess = null;
|
|
6436
6485
|
starting = null;
|
|
@@ -6439,23 +6488,48 @@ async function ensureBunProxy() {
|
|
|
6439
6488
|
proxyPort = null;
|
|
6440
6489
|
proxyProcess = null;
|
|
6441
6490
|
starting = null;
|
|
6442
|
-
|
|
6443
|
-
done = true;
|
|
6444
|
-
resolve2(null);
|
|
6445
|
-
}
|
|
6491
|
+
finish(null);
|
|
6446
6492
|
});
|
|
6447
|
-
setTimeout(() =>
|
|
6448
|
-
if (!done) {
|
|
6449
|
-
done = true;
|
|
6450
|
-
resolve2(null);
|
|
6451
|
-
}
|
|
6452
|
-
}, 5e3);
|
|
6493
|
+
setTimeout(() => finish(null), 5e3);
|
|
6453
6494
|
} catch {
|
|
6454
6495
|
resolve2(null);
|
|
6455
|
-
starting = null;
|
|
6456
6496
|
}
|
|
6457
6497
|
});
|
|
6458
|
-
|
|
6498
|
+
}
|
|
6499
|
+
async function ensureBunProxy() {
|
|
6500
|
+
if (process.env.VITEST || process.env.NODE_ENV === "test") return null;
|
|
6501
|
+
if (proxyPort && proxyProcess && !proxyProcess.killed) {
|
|
6502
|
+
return proxyPort;
|
|
6503
|
+
}
|
|
6504
|
+
if (!proxyPort && await isProxyHealthy(FIXED_PORT)) {
|
|
6505
|
+
proxyPort = FIXED_PORT;
|
|
6506
|
+
console.error("[bun-fetch] Reusing existing Bun proxy on port", FIXED_PORT);
|
|
6507
|
+
return proxyPort;
|
|
6508
|
+
}
|
|
6509
|
+
if (proxyPort && (!proxyProcess || proxyProcess.killed)) {
|
|
6510
|
+
proxyPort = null;
|
|
6511
|
+
proxyProcess = null;
|
|
6512
|
+
starting = null;
|
|
6513
|
+
}
|
|
6514
|
+
if (starting) return starting;
|
|
6515
|
+
starting = spawnProxy();
|
|
6516
|
+
const port = await starting;
|
|
6517
|
+
starting = null;
|
|
6518
|
+
if (port) console.error("[bun-fetch] Bun proxy started on port", port);
|
|
6519
|
+
else console.error("[bun-fetch] Failed to start Bun proxy, falling back to Node.js fetch");
|
|
6520
|
+
return port;
|
|
6521
|
+
}
|
|
6522
|
+
function stopBunProxy() {
|
|
6523
|
+
if (proxyProcess) {
|
|
6524
|
+
try {
|
|
6525
|
+
proxyProcess.kill();
|
|
6526
|
+
} catch {
|
|
6527
|
+
}
|
|
6528
|
+
proxyProcess = null;
|
|
6529
|
+
}
|
|
6530
|
+
proxyPort = null;
|
|
6531
|
+
starting = null;
|
|
6532
|
+
killStaleProxy();
|
|
6459
6533
|
}
|
|
6460
6534
|
async function fetchViaBun(input, init) {
|
|
6461
6535
|
const port = await ensureBunProxy();
|
|
@@ -6463,11 +6537,36 @@ async function fetchViaBun(input, init) {
|
|
|
6463
6537
|
if (!port) return fetch(input, init);
|
|
6464
6538
|
const headers = new Headers(init.headers);
|
|
6465
6539
|
headers.set("x-proxy-url", url);
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
6540
|
+
try {
|
|
6541
|
+
const resp = await fetch(`http://127.0.0.1:${port}/`, {
|
|
6542
|
+
method: init.method || "POST",
|
|
6543
|
+
headers,
|
|
6544
|
+
body: init.body
|
|
6545
|
+
});
|
|
6546
|
+
if (resp.status === 502) {
|
|
6547
|
+
const errText = await resp.text();
|
|
6548
|
+
throw new Error(`Bun proxy upstream error: ${errText}`);
|
|
6549
|
+
}
|
|
6550
|
+
healthCheckFails = 0;
|
|
6551
|
+
return resp;
|
|
6552
|
+
} catch (err) {
|
|
6553
|
+
healthCheckFails++;
|
|
6554
|
+
if (healthCheckFails >= MAX_HEALTH_FAILS) {
|
|
6555
|
+
stopBunProxy();
|
|
6556
|
+
const newPort = await ensureBunProxy();
|
|
6557
|
+
if (newPort) {
|
|
6558
|
+
healthCheckFails = 0;
|
|
6559
|
+
const retryHeaders = new Headers(init.headers);
|
|
6560
|
+
retryHeaders.set("x-proxy-url", url);
|
|
6561
|
+
return fetch(`http://127.0.0.1:${newPort}/`, {
|
|
6562
|
+
method: init.method || "POST",
|
|
6563
|
+
headers: retryHeaders,
|
|
6564
|
+
body: init.body
|
|
6565
|
+
});
|
|
6566
|
+
}
|
|
6567
|
+
}
|
|
6568
|
+
throw err;
|
|
6569
|
+
}
|
|
6471
6570
|
}
|
|
6472
6571
|
|
|
6473
6572
|
// src/index.ts
|
package/package.json
CHANGED
package/src/bun-fetch.ts
CHANGED
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
|
-
// Bun TLS proxy manager — spawns a Bun subprocess for BoringSSL TLS.
|
|
2
|
+
// Bun TLS proxy manager — spawns a single Bun subprocess for BoringSSL TLS.
|
|
3
|
+
// Hardened: health checks, auto-restart, single-instance guarantee.
|
|
3
4
|
// ---------------------------------------------------------------------------
|
|
4
5
|
|
|
5
6
|
import { execFileSync, spawn } from "node:child_process";
|
|
6
|
-
import { existsSync } from "node:fs";
|
|
7
|
+
import { existsSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
|
|
7
8
|
import { dirname, join } from "node:path";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
8
10
|
import { fileURLToPath } from "node:url";
|
|
9
11
|
|
|
10
12
|
let proxyPort: number | null = null;
|
|
11
13
|
let proxyProcess: ReturnType<typeof spawn> | null = null;
|
|
12
14
|
let starting: Promise<number | null> | null = null;
|
|
15
|
+
let healthCheckFails = 0;
|
|
16
|
+
|
|
17
|
+
const FIXED_PORT = 48372;
|
|
18
|
+
const PID_FILE = join(tmpdir(), "opencode-bun-proxy.pid");
|
|
19
|
+
const MAX_HEALTH_FAILS = 2;
|
|
20
|
+
|
|
21
|
+
// Kill proxy when parent process exits
|
|
22
|
+
let exitHandlerRegistered = false;
|
|
23
|
+
function registerExitHandler(): void {
|
|
24
|
+
if (exitHandlerRegistered) return;
|
|
25
|
+
exitHandlerRegistered = true;
|
|
26
|
+
const cleanup = () => { stopBunProxy(); };
|
|
27
|
+
process.on("exit", cleanup);
|
|
28
|
+
process.on("SIGINT", cleanup);
|
|
29
|
+
process.on("SIGTERM", cleanup);
|
|
30
|
+
}
|
|
13
31
|
|
|
14
32
|
function findProxyScript(): string | null {
|
|
15
33
|
const dir = typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath(import.meta.url));
|
|
@@ -23,75 +41,147 @@ function findProxyScript(): string | null {
|
|
|
23
41
|
return null;
|
|
24
42
|
}
|
|
25
43
|
|
|
44
|
+
let _hasBun: boolean | null = null;
|
|
26
45
|
function hasBun(): boolean {
|
|
46
|
+
if (_hasBun !== null) return _hasBun;
|
|
27
47
|
try {
|
|
28
48
|
execFileSync("which", ["bun"], { stdio: "ignore" });
|
|
29
|
-
|
|
49
|
+
_hasBun = true;
|
|
30
50
|
} catch {
|
|
31
|
-
|
|
51
|
+
_hasBun = false;
|
|
32
52
|
}
|
|
53
|
+
return _hasBun;
|
|
33
54
|
}
|
|
34
55
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
56
|
+
function killStaleProxy(): void {
|
|
57
|
+
try {
|
|
58
|
+
const raw = readFileSync(PID_FILE, "utf-8").trim();
|
|
59
|
+
const pid = parseInt(raw, 10);
|
|
60
|
+
if (pid > 0) {
|
|
61
|
+
try { process.kill(pid, "SIGTERM"); } catch { /* already dead */ }
|
|
62
|
+
}
|
|
63
|
+
unlinkSync(PID_FILE);
|
|
64
|
+
} catch {
|
|
65
|
+
// No PID file or already cleaned
|
|
66
|
+
}
|
|
67
|
+
}
|
|
40
68
|
|
|
41
|
-
|
|
69
|
+
async function isProxyHealthy(port: number): Promise<boolean> {
|
|
70
|
+
try {
|
|
71
|
+
const resp = await fetch(`http://127.0.0.1:${port}/__health`, {
|
|
72
|
+
signal: AbortSignal.timeout(2000),
|
|
73
|
+
});
|
|
74
|
+
return resp.ok;
|
|
75
|
+
} catch {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function spawnProxy(): Promise<number | null> {
|
|
81
|
+
return new Promise<number | null>((resolve) => {
|
|
42
82
|
const script = findProxyScript();
|
|
43
83
|
if (!script || !hasBun()) {
|
|
44
84
|
resolve(null);
|
|
45
|
-
starting = null;
|
|
46
85
|
return;
|
|
47
86
|
}
|
|
48
87
|
|
|
88
|
+
// Kill any stale instance first
|
|
89
|
+
killStaleProxy();
|
|
90
|
+
|
|
49
91
|
try {
|
|
50
|
-
const child = spawn("bun", ["run", script,
|
|
51
|
-
stdio: ["ignore", "pipe", "
|
|
92
|
+
const child = spawn("bun", ["run", script, String(FIXED_PORT)], {
|
|
93
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
52
94
|
detached: false,
|
|
53
95
|
});
|
|
54
96
|
proxyProcess = child;
|
|
97
|
+
registerExitHandler();
|
|
55
98
|
|
|
56
99
|
let done = false;
|
|
100
|
+
const finish = (port: number | null) => {
|
|
101
|
+
if (done) return;
|
|
102
|
+
done = true;
|
|
103
|
+
if (port && child.pid) {
|
|
104
|
+
try { writeFileSync(PID_FILE, String(child.pid)); } catch { /* ok */ }
|
|
105
|
+
}
|
|
106
|
+
resolve(port);
|
|
107
|
+
};
|
|
108
|
+
|
|
57
109
|
child.stdout?.on("data", (chunk: Buffer) => {
|
|
58
110
|
const m = chunk.toString().match(/BUN_PROXY_PORT=(\d+)/);
|
|
59
|
-
if (m
|
|
60
|
-
done = true;
|
|
111
|
+
if (m) {
|
|
61
112
|
proxyPort = parseInt(m[1], 10);
|
|
62
|
-
|
|
113
|
+
healthCheckFails = 0;
|
|
114
|
+
finish(proxyPort);
|
|
63
115
|
}
|
|
64
116
|
});
|
|
117
|
+
|
|
65
118
|
child.on("error", () => {
|
|
66
|
-
|
|
67
|
-
proxyPort = null;
|
|
119
|
+
finish(null);
|
|
120
|
+
proxyPort = null;
|
|
121
|
+
proxyProcess = null;
|
|
122
|
+
starting = null;
|
|
68
123
|
});
|
|
124
|
+
|
|
69
125
|
child.on("exit", () => {
|
|
70
|
-
proxyPort = null;
|
|
71
|
-
|
|
126
|
+
proxyPort = null;
|
|
127
|
+
proxyProcess = null;
|
|
128
|
+
starting = null;
|
|
129
|
+
finish(null);
|
|
72
130
|
});
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
131
|
+
|
|
132
|
+
// Timeout
|
|
133
|
+
setTimeout(() => finish(null), 5000);
|
|
76
134
|
} catch {
|
|
77
135
|
resolve(null);
|
|
78
|
-
starting = null;
|
|
79
136
|
}
|
|
80
137
|
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export async function ensureBunProxy(): Promise<number | null> {
|
|
141
|
+
if (process.env.VITEST || process.env.NODE_ENV === "test") return null;
|
|
142
|
+
|
|
143
|
+
// Fast path: proxy already running and healthy
|
|
144
|
+
if (proxyPort && proxyProcess && !proxyProcess.killed) {
|
|
145
|
+
return proxyPort;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Check if a proxy is already running on the fixed port (from previous session)
|
|
149
|
+
if (!proxyPort && await isProxyHealthy(FIXED_PORT)) {
|
|
150
|
+
proxyPort = FIXED_PORT;
|
|
151
|
+
console.error("[bun-fetch] Reusing existing Bun proxy on port", FIXED_PORT);
|
|
152
|
+
return proxyPort;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Restart if previous instance died
|
|
156
|
+
if (proxyPort && (!proxyProcess || proxyProcess.killed)) {
|
|
157
|
+
proxyPort = null;
|
|
158
|
+
proxyProcess = null;
|
|
159
|
+
starting = null;
|
|
160
|
+
}
|
|
81
161
|
|
|
82
|
-
return starting;
|
|
162
|
+
if (starting) return starting;
|
|
163
|
+
|
|
164
|
+
starting = spawnProxy();
|
|
165
|
+
const port = await starting;
|
|
166
|
+
starting = null;
|
|
167
|
+
if (port) console.error("[bun-fetch] Bun proxy started on port", port);
|
|
168
|
+
else console.error("[bun-fetch] Failed to start Bun proxy, falling back to Node.js fetch");
|
|
169
|
+
return port;
|
|
83
170
|
}
|
|
84
171
|
|
|
85
172
|
export function stopBunProxy(): void {
|
|
86
173
|
if (proxyProcess) {
|
|
87
|
-
try { proxyProcess.kill(); } catch { /*
|
|
88
|
-
proxyProcess = null;
|
|
174
|
+
try { proxyProcess.kill(); } catch { /* */ }
|
|
175
|
+
proxyProcess = null;
|
|
89
176
|
}
|
|
177
|
+
proxyPort = null;
|
|
178
|
+
starting = null;
|
|
179
|
+
killStaleProxy();
|
|
90
180
|
}
|
|
91
181
|
|
|
92
182
|
/**
|
|
93
183
|
* Fetch via Bun proxy for BoringSSL TLS fingerprint.
|
|
94
|
-
* Falls back to native
|
|
184
|
+
* Auto-restarts proxy on failure. Falls back to native fetch only if Bun is unavailable.
|
|
95
185
|
*/
|
|
96
186
|
export async function fetchViaBun(
|
|
97
187
|
input: string | URL | Request,
|
|
@@ -105,9 +195,41 @@ export async function fetchViaBun(
|
|
|
105
195
|
const headers = new Headers(init.headers);
|
|
106
196
|
headers.set("x-proxy-url", url);
|
|
107
197
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
198
|
+
try {
|
|
199
|
+
const resp = await fetch(`http://127.0.0.1:${port}/`, {
|
|
200
|
+
method: init.method || "POST",
|
|
201
|
+
headers,
|
|
202
|
+
body: init.body,
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// Proxy returned a 502 — Bun proxy couldn't reach Anthropic
|
|
206
|
+
if (resp.status === 502) {
|
|
207
|
+
const errText = await resp.text();
|
|
208
|
+
throw new Error(`Bun proxy upstream error: ${errText}`);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
healthCheckFails = 0;
|
|
212
|
+
return resp;
|
|
213
|
+
} catch (err) {
|
|
214
|
+
healthCheckFails++;
|
|
215
|
+
|
|
216
|
+
// If proxy seems dead, restart it and retry once
|
|
217
|
+
if (healthCheckFails >= MAX_HEALTH_FAILS) {
|
|
218
|
+
stopBunProxy();
|
|
219
|
+
const newPort = await ensureBunProxy();
|
|
220
|
+
if (newPort) {
|
|
221
|
+
healthCheckFails = 0;
|
|
222
|
+
const retryHeaders = new Headers(init.headers);
|
|
223
|
+
retryHeaders.set("x-proxy-url", url);
|
|
224
|
+
return fetch(`http://127.0.0.1:${newPort}/`, {
|
|
225
|
+
method: init.method || "POST",
|
|
226
|
+
headers: retryHeaders,
|
|
227
|
+
body: init.body,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Final fallback: native fetch (will use Node TLS — not ideal but better than failing)
|
|
233
|
+
throw err;
|
|
234
|
+
}
|
|
113
235
|
}
|
package/src/bun-proxy.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Standalone Bun TLS proxy — run with: bun dist/bun-proxy.mjs [port]
|
|
2
2
|
// Forwards requests using Bun's native fetch (BoringSSL TLS fingerprint).
|
|
3
3
|
|
|
4
|
-
const PORT = parseInt(process.argv[2] || "
|
|
4
|
+
const PORT = parseInt(process.argv[2] || "48372", 10);
|
|
5
5
|
|
|
6
6
|
const server = Bun.serve({
|
|
7
7
|
port: PORT,
|