mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix(nest): use buzz-dev symlink name for dev builds (#1587)
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
co-authored by
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7
parent
49391d8071
commit
dcbb3ff789
@@ -82,7 +82,10 @@ const overrides = new Map([
|
||||
// to split with the rest of this list.
|
||||
// dev-nest namespace: OnceLock<Option<PathBuf>> + init_nest_dir + constants
|
||||
// added to plumb the dev/prod discriminator. Load-bearing for the D2 nest fix.
|
||||
["src-tauri/src/managed_agents/nest.rs", 1501],
|
||||
// dev-build CLI symlink: cli_link_name helper + is_dev param on
|
||||
// ensure_cli_symlink + prod/dev test variants add ~68 lines. Load-bearing;
|
||||
// queued to split with the rest of this list.
|
||||
["src-tauri/src/managed_agents/nest.rs", 1569],
|
||||
// harness-persona-sync: persona-runtime resolution threaded into the spawn
|
||||
// path here. Load-bearing feature growth; queued to split in the resolver
|
||||
// unify refactor followup. +26 for resolve_effective_prompt_model_provider
|
||||
|
||||
@@ -323,7 +323,7 @@ pub fn run() {
|
||||
// bundled CLI binary. Non-fatal: agents find CLI via PATH.
|
||||
if let Ok(exe) = std::env::current_exe() {
|
||||
if let Some(parent) = exe.parent() {
|
||||
if let Err(error) = managed_agents::ensure_cli_symlink(parent) {
|
||||
if let Err(error) = managed_agents::ensure_cli_symlink(parent, is_dev_nest) {
|
||||
eprintln!("buzz-desktop: failed to create CLI symlink: {error}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,16 +306,35 @@ fn ensure_skill_symlinks(_root: &Path) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Ensures `~/.local/bin/buzz` is a symlink to the bundled CLI binary.
|
||||
/// Returns the `~/.local/bin` link name for the bundled CLI.
|
||||
///
|
||||
/// On every boot: replaces any existing symlink unconditionally (the `buzz`
|
||||
/// name is our namespace), creates a new one if absent, and leaves regular
|
||||
/// files alone to avoid clobbering a user-compiled binary.
|
||||
/// Dev builds (`is_dev = true`) use `"buzz-dev"` so that a running DMG and a
|
||||
/// concurrent dev build each own a separate link and never clobber each other —
|
||||
/// the same isolation that separates `~/.buzz` (prod) from `~/.buzz-dev` (dev).
|
||||
pub fn cli_link_name(is_dev: bool) -> &'static str {
|
||||
if is_dev {
|
||||
"buzz-dev"
|
||||
} else {
|
||||
"buzz"
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensures `~/.local/bin/buzz` (prod) or `~/.local/bin/buzz-dev` (dev) is a
|
||||
/// symlink to the bundled CLI binary.
|
||||
///
|
||||
/// The link name is split by `is_dev` so that an installed DMG and a
|
||||
/// concurrently running dev build each maintain their own symlink and never
|
||||
/// overwrite each other's target — the same isolation that separates the
|
||||
/// `~/.buzz` and `~/.buzz-dev` nests (see [`NEST_DIR_DEV`]).
|
||||
///
|
||||
/// On every boot: replaces any existing symlink unconditionally (the `buzz` /
|
||||
/// `buzz-dev` name is our namespace), creates a new one if absent, and leaves
|
||||
/// regular files alone to avoid clobbering a user-compiled binary.
|
||||
///
|
||||
/// Non-fatal: callers should ignore errors — the symlink is a convenience
|
||||
/// for human Terminal use; agents find the CLI via PATH augmentation.
|
||||
#[cfg(unix)]
|
||||
pub fn ensure_cli_symlink(exe_parent: &Path) -> Result<(), String> {
|
||||
pub fn ensure_cli_symlink(exe_parent: &Path, is_dev: bool) -> Result<(), String> {
|
||||
let buzz_bin = exe_parent.join("buzz");
|
||||
if !buzz_bin.exists() {
|
||||
return Ok(()); // CLI not bundled (e.g., dev builds without sidecars).
|
||||
@@ -327,7 +346,7 @@ pub fn ensure_cli_symlink(exe_parent: &Path) -> Result<(), String> {
|
||||
.join("bin");
|
||||
fs::create_dir_all(&local_bin).map_err(|e| format!("create {}: {e}", local_bin.display()))?;
|
||||
|
||||
let link = local_bin.join("buzz");
|
||||
let link = local_bin.join(cli_link_name(is_dev));
|
||||
match link.symlink_metadata() {
|
||||
Ok(meta) if meta.file_type().is_symlink() => {
|
||||
let _ = fs::remove_file(&link);
|
||||
@@ -351,7 +370,7 @@ pub fn ensure_cli_symlink(exe_parent: &Path) -> Result<(), String> {
|
||||
|
||||
/// No-op on non-Unix platforms — symlink management is macOS/Linux only.
|
||||
#[cfg(not(unix))]
|
||||
pub fn ensure_cli_symlink(_exe_parent: &Path) -> Result<(), String> {
|
||||
pub fn ensure_cli_symlink(_exe_parent: &Path, _is_dev: bool) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -983,19 +1002,29 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_link_name_prod_is_buzz() {
|
||||
assert_eq!(cli_link_name(false), "buzz");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_link_name_dev_is_buzz_dev() {
|
||||
assert_eq!(cli_link_name(true), "buzz-dev");
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn ensure_cli_symlink_creates_symlink() {
|
||||
fn ensure_cli_symlink_creates_symlink_prod() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let exe_parent = tmp.path().join("MacOS");
|
||||
fs::create_dir(&exe_parent).unwrap();
|
||||
fs::write(exe_parent.join("buzz"), "binary").unwrap();
|
||||
|
||||
// Simulate the symlink creation path.
|
||||
let local_bin = tmp.path().join("local_bin");
|
||||
fs::create_dir_all(&local_bin).unwrap();
|
||||
let link = local_bin.join("buzz");
|
||||
|
||||
// Prod link name is "buzz"; simulate the symlink creation path.
|
||||
let link = local_bin.join(cli_link_name(false));
|
||||
std::os::unix::fs::symlink(exe_parent.join("buzz"), &link).unwrap();
|
||||
assert!(link.symlink_metadata().unwrap().file_type().is_symlink());
|
||||
assert_eq!(fs::read_link(&link).unwrap(), exe_parent.join("buzz"));
|
||||
@@ -1003,11 +1032,33 @@ mod tests {
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn ensure_cli_symlink_does_not_clobber_regular_file() {
|
||||
fn ensure_cli_symlink_creates_symlink_dev() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let exe_parent = tmp.path().join("MacOS");
|
||||
fs::create_dir(&exe_parent).unwrap();
|
||||
fs::write(exe_parent.join("buzz"), "binary").unwrap();
|
||||
|
||||
let local_bin = tmp.path().join("local_bin");
|
||||
fs::create_dir_all(&local_bin).unwrap();
|
||||
|
||||
// Dev link must be "buzz-dev", never "buzz".
|
||||
assert_eq!(cli_link_name(true), "buzz-dev");
|
||||
|
||||
let link = local_bin.join(cli_link_name(true));
|
||||
std::os::unix::fs::symlink(exe_parent.join("buzz"), &link).unwrap();
|
||||
assert!(link.symlink_metadata().unwrap().file_type().is_symlink());
|
||||
assert_eq!(fs::read_link(&link).unwrap(), exe_parent.join("buzz"));
|
||||
// Prod link must not exist — the two builds don't touch each other.
|
||||
assert!(!local_bin.join("buzz").exists());
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn ensure_cli_symlink_does_not_clobber_regular_file_prod() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let local_bin = tmp.path().join("local_bin");
|
||||
fs::create_dir_all(&local_bin).unwrap();
|
||||
let link = local_bin.join("buzz");
|
||||
let link = local_bin.join(cli_link_name(false));
|
||||
fs::write(&link, "user-installed binary").unwrap();
|
||||
|
||||
// Regular files are preserved — the Ok(_) branch skips them.
|
||||
@@ -1015,6 +1066,23 @@ mod tests {
|
||||
assert_eq!(fs::read_to_string(&link).unwrap(), "user-installed binary");
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn ensure_cli_symlink_does_not_clobber_regular_file_dev() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let local_bin = tmp.path().join("local_bin");
|
||||
fs::create_dir_all(&local_bin).unwrap();
|
||||
let link = local_bin.join(cli_link_name(true));
|
||||
fs::write(&link, "user-installed buzz-dev binary").unwrap();
|
||||
|
||||
// Regular files at the dev path are also preserved.
|
||||
assert!(link.symlink_metadata().unwrap().file_type().is_file());
|
||||
assert_eq!(
|
||||
fs::read_to_string(&link).unwrap(),
|
||||
"user-installed buzz-dev binary"
|
||||
);
|
||||
}
|
||||
|
||||
fn make_persona(id: &str, display_name: &str) -> PersonaRecord {
|
||||
PersonaRecord {
|
||||
id: id.to_string(),
|
||||
|
||||
Reference in New Issue
Block a user