@simonyea/holysheep-cli 1.7.117 → 1.7.119

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 +102 -16
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.119",
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,35 @@ 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
+ const gPort = openclawTool?.getGatewayPort?.() || 18789
512
+ let gPid = null
513
+ for (let i = 0; i < 10 && !gPid; i++) {
514
+ await new Promise(r => setTimeout(r, 1500))
515
+ try {
516
+ if (process.platform === 'win32') {
517
+ const o = execSync(`powershell -NonInteractive -Command "(Get-NetTCPConnection -LocalPort ${gPort} -State Listen -ErrorAction SilentlyContinue).OwningProcess"`, { stdio: 'pipe', timeout: 5000 }).toString().trim()
518
+ gPid = Number(o.split(/\r?\n/)[0]) || null
519
+ } else {
520
+ const o = execSync(`lsof -iTCP:${gPort} -sTCP:LISTEN -t 2>/dev/null | head -1`, { stdio: 'pipe', timeout: 5000 }).toString().trim()
521
+ gPid = Number(o) || null
522
+ }
523
+ } catch {}
524
+ }
525
+ try {
526
+ if (gPid) {
527
+ const bridgeMod = require('../tools/openclaw-bridge')
528
+ const bc = bridgeMod.readBridgeConfig()
529
+ bc.gatewayPid = gPid
530
+ bc.gatewayStartedAt = new Date().toISOString()
531
+ fs.writeFileSync(bridgeMod.BRIDGE_CONFIG_FILE, JSON.stringify(bc, null, 2), 'utf8')
532
+ }
533
+ } catch {}
510
534
  try { openclawTool?.ensureBridgeRunning?.() } catch {}
511
- try { execSync('openclaw daemon start', { stdio: 'ignore', timeout: 30000 }) } catch {}
512
535
  }
513
536
 
514
537
  sseEmit(res, { type: 'tool', name: tool.name, status: ok ? 'ok' : 'error', localVer, newVer })
