83 lines
2.9 KiB
Go
83 lines
2.9 KiB
Go
|
|
package application
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
"unicode/utf8"
|
||
|
|
|
||
|
|
"img_infinite_canvas/internal/domain/design"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestAgentShortMemoryUsesSlidingWindow(t *testing.T) {
|
||
|
|
now := time.Now()
|
||
|
|
project := design.Project{Title: "Memory project"}
|
||
|
|
for index := 0; index < 24; index++ {
|
||
|
|
project.Messages = append(project.Messages, design.Message{
|
||
|
|
ID: fmt.Sprintf("m-%d", index),
|
||
|
|
Role: "user",
|
||
|
|
Type: "user",
|
||
|
|
Content: fmt.Sprintf("历史消息 %02d 需要保留高级品牌风格", index),
|
||
|
|
CreatedAt: now.Add(time.Duration(index) * time.Second),
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
memory := buildAgentMemory(project, "继续优化当前画面", "design", nil)
|
||
|
|
if !strings.Contains(memory.ShortTerm, "历史消息 23") {
|
||
|
|
t.Fatalf("expected latest message in short memory, got %s", memory.ShortTerm)
|
||
|
|
}
|
||
|
|
if strings.Contains(memory.ShortTerm, "历史消息 00") {
|
||
|
|
t.Fatalf("expected oldest message to be outside sliding window, got %s", memory.ShortTerm)
|
||
|
|
}
|
||
|
|
if utf8.RuneCountInString(memory.ShortTerm) > shortMemoryMaxRunes+80 {
|
||
|
|
t.Fatalf("short memory exceeds budget: %d", utf8.RuneCountInString(memory.ShortTerm))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAgentMemoryDoesNotLeakRawAssetURLs(t *testing.T) {
|
||
|
|
project := design.Project{
|
||
|
|
Title: "Asset memory",
|
||
|
|
Nodes: []design.Node{
|
||
|
|
{ID: "image-1", Type: design.NodeTypeImage, Title: "参考图", Content: "http://localhost:19000/canvas-assets/raw.png", Status: "success"},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
memory := buildAgentMemory(project, "参考这张图继续", "image", []design.AgentChatMessage{
|
||
|
|
{
|
||
|
|
Contents: []design.AgentContent{
|
||
|
|
{Type: "image", ImageURL: "https://example.com/private/upload.png", ImageWidth: 1024, ImageHeight: 1024},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
})
|
||
|
|
joined := memory.ShortTerm + "\n" + memory.LongTerm
|
||
|
|
if strings.Contains(joined, "localhost:19000") || strings.Contains(joined, "example.com/private") {
|
||
|
|
t.Fatalf("expected raw asset urls to be omitted from memory, got %s", joined)
|
||
|
|
}
|
||
|
|
if !strings.Contains(joined, "reference image") || !strings.Contains(joined, "asset reference") {
|
||
|
|
t.Fatalf("expected compact asset references, got %s", joined)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAgentLongMemoryKeepsRecentDurableDecisions(t *testing.T) {
|
||
|
|
project := design.Project{Title: "Long memory"}
|
||
|
|
for index := 0; index < 20; index++ {
|
||
|
|
project.Messages = append(project.Messages, design.Message{
|
||
|
|
ID: fmt.Sprintf("d-%d", index),
|
||
|
|
Role: "user",
|
||
|
|
Type: "user",
|
||
|
|
Content: fmt.Sprintf("必须保留品牌风格决定 %02d", index),
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
memory := buildAgentMemory(project, "继续", "design", nil)
|
||
|
|
if !strings.Contains(memory.LongTerm, "品牌风格决定 19") {
|
||
|
|
t.Fatalf("expected recent durable decision in long memory, got %s", memory.LongTerm)
|
||
|
|
}
|
||
|
|
if strings.Contains(memory.LongTerm, "品牌风格决定 00") {
|
||
|
|
t.Fatalf("expected oldest durable decision to be omitted, got %s", memory.LongTerm)
|
||
|
|
}
|
||
|
|
if utf8.RuneCountInString(memory.LongTerm) > longMemoryMaxRunes+80 {
|
||
|
|
t.Fatalf("long memory exceeds budget: %d", utf8.RuneCountInString(memory.LongTerm))
|
||
|
|
}
|
||
|
|
}
|