Watch
0
0
Fork
You've already forked hyperhive
0

order grant mirror writes by direction, re-mirror every five minutes, gate on the agent's own harness

This commit is contained in:
atlas 2026-11-01 18:27:55 +01:00
commit 329d556ab9

View file

@ -35,6 +35,7 @@ use tokio::time::{Interval, MissedTickBehavior};
use swarm_wire::agent_inference::Effective;
use swarm_wire::agent_login::Login;
use swarm_wire::hive_status::{Capabilities, TOLERANT_PERMISSIONS};
use swarm_wire::wanted::AgentState;
use crate::events::{Bus, BusEvent, LiveEvent, TurnState};
@ -100,6 +101,10 @@ struct AgentStateMsg {
/// `needs_login`, from this process's own [`LoginState`], so always set.
#[serde(flatten)]
login: Login,
/// What this harness can do, so swarm-controller grants an agent a
/// permission only when the harness running it can decode it.
#[serde(flatten)]
capabilities: Capabilities,
}
/// What this process can honestly report about the agent-state axis.
@ -140,6 +145,13 @@ fn login(state: LoginState) -> Login {
/// Build the current header from the bus, the login state and the pause
/// marker.
/// The capabilities this build reports.
fn capabilities() -> Capabilities {
Capabilities {
capabilities: vec![TOLERANT_PERMISSIONS.to_owned()],
}
}
fn snapshot(bus: &Bus, login_state: &Mutex<LoginState>) -> AgentStateMsg {
let (turn_state, since_unix) = bus.state_snapshot();
let model = bus.model();
@ -158,6 +170,7 @@ fn snapshot(bus: &Bus, login_state: &Mutex<LoginState>) -> AgentStateMsg {
ctx_usage: bus.last_ctx_usage(),
cost_usage: bus.last_cost_usage(),
login: login(*login_state.lock().unwrap_or_else(PoisonError::into_inner)),
capabilities: capabilities(),
}
}
@ -332,12 +345,14 @@ async fn publish(
#[cfg(test)]
mod tests {
use super::{
AgentStateMsg, REFRESH_INTERVAL, Trigger, due, login, next_trigger, refresh_timer, snapshot,
AgentStateMsg, REFRESH_INTERVAL, Trigger, capabilities, due, login, next_trigger,
refresh_timer, snapshot,
};
use crate::events::{BusEvent, LiveEvent, TurnState};
use crate::login::LoginState;
use std::sync::Mutex;
use swarm_wire::agent_inference::{Effective, Source};
use swarm_wire::hive_status::{Capabilities, TOLERANT_PERMISSIONS};
use swarm_wire::wanted::AgentState;
use tokio::sync::broadcast;
use tokio::time::{Duration, Instant};
@ -387,6 +402,7 @@ mod tests {
"cache_creation_input_tokens": 88,
}))),
login: login(LoginState::NeedsLogin),
capabilities: capabilities(),
}
}
@ -406,6 +422,7 @@ mod tests {
keys,
[
"agent_state",
"capabilities",
"context_window_tokens",
"cost_usage",
"ctx_usage",
@ -505,6 +522,14 @@ mod tests {
}
}
/// swarm-controller reads the harness's capabilities back out of a header.
#[test]
fn the_header_advertises_tolerant_permissions() {
let bytes = serde_json::to_vec(&msg()).expect("serialises");
let decoded: Capabilities = serde_json::from_slice(&bytes).expect("decodes");
assert!(decoded.has(TOLERANT_PERMISSIONS));
}
/// A login landing, or a logout, changes the header the next bus event
/// rebuilds, so it goes out without waiting for a refresh.
#[test]