Why: Old tool results were filling the window, compaction could split a tool group or commit a stale summary, and reminders arrived as extra user messages. Evidence: Compaction retries a conflict and opens the circuit after three failures; clearing keeps the last five tool results; a stale file write is rejected; RPC reports started, queued, or handled. Impact: Requests over the context window replace older tool results with a placeholder. Rewriting an existing file now requires a read in the same run. Subagent text over 32000 characters is capped. Refs: feature/context-engineering Co-authored-by: Cursor <cursoragent@cursor.com>
61 lines
1.7 KiB
Go
61 lines
1.7 KiB
Go
package session
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"agent-native/runtime/llm"
|
|
)
|
|
|
|
func TestClearOldToolResultsKeepsLastFive(t *testing.T) {
|
|
var msgs []llm.Message
|
|
for i := 0; i < 8; i++ {
|
|
id := string(rune('a' + i))
|
|
msgs = append(msgs,
|
|
llm.Message{Role: llm.RoleAssistant, ToolCalls: []llm.ToolCall{{ID: id, Name: "read_file"}}},
|
|
llm.Message{Role: llm.RoleTool, Name: "read_file", ToolCallID: id, Content: "正文-" + id},
|
|
)
|
|
}
|
|
out := ClearOldToolResults(msgs, 5)
|
|
if len(out) != len(msgs) {
|
|
t.Fatalf("len %d, want %d", len(out), len(msgs))
|
|
}
|
|
cleared := 0
|
|
for i, m := range out {
|
|
if m.Role != llm.RoleTool {
|
|
if m.Role != msgs[i].Role || len(m.ToolCalls) != len(msgs[i].ToolCalls) {
|
|
t.Fatalf("pairing changed at %d", i)
|
|
}
|
|
continue
|
|
}
|
|
if m.ToolCallID != msgs[i].ToolCallID {
|
|
t.Fatalf("tool id changed at %d", i)
|
|
}
|
|
if strings.Contains(m.Content, "旧工具结果已清理") {
|
|
cleared++
|
|
if !strings.Contains(m.Content, m.ToolCallID) {
|
|
t.Fatalf("placeholder missing call id: %s", m.Content)
|
|
}
|
|
} else if m.Content != msgs[i].Content {
|
|
t.Fatalf("recent result changed: %s", m.Content)
|
|
}
|
|
}
|
|
if cleared != 3 {
|
|
t.Fatalf("cleared %d, want 3", cleared)
|
|
}
|
|
for _, m := range out[len(out)-10:] {
|
|
if m.Role == llm.RoleTool && strings.Contains(m.Content, "旧工具结果已清理") {
|
|
t.Fatalf("last five were cleared: %s", m.ToolCallID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNeedsClearUsesConservativeWindow(t *testing.T) {
|
|
if NeedsClear(10, 0, 0, 0) {
|
|
t.Fatal("small estimate must fit the default window")
|
|
}
|
|
if !NeedsClear(DefaultContextWindow, 0, DefaultOutputReserve, DefaultContextBuffer) {
|
|
t.Fatal("estimate at the default window must clear")
|
|
}
|
|
}
|