5.4 KiB
5.4 KiB
exit_plan_mode
Submits the current plan-mode plan for user approval.
Source
- Entry:
packages/coding-agent/src/tools/exit-plan-mode.ts - Model-facing prompt:
packages/coding-agent/src/prompts/tools/exit-plan-mode.md - Key collaborators:
packages/coding-agent/src/tools/plan-mode-guard.ts— resolves canonical plan paths during plan modepackages/coding-agent/src/plan-mode/approved-plan.ts— renames approved plan artifact after user approvalpackages/coding-agent/src/modes/interactive-mode.ts— approval popup, plan preview, mode exit, tool restorationpackages/coding-agent/src/plan-mode/state.ts— plan-mode state shape
Inputs
| Field | Type | Required | Description |
|---|---|---|---|
title |
string |
Yes | Final plan title. .md is optional; the runtime normalizes to local://<title>.md. Allowed characters: letters, numbers, _, -. |
Outputs
- Single-shot success result with
content[0].text = "Plan ready for approval.". detailscontains:planFilePath— current plan artifact path from plan-mode state, typicallylocal://PLAN.mdplanExists— whether that file existed at call timetitle— normalized title without.mdfinalPlanFilePath— normalized destination, alwayslocal://<title>.md
- The actual rename and mode transition happen later in the interactive controller after the user chooses an approval action.
Flow
execute()readssession.getPlanModeState()and rejects the call unlessstate.enabledis true.normalizePlanTitle()trims whitespace, rejects empty values, rejects/,\\, and.., appends.mdif missing, and enforces^[A-Za-z0-9_-]+\.md$.- The tool computes
finalPlanFilePath = local://<normalized>.mdand resolves both source and destination throughresolvePlanPath(...)to validate them against plan-mode path rules. - It
stats the current plan file path; if the plan artifact does not exist it throws aToolErrortelling the caller to write the finalized plan first. - On success it returns the approval-ready payload; it does not mutate files itself.
packages/coding-agent/src/modes/controllers/event-controller.tswatches successfulexit_plan_moderesults and forwardsdetailstoInteractiveMode.handleExitPlanModeTool(...).- The interactive controller aborts the agent, renders the current plan, and shows four choices:
Approve and execute,Approve and keep context,Refine plan,Stay in plan mode. - If the user approves,
#approvePlan(...)renameslocal://PLAN.mdtolocal://<title>.md, exits plan mode, restores the previous tool set, optionally clears session context, writes the approved plan into the new local root when context is reset, and injects a synthetic system prompt instructing execution from the finalized artifact.
Side Effects
- Filesystem
- Tool itself only
stats the current plan file. - Approval path later renames the plan artifact via
fs.rename(...)and may rewrite the approved plan into a fresh local root withBun.write(...).
- Tool itself only
- Session state
- Requires active plan-mode state.
- Approval flow aborts the current agent loop, exits plan mode, restores previous active tools, clears or preserves context depending on the user choice, and records the approved plan reference path.
- User-visible prompts / interactive UI
- Successful calls trigger a plan preview and an approval/refinement selector in interactive mode.
- Background work / cancellation
- The controller aborts the running agent before showing the popup to prevent repeated
exit_plan_modecalls.
- The controller aborts the running agent before showing the popup to prevent repeated
Limits & Caps
titleaccepts only[A-Za-z0-9_-]plus optional.md(packages/coding-agent/src/tools/exit-plan-mode.ts).- Destination must be under the
local:scheme; approval rename rejects non-local:source or destination paths (packages/coding-agent/src/plan-mode/approved-plan.ts). - In plan mode, only the plan file may be edited; other writes are blocked by
enforcePlanModeWrite(...)inpackages/coding-agent/src/tools/plan-mode-guard.ts.
Errors
- Plan mode inactive: throws
ToolError("Plan mode is not active."). - Empty title: throws
ToolError("Title is required and must not be empty."). - Path traversal / separators: throws
ToolError("Title must not contain path separators or '..'."). - Invalid characters: throws
ToolError("Title may only contain letters, numbers, underscores, or hyphens."). - Missing plan artifact: throws
ToolError("Plan file not found at ... Write the finalized plan ... before calling exit_plan_mode."). - Approval-time failures surface in the UI from
InteractiveMode.handleExitPlanModeTool(...), including destination already exists and rename failures fromrenameApprovedPlanFile(...).
Notes
- This tool is hidden/internal: it is injected when
plan.enabledis on and is not part of normal discoverable built-ins (packages/coding-agent/src/tools/index.ts,packages/coding-agent/src/session/agent-session.ts). - The tool returning success does not mean plan mode has ended; it only means the request was handed off to the approval UI.
resolvePlanPath(...)special-cases bare filenames matching the plan basename soPLAN.mdmaps back to the canonical session-scopedlocal://PLAN.mdartifact.Approve and keep contextskips the full conversation reset;Approve and executeclears context, then copies the approved plan into the new session-local artifact root before execution resumes.