| 1 | package agent |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "testing" |
| 6 | |
| 7 | "reasonix/internal/attachment" |
| 8 | "reasonix/internal/provider" |
| 9 | "reasonix/internal/tool" |
| 10 | ) |
| 11 | |
| 12 | type urlImageResolver struct{} |
| 13 | |
| 14 | func (urlImageResolver) ResolveRequestImages(_ context.Context, msgs []provider.Message) ([]provider.Message, error) { |
| 15 | out := append([]provider.Message(nil), msgs...) |
| 16 | for i := range out { |
| 17 | if len(out[i].ImageInputs) == 0 { |
| 18 | continue |
| 19 | } |
| 20 | images := make([]string, 0, len(out[i].ImageInputs)) |
| 21 | for _, in := range out[i].ImageInputs { |
| 22 | if in.Kind == attachment.KindURL { |
| 23 | images = append(images, in.URL) |
| 24 | } |
| 25 | } |
| 26 | out[i].Images = images |
| 27 | out[i].ImageInputs = nil |
| 28 | } |
| 29 | return out, nil |
| 30 | } |
| 31 | |
| 32 | func (urlImageResolver) PersistToolImages(context.Context, []string) ([]attachment.ImageInput, error) { |
| 33 | return nil, nil |
| 34 | } |
| 35 | |
| 36 | func TestTaskToolPropagatesSubagentImageInputsWithoutCombiningImages(t *testing.T) { |
| 37 | sub := &mockProvider{name: "sub", chunks: []provider.Chunk{ |
| 38 | {Type: provider.ChunkText, Text: "image received"}, |
| 39 | {Type: provider.ChunkDone}, |
| 40 | }} |
| 41 | task := newTestTaskTool(t, sub, tool.NewRegistry(), "sys", "", "", nil).WithImageRequestResolver(urlImageResolver{}) |
| 42 | inputs := []attachment.ImageInput{{Kind: attachment.KindURL, URL: "https://example.invalid/shot.png"}} |
| 43 | ctx := WithSubagentImageInputs(testTaskContext(), inputs) |
| 44 | ctx = WithSubagentImageCandidates(ctx, []string{"data:image/png;base64,AAAA"}) |
| 45 | if _, err := task.Execute(ctx, []byte(`{"prompt":"inspect the attached image"}`)); err != nil { |
| 46 | t.Fatalf("Execute: %v", err) |
| 47 | } |
| 48 | var got provider.Message |
| 49 | for _, msg := range sub.lastReq.Messages { |
| 50 | if msg.Role == provider.RoleUser { |
| 51 | got = msg |
| 52 | } |
| 53 | } |
| 54 | if len(got.Images) != 1 || got.Images[0] != "https://example.invalid/shot.png" { |
| 55 | t.Fatalf("sub-agent images = %v, want the resolved ImageInput URL", got.Images) |
| 56 | } |
| 57 | if len(got.ImageInputs) != 0 { |
| 58 | t.Fatalf("request ImageInputs = %+v, want resolved away", got.ImageInputs) |
| 59 | } |
| 60 | } |
| 61 |