返回 DeepSeek-Reasonix
scope_resources.go
根目录 / internal / extension / scope_resources.go
1 package extension
2
3 import (
4 "context"
5 "fmt"
6 "io"
7 )
8
9 // TrackMCPClient registers an MCP client/transport closer as a reversible effect.
10 func TrackMCPClient(scope EffectScope, serverName string, c io.Closer) error {
11 if scope == nil || c == nil {
12 return nil
13 }
14 return scope.Track(Effect{
15 ID: "mcp-client:" + serverName,
16 Owner: "mcp",
17 Class: Reversible,
18 Dispose: func(context.Context) error {
19 return c.Close()
20 },
21 })
22 }
23
24 // FuncCloser adapts a func() into io.Closer for TrackMCPClient call sites.
25 type FuncCloser func()
26
27 // Close implements io.Closer.
28 func (f FuncCloser) Close() error {
29 if f != nil {
30 f()
31 }
32 return nil
33 }
34
35 // TrackUIHub registers a UI hub binding. Dispose is a no-op close of the
36 // binding registration (hub itself may be reused across generations).
37 func TrackUIHub(scope EffectScope, generation uint64) error {
38 if scope == nil {
39 return nil
40 }
41 return scope.Track(Effect{
42 ID: fmt.Sprintf("ui-hub-gen-%d", generation),
43 Owner: "uihub",
44 Component: "extension-ui",
45 Class: Reversible,
46 Dispose: func(context.Context) error { return nil },
47 })
48 }
49
50 // TrackProviderStream registers a cancelable provider stream so Dispose waits
51 // for background delivery to finish (caller supplies wait).
52 func TrackProviderStream(scope EffectScope, streamID string, cancel func(), wait func(context.Context) error) error {
53 if scope == nil {
54 return nil
55 }
56 return scope.Track(Effect{
57 ID: "provider-stream:" + streamID,
58 Owner: "providerext",
59 Class: Cancelable,
60 Dispose: func(ctx context.Context) error {
61 if cancel != nil {
62 cancel()
63 }
64 if wait != nil {
65 return wait(ctx)
66 }
67 return nil
68 },
69 })
70 }
71
72 // TrackWatcher registers a filesystem or config watcher.
73 func TrackWatcher(scope EffectScope, id string, stop func() error) error {
74 if scope == nil || stop == nil {
75 return nil
76 }
77 return scope.Track(Effect{
78 ID: "watcher:" + id,
79 Owner: "watcher",
80 Class: Reversible,
81 Dispose: func(context.Context) error {
82 return stop()
83 },
84 })
85 }
86
87 // TrackEventSubscription registers an event subscription teardown.
88 func TrackEventSubscription(scope EffectScope, id string, unsub func() error) error {
89 if scope == nil || unsub == nil {
90 return nil
91 }
92 return scope.Track(Effect{
93 ID: "event-sub:" + id,
94 Owner: "events",
95 Class: Reversible,
96 Dispose: func(context.Context) error {
97 return unsub()
98 },
99 })
100 }
101
102 // TrackBackgroundJob registers cancelable background work.
103 func TrackBackgroundJob(scope EffectScope, id string, cancel func(), wait func(context.Context) error) error {
104 if scope == nil {
105 return nil
106 }
107 return scope.Track(Effect{
108 ID: "bg:" + id,
109 Owner: "background",
110 Class: Cancelable,
111 Dispose: func(ctx context.Context) error {
112 if cancel != nil {
113 cancel()
114 }
115 if wait != nil {
116 return wait(ctx)
117 }
118 return nil
119 },
120 })
121 }
122
123 // TrackControllerCleanup registers a controller cleanup callback.
124 func TrackControllerCleanup(scope EffectScope, id string, cleanup func() error) error {
125 if scope == nil || cleanup == nil {
126 return nil
127 }
128 return scope.Track(Effect{
129 ID: "controller-cleanup:" + id,
130 Owner: "control",
131 Class: Reversible,
132 Dispose: func(context.Context) error {
133 return cleanup()
134 },
135 })
136 }
137
138 // TrackIrreversible records an irreversible external action (message send,
139 // provider request submitted) for recovery assessment — dispose never claims
140 // rollback success.
141 func TrackIrreversible(scope EffectScope, id, owner string) error {
142 if scope == nil {
143 return nil
144 }
145 err := scope.Track(Effect{
146 ID: id,
147 Owner: owner,
148 Class: Irreversible,
149 Dispose: func(context.Context) error {
150 return nil
151 },
152 })
153 if err == nil {
154 RuntimeOwnerOrDefault(nil).Receipts.Record(EffectReceipt{
155 ID: id,
156 Owner: owner,
157 Class: Irreversible,
158 Generation: scope.Generation(),
159 CompensationStatus: "not_applicable",
160 })
161 }
162 return err
163 }
164
164 lines GO