@simonyea/holysheep-cli 1.7.117 → 1.7.118

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/webui/server.js +82 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "1.7.117",
3
+ "version": "1.7.118",
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",
@@ -503,12 +503,30 @@ async function handleUpgrade(_req, res) {
503
503
  newVer = m ? m[1] : null
504
504
  } catch {}
505
505
 
506
- // OpenClaw 升级后自动重启 Bridge + Gateway
506
+ // OpenClaw 升级后:Gateway 更新 PID → Bridge
507
507
  if (ok && tool.id === 'openclaw') {
508
508
  try { execSync('openclaw daemon stop', { stdio: 'ignore', timeout: 10000 }) } catch {}
509
+ try { execSync('openclaw daemon start', { stdio: 'ignore', timeout: 30000 }) } catch {}
509
510
  const openclawTool = TOOLS.find(t => t.id === 'openclaw')
511
+ try {
512
+ const gPort = openclawTool?.getGatewayPort?.() || 18789
513
+ let gPid = null
514
+ if (process.platform === 'win32') {
515
+ const o = execSync(`powershell -NonInteractive -Command "(Get-NetTCPConnection -LocalPort ${gPort} -State Listen -ErrorAction SilentlyContinue).OwningProcess"`, { stdio: 'pipe', timeout: 5000 }).toString().trim()
516
+ gPid = Number(o.split(/\r?\n/)[0]) || null
517
+ } else {
518
+ const o = execSync(`lsof -iTCP:${gPort} -sTCP:LISTEN -t 2>/dev/null | head -1`, { stdio: 'pipe', timeout: 5000 }).toString().trim()
519
+ gPid = Number(o) || null
520
+ }
521
+ if (gPid) {
522
+ const bridgeMod = require('../tools/openclaw-bridge')
523
+ const bc = bridgeMod.readBridgeConfig()
524
+ bc.gatewayPid = gPid
525
+ bc.gatewayStartedAt = new Date().toISOString()
526
+ fs.writeFileSync(bridgeMod.BRIDGE_CONFIG_FILE, JSON.stringify(bc, null, 2), 'utf8')
527
+ }
528
+ } catch {}
510
529
  try { openclawTool?.ensureBridgeRunning?.() } catch {}
511
- try { execSync('openclaw daemon start', { stdio: 'ignore', timeout: 30000 }) } catch {}
512
530
  }
513
531
 
514
532
  sseEmit(res, { type: 'tool', name: tool.name, status: ok ? 'ok' : 'error', localVer, newVer })
