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

This commit is contained in:
2026-08-17 07:52:17 -04:00
parent deeb489b4e
commit 2eaafe6e2a
3 changed files with 62 additions and 5 deletions
+3 -4
View File
@@ -829,10 +829,9 @@ agents:
category: assistant category: assistant
website: https://github.com/sipeed/picoclaw website: https://github.com/sipeed/picoclaw
install: install:
type: git type: binary
repo: "https://github.com/sipeed/picoclaw" repo: sipeed/picoclaw
dependencies: binary: picoclaw
- { name: go, min_version: "1.21.0", install_hint: "https://go.dev/dl" }
run: picoclaw run: picoclaw
tags: [go, tiny] tags: [go, tiny]
+47
View File
@@ -175,9 +175,26 @@ pub fn resolve_exec(
args.extend(extra_args.iter().cloned()); args.extend(extra_args.iter().cloned());
let mut env = agent.env.clone(); let mut env = agent.env.clone();
env.extend(extra_env.clone()); env.extend(extra_env.clone());
let (program, args) = route_cmd_script(program, args);
Ok(ResolvedExec { program, args, env }) 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>) -> (String, Vec<String>) {
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. /// Parse --env KEY=VALUE entries.
pub fn parse_env_list(items: &[String]) -> Result<BTreeMap<String, String>> { pub fn parse_env_list(items: &[String]) -> Result<BTreeMap<String, String>> {
let mut map = BTreeMap::new(); 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()]);
}
}
+12 -1
View File
@@ -97,7 +97,7 @@ pub fn install(
.with_context(|| format!("cannot copy {} to {}", src.display(), dest.display()))?; .with_context(|| format!("cannot copy {} to {}", src.display(), dest.display()))?;
bins.push(dest); bins.push(dest);
} else { } else {
let shim = bindir.join(exe_name(&bin_name)); let shim = bindir.join(shim_name(&bin_name));
write_shim(agent, &shim, &repo_dir)?; write_shim(agent, &shim, &repo_dir)?;
bins.push(shim); bins.push(shim);
} }
@@ -132,6 +132,17 @@ pub fn install(
Ok(InstallOutcome { bins, version }) 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 /// Create a small script that runs the agent from inside the repository
/// directory (with node_modules/.bin on PATH for Node-based projects). /// directory (with node_modules/.bin on PATH for Node-based projects).
fn write_shim(agent: &AgentDef, shim: &Path, repo_dir: &Path) -> Result<()> { fn write_shim(agent: &AgentDef, shim: &Path, repo_dir: &Path) -> Result<()> {