Watch
0
0
Fork
You've already forked hyperhive
0

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.
This commit is contained in:
iris 2026-10-15 11:44:16 +02:00 • committed by mara
commit 37c91eb916
7 changed files with 288 additions and 47 deletions

View file

@ -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 (
<>
<TextField
id="inference-model"
id={`${idPrefix}-model`}
label="model"
value={draft.model}
placeholder="e.g. opus"
onInput={(model) => onChange({ ...draft, model })}
/>
<SelectField
id="inference-effort"
id={`${idPrefix}-effort`}
label="effort"
value={draft.effort}
options={EFFORT_OPTIONS}
onChange={(effort) => onChange({ ...draft, effort })}
/>
<TextField
id="inference-subagent-models"
id={`${idPrefix}-subagent-models`}
label="subagent models"
value={draft.subagents}
placeholder="e.g. haiku, sonnet"
onInput={(subagents) => onChange({ ...draft, subagents })}
/>
<TextField
id="inference-max-subagents"
id={`${idPrefix}-max-subagents`}
label="max subagents"
value={draft.maxSubagents}
placeholder="empty for no cap"

View file

@ -50,16 +50,20 @@ export function LimitsFields({
memory,
onCpu,
onMemory,
idPrefix = "limits",
}: {
cpu: string;
memory: string;
onCpu: (v: string) => 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 (
<>
<TextField
id="limits-cpu-quota"
id={`${idPrefix}-cpu-quota`}
label="cpu quota"
value={cpu}
placeholder="e.g. 400%"
@ -69,7 +73,7 @@ export function LimitsFields({
A percentage of one core: 100% is one core, 400% is four.
</p>
<TextField
id="limits-memory-max"
id={`${idPrefix}-memory-max`}
label="memory max"
value={memory}
placeholder="e.g. 8G"

View file

@ -167,8 +167,8 @@ export function CreateAgentForm({
<p class="create-agent-intro">
Create a new agent's swarm-level identity. This only queues the job
— check <Link href="/jobs">jobs</Link> 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.
</p>
{hivesError && (
<ApiErrorPanel
@ -206,6 +206,7 @@ export function CreateAgentForm({
<summary>resource caps</summary>
<div class="create-agent-section-body">
<LimitsFields
idPrefix="create-limits"
cpu={cpu}
memory={memory}
onCpu={setCpu}
@ -216,7 +217,11 @@ export function CreateAgentForm({
<details class="create-agent-section">
<summary>inference</summary>
<div class="create-agent-section-body">
<InferenceFields draft={inference} onChange={setInference} />
<InferenceFields
idPrefix="create-inference"
draft={inference}
onChange={setInference}
/>
</div>
</details>
<Button