@simonyea/holysheep-cli 1.7.39 → 1.7.41

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.39",
3
+ "version": "1.7.41",
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",
@@ -63,45 +63,47 @@ function killPortListeners(port) {
63
63
  return killed
64
64
  }
65
65
 
66
- // bridge 启动前调用:清空 gatewayStartedAt,让 watchdog 以 bridgeStartedAt(进程刚启动)
67
- // 为基准,并把宽限期延长到 60s,确保 gateway 有足够时间启动。
68
- function prepareForRestart(gatewayPort) {
66
+ function waitPortFree(port, maxTries, intervalMs) {
67
+ for (let i = 0; i < maxTries; i++) {
68
+ if (openclawTool.getPortListeners(port).length === 0) return true
69
+ const t0 = Date.now()
70
+ while (Date.now() - t0 < intervalMs) {}
71
+ }
72
+ return openclawTool.getPortListeners(port).length === 0
73
+ }
74
+
75
+ // 在 kill gateway 之前调用:禁用 watchdog,bridge 不会因 gateway 短暂下线而自杀
76
+ function disableWatchdog() {
69
77
  const { BRIDGE_CONFIG_FILE } = require('../tools/openclaw-bridge')
70
78
  const fs = require('fs')
71
79
  try {
72
80
  const raw = JSON.parse(fs.readFileSync(BRIDGE_CONFIG_FILE, 'utf8'))
73
- raw.gatewayStartedAt = null // watchdog fallback 到 bridgeStartedAt(始终是刚启动的时间)
74
- raw.gatewayPort = gatewayPort
75
81
  if (!raw.watchdog) raw.watchdog = {}
76
- raw.watchdog.startupGraceMs = 60000 // 给 bridge+gateway 全套重启留出 60s
82
+ raw.watchdog.enabled = false
83
+ raw.gatewayPid = null // 清旧 PID,防止 PID 检查误判
77
84
  fs.writeFileSync(BRIDGE_CONFIG_FILE, JSON.stringify(raw, null, 2), 'utf8')
78
- } catch {}
85
+ } catch (e) {
86
+ console.log(chalk.yellow(` ⚠ 无法更新 Bridge 配置: ${e.message}`))
87
+ }
79
88
  }
80
89
 
81
- // 在 gateway 确认就绪后调用:写入真实 gatewayStartedAt,恢复正常 30s 宽限期。
90
+ // 在 gateway 确认就绪后调用:重新启用 watchdog,写入真实 gatewayStartedAt
82
91
  function refreshGatewayStartedAt(gatewayPort) {
83
92
  const { BRIDGE_CONFIG_FILE } = require('../tools/openclaw-bridge')
84
93
  const fs = require('fs')
85
94
  try {
86
95
  const raw = JSON.parse(fs.readFileSync(BRIDGE_CONFIG_FILE, 'utf8'))
87
96
  raw.gatewayStartedAt = new Date().toISOString()
88
- raw.gatewayPort = gatewayPort
89
97
  raw.gatewayPid = null
98
+ raw.gatewayPort = gatewayPort
90
99
  raw.gatewayLaunchMode = 'direct-process'
91
- if (raw.watchdog) raw.watchdog.startupGraceMs = 30000
100
+ if (!raw.watchdog) raw.watchdog = {}
101
+ raw.watchdog.startupGraceMs = 30000
102
+ raw.watchdog.enabled = true // gateway 已就绪,安全地重新启用 watchdog
92
103
  fs.writeFileSync(BRIDGE_CONFIG_FILE, JSON.stringify(raw, null, 2), 'utf8')
93
104
  } catch {}
94
105
  }
95
106
 
