返回 DeepSeek-Reasonix
transcript_api.go
根目录 / desktop / transcript_api.go
1 package main
2
3 import (
4 "context"
5 "fmt"
6
7 "reasonix/internal/control"
8 "reasonix/internal/transcript"
9 )
10
11 // ResumeTranscriptSessionForTab adopts a session without materializing a legacy
12 // history response. The caller obtains its bounded page from TranscriptSnapshotForTab.
13 func (a *App) ResumeTranscriptSessionForTab(tabID, path string) (HistorySwitchPhases, error) {
14 page, err := a.resumeSessionForTranscript(tabID, path, 0, false)
15 if page.Switch == nil {
16 return HistorySwitchPhases{}, err
17 }
18 return *page.Switch, err
19 }
20
21 func (a *App) OpenChannelTranscriptSessionForTab(tabID, path string) (HistorySwitchPhases, error) {
22 page, err := a.openChannelSessionForTranscript(tabID, path, 0, false)
23 if page.Switch == nil {
24 return HistorySwitchPhases{}, err
25 }
26 return *page.Switch, err
27 }
28
29 func (a *App) transcriptAPIForTab(tabID string) (control.TranscriptProjectionAPI, func() bool, error) {
30 tab, ctrl := a.tabAndCtrlByID(tabID)
31 if ctrl == nil {
32 return nil, nil, a.workspaceNotReadyErr(tab)
33 }
34 api, ok := ctrl.(control.TranscriptProjectionAPI)
35 if !ok {
36 return nil, nil, control.ErrTranscriptProjectionUnavailable
37 }
38 a.mu.RLock()
39 bound := tab != nil && a.tabs[tabID] == tab && tab.Ctrl == ctrl
40 epoch := a.runtimeEpochForTabLocked(tab)
41 a.mu.RUnlock()
42 if !bound {
43 return nil, nil, fmt.Errorf("runtime changed while binding transcript")
44 }
45 return api, func() bool {
46 a.mu.RLock()
47 defer a.mu.RUnlock()
48 return a.tabs[tabID] == tab && tab.Ctrl == ctrl && a.runtimeEpochForTabLocked(tab) == epoch
49 }, nil
50 }
51
52 func (a *App) TranscriptSnapshotForTab(tabID string, req transcript.PageRequest) (transcript.Snapshot, error) {
53 api, current, err := a.transcriptAPIForTab(tabID)
54 if err != nil {
55 return transcript.Snapshot{}, err
56 }
57 result, err := api.TranscriptSnapshot(req)
58 if !current() {
59 return transcript.Snapshot{}, fmt.Errorf("runtime changed while reading transcript")
60 }
61 return result, err
62 }
63
64 func (a *App) TranscriptFollowForTab(tabID string, req transcript.FollowRequest) (control.TranscriptFollowResponse, error) {
65 api, current, err := a.transcriptAPIForTab(tabID)
66 if err != nil {
67 return control.TranscriptFollowResponse{}, err
68 }
69 follow, ok := api.(control.TranscriptFollowAPI)
70 if !ok {
71 return control.TranscriptFollowResponse{}, control.ErrTranscriptProjectionUnavailable
72 }
73 // Follow is a subscription, not a bounded command. Its 25-second idle
74 // poll must not be cancelled by the 15-second command deadline.
75 ctx := a.bootContext()
76 if ctx == nil {
77 ctx = context.Background()
78 }
79 ctx, cancel := context.WithCancel(ctx)
80 defer cancel()
81 result, err := follow.TranscriptFollow(ctx, req)
82 if !current() {
83 if result.Subscription != "" {
84 _, _ = follow.TranscriptFollow(context.Background(), transcript.FollowRequest{Subscription: result.Subscription, Close: true})
85 }
86 return control.TranscriptFollowResponse{}, fmt.Errorf("runtime changed while following transcript")
87 }
88 return result, err
89 }
90
91 func (a *App) TranscriptPageForTab(tabID string, req transcript.PageRequest) (transcript.Snapshot, error) {
92 return a.TranscriptSnapshotForTab(tabID, req)
93 }
94
95 // TranscriptOutlineForTab pages the complete turn index of one snapshot. The
96 // capability is optional beside the projection, so a controller without it is
97 // reported as unavailable instead of answering an empty outline.
98 func (a *App) TranscriptOutlineForTab(tabID string, req transcript.OutlineRequest) (transcript.OutlinePage, error) {
99 api, current, err := a.transcriptAPIForTab(tabID)
100 if err != nil {
101 return transcript.OutlinePage{}, err
102 }
103 outline, ok := api.(control.TranscriptOutlineAPI)
104 if !ok {
105 return transcript.OutlinePage{}, control.ErrTranscriptProjectionUnavailable
106 }
107 result, err := outline.TranscriptOutline(req)
108 if !current() {
109 return transcript.OutlinePage{}, fmt.Errorf("runtime changed while reading transcript outline")
110 }
111 return result, err
112 }
113
114 func (a *App) TranscriptContentForTab(tabID string, req transcript.ContentRequest) (transcript.ContentChunk, error) {
115 api, current, err := a.transcriptAPIForTab(tabID)
116 if err != nil {
117 return transcript.ContentChunk{}, err
118 }
119 result, err := api.TranscriptContent(req)
120 if !current() {
121 return transcript.ContentChunk{}, fmt.Errorf("runtime changed while reading transcript content")
122 }
123 return result, err
124 }
125
126 func (a *App) TranscriptReplayForTab(tabID string, req control.TranscriptReplayRequest) (control.TranscriptReplay, error) {
127 api, current, err := a.transcriptAPIForTab(tabID)
128 if err != nil {
129 return control.TranscriptReplay{}, err
130 }
131 result, err := api.TranscriptReplay(req)
132 if !current() {
133 return control.TranscriptReplay{}, fmt.Errorf("runtime changed while replaying transcript")
134 }
135 return result, err
136 }
137
137 lines GO