From fce6dee9fb56b86e8205a0c32e358045916221b4 Mon Sep 17 00:00:00 2001 From: AtoMicKraK1n Date: Thu, 26 Mar 2026 22:31:08 +0530 Subject: [PATCH 1/2] feat: add support for NO_DNA --- crates/cli/src/cli/mod.rs | 14 +++++++++++- crates/cli/src/main.rs | 33 +++++++++++++------------- crates/cli/src/no_dna.rs | 42 ++++++++++++++++++++++++++++++++++ crates/cli/src/runbook/mod.rs | 18 +++++++++++---- crates/cli/src/scaffold/mod.rs | 34 +++++++++++++++------------ 5 files changed, 105 insertions(+), 36 deletions(-) create mode 100644 crates/cli/src/no_dna.rs diff --git a/crates/cli/src/cli/mod.rs b/crates/cli/src/cli/mod.rs index 9a1c5d980..2617d1068 100644 --- a/crates/cli/src/cli/mod.rs +++ b/crates/cli/src/cli/mod.rs @@ -104,7 +104,15 @@ impl Context { } #[derive(Parser, Debug)] -#[clap(author, version, about, long_about = None, name = "surfpool", bin_name = "surfpool")] +#[clap( + author, + version, + about, + long_about = "Where you train before surfing Solana\n\nAutomation mode:\nSet NO_DNA=1 to disable interactive prompts and + TUI-oriented UX for agent/CI execution.", + name = "surfpool", + bin_name = "surfpool" +)] struct Opts { #[clap(subcommand)] command: Command, @@ -585,6 +593,10 @@ pub async fn handle_mcp_command(_ctx: &Context) -> Result<(), String> { fn handle_command(opts: Opts, ctx: &Context) -> Result<(), String> { match opts.command { Command::Simnet(mut cmd) => { + if crate::no_dna::is_no_dna() { + cmd.no_tui = true; + } + if cmd.ci { cmd.disable_instruction_profiling = true; cmd.no_studio = true; diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 27ce6ad03..769152d2d 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -1,16 +1,17 @@ -#[macro_use] -mod macros; - -extern crate hiro_system_kit; - -mod cli; -// mod manifest; -mod http; -mod runbook; -mod scaffold; -mod tui; -mod types; - -fn main() { - cli::main(); -} +#[macro_use] + mod macros; + mod no_dna; + + extern crate hiro_system_kit; + + mod cli; + // mod manifest; + mod http; + mod runbook; + mod scaffold; + mod tui; + mod types; + + fn main() { + cli::main(); + } \ No newline at end of file diff --git a/crates/cli/src/no_dna.rs b/crates/cli/src/no_dna.rs new file mode 100644 index 000000000..f7db92384 --- /dev/null +++ b/crates/cli/src/no_dna.rs @@ -0,0 +1,42 @@ +use std::env; + +/// Returns true when NO_DNA requests non-interactive agent mode. +/// Truthy values (case-insensitive) +pub fn is_no_dna() -> bool { + parse_truthy(env::var("NO_DNA").ok().as_deref()) +} + +fn parse_truthy(value: Option<&str>) -> bool { + match value { + Some(v) => { + let v = v.trim().to_ascii_lowercase(); + matches!(v.as_str(), "1" | "true" | "yes" | "on") + } + None => false, + } +} + +#[cfg(test)] +mod tests { + use super::parse_truthy; + + #[test] + fn parse_truthy_values() { + assert!(parse_truthy(Some("1"))); + assert!(parse_truthy(Some("true"))); + assert!(parse_truthy(Some("TRUE"))); + assert!(parse_truthy(Some("yes"))); + assert!(parse_truthy(Some("on"))); + assert!(parse_truthy(Some(" On "))); + } + + #[test] + fn parse_falsey_values() { + assert!(!parse_truthy(None)); + assert!(!parse_truthy(Some("0"))); + assert!(!parse_truthy(Some("fals e"))); + assert!(!parse_truthy(Some("no"))); + assert!(!parse_truthy(Some("off"))); + assert!(!parse_truthy(Some(""))); + } +} diff --git a/crates/cli/src/runbook/mod.rs b/crates/cli/src/runbook/mod.rs index 05ff9cf94..81dba263f 100644 --- a/crates/cli/src/runbook/mod.rs +++ b/crates/cli/src/runbook/mod.rs @@ -309,10 +309,20 @@ pub async fn execute_runbook( ..ColorfulTheme::default() }; - let confirm = Confirm::with_theme(&theme) - .with_prompt("Do you want to continue?") - .interact() - .unwrap(); + let confirm = if crate::no_dna::is_no_dna() { + // non-interactive mode should not block on prompt + // safest behavior: require explicit unsupervised/yes-style intent if available + if cmd.unsupervised { + true + } else { + return Err("NO_DNA=1 disables interactive confirmation. Re-run with non-interactive intent (e.g. --unsupervised or equivalent explicit approval flag).".to_string()); + } + } else { + Confirm::with_theme(&theme) + .with_prompt("Do you want to continue?") + .interact() + .map_err(|e| format!("failed to read confirmation input: {e}"))? + }; if !confirm { return Ok(()); diff --git a/crates/cli/src/scaffold/mod.rs b/crates/cli/src/scaffold/mod.rs index 33dffe4e2..08dd5123b 100644 --- a/crates/cli/src/scaffold/mod.rs +++ b/crates/cli/src/scaffold/mod.rs @@ -223,21 +223,25 @@ pub fn scaffold_iac_layout( let selected_programs = match auto_generate_runbooks { true => programs, false => { - let selection = MultiSelect::with_theme(&theme) - .with_prompt("Select the programs to deploy (all by default):") - .items_checked( - &programs - .iter() - .map(|p| (p.name.as_str(), true)) - .collect::>(), - ) - .interact() - .map_err(|e| format!("unable to select programs to deploy: {e}"))?; - - &selection - .iter() - .map(|i| programs[*i].clone()) - .collect::>() + if crate::no_dna::is_no_dna() { + programs + } else { + let selection = MultiSelect::with_theme(&theme) + .with_prompt("Select the programs to deploy (all by default):") + .items_checked( + &programs + .iter() + .map(|p| (p.name.as_str(), true)) + .collect::>(), + ) + .interact() + .map_err(|e| format!("unable to select programs to deploy: {e}"))?; + + &selection + .iter() + .map(|i| programs[*i].clone()) + .collect::>() + } } }; From d2c4aace40608dbf7f977ca0acabfc32e938780f Mon Sep 17 00:00:00 2001 From: AtoMicKraK1n Date: Fri, 27 Mar 2026 13:00:32 +0530 Subject: [PATCH 2/2] fix: formatted after rebasing --- crates/cli/src/main.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 769152d2d..0cf5a72a0 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -1,17 +1,17 @@ -#[macro_use] - mod macros; - mod no_dna; - - extern crate hiro_system_kit; - - mod cli; - // mod manifest; - mod http; - mod runbook; - mod scaffold; - mod tui; - mod types; - - fn main() { - cli::main(); - } \ No newline at end of file +#[macro_use] +mod macros; +mod no_dna; + +extern crate hiro_system_kit; + +mod cli; +// mod manifest; +mod http; +mod runbook; +mod scaffold; +mod tui; +mod types; + +fn main() { + cli::main(); +}