Profile cleanup (#611)

* remove redundant boilerplate

* migrate

* clippy

* frontend fixes

* fmt

* fix

* update shared types

* fmt
This commit is contained in:
Louis Knight-Webb
2025-09-02 21:25:37 +01:00
committed by GitHub
parent 57c5b4d687
commit 5ca32b50de
32 changed files with 220 additions and 826 deletions

View File

@@ -24,7 +24,7 @@ import {
import { Label } from '@/components/ui/label';
import { Input } from '@/components/ui/input';
import { Sparkles, Code, ChevronDown, HandMetal } from 'lucide-react';
import { EditorType } from 'shared/types';
import { BaseCodingAgent, EditorType } from 'shared/types';
import type { ExecutorProfileId } from 'shared/types';
import { useUserSystem } from '@/components/config-provider';
@@ -40,7 +40,7 @@ interface OnboardingDialogProps {
export function OnboardingDialog({ open, onComplete }: OnboardingDialogProps) {
const [profile, setProfile] = useState<ExecutorProfileId>({
executor: 'CLAUDE_CODE',
executor: BaseCodingAgent.CLAUDE_CODE,
variant: null,
});
const [editorType, setEditorType] = useState<EditorType>(EditorType.VS_CODE);
@@ -86,8 +86,8 @@ export function OnboardingDialog({ open, onComplete }: OnboardingDialogProps) {
<div className="flex gap-2">
<Select
value={profile.executor}
onValueChange={(value) =>
setProfile({ executor: value, variant: null })
onValueChange={(v) =>
setProfile({ executor: v as BaseCodingAgent, variant: null })
}
>
<SelectTrigger id="profile" className="flex-1">
@@ -95,11 +95,13 @@ export function OnboardingDialog({ open, onComplete }: OnboardingDialogProps) {
</SelectTrigger>
<SelectContent>
{profiles &&
Object.keys(profiles).map((profile) => (
<SelectItem key={profile} value={profile}>
{profile}
</SelectItem>
))}
(Object.keys(profiles) as BaseCodingAgent[]).map(
(agent) => (
<SelectItem key={agent} value={agent}>
{agent}
</SelectItem>
)
)}
</SelectContent>
</Select>

View File

@@ -13,13 +13,13 @@ import {
type UserSystemInfo,
CheckTokenResponse,
} from 'shared/types';
import type { ExecutorProfile } from 'shared/types';
import type { ExecutorConfig } from 'shared/types';
import { configApi, githubAuthApi } from '../lib/api';
interface UserSystemState {
config: Config | null;
environment: Environment | null;
profiles: Record<string, ExecutorProfile> | null;
profiles: Record<string, ExecutorConfig> | null;
}
interface UserSystemContextType {
@@ -34,9 +34,9 @@ interface UserSystemContextType {
// System data access
environment: Environment | null;
profiles: Record<string, ExecutorProfile> | null;
profiles: Record<string, ExecutorConfig> | null;
setEnvironment: (env: Environment | null) => void;
setProfiles: (profiles: Record<string, ExecutorProfile> | null) => void;
setProfiles: (profiles: Record<string, ExecutorConfig> | null) => void;
// Reload system data
reloadSystem: () => Promise<void>;
@@ -60,7 +60,7 @@ export function UserSystemProvider({ children }: UserSystemProviderProps) {
const [environment, setEnvironment] = useState<Environment | null>(null);
const [profiles, setProfiles] = useState<Record<
string,
ExecutorProfile
ExecutorConfig
> | null>(null);
const [loading, setLoading] = useState(true);
const [githubTokenInvalid, setGithubTokenInvalid] = useState(false);
@@ -72,7 +72,7 @@ export function UserSystemProvider({ children }: UserSystemProviderProps) {
setConfig(userSystemInfo.config);
setEnvironment(userSystemInfo.environment);
setProfiles(
userSystemInfo.executors as Record<string, ExecutorProfile> | null
userSystemInfo.executors as Record<string, ExecutorConfig> | null
);
} catch (err) {
console.error('Error loading user system:', err);
@@ -148,7 +148,7 @@ export function UserSystemProvider({ children }: UserSystemProviderProps) {
setConfig(userSystemInfo.config);
setEnvironment(userSystemInfo.environment);
setProfiles(
userSystemInfo.executors as Record<string, ExecutorProfile> | null
userSystemInfo.executors as Record<string, ExecutorConfig> | null
);
} catch (err) {
console.error('Error reloading user system:', err);

View File

@@ -66,7 +66,7 @@ export function AttemptHeaderCard({
</p>
<p>
<span className="text-secondary-foreground">Profile &middot; </span>
{selectedAttempt?.profile}
{selectedAttempt?.executor}
</p>
{selectedAttempt?.branch && (
<p className="max-w-30 truncate">

View File

@@ -187,7 +187,7 @@ export function TaskDetailsPanel({
task={task}
projectId={projectId}
selectedAttemptId={selectedAttempt?.id}
selectedAttemptProfile={selectedAttempt?.profile}
selectedAttemptProfile={selectedAttempt?.executor}
/>
</main>
</div>
@@ -226,7 +226,7 @@ export function TaskDetailsPanel({
task={task}
projectId={projectId}
selectedAttemptId={selectedAttempt?.id}
selectedAttemptProfile={selectedAttempt?.profile}
selectedAttemptProfile={selectedAttempt?.executor}
/>
</>
)}

View File

@@ -7,8 +7,8 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu.tsx';
import type { GitBranch, Task } from 'shared/types';
import type { ExecutorProfile } from 'shared/types';
import type { BaseCodingAgent, GitBranch, Task } from 'shared/types';
import type { ExecutorConfig } from 'shared/types';
import type { ExecutorProfileId } from 'shared/types';
import type { TaskAttempt } from 'shared/types';
import { useAttemptCreation } from '@/hooks/useAttemptCreation';
@@ -35,7 +35,7 @@ type Props = {
setIsInCreateAttemptMode: Dispatch<SetStateAction<boolean>>;
setCreateAttemptBranch: Dispatch<SetStateAction<string | null>>;
setSelectedProfile: Dispatch<SetStateAction<ExecutorProfileId | null>>;
availableProfiles: Record<string, ExecutorProfile> | null;
availableProfiles: Record<string, ExecutorConfig> | null;
selectedAttempt: TaskAttempt | null;
};
@@ -213,7 +213,7 @@ function CreateAttempt({
key={profileKey}
onClick={() => {
setSelectedProfile({
executor: profileKey,
executor: profileKey as BaseCodingAgent,
variant: null,
});
}}

View File

@@ -390,7 +390,7 @@ function CurrentAttempt({
<div className="text-xs font-medium text-muted-foreground uppercase tracking-wide mb-1">
Profile
</div>
<div className="text-sm font-medium">{selectedAttempt.profile}</div>
<div className="text-sm font-medium">{selectedAttempt.executor}</div>
</div>
<div className="min-w-0">
@@ -678,7 +678,7 @@ function CurrentAttempt({
{new Date(attempt.created_at).toLocaleTimeString()}
</span>
<span className="text-xs text-muted-foreground">
{attempt.profile || 'Base Agent'}
{attempt.executor || 'Base Agent'}
</span>
</div>
</DropdownMenuItem>

View File

@@ -1,6 +1,6 @@
import { useCallback, useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import type { ExecutorProfile } from 'shared/types';
import type { ExecutorConfig } from 'shared/types';
// Define available keyboard shortcuts
export interface KeyboardShortcut {
@@ -273,7 +273,7 @@ export function useVariantCyclingShortcut({
setSelectedVariant,
setIsAnimating,
}: {
currentProfile: ExecutorProfile | null | undefined;
currentProfile: ExecutorConfig | null | undefined;
selectedVariant: string | null;
setSelectedVariant: (variant: string | null) => void;
setIsAnimating: (animating: boolean) => void;

View File

@@ -19,7 +19,7 @@ import { Alert, AlertDescription } from '@/components/ui/alert';
import { JSONEditor } from '@/components/ui/json-editor';
import { Loader2 } from 'lucide-react';
import { McpConfig } from 'shared/types';
import type { ExecutorProfile } from 'shared/types';
import type { BaseCodingAgent, ExecutorConfig } from 'shared/types';
import { useUserSystem } from '@/components/config-provider';
import { mcpServersApi } from '../lib/api';
import { McpConfigStrategyGeneral } from '../lib/mcp-strategies';
@@ -30,8 +30,9 @@ export function McpServers() {
const [mcpConfig, setMcpConfig] = useState<McpConfig | null>(null);
const [mcpError, setMcpError] = useState<string | null>(null);
const [mcpLoading, setMcpLoading] = useState(true);
const [selectedProfile, setSelectedProfile] =
useState<ExecutorProfile | null>(null);
const [selectedProfile, setSelectedProfile] = useState<ExecutorConfig | null>(
null
);
const [mcpApplying, setMcpApplying] = useState(false);
const [mcpConfigPath, setMcpConfigPath] = useState<string>('');
const [success, setSuccess] = useState(false);
@@ -52,7 +53,7 @@ export function McpServers() {
// Load existing MCP configuration when selected profile changes
useEffect(() => {
const loadMcpServersForProfile = async (profile: ExecutorProfile) => {
const loadMcpServersForProfile = async (profile: ExecutorConfig) => {
// Reset state when loading
setMcpLoading(true);
setMcpError(null);
@@ -70,7 +71,7 @@ export function McpServers() {
}
const result = await mcpServersApi.load({
profile: profileKey,
executor: profileKey as BaseCodingAgent,
});
// Store the McpConfig from backend
setMcpConfig(result.mcp_config);
@@ -171,7 +172,7 @@ export function McpServers() {
await mcpServersApi.save(
{
profile: selectedProfileKey,
executor: selectedProfileKey as BaseCodingAgent,
},
{ servers: mcpServersConfig }
);

View File

@@ -27,7 +27,7 @@ import { Input } from '@/components/ui/input';
import { JSONEditor } from '@/components/ui/json-editor';
import { ChevronDown, Key, Loader2, Volume2 } from 'lucide-react';
import { ThemeMode, EditorType, SoundFile } from 'shared/types';
import type { ExecutorProfileId } from 'shared/types';
import type { BaseCodingAgent, ExecutorProfileId } from 'shared/types';
import { toPrettyCase } from '@/utils/string';
import { useTheme } from '@/components/theme-provider';
@@ -279,7 +279,7 @@ export function Settings() {
value={config.executor_profile?.executor ?? ''}
onValueChange={(value: string) => {
const newProfile: ExecutorProfileId = {
executor: value,
executor: value as BaseCodingAgent,
variant: null,
};
updateConfig({