Browse Source

wip: refactoring tui

adamdottv 9 months ago
parent
commit
913b3434d8

+ 0 - 255
internal/session/session.go

@@ -1,255 +0,0 @@
-package session
-
-import (
-	"context"
-	"database/sql"
-	"fmt"
-	"sync"
-	"time"
-
-	"github.com/google/uuid"
-	"github.com/sst/opencode/internal/db"
-	"github.com/sst/opencode/internal/pubsub"
-)
-
-type Session struct {
-	ID               string
-	ParentSessionID  string
-	Title            string
-	MessageCount     int64
-	PromptTokens     int64
-	CompletionTokens int64
-	Cost             float64
-	Summary          string
-	SummarizedAt     time.Time
-	CreatedAt        time.Time
-	UpdatedAt        time.Time
-}
-
-const (
-	EventSessionCreated pubsub.EventType = "session_created"
-	EventSessionUpdated pubsub.EventType = "session_updated"
-	EventSessionDeleted pubsub.EventType = "session_deleted"
-)
-
-type Service interface {
-	pubsub.Subscriber[Session]
-
-	Create(ctx context.Context, title string) (Session, error)
-	CreateTaskSession(ctx context.Context, toolCallID, parentSessionID, title string) (Session, error)
-	Get(ctx context.Context, id string) (Session, error)
-	List(ctx context.Context) ([]Session, error)
-	Update(ctx context.Context, session Session) (Session, error)
-	Delete(ctx context.Context, id string) error
-}
-
-type service struct {
-	db     *db.Queries
-	broker *pubsub.Broker[Session]
-	mu     sync.RWMutex
-}
-
-var globalSessionService *service
-
-func InitService(dbConn *sql.DB) error {
-	if globalSessionService != nil {
-		return fmt.Errorf("session service already initialized")
-	}
-	queries := db.New(dbConn)
-	broker := pubsub.NewBroker[Session]()
-
-	globalSessionService = &service{
-		db:     queries,
-		broker: broker,
-	}
-	return nil
-}
-
-func GetService() Service {
-	if globalSessionService == nil {
-		panic("session service not initialized. Call session.InitService() first.")
-	}
-	return globalSessionService
-}
-
-func (s *service) Create(ctx context.Context, title string) (Session, error) {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-
-	if title == "" {
-		title = "New Session - " + time.Now().Format("2006-01-02 15:04:05")
-	}
-
-	dbSessParams := db.CreateSessionParams{
-		ID:    uuid.New().String(),
-		Title: title,
-	}
-	dbSession, err := s.db.CreateSession(ctx, dbSessParams)
-	if err != nil {
-		return Session{}, fmt.Errorf("db.CreateSession: %w", err)
-	}
-
-	session := s.fromDBItem(dbSession)
-	s.broker.Publish(EventSessionCreated, session)
-	return session, nil
-}
-
-func (s *service) CreateTaskSession(ctx context.Context, toolCallID, parentSessionID, title string) (Session, error) {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-
-	if title == "" {
-		title = "Task Session - " + time.Now().Format("2006-01-02 15:04:05")
-	}
-	if toolCallID == "" {
-		toolCallID = uuid.New().String()
-	}
-
-	dbSessParams := db.CreateSessionParams{
-		ID:              toolCallID,
-		ParentSessionID: sql.NullString{String: parentSessionID, Valid: parentSessionID != ""},
-		Title:           title,
-	}
-	dbSession, err := s.db.CreateSession(ctx, dbSessParams)
-	if err != nil {
-		return Session{}, fmt.Errorf("db.CreateTaskSession: %w", err)
-	}
-	session := s.fromDBItem(dbSession)
-	s.broker.Publish(EventSessionCreated, session)
-	return session, nil
-}
-
-func (s *service) Get(ctx context.Context, id string) (Session, error) {
-	s.mu.RLock()
-	defer s.mu.RUnlock()
-	dbSession, err := s.db.GetSessionByID(ctx, id)
-	if err != nil {
-		if err == sql.ErrNoRows {
-			return Session{}, fmt.Errorf("session ID '%s' not found", id)
-		}
-		return Session{}, fmt.Errorf("db.GetSessionByID: %w", err)
-	}
-	return s.fromDBItem(dbSession), nil
-}
-
-func (s *service) List(ctx context.Context) ([]Session, error) {
-	s.mu.RLock()
-	defer s.mu.RUnlock()
-	dbSessions, err := s.db.ListSessions(ctx)
-	if err != nil {
-		return nil, fmt.Errorf("db.ListSessions: %w", err)
-	}
-	sessions := make([]Session, len(dbSessions))
-	for i, dbSess := range dbSessions {
-		sessions[i] = s.fromDBItem(dbSess)
-	}
-	return sessions, nil
-}
-
-func (s *service) Update(ctx context.Context, session Session) (Session, error) {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-
-	if session.ID == "" {
-		return Session{}, fmt.Errorf("cannot update session with empty ID")
-	}
-
-	params := db.UpdateSessionParams{
-		ID:               session.ID,
-		Title:            session.Title,
-		PromptTokens:     session.PromptTokens,
-		CompletionTokens: session.CompletionTokens,
-		Cost:             session.Cost,
-		Summary:          sql.NullString{String: session.Summary, Valid: session.Summary != ""},
-		SummarizedAt:     sql.NullString{String: session.SummarizedAt.UTC().Format(time.RFC3339Nano), Valid: !session.SummarizedAt.IsZero()},
-	}
-	dbSession, err := s.db.UpdateSession(ctx, params)
-	if err != nil {
-		return Session{}, fmt.Errorf("db.UpdateSession: %w", err)
-	}
-	updatedSession := s.fromDBItem(dbSession)
-	s.broker.Publish(EventSessionUpdated, updatedSession)
-	return updatedSession, nil
-}
-
-func (s *service) Delete(ctx context.Context, id string) error {
-	s.mu.Lock()
-	dbSess, err := s.db.GetSessionByID(ctx, id)
-	if err != nil {
-		s.mu.Unlock()
-		if err == sql.ErrNoRows {
-			return fmt.Errorf("session ID '%s' not found for deletion", id)
-		}
-		return fmt.Errorf("db.GetSessionByID before delete: %w", err)
-	}
-	sessionToPublish := s.fromDBItem(dbSess)
-	s.mu.Unlock()
-
-	s.mu.Lock()
-	defer s.mu.Unlock()
-	err = s.db.DeleteSession(ctx, id)
-	if err != nil {
-		return fmt.Errorf("db.DeleteSession: %w", err)
-	}
-	s.broker.Publish(EventSessionDeleted, sessionToPublish)
-	return nil
-}
-
-func (s *service) Subscribe(ctx context.Context) <-chan pubsub.Event[Session] {
-	return s.broker.Subscribe(ctx)
-}
-
-func (s *service) fromDBItem(item db.Session) Session {
-	var summarizedAt time.Time
-	if item.SummarizedAt.Valid {
-		parsedTime, err := time.Parse(time.RFC3339Nano, item.SummarizedAt.String)
-		if err == nil {
-			summarizedAt = parsedTime
-		}
-	}
-
-	createdAt, _ := time.Parse(time.RFC3339Nano, item.CreatedAt)
-	updatedAt, _ := time.Parse(time.RFC3339Nano, item.UpdatedAt)
-
-	return Session{
-		ID:               item.ID,
-		ParentSessionID:  item.ParentSessionID.String,
-		Title:            item.Title,
-		MessageCount:     item.MessageCount,
-		PromptTokens:     item.PromptTokens,
-		CompletionTokens: item.CompletionTokens,
-		Cost:             item.Cost,
-		Summary:          item.Summary.String,
-		SummarizedAt:     summarizedAt,
-		CreatedAt:        createdAt,
-		UpdatedAt:        updatedAt,
-	}
-}
-
-func Create(ctx context.Context, title string) (Session, error) {
-	return GetService().Create(ctx, title)
-}
-
-func CreateTaskSession(ctx context.Context, toolCallID, parentSessionID, title string) (Session, error) {
-	return GetService().CreateTaskSession(ctx, toolCallID, parentSessionID, title)
-}
-
-func Get(ctx context.Context, id string) (Session, error) {
-	return GetService().Get(ctx, id)
-}
-
-func List(ctx context.Context) ([]Session, error) {
-	return GetService().List(ctx)
-}
-
-func Update(ctx context.Context, session Session) (Session, error) {
-	return GetService().Update(ctx, session)
-}
-
-func Delete(ctx context.Context, id string) error {
-	return GetService().Delete(ctx, id)
-}
-
-func Subscribe(ctx context.Context) <-chan pubsub.Event[Session] {
-	return GetService().Subscribe(ctx)
-}

+ 18 - 37
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,
 		}
 	}
 

+ 0 - 41
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

+ 0 - 10
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]

+ 4 - 9
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)

+ 2 - 7
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()

+ 0 - 76
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()

+ 9 - 9
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: "",
 	}

+ 4 - 21
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):

+ 4 - 2
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 {

+ 1 - 1
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: