Enhance tool documentation and add new features
- Added module-level documentation for memory tools (`remember`, `recall`, `forget`) to clarify their purpose. - Improved documentation in `recall.rs` and `remember.rs` to describe the functionality and flow of memory entry operations. - Updated `mod.rs` to include descriptions for the tool trait and execution context. - Enhanced `plan.rs` with detailed comments on plan-mode signaling tools. - Documented text search tools in `search.rs` to explain their functionality. - Improved sequential-thinking tool documentation in `seqthink.rs`. - Added safety filter documentation in `shell_filter` for credential and git operations. - Enhanced utility tools documentation, including `cd`, `dir_cache_update`, and `todowrite`. - Improved rendering documentation in view modules (`chat`, `markdown`, `status`, `workflow`) to clarify rendering flows and purposes.
This commit is contained in:
@@ -1,3 +1,15 @@
|
||||
//! Chat transcript panel rendering.
|
||||
//!
|
||||
//! Flow: `draw_chat` turns `state.transcript_cache.messages` into a
|
||||
//! header + markdown-rendered body per message (via `super::markdown`),
|
||||
//! appends a streaming spinner line when a turn is in flight, then
|
||||
//! slices the combined line list to the currently visible scroll window
|
||||
//! before handing it to a ratatui `Paragraph`.
|
||||
//!
|
||||
//! Why: lines are recomputed every frame instead of cached, since
|
||||
//! markdown wrapping depends on the current terminal width, which can
|
||||
//! change between frames.
|
||||
|
||||
use ratatui::layout::Rect;
|
||||
use ratatui::style::{Style, Modifier};
|
||||
use ratatui::text::{Line, Span};
|
||||
@@ -5,6 +17,17 @@ use ratatui::widgets::{Block, Borders, Paragraph, Wrap};
|
||||
use ratatui::Frame;
|
||||
use super::theme::Theme;
|
||||
|
||||
/// Break a flat run of styled spans into `Line`s at embedded `\n` boundaries.
|
||||
///
|
||||
/// Flow: for each span, split its text on '\n' → push non-empty parts onto
|
||||
/// the current line's span buffer → on each newline boundary, flush the
|
||||
/// buffer into a new `Line` and start fresh.
|
||||
///
|
||||
/// Why: `render_markdown` produces a single Vec<Span> with newlines baked
|
||||
/// into span content; ratatui's Paragraph wants pre-split `Line`s to lay
|
||||
/// out and scroll correctly.
|
||||
///
|
||||
/// Return: at least one (possibly empty) `Line`, never an empty vec.
|
||||
fn split_spans_into_lines<'a>(spans: Vec<Span<'a>>) -> Vec<Line<'a>> {
|
||||
let mut lines = Vec::new();
|
||||
let mut current_spans = Vec::new();
|
||||
@@ -39,6 +62,7 @@ fn _role_name(role: &crate::dto::chat::message::Role) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
/// Map a message role to its short uppercase badge label for the chat header.
|
||||
fn role_badge(role: &crate::dto::chat::message::Role) -> &'static str {
|
||||
match role {
|
||||
crate::dto::chat::message::Role::User => "YOU",
|
||||
@@ -56,6 +80,17 @@ fn format_timestamp(ts: i64) -> String {
|
||||
format!("{:02}:{:02}", hrs, mins)
|
||||
}
|
||||
|
||||
/// Render the scrollable chat transcript panel.
|
||||
///
|
||||
/// Flow: build a header + markdown-rendered body Line list per message →
|
||||
/// append a streaming spinner line if a turn is in flight → slice the
|
||||
/// combined lines to the visible window based on scroll offset → wrap in
|
||||
/// a Paragraph and render.
|
||||
///
|
||||
/// Why: lines are computed fresh every frame rather than cached, since
|
||||
/// wrapping depends on the current terminal width.
|
||||
///
|
||||
/// Return: nothing; draws directly into `frame` at `area`.
|
||||
pub fn draw_chat(frame: &mut Frame, area: Rect, state: &crate::app::state::rest::AppStateRest) {
|
||||
let messages = &state.transcript_cache.messages;
|
||||
let scroll_offset = state.scroll.offset;
|
||||
|
||||
@@ -1,6 +1,30 @@
|
||||
//! Markdown-to-styled-spans rendering for the chat transcript.
|
||||
//!
|
||||
//! Flow: `render_markdown` walks a `pulldown_cmark` event stream and
|
||||
//! translates each markdown construct (headings, code blocks, links,
|
||||
//! emphasis, block quotes, lists) into styled `ratatui::text::Span`s,
|
||||
//! then optionally re-wraps the flat span list to a target column width.
|
||||
//!
|
||||
//! Why: ratatui has no built-in markdown renderer, so this module bridges
|
||||
//! `pulldown_cmark`'s event-based parser to ratatui's span/line model.
|
||||
|
||||
use ratatui::style::{Color, Modifier, Style};
|
||||
use ratatui::text::Span;
|
||||
|
||||
/// Render a markdown string into styled terminal spans, word-wrapped to `width`.
|
||||
///
|
||||
/// Flow: pulldown_cmark parses `text` into an event stream → each
|
||||
/// Start/End/Text/Code/Break event is translated into styled `Span`s
|
||||
/// (headings colored by level, code blocks green, links bracketed, etc.)
|
||||
/// → if `width > 0`, a second pass inserts manual newline spans whenever
|
||||
/// the running line length would exceed `width`.
|
||||
///
|
||||
/// Why: ratatui has no native markdown renderer, and the built-in `Wrap`
|
||||
/// widget wraps on grapheme count without honoring markdown structure,
|
||||
/// so wrapping is done manually here in terms of raw span byte length.
|
||||
///
|
||||
/// Return: a flat vec of styled spans; `chat::split_spans_into_lines`
|
||||
/// turns it back into `Line`s for the Paragraph widget.
|
||||
pub fn render_markdown(text: &str, width: u16) -> Vec<Span<'static>> {
|
||||
let mut spans = Vec::new();
|
||||
let parser = pulldown_cmark::Parser::new(text);
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
//! Top-level TUI render pipeline: layouts the terminal into chat / input
|
||||
//! / status regions, dispatches overlay rendering, and floats toast
|
||||
//! notifications over the top-right corner.
|
||||
|
||||
pub mod chat;
|
||||
pub mod markdown;
|
||||
pub mod status;
|
||||
@@ -11,6 +15,17 @@ use ratatui::widgets::{Block, Borders, Clear, Paragraph, Wrap};
|
||||
use ratatui::Frame;
|
||||
use theme::Theme;
|
||||
|
||||
/// Top-level render entry point called once per TUI frame.
|
||||
///
|
||||
/// Flow: split the frame into main / input / status regions → if an
|
||||
/// overlay is active, render it inside the main region; otherwise render
|
||||
/// the chat transcript → always render the input bar and status bar →
|
||||
/// overlay toast notifications in the top-right corner.
|
||||
///
|
||||
/// Why: a single function owns the layout so every state change
|
||||
/// re-renders the whole UI from a known template.
|
||||
///
|
||||
/// Return: nothing; writes directly into `frame`.
|
||||
pub fn draw(frame: &mut Frame, state: &crate::app::state::rest::AppStateRest) {
|
||||
let area = frame.area();
|
||||
|
||||
@@ -45,6 +60,18 @@ fn render_main_panel(frame: &mut Frame, area: Rect, state: &crate::app::state::r
|
||||
chat::draw_chat(frame, area, state);
|
||||
}
|
||||
|
||||
/// Render the active modal overlay (Help, Settings, Workflow, Bash, Editor, etc.).
|
||||
///
|
||||
/// Flow: compute a centered sub-area → clear it to make the rest of the
|
||||
/// frame visible behind → match on the Overlay variant to pick the
|
||||
/// panel's title, content Lines, and styling → render as a Paragraph or
|
||||
/// delegate to a specialized drawer (e.g. `workflow::draw_workflow_panel`).
|
||||
///
|
||||
/// Why: each Overlay variant has its own data sources (settings,
|
||||
/// session_runtime, app_config) and its own visual treatment, so they
|
||||
/// are dispatched individually rather than table-driven.
|
||||
///
|
||||
/// Return: nothing; draws directly into `frame`.
|
||||
fn render_overlay(frame: &mut Frame, area: Rect, overlay: crate::app::state::types::Overlay, state: &crate::app::state::rest::AppStateRest) {
|
||||
let overlay_area = centered_rect(area, 70, 60);
|
||||
|
||||
@@ -499,6 +526,20 @@ fn render_overlay(frame: &mut Frame, area: Rect, overlay: crate::app::state::typ
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the bottom input bar including the autocomplete dropdown above it.
|
||||
///
|
||||
/// Flow: if autocomplete is open and has candidates, draw a borderless
|
||||
/// dropdown anchored just above the input bar showing up to 10 candidates
|
||||
/// with the current selection highlighted → then render the prompt,
|
||||
/// placeholder, and the buffer with a single-character highlight under
|
||||
/// the cursor position.
|
||||
///
|
||||
/// Why: the cursor highlight is drawn by splitting the buffer at
|
||||
/// `state.input.cursor` and styling one character (or trailing space)
|
||||
/// with the highlight color, since ratatui Paragraph does not expose a
|
||||
/// native cursor widget.
|
||||
///
|
||||
/// Return: nothing; draws directly into `frame` at `area`.
|
||||
fn render_input_bar(frame: &mut Frame, area: Rect, state: &crate::app::state::rest::AppStateRest) {
|
||||
// Render autocomplete dropdown if visible
|
||||
if state.input.autocomplete_visible && !state.input.autocomplete_candidates.is_empty() {
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
//! Status bar rendering for the TUI.
|
||||
//!
|
||||
//! Flow: `draw_status_bar` reads live connection/turn state off
|
||||
//! `AppStateRest` every frame and paints a single-line bar at the top
|
||||
//! (or bottom, per layout) of the screen showing agent status, provider,
|
||||
//! and model.
|
||||
//!
|
||||
//! Why: kept as one small, self-contained render function rather than a
|
||||
//! widget struct, matching the other `view/*` modules' functional style.
|
||||
|
||||
use ratatui::layout::Rect;
|
||||
use ratatui::style::{Style, Modifier};
|
||||
use ratatui::text::{Line, Span};
|
||||
@@ -5,6 +15,13 @@ use ratatui::widgets::Block;
|
||||
use ratatui::Frame;
|
||||
use super::theme::Theme;
|
||||
|
||||
/// Render the single-line status bar showing connection state, provider, and model.
|
||||
///
|
||||
/// Flow: derive an agent status label/color from turn-in-flight and API
|
||||
/// connection state → build left ([zesdex] STATUS) and right
|
||||
/// (provider · model) span groups → render as one styled Line.
|
||||
///
|
||||
/// Return: nothing; draws directly into `frame` at `area`.
|
||||
pub fn draw_status_bar(frame: &mut Frame, area: Rect, state: &crate::app::state::rest::AppStateRest) {
|
||||
// Connection status — reflects actual agent readiness:
|
||||
// PROG → turn is in flight
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
//! Central color theme for the TUI.
|
||||
//!
|
||||
//! Flow: defines a single `Theme` marker struct with associated `Color`
|
||||
//! consts, consumed by every `view/*` render function so styling stays
|
||||
//! consistent and changeable from one place.
|
||||
//!
|
||||
//! Why: a zero-sized struct with associated consts (rather than an enum
|
||||
//! or a runtime-configured palette) keeps color lookups compile-time
|
||||
//! constant and allocation-free.
|
||||
|
||||
use ratatui::style::Color;
|
||||
|
||||
/// Central palette of terminal colors used across all TUI render functions.
|
||||
///
|
||||
/// Why: a zero-sized marker struct holding only associated consts, so
|
||||
/// every view module references colors as `Theme::NAME` instead of
|
||||
/// hardcoding `ratatui::style::Color` values inline.
|
||||
pub struct Theme;
|
||||
|
||||
impl Theme {
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
//! Workflow status panel rendering.
|
||||
//!
|
||||
//! Flow: `draw_workflow_panel` reads `state.session_runtime` and
|
||||
//! `state.workflow_engine` and renders a compact `List` of counters
|
||||
//! (messages, completed/pending tool calls, active bash jobs, agents,
|
||||
//! findings) plus the current auto-run phase.
|
||||
//!
|
||||
//! Why: shows a placeholder panel when there is no active session
|
||||
//! runtime, and only emits rows for counters that are nonzero, to keep
|
||||
//! the panel compact during simple single-turn sessions.
|
||||
|
||||
use ratatui::layout::Rect;
|
||||
use ratatui::style::{Style, Modifier};
|
||||
use ratatui::text::{Line, Span};
|
||||
@@ -5,6 +16,18 @@ use ratatui::widgets::{Block, Borders, List, ListItem};
|
||||
use ratatui::Frame;
|
||||
use super::theme::Theme;
|
||||
|
||||
/// Render the workflow status panel summarizing the active session runtime.
|
||||
///
|
||||
/// Flow: bail out with a "No active session" placeholder if
|
||||
/// `state.session_runtime` is None → otherwise build a list of status
|
||||
/// lines (message count, completed/pending tool calls, active bash jobs,
|
||||
/// agent/finding counts, auto-run phase) → render as a List widget.
|
||||
///
|
||||
/// Why: rows for pending tool queue, bash jobs, agents, and findings are
|
||||
/// only shown when their count is nonzero, to keep the panel compact
|
||||
/// during simple single-turn sessions.
|
||||
///
|
||||
/// Return: nothing; draws directly into `frame` at `area`.
|
||||
pub fn draw_workflow_panel(frame: &mut Frame, area: Rect, state: &crate::app::state::rest::AppStateRest) {
|
||||
let block = Block::default()
|
||||
.borders(Borders::ALL)
|
||||
|
||||
Reference in New Issue
Block a user