summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authoradamdottv <[email protected]>2025-06-04 13:52:23 -0500
committeradamdottv <[email protected]>2025-06-04 13:52:23 -0500
commit093e64eb54b0340442a8b1d73a4e7c769f3c275c (patch)
tree04b18060e22cc1354833133c305d1c7ddc604a65
parentf34a3b6f67ff3cf255a0a9e547da31fa0b5b8912 (diff)
downloadopencode-093e64eb54b0340442a8b1d73a4e7c769f3c275c.tar.gz
opencode-093e64eb54b0340442a8b1d73a4e7c769f3c275c.zip
wip: refactoring tui
-rw-r--r--packages/tui/internal/app/app.go27
-rw-r--r--packages/tui/internal/components/chat/editor.go8
-rw-r--r--packages/tui/internal/components/chat/message.go8
-rw-r--r--packages/tui/internal/components/chat/messages.go50
-rw-r--r--packages/tui/internal/page/chat.go11
-rw-r--r--packages/tui/internal/tui/tui.go16
6 files changed, 70 insertions, 50 deletions
diff --git a/packages/tui/internal/app/app.go b/packages/tui/internal/app/app.go
index 65b0217ce..d4b59c0b9 100644
--- a/packages/tui/internal/app/app.go
+++ b/packages/tui/internal/app/app.go
@@ -118,12 +118,12 @@ type Attachment struct {
}
func (a *App) IsBusy() bool {
- for _, message := range a.Messages {
- if message.Metadata.Time.Completed == nil {
- return true
- }
+ if len(a.Messages) == 0 {
+ return false
}
- return false
+
+ lastMessage := a.Messages[len(a.Messages)-1]
+ return lastMessage.Metadata.Time.Completed == nil
}
func (a *App) SaveConfig() {
@@ -231,6 +231,23 @@ func (a *App) SendChatMessage(ctx context.Context, text string, attachments []At
return tea.Batch(cmds...)
}
+func (a *App) Cancel(ctx context.Context, sessionID string) error {
+ response, err := a.Client.PostSessionAbort(ctx, client.PostSessionAbortJSONRequestBody{
+ SessionID: sessionID,
+ })
+ if err != nil {
+ slog.Error("Failed to cancel session", "error", err)
+ status.Error(err.Error())
+ return err
+ }
+ if response != nil && response.StatusCode != 200 {
+ slog.Error("Failed to cancel session", "error", fmt.Sprintf("failed to cancel session: %d", response.StatusCode))
+ status.Error(fmt.Sprintf("failed to cancel session: %d", response.StatusCode))
+ return fmt.Errorf("failed to cancel session: %d", response.StatusCode)
+ }
+ return nil
+}
+
func (a *App) ListSessions(ctx context.Context) ([]client.SessionInfo, error) {
resp, err := a.Client.PostSessionListWithResponse(ctx)
if err != nil {
diff --git a/packages/tui/internal/components/chat/editor.go b/packages/tui/internal/components/chat/editor.go
index bf5c5875e..305365a25 100644
--- a/packages/tui/internal/components/chat/editor.go
+++ b/packages/tui/internal/components/chat/editor.go
@@ -211,10 +211,10 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, nil
}
if key.Matches(msg, editorMaps.OpenEditor) {
- // if m.app.PrimaryAgentOLD.IsSessionBusy(m.app.CurrentSessionOLD.ID) {
- // status.Warn("Agent is working, please wait...")
- // return m, nil
- // }
+ if m.app.IsBusy() {
+ status.Warn("Agent is working, please wait...")
+ return m, nil
+ }
value := m.textarea.Value()
m.textarea.Reset()
return m, m.openEditor(value)
diff --git a/packages/tui/internal/components/chat/message.go b/packages/tui/internal/components/chat/message.go
index cfed8f339..d811ce7aa 100644
--- a/packages/tui/internal/components/chat/message.go
+++ b/packages/tui/internal/components/chat/message.go
@@ -93,6 +93,7 @@ func renderAssistantMessage(
msg client.MessageInfo,
width int,
showToolMessages bool,
+ appInfo client.AppInfo,
) string {
t := theme.CurrentTheme()
style := styles.BaseStyle().
@@ -144,7 +145,7 @@ func renderAssistantMessage(
if _, ok := msg.Metadata.Tool[toolCall.ToolCallId]; ok {
metadata = msg.Metadata.Tool[toolCall.ToolCallId].(map[string]any)
}
- message := renderToolInvocation(toolCall, result, metadata, width)
+ message := renderToolInvocation(toolCall, result, metadata, appInfo, width)
messages = append(messages, message)
}
}
@@ -152,7 +153,7 @@ func renderAssistantMessage(
return strings.Join(messages, "\n\n")
}
-func renderToolInvocation(toolCall client.MessageToolInvocationToolCall, result *string, metadata map[string]any, width int) string {
+func renderToolInvocation(toolCall client.MessageToolInvocationToolCall, result *string, metadata map[string]any, appInfo client.AppInfo, width int) string {
t := theme.CurrentTheme()
style := styles.BaseStyle().
BorderLeft(true).
@@ -176,6 +177,7 @@ func renderToolInvocation(toolCall client.MessageToolInvocationToolCall, result
if toolCall.ToolName == "opencode_edit" {
filename := toolMap["filePath"].(string)
+ filename = strings.TrimPrefix(filename, appInfo.Path.Root+"/")
title = styles.Padded().Render(fmt.Sprintf("%s: %s", toolName, filename))
if finished && metadata["diff"] != nil {
patch := metadata["diff"].(string)
@@ -189,6 +191,8 @@ func renderToolInvocation(toolCall client.MessageToolInvocationToolCall, result
))
} else if toolCall.ToolName == "opencode_read" {
filename := toolMap["filePath"].(string)
+ filename = strings.TrimPrefix(filename, appInfo.Path.Root+"/")
+ title = styles.Padded().Render(fmt.Sprintf("%s: %s", toolName, filename))
ext := filepath.Ext(filename)
if ext == "" {
ext = ""
diff --git a/packages/tui/internal/components/chat/messages.go b/packages/tui/internal/components/chat/messages.go
index e18b6d153..202f7adb6 100644
--- a/packages/tui/internal/components/chat/messages.go
+++ b/packages/tui/internal/components/chat/messages.go
@@ -108,7 +108,7 @@ func (m *messagesCmp) renderView() {
content := renderUserMessage(m.app.Info.User, msg, m.width)
messages = append(messages, content+"\n")
case client.Assistant:
- content := renderAssistantMessage(msg, m.width, m.showToolMessages)
+ content := renderAssistantMessage(msg, m.width, m.showToolMessages, *m.app.Info)
messages = append(messages, content+"\n")
}
}
@@ -215,9 +215,7 @@ func (m *messagesCmp) working() string {
baseStyle := styles.BaseStyle()
task := ""
-
- lastMessage := m.app.Messages[len(m.app.Messages)-1]
- if lastMessage.Metadata.Time.Completed == nil {
+ if m.app.IsBusy() {
task = "Working..."
}
// lastMessage := m.app.Messages[len(m.app.Messages)-1]
@@ -245,28 +243,28 @@ func (m *messagesCmp) help() string {
text := ""
- // if m.app.PrimaryAgentOLD.IsBusy() {
- // text += lipgloss.JoinHorizontal(
- // lipgloss.Left,
- // baseStyle.Foreground(t.TextMuted()).Bold(true).Render("press "),
- // baseStyle.Foreground(t.Text()).Bold(true).Render("esc"),
- // baseStyle.Foreground(t.TextMuted()).Bold(true).Render(" to interrupt"),
- // )
- // } else {
- text += lipgloss.JoinHorizontal(
- lipgloss.Left,
- baseStyle.Foreground(t.Text()).Bold(true).Render("enter"),
- baseStyle.Foreground(t.TextMuted()).Bold(true).Render(" to send,"),
- baseStyle.Foreground(t.Text()).Bold(true).Render(" \\"),
- baseStyle.Foreground(t.TextMuted()).Bold(true).Render("+"),
- baseStyle.Foreground(t.Text()).Bold(true).Render("enter"),
- baseStyle.Foreground(t.TextMuted()).Bold(true).Render(" for newline,"),
- baseStyle.Foreground(t.Text()).Bold(true).Render(" ↑↓"),
- baseStyle.Foreground(t.TextMuted()).Bold(true).Render(" for history,"),
- baseStyle.Foreground(t.Text()).Bold(true).Render(" ctrl+h"),
- baseStyle.Foreground(t.TextMuted()).Bold(true).Render(" to toggle tool messages"),
- )
- // }
+ if m.app.IsBusy() {
+ text += lipgloss.JoinHorizontal(
+ lipgloss.Left,
+ baseStyle.Foreground(t.TextMuted()).Bold(true).Render("press "),
+ baseStyle.Foreground(t.Text()).Bold(true).Render("esc"),
+ baseStyle.Foreground(t.TextMuted()).Bold(true).Render(" to interrupt"),
+ )
+ } else {
+ text += lipgloss.JoinHorizontal(
+ lipgloss.Left,
+ baseStyle.Foreground(t.Text()).Bold(true).Render("enter"),
+ baseStyle.Foreground(t.TextMuted()).Bold(true).Render(" to send,"),
+ baseStyle.Foreground(t.Text()).Bold(true).Render(" \\"),
+ baseStyle.Foreground(t.TextMuted()).Bold(true).Render("+"),
+ baseStyle.Foreground(t.Text()).Bold(true).Render("enter"),
+ baseStyle.Foreground(t.TextMuted()).Bold(true).Render(" for newline,"),
+ baseStyle.Foreground(t.Text()).Bold(true).Render(" ↑↓"),
+ baseStyle.Foreground(t.TextMuted()).Bold(true).Render(" for history,"),
+ baseStyle.Foreground(t.Text()).Bold(true).Render(" ctrl+h"),
+ baseStyle.Foreground(t.TextMuted()).Bold(true).Render(" to toggle tool messages"),
+ )
+ }
return baseStyle.
Width(m.width).
Render(text)
diff --git a/packages/tui/internal/page/chat.go b/packages/tui/internal/page/chat.go
index 1c559122f..8e175a26e 100644
--- a/packages/tui/internal/page/chat.go
+++ b/packages/tui/internal/page/chat.go
@@ -13,6 +13,7 @@ import (
"github.com/sst/opencode/internal/components/dialog"
"github.com/sst/opencode/internal/layout"
"github.com/sst/opencode/internal/state"
+ "github.com/sst/opencode/internal/status"
"github.com/sst/opencode/internal/util"
"github.com/sst/opencode/pkg/client"
)
@@ -75,10 +76,10 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
case dialog.CommandRunCustomMsg:
// Check if the agent is busy before executing custom commands
- // if p.app.PrimaryAgentOLD.IsBusy() {
- // status.Warn("Agent is busy, please wait before executing a command...")
- // return p, nil
- // }
+ if p.app.IsBusy() {
+ status.Warn("Agent is busy, please wait before executing a command...")
+ return p, nil
+ }
// Process the command content with arguments if any
content := msg.Content
@@ -122,7 +123,7 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if p.app.Session.Id != "" {
// Cancel the current session's generation process
// This allows users to interrupt long-running operations
- // p.app.PrimaryAgentOLD.Cancel(p.app.CurrentSessionOLD.ID)
+ p.app.Cancel(context.Background(), p.app.Session.Id)
return p, nil
}
case key.Matches(msg, keyMap.ToggleTools):
diff --git a/packages/tui/internal/tui/tui.go b/packages/tui/internal/tui/tui.go
index 66888d87f..776078b5f 100644
--- a/packages/tui/internal/tui/tui.go
+++ b/packages/tui/internal/tui/tui.go
@@ -551,13 +551,13 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
return a, nil
case key.Matches(msg, helpEsc):
- // if a.app.PrimaryAgentOLD.IsBusy() {
- if a.showQuit {
+ if a.app.IsBusy() {
+ if a.showQuit {
+ return a, nil
+ }
+ a.showHelp = !a.showHelp
return a, nil
}
- a.showHelp = !a.showHelp
- return a, nil
- // }
case key.Matches(msg, keys.Filepicker):
// Toggle filepicker
a.showFilepicker = !a.showFilepicker
@@ -755,9 +755,9 @@ func (a appModel) View() string {
if a.showPermissions {
bindings = append(bindings, a.permissions.BindingKeys()...)
}
- // if !a.app.PrimaryAgentOLD.IsBusy() {
- bindings = append(bindings, helpEsc)
- // }
+ if !a.app.IsBusy() {
+ bindings = append(bindings, helpEsc)
+ }
a.help.SetBindings(bindings)
overlay := a.help.View()