likhonsheikh commited on
Commit
cdf89b8
·
verified ·
1 Parent(s): 9e356af

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. app/api/completion/route.ts +111 -0
  2. app/globals.css +98 -0
  3. app/layout.tsx +29 -0
  4. app/page.tsx +206 -0
app/api/completion/route.ts ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { createHuggingFace } from '@ai-sdk/huggingface';
2
+ import { createOpenAI } from '@ai-sdk/openai';
3
+ import { createAnthropic } from '@ai-sdk/anthropic';
4
+ import { createGoogleGenerativeAI } from '@ai-sdk/google';
5
+ import { streamText, toTextStreamResponse } from 'ai';
6
+ import { NextRequest } from 'next/server';
7
+
8
+ // Create provider instances with proper configuration
9
+ const huggingface = createHuggingFace({
10
+ apiKey: process.env.HUGGINGFACE_API_KEY,
11
+ // Use the default base URL: https://router.huggingface.co/v1
12
+ });
13
+
14
+ const openai = createOpenAI({
15
+ apiKey: process.env.OPENAI_API_KEY,
16
+ });
17
+
18
+ const anthropic = createAnthropic({
19
+ apiKey: process.env.ANTHROPIC_API_KEY,
20
+ });
21
+
22
+ const google = createGoogleGenerativeAI({
23
+ apiKey: process.env.GOOGLE_API_KEY,
24
+ });
25
+
26
+ // Get provider and model from request
27
+ const getProviderForModel = (modelName: string) => {
28
+ if (modelName.includes('deepseek-ai') || modelName.includes('Qwen') ||
29
+ modelName.includes('moonshotai') || modelName.includes('zai-org') ||
30
+ modelName.includes('MiniMaxAI') || modelName.includes('meta-llama') ||
31
+ modelName.includes('gemma')) {
32
+ return huggingface;
33
+ }
34
+ if (modelName.includes('gpt')) {
35
+ return openai;
36
+ }
37
+ if (modelName.includes('claude')) {
38
+ return anthropic;
39
+ }
40
+ if (modelName.includes('gemini')) {
41
+ return google;
42
+ }
43
+
44
+ // Default to Hugging Face for unknown models
45
+ return huggingface;
46
+ };
47
+
48
+ export async function POST(req: NextRequest) {
49
+ try {
50
+ const { messages, model } = await req.json();
51
+
52
+ if (!model) {
53
+ return new Response('Model is required', { status: 400 });
54
+ }
55
+
56
+ if (!messages || !Array.isArray(messages)) {
57
+ return new Response('Messages array is required', { status: 400 });
58
+ }
59
+
60
+ const provider = getProviderForModel(model);
61
+
62
+ // Convert messages to the format expected by AI SDK
63
+ const systemMessage = messages.find((m: any) => m.role === 'system');
64
+ const userMessages = messages
65
+ .filter((m: any) => m.role === 'user')
66
+ .map((m: any) => m.content)
67
+ .join('\n\n');
68
+
69
+ const messagesToSend = systemMessage ? [systemMessage.content, userMessages] : [userMessages];
70
+
71
+ // Use streamText with proper Hugging Face streaming
72
+ const result = await streamText({
73
+ model: provider(model),
74
+ messages: messagesToSend,
75
+ maxTokens: 2000,
76
+ temperature: 0.7,
77
+ topP: 0.9,
78
+ presencePenalty: 0.1,
79
+ frequencyPenalty: 0.1,
80
+ onError: ({ error }) => {
81
+ console.error('Stream error:', error);
82
+ },
83
+ });
84
+
85
+ // Return the streaming response
86
+ return result.toTextStreamResponse();
87
+ } catch (error) {
88
+ console.error('AI API Error:', error);
89
+
90
+ // Return a helpful error message
91
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
92
+
93
+ return new Response(JSON.stringify({
94
+ error: 'Failed to process AI request',
95
+ details: errorMessage,
96
+ message: 'Please check your API keys and model configuration. Make sure you have a valid API key for the selected model provider.',
97
+ model: model || 'unknown',
98
+ provider: model ? getProviderForModel(model).constructor.name : 'unknown'
99
+ }), {
100
+ status: 500,
101
+ headers: {
102
+ 'Content-Type': 'application/json',
103
+ },
104
+ });
105
+ }
106
+ }
107
+
108
+ // Support both POST and GET for compatibility
109
+ export async function GET(req: NextRequest) {
110
+ return POST(req);
111
+ }
app/globals.css ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ :root {
7
+ --background: 0 0% 100%;
8
+ --foreground: 222.2 84% 4.9%;
9
+
10
+ --card: 0 0% 100%;
11
+ --card-foreground: 222.2 84% 4.9%;
12
+
13
+ --popover: 0 0% 100%;
14
+ --popover-foreground: 222.2 84% 4.9%;
15
+
16
+ --primary: 222.2 47.4% 11.2%;
17
+ --primary-foreground: 210 40% 98%;
18
+
19
+ --secondary: 210 40% 96%;
20
+ --secondary-foreground: 222.2 84% 4.9%;
21
+
22
+ --muted: 210 40% 96%;
23
+ --muted-foreground: 215.4 16.3% 46.9%;
24
+
25
+ --accent: 210 40% 96%;
26
+ --accent-foreground: 222.2 84% 4.9%;
27
+
28
+ --destructive: 0 84.2% 60.2%;
29
+ --destructive-foreground: 210 40% 98%;
30
+
31
+ --border: 214.3 31.8% 91.4%;
32
+ --input: 214.3 31.8% 91.4%;
33
+ --ring: 222.2 84% 4.9%;
34
+
35
+ --radius: 0.5rem;
36
+ }
37
+
38
+ .dark {
39
+ --background: 222.2 84% 4.9%;
40
+ --foreground: 210 40% 98%;
41
+
42
+ --card: 222.2 84% 4.9%;
43
+ --card-foreground: 210 40% 98%;
44
+
45
+ --popover: 222.2 84% 4.9%;
46
+ --popover-foreground: 210 40% 98%;
47
+
48
+ --primary: 210 40% 98%;
49
+ --primary-foreground: 222.2 47.4% 11.2%;
50
+
51
+ --secondary: 217.2 32.6% 17.5%;
52
+ --secondary-foreground: 210 40% 98%;
53
+
54
+ --muted: 217.2 32.6% 17.5%;
55
+ --muted-foreground: 215 20.2% 65.1%;
56
+
57
+ --accent: 217.2 32.6% 17.5%;
58
+ --accent-foreground: 210 40% 98%;
59
+
60
+ --destructive: 0 62.8% 30.6%;
61
+ --destructive-foreground: 210 40% 98%;
62
+
63
+ --border: 217.2 32.6% 17.5%;
64
+ --input: 217.2 32.6% 17.5%;
65
+ --ring: 212.7 26.8% 83.9%;
66
+ }
67
+ }
68
+
69
+ @layer base {
70
+ * {
71
+ @apply border-border;
72
+ }
73
+ body {
74
+ @apply bg-background text-foreground;
75
+ }
76
+ }
77
+
78
+ /* Monaco Editor custom styles */
79
+ .monaco-editor-container {
80
+ @apply rounded-lg border border-border overflow-hidden;
81
+ }
82
+
83
+ /* Custom scrollbar for code areas */
84
+ .code-area::-webkit-scrollbar {
85
+ width: 6px;
86
+ }
87
+
88
+ .code-area::-webkit-scrollbar-track {
89
+ @apply bg-muted;
90
+ }
91
+
92
+ .code-area::-webkit-scrollbar-thumb {
93
+ @apply bg-muted-foreground/30 rounded-full;
94
+ }
95
+
96
+ .code-area::-webkit-scrollbar-thumb:hover {
97
+ @apply bg-muted-foreground/50;
98
+ }
app/layout.tsx ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Metadata } from "next";
2
+ import { Inter } from "next/font/google";
3
+ import "./globals.css";
4
+ import { Providers } from "@/components/providers";
5
+
6
+ const inter = Inter({ subsets: ["latin"] });
7
+
8
+ export const metadata: Metadata = {
9
+ title: "DeepSite - AI-Powered Vibe Coding Platform",
10
+ description: "Integrate generative AI into your coding projects to enhance creativity and productivity",
11
+ keywords: ["AI", "coding", "development", "generative AI", "programming"],
12
+ authors: [{ name: "MiniMax Agent" }],
13
+ };
14
+
15
+ export default function RootLayout({
16
+ children,
17
+ }: Readonly<{
18
+ children: React.ReactNode;
19
+ }>) {
20
+ return (
21
+ <html lang="en" className="dark">
22
+ <body className={inter.className}>
23
+ <Providers>
24
+ {children}
25
+ </Providers>
26
+ </body>
27
+ </html>
28
+ );
29
+ }
app/page.tsx ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client';
2
+
3
+ import { useState, useCallback } from 'react';
4
+ import { useCompletion } from 'ai/react';
5
+ import { ChevronLeft, ChevronRight, Code, Send, Settings, Zap, Sparkles } from 'lucide-react';
6
+ import { Button } from '@/components/ui/button';
7
+ import { Textarea } from '@/components/ui/textarea';
8
+ import { Card } from '@/components/ui/card';
9
+ import { Badge } from '@/components/ui/badge';
10
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
11
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
12
+ import { CodeEditor } from '@/components/code-editor';
13
+ import { ModelSelector } from '@/components/model-selector';
14
+ import { ConversationPanel } from '@/components/conversation-panel';
15
+ import { supportedModels } from '@/components/providers';
16
+ import { createHuggingFace } from '@ai-sdk/huggingface';
17
+
18
+ export default function HomePage() {
19
+ const [activeTab, setActiveTab] = useState('editor');
20
+ const [code, setCode] = useState('// Welcome to DeepSite - AI-Powered Vibe Coding Platform\n// Start coding with AI assistance!\n\nfunction helloWorld() {\n console.log("Hello, AI-powered coding!");\n return "Ready to code with AI? 🚀";\n}');
21
+
22
+ const [selectedModel, setSelectedModel] = useState('deepseek-ai/DeepSeek-V3-0324');
23
+ const [prompt, setPrompt] = useState('');
24
+
25
+ const { completion, isLoading, complete } = useCompletion({
26
+ model: selectedModel,
27
+ api: '/api/completion',
28
+ });
29
+
30
+ const handlePromptSubmit = useCallback(async (userPrompt: string) => {
31
+ if (!userPrompt.trim()) return;
32
+
33
+ try {
34
+ await complete(`
35
+ Context: I have the following code in my editor:
36
+ \`\`\`
37
+ ${code}
38
+ \`\`\`
39
+
40
+ Task: ${userPrompt}
41
+
42
+ Please provide a helpful response and/or code modifications that address this task. Be specific and provide working code when possible.
43
+ `);
44
+ } catch (error) {
45
+ console.error('Error completing task:', error);
46
+ }
47
+ }, [code, complete]);
48
+
49
+ const handleSend = useCallback(() => {
50
+ if (prompt.trim()) {
51
+ handlePromptSubmit(prompt);
52
+ setPrompt('');
53
+ }
54
+ }, [prompt, handlePromptSubmit]);
55
+
56
+ const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
57
+ if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
58
+ handleSend();
59
+ }
60
+ }, [handleSend]);
61
+
62
+ return (
63
+ <div className="min-h-screen bg-background">
64
+ {/* Header */}
65
+ <header className="border-b border-border bg-card/50 backdrop-blur supports-[backdrop-filter]:bg-background/60">
66
+ <div className="container mx-auto px-4 py-4">
67
+ <div className="flex items-center justify-between">
68
+ <div className="flex items-center gap-3">
69
+ <div className="flex items-center gap-2">
70
+ <div className="w-8 h-8 bg-gradient-to-br from-blue-500 to-purple-600 rounded-lg flex items-center justify-center">
71
+ <Code className="w-4 h-4 text-white" />
72
+ </div>
73
+ <div>
74
+ <h1 className="text-2xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
75
+ DeepSite
76
+ </h1>
77
+ <p className="text-sm text-muted-foreground">AI-Powered Vibe Coding</p>
78
+ </div>
79
+ </div>
80
+ </div>
81
+
82
+ <div className="flex items-center gap-4">
83
+ <Badge variant="secondary" className="text-xs">
84
+ <Sparkles className="w-3 h-3 mr-1" />
85
+ Powered by AI SDK Elements
86
+ </Badge>
87
+ <ModelSelector
88
+ selectedModel={selectedModel}
89
+ onModelChange={setSelectedModel}
90
+ models={Object.keys(supportedModels)}
91
+ />
92
+ </div>
93
+ </div>
94
+ </div>
95
+ </header>
96
+
97
+ {/* Main Content */}
98
+ <main className="container mx-auto px-4 py-6">
99
+ <Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
100
+ <div className="flex items-center justify-between mb-6">
101
+ <TabsList className="grid w-fit grid-cols-2">
102
+ <TabsTrigger value="editor" className="flex items-center gap-2">
103
+ <Code className="w-4 h-4" />
104
+ Code Editor
105
+ </TabsTrigger>
106
+ <TabsTrigger value="chat" className="flex items-center gap-2">
107
+ <Zap className="w-4 h-4" />
108
+ AI Assistant
109
+ </TabsTrigger>
110
+ </TabsList>
111
+
112
+ <div className="text-sm text-muted-foreground">
113
+ {selectedModel.split('/').pop()}
114
+ </div>
115
+ </div>
116
+
117
+ <TabsContent value="editor" className="mt-0">
118
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-6 h-[calc(100vh-200px)]">
119
+ {/* Code Editor */}
120
+ <Card className="p-4 flex flex-col">
121
+ <div className="flex items-center justify-between mb-4">
122
+ <h2 className="text-lg font-semibold">Code Editor</h2>
123
+ <Badge variant="outline">JavaScript</Badge>
124
+ </div>
125
+ <CodeEditor
126
+ value={code}
127
+ onChange={setCode}
128
+ className="flex-1 min-h-0"
129
+ />
130
+ </Card>
131
+
132
+ {/* AI Assistant Chat */}
133
+ <Card className="p-4 flex flex-col">
134
+ <div className="flex items-center justify-between mb-4">
135
+ <h2 className="text-lg font-semibold">AI Assistant</h2>
136
+ <div className="flex items-center gap-2">
137
+ <div className={`w-2 h-2 rounded-full ${isLoading ? 'bg-yellow-500 animate-pulse' : 'bg-green-500'}`} />
138
+ <span className="text-xs text-muted-foreground">
139
+ {isLoading ? 'Thinking...' : 'Ready'}
140
+ </span>
141
+ </div>
142
+ </div>
143
+
144
+ <ConversationPanel
145
+ completion={completion}
146
+ isLoading={isLoading}
147
+ className="flex-1 min-h-0 mb-4"
148
+ />
149
+
150
+ <div className="flex gap-2">
151
+ <Textarea
152
+ value={prompt}
153
+ onChange={(e) => setPrompt(e.target.value)}
154
+ onKeyDown={handleKeyDown}
155
+ placeholder="Ask AI to help with your code... (Ctrl+Enter to send)"
156
+ className="flex-1 resize-none"
157
+ rows={3}
158
+ />
159
+ <Button
160
+ onClick={handleSend}
161
+ disabled={!prompt.trim() || isLoading}
162
+ size="icon"
163
+ className="self-end"
164
+ >
165
+ <Send className="w-4 h-4" />
166
+ </Button>
167
+ </div>
168
+ </Card>
169
+ </div>
170
+ </TabsContent>
171
+
172
+ <TabsContent value="chat" className="mt-0">
173
+ <div className="max-w-4xl mx-auto">
174
+ <Card className="p-6">
175
+ <ConversationPanel
176
+ completion={completion}
177
+ isLoading={isLoading}
178
+ className="mb-6"
179
+ />
180
+
181
+ <div className="flex gap-2">
182
+ <Textarea
183
+ value={prompt}
184
+ onChange={(e) => setPrompt(e.target.value)}
185
+ onKeyDown={handleKeyDown}
186
+ placeholder="Chat with AI about coding, ask for help, generate code, or discuss programming concepts..."
187
+ className="flex-1 resize-none"
188
+ rows={3}
189
+ />
190
+ <Button
191
+ onClick={handleSend}
192
+ disabled={!prompt.trim() || isLoading}
193
+ size="icon"
194
+ className="self-end"
195
+ >
196
+ <Send className="w-4 h-4" />
197
+ </Button>
198
+ </div>
199
+ </Card>
200
+ </div>
201
+ </TabsContent>
202
+ </Tabs>
203
+ </main>
204
+ </div>
205
+ );
206
+ }