From 00bee0486752baf2394c4e6dcda8a6d400d82724 Mon Sep 17 00:00:00 2001 From: Gemini AI Date: Tue, 23 Dec 2025 13:42:49 +0400 Subject: [PATCH] feat: add enhanced MULTIX UI features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added all missing MULTIX enhancements matching the original screenshot: 1. STREAMING indicator: - Animated purple badge with sparkles icon - Shows live token count during streaming - Pulsing animation effect 2. Status badges: - PENDING/RUNNING/DONE badges for tasks - Color-coded based on status 3. APEX/SHIELD renamed: - 'Auto' → 'APEX' with tooltip - 'Shield' → 'SHIELD' with tooltip 4. THINKING indicator: - Bouncing dots animation (3 dots) - Shows THINKING or SENDING status 5. STOP button: - Red stop button appears during agent work - Calls cancel endpoint to interrupt 6. Detailed token stats bar: - INPUT/OUTPUT tokens - REASONING tokens (amber) - CACHE READ (emerald) - CACHE WRITE (cyan) - COST (violet) - MODEL (indigo) 7. Message navigation sidebar: - YOU/ASST labels for each message - Click to scroll to message - Appears on right side when viewing task --- .../src/components/chat/multi-task-chat.tsx | 476 ++++++++++++------ 1 file changed, 314 insertions(+), 162 deletions(-) diff --git a/packages/ui/src/components/chat/multi-task-chat.tsx b/packages/ui/src/components/chat/multi-task-chat.tsx index 0a69a42..ef9322a 100644 --- a/packages/ui/src/components/chat/multi-task-chat.tsx +++ b/packages/ui/src/components/chat/multi-task-chat.tsx @@ -27,6 +27,12 @@ import { Layers, Shield, Activity, + Square, + Clock, + Sparkles, + StopCircle, + Bot, + User, } from "lucide-solid"; import type { InstanceMessageStore } from "@/stores/message-v2/instance-store"; import type { Task } from "@/types/session"; @@ -105,9 +111,21 @@ export default function MultiTaskChat(props: MultiTaskChatProps) { return { used: usage?.actualUsageTokens ?? 0, total: usage?.totalCost ?? 0, + input: usage?.inputTokens ?? 0, + output: usage?.outputTokens ?? 0, + reasoning: usage?.reasoningTokens ?? 0, + cacheRead: usage?.cacheReadTokens ?? 0, + cacheWrite: usage?.cacheWriteTokens ?? 0, + cost: usage?.totalCost ?? 0, }; }); + // Get current model from instance + const currentModel = createMemo(() => { + const instance = instances().get(props.instanceId); + return instance?.modelId || "unknown"; + }); + const activeTaskSessionId = createMemo(() => { const task = selectedTask(); return task?.taskSessionId || props.sessionId; @@ -153,7 +171,7 @@ export default function MultiTaskChat(props: MultiTaskChatProps) { createEffect(() => { const ids = filteredMessageIds(); const thinking = isAgentThinking(); - + // Scroll when message count changes or when thinking starts if (ids.length > 0 || thinking) { requestAnimationFrame(() => { @@ -242,6 +260,25 @@ export default function MultiTaskChat(props: MultiTaskChatProps) { } }; + // Stop/cancel the current agent operation + const handleStopAgent = async () => { + const task = selectedTask(); + if (!task) return; + + log.info("Stopping agent for task:", task.id); + // Send interrupt signal via the session API + try { + const targetSessionId = task.taskSessionId || props.sessionId; + // Use the cancel endpoint or interrupt mechanism + await fetch(`/api/workspaces/${props.instanceId}/sessions/${targetSessionId}/cancel`, { + method: "POST", + }); + log.info("Agent stopped successfully"); + } catch (error) { + log.error("Failed to stop agent:", error); + } + }; + return (
{/* Header */} @@ -274,6 +311,27 @@ export default function MultiTaskChat(props: MultiTaskChatProps) {
+ {/* STREAMING indicator */} + +
+ + Streaming + {formatTokenTotal(tokenStats().used)} +
+
+ + {/* Task status badge */} + +
+ {selectedTask()?.status === "completed" ? "DONE" : selectedTask()?.status === "in-progress" ? "RUNNING" : "PENDING"} +
+
+ @@ -336,181 +394,275 @@ export default function MultiTaskChat(props: MultiTaskChatProps) { {/* Main Content Area - min-h-0 is critical for flex containers with overflow */} -
-
- - true} - thinkingDefaultExpanded={() => true} - showUsageMetrics={() => true} - scrollContainer={() => scrollContainer} - setBottomSentinel={setBottomSentinel} - /> -
- }> - {/* Pipeline View */} -
-
-

Pipeline

-

Agentic Orchestration

+
+ {/* Main chat area */} +
+
+ + true} + thinkingDefaultExpanded={() => true} + showUsageMetrics={() => true} + scrollContainer={() => scrollContainer} + setBottomSentinel={setBottomSentinel} + />
- -
-
- Active Threads -
- - {tasks().length} - + }> + {/* Pipeline View */} +
+
+

Pipeline

+

Agentic Orchestration

-
- -
- -
-
-

No active tasks

-

Send a message below to start a new thread

-
-
- }> - {(task) => ( - - )} - -
-
-
- -
- - {/* Chat Input Area - Fixed at bottom */} -
-
- {/* Header Row */} -
-
-
- -
-
- - {selectedTaskId() ? "Task Context" : "Global Pipeline"} - - - {selectedTaskId() ? "MultiX Threaded" : "Auto-Task"} - -
-
- -
- - - 0}> -
- {formatTokenTotal(tokenStats().used)} +
+

No active tasks

+

Send a message below to start a new thread

+
+
+ }> + {(task) => ( + + )} +
- - -
- - {isAgentThinking() ? "Thinking" : "Sending"} -
-
+
-
+ +
- {/* Text Input */} -