Refactor ToolCallSidePanel to KortixComputer with Actions, Files, and…#14
Refactor ToolCallSidePanel to KortixComputer with Actions, Files, and…#14Logrui wants to merge 22 commits intoadvanced-workflowsfrom
Conversation
… Browser tabs. - Replaced ToolCallSidePanel with KortixComputer implementation from upstream/PRODUCTION. - Added support for 'Actions', 'Files', and 'Browser' tabs. - Integrated `FileBrowserView` and `FileViewerView` for full file system access. - Implemented `BrowserTakeover` component for full-screen VNC browser control. - Updated `BrowserToolView` header to support 'Use Browser' takeover action. - Added `kortix-computer-store` for managing tab and file selection state. - Updated dependencies for file rendering and markdown support.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR refactors the ToolCallSidePanel component into a more comprehensive KortixComputer interface with dedicated tabs for Actions, Files, and Browser views. The changes include:
- Complete redesign of the side panel with tab-based navigation (Actions/Files/Browser)
- New state management store for coordinating tab and file selection state
- Full file system browser with version history and restore capabilities
- Integrated file viewer with editing support for multiple formats
- Browser takeover mode for full-screen VNC control
- Enhanced file renderers with improved format detection and rendering
- Unified markdown rendering system with consistent styling
Key Changes
- Replaced ToolCallSidePanel with KortixComputer implementation featuring tabbed interface
- Added
kortix-computer-storefor centralized state management across views - Implemented comprehensive file browsing with FileBrowserView and FileViewerView
- Added BrowserTakeover component for immersive browser control
- Enhanced XLSX renderer with proper format detection to avoid vulnerable libraries where possible
- Created unified markdown rendering component with consistent styling
- Refactored billing hooks to use consolidated
useAccountStatepattern
Reviewed changes
Copilot reviewed 36 out of 37 changed files in this pull request and generated 19 comments.
Show a summary per file
| File | Description |
|---|---|
kortix-computer-store.ts |
New Zustand store managing view state, file navigation, and unsaved content |
url-autolink.ts |
Utility for auto-linking plain URLs in markdown with comprehensive TLD support |
site-config.ts |
Centralized site configuration with pricing and footer links |
use-download-restriction.ts |
New hook for restricting downloads on free tier with upgrade prompts |
use-thread-billing.ts |
Refactored to use unified useAccountState instead of separate billing queries |
FileDownloadButton.tsx |
Reusable download/export button with format options for markdown files |
BrowserToolView.tsx |
Updated with takeover button and Next.js Image component |
tool-call-side-panel.tsx |
Major refactor to KortixComputer with Actions/Files/Browser tabs |
FileBrowserView.tsx |
New file browser with version history and workspace navigation |
FileViewerView.tsx |
Comprehensive file viewer with editing, version control, and restore |
BrowserTakeover.tsx |
Full-screen browser control with floating controls |
unified-markdown.tsx |
New unified markdown renderer with consistent styling and auto-linking |
xlsx-renderer.tsx |
Enhanced with format detection using secure libraries for XLSX |
pptx-renderer.tsx |
New PPTX renderer using react-doc-viewer |
pdf-renderer.tsx |
Improved with responsive scaling and keyboard navigation |
Files not reviewed (1)
- frontend/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import { processUnicodeContent, getFileTypeFromExtension, getLanguageFromExtension } from './utils'; | ||
|
|
There was a problem hiding this comment.
Unused imports getFileTypeFromExtension, getLanguageFromExtension, processUnicodeContent.
| import { processUnicodeContent, getFileTypeFromExtension, getLanguageFromExtension } from './utils'; |
| import { | ||
| Bold, | ||
| Italic, | ||
| Underline as UnderlineIcon, | ||
| Strikethrough, | ||
| List, | ||
| ListOrdered, | ||
| Quote, | ||
| Code, | ||
| Heading1, | ||
| Heading2, | ||
| Heading3, | ||
| Link as LinkIcon, | ||
| Image as ImageIcon, | ||
| Table as TableIcon, | ||
| Undo, | ||
| Redo, | ||
| ChevronDown, | ||
| Minus, | ||
| ListTodo, | ||
| Check, | ||
| Loader2, | ||
| AlertCircle, | ||
| Save, | ||
| Type, | ||
| Download, | ||
| FileText, | ||
| FileType, | ||
| FileCode, | ||
| RotateCcw, | ||
| Upload, | ||
| Link2, | ||
| Plus, | ||
| Trash2, | ||
| ArrowUp, | ||
| ArrowDown, | ||
| ArrowLeft, | ||
| ArrowRight, | ||
| Columns, | ||
| Rows, | ||
| } from 'lucide-react'; |
There was a problem hiding this comment.
Unused import Plus.
| const [pageNumber, setPageNumber] = useState<number>(1); | ||
| const [scale, setScale] = useState<number>(1.0); | ||
| const [containerWidth, setContainerWidth] = useState<number>(0); | ||
| const [isLoading, setIsLoading] = useState(true); |
There was a problem hiding this comment.
Unused variable isLoading.
| const [isLoading, setIsLoading] = useState(true); |
| X, | ||
| ChevronLeft, | ||
| ChevronRight, | ||
| Maximize2, |
There was a problem hiding this comment.
Unused imports Maximize2, X.
| X, | |
| ChevronLeft, | |
| ChevronRight, | |
| Maximize2, | |
| ChevronLeft, | |
| ChevronRight, |
| import { | ||
| File, | ||
| Folder, | ||
| Upload, | ||
| Download, | ||
| ChevronRight, | ||
| Home, | ||
| Loader, | ||
| FileText, | ||
| Presentation, | ||
| ChevronDown, | ||
| AlertTriangle, | ||
| } from 'lucide-react'; |
There was a problem hiding this comment.
Unused import ChevronRight.
| }, [toolCalls]); | ||
|
|
||
| useEffect(() => { | ||
| const hadSnapshots = toolCallSnapshots.length > 0; |
There was a problem hiding this comment.
Unused variable hadSnapshots.
| const hadSnapshots = toolCallSnapshots.length > 0; |
| } | ||
| }, [currentIndex, toolCallSnapshots.length, isInitialized, navigationMode]); | ||
|
|
||
| const { safeInternalIndex, currentSnapshot, currentToolCall, totalCalls, latestIndex, completedToolCalls, totalCompletedCalls } = useMemo(() => { |
There was a problem hiding this comment.
Unused variable currentSnapshot.
| const { safeInternalIndex, currentSnapshot, currentToolCall, totalCalls, latestIndex, completedToolCalls, totalCompletedCalls } = useMemo(() => { | |
| const { safeInternalIndex, currentToolCall, totalCalls, latestIndex, completedToolCalls, totalCompletedCalls } = useMemo(() => { |
| const FLOATING_LAYOUT_ID = 'tool-panel-float'; | ||
| const CONTENT_LAYOUT_ID = 'tool-panel-content'; | ||
| const FLOATING_LAYOUT_ID = 'kortix-computer-float'; | ||
| const CONTENT_LAYOUT_ID = 'kortix-computer-content'; |
There was a problem hiding this comment.
Unused variable CONTENT_LAYOUT_ID.
| const CONTENT_LAYOUT_ID = 'kortix-computer-content'; |
| {isOpen && ( | ||
| <motion.div | ||
| key="sidepanel" | ||
| layoutId={FLOATING_LAYOUT_ID} | ||
| initial={disableInitialAnimation ? { opacity: 1 } : { opacity: 0 }} | ||
| animate={{ opacity: 1 }} | ||
| exit={{ opacity: 0 }} | ||
| transition={{ | ||
| opacity: { duration: disableInitialAnimation ? 0 : 0.15 }, | ||
| layout: { | ||
| type: "spring", | ||
| stiffness: 400, | ||
| damping: 35 | ||
| } | ||
| }} | ||
| className="m-4 h-[calc(100%-2rem)] w-[calc(100%-2rem)] max-w-[calc(100%-2rem)] max-h-[calc(100%-2rem)] border rounded-3xl flex flex-col z-30 overflow-hidden" | ||
| style={{ | ||
| contain: 'strict', | ||
| }} | ||
| > | ||
| <div className="flex-1 flex flex-col overflow-hidden bg-card max-w-full max-h-full min-w-0 min-h-0" style={{ contain: 'strict' }}> | ||
| {renderContent()} | ||
| </div> | ||
| {activeView === 'tools' && (displayTotalCalls > 1 || (isCurrentToolStreaming && totalCompletedCalls > 0)) && ( | ||
| <NavigationControls | ||
| displayIndex={displayIndex} | ||
| displayTotalCalls={displayTotalCalls} | ||
| safeInternalIndex={safeInternalIndex} | ||
| latestIndex={latestIndex} | ||
| isLiveMode={isLiveMode} | ||
| agentStatus={agentStatus} | ||
| onPrevious={navigateToPrevious} | ||
| onNext={navigateToNext} | ||
| onSliderChange={handleSliderChange} | ||
| onJumpToLive={jumpToLive} | ||
| onJumpToLatest={jumpToLatest} | ||
| isMobile={false} | ||
| /> | ||
| )} | ||
| </motion.div> | ||
| )} |
There was a problem hiding this comment.
This use of variable 'isOpen' always evaluates to true.
| {isOpen && ( | |
| <motion.div | |
| key="sidepanel" | |
| layoutId={FLOATING_LAYOUT_ID} | |
| initial={disableInitialAnimation ? { opacity: 1 } : { opacity: 0 }} | |
| animate={{ opacity: 1 }} | |
| exit={{ opacity: 0 }} | |
| transition={{ | |
| opacity: { duration: disableInitialAnimation ? 0 : 0.15 }, | |
| layout: { | |
| type: "spring", | |
| stiffness: 400, | |
| damping: 35 | |
| } | |
| }} | |
| className="m-4 h-[calc(100%-2rem)] w-[calc(100%-2rem)] max-w-[calc(100%-2rem)] max-h-[calc(100%-2rem)] border rounded-3xl flex flex-col z-30 overflow-hidden" | |
| style={{ | |
| contain: 'strict', | |
| }} | |
| > | |
| <div className="flex-1 flex flex-col overflow-hidden bg-card max-w-full max-h-full min-w-0 min-h-0" style={{ contain: 'strict' }}> | |
| {renderContent()} | |
| </div> | |
| {activeView === 'tools' && (displayTotalCalls > 1 || (isCurrentToolStreaming && totalCompletedCalls > 0)) && ( | |
| <NavigationControls | |
| displayIndex={displayIndex} | |
| displayTotalCalls={displayTotalCalls} | |
| safeInternalIndex={safeInternalIndex} | |
| latestIndex={latestIndex} | |
| isLiveMode={isLiveMode} | |
| agentStatus={agentStatus} | |
| onPrevious={navigateToPrevious} | |
| onNext={navigateToNext} | |
| onSliderChange={handleSliderChange} | |
| onJumpToLive={jumpToLive} | |
| onJumpToLatest={jumpToLatest} | |
| isMobile={false} | |
| /> | |
| )} | |
| </motion.div> | |
| )} | |
| <motion.div | |
| key="sidepanel" | |
| layoutId={FLOATING_LAYOUT_ID} | |
| initial={disableInitialAnimation ? { opacity: 1 } : { opacity: 0 }} | |
| animate={{ opacity: 1 }} | |
| exit={{ opacity: 0 }} | |
| transition={{ | |
| opacity: { duration: disableInitialAnimation ? 0 : 0.15 }, | |
| layout: { | |
| type: "spring", | |
| stiffness: 400, | |
| damping: 35 | |
| } | |
| }} | |
| className="m-4 h-[calc(100%-2rem)] w-[calc(100%-2rem)] max-w-[calc(100%-2rem)] max-h-[calc(100%-2rem)] border rounded-3xl flex flex-col z-30 overflow-hidden" | |
| style={{ | |
| contain: 'strict', | |
| }} | |
| > | |
| <div className="flex-1 flex flex-col overflow-hidden bg-card max-w-full max-h-full min-w-0 min-h-0" style={{ contain: 'strict' }}> | |
| {renderContent()} | |
| </div> | |
| {activeView === 'tools' && (displayTotalCalls > 1 || (isCurrentToolStreaming && totalCompletedCalls > 0)) && ( | |
| <NavigationControls | |
| displayIndex={displayIndex} | |
| displayTotalCalls={displayTotalCalls} | |
| safeInternalIndex={safeInternalIndex} | |
| latestIndex={latestIndex} | |
| isLiveMode={isLiveMode} | |
| agentStatus={agentStatus} | |
| onPrevious={navigateToPrevious} | |
| onNext={navigateToNext} | |
| onSliderChange={handleSliderChange} | |
| onJumpToLive={jumpToLive} | |
| onJumpToLatest={jumpToLatest} | |
| isMobile={false} | |
| /> | |
| )} | |
| </motion.div> |
| if (!isOpen) { | ||
| return null; | ||
| } | ||
|
|
There was a problem hiding this comment.
This negation always evaluates to false.
| if (!isOpen) { | |
| return null; | |
| } |
…hread with upstream/PRODUCTION
…ith upstream/PRODUCTION
Added two detailed documents analyzing the upstream architectural improvements: 1. UPSTREAM_ARCHITECTURAL_CHANGES_SUMMARY.md - Detailed explanation of 5 major architectural changes - System prompt reduction (<200 lines) - Dynamic tool loading with caching - Parallel MCP initialization with Redis - Performance improvements (3-5x faster startup) - Migration strategy in 5 phases - Breaking changes and risk assessment 2. UPSTREAM_FILES_TO_UPDATE_CHECKLIST.md - File-by-file update checklist - Organized by priority (Critical → Low) - Specific code changes for each file - Verification steps - Common issues and solutions Key Findings: - 135 backend files changed in upstream - Major refactor: backend/agent/ → backend/core/ - Tool schemas moved from system prompt to function calling API - Pre-computed schema caching for instant tool registration - Parallel operations for faster agent startup - Expected performance: 3-5x faster (1-2s → 200-400ms) These documents provide complete implementation guidance for merging upstream changes into our self-hosted fork.
ce40200 to
b471cb2
Compare
…defined sandbox_tuple variable
…e2EfMbfDVsksp7gy docs: comprehensive analysis of upstream/main architectural changes
… Browser tabs.
FileBrowserViewandFileViewerViewfor full file system access.BrowserTakeovercomponent for full-screen VNC browser control.BrowserToolViewheader to support 'Use Browser' takeover action.kortix-computer-storefor managing tab and file selection state.