import { createSignal, createMemo, Show, For, onMount } from "solid-js"; import { sessions, withSession, setActiveSession } from "@/stores/session-state"; import { instances } from "@/stores/instances"; import { sendMessage } from "@/stores/session-actions"; import { addTask, setActiveTask } from "@/stores/task-actions"; import { messageStoreBus } from "@/stores/message-v2/bus"; import MessageBlockList from "@/components/message-block-list"; import { Command, Plus, CheckCircle2, MoreHorizontal, PanelRight, ListTodo, AtSign, Hash, Mic, ArrowUp, Terminal, FileCode2, ChevronRight, Loader2, AlertCircle, Clock, Code2, } from "lucide-solid"; import type { Task, TaskStatus } from "@/types/session"; import type { InstanceMessageStore } from "@/stores/message-v2/instance-store"; interface MultiTaskChatProps { instanceId: string; sessionId: string; } type PanelView = "tasks" | "active"; export default function MultiTaskChat(props: MultiTaskChatProps) { const session = () => { const instanceSessions = sessions().get(props.instanceId); return instanceSessions?.get(props.sessionId); }; const selectedTaskId = () => session()?.activeTaskId || null; const setSelectedTaskId = (id: string | null) => setActiveTask(props.instanceId, props.sessionId, id || undefined); const [isCreatingTask, setIsCreatingTask] = createSignal(false); const [chatInput, setChatInput] = createSignal(""); const [isSending, setIsSending] = createSignal(false); let scrollContainer: HTMLDivElement | undefined; const [bottomSentinel, setBottomSentinel] = createSignal(null); // Message store integration for chat display const messageStore = () => messageStoreBus.getOrCreate(props.instanceId); const messageIds = () => messageStore().getSessionMessageIds(props.sessionId); const lastAssistantIndex = () => { const ids = messageIds(); const store = messageStore(); for (let i = ids.length - 1; i >= 0; i--) { const msg = store.getMessage(ids[i]); if (msg?.role === "assistant") return i; } return -1; }; // Handle message sending with comprehensive error handling const handleSendMessage = async () => { const message = chatInput().trim(); if (!message || isSending()) return; const currentInstance = instances().get(props.instanceId); const instanceSessions = sessions().get(props.instanceId); const currentSession = instanceSessions?.get(props.sessionId); const sessionTasks = currentSession?.tasks || []; const selectedTask = sessionTasks.find((task: Task) => task.id === selectedTaskId()); if (!currentInstance || !currentSession) { console.error("[MultiTaskChat] Instance or session not available"); return; } setIsSending(true); try { const messageId = await sendMessage( props.instanceId, props.sessionId, message, [], // No attachments for now selectedTask?.id ); // Clear input after successful send setChatInput(""); console.log("[MultiTaskChat] Message sent successfully:", messageId); } catch (error) { console.error("[MultiTaskChat] Failed to send message:", error); // TODO: Show toast notification to user } finally { setIsSending(false); } }; // Handle keyboard shortcuts (Cmd/Ctrl+Enter to send) const handleKeyDown = (e: KeyboardEvent) => { if ((e.metaKey || e.ctrlKey) && e.key === "Enter") { e.preventDefault(); handleSendMessage(); } }; // Handle artifact opening via code streamer const handleArtifactOpen = (artifact: any) => { console.log("[MultiTaskChat] Opening artifact:", artifact); // TODO: Implement code streamer integration // For now, we'll log artifact and show a placeholder message console.log(`[MultiTaskChat] Would open ${artifact.name} (${artifact.type})`); // TODO: Show toast notification to user }; const tasks = () => { const instanceSessions = sessions().get(props.instanceId); const currentSession = instanceSessions?.get(props.sessionId); return currentSession?.tasks || []; }; const handleAddTask = () => { const taskTitle = `Task ${tasks().length + 1}`; addTask(props.instanceId, props.sessionId, taskTitle); }; const formatTimestamp = (timestamp: number) => { return new Date(timestamp).toLocaleTimeString(); }; const selectedTask = () => { const instanceSessions = sessions().get(props.instanceId); const currentSession = instanceSessions?.get(props.sessionId); const sessionTasks = currentSession?.tasks || []; return sessionTasks.find(task => task.id === selectedTaskId()); }; return (
{/* Header */}
MULTIX
}>
{tasks().length}
{/* TASK LIST VIEW - CODEX 5.1 Styled */}

Project Pipeline

Manage and orchestrate agentic tasks

{/* Task List */}
{(task) => (
setSelectedTaskId(task.id)} class={`p-4 rounded-xl border transition-all cursor-pointer ${ task.id === selectedTaskId() ? "bg-indigo-500/10 border-indigo-500/20" : "bg-zinc-800/40 border-white/5 hover:border-indigo-500/20 hover:bg-indigo-500/5" }`} >
{task.status === "completed" ? ( ) : task.status === "in-progress" ? ( ) : ( )}

{task.title}

{formatTimestamp(task.timestamp)}

)}
{/* TASK CHAT VIEW - When task is selected */}
scrollContainer} setBottomSentinel={setBottomSentinel} showThinking={() => true} thinkingDefaultExpanded={() => true} showUsageMetrics={() => true} />
{/* CODEX 5.1 Chat Input Area */}
TASK ASSISTANT
{selectedTask()?.status}