Watch
0
0
Fork
You've already forked hyperhive
0

swarm-ui: fix the stray doc text, name the agent in the cap-read warning

docs/swarm/inference.md had a table-row suffix pasted before the H1 by a
bad substitution, and the PUT row had lost it; the text is back in the
row.

A failed read of the agent-inference key already applied no cap (an
unreachable swarm must not block subagent work) and warned, but the
warning did not say which agent. It now names the agent and the error,
a test pins that, and subagent.md says a failed read starts anyway.

The max-subagents field stays a text field with a digit pattern: the
review-settings page's numeric field (concurrent reviews) is a TextField
with pattern="[0-9]+" and validation, and no field in swarm-ui uses
type="number". The new field gets the same pattern.
This commit is contained in:
atlas 2026-10-13 19:46:59 +02:00 • committed by mara
commit 461795b2cf
5 changed files with 48 additions and 14 deletions

View file

@ -560,7 +560,11 @@ impl State {
Some(reader) => Some(reader.read().await),
None => None,
};
let cap = subagent_cap(read.as_ref());
let agent = self
.models
.as_ref()
.map_or("", crate::swarm_models::Reader::agent);
let cap = subagent_cap(read.as_ref(), agent);
if model.is_some() {
check_model(model, &model_list(read, (self.local_models)()))?;
}
@ -1089,13 +1093,14 @@ fn model_list(read: Option<crate::swarm_models::Read>, local: Option<String>) ->
/// The swarm's `max_subagents` for this agent, or `None`, no cap: when it
/// sets none, when `read` is `None` because this daemon has no swarm queue,
/// or when the read failed, which is logged.
fn subagent_cap(read: Option<&crate::swarm_models::Read>) -> Option<u32> {
/// or when the read failed, which is logged as a warning naming the agent and the error.
fn subagent_cap(read: Option<&crate::swarm_models::Read>, agent: &str) -> Option<u32> {
use crate::swarm_models::Read;
match read? {
Read::Current(settings) => settings.max_subagents,
Read::Failed(error) => {
tracing::warn!(
agent,
%error,
"reading this agent's subagent settings from the swarm failed; applying no \
subagent cap"
@ -4697,11 +4702,29 @@ mod tests {
#[test]
fn the_cap_is_the_swarm_value_and_none_otherwise() {
assert_eq!(subagent_cap(Some(&capped(3))), Some(3));
assert_eq!(subagent_cap(Some(&unset())), None);
assert_eq!(subagent_cap(None), None);
assert_eq!(subagent_cap(Some(&capped(3)), "a"), Some(3));
assert_eq!(subagent_cap(Some(&unset()), "a"), None);
assert_eq!(subagent_cap(None, "a"), None);
let failed = crate::swarm_models::Read::Failed("no answer".to_owned());
assert_eq!(subagent_cap(Some(&failed)), None);
assert_eq!(subagent_cap(Some(&failed), "a"), None);
}
#[test]
fn a_failed_cap_read_warns_naming_the_agent_and_the_error() {
let logs = CapturedLogs::default();
let subscriber = tracing_subscriber::fmt()
.with_writer(logs.clone())
.with_ansi(false)
.finish();
let failed = crate::swarm_models::Read::Failed("no answer".to_owned());
let cap =
tracing::subscriber::with_default(subscriber, || subagent_cap(Some(&failed), "iris"));
assert_eq!(cap, None);
let logged = logs.text();
assert!(
logged.contains("WARN") && logged.contains("iris") && logged.contains("no answer"),
"{logged}"
);
}
/// `start` and `continue` read the cap live: the swarm's cap of 1 refuses

View file

@ -105,6 +105,16 @@ impl Reader {
(Self { source }, reads)
}
/// The agent whose key is read; `"test"` for a fixed reader.
#[must_use]
pub fn agent(&self) -> &str {
match &self.source {
Source::Queue { agent, .. } => agent,
#[cfg(test)]
Source::Fixed { .. } => "test",
}
}
/// This agent's settings as the swarm holds them now.
pub async fn read(&self) -> Read {
match &self.source {