mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-10-03 17:53:20 +00:00
fix: UI improvements to the approved plan component (#611)
* fix: UI improvements to the approved plan component * cr
This commit is contained in:
parent
997b7fc278
commit
6440542b23
3 changed files with 21 additions and 7 deletions
|
|
@ -12,6 +12,9 @@ import { cn } from "@/lib/utils";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import { Badge } from "../ui/badge";
|
import { Badge } from "../ui/badge";
|
||||||
import { HumanResponse } from "@langchain/langgraph/prebuilt";
|
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 = {
|
type PlanItem = {
|
||||||
index: number;
|
index: number;
|
||||||
|
|
@ -20,6 +23,7 @@ type PlanItem = {
|
||||||
};
|
};
|
||||||
|
|
||||||
type AcceptedPlanStepProps = {
|
type AcceptedPlanStepProps = {
|
||||||
|
taskPlan?: TaskPlan;
|
||||||
planTitle?: string;
|
planTitle?: string;
|
||||||
planItems?: PlanItem[];
|
planItems?: PlanItem[];
|
||||||
interruptType?: HumanResponse["type"];
|
interruptType?: HumanResponse["type"];
|
||||||
|
|
@ -27,12 +31,14 @@ type AcceptedPlanStepProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export function AcceptedPlanStep({
|
export function AcceptedPlanStep({
|
||||||
|
taskPlan,
|
||||||
planTitle,
|
planTitle,
|
||||||
planItems = [],
|
planItems = [],
|
||||||
interruptType,
|
interruptType,
|
||||||
collapse: collapseProp = true,
|
collapse: collapseProp = true,
|
||||||
}: AcceptedPlanStepProps) {
|
}: AcceptedPlanStepProps) {
|
||||||
const [collapsed, setCollapsed] = useState(collapseProp);
|
const [collapsed, setCollapsed] = useState(collapseProp);
|
||||||
|
const activeTaskPlan = taskPlan ? getActivePlanItems(taskPlan) : planItems;
|
||||||
|
|
||||||
const getStatusText = () => {
|
const getStatusText = () => {
|
||||||
if (interruptType === "edit") {
|
if (interruptType === "edit") {
|
||||||
|
|
@ -68,7 +74,7 @@ export function AcceptedPlanStep({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const totalCount = planItems.length;
|
const totalCount = activeTaskPlan.length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
@ -97,7 +103,7 @@ export function AcceptedPlanStep({
|
||||||
</div>
|
</div>
|
||||||
{totalCount > 0 && (
|
{totalCount > 0 && (
|
||||||
<p className="text-muted-foreground mt-1 text-xs">
|
<p className="text-muted-foreground mt-1 text-xs">
|
||||||
{totalCount} steps
|
{totalCount} step{totalCount === 1 ? "" : "s"}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -139,7 +145,7 @@ export function AcceptedPlanStep({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{planItems.length > 0 && (
|
{activeTaskPlan.length > 0 && (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<h4 className="text-foreground flex items-center gap-2 text-sm font-medium">
|
<h4 className="text-foreground flex items-center gap-2 text-sm font-medium">
|
||||||
Execution Steps
|
Execution Steps
|
||||||
|
|
@ -152,7 +158,7 @@ export function AcceptedPlanStep({
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{planItems
|
{activeTaskPlan
|
||||||
.sort((a, b) => a.index - b.index)
|
.sort((a, b) => a.index - b.index)
|
||||||
.map((item, idx) => (
|
.map((item, idx) => (
|
||||||
<div
|
<div
|
||||||
|
|
@ -170,7 +176,7 @@ export function AcceptedPlanStep({
|
||||||
|
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
<div className="flex items-start justify-between gap-2">
|
<div className="flex items-start justify-between gap-2">
|
||||||
<p
|
<InlineMarkdownText
|
||||||
className={cn(
|
className={cn(
|
||||||
"text-sm leading-relaxed",
|
"text-sm leading-relaxed",
|
||||||
item.completed
|
item.completed
|
||||||
|
|
@ -179,7 +185,7 @@ export function AcceptedPlanStep({
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{item.plan}
|
{item.plan}
|
||||||
</p>
|
</InlineMarkdownText>
|
||||||
<Badge
|
<Badge
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,11 @@ import { Message } from "@langchain/langgraph-sdk";
|
||||||
import { InitializeStep } from "../gen-ui/initialize-step";
|
import { InitializeStep } from "../gen-ui/initialize-step";
|
||||||
import { AcceptedPlanStep } from "../gen-ui/accepted-plan-step";
|
import { AcceptedPlanStep } from "../gen-ui/accepted-plan-step";
|
||||||
import { PlannerGraphState } from "@open-swe/shared/open-swe/planner/types";
|
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 { HumanResponse } from "@langchain/langgraph/prebuilt";
|
||||||
import { LoadingActionsCardContent } from "./thread-view-loading";
|
import { LoadingActionsCardContent } from "./thread-view-loading";
|
||||||
import { Interrupt } from "../thread/messages/interrupt";
|
import { Interrupt } from "../thread/messages/interrupt";
|
||||||
|
|
@ -65,6 +69,7 @@ interface ActionsRendererProps<
|
||||||
customNodeEvents: CustomNodeEvent[];
|
customNodeEvents: CustomNodeEvent[];
|
||||||
setCustomNodeEvents: Dispatch<SetStateAction<CustomNodeEvent[]>>;
|
setCustomNodeEvents: Dispatch<SetStateAction<CustomNodeEvent[]>>;
|
||||||
stream: ReturnType<typeof useStream<StateType>>;
|
stream: ReturnType<typeof useStream<StateType>>;
|
||||||
|
taskPlan?: TaskPlan;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getCustomNodeEventsFromMessages = (
|
const getCustomNodeEventsFromMessages = (
|
||||||
|
|
@ -92,6 +97,7 @@ const getCustomNodeEventsFromMessages = (
|
||||||
export function ActionsRenderer<
|
export function ActionsRenderer<
|
||||||
StateType extends PlannerGraphState | GraphState,
|
StateType extends PlannerGraphState | GraphState,
|
||||||
>({
|
>({
|
||||||
|
taskPlan,
|
||||||
runId,
|
runId,
|
||||||
customNodeEvents,
|
customNodeEvents,
|
||||||
setCustomNodeEvents,
|
setCustomNodeEvents,
|
||||||
|
|
@ -224,6 +230,7 @@ export function ActionsRenderer<
|
||||||
{acceptedPlanEvents.length > 0 &&
|
{acceptedPlanEvents.length > 0 &&
|
||||||
isAcceptedPlanEvents(acceptedPlanEvents) && (
|
isAcceptedPlanEvents(acceptedPlanEvents) && (
|
||||||
<AcceptedPlanStep
|
<AcceptedPlanStep
|
||||||
|
taskPlan={taskPlan}
|
||||||
planTitle={
|
planTitle={
|
||||||
acceptedPlanEvents[acceptedPlanEvents.length - 1].data.planTitle
|
acceptedPlanEvents[acceptedPlanEvents.length - 1].data.planTitle
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -403,6 +403,7 @@ export function ThreadView({
|
||||||
{plannerSession ? (
|
{plannerSession ? (
|
||||||
<div className="scrollbar-pretty-auto overflow-y-auto px-2">
|
<div className="scrollbar-pretty-auto overflow-y-auto px-2">
|
||||||
<ActionsRenderer<PlannerGraphState>
|
<ActionsRenderer<PlannerGraphState>
|
||||||
|
taskPlan={programmerTaskPlan}
|
||||||
runId={plannerSession.runId}
|
runId={plannerSession.runId}
|
||||||
customNodeEvents={customPlannerNodeEvents}
|
customNodeEvents={customPlannerNodeEvents}
|
||||||
setCustomNodeEvents={
|
setCustomNodeEvents={
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue