Skip to content

feat: centralized FocusMode state machine for TUI input dispatch#60

Merged
yishuiliunian merged 2 commits intomainfrom
feat/tui-focus-mode-state-machine
Apr 1, 2026
Merged

feat: centralized FocusMode state machine for TUI input dispatch#60
yishuiliunian merged 2 commits intomainfrom
feat/tui-focus-mode-state-machine

Conversation

@yishuiliunian
Copy link
Copy Markdown
Contributor

Summary

  • Introduce FocusMode enum (Input / AgentPanel) to replace implicit conditional checks for agent panel navigation
  • Agent panel now scrolls with ↑ N more / ↓ N more indicators when >5 agents
  • 46 new test cases covering mode transitions, key dispatch, and scroll logic

Changes

New type: FocusMode in app/types.rs — orthogonal to focused_agent (mode = which region, focus = which agent)

Input dispatch refactor (input/mod.rs):

  • handle_normal_key split into handle_agent_panel_key / handle_input_mode_key
  • AgentPanel: Up/Down navigate agents, Enter drills in, Tab/Esc exit, Char/Backspace auto-switch to Input
  • Ctrl+P/N are mode-aware (agent nav in AgentPanel, history in Input)

Dispatch logic (key_dispatch_ops.rs):

  • enter_agent_panel: validates live agents, recovers stale focused_agent
  • cycle_agent_focus: auto-exits AgentPanel when no agents remain
  • adjust_agent_scroll: keeps focused agent in visible 5-row window

Rendering (views/agent_panel.rs):

  • Sliding window render with ↑ N more / ↓ N more scroll indicators
  • panel_height uses clamped offset for layout consistency

Tests (4 new files):

  • focus_mode_test.rs — mode transition coverage
  • focus_panel_keys_test.rs — key behavior per mode
  • enter_panel_test.rs — enter_agent_panel dispatch logic
  • cycle_focus_test.rs — cycling, wrap-around, scroll boundaries

Test plan

  • bazel build //... passes
  • bazel build //... --config=clippy zero warnings
  • bazel test //... — 46/46 pass
  • CI passes

Introduce FocusMode enum (Input / AgentPanel) to replace implicit
conditional checks for agent panel navigation. Different modes produce
different key behaviors, and the agent list now scrolls when there are
more than 5 agents.

Key changes:
- FocusMode dispatches handle_normal_key into mode-specific handlers
- AgentPanel mode: Up/Down navigate agents, Enter drills in, Tab/Esc exit
- Typing auto-switches back to Input mode
- Scrollable agent list with ↑/↓ indicators
- Ctrl+P/N are mode-aware (agent nav in AgentPanel, history in Input)
- Stale focused_agent auto-recovers on re-entry
- 46 new test cases across 4 test files
@yishuiliunian yishuiliunian merged commit 2e3fadd into main Apr 1, 2026
3 checks passed
yishuiliunian added a commit that referenced this pull request Apr 2, 2026
…user approval (#60)

Align Plan mode with Claude Code's plan-approve-execute pattern:

- PlanFile: session-scoped plan file with slug collision retry, path matching
  for relative/absolute paths, and read with NotFound vs IO error distinction
- PlanModeState: atomic snapshot of pre-plan mode/permission/tool-filter,
  restored on ExitPlanMode via take() — prevents inconsistent partial state
- EnterPlanMode: user consent, sub-agent guard, mkdir rollback on failure
- ExitPlanMode: validates mode + plan file, reads plan, requests approval
  via Frontend trait, injects approved plan into tool_result context
- Hard enforcement: dual-layer tool filtering (LLM-side via llm_params +
  runtime-side via tools_check), Write/Edit path-restricted to plan file
- System-reminder: wraps non-intercepted tool results with plan mode rules
- Fragment: 5-phase workflow (Explore→Design→Review→Write→Approve)
- mode.system_prompt_suffix() returns empty for Plan to avoid conflict
  with Fragment instructions
- 26 new tests across 3 files covering PlanFile, Enter/Exit interception,
  tool filtering, and system-reminder wrapping
yishuiliunian added a commit that referenced this pull request Apr 2, 2026
…user approval (#61)

* chore: ignore

* feat: enhance Plan mode with 5-phase workflow, hard enforcement, and user approval (#60)

Align Plan mode with Claude Code's plan-approve-execute pattern:

- PlanFile: session-scoped plan file with slug collision retry, path matching
  for relative/absolute paths, and read with NotFound vs IO error distinction
- PlanModeState: atomic snapshot of pre-plan mode/permission/tool-filter,
  restored on ExitPlanMode via take() — prevents inconsistent partial state
- EnterPlanMode: user consent, sub-agent guard, mkdir rollback on failure
- ExitPlanMode: validates mode + plan file, reads plan, requests approval
  via Frontend trait, injects approved plan into tool_result context
- Hard enforcement: dual-layer tool filtering (LLM-side via llm_params +
  runtime-side via tools_check), Write/Edit path-restricted to plan file
- System-reminder: wraps non-intercepted tool results with plan mode rules
- Fragment: 5-phase workflow (Explore→Design→Review→Write→Approve)
- mode.system_prompt_suffix() returns empty for Plan to avoid conflict
  with Fragment instructions
- 26 new tests across 3 files covering PlanFile, Enter/Exit interception,
  tool filtering, and system-reminder wrapping

* fix: resolve rustfmt formatting issues in plan mode files
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant