2747 lines · 96.6 KB · TypeScript
RawDownload
import {  ChevronDownIcon,  ChevronsLeftRightEllipsisIcon,  PlusIcon,  QrCodeIcon,  RefreshCwIcon,  TerminalIcon,  TriangleAlertIcon,} from "lucide-react";import { type ReactNode, memo, useCallback, useEffect, useMemo, useState } from "react";import {  type AuthClientSession,  type AuthPairingLink,  type AdvertisedEndpoint,  type DesktopDiscoveredSshHost,  type DesktopSshEnvironmentTarget,  type DesktopServerExposureState,  type EnvironmentId,} from "@t3tools/contracts";import * as DateTime from "effect/DateTime"; import { useCopyToClipboard } from "../../hooks/useCopyToClipboard";import { cn } from "../../lib/utils";import { formatElapsedDurationLabel, formatExpiresInLabel } from "../../timestampFormat";import { resolveDesktopPairingUrl, resolveHostedPairingUrl } from "./pairingUrls";import {  SettingsPageContainer,  SettingsRow,  SettingsSection,  useRelativeTimeTick,} from "./settingsLayout";import { Input } from "../ui/input";import {  Dialog,  DialogClose,  DialogFooter,  DialogDescription,  DialogHeader,  DialogPanel,  DialogPopup,  DialogTitle,  DialogTrigger,} from "../ui/dialog";import { ScrollArea } from "../ui/scroll-area";import {  AlertDialog,  AlertDialogClose,  AlertDialogDescription,  AlertDialogFooter,  AlertDialogHeader,  AlertDialogPopup,  AlertDialogTitle,} from "../ui/alert-dialog";import { Popover, PopoverPopup, PopoverTrigger } from "../ui/popover";import { QRCodeSvg } from "../ui/qr-code";import { Spinner } from "../ui/spinner";import { Switch } from "../ui/switch";import { stackedThreadToast, toastManager } from "../ui/toast";import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";import { Button } from "../ui/button";import { Group, GroupSeparator } from "../ui/group";import { AnimatedHeight } from "../AnimatedHeight";import {  Menu,  MenuGroup,  MenuGroupLabel,  MenuItem,  MenuPopup,  MenuSeparator,  MenuTrigger,} from "../ui/menu";import { Textarea } from "../ui/textarea";import { getPairingTokenFromUrl, setPairingTokenOnUrl } from "../../pairingUrl";import { readHostedPairingRequest } from "../../hostedPairing";import {  createServerPairingCredential,  fetchSessionState,  revokeOtherServerClientSessions,  revokeServerClientSession,  revokeServerPairingLink,  isLoopbackHostname,  type ServerClientSessionRecord,  type ServerPairingLinkRecord,} from "~/environments/primary";import type { WsRpcClient } from "~/rpc/wsRpcClient";import {  type SavedEnvironmentRecord,  type SavedEnvironmentRuntimeState,  useSavedEnvironmentRegistryStore,  useSavedEnvironmentRuntimeStore,  addSavedEnvironment,  connectDesktopSshEnvironment,  disconnectSavedEnvironment,  getPrimaryEnvironmentConnection,  reconnectSavedEnvironment,  removeSavedEnvironment,} from "~/environments/runtime";import { useUiStateStore } from "~/uiStateStore";import { resolveServerConfigVersionMismatch } from "~/versionSkew";import { useServerConfig } from "~/rpc/serverState"; const DEFAULT_TAILSCALE_SERVE_PORT = 443; const accessTimestampFormatter = new Intl.DateTimeFormat(undefined, {  dateStyle: "medium",  timeStyle: "short",}); function formatAccessTimestamp(value: string): string {  const parsed = new Date(value);  if (Number.isNaN(parsed.getTime())) {    return value;  }  return accessTimestampFormatter.format(parsed);} type ConnectionStatusDotProps = {  tooltipText?: string | null;  dotClassName: string;  pingClassName?: string | null;}; function ConnectionStatusDot({  tooltipText,  dotClassName,  pingClassName,}: ConnectionStatusDotProps) {  const dotContent = (    <>      {pingClassName ? (        <span          className={cn(            "absolute inline-flex h-full w-full animate-ping rounded-full",            pingClassName,          )}        />      ) : null}      <span className={cn("relative inline-flex size-2 rounded-full", dotClassName)} />    </>  );   if (!tooltipText) {    return (      <span className="relative flex size-3 shrink-0 items-center justify-center">        {dotContent}      </span>    );  }   const dot = (    <button      type="button"      title={tooltipText}      aria-label={tooltipText}      className="relative flex size-3 shrink-0 cursor-help items-center justify-center rounded-full outline-hidden"    >      {dotContent}    </button>  );   return (    <Tooltip>      <TooltipTrigger render={dot} />      <TooltipPopup side="top" className="max-w-80 whitespace-pre-wrap leading-tight">        {tooltipText}      </TooltipPopup>    </Tooltip>  );} function getSavedBackendStatusTooltip(  runtime: SavedEnvironmentRuntimeState | null,  record: SavedEnvironmentRecord,  nowMs: number,) {  const connectionState = runtime?.connectionState ?? "disconnected";   if (connectionState === "connected") {    const connectedAt = runtime?.connectedAt ?? record.lastConnectedAt;    return connectedAt ? `Connected for ${formatElapsedDurationLabel(connectedAt, nowMs)}` : null;  }   if (connectionState === "connecting") {    return null;  }   if (connectionState === "error") {    return runtime?.lastError ?? "An unknown connection error occurred.";  }   return record.lastConnectedAt    ? `Last connected at ${formatAccessTimestamp(record.lastConnectedAt)}`    : "Not connected yet.";} function formatDesktopSshTarget(target: NonNullable<SavedEnvironmentRecord["desktopSsh"]>): string {  const authority = target.username ? `${target.username}@${target.hostname}` : target.hostname;  return target.port ? `${authority}:${target.port}` : authority;} function parseManualDesktopSshTarget(input: {  readonly host: string;  readonly username: string;  readonly port: string;}): DesktopSshEnvironmentTarget {  const rawHost = input.host.trim();  if (rawHost.length === 0) {    throw new Error("SSH host or alias is required.");  }   let hostname = rawHost;  let username = input.username.trim() || null;  let port: number | null = null;   const atIndex = hostname.lastIndexOf("@");  if (atIndex > 0) {    const inlineUsername = hostname.slice(0, atIndex).trim();    hostname = hostname.slice(atIndex + 1).trim();    if (!username && inlineUsername.length > 0) {      username = inlineUsername;    }  }   const bracketedHostMatch = /^\[([^\]]+)\](?::(\d+))?$/u.exec(hostname);  if (bracketedHostMatch) {    hostname = bracketedHostMatch[1]!.trim();    if (bracketedHostMatch[2]) {      port = Number.parseInt(bracketedHostMatch[2], 10);    }  } else {    const colonSegments = hostname.split(":");    if (colonSegments.length === 2 && /^\d+$/u.test(colonSegments[1] ?? "")) {      hostname = colonSegments[0]!.trim();      port = Number.parseInt(colonSegments[1]!, 10);    }  }   const rawPort = input.port.trim();  if (rawPort.length > 0) {    port = Number.parseInt(rawPort, 10);  }   if (hostname.length === 0) {    throw new Error("SSH host or alias is required.");  }   if (port !== null && (!Number.isInteger(port) || port <= 0 || port > 65_535)) {    throw new Error("SSH port must be between 1 and 65535.");  }   return {    alias: hostname,    hostname,    username,    port,  };} function parsePairingUrlFields(  input: string,): { readonly host: string; readonly pairingCode: string } | null {  const trimmed = input.trim();  if (!trimmed) return null;   try {    const urlLikeInput =      /^[a-zA-Z][a-zA-Z\d+.-]*:\/\//u.test(trimmed) || trimmed.startsWith("//")        ? trimmed        : `https://${trimmed}`;    const url = new URL(urlLikeInput, window.location.origin);    const hostedPairingRequest = readHostedPairingRequest(url);    if (hostedPairingRequest) {      return {        host: hostedPairingRequest.host,        pairingCode: hostedPairingRequest.token,      };    }     const pairingCode = getPairingTokenFromUrl(url);    if (!pairingCode) return null;    return {      host: url.origin,      pairingCode,    };  } catch {    return null;  }} function parseRemotePairingFields(input: { readonly host: string; readonly pairingCode: string }): {  readonly host: string;  readonly pairingCode: string;} {  const parsedPairingUrl = parsePairingUrlFields(input.host);  if (parsedPairingUrl) return parsedPairingUrl;   const host = input.host.trim();  const pairingCode = input.pairingCode.trim();  if (!host) {    throw new Error("Enter a backend host.");  }  if (!pairingCode) {    throw new Error("Enter a pairing code.");  }  return { host, pairingCode };} function formatDesktopSshConnectionError(error: unknown): string {  const fallback = "Failed to connect SSH host.";  const rawMessage = error instanceof Error ? error.message : fallback;  const withoutIpcPrefix = rawMessage.replace(    /^Error invoking remote method 'desktop:ensure-ssh-environment':\s*/u,    "",  );  const withoutTaggedErrorPrefix = withoutIpcPrefix.replace(/^Ssh[A-Za-z]+Error:\s*/u, "");  return withoutTaggedErrorPrefix.trim() || fallback;} /** Direct row in the card – same pattern as the Provider / ACP-agent list rows. */const ITEM_ROW_CLASSNAME = "border-t border-border/60 px-4 py-4 first:border-t-0 sm:px-5";const ENDPOINT_ROW_CLASSNAME = "border-t border-border/60 px-4 py-2.5 first:border-t-0 sm:px-5"; const ITEM_ROW_INNER_CLASSNAME =  "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between"; type AccessSectionPresentation = "current" | "endpoint-rail"; function accessRowClassName(_presentation: AccessSectionPresentation) {  return ITEM_ROW_CLASSNAME;} function endpointRowClassName(presentation: AccessSectionPresentation, isAvailable: boolean) {  if (presentation === "endpoint-rail") {    return cn(      "relative border-t border-border/60 px-4 py-3 first:border-t-0 sm:px-5",      !isAvailable && "bg-muted/20",    );  }   return cn(ENDPOINT_ROW_CLASSNAME, !isAvailable && "bg-muted/24");} function sortDesktopPairingLinks(links: ReadonlyArray<ServerPairingLinkRecord>) {  return [...links].toSorted(    (left, right) => new Date(right.createdAt).getTime() - new Date(left.createdAt).getTime(),  );} function sortDesktopClientSessions(sessions: ReadonlyArray<ServerClientSessionRecord>) {  return [...sessions].toSorted((left, right) => {    if (left.current !== right.current) {      return left.current ? -1 : 1;    }    if (left.connected !== right.connected) {      return left.connected ? -1 : 1;    }    return new Date(right.issuedAt).getTime() - new Date(left.issuedAt).getTime();  });} function toDesktopPairingLinkRecord(pairingLink: AuthPairingLink): ServerPairingLinkRecord {  return {    ...pairingLink,    createdAt: DateTime.formatIso(pairingLink.createdAt),    expiresAt: DateTime.formatIso(pairingLink.expiresAt),  };} function toDesktopClientSessionRecord(clientSession: AuthClientSession): ServerClientSessionRecord {  return {    ...clientSession,    issuedAt: DateTime.formatIso(clientSession.issuedAt),    expiresAt: DateTime.formatIso(clientSession.expiresAt),    lastConnectedAt:      clientSession.lastConnectedAt === null        ? null        : DateTime.formatIso(clientSession.lastConnectedAt),  };} function upsertDesktopPairingLink(  current: ReadonlyArray<ServerPairingLinkRecord>,  next: ServerPairingLinkRecord,) {  const existingIndex = current.findIndex((pairingLink) => pairingLink.id === next.id);  if (existingIndex === -1) {    return sortDesktopPairingLinks([...current, next]);  }  const updated = [...current];  updated[existingIndex] = next;  return sortDesktopPairingLinks(updated);} function removeDesktopPairingLink(current: ReadonlyArray<ServerPairingLinkRecord>, id: string) {  return current.filter((pairingLink) => pairingLink.id !== id);} function upsertDesktopClientSession(  current: ReadonlyArray<ServerClientSessionRecord>,  next: ServerClientSessionRecord,) {  const existingIndex = current.findIndex(    (clientSession) => clientSession.sessionId === next.sessionId,  );  if (existingIndex === -1) {    return sortDesktopClientSessions([...current, next]);  }  const updated = [...current];  updated[existingIndex] = next;  return sortDesktopClientSessions(updated);} function removeDesktopClientSession(  current: ReadonlyArray<ServerClientSessionRecord>,  sessionId: ServerClientSessionRecord["sessionId"],) {  return current.filter((clientSession) => clientSession.sessionId !== sessionId);} function selectPairingEndpoint(  endpoints: ReadonlyArray<AdvertisedEndpoint>,  defaultEndpointKey?: string | null,): AdvertisedEndpoint | null {  const availableEndpoints = endpoints.filter((endpoint) => endpoint.status !== "unavailable");  if (defaultEndpointKey) {    const selectedEndpoint = availableEndpoints.find(      (endpoint) => endpointDefaultPreferenceKey(endpoint) === defaultEndpointKey,    );    if (selectedEndpoint) {      return selectedEndpoint;    }  }  return (    availableEndpoints.find((endpoint) => endpoint.isDefault) ??    availableEndpoints.find((endpoint) => endpoint.reachability !== "loopback") ??    availableEndpoints.find((endpoint) => endpoint.compatibility.hostedHttpsApp === "compatible") ??    null  );} function isTailscaleHttpsEndpoint(endpoint: AdvertisedEndpoint): boolean {  return endpoint.id.startsWith("tailscale-magicdns:");} function endpointDefaultPreferenceKey(endpoint: AdvertisedEndpoint): string {  if (endpoint.id.startsWith("desktop-loopback:")) {    return "desktop-core:loopback:http";  }  if (endpoint.id.startsWith("desktop-lan:")) {    return "desktop-core:lan:http";  }  if (endpoint.id.startsWith("tailscale-ip:")) {    return "tailscale:ip:http";  }  if (isTailscaleHttpsEndpoint(endpoint)) {    return "tailscale:magicdns:https";  }   let scheme = "unknown";  try {    scheme = new URL(endpoint.httpBaseUrl).protocol.replace(/:$/u, "");  } catch {    // Keep the stored preference stable even if a custom endpoint is malformed.  }   return `${endpoint.provider.id}:${endpoint.reachability}:${scheme}:${endpoint.label}`;} function resolveAdvertisedEndpointPairingUrl(  endpoint: AdvertisedEndpoint,  credential: string,): string {  if (endpoint.compatibility.hostedHttpsApp === "compatible") {    return (      resolveHostedPairingUrl(endpoint.httpBaseUrl, credential) ??      resolveDesktopPairingUrl(endpoint.httpBaseUrl, credential)    );  }  return resolveDesktopPairingUrl(endpoint.httpBaseUrl, credential);} function resolveCurrentOriginPairingUrl(credential: string): string {  const url = new URL("/pair", window.location.href);  return setPairingTokenOnUrl(url, credential).toString();} function isHostedAppPairingUrl(value: string): boolean {  try {    const url = new URL(value);    return url.pathname === "/pair" && url.searchParams.has("host");  } catch {    return false;  }} type PairingLinkListRowProps = {  pairingLink: ServerPairingLinkRecord;  endpointUrl: string | null | undefined;  endpoints: ReadonlyArray<AdvertisedEndpoint>;  defaultEndpointKey: string | null;

Lines 1–500 of 2747.