Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
138ca46
WIP: introduce optional Mesh native capability skeleton
Oct 1, 2026
90a07ff
WIP: gate Mesh SDK and isolate consumer configuration
Oct 1, 2026
c0e750c
Preserve legacy Mesh consumer transport and roster policy
Oct 1, 2026
4255789
WIP: retain Mesh startup and shutdown ownership
Oct 1, 2026
c8a762c
WIP: bound Mesh shutdown and bind app lifetime
Oct 1, 2026
99455f0
Add isolated opt-in native MeshHost smoke test
Oct 1, 2026
0947ddb
WIP: port Mesh discovery with verified roster authority
Oct 1, 2026
2366457
Ignore invalid member discovery notes without blocking Mesh
Oct 1, 2026
caf2440
WIP: wire authenticated Mesh discovery and leased native Start
Oct 1, 2026
0e5c0e9
WIP: add bundled Mesh client controls with selection cleanup
Oct 1, 2026
ac6f12c
Keep Mesh selection alive across relay reconnects
Oct 1, 2026
a6c13c9
Fix strict indexing in Mesh reconnect regression
Oct 1, 2026
ec900e5
Allow Mesh IPC commands and guard frontend ACL wiring
Oct 1, 2026
f902131
Unlock existing encrypted Mesh identities through the OS credential s…
Oct 1, 2026
67335eb
Present Mesh controls as shared compute preferences
Oct 1, 2026
18e4a93
Use donor consumer page and refresh transient Mesh lifecycle
Oct 1, 2026
3394dd2
Test opt-in Mesh plugin page in browser composition
Oct 1, 2026
99a6fc0
Restore Compute consumer to Settings instead of sidebar
Oct 1, 2026
fb9a837
Name Compute view Use shared compute
Oct 1, 2026
2e93d79
Place Compute in community settings with CPU icon
Oct 1, 2026
8b6260e
Keep Compute discoverable in Personal space with community prompt
Oct 1, 2026
38879ea
Revert "Keep Compute discoverable in Personal space with community pr…
Oct 1, 2026
1605f41
Show selected community on shared compute view
Oct 1, 2026
ef16221
Rename Shared compute and remove manual consumer connect action
Oct 1, 2026
c5c4f49
Read community mesh inventory from verified relay discovery
Oct 1, 2026
ed2788d
Separate inventory evidence state and isolate Mesh default ports
Oct 1, 2026
a1af4e0
Checkpoint native Mesh launch grants and consumer ownership ledger
Oct 1, 2026
0884a66
Confirm community roster changes before native reconciliation
Oct 1, 2026
440d136
Match classic roster growth and startup confirmation ordering
Oct 1, 2026
5900abc
Remove unused per-agent Mesh lifetime ledger
Oct 2, 2026
e698b9d
Wire agent startup to current-community Mesh readiness
Oct 2, 2026
b7dd812
Add private serving configuration to the shared Mesh lifecycle
Oct 2, 2026
455c8f4
Build owner-bound community Mesh status notes
Oct 2, 2026
4996bb3
Wire bounded community Mesh heartbeat and SDK status reads
Oct 2, 2026
d3a5fbd
WIP: checkpoint inherited Mesh sharing implementation
Oct 2, 2026
b681c22
Preserve saved Mesh sharing across plugin release and selection
Oct 2, 2026
be1f59f
Explain saved sharing after Disconnect
Oct 2, 2026
3b03e24
Complete shared compute selection and community coordination for preview
Oct 4, 2026
d72dbca
Integrate current app and update shared compute setup
Oct 5, 2026
4fd638d
Let Mesh serving own model acquisition and retain download progress
Oct 5, 2026
1fba91a
Distinguish model preparation from active sharing
Oct 5, 2026
be0af00
Cover Mesh discovery membership and owner-binding regressions
Oct 5, 2026
4e2d61b
Restore Mesh agent defaults and decouple GGUF ladder from layer catalog
Oct 5, 2026
dce464e
Expose Mesh startup diagnostics and reset model recommendation
Oct 5, 2026
af7e403
Persist Auto sharing and reset overrides without restarting Mesh
Oct 5, 2026
4dff272
Merge main into Mesh plugin worktree
Oct 6, 2026
3f5fffb
Update Mesh to v0.78.1 and align Auto browser assertion
Oct 6, 2026
525d684
Keep Mesh bound across navigation and repair admission and peer failures
Oct 6, 2026
9b7ab84
Restore legacy Mesh enrollment and fix shared-compute browser journey
Oct 6, 2026
0816c3a
Simplify Mesh sharing controls to a Share this machine switch
Oct 6, 2026
6eddbad
Show readable model names in the Mesh model picker
Oct 6, 2026
400a600
Advertise Mesh's display names for local-gguf models
Oct 6, 2026
84922f8
Revert "Show readable model names in the Mesh model picker"
Oct 6, 2026
18ee3d0
Remove Mesh Disconnect and make sharing failure states recoverable
Oct 6, 2026
9624110
Let Share off clear saved consent without a lease
Oct 6, 2026
124b208
Fence the Mesh disarm fallback to its originating identity
Oct 6, 2026
810e0cc
Await the retired Share action in Mesh fencing tests
Oct 6, 2026
60e5f8a
Restore legacy Mesh agent readiness and honest model names
Oct 6, 2026
3de4498
Make the Mesh name fallback char-safe, drop the cold scan, fix probe …
Oct 6, 2026
e0abe89
Withdraw Mesh adverts on Share Off and keep explicit agent timeouts
Oct 6, 2026
eac09b5
Compact Mesh sharing card and community summary, one status and Refresh
Oct 6, 2026
8949df4
Re-arm Mesh consumers after Share Off, serialize withdrawal, honest m…
Oct 6, 2026
61de853
Order Mesh withdrawal at the relay, test Off orchestration, correlate…
Oct 6, 2026
b262f36
Test the real Share Off orchestration and report consumer re-arm failure
Oct 6, 2026
a255373
Fence delayed Share Off stops and errors to the original lease
Oct 6, 2026
6208236
Track mesh_compute_disarm in the native command ACL test
Oct 6, 2026
8d45e94
Polish community shared compute and agent setup
sandro-sq Oct 6, 2026
def6be2
Merge main into mesh shared compute branch
Oct 7, 2026
b5100c3
Merge upstream main into Mesh compute preview
Oct 7, 2026
eb9bddd
Fix Mesh admission recovery, restore, join coalescing and picker gating
Oct 7, 2026
32d94b4
Document Mesh recovery and assert unsupported browser inventory stays…
Oct 7, 2026
c3bcf38
Resolve owned Mesh host from app rather than redundant startup argument
Oct 7, 2026
7de6dcd
Avoid unnecessary event clone in Mesh route regression
Oct 7, 2026
e6bf587
Fix saved shared-compute model discovery validation
Oct 9, 2026
0b56ff9
Merge main preserving Mesh and native owner admission
Oct 9, 2026
f0e9d3c
Merge origin/main into jimmy/mesh-share-wip
Oct 10, 2026
c3f380e
Keep saved Mesh discovery fixture compatible with agent effort
Oct 10, 2026
d4ce094
Mark Mesh model catalogs as non-Codex after main integration
Oct 10, 2026
fb65321
test: wait for member roster visibility after confirmation
Oct 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5,322 changes: 4,996 additions & 326 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[workspace]
members = ["crates/pairing", "crates/plugin-manager", "crates/agent-controller", "crates/credential-store", "src-tauri"]
members = ["crates/pairing", "crates/plugin-manager", "crates/agent-controller", "crates/credential-store", "crates/mesh-compute", "src-tauri"]
default-members = ["crates/plugin-manager"]
resolver = "2"
3 changes: 3 additions & 0 deletions crates/agent-controller/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,6 @@ pub use secret::{validate_snapshot_memory_envelope, Credentials, Secret};
pub use skills::ensure_buzz_cli_skill;
pub use store::{ParkedIdentity, Store};
type Result<T> = std::result::Result<T, String>;

