瀏覽代碼

fix panic

Dax Raad 7 月之前
父節點
當前提交
d62746ceb7
共有 1 個文件被更改,包括 115 次插入107 次删除
  1. 115 107
      packages/tui/internal/components/chat/message.go

+ 115 - 107
packages/tui/internal/components/chat/message.go

@@ -337,124 +337,132 @@ func renderToolDetails(
 		borderColor = t.BorderActive()
 	}
 
-	metadata := toolCall.State.Metadata.(map[string]any)
-	switch toolCall.Tool {
-	case "read":
-		preview := metadata["preview"]
-		if preview != nil && toolInputMap["filePath"] != nil {
-			filename := toolInputMap["filePath"].(string)
-			body = preview.(string)
-			body = util.RenderFile(filename, body, width, util.WithTruncate(6))
-		}
-	case "edit":
-		if filename, ok := toolInputMap["filePath"].(string); ok {
-			diffField := metadata["diff"]
-			if diffField != nil {
-				patch := diffField.(string)
-				var formattedDiff string
-				formattedDiff, _ = diff.FormatUnifiedDiff(
-					filename,
-					patch,
-					diff.WithWidth(width-2),
-				)
-				body = strings.TrimSpace(formattedDiff)
-				style := styles.NewStyle().
-					Background(backgroundColor).
-					Foreground(t.TextMuted()).
-					Padding(1, 2).
-					Width(width - 4)
-				if highlight {
-					style = style.Foreground(t.Text()).Bold(true)
+	if toolCall.State.Metadata != nil {
+		metadata := toolCall.State.Metadata.(map[string]any)
+		switch toolCall.Tool {
+		case "read":
+			var preview any
+			if metadata != nil {
+				preview = metadata["preview"]
+			}
+			if preview != nil && toolInputMap["filePath"] != nil {
+				filename := toolInputMap["filePath"].(string)
+				body = preview.(string)
+				body = util.RenderFile(filename, body, width, util.WithTruncate(6))
+			}
+		case "edit":
+			if filename, ok := toolInputMap["filePath"].(string); ok {
+				var diffField any
+				if metadata != nil {
+					diffField = metadata["diff"]
 				}
-
-				if diagnostics := renderDiagnostics(metadata, filename); diagnostics != "" {
-					diagnostics = style.Render(diagnostics)
-					body += "\n" + diagnostics
+				if diffField != nil {
+					patch := diffField.(string)
+					var formattedDiff string
+					formattedDiff, _ = diff.FormatUnifiedDiff(
+						filename,
+						patch,
+						diff.WithWidth(width-2),
+					)
+					body = strings.TrimSpace(formattedDiff)
+					style := styles.NewStyle().
+						Background(backgroundColor).
+						Foreground(t.TextMuted()).
+						Padding(1, 2).
+						Width(width - 4)
+					if highlight {
+						style = style.Foreground(t.Text()).Bold(true)
+					}
+
+					if diagnostics := renderDiagnostics(metadata, filename); diagnostics != "" {
+						diagnostics = style.Render(diagnostics)
+						body += "\n" + diagnostics
+					}
+
+					title := renderToolTitle(toolCall, width)
+					title = style.Render(title)
+					content := title + "\n" + body
+					content = renderContentBlock(
+						app,
+						content,
+						highlight,
+						width,
+						WithPadding(0),
+						WithBorderColor(borderColor),
+					)
+					return content
 				}
-
-				title := renderToolTitle(toolCall, width)
-				title = style.Render(title)
-				content := title + "\n" + body
-				content = renderContentBlock(
-					app,
-					content,
-					highlight,
-					width,
-					WithPadding(0),
-					WithBorderColor(borderColor),
-				)
-				return content
 			}
-		}
-	case "write":
-		if filename, ok := toolInputMap["filePath"].(string); ok {
-			if content, ok := toolInputMap["content"].(string); ok {
-				body = util.RenderFile(filename, content, width)
-				if diagnostics := renderDiagnostics(metadata, filename); diagnostics != "" {
-					body += "\n\n" + diagnostics
+		case "write":
+			if filename, ok := toolInputMap["filePath"].(string); ok {
+				if content, ok := toolInputMap["content"].(string); ok {
+					body = util.RenderFile(filename, content, width)
+					if diagnostics := renderDiagnostics(metadata, filename); diagnostics != "" {
+						body += "\n\n" + diagnostics
+					}
 				}
 			}
-		}
-	case "bash":
-		stdout := metadata["stdout"]
-		if stdout != nil {
-			command := toolInputMap["command"].(string)
-			body = fmt.Sprintf("```console\n> %s\n%s```", command, stdout)
-			body = util.ToMarkdown(body, width, backgroundColor)
-		}
-	case "webfetch":
-		if format, ok := toolInputMap["format"].(string); ok && result != nil {
-			body = *result
-			body = util.TruncateHeight(body, 10)
-			if format == "html" || format == "markdown" {
+		case "bash":
+			stdout := metadata["stdout"]
+			if stdout != nil {
+				command := toolInputMap["command"].(string)
+				body = fmt.Sprintf("```console\n> %s\n%s```", command, stdout)
 				body = util.ToMarkdown(body, width, backgroundColor)
 			}
-		}
-	case "todowrite":
-		todos := metadata["todos"]
-		if todos != nil {
-			for _, item := range todos.([]any) {
-				todo := item.(map[string]any)
-				content := todo["content"].(string)
-				switch todo["status"] {
-				case "completed":
-					body += fmt.Sprintf("- [x] %s\n", content)
-				case "cancelled":
-					// strike through cancelled todo
-					body += fmt.Sprintf("- [~] ~~%s~~\n", content)
-				case "in_progress":
-					// highlight in progress todo
-					body += fmt.Sprintf("- [ ] `%s`\n", content)
-				default:
-					body += fmt.Sprintf("- [ ] %s\n", content)
+		case "webfetch":
+			if format, ok := toolInputMap["format"].(string); ok && result != nil {
+				body = *result
+				body = util.TruncateHeight(body, 10)
+				if format == "html" || format == "markdown" {
+					body = util.ToMarkdown(body, width, backgroundColor)
 				}
 			}
-			body = util.ToMarkdown(body, width, backgroundColor)
-		}
-	case "task":
-		summary := metadata["summary"]
-		if summary != nil {
-			toolcalls := summary.([]any)
-			steps := []string{}
-			for _, item := range toolcalls {
-				data, _ := json.Marshal(item)
-				var toolCall opencode.ToolPart
-				_ = json.Unmarshal(data, &toolCall)
-				step := renderToolTitle(toolCall, width)
-				step = "∟ " + step
-				steps = append(steps, step)
+		case "todowrite":
+			todos := metadata["todos"]
+			if todos != nil {
+				for _, item := range todos.([]any) {
+					todo := item.(map[string]any)
+					content := todo["content"].(string)
+					switch todo["status"] {
+					case "completed":
+						body += fmt.Sprintf("- [x] %s\n", content)
+					case "cancelled":
+						// strike through cancelled todo
+						body += fmt.Sprintf("- [~] ~~%s~~\n", content)
+					case "in_progress":
+						// highlight in progress todo
+						body += fmt.Sprintf("- [ ] `%s`\n", content)
+					default:
+						body += fmt.Sprintf("- [ ] %s\n", content)
+					}
+				}
+				body = util.ToMarkdown(body, width, backgroundColor)
 			}
-			body = strings.Join(steps, "\n")
-		}
-		body = styles.NewStyle().Width(width - 6).Render(body)
-	default:
-		if result == nil {
-			empty := ""
-			result = &empty
+		case "task":
+			summary := metadata["summary"]
+			if summary != nil {
+				toolcalls := summary.([]any)
+				steps := []string{}
+				for _, item := range toolcalls {
+					data, _ := json.Marshal(item)
+					var toolCall opencode.ToolPart
+					_ = json.Unmarshal(data, &toolCall)
+					step := renderToolTitle(toolCall, width)
+					step = "∟ " + step
+					steps = append(steps, step)
+				}
+				body = strings.Join(steps, "\n")
+			}
+			body = styles.NewStyle().Width(width - 6).Render(body)
+		default:
+			if result == nil {
+				empty := ""
+				result = &empty
+			}
+			body = *result
+			body = util.TruncateHeight(body, 10)
+			body = styles.NewStyle().Width(width - 6).Render(body)
 		}
-		body = *result
-		body = util.TruncateHeight(body, 10)
-		body = styles.NewStyle().Width(width - 6).Render(body)
 	}
 
 	error := ""