@simonyea/holysheep-cli 1.7.38 → 1.7.40
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 +1 -1
- package/src/commands/openclaw.js +61 -54
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simonyea/holysheep-cli",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.40",
|
|
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",
|
package/src/commands/openclaw.js
CHANGED
|
@@ -63,28 +63,47 @@ function killPortListeners(port) {
|
|
|
63
63
|
return killed
|
|
64
64
|
}
|
|
65
65
|
|
|
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() {
|
|
77
|
+
const { BRIDGE_CONFIG_FILE } = require('../tools/openclaw-bridge')
|
|
78
|
+
const fs = require('fs')
|
|
79
|
+
try {
|
|
80
|
+
const raw = JSON.parse(fs.readFileSync(BRIDGE_CONFIG_FILE, 'utf8'))
|
|
81
|
+
if (!raw.watchdog) raw.watchdog = {}
|
|
82
|
+
raw.watchdog.enabled = false
|
|
83
|
+
raw.gatewayPid = null // 清旧 PID,防止 PID 检查误判
|
|
84
|
+
fs.writeFileSync(BRIDGE_CONFIG_FILE, JSON.stringify(raw, null, 2), 'utf8')
|
|
85
|
+
} catch (e) {
|
|
86
|
+
console.log(chalk.yellow(` ⚠ 无法更新 Bridge 配置: ${e.message}`))
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 在 gateway 确认就绪后调用:重新启用 watchdog,写入真实 gatewayStartedAt
|
|
66
91
|
function refreshGatewayStartedAt(gatewayPort) {
|
|
67
92
|
const { BRIDGE_CONFIG_FILE } = require('../tools/openclaw-bridge')
|
|
68
93
|
const fs = require('fs')
|
|
69
94
|
try {
|
|
70
95
|
const raw = JSON.parse(fs.readFileSync(BRIDGE_CONFIG_FILE, 'utf8'))
|
|
71
96
|
raw.gatewayStartedAt = new Date().toISOString()
|
|
72
|
-
raw.gatewayPort = gatewayPort
|
|
73
97
|
raw.gatewayPid = null
|
|
98
|
+
raw.gatewayPort = gatewayPort
|
|
74
99
|
raw.gatewayLaunchMode = 'direct-process'
|
|
100
|
+
if (!raw.watchdog) raw.watchdog = {}
|
|
101
|
+
raw.watchdog.startupGraceMs = 30000
|
|
102
|
+
raw.watchdog.enabled = true // gateway 已就绪,安全地重新启用 watchdog
|
|
75
103
|
fs.writeFileSync(BRIDGE_CONFIG_FILE, JSON.stringify(raw, null, 2), 'utf8')
|
|
76
104
|
} catch {}
|
|
77
105
|
}
|
|
78
106
|
|
|
79
|
-
function waitPortFree(port, maxTries, intervalMs) {
|
|
80
|
-
for (let i = 0; i < maxTries; i++) {
|
|
81
|
-
if (openclawTool.getPortListeners(port).length === 0) return true
|
|
82
|
-
const t0 = Date.now()
|
|
83
|
-
while (Date.now() - t0 < intervalMs) {}
|
|
84
|
-
}
|
|
85
|
-
return openclawTool.getPortListeners(port).length === 0
|
|
86
|
-
}
|
|
87
|
-
|
|
88
107
|
function findChrome() {
|
|
89
108
|
const { existsSync } = require('fs')
|
|
90
109
|
if (process.platform === 'darwin') {
|
|
@@ -148,35 +167,34 @@ async function openclaw() {
|
|
|
148
167
|
const bridgePort = openclawTool.getBridgePort()
|
|
149
168
|
const gatewayPort = openclawTool.getGatewayPort()
|
|
150
169
|
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
170
|
+
// 先禁用 watchdog,防止后续 kill gateway 期间 bridge 误判自杀
|
|
171
|
+
disableWatchdog()
|
|
172
|
+
|
|
173
|
+
// Bridge:只确保运行,不重启
|
|
174
|
+
if (checkBridgeHealth(bridgePort)) {
|
|
175
|
+
console.log(chalk.green(`✓ Bridge 已运行 (端口 ${bridgePort})`))
|
|
157
176
|
} else {
|
|
158
177
|
process.stdout.write(chalk.gray(` 正在启动 Bridge (端口 ${bridgePort})... `))
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
})
|
|
168
|
-
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()
|
|
169
186
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
+
}
|
|
177
195
|
}
|
|
178
196
|
|
|
179
|
-
//
|
|
197
|
+
// Gateway:kill 旧的,直接 spawn 新的(明确 --port,避免 service 配置不一致)
|
|
180
198
|
const existingGatewayListeners = openclawTool.getPortListeners(gatewayPort)
|
|
181
199
|
if (existingGatewayListeners.length > 0) {
|
|
182
200
|
process.stdout.write(chalk.gray(` 正在重启 Gateway (端口 ${gatewayPort})... `))
|
|
@@ -187,27 +205,17 @@ async function openclaw() {
|
|
|
187
205
|
}
|
|
188
206
|
|
|
189
207
|
const preferNpx = runtime.via === 'npx'
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
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,
|
|
193
214
|
stdio: 'ignore',
|
|
194
|
-
timeout: 10000,
|
|
195
215
|
shell: isWin,
|
|
216
|
+
windowsHide: true,
|
|
196
217
|
})
|
|
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,
|
|
205
|
-
stdio: 'ignore',
|
|
206
|
-
shell: isWin,
|
|
207
|
-
windowsHide: true,
|
|
208
|
-
})
|
|
209
|
-
gatewayChild.unref()
|
|
210
|
-
}
|
|
218
|
+
gatewayChild.unref()
|
|
211
219
|
|
|
212
220
|
const gatewayReady = waitForPort(() => checkGatewayHealth(gatewayPort), 12, 1500)
|
|
213
221
|
if (gatewayReady) {
|
|
@@ -217,14 +225,13 @@ async function openclaw() {
|
|
|
217
225
|
console.log(chalk.yellow(' Gateway 未就绪,仍将尝试打开 Dashboard'))
|
|
218
226
|
}
|
|
219
227
|
|
|
220
|
-
//
|
|
228
|
+
// Gateway 就绪后重新启用 watchdog,写入真实 gatewayStartedAt
|
|
221
229
|
refreshGatewayStartedAt(gatewayPort)
|
|
222
230
|
|
|
223
231
|
// 获取 Dashboard URL
|
|
224
232
|
const fallbackUrl = `http://127.0.0.1:${gatewayPort}/`
|
|
225
233
|
let dashUrl = fallbackUrl
|
|
226
234
|
try {
|
|
227
|
-
const preferNpx = runtime.via === 'npx'
|
|
228
235
|
const dashArgs = preferNpx ? ['openclaw', 'dashboard', '--no-open'] : ['dashboard', '--no-open']
|
|
229
236
|
const dashCmd = preferNpx ? 'npx' : 'openclaw'
|
|
230
237
|
const result = spawnSync(dashCmd, dashArgs, {
|