fix: improve WSL login fallback

This commit is contained in:
Advait Paliwal
2026-04-14 09:01:44 -07:00
parent 5d10285372
commit 8de8054e4f
7 changed files with 157 additions and 18 deletions

View File

@@ -259,6 +259,15 @@ Use this file to track chronology, not release notes. Keep entries short, factua
- Blockers: I did not rerun a full broad deepresearch workflow end-to-end after this prompt-only hardening because those runs are materially longer and more expensive than the narrow reproductions already used to isolate the earlier deadlocks. - Blockers: I did not rerun a full broad deepresearch workflow end-to-end after this prompt-only hardening because those runs are materially longer and more expensive than the narrow reproductions already used to isolate the earlier deadlocks.
- Next: Commit and push the prompt hardening, then, if needed, add a deterministic wrapper around final artifact promotion instead of relying only on prompt adherence. - Next: Commit and push the prompt hardening, then, if needed, add a deterministic wrapper around final artifact promotion instead of relying only on prompt adherence.
### 2026-04-14 09:30 PDT — wsl-login-and-uninstall-docs-pass
- Objective: Fix the remaining WSL setup blocker and close the last actionable support issue instead of leaving the tracker open after the earlier workflow/model fixes.
- Changed: Added a dedicated alpha-hub auth patch helper and tests; extended the alphaXiv login patch so WSL uses `wslview` when available and falls back to `cmd.exe /c start`, while also printing the auth URL explicitly for manual copy/paste if browser launch still fails; documented standalone uninstall steps in `README.md` and `website/src/content/docs/getting-started/installation.md`.
- Verified: Added regression tests for the alpha-hub auth patch, reran `npm test`, `npm run typecheck`, and `npm run build`, and smoke-checked the patched alpha-hub source rewrite to confirm it injects both the WSL browser path and the explicit auth URL logging.
- Failed / learned: This repo can patch alpha-hub's login UX reliably, but it still does not ship a destructive `feynman uninstall` command; the practical fix for the support issue is documented uninstall steps rather than a rushed cross-platform remover.
- Blockers: I did not run a true WSL shell here, so the WSL fix is validated by the deterministic source patch plus tests rather than an actual Windows-hosted browser-launch repro.
- Next: Push the WSL/login pass and close the stale issues and PRs that are already superseded by `main`.
### 2026-04-12 13:20 PDT — capital-france (citation verification brief) ### 2026-04-12 13:20 PDT — capital-france (citation verification brief)
- Objective: Verify citations in the capital-of-France draft and produce a cited verifier brief. - Objective: Verify citations in the capital-of-France draft and produce a cited verifier brief.

View File

@@ -31,6 +31,8 @@ The installer downloads a standalone native bundle with its own Node.js runtime.
To upgrade the standalone app later, rerun the installer. `feynman update` only refreshes installed Pi packages inside Feynman's environment; it does not replace the standalone runtime bundle itself. To upgrade the standalone app later, rerun the installer. `feynman update` only refreshes installed Pi packages inside Feynman's environment; it does not replace the standalone runtime bundle itself.
To uninstall the standalone app, remove the launcher and runtime bundle, then optionally remove `~/.feynman` if you also want to delete settings, auth, and sessions. See the installation guide for platform-specific paths.
Local models are supported through the custom-provider flow. For Ollama, run `feynman setup`, choose `Custom provider (baseUrl + API key)`, use `openai-completions`, and point it at `http://localhost:11434/v1`. Local models are supported through the custom-provider flow. For Ollama, run `feynman setup`, choose `Custom provider (baseUrl + API key)`, use `openai-completions`, and point it at `http://localhost:11434/v1`.
### Skills Only ### Skills Only

View File

@@ -0,0 +1 @@
export declare function patchAlphaHubAuthSource(source: string): string;

View File

