1#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
14
15pub mod admission;
16pub mod auto_register;
17pub mod autostart;
18pub mod catalog;
19pub mod cli;
20pub mod config;
21pub mod control;
22pub mod daemon_api;
23pub mod daemon_client;
24pub mod daemon_link;
25pub mod daemon_lock;
26pub mod engine;
27pub mod host;
28pub mod http;
29pub mod job_gate;
30pub mod job_log;
31pub mod job_run;
32pub mod lifecycle;
33pub mod loaders;
34pub mod local;
35pub mod local_api;
36pub mod net;
37pub mod residency;
38pub mod runtime;
39pub mod secrets;
40pub mod service;
41pub mod stt_stream;
42pub mod sys;
43pub mod telemetry;
44#[doc(hidden)]
45pub mod test_support;
46pub mod thumbnail;
47pub mod types;
48#[cfg(feature = "ui")]
49pub mod ui;
50pub mod update;
51pub mod ws;
52
53pub const AGENT_VERSION: &str = env!("CARGO_PKG_VERSION");
54
55pub const RELEASE_NAME: &str = concat!(env!("CARGO_PKG_NAME"), "@", env!("CARGO_PKG_VERSION"));
60
61const CLI_TRACE_TARGET: &str = "studio_worker::cli";
64
65fn log_cli_startup(command: &cli::Command) {
71 tracing::info!(
72 target: CLI_TRACE_TARGET,
73 op = "startup",
74 version = AGENT_VERSION,
75 command = command.name(),
76 "studio-worker starting"
77 );
78}
79
80pub async fn run_cli(args: cli::Cli) -> anyhow::Result<()> {
83 log_cli_startup(&args.command);
84 match args.command {
85 cli::Command::Run => runtime::run(args.config.as_deref()).await,
86 cli::Command::Register {
87 api_base_url,
88 reset,
89 } => {
90 runtime::register(
91 args.config.as_deref(),
92 runtime::RegisterArgs {
93 api_base_url,
94 reset,
95 },
96 )
97 .await
98 }
99 cli::Command::Status => runtime::status(args.config.as_deref()).await,
100 cli::Command::Setup => service::setup(args.config.as_deref()),
101 cli::Command::InstallService => service::install(args.config.as_deref()),
102 cli::Command::UninstallService => service::uninstall(),
103 cli::Command::SetThreshold { gb } => runtime::set_threshold(args.config.as_deref(), gb),
104 cli::Command::Config => runtime::show_config(args.config.as_deref()),
105 cli::Command::CheckUpdate => runtime::check_update(args.config.as_deref()).await,
106 cli::Command::Ui => run_ui(args.config.as_deref()).await,
107 }
108}
109
110#[cfg(feature = "ui")]
111async fn run_ui(config_path: Option<&str>) -> anyhow::Result<()> {
112 ui::run(config_path)
113}
114
115#[cfg(not(feature = "ui"))]
116async fn run_ui(_config_path: Option<&str>) -> anyhow::Result<()> {
117 anyhow::bail!(
118 "this build of studio-worker was compiled without the `ui` cargo feature \
119 (it is on by default \u{2014} you built with `--no-default-features`).\n\
120 Reinstall with `cargo install studio-worker` (UI is the default), or use \
121 the desktop installer from the releases page, to enable the native UI."
122 )
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128 use crate::test_support::capture;
129
130 #[test]
131 fn startup_breadcrumb_names_version_and_command() {
132 let logs = capture(|| log_cli_startup(&cli::Command::Run));
133 assert!(logs.contains("INFO"), "expected INFO event, got: {logs}");
134 assert!(
135 logs.contains("studio_worker::cli"),
136 "expected the cli target, got: {logs}"
137 );
138 assert!(
139 logs.contains("op=\"startup\""),
140 "expected op=startup, got: {logs}"
141 );
142 assert!(
143 logs.contains("command=\"run\""),
144 "expected command field, got: {logs}"
145 );
146 assert!(
147 logs.contains(AGENT_VERSION),
148 "expected agent version, got: {logs}"
149 );
150 }
151}