1mod commands;
2mod normalization;
3mod runtime_surface_help;
4mod validation;
5
6pub use commands::{
7 AuthCommand, BinaryFlavor, Cli, Command, ConfigCommand, DiscoveryScope, DoctorCommand,
8 GpuCommand, MeshDiscoveryMode, MeshGuardrailCliMode, PluginCommand, SkillAgentArg,
9 SkillCommand, TrustCommand, TrustPolicy,
10};
11pub use normalization::{
12 NormalizedRuntimeArgs, RuntimeSurface, legacy_runtime_surface_warning,
13 normalize_runtime_surface_args,
14};
15pub use runtime_surface_help::runtime_surface_help;
16pub use validation::validate_discovery_mode_args;
17
18#[cfg(test)]
19mod setup_tests;
20
21#[cfg(test)]
22mod uninstall_tests;
23
24#[cfg(test)]
25use std::path::PathBuf;
26
27#[cfg(test)]
28use clap::Parser;
29
30#[cfg(test)]
31use crate::runtime::RuntimeCommand;
32
33#[cfg(test)]
34pub fn assert_mesh_requirements_docs_examples_parse() {
35 let unrestricted_args =
36 normalize_runtime_surface_args(["mesh-llm", "serve", "--model", "Qwen3-8B-Q4_K_M"]);
37 let unrestricted = Cli::parse_from(unrestricted_args.normalized.clone());
38 assert!(unrestricted.command.is_none());
39 assert_eq!(unrestricted.model, vec![PathBuf::from("Qwen3-8B-Q4_K_M")]);
40 assert!(!unrestricted.publish);
41
42 let signed_public_args = normalize_runtime_surface_args([
43 "mesh-llm",
44 "serve",
45 "--model",
46 "Qwen3-8B-Q4_K_M",
47 "--publish",
48 "--require-release-attestation",
49 "--release-signer-key",
50 "ed25519:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
51 "--owner-key",
52 "~/.mesh-llm/owner-keystore.json",
53 "--owner-required",
54 "--trust-policy",
55 "require-owned",
56 "--node-label",
57 "lab-a",
58 ]);
59 let signed_public = Cli::parse_from(signed_public_args.normalized.clone());
60 assert!(signed_public.command.is_none());
61 assert_eq!(signed_public.model, vec![PathBuf::from("Qwen3-8B-Q4_K_M")]);
62 assert!(signed_public.publish);
63 assert!(signed_public.require_release_attestation);
64 assert_eq!(
65 signed_public.release_signer_key,
66 vec![
67 "ed25519:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef".to_string()
68 ]
69 );
70 assert_eq!(
71 signed_public.owner_key,
72 Some(PathBuf::from("~/.mesh-llm/owner-keystore.json"))
73 );
74 assert!(signed_public.owner_required);
75 assert_eq!(signed_public.trust_policy, Some(TrustPolicy::RequireOwned));
76 assert_eq!(signed_public.node_label, Some("lab-a".to_string()));
77
78 let signed_bootstrap_args =
79 normalize_runtime_surface_args(["mesh-llm", "serve", "--join", "signed-bootstrap-token"]);
80 let signed_bootstrap = Cli::parse_from(signed_bootstrap_args.normalized.clone());
81 assert!(signed_bootstrap.command.is_none());
82 assert_eq!(
83 signed_bootstrap.join,
84 vec!["signed-bootstrap-token".to_string()]
85 );
86
87 let runtime_bootstrap = Cli::parse_from(["mesh-llm", "runtime", "bootstrap", "--port", "3131"]);
88 match runtime_bootstrap.command.expect("runtime command expected") {
89 Command::Runtime {
90 command: Some(RuntimeCommand::Bootstrap { port, json }),
91 } => {
92 assert_eq!(port, 3131);
93 assert!(!json);
94 }
95 other => panic!("unexpected command: {other:?}"),
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::{Cli, Command};
102 use crate::models::ModelsCommand;
103 use clap::Parser;
104
105 #[test]
106 fn mesh_requirements_docs_examples_parse() {
107 super::assert_mesh_requirements_docs_examples_parse();
108 }
109
110 #[test]
111 fn split_topology_lock_requires_split_mode() {
112 let error = Cli::try_parse_from([
113 "mesh-llm",
114 "--model",
115 "model.gguf",
116 "--split-topology-lock",
117 "topology.json",
118 ])
119 .expect_err("topology lock without --split should fail");
120
121 assert!(error.to_string().contains("--split"));
122 }
123
124 #[test]
125 fn split_topology_lock_parses_with_split_mode() {
126 let cli = Cli::try_parse_from([
127 "mesh-llm",
128 "--model",
129 "model.gguf",
130 "--split",
131 "--split-topology-lock",
132 "topology.json",
133 ])
134 .expect("locked split CLI should parse");
135
136 assert!(cli.split);
137 assert_eq!(
138 cli.split_topology_lock,
139 Some(std::path::PathBuf::from("topology.json"))
140 );
141 }
142
143 #[test]
144 fn models_package_parses_experimental_publication() {
145 let cli = Cli::parse_from([
146 "mesh-llm",
147 "models",
148 "package",
149 "unsloth/inkling-GGUF:UD-Q2_K_XL",
150 "--experimental",
151 "--dry-run",
152 ]);
153
154 match cli.command.expect("models command expected") {
155 Command::Models {
156 command:
157 ModelsCommand::Package {
158 source_repo: Some(source_repo),
159 experimental: true,
160 dry_run: true,
161 ..
162 },
163 } => assert_eq!(source_repo, "unsloth/inkling-GGUF:UD-Q2_K_XL"),
164 other => panic!("unexpected command: {other:?}"),
165 }
166 }
167}