From f10374c925596bac54fe5b1e3378b8949132367f Mon Sep 17 00:00:00 2001 From: "Dhanji R. Prasanna" Date: Mon, 12 Jan 2026 06:01:31 +0530 Subject: [PATCH] Remove machine mode entirely from g3 - Delete machine_ui_writer.rs - Remove --machine CLI flag from cli_args.rs - Remove run_machine_mode(), run_interactive_machine(), run_autonomous_machine() functions - Remove handle_machine_command() function - Simplify OutputMode enum to just use SimpleOutput directly - Simplify SimpleOutput struct (remove machine_mode field) - Remove machine_mode parameter from setup_workspace_directory() - Remove test_machine_option_accepted test - Disable ACD by default in agent_mode (requires --acd flag) - Change 'memory checkpoint' message formatting - Remove dehydration status message --- crates/g3-cli/src/agent_mode.rs | 3 - crates/g3-cli/src/autonomous.rs | 55 ---- crates/g3-cli/src/cli_args.rs | 4 - crates/g3-cli/src/interactive.rs | 297 +------------------- crates/g3-cli/src/lib.rs | 83 +----- crates/g3-cli/src/machine_ui_writer.rs | 111 -------- crates/g3-cli/src/simple_output.rs | 20 +- crates/g3-cli/src/task_execution.rs | 113 +------- crates/g3-cli/src/utils.rs | 4 +- crates/g3-cli/tests/cli_integration_test.rs | 17 -- crates/g3-core/src/lib.rs | 4 +- 11 files changed, 26 insertions(+), 685 deletions(-) delete mode 100644 crates/g3-cli/src/machine_ui_writer.rs diff --git a/crates/g3-cli/src/agent_mode.rs b/crates/g3-cli/src/agent_mode.rs index f8cd7b5..9a30649 100644 --- a/crates/g3-cli/src/agent_mode.rs +++ b/crates/g3-cli/src/agent_mode.rs @@ -209,9 +209,6 @@ pub async fn run_agent_mode( // This prompts the LLM to save discoveries to project memory after each turn agent.set_auto_memory(true); - // Enable ACD in agent mode for longer sessions - agent.set_acd_enabled(true); - // If resuming a session, restore context and TODO let initial_task = if let Some(ref incomplete_session) = resuming_session { // Restore the session context diff --git a/crates/g3-cli/src/autonomous.rs b/crates/g3-cli/src/autonomous.rs index 37b603c..f534bc6 100644 --- a/crates/g3-cli/src/autonomous.rs +++ b/crates/g3-cli/src/autonomous.rs @@ -11,7 +11,6 @@ use g3_core::project::Project; use g3_core::{Agent, DiscoveryOptions}; use crate::coach_feedback; -use crate::machine_ui_writer::MachineUiWriter; use crate::metrics::{format_elapsed_time, generate_turn_histogram, TurnMetrics}; use crate::simple_output::SimpleOutput; use crate::ui_writer_impl::ConsoleUiWriter; @@ -264,60 +263,6 @@ pub async fn run_autonomous( Ok(agent) } -/// Run autonomous mode with machine-friendly output. -pub async fn run_autonomous_machine( - mut agent: Agent, - project: Project, - show_prompt: bool, - show_code: bool, - max_turns: usize, - _quiet: bool, - _codebase_fast_start: Option, -) -> Result<()> { - println!("AUTONOMOUS_MODE_STARTED"); - println!("WORKSPACE: {}", project.workspace().display()); - println!("MAX_TURNS: {}", max_turns); - - // Check if requirements exist - if !project.has_requirements() { - println!("ERROR: requirements.md not found in workspace directory"); - return Ok(()); - } - - // Read requirements - let requirements = match project.read_requirements()? { - Some(content) => content, - None => { - println!("ERROR: Could not read requirements"); - return Ok(()); - } - }; - - println!("REQUIREMENTS_LOADED"); - - // For now, just execute a simple autonomous loop - // This is a simplified version - full implementation would need coach-player loop - let task = format!( - "You are G3 in implementation mode. Read and implement the following requirements:\n\n{}\n\nImplement this step by step, creating all necessary files and code.", - requirements - ); - - println!("TASK_START"); - let result = agent - .execute_task_with_timing(&task, None, false, show_prompt, show_code, true, None) - .await?; - println!("AGENT_RESPONSE:"); - println!("{}", result.response); - println!("END_AGENT_RESPONSE"); - println!("TASK_END"); - - // Save session continuation for resume capability - agent.save_session_continuation(Some(result.response.clone())); - - println!("AUTONOMOUS_MODE_ENDED"); - Ok(()) -} - // --- Helper types and functions --- enum PlayerTurnResult { diff --git a/crates/g3-cli/src/cli_args.rs b/crates/g3-cli/src/cli_args.rs index 3d9edc7..eb5dce7 100644 --- a/crates/g3-cli/src/cli_args.rs +++ b/crates/g3-cli/src/cli_args.rs @@ -55,10 +55,6 @@ pub struct Cli { #[arg(long)] pub chat: bool, - /// Enable machine-friendly output mode with JSON markers and stats - #[arg(long)] - pub machine: bool, - /// Override the configured provider (anthropic, databricks, embedded, openai) #[arg(long, value_name = "PROVIDER")] pub provider: Option, diff --git a/crates/g3-cli/src/interactive.rs b/crates/g3-cli/src/interactive.rs index 491eb1b..b7a1351 100644 --- a/crates/g3-cli/src/interactive.rs +++ b/crates/g3-cli/src/interactive.rs @@ -10,10 +10,9 @@ use tracing::{debug, error}; use g3_core::ui_writer::UiWriter; use g3_core::Agent; -use crate::machine_ui_writer::MachineUiWriter; use crate::project_files::extract_readme_heading; use crate::simple_output::SimpleOutput; -use crate::task_execution::{execute_task_with_retry, OutputMode}; +use crate::task_execution::execute_task_with_retry; use crate::utils::display_context_progress; /// Run interactive mode with console output. @@ -206,7 +205,7 @@ pub async fn run_interactive( &input, show_prompt, show_code, - OutputMode::Console(&output), + &output, ) .await; @@ -242,7 +241,7 @@ pub async fn run_interactive( &input, show_prompt, show_code, - OutputMode::Console(&output), + &output, ) .await; @@ -287,95 +286,6 @@ pub async fn run_interactive( Ok(()) } -/// Run interactive mode with machine-friendly output. -pub async fn run_interactive_machine( - mut agent: Agent, - show_prompt: bool, - show_code: bool, -) -> Result<()> { - println!("INTERACTIVE_MODE_STARTED"); - - // Display provider and model information - match agent.get_provider_info() { - Ok((provider, model)) => { - println!("PROVIDER: {}", provider); - println!("MODEL: {}", model); - } - Err(e) => { - println!("ERROR: Failed to get provider info: {}", e); - } - } - - // Initialize rustyline editor with history - let mut rl = DefaultEditor::new()?; - - // Try to load history from a file in the user's home directory - let history_file = dirs::home_dir().map(|mut path| { - path.push(".g3_history"); - path - }); - - if let Some(ref history_path) = history_file { - let _ = rl.load_history(history_path); - } - - loop { - let readline = rl.readline(""); - match readline { - Ok(line) => { - let input = line.trim().to_string(); - - if input.is_empty() { - continue; - } - - if input == "exit" || input == "quit" { - break; - } - - // Add to history - rl.add_history_entry(&input)?; - - // Check for control commands - if input.starts_with('/') { - if handle_machine_command(&input, &mut agent).await? { - continue; - } - } - - // Execute task - println!("TASK_START"); - execute_task_with_retry(&mut agent, &input, show_prompt, show_code, OutputMode::Machine) - .await; - - // Send auto-memory reminder if enabled and tools were called - if let Err(e) = agent.send_auto_memory_reminder().await { - debug!("Auto-memory reminder failed: {}", e); - } - - println!("TASK_END"); - } - Err(ReadlineError::Interrupted) => continue, - Err(ReadlineError::Eof) => break, - Err(err) => { - println!("ERROR: {:?}", err); - break; - } - } - } - - // Save history before exiting - if let Some(ref history_path) = history_file { - let _ = rl.save_history(history_path); - } - - // Save session continuation for resume capability - agent.save_session_continuation(None); - - println!("INTERACTIVE_MODE_ENDED"); - Ok(()) -} - /// Handle a control command. Returns true if the command was handled and the loop should continue. async fn handle_command( input: &str, @@ -648,204 +558,3 @@ async fn handle_command( } } } - -/// Handle a control command in machine mode. Returns true if the command was handled. -async fn handle_machine_command( - input: &str, - agent: &mut Agent, -) -> Result { - match input { - "/compact" => { - println!("COMMAND: compact"); - match agent.force_compact().await { - Ok(true) => println!("RESULT: Compaction completed"), - Ok(false) => println!("RESULT: Compaction failed"), - Err(e) => println!("ERROR: {}", e), - } - Ok(true) - } - "/thinnify" => { - println!("COMMAND: thinnify"); - let summary = agent.force_thin(); - println!("{}", summary); - Ok(true) - } - "/skinnify" => { - println!("COMMAND: skinnify"); - let summary = agent.force_thin_all(); - println!("{}", summary); - Ok(true) - } - "/fragments" => { - println!("COMMAND: fragments"); - if let Some(session_id) = agent.get_session_id() { - match g3_core::acd::list_fragments(session_id) { - Ok(fragments) => { - println!("FRAGMENT_COUNT: {}", fragments.len()); - for fragment in &fragments { - println!("FRAGMENT_ID: {}", fragment.fragment_id); - println!("FRAGMENT_MESSAGES: {}", fragment.message_count); - println!("FRAGMENT_TOKENS: {}", fragment.estimated_tokens); - } - } - Err(e) => { - println!("ERROR: {}", e); - } - } - } else { - println!("ERROR: No active session"); - } - Ok(true) - } - cmd if cmd.starts_with("/rehydrate") => { - println!("COMMAND: rehydrate"); - let parts: Vec<&str> = cmd.splitn(2, ' ').collect(); - if parts.len() < 2 || parts[1].trim().is_empty() { - println!("ERROR: Usage: /rehydrate "); - } else { - let fragment_id = parts[1].trim(); - println!("FRAGMENT_ID: {}", fragment_id); - println!("RESULT: Use the rehydrate tool to restore fragment content"); - } - Ok(true) - } - "/dump" => { - println!("COMMAND: dump"); - let dump_dir = std::path::Path::new("tmp"); - if !dump_dir.exists() { - if let Err(e) = std::fs::create_dir_all(dump_dir) { - println!("ERROR: Failed to create tmp directory: {}", e); - return Ok(true); - } - } - - let timestamp = chrono::Utc::now().format("%Y%m%d_%H%M%S"); - let dump_path = dump_dir.join(format!("context_dump_{}.txt", timestamp)); - - let context = agent.get_context_window(); - let mut dump_content = String::new(); - dump_content.push_str("# Context Window Dump\n"); - dump_content.push_str(&format!("# Timestamp: {}\n", chrono::Utc::now())); - dump_content.push_str(&format!( - "# Messages: {}\n", - context.conversation_history.len() - )); - dump_content.push_str(&format!( - "# Used tokens: {} / {} ({:.1}%)\n\n", - context.used_tokens, - context.total_tokens, - context.percentage_used() - )); - - for (i, msg) in context.conversation_history.iter().enumerate() { - dump_content.push_str(&format!( - "=== Message {} ===\nRole: {:?}\nKind: {:?}\nContent ({} chars):\n{}\n\n", - i, - msg.role, - msg.kind, - msg.content.len(), - msg.content - )); - } - - match std::fs::write(&dump_path, &dump_content) { - Ok(_) => println!("RESULT: Context dumped to {}", dump_path.display()), - Err(e) => println!("ERROR: Failed to write dump: {}", e), - } - Ok(true) - } - "/clear" => { - println!("COMMAND: clear"); - agent.clear_session(); - println!("RESULT: Session cleared"); - Ok(true) - } - "/readme" => { - println!("COMMAND: readme"); - match agent.reload_readme() { - Ok(true) => println!("RESULT: README content reloaded successfully"), - Ok(false) => println!("RESULT: No README was loaded at startup, cannot reload"), - Err(e) => println!("ERROR: {}", e), - } - Ok(true) - } - "/stats" => { - println!("COMMAND: stats"); - let stats = agent.get_stats(); - // Emit stats as structured data (name: value pairs) - println!("{}", stats); - Ok(true) - } - "/help" => { - println!("COMMAND: help"); - println!("AVAILABLE_COMMANDS: /compact /thinnify /skinnify /clear /dump /fragments /rehydrate /resume /readme /stats /help"); - Ok(true) - } - "/resume" => { - println!("COMMAND: resume"); - match g3_core::list_sessions_for_directory() { - Ok(sessions) => { - if sessions.is_empty() { - println!("RESULT: No sessions found"); - return Ok(true); - } - - println!("SESSIONS_START"); - for (i, session) in sessions.iter().enumerate() { - let time_str = g3_core::format_session_time(&session.created_at); - let has_todos = if session.has_incomplete_todos() { - "true" - } else { - "false" - }; - println!( - "SESSION: {} | {} | {} | {:.0}% | {}", - i + 1, - session.session_id, - time_str, - session.context_percentage, - has_todos - ); - } - println!("SESSIONS_END"); - println!("HINT: Use /resume to switch to a session"); - } - Err(e) => println!("ERROR: {}", e), - } - Ok(true) - } - _ => { - // Check for /resume pattern - if input.starts_with("/resume ") { - let num_str = input.strip_prefix("/resume ").unwrap().trim(); - if let Ok(num) = num_str.parse::() { - println!("COMMAND: resume {}", num); - match g3_core::list_sessions_for_directory() { - Ok(sessions) => { - if num >= 1 && num <= sessions.len() { - let selected = &sessions[num - 1]; - match agent.switch_to_session(selected) { - Ok(true) => println!( - "RESULT: Full context restored from session {}", - selected.session_id - ), - Ok(false) => println!( - "RESULT: Session {} restored from summary", - selected.session_id - ), - Err(e) => println!("ERROR: {}", e), - } - } else { - println!("ERROR: Invalid session number"); - } - } - Err(e) => println!("ERROR: {}", e), - } - return Ok(true); - } - } - println!("ERROR: Unknown command: {}", input); - Ok(true) - } - } -} diff --git a/crates/g3-cli/src/lib.rs b/crates/g3-cli/src/lib.rs index 1515e7b..8979247 100644 --- a/crates/g3-cli/src/lib.rs +++ b/crates/g3-cli/src/lib.rs @@ -11,7 +11,6 @@ mod autonomous; mod cli_args; mod coach_feedback; mod interactive; -mod machine_ui_writer; mod simple_output; mod task_execution; mod ui_writer_impl; @@ -30,9 +29,8 @@ use clap::Parser; use accumulative::run_accumulative_mode; use agent_mode::run_agent_mode; -use autonomous::{run_autonomous, run_autonomous_machine}; -use interactive::{run_interactive, run_interactive_machine}; -use machine_ui_writer::MachineUiWriter; +use autonomous::run_autonomous; +use interactive::run_interactive; use project_files::{read_agents_config, read_project_memory, read_project_readme}; use simple_output::SimpleOutput; use ui_writer_impl::ConsoleUiWriter; @@ -110,12 +108,7 @@ pub async fn run() -> Result<()> { // Combine AGENTS.md, README, and memory content let combined_content = combine_project_content(agents_content, readme_content, memory_content); - // Execute based on mode - if cli.machine { - run_machine_mode(cli, config, project, combined_content).await - } else { - run_console_mode(cli, config, project, combined_content, workspace_dir).await - } + run_console_mode(cli, config, project, combined_content, workspace_dir).await } // --- Helper functions --- @@ -123,10 +116,7 @@ pub async fn run() -> Result<()> { fn initialize_logging(cli: &Cli) { use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; - let filter = if cli.machine { - // In machine mode, suppress ALL logs - EnvFilter::from_default_env().add_directive("off".parse().unwrap()) - } else if cli.verbose { + let filter = if cli.verbose { EnvFilter::from_default_env() .add_directive(format!("{}=debug", env!("CARGO_PKG_NAME")).parse().unwrap()) .add_directive("g3_core=debug".parse().unwrap()) @@ -154,7 +144,7 @@ fn determine_workspace_dir(cli: &Cli) -> Result { if let Some(ws) = &cli.workspace { Ok(ws.clone()) } else if cli.autonomous { - setup_workspace_directory(cli.machine) + setup_workspace_directory() } else { Ok(std::env::current_dir()?) } @@ -243,69 +233,6 @@ fn combine_project_content( } } -async fn run_machine_mode( - cli: Cli, - config: Config, - project: Project, - combined_content: Option, -) -> Result<()> { - let ui_writer = MachineUiWriter::new(); - - let mut agent = if cli.autonomous { - Agent::new_autonomous_with_readme_and_quiet( - config.clone(), - ui_writer, - combined_content.clone(), - cli.quiet, - ) - .await? - } else { - Agent::new_with_readme_and_quiet( - config.clone(), - ui_writer, - combined_content.clone(), - cli.quiet, - ) - .await? - }; - - if cli.auto_memory { - agent.set_auto_memory(true); - } - if cli.acd { - agent.set_acd_enabled(true); - } - - if cli.autonomous { - run_autonomous_machine( - agent, - project, - cli.show_prompt, - cli.show_code, - cli.max_turns, - cli.quiet, - cli.codebase_fast_start.clone(), - ) - .await - } else if let Some(task) = cli.task { - // Single-shot mode - let result = agent - .execute_task_with_timing(&task, None, false, cli.show_prompt, cli.show_code, true, None) - .await?; - println!("AGENT_RESPONSE:"); - println!("{}", result.response); - println!("END_AGENT_RESPONSE"); - - if let Err(e) = agent.send_auto_memory_reminder().await { - debug!("Auto-memory reminder failed: {}", e); - } - agent.save_session_continuation(Some(result.response.clone())); - Ok(()) - } else { - run_interactive_machine(agent, cli.show_prompt, cli.show_code).await - } -} - async fn run_console_mode( cli: Cli, config: Config, diff --git a/crates/g3-cli/src/machine_ui_writer.rs b/crates/g3-cli/src/machine_ui_writer.rs deleted file mode 100644 index f8bef83..0000000 --- a/crates/g3-cli/src/machine_ui_writer.rs +++ /dev/null @@ -1,111 +0,0 @@ -use g3_core::ui_writer::UiWriter; -use std::io::{self, Write}; - -/// Machine-mode implementation of UiWriter that prints plain, unformatted output -/// This is designed for programmatic consumption and outputs everything verbatim -pub struct MachineUiWriter; - -impl MachineUiWriter { - pub fn new() -> Self { - Self - } -} - -impl UiWriter for MachineUiWriter { - fn print(&self, message: &str) { - print!("{}", message); - } - - fn println(&self, message: &str) { - println!("{}", message); - } - - fn print_inline(&self, message: &str) { - print!("{}", message); - let _ = io::stdout().flush(); - } - - fn print_system_prompt(&self, prompt: &str) { - println!("SYSTEM_PROMPT:"); - println!("{}", prompt); - println!("END_SYSTEM_PROMPT"); - println!(); - } - - fn print_context_status(&self, message: &str) { - println!("CONTEXT_STATUS: {}", message); - } - - fn print_context_thinning(&self, message: &str) { - println!("CONTEXT_THINNING: {}", message); - } - - fn print_tool_header(&self, tool_name: &str, _tool_args: Option<&serde_json::Value>) { - println!("TOOL_CALL: {}", tool_name); - } - - fn print_tool_arg(&self, key: &str, value: &str) { - println!("TOOL_ARG: {} = {}", key, value); - } - - fn print_tool_output_header(&self) { - println!("TOOL_OUTPUT:"); - } - - fn update_tool_output_line(&self, line: &str) { - println!("{}", line); - } - - fn print_tool_output_line(&self, line: &str) { - println!("{}", line); - } - - fn print_tool_output_summary(&self, count: usize) { - println!("TOOL_OUTPUT_LINES: {}", count); - } - - fn print_tool_timing(&self, duration_str: &str, tokens_delta: u32, context_percentage: f32) { - println!("TOOL_DURATION: {}", duration_str); - println!("TOKENS_DELTA: {}", tokens_delta); - println!("CONTEXT_PERCENTAGE: {:.0}", context_percentage); - println!("END_TOOL_OUTPUT"); - println!(); - } - - fn print_agent_prompt(&self) { - println!("AGENT_RESPONSE:"); - let _ = io::stdout().flush(); - } - - fn print_agent_response(&self, content: &str) { - print!("{}", content); - let _ = io::stdout().flush(); - } - - fn notify_sse_received(&self) { - // No-op for machine mode - } - - fn flush(&self) { - let _ = io::stdout().flush(); - } - - fn wants_full_output(&self) -> bool { - true // Machine mode wants complete, untruncated output - } - - fn prompt_user_yes_no(&self, message: &str) -> bool { - // In machine mode, we can't interactively prompt, so we log the request and return true - // to allow automation to proceed. - println!("PROMPT_USER_YES_NO: {}", message); - true - } - - fn prompt_user_choice(&self, message: &str, options: &[&str]) -> usize { - println!("PROMPT_USER_CHOICE: {}", message); - println!("OPTIONS: {:?}", options); - // Default to first option (index 0) for automation - 0 - } - -} diff --git a/crates/g3-cli/src/simple_output.rs b/crates/g3-cli/src/simple_output.rs index 3838f29..e6bd99b 100644 --- a/crates/g3-cli/src/simple_output.rs +++ b/crates/g3-cli/src/simple_output.rs @@ -1,30 +1,18 @@ /// Simple output helper for printing messages #[derive(Clone)] -pub struct SimpleOutput { - machine_mode: bool, -} +pub struct SimpleOutput; impl SimpleOutput { pub fn new() -> Self { - SimpleOutput { - machine_mode: false, - } - } - - pub fn new_with_mode(machine_mode: bool) -> Self { - SimpleOutput { machine_mode } + SimpleOutput } pub fn print(&self, message: &str) { - if !self.machine_mode { - println!("{}", message); - } + println!("{}", message); } pub fn print_smart(&self, message: &str) { - if !self.machine_mode { - println!("{}", message); - } + println!("{}", message); } } diff --git a/crates/g3-cli/src/task_execution.rs b/crates/g3-cli/src/task_execution.rs index 0c807b6..9ad01f3 100644 --- a/crates/g3-cli/src/task_execution.rs +++ b/crates/g3-cli/src/task_execution.rs @@ -11,101 +11,17 @@ use crate::simple_output::SimpleOutput; /// Maximum number of retry attempts for timeout errors const MAX_TIMEOUT_RETRIES: u32 = 3; -/// Output mode for task execution feedback -pub enum OutputMode<'a> { - /// Console mode with SimpleOutput for user-friendly messages - Console(&'a SimpleOutput), - /// Machine mode with structured output markers - Machine, -} - -impl<'a> OutputMode<'a> { - fn print_thinking(&self) { - match self { - OutputMode::Console(output) => output.print("🤔 Thinking..."), - OutputMode::Machine => {} // No thinking indicator in machine mode - } - } - - fn print_cancelled(&self) { - match self { - OutputMode::Console(output) => output.print("\n⚠️ Operation cancelled by user (Ctrl+C)"), - OutputMode::Machine => println!("CANCELLED"), - } - } - - fn print_cancelled_simple(&self) { - match self { - OutputMode::Console(output) => output.print("⚠️ Operation cancelled by user"), - OutputMode::Machine => println!("CANCELLED"), - } - } - - fn print_retry_success(&self, attempt: u32) { - match self { - OutputMode::Console(output) => { - output.print(&format!("✅ Request succeeded after {} attempts", attempt)) - } - OutputMode::Machine => println!("RETRY_SUCCESS: attempt {}", attempt), - } - } - - fn print_response(&self, response: &str, output: Option<&SimpleOutput>) { - match self { - OutputMode::Console(o) => o.print_smart(response), - OutputMode::Machine => { - println!("AGENT_RESPONSE:"); - println!("{}", response); - println!("END_AGENT_RESPONSE"); - // Ignore the output parameter in machine mode - let _ = output; - } - } - } - - fn print_timeout_retry(&self, attempt: u32, delay: std::time::Duration) { - match self { - OutputMode::Console(output) => { - output.print(&format!( - "⏱️ Timeout error detected (attempt {}/{}). Retrying in {:?}...", - attempt, MAX_TIMEOUT_RETRIES, delay - )); - } - OutputMode::Machine => { - println!( - "TIMEOUT: attempt {} of {}, retrying in {:?}", - attempt, MAX_TIMEOUT_RETRIES, delay - ); - } - } - } - - fn print_error(&self, e: &anyhow::Error, attempt: u32) { - match self { - OutputMode::Console(_) => {} // Handled by handle_execution_error - OutputMode::Machine => { - println!("ERROR: {}", e); - if attempt > 1 { - println!("FAILED_AFTER_RETRIES: {}", attempt); - } - } - } - } -} - /// Execute a task with retry logic for timeout errors. -/// -/// This is the unified implementation used by both console and machine modes. pub async fn execute_task_with_retry( agent: &mut Agent, input: &str, show_prompt: bool, show_code: bool, - mode: OutputMode<'_>, + output: &SimpleOutput, ) { let mut attempt = 0; - mode.print_thinking(); + output.print("🤔 Thinking..."); // Create cancellation token for this request let cancellation_token = CancellationToken::new(); @@ -123,7 +39,7 @@ pub async fn execute_task_with_retry( } _ = tokio::signal::ctrl_c() => { cancel_token_clone.cancel(); - mode.print_cancelled(); + output.print("\n⚠️ Operation cancelled by user (Ctrl+C)"); return; } }; @@ -131,17 +47,14 @@ pub async fn execute_task_with_retry( match execution_result { Ok(result) => { if attempt > 1 { - mode.print_retry_success(attempt); + output.print(&format!("✅ Request succeeded after {} attempts", attempt)); } - mode.print_response(&result.response, match &mode { - OutputMode::Console(o) => Some(*o), - OutputMode::Machine => None, - }); + output.print_smart(&result.response); return; } Err(e) => { if e.to_string().contains("cancelled") { - mode.print_cancelled_simple(); + output.print("⚠️ Operation cancelled by user"); return; } @@ -157,7 +70,10 @@ pub async fn execute_task_with_retry( let delay_ms = 1000 * (2_u64.pow(attempt - 1)); let delay = std::time::Duration::from_millis(delay_ms); - mode.print_timeout_retry(attempt, delay); + output.print(&format!( + "⏱️ Timeout error detected (attempt {}/{}). Retrying in {:?}...", + attempt, MAX_TIMEOUT_RETRIES, delay + )); // Wait before retrying tokio::time::sleep(delay).await; @@ -165,14 +81,7 @@ pub async fn execute_task_with_retry( } // For non-timeout errors or after max retries - match &mode { - OutputMode::Console(output) => { - handle_execution_error(&e, input, output, attempt); - } - OutputMode::Machine => { - mode.print_error(&e, attempt); - } - } + handle_execution_error(&e, input, output, attempt); return; } } diff --git a/crates/g3-cli/src/utils.rs b/crates/g3-cli/src/utils.rs index 3e7858f..caab742 100644 --- a/crates/g3-cli/src/utils.rs +++ b/crates/g3-cli/src/utils.rs @@ -67,7 +67,7 @@ pub fn display_context_progress(agent: &Agent, _output: &SimpleO /// Set up the workspace directory for autonomous mode. /// Uses G3_WORKSPACE environment variable or defaults to ~/tmp/workspace. -pub fn setup_workspace_directory(machine_mode: bool) -> Result { +pub fn setup_workspace_directory() -> Result { let workspace_dir = if let Ok(env_workspace) = std::env::var("G3_WORKSPACE") { PathBuf::from(env_workspace) } else { @@ -80,7 +80,7 @@ pub fn setup_workspace_directory(machine_mode: bool) -> Result { // Create the directory if it doesn't exist if !workspace_dir.exists() { std::fs::create_dir_all(&workspace_dir)?; - let output = SimpleOutput::new_with_mode(machine_mode); + let output = SimpleOutput::new(); output.print(&format!( "📁 Created workspace directory: {}", workspace_dir.display() diff --git a/crates/g3-cli/tests/cli_integration_test.rs b/crates/g3-cli/tests/cli_integration_test.rs index 9528b1b..d20bfc0 100644 --- a/crates/g3-cli/tests/cli_integration_test.rs +++ b/crates/g3-cli/tests/cli_integration_test.rs @@ -275,20 +275,3 @@ fn test_quiet_option_accepted() { "--quiet option should be recognized" ); } - -// ============================================================================= -// Test: Machine mode option is accepted -// ============================================================================= - -#[test] -fn test_machine_option_accepted() { - let output = Command::new(get_g3_binary()) - .args(["--machine", "--help"]) - .output() - .expect("Failed to execute g3 with machine option"); - - assert!( - output.status.success(), - "--machine option should be recognized" - ); -} diff --git a/crates/g3-core/src/lib.rs b/crates/g3-core/src/lib.rs index e573292..1f8f283 100644 --- a/crates/g3-core/src/lib.rs +++ b/crates/g3-core/src/lib.rs @@ -1452,8 +1452,6 @@ impl Agent { return; // Don't modify context if save failed } - println!("💾 Dehydrated {} messages to fragment {}", fragment.message_count, fragment.fragment_id); - // Now replace the context: keep system messages + previous stubs/summaries, add new stub, add new summary // Extract messages to keep: system messages + everything up to (but not including) dehydrate_start let messages_to_keep: Vec<_> = self.context_window @@ -1524,7 +1522,7 @@ impl Agent { let tools_called = std::mem::take(&mut self.tool_calls_this_turn); debug!("Auto-memory: Sending reminder to LLM ({} tools called this turn: {:?})", tools_called.len(), tools_called); - self.ui_writer.print_context_status("\n*memory checkpoint:* "); + self.ui_writer.print_context_status("\nMemory checkpoint: "); let reminder = "SYSTEM REMINDER: You used tools during this turn. If you discovered any key code locations, patterns, or entry points that aren't already in Project Memory, please call the `remember` tool now to save them. If you didn't discover anything new worth remembering, you can skip this. Respond briefly after deciding.";