1pub mod agent;
2pub mod analyzer;
3pub mod bedrock; pub mod cli;
5pub mod common;
6pub mod config;
7pub mod error;
8pub mod generator;
9pub mod handlers;
10pub mod telemetry; pub use analyzer::{ProjectAnalysis, analyze_project};
14use cli::Commands;
15pub use error::{IaCGeneratorError, Result};
16pub use generator::{generate_compose, generate_dockerfile, generate_terraform};
17pub use handlers::*;
18pub use telemetry::{TelemetryClient, TelemetryConfig, UserId}; pub const VERSION: &str = env!("CARGO_PKG_VERSION");
22
23pub async fn run_command(command: Commands) -> Result<()> {
24 match command {
25 Commands::Analyze {
26 path,
27 json,
28 detailed,
29 display,
30 only,
31 color_scheme,
32 } => {
33 match handlers::handle_analyze(path, json, detailed, display, only, color_scheme) {
34 Ok(_output) => Ok(()), Err(e) => Err(e),
36 }
37 }
38 Commands::Generate {
39 path,
40 output,
41 dockerfile,
42 compose,
43 terraform,
44 all,
45 dry_run,
46 force,
47 } => handlers::handle_generate(
48 path, output, dockerfile, compose, terraform, all, dry_run, force,
49 ),
50 Commands::Validate { path, types, fix } => handlers::handle_validate(path, types, fix),
51 Commands::Support {
52 languages,
53 frameworks,
54 detailed,
55 } => handlers::handle_support(languages, frameworks, detailed),
56 Commands::Dependencies {
57 path,
58 licenses,
59 vulnerabilities,
60 prod_only,
61 dev_only,
62 format,
63 } => handlers::handle_dependencies(
64 path,
65 licenses,
66 vulnerabilities,
67 prod_only,
68 dev_only,
69 format,
70 )
71 .await
72 .map(|_| ()),
73 Commands::Vulnerabilities {
74 path,
75 severity,
76 format,
77 output,
78 } => handlers::handle_vulnerabilities(path, severity, format, output).await,
79 Commands::Security {
80 path,
81 mode,
82 include_low,
83 no_secrets,
84 no_code_patterns,
85 no_infrastructure,
86 no_compliance,
87 frameworks,
88 format,
89 output,
90 fail_on_findings,
91 } => {
92 handlers::handle_security(
93 path,
94 mode,
95 include_low,
96 no_secrets,
97 no_code_patterns,
98 no_infrastructure,
99 no_compliance,
100 frameworks,
101 format,
102 output,
103 fail_on_findings,
104 )
105 .map(|_| ()) }
107 Commands::Tools { command } => handlers::handle_tools(command).await,
108 Commands::Chat {
109 path,
110 provider,
111 model,
112 query,
113 resume,
114 list_sessions: _, } => {
116 use agent::ProviderType;
117 use cli::ChatProvider;
118 use config::load_agent_config;
119
120 let project_path = path.canonicalize().unwrap_or(path);
121
122 if let Some(ref resume_arg) = resume {
124 use agent::persistence::{SessionSelector, format_relative_time};
125
126 let selector = SessionSelector::new(&project_path);
127 if let Some(session_info) = selector.resolve_session(resume_arg) {
128 let time = format_relative_time(session_info.last_updated);
129 println!(
130 "\nResuming session: {} ({}, {} messages)",
131 session_info.display_name, time, session_info.message_count
132 );
133 println!("Session ID: {}\n", session_info.id);
134
135 match selector.load_conversation(&session_info) {
137 Ok(record) => {
138 println!("--- Previous conversation ---");
140 for msg in record.messages.iter().take(5) {
141 let role = match msg.role {
142 agent::persistence::MessageRole::User => "You",
143 agent::persistence::MessageRole::Assistant => "AI",
144 agent::persistence::MessageRole::System => "System",
145 };
146 let preview = if msg.content.len() > 100 {
147 format!("{}...", &msg.content[..100])
148 } else {
149 msg.content.clone()
150 };
151 println!(" {}: {}", role, preview);
152 }
153 if record.messages.len() > 5 {
154 println!(" ... and {} more messages", record.messages.len() - 5);
155 }
156 println!("--- End of history ---\n");
157 }
159 Err(e) => {
160 eprintln!("Warning: Failed to load session history: {}", e);
161 }
162 }
163 } else {
164 eprintln!(
165 "Session '{}' not found. Use --list-sessions to see available sessions.",
166 resume_arg
167 );
168 return Ok(());
169 }
170 }
171
172 let agent_config = load_agent_config();
174
175 let (provider_type, effective_model) = match provider {
177 ChatProvider::Openai => (ProviderType::OpenAI, model),
178 ChatProvider::Anthropic => (ProviderType::Anthropic, model),
179 ChatProvider::Bedrock => (ProviderType::Bedrock, model),
180 ChatProvider::Ollama => {
181 eprintln!("Ollama support coming soon. Using OpenAI as fallback.");
182 (ProviderType::OpenAI, model)
183 }
184 ChatProvider::Auto => {
185 let saved_provider = match agent_config.default_provider.as_str() {
187 "openai" => ProviderType::OpenAI,
188 "anthropic" => ProviderType::Anthropic,
189 "bedrock" => ProviderType::Bedrock,
190 _ => ProviderType::OpenAI, };
192 let saved_model = if model.is_some() {
194 model
195 } else {
196 agent_config.default_model.clone()
197 };
198 (saved_provider, saved_model)
199 }
200 };
201
202 agent::session::ChatSession::load_api_key_to_env(provider_type);
205
206 if let Some(q) = query {
207 let response =
208 agent::run_query(&project_path, &q, provider_type, effective_model).await?;
209 println!("{}", response);
210 Ok(())
211 } else {
212 agent::run_interactive(&project_path, provider_type, effective_model).await?;
213 Ok(())
214 }
215 }
216 }
217}