+
{chatColumn}
);
diff --git a/src/components/Session/SidePanelSections/ProgressSection.tsx b/src/components/Session/SidePanelSections/ProgressSection.tsx
index 053bb9c5..a10a27ca 100644
--- a/src/components/Session/SidePanelSections/ProgressSection.tsx
+++ b/src/components/Session/SidePanelSections/ProgressSection.tsx
@@ -23,6 +23,7 @@ import { cn } from '@/lib/utils';
import { usePageTabStore } from '@/store/pageTabStore';
import { TaskStatus } from '@/types/constants';
import { AnimatePresence, motion } from 'framer-motion';
+import { useMemo } from 'react';
function isDone(task: TaskInfo) {
return task.status === TaskStatus.COMPLETED;
@@ -34,14 +35,18 @@ interface ProgressSectionProps {
}
export function ProgressSection({ title, subtasks }: ProgressSectionProps) {
- const count = subtasks.length;
+ const visibleSubtasks = useMemo(
+ () => subtasks.filter((task) => task.content.trim() !== ''),
+ [subtasks]
+ );
+ const count = visibleSubtasks.length;
const requestTaskBoxFocus = usePageTabStore((s) => s.requestTaskBoxFocus);
const collapsedStrip =
count > 0 ? (
- {subtasks.map((task, idx) => (
+ {visibleSubtasks.map((task, idx) => (
- {idx < subtasks.length - 1 ? : null}
+ {idx < visibleSubtasks.length - 1 ? : null}
))}
@@ -78,7 +83,7 @@ export function ProgressSection({ title, subtasks }: ProgressSectionProps) {
return (
- {subtasks.map((task) => (
+ {visibleSubtasks.map((task) => (
{
- const fallback = {
- taskCardVisible: false,
- isSkeletonPhase: false,
- showStreamingDecompose: false,
- taskType: 1 as 1 | 2 | 3,
- };
- if (!activeTask || !activeTaskId) return fallback;
+ const { taskCardVisible, taskType } = useMemo(() => {
+ const fallback = {
+ taskCardVisible: false,
+ taskType: 1 as 1 | 2 | 3,
+ };
+ if (!activeTask || !activeTaskId) return fallback;
- const messages = activeTask.messages;
- const isHumanReply =
- !!activeTask.activeAsk ||
- (() => {
- const userMessages = messages.filter((m: any) => m.role === 'user');
- const lastUser = userMessages[userMessages.length - 1];
- if (!lastUser) return false;
- const userMessageIndex = messages.findIndex(
- (m: any) => m.id === lastUser.id
+ const messages = activeTask.messages;
+ const isHumanReply =
+ !!activeTask.activeAsk ||
+ (() => {
+ const userMessages = messages.filter((m: any) => m.role === 'user');
+ const lastUser = userMessages[userMessages.length - 1];
+ if (!lastUser) return false;
+ const userMessageIndex = messages.findIndex(
+ (m: any) => m.id === lastUser.id
+ );
+ if (userMessageIndex > 0) {
+ const prevMessage = messages[userMessageIndex - 1];
+ return (
+ prevMessage?.role === 'agent' && prevMessage?.step === AgentStep.ASK
);
- if (userMessageIndex > 0) {
- const prevMessage = messages[userMessageIndex - 1];
- return (
- prevMessage?.role === 'agent' &&
- prevMessage?.step === AgentStep.ASK
- );
- }
- return false;
- })();
-
- const anyToSubTasksMessage = messages.find(
- (m: any) => m.step === AgentStep.TO_SUB_TASKS
- );
- const isSkeletonPhaseLocal =
- (activeTask.status !== ChatTaskStatus.FINISHED &&
- activeTask.status !== ChatTaskStatus.RUNNING &&
- !anyToSubTasksMessage &&
- !activeTask.hasWaitComfirm &&
- messages.length > 0) ||
- (!!activeTask.isTakeControl && !anyToSubTasksMessage);
-
- let lastUserIndex = -1;
- for (let i = messages.length - 1; i >= 0; i--) {
- if (messages[i].role === 'user') {
- lastUserIndex = i;
- break;
}
- }
- const afterLastUser =
- lastUserIndex >= 0 ? messages.slice(lastUserIndex + 1) : [];
- const hasTaskPlanForCurrentTurn = afterLastUser.some(
- (m: any) => m.step === AgentStep.TO_SUB_TASKS
- );
+ return false;
+ })();
- const isDecomposing = streamingDecomposeText.length > 0;
- const shouldShowFallbackTask =
- lastUserIndex >= 0 &&
- !hasTaskPlanForCurrentTurn &&
+ const anyToSubTasksMessage = messages.find(
+ (m: any) => m.step === AgentStep.TO_SUB_TASKS
+ );
+ const isSkeletonPhaseLocal =
+ (activeTask.status !== ChatTaskStatus.FINISHED &&
+ activeTask.status !== ChatTaskStatus.RUNNING &&
+ !anyToSubTasksMessage &&
!activeTask.hasWaitComfirm &&
- !isDecomposing &&
- activeTask.status !== ChatTaskStatus.FINISHED;
+ messages.length > 0) ||
+ (!!activeTask.isTakeControl && !anyToSubTasksMessage);
- const taskLike = hasTaskPlanForCurrentTurn || shouldShowFallbackTask;
+ let lastUserIndex = -1;
+ for (let i = messages.length - 1; i >= 0; i--) {
+ if (messages[i].role === 'user') {
+ lastUserIndex = i;
+ break;
+ }
+ }
+ const afterLastUser =
+ lastUserIndex >= 0 ? messages.slice(lastUserIndex + 1) : [];
+ const hasTaskPlanForCurrentTurn = afterLastUser.some(
+ (m: any) => m.step === AgentStep.TO_SUB_TASKS
+ );
- const taskCardVisibleLocal =
- taskLike && !isSkeletonPhaseLocal && !isHumanReply;
+ const isDecomposing = streamingDecomposeText.length > 0;
+ const shouldShowFallbackTask =
+ lastUserIndex >= 0 &&
+ !hasTaskPlanForCurrentTurn &&
+ !activeTask.hasWaitComfirm &&
+ !isDecomposing &&
+ activeTask.status !== ChatTaskStatus.FINISHED;
- const showStreamingDecomposeLocal =
- streamingDecomposeText.length > 0 &&
- activeTask.status !== ChatTaskStatus.FINISHED &&
- !isHumanReply &&
- !hasTaskPlanForCurrentTurn;
+ const taskLike = hasTaskPlanForCurrentTurn || shouldShowFallbackTask;
- const toSub = [...messages]
- .reverse()
- .find((m: any) => m.step === AgentStep.TO_SUB_TASKS);
- const taskTypeLocal = (toSub?.taskType as 1 | 2 | 3) || 1;
+ const taskCardVisibleLocal =
+ taskLike && !isSkeletonPhaseLocal && !isHumanReply;
- return {
- taskCardVisible: taskCardVisibleLocal,
- isSkeletonPhase: isSkeletonPhaseLocal,
- showStreamingDecompose: showStreamingDecomposeLocal,
- taskType: taskTypeLocal,
- };
- }, [activeTask, activeTaskId, streamingDecomposeText]);
+ const toSub = [...messages]
+ .reverse()
+ .find((m: any) => m.step === AgentStep.TO_SUB_TASKS);
+ const taskTypeLocal = (toSub?.taskType as 1 | 2 | 3) || 1;
+
+ return {
+ taskCardVisible: taskCardVisibleLocal,
+ taskType: taskTypeLocal,
+ };
+ }, [activeTask, activeTaskId, streamingDecomposeText]);
const sortedAgents = useMemo(() => {
const base = [...BASE_WORKFLOW_AGENTS, ...workerList].filter(
@@ -300,6 +288,22 @@ export default function FoldedPanel({
activeTask.status === ChatTaskStatus.FINISHED ||
activeTask.status === ChatTaskStatus.PAUSE);
+ const hasUnconfirmedPlan = Boolean(
+ activeTask?.messages.some(
+ (m: any) => m.step === AgentStep.TO_SUB_TASKS && !m.isConfirm
+ )
+ );
+ const showPlanTaskBox = Boolean(
+ activeTaskId &&
+ activeTask &&
+ activeChatStore &&
+ !activeTask.hasWaitComfirm &&
+ !isMainTaskStarted &&
+ (isPlanSplittingPhase(activeTask) ||
+ streamingDecomposeText.length > 0 ||
+ hasUnconfirmedPlan)
+ );
+
/** TaskCard only after the main task has started and an agent is selected (not detail-pane "Select an agent"). */
const showFoldedTaskCard =
taskCardVisible && isMainTaskStarted && detailAgent != null;
@@ -427,53 +431,45 @@ export default function FoldedPanel({
))}
- {(showFoldedTaskCard ||
- isSkeletonPhase ||
- showStreamingDecompose) &&
+ {showFoldedTaskCard &&
activeTaskId &&
activeTask &&
chatStore && (