@simonyea/holysheep-cli 2.1.76 → 2.1.78
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/configure-worker.js +140 -32
- package/dist/index.js +167 -33
- package/dist/process-proxy-inject.js +55 -8
- package/package.json +2 -2
package/dist/configure-worker.js
CHANGED
|
@@ -115,6 +115,34 @@ var require_claude_process_proxy = __commonJS({
|
|
|
115
115
|
var ENABLE_TIMING_LOG = process.env.HS_CLAUDE_TIMING_LOG === "1";
|
|
116
116
|
var SLOW_PATH_LOG_MS = Number(process.env.HS_CLAUDE_SLOW_PATH_LOG_MS) || 5e3;
|
|
117
117
|
var ENABLE_LEASE_LOG = process.env.HS_CLAUDE_LEASE_LOG === "1";
|
|
118
|
+
function positiveInt(value, fallback) {
|
|
119
|
+
const n = Number(value);
|
|
120
|
+
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
121
|
+
}
|
|
122
|
+
__name(positiveInt, "positiveInt");
|
|
123
|
+
var LEASE_OPEN_TIMEOUT_MS = positiveInt(process.env.HS_CLAUDE_LEASE_OPEN_TIMEOUT_MS, 15e3);
|
|
124
|
+
var LEASE_CLOSE_TIMEOUT_MS = positiveInt(process.env.HS_CLAUDE_LEASE_CLOSE_TIMEOUT_MS, 5e3);
|
|
125
|
+
async function fetchWithTimeout(url, options, timeoutMs, label, consume = (response) => response) {
|
|
126
|
+
const controller = typeof AbortController === "function" ? new AbortController() : null;
|
|
127
|
+
const timer = controller ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
128
|
+
if (timer && typeof timer.unref === "function") timer.unref();
|
|
129
|
+
try {
|
|
130
|
+
const requestOptions = controller ? { ...options, signal: controller.signal } : { ...options, timeout: timeoutMs };
|
|
131
|
+
const response = await fetch(url, requestOptions);
|
|
132
|
+
return await consume(response);
|
|
133
|
+
} catch (err) {
|
|
134
|
+
const aborted = err && (err.name === "AbortError" || err.type === "aborted");
|
|
135
|
+
if (aborted) {
|
|
136
|
+
const timeoutErr = new Error(`${label} timed out after ${timeoutMs}ms`);
|
|
137
|
+
timeoutErr.code = "ETIMEDOUT";
|
|
138
|
+
throw timeoutErr;
|
|
139
|
+
}
|
|
140
|
+
throw err;
|
|
141
|
+
} finally {
|
|
142
|
+
if (timer) clearTimeout(timer);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
__name(fetchWithTimeout, "fetchWithTimeout");
|
|
118
146
|
function sanitizeUrl(value) {
|
|
119
147
|
if (!value) return "";
|
|
120
148
|
try {
|
|
@@ -201,19 +229,27 @@ var require_claude_process_proxy = __commonJS({
|
|
|
201
229
|
const controlPlaneUrl = getControlPlaneUrl(config);
|
|
202
230
|
if (!controlPlaneUrl) throw new Error("Claude relay control plane is not configured");
|
|
203
231
|
const startedAt = Date.now();
|
|
204
|
-
const response = await
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
232
|
+
const { response, payload } = await fetchWithTimeout(
|
|
233
|
+
`${controlPlaneUrl}/session/open`,
|
|
234
|
+
{
|
|
235
|
+
method: "POST",
|
|
236
|
+
headers: { "content-type": "application/json" },
|
|
237
|
+
body: JSON.stringify({
|
|
238
|
+
sessionId,
|
|
239
|
+
bridgeId: config.bridgeId || "local-bridge",
|
|
240
|
+
deviceId: config.deviceId || "",
|
|
241
|
+
installSource: config.installSource || "holysheep-cli",
|
|
242
|
+
proxyMode: "claude-process",
|
|
243
|
+
forceReassign: options.forceReassign === true
|
|
244
|
+
})
|
|
245
|
+
},
|
|
246
|
+
LEASE_OPEN_TIMEOUT_MS,
|
|
247
|
+
"Claude relay session open",
|
|
248
|
+
async (response2) => ({
|
|
249
|
+
response: response2,
|
|
250
|
+
payload: await response2.json().catch(() => null)
|
|
214
251
|
})
|
|
215
|
-
|
|
216
|
-
const payload = await response.json().catch(() => null);
|
|
252
|
+
);
|
|
217
253
|
if (!response.ok || !(payload == null ? void 0 : payload.success) || !((_a = payload == null ? void 0 : payload.data) == null ? void 0 : _a.ticket)) {
|
|
218
254
|
throw new Error(((_b = payload == null ? void 0 : payload.error) == null ? void 0 : _b.message) || `Failed to open Claude session (HTTP ${response.status})`);
|
|
219
255
|
}
|
|
@@ -302,7 +338,53 @@ var require_claude_process_proxy = __commonJS({
|
|
|
302
338
|
})}`
|
|
303
339
|
);
|
|
304
340
|
}
|
|
305
|
-
|
|
341
|
+
let settled = false;
|
|
342
|
+
let responseTimer = null;
|
|
343
|
+
let stallTimer = null;
|
|
344
|
+
let upReq = null;
|
|
345
|
+
let upResRef = null;
|
|
346
|
+
const clearResponseTimer = /* @__PURE__ */ __name(() => {
|
|
347
|
+
if (responseTimer) {
|
|
348
|
+
clearTimeout(responseTimer);
|
|
349
|
+
responseTimer = null;
|
|
350
|
+
}
|
|
351
|
+
}, "clearResponseTimer");
|
|
352
|
+
const clearStallTimer = /* @__PURE__ */ __name(() => {
|
|
353
|
+
if (stallTimer) {
|
|
354
|
+
clearTimeout(stallTimer);
|
|
355
|
+
stallTimer = null;
|
|
356
|
+
}
|
|
357
|
+
}, "clearStallTimer");
|
|
358
|
+
const clearTimers = /* @__PURE__ */ __name(() => {
|
|
359
|
+
clearResponseTimer();
|
|
360
|
+
clearStallTimer();
|
|
361
|
+
}, "clearTimers");
|
|
362
|
+
const fail = /* @__PURE__ */ __name((error) => {
|
|
363
|
+
if (settled) return;
|
|
364
|
+
settled = true;
|
|
365
|
+
clearTimers();
|
|
366
|
+
const err = error instanceof Error ? error : new Error(String(error || "direct-https upstream error"));
|
|
367
|
+
if (upReq && !upReq.destroyed) upReq.destroy(err);
|
|
368
|
+
if (upResRef && !upResRef.destroyed) upResRef.destroy(err);
|
|
369
|
+
if (clientRes.headersSent && !clientRes.destroyed) clientRes.destroy(err);
|
|
370
|
+
reject(err);
|
|
371
|
+
}, "fail");
|
|
372
|
+
const finish = /* @__PURE__ */ __name(() => {
|
|
373
|
+
if (settled) return;
|
|
374
|
+
settled = true;
|
|
375
|
+
clearTimers();
|
|
376
|
+
resolve();
|
|
377
|
+
}, "finish");
|
|
378
|
+
const armResponseTimer = /* @__PURE__ */ __name(() => {
|
|
379
|
+
if (responseTimer || settled) return;
|
|
380
|
+
responseTimer = setTimeout(() => fail(new Error("direct-https upstream response timeout")), RESPONSE_TIMEOUT_MS);
|
|
381
|
+
}, "armResponseTimer");
|
|
382
|
+
const armStallTimer = /* @__PURE__ */ __name(() => {
|
|
383
|
+
if (settled) return;
|
|
384
|
+
clearStallTimer();
|
|
385
|
+
stallTimer = setTimeout(() => fail(new Error("direct-https upstream stream stalled")), STALL_TIMEOUT_MS);
|
|
386
|
+
}, "armStallTimer");
|
|
387
|
+
upReq = https2.request({
|
|
306
388
|
hostname: target.hostname,
|
|
307
389
|
port: target.port || 443,
|
|
308
390
|
path: target.pathname + target.search,
|
|
@@ -310,15 +392,21 @@ var require_claude_process_proxy = __commonJS({
|
|
|
310
392
|
headers,
|
|
311
393
|
timeout: RESPONSE_TIMEOUT_MS + 5e3
|
|
312
394
|
}, (upRes) => {
|
|
395
|
+
upResRef = upRes;
|
|
396
|
+
clearResponseTimer();
|
|
397
|
+
armStallTimer();
|
|
313
398
|
clientRes.writeHead(upRes.statusCode, upRes.headers);
|
|
399
|
+
upRes.on("data", armStallTimer);
|
|
314
400
|
upRes.pipe(clientRes);
|
|
315
|
-
upRes.on("end",
|
|
316
|
-
upRes.on("
|
|
401
|
+
upRes.on("end", finish);
|
|
402
|
+
upRes.on("close", finish);
|
|
403
|
+
upRes.on("error", fail);
|
|
317
404
|
});
|
|
318
|
-
upReq.on("error",
|
|
405
|
+
upReq.on("error", fail);
|
|
319
406
|
upReq.on("timeout", () => {
|
|
320
|
-
|
|
407
|
+
fail(new Error("direct-https upstream timeout"));
|
|
321
408
|
});
|
|
409
|
+
armResponseTimer();
|
|
322
410
|
clientReq.pipe(upReq);
|
|
323
411
|
});
|
|
324
412
|
}
|
|
@@ -406,9 +494,9 @@ var require_claude_process_proxy = __commonJS({
|
|
|
406
494
|
if (settled || sawUpstreamResponse || responseTimer) return;
|
|
407
495
|
responseTimer = setTimeout(() => failWithAnthropicError("upstream response timeout"), RESPONSE_TIMEOUT_MS);
|
|
408
496
|
}, "armResponseTimer");
|
|
409
|
-
const armStallTimer = /* @__PURE__ */ __name(() => {
|
|
497
|
+
const armStallTimer = /* @__PURE__ */ __name((markData = true) => {
|
|
410
498
|
if (settled) return;
|
|
411
|
-
sawUpstreamData = true;
|
|
499
|
+
if (markData) sawUpstreamData = true;
|
|
412
500
|
clearStallTimer();
|
|
413
501
|
stallTimer = setTimeout(() => failWithAnthropicError("upstream stream stalled"), STALL_TIMEOUT_MS);
|
|
414
502
|
}, "armStallTimer");
|
|
@@ -460,9 +548,15 @@ var require_claude_process_proxy = __commonJS({
|
|
|
460
548
|
const status = forwardRes.statusCode || 502;
|
|
461
549
|
if (status === 403 || status === 502 || status === 503) {
|
|
462
550
|
const chunks = [];
|
|
463
|
-
|
|
551
|
+
let ended = false;
|
|
552
|
+
armStallTimer(false);
|
|
553
|
+
forwardRes.on("data", (c) => {
|
|
554
|
+
chunks.push(c);
|
|
555
|
+
armStallTimer(true);
|
|
556
|
+
});
|
|
464
557
|
forwardRes.on("end", () => {
|
|
465
558
|
if (settled) return;
|
|
559
|
+
ended = true;
|
|
466
560
|
settled = true;
|
|
467
561
|
clearTimers();
|
|
468
562
|
const body = Buffer.concat(chunks).toString("utf8");
|
|
@@ -475,10 +569,14 @@ var require_claude_process_proxy = __commonJS({
|
|
|
475
569
|
});
|
|
476
570
|
reject(error);
|
|
477
571
|
});
|
|
572
|
+
forwardRes.on("close", () => {
|
|
573
|
+
if (!ended && !settled) failWithAnthropicError("upstream error response closed before end");
|
|
574
|
+
});
|
|
478
575
|
forwardRes.on("error", fail);
|
|
479
576
|
return;
|
|
480
577
|
}
|
|
481
578
|
upstreamAssignedAt = upstreamAssignedAt || Date.now();
|
|
579
|
+
armStallTimer(false);
|
|
482
580
|
clientRes.writeHead(status, forwardRes.headers);
|
|
483
581
|
forwardRes.on("data", () => {
|
|
484
582
|
if (!firstByteAt) {
|
|
@@ -777,7 +875,7 @@ var require_claude_process_proxy = __commonJS({
|
|
|
777
875
|
forceReassign: shouldRefreshLeaseAfterError(err)
|
|
778
876
|
});
|
|
779
877
|
if (clientRes.headersSent) return;
|
|
780
|
-
if (!isRetryableNodeLeaseError(err)
|
|
878
|
+
if (!isRetryableNodeLeaseError(err)) break;
|
|
781
879
|
}
|
|
782
880
|
}
|
|
783
881
|
if (lastError && !clientRes.headersSent) {
|
|
@@ -786,7 +884,12 @@ var require_claude_process_proxy = __commonJS({
|
|
|
786
884
|
if (isConnectionLevel) {
|
|
787
885
|
try {
|
|
788
886
|
const config = readConfig(configPath);
|
|
789
|
-
|
|
887
|
+
let lease;
|
|
888
|
+
try {
|
|
889
|
+
lease = getCachedLease(sessionId);
|
|
890
|
+
} catch {
|
|
891
|
+
lease = await fetchFreshLease(config, sessionId, {});
|
|
892
|
+
}
|
|
790
893
|
logProxyTiming("request.direct-fallback", {
|
|
791
894
|
sessionId,
|
|
792
895
|
originalError: msg.slice(0, 160)
|
|
@@ -905,7 +1008,7 @@ var require_claude_process_proxy = __commonJS({
|
|
|
905
1008
|
break;
|
|
906
1009
|
} catch (err) {
|
|
907
1010
|
lastError = err;
|
|
908
|
-
if (!isRetryableNodeLeaseError(err)
|
|
1011
|
+
if (!isRetryableNodeLeaseError(err)) break;
|
|
909
1012
|
}
|
|
910
1013
|
}
|
|
911
1014
|
if (lastError) {
|
|
@@ -968,14 +1071,19 @@ ${body}`);
|
|
|
968
1071
|
const startedAt = Date.now();
|
|
969
1072
|
let status = "unknown";
|
|
970
1073
|
try {
|
|
971
|
-
const response = await
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1074
|
+
const response = await fetchWithTimeout(
|
|
1075
|
+
`${controlPlaneUrl}/session/close`,
|
|
1076
|
+
{
|
|
1077
|
+
method: "POST",
|
|
1078
|
+
headers: { "content-type": "application/json" },
|
|
1079
|
+
body: JSON.stringify({ sessionId })
|
|
1080
|
+
},
|
|
1081
|
+
LEASE_CLOSE_TIMEOUT_MS,
|
|
1082
|
+
"Claude relay session close"
|
|
1083
|
+
);
|
|
976
1084
|
status = response.ok ? "ok" : `http_${response.status}`;
|
|
977
1085
|
} catch (err) {
|
|
978
|
-
status = `err_${err.name || "unknown"}`;
|
|
1086
|
+
status = err && err.code === "ETIMEDOUT" ? "timeout" : `err_${err.name || "unknown"}`;
|
|
979
1087
|
}
|
|
980
1088
|
console.error(
|
|
981
1089
|
`[hs-claude-proxy] lease.close ${JSON.stringify({
|
|
@@ -4382,7 +4490,7 @@ ${block}
|
|
|
4382
4490
|
getConfigPath() {
|
|
4383
4491
|
return CONFIG_FILE;
|
|
4384
4492
|
},
|
|
4385
|
-
hint: "CodeBuddy \
|
|
4493
|
+
hint: "CodeBuddy \u9ED8\u8BA4\u8D70 Tencent SSO\uFF08\u8981\u6C42\u4EA4\u4E92\u5F0F /login\uFF09\u3002HolySheep \u5DF2\u628A API Key/Base URL \u5199\u5230 ~/.codebuddy/.env \u4F5C\u4E3A\u7B2C\u4E09\u65B9\u6A21\u5F0F\u5907\u7528\uFF1B\u8981\u542F\u7528\u7B2C\u4E09\u65B9\u8DEF\u7531\uFF0C\u9700\u8981 export \u8FD9\u4E24\u4E2A\u53D8\u91CF\u8FDB\u5F53\u524D shell\uFF08CodeBuddy \u4E0D\u81EA\u52A8\u8BFB .env\uFF09\uFF1Aset -a; source ~/.codebuddy/.env; set +a; export CODEBUDDY_INTERNET_ENVIRONMENT=third_party\u3002CODEBUDDY_INTERNET_ENVIRONMENT \u6211\u4EEC\u6545\u610F\u4E0D\u5199\u5165 .env\uFF0C\u4EE5\u514D\u8986\u76D6\u4E2D\u56FD\u7248/iOA \u7248\u7528\u6237\u9009\u62E9\u3002",
|
|
4386
4494
|
launchCmd: "codebuddy",
|
|
4387
4495
|
installCmd: "npm install -g @tencent-ai/codebuddy-code",
|
|
4388
4496
|
docsUrl: "https://www.codebuddy.ai/docs/cli/env-vars",
|
|
@@ -4404,11 +4512,11 @@ var require_package = __commonJS({
|
|
|
4404
4512
|
"package.json"(exports2, module2) {
|
|
4405
4513
|
module2.exports = {
|
|
4406
4514
|
name: "@simonyea/holysheep-cli",
|
|
4407
|
-
version: "2.1.
|
|
4515
|
+
version: "2.1.78",
|
|
4408
4516
|
description: "Claude Code/Cursor/Cline API relay for China \u2014 \xA51=$1, WeChat/Alipay payment, no credit card, no VPN. One command setup for all AI coding tools.",
|
|
4409
4517
|
scripts: {
|
|
4410
4518
|
build: "node scripts/build.mjs",
|
|
4411
|
-
test: "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js && node tests/claude-code-windows-local-bin.test.js && node tests/qwen-code-config.test.js && node tests/codebuddy-config.test.js && node tests/hs-reset-routing.test.js",
|
|
4519
|
+
test: "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-timeout-hardening.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js && node tests/claude-code-windows-local-bin.test.js && node tests/qwen-code-config.test.js && node tests/codebuddy-config.test.js && node tests/hs-reset-routing.test.js && node tests/setup-auto-install-routing.test.js && node tests/upgrade-routing.test.js",
|
|
4412
4520
|
prepublishOnly: "npm run build && npm test && node scripts/check-tarball-size.js"
|
|
4413
4521
|
},
|
|
4414
4522
|
keywords: [
|
package/dist/index.js
CHANGED
|
@@ -12,11 +12,11 @@ var require_package = __commonJS({
|
|
|
12
12
|
"package.json"(exports2, module2) {
|
|
13
13
|
module2.exports = {
|
|
14
14
|
name: "@simonyea/holysheep-cli",
|
|
15
|
-
version: "2.1.
|
|
15
|
+
version: "2.1.78",
|
|
16
16
|
description: "Claude Code/Cursor/Cline API relay for China \u2014 \xA51=$1, WeChat/Alipay payment, no credit card, no VPN. One command setup for all AI coding tools.",
|
|
17
17
|
scripts: {
|
|
18
18
|
build: "node scripts/build.mjs",
|
|
19
|
-
test: "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js && node tests/claude-code-windows-local-bin.test.js && node tests/qwen-code-config.test.js && node tests/codebuddy-config.test.js && node tests/hs-reset-routing.test.js",
|
|
19
|
+
test: "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-timeout-hardening.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js && node tests/claude-code-windows-local-bin.test.js && node tests/qwen-code-config.test.js && node tests/codebuddy-config.test.js && node tests/hs-reset-routing.test.js && node tests/setup-auto-install-routing.test.js && node tests/upgrade-routing.test.js",
|
|
20
20
|
prepublishOnly: "npm run build && npm test && node scripts/check-tarball-size.js"
|
|
21
21
|
},
|
|
22
22
|
keywords: [
|
|
@@ -834,6 +834,34 @@ var require_claude_process_proxy = __commonJS({
|
|
|
834
834
|
var ENABLE_TIMING_LOG = process.env.HS_CLAUDE_TIMING_LOG === "1";
|
|
835
835
|
var SLOW_PATH_LOG_MS = Number(process.env.HS_CLAUDE_SLOW_PATH_LOG_MS) || 5e3;
|
|
836
836
|
var ENABLE_LEASE_LOG = process.env.HS_CLAUDE_LEASE_LOG === "1";
|
|
837
|
+
function positiveInt(value, fallback) {
|
|
838
|
+
const n = Number(value);
|
|
839
|
+
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
840
|
+
}
|
|
841
|
+
__name(positiveInt, "positiveInt");
|
|
842
|
+
var LEASE_OPEN_TIMEOUT_MS = positiveInt(process.env.HS_CLAUDE_LEASE_OPEN_TIMEOUT_MS, 15e3);
|
|
843
|
+
var LEASE_CLOSE_TIMEOUT_MS = positiveInt(process.env.HS_CLAUDE_LEASE_CLOSE_TIMEOUT_MS, 5e3);
|
|
844
|
+
async function fetchWithTimeout(url, options, timeoutMs, label, consume = (response) => response) {
|
|
845
|
+
const controller = typeof AbortController === "function" ? new AbortController() : null;
|
|
846
|
+
const timer = controller ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
847
|
+
if (timer && typeof timer.unref === "function") timer.unref();
|
|
848
|
+
try {
|
|
849
|
+
const requestOptions = controller ? { ...options, signal: controller.signal } : { ...options, timeout: timeoutMs };
|
|
850
|
+
const response = await fetch(url, requestOptions);
|
|
851
|
+
return await consume(response);
|
|
852
|
+
} catch (err) {
|
|
853
|
+
const aborted = err && (err.name === "AbortError" || err.type === "aborted");
|
|
854
|
+
if (aborted) {
|
|
855
|
+
const timeoutErr = new Error(`${label} timed out after ${timeoutMs}ms`);
|
|
856
|
+
timeoutErr.code = "ETIMEDOUT";
|
|
857
|
+
throw timeoutErr;
|
|
858
|
+
}
|
|
859
|
+
throw err;
|
|
860
|
+
} finally {
|
|
861
|
+
if (timer) clearTimeout(timer);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
__name(fetchWithTimeout, "fetchWithTimeout");
|
|
837
865
|
function sanitizeUrl(value) {
|
|
838
866
|
if (!value) return "";
|
|
839
867
|
try {
|
|
@@ -920,19 +948,27 @@ var require_claude_process_proxy = __commonJS({
|
|
|
920
948
|
const controlPlaneUrl = getControlPlaneUrl(config);
|
|
921
949
|
if (!controlPlaneUrl) throw new Error("Claude relay control plane is not configured");
|
|
922
950
|
const startedAt = Date.now();
|
|
923
|
-
const response = await
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
951
|
+
const { response, payload } = await fetchWithTimeout(
|
|
952
|
+
`${controlPlaneUrl}/session/open`,
|
|
953
|
+
{
|
|
954
|
+
method: "POST",
|
|
955
|
+
headers: { "content-type": "application/json" },
|
|
956
|
+
body: JSON.stringify({
|
|
957
|
+
sessionId,
|
|
958
|
+
bridgeId: config.bridgeId || "local-bridge",
|
|
959
|
+
deviceId: config.deviceId || "",
|
|
960
|
+
installSource: config.installSource || "holysheep-cli",
|
|
961
|
+
proxyMode: "claude-process",
|
|
962
|
+
forceReassign: options.forceReassign === true
|
|
963
|
+
})
|
|
964
|
+
},
|
|
965
|
+
LEASE_OPEN_TIMEOUT_MS,
|
|
966
|
+
"Claude relay session open",
|
|
967
|
+
async (response2) => ({
|
|
968
|
+
response: response2,
|
|
969
|
+
payload: await response2.json().catch(() => null)
|
|
933
970
|
})
|
|
934
|
-
|
|
935
|
-
const payload = await response.json().catch(() => null);
|
|
971
|
+
);
|
|
936
972
|
if (!response.ok || !(payload == null ? void 0 : payload.success) || !((_a = payload == null ? void 0 : payload.data) == null ? void 0 : _a.ticket)) {
|
|
937
973
|
throw new Error(((_b = payload == null ? void 0 : payload.error) == null ? void 0 : _b.message) || `Failed to open Claude session (HTTP ${response.status})`);
|
|
938
974
|
}
|
|
@@ -1021,7 +1057,53 @@ var require_claude_process_proxy = __commonJS({
|
|
|
1021
1057
|
})}`
|
|
1022
1058
|
);
|
|
1023
1059
|
}
|
|
1024
|
-
|
|
1060
|
+
let settled = false;
|
|
1061
|
+
let responseTimer = null;
|
|
1062
|
+
let stallTimer = null;
|
|
1063
|
+
let upReq = null;
|
|
1064
|
+
let upResRef = null;
|
|
1065
|
+
const clearResponseTimer = /* @__PURE__ */ __name(() => {
|
|
1066
|
+
if (responseTimer) {
|
|
1067
|
+
clearTimeout(responseTimer);
|
|
1068
|
+
responseTimer = null;
|
|
1069
|
+
}
|
|
1070
|
+
}, "clearResponseTimer");
|
|
1071
|
+
const clearStallTimer = /* @__PURE__ */ __name(() => {
|
|
1072
|
+
if (stallTimer) {
|
|
1073
|
+
clearTimeout(stallTimer);
|
|
1074
|
+
stallTimer = null;
|
|
1075
|
+
}
|
|
1076
|
+
}, "clearStallTimer");
|
|
1077
|
+
const clearTimers = /* @__PURE__ */ __name(() => {
|
|
1078
|
+
clearResponseTimer();
|
|
1079
|
+
clearStallTimer();
|
|
1080
|
+
}, "clearTimers");
|
|
1081
|
+
const fail = /* @__PURE__ */ __name((error) => {
|
|
1082
|
+
if (settled) return;
|
|
1083
|
+
settled = true;
|
|
1084
|
+
clearTimers();
|
|
1085
|
+
const err = error instanceof Error ? error : new Error(String(error || "direct-https upstream error"));
|
|
1086
|
+
if (upReq && !upReq.destroyed) upReq.destroy(err);
|
|
1087
|
+
if (upResRef && !upResRef.destroyed) upResRef.destroy(err);
|
|
1088
|
+
if (clientRes.headersSent && !clientRes.destroyed) clientRes.destroy(err);
|
|
1089
|
+
reject(err);
|
|
1090
|
+
}, "fail");
|
|
1091
|
+
const finish = /* @__PURE__ */ __name(() => {
|
|
1092
|
+
if (settled) return;
|
|
1093
|
+
settled = true;
|
|
1094
|
+
clearTimers();
|
|
1095
|
+
resolve();
|
|
1096
|
+
}, "finish");
|
|
1097
|
+
const armResponseTimer = /* @__PURE__ */ __name(() => {
|
|
1098
|
+
if (responseTimer || settled) return;
|
|
1099
|
+
responseTimer = setTimeout(() => fail(new Error("direct-https upstream response timeout")), RESPONSE_TIMEOUT_MS);
|
|
1100
|
+
}, "armResponseTimer");
|
|
1101
|
+
const armStallTimer = /* @__PURE__ */ __name(() => {
|
|
1102
|
+
if (settled) return;
|
|
1103
|
+
clearStallTimer();
|
|
1104
|
+
stallTimer = setTimeout(() => fail(new Error("direct-https upstream stream stalled")), STALL_TIMEOUT_MS);
|
|
1105
|
+
}, "armStallTimer");
|
|
1106
|
+
upReq = https2.request({
|
|
1025
1107
|
hostname: target.hostname,
|
|
1026
1108
|
port: target.port || 443,
|
|
1027
1109
|
path: target.pathname + target.search,
|
|
@@ -1029,15 +1111,21 @@ var require_claude_process_proxy = __commonJS({
|
|
|
1029
1111
|
headers,
|
|
1030
1112
|
timeout: RESPONSE_TIMEOUT_MS + 5e3
|
|
1031
1113
|
}, (upRes) => {
|
|
1114
|
+
upResRef = upRes;
|
|
1115
|
+
clearResponseTimer();
|
|
1116
|
+
armStallTimer();
|
|
1032
1117
|
clientRes.writeHead(upRes.statusCode, upRes.headers);
|
|
1118
|
+
upRes.on("data", armStallTimer);
|
|
1033
1119
|
upRes.pipe(clientRes);
|
|
1034
|
-
upRes.on("end",
|
|
1035
|
-
upRes.on("
|
|
1120
|
+
upRes.on("end", finish);
|
|
1121
|
+
upRes.on("close", finish);
|
|
1122
|
+
upRes.on("error", fail);
|
|
1036
1123
|
});
|
|
1037
|
-
upReq.on("error",
|
|
1124
|
+
upReq.on("error", fail);
|
|
1038
1125
|
upReq.on("timeout", () => {
|
|
1039
|
-
|
|
1126
|
+
fail(new Error("direct-https upstream timeout"));
|
|
1040
1127
|
});
|
|
1128
|
+
armResponseTimer();
|
|
1041
1129
|
clientReq.pipe(upReq);
|
|
1042
1130
|
});
|
|
1043
1131
|
}
|
|
@@ -1125,9 +1213,9 @@ var require_claude_process_proxy = __commonJS({
|
|
|
1125
1213
|
if (settled || sawUpstreamResponse || responseTimer) return;
|
|
1126
1214
|
responseTimer = setTimeout(() => failWithAnthropicError("upstream response timeout"), RESPONSE_TIMEOUT_MS);
|
|
1127
1215
|
}, "armResponseTimer");
|
|
1128
|
-
const armStallTimer = /* @__PURE__ */ __name(() => {
|
|
1216
|
+
const armStallTimer = /* @__PURE__ */ __name((markData = true) => {
|
|
1129
1217
|
if (settled) return;
|
|
1130
|
-
sawUpstreamData = true;
|
|
1218
|
+
if (markData) sawUpstreamData = true;
|
|
1131
1219
|
clearStallTimer();
|
|
1132
1220
|
stallTimer = setTimeout(() => failWithAnthropicError("upstream stream stalled"), STALL_TIMEOUT_MS);
|
|
1133
1221
|
}, "armStallTimer");
|
|
@@ -1179,9 +1267,15 @@ var require_claude_process_proxy = __commonJS({
|
|
|
1179
1267
|
const status = forwardRes.statusCode || 502;
|
|
1180
1268
|
if (status === 403 || status === 502 || status === 503) {
|
|
1181
1269
|
const chunks = [];
|
|
1182
|
-
|
|
1270
|
+
let ended = false;
|
|
1271
|
+
armStallTimer(false);
|
|
1272
|
+
forwardRes.on("data", (c) => {
|
|
1273
|
+
chunks.push(c);
|
|
1274
|
+
armStallTimer(true);
|
|
1275
|
+
});
|
|
1183
1276
|
forwardRes.on("end", () => {
|
|
1184
1277
|
if (settled) return;
|
|
1278
|
+
ended = true;
|
|
1185
1279
|
settled = true;
|
|
1186
1280
|
clearTimers();
|
|
1187
1281
|
const body = Buffer.concat(chunks).toString("utf8");
|
|
@@ -1194,10 +1288,14 @@ var require_claude_process_proxy = __commonJS({
|
|
|
1194
1288
|
});
|
|
1195
1289
|
reject(error);
|
|
1196
1290
|
});
|
|
1291
|
+
forwardRes.on("close", () => {
|
|
1292
|
+
if (!ended && !settled) failWithAnthropicError("upstream error response closed before end");
|
|
1293
|
+
});
|
|
1197
1294
|
forwardRes.on("error", fail);
|
|
1198
1295
|
return;
|
|
1199
1296
|
}
|
|
1200
1297
|
upstreamAssignedAt = upstreamAssignedAt || Date.now();
|
|
1298
|
+
armStallTimer(false);
|
|
1201
1299
|
clientRes.writeHead(status, forwardRes.headers);
|
|
1202
1300
|
forwardRes.on("data", () => {
|
|
1203
1301
|
if (!firstByteAt) {
|
|
@@ -1496,7 +1594,7 @@ var require_claude_process_proxy = __commonJS({
|
|
|
1496
1594
|
forceReassign: shouldRefreshLeaseAfterError(err)
|
|
1497
1595
|
});
|
|
1498
1596
|
if (clientRes.headersSent) return;
|
|
1499
|
-
if (!isRetryableNodeLeaseError(err)
|
|
1597
|
+
if (!isRetryableNodeLeaseError(err)) break;
|
|
1500
1598
|
}
|
|
1501
1599
|
}
|
|
1502
1600
|
if (lastError && !clientRes.headersSent) {
|
|
@@ -1505,7 +1603,12 @@ var require_claude_process_proxy = __commonJS({
|
|
|
1505
1603
|
if (isConnectionLevel) {
|
|
1506
1604
|
try {
|
|
1507
1605
|
const config = readConfig(configPath);
|
|
1508
|
-
|
|
1606
|
+
let lease;
|
|
1607
|
+
try {
|
|
1608
|
+
lease = getCachedLease(sessionId);
|
|
1609
|
+
} catch {
|
|
1610
|
+
lease = await fetchFreshLease(config, sessionId, {});
|
|
1611
|
+
}
|
|
1509
1612
|
logProxyTiming("request.direct-fallback", {
|
|
1510
1613
|
sessionId,
|
|
1511
1614
|
originalError: msg.slice(0, 160)
|
|
@@ -1624,7 +1727,7 @@ var require_claude_process_proxy = __commonJS({
|
|
|
1624
1727
|
break;
|
|
1625
1728
|
} catch (err) {
|
|
1626
1729
|
lastError = err;
|
|
1627
|
-
if (!isRetryableNodeLeaseError(err)
|
|
1730
|
+
if (!isRetryableNodeLeaseError(err)) break;
|
|
1628
1731
|
}
|
|
1629
1732
|
}
|
|
1630
1733
|
if (lastError) {
|
|
@@ -1687,14 +1790,19 @@ ${body}`);
|
|
|
1687
1790
|
const startedAt = Date.now();
|
|
1688
1791
|
let status = "unknown";
|
|
1689
1792
|
try {
|
|
1690
|
-
const response = await
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1793
|
+
const response = await fetchWithTimeout(
|
|
1794
|
+
`${controlPlaneUrl}/session/close`,
|
|
1795
|
+
{
|
|
1796
|
+
method: "POST",
|
|
1797
|
+
headers: { "content-type": "application/json" },
|
|
1798
|
+
body: JSON.stringify({ sessionId })
|
|
1799
|
+
},
|
|
1800
|
+
LEASE_CLOSE_TIMEOUT_MS,
|
|
1801
|
+
"Claude relay session close"
|
|
1802
|
+
);
|
|
1695
1803
|
status = response.ok ? "ok" : `http_${response.status}`;
|
|
1696
1804
|
} catch (err) {
|
|
1697
|
-
status = `err_${err.name || "unknown"}`;
|
|
1805
|
+
status = err && err.code === "ETIMEDOUT" ? "timeout" : `err_${err.name || "unknown"}`;
|
|
1698
1806
|
}
|
|
1699
1807
|
console.error(
|
|
1700
1808
|
`[hs-claude-proxy] lease.close ${JSON.stringify({
|
|
@@ -4950,7 +5058,7 @@ ${block}
|
|
|
4950
5058
|
getConfigPath() {
|
|
4951
5059
|
return CONFIG_FILE;
|
|
4952
5060
|
},
|
|
4953
|
-
hint: "CodeBuddy \
|
|
5061
|
+
hint: "CodeBuddy \u9ED8\u8BA4\u8D70 Tencent SSO\uFF08\u8981\u6C42\u4EA4\u4E92\u5F0F /login\uFF09\u3002HolySheep \u5DF2\u628A API Key/Base URL \u5199\u5230 ~/.codebuddy/.env \u4F5C\u4E3A\u7B2C\u4E09\u65B9\u6A21\u5F0F\u5907\u7528\uFF1B\u8981\u542F\u7528\u7B2C\u4E09\u65B9\u8DEF\u7531\uFF0C\u9700\u8981 export \u8FD9\u4E24\u4E2A\u53D8\u91CF\u8FDB\u5F53\u524D shell\uFF08CodeBuddy \u4E0D\u81EA\u52A8\u8BFB .env\uFF09\uFF1Aset -a; source ~/.codebuddy/.env; set +a; export CODEBUDDY_INTERNET_ENVIRONMENT=third_party\u3002CODEBUDDY_INTERNET_ENVIRONMENT \u6211\u4EEC\u6545\u610F\u4E0D\u5199\u5165 .env\uFF0C\u4EE5\u514D\u8986\u76D6\u4E2D\u56FD\u7248/iOA \u7248\u7528\u6237\u9009\u62E9\u3002",
|
|
4954
5062
|
launchCmd: "codebuddy",
|
|
4955
5063
|
installCmd: "npm install -g @tencent-ai/codebuddy-code",
|
|
4956
5064
|
docsUrl: "https://www.codebuddy.ai/docs/cli/env-vars",
|
|
@@ -5231,7 +5339,13 @@ var require_setup = __commonJS({
|
|
|
5231
5339
|
"gemini-cli": { cmd: "npm install -g @google/gemini-cli", mgr: "npm" },
|
|
5232
5340
|
"opencode": { cmd: "npm install -g opencode-ai", mgr: "npm" },
|
|
5233
5341
|
"openclaw": { cmd: "npm install -g openclaw@latest", mgr: "npm" },
|
|
5234
|
-
"aider": { cmd: "pip install aider-chat", mgr: "pip" }
|
|
5342
|
+
"aider": { cmd: "pip install aider-chat", mgr: "pip" },
|
|
5343
|
+
// [v2.1.77] Qwen Code + CodeBuddy: hs setup install entry. Adapter
|
|
5344
|
+
// checkInstalled() is hardcoded true (npx fallback for AionUI), so the
|
|
5345
|
+
// setup flow needs to detect real PATH separately. canAutoInstall(t.id)
|
|
5346
|
+
// already keys off this dict — adding here is enough.
|
|
5347
|
+
"qwen-code": { cmd: "npm install -g @qwen-code/qwen-code", mgr: "npm" },
|
|
5348
|
+
"codebuddy": { cmd: "npm install -g @tencent-ai/codebuddy-code", mgr: "npm" }
|
|
5235
5349
|
};
|
|
5236
5350
|
function getWindowsImmediateLaunchCmd(tool) {
|
|
5237
5351
|
if (process.platform !== "win32" || !(tool == null ? void 0 : tool.launchCmd)) return null;
|
|
@@ -5954,6 +6068,26 @@ var require_upgrade = __commonJS({
|
|
|
5954
6068
|
versionCmd: "gemini --version",
|
|
5955
6069
|
npmPkg: "@google/gemini-cli",
|
|
5956
6070
|
installCmd: "npm install -g @google/gemini-cli@latest"
|
|
6071
|
+
},
|
|
6072
|
+
// [v2.1.77] Qwen Code: adapter checkInstalled() is hardcoded true (npx
|
|
6073
|
+
// fallback for AionUI), so we must NOT use that here — upgrade uses
|
|
6074
|
+
// commandExists(tool.command) below, which checks real PATH. Same for
|
|
6075
|
+
// CodeBuddy.
|
|
6076
|
+
{
|
|
6077
|
+
name: "Qwen Code",
|
|
6078
|
+
id: "qwen-code",
|
|
6079
|
+
command: "qwen",
|
|
6080
|
+
versionCmd: "qwen --version",
|
|
6081
|
+
npmPkg: "@qwen-code/qwen-code",
|
|
6082
|
+
installCmd: "npm install -g @qwen-code/qwen-code@latest"
|
|
6083
|
+
},
|
|
6084
|
+
{
|
|
6085
|
+
name: "CodeBuddy",
|
|
6086
|
+
id: "codebuddy",
|
|
6087
|
+
command: "codebuddy",
|
|
6088
|
+
versionCmd: "codebuddy --version",
|
|
6089
|
+
npmPkg: "@tencent-ai/codebuddy-code",
|
|
6090
|
+
installCmd: "npm install -g @tencent-ai/codebuddy-code@latest"
|
|
5957
6091
|
}
|
|
5958
6092
|
];
|
|
5959
6093
|
function getLocalVersion(tool) {
|
|
@@ -15,6 +15,15 @@ try {
|
|
|
15
15
|
}
|
|
16
16
|
var PROXY_HOST = parsed.hostname;
|
|
17
17
|
var PROXY_PORT = Number(parsed.port) || 80;
|
|
18
|
+
function positiveInt(value, fallback) {
|
|
19
|
+
const n = Number(value);
|
|
20
|
+
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
21
|
+
}
|
|
22
|
+
__name(positiveInt, "positiveInt");
|
|
23
|
+
var CONNECT_TIMEOUT_MS = positiveInt(
|
|
24
|
+
process.env.HS_PROXY_CONNECT_TIMEOUT_MS || process.env.HS_CLAUDE_CONNECT_TIMEOUT_MS,
|
|
25
|
+
15e3
|
|
26
|
+
);
|
|
18
27
|
var SKIP = /* @__PURE__ */ new Set(["127.0.0.1", "::1", "localhost", "0.0.0.0", PROXY_HOST]);
|
|
19
28
|
var BLOCK = /* @__PURE__ */ new Set(["api.anthropic.com"]);
|
|
20
29
|
function shouldProxy(host, port) {
|
|
@@ -30,16 +39,39 @@ function rewriteHost(host) {
|
|
|
30
39
|
__name(rewriteHost, "rewriteHost");
|
|
31
40
|
function setupTunnel(sock, host, port, origEmit) {
|
|
32
41
|
const targetHost = rewriteHost(host);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
let settled = false;
|
|
43
|
+
let timer = null;
|
|
44
|
+
const cleanup = /* @__PURE__ */ __name(() => {
|
|
45
|
+
if (timer) {
|
|
46
|
+
clearTimeout(timer);
|
|
47
|
+
timer = null;
|
|
48
|
+
}
|
|
49
|
+
sock.removeListener("data", onData);
|
|
50
|
+
sock.removeListener("close", onClose);
|
|
51
|
+
sock.removeListener("error", onError);
|
|
52
|
+
}, "cleanup");
|
|
53
|
+
const fail = /* @__PURE__ */ __name((message) => {
|
|
54
|
+
if (settled) return;
|
|
55
|
+
settled = true;
|
|
56
|
+
cleanup();
|
|
57
|
+
sock.emit = origEmit;
|
|
58
|
+
sock.destroy(new Error(message));
|
|
59
|
+
}, "fail");
|
|
60
|
+
function onClose() {
|
|
61
|
+
cleanup();
|
|
62
|
+
}
|
|
63
|
+
__name(onClose, "onClose");
|
|
64
|
+
function onError() {
|
|
65
|
+
cleanup();
|
|
66
|
+
}
|
|
67
|
+
__name(onError, "onError");
|
|
68
|
+
function onData(chunk) {
|
|
39
69
|
buf = Buffer.concat([buf, chunk]);
|
|
40
70
|
const i = buf.indexOf("\r\n\r\n");
|
|
41
71
|
if (i === -1) return;
|
|
42
|
-
|
|
72
|
+
if (settled) return;
|
|
73
|
+
settled = true;
|
|
74
|
+
cleanup();
|
|
43
75
|
if (!buf.slice(0, i).toString().includes(" 200 ")) {
|
|
44
76
|
sock.emit = origEmit;
|
|
45
77
|
sock.destroy(new Error(`CONNECT ${host}:${port} failed: ${buf.slice(0, buf.indexOf("\r\n")).toString()}`));
|
|
@@ -49,7 +81,22 @@ Host: ${targetHost}:${port}\r
|
|
|
49
81
|
if (rest.length) sock.unshift(rest);
|
|
50
82
|
sock.emit = origEmit;
|
|
51
83
|
origEmit("connect");
|
|
52
|
-
}
|
|
84
|
+
}
|
|
85
|
+
__name(onData, "onData");
|
|
86
|
+
if (CONNECT_TIMEOUT_MS > 0) {
|
|
87
|
+
timer = setTimeout(() => {
|
|
88
|
+
fail(`CONNECT ${host}:${port} timed out after ${CONNECT_TIMEOUT_MS}ms`);
|
|
89
|
+
}, CONNECT_TIMEOUT_MS);
|
|
90
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
91
|
+
}
|
|
92
|
+
sock.once("close", onClose);
|
|
93
|
+
sock.once("error", onError);
|
|
94
|
+
sock.write(`CONNECT ${targetHost}:${port} HTTP/1.1\r
|
|
95
|
+
Host: ${targetHost}:${port}\r
|
|
96
|
+
\r
|
|
97
|
+
`);
|
|
98
|
+
let buf = Buffer.alloc(0);
|
|
99
|
+
sock.on("data", onData);
|
|
53
100
|
}
|
|
54
101
|
__name(setupTunnel, "setupTunnel");
|
|
55
102
|
function patchEmitAndConnect(sock, host, port, connectFn) {
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simonyea/holysheep-cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.78",
|
|
4
4
|
"description": "Claude Code/Cursor/Cline API relay for China — ¥1=$1, WeChat/Alipay payment, no credit card, no VPN. One command setup for all AI coding tools.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "node scripts/build.mjs",
|
|
7
|
-
"test": "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js && node tests/claude-code-windows-local-bin.test.js && node tests/qwen-code-config.test.js && node tests/codebuddy-config.test.js && node tests/hs-reset-routing.test.js",
|
|
7
|
+
"test": "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-timeout-hardening.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js && node tests/claude-code-windows-local-bin.test.js && node tests/qwen-code-config.test.js && node tests/codebuddy-config.test.js && node tests/hs-reset-routing.test.js && node tests/setup-auto-install-routing.test.js && node tests/upgrade-routing.test.js",
|
|
8
8
|
"prepublishOnly": "npm run build && npm test && node scripts/check-tarball-size.js"
|
|
9
9
|
},
|
|
10
10
|
"keywords": [
|