1package backend
2
3import (
4 "context"
5
6 "github.com/charmbracelet/crush/internal/message"
7 "github.com/charmbracelet/crush/internal/proto"
8 "github.com/charmbracelet/crush/internal/session"
9)
10
11// CreateSession creates a new session in the given workspace.
12func (b *Backend) CreateSession(ctx context.Context, workspaceID, title string) (session.Session, error) {
13 ws, err := b.GetWorkspace(workspaceID)
14 if err != nil {
15 return session.Session{}, err
16 }
17
18 return ws.Sessions.Create(ctx, title)
19}
20
21// GetSession retrieves a session by workspace and session ID.
22func (b *Backend) GetSession(ctx context.Context, workspaceID, sessionID string) (session.Session, error) {
23 ws, err := b.GetWorkspace(workspaceID)
24 if err != nil {
25 return session.Session{}, err
26 }
27
28 return ws.Sessions.Get(ctx, sessionID)
29}
30
31// ListSessions returns all sessions in the given workspace.
32func (b *Backend) ListSessions(ctx context.Context, workspaceID string) ([]session.Session, error) {
33 ws, err := b.GetWorkspace(workspaceID)
34 if err != nil {
35 return nil, err
36 }
37
38 return ws.Sessions.List(ctx)
39}
40
41// GetAgentSession returns session metadata with the agent's busy
42// status.
43func (b *Backend) GetAgentSession(ctx context.Context, workspaceID, sessionID string) (proto.AgentSession, error) {
44 ws, err := b.GetWorkspace(workspaceID)
45 if err != nil {
46 return proto.AgentSession{}, err
47 }
48
49 se, err := ws.Sessions.Get(ctx, sessionID)
50 if err != nil {
51 return proto.AgentSession{}, err
52 }
53
54 var isSessionBusy bool
55 if ws.AgentCoordinator != nil {
56 isSessionBusy = ws.AgentCoordinator.IsSessionBusy(sessionID)
57 }
58
59 return proto.AgentSession{
60 Session: proto.Session{
61 ID: se.ID,
62 Title: se.Title,
63 },
64 IsBusy: isSessionBusy,
65 }, nil
66}
67
68// ListSessionMessages returns all messages for a session.
69func (b *Backend) ListSessionMessages(ctx context.Context, workspaceID, sessionID string) ([]message.Message, error) {
70 ws, err := b.GetWorkspace(workspaceID)
71 if err != nil {
72 return nil, err
73 }
74
75 // Drain debounced updates so HTTP clients (and the TUI on session
76 // switch) observe the latest in-memory state rather than racing the
77 // debounce timer in message.Service.
78 if err := ws.Messages.FlushAll(ctx); err != nil {
79 return nil, err
80 }
81 return ws.Messages.List(ctx, sessionID)
82}
83
84// ListSessionHistory returns the history items for a session.
85func (b *Backend) ListSessionHistory(ctx context.Context, workspaceID, sessionID string) (any, error) {
86 ws, err := b.GetWorkspace(workspaceID)
87 if err != nil {
88 return nil, err
89 }
90
91 return ws.History.ListBySession(ctx, sessionID)
92}
93
94// SaveSession updates a session in the given workspace.
95func (b *Backend) SaveSession(ctx context.Context, workspaceID string, sess session.Session) (session.Session, error) {
96 ws, err := b.GetWorkspace(workspaceID)
97 if err != nil {
98 return session.Session{}, err
99 }
100
101 return ws.Sessions.Save(ctx, sess)
102}
103
104// DeleteSession deletes a session from the given workspace.
105func (b *Backend) DeleteSession(ctx context.Context, workspaceID, sessionID string) error {
106 ws, err := b.GetWorkspace(workspaceID)
107 if err != nil {
108 return err
109 }
110
111 return ws.Sessions.Delete(ctx, sessionID)
112}
113
114// ListUserMessages returns user-role messages for a session.
115func (b *Backend) ListUserMessages(ctx context.Context, workspaceID, sessionID string) ([]message.Message, error) {
116 ws, err := b.GetWorkspace(workspaceID)
117 if err != nil {
118 return nil, err
119 }
120
121 return ws.Messages.ListUserMessages(ctx, sessionID)
122}
123
124// ListAllUserMessages returns all user-role messages across sessions.
125func (b *Backend) ListAllUserMessages(ctx context.Context, workspaceID string) ([]message.Message, error) {
126 ws, err := b.GetWorkspace(workspaceID)
127 if err != nil {
128 return nil, err
129 }
130
131 return ws.Messages.ListAllUserMessages(ctx)
132}