Add login status command (#1716)
Print the current login mode, sanitized key and return an appropriate status.
This commit is contained in:
@@ -95,6 +95,12 @@ codex login
|
|||||||
|
|
||||||
If you complete the process successfully, you should have a `~/.codex/auth.json` file that contains the credentials that Codex will use.
|
If you complete the process successfully, you should have a `~/.codex/auth.json` file that contains the credentials that Codex will use.
|
||||||
|
|
||||||
|
To verify whether you are currently logged in, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
codex login status
|
||||||
|
```
|
||||||
|
|
||||||
If you encounter problems with the login flow, please comment on <https://github.com/openai/codex/issues/1243>.
|
If you encounter problems with the login flow, please comment on <https://github.com/openai/codex/issues/1243>.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
|||||||
@@ -1,25 +1,12 @@
|
|||||||
use codex_common::CliConfigOverrides;
|
use codex_common::CliConfigOverrides;
|
||||||
use codex_core::config::Config;
|
use codex_core::config::Config;
|
||||||
use codex_core::config::ConfigOverrides;
|
use codex_core::config::ConfigOverrides;
|
||||||
|
use codex_login::AuthMode;
|
||||||
|
use codex_login::load_auth;
|
||||||
use codex_login::login_with_chatgpt;
|
use codex_login::login_with_chatgpt;
|
||||||
|
|
||||||
pub async fn run_login_with_chatgpt(cli_config_overrides: CliConfigOverrides) -> ! {
|
pub async fn run_login_with_chatgpt(cli_config_overrides: CliConfigOverrides) -> ! {
|
||||||
let cli_overrides = match cli_config_overrides.parse_overrides() {
|
let config = load_config_or_exit(cli_config_overrides);
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Error parsing -c overrides: {e}");
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let config_overrides = ConfigOverrides::default();
|
|
||||||
let config = match Config::load_with_cli_overrides(cli_overrides, config_overrides) {
|
|
||||||
Ok(config) => config,
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Error loading configuration: {e}");
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let capture_output = false;
|
let capture_output = false;
|
||||||
match login_with_chatgpt(&config.codex_home, capture_output).await {
|
match login_with_chatgpt(&config.codex_home, capture_output).await {
|
||||||
@@ -33,3 +20,77 @@ pub async fn run_login_with_chatgpt(cli_config_overrides: CliConfigOverrides) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn run_login_status(cli_config_overrides: CliConfigOverrides) -> ! {
|
||||||
|
let config = load_config_or_exit(cli_config_overrides);
|
||||||
|
|
||||||
|
match load_auth(&config.codex_home) {
|
||||||
|
Ok(Some(auth)) => match auth.mode {
|
||||||
|
AuthMode::ApiKey => {
|
||||||
|
if let Some(api_key) = auth.api_key.as_deref() {
|
||||||
|
eprintln!("Logged in using an API key - {}", safe_format_key(api_key));
|
||||||
|
} else {
|
||||||
|
eprintln!("Logged in using an API key");
|
||||||
|
}
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
AuthMode::ChatGPT => {
|
||||||
|
eprintln!("Logged in using ChatGPT");
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Ok(None) => {
|
||||||
|
eprintln!("Not logged in");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error checking login status: {e}");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_config_or_exit(cli_config_overrides: CliConfigOverrides) -> Config {
|
||||||
|
let cli_overrides = match cli_config_overrides.parse_overrides() {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error parsing -c overrides: {e}");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let config_overrides = ConfigOverrides::default();
|
||||||
|
match Config::load_with_cli_overrides(cli_overrides, config_overrides) {
|
||||||
|
Ok(config) => config,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error loading configuration: {e}");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn safe_format_key(key: &str) -> String {
|
||||||
|
if key.len() <= 13 {
|
||||||
|
return "***".to_string();
|
||||||
|
}
|
||||||
|
let prefix = &key[..8];
|
||||||
|
let suffix = &key[key.len() - 5..];
|
||||||
|
format!("{prefix}***{suffix}")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::safe_format_key;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn formats_long_key() {
|
||||||
|
let key = "sk-proj-1234567890ABCDE";
|
||||||
|
assert_eq!(safe_format_key(key), "sk-proj-***ABCDE");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn short_key_returns_stars() {
|
||||||
|
let key = "sk-proj-12345";
|
||||||
|
assert_eq!(safe_format_key(key), "***");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use codex_chatgpt::apply_command::ApplyCommand;
|
|||||||
use codex_chatgpt::apply_command::run_apply_command;
|
use codex_chatgpt::apply_command::run_apply_command;
|
||||||
use codex_cli::LandlockCommand;
|
use codex_cli::LandlockCommand;
|
||||||
use codex_cli::SeatbeltCommand;
|
use codex_cli::SeatbeltCommand;
|
||||||
|
use codex_cli::login::run_login_status;
|
||||||
use codex_cli::login::run_login_with_chatgpt;
|
use codex_cli::login::run_login_with_chatgpt;
|
||||||
use codex_cli::proto;
|
use codex_cli::proto;
|
||||||
use codex_common::CliConfigOverrides;
|
use codex_common::CliConfigOverrides;
|
||||||
@@ -43,7 +44,7 @@ enum Subcommand {
|
|||||||
#[clap(visible_alias = "e")]
|
#[clap(visible_alias = "e")]
|
||||||
Exec(ExecCli),
|
Exec(ExecCli),
|
||||||
|
|
||||||
/// Login with ChatGPT.
|
/// Manage login.
|
||||||
Login(LoginCommand),
|
Login(LoginCommand),
|
||||||
|
|
||||||
/// Experimental: run Codex as an MCP server.
|
/// Experimental: run Codex as an MCP server.
|
||||||
@@ -90,6 +91,15 @@ enum DebugCommand {
|
|||||||
struct LoginCommand {
|
struct LoginCommand {
|
||||||
#[clap(skip)]
|
#[clap(skip)]
|
||||||
config_overrides: CliConfigOverrides,
|
config_overrides: CliConfigOverrides,
|
||||||
|
|
||||||
|
#[command(subcommand)]
|
||||||
|
action: Option<LoginSubcommand>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, clap::Subcommand)]
|
||||||
|
enum LoginSubcommand {
|
||||||
|
/// Show login status.
|
||||||
|
Status,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
@@ -118,7 +128,14 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
|||||||
}
|
}
|
||||||
Some(Subcommand::Login(mut login_cli)) => {
|
Some(Subcommand::Login(mut login_cli)) => {
|
||||||
prepend_config_flags(&mut login_cli.config_overrides, cli.config_overrides);
|
prepend_config_flags(&mut login_cli.config_overrides, cli.config_overrides);
|
||||||
run_login_with_chatgpt(login_cli.config_overrides).await;
|
match login_cli.action {
|
||||||
|
Some(LoginSubcommand::Status) => {
|
||||||
|
run_login_status(login_cli.config_overrides).await;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
run_login_with_chatgpt(login_cli.config_overrides).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(Subcommand::Proto(mut proto_cli)) => {
|
Some(Subcommand::Proto(mut proto_cli)) => {
|
||||||
prepend_config_flags(&mut proto_cli.config_overrides, cli.config_overrides);
|
prepend_config_flags(&mut proto_cli.config_overrides, cli.config_overrides);
|
||||||
|
|||||||
Reference in New Issue
Block a user