refactor: remove agent flavours, move provider to Agent (#2091)

This commit is contained in:
Salman Mohammed
2025-04-09 15:02:47 -04:00
committed by GitHub
parent a8cbd81c61
commit 513d5c8f5a
30 changed files with 1297 additions and 2272 deletions
-8
View File
@@ -3,7 +3,6 @@ use clap::{Args, Parser, Subcommand};
use goose::config::Config;
use crate::commands::agent_version::AgentCommand;
use crate::commands::bench::agent_generator;
use crate::commands::configure::handle_configure;
use crate::commands::info::handle_info;
@@ -279,9 +278,6 @@ enum Command {
builtin: Vec<String>,
},
/// List available agent versions
Agents(AgentCommand),
/// Update the Goose CLI version
#[command(about = "Update the goose CLI version")]
Update {
@@ -417,10 +413,6 @@ pub async fn cli() -> Result<()> {
return Ok(());
}
Some(Command::Agents(cmd)) => {
cmd.run()?;
return Ok(());
}
Some(Command::Update {
canary,
reconfigure,
@@ -1,33 +0,0 @@
use anyhow::Result;
use clap::Args;
use goose::agents::AgentFactory;
use std::fmt::Write;
#[derive(Args)]
pub struct AgentCommand {}
impl AgentCommand {
pub fn run(&self) -> Result<()> {
let mut output = String::new();
writeln!(output, "Available agent versions:")?;
let versions = AgentFactory::available_versions();
let default_version = AgentFactory::default_version();
let configured_version = AgentFactory::configured_version();
for version in versions {
if version == default_version && version == configured_version {
writeln!(output, "* {} (default)", version)?;
} else if version == default_version {
writeln!(output, " {} (default)", version)?;
} else if version == configured_version {
writeln!(output, "* {}", version)?;
} else {
writeln!(output, " {}", version)?;
}
}
print!("{}", output);
Ok(())
}
}
+12 -11
View File
@@ -3,7 +3,8 @@ use console::style;
use goose::agents::{extension::Envs, ExtensionConfig};
use goose::config::extensions::name_to_key;
use goose::config::{
Config, ConfigError, ExperimentManager, ExtensionEntry, ExtensionManager, PermissionManager,
Config, ConfigError, ExperimentManager, ExtensionConfigManager, ExtensionEntry,
PermissionManager,
};
use goose::message::Message;
use goose::providers::{create, providers};
@@ -63,7 +64,7 @@ pub async fn handle_configure() -> Result<(), Box<dyn Error>> {
);
// Since we are setting up for the first time, we'll also enable the developer system
// This operation is best-effort and errors are ignored
ExtensionManager::set(ExtensionEntry {
ExtensionConfigManager::set(ExtensionEntry {
enabled: true,
config: ExtensionConfig::Builtin {
name: "developer".to_string(),
@@ -392,7 +393,7 @@ pub async fn configure_provider_dialog() -> Result<bool, Box<dyn Error>> {
/// Configure extensions that can be used with goose
/// Dialog for toggling which extensions are enabled/disabled
pub fn toggle_extensions_dialog() -> Result<(), Box<dyn Error>> {
let extensions = ExtensionManager::get_all()?;
let extensions = ExtensionConfigManager::get_all()?;
if extensions.is_empty() {
cliclack::outro(
@@ -430,7 +431,7 @@ pub fn toggle_extensions_dialog() -> Result<(), Box<dyn Error>> {
// Update enabled status for each extension
for name in extension_status.iter().map(|(name, _)| name) {
ExtensionManager::set_enabled(
ExtensionConfigManager::set_enabled(
&name_to_key(name),
selected.iter().any(|s| s.as_str() == name),
)?;
@@ -502,7 +503,7 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
let display_name = get_display_name(&extension);
ExtensionManager::set(ExtensionEntry {
ExtensionConfigManager::set(ExtensionEntry {
enabled: true,
config: ExtensionConfig::Builtin {
name: extension.clone(),
@@ -514,7 +515,7 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
cliclack::outro(format!("Enabled {} extension", style(extension).green()))?;
}
"stdio" => {
let extensions = ExtensionManager::get_all_names()?;
let extensions = ExtensionConfigManager::get_all_names()?;
let name: String = cliclack::input("What would you like to call this extension?")
.placeholder("my-extension")
.validate(move |input: &String| {
@@ -590,7 +591,7 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
}
}
ExtensionManager::set(ExtensionEntry {
ExtensionConfigManager::set(ExtensionEntry {
enabled: true,
config: ExtensionConfig::Stdio {
name: name.clone(),
@@ -605,7 +606,7 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
cliclack::outro(format!("Added {} extension", style(name).green()))?;
}
"sse" => {
let extensions = ExtensionManager::get_all_names()?;
let extensions = ExtensionConfigManager::get_all_names()?;
let name: String = cliclack::input("What would you like to call this extension?")
.placeholder("my-remote-extension")
.validate(move |input: &String| {
@@ -677,7 +678,7 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
}
}
ExtensionManager::set(ExtensionEntry {
ExtensionConfigManager::set(ExtensionEntry {
enabled: true,
config: ExtensionConfig::Sse {
name: name.clone(),
@@ -697,7 +698,7 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
}
pub fn remove_extension_dialog() -> Result<(), Box<dyn Error>> {
let extensions = ExtensionManager::get_all()?;
let extensions = ExtensionConfigManager::get_all()?;
// Create a list of extension names and their enabled status
let extension_status: Vec<(String, bool)> = extensions
@@ -739,7 +740,7 @@ pub fn remove_extension_dialog() -> Result<(), Box<dyn Error>> {
.interact()?;
for name in selected {
ExtensionManager::remove(&name_to_key(name))?;
ExtensionConfigManager::remove(&name_to_key(name))?;
let mut permission_manager = PermissionManager::default();
permission_manager.remove_extension(&name_to_key(name));
cliclack::outro(format!("Removed {} extension", style(name).green()))?;
-1
View File
@@ -1,4 +1,3 @@
pub mod agent_version;
pub mod bench;
pub mod configure;
pub mod info;
+4 -5
View File
@@ -1,7 +1,7 @@
use console::style;
use goose::agents::extension::ExtensionError;
use goose::agents::AgentFactory;
use goose::config::{Config, ExtensionManager};
use goose::agents::Agent;
use goose::config::{Config, ExtensionConfigManager};
use goose::session;
use goose::session::Identifier;
use mcp_client::transport::Error as McpClientError;
@@ -33,8 +33,7 @@ pub async fn build_session(
goose::providers::create(&provider_name, model_config).expect("Failed to create provider");
// Create the agent
let mut agent = AgentFactory::create(&AgentFactory::configured_version(), provider)
.expect("Failed to create agent");
let mut agent = Agent::new(provider);
// Handle session file resolution and resuming
let session_file = if resume {
@@ -93,7 +92,7 @@ pub async fn build_session(
// Setup extensions for the agent
// Extensions need to be added after the session is created because we change directory when resuming a session
for extension in ExtensionManager::get_all().expect("should load extensions") {
for extension in ExtensionConfigManager::get_all().expect("should load extensions") {
if extension.enabled {
let config = extension.config.clone();
agent
+8 -8
View File
@@ -38,7 +38,7 @@ pub enum RunMode {
}
pub struct Session {
agent: Box<dyn Agent>,
agent: Agent,
messages: Vec<Message>,
session_file: PathBuf,
// Cache for completion data - using std::sync for thread safety without async
@@ -76,7 +76,7 @@ pub enum PlannerResponseType {
/// question.
pub async fn classify_planner_response(
message_text: String,
provider: Arc<Box<dyn Provider>>,
provider: Arc<dyn Provider>,
) -> Result<PlannerResponseType> {
let prompt = format!("The text below is the output from an AI model which can either provide a plan or list of clarifying questions. Based on the text below, decide if the output is a \"plan\" or \"clarifying questions\".\n---\n{message_text}");
@@ -101,7 +101,7 @@ pub async fn classify_planner_response(
}
impl Session {
pub fn new(agent: Box<dyn Agent>, session_file: PathBuf, debug: bool) -> Self {
pub fn new(agent: Agent, session_file: PathBuf, debug: bool) -> Self {
let messages = match session::read_messages(&session_file) {
Ok(msgs) => msgs,
Err(e) => {
@@ -278,7 +278,7 @@ impl Session {
async fn process_message(&mut self, message: String) -> Result<()> {
self.messages.push(Message::user().with_text(&message));
// Get the provider from the agent for description generation
let provider = self.agent.provider().await;
let provider = self.agent.provider();
// Persist messages with provider for automatic description generation
session::persist_messages(&self.session_file, &self.messages, Some(provider)).await?;
@@ -350,7 +350,7 @@ impl Session {
self.messages.push(Message::user().with_text(&content));
// Get the provider from the agent for description generation
let provider = self.agent.provider().await;
let provider = self.agent.provider();
// Persist messages with provider for automatic description generation
session::persist_messages(
@@ -535,7 +535,7 @@ impl Session {
async fn plan_with_reasoner_model(
&mut self,
plan_messages: Vec<Message>,
reasoner: Box<dyn Provider + Send + Sync>,
reasoner: Arc<dyn Provider>,
) -> Result<(), anyhow::Error> {
let plan_prompt = self.agent.get_plan_prompt().await?;
output::show_thinking();
@@ -543,7 +543,7 @@ impl Session {
output::render_message(&plan_response, self.debug);
output::hide_thinking();
let planner_response_type =
classify_planner_response(plan_response.as_concat_text(), self.agent.provider().await)
classify_planner_response(plan_response.as_concat_text(), self.agent.provider())
.await?;
match planner_response_type {
@@ -857,7 +857,7 @@ impl Session {
}
}
fn get_reasoner() -> Result<Box<dyn Provider + Send + Sync>, anyhow::Error> {
fn get_reasoner() -> Result<Arc<dyn Provider>, anyhow::Error> {
use goose::model::ModelConfig;
use goose::providers::create;