1use clap::{Parser, Subcommand};
2
3#[derive(Parser)]
4#[command(name = "rustchain")]
5#[command(about = "RustChain - Advanced AI Agent Framework")]
6#[command(long_about = "RustChain is a powerful AI orchestration framework built in Rust.
7
8Execute missions, chat with AI models, manage tools, and ensure safety across
9all AI operations. Designed for developers, researchers, and enterprises.
10
11QUICK START:
12 rustchain run examples/hello_world.yaml # Run your first mission
13 rustchain interactive # Start conversational mode
14 rustchain mission list # List available missions
15 rustchain safety validate mission.yaml # Validate mission safety
16
17For detailed help on any command, use: rustchain <COMMAND> --help
18Documentation: https://github.com/rustchain-community/rustchain-community")]
19#[command(version = "0.1.0")]
20pub struct Cli {
21 #[command(subcommand)]
22 pub command: Commands,
23}
24
25#[derive(Subcommand)]
26pub enum Commands {
27 #[command(long_about = "Start an interactive session where you can:
33• Have natural conversations with AI models
34• Create and execute missions dynamically
35• Get real-time help and guidance
36• Explore RustChain capabilities interactively
37
38Example session:
39$ rustchain interactive
40> create a mission to analyze my Rust codebase
41> run the generated mission
42> show me performance metrics")]
43 Interactive,
44
45 #[command(long_about = "Execute a RustChain mission file with comprehensive safety checks.
50
51MISSION FILE EXAMPLE:
52name: \"Hello World\"
53description: \"Simple demonstration\"
54version: \"1.0\"
55steps:
56 - id: \"greet\"
57 step_type: \"llm\"
58 parameters:
59 provider: \"openai\"
60 model: \"gpt-4\"
61 prompt: \"Say hello in a creative way\"
62
63BEST PRACTICES:
64• Always validate with --dry-run first
65• Review safety warnings before proceeding
66• Start with simple missions and build complexity
67• Keep mission files in version control")]
68 Run {
69 #[arg(help = "Path to YAML mission file (e.g., examples/hello_world.yaml)")]
71 mission: String,
72 #[arg(short, long, help = "Validate and plan execution without running tools - safe to use")]
74 dry_run: bool,
75 #[arg(short, long, help = "Skip safety validation - only use with trusted missions")]
77 skip_safety: bool,
78 },
79 #[command(long_about = "Mission management for RustChain workflows.
84
85COMMON OPERATIONS:
86• List example missions: rustchain mission list
87• Validate mission file: rustchain mission validate mission.yaml
88• Get mission details: rustchain mission info mission.yaml
89
90VALIDATION CHECKS:
91CHECKS: YAML syntax correctness
92CHECKS: Required fields present
93CHECKS: Step dependencies resolved
94CHECKS: Parameter requirements met")]
95 Mission {
96 #[command(subcommand)]
97 action: MissionAction,
98 },
99
100 #[command(long_about = "Security policy management for safe AI operations.
105
106POLICY TYPES:
107FILE ACCESS: Control file system operations
108NETWORK POLICY: Manage external connections
109COMMAND EXECUTION: Restrict system commands
110LLM SAFETY: Filter AI interactions
111
112COMMANDS:
113• View active policies: rustchain policy list
114• Check policy status: rustchain policy status
115• Validate configuration: rustchain policy validate")]
116 Policy {
117 #[command(subcommand)]
118 action: PolicyAction,
119 },
120
121 #[command(long_about = "Security validation and risk assessment.
126
127SAFETY FEATURES:
128MISSION ANALYSIS: Review all mission steps
129RISK ASSESSMENT: Evaluate security implications
130POLICY COMPLIANCE: Check against active policies
131
132RISK LEVELS:
133LOW: Safe to execute
134MEDIUM: Review recommended
135HIGH: Caution required
136CRITICAL: Do not execute
137
138BEST PRACTICE: Always run 'rustchain safety validate' before executing missions")]
139 Safety {
140 #[command(subcommand)]
141 action: SafetyAction,
142 },
143 #[cfg(feature = "tools")]
148 #[command(long_about = "Tool management and direct execution.
149
150TOOL CATEGORIES:
151FILE OPERATIONS: file_create, file_read, file_write
152NETWORK OPERATIONS: http_request, websocket_connect
153SYSTEM OPERATIONS: command_execute, process_info
154AI OPERATIONS: llm_call, embedding_generate
155
156EXAMPLES:
157• List all tools: rustchain tools list
158• Get tool info: rustchain tools info file_create
159• Execute tool: rustchain tools execute file_create --params '{\"path\":\"test.txt\",\"content\":\"Hello\"}'
160
161All tools respect security policies and run in controlled environments.")]
162 Tools {
163 #[command(subcommand)]
164 action: ToolAction,
165 },
166
167 #[cfg(feature = "llm")]
172 #[command(long_about = "AI model interactions and management.
173
174SUPPORTED PROVIDERS:
175• OpenAI - GPT-3.5, GPT-4, GPT-4 Turbo
176• Anthropic - Claude 3 family (Haiku, Sonnet, Opus)
177• Ollama - Local models (Llama, Mistral, CodeLlama)
178• Custom providers via API configuration
179
180EXAMPLES:
181Note: LLM commands are available when compiled with 'llm' feature flag
182• Interactive mode: rustchain interactive
183• Mission execution: rustchain run examples/chat_mission.yaml
184• Safety validation: rustchain safety validate mission.yaml
185
186SETUP: Configure API keys in environment variables or config file.")]
187 LLM {
188 #[command(subcommand)]
189 action: LLMAction,
190 },
191 #[cfg(feature = "rag")]
193 RAG {
194 #[command(subcommand)]
195 action: RAGAction,
196 },
197 #[cfg(feature = "sandbox")]
199 Sandbox {
200 #[command(subcommand)]
201 action: SandboxAction,
202 },
203 #[cfg(feature = "server")]
205 Server {
206 #[command(subcommand)]
207 action: ServerAction,
208 },
209 Audit {
211 #[command(subcommand)]
212 action: AuditAction,
213 },
214 Build {
216 #[command(subcommand)]
217 action: BuildAction,
218 },
219 Config {
221 #[command(subcommand)]
222 action: ConfigAction,
223 },
224 Enterprise {
226 #[command(subcommand)]
227 action: EnterpriseAction,
228 },
229 Features {
231 #[command(subcommand)]
232 action: FeatureAction,
233 },
234 #[cfg(feature = "compliance")]
236 Compliance {
237 #[command(subcommand)]
238 action: ComplianceAction,
239 },
240
241 #[command(long_about = "Universal workflow transpilation for enterprise platforms.
246
247SUPPORTED FORMATS:
248INPUT FORMATS:
249 • LangChain Python scripts (.py)
250 • Airflow DAGs (.py)
251 • GitHub Actions workflows (.yml)
252 • Kubernetes manifests (.yaml)
253 • Docker Compose files (.yml)
254 • Jenkins pipelines (Jenkinsfile)
255 • Terraform configurations (.tf)
256 • Bash scripts (.sh)
257 • Cron expressions
258
259OUTPUT FORMATS:
260 • RustChain YAML missions
261 • All input formats (bidirectional)
262
263ENTERPRISE FEATURES:
264FEATURE: Complete workflow transpilation with zero information loss
265FEATURE: Authentication and security configuration preservation
266FEATURE: Performance optimization for Rust-native execution
267FEATURE: Compliance validation (SOX, GDPR, HIPAA)
268FEATURE: Enterprise-grade error handling and retry logic
269
270EXAMPLES:
271 # Convert LangChain to RustChain
272 rustchain transpile langchain_pipeline.py --output rustchain
273
274 # Convert to all platforms
275 rustchain transpile workflow.py --output-all
276
277 # Enterprise validation
278 rustchain transpile enterprise.py --validate-compliance
279
280DEMO READY: This is production-grade transpilation technology.")]
281 Transpile {
282 #[command(subcommand)]
283 action: TranspileAction,
284 },
285
286 #[command(long_about = "COMPETITIVE PERFORMANCE SHOWDOWN
296
297TECHNICAL DEMO READY: Side-by-side comparisons demonstrating RustChain's technical advantages
298
299SUPPORTED COMPARISONS:
300 LangChain Python → 97% faster execution
301 Apache Airflow → 90% memory reduction
302 GitHub Actions → Instant vs container overhead
303 Jenkins Pipeline → No JVM startup delays
304 Kubernetes Native → Optimized resource usage
305 Docker Compose → Native binary efficiency
306
307PERFORMANCE METRICS:
308 • Execution time (milliseconds)
309 • Memory usage (MB)
310 • CPU efficiency (%)
311 • Throughput (ops/second)
312 • Error rates (%)
313 • Startup overhead
314
315TECHNICAL VALUE:
316 • Technical advantages impossible to replicate in Python
317 • Universal workflow portability
318 • Enterprise-grade memory safety
319 • 10-100x performance advantages
320
321EXAMPLES:
322 # Full competitive analysis
323 rustchain benchmark showdown
324
325 # Live performance dashboard
326 rustchain benchmark dashboard
327
328 # Generate technical report
329 rustchain benchmark report --output technical-analysis.md
330
331EVALUATION READY: Technical performance comparison demonstrations.")]
332 Benchmark {
333 #[command(subcommand)]
334 action: BenchmarkAction,
335 },
336}
337
338#[derive(Subcommand)]
339pub enum MissionAction {
340 List,
342 Validate {
344 file: String,
346 },
347 Info {
349 file: String,
351 },
352}
353
354#[derive(Subcommand, Debug)]
355pub enum PolicyAction {
356 List,
358 Validate,
360 Status,
362}
363
364#[derive(Subcommand)]
365pub enum SafetyAction {
366 Validate {
368 mission: String,
370 #[arg(long)]
372 strict: bool,
373 },
374 Check {
376 #[arg(long)]
378 include_policies: bool,
379 },
380 Report {
382 mission: String,
384 #[arg(short, long, default_value = "text")]
386 format: String,
387 },
388}
389
390#[cfg(feature = "tools")]
391#[derive(Subcommand)]
392pub enum ToolAction {
393 List,
395 Info {
397 name: String,
399 },
400 Execute {
402 name: String,
404 #[arg(short, long)]
406 params: Option<String>,
407 },
408}
409
410#[cfg(feature = "llm")]
411#[derive(Subcommand)]
412pub enum LLMAction {
413 Models {
415 #[arg(short, long)]
417 provider: Option<String>,
418 },
419 Chat {
421 message: String,
423 #[arg(short, long)]
425 model: Option<String>,
426 #[arg(short, long)]
428 provider: Option<String>,
429 #[arg(short, long)]
431 temperature: Option<f32>,
432 },
433 Test {
435 provider: Option<String>,
437 },
438}
439
440#[cfg(feature = "rag")]
441#[derive(Subcommand)]
442pub enum RAGAction {
443 Add {
445 #[arg(short, long)]
447 id: String,
448 #[arg(short, long)]
450 file: String,
451 #[arg(short, long)]
453 metadata: Option<String>,
454 },
455 Search {
457 query: String,
459 #[arg(short, long, default_value = "5")]
461 limit: usize,
462 #[arg(short, long)]
464 threshold: Option<f32>,
465 },
466 List {
468 #[arg(long, default_value = "0")]
470 offset: usize,
471 #[arg(short, long, default_value = "10")]
473 limit: usize,
474 },
475 Delete {
477 id: String,
479 },
480 Context {
482 query: String,
484 #[arg(short, long, default_value = "2000")]
486 max_length: usize,
487 },
488}
489
490#[cfg(feature = "sandbox")]
491#[derive(Subcommand)]
492pub enum SandboxAction {
493 Create,
495 Execute {
497 #[arg(short, long)]
499 session: String,
500 command: String,
502 args: Vec<String>,
504 },
505 Write {
507 #[arg(short, long)]
509 session: String,
510 #[arg(short, long)]
512 file: String,
513 #[arg(short, long)]
515 content: String,
516 },
517 Read {
519 #[arg(short, long)]
521 session: String,
522 #[arg(short, long)]
524 file: String,
525 },
526 Files {
528 #[arg(short, long)]
530 session: String,
531 },
532 Info {
534 #[arg(short, long)]
536 session: String,
537 },
538 Destroy {
540 #[arg(short, long)]
542 session: String,
543 },
544 List,
546 Cleanup {
548 #[arg(short, long)]
550 session: String,
551 },
552 CleanupAll,
554}
555
556#[cfg(feature = "server")]
557#[derive(Subcommand)]
558pub enum ServerAction {
559 Start {
561 #[arg(long, default_value = "127.0.0.1")]
563 host: String,
564 #[arg(long, default_value = "8080")]
566 port: u16,
567 #[arg(long)]
569 cors: bool,
570 #[arg(long, help = "Enable agent mode for Shimmy TUI integration")]
572 agent_mode: bool,
573 },
574 Config,
576}
577
578#[derive(Subcommand)]
579pub enum AuditAction {
580 Query {
582 #[arg(long)]
584 start_time: Option<String>,
585 #[arg(long)]
587 end_time: Option<String>,
588 #[arg(long)]
590 event_types: Option<Vec<String>>,
591 #[arg(short, long, default_value = "10")]
593 limit: usize,
594 #[arg(long, default_value = "0")]
596 offset: usize,
597 },
598 Report {
600 #[arg(long)]
602 start_time: Option<String>,
603 #[arg(long)]
605 end_time: Option<String>,
606 #[arg(short, long, default_value = "json")]
608 format: String,
609 },
610 Verify,
612 Export {
614 #[arg(short, long, default_value = "json")]
616 format: String,
617 #[arg(short, long)]
619 output: Option<String>,
620 },
621 Stats,
623}
624
625#[derive(Subcommand, Debug)]
626pub enum BuildAction {
627 Dashboard,
629 Status,
631 Update,
633 Save {
635 #[arg(short, long, default_value = "build_dashboard.json")]
637 output: String,
638 },
639 Load {
641 #[arg(short, long)]
643 input: String,
644 },
645}
646
647#[derive(Subcommand, Debug)]
648pub enum ConfigAction {
649 Show,
651 Validate,
653 Init,
655}
656
657#[derive(Subcommand, Debug)]
658pub enum EnterpriseAction {
659 Auth {
661 #[command(subcommand)]
662 action: AuthAction,
663 },
664 Compliance {
666 #[command(subcommand)]
667 action: ComplianceAction,
668 },
669 Monitoring {
671 #[command(subcommand)]
672 action: MonitoringAction,
673 },
674 MultiTenant {
676 #[command(subcommand)]
677 action: MultiTenantAction,
678 },
679}
680
681#[derive(Subcommand, Debug)]
682pub enum FeatureAction {
683 List {
685 #[arg(short, long)]
687 category: Option<String>,
688 #[arg(short, long)]
690 available_only: bool,
691 },
692 Check {
694 feature: String,
696 },
697 Summary,
699 Upgrade,
701}
702
703#[derive(Subcommand, Debug)]
704pub enum AuthAction {
705 InitJWT {
707 #[arg(short, long)]
709 secret: Option<String>,
710 },
711 SetupOAuth2 {
713 provider: String,
715 #[arg(short, long)]
717 client_id: String,
718 },
719 SetupRBAC {
721 #[arg(short, long)]
723 roles_file: String,
724 },
725 Test,
727}
728
729#[derive(Subcommand, Debug)]
730pub enum ComplianceAction {
731 Verify {
733 mission: String,
735 #[arg(short, long)]
737 standard: Option<String>,
738 #[arg(long)]
740 all_standards: bool,
741 },
742 ListStandards,
744 Report {
746 mission: String,
748 #[arg(short, long)]
750 output: Option<String>,
751 },
752 GDPRReport {
754 #[arg(short, long, default_value = "json")]
756 format: String,
757 },
758 HIPAAReport {
760 #[arg(short, long, default_value = "json")]
762 format: String,
763 },
764 SetRetention {
766 #[arg(short, long)]
768 days: u32,
769 #[arg(short, long)]
771 scope: String,
772 },
773 Audit,
775}
776
777#[derive(Subcommand, Debug)]
779pub enum TranspileAction {
780 LangChain {
784 input: String,
786 #[arg(short, long)]
788 output: Option<String>,
789 #[arg(long)]
791 validate_compliance: bool,
792 #[arg(long)]
794 optimize: bool,
795 },
796
797 Airflow {
801 input: String,
803 #[arg(short, long)]
805 output: Option<String>,
806 #[arg(long)]
808 enterprise: bool,
809 },
810
811 GitHubActions {
815 input: String,
817 #[arg(short, long)]
819 output: Option<String>,
820 #[arg(long)]
822 preserve_enterprise: bool,
823 },
824
825 Kubernetes {
829 input: String,
831 #[arg(short, long)]
833 output: Option<String>,
834 #[arg(long)]
836 production: bool,
837 },
838
839 DockerCompose {
843 input: String,
845 #[arg(short, long)]
847 output: Option<String>,
848 #[arg(long)]
850 scale: bool,
851 },
852
853 Auto {
857 input: String,
859 #[arg(short, long)]
861 output: Option<String>,
862 #[arg(long)]
864 enterprise_mode: bool,
865 #[arg(long)]
867 validate: bool,
868 },
869
870 ShowcaseAll {
875 input: String,
877 #[arg(short, long, default_value = "transpiled_output")]
879 output_dir: String,
880 #[arg(long)]
882 benchmark: bool,
883 #[arg(long)]
885 enterprise_validation: bool,
886 },
887}
888
889#[derive(Subcommand, Debug)]
890pub enum MonitoringAction {
891 StartMetrics {
893 #[arg(short, long, default_value = "9090")]
895 port: u16,
896 },
897 Dashboard,
899 SetupAlerts {
901 #[arg(short, long)]
903 config: String,
904 },
905 Metrics,
907}
908
909#[derive(Subcommand, Debug)]
910pub enum MultiTenantAction {
911 CreateTenant {
913 id: String,
915 name: String,
917 },
918 ListTenants,
920 SetupIsolation {
922 tenant: String,
924 #[arg(short, long)]
926 level: String,
927 },
928}
929
930#[derive(Subcommand, Debug)]
931pub enum BenchmarkAction {
932 Showdown {
934 #[arg(long)]
936 verbose: bool,
937 #[arg(short, long)]
939 output: Option<String>,
940 },
941 Dashboard {
943 #[arg(long, default_value = "1")]
945 refresh: u64,
946 #[arg(long, default_value = "3000")]
948 port: u16,
949 },
950 Report {
952 #[arg(short, long, default_value = "technical-competitive-analysis.md")]
954 output: String,
955 #[arg(long)]
957 detailed: bool,
958 },
959 Versus {
961 #[arg(value_enum)]
963 framework: BenchmarkFramework,
964 #[arg(short, long)]
966 workflow: Option<String>,
967 },
968 Metrics,
970}
971
972#[derive(clap::ValueEnum, Clone, Debug)]
973pub enum BenchmarkFramework {
974 LangChain,
975 Airflow,
976 GitHubActions,
977 Jenkins,
978 Kubernetes,
979 DockerCompose,
980 Terraform,
981}
982
983#[cfg(test)]
984mod tests {
985 use super::*;
986 use clap::Parser;
987
988 #[test]
989 fn test_cli_basic_structure() {
990 let cli = Cli::try_parse_from(["rustchain", "config", "show"]);
992 assert!(cli.is_ok());
993
994 if let Ok(cli) = cli {
995 assert!(matches!(cli.command, Commands::Config { .. }));
996 }
997 }
998
999 #[test]
1000 fn test_run_command_basic() {
1001 let cli = Cli::try_parse_from(["rustchain", "run", "test.yaml"]);
1002 assert!(cli.is_ok());
1003
1004 if let Ok(cli) = cli {
1005 if let Commands::Run {
1006 mission,
1007 dry_run,
1008 skip_safety,
1009 } = cli.command
1010 {
1011 assert_eq!(mission, "test.yaml");
1012 assert!(!dry_run);
1013 assert!(!skip_safety);
1014 }
1015 }
1016 }
1017
1018 #[test]
1019 fn test_run_command_with_flags() {
1020 let cli = Cli::try_parse_from([
1021 "rustchain",
1022 "run",
1023 "test.yaml",
1024 "--dry-run",
1025 "--skip-safety",
1026 ]);
1027 assert!(cli.is_ok());
1028
1029 if let Ok(cli) = cli {
1030 if let Commands::Run {
1031 mission,
1032 dry_run,
1033 skip_safety,
1034 } = cli.command
1035 {
1036 assert_eq!(mission, "test.yaml");
1037 assert!(dry_run);
1038 assert!(skip_safety);
1039 }
1040 }
1041 }
1042
1043 #[test]
1044 fn test_mission_list_command() {
1045 let cli = Cli::try_parse_from(["rustchain", "mission", "list"]);
1046 assert!(cli.is_ok());
1047
1048 if let Ok(cli) = cli {
1049 if let Commands::Mission { action } = cli.command {
1050 assert!(matches!(action, MissionAction::List));
1051 }
1052 }
1053 }
1054
1055 #[test]
1056 fn test_mission_validate_command() {
1057 let cli = Cli::try_parse_from(["rustchain", "mission", "validate", "test.yaml"]);
1058 assert!(cli.is_ok());
1059
1060 if let Ok(cli) = cli {
1061 if let Commands::Mission { action } = cli.command {
1062 if let MissionAction::Validate { file } = action {
1063 assert_eq!(file, "test.yaml");
1064 }
1065 }
1066 }
1067 }
1068
1069 #[test]
1070 fn test_mission_info_command() {
1071 let cli = Cli::try_parse_from(["rustchain", "mission", "info", "test.yaml"]);
1072 assert!(cli.is_ok());
1073
1074 if let Ok(cli) = cli {
1075 if let Commands::Mission { action } = cli.command {
1076 if let MissionAction::Info { file } = action {
1077 assert_eq!(file, "test.yaml");
1078 }
1079 }
1080 }
1081 }
1082
1083 #[test]
1084 fn test_policy_commands() {
1085 let commands = [
1086 (["rustchain", "policy", "list"], PolicyAction::List),
1087 (["rustchain", "policy", "validate"], PolicyAction::Validate),
1088 (["rustchain", "policy", "status"], PolicyAction::Status),
1089 ];
1090
1091 for (args, expected) in commands {
1092 let cli = Cli::try_parse_from(args);
1093 assert!(cli.is_ok(), "Failed to parse: {:?}", args);
1094
1095 if let Ok(cli) = cli {
1096 if let Commands::Policy { ref action } = cli.command {
1097 assert!(std::mem::discriminant(action) == std::mem::discriminant(&expected));
1098 }
1099 }
1100 }
1101 }
1102
1103 #[test]
1104 fn test_safety_validate_command() {
1105 let cli = Cli::try_parse_from(["rustchain", "safety", "validate", "test.yaml"]);
1106 assert!(cli.is_ok());
1107
1108 if let Ok(cli) = cli {
1109 if let Commands::Safety { action } = cli.command {
1110 if let SafetyAction::Validate { mission, strict } = action {
1111 assert_eq!(mission, "test.yaml");
1112 assert!(!strict);
1113 }
1114 }
1115 }
1116 }
1117
1118 #[test]
1119 fn test_safety_validate_strict() {
1120 let cli = Cli::try_parse_from(["rustchain", "safety", "validate", "test.yaml", "--strict"]);
1121 assert!(cli.is_ok());
1122
1123 if let Ok(cli) = cli {
1124 if let Commands::Safety { action } = cli.command {
1125 if let SafetyAction::Validate { mission, strict } = action {
1126 assert_eq!(mission, "test.yaml");
1127 assert!(strict);
1128 }
1129 }
1130 }
1131 }
1132
1133 #[test]
1134 fn test_safety_check_command() {
1135 let cli = Cli::try_parse_from(["rustchain", "safety", "check", "--include-policies"]);
1136 assert!(cli.is_ok());
1137
1138 if let Ok(cli) = cli {
1139 if let Commands::Safety { action } = cli.command {
1140 if let SafetyAction::Check { include_policies } = action {
1141 assert!(include_policies);
1142 }
1143 }
1144 }
1145 }
1146
1147 #[test]
1148 fn test_safety_report_command() {
1149 let cli = Cli::try_parse_from([
1150 "rustchain",
1151 "safety",
1152 "report",
1153 "test.yaml",
1154 "--format",
1155 "json",
1156 ]);
1157 assert!(cli.is_ok());
1158
1159 if let Ok(cli) = cli {
1160 if let Commands::Safety { action } = cli.command {
1161 if let SafetyAction::Report { mission, format } = action {
1162 assert_eq!(mission, "test.yaml");
1163 assert_eq!(format, "json");
1164 }
1165 }
1166 }
1167 }
1168
1169 #[cfg(feature = "tools")]
1170 #[test]
1171 fn test_tools_list_command() {
1172 let cli = Cli::try_parse_from(["rustchain", "tools", "list"]);
1173 assert!(cli.is_ok());
1174
1175 if let Ok(cli) = cli {
1176 if let Commands::Tools { action } = cli.command {
1177 assert!(matches!(action, ToolAction::List));
1178 }
1179 }
1180 }
1181
1182 #[cfg(feature = "tools")]
1183 #[test]
1184 fn test_tools_info_command() {
1185 let cli = Cli::try_parse_from(["rustchain", "tools", "info", "file_create"]);
1186 assert!(cli.is_ok());
1187
1188 if let Ok(cli) = cli {
1189 if let Commands::Tools { action } = cli.command {
1190 if let ToolAction::Info { name } = action {
1191 assert_eq!(name, "file_create");
1192 }
1193 }
1194 }
1195 }
1196
1197 #[cfg(feature = "tools")]
1198 #[test]
1199 fn test_tools_execute_command() {
1200 let cli = Cli::try_parse_from([
1201 "rustchain",
1202 "tools",
1203 "execute",
1204 "file_create",
1205 "--params",
1206 "{\"path\":\"test.txt\"}",
1207 ]);
1208 assert!(cli.is_ok());
1209
1210 if let Ok(cli) = cli {
1211 if let Commands::Tools { action } = cli.command {
1212 if let ToolAction::Execute { name, params } = action {
1213 assert_eq!(name, "file_create");
1214 assert_eq!(params, Some("{\"path\":\"test.txt\"}".to_string()));
1215 }
1216 }
1217 }
1218 }
1219
1220 #[cfg(feature = "llm")]
1221 #[test]
1222 fn test_llm_models_command() {
1223 let cli = Cli::try_parse_from(["rustchain", "llm", "models"]);
1224 assert!(cli.is_ok());
1225
1226 if let Ok(cli) = cli {
1227 if let Commands::LLM { action } = cli.command {
1228 if let LLMAction::Models { provider } = action {
1229 assert!(provider.is_none());
1230 }
1231 }
1232 }
1233 }
1234
1235 #[cfg(feature = "llm")]
1236 #[test]
1237 fn test_llm_models_with_provider() {
1238 let cli = Cli::try_parse_from(["rustchain", "llm", "models", "--provider", "openai"]);
1239 assert!(cli.is_ok());
1240
1241 if let Ok(cli) = cli {
1242 if let Commands::LLM { action } = cli.command {
1243 if let LLMAction::Models { provider } = action {
1244 assert_eq!(provider, Some("openai".to_string()));
1245 }
1246 }
1247 }
1248 }
1249
1250 #[cfg(feature = "llm")]
1251 #[test]
1252 fn test_llm_chat_command() {
1253 let cli = Cli::try_parse_from([
1254 "rustchain",
1255 "llm",
1256 "chat",
1257 "Hello world",
1258 "--model",
1259 "gpt-4",
1260 "--provider",
1261 "openai",
1262 "--temperature",
1263 "0.7",
1264 ]);
1265 assert!(cli.is_ok());
1266
1267 if let Ok(cli) = cli {
1268 if let Commands::LLM { action } = cli.command {
1269 if let LLMAction::Chat {
1270 message,
1271 model,
1272 provider,
1273 temperature,
1274 } = action
1275 {
1276 assert_eq!(message, "Hello world");
1277 assert_eq!(model, Some("gpt-4".to_string()));
1278 assert_eq!(provider, Some("openai".to_string()));
1279 assert_eq!(temperature, Some(0.7));
1280 }
1281 }
1282 }
1283 }
1284
1285 #[cfg(feature = "llm")]
1286 #[test]
1287 fn test_llm_test_command() {
1288 let cli = Cli::try_parse_from(["rustchain", "llm", "test", "openai"]);
1289 assert!(cli.is_ok());
1290
1291 if let Ok(cli) = cli {
1292 if let Commands::LLM { action } = cli.command {
1293 if let LLMAction::Test { provider } = action {
1294 assert_eq!(provider, Some("openai".to_string()));
1295 }
1296 }
1297 }
1298 }
1299
1300 #[cfg(feature = "rag")]
1301 #[test]
1302 fn test_rag_add_command() {
1303 let cli = Cli::try_parse_from([
1304 "rustchain",
1305 "rag",
1306 "add",
1307 "--id",
1308 "doc1",
1309 "--file",
1310 "document.pdf",
1311 "--metadata",
1312 "{\"type\":\"pdf\"}",
1313 ]);
1314 assert!(cli.is_ok());
1315
1316 if let Ok(cli) = cli {
1317 if let Commands::RAG { action } = cli.command {
1318 if let RAGAction::Add { id, file, metadata } = action {
1319 assert_eq!(id, "doc1");
1320 assert_eq!(file, "document.pdf");
1321 assert_eq!(metadata, Some("{\"type\":\"pdf\"}".to_string()));
1322 }
1323 }
1324 }
1325 }
1326
1327 #[cfg(feature = "rag")]
1328 #[test]
1329 fn test_rag_search_command() {
1330 let cli = Cli::try_parse_from([
1331 "rustchain",
1332 "rag",
1333 "search",
1334 "machine learning",
1335 "--limit",
1336 "10",
1337 "--threshold",
1338 "0.8",
1339 ]);
1340 assert!(cli.is_ok());
1341
1342 if let Ok(cli) = cli {
1343 if let Commands::RAG { action } = cli.command {
1344 if let RAGAction::Search {
1345 query,
1346 limit,
1347 threshold,
1348 } = action
1349 {
1350 assert_eq!(query, "machine learning");
1351 assert_eq!(limit, 10);
1352 assert_eq!(threshold, Some(0.8));
1353 }
1354 }
1355 }
1356 }
1357
1358 #[cfg(feature = "rag")]
1359 #[test]
1360 fn test_rag_list_command() {
1361 let cli =
1362 Cli::try_parse_from(["rustchain", "rag", "list", "--offset", "5", "--limit", "20"]);
1363 assert!(cli.is_ok());
1364
1365 if let Ok(cli) = cli {
1366 if let Commands::RAG { action } = cli.command {
1367 if let RAGAction::List { offset, limit } = action {
1368 assert_eq!(offset, 5);
1369 assert_eq!(limit, 20);
1370 }
1371 }
1372 }
1373 }
1374
1375 #[cfg(feature = "rag")]
1376 #[test]
1377 fn test_rag_delete_command() {
1378 let cli = Cli::try_parse_from(["rustchain", "rag", "delete", "doc1"]);
1379 assert!(cli.is_ok());
1380
1381 if let Ok(cli) = cli {
1382 if let Commands::RAG { action } = cli.command {
1383 if let RAGAction::Delete { id } = action {
1384 assert_eq!(id, "doc1");
1385 }
1386 }
1387 }
1388 }
1389
1390 #[cfg(feature = "rag")]
1391 #[test]
1392 fn test_rag_context_command() {
1393 let cli = Cli::try_parse_from([
1394 "rustchain",
1395 "rag",
1396 "context",
1397 "machine learning",
1398 "--max-length",
1399 "4000",
1400 ]);
1401 assert!(cli.is_ok());
1402
1403 if let Ok(cli) = cli {
1404 if let Commands::RAG { action } = cli.command {
1405 if let RAGAction::Context { query, max_length } = action {
1406 assert_eq!(query, "machine learning");
1407 assert_eq!(max_length, 4000);
1408 }
1409 }
1410 }
1411 }
1412
1413 #[cfg(feature = "sandbox")]
1414 #[test]
1415 fn test_sandbox_create_command() {
1416 let cli = Cli::try_parse_from(["rustchain", "sandbox", "create"]);
1417 assert!(cli.is_ok());
1418
1419 if let Ok(cli) = cli {
1420 if let Commands::Sandbox { action } = cli.command {
1421 assert!(matches!(action, SandboxAction::Create));
1422 }
1423 }
1424 }
1425
1426 #[cfg(feature = "sandbox")]
1427 #[test]
1428 fn test_sandbox_execute_command() {
1429 let cli = Cli::try_parse_from([
1430 "rustchain",
1431 "sandbox",
1432 "execute",
1433 "--session",
1434 "session1",
1435 "ls",
1436 ]);
1437 assert!(cli.is_ok());
1438
1439 if let Ok(cli) = cli {
1440 if let Commands::Sandbox { action } = cli.command {
1441 if let SandboxAction::Execute {
1442 session,
1443 command,
1444 args,
1445 } = action
1446 {
1447 assert_eq!(session, "session1");
1448 assert_eq!(command, "ls");
1449 assert_eq!(args, Vec::<String>::new());
1450 }
1451 }
1452 }
1453 }
1454
1455 #[cfg(feature = "sandbox")]
1456 #[test]
1457 fn test_sandbox_write_command() {
1458 let cli = Cli::try_parse_from([
1459 "rustchain",
1460 "sandbox",
1461 "write",
1462 "--session",
1463 "session1",
1464 "--file",
1465 "test.txt",
1466 "--content",
1467 "Hello World",
1468 ]);
1469 assert!(cli.is_ok());
1470
1471 if let Ok(cli) = cli {
1472 if let Commands::Sandbox { action } = cli.command {
1473 if let SandboxAction::Write {
1474 session,
1475 file,
1476 content,
1477 } = action
1478 {
1479 assert_eq!(session, "session1");
1480 assert_eq!(file, "test.txt");
1481 assert_eq!(content, "Hello World");
1482 }
1483 }
1484 }
1485 }
1486
1487 #[cfg(feature = "server")]
1488 #[test]
1489 fn test_server_start_command() {
1490 let cli = Cli::try_parse_from([
1491 "rustchain",
1492 "server",
1493 "start",
1494 "--host",
1495 "0.0.0.0",
1496 "--port",
1497 "9090",
1498 "--cors",
1499 "--agent-mode",
1500 ]);
1501 assert!(cli.is_ok());
1502
1503 if let Ok(cli) = cli {
1504 if let Commands::Server { action } = cli.command {
1505 if let ServerAction::Start { host, port, cors, agent_mode } = action {
1506 assert_eq!(host, "0.0.0.0");
1507 assert_eq!(port, 9090);
1508 assert!(cors);
1509 assert!(agent_mode);
1510 }
1511 }
1512 }
1513 }
1514
1515 #[cfg(feature = "server")]
1516 #[test]
1517 fn test_server_config_command() {
1518 let cli = Cli::try_parse_from(["rustchain", "server", "config"]);
1519 assert!(cli.is_ok());
1520
1521 if let Ok(cli) = cli {
1522 if let Commands::Server { action } = cli.command {
1523 assert!(matches!(action, ServerAction::Config));
1524 }
1525 }
1526 }
1527
1528 #[test]
1529 fn test_audit_query_command() {
1530 let cli = Cli::try_parse_from([
1531 "rustchain",
1532 "audit",
1533 "query",
1534 "--start-time",
1535 "2024-01-01T00:00:00Z",
1536 "--end-time",
1537 "2024-12-31T23:59:59Z",
1538 "--limit",
1539 "50",
1540 "--offset",
1541 "10",
1542 ]);
1543 assert!(cli.is_ok());
1544
1545 if let Ok(cli) = cli {
1546 if let Commands::Audit { action } = cli.command {
1547 if let AuditAction::Query {
1548 start_time,
1549 end_time,
1550 event_types: _,
1551 limit,
1552 offset,
1553 } = action
1554 {
1555 assert_eq!(start_time, Some("2024-01-01T00:00:00Z".to_string()));
1556 assert_eq!(end_time, Some("2024-12-31T23:59:59Z".to_string()));
1557 assert_eq!(limit, 50);
1558 assert_eq!(offset, 10);
1559 }
1560 }
1561 }
1562 }
1563
1564 #[test]
1565 fn test_audit_report_command() {
1566 let cli = Cli::try_parse_from([
1567 "rustchain",
1568 "audit",
1569 "report",
1570 "--format",
1571 "csv",
1572 "--start-time",
1573 "2024-01-01T00:00:00Z",
1574 ]);
1575 assert!(cli.is_ok());
1576
1577 if let Ok(cli) = cli {
1578 if let Commands::Audit { action } = cli.command {
1579 if let AuditAction::Report {
1580 start_time,
1581 end_time: _,
1582 format,
1583 } = action
1584 {
1585 assert_eq!(start_time, Some("2024-01-01T00:00:00Z".to_string()));
1586 assert_eq!(format, "csv");
1587 }
1588 }
1589 }
1590 }
1591
1592 #[test]
1593 fn test_audit_verify_command() {
1594 let cli = Cli::try_parse_from(["rustchain", "audit", "verify"]);
1595 assert!(cli.is_ok());
1596
1597 if let Ok(cli) = cli {
1598 if let Commands::Audit { action } = cli.command {
1599 assert!(matches!(action, AuditAction::Verify));
1600 }
1601 }
1602 }
1603
1604 #[test]
1605 fn test_audit_export_command() {
1606 let cli = Cli::try_parse_from([
1607 "rustchain",
1608 "audit",
1609 "export",
1610 "--format",
1611 "yaml",
1612 "--output",
1613 "audit.yaml",
1614 ]);
1615 assert!(cli.is_ok());
1616
1617 if let Ok(cli) = cli {
1618 if let Commands::Audit { action } = cli.command {
1619 if let AuditAction::Export { format, output } = action {
1620 assert_eq!(format, "yaml");
1621 assert_eq!(output, Some("audit.yaml".to_string()));
1622 }
1623 }
1624 }
1625 }
1626
1627 #[test]
1628 fn test_audit_stats_command() {
1629 let cli = Cli::try_parse_from(["rustchain", "audit", "stats"]);
1630 assert!(cli.is_ok());
1631
1632 if let Ok(cli) = cli {
1633 if let Commands::Audit { action } = cli.command {
1634 assert!(matches!(action, AuditAction::Stats));
1635 }
1636 }
1637 }
1638
1639 #[test]
1640 fn test_config_commands() {
1641 let commands = [
1642 (["rustchain", "config", "show"], ConfigAction::Show),
1643 (["rustchain", "config", "validate"], ConfigAction::Validate),
1644 (["rustchain", "config", "init"], ConfigAction::Init),
1645 ];
1646
1647 for (args, expected) in commands {
1648 let cli = Cli::try_parse_from(args);
1649 assert!(cli.is_ok(), "Failed to parse: {:?}", args);
1650
1651 if let Ok(cli) = cli {
1652 if let Commands::Config { ref action } = cli.command {
1653 assert!(std::mem::discriminant(action) == std::mem::discriminant(&expected));
1654 }
1655 }
1656 }
1657 }
1658
1659 #[test]
1660 fn test_invalid_commands() {
1661 let invalid_args: &[&[&str]] = &[
1662 &["rustchain", "invalid"],
1663 &["rustchain", "run"], &["rustchain", "mission", "validate"], &["rustchain", "safety", "validate"], ];
1667
1668 for args in invalid_args {
1669 let result = Cli::try_parse_from(*args);
1670 assert!(result.is_err(), "Should have failed to parse: {:?}", args);
1671 }
1672 }
1673
1674 #[test]
1675 fn test_help_generation() {
1676 let result = Cli::try_parse_from(["rustchain", "--help"]);
1677 assert!(result.is_err()); let result = Cli::try_parse_from(["rustchain", "run", "--help"]);
1680 assert!(result.is_err()); }
1682
1683 #[test]
1684 fn test_version_flag() {
1685 let result = Cli::try_parse_from(["rustchain", "--version"]);
1686 assert!(result.is_err()); }
1688}