import { assertEquals, assertExists, assertStrictEquals } from "@std/assert"; import type { ConversationId, EntryId, EntryRecord, LiveState } from "@earendil-works/pi-durable"; import { fauxAssistantMessage, fauxToolCall } from "@earendil-works/pi-ai/providers/faux"; import type { JsonValue } from "@berry/api"; import { withDom } from "@berry/util/dom.ts"; Deno.test("codemode exposes its calls with independent short input and output previews", async (t) => { const observed = new Set(); let resize: (entries: { target: Element }[]) => void; class Resize { constructor(callback: typeof resize) { resize = callback; } observe(target: Element) { observed.add(target); } unobserve(target: Element) { observed.delete(target); } } const record = (id: number, kind: string, model: EntryRecord["model"]): EntryRecord => ({ id: id as EntryId, conversationId: 1 as ConversationId, kind, model, }); const source = Array.from({ length: 20 }, (_, i) => `text("line ${i + 1}");`).join("\n"); const output = Array.from({ length: 20 }, (_, i) => `line ${i + 1}`).join("\n"); const calls: JsonValue[] = [ { extension: "code", name: "read", args: { path: "a.ts" }, status: "ok", value: "file text" }, { extension: "code", name: "bash", args: { command: "false" }, status: "error", error: "failed", }, ]; const entries = [record(1, "pi.assistant", [ fauxAssistantMessage(fauxToolCall("codemode", { code: source }, { id: "script" }), { stopReason: "toolUse", }), ])]; const live = { run: { taskId: 2 }, tools: [{ callId: "script", name: "codemode", status: "running", details: { calls } }], } as unknown as LiveState; let nextResult = 3; const result = (text: string, isError = false) => record(nextResult++, "pi.tool-result", [{ role: "toolResult", toolCallId: "script", toolName: "codemode", content: [{ type: "text", text }], details: { calls }, isError, timestamp: 0, }]); await withDom(async () => { const { transcript } = await import("./transcript.tsx"); const view = transcript(); document.body.append(view.element); const header = (card: Element) => { const button = card.querySelector(":scope > .tool-header"); assertExists(button); return button; }; try { view.update(entries, live); const outer = view.element.querySelector(".tool")!; const [input, outputCard] = [...outer.querySelectorAll(".codemode-text")]; const nested = [...outer.querySelectorAll(".nested .tool")]; await t.step("the parent starts open and every constituent call starts closed", () => { assertEquals(header(outer).getAttribute("aria-expanded"), "true"); assertEquals(outer.dataset.view, "open"); for (const call of nested) { assertEquals(header(call).getAttribute("aria-expanded"), "false"); assertEquals(call.dataset.view, "closed"); } assertEquals(outputCard.hidden, true); assertEquals( [...input.querySelectorAll(".code-text")].map((line) => line.textContent).join(""), source, ); }); await t.step("input and output expand independently", () => { view.update([...entries, result(`Script completed\n${output}`)], {}); assertEquals(outputCard.hidden, false); assertEquals(outputCard.querySelector("pre")!.textContent, output); header(input).click(); assertEquals(input.dataset.view, "open"); assertEquals(outputCard.dataset.view, "preview"); header(outputCard).click(); assertEquals(outputCard.dataset.view, "open"); header(input).click(); header(outputCard).click(); assertEquals([input.dataset.view, outputCard.dataset.view], ["preview", "preview"]); assertEquals(outer.dataset.view, "open"); assertEquals(nested.map((call) => call.dataset.view), ["closed", "closed"]); }); await t.step("clipped text has a working show-all affordance", () => { for (const card of [input, outputCard]) { const preview = card.querySelector(":scope > .tool-preview")!; Object.defineProperty(preview, "clientHeight", { configurable: true, value: 96 }); Object.defineProperty(preview.firstElementChild!, "offsetHeight", { configurable: true, value: 600, }); } resize!([...observed].map((target) => ({ target }))); for (const card of [input, outputCard]) { const more = card.querySelector(".tool-more")!; const content = card.querySelector(".tool-preview > div")!; assertEquals(content.inert, true); assertEquals(more.hidden, false); assertEquals(header(card).getAttribute("aria-expanded"), "false"); more.click(); assertEquals(more.hidden, true); assertEquals(content.inert, false); assertEquals(header(card).getAttribute("aria-expanded"), "true"); assertStrictEquals(document.activeElement, header(card)); } }); await t.step( "bottom controls restore previews and closed calls without changing siblings", () => { const less = input.querySelector(":scope > .tool-less")!; assertEquals(less.hidden, false); less.click(); assertEquals(input.dataset.view, "preview"); assertEquals(less.hidden, true); assertEquals(header(input).getAttribute("aria-expanded"), "false"); assertStrictEquals(document.activeElement, header(input)); assertEquals(outputCard.dataset.view, "open"); input.querySelector(".tool-more")!.click(); assertEquals(input.dataset.view, "open"); header(nested[0]).click(); const close = nested[0].querySelector(":scope > .tool-less")!; close.click(); assertEquals(nested[0].dataset.view, "closed"); assertEquals(close.hidden, true); assertEquals(header(nested[0]).getAttribute("aria-expanded"), "false"); assertStrictEquals(document.activeElement, header(nested[0])); assertEquals(outer.dataset.view, "open"); }, ); await t.step( "user choices survive progress, completion and errors without affecting siblings", () => { header(input).click(); header(nested[0]).click(); header(outer).click(); view.update(entries, live); view.update([...entries, result("Script failed\nFailure details", true)], {}); assertEquals(outer.dataset.view, "closed"); header(outer).click(); assertEquals(outer.dataset.view, "open"); assertStrictEquals(outer.querySelector(".codemode-text"), input); assertEquals(input.dataset.view, "preview"); assertEquals(outputCard.dataset.view, "open"); assertEquals(nested.map((call) => call.dataset.view), ["open", "closed"]); assertEquals(outputCard.querySelector("pre")!.textContent, "Failure details"); view.update(entries, live); assertEquals(outputCard.hidden, true); view.update([...entries, result(`Script completed\n${output}`)], {}); assertEquals(outputCard.hidden, false); assertEquals(outputCard.dataset.view, "open"); assertEquals(input.dataset.view, "preview"); }, ); } finally { view.dispose(); assertEquals(observed.size, 0); } }, { globals: { ResizeObserver: Resize } }); });