Merge branch 'main' into fix-build

This commit is contained in:
Cody Seibert
2025-12-10 23:37:14 -05:00
14 changed files with 247 additions and 433 deletions

View File

@@ -768,16 +768,14 @@ ${Object.entries(projectAnalysis.filesByExtension)
throw new Error("Features API not available");
}
// Convert DetectedFeature to Feature by adding required id and status
for (const detectedFeature of detectedFeatures) {
const feature: Feature = {
await api.features.create(currentProject.path, {
id: crypto.randomUUID(),
category: detectedFeature.category,
description: detectedFeature.description,
steps: detectedFeature.steps,
status: "backlog" as const,
};
await api.features.create(currentProject.path, feature);
status: "backlog",
});
}
setFeatureListGenerated(true);

View File

@@ -325,6 +325,7 @@ export function InterviewView() {
],
skipTests: true,
};
if (!api.features) {
throw new Error("Features API not available");
}

View File

@@ -53,41 +53,22 @@ export function AuthenticationStatusDisplay({
<>
<div className="flex items-center gap-2">
<CheckCircle2 className="w-3 h-3 text-green-500 shrink-0" />
<span className="text-muted-foreground">
Method:{" "}
<span className="font-mono text-foreground">
{claudeAuthStatus.method === "oauth"
? "OAuth Token"
: claudeAuthStatus.method === "api_key"
? "API Key"
: "Unknown"}
</span>
<span className="text-green-400 font-medium">Authenticated</span>
</div>
<div className="flex items-center gap-2 text-muted-foreground">
<Info className="w-3 h-3 shrink-0" />
<span>
{claudeAuthStatus.method === "oauth_token_env"
? "Using CLAUDE_CODE_OAUTH_TOKEN"
: claudeAuthStatus.method === "oauth_token"
? "Using stored OAuth token"
: claudeAuthStatus.method === "api_key_env"
? "Using ANTHROPIC_API_KEY"
: claudeAuthStatus.method === "api_key"
? "Using stored API key"
: "Unknown method"}
</span>
</div>
{claudeAuthStatus.oauthTokenValid && (
<div className="flex items-center gap-2 text-green-400">
<CheckCircle2 className="w-3 h-3 shrink-0" />
<span>OAuth token configured</span>
</div>
)}
{claudeAuthStatus.apiKeyValid && (
<div className="flex items-center gap-2 text-green-400">
<CheckCircle2 className="w-3 h-3 shrink-0" />
<span>API key configured</span>
</div>
)}
{apiKeyStatus?.hasAnthropicKey && (
<div className="flex items-center gap-2 text-blue-400">
<Info className="w-3 h-3 shrink-0" />
<span>Environment variable detected</span>
</div>
)}
{apiKeys.anthropic && (
<div className="flex items-center gap-2 text-blue-400">
<Info className="w-3 h-3 shrink-0" />
<span>Manual API key in settings</span>
</div>
)}
</>
) : apiKeyStatus?.hasAnthropicKey ? (
<div className="flex items-center gap-2 text-blue-400">
@@ -100,9 +81,9 @@ export function AuthenticationStatusDisplay({
<span>Using manual API key from settings</span>
</div>
) : (
<div className="flex items-center gap-1.5 text-muted-foreground py-0.5">
<AlertCircle className="w-2.5 h-2.5 shrink-0" />
<span className="text-xs">Not Setup</span>
<div className="flex items-center gap-1.5 text-yellow-500 py-0.5">
<AlertCircle className="w-3 h-3 shrink-0" />
<span className="text-xs">Not configured</span>
</div>
)}
</div>
@@ -121,44 +102,21 @@ export function AuthenticationStatusDisplay({
<>
<div className="flex items-center gap-2">
<CheckCircle2 className="w-3 h-3 text-green-500 shrink-0" />
<span className="text-muted-foreground">
Method:{" "}
<span className="font-mono text-foreground">
{codexAuthStatus.method === "cli_verified" ||
codexAuthStatus.method === "cli_tokens"
? "CLI Login (OpenAI Account)"
: codexAuthStatus.method === "api_key"
? "API Key (Auth File)"
: codexAuthStatus.method === "env"
? "API Key (Environment)"
: "Unknown"}
</span>
<span className="text-green-400 font-medium">Authenticated</span>
</div>
<div className="flex items-center gap-2 text-muted-foreground">
<Info className="w-3 h-3 shrink-0" />
<span>
{codexAuthStatus.method === "cli_verified" ||
codexAuthStatus.method === "cli_tokens"
? "Using CLI login (OpenAI account)"
: codexAuthStatus.method === "api_key"
? "Using stored API key"
: codexAuthStatus.method === "env"
? "Using OPENAI_API_KEY"
: "Unknown method"}
</span>
</div>
{codexAuthStatus.method === "cli_verified" ||
codexAuthStatus.method === "cli_tokens" ? (
<div className="flex items-center gap-2 text-green-400">
<CheckCircle2 className="w-3 h-3 shrink-0" />
<span>Account authenticated</span>
</div>
) : codexAuthStatus.apiKeyValid ? (
<div className="flex items-center gap-2 text-green-400">
<CheckCircle2 className="w-3 h-3 shrink-0" />
<span>API key configured</span>
</div>
) : null}
{apiKeyStatus?.hasOpenAIKey && (
<div className="flex items-center gap-2 text-blue-400">
<Info className="w-3 h-3 shrink-0" />
<span>Environment variable detected</span>
</div>
)}
{apiKeys.openai && (
<div className="flex items-center gap-2 text-blue-400">
<Info className="w-3 h-3 shrink-0" />
<span>Manual API key in settings</span>
</div>
)}
</>
) : apiKeyStatus?.hasOpenAIKey ? (
<div className="flex items-center gap-2 text-blue-400">
@@ -171,9 +129,9 @@ export function AuthenticationStatusDisplay({
<span>Using manual API key from settings</span>
</div>
) : (
<div className="flex items-center gap-1.5 text-muted-foreground py-0.5">
<AlertCircle className="w-2.5 h-2.5 shrink-0" />
<span className="text-xs">Not Setup</span>
<div className="flex items-center gap-1.5 text-yellow-500 py-0.5">
<AlertCircle className="w-3 h-3 shrink-0" />
<span className="text-xs">Not configured</span>
</div>
)}
</div>
@@ -189,19 +147,31 @@ export function AuthenticationStatusDisplay({
</div>
<div className="space-y-1.5 text-xs min-h-12">
{apiKeyStatus?.hasGoogleKey ? (
<div className="flex items-center gap-2 text-blue-400">
<Info className="w-3 h-3 shrink-0" />
<span>Using environment variable (GOOGLE_API_KEY)</span>
</div>
<>
<div className="flex items-center gap-2">
<CheckCircle2 className="w-3 h-3 text-green-500 shrink-0" />
<span className="text-green-400 font-medium">Authenticated</span>
</div>
<div className="flex items-center gap-2 text-muted-foreground">
<Info className="w-3 h-3 shrink-0" />
<span>Using GOOGLE_API_KEY</span>
</div>
</>
) : apiKeys.google ? (
<div className="flex items-center gap-2 text-blue-400">
<Info className="w-3 h-3 shrink-0" />
<span>Using manual API key from settings</span>
</div>
<>
<div className="flex items-center gap-2">
<CheckCircle2 className="w-3 h-3 text-green-500 shrink-0" />
<span className="text-green-400 font-medium">Authenticated</span>
</div>
<div className="flex items-center gap-2 text-muted-foreground">
<Info className="w-3 h-3 shrink-0" />
<span>Using stored API key</span>
</div>
</>
) : (
<div className="flex items-center gap-1.5 text-muted-foreground py-0.5">
<AlertCircle className="w-2.5 h-2.5 shrink-0" />
<span className="text-xs">Not Setup</span>
<div className="flex items-center gap-1.5 text-yellow-500 py-0.5">
<AlertCircle className="w-3 h-3 shrink-0" />
<span className="text-xs">Not configured</span>
</div>
)}
</div>

View File

@@ -69,17 +69,20 @@ export function useCliStatus() {
const result = await api.setup.getClaudeStatus();
if (result.success && result.auth) {
const auth = result.auth;
// Validate method is one of the expected values, default to "none"
const validMethods = ["oauth_token_env", "oauth_token", "api_key", "api_key_env", "none"] as const;
type AuthMethod = typeof validMethods[number];
const method: AuthMethod = validMethods.includes(auth.method as AuthMethod)
? (auth.method as AuthMethod)
: "none";
const authStatus = {
authenticated: auth.authenticated,
method:
auth.method === "oauth_token"
? ("oauth" as const)
: auth.method?.includes("api_key")
? ("api_key" as const)
: ("none" as const),
method,
hasCredentialsFile: auth.hasCredentialsFile ?? false,
oauthTokenValid: auth.hasStoredOAuthToken,
oauthTokenValid: auth.hasStoredOAuthToken || auth.hasEnvOAuthToken,
apiKeyValid: auth.hasStoredApiKey || auth.hasEnvApiKey,
hasEnvOAuthToken: auth.hasEnvOAuthToken,
hasEnvApiKey: auth.hasEnvApiKey,
};
setClaudeAuthStatus(authStatus);
}

View File

@@ -250,21 +250,32 @@ function ClaudeSetupStep({
setClaudeCliStatus(cliStatus);
if (result.auth) {
// Validate method is one of the expected values, default to "none"
const validMethods = [
"oauth_token_env",
"oauth_token",
"api_key",
"api_key_env",
"none",
] as const;
type AuthMethod = (typeof validMethods)[number];
const method: AuthMethod = validMethods.includes(
result.auth.method as AuthMethod
)
? (result.auth.method as AuthMethod)
: "none";
const authStatus = {
authenticated: result.auth.authenticated,
method:
result.auth.method === "oauth_token"
? "oauth"
: result.auth.method?.includes("api_key")
? "api_key"
: "none",
method,
hasCredentialsFile: false,
oauthTokenValid: result.auth.hasStoredOAuthToken,
oauthTokenValid:
result.auth.hasStoredOAuthToken || result.auth.hasEnvOAuthToken,
apiKeyValid:
result.auth.hasStoredApiKey || result.auth.hasEnvApiKey,
hasEnvOAuthToken: result.auth.hasEnvOAuthToken,
hasEnvApiKey: result.auth.hasEnvApiKey,
};
console.log("[Claude Setup] Auth Status:", authStatus);
setClaudeAuthStatus(authStatus as any);
setClaudeAuthStatus(authStatus);
}
}
}
@@ -385,7 +396,7 @@ function ClaudeSetupStep({
if (result.success) {
setClaudeAuthStatus({
authenticated: true,
method: "oauth",
method: "oauth_token",
hasCredentialsFile: false,
oauthTokenValid: true,
});
@@ -463,8 +474,16 @@ function ClaudeSetupStep({
const getAuthMethodLabel = () => {
if (!isAuthenticated) return null;
if (claudeAuthStatus?.method === "oauth") return "Subscription Token";
if (apiKeys.anthropic || claudeAuthStatus?.method === "api_key")
if (
claudeAuthStatus?.method === "oauth_token_env" ||
claudeAuthStatus?.method === "oauth_token"
)
return "Subscription Token";
if (
apiKeys.anthropic ||
claudeAuthStatus?.method === "api_key" ||
claudeAuthStatus?.method === "api_key_env"
)
return "API Key";
return "Authenticated";
};