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:
asepharyana
2026-07-12 11:28:39 +07:00
parent 7158d362fd
commit 2efd40ca88
124 changed files with 2379 additions and 19 deletions
+35
View File
@@ -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;
+24
View File
@@ -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);
+41
View File
@@ -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() {
+17
View File
@@ -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
+15
View File
@@ -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 {
+23
View File
@@ -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)