webui: add diff display for patches

Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: s2e9bdfb014ddec3ck
diff --git a/llm/conversation/convo.go b/llm/conversation/convo.go
index a52d494..5e20137 100644
--- a/llm/conversation/convo.go
+++ b/llm/conversation/convo.go
@@ -459,15 +459,16 @@
 				c.Listener.OnToolResult(ctx, c, part.ID, part.ToolName, part.ToolInput, content, nil, err)
 				toolResultC <- content
 			}
-			sendRes := func(toolResult []llm.Content) {
+			sendRes := func(toolOut llm.ToolOut) {
 				// Record end time
 				endTime := time.Now()
 				content.ToolUseEndTime = &endTime
 
-				content.ToolResult = toolResult
+				content.ToolResult = toolOut.LLMContent
+				content.Display = toolOut.Display
 				var firstText string
-				if len(toolResult) > 0 {
-					firstText = toolResult[0].Text
+				if len(toolOut.LLMContent) > 0 {
+					firstText = toolOut.LLMContent[0].Text
 				}
 				c.Listener.OnToolResult(ctx, c, part.ID, part.ToolName, part.ToolInput, content, &firstText, nil)
 				toolResultC <- content
@@ -497,7 +498,7 @@
 				sendErr(toolOut.Error)
 				return
 			}
-			sendRes(toolOut.LLMContent)
+			sendRes(toolOut)
 		}()
 	}
 	wg.Wait()
diff --git a/llm/llm.go b/llm/llm.go
index 638a6a3..ffaad3e 100644
--- a/llm/llm.go
+++ b/llm/llm.go
@@ -100,6 +100,10 @@
 	// LLMContent is the output of the tool to be sent back to the LLM.
 	// May be nil on error.
 	LLMContent []Content
+	// Display is content to be displayed to the user.
+	// The type of content is set by the tool and coordinated with the UIs.
+	// It should be JSON-serializable.
+	Display any
 	// Error is the error (if any) that occurred during the tool run.
 	// The text contents of the error will be sent back to the LLM.
 	// If non-nil, LLMContent will be ignored.
@@ -132,6 +136,9 @@
 	ToolUseStartTime *time.Time
 	ToolUseEndTime   *time.Time
 
+	// Display is content to be displayed to the user, copied from ToolOut
+	Display any
+
 	Cache bool
 }