mod mesh;
pub use mesh::{MeshLaunch, MeshRequest};
117 changes: 117 additions & 0 deletions crates/agent-controller/src/mesh.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
//! Native-only endpoint configuration for one saved Mesh agent start. Never persisted.
use crate::{config::Agent, Result};

/// Effective saved selectors for the native readiness check; contains no secrets.
pub struct MeshRequest {
pub agent_id: String,
pub revision: u64,
pub relay: String,
pub model: String,
}

impl crate::Controller {
/// Resolve the same defaults and environment used at launch.
pub fn mesh_request(&self, id: &str) -> Result<Option<MeshRequest>> {
let agent = self.mesh_agent(id)?;
if agent.harness.provider != "relay-mesh" {
return Ok(None);
}
if agent.harness.command != "buzz-agent"
|| !agent.imported["record"]["relay_mesh"].is_null()
{
return Err("Shared compute supports the local Buzz Agent harness".into());
}
Ok(Some(MeshRequest {
agent_id: agent.id,
revision: agent.revision,
relay: agent.relay_url,
model: agent.harness.model,
}))
}
}

/// Prepared after node readiness; the app, not an agent process, owns the node.
pub struct MeshLaunch {
agent_id: String,
revision: u64,
relay: String,
model: String,
port: u16,
}

