Ctrl K
ComunidadGuías…

electron/capabilities.cjs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
const { PLUGIN_REQUIRED_MESSAGE, isHyprlandSession } = require("./cua-hyprland.cjs");

const DESKTOP_PLATFORMS = new Set(["darwin", "linux", "win32"]);
const UNAVAILABLE_LOCAL_STATUSES = new Set(["disabled", "checking", "starting", "error", "stopped", "unavailable"]);

function normalizedPlatform(platform) {
  return DESKTOP_PLATFORMS.has(platform) ? platform : "other";
}

function nativeDesktopActions(platform) {
  const appleNative = normalizedPlatform(platform) === "darwin";
  return Object.freeze({
    appleMediaPermissions: appleNative,
    applePrivacySettings: appleNative,
    appleSpeech: appleNative,
  });
}

function linuxSession(platform, env) {
  if (platform !== "linux") return "unknown";
  const declared = String(env.XDG_SESSION_TYPE ?? "").toLowerCase();
  // A Wayland session may also expose DISPLAY for XWayland: prefer Wayland so the UI never bypasses portals.
  if (declared === "wayland" || env.WAYLAND_DISPLAY) return "wayland";
  if (declared === "x11" || declared === "xorg") return "x11";
  if (env.DISPLAY) return "x11";
  return "headless";
}

/** `hyprlandPlugin` is what `probeCuaHyprlandPlugin` found: "active" or anything else. */
function linuxLocalControlSupport(platform, env, { hyprlandPlugin } = {}) {
  if (platform !== "linux") {
    return Object.freeze({
      available: false,
      session: "unknown",
      reasonCode: "unsupported-platform",
      message: "Local control is not available on this platform.",
    });
  }
  const session = linuxSession(platform, env);
  if (session === "x11") return Object.freeze({ available: true, session });
  // Hyprland with Cua's plugin is the one Wayland desktop allowed: the plugin gives the bot seats of its own inside the
  // compositor. Every other Wayland desktop keeps the seat-safety block.
  if (session === "wayland" && isHyprlandSession(env)) {
    if (hyprlandPlugin === "active") return Object.freeze({ available: true, session, compositor: "hyprland" });
    return Object.freeze({
      available: false,
      session,
      compositor: "hyprland",
      reasonCode: "linux-hyprland-plugin-required",
      message: PLUGIN_REQUIRED_MESSAGE,
    });
  }
  if (session === "wayland") {
    return Object.freeze({
      available: false,
      session,
      reasonCode: "linux-wayland-seat-safety-blocked",
      message:
        "Local control is not available on Wayland yet. Sign out and choose Ubuntu on Xorg to use This computer.",
    });
  }
  return Object.freeze({
    available: false,
    session,
    reasonCode: "headless-session",
    message: "Local control needs an active Ubuntu Xorg desktop session.",
  });
}

/** Computer control's helper is gone, or the system refused to run it: access denied (os error 5), or Windows Security
 * found it unsafe (os error 225, ERROR_VIRUS_INFECTED). */
function driverBlocked(reason) {
  return /binary not found|is missing|ENOENT|EPERM|EACCES|os error (?:2|5|225)\b|access is denied|virus/i.test(String(reason ?? ""));
}

function localComputerReady(platform, connection) {
  const validLegacyConnection = connection &&
    (!Object.hasOwn(connection, "status") || connection.status === "ready") &&
    typeof connection.socketPath === "string" && connection.socketPath.length > 0 &&
    typeof connection.mcpCommand === "string" && connection.mcpCommand.trim().length > 0 &&
    Array.isArray(connection.mcpArgs) && connection.mcpArgs[0] === "mcp" &&
    connection.mcpArgs.every((arg) => typeof arg === "string") &&
    connection.mcpEnv && typeof connection.mcpEnv === "object" && !Array.isArray(connection.mcpEnv) &&
    Object.values(connection.mcpEnv).every((value) => typeof value === "string");
  if (platform === "darwin") {
    return Boolean(validLegacyConnection && (connection.mode === "embedded" || connection.mode === "standalone"));
  }
  if (platform === "win32") {
    return Boolean(validLegacyConnection && connection.mode === "embedded");
  }
  if (
    platform !== "linux" ||
    connection?.schemaVersion !== 1 ||
    connection?.platform !== "linux" ||
    connection?.enabled !== true ||
    connection?.status !== "ready"
  ) {
    return false;
  }
  if (connection.mode === "linux-x11-supervised") {
    return connection.session === "x11";
  }
  if (connection.mode === "linux-wayland-hyprland-supervised") {
    return connection.session === "wayland" && connection.compositor === "hyprland";
  }
  return false;
}

