package agent import ( "errors" "strings" "testing" "git.gopher.ink/mirrors2/AutoZero/llm" ) // TestTruncateSpillSavesAndReferences:截断时把原文落盘并在提示里给出可读路径。 func TestTruncateSpillSavesAndReferences(t *testing.T) { long := "HEAD" + strings.Repeat("m", 50000) + "TAIL" msgs := []llm.Message{{Role: llm.RoleTool, ToolCallID: "call-1", Content: long}} var gotID, gotFull string spillFn := func(callID, full string) (string, error) { gotID, gotFull = callID, full return "/tmp/results/call-1.txt", nil } view := truncateToolResultsSpill(msgs, 20000, spillFn) if gotID != "call-1" { t.Errorf("spillFn got callID %q, want call-1", gotID) } if gotFull != long { t.Errorf("spillFn must receive the full original text (got %d bytes, want %d)", len(gotFull), len(long)) } content := view[0].Content if !strings.Contains(content, "/tmp/results/call-1.txt") { t.Errorf("notice should reference the spilled path:\n%s", content) } if !strings.Contains(content, "use the read tool") { t.Errorf("notice should tell the model how to retrieve it:\n%s", content) } if !strings.Contains(content, "[truncated") { t.Errorf("notice should mention truncation:\n%s", content) } if len(content) > 20000 { t.Errorf("truncated content too long: %d", len(content)) } // transcript(传入的切片)不能被修改。 if msgs[0].Content != long { t.Error("original message must not be mutated") } } // TestTruncateSpillFailureDegrades:落盘失败时退回"重跑工具"提示,不 panic。 func TestTruncateSpillFailureDegrades(t *testing.T) { msgs := []llm.Message{{Role: llm.RoleTool, ToolCallID: "c", Content: strings.Repeat("b", 50000)}} view := truncateToolResultsSpill(msgs, 20000, func(_, _ string) (string, error) { return "", errors.New("disk full") }) if strings.Contains(view[0].Content, "full output saved") { t.Errorf("failed spill must not advertise a path:\n%s", view[0].Content) } if !strings.Contains(view[0].Content, "narrower query") { t.Errorf("failed spill should fall back to the rerun hint:\n%s", view[0].Content) } }