blob: 508c6687ca8d7976ad74063e806fe755f5645283 [file] [log] [blame]
Sean McCullough86b56862025-04-18 13:04:03 -07001import { css, html, LitElement } from "lit";
Philip Zeyliger16fa8b42025-05-02 04:28:16 +00002import { customElement, property, state } from "lit/decorators.js";
Sean McCullough2deac842025-04-21 18:17:57 -07003import { repeat } from "lit/directives/repeat.js";
Josh Bleecher Snyder19969a92025-06-05 14:34:02 -07004import { State, ToolCall } from "../types";
Pokey Rule7ac5ed02025-05-07 15:26:10 +01005import "./sketch-tool-card";
Philip Zeyliger80b488d2025-05-10 18:21:54 -07006import "./sketch-tool-card-take-screenshot";
Josh Bleecher Snyder74d690e2025-05-14 18:16:03 -07007import "./sketch-tool-card-about-sketch";
Josh Bleecher Snyder2d081192025-05-29 13:46:04 +00008import "./sketch-tool-card-browser-navigate";
9import "./sketch-tool-card-browser-click";
10import "./sketch-tool-card-browser-type";
11import "./sketch-tool-card-browser-wait-for";
12import "./sketch-tool-card-browser-get-text";
13import "./sketch-tool-card-browser-eval";
14import "./sketch-tool-card-browser-scroll-into-view";
15import "./sketch-tool-card-browser-resize";
Philip Zeyliger542bda32025-06-11 18:31:03 -070016import "./sketch-tool-card-read-image";
Josh Bleecher Snyder2d081192025-05-29 13:46:04 +000017import "./sketch-tool-card-browser-recent-console-logs";
18import "./sketch-tool-card-browser-clear-console-logs";
Sean McCullough86b56862025-04-18 13:04:03 -070019
20@customElement("sketch-tool-calls")
21export class SketchToolCalls extends LitElement {
22 @property()
23 toolCalls: ToolCall[] = [];
24
Sean McCullough2deac842025-04-21 18:17:57 -070025 @property()
26 open: boolean = false;
27
Josh Bleecher Snyder19969a92025-06-05 14:34:02 -070028 @property()
29 state: State;
30
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000031 @state()
32 expanded: boolean = false;
33
Sean McCullough86b56862025-04-18 13:04:03 -070034 static styles = css`
35 /* Tool calls container styles */
36 .tool-calls-container {
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000037 margin-top: 8px;
38 padding-top: 4px;
Philip Zeyligere31d2a92025-05-11 15:22:35 -070039 max-width: 100%;
40 width: 100%;
41 box-sizing: border-box;
Sean McCullough86b56862025-04-18 13:04:03 -070042 }
43
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070044 /* Card container */
Sean McCullough86b56862025-04-18 13:04:03 -070045 .tool-call-card {
46 display: flex;
47 flex-direction: column;
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000048 background-color: rgba(255, 255, 255, 0.6);
49 border-radius: 6px;
50 margin-bottom: 6px;
Sean McCullough86b56862025-04-18 13:04:03 -070051 overflow: hidden;
52 cursor: pointer;
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000053 border-left: 2px solid rgba(0, 0, 0, 0.1);
54 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
Philip Zeyligere31d2a92025-05-11 15:22:35 -070055 max-width: 100%;
56 overflow-wrap: break-word;
57 word-break: break-word;
Sean McCullough86b56862025-04-18 13:04:03 -070058 }
59
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070060 /* Status indicators for tool calls */
Sean McCullough86b56862025-04-18 13:04:03 -070061 .tool-call-status {
62 margin-right: 4px;
63 text-align: center;
64 }
65
66 .tool-call-status.spinner {
67 animation: spin 1s infinite linear;
68 display: inline-block;
69 width: 1em;
70 }
71
Sean McCullough86b56862025-04-18 13:04:03 -070072 @keyframes spin {
73 0% {
74 transform: rotate(0deg);
75 }
76 100% {
77 transform: rotate(360deg);
78 }
79 }
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000080
81 .tool-call-cards-container {
82 display: block;
83 }
Sean McCullough86b56862025-04-18 13:04:03 -070084 `;
85
86 constructor() {
87 super();
88 }
89
Sean McCullough86b56862025-04-18 13:04:03 -070090 connectedCallback() {
91 super.connectedCallback();
92 }
93
Sean McCullough86b56862025-04-18 13:04:03 -070094 disconnectedCallback() {
95 super.disconnectedCallback();
96 }
97
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070098 cardForToolCall(toolCall: ToolCall, open: boolean) {
Sean McCullough86b56862025-04-18 13:04:03 -070099 switch (toolCall.name) {
Sean McCullough86b56862025-04-18 13:04:03 -0700100 case "bash":
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700101 return html`<sketch-tool-card-bash
102 .open=${open}
103 .toolCall=${toolCall}
104 ></sketch-tool-card-bash>`;
Sean McCullough86b56862025-04-18 13:04:03 -0700105 case "codereview":
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700106 return html`<sketch-tool-card-codereview
107 .open=${open}
108 .toolCall=${toolCall}
109 ></sketch-tool-card-codereview>`;
Sean McCullough86b56862025-04-18 13:04:03 -0700110 case "done":
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700111 return html`<sketch-tool-card-done
112 .open=${open}
113 .toolCall=${toolCall}
114 ></sketch-tool-card-done>`;
Sean McCullough485afc62025-04-28 14:28:39 -0700115 case "multiplechoice":
116 return html`<sketch-tool-card-multiple-choice
117 .open=${open}
118 .toolCall=${toolCall}
119 ></sketch-tool-card-multiple-choice>`;
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700120 case "patch":
121 return html`<sketch-tool-card-patch
122 .open=${open}
123 .toolCall=${toolCall}
124 ></sketch-tool-card-patch>`;
125 case "think":
126 return html`<sketch-tool-card-think
127 .open=${open}
128 .toolCall=${toolCall}
129 ></sketch-tool-card-think>`;
Josh Bleecher Snyder19969a92025-06-05 14:34:02 -0700130 case "set-slug":
131 return html`<sketch-tool-card-set-slug
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700132 .open=${open}
133 .toolCall=${toolCall}
Josh Bleecher Snyder19969a92025-06-05 14:34:02 -0700134 ></sketch-tool-card-set-slug>`;
135 case "commit-message-style":
136 return html`<sketch-tool-card-commit-message-style
Josh Bleecher Snydera2a31502025-05-07 12:37:18 +0000137 .open=${open}
138 .toolCall=${toolCall}
Josh Bleecher Snyder19969a92025-06-05 14:34:02 -0700139 .state=${this.state}
140 ></sketch-tool-card-commit-message-style>`;
Philip Zeyliger80b488d2025-05-10 18:21:54 -0700141 case "browser_take_screenshot":
142 return html`<sketch-tool-card-take-screenshot
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000143 .open=${open}
144 .toolCall=${toolCall}
Philip Zeyliger80b488d2025-05-10 18:21:54 -0700145 ></sketch-tool-card-take-screenshot>`;
Josh Bleecher Snyder74d690e2025-05-14 18:16:03 -0700146 case "about_sketch":
147 return html`<sketch-tool-card-about-sketch
Josh Bleecher Snyder31785ae2025-05-06 01:50:58 +0000148 .open=${open}
149 .toolCall=${toolCall}
Josh Bleecher Snyder74d690e2025-05-14 18:16:03 -0700150 ></sketch-tool-card-about-sketch>`;
Josh Bleecher Snyder112b9232025-05-23 11:26:33 -0700151 case "todo_write":
152 return html`<sketch-tool-card-todo-write
153 .open=${open}
154 .toolCall=${toolCall}
155 ></sketch-tool-card-todo-write>`;
156 case "todo_read":
157 return html`<sketch-tool-card-todo-read
158 .open=${open}
159 .toolCall=${toolCall}
160 ></sketch-tool-card-todo-read>`;
Josh Bleecher Snyder2d081192025-05-29 13:46:04 +0000161 case "browser_navigate":
162 return html`<sketch-tool-card-browser-navigate
163 .open=${open}
164 .toolCall=${toolCall}
165 ></sketch-tool-card-browser-navigate>`;
Josh Bleecher Snyder991164f2025-05-29 05:02:10 +0000166 case "keyword_search":
167 return html`<sketch-tool-card-keyword-search
168 .open=${open}
169 .toolCall=${toolCall}
170 ></sketch-tool-card-keyword-search>`;
Josh Bleecher Snyder2d081192025-05-29 13:46:04 +0000171 case "browser_click":
172 return html`<sketch-tool-card-browser-click
173 .open=${open}
174 .toolCall=${toolCall}
175 ></sketch-tool-card-browser-click>`;
176 case "browser_type":
177 return html`<sketch-tool-card-browser-type
178 .open=${open}
179 .toolCall=${toolCall}
180 ></sketch-tool-card-browser-type>`;
181 case "browser_wait_for":
182 return html`<sketch-tool-card-browser-wait-for
183 .open=${open}
184 .toolCall=${toolCall}
185 ></sketch-tool-card-browser-wait-for>`;
186 case "browser_get_text":
187 return html`<sketch-tool-card-browser-get-text
188 .open=${open}
189 .toolCall=${toolCall}
190 ></sketch-tool-card-browser-get-text>`;
191 case "browser_eval":
192 return html`<sketch-tool-card-browser-eval
193 .open=${open}
194 .toolCall=${toolCall}
195 ></sketch-tool-card-browser-eval>`;
196 case "browser_scroll_into_view":
197 return html`<sketch-tool-card-browser-scroll-into-view
198 .open=${open}
199 .toolCall=${toolCall}
200 ></sketch-tool-card-browser-scroll-into-view>`;
201 case "browser_resize":
202 return html`<sketch-tool-card-browser-resize
203 .open=${open}
204 .toolCall=${toolCall}
205 ></sketch-tool-card-browser-resize>`;
Philip Zeyliger542bda32025-06-11 18:31:03 -0700206 case "read_image":
207 return html`<sketch-tool-card-read-image
Josh Bleecher Snyder2d081192025-05-29 13:46:04 +0000208 .open=${open}
209 .toolCall=${toolCall}
Philip Zeyliger542bda32025-06-11 18:31:03 -0700210 ></sketch-tool-card-read-image>`;
Josh Bleecher Snyder2d081192025-05-29 13:46:04 +0000211 case "browser_recent_console_logs":
212 return html`<sketch-tool-card-browser-recent-console-logs
213 .open=${open}
214 .toolCall=${toolCall}
215 ></sketch-tool-card-browser-recent-console-logs>`;
216 case "browser_clear_console_logs":
217 return html`<sketch-tool-card-browser-clear-console-logs
218 .open=${open}
219 .toolCall=${toolCall}
220 ></sketch-tool-card-browser-clear-console-logs>`;
Sean McCullough86b56862025-04-18 13:04:03 -0700221 }
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700222 return html`<sketch-tool-card-generic
223 .open=${open}
224 .toolCall=${toolCall}
225 ></sketch-tool-card-generic>`;
Sean McCullough86b56862025-04-18 13:04:03 -0700226 }
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700227
Sean McCullough2deac842025-04-21 18:17:57 -0700228 // toolUseKey return value should change, if the toolCall gets a response.
229 toolUseKey(toolCall: ToolCall): string {
Sean McCullough2deac842025-04-21 18:17:57 -0700230 if (!toolCall.result_message) {
231 return toolCall.tool_call_id;
232 }
233 return `${toolCall.tool_call_id}-${toolCall.result_message.idx}`;
234 }
235
Sean McCullough86b56862025-04-18 13:04:03 -0700236 render() {
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000237 if (!this.toolCalls || this.toolCalls.length === 0) {
238 return html``;
239 }
240
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700241 return html`<div class="tool-calls-container">
Sean McCullough86b56862025-04-18 13:04:03 -0700242 <div class="tool-call-cards-container">
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000243 ${repeat(this.toolCalls, this.toolUseKey, (toolCall, idx) => {
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000244 let shouldOpen = false;
245 // Always expand screenshot tool calls, expand last tool call if this.open is true
246 if (
Philip Zeyliger80b488d2025-05-10 18:21:54 -0700247 toolCall.name === "browser_take_screenshot" ||
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000248 (idx == this.toolCalls?.length - 1 && this.open)
249 ) {
250 shouldOpen = true;
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000251 }
252 return html`<div
253 id="${toolCall.tool_call_id}"
254 class="tool-call-card ${toolCall.name}"
255 >
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000256 ${this.cardForToolCall(toolCall, shouldOpen)}
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000257 </div>`;
258 })}
Sean McCullough86b56862025-04-18 13:04:03 -0700259 </div>
260 </div>`;
261 }
262}
263
264declare global {
265 interface HTMLElementTagNameMap {
266 "sketch-tool-calls": SketchToolCalls;
267 }
268}