import { RefreshIcon } from "~/components/ui/refresh-icon";import { useAtomValue } from "@effect/atom-react";import { connectionStatusTitle } from "@t3tools/client-runtime/connection";import { safeErrorLogAttributes } from "@t3tools/client-runtime/errors";import { isAtomCommandInterrupted, squashAtomCommandFailure,} from "@t3tools/client-runtime/state/runtime";import { defaultInstanceIdForDriver, type EnvironmentId, PROVIDER_DISPLAY_NAMES, ProviderDriverKind, type ProviderInstanceConfig, type ProviderInstanceId, resolveEnvironmentMachineKind, resolveProviderInstanceEnabled,} from "@t3tools/contracts";import { DEFAULT_UNIFIED_SETTINGS } from "@t3tools/contracts/settings";import { getBackgroundActivityPresetSettings, resolveServerBackgroundActivitySettings,} from "@t3tools/shared/backgroundActivitySettings";import * as Arr from "effect/Array";import * as Duration from "effect/Duration";import * as Equal from "effect/Equal";import * as Result from "effect/Result";import { PlusIcon } from "lucide-react";import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from "react"; import { isDesktopLocalConnectionTarget } from "../../connection/desktopLocal";import { isElectron } from "../../env";import { usePrimarySessionState } from "../../environments/primary";import { useEnvironmentSettings, useUpdateEnvironmentSettings } from "../../hooks/useSettings";import { EnvironmentMachineIcon } from "../EnvironmentMachineIcon";import { cn } from "../../lib/utils";import { resolveAppModelSelectionState } from "../../modelSelection";import { useEnvironments, usePrimaryEnvironmentId, type EnvironmentPresentation,} from "../../state/environments";import { EMPTY_SERVER_PROVIDERS, serverEnvironment } from "../../state/server";import { useEnvironmentSessionState } from "../../state/session";import { useAtomCommand } from "../../state/use-atom-command";import { getRelativeTimeState } from "../../timestampFormat";import { ConnectionStatusDot, connectionPhaseDotClassName, connectionPhasePingClassName,} from "../ConnectionStatusDot";import { isProviderSettingsUpdateCandidate, isProviderUpdateActive, type ProviderSettingsUpdateCandidate,} from "../ProviderUpdateLaunchNotification.logic";import { Button } from "../ui/button";import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle,} from "../ui/empty";import { NumberField, NumberFieldDecrement, NumberFieldGroup, NumberFieldIncrement, NumberFieldInput,} from "../ui/number-field";import { ScrollArea } from "../ui/scroll-area";import { Toggle, ToggleGroup } from "../ui/toggle-group";import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";import { stackedThreadToast, toastManager } from "../ui/toast";import { AddProviderInstanceDialog } from "./AddProviderInstanceDialog";import { ExpandableText } from "./ExpandableText";import { ProviderInstanceCard } from "./ProviderInstanceCard";import { UsageProviderSettings } from "./UsageProviderSettings";import { ProviderSetupSection, readAntigravityAuthMethod } from "./ProviderSetupSection";import { DRIVER_OPTIONS, getDriverOption } from "./providerDriverMeta";import { searchableSetting } from "./settingsSearch";import { backgroundActivityOverrideSettings, buildProviderInstanceUpdatePatch, durationToSeconds, normalizeIntervalSeconds, PROVIDER_HEALTH_INTERVAL_STEP_SECONDS,} from "./SettingsPanels.logic";import { PolicyTooltip, SettingResetButton, SettingsPageContainer, SettingsRow, SettingsSection, useRelativeTimeTick, useSettingsSearchTargetId,} from "./settingsLayout";import { buildProviderEnvironmentOptions, classifyProviderEnvironmentAccess, isProviderSettingsEnvironmentAvailable, type ProviderEnvironmentAccess, type ProviderOperateAccess, resolvePrimaryOperateAccess, resolveRemoteOperateAccess, resolveSelectedProviderEnvironmentId,} from "./ProviderSettingsPanel.logic"; function withoutProviderInstanceKey<V>( record: Readonly<Record<ProviderInstanceId, V>> | undefined, key: ProviderInstanceId,): Record<ProviderInstanceId, V> { const next = { ...record } as Record<ProviderInstanceId, V>; delete next[key]; return next;} function withoutProviderInstanceFavorites( favorites: ReadonlyArray<{ readonly provider: ProviderInstanceId; readonly model: string }>, instanceId: ProviderInstanceId,) { return favorites.filter((favorite) => favorite.provider !== instanceId);} const PROVIDER_SETTINGS = DRIVER_OPTIONS.map((definition) => ({ provider: definition.value,})); function configuredBinaryPath(config: unknown): string { if (config === null || typeof config !== "object" || !("binaryPath" in config)) return ""; return typeof config.binaryPath === "string" ? config.binaryPath.trim() : "";} function ProviderLastChecked({ lastCheckedAt }: { lastCheckedAt: string | null }) { useRelativeTimeTick(); const lastCheckedRelative = getRelativeTimeState(lastCheckedAt); if (lastCheckedRelative.status === "missing") { return null; } if (lastCheckedRelative.status === "invalid") { return <span>Checked unavailable</span>; } return ( <span> {lastCheckedRelative.suffix ? ( <> Checked <span className="font-mono tabular-nums">{lastCheckedRelative.value}</span>{" "} {lastCheckedRelative.suffix} </> ) : ( <>Checked {lastCheckedRelative.value}</> )} </span> );} function providerEnvironmentDetail(environment: EnvironmentPresentation): string { if (environment.entry.target._tag === "PrimaryConnectionTarget") return "Primary device"; if (environment.relayManaged) return "T3 Connect"; if (environment.entry.target._tag === "SshConnectionTarget") return "SSH"; if (isDesktopLocalConnectionTarget(environment.entry.target)) return "Local device"; return environment.displayUrl ?? "Remote device";} const providerCardClassName = "rounded-xl border border-border/60 bg-card/40 shadow-xs/5";// Shared by the editor grid and the placeholder states so switching devices// never changes the card's footprint.const providerCardHeightClassName = "lg:h-[min(44rem,calc(100dvh-11rem))] lg:min-h-[32rem]"; /** * Same chrome as the provider editor (section heading, floating device tabs, * tall card) for states that cannot render provider settings yet. */function ProviderSettingsPlaceholder({ deviceTabs, icon, title, description, children,}: { readonly deviceTabs?: ReactNode; readonly icon: ReactNode; readonly title: string; readonly description: string; readonly children?: ReactNode;}) { return ( <SettingsSection {...searchableSetting("providers")} hideTitle variant="plain"> {deviceTabs ? ( <div className="flex min-h-11 min-w-0 items-center px-3 sm:px-4">{deviceTabs}</div> ) : null} <div className={cn( providerCardClassName, providerCardHeightClassName, "flex overflow-x-hidden overflow-y-auto", )} > <Empty className="min-h-88"> <EmptyMedia variant="icon">{icon}</EmptyMedia> <EmptyHeader> <EmptyTitle>{title}</EmptyTitle> <EmptyDescription>{description}</EmptyDescription> </EmptyHeader> {children ? <EmptyContent className="max-w-xl">{children}</EmptyContent> : null} </Empty> </div> </SettingsSection> );} function EnvironmentUnavailablePlaceholder({ environment, access, deviceTabs,}: { readonly environment: EnvironmentPresentation; readonly access: Exclude<ProviderEnvironmentAccess, { kind: "editable" | "read-only" }>; readonly deviceTabs?: ReactNode;}) { const isLoading = access.kind === "loading"; const title = isLoading ? "Loading provider settings" : access.kind === "error" ? "Could not connect to this device" : "Provider settings are unavailable"; // Keep the description to a short status; the raw failure can be a // multi-paragraph CLI dump, so it goes below, clamped and expandable. const description = isLoading ? access.reason === "permissions" ? "Checking what this session is allowed to change." : `Waiting for ${environment.label}'s configuration.` : connectionStatusTitle(environment.connection); const error = isLoading ? null : environment.connection.error; // No spinner: this state can persist indefinitely for a wedged device, and a // continuously repainting animation would run the whole time. return ( <ProviderSettingsPlaceholder deviceTabs={deviceTabs} icon={ <EnvironmentMachineIcon kind={resolveEnvironmentMachineKind(environment.serverConfig)} /> } title={title} description={description} > {error ? ( <ExpandableText key={environment.environmentId} text={error} className="w-full text-left font-mono text-xs leading-relaxed text-muted-foreground" /> ) : null} </ProviderSettingsPlaceholder> );} interface ProviderSettingsTarget { readonly environmentId?: EnvironmentId; readonly instanceId?: ProviderInstanceId;} export function ProviderSettingsPanel(target: ProviderSettingsTarget) { return ( <SettingsPageContainer width="wide" className="gap-8"> <ProviderSettingsPanelContent key={`${target.environmentId ?? ""}:${target.instanceId ?? ""}`} {...target} /> </SettingsPageContainer> );} function ProviderSettingsPanelContent(target: ProviderSettingsTarget) { const { environments, isReady } = useEnvironments(); const primaryEnvironmentId = usePrimaryEnvironmentId(); const searchTargetId = useSettingsSearchTargetId(); const options = useMemo( () => buildProviderEnvironmentOptions(environments, primaryEnvironmentId), [environments, primaryEnvironmentId], ); // Raw user intent; the effective selection is re-derived every render so a // device that drops out of the catalog falls back without erasing the pick — // if it reappears (e.g. after a reconnect) the selection is restored. const [selectedEnvironmentId, setSelectedEnvironmentId] = useState<EnvironmentId | null>( target.environmentId ?? primaryEnvironmentId, ); const targetEnvironmentMissing = target.environmentId !== undefined && selectedEnvironmentId === target.environmentId && !options.some((environment) => environment.environmentId === target.environmentId); const effectiveEnvironmentId = targetEnvironmentMissing ? target.environmentId : resolveSelectedProviderEnvironmentId(options, selectedEnvironmentId, primaryEnvironmentId); const selectedEnvironment = options.find((environment) => environment.environmentId === effectiveEnvironmentId) ?? null; const selectedEnvironmentCanRenderSettings = selectedEnvironment !== null && isProviderSettingsEnvironmentAvailable({ connectionPhase: selectedEnvironment.connection.phase, hasServerConfig: selectedEnvironment.serverConfig !== null, }); const searchableEnvironmentId = options.find((environment) => isProviderSettingsEnvironmentAvailable({ connectionPhase: environment.connection.phase, hasServerConfig: environment.serverConfig !== null, }), )?.environmentId; useEffect(() => { if ( (searchTargetId === searchableSetting("provider-health-check-interval").id || searchTargetId === searchableSetting("usage-providers").id) && !selectedEnvironmentCanRenderSettings && searchableEnvironmentId !== undefined ) { setSelectedEnvironmentId(searchableEnvironmentId); } }, [searchTargetId, searchableEnvironmentId, selectedEnvironmentCanRenderSettings]); const onlyPrimaryDevice = options.length === 1 && options[0]?.entry.target._tag === "PrimaryConnectionTarget"; const deviceTabs = !onlyPrimaryDevice && options.length > 0 ? ( <ScrollArea hideScrollbars scrollFade className="h-11 min-w-0 flex-1 rounded-none"> <ToggleGroup aria-label="Devices" variant="segmented" className="my-2" value={effectiveEnvironmentId ? [effectiveEnvironmentId] : []} onValueChange={(next) => { const environment = options.find((option) => option.environmentId === next[0]); if (environment) setSelectedEnvironmentId(environment.environmentId); }} > {options.map((environment) => { const machine = resolveEnvironmentMachineKind(environment.serverConfig); const detail = providerEnvironmentDetail(environment); const statusText = connectionStatusTitle(environment.connection); return ( <Tooltip key={environment.environmentId}> <TooltipTrigger render={ <Toggle value={environment.environmentId} className="gap-2 text-left"> <EnvironmentMachineIcon kind={machine} className="size-3.5 shrink-0" aria-hidden /> <span className="max-w-40 truncate">{environment.label}</span> {environment.connection.phase !== "connected" ? ( <ConnectionStatusDot dotClassName={connectionPhaseDotClassName(environment.connection.phase)} pingClassName={connectionPhasePingClassName(environment.connection.phase)} /> ) : null} <span className="sr-only"> {detail}, {statusText} </span> </Toggle> } /> <TooltipPopup side="top"> {detail} · {statusText} </TooltipPopup> </Tooltip> ); })} </ToggleGroup> </ScrollArea> ) : null; return ( <> {targetEnvironmentMissing ? ( <ProviderSettingsPlaceholder deviceTabs={deviceTabs} icon={<EnvironmentMachineIcon kind={resolveEnvironmentMachineKind(null)} />} title="Device unavailable" description="Reconnect this device to set up its provider, or select another device." /> ) : null} {options.length === 0 && !targetEnvironmentMissing ? ( <ProviderSettingsPlaceholder icon={<EnvironmentMachineIcon kind={resolveEnvironmentMachineKind(null)} />} title={isReady ? "No connected devices" : "Loading devices"} description={ isReady ? "Connect an execution environment before configuring providers." : "Reading connected execution environments." } /> ) : null} {selectedEnvironment ? ( <SelectedEnvironmentProviderSettings key={selectedEnvironment.environmentId} environment={selectedEnvironment} deviceTabs={deviceTabs} targetInstanceId={ target.environmentId === undefined || selectedEnvironment.environmentId === target.environmentId ? target.instanceId : undefined } /> ) : null} </> );} function SelectedEnvironmentProviderSettings({ environment, deviceTabs, targetInstanceId,}: { readonly environment: EnvironmentPresentation; readonly deviceTabs?: ReactNode; readonly targetInstanceId?: ProviderInstanceId | undefined;}) { const isPrimary = environment.entry.target._tag === "PrimaryConnectionTarget"; if (isPrimary) { // The desktop app owns its primary server outright; a browser session // checks the scopes its cookie session was granted. if (isElectron) { return ( <AccessGatedProviderSettings environment={environment} operateAccess="granted" deviceTabs={deviceTabs} targetInstanceId={targetInstanceId} /> ); } return ( <PrimarySessionGatedProviderSettings environment={environment} deviceTabs={deviceTabs} targetInstanceId={targetInstanceId} /> ); } return ( <RemoteSessionGatedProviderSettings environment={environment} deviceTabs={deviceTabs} targetInstanceId={targetInstanceId} /> );} function PrimarySessionGatedProviderSettings({ environment, deviceTabs, targetInstanceId,}: { readonly environment: EnvironmentPresentation; readonly deviceTabs?: ReactNode; readonly targetInstanceId?: ProviderInstanceId | undefined;}) { const primarySessionState = usePrimarySessionState(); const operateAccess = resolvePrimaryOperateAccess({ isPrimary: true, hasDesktopBridge: false, session: primarySessionState.data, isPending: primarySessionState.isPending, hasError: primarySessionState.error !== null, }); return ( <AccessGatedProviderSettings environment={environment} operateAccess={operateAccess} deviceTabs={deviceTabs} targetInstanceId={targetInstanceId} /> );} function RemoteSessionGatedProviderSettings({ environment, deviceTabs, targetInstanceId,}: { readonly environment: EnvironmentPresentation; readonly deviceTabs?: ReactNode; readonly targetInstanceId?: ProviderInstanceId | undefined;}) { const sessionState = useEnvironmentSessionState(environment.environmentId); const operateAccess = resolveRemoteOperateAccess({ session: sessionState.data, isPending: sessionState.isPending, hasError: sessionState.hasError, }); return ( <AccessGatedProviderSettings environment={environment} operateAccess={operateAccess} deviceTabs={deviceTabs}Lines 1–500 of 1160. Load more
import { RefreshIcon } from "~/components/ui/refresh-icon"; import { useAtomValue } from "@effect/atom-react"; import { connectionStatusTitle } from "@t3tools/client-runtime/connection"; import { safeErrorLogAttributes } from "@t3tools/client-runtime/errors"; import { isAtomCommandInterrupted, squashAtomCommandFailure, } from "@t3tools/client-runtime/state/runtime"; import { defaultInstanceIdForDriver, type EnvironmentId, PROVIDER_DISPLAY_NAMES, ProviderDriverKind, type ProviderInstanceConfig, type ProviderInstanceId, resolveEnvironmentMachineKind, resolveProviderInstanceEnabled, } from "@t3tools/contracts"; import { DEFAULT_UNIFIED_SETTINGS } from "@t3tools/contracts/settings"; import { getBackgroundActivityPresetSettings, resolveServerBackgroundActivitySettings, } from "@t3tools/shared/backgroundActivitySettings"; import * as Arr from "effect/Array"; import * as Duration from "effect/Duration"; import * as Equal from "effect/Equal"; import * as Result from "effect/Result"; import { PlusIcon } from "lucide-react"; import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from "react"; import { isDesktopLocalConnectionTarget } from "../../connection/desktopLocal"; import { isElectron } from "../../env"; import { usePrimarySessionState } from "../../environments/primary"; import { useEnvironmentSettings, useUpdateEnvironmentSettings } from "../../hooks/useSettings"; import { EnvironmentMachineIcon } from "../EnvironmentMachineIcon"; import { cn } from "../../lib/utils"; import { resolveAppModelSelectionState } from "../../modelSelection"; import { useEnvironments, usePrimaryEnvironmentId, type EnvironmentPresentation, } from "../../state/environments"; import { EMPTY_SERVER_PROVIDERS, serverEnvironment } from "../../state/server"; import { useEnvironmentSessionState } from "../../state/session"; import { useAtomCommand } from "../../state/use-atom-command"; import { getRelativeTimeState } from "../../timestampFormat"; import { ConnectionStatusDot, connectionPhaseDotClassName, connectionPhasePingClassName, } from "../ConnectionStatusDot"; import { isProviderSettingsUpdateCandidate, isProviderUpdateActive, type ProviderSettingsUpdateCandidate, } from "../ProviderUpdateLaunchNotification.logic"; import { Button } from "../ui/button"; import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, } from "../ui/empty"; import { NumberField, NumberFieldDecrement, NumberFieldGroup, NumberFieldIncrement, NumberFieldInput, } from "../ui/number-field"; import { ScrollArea } from "../ui/scroll-area"; import { Toggle, ToggleGroup } from "../ui/toggle-group"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; import { stackedThreadToast, toastManager } from "../ui/toast"; import { AddProviderInstanceDialog } from "./AddProviderInstanceDialog"; import { ExpandableText } from "./ExpandableText"; import { ProviderInstanceCard } from "./ProviderInstanceCard"; import { UsageProviderSettings } from "./UsageProviderSettings"; import { ProviderSetupSection, readAntigravityAuthMethod } from "./ProviderSetupSection"; import { DRIVER_OPTIONS, getDriverOption } from "./providerDriverMeta"; import { searchableSetting } from "./settingsSearch"; import { backgroundActivityOverrideSettings, buildProviderInstanceUpdatePatch, durationToSeconds, normalizeIntervalSeconds, PROVIDER_HEALTH_INTERVAL_STEP_SECONDS, } from "./SettingsPanels.logic"; import { PolicyTooltip, SettingResetButton, SettingsPageContainer, SettingsRow, SettingsSection, useRelativeTimeTick, useSettingsSearchTargetId, } from "./settingsLayout"; import { buildProviderEnvironmentOptions, classifyProviderEnvironmentAccess, isProviderSettingsEnvironmentAvailable, type ProviderEnvironmentAccess, type ProviderOperateAccess, resolvePrimaryOperateAccess, resolveRemoteOperateAccess, resolveSelectedProviderEnvironmentId, } from "./ProviderSettingsPanel.logic"; function withoutProviderInstanceKey<V>( record: Readonly<Record<ProviderInstanceId, V>> | undefined, key: ProviderInstanceId, ): Record<ProviderInstanceId, V> { const next = { ...record } as Record<ProviderInstanceId, V>; delete next[key]; return next; } function withoutProviderInstanceFavorites( favorites: ReadonlyArray<{ readonly provider: ProviderInstanceId; readonly model: string }>, instanceId: ProviderInstanceId, ) { return favorites.filter((favorite) => favorite.provider !== instanceId); } const PROVIDER_SETTINGS = DRIVER_OPTIONS.map((definition) => ({ provider: definition.value, })); function configuredBinaryPath(config: unknown): string { if (config === null || typeof config !== "object" || !("binaryPath" in config)) return ""; return typeof config.binaryPath === "string" ? config.binaryPath.trim() : ""; } function ProviderLastChecked({ lastCheckedAt }: { lastCheckedAt: string | null }) { useRelativeTimeTick(); const lastCheckedRelative = getRelativeTimeState(lastCheckedAt); if (lastCheckedRelative.status === "missing") { return null; } if (lastCheckedRelative.status === "invalid") { return <span>Checked unavailable</span>; } return ( <span> {lastCheckedRelative.suffix ? ( <> Checked <span className="font-mono tabular-nums">{lastCheckedRelative.value}</span>{" "} {lastCheckedRelative.suffix} </> ) : ( <>Checked {lastCheckedRelative.value}</> )} </span> ); } function providerEnvironmentDetail(environment: EnvironmentPresentation): string { if (environment.entry.target._tag === "PrimaryConnectionTarget") return "Primary device"; if (environment.relayManaged) return "T3 Connect"; if (environment.entry.target._tag === "SshConnectionTarget") return "SSH"; if (isDesktopLocalConnectionTarget(environment.entry.target)) return "Local device"; return environment.displayUrl ?? "Remote device"; } const providerCardClassName = "rounded-xl border border-border/60 bg-card/40 shadow-xs/5"; // Shared by the editor grid and the placeholder states so switching devices // never changes the card's footprint. const providerCardHeightClassName = "lg:h-[min(44rem,calc(100dvh-11rem))] lg:min-h-[32rem]"; /** * Same chrome as the provider editor (section heading, floating device tabs, * tall card) for states that cannot render provider settings yet. */ function ProviderSettingsPlaceholder({ deviceTabs, icon, title, description, children, }: { readonly deviceTabs?: ReactNode; readonly icon: ReactNode; readonly title: string; readonly description: string; readonly children?: ReactNode; }) { return ( <SettingsSection {...searchableSetting("providers")} hideTitle variant="plain"> {deviceTabs ? ( <div className="flex min-h-11 min-w-0 items-center px-3 sm:px-4">{deviceTabs}</div> ) : null} <div className={cn( providerCardClassName, providerCardHeightClassName, "flex overflow-x-hidden overflow-y-auto", )} > <Empty className="min-h-88"> <EmptyMedia variant="icon">{icon}</EmptyMedia> <EmptyHeader> <EmptyTitle>{title}</EmptyTitle> <EmptyDescription>{description}</EmptyDescription> </EmptyHeader> {children ? <EmptyContent className="max-w-xl">{children}</EmptyContent> : null} </Empty> </div> </SettingsSection> ); } function EnvironmentUnavailablePlaceholder({ environment, access, deviceTabs, }: { readonly environment: EnvironmentPresentation; readonly access: Exclude<ProviderEnvironmentAccess, { kind: "editable" | "read-only" }>; readonly deviceTabs?: ReactNode; }) { const isLoading = access.kind === "loading"; const title = isLoading ? "Loading provider settings" : access.kind === "error" ? "Could not connect to this device" : "Provider settings are unavailable"; // Keep the description to a short status; the raw failure can be a // multi-paragraph CLI dump, so it goes below, clamped and expandable. const description = isLoading ? access.reason === "permissions" ? "Checking what this session is allowed to change." : `Waiting for ${environment.label}'s configuration.` : connectionStatusTitle(environment.connection); const error = isLoading ? null : environment.connection.error; // No spinner: this state can persist indefinitely for a wedged device, and a // continuously repainting animation would run the whole time. return ( <ProviderSettingsPlaceholder deviceTabs={deviceTabs} icon={ <EnvironmentMachineIcon kind={resolveEnvironmentMachineKind(environment.serverConfig)} /> } title={title} description={description} > {error ? ( <ExpandableText key={environment.environmentId} text={error} className="w-full text-left font-mono text-xs leading-relaxed text-muted-foreground" /> ) : null} </ProviderSettingsPlaceholder> ); } interface ProviderSettingsTarget { readonly environmentId?: EnvironmentId; readonly instanceId?: ProviderInstanceId; } export function ProviderSettingsPanel(target: ProviderSettingsTarget) { return ( <SettingsPageContainer width="wide" className="gap-8"> <ProviderSettingsPanelContent key={`${target.environmentId ?? ""}:${target.instanceId ?? ""}`} {...target} /> </SettingsPageContainer> ); } function ProviderSettingsPanelContent(target: ProviderSettingsTarget) { const { environments, isReady } = useEnvironments(); const primaryEnvironmentId = usePrimaryEnvironmentId(); const searchTargetId = useSettingsSearchTargetId(); const options = useMemo( () => buildProviderEnvironmentOptions(environments, primaryEnvironmentId), [environments, primaryEnvironmentId], ); // Raw user intent; the effective selection is re-derived every render so a // device that drops out of the catalog falls back without erasing the pick — // if it reappears (e.g. after a reconnect) the selection is restored. const [selectedEnvironmentId, setSelectedEnvironmentId] = useState<EnvironmentId | null>( target.environmentId ?? primaryEnvironmentId, ); const targetEnvironmentMissing = target.environmentId !== undefined && selectedEnvironmentId === target.environmentId && !options.some((environment) => environment.environmentId === target.environmentId); const effectiveEnvironmentId = targetEnvironmentMissing ? target.environmentId : resolveSelectedProviderEnvironmentId(options, selectedEnvironmentId, primaryEnvironmentId); const selectedEnvironment = options.find((environment) => environment.environmentId === effectiveEnvironmentId) ?? null; const selectedEnvironmentCanRenderSettings = selectedEnvironment !== null && isProviderSettingsEnvironmentAvailable({ connectionPhase: selectedEnvironment.connection.phase, hasServerConfig: selectedEnvironment.serverConfig !== null, }); const searchableEnvironmentId = options.find((environment) => isProviderSettingsEnvironmentAvailable({ connectionPhase: environment.connection.phase, hasServerConfig: environment.serverConfig !== null, }), )?.environmentId; useEffect(() => { if ( (searchTargetId === searchableSetting("provider-health-check-interval").id || searchTargetId === searchableSetting("usage-providers").id) && !selectedEnvironmentCanRenderSettings && searchableEnvironmentId !== undefined ) { setSelectedEnvironmentId(searchableEnvironmentId); } }, [searchTargetId, searchableEnvironmentId, selectedEnvironmentCanRenderSettings]); const onlyPrimaryDevice = options.length === 1 && options[0]?.entry.target._tag === "PrimaryConnectionTarget"; const deviceTabs = !onlyPrimaryDevice && options.length > 0 ? ( <ScrollArea hideScrollbars scrollFade className="h-11 min-w-0 flex-1 rounded-none"> <ToggleGroup aria-label="Devices" variant="segmented" className="my-2" value={effectiveEnvironmentId ? [effectiveEnvironmentId] : []} onValueChange={(next) => { const environment = options.find((option) => option.environmentId === next[0]); if (environment) setSelectedEnvironmentId(environment.environmentId); }} > {options.map((environment) => { const machine = resolveEnvironmentMachineKind(environment.serverConfig); const detail = providerEnvironmentDetail(environment); const statusText = connectionStatusTitle(environment.connection); return ( <Tooltip key={environment.environmentId}> <TooltipTrigger render={ <Toggle value={environment.environmentId} className="gap-2 text-left"> <EnvironmentMachineIcon kind={machine} className="size-3.5 shrink-0" aria-hidden /> <span className="max-w-40 truncate">{environment.label}</span> {environment.connection.phase !== "connected" ? ( <ConnectionStatusDot dotClassName={connectionPhaseDotClassName(environment.connection.phase)} pingClassName={connectionPhasePingClassName(environment.connection.phase)} /> ) : null} <span className="sr-only"> {detail}, {statusText} </span> </Toggle> } /> <TooltipPopup side="top"> {detail} · {statusText} </TooltipPopup> </Tooltip> ); })} </ToggleGroup> </ScrollArea> ) : null; return ( <> {targetEnvironmentMissing ? ( <ProviderSettingsPlaceholder deviceTabs={deviceTabs} icon={<EnvironmentMachineIcon kind={resolveEnvironmentMachineKind(null)} />} title="Device unavailable" description="Reconnect this device to set up its provider, or select another device." /> ) : null} {options.length === 0 && !targetEnvironmentMissing ? ( <ProviderSettingsPlaceholder icon={<EnvironmentMachineIcon kind={resolveEnvironmentMachineKind(null)} />} title={isReady ? "No connected devices" : "Loading devices"} description={ isReady ? "Connect an execution environment before configuring providers." : "Reading connected execution environments." } /> ) : null} {selectedEnvironment ? ( <SelectedEnvironmentProviderSettings key={selectedEnvironment.environmentId} environment={selectedEnvironment} deviceTabs={deviceTabs} targetInstanceId={ target.environmentId === undefined || selectedEnvironment.environmentId === target.environmentId ? target.instanceId : undefined } /> ) : null} </> ); } function SelectedEnvironmentProviderSettings({ environment, deviceTabs, targetInstanceId, }: { readonly environment: EnvironmentPresentation; readonly deviceTabs?: ReactNode; readonly targetInstanceId?: ProviderInstanceId | undefined; }) { const isPrimary = environment.entry.target._tag === "PrimaryConnectionTarget"; if (isPrimary) { // The desktop app owns its primary server outright; a browser session // checks the scopes its cookie session was granted. if (isElectron) { return ( <AccessGatedProviderSettings environment={environment} operateAccess="granted" deviceTabs={deviceTabs} targetInstanceId={targetInstanceId} /> ); } return ( <PrimarySessionGatedProviderSettings environment={environment} deviceTabs={deviceTabs} targetInstanceId={targetInstanceId} /> ); } return ( <RemoteSessionGatedProviderSettings environment={environment} deviceTabs={deviceTabs} targetInstanceId={targetInstanceId} /> ); } function PrimarySessionGatedProviderSettings({ environment, deviceTabs, targetInstanceId, }: { readonly environment: EnvironmentPresentation; readonly deviceTabs?: ReactNode; readonly targetInstanceId?: ProviderInstanceId | undefined; }) { const primarySessionState = usePrimarySessionState(); const operateAccess = resolvePrimaryOperateAccess({ isPrimary: true, hasDesktopBridge: false, session: primarySessionState.data, isPending: primarySessionState.isPending, hasError: primarySessionState.error !== null, }); return ( <AccessGatedProviderSettings environment={environment} operateAccess={operateAccess} deviceTabs={deviceTabs} targetInstanceId={targetInstanceId} /> ); } function RemoteSessionGatedProviderSettings({ environment, deviceTabs, targetInstanceId, }: { readonly environment: EnvironmentPresentation; readonly deviceTabs?: ReactNode; readonly targetInstanceId?: ProviderInstanceId | undefined; }) { const sessionState = useEnvironmentSessionState(environment.environmentId); const operateAccess = resolveRemoteOperateAccess({ session: sessionState.data, isPending: sessionState.isPending, hasError: sessionState.hasError, }); return ( <AccessGatedProviderSettings environment={environment} operateAccess={operateAccess} deviceTabs={deviceTabs}