From f09d01b85e0384647fcab6779d35ab9dabe04be3 Mon Sep 17 00:00:00 2001 From: Rcardo <2895359972@qq.com> Date: Fri, 30 Oct 2026 05:11:08 +0800 Subject: [PATCH] fix(tui): detect Orca terminals as Kitty-image capable (#9329) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Treat `TERM_PROGRAM=Orca` as Kitty-image capable in `pi-tui`'s terminal capability detection, so image components render inline instead of falling back to text when running inside Orca. - Recognize Orca as supporting Kitty inline images, true color, and OSC 8 hyperlinks. - Preserve the existing tmux and screen precedence guards. - Gate images on Orca's capability advertisement: require both `TERM_PROGRAM=Orca` and Orca's `ORCA_IMAGE_PROTOCOL=kitty` signal before enabling Kitty output, so existing Orca releases that do not yet advertise image support safely keep the text fallback. - Add a regression test and the package/CLI changesets. ## Related - Requested by maintainer approval in [earendil-works/pi#7357](https://github.com/earendil-works/pi/issues/7357) (lgtm). - Depends on the Orca-side capability advertisement, which has landed: [stablyai/orca#19512](https://github.com/stablyai/orca/pull/19512) (merged 2026-09-18, `09073086a8`) exports `ORCA_IMAGE_PROTOCOL=kitty` on the daemon, local, and relay PTY paths, and forwards it across the WSL boundary. Supersedes [stablyai/orca#11706](https://github.com/stablyai/orca/pull/11706), which was closed in favor of #19512. ## Testing - `pnpm --filter @moonshot-ai/pi-tui test` — focused regression suite passes. - `pnpm --filter @moonshot-ai/pi-tui typecheck` — passes. --- packages/tui/src/terminal-image.ts | 7 +++++++ packages/tui/test/terminal-image.test.ts | 17 +++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/packages/tui/src/terminal-image.ts b/packages/tui/src/terminal-image.ts index 201a40603..64703bf48 100644 --- a/packages/tui/src/terminal-image.ts +++ b/packages/tui/src/terminal-image.ts @@ -96,6 +96,13 @@ function detectCapabilitiesFromEnvironment(tmuxForwardsHyperlink: () => boolean) return { images: "kitty", trueColor: true, hyperlinks: true }; } + // Orca supports Kitty graphics but only advertises it through ORCA_IMAGE_PROTOCOL. Require + // both signals so Orca releases predating that advertisement keep the text fallback instead + // of reserving image rows that nothing renders. + if (termProgram === "orca" && process.env.ORCA_IMAGE_PROTOCOL === "kitty") { + return { images: "kitty", trueColor: true, hyperlinks: true }; + } + if (process.env.KITTY_WINDOW_ID || termProgram === "kitty") { return { images: "kitty", trueColor: true, hyperlinks: true }; } diff --git a/packages/tui/test/terminal-image.test.ts b/packages/tui/test/terminal-image.test.ts index 6fd05f43d..0ae5bd8b4 100644 --- a/packages/tui/test/terminal-image.test.ts +++ b/packages/tui/test/terminal-image.test.ts @@ -34,6 +34,7 @@ import { visibleWidth } from "../src/utils.ts"; const ENV_KEYS = [ "TERM", "TERM_PROGRAM", + "ORCA_IMAGE_PROTOCOL", "TERMINAL_EMULATOR", "COLORTERM", "TMUX", @@ -343,6 +344,22 @@ describe("detectCapabilities", () => { }); }); + it("keeps images disabled for Orca without an image capability signal", () => { + withEnv({ TERM_PROGRAM: "Orca" }, () => { + const caps = detectCapabilities(); + assert.strictEqual(caps.images, null); + }); + }); + + it("enables images and hyperlinks for Orca advertising Kitty support", () => { + withEnv({ TERM_PROGRAM: "Orca", ORCA_IMAGE_PROTOCOL: "kitty" }, () => { + const caps = detectCapabilities(); + assert.strictEqual(caps.images, "kitty"); + assert.strictEqual(caps.trueColor, true); + assert.strictEqual(caps.hyperlinks, true); + }); + }); + it("enables hyperlinks for Ghostty", () => { withEnv({ TERM_PROGRAM: "ghostty" }, () => { const caps = detectCapabilities();