Add option to run extensions in a container (#6590)

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Jack Amadeo
2026-01-27 16:30:51 -05:00
committed by GitHub
parent 03109aabf4
commit 3fcf022236
12 changed files with 194 additions and 34 deletions
+12
View File
@@ -27,6 +27,7 @@ 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};
use goose::agents::Container;
use goose::session::session_manager::SessionType;
use goose::session::SessionManager;
use goose_bench::bench_config::BenchRunConfig;
@@ -101,6 +102,14 @@ pub struct SessionOptions {
long_help = "Set a limit on how many turns (iterations) the agent can take without asking for user input to continue."
)]
pub max_turns: Option<u32>,
#[arg(
long = "container",
value_name = "CONTAINER_ID",
help = "Docker container ID to run extensions inside",
long_help = "Run extensions (stdio and built-in) inside the specified container. The extension must exist in the container. For built-in extensions, goose must be installed inside the container."
)]
pub container: Option<String>,
}
/// Extension configuration options shared between Session and Run commands
@@ -1125,6 +1134,7 @@ async fn handle_interactive_session(
interactive: true,
quiet: false,
output_format: "text".to_string(),
container: session_opts.container.map(Container::new),
})
.await;
@@ -1328,6 +1338,7 @@ async fn handle_run_command(
interactive: run_behavior.interactive,
quiet: output_opts.quiet,
output_format: output_opts.output_format,
container: session_opts.container.map(Container::new),
})
.await;
@@ -1453,6 +1464,7 @@ async fn handle_default_session() -> Result<()> {
interactive: true,
quiet: false,
output_format: "text".to_string(),
container: None,
})
.await;
session.interactive(None).await
+1
View File
@@ -53,6 +53,7 @@ pub async fn agent_generator(
max_turns: None,
quiet: false,
output_format: "text".to_string(),
container: None,
})
.await;
+10 -1
View File
@@ -1,7 +1,7 @@
use super::output;
use super::CliSession;
use console::style;
use goose::agents::Agent;
use goose::agents::{Agent, Container};
use goose::config::get_enabled_extensions;
use goose::config::resolve_extensions_for_new_session;
use goose::config::{
@@ -114,6 +114,8 @@ pub struct SessionBuilderConfig {
pub quiet: bool,
/// Output format (text, json)
pub output_format: String,
/// Docker container to run stdio extensions inside
pub container: Option<Container>,
}
/// Manual implementation of Default to ensure proper initialization of output_format
@@ -139,6 +141,7 @@ impl Default for SessionBuilderConfig {
interactive: false,
quiet: false,
output_format: "text".to_string(),
container: None,
}
}
}
@@ -371,6 +374,11 @@ pub async fn build_session(session_config: SessionBuilderConfig) -> CliSession {
let config = Config::global();
let agent: Agent = Agent::new();
if session_config.container.is_some() {
agent.set_container(session_config.container.clone()).await;
}
let session_manager = agent.config.session_manager.clone();
let (saved_provider, saved_model_config) = if session_config.resume {
@@ -678,6 +686,7 @@ mod tests {
interactive: true,
quiet: false,
output_format: "text".to_string(),
container: None,
};
assert_eq!(config.extensions.len(), 1);