use std::process::ExitCode;
use anyhow::Result;
use crate::commands;
use crate::host_adapter;
use crate::mcp;
use crate::output::{self, OutputFormat};
use crate::paths;
pub(crate) fn host(command: crate::HostCommand, format: OutputFormat) -> Result<ExitCode> {
match command {
crate::HostCommand::Apply(args) => {
let repo_path = paths::cli::resolve(&args.path)?;
let report = commands::host::apply(
&repo_path,
args.profile.as_deref(),
args.host.map(crate::RepoHostArg::into_host),
args.force,
args.with_launcher,
)?;
output::render_report(format, &report)
}
}
}
pub(crate) fn host_hook(args: crate::HostHookRunArgs, format: OutputFormat) -> Result<ExitCode> {
let repo_path = paths::cli::resolve(&args.path)?;
let profile_name = crate::profile::resolve(args.profile.as_deref())?;
let host = crate::resolve_host_adapter_name(args.host.clone())?;
let hook = args.hook.as_str();
let hook_protocol_hook = if format == OutputFormat::HookProtocol {
if host != "claude" {
anyhow::bail!(
"--output hook-protocol is only implemented for --host claude; host `{host}` is not supported in v1"
);
}
let cli_hook = hook.replace('_', "-");
commands::host::claude_event_for_hook(&cli_hook)?;
Some(cli_hook)
} else {
None
};
let runtime_hints = crate::host_hook_runtime_hints(&args);
let session_start = crate::host_hook_session_start_options(&args);
let capture = crate::build_host_hook_capture(&args, &host, &runtime_hints)?;
let report = host_adapter::run_hook(
&repo_path,
profile_name.as_str(),
&host,
hook,
session_start,
args.diagnostics,
args.host_total_context_chars,
args.attempt_outcome
.map(crate::AttemptOutcomeArg::into_state_outcome),
capture,
args.protected_write.into_state_options(),
runtime_hints,
)?;
if let Some(cli_hook) = hook_protocol_hook {
let payload = commands::host::build_hook_protocol_payload(
&cli_hook,
commands::host::HookProtocolInputs {
context: report.context(),
session_boundary_action: report.session_boundary_action(),
},
)?;
println!("{}", serde_json::to_string_pretty(&payload)?);
return Ok(ExitCode::SUCCESS);
}
output::render_report(format, &report)
}
pub(crate) fn telemetry(
command: crate::TelemetryCommand,
format: OutputFormat,
) -> Result<ExitCode> {
match command {
crate::TelemetryCommand::Report(args) => {
let repo_path = paths::cli::resolve(&args.path)?;
let report =
commands::telemetry::run_report(&repo_path, args.profile.as_deref(), args.limit)?;
output::render_report(format, &report)
}
}
}
pub(crate) fn mcp_serve() -> Result<ExitCode> {
mcp::serve()?;
Ok(ExitCode::SUCCESS)
}
#[cfg(feature = "daemon")]
pub(crate) fn daemon(args: crate::DaemonArgs) -> Result<ExitCode> {
let rt = tokio::runtime::Runtime::new()
.map_err(|e| anyhow::anyhow!("failed to create tokio runtime: {e}"))?;
rt.block_on(mcp::daemon::serve(
&args.host,
args.port,
args.profile,
args.cors,
))?;
Ok(ExitCode::SUCCESS)
}