diff --git a/crates/maestro-tui/src/draft.rs b/crates/maestro-tui/src/draft.rs index a9ccee7..8f5cf96 100644 --- a/crates/maestro-tui/src/draft.rs +++ b/crates/maestro-tui/src/draft.rs @@ -41,8 +41,10 @@ use std::time::{Duration, Instant}; use chrono::{DateTime, Utc}; use maestro_config::{builtin_presets, custom_preset}; -use maestro_protocol::display::abbreviate_dir; -use maestro_protocol::{BranchInfo, CreateSessionRequest, Project, SpawnPreset, WorktreeSpec}; +use maestro_protocol::display::{abbreviate_dir, command_tool}; +use maestro_protocol::{ + BranchInfo, CreateSessionRequest, Project, SessionView, SpawnPreset, WorktreeSpec, +}; use ratatui::layout::{Constraint, Layout, Rect}; use ratatui::style::{Modifier, Style}; use ratatui::text::{Line, Span}; @@ -86,9 +88,11 @@ pub enum DraftField { /// apply immediately, mirroring the web form's per-click choice. WorktreeChoice, Name, - /// Disclosure collapsing the worktree/branch controls below (#93). + /// Disclosure collapsing the optional view and worktree controls below. /// Closed by default; Enter / Space toggles. Advanced, + /// ACP-backed transcript instead of a terminal. Claude Code only. + StructuredToggle, /// Worktree on/off for this session (#65). Enter / Space toggles. WorktreeToggle, /// New-vs-existing branch source; Left / Right switches. @@ -251,6 +255,9 @@ pub struct DraftPane { /// "Advanced options" disclosure (#93). Closed by default — most spawns /// take the default target. pub advanced_collapsed: bool, + /// ACP-backed structured transcript. Off by default and supported only + /// when the resolved command is Claude Code. + pub structured_view: bool, /// Enclosing repository of the chosen target — from the project scan for /// picked rows, `/api/gitroot` for raw paths. `None` until known. pub base_repo: Option, @@ -311,6 +318,7 @@ impl Default for DraftPane { name_touched: false, worktree_enabled: true, advanced_collapsed: true, + structured_view: false, base_repo: None, probed_cwd: None, probe_seq: 0, @@ -348,6 +356,7 @@ impl DraftPane { .position(|p| !p.command.is_empty()) .unwrap_or(0); self.apply_seed_command(); + self.clear_unsupported_structured_view(); } /// Land a seeded command on the tile that runs it: its own preset when the @@ -663,6 +672,22 @@ impl DraftPane { } } + fn supports_structured_view(&self) -> bool { + command_tool(self.command()) == Some("claude") + } + + fn clear_unsupported_structured_view(&mut self) { + if !self.supports_structured_view() { + self.structured_view = false; + } + } + + pub fn toggle_structured_view(&mut self) { + if self.supports_structured_view() { + self.structured_view = !self.structured_view; + } + } + /// The chosen working directory: a picked project row, else the raw path /// input when it holds something. pub fn cwd(&self) -> Option { @@ -694,7 +719,11 @@ impl DraftPane { } let worktree = self.build_worktree()?; Ok(CreateSessionRequest { - view: Default::default(), + view: if self.structured_view && self.supports_structured_view() { + SessionView::Structured + } else { + SessionView::Terminal + }, cwd, command: command.to_string(), env: Default::default(), @@ -754,6 +783,9 @@ impl DraftPane { order.push(DraftField::Name); order.push(DraftField::Advanced); if !self.advanced_collapsed { + if self.supports_structured_view() { + order.push(DraftField::StructuredToggle); + } if !self.cwd_raw_visible && self.selected_group_key.is_some() { order.push(DraftField::WorktreeChoice); } @@ -795,6 +827,7 @@ impl DraftPane { } self.selected_preset = ((self.selected_preset as i32) + delta).rem_euclid(len as i32) as usize; + self.clear_unsupported_structured_view(); } /// Step-one boxes surviving the type-to-filter, in display order. A @@ -1001,9 +1034,9 @@ impl DraftPane { // Two fields keep their own Enter instead: `DirPicker`, whose // highlighted row isn't the picked one until a first Enter chooses // it (the next Enter, now that it's active, falls through to - // submit); and the disclosure/toggle pair (`Advanced`, - // `WorktreeToggle`), which activate on Enter like a button rather - // than submitting, same as the web form's own `