From 1bb5018bb33d5e9d2c9c0ce69509a910a67813e8 Mon Sep 17 00:00:00 2001 From: Anthony Ronning <101225832+AnthonyRonning@users.noreply.github.com> Date: Sat, 11 Jul 2026 07:40:40 +0000 Subject: [PATCH] feat: align agent chat with normal chat --- frontend/src/components/AgentMode.tsx | 245 +++++++++++++------- frontend/src/components/UnifiedChat.tsx | 204 ++++++---------- frontend/src/components/chat/ChatTurn.tsx | 138 +++++++++++ frontend/src/components/markdown.tsx | 14 +- frontend/src/services/agentTimeline.test.ts | 105 ++++++++- frontend/src/services/agentTimeline.ts | 42 ++++ 6 files changed, 525 insertions(+), 223 deletions(-) create mode 100644 frontend/src/components/chat/ChatTurn.tsx diff --git a/frontend/src/components/AgentMode.tsx b/frontend/src/components/AgentMode.tsx index d63903d27..20421272e 100644 --- a/frontend/src/components/AgentMode.tsx +++ b/frontend/src/components/AgentMode.tsx @@ -16,15 +16,20 @@ import { MessageSquarePlus, MoreHorizontal, ShieldCheck, - Terminal, Trash, X, Zap } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; -import { Badge } from "@/components/ui/badge"; -import { Markdown } from "@/components/markdown"; +import { Markdown, ThinkingBlock } from "@/components/markdown"; +import { + CHAT_COMPOSER_TEXTAREA_CLASS, + ChatAssistantTurn, + ChatComposerSurface, + ChatDesktopConversationHeader, + ChatUserTurn +} from "@/components/chat/ChatTurn"; import { Select, SelectContent, @@ -60,7 +65,12 @@ import { proxyService } from "@/services/proxyService"; import { agentOperationFence } from "@/services/agentOperationFence"; -import { coalesceAdjacentThinkingItems, hasRenderableThinkingText } from "@/services/agentTimeline"; +import { + activeAgentThinkingItemId, + coalesceAdjacentThinkingItems, + groupAgentTimelineItems, + hasRenderableThinkingText +} from "@/services/agentTimeline"; import { DEFAULT_AGENT_MODEL, PRIMARY_AGENT_MODEL_IDS, @@ -288,6 +298,10 @@ export function AgentMode({ userId }: { userId: string }) { if (!projectRoot) return "Select folder"; return recentRoots.find((root) => root.path === projectRoot)?.name || basename(projectRoot); }, [projectRoot, recentRoots]); + const activeSessionTitle = useMemo(() => { + const activeSession = sessions.find((session) => session.id === activeSessionId); + return activeSession ? sessionTitle(activeSession) : "Agent session"; + }, [activeSessionId, sessions]); const activeRunId = activeSessionId ? (activeRunsBySession[activeSessionId] ?? null) : null; const activePendingSendKey = activeSessionId || NEW_SESSION_PENDING_KEY; const isSubmitting = pendingSendSessionIds.has(activePendingSendKey); @@ -1407,6 +1421,14 @@ export function AgentMode({ userId }: { userId: string }) { )} + {timelineItems.length > 0 ? ( + void createSession()} + /> + ) : null} + {hasManualProxyConflict && (
@@ -1449,10 +1471,10 @@ export function AgentMode({ userId }: { userId: string }) {
-
+
{timelineItems.length === 0 ? ( void sendMessage()} /> ) : ( - + )}
{timelineItems.length > 0 ? ( -
-
+
+
void sendMessage()} /> +

+ AI can make mistakes. Check important info. +

) : null} @@ -1515,11 +1544,15 @@ export function AgentMode({ userId }: { userId: string }) { function EmptyAgentState(props: AgentComposerProps) { return (
-
-

+
+

Work in a folder... -

+

+

+ + Encrypted and private at every step +

); @@ -1914,7 +1947,7 @@ function AgentComposer({ : recentRoots; return ( -
+