Merge branch 'sipeed:main' into main
This commit is contained in:
commit
9870f46180
4 changed files with 150 additions and 4 deletions
|
|
@ -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"
|
||||
|
|
|
|||
76
pkg/agent/agent_utils_test.go
Normal file
76
pkg/agent/agent_utils_test.go
Normal file
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -602,8 +602,8 @@ func (e *CompactionEngine) generateLeafSummary(
|
|||
}
|
||||
}
|
||||
|
||||
// Check if level 1 succeeded
|
||||
if content != "" && tokenizer.EstimateMessageTokens(providers.Message{Content: content}) < inputTokens {
|
||||
// Level 1 only succeeds if it actually reaches the requested target size.
|
||||
if content != "" && tokenizer.EstimateMessageTokens(providers.Message{Content: content}) <= targetTokens {
|
||||
return content, nil
|
||||
}
|
||||
|
||||
|
|
@ -627,7 +627,7 @@ func (e *CompactionEngine) generateLeafSummary(
|
|||
return "", err
|
||||
}
|
||||
}
|
||||
if content != "" && tokenizer.EstimateMessageTokens(providers.Message{Content: content}) < inputTokens {
|
||||
if content != "" && tokenizer.EstimateMessageTokens(providers.Message{Content: content}) <= aggressiveTarget {
|
||||
return content, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package seahorse
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
|
|
@ -697,6 +698,69 @@ func TestGenerateLeafSummaryEscalationToAggressive(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGenerateLeafSummaryEscalatesWhenLevel1MissesTarget(t *testing.T) {
|
||||
var calls []string
|
||||
normalContent := strings.Repeat("n", 1000) // ~404 tokens: below input, above target
|
||||
aggressiveContent := strings.Repeat("a", 450) // ~184 tokens: within aggressive target
|
||||
escalateComplete := func(ctx context.Context, prompt string, opts CompleteOptions) (string, error) {
|
||||
if contains(prompt, "Aggressive summary policy") {
|
||||
calls = append(calls, "aggressive")
|
||||
return aggressiveContent, nil
|
||||
}
|
||||
calls = append(calls, "normal")
|
||||
return normalContent, nil
|
||||
}
|
||||
|
||||
s := openTestStore(t)
|
||||
ce, _ := newTestCompactionEngineWithStore(s, escalateComplete)
|
||||
|
||||
msgs := []Message{
|
||||
{Role: "user", Content: "hello world", TokenCount: 500},
|
||||
{Role: "assistant", Content: "response", TokenCount: 500},
|
||||
}
|
||||
|
||||
content, err := ce.generateLeafSummary(context.Background(), msgs, "")
|
||||
if err != nil {
|
||||
t.Fatalf("generateLeafSummary: %v", err)
|
||||
}
|
||||
if content != aggressiveContent {
|
||||
t.Fatalf("expected aggressive summary after level 1 missed target")
|
||||
}
|
||||
if len(calls) != 2 || calls[0] != "normal" || calls[1] != "aggressive" {
|
||||
t.Fatalf("expected normal then aggressive calls, got %v", calls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateLeafSummaryAcceptsContentAtTargetBoundary(t *testing.T) {
|
||||
exactTargetContent := strings.Repeat("x", 488) // (488 + 12) * 2 / 5 = 200 tokens
|
||||
var aggressiveCalled bool
|
||||
complete := func(ctx context.Context, prompt string, opts CompleteOptions) (string, error) {
|
||||
if contains(prompt, "Aggressive summary policy") {
|
||||
aggressiveCalled = true
|
||||
}
|
||||
return exactTargetContent, nil
|
||||
}
|
||||
|
||||
s := openTestStore(t)
|
||||
ce, _ := newTestCompactionEngineWithStore(s, complete)
|
||||
|
||||
msgs := []Message{
|
||||
{Role: "user", Content: "hello world", TokenCount: 286},
|
||||
{Role: "assistant", Content: "response", TokenCount: 286},
|
||||
}
|
||||
|
||||
content, err := ce.generateLeafSummary(context.Background(), msgs, "")
|
||||
if err != nil {
|
||||
t.Fatalf("generateLeafSummary: %v", err)
|
||||
}
|
||||
if content != exactTargetContent {
|
||||
t.Fatalf("expected level 1 summary at target boundary to be accepted")
|
||||
}
|
||||
if aggressiveCalled {
|
||||
t.Fatal("did not expect aggressive retry when level 1 hit target exactly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateLeafSummaryEscalationToTruncation(t *testing.T) {
|
||||
// Both normal and aggressive return empty, should escalate to level 3 truncation
|
||||
emptyComplete := func(ctx context.Context, prompt string, opts CompleteOptions) (string, error) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue