Skip to content
Merged
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
9 changes: 5 additions & 4 deletions cortex-cli/src/github_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
//! - `cortex github run` - Run GitHub agent in Actions context
//! - `cortex github status` - Check installation status

use crate::styled_output::{print_error, print_success, print_warning};
use anyhow::{Context, Result, bail};
use clap::Parser;
use std::path::PathBuf;
Expand Down Expand Up @@ -583,19 +584,19 @@ async fn run_status(args: StatusArgs) -> Result<()> {
println!();

if !status.is_git_repo {
eprintln!("\x1b[1;33mWarning:\x1b[0m Not a git repository");
print_warning("Not a git repository.");
println!(" Run this command from a git repository root.");
std::process::exit(1);
}

if !status.github_dir_exists {
eprintln!("\x1b[1;31mError:\x1b[0m .github directory not found");
print_error(".github directory not found.");
println!(" Run `cortex github install` to set up GitHub Actions.");
std::process::exit(1);
}

if status.workflow_installed {
println!("Cortex workflow installed");
print_success("Cortex workflow is installed.");
if let Some(ref path) = status.workflow_path {
println!(" Path: {}", path.display());
}
Expand All @@ -605,7 +606,7 @@ async fn run_status(args: StatusArgs) -> Result<()> {
println!(" • {}", feature);
}
} else {
eprintln!("\x1b[1;31mError:\x1b[0m Cortex workflow not found");
print_error("Cortex workflow not found.");
println!(" Run `cortex github install` to set up GitHub Actions.");
std::process::exit(1);
}
Expand Down
23 changes: 13 additions & 10 deletions cortex-cli/src/import_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use anyhow::{Context, Result, bail};
use clap::Parser;
use std::path::PathBuf;

use crate::styled_output::{print_info, print_success, print_warning};
use cortex_engine::rollout::recorder::{RolloutRecorder, SessionMeta};
use cortex_engine::rollout::{SESSIONS_SUBDIR, get_rollout_path};
use cortex_protocol::{
Expand Down Expand Up @@ -109,11 +110,13 @@ impl ImportCommand {
if let Ok(orig_id) = original_id {
let existing_path = get_rollout_path(&cortex_home, &orig_id);
if existing_path.exists() && !self.force {
eprintln!(
"Warning: Original session {} already exists locally.",
print_warning(&format!(
"Original session {} already exists locally.",
export.session.id
);
eprintln!("Creating new session with ID: {new_conversation_id}");
));
print_info(&format!(
"Creating new session with ID: {new_conversation_id}"
));
}
}

Expand Down Expand Up @@ -157,7 +160,7 @@ impl ImportCommand {

recorder.flush()?;

println!("Imported session as: {new_conversation_id}");
print_success(&format!("Imported session as: {new_conversation_id}"));
println!(" Original ID: {}", export.session.id);
if let Some(title) = &export.session.title {
println!(" Title: {title}");
Expand All @@ -167,7 +170,7 @@ impl ImportCommand {

if self.resume {
// Launch resume
println!("\nResuming session...");
print_info("Resuming session...");
let config = cortex_engine::Config::default();

#[cfg(feature = "cortex-tui")]
Expand Down Expand Up @@ -202,11 +205,11 @@ async fn fetch_url(url: &str) -> Result<String> {
&& !content_type_str.contains("text/plain")
&& !content_type_str.is_empty()
{
eprintln!(
"Warning: URL returned Content-Type '{}', expected 'application/json'",
print_warning(&format!(
"URL returned Content-Type '{}', expected 'application/json'.",
content_type_str
);
eprintln!("The import may fail if the content is not valid JSON.");
));
print_info("The import may fail if the content is not valid JSON.");
}
}

Expand Down
1 change: 1 addition & 0 deletions cortex-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub mod pr_cmd;
pub mod run_cmd;
pub mod scrape_cmd;
pub mod stats_cmd;
pub mod styled_output;
pub mod uninstall_cmd;
pub mod upgrade_cmd;

Expand Down
58 changes: 31 additions & 27 deletions cortex-cli/src/login.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Login command handlers.

use crate::styled_output::{print_dim, print_error, print_info, print_success, print_warning};
use cortex_common::CliConfigOverrides;
use cortex_login::{
AuthMode, CredentialsStoreMode, SecureAuthData, load_auth_with_fallback, logout_with_fallback,
Expand All @@ -25,8 +26,8 @@ fn check_duplicate_config_overrides(config_overrides: &CliConfigOverrides) {
}

if has_duplicates {
eprintln!(
"Warning: Duplicate config override keys detected. Only the last value for each key will be used."
print_warning(
"Duplicate config override keys detected. Only the last value for each key will be used.",
);
}
}
Expand All @@ -53,20 +54,20 @@ pub async fn run_login_with_api_key(config_overrides: CliConfigOverrides, api_ke
Ok(mode) => {
match mode {
CredentialsStoreMode::Keyring => {
eprintln!("Successfully logged in (credentials stored in system keyring)");
print_success("Logged in successfully. Credentials stored in system keyring.");
}
CredentialsStoreMode::EncryptedFile => {
eprintln!("Successfully logged in (credentials stored in encrypted file)");
eprintln!("Note: System keyring unavailable, using encrypted file storage");
print_success("Logged in successfully. Credentials stored in encrypted file.");
print_dim("System keyring unavailable, using encrypted file storage.");
}
CredentialsStoreMode::File => {
eprintln!("Successfully logged in (legacy storage)");
print_success("Logged in successfully (legacy storage).");
}
}
std::process::exit(0);
}
Err(e) => {
eprintln!("Error logging in: {e}");
print_error(&format!("Login failed: {e}"));
std::process::exit(1);
}
}
Expand All @@ -92,11 +93,11 @@ pub async fn run_login_with_device_code(

match cortex_login::run_device_code_login(opts).await {
Ok(()) => {
eprintln!("Successfully logged in");
print_success("Logged in successfully.");
std::process::exit(0);
}
Err(e) => {
eprintln!("Error logging in with device code: {e}");
print_error(&format!("Login failed: {e}"));
std::process::exit(1);
}
}
Expand All @@ -112,27 +113,30 @@ pub async fn run_login_status(config_overrides: CliConfigOverrides) -> ! {
Ok(Some(auth)) => match auth.mode {
AuthMode::ApiKey => {
if let Some(key) = auth.get_token() {
eprintln!("Logged in using an API key - {}", safe_format_key(key));
print_success(&format!(
"Logged in using an API key: {}",
safe_format_key(key)
));
std::process::exit(0);
} else {
eprintln!("Logged in but no token available");
print_warning("Logged in but no token available.");
std::process::exit(1);
}
}
AuthMode::OAuth => {
eprintln!("Logged in using OAuth");
print_success("Logged in using OAuth.");
if auth.is_expired() {
eprintln!("(token may be expired)");
print_warning("Token may be expired.");
}
std::process::exit(0);
}
},
Ok(None) => {
eprintln!("Not logged in");
print_info("Not logged in.");
std::process::exit(1);
}
Err(e) => {
eprintln!("Error checking login status: {e}");
print_error(&format!("Failed to check login status: {e}"));
std::process::exit(1);
}
}
Expand Down Expand Up @@ -162,18 +166,18 @@ pub async fn run_logout(config_overrides: CliConfigOverrides, skip_confirmation:
if std::io::stdin().read_line(&mut input).is_ok() {
let input = input.trim().to_lowercase();
if input != "y" && input != "yes" {
eprintln!("Logout cancelled.");
print_info("Logout cancelled.");
std::process::exit(0);
}
}
}
}
Ok(None) => {
eprintln!("Not logged in");
print_info("Not logged in.");
std::process::exit(0);
}
Err(e) => {
eprintln!("Error checking login status: {e}");
print_error(&format!("Failed to check login status: {e}"));
std::process::exit(1);
}
}
Expand All @@ -183,15 +187,15 @@ pub async fn run_logout(config_overrides: CliConfigOverrides, skip_confirmation:
// may have stored them in encrypted file when keyring was unavailable
match logout_with_fallback(&cortex_home) {
Ok(true) => {
eprintln!("Successfully logged out");
print_success("Logged out successfully. Credentials have been removed.");
std::process::exit(0);
}
Ok(false) => {
eprintln!("Not logged in");
print_info("Not logged in.");
std::process::exit(0);
}
Err(e) => {
eprintln!("Error logging out: {e}");
print_error(&format!("Failed to log out: {e}"));
std::process::exit(1);
}
}
Expand All @@ -202,24 +206,24 @@ pub fn read_api_key_from_stdin() -> String {
let mut stdin = std::io::stdin();

if stdin.is_terminal() {
eprintln!(
"--with-api-key expects the API key on stdin. Try piping it, e.g. \
`printenv OPENAI_API_KEY | cortex login --with-api-key`."
print_error(
"The --with-api-key flag expects input from stdin. Try piping it: \
`printenv OPENAI_API_KEY | cortex login --with-api-key`",
);
std::process::exit(1);
}

eprintln!("Reading API key from stdin...");
print_info("Reading API key from stdin...");

let mut buffer = String::new();
if let Err(err) = stdin.read_to_string(&mut buffer) {
eprintln!("Failed to read API key from stdin: {err}");
print_error(&format!("Failed to read API key from stdin: {err}"));
std::process::exit(1);
}

let api_key = buffer.trim().to_string();
if api_key.is_empty() {
eprintln!("No API key provided via stdin.");
print_error("No API key provided via stdin.");
std::process::exit(1);
}

Expand Down
28 changes: 16 additions & 12 deletions cortex-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use cortex_cli::pr_cmd::PrCli;
use cortex_cli::run_cmd::RunCli;
use cortex_cli::scrape_cmd::ScrapeCommand;
use cortex_cli::stats_cmd::StatsCli;
use cortex_cli::styled_output::{print_error, print_info, print_success, print_warning};
use cortex_cli::uninstall_cmd::UninstallCli;
use cortex_cli::upgrade_cmd::UpgradeCli;
use cortex_cli::{LandlockCommand, SeatbeltCommand, WindowsCommand};
Expand Down Expand Up @@ -752,10 +753,10 @@ async fn run_resume(resume_cli: ResumeCommand) -> Result<()> {
(None, true) | (None, false) => {
let sessions = cortex_engine::list_sessions(&config.cortex_home)?;
if sessions.is_empty() {
println!("No sessions found to resume.");
print_info("No sessions found to resume.");
return Ok(());
}
println!("Resuming most recent session...");
print_info("Resuming most recent session...");
sessions[0].id.clone()
}
};
Expand Down Expand Up @@ -792,7 +793,7 @@ async fn run_resume(resume_cli: ResumeCommand) -> Result<()> {
}
};

println!("Resuming session: {conversation_id}");
print_success(&format!("Resuming session: {conversation_id}"));

#[cfg(feature = "cortex-tui")]
{
Expand Down Expand Up @@ -917,7 +918,7 @@ async fn list_sessions(
// TODO: Integrate with cortex-storage SessionStorage to filter favorites
// For now, this is a placeholder - favorites data is stored in cortex-storage
// and would need to be cross-referenced with the rollout-based sessions.
eprintln!("Note: --favorites filter requires session metadata from cortex-storage");
print_info("The --favorites filter requires session metadata from cortex-storage.");
}

if sessions.is_empty() {
Expand Down Expand Up @@ -1109,7 +1110,7 @@ async fn show_config(config_cli: ConfigCommand) -> Result<()> {
.status()?;

if !status.success() {
eprintln!("Editor exited with error");
print_error("Editor exited with an error.");
}
} else {
println!("Cortex Configuration:");
Expand Down Expand Up @@ -1202,7 +1203,7 @@ fn check_special_ip_address(host: &str) {

for (pattern, warning) in special_addresses {
if host == pattern || host.starts_with(pattern) {
eprintln!("Warning: {} - {}", host, warning);
print_warning(&format!("{} - {}", host, warning));
break;
}
}
Expand Down Expand Up @@ -1250,10 +1251,10 @@ async fn run_serve(serve_cli: ServeCommand) -> Result<()> {
..Default::default()
};

println!(
"Starting Cortex server on {}:{}",
print_info(&format!(
"Starting Cortex server on {}:{}...",
serve_cli.host, serve_cli.port
);
));

// Setup mDNS advertising if enabled
let mut mdns_service = if serve_cli.mdns && !serve_cli.no_mdns {
Expand All @@ -1266,11 +1267,14 @@ async fn run_serve(serve_cli: ServeCommand) -> Result<()> {

match mdns.advertise(serve_cli.port, &service_name).await {
Ok(info) => {
println!("mDNS: Advertising as '{}' on port {}", info.name, info.port);
print_success(&format!(
"mDNS: Advertising as '{}' on port {}",
info.name, info.port
));
Some(mdns)
}
Err(e) => {
eprintln!("Warning: Failed to start mDNS advertising: {e}");
print_warning(&format!("Failed to start mDNS advertising: {e}"));
None
}
}
Expand All @@ -1284,7 +1288,7 @@ async fn run_serve(serve_cli: ServeCommand) -> Result<()> {
// Stop mDNS advertising on shutdown
if let Some(ref mut mdns) = mdns_service {
if let Err(e) = mdns.stop_advertising().await {
eprintln!("Warning: Failed to stop mDNS advertising: {e}");
print_warning(&format!("Failed to stop mDNS advertising: {e}"));
}
}

Expand Down
Loading
Loading