fix: UI improvements to the approved plan component (#611)

* fix: UI improvements to the approved plan component

* cr
This commit is contained in:
Brace Sproul 2025-07-30 12:12:38 -07:00 • committed by GitHub
parent 997b7fc278
commit 6440542b23
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 21 additions and 7 deletions

View file

@ -12,6 +12,9 @@ import { cn } from "@/lib/utils";
import { Button } from "../ui/button";
import { Badge } from "../ui/badge";
import { HumanResponse } from "@langchain/langgraph/prebuilt";
import { TaskPlan } from "@open-swe/shared/open-swe/types";
import { getActivePlanItems } from "@open-swe/shared/open-swe/tasks";
import { InlineMarkdownText } from "../thread/markdown-text";
type PlanItem = {
index: number;
@ -20,6 +23,7 @@ type PlanItem = {
};
type AcceptedPlanStepProps = {
taskPlan?: TaskPlan;
planTitle?: string;
planItems?: PlanItem[];
interruptType?: HumanResponse["type"];
@ -27,12 +31,14 @@ type AcceptedPlanStepProps = {
};
export function AcceptedPlanStep({
taskPlan,
planTitle,
planItems = [],
interruptType,
collapse: collapseProp = true,
}: AcceptedPlanStepProps) {
const [collapsed, setCollapsed] = useState(collapseProp);
const activeTaskPlan = taskPlan ? getActivePlanItems(taskPlan) : planItems;
const getStatusText = () => {
if (interruptType === "edit") {
@ -68,7 +74,7 @@ export function AcceptedPlanStep({
);
};
const totalCount = planItems.length;
const totalCount = activeTaskPlan.length;
return (
<div
@ -97,7 +103,7 @@ export function AcceptedPlanStep({
</div>
{totalCount > 0 && (
<p className="text-muted-foreground mt-1 text-xs">
{totalCount} steps
{totalCount} step{totalCount === 1 ? "" : "s"}
</p>
)}
</div>
@ -139,7 +145,7 @@ export function AcceptedPlanStep({
</div>
)}
{planItems.length > 0 && (
{activeTaskPlan.length > 0 && (
<div className="space-y-3">
<h4 className="text-foreground flex items-center gap-2 text-sm font-medium">
Execution Steps
@ -152,7 +158,7 @@ export function AcceptedPlanStep({
</h4>
<div className="space-y-3">
{planItems
{activeTaskPlan
.sort((a, b) => a.index - b.index)
.map((item, idx) => (
<div
@ -170,7 +176,7 @@ export function AcceptedPlanStep({
<div className="min-w-0 flex-1">
<div className="flex items-start justify-between gap-2">
<p
<InlineMarkdownText
className={cn(
"text-sm leading-relaxed",
item.completed
@ -179,7 +185,7 @@ export function AcceptedPlanStep({
)}
>
{item.plan}
</p>
</InlineMarkdownText>
<Badge
variant="outline"
className={cn(

View file

@ -13,7 +13,11 @@ import { Message } from "@langchain/langgraph-sdk";
import { InitializeStep } from "../gen-ui/initialize-step";
import { AcceptedPlanStep } from "../gen-ui/accepted-plan-step";
import { PlannerGraphState } from "@open-swe/shared/open-swe/planner/types";
import { GraphState, PlanItem } from "@open-swe/shared/open-swe/types";
import {
GraphState,
PlanItem,
TaskPlan,
} from "@open-swe/shared/open-swe/types";
import { HumanResponse } from "@langchain/langgraph/prebuilt";
import { LoadingActionsCardContent } from "./thread-view-loading";
import { Interrupt } from "../thread/messages/interrupt";
@ -65,6 +69,7 @@ interface ActionsRendererProps<
customNodeEvents: CustomNodeEvent[];
setCustomNodeEvents: Dispatch<SetStateAction<CustomNodeEvent[]>>;
stream: ReturnType<typeof useStream<StateType>>;
taskPlan?: TaskPlan;
}
const getCustomNodeEventsFromMessages = (
@ -92,6 +97,7 @@ const getCustomNodeEventsFromMessages = (
export function ActionsRenderer<
StateType extends PlannerGraphState | GraphState,
>({
taskPlan,
runId,
customNodeEvents,
setCustomNodeEvents,
@ -224,6 +230,7 @@ export function ActionsRenderer<
{acceptedPlanEvents.length > 0 &&
isAcceptedPlanEvents(acceptedPlanEvents) && (
<AcceptedPlanStep
taskPlan={taskPlan}
planTitle={
acceptedPlanEvents[acceptedPlanEvents.length - 1].data.planTitle
}

View file

@ -403,6 +403,7 @@ export function ThreadView({
{plannerSession ? (
<div className="scrollbar-pretty-auto overflow-y-auto px-2">
<ActionsRenderer<PlannerGraphState>
taskPlan={programmerTaskPlan}
runId={plannerSession.runId}
customNodeEvents={customPlannerNodeEvents}
setCustomNodeEvents={