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
30 changes: 15 additions & 15 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.108"
version = "0.1.109"
edition = "2024"
rust-version = "1.85"
license = "Apache-2.0"
Expand Down
1 change: 1 addition & 0 deletions crates/cli-sub-agent/src/claude_sub_agent_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub(crate) async fn handle_claude_sub_agent(
&project_root,
false, // claude-sub-agent does not support --force
false, // claude-sub-agent does not support --force-override-user-config
false, // sub-agent dispatch always uses explicit tool
)?;

// 8. Build executor and validate tool
Expand Down
1 change: 1 addition & 0 deletions crates/cli-sub-agent/src/mcp_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ async fn handle_run_tool(args: Value) -> Result<Value> {
&project_root,
false, // MCP server does not support --force
false, // MCP server does not support --force-override-user-config
false, // MCP tool dispatch always uses explicit tool
)?;

// Build executor
Expand Down
2 changes: 2 additions & 0 deletions crates/cli-sub-agent/src/run_cmd_execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ pub(crate) async fn handle_run(
};
let run_timeout_seconds = resolve_run_timeout_seconds(timeout, skill.as_deref());
let run_started_at = Instant::now();
let needs_edit = crate::run_helpers::infer_task_edit_requirement(&prompt_text).unwrap_or(false);
let strategy_result = resolve_tool_by_strategy(
&strategy,
model_spec.as_deref(),
Expand All @@ -181,6 +182,7 @@ pub(crate) async fn handle_run(
&project_root,
force,
force_override_user_config,
needs_edit,
)?;
let heterogeneous_runtime_fallback_candidates = strategy_result.runtime_fallback_candidates;
let resolved_model_spec = strategy_result.model_spec;
Expand Down
14 changes: 14 additions & 0 deletions crates/cli-sub-agent/src/run_cmd_tool_selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ pub(crate) fn resolve_tool_by_strategy(
project_root: &Path,
force: bool,
force_override_user_config: bool,
needs_edit: bool,
) -> Result<StrategyResolution> {
match strategy {
ToolSelectionStrategy::Explicit(t) => {
Expand All @@ -144,6 +145,7 @@ pub(crate) fn resolve_tool_by_strategy(
project_root,
force,
force_override_user_config,
needs_edit,
)?;
Ok(StrategyResolution {
tool,
Expand All @@ -161,6 +163,7 @@ pub(crate) fn resolve_tool_by_strategy(
project_root,
force,
force_override_user_config,
needs_edit,
)?;
Ok(StrategyResolution {
tool,
Expand All @@ -177,6 +180,7 @@ pub(crate) fn resolve_tool_by_strategy(
project_root,
force,
force_override_user_config,
needs_edit,
),
ToolSelectionStrategy::HeterogeneousStrict => {
let res = resolve_heterogeneous_strict(
Expand All @@ -187,6 +191,7 @@ pub(crate) fn resolve_tool_by_strategy(
project_root,
force,
force_override_user_config,
needs_edit,
)?;
Ok(StrategyResolution {
tool: res.0,
Expand Down Expand Up @@ -216,6 +221,7 @@ fn collect_enabled_tools(
}
}

#[allow(clippy::too_many_arguments)]
fn resolve_heterogeneous_preferred(
model_spec: Option<&str>,
model: Option<&str>,
Expand All @@ -224,6 +230,7 @@ fn resolve_heterogeneous_preferred(
project_root: &Path,
force: bool,
force_override_user_config: bool,
needs_edit: bool,
) -> Result<StrategyResolution> {
let detected_parent_tool = detect_parent_tool();
let parent_tool_name = resolve_tool(detected_parent_tool, global_config);
Expand All @@ -245,6 +252,7 @@ fn resolve_heterogeneous_preferred(
project_root,
force,
force_override_user_config,
needs_edit,
)?;
Ok(StrategyResolution {
tool: t,
Expand All @@ -267,6 +275,7 @@ fn resolve_heterogeneous_preferred(
project_root,
force,
force_override_user_config,
needs_edit,
)?;
Ok(StrategyResolution {
tool: t,
Expand All @@ -288,6 +297,7 @@ fn resolve_heterogeneous_preferred(
project_root,
force,
force_override_user_config,
needs_edit,
)?;
Ok(StrategyResolution {
tool: t,
Expand All @@ -298,6 +308,7 @@ fn resolve_heterogeneous_preferred(
}
}

#[allow(clippy::too_many_arguments)]
fn resolve_heterogeneous_strict(
model_spec: Option<&str>,
model: Option<&str>,
Expand All @@ -306,6 +317,7 @@ fn resolve_heterogeneous_strict(
project_root: &Path,
force: bool,
force_override_user_config: bool,
needs_edit: bool,
) -> Result<(ToolName, Option<String>, Option<String>)> {
let detected_parent_tool = detect_parent_tool();
let parent_tool_name = resolve_tool(detected_parent_tool, global_config);
Expand All @@ -323,6 +335,7 @@ fn resolve_heterogeneous_strict(
project_root,
force,
force_override_user_config,
needs_edit,
),
None => {
anyhow::bail!(
Expand All @@ -346,6 +359,7 @@ fn resolve_heterogeneous_strict(
project_root,
force,
force_override_user_config,
needs_edit,
)
}
}
Expand Down
11 changes: 8 additions & 3 deletions crates/cli-sub-agent/src/run_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ use csa_session::TokenUsage;
/// - model: optional model string (from CLI, with alias resolution applied)
///
/// When tool is None, uses tier-based round-robin selection.
/// `needs_edit`: when true, filters out tools with `allow_edit_existing_files = false`.
#[allow(clippy::too_many_arguments)]
pub(crate) fn resolve_tool_and_model(
tool: Option<ToolName>,
model_spec: Option<&str>,
Expand All @@ -25,6 +27,7 @@ pub(crate) fn resolve_tool_and_model(
project_root: &Path,
force: bool,
force_override_user_config: bool,
needs_edit: bool,
) -> Result<(ToolName, Option<String>, Option<String>)> {
// Case 1: model_spec provided → parse it to get tool
if let Some(spec) = model_spec {
Expand Down Expand Up @@ -84,13 +87,15 @@ pub(crate) fn resolve_tool_and_model(
if let Some(cfg) = config {
// Try round-robin rotation first (needs project root to persist state)
if let Ok(Some((tool_name_str, tier_model_spec))) =
csa_scheduler::resolve_tier_tool_rotated(cfg, "default", project_root, false)
csa_scheduler::resolve_tier_tool_rotated(cfg, "default", project_root, needs_edit)
{
let tool_name = parse_tool_name(&tool_name_str)?;
return Ok((tool_name, Some(tier_model_spec), None));
}
// Fallback: original non-rotating selection
if let Some((tool_name_str, tier_model_spec)) = cfg.resolve_tier_tool("default") {
// Fallback: original non-rotating selection (also respects edit restrictions)
if let Some((tool_name_str, tier_model_spec)) =
cfg.resolve_tier_tool_filtered("default", needs_edit)
{
let tool_name = parse_tool_name(&tool_name_str)?;
return Ok((tool_name, Some(tier_model_spec), None));
}
Expand Down
7 changes: 5 additions & 2 deletions crates/cli-sub-agent/src/run_helpers_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@ fn resolve_tool_and_model_disabled_tool_explicit_errors() {
std::path::Path::new("/tmp"),
true, // force tier bypass
false, // no override
false, // needs_edit
);
assert!(result.is_err());
let msg = result.unwrap_err().to_string();
Expand Down Expand Up @@ -594,8 +595,9 @@ fn resolve_tool_and_model_disabled_tool_with_override_succeeds() {
None,
Some(&config),
std::path::Path::new("/tmp"),
true, // force tier bypass
true, // override enabled
true, // force tier bypass
true, // override enabled
false, // needs_edit
);
assert!(result.is_ok());
let (tool, _, _) = result.unwrap();
Expand Down Expand Up @@ -643,6 +645,7 @@ fn resolve_tool_and_model_disabled_tool_model_spec_errors() {
std::path::Path::new("/tmp"),
true,
false,
false, // needs_edit
);
assert!(result.is_err());
let msg = result.unwrap_err().to_string();
Expand Down
Loading
Loading