import { afterEach, beforeAll, beforeEach, describe, expect, it } from "bun:test"; import type { AssistantMessage } from "@oh-my-pi/pi-ai"; import { resetSettingsForTest, Settings } from "@oh-my-pi/pi-coding-agent/config/settings"; import { AssistantMessageComponent } from "@oh-my-pi/pi-coding-agent/modes/components/assistant-message"; import { initTheme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme"; import { setTerminalImageProtocol, TERMINAL } from "@oh-my-pi/pi-tui"; const originalImageProtocol = TERMINAL.imageProtocol; const RENDER_WIDTH = 120; function erroredMessage(errorMessage: string): AssistantMessage { return { role: "assistant", content: [], api: "anthropic-messages", provider: "anthropic", model: "claude-sonnet-4-5", usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }, }, stopReason: "error", errorMessage, timestamp: Date.now(), }; } function renderLines(message: AssistantMessage): string[] { const component = new AssistantMessageComponent(message); return Bun.stripANSI(component.render(RENDER_WIDTH).join("\n")) .split("\n") .map(line => line.trimEnd()); } beforeAll(async () => { await initTheme(false); }); beforeEach(async () => { resetSettingsForTest(); await Settings.init({ inMemory: true }); setTerminalImageProtocol(null); }); afterEach(() => { resetSettingsForTest(); setTerminalImageProtocol(originalImageProtocol); }); describe("AssistantMessageComponent error rendering", () => { // A proxy 502 returns its own HTML page as the body; AnthropicApiError folds // that whole document into `errorMessage`. The inline transcript render must // not faithfully reprint every line, or the scrollback fills with the HTML // page's blank lines (the reported "weird terminal state"). const longLine = "x".repeat(300); const body = Array.from({ length: 25 }, (_, i) => `marker-${i}