blob: ae63de0ba4ea35f74a0a7194c16d22798e30969b [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 Zeyliger33d282f2025-05-03 04:01:54 +00006import "./sketch-tool-card-screenshot";
Sean McCullough86b56862025-04-18 13:04:03 -07007
8@customElement("sketch-tool-calls")
9export class SketchToolCalls extends LitElement {
10 @property()
11 toolCalls: ToolCall[] = [];
12
Sean McCullough2deac842025-04-21 18:17:57 -070013 @property()
14 open: boolean = false;
15
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000016 @state()
17 expanded: boolean = false;
18
Sean McCullough86b56862025-04-18 13:04:03 -070019 static styles = css`
20 /* Tool calls container styles */
21 .tool-calls-container {
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000022 margin-top: 8px;
23 padding-top: 4px;
Sean McCullough86b56862025-04-18 13:04:03 -070024 }
25
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070026 /* Card container */
Sean McCullough86b56862025-04-18 13:04:03 -070027 .tool-call-card {
28 display: flex;
29 flex-direction: column;
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000030 background-color: rgba(255, 255, 255, 0.6);
31 border-radius: 6px;
32 margin-bottom: 6px;
Sean McCullough86b56862025-04-18 13:04:03 -070033 overflow: hidden;
34 cursor: pointer;
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000035 border-left: 2px solid rgba(0, 0, 0, 0.1);
36 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
Sean McCullough86b56862025-04-18 13:04:03 -070037 }
38
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070039 /* Status indicators for tool calls */
Sean McCullough86b56862025-04-18 13:04:03 -070040 .tool-call-status {
41 margin-right: 4px;
42 text-align: center;
43 }
44
45 .tool-call-status.spinner {
46 animation: spin 1s infinite linear;
47 display: inline-block;
48 width: 1em;
49 }
50
Sean McCullough86b56862025-04-18 13:04:03 -070051 @keyframes spin {
52 0% {
53 transform: rotate(0deg);
54 }
55 100% {
56 transform: rotate(360deg);
57 }
58 }
Philip Zeyliger16fa8b42025-05-02 04:28:16 +000059
60 .tool-call-cards-container {
61 display: block;
62 }
Sean McCullough86b56862025-04-18 13:04:03 -070063 `;
64
65 constructor() {
66 super();
67 }
68
Sean McCullough86b56862025-04-18 13:04:03 -070069 connectedCallback() {
70 super.connectedCallback();
71 }
72
Sean McCullough86b56862025-04-18 13:04:03 -070073 disconnectedCallback() {
74 super.disconnectedCallback();
75 }
76
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070077 cardForToolCall(toolCall: ToolCall, open: boolean) {
Sean McCullough86b56862025-04-18 13:04:03 -070078 switch (toolCall.name) {
Sean McCullough86b56862025-04-18 13:04:03 -070079 case "bash":
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070080 return html`<sketch-tool-card-bash
81 .open=${open}
82 .toolCall=${toolCall}
83 ></sketch-tool-card-bash>`;
Sean McCullough86b56862025-04-18 13:04:03 -070084 case "codereview":
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070085 return html`<sketch-tool-card-codereview
86 .open=${open}
87 .toolCall=${toolCall}
88 ></sketch-tool-card-codereview>`;
Sean McCullough86b56862025-04-18 13:04:03 -070089 case "done":
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070090 return html`<sketch-tool-card-done
91 .open=${open}
92 .toolCall=${toolCall}
93 ></sketch-tool-card-done>`;
Sean McCullough485afc62025-04-28 14:28:39 -070094 case "multiplechoice":
95 return html`<sketch-tool-card-multiple-choice
96 .open=${open}
97 .toolCall=${toolCall}
98 ></sketch-tool-card-multiple-choice>`;
Sean McCulloughec3ad1a2025-04-18 13:55:16 -070099 case "patch":
100 return html`<sketch-tool-card-patch
101 .open=${open}
102 .toolCall=${toolCall}
103 ></sketch-tool-card-patch>`;
104 case "think":
105 return html`<sketch-tool-card-think
106 .open=${open}
107 .toolCall=${toolCall}
108 ></sketch-tool-card-think>`;
109 case "title":
110 return html`<sketch-tool-card-title
111 .open=${open}
112 .toolCall=${toolCall}
113 ></sketch-tool-card-title>`;
Josh Bleecher Snydera2a31502025-05-07 12:37:18 +0000114 case "precommit":
115 return html`<sketch-tool-card-precommit
116 .open=${open}
117 .toolCall=${toolCall}
118 ></sketch-tool-card-precommit>`;
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000119 case "browser_screenshot":
120 return html`<sketch-tool-card-screenshot
121 .open=${open}
122 .toolCall=${toolCall}
123 ></sketch-tool-card-screenshot>`;
Sean McCullough86b56862025-04-18 13:04:03 -0700124 }
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700125 return html`<sketch-tool-card-generic
126 .open=${open}
127 .toolCall=${toolCall}
128 ></sketch-tool-card-generic>`;
Sean McCullough86b56862025-04-18 13:04:03 -0700129 }
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700130
Sean McCullough2deac842025-04-21 18:17:57 -0700131 // toolUseKey return value should change, if the toolCall gets a response.
132 toolUseKey(toolCall: ToolCall): string {
Sean McCullough2deac842025-04-21 18:17:57 -0700133 if (!toolCall.result_message) {
134 return toolCall.tool_call_id;
135 }
136 return `${toolCall.tool_call_id}-${toolCall.result_message.idx}`;
137 }
138
Sean McCullough86b56862025-04-18 13:04:03 -0700139 render() {
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000140 if (!this.toolCalls || this.toolCalls.length === 0) {
141 return html``;
142 }
143
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700144 return html`<div class="tool-calls-container">
Sean McCullough86b56862025-04-18 13:04:03 -0700145 <div class="tool-call-cards-container">
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000146 ${repeat(this.toolCalls, this.toolUseKey, (toolCall, idx) => {
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000147 let shouldOpen = false;
148 // Always expand screenshot tool calls, expand last tool call if this.open is true
149 if (
150 toolCall.name === "browser_screenshot" ||
151 (idx == this.toolCalls?.length - 1 && this.open)
152 ) {
153 shouldOpen = true;
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000154 }
155 return html`<div
156 id="${toolCall.tool_call_id}"
157 class="tool-call-card ${toolCall.name}"
158 >
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000159 ${this.cardForToolCall(toolCall, shouldOpen)}
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000160 </div>`;
161 })}
Sean McCullough86b56862025-04-18 13:04:03 -0700162 </div>
163 </div>`;
164 }
165}
166
167declare global {
168 interface HTMLElementTagNameMap {
169 "sketch-tool-calls": SketchToolCalls;
170 }
171}