use anyhow::Result;
use theway_core::ThinkingLevel;
mod controller_storage;
mod host_assembly;
mod process_state;
mod serve;
mod session_assembly;
mod settings;
use host_assembly::build_turn_host;
use process_state::ProcessRuntime;
use serve::{port_file_listener, serve_transport};
#[allow(unused_imports)]
pub(crate) use controller_storage::{
canonical_work_dir, monitor_controller_storage, supervise_controller_storage,
};
#[allow(unused_imports)]
pub(crate) use settings::{provision_model_catalog, resolve_startup_model};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DaemonTransport {
Grpc,
Http,
Mcp,
}
impl DaemonTransport {
fn label(self) -> &'static str {
match self {
DaemonTransport::Grpc => "grpc",
DaemonTransport::Http => "http",
DaemonTransport::Mcp => "mcp",
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum SessionSelection {
New,
Latest,
Id(String),
}
pub struct DaemonOptions {
pub paths: crate::DaemonPaths,
pub transport: DaemonTransport,
pub host: String,
pub port: u16,
pub provider: Option<String>,
pub model: Option<String>,
pub base_url: Option<String>,
pub thinking: ThinkingLevel,
pub session: SessionSelection,
pub approve_control_plane: bool,
pub debug: bool,
pub trigger_poll_secs: Option<u64>,
pub builtin_skills: Vec<String>,
pub storage_service_addr: Option<String>,
pub executor_kind: Option<String>,
pub no_tgrep: bool,
pub api_key: Option<String>,
pub auto_fetch_models: bool,
}
pub async fn run(options: DaemonOptions) -> Result<()> {
let mode = options.transport;
let mut process = ProcessRuntime::start(&options).await?;
let host = build_turn_host(&mut process, &options).await?;
let mode_label = mode.label();
tracing::info!(
"thewayd starting in {mode_label} mode on {}:{}",
options.host,
options.port
);
let port_file = theway_transport::client::port_file_path(&process.cwd);
let daemon_pid = std::process::id();
let on_listen = port_file_listener(port_file.clone(), daemon_pid);
let result = serve_transport(mode, &options, host, &process.cwd, &port_file, on_listen).await;
process.shutdown(result, daemon_pid).await
}
#[cfg(test)]
tests_bridge_macro::tests_bridge!("orchestration/startup");