fix(core): exact-resume saved session on workspace reconnect (#315)

This commit is contained in:
xxb authored and GitHub committed 2026-03-25 06:30:30 +08:00
1 parent 3a0ab9dd51
commit a44b375bce
2 files changed
+53 -5

No files matched your search

+11 -5
View File
@@ -1932,16 +1932,22 @@ func (e *Engine) getOrCreateInteractiveStateWith(sessionKey string, p Platform,
return state
}
// On first real-user connection after engine startup (or workspace re-creation
// after idle reap), use --continue to pick up the most recent CLI session.
// Subsequent connections respect the stored session ID (or "" for fresh).
// On first real-user connection after engine startup, use --continue to pick
// up the most recent CLI session. For workspace-scoped reconnects after idle
// reap, keep that behavior only when we do not already have a concrete saved
// agent session ID; otherwise exact resume is more precise than continuing
// whatever the CLI considers "latest" in that workspace.
startSessionID := session.GetAgentSessionID()
once := &e.hasConnectedOnce
if connectedOnce != nil {
once = connectedOnce
}
if consumeFirstUserContinueBridge && !once.Swap(true) {
startSessionID = ContinueSession
if consumeFirstUserContinueBridge {
if connectedOnce != nil && startSessionID != "" {
once.Store(true)
} else if !once.Swap(true) {
startSessionID = ContinueSession
}
}
isResume := startSessionID != ""
+42
View File
@@ -8,6 +8,7 @@ import (
"path/filepath"
"strings"
"sync"
"sync/atomic"
"testing"
"time"
)
@@ -4450,6 +4451,47 @@ func TestFreshSessionRespectedAfterFirstConnection(t *testing.T) {
}
}
func TestWorkspaceReconnectWithSavedSessionIDSkipsContinueBridge(t *testing.T) {
agent := &stubStartSessionAgent{}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
e := &Engine{
agent: agent,
sessions: NewSessionManager(""),
ctx: ctx,
i18n: NewI18n("en"),
interactiveStates: make(map[string]*interactiveState),
display: DisplayCfg{},
}
session := e.sessions.GetOrCreateActive("test:user3")
session.SetAgentSessionID("saved-session-id", "stub")
var wsConnectedOnce atomic.Bool
p := &stubPlatformEngine{n: "test"}
state := e.getOrCreateInteractiveStateWith("test:user3", p, "ctx", session, e.sessions, nil, "", true, &wsConnectedOnce)
if state.agentSession == nil {
t.Fatal("expected agentSession to be non-nil")
}
if !wsConnectedOnce.Load() {
t.Fatal("workspace connectedOnce flag should be marked after exact resume")
}
agent.mu.Lock()
calls := append([]string{}, agent.calls...)
agent.mu.Unlock()
if len(calls) != 1 {
t.Fatalf("expected 1 StartSession call, got %d: %v", len(calls), calls)
}
if calls[0] != "saved-session-id" {
t.Fatalf("StartSession call = %q, want saved session id", calls[0])
}
}
func TestParseSelfReportedCtx(t *testing.T) {
tests := []struct {
input string