import { isAtomCommandInterrupted, squashAtomCommandFailure, type AtomCommandResult,} from "@t3tools/client-runtime/state/runtime";import { ANTIGRAVITY_AUTH_METHODS, type AntigravityAuthMethod, type EnvironmentId, type ProviderAuthState, type ProviderInstanceId, type ServerProvider,} from "@t3tools/contracts";import { useRef, useState } from "react"; import { writeTextToClipboard } from "../../hooks/useCopyToClipboard";import { ensureLocalApi } from "../../localApi";import { useEnvironmentQuery } from "../../state/query";import { serverEnvironment } from "../../state/server";import { useAtomCommand } from "../../state/use-atom-command";import { Button } from "../ui/button";import { Input } from "../ui/input"; interface ProviderSetupSectionProps { readonly environmentId: EnvironmentId; readonly environmentLabel: string; readonly instanceId: ProviderInstanceId; readonly provider: ServerProvider | undefined; readonly binaryPath?: string | undefined; readonly authMethod?: AntigravityAuthMethod | undefined; readonly enabled: boolean; readonly readOnly: boolean; readonly onEnable: () => void;} const AUTH_PHASE_LABELS: Record<ProviderAuthState["phase"], string> = { idle: "Sign in with your Google account.", starting: "Starting Google sign-in.", waiting: "Waiting for Google sign-in.", verifying: "Checking Google sign-in and available models.", succeeded: "Google sign-in complete.", failed: "Google sign-in failed.", cancelled: "Google sign-in cancelled.",}; /** API key methods skip the browser, so the phases read as a credential check. */const CREDENTIAL_PHASE_LABELS: Record<ProviderAuthState["phase"], string> = { idle: "Connect with the credentials in the provider settings.", starting: "Checking credentials.", waiting: "Checking credentials.", verifying: "Checking credentials and available models.", succeeded: "Connected.", failed: "Could not connect with the configured credentials.", cancelled: "Connection cancelled.",}; /** Read the configured method from the instance config. Unknown values fall back to personal. */export function readAntigravityAuthMethod(config: unknown): AntigravityAuthMethod { const value = config !== null && typeof config === "object" && "authMethod" in config ? config.authMethod : undefined; return ( ANTIGRAVITY_AUTH_METHODS.find((method) => method.value === value)?.value ?? "oauth-personal" );} /** Setup state belongs to the selected environment and is never saved in client settings. */export function ProviderSetupSection(props: ProviderSetupSectionProps) { return ( <section aria-label="Antigravity setup" className="grid gap-3 text-xs"> <p>Antigravity runs on {props.environmentLabel}.</p> {!props.enabled ? ( <div className="flex flex-wrap items-center gap-2"> <span className="text-muted-foreground">Enable it to use it in threads.</span> {!props.readOnly ? ( <Button size="xs" variant="outline" onClick={props.onEnable}> Enable Antigravity </Button> ) : null} </div> ) : null} {props.readOnly ? ( <p className="text-muted-foreground">This connection cannot change provider setup.</p> ) : props.provider?.setup === undefined ? ( <p className="text-muted-foreground"> Update this environment to install Antigravity and sign in with Google here. </p> ) : ( <ProviderSetupActions key={`${props.environmentId}:${props.instanceId}`} environmentId={props.environmentId} environmentLabel={props.environmentLabel} instanceId={props.instanceId} provider={props.provider} binaryPath={props.binaryPath} authMethod={props.authMethod ?? "oauth-personal"} enabled={props.enabled} /> )} </section> );} function ProviderSetupActions({ environmentId, environmentLabel, instanceId, provider, enabled, binaryPath, authMethod,}: Pick< ProviderSetupSectionProps, "environmentId" | "environmentLabel" | "instanceId" | "enabled" | "binaryPath"> & { readonly provider: ServerProvider; readonly authMethod: AntigravityAuthMethod;}) { const target = { environmentId, input: { instanceId } }; const usesBrowser = authMethod === "oauth-personal" || authMethod === "oauth-business"; const phaseLabels = usesBrowser ? AUTH_PHASE_LABELS : CREDENTIAL_PHASE_LABELS; const methodLabel = ANTIGRAVITY_AUTH_METHODS.find((method) => method.value === authMethod)?.label ?? "Google account"; const authQuery = useEnvironmentQuery(serverEnvironment.providerAuthState(target)); const installQuery = useEnvironmentQuery(serverEnvironment.providerInstallState(target)); const auth = authQuery.data; const installation = installQuery.data; const commandOptions = { reportFailure: false, reportDefect: false }; const startAuth = useAtomCommand(serverEnvironment.startProviderAuth, commandOptions); const completeAuth = useAtomCommand(serverEnvironment.completeProviderAuth, commandOptions); const cancelAuth = useAtomCommand(serverEnvironment.cancelProviderAuth, commandOptions); const logoutAuth = useAtomCommand(serverEnvironment.logoutProviderAuth, commandOptions); const startInstall = useAtomCommand(serverEnvironment.startProviderInstall, commandOptions); const cancelInstall = useAtomCommand(serverEnvironment.cancelProviderInstall, commandOptions); const removeInstall = useAtomCommand( serverEnvironment.removeProviderInstallation, commandOptions, ); const [pendingLabel, setPendingLabel] = useState<string | null>(null); const pendingRef = useRef(false); const [error, setError] = useState<string | null>(null); const [callbackDraft, setCallbackDraft] = useState({ flowId: null as string | null, value: "" }); const [copiedFlowId, setCopiedFlowId] = useState<string | null>(null); const callbackUrl = callbackDraft.flowId === auth?.flowId ? callbackDraft.value : ""; const authActive = auth?.phase === "starting" || auth?.phase === "waiting" || auth?.phase === "verifying"; const installActive = installation?.phase === "downloading" || installation?.phase === "extracting" || installation?.phase === "verifying"; const usesCustomBinary = Boolean(binaryPath?.trim()); const installed = provider.installed || (!usesCustomBinary && installation?.installedVersion != null); const authenticated = provider.auth.status === "authenticated"; const authStatusMessage = auth === null ? "Reading sign-in status." : authActive || auth.phase === "failed" || auth.phase === "cancelled" ? (auth.message ?? phaseLabels[auth.phase]) : authenticated ? usesBrowser ? "Signed in with Google." : "Connected." : auth.phase === "idle" && auth.message ? auth.message : phaseLabels.idle; const authorizationUrl = auth?.phase === "waiting" ? auth.authorizationUrl : null; const queryError = authQuery.error ?? installQuery.error; const actionsDisabled = pendingLabel !== null || queryError !== null; const installationStatusMessage = installation?.phase === "downloading" ? `Downloading ${(installation.downloadedBytes / 1_000_000).toFixed(1)} MB${installation.totalBytes === null ? "" : ` of ${(installation.totalBytes / 1_000_000).toFixed(1)} MB`}.` : installation?.phase === "extracting" ? "Extracting Antigravity." : installation?.phase === "verifying" ? "Checking the downloaded runtime." : installed ? "Antigravity is installed." : usesCustomBinary ? enabled ? "The configured Antigravity runtime is unavailable." : "The configured Antigravity runtime has not been checked." : "Install the official Antigravity runtime before signing in."; async function runCommand<A, E>( label: string, request: () => Promise<AtomCommandResult<A, E>>, ): Promise<boolean> { if (pendingRef.current) return false; pendingRef.current = true; setPendingLabel(label); setError(null); try { const result = await request(); if (result._tag === "Failure") { if (!isAtomCommandInterrupted(result)) { const failure = squashAtomCommandFailure(result); setError(failure instanceof Error ? failure.message : "Provider setup failed."); } return false; } return true; } catch { setError("Provider setup failed. Try again."); return false; } finally { pendingRef.current = false; setPendingLabel(null); } } async function openSignInPage() { if (!authorizationUrl) return; try { await ensureLocalApi().shell.openExternal(authorizationUrl); setError(null); } catch { setError("Could not open the sign-in page. Copy the link and open it in your browser."); } } async function copySignInLink() { if (!authorizationUrl) return; try { await writeTextToClipboard(authorizationUrl, "Google sign-in link"); setCopiedFlowId(auth?.flowId ?? null); setError(null); } catch { setError("Could not copy the sign-in link. Use Open sign-in page."); } } async function submitCallback() { const flowId = auth?.flowId; if (!flowId || !callbackUrl.trim() || auth.phase !== "waiting") return; const accepted = await runCommand("Checking redirect", () => completeAuth({ environmentId, input: { instanceId, flowId, callbackUrl } }), ); if (accepted) { setCallbackDraft({ flowId: null, value: "" }); } } async function signOut() { const confirmed = await ensureLocalApi().dialogs.confirm( `${usesBrowser ? "Sign out of Google" : "Disconnect"} for ${provider.displayName ?? "Antigravity"} on ${environmentLabel}? This stops its running threads. Thread history is kept.`, ); if (confirmed) { await runCommand("Signing out", () => logoutAuth(target)); } } async function removeRuntime() { const confirmed = await ensureLocalApi().dialogs.confirm( `Remove the downloaded Antigravity runtime from ${environmentLabel}? Google sign-in and thread history are kept.`, ); if (confirmed) { await runCommand("Removing runtime", () => removeInstall(target)); } } return ( <div className="grid gap-3"> <div className="grid gap-2"> <p className="font-medium">Runtime</p> <p role="status" className="text-muted-foreground"> {installationStatusMessage} </p> {installation?.phase === "downloading" && installation.totalBytes !== null && installation.totalBytes > 0 ? ( <progress aria-label="Antigravity download" className="h-1 w-full accent-foreground" value={installation.downloadedBytes} max={installation.totalBytes} /> ) : null} {installation?.message && installation.message !== installationStatusMessage ? ( <p className="text-muted-foreground [overflow-wrap:anywhere]">{installation.message}</p> ) : null} {usesCustomBinary ? ( <p className="text-muted-foreground"> This instance uses the binary path below. Installing a managed runtime does not change that path. </p> ) : null} {!installed && !usesCustomBinary && !installActive && installation?.totalBytes ? ( <p className="text-muted-foreground"> Downloads {Math.ceil(installation.totalBytes / 1_000_000)} MB from Google. </p> ) : null} {!installed && !provider.setup?.canInstall ? ( <p className="text-muted-foreground"> Automatic installation is unavailable here. Set an existing binary path below or use a supported remote environment. </p> ) : null} <div className="flex flex-wrap gap-2"> {installActive && installation.operationId ? ( <Button size="xs" variant="outline" disabled={actionsDisabled} onClick={() => { const operationId = installation.operationId; if (!operationId) return; void runCommand("Cancelling installation", () => cancelInstall({ environmentId, input: { instanceId, operationId } }), ); }} > Cancel installation </Button> ) : !installActive && provider.setup?.canInstall ? ( <Button size="xs" variant="outline" disabled={actionsDisabled || installation === null || authActive} onClick={() => void runCommand("Starting installation", () => startInstall(target))} > {installation?.installedVersion ? installation.version && installation.version !== installation.installedVersion ? "Update Antigravity" : "Reinstall Antigravity" : installation?.phase === "failed" || installation?.phase === "cancelled" ? "Retry installation" : installed ? "Install managed runtime" : "Install Antigravity"} </Button> ) : null} {installation?.canRemove && !installActive ? ( <Button size="xs" variant="ghost" disabled={actionsDisabled || authActive} onClick={() => void removeRuntime()} > Remove downloaded runtime </Button> ) : null} </div> </div> <div className="grid gap-2 border-t border-border/60 pt-3"> <p className="font-medium">{methodLabel}</p> <p role="status" className="text-muted-foreground [overflow-wrap:anywhere]"> {authStatusMessage} </p> {authorizationUrl ? ( <> <div className="flex flex-wrap gap-2"> <Button size="xs" variant="outline" onClick={() => void openSignInPage()}> Open sign-in page </Button> <Button size="xs" variant="ghost" onClick={() => void copySignInLink()}> {copiedFlowId === auth?.flowId ? "Link copied" : "Copy sign-in link"} </Button> </div> {auth?.expiresAt ? ( <p className="text-muted-foreground"> Link expires at{" "} <time dateTime={auth.expiresAt}> {new Date(auth.expiresAt).toLocaleTimeString([], { hour: "numeric", minute: "2-digit", })} </time> . </p> ) : null} <form className="grid gap-2" onSubmit={(event) => { event.preventDefault(); void submitCallback(); }} > <label htmlFor={`provider-callback-${instanceId}`}> If the final localhost page does not load, paste its full URL here. </label> <Input id={`provider-callback-${instanceId}`} size="sm" type="url" autoComplete="off" spellCheck={false} placeholder="http://127.0.0.1:..." value={callbackUrl} maxLength={16_384} disabled={actionsDisabled} onChange={(event) => setCallbackDraft({ flowId: auth?.flowId ?? null, value: event.target.value }) } /> <Button size="xs" variant="outline" type="submit" className="w-fit" disabled={actionsDisabled || !callbackUrl.trim()} > Continue </Button> </form> </> ) : auth?.phase === "waiting" ? ( <p className="text-muted-foreground"> Sign-in is open in another client. Complete or cancel it there. </p> ) : null} <div className="flex flex-wrap gap-2"> {authActive && auth?.flowId ? ( <Button size="xs" variant="ghost" disabled={actionsDisabled} onClick={() => { const flowId = auth.flowId; if (!flowId) return; void runCommand("Cancelling sign-in", () => cancelAuth({ environmentId, input: { instanceId, flowId } }), ); }} > Cancel sign-in </Button> ) : !authActive && !authenticated && provider.setup?.canAuthenticate ? ( <Button size="xs" variant="outline" disabled={actionsDisabled || !installed || auth === null || installActive} onClick={() => void runCommand("Starting sign-in", () => startAuth(target))} > {usesBrowser ? auth?.phase === "failed" || auth?.phase === "cancelled" ? "Retry Google sign-in" : "Sign in with Google" : auth?.phase === "failed" || auth?.phase === "cancelled" ? "Retry connection" : "Connect"} </Button> ) : null} {!authActive && provider.setup?.canAuthenticate ? ( <Button size="xs" variant={authenticated ? "outline" : "ghost"} disabled={actionsDisabled || auth === null} onClick={() => void signOut()} > {usesBrowser ? "Sign out of Google" : "Disconnect"} </Button> ) : null} </div> </div> {pendingLabel ? <p role="status">{pendingLabel}.</p> : null} {error || queryError ? ( <div className="grid gap-2"> <p role="alert" className="text-destructive [overflow-wrap:anywhere]"> {error ?? queryError} </p> {queryError ? ( <Button size="xs" variant="outline" className="w-fit" onClick={() => { authQuery.refresh(); installQuery.refresh(); }} > Retry setup status </Button> ) : null} </div> ) : null} </div> );}
import {
isAtomCommandInterrupted,
squashAtomCommandFailure,
type AtomCommandResult,
} from "@t3tools/client-runtime/state/runtime";
import {
ANTIGRAVITY_AUTH_METHODS,
type AntigravityAuthMethod,
type EnvironmentId,
type ProviderAuthState,
type ProviderInstanceId,
type ServerProvider,
} from "@t3tools/contracts";
import { useRef, useState } from "react";
import { writeTextToClipboard } from "../../hooks/useCopyToClipboard";
import { ensureLocalApi } from "../../localApi";
import { useEnvironmentQuery } from "../../state/query";
import { serverEnvironment } from "../../state/server";
import { useAtomCommand } from "../../state/use-atom-command";
import { Button } from "../ui/button";
import { Input } from "../ui/input";
interface ProviderSetupSectionProps {
readonly environmentId: EnvironmentId;
readonly environmentLabel: string;
readonly instanceId: ProviderInstanceId;
readonly provider: ServerProvider | undefined;
readonly binaryPath?: string | undefined;
readonly authMethod?: AntigravityAuthMethod | undefined;
readonly enabled: boolean;
readonly readOnly: boolean;
readonly onEnable: () => void;
}
const AUTH_PHASE_LABELS: Record<ProviderAuthState["phase"], string> = {
idle: "Sign in with your Google account.",
starting: "Starting Google sign-in.",
waiting: "Waiting for Google sign-in.",
verifying: "Checking Google sign-in and available models.",
succeeded: "Google sign-in complete.",
failed: "Google sign-in failed.",
cancelled: "Google sign-in cancelled.",
};
/** API key methods skip the browser, so the phases read as a credential check. */
const CREDENTIAL_PHASE_LABELS: Record<ProviderAuthState["phase"], string> = {
idle: "Connect with the credentials in the provider settings.",
starting: "Checking credentials.",
waiting: "Checking credentials.",
verifying: "Checking credentials and available models.",
succeeded: "Connected.",
failed: "Could not connect with the configured credentials.",
cancelled: "Connection cancelled.",
};
/** Read the configured method from the instance config. Unknown values fall back to personal. */
export function readAntigravityAuthMethod(config: unknown): AntigravityAuthMethod {
const value =
config !== null && typeof config === "object" && "authMethod" in config
? config.authMethod
: undefined;
return (
ANTIGRAVITY_AUTH_METHODS.find((method) => method.value === value)?.value ?? "oauth-personal"
);
}
/** Setup state belongs to the selected environment and is never saved in client settings. */
export function ProviderSetupSection(props: ProviderSetupSectionProps) {
return (
<section aria-label="Antigravity setup" className="grid gap-3 text-xs">
<p>Antigravity runs on {props.environmentLabel}.</p>
{!props.enabled ? (
<div className="flex flex-wrap items-center gap-2">
<span className="text-muted-foreground">Enable it to use it in threads.</span>
{!props.readOnly ? (
<Button size="xs" variant="outline" onClick={props.onEnable}>
Enable Antigravity
</Button>
) : null}
</div>
) : null}
{props.readOnly ? (
<p className="text-muted-foreground">This connection cannot change provider setup.</p>
) : props.provider?.setup === undefined ? (
<p className="text-muted-foreground">
Update this environment to install Antigravity and sign in with Google here.
</p>
) : (
<ProviderSetupActions
key={`${props.environmentId}:${props.instanceId}`}
environmentId={props.environmentId}
environmentLabel={props.environmentLabel}
instanceId={props.instanceId}
provider={props.provider}
binaryPath={props.binaryPath}
authMethod={props.authMethod ?? "oauth-personal"}
enabled={props.enabled}
/>
)}
</section>
);
}
function ProviderSetupActions({
environmentId,
environmentLabel,
instanceId,
provider,
enabled,
binaryPath,
authMethod,
}: Pick<
ProviderSetupSectionProps,
"environmentId" | "environmentLabel" | "instanceId" | "enabled" | "binaryPath"
> & {
readonly provider: ServerProvider;
readonly authMethod: AntigravityAuthMethod;
}) {
const target = { environmentId, input: { instanceId } };
const usesBrowser = authMethod === "oauth-personal" || authMethod === "oauth-business";
const phaseLabels = usesBrowser ? AUTH_PHASE_LABELS : CREDENTIAL_PHASE_LABELS;
const methodLabel =
ANTIGRAVITY_AUTH_METHODS.find((method) => method.value === authMethod)?.label ??
"Google account";
const authQuery = useEnvironmentQuery(serverEnvironment.providerAuthState(target));
const installQuery = useEnvironmentQuery(serverEnvironment.providerInstallState(target));
const auth = authQuery.data;
const installation = installQuery.data;
const commandOptions = { reportFailure: false, reportDefect: false };
const startAuth = useAtomCommand(serverEnvironment.startProviderAuth, commandOptions);
const completeAuth = useAtomCommand(serverEnvironment.completeProviderAuth, commandOptions);
const cancelAuth = useAtomCommand(serverEnvironment.cancelProviderAuth, commandOptions);
const logoutAuth = useAtomCommand(serverEnvironment.logoutProviderAuth, commandOptions);
const startInstall = useAtomCommand(serverEnvironment.startProviderInstall, commandOptions);
const cancelInstall = useAtomCommand(serverEnvironment.cancelProviderInstall, commandOptions);
const removeInstall = useAtomCommand(
serverEnvironment.removeProviderInstallation,
commandOptions,
);
const [pendingLabel, setPendingLabel] = useState<string | null>(null);
const pendingRef = useRef(false);
const [error, setError] = useState<string | null>(null);
const [callbackDraft, setCallbackDraft] = useState({ flowId: null as string | null, value: "" });
const [copiedFlowId, setCopiedFlowId] = useState<string | null>(null);
const callbackUrl = callbackDraft.flowId === auth?.flowId ? callbackDraft.value : "";
const authActive =
auth?.phase === "starting" || auth?.phase === "waiting" || auth?.phase === "verifying";
const installActive =
installation?.phase === "downloading" ||
installation?.phase === "extracting" ||
installation?.phase === "verifying";
const usesCustomBinary = Boolean(binaryPath?.trim());
const installed =
provider.installed || (!usesCustomBinary && installation?.installedVersion != null);
const authenticated = provider.auth.status === "authenticated";
const authStatusMessage =
auth === null
? "Reading sign-in status."
: authActive || auth.phase === "failed" || auth.phase === "cancelled"
? (auth.message ?? phaseLabels[auth.phase])
: authenticated
? usesBrowser
? "Signed in with Google."
: "Connected."
: auth.phase === "idle" && auth.message
? auth.message
: phaseLabels.idle;
const authorizationUrl = auth?.phase === "waiting" ? auth.authorizationUrl : null;
const queryError = authQuery.error ?? installQuery.error;
const actionsDisabled = pendingLabel !== null || queryError !== null;
const installationStatusMessage =
installation?.phase === "downloading"
? `Downloading ${(installation.downloadedBytes / 1_000_000).toFixed(1)} MB${installation.totalBytes === null ? "" : ` of ${(installation.totalBytes / 1_000_000).toFixed(1)} MB`}.`
: installation?.phase === "extracting"
? "Extracting Antigravity."
: installation?.phase === "verifying"
? "Checking the downloaded runtime."
: installed
? "Antigravity is installed."
: usesCustomBinary
? enabled
? "The configured Antigravity runtime is unavailable."
: "The configured Antigravity runtime has not been checked."
: "Install the official Antigravity runtime before signing in.";
async function runCommand<A, E>(
label: string,
request: () => Promise<AtomCommandResult<A, E>>,
): Promise<boolean> {
if (pendingRef.current) return false;
pendingRef.current = true;
setPendingLabel(label);
setError(null);
try {
const result = await request();
if (result._tag === "Failure") {
if (!isAtomCommandInterrupted(result)) {
const failure = squashAtomCommandFailure(result);
setError(failure instanceof Error ? failure.message : "Provider setup failed.");
}
return false;
}
return true;
} catch {
setError("Provider setup failed. Try again.");
return false;
} finally {
pendingRef.current = false;
setPendingLabel(null);
}
}
async function openSignInPage() {
if (!authorizationUrl) return;
try {
await ensureLocalApi().shell.openExternal(authorizationUrl);
setError(null);
} catch {
setError("Could not open the sign-in page. Copy the link and open it in your browser.");
}
}
async function copySignInLink() {
if (!authorizationUrl) return;
try {
await writeTextToClipboard(authorizationUrl, "Google sign-in link");
setCopiedFlowId(auth?.flowId ?? null);
setError(null);
} catch {
setError("Could not copy the sign-in link. Use Open sign-in page.");
}
}
async function submitCallback() {
const flowId = auth?.flowId;
if (!flowId || !callbackUrl.trim() || auth.phase !== "waiting") return;
const accepted = await runCommand("Checking redirect", () =>
completeAuth({ environmentId, input: { instanceId, flowId, callbackUrl } }),
);
if (accepted) {
setCallbackDraft({ flowId: null, value: "" });
}
}
async function signOut() {
const confirmed = await ensureLocalApi().dialogs.confirm(
`${usesBrowser ? "Sign out of Google" : "Disconnect"} for ${provider.displayName ?? "Antigravity"} on ${environmentLabel}? This stops its running threads. Thread history is kept.`,
);
if (confirmed) {
await runCommand("Signing out", () => logoutAuth(target));
}
}
async function removeRuntime() {
const confirmed = await ensureLocalApi().dialogs.confirm(
`Remove the downloaded Antigravity runtime from ${environmentLabel}? Google sign-in and thread history are kept.`,
);
if (confirmed) {
await runCommand("Removing runtime", () => removeInstall(target));
}
}
return (
<div className="grid gap-3">
<div className="grid gap-2">
<p className="font-medium">Runtime</p>
<p role="status" className="text-muted-foreground">
{installationStatusMessage}
</p>
{installation?.phase === "downloading" &&
installation.totalBytes !== null &&
installation.totalBytes > 0 ? (
<progress
aria-label="Antigravity download"
className="h-1 w-full accent-foreground"
value={installation.downloadedBytes}
max={installation.totalBytes}
/>
) : null}
{installation?.message && installation.message !== installationStatusMessage ? (
<p className="text-muted-foreground [overflow-wrap:anywhere]">{installation.message}</p>
) : null}
{usesCustomBinary ? (
<p className="text-muted-foreground">
This instance uses the binary path below. Installing a managed runtime does not change
that path.
</p>
) : null}
{!installed && !usesCustomBinary && !installActive && installation?.totalBytes ? (
<p className="text-muted-foreground">
Downloads {Math.ceil(installation.totalBytes / 1_000_000)} MB from Google.
</p>
) : null}
{!installed && !provider.setup?.canInstall ? (
<p className="text-muted-foreground">
Automatic installation is unavailable here. Set an existing binary path below or use a
supported remote environment.
</p>
) : null}
<div className="flex flex-wrap gap-2">
{installActive && installation.operationId ? (
<Button
size="xs"
variant="outline"
disabled={actionsDisabled}
onClick={() => {
const operationId = installation.operationId;
if (!operationId) return;
void runCommand("Cancelling installation", () =>
cancelInstall({ environmentId, input: { instanceId, operationId } }),
);
}}
>
Cancel installation
</Button>
) : !installActive && provider.setup?.canInstall ? (
<Button
size="xs"
variant="outline"
disabled={actionsDisabled || installation === null || authActive}
onClick={() => void runCommand("Starting installation", () => startInstall(target))}
>
{installation?.installedVersion
? installation.version && installation.version !== installation.installedVersion
? "Update Antigravity"
: "Reinstall Antigravity"
: installation?.phase === "failed" || installation?.phase === "cancelled"
? "Retry installation"
: installed
? "Install managed runtime"
: "Install Antigravity"}
</Button>
) : null}
{installation?.canRemove && !installActive ? (
<Button
size="xs"
variant="ghost"
disabled={actionsDisabled || authActive}
onClick={() => void removeRuntime()}
>
Remove downloaded runtime
</Button>
) : null}
</div>
</div>
<div className="grid gap-2 border-t border-border/60 pt-3">
<p className="font-medium">{methodLabel}</p>
<p role="status" className="text-muted-foreground [overflow-wrap:anywhere]">
{authStatusMessage}
</p>
{authorizationUrl ? (
<>
<div className="flex flex-wrap gap-2">
<Button size="xs" variant="outline" onClick={() => void openSignInPage()}>
Open sign-in page
</Button>
<Button size="xs" variant="ghost" onClick={() => void copySignInLink()}>
{copiedFlowId === auth?.flowId ? "Link copied" : "Copy sign-in link"}
</Button>
</div>
{auth?.expiresAt ? (
<p className="text-muted-foreground">
Link expires at{" "}
<time dateTime={auth.expiresAt}>
{new Date(auth.expiresAt).toLocaleTimeString([], {
hour: "numeric",
minute: "2-digit",
})}
</time>
.
</p>
) : null}
<form
className="grid gap-2"
onSubmit={(event) => {
event.preventDefault();
void submitCallback();
}}
>
<label htmlFor={`provider-callback-${instanceId}`}>
If the final localhost page does not load, paste its full URL here.
</label>
<Input
id={`provider-callback-${instanceId}`}
size="sm"
type="url"
autoComplete="off"
spellCheck={false}
placeholder="http://127.0.0.1:..."
value={callbackUrl}
maxLength={16_384}
disabled={actionsDisabled}
onChange={(event) =>
setCallbackDraft({ flowId: auth?.flowId ?? null, value: event.target.value })
}
/>
<Button
size="xs"
variant="outline"
type="submit"
className="w-fit"
disabled={actionsDisabled || !callbackUrl.trim()}
>
Continue
</Button>
</form>
</>
) : auth?.phase === "waiting" ? (
<p className="text-muted-foreground">
Sign-in is open in another client. Complete or cancel it there.
</p>
) : null}
<div className="flex flex-wrap gap-2">
{authActive && auth?.flowId ? (
<Button
size="xs"
variant="ghost"
disabled={actionsDisabled}
onClick={() => {
const flowId = auth.flowId;
if (!flowId) return;
void runCommand("Cancelling sign-in", () =>
cancelAuth({ environmentId, input: { instanceId, flowId } }),
);
}}
>
Cancel sign-in
</Button>
) : !authActive && !authenticated && provider.setup?.canAuthenticate ? (
<Button
size="xs"
variant="outline"
disabled={actionsDisabled || !installed || auth === null || installActive}
onClick={() => void runCommand("Starting sign-in", () => startAuth(target))}
>
{usesBrowser
? auth?.phase === "failed" || auth?.phase === "cancelled"
? "Retry Google sign-in"
: "Sign in with Google"
: auth?.phase === "failed" || auth?.phase === "cancelled"
? "Retry connection"
: "Connect"}
</Button>
) : null}
{!authActive && provider.setup?.canAuthenticate ? (
<Button
size="xs"
variant={authenticated ? "outline" : "ghost"}
disabled={actionsDisabled || auth === null}
onClick={() => void signOut()}
>
{usesBrowser ? "Sign out of Google" : "Disconnect"}
</Button>
) : null}
</div>
</div>
{pendingLabel ? <p role="status">{pendingLabel}.</p> : null}
{error || queryError ? (
<div className="grid gap-2">
<p role="alert" className="text-destructive [overflow-wrap:anywhere]">
{error ?? queryError}
</p>
{queryError ? (
<Button
size="xs"
variant="outline"
className="w-fit"
onClick={() => {
authQuery.refresh();
installQuery.refresh();
}}
>
Retry setup status
</Button>
) : null}
</div>
) : null}
</div>
);
}