change v1

This commit is contained in:
lky-spec
2026-04-25 16:18:45 +08:00
parent 737f9bca95
commit c244e4cdf1
89 changed files with 17382 additions and 6198 deletions

116
agent/clear_memory_test.go Normal file
View File

@@ -0,0 +1,116 @@
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)
}
}