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,132 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {createRequire} from 'node:module';
import {afterEach, describe, expect, test} from 'vitest';
const require = createRequire(import.meta.url);
const macAppAudio = require('./index.js');
function makeFakeBinding() {
const calls = [];
const natives = [];
class FakeNative {
constructor() {
this.frameCallback = undefined;
this.lifecycleCallback = undefined;
this.stopCount = 0;
natives.push(this);
}
setFrameCallback(callback) {
this.frameCallback = callback;
}
setLifecycleCallback(callback) {
this.lifecycleCallback = callback;
}
async start(pid, excludeSelf, includeProcessTree, backend, captureScope) {
calls.push({pid, excludeSelf, includeProcessTree, backend, captureScope});
}
async stop() {
this.stopCount += 1;
}
}
return {
binding: {
ProcessLoopback: FakeNative,
listAudibleApplications: async () => [],
getBackendAvailability: async () => ({}),
pidFromWindowId: () => 0,
},
calls,
natives,
};
}
afterEach(() => {
macAppAudio.__setBindingForTests(null);
});
describe('mac-app-audio loader wrapper', () => {
test('forces excludeSelf=true and preserves includeProcessTree=false', async () => {
const {binding, calls} = makeFakeBinding();
macAppAudio.__setBindingForTests(binding);
const loopback = new macAppAudio.ProcessLoopback(1234, {
excludeSelf: false,
includeProcessTree: false,
});
loopback.on('error', () => {});
await loopback.start();
expect(calls).toEqual([
{pid: 1234, excludeSelf: true, includeProcessTree: false, backend: 'auto', captureScope: 'process'},
]);
});
test('forwards explicit backend preference to native binding', async () => {
const {binding, calls} = makeFakeBinding();
macAppAudio.__setBindingForTests(binding);
const loopback = new macAppAudio.ProcessLoopback(1234, {
backend: 'coreaudio',
});
loopback.on('error', () => {});
await loopback.start();
expect(calls).toEqual([
{pid: 1234, excludeSelf: true, includeProcessTree: true, backend: 'coreaudio', captureScope: 'process'},
]);
});
test('forwards explicit capture scope to native binding', async () => {
const {binding, calls} = makeFakeBinding();
macAppAudio.__setBindingForTests(binding);
const loopback = new macAppAudio.ProcessLoopback(1234, {
captureScope: 'system',
backend: 'coreaudio',
});
loopback.on('error', () => {});
await loopback.start();
expect(calls).toEqual([
{pid: 1234, excludeSelf: true, includeProcessTree: true, backend: 'coreaudio', captureScope: 'system'},
]);
});
test('forwards ScreenCaptureKit system capture requests to native binding', async () => {
const {binding, calls} = makeFakeBinding();
macAppAudio.__setBindingForTests(binding);
const loopback = new macAppAudio.ProcessLoopback(1234, {
captureScope: 'system',
backend: 'sck',
});
loopback.on('error', () => {});
await loopback.start();
expect(calls).toEqual([
{pid: 1234, excludeSelf: true, includeProcessTree: true, backend: 'sck', captureScope: 'system'},
]);
});
test('copies native frame samples before emitting', () => {
const {binding, natives} = makeFakeBinding();
macAppAudio.__setBindingForTests(binding);
const loopback = new macAppAudio.ProcessLoopback(1234);
const frames = [];
loopback.on('frame', (frame) => frames.push(frame));
const nativeSamples = new Float32Array([0.1, 0.2, 0.3, 0.4]);
natives[0].frameCallback(nativeSamples);
nativeSamples.fill(9);
expect(frames).toHaveLength(1);
expect(Array.from(frames[0].samples)).toEqual(Array.from(new Float32Array([0.1, 0.2, 0.3, 0.4])));
expect(frames[0].channels).toBe(2);
expect(frames[0].sampleRate).toBe(48000);
});
test('emits closed once when native lifecycle closes and stop is called later', async () => {
const {binding, natives} = makeFakeBinding();
macAppAudio.__setBindingForTests(binding);
const loopback = new macAppAudio.ProcessLoopback(1234);
let closed = 0;
loopback.on('closed', () => {
closed += 1;
});
natives[0].lifecycleCallback('closed', '');
await Promise.resolve();
await loopback.stop();
expect(closed).toBe(1);
expect(natives[0].stopCount).toBe(1);
});
});