Files
nofx/agent/clear_memory_test.go
2026-04-25 16:18:45 +08:00

117 lines
3.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package agent
import (
"context"
"log/slog"
"path/filepath"
"strings"
"testing"
"nofx/store"
)
func TestClearRemovesActiveAndPendingConversationState(t *testing.T) {
dbPath := filepath.Join(t.TempDir(), "agent-clear.db")
st, err := store.New(dbPath)
if err != nil {
t.Fatalf("create store: %v", err)
}
a := New(nil, st, DefaultConfig(), slog.Default())
userID := int64(42)
a.history.Add(userID, "assistant", "之前的回复")
_ = a.saveTaskState(userID, TaskState{CurrentGoal: "配置模型"})
a.saveActiveSkillSession(ActiveSkillSession{
SessionID: "as_test",
UserID: userID,
SkillName: "model_management",
ActionName: "create",
PendingHint: &PendingHint{
Prompt: "请选择 provider",
HintType: "question",
},
})
a.savePendingProposalSession(PendingProposalSession{
UserID: userID,
SourceUserText: "帮我配置模型",
ProposalText: "推荐 claw402你要继续吗",
})
a.saveSetupState(userID, &SetupState{
Step: "await_ai_model",
AIProvider: "claw402",
})
if err := st.SetSystemConfig(skillSessionConfigKey(userID), `{"name":"model_management","action":"create"}`); err != nil {
t.Fatalf("seed skill session: %v", err)
}
a.saveWorkflowSession(userID, WorkflowSession{
Tasks: []WorkflowTask{{
ID: "task_1",
Skill: "model_management",
Action: "create",
Request: "帮我配置模型",
Status: workflowTaskPending,
}},
})
if err := st.SetSystemConfig(ExecutionStateConfigKey(userID), `{"user_id":42,"session_id":"exec_1"}`); err != nil {
t.Fatalf("seed execution state: %v", err)
}
a.saveReferenceMemory(userID, &CurrentReferences{
Model: &EntityReference{ID: "m1", Name: "claw402", Source: "context"},
}, nil)
a.SnapshotManager(userID).Save(SuspendedTask{ResumeHint: "旧任务"})
reply, err := a.HandleMessage(context.Background(), userID, "/clear")
if err != nil {
t.Fatalf("clear returned error: %v", err)
}
if reply == "" {
t.Fatalf("expected clear reply")
}
if got := a.history.Get(userID); len(got) != 0 {
t.Fatalf("history not cleared: %+v", got)
}
if got := a.buildRecentConversationContext(userID, "你好"); got != "" {
t.Fatalf("recent conversation context not cleared: %q", got)
}
if got := a.currentPendingHintText(userID); got != "" {
t.Fatalf("pending hint not cleared: %q", got)
}
if got := a.buildCurrentTurnContext(userID, "zh", "你好"); got != "" {
if strings.Contains(got, "Previous assistant reply:") || strings.Contains(got, "Recent conversation:") {
t.Fatalf("current turn context still contains prior chat memory: %q", got)
}
}
if got := a.buildActiveTaskStateContext(userID, "zh"); got != "" {
t.Fatalf("active task state context not cleared: %q", got)
}
if state := a.getTaskState(userID); state.CurrentGoal != "" || state.ActiveFlow != "" {
t.Fatalf("task state not cleared: %+v", state)
}
if _, ok := a.getActiveSkillSession(userID); ok {
t.Fatalf("active skill session not cleared")
}
if _, ok := a.getPendingProposalSession(userID); ok {
t.Fatalf("pending proposal session not cleared")
}
if session := a.getSkillSession(userID); session.Name != "" {
t.Fatalf("legacy skill session not cleared: %+v", session)
}
if session := a.getWorkflowSession(userID); len(session.Tasks) != 0 {
t.Fatalf("workflow session not cleared: %+v", session)
}
if state := a.getExecutionState(userID); state.SessionID != "" {
t.Fatalf("execution state not cleared: %+v", state)
}
if memory := a.getReferenceMemory(userID); memory.CurrentReferences != nil || len(memory.ReferenceHistory) != 0 {
t.Fatalf("reference memory not cleared: %+v", memory)
}
if stack := a.SnapshotManager(userID).List(); len(stack) != 0 {
t.Fatalf("snapshots not cleared: %+v", stack)
}
if setup := a.getSetupState(userID); setup.Step != "" || setup.AIProvider != "" {
t.Fatalf("setup state not cleared: %+v", setup)
}
}