diff --git a/internal/handler/agent_progress_callback_test.go b/internal/handler/agent_progress_callback_test.go index 8c2b0da5..ea2bd69e 100644 --- a/internal/handler/agent_progress_callback_test.go +++ b/internal/handler/agent_progress_callback_test.go @@ -3,7 +3,6 @@ package handler import ( "context" "fmt" - "os" "path/filepath" "strings" "sync" @@ -86,6 +85,7 @@ func TestCreateProgressCallback_HidesInternalEinoDiagnostics(t *testing.T) { if err != nil { t.Fatalf("NewDB: %v", err) } + t.Cleanup(func() { _ = db.Close() }) conv, err := db.CreateConversation("diag-hidden", database.ConversationCreateMeta{}) if err != nil { t.Fatalf("CreateConversation: %v", err) @@ -133,6 +133,7 @@ func TestCreateProgressCallback_PersistsRunningResponseBeforeDone(t *testing.T) if err != nil { t.Fatalf("NewDB: %v", err) } + t.Cleanup(func() { _ = db.Close() }) conv, err := db.CreateConversation("refresh-running", database.ConversationCreateMeta{}) if err != nil { t.Fatalf("CreateConversation: %v", err) @@ -178,8 +179,8 @@ func TestCreateProgressCallback_FlushesReasoningOnDone(t *testing.T) { if err != nil { t.Fatalf("NewDB: %v", err) } - defer os.RemoveAll(tmp) + t.Cleanup(func() { _ = db.Close() }) conv, err := db.CreateConversation("test", database.ConversationCreateMeta{}) if err != nil { t.Fatalf("CreateConversation: %v", err) diff --git a/internal/handler/hitl.go b/internal/handler/hitl.go index c136499d..44b8b4a4 100644 --- a/internal/handler/hitl.go +++ b/internal/handler/hitl.go @@ -153,7 +153,8 @@ SELECT msg.id, msg.conversation_id, SELECT MIN(later.created_at) FROM messages later WHERE later.conversation_id = msg.conversation_id - AND later.created_at > msg.created_at + AND (later.created_at > msg.created_at + OR (later.created_at = msg.created_at AND later.rowid > msg.rowid)) ), ( SELECT MAX(pd.created_at) FROM process_details pd @@ -177,7 +178,8 @@ WHERE msg.role = 'assistant' OR EXISTS ( SELECT 1 FROM messages later WHERE later.conversation_id = msg.conversation_id - AND later.created_at > msg.created_at + AND (later.created_at > msg.created_at + OR (later.created_at = msg.created_at AND later.rowid > msg.rowid)) ) )`) if err != nil { diff --git a/internal/handler/hitl_context_test.go b/internal/handler/hitl_context_test.go index cdf3870c..baa538e9 100644 --- a/internal/handler/hitl_context_test.go +++ b/internal/handler/hitl_context_test.go @@ -1,7 +1,6 @@ package handler import ( - "os" "path/filepath" "testing" @@ -16,7 +15,7 @@ func TestEnrichHitlApprovalPayload(t *testing.T) { if err != nil { t.Fatalf("db: %v", err) } - defer os.RemoveAll(tmp) + t.Cleanup(func() { _ = db.Close() }) conv, err := db.CreateConversation("hitl ctx", database.ConversationCreateMeta{}) if err != nil { diff --git a/internal/handler/hitl_restart_test.go b/internal/handler/hitl_restart_test.go index f5ec1475..00df54ee 100644 --- a/internal/handler/hitl_restart_test.go +++ b/internal/handler/hitl_restart_test.go @@ -98,9 +98,16 @@ func TestEnsureSchemaFinalizesOnlyHistoricalPlaceholdersWithTerminalEvidence(t * if err != nil { t.Fatalf("create superseded placeholder: %v", err) } - if _, err := db.AddMessage(supersededConversation.ID, "user", "继续", nil); err != nil { + later, err := db.AddMessage(supersededConversation.ID, "user", "继续", nil) + if err != nil { t.Fatalf("create later message: %v", err) } + // Coarse clocks (notably Windows) can give consecutive messages the same + // timestamp. Match the message ordering used by GetMessages: time, then rowid. + if _, err := db.Exec(`UPDATE messages SET created_at = + (SELECT created_at FROM messages WHERE id = ?) WHERE id = ?`, superseded.ID, later.ID); err != nil { + t.Fatalf("give consecutive messages equal timestamps: %v", err) + } timeoutConversation, err := db.CreateConversation("timeout placeholder", database.ConversationCreateMeta{}) if err != nil { @@ -136,10 +143,18 @@ func TestEnsureSchemaFinalizesOnlyHistoricalPlaceholdersWithTerminalEvidence(t * if err != nil { t.Fatalf("create active conversation: %v", err) } + earlier, err := db.AddMessage(activeConversation.ID, "user", "开始", nil) + if err != nil { + t.Fatalf("create preceding message: %v", err) + } potentiallyActive, err := db.AddMessage(activeConversation.ID, "assistant", "处理中...", nil) if err != nil { t.Fatalf("create potentially active placeholder: %v", err) } + if _, err := db.Exec(`UPDATE messages SET created_at = + (SELECT created_at FROM messages WHERE id = ?) WHERE id = ?`, potentiallyActive.ID, earlier.ID); err != nil { + t.Fatalf("give preceding message equal timestamp: %v", err) + } if err := manager.EnsureSchema(); err != nil { t.Fatalf("reconcile historical placeholders: %v", err) diff --git a/internal/handler/tool_guard_test.go b/internal/handler/tool_guard_test.go index 570c659c..e2d77cd2 100644 --- a/internal/handler/tool_guard_test.go +++ b/internal/handler/tool_guard_test.go @@ -50,6 +50,10 @@ func toolGuardRequest(t *testing.T, handler gin.HandlerFunc, body interface{}) * func TestToolGuardSavePersistsAndAppliesWithoutChangingHITL(t *testing.T) { h := newToolGuardTestHandler(t) + before, err := os.Stat(h.configPath) + if err != nil { + t.Fatal(err) + } cfg := toolguard.DefaultConfig() cfg.Rules[0].Message = "识别到 {match},禁止攻击政府网站,请检查目标。" w := toolGuardRequest(t, h.UpdateToolGuard, cfg) @@ -68,7 +72,7 @@ func TestToolGuardSavePersistsAndAppliesWithoutChangingHITL(t *testing.T) { } info, _ := os.Stat(h.configPath) data, _ := os.ReadFile(h.configPath) - if info.Mode().Perm() != 0600 || !strings.Contains(string(data), "# keep this comment") { + if info.Mode().Perm() != before.Mode().Perm() || !strings.Contains(string(data), "# keep this comment") { t.Fatal("file permissions or comments were lost") } match := h.toolGuard.Check("scan", map[string]interface{}{"target": "agency.gov.cn"})