|
|
import { Button } from '@/components/ui/button' |
|
|
import { Label } from '@/components/ui/label' |
|
|
import { Badge } from '@/components/ui/badge' |
|
|
import { |
|
|
Select, |
|
|
SelectContent, |
|
|
SelectGroup, |
|
|
SelectItem, |
|
|
SelectLabel, |
|
|
SelectTrigger, |
|
|
SelectValue, |
|
|
} from '@/components/ui/select' |
|
|
import { Bot, Plus, X, User, Bookmark, Save, Settings } from 'lucide-react' |
|
|
|
|
|
interface SavedAssistant { |
|
|
id: string |
|
|
name: string |
|
|
systemPrompt: string |
|
|
temperature: number |
|
|
maxTokens: number |
|
|
model?: string |
|
|
ragEnabled?: boolean |
|
|
retrievalCount?: number |
|
|
createdAt: string |
|
|
} |
|
|
|
|
|
interface SystemPromptPreset { |
|
|
name: string |
|
|
prompt: string |
|
|
} |
|
|
|
|
|
interface SelectedAssistant { |
|
|
id: string |
|
|
name: string |
|
|
type: 'user'|'template'|'new' |
|
|
originalTemplate?: string |
|
|
} |
|
|
|
|
|
interface AssistantSelectorProps { |
|
|
savedAssistants: SavedAssistant[] |
|
|
loadSavedAssistant: (id: string) => void |
|
|
openSaveDialog: () => void |
|
|
presets: SystemPromptPreset[] |
|
|
onPresetSelect: (presetName: string) => void |
|
|
isLoading: boolean |
|
|
selectedAssistant: SelectedAssistant | null |
|
|
createNewAssistant: () => void |
|
|
clearCurrentAssistant: () => void |
|
|
openRenameDialog: () => void |
|
|
systemPrompt: string |
|
|
} |
|
|
|
|
|
export function AssistantSelector({ |
|
|
savedAssistants, |
|
|
loadSavedAssistant, |
|
|
openSaveDialog, |
|
|
presets, |
|
|
onPresetSelect, |
|
|
isLoading, |
|
|
selectedAssistant, |
|
|
createNewAssistant, |
|
|
clearCurrentAssistant, |
|
|
openRenameDialog, |
|
|
systemPrompt |
|
|
}: AssistantSelectorProps) { |
|
|
const handleAssistantSelect = (value: string) => { |
|
|
if (value === 'create_new') { |
|
|
createNewAssistant() |
|
|
} else if (value === 'clear_current') { |
|
|
clearCurrentAssistant() |
|
|
} else if (value.startsWith('user_')) { |
|
|
|
|
|
const assistantId = value.replace('user_', '') |
|
|
loadSavedAssistant(assistantId) |
|
|
} else { |
|
|
|
|
|
onPresetSelect(value) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const getCurrentValue = () => { |
|
|
if (!selectedAssistant) return '' |
|
|
|
|
|
if (selectedAssistant.type === 'user') { |
|
|
return `user_${selectedAssistant.id}` |
|
|
} else if (selectedAssistant.type === 'new') { |
|
|
return 'new_assistant' |
|
|
} else { |
|
|
return selectedAssistant.id |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const getAssistantBadge = (type: 'user'|'template'|'new') => { |
|
|
switch (type) { |
|
|
case 'user': |
|
|
return { variant: 'secondary' as const, text: 'Mine' } |
|
|
case 'template': |
|
|
return { variant: 'outline' as const, text: 'Template' } |
|
|
case 'new': |
|
|
return { variant: 'default' as const, text: 'New', className: 'bg-green-100 text-green-700' } |
|
|
} |
|
|
} |
|
|
|
|
|
const totalAssistants = savedAssistants.length + presets.length |
|
|
|
|
|
return ( |
|
|
<div className="space-y-4"> |
|
|
<div> |
|
|
<Label className="text-sm font-medium mb-2 block">Load Assistant</Label> |
|
|
<Select value={getCurrentValue()} onValueChange={handleAssistantSelect}> |
|
|
<SelectTrigger className="w-full"> |
|
|
<SelectValue placeholder={`Choose assistant (${totalAssistants} available)`}> |
|
|
{selectedAssistant ? ( |
|
|
<div className="flex items-center gap-2"> |
|
|
<Bot className="h-4 w-4" /> |
|
|
<span>{selectedAssistant.name}</span> |
|
|
{selectedAssistant.originalTemplate && ( |
|
|
<span className="text-xs text-muted-foreground"> |
|
|
(from {selectedAssistant.originalTemplate}) |
|
|
</span> |
|
|
)} |
|
|
<Badge |
|
|
variant={getAssistantBadge(selectedAssistant.type).variant} |
|
|
className={`text-xs ml-auto ${getAssistantBadge(selectedAssistant.type).className || ''}`} |
|
|
> |
|
|
{getAssistantBadge(selectedAssistant.type).text} |
|
|
</Badge> |
|
|
</div> |
|
|
) : ( |
|
|
<div className="flex items-center gap-2"> |
|
|
<Bot className="h-4 w-4" /> |
|
|
<span>Choose assistant</span> |
|
|
<Badge variant="outline" className="text-xs ml-auto"> |
|
|
{totalAssistants} |
|
|
</Badge> |
|
|
</div> |
|
|
)} |
|
|
</SelectValue> |
|
|
</SelectTrigger> |
|
|
<SelectContent> |
|
|
{/* Actions Section */} |
|
|
<SelectGroup> |
|
|
<SelectLabel className="flex items-center gap-2 text-sm font-medium"> |
|
|
<Plus className="h-4 w-4" /> |
|
|
Actions |
|
|
</SelectLabel> |
|
|
<SelectItem value="create_new"> |
|
|
<div className="flex items-center gap-2 w-full"> |
|
|
<Plus className="h-4 w-4 text-green-600" /> |
|
|
<span className="truncate flex-1">Create New Assistant</span> |
|
|
<Badge variant="default" className="text-xs bg-green-100 text-green-700">New</Badge> |
|
|
</div> |
|
|
</SelectItem> |
|
|
{selectedAssistant && ( |
|
|
<SelectItem value="clear_current"> |
|
|
<div className="flex items-center gap-2 w-full"> |
|
|
<X className="h-4 w-4 text-gray-600" /> |
|
|
<span className="truncate flex-1">Clear Current</span> |
|
|
<Badge variant="outline" className="text-xs">Clear</Badge> |
|
|
</div> |
|
|
</SelectItem> |
|
|
)} |
|
|
</SelectGroup> |
|
|
|
|
|
{/* My Assistants Section */} |
|
|
{savedAssistants.length > 0 && ( |
|
|
<SelectGroup> |
|
|
<SelectLabel className="flex items-center gap-2 text-sm font-medium"> |
|
|
<User className="h-4 w-4" /> |
|
|
My Assistants ({savedAssistants.length}) |
|
|
</SelectLabel> |
|
|
{savedAssistants.map((assistant) => ( |
|
|
<SelectItem key={`user_${assistant.id}`} value={`user_${assistant.id}`}> |
|
|
<div className="flex items-center gap-2 w-full"> |
|
|
<Bot className="h-4 w-4 text-blue-600" /> |
|
|
<span className="truncate flex-1">{assistant.name}</span> |
|
|
<Badge variant="secondary" className="text-xs">Mine</Badge> |
|
|
</div> |
|
|
</SelectItem> |
|
|
))} |
|
|
</SelectGroup> |
|
|
)} |
|
|
|
|
|
{/* Templates Section */} |
|
|
{presets.length > 0 && ( |
|
|
<SelectGroup> |
|
|
<SelectLabel className="flex items-center gap-2 text-sm font-medium"> |
|
|
<Bookmark className="h-4 w-4" /> |
|
|
Templates ({presets.length}) |
|
|
</SelectLabel> |
|
|
{presets.map((preset) => ( |
|
|
<SelectItem key={preset.name} value={preset.name}> |
|
|
<div className="flex items-center gap-2 w-full"> |
|
|
<Bot className="h-4 w-4 text-green-600" /> |
|
|
<span className="truncate flex-1">{preset.name}</span> |
|
|
<Badge variant="outline" className="text-xs">Template</Badge> |
|
|
</div> |
|
|
</SelectItem> |
|
|
))} |
|
|
</SelectGroup> |
|
|
)} |
|
|
|
|
|
{/* Empty State */} |
|
|
{totalAssistants === 0 && ( |
|
|
<div className="p-2 text-sm text-muted-foreground text-center"> |
|
|
No assistants available |
|
|
</div> |
|
|
)} |
|
|
</SelectContent> |
|
|
</Select> |
|
|
</div> |
|
|
|
|
|
{/* Rename Assistant */} |
|
|
{selectedAssistant && selectedAssistant.type !== 'template' && ( |
|
|
<Button |
|
|
onClick={openRenameDialog} |
|
|
size="sm" |
|
|
variant="ghost" |
|
|
className="w-full justify-start" |
|
|
disabled={isLoading} |
|
|
> |
|
|
<Settings className="h-4 w-4 mr-2" /> |
|
|
Rename |
|
|
</Button> |
|
|
)} |
|
|
|
|
|
{/* Save Current Configuration */} |
|
|
<Button |
|
|
onClick={openSaveDialog} |
|
|
size="sm" |
|
|
variant="outline" |
|
|
className="w-full" |
|
|
disabled={isLoading || !systemPrompt.trim()} |
|
|
> |
|
|
<Save className="h-4 w-4 mr-2" /> |
|
|
Save Assistant |
|
|
</Button> |
|
|
</div> |
|
|
) |
|
|
} |
|
|
|