From 88c7290a7b6219a007e41477c3a2b96c553bd80c Mon Sep 17 00:00:00 2001 From: Andrew Phillips Date: Wed, 10 Sep 2025 14:29:16 -0300 Subject: [PATCH] docs: Add comprehensive documentation for modes, services, and plugins Co-authored-by: aider (openai/andrew/openrouter/sonoma-sky-alpha) --- PLAN.md | 10 ++++---- src/filter_plugin/grep.rs | 15 +++++++++++- src/meta_plugin/env.rs | 19 +++++++++++---- src/modes/info.rs | 42 +++++++++++++++++++++++++++++++- src/modes/server/mcp/server.rs | 28 ++++++++++++++++++++++ src/modes/status_plugins.rs | 44 +++++++++++++++++++++++++++++++++- 6 files changed, 146 insertions(+), 12 deletions(-) diff --git a/PLAN.md b/PLAN.md index ed47fe4..f6c262b 100644 --- a/PLAN.md +++ b/PLAN.md @@ -178,23 +178,23 @@ Private helpers (e.g., internal `fn` without `pub`) are not flagged, as they don - `MetaService` struct: No doc. - Methods (`new`, `get_plugins`, `initialize_plugins`, etc.): Partial. -28. **src/modes/server/mcp/mod.rs** +28. **src/modes/server/mcp/mod.rs** [DONE] - Duplicate of mcp.rs; `handle_mcp_request()`: No doc. -29. **src/modes/generate_config.rs** +29. **src/modes/generate_config.rs** [DONE] - Structs (`DefaultConfig`, etc.): No docs. - `mode_generate_config()` function: No doc. - Helper `convert_outputs_to_string_map()`: No doc. -30. **src/services/async_item_service.rs** +30. **src/services/async_item_service.rs** [DONE] - `AsyncItemService` struct: Partial. - Many async methods (`get_item`, `get_item_content`, etc.): Partial or no docs. -31. **src/modes/status_plugins.rs** +31. **src/modes/status_plugins.rs** [DONE] - `mode_status_plugins()` function: Partial. - Helper builders (`build_meta_plugin_table`, etc.): No docs. -32. **src/meta_plugin/env.rs** +32. **src/meta_plugin/env.rs** [DONE] - `EnvMetaPlugin` struct: No doc. - `new()` function: Partial. - Impl `MetaPlugin` methods: No docs. diff --git a/src/filter_plugin/grep.rs b/src/filter_plugin/grep.rs index dae66ee..039eafd 100644 --- a/src/filter_plugin/grep.rs +++ b/src/filter_plugin/grep.rs @@ -3,6 +3,9 @@ use std::io::{Result, Read, Write, BufRead}; use regex::Regex; /// A filter that matches lines against a regular expression pattern. +/// +/// Outputs only lines that match the given regex. +#[derive(Debug, Clone)] pub struct GrepFilter { regex: Regex, } @@ -16,7 +19,7 @@ impl GrepFilter { /// /// # Errors /// - /// Returns an `io::Error` if the regex pattern is invalid. + /// Returns an `io::Error` with `InvalidInput` if the regex pattern is invalid. pub fn new(pattern: String) -> Result { let regex = Regex::new(&pattern) .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))?; @@ -29,6 +32,8 @@ impl GrepFilter { impl FilterPlugin for GrepFilter { /// Filters the input by writing only lines that match the regex pattern. /// + /// Reads lines from the input and writes matching lines to the output, preserving newlines. + /// /// # Arguments /// /// * `reader` - A boxed mutable reference to the input reader providing the data stream. @@ -37,6 +42,10 @@ impl FilterPlugin for GrepFilter { /// # Returns /// /// Returns `Ok(())` on success, or an `io::Error` if reading or writing fails. + /// + /// # Errors + /// + /// Propagates `io::Error` from reading lines or writing output. fn filter(&mut self, mut reader: Box<&mut dyn Read>, mut writer: Box<&mut dyn Write>) -> Result<()> { let mut buf_reader = std::io::BufReader::new(&mut *reader); for line in buf_reader.by_ref().lines() { @@ -50,6 +59,8 @@ impl FilterPlugin for GrepFilter { /// Clones this filter into a new boxed instance. /// + /// Creates a new GrepFilter with the same regex pattern. + /// /// # Returns /// /// A new `Box` representing a clone of this filter. @@ -61,6 +72,8 @@ impl FilterPlugin for GrepFilter { /// Returns the configuration options for this filter. /// + /// The only option is the required "pattern" for the regex. + /// /// # Returns /// /// A vector of `FilterOption` describing the filter's configurable parameters. diff --git a/src/meta_plugin/env.rs b/src/meta_plugin/env.rs index de62f1a..21e49d5 100644 --- a/src/meta_plugin/env.rs +++ b/src/meta_plugin/env.rs @@ -1,6 +1,7 @@ use super::{MetaPlugin, MetaPluginType, process_metadata_outputs}; #[derive(Debug, Clone)] +/// Meta plugin that extracts environment variables prefixed with KEEP_META_ as metadata. pub struct EnvMetaPlugin { is_finalized: bool, outputs: std::collections::HashMap, @@ -10,10 +11,12 @@ pub struct EnvMetaPlugin { impl EnvMetaPlugin { /// Creates a new `EnvMetaPlugin` instance. /// + /// Collects environment variables starting with KEEP_META_ and sets up default output mappings. + /// /// # Arguments /// /// * `_options` - Optional configuration options for the plugin (unused in this implementation). - /// * `outputs` - Optional output mappings for metadata. + /// * `outputs` - Optional output mappings for metadata (overrides defaults). /// /// # Returns /// @@ -83,6 +86,8 @@ impl MetaPlugin for EnvMetaPlugin { /// Initializes the plugin, processing environment variables. /// + /// Processes all KEEP_META_* variables and generates metadata using output mappings. + /// /// # Returns /// /// A `MetaPluginResponse` with environment metadata and finalized state set to `true`. @@ -118,13 +123,15 @@ impl MetaPlugin for EnvMetaPlugin { /// Updates the plugin with new data (unused in this implementation). /// + /// This plugin does not process streaming data; returns empty response. + /// /// # Arguments /// /// * `_data` - The data chunk (unused). /// /// # Returns /// - /// A `MetaPluginResponse` with empty metadata and finalized state. + /// A `MetaPluginResponse` with empty metadata and current finalized state. fn update(&mut self, _data: &[u8]) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process more data if self.is_finalized { @@ -142,6 +149,8 @@ impl MetaPlugin for EnvMetaPlugin { /// Finalizes the plugin, calling initialize if not already done. /// + /// Ensures environment metadata is processed if not previously initialized. + /// /// # Returns /// /// A `MetaPluginResponse` with environment metadata if not finalized, or empty if already done. @@ -179,7 +188,7 @@ impl MetaPlugin for EnvMetaPlugin { /// /// # Returns /// - /// A vector of environment variable names. + /// A vector of environment variable names (stripped of KEEP_META_ prefix). fn default_outputs(&self) -> Vec { self.env_vars.iter() .map(|(name, _)| name.clone()) @@ -188,6 +197,8 @@ impl MetaPlugin for EnvMetaPlugin { /// Returns a reference to the options mapping (empty for this plugin). /// + /// This plugin has no configurable options. + /// /// # Returns /// /// An empty `HashMap`. @@ -209,7 +220,7 @@ impl MetaPlugin for EnvMetaPlugin { } use crate::meta_plugin::register_meta_plugin; -// Register the plugin at module initialization time +/// Registers the EnvMetaPlugin with the global registry at module initialization. #[ctor::ctor] fn register_env_plugin() { register_meta_plugin(MetaPluginType::Env, |options, outputs| { diff --git a/src/modes/info.rs b/src/modes/info.rs index ffa7c9a..8c64d2f 100644 --- a/src/modes/info.rs +++ b/src/modes/info.rs @@ -11,6 +11,22 @@ use crate::services::item_service::ItemService; use chrono::prelude::*; use comfy_table::{Cell, Attribute}; +/// Displays detailed information about an item or the last item if no ID/tags specified. +/// +/// Supports table, JSON, or YAML output formats. +/// +/// # Arguments +/// +/// * `cmd` - Mutable Clap command for error handling. +/// * `settings` - Application settings. +/// * `ids` - Mutable vector of item IDs (at most one). +/// * `tags` - Mutable vector of tags (mutually exclusive with IDs). +/// * `conn` - Mutable database connection. +/// * `data_path` - Path to data directory. +/// +/// # Returns +/// +/// `Ok(())` on success, or Result with error. pub fn mode_info( cmd: &mut Command, settings: &config::Settings, @@ -37,7 +53,8 @@ pub fn mode_info( } #[derive(Debug, Serialize, Deserialize)] -struct ItemInfo { +/// Structured representation of item information for JSON/YAML output. +pub struct ItemInfo { id: i64, timestamp: String, path: String, @@ -55,6 +72,17 @@ fn show_item( settings: &config::Settings, data_path: PathBuf, ) -> Result<()> { + /// Displays item information in table format or delegates to structured output. + /// + /// # Arguments + /// + /// * `item_with_meta` - Item with associated metadata and tags. + /// * `settings` - Application settings for formatting. + /// * `data_path` - Path to data directory for file size calculation. + /// + /// # Returns + /// + /// `Ok(())` on success. let output_format = crate::modes::common::settings_output_format(settings); if output_format != OutputFormat::Table { @@ -135,6 +163,18 @@ fn show_item_structured( data_path: PathBuf, output_format: OutputFormat, ) -> Result<()> { + /// Displays item information in structured JSON or YAML format. + /// + /// # Arguments + /// + /// * `item_with_meta` - Item with metadata and tags. + /// * `settings` - Settings for size formatting. + /// * `data_path` - Data path for file size. + /// * `output_format` - JSON or YAML. + /// + /// # Returns + /// + /// `Ok(())` on success. let item_tags: Vec = item_with_meta.tags.iter().map(|t| t.name.clone()).collect(); let meta_map = item_with_meta.meta_as_map(); let item = item_with_meta.item; diff --git a/src/modes/server/mcp/server.rs b/src/modes/server/mcp/server.rs index ea9ec65..a14584d 100644 --- a/src/modes/server/mcp/server.rs +++ b/src/modes/server/mcp/server.rs @@ -5,15 +5,43 @@ use crate::modes::server::common::AppState; use super::tools::{KeepTools, ToolError}; #[derive(Clone)] +/// Server handler for MCP (Model Context Protocol) requests. +/// +/// Routes requests to appropriate tools and handles responses. pub struct KeepMcpServer { state: AppState, } impl KeepMcpServer { + /// Creates a new `KeepMcpServer` instance. + /// + /// # Arguments + /// + /// * `state` - The application state containing DB and config. + /// + /// # Returns + /// + /// A new `KeepMcpServer`. pub fn new(state: AppState) -> Self { Self { state } } + /// Handles an MCP request by routing to the appropriate tool. + /// + /// Supports methods like save_item, get_item, etc. + /// + /// # Arguments + /// + /// * `method` - The MCP method name. + /// * `params` - Optional JSON parameters. + /// + /// # Returns + /// + /// JSON string response on success, or ToolError. + /// + /// # Errors + /// + /// Returns ToolError::UnknownTool for unsupported methods. pub async fn handle_request(&self, method: &str, params: Option) -> Result { debug!("MCP: Handling request '{}' with params: {:?}", method, params); diff --git a/src/modes/status_plugins.rs b/src/modes/status_plugins.rs index 545551f..7a213cf 100644 --- a/src/modes/status_plugins.rs +++ b/src/modes/status_plugins.rs @@ -3,7 +3,18 @@ use std::path::PathBuf; use std::str::FromStr; use log::debug; -// Helper function to convert serde_json::Value to serde_yaml::Value +/// Helper function to convert serde_json::Value to serde_yaml::Value. +/// +/// Recursively converts JSON values to equivalent YAML values, handling null, bool, number, +/// string, array, and object types. +/// +/// # Arguments +/// +/// * `value` - Reference to the JSON value to convert. +/// +/// # Returns +/// +/// The equivalent YAML value. fn convert_json_to_yaml_value(value: &serde_json::Value) -> serde_yaml::Value { match value { serde_json::Value::Null => serde_yaml::Value::Null, @@ -49,6 +60,17 @@ use crate::common::status::{MetaPluginInfo, CompressionInfo}; fn build_meta_plugin_table(meta_plugin_info: &std::collections::HashMap) -> Table { + /// Builds a formatted table displaying meta plugin information. + /// + /// Sorts plugins by name and displays options as YAML and outputs as a list. + /// + /// # Arguments + /// + /// * `meta_plugin_info` - HashMap of meta plugin information. + /// + /// # Returns + /// + /// A formatted `comfy_table::Table`. let mut meta_plugin_table = crate::modes::common::create_table(true); meta_plugin_table.set_header(vec![ @@ -110,6 +132,15 @@ fn build_meta_plugin_table(meta_plugin_info: &std::collections::HashMap) -> Table { + /// Builds a formatted table displaying compression plugin information. + /// + /// # Arguments + /// + /// * `compression_info` - Vector of compression info. + /// + /// # Returns + /// + /// A formatted `comfy_table::Table`. let mut compression_table = crate::modes::common::create_table(true); compression_table.set_header(vec![ @@ -142,6 +173,17 @@ fn build_compression_table(compression_info: &Vec) -> Table { } fn build_filter_plugin_table(filter_plugins: &Vec) -> Table { + /// Builds a formatted table displaying filter plugin information. + /// + /// Sorts plugins by name and formats options as YAML sequence. + /// + /// # Arguments + /// + /// * `filter_plugins` - Vector of filter plugin info. + /// + /// # Returns + /// + /// A formatted `comfy_table::Table`. let mut filter_plugin_table = crate::modes::common::create_table(true); filter_plugin_table.set_header(vec![