Просмотр исходного кода

fix(tui): use alternate screen buffer to isolate IME from rendering

Terminal.app crashes in IMKInputSession when the IME's NSRemoteView
XPC connection conflicts with Ink's screen redraws. Enter the
alternate screen buffer (DEC 1049) before rendering — this isolates
Ink to a separate terminal view so the IME interacts with the
primary screen without corruption. Same approach as Claude Code's
<AlternateScreen> component.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fanghanjun 7 месяцев назад
Родитель
Сommit
9e60c0588e
1 измененных файлов с 9 добавлено и 2 удалено
  1. 9 2
      packages/cli/src/tui/app.ts

+ 9 - 2
packages/cli/src/tui/app.ts

@@ -186,6 +186,14 @@ export async function launchTui(
     return (originalStderrWrite as Function)(chunk, ...args);
   };
 
+  // Enter alternate screen buffer — isolates Ink rendering from the primary
+  // terminal view. This prevents IME XPC corruption on Terminal.app (the IME's
+  // NSRemoteView interacts with the primary screen; the alt screen is separate).
+  // Claude Code uses the same approach via <AlternateScreen> + DEC 1049.
+  const ENTER_ALT = "\x1b[?1049h";
+  const EXIT_ALT = "\x1b[?1049l";
+  process.stdout.write(ENTER_ALT);
+
   try {
     await animateStartup(version, basename(projectRoot), session.activeBookId, modelInfo);
 
@@ -201,13 +209,12 @@ export async function launchTui(
       }),
       {
         exitOnCtrlC: true,
-        // Terminal.app crashes with rapid ANSI redraws + CJK IME input;
-        // halve the frame rate to reduce rendering pressure.
         ...(isAppleTerminal && { maxFps: 15 }),
       },
     );
     await app.waitUntilExit();
   } finally {
+    process.stdout.write(EXIT_ALT);
     process.emitWarning = originalEmitWarning;
     process.stderr.write = originalStderrWrite;
   }