on main help sign in
fix(server): support attachments in client-server mode
commit27a35c94cc1496bd4a2f5fdb4e398427815a4715 authorChristian Rocha <christian@rocha.is> dateTue 19 May 2026, 17:57 (5 months ago) parent8468c8c
3 files changed+44−11
internal/backend/agent.go+1−1 internal/client/proto.go+1−10 internal/proto/message.go+42
internal/backend/agent.go+1−1
@@ -19,7 +19,7 @@ func (b *Backend) SendMessage(ctx context.Context, workspaceID string, msg proto
1919 return ErrAgentNotInitialized
2020 }
2121
22− _, err = ws.AgentCoordinator.Run(ctx, msg.SessionID, msg.Prompt)
22+ _, err = ws.AgentCoordinator.Run(ctx, msg.SessionID, msg.Prompt, proto.AttachmentsToMessage(msg.Attachments)...)
2323 return err
2424}
2525
internal/client/proto.go+1−10
@@ -335,19 +335,10 @@ func (c *Client) UpdateAgent(ctx context.Context, id string) error {
335335
336336// SendMessage sends a message to the agent for a workspace.
337337func (c *Client) SendMessage(ctx context.Context, id string, sessionID, prompt string, attachments ...message.Attachment) error {
338− protoAttachments := make([]proto.Attachment, len(attachments))
339− for i, a := range attachments {
340− protoAttachments[i] = proto.Attachment{
341− FilePath: a.FilePath,
342− FileName: a.FileName,
343− MimeType: a.MimeType,
344− Content: a.Content,
345− }
346− }
347338 rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/agent", id), nil, jsonBody(proto.AgentMessage{
348339 SessionID: sessionID,
349340 Prompt: prompt,
350− Attachments: protoAttachments,
341+ Attachments: proto.AttachmentsFromMessage(attachments),
351342 }), http.Header{"Content-Type": []string{"application/json"}})
352343 if err != nil {
353344 return fmt.Errorf("failed to send message to agent: %w", err)
internal/proto/message.go+42
@@ -8,6 +8,7 @@ import (
88 "time"
99
1010 "charm.land/catwalk/pkg/catwalk"
11+ "github.com/charmbracelet/crush/internal/message"
1112)
1213
1314// CreateMessageParams represents parameters for creating a message.
@@ -621,6 +622,47 @@ type Attachment struct {
621622 Content []byte `json:"content"`
622623}
623624
625+// ToMessage converts a proto Attachment to a [message.Attachment].
626+func (a Attachment) ToMessage() message.Attachment {
627+ return message.Attachment{
628+ FilePath: a.FilePath,
629+ FileName: a.FileName,
630+ MimeType: a.MimeType,
631+ Content: a.Content,
632+ }
633+}
634+
635+// AttachmentFromMessage converts a [message.Attachment] to a proto
636+// Attachment.
637+func AttachmentFromMessage(a message.Attachment) Attachment {
638+ return Attachment{
639+ FilePath: a.FilePath,
640+ FileName: a.FileName,
641+ MimeType: a.MimeType,
642+ Content: a.Content,
643+ }
644+}
645+
646+// AttachmentsToMessage converts a slice of proto Attachments to a slice
647+// of [message.Attachment].
648+func AttachmentsToMessage(as []Attachment) []message.Attachment {
649+ out := make([]message.Attachment, len(as))
650+ for i, a := range as {
651+ out[i] = a.ToMessage()
652+ }
653+ return out
654+}
655+
656+// AttachmentsFromMessage converts a slice of [message.Attachment] to a
657+// slice of proto Attachments.
658+func AttachmentsFromMessage(as []message.Attachment) []Attachment {
659+ out := make([]Attachment, len(as))
660+ for i, a := range as {
661+ out[i] = AttachmentFromMessage(a)
662+ }
663+ return out
664+}
665+
624666// MarshalJSON implements the [json.Marshaler] interface.
625667func (a Attachment) MarshalJSON() ([]byte, error) {
626668 type Alias Attachment