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
32 changes: 16 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = ["crates/*"]
resolver = "2"

[workspace.package]
version = "0.1.197"
version = "0.1.198"
edition = "2024"
rust-version = "1.88"
license = "Apache-2.0"
Expand Down
9 changes: 6 additions & 3 deletions crates/cli-sub-agent/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,14 @@ pub enum Commands {
#[arg(long, value_delimiter = ',', value_name = "PATH")]
extra_writable: Vec<PathBuf>,

/// Detach as a background daemon; prints session ID and exits immediately.
/// Use `csa session wait/attach/result` to interact with the daemon.
#[arg(long)]
/// [DEPRECATED] Daemon mode is now the default. This flag is a no-op.
#[arg(long, hide = true)]
daemon: bool,

/// Run in foreground blocking mode instead of the default daemon mode.
#[arg(long)]
no_daemon: bool,

/// Internal flag: this process IS the daemon child. Skip re-spawning.
#[arg(long, hide = true)]
daemon_child: bool,
Expand Down
16 changes: 12 additions & 4 deletions crates/cli-sub-agent/src/cli_session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,15 +191,23 @@ pub enum SessionCommands {
cd: Option<String>,
},

/// Wait for a daemon session to complete (poll until result.toml exists)
/// Wait for a daemon session to complete (poll until result.toml exists).
/// Hardcoded timeout: 250 seconds.
Wait {
/// Session ID to wait for
#[arg(long)]
session: String,

/// Timeout in seconds (0 = wait forever)
#[arg(long, default_value = "0")]
timeout: u64,
/// Working directory
#[arg(long)]
cd: Option<String>,
},

/// Kill a running daemon session (SIGTERM, then SIGKILL after grace period)
Kill {
/// Session ID to kill
#[arg(long)]
session: String,

/// Working directory
#[arg(long)]
Expand Down
7 changes: 4 additions & 3 deletions crates/cli-sub-agent/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,12 +407,13 @@ async fn run() -> Result<()> {
force_ignore_tier_setting,
no_fs_sandbox,
extra_writable,
daemon,
daemon: _daemon,
no_daemon,
daemon_child,
session_id,
} => {
// Daemon spawn: when --daemon is set and not already the child, fork and exit.
if daemon && !daemon_child {
// Daemon spawn: daemon mode is the default; --no-daemon opts out.
if !no_daemon && !daemon_child {
if let Some(ref _id) = session_id {
anyhow::bail!("--session-id is an internal flag and must not be used directly");
}
Expand Down
9 changes: 7 additions & 2 deletions crates/cli-sub-agent/src/run_cmd_daemon.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Daemon spawn logic for `csa run --daemon`.
//! Daemon spawn logic for `csa run` (daemon mode is the default).
//!
//! Extracted from main.rs to keep the dispatch function under the
//! monolith file limit.
Expand Down Expand Up @@ -26,7 +26,12 @@ pub(crate) fn spawn_and_exit(cd: Option<&str>) -> Result<()> {
// that may appear before the subcommand (e.g. `csa --format json run ...`).
let all_args: Vec<String> = std::env::args().collect();
let run_pos = all_args.iter().position(|a| a == "run").unwrap_or(1);
let forwarded_args: Vec<String> = all_args.iter().skip(run_pos + 1).cloned().collect();
let forwarded_args: Vec<String> = all_args
.iter()
.skip(run_pos + 1)
.filter(|a| *a != "--daemon") // daemon is now default; strip no-op flag
.cloned()
.collect();
Comment on lines +29 to +34
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current logic for collecting forwarded_args skips all arguments before the run subcommand. This causes global flags (e.g., --format json) passed before run to be lost when spawning the daemon child. The code should preserve arguments both before and after the run subcommand to ensure the child process inherits the same global configuration, as suggested by the comment on line 26.

Suggested change
let forwarded_args: Vec<String> = all_args
.iter()
.skip(run_pos + 1)
.filter(|a| *a != "--daemon") // daemon is now default; strip no-op flag
.cloned()
.collect();
let mut forwarded_args: Vec<String> = all_args.iter().take(run_pos).skip(1).cloned().collect();
forwarded_args.extend(
all_args
.iter()
.skip(run_pos + 1)
.filter(|a| *a != "--daemon") // daemon is now default; strip no-op flag
.cloned(),
)


let csa_binary = std::env::current_exe().unwrap_or_else(|_| std::path::PathBuf::from("csa"));

Expand Down
6 changes: 4 additions & 2 deletions crates/cli-sub-agent/src/session_cmds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -759,8 +759,10 @@ pub(crate) fn handle_session_checkpoints(cd: Option<String>) -> Result<()> {
Ok(())
}

// Daemon-specific commands (wait, attach) are in session_cmds_daemon.rs.
pub(crate) use crate::session_cmds_daemon::{handle_session_attach, handle_session_wait};
// Daemon-specific commands (wait, attach, kill) are in session_cmds_daemon.rs.
pub(crate) use crate::session_cmds_daemon::{
handle_session_attach, handle_session_kill, handle_session_wait,
};

#[cfg(test)]
#[path = "session_cmds_tests.rs"]
Expand Down
Loading
Loading