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
116 changes: 116 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion crates/goose-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,7 @@ pub async fn cli() -> Result<()> {
interactive: true,
quiet: false,
sub_recipes: None,
final_output_response: None,
})
.await;
setup_logging(
Expand Down Expand Up @@ -736,7 +737,7 @@ pub async fn cli() -> Result<()> {
quiet,
additional_sub_recipes,
}) => {
let (input_config, session_settings, sub_recipes) = match (
let (input_config, session_settings, sub_recipes, final_output_response) = match (
instructions,
input_text,
recipe,
Expand All @@ -755,6 +756,7 @@ pub async fn cli() -> Result<()> {
},
None,
None,
None,
)
}
(Some(file), _, _) => {
Expand All @@ -773,6 +775,7 @@ pub async fn cli() -> Result<()> {
},
None,
None,
None,
)
}
(_, Some(text), _) => (
Expand All @@ -783,6 +786,7 @@ pub async fn cli() -> Result<()> {
},
None,
None,
None,
),
(_, _, Some(recipe_name)) => {
if explain {
Expand Down Expand Up @@ -822,6 +826,7 @@ pub async fn cli() -> Result<()> {
interactive, // Use the interactive flag from the Run command
quiet,
sub_recipes,
final_output_response,
})
.await;

Expand Down Expand Up @@ -941,6 +946,7 @@ pub async fn cli() -> Result<()> {
interactive: true, // Default case is always interactive
quiet: false,
sub_recipes: None,
final_output_response: None,
})
.await;
setup_logging(
Expand Down
1 change: 1 addition & 0 deletions crates/goose-cli/src/commands/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub async fn agent_generator(
scheduled_job_id: None,
quiet: false,
sub_recipes: None,
final_output_response: None,
})
.await;

Expand Down
43 changes: 39 additions & 4 deletions crates/goose-cli/src/recipes/extract_from_cli.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
use std::path::PathBuf;

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

use crate::{cli::InputConfig, recipes::recipe::load_recipe_as_template, session::SessionSettings};

#[allow(clippy::type_complexity)]
pub fn extract_recipe_info_from_cli(
recipe_name: String,
params: Vec<(String, String)>,
additional_sub_recipes: Vec<String>,
) -> Result<(InputConfig, Option<SessionSettings>, Option<Vec<SubRecipe>>)> {
) -> Result<(
InputConfig,
Option<SessionSettings>,
Option<Vec<SubRecipe>>,
Option<Response>,
)> {
let recipe = load_recipe_as_template(&recipe_name, params).unwrap_or_else(|err| {
eprintln!("{}: {}", console::style("Error").red().bold(), err);
std::process::exit(1);
Expand Down Expand Up @@ -43,6 +49,7 @@ pub fn extract_recipe_info_from_cli(
temperature: s.temperature,
}),
Some(all_sub_recipes),
recipe.response,
))
}

Expand All @@ -69,7 +76,7 @@ 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, settings, sub_recipes) =
let (input_config, settings, sub_recipes, response) =
extract_recipe_info_from_cli(recipe_name, params, Vec::new()).unwrap();

assert_eq!(input_config.contents, Some("test_prompt".to_string()));
Expand All @@ -91,6 +98,17 @@ mod tests {
assert_eq!(sub_recipes[0].path, "existing_sub_recipe.yaml".to_string());
assert_eq!(sub_recipes[0].name, "existing_sub_recipe".to_string());
assert!(sub_recipes[0].values.is_none());
assert!(response.is_some());
let response = response.unwrap();
assert_eq!(
response.json_schema,
Some(serde_json::json!({
"type": "object",
"properties": {
"result": {"type": "string"}
}
}))
);
}

#[test]
Expand All @@ -103,7 +121,7 @@ mod tests {
"another/sub_recipe2.yaml".to_string(),
];

let (input_config, settings, sub_recipes) =
let (input_config, settings, sub_recipes, response) =
extract_recipe_info_from_cli(recipe_name, params, additional_sub_recipes).unwrap();

assert_eq!(input_config.contents, Some("test_prompt".to_string()));
Expand Down Expand Up @@ -131,6 +149,17 @@ mod tests {
assert_eq!(sub_recipes[2].path, "another/sub_recipe2.yaml".to_string());
assert_eq!(sub_recipes[2].name, "sub_recipe2".to_string());
assert!(sub_recipes[2].values.is_none());
assert!(response.is_some());
let response = response.unwrap();
assert_eq!(
response.json_schema,
Some(serde_json::json!({
"type": "object",
"properties": {
"result": {"type": "string"}
}
}))
);
}

fn create_recipe() -> (TempDir, PathBuf) {
Expand All @@ -151,6 +180,12 @@ settings:
sub_recipes:
- path: existing_sub_recipe.yaml
name: existing_sub_recipe
response:
json_schema:
type: object
properties:
result:
type: string
"#;
let temp_dir = tempfile::tempdir().unwrap();
let recipe_path: std::path::PathBuf = temp_dir.path().join("test_recipe.yaml");
Expand Down
11 changes: 10 additions & 1 deletion crates/goose-cli/src/session/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use goose::agents::extension::ExtensionError;
use goose::agents::Agent;
use goose::config::{Config, ExtensionConfig, ExtensionConfigManager};
use goose::providers::create;
use goose::recipe::SubRecipe;
use goose::recipe::{Response, SubRecipe};
use goose::session;
use goose::session::Identifier;
use mcp_client::transport::Error as McpClientError;
Expand Down Expand Up @@ -49,6 +49,8 @@ pub struct SessionBuilderConfig {
pub quiet: bool,
/// Sub-recipes to add to the session
pub sub_recipes: Option<Vec<SubRecipe>>,
/// Final output expected response
pub final_output_response: Option<Response>,
}

/// Offers to help debug an extension failure by creating a minimal debugging session
Expand Down Expand Up @@ -180,6 +182,11 @@ pub async fn build_session(session_config: SessionBuilderConfig) -> Session {
if let Some(sub_recipes) = session_config.sub_recipes {
agent.add_sub_recipes(sub_recipes).await;
}

if let Some(final_output_response) = session_config.final_output_response {
agent.add_final_output_tool(final_output_response).await;
}

let new_provider = match create(&provider_name, model_config) {
Ok(provider) => provider,
Err(e) => {
Expand Down Expand Up @@ -520,6 +527,7 @@ mod tests {
interactive: true,
quiet: false,
sub_recipes: None,
final_output_response: None,
};

assert_eq!(config.extensions.len(), 1);
Expand Down Expand Up @@ -549,6 +557,7 @@ mod tests {
assert!(config.scheduled_job_id.is_none());
assert!(!config.interactive);
assert!(!config.quiet);
assert!(config.final_output_response.is_none());
}

#[tokio::test]
Expand Down
Loading
Loading