@simonyea/holysheep-cli 1.7.63 → 1.7.65

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/webui/server.js +27 -14
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "1.7.63",
3
+ "version": "1.7.65",
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
  "keywords": [
6
6
  "openai-china",
@@ -4,6 +4,11 @@
4
4
  */
5
5
  'use strict'
6
6
 
7
+ // 设置 DNS 回退:Cloudflare (1.1.1.1) + 阿里 (223.5.5.5) + 系统默认
8
+ // 解决大陆服务器 DNS 解析 api.holysheep.ai 失败 (EAI_AGAIN) 的问题
9
+ const dns = require('dns')
10
+ dns.setServers([...new Set([...dns.getServers(), '1.1.1.1', '223.5.5.5'])])
11
+
7
12
  const http = require('http')
8
13
  const fs = require('fs')
9
14
  const path = require('path')
@@ -21,12 +26,26 @@ function maskKey(key) {
21
26
  return key.slice(0, 6) + '...' + key.slice(-4)
22
27
  }
23
28
 
24
- async function validateApiKey(apiKey) {
29
+ async function fetchWithRetry(url, opts = {}, retries = 3) {
25
30
  const fetch = require('node-fetch')
26
- const res = await fetch(`${BASE_URL_OPENAI}/models`, {
31
+ for (let i = 0; i < retries; i++) {
32
+ try {
33
+ return await fetch(url, { timeout: 10000, ...opts })
34
+ } catch (e) {
35
+ // DNS 暂时失败 (EAI_AGAIN) 或网络抖动,重试
36
+ if (i < retries - 1 && (e.code === 'EAI_AGAIN' || e.code === 'ETIMEDOUT' || e.code === 'ECONNRESET' || e.type === 'system')) {
37
+ await new Promise(r => setTimeout(r, 1500 * (i + 1)))
38
+ continue
39
+ }
40
+ throw e
41
+ }
42
+ }
43
+ }
44
+
45
+ async function validateApiKey(apiKey) {
46
+ const res = await fetchWithRetry(`${BASE_URL_OPENAI}/models`, {
27
47
  method: 'GET',
28
48
  headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
29
- timeout: 10000,
30
49
  })
31
50
  return res.status === 200
32
51
  }
@@ -105,7 +124,7 @@ const UPGRADABLE_TOOLS = [
105
124
  : 'curl -fsSL https://claude.ai/install.sh | bash',
106
125
  },
107
126
  { name: 'Codex CLI', id: 'codex', command: 'codex', versionCmd: 'codex --version', npmPkg: '@openai/codex', installCmd: 'npm install -g @openai/codex@latest' },
108
- { name: 'Droid CLI', id: 'droid', command: 'droid', versionCmd: 'droid --version', npmPkg: null, installCmd: 'brew install --cask droid' },
127
+ { name: 'Droid CLI', id: 'droid', command: 'droid', versionCmd: 'droid --version', npmPkg: null, installCmd: process.platform === 'win32' ? 'winget upgrade --id Droid.Droid' : 'brew install --cask droid' },
109
128
  { name: 'OpenCode', id: 'opencode', command: 'opencode', versionCmd: 'opencode --version', npmPkg: 'opencode-ai', installCmd: 'npm install -g opencode-ai@latest' },
110
129
  { name: 'OpenClaw', id: 'openclaw', command: 'openclaw', versionCmd: 'openclaw --version', npmPkg: 'openclaw', installCmd: 'npm install -g openclaw@latest --ignore-scripts' },
111
130
  { name: 'Gemini CLI', id: 'gemini-cli', command: 'gemini', versionCmd: 'gemini --version', npmPkg: '@google/gemini-cli', installCmd: 'npm install -g @google/gemini-cli@latest' },
@@ -115,14 +134,13 @@ const UPGRADABLE_TOOLS = [
115
134
 
116
135
  let _latestVersion = null
117
136
  let _lastCheckTime = 0
118
- const UPDATE_CHECK_INTERVAL = 30 * 60 * 1000
137
+ const UPDATE_CHECK_INTERVAL = 5 * 60 * 1000
119
138
 
120
139
  async function checkLatestVersion() {
121
140
  const now = Date.now()
122
141
  if (_latestVersion && now - _lastCheckTime < UPDATE_CHECK_INTERVAL) return _latestVersion
123
142
  try {
124
- const fetch = require('node-fetch')
125
- const r = await fetch('https://registry.npmjs.org/@simonyea/holysheep-cli/latest', { timeout: 5000 })
143
+ const r = await fetchWithRetry('https://registry.npmjs.org/@simonyea/holysheep-cli/latest', {}, 2)
126
144
  if (r.ok) {
127
145
  const data = await r.json()
128
146
  _latestVersion = data.version || null
@@ -188,14 +206,9 @@ async function handleBalance(_req, res) {
188
206
  const apiKey = getApiKey()
189
207
  if (!apiKey) return json(res, { error: '未登录' }, 401)
190
208
  try {
191
- const fetch = require('node-fetch')
192
- const controller = new AbortController()
193
- const timer = setTimeout(() => controller.abort(), 15000)
194
- const r = await fetch(`${SHOP_URL}/api/stats/overview`, {
209
+ const r = await fetchWithRetry(`${SHOP_URL}/api/stats/overview`, {
195
210
  headers: { Authorization: `Bearer ${apiKey}` },
196
- signal: controller.signal,
197
211
  })
198
- clearTimeout(timer)
199
212
  if (r.status === 401) return json(res, { error: 'API Key 无效或已过期' }, 401)
200
213
  if (!r.ok) return json(res, { error: `HTTP ${r.status}` }, r.status)
201
214
  const data = await r.json()
@@ -206,7 +219,7 @@ async function handleBalance(_req, res) {
206
219
  totalCalls: Number(data.totalCalls || 0),
207
220
  })
208
221
  } catch (e) {
209
- const msg = e.name === 'AbortError' ? '请求超时,请稍后重试' : e.message
222
+ const msg = e.code === 'EAI_AGAIN' ? 'DNS 解析失败,请检查网络' : e.message
210
223
  json(res, { error: msg }, 500)
211
224
  }
212
225
  }