diff --git a/crates/goose-cli/src/session/builder.rs b/crates/goose-cli/src/session/builder.rs index b5d3da1d7f45..7f39f768d97f 100644 --- a/crates/goose-cli/src/session/builder.rs +++ b/crates/goose-cli/src/session/builder.rs @@ -7,6 +7,7 @@ use goose::recipe::{Response, SubRecipe}; use goose::session; use goose::session::Identifier; use mcp_client::transport::Error as McpClientError; +use rustyline::EditMode; use std::process; use std::sync::Arc; @@ -130,6 +131,7 @@ async fn offer_extension_debugging_help( false, None, None, + None, ); // Process the debugging request @@ -369,6 +371,19 @@ pub async fn build_session(session_config: SessionBuilderConfig) -> Session { } } + // Determine editor mode + let edit_mode = config + .get_param::("EDIT_MODE") + .ok() + .and_then(|edit_mode| match edit_mode.to_lowercase().as_str() { + "emacs" => Some(EditMode::Emacs), + "vi" => Some(EditMode::Vi), + _ => { + eprintln!("Invalid EDIT_MODE specified, defaulting to Emacs"); + None + } + }); + // Create new session let mut session = Session::new( agent, @@ -376,6 +391,7 @@ pub async fn build_session(session_config: SessionBuilderConfig) -> Session { session_config.debug, session_config.scheduled_job_id.clone(), session_config.max_turns, + edit_mode, ); // Add extensions if provided diff --git a/crates/goose-cli/src/session/mod.rs b/crates/goose-cli/src/session/mod.rs index bec2a2db9386..5c1bfc9ec336 100644 --- a/crates/goose-cli/src/session/mod.rs +++ b/crates/goose-cli/src/session/mod.rs @@ -31,6 +31,7 @@ use mcp_core::protocol::JsonRpcMessage; use mcp_core::protocol::JsonRpcNotification; use rand::{distributions::Alphanumeric, Rng}; +use rustyline::EditMode; use serde_json::Value; use std::collections::HashMap; use std::path::PathBuf; @@ -53,6 +54,7 @@ pub struct Session { run_mode: RunMode, scheduled_job_id: Option, // ID of the scheduled job that triggered this session max_turns: Option, + edit_mode: Option, } // Cache structure for completion data @@ -115,6 +117,7 @@ impl Session { debug: bool, scheduled_job_id: Option, max_turns: Option, + edit_mode: Option, ) -> Self { let messages = if let Some(session_file) = &session_file { match session::read_messages(session_file) { @@ -138,6 +141,7 @@ impl Session { run_mode: RunMode::Normal, scheduled_job_id, max_turns, + edit_mode, } } @@ -364,9 +368,15 @@ impl Session { self.update_completion_cache().await?; // Create a new editor with our custom completer - let config = rustyline::Config::builder() - .completion_type(rustyline::CompletionType::Circular) - .build(); + let builder = + rustyline::Config::builder().completion_type(rustyline::CompletionType::Circular); + let builder = if let Some(edit_mode) = self.edit_mode { + builder.edit_mode(edit_mode) + } else { + // Default to Emacs mode if no edit mode is set + builder.edit_mode(EditMode::Emacs) + }; + let config = builder.build(); let mut editor = rustyline::Editor::::with_config( config,