Skip to main content

asimov_cli/commands/
module.rs

1// This is free and unencumbered software released into the public domain.
2
3use crate::BoxError;
4use asimov_module::ModuleName;
5use clientele::{StandardOptions, SysexitsError::*, crates::clap::Subcommand};
6use color_print::ceprintln;
7use std::{string::String, vec::Vec};
8
9#[derive(Debug, Subcommand)]
10pub enum ModuleCommand {
11    /// Open the module's package page in a web browser
12    #[clap(alias = "open")]
13    Browse {
14        /// The name of the module to browse
15        name: ModuleName,
16    },
17
18    /// Show or change an installed module's configuration
19    #[clap(args_conflicts_with_subcommands = true)]
20    Config {
21        #[clap(subcommand)]
22        command: Option<ConfigCommand>,
23
24        /// The name of the module whose configuration to show
25        name: Option<ModuleName>,
26    },
27
28    /// Disable modules
29    Disable {
30        /// The names of the modules to disable
31        names: Vec<ModuleName>,
32    },
33
34    /// Print an installed module's documentation
35    #[clap(alias = "readme")]
36    Doc {
37        /// The name of the module whose documentation to print
38        name: ModuleName,
39    },
40
41    /// Enable modules
42    Enable {
43        /// The names of the modules to enable
44        names: Vec<ModuleName>,
45    },
46
47    /// TBD
48    #[cfg(feature = "unstable")]
49    #[clap(alias = "which")]
50    Find {
51        /// The name of the module to find
52        name: ModuleName,
53    },
54
55    /// Inspect a module's manifest, state, and configuration status
56    #[clap(alias = "show")]
57    Inspect {
58        /// The name of the module to inspect
59        name: ModuleName,
60
61        /// Set the output format [default: cli] [possible values: cli, json]
62        #[arg(value_name = "FORMAT", short = 'o', long)]
63        output: Option<String>,
64    },
65
66    /// Install an available module locally
67    Install {
68        /// The names of the modules to install
69        names: Vec<ModuleName>,
70
71        /// Optionally install a specific version instead of latest
72        #[arg(long)]
73        version: Option<String>,
74
75        /// Optionally specify desired model size to download for module.
76        /// Only affects modules which require models.
77        #[arg(long)]
78        model_size: Option<String>,
79    },
80
81    /// Print the module's package link
82    #[clap(alias = "url")]
83    Link {
84        /// The name of the module to link to
85        name: ModuleName,
86    },
87
88    /// List installed modules
89    #[clap(alias = "ls")]
90    List {
91        /// Set the output format [default: cli] [possible values: cli, jsonl]
92        #[arg(value_name = "FORMAT", short = 'o', long)]
93        output: Option<String>,
94    },
95
96    /// Resolve a given URL to modules which can handle it
97    Resolve {
98        /// The URL to resolve
99        url: String,
100    },
101
102    /// Search the index of available modules
103    Search {
104        /// The terms to search for, all of which must match
105        #[clap(required = true)]
106        query: Vec<String>,
107
108        /// Set the output format [default: cli] [possible values: cli, jsonl]
109        #[arg(value_name = "FORMAT", short = 'o', long)]
110        output: Option<String>,
111    },
112
113    /// Uninstall a currently installed module
114    Uninstall {
115        /// The names of the modules to uninstall
116        names: Vec<ModuleName>,
117    },
118
119    /// Upgrade currently installed modules
120    ///
121    /// By default upgrades all installed modules.
122    #[clap(alias = "update")]
123    Upgrade {
124        /// The names of the modules to upgrade
125        names: Vec<ModuleName>,
126
127        /// Optionally upgrade to a specific version instead of latest
128        #[arg(long)]
129        version: Option<String>,
130
131        /// Optionally specify desired model size to download for module.
132        /// Only affects modules which require models.
133        #[arg(long)]
134        model_size: Option<String>,
135    },
136}
137
138impl ModuleCommand {
139    pub async fn run(self, flags: &StandardOptions) -> Result<(), BoxError> {
140        use ModuleCommand::*;
141        match self {
142            Browse { name } => browse(name, flags).await,
143
144            Config { command, name } => match (command, name) {
145                (Some(command), _) => command.run(flags).await,
146                // a bare module name lists its configuration
147                (None, Some(name)) => {
148                    ConfigCommand::Show {
149                        name: name.clone(),
150                        output: None,
151                    }
152                    .run(flags)
153                    .await
154                },
155                (None, None) => {
156                    ceprintln!("<s,r>error:</> missing module name or subcommand");
157                    ceprintln!(
158                        "<s,dim>hint:</> See the available subcommands with: <s>asimov module config --help</>"
159                    );
160                    Err(EX_USAGE.into())
161                },
162            },
163
164            Disable { names } => disable(names, flags).await,
165
166            Doc { name } => doc(name, flags).await,
167
168            Enable { names } => enable(names, flags).await,
169
170            #[cfg(feature = "unstable")]
171            Find { name } => find(name, flags).await,
172
173            Inspect { name, output } => {
174                inspect(name, output.as_deref().unwrap_or("cli").into(), flags).await
175            },
176
177            Install {
178                names,
179                version,
180                model_size,
181            } => install(names, version, model_size, flags).await,
182
183            Link { name } => link(name, flags).await,
184
185            List { output } => list(output.as_deref().unwrap_or("cli").into(), flags).await,
186
187            Resolve { url } => resolve(url, flags).await,
188
189            Search { query, output } => {
190                search(query, output.as_deref().unwrap_or("cli").into(), flags).await
191            },
192
193            Uninstall { names } => uninstall(names, flags).await,
194
195            Upgrade {
196                names,
197                version,
198                model_size,
199            } => upgrade(names, version, model_size, flags).await,
200        }
201    }
202}
203
204mod browse;
205pub use browse::*;
206
207mod config;
208pub use config::*;
209
210mod disable;
211pub use disable::*;
212
213mod doc;
214pub use doc::*;
215
216mod enable;
217pub use enable::*;
218
219mod find;
220pub use find::*;
221
222mod inspect;
223pub use inspect::*;
224
225mod install;
226pub use install::*;
227
228mod link;
229pub use link::*;
230
231mod list;
232pub use list::*;
233
234mod resolve;
235pub use resolve::*;
236
237mod search;
238pub use search::*;
239
240mod uninstall;
241pub use uninstall::*;
242
243mod upgrade;
244pub use upgrade::*;