[config] Onboarding flow with persistence (#1929)
## Summary In collaboration with @gpeal: upgrade the onboarding flow, and persist user settings. --------- Co-authored-by: Gabriel Peal <gabriel@openai.com>
This commit is contained in:
@@ -6,8 +6,12 @@ use app::App;
|
||||
use codex_core::BUILT_IN_OSS_MODEL_PROVIDER_ID;
|
||||
use codex_core::config::Config;
|
||||
use codex_core::config::ConfigOverrides;
|
||||
use codex_core::config::ConfigToml;
|
||||
use codex_core::config::find_codex_home;
|
||||
use codex_core::config::load_config_as_toml_with_cli_overrides;
|
||||
use codex_core::config_types::SandboxMode;
|
||||
use codex_core::protocol::AskForApproval;
|
||||
use codex_core::protocol::SandboxPolicy;
|
||||
use codex_login::load_auth;
|
||||
use codex_ollama::DEFAULT_OSS_MODEL;
|
||||
use log_layer::TuiLogLayer;
|
||||
@@ -89,33 +93,38 @@ pub async fn run_main(
|
||||
None
|
||||
};
|
||||
|
||||
let config = {
|
||||
// canonicalize the cwd
|
||||
let cwd = cli.cwd.clone().map(|p| p.canonicalize().unwrap_or(p));
|
||||
|
||||
let overrides = ConfigOverrides {
|
||||
model,
|
||||
approval_policy,
|
||||
sandbox_mode,
|
||||
cwd,
|
||||
model_provider: model_provider_override,
|
||||
config_profile: cli.config_profile.clone(),
|
||||
codex_linux_sandbox_exe,
|
||||
base_instructions: None,
|
||||
include_plan_tool: Some(true),
|
||||
disable_response_storage: cli.oss.then_some(true),
|
||||
show_raw_agent_reasoning: cli.oss.then_some(true),
|
||||
};
|
||||
|
||||
// Parse `-c` overrides from the CLI.
|
||||
let cli_kv_overrides = match cli.config_overrides.parse_overrides() {
|
||||
Ok(v) => v,
|
||||
#[allow(clippy::print_stderr)]
|
||||
Err(e) => {
|
||||
eprintln!("Error parsing -c overrides: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let mut config = {
|
||||
// Load configuration and support CLI overrides.
|
||||
let overrides = ConfigOverrides {
|
||||
model,
|
||||
approval_policy,
|
||||
sandbox_mode,
|
||||
cwd: cli.cwd.clone().map(|p| p.canonicalize().unwrap_or(p)),
|
||||
model_provider: model_provider_override,
|
||||
config_profile: cli.config_profile.clone(),
|
||||
codex_linux_sandbox_exe,
|
||||
base_instructions: None,
|
||||
include_plan_tool: Some(true),
|
||||
disable_response_storage: cli.oss.then_some(true),
|
||||
show_raw_agent_reasoning: cli.oss.then_some(true),
|
||||
};
|
||||
// Parse `-c` overrides from the CLI.
|
||||
let cli_kv_overrides = match cli.config_overrides.parse_overrides() {
|
||||
Ok(v) => v,
|
||||
#[allow(clippy::print_stderr)]
|
||||
Err(e) => {
|
||||
eprintln!("Error parsing -c overrides: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
#[allow(clippy::print_stderr)]
|
||||
match Config::load_with_cli_overrides(cli_kv_overrides, overrides) {
|
||||
match Config::load_with_cli_overrides(cli_kv_overrides.clone(), overrides) {
|
||||
Ok(config) => config,
|
||||
Err(err) => {
|
||||
eprintln!("Error loading configuration: {err}");
|
||||
@@ -124,6 +133,34 @@ pub async fn run_main(
|
||||
}
|
||||
};
|
||||
|
||||
// we load config.toml here to determine project state.
|
||||
#[allow(clippy::print_stderr)]
|
||||
let config_toml = {
|
||||
let codex_home = match find_codex_home() {
|
||||
Ok(codex_home) => codex_home,
|
||||
Err(err) => {
|
||||
eprintln!("Error finding codex home: {err}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
match load_config_as_toml_with_cli_overrides(&codex_home, cli_kv_overrides) {
|
||||
Ok(config_toml) => config_toml,
|
||||
Err(err) => {
|
||||
eprintln!("Error loading config.toml: {err}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let should_show_trust_screen = determine_repo_trust_state(
|
||||
&mut config,
|
||||
&config_toml,
|
||||
approval_policy,
|
||||
sandbox_mode,
|
||||
cli.config_profile.clone(),
|
||||
)?;
|
||||
|
||||
let log_dir = codex_core::config::log_dir(&config)?;
|
||||
std::fs::create_dir_all(&log_dir)?;
|
||||
// Open (or create) your log file, appending to it.
|
||||
@@ -204,12 +241,14 @@ pub async fn run_main(
|
||||
eprintln!("");
|
||||
}
|
||||
|
||||
run_ratatui_app(cli, config, log_rx).map_err(|err| std::io::Error::other(err.to_string()))
|
||||
run_ratatui_app(cli, config, should_show_trust_screen, log_rx)
|
||||
.map_err(|err| std::io::Error::other(err.to_string()))
|
||||
}
|
||||
|
||||
fn run_ratatui_app(
|
||||
cli: Cli,
|
||||
config: Config,
|
||||
should_show_trust_screen: bool,
|
||||
mut log_rx: tokio::sync::mpsc::UnboundedReceiver<String>,
|
||||
) -> color_eyre::Result<codex_core::protocol::TokenUsage> {
|
||||
color_eyre::install()?;
|
||||
@@ -227,7 +266,7 @@ fn run_ratatui_app(
|
||||
terminal.clear()?;
|
||||
|
||||
let Cli { prompt, images, .. } = cli;
|
||||
let mut app = App::new(config.clone(), prompt, cli.skip_git_repo_check, images);
|
||||
let mut app = App::new(config.clone(), prompt, images, should_show_trust_screen);
|
||||
|
||||
// Bridge log receiver into the AppEvent channel so latest log lines update the UI.
|
||||
{
|
||||
@@ -277,3 +316,39 @@ fn should_show_login_screen(config: &Config) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Determine if user has configured a sandbox / approval policy,
|
||||
/// or if the current cwd project is trusted, and updates the config
|
||||
/// accordingly.
|
||||
fn determine_repo_trust_state(
|
||||
config: &mut Config,
|
||||
config_toml: &ConfigToml,
|
||||
approval_policy_overide: Option<AskForApproval>,
|
||||
sandbox_mode_override: Option<SandboxMode>,
|
||||
config_profile_override: Option<String>,
|
||||
) -> std::io::Result<bool> {
|
||||
let config_profile = config_toml.get_config_profile(config_profile_override)?;
|
||||
|
||||
if approval_policy_overide.is_some() || sandbox_mode_override.is_some() {
|
||||
// if the user has overridden either approval policy or sandbox mode,
|
||||
// skip the trust flow
|
||||
Ok(false)
|
||||
} else if config_profile.approval_policy.is_some() {
|
||||
// if the user has specified settings in a config profile, skip the trust flow
|
||||
// todo: profile sandbox mode?
|
||||
Ok(false)
|
||||
} else if config_toml.approval_policy.is_some() || config_toml.sandbox_mode.is_some() {
|
||||
// if the user has specified either approval policy or sandbox mode in config.toml
|
||||
// skip the trust flow
|
||||
Ok(false)
|
||||
} else if config_toml.is_cwd_trusted(&config.cwd) {
|
||||
// if the current cwd project is trusted and no config has been set
|
||||
// skip the trust flow and set the approval policy and sandbox mode
|
||||
config.approval_policy = AskForApproval::OnRequest;
|
||||
config.sandbox_policy = SandboxPolicy::new_workspace_write_policy();
|
||||
Ok(false)
|
||||
} else {
|
||||
// if none of the above conditions are met, show the trust screen
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user