feat: add vapora-doc-lifecycle adapter for documentation management
- Create VAPORA adapter for doc-lifecycle-core integration - DocLifecyclePlugin: Main plugin interface for orchestration - DocumenterIntegration: Integrates with Documenter agent - Configuration for VAPORA-specific settings Features: - Event-driven documentation processing (NATS) - Automatic classification and consolidation - RAG index generation with SurrealDB - mdBook site generation - Root files management (README, CHANGELOG, ROADMAP) Dependency structure: - Development: local path to doc-lifecycle-core - Production: will use crates.io version This enables gradual adoption: 1. Use standalone tool in any Rust project 2. Integrate into VAPORA for automatic processing 3. Share core library between both deployments
This commit is contained in:
parent
ca3fa91d5d
commit
5ea9e3f4de
23
crates/vapora-doc-lifecycle/Cargo.toml
Normal file
23
crates/vapora-doc-lifecycle/Cargo.toml
Normal file
@ -0,0 +1,23 @@
|
||||
[package]
|
||||
name = "vapora-doc-lifecycle"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = ["Jesus Perez <jesus@jesusperez.pro>"]
|
||||
license = "MIT"
|
||||
description = "VAPORA adapter for documentation lifecycle management"
|
||||
|
||||
[dependencies]
|
||||
doc-lifecycle-core = { path = "../../../Tools/doc-lifecycle-manager/crates/doc-lifecycle-core" }
|
||||
tokio = { version = "1.35", features = ["full"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
tracing = "0.1"
|
||||
anyhow = "1.0"
|
||||
thiserror = "1.0"
|
||||
|
||||
# VAPORA dependencies (will be added later)
|
||||
# vapora-shared = { path = "../vapora-shared" }
|
||||
# vapora-agents = { path = "../vapora-agents" }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.8"
|
||||
55
crates/vapora-doc-lifecycle/src/config.rs
Normal file
55
crates/vapora-doc-lifecycle/src/config.rs
Normal file
@ -0,0 +1,55 @@
|
||||
//! Configuration for doc-lifecycle VAPORA adapter
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Plugin configuration
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PluginConfig {
|
||||
/// Enable doc-lifecycle plugin
|
||||
pub enabled: bool,
|
||||
|
||||
/// Root directory for documentation
|
||||
pub docs_root: PathBuf,
|
||||
|
||||
/// Mode: minimal, standard, or full
|
||||
pub mode: String,
|
||||
|
||||
/// Classify on task completion
|
||||
pub auto_classify: bool,
|
||||
|
||||
/// Consolidate duplicates automatically
|
||||
pub auto_consolidate: bool,
|
||||
|
||||
/// Generate RAG index
|
||||
pub generate_rag_index: bool,
|
||||
|
||||
/// Generate mdBook site
|
||||
pub generate_mdbook: bool,
|
||||
|
||||
/// Language for documentation
|
||||
pub language: String,
|
||||
|
||||
/// NATS subject for task events
|
||||
pub nats_subject: String,
|
||||
|
||||
/// SurrealDB connection string
|
||||
pub surreal_url: String,
|
||||
}
|
||||
|
||||
impl Default for PluginConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
enabled: true,
|
||||
docs_root: PathBuf::from("docs"),
|
||||
mode: "standard".to_string(),
|
||||
auto_classify: true,
|
||||
auto_consolidate: true,
|
||||
generate_rag_index: true,
|
||||
generate_mdbook: true,
|
||||
language: "en".to_string(),
|
||||
nats_subject: "vapora.tasks.completed".to_string(),
|
||||
surreal_url: "surreal://localhost:8000".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
56
crates/vapora-doc-lifecycle/src/documenter.rs
Normal file
56
crates/vapora-doc-lifecycle/src/documenter.rs
Normal file
@ -0,0 +1,56 @@
|
||||
//! Documenter agent integration with doc-lifecycle
|
||||
|
||||
use crate::config::PluginConfig;
|
||||
use crate::plugin::DocLifecyclePlugin;
|
||||
use crate::Result;
|
||||
|
||||
/// Documenter agent integration
|
||||
#[derive(Debug)]
|
||||
pub struct DocumenterIntegration {
|
||||
plugin: DocLifecyclePlugin,
|
||||
config: PluginConfig,
|
||||
}
|
||||
|
||||
impl DocumenterIntegration {
|
||||
/// Create a new documenter integration
|
||||
pub fn new(config: PluginConfig) -> Result<Self> {
|
||||
let plugin = DocLifecyclePlugin::new(config.clone())?;
|
||||
|
||||
Ok(Self { plugin, config })
|
||||
}
|
||||
|
||||
/// Handle task completion event
|
||||
pub async fn on_task_completed(&mut self, task_id: &str) -> Result<()> {
|
||||
tracing::info!(
|
||||
"Documenter: Processing task completion for task {}",
|
||||
task_id
|
||||
);
|
||||
|
||||
// 1. Process documentation
|
||||
self.plugin.process_task_docs(task_id).await?;
|
||||
|
||||
// 2. Update root files (README, CHANGELOG, ROADMAP)
|
||||
self.update_root_files(task_id).await?;
|
||||
|
||||
// 3. Publish event for other agents
|
||||
self.publish_docs_updated_event(task_id).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn update_root_files(&self, _task_id: &str) -> Result<()> {
|
||||
// TODO: Update README, CHANGELOG, ROADMAP
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn publish_docs_updated_event(&self, _task_id: &str) -> Result<()> {
|
||||
// TODO: Publish to NATS
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get current configuration
|
||||
#[must_use]
|
||||
pub fn config(&self) -> &PluginConfig {
|
||||
&self.config
|
||||
}
|
||||
}
|
||||
41
crates/vapora-doc-lifecycle/src/error.rs
Normal file
41
crates/vapora-doc-lifecycle/src/error.rs
Normal file
@ -0,0 +1,41 @@
|
||||
//! Error types for VAPORA doc-lifecycle adapter
|
||||
|
||||
use std::fmt;
|
||||
|
||||
/// Result type for adapter operations
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Error type for adapter operations
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Core library error
|
||||
Core(doc_lifecycle_core::Error),
|
||||
/// Configuration error
|
||||
Config(String),
|
||||
/// NATS error
|
||||
NatsError(String),
|
||||
/// Database error
|
||||
DatabaseError(String),
|
||||
/// Other errors
|
||||
Other(Box<dyn std::error::Error + Send + Sync>),
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Core(e) => write!(f, "Core error: {}", e),
|
||||
Self::Config(msg) => write!(f, "Config error: {}", msg),
|
||||
Self::NatsError(msg) => write!(f, "NATS error: {}", msg),
|
||||
Self::DatabaseError(msg) => write!(f, "Database error: {}", msg),
|
||||
Self::Other(e) => write!(f, "{}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
impl From<doc_lifecycle_core::Error> for Error {
|
||||
fn from(err: doc_lifecycle_core::Error) -> Self {
|
||||
Self::Core(err)
|
||||
}
|
||||
}
|
||||
28
crates/vapora-doc-lifecycle/src/lib.rs
Normal file
28
crates/vapora-doc-lifecycle/src/lib.rs
Normal file
@ -0,0 +1,28 @@
|
||||
//! VAPORA Documentation Lifecycle Management Adapter
|
||||
//!
|
||||
//! This crate provides integration between VAPORA's agent orchestration
|
||||
//! and the doc-lifecycle-core library.
|
||||
//!
|
||||
//! Features:
|
||||
//! - Event-driven documentation processing
|
||||
//! - NATS JetStream integration for task events
|
||||
//! - SurrealDB vector store for RAG indexing
|
||||
//! - Automatic triggering on task completion
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![warn(missing_debug_implementations)]
|
||||
|
||||
pub mod plugin;
|
||||
pub mod documenter;
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
|
||||
pub use error::{Error, Result};
|
||||
|
||||
/// Re-export commonly used types
|
||||
pub mod prelude {
|
||||
pub use crate::plugin::DocLifecyclePlugin;
|
||||
pub use crate::documenter::DocumenterIntegration;
|
||||
pub use crate::config::PluginConfig;
|
||||
pub use crate::{Error, Result};
|
||||
}
|
||||
88
crates/vapora-doc-lifecycle/src/plugin.rs
Normal file
88
crates/vapora-doc-lifecycle/src/plugin.rs
Normal file
@ -0,0 +1,88 @@
|
||||
//! Doc-lifecycle plugin for VAPORA
|
||||
|
||||
use crate::config::PluginConfig;
|
||||
use crate::Result;
|
||||
use doc_lifecycle_core::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Main plugin interface for doc-lifecycle integration
|
||||
#[derive(Debug)]
|
||||
pub struct DocLifecyclePlugin {
|
||||
config: PluginConfig,
|
||||
classifier: Classifier,
|
||||
consolidator: Consolidator,
|
||||
rag_indexer: RagIndexer,
|
||||
mdbook_generator: Option<MdBookGenerator>,
|
||||
}
|
||||
|
||||
impl DocLifecyclePlugin {
|
||||
/// Create a new doc-lifecycle plugin
|
||||
pub fn new(config: PluginConfig) -> Result<Self> {
|
||||
let mdbook_generator = if config.generate_mdbook {
|
||||
let mdbook_config = doc_lifecycle_core::mdbook_generator::MdBookConfig::new(
|
||||
PathBuf::from("book"),
|
||||
"VAPORA Project".to_string(),
|
||||
);
|
||||
Some(MdBookGenerator::new(mdbook_config))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
config,
|
||||
classifier: Classifier::new(),
|
||||
consolidator: Consolidator::new(),
|
||||
rag_indexer: RagIndexer::new(),
|
||||
mdbook_generator,
|
||||
})
|
||||
}
|
||||
|
||||
/// Process documentation for a completed task
|
||||
pub async fn process_task_docs(&mut self, task_id: &str) -> Result<()> {
|
||||
tracing::info!("Processing task docs for task {}", task_id);
|
||||
|
||||
// 1. Classify documents
|
||||
if self.config.auto_classify {
|
||||
self.classify_session_docs(task_id).await?;
|
||||
}
|
||||
|
||||
// 2. Consolidate duplicates
|
||||
if self.config.auto_consolidate {
|
||||
self.consolidate_docs().await?;
|
||||
}
|
||||
|
||||
// 3. Generate RAG index
|
||||
if self.config.generate_rag_index {
|
||||
self.update_rag_index().await?;
|
||||
}
|
||||
|
||||
// 4. Generate mdBook
|
||||
if self.config.generate_mdbook {
|
||||
self.generate_mdbook().await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn classify_session_docs(&self, _task_id: &str) -> Result<()> {
|
||||
// TODO: Implement session doc classification
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn consolidate_docs(&self) -> Result<()> {
|
||||
// TODO: Implement consolidation
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn update_rag_index(&self) -> Result<()> {
|
||||
// TODO: Implement RAG index update
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn generate_mdbook(&self) -> Result<()> {
|
||||
if let Some(generator) = &self.mdbook_generator {
|
||||
generator.generate()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user