diff --git a/ui/src/components/OnboardingWizard.tsx b/ui/src/components/OnboardingWizard.tsx index 9d368f73..017736b2 100644 --- a/ui/src/components/OnboardingWizard.tsx +++ b/ui/src/components/OnboardingWizard.tsx @@ -89,6 +89,9 @@ export function OnboardingWizard() { useState(null); const [adapterEnvError, setAdapterEnvError] = useState(null); const [adapterEnvLoading, setAdapterEnvLoading] = useState(false); + const [forceUnsetAnthropicApiKey, setForceUnsetAnthropicApiKey] = + useState(false); + const [unsetAnthropicLoading, setUnsetAnthropicLoading] = useState(false); // Step 3 const [taskTitle, setTaskTitle] = useState("Create your CEO HEARTBEAT.md"); @@ -159,6 +162,15 @@ export function OnboardingWizard() { }, [step, adapterType, cwd, model, command, args, url]); const selectedModel = (adapterModels ?? []).find((m) => m.id === model); + const hasAnthropicApiKeyOverrideCheck = + adapterEnvResult?.checks.some( + (check) => + check.code === "claude_anthropic_api_key_overrides_subscription" + ) ?? false; + const shouldSuggestUnsetAnthropicApiKey = + adapterType === "claude_local" && + adapterEnvResult?.status === "fail" && + hasAnthropicApiKeyOverrideCheck; function reset() { setStep(1); @@ -176,6 +188,8 @@ export function OnboardingWizard() { setAdapterEnvResult(null); setAdapterEnvError(null); setAdapterEnvLoading(false); + setForceUnsetAnthropicApiKey(false); + setUnsetAnthropicLoading(false); setTaskTitle("Create your CEO HEARTBEAT.md"); setTaskDescription(DEFAULT_TASK_DESCRIPTION); setCreatedCompanyId(null); @@ -191,7 +205,7 @@ export function OnboardingWizard() { function buildAdapterConfig(): Record { const adapter = getUIAdapter(adapterType); - return adapter.buildAdapterConfig({ + const config = adapter.buildAdapterConfig({ ...defaultCreateValues, adapterType, cwd, @@ -208,9 +222,22 @@ export function OnboardingWizard() { ? DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX : defaultCreateValues.dangerouslyBypassSandbox }); + if (adapterType === "claude_local" && forceUnsetAnthropicApiKey) { + const env = + typeof config.env === "object" && + config.env !== null && + !Array.isArray(config.env) + ? { ...(config.env as Record) } + : {}; + env.ANTHROPIC_API_KEY = { type: "plain", value: "" }; + config.env = env; + } + return config; } - async function runAdapterEnvironmentTest(): Promise { + async function runAdapterEnvironmentTest( + adapterConfigOverride?: Record + ): Promise { if (!createdCompanyId) { setAdapterEnvError( "Create or select a company before testing adapter environment." @@ -224,7 +251,7 @@ export function OnboardingWizard() { createdCompanyId, adapterType, { - adapterConfig: buildAdapterConfig() + adapterConfig: adapterConfigOverride ?? buildAdapterConfig() } ); setAdapterEnvResult(result); @@ -311,6 +338,55 @@ export function OnboardingWizard() { } } + async function handleUnsetAnthropicApiKey() { + if (!createdCompanyId || unsetAnthropicLoading) return; + setUnsetAnthropicLoading(true); + setError(null); + setAdapterEnvError(null); + setForceUnsetAnthropicApiKey(true); + + const configWithUnset = (() => { + const config = buildAdapterConfig(); + const env = + typeof config.env === "object" && + config.env !== null && + !Array.isArray(config.env) + ? { ...(config.env as Record) } + : {}; + env.ANTHROPIC_API_KEY = { type: "plain", value: "" }; + config.env = env; + return config; + })(); + + try { + if (createdAgentId) { + await agentsApi.update( + createdAgentId, + { adapterConfig: configWithUnset }, + createdCompanyId + ); + queryClient.invalidateQueries({ + queryKey: queryKeys.agents.list(createdCompanyId) + }); + } + + const result = await runAdapterEnvironmentTest(configWithUnset); + if (result?.status === "fail") { + setError( + "Retried with ANTHROPIC_API_KEY unset in adapter config, but the environment test is still failing." + ); + } + } catch (err) { + setError( + err instanceof Error + ? err.message + : "Failed to unset ANTHROPIC_API_KEY and retry." + ); + } finally { + setUnsetAnthropicLoading(false); + } + } + async function handleStep3Next() { if (!createdCompanyId || !createdAgentId) return; setLoading(true); @@ -673,6 +749,24 @@ export function OnboardingWizard() { )} + {shouldSuggestUnsetAnthropicApiKey && ( +
+

+ Claude failed while ANTHROPIC_API_KEY is set. + You can clear it in this CEO adapter config and retry the probe. +

+ +
+ )} +

Manual debug