Streamable HTTP CLI flag (#3394)

This commit is contained in:
Angie Jones
2025-07-13 18:09:04 -05:00
committed by GitHub
parent 192a8077dc
commit 1987956422
7 changed files with 203 additions and 10 deletions

View File

@@ -341,6 +341,16 @@ enum Command {
)]
remote_extensions: Vec<String>,
/// Add streamable HTTP extensions with a URL
#[arg(
long = "with-streamable-http-extension",
value_name = "URL",
help = "Add streamable HTTP extensions (can be specified multiple times)",
long_help = "Add streamable HTTP extensions from a URL. Can be specified multiple times. Format: 'url...'",
action = clap::ArgAction::Append
)]
streamable_http_extensions: Vec<String>,
/// Add builtin extensions by name
#[arg(
long = "with-builtin",
@@ -509,6 +519,16 @@ enum Command {
)]
remote_extensions: Vec<String>,
/// Add streamable HTTP extensions
#[arg(
long = "with-streamable-http-extension",
value_name = "URL",
help = "Add streamable HTTP extensions (can be specified multiple times)",
long_help = "Add streamable HTTP extensions. Can be specified multiple times. Format: 'url...'",
action = clap::ArgAction::Append
)]
streamable_http_extensions: Vec<String>,
/// Add builtin extensions by name
#[arg(
long = "with-builtin",
@@ -674,6 +694,7 @@ pub async fn cli() -> Result<()> {
max_turns,
extensions,
remote_extensions,
streamable_http_extensions,
builtins,
}) => {
return match command {
@@ -714,6 +735,7 @@ pub async fn cli() -> Result<()> {
no_session: false,
extensions,
remote_extensions,
streamable_http_extensions,
builtins,
extensions_override: None,
additional_system_prompt: None,
@@ -774,6 +796,7 @@ pub async fn cli() -> Result<()> {
max_turns,
extensions,
remote_extensions,
streamable_http_extensions,
builtins,
params,
explain,
@@ -863,6 +886,7 @@ pub async fn cli() -> Result<()> {
no_session,
extensions,
remote_extensions,
streamable_http_extensions,
builtins,
extensions_override: input_config.extensions_override,
additional_system_prompt: input_config.additional_system_prompt,
@@ -990,6 +1014,7 @@ pub async fn cli() -> Result<()> {
no_session: false,
extensions: Vec::new(),
remote_extensions: Vec::new(),
streamable_http_extensions: Vec::new(),
builtins: Vec::new(),
extensions_override: None,
additional_system_prompt: None,

View File

@@ -37,6 +37,7 @@ pub async fn agent_generator(
no_session: false,
extensions: requirements.external,
remote_extensions: requirements.remote,
streamable_http_extensions: Vec::new(),
builtins: requirements.builtin,
extensions_override: None,
additional_system_prompt: None,

View File

@@ -29,6 +29,8 @@ pub struct SessionBuilderConfig {
pub extensions: Vec<String>,
/// List of remote extension commands to add
pub remote_extensions: Vec<String>,
/// List of streamable HTTP extension commands to add
pub streamable_http_extensions: Vec<String>,
/// List of builtin extension commands to add
pub builtins: Vec<String>,
/// List of extensions to enable, enable only this set and ignore configured ones
@@ -454,6 +456,43 @@ pub async fn build_session(session_config: SessionBuilderConfig) -> Session {
}
}
// Add streamable HTTP extensions if provided
for extension_str in session_config.streamable_http_extensions {
if let Err(e) = session
.add_streamable_http_extension(extension_str.clone())
.await
{
eprintln!(
"{}",
style(format!(
"Warning: Failed to start streamable HTTP extension '{}': {}",
extension_str, e
))
.yellow()
);
eprintln!(
"{}",
style(format!(
"Continuing without streamable HTTP extension '{}'",
extension_str
))
.yellow()
);
// Offer debugging help
if let Err(debug_err) = offer_extension_debugging_help(
&extension_str,
&e.to_string(),
Arc::clone(&provider_for_display),
session_config.interactive,
)
.await
{
eprintln!("Note: Could not start debugging session: {}", debug_err);
}
}
}
// Add builtin extensions
for builtin in session_config.builtins {
if let Err(e) = session.add_builtin(builtin.clone()).await {
@@ -531,6 +570,7 @@ mod tests {
no_session: false,
extensions: vec!["echo test".to_string()],
remote_extensions: vec!["http://example.com".to_string()],
streamable_http_extensions: vec!["http://example.com/streamable".to_string()],
builtins: vec!["developer".to_string()],
extensions_override: None,
additional_system_prompt: Some("Test prompt".to_string()),
@@ -549,6 +589,7 @@ mod tests {
assert_eq!(config.extensions.len(), 1);
assert_eq!(config.remote_extensions.len(), 1);
assert_eq!(config.streamable_http_extensions.len(), 1);
assert_eq!(config.builtins.len(), 1);
assert!(config.debug);
assert_eq!(config.max_tool_repetitions, Some(5));
@@ -567,6 +608,7 @@ mod tests {
assert!(!config.no_session);
assert!(config.extensions.is_empty());
assert!(config.remote_extensions.is_empty());
assert!(config.streamable_http_extensions.is_empty());
assert!(config.builtins.is_empty());
assert!(config.extensions_override.is_none());
assert!(config.additional_system_prompt.is_none());

View File

@@ -244,6 +244,40 @@ impl Session {
Ok(())
}
/// Add a streamable HTTP extension to the session
///
/// # Arguments
/// * `extension_url` - URL of the server
pub async fn add_streamable_http_extension(&mut self, extension_url: String) -> Result<()> {
let name: String = rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(8)
.map(char::from)
.collect();
let config = ExtensionConfig::StreamableHttp {
name,
uri: extension_url,
envs: Envs::new(HashMap::new()),
env_keys: Vec::new(),
headers: HashMap::new(),
description: Some(goose::config::DEFAULT_EXTENSION_DESCRIPTION.to_string()),
// TODO: should set timeout
timeout: Some(goose::config::DEFAULT_EXTENSION_TIMEOUT),
bundled: None,
};
self.agent
.add_extension(config)
.await
.map_err(|e| anyhow::anyhow!("Failed to start extension: {}", e))?;
// Invalidate the completion cache when a new extension is added
self.invalidate_completion_cache().await;
Ok(())
}
/// Add a builtin extension to the session
///
/// # Arguments

View File

@@ -291,6 +291,26 @@ For example, a deeplink for a URL like `http://localhost:8080/sse` would look li
```
goose://extension?url=http%3A%2F%2Flocalhost%3A8080%2Fsse&timeout=<timeout>&id=<id>&name=<name>&description=<description>>
```
</TabItem>
<TabItem value="streamable_http" label="Streaming HTTP">
```
goose://extension?url=<remote-streamable-http-url>&type=streamable_http&id=<id>&name=<n>&description=<description>
```
Parameters:
- `url`: The URL of the remote Streaming HTTP server
- `type`: Must be set to `streamable_http` to specify the protocol type
- `timeout`: Maximum time (in seconds) to wait for extension responses
- `id`: Unique identifier for the extension
- `name`: Display name for the extension
- `description`: Brief description of the extension's functionality
For example, a deeplink for a URL like `https://example.com/streamable` would look like this when URL-encoded:
```
goose://extension?url=https%3A%2F%2Fexample.com%2Fstreamable&type=streamable_http&timeout=<timeout>&id=<id>&name=<n>&description=<description>
```
</TabItem>
@@ -598,8 +618,22 @@ For example, to start a session with a remote extension over SSE running on loca
goose session --with-remote-extension "http://localhost:8080/sse"
```
### Remote Extensions over Streaming HTTP
To enable a remote extension over Streaming HTTP while starting a session, run the following command:
```bash
goose session --with-streamable-http-extension "{extension URL}" --with-streamable-http-extension "{another extension URL}"
```
For example, to start a session with a Streaming HTTP extension, you'd run:
```bash
goose session --with-streamable-http-extension "https://example.com/streamable"
```
## Developing Extensions
Goose extensions are implemented with MCP, a standard protocol that allows AI models and agents to securely connect with local or remote resources. Learn how to build your own [extension as an MCP server](https://modelcontextprotocol.io/quickstart/server).
[extensions-directory]: https://block.github.io/goose/v1/extensions
[extensions-directory]: https://block.github.io/goose/v1/extensions

View File

@@ -32,7 +32,7 @@ goose configure
### session [options]
- Start a session and give it a name
#### Start a session and give it a name
**Options:**
@@ -43,8 +43,9 @@ goose configure
```bash
goose session --name <n>
```
---
- Resume a previous session
#### Resume a previous session
**Options:**
@@ -59,8 +60,9 @@ goose configure
```bash
goose session --resume --id <id>
```
---
- Start a session with the specified extension
#### Start a session with the specified extension
**Options:**
@@ -83,8 +85,9 @@ goose configure
```bash
goose session --with-extension "GITHUB_PERSONAL_ACCESS_TOKEN=<YOUR_TOKEN> npx -y @modelcontextprotocol/server-github"
```
---
- Start a session with the specified remote extension over SSE
#### Start a session with the specified remote extension over SSE
**Options:**
@@ -102,7 +105,48 @@ goose configure
goose session --with-remote-extension "http://localhost:8080/sse"
```
- Start a session with the specified [built-in extension](/docs/getting-started/using-extensions#built-in-extensions) enabled (e.g. 'developer')
---
#### Start a session with the specified remote extension over Streaming HTTP
**Options:**
**`--with-streamable-http-extension <url>`**
**Usage:**
```bash
goose session --with-streamable-http-extension <url>
```
**Examples:**
```bash
goose session --with-streamable-http-extension "https://example.com/streamable"
```
**Advanced Examples:**
```bash
# Start a session with a streamable HTTP extension
goose session --with-streamable-http-extension "http://api.example.com"
# Use multiple streamable HTTP extensions
goose session \
--with-streamable-http-extension "http://api1.example.com" \
--with-streamable-http-extension "http://api2.example.com"
# Mix different extension types
goose session \
--with-extension "echo hello" \
--with-remote-extension "http://sse.example.com/sse" \
--with-streamable-http-extension "http://http.example.com" \
--with-builtin "developer"
```
---
#### Start a session with the specified [built-in extension](/docs/getting-started/using-extensions#built-in-extensions) enabled (e.g. 'developer')
**Options:**
@@ -119,8 +163,9 @@ goose configure
```bash
goose session --with-builtin computercontroller
```
---
- Enable debug mode to output complete tool responses, detailed parameter values, and full file paths
#### Enable debug mode to output complete tool responses, detailed parameter values, and full file paths
**Options:**
@@ -131,8 +176,9 @@ goose configure
```bash
goose session --name my-session --debug
```
---
- Limit the maximum number of turns the agent can take before asking for user input to continue
#### Limit the maximum number of turns the agent can take before asking for user input to continue
**Options:**
@@ -144,7 +190,9 @@ goose configure
goose session --max-turns 50
```
- Set the [maximum number of turns](/docs/guides/smart-context-management#maximum-turns) allowed without user input (default: 1000)
---
#### Set the [maximum number of turns](/docs/guides/smart-context-management#maximum-turns) allowed without user input (default: 1000)
**Options:**
@@ -170,6 +218,7 @@ goose configure
```
---
### session list [options]
List all saved sessions.
@@ -326,6 +375,8 @@ Execute commands from an instruction file or stdin. Check out the [full guide](/
- **`--recipe <RECIPE_FILE_NAME> <OPTIONS>`**: Load a custom recipe in current session
- **`-p, --path <PATH>`**: Path for this run session (e.g. `./playground.jsonl`)
- **`--with-extension <COMMAND>`**: Add stdio extensions (can be used multiple times in the same command)
- **`--with-remote-extension <URL>`**: Add remote extensions over SSE (can be used multiple times in the same command)
- **`--with-streamable-http-extension <URL>`**: Add remote extensions over Streaming HTTP (can be used multiple times in the same command)
- **`--with-builtin <n>`**: Add builtin extensions by name (e.g., 'developer' or multiple: 'developer,github')
- **`--debug`**: Output complete tool responses, detailed parameter values, and full file paths
- **`--max-turns <NUMBER>`**: [Maximum number of turns](/docs/guides/smart-context-management#maximum-turns) allowed without user input (default: 1000)

View File

@@ -100,7 +100,7 @@ goose run --no-session -t "your command here"
### Working with Extensions
If you want to ensure specific extensions are available when running your task, you can indicate this with arguments. This can be done using the `--with-extension`, `--with-remote-extension`, or `--with-builtin` flags:
If you want to ensure specific extensions are available when running your task, you can indicate this with arguments. This can be done using the `--with-extension`, `--with-remote-extension`, `--with-streamable-http-extension`, or `--with-builtin` flags:
- Using built-in extensions e.g developer and computercontroller extensions
@@ -120,6 +120,12 @@ goose run --with-extension "ENV1=value1 custom-extension-args" -t "your instruct
goose run --with-remote-extension "url" -t "your instructions"
```
- Using streamable HTTP extensions
```bash
goose run --with-streamable-http-extension "https://example.com/streamable" -t "your instructions"
```
### Debug Mode
When troubleshooting or developing complex workflows, you can enable debug mode to get more detailed information about tool execution. The `--debug` flag provides: