diff --git a/packages/coding-agent/src/utils/ansi.ts b/packages/coding-agent/src/utils/ansi.ts index cad5eb65b..0c540ae8e 100644 --- a/packages/coding-agent/src/utils/ansi.ts +++ b/packages/coding-agent/src/utils/ansi.ts @@ -32,8 +32,9 @@ const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)"; // OSC sequences: ESC ] ... ST const OSC_START = "\\u001B\\]"; -// CSI and related: ESC/C1, optional intermediates, optional params (supports ; and :), then final byte -const CSI_START = "[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?"; +// CSI and related: ESC/C1, optional intermediates, optional private prefix (<, =, >), optional params +// (supports ; and :), then final byte +const CSI_START = "[\\u001B\\u009B][[\\]()#;?]*[<=>]?(?:\\d{1,4}(?:[;:]\\d{0,4})*)?"; const CSI_FINAL = "[\\dA-PR-TZcf-nq-uy=><~]"; // Complete sequences. OSC is non-greedy until the first ST. diff --git a/packages/coding-agent/test/ansi-utils.test.ts b/packages/coding-agent/test/ansi-utils.test.ts index 15bb43140..b395b6327 100644 --- a/packages/coding-agent/test/ansi-utils.test.ts +++ b/packages/coding-agent/test/ansi-utils.test.ts @@ -107,4 +107,12 @@ describe("stripAnsi", () => { const input = "a\x1b[31mred\x1b[0m\x1b]8;;https://example.com\x07link\x1b]8;;\x07z"; expect(stripAnsi(input)).toBe("aredlinkz"); }); + + it("strips private-parameter CSI sequences with their parameters", () => { + expect(stripAnsi("\x1b[<35;59;1Mstep 1")).toBe("step 1"); + expect(stripAnsi("a\x1b[<0;10;20mb")).toBe("ab"); + expect(stripAnsi("a\x1b[>0;276;0cb")).toBe("ab"); + expect(stripAnsi("a\x1b[=5hb")).toBe("ab"); + expect(stripAnsi("a\x9b<35;59;1Mb")).toBe("ab"); + }); });