@@ -662,11 +680,37 @@ async function handleToolUpgrade(req, res) {
662
680
 
663
681
  if (ok) {
664
682
  sseEmit(res, { type: 'progress', message: `✓ ${entry.name} 升级成功: ${localVer || '?'} → ${newVer || 'latest'}` })
665
- // OpenClaw 升级后自动重启 Bridge + Gateway
683
+ // OpenClaw 升级后:先停 启动 Gateway(拿 PID)→ 更新 bridge config → 启动 Bridge
666
684
  if (entry.id === 'openclaw') {
667
685
  const openclawTool = TOOLS.find(t => t.id === 'openclaw')
668
686
  sseEmit(res, { type: 'progress', message: '正在重启 OpenClaw...' })
669
687
  try { execSync('openclaw daemon stop', { stdio: 'ignore', timeout: 10000 }) } catch {}
688
+ try {
689
+ execSync('openclaw daemon start', { stdio: 'ignore', timeout: 30000 })
690
+ sseEmit(res, { type: 'progress', message: '✓ OpenClaw Gateway 已启动' })
691
+ } catch {
692
+ sseEmit(res, { type: 'progress', message: '⚠️ Gateway 启动失败' })
693
+ }
694
+ // 获取 Gateway PID 写入 bridge config
695
+ try {
696
+ const gatewayPort = openclawTool?.getGatewayPort?.() || 18789
697
+ let gatewayPid = null
698
+ if (process.platform === 'win32') {
699
+ const out = execSync(`powershell -NonInteractive -Command "(Get-NetTCPConnection -LocalPort ${gatewayPort} -State Listen -ErrorAction SilentlyContinue).OwningProcess"`, { stdio: 'pipe', timeout: 5000 }).toString().trim()
700
+ gatewayPid = Number(out.split(/\r?\n/)[0]) || null
701
+ } else {
702
+ const out = execSync(`lsof -iTCP:${gatewayPort} -sTCP:LISTEN -t 2>/dev/null | head -1`, { stdio: 'pipe', timeout: 5000 }).toString().trim()
703
+ gatewayPid = Number(out) || null
704
+ }
705
+ if (gatewayPid) {
706
+ const bridgeMod = require('../tools/openclaw-bridge')
707
+ const bc = bridgeMod.readBridgeConfig()
708
+ bc.gatewayPid = gatewayPid
709
+ bc.gatewayStartedAt = new Date().toISOString()
710
+ fs.writeFileSync(bridgeMod.BRIDGE_CONFIG_FILE, JSON.stringify(bc, null, 2), 'utf8')
711
+ }
712
+ } catch {}
713
+ // 启动 Bridge
670
714
  if (openclawTool?.ensureBridgeRunning) {
671
715
  try {
672
716
  openclawTool.ensureBridgeRunning()
@@ -675,12 +719,6 @@ async function handleToolUpgrade(req, res) {
675
719
  sseEmit(res, { type: 'progress', message: '⚠️ Bridge 启动失败' })
676
720
  }
677
721
  }
678
- try {
679
- execSync('openclaw daemon start', { stdio: 'ignore', timeout: 30000 })
680
- sseEmit(res, { type: 'progress', message: '✓ OpenClaw Gateway 已重启' })
681
- } catch {
682
- sseEmit(res, { type: 'progress', message: '⚠️ Gateway 重启失败,请手动运行: openclaw daemon start' })
683
- }
684
722
  }
685
723
  } else {
686
724
  sseEmit(res, { type: 'progress', message: `✗ ${entry.name} 升级失败` })
@@ -793,17 +831,46 @@ async function handleToolRollback(req, res) {
793
831
 
794
832
  if (ok) {
795
833
  sseEmit(res, { type: 'progress', message: `✓ ${entry.name} 已回退: ${localVer || '?'} → ${newVer || targetVer}` })
796
- // OpenClaw: 重启 Bridge + Gateway
834
+ // OpenClaw: 先启动 Gateway(拿 PID),更新 bridge config,再启动 Bridge
797
835
  if (entry.id === 'openclaw') {
798
- const openclawTool = TOOLS.find(t => t.id === 'openclaw')
799
836
  sseEmit(res, { type: 'progress', message: '正在重启 OpenClaw...' })
800
- if (openclawTool?.ensureBridgeRunning) {
801
- try { openclawTool.ensureBridgeRunning() } catch {}
802
- }
837
+ // 1. 启动 Gateway
803
838
  try {
804
839
  execSync('openclaw daemon start', { stdio: 'ignore', timeout: 30000 })
805
- sseEmit(res, { type: 'progress', message: '✓ OpenClaw 已重启' })
840
+ sseEmit(res, { type: 'progress', message: '✓ OpenClaw Gateway 已启动' })
841
+ } catch {
842
+ sseEmit(res, { type: 'progress', message: '⚠️ Gateway 启动失败' })
843
+ }
844
+ // 2. 获取 Gateway PID 并写入 bridge config,否则 bridge watchdog 会自杀
845
+ const openclawTool = TOOLS.find(t => t.id === 'openclaw')
846
+ try {
847
+ const gatewayPort = openclawTool?.getGatewayPort?.() || 18789
848
+ let gatewayPid = null
849
+ if (process.platform === 'win32') {
850
+ const out = execSync(`powershell -NonInteractive -Command "(Get-NetTCPConnection -LocalPort ${gatewayPort} -State Listen -ErrorAction SilentlyContinue).OwningProcess"`, { stdio: 'pipe', timeout: 5000 }).toString().trim()
851
+ gatewayPid = Number(out.split(/\r?\n/)[0]) || null
852
+ } else {
853
+ const out = execSync(`lsof -iTCP:${gatewayPort} -sTCP:LISTEN -t 2>/dev/null | head -1`, { stdio: 'pipe', timeout: 5000 }).toString().trim()
854
+ gatewayPid = Number(out) || null
855
+ }
856
+ if (gatewayPid) {
857
+ const bridgeMod = require('../tools/openclaw-bridge')
858
+ const bc = bridgeMod.readBridgeConfig()
859
+ bc.gatewayPid = gatewayPid
860
+ bc.gatewayStartedAt = new Date().toISOString()
861
+ fs.writeFileSync(bridgeMod.BRIDGE_CONFIG_FILE, JSON.stringify(bc, null, 2), 'utf8')
862
+ sseEmit(res, { type: 'progress', message: `Gateway PID: ${gatewayPid}` })
863
+ }
806
864
  } catch {}
865
+ // 3. 启动 Bridge
866
+ if (openclawTool?.ensureBridgeRunning) {
867
+ try {
868
+ openclawTool.ensureBridgeRunning()
869
+ sseEmit(res, { type: 'progress', message: '✓ HolySheep Bridge 已启动' })
870
+ } catch {
871
+ sseEmit(res, { type: 'progress', message: '⚠️ Bridge 启动失败' })
872
+ }
873
+ }
807
874
  }
808
875
  } else {
809
876
  sseEmit(res, { type: 'progress', message: `✗ 回退失败,请手动运行: ${installCmd}` })