diff options
| author | Kujtim Hoxha <[email protected]> | 2025-04-03 15:20:15 +0200 |
|---|---|---|
| committer | Kujtim Hoxha <[email protected]> | 2025-04-03 17:23:41 +0200 |
| commit | cfdd687216799cb5b47f099f1e7cd5dd16b3bdd0 (patch) | |
| tree | a822bfde1463a7080c0ea06dd17796d7a1617d3d /internal/tui | |
| parent | afd9ad0560d76c2a6d161dad52553b10ff428905 (diff) | |
| download | opencode-cfdd687216799cb5b47f099f1e7cd5dd16b3bdd0.tar.gz opencode-cfdd687216799cb5b47f099f1e7cd5dd16b3bdd0.zip | |
add initial lsp support
Diffstat (limited to 'internal/tui')
| -rw-r--r-- | internal/tui/components/repl/messages.go | 85 | ||||
| -rw-r--r-- | internal/tui/components/repl/sessions.go | 1 | ||||
| -rw-r--r-- | internal/tui/styles/icons.go | 9 |
3 files changed, 76 insertions, 19 deletions
diff --git a/internal/tui/components/repl/messages.go b/internal/tui/components/repl/messages.go index 7956867ce..2b5e599aa 100644 --- a/internal/tui/components/repl/messages.go +++ b/internal/tui/components/repl/messages.go @@ -5,6 +5,7 @@ import ( "fmt" "sort" "strings" + "time" "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/viewport" @@ -13,6 +14,7 @@ import ( "github.com/charmbracelet/lipgloss" "github.com/kujtimiihoxha/termai/internal/app" "github.com/kujtimiihoxha/termai/internal/llm/agent" + "github.com/kujtimiihoxha/termai/internal/lsp/protocol" "github.com/kujtimiihoxha/termai/internal/message" "github.com/kujtimiihoxha/termai/internal/pubsub" "github.com/kujtimiihoxha/termai/internal/session" @@ -39,6 +41,7 @@ type messagesCmp struct { height int focused bool cachedView string + timeLoaded time.Time } func (m *messagesCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { @@ -51,7 +54,8 @@ func (m *messagesCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.viewport.GotoBottom() } for _, v := range m.messages { - for _, c := range v.ToolCalls { + for _, c := range v.ToolCalls() { + // the message is being added to the session of a tool called if c.ID == msg.Payload.SessionID { m.renderView() m.viewport.GotoBottom() @@ -130,12 +134,11 @@ func hasUnfinishedMessages(messages []message.Message) bool { return false } for _, msg := range messages { - if !msg.Finished { + if !msg.IsFinished() { return true } } - lastMessage := messages[len(messages)-1] - return lastMessage.Role != message.Assistant + return false } func (m *messagesCmp) renderMessageWithToolCall(content string, tools []message.ToolCall, futureMessages []message.Message) string { @@ -205,7 +208,7 @@ func (m *messagesCmp) renderMessageWithToolCall(content string, tools []message. findToolResult := func(toolCallID string, messages []message.Message) *message.ToolResult { for _, msg := range messages { if msg.Role == message.Tool { - for _, result := range msg.ToolResults { + for _, result := range msg.ToolResults() { if result.ToolCallID == toolCallID { return &result } @@ -257,7 +260,7 @@ func (m *messagesCmp) renderMessageWithToolCall(content string, tools []message. taskSessionMessages, _ := m.app.Messages.List(toolCall.ID) for _, msg := range taskSessionMessages { if msg.Role == message.Assistant { - for _, toolCall := range msg.ToolCalls { + for _, toolCall := range msg.ToolCalls() { toolHeader := lipgloss.NewStyle(). Bold(true). Foreground(styles.Blue). @@ -304,11 +307,11 @@ func (m *messagesCmp) renderMessageWithToolCall(content string, tools []message. } for _, msg := range futureMessages { - if msg.Content != "" { + if msg.Content().String() != "" { break } - for _, toolCall := range msg.ToolCalls { + for _, toolCall := range msg.ToolCalls() { toolOutput := renderTool(toolCall) allParts = append(allParts, " "+strings.ReplaceAll(toolOutput, "\n", "\n ")) @@ -339,10 +342,10 @@ func (m *messagesCmp) renderView() { prevMessageWasUser := false for inx, msg := range m.messages { - content := msg.Content + content := msg.Content().String() if content != "" || prevMessageWasUser { - if msg.Thinking != "" && content == "" { - content = msg.Thinking + if msg.ReasoningContent().String() != "" && content == "" { + content = msg.ReasoningContent().String() } else if content == "" { content = "..." } @@ -367,14 +370,14 @@ func (m *messagesCmp) renderView() { EmbeddedText: borderText(msg.Role, currentMessage), }, ) - if len(msg.ToolCalls) > 0 { - content = m.renderMessageWithToolCall(content, msg.ToolCalls, m.messages[inx+1:]) + if len(msg.ToolCalls()) > 0 { + content = m.renderMessageWithToolCall(content, msg.ToolCalls(), m.messages[inx+1:]) } stringMessages = append(stringMessages, content) currentMessage++ displayedMsgCount++ } - if msg.Role == message.User && msg.Content != "" { + if msg.Role == message.User && msg.Content().String() != "" { prevMessageWasUser = true } else { prevMessageWasUser = false @@ -398,6 +401,57 @@ func (m *messagesCmp) Blur() tea.Cmd { return nil } +func (m *messagesCmp) projectDiagnostics() string { + errorDiagnostics := []protocol.Diagnostic{} + warnDiagnostics := []protocol.Diagnostic{} + hintDiagnostics := []protocol.Diagnostic{} + infoDiagnostics := []protocol.Diagnostic{} + for _, client := range m.app.LSPClients { + for _, d := range client.GetDiagnostics() { + for _, diag := range d { + switch diag.Severity { + case protocol.SeverityError: + errorDiagnostics = append(errorDiagnostics, diag) + case protocol.SeverityWarning: + warnDiagnostics = append(warnDiagnostics, diag) + case protocol.SeverityHint: + hintDiagnostics = append(hintDiagnostics, diag) + case protocol.SeverityInformation: + infoDiagnostics = append(infoDiagnostics, diag) + } + } + } + } + + if len(errorDiagnostics) == 0 && len(warnDiagnostics) == 0 && len(hintDiagnostics) == 0 && len(infoDiagnostics) == 0 { + if time.Since(m.timeLoaded) < time.Second*10 { + return "Loading diagnostics..." + } + return "No diagnostics" + } + + diagnostics := []string{} + + if len(errorDiagnostics) > 0 { + errStr := lipgloss.NewStyle().Foreground(styles.Error).Render(fmt.Sprintf("%s %d", styles.ErrorIcon, len(errorDiagnostics))) + diagnostics = append(diagnostics, errStr) + } + if len(warnDiagnostics) > 0 { + warnStr := lipgloss.NewStyle().Foreground(styles.Warning).Render(fmt.Sprintf("%s %d", styles.WarningIcon, len(warnDiagnostics))) + diagnostics = append(diagnostics, warnStr) + } + if len(hintDiagnostics) > 0 { + hintStr := lipgloss.NewStyle().Foreground(styles.Text).Render(fmt.Sprintf("%s %d", styles.HintIcon, len(hintDiagnostics))) + diagnostics = append(diagnostics, hintStr) + } + if len(infoDiagnostics) > 0 { + infoStr := lipgloss.NewStyle().Foreground(styles.Peach).Render(fmt.Sprintf("%s %d", styles.InfoIcon, len(infoDiagnostics))) + diagnostics = append(diagnostics, infoStr) + } + + return strings.Join(diagnostics, " ") +} + func (m *messagesCmp) BorderText() map[layout.BorderPosition]string { title := m.session.Title titleWidth := m.width / 2 @@ -409,7 +463,7 @@ func (m *messagesCmp) BorderText() map[layout.BorderPosition]string { } borderTest := map[layout.BorderPosition]string{ layout.TopLeftBorder: title, - layout.BottomRightBorder: formatTokensAndCost(m.session.CompletionTokens+m.session.PromptTokens, m.session.Cost), + layout.BottomRightBorder: m.projectDiagnostics(), } if hasUnfinishedMessages(m.messages) { borderTest[layout.BottomLeftBorder] = lipgloss.NewStyle().Foreground(styles.Peach).Render("Thinking...") @@ -442,6 +496,7 @@ func (m *messagesCmp) SetSize(width int, height int) { } func (m *messagesCmp) Init() tea.Cmd { + m.timeLoaded = time.Now() return nil } diff --git a/internal/tui/components/repl/sessions.go b/internal/tui/components/repl/sessions.go index a1302baae..093337b18 100644 --- a/internal/tui/components/repl/sessions.go +++ b/internal/tui/components/repl/sessions.go @@ -245,4 +245,3 @@ func NewSessionsCmp(app *app.App) SessionsCmp { focused: false, } } - diff --git a/internal/tui/styles/icons.go b/internal/tui/styles/icons.go index d3dcc0c56..f641984e7 100644 --- a/internal/tui/styles/icons.go +++ b/internal/tui/styles/icons.go @@ -9,8 +9,11 @@ const ( UserIcon string = "" CheckIcon string = "✓" - ErrorIcon string = "✗" + ErrorIcon string = "" + WarningIcon string = "" + InfoIcon string = "" + HintIcon string = "" SpinnerIcon string = "..." - - SleepIcon string = "" + BugIcon string = "" + SleepIcon string = "" ) |
