Skip to content
Source
Sign inSign up
Open History to see the last commit

toolItems.test.ts

94 lines3.2 KB

1import { ThreadId, TurnItemId } from "@t3tools/contracts";
2import * as DateTime from "effect/DateTime";
3import { describe, expect, it } from "vite-plus/test";
4import {
5 MAX_TOOL_OUTPUT_IMAGES,
6 MAX_TOOL_OUTPUT_IMAGE_BASE64_LENGTH,
7 toolOutputImages,
8} from "@t3tools/shared/toolOutput";
9​
10import { openCodeToolOutput, openCodeToolTurnItem } from "./toolItems.ts";
11​
12describe("openCodeToolOutput", () => {
13 it("preserves inline raster file content and leaves other files unserved", () => {
14 const output = openCodeToolOutput("Preview complete", [
15 { uri: "https://example.com/preview.png", mime: "image/png" },
16 { uri: "file:///tmp/preview.png", mime: "image/png" },
17 { uri: "data:image/svg+xml;base64,AAAA", mime: "image/svg+xml" },
18 { uri: "data:image/png;base64,AAAA", mime: "image/jpeg" },
19 { uri: "data:image/png;base64,", mime: "image/png" },
20 { uri: "data:image/png;base64,iVBORw0KGgo=", mime: "image/png" },
21 ]);
22 expect(toolOutputImages(output)).toEqual([{ mimeType: "image/png", data: "iVBORw0KGgo=" }]);
23 expect(output).toEqual({
24 content: [
25 { type: "text", text: "Preview complete" },
26 { type: "image", mimeType: "image/png", data: "iVBORw0KGgo=" },
27 ],
28 });
29 expect(openCodeToolOutput("Text result")).toBe("Text result");
30 const oversized = "A".repeat(MAX_TOOL_OUTPUT_IMAGE_BASE64_LENGTH + 4);
31 const bounded = openCodeToolOutput(
32 "Preview complete",
33 Array.from({ length: MAX_TOOL_OUTPUT_IMAGES + 2 }, (_, index) => ({
34 uri: `data:image/png;base64,${index === 0 ? oversized : "AQ=="}`,
35 mime: "image/png",
36 })),
37 );
38 expect(typeof bounded === "object" ? bounded.content.length : 0).toBe(
39 MAX_TOOL_OUTPUT_IMAGES + 1,
40 );
41 const images = toolOutputImages(bounded);
42 expect(images[0]?.data?.length).toBe(oversized.length);
43 expect(images[1]?.data).toBe("AQ==");
44 });
45});
46​
47describe("openCodeToolTurnItem", () => {
48 it.each([
49 {
50 name: "deletion",
51 toolName: "edit",
52 input: { oldString: "old\n", newString: "", newText: "fallback" },
53 expected: { oldStr: "old\n", newStr: "" },
54 },
55 {
56 name: "whitespace replacement",
57 toolName: "edit",
58 input: { oldString: " \t", newString: "\n\t" },
59 expected: { oldStr: " \t", newStr: "\n\t" },
60 },
61 {
62 name: "empty write",
63 toolName: "write",
64 input: { content: "" },
65 expected: { newStr: "" },
66 },
67 ])("preserves exact file content for $name", ({ toolName, input, expected }) => {
68 const item = openCodeToolTurnItem(
69 {
70 id: TurnItemId.make("tool-item"),
71 threadId: ThreadId.make("thread"),
72 runId: null,
73 nodeId: null,
74 providerThreadId: null,
75 providerTurnId: null,
76 nativeItemRef: null,
77 parentItemId: null,
78 ordinal: 0,
79 status: "completed",
80 title: toolName,
81 startedAt: null,
82 completedAt: null,
83 updatedAt: DateTime.makeUnsafe("2026-11-04T00:00:00Z"),
84 },
85 {
86 name: toolName,
87 input: { filePath: "src/index.ts", ...input },
88 output: undefined,
89 completedMetadata: undefined,
90 },
91 );
92 expect(item).toMatchObject({ type: "file_change", fileName: "src/index.ts", ...expected });
93 });
94});