use crate::adapters::{edge, linux, macos, mobile, windows};
use crate::benchmark::{BenchmarkOptions, CrossPlatformBenchmark};
use crate::core::adapters::ai::factory::AIProviderFactory;
use crate::core::hardware::{detect_hardware, PlatformKind};
use crate::core::prompting::{PromptIntent, PromptRouter};
use crate::enhanced_ui;
use crate::pwa;
use crate::security::mobile as mobile_security;
use crate::security::platform::PlatformHardener;
use crate::utils::config::{Config, SecureKey};
use crate::utils::plugins::PluginManager;
use crate::utils::project_manager::ProjectManager;
use crate::utils::refactoring::{RefactorEngine, RefactorParams};
use crate::utils::templates::TemplateEngine;
use crate::utils::test_generation::TestGenerator;
use anyhow::Result;
use clap::{Parser, Subcommand};
use futures_util::stream::StreamExt;
use std::{path::PathBuf, sync::Arc};
use tokio::{fs, io::AsyncWriteExt, task};
#[derive(Parser)]
#[command(name = "kandil")]
#[command(about = "Intelligent development platform", long_about = None)]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Commands>,
#[arg(short, long, global = true, help = "Verbose output")]
pub verbose: bool,
}
#[derive(Subcommand)]
pub enum Commands {
Init,
Chat {
#[arg(value_parser)]
message: Option<String>,
},
Create {
#[arg(value_parser)]
template: String,
#[arg(value_parser)]
name: String,
},
Tui,
Projects {
#[command(subcommand)]
sub: ProjectSub,
},
Agent {
#[command(subcommand)]
sub: AgentSub,
},
Refactor {
#[command(subcommand)]
sub: RefactorSub,
},
Test {
#[command(subcommand)]
sub: TestSub,
},
SwitchModel { provider: String, model: String },
Plugin {
#[command(subcommand)]
sub: PluginSub,
},
Config {
#[command(subcommand)]
sub: ConfigSub,
},
LocalModel {
#[command(subcommand)]
sub: LocalModelSub,
},
Auth {
#[command(subcommand)]
sub: AuthSub,
},
Doctor {
#[arg(long)]
verbose: bool,
#[arg(long, default_value = "json")]
format: String,
},
Windows {
#[command(subcommand)]
sub: WindowsSub,
},
Macos {
#[command(subcommand)]
sub: MacosSub,
},
Linux {
#[command(subcommand)]
sub: LinuxSub,
},
Mobile {
#[command(subcommand)]
sub: MobileSub,
},
Pwa {
#[arg(long, default_value = "dist/pwa")]
output: PathBuf,
},
Web {
#[arg(short, long, default_value = "127.0.0.1:7878")]
address: String,
},
}
#[derive(Subcommand)]
pub enum AgentSub {
Requirements {
description: String,
},
Design {
requirements: String,
},
Code {
design_path: String,
language: String,
},
Test {
#[command(subcommand)]
sub: TestSubCommand,
},
Documentation {
#[command(subcommand)]
sub: DocumentationSubCommand,
},
Release {
#[command(subcommand)]
sub: ReleaseSubCommand,
},
Qa {
#[command(subcommand)]
sub: QaSubCommand,
},
Maintenance {
#[command(subcommand)]
sub: MaintenanceSubCommand,
},
Simulate {
#[command(subcommand)]
sub: SimulateSubCommand,
},
Advanced {
#[command(subcommand)]
sub: AdvancedSubCommand,
},
TechRole {
#[command(subcommand)]
sub: TechRoleSubCommand,
},
AdvancedFeatures {
#[command(subcommand)]
sub: AdvancedFeaturesSubCommand,
},
}
#[derive(Subcommand)]
pub enum MaintenanceSubCommand {
HealthCheck {
system_name: String,
},
}
#[derive(Subcommand)]
pub enum QaSubCommand {
FullSuite {
project_path: String,
},
}
#[derive(Subcommand)]
pub enum ReleaseSubCommand {
FullProcess {
version: String,
},
}
#[derive(Subcommand)]
pub enum DocumentationSubCommand {
Generate {
path: String,
},
}
#[derive(Subcommand)]
pub enum AdvancedFeaturesSubCommand {
DevOps {
#[command(subcommand)]
sub: DevOpsSubCommand,
},
Scrum {
#[command(subcommand)]
sub: ScrumSubCommand,
},
I18n {
#[command(subcommand)]
sub: I18nSubCommand,
},
A11y {
#[command(subcommand)]
sub: A11ySubCommand,
},
Collab {
#[command(subcommand)]
sub: CollabSubCommand,
},
Ide {
#[command(subcommand)]
sub: IdeSubCommand,
},
}
#[derive(Subcommand)]
pub enum DevOpsSubCommand {
Terraform {
spec: String,
},
Drill {
scenario: String,
},
Pipeline {
project_type: String,
},
}
#[derive(Subcommand)]
pub enum ScrumSubCommand {
Plan {
goal: String,
duration: u32,
team_size: u32,
},
Retro {
sprint: u32,
},
Ceremony {
ceremony_type: String,
participants: String,
},
}
#[derive(Subcommand)]
pub enum I18nSubCommand {
Translate {
text: String,
target: String,
source: String,
},
Audit {
path: String,
},
Review {
original: String,
translation: String,
target: String,
},
}
#[derive(Subcommand)]
pub enum A11ySubCommand {
Audit {
content: String,
},
Guidelines {
component: String,
},
Fix {
html: String,
},
}
#[derive(Subcommand)]
pub enum CollabSubCommand {
Session {
name: String,
creator_id: String,
creator_name: String,
},
AddParticipant {
session_id: String,
user_id: String,
name: String,
role: String,
},
AddDoc {
session_id: String,
doc_id: String,
name: String,
content: String,
language: String,
},
}
#[derive(Subcommand)]
pub enum IdeSubCommand {
Suggestions {
file: String,
language: String,
code: String,
},
Docs {
code: String,
language: String,
},
Refactor {
code: String,
language: String,
},
Review {
code: String,
language: String,
},
}
#[derive(Subcommand)]
pub enum TechRoleSubCommand {
Architect {
#[command(subcommand)]
sub: ArchitectSubCommand,
},
Developer {
#[command(subcommand)]
sub: DeveloperSubCommand,
},
Collaborate {
#[command(subcommand)]
sub: CollaborateSubCommand,
},
}
#[derive(Subcommand)]
pub enum ArchitectSubCommand {
Review {
diagram: String,
},
Decide {
context: String,
decision: String,
},
Adr {
decision_id: String,
},
}
#[derive(Subcommand)]
pub enum DeveloperSubCommand {
Implement {
spec: String,
file: String,
},
Pair {
partner: String,
task: String,
file: String,
},
Bugs {
code: String,
file: String,
},
}
#[derive(Subcommand)]
pub enum CollaborateSubCommand {
Session {
title: String,
roles: String,
agenda: Vec<String>,
},
Decision {
title: String,
description: String,
roles: String,
},
}
#[derive(Subcommand)]
pub enum AdvancedSubCommand {
Review {
file: String,
},
Security {
file: String,
description: String,
},
Deploy {
#[command(subcommand)]
sub: DeploySubCommand,
},
SelfImprove {
path: String,
},
}
#[derive(Subcommand)]
pub enum DeploySubCommand {
Plan {
environment: String,
app: String,
},
Execute {
plan: String,
},
}
#[derive(Subcommand)]
pub enum TestSubCommand {
Generate {
source: String,
language: String,
},
Execute {
test: String,
framework: String,
},
Coverage {
source: String,
test: String,
},
}
#[derive(Subcommand)]
pub enum SimulateSubCommand {
Pm {
#[command(subcommand)]
sub: PmSubCommand,
},
Ba {
#[command(subcommand)]
sub: BaSubCommand,
},
}
#[derive(Subcommand)]
pub enum PmSubCommand {
PlanSprint {
project: String,
duration: u32,
},
Retrospective {
sprint: u32,
},
}
#[derive(Subcommand)]
pub enum BaSubCommand {
Validate {
requirements: String,
},
UserStory {
feature: String,
},
}
#[derive(Subcommand)]
pub enum ProjectSub {
List,
Switch {
id: String,
},
Sync {
id: Option<String>,
},
Info {
id: Option<String>,
},
}
#[derive(Subcommand)]
pub enum RefactorSub {
Preview {
file: String,
refactor_type: String,
#[arg(short, long)]
params: Vec<String>,
},
Apply,
Cancel,
}
#[derive(Subcommand)]
pub enum TestSub {
Generate {
file: String,
#[arg(short, long, default_value = "")]
framework: String,
},
Integration {
feature: String,
},
Coverage {
source: String,
test: String,
},
}
#[derive(Subcommand)]
pub enum PluginSub {
Install { source: String },
List,
Run { name: String, args: Vec<String> },
}
#[derive(Subcommand)]
pub enum ConfigSub {
SetKey { provider: String, key: String },
ListKeys,
Costs {
provider: Option<String>,
},
Validate,
}
#[derive(Subcommand)]
pub enum LocalModelSub {
List {
#[arg(long)]
compatible: bool,
},
Install {
#[arg(value_parser)]
model: String,
#[arg(long)]
force: bool,
},
Remove {
#[arg(value_parser)]
model: String,
},
Verify {
#[arg(value_parser)]
model: String,
},
Benchmark {
#[arg(value_parser)]
model: Option<String>,
#[arg(long, default_value = "table")]
format: String,
#[arg(long)]
runtime: Option<String>,
#[arg(long)]
all_runtimes: bool,
},
Use {
#[arg(value_parser)]
model: String,
},
Status,
}
struct BenchmarkCliOptions {
model: Option<String>,
format: String,
runtime: Option<String>,
all_runtimes: bool,
}
#[derive(Subcommand)]
pub enum AuthSub {
Login { provider: String },
}
#[derive(Subcommand)]
pub enum WindowsSub {
Status,
CheckGpu,
Doctor,
SetupWsl2,
}
#[derive(Subcommand)]
pub enum MacosSub {
Status,
Doctor,
SetupCoreml,
}
#[derive(Subcommand)]
pub enum LinuxSub {
Status,
Doctor,
Setup,
}
#[derive(Subcommand)]
pub enum MobileSub {
IosSync,
AndroidSync,
EdgeSnapshot,
}
pub async fn run(cli: Cli) -> Result<()> {
match cli.command {
Some(Commands::Init) => init_project().await?,
Some(Commands::Chat { message }) => chat(message.unwrap_or_default()).await?,
Some(Commands::Create { template, name }) => create_project(&template, &name).await?,
Some(Commands::Tui) => launch_tui().await?,
Some(Commands::Projects { sub }) => handle_projects(sub).await?,
Some(Commands::Agent { sub }) => handle_agent(sub).await?,
Some(Commands::Refactor { sub }) => handle_refactor(sub).await?,
Some(Commands::Test { sub }) => handle_test(sub).await?,
Some(Commands::SwitchModel { provider, model }) => switch_model(provider, model).await?,
Some(Commands::Plugin { sub }) => handle_plugin(sub).await?,
Some(Commands::Config { sub }) => handle_config(sub).await?,
Some(Commands::LocalModel { sub }) => handle_local_model(sub).await?,
Some(Commands::Auth { sub }) => handle_auth(sub).await?,
Some(Commands::Windows { sub }) => handle_windows(sub).await?,
Some(Commands::Macos { sub }) => handle_macos(sub).await?,
Some(Commands::Linux { sub }) => handle_linux(sub).await?,
Some(Commands::Mobile { sub }) => handle_mobile(sub).await?,
Some(Commands::Pwa { output }) => handle_pwa(output).await?,
Some(Commands::Web { address }) => {
eprintln!("Web module is temporarily unavailable in this build");
return Ok(());
},
Some(Commands::Doctor { verbose, format }) => handle_doctor(verbose, &format).await?,
None => {
println!("Kandil Code - Intelligent Development Platform");
println!("Use --help for commands");
}
}
Ok(())
}
async fn init_project() -> Result<()> {
println!("Initializing new Kandil project...");
let project_manager = ProjectManager::new()?;
let current_dir = std::env::current_dir()?.to_string_lossy().to_string();
let project_name = std::path::Path::new(¤t_dir)
.file_name()
.and_then(|name| name.to_str())
.unwrap_or("unnamed_project");
let project =
project_manager.create_project(project_name, ¤t_dir, "ollama", "llama3:70b")?;
println!("Created project: {} with ID: {}", project.name, project.id);
Ok(())
}
async fn chat(message: String) -> Result<()> {
if message.trim().is_empty() {
return enhanced_ui::repl::run_repl().await;
}
let config = Config::load()?;
let factory = AIProviderFactory::new(config.clone());
let router = PromptRouter::new();
let routed = router.route_message(
&message,
&config.ai_provider,
&config.ai_model,
);
let ai = Arc::new(factory.create_ai(&routed.provider, &routed.model)?);
let tracked_ai = crate::core::adapters::TrackedAI::new(ai.clone(), factory.get_cost_tracker());
if routed.provider != config.ai_provider || routed.model != config.ai_model {
println!("🎯 Routed to {} ({}) for {:?} intent",
routed.provider, routed.model, routed.intent);
println!(" {}", routed.explanation);
}
let response = tracked_ai.chat(&message).await?;
println!("{}", response);
if let Ok(project_manager) = ProjectManager::new() {
if let Ok(current_project) = project_manager.ensure_active_project(None) {
let session_id = uuid::Uuid::new_v4().to_string();
let _ = project_manager.save_project_memory(
¤t_project.id,
&session_id,
"user",
&message,
None, );
let _ = project_manager.save_project_memory(
¤t_project.id,
&session_id,
"ai",
&response,
None, );
}
}
Ok(())
}
async fn create_project(template: &str, name: &str) -> Result<()> {
let engine = TemplateEngine::new();
engine.create_project(template, name, name)?;
let project_manager = ProjectManager::new()?;
let project = project_manager.create_project(
name,
&std::env::current_dir()?.join(name).to_string_lossy(),
"ollama",
"llama3:70b",
)?;
println!("Created project '{}' using template '{}'", name, template);
println!("Project ID: {}", project.id);
Ok(())
}
async fn handle_agent(sub: AgentSub) -> Result<()> {
let config = Config::load()?;
let factory = AIProviderFactory::new(config.clone());
let router = PromptRouter::new();
let (intent, task_description) = match &sub {
AgentSub::Requirements { description } => (PromptIntent::Planning, description.clone()),
AgentSub::Design { requirements } => (PromptIntent::Architecture, requirements.clone()),
AgentSub::Code { design_path, .. } => (PromptIntent::Coding, format!("Generate code from {}", design_path)),
AgentSub::Test { .. } => (PromptIntent::Testing, "Generate tests".to_string()),
AgentSub::Documentation { .. } => (PromptIntent::Analysis, "Generate documentation".to_string()),
_ => (PromptIntent::Conversation, "Agent task".to_string()),
};
let routed = router.route_for_intent(intent, &config.ai_provider, &config.ai_model);
let ai = Arc::new(factory.create_ai(&routed.provider, &routed.model)?);
if routed.provider != config.ai_provider || routed.model != config.ai_model {
println!("🎯 Agent using {} ({}) for {:?} intent",
routed.provider, routed.model, routed.intent);
}
match sub {
AgentSub::Requirements { description } => {
let requirements_agent = crate::core::agents::RequirementsAgent::new(ai);
let _doc = requirements_agent
.generate_requirements_document(&description)
.await?;
println!("Generated requirements document for: {}", description);
println!("Requirements document structure created (content generation would happen in full implementation)");
}
AgentSub::Design { requirements } => {
let design_agent = crate::core::agents::DesignAgent::new(ai);
let _doc = design_agent.generate_design_document(&requirements).await?;
println!(
"Generated design document based on requirements: {}",
requirements
);
println!("Design document structure created (content generation would happen in full implementation)");
}
AgentSub::Code {
design_path,
language,
} => {
let design_content = std::fs::read_to_string(&design_path)
.unwrap_or_else(|_| "Design document content would be read from file".to_string());
let code_agent = crate::core::agents::CodeAgent::new(ai)?;
let output = code_agent.generate_code(&design_content, &language).await?;
println!(
"Generated {} code with {} files",
language,
output.files.len()
);
println!("Code generation completed (files would be saved in full implementation)");
}
AgentSub::Test { sub: test_cmd } => {
let test_agent = crate::core::agents::TestAgent::new(ai);
match test_cmd {
TestSubCommand::Generate { source, language } => {
let tests = test_agent.generate_tests(&source, &language).await?;
println!("Generated tests for: {}", source);
println!("{}", tests);
}
TestSubCommand::Execute { test, framework } => {
let results = test_agent.execute_tests(&test, &framework).await?;
println!("Test execution results:");
println!(
" Passed: {}, Failed: {}, Skipped: {}",
results.passed, results.failed, results.skipped
);
println!(" Duration: {}ms", results.duration_ms);
}
TestSubCommand::Coverage { source, test } => {
let analysis = test_agent.analyze_test_coverage(&source, &test).await?;
println!("Test coverage analysis for {} and {}:", source, test);
println!("{}", analysis);
}
}
}
AgentSub::Documentation { sub: doc_cmd } => {
let doc_agent = crate::core::agents::documentation::DocumentationGenerator::new(ai);
match doc_cmd {
DocumentationSubCommand::Generate { path } => {
let report = doc_agent.generate_documentation_for_project(&path).await?;
println!("Generated documentation for project at {}:", path);
println!("{}", report);
}
}
}
AgentSub::Release { sub: release_cmd } => {
let mut release_manager =
crate::core::agents::release_manager::ReleaseManager::new(ai, "0.1.0".to_string()); match release_cmd {
ReleaseSubCommand::FullProcess { version } => {
release_manager.version = version; release_manager.run_full_release_process().await?;
println!(
"Full release process completed for version: {}",
release_manager.version
);
}
}
}
AgentSub::Qa { sub: qa_cmd } => {
let mut qa_system =
crate::core::agents::quality_assurance::QualityAssuranceSystem::new(ai);
match qa_cmd {
QaSubCommand::FullSuite { project_path } => {
let _report = qa_system.run_full_qa_suite(&project_path).await?;
println!("Full QA suite completed for project at {}:", project_path);
println!("{}", qa_system.generate_qa_report_md());
}
}
}
AgentSub::Maintenance {
sub: maintenance_cmd,
} => {
let mut maintenance_manager =
crate::core::agents::maintenance::MaintenanceManager::new(ai);
match maintenance_cmd {
MaintenanceSubCommand::HealthCheck { system_name } => {
maintenance_manager.run_health_checks(&system_name).await?;
println!("Health check completed for system: {}", system_name);
}
}
}
AgentSub::Simulate { sub: sim_cmd } => match sim_cmd {
SimulateSubCommand::Pm { sub: pm_cmd } => {
let pm_sim = crate::core::agents::ProjectManagerSimulation::new(ai);
match pm_cmd {
PmSubCommand::PlanSprint { project, duration } => {
let plan = pm_sim.plan_sprint(&project, duration).await?;
println!("Sprint plan for project '{}':", project);
println!(
" Sprint: {}, Duration: {} weeks",
plan.sprint_number, duration
);
println!(" Goals: {} items", plan.goals.len());
println!(" Timeline: {} to {}", plan.start_date, plan.end_date);
}
PmSubCommand::Retrospective { sprint } => {
let results = pm_sim.run_retrospective(sprint).await?;
println!("Retrospective results for Sprint {}:", sprint);
println!("{}", results);
}
}
}
SimulateSubCommand::Ba { sub: ba_cmd } => {
let ba_sim = crate::core::agents::BusinessAnalystSimulation::new(ai);
match ba_cmd {
BaSubCommand::Validate { requirements } => {
let validation = ba_sim.validate_requirements(&requirements).await?;
println!("Requirements validation for: {}", requirements);
println!("{}", validation);
}
BaSubCommand::UserStory { feature } => {
let story = ba_sim.create_user_story(&feature).await?;
println!("Created user story for feature: {}", feature);
println!(" ID: {}, Title: {}", story.id, story.title);
println!(" Priority: {:?}", story.priority);
println!(" Story Points: {}", story.story_points);
}
}
}
},
AgentSub::Advanced { sub: advanced_cmd } => {
match advanced_cmd {
AdvancedSubCommand::Review { file } => {
let review_agent = crate::core::agents::ReviewAgent::new(ai);
let report = review_agent.code_review(&file).await?;
println!("Code review for: {}", file);
println!(" Score: {}/100", report.score);
println!(" Issues found: {}", report.issues.len());
println!(" Summary: {}", report.summary);
}
AdvancedSubCommand::Security { file, description } => {
let security_agent = crate::core::agents::EthicsSecurityAgent::new(ai);
let report = security_agent
.security_scan(&std::fs::read_to_string(&file)?, &file)
.await?;
println!("Security scan for: {}", file);
println!(" Risk Score: {}/100", report.risk_score);
println!(" Vulnerabilities: {}", report.vulnerabilities.len());
let ethics_report = security_agent
.ethics_check(&std::fs::read_to_string(&file)?, &description)
.await?;
println!(
"Ethics check completed with score: {}/100",
ethics_report.ethics_score
);
}
AdvancedSubCommand::Deploy { sub: deploy_cmd } => {
let deploy_agent = crate::core::agents::DeploymentAgent::new(ai)?;
match deploy_cmd {
DeploySubCommand::Plan { environment, app } => {
let plan = deploy_agent
.create_deployment_plan(&environment, &app)
.await?;
println!("Deployment plan for {} to {}:", app, environment);
println!(" Steps: {}", plan.steps.len());
println!(" Estimated duration: {}", plan.estimated_duration);
println!(
" Rollback plan: {}",
if plan.rollback_plan.steps.is_empty() {
"No"
} else {
"Yes"
}
);
}
DeploySubCommand::Execute { plan } => {
println!("Executing deployment plan from: {}", plan);
println!("Deployment execution would happen in full implementation");
}
}
}
AdvancedSubCommand::SelfImprove { path } => {
let meta_agent = crate::core::agents::MetaAgent::new(ai);
let analysis = meta_agent.analyze_system(&path).await?;
println!("System analysis for: {}", path);
println!(
" Performance issues: {}",
analysis.performance_bottlenecks.len()
);
println!(
" Code quality issues: {}",
analysis.code_quality_issues.len()
);
println!(" Security concerns: {}", analysis.security_concerns.len());
let improvement_plans = meta_agent.generate_improvement_plan(&analysis).await?;
println!(" Suggested improvements: {}", improvement_plans.len());
let evolution_result = meta_agent.evolve_agent_capabilities().await?;
println!(" Self-improvement analysis: {}", evolution_result);
}
}
}
AgentSub::TechRole { sub: tech_role_cmd } => {
match tech_role_cmd {
TechRoleSubCommand::Architect { sub: arch_cmd } => {
let mut arch_agent = crate::core::agents::ArchitectSimulation::new(ai)?;
match arch_cmd {
ArchitectSubCommand::Review { diagram } => {
let review = arch_agent.review_design(&diagram).await?;
println!("Architecture review completed:");
println!(" Score: {}/100", review.score);
println!(" Recommendations: {}", review.recommendations.len());
println!(" Issues found: {}", review.identified_issues.len());
}
ArchitectSubCommand::Decide { context, decision } => {
let arch_decision = arch_agent
.make_architecture_decision(&context, &decision)
.await?;
println!("Architecture decision made:");
println!(" ID: {}, Title: {}", arch_decision.id, arch_decision.title);
println!(" Status: {:?}", arch_decision.status);
}
ArchitectSubCommand::Adr { decision_id } => {
let adr = arch_agent.generate_adr(&decision_id).await?;
println!("Architecture Decision Record for {}: ", decision_id);
println!("{}", adr);
}
}
}
TechRoleSubCommand::Developer { sub: dev_cmd } => {
let mut dev_agent = crate::core::agents::DeveloperSimulation::new(
ai,
"Current Project".to_string(),
);
match dev_cmd {
DeveloperSubCommand::Implement { spec, file } => {
let implementation = dev_agent.implement_feature(&spec, &file).await?;
println!("Feature implementation completed for: {}", file);
println!("{}", implementation);
}
DeveloperSubCommand::Pair {
partner,
task,
file,
} => {
let session_id = dev_agent
.start_pair_programming(&partner, &task, &file)
.await?;
println!("Started pair programming session: {}", session_id);
}
DeveloperSubCommand::Bugs { code, file } => {
let bugs = dev_agent.find_bugs(&code, &file).await?;
println!("Bugs found in {}: {}", file, bugs.len());
for bug in bugs {
println!(" - {} ({}): {}", bug.id, bug.severity, bug.description);
}
}
}
}
TechRoleSubCommand::Collaborate { sub: collab_cmd } => {
let mut collab_manager = crate::core::agents::CollaborationManager::new();
match collab_cmd {
CollaborateSubCommand::Session {
title,
roles,
agenda,
} => {
let role_list: Vec<crate::core::agents::collaboration::Role> = roles
.split(',')
.map(|r| match r.trim() {
"architect" => {
crate::core::agents::collaboration::Role::Architect
}
"developer" => {
crate::core::agents::collaboration::Role::Developer
}
"qa" => crate::core::agents::collaboration::Role::QA,
_ => crate::core::agents::collaboration::Role::Developer, })
.collect();
let session_id = collab_manager
.start_collaboration_session(&title, role_list, agenda)
.await;
println!("Collaboration session started: {}", session_id);
}
CollaborateSubCommand::Decision {
title,
description,
roles,
} => {
let role_list: Vec<crate::core::agents::collaboration::Role> = roles
.split(',')
.map(|r| match r.trim() {
"architect" => {
crate::core::agents::collaboration::Role::Architect
}
"developer" => {
crate::core::agents::collaboration::Role::Developer
}
"qa" => crate::core::agents::collaboration::Role::QA,
_ => crate::core::agents::collaboration::Role::Developer, })
.collect();
println!("Creating cross-role decision: {}", title);
println!("Roles involved: {:?}", role_list);
println!("Description: {}", description);
}
}
}
}
}
AgentSub::AdvancedFeatures {
sub: advanced_features_cmd,
} => {
match advanced_features_cmd {
AdvancedFeaturesSubCommand::DevOps { sub: devops_cmd } => {
let devops_agent = crate::core::agents::DevOpsSimulation::new(ai);
match devops_cmd {
DevOpsSubCommand::Terraform { spec } => {
let tf_path = devops_agent.generate_terraform(&spec).await?;
println!("Generated Terraform configuration: {:?}", tf_path);
}
DevOpsSubCommand::Drill { scenario } => {
let report = devops_agent.run_drill(&scenario).await?;
println!("Incident response drill completed:");
println!(" Scenario: {}", report.scenario);
println!(" Duration: {} seconds", report.duration_seconds);
println!(" Effectiveness: {}/100", report.effectiveness_score);
}
DevOpsSubCommand::Pipeline { project_type } => {
let pipeline =
devops_agent.generate_ci_cd_pipeline(&project_type).await?;
println!("Generated CI/CD pipeline for {} projects", project_type);
println!("{}", pipeline);
}
}
}
AdvancedFeaturesSubCommand::Scrum { sub: scrum_cmd } => {
let mut scrum_agent = crate::core::agents::ScrumSimulation::new(ai);
match scrum_cmd {
ScrumSubCommand::Plan {
goal,
duration,
team_size,
} => {
let sprint = scrum_agent.plan_sprint(goal, duration, team_size).await?;
println!("Sprint {} planned:", sprint.number);
println!(" Goal: {}", sprint.goal);
println!(" Duration: {} days", sprint.duration_days);
println!(" Team size: {}", sprint.team_size);
}
ScrumSubCommand::Retro { sprint } => {
let retro = scrum_agent.run_retrospective(sprint).await?;
println!("Sprint {} retrospective:", retro.sprint_number);
println!(" Satisfaction: {}/10", retro.satisfaction_score);
println!(" Good things: {}", retro.good_things.len());
println!(" Improvement areas: {}", retro.improvement_areas.len());
}
ScrumSubCommand::Ceremony {
ceremony_type,
participants,
} => {
let participants_list = participants
.split(',')
.map(|s| s.trim().to_string())
.collect();
let ceremony = scrum_agent
.conduct_ceremony(
&ceremony_type,
participants_list,
scrum_agent.get_current_sprint(),
)
.await?;
println!(
"Conducted {} ceremony with {} participants",
ceremony.name,
ceremony.participants.len()
);
}
}
}
AdvancedFeaturesSubCommand::I18n { sub: i18n_cmd } => {
let mut i18n_agent = crate::core::agents::I18nAssistant::new(ai);
match i18n_cmd {
I18nSubCommand::Translate {
text,
target,
source,
} => {
let translation =
i18n_agent.translate_text(&text, &target, &source).await?;
println!("Translation from {} to {}:", source, target);
println!("{}", translation);
}
I18nSubCommand::Audit { path } => {
let report = i18n_agent.audit_translations(&path).await?;
println!("Translation audit completed:");
println!(" Languages: {}", report.completeness_by_language.len());
println!(" Recommendations: {}", report.recommendations.len());
}
I18nSubCommand::Review {
original,
translation,
target,
} => {
let report = i18n_agent
.review_translation(&original, &translation, &target)
.await?;
println!("Translation review completed:");
println!(" Quality score: {}/100", report.quality_score);
println!(" Issues found: {}", report.issues_found.len());
}
}
}
AdvancedFeaturesSubCommand::A11y { sub: a11y_cmd } => {
let a11y_agent = crate::core::agents::A11yAssistant::new(ai);
match a11y_cmd {
A11ySubCommand::Audit { content } => {
use crate::core::agents::a11y::WcagLevel;
let report = a11y_agent.wcag_audit(&content, WcagLevel::AA).await?;
println!("Accessibility audit completed:");
println!(" Score: {}/100", report.accessibility_score);
println!(" Issues found: {}", report.issues_found.len());
}
A11ySubCommand::Guidelines { component } => {
let guidelines =
a11y_agent.generate_a11y_guidelines(&component).await?;
println!("Accessibility guidelines for {}:", component);
println!("{}", guidelines);
}
A11ySubCommand::Fix { html } => {
let fixed_html = a11y_agent.remediate_issues(&html).await?;
println!("Accessibility issues remediated in HTML:");
println!("{}", fixed_html);
}
}
}
AdvancedFeaturesSubCommand::Collab { sub: collab_cmd } => {
let mut collab = crate::core::agents::RealTimeCollaboration::new();
match collab_cmd {
CollabSubCommand::Session {
name,
creator_id,
creator_name,
} => {
let session_id =
collab.create_session(&name, &creator_id, &creator_name)?;
println!("Created collaboration session: {}", session_id);
}
CollabSubCommand::AddParticipant {
session_id,
user_id,
name,
role,
} => {
use crate::core::agents::collaboration_realtime::Role;
let role_enum = match role.as_str() {
"owner" => Role::Owner,
"admin" => Role::Admin,
"editor" => Role::Editor,
"viewer" => Role::Viewer,
_ => Role::Editor,
};
collab.add_participant(&session_id, &user_id, &name, role_enum)?;
println!("Added participant {} to session {}", name, session_id);
}
CollabSubCommand::AddDoc {
session_id,
doc_id,
name,
content,
language,
} => {
collab.add_document(
&session_id,
&doc_id,
&name,
&content,
&language,
)?;
println!("Added document {} to session {}", name, session_id);
}
}
}
AdvancedFeaturesSubCommand::Ide { sub: ide_cmd } => {
let ide_ext = crate::core::agents::IdeExtension::new(ai);
match ide_cmd {
IdeSubCommand::Suggestions {
file,
language,
code,
} => {
let ctx = crate::core::agents::ide_extension::ExtensionContext {
file_path: file,
language,
selected_code: code,
cursor_position: (1, 1),
workspace_root: ".".to_string(),
};
let suggestions = ide_ext.get_code_suggestions(&ctx).await?;
println!("Code suggestions ({} found):", suggestions.len());
for suggestion in suggestions {
println!(" - {}: {}", suggestion.title, suggestion.description);
}
}
IdeSubCommand::Docs { code, language } => {
let docs = ide_ext.generate_documentation(&code, &language).await?;
println!("Generated documentation:");
println!("{}", docs);
}
IdeSubCommand::Refactor { code, language } => {
let options = ide_ext.get_refactoring_options(&code, &language).await?;
println!("Refactoring options:");
for option in options {
println!("{}", option);
}
}
IdeSubCommand::Review { code, language } => {
let comments = ide_ext.run_inline_code_review(&code, &language).await?;
println!("Inline code review comments ({} found):", comments.len());
for comment in comments {
println!(
" Line {}: [{}] {}",
comment.line_number, comment.severity, comment.message
);
}
}
}
}
}
}
}
Ok(())
}
async fn handle_projects(sub: ProjectSub) -> Result<()> {
let project_manager = ProjectManager::new()?;
match sub {
ProjectSub::List => {
let projects = project_manager.list_projects()?;
if projects.is_empty() {
println!("No projects found");
} else {
println!("Projects:");
for project in projects {
let last_opened = project
.last_opened
.map(|d| d.format("%Y-%m-%d %H:%M:%S").to_string())
.unwrap_or_else(|| "Never".to_string());
println!(
" ID: {} | Name: {} | Path: {} | Last Opened: {}",
project.id, project.name, project.root_path, last_opened
);
}
}
}
ProjectSub::Switch { id } => {
let project = project_manager.switch_project(&id)?;
println!(
"Switched to project: {} at {}",
project.name, project.root_path
);
}
ProjectSub::Sync { id } => {
match id {
Some(project_id) => println!("Syncing project: {}", project_id),
None => println!("Syncing current project"),
}
println!("Note: Cloud sync functionality would be implemented with Supabase in a full implementation");
}
ProjectSub::Info { id } => {
let project = if let Some(project_id) = id {
project_manager.get_project(&project_id)?
} else {
let projects = project_manager.list_projects()?;
projects.first().cloned()
};
match project {
Some(p) => {
println!("Project Details:");
println!(" ID: {}", p.id);
println!(" Name: {}", p.name);
println!(" Path: {}", p.root_path);
println!(" AI Provider: {}", p.ai_provider);
println!(" AI Model: {}", p.ai_model);
println!(" Memory Enabled: {}", p.memory_enabled);
println!(" Created: {}", p.created_at.format("%Y-%m-%d %H:%M:%S"));
println!(
" Last Opened: {}",
p.last_opened
.map(|d| d.format("%Y-%m-%d %H:%M:%S").to_string())
.unwrap_or_else(|| "Never".to_string())
);
}
None => println!("Project not found"),
}
}
}
Ok(())
}
#[cfg(feature = "tui")]
async fn launch_tui() -> Result<()> {
let project_manager = ProjectManager::new()?;
let _current_project = project_manager.ensure_active_project(None)?;
let mut app = crate::tui::StudioApp::new()?;
app.run().await?;
Ok(())
}
#[cfg(not(feature = "tui"))]
async fn launch_tui() -> Result<()> {
Err(anyhow::anyhow!("TUI feature is not enabled in this build"))
}
async fn handle_refactor(sub: RefactorSub) -> Result<()> {
let mut engine = RefactorEngine::new();
match sub {
RefactorSub::Preview {
file,
refactor_type,
params,
} => {
let mut refactor_params = RefactorParams {
old_name: None,
new_name: None,
start_line: None,
end_line: None,
function_name: None,
visibility: None,
};
for param in params {
if let Some((key, value)) = param.split_once('=') {
match key {
"old_name" => refactor_params.old_name = Some(value.to_string()),
"new_name" => refactor_params.new_name = Some(value.to_string()),
_ => {}
}
}
}
let result = engine.preview_refactor(&file, &refactor_type, &refactor_params)?;
println!("Refactoring preview for '{}':", file);
println!("{}", result);
}
RefactorSub::Apply => {
engine.apply_pending_operations()?;
println!("Applied all pending refactor operations");
}
RefactorSub::Cancel => {
engine.cancel_pending_operations();
println!("Cancelled all pending refactor operations");
}
}
Ok(())
}
async fn handle_test(sub: TestSub) -> Result<()> {
let config = Config::load()?;
let factory = AIProviderFactory::new(config.clone());
let ai = Arc::new(factory.create_ai(&config.ai_provider, &config.ai_model)?);
let tracked_ai = crate::core::adapters::TrackedAI::new(ai.clone(), factory.get_cost_tracker());
let generator = TestGenerator::new(ai.clone());
match sub {
TestSub::Generate { file, framework } => {
let tests = generator.generate_tests_for_file(&file, &framework).await?;
println!("Generated tests for '{}':", file);
println!("{}", tests);
}
TestSub::Integration { feature } => {
let tests = generator.generate_integration_tests(&feature).await?;
println!("Generated integration tests for feature:");
println!("{}", tests);
}
TestSub::Coverage { source, test } => {
let analysis = generator.analyze_test_coverage(&source, &test).await?;
println!("Test coverage analysis for '{}' and '{}':", source, test);
println!("{}", analysis);
}
}
Ok(())
}
async fn switch_model(provider: String, model: String) -> Result<()> {
match provider.as_str() {
"ollama" | "claude" | "qwen" | "openai" => {
println!("Switched to provider: {}, model: {}", provider, model);
}
_ => return Err(anyhow::anyhow!("Invalid provider: {}", provider)),
}
Ok(())
}
async fn handle_plugin(sub: PluginSub) -> Result<()> {
let manager = PluginManager::new();
match sub {
PluginSub::Install { source } => {
manager.install_plugin(&source)?;
println!("Plugin installed from: {}", source);
}
PluginSub::List => {
let plugins = manager.list_plugins()?;
if plugins.is_empty() {
println!("No plugins installed");
} else {
println!("Installed plugins:");
for plugin in plugins {
println!(" - {}", plugin);
}
}
}
PluginSub::Run { name, args } => {
println!("Running plugin: {} with args: {:?}", name, args);
}
}
Ok(())
}
async fn handle_config(sub: ConfigSub) -> Result<()> {
match sub {
ConfigSub::SetKey { provider, key } => {
SecureKey::save(&provider, &key)?;
println!("API key saved securely for provider: {}", provider);
}
ConfigSub::ListKeys => {
println!("Currently implemented as a placeholder - key listing will be implemented in future versions");
}
ConfigSub::Costs { provider } => {
match provider {
Some(provider_str) => {
println!(
"Cost tracking for provider: {} is not available in this context",
provider_str
);
println!("Cost tracking is available when using AI features");
}
None => {
println!("Cost tracking summary is not available in this context");
println!("Cost tracking is available when using AI features");
}
}
}
ConfigSub::Validate => {
let cfg = Config::load()?;
match cfg.validate_production().await {
Ok(()) => println!("Configuration validation: ok"),
Err(e) => {
eprintln!("Configuration validation failed: {}", e);
return Err(e);
}
}
}
}
Ok(())
}
async fn handle_local_model(sub: LocalModelSub) -> Result<()> {
match sub {
LocalModelSub::List { compatible } => {
let hardware = detect_hardware();
let catalog = &crate::models::catalog::MODEL_CATALOG;
println!("Available Models:");
for model in catalog.iter() {
if compatible && model.ram_required_gb > hardware.total_ram_gb {
continue;
}
println!(" {}", model.name);
println!(
" Size: {}GB, RAM: {}GB, GPU: {:?}GB",
model.size_gb, model.ram_required_gb, model.gpu_vram_min
);
let speed_str = match &model.speed_rating {
crate::models::catalog::Speed::UltraFast(tps) => {
format!("Ultra Fast ({} t/s)", tps)
}
crate::models::catalog::Speed::VeryFast(tps) => {
format!("Very Fast ({} t/s)", tps)
}
crate::models::catalog::Speed::Fast(tps) => format!("Fast ({} t/s)", tps),
crate::models::catalog::Speed::Medium(tps) => format!("Medium ({} t/s)", tps),
crate::models::catalog::Speed::Slow(tps) => format!("Slow ({} t/s)", tps),
};
let quality_str = format!("{:?}", model.quality_rating);
println!(" Speed: {}, Quality: {}", speed_str, quality_str);
println!(" {}", model.description);
println!(" Context sizes: {:?}", model.context_sizes);
}
}
LocalModelSub::Install { model, force } => {
let model_spec = crate::models::catalog::MODEL_CATALOG
.iter()
.find(|m| m.name == model)
.ok_or_else(|| anyhow::anyhow!("Unknown model: {}", model))?;
let hardware = detect_hardware();
if !force && model_spec.ram_required_gb > hardware.total_ram_gb {
anyhow::bail!(
"Insufficient RAM. Model requires {}GB, you have {}GB. Use --force to override.",
model_spec.ram_required_gb,
hardware.total_ram_gb
);
}
let path = get_model_path(&model_spec.filename).await?;
if path.exists() {
println!("Model already installed at {:?}", path);
return Ok(());
}
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).await?;
}
download_model(model_spec, &path).await?;
println!("✅ Model {} installed successfully", model);
}
LocalModelSub::Remove { model } => {
let model_spec = crate::models::catalog::MODEL_CATALOG
.iter()
.find(|m| m.name == model)
.ok_or_else(|| anyhow::anyhow!("Unknown model: {}", model))?;
let path = get_model_path(&model_spec.filename).await?;
if path.exists() {
fs::remove_file(&path).await?;
println!("✅ Model {} removed successfully", model);
} else {
println!("Model {} not found at {:?}", model, path);
}
}
LocalModelSub::Verify { model } => {
let model_spec = crate::models::catalog::MODEL_CATALOG
.iter()
.find(|m| m.name == model)
.ok_or_else(|| anyhow::anyhow!("Unknown model: {}", model))?;
let path = get_model_path(&model_spec.filename).await?;
if path.exists() {
println!("✅ Model {} found and verified at {:?}", model, path);
} else {
println!("❌ Model {} not found at {:?}", model, path);
}
}
LocalModelSub::Benchmark {
model,
format,
runtime,
all_runtimes,
} => {
let opts = BenchmarkCliOptions {
model,
format,
runtime,
all_runtimes,
};
benchmark_model(opts).await?;
}
LocalModelSub::Use { model } => {
println!("Setting {} as the default model", model);
println!("Note: This would normally update the default model in your config file.");
}
LocalModelSub::Status => {
let hardware = detect_hardware();
let catalog = &crate::models::catalog::MODEL_CATALOG;
println!("Hardware Profile:");
println!(
" RAM: {}GB total, {}GB available",
hardware.total_ram_gb, hardware.available_ram_gb
);
println!(
" CPU: {} physical cores, {} logical cores",
hardware.cpu_physical_cores, hardware.cpu_logical_cores
);
println!(" Disk free: {}GB", hardware.free_disk_gb);
if let Some(gpu) = &hardware.gpu {
println!(
" GPU: {} {} with {}GB memory",
gpu.brand, gpu.model, gpu.memory_gb
);
} else {
println!(" GPU: None detected");
}
println!(" Platform: {:?}\n", hardware.platform);
let models_dir = models_root().await?;
let mut installed_count = 0usize;
for model in catalog.iter() {
let path = models_dir.join(&model.filename);
if fs::metadata(&path).await.is_ok() {
installed_count += 1;
}
}
println!("Installed models: {}", installed_count);
match hardware.platform {
PlatformKind::Windows | PlatformKind::WindowsWsl => {
let status = windows::WindowsAdapterStatus::gather().await;
println!(
"WSL IP: {}",
status.wsl_ip.unwrap_or_else(|| "not detected".to_string())
);
println!(" Ollama (WSL2): {}", bool_icon(status.ollama_reachable));
println!(" LM Studio API: {}", bool_icon(status.lmstudio_reachable));
println!(" GPT4All API: {}", bool_icon(status.gpt4all_reachable));
println!(
" Foundry Local API: {}",
bool_icon(status.foundry_reachable)
);
let gpu_report = windows::check_wsl_gpu();
println!(" GPU passthrough: {}", gpu_report.message);
}
PlatformKind::MacOs => {
let status = macos::CoremlRuntimeStatus::detect();
println!(
"Core ML tools installed: {}",
bool_icon(status.coremltools_available)
);
println!(
"Apple Neural Engine available: {}",
bool_icon(status.ane_available)
);
for note in status.notes {
println!(" - {}", note);
}
}
PlatformKind::Linux => {
let status = linux::LinuxRuntimeStatus::detect();
println!("Ollama socket present: {}", bool_icon(status.ollama_socket));
println!("CUDA detected: {}", bool_icon(status.cuda_available));
for note in status.notes {
println!(" - {}", note);
}
}
PlatformKind::Unknown => {
println!("Platform-specific runtime diagnostics unavailable.");
}
}
}
}
Ok(())
}
async fn models_root() -> Result<std::path::PathBuf> {
let path = dirs::data_dir()
.unwrap_or_else(|| std::env::current_dir().unwrap())
.join("kandil")
.join("models");
fs::create_dir_all(&path).await?;
Ok(path)
}
fn bool_icon(value: bool) -> &'static str {
if value {
"✅"
} else {
"⚠️"
}
}
async fn get_model_path(filename: &str) -> Result<std::path::PathBuf> {
Ok(models_root().await?.join(filename))
}
async fn download_model(
model: &crate::models::catalog::ModelSpec,
path: &std::path::PathBuf,
) -> Result<()> {
let url = format!(
"https://huggingface.co/{}/resolve/main/{}",
model.huggingface_repo, model.filename
);
let client = reqwest::Client::new();
let response = client.get(&url).send().await?;
let total_size = response.content_length().unwrap_or(0);
let pb = indicatif::ProgressBar::new(total_size);
pb.set_style(indicatif::ProgressStyle::default_bar()
.template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {bytes}/{total_bytes} ({eta})")
.unwrap());
let mut file = tokio::io::BufWriter::new(fs::File::create(path).await?);
let mut stream = response.bytes_stream();
while let Some(chunk) = stream.next().await {
let chunk = chunk?;
pb.inc(chunk.len() as u64);
tokio::io::copy(&mut &chunk[..], &mut file).await?;
}
pb.finish_with_message("Download complete");
file.flush().await?;
Ok(())
}
async fn benchmark_model(opts: BenchmarkCliOptions) -> Result<()> {
let cfg = Config::load()?;
let model = opts.model.clone().unwrap_or_else(|| cfg.ai_model.clone());
let suite = CrossPlatformBenchmark::new();
let report = suite
.run(BenchmarkOptions {
model: model.clone(),
default_provider: cfg.ai_provider.clone(),
runtime: opts.runtime.clone(),
include_all_runtimes: opts.all_runtimes,
prompts: None,
})
.await?;
match opts.format.to_lowercase().as_str() {
"json" => {
println!("{}", serde_json::to_string_pretty(&report)?);
}
_ => {
println!("📊 Cross-Platform Benchmark");
println!("Model: {}", report.model);
println!(
"Hardware: {}GB RAM ({}GB available) • Disk free: {}GB • Platform: {:?}",
report.hardware.total_ram_gb,
report.hardware.available_ram_gb,
report.hardware.free_disk_gb,
report.hardware.platform
);
if let Some(gpu) = &report.hardware.gpu {
println!("GPU: {} {} ({}GB)", gpu.brand, gpu.model, gpu.memory_gb);
} else {
println!("GPU: not detected");
}
println!("Prompts: {}", report.prompts.len());
println!("Timestamp: {}", report.timestamp);
for runtime in &report.results {
println!("\nRuntime: {}", runtime.runtime);
println!(" Provider: {}", runtime.provider);
println!(" Avg latency: {} ms", runtime.average_latency_ms);
println!(
" Avg throughput: {} tokens/s",
runtime.average_tokens_per_sec
);
println!(" Memory peak: {} MB", runtime.memory_peak_mb);
if let Some(impact) = runtime.battery_impact {
println!(" Battery impact: {:.1}%/min", impact);
}
println!(" Samples:");
for sample in &runtime.samples {
println!(
" • {} → {} ms, {} tokens",
sample.prompt, sample.latency_ms, sample.output_tokens
);
}
}
if !report.warnings.is_empty() {
println!("\nWarnings:");
for warning in &report.warnings {
println!(" - {}", warning);
}
}
}
}
Ok(())
}
async fn handle_auth(sub: AuthSub) -> Result<()> {
match sub {
AuthSub::Login { provider } => {
println!("Enter API key for {}:", provider);
let mut buf = String::new();
use std::io::Read;
let mut stdin = std::io::stdin();
stdin.read_to_string(&mut buf)?;
let key = buf.trim().to_string();
if key.is_empty() {
return Err(anyhow::anyhow!("Empty API key"));
}
SecureKey::save(&provider, &key)?;
println!("API key saved for {}", provider);
}
}
Ok(())
}
async fn handle_pwa(output: PathBuf) -> Result<()> {
pwa::write_assets(&output)?;
println!("📦 PWA assets exported to {}", output.display());
Ok(())
}
async fn handle_windows(sub: WindowsSub) -> Result<()> {
match sub {
WindowsSub::Status => {
let status = windows::WindowsAdapterStatus::gather().await;
println!(
"WSL IP: {}",
status.wsl_ip.unwrap_or_else(|| "not detected".to_string())
);
println!(
"Ollama (WSL2) reachable: {}",
if status.ollama_reachable {
"✅"
} else {
"⚠️"
}
);
println!(
"LM Studio API reachable: {}",
if status.lmstudio_reachable {
"✅"
} else {
"⚠️"
}
);
println!(
"GPT4All API reachable: {}",
if status.gpt4all_reachable {
"✅"
} else {
"⚠️"
}
);
println!(
"Foundry Local reachable: {}",
if status.foundry_reachable {
"✅"
} else {
"⚠️"
}
);
}
WindowsSub::CheckGpu => {
let report = windows::check_wsl_gpu();
println!("{}", report.message);
}
WindowsSub::Doctor => {
use crate::benchmark::CrossPlatformBenchmark;
let benchmark = CrossPlatformBenchmark::new();
let report = benchmark.run_diagnostics().await;
println!("🏥 Windows System Diagnostic Report:");
println!("Platform: {:?}", report.hardware.platform);
println!("Hardware: {}GB RAM, {} CPU cores",
report.hardware.total_ram_gb, report.hardware.cpu_logical_cores);
if let Some(gpu) = &report.hardware.gpu {
println!("GPU: {} {} with {}GB memory",
gpu.brand, gpu.model, gpu.memory_gb);
}
let reachable_count = report.connectivity.endpoints.iter().filter(|e| e.reachable).count();
println!("Connectivity: {}/{} endpoints reachable",
reachable_count, report.connectivity.endpoints.len());
for endpoint in &report.connectivity.endpoints {
let status = if endpoint.reachable { "✅" } else { "❌" };
println!(" {} {}: {}", status, endpoint.name, endpoint.endpoint);
}
}
WindowsSub::SetupWsl2 => {
println!("{}", windows::setup_wsl2_instructions());
}
}
Ok(())
}
async fn handle_macos(sub: MacosSub) -> Result<()> {
match sub {
MacosSub::Status => {
let status = macos::CoremlRuntimeStatus::detect();
println!(
"Core ML tools installed: {}",
bool_icon(status.coremltools_available)
);
println!(
"Apple Neural Engine available: {}",
bool_icon(status.ane_available)
);
for note in status.notes {
println!(" - {}", note);
}
}
MacosSub::Doctor => {
use crate::benchmark::CrossPlatformBenchmark;
let benchmark = CrossPlatformBenchmark::new();
let report = benchmark.run_diagnostics().await;
println!("🏥 macOS System Diagnostic Report:");
println!("Platform: {:?}", report.hardware.platform);
println!("Hardware: {}GB RAM, {} CPU cores",
report.hardware.total_ram_gb, report.hardware.cpu_logical_cores);
if let Some(gpu) = &report.hardware.gpu {
println!("GPU: {} {} with {}GB memory",
gpu.brand, gpu.model, gpu.memory_gb);
}
let reachable_count = report.connectivity.endpoints.iter().filter(|e| e.reachable).count();
println!("Connectivity: {}/{} endpoints reachable",
reachable_count, report.connectivity.endpoints.len());
for endpoint in &report.connectivity.endpoints {
let status = if endpoint.reachable { "✅" } else { "❌" };
println!(" {} {}: {}", status, endpoint.name, endpoint.endpoint);
}
}
MacosSub::SetupCoreml => {
println!("{}", macos::setup_instructions());
}
}
Ok(())
}
async fn handle_linux(sub: LinuxSub) -> Result<()> {
match sub {
LinuxSub::Status => {
let status = linux::LinuxRuntimeStatus::detect();
println!("Ollama socket present: {}", bool_icon(status.ollama_socket));
println!("CUDA detected: {}", bool_icon(status.cuda_available));
for note in status.notes {
println!(" - {}", note);
}
}
LinuxSub::Doctor => {
let hardware = detect_hardware();
PlatformHardener::new(&hardware).apply()?;
println!("Ran Linux platform hardening checks. Review warnings above, if any.");
use crate::benchmark::CrossPlatformBenchmark;
let benchmark = CrossPlatformBenchmark::new();
let report = benchmark.run_diagnostics().await;
println!("\n🏥 Additional System Diagnostic Report:");
println!("Platform: {:?}", report.hardware.platform);
println!("Connectivity endpoints reachable: {}/{}",
report.connectivity.endpoints.iter().filter(|e| e.reachable).count(),
report.connectivity.endpoints.len());
println!("Memory usage: {}MB baseline, {}MB peak",
report.performance.memory_baseline_mb,
report.performance.memory_peak_mb);
}
LinuxSub::Setup => {
println!("{}", linux::setup_instructions());
}
}
Ok(())
}
async fn handle_doctor(verbose: bool, format: &str) -> Result<()> {
use crate::benchmark::CrossPlatformBenchmark;
println!("🏥 Running system diagnostics...");
let benchmark = CrossPlatformBenchmark::new();
let report = benchmark.run_diagnostics().await;
match format.to_lowercase().as_str() {
"json" => {
println!("{}", serde_json::to_string_pretty(&report)?);
}
"table" | "text" => {
println!("\n🏥 Kandil Code System Diagnostic Report");
println!("=====================================");
println!("Timestamp: {}", report.timestamp);
println!("\n🖥️ Hardware Profile:");
println!(" Platform: {:?}", report.hardware.platform);
println!(" CPU: {} physical cores, {} logical cores",
report.hardware.cpu_physical_cores, report.hardware.cpu_logical_cores);
println!(" RAM: {}GB total, {}GB available",
report.hardware.total_ram_gb, report.hardware.available_ram_gb);
println!(" Disk: {}GB free", report.hardware.free_disk_gb);
if let Some(gpu) = &report.hardware.gpu {
println!(" GPU: {} {} with {}GB memory",
gpu.brand, gpu.model, gpu.memory_gb);
} else {
println!(" GPU: None detected");
}
println!("\n🔌 Connectivity Status:");
for endpoint in &report.connectivity.endpoints {
let status = if endpoint.reachable { "✅" } else { "❌" };
println!(" {} {}: {} ({})", status, endpoint.name, endpoint.endpoint, endpoint.reachable);
}
println!("\n⚡ Performance Metrics:");
println!(" CPU Test Duration: {}ms", report.performance.cpu_test_duration_ms);
println!(" Memory Baseline: {}MB", report.performance.memory_baseline_mb);
println!(" Memory Peak: {}MB", report.performance.memory_peak_mb);
println!("\n🔒 Security Status:");
println!(" API Keys Secure: {}", if report.security.api_key_secure { "✅" } else { "⚠️ " });
println!(" Network Secure: {}", if report.security.network_secure { "✅" } else { "⚠️ " });
if verbose {
println!("\n📋 Detailed Report:");
println!(" Hardware: {:?}", report.hardware);
println!(" Connectivity: {:?}", report.connectivity);
println!(" Performance: {:?}", report.performance);
println!(" Security: {:?}", report.security);
}
}
_ => {
println!("{}", serde_json::to_string_pretty(&report)?);
}
}
Ok(())
}
async fn handle_mobile(sub: MobileSub) -> Result<()> {
let models_dir = models_root().await?;
match sub {
MobileSub::IosSync => {
let dir = models_dir.clone();
let export = task::spawn_blocking(move || mobile::export_ios_bundle(&dir)).await??;
mobile_security::enforce_ios_bundle_security(&export)?;
println!("📦 iOS bundle created at {}", export.display());
println!(
"Copy this directory into iCloud Drive and import it from the Kandil iOS app."
);
}
MobileSub::AndroidSync => {
let dir = models_dir.clone();
let export =
task::spawn_blocking(move || mobile::export_android_bundle(&dir)).await??;
mobile_security::enforce_android_bundle_security(&export)?;
println!("🤖 Android bundle created at {}", export.display());
println!("Transfer it to /sdcard/kandil/models and use Termux or AI Core to import.");
}
MobileSub::EdgeSnapshot => {
let dir = models_dir.clone();
let export = task::spawn_blocking(move || edge::export_edge_snapshot(&dir)).await??;
mobile_security::enforce_edge_bundle_security(&export)?;
println!("🛠️ Edge manifest written to {}", export.display());
println!(
"Use the manifest to drive ONNX exports for Raspberry Pi / Jetson deployments."
);
}
}
Ok(())
}