9 "github.com/charmbracelet/crush/internal/db"
10 "github.com/charmbracelet/crush/internal/event"
11 "github.com/charmbracelet/crush/internal/pubsub"
12 "github.com/google/uuid"
17 ParentSessionID string
21 CompletionTokens int64
22 SummaryMessageID string
28type Service interface {
29 pubsub.Suscriber[Session]
30 Create(ctx context.Context, title string) (Session, error)
31 CreateTitleSession(ctx context.Context, parentSessionID string) (Session, error)
32 CreateTaskSession(ctx context.Context, toolCallID, parentSessionID, title string) (Session, error)
33 Get(ctx context.Context, id string) (Session, error)
34 List(ctx context.Context) ([]Session, error)
35 Save(ctx context.Context, session Session) (Session, error)
36 Delete(ctx context.Context, id string) error
38 // Agent tool session management
39 CreateAgentToolSessionID(messageID, toolCallID string) string
40 ParseAgentToolSessionID(sessionID string) (messageID string, toolCallID string, ok bool)
41 IsAgentToolSession(sessionID string) bool
45 *pubsub.Broker[Session]
49func (s *service) Create(ctx context.Context, title string) (Session, error) {
50 dbSession, err := s.q.CreateSession(ctx, db.CreateSessionParams{
51 ID: uuid.New().String(),
57 session := s.fromDBItem(dbSession)
58 s.Publish(pubsub.CreatedEvent, session)
59 event.SessionCreated()
63func (s *service) CreateTaskSession(ctx context.Context, toolCallID, parentSessionID, title string) (Session, error) {
64 dbSession, err := s.q.CreateSession(ctx, db.CreateSessionParams{
66 ParentSessionID: sql.NullString{String: parentSessionID, Valid: true},
72 session := s.fromDBItem(dbSession)
73 s.Publish(pubsub.CreatedEvent, session)
77func (s *service) CreateTitleSession(ctx context.Context, parentSessionID string) (Session, error) {
78 dbSession, err := s.q.CreateSession(ctx, db.CreateSessionParams{
79 ID: "title-" + parentSessionID,
80 ParentSessionID: sql.NullString{String: parentSessionID, Valid: true},
81 Title: "Generate a title",
86 session := s.fromDBItem(dbSession)
87 s.Publish(pubsub.CreatedEvent, session)
91func (s *service) Delete(ctx context.Context, id string) error {
92 session, err := s.Get(ctx, id)
96 err = s.q.DeleteSession(ctx, session.ID)
100 s.Publish(pubsub.DeletedEvent, session)
101 event.SessionDeleted()
105func (s *service) Get(ctx context.Context, id string) (Session, error) {
106 dbSession, err := s.q.GetSessionByID(ctx, id)
108 return Session{}, err
110 return s.fromDBItem(dbSession), nil
113func (s *service) Save(ctx context.Context, session Session) (Session, error) {
114 dbSession, err := s.q.UpdateSession(ctx, db.UpdateSessionParams{
116 Title: session.Title,
117 PromptTokens: session.PromptTokens,
118 CompletionTokens: session.CompletionTokens,
119 SummaryMessageID: sql.NullString{
120 String: session.SummaryMessageID,
121 Valid: session.SummaryMessageID != "",
126 return Session{}, err
128 session = s.fromDBItem(dbSession)
129 s.Publish(pubsub.UpdatedEvent, session)
133func (s *service) List(ctx context.Context) ([]Session, error) {
134 dbSessions, err := s.q.ListSessions(ctx)
138 sessions := make([]Session, len(dbSessions))
139 for i, dbSession := range dbSessions {
140 sessions[i] = s.fromDBItem(dbSession)
145func (s service) fromDBItem(item db.Session) Session {
148 ParentSessionID: item.ParentSessionID.String,
150 MessageCount: item.MessageCount,
151 PromptTokens: item.PromptTokens,
152 CompletionTokens: item.CompletionTokens,
153 SummaryMessageID: item.SummaryMessageID.String,
155 CreatedAt: item.CreatedAt,
156 UpdatedAt: item.UpdatedAt,
160func NewService(q db.Querier) Service {
161 broker := pubsub.NewBroker[Session]()
168// CreateAgentToolSessionID creates a session ID for agent tool sessions using the format "messageID$$toolCallID"
169func (s *service) CreateAgentToolSessionID(messageID, toolCallID string) string {
170 return fmt.Sprintf("%s$$%s", messageID, toolCallID)
173// ParseAgentToolSessionID parses an agent tool session ID into its components
174func (s *service) ParseAgentToolSessionID(sessionID string) (messageID string, toolCallID string, ok bool) {
175 parts := strings.Split(sessionID, "$$")
179 return parts[0], parts[1], true
182// IsAgentToolSession checks if a session ID follows the agent tool session format
183func (s *service) IsAgentToolSession(sessionID string) bool {
184 _, _, ok := s.ParseAgentToolSessionID(sessionID)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list