@simonyea/holysheep-cli 2.1.66 → 2.1.68

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.
@@ -1147,7 +1147,34 @@ var require_claude_code = __commonJS({
1147
1147
  BASE_URL_CLAUDE_RELAY
1148
1148
  } = require_config();
1149
1149
  var { readConfig, writeConfig } = require_claude_process_proxy();
1150
- var SETTINGS_FILE = path.join(os.homedir(), ".claude", "settings.json");
1150
+ function resolveClaudeHomeDir() {
1151
+ const platform = process.env.HOLYSHEEP_TEST_PLATFORM || process.platform;
1152
+ if (platform === "win32") return process.env.USERPROFILE || process.env.HOME || os.homedir();
1153
+ return os.homedir();
1154
+ }
1155
+ __name(resolveClaudeHomeDir, "resolveClaudeHomeDir");
1156
+ function getSettingsFile() {
1157
+ return path.join(resolveClaudeHomeDir(), ".claude", "settings.json");
1158
+ }
1159
+ __name(getSettingsFile, "getSettingsFile");
1160
+ function isLocalProxyBaseUrl(value) {
1161
+ if (!value) return false;
1162
+ try {
1163
+ const url = new URL(String(value));
1164
+ return (url.hostname === "127.0.0.1" || url.hostname === "localhost") && (url.protocol === "http:" || url.protocol === "https:");
1165
+ } catch {
1166
+ return String(value).includes("127.0.0.1") || String(value).includes("localhost");
1167
+ }
1168
+ }
1169
+ __name(isLocalProxyBaseUrl, "isLocalProxyBaseUrl");
1170
+ function hasDaemonProxyMarker(env = {}) {
1171
+ return env.HOLYSHEEP_CLAUDE_LAUNCHER === "hs-claude-proxy" || env.HOLYSHEEP_CLAUDE_PROCESS_PROXY === "1";
1172
+ }
1173
+ __name(hasDaemonProxyMarker, "hasDaemonProxyMarker");
1174
+ function shouldPreserveDaemonProxyEnv(env = {}) {
1175
+ return hasDaemonProxyMarker(env) && isLocalProxyBaseUrl(env.ANTHROPIC_BASE_URL);
1176
+ }
1177
+ __name(shouldPreserveDaemonProxyEnv, "shouldPreserveDaemonProxyEnv");
1151
1178
  function buildBridgeConfig(apiKey, baseUrl, bridge = {}) {
1152
1179
  const relayUrl = bridge.relayUrl || BASE_URL_CLAUDE_RELAY || "";
1153
1180
  return {
@@ -1169,7 +1196,7 @@ var require_claude_code = __commonJS({
1169
1196
  __name(buildBridgeConfig, "buildBridgeConfig");
1170
1197
  function readSettings() {
1171
1198
  try {
1172
- const raw = fs.readFileSync(SETTINGS_FILE, "utf8");
1199
+ const raw = fs.readFileSync(getSettingsFile(), "utf8");
1173
1200
  return JSON.parse(raw.replace(/[\x00-\x1F\x7F]/g, " "));
1174
1201
  } catch {
1175
1202
  return {};
@@ -1177,9 +1204,10 @@ var require_claude_code = __commonJS({
1177
1204
  }
1178
1205
  __name(readSettings, "readSettings");
1179
1206
  function writeSettings(data) {
1180
- const dir = path.dirname(SETTINGS_FILE);
1207
+ const file = getSettingsFile();
1208
+ const dir = path.dirname(file);
1181
1209
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
1182
- fs.writeFileSync(SETTINGS_FILE, JSON.stringify(data, null, 2), "utf8");
1210
+ fs.writeFileSync(file, JSON.stringify(data, null, 2), "utf8");
1183
1211
  }
1184
1212
  __name(writeSettings, "writeSettings");
1185
1213
  function cloneSettings(data) {
@@ -1293,16 +1321,23 @@ var require_claude_code = __commonJS({
1293
1321
  writeConfig(bridgeConfig);
1294
1322
  const settings = readSettings();
1295
1323
  if (!settings.env) settings.env = {};
1324
+ const preserveDaemonProxy = shouldPreserveDaemonProxyEnv(settings.env);
1296
1325
  settings.env.ANTHROPIC_AUTH_TOKEN = apiKey;
1297
- delete settings.env.ANTHROPIC_BASE_URL;
1326
+ if (preserveDaemonProxy) {
1327
+ settings.env.HOLYSHEEP_CLAUDE_LAUNCHER = "hs-claude-proxy";
1328
+ settings.env.HOLYSHEEP_CLAUDE_PROCESS_PROXY = "1";
1329
+ } else {
1330
+ delete settings.env.ANTHROPIC_BASE_URL;
1331
+ settings.env.HOLYSHEEP_CLAUDE_LAUNCHER = "hs";
1332
+ delete settings.env.HOLYSHEEP_CLAUDE_PROCESS_PROXY;
1333
+ }
1298
1334
  settings.env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = "1";
1299
- settings.env.HOLYSHEEP_CLAUDE_LAUNCHER = "hs";
1300
1335
  if (primaryModel) settings.model = primaryModel;
1301
1336
  delete settings.env.ANTHROPIC_API_KEY;
1302
1337
  delete settings.env.HOLYSHEEP_CLAUDE_BRIDGE;
1303
1338
  writeSettings(settings);
1304
1339
  return {
1305
- file: SETTINGS_FILE,
1340
+ file: getSettingsFile(),
1306
1341
  hot: true,
1307
1342
  extraFiles: ["~/.holysheep/claude-proxy.json"]
1308
1343
  };
@@ -1320,7 +1355,7 @@ var require_claude_code = __commonJS({
1320
1355
  writeSettings(settings);
1321
1356
  },
1322
1357
  getConfigPath() {
1323
- return SETTINGS_FILE;
1358
+ return getSettingsFile();
1324
1359
  },
1325
1360
  hint: "\u901A\u8FC7 hs claude \u4EE5\u6574\u8FDB\u7A0B\u4EE3\u7406\u65B9\u5F0F\u542F\u52A8 Claude Code",
1326
1361
  launchCmd: "hs claude",
@@ -1333,7 +1368,8 @@ var require_claude_code = __commonJS({
1333
1368
  detectClaudeRuntime,
1334
1369
  readSettings,
1335
1370
  writeSettings,
1336
- applyRuntimeSettingsOverride
1371
+ applyRuntimeSettingsOverride,
1372
+ _private: { getSettingsFile, resolveClaudeHomeDir, shouldPreserveDaemonProxyEnv, hasDaemonProxyMarker, isLocalProxyBaseUrl }
1337
1373
  };
1338
1374
  }
1339
1375
  });
@@ -4099,11 +4135,11 @@ var require_package = __commonJS({
4099
4135
  "package.json"(exports2, module2) {
4100
4136
  module2.exports = {
4101
4137
  name: "@simonyea/holysheep-cli",
4102
- version: "2.1.66",
4138
+ version: "2.1.68",
4103
4139
  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.",
4104
4140
  scripts: {
4105
4141
  build: "node scripts/build.mjs",
4106
- 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/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js",
4142
+ 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",
4107
4143
  prepublishOnly: "npm run build && npm test && node scripts/check-tarball-size.js"
4108
4144
  },
4109
4145
  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.66",
15
+ version: "2.1.68",
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/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.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-code-configure-preserve.test.js",
20
20
  prepublishOnly: "npm run build && npm test && node scripts/check-tarball-size.js"
21
21
  },
22
22
  keywords: [
@@ -1693,7 +1693,34 @@ var require_claude_code = __commonJS({
1693
1693
  BASE_URL_CLAUDE_RELAY
1694
1694
  } = require_config();
1695
1695
  var { readConfig, writeConfig } = require_claude_process_proxy();
1696
- var SETTINGS_FILE = path.join(os.homedir(), ".claude", "settings.json");
1696
+ function resolveClaudeHomeDir() {
1697
+ const platform = process.env.HOLYSHEEP_TEST_PLATFORM || process.platform;
1698
+ if (platform === "win32") return process.env.USERPROFILE || process.env.HOME || os.homedir();
1699
+ return os.homedir();
1700
+ }
1701
+ __name(resolveClaudeHomeDir, "resolveClaudeHomeDir");
1702
+ function getSettingsFile() {
1703
+ return path.join(resolveClaudeHomeDir(), ".claude", "settings.json");
1704
+ }
1705
+ __name(getSettingsFile, "getSettingsFile");
1706
+ function isLocalProxyBaseUrl(value) {
1707
+ if (!value) return false;
1708
+ try {
1709
+ const url = new URL(String(value));
1710
+ return (url.hostname === "127.0.0.1" || url.hostname === "localhost") && (url.protocol === "http:" || url.protocol === "https:");
1711
+ } catch {
1712
+ return String(value).includes("127.0.0.1") || String(value).includes("localhost");
1713
+ }
1714
+ }
1715
+ __name(isLocalProxyBaseUrl, "isLocalProxyBaseUrl");
1716
+ function hasDaemonProxyMarker(env = {}) {
1717
+ return env.HOLYSHEEP_CLAUDE_LAUNCHER === "hs-claude-proxy" || env.HOLYSHEEP_CLAUDE_PROCESS_PROXY === "1";
1718
+ }
1719
+ __name(hasDaemonProxyMarker, "hasDaemonProxyMarker");
1720
+ function shouldPreserveDaemonProxyEnv(env = {}) {
1721
+ return hasDaemonProxyMarker(env) && isLocalProxyBaseUrl(env.ANTHROPIC_BASE_URL);
1722
+ }
1723
+ __name(shouldPreserveDaemonProxyEnv, "shouldPreserveDaemonProxyEnv");
1697
1724
  function buildBridgeConfig(apiKey, baseUrl, bridge = {}) {
1698
1725
  const relayUrl = bridge.relayUrl || BASE_URL_CLAUDE_RELAY || "";
1699
1726
  return {
@@ -1715,7 +1742,7 @@ var require_claude_code = __commonJS({
1715
1742
  __name(buildBridgeConfig, "buildBridgeConfig");
1716
1743
  function readSettings() {
1717
1744
  try {
1718
- const raw = fs.readFileSync(SETTINGS_FILE, "utf8");
1745
+ const raw = fs.readFileSync(getSettingsFile(), "utf8");
1719
1746
  return JSON.parse(raw.replace(/[\x00-\x1F\x7F]/g, " "));
1720
1747
  } catch {
1721
1748
  return {};
@@ -1723,9 +1750,10 @@ var require_claude_code = __commonJS({
1723
1750
  }
1724
1751
  __name(readSettings, "readSettings");
1725
1752
  function writeSettings(data) {
1726
- const dir = path.dirname(SETTINGS_FILE);
1753
+ const file = getSettingsFile();
1754
+ const dir = path.dirname(file);
1727
1755
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
1728
- fs.writeFileSync(SETTINGS_FILE, JSON.stringify(data, null, 2), "utf8");
1756
+ fs.writeFileSync(file, JSON.stringify(data, null, 2), "utf8");
1729
1757
  }
1730
1758
  __name(writeSettings, "writeSettings");
1731
1759
  function cloneSettings(data) {
@@ -1839,16 +1867,23 @@ var require_claude_code = __commonJS({
1839
1867
  writeConfig(bridgeConfig);
1840
1868
  const settings = readSettings();
1841
1869
  if (!settings.env) settings.env = {};
1870
+ const preserveDaemonProxy = shouldPreserveDaemonProxyEnv(settings.env);
1842
1871
  settings.env.ANTHROPIC_AUTH_TOKEN = apiKey;
1843
- delete settings.env.ANTHROPIC_BASE_URL;
1872
+ if (preserveDaemonProxy) {
1873
+ settings.env.HOLYSHEEP_CLAUDE_LAUNCHER = "hs-claude-proxy";
1874
+ settings.env.HOLYSHEEP_CLAUDE_PROCESS_PROXY = "1";
1875
+ } else {
1876
+ delete settings.env.ANTHROPIC_BASE_URL;
1877
+ settings.env.HOLYSHEEP_CLAUDE_LAUNCHER = "hs";
1878
+ delete settings.env.HOLYSHEEP_CLAUDE_PROCESS_PROXY;
1879
+ }
1844
1880
  settings.env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = "1";
1845
- settings.env.HOLYSHEEP_CLAUDE_LAUNCHER = "hs";
1846
1881
  if (primaryModel) settings.model = primaryModel;
1847
1882
  delete settings.env.ANTHROPIC_API_KEY;
1848
1883
  delete settings.env.HOLYSHEEP_CLAUDE_BRIDGE;
1849
1884
  writeSettings(settings);
1850
1885
  return {
1851
- file: SETTINGS_FILE,
1886
+ file: getSettingsFile(),
1852
1887
  hot: true,
1853
1888
  extraFiles: ["~/.holysheep/claude-proxy.json"]
1854
1889
  };
@@ -1866,7 +1901,7 @@ var require_claude_code = __commonJS({
1866
1901
  writeSettings(settings);
1867
1902
  },
1868
1903
  getConfigPath() {
1869
- return SETTINGS_FILE;
1904
+ return getSettingsFile();
1870
1905
  },
1871
1906
  hint: "\u901A\u8FC7 hs claude \u4EE5\u6574\u8FDB\u7A0B\u4EE3\u7406\u65B9\u5F0F\u542F\u52A8 Claude Code",
1872
1907
  launchCmd: "hs claude",
@@ -1879,7 +1914,8 @@ var require_claude_code = __commonJS({
1879
1914
  detectClaudeRuntime,
1880
1915
  readSettings,
1881
1916
  writeSettings,
1882
- applyRuntimeSettingsOverride
1917
+ applyRuntimeSettingsOverride,
1918
+ _private: { getSettingsFile, resolveClaudeHomeDir, shouldPreserveDaemonProxyEnv, hasDaemonProxyMarker, isLocalProxyBaseUrl }
1883
1919
  };
1884
1920
  }
1885
1921
  });
@@ -7071,7 +7107,7 @@ var require_claude_proxy = __commonJS({
7071
7107
  var path = require("path");
7072
7108
  var os = require("os");
7073
7109
  var http2 = require("http");
7074
- var { spawn, execSync } = require("child_process");
7110
+ var { spawn, execSync, execFileSync } = require("child_process");
7075
7111
  var chalk2 = require("chalk");
7076
7112
  var {
7077
7113
  startProcessProxy,
@@ -7092,6 +7128,19 @@ var require_claude_proxy = __commonJS({
7092
7128
  var DAEMON_READY_TIMEOUT_MS = Number(process.env.HS_CLAUDE_PROXY_DAEMON_READY_TIMEOUT_MS) || 12e3;
7093
7129
  var DAEMON_READY_INTERVAL_MS = Number(process.env.HS_CLAUDE_PROXY_DAEMON_READY_INTERVAL_MS) || 400;
7094
7130
  var DAEMON_TEST_CHILD_EXIT = process.env.HS_CLAUDE_PROXY_DAEMON_TEST_CHILD_EXIT === "1";
7131
+ var WINDOWS_ENV_KEYS = [
7132
+ "ANTHROPIC_BASE_URL",
7133
+ "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC",
7134
+ "HOLYSHEEP_CLAUDE_LAUNCHER",
7135
+ "HOLYSHEEP_CLAUDE_PROCESS_PROXY"
7136
+ ];
7137
+ var platformOverride = null;
7138
+ var winUserEnvWriterOverride = null;
7139
+ var execFileSyncOverride = null;
7140
+ function effectivePlatform() {
7141
+ return platformOverride || process.env.HS_CLAUDE_PROXY_TEST_PLATFORM || process.platform;
7142
+ }
7143
+ __name(effectivePlatform, "effectivePlatform");
7095
7144
  function readPid() {
7096
7145
  try {
7097
7146
  const content = fs.readFileSync(PID_FILE, "utf8").trim();
@@ -7189,13 +7238,17 @@ ${logTail}` : message);
7189
7238
  return err;
7190
7239
  }
7191
7240
  __name(makeDaemonError, "makeDaemonError");
7241
+ function getHolySheepApiKey() {
7242
+ const config = readConfig();
7243
+ return config.apiKey || getApiKey();
7244
+ }
7245
+ __name(getHolySheepApiKey, "getHolySheepApiKey");
7192
7246
  function writeBaseUrlToSettings(port) {
7193
7247
  const settings = claudeCodeTool.readSettings();
7194
7248
  if (!settings.env) settings.env = {};
7195
7249
  settings.env.ANTHROPIC_BASE_URL = getLocalProxyUrl(port);
7196
7250
  if (settings.env.ANTHROPIC_AUTH_TOKEN === void 0 || settings.env.ANTHROPIC_AUTH_TOKEN === null || settings.env.ANTHROPIC_AUTH_TOKEN === "") {
7197
- const config = readConfig();
7198
- const apiKey = config.apiKey || getApiKey();
7251
+ const apiKey = getHolySheepApiKey();
7199
7252
  if (apiKey) settings.env.ANTHROPIC_AUTH_TOKEN = apiKey;
7200
7253
  }
7201
7254
  settings.env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = "1";
@@ -7204,15 +7257,98 @@ ${logTail}` : message);
7204
7257
  claudeCodeTool.writeSettings(settings);
7205
7258
  }
7206
7259
  __name(writeBaseUrlToSettings, "writeBaseUrlToSettings");
7260
+ function quotePowerShellString(value) {
7261
+ return `'${String(value).replace(/'/g, "''")}'`;
7262
+ }
7263
+ __name(quotePowerShellString, "quotePowerShellString");
7264
+ function tailText(value, max = 1200) {
7265
+ const text = String(value || "").trim();
7266
+ return text.length > max ? text.slice(-max) : text;
7267
+ }
7268
+ __name(tailText, "tailText");
7269
+ function runPowerShellUserEnvScript(script) {
7270
+ const runner = execFileSyncOverride || execFileSync;
7271
+ try {
7272
+ runner("powershell.exe", ["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", script], {
7273
+ encoding: "utf8",
7274
+ windowsHide: true
7275
+ });
7276
+ } catch (err) {
7277
+ const stderr = tailText((err == null ? void 0 : err.stderr) || (err == null ? void 0 : err.stdout) || (err == null ? void 0 : err.message) || err);
7278
+ const code = err && (err.status ?? err.code ?? err.signal ?? "unknown");
7279
+ throw new Error(`Windows \u7528\u6237\u7EA7\u73AF\u5883\u53D8\u91CF\u5199\u5165\u5931\u8D25 (powershell exit=${code}): ${stderr || "no stderr"}`);
7280
+ }
7281
+ }
7282
+ __name(runPowerShellUserEnvScript, "runPowerShellUserEnvScript");
7283
+ function defaultWinUserEnvWriter(action, key, value) {
7284
+ if (process.env.HS_CLAUDE_PROXY_TEST_WIN_ENV_FILE) {
7285
+ const file = process.env.HS_CLAUDE_PROXY_TEST_WIN_ENV_FILE;
7286
+ let env = {};
7287
+ try {
7288
+ env = JSON.parse(fs.readFileSync(file, "utf8"));
7289
+ } catch {
7290
+ }
7291
+ if (action === "delete") delete env[key];
7292
+ else env[key] = value;
7293
+ fs.mkdirSync(path.dirname(file), { recursive: true });
7294
+ fs.writeFileSync(file, JSON.stringify(env, null, 2), "utf8");
7295
+ return;
7296
+ }
7297
+ if (effectivePlatform() !== "win32") return;
7298
+ if (!/^[A-Z0-9_]+$/i.test(String(key))) throw new Error(`Invalid env var name: ${key}`);
7299
+ const ps = action === "delete" ? `[Environment]::SetEnvironmentVariable(${quotePowerShellString(key)}, $null, 'User')` : `[Environment]::SetEnvironmentVariable(${quotePowerShellString(key)}, ${quotePowerShellString(value || "")}, 'User')`;
7300
+ runPowerShellUserEnvScript(ps);
7301
+ }
7302
+ __name(defaultWinUserEnvWriter, "defaultWinUserEnvWriter");
7303
+ function getWinUserEnvWriter() {
7304
+ if (winUserEnvWriterOverride) return winUserEnvWriterOverride;
7305
+ return defaultWinUserEnvWriter;
7306
+ }
7307
+ __name(getWinUserEnvWriter, "getWinUserEnvWriter");
7308
+ function writeWindowsUserProxyEnv(port) {
7309
+ if (effectivePlatform() !== "win32") return false;
7310
+ const apiKey = getHolySheepApiKey();
7311
+ const env = {
7312
+ ANTHROPIC_BASE_URL: getLocalProxyUrl(port),
7313
+ ...apiKey ? { ANTHROPIC_AUTH_TOKEN: apiKey } : {},
7314
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1",
7315
+ HOLYSHEEP_CLAUDE_LAUNCHER: "hs-claude-proxy",
7316
+ HOLYSHEEP_CLAUDE_PROCESS_PROXY: "1"
7317
+ };
7318
+ const writer = getWinUserEnvWriter();
7319
+ for (const [key, value] of Object.entries(env)) writer("set", key, value);
7320
+ return true;
7321
+ }
7322
+ __name(writeWindowsUserProxyEnv, "writeWindowsUserProxyEnv");
7323
+ function persistVsCodeProxyEnvironment(port) {
7324
+ writeBaseUrlToSettings(port);
7325
+ const wroteWindowsEnv = writeWindowsUserProxyEnv(port);
7326
+ return { wroteWindowsEnv };
7327
+ }
7328
+ __name(persistVsCodeProxyEnvironment, "persistVsCodeProxyEnvironment");
7207
7329
  function clearBaseUrlFromSettings() {
7208
7330
  var _a;
7209
7331
  const settings = claudeCodeTool.readSettings();
7210
7332
  if (isLocalProxyBaseUrl((_a = settings.env) == null ? void 0 : _a.ANTHROPIC_BASE_URL)) {
7211
7333
  delete settings.env.ANTHROPIC_BASE_URL;
7334
+ if (settings.env.HOLYSHEEP_CLAUDE_LAUNCHER === "hs-claude-proxy") delete settings.env.HOLYSHEEP_CLAUDE_LAUNCHER;
7335
+ if (settings.env.HOLYSHEEP_CLAUDE_PROCESS_PROXY === "1") delete settings.env.HOLYSHEEP_CLAUDE_PROCESS_PROXY;
7212
7336
  claudeCodeTool.writeSettings(settings);
7213
7337
  }
7214
7338
  }
7215
7339
  __name(clearBaseUrlFromSettings, "clearBaseUrlFromSettings");
7340
+ function clearWindowsUserProxyEnv() {
7341
+ if (effectivePlatform() !== "win32") return false;
7342
+ const writer = getWinUserEnvWriter();
7343
+ for (const key of WINDOWS_ENV_KEYS) writer("delete", key);
7344
+ return true;
7345
+ }
7346
+ __name(clearWindowsUserProxyEnv, "clearWindowsUserProxyEnv");
7347
+ function clearVsCodeProxyEnvironment() {
7348
+ clearBaseUrlFromSettings();
7349
+ clearWindowsUserProxyEnv();
7350
+ }
7351
+ __name(clearVsCodeProxyEnvironment, "clearVsCodeProxyEnvironment");
7216
7352
  function isLocalProxyBaseUrl(value) {
7217
7353
  if (!value) return false;
7218
7354
  try {
@@ -7245,7 +7381,7 @@ ${logTail}` : message);
7245
7381
  } else {
7246
7382
  console.log(chalk2.gray("\u4EE3\u7406\u8FDB\u7A0B\u5DF2\u4E0D\u5B58\u5728"));
7247
7383
  }
7248
- clearBaseUrlFromSettings();
7384
+ clearVsCodeProxyEnvironment();
7249
7385
  clearPid();
7250
7386
  }
7251
7387
  __name(handleStop, "handleStop");
@@ -7268,7 +7404,7 @@ ${logTail}` : message);
7268
7404
  } else {
7269
7405
  console.log(chalk2.yellow("\u4EE3\u7406\u8FDB\u7A0B\u5DF2\u9000\u51FA"));
7270
7406
  clearPid();
7271
- clearBaseUrlFromSettings();
7407
+ clearVsCodeProxyEnvironment();
7272
7408
  }
7273
7409
  }
7274
7410
  __name(handleStatus, "handleStatus");
@@ -7278,8 +7414,9 @@ ${logTail}` : message);
7278
7414
  }
7279
7415
  const info = readPid();
7280
7416
  if (info && isProcessAlive(info.pid) && await isProxyHealthy(info.port)) {
7281
- writeBaseUrlToSettings(info.port);
7417
+ const persisted = persistVsCodeProxyEnvironment(info.port);
7282
7418
  console.log(chalk2.green(`\u4EE3\u7406\u5DF2\u5728\u8FD0\u884C (PID ${info.pid}, \u7AEF\u53E3 ${info.port})`));
7419
+ if (persisted.wroteWindowsEnv) console.log(chalk2.cyan("Windows \u7528\u6237\uFF1A\u8BF7\u5B8C\u5168\u9000\u51FA\u5E76\u91CD\u5F00 VS Code\uFF0C\u8BA9\u7528\u6237\u7EA7\u73AF\u5883\u53D8\u91CF\u751F\u6548"));
7283
7420
  return;
7284
7421
  }
7285
7422
  const { selfEntrypoint } = require_paths();
@@ -7317,13 +7454,14 @@ ${logTail}` : message);
7317
7454
  }
7318
7455
  const latest = await readHealthyPid({ timeoutMs: 1e3 });
7319
7456
  if (latest) {
7320
- writeBaseUrlToSettings(latest.port);
7457
+ const persisted = persistVsCodeProxyEnvironment(latest.port);
7321
7458
  console.log(chalk2.green(`\u4EE3\u7406\u5DF2\u5728\u540E\u53F0\u542F\u52A8`));
7322
7459
  console.log(chalk2.gray(` PID: ${latest.pid}`));
7323
7460
  console.log(chalk2.gray(` \u7AEF\u53E3: ${latest.port}`));
7324
7461
  console.log(chalk2.gray(` \u5730\u5740: ${getLocalProxyUrl(latest.port)}`));
7325
7462
  console.log(chalk2.gray(` \u65E5\u5FD7: ${LOG_FILE}`));
7326
7463
  console.log(chalk2.cyan("\n VS Code Claude \u6269\u5C55\u73B0\u5728\u53EF\u4EE5\u4F7F\u7528\u4E86"));
7464
+ if (persisted.wroteWindowsEnv) console.log(chalk2.cyan(" Windows \u7528\u6237\uFF1A\u8BF7\u5B8C\u5168\u9000\u51FA\u5E76\u91CD\u5F00 VS Code\uFF0C\u8BA9\u7528\u6237\u7EA7\u73AF\u5883\u53D8\u91CF\u751F\u6548"));
7327
7465
  return;
7328
7466
  }
7329
7467
  if (child.exitCode !== null) {
@@ -7356,7 +7494,7 @@ ${logTail}` : message);
7356
7494
  console.log(chalk2.gray("\u542F\u52A8 Claude \u4EE3\u7406..."));
7357
7495
  const { server, port, sessionId } = await startProcessProxy({});
7358
7496
  writePid(process.pid, port, sessionId);
7359
- writeBaseUrlToSettings(port);
7497
+ persistVsCodeProxyEnvironment(port);
7360
7498
  console.log(chalk2.green(`
7361
7499
  \u2713 Claude \u4EE3\u7406\u5DF2\u542F\u52A8`));
7362
7500
  console.log(chalk2.gray(` \u7AEF\u53E3: ${port}`));
@@ -7366,7 +7504,7 @@ ${logTail}` : message);
7366
7504
  console.log(chalk2.gray(" \u6309 Ctrl+C \u505C\u6B62\n"));
7367
7505
  const cleanup = /* @__PURE__ */ __name(async () => {
7368
7506
  console.log(chalk2.gray("\n\u6B63\u5728\u505C\u6B62..."));
7369
- clearBaseUrlFromSettings();
7507
+ clearVsCodeProxyEnvironment();
7370
7508
  clearPid();
7371
7509
  server.close();
7372
7510
  await closeSession(void 0, sessionId);
@@ -7402,7 +7540,20 @@ ${logTail}` : message);
7402
7540
  probeLocalProxy,
7403
7541
  readHealthyPid,
7404
7542
  daemonLogFile: /* @__PURE__ */ __name(() => LOG_FILE, "daemonLogFile"),
7405
- daemonPidFile: /* @__PURE__ */ __name(() => PID_FILE, "daemonPidFile")
7543
+ daemonPidFile: /* @__PURE__ */ __name(() => PID_FILE, "daemonPidFile"),
7544
+ persistVsCodeProxyEnvironment,
7545
+ writeWindowsUserProxyEnv,
7546
+ clearWindowsUserProxyEnv,
7547
+ defaultWinUserEnvWriter,
7548
+ setPlatformOverride(value) {
7549
+ platformOverride = value || null;
7550
+ },
7551
+ setWinUserEnvWriterForTest(writer) {
7552
+ winUserEnvWriterOverride = writer || null;
7553
+ },
7554
+ setExecFileSyncForTest(runner) {
7555
+ execFileSyncOverride = runner || null;
7556
+ }
7406
7557
  };
7407
7558
  module2.exports = claudeProxy;
7408
7559
  }
@@ -10238,6 +10389,7 @@ var require_aionui_wrapper = __commonJS({
10238
10389
  }
10239
10390
  __name(_startDetachedNpmUpgrade, "_startDetachedNpmUpgrade");
10240
10391
  function _ensureClaudeProxyConfig(apiKey) {
10392
+ var _a;
10241
10393
  const config = claudeProcessProxy.readConfig();
10242
10394
  const next = claudeCodeTool.buildBridgeConfig(apiKey, BASE_URL_ANTHROPIC, {
10243
10395
  ...config,
@@ -10251,14 +10403,21 @@ var require_aionui_wrapper = __commonJS({
10251
10403
  try {
10252
10404
  const existing = claudeCodeTool.readSettings();
10253
10405
  const hasToken = existing && existing.env && existing.env.ANTHROPIC_AUTH_TOKEN === apiKey;
10254
- const hasLauncherMark = existing && existing.env && existing.env.HOLYSHEEP_CLAUDE_LAUNCHER === "hs";
10406
+ const preserveDaemonProxy = typeof ((_a = claudeCodeTool._private) == null ? void 0 : _a.shouldPreserveDaemonProxyEnv) === "function" ? claudeCodeTool._private.shouldPreserveDaemonProxyEnv(existing && existing.env || {}) : false;
10407
+ const hasLauncherMark = existing && existing.env && existing.env.HOLYSHEEP_CLAUDE_LAUNCHER === (preserveDaemonProxy ? "hs-claude-proxy" : "hs");
10255
10408
  if (!hasToken || !hasLauncherMark) {
10256
10409
  const settings = existing || {};
10257
10410
  if (!settings.env) settings.env = {};
10258
10411
  settings.env.ANTHROPIC_AUTH_TOKEN = apiKey;
10259
- delete settings.env.ANTHROPIC_BASE_URL;
10412
+ if (preserveDaemonProxy) {
10413
+ settings.env.HOLYSHEEP_CLAUDE_LAUNCHER = "hs-claude-proxy";
10414
+ settings.env.HOLYSHEEP_CLAUDE_PROCESS_PROXY = "1";
10415
+ } else {
10416
+ delete settings.env.ANTHROPIC_BASE_URL;
10417
+ settings.env.HOLYSHEEP_CLAUDE_LAUNCHER = "hs";
10418
+ delete settings.env.HOLYSHEEP_CLAUDE_PROCESS_PROXY;
10419
+ }
10260
10420
  settings.env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = "1";
10261
- settings.env.HOLYSHEEP_CLAUDE_LAUNCHER = "hs";
10262
10421
  delete settings.env.ANTHROPIC_API_KEY;
10263
10422
  delete settings.env.HOLYSHEEP_CLAUDE_BRIDGE;
10264
10423
  claudeCodeTool.writeSettings(settings);
@@ -10950,7 +11109,7 @@ var require_claude = __commonJS({
10950
11109
  }
10951
11110
  __name(ensureClaudeProxyConfig, "ensureClaudeProxyConfig");
10952
11111
  async function runClaude(args = []) {
10953
- var _a;
11112
+ var _a, _b;
10954
11113
  const config = readConfig();
10955
11114
  const apiKey = config.apiKey || getApiKey();
10956
11115
  if (!apiKey) {
@@ -10976,7 +11135,8 @@ var require_claude = __commonJS({
10976
11135
  throw err;
10977
11136
  }
10978
11137
  const settings = claudeCodeTool.readSettings();
10979
- if ((_a = settings.env) == null ? void 0 : _a.ANTHROPIC_BASE_URL) {
11138
+ const shouldPreserveDaemonProxy = typeof ((_a = claudeCodeTool._private) == null ? void 0 : _a.shouldPreserveDaemonProxyEnv) === "function" ? claudeCodeTool._private.shouldPreserveDaemonProxyEnv(settings.env || {}) : false;
11139
+ if (((_b = settings.env) == null ? void 0 : _b.ANTHROPIC_BASE_URL) && !shouldPreserveDaemonProxy) {
10980
11140
  delete settings.env.ANTHROPIC_BASE_URL;
10981
11141
  claudeCodeTool.writeSettings(settings);
10982
11142
  }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "2.1.66",
3
+ "version": "2.1.68",
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/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.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-code-configure-preserve.test.js",
8
8
  "prepublishOnly": "npm run build && npm test && node scripts/check-tarball-size.js"
9
9
  },
10
10
  "keywords": [