mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-26 12:14:20 +01:00
wip: refactoring tui
This commit is contained in:
@@ -23,7 +23,6 @@ import (
|
||||
type App struct {
|
||||
Client *client.ClientWithResponses
|
||||
Events *client.Client
|
||||
State map[string]any
|
||||
Session *client.SessionInfo
|
||||
Messages []client.MessageInfo
|
||||
|
||||
@@ -76,7 +75,6 @@ func New(ctx context.Context) (*App, error) {
|
||||
agentBridge := NewAgentServiceBridge(httpClient)
|
||||
|
||||
app := &App{
|
||||
State: make(map[string]any),
|
||||
Client: httpClient,
|
||||
Events: eventClient,
|
||||
Session: &client.SessionInfo{},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package chat
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
@@ -93,63 +94,9 @@ func (m *messagesCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
case renderFinishedMsg:
|
||||
m.rendering = false
|
||||
m.viewport.GotoBottom()
|
||||
|
||||
case state.StateUpdatedMsg:
|
||||
m.renderView()
|
||||
m.viewport.GotoBottom()
|
||||
|
||||
// case pubsub.Event[message.Message]:
|
||||
// needsRerender := false
|
||||
// if msg.Type == message.EventMessageCreated {
|
||||
// if msg.Payload.SessionID == m.app.CurrentSessionOLD.ID {
|
||||
// messageExists := false
|
||||
// for _, v := range m.messages {
|
||||
// if v.ID == msg.Payload.ID {
|
||||
// messageExists = true
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if !messageExists {
|
||||
// if len(m.messages) > 0 {
|
||||
// lastMsgID := m.messages[len(m.messages)-1].ID
|
||||
// delete(m.cachedContent, lastMsgID)
|
||||
// }
|
||||
//
|
||||
// m.messages = append(m.messages, msg.Payload)
|
||||
// delete(m.cachedContent, m.currentMsgID)
|
||||
// m.currentMsgID = msg.Payload.ID
|
||||
// needsRerender = true
|
||||
// }
|
||||
// }
|
||||
// // There are tool calls from the child task
|
||||
// for _, v := range m.messages {
|
||||
// for _, c := range v.ToolCalls() {
|
||||
// if c.ID == msg.Payload.SessionID {
|
||||
// delete(m.cachedContent, v.ID)
|
||||
// needsRerender = true
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } else if msg.Type == message.EventMessageUpdated && msg.Payload.SessionID == m.app.CurrentSessionOLD.ID {
|
||||
// for i, v := range m.messages {
|
||||
// if v.ID == msg.Payload.ID {
|
||||
// m.messages[i] = msg.Payload
|
||||
// delete(m.cachedContent, msg.Payload.ID)
|
||||
// needsRerender = true
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if needsRerender {
|
||||
// m.renderView()
|
||||
// if len(m.messages) > 0 {
|
||||
// if (msg.Type == message.EventMessageCreated) ||
|
||||
// (msg.Type == message.EventMessageUpdated && msg.Payload.ID == m.messages[len(m.messages)-1].ID) {
|
||||
// m.viewport.GotoBottom()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
spinner, cmd := m.spinner.Update(msg)
|
||||
@@ -190,7 +137,6 @@ func (m *messagesCmp) renderView() {
|
||||
m.viewport.SetContent(
|
||||
styles.ForceReplaceBackgroundWithLipgloss(
|
||||
styles.BaseStyle().
|
||||
Width(m.width).
|
||||
Render(
|
||||
lipgloss.JoinVertical(
|
||||
lipgloss.Top,
|
||||
@@ -212,11 +158,12 @@ func (m *messagesCmp) View() string {
|
||||
lipgloss.JoinVertical(
|
||||
lipgloss.Top,
|
||||
"Loading...",
|
||||
// m.working(),
|
||||
m.working(),
|
||||
m.help(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
if len(m.app.Messages) == 0 {
|
||||
content := baseStyle.
|
||||
Width(m.width).
|
||||
@@ -243,7 +190,7 @@ func (m *messagesCmp) View() string {
|
||||
lipgloss.JoinVertical(
|
||||
lipgloss.Top,
|
||||
m.viewport.View(),
|
||||
// m.working(),
|
||||
m.working(),
|
||||
m.help(),
|
||||
),
|
||||
)
|
||||
@@ -285,31 +232,31 @@ func hasUnfinishedToolCalls(messages []message.Message) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// func (m *messagesCmp) working() string {
|
||||
// text := ""
|
||||
// if m.IsAgentWorking() && len(m.app.Messages) > 0 {
|
||||
// t := theme.CurrentTheme()
|
||||
// baseStyle := styles.BaseStyle()
|
||||
//
|
||||
// task := "Thinking..."
|
||||
// lastMessage := m.app.Messages[len(m.app.Messages)-1]
|
||||
// if hasToolsWithoutResponse(m.app.Messages) {
|
||||
// task = "Waiting for tool response..."
|
||||
// } else if hasUnfinishedToolCalls(m.app.Messages) {
|
||||
// task = "Building tool call..."
|
||||
// } else if !lastMessage.IsFinished() {
|
||||
// task = "Generating..."
|
||||
// }
|
||||
// if task != "" {
|
||||
// text += baseStyle.
|
||||
// Width(m.width).
|
||||
// Foreground(t.Primary()).
|
||||
// Bold(true).
|
||||
// Render(fmt.Sprintf("%s %s ", m.spinner.View(), task))
|
||||
// }
|
||||
// }
|
||||
// return text
|
||||
// }
|
||||
func (m *messagesCmp) working() string {
|
||||
text := ""
|
||||
if len(m.app.Messages) > 0 {
|
||||
t := theme.CurrentTheme()
|
||||
baseStyle := styles.BaseStyle()
|
||||
|
||||
task := "Working..."
|
||||
// lastMessage := m.app.Messages[len(m.app.Messages)-1]
|
||||
// if hasToolsWithoutResponse(m.app.Messages) {
|
||||
// task = "Waiting for tool response..."
|
||||
// } else if hasUnfinishedToolCalls(m.app.Messages) {
|
||||
// task = "Building tool call..."
|
||||
// } else if !lastMessage.IsFinished() {
|
||||
// task = "Generating..."
|
||||
// }
|
||||
if task != "" {
|
||||
text += baseStyle.
|
||||
Width(m.width).
|
||||
Foreground(t.Primary()).
|
||||
Bold(true).
|
||||
Render(fmt.Sprintf("%s %s ", m.spinner.View(), task))
|
||||
}
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
func (m *messagesCmp) help() string {
|
||||
t := theme.CurrentTheme()
|
||||
|
||||
@@ -86,7 +86,7 @@ func (m *sidebarCmp) sessionSection() string {
|
||||
|
||||
sessionValue := baseStyle.
|
||||
Foreground(t.Text()).
|
||||
Render(fmt.Sprintf(": %s", m.app.CurrentSessionOLD.Title))
|
||||
Render(fmt.Sprintf(": %s", m.app.Session.Title))
|
||||
|
||||
return sessionKey + sessionValue
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package tui
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
@@ -267,85 +266,27 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
case client.EventStorageWrite:
|
||||
parts := strings.Split(msg.Key, "/")
|
||||
if len(parts) < 3 {
|
||||
return a, nil
|
||||
}
|
||||
|
||||
if parts[0] == "session" && parts[1] == "info" {
|
||||
sessionId := parts[2]
|
||||
if sessionId == a.app.Session.Id {
|
||||
var sessionInfo client.SessionInfo
|
||||
bytes, _ := json.Marshal(msg.Content)
|
||||
if err := json.Unmarshal(bytes, &sessionInfo); err != nil {
|
||||
status.Error(err.Error())
|
||||
return a, nil
|
||||
case client.EventMessageUpdated:
|
||||
if msg.Properties.Info.Metadata.SessionID == a.app.Session.Id {
|
||||
for i, m := range a.app.Messages {
|
||||
if m.Id == msg.Properties.Info.Id {
|
||||
a.app.Messages[i] = msg.Properties.Info
|
||||
slog.Debug("Updated message", "message", msg.Properties.Info)
|
||||
return a.updateAllPages(state.StateUpdatedMsg{State: nil})
|
||||
}
|
||||
|
||||
a.app.Session = &sessionInfo
|
||||
}
|
||||
|
||||
return a.updateAllPages(state.StateUpdatedMsg{State: a.app.State})
|
||||
a.app.Messages = append(a.app.Messages, msg.Properties.Info)
|
||||
slog.Debug("Appended message", "message", msg.Properties.Info)
|
||||
return a.updateAllPages(state.StateUpdatedMsg{State: nil})
|
||||
}
|
||||
|
||||
if parts[0] == "session" && parts[1] == "message" {
|
||||
sessionId := parts[2]
|
||||
if sessionId == a.app.Session.Id {
|
||||
messageId := parts[3]
|
||||
var message client.MessageInfo
|
||||
bytes, _ := json.Marshal(msg.Content)
|
||||
if err := json.Unmarshal(bytes, &message); err != nil {
|
||||
status.Error(err.Error())
|
||||
return a, nil
|
||||
}
|
||||
|
||||
for i, m := range a.app.Messages {
|
||||
if m.Id == messageId {
|
||||
a.app.Messages[i] = message
|
||||
slog.Debug("Updated message", "message", message)
|
||||
return a.updateAllPages(state.StateUpdatedMsg{State: a.app.State})
|
||||
}
|
||||
}
|
||||
|
||||
a.app.Messages = append(a.app.Messages, message)
|
||||
slog.Debug("Appended message", "message", message)
|
||||
|
||||
// a.app.CurrentSession.MessageCount++
|
||||
// a.app.CurrentSession.PromptTokens += message.PromptTokens
|
||||
// a.app.CurrentSession.CompletionTokens += message.CompletionTokens
|
||||
// a.app.CurrentSession.Cost += message.Cost
|
||||
// a.app.CurrentSession.UpdatedAt = message.CreatedAt
|
||||
}
|
||||
|
||||
return a.updateAllPages(state.StateUpdatedMsg{State: a.app.State})
|
||||
case client.EventSessionUpdated:
|
||||
if msg.Properties.Info.Id == a.app.Session.Id {
|
||||
a.app.Session = &msg.Properties.Info
|
||||
return a.updateAllPages(state.StateUpdatedMsg{State: nil})
|
||||
}
|
||||
|
||||
// log key and content
|
||||
slog.Debug("Received SSE event", "key", msg.Key, "content", msg.Content)
|
||||
|
||||
current := a.app.State
|
||||
|
||||
for i, part := range parts {
|
||||
if i == len(parts)-1 {
|
||||
current[part] = msg.Content
|
||||
} else {
|
||||
if _, exists := current[part]; !exists {
|
||||
current[part] = make(map[string]any)
|
||||
}
|
||||
|
||||
nextLevel, ok := current[part].(map[string]any)
|
||||
if !ok {
|
||||
current[part] = make(map[string]any)
|
||||
nextLevel = current[part].(map[string]any)
|
||||
}
|
||||
current = nextLevel
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger UI update by updating all pages with the new state
|
||||
return a.updateAllPages(state.StateUpdatedMsg{State: a.app.State})
|
||||
|
||||
case dialog.CloseQuitMsg:
|
||||
a.showQuit = false
|
||||
return a, nil
|
||||
|
||||
Reference in New Issue
Block a user