blob: 8842aee4ced8985d32a3008df634d0ce61c2a97b [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>`;
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000114 case "browser_screenshot":
115 return html`<sketch-tool-card-screenshot
116 .open=${open}
117 .toolCall=${toolCall}
118 ></sketch-tool-card-screenshot>`;
Sean McCullough86b56862025-04-18 13:04:03 -0700119 }
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700120 return html`<sketch-tool-card-generic
121 .open=${open}
122 .toolCall=${toolCall}
123 ></sketch-tool-card-generic>`;
Sean McCullough86b56862025-04-18 13:04:03 -0700124 }
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700125
Sean McCullough2deac842025-04-21 18:17:57 -0700126 // toolUseKey return value should change, if the toolCall gets a response.
127 toolUseKey(toolCall: ToolCall): string {
Sean McCullough2deac842025-04-21 18:17:57 -0700128 if (!toolCall.result_message) {
129 return toolCall.tool_call_id;
130 }
131 return `${toolCall.tool_call_id}-${toolCall.result_message.idx}`;
132 }
133
Sean McCullough86b56862025-04-18 13:04:03 -0700134 render() {
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000135 if (!this.toolCalls || this.toolCalls.length === 0) {
136 return html``;
137 }
138
Sean McCulloughec3ad1a2025-04-18 13:55:16 -0700139 return html`<div class="tool-calls-container">
Sean McCullough86b56862025-04-18 13:04:03 -0700140 <div class="tool-call-cards-container">
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000141 ${repeat(this.toolCalls, this.toolUseKey, (toolCall, idx) => {
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000142 let shouldOpen = false;
143 // Always expand screenshot tool calls, expand last tool call if this.open is true
144 if (
145 toolCall.name === "browser_screenshot" ||
146 (idx == this.toolCalls?.length - 1 && this.open)
147 ) {
148 shouldOpen = true;
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000149 }
150 return html`<div
151 id="${toolCall.tool_call_id}"
152 class="tool-call-card ${toolCall.name}"
153 >
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000154 ${this.cardForToolCall(toolCall, shouldOpen)}
Philip Zeyliger16fa8b42025-05-02 04:28:16 +0000155 </div>`;
156 })}
Sean McCullough86b56862025-04-18 13:04:03 -0700157 </div>
158 </div>`;
159 }
160}
161
162declare global {
163 interface HTMLElementTagNameMap {
164 "sketch-tool-calls": SketchToolCalls;
165 }
166}