Advanced settings
-+ No profiles yet. Create one to add environment variables, MCP servers, and skills. +
+ ); + } + + // No base and no top, but profiles exist — show the picker list directly so + // the user can select one with a single click. + if (!baseProfile && !topProfile) { + return ( + <> ++ Pick a profile +
++ Active profile +
+ ++ Pick override +
+No other profiles available.
+ )} + > + ); +} diff --git a/apps/web/src/components/cloud-agent/ProfilesListDialog.tsx b/apps/web/src/components/cloud-agent/ProfilesListDialog.tsx index 8d52a1eed2..8621eb274e 100644 --- a/apps/web/src/components/cloud-agent/ProfilesListDialog.tsx +++ b/apps/web/src/components/cloud-agent/ProfilesListDialog.tsx @@ -1,7 +1,8 @@ -/** Dialog to list and manage all environment profiles with inline editing. */ +/** Dialog to list and manage all environment profiles with list+detail layout. */ 'use client'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef } from 'react'; +import { useQuery } from '@tanstack/react-query'; import { toast } from 'sonner'; import { FolderCog, @@ -9,49 +10,64 @@ import { Plus, Loader2, AlertCircle, - ChevronDown, - ChevronRight, Eye, EyeOff, Lock, + Unlock, + Check, Trash2, Key, Terminal, Building, User, + GitBranch, + Link2Off, + Link2, + ChevronDown, } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from '@/components/ui/dialog'; + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from '@/components/ui/command'; +import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; +import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { Textarea } from '@/components/ui/textarea'; import { Switch } from '@/components/ui/switch'; -import { Checkbox } from '@/components/ui/checkbox'; -import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { InlineDeleteConfirmation } from '@/components/ui/inline-delete-confirmation'; +import { cn } from '@/lib/utils'; +import { useTRPC } from '@/lib/trpc/utils'; import { useProfiles, useCombinedProfiles, useProfile, useProfileMutations, useCombinedProfileMutations, + useRepoBindings, + useBindRepoMutation, + useUnbindRepoMutation, type ProfileSummaryWithOwner, type ProfileVar, - type ProfileOwnerType, } from '@/hooks/useCloudAgentProfiles'; +import type { ProfileOwnerType } from '@kilocode/cloud-agent-profile'; +import { McpServersTab } from './profile-editor/McpServersTab'; +import { SkillsTab } from './profile-editor/SkillsTab'; +import { ProfileAgentsTab } from './profile-editor/ProfileAgentsTab'; type ProfilesListDialogProps = { organizationId?: string; open: boolean; onOpenChange: (open: boolean) => void; onProfileSelect?: (profileId: string) => void; + openToNewProfile?: boolean; + /** If provided, the dialog opens with this profile pre-selected for editing. */ + initialSelectedProfileId?: string | null; }; export function ProfilesListDialog({ @@ -59,8 +75,9 @@ export function ProfilesListDialog({ open, onOpenChange, onProfileSelect, + openToNewProfile, + initialSelectedProfileId, }: ProfilesListDialogProps) { - // Use combined profiles when in org context const combinedQuery = useCombinedProfiles({ organizationId: organizationId ?? '', enabled: open && !!organizationId, @@ -73,43 +90,52 @@ export function ProfilesListDialog({ const isLoading = organizationId ? combinedQuery.isLoading : regularQuery.isLoading; const error = organizationId ? combinedQuery.error : regularQuery.error; - // Get profiles based on context const orgProfiles = organizationId ? (combinedQuery.data?.orgProfiles ?? []) : []; const personalProfiles = organizationId ? (combinedQuery.data?.personalProfiles ?? []) : (regularQuery.data ?? []).map(p => ({ ...p, ownerType: 'user' as const })); const effectiveDefaultId = organizationId ? combinedQuery.data?.effectiveDefaultId : null; + const allProfiles: ProfileSummaryWithOwner[] = [...orgProfiles, ...personalProfiles]; - // Use combined mutations when in org context - const combinedMutations = useCombinedProfileMutations({ - organizationId: organizationId ?? '', - }); - const regularMutations = useProfileMutations({ - organizationId: undefined, - }); + const combinedMutations = useCombinedProfileMutations({ organizationId: organizationId ?? '' }); + const regularMutations = useProfileMutations({ organizationId: undefined }); + const mutations = organizationId ? combinedMutations : regularMutations; - // State for creating new profile + const [selectedId, setSelectedId] = useState