diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 44d5cf66..fd70cf73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,18 +39,16 @@ jobs: with: components: clippy - uses: Swatinem/rust-cache@v2 - - run: cargo clippy --all-targets --all-features -- -D warnings + - run: cargo clippy --all-features -- -D clippy::correctness - # test: - # name: Test - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v4 - # - uses: dtolnay/rust-toolchain@stable - # - uses: Swatinem/rust-cache@v2 - # - run: cargo test --lib --all-features - # env: - # OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - run: cargo test --lib --all-features docs: name: Documentation @@ -60,24 +58,10 @@ jobs: - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: Check documentation build - run: cargo doc --no-deps --all-features + run: cargo doc -p vectorless --no-deps --all-features env: RUSTDOCFLAGS: -D warnings - # doctest: - # name: Doc Tests - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v4 - # - uses: dtolnay/rust-toolchain@stable - # - uses: Swatinem/rust-cache@v2 - # - name: Run documentation tests - # run: cargo test --doc --all-features - # continue-on-error: true # Allow doctest failures initially - # env: - # OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - - # Release build check build: name: Build runs-on: ubuntu-latest diff --git a/python/src/lib.rs b/python/src/lib.rs index c0649759..f6ff36ee 100644 --- a/python/src/lib.rs +++ b/python/src/lib.rs @@ -15,7 +15,9 @@ use ::vectorless::client::{ }; use ::vectorless::error::Error as RustError; use ::vectorless::metrics::IndexMetrics; -use ::vectorless::metrics::{LlmMetricsReport, MetricsReport, PilotMetricsReport, RetrievalMetricsReport}; +use ::vectorless::metrics::{ + LlmMetricsReport, MetricsReport, PilotMetricsReport, RetrievalMetricsReport, +}; // ============================================================ // Error Types @@ -679,9 +681,7 @@ impl PyLlmMetricsReport { fn __repr__(&self) -> String { format!( "LlmMetricsReport(calls={}, tokens={}, cost=${:.4})", - self.inner.total_calls, - self.inner.total_tokens, - self.inner.estimated_cost_usd, + self.inner.total_calls, self.inner.total_tokens, self.inner.estimated_cost_usd, ) } } diff --git a/rust/examples/advanced.rs b/rust/examples/advanced.rs index 2df75f9b..fa14e931 100644 --- a/rust/examples/advanced.rs +++ b/rust/examples/advanced.rs @@ -55,7 +55,10 @@ async fn main() -> vectorless::Result<()> { // Query let result = client - .query(QueryContext::new("What features does Vectorless provide?").with_doc_ids(vec![doc_id.clone()])) + .query( + QueryContext::new("What features does Vectorless provide?") + .with_doc_ids(vec![doc_id.clone()]), + ) .await?; println!("Query: What features does Vectorless provide?"); if let Some(item) = result.single() { diff --git a/rust/examples/index_directory.rs b/rust/examples/index_directory.rs index 922c38a5..29f6cb08 100644 --- a/rust/examples/index_directory.rs +++ b/rust/examples/index_directory.rs @@ -24,10 +24,7 @@ async fn main() -> vectorless::Result<()> { // Parse CLI arguments let args: Vec = std::env::args().collect(); - let dir = args - .get(1) - .map(|s| s.as_str()) - .unwrap_or("./samples"); + let dir = args.get(1).map(|s| s.as_str()).unwrap_or("./samples"); let recursive = !args.iter().any(|a| a == "--no-recursive"); // Build engine @@ -46,7 +43,11 @@ async fn main() -> vectorless::Result<()> { .map_err(|e| vectorless::Error::Config(e.to_string()))?; // Index directory - println!("{}indexing: {}", if recursive { "Recursively " } else { "" }, dir); + println!( + "{}indexing: {}", + if recursive { "Recursively " } else { "" }, + dir + ); let ctx = IndexContext::from_dir(dir, recursive); if ctx.is_empty() { @@ -81,9 +82,7 @@ async fn main() -> vectorless::Result<()> { let query = "What is this about?"; println!("\nQuerying: \"{query}\""); - let answer = engine - .query(vectorless::QueryContext::new(query)) - .await?; + let answer = engine.query(vectorless::QueryContext::new(query)).await?; for item in &answer.items { println!(" [{} score={:.2}]", item.doc_id, item.score); @@ -99,9 +98,7 @@ async fn main() -> vectorless::Result<()> { println!("\nMetrics:"); println!( " LLM: {} calls, {} tokens, ${:.4}", - report.llm.total_calls, - report.llm.total_tokens, - report.llm.estimated_cost_usd, + report.llm.total_calls, report.llm.total_tokens, report.llm.estimated_cost_usd, ); println!( " Retrieval: {} queries, avg score {:.2}", diff --git a/rust/src/client/builder.rs b/rust/src/client/builder.rs index 06519d8f..7fea2913 100644 --- a/rust/src/client/builder.rs +++ b/rust/src/client/builder.rs @@ -442,8 +442,7 @@ impl EngineBuilder { }; // Indexer uses pool.index() - let indexer = - crate::client::indexer::IndexerClient::with_llm(pool.index().clone()); + let indexer = crate::client::indexer::IndexerClient::with_llm(pool.index().clone()); // Retriever uses pool.retrieval() let retrieval_config = config.retrieval.clone(); @@ -462,9 +461,7 @@ impl EngineBuilder { retriever = retriever.with_memo_store(memo_store); } else { // Create default memo store with model from config - let memo_store = MemoStore::new() - .with_model(retrieval_model) - .with_version(1); + let memo_store = MemoStore::new().with_model(retrieval_model).with_version(1); retriever = retriever.with_memo_store(memo_store); } diff --git a/rust/src/client/engine.rs b/rust/src/client/engine.rs index ebb302f4..5c909c36 100644 --- a/rust/src/client/engine.rs +++ b/rust/src/client/engine.rs @@ -51,13 +51,13 @@ use crate::retrieval::{PipelineRetriever, RetrieveEventReceiver}; use crate::storage::{PersistedDocument, Workspace}; use crate::{DocumentTree, Error}; -use crate::events::EventEmitter; use super::index_context::{IndexContext, IndexSource}; use super::indexer::IndexerClient; use super::query_context::{QueryContext, QueryScope}; use super::retriever::RetrieverClient; use super::types::{DocumentInfo, FailedItem, IndexItem, IndexMode, IndexResult, QueryResult}; use super::workspace::WorkspaceClient; +use crate::events::EventEmitter; /// The main Engine client. /// @@ -485,7 +485,7 @@ impl Engine { /// Query a document with streaming results. /// - /// Returns a [`RetrieveEventReceiver`] that yields [`RetrieveEvent`](crate::retrieval::RetrieveEvent)s + /// Returns a receiver that yields retrieval events /// as the retrieval pipeline progresses through each stage. /// /// Only supports single-document scope (via `with_doc_ids` with one ID). diff --git a/rust/src/client/indexer.rs b/rust/src/client/indexer.rs index 693000b3..79c89b37 100644 --- a/rust/src/client/indexer.rs +++ b/rust/src/client/indexer.rs @@ -34,9 +34,9 @@ use crate::index::{ use crate::llm::LlmClient; use crate::storage::{DocumentMeta, PersistedDocument}; -use crate::events::{EventEmitter, IndexEvent}; use super::index_context::IndexSource; use super::types::{IndexOptions, IndexedDocument}; +use crate::events::{EventEmitter, IndexEvent}; /// Document indexing client. /// @@ -115,7 +115,11 @@ impl IndexerClient { let validation = crate::utils::validate_file(&path)?; if !validation.valid { return Err(Error::Parse( - validation.errors.first().cloned().unwrap_or_else(|| "Invalid file".to_string()), + validation + .errors + .first() + .cloned() + .unwrap_or_else(|| "Invalid file".to_string()), )); } for warning in &validation.warnings { @@ -162,7 +166,11 @@ impl IndexerClient { let validation = crate::utils::validate_content(content, format); if !validation.valid { return Err(Error::Parse( - validation.errors.first().cloned().unwrap_or_else(|| "Invalid content".to_string()), + validation + .errors + .first() + .cloned() + .unwrap_or_else(|| "Invalid content".to_string()), )); } @@ -199,7 +207,11 @@ impl IndexerClient { let validation = crate::utils::validate_bytes(bytes, format); if !validation.valid { return Err(Error::Parse( - validation.errors.first().cloned().unwrap_or_else(|| "Invalid bytes".to_string()), + validation + .errors + .first() + .cloned() + .unwrap_or_else(|| "Invalid bytes".to_string()), )); } diff --git a/rust/src/client/query_context.rs b/rust/src/client/query_context.rs index bb32d05a..24d5d8b0 100644 --- a/rust/src/client/query_context.rs +++ b/rust/src/client/query_context.rs @@ -171,7 +171,9 @@ mod tests { #[test] fn test_single_doc_scope() { let ctx = QueryContext::new("test").with_doc_ids(vec!["doc-1".to_string()]); - assert!(matches!(ctx.scope, QueryScope::Documents(ref ids) if ids == &["doc-1".to_string()])); + assert!( + matches!(ctx.scope, QueryScope::Documents(ref ids) if ids == &["doc-1".to_string()]) + ); } #[test] diff --git a/rust/src/client/retriever.rs b/rust/src/client/retriever.rs index f1b38a4d..3e826d0a 100644 --- a/rust/src/client/retriever.rs +++ b/rust/src/client/retriever.rs @@ -21,11 +21,11 @@ use std::sync::Arc; use tracing::info; -use crate::events::{EventEmitter, QueryEvent}; use super::types::QueryResultItem; use crate::config::Config; use crate::document::{DocumentTree, ReasoningIndex}; use crate::error::{Error, Result}; +use crate::events::{EventEmitter, QueryEvent}; use crate::retrieval::stream::RetrieveEventReceiver; use crate::retrieval::{RetrieveOptions, RetrieveResponse}; diff --git a/rust/src/client/workspace.rs b/rust/src/client/workspace.rs index 7a27d1d6..7f7b570c 100644 --- a/rust/src/client/workspace.rs +++ b/rust/src/client/workspace.rs @@ -30,8 +30,8 @@ use tracing::{debug, info}; use crate::error::Result; use crate::storage::{PersistedDocument, Workspace}; -use crate::events::{EventEmitter, WorkspaceEvent}; use super::types::DocumentInfo; +use crate::events::{EventEmitter, WorkspaceEvent}; /// Workspace management client. /// @@ -230,4 +230,4 @@ impl WorkspaceClient { pub async fn set_graph(&self, graph: &crate::graph::DocumentGraph) -> Result<()> { self.workspace.set_graph(graph).await } -} \ No newline at end of file +} diff --git a/rust/src/config/mod.rs b/rust/src/config/mod.rs index f2bedd85..0a347826 100644 --- a/rust/src/config/mod.rs +++ b/rust/src/config/mod.rs @@ -14,6 +14,7 @@ mod validator; pub(crate) use loader::ConfigLoader; pub(crate) use types::{ CacheConfig, CompressionAlgorithm, ConcurrencyConfig, Config, FallbackBehavior, FallbackConfig, - IndexerConfig, LlmClientConfig, LlmConfig, LlmMetricsConfig, LlmPoolConfig, MetricsConfig, OnAllFailedBehavior, - PilotMetricsConfig, RetrievalConfig, RetrievalMetricsConfig, SufficiencyConfig, SummaryConfig, + IndexerConfig, LlmClientConfig, LlmConfig, LlmMetricsConfig, LlmPoolConfig, MetricsConfig, + OnAllFailedBehavior, PilotMetricsConfig, RetrievalConfig, RetrievalMetricsConfig, + SufficiencyConfig, SummaryConfig, }; diff --git a/rust/src/error.rs b/rust/src/error.rs index 1564697e..42e10adf 100644 --- a/rust/src/error.rs +++ b/rust/src/error.rs @@ -4,7 +4,7 @@ //! Error types for the vectorless library. //! //! This module provides a comprehensive error type hierarchy for all operations. -//! All errors are consolidated into [`Error`] with specific variants for each category. +//! All errors are consolidated into [`enum@Error`] with specific variants for each category. use thiserror::Error; diff --git a/rust/src/index/pipeline/context.rs b/rust/src/index/pipeline/context.rs index 502d241e..4f38d0a6 100644 --- a/rust/src/index/pipeline/context.rs +++ b/rust/src/index/pipeline/context.rs @@ -296,7 +296,7 @@ impl IndexContext { /// Compute SHA-256 hash of the source content. fn compute_source_hash(input: &IndexInput) -> String { - use sha2::{Sha256, Digest}; + use sha2::{Digest, Sha256}; let hash = match input { IndexInput::File(path) => { // Hash the file path as proxy — actual content may not be readable yet diff --git a/rust/src/index/pipeline/executor.rs b/rust/src/index/pipeline/executor.rs index cee63645..e54750f4 100644 --- a/rust/src/index/pipeline/executor.rs +++ b/rust/src/index/pipeline/executor.rs @@ -81,7 +81,9 @@ impl PipelineExecutor { /// 7. `reasoning_index` - Build pre-computed reasoning index /// 8. `optimize` - Optimize tree pub fn with_llm(client: LlmClient) -> Self { - tracing::info!("PipelineExecutor::with_llm — cloning client to ParseStage + EnhanceStage + context"); + tracing::info!( + "PipelineExecutor::with_llm — cloning client to ParseStage + EnhanceStage + context" + ); let orchestrator = PipelineOrchestrator::new() .with_llm_client(client.clone()) .stage_with_priority(ParseStage::with_llm_client(client.clone()), 10) diff --git a/rust/src/index/pipeline/orchestrator.rs b/rust/src/index/pipeline/orchestrator.rs index 95ace65a..fc77dbc9 100644 --- a/rust/src/index/pipeline/orchestrator.rs +++ b/rust/src/index/pipeline/orchestrator.rs @@ -528,7 +528,9 @@ impl PipelineOrchestrator { ctx.stage_results.contains_key(name) }); if all_completed { - let names: Vec<&str> = group.stage_indices.iter() + let names: Vec<&str> = group + .stage_indices + .iter() .map(|&i| self.stages[i].stage.name()) .collect(); info!("Skipping already completed parallel group: {:?}", names); diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 780e1f09..7541d900 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -73,4 +73,6 @@ pub use graph::DocumentGraph; pub use events::{EventEmitter, IndexEvent, QueryEvent, WorkspaceEvent}; // Runtime metrics reports -pub use metrics::{IndexMetrics, LlmMetricsReport, MetricsReport, PilotMetricsReport, RetrievalMetricsReport}; +pub use metrics::{ + IndexMetrics, LlmMetricsReport, MetricsReport, PilotMetricsReport, RetrievalMetricsReport, +}; diff --git a/rust/src/utils/validation.rs b/rust/src/utils/validation.rs index fc18aee5..ae541c16 100644 --- a/rust/src/utils/validation.rs +++ b/rust/src/utils/validation.rs @@ -73,11 +73,10 @@ pub fn validate_file(path: &Path) -> Result { let ext = path.extension().and_then(|e| e.to_str()).unwrap_or(""); if DocumentFormat::from_extension(ext).is_none() { - return Ok(SourceValidation::invalid(vec![format!( - "Unsupported format: .{}", - ext - )]) - .with_warnings(warnings)); + return Ok( + SourceValidation::invalid(vec![format!("Unsupported format: .{}", ext)]) + .with_warnings(warnings), + ); } Ok(SourceValidation::valid().with_warnings(warnings))