Skip to content

Commit dd15131

Browse files
authored
Merge pull request #2449 from rumpl/fix-attach-without-message
Fix --attach flag
2 parents 45be5d1 + 97e9a42 commit dd15131

File tree

2 files changed

+39
-8
lines changed

2 files changed

+39
-8
lines changed

cmd/root/run.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,11 @@ func (f *runExecFlags) buildAppOpts(args []string) ([]app.Opt, error) {
485485
var opts []app.Opt
486486
if firstMessage != nil {
487487
opts = append(opts, app.WithFirstMessage(*firstMessage))
488+
} else if f.attachmentPath != "" {
489+
// When --attach is used without an explicit message, provide a default
490+
// so that SendFirstMessage processes the attachment.
491+
defaultMsg := ""
492+
opts = append(opts, app.WithFirstMessage(defaultMsg))
488493
}
489494
if len(args) > 2 {
490495
opts = append(opts, app.WithQueuedMessages(args[2:]))

pkg/cli/runner.go

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cli
33
import (
44
"cmp"
55
"context"
6+
"encoding/base64"
67
"encoding/json"
78
"errors"
89
"fmt"
@@ -436,19 +437,44 @@ func CreateUserMessageWithAttachment(userContent, attachmentPath string) *sessio
436437
})
437438

438439
default:
439-
// Binary files (images, PDFs) are kept as file references.
440+
// Binary files (images, PDFs) are handled based on type.
440441
mimeType := chat.DetectMimeType(absPath)
441442
if !chat.IsSupportedMimeType(mimeType) {
442443
slog.Warn("Unsupported attachment file type", "path", absPath, "mime_type", mimeType)
443444
return session.UserMessage(userContent)
444445
}
445-
multiContent = append(multiContent, chat.MessagePart{
446-
Type: chat.MessagePartTypeFile,
447-
File: &chat.MessageFile{
448-
Path: absPath,
449-
MimeType: mimeType,
450-
},
451-
})
446+
if chat.IsImageMimeType(mimeType) {
447+
// Read, resize if needed, and inline as base64 data URL.
448+
// This ensures cross-provider compatibility (not all providers
449+
// support file references).
450+
imgData, readErr := os.ReadFile(absPath)
451+
if readErr != nil {
452+
slog.Warn("Failed to read image attachment", "path", absPath, "error", readErr)
453+
return session.UserMessage(userContent)
454+
}
455+
resized, resizeErr := chat.ResizeImage(imgData, mimeType)
456+
if resizeErr != nil {
457+
slog.Warn("Image resize failed for attachment", "path", absPath, "error", resizeErr)
458+
return session.UserMessage(userContent)
459+
}
460+
dataURL := fmt.Sprintf("data:%s;base64,%s", resized.MimeType, base64.StdEncoding.EncodeToString(resized.Data))
461+
multiContent = append(multiContent, chat.MessagePart{
462+
Type: chat.MessagePartTypeImageURL,
463+
ImageURL: &chat.MessageImageURL{
464+
URL: dataURL,
465+
Detail: chat.ImageURLDetailAuto,
466+
},
467+
})
468+
} else {
469+
// Non-image binary files (e.g. PDFs) are kept as file references.
470+
multiContent = append(multiContent, chat.MessagePart{
471+
Type: chat.MessagePartTypeFile,
472+
File: &chat.MessageFile{
473+
Path: absPath,
474+
MimeType: mimeType,
475+
},
476+
})
477+
}
452478
}
453479

454480
return session.UserMessage(textContent, multiContent...)

0 commit comments

Comments
 (0)