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;
/** Placeholder text for the instruction textarea */
instructionPlaceholder?: string;
/** Pre-populate the instruction field (e.g. from a crashed agent's original instruction) */
defaultInstruction?: string;
/** Whether the spawn mutation is pending */
isSpawning: boolean;
/** Error message if spawn failed */
@@ -38,6 +40,7 @@ export function RefineSpawnDialog({
description,
showInstructionInput = true,
instructionPlaceholder = "What should the agent focus on? (optional)",
defaultInstruction,
isSpawning,
error,
onSpawn,
@@ -53,18 +56,25 @@ export function RefineSpawnDialog({
onSpawn(finalInstruction);
};
const openDialog = () => {
setInstruction(defaultInstruction ?? "");
setShowDialog(true);
};
const handleOpenChange = (open: boolean) => {
setShowDialog(open);
if (!open) {
if (open) {
setInstruction(defaultInstruction ?? "");
} else {
setInstruction("");
}
setShowDialog(open);
};
const defaultTrigger = (
<Button
variant="outline"
size="sm"
onClick={() => setShowDialog(true)}
onClick={openDialog}
className="gap-1.5"
>
<Sparkles className="h-3.5 w-3.5" />
@@ -75,7 +85,7 @@ export function RefineSpawnDialog({
return (
<>
{trigger ? (
<div onClick={() => setShowDialog(true)}>
<div onClick={openDialog}>
{trigger}
</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 { Button } from "@/components/ui/button";
import { QuestionForm } from "@/components/QuestionForm";
@@ -6,6 +6,12 @@ import { ChangeSetBanner } from "@/components/ChangeSetBanner";
import { RefineSpawnDialog } from "../RefineSpawnDialog";
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 {
initiativeId: string;
}
@@ -123,6 +129,11 @@ export function RefineAgentPanel({ initiativeId }: RefineAgentPanelProps) {
}
// Crashed
const crashedInstruction = useMemo(
() => (state === "crashed" ? extractInstruction(agent?.prompt) : undefined),
[state, agent?.prompt],
);
if (state === "crashed") {
return (
<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"
description="An agent will review all pages and suggest improvements."
instructionPlaceholder="What should the agent focus on? (optional)"
defaultInstruction={crashedInstruction}
isSpawning={spawn.isPending}
error={spawn.error?.message}
onSpawn={handleSpawn}