feat: refactor Claude API Profiles to Claude Compatible Providers

- Rename ClaudeApiProfile to ClaudeCompatibleProvider with models[] array
- Each ProviderModel has mapsToClaudeModel field for Claude tier mapping
- Add providerType field for provider-specific icons (glm, minimax, openrouter)
- Add thinking level support for provider models in phase selectors
- Show all mapped Claude models per provider model (e.g., "Maps to Haiku, Sonnet, Opus")
- Add Bulk Replace feature to switch all phases to a provider at once
- Hide Bulk Replace button when no providers are enabled
- Fix project-level phaseModelOverrides not persisting after refresh
- Fix deleting last provider not persisting (remove empty array guard)
- Add getProviderByModelId() helper for all SDK routes
- Update all routes to pass provider config for provider models
- Update terminology from "profiles" to "providers" throughout UI
- Update documentation to reflect new provider system
This commit is contained in:
Stefan de Vogelaere
2026-01-20 19:13:34 +01:00
parent 47e6ed6a17
commit 2ceab3d65e
40 changed files with 3730 additions and 1019 deletions

View File

@@ -1,8 +1,10 @@
import { Workflow, RotateCcw } from 'lucide-react';
import { useState } from 'react';
import { Workflow, RotateCcw, Replace } from 'lucide-react';
import { cn } from '@/lib/utils';
import { useAppStore } from '@/store/app-store';
import { Button } from '@/components/ui/button';
import { PhaseModelSelector } from './phase-model-selector';
import { BulkReplaceDialog } from './bulk-replace-dialog';
import type { PhaseModelKey } from '@automaker/types';
import { DEFAULT_PHASE_MODELS } from '@automaker/types';
@@ -112,7 +114,12 @@ function PhaseGroup({
}
export function ModelDefaultsSection() {
const { resetPhaseModels } = useAppStore();
const { resetPhaseModels, claudeCompatibleProviders } = useAppStore();
const [showBulkReplace, setShowBulkReplace] = useState(false);
// Check if there are any enabled ClaudeCompatibleProviders
const hasEnabledProviders =
claudeCompatibleProviders && claudeCompatibleProviders.some((p) => p.enabled !== false);
return (
<div
@@ -139,13 +146,29 @@ export function ModelDefaultsSection() {
</p>
</div>
</div>
<Button variant="outline" size="sm" onClick={resetPhaseModels} className="gap-2">
<RotateCcw className="w-3.5 h-3.5" />
Reset to Defaults
</Button>
<div className="flex items-center gap-2">
{hasEnabledProviders && (
<Button
variant="outline"
size="sm"
onClick={() => setShowBulkReplace(true)}
className="gap-2"
>
<Replace className="w-3.5 h-3.5" />
Bulk Replace
</Button>
)}
<Button variant="outline" size="sm" onClick={resetPhaseModels} className="gap-2">
<RotateCcw className="w-3.5 h-3.5" />
Reset to Defaults
</Button>
</div>
</div>
</div>
{/* Bulk Replace Dialog */}
<BulkReplaceDialog open={showBulkReplace} onOpenChange={setShowBulkReplace} />
{/* Content */}
<div className="p-6 space-y-8">
{/* Quick Tasks */}