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
53 changes: 11 additions & 42 deletions crates/goose-cli/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use anyhow::Result;
use clap::{Args, CommandFactory, Parser, Subcommand};
use clap_complete::{generate, Shell as ClapShell};
use goose::config::{Config, ExtensionConfig};
use goose::config::Config;
use goose::posthog::get_telemetry_choice;
use goose::recipe::Recipe;
use goose_mcp::mcp_server_runner::{serve, McpCommand};
use goose_mcp::{
AutoVisualiserRouter, ComputerControllerServer, DeveloperServer, MemoryServer, TutorialServer,
Expand All @@ -25,7 +26,7 @@ use crate::commands::schedule::{
use crate::commands::session::{handle_session_list, handle_session_remove};
use crate::recipes::extract_from_cli::extract_recipe_info_from_cli;
use crate::recipes::recipe::{explain_recipe, render_recipe_as_yaml};
use crate::session::{build_session, SessionBuilderConfig, SessionSettings};
use crate::session::{build_session, SessionBuilderConfig};
use goose::session::session_manager::SessionType;
use goose::session::SessionManager;
use goose_bench::bench_config::BenchRunConfig;
Expand Down Expand Up @@ -941,18 +942,9 @@ enum CliProviderVariant {
#[derive(Debug)]
pub struct InputConfig {
pub contents: Option<String>,
pub extensions_override: Option<Vec<ExtensionConfig>>,
pub additional_system_prompt: Option<String>,
}

#[derive(Debug)]
pub struct RecipeInfo {
pub session_settings: Option<SessionSettings>,
pub sub_recipes: Option<Vec<goose::recipe::SubRecipe>>,
pub final_output_response: Option<goose::recipe::Response>,
pub retry_config: Option<goose::agents::types::RetryConfig>,
}

fn get_command_name(command: &Option<Command>) -> &'static str {
match command {
Some(Command::Configure {}) => "configure",
Expand Down Expand Up @@ -1093,9 +1085,8 @@ async fn handle_interactive_session(
extensions: extension_opts.extensions,
streamable_http_extensions: extension_opts.streamable_http_extensions,
builtins: extension_opts.builtins,
extensions_override: None,
recipe: None,
additional_system_prompt: None,
settings: None,
provider: None,
model: None,
debug: session_opts.debug,
Expand All @@ -1104,9 +1095,6 @@ async fn handle_interactive_session(
scheduled_job_id: None,
interactive: true,
quiet: false,
sub_recipes: None,
final_output_response: None,
retry_config: None,
output_format: "text".to_string(),
})
.await;
Expand Down Expand Up @@ -1163,7 +1151,7 @@ async fn log_session_completion(
fn parse_run_input(
input_opts: &InputOptions,
quiet: bool,
) -> Result<Option<(InputConfig, Option<RecipeInfo>)>> {
) -> Result<Option<(InputConfig, Option<Recipe>)>> {
match (
&input_opts.instructions,
&input_opts.input_text,
Expand All @@ -1177,7 +1165,6 @@ fn parse_run_input(
Ok(Some((
InputConfig {
contents: Some(contents),
extensions_override: None,
additional_system_prompt: input_opts.system.clone(),
},
None,
Expand All @@ -1194,7 +1181,6 @@ fn parse_run_input(
Ok(Some((
InputConfig {
contents: Some(contents),
extensions_override: None,
additional_system_prompt: None,
},
None,
Expand All @@ -1203,7 +1189,6 @@ fn parse_run_input(
(_, Some(text), _) => Ok(Some((
InputConfig {
contents: Some(text.clone()),
extensions_override: None,
additional_system_prompt: input_opts.system.clone(),
},
None,
Expand Down Expand Up @@ -1247,13 +1232,13 @@ fn parse_run_input(
"Recipe execution started"
);

let (input_config, recipe_info) = extract_recipe_info_from_cli(
let (input_config, recipe) = extract_recipe_info_from_cli(
recipe_name.clone(),
input_opts.params.clone(),
input_opts.additional_sub_recipes.clone(),
quiet,
)?;
Ok(Some((input_config, Some(recipe_info))))
Ok(Some((input_config, Some(recipe))))
}
(None, None, None) => {
eprintln!("Error: Must provide either --instructions (-i), --text (-t), or --recipe. Use -i - for stdin.");
Expand All @@ -1277,7 +1262,7 @@ async fn handle_run_command(

let parsed = parse_run_input(&input_opts, output_opts.quiet)?;

let Some((input_config, recipe_info)) = parsed else {
let Some((input_config, recipe)) = parsed else {
return Ok(());
};

Expand All @@ -1302,11 +1287,8 @@ async fn handle_run_command(
extensions: extension_opts.extensions,
streamable_http_extensions: extension_opts.streamable_http_extensions,
builtins: extension_opts.builtins,
extensions_override: input_config.extensions_override,
recipe: recipe.clone(),
additional_system_prompt: input_config.additional_system_prompt,
settings: recipe_info
.as_ref()
.and_then(|r| r.session_settings.clone()),
provider: model_opts.provider,
model: model_opts.model,
debug: session_opts.debug,
Expand All @@ -1315,11 +1297,6 @@ async fn handle_run_command(
scheduled_job_id: run_behavior.scheduled_job_id,
interactive: run_behavior.interactive,
quiet: output_opts.quiet,
sub_recipes: recipe_info.as_ref().and_then(|r| r.sub_recipes.clone()),
final_output_response: recipe_info
.as_ref()
.and_then(|r| r.final_output_response.clone()),
retry_config: recipe_info.as_ref().and_then(|r| r.retry_config.clone()),
output_format: output_opts.output_format,
})
.await;
Expand All @@ -1328,11 +1305,7 @@ async fn handle_run_command(
session.interactive(input_config.contents).await
} else if let Some(contents) = input_config.contents {
let session_start = std::time::Instant::now();
let session_type = if recipe_info.is_some() {
"recipe"
} else {
"run"
};
let session_type = if recipe.is_some() { "recipe" } else { "run" };

tracing::info!(
counter.goose.session_starts = 1,
Expand Down Expand Up @@ -1438,9 +1411,8 @@ async fn handle_default_session() -> Result<()> {
extensions: Vec::new(),
streamable_http_extensions: Vec::new(),
builtins: Vec::new(),
extensions_override: None,
recipe: None,
additional_system_prompt: None,
settings: None::<SessionSettings>,
provider: None,
model: None,
debug: false,
Expand All @@ -1449,9 +1421,6 @@ async fn handle_default_session() -> Result<()> {
scheduled_job_id: None,
interactive: true,
quiet: false,
sub_recipes: None,
final_output_response: None,
retry_config: None,
output_format: "text".to_string(),
})
.await;
Expand Down
6 changes: 1 addition & 5 deletions crates/goose-cli/src/commands/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,8 @@ pub async fn agent_generator(
extensions: requirements.external,
streamable_http_extensions: requirements.streamable_http,
builtins: requirements.builtin,
extensions_override: None,
recipe: None,
additional_system_prompt: None,
settings: None,
provider: None,
model: None,
debug: false,
Expand All @@ -52,9 +51,6 @@ pub async fn agent_generator(
scheduled_job_id: None,
max_turns: None,
quiet: false,
sub_recipes: None,
final_output_response: None,
retry_config: None,
output_format: "text".to_string(),
})
.await;
Expand Down
54 changes: 21 additions & 33 deletions crates/goose-cli/src/recipes/extract_from_cli.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
use std::path::PathBuf;

use anyhow::{anyhow, Result};
use goose::recipe::SubRecipe;
use goose::recipe::{Recipe, SubRecipe};

use crate::cli::InputConfig;
use crate::recipes::print_recipe::print_recipe_info;
use crate::recipes::recipe::load_recipe;
use crate::recipes::search_recipe::load_recipe_file;
use crate::{
cli::{InputConfig, RecipeInfo},
session::SessionSettings,
};

pub fn extract_recipe_info_from_cli(
recipe_name: String,
params: Vec<(String, String)>,
additional_sub_recipes: Vec<String>,
quiet: bool,
) -> Result<(InputConfig, RecipeInfo)> {
let recipe = load_recipe(&recipe_name, params.clone()).unwrap_or_else(|err| {
) -> Result<(InputConfig, Recipe)> {
let mut recipe = load_recipe(&recipe_name, params.clone()).unwrap_or_else(|err| {
eprintln!("{}: {}", console::style("Error").red().bold(), err);
std::process::exit(1);
});
if !quiet {
print_recipe_info(&recipe, params);
}
let mut all_sub_recipes = recipe.sub_recipes.clone().unwrap_or_default();

if !additional_sub_recipes.is_empty() {
let mut all_sub_recipes = recipe.sub_recipes.clone().unwrap_or_default();
for sub_recipe_name in additional_sub_recipes {
match load_recipe_file(&sub_recipe_name) {
Ok(recipe_file) => {
Expand All @@ -49,25 +47,15 @@ pub fn extract_recipe_info_from_cli(
}
}
}
recipe.sub_recipes = Some(all_sub_recipes);
}
let input_config = InputConfig {
contents: recipe.prompt.filter(|s| !s.trim().is_empty()),
extensions_override: recipe.extensions,
additional_system_prompt: recipe.instructions,
};

let recipe_info = RecipeInfo {
session_settings: recipe.settings.map(|s| SessionSettings {
goose_provider: s.goose_provider,
goose_model: s.goose_model,
temperature: s.temperature,
}),
sub_recipes: Some(all_sub_recipes),
final_output_response: recipe.response,
retry_config: recipe.retry,
let input_config = InputConfig {
contents: recipe.prompt.clone().filter(|s| !s.trim().is_empty()),
additional_system_prompt: recipe.instructions.clone(),
};

Ok((input_config, recipe_info))
Ok((input_config, recipe))
}

fn extract_recipe_name(recipe_identifier: &str) -> String {
Expand Down Expand Up @@ -98,18 +86,18 @@ mod tests {
let params = vec![("name".to_string(), "my_value".to_string())];
let recipe_name = recipe_path.to_str().unwrap().to_string();

let (input_config, recipe_info) =
let (input_config, recipe) =
extract_recipe_info_from_cli(recipe_name, params, Vec::new(), false).unwrap();
let settings = recipe_info.session_settings;
let sub_recipes = recipe_info.sub_recipes;
let response = recipe_info.final_output_response;
let settings = recipe.settings;
let sub_recipes = recipe.sub_recipes;
let response = recipe.response;

assert_eq!(input_config.contents, Some("test_prompt".to_string()));
assert_eq!(
input_config.additional_system_prompt,
Some("test_instructions my_value".to_string())
);
assert!(input_config.extensions_override.is_none());
assert!(recipe.extensions.is_none());

assert!(settings.is_some());
let settings = settings.unwrap();
Expand Down Expand Up @@ -162,19 +150,19 @@ mod tests {
sub_recipe2_path.to_string_lossy().to_string(),
];

let (input_config, recipe_info) =
let (input_config, recipe) =
extract_recipe_info_from_cli(recipe_name, params, additional_sub_recipes, false)
.unwrap();
let settings = recipe_info.session_settings;
let sub_recipes = recipe_info.sub_recipes;
let response = recipe_info.final_output_response;
let settings = recipe.settings;
let sub_recipes = recipe.sub_recipes;
let response = recipe.response;

assert_eq!(input_config.contents, Some("test_prompt".to_string()));
assert_eq!(
input_config.additional_system_prompt,
Some("test_instructions my_value".to_string())
);
assert!(input_config.extensions_override.is_none());
assert!(recipe.extensions.is_none());

assert!(settings.is_some());
let settings = settings.unwrap();
Expand Down
Loading
Loading