/* 3-pane IDE workspace: FileTree | Editor+Terminal | AgentTimeline */ import { useState, useRef, useCallback } from "react"; import { FileTree, type FileNode } from "./FileTree"; import { MonacoEditor } from "./MonacoEditor"; import { Terminal } from "#/components/Terminal"; import { AgentTimeline } from "#/components/ui/AgentTimeline"; interface TimelineEvent { id: string; type: "action" | "observation" | "message" | "error" | "status"; actionType?: string; title: string; detail?: string; timestamp: Date; duration?: number; status?: "running" | "done" | "error" | "skipped"; } interface IDEWorkspaceProps { files: FileNode[]; timelineEvents: TimelineEvent[]; terminalLines: Array<{ id: string; type: "input" | "output" | "system"; text: string; timestamp: number; }>; onTerminalCommand?: (cmd: string) => void; } export function IDEWorkspace({ files, timelineEvents, terminalLines, onTerminalCommand, }: IDEWorkspaceProps) { const [activeFile, setActiveFile] = useState(""); const [activeCode, setActiveCode] = useState(""); const [showTimeline, setShowTimeline] = useState(true); const [showFileTree, setShowFileTree] = useState(true); const [showTerminal, setShowTerminal] = useState(true); const containerRef = useRef(null); /* drag-resize state */ const [leftWidth, setLeftWidth] = useState(240); const [rightWidth, setRightWidth] = useState(280); const [terminalHeight] = useState(200); const isDraggingLeft = useRef(false); const isDraggingRight = useRef(false); const isDraggingTerminal = useRef(false); const handleFileSelect = useCallback((path: string) => { setActiveFile(path); /* find code content from observations - for now, pick the file name */ setActiveCode(`// ${path}\n// Select a file to view its contents`); }, []); const handleDragStart = useCallback( (ref: React.MutableRefObject) => (e: React.MouseEvent) => { e.preventDefault(); ref.current = true; document.body.style.cursor = "col-resize"; document.body.style.userSelect = "none"; }, [], ); const handleMouseMove = useCallback((e: React.MouseEvent) => { if (!containerRef.current) return; const rect = containerRef.current.getBoundingClientRect(); if (isDraggingLeft.current) { setLeftWidth(Math.max(180, Math.min(480, e.clientX - rect.left))); } if (isDraggingRight.current) { setRightWidth(Math.max(200, Math.min(500, rect.right - e.clientX))); } }, []); const handleMouseUp = useCallback(() => { isDraggingLeft.current = false; isDraggingRight.current = false; isDraggingTerminal.current = false; document.body.style.cursor = ""; document.body.style.userSelect = ""; }, []); return (
{/* ── Left: File Tree ── */} {showFileTree && ( <>
{/* Resize handle */}
)} {/* ── Center: Editor + Terminal ── */}
{/* Editor */}
{activeFile ? ( ) : (

Select a file from the workspace to view

)}
{/* Terminal resize handle */} {showTerminal && (
{ e.preventDefault(); isDraggingTerminal.current = true; document.body.style.cursor = "row-resize"; }} /> )} {/* Terminal */} {showTerminal && (
)} {/* IDE bottom bar */}
Sandbox Ready
{/* ── Right: Timeline ── */} {showTimeline && ( <> {/* Resize handle */}
Agent Timeline
)}
); }