+package main
+
+import (
+ "encoding/json"
+ "net/http"
+ "path/filepath"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestImageShowUsesStoredImageForTelegramAndTerminal(t *testing.T) {
+ picture := imageTestPNG(t, 5, 4)
+ store := &ImageStore{dir: filepath.Join(t.TempDir(), imageDirName)}
+ name, err := store.Save(picture)
+ require.NoError(t, err)
+
+ telegram := newTelegramFake(t)
+ bot, logs := telegramStartTestBot(t, telegram)
+ box := &Toolbox{imageShow: &ImageShow{
+ store: store,
+ bot: bot,
+ }}
+ args, err := json.Marshal(ToolImageShowArguments{
+ Image: name,
+ Caption: "A red point.",
+ })
+ require.NoError(t, err)
+
+ output := box.run(t.Context(), "image_show", string(args))
+ require.Equal(t, imageText([]string{name}, "A red point.")+"\n"+filepath.Join(store.dir, name), output)
+
+ calls := telegram.Calls()
+ require.Len(t, calls, 1)
+ require.Equal(t, "sendPhoto", calls[0].method)
+ require.Equal(t, "4242", calls[0].params["chat_id"])
+ require.Equal(t, "A red point.", calls[0].params["caption"])
+ require.Equal(t, name, calls[0].params["photo_name"])
+ require.Equal(t, picture, calls[0].params["photo"])
+ require.Empty(t, logs.String())
+}
+
+func TestImageShowRefusesUnknownNamesBeforeSending(t *testing.T) {
+ telegram := newTelegramFake(t)
+ bot, _ := telegramStartTestBot(t, telegram)
+ show := &ImageShow{
+ store: &ImageStore{dir: t.TempDir()},
+ bot: bot,
+ }
+
+ for _, name := range []string{"../image.png", "unknown", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.png"} {
+ _, err := show.Show(t.Context(), name, "Do not send this.")
+ require.Error(t, err)
+ }
+
+ require.Empty(t, telegram.Calls())
+
+ box := &Toolbox{}
+ require.Equal(t, `error: unknown tool "image_show"`, box.run(t.Context(), "image_show", `{"image":"unknown","caption":""}`))
+}
+
+func TestImageShowFallsBackOnlyWhenTelegramRefusesPhoto(t *testing.T) {
+ testCases := []struct {
+ name string
+ status int
+ methods []string
+ failure bool
+ }{
+ {
+ name: "refused photo sends document",
+ status: http.StatusBadRequest,
+ methods: []string{"sendPhoto", "sendDocument"},
+ },
+ {
+ name: "uncertain server error does not send twice",
+ status: http.StatusBadGateway,
+ methods: []string{"sendPhoto"},
+ failure: true,
+ },
+ }
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ telegram := newTelegramFake(t)
+ telegram.fail = func(call TelegramFakeCall) (int, string) {
+ if call.method == "sendPhoto" {
+ return tc.status, "photo refused"
+ }
+
+ return 0, ""
+ }
+ store := &ImageStore{dir: t.TempDir()}
+ picture := imageTestPNG(t, 3, 3)
+ name, err := store.Save(picture)
+ require.NoError(t, err)
+
+ bot, _ := telegramStartTestBot(t, telegram)
+ show := &ImageShow{
+ store: store,
+ bot: bot,
+ }
+ _, err = show.Show(t.Context(), name, "Caption")
+ if tc.failure {
+ require.Error(t, err)
+ } else {
+ require.NoError(t, err)
+ }
+
+ var methods []string
+
+ for _, call := range telegram.Calls() {
+ methods = append(methods, call.method)
+ if call.method == "sendDocument" {
+ require.Equal(t, picture, call.params["document"])
+ require.Equal(t, name, call.params["document_name"])
+ require.Equal(t, "Caption", call.params["caption"])
+ }
+ }
+
+ require.Equal(t, tc.methods, methods)
+ })
+ }
+}
+
+func TestAgentShowsImageInTerminalWithoutTelegram(t *testing.T) {
+ server := newModelFake(t)
+ test := newTestTurnLoop(t, server)
+ name, err := test.agent.Images().Save(imageTestPNG(t, 2, 2))
+ require.NoError(t, err)
+
+ output := test.loop.tools.run(t.Context(), "image_show", `{"image":"`+name+`","caption":"Here it is."}`)
+ require.Equal(t, imageText([]string{name}, "Here it is.")+"\n"+filepath.Join(test.agent.Images().dir, name), output)
+ require.Contains(t, terminalEventText(Event{
+ Kind: "echo",
+ Text: output,
+ }), filepath.Join(test.agent.Images().dir, name))
+}