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
33 changes: 17 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 @@ -20,7 +20,7 @@ default-members = [
resolver = "2"

[workspace.package]
version = "0.1.732"
version = "0.1.733"
edition = "2024"
rust-version = "1.88"
license = "Apache-2.0"
Expand Down
13 changes: 9 additions & 4 deletions crates/cli-sub-agent/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,22 @@ pub enum Commands {
#[arg(long, value_name = "SESSION_ID", value_parser = validate_ulid)]
inline_context_from_review_session: Option<String>,
/// Resume existing session (ULID or prefix match) [DEPRECATED: use --fork-from]
#[arg(short, long, conflicts_with_all = ["last", "fork_from", "fork_last"])]
#[arg(short, long, conflicts_with_all = ["last", "fork_from", "fork_last", "fork_from_caller"])]
session: Option<String>,
/// Resume the most recent session for this project [DEPRECATED: use --fork-last]
#[arg(long, conflicts_with_all = ["session", "ephemeral", "fork_from", "fork_last"])]
#[arg(long, conflicts_with_all = ["session", "ephemeral", "fork_from", "fork_last", "fork_from_caller"])]
last: bool,
/// Fork from a specific session (ULID or prefix match)
#[arg(long, conflicts_with_all = ["session", "last", "fork_last", "ephemeral"])]
#[arg(long, conflicts_with_all = ["session", "last", "fork_last", "fork_from_caller", "ephemeral"])]
fork_from: Option<String>,
/// Fork the most recent session for this project
#[arg(long, conflicts_with_all = ["session", "last", "fork_from", "ephemeral"])]
#[arg(long, conflicts_with_all = ["session", "last", "fork_from", "fork_from_caller", "ephemeral"])]
fork_last: bool,
/// Fork from the auto-detected caller's Claude conversation (CSA-lite, #1432).
/// Reads `CLAUDE_SESSION_ID` or the most recent Claude thread on disk,
/// extracts a budgeted conversation prefix, and seeds the new session with it.
#[arg(long, conflicts_with_all = ["session", "last", "fork_from", "fork_last", "ephemeral"])]
fork_from_caller: bool,
/// Human-readable description for a new session
#[arg(short, long)]
description: Option<String>,
Expand Down
3 changes: 3 additions & 0 deletions crates/cli-sub-agent/src/goal_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ pub(crate) struct GoalRunRequest {
pub(crate) last: bool,
pub(crate) fork_from: Option<String>,
pub(crate) fork_last: bool,
pub(crate) fork_from_caller: bool,
pub(crate) description: Option<String>,
pub(crate) fork_call: bool,
pub(crate) return_to: Option<String>,
Expand Down Expand Up @@ -138,6 +139,7 @@ pub(crate) async fn handle_run_or_goal(request: GoalRunRequest) -> Result<i32> {
request.last,
request.fork_from,
request.fork_last,
request.fork_from_caller,
request.description,
request.fork_call,
request.return_to,
Expand Down Expand Up @@ -293,6 +295,7 @@ async fn run_goal_iteration(
first_iteration && request.last,
first_iteration.then(|| request.fork_from.clone()).flatten(),
first_iteration && request.fork_last,
first_iteration && request.fork_from_caller,
request.description.clone(),
request.fork_call,
request.return_to.clone(),
Expand Down
16 changes: 5 additions & 11 deletions crates/cli-sub-agent/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ mod review_prior_rounds;
mod review_routing;
mod review_session_findings;
mod run_cmd;
mod run_cmd_caller_fork;
mod run_cmd_daemon;
mod run_cmd_fork;
mod run_cmd_post;
Expand All @@ -80,6 +81,7 @@ mod self_update;
mod session_cmds;
mod session_cmds_daemon;
mod session_cmds_result;
mod session_cmds_result_measure;
mod session_dispatch;
mod session_guard;
mod session_observability;
Expand Down Expand Up @@ -243,10 +245,8 @@ async fn run() -> Result<()> {
});

if auto_upgrade {
use std::time::Duration;

let mut success = false;
let mut delay = Duration::from_secs(1);
let mut delay = std::time::Duration::from_secs(1);

for attempt in 0..3 {
let result = tokio::process::Command::new("weave")
Expand Down Expand Up @@ -281,14 +281,6 @@ async fn run() -> Result<()> {

let legacy_xdg_paths = csa_config::paths::legacy_paths_requiring_migration();
if !legacy_xdg_paths.is_empty() {
for path in &legacy_xdg_paths {
tracing::debug!(
label = path.label,
legacy = %path.legacy_path.display(),
new = %path.new_path.display(),
"legacy XDG path detected, auto-migrating"
);
}
match csa_config::migrate::run_xdg_migration() {
Ok(()) => {
tracing::debug!(
Expand Down Expand Up @@ -320,6 +312,7 @@ async fn run() -> Result<()> {
last,
fork_from,
fork_last,
fork_from_caller,
description,
fork_call,
return_to,
Expand Down Expand Up @@ -404,6 +397,7 @@ async fn run() -> Result<()> {
last,
fork_from,
fork_last,
fork_from_caller,
description,
fork_call,
return_to,
Expand Down
6 changes: 6 additions & 0 deletions crates/cli-sub-agent/src/pipeline_post_exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,12 @@ fn update_cumulative_tokens(session: &mut MetaSessionState, token_usage: Option<
cumulative.estimated_cost_usd = Some(
cumulative.estimated_cost_usd.unwrap_or(0.0) + new_usage.estimated_cost_usd.unwrap_or(0.0),
);
// Accumulate cache-read tokens only when the new usage reports a value;
// missing fields must not zero out a previously recorded total.
if let Some(new_cache_read) = new_usage.cache_read_input_tokens {
cumulative.cache_read_input_tokens =
Some(cumulative.cache_read_input_tokens.unwrap_or(0) + new_cache_read);
}

// Update token budget tracking
if let Some(ref mut budget) = session.token_budget {
Expand Down
1 change: 1 addition & 0 deletions crates/cli-sub-agent/src/run_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ impl SubagentRunConfig {
false,
None,
false,
false,
None,
false,
None,
Expand Down
2 changes: 1 addition & 1 deletion crates/cli-sub-agent/src/run_cmd_attempt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pub(crate) async fn execute_run_loop(request: RunLoopRequest<'_>) -> Result<RunL
);
let mut executed_session_id: Option<String> = None;
let mut pre_created_fork_session_id: Option<String> = None;
let mut fork_resolution: Option<ForkResolution> = None;
let mut fork_resolution: Option<ForkResolution> = request.caller_fork_resolution;
let mut is_fork = request.is_fork;
let mut failover_context_addendum: Option<String> = None;
let mut is_auto_seed_fork = request.is_auto_seed_fork;
Expand Down
5 changes: 5 additions & 0 deletions crates/cli-sub-agent/src/run_cmd_attempt_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ pub(crate) struct RunLoopRequest<'a> {
pub(crate) run_started_at: Instant,
pub(crate) is_fork: bool,
pub(crate) is_auto_seed_fork: bool,
/// Pre-resolved fork from `--fork-from-caller` (CSA-lite, #1432).
/// When present, supplies the initial fork_resolution before the loop
/// runs `resolve_fork()`; downstream prepend-to-prompt path picks up
/// the extracted caller conversation prefix.
pub(crate) caller_fork_resolution: Option<ForkResolution>,
pub(crate) ephemeral: bool,
pub(crate) fork_call: bool,
pub(crate) session_arg: Option<String>,
Expand Down
Loading
Loading