@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 +1 -1
- package/src/commands/openclaw.js +52 -66
- package/src/tools/claude-code.js +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simonyea/holysheep-cli",
|
|
3
|
-
"version": "1.7.
|
|
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",
|
package/src/commands/openclaw.js
CHANGED
|
@@ -63,45 +63,47 @@ function killPortListeners(port) {
|
|
|
63
63
|
return killed
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
//
|
|
169
|
-
|
|
170
|
-
prepareForRestart(gatewayPort)
|
|
170
|
+
// 先禁用 watchdog,防止后续 kill gateway 期间 bridge 误判自杀
|
|
171
|
+
disableWatchdog()
|
|
171
172
|
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
|
|
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
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
-
//
|
|
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
|
|
212
|
-
|
|
213
|
-
|
|
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
|
-
//
|
|
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, {
|
package/src/tools/claude-code.js
CHANGED
|
@@ -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
|