Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ use clap::Args;

pub use braintrust_sdk_rust::{DEFAULT_API_URL, DEFAULT_APP_URL};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ArgValueSource {
CommandLine,
EnvVariable,
}

#[derive(Debug, Clone, Args)]
pub struct BaseArgs {
/// Output as JSON
#[arg(long, global = true)]
pub json: bool,

/// Suppress non-essential output
#[arg(long, short = 'q', env = "BRAINTRUST_QUIET", global = true, value_parser = clap::builder::BoolishValueParser::new(), default_value_t = false)]
pub quiet: bool,
/// Verbose mode — set at runtime by subcommands that support it
#[arg(skip)]
pub verbose: bool,

/// Disable ANSI color output
#[arg(long, env = "BRAINTRUST_NO_COLOR", global = true, value_parser = clap::builder::BoolishValueParser::new(), default_value_t = false)]
Expand Down Expand Up @@ -40,14 +46,13 @@ pub struct BaseArgs {
#[arg(long, env = "BRAINTRUST_API_KEY", global = true, hide = true)]
pub api_key: Option<String>,

#[arg(skip)]
pub api_key_source: Option<ArgValueSource>,

/// Prefer profile credentials even if BRAINTRUST_API_KEY/--api-key is set.
#[arg(long, global = true)]
pub prefer_profile: bool,

/// Disable all interactive prompts
#[arg(long, global = true)]
pub no_input: bool,

/// Override API URL (or via BRAINTRUST_API_URL)
#[arg(
long,
Expand Down
10 changes: 8 additions & 2 deletions src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,7 @@ async fn run_login_oauth(base: &BaseArgs, args: AuthLoginArgs) -> Result<()> {
Ok(())
}

#[allow(dead_code)]
pub async fn login_interactive(base: &mut BaseArgs) -> Result<String> {
let methods = ["OAuth (browser)", "API key"];
let selected = ui::fuzzy_select("Select login method", &methods, 0)?;
Expand All @@ -790,6 +791,11 @@ pub async fn login_interactive(base: &mut BaseArgs) -> Result<String> {
}
}

pub async fn login_setup_oauth(base: &mut BaseArgs) -> Result<String> {
login_interactive_oauth(base).await
}

#[allow(dead_code)]
async fn login_interactive_api_key(base: &mut BaseArgs) -> Result<String> {
let api_key = prompt_api_key()?;

Expand Down Expand Up @@ -2580,14 +2586,14 @@ mod tests {
fn make_base() -> BaseArgs {
BaseArgs {
json: false,
quiet: false,
verbose: false,
no_color: false,
profile: None,
project: None,
org_name: None,
api_key: None,
api_key_source: None,
prefer_profile: false,
no_input: false,
api_url: None,
app_url: None,
env_file: None,
Expand Down
4 changes: 2 additions & 2 deletions src/functions/push.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3359,14 +3359,14 @@ mod tests {
fn test_base_args() -> BaseArgs {
BaseArgs {
json: false,
quiet: false,
verbose: false,
no_color: false,
profile: None,
org_name: None,
project: None,
api_key: None,
api_key_source: None,
prefer_profile: false,
no_input: false,
api_url: None,
app_url: None,
env_file: None,
Expand Down
56 changes: 43 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use anyhow::Result;
use clap::{Parser, Subcommand};
use clap::{parser::ValueSource, ArgMatches, CommandFactory, FromArgMatches, Parser, Subcommand};
use std::ffi::{OsStr, OsString};

mod args;
Expand Down Expand Up @@ -31,7 +31,7 @@ mod ui;
mod util_cmd;
mod utils;

use crate::args::{BaseArgs, CLIArgs};
use crate::args::{ArgValueSource, BaseArgs, CLIArgs};

const DEFAULT_CANARY_VERSION: &str = concat!(env!("CARGO_PKG_VERSION"), "-canary.dev");
const CLI_VERSION: &str = match option_env!("BT_VERSION_STRING") {
Expand Down Expand Up @@ -80,10 +80,8 @@ Flags
--profile <PROFILE> Use a saved login profile [env: BRAINTRUST_PROFILE]
-o, --org <ORG> Override active org [env: BRAINTRUST_ORG_NAME]
-p, --project <PROJECT> Override active project [env: BRAINTRUST_DEFAULT_PROJECT]
-q, --quiet Suppress non-essential output
--json Output as JSON
--no-color Disable ANSI color output
--no-input Disable all interactive prompts
--api-url <URL> Override API URL [env: BRAINTRUST_API_URL]
--app-url <URL> Override app URL [env: BRAINTRUST_APP_URL]
--env-file <PATH> Path to a .env file to load
Expand Down Expand Up @@ -178,6 +176,30 @@ impl Commands {
Commands::Status(cmd) => &cmd.base,
}
}

fn base_mut(&mut self) -> &mut BaseArgs {
match self {
Commands::Init(cmd) => &mut cmd.base,
Commands::Setup(cmd) => &mut cmd.base,
Commands::Docs(cmd) => &mut cmd.base,
Commands::Sql(cmd) => &mut cmd.base,
Commands::Auth(cmd) => &mut cmd.base,
Commands::View(cmd) => &mut cmd.base,
#[cfg(unix)]
Commands::Eval(cmd) => &mut cmd.base,
Commands::Projects(cmd) => &mut cmd.base,
Commands::Prompts(cmd) => &mut cmd.base,
Commands::SelfCommand(cmd) => &mut cmd.base,
Commands::Tools(cmd) => &mut cmd.base,
Commands::Scorers(cmd) => &mut cmd.base,
Commands::Functions(cmd) => &mut cmd.base,
Commands::Experiments(cmd) => &mut cmd.base,
Commands::Sync(cmd) => &mut cmd.base,
Commands::Util(cmd) => &mut cmd.base,
Commands::Switch(cmd) => &mut cmd.base,
Commands::Status(cmd) => &mut cmd.base,
}
}
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
Expand Down Expand Up @@ -207,7 +229,9 @@ async fn try_main() -> Result<()> {
let argv: Vec<OsString> = std::env::args_os().collect();
env::bootstrap_from_args(&argv)?;

let cli = Cli::parse_from(argv);
let matches = Cli::command().get_matches_from(&argv);
let mut cli = Cli::from_arg_matches(&matches).expect("clap matches should parse");
apply_base_arg_sources(&matches, cli.command.base_mut());
configure_output(cli.command.base());

match cli.command {
Expand Down Expand Up @@ -235,6 +259,18 @@ async fn try_main() -> Result<()> {
Ok(())
}

fn apply_base_arg_sources(matches: &ArgMatches, base: &mut BaseArgs) {
base.api_key_source = matches.value_source("api_key").and_then(map_value_source);
}

fn map_value_source(source: ValueSource) -> Option<ArgValueSource> {
match source {
ValueSource::CommandLine => Some(ArgValueSource::CommandLine),
ValueSource::EnvVariable => Some(ArgValueSource::EnvVariable),
_ => None,
}
}

fn configure_output(base: &BaseArgs) {
let mut disable_color = base.no_color || std::env::var_os("NO_COLOR").is_some();

Expand All @@ -249,14 +285,8 @@ fn configure_output(base: &BaseArgs) {
ui::set_animations_enabled(false);
}

if base.quiet {
ui::set_quiet(true);
ui::set_animations_enabled(false);
}

if base.no_input {
ui::set_no_input(true);
}
ui::set_quiet(true);
ui::set_animations_enabled(false);

if disable_color {
dialoguer::console::set_colors_enabled(false);
Expand Down
Loading
Loading