返回 DeepSeek-Reasonix
remote_tab_extension_pending.go
根目录 / desktop / remote_tab_extension_pending.go
1 package main
2
3 import (
4 "bytes"
5 "encoding/json"
6 "strings"
7 )
8
9 const remotePendingExtensionFormKey = "extension_surface:form"
10
11 // cacheRemotePendingExtensionForm retains the latest actionable form while a
12 // remote tab has no mounted frontend listener. Other extension publications
13 // remain ordinary stream history; the shared reducer only exposes one pending
14 // form at a time, so the newest form replaces the previous one here as well.
15 func (a *App) cacheRemotePendingExtensionForm(tabID string, gen uint64, frame json.RawMessage) bool {
16 if !remotePendingExtensionForm(frame) {
17 return false
18 }
19 a.remoteTabMu.Lock()
20 tab := a.remoteTabs[tabID]
21 if tab == nil || tab.gen != gen {
22 a.remoteTabMu.Unlock()
23 return false
24 }
25 tab.runtime.revision++
26 if tab.pendingEvents == nil {
27 tab.pendingEvents = make(map[string]json.RawMessage)
28 }
29 tab.pendingEvents[remotePendingExtensionFormKey] = append(json.RawMessage(nil), frame...)
30 tab.runtime.pendingPrompt = true
31 tab.runtime.cancellable = true
32 meta := remoteTabMetaLocked(tab)
33 a.remoteTabMu.Unlock()
34 a.emitRemoteEvent("remote-tab:updated", meta)
35 return true
36 }
37
38 func remotePendingExtensionForm(frame json.RawMessage) bool {
39 var probe struct {
40 Extension *struct {
41 PluginID string `json:"pluginId"`
42 SurfaceID string `json:"surfaceId"`
43 Kind string `json:"kind"`
44 Form json.RawMessage `json:"form"`
45 } `json:"extension"`
46 }
47 if json.Unmarshal(frame, &probe) != nil || probe.Extension == nil ||
48 probe.Extension.Kind != "form" || len(probe.Extension.Form) == 0 || bytes.Equal(bytes.TrimSpace(probe.Extension.Form), []byte("null")) ||
49 strings.TrimSpace(probe.Extension.PluginID) == "" || strings.TrimSpace(probe.Extension.SurfaceID) == "" {
50 return false
51 }
52 return true
53 }
54
55 func (a *App) clearRemotePendingExtensionForm(tabID, pluginID, surfaceID string) {
56 a.remoteTabMu.Lock()
57 var meta TabMeta
58 changed := false
59 if tab := a.remoteTabs[tabID]; tab != nil {
60 frame := tab.pendingEvents[remotePendingExtensionFormKey]
61 var probe struct {
62 Extension *struct {
63 PluginID string `json:"pluginId"`
64 SurfaceID string `json:"surfaceId"`
65 } `json:"extension"`
66 }
67 if json.Unmarshal(frame, &probe) == nil && probe.Extension != nil &&
68 probe.Extension.PluginID == pluginID && probe.Extension.SurfaceID == surfaceID {
69 tab.runtime.revision++
70 delete(tab.pendingEvents, remotePendingExtensionFormKey)
71 pending := len(tab.pendingEvents) > 0
72 changed = tab.runtime.pendingPrompt != pending
73 tab.runtime.pendingPrompt = pending
74 meta = remoteTabMetaLocked(tab)
75 }
76 }
77 a.remoteTabMu.Unlock()
78 if changed {
79 a.emitRemoteEvent("remote-tab:updated", meta)
80 }
81 }
82
83 func (a *App) clearRemotePendingExtensionFormExact(tabID, pluginID, surfaceID, formInstanceID string) {
84 a.remoteTabMu.Lock()
85 var meta TabMeta
86 changed := false
87 if tab := a.remoteTabs[tabID]; tab != nil {
88 frame := tab.pendingEvents[remotePendingExtensionFormKey]
89 var probe struct {
90 Extension *struct {
91 PluginID string `json:"pluginId"`
92 SurfaceID string `json:"surfaceId"`
93 FormInstanceID string `json:"formInstanceId"`
94 } `json:"extension"`
95 }
96 if json.Unmarshal(frame, &probe) == nil && probe.Extension != nil &&
97 probe.Extension.PluginID == pluginID && probe.Extension.SurfaceID == surfaceID &&
98 probe.Extension.FormInstanceID == formInstanceID {
99 tab.runtime.revision++
100 delete(tab.pendingEvents, remotePendingExtensionFormKey)
101 pending := len(tab.pendingEvents) > 0
102 changed = tab.runtime.pendingPrompt != pending
103 tab.runtime.pendingPrompt = pending
104 meta = remoteTabMetaLocked(tab)
105 }
106 }
107 a.remoteTabMu.Unlock()
108 if changed {
109 a.emitRemoteEvent("remote-tab:updated", meta)
110 }
111 }
112
112 lines GO