返回 DeepSeek-Reasonix
session_resume_commit.go
根目录 / internal / serve / session_resume_commit.go
1 package serve
2
3 import (
4 "context"
5 "log/slog"
6 "net/http"
7
8 "reasonix/internal/agent"
9 "reasonix/internal/control"
10 )
11
12 // commitLoadedResume moves an idle controller to a validated transcript while
13 // keeping write authority, event tags, and current-only publication atomic to
14 // observers. The bool reports whether the caller may publish its routing
15 // barrier and HTTP success response.
16 func (s *Server) commitLoadedResume(w http.ResponseWriter, cur control.SessionAPI, loaded *agent.Session, realPath string) bool {
17 ctrl, concrete := cur.(*control.Controller)
18 if concrete && s.leases != nil {
19 // Issue target authority directly onto the loaded candidate before Resume
20 // replaces the executor session. Rebinding the controller here would only
21 // authorize the outgoing session and leave loaded on the permissive path.
22 if err := s.leases.BindSessionAuthority(loaded); err != nil {
23 _ = s.rebindSessionLease(cur.SessionPath())
24 http.Error(w, "session authority: unable to bind resumed session", http.StatusInternalServerError)
25 return false
26 }
27 }
28 var tag *sessionTagSink
29 if concrete {
30 tag = s.tagFor(ctrl)
31 if tag != nil && !ctrl.UsesExclusiveSession() {
32 tag.BufferPath(realPath)
33 }
34 }
35 if hook := resumeBindHookForTest; hook != nil {
36 hook()
37 }
38 if identity, ok := cur.(control.IdentityLifecycle); ok && identity.UsesExclusiveSession() {
39 ctrl, concrete := cur.(*control.Controller)
40 if !concrete || controllerHasActiveRuntimeWork(ctrl) {
41 _ = s.rebindSessionLease(cur.SessionPath())
42 http.Error(w, "open legacy session: controller replacement is unavailable", http.StatusConflict)
43 return false
44 }
45 next, tag, err := s.buildTaggedMode(context.Background(), currentModelRef(ctrl), false, true)
46 if err != nil {
47 _ = s.rebindSessionLease(cur.SessionPath())
48 http.Error(w, "open legacy session: "+err.Error(), http.StatusConflict)
49 return false
50 }
51 if err := next.ResumeNativeSession(loaded, realPath); err != nil {
52 s.closeTaggedController(next)
53 _ = s.rebindSessionLease(cur.SessionPath())
54 http.Error(w, "open historical session: "+err.Error(), http.StatusConflict)
55 return false
56 }
57 next.EnableInteractiveApproval()
58 if _, bound := next.SessionRef(); !bound {
59 next.SetToolApprovalMode(ctrl.ToolApprovalMode())
60 }
61 next.SetPlanMode(ctrl.PlanMode())
62 next.SetOnSessionRecovered(s.sessionRecoveryHandler(next, s.leases))
63 if s.leases != nil {
64 if err := s.leases.BindControllerAuthority(next); err != nil {
65 s.closeTaggedController(next)
66 _ = s.rebindSessionLease(cur.SessionPath())
67 http.Error(w, "bind legacy session authority: "+err.Error(), http.StatusInternalServerError)
68 return false
69 }
70 }
71 if ref, ok := next.SessionRef(); ok {
72 tag.PrimeIdentity(realPath, ref.SessionID)
73 } else {
74 tag.PrimePath(realPath)
75 }
76 if !s.publishControllerSwap(cur, next, realPath) {
77 s.closeTaggedController(next)
78 _ = s.rebindSessionLease(cur.SessionPath())
79 http.Error(w, "session changed during resume", http.StatusConflict)
80 return false
81 }
82 tag.Activate()
83 cur.Close()
84 s.forgetSessionTag(ctrl)
85 return true
86 } else {
87 cur.Resume(loaded, realPath)
88 }
89 if !concrete {
90 return true
91 }
92 // Rebind dropped the controller handlers with the outgoing authority. Resume
93 // has now made loaded current, so restore its owner binding before the next
94 // /new, /clear, or /fork enters the ordinary authorized transition path.
95 if s.leases != nil && !ctrl.UsesExclusiveSession() {
96 if err := s.leases.BindControllerAuthority(ctrl); err != nil {
97 slog.Warn("serve: rebind controller authority after resume", "err", err)
98 }
99 }
100 if tag == nil {
101 if !s.publishControllerPathIfCurrent(ctrl, realPath) {
102 http.Error(w, "session changed during resume", http.StatusConflict)
103 return false
104 }
105 return true
106 }
107 // Publish current-only routing before releasing buffered Resume events so
108 // every target-tagged warning/surface is marked foreground.
109 if !s.publishControllerPathIfCurrent(ctrl, realPath) {
110 http.Error(w, "session changed during resume", http.StatusConflict)
111 return false
112 }
113 tag.Activate()
114 return true
115 }
116
116 lines GO