summaryrefslogtreecommitdiffhomepage
path: root/internal/tui
diff options
context:
space:
mode:
Diffstat (limited to 'internal/tui')
-rw-r--r--internal/tui/app/app.go55
-rw-r--r--internal/tui/app/bridge.go41
-rw-r--r--internal/tui/app/interfaces.go10
-rw-r--r--internal/tui/components/chat/editor.go13
-rw-r--r--internal/tui/components/chat/messages.go9
-rw-r--r--internal/tui/components/chat/sidebar.go76
-rw-r--r--internal/tui/components/dialog/session.go18
-rw-r--r--internal/tui/page/chat.go25
-rw-r--r--internal/tui/state/state.go6
-rw-r--r--internal/tui/tui.go2
10 files changed, 42 insertions, 213 deletions
diff --git a/internal/tui/app/app.go b/internal/tui/app/app.go
index 4939a5802..d169f6dc2 100644
--- a/internal/tui/app/app.go
+++ b/internal/tui/app/app.go
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"sync"
- "time"
"log/slog"
@@ -12,7 +11,6 @@ import (
"github.com/sst/opencode/internal/config"
"github.com/sst/opencode/internal/fileutil"
"github.com/sst/opencode/internal/message"
- "github.com/sst/opencode/internal/session"
"github.com/sst/opencode/internal/status"
"github.com/sst/opencode/internal/tui/state"
"github.com/sst/opencode/internal/tui/theme"
@@ -26,13 +24,11 @@ type App struct {
Session *client.SessionInfo
Messages []client.MessageInfo
- CurrentSessionOLD *session.Session
- SessionsOLD SessionService
- MessagesOLD MessageService
- LogsOLD any // TODO: Define LogService interface when needed
- HistoryOLD any // TODO: Define HistoryService interface when needed
- PermissionsOLD any // TODO: Define PermissionService interface when needed
- Status status.Service
+ MessagesOLD MessageService
+ LogsOLD any // TODO: Define LogService interface when needed
+ HistoryOLD any // TODO: Define HistoryService interface when needed
+ PermissionsOLD any // TODO: Define PermissionService interface when needed
+ Status status.Service
PrimaryAgentOLD AgentService
@@ -70,19 +66,16 @@ func New(ctx context.Context) (*App, error) {
}
// Create service bridges
- sessionBridge := NewSessionServiceBridge(httpClient)
messageBridge := NewMessageServiceBridge(httpClient)
agentBridge := NewAgentServiceBridge(httpClient)
app := &App{
- Client: httpClient,
- Events: eventClient,
- Session: &client.SessionInfo{},
- CurrentSessionOLD: &session.Session{},
- SessionsOLD: sessionBridge,
- MessagesOLD: messageBridge,
- PrimaryAgentOLD: agentBridge,
- Status: status.GetService(),
+ Client: httpClient,
+ Events: eventClient,
+ Session: &client.SessionInfo{},
+ MessagesOLD: messageBridge,
+ PrimaryAgentOLD: agentBridge,
+ Status: status.GetService(),
// TODO: These services need API endpoints:
LogsOLD: nil, // logging.GetService(),
@@ -113,16 +106,7 @@ func (a *App) SendChatMessage(ctx context.Context, text string, attachments []me
info := resp.JSON200
a.Session = info
- // Convert to old session type for backwards compatibility
- newSession := session.Session{
- ID: info.Id,
- Title: info.Title,
- CreatedAt: time.Now(), // API doesn't provide this yet
- UpdatedAt: time.Now(), // API doesn't provide this yet
- }
- a.CurrentSessionOLD = &newSession
-
- cmds = append(cmds, util.CmdHandler(state.SessionSelectedMsg(&newSession)))
+ cmds = append(cmds, util.CmdHandler(state.SessionSelectedMsg(info)))
}
// TODO: Handle attachments when API supports them
@@ -151,7 +135,7 @@ func (a *App) SendChatMessage(ctx context.Context, text string, attachments []me
return tea.Batch(cmds...)
}
-func (a *App) ListSessions(ctx context.Context) ([]session.Session, error) {
+func (a *App) ListSessions(ctx context.Context) ([]client.SessionInfo, error) {
resp, err := a.Client.PostSessionListWithResponse(ctx)
if err != nil {
return nil, err
@@ -162,19 +146,16 @@ func (a *App) ListSessions(ctx context.Context) ([]session.Session, error) {
}
if resp.JSON200 == nil {
- return []session.Session{}, nil
+ return []client.SessionInfo{}, nil
}
infos := *resp.JSON200
- // Convert to old session type
- sessions := make([]session.Session, len(infos))
+ sessions := make([]client.SessionInfo, len(infos))
for i, info := range infos {
- sessions[i] = session.Session{
- ID: info.Id,
- Title: info.Title,
- CreatedAt: time.Now(), // API doesn't provide this yet
- UpdatedAt: time.Now(), // API doesn't provide this yet
+ sessions[i] = client.SessionInfo{
+ Id: info.Id,
+ Title: info.Title,
}
}
diff --git a/internal/tui/app/bridge.go b/internal/tui/app/bridge.go
index b646ca455..74abd712a 100644
--- a/internal/tui/app/bridge.go
+++ b/internal/tui/app/bridge.go
@@ -8,50 +8,9 @@ import (
"github.com/sst/opencode/internal/message"
"github.com/sst/opencode/internal/pubsub"
- "github.com/sst/opencode/internal/session"
"github.com/sst/opencode/pkg/client"
)
-// SessionServiceBridge adapts the HTTP API to the old session.Service interface
-type SessionServiceBridge struct {
- client *client.ClientWithResponses
-}
-
-// NewSessionServiceBridge creates a new session service bridge
-func NewSessionServiceBridge(client *client.ClientWithResponses) *SessionServiceBridge {
- return &SessionServiceBridge{client: client}
-}
-
-// Create creates a new session
-func (s *SessionServiceBridge) Create(ctx context.Context, title string) (session.Session, error) {
- // Moved to app.CreateSession
- return session.Session{}, fmt.Errorf("don't use this")
-}
-
-// Get retrieves a session by ID
-func (s *SessionServiceBridge) Get(ctx context.Context, id string) (session.Session, error) {
- // Moved to app.GetSession
- return session.Session{}, fmt.Errorf("don't use this")
-}
-
-// List retrieves all sessions
-func (s *SessionServiceBridge) List(ctx context.Context) ([]session.Session, error) {
- // Moved to app.ListSessions
- return []session.Session{}, fmt.Errorf("don't use this")
-}
-
-// Update updates a session - NOT IMPLEMENTED IN API YET
-func (s *SessionServiceBridge) Update(ctx context.Context, id, title string) error {
- // TODO: Not implemented in TypeScript API yet
- return fmt.Errorf("session update not implemented in API")
-}
-
-// Delete deletes a session - NOT IMPLEMENTED IN API YET
-func (s *SessionServiceBridge) Delete(ctx context.Context, id string) error {
- // TODO: Not implemented in TypeScript API yet
- return fmt.Errorf("session delete not implemented in API")
-}
-
// AgentServiceBridge provides a minimal agent service that sends messages to the API
type AgentServiceBridge struct {
client *client.ClientWithResponses
diff --git a/internal/tui/app/interfaces.go b/internal/tui/app/interfaces.go
index 9729a3bcb..01271156e 100644
--- a/internal/tui/app/interfaces.go
+++ b/internal/tui/app/interfaces.go
@@ -6,18 +6,8 @@ import (
"github.com/sst/opencode/internal/message"
"github.com/sst/opencode/internal/pubsub"
- "github.com/sst/opencode/internal/session"
)
-// SessionService defines the interface for session operations
-type SessionService interface {
- Create(ctx context.Context, title string) (session.Session, error)
- Get(ctx context.Context, id string) (session.Session, error)
- List(ctx context.Context) ([]session.Session, error)
- Update(ctx context.Context, id, title string) error
- Delete(ctx context.Context, id string) error
-}
-
// MessageService defines the interface for message operations
type MessageService interface {
pubsub.Subscriber[message.Message]
diff --git a/internal/tui/components/chat/editor.go b/internal/tui/components/chat/editor.go
index 17fb82c20..c3b06787e 100644
--- a/internal/tui/components/chat/editor.go
+++ b/internal/tui/components/chat/editor.go
@@ -143,11 +143,6 @@ func (m *editorCmp) Init() tea.Cmd {
}
func (m *editorCmp) send() tea.Cmd {
- if m.app.PrimaryAgentOLD.IsSessionBusy(m.app.CurrentSessionOLD.ID) {
- status.Warn("Agent is working, please wait...")
- return nil
- }
-
value := m.textarea.Value()
m.textarea.Reset()
attachments := m.attachments
@@ -217,10 +212,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.PrimaryAgentOLD.IsSessionBusy(m.app.CurrentSessionOLD.ID) {
+ // 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/internal/tui/components/chat/messages.go b/internal/tui/components/chat/messages.go
index 196d774cb..92e6ec471 100644
--- a/internal/tui/components/chat/messages.go
+++ b/internal/tui/components/chat/messages.go
@@ -10,7 +10,6 @@ import (
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/sst/opencode/internal/message"
- "github.com/sst/opencode/internal/session"
"github.com/sst/opencode/internal/tui/app"
"github.com/sst/opencode/internal/tui/components/dialog"
"github.com/sst/opencode/internal/tui/state"
@@ -72,7 +71,7 @@ func (m *messagesCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.renderView()
return m, nil
case state.SessionSelectedMsg:
- cmd := m.Reload(msg)
+ cmd := m.Reload()
return m, cmd
case state.SessionClearedMsg:
m.rendering = false
@@ -98,10 +97,6 @@ func (m *messagesCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, tea.Batch(cmds...)
}
-func (m *messagesCmp) IsAgentWorking() bool {
- return m.app.PrimaryAgentOLD.IsSessionBusy(m.app.CurrentSessionOLD.ID)
-}
-
func (m *messagesCmp) renderView() {
if m.width == 0 {
return
@@ -313,7 +308,7 @@ func (m *messagesCmp) GetSize() (int, int) {
return m.width, m.height
}
-func (m *messagesCmp) Reload(session *session.Session) tea.Cmd {
+func (m *messagesCmp) Reload() tea.Cmd {
m.rendering = true
return func() tea.Msg {
m.renderView()
diff --git a/internal/tui/components/chat/sidebar.go b/internal/tui/components/chat/sidebar.go
index 1f038a9b0..4a85784fc 100644
--- a/internal/tui/components/chat/sidebar.go
+++ b/internal/tui/components/chat/sidebar.go
@@ -1,7 +1,6 @@
package chat
import (
- "context"
"fmt"
"sort"
"strings"
@@ -205,81 +204,6 @@ func NewSidebarCmp(app *app.App) tea.Model {
}
}
-func (m *sidebarCmp) loadModifiedFiles(ctx context.Context) {
- if m.app.CurrentSessionOLD.ID == "" {
- return
- }
-
- // TODO: History service not implemented in API yet
- return
- /*
- // Get all latest files for this session
- latestFiles, err := m.app.History.ListLatestSessionFiles(ctx, m.app.CurrentSession.ID)
- if err != nil {
- return
- }
-
- // Get all files for this session (to find initial versions)
- allFiles, err := m.app.History.ListBySession(ctx, m.app.CurrentSession.ID)
- if err != nil {
- return
- }
- */
-
- // Clear the existing map to rebuild it
- m.modFiles = make(map[string]struct {
- additions int
- removals int
- })
-
- /*
- // Process each latest file
- for _, file := range latestFiles {
- // Skip if this is the initial version (no changes to show)
- if file.Version == history.InitialVersion {
- continue
- }
-
- // Find the initial version for this specific file
- var initialVersion history.File
- for _, v := range allFiles {
- if v.Path == file.Path && v.Version == history.InitialVersion {
- initialVersion = v
- break
- }
- }
-
- // Skip if we can't find the initial version
- if initialVersion.ID == "" {
- continue
- }
- if initialVersion.Content == file.Content {
- continue
- }
-
- // Calculate diff between initial and latest version
- _, additions, removals := diff.GenerateDiff(initialVersion.Content, file.Content, file.Path)
-
- // Only add to modified files if there are changes
- if additions > 0 || removals > 0 {
- // Remove working directory prefix from file path
- displayPath := file.Path
- workingDir := config.WorkingDirectory()
- displayPath = strings.TrimPrefix(displayPath, workingDir)
- displayPath = strings.TrimPrefix(displayPath, "/")
-
- m.modFiles[displayPath] = struct {
- additions int
- removals int
- }{
- additions: additions,
- removals: removals,
- }
- }
- }
- */
-}
-
// Helper function to get the display path for a file
func getDisplayPath(path string) string {
workingDir := config.WorkingDirectory()
diff --git a/internal/tui/components/dialog/session.go b/internal/tui/components/dialog/session.go
index 0ec828266..fd08a7db5 100644
--- a/internal/tui/components/dialog/session.go
+++ b/internal/tui/components/dialog/session.go
@@ -4,28 +4,28 @@ import (
"github.com/charmbracelet/bubbles/key"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
- "github.com/sst/opencode/internal/session"
"github.com/sst/opencode/internal/tui/layout"
"github.com/sst/opencode/internal/tui/styles"
"github.com/sst/opencode/internal/tui/theme"
"github.com/sst/opencode/internal/tui/util"
+ "github.com/sst/opencode/pkg/client"
)
// CloseSessionDialogMsg is sent when the session dialog is closed
type CloseSessionDialogMsg struct {
- Session *session.Session
+ Session *client.SessionInfo
}
// SessionDialog interface for the session switching dialog
type SessionDialog interface {
tea.Model
layout.Bindings
- SetSessions(sessions []session.Session)
+ SetSessions(sessions []client.SessionInfo)
SetSelectedSession(sessionID string)
}
type sessionDialogCmp struct {
- sessions []session.Session
+ sessions []client.SessionInfo
selectedIdx int
width int
height int
@@ -89,7 +89,7 @@ func (s *sessionDialogCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case key.Matches(msg, sessionKeys.Enter):
if len(s.sessions) > 0 {
selectedSession := s.sessions[s.selectedIdx]
- s.selectedSessionID = selectedSession.ID
+ s.selectedSessionID = selectedSession.Id
return s, util.CmdHandler(CloseSessionDialogMsg{
Session: &selectedSession,
@@ -189,13 +189,13 @@ func (s *sessionDialogCmp) BindingKeys() []key.Binding {
return layout.KeyMapToSlice(sessionKeys)
}
-func (s *sessionDialogCmp) SetSessions(sessions []session.Session) {
+func (s *sessionDialogCmp) SetSessions(sessions []client.SessionInfo) {
s.sessions = sessions
// If we have a selected session ID, find its index
if s.selectedSessionID != "" {
for i, sess := range sessions {
- if sess.ID == s.selectedSessionID {
+ if sess.Id == s.selectedSessionID {
s.selectedIdx = i
return
}
@@ -212,7 +212,7 @@ func (s *sessionDialogCmp) SetSelectedSession(sessionID string) {
// Update the selected index if sessions are already loaded
if len(s.sessions) > 0 {
for i, sess := range s.sessions {
- if sess.ID == sessionID {
+ if sess.Id == sessionID {
s.selectedIdx = i
return
}
@@ -223,7 +223,7 @@ func (s *sessionDialogCmp) SetSelectedSession(sessionID string) {
// NewSessionDialogCmp creates a new session switching dialog
func NewSessionDialogCmp() SessionDialog {
return &sessionDialogCmp{
- sessions: []session.Session{},
+ sessions: []client.SessionInfo{},
selectedIdx: 0,
selectedSessionID: "",
}
diff --git a/internal/tui/page/chat.go b/internal/tui/page/chat.go
index d0f974ce4..4a4692bbe 100644
--- a/internal/tui/page/chat.go
+++ b/internal/tui/page/chat.go
@@ -2,7 +2,6 @@ package page
import (
"context"
- "fmt"
"strings"
"github.com/charmbracelet/bubbles/key"
@@ -10,7 +9,6 @@ import (
"github.com/charmbracelet/lipgloss"
"github.com/sst/opencode/internal/completions"
"github.com/sst/opencode/internal/message"
- "github.com/sst/opencode/internal/session"
"github.com/sst/opencode/internal/status"
"github.com/sst/opencode/internal/tui/app"
"github.com/sst/opencode/internal/tui/components/chat"
@@ -18,6 +16,7 @@ import (
"github.com/sst/opencode/internal/tui/layout"
"github.com/sst/opencode/internal/tui/state"
"github.com/sst/opencode/internal/tui/util"
+ "github.com/sst/opencode/pkg/client"
)
var ChatPage PageID = "chat"
@@ -104,23 +103,7 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case state.SessionClearedMsg:
cmd := p.setSidebar()
cmds = append(cmds, cmd)
- case state.CompactSessionMsg:
- if p.app.CurrentSessionOLD.ID == "" {
- status.Warn("No active session to compact.")
- return p, nil
- }
-
- // Run compaction in background
- go func(sessionID string) {
- err := p.app.PrimaryAgentOLD.CompactSession(context.Background(), sessionID, false)
- if err != nil {
- status.Error(fmt.Sprintf("Compaction failed: %v", err))
- } else {
- status.Info("Conversation compacted successfully.")
- }
- }(p.app.CurrentSessionOLD.ID)
- return p, nil
case dialog.CompletionDialogCloseMsg:
p.showCompletionDialog = false
p.app.SetCompletionDialogOpen(false)
@@ -131,16 +114,16 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
p.app.SetCompletionDialogOpen(true)
// Continue sending keys to layout->chat
case key.Matches(msg, keyMap.NewSession):
- p.app.CurrentSessionOLD = &session.Session{}
+ p.app.Session = &client.SessionInfo{}
return p, tea.Batch(
p.clearSidebar(),
util.CmdHandler(state.SessionClearedMsg{}),
)
case key.Matches(msg, keyMap.Cancel):
- if p.app.CurrentSessionOLD.ID != "" {
+ 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.PrimaryAgentOLD.Cancel(p.app.CurrentSessionOLD.ID)
return p, nil
}
case key.Matches(msg, keyMap.ToggleTools):
diff --git a/internal/tui/state/state.go b/internal/tui/state/state.go
index d2125b930..33b1cc7f1 100644
--- a/internal/tui/state/state.go
+++ b/internal/tui/state/state.go
@@ -1,8 +1,10 @@
package state
-import "github.com/sst/opencode/internal/session"
+import (
+ "github.com/sst/opencode/pkg/client"
+)
-type SessionSelectedMsg = *session.Session
+type SessionSelectedMsg = *client.SessionInfo
type SessionClearedMsg struct{}
type CompactSessionMsg struct{}
type StateUpdatedMsg struct {
diff --git a/internal/tui/tui.go b/internal/tui/tui.go
index ed207b704..ec4f49fd7 100644
--- a/internal/tui/tui.go
+++ b/internal/tui/tui.go
@@ -275,7 +275,7 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return a, a.moveToPage(msg.ID)
case state.SessionSelectedMsg:
- a.app.CurrentSessionOLD = msg
+ a.app.Session = msg
return a.updateAllPages(msg)
case dialog.CloseQuitMsg: