gbclient/app/sources/page.tsx
Rodrigo Rodriguez (Pragmatismo) 21a8236516
Some checks failed
GBCI / build (push) Failing after 10m8s
Add global styles using Tailwind CSS with custom color variables for light and dark themes
2025-06-28 23:58:53 -03:00

1151 lines
53 KiB
TypeScript

"use client";
import React, { useState } from 'react';
import {
Search, FileText, Newspaper, Presentation, Table,
Lightbulb, TrendingUp, Code, Briefcase,
Shield, Heart, Gamepad2, Palette, Book, Calculator,
Globe, Clock, Star, ArrowRight, ExternalLink,
Copy, Download, Play, Server, Cpu, Cloud, Sun, ShoppingCart, UserPlus
} from 'lucide-react';
// Mock data for prompts
const promptCategories = [
{ name: "AI Development", count: 4, color: "--primary", icon: Code },
{ name: "Security", count: 8, color: "--destructive", icon: Shield },
{ name: "Programming", count: 6, color: "--secondary", icon: Code },
{ name: "Career & Employment", count: 3, color: "--accent", icon: Briefcase },
{ name: "Health & Therapy", count: 4, color: "--chart-1", icon: Heart },
{ name: "Games & Entertainment", count: 5, color: "--chart-2", icon: Gamepad2 },
{ name: "Art & Design", count: 4, color: "--chart-3", icon: Palette },
{ name: "Education", count: 6, color: "--chart-4", icon: Book },
{ name: "Business & Finance", count: 4, color: "--chart-5", icon: Calculator },
{ name: "Technology", count: 3, color: "--primary", icon: Globe }
];
const featuredPrompts = [
{ name: "Job Scout Pro", category: "Career & Employment", description: "AI-powered job hunting assistant", rating: 4.8 },
{ name: "Cyber Security Sentinel", category: "Security", description: "Advanced security analysis tool", rating: 4.9 },
{ name: "Code Copilot Pro", category: "Programming", description: "Intelligent coding companion", rating: 4.7 },
{ name: "Digital Synthia Companion", category: "AI & Chatbots", description: "Advanced AI conversation partner", rating: 4.6 }
];
// Mock data for templates
const templateCategories = [
{ name: "Documents", icon: FileText, count: 12, color: "--primary" },
{ name: "Presentations", icon: Presentation, count: 8, color: "--destructive" },
{ name: "Spreadsheets", icon: Table, count: 6, color: "--secondary" }
];
// Mock data for news
const newsCategories = [
{ name: "Technology", count: 45, color: "--primary" },
{ name: "AI & ML", count: 38, color: "--chart-2" },
{ name: "Business", count: 52, color: "--secondary" },
{ name: "Science", count: 29, color: "--destructive" },
{ name: "Startups", count: 34, color: "--accent" }
];
const mcpServers = [
{
name: "ModelScope MCP Playground",
description: "Exploring the Free Combination and Interaction of Open Source Models and MCP Server",
type: "Hosted",
category: "developer-tools",
usage: "1203",
icon: Server
},
{
name: "ModelScope MCP Tutorial",
description: "Learn about MCP, observe and discuss best practices",
type: "Hosted",
category: "knowledge-and-memory",
usage: "264",
icon: Book
},
{
name: "TONGYI Lingma Programming Agent",
description: "Supports the use of MCP tools",
type: "Hosted",
category: "developer-tools",
usage: "1203",
icon: Code
},
{
name: "Cherry Studio Integration",
description: "Integrate ModelScope-hosted MCP server in Cherry Studio",
type: "Hosted",
category: "developer-tools",
usage: "1203",
icon: Cpu
},
{
name: "fetch",
description: "Retrieve and process content from web pages, converting HTML to markdown",
type: "Hosted",
category: "search",
usage: "609",
icon: Cloud
},
{
name: "amap-maps",
description: "Location-based services using Amap Maps MCP server",
type: "Hosted",
category: "location-services",
usage: "71",
icon: Globe
},
{
name: "bing-cn-mcp-server",
description: "Bing search Chinese version",
type: "Hosted",
category: "search",
usage: "609",
icon: Search
},
{
name: "AllVoiceLab",
description: "Text-to-speech and video translation APIs",
type: "Local",
category: "entertainment-and-media",
usage: "106",
icon: Heart
},
{
name: "12306-mcp",
description: "Search for 12306 train tickets",
type: "Hosted",
category: "other",
usage: "294",
icon: Clock
},
{
name: "Jina-AI-MCP-Tools",
description: "Integrates with Jina AI Search Foundation APIs",
type: "Hosted",
category: "search",
usage: "609",
icon: TrendingUp
}
];
// LLM Tools data
const llmTools = [
{
name: "Enroll",
description: "User registration and account creation tool",
category: "User Management",
icon: UserPlus,
color: "--primary"
},
{
name: "How is the weather",
description: "Real-time weather information lookup",
category: "Location Services",
icon: Sun,
color: "--accent"
},
{
name: "Price of Product",
description: "Product price lookup and comparison",
category: "E-commerce",
icon: ShoppingCart,
color: "--secondary"
},
{
name: "Document Analyzer",
description: "Extract and analyze document content",
category: "Knowledge",
icon: FileText,
color: "--chart-2"
},
{
name: "Code Generator",
description: "Generate code snippets from descriptions",
category: "Development",
icon: Code,
color: "--primary"
},
{
name: "Data Visualizer",
description: "Create charts and visualizations from data",
category: "Analytics",
icon: TrendingUp,
color: "--chart-1"
}
];
export default function LabComponent() {
const [activeTab, setActiveTab] = useState('prompts');
const [selectedCategory, setSelectedCategory] = useState(null);
const renderPrompts = () => (
<div className="h-full flex flex-col" style={{ backgroundColor: 'var(--background)', color: 'var(--foreground)' }}>
{/* Header */}
<div className="p-4 border-b" style={{ borderColor: 'var(--border)' }}>
<div className="flex items-center justify-between mb-4">
<h2 className="text-2xl font-bold flex items-center gap-2">
<Lightbulb className="h-6 w-6" style={{ color: 'var(--chart-4)' }} />
Prompt Library
</h2>
<div className="flex gap-2">
<button className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors" style={{ backgroundColor: 'var(--primary)', color: 'var(--primary-foreground)' }}>
Create Custom
</button>
</div>
</div>
{/* Search */}
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4" style={{ color: 'var(--muted-foreground)' }} />
<input
type="text"
placeholder="Search 1000+ prompts..."
className="w-full pl-10 pr-4 py-2 border rounded-lg focus:ring-2 focus:border-transparent"
style={{
borderColor: 'var(--border)',
backgroundColor: 'var(--background)',
color: 'var(--foreground)',
}}
/>
</div>
</div>
<div className="flex-1 flex">
{/* Categories Sidebar */}
<div className="w-80 border-r p-4" style={{ borderColor: 'var(--border)', backgroundColor: 'var(--background)' }}>
<h3 className="font-semibold mb-4" style={{ color: 'var(--muted-foreground)' }}>Categories</h3>
<div className="space-y-2">
{promptCategories.map((category, index) => {
const IconComponent = category.icon;
return (
<button
key={index}
onClick={() => setSelectedCategory(category.name)}
className={`w-full text-left p-3 rounded-lg transition-colors flex items-center justify-between hover:bg-card ${selectedCategory === category.name ? 'bg-card shadow-sm border-l-4' : ''
}`}
style={{
borderLeftColor: selectedCategory === category.name ? `var(${category.color})` : 'transparent',
backgroundColor: selectedCategory === category.name ? 'var(--card)' : '',
color: 'var(--card-foreground)'
}}
>
<div className="flex items-center gap-3">
<IconComponent className="h-4 w-4" style={{ color: `var(${category.color})` }} />
<span className="font-medium">{category.name}</span>
</div>
<span className="text-sm bg-gray-200 px-2 py-1 rounded-full" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>
{category.count}
</span>
</button>
);
})}
</div>
{/* Featured Section */}
<div className="mt-8">
<h3 className="font-semibold mb-4 flex items-center gap-2" style={{ color: 'var(--muted-foreground)' }}>
<Star className="h-4 w-4" style={{ color: 'var(--chart-4)' }} />
Featured Prompts
</h3>
<div className="space-y-3">
{featuredPrompts.map((prompt, index) => (
<div key={index} className="p-3 rounded-lg shadow-sm border" style={{ backgroundColor: 'var(--card)', color: 'var(--card-foreground)', borderColor: 'var(--border)' }}>
<h4 className="font-medium text-sm">{prompt.name}</h4>
<p className="text-xs mt-1" style={{ color: 'var(--muted-foreground)' }}>{prompt.description}</p>
<div className="flex items-center justify-between mt-2">
<span className="text-xs px-2 py-1 rounded" style={{ backgroundColor: 'var(--primary)', color: 'var(--primary-foreground)' }}>
{prompt.category}
</span>
<div className="flex items-center gap-1">
<Star className="h-3 w-3 fill-current" style={{ color: 'var(--chart-4)' }} />
<span className="text-xs" style={{ color: 'var(--muted-foreground)' }}>{prompt.rating}</span>
</div>
</div>
</div>
))}
</div>
</div>
</div>
{/* Content Area */}
<div className="flex-1 p-6" style={{ backgroundColor: 'var(--background)', color: 'var(--foreground)' }}>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{[...Array(8)].map((_, index) => (
<div key={index} className="border rounded-lg p-4 transition-shadow" style={{ backgroundColor: 'var(--card)', color: 'var(--card-foreground)', borderColor: 'var(--border)' }}>
<div className="flex items-start justify-between mb-3">
<h3 className="font-semibold text-lg">Advanced Code Review Assistant</h3>
<div className="flex gap-2">
<button className="p-1 hover:bg-gray-100 rounded">
<Copy className="h-4 w-4" style={{ color: 'var(--muted-foreground)' }} />
</button>
<button className="p-1 hover:bg-gray-100 rounded">
<Download className="h-4 w-4" style={{ color: 'var(--muted-foreground)' }} />
</button>
</div>
</div>
<p className="text-sm mb-3" style={{ color: 'var(--muted-foreground)' }}>
AI assistant specialized in code review, security analysis, and optimization suggestions.
</p>
<div className="flex items-center justify-between">
<span className="text-xs px-2 py-1 rounded" style={{ backgroundColor: 'var(--chart-2)', color: 'var(--chart-2-foreground)' }}>Programming</span>
<button className="flex items-center gap-1 text-sm font-medium" style={{ color: 'var(--primary)' }}>
<Play className="h-3 w-3" />
Use Prompt
</button>
</div>
</div>
))}
</div>
</div>
</div>
</div>
);
const renderTemplates = () => (
<div className="h-full flex flex-col" style={{ backgroundColor: 'var(--background)', color: 'var(--foreground)' }}>
{/* Header */}
<div className="p-4 border-b" style={{ borderColor: 'var(--border)' }}>
<div className="flex items-center justify-between mb-4">
<h2 className="text-2xl font-bold flex items-center gap-2">
<FileText className="h-6 w-6" style={{ color: 'var(--secondary)' }} />
Document Templates
</h2>
<button className="px-4 py-2 text-white rounded-lg hover:bg-green-700 transition-colors" style={{ backgroundColor: 'var(--secondary)', color: 'var(--secondary-foreground)' }}>
Upload Template
</button>
</div>
{/* Search */}
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4" style={{ color: 'var(--muted-foreground)' }} />
<input
type="text"
placeholder="Search templates..."
className="w-full pl-10 pr-4 py-2 border rounded-lg focus:ring-2 focus:border-transparent"
style={{
borderColor: 'var(--border)',
backgroundColor: 'var(--background)',
color: 'var(--foreground)',
}}
/>
</div>
</div>
<div className="flex-1 flex">
{/* Template Types */}
<div className="w-80 border-r p-4" style={{ borderColor: 'var(--border)', backgroundColor: 'var(--background)' }}>
<h3 className="font-semibold mb-4" style={{ color: 'var(--muted-foreground)' }}>Template Types</h3>
<div className="space-y-2">
{templateCategories.map((category, index) => {
const IconComponent = category.icon;
return (
<button
key={index}
className="w-full text-left p-3 rounded-lg transition-colors flex items-center justify-between hover:bg-card"
style={{ color: 'var(--card-foreground)' }}
>
<div className="flex items-center gap-3">
<IconComponent className="h-4 w-4" style={{ color: `var(${category.color})` }} />
<span className="font-medium">{category.name}</span>
</div>
<span className="text-sm bg-gray-200 px-2 py-1 rounded-full" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>
{category.count}
</span>
</button>
);
})}
</div>
{/* Quick Actions */}
<div className="mt-8">
<h3 className="font-semibold mb-4" style={{ color: 'var(--muted-foreground)' }}>Quick Start</h3>
<div className="space-y-2">
<button className="w-full p-3 text-left rounded-lg transition-colors border-l-4" style={{ backgroundColor: 'var(--primary)/10', borderColor: 'var(--primary)', color: 'var(--primary)' }}>
<div className="font-medium">Blank Document</div>
<div className="text-xs">Start with empty document</div>
</button>
<button className="w-full p-3 text-left rounded-lg transition-colors border-l-4" style={{ backgroundColor: 'var(--destructive)/10', borderColor: 'var(--destructive)', color: 'var(--destructive)' }}>
<div className="font-medium">Blank Presentation</div>
<div className="text-xs">Create new slideshow</div>
</button>
<button className="w-full p-3 text-left rounded-lg transition-colors border-l-4" style={{ backgroundColor: 'var(--secondary)/10', borderColor: 'var(--secondary)', color: 'var(--secondary)' }}>
<div className="font-medium">Blank Spreadsheet</div>
<div className="text-xs">New data table</div>
</button>
</div>
</div>
</div>
{/* Templates Grid */}
<div className="flex-1 p-6" style={{ backgroundColor: 'var(--background)', color: 'var(--foreground)' }}>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{[...Array(9)].map((_, index) => (
<div key={index} className="border rounded-lg overflow-hidden transition-shadow" style={{ backgroundColor: 'var(--card)', color: 'var(--card-foreground)', borderColor: 'var(--border)' }}>
{/* Template Preview */}
<div className="h-40 flex items-center justify-center" style={{ background: 'linear-gradient(to bottom right, var(--primary)/20, var(--secondary)/30)' }}>
<FileText className="h-12 w-12" style={{ color: 'var(--primary)' }} />
</div>
<div className="p-4">
<h3 className="font-semibold mb-2">Business Proposal Template</h3>
<p className="text-sm mb-3" style={{ color: 'var(--muted-foreground)' }}>
Professional template for business proposals and project pitches.
</p>
<div className="flex items-center justify-between">
<span className="text-xs px-2 py-1 rounded" style={{ backgroundColor: 'var(--primary)', color: 'var(--primary-foreground)' }}>Document</span>
<button className="flex items-center gap-1 text-sm font-medium" style={{ color: 'var(--primary)' }}>
Use Template
<ArrowRight className="h-3 w-3" />
</button>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</div>
);
const renderNews = () => (
<div className="h-full flex flex-col" style={{ backgroundColor: 'var(--background)', color: 'var(--foreground)' }}>
{/* Header */}
<div className="p-4 border-b" style={{ borderColor: 'var(--border)' }}>
<div className="flex items-center justify-between mb-4">
<h2 className="text-2xl font-bold flex items-center gap-2">
<Newspaper className="h-6 w-6" style={{ color: 'var(--primary)' }} />
News & Insights
</h2>
<div className="flex gap-2">
<button className="px-4 py-2 border rounded-lg transition-colors" style={{ borderColor: 'var(--border)', color: 'var(--foreground)' }}>
Customize Feed
</button>
<button className="px-4 py-2 text-white rounded-lg transition-colors" style={{ backgroundColor: 'var(--primary)', color: 'var(--primary-foreground)' }}>
Add Source
</button>
</div>
</div>
{/* Search & Filters */}
<div className="flex gap-4">
<div className="flex-1 relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4" style={{ color: 'var(--muted-foreground)' }} />
<input
type="text"
placeholder="Search news and articles..."
className="w-full pl-10 pr-4 py-2 border rounded-lg focus:ring-2 focus:border-transparent"
style={{
borderColor: 'var(--border)',
backgroundColor: 'var(--background)',
color: 'var(--foreground)',
}}
/>
</div>
<select className="px-4 py-2 border rounded-lg focus:ring-2 focus:border-transparent" style={{ borderColor: 'var(--border)', backgroundColor: 'var(--background)', color: 'var(--foreground)' }}>
<option>All Time</option>
<option>Today</option>
<option>This Week</option>
<option>This Month</option>
</select>
</div>
</div>
<div className="flex-1 flex">
{/* News Categories */}
<div className="w-80 border-r p-4" style={{ borderColor: 'var(--border)', backgroundColor: 'var(--background)' }}>
<h3 className="font-semibold mb-4" style={{ color: 'var(--muted-foreground)' }}>Categories</h3>
<div className="space-y-2">
{newsCategories.map((category, index) => (
<button
key={index}
className="w-full text-left p-3 rounded-lg transition-colors flex items-center justify-between hover:bg-card"
style={{ color: 'var(--card-foreground)' }}
>
<div className="flex items-center gap-3">
<div
className="w-3 h-3 rounded-full"
style={{ backgroundColor: `var(${category.color})` }}
></div>
<span className="font-medium">{category.name}</span>
</div>
<span className="text-sm bg-gray-200 px-2 py-1 rounded-full" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>
{category.count}
</span>
</button>
))}
</div>
{/* Trending Topics */}
<div className="mt-8">
<h3 className="font-semibold mb-4 flex items-center gap-2" style={{ color: 'var(--muted-foreground)' }}>
<TrendingUp className="h-4 w-4" style={{ color: 'var(--accent)' }} />
Trending
</h3>
<div className="space-y-2">
{['OpenAI GPT-5', 'Quantum Computing', 'Climate Tech', 'Space X'].map((topic, index) => (
<button key={index} className="w-full text-left p-2 hover:bg-card rounded-lg transition-colors" style={{ color: 'var(--card-foreground)' }}>
<span className="text-sm font-medium">#{topic}</span>
</button>
))}
</div>
</div>
</div>
{/* News Feed */}
<div className="flex-1 p-6" style={{ backgroundColor: 'var(--background)', color: 'var(--foreground)' }}>
<div className="space-y-4">
{[...Array(6)].map((_, index) => (
<article key={index} className="border rounded-lg p-4 transition-shadow" style={{ backgroundColor: 'var(--card)', color: 'var(--card-foreground)', borderColor: 'var(--border)' }}>
<div className="flex items-start gap-4">
<div className="w-24 h-24 rounded-lg flex-shrink-0 flex items-center justify-center" style={{ background: 'linear-gradient(to bottom right, var(--primary)/20, var(--secondary)/30)' }}>
<Newspaper className="h-8 w-8" style={{ color: 'var(--primary)' }} />
</div>
<div className="flex-1">
<div className="flex items-center gap-2 mb-2">
<span className="text-xs px-2 py-1 rounded" style={{ backgroundColor: 'var(--primary)', color: 'var(--primary-foreground)' }}>AI & ML</span>
<span className="text-xs" style={{ color: 'var(--muted-foreground)' }}>TechCrunch</span>
<span className="text-xs" style={{ color: 'var(--muted-foreground)' }}></span>
<span className="text-xs flex items-center gap-1" style={{ color: 'var(--muted-foreground)' }}>
<Clock className="h-3 w-3" />
2 hours ago
</span>
</div>
<h3 className="font-semibold text-lg mb-2 hover:text-primary cursor-pointer">
OpenAI Announces GPT-5 with Revolutionary Capabilities
</h3>
<p className="text-sm mb-3" style={{ color: 'var(--muted-foreground)' }}>
The latest AI model shows unprecedented reasoning abilities and multimodal understanding,
setting new benchmarks across various tasks and potentially reshaping the AI landscape...
</p>
<div className="flex items-center justify-between">
<div className="flex items-center gap-4 text-sm" style={{ color: 'var(--muted-foreground)' }}>
<button className="hover:text-primary transition-colors">Save</button>
<button className="hover:text-primary transition-colors">Share</button>
<button className="hover:text-primary transition-colors">Discuss</button>
</div>
<button className="flex items-center gap-1 text-sm font-medium" style={{ color: 'var(--primary)' }}>
Read Full Article
<ExternalLink className="h-3 w-3" />
</button>
</div>
</div>
</div>
</article>
))}
</div>
</div>
</div>
</div>
);
const renderMCPServers = () => (
<div className="h-full flex flex-col" style={{ backgroundColor: 'var(--background)', color: 'var(--foreground)' }}>
{/* Header */}
<div className="p-4 border-b" style={{ borderColor: 'var(--border)' }}>
<div className="flex items-center justify-between mb-4">
<h2 className="text-2xl font-bold flex items-center gap-2">
<Server className="h-6 w-6" style={{ color: 'var(--chart-2)' }} />
MCP Servers
</h2>
<div className="flex gap-2">
<button className="px-4 py-2 border rounded-lg transition-colors" style={{ borderColor: 'var(--border)', color: 'var(--foreground)' }}>
Documentation
</button>
<button className="px-4 py-2 text-white rounded-lg transition-colors" style={{ backgroundColor: 'var(--chart-2)', color: 'var(--chart-2-foreground)' }}>
Create Server
</button>
</div>
</div>
{/* Search */}
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4" style={{ color: 'var(--muted-foreground)' }} />
<input
type="text"
placeholder="Search MCP servers..."
className="w-full pl-10 pr-4 py-2 border rounded-lg focus:ring-2 focus:border-transparent"
style={{
borderColor: 'var(--border)',
backgroundColor: 'var(--background)',
color: 'var(--foreground)',
}}
/>
</div>
</div>
<div className="flex-1 flex">
{/* Categories Sidebar */}
<div className="w-80 border-r p-4" style={{ borderColor: 'var(--border)', backgroundColor: 'var(--background)' }}>
<h3 className="font-semibold mb-4" style={{ color: 'var(--muted-foreground)' }}>Categories</h3>
<div className="space-y-2">
{[
{ name: "developer-tools", count: 1203, color: "--primary" },
{ name: "search", count: 609, color: "--secondary" },
{ name: "communication", count: 233, color: "--chart-1" },
{ name: "entertainment", count: 106, color: "--chart-2" },
{ name: "file-systems", count: 207, color: "--chart-3" },
{ name: "finance", count: 226, color: "--chart-4" },
{ name: "knowledge", count: 264, color: "--chart-5" },
{ name: "location", count: 71, color: "--primary" },
{ name: "other", count: 294, color: "--accent" }
].map((category, index) => (
<button
key={index}
onClick={() => setSelectedCategory(category.name)}
className={`w-full text-left p-3 rounded-lg transition-colors flex items-center justify-between hover:bg-card ${selectedCategory === category.name ? 'bg-card shadow-sm border-l-4' : ''
}`}
style={{
borderLeftColor: selectedCategory === category.name ? `var(${category.color})` : 'transparent',
backgroundColor: selectedCategory === category.name ? 'var(--card)' : '',
color: 'var(--card-foreground)'
}}
>
<div className="flex items-center gap-3">
<div
className="w-3 h-3 rounded-full"
style={{ backgroundColor: `var(${category.color})` }}
></div>
<span className="font-medium">{category.name}</span>
</div>
<span className="text-sm bg-gray-200 px-2 py-1 rounded-full" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>
{category.count}
</span>
</button>
))}
</div>
{/* Quick Filters */}
<div className="mt-8">
<h3 className="font-semibold mb-4" style={{ color: 'var(--muted-foreground)' }}>Server Type</h3>
<div className="space-y-2">
<button className="w-full text-left p-3 rounded-lg transition-colors flex items-center justify-between hover:bg-card" style={{ color: 'var(--card-foreground)' }}>
<span className="font-medium">Hosted</span>
<span className="text-sm bg-gray-200 px-2 py-1 rounded-full" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>24</span>
</button>
<button className="w-full text-left p-3 rounded-lg transition-colors flex items-center justify-between hover:bg-card" style={{ color: 'var(--card-foreground)' }}>
<span className="font-medium">Local</span>
<span className="text-sm bg-gray-200 px-2 py-1 rounded-full" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>8</span>
</button>
</div>
</div>
</div>
{/* Content Area */}
<div className="flex-1 p-6 overflow-y-auto" style={{ backgroundColor: 'var(--background)', color: 'var(--foreground)' }}>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{mcpServers.map((server, index) => {
const IconComponent = server.icon;
return (
<div key={index} className="border rounded-lg p-4 transition-shadow" style={{ backgroundColor: 'var(--card)', color: 'var(--card-foreground)', borderColor: 'var(--border)' }}>
<div className="flex items-start justify-between mb-3">
<div className="flex items-center gap-3">
<IconComponent className="h-5 w-5" style={{ color: 'var(--chart-2)' }} />
<h3 className="font-semibold">{server.name}</h3>
</div>
<span className={`text-xs px-2 py-1 rounded ${server.type === 'Hosted' ? 'bg-blue-100 text-blue-800' : 'bg-green-100 text-green-800'
}`}>
{server.type}
</span>
</div>
<p className="text-sm mb-3" style={{ color: 'var(--muted-foreground)' }}>
{server.description}
</p>
<div className="flex items-center justify-between">
<span className="text-xs px-2 py-1 rounded" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>
{server.category}
</span>
<div className="flex items-center gap-2">
<span className="text-xs" style={{ color: 'var(--muted-foreground)' }}>{server.usage} uses</span>
<button className="flex items-center gap-1 text-sm font-medium" style={{ color: 'var(--chart-2)' }}>
<ArrowRight className="h-3 w-3" />
Connect
</button>
</div>
</div>
</div>
);
})}
</div>
</div>
</div>
</div>
);
const renderLLMTools = () => (
<div className="h-full flex flex-col" style={{ backgroundColor: 'var(--background)', color: 'var(--foreground)' }}>
{/* Header */}
<div className="p-4 border-b" style={{ borderColor: 'var(--border)' }}>
<div className="flex items-center justify-between mb-4">
<h2 className="text-2xl font-bold flex items-center gap-2">
<Cpu className="h-6 w-6" style={{ color: 'var(--chart-3)' }} />
LLM Tools
</h2>
<div className="flex gap-2">
<button className="px-4 py-2 border rounded-lg transition-colors" style={{ borderColor: 'var(--border)', color: 'var(--foreground)' }}>
Documentation
</button>
<button className="px-4 py-2 text-white rounded-lg transition-colors" style={{ backgroundColor: 'var(--chart-3)', color: 'var(--chart-3-foreground)' }}>
Create Tool
</button>
</div>
</div>
{/* Search */}
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4" style={{ color: 'var(--muted-foreground)' }} />
<input
type="text"
placeholder="Search LLM tools..."
className="w-full pl-10 pr-4 py-2 border rounded-lg focus:ring-2 focus:border-transparent"
style={{
borderColor: 'var(--border)',
backgroundColor: 'var(--background)',
color: 'var(--foreground)',
}}
/>
</div>
</div>
<div className="flex-1 flex">
{/* Categories Sidebar */}
<div className="w-80 border-r p-4" style={{ borderColor: 'var(--border)', backgroundColor: 'var(--background)' }}>
<h3 className="font-semibold mb-4" style={{ color: 'var(--muted-foreground)' }}>Categories</h3>
<div className="space-y-2">
{[
{ name: "User Management", count: 12, color: "--primary" },
{ name: "Location Services", count: 8, color: "--accent" },
{ name: "E-commerce", count: 6, color: "--secondary" },
{ name: "Knowledge", count: 15, color: "--chart-2" },
{ name: "Development", count: 22, color: "--primary" },
{ name: "Analytics", count: 9, color: "--chart-1" }
].map((category, index) => (
<button
key={index}
onClick={() => setSelectedCategory(category.name)}
className={`w-full text-left p-3 rounded-lg transition-colors flex items-center justify-between hover:bg-card ${selectedCategory === category.name ? 'bg-card shadow-sm border-l-4' : ''
}`}
style={{
borderLeftColor: selectedCategory === category.name ? `var(${category.color})` : 'transparent',
backgroundColor: selectedCategory === category.name ? 'var(--card)' : '',
color: 'var(--card-foreground)'
}}
>
<div className="flex items-center gap-3">
<div
className="w-3 h-3 rounded-full"
style={{ backgroundColor: `var(${category.color})` }}
></div>
<span className="font-medium">{category.name}</span>
</div>
<span className="text-sm bg-gray-200 px-2 py-1 rounded-full" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>
{category.count}
</span>
</button>
))}
</div>
{/* Featured Tools */}
<div className="mt-8">
<h3 className="font-semibold mb-4 flex items-center gap-2" style={{ color: 'var(--muted-foreground)' }}>
<Star className="h-4 w-4" style={{ color: 'var(--chart-4)' }} />
Most Used
</h3>
<div className="space-y-3">
{llmTools.slice(0, 3).map((tool, index) => (
<div key={index} className="p-3 rounded-lg shadow-sm border" style={{ backgroundColor: 'var(--card)', color: 'var(--card-foreground)', borderColor: 'var(--border)' }}>
<div className="flex items-center gap-2">
<div
className="w-3 h-3 rounded-full flex-shrink-0"
style={{ backgroundColor: `var(${tool.color})` }}
></div>
<h4 className="font-medium text-sm">{tool.name}</h4>
</div>
<p className="text-xs mt-1" style={{ color: 'var(--muted-foreground)' }}>{tool.description}</p>
</div>
))}
</div>
</div>
</div>
{/* Content Area */}
<div className="flex-1 p-6 overflow-y-auto" style={{ backgroundColor: 'var(--background)', color: 'var(--foreground)' }}>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{llmTools.map((tool, index) => {
const IconComponent = tool.icon;
return (
<div key={index} className="border rounded-lg p-4 transition-shadow" style={{ backgroundColor: 'var(--card)', color: 'var(--card-foreground)', borderColor: 'var(--border)' }}>
<div className="flex items-start justify-between mb-3">
<div className="flex items-center gap-3">
<IconComponent className="h-5 w-5" style={{ color: `var(${tool.color})` }} />
<h3 className="font-semibold">{tool.name}</h3>
</div>
<button className="p-1 hover:bg-gray-100 rounded" >
<Copy className="h-4 w-4" style={{ color: 'var(--muted-foreground)' }} />
</button>
</div>
<p className="text-sm mb-3" style={{ color: 'var(--muted-foreground)' }}>
{tool.description}
</p>
<div className="flex items-center justify-between">
<span className="text-xs px-2 py-1 rounded" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>
{tool.category}
</span>
<button className="flex items-center gap-1 text-sm font-medium" style={{ color: 'var(--chart-3)' }}>
<Play className="h-3 w-3" />
Run Tool
</button>
</div>
</div>
);
})}
</div>
</div>
</div>
</div>
);
const renderModels = () => (
<div className="h-full flex flex-col" style={{ backgroundColor: 'var(--background)', color: 'var(--foreground)' }}>
{/* Header */}
<div className="p-4 border-b" style={{ borderColor: 'var(--border)' }}>
<div className="flex items-center justify-between mb-4">
<h2 className="text-2xl font-bold flex items-center gap-2">
<Cpu className="h-6 w-6" style={{ color: 'var(--chart-5)' }} />
AI Models
</h2>
<div className="flex gap-2">
<button className="px-4 py-2 border rounded-lg transition-colors" style={{ borderColor: 'var(--border)', color: 'var(--foreground)' }}>
Documentation
</button>
<button className="px-4 py-2 text-white rounded-lg transition-colors" style={{ backgroundColor: 'var(--chart-5)', color: 'var(--chart-5-foreground)' }}>
Add Model
</button>
</div>
</div>
{/* Search */}
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4" style={{ color: 'var(--muted-foreground)' }} />
<input
type="text"
placeholder="Search AI models..."
className="w-full pl-10 pr-4 py-2 border rounded-lg focus:ring-2 focus:border-transparent"
style={{
borderColor: 'var(--border)',
backgroundColor: 'var(--background)',
color: 'var(--foreground)',
}}
/>
</div>
</div>
<div className="flex-1 flex">
{/* Categories Sidebar */}
<div className="w-80 border-r p-4" style={{ borderColor: 'var(--border)', backgroundColor: 'var(--background)' }}>
<h3 className="font-semibold mb-4" style={{ color: 'var(--muted-foreground)' }}>Providers</h3>
<div className="space-y-2">
{[
{ name: "OpenAI", count: 12, color: "--primary" },
{ name: "Anthropic", count: 8, color: "--accent" },
{ name: "Google", count: 6, color: "--secondary" },
{ name: "Meta", count: 5, color: "--chart-2" },
{ name: "Mistral", count: 4, color: "--chart-3" },
{ name: "Cohere", count: 3, color: "--chart-4" },
{ name: "AWS", count: 7, color: "--chart-5" },
{ name: "Azure", count: 5, color: "--primary" },
{ name: "Other", count: 9, color: "--destructive" }
].map((category, index) => (
<button
key={index}
onClick={() => setSelectedCategory(category.name)}
className={`w-full text-left p-3 rounded-lg transition-colors flex items-center justify-between hover:bg-card ${selectedCategory === category.name ? 'bg-card shadow-sm border-l-4' : ''
}`}
style={{
borderLeftColor: selectedCategory === category.name ? `var(${category.color})` : 'transparent',
backgroundColor: selectedCategory === category.name ? 'var(--card)' : '',
color: 'var(--card-foreground)'
}}
>
<div className="flex items-center gap-3">
<div
className="w-3 h-3 rounded-full"
style={{ backgroundColor: `var(${category.color})` }}
></div>
<span className="font-medium">{category.name}</span>
</div>
<span className="text-sm bg-gray-200 px-2 py-1 rounded-full" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>
{category.count}
</span>
</button>
))}
</div>
{/* Model Types */}
<div className="mt-8">
<h3 className="font-semibold mb-4" style={{ color: 'var(--muted-foreground)' }}>Model Types</h3>
<div className="space-y-2">
<button className="w-full text-left p-3 rounded-lg transition-colors flex items-center justify-between hover:bg-card" style={{ color: 'var(--card-foreground)' }}>
<span className="font-medium">Text Generation</span>
<span className="text-sm bg-gray-200 px-2 py-1 rounded-full" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>32</span>
</button>
<button className="w-full text-left p-3 rounded-lg transition-colors flex items-center justify-between hover:bg-card" style={{ color: 'var(--card-foreground)' }}>
<span className="font-medium">Multimodal</span>
<span className="text-sm bg-gray-200 px-2 py-1 rounded-full" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>15</span>
</button>
<button className="w-full text-left p-3 rounded-lg transition-colors flex items-center justify-between hover:bg-card" style={{ color: 'var(--card-foreground)' }}>
<span className="font-medium">Embeddings</span>
<span className="text-sm bg-gray-200 px-2 py-1 rounded-full" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>12</span>
</button>
</div>
</div>
</div>
{/* Content Area */}
<div className="flex-1 p-6 overflow-y-auto" style={{ backgroundColor: 'var(--background)', color: 'var(--foreground)' }}>
<div className="space-y-4">
{[
{
name: "AI21",
description: "You can get started with AI21Labs' Jurassic family of models, as well as their task-specific models.",
provider: "AI21 Labs",
type: "Text Generation",
status: "Active"
},
{
name: "AlephAlpha",
description: "LangChain.js supports AlephAlpha's Luminous family of models. You'll need an AlephAlpha API key.",
provider: "Aleph Alpha",
type: "Text Generation",
status: "Active"
},
{
name: "Arcjet Redact",
description: "The Arcjet redact integration allows you to redact sensitive information from text.",
provider: "Arcjet",
type: "Text Processing",
status: "Beta"
},
{
name: "AWS SageMakerEndpoint",
description: "LangChain.js supports integration with AWS SageMaker-hosted endpoints for custom models.",
provider: "AWS",
type: "Custom Models",
status: "Active"
},
{
name: "Azure OpenAI",
description: "Azure OpenAI provides access to OpenAI models through Microsoft's Azure cloud platform.",
provider: "Microsoft",
type: "Text Generation",
status: "Active"
},
{
name: "Bedrock",
description: "Amazon Bedrock is a fully managed service that makes foundation models from AI21, Anthropic, and Amazon accessible via API.",
provider: "AWS",
type: "Text Generation",
status: "Active"
},
{
name: "ChromeAI",
description: "This feature is experimental and is subject to change. Provides browser-based AI capabilities.",
provider: "Google",
type: "Experimental",
status: "Preview"
},
{
name: "Cloudflare Workers AI",
description: "This will help you get started with Cloudflare Workers AI text generation models.",
provider: "Cloudflare",
type: "Text Generation",
status: "Active"
},
{
name: "Cohere",
description: "This will help you get started with Cohere completion models (LLMs) and embedding models.",
provider: "Cohere",
type: "Text Generation",
status: "Active"
},
{
name: "Deep Infra",
description: "LangChain supports LLMs hosted by Deep Infra through the DeepInfra wrapper.",
provider: "Deep Infra",
type: "Text Generation",
status: "Active"
},
{
name: "Fireworks",
description: "Fireworks AI is an AI inference platform to run open-source models at scale.",
provider: "Fireworks",
type: "Text Generation",
status: "Active"
},
{
name: "Friendli",
description: "Friendli enhances AI application performance and optimizes cost savings for LLM inference.",
provider: "Friendli",
type: "Optimization",
status: "Beta"
},
{
name: "Google Vertex AI",
description: "Google Vertex is a service that provides access to Google's foundation models.",
provider: "Google",
type: "Text Generation",
status: "Active"
},
{
name: "HuggingFaceInference",
description: "Here's an example of calling a HuggingFaceInference model as an LLM.",
provider: "Hugging Face",
type: "Text Generation",
status: "Active"
},
{
name: "IBM watsonx.ai",
description: "This will help you get started with IBM text completion models on watsonx.ai.",
provider: "IBM",
type: "Text Generation",
status: "Active"
},
{
name: "Llama CPP",
description: "Only available on Node.js. Provides access to locally run Llama models.",
provider: "Meta",
type: "Local Inference",
status: "Active"
},
{
name: "MistralAI",
description: "Mistral AI is a platform that offers hosting for their open-weight models.",
provider: "Mistral",
type: "Text Generation",
status: "Active"
},
{
name: "Ollama",
description: "This will help you get started with Ollama text completion models running locally.",
provider: "Ollama",
type: "Local Inference",
status: "Active"
},
{
name: "Replicate",
description: "Here's an example of calling a Replicate model as an LLM.",
provider: "Replicate",
type: "Text Generation",
status: "Active"
},
{
name: "Together AI",
description: "You are currently on a page documenting the use of Together AI models with LangChain.",
provider: "Together AI",
type: "Text Generation",
status: "Active"
},
{
name: "Writer",
description: "LangChain.js supports calling Writer LLMs for content generation.",
provider: "Writer",
type: "Text Generation",
status: "Active"
},
{
name: "YandexGPT",
description: "LangChain.js supports calling YandexGPT LLMs. Also supports qwen and deepseek models.",
provider: "Yandex",
type: "Text Generation",
status: "Active"
}
].map((model, index) => (
<div key={index} className="border rounded-lg p-4 transition-shadow" style={{ backgroundColor: 'var(--card)', color: 'var(--card-foreground)', borderColor: 'var(--border)' }}>
<div className="flex items-start justify-between mb-3">
<h3 className="font-semibold text-lg">{model.name}</h3>
<span className={`text-xs px-2 py-1 rounded ${model.status === 'Active' ? 'bg-green-100 text-green-800' :
model.status === 'Beta' ? 'bg-blue-100 text-blue-800' :
'bg-yellow-100 text-yellow-800'
}`}>
{model.status}
</span>
</div>
<p className="text-sm mb-3" style={{ color: 'var(--muted-foreground)' }}>
{model.description}
</p>
<div className="flex items-center justify-between">
<div className="flex gap-2">
<span className="text-xs px-2 py-1 rounded" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>
{model.provider}
</span>
<span className="text-xs px-2 py-1 rounded" style={{ backgroundColor: 'var(--muted)', color: 'var(--muted-foreground)' }}>
{model.type}
</span>
</div>
<button className="flex items-center gap-1 text-sm font-medium" style={{ color: 'var(--chart-5)' }}>
<ExternalLink className="h-3 w-3" />
View Details
</button>
</div>
</div>
))}
</div>
</div>
</div>
</div>
);
return (
<div className="h-screen flex flex-col" style={{ backgroundColor: 'var(--background)', color: 'var(--foreground)' }}>
{/* Tab Navigation */}
<div className="border-b" style={{ backgroundColor: 'var(--background)', borderColor: 'var(--border)' }}>
<div className="flex">
{[
{ id: 'prompts', label: 'Prompts', icon: Lightbulb, color: 'text-yellow-600' },
{ id: 'templates', label: 'Templates', icon: FileText, color: 'text-green-600' },
{ id: 'news', label: 'News', icon: Newspaper, color: 'text-blue-600' },
{ id: 'mcp', label: 'MCP Servers', icon: Server, color: 'text-purple-600' },
{ id: 'llm-tools', label: 'LLM Tools', icon: Cpu, color: 'text-indigo-600' },
{ id: 'models', label: 'Models', icon: Cpu, color: 'text-teal-600' }
].map((tab) => {
const IconComponent = tab.icon;
return (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
className={`flex items-center gap-2 px-6 py-4 border-b-2 transition-colors font-medium ${activeTab === tab.id
? `border-current ${tab.color} bg-card`
: 'border-transparent hover:bg-card'
}`}
>
<IconComponent className="h-4 w-4" />
{tab.label}
</button>
);
})}
</div>
</div>
{/* Content */}
<div className="flex-1 overflow-hidden">
{activeTab === 'prompts' && renderPrompts()}
{activeTab === 'templates' && renderTemplates()}
{activeTab === 'news' && renderNews()}
{activeTab === 'mcp' && renderMCPServers()}
{activeTab === 'llm-tools' && renderLLMTools()}
{activeTab === 'models' && renderModels()}
</div>
</div>
);
}