diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index d4a342646..81495eef5 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -9,6 +9,7 @@ ### Changed - Softened the bash tool's `PI_*` environment guideline in an attempt to reduce unnecessary inspection commands ([#7128](https://github.com/earendil-works/pi/issues/7128)). +- Reduced worst-case automatic terminal theme detection delay from 200 ms to 100 ms by probing color-scheme and background support concurrently. ### Fixed diff --git a/packages/coding-agent/src/modes/interactive/theme/theme.ts b/packages/coding-agent/src/modes/interactive/theme/theme.ts index b38678629..c6bb899d4 100644 --- a/packages/coding-agent/src/modes/interactive/theme/theme.ts +++ b/packages/coding-agent/src/modes/interactive/theme/theme.ts @@ -793,13 +793,21 @@ export async function detectTerminalThemeForAuto({ timeoutMs, env, }: TerminalAutoThemeDetectionOptions): Promise { + let colorSchemePromise: Promise | undefined; try { - const colorScheme = await ui.queryTerminalColorScheme?.({ timeoutMs }); + colorSchemePromise = ui.queryTerminalColorScheme?.({ timeoutMs }); + } catch { + // Fall back to OSC 11 / COLORFGBG detection when starting the color-scheme query fails. + } + const backgroundThemePromise = detectTerminalBackgroundTheme({ ui, timeoutMs, env }); + + try { + const colorScheme = await colorSchemePromise; if (colorScheme) return colorScheme; } catch { - // Fall back to OSC 11 / COLORFGBG detection when color-scheme DSR is unsupported. + // Fall back to the concurrently queried OSC 11 / COLORFGBG detection. } - return (await detectTerminalBackgroundTheme({ ui, timeoutMs, env })).theme; + return (await backgroundThemePromise).theme; } export function getDefaultTheme(): string { diff --git a/packages/coding-agent/test/theme-detection.test.ts b/packages/coding-agent/test/theme-detection.test.ts index 6bdc597bd..c323ec6f8 100644 --- a/packages/coding-agent/test/theme-detection.test.ts +++ b/packages/coding-agent/test/theme-detection.test.ts @@ -3,6 +3,7 @@ import { afterEach, describe, expect, it } from "vitest"; import { detectTerminalBackgroundFromEnv, detectTerminalBackgroundTheme, + detectTerminalThemeForAuto, getThemeByName, getThemeForRgbColor, parseAutoThemeSetting, @@ -99,6 +100,46 @@ describe("detectTerminalBackgroundTheme", () => { }); }); +describe("detectTerminalThemeForAuto", () => { + it("starts both queries and returns the preferred color-scheme result without waiting", async () => { + let resolveColorScheme!: (theme: "dark" | "light" | undefined) => void; + let backgroundQueryStarted = false; + const detection = detectTerminalThemeForAuto({ + timeoutMs: 100, + ui: { + queryTerminalColorScheme: () => + new Promise((resolve) => { + resolveColorScheme = resolve; + }), + queryTerminalBackgroundColor: () => { + backgroundQueryStarted = true; + return new Promise(() => {}); + }, + }, + }); + + expect(backgroundQueryStarted).toBe(true); + resolveColorScheme("dark"); + await expect(detection).resolves.toBe("dark"); + }); + + it("uses the background result when the color-scheme query fails", async () => { + await expect( + detectTerminalThemeForAuto({ + timeoutMs: 100, + ui: { + async queryTerminalColorScheme(): Promise { + throw new Error("color-scheme query failed"); + }, + async queryTerminalBackgroundColor(): Promise { + return { r: 250, g: 250, b: 250 }; + }, + }, + }), + ).resolves.toBe("light"); + }); +}); + describe("theme color mode", () => { it("uses terminal capabilities", () => { setCapabilities({ images: null, trueColor: false, hyperlinks: false });