import { assertEquals } from "@std/assert"; import { withDom } from "@berry/util/dom.ts"; import type { JsonValue } from "@berry/api"; import type { ToolCall } from "@berry/api/web.ts"; import { builtRenderers } from "./fixture.ts"; const call = (patch: Partial = {}): ToolCall => ({ name: "test", args: null, result: null, details: null, error: null, output: null, status: "ok", startedAt: null, durationMs: null, ...patch, }); /** What a card may be handed: arguments the model is still writing, and results of any shape. */ const ODD: JsonValue[] = [ null, 42, "partial", "not json", [], [null, false], {}, { path: 42, offset: "x", edits: "x", command: 5, url: false, format: 42 }, { actions: "bad", screenshots: "bad", completed: "bad", output: 42, exitCode: "bad" }, { actions: [null, false, { action: "pointer", x: 12 }] }, [{ title: "bad", url: false, snippet: "" }], ]; Deno.test("every built tool renderer survives partial arguments and malformed results", () => withDom(async () => { for (const name of ["browser", "code", "web"]) { for (const [tool, renderer] of Object.entries((await builtRenderers(name)).tools ?? {})) { const body = renderer.body?.(); for (const value of ODD) { renderer.summary?.(value); renderer.timeout?.(value); for (const status of ["streaming", "ok", "error"] as const) { body?.update(call({ name: tool, status, args: value, result: value, details: value })); } body?.update(call({ name: tool, output: "streamed", error: "failed" })); } body?.dispose?.(); } } })); Deno.test("search results read the same as a value or as the text a direct call returns", () => withDom(async () => { const view = (await builtRenderers("web")).tools!.web_search.body!(); const found = [{ title: "A result", url: "https://example.com/", snippet: "A snippet" }]; for (const result of [found, JSON.stringify(found)]) { view.update(call({ result })); assertEquals(view.element.querySelector("a")?.getAttribute("href"), "https://example.com/"); } })); Deno.test("naive file renderers keep literal text that resembles line anchors", () => withDom(async () => { const renderers = (await builtRenderers("code")).tools!; const read = renderers.read.body!(); read.update(call({ result: "AbCd│literal", details: { editMode: "naive" } })); assertEquals(read.element.textContent, "AbCd│literal"); const diff = renderers.edit.body!(); const result = "+AbCd│literal"; diff.update(call({ result, details: { editMode: "naive" } })); assertEquals(diff.element.textContent, "+AbCd│literal"); diff.update(call({ result })); assertEquals(diff.element.textContent, "+literal"); }));