feat(desktop): lead onboarding with Nous Portal + fix fresh-install detection (#34970)

- Feature Nous Portal as the primary onboarding card (Recommended tag,
  app logo, single pitch line); collapse other OAuth providers behind an
  "Other providers" disclosure whose open/closed state persists.
- Surface OpenRouter as a one-click API-key option inside the disclosure;
  move "I have an API key" to a quiet bottom-right link.
- Treat "no provider configured" as a normal onboarding state, not a red
  error banner (provider-setup-errors copy match).
- Fix setup.runtime_check: it reported ready when the resolved runtime had
  an empty credential or only implicit Bedrock/IAM, so fresh installs never
  saw onboarding. Now requires a usable credential.
- Auto-wire Windows fonts for WSL2 users so the renderer renders real
  Segoe UI instead of the DejaVu fallback; make WSL detection env-independent
  via the /proc kernel marker.
This commit is contained in:
brooklyn!
2026-05-29 17:00:45 -05:00
committed by GitHub
parent 696037587f
commit de8fed32fd
9 changed files with 361 additions and 42 deletions
+11 -2
View File
@@ -1,6 +1,15 @@
function isWslEnvironment(env = process.env, platform = process.platform) {
const fs = require('node:fs')
function isWslEnvironment(env = process.env, platform = process.platform, kernelRelease = null) {
if (platform !== 'linux') return false
return Boolean(env.WSL_DISTRO_NAME || env.WSL_INTEROP)
if (env.WSL_DISTRO_NAME || env.WSL_INTEROP) return true
try {
const release = kernelRelease ?? fs.readFileSync('/proc/sys/kernel/osrelease', 'utf8')
return /microsoft|wsl/i.test(release)
} catch {
return false
}
}
function isWindowsBinaryPathInWsl(filePath, options = {}) {
@@ -8,7 +8,8 @@ const { bundledRuntimeImportCheck, isWindowsBinaryPathInWsl, isWslEnvironment }
test('isWslEnvironment detects WSL2 env vars on linux', () => {
assert.equal(isWslEnvironment({ WSL_DISTRO_NAME: 'Ubuntu' }, 'linux'), true)
assert.equal(isWslEnvironment({ WSL_INTEROP: '/run/WSL/123_interop' }, 'linux'), true)
assert.equal(isWslEnvironment({}, 'linux'), false)
assert.equal(isWslEnvironment({}, 'linux', '6.6.87.2-microsoft-standard-WSL2'), true)
assert.equal(isWslEnvironment({}, 'linux', '6.6.87-generic'), false)
assert.equal(isWslEnvironment({ WSL_DISTRO_NAME: 'Ubuntu' }, 'darwin'), false)
})
+40 -3
View File
@@ -490,6 +490,44 @@ function openExternalUrl(rawUrl) {
return true
}
function ensureWslWindowsFonts() {
if (!IS_WSL) return
const fontsDir = ['/mnt/c/Windows/Fonts', '/mnt/c/windows/fonts'].find(candidate => {
try {
return fs.statSync(candidate).isDirectory()
} catch {
return false
}
})
if (!fontsDir) return
try {
const confDir = path.join(app.getPath('home'), '.config', 'fontconfig', 'conf.d')
const confPath = path.join(confDir, '99-hermes-wsl-windows-fonts.conf')
let existing = ''
try {
existing = fs.readFileSync(confPath, 'utf8')
} catch {
existing = ''
}
if (existing.includes(fontsDir)) return
fs.mkdirSync(confDir, { recursive: true })
fs.writeFileSync(
confPath,
`<?xml version="1.0"?>\n<!DOCTYPE fontconfig SYSTEM "fonts.dtd">\n<fontconfig>\n <dir>${fontsDir}</dir>\n</fontconfig>\n`
)
rememberLog(`[fonts] wired WSL Windows fonts for renderer: ${fontsDir}`)
const cache = spawn('fc-cache', ['-f', fontsDir], { detached: true, stdio: 'ignore' })
cache.on('error', () => undefined)
cache.unref()
} catch (error) {
rememberLog(`[fonts] WSL font setup skipped: ${error.message}`)
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
@@ -1341,9 +1379,7 @@ function resolveHermesBackend(dashboardArgs) {
shell: false
}
}
rememberLog(
`Ignoring system Python ${python}: hermes_cli is not importable; falling through to bootstrap.`
)
rememberLog(`Ignoring system Python ${python}: hermes_cli is not importable; falling through to bootstrap.`)
}
// 6. Nothing usable yet -- signal the bootstrap runner that we need to
@@ -3296,6 +3332,7 @@ app.whenReady().then(() => {
Menu.setApplicationMenu(null)
}
installMediaPermissions()
ensureWslWindowsFonts()
createWindow()
app.on('activate', () => {