summaryrefslogtreecommitdiff
path: root/makima/src/daemon/tui/widgets
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-05-18 01:21:30 +0100
committerGitHub <noreply@github.com>2026-05-18 01:21:30 +0100
commitf240675da99bc7705e473b8f70a2628812aa4c10 (patch)
tree3ee2d24b431ccb8cd1a3013c86b34a5782a3e224 /makima/src/daemon/tui/widgets
parent0d996cf7590e3e52f424859c7d6f0e68640f119e (diff)
downloadsoryu-master.tar.gz
soryu-master.zip
chore: drop legacy contracts + supervisor task-grouping (#136)HEADmaster
The contracts table, supervisor task type, and all their backing machinery have been inert for several PRs. The directives system reads its own active contract body for spec text, and PR #135 removed the last LLM surface that spawned supervisors. This PR wipes the dead surface in one shot — the user authorised a DB wipe, so the migration drops every legacy table with CASCADE rather than carrying forward stub rows. Net change: −12k LOC across handlers, repository, state, models, the TUI, and the listen module. What's gone: - contracts, contract_chat_*, contract_events, contract_repositories, contract_type_templates tables. - supervisor_states, supervisor_heartbeats tables. - mesh_chat_conversations, mesh_chat_messages tables. - tasks.contract_id/is_supervisor/supervisor_task_id/supervisor_worktree_task_id columns. - directive_steps.contract_id/contract_type columns. - files.contract_id/contract_phase columns. - history_events.contract_id/phase columns. - The Contract/Supervisor/MeshChat handler + model + repository surface, plus the daemon TUI views that read them. - The standalone listen.rs websocket handler (orphaned with the LLM). What stays: - mesh_supervisor handler: trimmed to just the questions + orders backchannel used by `makima directive ask` / `create-order` (kept the URL prefix for CLI client compat). - directive_documents (the user-facing "contracts" surface). - pending_questions in-memory state for the directive Ask flow. cargo check, cargo test --lib (68 passed), tsc, and vite build all clean. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'makima/src/daemon/tui/widgets')
-rw-r--r--makima/src/daemon/tui/widgets/list_view.rs127
-rw-r--r--makima/src/daemon/tui/widgets/mod.rs4
-rw-r--r--makima/src/daemon/tui/widgets/preview_pane.rs21
-rw-r--r--makima/src/daemon/tui/widgets/search_input.rs82
-rw-r--r--makima/src/daemon/tui/widgets/status_bar.rs19
5 files changed, 0 insertions, 253 deletions
diff --git a/makima/src/daemon/tui/widgets/list_view.rs b/makima/src/daemon/tui/widgets/list_view.rs
deleted file mode 100644
index ff8269a..0000000
--- a/makima/src/daemon/tui/widgets/list_view.rs
+++ /dev/null
@@ -1,127 +0,0 @@
-//! List view widget with fuzzy match highlighting.
-
-use std::collections::HashSet;
-
-use ratatui::{
- prelude::*,
- widgets::{Block, Borders, List, ListItem, ListState},
-};
-
-use crate::daemon::tui::app::{App, ViewMode};
-
-/// Style for matched characters in search results
-const MATCH_HIGHLIGHT_COLOR: Color = Color::Yellow;
-const MATCH_HIGHLIGHT_MODIFIER: Modifier = Modifier::BOLD;
-
-/// Build a Line with highlighted characters based on matched indices
-fn build_highlighted_name(name: &str, matched_indices: &[usize]) -> Vec<Span<'static>> {
- if matched_indices.is_empty() {
- return vec![Span::raw(name.to_string())];
- }
-
- let matched_set: HashSet<usize> = matched_indices.iter().cloned().collect();
- let mut spans = Vec::new();
- let mut current_run = String::new();
- let mut is_highlighted = false;
-
- for (byte_idx, ch) in name.char_indices() {
- let should_highlight = matched_set.contains(&byte_idx);
-
- if should_highlight != is_highlighted {
- // Flush current run
- if !current_run.is_empty() {
- if is_highlighted {
- spans.push(Span::styled(
- current_run.clone(),
- Style::default()
- .fg(MATCH_HIGHLIGHT_COLOR)
- .add_modifier(MATCH_HIGHLIGHT_MODIFIER),
- ));
- } else {
- spans.push(Span::raw(current_run.clone()));
- }
- current_run.clear();
- }
- is_highlighted = should_highlight;
- }
-
- current_run.push(ch);
- }
-
- // Flush remaining
- if !current_run.is_empty() {
- if is_highlighted {
- spans.push(Span::styled(
- current_run,
- Style::default()
- .fg(MATCH_HIGHLIGHT_COLOR)
- .add_modifier(MATCH_HIGHLIGHT_MODIFIER),
- ));
- } else {
- spans.push(Span::raw(current_run));
- }
- }
-
- spans
-}
-
-/// Get status icon and color for an item
-fn get_status_display(status: Option<&str>) -> (&'static str, Color) {
- match status {
- Some("running") => ("▸", Color::Green),
- Some("done") => ("✓", Color::Blue),
- Some("failed") => ("✗", Color::Red),
- Some("pending") => ("○", Color::Yellow),
- Some("paused") => ("⏸", Color::Cyan),
- _ => (" ", Color::Gray),
- }
-}
-
-pub fn render(f: &mut Frame, area: Rect, app: &mut App) {
- let items: Vec<ListItem> = app
- .filtered_items
- .iter()
- .map(|filtered_item| {
- let item = &app.items[filtered_item.index];
- let (status_icon, status_color) = get_status_display(item.status.as_deref());
-
- // Build spans with highlighted matched characters
- let mut spans = vec![Span::styled(
- format!("{} ", status_icon),
- Style::default().fg(status_color),
- )];
-
- // Add name with match highlighting
- spans.extend(build_highlighted_name(&item.name, &filtered_item.matched_indices));
-
- ListItem::new(Line::from(spans))
- })
- .collect();
-
- let view_label = match app.view_mode {
- ViewMode::Tasks => "Tasks",
- ViewMode::Contracts => "Contracts",
- ViewMode::Files => "Files",
- };
-
- let title = format!(
- " {} ({}{}) ",
- view_label,
- app.filtered_items.len(),
- if app.filtered_items.len() != app.items.len() {
- format!("/{}", app.items.len())
- } else {
- String::new()
- }
- );
-
- let list = List::new(items)
- .block(Block::default().title(title).borders(Borders::ALL))
- .highlight_style(Style::default().add_modifier(Modifier::REVERSED))
- .highlight_symbol("> ");
-
- let mut state = ListState::default();
- state.select(Some(app.selected_index));
-
- f.render_stateful_widget(list, area, &mut state);
-}
diff --git a/makima/src/daemon/tui/widgets/mod.rs b/makima/src/daemon/tui/widgets/mod.rs
deleted file mode 100644
index ddea546..0000000
--- a/makima/src/daemon/tui/widgets/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-pub mod list_view;
-pub mod preview_pane;
-pub mod search_input;
-pub mod status_bar;
diff --git a/makima/src/daemon/tui/widgets/preview_pane.rs b/makima/src/daemon/tui/widgets/preview_pane.rs
deleted file mode 100644
index 84095d0..0000000
--- a/makima/src/daemon/tui/widgets/preview_pane.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-//! Preview pane widget.
-
-use ratatui::{
- prelude::*,
- widgets::{Block, Borders, Paragraph, Wrap},
-};
-
-use crate::daemon::tui::app::App;
-
-pub fn render(f: &mut Frame, area: Rect, app: &App) {
- let content = app
- .preview_content
- .as_deref()
- .unwrap_or("No preview available");
-
- let preview = Paragraph::new(content)
- .block(Block::default().title(" Preview ").borders(Borders::ALL))
- .wrap(Wrap { trim: true });
-
- f.render_widget(preview, area);
-}
diff --git a/makima/src/daemon/tui/widgets/search_input.rs b/makima/src/daemon/tui/widgets/search_input.rs
deleted file mode 100644
index 311b4f0..0000000
--- a/makima/src/daemon/tui/widgets/search_input.rs
+++ /dev/null
@@ -1,82 +0,0 @@
-//! Search input widget with match count and visual feedback.
-
-use ratatui::{
- prelude::*,
- widgets::{Block, Borders, Paragraph},
-};
-
-use crate::daemon::tui::app::{App, InputMode, ViewMode};
-
-/// Color for the search bar when there are no matches
-const NO_MATCH_COLOR: Color = Color::Red;
-/// Color for the search bar when actively searching
-const SEARCH_ACTIVE_COLOR: Color = Color::Yellow;
-
-pub fn render(f: &mut Frame, area: Rect, app: &App) {
- let view_label = match app.view_mode {
- ViewMode::Tasks => "Tasks",
- ViewMode::Contracts => "Contracts",
- ViewMode::Files => "Files",
- };
-
- let (matched, total) = app.match_count();
- let has_no_matches = app.has_no_matches();
- let is_searching = matches!(app.input_mode, InputMode::Search);
- let has_query = !app.search_query.is_empty();
-
- // Determine border style based on state
- let border_style = if has_no_matches {
- Style::default().fg(NO_MATCH_COLOR)
- } else if is_searching {
- Style::default().fg(SEARCH_ACTIVE_COLOR)
- } else {
- Style::default()
- };
-
- // Build the search input content
- let search_text = if app.search_query.is_empty() {
- if is_searching {
- " Type to search...".to_string()
- } else {
- " Press / to search".to_string()
- }
- } else {
- format!(" {}", app.search_query)
- };
-
- // Build the title with match count
- let title = if has_query {
- if has_no_matches {
- format!(" 🔍 Search [{}] - No matches ", view_label)
- } else {
- format!(" 🔍 Search [{}] - {}/{} matches ", view_label, matched, total)
- }
- } else {
- format!(" 🔍 Search [{}] ", view_label)
- };
-
- // Create input text with appropriate style
- let text_style = if app.search_query.is_empty() && !is_searching {
- Style::default().fg(Color::DarkGray)
- } else if has_no_matches {
- Style::default().fg(NO_MATCH_COLOR)
- } else {
- Style::default()
- };
-
- let input = Paragraph::new(Span::styled(search_text, text_style)).block(
- Block::default()
- .title(title)
- .borders(Borders::ALL)
- .border_style(border_style),
- );
-
- f.render_widget(input, area);
-
- // Show cursor in search mode
- if is_searching {
- // Calculate cursor position based on actual search query length
- let cursor_x = area.x + app.search_query.len() as u16 + 2;
- f.set_cursor_position(Position::new(cursor_x, area.y + 1));
- }
-}
diff --git a/makima/src/daemon/tui/widgets/status_bar.rs b/makima/src/daemon/tui/widgets/status_bar.rs
deleted file mode 100644
index 3357c58..0000000
--- a/makima/src/daemon/tui/widgets/status_bar.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-//! Status bar widget.
-
-use ratatui::{prelude::*, widgets::Paragraph};
-
-use crate::daemon::tui::app::{App, InputMode};
-
-pub fn render(f: &mut Frame, area: Rect, app: &App) {
- let keybindings = match app.input_mode {
- InputMode::Normal => {
- "↑↓:Navigate Enter:View e:Edit d:Delete Tab:Preview /:Search q:Quit"
- }
- InputMode::Search => "Type to search Enter:Select Esc:Cancel",
- InputMode::Confirm => "y:Confirm n:Cancel",
- };
-
- let status = Paragraph::new(keybindings).style(Style::default().bg(Color::DarkGray));
-
- f.render_widget(status, area);
-}