@simonyea/holysheep-cli 1.7.37 → 1.7.38

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.38",
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,19 @@ function killBridge(port) {
63
63
  return killed
64
64
  }
65
65
 
66
+ function refreshGatewayStartedAt(gatewayPort) {
67
+ const { BRIDGE_CONFIG_FILE } = require('../tools/openclaw-bridge')
68
+ const fs = require('fs')
69
+ try {
70
+ const raw = JSON.parse(fs.readFileSync(BRIDGE_CONFIG_FILE, 'utf8'))
71
+ raw.gatewayStartedAt = new Date().toISOString()
72
+ raw.gatewayPort = gatewayPort
73
+ raw.gatewayPid = null
74
+ raw.gatewayLaunchMode = 'direct-process'
75
+ fs.writeFileSync(BRIDGE_CONFIG_FILE, JSON.stringify(raw, null, 2), 'utf8')
76
+ } catch {}
77
+ }
78
+
66
79
  function waitPortFree(port, maxTries, intervalMs) {
67
80
  for (let i = 0; i < maxTries; i++) {
68
81
  if (openclawTool.getPortListeners(port).length === 0) return true
@@ -136,10 +149,10 @@ async function openclaw() {
136
149
  const gatewayPort = openclawTool.getGatewayPort()
137
150
 
138
151
  // 先杀掉旧 Bridge,再启动新的
139
- const existingListeners = openclawTool.getPortListeners(bridgePort)
140
- if (existingListeners.length > 0) {
152
+ const existingBridgeListeners = openclawTool.getPortListeners(bridgePort)
153
+ if (existingBridgeListeners.length > 0) {
141
154
  process.stdout.write(chalk.gray(` 正在重启 Bridge (端口 ${bridgePort})... `))
142
- killBridge(bridgePort)
155
+ killPortListeners(bridgePort)
143
156
  waitPortFree(bridgePort, 10, 200)
144
157
  } else {
145
158
  process.stdout.write(chalk.gray(` 正在启动 Bridge (端口 ${bridgePort})... `))
@@ -163,44 +176,50 @@ async function openclaw() {
163
176
  process.exit(1)
164
177
  }
165
178
 
166
- // 确保 Gateway 运行
167
- if (checkGatewayHealth(gatewayPort)) {
168
- console.log(chalk.green(`✓ Gateway 已运行 (端口 ${gatewayPort})`))
179
+ // 先杀掉旧 Gateway,再启动新的(避免端口残留导致新进程无法绑定)
180
+ const existingGatewayListeners = openclawTool.getPortListeners(gatewayPort)
181
+ if (existingGatewayListeners.length > 0) {
182
+ process.stdout.write(chalk.gray(` 正在重启 Gateway (端口 ${gatewayPort})... `))
183
+ killPortListeners(gatewayPort)
184
+ waitPortFree(gatewayPort, 10, 200)
169
185
  } else {
170
186
  process.stdout.write(chalk.gray(` 正在启动 Gateway (端口 ${gatewayPort})... `))
187
+ }
171
188
 
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, {
189
+ const preferNpx = runtime.via === 'npx'
190
+ const gatewayStartArgs = preferNpx ? ['openclaw', 'gateway', 'start'] : ['gateway', 'start']
191
+ const gatewayStartCmd = preferNpx ? 'npx' : 'openclaw'
192
+ const serviceResult = spawnSync(gatewayStartCmd, gatewayStartArgs, {
193
+ stdio: 'ignore',
194
+ timeout: 10000,
195
+ shell: isWin,
196
+ })
197
+
198
+ if (serviceResult.status !== 0) {
199
+ const directArgs = preferNpx
200
+ ? ['openclaw', 'gateway', '--port', String(gatewayPort)]
201
+ : ['gateway', '--port', String(gatewayPort)]
202
+ const directCmd = preferNpx ? 'npx' : 'openclaw'
203
+ const gatewayChild = spawn(directCmd, directArgs, {
204
+ detached: true,
176
205
  stdio: 'ignore',
177
- timeout: 10000,
178
206
  shell: isWin,
207
+ windowsHide: true,
179
208
  })
209
+ gatewayChild.unref()
210
+ }
180
211
 
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
- }
212
+ const gatewayReady = waitForPort(() => checkGatewayHealth(gatewayPort), 12, 1500)
213
+ if (gatewayReady) {
214
+ console.log(chalk.green(''))
215
+ } else {
216
+ console.log(chalk.yellow(''))
217
+ console.log(chalk.yellow(' Gateway 未就绪,仍将尝试打开 Dashboard'))
202
218
  }
203
219
 
220
+ // 刷新 bridge config 中的 gatewayStartedAt,让 watchdog 宽限期从现在起算
221
+ refreshGatewayStartedAt(gatewayPort)
222
+
204
223
  // 获取 Dashboard URL
205
224
  const fallbackUrl = `http://127.0.0.1:${gatewayPort}/`
206
225
  let dashUrl = fallbackUrl