Image input
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -359,10 +360,34 @@ func (s *Session) ID() string {
|
||||
return s.id
|
||||
}
|
||||
|
||||
func (s *Session) Send(text string) error {
|
||||
type Image struct {
|
||||
MediaType string
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func (s *Session) Send(text string, images ...Image) error {
|
||||
var content any = text
|
||||
if len(images) > 0 {
|
||||
blocks := []map[string]any{}
|
||||
for _, img := range images {
|
||||
blocks = append(blocks, map[string]any{
|
||||
"type": "image",
|
||||
"source": map[string]any{
|
||||
"type": "base64",
|
||||
"media_type": img.MediaType,
|
||||
"data": base64.StdEncoding.EncodeToString(img.Data),
|
||||
},
|
||||
})
|
||||
}
|
||||
if text != "" {
|
||||
blocks = append(blocks, map[string]any{"type": "text", "text": text})
|
||||
}
|
||||
content = blocks
|
||||
}
|
||||
|
||||
return s.write(map[string]any{
|
||||
"type": "user",
|
||||
"message": map[string]any{"role": "user", "content": text},
|
||||
"message": map[string]any{"role": "user", "content": content},
|
||||
"parent_tool_use_id": nil,
|
||||
"session_id": s.ID(),
|
||||
})
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
package claude_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"image/png"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -198,6 +203,30 @@ func TestInterrupt(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageInput(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := testContext(t)
|
||||
s := start(t, ctx, claude.Options{Cwd: scratchRepo(t)})
|
||||
|
||||
img := image.NewRGBA(image.Rect(0, 0, 64, 64))
|
||||
draw.Draw(img, img.Bounds(), &image.Uniform{C: color.RGBA{R: 255, A: 255}}, image.Point{}, draw.Src)
|
||||
buf := bytes.Buffer{}
|
||||
err := png.Encode(&buf, img)
|
||||
if err != nil {
|
||||
t.Fatalf("encode png: %v", err)
|
||||
}
|
||||
|
||||
err = s.Send("Without using any tools, what single colour fills the attached image? Reply with just the colour name.", claude.Image{MediaType: "image/png", Data: buf.Bytes()})
|
||||
if err != nil {
|
||||
t.Fatalf("send: %v", err)
|
||||
}
|
||||
text := waitResult(t, ctx, s, nil)
|
||||
|
||||
if !strings.Contains(strings.ToLower(text), "red") {
|
||||
t.Fatalf("model didn't see the image; assistant said %q", text)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResume(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := testContext(t)
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user