fix: make name/emoji/persona optional, auto-skip empty steps, back button
- Make name, emoji, persona params optional in dedicated-channel-agent - Auto-skip steps whose template args resolve to empty strings - Move "Back to Recipes" to a back arrow next to the title Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,9 +11,9 @@
|
||||
{ "id": "agent_id", "label": "Agent ID", "type": "string", "required": true, "placeholder": "e.g. my-bot" },
|
||||
{ "id": "guild_id", "label": "Guild", "type": "discord_guild", "required": true },
|
||||
{ "id": "channel_id", "label": "Channel", "type": "discord_channel", "required": true },
|
||||
{ "id": "name", "label": "Display Name", "type": "string", "required": true, "placeholder": "e.g. MyBot" },
|
||||
{ "id": "name", "label": "Display Name", "type": "string", "required": false, "placeholder": "e.g. MyBot" },
|
||||
{ "id": "emoji", "label": "Emoji", "type": "string", "required": false, "placeholder": "e.g. \ud83e\udd16" },
|
||||
{ "id": "persona", "label": "Persona", "type": "textarea", "required": true, "placeholder": "You are..." }
|
||||
{ "id": "persona", "label": "Persona", "type": "textarea", "required": false, "placeholder": "You are..." }
|
||||
],
|
||||
"steps": [
|
||||
{ "action": "create_agent", "label": "Create independent agent", "args": { "agentId": "{{agent_id}}", "independent": true } },
|
||||
|
||||
@@ -81,6 +81,7 @@ export interface ResolvedStep {
|
||||
label: string;
|
||||
args: Record<string, unknown>;
|
||||
description: string;
|
||||
skippable: boolean;
|
||||
}
|
||||
|
||||
export function resolveSteps(
|
||||
@@ -92,6 +93,14 @@ export function resolveSteps(
|
||||
if (step.action === "config_patch") {
|
||||
resolved.params = params;
|
||||
}
|
||||
// A step is skippable if any of its template args resolved to empty string
|
||||
const skippable = Object.entries(step.args).some(([key, origValue]) => {
|
||||
if (typeof origValue === "string" && origValue.includes("{{")) {
|
||||
const rv = resolved[key];
|
||||
return typeof rv === "string" && rv.trim() === "";
|
||||
}
|
||||
return false;
|
||||
});
|
||||
const actionDef = getAction(step.action);
|
||||
const description = actionDef?.describe(resolved) || step.label;
|
||||
return {
|
||||
@@ -100,6 +109,7 @@ export function resolveSteps(
|
||||
label: step.label,
|
||||
args: resolved,
|
||||
description: description || step.label,
|
||||
skippable,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -48,9 +48,10 @@ export function Cook({
|
||||
const handleNext = () => {
|
||||
const steps = resolveSteps(recipe.steps, params);
|
||||
setResolvedStepList(steps);
|
||||
setStepStatuses(steps.map(() => "pending"));
|
||||
// Auto-skip steps whose template args resolved to empty
|
||||
setStepStatuses(steps.map((s) => (s.skippable ? "skipped" : "pending")));
|
||||
setStepErrors({});
|
||||
setHasConfigPatch(steps.some((s) => s.action === "config_patch"));
|
||||
setHasConfigPatch(steps.some((s) => !s.skippable && s.action === "config_patch"));
|
||||
setPhase("confirm");
|
||||
};
|
||||
|
||||
@@ -75,8 +76,7 @@ export function Cook({
|
||||
|
||||
const handleExecute = () => {
|
||||
setPhase("execute");
|
||||
const statuses: StepStatus[] = resolvedStepList.map(() => "pending");
|
||||
setStepStatuses([...statuses]);
|
||||
const statuses = [...stepStatuses];
|
||||
runFrom(0, statuses);
|
||||
};
|
||||
|
||||
@@ -131,7 +131,12 @@ export function Cook({
|
||||
|
||||
return (
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">{recipe.name}</h2>
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<Button variant="ghost" size="sm" className="px-2" onClick={onDone}>
|
||||
←
|
||||
</Button>
|
||||
<h2 className="text-2xl font-bold">{recipe.name}</h2>
|
||||
</div>
|
||||
|
||||
{phase === "params" && (
|
||||
<ParamForm
|
||||
@@ -149,13 +154,18 @@ export function Cook({
|
||||
<CardContent>
|
||||
<div className="space-y-3">
|
||||
{resolvedStepList.map((step, i) => (
|
||||
<div key={i} className="flex items-start gap-3">
|
||||
<div key={i} className={cn("flex items-start gap-3", stepStatuses[i] === "skipped" && "opacity-50")}>
|
||||
<span className={cn("text-lg font-mono w-5 text-center", statusColor(stepStatuses[i]))}>
|
||||
{statusIcon(stepStatuses[i])}
|
||||
</span>
|
||||
<div className="flex-1">
|
||||
<div className="text-sm font-medium">{step.label}</div>
|
||||
{step.description !== step.label && (
|
||||
<div className="text-sm font-medium">
|
||||
{step.label}
|
||||
{stepStatuses[i] === "skipped" && phase === "confirm" && (
|
||||
<span className="text-xs text-muted-foreground ml-2">(skipped — empty params)</span>
|
||||
)}
|
||||
</div>
|
||||
{step.description !== step.label && stepStatuses[i] !== "skipped" && (
|
||||
<div className="text-xs text-muted-foreground">{step.description}</div>
|
||||
)}
|
||||
{stepErrors[i] && (
|
||||
@@ -198,9 +208,6 @@ export function Cook({
|
||||
Use "Apply Changes" in the sidebar to restart the gateway and activate config changes.
|
||||
</p>
|
||||
)}
|
||||
<Button className="mt-4" onClick={onDone}>
|
||||
Back to Recipes
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user