Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions cmux-tui/crates/acpmux/src/cli/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,8 @@ pub enum Command {
/// What to do when the turn asks for a permission: wait (default), deny, or fail (exit 5).
#[arg(long, default_value = "wait")]
on_permission: String,
/// Report prompt_stalled (exit 1) when nothing happens for this many seconds after sending; 0 disables.
#[arg(long, default_value_t = 30)]
/// Report prompt_stalled (exit 1) when nothing happens for this many seconds after sending; 0 disables. The default waits for the live peer.
#[arg(long, default_value_t = 0)]
stall: u64,
/// Send this prompt id again (from a `daemon_closed` error): the daemon runs an id once and
/// answers a repeat with the first run's outcome.
Expand Down Expand Up @@ -2003,3 +2003,27 @@ mod config_set_tests {
}
}
}

#[cfg(test)]
mod deadline_defaults_tests {
use super::{Cli, Command};
use clap::Parser;

#[test]
fn send_waits_for_a_live_peer_by_default() {
let cli = Cli::try_parse_from(["acpmux", "send", "session", "slow reply"]).unwrap();
match cli.command {
Some(Command::Send { stall, .. }) => assert_eq!(stall, 0),
_ => panic!("expected send command"),
}
}

#[test]
fn explicit_stall_remains_a_caller_choice() {
let cli = Cli::try_parse_from(["acpmux", "send", "session", "--stall", "7"]).unwrap();
match cli.command {
Some(Command::Send { stall, .. }) => assert_eq!(stall, 7),
_ => panic!("expected send command"),
}
}
}
4 changes: 2 additions & 2 deletions cmux-tui/crates/acpmux/src/cli/command_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ pub struct NewArgs {
/// Retry the turn on an agent-internal error, only when it produced nothing yet.
#[arg(long, default_value_t = 0)]
pub retries: u32,
/// Report prompt_stalled (exit 1) when nothing happens for this many seconds; 0 disables.
#[arg(long, default_value_t = 30)]
/// Report prompt_stalled (exit 1) when nothing happens for this many seconds; 0 disables. The default waits for the live peer.
#[arg(long, default_value_t = 0)]
pub stall: u64,
/// Send the first prompt with this id again (from a `daemon_closed` error); it runs once.
#[arg(long)]
Expand Down
16 changes: 5 additions & 11 deletions cmux-tui/crates/acpmux/src/cli/run/standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,17 +173,11 @@ pub(super) async fn run(cmd: Command, json_out: bool, suppress_reads: bool) -> R
}
Command::Last { session, count } => {
let client = connect(true).await?;
// One budget includes resolution and every transcript page. Each forwarded read
// has its own bound too, but many slow pages must not multiply this CLI's wait.
let (id, replies) = tokio::time::timeout(std::time::Duration::from_secs(30), async {
let id = resolve_id(&client, &session).await?;
let replies = last_replies(&client, &id, count).await?;
Ok::<_, anyhow::Error>((id, replies))
})
.await
.map_err(|_| anyhow!(
"reading last replies for {session:?} did not finish within 30 seconds; check the peer connection and retry this read (the session may still be running)"
))??;
// The daemon connection is the liveness boundary: a live peer may
// take as long as it needs to page a large transcript, while EOF
// still fails the request promptly.
let id = resolve_id(&client, &session).await?;
let replies = last_replies(&client, &id, count).await?;
if json_out {
print_json(&json!({"sessionId": id, "replies": replies}));
} else {
Expand Down
Loading
Loading