Documentation
¶
Overview ¶
Package mode hosts agent-mode and isolation tools: EnterPlanMode / ExitPlanMode (read-only planning) and EnterWorktree / ExitWorktree (filesystem-isolated worktrees).
Each pair is wired through a narrow controller supplied by the agent: PlanModeController mutates the owning agent's permission mode and reads the plan-file path off its workdir; WorktreeController switches the agent's workdir into / out of a git worktree and rebuilds workdir-bound active tools. See worktree.go / worktree_controller.go.
Index ¶
- Constants
- func CleanupSubagentWorktree(ctx context.Context, sess WorktreeSession, removeAlways bool) (bool, string)
- func Names() []tools.ToolName
- func PlanFilePath(workdir string) string
- type ControllerLookup
- type EnterPlanModeTool
- type EnterWorktreeTool
- type ExitPlanModeTool
- type ExitWorktreeTool
- type PlanModeController
- type WorktreeController
- type WorktreeControllerLookup
- type WorktreeSession
Constants ¶
const PlanFileName = "current.md"
PlanFileName is the workdir-relative filename EnterPlanMode prepares and ExitPlanMode reads. One plan per session — keeps state trivial. Future phases can grow this to named plans if needed.
Variables ¶
This section is empty.
Functions ¶
func CleanupSubagentWorktree ¶
func CleanupSubagentWorktree(ctx context.Context, sess WorktreeSession, removeAlways bool) (bool, string)
CleanupSubagentWorktree tears down a worktree created by CreateForSubagent. If the worktree has any uncommitted changes the caller can decide to keep it (return the path to the user) instead of removing it. RemoveAlways=true forces removal regardless.
Returns (wasRemoved, summary). On wasRemoved=false the worktree is still on disk; summary describes why (e.g. "had 3 uncommitted file(s)").
func PlanFilePath ¶
PlanFilePath returns the absolute path of the active session's plan file given a workdir. Exposed so tests and the user-guide doc can reference the canonical location.
Types ¶
type ControllerLookup ¶
type ControllerLookup func() PlanModeController
ControllerLookup is the late-bound factory closure passed to the EnterPlanMode / ExitPlanMode constructors. Returning nil disables the tool — Execute surfaces a clear "no controller installed" error instead of crashing.
type EnterPlanModeTool ¶
type EnterPlanModeTool struct {
// contains filtered or unexported fields
}
EnterPlanModeTool flips the session into plan mode, stashes the prior mode for restore, and prepares an empty plan file the model writes to.
func NewEnterPlanMode ¶
func NewEnterPlanMode(lookup ControllerLookup) *EnterPlanModeTool
NewEnterPlanMode constructs the tool with a late-bound controller lookup. The lookup is invoked once per Execute call — passing a closure (rather than the controller directly) lets toolset.Build resolve the agent after agent.New returns.
func (*EnterPlanModeTool) Description ¶
func (t *EnterPlanModeTool) Description() string
func (*EnterPlanModeTool) Execute ¶
func (t *EnterPlanModeTool) Execute(_ context.Context, logger *slog.Logger, _ json.RawMessage) (tools.Result, error)
func (*EnterPlanModeTool) Name ¶
func (t *EnterPlanModeTool) Name() string
func (*EnterPlanModeTool) Schema ¶
func (t *EnterPlanModeTool) Schema() json.RawMessage
type EnterWorktreeTool ¶
type EnterWorktreeTool struct {
// contains filtered or unexported fields
}
EnterWorktreeTool creates `.evva/worktrees/<slug>/` on a new branch `worktree-<slug>` and switches the agent's workdir into it.
func NewEnterWorktree ¶
func NewEnterWorktree(lookup WorktreeControllerLookup) *EnterWorktreeTool
func (*EnterWorktreeTool) Description ¶
func (t *EnterWorktreeTool) Description() string
func (*EnterWorktreeTool) Execute ¶
func (t *EnterWorktreeTool) Execute(ctx context.Context, logger *slog.Logger, input json.RawMessage) (tools.Result, error)
func (*EnterWorktreeTool) Name ¶
func (t *EnterWorktreeTool) Name() string
func (*EnterWorktreeTool) Schema ¶
func (t *EnterWorktreeTool) Schema() json.RawMessage
type ExitPlanModeTool ¶
type ExitPlanModeTool struct {
// contains filtered or unexported fields
}
ExitPlanModeTool reads the plan file, asks the user to approve, and restores the pre-plan permission mode on approval. Rejection leaves the session in ModePlan with the user's reason surfaced to the model.
func NewExitPlanMode ¶
func NewExitPlanMode(lookup ControllerLookup) *ExitPlanModeTool
func (*ExitPlanModeTool) Description ¶
func (t *ExitPlanModeTool) Description() string
func (*ExitPlanModeTool) Execute ¶
func (t *ExitPlanModeTool) Execute(ctx context.Context, logger *slog.Logger, input json.RawMessage) (tools.Result, error)
func (*ExitPlanModeTool) Name ¶
func (t *ExitPlanModeTool) Name() string
func (*ExitPlanModeTool) Schema ¶
func (t *ExitPlanModeTool) Schema() json.RawMessage
type ExitWorktreeTool ¶
type ExitWorktreeTool struct {
// contains filtered or unexported fields
}
ExitWorktreeTool tears down (or keeps) a worktree session opened by EnterWorktree, restoring the agent's original workdir.
func NewExitWorktree ¶
func NewExitWorktree(lookup WorktreeControllerLookup) *ExitWorktreeTool
func (*ExitWorktreeTool) Description ¶
func (t *ExitWorktreeTool) Description() string
func (*ExitWorktreeTool) Execute ¶
func (t *ExitWorktreeTool) Execute(ctx context.Context, logger *slog.Logger, input json.RawMessage) (tools.Result, error)
func (*ExitWorktreeTool) Name ¶
func (t *ExitWorktreeTool) Name() string
func (*ExitWorktreeTool) Schema ¶
func (t *ExitWorktreeTool) Schema() json.RawMessage
type PlanModeController ¶
type PlanModeController interface {
PermissionMode() permission.Mode
SetPermissionMode(m permission.Mode)
PrePlanMode() permission.Mode
SetPrePlanMode(m permission.Mode)
Workdir() string
Broker() permission.Broker
AgentID() string
}
PlanModeController is the seam between the EnterPlanMode / ExitPlanMode tools and the owning agent. The agent satisfies it directly; the tool constructors take a lookup closure (returns a PlanModeController) so builtin registration can stay late-bound — the agent installs itself after toolset.NewToolState runs.
The interface is intentionally narrow: only what the two plan-mode tools actually touch. Permission mode mutation, the pre-plan stash (used by ExitPlanMode to restore), the workdir (for the plan-file path), the approval broker (for ExitPlanMode's user-approval gate), and the AgentID that the broker uses to route the approval event.
type WorktreeController ¶
type WorktreeController interface {
Workdir() string
SwitchWorkdir(path string) error
WorktreeSession() *WorktreeSession
BeginWorktreeSession(s WorktreeSession)
EndWorktreeSession()
AgentID() string
Logger() *slog.Logger
}
WorktreeController is the seam between the EnterWorktree / ExitWorktree tools and the owning agent — same shape and lifecycle as PlanModeController: the agent satisfies it directly, the tool constructors take a lookup closure so the agent can install itself after toolset construction without an init ordering hazard.
SwitchWorkdir is the load-bearing call: implementations rebuild any active tool that captured the OLD workdir at construction time (filesystem tools, the bash tool), reload the EVVA.md / USER_PROFILE.md memory snapshot from the new path, and re-render the system prompt so the next LLM turn sees the new working directory.
BeginWorktreeSession / EndWorktreeSession bracket a logical session; while a session is live, WorktreeSession() returns a non-nil pointer so EnterWorktree can refuse re-entry and ExitWorktree knows whether to no-op or actually tear the worktree down.
type WorktreeControllerLookup ¶
type WorktreeControllerLookup func() WorktreeController
WorktreeControllerLookup is the late-bound factory closure passed to the EnterWorktree / ExitWorktree constructors. Returning nil disables the tool — Execute surfaces a clear "no controller installed" error instead of crashing.
type WorktreeSession ¶
type WorktreeSession struct {
// OriginalWorkdir is the workdir the agent was in before EnterWorktree
// fired. ExitWorktree restores it.
OriginalWorkdir string
// Path is the absolute path to the worktree directory.
Path string
// Branch is the branch name created with `git worktree add -b`.
Branch string
// Slug is the flattened slug used to compose Path and Branch — kept
// for logging and the tool's confirmation message.
Slug string
// CreatedBySubagent marks worktrees the AgentTool's isolation path
// created (vs the user-invoked EnterWorktree tool). The post-run
// cleanup in spawn.go uses this to decide whether to auto-remove on
// clean exit.
CreatedBySubagent bool
CreatedAt time.Time
}
WorktreeSession records the metadata the worktree tools and AgentTool isolation need to clean up a worktree on exit. It is also what the subagent spawner threads into a child constructed under `isolation: "worktree"` — the child carries it so its own ExitWorktree (rarely invoked from a subagent but possible) and the post-run cleanup path in spawn.go agree on what to tear down.
func CreateForSubagent ¶
func CreateForSubagent(ctx context.Context, parentWorkdir, agentName string) (WorktreeSession, error)
CreateForSubagent provisions a worktree for an AgentTool isolation spawn. It is callable from internal/agent/spawn.go (no controller involved — the child agent's workdir is fixed at construction). Returns the worktree session metadata so spawn.go can:
- construct the child with cfg.WorkDir = session.Path
- tear down the worktree after the child exits (clean-exit path) or surface its path back to the parent (dirty-exit path).
agentName is folded into the slug so panel rows / logs / branch names stay readable; if the child name is empty, a random suffix is used.