an archetype's prompt prefills the new agent's agents.md in the create form
This commit is contained in:
parent
2acde41e54
commit
a5470d82ae
4 changed files with 179 additions and 12 deletions
|
|
@ -21,3 +21,17 @@ export function agentsMdRefusal(problem: ProblemDetails): string | null {
|
|||
? problem.detail
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The AGENTS.md box after the archetype pick changes from one whose prompt was
|
||||
* `previous` to one whose prompt is `next` (both `""` for none). The pick
|
||||
* replaces what is in the box only when the box is empty or still holds the
|
||||
* previous pick's prompt; text the operator typed or edited stays.
|
||||
*/
|
||||
export function agentsMdAfterPick(
|
||||
current: string,
|
||||
previous: string,
|
||||
next: string,
|
||||
): string {
|
||||
return current.trim() === "" || current === previous ? next : current;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ export interface Archetype {
|
|||
subagent_models?: string[];
|
||||
max_subagents?: number;
|
||||
};
|
||||
prompt?: string;
|
||||
}
|
||||
|
||||
// Mirrors swarm-controller's `Archetypes`.
|
||||
|
|
|
|||
|
|
@ -63,7 +63,11 @@ import {
|
|||
requestArchetype,
|
||||
type ArchetypeList,
|
||||
} from "./CreateAgentArchetype.js";
|
||||
import { agentsMdBody, agentsMdRefusal } from "./CreateAgentAgentsMd.js";
|
||||
import {
|
||||
agentsMdAfterPick,
|
||||
agentsMdBody,
|
||||
agentsMdRefusal,
|
||||
} from "./CreateAgentAgentsMd.js";
|
||||
import {
|
||||
NAME_PATTERN,
|
||||
nextStep,
|
||||
|
|
@ -191,13 +195,14 @@ export function CreateAgentForm({
|
|||
})().catch((e: unknown) => setArchetypesError({ detail: String(e) }));
|
||||
}, []);
|
||||
|
||||
// Fills permissions, caps and inference from the picked archetype; each
|
||||
// stays editable, and the request carries only those fields.
|
||||
// Fills permissions, caps, inference and the AGENTS.md text from the picked
|
||||
// archetype; each stays editable, and the request carries only those fields.
|
||||
function pickArchetype(key: string) {
|
||||
setArchetype(key);
|
||||
const p = prefill(
|
||||
archetypes?.archetypes.find((a) => archetypeKey(a) === key),
|
||||
catalogue?.default ?? [],
|
||||
const next = archetypes?.archetypes.find((a) => archetypeKey(a) === key);
|
||||
const p = prefill(next, catalogue?.default ?? []);
|
||||
setAgentsMd((current) =>
|
||||
agentsMdAfterPick(current, picked?.prompt ?? "", next?.prompt ?? ""),
|
||||
);
|
||||
setSelected(p.permissions);
|
||||
setCpu(p.cpu);
|
||||
|
|
@ -401,7 +406,8 @@ export function CreateAgentForm({
|
|||
<div class="create-agent-fields">
|
||||
<p class="create-agent-intro">
|
||||
The text the agent's AGENTS.md starts with. Optional: leave it
|
||||
empty and the agent starts without the file.
|
||||
empty and the agent starts without the file. An archetype with a
|
||||
prompt fills the box in; edit it freely.
|
||||
</p>
|
||||
<TextAreaField
|
||||
id="agent-agents-md"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
import assert from "node:assert/strict";
|
||||
import { test } from "node:test";
|
||||
import {
|
||||
agentsMdAfterPick,
|
||||
agentsMdBody,
|
||||
agentsMdRefusal,
|
||||
} from "../src/pages/CreateAgentAgentsMd.ts";
|
||||
|
|
@ -41,3 +42,29 @@ test("other failures stay with the general error", () => {
|
|||
assert.equal(agentsMdRefusal({ status: 400 }), null);
|
||||
assert.equal(agentsMdRefusal({ detail: "agents_md is too long" }), null);
|
||||
});
|
||||
|
||||
test("a pick fills an empty box with the archetype's prompt", () => {
|
||||
assert.equal(agentsMdAfterPick("", "", "Review only."), "Review only.");
|
||||
assert.equal(agentsMdAfterPick(" \n", "", "Review only."), "Review only.");
|
||||
});
|
||||
|
||||
test("a pick keeps text the operator typed or edited", () => {
|
||||
assert.equal(agentsMdAfterPick("# mine", "", "Review only."), "# mine");
|
||||
assert.equal(
|
||||
agentsMdAfterPick("Review only. Also x.", "Review only.", "Triage."),
|
||||
"Review only. Also x.",
|
||||
);
|
||||
});
|
||||
|
||||
test("a pick over an unedited prefill swaps it, and none clears it", () => {
|
||||
assert.equal(
|
||||
agentsMdAfterPick("Review only.", "Review only.", "Triage."),
|
||||
"Triage.",
|
||||
);
|
||||
assert.equal(agentsMdAfterPick("Review only.", "Review only.", ""), "");
|
||||
});
|
||||
|
||||
test("an archetype without a prompt leaves the box as it is", () => {
|
||||
assert.equal(agentsMdAfterPick("# mine", "", ""), "# mine");
|
||||
assert.equal(agentsMdAfterPick("", "", ""), "");
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue