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,} 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 { CloudIcon, LaptopIcon, LoaderIcon, MonitorIcon, PlusIcon, RefreshCwIcon, TerminalIcon,} from "lucide-react";import { useCallback, useMemo, useRef, useState } 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 { NumberField, NumberFieldDecrement, NumberFieldGroup, NumberFieldIncrement, NumberFieldInput,} from "../ui/number-field";import { stackedThreadToast, toastManager } from "../ui/toast";import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";import { AddProviderInstanceDialog } from "./AddProviderInstanceDialog";import { ProviderInstanceCard } from "./ProviderInstanceCard";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,} from "./settingsLayout";import { buildProviderEnvironmentOptions, classifyProviderEnvironmentAccess, 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 className="text-[11px] text-muted-foreground/50">Checked unavailable</span>; } return ( <span className="text-[11px] text-muted-foreground/60"> {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,}: { readonly environment: EnvironmentPresentation; readonly access: Exclude<ProviderEnvironmentAccess, { kind: "editable" | "read-only" }>;}) { 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 title="Providers"> <SettingsRow title={title} description={description} /> </SettingsSection> );} export function ProviderSettingsPanel() { const { environments, isReady } = useEnvironments(); const primaryEnvironmentId = usePrimaryEnvironmentId(); 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 onlyPrimaryDevice = options.length === 1 && options[0]?.entry.target._tag === "PrimaryConnectionTarget"; return ( <SettingsPageContainer> {!onlyPrimaryDevice ? ( <SettingsSection title="Devices"> {options.length === 0 ? ( // The catalog hydrates asynchronously, so an empty list before it is // ready means "not loaded yet", not "nothing is connected". <SettingsRow title={isReady ? "No connected devices" : "Loading devices"} description={ isReady ? "Connect an execution environment before configuring providers." : "Reading connected execution environments." } /> ) : ( <div className="grid gap-1 sm:grid-cols-2"> {options.map((environment) => { const Icon = providerEnvironmentIcon(environment); const selected = environment.environmentId === effectiveEnvironmentId; const statusText = connectionStatusText(environment.connection); return ( <button key={environment.environmentId} type="button" aria-pressed={selected} className={cn( "flex min-w-0 items-center gap-3 rounded-xl px-3 py-2.5 text-left transition-colors sm:px-4", selected ? "bg-primary/8 ring-1 ring-primary/25 dark:bg-primary/12" : "hover:bg-muted/40", )} onClick={() => setSelectedEnvironmentId(environment.environmentId)} > <span className="flex size-8 shrink-0 items-center justify-center rounded-lg border border-border/60 bg-background text-muted-foreground"> <Icon className="size-4" aria-hidden /> </span> <span className="min-w-0 flex-1"> <span className="flex items-center gap-1.5"> <ConnectionStatusDot tooltipText={statusText} dotClassName={connectionPhaseDotClassName(environment.connection.phase)} pingClassName={connectionPhasePingClassName(environment.connection.phase)} /> <span className="truncate text-sm font-medium text-foreground"> {environment.label} </span> </span> <span className="block truncate pl-[18px] text-xs text-muted-foreground"> {providerEnvironmentDetail(environment)} · {statusText} </span> </span> </button> ); })} </div> )} </SettingsSection> ) : null} {selectedEnvironment ? ( <SelectedEnvironmentProviderSettings key={selectedEnvironment.environmentId} environment={selectedEnvironment} /> ) : null} </SettingsPageContainer> );} function SelectedEnvironmentProviderSettings({ environment,}: { readonly environment: EnvironmentPresentation;}) { 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" />; } return <PrimarySessionGatedProviderSettings environment={environment} />; } return <RemoteSessionGatedProviderSettings environment={environment} />;} function PrimarySessionGatedProviderSettings({ environment,}: { readonly environment: EnvironmentPresentation;}) { 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} />;} function RemoteSessionGatedProviderSettings({ environment,}: { readonly environment: EnvironmentPresentation;}) { const sessionState = useEnvironmentSessionState(environment.environmentId); const operateAccess = resolveRemoteOperateAccess({ session: sessionState.data, isPending: sessionState.isPending, hasError: sessionState.hasError, }); return <AccessGatedProviderSettings environment={environment} operateAccess={operateAccess} />;} function AccessGatedProviderSettings({ environment, operateAccess,}: { readonly environment: EnvironmentPresentation; readonly operateAccess: ProviderOperateAccess;}) { 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} />; } return ( <EnvironmentProviderSettings environmentId={environment.environmentId} environmentLabel={environment.label} readOnly={access.kind === "read-only"} /> );} export function EnvironmentProviderSettings({ environmentId, environmentLabel, readOnly = false,}: { readonly environmentId: EnvironmentId; readonly environmentLabel: string; /** * Render the full provider layout, greyed out and inert, when this session's * credential lacks `orchestration:operate` on the environment. Showing the * real configuration keeps the view honest; disabling interaction keeps * every one of its writes from being 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 [updatingProviderDrivers, setUpdatingProviderDrivers] = useState< ReadonlySet<ProviderDriverKind> >(() => new Set()); const [openInstanceDetails, setOpenInstanceDetails] = useState<Record<string, boolean>>({}); const refreshingRef = useRef(false); const updatingDriversRef = useRef<Set<ProviderDriverKind>>(new Set()); 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, ); const defaultProviderHealthRefreshIntervalSeconds = durationToSeconds(providerHealthPreset); const lastCheckedAt = serverProviders.length > 0 ? serverProviders.reduce( (latest, provider) => (provider.checkedAt > latest ? provider.checkedAt : latest), serverProviders[0]!.checkedAt, ) : null; const refreshProviders = useCallback(() => { if (refreshingRef.current) return; refreshingRef.current = true; setIsRefreshingProviders(true); void (async () => { const result = await refreshServerProviders({ environmentId, input: {}, }); refreshingRef.current = false; setIsRefreshingProviders(false); if (result._tag === "Failure" && !isAtomCommandInterrupted(result)) { console.warn("Failed to refresh providers", { operation: "refresh-providers", environmentId, ...safeErrorLogAttributes(squashAtomCommandFailure(result)), }); } })(); }, [environmentId, refreshServerProviders]); const runProviderUpdate = useCallback( async (candidate: ProviderUpdateCandidate) => { // Ref-based re-entry guard, mirroring refreshProviders: a state updater // may run after this function returns, so it cannot gate the dispatch. if (updatingDriversRef.current.has(candidate.driver)) { return; } updatingDriversRef.current.add(candidate.driver); setUpdatingProviderDrivers((previous) => new Set(previous).add(candidate.driver)); const result = await updateProvider({ environmentId, input: { provider: candidate.driver, instanceId: candidate.instanceId, }, }); if (result._tag === "Failure" && !isAtomCommandInterrupted(result)) { const error = squashAtomCommandFailure(result); toastManager.add( stackedThreadToast({ type: "error", title: `Could not update ${PROVIDER_DISPLAY_NAMES[candidate.driver] ?? candidate.driver}`, description: error instanceof Error ? error.message : "The provider update command could not be started.", }), ); } updatingDriversRef.current.delete(candidate.driver); setUpdatingProviderDrivers((previous) => { if (!previous.has(candidate.driver)) { return previous; } const next = new Set(previous); next.delete(candidate.driver); return next; }); }, [environmentId, updateProvider], ); interface InstanceRow { readonly instanceId: ProviderInstanceId; readonly instance: ProviderInstanceConfig; readonly driver: ProviderDriverKind; readonly isDefault: boolean; readonly isDirty?: boolean; } const instancesByDriver = new Map< ProviderDriverKind, Array<[ProviderInstanceId, ProviderInstanceConfig]> >(); for (const [rawId, instance] of Object.entries(settings.providerInstances ?? {})) { const driver = instance.driver;Lines 1–500 of 902. 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, } 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 { CloudIcon, LaptopIcon, LoaderIcon, MonitorIcon, PlusIcon, RefreshCwIcon, TerminalIcon, } from "lucide-react"; import { useCallback, useMemo, useRef, useState } 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 { NumberField, NumberFieldDecrement, NumberFieldGroup, NumberFieldIncrement, NumberFieldInput, } from "../ui/number-field"; import { stackedThreadToast, toastManager } from "../ui/toast"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; import { AddProviderInstanceDialog } from "./AddProviderInstanceDialog"; import { ProviderInstanceCard } from "./ProviderInstanceCard"; 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, } from "./settingsLayout"; import { buildProviderEnvironmentOptions, classifyProviderEnvironmentAccess, 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 className="text-[11px] text-muted-foreground/50">Checked unavailable</span>; } return ( <span className="text-[11px] text-muted-foreground/60"> {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, }: { readonly environment: EnvironmentPresentation; readonly access: Exclude<ProviderEnvironmentAccess, { kind: "editable" | "read-only" }>; }) { 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 title="Providers"> <SettingsRow title={title} description={description} /> </SettingsSection> ); } export function ProviderSettingsPanel() { const { environments, isReady } = useEnvironments(); const primaryEnvironmentId = usePrimaryEnvironmentId(); 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 onlyPrimaryDevice = options.length === 1 && options[0]?.entry.target._tag === "PrimaryConnectionTarget"; return ( <SettingsPageContainer> {!onlyPrimaryDevice ? ( <SettingsSection title="Devices"> {options.length === 0 ? ( // The catalog hydrates asynchronously, so an empty list before it is // ready means "not loaded yet", not "nothing is connected". <SettingsRow title={isReady ? "No connected devices" : "Loading devices"} description={ isReady ? "Connect an execution environment before configuring providers." : "Reading connected execution environments." } /> ) : ( <div className="grid gap-1 sm:grid-cols-2"> {options.map((environment) => { const Icon = providerEnvironmentIcon(environment); const selected = environment.environmentId === effectiveEnvironmentId; const statusText = connectionStatusText(environment.connection); return ( <button key={environment.environmentId} type="button" aria-pressed={selected} className={cn( "flex min-w-0 items-center gap-3 rounded-xl px-3 py-2.5 text-left transition-colors sm:px-4", selected ? "bg-primary/8 ring-1 ring-primary/25 dark:bg-primary/12" : "hover:bg-muted/40", )} onClick={() => setSelectedEnvironmentId(environment.environmentId)} > <span className="flex size-8 shrink-0 items-center justify-center rounded-lg border border-border/60 bg-background text-muted-foreground"> <Icon className="size-4" aria-hidden /> </span> <span className="min-w-0 flex-1"> <span className="flex items-center gap-1.5"> <ConnectionStatusDot tooltipText={statusText} dotClassName={connectionPhaseDotClassName(environment.connection.phase)} pingClassName={connectionPhasePingClassName(environment.connection.phase)} /> <span className="truncate text-sm font-medium text-foreground"> {environment.label} </span> </span> <span className="block truncate pl-[18px] text-xs text-muted-foreground"> {providerEnvironmentDetail(environment)} · {statusText} </span> </span> </button> ); })} </div> )} </SettingsSection> ) : null} {selectedEnvironment ? ( <SelectedEnvironmentProviderSettings key={selectedEnvironment.environmentId} environment={selectedEnvironment} /> ) : null} </SettingsPageContainer> ); } function SelectedEnvironmentProviderSettings({ environment, }: { readonly environment: EnvironmentPresentation; }) { 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" />; } return <PrimarySessionGatedProviderSettings environment={environment} />; } return <RemoteSessionGatedProviderSettings environment={environment} />; } function PrimarySessionGatedProviderSettings({ environment, }: { readonly environment: EnvironmentPresentation; }) { 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} />; } function RemoteSessionGatedProviderSettings({ environment, }: { readonly environment: EnvironmentPresentation; }) { const sessionState = useEnvironmentSessionState(environment.environmentId); const operateAccess = resolveRemoteOperateAccess({ session: sessionState.data, isPending: sessionState.isPending, hasError: sessionState.hasError, }); return <AccessGatedProviderSettings environment={environment} operateAccess={operateAccess} />; } function AccessGatedProviderSettings({ environment, operateAccess, }: { readonly environment: EnvironmentPresentation; readonly operateAccess: ProviderOperateAccess; }) { 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} />; } return ( <EnvironmentProviderSettings environmentId={environment.environmentId} environmentLabel={environment.label} readOnly={access.kind === "read-only"} /> ); } export function EnvironmentProviderSettings({ environmentId, environmentLabel, readOnly = false, }: { readonly environmentId: EnvironmentId; readonly environmentLabel: string; /** * Render the full provider layout, greyed out and inert, when this session's * credential lacks `orchestration:operate` on the environment. Showing the * real configuration keeps the view honest; disabling interaction keeps * every one of its writes from being 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 [updatingProviderDrivers, setUpdatingProviderDrivers] = useState< ReadonlySet<ProviderDriverKind> >(() => new Set()); const [openInstanceDetails, setOpenInstanceDetails] = useState<Record<string, boolean>>({}); const refreshingRef = useRef(false); const updatingDriversRef = useRef<Set<ProviderDriverKind>>(new Set()); 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, ); const defaultProviderHealthRefreshIntervalSeconds = durationToSeconds(providerHealthPreset); const lastCheckedAt = serverProviders.length > 0 ? serverProviders.reduce( (latest, provider) => (provider.checkedAt > latest ? provider.checkedAt : latest), serverProviders[0]!.checkedAt, ) : null; const refreshProviders = useCallback(() => { if (refreshingRef.current) return; refreshingRef.current = true; setIsRefreshingProviders(true); void (async () => { const result = await refreshServerProviders({ environmentId, input: {}, }); refreshingRef.current = false; setIsRefreshingProviders(false); if (result._tag === "Failure" && !isAtomCommandInterrupted(result)) { console.warn("Failed to refresh providers", { operation: "refresh-providers", environmentId, ...safeErrorLogAttributes(squashAtomCommandFailure(result)), }); } })(); }, [environmentId, refreshServerProviders]); const runProviderUpdate = useCallback( async (candidate: ProviderUpdateCandidate) => { // Ref-based re-entry guard, mirroring refreshProviders: a state updater // may run after this function returns, so it cannot gate the dispatch. if (updatingDriversRef.current.has(candidate.driver)) { return; } updatingDriversRef.current.add(candidate.driver); setUpdatingProviderDrivers((previous) => new Set(previous).add(candidate.driver)); const result = await updateProvider({ environmentId, input: { provider: candidate.driver, instanceId: candidate.instanceId, }, }); if (result._tag === "Failure" && !isAtomCommandInterrupted(result)) { const error = squashAtomCommandFailure(result); toastManager.add( stackedThreadToast({ type: "error", title: `Could not update ${PROVIDER_DISPLAY_NAMES[candidate.driver] ?? candidate.driver}`, description: error instanceof Error ? error.message : "The provider update command could not be started.", }), ); } updatingDriversRef.current.delete(candidate.driver); setUpdatingProviderDrivers((previous) => { if (!previous.has(candidate.driver)) { return previous; } const next = new Set(previous); next.delete(candidate.driver); return next; }); }, [environmentId, updateProvider], ); interface InstanceRow { readonly instanceId: ProviderInstanceId; readonly instance: ProviderInstanceConfig; readonly driver: ProviderDriverKind; readonly isDefault: boolean; readonly isDirty?: boolean; } const instancesByDriver = new Map< ProviderDriverKind, Array<[ProviderInstanceId, ProviderInstanceConfig]> >(); for (const [rawId, instance] of Object.entries(settings.providerInstances ?? {})) { const driver = instance.driver;