feat: added global llm configurations

This commit is contained in:
DESKTOP-RTLN3BA\$punk 2025-11-14 21:53:46 -08:00
parent 48fca3329b
commit d4345f75e5
24 changed files with 878 additions and 158 deletions

View file

@ -27,7 +27,7 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { useLLMConfigs, useLLMPreferences } from "@/hooks/use-llm-configs";
import { useGlobalLLMConfigs, useLLMConfigs, useLLMPreferences } from "@/hooks/use-llm-configs";
const ROLE_DESCRIPTIONS = {
long_context: {
@ -67,6 +67,12 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
error: configsError,
refreshConfigs,
} = useLLMConfigs(searchSpaceId);
const {
globalConfigs,
loading: globalConfigsLoading,
error: globalConfigsError,
refreshGlobalConfigs,
} = useGlobalLLMConfigs();
const {
preferences,
loading: preferencesLoading,
@ -164,12 +170,17 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
const isAssignmentComplete =
assignments.long_context_llm_id && assignments.fast_llm_id && assignments.strategic_llm_id;
const assignedConfigIds = Object.values(assignments).filter((id) => id !== "");
const availableConfigs = llmConfigs.filter(
(config) => config.id && config.id.toString().trim() !== ""
);
const isLoading = configsLoading || preferencesLoading;
const hasError = configsError || preferencesError;
// Combine global and custom configs
const allConfigs = [
...globalConfigs.map((config) => ({ ...config, is_global: true })),
...llmConfigs.filter((config) => config.id && config.id.toString().trim() !== ""),
];
const availableConfigs = allConfigs;
const isLoading = configsLoading || preferencesLoading || globalConfigsLoading;
const hasError = configsError || preferencesError || globalConfigsError;
return (
<div className="space-y-6">
@ -218,7 +229,9 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
{hasError && (
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertDescription>{configsError || preferencesError}</AlertDescription>
<AlertDescription>
{configsError || preferencesError || globalConfigsError}
</AlertDescription>
</Alert>
)}
@ -249,6 +262,10 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
<div className="space-y-1">
<p className="text-3xl font-bold tracking-tight">{availableConfigs.length}</p>
<p className="text-sm font-medium text-muted-foreground">Available Models</p>
<div className="flex gap-2 text-xs text-muted-foreground">
<span>🌐 {globalConfigs.length} Global</span>
<span> {llmConfigs.length} Custom</span>
</div>
</div>
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-blue-500/10">
<Bot className="h-6 w-6 text-blue-600" />
@ -422,30 +439,73 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
<SelectItem value="unassigned">
<span className="text-muted-foreground">Unassigned</span>
</SelectItem>
{availableConfigs.map((config) => (
<SelectItem key={config.id} value={config.id.toString()}>
<div className="flex items-center gap-2">
<Badge variant="outline" className="text-xs">
{config.provider}
</Badge>
<span>{config.name}</span>
<span className="text-muted-foreground">
({config.model_name})
</span>
{/* Global Configurations */}
{globalConfigs.length > 0 && (
<>
<div className="px-2 py-1.5 text-xs font-semibold text-muted-foreground">
Global Configurations
</div>
</SelectItem>
))}
{globalConfigs.map((config) => (
<SelectItem key={config.id} value={config.id.toString()}>
<div className="flex items-center gap-2">
<Badge variant="outline" className="text-xs">
{config.provider}
</Badge>
<span>{config.name}</span>
<span className="text-muted-foreground">
({config.model_name})
</span>
<Badge variant="secondary" className="text-xs">
🌐 Global
</Badge>
</div>
</SelectItem>
))}
</>
)}
{/* Custom Configurations */}
{llmConfigs.length > 0 && (
<>
<div className="px-2 py-1.5 text-xs font-semibold text-muted-foreground">
Your Configurations
</div>
{llmConfigs
.filter(
(config) => config.id && config.id.toString().trim() !== ""
)
.map((config) => (
<SelectItem key={config.id} value={config.id.toString()}>
<div className="flex items-center gap-2">
<Badge variant="outline" className="text-xs">
{config.provider}
</Badge>
<span>{config.name}</span>
<span className="text-muted-foreground">
({config.model_name})
</span>
</div>
</SelectItem>
))}
</>
)}
</SelectContent>
</Select>
</div>
{assignedConfig && (
<div className="mt-3 p-3 bg-muted/50 rounded-lg">
<div className="flex items-center gap-2 text-sm">
<div className="flex items-center gap-2 text-sm flex-wrap">
<Bot className="w-4 h-4" />
<span className="font-medium">Assigned:</span>
<Badge variant="secondary">{assignedConfig.provider}</Badge>
<span>{assignedConfig.name}</span>
{assignedConfig.is_global && (
<Badge variant="outline" className="text-xs">
🌐 Global
</Badge>
)}
</div>
<div className="text-xs text-muted-foreground mt-1">
Model: {assignedConfig.model_name}

View file

@ -51,7 +51,12 @@ import {
import { LANGUAGES } from "@/contracts/enums/languages";
import { getModelsByProvider } from "@/contracts/enums/llm-models";
import { LLM_PROVIDERS } from "@/contracts/enums/llm-providers";
import { type CreateLLMConfig, type LLMConfig, useLLMConfigs } from "@/hooks/use-llm-configs";
import {
type CreateLLMConfig,
type LLMConfig,
useGlobalLLMConfigs,
useLLMConfigs,
} from "@/hooks/use-llm-configs";
import { cn } from "@/lib/utils";
import InferenceParamsEditor from "../inference-params-editor";
@ -69,6 +74,7 @@ export function ModelConfigManager({ searchSpaceId }: ModelConfigManagerProps) {
deleteLLMConfig,
refreshConfigs,
} = useLLMConfigs(searchSpaceId);
const { globalConfigs } = useGlobalLLMConfigs();
const [isAddingNew, setIsAddingNew] = useState(false);
const [editingConfig, setEditingConfig] = useState<LLMConfig | null>(null);
const [showApiKey, setShowApiKey] = useState<Record<number, boolean>>({});
@ -224,6 +230,20 @@ export function ModelConfigManager({ searchSpaceId }: ModelConfigManagerProps) {
</Alert>
)}
{/* Global Configs Info Alert */}
{!loading && !error && globalConfigs.length > 0 && (
<Alert>
<CheckCircle className="h-4 w-4" />
<AlertDescription>
<strong>
{globalConfigs.length} global configuration{globalConfigs.length > 1 ? "s" : ""}
</strong>{" "}
available for use. You can assign them in the LLM Roles tab without adding your own API
keys.
</AlertDescription>
</Alert>
)}
{/* Loading State */}
{loading && (
<Card>
@ -310,8 +330,7 @@ export function ModelConfigManager({ searchSpaceId }: ModelConfigManagerProps) {
<div className="space-y-2 mb-6">
<h3 className="text-xl font-semibold">No Configurations Yet</h3>
<p className="text-muted-foreground max-w-sm">
Get started by adding your first LLM provider configuration to begin using the
system.
Add your own LLM provider configurations.
</p>
</div>
<Button onClick={() => setIsAddingNew(true)} size="lg">
@ -412,12 +431,14 @@ export function ModelConfigManager({ searchSpaceId }: ModelConfigManagerProps) {
{/* Metadata */}
<div className="flex flex-wrap items-center gap-4 pt-4 border-t border-border/50">
<div className="flex items-center gap-2 text-xs text-muted-foreground">
<Clock className="h-3 w-3" />
<span>
Created {new Date(config.created_at).toLocaleDateString()}
</span>
</div>
{config.created_at && (
<div className="flex items-center gap-2 text-xs text-muted-foreground">
<Clock className="h-3 w-3" />
<span>
Created {new Date(config.created_at).toLocaleDateString()}
</span>
</div>
)}
<div className="flex items-center gap-2 text-xs">
<div className="h-2 w-2 rounded-full bg-green-500"></div>
<span className="text-green-600 font-medium">Active</span>