@simonyea/holysheep-cli 1.7.37 → 1.7.39

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.37",
3
+ "version": "1.7.39",
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",
@@ -45,7 +45,7 @@ function waitForPort(checkFn, maxTries, intervalMs) {
45
45
  return false
46
46
  }
47
47
 
48
- function killBridge(port) {
48
+ function killPortListeners(port) {
49
49
  const listeners = openclawTool.getPortListeners(port)
50
50
  let killed = 0
51
51
  for (const item of listeners) {
@@ -63,6 +63,36 @@ function killBridge(port) {
63
63
  return killed
64
64
  }
65
65
 
66
+ // 在 bridge 启动前调用:清空 gatewayStartedAt,让 watchdog 以 bridgeStartedAt(进程刚启动)
67
+ // 为基准,并把宽限期延长到 60s,确保 gateway 有足够时间启动。
68
+ function prepareForRestart(gatewayPort) {
69
+ const { BRIDGE_CONFIG_FILE } = require('../tools/openclaw-bridge')
70
+ const fs = require('fs')
71
+ try {
72
+ const raw = JSON.parse(fs.readFileSync(BRIDGE_CONFIG_FILE, 'utf8'))
73
+ raw.gatewayStartedAt = null // watchdog fallback 到 bridgeStartedAt(始终是刚启动的时间)
74
+ raw.gatewayPort = gatewayPort
75
+ if (!raw.watchdog) raw.watchdog = {}
76
+ raw.watchdog.startupGraceMs = 60000 // 给 bridge+gateway 全套重启留出 60s
77
+ fs.writeFileSync(BRIDGE_CONFIG_FILE, JSON.stringify(raw, null, 2), 'utf8')
78
+ } catch {}
79
+ }
80
+
81
+ // 在 gateway 确认就绪后调用:写入真实 gatewayStartedAt,恢复正常 30s 宽限期。
82
+ function refreshGatewayStartedAt(gatewayPort) {
83
+ const { BRIDGE_CONFIG_FILE } = require('../tools/openclaw-bridge')
84
+ const fs = require('fs')
85
+ try {
86
+ const raw = JSON.parse(fs.readFileSync(BRIDGE_CONFIG_FILE, 'utf8'))
87
+ raw.gatewayStartedAt = new Date().toISOString()
88
+ raw.gatewayPort = gatewayPort
89
+ raw.gatewayPid = null
90
+ raw.gatewayLaunchMode = 'direct-process'
91
+ if (raw.watchdog) raw.watchdog.startupGraceMs = 30000
92
+ fs.writeFileSync(BRIDGE_CONFIG_FILE, JSON.stringify(raw, null, 2), 'utf8')
93
+ } catch {}
94
+ }
95
+
66
96
  function waitPortFree(port, maxTries, intervalMs) {
67
97
  for (let i = 0; i < maxTries; i++) {
68
98
  if (openclawTool.getPortListeners(port).length === 0) return true
@@ -135,11 +165,15 @@ async function openclaw() {
135
165
  const bridgePort = openclawTool.getBridgePort()
136
166
  const gatewayPort = openclawTool.getGatewayPort()
137
167
 
168
+ // 在所有 spawn 之前写好 config:清空 gatewayStartedAt + 延长宽限期到 60s
169
+ // 这样新 bridge 的 watchdog 第一次 tick 读到的就是新鲜的基准时间,不会立即过期
170
+ prepareForRestart(gatewayPort)
171
+
138
172
  // 先杀掉旧 Bridge,再启动新的
139
- const existingListeners = openclawTool.getPortListeners(bridgePort)
140
- if (existingListeners.length > 0) {
173
+ const existingBridgeListeners = openclawTool.getPortListeners(bridgePort)
174
+ if (existingBridgeListeners.length > 0) {
141
175
  process.stdout.write(chalk.gray(` 正在重启 Bridge (端口 ${bridgePort})... `))
142
- killBridge(bridgePort)
176
+ killPortListeners(bridgePort)
143
177
  waitPortFree(bridgePort, 10, 200)
144
178
  } else {
145
179
  process.stdout.write(chalk.gray(` 正在启动 Bridge (端口 ${bridgePort})... `))
@@ -163,44 +197,50 @@ async function openclaw() {
163
197
  process.exit(1)
164
198
  }
165
199
 
166
- // 确保 Gateway 运行
167
- if (checkGatewayHealth(gatewayPort)) {
168
- console.log(chalk.green(`✓ Gateway 已运行 (端口 ${gatewayPort})`))
200
+ // 先杀掉旧 Gateway,再启动新的(避免端口残留导致新进程无法绑定)
201
+ const existingGatewayListeners = openclawTool.getPortListeners(gatewayPort)
202
+ if (existingGatewayListeners.length > 0) {
203
+ process.stdout.write(chalk.gray(` 正在重启 Gateway (端口 ${gatewayPort})... `))
204
+ killPortListeners(gatewayPort)
205
+ waitPortFree(gatewayPort, 10, 200)
169
206
  } else {
170
207
  process.stdout.write(chalk.gray(` 正在启动 Gateway (端口 ${gatewayPort})... `))
208
+ }
171
209
 
172
- const preferNpx = runtime.via === 'npx'
173
- const gatewayStartArgs = preferNpx ? ['openclaw', 'gateway', 'start'] : ['gateway', 'start']
174
- const gatewayStartCmd = preferNpx ? 'npx' : 'openclaw'
175
- const serviceResult = spawnSync(gatewayStartCmd, gatewayStartArgs, {
210
+ 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, {
214
+ stdio: 'ignore',
215
+ timeout: 10000,
216
+ shell: isWin,
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,
176
226
  stdio: 'ignore',
177
- timeout: 10000,
178
227
  shell: isWin,
228
+ windowsHide: true,
179
229
  })
230
+ gatewayChild.unref()
231
+ }
180
232
 
181
- if (serviceResult.status !== 0) {
182
- const directArgs = preferNpx
183
- ? ['openclaw', 'gateway', '--port', String(gatewayPort)]
184
- : ['gateway', '--port', String(gatewayPort)]
185
- const directCmd = preferNpx ? 'npx' : 'openclaw'
186
- const gatewayChild = spawn(directCmd, directArgs, {
187
- detached: true,
188
- stdio: 'ignore',
189
- shell: isWin,
190
- windowsHide: true,
191
- })
192
- gatewayChild.unref()
193
- }
194
-
195
- const gatewayReady = waitForPort(() => checkGatewayHealth(gatewayPort), 12, 1500)
196
- if (gatewayReady) {
197
- console.log(chalk.green('✓'))
198
- } else {
199
- console.log(chalk.yellow('⚠'))
200
- console.log(chalk.yellow(' Gateway 未就绪,仍将尝试打开 Dashboard'))
201
- }
233
+ const gatewayReady = waitForPort(() => checkGatewayHealth(gatewayPort), 12, 1500)
234
+ if (gatewayReady) {
235
+ console.log(chalk.green(''))
236
+ } else {
237
+ console.log(chalk.yellow(''))
238
+ console.log(chalk.yellow(' Gateway 未就绪,仍将尝试打开 Dashboard'))
202
239
  }
203
240
 
241
+ // 刷新 bridge config 中的 gatewayStartedAt,让 watchdog 宽限期从现在起算
242
+ refreshGatewayStartedAt(gatewayPort)
243
+
204
244
  // 获取 Dashboard URL
205
245
  const fallbackUrl = `http://127.0.0.1:${gatewayPort}/`
206
246
  let dashUrl = fallbackUrl