返回 DeepSeek-Reasonix
tool_recovery.go
根目录 / desktop / tool_recovery.go
1 package main
2
3 import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "io"
8 "net/http"
9
10 "reasonix/internal/control"
11 )
12
13 type toolRecoveryController interface {
14 ToolRecoverySnapshot() control.ToolRecoverySnapshot
15 ResolveToolRecovery(context.Context, control.ToolRecoveryRequest) (control.ToolRecoverySnapshot, error)
16 }
17
18 // Both local and remote surfaces use the same generation-bound request shape.
19 func (a *App) GetToolRecoveryForTab(tabID string) (control.ToolRecoverySnapshot, error) {
20 if a.isRemoteTab(tabID) {
21 return a.remoteToolRecovery(tabID, nil)
22 }
23 _, ctrl := a.tabAndCtrlByID(tabID)
24 if target, ok := ctrl.(toolRecoveryController); ok {
25 return target.ToolRecoverySnapshot(), nil
26 }
27 return control.ToolRecoverySnapshot{}, fmt.Errorf("tool recovery unavailable")
28 }
29
30 func (a *App) ResolveToolRecoveryForTab(tabID string, req control.ToolRecoveryRequest) (control.ToolRecoverySnapshot, error) {
31 if a.isRemoteTab(tabID) {
32 return a.remoteToolRecovery(tabID, &req)
33 }
34 _, ctrl := a.tabAndCtrlByID(tabID)
35 if target, ok := ctrl.(toolRecoveryController); ok {
36 ctx, cancel := commandContext(a)
37 defer cancel()
38 return target.ResolveToolRecovery(ctx, req)
39 }
40 return control.ToolRecoverySnapshot{}, fmt.Errorf("tool recovery unavailable")
41 }
42
43 func (a *App) remoteToolRecovery(tabID string, req *control.ToolRecoveryRequest) (control.ToolRecoverySnapshot, error) {
44 if req != nil {
45 if err := a.requireRemoteExecutionProtocol(tabID); err != nil {
46 return control.ToolRecoverySnapshot{}, err
47 }
48 }
49 client, base, path, err := a.remoteTabCommandTarget(tabID)
50 if err != nil {
51 return control.ToolRecoverySnapshot{}, err
52 }
53 ctx, cancel := commandContext(a)
54 defer cancel()
55 method := http.MethodGet
56 var body []byte
57 if req != nil {
58 method = http.MethodPost
59 body, err = json.Marshal(req)
60 if err != nil {
61 return control.ToolRecoverySnapshot{}, err
62 }
63 }
64 resp, err := serveDoForSession(ctx, client, method, serveURL(base, "/tool-recovery"), body, path)
65 if err != nil {
66 return control.ToolRecoverySnapshot{}, err
67 }
68 defer resp.Body.Close()
69 if resp.StatusCode != http.StatusOK {
70 b, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
71 return control.ToolRecoverySnapshot{}, fmt.Errorf("tool recovery: %s", b)
72 }
73 var view control.ToolRecoverySnapshot
74 err = json.NewDecoder(io.LimitReader(resp.Body, 2<<20)).Decode(&view)
75 if err == nil && view.SessionPath != path {
76 return view, fmt.Errorf("remote recovery session changed")
77 }
78 return view, err
79 }
80
80 lines GO