impl MeshLaunch {
/// Create only after native discovery and node readiness succeed.
/// A port, rather than an arbitrary URL, limits child routing to loopback.
pub fn new(
agent_id: String,
revision: u64,
relay: String,
model: String,
port: u16,
) -> Result<Self> {
let grant = Self {
agent_id: agent_id.clone(),
revision,
relay,
model,
port,
};
if grant.port == 0 || grant.model.trim().is_empty() {
return Err("Shared compute requires a ready endpoint and model".into());
}
Ok(grant)
}

pub(crate) fn apply(&self, agent: &Agent) -> Result<Agent> {
let mut agent = agent.clone();
agent.harness = crate::build_defaults().resolve(&agent.harness, &agent.environment);
if agent.id != self.agent_id
|| agent.revision != self.revision
|| agent.relay_url != self.relay
|| agent.harness.provider != "relay-mesh"
|| agent.harness.command != "buzz-agent"
|| !agent.imported["record"]["relay_mesh"].is_null()
{
return Err("Shared compute grant no longer matches the saved agent".into());
}
let mut runtime = agent.clone();
runtime.harness.provider = "openai".into();
runtime.harness.model.clone_from(&self.model);
// Legacy relay_mesh default, not policy: an explicit agent value wins and
// no context window is derived from the catalog (buzz-agent's default applies).
runtime
.environment
.entry("BUZZ_AGENT_MAX_OUTPUT_TOKENS".into())
.or_insert_with(|| "4096".into());
// Explicit last-writer runtime settings; user environment cannot reroute this grant.
// Legacy default just above MeshLLM's 600 s backend budget; a user value wins.
runtime
.environment
.entry("BUZZ_AGENT_LLM_TIMEOUT_SECS".into())
.or_insert_with(|| "660".into());
for (name, value) in [
("BUZZ_AGENT_PROVIDER", "openai".to_owned()),
("BUZZ_AGENT_MODEL", self.model.clone()),
("OPENAI_COMPAT_MODEL", self.model.clone()),
(
"OPENAI_COMPAT_BASE_URL",
format!("http://127.0.0.1:{}/v1", self.port),
),
("OPENAI_COMPAT_API_KEY", "mesh-local".to_owned()),
Comment on lines +96 to +100

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Bind running agents to a community/runtime generation, not the reusable port

Start an Auto Mesh agent in community A, switch the foreground community to B, and start B's node (including via saved sharing/agent restore). mesh_compute_select stops A's node but leaves its agent process running; B reuses port 19337. The A process retains this URL, the constant mesh-local key and model mesh, so its next A conversation request can be routed to B's peers. Prepared::with_current fences only launch, and Running retains no Mesh grant to revoke. This violates the community isolation promised in VISION_MESH.md, even though both peer allowlists individually validate correctly.

At SDK pin fc57e326, local OpenAI ingress uses the current node's targets with no remote caller identity (network/openai/ingress.rs:2449-2487,2519-2554); the peer allowlist does not bind a local request to A. Keep an enforceable community/generation-bound consumer lifetime: either refuse switching while consumers remain, confirm all affected agents stop before reusing the endpoint, or reject retired credentials at a host-owned ingress. Add an A-agent → B-node → next A prompt regression asserting B receives nothing. Source-traced, not a live disclosure reproduction.

("OPENAI_COMPAT_API", "chat".to_owned()),
] {
runtime.environment.insert(name.into(), value);
}
// Match classic Buzz without overriding an explicit opt-out.
runtime
.environment
.entry("BUZZ_AGENT_REQUIRE_REPLY".into())
.or_insert_with(|| "1".into());
// Mesh agents default to no reasoning; explicit user effort wins.
runtime
.environment
.entry("BUZZ_AGENT_THINKING_EFFORT".into())
.or_insert_with(|| "none".into());
Ok(runtime)
}
}
95 changes: 87 additions & 8 deletions crates/agent-controller/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ struct Running {
/// Native-only: holds environment values and is never serialized.
spawned: serde_json::Value,
databricks_host: Option<String>,
mesh_consumer: bool,
#[cfg(all(test, unix))]
temporary: Option<PathBuf>,
}
Expand All @@ -541,6 +542,8 @@ impl Drop for Running {
}
/// Deliberately not serializable: only the native connection owner consumes it.
pub struct ModelContext {
pub mesh: bool,
pub relay: Option<String>,
pub host: Option<String>,
pub filter: Option<String>,
pub model_overridden: bool,
Expand Down Expand Up @@ -663,7 +666,9 @@ impl Controller {
}
pub fn model_context(&self, id: &str, revision: u64, edit: AgentEdit) -> Result<ModelContext> {
let agent = self.edited_agent(id, revision, edit)?;
model_context(&agent.harness, &agent.environment)
let mut context = model_context(&agent.harness, &agent.environment)?;
context.relay = Some(agent.relay_url);
Ok(context)
}
pub fn goose_model_context(
&self,
Expand Down Expand Up @@ -1048,6 +1053,17 @@ impl Controller {
}
self.snapshot()
}
pub(crate) fn mesh_agent(&self, id: &str) -> Result<Agent> {
let agent = self
.store
.agents()?
.into_iter()
.find(|a| a.id == id)
.ok_or("Agent no longer exists")?;
let mut agent = crate::agent_defaults::effective(&agent, &self.store.defaults()?);
agent.harness = crate::build_defaults().resolve(&agent.harness, &agent.environment);
Ok(agent)
}
pub fn credential_request(&self, id: &str) -> Result<(String, String, u64, Option<String>)> {
let agent = self
.store
Expand All @@ -1072,7 +1088,7 @@ impl Controller {
key: &crate::Secret,
replay_floor: Option<u64>,
) -> Result<()> {
self.action_checked(id, action, revision, key, replay_floor, None)
self.action_checked(id, action, revision, key, replay_floor, (None, None))
}
pub fn action_with_preflight(
&mut self,
Expand All @@ -1083,7 +1099,33 @@ impl Controller {
replay_floor: Option<u64>,
preflight: &crate::pi::LaunchPreflight,
) -> Result<()> {
self.action_checked(id, action, revision, key, replay_floor, Some(preflight))
self.action_checked(
id,
action,
revision,
key,
replay_floor,
(Some(preflight), None),
)
}
/// Start with an identity-bound Mesh grant and the host's verified preflight.
pub fn action_with_mesh(
&mut self,
id: &str,
action: Action,
revision: u64,
key: &crate::Secret,
replay_floor: Option<u64>,
launch: (&crate::pi::LaunchPreflight, crate::MeshLaunch),
) -> Result<()> {
self.action_checked(
id,
action,
revision,
key,
replay_floor,
(Some(launch.0), Some(launch.1)),
)
}
fn action_checked(
&mut self,
Expand All @@ -1092,8 +1134,12 @@ impl Controller {
revision: u64,
key: &crate::Secret,
replay_floor: Option<u64>,
preflight: Option<&crate::pi::LaunchPreflight>,
launch: (
Option<&crate::pi::LaunchPreflight>,
Option<crate::MeshLaunch>,
),
) -> Result<()> {
let (preflight, mesh) = launch;
if self.credential_request(id)?.2 != revision {
return Err("Saved settings changed while opening credentials; retry Start".into());
}
Expand All @@ -1107,7 +1153,7 @@ impl Controller {
return Ok(());
}
}
match self.start_with_key(id, Some(key), replay_floor, preflight) {
match self.start_with_key(id, Some(key), replay_floor, preflight, mesh) {
Ok(()) => {
self.errors.remove(id);
}
Expand All @@ -1130,14 +1176,15 @@ impl Controller {
.collect())
}
fn start(&mut self, id: &str) -> Result<()> {
self.start_with_key(id, None, None, None)
self.start_with_key(id, None, None, None, None)
}
fn start_with_key(
&mut self,
id: &str,
supplied: Option<&crate::Secret>,
replay_floor: Option<u64>,
preflight: Option<&crate::pi::LaunchPreflight>,
mesh: Option<crate::MeshLaunch>,
) -> Result<()> {
if let Some(run) = self.running.get_mut(id) {
if run.process.alive()? {
Expand Down Expand Up @@ -1182,10 +1229,12 @@ impl Controller {
.map_err(|_| "Could not create private runtime directory")?;
let scratch = temporary.path().join("tmp");
crate::connection::private_directory(&scratch)?;
let runtime_agent = mesh.as_ref().map(|grant| grant.apply(&agent)).transpose()?;
let launch_agent = runtime_agent.as_ref().unwrap_or(&agent);
let mut command = if let Some(preflight) = preflight {
bundle.command_checked(&agent, key, &crate::build_defaults(), Some(preflight))?
bundle.command_checked(launch_agent, key, &crate::build_defaults(), Some(preflight))?
} else {
bundle.command(&agent, key)?
bundle.command(launch_agent, key)?
};
// Per-send startup input, never saved configuration or inherited environment.
if let Some(floor) = replay_floor {
Expand Down Expand Up @@ -1225,6 +1274,7 @@ impl Controller {
revision: agent.revision,
spawned: crate::restart::spawn_config(&agent),
databricks_host: settings.map(|s| s.host),
mesh_consumer: mesh.is_some(),
#[cfg(all(test, unix))]
temporary: Some(temporary),
},
Expand Down Expand Up @@ -1265,6 +1315,24 @@ impl Controller {
let cache = crate::connection::oauth_root(self.store.root())?;
crate::connection::disconnect(&cache, &workspace)
}
/// Whether any running agent was launched as a Mesh consumer.
pub fn has_mesh_consumers(&self) -> bool {
self.running.values().any(|run| run.mesh_consumer)
}
/// Stop exact running Mesh consumers using captured launch evidence, not edited settings.
/// A failed process teardown retains ownership and prevents endpoint replacement.
pub fn stop_mesh_consumers(&mut self) -> Result<()> {
let ids: Vec<_> = self
.running
.iter()
.filter(|(_, run)| run.mesh_consumer)
.map(|(id, _)| id.clone())
.collect();
for id in ids {
self.stop(&id)?;
}
Ok(())
}
pub fn shutdown(&mut self) -> Result<()> {
let ids: Vec<_> = self.running.keys().cloned().collect();
let mut result = Ok(());
Expand Down Expand Up @@ -1313,6 +1381,15 @@ fn model_context_with_defaults(
let provider = environment
.get("BUZZ_AGENT_PROVIDER")
.unwrap_or(&harness.provider);
if provider == "relay-mesh" {
return Ok(ModelContext {
mesh: true,
relay: None,
host: None,
filter: None,
model_overridden: environment.contains_key("BUZZ_AGENT_MODEL"),
});
}
if !matches!(provider.as_str(), "databricks_v2" | "databricks-v2") {
return Err(
"Effective provider is not Databricks v2; check the provider and environment overrides"
Expand All @@ -1323,6 +1400,8 @@ fn model_context_with_defaults(
return Err("A saved or draft token override conflicts with this app-isolated OAuth connection. Remove it explicitly or keep manual model entry".into());
}
Ok(ModelContext {
mesh: false,
relay: None,
host: environment
.get("DATABRICKS_HOST")
.cloned()
Expand Down
Loading
Loading