Skip to content

Commit

Permalink
feat: interactive after run
Browse files Browse the repository at this point in the history
This adds a flag -s/--interactive that drops into an
interactive session after starting from a CLI/file
message
  • Loading branch information
baxen committed Feb 25, 2025
1 parent d0110e2 commit 3485f75
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 13 deletions.
18 changes: 16 additions & 2 deletions crates/goose-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ enum Command {
)]
input_text: Option<String>,

/// Continue in interactive mode after processing input
#[arg(
short = 's',
long = "interactive",
help = "Continue in interactive mode after processing initial input"
)]
interactive: bool,

/// Name for this run session
#[arg(
short,
Expand Down Expand Up @@ -182,12 +190,13 @@ async fn main() -> Result<()> {
}) => {
let mut session = build_session(name, resume, extension, builtin).await;
setup_logging(session.session_file().file_stem().and_then(|s| s.to_str()))?;
let _ = session.start().await;
let _ = session.interactive(None).await;
return Ok(());
}
Some(Command::Run {
instructions,
input_text,
interactive,
name,
resume,
extension,
Expand All @@ -213,7 +222,12 @@ async fn main() -> Result<()> {
};
let mut session = build_session(name, resume, extension, builtin).await;
setup_logging(session.session_file().file_stem().and_then(|s| s.to_str()))?;
let _ = session.headless_start(contents.clone()).await;

if interactive {
let _ = session.interactive(Some(contents)).await?;
} else {
let _ = session.headless(contents).await?;
}
return Ok(());
}
Some(Command::Agents(cmd)) => {
Expand Down
33 changes: 22 additions & 11 deletions crates/goose-cli/src/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,21 @@ impl Session {
Ok(())
}

pub async fn start(&mut self) -> Result<()> {
/// Process a single message and get the response
async fn process_message(&mut self, message: String) -> Result<()> {
self.messages.push(Message::user().with_text(&message));
storage::persist_messages(&self.session_file, &self.messages)?;
self.process_agent_response(false).await?;
Ok(())
}

/// Start an interactive session, optionally with an initial message
pub async fn interactive(&mut self, message: Option<String>) -> Result<()> {
// Process initial message if provided
if let Some(msg) = message {
self.process_message(msg).await?;
}

let mut editor = rustyline::Editor::<(), rustyline::history::DefaultHistory>::new()?;

// Load history from messages
Expand All @@ -129,7 +143,7 @@ impl Session {
storage::persist_messages(&self.session_file, &self.messages)?;

output::show_thinking();
self.process_agent_response().await?;
self.process_agent_response(true).await?;
output::hide_thinking();
}
input::InputResult::Exit => break,
Expand Down Expand Up @@ -184,15 +198,12 @@ impl Session {
Ok(())
}

pub async fn headless_start(&mut self, initial_message: String) -> Result<()> {
self.messages
.push(Message::user().with_text(&initial_message));
storage::persist_messages(&self.session_file, &self.messages)?;
self.process_agent_response().await?;
Ok(())
/// Process a single message and exit
pub async fn headless(&mut self, message: String) -> Result<()> {
self.process_message(message).await
}

async fn process_agent_response(&mut self) -> Result<()> {
async fn process_agent_response(&mut self, interactive: bool) -> Result<()> {
let mut stream = self.agent.reply(&self.messages).await?;

use futures::StreamExt;
Expand All @@ -203,9 +214,9 @@ impl Session {
Some(Ok(message)) => {
self.messages.push(message.clone());
storage::persist_messages(&self.session_file, &self.messages)?;
output::hide_thinking();
if interactive {output::hide_thinking()};
output::render_message(&message);
output::show_thinking();
if interactive {output::show_thinking()};
}
Some(Err(e)) => {
eprintln!("Error: {}", e);
Expand Down

0 comments on commit 3485f75

Please sign in to comment.