cc-viewer 1.7.18 → 1.7.20

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/cli.js CHANGED
@@ -494,10 +494,38 @@ async function runCliMode(extraClaudeArgs = [], cwd, noOpen = false) {
494
494
  }
495
495
 
496
496
  // 3. 启动 PTY 中的 claude
497
- const { spawnClaude, killPty } = await import('./server/pty-manager.js');
497
+ const { spawnClaude, killPty, onPtyExit } = await import('./server/pty-manager.js');
498
+ const { isCodeFuseManagedEnvironment } = await import('./server/lib/codefuse-managed-mode.js');
499
+ const codeFuseManaged = isCodeFuseManagedEnvironment();
500
+ let managedExitCode = 0;
501
+ let removeManagedExitListener = null;
502
+
503
+ // CodeFuse waits for this wrapper process to finish before tearing down its engine.
504
+ // Standalone CCV intentionally remains alive after Claude exits so the browser can reconnect.
505
+ const cleanup = createHardenedCleanup({
506
+ doCleanup: () => {
507
+ // A signal-driven kill also produces a PTY exit event. Unsubscribe first so that event
508
+ // cannot look like a second cleanup request and force the hardened 130 exit path.
509
+ removeManagedExitListener?.();
510
+ removeManagedExitListener = null;
511
+ killPty();
512
+ return serverMod.stopViewer();
513
+ },
514
+ exit: (code) => process.exit(code ?? managedExitCode),
515
+ });
516
+
517
+ if (codeFuseManaged) {
518
+ removeManagedExitListener = onPtyExit((exitCode) => {
519
+ managedExitCode = Number.isInteger(exitCode) ? exitCode : 1;
520
+ cleanup();
521
+ });
522
+ }
523
+
498
524
  try {
499
525
  await spawnClaude(proxyPort, workingDir, extraClaudeArgs, claudePath, isNpmVersion, port, serverProtocol, serverMod.getInternalToken());
500
526
  } catch (err) {
527
+ removeManagedExitListener?.();
528
+ removeManagedExitListener = null;
501
529
  console.error('[CC Viewer] Failed to spawn Claude:', err.message);
502
530
  await serverMod.stopViewer();
503
531
  process.exit(1);
@@ -546,14 +574,9 @@ async function runCliMode(extraClaudeArgs = [], cwd, noOpen = false) {
546
574
 
547
575
  // 5. 注册退出处理(hardened:watchdog 5s 强退 + 连按 Ctrl+C 立退,
548
576
  // 防 Windows 上 ConPTY kill / IM teardown 挂住导致"Ctrl+C 完全无反应")
549
- const cleanup = createHardenedCleanup({
550
- doCleanup: () => {
551
- killPty();
552
- return serverMod.stopViewer();
553
- },
554
- });
555
577
  process.on('SIGINT', cleanup);
556
578
  process.on('SIGTERM', cleanup);
579
+ process.on('exit', () => removeManagedExitListener?.());
557
580
  // Windows 兜底:ConPTY 下控制台 Ctrl+C 事件偶发不送达(SIGINT 永不触发),
558
581
  // raw mode keypress 直连 cleanup。silent 模式本地终端无人读 stdin,无副作用;
559
582
  // darwin / 非 TTY 内部自动跳过。