start contextuel : am start sans argument lance l'agent par defaut du projet (issue #30) - resolution pure resolve_start_target, restart identique, REPL sans agent obligatoire
This commit is contained in:
+2
-2
@@ -298,8 +298,8 @@ pub enum Command {
|
|||||||
/// Arguments shared by start and restart.
|
/// Arguments shared by start and restart.
|
||||||
#[derive(Args, Debug, Clone, Default)]
|
#[derive(Args, Debug, Clone, Default)]
|
||||||
pub struct StartArgs {
|
pub struct StartArgs {
|
||||||
/// Agent name, alias, or group:<name>
|
/// Agent name, alias, or group:<name> (defaults to the project's default agent)
|
||||||
pub agent: String,
|
pub agent: Option<String>,
|
||||||
/// Run detached in the background; output goes to the agent log file
|
/// Run detached in the background; output goes to the agent log file
|
||||||
#[arg(short = 'b', long, conflicts_with = "foreground", action = ArgAction::SetTrue)]
|
#[arg(short = 'b', long, conflicts_with = "foreground", action = ArgAction::SetTrue)]
|
||||||
pub background: bool,
|
pub background: bool,
|
||||||
|
|||||||
+21
-4
@@ -11,10 +11,25 @@ use std::ffi::OsString;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
|
/// Resolve the start target: the explicit agent/alias/group when given,
|
||||||
|
/// otherwise the default agent of the project containing cwd (issue #30).
|
||||||
|
pub fn resolve_start_target(app: &App, cwd: &std::path::Path, agent: Option<&str>) -> Result<String> {
|
||||||
|
if let Some(a) = agent.filter(|s| !s.is_empty()) {
|
||||||
|
return Ok(a.to_string());
|
||||||
|
}
|
||||||
|
crate::projects::default_agent_for_dir(app, cwd).ok_or_else(|| {
|
||||||
|
anyhow!(
|
||||||
|
"no agent given — set default_agent in this project's profile ('am init' does it) or pass an agent name"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn start(app: &App, opts: &StartArgs) -> Result<i32> {
|
pub fn start(app: &App, opts: &StartArgs) -> Result<i32> {
|
||||||
|
let cwd = std::env::current_dir().unwrap_or_default();
|
||||||
|
let target = resolve_start_target(app, &cwd, opts.agent.as_deref())?;
|
||||||
let extra_env = parse_env_list(&opts.env)?;
|
let extra_env = parse_env_list(&opts.env)?;
|
||||||
let extra_args = parse_extra_args(&opts.args);
|
let extra_args = parse_extra_args(&opts.args);
|
||||||
if let Some(group) = crate::catalog::Catalog::parse_group_selector(&opts.agent) {
|
if let Some(group) = crate::catalog::Catalog::parse_group_selector(&target) {
|
||||||
let members = app.catalog.group_members(group);
|
let members = app.catalog.group_members(group);
|
||||||
if members.is_empty() {
|
if members.is_empty() {
|
||||||
bail!("unknown group '{group}'");
|
bail!("unknown group '{group}'");
|
||||||
@@ -24,7 +39,7 @@ pub fn start(app: &App, opts: &StartArgs) -> Result<i32> {
|
|||||||
}
|
}
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
let agent = require_agent(app, &opts.agent)?;
|
let agent = require_agent(app, &target)?;
|
||||||
start_one(app, agent, &extra_args, &extra_env, opts.notify, opts.background)
|
start_one(app, agent, &extra_args, &extra_env, opts.notify, opts.background)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +212,9 @@ fn stop_one(app: &App, agent: &AgentDef, force: bool, timeout: u64) -> Result<i3
|
|||||||
|
|
||||||
pub fn restart(app: &App, opts: &StartArgs, force: bool, timeout: Option<u64>) -> Result<i32> {
|
pub fn restart(app: &App, opts: &StartArgs, force: bool, timeout: Option<u64>) -> Result<i32> {
|
||||||
let timeout = timeout.unwrap_or_else(|| app.config.settings.stop_timeout());
|
let timeout = timeout.unwrap_or_else(|| app.config.settings.stop_timeout());
|
||||||
if let Some(group) = crate::catalog::Catalog::parse_group_selector(&opts.agent) {
|
let cwd = std::env::current_dir().unwrap_or_default();
|
||||||
|
let target = resolve_start_target(app, &cwd, opts.agent.as_deref())?;
|
||||||
|
if let Some(group) = crate::catalog::Catalog::parse_group_selector(&target) {
|
||||||
let members = app.catalog.group_members(group);
|
let members = app.catalog.group_members(group);
|
||||||
if members.is_empty() {
|
if members.is_empty() {
|
||||||
bail!("unknown group '{group}'");
|
bail!("unknown group '{group}'");
|
||||||
@@ -212,7 +229,7 @@ pub fn restart(app: &App, opts: &StartArgs, force: bool, timeout: Option<u64>) -
|
|||||||
}
|
}
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
let agent = require_agent(app, &opts.agent)?;
|
let agent = require_agent(app, &target)?;
|
||||||
stop_one(app, agent, force, timeout)?;
|
stop_one(app, agent, force, timeout)?;
|
||||||
let extra_env = parse_env_list(&opts.env)?;
|
let extra_env = parse_env_list(&opts.env)?;
|
||||||
let extra_args = parse_extra_args(&opts.args);
|
let extra_args = parse_extra_args(&opts.args);
|
||||||
|
|||||||
+2
-2
@@ -1283,7 +1283,7 @@ fn handle_line(
|
|||||||
agent: need("agent name")?,
|
agent: need("agent name")?,
|
||||||
},
|
},
|
||||||
"start" => Command::Start(StartArgs {
|
"start" => Command::Start(StartArgs {
|
||||||
agent: need("agent name")?,
|
agent: rest.first().cloned(),
|
||||||
background: flag("--background") || flag("-b"),
|
background: flag("--background") || flag("-b"),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
@@ -1294,7 +1294,7 @@ fn handle_line(
|
|||||||
},
|
},
|
||||||
"restart" => Command::Restart {
|
"restart" => Command::Restart {
|
||||||
start: StartArgs {
|
start: StartArgs {
|
||||||
agent: need("agent name")?,
|
agent: rest.first().cloned(),
|
||||||
background: flag("--background") || flag("-b"),
|
background: flag("--background") || flag("-b"),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ fn start_and_stop_emit_a_matching_pair() {
|
|||||||
app.state.set(&entry).unwrap();
|
app.state.set(&entry).unwrap();
|
||||||
|
|
||||||
let opts = StartArgs {
|
let opts = StartArgs {
|
||||||
agent: "sleeper".to_string(),
|
agent: Some("sleeper".to_string()),
|
||||||
background: true,
|
background: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -75,5 +75,18 @@ projects:
|
|||||||
);
|
);
|
||||||
// Hors du projet : pas de profil.
|
// Hors du projet : pas de profil.
|
||||||
assert!(projects::default_agent_for_dir(&app, &std::env::temp_dir()).is_none());
|
assert!(projects::default_agent_for_dir(&app, &std::env::temp_dir()).is_none());
|
||||||
|
|
||||||
|
// am start contextuel (issue #30) : résolution pure sans changer de cwd.
|
||||||
|
use agent_manager::commands::run_cmd;
|
||||||
|
assert_eq!(
|
||||||
|
run_cmd::resolve_start_target(&app, &sub, None).unwrap(),
|
||||||
|
"claude-code"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
run_cmd::resolve_start_target(&app, &sub, Some("aider")).unwrap(),
|
||||||
|
"aider"
|
||||||
|
);
|
||||||
|
assert!(run_cmd::resolve_start_target(&app, &std::env::temp_dir(), None).is_err());
|
||||||
|
|
||||||
let _ = std::fs::remove_dir_all(&dir);
|
let _ = std::fs::remove_dir_all(&dir);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user