webui: add diff display for patches
Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: s2e9bdfb014ddec3ck
diff --git a/webui/src/web-components/demo/sketch-tool-card.demo.ts b/webui/src/web-components/demo/sketch-tool-card.demo.ts
index 6b499f1..625e555 100644
--- a/webui/src/web-components/demo/sketch-tool-card.demo.ts
+++ b/webui/src/web-components/demo/sketch-tool-card.demo.ts
@@ -142,6 +142,8 @@
result_message: {
type: "tool",
tool_result: "- Applied all patches\n",
+ display:
+ "@@ -1,3 +1,3 @@\n # Web Components\n \n-This directory contains the old components.\n+This directory contains custom web components...",
tool_call_id: "toolu_01TNhLX2AWkZwsu2KCLKrpju",
},
},
diff --git a/webui/src/web-components/sketch-tool-card-base.ts b/webui/src/web-components/sketch-tool-card-base.ts
index 8dcc887..9018275 100644
--- a/webui/src/web-components/sketch-tool-card-base.ts
+++ b/webui/src/web-components/sketch-tool-card-base.ts
@@ -118,7 +118,9 @@
? html`<div class="mb-2">${this.inputContent}</div>`
: ""}
${this.resultContent
- ? html`<div class="mt-2">${this.resultContent}</div>`
+ ? html`<div class="${this.inputContent ? "mt-2" : ""}">
+ ${this.resultContent}
+ </div>`
: ""}
</div>
</div>
diff --git a/webui/src/web-components/sketch-tool-card.ts b/webui/src/web-components/sketch-tool-card.ts
index 8016fbc..9c1ae62 100644
--- a/webui/src/web-components/sketch-tool-card.ts
+++ b/webui/src/web-components/sketch-tool-card.ts
@@ -1,7 +1,7 @@
import { html } from "lit";
import { unsafeHTML } from "lit/directives/unsafe-html.js";
import { customElement, property } from "lit/decorators.js";
-import { ToolCall, State } from "../types";
+import { State, ToolCall } from "../types";
import { marked } from "marked";
import DOMPurify from "dompurify";
import { SketchTailwindElement } from "./sketch-tailwind-element";
@@ -199,6 +199,37 @@
@property() toolCall: ToolCall;
@property() open: boolean;
+ // Render a diff with syntax highlighting
+ renderDiff(diff: string) {
+ // Remove ---/+++ header lines and trim leading/trailing blank lines
+ const lines = diff
+ .split("\n")
+ .filter((line) => !line.startsWith("---") && !line.startsWith("+++"))
+ .join("\n")
+ .trim()
+ .split("\n");
+
+ const coloredLines = lines.map((line) => {
+ if (line.startsWith("+")) {
+ return html`<div class="text-green-600 bg-green-50">${line}</div>`;
+ } else if (line.startsWith("-")) {
+ return html`<div class="text-red-600 bg-red-50">${line}</div>`;
+ } else if (line.startsWith("@@")) {
+ // prettier-ignore
+ return html`<div class="text-cyan-600 bg-cyan-50 font-semibold">${line}</div>`;
+ } else {
+ return html`<div class="text-gray-800">${line}</div>`;
+ }
+ });
+
+ return html`<pre
+ class="bg-gray-100 text-xs p-2 rounded whitespace-pre-wrap break-words max-w-full w-full box-border overflow-x-auto font-mono"
+ >
+ ${coloredLines}
+ </pre
+ >`;
+ }
+
render() {
const patchInput = JSON.parse(this.toolCall?.input);
@@ -209,18 +240,25 @@
edit${patchInput.patches.length > 1 ? "s" : ""}
</span>`;
- const inputContent = html`<div>
- ${patchInput.patches.map((patch) => {
- return html`<div class="mb-2">
- Patch operation: <b>${patch.operation}</b>
- ${createPreElement(patch.newText)}
- </div>`;
- })}
- </div>`;
+ const inputContent = html``;
- const resultContent = this.toolCall?.result_message?.tool_result
- ? createPreElement(this.toolCall.result_message.tool_result)
- : "";
+ // Show diff if available, otherwise show the regular result
+ let resultContent;
+ if (
+ this.toolCall?.result_message?.display &&
+ typeof this.toolCall.result_message.display === "string"
+ ) {
+ // Render the diff with syntax highlighting
+ resultContent = html`<div class="w-full relative">
+ ${this.renderDiff(this.toolCall.result_message.display)}
+ </div>`;
+ } else if (this.toolCall?.result_message?.tool_result) {
+ resultContent = createPreElement(
+ this.toolCall.result_message.tool_result,
+ );
+ } else {
+ resultContent = "";
+ }
return html`<sketch-tool-card-base
.open=${this.open}