Spaces:
Sleeping
Sleeping
| import { useState } from "react"; | |
| import { Plus, Trash2, Server } from "lucide-react"; | |
| import { Button } from "@/components/ui/button"; | |
| import { Input } from "@/components/ui/input"; | |
| import { Label } from "@/components/ui/label"; | |
| import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"; | |
| import { | |
| Dialog, | |
| DialogContent, | |
| DialogHeader, | |
| DialogTitle, | |
| DialogFooter, | |
| DialogDescription, | |
| } from "@/components/ui/dialog"; | |
| import { useConfigStore } from "@/stores/configStore"; | |
| import type { LLMProviderConfig as ProviderConfig } from "@/types/execution"; | |
| export function LLMProviderConfigComponent() { | |
| const { llmProviders, addProvider, deleteProvider } = useConfigStore(); | |
| const [dialogOpen, setDialogOpen] = useState(false); | |
| const [form, setForm] = useState<ProviderConfig>({ | |
| provider_id: "", | |
| name: "", | |
| base_url: "", | |
| api_key: "", | |
| default_model: "", | |
| }); | |
| const handleAdd = async () => { | |
| if (!form.provider_id || !form.name || !form.base_url || !form.api_key) return; | |
| await addProvider(form); | |
| setDialogOpen(false); | |
| setForm({ provider_id: "", name: "", base_url: "", api_key: "", default_model: "" }); | |
| }; | |
| return ( | |
| <Card> | |
| <CardHeader> | |
| <div className="flex items-center justify-between"> | |
| <div> | |
| <CardTitle className="text-lg">LLM Providers</CardTitle> | |
| <CardDescription>Configure API endpoints for LLM models.</CardDescription> | |
| </div> | |
| <Button size="sm" onClick={() => setDialogOpen(true)} className="gap-1"> | |
| <Plus className="h-3.5 w-3.5" /> | |
| Add Provider | |
| </Button> | |
| </div> | |
| </CardHeader> | |
| <CardContent> | |
| {llmProviders.length === 0 ? ( | |
| <p className="text-sm text-muted-foreground text-center py-6"> | |
| No LLM providers configured. Add one to enable real LLM execution. | |
| </p> | |
| ) : ( | |
| <div className="space-y-2"> | |
| {llmProviders.map((p) => ( | |
| <div | |
| key={p.provider_id} | |
| className="flex items-center gap-3 rounded-md border p-3" | |
| > | |
| <Server className="h-4 w-4 text-muted-foreground" /> | |
| <div className="flex-1"> | |
| <div className="text-sm font-medium">{p.name}</div> | |
| <div className="text-xs text-muted-foreground"> | |
| {p.base_url} {p.default_model && `- ${p.default_model}`} | |
| </div> | |
| </div> | |
| <Button | |
| variant="ghost" | |
| size="icon" | |
| className="h-8 w-8 text-destructive" | |
| onClick={() => deleteProvider(p.provider_id)} | |
| > | |
| <Trash2 className="h-3.5 w-3.5" /> | |
| </Button> | |
| </div> | |
| ))} | |
| </div> | |
| )} | |
| </CardContent> | |
| <Dialog open={dialogOpen} onOpenChange={setDialogOpen}> | |
| <DialogContent> | |
| <DialogHeader> | |
| <DialogTitle>Add LLM Provider</DialogTitle> | |
| <DialogDescription>Configure a new LLM API endpoint.</DialogDescription> | |
| </DialogHeader> | |
| <div className="grid gap-4 py-4"> | |
| <div className="grid grid-cols-2 gap-3"> | |
| <div className="space-y-2"> | |
| <Label>Provider ID</Label> | |
| <Input | |
| placeholder="openai" | |
| value={form.provider_id} | |
| onChange={(e) => setForm({ ...form, provider_id: e.target.value })} | |
| /> | |
| </div> | |
| <div className="space-y-2"> | |
| <Label>Display Name</Label> | |
| <Input | |
| placeholder="OpenAI" | |
| value={form.name} | |
| onChange={(e) => setForm({ ...form, name: e.target.value })} | |
| /> | |
| </div> | |
| </div> | |
| <div className="space-y-2"> | |
| <Label>Base URL</Label> | |
| <Input | |
| placeholder="https://api.openai.com/v1" | |
| value={form.base_url} | |
| onChange={(e) => setForm({ ...form, base_url: e.target.value })} | |
| /> | |
| </div> | |
| <div className="space-y-2"> | |
| <Label>API Key (use $ENV_VAR for env variables)</Label> | |
| <Input | |
| placeholder="$OPENAI_API_KEY" | |
| value={form.api_key} | |
| onChange={(e) => setForm({ ...form, api_key: e.target.value })} | |
| /> | |
| </div> | |
| <div className="space-y-2"> | |
| <Label>Default Model</Label> | |
| <Input | |
| placeholder="gpt-4" | |
| value={form.default_model || ""} | |
| onChange={(e) => setForm({ ...form, default_model: e.target.value || null })} | |
| /> | |
| </div> | |
| </div> | |
| <DialogFooter> | |
| <Button variant="outline" onClick={() => setDialogOpen(false)}> | |
| Cancel | |
| </Button> | |
| <Button onClick={handleAdd}>Add Provider</Button> | |
| </DialogFooter> | |
| </DialogContent> | |
| </Dialog> | |
| </Card> | |
| ); | |
| } | |