vtcode_core/tools/registry/plan_mode_facade.rs
1//! Plan mode state accessors for ToolRegistry.
2
3use crate::tools::handlers::PlanModeState;
4
5use super::ToolRegistry;
6
7impl ToolRegistry {
8 /// Enable plan mode (read-only enforcement).
9 ///
10 /// When enabled, mutating tools (`unified_file` writes/edits, `apply_patch`,
11 /// `unified_exec` runs, etc.)
12 /// are blocked and the agent can only read/analyze the codebase.
13 ///
14 /// `PlanModeState` is the single source of truth; this method delegates to it
15 /// so that `is_plan_mode()` and `plan_mode_state().is_active()` are always in
16 /// agreement.
17 pub fn enable_plan_mode(&self) {
18 let was_active = self.plan_mode_state.is_active();
19 self.plan_mode_state.enable();
20 if !was_active {
21 // Invalidate the tool catalog cache so the next snapshot reflects the
22 // plan-mode-filtered tool set rather than serving a stale pre-transition entry.
23 self.tool_catalog_state
24 .note_explicit_refresh("plan_mode_enabled");
25 }
26 }
27
28 /// Disable plan mode (allow mutating tools again).
29 pub fn disable_plan_mode(&self) {
30 let was_active = self.plan_mode_state.is_active();
31 self.plan_mode_state.disable();
32 if was_active {
33 // Invalidate the catalog cache so mutating tools reappear immediately.
34 self.tool_catalog_state
35 .note_explicit_refresh("plan_mode_disabled");
36 }
37 }
38
39 /// Check if plan mode is currently enabled.
40 ///
41 /// Reads directly from `PlanModeState` — the single authoritative flag.
42 #[inline]
43 pub fn is_plan_mode(&self) -> bool {
44 self.plan_mode_state.is_active()
45 }
46
47 /// Get the shared Plan Mode state (used by plan mode tools and pipeline transitions).
48 #[inline]
49 pub fn plan_mode_state(&self) -> PlanModeState {
50 self.plan_mode_state.clone()
51 }
52}