blob: 99b0f21086652acc5733df209bbbc38d61d9068c [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";
Sean McCulloughd9f13372025-04-21 15:08:49 -07004import { 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 Snyder31785ae2025-05-06 01:50:58 +00007import "./sketch-tool-card-knowledge-base";
Sean McCullough86b56862025-04-18 13:04:03 -07008
9@customElement("sketch-tool-calls")
10export class SketchToolCalls extends LitElement {
11 @property()
12 toolCalls: ToolCall[] = [];
13
Sean McCullough2deac842025-04-21 18:17:57 -070014 @property()
15 open: boolean = false;
16
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000017 @state()
18 expanded: boolean = false;
19
Sean McCullough86b56862025-04-18 13:04:03 -070020 static styles = css`
21 /* Tool calls container styles */
22 .tool-calls-container {
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000023 margin-top: 8px;
24 padding-top: 4px;
Philip Zeyligere31d2a92025-05-11 15:22:35 -070025 max-width: 100%;
26 width: 100%;
27 box-sizing: border-box;
Sean McCullough86b56862025-04-18 13:04:03 -070028 }
29
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070030 /* Card container */
Sean McCullough86b56862025-04-18 13:04:03 -070031 .tool-call-card {
32 display: flex;
33 flex-direction: column;
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000034 background-color: rgba(255, 255, 255, 0.6);
35 border-radius: 6px;
36 margin-bottom: 6px;
Sean McCullough86b56862025-04-18 13:04:03 -070037 overflow: hidden;
38 cursor: pointer;
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000039 border-left: 2px solid rgba(0, 0, 0, 0.1);
40 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
Philip Zeyligere31d2a92025-05-11 15:22:35 -070041 max-width: 100%;
42 overflow-wrap: break-word;
43 word-break: break-word;
Sean McCullough86b56862025-04-18 13:04:03 -070044 }
45
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070046 /* Status indicators for tool calls */
Sean McCullough86b56862025-04-18 13:04:03 -070047 .tool-call-status {
48 margin-right: 4px;
49 text-align: center;
50 }
51
52 .tool-call-status.spinner {
53 animation: spin 1s infinite linear;
54 display: inline-block;
55 width: 1em;
56 }
57
Sean McCullough86b56862025-04-18 13:04:03 -070058 @keyframes spin {
59 0% {
60 transform: rotate(0deg);
61 }
62 100% {
63 transform: rotate(360deg);
64 }
65 }
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000066
67 .tool-call-cards-container {
68 display: block;
69 }
Sean McCullough86b56862025-04-18 13:04:03 -070070 `;
71
72 constructor() {
73 super();
74 }
75
Sean McCullough86b56862025-04-18 13:04:03 -070076 connectedCallback() {
77 super.connectedCallback();
78 }
79
Sean McCullough86b56862025-04-18 13:04:03 -070080 disconnectedCallback() {
81 super.disconnectedCallback();
82 }
83
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070084 cardForToolCall(toolCall: ToolCall, open: boolean) {
Sean McCullough86b56862025-04-18 13:04:03 -070085 switch (toolCall.name) {
Sean McCullough86b56862025-04-18 13:04:03 -070086 case "bash":
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070087 return html`<sketch-tool-card-bash
88 .open=${open}
89 .toolCall=${toolCall}
90 ></sketch-tool-card-bash>`;
Sean McCullough86b56862025-04-18 13:04:03 -070091 case "codereview":
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070092 return html`<sketch-tool-card-codereview
93 .open=${open}
94 .toolCall=${toolCall}
95 ></sketch-tool-card-codereview>`;
Sean McCullough86b56862025-04-18 13:04:03 -070096 case "done":
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070097 return html`<sketch-tool-card-done
98 .open=${open}
99 .toolCall=${toolCall}
100 ></sketch-tool-card-done>`;
Sean McCullough485afc62025-04-28 14:28:39 -0700101 case "multiplechoice":
102 return html`<sketch-tool-card-multiple-choice
103 .open=${open}
104 .toolCall=${toolCall}
105 ></sketch-tool-card-multiple-choice>`;
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700106 case "patch":
107 return html`<sketch-tool-card-patch
108 .open=${open}
109 .toolCall=${toolCall}
110 ></sketch-tool-card-patch>`;
111 case "think":
112 return html`<sketch-tool-card-think
113 .open=${open}
114 .toolCall=${toolCall}
115 ></sketch-tool-card-think>`;
116 case "title":
117 return html`<sketch-tool-card-title
118 .open=${open}
119 .toolCall=${toolCall}
120 ></sketch-tool-card-title>`;
Josh Bleecher Snydera2a31502025-05-07 12:37:18 +0000121 case "precommit":
122 return html`<sketch-tool-card-precommit
123 .open=${open}
124 .toolCall=${toolCall}
125 ></sketch-tool-card-precommit>`;
Philip Zeyliger80b488d2025-05-10 18:21:54 -0700126 case "browser_take_screenshot":
127 return html`<sketch-tool-card-take-screenshot
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000128 .open=${open}
129 .toolCall=${toolCall}
Philip Zeyliger80b488d2025-05-10 18:21:54 -0700130 ></sketch-tool-card-take-screenshot>`;
Josh Bleecher Snyder31785ae2025-05-06 01:50:58 +0000131 case "knowledge_base":
132 return html`<sketch-tool-card-knowledge-base
133 .open=${open}
134 .toolCall=${toolCall}
135 ></sketch-tool-card-knowledge-base>`;
Sean McCullough86b56862025-04-18 13:04:03 -0700136 }
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700137 return html`<sketch-tool-card-generic
138 .open=${open}
139 .toolCall=${toolCall}
140 ></sketch-tool-card-generic>`;
Sean McCullough86b56862025-04-18 13:04:03 -0700141 }
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700142
Sean McCullough2deac842025-04-21 18:17:57 -0700143 // toolUseKey return value should change, if the toolCall gets a response.
144 toolUseKey(toolCall: ToolCall): string {
Sean McCullough2deac842025-04-21 18:17:57 -0700145 if (!toolCall.result_message) {
146 return toolCall.tool_call_id;
147 }
148 return `${toolCall.tool_call_id}-${toolCall.result_message.idx}`;
149 }
150
Sean McCullough86b56862025-04-18 13:04:03 -0700151 render() {
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000152 if (!this.toolCalls || this.toolCalls.length === 0) {
153 return html``;
154 }
155
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700156 return html`<div class="tool-calls-container">
Sean McCullough86b56862025-04-18 13:04:03 -0700157 <div class="tool-call-cards-container">
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000158 ${repeat(this.toolCalls, this.toolUseKey, (toolCall, idx) => {
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000159 let shouldOpen = false;
160 // Always expand screenshot tool calls, expand last tool call if this.open is true
161 if (
Philip Zeyliger80b488d2025-05-10 18:21:54 -0700162 toolCall.name === "browser_take_screenshot" ||
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000163 (idx == this.toolCalls?.length - 1 && this.open)
164 ) {
165 shouldOpen = true;
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000166 }
167 return html`<div
168 id="${toolCall.tool_call_id}"
169 class="tool-call-card ${toolCall.name}"
170 >
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000171 ${this.cardForToolCall(toolCall, shouldOpen)}
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000172 </div>`;
173 })}
Sean McCullough86b56862025-04-18 13:04:03 -0700174 </div>
175 </div>`;
176 }
177}
178
179declare global {
180 interface HTMLElementTagNameMap {
181 "sketch-tool-calls": SketchToolCalls;
182 }
183}