diff --git a/lib/crates/fabro-cli/src/commands/exec.rs b/lib/crates/fabro-cli/src/commands/exec.rs index 4048915e5..c8b218daf 100644 --- a/lib/crates/fabro-cli/src/commands/exec.rs +++ b/lib/crates/fabro-cli/src/commands/exec.rs @@ -13,15 +13,15 @@ use fabro_llm::types::{ FinishReason, Message, Request, Response as LlmResponse, StreamEvent, TokenCounts, }; use fabro_mcp::config::{McpServerSettings, McpTransport}; +use fabro_types::settings::InterpString; use fabro_types::settings::cli::OutputFormat as SettingsOutputFormat; use fabro_types::settings::run::McpEntryLayer; -use fabro_types::settings::{CliNamespace, InterpString}; use fabro_util::exit::{ErrorExt, ExitClass}; -use fabro_util::printer::Printer; use futures::stream; use serde::Deserialize; use crate::args::ExecArgs; +use crate::command_context::CommandContext; use crate::{server_client, user_config}; fn runtime_mcp_server(name: &str, entry: &McpEntryLayer) -> McpServerSettings { @@ -356,14 +356,11 @@ impl ProviderAdapter for AuthenticatedFabroServerAdapter { } } -pub(crate) async fn execute( - mut args: ExecArgs, - cli: &CliNamespace, - _printer: Printer, -) -> AnyResult<()> { +pub(crate) async fn execute(mut args: ExecArgs, ctx: &CommandContext) -> AnyResult<()> { use fabro_agent::cli::PermissionLevel as AgentPermissionLevel; use fabro_types::settings::run::AgentPermissions; + let cli = &ctx.user_settings().cli; let raw_settings = user_config::load_settings()?; #[cfg(feature = "sleep_inhibitor")] let _sleep_guard = crate::sleep_inhibitor::guard(cli.exec.prevent_idle_sleep); diff --git a/lib/crates/fabro-cli/src/commands/parse.rs b/lib/crates/fabro-cli/src/commands/parse.rs index e14d970ce..12088ca04 100644 --- a/lib/crates/fabro-cli/src/commands/parse.rs +++ b/lib/crates/fabro-cli/src/commands/parse.rs @@ -11,13 +11,11 @@ use std::io::Write; use fabro_config::project::resolve_workflow; use fabro_graphviz::parser::parse_ast; -use fabro_types::settings::CliNamespace; -use fabro_util::printer::Printer; use crate::args::ParseArgs; use crate::shared::read_workflow_file; -pub(crate) fn run(args: &ParseArgs, _cli: &CliNamespace, _printer: Printer) -> anyhow::Result<()> { +pub(crate) fn run(args: &ParseArgs) -> anyhow::Result<()> { let stdout = std::io::stdout(); run_to(args, stdout.lock()) } diff --git a/lib/crates/fabro-cli/src/commands/uninstall.rs b/lib/crates/fabro-cli/src/commands/uninstall.rs index 5d19aa459..63b5fd67d 100644 --- a/lib/crates/fabro-cli/src/commands/uninstall.rs +++ b/lib/crates/fabro-cli/src/commands/uninstall.rs @@ -15,14 +15,13 @@ use std::time::Duration; use anyhow::{Context, Result}; use fabro_config::Storage; use fabro_config::daemon::ServerDaemon; -use fabro_types::settings::CliNamespace; -use fabro_types::settings::cli::OutputFormat; use fabro_util::Home; use fabro_util::printer::Printer; use serde::Serialize; use tracing::warn; use crate::args::UninstallArgs; +use crate::command_context::CommandContext; use crate::commands::server::stop; use crate::shared::{format_size, print_json_pretty, tilde_path}; use crate::{local_server, user_config}; @@ -43,12 +42,9 @@ struct Inventory { clippy::unused_async, reason = "The shared command dispatch path expects an async handler." )] -pub(crate) async fn run_uninstall( - args: &UninstallArgs, - cli: &CliNamespace, - printer: Printer, -) -> Result<()> { - let json = cli.output.format == OutputFormat::Json; +pub(crate) async fn run_uninstall(args: &UninstallArgs, ctx: &CommandContext) -> Result<()> { + let json = ctx.json_output(); + let printer = ctx.printer(); let home = Home::from_env(); let home_root = home.root().to_path_buf(); diff --git a/lib/crates/fabro-cli/src/commands/upgrade.rs b/lib/crates/fabro-cli/src/commands/upgrade.rs index 53390cfd5..694ac7838 100644 --- a/lib/crates/fabro-cli/src/commands/upgrade.rs +++ b/lib/crates/fabro-cli/src/commands/upgrade.rs @@ -23,6 +23,7 @@ use tokio::task::JoinHandle; use tracing::debug; use crate::args::UpgradeArgs; +use crate::command_context::CommandContext; use crate::shared::print_json_pretty; // ── Download backend abstraction ─────────────────────────────────────────── @@ -434,11 +435,9 @@ impl UpgradeCheckState { // ── Main upgrade command ─────────────────────────────────────────────────── -pub(crate) async fn run_upgrade( - args: UpgradeArgs, - cli: &CliNamespace, - printer: Printer, -) -> Result<()> { +pub(crate) async fn run_upgrade(args: UpgradeArgs, ctx: &CommandContext) -> Result<()> { + let cli = &ctx.user_settings().cli; + let printer = ctx.printer(); let current_exe = std::env::current_exe() .context("resolving current fabro executable path")? .canonicalize() diff --git a/lib/crates/fabro-cli/src/commands/workflow/create.rs b/lib/crates/fabro-cli/src/commands/workflow/create.rs index 6a4f7b5f8..742c3cad5 100644 --- a/lib/crates/fabro-cli/src/commands/workflow/create.rs +++ b/lib/crates/fabro-cli/src/commands/workflow/create.rs @@ -7,18 +7,13 @@ use std::path::Path; use anyhow::{Context, Result, bail}; use fabro_config::project::{discover_project_config, resolve_fabro_root}; -use fabro_types::settings::CliNamespace; -use fabro_types::settings::cli::OutputFormat; -use fabro_util::printer::Printer; use crate::args::WorkflowCreateArgs; +use crate::command_context::CommandContext; use crate::shared::{print_json_pretty, relative_path}; -pub(super) fn create_command( - args: &WorkflowCreateArgs, - cli: &CliNamespace, - printer: Printer, -) -> Result<()> { +pub(super) fn create_command(args: &WorkflowCreateArgs, base_ctx: &CommandContext) -> Result<()> { + let printer = base_ctx.printer(); let cwd = std::env::current_dir()?; let Some((config_path, config)) = discover_project_config(&cwd)? else { @@ -31,7 +26,7 @@ pub(super) fn create_command( let fabro_root = resolve_fabro_root(&config_path, &config); let created = write_workflow_scaffold(args, &fabro_root)?; - if cli.output.format == OutputFormat::Json { + if base_ctx.json_output() { let created: Vec<_> = created.iter().map(|path| relative_path(path)).collect(); print_json_pretty(&serde_json::json!({ "name": args.name, diff --git a/lib/crates/fabro-cli/src/commands/workflow/list.rs b/lib/crates/fabro-cli/src/commands/workflow/list.rs index 40da91203..96553af73 100644 --- a/lib/crates/fabro-cli/src/commands/workflow/list.rs +++ b/lib/crates/fabro-cli/src/commands/workflow/list.rs @@ -5,21 +5,17 @@ use fabro_config::project::{ WorkflowInfo, WorkflowSource, discover_project_config, list_workflows_detailed, resolve_fabro_root, }; -use fabro_types::settings::CliNamespace; -use fabro_types::settings::cli::OutputFormat; use fabro_util::printer::Printer; use fabro_util::terminal::Styles; use crate::args::WorkflowListArgs; +use crate::command_context::CommandContext; use crate::shared::{color_if, print_json_pretty, relative_path}; const GOAL_MAX_LEN: usize = 60; -pub(super) fn list_command( - _args: &WorkflowListArgs, - cli: &CliNamespace, - printer: Printer, -) -> Result<()> { +pub(super) fn list_command(_args: &WorkflowListArgs, base_ctx: &CommandContext) -> Result<()> { + let printer = base_ctx.printer(); let styles = Styles::detect_stderr(); let cwd = std::env::current_dir()?; @@ -36,7 +32,7 @@ pub(super) fn list_command( let workflows = list_workflows_detailed(Some(&project_wf_dir), user_wf_dir.as_deref()); - if cli.output.format == OutputFormat::Json { + if base_ctx.json_output() { print_json_pretty(&workflows)?; return Ok(()); } diff --git a/lib/crates/fabro-cli/src/commands/workflow/mod.rs b/lib/crates/fabro-cli/src/commands/workflow/mod.rs index 44de6cf4e..528dc8a35 100644 --- a/lib/crates/fabro-cli/src/commands/workflow/mod.rs +++ b/lib/crates/fabro-cli/src/commands/workflow/mod.rs @@ -2,14 +2,13 @@ mod create; mod list; use anyhow::Result; -use fabro_types::settings::CliNamespace; -use fabro_util::printer::Printer; use crate::args::{WorkflowCommand, WorkflowNamespace}; +use crate::command_context::CommandContext; -pub(crate) fn dispatch(ns: WorkflowNamespace, cli: &CliNamespace, printer: Printer) -> Result<()> { +pub(crate) fn dispatch(ns: WorkflowNamespace, base_ctx: &CommandContext) -> Result<()> { match ns.command { - WorkflowCommand::List(args) => list::list_command(&args, cli, printer), - WorkflowCommand::Create(args) => create::create_command(&args, cli, printer), + WorkflowCommand::List(args) => list::list_command(&args, base_ctx), + WorkflowCommand::Create(args) => create::create_command(&args, base_ctx), } } diff --git a/lib/crates/fabro-cli/src/main.rs b/lib/crates/fabro-cli/src/main.rs index 51b203439..3f559e7b3 100644 --- a/lib/crates/fabro-cli/src/main.rs +++ b/lib/crates/fabro-cli/src/main.rs @@ -208,7 +208,10 @@ async fn main_inner() -> (String, Result<()>) { let build_base_ctx = || resolved_base.to_context(); match *command { - Commands::Exec(args) => commands::exec::execute(args, cli_settings, printer).await?, + Commands::Exec(args) => { + let base_ctx = build_base_ctx()?; + commands::exec::execute(args, &base_ctx).await?; + } Commands::RunCmd(cmd) => { let base_ctx = build_base_ctx()?; Box::pin(commands::run::dispatch(cmd, &base_ctx)).await?; @@ -228,7 +231,7 @@ async fn main_inner() -> (String, Result<()>) { commands::graph::run(&args, &styles, &base_ctx).await?; } Commands::Parse(args) => { - commands::parse::run(&args, cli_settings, printer)?; + commands::parse::run(&args)?; } Commands::Artifact(ns) => { let base_ctx = build_base_ctx()?; @@ -298,7 +301,8 @@ async fn main_inner() -> (String, Result<()>) { .await?; } Commands::Uninstall(args) => { - commands::uninstall::run_uninstall(&args, cli_settings, printer).await?; + let base_ctx = build_base_ctx()?; + commands::uninstall::run_uninstall(&args, &base_ctx).await?; } Commands::Auth(ns) => { let base_ctx = build_base_ctx()?; @@ -316,9 +320,13 @@ async fn main_inner() -> (String, Result<()>) { let base_ctx = build_base_ctx()?; Box::pin(commands::config::execute(&args, &base_ctx)).await?; } - Commands::Workflow(ns) => commands::workflow::dispatch(ns, cli_settings, printer)?, + Commands::Workflow(ns) => { + let base_ctx = build_base_ctx()?; + commands::workflow::dispatch(ns, &base_ctx)?; + } Commands::Upgrade(args) => { - commands::upgrade::run_upgrade(args, cli_settings, printer).await?; + let base_ctx = build_base_ctx()?; + commands::upgrade::run_upgrade(args, &base_ctx).await?; } Commands::Provider(ns) => { let base_ctx = build_base_ctx()?;