@simonyea/holysheep-cli 2.1.43 → 2.1.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.
@@ -76,21 +76,25 @@ var require_claude_process_proxy = __commonJS({
76
76
  var HOLYSHEEP_DIR = path.join(os.homedir(), ".holysheep");
77
77
  var CONFIG_PATH = path.join(HOLYSHEEP_DIR, "claude-proxy.json");
78
78
  var DEFAULT_PROXY_PORT = 14556;
79
+ var LOCAL_PING_PATH = "/__hs_local_ping__";
80
+ var LOCAL_PING_HEADER = "x-hs-local-proxy";
81
+ var LOCAL_PING_HEADER_VALUE = "1";
79
82
  function ensureDir() {
80
83
  if (!fs.existsSync(HOLYSHEEP_DIR)) fs.mkdirSync(HOLYSHEEP_DIR, { recursive: true });
81
84
  }
82
85
  __name(ensureDir, "ensureDir");
83
- function readConfig() {
86
+ function readConfig(configPath) {
84
87
  try {
85
- return JSON.parse(fs.readFileSync(CONFIG_PATH, "utf8"));
88
+ return JSON.parse(fs.readFileSync(configPath || CONFIG_PATH, "utf8"));
86
89
  } catch {
87
90
  return {};
88
91
  }
89
92
  }
90
93
  __name(readConfig, "readConfig");
91
- function writeConfig(data) {
92
- ensureDir();
93
- fs.writeFileSync(CONFIG_PATH, JSON.stringify(data, null, 2), "utf8");
94
+ function writeConfig(data, configPath) {
95
+ const target = configPath || CONFIG_PATH;
96
+ if (!configPath) ensureDir();
97
+ fs.writeFileSync(target, JSON.stringify(data, null, 2), "utf8");
94
98
  }
95
99
  __name(writeConfig, "writeConfig");
96
100
  function getProcessProxyPort(config = readConfig()) {
@@ -572,6 +576,31 @@ var require_claude_process_proxy = __commonJS({
572
576
  __name(pipeWithCleanup, "pipeWithCleanup");
573
577
  function createProcessProxyServer({ sessionId, configPath = CONFIG_PATH, allowAnthropicConnect = false }) {
574
578
  const server = http.createServer(async (clientReq, clientRes) => {
579
+ if (clientReq.method === "GET" && !clientReq.url.startsWith("http")) {
580
+ const u = clientReq.url.split("?")[0];
581
+ if (u === LOCAL_PING_PATH) {
582
+ const hostHeader = String(clientReq.headers.host || "").toLowerCase();
583
+ const isLoopbackHost = hostHeader.startsWith("127.0.0.1") || hostHeader.startsWith("localhost") || hostHeader.startsWith("[::1]");
584
+ if (!isLoopbackHost) {
585
+ clientRes.writeHead(404, { "content-type": "text/plain" });
586
+ clientRes.end("not found");
587
+ return;
588
+ }
589
+ const body = JSON.stringify({
590
+ hsLocalProxy: true,
591
+ sessionId: String(sessionId || ""),
592
+ pid: process.pid,
593
+ ts: Date.now()
594
+ });
595
+ clientRes.writeHead(200, {
596
+ "content-type": "application/json",
597
+ [LOCAL_PING_HEADER]: LOCAL_PING_HEADER_VALUE,
598
+ "cache-control": "no-store"
599
+ });
600
+ clientRes.end(body);
601
+ return;
602
+ }
603
+ }
575
604
  const isDirect = !clientReq.url.startsWith("http");
576
605
  if (ENABLE_TIMING_LOG) {
577
606
  console.error(
@@ -885,7 +914,16 @@ ${body}`);
885
914
  }
886
915
  });
887
916
  server.once("listening", () => {
888
- resolve({ server, port: server.address().port, sessionId: effectiveSessionId });
917
+ const boundPort = server.address().port;
918
+ try {
919
+ const latest = readConfig(configPath);
920
+ if (Number(latest.processProxyPort) !== boundPort) {
921
+ writeConfig({ ...latest, processProxyPort: boundPort }, configPath);
922
+ }
923
+ } catch (persistErr) {
924
+ console.error("[hs-claude-proxy] warn: failed to persist processProxyPort:", persistErr && persistErr.message);
925
+ }
926
+ resolve({ server, port: boundPort, sessionId: effectiveSessionId });
889
927
  });
890
928
  server.listen(p, "127.0.0.1");
891
929
  }, "tryListen");
@@ -931,7 +969,10 @@ ${body}`);
931
969
  getControlPlaneUrl,
932
970
  readConfig,
933
971
  startProcessProxy,
934
- writeConfig
972
+ writeConfig,
973
+ LOCAL_PING_PATH,
974
+ LOCAL_PING_HEADER,
975
+ LOCAL_PING_HEADER_VALUE
935
976
  };
936
977
  }
937
978
  });
@@ -3931,11 +3972,11 @@ var require_package = __commonJS({
3931
3972
  "package.json"(exports2, module2) {
3932
3973
  module2.exports = {
3933
3974
  name: "@simonyea/holysheep-cli",
3934
- version: "2.1.43",
3975
+ version: "2.1.44",
3935
3976
  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.",
3936
3977
  scripts: {
3937
3978
  build: "node scripts/build.mjs",
3938
- 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/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-wrapper-claude-proxy.test.js",
3979
+ 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/opencode-default-model.test.js && node tests/paths-bundled.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",
3939
3980
  prepublishOnly: "npm run build && npm test && node scripts/check-tarball-size.js"
3940
3981
  },
3941
3982
  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.43",
15
+ version: "2.1.44",
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/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-wrapper-claude-proxy.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/opencode-default-model.test.js && node tests/paths-bundled.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",
20
20
  prepublishOnly: "npm run build && npm test && node scripts/check-tarball-size.js"
21
21
  },
22
22
  keywords: [
@@ -752,21 +752,25 @@ var require_claude_process_proxy = __commonJS({
752
752
  var HOLYSHEEP_DIR = path.join(os.homedir(), ".holysheep");
753
753
  var CONFIG_PATH = path.join(HOLYSHEEP_DIR, "claude-proxy.json");
754
754
  var DEFAULT_PROXY_PORT = 14556;
755
+ var LOCAL_PING_PATH = "/__hs_local_ping__";
756
+ var LOCAL_PING_HEADER = "x-hs-local-proxy";
757
+ var LOCAL_PING_HEADER_VALUE = "1";
755
758
  function ensureDir() {
756
759
  if (!fs.existsSync(HOLYSHEEP_DIR)) fs.mkdirSync(HOLYSHEEP_DIR, { recursive: true });
757
760
  }
758
761
  __name(ensureDir, "ensureDir");
759
- function readConfig() {
762
+ function readConfig(configPath) {
760
763
  try {
761
- return JSON.parse(fs.readFileSync(CONFIG_PATH, "utf8"));
764
+ return JSON.parse(fs.readFileSync(configPath || CONFIG_PATH, "utf8"));
762
765
  } catch {
763
766
  return {};
764
767
  }
765
768
  }
766
769
  __name(readConfig, "readConfig");
767
- function writeConfig(data) {
768
- ensureDir();
769
- fs.writeFileSync(CONFIG_PATH, JSON.stringify(data, null, 2), "utf8");
770
+ function writeConfig(data, configPath) {
771
+ const target = configPath || CONFIG_PATH;
772
+ if (!configPath) ensureDir();
773
+ fs.writeFileSync(target, JSON.stringify(data, null, 2), "utf8");
770
774
  }
771
775
  __name(writeConfig, "writeConfig");
772
776
  function getProcessProxyPort(config = readConfig()) {
@@ -1248,6 +1252,31 @@ var require_claude_process_proxy = __commonJS({
1248
1252
  __name(pipeWithCleanup, "pipeWithCleanup");
1249
1253
  function createProcessProxyServer({ sessionId, configPath = CONFIG_PATH, allowAnthropicConnect = false }) {
1250
1254
  const server = http.createServer(async (clientReq, clientRes) => {
1255
+ if (clientReq.method === "GET" && !clientReq.url.startsWith("http")) {
1256
+ const u = clientReq.url.split("?")[0];
1257
+ if (u === LOCAL_PING_PATH) {
1258
+ const hostHeader = String(clientReq.headers.host || "").toLowerCase();
1259
+ const isLoopbackHost = hostHeader.startsWith("127.0.0.1") || hostHeader.startsWith("localhost") || hostHeader.startsWith("[::1]");
1260
+ if (!isLoopbackHost) {
1261
+ clientRes.writeHead(404, { "content-type": "text/plain" });
1262
+ clientRes.end("not found");
1263
+ return;
1264
+ }
1265
+ const body = JSON.stringify({
1266
+ hsLocalProxy: true,
1267
+ sessionId: String(sessionId || ""),
1268
+ pid: process.pid,
1269
+ ts: Date.now()
1270
+ });
1271
+ clientRes.writeHead(200, {
1272
+ "content-type": "application/json",
1273
+ [LOCAL_PING_HEADER]: LOCAL_PING_HEADER_VALUE,
1274
+ "cache-control": "no-store"
1275
+ });
1276
+ clientRes.end(body);
1277
+ return;
1278
+ }
1279
+ }
1251
1280
  const isDirect = !clientReq.url.startsWith("http");
1252
1281
  if (ENABLE_TIMING_LOG) {
1253
1282
  console.error(
@@ -1561,7 +1590,16 @@ ${body}`);
1561
1590
  }
1562
1591
  });
1563
1592
  server.once("listening", () => {
1564
- resolve({ server, port: server.address().port, sessionId: effectiveSessionId });
1593
+ const boundPort = server.address().port;
1594
+ try {
1595
+ const latest = readConfig(configPath);
1596
+ if (Number(latest.processProxyPort) !== boundPort) {
1597
+ writeConfig({ ...latest, processProxyPort: boundPort }, configPath);
1598
+ }
1599
+ } catch (persistErr) {
1600
+ console.error("[hs-claude-proxy] warn: failed to persist processProxyPort:", persistErr && persistErr.message);
1601
+ }
1602
+ resolve({ server, port: boundPort, sessionId: effectiveSessionId });
1565
1603
  });
1566
1604
  server.listen(p, "127.0.0.1");
1567
1605
  }, "tryListen");
@@ -1607,7 +1645,10 @@ ${body}`);
1607
1645
  getControlPlaneUrl,
1608
1646
  readConfig,
1609
1647
  startProcessProxy,
1610
- writeConfig
1648
+ writeConfig,
1649
+ LOCAL_PING_PATH,
1650
+ LOCAL_PING_HEADER,
1651
+ LOCAL_PING_HEADER_VALUE
1611
1652
  };
1612
1653
  }
1613
1654
  });
@@ -8988,10 +9029,13 @@ var require_aionui_wrapper = __commonJS({
8988
9029
  }, "onRequest");
8989
9030
  }
8990
9031
  __name(buildRouter, "buildRouter");
8991
- function probeLocalPort(port, timeoutMs = 500) {
9032
+ function probeLocalPort(port, timeoutMs = 800) {
8992
9033
  return new Promise((resolve) => {
8993
9034
  const socket = net.createConnection({ host: "127.0.0.1", port });
8994
- const timer = setTimeout(() => {
9035
+ let tcpSettled = false;
9036
+ const tcpTimer = setTimeout(() => {
9037
+ if (tcpSettled) return;
9038
+ tcpSettled = true;
8995
9039
  try {
8996
9040
  socket.destroy();
8997
9041
  } catch {
@@ -8999,15 +9043,53 @@ var require_aionui_wrapper = __commonJS({
8999
9043
  resolve(false);
9000
9044
  }, timeoutMs);
9001
9045
  socket.once("connect", () => {
9002
- clearTimeout(timer);
9046
+ if (tcpSettled) return;
9047
+ tcpSettled = true;
9048
+ clearTimeout(tcpTimer);
9003
9049
  try {
9004
9050
  socket.end();
9005
9051
  } catch {
9006
9052
  }
9007
- resolve(true);
9053
+ const req = http.request({
9054
+ host: "127.0.0.1",
9055
+ port,
9056
+ method: "GET",
9057
+ path: "/__hs_local_ping__",
9058
+ timeout: timeoutMs,
9059
+ headers: { "host": `127.0.0.1:${port}`, "connection": "close" }
9060
+ }, (res) => {
9061
+ const chunks = [];
9062
+ res.on("data", (c) => chunks.push(c));
9063
+ res.on("end", () => {
9064
+ const header = String(res.headers["x-hs-local-proxy"] || "");
9065
+ if (res.statusCode !== 200 || header !== "1") {
9066
+ resolve(false);
9067
+ return;
9068
+ }
9069
+ try {
9070
+ const parsed = JSON.parse(Buffer.concat(chunks).toString("utf8"));
9071
+ resolve(parsed && parsed.hsLocalProxy === true);
9072
+ } catch {
9073
+ resolve(false);
9074
+ }
9075
+ });
9076
+ res.on("error", () => resolve(false));
9077
+ });
9078
+ req.on("timeout", () => {
9079
+ try {
9080
+ req.destroy();
9081
+ } catch {
9082
+ }
9083
+ ;
9084
+ resolve(false);
9085
+ });
9086
+ req.on("error", () => resolve(false));
9087
+ req.end();
9008
9088
  });
9009
9089
  socket.once("error", () => {
9010
- clearTimeout(timer);
9090
+ if (tcpSettled) return;
9091
+ tcpSettled = true;
9092
+ clearTimeout(tcpTimer);
9011
9093
  resolve(false);
9012
9094
  });
9013
9095
  });
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "2.1.43",
3
+ "version": "2.1.44",
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/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-wrapper-claude-proxy.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/opencode-default-model.test.js && node tests/paths-bundled.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",
8
8
  "prepublishOnly": "npm run build && npm test && node scripts/check-tarball-size.js"
9
9
  },
10
10
  "keywords": [