blob: 4b0215b3db7fb7f6686bed9357c2e8039e18c10d [file] [log] [blame]
banksean333aa672025-07-13 19:49:21 +00001import { html } from "lit";
Philip Zeyliger33d282f2025-05-03 04:01:54 +00002import { customElement, property, state } from "lit/decorators.js";
3import { ToolCall } from "../types";
banksean333aa672025-07-13 19:49:21 +00004import { SketchTailwindElement } from "./sketch-tailwind-element";
5import "./sketch-tool-card-base";
Philip Zeyliger33d282f2025-05-03 04:01:54 +00006
Philip Zeyliger80b488d2025-05-10 18:21:54 -07007@customElement("sketch-tool-card-take-screenshot")
banksean333aa672025-07-13 19:49:21 +00008export class SketchToolCardTakeScreenshot extends SketchTailwindElement {
Philip Zeyliger33d282f2025-05-03 04:01:54 +00009 @property()
10 toolCall: ToolCall;
11
12 @property()
13 open: boolean;
14
15 @state()
16 imageLoaded: boolean = false;
17
18 @state()
19 loadError: boolean = false;
20
Philip Zeyliger33d282f2025-05-03 04:01:54 +000021 constructor() {
22 super();
23 }
24
25 connectedCallback() {
26 super.connectedCallback();
27 }
28
29 disconnectedCallback() {
30 super.disconnectedCallback();
31 }
32
33 render() {
34 // Parse the input to get selector
35 let selector = "";
36 try {
37 if (this.toolCall?.input) {
38 const input = JSON.parse(this.toolCall.input);
39 selector = input.selector || "(full page)";
40 }
41 } catch (e) {
42 console.error("Error parsing screenshot input:", e);
43 }
44
Philip Zeyliger542bda32025-06-11 18:31:03 -070045 // Extract the screenshot ID from the result text
Philip Zeyliger33d282f2025-05-03 04:01:54 +000046 let screenshotId = "";
47 let hasResult = false;
48 if (this.toolCall?.result_message?.tool_result) {
Philip Zeyliger542bda32025-06-11 18:31:03 -070049 // The tool result is now a text like "Screenshot taken (saved as /tmp/sketch-screenshots/{id}.png)"
50 // Extract the ID from this text
51 const resultText = this.toolCall.result_message.tool_result;
52 const pathMatch = resultText.match(
53 /\/tmp\/sketch-screenshots\/(.*?)\.png/,
54 );
55 if (pathMatch) {
56 screenshotId = pathMatch[1];
Philip Zeyliger33d282f2025-05-03 04:01:54 +000057 hasResult = true;
Philip Zeyliger33d282f2025-05-03 04:01:54 +000058 }
59 }
60
61 // Construct the URL for the screenshot (using relative URL without leading slash)
62 const screenshotUrl = screenshotId ? `screenshot/${screenshotId}` : "";
63
banksean333aa672025-07-13 19:49:21 +000064 const summaryContent = html`<span class="italic p-2">
65 Screenshot of ${selector}
66 </span>`;
67 const inputContent = html`<div
banksean1ee0bc62025-07-22 23:24:18 +000068 class="px-2 py-1 bg-gray-100 dark:bg-gray-700 rounded font-mono my-1.5 inline-block"
banksean333aa672025-07-13 19:49:21 +000069 >
70 ${selector !== "(full page)"
71 ? `Taking screenshot of element: ${selector}`
72 : `Taking full page screenshot`}
73 </div>`;
74 const resultContent = hasResult
75 ? html`
76 <div class="my-2.5 flex flex-col items-center">
77 ${!this.imageLoaded && !this.loadError
banksean1ee0bc62025-07-22 23:24:18 +000078 ? html`<div class="m-5 text-gray-600 dark:text-gray-400 italic">
banksean333aa672025-07-13 19:49:21 +000079 Loading screenshot...
80 </div>`
81 : ""}
82 ${this.loadError
banksean1ee0bc62025-07-22 23:24:18 +000083 ? html`<div class="text-red-700 dark:text-red-400 italic my-2.5">
banksean333aa672025-07-13 19:49:21 +000084 Failed to load screenshot
85 </div>`
86 : html`
87 <img
banksean1ee0bc62025-07-22 23:24:18 +000088 class="max-w-full max-h-[500px] rounded shadow-md border border-gray-300 dark:border-gray-600"
banksean333aa672025-07-13 19:49:21 +000089 src="${screenshotUrl}"
90 @load=${() => (this.imageLoaded = true)}
91 @error=${() => (this.loadError = true)}
92 ?hidden=${!this.imageLoaded}
93 />
94 ${this.imageLoaded
banksean1ee0bc62025-07-22 23:24:18 +000095 ? html`<div
96 class="mt-2 text-xs text-gray-600 dark:text-gray-400"
97 >
banksean333aa672025-07-13 19:49:21 +000098 Screenshot saved and displayed
Autoformatter4962f152025-05-06 17:24:20 +000099 </div>`
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000100 : ""}
banksean333aa672025-07-13 19:49:21 +0000101 `}
102 </div>
103 `
104 : "";
105
106 return html`
107 <sketch-tool-card-base
108 .open=${this.open}
109 .toolCall=${this.toolCall}
110 .summaryContent=${summaryContent}
111 .inputContent=${inputContent}
112 .resultContent=${resultContent}
113 >
114 </sketch-tool-card-base>
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000115 `;
116 }
117}
118
119declare global {
120 interface HTMLElementTagNameMap {
Philip Zeyliger80b488d2025-05-10 18:21:54 -0700121 "sketch-tool-card-take-screenshot": SketchToolCardTakeScreenshot;
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000122 }
123}