From 2eaafe6e2a566a0f0b1e13fd7a97c4e72077958e Mon Sep 17 00:00:00 2001 From: Bruno Charest Date: Mon, 17 Aug 2026 07:52:17 -0400 Subject: [PATCH] v0.3.0 : picoclaw en binaire 64-bit officiel (sipeed/picoclaw releases) + shims git en .cmd sur Windows (fini le batch renomme en .exe qui donnait Unsupported 16-Bit Application) avec routage via cmd.exe --- config.yaml | 7 +++---- src/commands/mod.rs | 47 +++++++++++++++++++++++++++++++++++++++++++ src/installers/git.rs | 13 +++++++++++- 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/config.yaml b/config.yaml index 255920e..4f960e0 100644 --- a/config.yaml +++ b/config.yaml @@ -829,10 +829,9 @@ agents: category: assistant website: https://github.com/sipeed/picoclaw install: - type: git - repo: "https://github.com/sipeed/picoclaw" - dependencies: - - { name: go, min_version: "1.21.0", install_hint: "https://go.dev/dl" } + type: binary + repo: sipeed/picoclaw + binary: picoclaw run: picoclaw tags: [go, tiny] diff --git a/src/commands/mod.rs b/src/commands/mod.rs index e921759..1ec7a76 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -175,9 +175,26 @@ pub fn resolve_exec( args.extend(extra_args.iter().cloned()); let mut env = agent.env.clone(); env.extend(extra_env.clone()); + let (program, args) = route_cmd_script(program, args); Ok(ResolvedExec { program, args, env }) } +/// On Windows, .cmd/.bat shims (git installs without a build step) must be +/// executed through cmd.exe — spawning them directly fails. +pub fn route_cmd_script(program: String, args: Vec) -> (String, Vec) { + let lower = program.to_lowercase(); + if cfg!(windows) && (lower.ends_with(".cmd") || lower.ends_with(".bat")) { + let shell = std::env::var_os("COMSPEC") + .map(|s| s.to_string_lossy().to_string()) + .unwrap_or_else(|| "cmd.exe".to_string()); + let mut full = vec!["/C".to_string(), program]; + full.extend(args); + (shell, full) + } else { + (program, args) + } +} + /// Parse --env KEY=VALUE entries. pub fn parse_env_list(items: &[String]) -> Result> { let mut map = BTreeMap::new(); @@ -273,3 +290,33 @@ pub fn select_method<'a>( } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn routes_cmd_scripts_through_comspec() { + let (program, args) = route_cmd_script( + "C:/x/agent.cmd".to_string(), + vec!["--flag".to_string()], + ); + let lower = program.to_lowercase(); + if cfg!(windows) { + assert!(lower.ends_with("cmd.exe"), "{program}"); + assert_eq!(args[0], "/C"); + assert_eq!(args[1], "C:/x/agent.cmd"); + assert_eq!(args[2], "--flag"); + } else { + assert_eq!(program, "C:/x/agent.cmd"); + assert_eq!(args, vec!["--flag".to_string()]); + } + } + + #[test] + fn leaves_regular_programs_untouched() { + let (program, args) = route_cmd_script("node".to_string(), vec!["-v".to_string()]); + assert_eq!(program, "node"); + assert_eq!(args, vec!["-v".to_string()]); + } +} diff --git a/src/installers/git.rs b/src/installers/git.rs index 709c6d6..d046774 100644 --- a/src/installers/git.rs +++ b/src/installers/git.rs @@ -97,7 +97,7 @@ pub fn install( .with_context(|| format!("cannot copy {} to {}", src.display(), dest.display()))?; bins.push(dest); } else { - let shim = bindir.join(exe_name(&bin_name)); + let shim = bindir.join(shim_name(&bin_name)); write_shim(agent, &shim, &repo_dir)?; bins.push(shim); } @@ -132,6 +132,17 @@ pub fn install( Ok(InstallOutcome { bins, version }) } +/// File name of the shim for an agent: a .cmd script on Windows (a batch +/// file renamed to .exe would fail with "Unsupported 16-Bit Application"), +/// a plain executable name elsewhere. +fn shim_name(bin_name: &str) -> String { + if cfg!(windows) { + format!("{bin_name}.cmd") + } else { + bin_name.to_string() + } +} + /// Create a small script that runs the agent from inside the repository /// directory (with node_modules/.bin on PATH for Node-based projects). fn write_shim(agent: &AgentDef, shim: &Path, repo_dir: &Path) -> Result<()> {