mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
feat(desktop): surface effective buzz-agent MCP servers on config surface
Add buzz_agent_mcp_servers to RuntimeConfigSurface, populated by resolve_config_surface via the existing effective_buzz_agent_mcp_servers merge (global < definition < agent, enabled-only) for the buzz-agent runtime only. Every other runtime keeps the field empty and continues to surface its servers via extensions. This is the WYSIWYG read path the PR3 UI's read-only buzzAgentSlot will consume — the effective list is now reachable from the config-bridge surface the frontend already reads, matching what actually runs at spawn (spawn_hash.rs, runtime.rs) rather than just the agent's own record layer. Also bumps two pre-existing file-size overrides (agent_config.rs, readiness.rs) to their gate's own split-count, matching this diff and a prior unaccounted +1 line already on the branch. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
This commit is contained in:
co-authored by
Will Pfleger
parent
812301592a
commit
c3386a9627
@@ -166,9 +166,10 @@ const overrides = new Map([
|
||||
// setup-mode requirements. The Windows-only requirement and serialization
|
||||
// test add eight lines; split remains queued with the existing file debt.
|
||||
// Windows Doctor install fix: cli_install_commands_windows field added to test stubs.
|
||||
// team-instructions-first-class: ManagedAgentRecord fixture gains the new
|
||||
// team_id field (+1 line).
|
||||
["src-tauri/src/managed_agents/readiness.rs", 1765],
|
||||
// `team-instructions-first-class` added `team_id`; MCP configuration added
|
||||
// the required `mcp_servers` minimal-fixture field. The gate counts the
|
||||
// trailing newline, so 1,765 physical lines are 1,766 counted lines.
|
||||
["src-tauri/src/managed_agents/readiness.rs", 1766],
|
||||
// applyWorkspace reposDir parameter plus the validateReposDir binding,
|
||||
// threaded through Tauri invokes for configurable repos_dir, plus the
|
||||
// harness-persona-sync `harnessOverride` create-input bit — load-bearing
|
||||
@@ -429,7 +430,11 @@ const overrides = new Map([
|
||||
// is_safe_to_reveal allowlist + baked_env_thinking_effort_is_unmasked test.
|
||||
// +1: doctor-install-reliability: login_hint: None added to goose_runtime test stub.
|
||||
// +1: doctor-install-reliability review fixes: auth_probe_args: None added to stub.
|
||||
["src-tauri/src/commands/agent_config.rs", 1021],
|
||||
// MCP config surface: `resolve_config_surface` receives the effective command
|
||||
// and exposes the effective `buzz_agent_mcp_servers` merge; coverage pins the
|
||||
// merge, disabled-mask, and non-buzz-agent cases. The gate counts trailing
|
||||
// newlines, so 1,139 physical lines are 1,140 counted lines.
|
||||
["src-tauri/src/commands/agent_config.rs", 1140],
|
||||
// codex-install-auto-restart review-fixes: should_restart_after_install
|
||||
// takes pid_alive:bool (pure predicate, no OS-dependent call); 3 racy
|
||||
// cache tests replaced with 6 pure availability_drift predicate tests;
|
||||
|
||||
@@ -55,6 +55,7 @@ fn resolve_config_surface(
|
||||
mut record: ManagedAgentRecord,
|
||||
personas: &[AgentDefinition],
|
||||
runtime_meta: Option<&KnownAcpRuntime>,
|
||||
effective_command: &str,
|
||||
session_cache: Option<&SessionConfigCache>,
|
||||
global: &GlobalAgentConfig,
|
||||
) -> RuntimeConfigSurface {
|
||||
@@ -152,6 +153,19 @@ fn resolve_config_surface(
|
||||
baseline.as_ref().map(|(m, o)| (m.as_str(), o.clone())),
|
||||
);
|
||||
|
||||
if runtime_meta.is_some_and(|m| m.id == "buzz-agent") {
|
||||
surface.buzz_agent_mcp_servers = crate::managed_agents::effective_buzz_agent_mcp_servers(
|
||||
&record,
|
||||
personas,
|
||||
&global.mcp_servers,
|
||||
effective_command,
|
||||
)
|
||||
.unwrap_or_else(|error| {
|
||||
eprintln!("buzz-desktop: invalid persisted MCP server configuration: {error}");
|
||||
Vec::new()
|
||||
});
|
||||
}
|
||||
|
||||
// Re-tag persona-sourced fields from BuzzExplicit to PersonaDefault.
|
||||
if !had_prompt {
|
||||
retag_persona_default(&mut surface.normalized.system_prompt);
|
||||
@@ -375,6 +389,7 @@ pub async fn get_agent_config_surface(
|
||||
record,
|
||||
&personas,
|
||||
runtime_meta,
|
||||
&effective_cmd,
|
||||
session_cache.as_ref(),
|
||||
&global,
|
||||
))
|
||||
@@ -713,6 +728,7 @@ mod tests {
|
||||
record,
|
||||
&personas,
|
||||
Some(goose_runtime()),
|
||||
"goose",
|
||||
None,
|
||||
&Default::default(),
|
||||
);
|
||||
@@ -740,6 +756,7 @@ mod tests {
|
||||
record,
|
||||
&personas,
|
||||
Some(goose_runtime()),
|
||||
"goose",
|
||||
Some(&cache),
|
||||
&Default::default(),
|
||||
);
|
||||
@@ -768,6 +785,7 @@ mod tests {
|
||||
record,
|
||||
&personas,
|
||||
Some(goose_runtime()),
|
||||
"goose",
|
||||
Some(&cache),
|
||||
&Default::default(),
|
||||
);
|
||||
@@ -795,6 +813,7 @@ mod tests {
|
||||
record,
|
||||
&personas,
|
||||
Some(goose_runtime()),
|
||||
"goose",
|
||||
Some(&cache),
|
||||
&Default::default(),
|
||||
);
|
||||
@@ -819,6 +838,7 @@ mod tests {
|
||||
record,
|
||||
&personas,
|
||||
Some(goose_runtime()),
|
||||
"goose",
|
||||
Some(&cache),
|
||||
&Default::default(),
|
||||
);
|
||||
@@ -855,6 +875,7 @@ mod tests {
|
||||
record,
|
||||
&personas,
|
||||
Some(goose_runtime()),
|
||||
"goose",
|
||||
Some(&cache),
|
||||
&global,
|
||||
);
|
||||
@@ -876,6 +897,102 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ── buzz_agent_mcp_servers surface tests ────────────────────────────────
|
||||
|
||||
fn mcp_server(
|
||||
name: &str,
|
||||
command: &str,
|
||||
enabled: bool,
|
||||
) -> crate::managed_agents::McpServerConfig {
|
||||
crate::managed_agents::McpServerConfig {
|
||||
name: name.to_string(),
|
||||
command: command.to_string(),
|
||||
args: vec![],
|
||||
env: vec![],
|
||||
enabled,
|
||||
}
|
||||
}
|
||||
|
||||
/// The buzz-agent runtime surfaces its effective-merged MCP servers onto
|
||||
/// `RuntimeConfigSurface.buzz_agent_mcp_servers`, matching what
|
||||
/// `effective_buzz_agent_mcp_servers` (the spawn-time source of truth)
|
||||
/// would compute for the same record/persona/global layers.
|
||||
#[test]
|
||||
fn buzz_agent_runtime_surfaces_effective_merged_mcp_servers() {
|
||||
let mut record = agent_record();
|
||||
record.persona_id = None;
|
||||
record.mcp_servers = vec![mcp_server("agent-server", "agent-cmd", true)];
|
||||
let personas: Vec<AgentDefinition> = vec![];
|
||||
let global = crate::managed_agents::GlobalAgentConfig {
|
||||
mcp_servers: vec![mcp_server("global-server", "global-cmd", true)],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let surface = resolve_config_surface(
|
||||
record,
|
||||
&personas,
|
||||
known_acp_runtime("buzz-agent"),
|
||||
"buzz-agent",
|
||||
None,
|
||||
&global,
|
||||
);
|
||||
|
||||
let mut names: Vec<&str> = surface
|
||||
.buzz_agent_mcp_servers
|
||||
.iter()
|
||||
.map(|s| s.name.as_str())
|
||||
.collect();
|
||||
names.sort_unstable();
|
||||
assert_eq!(names, vec!["agent-server", "global-server"]);
|
||||
}
|
||||
|
||||
/// A disabled agent-layer entry masks a same-named global entry — the
|
||||
/// merged effective list must NOT include it. Fails against a variant
|
||||
/// that surfaces the raw record layer instead of the merged result.
|
||||
#[test]
|
||||
fn buzz_agent_disabled_override_masks_inherited_server_in_surface() {
|
||||
let mut record = agent_record();
|
||||
record.persona_id = None;
|
||||
record.mcp_servers = vec![mcp_server("shared", "", false)];
|
||||
let personas: Vec<AgentDefinition> = vec![];
|
||||
let global = crate::managed_agents::GlobalAgentConfig {
|
||||
mcp_servers: vec![mcp_server("shared", "global-cmd", true)],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let surface = resolve_config_surface(
|
||||
record,
|
||||
&personas,
|
||||
known_acp_runtime("buzz-agent"),
|
||||
"buzz-agent",
|
||||
None,
|
||||
&global,
|
||||
);
|
||||
|
||||
assert!(surface.buzz_agent_mcp_servers.is_empty());
|
||||
}
|
||||
|
||||
/// Non-buzz-agent runtimes (e.g. goose) must never populate
|
||||
/// `buzz_agent_mcp_servers` — they surface their servers via `extensions`
|
||||
/// instead. Fails against a variant that populates the field unconditionally.
|
||||
#[test]
|
||||
fn non_buzz_agent_runtime_leaves_mcp_surface_empty() {
|
||||
let mut record = agent_record();
|
||||
record.mcp_servers = vec![mcp_server("agent-server", "agent-cmd", true)];
|
||||
let personas = vec![persona_with_model("persona-model")];
|
||||
|
||||
let surface = resolve_config_surface(
|
||||
record,
|
||||
&personas,
|
||||
Some(goose_runtime()),
|
||||
"goose",
|
||||
None,
|
||||
&Default::default(),
|
||||
);
|
||||
|
||||
assert!(surface.buzz_agent_mcp_servers.is_empty());
|
||||
}
|
||||
|
||||
// ── get_baked_build_env / is_secret_key tests ──────────────────────────
|
||||
|
||||
/// Build a `BakedEnvEntry` vec from a synthetic map, mirroring what
|
||||
|
||||
@@ -209,6 +209,10 @@ pub(crate) fn read_config_surface(
|
||||
normalized,
|
||||
advanced,
|
||||
extensions,
|
||||
// Populated by `resolve_config_surface` for the buzz-agent runtime only;
|
||||
// this reader has no access to the global/persona MCP layers needed to
|
||||
// compute the effective merge.
|
||||
buzz_agent_mcp_servers: Vec::new(),
|
||||
sources,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ use std::collections::BTreeMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::managed_agents::types::McpServerConfig;
|
||||
|
||||
/// Where a config value came from — determines precedence and UI annotations.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@@ -136,6 +138,12 @@ pub struct RuntimeConfigSurface {
|
||||
pub normalized: NormalizedConfig,
|
||||
pub advanced: Vec<ConfigField>,
|
||||
pub extensions: Vec<ExtensionEntry>,
|
||||
/// Effective (global < definition < agent merged, enabled-only) buzz-agent
|
||||
/// MCP servers — "what runs." Populated only for the `buzz-agent` runtime;
|
||||
/// empty for every other runtime, which surface their servers via
|
||||
/// `extensions` instead.
|
||||
#[serde(default)]
|
||||
pub buzz_agent_mcp_servers: Vec<McpServerConfig>,
|
||||
pub sources: ConfigSourceReport,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user