fix(agent): keep suspended-task snapshots on the legacy stack

suspendActiveContexts clears all active contexts after parking a task on
the snapshot stack, so the active-context guard alone let the agentic
loop hijack resume requests and strand suspended tasks. Check the
snapshot stack in shouldUseAgenticTurn.
This commit is contained in:
tinkle-community
2026-06-11 01:12:36 +08:00
parent 4f3869c81c
commit 3a048876bd
2 changed files with 25 additions and 0 deletions

View File

@@ -46,6 +46,11 @@ func (a *Agent) shouldUseAgenticTurn(userID int64) bool {
if _, ok := a.getPendingProposalSession(userID); ok {
return false
}
// Suspended tasks are parked on the snapshot stack with all active
// contexts cleared; only the legacy router knows how to resume them.
if len(a.SnapshotManager(userID).Stack()) > 0 {
return false
}
return true
}

View File

@@ -274,6 +274,26 @@ func TestShouldUseAgenticTurn(t *testing.T) {
}
})
t.Run("suspended task snapshot stays on legacy stack", func(t *testing.T) {
st, err := store.New(filepath.Join(t.TempDir(), "agentic-snapshot.db"))
if err != nil {
t.Fatalf("create store: %v", err)
}
b := New(nil, st, DefaultConfig(), slog.Default())
b.SetAIClient(&scriptedAIClient{})
if !b.shouldUseAgenticTurn(12) {
t.Fatal("fresh conversation should use the agentic turn")
}
b.SnapshotManager(12).Save(SuspendedTask{
SnapshotID: "snap_test",
Kind: "skill",
ResumeHint: "continue strategy create",
})
if b.shouldUseAgenticTurn(12) {
t.Fatal("suspended task snapshot must stay on the legacy stack so it can be resumed")
}
})
t.Run("active legacy session stays on legacy stack", func(t *testing.T) {
st, err := store.New(filepath.Join(t.TempDir(), "agentic-guard.db"))
if err != nil {