Initial scaffold: GyanDoot v2.0 in Rust

Full Cargo workspace with 11 crates:
- gyandoot-core: Shared types, config, error types
- gyandoot-agent: Agent loop, tool execution, context compression
- gyandoot-providers: LLM provider abstraction (OpenAI, Anthropic, Ollama)
- gyandoot-memory: MemPalace persistent memory system
- gyandoot-platform: Platform adapters (Telegram, Discord, Webhook, CLI)
- gyandoot-security: Credential vault, sanitizer, threat detector
- gyandoot-kanban: Task decomposition, swarm orchestration, diagnostics
- gyandoot-subagents: Sub-agent spawning and orchestration
- gyandoot-skills: Skills discovery, loading, preprocessing, bundles
- gyandoot-profile: Multi-agent profile manager
- gyandoot-gateway: Gateway sessions, routing, access control

Plus: CLI entry point with clap, cross-platform installer script,
KANBAN.md, .gnpl/AGENTS.md

Workspace compiles clean: cargo check passes with 0 errors.
This commit is contained in:
2026-06-11 20:04:12 +05:30
commit 851c838ca5
53 changed files with 8037 additions and 0 deletions

288
src/main.rs Normal file
View File

@@ -0,0 +1,288 @@
//! GyanDoot v2.0 — AI Agent Platform CLI Entry Point
//!
//! This binary provides the command-line interface for configuring, running,
//! and managing GyanDoot agents across multiple platforms.
use std::path::PathBuf;
use clap::{Parser, Subcommand};
use tracing_subscriber::EnvFilter;
/// GyanDoot v2.0 — AI Agent Platform
#[derive(Parser, Debug)]
#[command(name = "gyandoot", version, about, long_about = None)]
struct Cli {
/// Path to the config file (default: ~/.config/gyandoot/config.toml)
#[arg(short = 'c', long = "config", env = "GYANDOOT_CONFIG")]
config: Option<PathBuf>,
/// Profile name to use
#[arg(short = 'P', long = "profile", default_value = "default")]
profile: String,
/// Log level filter (e.g., info, debug, gyandoot=debug)
#[arg(short = 'l', long = "log", default_value = "info", env = "GYANDOOT_LOG")]
log_filter: String,
#[command(subcommand)]
command: Option<Commands>,
}
#[derive(Subcommand, Debug)]
enum Commands {
/// Run the agent interactively
Run {
/// Platform to run on (cli, telegram, discord)
#[arg(default_value = "cli")]
platform: String,
/// Initial prompt or task description
prompt: Option<String>,
},
/// Start the gateway server (handles multi-platform sessions)
Serve {
/// Host to bind the gateway server
#[arg(long, default_value = "127.0.0.1")]
host: String,
/// Port for the gateway server
#[arg(long, default_value_t = 8777)]
port: u16,
},
/// Initialize a default config file
Init,
/// List available profiles
Profiles,
/// Manage skills
#[command(name = "skills")]
Skills {
#[command(subcommand)]
action: SkillsAction,
},
/// Manage memory (MemPalace)
#[command(name = "memory")]
Memory {
#[command(subcommand)]
action: MemoryAction,
},
}
#[derive(Subcommand, Debug)]
enum SkillsAction {
/// List installed skills
List,
/// Install a skill from path or registry
Install { source: String },
/// Remove a skill
Remove { name: String },
}
#[derive(Subcommand, Debug)]
enum MemoryAction {
/// Show memory status
Status,
/// Query memory for content
Query { query: String },
/// Export memory to a file
Export { path: PathBuf },
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
// Initialize tracing subscriber
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::new(&cli.log_filter))
.with_target(true)
.init();
tracing::debug!("GyanDoot v2.0 starting (profile: {})", cli.profile);
tracing::debug!("Config path: {:?}", cli.config);
// Resolve config dir
let _config_dir = cli.config.unwrap_or_else(default_config_dir);
tracing::debug!("Using config dir: {}", _config_dir.display());
match cli.command {
Some(Commands::Run { platform, prompt }) => {
cmd_run(&cli.profile, &platform, prompt.as_deref()).await?;
}
Some(Commands::Serve { host, port }) => {
cmd_serve(&cli.profile, &host, port).await?;
}
Some(Commands::Init) => {
cmd_init().await?;
}
Some(Commands::Profiles) => {
cmd_profiles().await?;
}
Some(Commands::Skills { action }) => {
cmd_skills(action).await?;
}
Some(Commands::Memory { action }) => {
cmd_memory(action).await?;
}
None => {
// Default: run interactive CLI mode
cmd_run(&cli.profile, "cli", None).await?;
}
}
Ok(())
}
/// Returns the default config directory: ~/.config/gyandoot/
fn default_config_dir() -> PathBuf {
let home = dirs::home_dir().expect("Cannot determine home directory");
home.join(".config").join("gyandoot")
}
/// Run the agent in the given platform mode
async fn cmd_run(profile_name: &str, platform: &str, prompt: Option<&str>) -> anyhow::Result<()> {
tracing::info!("Running agent (profile={}, platform={})", profile_name, platform);
// Load config via resolver
let resolver = gyandoot_profile::ConfigResolver::default();
let _resolved = resolver.resolve();
// Initialize the agent loop using gyandoot-core config
let config = gyandoot_core::config::AgentConfig::default();
let agent = gyandoot_agent::agent_loop::AgentLoop::new(config);
if let Some(p) = prompt {
tracing::info!("Starting with prompt: {}", p);
}
agent.run().await?;
Ok(())
}
/// Start the gateway server for multi-platform sessions
async fn cmd_serve(profile_name: &str, host: &str, port: u16) -> anyhow::Result<()> {
tracing::info!(
"Starting gateway server (profile={}, bind={}:{})",
profile_name, host, port
);
let gateway = gyandoot_gateway::GatewayRunner::new();
gateway.start().await?;
tracing::info!("Gateway running on {}:{} — press Ctrl+C to stop", host, port);
// Keep running until signal
tokio::signal::ctrl_c().await?;
gateway.stop().await;
Ok(())
}
/// Initialize default config files
async fn cmd_init() -> anyhow::Result<()> {
let config_dir = default_config_dir();
tracing::info!("Initializing config in {}", config_dir.display());
std::fs::create_dir_all(&config_dir)?;
let config_path = config_dir.join("config.toml");
if config_path.exists() {
tracing::warn!("Config already exists at {}", config_path.display());
return Ok(());
}
let default_config = r#"
[agent]
name = "gyandoot"
model = "gpt-4o"
max_tokens = 4096
temperature = 0.7
system_prompt = "You are GyanDoot, an AI Agent Platform."
[providers]
default = "openai"
[providers.openai]
api_key = ""
model = "gpt-4o"
[platform]
default = "cli"
[memory]
backend = "local"
"#;
std::fs::write(&config_path, default_config.trim())?;
tracing::info!("Created default config at {}", config_path.display());
Ok(())
}
/// List available profiles
async fn cmd_profiles() -> anyhow::Result<()> {
let resolver = gyandoot_profile::ConfigResolver::default();
let profiles_dir = resolver.profiles_dir();
if profiles_dir.exists() {
let mut entries: Vec<_> = std::fs::read_dir(&profiles_dir)?
.filter_map(|e| e.ok())
.filter(|e| e.path().is_dir())
.map(|e| e.file_name().to_string_lossy().to_string())
.collect();
entries.sort();
if entries.is_empty() {
println!("No profiles found. Use 'gyandoot init' to create one.");
} else {
println!("Available profiles:");
for p in &entries {
println!(" - {}", p);
}
}
} else {
println!("No profiles found. Use 'gyandoot init' to create one.");
}
Ok(())
}
/// Handle skill management subcommands
async fn cmd_skills(action: SkillsAction) -> anyhow::Result<()> {
match action {
SkillsAction::List => {
let mut manager = gyandoot_skills::SkillsManager::new();
let skills = manager.scan();
if skills.is_empty() {
println!("No skills installed.");
} else {
println!("Installed skills:");
for s in &skills {
println!(" - {} ({:?})", s.name, s.trust);
}
}
}
SkillsAction::Install { source } => {
tracing::info!("Skill install from {} (placeholder — integrate skill hub)", source);
}
SkillsAction::Remove { name } => {
tracing::info!("Skill remove: {} (placeholder)", name);
}
}
Ok(())
}
/// Handle memory management subcommands
async fn cmd_memory(action: MemoryAction) -> anyhow::Result<()> {
let palace = gyandoot_memory::palace::MemPalace::new();
match action {
MemoryAction::Status => {
#[allow(unused_variables)]
let status_msg = format!("Memory: initialized ({})", "in-memory");
println!("{}", status_msg);
}
MemoryAction::Query { query } => {
println!("Memory query for: {}", query);
#[allow(unused_variables)]
let _results = palace.query(&query, 10);
println!(" (full memory query not yet implemented in CLI)");
}
MemoryAction::Export { path } => {
tracing::info!("Exporting memory to {}", path.display());
}
}
Ok(())
}