Watch
0
0
Fork
You've already forked hyperhive
0

keep the operator list under one key and read it with one direct get

The agent read the operator-profiles bucket with a keys() listing, an
ordered consumer whose grant (STREAM.INFO, CONSUMER.CREATE) and flow-control
reply had never run against a permissioned queue. The controller now writes
the whole list as one JSON array under one key, only when it changed, and
the agent reads it with one DIRECT.GET the way agent_inference::read_own
reads its key. The agent grant shrinks to that one subject.
This commit is contained in:
atlas 2026-10-17 12:19:43 +02:00 • committed by mara
commit 49015eb553
12 changed files with 254 additions and 201 deletions

View file

@ -38,9 +38,9 @@ rusqlite.workspace = true
schemars.workspace = true
serde.workspace = true
serde_json.workspace = true
# `agent-schedules` and `agent-inference`: the schedule ticker and the
# inference poller each read their own key with one direct get.
# `operator-profiles`: the prompt renderer lists the operator-profile bucket.
# `agent-schedules`, `agent-inference` and `operator-profiles`: the schedule
# ticker and the inference poller each read their own key, and the prompt
# renderer the operator list, with one direct get.
# `kv`/`notices` name buckets and streams this harness opens neither end of,
# and the terminal publisher is a plain core-subject publish.
swarm-queue-client = { workspace = true, features = [

View file

@ -81,12 +81,20 @@ fn operators_line(operators: &[OperatorProfile]) -> String {
/// read within [`OPERATORS_TIMEOUT`]: the prompt then reads as it does with no
/// operator list.
async fn operators() -> Vec<OperatorProfile> {
within_timeout(OPERATORS_TIMEOUT, async {
let client = crate::swarm_queue::client().await;
swarm_queue_client::ensure_connected(&client)?;
operator_profiles::read_all(&client).await
})
.await
within_timeout(OPERATORS_TIMEOUT, read_operators()).await
}
/// One read of the operator list over this agent's queue connection.
async fn read_operators()
-> std::result::Result<Vec<OperatorProfile>, Box<dyn std::error::Error + Send + Sync>> {
let client = crate::swarm_queue::client().await;
swarm_queue_client::ensure_connected(&client)?;
match operator_profiles::read(&client).await? {
operator_profiles::Read::Current(operators) => Ok(operators),
operator_profiles::Read::NoBucket => {
Err("the operator-profiles bucket does not answer".into())
}
}
}
/// `read`'s profiles, or none when it fails or outlasts `timeout`.