wu981526092 commited on
Commit
6c45e39
·
1 Parent(s): 47f57e6

Implement workflow-driven UX with improved Playground layout

Browse files

- Redesign Home page with clear 3-path workflow (Templates/Create/Chat)
- Expand Playground settings panel from 320px to 384px (w-96)
- Make system prompt always visible and prominent (no collapsible)
- Add creation mode detection (?mode=create) with visual indicators
- Style system prompt area like ChatGPT with better UX
- Combine assistant builder functionality into unified Playground
- Improve user guidance with contextual tips and better labeling

frontend/src/App.tsx CHANGED
@@ -2,8 +2,6 @@ import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
2
  import { Layout } from './components/Layout'
3
  import { Home } from './pages/Home'
4
  import { Playground } from './pages/Playground'
5
- import { ChatInterface } from './pages/ChatInterface'
6
- import { AssistantBuilder } from './pages/AssistantBuilder'
7
  import { Models } from './pages/Models'
8
  import { Assistants } from './pages/Assistants'
9
  import { Community } from './pages/Community'
@@ -16,8 +14,6 @@ function App() {
16
  <Route path="/" element={<Layout />}>
17
  <Route index element={<Home />} />
18
  <Route path="playground" element={<Playground />} />
19
- <Route path="chat" element={<ChatInterface />} />
20
- <Route path="assistant-builder" element={<AssistantBuilder />} />
21
  <Route path="models" element={<Models />} />
22
  <Route path="assistants" element={<Assistants />} />
23
  <Route path="community" element={<Community />} />
 
2
  import { Layout } from './components/Layout'
3
  import { Home } from './pages/Home'
4
  import { Playground } from './pages/Playground'
 
 
5
  import { Models } from './pages/Models'
6
  import { Assistants } from './pages/Assistants'
7
  import { Community } from './pages/Community'
 
14
  <Route path="/" element={<Layout />}>
15
  <Route index element={<Home />} />
16
  <Route path="playground" element={<Playground />} />
 
 
17
  <Route path="models" element={<Models />} />
18
  <Route path="assistants" element={<Assistants />} />
19
  <Route path="community" element={<Community />} />
frontend/src/components/Sidebar.tsx CHANGED
@@ -7,8 +7,7 @@ import {
7
  Settings,
8
  Brain,
9
  Bot,
10
- Users,
11
- Wrench
12
  } from 'lucide-react'
13
 
14
  const navigation = [
@@ -19,34 +18,28 @@ const navigation = [
19
  description: 'Overview and getting started'
20
  },
21
  {
22
- name: 'Chat',
23
- href: '/chat',
24
  icon: MessageSquare,
25
- description: 'Chat with your AI assistants'
26
  },
27
  {
28
- name: 'Assistant Builder',
29
- href: '/assistant-builder',
30
- icon: Wrench,
31
- description: 'Create and customize AI assistants'
32
  },
33
  {
34
  name: 'My Assistants',
35
  href: '/assistants',
36
  icon: Bot,
37
- description: 'Manage your saved assistants'
38
  },
39
  {
40
  name: 'Community',
41
  href: '/community',
42
  icon: Users,
43
- description: 'Discover community templates'
44
- },
45
- {
46
- name: 'Models',
47
- href: '/models',
48
- icon: BookOpen,
49
- description: 'Manage AI models'
50
  },
51
  {
52
  name: 'Settings',
 
7
  Settings,
8
  Brain,
9
  Bot,
10
+ Users
 
11
  } from 'lucide-react'
12
 
13
  const navigation = [
 
18
  description: 'Overview and getting started'
19
  },
20
  {
21
+ name: 'Chat Playground',
22
+ href: '/playground',
23
  icon: MessageSquare,
24
+ description: 'AI chatbot with conversation history'
25
  },
26
  {
27
+ name: 'Model Catalog',
28
+ href: '/models',
29
+ icon: BookOpen,
30
+ description: 'Browse and manage AI models'
31
  },
32
  {
33
  name: 'My Assistants',
34
  href: '/assistants',
35
  icon: Bot,
36
+ description: 'Manage your custom AI assistants'
37
  },
38
  {
39
  name: 'Community',
40
  href: '/community',
41
  icon: Users,
42
+ description: 'Discover and share assistant templates'
 
 
 
 
 
 
43
  },
44
  {
45
  name: 'Settings',
frontend/src/pages/AssistantBuilder.tsx DELETED
@@ -1,476 +0,0 @@
1
- import { useState, useEffect } from 'react'
2
- import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'
3
- import { Button } from '@/components/ui/button'
4
- import { Badge } from '@/components/ui/badge'
5
- import { Input } from '@/components/ui/input'
6
- import { Textarea } from '@/components/ui/textarea'
7
- import { Slider } from '@/components/ui/slider'
8
- import { Label } from '@/components/ui/label'
9
- import {
10
- Select,
11
- SelectContent,
12
- SelectItem,
13
- SelectTrigger,
14
- SelectValue,
15
- } from '@/components/ui/select'
16
- import {
17
- Bot,
18
- Save,
19
- MessageSquare,
20
- Settings,
21
- Brain,
22
- Zap,
23
- ArrowLeft,
24
- Copy,
25
- Sparkles,
26
- User,
27
- Info
28
- } from 'lucide-react'
29
-
30
- interface ModelInfo {
31
- model_name: string
32
- name: string
33
- supports_thinking: boolean
34
- description: string
35
- size_gb: string
36
- is_loaded: boolean
37
- type: 'local' | 'api'
38
- }
39
-
40
- interface ModelsResponse {
41
- models: ModelInfo[]
42
- current_model: string
43
- }
44
-
45
- interface AssistantConfig {
46
- id?: string
47
- name: string
48
- description: string
49
- instructions: string
50
- model: string
51
- temperature: number
52
- maxTokens: number
53
- capabilities: string[]
54
- createdAt?: string
55
- }
56
-
57
- export function AssistantBuilder() {
58
- const [models, setModels] = useState<ModelInfo[]>([])
59
- const [loading, setLoading] = useState(true)
60
-
61
- // Assistant configuration
62
- const [config, setConfig] = useState<AssistantConfig>({
63
- name: '',
64
- description: '',
65
- instructions: '',
66
- model: '',
67
- temperature: 0.7,
68
- maxTokens: 1024,
69
- capabilities: []
70
- })
71
-
72
- // UI state
73
- const [saving, setSaving] = useState(false)
74
- const [isEditing, setIsEditing] = useState(false)
75
-
76
- useEffect(() => {
77
- fetchModels()
78
- // Check if we're editing an existing assistant
79
- checkForExistingAssistant()
80
- }, [])
81
-
82
- const fetchModels = async () => {
83
- try {
84
- const baseUrl = `${window.location.protocol}//${window.location.host}`
85
- const res = await fetch(`${baseUrl}/models`)
86
-
87
- if (!res.ok) {
88
- throw new Error(`Failed to fetch models: ${res.status}`)
89
- }
90
-
91
- const data: ModelsResponse = await res.json()
92
- setModels(data.models)
93
-
94
- // Set default model if none selected
95
- if (!config.model && data.models.length > 0) {
96
- const apiModels = data.models.filter(m => m.type === 'api')
97
- const defaultModel = apiModels.length > 0 ? apiModels[0].model_name : data.models[0].model_name
98
- setConfig(prev => ({ ...prev, model: defaultModel }))
99
- }
100
- } catch (error) {
101
- console.error('Error fetching models:', error)
102
- } finally {
103
- setLoading(false)
104
- }
105
- }
106
-
107
- const checkForExistingAssistant = () => {
108
- const editConfig = localStorage.getItem('editAssistantConfig')
109
- if (editConfig) {
110
- try {
111
- const existingConfig = JSON.parse(editConfig)
112
- setConfig(existingConfig)
113
- setIsEditing(true)
114
- localStorage.removeItem('editAssistantConfig')
115
- } catch (error) {
116
- console.error('Failed to load existing assistant config:', error)
117
- }
118
- }
119
- }
120
-
121
- const saveAssistant = async () => {
122
- if (!config.name.trim() || !config.instructions.trim()) {
123
- alert('Please provide a name and instructions for your assistant.')
124
- return
125
- }
126
-
127
- setSaving(true)
128
-
129
- try {
130
- const assistant = {
131
- ...config,
132
- id: config.id || Date.now().toString(),
133
- createdAt: config.createdAt || new Date().toISOString(),
134
- updatedAt: new Date().toISOString()
135
- }
136
-
137
- // Save to localStorage
138
- const savedAssistants = JSON.parse(localStorage.getItem('savedAssistants') || '[]')
139
-
140
- if (isEditing && config.id) {
141
- const index = savedAssistants.findIndex((a: any) => a.id === config.id)
142
- if (index !== -1) {
143
- savedAssistants[index] = assistant
144
- }
145
- } else {
146
- savedAssistants.push(assistant)
147
- }
148
-
149
- localStorage.setItem('savedAssistants', JSON.stringify(savedAssistants))
150
-
151
- alert(`Assistant "${config.name}" saved successfully!`)
152
-
153
- // Reset form or navigate to assistants page
154
- setConfig({
155
- name: '',
156
- description: '',
157
- instructions: '',
158
- model: models.length > 0 ? models[0].model_name : '',
159
- temperature: 0.7,
160
- maxTokens: 1024,
161
- capabilities: []
162
- })
163
- setIsEditing(false)
164
-
165
- } catch (error) {
166
- console.error('Error saving assistant:', error)
167
- alert('Failed to save assistant. Please try again.')
168
- } finally {
169
- setSaving(false)
170
- }
171
- }
172
-
173
- const testAssistant = () => {
174
- if (!config.name.trim() || !config.instructions.trim()) {
175
- alert('Please provide a name and instructions before testing.')
176
- return
177
- }
178
-
179
- // Store current config for playground to use
180
- localStorage.setItem('testAssistantConfig', JSON.stringify({
181
- ...config,
182
- systemPrompt: config.instructions
183
- }))
184
-
185
- // Navigate to playground
186
- window.location.href = '/playground'
187
- }
188
-
189
- const systemPromptExamples = [
190
- {
191
- title: "Code Review Expert",
192
- description: "Analyzes code for quality, security, and best practices",
193
- prompt: "You are a senior software engineer specializing in code review. Analyze the provided code for:\n\n1. **Code Quality**: Structure, readability, maintainability\n2. **Best Practices**: Following language conventions and patterns\n3. **Performance**: Potential optimizations and bottlenecks\n4. **Security**: Common vulnerabilities and security issues\n5. **Testing**: Testability and edge cases\n\nProvide constructive feedback with specific examples and actionable suggestions."
194
- },
195
- {
196
- title: "Writing Assistant",
197
- description: "Helps improve academic and professional writing",
198
- prompt: "You are an experienced writing tutor. Help users improve their writing by:\n\n1. **Structure & Organization**: Clear thesis, logical flow, proper transitions\n2. **Clarity & Precision**: Eliminate ambiguity, improve word choice\n3. **Style**: Appropriate tone, engaging voice\n4. **Grammar & Mechanics**: Correct errors, improve sentence variety\n\nProvide specific feedback with examples and rewrite suggestions where helpful."
199
- },
200
- {
201
- title: "Creative Brainstorming Partner",
202
- description: "Generates creative ideas and helps develop concepts",
203
- prompt: "You are a creative brainstorming partner with expertise in idea generation. Help users by:\n\n1. **Idea Generation**: Provide diverse, creative, and original ideas\n2. **Concept Development**: Help refine and expand on initial concepts\n3. **Problem Solving**: Approach challenges from multiple angles\n4. **Innovation**: Suggest unconventional solutions and approaches\n\nBe enthusiastic, encouraging, and think outside the box."
204
- }
205
- ]
206
-
207
- if (loading) {
208
- return (
209
- <div className="min-h-screen bg-background flex items-center justify-center">
210
- <div className="text-center">
211
- <Brain className="h-8 w-8 animate-pulse mx-auto mb-4 text-blue-600" />
212
- <p>Loading models...</p>
213
- </div>
214
- </div>
215
- )
216
- }
217
-
218
- return (
219
- <div className="min-h-screen bg-background">
220
- {/* Header */}
221
- <div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
222
- <div className="max-w-6xl mx-auto p-6">
223
- <div className="flex items-center justify-between">
224
- <div className="flex items-center gap-4">
225
- <Button
226
- variant="ghost"
227
- size="sm"
228
- onClick={() => window.location.href = '/assistants'}
229
- className="flex items-center gap-2"
230
- >
231
- <ArrowLeft className="h-4 w-4" />
232
- Back
233
- </Button>
234
- <div className="flex items-center gap-3">
235
- <div className="w-8 h-8 bg-purple-600 rounded-lg flex items-center justify-center">
236
- <Bot className="h-5 w-5 text-white" />
237
- </div>
238
- <div>
239
- <h1 className="text-2xl font-bold">
240
- {isEditing ? 'Edit Assistant' : 'Create Assistant'}
241
- </h1>
242
- <p className="text-sm text-muted-foreground">
243
- Design a custom AI assistant with specialized capabilities
244
- </p>
245
- </div>
246
- </div>
247
- </div>
248
-
249
- <div className="flex items-center gap-3">
250
- <Button
251
- variant="outline"
252
- onClick={testAssistant}
253
- disabled={!config.name.trim() || !config.instructions.trim()}
254
- >
255
- <MessageSquare className="h-4 w-4 mr-2" />
256
- Test Chat
257
- </Button>
258
- <Button
259
- onClick={saveAssistant}
260
- disabled={saving || !config.name.trim() || !config.instructions.trim()}
261
- >
262
- {saving ? (
263
- <>
264
- <Zap className="h-4 w-4 mr-2 animate-spin" />
265
- Saving...
266
- </>
267
- ) : (
268
- <>
269
- <Save className="h-4 w-4 mr-2" />
270
- Save Assistant
271
- </>
272
- )}
273
- </Button>
274
- </div>
275
- </div>
276
- </div>
277
- </div>
278
-
279
- <div className="max-w-6xl mx-auto p-6 grid grid-cols-1 lg:grid-cols-2 gap-8">
280
-
281
- {/* Configuration Panel */}
282
- <div className="space-y-6">
283
-
284
- {/* Basic Information */}
285
- <Card>
286
- <CardHeader>
287
- <CardTitle className="flex items-center gap-2">
288
- <User className="h-5 w-5" />
289
- Basic Information
290
- </CardTitle>
291
- </CardHeader>
292
- <CardContent className="space-y-4">
293
- <div>
294
- <Label htmlFor="name">Assistant Name</Label>
295
- <Input
296
- id="name"
297
- value={config.name}
298
- onChange={(e) => setConfig(prev => ({ ...prev, name: e.target.value }))}
299
- placeholder="e.g., Code Review Expert, Writing Assistant"
300
- className="mt-1"
301
- />
302
- </div>
303
-
304
- <div>
305
- <Label htmlFor="description">Description</Label>
306
- <Input
307
- id="description"
308
- value={config.description}
309
- onChange={(e) => setConfig(prev => ({ ...prev, description: e.target.value }))}
310
- placeholder="Brief description of what this assistant does"
311
- className="mt-1"
312
- />
313
- </div>
314
- </CardContent>
315
- </Card>
316
-
317
- {/* Model Configuration */}
318
- <Card>
319
- <CardHeader>
320
- <CardTitle className="flex items-center gap-2">
321
- <Brain className="h-5 w-5" />
322
- Model & Parameters
323
- </CardTitle>
324
- </CardHeader>
325
- <CardContent className="space-y-4">
326
- <div>
327
- <Label htmlFor="model">AI Model</Label>
328
- <Select
329
- value={config.model}
330
- onValueChange={(value) => setConfig(prev => ({ ...prev, model: value }))}
331
- >
332
- <SelectTrigger className="mt-1">
333
- <SelectValue placeholder="Choose a model" />
334
- </SelectTrigger>
335
- <SelectContent>
336
- {models.map((model) => (
337
- <SelectItem key={model.model_name} value={model.model_name}>
338
- <div className="flex items-center gap-2">
339
- <Badge variant={model.type === 'api' ? 'default' : 'secondary'} className="text-xs">
340
- {model.type === 'api' ? 'API' : 'Local'}
341
- </Badge>
342
- {model.name}
343
- </div>
344
- </SelectItem>
345
- ))}
346
- </SelectContent>
347
- </Select>
348
- </div>
349
-
350
- <div>
351
- <Label htmlFor="temperature">
352
- Temperature: {config.temperature}
353
- </Label>
354
- <Slider
355
- id="temperature"
356
- min={0}
357
- max={1}
358
- step={0.1}
359
- value={[config.temperature]}
360
- onValueChange={([value]) => setConfig(prev => ({ ...prev, temperature: value }))}
361
- className="mt-2"
362
- />
363
- <p className="text-xs text-muted-foreground mt-1">
364
- Lower = more focused, Higher = more creative
365
- </p>
366
- </div>
367
-
368
- <div>
369
- <Label htmlFor="maxTokens">
370
- Max Tokens: {config.maxTokens}
371
- </Label>
372
- <Slider
373
- id="maxTokens"
374
- min={128}
375
- max={4096}
376
- step={128}
377
- value={[config.maxTokens]}
378
- onValueChange={([value]) => setConfig(prev => ({ ...prev, maxTokens: value }))}
379
- className="mt-2"
380
- />
381
- <p className="text-xs text-muted-foreground mt-1">
382
- Maximum length of the response
383
- </p>
384
- </div>
385
- </CardContent>
386
- </Card>
387
- </div>
388
-
389
- {/* Instructions Panel */}
390
- <div className="space-y-6">
391
-
392
- {/* System Instructions */}
393
- <Card>
394
- <CardHeader>
395
- <CardTitle className="flex items-center gap-2">
396
- <Settings className="h-5 w-5" />
397
- Instructions
398
- </CardTitle>
399
- </CardHeader>
400
- <CardContent>
401
- <div>
402
- <Label htmlFor="instructions">
403
- System Instructions
404
- </Label>
405
- <Textarea
406
- id="instructions"
407
- value={config.instructions}
408
- onChange={(e) => setConfig(prev => ({ ...prev, instructions: e.target.value }))}
409
- placeholder="Define how your assistant should behave, its role, and capabilities..."
410
- className="mt-1 min-h-[300px] text-sm"
411
- />
412
- <p className="text-xs text-muted-foreground mt-2">
413
- These instructions define your assistant's behavior, expertise, and response style.
414
- </p>
415
- </div>
416
- </CardContent>
417
- </Card>
418
-
419
- {/* Examples */}
420
- <Card>
421
- <CardHeader>
422
- <CardTitle className="flex items-center gap-2">
423
- <Sparkles className="h-5 w-5" />
424
- Example Templates
425
- </CardTitle>
426
- </CardHeader>
427
- <CardContent>
428
- <div className="space-y-3">
429
- {systemPromptExamples.map((example) => (
430
- <div
431
- key={example.title}
432
- className="p-3 border rounded-lg hover:bg-gray-50 cursor-pointer transition-colors"
433
- onClick={() => setConfig(prev => ({
434
- ...prev,
435
- instructions: example.prompt,
436
- name: prev.name || example.title,
437
- description: prev.description || example.description
438
- }))}
439
- >
440
- <div className="flex items-start justify-between">
441
- <div>
442
- <h4 className="font-medium text-sm">{example.title}</h4>
443
- <p className="text-xs text-muted-foreground mt-1">
444
- {example.description}
445
- </p>
446
- </div>
447
- <Copy className="h-4 w-4 text-muted-foreground" />
448
- </div>
449
- </div>
450
- ))}
451
- </div>
452
- </CardContent>
453
- </Card>
454
-
455
- {/* Info */}
456
- <Card className="bg-blue-50 border-blue-200">
457
- <CardContent className="pt-6">
458
- <div className="flex items-start gap-3">
459
- <Info className="h-5 w-5 text-blue-600 mt-0.5" />
460
- <div>
461
- <h3 className="font-medium text-blue-900">Tips for Great Instructions</h3>
462
- <ul className="text-sm text-blue-700 mt-2 space-y-1">
463
- <li>• Be specific about the assistant's role and expertise</li>
464
- <li>• Include examples of desired behavior</li>
465
- <li>• Define the tone and style of responses</li>
466
- <li>• Specify any constraints or guidelines</li>
467
- </ul>
468
- </div>
469
- </div>
470
- </CardContent>
471
- </Card>
472
- </div>
473
- </div>
474
- </div>
475
- )
476
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/src/pages/ChatInterface.tsx DELETED
@@ -1,334 +0,0 @@
1
- import { useState, useEffect } from 'react'
2
- import { Button } from '@/components/ui/button'
3
- import { Card, CardContent } from '@/components/ui/card'
4
- import { Badge } from '@/components/ui/badge'
5
-
6
- import { Chat } from '@/components/ui/chat'
7
- import { useChat } from '@/hooks/useChat'
8
- import {
9
- MessageSquare,
10
- Settings,
11
- Bot,
12
- Plus,
13
- Trash2,
14
- History,
15
- PanelLeftOpen,
16
- PanelLeftClose
17
- } from 'lucide-react'
18
-
19
- interface AssistantConfig {
20
- id: string
21
- name: string
22
- description: string
23
- instructions: string
24
- model: string
25
- temperature: number
26
- maxTokens: number
27
- capabilities: string[]
28
- createdAt: string
29
- }
30
-
31
- export function ChatInterface() {
32
- const [savedAssistants, setSavedAssistants] = useState<AssistantConfig[]>([])
33
- const [selectedAssistant, setSelectedAssistant] = useState<AssistantConfig | null>(null)
34
- const [showSessions, setShowSessions] = useState(false)
35
-
36
- // Chat functionality with restricted access
37
- const {
38
- sessions,
39
- currentSessionId,
40
- createNewSession,
41
- selectSession,
42
- deleteSession,
43
- messages,
44
- input,
45
- setInput,
46
- sendMessage,
47
- stopGeneration,
48
- isLoading,
49
- // Remove direct access to these - they should be controlled by assistant
50
- setSelectedModel,
51
- setSystemPrompt,
52
- setTemperature,
53
- setMaxTokens
54
- } = useChat()
55
-
56
- useEffect(() => {
57
- loadSavedAssistants()
58
-
59
- // Check if we're loading a specific assistant
60
- checkForAssistantToLoad()
61
- }, [])
62
-
63
- const loadSavedAssistants = () => {
64
- try {
65
- const assistants = JSON.parse(localStorage.getItem('savedAssistants') || '[]')
66
- setSavedAssistants(assistants)
67
-
68
- // If no assistant selected and we have assistants, select the first one
69
- if (!selectedAssistant && assistants.length > 0) {
70
- loadAssistant(assistants[0])
71
- }
72
- } catch (error) {
73
- console.error('Failed to load assistants:', error)
74
- }
75
- }
76
-
77
- const checkForAssistantToLoad = () => {
78
- const testConfig = localStorage.getItem('testAssistantConfig')
79
- const loadConfig = localStorage.getItem('loadAssistantConfig')
80
-
81
- if (testConfig) {
82
- try {
83
- const config = JSON.parse(testConfig)
84
- setSelectedAssistant(config)
85
- applyAssistantConfig(config)
86
- localStorage.removeItem('testAssistantConfig')
87
- } catch (error) {
88
- console.error('Failed to load test assistant config:', error)
89
- }
90
- } else if (loadConfig) {
91
- try {
92
- const config = JSON.parse(loadConfig)
93
- setSelectedAssistant(config)
94
- applyAssistantConfig(config)
95
- localStorage.removeItem('loadAssistantConfig')
96
- } catch (error) {
97
- console.error('Failed to load assistant config:', error)
98
- }
99
- }
100
- }
101
-
102
- const loadAssistant = (assistant: AssistantConfig) => {
103
- setSelectedAssistant(assistant)
104
- applyAssistantConfig(assistant)
105
-
106
- // Create a new session for this assistant
107
- createNewSession()
108
- }
109
-
110
- const applyAssistantConfig = (config: AssistantConfig) => {
111
- setSelectedModel(config.model)
112
- setSystemPrompt(config.instructions)
113
- setTemperature(config.temperature)
114
- setMaxTokens(config.maxTokens)
115
- }
116
-
117
- const editCurrentAssistant = () => {
118
- if (!selectedAssistant) return
119
-
120
- localStorage.setItem('editAssistantConfig', JSON.stringify(selectedAssistant))
121
- window.location.href = '/assistant-builder'
122
- }
123
-
124
- return (
125
- <div className="flex h-screen bg-background">
126
-
127
- {/* Sidebar - Assistant Selection */}
128
- <div className={`${showSessions ? 'w-80' : 'w-0'} transition-all duration-200 overflow-hidden border-r bg-background/95`}>
129
- <div className="p-4 border-b">
130
- <div className="flex items-center justify-between mb-4">
131
- <h2 className="text-lg font-semibold">My Assistants</h2>
132
- <Button
133
- size="sm"
134
- onClick={() => window.location.href = '/assistant-builder'}
135
- >
136
- <Plus className="h-4 w-4" />
137
- </Button>
138
- </div>
139
-
140
- {/* Assistant List */}
141
- <div className="space-y-2">
142
- {savedAssistants.map((assistant) => (
143
- <Card
144
- key={assistant.id}
145
- className={`cursor-pointer hover:bg-accent transition-colors ${
146
- selectedAssistant?.id === assistant.id ? 'ring-2 ring-blue-500' : ''
147
- }`}
148
- onClick={() => loadAssistant(assistant)}
149
- >
150
- <CardContent className="p-3">
151
- <div className="flex items-start gap-2">
152
- <Bot className="h-4 w-4 mt-1 text-purple-600" />
153
- <div className="flex-1 min-w-0">
154
- <h3 className="font-medium text-sm truncate">{assistant.name}</h3>
155
- <p className="text-xs text-muted-foreground truncate">
156
- {assistant.description || 'No description'}
157
- </p>
158
- <Badge variant="secondary" className="text-xs mt-1">
159
- {assistant.model}
160
- </Badge>
161
- </div>
162
- </div>
163
- </CardContent>
164
- </Card>
165
- ))}
166
-
167
- {savedAssistants.length === 0 && (
168
- <div className="text-center py-8">
169
- <Bot className="h-8 w-8 mx-auto text-muted-foreground mb-2" />
170
- <p className="text-sm text-muted-foreground">No assistants yet</p>
171
- <Button
172
- size="sm"
173
- variant="outline"
174
- className="mt-2"
175
- onClick={() => window.location.href = '/assistant-builder'}
176
- >
177
- Create One
178
- </Button>
179
- </div>
180
- )}
181
- </div>
182
- </div>
183
-
184
- {/* Chat Sessions */}
185
- <div className="p-4">
186
- <div className="flex items-center justify-between mb-3">
187
- <h3 className="text-sm font-medium">Sessions</h3>
188
- <Button size="sm" variant="ghost" onClick={createNewSession}>
189
- <Plus className="h-3 w-3" />
190
- </Button>
191
- </div>
192
-
193
- <div className="space-y-1">
194
- {sessions.map((session) => (
195
- <div
196
- key={session.id}
197
- className={`flex items-center justify-between p-2 rounded-md cursor-pointer hover:bg-accent ${
198
- currentSessionId === session.id ? 'bg-accent' : ''
199
- }`}
200
- >
201
- <div className="flex-1 min-w-0" onClick={() => selectSession(session.id)}>
202
- <p className="text-xs truncate">{session.title}</p>
203
- <p className="text-xs text-muted-foreground">
204
- {session.messages.length} messages
205
- </p>
206
- </div>
207
- <Button
208
- size="sm"
209
- variant="ghost"
210
- onClick={() => deleteSession(session.id)}
211
- className="h-6 w-6 p-0"
212
- >
213
- <Trash2 className="h-3 w-3" />
214
- </Button>
215
- </div>
216
- ))}
217
- </div>
218
- </div>
219
- </div>
220
-
221
- {/* Main Chat Area */}
222
- <div className="flex-1 flex flex-col">
223
-
224
- {/* Header */}
225
- <div className="border-b p-4">
226
- <div className="flex items-center justify-between">
227
- <div className="flex items-center gap-4">
228
- <Button
229
- variant="ghost"
230
- size="sm"
231
- onClick={() => setShowSessions(!showSessions)}
232
- >
233
- {showSessions ? (
234
- <PanelLeftClose className="h-4 w-4" />
235
- ) : (
236
- <PanelLeftOpen className="h-4 w-4" />
237
- )}
238
- </Button>
239
-
240
- {selectedAssistant ? (
241
- <div className="flex items-center gap-3">
242
- <div className="w-8 h-8 bg-purple-600 rounded-lg flex items-center justify-center">
243
- <Bot className="h-4 w-4 text-white" />
244
- </div>
245
- <div>
246
- <h1 className="font-semibold">{selectedAssistant.name}</h1>
247
- <p className="text-sm text-muted-foreground">
248
- {selectedAssistant.description}
249
- </p>
250
- </div>
251
- </div>
252
- ) : (
253
- <div>
254
- <h1 className="font-semibold">Select an Assistant</h1>
255
- <p className="text-sm text-muted-foreground">
256
- Choose an assistant to start chatting
257
- </p>
258
- </div>
259
- )}
260
- </div>
261
-
262
- <div className="flex items-center gap-2">
263
- {!selectedAssistant && savedAssistants.length === 0 && (
264
- <Button onClick={() => window.location.href = '/assistant-builder'}>
265
- <Plus className="h-4 w-4 mr-2" />
266
- Create Assistant
267
- </Button>
268
- )}
269
-
270
- {selectedAssistant && (
271
- <>
272
- <Button variant="outline" size="sm" onClick={editCurrentAssistant}>
273
- <Settings className="h-4 w-4" />
274
- </Button>
275
-
276
- <div className="flex items-center gap-2">
277
- <Badge variant="secondary" className="text-xs">
278
- {selectedAssistant.model}
279
- </Badge>
280
- <Badge variant="outline" className="text-xs">
281
- T: {selectedAssistant.temperature}
282
- </Badge>
283
- <Badge variant="outline" className="text-xs">
284
- Max: {selectedAssistant.maxTokens}
285
- </Badge>
286
- </div>
287
- </>
288
- )}
289
- </div>
290
- </div>
291
- </div>
292
-
293
- {/* Chat Interface */}
294
- <div className="flex-1 overflow-hidden">
295
- {selectedAssistant ? (
296
- <Chat
297
- messages={messages}
298
- input={input}
299
- handleInputChange={(e) => setInput(e.target.value)}
300
- handleSubmit={(e) => {
301
- e.preventDefault()
302
- sendMessage()
303
- }}
304
- isGenerating={isLoading}
305
- stop={stopGeneration}
306
- />
307
- ) : (
308
- <div className="flex items-center justify-center h-full">
309
- <div className="text-center max-w-md">
310
- <MessageSquare className="h-16 w-16 mx-auto text-muted-foreground mb-4" />
311
- <h2 className="text-xl font-semibold mb-2">Welcome to Chat Interface</h2>
312
- <p className="text-muted-foreground mb-6">
313
- Select an assistant from the sidebar to start a conversation, or create a new one.
314
- </p>
315
- <div className="flex items-center justify-center gap-3">
316
- {savedAssistants.length > 0 ? (
317
- <Button onClick={() => setShowSessions(true)}>
318
- <History className="h-4 w-4 mr-2" />
319
- Choose Assistant
320
- </Button>
321
- ) : null}
322
- <Button onClick={() => window.location.href = '/assistant-builder'}>
323
- <Plus className="h-4 w-4 mr-2" />
324
- Create Assistant
325
- </Button>
326
- </div>
327
- </div>
328
- </div>
329
- )}
330
- </div>
331
- </div>
332
- </div>
333
- )
334
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/src/pages/Home.tsx CHANGED
@@ -11,8 +11,7 @@ import {
11
  Zap,
12
  Shield,
13
  Cpu,
14
- Brain,
15
- Sparkles
16
  } from 'lucide-react'
17
 
18
  export function Home() {
@@ -54,56 +53,38 @@ export function Home() {
54
  }
55
  }
56
 
57
- const workflows = [
58
  {
59
- title: 'Quick Start',
60
- subtitle: 'New to AI assistants?',
61
- description: 'Start with pre-built templates from our community',
62
  icon: MessageSquare,
63
- href: '/community',
64
  color: 'bg-blue-600',
65
- primary: true,
66
- badge: 'Recommended',
67
- steps: ['Browse templates', 'Select one that fits', 'Start chatting immediately']
68
- },
69
- {
70
- title: 'Custom Assistant',
71
- subtitle: 'Need something specific?',
72
- description: 'Create your own AI assistant with custom instructions',
73
- icon: Bot,
74
- href: '/assistant-builder',
75
- color: 'bg-purple-600',
76
- primary: true,
77
- badge: 'Advanced',
78
- steps: ['Define your assistant', 'Set parameters', 'Test and refine']
79
  },
80
  {
81
- title: 'Quick Chat',
82
- subtitle: 'Already have assistants?',
83
- description: 'Jump directly into conversations with your saved assistants',
84
- icon: Zap,
85
- href: '/chat',
86
- color: 'bg-green-600',
87
- primary: true,
88
- badge: 'Fast',
89
- steps: ['Select assistant', 'Start conversation', 'Get instant results']
90
- }
91
- ]
92
-
93
- const supportActions = [
94
- {
95
- title: 'Manage Models',
96
- description: 'Configure AI models and settings',
97
  icon: BookOpen,
98
  href: '/models',
99
- color: 'bg-gray-600'
 
100
  },
101
  {
102
  title: 'My Assistants',
103
- description: 'View and organize your saved assistants',
104
- icon: Users,
105
  href: '/assistants',
106
- color: 'bg-orange-600'
 
 
 
 
 
 
 
 
 
107
  }
108
  ]
109
 
@@ -152,99 +133,99 @@ export function Home() {
152
  Professional AI platform for local and cloud language models.
153
  Complete privacy, advanced features, industrial-grade performance.
154
  </p>
155
-
156
- <div className="flex items-center justify-center gap-4 pt-4">
157
- <Button size="lg" onClick={() => window.location.href = '/community'} className="flex items-center gap-2">
158
- <MessageSquare className="h-5 w-5" />
159
- Get Started
160
- <ArrowRight className="h-4 w-4" />
161
- </Button>
162
-
163
- <Button size="lg" variant="outline" onClick={() => window.location.href = '/assistant-builder'}>
164
- <Bot className="h-5 w-5 mr-2" />
165
- Create Assistant
166
- </Button>
167
- </div>
168
  </div>
169
  </div>
170
  </div>
171
 
172
- <div className="max-w-6xl mx-auto px-6 py-12 space-y-12">
173
-
174
- {/* Workflow Selection */}
175
  <section>
176
  <div className="text-center mb-8">
177
- <h2 className="text-2xl font-semibold mb-3">Choose Your Path</h2>
178
  <p className="text-gray-600 max-w-2xl mx-auto">
179
- Select the workflow that best matches your experience level and needs
180
  </p>
181
  </div>
182
 
183
- {/* Primary Workflows */}
184
- <div className="grid grid-cols-1 md:grid-cols-3 gap-8 mb-8">
185
- {workflows.map((workflow) => (
186
- <Card
187
- key={workflow.title}
188
- className="hover:shadow-xl transition-all duration-300 cursor-pointer hover:-translate-y-2 border-2 border-transparent hover:border-blue-200 relative overflow-hidden"
189
- onClick={() => window.location.href = workflow.href}
190
- >
191
- <div className="absolute top-4 right-4">
192
- <Badge className="bg-white text-gray-700 border border-gray-200 shadow-sm">
193
- {workflow.badge}
194
- </Badge>
195
  </div>
196
-
197
- <CardContent className="p-8 text-center space-y-6">
198
- <div className={`w-16 h-16 ${workflow.color} rounded-2xl flex items-center justify-center mx-auto`}>
199
- <workflow.icon className="h-8 w-8 text-white" />
200
- </div>
201
-
202
- <div>
203
- <h3 className="font-bold text-xl mb-1">{workflow.title}</h3>
204
- <p className="text-sm text-blue-600 font-medium mb-3">{workflow.subtitle}</p>
205
- <p className="text-gray-600 text-sm leading-relaxed mb-4">{workflow.description}</p>
206
  </div>
207
-
208
- <div className="space-y-2 text-left">
209
- {workflow.steps.map((step, index) => (
210
- <div key={index} className="flex items-center gap-2 text-sm text-gray-600">
211
- <div className="w-5 h-5 bg-gray-100 rounded-full flex items-center justify-center text-xs font-medium">
212
- {index + 1}
213
- </div>
214
- <span>{step}</span>
215
- </div>
216
- ))}
217
- </div>
218
-
219
- <Button className="w-full" size="lg">
220
- Get Started
221
- <ArrowRight className="h-4 w-4 ml-2" />
222
- </Button>
223
- </CardContent>
224
- </Card>
225
- ))}
226
- </div>
227
-
228
- {/* Support Actions */}
229
- <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
230
- {supportActions.map((action) => (
231
- <Card
232
- key={action.title}
233
- className="hover:shadow-md transition-all duration-200 cursor-pointer hover:-translate-y-1"
234
- onClick={() => window.location.href = action.href}
235
- >
236
- <CardContent className="p-4 flex items-center gap-4">
237
- <div className={`w-12 h-12 ${action.color} rounded-lg flex items-center justify-center`}>
238
- <action.icon className="h-6 w-6 text-white" />
239
  </div>
240
- <div className="flex-1">
241
- <h3 className="font-semibold text-base">{action.title}</h3>
242
- <p className="text-sm text-gray-600">{action.description}</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  </div>
244
- <ArrowRight className="h-5 w-5 text-gray-400" />
245
- </CardContent>
246
- </Card>
247
- ))}
 
 
 
 
 
 
 
 
 
 
 
248
  </div>
249
  </section>
250
 
@@ -292,29 +273,23 @@ export function Home() {
292
  </div>
293
  </section>
294
 
295
- {/* Recommendation */}
296
- <section className="bg-gradient-to-r from-blue-50 to-purple-50 rounded-2xl p-8 border border-blue-200">
297
- <div className="text-center">
298
- <div className="w-12 h-12 bg-blue-600 rounded-xl flex items-center justify-center mx-auto mb-4">
299
- <Sparkles className="h-6 w-6 text-white" />
300
- </div>
301
- <h2 className="text-2xl font-semibold mb-4">New to AI Assistants?</h2>
302
- <p className="text-gray-600 mb-6 max-w-2xl mx-auto">
303
- We recommend starting with our <strong>Community Templates</strong> to see what's possible,
304
- then try creating your own custom assistant when you're ready.
305
- </p>
306
- <div className="flex items-center justify-center gap-4">
307
- <Button size="lg" onClick={() => window.location.href = '/community'}>
308
- <Users className="h-4 w-4 mr-2" />
309
- Browse Templates
310
- </Button>
311
- <Button size="lg" variant="outline" onClick={() => window.location.href = '/assistant-builder'}>
312
- <Bot className="h-4 w-4 mr-2" />
313
- Create Assistant
314
- </Button>
315
- </div>
316
- </div>
317
- </section>
318
  </div>
319
  </div>
320
  )
 
11
  Zap,
12
  Shield,
13
  Cpu,
14
+ Brain
 
15
  } from 'lucide-react'
16
 
17
  export function Home() {
 
53
  }
54
  }
55
 
56
+ const quickActions = [
57
  {
58
+ title: 'Start Chatting',
59
+ description: 'Begin conversations with AI models',
 
60
  icon: MessageSquare,
61
+ href: '/playground',
62
  color: 'bg-blue-600',
63
+ primary: true
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  },
65
  {
66
+ title: 'Browse Models',
67
+ description: 'Manage and load AI models',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  icon: BookOpen,
69
  href: '/models',
70
+ color: 'bg-green-600',
71
+ primary: false
72
  },
73
  {
74
  title: 'My Assistants',
75
+ description: 'Custom AI assistant configurations',
76
+ icon: Bot,
77
  href: '/assistants',
78
+ color: 'bg-purple-600',
79
+ primary: false
80
+ },
81
+ {
82
+ title: 'Community',
83
+ description: 'Discover and share templates',
84
+ icon: Users,
85
+ href: '/community',
86
+ color: 'bg-orange-600',
87
+ primary: false
88
  }
89
  ]
90
 
 
133
  Professional AI platform for local and cloud language models.
134
  Complete privacy, advanced features, industrial-grade performance.
135
  </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  </div>
137
  </div>
138
  </div>
139
 
140
+ <div className="max-w-6xl mx-auto px-6 py-12 space-y-12">
141
+
142
+ {/* Workflow Guide */}
143
  <section>
144
  <div className="text-center mb-8">
145
+ <h2 className="text-2xl font-semibold mb-3">Choose Your Starting Point</h2>
146
  <p className="text-gray-600 max-w-2xl mx-auto">
147
+ Select the path that matches your experience level and goals
148
  </p>
149
  </div>
150
 
151
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-8">
152
+ {/* New Users */}
153
+ <Card className="hover:shadow-xl transition-all duration-300 cursor-pointer hover:-translate-y-2 border-2 border-green-200 bg-green-50">
154
+ <CardContent className="p-8 text-center space-y-6">
155
+ <div className="w-16 h-16 bg-green-600 rounded-2xl flex items-center justify-center mx-auto">
156
+ <Users className="h-8 w-8 text-white" />
 
 
 
 
 
 
157
  </div>
158
+ <div>
159
+ <div className="inline-flex items-center gap-1 bg-green-100 text-green-700 px-3 py-1 rounded-full text-xs font-medium mb-3">
160
+ <span>👋</span> New to AI Assistants
 
 
 
 
 
 
 
161
  </div>
162
+ <h3 className="font-bold text-xl mb-2">Start with Templates</h3>
163
+ <p className="text-gray-600 text-sm leading-relaxed">
164
+ Explore pre-built AI assistants from our community. Perfect for learning and getting immediate results.
165
+ </p>
166
+ </div>
167
+ <Button
168
+ className="w-full bg-green-600 hover:bg-green-700"
169
+ size="lg"
170
+ onClick={() => window.location.href = '/community'}
171
+ >
172
+ Browse Templates
173
+ <ArrowRight className="h-4 w-4 ml-2" />
174
+ </Button>
175
+ </CardContent>
176
+ </Card>
177
+
178
+ {/* Experienced Users */}
179
+ <Card className="hover:shadow-xl transition-all duration-300 cursor-pointer hover:-translate-y-2 border-2 border-blue-200 bg-blue-50">
180
+ <CardContent className="p-8 text-center space-y-6">
181
+ <div className="w-16 h-16 bg-blue-600 rounded-2xl flex items-center justify-center mx-auto">
182
+ <Bot className="h-8 w-8 text-white" />
183
+ </div>
184
+ <div>
185
+ <div className="inline-flex items-center gap-1 bg-blue-100 text-blue-700 px-3 py-1 rounded-full text-xs font-medium mb-3">
186
+ <span>🎯</span> Ready to Create
 
 
 
 
 
 
 
187
  </div>
188
+ <h3 className="font-bold text-xl mb-2">Build Custom Assistant</h3>
189
+ <p className="text-gray-600 text-sm leading-relaxed">
190
+ Create your own AI assistant with custom prompts, parameters, and specialized behaviors.
191
+ </p>
192
+ </div>
193
+ <Button
194
+ className="w-full"
195
+ size="lg"
196
+ onClick={() => window.location.href = '/playground?mode=create'}
197
+ >
198
+ Create Assistant
199
+ <ArrowRight className="h-4 w-4 ml-2" />
200
+ </Button>
201
+ </CardContent>
202
+ </Card>
203
+
204
+ {/* Quick Chat */}
205
+ <Card className="hover:shadow-xl transition-all duration-300 cursor-pointer hover:-translate-y-2 border-2 border-purple-200 bg-purple-50">
206
+ <CardContent className="p-8 text-center space-y-6">
207
+ <div className="w-16 h-16 bg-purple-600 rounded-2xl flex items-center justify-center mx-auto">
208
+ <MessageSquare className="h-8 w-8 text-white" />
209
+ </div>
210
+ <div>
211
+ <div className="inline-flex items-center gap-1 bg-purple-100 text-purple-700 px-3 py-1 rounded-full text-xs font-medium mb-3">
212
+ <span>💬</span> Just Want to Chat
213
  </div>
214
+ <h3 className="font-bold text-xl mb-2">Quick Conversation</h3>
215
+ <p className="text-gray-600 text-sm leading-relaxed">
216
+ Jump straight into chatting with AI models. No setup required, start talking immediately.
217
+ </p>
218
+ </div>
219
+ <Button
220
+ className="w-full bg-purple-600 hover:bg-purple-700"
221
+ size="lg"
222
+ onClick={() => window.location.href = '/playground'}
223
+ >
224
+ Start Chatting
225
+ <ArrowRight className="h-4 w-4 ml-2" />
226
+ </Button>
227
+ </CardContent>
228
+ </Card>
229
  </div>
230
  </section>
231
 
 
273
  </div>
274
  </section>
275
 
276
+ {/* Get Started */}
277
+ <section className="text-center bg-gray-50 rounded-2xl p-8">
278
+ <h2 className="text-2xl font-semibold mb-4">Ready to Get Started?</h2>
279
+ <p className="text-gray-600 mb-6 max-w-2xl mx-auto">
280
+ Choose your preferred way to begin. Load models for local processing or start chatting with cloud APIs immediately.
281
+ </p>
282
+ <div className="flex items-center justify-center gap-4">
283
+ <Button onClick={() => window.location.href = '/playground'}>
284
+ <MessageSquare className="h-4 w-4 mr-2" />
285
+ Open Playground
286
+ </Button>
287
+ <Button variant="outline" onClick={() => window.location.href = '/assistants'}>
288
+ <Bot className="h-4 w-4 mr-2" />
289
+ Create Assistant
290
+ </Button>
291
+ </div>
292
+ </section>
 
 
 
 
 
 
293
  </div>
294
  </div>
295
  )
frontend/src/pages/Playground.tsx CHANGED
@@ -108,6 +108,7 @@ export function Playground() {
108
  const [showSaveAssistant, setShowSaveAssistant] = useState(false)
109
  const [assistantName, setAssistantName] = useState('')
110
  const [assistantDescription, setAssistantDescription] = useState('')
 
111
 
112
  // Model management state
113
  const [models, setModels] = useState<ModelInfo[]>([])
@@ -197,6 +198,12 @@ export function Playground() {
197
  fetchModels()
198
  // Check if we need to load an assistant configuration
199
  loadAssistantIfNeeded()
 
 
 
 
 
 
200
  }, [])
201
 
202
  const loadAssistantIfNeeded = () => {
@@ -461,9 +468,16 @@ export function Playground() {
461
  >
462
  {showSessions ? <PanelLeftClose className="h-4 w-4" /> : <PanelLeftOpen className="h-4 w-4" />}
463
  </Button>
464
- <MessageSquare className="h-5 w-5" />
465
- <h1 className="text-lg font-semibold">Chat Playground</h1>
466
- {currentSession && (
 
 
 
 
 
 
 
467
  <Badge variant="outline" className="text-xs">
468
  {currentSession.title.slice(0, 20)}...
469
  </Badge>
@@ -559,8 +573,8 @@ export function Playground() {
559
  />
560
  </div>
561
 
562
- {/* Settings Panel */}
563
- <div className="w-80 border-l bg-muted/30 overflow-y-auto">
564
  <div className="p-4 space-y-6">
565
  <div className="flex items-center gap-2">
566
  <Settings className="h-4 w-4" />
@@ -701,79 +715,67 @@ export function Playground() {
701
  </CardContent>
702
  </Card>
703
 
704
- {/* System Prompt */}
705
- <Card>
706
- <Collapsible
707
- open={isSystemPromptOpen}
708
- onOpenChange={setIsSystemPromptOpen}
709
- >
710
- <CardHeader>
711
- <CollapsibleTrigger asChild>
712
- <Button variant="ghost" className="w-full justify-between p-0" disabled={isLoading}>
713
- <div className="flex items-center gap-2">
714
- <MessageSquare className="h-4 w-4" />
715
- <span className="text-sm font-medium">System Prompt</span>
716
- {systemPrompt && <Badge variant="secondary" className="text-xs">Custom</Badge>}
717
- </div>
718
- <ChevronDown className={`h-4 w-4 transition-transform ${isSystemPromptOpen ? 'transform rotate-180' : ''}`} />
719
- </Button>
720
- </CollapsibleTrigger>
721
- </CardHeader>
722
- <CollapsibleContent>
723
- <CardContent className="space-y-3">
724
- {/* Preset System Prompts */}
725
- <div>
726
- <Label className="text-xs font-medium text-muted-foreground">Quick Presets</Label>
727
- <div className="grid grid-cols-1 gap-1 mt-1">
728
- {systemPromptPresets.map((preset) => (
729
- <Button
730
- key={preset.name}
731
- variant="outline"
732
- size="sm"
733
- className="h-auto p-2 text-xs justify-start"
734
- onClick={() => setSystemPrompt(preset.prompt)}
735
- disabled={isLoading}
736
- >
737
- {preset.name}
738
- </Button>
739
- ))}
740
- </div>
741
- </div>
742
-
743
- {/* Custom System Prompt */}
744
- <div>
745
- <div className="flex items-center justify-between mb-2">
746
- <Label htmlFor="system-prompt" className="text-xs font-medium">
747
- Custom System Prompt
748
- </Label>
749
- {systemPrompt && (
750
- <Button
751
- variant="ghost"
752
- size="sm"
753
- onClick={() => setSystemPrompt('')}
754
- className="h-6 px-2 text-xs"
755
- disabled={isLoading}
756
- >
757
- <RotateCcw className="h-3 w-3 mr-1" />
758
- Clear
759
- </Button>
760
- )}
761
- </div>
762
- <textarea
763
- id="system-prompt"
764
- value={systemPrompt}
765
- onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setSystemPrompt(e.target.value)}
766
- placeholder="Enter custom system prompt to define how the model should behave..."
767
- className="w-full min-h-[80px] text-xs p-2 border rounded-md bg-background"
768
  disabled={isLoading}
769
- />
770
- <p className="text-xs text-muted-foreground mt-1">
771
- System prompts define the model's role and behavior.
772
- </p>
773
- </div>
774
- </CardContent>
775
- </CollapsibleContent>
776
- </Collapsible>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
777
  </Card>
778
  </div>
779
  </div>
 
108
  const [showSaveAssistant, setShowSaveAssistant] = useState(false)
109
  const [assistantName, setAssistantName] = useState('')
110
  const [assistantDescription, setAssistantDescription] = useState('')
111
+ const [isCreateMode, setIsCreateMode] = useState(false)
112
 
113
  // Model management state
114
  const [models, setModels] = useState<ModelInfo[]>([])
 
198
  fetchModels()
199
  // Check if we need to load an assistant configuration
200
  loadAssistantIfNeeded()
201
+
202
+ // Check if we're in create mode from URL
203
+ const urlParams = new URLSearchParams(window.location.search)
204
+ if (urlParams.get('mode') === 'create') {
205
+ setIsCreateMode(true)
206
+ }
207
  }, [])
208
 
209
  const loadAssistantIfNeeded = () => {
 
468
  >
469
  {showSessions ? <PanelLeftClose className="h-4 w-4" /> : <PanelLeftOpen className="h-4 w-4" />}
470
  </Button>
471
+ {isCreateMode ? <Bot className="h-5 w-5 text-blue-600" /> : <MessageSquare className="h-5 w-5" />}
472
+ <h1 className="text-lg font-semibold">
473
+ {isCreateMode ? 'Create AI Assistant' : 'Chat Playground'}
474
+ </h1>
475
+ {isCreateMode && (
476
+ <Badge variant="default" className="text-xs bg-blue-600">
477
+ Creation Mode
478
+ </Badge>
479
+ )}
480
+ {currentSession && !isCreateMode && (
481
  <Badge variant="outline" className="text-xs">
482
  {currentSession.title.slice(0, 20)}...
483
  </Badge>
 
573
  />
574
  </div>
575
 
576
+ {/* Settings Panel - Expanded for better UX */}
577
+ <div className="w-96 border-l bg-muted/30 overflow-y-auto">
578
  <div className="p-4 space-y-6">
579
  <div className="flex items-center gap-2">
580
  <Settings className="h-4 w-4" />
 
715
  </CardContent>
716
  </Card>
717
 
718
+ {/* Assistant Configuration - Always Visible like ChatGPT */}
719
+ <Card className="border-2 border-blue-200 bg-blue-50/50">
720
+ <CardHeader>
721
+ <CardTitle className="text-sm flex items-center gap-2">
722
+ <Bot className="h-4 w-4 text-blue-600" />
723
+ Assistant Configuration
724
+ {systemPrompt && <Badge variant="default" className="text-xs bg-blue-600">Custom</Badge>}
725
+ </CardTitle>
726
+ </CardHeader>
727
+ <CardContent className="space-y-4">
728
+ {/* Quick Presets */}
729
+ <div>
730
+ <Label className="text-xs font-medium text-muted-foreground mb-2 block">Quick Presets</Label>
731
+ <div className="grid grid-cols-2 gap-2">
732
+ {systemPromptPresets.slice(0, 6).map((preset) => (
733
+ <Button
734
+ key={preset.name}
735
+ variant="outline"
736
+ size="sm"
737
+ className="h-auto p-2 text-xs justify-start bg-white hover:bg-blue-50"
738
+ onClick={() => setSystemPrompt(preset.prompt)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
739
  disabled={isLoading}
740
+ >
741
+ {preset.name}
742
+ </Button>
743
+ ))}
744
+ </div>
745
+ </div>
746
+
747
+ {/* System Prompt - Larger and More Prominent */}
748
+ <div>
749
+ <div className="flex items-center justify-between mb-3">
750
+ <Label htmlFor="system-prompt" className="text-sm font-semibold">
751
+ System Instructions
752
+ </Label>
753
+ {systemPrompt && (
754
+ <Button
755
+ variant="ghost"
756
+ size="sm"
757
+ onClick={() => setSystemPrompt('')}
758
+ className="h-7 px-2 text-xs"
759
+ disabled={isLoading}
760
+ >
761
+ <RotateCcw className="h-3 w-3 mr-1" />
762
+ Clear
763
+ </Button>
764
+ )}
765
+ </div>
766
+ <textarea
767
+ id="system-prompt"
768
+ value={systemPrompt}
769
+ onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setSystemPrompt(e.target.value)}
770
+ placeholder="Define your AI assistant's role, personality, and behavior. For example: 'You are a helpful coding assistant that explains concepts clearly and provides practical examples...'"
771
+ className="w-full min-h-[120px] text-sm p-3 border-2 border-blue-200 rounded-lg bg-white focus:border-blue-400 focus:ring-2 focus:ring-blue-100 resize-y"
772
+ disabled={isLoading}
773
+ />
774
+ <p className="text-xs text-blue-600 mt-2 bg-blue-50 p-2 rounded">
775
+ 💡 <strong>Tip:</strong> Be specific about the assistant's role, tone, and how it should respond to help users.
776
+ </p>
777
+ </div>
778
+ </CardContent>
779
  </Card>
780
  </div>
781
  </div>