Add native self-hosted instance connection to fluxer_desktop

Trimmed monorepo checkout (fluxer_desktop + packages/voice_engine_v2 +
tools/ci) with a "Connect to a Different Server" menu item and popout
that lets the desktop app switch to any self-hosted Fluxer instance,
plus fixes for well-known discovery on single-domain self-hosted
deployments and a false-positive ERR_ABORTED on same-origin client
redirects during the switch. Defaults to chat.fluxr.chat and uses an
isolated userData directory from the official build.
This commit is contained in:
2026-07-01 18:22:43 -04:00
commit 682afacd30
1763 changed files with 613720 additions and 0 deletions
@@ -0,0 +1,539 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
use napi_derive::napi;
pub const SOURCE_METAL: &str = "metal";
pub const SOURCE_DXGI: &str = "dxgi";
pub const SOURCE_LINUX_SYSFS: &str = "linux-sysfs";
#[napi(object)]
pub struct PlatformGpuDeviceInfo {
pub active: bool,
#[napi(js_name = "vendorId")]
pub vendor_id: u32,
#[napi(js_name = "deviceId")]
pub device_id: u32,
#[napi(js_name = "vendorName")]
pub vendor_name: Option<String>,
#[napi(js_name = "deviceString")]
pub device_string: Option<String>,
#[napi(js_name = "driverVendor")]
pub driver_vendor: Option<String>,
#[napi(js_name = "driverVersion")]
pub driver_version: Option<String>,
#[napi(js_name = "dedicatedVideoMemory")]
pub dedicated_video_memory: Option<f64>,
#[napi(js_name = "sharedSystemMemory")]
pub shared_system_memory: Option<f64>,
#[napi(js_name = "subsystemVendorId")]
pub subsystem_vendor_id: Option<u32>,
#[napi(js_name = "subsystemDeviceId")]
pub subsystem_device_id: Option<u32>,
#[napi(js_name = "registryId")]
pub registry_id: Option<String>,
#[napi(js_name = "adapterLuid")]
pub adapter_luid: Option<String>,
#[napi(js_name = "pciPath")]
pub pci_path: Option<String>,
pub integrated: Option<bool>,
pub removable: Option<bool>,
pub headless: Option<bool>,
pub source: String,
}
#[napi(object)]
pub struct PlatformGpuInfo {
pub devices: Vec<PlatformGpuDeviceInfo>,
pub source: String,
pub error: Option<String>,
}
#[napi(js_name = "getGpuInfo")]
pub fn get_gpu_info() -> PlatformGpuInfo {
platform::gpu_info()
}
#[allow(dead_code)]
fn base_device(
active: bool,
vendor_id: u32,
device_id: u32,
source: &str,
) -> PlatformGpuDeviceInfo {
PlatformGpuDeviceInfo {
active,
vendor_id,
device_id,
vendor_name: fluxer_desktop_native::platform_info::probe_helpers::vendor_name(vendor_id)
.map(str::to_owned),
device_string: None,
driver_vendor: None,
driver_version: None,
dedicated_video_memory: None,
shared_system_memory: None,
subsystem_vendor_id: None,
subsystem_device_id: None,
registry_id: None,
adapter_luid: None,
pci_path: None,
integrated: None,
removable: None,
headless: None,
source: source.to_owned(),
}
}
#[allow(dead_code)]
fn empty_info(source: &str) -> PlatformGpuInfo {
PlatformGpuInfo {
devices: Vec::new(),
source: source.to_owned(),
error: None,
}
}
#[cfg(target_os = "macos")]
mod platform {
use fluxer_desktop_native::platform_info::probe_helpers::{
vendor_id_from_name, vendor_name, write_hex_u64,
};
use objc2::exception::catch;
use objc2::rc::autoreleasepool;
use objc2_metal::{MTLCopyAllDevices, MTLCreateSystemDefaultDevice, MTLDevice};
use super::{PlatformGpuDeviceInfo, PlatformGpuInfo, SOURCE_METAL, empty_info};
pub(super) fn gpu_info() -> PlatformGpuInfo {
match catch(|| autoreleasepool(|_| gpu_info_inner())) {
Ok(info) => info,
Err(exception) => {
let mut info = empty_info(SOURCE_METAL);
info.error = Some(exception.map_or_else(
|| "macOS GPU probe failed".to_owned(),
|exception| exception.to_string(),
));
info
}
}
}
fn gpu_info_inner() -> PlatformGpuInfo {
let default_device = MTLCreateSystemDefaultDevice();
let default_registry_id = default_device.as_deref().map(MTLDevice::registryID);
let all_devices = MTLCopyAllDevices();
let mut devices = Vec::new();
for index in 0..all_devices.count() {
let device = all_devices.objectAtIndex(index);
let active =
default_registry_id.is_some_and(|registry_id| registry_id == device.registryID());
devices.push(mac_device(&device, active));
}
if devices.is_empty() {
if let Some(device) = default_device {
devices.push(mac_device(&device, true));
}
} else if !devices.iter().any(|device| device.active) {
devices[0].active = true;
}
PlatformGpuInfo {
devices,
source: SOURCE_METAL.to_owned(),
error: None,
}
}
fn mac_device(
device: &objc2::runtime::ProtocolObject<dyn MTLDevice>,
active: bool,
) -> PlatformGpuDeviceInfo {
let name = device.name().to_string();
let vendor_id = vendor_id_from_name(&name);
PlatformGpuDeviceInfo {
active,
vendor_id,
device_id: 0,
vendor_name: vendor_name(vendor_id).map(str::to_owned),
device_string: Some(if name.is_empty() {
"Metal GPU".to_owned()
} else {
name
}),
driver_vendor: None,
driver_version: None,
dedicated_video_memory: None,
shared_system_memory: None,
subsystem_vendor_id: None,
subsystem_device_id: None,
registry_id: Some(write_hex_u64(device.registryID())),
adapter_luid: None,
pci_path: None,
integrated: Some(device.isLowPower() || vendor_id == 0x106b),
removable: Some(device.isRemovable()),
headless: Some(device.isHeadless()),
source: SOURCE_METAL.to_owned(),
}
}
}
#[allow(dead_code)]
mod dxgi_helpers {
pub fn utf16_description(raw: &[u16; 128]) -> String {
let end = raw.iter().position(|ch| *ch == 0).unwrap_or(raw.len());
let text = String::from_utf16_lossy(&raw[..end]);
if text.is_empty() {
"DXGI adapter".to_owned()
} else {
text
}
}
pub fn luid_string(high_part: i32, low_part: u32) -> String {
format!("{:08x}:{low_part:08x}", high_part as u32)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn luid_format_matches_legacy_contract() {
assert_eq!("ffffffff:1234abcd", luid_string(-1, 0x1234_abcd));
assert_eq!("00000002:00000001", luid_string(2, 1));
}
#[test]
fn utf16_description_trims_at_first_nul() {
let mut raw = [0u16; 128];
raw[0] = 'G' as u16;
raw[1] = 'P' as u16;
raw[2] = 'U' as u16;
raw[3] = 0;
raw[4] = 'X' as u16;
assert_eq!("GPU", utf16_description(&raw));
}
}
}
#[cfg(target_os = "windows")]
mod platform {
use super::dxgi_helpers::{luid_string, utf16_description};
use fluxer_desktop_native::platform_info::probe_helpers::vendor_name;
use windows::Win32::Graphics::Dxgi::{
CreateDXGIFactory1, DXGI_ADAPTER_DESC1, DXGI_ADAPTER_FLAG_SOFTWARE,
DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IDXGIAdapter1, IDXGIFactory1, IDXGIFactory6,
};
use super::{PlatformGpuDeviceInfo, PlatformGpuInfo, SOURCE_DXGI, empty_info};
pub(super) fn gpu_info() -> PlatformGpuInfo {
let mut info = empty_info(SOURCE_DXGI);
info.devices = enumerate_dxgi_adapters();
info
}
fn enumerate_dxgi_adapters() -> Vec<PlatformGpuDeviceInfo> {
unsafe {
if let Ok(factory) = CreateDXGIFactory1::<IDXGIFactory6>() {
return enumerate_factory6(&factory);
}
if let Ok(factory) = CreateDXGIFactory1::<IDXGIFactory1>() {
return enumerate_factory1(&factory);
}
}
Vec::new()
}
unsafe fn enumerate_factory6(factory: &IDXGIFactory6) -> Vec<PlatformGpuDeviceInfo> {
let mut devices = Vec::new();
let mut ordered_index = 0;
loop {
let Ok(adapter) = (unsafe {
factory.EnumAdapterByGpuPreference::<IDXGIAdapter1>(
ordered_index,
DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
)
}) else {
break;
};
if let Ok(desc) = unsafe { adapter.GetDesc1() } {
push_dxgi_desc(&mut devices, &desc, ordered_index);
}
ordered_index += 1;
}
devices
}
unsafe fn enumerate_factory1(factory: &IDXGIFactory1) -> Vec<PlatformGpuDeviceInfo> {
let mut devices = Vec::new();
let mut ordered_index = 0;
loop {
let Ok(adapter) = (unsafe { factory.EnumAdapters1(ordered_index) }) else {
break;
};
if let Ok(desc) = unsafe { adapter.GetDesc1() } {
push_dxgi_desc(&mut devices, &desc, ordered_index);
}
ordered_index += 1;
}
devices
}
fn push_dxgi_desc(
devices: &mut Vec<PlatformGpuDeviceInfo>,
desc: &DXGI_ADAPTER_DESC1,
ordered_index: u32,
) {
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE.0 as u32) != 0 {
return;
}
let mut device = PlatformGpuDeviceInfo {
active: ordered_index == 0,
vendor_id: desc.VendorId,
device_id: desc.DeviceId,
vendor_name: vendor_name(desc.VendorId).map(str::to_owned),
device_string: Some(utf16_description(&desc.Description)),
driver_vendor: None,
driver_version: None,
dedicated_video_memory: Some(desc.DedicatedVideoMemory as f64),
shared_system_memory: Some(desc.SharedSystemMemory as f64),
subsystem_vendor_id: Some(desc.SubSysId >> 16),
subsystem_device_id: Some(desc.SubSysId & 0xffff),
registry_id: None,
adapter_luid: None,
pci_path: None,
integrated: None,
removable: None,
headless: None,
source: SOURCE_DXGI.to_owned(),
};
device.adapter_luid = Some(luid_string(
desc.AdapterLuid.HighPart,
desc.AdapterLuid.LowPart,
));
devices.push(device);
}
}
#[cfg(target_os = "linux")]
mod platform {
use std::fs;
use std::path::Path;
use fluxer_desktop_native::platform_info::probe_helpers::{
basename, is_drm_card_name, parse_hex_id, vendor_name,
};
use super::{PlatformGpuDeviceInfo, PlatformGpuInfo, SOURCE_LINUX_SYSFS, base_device};
pub(super) fn gpu_info() -> PlatformGpuInfo {
linux_gpu_info_from_drm_root(Path::new("/sys/class/drm"))
}
fn linux_gpu_info_from_drm_root(root: &Path) -> PlatformGpuInfo {
let mut info = PlatformGpuInfo {
devices: Vec::new(),
source: SOURCE_LINUX_SYSFS.to_owned(),
error: None,
};
let Ok(entries) = fs::read_dir(root) else {
return info;
};
let mut card_names = entries
.filter_map(Result::ok)
.filter_map(|entry| entry.file_name().into_string().ok())
.filter(|name| is_drm_card_name(name))
.collect::<Vec<_>>();
card_names.sort_unstable_by_key(|name| card_sort_key(name));
for card_name in card_names {
if let Some(device) = linux_card(root, &card_name, info.devices.is_empty()) {
info.devices.push(device);
}
}
info
}
fn linux_card(root: &Path, card_name: &str, active: bool) -> Option<PlatformGpuDeviceInfo> {
let base = root.join(card_name).join("device");
let vendor_id = read_hex_file(base.join("vendor"))?;
let device_id = read_hex_file(base.join("device")).unwrap_or(0);
let mut device = base_device(active, vendor_id, device_id, SOURCE_LINUX_SYSFS);
device.subsystem_vendor_id =
Some(read_hex_file(base.join("subsystem_vendor")).unwrap_or(0));
device.subsystem_device_id =
Some(read_hex_file(base.join("subsystem_device")).unwrap_or(0));
device.pci_path = read_link_basename(&base);
device.driver_vendor = read_link_basename(base.join("driver"));
if let Some(uevent) = read_trimmed_file(base.join("uevent")) {
if let Some(driver) = uevent_value(&uevent, "DRIVER") {
device.driver_vendor = Some(driver.to_owned());
}
if let Some(pci_id) = uevent_value(&uevent, "PCI_ID") {
device.device_string = Some(match vendor_name(vendor_id) {
Some(vendor) => format!("{vendor} GPU ({pci_id})"),
None => format!("GPU ({pci_id})"),
});
}
}
if let Some(vram) = read_trimmed_file(base.join("mem_info_vram_total"))
&& let Ok(bytes) = vram.parse::<u64>()
{
device.dedicated_video_memory = Some(bytes as f64);
}
Some(device)
}
fn card_sort_key(name: &str) -> u32 {
name.strip_prefix("card")
.and_then(|rest| rest.parse::<u32>().ok())
.unwrap_or(u32::MAX)
}
fn read_hex_file(path: impl AsRef<Path>) -> Option<u32> {
let raw = fs::read_to_string(path).ok()?;
parse_hex_id(&raw).ok()
}
fn read_trimmed_file(path: impl AsRef<Path>) -> Option<String> {
let raw = fs::read_to_string(path).ok()?;
Some(raw.trim_matches([' ', '\t', '\r', '\n']).to_owned())
}
fn read_link_basename(path: impl AsRef<Path>) -> Option<String> {
let target = fs::read_link(path).ok()?;
Some(path_basename(&target))
}
fn path_basename(path: &Path) -> String {
path.file_name()
.and_then(|name| name.to_str())
.map(str::to_owned)
.unwrap_or_else(|| basename(&path.to_string_lossy()).to_owned())
}
fn uevent_value<'a>(blob: &'a str, key: &str) -> Option<&'a str> {
blob.lines().find_map(|line| {
let (line_key, value) = line.split_once('=')?;
if line_key == key {
Some(value.trim_matches([' ', '\t', '\r', '\n']))
} else {
None
}
})
}
#[cfg(test)]
mod tests {
use std::fs::{create_dir_all, write};
use std::os::unix::fs::symlink;
use super::*;
#[test]
fn uevent_value_matches_exact_keys() {
let blob = "PCI_ID=8086:46A6\nDRIVER=i915\nNOT_DRIVER=bad\n";
assert_eq!(Some("i915"), uevent_value(blob, "DRIVER"));
assert_eq!(Some("8086:46A6"), uevent_value(blob, "PCI_ID"));
assert_eq!(None, uevent_value(blob, "MISSING"));
}
#[test]
fn card_sort_key_keeps_card_order_numeric() {
let mut names = ["card10".to_owned(), "card2".to_owned(), "card0".to_owned()];
names.sort_unstable_by_key(|name| card_sort_key(name));
assert_eq!(["card0", "card2", "card10"], names);
}
#[test]
fn linux_sysfs_fixture_ports_legacy_gpu_contract() {
let tmp = tempfile::tempdir().unwrap();
let root = tmp.path();
let pci0 = root.join("devices/pci0000:00/0000:00:02.0");
let pci1 = root.join("devices/pci0000:01/0000:01:00.0");
create_dir_all(root.join("card0")).unwrap();
create_dir_all(root.join("card1")).unwrap();
create_dir_all(&pci0).unwrap();
create_dir_all(&pci1).unwrap();
symlink(
"../devices/pci0000:00/0000:00:02.0",
root.join("card0/device"),
)
.unwrap();
symlink(
"../devices/pci0000:01/0000:01:00.0",
root.join("card1/device"),
)
.unwrap();
let card0 = root.join("card0/device");
let card1 = root.join("card1/device");
write(card0.join("vendor"), "0x8086\n").unwrap();
write(card0.join("device"), "0x46a6\n").unwrap();
write(card0.join("subsystem_vendor"), "0x1028\n").unwrap();
write(card0.join("subsystem_device"), "0x0b19\n").unwrap();
write(card0.join("uevent"), "DRIVER=i915\nPCI_ID=8086:46A6\n").unwrap();
write(card0.join("mem_info_vram_total"), "268435456\n").unwrap();
write(card1.join("vendor"), "0x10de\n").unwrap();
write(card1.join("device"), "0x1f99\n").unwrap();
write(card1.join("uevent"), "PCI_ID=10DE:1F99\n").unwrap();
symlink("/sys/bus/pci/drivers/nvidia", card1.join("driver")).unwrap();
let info = linux_gpu_info_from_drm_root(root);
assert_eq!(SOURCE_LINUX_SYSFS, info.source);
assert_eq!(2, info.devices.len());
assert!(info.devices[0].active);
assert_eq!(0x8086, info.devices[0].vendor_id);
assert_eq!(Some("Intel".to_owned()), info.devices[0].vendor_name);
assert_eq!(
Some("Intel GPU (8086:46A6)".to_owned()),
info.devices[0].device_string
);
assert_eq!(Some("i915".to_owned()), info.devices[0].driver_vendor);
assert_eq!(Some("0000:00:02.0".to_owned()), info.devices[0].pci_path);
assert_eq!(Some(268_435_456.0), info.devices[0].dedicated_video_memory);
assert!(!info.devices[1].active);
assert_eq!(Some("nvidia".to_owned()), info.devices[1].driver_vendor);
}
}
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
mod platform {
use super::{PlatformGpuInfo, SOURCE_LINUX_SYSFS, empty_info};
pub(super) fn gpu_info() -> PlatformGpuInfo {
empty_info(SOURCE_LINUX_SYSFS)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn base_device_sets_required_contract_fields() {
let device = base_device(true, 0x10de, 0x2684, SOURCE_DXGI);
assert!(device.active);
assert_eq!(0x10de, device.vendor_id);
assert_eq!(0x2684, device.device_id);
assert_eq!(Some("NVIDIA".to_owned()), device.vendor_name);
assert_eq!(SOURCE_DXGI, device.source);
}
#[test]
fn empty_info_preserves_source_and_empty_devices() {
let info = empty_info(SOURCE_LINUX_SYSFS);
assert_eq!(SOURCE_LINUX_SYSFS, info.source);
assert!(info.devices.is_empty());
assert!(info.error.is_none());
}
}