function desktopCapabilities({
  platform = process.platform,
  env = process.env,
  packaged = false,
  localConnection = null,
  homeDir = require("node:os").homedir(),
  // Whether the page draws the window's frame now.
  frame = true,
  // A remote server's page: this computer's screen, voice and local control are never on offer.
  remote = false,
} = {}) {
  const hostPlatform = normalizedPlatform(platform);
  const isMac = hostPlatform === "darwin";
  const hostSession = linuxSession(hostPlatform, env);
  const linuxPreview = hostPlatform === "linux" && hostSession !== "headless";
  const localAvailable = localComputerReady(hostPlatform, localConnection);
  const localStatus = localAvailable ? "ready" :
    UNAVAILABLE_LOCAL_STATUSES.has(localConnection?.status) ? localConnection.status : "unavailable";
  const screenPreview = {
    available: isMac || linuxPreview,
    interaction:
      isMac || hostSession === "x11"
        ? "direct"
        : hostSession === "wayland"
          ? "portal-picker"
          : "none",
  };
  if (!(isMac || linuxPreview)) {
    screenPreview.reasonCode =
      hostPlatform === "linux" ? "headless-session" : "unsupported-platform";
  }
  // Off the Mac the page listens itself and Fish Audio turns each clip into text (src/lib/fish-speech.ts).
  const fishListening = hostPlatform === "win32" || hostPlatform === "linux";
  const dictation = {
    available: isMac || fishListening,
    engine: isMac ? "apple-speech" : fishListening ? "fish-audio" : "none",
    onDevice: isMac,
  };
  if (!dictation.available) dictation.reasonCode = "unsupported-platform";
  const localComputer = {
    available: localAvailable,
    support:
      localAvailable && hostPlatform === "linux"
        ? "limited"
        : localAvailable
          ? "supported"
          : "unsupported",
    enabled: connectionEnabled(hostPlatform, localConnection),
    status: localStatus,
  };
  // Local-machine detail (driver, seat, diagnostics): a remote page must never receive these.
  if (!remote) {
    if (localConnection?.mode === "unavailable" && typeof localConnection.reason === "string" &&
        localConnection.reason.trim() && localConnection.reason.length <= 2_000) {
      localComputer.message = localConnection.reason.trim();
    }
    if (typeof localConnection?.message === "string") {
      localComputer.message = localConnection.message;
    }
    if (typeof localConnection?.driver?.path === "string") {
      localComputer.driverPath = localConnection.driver.path;
    }
    if (typeof localConnection?.driver?.version === "string") {
      localComputer.driverVersion = localConnection.driver.version;
    }
    if (typeof localConnection?.driver?.source === "string") {
      localComputer.driverSource = localConnection.driver.source;
    }
    if (typeof localConnection?.session === "string") {
      localComputer.session = localConnection.session;
    }
    if (typeof localConnection?.compositor === "string") {
      localComputer.compositor = localConnection.compositor;
    }
  }
  if (!localAvailable) {
    localComputer.reasonCode =
      localConnection?.reasonCode ??
      (hostPlatform === "darwin" || hostPlatform === "win32"
        ? driverBlocked(localConnection?.reason) ? "cua-driver-blocked" : "cua-driver-unavailable"
        : "unsupported-platform");
  }

  if (remote) {
    const unavailable = { reasonCode: "remote-server" };
    Object.assign(screenPreview, { available: false, interaction: "none" }, unavailable);
    Object.assign(dictation, { available: false, engine: "none", onDevice: false }, unavailable);
    Object.assign(localComputer, {
      available: false,
      support: "unsupported",
      enabled: false,
      status: "unavailable",
      driverPath: "",
      driverVersion: "",
      driverSource: "",
      session: "",
      compositor: "",
      message: "",
    }, unavailable);
  }

  return {
    remote: Boolean(remote),
    host: {
      platform: hostPlatform,
      label:
        hostPlatform === "darwin"
          ? "macOS"
          : hostPlatform === "linux"
            ? "Linux"
            : hostPlatform === "win32"
              ? "Windows"
              : "Desktop",
      session: hostSession,
      packaged: Boolean(packaged),
      // The sandboxed preload has no Node builtins; a remote page learns nothing about this computer's users.
      homeDir: remote ? "" : homeDir,
    },
    windowChrome:
      isMac ? "mac-inset" : hostPlatform === "win32" && frame ? "win-caption" : "native",
    windowFrame: frame !== false,
    screenPreview,
    dictation,
    localComputer,
  };
}

function connectionEnabled(platform, connection) {
  if (platform === "darwin" || platform === "win32") {
    return localComputerReady(platform, connection);
  }
  return platform === "linux" && connection?.enabled === true;
}

module.exports = {
  connectionEnabled,
  desktopCapabilities,
  driverBlocked,
  linuxLocalControlSupport,
  linuxSession,
  localComputerReady,
  nativeDesktopActions,
};