mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-09 08:21:50 +00:00
fix(desktop): don't treat WSLg as a remote display
WSLg renders Linux GUIs locally through a vGPU surface rather than shipping frames over the wire, so it doesn't show the remote-compositor flicker — confirmed by a WSL user seeing zero flickering. Drop the WSL branch from detectRemoteDisplay so WSLg keeps hardware acceleration; detection now covers only genuinely-remote displays (SSH X11 forwarding, VNC, RDP). The HERMES_DESKTOP_DISABLE_GPU override still works for anyone who does hit it.
This commit is contained in:
parent
6a2909fe5a
commit
d0ea4caf7f
3 changed files with 25 additions and 28 deletions
|
|
@ -51,7 +51,6 @@ const GPU_OVERRIDE_OFF = new Set(['0', 'false', 'no', 'off'])
|
|||
function detectRemoteDisplay(options = {}) {
|
||||
const env = options.env ?? process.env
|
||||
const platform = options.platform ?? process.platform
|
||||
const isWsl = options.isWsl ?? isWslEnvironment(env, platform)
|
||||
|
||||
const override = String(env.HERMES_DESKTOP_DISABLE_GPU || '').trim().toLowerCase()
|
||||
if (GPU_OVERRIDE_ON.has(override)) return 'override (HERMES_DESKTOP_DISABLE_GPU)'
|
||||
|
|
@ -64,12 +63,12 @@ function detectRemoteDisplay(options = {}) {
|
|||
if (platform === 'linux') {
|
||||
// X11 forwarding sets DISPLAY to "<host>:N" (e.g. "localhost:10.0"); a
|
||||
// local X server is ":0"/":1" with no host part before the colon.
|
||||
// NB: WSLg deliberately isn't treated as remote — it reports
|
||||
// GPU-accelerated vGPU surfaces locally and doesn't show the flicker.
|
||||
const display = String(env.DISPLAY || '')
|
||||
if (display.includes(':') && display.split(':')[0]) {
|
||||
return `x11-forwarding (DISPLAY=${display})`
|
||||
}
|
||||
// WSLg pipes the GUI through an RDP/Wayland bridge — same flicker profile.
|
||||
if (isWsl) return 'wslg'
|
||||
}
|
||||
|
||||
if (platform === 'win32') {
|
||||
|
|
|
|||
|
|
@ -35,12 +35,19 @@ test('bundledRuntimeImportCheck selects platform-specific import checks', () =>
|
|||
|
||||
test('detectRemoteDisplay keeps GPU on for local sessions', () => {
|
||||
// Plain local X11, Wayland, native Windows, native macOS — no remote signal.
|
||||
assert.equal(detectRemoteDisplay({ env: { DISPLAY: ':0' }, platform: 'linux', isWsl: false }), null)
|
||||
assert.equal(detectRemoteDisplay({ env: { WAYLAND_DISPLAY: 'wayland-0' }, platform: 'linux', isWsl: false }), null)
|
||||
assert.equal(detectRemoteDisplay({ env: { DISPLAY: ':0' }, platform: 'linux' }), null)
|
||||
assert.equal(detectRemoteDisplay({ env: { WAYLAND_DISPLAY: 'wayland-0' }, platform: 'linux' }), null)
|
||||
assert.equal(detectRemoteDisplay({ env: { SESSIONNAME: 'Console' }, platform: 'win32' }), null)
|
||||
assert.equal(detectRemoteDisplay({ env: {}, platform: 'darwin' }), null)
|
||||
})
|
||||
|
||||
test('detectRemoteDisplay does not treat WSLg as remote', () => {
|
||||
// WSLg renders locally via vGPU and doesn't show the flicker, so a WSL
|
||||
// session with a local DISPLAY keeps hardware acceleration on.
|
||||
assert.equal(detectRemoteDisplay({ env: { WSL_DISTRO_NAME: 'Ubuntu', DISPLAY: ':0' }, platform: 'linux' }), null)
|
||||
assert.equal(detectRemoteDisplay({ env: { WSL_INTEROP: '/run/WSL/1_interop', DISPLAY: ':0' }, platform: 'linux' }), null)
|
||||
})
|
||||
|
||||
test('detectRemoteDisplay flags SSH sessions on any platform', () => {
|
||||
assert.equal(detectRemoteDisplay({ env: { SSH_CONNECTION: '1.2.3.4 5 6.7.8.9 22' }, platform: 'linux' }), 'ssh-session')
|
||||
assert.equal(detectRemoteDisplay({ env: { SSH_CLIENT: '1.2.3.4 5 22' }, platform: 'darwin' }), 'ssh-session')
|
||||
|
|
@ -48,29 +55,19 @@ test('detectRemoteDisplay flags SSH sessions on any platform', () => {
|
|||
})
|
||||
|
||||
test('detectRemoteDisplay flags forwarded X11 displays but not local ones', () => {
|
||||
assert.match(
|
||||
String(detectRemoteDisplay({ env: { DISPLAY: 'localhost:10.0' }, platform: 'linux', isWsl: false })),
|
||||
/x11-forwarding/
|
||||
)
|
||||
assert.match(
|
||||
String(detectRemoteDisplay({ env: { DISPLAY: '192.168.1.5:0' }, platform: 'linux', isWsl: false })),
|
||||
/x11-forwarding/
|
||||
)
|
||||
assert.equal(detectRemoteDisplay({ env: { DISPLAY: ':1' }, platform: 'linux', isWsl: false }), null)
|
||||
assert.match(String(detectRemoteDisplay({ env: { DISPLAY: 'localhost:10.0' }, platform: 'linux' })), /x11-forwarding/)
|
||||
assert.match(String(detectRemoteDisplay({ env: { DISPLAY: '192.168.1.5:0' }, platform: 'linux' })), /x11-forwarding/)
|
||||
assert.equal(detectRemoteDisplay({ env: { DISPLAY: ':1' }, platform: 'linux' }), null)
|
||||
})
|
||||
|
||||
test('detectRemoteDisplay flags WSLg and RDP', () => {
|
||||
assert.equal(detectRemoteDisplay({ env: { DISPLAY: ':0' }, platform: 'linux', isWsl: true }), 'wslg')
|
||||
assert.match(
|
||||
String(detectRemoteDisplay({ env: { SESSIONNAME: 'RDP-Tcp#7' }, platform: 'win32' })),
|
||||
/^rdp/
|
||||
)
|
||||
test('detectRemoteDisplay flags RDP sessions', () => {
|
||||
assert.match(String(detectRemoteDisplay({ env: { SESSIONNAME: 'RDP-Tcp#7' }, platform: 'win32' })), /^rdp/)
|
||||
})
|
||||
|
||||
test('detectRemoteDisplay honors the HERMES_DESKTOP_DISABLE_GPU override both ways', () => {
|
||||
// Force-on even on a local display.
|
||||
assert.match(
|
||||
String(detectRemoteDisplay({ env: { HERMES_DESKTOP_DISABLE_GPU: '1', DISPLAY: ':0' }, platform: 'linux', isWsl: false })),
|
||||
String(detectRemoteDisplay({ env: { HERMES_DESKTOP_DISABLE_GPU: '1', DISPLAY: ':0' }, platform: 'linux' })),
|
||||
/override/
|
||||
)
|
||||
// Force-off even over SSH (escape hatch when a remote display has working accel).
|
||||
|
|
|
|||
|
|
@ -74,15 +74,16 @@ const IS_WINDOWS = process.platform === 'win32'
|
|||
const IS_WSL = isWslEnvironment()
|
||||
const APP_ROOT = app.getAppPath()
|
||||
|
||||
// Remote displays (SSH X11 forwarding, VNC, RDP, WSLg) make Chromium's GPU
|
||||
// Remote displays (SSH X11 forwarding, VNC, RDP) make Chromium's GPU
|
||||
// compositor flicker — accelerated layers can't be presented cleanly over the
|
||||
// wire, so the window flashes during scroll/streaming/animation. Local
|
||||
// Windows/macOS composite on the GPU and never see it. Fall back to software
|
||||
// rendering when a remote display is detected; it's rock-steady over the wire
|
||||
// and the CPU cost is negligible next to the connection's latency. Must run
|
||||
// before app `ready` — these switches only apply pre-launch. Override with
|
||||
// HERMES_DESKTOP_DISABLE_GPU (1/true → always disable, 0/false → keep GPU on).
|
||||
const REMOTE_DISPLAY_REASON = detectRemoteDisplay({ isWsl: IS_WSL })
|
||||
// Windows/macOS (and WSLg, which renders locally via vGPU) composite on the
|
||||
// GPU and never see it. Fall back to software rendering when a remote display
|
||||
// is detected; it's rock-steady over the wire and the CPU cost is negligible
|
||||
// next to the connection's latency. Must run before app `ready` — these
|
||||
// switches only apply pre-launch. Override with HERMES_DESKTOP_DISABLE_GPU
|
||||
// (1/true → always disable, 0/false → keep GPU on).
|
||||
const REMOTE_DISPLAY_REASON = detectRemoteDisplay()
|
||||
if (REMOTE_DISPLAY_REASON) {
|
||||
app.disableHardwareAcceleration()
|
||||
// Belt-and-suspenders for X11/VNC, where the Viz compositor can still glitch
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue