mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
chore(acp): raise default idle timeout from 320s to 620s (#566)
Signed-off-by: Tyler Longwell <109685178+tlongwell-block@users.noreply.github.com>
This commit is contained in:
@@ -105,7 +105,7 @@ All configuration is via environment variables (or CLI flags — every env var h
|
||||
| `SPROUT_ACP_AGENT_COMMAND` | no | `goose` | Agent binary to spawn. |
|
||||
| `SPROUT_ACP_AGENT_ARGS` | no | `acp` | Agent arguments (comma-separated). |
|
||||
| `SPROUT_ACP_MCP_COMMAND` | no | `sprout-mcp-server` | Path to the Sprout MCP server binary. |
|
||||
| `SPROUT_ACP_IDLE_TIMEOUT` | no | `300` | Idle timeout: max seconds of silence before cancelling a turn. Resets on any agent stdout activity. |
|
||||
| `SPROUT_ACP_IDLE_TIMEOUT` | no | `620` | Idle timeout: max seconds of silence before cancelling a turn. Resets on any agent stdout activity. |
|
||||
| `SPROUT_ACP_MAX_TURN_DURATION` | no | `3600` | Absolute wall-clock cap per turn (safety valve). |
|
||||
| `SPROUT_API_TOKEN` | no | — | API token (required if relay enforces token auth). |
|
||||
|
||||
|
||||
@@ -13,6 +13,17 @@ use uuid::Uuid;
|
||||
|
||||
use crate::filter::SubscriptionRule;
|
||||
|
||||
// ── Constants ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/// Default idle timeout (seconds) when neither `--idle-timeout` nor the
|
||||
/// deprecated `--turn-timeout` is set.
|
||||
///
|
||||
/// Sized for slow turns where the agent may go silent on its outer ACP channel
|
||||
/// while running long sub-tools (e.g. a sprout-agent running another agent, or
|
||||
/// codex/claude doing multi-minute single tool calls). 600s working budget +
|
||||
/// 20s buffer. Override via `--idle-timeout` / `SPROUT_ACP_IDLE_TIMEOUT`.
|
||||
pub(crate) const DEFAULT_IDLE_TIMEOUT_SECS: u64 = 620;
|
||||
|
||||
// ── Errors ────────────────────────────────────────────────────────────────────
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
@@ -597,7 +608,7 @@ impl Config {
|
||||
};
|
||||
|
||||
// Resolve idle_timeout_secs with deprecation handling.
|
||||
// Precedence: explicit --idle-timeout > --turn-timeout (deprecated) > default 320.
|
||||
// Precedence: explicit --idle-timeout > --turn-timeout (deprecated) > `DEFAULT_IDLE_TIMEOUT_SECS`.
|
||||
let idle_timeout_secs = {
|
||||
let raw = match (args.idle_timeout, args.turn_timeout) {
|
||||
(Some(idle), Some(_turn)) => {
|
||||
@@ -615,7 +626,7 @@ impl Config {
|
||||
);
|
||||
turn
|
||||
}
|
||||
(None, None) => 320, // default: 20s buffer over goose's 300s turn timeout
|
||||
(None, None) => DEFAULT_IDLE_TIMEOUT_SECS,
|
||||
};
|
||||
if raw == 0 {
|
||||
tracing::warn!("idle timeout of 0 is invalid — using 1s minimum");
|
||||
@@ -1092,7 +1103,7 @@ mod tests {
|
||||
agent_command: "goose".into(),
|
||||
agent_args: vec!["acp".into()],
|
||||
mcp_command: "sprout-mcp-server".into(),
|
||||
idle_timeout_secs: 320,
|
||||
idle_timeout_secs: DEFAULT_IDLE_TIMEOUT_SECS,
|
||||
max_turn_duration_secs: 3600,
|
||||
agents: 1,
|
||||
heartbeat_interval_secs: 0,
|
||||
@@ -1800,13 +1811,13 @@ channels = "ALL"
|
||||
// ── Idle timeout config precedence ─────────────────────────────────────
|
||||
|
||||
/// Helper: resolve idle_timeout_secs using the same precedence logic as Config::from_args.
|
||||
/// Precedence: explicit --idle-timeout > --turn-timeout (deprecated) > default 320.
|
||||
/// Precedence: explicit --idle-timeout > --turn-timeout (deprecated) > `DEFAULT_IDLE_TIMEOUT_SECS`.
|
||||
fn resolve_idle_timeout(idle: Option<u64>, turn: Option<u64>) -> u64 {
|
||||
let raw = match (idle, turn) {
|
||||
(Some(idle), Some(_)) => idle,
|
||||
(Some(idle), None) => idle,
|
||||
(None, Some(turn)) => turn,
|
||||
(None, None) => 320,
|
||||
(None, None) => DEFAULT_IDLE_TIMEOUT_SECS,
|
||||
};
|
||||
if raw == 0 {
|
||||
1
|
||||
@@ -1826,8 +1837,8 @@ channels = "ALL"
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn idle_timeout_defaults_to_320_when_neither_set() {
|
||||
assert_eq!(resolve_idle_timeout(None, None), 320);
|
||||
fn idle_timeout_defaults_to_constant_when_neither_set() {
|
||||
assert_eq!(resolve_idle_timeout(None, None), DEFAULT_IDLE_TIMEOUT_SECS);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1844,9 +1855,10 @@ channels = "ALL"
|
||||
fn test_config_summary_includes_idle_and_max_turn() {
|
||||
let config = test_config(SubscribeMode::Mentions);
|
||||
let summary = config.summary();
|
||||
let expected_idle = format!("idle_timeout={DEFAULT_IDLE_TIMEOUT_SECS}s");
|
||||
assert!(
|
||||
summary.contains("idle_timeout=320s"),
|
||||
"summary should include idle_timeout: {summary}"
|
||||
summary.contains(&expected_idle),
|
||||
"summary should include {expected_idle}: {summary}"
|
||||
);
|
||||
assert!(
|
||||
summary.contains("max_turn=3600s"),
|
||||
|
||||
@@ -2729,7 +2729,7 @@ mod build_mcp_servers_tests {
|
||||
agent_command: "goose".into(),
|
||||
agent_args: vec!["acp".into()],
|
||||
mcp_command: "sprout-mcp-server".into(),
|
||||
idle_timeout_secs: 320,
|
||||
idle_timeout_secs: config::DEFAULT_IDLE_TIMEOUT_SECS,
|
||||
max_turn_duration_secs: 3600,
|
||||
agents: 1,
|
||||
heartbeat_interval_secs: 0,
|
||||
|
||||
Reference in New Issue
Block a user