@simonyea/holysheep-cli 2.1.29 → 2.1.30

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "2.1.29",
3
+ "version": "2.1.30",
4
4
  "description": "Claude Code/Cursor/Cline API relay for China \u2014 \u00a51=$1, WeChat/Alipay payment, no credit card, no VPN. One command setup for all AI coding tools.",
5
5
  "scripts": {
6
6
  "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",
@@ -205,6 +205,26 @@ function buildAuthHeaders(config, lease) {
205
205
  }
206
206
  }
207
207
 
208
+ // [HolySheep fork v2.1.29 / hs22] Rewrite User-Agent away from claude-cli/*.
209
+ // CRS enforces a "Claude Code CLI must use hs claude" policy keyed on UA —
210
+ // when it sees claude-cli/* or claude-code/*, it 403s even with valid bridge
211
+ // headers, under the assumption the user bypassed the wrapper. Every forward
212
+ // path (node-proxy + direct-https fallback) now normalises UA to
213
+ // holysheep-cli so the wrapper identity is preserved end-to-end.
214
+ function sanitizeClaudeClientHeaders(headers, config) {
215
+ const out = { ...(headers || {}) }
216
+ for (const k of Object.keys(out)) {
217
+ if (/^x-forwarded-|^x-real-ip$|^forwarded$|^via$/i.test(k)) {
218
+ delete out[k]
219
+ continue
220
+ }
221
+ if (/^user-agent$/i.test(k) && /claude-cli|claude-code/i.test(String(out[k] || ''))) {
222
+ out[k] = `holysheep-cli/${(config && config.cliVersion) || 'process-proxy'} (hs-claude-proxy)`
223
+ }
224
+ }
225
+ return out
226
+ }
227
+
208
228
  function deriveNodeProxyUrl(lease) {
209
229
  if (process.env.HS_CLAUDE_NODE_PROXY_OVERRIDE) {
210
230
  return String(process.env.HS_CLAUDE_NODE_PROXY_OVERRIDE).replace(/\/+$/, '')
@@ -244,12 +264,7 @@ function forwardDirectHttps({ config, lease, clientReq, clientRes, trace }) {
244
264
  // (or a proxy earlier in the chain could tag the request) and leak the
245
265
  // loopback origin / real client IP to api.holysheep.ai. The upstream
246
266
  // doesn't need them — it authenticates off bridge headers + API key.
247
- const sanitized = { ...clientReq.headers }
248
- for (const k of Object.keys(sanitized)) {
249
- if (/^x-forwarded-|^x-real-ip$|^forwarded$|^via$/i.test(k)) {
250
- delete sanitized[k]
251
- }
252
- }
267
+ const sanitized = sanitizeClaudeClientHeaders(clientReq.headers, config)
253
268
  const headers = {
254
269
  ...sanitized,
255
270
  ...buildAuthHeaders(config, lease),
@@ -375,8 +390,14 @@ function forwardViaNodeProxy({ nodeProxyUrl, targetUrl, clientReq, clientRes, ex
375
390
  stallTimer = setTimeout(() => failWithAnthropicError('upstream stream stalled'), STALL_TIMEOUT_MS)
376
391
  }
377
392
 
393
+ // [HolySheep fork v2.1.29 / hs22] Same UA-rewrite logic as forwardDirectHttps.
394
+ // Even when we go through node4:3129, the forward-proxy delivers the UA
395
+ // verbatim to upstream CRS; keeping claude-cli/* gets us 403.
396
+ // `extraHeaders` already contains bridge auth via buildAuthHeaders.
397
+ // `config` may be undefined here because forwardViaNodeProxy doesn't take
398
+ // one; use a minimal stub — cliVersion is optional.
378
399
  const finalHeaders = {
379
- ...clientReq.headers,
400
+ ...sanitizeClaudeClientHeaders(clientReq.headers, { cliVersion: undefined }),
380
401
  ...extraHeaders,
381
402
  host: targetUrl.host,
382
403
  connection: 'close',