From c671b660437bb1175bee243e771e55fed9a0a8a0 Mon Sep 17 00:00:00 2001 From: steven_li Date: Fri, 22 May 2026 14:34:45 +0800 Subject: [PATCH] feat(frontend): restore session progress sidebar --- app-instance/frontend/app/(app)/page.tsx | 39 +- .../CurrentSessionProgressSidebar.tsx | 324 +++++++++++++++ .../frontend/lib/chat-messages.test.ts | 22 +- app-instance/frontend/lib/chat-messages.ts | 36 ++ .../frontend/lib/session-progress.test.ts | 201 +++++++++ app-instance/frontend/lib/session-progress.ts | 392 ++++++++++++++++++ app-instance/frontend/lib/store.test.ts | 15 + app-instance/frontend/lib/store.ts | 24 +- 8 files changed, 1046 insertions(+), 7 deletions(-) create mode 100644 app-instance/frontend/components/chat-workbench/CurrentSessionProgressSidebar.tsx create mode 100644 app-instance/frontend/lib/session-progress.test.ts create mode 100644 app-instance/frontend/lib/session-progress.ts diff --git a/app-instance/frontend/app/(app)/page.tsx b/app-instance/frontend/app/(app)/page.tsx index a67c7a1..a2b1994 100644 --- a/app-instance/frontend/app/(app)/page.tsx +++ b/app-instance/frontend/app/(app)/page.tsx @@ -5,6 +5,7 @@ import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useSta import { Brain, Plus, Send, Trash2, X } from 'lucide-react'; import { ChatWorkbench } from '@/components/chat-workbench/ChatWorkbench'; +import { CurrentSessionProgressSidebar } from '@/components/chat-workbench/CurrentSessionProgressSidebar'; import { ScrollArea } from '@/components/ui/scroll-area'; import { archiveSession, @@ -18,9 +19,10 @@ import { uploadFile, wsManager, } from '@/lib/api'; -import { mergeServerWithPendingUsers } from '@/lib/chat-messages'; +import { mergeServerWithPendingUsers, shouldMergePendingUsers } from '@/lib/chat-messages'; import { pickAppText } from '@/lib/i18n/core'; import { useAppI18n } from '@/lib/i18n/provider'; +import { buildSessionProgressView } from '@/lib/session-progress'; import { useChatStore } from '@/lib/store'; import type { ActiveTask, ChatMessage, FileAttachment, SessionUpdatedEvent, WsEvent } from '@/types'; @@ -60,6 +62,9 @@ export default function ChatPage() { setSessionId, setMessages, addMessage, + setInputDraft, + getInputDraft, + clearInputDraft, setIsLoading, clearMessages, setIsThinking, @@ -68,7 +73,7 @@ export default function ChatPage() { updateMessageFeedback, } = useChatStore(); - const [input, setInput] = useState(''); + const [input, setInput] = useState(() => useChatStore.getState().getInputDraft(useChatStore.getState().sessionId)); const [thinkingModeEnabled, setThinkingModeEnabled] = useState(loadThinkingModePreference); const [pendingFiles, setPendingFiles] = useState>([]); const [activeTask, setActiveTask] = useState(null); @@ -105,6 +110,17 @@ export default function ChatPage() { ); const selectedSessionRunId = selectedRunId && sessionRunIds.has(selectedRunId) ? selectedRunId : null; + const sessionProgressView = useMemo( + () => + buildSessionProgressView({ + sessionId, + processRuns, + processEvents, + processArtifacts, + locale, + }), + [locale, processArtifacts, processEvents, processRuns, sessionId] + ); const loadSessions = useCallback(async () => { try { @@ -141,7 +157,8 @@ export default function ChatPage() { setSessionProcess(key, process); } void loadActiveTask(key); - const nextMessages = waitingForReply + const shouldMergePending = shouldMergePendingUsers(detail.messages, localSnapshot, waitingForReply); + const nextMessages = shouldMergePending ? mergeServerWithPendingUsers(detail.messages, localSnapshot) : detail.messages; setMessages(nextMessages); @@ -167,6 +184,7 @@ export default function ChatPage() { } setActiveTask(null); setRevisionTargetRunId(null); + setInput(useChatStore.getState().getInputDraft(sessionId)); void loadSessionMessages(sessionId); void loadActiveTask(sessionId); }, [clearMessages, loadActiveTask, loadSessionMessages, sessionId, setIsLoading, setIsThinking]); @@ -308,6 +326,7 @@ export default function ChatPage() { } setInput(''); + clearInputDraft(sessionId); setPendingFiles([]); addMessage({ role: 'user', @@ -372,7 +391,7 @@ export default function ChatPage() { }); } } - }, [addMessage, input, isLoading, loadActiveTask, loadSessionMessages, loadSessions, locale, pendingFiles, revisionTargetRunId, sessionId, setIsLoading, setIsThinking, setSessionProcess, thinkingModeEnabled, updateMessageFeedback]); + }, [addMessage, clearInputDraft, input, isLoading, loadActiveTask, loadSessionMessages, loadSessions, locale, pendingFiles, revisionTargetRunId, sessionId, setIsLoading, setIsThinking, setSessionProcess, thinkingModeEnabled, updateMessageFeedback]); const handleFeedback = useCallback(async (runId: string, feedbackType: 'satisfied' | 'revise' | 'abandon', comment?: string) => { updateMessageFeedback(runId, feedbackType); @@ -433,6 +452,8 @@ export default function ChatPage() { setSelectedRunId(null); setActiveTask(null); setRevisionTargetRunId(null); + clearInputDraft(id); + setInput(''); clearMessages(); useChatStore.getState().resetProcessState(); try { @@ -452,6 +473,8 @@ export default function ChatPage() { setSessionId('web:default'); setActiveTask(null); setRevisionTargetRunId(null); + clearInputDraft(key); + setInput(useChatStore.getState().getInputDraft('web:default')); clearMessages(); useChatStore.getState().resetProcessState(); } @@ -469,6 +492,7 @@ export default function ChatPage() { setSelectedRunId(null); setActiveTask(null); setRevisionTargetRunId(null); + setInput(useChatStore.getState().getInputDraft(key)); setSessionId(key); }; @@ -619,7 +643,10 @@ export default function ChatPage() {