From 37c91eb9168d951e27bc6f9458f707a5d2a3ef88 Mon Sep 17 00:00:00 2001 From: iris Date: Thu, 15 Oct 2026 11:44:16 +0200 Subject: [PATCH] Roll back stored settings when a creation fails, and keep form ids unique create_agent puts back the caps and inference settings it replaced if a later store or the job insert fails, so a refused creation leaves nothing behind for the name. The shared field components take an id prefix so the create dialog and an open editor never share a DOM id. The queue check now follows the hive roster check, the 422 is documented, and the copy says empty rather than closed and that destroy keeps stored settings. --- docs/swarm/ui.md | 20 ++- .../src/agent/detail/AgentInference.tsx | 12 +- .../swarm-ui/src/agent/detail/AgentLimits.tsx | 8 +- .../swarm-ui/src/pages/CreateAgentForm.tsx | 11 +- swarm-controller/src/agent_limits.rs | 59 +++++- swarm-controller/src/inference.rs | 55 +++++- swarm-controller/src/main.rs | 170 +++++++++++++++--- 7 files changed, 288 insertions(+), 47 deletions(-) diff --git a/docs/swarm/ui.md b/docs/swarm/ui.md index 217fd426..606819a9 100644 --- a/docs/swarm/ui.md +++ b/docs/swarm/ui.md @@ -299,14 +299,18 @@ sets the hive's own limits. ### Settings at creation The **+ agent** dialog has two collapsed sections, **resource caps** and -**inference**, with the same fields as the detail panel's editors. Leave them -closed or empty and the request is the plain name and hive. Fill them and -`POST /api/agents` carries them as optional `limits` and `inference` objects, -the same shapes the two `PUT` routes take. The controller checks them with the -`PUT` rules before it queues anything, so a bad value gets a refusal with its -reason and creates no agent. It stores them ahead of the job graph, so they -are in place before the agent first runs. Creating a name that already exists with no settings -leaves any stored ones alone. +**inference**, with the same fields as the detail panel's editors. Leave the +fields empty and the request is the plain name and hive; collapsing a section doesn't +withdraw what you typed in it. Fill them and `POST /api/agents` carries them +as optional `limits` and `inference` objects, the same shapes the two `PUT` +routes take. The controller checks them with the `PUT` rules before it queues +anything, so a bad value gets a refusal with its reason and creates no agent. + +It stores them ahead of the job graph, before it declares the agent, so they +are in place before the agent first runs. If the creation then fails, the +controller puts back what it replaced. Each agent name keys its settings and +destroying an agent doesn't clear them, so a name set up before keeps its +stored settings when you leave the fields empty. ### Linking external accounts diff --git a/frontend/packages/swarm-ui/src/agent/detail/AgentInference.tsx b/frontend/packages/swarm-ui/src/agent/detail/AgentInference.tsx index 08e5a7f7..4bea9102 100644 --- a/frontend/packages/swarm-ui/src/agent/detail/AgentInference.tsx +++ b/frontend/packages/swarm-ui/src/agent/detail/AgentInference.tsx @@ -141,36 +141,40 @@ export function draftBody(d: InferenceDraft): Settings { export function InferenceFields({ draft, onChange, + idPrefix = "inference", }: { draft: InferenceDraft; onChange: (d: InferenceDraft) => void; + // Ids must be unique on the page, and the agents page can hold the editor + // and the create dialog at once. + idPrefix?: string; }) { const problem = draftProblem(draft); return ( <> onChange({ ...draft, model })} /> onChange({ ...draft, effort })} /> onChange({ ...draft, subagents })} /> void; onMemory: (v: string) => void; + // Ids must be unique on the page, and the agents page can hold the editor + // and the create dialog at once. + idPrefix?: string; }) { return ( <> Create a new agent's swarm-level identity. This only queues the job — check jobs to watch it settle. Resource - caps and inference are optional; leave them closed to keep the - defaults. + caps and inference are optional; leave them empty to set nothing. A + name set up before keeps the settings stored for it.

{hivesError && ( resource caps
inference
- +