@simonyea/holysheep-cli 2.1.33 → 2.1.34

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,7 +1,7 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "2.1.33",
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.",
3
+ "version": "2.1.34",
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
  "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",
7
7
  "prepublishOnly": "node scripts/check-tarball-size.js"
@@ -229,8 +229,17 @@ function deriveNodeProxyUrl(lease) {
229
229
  if (process.env.HS_CLAUDE_NODE_PROXY_OVERRIDE) {
230
230
  return String(process.env.HS_CLAUDE_NODE_PROXY_OVERRIDE).replace(/\/+$/, '')
231
231
  }
232
- if (lease.nodeProxyUrl) return String(lease.nodeProxyUrl)
233
- if (!lease.nodeBaseUrl) throw new Error('Lease does not include node proxy information')
232
+ // [HolySheep fork v2.1.34 / hs23] Distinguish "field present but empty"
233
+ // (sub2api nodes have no process-proxy) from "field absent" (old lease format).
234
+ // Control plane sets nodeProxyUrl:"" for sub2api nodes = no process proxy exists.
235
+ // Return null so callers skip node-proxy and go straight to direct-https.
236
+ // Only fall through to port inference when field is entirely absent (legacy leases).
237
+ if (Object.prototype.hasOwnProperty.call(lease, 'nodeProxyUrl')) {
238
+ if (!lease.nodeProxyUrl) return null // explicit empty = no proxy on this node
239
+ return String(lease.nodeProxyUrl)
240
+ }
241
+ // Legacy fallback: field absent → infer proxy port from nodeBaseUrl
242
+ if (!lease.nodeBaseUrl) return null
234
243
  const upstream = new URL(String(lease.nodeBaseUrl))
235
244
  const proxyPort = upstream.port === '3101' ? '3129' : upstream.port
236
245
  upstream.port = proxyPort || '3129'
@@ -678,6 +687,16 @@ function createProcessProxyServer({ sessionId, configPath = CONFIG_PATH, allowAn
678
687
  const config = readConfig(configPath)
679
688
  const nodeProxyUrl = deriveNodeProxyUrl(lease)
680
689
 
690
+ // [HolySheep fork v2.1.34 / hs23] nodeProxyUrl===null means the control
691
+ // plane signalled this node has no process proxy (sub2api nodes).
692
+ // Skip node-proxy entirely and go straight to direct-https. This avoids
693
+ // the ECONNREFUSED → retry × MAX_PROXY_RETRIES delay that was burning
694
+ // ~5 s before falling back.
695
+ if (nodeProxyUrl === null) {
696
+ logProxyTiming('request.direct-noproxy', { sessionId, nodeId: lease.nodeId || '', attempt })
697
+ return forwardDirectHttps({ config, lease, clientReq, clientRes, trace: null })
698
+ }
699
+
681
700
  if (isDirect) {
682
701
  const crsBase = config.baseUrlAnthropic || 'https://api.holysheep.ai'
683
702
  const target = new URL(clientReq.url, crsBase)
@@ -824,8 +843,23 @@ function createProcessProxyServer({ sessionId, configPath = CONFIG_PATH, allowAn
824
843
  }
825
844
 
826
845
  const doConnect = async (lease) => {
846
+ const nodeProxyUrl = deriveNodeProxyUrl(lease)
847
+ // [HolySheep fork v2.1.34 / hs23] No process proxy on this node (sub2api).
848
+ // CONNECT tunnels go directly to the target host — no bridge headers needed.
849
+ if (nodeProxyUrl === null) {
850
+ logProxyTiming('connect.direct-noproxy', { sessionId, nodeId: lease.nodeId || '', target })
851
+ const upstreamSocket = await new Promise((resolve, reject) => {
852
+ const sock = net.connect(port, host, () => resolve(sock))
853
+ sock.once('error', reject)
854
+ sock.setTimeout(15000, () => sock.destroy(new Error('CONNECT direct tunnel timeout')))
855
+ })
856
+ clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n')
857
+ if (head?.length) upstreamSocket.write(head)
858
+ pipeWithCleanup(clientSocket, upstreamSocket)
859
+ return
860
+ }
827
861
  const upstreamSocket = await createConnectTunnel(
828
- deriveNodeProxyUrl(lease),
862
+ nodeProxyUrl,
829
863
  target,
830
864
  buildAuthHeaders(readConfig(configPath), lease)
831
865
  )