@@ -0,0 +1,66 @@
const LEGACY_SUCCESS_HTML = "'<html><body><h2>Logged in to Alpha Hub</h2><p>You can close this tab.</p></body></html>'";
const LEGACY_ERROR_HTML = "'<html><body><h2>Login failed</h2><p>You can close this tab.</p></body></html>'";
const bodyAttr = 'style="font-family:system-ui,sans-serif;text-align:center;padding-top:20vh;background:#050a08;color:#f0f5f2"';
const logo = '<h1 style="font-family:monospace;font-size:48px;color:#34d399;margin:0">feynman</h1>';
const FEYNMAN_SUCCESS_HTML = `'<html><body ${bodyAttr}>${logo}<h2 style="color:#34d399;margin-top:16px">Logged in</h2><p style="color:#8aaa9a">You can close this tab.</p></body></html>'`;
const FEYNMAN_ERROR_HTML = `'<html><body ${bodyAttr}>${logo}<h2 style="color:#ef4444;margin-top:16px">Login failed</h2><p style="color:#8aaa9a">You can close this tab.</p></body></html>'`;
const CURRENT_OPEN_BROWSER = [
"function openBrowser(url) {",
" try {",
" const plat = platform();",
" if (plat === 'darwin') execSync(`open \"${url}\"`);",
" else if (plat === 'linux') execSync(`xdg-open \"${url}\"`);",
" else if (plat === 'win32') execSync(`start \"\" \"${url}\"`);",
" } catch {}",
"}",
].join("\n");
const PATCHED_OPEN_BROWSER = [
"function openBrowser(url) {",
" try {",
" const plat = platform();",
" const isWsl = plat === 'linux' && (Boolean(process.env.WSL_DISTRO_NAME) || Boolean(process.env.WSL_INTEROP));",
" if (plat === 'darwin') execSync(`open \"${url}\"`);",
" else if (isWsl) {",
" try {",
" execSync(`wslview \"${url}\"`);",
" } catch {",
" execSync(`cmd.exe /c start \"\" \"${url}\"`);",
" }",
" }",
" else if (plat === 'linux') execSync(`xdg-open \"${url}\"`);",
" else if (plat === 'win32') execSync(`cmd /c start \"\" \"${url}\"`);",
" } catch {}",
"}",
].join("\n");
const LEGACY_WIN_OPEN = "else if (plat === 'win32') execSync(`start \"${url}\"`);";
const FIXED_WIN_OPEN = "else if (plat === 'win32') execSync(`cmd /c start \"\" \"${url}\"`);";
const OPEN_BROWSER_LOG = "process.stderr.write('Opening browser for alphaXiv login...\\n');";
const OPEN_BROWSER_LOG_WITH_URL = "process.stderr.write(`Opening browser for alphaXiv login...\\nAuth URL: ${authUrl.toString()}\\n`);";
export function patchAlphaHubAuthSource(source) {
let patched = source;
if (patched.includes(LEGACY_SUCCESS_HTML)) {
patched = patched.replace(LEGACY_SUCCESS_HTML, FEYNMAN_SUCCESS_HTML);
}
if (patched.includes(LEGACY_ERROR_HTML)) {
patched = patched.replace(LEGACY_ERROR_HTML, FEYNMAN_ERROR_HTML);
}
if (patched.includes(CURRENT_OPEN_BROWSER)) {
patched = patched.replace(CURRENT_OPEN_BROWSER, PATCHED_OPEN_BROWSER);
}
if (patched.includes(LEGACY_WIN_OPEN)) {
patched = patched.replace(LEGACY_WIN_OPEN, FIXED_WIN_OPEN);
}
if (patched.includes(OPEN_BROWSER_LOG)) {
patched = patched.replace(OPEN_BROWSER_LOG, OPEN_BROWSER_LOG_WITH_URL);
}
return patched;
}

View File

