theia Component Reuse Strategy
Date: 2025-10-08 Status: ✅ STRATEGIC PIVOT - LEVERAGE THEIA AI SYSTEM
🎯 Key Insight
STOP building custom components. theia already has everything we need.
Eclipse theia 1.65.0 includes a complete AI system with:
- AI chat interface
- llm integrations (OpenAI, Ollama, MCP)
- Agent system
- Code completion
- terminal
- Monaco editor
- File explorer
- Multi-session support
We should wrap and reuse these components, not rebuild them.
📦 theia AI Packages (Already Installed)
| Package | Purpose | Components |
|---|---|---|
| @theia/ai-core | Core AI framework | Agent system, tool calling, prompts |
| @theia/ai-chat | Chat service | ChatService, ChatSession, agents |
| @theia/ai-chat-ui | Chat UI widgets | ChatViewWidget, ChatInputWidget, ChatTreeWidget |
| @theia/ai-openai | OpenAI integration | GPT-3.5/4 support |
| @theia/ai-ollama | Ollama integration | Local llm support |
| @theia/ai-mcp | MCP protocol | Tool/resource access |
| @theia/ai-code-completion | Code autocomplete | IntelliSense AI |
| @theia/ai-editor | editor AI features | Inline chat, code actions |
| @theia/ai-history | Conversation history | Session persistence |
| @theia/ai-ide | IDE integration | workspace AI tools |
🔄 What We Should Reuse vs Build
✅ Reuse from theia (Don't Rebuild)
| Component | theia Package | Why Reuse |
|---|---|---|
| AI Chat Interface | @theia/ai-chat-ui | Complete chat UI with history, agents, tools |
| terminal | @theia/terminal | Full xterm.js integration, multi-terminal support |
| Monaco editor | @theia/monaco | VS Code editor with IntelliSense |
| File Explorer | @theia/navigator | Tree view with drag-drop, context menu |
| llm Service | @theia/ai-core | Agent system, tool calling, prompts |
| Session Management | @theia/ai-history | Conversation persistence |
| Code Completion | @theia/ai-code-completion | AI-powered autocomplete |
🔨 Build Custom (V5-Specific)
| Component | Purpose | Why Custom |
|---|---|---|
| Header/Footer | Branding, navigation | V5 wrapper UI |
| Mobile-First Wrapper | Touch-friendly layout | theia is desktop-focused |
| Multi-Tab Modality | AI Studio / workspace / theia IDE | V5 architecture |
| Session Routing | URL-based session switching | V5 feature |
| Touch-Friendly Cards | Mobile navigation | theia uses desktop patterns |
🏗️ Architecture: theia Widgets in React
The Challenge
theia uses:
- Inversify dependency injection
- Widget base classes
- ContainerModule for bindings
React uses:
- Props/hooks for state
- Components as functions
- Context for DI
The Solution: React-theia Bridge
Create wrapper components that:
- Instantiate theia widgets via DI container
- Mount widgets into React DOM refs
- Handle lifecycle (mount/unmount)
- Bridge events between theia and React
Example Pattern:
// src/components/theia/theia-chat-widget.tsx
import React, { useRef, useEffect } from 'react'
import { Container } from '@theia/core/shared/inversify'
import { ChatViewWidget } from '@theia/ai-chat-ui/lib/browser/chat-view-widget'
import { Box } from '@chakra-ui/react'
export const theiaChatWidget: React.FC = () => {
const containerRef = useRef<HTMLDivElement>(null)
const widgetRef = useRef<ChatViewWidget | null>(null)
useEffect(() => {
if (!containerRef.current) return
// Get theia DI container (from window or create)
const container = gettheiaContainer()
// Resolve widget from container
const widget = container.get(ChatViewWidget)
// Attach widget to DOM
widget.node.style.height = '100%'
containerRef.current.appendChild(widget.node)
widgetRef.current = widget
return () => {
// Cleanup on unmount
widget.dispose()
}
}, [])
return <Box ref={containerRef} h="100%" w="100%" />
}
🎨 Integration Patterns
Pattern 1: Embed theia Widget in React Page
Use Case: AI Studio tab wants to use theia's chat interface
// src/components/ai-studio/ai-studio-tab.tsx
import { theiaChatWidget } from '../theia/theiaChatWidget'
export const ai-studioTab = () => {
return (
<Split>
<Panel>
<theiaChatWidget /> {/* theia AI chat */}
</Panel>
<Panel>
<CodePreview /> {/* Custom React component */}
</Panel>
</Split>
)
}
Pattern 2: Full theia IDE in Iframe
Use Case: theia IDE tab needs full theia experience
// src/components/layout.tsx
<theiaEmbed
theiaUrl="http://localhost:3000"
sessionId={sessionId}
/>
Pattern 3: Hybrid - React Wrapper + theia Components
Use Case: workspace tab with custom layout + theia widgets
// src/components/workspace/workspace-tab.tsx
export const workspaceTab = () => {
return (
<Flex>
<TouchFriendlyCard> {/* Custom mobile UI */}
<theiafile-explorer /> {/* theia widget */}
</TouchFriendlyCard>
<theiaMonacoeditor /> {/* theia widget */}
<theiaterminal /> {/* theia widget */}
</Flex>
)
}
🔌 How to Access theia Widgets from React
Option 1: theia Frontend Module
Create a theia extension that exports widgets for React:
// src/browser/theia-react-bridge/theia-react-bridge-module.ts
import { ContainerModule } from '@theia/core/shared/inversify'
import { ChatViewWidget } from '@theia/ai-chat-ui/lib/browser/chat-view-widget'
export default new ContainerModule(bind => {
bind(ChatViewWidget).toSelf().inSingletonScope()
// Export to window for React access
bind(Symbol.for('react-bridge')).toDynamicValue(ctx => ({
getChatWidget: () => ctx.container.get(ChatViewWidget),
getterminal: () => ctx.container.get(terminalWidget),
getMonaco: () => ctx.container.get(Monacoeditor),
}))
})
Option 2: Direct Container Access
// src/services/theia-container-service.ts
import { Container } from '@theia/core/shared/inversify'
class theiaContainerService {
private container: Container | null = null
setContainer(container: Container) {
this.container = container
}
getWidget<T>(identifier: symbol | string): T {
if (!this.container) throw new Error('theia container not initialized')
return this.container.get<T>(identifier)
}
}
export const theiaContainerService = new theiaContainerService()
🚀 Immediate Actions
1. Delete Custom Components (We Don't Need These)
❌ Delete:
src/components/workspace/terminal.tsx- Use@theia/terminalsrc/components/workspace/Monacoeditor.tsx- Use@theia/monacosrc/components/workspace/file-explorer.tsx- Use@theia/navigatorsrc/services/llm-service.ts- Use@theia/ai-coreChatService
2. Create theia Widget Wrappers
✅ Create:
src/components/theia/theia-chat-widget.tsx- Wraps ChatViewWidgetsrc/components/theia/theia-terminal-widget.tsx- Wraps terminalWidgetsrc/components/theia/theia-monaco-widget.tsx- Wraps Monacoeditorsrc/components/theia/theia-file-explorer-widget.tsx- Wraps FileTreeWidget
3. Update AI Studio Tab
Replace custom chat with theia's ChatViewWidget:
// src/components/ai-studio/ai-studio-tab.tsx
- import { ChatInterface } from './ChatInterface' // Custom
+ import { theiaChatWidget } from '../theia/theiaChatWidget' // theia
export const ai-studioTab = () => (
<Split>
<Panel>
- <ChatInterface models={models} onSend={handleSend} />
+ <theiaChatWidget />
</Panel>
<Panel>
<CodePreview />
</Panel>
</Split>
)
4. Update workspace Tab
Replace custom components with theia widgets:
// src/components/workspace/workspace-tab.tsx
- import { file-explorer } from './file-explorer'
- import { Monacoeditor } from './Monacoeditor'
- import { terminal } from './terminal'
+ import { theiafile-explorerWidget } from '../theia/theiafile-explorerWidget'
+ import { theiaMonacoWidget } from '../theia/theiaMonacoWidget'
+ import { theiaterminalWidget } from '../theia/theiaterminalWidget'
🎯 Benefits of This Approach
1. Massive Time Savings
- ❌ Before: 2-3 weeks building custom chat, terminal, editor
- ✅ After: 2-3 days wrapping theia widgets
2. Production-Ready Features
theia widgets include:
- Multi-terminal support
- terminal tabs, splits, search
- Monaco IntelliSense, debugging
- AI code completion
- Chat history, agent switching
- MCP tool integration
- Session persistence
3. Consistent UX
Users already know theia's UI patterns. Don't reinvent.
4. Automatic Updates
When theia adds new AI features, we get them for free.
5. Proven at Scale
theia powers Gitpod, Google Cloud Shell, Arduino IDE. Battle-tested.
📋 Migration Checklist
Phase 1: Setup theia Widget Access (1 day)
- Create
src/services/theia-container-service.ts - Create React-theia bridge utility
- Test widget instantiation from React
Phase 2: Create Widget Wrappers (2 days)
-
theia-chat-widget.tsx- AI chat interface -
theia-terminal-widget.tsx- terminal -
theia-monaco-widget.tsx- Code editor -
theia-file-explorer-widget.tsx- File tree
Phase 3: Integrate into V5 UI (2 days)
- Update AI Studio tab to use theiaChatWidget
- Update workspace tab to use theia components
- Add mobile-first wrappers (TouchFriendlyCard)
- Test on 320px viewport
Phase 4: Connect to LM Studio (1 day)
- Configure
@theia/ai-openaito point to LM Studio API - Test chat with local llms
- Verify MCP tool integration
Total: 6 days instead of 3+ weeks
🔗 Key theia Packages to Study
Documentation
Source Code to Read
# AI Chat UI
node_modules/@theia/ai-chat-ui/lib/browser/chat-view-widget.d.ts
node_modules/@theia/ai-chat-ui/lib/browser/chat-input-widget.d.ts
# AI Core Services
node_modules/@theia/ai-core/lib/browser/ai-core-frontend-application-contribution.d.ts
node_modules/@theia/ai-chat/lib/browser/frontend-chat-service.d.ts
# terminal
node_modules/@theia/terminal/lib/browser/terminal-widget.d.ts
# Monaco
node_modules/@theia/monaco/lib/browser/monaco-editor.d.ts
# File Explorer
node_modules/@theia/navigator/lib/browser/navigator-widget.d.ts
💡 Example: Connecting theia AI to LM Studio
theia's AI system already supports OpenAI-compatible APIs. LM Studio IS OpenAI-compatible.
// Configure theia AI to use LM Studio
// In theia preferences or extension config:
{
"ai.openai.api.baseUrl": "http://localhost:1234/v1",
"ai.openai.api.key": "not-needed", // LM Studio doesn't need key
"ai.openai.models": [
"meta-llama-3.3-70b-instruct",
"qwen/qwq-32b",
"deepseek-coder-v2"
]
}
That's it. theia's ChatViewWidget will now use LM Studio models.
🎨 Mobile-First Wrapper Pattern
theia widgets are desktop-focused. Wrap them in TouchFriendlyCard:
// Mobile-first wrapper for theia chat
export const MobiletheiaChatWidget = () => {
const [isOpen, setIsOpen] = useState(true)
return (
<TouchFriendlyCard
title="AI Assistant"
icon={FiMessageSquare}
isOpen={isOpen}
onToggle={() => setIsOpen(!isOpen)}
>
<Box h="400px"> {/* Fixed height for mobile */}
<theiaChatWidget />
</Box>
</TouchFriendlyCard>
)
}
🚀 Next Steps
- Stop building custom components immediately
- Study theia widget APIs (read .d.ts files)
- Create React-theia bridge (theiaContainerService)
- Wrap ChatViewWidget (highest value first)
- Test in AI Studio tab
- Repeat for terminal, Monaco, file-explorer
📊 Impact Assessment
Before (Custom Build)
- Time: 3+ weeks
- Code: ~5,000 lines custom React
- Maintenance: High (we own all bugs)
- Features: Basic (no history, no tools, no MCP)
- Quality: Unproven
After (theia Reuse)
- Time: 6 days
- Code: ~500 lines (wrappers only)
- Maintenance: Low (theia team maintains)
- Features: Full (history, agents, tools, MCP, code completion)
- Quality: Production-ready (used by Gitpod, Google)
ROI: 10x time savings, 10x feature richness
✅ Summary
Strategic Decision: Leverage theia's AI system instead of rebuilding.
Key Principle: Wrap, don't rewrite.
Implementation: Create thin React wrappers around theia widgets.
Timeline: 6 days instead of 3+ weeks.
Result: Production-ready AI IDE with minimal custom code.
Document Version: 1.0.0 Last Updated: 2025-10-08 Status: ✅ APPROVED STRATEGY