mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 10:23:14 +00:00
feat: Thread title proposed plan (#494)
* init thread title from proposed plan task * add proposed plan thread title to threadCard component * remove comments * refactor * abstract computeThreadTitle * self CR, refactor * self CR, refactor, rm unused import from un-needed memo * Update apps/web/src/lib/thread.ts Co-authored-by: Brace Sproul <braceasproul@gmail.com> * CR: useThreadMetadata remove increased polling speed * CR: revert inlineMD, rm wrapped <p> pass className to basicMD, import getActiveTask * CR: revert getActiveTaskPlan to previous first task logic --------- Co-authored-by: Brace Sproul <braceasproul@gmail.com>
This commit is contained in:
parent
6f31717637
commit
fac83e1a55
5 changed files with 28 additions and 15 deletions
|
|
@ -327,9 +327,9 @@ export function TasksSidebar({
|
|||
<div className="min-w-0 flex-1">
|
||||
<>
|
||||
<div className="mb-1 flex items-start justify-between gap-2">
|
||||
<p className="text-sm leading-relaxed text-gray-900 dark:text-gray-100">
|
||||
<BasicMarkdownText>{item.plan}</BasicMarkdownText>
|
||||
</p>
|
||||
<BasicMarkdownText className="text-sm leading-relaxed text-gray-900 dark:text-gray-100">
|
||||
{item.plan}
|
||||
</BasicMarkdownText>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { cn } from "@/lib/utils";
|
|||
import { TaskPlan } from "@open-swe/shared/open-swe/types";
|
||||
import { getActivePlanItems } from "@open-swe/shared/open-swe/tasks";
|
||||
import { InlineMarkdownText } from "../thread/markdown-text";
|
||||
import { computeThreadTitle } from "@/lib/thread";
|
||||
|
||||
interface ThreadCardProps {
|
||||
thread: ThreadMetadata;
|
||||
|
|
@ -36,6 +37,7 @@ export function ThreadCard({
|
|||
}: ThreadCardProps) {
|
||||
const router = useRouter();
|
||||
|
||||
const threadTitle = computeThreadTitle(taskPlan, thread.title);
|
||||
const isStatusLoading = statusLoading && !status;
|
||||
const displayStatus = status || ("idle" as ThreadUIStatus);
|
||||
|
||||
|
|
@ -48,7 +50,6 @@ export function ThreadCard({
|
|||
const planItems = getActivePlanItems(taskPlan);
|
||||
const sortedPlanItems = [...planItems].sort((a, b) => a.index - b.index);
|
||||
|
||||
// Find the current task (lowest index among uncompleted tasks)
|
||||
const currentTaskIndex = sortedPlanItems
|
||||
.filter((item) => !item.completed)
|
||||
.reduce(
|
||||
|
|
@ -58,8 +59,8 @@ export function ThreadCard({
|
|||
|
||||
const displayCurrentIndex =
|
||||
currentTaskIndex === Number.POSITIVE_INFINITY
|
||||
? sortedPlanItems.length // All tasks completed
|
||||
: currentTaskIndex; // +1 for 1-based display
|
||||
? sortedPlanItems.length
|
||||
: currentTaskIndex;
|
||||
|
||||
return {
|
||||
currentTaskIndex: displayCurrentIndex,
|
||||
|
|
@ -137,7 +138,7 @@ export function ThreadCard({
|
|||
<div className="flex items-start justify-between gap-2">
|
||||
<div className="min-w-0 flex-1">
|
||||
<CardTitle className="text-foreground truncate text-sm">
|
||||
<InlineMarkdownText>{thread.title}</InlineMarkdownText>
|
||||
<InlineMarkdownText>{threadTitle}</InlineMarkdownText>
|
||||
</CardTitle>
|
||||
<div className="mt-1 flex items-center gap-1">
|
||||
<GitBranch className="text-muted-foreground h-2 w-2" />
|
||||
|
|
|
|||
|
|
@ -188,12 +188,10 @@ export function ThreadView({
|
|||
}
|
||||
}, [plannerStream.values, selectedTab]);
|
||||
|
||||
// Extract task plan from programmer stream
|
||||
useEffect(() => {
|
||||
if (programmerStream.values?.taskPlan) {
|
||||
setProgrammerTaskPlan(programmerStream.values.taskPlan);
|
||||
} else if (realTimeTaskPlan) {
|
||||
// Fallback to real-time task plan if stream doesn't have it
|
||||
setProgrammerTaskPlan(realTimeTaskPlan);
|
||||
}
|
||||
}, [programmerStream.values, realTimeTaskPlan]);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { ManagerGraphState } from "@open-swe/shared/open-swe/manager/types";
|
|||
import { ThreadMetadata } from "@/components/v2/types";
|
||||
import { useThreadStatus } from "./useThreadStatus";
|
||||
import { useMemo } from "react";
|
||||
import { getThreadTitle } from "@/lib/thread";
|
||||
import { getThreadTitle, computeThreadTitle } from "@/lib/thread";
|
||||
import { calculateLastActivity } from "@/lib/thread-utils";
|
||||
|
||||
/**
|
||||
|
|
@ -18,6 +18,7 @@ export function useThreadMetadata(thread: Thread<ManagerGraphState>): {
|
|||
status,
|
||||
isLoading: isStatusLoading,
|
||||
error: statusError,
|
||||
taskPlan: realTimeTaskPlan,
|
||||
} = useThreadStatus(thread.thread_id);
|
||||
|
||||
const metadata: ThreadMetadata = useMemo((): ThreadMetadata => {
|
||||
|
|
@ -25,14 +26,14 @@ export function useThreadMetadata(thread: Thread<ManagerGraphState>): {
|
|||
|
||||
return {
|
||||
id: thread.thread_id,
|
||||
title: getThreadTitle(thread),
|
||||
title: computeThreadTitle(realTimeTaskPlan, getThreadTitle(thread)),
|
||||
lastActivity: calculateLastActivity(thread.updated_at),
|
||||
taskCount: values?.taskPlan?.tasks.length ?? 0,
|
||||
taskCount: realTimeTaskPlan?.tasks.length ?? 0,
|
||||
repository: values?.targetRepository
|
||||
? `${values.targetRepository.owner}/${values.targetRepository.repo}`
|
||||
: "",
|
||||
branch: values?.targetRepository?.branch || "main",
|
||||
taskPlan: values?.taskPlan,
|
||||
taskPlan: realTimeTaskPlan,
|
||||
status,
|
||||
githubIssue: values?.githubIssueId
|
||||
? {
|
||||
|
|
@ -41,7 +42,7 @@ export function useThreadMetadata(thread: Thread<ManagerGraphState>): {
|
|||
}
|
||||
: undefined,
|
||||
};
|
||||
}, [thread, status]);
|
||||
}, [thread, status, realTimeTaskPlan]);
|
||||
|
||||
return {
|
||||
metadata,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,21 @@
|
|||
import { Thread } from "@langchain/langgraph-sdk";
|
||||
import { getMessageContentString } from "@open-swe/shared/messages";
|
||||
import { GraphState } from "@open-swe/shared/open-swe/types";
|
||||
import { GraphState, TaskPlan } from "@open-swe/shared/open-swe/types";
|
||||
import { getActivePlanItems } from "@open-swe/shared/open-swe/tasks";
|
||||
|
||||
export function computeThreadTitle(
|
||||
taskPlan: TaskPlan | undefined,
|
||||
fallbackTitle: string,
|
||||
): string {
|
||||
if (taskPlan?.tasks && taskPlan.tasks.length > 0) {
|
||||
const firstTaskTitle = taskPlan.tasks[0]?.title;
|
||||
if (firstTaskTitle && firstTaskTitle.trim()) {
|
||||
return firstTaskTitle;
|
||||
}
|
||||
}
|
||||
return fallbackTitle;
|
||||
}
|
||||
|
||||
export function getThreadTitle<State extends Record<string, any> = GraphState>(
|
||||
thread: Thread<State>,
|
||||
): string {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue