mirror of
https://github.com/block/buzz.git
synced 2026-11-02 15:31:27 +00:00
## Summary Fixes two distinct fidelity failures in direct agent sharing: - The sender now puts the same effective avatar shown on the agent card into People-share and file-export snapshot PNGs, including profile/kind:0 fallback avatars. - The importer now persists the visible PNG body as the portable avatar instead of ignoring it in favor of sender-local manifest references. - Export materializes inherited runtime, provider, and model identifiers verbatim, while preserving explicit definition values. It does not translate or substitute configuration for a different recipient setup. - Sharing waits for a profile-only fallback avatar query, preventing an early-click race. The PNG import path keeps the existing safety invariant: decode is capped at 2048×2048 / 32 MiB and re-encoded avatars above the 2 MiB inline limit fall back to the manifest reference. The exact transparent 1×1 no-avatar placeholder is ignored. The original Tyler↔Wes screenshot demonstrates both stages: Wren's attachment had an avatar that disappeared after **Add agent** (receiver/import failure), while Pinky's attachment was already blank (sender/projection failure). ### Related issue N/A — reported and traced in the linked Buzz conversation. ### Testing - `cargo test --manifest-path desktop/src-tauri/Cargo.toml commands::personas::snapshot` — 57 passed - `pnpm exec tsc --noEmit` - Biome check on changed frontend/E2E files - Pre-push hooks: - desktop check - desktop tests - desktop Tauri tests — 1853 passed, 14 ignored - file-size ratchet The People-share E2E regression asserts that a profile-only avatar reaches `avatarPngDataUrl` in the real encode command payload. --------- Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
112 lines
3.4 KiB
Rust
112 lines
3.4 KiB
Rust
mod agent_env;
|
|
pub(crate) mod agent_events;
|
|
pub(crate) mod agent_snapshot;
|
|
pub(crate) mod team_snapshot;
|
|
pub(crate) use agent_env::{
|
|
baked_build_env, build_buzz_agent_provider_defaults, discovery_env_with_baked_floor,
|
|
};
|
|
mod backend;
|
|
pub(crate) mod config_bridge;
|
|
pub(crate) mod custom_harnesses;
|
|
mod discovery;
|
|
pub(crate) mod effective_config;
|
|
mod env_vars;
|
|
pub(crate) mod git_bash;
|
|
pub(crate) mod global_config;
|
|
mod managed_node_paths;
|
|
mod nest;
|
|
mod persona_avatars;
|
|
pub(crate) mod persona_events;
|
|
mod personas;
|
|
#[cfg(windows)]
|
|
mod process_lifecycle;
|
|
pub(crate) mod readiness;
|
|
pub(crate) mod reconcile;
|
|
mod relay_mesh;
|
|
mod repos;
|
|
mod restore;
|
|
pub mod retention;
|
|
mod runtime;
|
|
mod runtime_commands;
|
|
mod runtime_types;
|
|
pub(crate) mod snapshot_avatar;
|
|
pub(crate) mod spawn_hash;
|
|
pub(crate) mod storage;
|
|
pub(crate) mod team_events;
|
|
mod team_repair;
|
|
mod teams;
|
|
mod types;
|
|
|
|
// Shared guard for tests that mutate or read process-global PATH.
|
|
#[cfg(test)]
|
|
static PATH_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(());
|
|
|
|
#[cfg(test)]
|
|
pub(crate) fn lock_path_mutex() -> std::sync::MutexGuard<'static, ()> {
|
|
PATH_MUTEX.lock().unwrap_or_else(|e| e.into_inner())
|
|
}
|
|
|
|
pub use backend::*;
|
|
pub use discovery::*;
|
|
pub use env_vars::*;
|
|
#[cfg(windows)]
|
|
pub(crate) use git_bash::git_bash_available;
|
|
pub(crate) use git_bash::{discover_git_bash, GitBashPrerequisite};
|
|
pub(crate) use global_config::{
|
|
load_global_agent_config, resolve_effective_model_provider, save_global_agent_config,
|
|
validate_global_config, GlobalAgentConfig,
|
|
};
|
|
pub(crate) use managed_node_paths::*;
|
|
pub use nest::*;
|
|
pub use personas::*;
|
|
#[cfg(windows)]
|
|
pub use process_lifecycle::*;
|
|
pub(crate) use readiness::{
|
|
agent_readiness, resolve_effective_agent_env, resolve_effective_harness_descriptor,
|
|
AgentReadiness, Requirement,
|
|
};
|
|
pub use relay_mesh::*;
|
|
pub use repos::{
|
|
effective_repos_dir, ensure_repos_symlink, resolve_repos_at_boot, validate_repos_dir,
|
|
write_persisted_repos_dir,
|
|
};
|
|
pub use restore::*;
|
|
pub use runtime::*;
|
|
pub use runtime_commands::*;
|
|
pub use runtime_types::*;
|
|
pub use storage::*;
|
|
pub use teams::*;
|
|
pub use types::*;
|
|
|
|
/// Returns the Buzz nest directory (`~/.buzz`) if it exists as a real
|
|
/// directory (not a symlink), falling back to the user's home directory.
|
|
///
|
|
/// Used as the default working directory for spawned agent processes.
|
|
/// `ensure_nest()` must be called during app setup before this is first
|
|
/// invoked, so that `~/.buzz` exists and gets cached.
|
|
///
|
|
/// Cached for the process lifetime via `OnceLock`.
|
|
/// Returns `None` in sandboxed/containerized environments where `$HOME` is
|
|
/// unset or points to a non-existent path; callers fall back to inheriting
|
|
/// the parent's CWD.
|
|
pub fn default_agent_workdir() -> Option<std::path::PathBuf> {
|
|
use std::sync::OnceLock;
|
|
static WORKDIR: OnceLock<Option<std::path::PathBuf>> = OnceLock::new();
|
|
WORKDIR
|
|
.get_or_init(|| {
|
|
// Prefer ~/.buzz if it exists (created by ensure_nest()).
|
|
// Reject symlinks to prevent redirect attacks — is_dir()
|
|
// follows symlinks, so check symlink_metadata() first.
|
|
// Fall back to $HOME for resilience.
|
|
nest_dir()
|
|
.filter(|p| is_real_dir(p))
|
|
.or_else(|| dirs::home_dir().filter(|p| p.is_dir()))
|
|
})
|
|
.clone()
|
|
}
|
|
|
|
/// Returns `true` if `path` is a real directory (not a symlink).
|
|
fn is_real_dir(path: &std::path::Path) -> bool {
|
|
path.symlink_metadata().map(|m| m.is_dir()).unwrap_or(false)
|
|
}
|