From c8b37c8d2e04f2a6ff39a47e2e2ada2e1fa9743e Mon Sep 17 00:00:00 2001 From: omp-eval Date: Sun, 26 Jul 2026 15:31:38 +0200 Subject: [PATCH] fix(plugins): return bare Kitty delete sequences from legacy pi-tui shim Upstream Pi's deleteKittyImage/deleteAllKittyImages return unwrapped control sequences; legacy callers such as pi-sprite wrap tmux passthrough themselves. Aliasing OMP's auto-wrapping encodeKittyDeleteImage (and hand-wrapping deleteAllKittyImages) double-wrapped under tmux, so the outer terminal dropped the delete command. Match the upstream bare-sequence contract and pin it in the regression test. --- .../src/extensibility/legacy-pi-tui-shim.ts | 25 ++++++++++++------- .../legacy-pi-ai-type-remap.test.ts | 6 +++-- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/packages/coding-agent/src/extensibility/legacy-pi-tui-shim.ts b/packages/coding-agent/src/extensibility/legacy-pi-tui-shim.ts index 7b448933a..870de8c76 100644 --- a/packages/coding-agent/src/extensibility/legacy-pi-tui-shim.ts +++ b/packages/coding-agent/src/extensibility/legacy-pi-tui-shim.ts @@ -6,13 +6,10 @@ * exposes the equivalent, broader `decodePrintableKey` helper. Keep the legacy * name available without reintroducing it into the canonical package surface. */ -import { ImageProtocol, isInsideTmux, TERMINAL, wrapTmuxPassthrough } from "@oh-my-pi/pi-tui"; +import { ImageProtocol, TERMINAL } from "@oh-my-pi/pi-tui"; export * from "@oh-my-pi/pi-tui"; -export { - decodePrintableKey as decodeKittyPrintable, - encodeKittyDeleteImage as deleteKittyImage, -} from "@oh-my-pi/pi-tui"; +export { decodePrintableKey as decodeKittyPrintable } from "@oh-my-pi/pi-tui"; /** Report canonical terminal capabilities through the legacy Pi TUI shape. */ export function getCapabilities(): { @@ -29,8 +26,18 @@ export function getCapabilities(): { return { images, trueColor: TERMINAL.trueColor, hyperlinks: TERMINAL.hyperlinks }; } -/** Delete every Kitty graphics image using the legacy Pi TUI control sequence. */ -export function deleteAllKittyImages(): string { - const sequence = "\x1b_Ga=d,d=A,q=2\x1b\\"; - return isInsideTmux() ? wrapTmuxPassthrough(sequence) : sequence; +/** + * Delete one Kitty graphics image by id, matching the legacy Pi TUI helper. + * + * Returns the bare control sequence exactly like upstream Pi: legacy callers + * (e.g. pi-sprite) apply their own tmux passthrough wrapping, so wrapping here + * would double-wrap under tmux and the outer terminal would drop the command. + */ +export function deleteKittyImage(imageId: number): string { + return `\x1b_Ga=d,d=I,i=${imageId},q=2\x1b\\`; +} + +/** Delete every Kitty graphics image using the legacy Pi TUI bare sequence. */ +export function deleteAllKittyImages(): string { + return "\x1b_Ga=d,d=A,q=2\x1b\\"; } diff --git a/packages/coding-agent/test/extensibility/legacy-pi-ai-type-remap.test.ts b/packages/coding-agent/test/extensibility/legacy-pi-ai-type-remap.test.ts index 90ebf4d6b..4eb64ddbd 100644 --- a/packages/coding-agent/test/extensibility/legacy-pi-ai-type-remap.test.ts +++ b/packages/coding-agent/test/extensibility/legacy-pi-ai-type-remap.test.ts @@ -280,8 +280,10 @@ describe("legacy pi package root remaps (issue #1474)", () => { deleteAll: string; capabilities: { images: "kitty" | "iterm2" | null; trueColor: boolean; hyperlinks: boolean }; }; - expect(loaded.deleteOne).toContain("a=d,d=I,i=42,q=2"); - expect(loaded.deleteAll).toContain("a=d,d=A,q=2"); + // Bare sequences, exactly like upstream Pi: legacy callers (pi-sprite) + // apply their own tmux passthrough wrapping. + expect(loaded.deleteOne).toBe("\x1b_Ga=d,d=I,i=42,q=2\x1b\\"); + expect(loaded.deleteAll).toBe("\x1b_Ga=d,d=A,q=2\x1b\\"); expect(["kitty", "iterm2", null]).toContain(loaded.capabilities.images); expect(typeof loaded.capabilities.trueColor).toBe("boolean"); expect(typeof loaded.capabilities.hyperlinks).toBe("boolean");