Watch
0
0
Fork
You've already forked hyperhive
0

archetype flows behave like the built-ins: switch off per archetype or per agent, board cards, duplicate

The document's disabled list takes archetype:<archetype>/<flow> (off for every member) and the same with @<agent> (off for one member); a key naming nothing is ignored. GET /api/notify/flows lists the archetype flows with their members, the board draws a card for each with a switch, a checkbox per agent and duplicate, and the dry run counts their hits. The flows keep following the archetype.
This commit is contained in:
atlas 2026-11-11 19:08:19 +01:00 • committed by mara
commit 68c24643f6

View file

@ -9,11 +9,12 @@
//! result here, so the create screen lists archetypes from a value that a
//! create would accept.
use std::collections::BTreeMap;
use std::collections::{BTreeMap, BTreeSet};
use swarm_wire::agent_archetype::ArchetypeRef;
use swarm_wire::agent_inference::AgentInference;
use swarm_wire::agent_limits::AgentCaps;
use swarm_wire::notify_flows::Flow;
use swarm_wire::notify_flows::{Flow, archetype_flow_key};
/// The KV bucket archetype sources are published into, keyed by source name.
pub const BUCKET: &str = "agent-archetypes";
@ -70,6 +71,67 @@ pub struct ArchetypeMeta {
pub flows: Vec<Flow>,
}
/// One flow an archetype carries, with the agents of that archetype.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ArchetypeFlow {
pub archetype: String,
/// As the archetype declares it, under its own `id`.
pub flow: Flow,
/// The agents whose archetype this is, by name.
pub members: Vec<String>,
}
impl ArchetypeFlow {
/// The name the flow goes by, see [`archetype_flow_key`].
#[must_use]
pub fn key(&self) -> String {
archetype_flow_key(&self.archetype, &self.flow.id)
}
}
/// The flows to run: each enabled flow of each archetype that has an agent
/// in `refs` (agent to archetype), with those agents, and why any flow was
/// left out. A flow that fails [`Flow::validate_archetype`] or repeats an id
/// of its archetype is left out.
#[must_use]
pub fn flows_of(
refs: &BTreeMap<String, ArchetypeRef>,
records: &BTreeMap<String, SourceRecord>,
) -> (Vec<ArchetypeFlow>, Vec<String>) {
let mut agents: BTreeMap<(&str, &str), Vec<String>> = BTreeMap::new();
for (agent, r) in refs {
agents
.entry((r.source.as_str(), r.name.as_str()))
.or_default()
.push(agent.clone());
}
let mut active = Vec::new();
let mut skipped = Vec::new();
for ((source, name), members) in agents {
let Some(meta) = records
.get(source)
.and_then(|record| record.archetypes.get(name))
else {
continue;
};
let mut ids = BTreeSet::new();
for flow in meta.flows.iter().filter(|f| f.enabled) {
if !ids.insert(flow.id.as_str()) {
skipped.push(format!("{name}: flow {}: its id is used twice", flow.id));
} else if let Err(why) = flow.validate_archetype() {
skipped.push(format!("{name}: flow {}: {why}", flow.id));
} else {
active.push(ArchetypeFlow {
archetype: name.to_owned(),
flow: flow.clone(),
members: members.clone(),
});
}
}
}
(active, skipped)
}
/// Open the archetype bucket for writing, creating it if nothing has yet.
///
/// **Controller-side only.** `history: 1`: a reader wants the current value.