@@ -5,6 +5,7 @@ import { homedir } from "node:os";
import { dirname, resolve } from "node:path"; import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url"; import { fileURLToPath } from "node:url";
import { FEYNMAN_LOGO_HTML } from "../logo.mjs"; import { FEYNMAN_LOGO_HTML } from "../logo.mjs";
import { patchAlphaHubAuthSource } from "./lib/alpha-hub-auth-patch.mjs";
import { patchPiExtensionLoaderSource } from "./lib/pi-extension-loader-patch.mjs"; import { patchPiExtensionLoaderSource } from "./lib/pi-extension-loader-patch.mjs";
import { patchPiGoogleLegacySchemaSource } from "./lib/pi-google-legacy-schema-patch.mjs"; import { patchPiGoogleLegacySchemaSource } from "./lib/pi-google-legacy-schema-patch.mjs";
import { PI_WEB_ACCESS_PATCH_TARGETS, patchPiWebAccessSource } from "./lib/pi-web-access-patch.mjs"; import { PI_WEB_ACCESS_PATCH_TARGETS, patchPiWebAccessSource } from "./lib/pi-web-access-patch.mjs";
@@ -620,25 +621,11 @@ const alphaHubAuthPath = findPackageRoot("@companion-ai/alpha-hub")
: null; : null;
if (alphaHubAuthPath && existsSync(alphaHubAuthPath)) { if (alphaHubAuthPath && existsSync(alphaHubAuthPath)) {
let source = readFileSync(alphaHubAuthPath, "utf8"); const source = readFileSync(alphaHubAuthPath, "utf8");
const oldSuccess = "'<html><body><h2>Logged in to Alpha Hub</h2><p>You can close this tab.</p></body></html>'"; const patched = patchAlphaHubAuthSource(source);
const oldError = "'<html><body><h2>Login failed</h2><p>You can close this tab.</p></body></html>'"; if (patched !== source) {
const bodyAttr = `style="font-family:system-ui,sans-serif;text-align:center;padding-top:20vh;background:#050a08;color:#f0f5f2"`; writeFileSync(alphaHubAuthPath, patched, "utf8");
const logo = `<h1 style="font-family:monospace;font-size:48px;color:#34d399;margin:0">feynman</h1>`;
const newSuccess = `'<html><body ${bodyAttr}>${logo}<h2 style="color:#34d399;margin-top:16px">Logged in</h2><p style="color:#8aaa9a">You can close this tab.</p></body></html>'`;
const newError = `'<html><body ${bodyAttr}>${logo}<h2 style="color:#ef4444;margin-top:16px">Login failed</h2><p style="color:#8aaa9a">You can close this tab.</p></body></html>'`;
if (source.includes(oldSuccess)) {
source = source.replace(oldSuccess, newSuccess);
} }
if (source.includes(oldError)) {
source = source.replace(oldError, newError);
}
const brokenWinOpen = "else if (plat === 'win32') execSync(`start \"${url}\"`);";
const fixedWinOpen = "else if (plat === 'win32') execSync(`cmd /c start \"\" \"${url}\"`);";
if (source.includes(brokenWinOpen)) {
source = source.replace(brokenWinOpen, fixedWinOpen);
}
writeFileSync(alphaHubAuthPath, source, "utf8");
} }
if (existsSync(piMemoryPath)) { if (existsSync(piMemoryPath)) {

View File

@@ -0,0 +1,51 @@
import test from "node:test";
import assert from "node:assert/strict";
import { patchAlphaHubAuthSource } from "../scripts/lib/alpha-hub-auth-patch.mjs";
test("patchAlphaHubAuthSource fixes browser open logic for WSL and Windows", () => {
const input = [
"function openBrowser(url) {",
" try {",
" const plat = platform();",
" if (plat === 'darwin') execSync(`open \"${url}\"`);",
" else if (plat === 'linux') execSync(`xdg-open \"${url}\"`);",
" else if (plat === 'win32') execSync(`start \"\" \"${url}\"`);",
" } catch {}",
"}",
].join("\n");
const patched = patchAlphaHubAuthSource(input);
assert.match(patched, /const isWsl = plat === 'linux'/);
assert.match(patched, /wslview/);
assert.match(patched, /cmd\.exe \/c start/);
assert.match(patched, /cmd \/c start/);
});
test("patchAlphaHubAuthSource includes the auth URL in login output", () => {
const input = "process.stderr.write('Opening browser for alphaXiv login...\\n');";
const patched = patchAlphaHubAuthSource(input);
assert.match(patched, /Auth URL: \$\{authUrl\.toString\(\)\}/);
});
test("patchAlphaHubAuthSource is idempotent", () => {
const input = [
"function openBrowser(url) {",
" try {",
" const plat = platform();",
" if (plat === 'darwin') execSync(`open \"${url}\"`);",
" else if (plat === 'linux') execSync(`xdg-open \"${url}\"`);",
" else if (plat === 'win32') execSync(`start \"\" \"${url}\"`);",
" } catch {}",
"}",
"process.stderr.write('Opening browser for alphaXiv login...\\n');",
].join("\n");
const once = patchAlphaHubAuthSource(input);
const twice = patchAlphaHubAuthSource(once);
assert.equal(twice, once);
});

View File

@@ -33,6 +33,29 @@ To update the standalone Feynman app on macOS, Linux, or Windows, rerun the inst
`feynman update` is different: it updates installed Pi packages inside Feynman's environment, not the standalone app bundle itself. `feynman update` is different: it updates installed Pi packages inside Feynman's environment, not the standalone app bundle itself.
## Uninstalling
Feynman does not currently ship a dedicated `uninstall` command. Remove the standalone launcher and runtime bundle directly, then optionally remove the Feynman home directory if you also want to delete settings, auth, and sessions.
On macOS or Linux:
```bash
rm -f ~/.local/bin/feynman
rm -rf ~/.local/share/feynman
# optional: remove settings, auth, sessions, and installed package state
rm -rf ~/.feynman
```
On Windows PowerShell:
```powershell
Remove-Item "$env:LOCALAPPDATA\\Programs\\feynman" -Recurse -Force
# optional: remove settings, auth, sessions, and installed package state
Remove-Item "$HOME\\.feynman" -Recurse -Force
```
If you added the launcher directory to `PATH` manually, remove that entry as well.
## Skills only ## Skills only
If you only want Feynman's research skills and not the full terminal runtime, install the skill library separately. If you only want Feynman's research skills and not the full terminal runtime, install the skill library separately.