From d601b752681028ea20fba95763d0d698d3f686d0 Mon Sep 17 00:00:00 2001 From: xp Date: Tue, 5 May 2026 19:36:09 +0800 Subject: [PATCH] fix(agent): send SVG attachments as files --- pkg/agent/agent_utils.go | 8 +++- pkg/agent/agent_utils_test.go | 76 +++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 pkg/agent/agent_utils_test.go diff --git a/pkg/agent/agent_utils.go b/pkg/agent/agent_utils.go index 2651fb2db..9228b6d55 100644 --- a/pkg/agent/agent_utils.go +++ b/pkg/agent/agent_utils.go @@ -285,6 +285,12 @@ func inferMediaType(filename, contentType string) string { ct := strings.ToLower(contentType) fn := strings.ToLower(filename) + // SVG is an image MIME type, but raster-only delivery endpoints such as + // Telegram SendPhoto reject it. Treat it as a file/document instead. + if strings.HasPrefix(ct, "image/svg") || filepath.Ext(fn) == ".svg" { + return "file" + } + if strings.HasPrefix(ct, "image/") { return "image" } @@ -298,7 +304,7 @@ func inferMediaType(filename, contentType string) string { // Fallback: infer from extension ext := filepath.Ext(fn) switch ext { - case ".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".svg": + case ".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp": return "image" case ".mp3", ".wav", ".ogg", ".m4a", ".flac", ".aac", ".wma", ".opus": return "audio" diff --git a/pkg/agent/agent_utils_test.go b/pkg/agent/agent_utils_test.go new file mode 100644 index 000000000..6612a60b3 --- /dev/null +++ b/pkg/agent/agent_utils_test.go @@ -0,0 +1,76 @@ +package agent + +import "testing" + +func TestInferMediaType(t *testing.T) { + tests := []struct { + name string + filename string + contentType string + want string + }{ + { + name: "png content type", + filename: "diagram", + contentType: "image/png", + want: "image", + }, + { + name: "jpeg extension fallback", + filename: "photo.JPG", + contentType: "", + want: "image", + }, + { + name: "svg content type is file", + filename: "diagram", + contentType: "image/svg+xml", + want: "file", + }, + { + name: "svg content type with parameters is file", + filename: "diagram", + contentType: "image/svg+xml; charset=utf-8", + want: "file", + }, + { + name: "svg extension fallback is file", + filename: "diagram.SVG", + contentType: "", + want: "file", + }, + { + name: "audio content type", + filename: "voice", + contentType: "audio/ogg", + want: "audio", + }, + { + name: "ogg application content type", + filename: "voice.ogg", + contentType: "application/ogg", + want: "audio", + }, + { + name: "video extension fallback", + filename: "clip.MP4", + contentType: "", + want: "video", + }, + { + name: "unknown type", + filename: "archive.bin", + contentType: "application/octet-stream", + want: "file", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := inferMediaType(tt.filename, tt.contentType) + if got != tt.want { + t.Fatalf("inferMediaType(%q, %q) = %q, want %q", tt.filename, tt.contentType, got, tt.want) + } + }) + } +}