claude-opencode-viewer 2.6.29 → 2.6.30

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/server.js +28 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-opencode-viewer",
3
- "version": "2.6.29",
3
+ "version": "2.6.30",
4
4
  "description": "A unified terminal viewer for Claude Code and OpenCode with seamless switching",
5
5
  "type": "module",
6
6
  "main": "server.js",
package/server.js CHANGED
@@ -199,6 +199,20 @@ function killProcessTree(proc) {
199
199
  }, 1000);
200
200
  }
201
201
 
202
+ // 清理孤儿进程(PPID=1 的 opencode/claude)
203
+ function cleanupOrphanProcesses() {
204
+ try {
205
+ const orphans = execSync(
206
+ "ps -eo pid,ppid,comm 2>/dev/null | awk '$2==1 && (/opencode/||/claude/) {print $1}'",
207
+ { encoding: 'utf-8', timeout: 5000 }
208
+ ).trim().split(/\s+/).filter(Boolean).map(Number);
209
+ for (const pid of orphans) {
210
+ try { process.kill(pid, 'SIGKILL'); } catch {}
211
+ }
212
+ if (orphans.length > 0) LOG(`[cleanup] 清理孤儿进程: ${orphans.join(', ')}`);
213
+ } catch {}
214
+ }
215
+
202
216
  async function spawnProcess(mode, sessionId = null) {
203
217
  const pty = await getPty();
204
218
  fixSpawnHelperPermissions();
@@ -336,8 +350,14 @@ async function switchMode(newMode) {
336
350
  }
337
351
  currentProcess = null;
338
352
 
339
- // 等待一小段时间确保进程完全退出
340
- await new Promise(resolve => setTimeout(resolve, 100));
353
+ // 等待旧进程完全退出(Bun crash dump 可能延迟输出)
354
+ await new Promise(resolve => setTimeout(resolve, 500));
355
+
356
+ // 清理可能的孤儿进程(Bun segfault 导致子进程未被回收)
357
+ cleanupOrphanProcesses();
358
+
359
+ // 清空旧进程残留输出(包括 Bun crash dump)
360
+ outputBuffer = '';
341
361
 
342
362
  // 切换到新模式
343
363
  currentMode = newMode;
@@ -933,7 +953,8 @@ wssInst.on('connection', (ws, req) => {
933
953
  outputBuffer = '';
934
954
 
935
955
  // 等待进程完全退出
936
- await new Promise(resolve => setTimeout(resolve, 200));
956
+ await new Promise(resolve => setTimeout(resolve, 500));
957
+ cleanupOrphanProcesses();
937
958
 
938
959
  // 启动新的 opencode 进程,传入 session ID
939
960
  try {
@@ -978,7 +999,8 @@ wssInst.on('connection', (ws, req) => {
978
999
  }
979
1000
 
980
1001
  outputBuffer = '';
981
- await new Promise(resolve => setTimeout(resolve, 200));
1002
+ await new Promise(resolve => setTimeout(resolve, 500));
1003
+ cleanupOrphanProcesses();
982
1004
 
983
1005
  // 先通知前端准备好,再启动新进程
984
1006
  ws.send(JSON.stringify({ type: 'new-session-ok', mode }));
@@ -1089,17 +1111,8 @@ function startServer() {
1089
1111
  LOG('\n按 Ctrl+C 停止服务\n');
1090
1112
  }
1091
1113
 
1092
- // 清理上次 cov 崩溃残留的孤儿进程(PPID=1 的 opencode/claude)
1093
- try {
1094
- const orphans = execSync(
1095
- "ps -eo pid,ppid,comm 2>/dev/null | awk '$2==1 && (/opencode/||/claude/) {print $1}'",
1096
- { encoding: 'utf-8', timeout: 5000 }
1097
- ).trim().split(/\s+/).filter(Boolean).map(Number);
1098
- for (const pid of orphans) {
1099
- try { process.kill(pid, 'SIGTERM'); } catch {}
1100
- }
1101
- if (orphans.length > 0) LOG(`[startup] 清理孤儿进程: ${orphans.join(', ')}`);
1102
- } catch {}
1114
+ // 清理上次 cov 崩溃残留的孤儿进程
1115
+ cleanupOrphanProcesses();
1103
1116
 
1104
1117
  // 尝试恢复最近的会话,如果没有则新建
1105
1118
  let lastSessionId = null;