返回 DeepSeek-Reasonix
port.go
根目录 / internal / control / port.go
1 package control
2
3 import (
4 "context"
5
6 "reasonix/internal/agent"
7 "reasonix/internal/autoresearch"
8 "reasonix/internal/billing"
9 "reasonix/internal/checkpoint"
10 "reasonix/internal/command"
11 "reasonix/internal/config"
12 "reasonix/internal/event"
13 "reasonix/internal/evidence"
14 "reasonix/internal/hook"
15 "reasonix/internal/jobs"
16 "reasonix/internal/memory"
17 "reasonix/internal/plugin"
18 "reasonix/internal/provider"
19 "reasonix/internal/skill"
20 )
21
22 // This file defines the driving port: the typed, segregated interface surface
23 // that frontends (cli, desktop, bot, acp, serve) consume instead of coupling to
24 // the concrete *Controller and its ~99 methods. Each frontend depends only on
25 // the sub-ports it actually uses (interface segregation), so e.g. the bot never
26 // sees checkpoint or memory methods.
27 //
28 // The sub-ports are also the intended decomposition boundary for Controller
29 // itself: the port comes first and gives the later collaborator splits a spec to
30 // follow. *Controller implements every sub-port (asserted below). The full
31 // SessionAPI composition will accrete here as the remaining frontends migrate.
32
33 // Lifecycle covers a session's identity and lifecycle: minting, resuming,
34 // clearing, and locating the active session.
35 type Lifecycle interface {
36 NewSession() error
37 ClearSession() error
38 Resume(s *agent.Session, path string)
39 SetSessionPath(p string)
40 SessionPath() string
41 SessionDir() string
42 Label() string
43 ModelRef() string
44 WorkspaceRoot() string
45 Close()
46 }
47
48 // TurnControl covers driving a model turn and observing its run state: the
49 // various submit/run entry points, cancellation, steering, and status reads.
50 type TurnControl interface {
51 Submit(input string)
52 SubmitDisplay(display, input string)
53 SubmitDeliveryRecovery(display, input string)
54 SubmitInvocationDisplay(display, input string, invocations []InvocationRequest)
55 SubmitEditedDisplay(display, input, original string)
56 SubmitHTTP(input string)
57 SubmitHTTPFormat(input, format string)
58 SubmitUserTurn(input, display string)
59 Send(input string)
60 SendWithRaw(input, raw string)
61 Run(ctx context.Context, input string) error
62 RunTurn(ctx context.Context, input string) error
63 RunShell(command string)
64 Cancel()
65 Steer(text string)
66 SteerConsumed() bool
67 Running() bool
68 CancelRequested() bool
69 RuntimeStatus() RuntimeStatus
70 Turn() int
71 History() []provider.Message
72 ToolResult(toolID string) *ToolResultData
73 }
74
75 // Approvals covers tool-approval and ask prompts plus the runtime approval
76 // posture (ask/auto/yolo). It mirrors the approvalManager surface.
77 type Approvals interface {
78 Approve(id string, allow, session, persist bool)
79 ResolvePlanDecision(id string, action PlanDecisionAction) error
80 // ResolveRecovery answers an Auto Guard card: continue|continue_task|revise. Revise
81 // refuses the mutation and steers feedback.
82 ResolveRecovery(id string, action agent.RecoveryAction, feedback string) error
83 AnswerQuestion(id string, answers []event.AskAnswer)
84 Ask(ctx context.Context, questions []event.AskQuestion) ([]event.AskAnswer, error)
85 ReplayPendingPrompts()
86 ReplayPendingPromptsTo(sink event.Sink)
87 ReplayPendingPromptsWith(sinkFactory func() event.Sink)
88 PendingPrompt() bool
89 EnableInteractiveApproval()
90 ToolApprovalMode() string
91 SetToolApprovalMode(mode string)
92 AutoApproveTools() bool
93 SetAutoApproveTools(on bool)
94 Bypass() bool
95 SetBypass(on bool)
96 SetMode(plan, autoApproveTools bool)
97 }
98
99 // Goals covers the active-goal FSM and plan mode.
100 type Goals interface {
101 Goal() string
102 GoalStatus() string
103 SetGoal(goal string)
104 SetGoalWithResearchMode(goal string, researchMode GoalResearchMode)
105 ResumeGoal() bool
106 PauseGoal() bool
107 GoalRuntime() GoalRuntimeView
108 GoalStrict(strict bool)
109 ClearGoal()
110 AutoResearchSummary() (*autoresearch.Summary, bool)
111 AutoResearchList() ([]autoresearch.Summary, bool)
112 AutoResearchFindings(limit int) ([]autoresearch.Finding, bool)
113 RecordAutoResearchEvidence(criterionID string, input AutoResearchEvidenceInput) error
114 ResetPlannerSession()
115 PlanMode() bool
116 SetPlanMode(v bool)
117 }
118
119 // SessionHistory covers checkpoint/rewind, branch/fork, and the log-restructuring
120 // operations (compact, summarize).
121 type SessionHistory interface {
122 Checkpoints() []checkpoint.Meta
123 CheckpointFileState(path string) (checkpoint.FileState, bool)
124 CheckpointTurnsByMessageIndex() map[int]int
125 CheckpointHasBoundary(turn int) bool
126 Rewind(turn int, scope RewindScope) error
127 PrepareRewind(turn int, scope RewindScope) (checkpoint.RewindPlan, error)
128 CommitRewind(planID string) (checkpoint.RewindResult, error)
129 UndoRewind(transactionID string) (checkpoint.RewindResult, error)
130 PrepareFileRevert(path string) (checkpoint.RewindPlan, error)
131 CommitFileRevert(planID string, resolution checkpoint.ConflictResolution) (checkpoint.RewindResult, error)
132 Fork(turn int) (string, error)
133 ForkNamed(turn int, name string) (string, error)
134 ForkSession(turn int, name string) (string, error)
135 Branch(name string) (string, error)
136 Branches() ([]agent.BranchInfo, error)
137 BranchTreeText() string
138 SwitchBranch(ref string) (agent.BranchInfo, error)
139 Compact(ctx context.Context, instructions string) error
140 CompactRatio() float64
141 SummarizeFrom(ctx context.Context, turn int) error
142 SummarizeUpTo(ctx context.Context, turn int) error
143 }
144
145 // MemoryControl covers session/project memory reads and mutations.
146 type MemoryControl interface {
147 Memory() *memory.Set
148 QuickAdd(scope memory.Scope, note string) (string, error)
149 SaveDoc(path, body string) (string, error)
150 SaveMemory(m memory.Memory) (string, error)
151 ForgetMemory(name string) error
152 QueueMemory(note string)
153 MemoryRevisions(ref string) []memory.Memory
154 RestoreMemory(ref string, revision int) (memory.Memory, error)
155 RestoreArchivedMemory(archivePath string) (memory.Memory, error)
156 LastMemoryRecall() memory.RecallResult
157 }
158
159 // Capabilities covers the session's pluggable surface — MCP servers, skills,
160 // slash commands, hooks — and resolving prompt/command/skill inputs.
161 type Capabilities interface {
162 Host() *plugin.Host
163 Commands() []command.Command
164 ReloadCommands(ctx context.Context) error
165 Skills() []skill.Skill
166 SlashSkills() []skill.Skill
167 AllSkills() []skill.Skill
168 DisabledSkills() []skill.Skill
169 SkillEnabled(name string) bool
170 SetSkillEnabled(name string, enabled bool) error
171 CreateSkill(name string, scope skill.Scope, content string) (string, error)
172 UpdateSkill(name string, scope skill.Scope, content string) error
173 DeleteSkill(name string, scope skill.Scope) error
174 HookRunner() *hook.Runner
175 CustomCommand(input string) (sent string, found bool)
176 MCPPrompt(ctx context.Context, input string) (sent string, found bool, err error)
177 RunSkill(input string) (sent string, found bool)
178 AddMCPServer(e config.PluginEntry) (int, error)
179 ConnectMCPServer(e config.PluginEntry) (int, error)
180 RegisterMCPServerOnDemand(e config.PluginEntry) (int, error)
181 ConnectConfiguredMCPServer(name string) (int, error)
182 DisconnectMCPServer(name string) bool
183 RemoveMCPServer(name string) (disconnected bool, err error)
184 ConfiguredMCPNames() []string
185 DisconnectedMCPNames() []string
186 UnregisterMCPServerTools(name string) bool
187 ImportMCPEntries(entries []config.PluginEntry) (total, added, updated, connected, failed, skipped int, err error)
188 // Extension UI (stage 8a): enumerate handshake-declared extension actions
189 // and invoke one by its public /<plugin>:<action> name. Nil hub → empty /
190 // error; the stage-8b slash dispatch resolves these.
191 ExtensionActions() []ExtensionActionView
192 InvokeExtensionAction(ctx context.Context, name string, args map[string]string) (string, error)
193 // ProviderCatalog is the session's merged provider catalog — config/broker
194 // base plus sidecar-declared extension providers (plugin/... refs). Nil
195 // when no extension declared providers; frontends merge it into their
196 // model pickers and skip nil.
197 ProviderCatalog() []provider.Descriptor
198 }
199
200 // Status covers read-only run/usage/billing telemetry and task list state.
201 type Status interface {
202 ContextSnapshot() (int, int)
203 LastUsage() *provider.Usage
204 Balance(ctx context.Context) (*billing.Balance, error)
205 Jobs() []jobs.View
206 Todos() []evidence.TodoItem
207 }
208
209 // SessionPersistence covers snapshotting a session and tearing down its on-disk
210 // state.
211 type SessionPersistence interface {
212 Snapshot() error
213 SnapshotForShutdown() error
214 SnapshotActivity() error
215 SessionCache() (hit, miss int)
216 BeginDestroySession(sessionPath string) SessionDestroyHandle
217 CloseAfterDestroy()
218 IsDestroyingSession(sessionPath string) bool
219 ReleaseResources()
220 }
221
222 // Input covers composing a turn's text (plan/goal/memory injection) and
223 // resolving @-references before submission.
224 type Input interface {
225 Compose(text string) string
226 ComposeSynthetic(text string) string
227 ResolveRefs(ctx context.Context, line string) (block string, errs []string)
228 HasRefs(line string) bool
229 ImageInputEnabled() bool
230 RegisterExternalFolderRef(path string) (token, displayPath string, err error)
231 }
232
233 // Settings covers runtime session settings that don't fit a richer domain.
234 type Settings interface {
235 SetResponseLanguage(lang string)
236 SetReasoningLanguage(lang string)
237 SetDisplayRecorder(fn func(content, display string))
238 }
239
240 // SessionAPI is the full driving port — the composition of every sub-port. A
241 // rich frontend (the HTTP server, the desktop app, the TUI) depends on this;
242 // leaner frontends (bot, acp) depend on just the sub-ports they use.
243 type SessionAPI interface {
244 Lifecycle
245 TurnControl
246 Approvals
247 Goals
248 SessionHistory
249 MemoryControl
250 Capabilities
251 Status
252 SessionPersistence
253 Input
254 Settings
255 }
256
257 // Compile-time proof that the concrete controller satisfies each sub-port and
258 // the full port, so frontend migrations to the interfaces are mechanical and can
259 // never silently drift from the implementation.
260 var (
261 _ Lifecycle = (*Controller)(nil)
262 _ TurnControl = (*Controller)(nil)
263 _ Approvals = (*Controller)(nil)
264 _ Goals = (*Controller)(nil)
265 _ SessionHistory = (*Controller)(nil)
266 _ MemoryControl = (*Controller)(nil)
267 _ Capabilities = (*Controller)(nil)
268 _ Status = (*Controller)(nil)
269 _ SessionPersistence = (*Controller)(nil)
270 _ Input = (*Controller)(nil)
271 _ Settings = (*Controller)(nil)
272 _ SessionAPI = (*Controller)(nil)
273 )
274
274 lines GO