feat: pre-populate retry dialog with crashed agent's original instruction

When a refine agent crashes, the Retry dialog now extracts the
user_instruction from the agent's stored prompt and pre-fills the
textarea, so users can re-run with the same instruction without
retyping it.
This commit is contained in:
Lukas May
2026-03-06 21:13:03 +01:00
parent e77be50b04
commit f5b1a3a5b9
2 changed files with 27 additions and 5 deletions

View File

@@ -22,6 +22,8 @@ interface RefineSpawnDialogProps {
showInstructionInput?: boolean; showInstructionInput?: boolean;
/** Placeholder text for the instruction textarea */ /** Placeholder text for the instruction textarea */
instructionPlaceholder?: string; instructionPlaceholder?: string;
/** Pre-populate the instruction field (e.g. from a crashed agent's original instruction) */
defaultInstruction?: string;
/** Whether the spawn mutation is pending */ /** Whether the spawn mutation is pending */
isSpawning: boolean; isSpawning: boolean;
/** Error message if spawn failed */ /** Error message if spawn failed */
@@ -38,6 +40,7 @@ export function RefineSpawnDialog({
description, description,
showInstructionInput = true, showInstructionInput = true,
instructionPlaceholder = "What should the agent focus on? (optional)", instructionPlaceholder = "What should the agent focus on? (optional)",
defaultInstruction,
isSpawning, isSpawning,
error, error,
onSpawn, onSpawn,
@@ -53,18 +56,25 @@ export function RefineSpawnDialog({
onSpawn(finalInstruction); onSpawn(finalInstruction);
}; };
const openDialog = () => {
setInstruction(defaultInstruction ?? "");
setShowDialog(true);
};
const handleOpenChange = (open: boolean) => { const handleOpenChange = (open: boolean) => {
setShowDialog(open); if (open) {
if (!open) { setInstruction(defaultInstruction ?? "");
} else {
setInstruction(""); setInstruction("");
} }
setShowDialog(open);
}; };
const defaultTrigger = ( const defaultTrigger = (
<Button <Button
variant="outline" variant="outline"
size="sm" size="sm"
onClick={() => setShowDialog(true)} onClick={openDialog}
className="gap-1.5" className="gap-1.5"
> >
<Sparkles className="h-3.5 w-3.5" /> <Sparkles className="h-3.5 w-3.5" />
@@ -75,7 +85,7 @@ export function RefineSpawnDialog({
return ( return (
<> <>
{trigger ? ( {trigger ? (
<div onClick={() => setShowDialog(true)}> <div onClick={openDialog}>
{trigger} {trigger}
</div> </div>
) : ( ) : (

View File

@@ -1,4 +1,4 @@
import { useCallback, useEffect } from "react"; import { useCallback, useEffect, useMemo } from "react";
import { Loader2, AlertCircle } from "lucide-react"; import { Loader2, AlertCircle } from "lucide-react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { QuestionForm } from "@/components/QuestionForm"; import { QuestionForm } from "@/components/QuestionForm";
@@ -6,6 +6,12 @@ import { ChangeSetBanner } from "@/components/ChangeSetBanner";
import { RefineSpawnDialog } from "../RefineSpawnDialog"; import { RefineSpawnDialog } from "../RefineSpawnDialog";
import { useRefineAgent } from "@/hooks"; import { useRefineAgent } from "@/hooks";
function extractInstruction(prompt: string | null | undefined): string | undefined {
if (!prompt) return undefined;
const match = prompt.match(/<user_instruction>\n([\s\S]*?)\n<\/user_instruction>/);
return match?.[1] || undefined;
}
interface RefineAgentPanelProps { interface RefineAgentPanelProps {
initiativeId: string; initiativeId: string;
} }
@@ -123,6 +129,11 @@ export function RefineAgentPanel({ initiativeId }: RefineAgentPanelProps) {
} }
// Crashed // Crashed
const crashedInstruction = useMemo(
() => (state === "crashed" ? extractInstruction(agent?.prompt) : undefined),
[state, agent?.prompt],
);
if (state === "crashed") { if (state === "crashed") {
return ( return (
<div className="mb-3 rounded-lg border border-destructive/50 bg-destructive/5 px-3 py-2"> <div className="mb-3 rounded-lg border border-destructive/50 bg-destructive/5 px-3 py-2">
@@ -134,6 +145,7 @@ export function RefineAgentPanel({ initiativeId }: RefineAgentPanelProps) {
title="Refine Initiative Content" title="Refine Initiative Content"
description="An agent will review all pages and suggest improvements." description="An agent will review all pages and suggest improvements."
instructionPlaceholder="What should the agent focus on? (optional)" instructionPlaceholder="What should the agent focus on? (optional)"
defaultInstruction={crashedInstruction}
isSpawning={spawn.isPending} isSpawning={spawn.isPending}
error={spawn.error?.message} error={spawn.error?.message}
onSpawn={handleSpawn} onSpawn={handleSpawn}