mirror of
https://github.com/block/buzz.git
synced 2026-11-05 00:41:28 +00:00
🤖 I’m Larry, updating this description on Logan’s behalf. ## Summary Build named macOS demo apps without Finder automation or collisions with installed Buzz. `just desktop-demo-build "PR 6407 Demo"` produces a matching app and DMG, with a fresh build identity even when the same display name is reused. - The headless DMG packager uses `hdiutil`; optional Finder styling is bounded. The existing production release recipe is unchanged. - Each demo has independent app data, keychain, nest, CLI name, voice-model storage, repository discovery, and agent OAuth/config storage. Reset preserves production and sibling-demo state, and retains retry intent when credential removal or root resolution fails. - Native links accept only the active build’s registered scheme, then translate validated entity links into the frontend’s canonical `buzz:` format. - The recipe builds all six executable sidecars. Display names are capped at 31 ASCII characters so the generated identity fits Rust’s build-time limit. **Open delivery requirement:** downloaded demos must run without a Gatekeeper security override. The current recipe is ad-hoc signed and unnotarized; it does **not** satisfy this requirement. Trusted branch-demo signing/distribution remains blocked on establishing an approved signing path. This PR is not being presented as complete download-and-run delivery. ### Related issue N/A — reported in the Buzz DMG-packaging workstream. ### Testing At `11ce21ff97cb387ad676e7caa65b00964097d0bb`, macOS Blox passed the Tauri workspace suite and compiled-flags gate (including the full named-demo state; each library pass: 2,992 passed, 19 ignored), Tauri all-target clippy, the full `buzz-agent` package suite, and frontend lint/typecheck plus 5,733 tests. Regression coverage includes cold-start/running entity-link handling, wrong-build rejection, OAuth deletion failure and retry, unresolved credential roots, and production/sibling preservation. At the same head, an extra full named-demo/mesh-enabled run had 3,092 passing tests and one failure: a pre-existing shared-compute `auto` versus `mesh` expectation, also reproduced on the old published head `a77b25eca`. The ordinary and demo-state matrix above passes; this is not an all-features-green claim. Live macOS Launch Services delivery remains unverified. GitHub CI completed with 30 successful checks and 9 skipped. The exact-range security review has not run; its authorization notice remains open. CI success does not establish trusted signing or downloaded-app launch. Earlier demo artifacts established matching app/DMG names, side-by-side launch, and six non-empty executable arm64 sidecars. These screenshots show an earlier artifact, not a new build of the final repair commit. Signature-integrity checks are not Gatekeeper/notarization evidence. <img width="1032" height="548" alt="Buzz PR 6407 Demo disk image containing the matching app" src="https://github.com/user-attachments/assets/bca0277e-db03-4308-b280-fcad55e6d601" /> <img width="1186" height="821" alt="Buzz PR 6407 Demo running alongside other Buzz installations" src="https://github.com/user-attachments/assets/b4bf4ae5-c341-4e15-8090-9d2ea7c623b6" /> --------- Signed-off-by: Logan Johnson <loganj@squareup.com> Signed-off-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz> Co-authored-by: Other Brother Darryl <cee32d92756729ee0c097c5661b879c6199931cd25315c8cf398dcbf0f155cf1@buzz.block.builderlab.xyz> Co-authored-by: Larry <loganj+sandbox-larry@squareup.com> Co-authored-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
87 lines
3.8 KiB
Rust
87 lines
3.8 KiB
Rust
use std::{collections::BTreeMap, path::PathBuf};
|
|
|
|
use crate::managed_agents::{
|
|
build_buzz_agent_provider_defaults, default_agent_workdir, known_acp_runtime,
|
|
redact_env_values_in, AgentModelsResponse,
|
|
};
|
|
|
|
use super::agent_models::normalize_agent_models;
|
|
|
|
pub(super) async fn run_agent_models_command(
|
|
resolved_acp: PathBuf,
|
|
agent_command: String,
|
|
agent_args: Vec<String>,
|
|
persisted_model: Option<String>,
|
|
merged_env: BTreeMap<String, String>,
|
|
) -> Result<AgentModelsResponse, String> {
|
|
// Clone the env map for redaction below — `merged_env` is moved
|
|
// into the spawn_blocking closure and we still need the values to
|
|
// scrub any user-supplied secrets that the child surfaces in stderr.
|
|
let env_for_redaction = merged_env.clone();
|
|
|
|
// Use spawn_blocking because the desktop Tauri crate doesn't enable
|
|
// tokio's `process` feature. std::process::Command is synchronous
|
|
// but fine for a short-lived subprocess (~2-5s).
|
|
let output = tokio::task::spawn_blocking(move || {
|
|
let mut cmd = std::process::Command::new(&resolved_acp);
|
|
if let Some(home) = default_agent_workdir() {
|
|
cmd.current_dir(home);
|
|
}
|
|
// Inject the same augmented PATH used for launched agents and CLI
|
|
// probes: managed Node/npm dirs, exe-parent sidecars, login-shell
|
|
// PATH, and (Windows) the inherited process PATH. login_shell_path()
|
|
// alone is always None on Windows, which left this child with no
|
|
// managed Node dirs — the ACP adapter's `.cmd` shims then failed with
|
|
// `'node' is not recognized` and the model dropdown stayed empty.
|
|
if let Some(ref path) = crate::managed_agents::readiness::cli_probe::augmented_path() {
|
|
cmd.env("PATH", path);
|
|
}
|
|
cmd.arg("models")
|
|
.arg("--json")
|
|
.env("BUZZ_ACP_AGENT_COMMAND", &agent_command)
|
|
.env("BUZZ_ACP_AGENT_ARGS", agent_args.join(","));
|
|
if let Some(meta) = known_acp_runtime(&agent_command) {
|
|
for (key, value) in meta.default_env {
|
|
if std::env::var(key).is_err() {
|
|
cmd.env(key, value);
|
|
}
|
|
}
|
|
}
|
|
// Mirror runtime spawn: internal builds may bake provider/model
|
|
// defaults. User-provided env below still wins.
|
|
build_buzz_agent_provider_defaults(&mut cmd);
|
|
// User env layering — written LAST so it overrides any Buzz-set env above.
|
|
for (k, v) in &merged_env {
|
|
cmd.env(k, v);
|
|
}
|
|
// Demo identity is authoritative and must win over ambient/user env.
|
|
crate::build_identity::apply_demo_config_home(&mut cmd)?;
|
|
crate::managed_agents::configure_runtime_cli(&mut cmd, known_acp_runtime(&agent_command));
|
|
crate::util::configure_no_window(&mut cmd);
|
|
cmd.stdout(std::process::Stdio::piped())
|
|
.stderr(std::process::Stdio::piped())
|
|
.output()
|
|
.map_err(|e| format!("failed to spawn buzz-acp models: {e}"))
|
|
})
|
|
.await
|
|
.map_err(|e| format!("model discovery task failed: {e}"))?
|
|
.map_err(|e: String| e)?;
|
|
|
|
if !output.status.success() {
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
// Scrub any user-supplied env values before surfacing stderr to
|
|
// the frontend — persona/agent env_vars may carry API keys that
|
|
// a failing child process echoed back.
|
|
let stderr_redacted = redact_env_values_in(stderr.as_ref(), &env_for_redaction);
|
|
return Err(format!(
|
|
"buzz-acp models failed (exit {}): {stderr_redacted}",
|
|
output.status.code().unwrap_or(-1)
|
|
));
|
|
}
|
|
|
|
let raw: serde_json::Value = serde_json::from_slice(&output.stdout)
|
|
.map_err(|e| format!("failed to parse model JSON: {e}"))?;
|
|
|
|
Ok(normalize_agent_models(&raw, persisted_model))
|
|
}
|