diff --git a/apps/web/src/components/settings/ProviderInstanceCard.tsx b/apps/web/src/components/settings/ProviderInstanceCard.tsx index f9d078f9840cd..1a6a0b885acf6 100644 --- a/apps/web/src/components/settings/ProviderInstanceCard.tsx +++ b/apps/web/src/components/settings/ProviderInstanceCard.tsx @@ -66,9 +66,9 @@ import { readCodexSetupMode } from "./CodexSetupSection.logic"; import { getProviderVersionAdvisoryPresentation, PROVIDER_STATUS_STYLES, + getProviderStatusKey, getProviderSummary, getProviderVersionLabel, - type ProviderStatusKey, } from "./providerStatus"; const ENVIRONMENT_VARIABLE_NAME_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/; @@ -645,13 +645,12 @@ export function ProviderInstanceCard({ projectOverride, }: ProviderInstanceCardProps) { const enabled = projectOverride?.effectiveEnabled ?? resolveProviderInstanceEnabled(instance); + const effectiveProvider = liveProvider && { ...liveProvider, enabled }; const compatibility = enabled ? liveProvider?.compatibilityAdvisory : undefined; - const statusKey: ProviderStatusKey = enabled - ? ((liveProvider?.status as ProviderStatusKey | undefined) ?? "warning") - : "disabled"; + const statusKey = enabled ? getProviderStatusKey(effectiveProvider) : "disabled"; const statusStyle = PROVIDER_STATUS_STYLES[statusKey]; const summary = enabled - ? getProviderSummary(liveProvider && { ...liveProvider, enabled: true }) + ? getProviderSummary(effectiveProvider) : { headline: "Disabled", detail: null }; const authEmail = liveProvider?.auth.email?.trim(); const isAuthenticated = enabled && liveProvider?.auth.status === "authenticated"; diff --git a/apps/web/src/components/settings/providerStatus.test.ts b/apps/web/src/components/settings/providerStatus.test.ts index d231b911e7503..c165b9401fe43 100644 --- a/apps/web/src/components/settings/providerStatus.test.ts +++ b/apps/web/src/components/settings/providerStatus.test.ts @@ -1,7 +1,11 @@ import { ProviderDriverKind, ProviderInstanceId, type ServerProvider } from "@t3tools/contracts"; import { describe, expect, it } from "vite-plus/test"; -import { getProviderSummary, getProviderVersionAdvisoryPresentation } from "./providerStatus"; +import { + getProviderSummary, + getProviderVersionAdvisoryPresentation, + getProviderStatusKey, +} from "./providerStatus"; const provider: ServerProvider = { instanceId: ProviderInstanceId.make("codex"), @@ -70,6 +74,86 @@ describe("getProviderSummary", () => { }); }); +describe("Antigravity with unchecked sign-in", () => { + const unchecked: ServerProvider = { + ...provider, + instanceId: ProviderInstanceId.make("antigravity"), + driver: ProviderDriverKind.make("antigravity"), + status: "warning", + auth: { status: "unknown" }, + message: "Antigravity is installed. Google account access is not checked yet.", + }; + + it("presents an unchecked Google sign-in neutrally without claiming authentication is required", () => { + for (const auth of [unchecked.auth, { status: "unknown", type: "oauth-personal" }] as const) { + const candidate = { ...unchecked, auth }; + expect.soft(getProviderSummary(candidate)).toEqual({ + headline: "Installed · Sign-in not checked", + detail: unchecked.message, + }); + expect(getProviderStatusKey(candidate)).toBe("neutral"); + } + }); + + it("preserves actionable warnings, failures and disabled states outside unchecked Google sign-in", () => { + const cases = [ + { + name: "confirmed sign-out", + change: { auth: { status: "unauthenticated" } }, + headline: "Not authenticated", + status: "warning", + }, + { + name: "warning despite known authentication", + change: { auth: { status: "authenticated" } }, + headline: "Needs attention", + status: "warning", + }, + { + name: "probe failure", + change: { status: "error" }, + headline: "Unavailable", + status: "error", + }, + { + name: "missing CLI", + change: { installed: false }, + headline: "Not found", + status: "warning", + }, + { + name: "API key authentication", + change: { auth: { status: "unknown", type: "gemini-api-key" } }, + headline: "Needs attention", + status: "warning", + }, + { + name: "Agent Platform authentication", + change: { auth: { status: "unknown", type: "agent-platform" } }, + headline: "Needs attention", + status: "warning", + }, + { + name: "another provider", + change: { driver: provider.driver }, + headline: "Needs attention", + status: "warning", + }, + { + name: "disabled provider", + change: { enabled: false }, + headline: "Disabled", + status: "disabled", + }, + ] as const; + for (const { name, change, headline, status } of cases) { + const candidate = { ...unchecked, ...change }; + expect.soft(getProviderSummary(candidate).headline, name).toBe(headline); + expect.soft(getProviderStatusKey(candidate), name).toBe(status); + } + }); +}); + it("does not suggest copying a command that installs an incompatible latest version", () => { const advisory = { status: "behind_latest" as const, diff --git a/apps/web/src/components/settings/providerStatus.ts b/apps/web/src/components/settings/providerStatus.ts index 32d1ef836109f..fbd72b1c41165 100644 --- a/apps/web/src/components/settings/providerStatus.ts +++ b/apps/web/src/components/settings/providerStatus.ts @@ -11,6 +11,9 @@ export const PROVIDER_STATUS_STYLES = { error: { dot: "bg-destructive", }, + neutral: { + dot: "bg-muted-foreground", + }, ready: { dot: "bg-success", }, @@ -21,6 +24,26 @@ export const PROVIDER_STATUS_STYLES = { export type ProviderStatusKey = keyof typeof PROVIDER_STATUS_STYLES; +// Antigravity's local health check verifies installation, not Google sign-in. +// API-key and Agent Platform warnings still need attention. +function isAntigravitySignInUnchecked(provider: ServerProvider): boolean { + return ( + provider.driver === "antigravity" && + provider.installed && + provider.status === "warning" && + provider.auth.status === "unknown" && + (provider.auth.type === undefined || + provider.auth.type === "oauth-personal" || + provider.auth.type === "oauth-business") + ); +} + +export function getProviderStatusKey(provider: ServerProvider | undefined): ProviderStatusKey { + if (provider && !provider.enabled) return "disabled"; + if (provider && isAntigravitySignInUnchecked(provider)) return "neutral"; + return provider?.status ?? "warning"; +} + export function getProviderSummary(provider: ServerProvider | undefined) { if (!provider) { return { @@ -48,6 +71,12 @@ export function getProviderSummary(provider: ServerProvider | undefined) { detail: provider.message ?? null, }; } + if (isAntigravitySignInUnchecked(provider)) { + return { + headline: "Installed · Sign-in not checked", + detail: provider.message ?? null, + }; + } if (provider.status === "warning") { return { headline: "Needs attention",