diff --git a/ui/web/src/pages/setup/hooks/use-bootstrap-status.ts b/ui/web/src/pages/setup/hooks/use-bootstrap-status.ts index c1d7d786..b49631f0 100644 --- a/ui/web/src/pages/setup/hooks/use-bootstrap-status.ts +++ b/ui/web/src/pages/setup/hooks/use-bootstrap-status.ts @@ -17,7 +17,9 @@ export function useBootstrapStatus() { if (loading) return { needsSetup: false, currentStep: "complete" as SetupStep }; // A provider is "configured" if enabled + has an API key set (masked as "***") - const hasProvider = providers.some((p) => p.enabled && p.api_key === "***"); + // Claude CLI and ChatGPT OAuth don't require API keys — check type instead + const hasProvider = providers.some((p) => p.enabled && + (p.api_key === "***" || p.provider_type === "claude_cli" || p.provider_type === "chatgpt_oauth")); const hasAgent = agents.length > 0; if (!hasProvider) return { needsSetup: true, currentStep: 1 as SetupStep }; diff --git a/ui/web/src/pages/setup/setup-page.tsx b/ui/web/src/pages/setup/setup-page.tsx index 5e356460..a12d7971 100644 --- a/ui/web/src/pages/setup/setup-page.tsx +++ b/ui/web/src/pages/setup/setup-page.tsx @@ -52,7 +52,8 @@ export function SetupPage() { if (showComplete) { completedSteps.push(1, 2, 3, 4); } // For resuming: find existing provider/agent from server data - const activeProvider = createdProvider ?? providers.find((p) => p.enabled && p.api_key === "***") ?? null; + const activeProvider = createdProvider ?? providers.find((p) => p.enabled && + (p.api_key === "***" || p.provider_type === "claude_cli" || p.provider_type === "chatgpt_oauth")) ?? null; const activeAgent = createdAgent ?? agents[0] ?? null; const handleFinish = () => setShowComplete(true); diff --git a/ui/web/src/pages/setup/step-provider.tsx b/ui/web/src/pages/setup/step-provider.tsx index 42151486..dae45d4d 100644 --- a/ui/web/src/pages/setup/step-provider.tsx +++ b/ui/web/src/pages/setup/step-provider.tsx @@ -14,6 +14,7 @@ import { } from "@/components/ui/select"; import { PROVIDER_TYPES } from "@/constants/providers"; import { useProviders } from "@/pages/providers/hooks/use-providers"; +import { CLISection } from "@/pages/providers/provider-cli-section"; import { slugify } from "@/lib/slug"; import type { ProviderData } from "@/types/provider"; @@ -31,11 +32,14 @@ export function StepProvider({ onComplete }: StepProviderProps) { const [loading, setLoading] = useState(false); const [error, setError] = useState(""); + const isCLI = providerType === "claude_cli"; + const handleTypeChange = (value: string) => { setProviderType(value); const preset = PROVIDER_TYPES.find((t) => t.value === value); setName(slugify(value)); setApiBase(preset?.apiBase || ""); + setApiKey(""); setError(""); }; @@ -47,7 +51,7 @@ export function StepProvider({ onComplete }: StepProviderProps) { ); const handleCreate = async () => { - if (!apiKey.trim()) { setError("API key is required"); return; } + if (!isCLI && !apiKey.trim()) { setError("API key is required"); return; } setLoading(true); setError(""); try { @@ -55,7 +59,7 @@ export function StepProvider({ onComplete }: StepProviderProps) { name: name.trim(), provider_type: providerType, api_base: apiBase.trim() || undefined, - api_key: apiKey.trim(), + api_key: isCLI ? undefined : apiKey.trim(), enabled: true, }) as ProviderData; onComplete(provider); @@ -73,7 +77,9 @@ export function StepProvider({ onComplete }: StepProviderProps) {
- Connect to an AI provider to power your agents. You'll need an API key. + {isCLI + ? "Connect using your local Claude CLI installation. No API key needed." + : "Connect to an AI provider to power your agents. You'll need an API key."}
{error}
}