Files
2026-07-13 13:00:08 +08:00

245 lines
8.3 KiB
Go

package control
import (
"context"
"reasonix/internal/agent"
"reasonix/internal/autoresearch"
"reasonix/internal/billing"
"reasonix/internal/checkpoint"
"reasonix/internal/command"
"reasonix/internal/config"
"reasonix/internal/event"
"reasonix/internal/evidence"
"reasonix/internal/hook"
"reasonix/internal/jobs"
"reasonix/internal/memory"
"reasonix/internal/plugin"
"reasonix/internal/provider"
"reasonix/internal/skill"
)
// This file defines the driving port: the typed, segregated interface surface
// that frontends (cli, desktop, bot, acp, serve) consume instead of coupling to
// the concrete *Controller and its ~99 methods. Each frontend depends only on
// the sub-ports it actually uses (interface segregation), so e.g. the bot never
// sees checkpoint or memory methods.
//
// The sub-ports are also the intended decomposition boundary for Controller
// itself: the port comes first and gives the later collaborator splits a spec to
// follow. *Controller implements every sub-port (asserted below). The full
// SessionAPI composition will accrete here as the remaining frontends migrate.
// Lifecycle covers a session's identity and lifecycle: minting, resuming,
// clearing, and locating the active session.
type Lifecycle interface {
NewSession() error
ClearSession() error
Resume(s *agent.Session, path string)
SetSessionPath(p string)
SessionPath() string
SessionDir() string
Label() string
ModelRef() string
WorkspaceRoot() string
Close()
}
// TurnControl covers driving a model turn and observing its run state: the
// various submit/run entry points, cancellation, steering, and status reads.
type TurnControl interface {
Submit(input string)
SubmitDisplay(display, input string)
SubmitInvocationDisplay(display, input string, invocations []InvocationRequest)
SubmitEditedDisplay(display, input, original string)
SubmitHTTP(input string)
SubmitUserTurn(input, display string)
Send(input string)
SendWithRaw(input, raw string)
Run(ctx context.Context, input string) error
RunTurn(ctx context.Context, input string) error
RunShell(command string)
Cancel()
Steer(text string)
SteerConsumed() bool
Running() bool
CancelRequested() bool
RuntimeStatus() RuntimeStatus
Turn() int
History() []provider.Message
ToolResult(toolID string) *ToolResultData
}
// Approvals covers tool-approval and ask prompts plus the runtime approval
// posture (ask/auto/yolo). It mirrors the approvalManager surface.
type Approvals interface {
Approve(id string, allow, session, persist bool)
AnswerQuestion(id string, answers []event.AskAnswer)
Ask(ctx context.Context, questions []event.AskQuestion) ([]event.AskAnswer, error)
ReplayPendingPrompts()
PendingPrompt() bool
EnableInteractiveApproval()
ToolApprovalMode() string
SetToolApprovalMode(mode string)
AutoApproveTools() bool
SetAutoApproveTools(on bool)
Bypass() bool
SetBypass(on bool)
SetMode(plan, autoApproveTools bool)
}
// Goals covers the active-goal FSM and plan mode.
type Goals interface {
Goal() string
GoalStatus() string
SetGoal(goal string)
SetGoalWithResearchMode(goal string, researchMode GoalResearchMode)
GoalStrict(strict bool)
ClearGoal()
AutoResearchSummary() (*autoresearch.Summary, bool)
AutoResearchList() ([]autoresearch.Summary, bool)
AutoResearchFindings(limit int) ([]autoresearch.Finding, bool)
RecordAutoResearchEvidence(criterionID string, input AutoResearchEvidenceInput) error
AutoStartResearchGoal(input string) (string, bool)
ResetPlannerSession()
PlanMode() bool
SetPlanMode(v bool)
SetAutoPlan(mode string)
}
// SessionHistory covers checkpoint/rewind, branch/fork, and the log-restructuring
// operations (compact, summarize).
type SessionHistory interface {
Checkpoints() []checkpoint.Meta
CheckpointTurnsByMessageIndex() map[int]int
CheckpointHasBoundary(turn int) bool
Rewind(turn int, scope RewindScope) error
Fork(turn int) (string, error)
ForkNamed(turn int, name string) (string, error)
ForkSession(turn int, name string) (string, error)
Branch(name string) (string, error)
Branches() ([]agent.BranchInfo, error)
BranchTreeText() string
SwitchBranch(ref string) (agent.BranchInfo, error)
Compact(ctx context.Context, instructions string) error
CompactRatio() float64
SummarizeFrom(ctx context.Context, turn int) error
SummarizeUpTo(ctx context.Context, turn int) error
}
// MemoryControl covers session/project memory reads and mutations.
type MemoryControl interface {
Memory() *memory.Set
QuickAdd(scope memory.Scope, note string) (string, error)
SaveDoc(path, body string) (string, error)
SaveMemory(m memory.Memory) (string, error)
ForgetMemory(name string) error
QueueMemory(note string)
}
// Capabilities covers the session's pluggable surface — MCP servers, skills,
// slash commands, hooks — and resolving prompt/command/skill inputs.
type Capabilities interface {
Host() *plugin.Host
Commands() []command.Command
ReloadCommands(ctx context.Context) error
Skills() []skill.Skill
SlashSkills() []skill.Skill
AllSkills() []skill.Skill
DisabledSkills() []skill.Skill
SkillEnabled(name string) bool
SetSkillEnabled(name string, enabled bool) error
CreateSkill(name string, scope skill.Scope, content string) (string, error)
UpdateSkill(name string, scope skill.Scope, content string) error
DeleteSkill(name string, scope skill.Scope) error
HookRunner() *hook.Runner
CustomCommand(input string) (sent string, found bool)
MCPPrompt(ctx context.Context, input string) (sent string, found bool, err error)
RunSkill(input string) (sent string, found bool)
AddMCPServer(e config.PluginEntry) (int, error)
ConnectMCPServer(e config.PluginEntry) (int, error)
ConnectConfiguredMCPServer(name string) (int, error)
DisconnectMCPServer(name string) bool
RemoveMCPServer(name string) (disconnected bool, err error)
ConfiguredMCPNames() []string
DisconnectedMCPNames() []string
UnregisterMCPServerTools(name string) bool
ImportMCPEntries(entries []config.PluginEntry) (total, added, updated, connected, failed, skipped int, err error)
}
// Status covers read-only run/usage/billing telemetry and task list state.
type Status interface {
ContextSnapshot() (int, int)
LastUsage() *provider.Usage
Balance(ctx context.Context) (*billing.Balance, error)
Jobs() []jobs.View
Todos() []evidence.TodoItem
}
// SessionPersistence covers snapshotting a session and tearing down its on-disk
// state.
type SessionPersistence interface {
Snapshot() error
SnapshotActivity() error
SessionCache() (hit, miss int)
BeginDestroySession(sessionPath string) SessionDestroyHandle
CloseAfterDestroy()
IsDestroyingSession(sessionPath string) bool
ReleaseResources()
}
// Input covers composing a turn's text (plan/goal/memory injection) and
// resolving @-references before submission.
type Input interface {
Compose(text string) string
ComposeSynthetic(text string) string
ResolveRefs(ctx context.Context, line string) (block string, errs []string)
HasRefs(line string) bool
ImageInputEnabled() bool
RegisterExternalFolderRef(path string) (token, displayPath string, err error)
}
// Settings covers runtime session settings that don't fit a richer domain.
type Settings interface {
SetResponseLanguage(lang string)
SetReasoningLanguage(lang string)
SetMemoryCompilerEnabled(enabled bool)
SetMemoryCompilerVerbosity(verbosity string)
SetDisplayRecorder(fn func(content, display string))
}
// SessionAPI is the full driving port — the composition of every sub-port. A
// rich frontend (the HTTP server, the desktop app, the TUI) depends on this;
// leaner frontends (bot, acp) depend on just the sub-ports they use.
type SessionAPI interface {
Lifecycle
TurnControl
Approvals
Goals
SessionHistory
MemoryControl
Capabilities
Status
SessionPersistence
Input
Settings
}
// Compile-time proof that the concrete controller satisfies each sub-port and
// the full port, so frontend migrations to the interfaces are mechanical and can
// never silently drift from the implementation.
var (
_ Lifecycle = (*Controller)(nil)
_ TurnControl = (*Controller)(nil)
_ Approvals = (*Controller)(nil)
_ Goals = (*Controller)(nil)
_ SessionHistory = (*Controller)(nil)
_ MemoryControl = (*Controller)(nil)
_ Capabilities = (*Controller)(nil)
_ Status = (*Controller)(nil)
_ SessionPersistence = (*Controller)(nil)
_ Input = (*Controller)(nil)
_ Settings = (*Controller)(nil)
_ SessionAPI = (*Controller)(nil)
)