1import { describe, expect, it } from "@effect/vitest";
2
3import { extractToolActivityPresentation } from "./toolPresentation.ts";
4
5describe("extractToolActivityPresentation", () => {
6 it("recovers computer-use presentation for retained calls without result metadata", () => {
7 const item = {
8 type: "dynamic_tool",
9 toolName: "js",
10 input: { code: "await sky.get_app_state(app);" },
11 };
12 expect(extractToolActivityPresentation(item)).toEqual({
13 toolSurface: "computer",
14 toolSource: { key: "computer-use", name: "Computer Use", kind: "computer" },
15 });
16 expect(extractToolActivityPresentation({ ...item, toolSurface: "browser" })).toEqual({
17 toolSurface: "browser",
18 });
19 expect(
20 extractToolActivityPresentation({ ...item, input: { code: "await fs.readFile(path);" } }),
21 ).toEqual({});
22 });
23
24 it("replaces a failed Sky call's generic node REPL source", () => {
25 const source = { key: "mcp:node_repl", name: "node repl", kind: "integration" };
26 const item = {
27 type: "dynamic_tool",
28 toolName: "node_repl.js",
29 title: "js",
30 status: "failed",
31 toolSource: source,
32 input: {
33 title: "Restrict the breakpoint to Git actions",
34 code: "await sky.type_text({app:'T3 Code (Nightly)',text:'debug(ga.run)'});",
35 },
36 };
37 expect(extractToolActivityPresentation(item)).toEqual({
38 toolSurface: "computer",
39 toolSource: { key: "computer-use", name: "Computer Use", kind: "computer" },
40 });
41 expect(
42 extractToolActivityPresentation({
43 ...item,
44 input: { code: "await fetch('http://127.0.0.1/json/list');" },
45 }),
46 ).toEqual({ toolSource: source });
47 });
48
49 it("retains valid image paths independently of redacted output", () => {
50 expect(
51 extractToolActivityPresentation({ viewedImagePath: " /workspace/reference.webp " }),
52 ).toEqual({ viewedImagePath: "/workspace/reference.webp" });
53 for (const viewedImagePath of [
54 "/workspace/README.md",
55 "/workspace/a.png\nother",
56 "x".repeat(4097) + ".png",
57 ])
58 expect(extractToolActivityPresentation({ viewedImagePath })).toEqual({});
59 });
60
61 it("reads provider-neutral presentation fields", () => {
62 expect(
63 extractToolActivityPresentation({
64 toolSurface: "browser",
65 toolIcon: {
66 _tag: "website",
67 pageUrl: "https://example.com/docs",
68 faviconUrl: "https://example.com/favicon.png",
69 faviconUrlDark: "https://example.com/favicon-dark.png",
70 },
71 toolSource: {
72 key: "integration:example",
73 name: "Example",
74 kind: "integration",
75 icon: {
76 _tag: "themed-logo",
77 logoUrl: "https://example.com/logo-light.png",
78 logoUrlDark: "https://example.com/logo-dark.png",
79 },
80 },
81 }),
82 ).toEqual({
83 toolSurface: "browser",
84 toolIcon: {
85 _tag: "website",
86 pageUrl: "https://example.com/docs",
87 faviconUrl: "https://example.com/favicon.png",
88 faviconUrlDark: "https://example.com/favicon-dark.png",
89 },
90 toolSource: {
91 key: "integration:example",
92 name: "Example",
93 kind: "integration",
94 icon: {
95 _tag: "themed-logo",
96 logoUrl: "https://example.com/logo-light.png",
97 logoUrlDark: "https://example.com/logo-dark.png",
98 },
99 },
100 });
101 });
102
103 it("reads provider-neutral native app icons", () => {
104 expect(
105 extractToolActivityPresentation({
106 toolSurface: "computer",
107 toolIcon: {
108 _tag: "native-app",
109 app: { _tag: "app-id", appId: "com.example.Editor" },
110 },
111 toolSource: {
112 key: "native-app:com.example.editor",
113 name: "Editor",
114 kind: "computer",
115 },
116 }),
117 ).toEqual({
118 toolSurface: "computer",
119 toolIcon: {
120 _tag: "native-app",
121 app: { _tag: "app-id", appId: "com.example.Editor" },
122 },
123 toolSource: {
124 key: "native-app:com.example.editor",
125 name: "Editor",
126 kind: "computer",
127 },
128 });
129 });
130
131 it("does not infer presentation from provider-specific payload data", () => {
132 expect(
133 extractToolActivityPresentation({
134 data: {
135 item: {
136 arguments: { code: 'await sky.click({ app: "Finder" })' },
137 result: {
138 _meta: {
139 "codex/toolSurface": {
140 kind: "computerUse",
141 app: { kind: "displayName", displayName: "Finder" },
142 },
143 },
144 },
145 },
146 },
147 }),
148 ).toEqual({});
149 });
150});