summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authoradamdottv <[email protected]>2025-06-26 12:47:17 -0500
committeradamdottv <[email protected]>2025-06-26 12:47:17 -0500
commit5358d43b74a908de866dd0123caf80b9a7d09fee (patch)
tree62f1ef2a84cd5bb9a5fe139a518cbc82b6fb81d2
parentf777347bac6e610b8b5cf2428131fb40aee254df (diff)
downloadopencode-5358d43b74a908de866dd0123caf80b9a7d09fee.tar.gz
opencode-5358d43b74a908de866dd0123caf80b9a7d09fee.zip
feat(tui): show lsp diagnostics for edit and write tools
-rw-r--r--packages/tui/internal/components/chat/message.go88
1 files changed, 88 insertions, 0 deletions
diff --git a/packages/tui/internal/components/chat/message.go b/packages/tui/internal/components/chat/message.go
index 4f0293de5..f547907ee 100644
--- a/packages/tui/internal/components/chat/message.go
+++ b/packages/tui/internal/components/chat/message.go
@@ -397,6 +397,11 @@ func renderToolInvocation(
body,
styles.WhitespaceStyle(t.Background()),
)
+
+ // Add diagnostics at the bottom if they exist
+ if diagnostics := renderDiagnostics(metadata, filename); diagnostics != "" {
+ body += "\n" + renderContentBlock(diagnostics, WithFullWidth(), WithBorderColor(t.Error()))
+ }
}
}
case "write":
@@ -404,6 +409,11 @@ func renderToolInvocation(
title = fmt.Sprintf("WRITE %s", relative(filename))
if content, ok := toolArgsMap["content"].(string); ok {
body = renderFile(filename, content)
+
+ // Add diagnostics at the bottom if they exist
+ if diagnostics := renderDiagnostics(metadata, filename); diagnostics != "" {
+ body += "\n" + renderContentBlock(diagnostics, WithFullWidth(), WithBorderColor(t.Error()))
+ }
}
}
case "bash":
@@ -685,3 +695,81 @@ func extension(path string) string {
}
return ext
}
+
+// Diagnostic represents an LSP diagnostic
+type Diagnostic struct {
+ Range struct {
+ Start struct {
+ Line int `json:"line"`
+ Character int `json:"character"`
+ } `json:"start"`
+ } `json:"range"`
+ Severity int `json:"severity"`
+ Message string `json:"message"`
+}
+
+// renderDiagnostics formats LSP diagnostics for display in the TUI
+func renderDiagnostics(metadata client.MessageMetadata_Tool_AdditionalProperties, filePath string) string {
+ diagnosticsData, ok := metadata.Get("diagnostics")
+ if !ok {
+ return ""
+ }
+
+ // diagnosticsData should be a map[string][]Diagnostic
+ diagnosticsMap, ok := diagnosticsData.(map[string]interface{})
+ if !ok {
+ return ""
+ }
+
+ fileDiagnostics, ok := diagnosticsMap[filePath]
+ if !ok {
+ return ""
+ }
+
+ diagnosticsList, ok := fileDiagnostics.([]interface{})
+ if !ok {
+ return ""
+ }
+
+ var errorDiagnostics []string
+ for _, diagInterface := range diagnosticsList {
+ diagMap, ok := diagInterface.(map[string]interface{})
+ if !ok {
+ continue
+ }
+
+ // Parse the diagnostic
+ var diag Diagnostic
+ diagBytes, err := json.Marshal(diagMap)
+ if err != nil {
+ continue
+ }
+ if err := json.Unmarshal(diagBytes, &diag); err != nil {
+ continue
+ }
+
+ // Only show error diagnostics (severity === 1)
+ if diag.Severity != 1 {
+ continue
+ }
+
+ line := diag.Range.Start.Line + 1 // 1-based
+ column := diag.Range.Start.Character + 1 // 1-based
+ errorDiagnostics = append(errorDiagnostics, fmt.Sprintf("Error [%d:%d] %s", line, column, diag.Message))
+ }
+
+ if len(errorDiagnostics) == 0 {
+ return ""
+ }
+
+ t := theme.CurrentTheme()
+ var result strings.Builder
+ for _, diagnostic := range errorDiagnostics {
+ if result.Len() > 0 {
+ result.WriteString("\n")
+ }
+ result.WriteString(styles.NewStyle().Foreground(t.Error()).Render(diagnostic))
+ }
+
+ return result.String()
+}