import { useAtomValue } from "@effect/atom-react";import { connectionStatusText } 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, 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 { ChevronDownIcon, CloudIcon, LaptopIcon, LoaderIcon, MonitorIcon, PlusIcon, RefreshCwIcon, TerminalIcon,} 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 { 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 { canOneClickUpdateProviderCandidate, collectProviderUpdateCandidates, hasOneClickUpdateProviderCandidate, isProviderUpdateActive, type ProviderUpdateCandidate,} from "../ProviderUpdateLaunchNotification.logic";import { Button } from "../ui/button";import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../ui/collapsible";import { NumberField, NumberFieldDecrement, NumberFieldGroup, NumberFieldIncrement, NumberFieldInput,} from "../ui/number-field";import { ScrollArea } from "../ui/scroll-area";import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";import { stackedThreadToast, toastManager } from "../ui/toast";import { AddProviderInstanceDialog } from "./AddProviderInstanceDialog";import { ProviderInstanceCard } from "./ProviderInstanceCard";import { DRIVER_OPTIONS, getDriverOption } from "./providerDriverMeta";import { providerSettingsTabClassName } from "./providerSettingsTabs";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 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 providerEnvironmentIcon(environment: EnvironmentPresentation) { if (environment.entry.target._tag === "PrimaryConnectionTarget") return MonitorIcon; if (environment.entry.target._tag === "RelayConnectionTarget") return CloudIcon; if (environment.entry.target._tag === "SshConnectionTarget") return TerminalIcon; if (isDesktopLocalConnectionTarget(environment.entry.target)) return LaptopIcon; return CloudIcon;} 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";} function EnvironmentUnavailableRow({ 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"; const description = isLoading ? access.reason === "permissions" ? "Checking what this session is allowed to change." : `Waiting for ${environment.label}'s configuration.` : connectionStatusText(environment.connection); // No spinner: this state can persist indefinitely for a wedged device, and a // continuously repainting animation would run the whole time. return ( <SettingsSection {...searchableSetting("providers")}> {deviceTabs} <SettingsRow title={title} description={description} /> </SettingsSection> );} export function ProviderSettingsPanel() { return ( <SettingsPageContainer className="gap-8"> <ProviderSettingsPanelContent /> </SettingsPageContainer> );} function ProviderSettingsPanelContent() { 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>( primaryEnvironmentId, ); const effectiveEnvironmentId = 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 && !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="mx-3 h-11 min-w-0 rounded-none sm:mx-4"> <div role="group" aria-label="Devices" className="flex h-full w-max min-w-full border-b border-border/70 px-1" > {options.map((environment) => { const Icon = providerEnvironmentIcon(environment); const selected = environment.environmentId === effectiveEnvironmentId; const detail = providerEnvironmentDetail(environment); const statusText = connectionStatusText(environment.connection); return ( <Tooltip key={environment.environmentId}> <TooltipTrigger render={ <button type="button" aria-pressed={selected} className={cn(providerSettingsTabClassName(selected), "gap-2 text-left")} onClick={() => setSelectedEnvironmentId(environment.environmentId)} > <Icon 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> </button> } /> <TooltipPopup side="top"> {detail} · {statusText} </TooltipPopup> </Tooltip> ); })} </div> </ScrollArea> ) : null; return ( <> {options.length === 0 ? ( <SettingsSection {...searchableSetting("providers")}> <SettingsRow title={isReady ? "No connected devices" : "Loading devices"} description={ isReady ? "Connect an execution environment before configuring providers." : "Reading connected execution environments." } /> </SettingsSection> ) : null} {selectedEnvironment ? ( <SelectedEnvironmentProviderSettings key={selectedEnvironment.environmentId} environment={selectedEnvironment} deviceTabs={deviceTabs} /> ) : null} </> );} function SelectedEnvironmentProviderSettings({ environment, deviceTabs,}: { readonly environment: EnvironmentPresentation; readonly deviceTabs?: ReactNode;}) { 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} /> ); } return ( <PrimarySessionGatedProviderSettings environment={environment} deviceTabs={deviceTabs} /> ); } return <RemoteSessionGatedProviderSettings environment={environment} deviceTabs={deviceTabs} />;} function PrimarySessionGatedProviderSettings({ environment, deviceTabs,}: { readonly environment: EnvironmentPresentation; readonly deviceTabs?: ReactNode;}) { 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} /> );} function RemoteSessionGatedProviderSettings({ environment, deviceTabs,}: { readonly environment: EnvironmentPresentation; readonly deviceTabs?: ReactNode;}) { 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} /> );} function AccessGatedProviderSettings({ environment, operateAccess, deviceTabs,}: { readonly environment: EnvironmentPresentation; readonly operateAccess: ProviderOperateAccess; readonly deviceTabs?: ReactNode;}) { const access = classifyProviderEnvironmentAccess({ connectionPhase: environment.connection.phase, hasServerConfig: environment.serverConfig !== null, operateAccess, }); if (access.kind !== "editable" && access.kind !== "read-only") { return ( <EnvironmentUnavailableRow environment={environment} access={access} deviceTabs={deviceTabs} /> ); } return ( <EnvironmentProviderSettings environmentId={environment.environmentId} environmentLabel={environment.label} readOnly={access.kind === "read-only"} deviceTabs={deviceTabs} /> );} export function EnvironmentProviderSettings({ environmentId, environmentLabel, readOnly = false, deviceTabs,}: { readonly environmentId: EnvironmentId; readonly environmentLabel: string; readonly deviceTabs?: ReactNode; /** * Grey out and freeze every write control when this session's credential * lacks `orchestration:operate` on the environment. Selecting providers and * opening Advanced still work so the real configuration stays readable; * switches, forms, and the health interval are inert so no write is * offered and then rejected. */ readonly readOnly?: boolean;}) { const settings = useEnvironmentSettings(environmentId); const updateSettings = useUpdateEnvironmentSettings(environmentId); const serverProviders = useAtomValue(serverEnvironment.providersValueAtom(environmentId)) ?? EMPTY_SERVER_PROVIDERS; const refreshServerProviders = useAtomCommand(serverEnvironment.refreshProviders, { reportFailure: false, }); const updateProvider = useAtomCommand(serverEnvironment.updateProvider, { reportFailure: false, }); const [isRefreshingProviders, setIsRefreshingProviders] = useState(false); const [isAddInstanceDialogOpen, setIsAddInstanceDialogOpen] = useState(false); const [selectedInstanceId, setSelectedInstanceId] = useState<ProviderInstanceId | null>(null); const [advancedOpen, setAdvancedOpen] = useState(false); const searchTargetId = useSettingsSearchTargetId(); const [updatingProviderDrivers, setUpdatingProviderDrivers] = useState< ReadonlySet<ProviderDriverKind> >(() => new Set()); const refreshingRef = useRef(false); const updatingDriversRef = useRef<Set<ProviderDriverKind>>(new Set()); useEffect(() => { if (searchTargetId === searchableSetting("provider-health-check-interval").id) { setAdvancedOpen(true); } }, [searchTargetId]); const providerUpdateCandidates = useMemo( () => collectProviderUpdateCandidates(serverProviders), [serverProviders], ); const providerUpdateCandidateByInstanceId = useMemo( () => new Map(providerUpdateCandidates.map((candidate) => [candidate.instanceId, candidate])), [providerUpdateCandidates], ); const visibleProviderSettings = PROVIDER_SETTINGS.filter( (providerSettings) => providerSettings.provider !== "cursor" || serverProviders.some( (provider) => provider.instanceId === defaultInstanceIdForDriver(ProviderDriverKind.make("cursor")), ), ); const textGenerationModelSelection = resolveAppModelSelectionState(settings, serverProviders); const textGenInstanceId = textGenerationModelSelection.instanceId; const resolvedBackgroundActivity = resolveServerBackgroundActivitySettings(settings); const providerHealthPreset = getBackgroundActivityPresetSettings( resolvedBackgroundActivity.profile, ).providerHealthRefreshInterval; const providerHealthRefreshIntervalSeconds = durationToSeconds( resolvedBackgroundActivity.providerHealthRefreshInterval,Lines 1–500 of 1036. Load more
import { useAtomValue } from "@effect/atom-react"; import { connectionStatusText } 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, 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 { ChevronDownIcon, CloudIcon, LaptopIcon, LoaderIcon, MonitorIcon, PlusIcon, RefreshCwIcon, TerminalIcon, } 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 { 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 { canOneClickUpdateProviderCandidate, collectProviderUpdateCandidates, hasOneClickUpdateProviderCandidate, isProviderUpdateActive, type ProviderUpdateCandidate, } from "../ProviderUpdateLaunchNotification.logic"; import { Button } from "../ui/button"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../ui/collapsible"; import { NumberField, NumberFieldDecrement, NumberFieldGroup, NumberFieldIncrement, NumberFieldInput, } from "../ui/number-field"; import { ScrollArea } from "../ui/scroll-area"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; import { stackedThreadToast, toastManager } from "../ui/toast"; import { AddProviderInstanceDialog } from "./AddProviderInstanceDialog"; import { ProviderInstanceCard } from "./ProviderInstanceCard"; import { DRIVER_OPTIONS, getDriverOption } from "./providerDriverMeta"; import { providerSettingsTabClassName } from "./providerSettingsTabs"; 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 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 providerEnvironmentIcon(environment: EnvironmentPresentation) { if (environment.entry.target._tag === "PrimaryConnectionTarget") return MonitorIcon; if (environment.entry.target._tag === "RelayConnectionTarget") return CloudIcon; if (environment.entry.target._tag === "SshConnectionTarget") return TerminalIcon; if (isDesktopLocalConnectionTarget(environment.entry.target)) return LaptopIcon; return CloudIcon; } 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"; } function EnvironmentUnavailableRow({ 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"; const description = isLoading ? access.reason === "permissions" ? "Checking what this session is allowed to change." : `Waiting for ${environment.label}'s configuration.` : connectionStatusText(environment.connection); // No spinner: this state can persist indefinitely for a wedged device, and a // continuously repainting animation would run the whole time. return ( <SettingsSection {...searchableSetting("providers")}> {deviceTabs} <SettingsRow title={title} description={description} /> </SettingsSection> ); } export function ProviderSettingsPanel() { return ( <SettingsPageContainer className="gap-8"> <ProviderSettingsPanelContent /> </SettingsPageContainer> ); } function ProviderSettingsPanelContent() { 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>( primaryEnvironmentId, ); const effectiveEnvironmentId = 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 && !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="mx-3 h-11 min-w-0 rounded-none sm:mx-4"> <div role="group" aria-label="Devices" className="flex h-full w-max min-w-full border-b border-border/70 px-1" > {options.map((environment) => { const Icon = providerEnvironmentIcon(environment); const selected = environment.environmentId === effectiveEnvironmentId; const detail = providerEnvironmentDetail(environment); const statusText = connectionStatusText(environment.connection); return ( <Tooltip key={environment.environmentId}> <TooltipTrigger render={ <button type="button" aria-pressed={selected} className={cn(providerSettingsTabClassName(selected), "gap-2 text-left")} onClick={() => setSelectedEnvironmentId(environment.environmentId)} > <Icon 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> </button> } /> <TooltipPopup side="top"> {detail} · {statusText} </TooltipPopup> </Tooltip> ); })} </div> </ScrollArea> ) : null; return ( <> {options.length === 0 ? ( <SettingsSection {...searchableSetting("providers")}> <SettingsRow title={isReady ? "No connected devices" : "Loading devices"} description={ isReady ? "Connect an execution environment before configuring providers." : "Reading connected execution environments." } /> </SettingsSection> ) : null} {selectedEnvironment ? ( <SelectedEnvironmentProviderSettings key={selectedEnvironment.environmentId} environment={selectedEnvironment} deviceTabs={deviceTabs} /> ) : null} </> ); } function SelectedEnvironmentProviderSettings({ environment, deviceTabs, }: { readonly environment: EnvironmentPresentation; readonly deviceTabs?: ReactNode; }) { 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} /> ); } return ( <PrimarySessionGatedProviderSettings environment={environment} deviceTabs={deviceTabs} /> ); } return <RemoteSessionGatedProviderSettings environment={environment} deviceTabs={deviceTabs} />; } function PrimarySessionGatedProviderSettings({ environment, deviceTabs, }: { readonly environment: EnvironmentPresentation; readonly deviceTabs?: ReactNode; }) { 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} /> ); } function RemoteSessionGatedProviderSettings({ environment, deviceTabs, }: { readonly environment: EnvironmentPresentation; readonly deviceTabs?: ReactNode; }) { 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} /> ); } function AccessGatedProviderSettings({ environment, operateAccess, deviceTabs, }: { readonly environment: EnvironmentPresentation; readonly operateAccess: ProviderOperateAccess; readonly deviceTabs?: ReactNode; }) { const access = classifyProviderEnvironmentAccess({ connectionPhase: environment.connection.phase, hasServerConfig: environment.serverConfig !== null, operateAccess, }); if (access.kind !== "editable" && access.kind !== "read-only") { return ( <EnvironmentUnavailableRow environment={environment} access={access} deviceTabs={deviceTabs} /> ); } return ( <EnvironmentProviderSettings environmentId={environment.environmentId} environmentLabel={environment.label} readOnly={access.kind === "read-only"} deviceTabs={deviceTabs} /> ); } export function EnvironmentProviderSettings({ environmentId, environmentLabel, readOnly = false, deviceTabs, }: { readonly environmentId: EnvironmentId; readonly environmentLabel: string; readonly deviceTabs?: ReactNode; /** * Grey out and freeze every write control when this session's credential * lacks `orchestration:operate` on the environment. Selecting providers and * opening Advanced still work so the real configuration stays readable; * switches, forms, and the health interval are inert so no write is * offered and then rejected. */ readonly readOnly?: boolean; }) { const settings = useEnvironmentSettings(environmentId); const updateSettings = useUpdateEnvironmentSettings(environmentId); const serverProviders = useAtomValue(serverEnvironment.providersValueAtom(environmentId)) ?? EMPTY_SERVER_PROVIDERS; const refreshServerProviders = useAtomCommand(serverEnvironment.refreshProviders, { reportFailure: false, }); const updateProvider = useAtomCommand(serverEnvironment.updateProvider, { reportFailure: false, }); const [isRefreshingProviders, setIsRefreshingProviders] = useState(false); const [isAddInstanceDialogOpen, setIsAddInstanceDialogOpen] = useState(false); const [selectedInstanceId, setSelectedInstanceId] = useState<ProviderInstanceId | null>(null); const [advancedOpen, setAdvancedOpen] = useState(false); const searchTargetId = useSettingsSearchTargetId(); const [updatingProviderDrivers, setUpdatingProviderDrivers] = useState< ReadonlySet<ProviderDriverKind> >(() => new Set()); const refreshingRef = useRef(false); const updatingDriversRef = useRef<Set<ProviderDriverKind>>(new Set()); useEffect(() => { if (searchTargetId === searchableSetting("provider-health-check-interval").id) { setAdvancedOpen(true); } }, [searchTargetId]); const providerUpdateCandidates = useMemo( () => collectProviderUpdateCandidates(serverProviders), [serverProviders], ); const providerUpdateCandidateByInstanceId = useMemo( () => new Map(providerUpdateCandidates.map((candidate) => [candidate.instanceId, candidate])), [providerUpdateCandidates], ); const visibleProviderSettings = PROVIDER_SETTINGS.filter( (providerSettings) => providerSettings.provider !== "cursor" || serverProviders.some( (provider) => provider.instanceId === defaultInstanceIdForDriver(ProviderDriverKind.make("cursor")), ), ); const textGenerationModelSelection = resolveAppModelSelectionState(settings, serverProviders); const textGenInstanceId = textGenerationModelSelection.instanceId; const resolvedBackgroundActivity = resolveServerBackgroundActivitySettings(settings); const providerHealthPreset = getBackgroundActivityPresetSettings( resolvedBackgroundActivity.profile, ).providerHealthRefreshInterval; const providerHealthRefreshIntervalSeconds = durationToSeconds( resolvedBackgroundActivity.providerHealthRefreshInterval,