@simonyea/holysheep-cli 1.7.45 → 1.7.47

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": "1.7.45",
3
+ "version": "1.7.47",
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
  "keywords": [
6
6
  "openai-china",
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ const path = require('path')
3
4
  const { spawn } = require('child_process')
4
5
  const {
5
6
  BASE_URL_ANTHROPIC,
@@ -15,6 +16,8 @@ const {
15
16
  } = require('../tools/claude-process-proxy')
16
17
  const claudeCodeTool = require('../tools/claude-code')
17
18
 
19
+ const INJECT_PATH = path.resolve(__dirname, '../tools/process-proxy-inject.js')
20
+
18
21
  function ensureClaudeProxyConfig(apiKey) {
19
22
  const config = readConfig()
20
23
  const next = claudeCodeTool.buildBridgeConfig(apiKey, BASE_URL_ANTHROPIC, {
@@ -46,10 +49,13 @@ async function runClaude(args = []) {
46
49
  ...process.env,
47
50
  ANTHROPIC_API_KEY: undefined,
48
51
  ANTHROPIC_AUTH_TOKEN: apiKey,
49
- ANTHROPIC_BASE_URL: `http://127.0.0.1:${port}`,
52
+ ANTHROPIC_BASE_URL: BASE_URL_ANTHROPIC,
50
53
  CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1',
51
54
  HOLYSHEEP_CLAUDE_PROCESS_PROXY: '1',
52
55
  HOLYSHEEP_CLAUDE_SESSION_ID: sessionId,
56
+ // 进程级代理注入:强制所有 TCP 连接走本地 bridge CONNECT 隧道
57
+ NODE_OPTIONS: `--require ${INJECT_PATH}`,
58
+ HS_PROXY_URL: proxyUrl,
53
59
  HTTP_PROXY: undefined,
54
60
  HTTPS_PROXY: undefined,
55
61
  ALL_PROXY: undefined,
@@ -152,37 +152,8 @@ function pipeWithCleanup(a, b) {
152
152
 
153
153
  function createProcessProxyServer({ sessionId, configPath = CONFIG_PATH }) {
154
154
  const server = http.createServer(async (clientReq, clientRes) => {
155
- const isDirect = !clientReq.url.startsWith('http')
156
-
157
155
  const doForward = async (lease) => {
158
156
  const config = readConfig(configPath)
159
-
160
- if (isDirect) {
161
- const crsBase = config.baseUrlAnthropic || 'https://api.holysheep.ai'
162
- const target = new URL(clientReq.url, crsBase)
163
- const fwdHeaders = { ...clientReq.headers, ...buildAuthHeaders(config, lease), 'x-hs-node-proxied': '1', host: target.host }
164
- const transport = target.protocol === 'https:' ? https : http
165
- return new Promise((resolve, reject) => {
166
- const fwd = transport.request({
167
- hostname: target.hostname,
168
- port: Number(target.port || (target.protocol === 'https:' ? 443 : 80)),
169
- method: clientReq.method,
170
- path: target.pathname + target.search,
171
- headers: fwdHeaders,
172
- }, (res) => {
173
- if (res.statusCode === 401 || res.statusCode === 403) {
174
- res.resume()
175
- return reject(new Error(`Auth error ${res.statusCode}`))
176
- }
177
- clientRes.writeHead(res.statusCode || 502, res.headers)
178
- res.pipe(clientRes)
179
- resolve()
180
- })
181
- fwd.once('error', reject)
182
- clientReq.pipe(fwd)
183
- })
184
- }
185
-
186
157
  const nodeProxyUrl = deriveNodeProxyUrl(lease)
187
158
  const headers = {
188
159
  ...buildAuthHeaders(config, lease),
@@ -0,0 +1,75 @@
1
+ 'use strict'
2
+ /**
3
+ * 进程级代理注入 — 通过 NODE_OPTIONS=--require 加载
4
+ * patch sock.emit 拦截 'connect' 事件,强制所有 TCP 连接走 CONNECT 隧道
5
+ * 无论 TLSSocket 用何种方式注册监听器都无法绕过
6
+ */
7
+ const net = require('net')
8
+ const { URL } = require('url')
9
+
10
+ const raw = process.env.HS_PROXY_URL
11
+ if (!raw) return
12
+
13
+ let parsed
14
+ try {
15
+ parsed = new URL(raw)
16
+ } catch {
17
+ return
18
+ }
19
+
20
+ const PROXY_HOST = parsed.hostname
21
+ const PROXY_PORT = Number(parsed.port) || 80
22
+ const SKIP = new Set(['127.0.0.1', '::1', 'localhost', '0.0.0.0', PROXY_HOST])
23
+
24
+ const _orig = net.createConnection
25
+
26
+ function proxied(options, cb) {
27
+ const isObj = options !== null && typeof options === 'object'
28
+ const host = isObj
29
+ ? String(options.host || options.hostname || 'localhost')
30
+ : String(options || 'localhost')
31
+ const port = isObj
32
+ ? Number(options.port || 0)
33
+ : Number(arguments[1] || 0)
34
+
35
+ if (!port || SKIP.has(host)) return _orig.apply(this, arguments)
36
+
37
+ const sock = _orig({ host: PROXY_HOST, port: PROXY_PORT })
38
+ let tunnelReady = false
39
+ const origEmit = sock.emit.bind(sock)
40
+
41
+ // patch emit 而不是 on/once:无论监听器怎么注册都能拦截
42
+ sock.emit = function(type) {
43
+ if (type === 'connect' && !tunnelReady) {
44
+ // proxy TCP 已建立,发起 CONNECT 隧道
45
+ sock.write(`CONNECT ${host}:${port} HTTP/1.1\r\nHost: ${host}:${port}\r\n\r\n`)
46
+ let buf = Buffer.alloc(0)
47
+ sock.on('data', function onData(chunk) {
48
+ buf = Buffer.concat([buf, chunk])
49
+ const i = buf.indexOf('\r\n\r\n')
50
+ if (i === -1) return
51
+ sock.removeListener('data', onData)
52
+ const header = buf.slice(0, i).toString()
53
+ if (!header.includes(' 200 ')) {
54
+ sock.emit = origEmit
55
+ sock.destroy(new Error(`CONNECT ${host}:${port} failed: ${header.split('\r\n')[0]}`))
56
+ return
57
+ }
58
+ const rest = buf.slice(i + 4)
59
+ if (rest.length) sock.unshift(rest)
60
+ // 隧道就绪:恢复 emit,触发所有注册的 connect 监听器(含 TLSSocket)
61
+ tunnelReady = true
62
+ sock.emit = origEmit
63
+ origEmit('connect')
64
+ })
65
+ return false
66
+ }
67
+ // eslint-disable-next-line prefer-rest-params
68
+ return origEmit.apply(null, arguments)
69
+ }
70
+
71
+ if (typeof cb === 'function') sock.once('connect', cb)
72
+ return sock
73
+ }
74
+
75
+ net.createConnection = net.connect = proxied