Skip to main content

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)

PackagePurposeComponents
@theia/ai-coreCore AI frameworkAgent system, tool calling, prompts
@theia/ai-chatChat serviceChatService, ChatSession, agents
@theia/ai-chat-uiChat UI widgetsChatViewWidget, ChatInputWidget, ChatTreeWidget
@theia/ai-openaiOpenAI integrationGPT-3.5/4 support
@theia/ai-ollamaOllama integrationLocal llm support
@theia/ai-mcpMCP protocolTool/resource access
@theia/ai-code-completionCode autocompleteIntelliSense AI
@theia/ai-editoreditor AI featuresInline chat, code actions
@theia/ai-historyConversation historySession persistence
@theia/ai-ideIDE integrationworkspace AI tools

🔄 What We Should Reuse vs Build

✅ Reuse from theia (Don't Rebuild)

Componenttheia PackageWhy Reuse
AI Chat Interface@theia/ai-chat-uiComplete chat UI with history, agents, tools
terminal@theia/terminalFull xterm.js integration, multi-terminal support
Monaco editor@theia/monacoVS Code editor with IntelliSense
File Explorer@theia/navigatorTree view with drag-drop, context menu
llm Service@theia/ai-coreAgent system, tool calling, prompts
Session Management@theia/ai-historyConversation persistence
Code Completion@theia/ai-code-completionAI-powered autocomplete

🔨 Build Custom (V5-Specific)

ComponentPurposeWhy Custom
Header/FooterBranding, navigationV5 wrapper UI
Mobile-First WrapperTouch-friendly layouttheia is desktop-focused
Multi-Tab ModalityAI Studio / workspace / theia IDEV5 architecture
Session RoutingURL-based session switchingV5 feature
Touch-Friendly CardsMobile navigationtheia 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:

  1. Instantiate theia widgets via DI container
  2. Mount widgets into React DOM refs
  3. Handle lifecycle (mount/unmount)
  4. 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/terminal
  • src/components/workspace/Monacoeditor.tsx - Use @theia/monaco
  • src/components/workspace/file-explorer.tsx - Use @theia/navigator
  • src/services/llm-service.ts - Use @theia/ai-core ChatService

2. Create theia Widget Wrappers

✅ Create:

  • src/components/theia/theia-chat-widget.tsx - Wraps ChatViewWidget
  • src/components/theia/theia-terminal-widget.tsx - Wraps terminalWidget
  • src/components/theia/theia-monaco-widget.tsx - Wraps Monacoeditor
  • src/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-openai to 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

  1. Stop building custom components immediately
  2. Study theia widget APIs (read .d.ts files)
  3. Create React-theia bridge (theiaContainerService)
  4. Wrap ChatViewWidget (highest value first)
  5. Test in AI Studio tab
  6. 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