@@ -14,11 +14,9 @@ import (
1414 "time"
1515
1616 "github.com/charmbracelet/crush/internal/config"
17− "github.com/charmbracelet/crush/internal/history"
1817 "github.com/charmbracelet/crush/internal/message"
1918 "github.com/charmbracelet/crush/internal/proto"
2019 "github.com/charmbracelet/crush/internal/pubsub"
21− "github.com/charmbracelet/crush/internal/session"
2220 "github.com/charmbracelet/x/powernap/pkg/lsp/protocol"
2321)
2422
@@ -404,8 +402,8 @@ func (c *Client) InitiateAgentProcessing(ctx context.Context, id string) error {
404402 return nil
405403}
406404
407−// ListMessages retrieves all messages for a session.
408−func (c *Client) ListMessages(ctx context.Context, id string, sessionID string) ([]message.Message, error) {
405+// ListMessages retrieves all messages for a session as proto types.
406+func (c *Client) ListMessages(ctx context.Context, id string, sessionID string) ([]proto.Message, error) {
409407 rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/sessions/%s/messages", id, sessionID), nil, nil)
410408 if err != nil {
411409 return nil, fmt.Errorf("failed to get messages: %w", err)
@@ -414,15 +412,15 @@ func (c *Client) ListMessages(ctx context.Context, id string, sessionID string)
414412 if rsp.StatusCode != http.StatusOK {
415413 return nil, fmt.Errorf("failed to get messages: status code %d", rsp.StatusCode)
416414 }
417− var protoMsgs []proto.Message
418− if err := json.NewDecoder(rsp.Body).Decode(&protoMsgs); err != nil && !errors.Is(err, io.EOF) {
415+ var msgs []proto.Message
416+ if err := json.NewDecoder(rsp.Body).Decode(&msgs); err != nil && !errors.Is(err, io.EOF) {
419417 return nil, fmt.Errorf("failed to decode messages: %w", err)
420418 }
421− return protoToMessages(protoMsgs), nil
419+ return msgs, nil
422420}
423421
424−// GetSession retrieves a specific session.
425−func (c *Client) GetSession(ctx context.Context, id string, sessionID string) (*session.Session, error) {
422+// GetSession retrieves a specific session as a proto type.
423+func (c *Client) GetSession(ctx context.Context, id string, sessionID string) (*proto.Session, error) {
426424 rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/sessions/%s", id, sessionID), nil, nil)
427425 if err != nil {
428426 return nil, fmt.Errorf("failed to get session: %w", err)
@@ -431,15 +429,15 @@ func (c *Client) GetSession(ctx context.Context, id string, sessionID string) (*
431429 if rsp.StatusCode != http.StatusOK {
432430 return nil, fmt.Errorf("failed to get session: status code %d", rsp.StatusCode)
433431 }
434− var sess session.Session
432+ var sess proto.Session
435433 if err := json.NewDecoder(rsp.Body).Decode(&sess); err != nil {
436434 return nil, fmt.Errorf("failed to decode session: %w", err)
437435 }
438436 return &sess, nil
439437}
440438
441−// ListSessionHistoryFiles retrieves history files for a session.
442−func (c *Client) ListSessionHistoryFiles(ctx context.Context, id string, sessionID string) ([]history.File, error) {
439+// ListSessionHistoryFiles retrieves history files for a session as proto types.
440+func (c *Client) ListSessionHistoryFiles(ctx context.Context, id string, sessionID string) ([]proto.File, error) {
443441 rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/sessions/%s/history", id, sessionID), nil, nil)
444442 if err != nil {
445443 return nil, fmt.Errorf("failed to get session history files: %w", err)
@@ -448,16 +446,16 @@ func (c *Client) ListSessionHistoryFiles(ctx context.Context, id string, session
448446 if rsp.StatusCode != http.StatusOK {
449447 return nil, fmt.Errorf("failed to get session history files: status code %d", rsp.StatusCode)
450448 }
451− var files []history.File
449+ var files []proto.File
452450 if err := json.NewDecoder(rsp.Body).Decode(&files); err != nil {
453451 return nil, fmt.Errorf("failed to decode session history files: %w", err)
454452 }
455453 return files, nil
456454}
457455
458−// CreateSession creates a new session in a workspace.
459−func (c *Client) CreateSession(ctx context.Context, id string, title string) (*session.Session, error) {
460− rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/sessions", id), nil, jsonBody(session.Session{Title: title}), http.Header{"Content-Type": []string{"application/json"}})
456+// CreateSession creates a new session in a workspace as a proto type.
457+func (c *Client) CreateSession(ctx context.Context, id string, title string) (*proto.Session, error) {
458+ rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/sessions", id), nil, jsonBody(proto.Session{Title: title}), http.Header{"Content-Type": []string{"application/json"}})
461459 if err != nil {
462460 return nil, fmt.Errorf("failed to create session: %w", err)
463461 }
@@ -465,15 +463,15 @@ func (c *Client) CreateSession(ctx context.Context, id string, title string) (*s
465463 if rsp.StatusCode != http.StatusOK {
466464 return nil, fmt.Errorf("failed to create session: status code %d", rsp.StatusCode)
467465 }
468− var sess session.Session
466+ var sess proto.Session
469467 if err := json.NewDecoder(rsp.Body).Decode(&sess); err != nil {
470468 return nil, fmt.Errorf("failed to decode session: %w", err)
471469 }
472470 return &sess, nil
473471}
474472
475−// ListSessions lists all sessions in a workspace.
476−func (c *Client) ListSessions(ctx context.Context, id string) ([]session.Session, error) {
473+// ListSessions lists all sessions in a workspace as proto types.
474+func (c *Client) ListSessions(ctx context.Context, id string) ([]proto.Session, error) {
477475 rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/sessions", id), nil, nil)
478476 if err != nil {
479477 return nil, fmt.Errorf("failed to get sessions: %w", err)
@@ -482,7 +480,7 @@ func (c *Client) ListSessions(ctx context.Context, id string) ([]session.Session
482480 if rsp.StatusCode != http.StatusOK {
483481 return nil, fmt.Errorf("failed to get sessions: status code %d", rsp.StatusCode)
484482 }
485− var sessions []session.Session
483+ var sessions []proto.Session
486484 if err := json.NewDecoder(rsp.Body).Decode(&sessions); err != nil {
487485 return nil, fmt.Errorf("failed to decode sessions: %w", err)
488486 }
@@ -556,8 +554,8 @@ func jsonBody(v any) *bytes.Buffer {
556554 return b
557555}
558556
559−// SaveSession updates a session in a workspace.
560−func (c *Client) SaveSession(ctx context.Context, id string, sess session.Session) (*session.Session, error) {
557+// SaveSession updates a session in a workspace, returning a proto type.
558+func (c *Client) SaveSession(ctx context.Context, id string, sess proto.Session) (*proto.Session, error) {
561559 rsp, err := c.put(ctx, fmt.Sprintf("/workspaces/%s/sessions/%s", id, sess.ID), nil, jsonBody(sess), http.Header{"Content-Type": []string{"application/json"}})
562560 if err != nil {
563561 return nil, fmt.Errorf("failed to save session: %w", err)
@@ -566,7 +564,7 @@ func (c *Client) SaveSession(ctx context.Context, id string, sess session.Sessio
566564 if rsp.StatusCode != http.StatusOK {
567565 return nil, fmt.Errorf("failed to save session: status code %d", rsp.StatusCode)
568566 }
569− var saved session.Session
567+ var saved proto.Session
570568 if err := json.NewDecoder(rsp.Body).Decode(&saved); err != nil {
571569 return nil, fmt.Errorf("failed to decode session: %w", err)
572570 }
@@ -586,8 +584,8 @@ func (c *Client) DeleteSession(ctx context.Context, id string, sessionID string)
586584 return nil
587585}
588586
589−// ListUserMessages retrieves user-role messages for a session.
590−func (c *Client) ListUserMessages(ctx context.Context, id string, sessionID string) ([]message.Message, error) {
587+// ListUserMessages retrieves user-role messages for a session as proto types.
588+func (c *Client) ListUserMessages(ctx context.Context, id string, sessionID string) ([]proto.Message, error) {
591589 rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/sessions/%s/messages/user", id, sessionID), nil, nil)
592590 if err != nil {
593591 return nil, fmt.Errorf("failed to get user messages: %w", err)
@@ -596,15 +594,15 @@ func (c *Client) ListUserMessages(ctx context.Context, id string, sessionID stri
596594 if rsp.StatusCode != http.StatusOK {
597595 return nil, fmt.Errorf("failed to get user messages: status code %d", rsp.StatusCode)
598596 }
599− var protoMsgs []proto.Message
600− if err := json.NewDecoder(rsp.Body).Decode(&protoMsgs); err != nil && !errors.Is(err, io.EOF) {
597+ var msgs []proto.Message
598+ if err := json.NewDecoder(rsp.Body).Decode(&msgs); err != nil && !errors.Is(err, io.EOF) {
601599 return nil, fmt.Errorf("failed to decode user messages: %w", err)
602600 }
603− return protoToMessages(protoMsgs), nil
601+ return msgs, nil
604602}
605603
606−// ListAllUserMessages retrieves all user-role messages across sessions.
607−func (c *Client) ListAllUserMessages(ctx context.Context, id string) ([]message.Message, error) {
604+// ListAllUserMessages retrieves all user-role messages across sessions as proto types.
605+func (c *Client) ListAllUserMessages(ctx context.Context, id string) ([]proto.Message, error) {
608606 rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/messages/user", id), nil, nil)
609607 if err != nil {
610608 return nil, fmt.Errorf("failed to get all user messages: %w", err)
@@ -613,11 +611,11 @@ func (c *Client) ListAllUserMessages(ctx context.Context, id string) ([]message.
613611 if rsp.StatusCode != http.StatusOK {
614612 return nil, fmt.Errorf("failed to get all user messages: status code %d", rsp.StatusCode)
615613 }
616− var protoMsgs []proto.Message
617− if err := json.NewDecoder(rsp.Body).Decode(&protoMsgs); err != nil && !errors.Is(err, io.EOF) {
614+ var msgs []proto.Message
615+ if err := json.NewDecoder(rsp.Body).Decode(&msgs); err != nil && !errors.Is(err, io.EOF) {
618616 return nil, fmt.Errorf("failed to decode all user messages: %w", err)
619617 }
620− return protoToMessages(protoMsgs), nil
618+ return msgs, nil
621619}
622620
623621// CancelAgentSession cancels an ongoing agent operation for a session.
@@ -749,64 +747,3 @@ func (c *Client) LSPStopAll(ctx context.Context, id string) error {
749747 }
750748 return nil
751749}
752−
753−func protoToMessages(msgs []proto.Message) []message.Message {
754− out := make([]message.Message, len(msgs))
755− for i, m := range msgs {
756− out[i] = protoToMessage(m)
757− }
758− return out
759−}
760−
761−func protoToMessage(m proto.Message) message.Message {
762− msg := message.Message{
763− ID: m.ID,
764− SessionID: m.SessionID,
765− Role: message.MessageRole(m.Role),
766− Model: m.Model,
767− Provider: m.Provider,
768− CreatedAt: m.CreatedAt,
769− UpdatedAt: m.UpdatedAt,
770− }
771−
772− for _, p := range m.Parts {
773− switch v := p.(type) {
774− case proto.TextContent:
775− msg.Parts = append(msg.Parts, message.TextContent{Text: v.Text})
776− case proto.ReasoningContent:
777− msg.Parts = append(msg.Parts, message.ReasoningContent{
778− Thinking: v.Thinking,
779− Signature: v.Signature,
780− StartedAt: v.StartedAt,
781− FinishedAt: v.FinishedAt,
782− })
783− case proto.ToolCall:
784− msg.Parts = append(msg.Parts, message.ToolCall{
785− ID: v.ID,
786− Name: v.Name,
787− Input: v.Input,
788− Finished: v.Finished,
789− })
790− case proto.ToolResult:
791− msg.Parts = append(msg.Parts, message.ToolResult{
792− ToolCallID: v.ToolCallID,
793− Name: v.Name,
794− Content: v.Content,
795− IsError: v.IsError,
796− })
797− case proto.Finish:
798− msg.Parts = append(msg.Parts, message.Finish{
799− Reason: message.FinishReason(v.Reason),
800− Time: v.Time,
801− Message: v.Message,
802− Details: v.Details,
803− })
804− case proto.ImageURLContent:
805− msg.Parts = append(msg.Parts, message.ImageURLContent{URL: v.URL, Detail: v.Detail})
806− case proto.BinaryContent:
807− msg.Parts = append(msg.Parts, message.BinaryContent{Path: v.Path, MIMEType: v.MIMEType, Data: v.Data})
808− }
809− }
810−
811− return msg
812−}