返回 DeepSeek-Reasonix
remote_tab_frame_publish.go
根目录 / desktop / remote_tab_frame_publish.go
1 package main
2
3 import (
4 "encoding/json"
5 "fmt"
6 "net/http"
7 "time"
8 )
9
10 func (a *App) publishRemoteTabFrame(tabID string, gen uint64, sessionPath, kind string, frame json.RawMessage) bool {
11 return a.publishRemoteTabFrameForRoute(tabID, nil, nil, gen, sessionPath, false, kind, frame)
12 }
13
14 // publishRemoteTabFrameForRoute holds the tab's route/event boundary from the
15 // final route validation through frontend publication. A concurrent adoption
16 // therefore publishes its barrier wholly before or after the validated frame.
17 func (a *App) publishRemoteTabFrameForRoute(tabID string, expectedTab *remoteTab, expectedClient *http.Client, gen uint64, sessionPath string, requireRehydrating bool, kind string, frame json.RawMessage) bool {
18 a.remoteTabMu.Lock()
19 tab := a.remoteTabs[tabID]
20 a.remoteTabMu.Unlock()
21 if tab == nil {
22 return false
23 }
24 tab.routeEventMu.Lock()
25 defer tab.routeEventMu.Unlock()
26 return a.publishRemoteTabFrameForRouteLocked(tabID, tab, expectedTab, expectedClient, gen, sessionPath, requireRehydrating, kind, frame)
27 }
28
29 // publishRemoteTabFrameForRouteLocked publishes while tab.routeEventMu is held.
30 func (a *App) publishRemoteTabFrameForRouteLocked(tabID string, tab, expectedTab *remoteTab, expectedClient *http.Client, gen uint64, sessionPath string, requireRehydrating bool, kind string, frame json.RawMessage) bool {
31 a.remoteTabMu.Lock()
32 current := a.remoteTabs[tabID]
33 valid := current == tab && current.gen == gen &&
34 (expectedTab == nil || current == expectedTab) &&
35 (expectedClient == nil || current.client == expectedClient) &&
36 (sessionPath == "" || current.routing.currentPath == sessionPath) &&
37 (!requireRehydrating || current.routing.rehydratingPath == sessionPath)
38 a.remoteTabMu.Unlock()
39 if !valid {
40 return false
41 }
42 refreshRuntime := false
43 switch kind {
44 case "turn_started":
45 a.recordRemoteTabTurnStarted(tabID, gen, frame)
46 refreshRuntime = true
47 case "approval_request", "ask_request", "mcp_interaction":
48 a.cacheRemotePendingEvent(tabID, gen, kind, frame)
49 refreshRuntime = true
50 case "extension_surface":
51 refreshRuntime = a.cacheRemotePendingExtensionForm(tabID, gen, frame)
52 case "turn_done":
53 a.completeRemoteTabTurn(tabID, gen)
54 }
55 a.emitRemoteEvent(fmt.Sprintf("remote-tab:%s:event", tabID), frame)
56 if refreshRuntime {
57 a.goRemoteTabSafe("remoteTabRuntimeStatus", func() { _, _ = a.RemoteTabStatus(tabID) })
58 }
59 if kind == "turn_done" {
60 // Capture the durable session name immediately, closing the window
61 // where a replacement Serve could otherwise lose a just-finished
62 // conversation before the slower generated-title refresh runs.
63 a.goRemoteTabSafe("remoteTabTitle", func() {
64 _, _ = a.RemoteTabStatus(tabID)
65 // The serve generates the session title from the finished
66 // conversation; pick it up shortly after the turn settles.
67 time.Sleep(1500 * time.Millisecond)
68 a.refreshRemoteTabTitle(tabID)
69 })
70 }
71 return true
72 }
73
73 lines GO