@@ -662,11 +685,42 @@ async function handleToolUpgrade(req, res) {
662
685
 
663
686
  if (ok) {
664
687
  sseEmit(res, { type: 'progress', message: `✓ ${entry.name} 升级成功: ${localVer || '?'} → ${newVer || 'latest'}` })
665
- // OpenClaw 升级后自动重启 Bridge + Gateway
688
+ // OpenClaw 升级后:先停 启动 Gateway(拿 PID)→ 更新 bridge config → 启动 Bridge
666
689
  if (entry.id === 'openclaw') {
667
690
  const openclawTool = TOOLS.find(t => t.id === 'openclaw')
668
691
  sseEmit(res, { type: 'progress', message: '正在重启 OpenClaw...' })
669
692
  try { execSync('openclaw daemon stop', { stdio: 'ignore', timeout: 10000 }) } catch {}
693
+ try {
694
+ execSync('openclaw daemon start', { stdio: 'ignore', timeout: 30000 })
695
+ sseEmit(res, { type: 'progress', message: '✓ OpenClaw Gateway 已启动' })
696
+ } catch {
697
+ sseEmit(res, { type: 'progress', message: '⚠️ Gateway 启动失败' })
698
+ }
699
+ // 等 Gateway 端口就绪,获取 PID 写入 bridge config
700
+ const gPort = openclawTool?.getGatewayPort?.() || 18789
701
+ let gPid = null
702
+ for (let i = 0; i < 10 && !gPid; i++) {
703
+ await new Promise(r => setTimeout(r, 1500))
704
+ try {
705
+ if (process.platform === 'win32') {
706
+ const o = execSync(`powershell -NonInteractive -Command "(Get-NetTCPConnection -LocalPort ${gPort} -State Listen -ErrorAction SilentlyContinue).OwningProcess"`, { stdio: 'pipe', timeout: 5000 }).toString().trim()
707
+ gPid = Number(o.split(/\r?\n/)[0]) || null
708
+ } else {
709
+ const o = execSync(`lsof -iTCP:${gPort} -sTCP:LISTEN -t 2>/dev/null | head -1`, { stdio: 'pipe', timeout: 5000 }).toString().trim()
710
+ gPid = Number(o) || null
711
+ }
712
+ } catch {}
713
+ }
714
+ if (gPid) {
715
+ try {
716
+ const bridgeMod = require('../tools/openclaw-bridge')
717
+ const bc = bridgeMod.readBridgeConfig()
718
+ bc.gatewayPid = gPid
719
+ bc.gatewayStartedAt = new Date().toISOString()
720
+ fs.writeFileSync(bridgeMod.BRIDGE_CONFIG_FILE, JSON.stringify(bc, null, 2), 'utf8')
721
+ } catch {}
722
+ }
723
+ // 启动 Bridge
670
724
  if (openclawTool?.ensureBridgeRunning) {
671
725
  try {
672
726
  openclawTool.ensureBridgeRunning()
@@ -675,12 +729,6 @@ async function handleToolUpgrade(req, res) {
675
729
  sseEmit(res, { type: 'progress', message: '⚠️ Bridge 启动失败' })
676
730
  }
677
731
  }
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
732
  }
685
733
  } else {
686
734
  sseEmit(res, { type: 'progress', message: `✗ ${entry.name} 升级失败` })
@@ -793,17 +841,55 @@ async function handleToolRollback(req, res) {
793
841
 
794
842
  if (ok) {
795
843
  sseEmit(res, { type: 'progress', message: `✓ ${entry.name} 已回退: ${localVer || '?'} → ${newVer || targetVer}` })
796
- // OpenClaw: 重启 Bridge + Gateway
844
+ // OpenClaw: 先启动 Gateway(拿 PID),更新 bridge config,再启动 Bridge
797
845
  if (entry.id === 'openclaw') {
798
- const openclawTool = TOOLS.find(t => t.id === 'openclaw')
799
846
  sseEmit(res, { type: 'progress', message: '正在重启 OpenClaw...' })
800
- if (openclawTool?.ensureBridgeRunning) {
801
- try { openclawTool.ensureBridgeRunning() } catch {}
802
- }
847
+ // 1. 启动 Gateway
803
848
  try {
804
849
  execSync('openclaw daemon start', { stdio: 'ignore', timeout: 30000 })
805
- sseEmit(res, { type: 'progress', message: '✓ OpenClaw 已重启' })
806
- } catch {}
850
+ sseEmit(res, { type: 'progress', message: '✓ OpenClaw Gateway 已启动' })
851
+ } catch {
852
+ sseEmit(res, { type: 'progress', message: '⚠️ Gateway 启动失败' })
853
+ }
854
+ // 2. 等 Gateway 端口就绪,获取 PID 写入 bridge config
855
+ const openclawTool = TOOLS.find(t => t.id === 'openclaw')
856
+ const gatewayPort = openclawTool?.getGatewayPort?.() || 18789
857
+ let gatewayPid = null
858
+ for (let attempt = 0; attempt < 10 && !gatewayPid; attempt++) {
859
+ await new Promise(r => setTimeout(r, 1500))
860
+ try {
861
+ if (process.platform === 'win32') {
862
+ const out = execSync(`powershell -NonInteractive -Command "(Get-NetTCPConnection -LocalPort ${gatewayPort} -State Listen -ErrorAction SilentlyContinue).OwningProcess"`, { stdio: 'pipe', timeout: 5000 }).toString().trim()
863
+ gatewayPid = Number(out.split(/\r?\n/)[0]) || null
864
+ } else {
865
+ const out = execSync(`lsof -iTCP:${gatewayPort} -sTCP:LISTEN -t 2>/dev/null | head -1`, { stdio: 'pipe', timeout: 5000 }).toString().trim()
866
+ gatewayPid = Number(out) || null
867
+ }
868
+ } catch {}
869
+ }
870
+ if (gatewayPid) {
871
+ try {
872
+ const bridgeMod = require('../tools/openclaw-bridge')
873
+ const bc = bridgeMod.readBridgeConfig()
874
+ bc.gatewayPid = gatewayPid
875
+ bc.gatewayStartedAt = new Date().toISOString()
876
+ fs.writeFileSync(bridgeMod.BRIDGE_CONFIG_FILE, JSON.stringify(bc, null, 2), 'utf8')
877
+ sseEmit(res, { type: 'progress', message: `Gateway PID: ${gatewayPid}` })
878
+ } catch (e) {
879
+ sseEmit(res, { type: 'progress', message: `⚠️ 写入 Bridge 配置失败: ${e.message}` })
880
+ }
881
+ } else {
882
+ sseEmit(res, { type: 'progress', message: '⚠️ 未检测到 Gateway PID,Bridge 可能无��启动' })
883
+ }
884
+ // 3. 启动 Bridge
885
+ if (openclawTool?.ensureBridgeRunning) {
886
+ try {
887
+ const bridgeOk = openclawTool.ensureBridgeRunning()
888
+ sseEmit(res, { type: 'progress', message: bridgeOk ? '✓ HolySheep Bridge 已启动' : '⚠️ Bridge 未就绪' })
889
+ } catch (e) {
890
+ sseEmit(res, { type: 'progress', message: `⚠️ Bridge 启动失败: ${e.message}` })
891
+ }
892
+ }
807
893
  }
808
894
  } else {
809
895
  sseEmit(res, { type: 'progress', message: `✗ 回退失败,请手动运行: ${installCmd}` })