96
- function waitPortFree(port, maxTries, intervalMs) {
97
- for (let i = 0; i < maxTries; i++) {
98
- if (openclawTool.getPortListeners(port).length === 0) return true
99
- const t0 = Date.now()
100
- while (Date.now() - t0 < intervalMs) {}
101
- }
102
- return openclawTool.getPortListeners(port).length === 0
103
- }
104
-
105
107
  function findChrome() {
106
108
  const { existsSync } = require('fs')
107
109
  if (process.platform === 'darwin') {
@@ -165,39 +167,34 @@ async function openclaw() {
165
167
  const bridgePort = openclawTool.getBridgePort()
166
168
  const gatewayPort = openclawTool.getGatewayPort()
167
169
 
168
- // 在所有 spawn 之前写好 config:清空 gatewayStartedAt + 延长宽限期到 60s
169
- // 这样新 bridge 的 watchdog 第一次 tick 读到的就是新鲜的基准时间,不会立即过期
170
- prepareForRestart(gatewayPort)
170
+ // 先禁用 watchdog,防止后续 kill gateway 期间 bridge 误判自杀
171
+ disableWatchdog()
171
172
 
172
- // 先杀掉旧 Bridge,再启动新的
173
- const existingBridgeListeners = openclawTool.getPortListeners(bridgePort)
174
- if (existingBridgeListeners.length > 0) {
175
- process.stdout.write(chalk.gray(` 正在重启 Bridge (端口 ${bridgePort})... `))
176
- killPortListeners(bridgePort)
177
- waitPortFree(bridgePort, 10, 200)
173
+ // Bridge:只确保运行,不重启
174
+ if (checkBridgeHealth(bridgePort)) {
175
+ console.log(chalk.green(`✓ Bridge 已运行 (端口 ${bridgePort})`))
178
176
  } else {
179
177
  process.stdout.write(chalk.gray(` 正在启动 Bridge (端口 ${bridgePort})... `))
180
- }
181
-
182
- const scriptPath = path.join(__dirname, '..', 'index.js')
183
- const spawnCmd = isWin ? 'node' : process.execPath
184
- const child = spawn(spawnCmd, [scriptPath, 'openclaw-bridge', '--port', String(bridgePort)], {
185
- detached: true,
186
- stdio: 'ignore',
187
- windowsHide: true,
188
- })
189
- child.unref()
178
+ const scriptPath = path.join(__dirname, '..', 'index.js')
179
+ const spawnCmd = isWin ? 'node' : process.execPath
180
+ const child = spawn(spawnCmd, [scriptPath, 'openclaw-bridge', '--port', String(bridgePort)], {
181
+ detached: true,
182
+ stdio: 'ignore',
183
+ windowsHide: true,
184
+ })
185
+ child.unref()
190
186
 
191
- const bridgeReady = waitForPort(() => checkBridgeHealth(bridgePort), 10, 1000)
192
- if (bridgeReady) {
193
- console.log(chalk.green('✓'))
194
- } else {
195
- console.log(chalk.red('✗'))
196
- console.log(chalk.red(` Bridge 启动失败,请手动运行: hs openclaw-bridge --port ${bridgePort}`))
197
- process.exit(1)
187
+ const bridgeReady = waitForPort(() => checkBridgeHealth(bridgePort), 10, 1000)
188
+ if (bridgeReady) {
189
+ console.log(chalk.green('✓'))
190
+ } else {
191
+ console.log(chalk.red('✗'))
192
+ console.log(chalk.red(` Bridge 启动失败,请手动运行: hs openclaw-bridge --port ${bridgePort}`))
193
+ process.exit(1)
194
+ }
198
195
  }
199
196
 
200
- // 先杀掉旧 Gateway,再启动新的(避免端口残留导致新进程无法绑定)
197
+ // Gateway:kill 旧的,直接 spawn 新的(明确 --port,避免 service 配置不一致)
201
198
  const existingGatewayListeners = openclawTool.getPortListeners(gatewayPort)
202
199
  if (existingGatewayListeners.length > 0) {
203
200
  process.stdout.write(chalk.gray(` 正在重启 Gateway (端口 ${gatewayPort})... `))
@@ -208,27 +205,17 @@ async function openclaw() {
208
205
  }
209
206
 
210
207
  const preferNpx = runtime.via === 'npx'
211
- const gatewayStartArgs = preferNpx ? ['openclaw', 'gateway', 'start'] : ['gateway', 'start']
212
- const gatewayStartCmd = preferNpx ? 'npx' : 'openclaw'
213
- const serviceResult = spawnSync(gatewayStartCmd, gatewayStartArgs, {
208
+ const gatewayArgs = preferNpx
209
+ ? ['openclaw', 'gateway', '--port', String(gatewayPort)]
210
+ : ['gateway', '--port', String(gatewayPort)]
211
+ const gatewayCmd = preferNpx ? 'npx' : 'openclaw'
212
+ const gatewayChild = spawn(gatewayCmd, gatewayArgs, {
213
+ detached: true,
214
214
  stdio: 'ignore',
215
- timeout: 10000,
216
215
  shell: isWin,
216
+ windowsHide: true,
217
217
  })
218
-
219
- if (serviceResult.status !== 0) {
220
- const directArgs = preferNpx
221
- ? ['openclaw', 'gateway', '--port', String(gatewayPort)]
222
- : ['gateway', '--port', String(gatewayPort)]
223
- const directCmd = preferNpx ? 'npx' : 'openclaw'
224
- const gatewayChild = spawn(directCmd, directArgs, {
225
- detached: true,
226
- stdio: 'ignore',
227
- shell: isWin,
228
- windowsHide: true,
229
- })
230
- gatewayChild.unref()
231
- }
218
+ gatewayChild.unref()
232
219
 
233
220
  const gatewayReady = waitForPort(() => checkGatewayHealth(gatewayPort), 12, 1500)
234
221
  if (gatewayReady) {
@@ -238,14 +225,13 @@ async function openclaw() {
238
225
  console.log(chalk.yellow(' Gateway 未就绪,仍将尝试打开 Dashboard'))
239
226
  }
240
227
 
241
- // 刷新 bridge config 中的 gatewayStartedAt,让 watchdog 宽限期从现在起算
228
+ // Gateway 就绪后重新启用 watchdog,写入真实 gatewayStartedAt
242
229
  refreshGatewayStartedAt(gatewayPort)
243
230
 
244
231
  // 获取 Dashboard URL
245
232
  const fallbackUrl = `http://127.0.0.1:${gatewayPort}/`
246
233
  let dashUrl = fallbackUrl
247
234
  try {
248
- const preferNpx = runtime.via === 'npx'
249
235
  const dashArgs = preferNpx ? ['openclaw', 'dashboard', '--no-open'] : ['dashboard', '--no-open']
250
236
  const dashCmd = preferNpx ? 'npx' : 'openclaw'
251
237
  const result = spawnSync(dashCmd, dashArgs, {
@@ -75,7 +75,7 @@ module.exports = {
75
75
  bridge.processProxyPort
76
76
  )
77
77
  },
78
- configure(apiKey, baseUrl) {
78
+ configure(apiKey, baseUrl, baseUrlOpenAI, primaryModel) {
79
79
  const bridgeConfig = buildBridgeConfig(apiKey, baseUrl, readConfig())
80
80
  writeConfig(bridgeConfig)
81
81
 
@@ -85,6 +85,7 @@ module.exports = {
85
85
  settings.env.ANTHROPIC_BASE_URL = BASE_URL_ANTHROPIC
86
86
  settings.env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = '1'
87
87
  settings.env.HOLYSHEEP_CLAUDE_LAUNCHER = 'hs'
88
+ if (primaryModel) settings.model = primaryModel
88
89
  // 清理旧的同义字段
89
90
  delete settings.env.ANTHROPIC_API_KEY
90
91
  delete settings.env.HOLYSHEEP_CLAUDE_BRIDGE