Support configurable timeouts for thread shell commands (#41384)

## What changed

- Add an optional `timeoutMs` parameter to `thread/shellCommand` and propagate it to user shell execution.
- Preserve the one-hour default when the parameter is omitted or `null`, allow longer deadlines, and treat `0` as an immediate timeout.
- Reject negative or otherwise invalid values before execution. Timing out an auxiliary shell command leaves its active turn running.

## Testing

- Cover default, extended, immediate, invalid, standalone, active-turn, and interruption behavior.

GitOrigin-RevId: d72f67793d9766b7383f28d30140270a4a76a495
This commit is contained in:
gero-oai authored and copyberry committed 2026-08-28 18:07:40 +00:00
1 parent 4ee04c0aa5
commit e4d0ba4e92
20 files changed
+475 -45

No files matched your search

+18 -5
View File
@@ -95,7 +95,12 @@ pub async fn inter_agent_communication(
}
}
pub async fn run_user_shell_command(sess: &Arc<Session>, sub_id: String, command: String) {
pub async fn run_user_shell_command(
sess: &Arc<Session>,
sub_id: String,
command: String,
timeout_ms: Option<u64>,
) {
if let Some((turn_context, cancellation_token)) =
sess.active_turn_context_and_cancellation_token().await
{
@@ -105,6 +110,7 @@ pub async fn run_user_shell_command(sess: &Arc<Session>, sub_id: String, command
session,
turn_context,
command,
timeout_ms,
cancellation_token,
UserShellCommandMode::ActiveTurnAuxiliary,
)
@@ -116,8 +122,12 @@ pub async fn run_user_shell_command(sess: &Arc<Session>, sub_id: String, command
let turn_context = sess
.new_turn_with_default_settings(sub_id, Default::default())
.await;
sess.spawn_task(turn_context, Vec::new(), UserShellCommandTask::new(command))
.await;
sess.spawn_task(
turn_context,
Vec::new(),
UserShellCommandTask::new(command, timeout_ms),
)
.await;
}
pub async fn resolve_elicitation(
@@ -675,8 +685,11 @@ pub(super) async fn submission_loop(
set_thread_memory_mode(&sess, sub.id.clone(), mode).await;
false
}
Op::RunUserShellCommand { command } => {
run_user_shell_command(&sess, sub.id.clone(), command).await;
Op::RunUserShellCommand {
command,
timeout_ms,
} => {
run_user_shell_command(&sess, sub.id.clone(), command, timeout_ms).await;
false
}
Op::ResolveElicitation {