feat(install): run on Linux, and pick the platform at install time - #245
Open
y-ashish-y wants to merge 3 commits into
Open
feat(install): run on Linux, and pick the platform at install time#245y-ashish-y wants to merge 3 commits into
y-ashish-y wants to merge 3 commits into
Conversation
`install.sh` refused everything that was not Darwin, so the only way to use the harness on Linux was to fork it. This adds the missing half rather than replacing the existing one: the macOS DMG flow is untouched, and `main()` now dispatches on `uname -s` instead of dying on it. The Linux side is `package/ego-linux`, a CDP shim that supplies the `globalThis.ego` object the macOS app injects natively, backed by a stock Chrome/Chromium. `package/ego-browser` is unchanged — every helper, locator, driver and format runs as-is on both platforms. That is the point of the design, and it is what the test run below actually verifies. Install on Linux is a build plus a symlink, not a download: the script checks Node >= 22 and a browser on PATH up front and stops with a clear error rather than half-installing. `EGO_LINUX_CHROME` and `EGO_LINUX_BIN_DIR` override the two things worth overriding. Verified on Linux against an unmodified `package/ego-browser`: - `package/ego-linux` suite: 54/54 pass - `sh skills/ego-browser/scripts/install.sh` end to end — build, link, PATH warning, and the post-install smoke check - dispatcher, with `uname` stubbed: Darwin enters the DMG flow (reaches `require_command hdiutil`), FreeBSD exits with `unsupported platform` Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two places described `finishDragProbe` by its current constant — a 50 ms window — and one of them prescribed the fix. Both go stale the moment that window changes, and neither belongs in install/porting docs: the race is in the shared harness, not in anything Linux-specific. The install troubleshooting bullet is dropped outright; it was filed under "Linux" for a symptom that has nothing to do with the platform. The README's section keeps the measurement — what was observed, how it reproduces, and why the shim cannot suppress it — and drops the constant and the remedy, so it stays true whatever the harness does about it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- spaces-server: await Target.detachFromTarget before releasing the session
in closeAll, retain, and the two error paths in open(). The previous
fire-and-forget detach left frames in flight forwarded into the harness
event buffer (drainEvents -> agent). Promise.all + await is the fix.
- spaces-server: cap request bodies at 1 MiB with a 413 ResponseError so a
caller cannot OOM the loopback daemon. Pass Connection: close on the
413 response so the half-written socket does not stall server.close().
- chrome: when EGO_LINUX_CDP_URL is set, parse the port out of the URL and
best-effort probe it. The previous shape returned { wsUrl, launched }
with no port, which silently disabled MRU tab ordering in createTabsApi.
- bin/ego-browser: pull detached spawns through a helper that attaches an
error listener. Detached + unref'd, an unhandled 'error' on the child
process kills Node, which is exactly what --spaces is trying to avoid.
- install.sh: set -euo pipefail; split the npm ci / npm run build steps so
each dies with its own message.
- install.md: align with the code — listTabs is scoped to the selected
space (was described as browser-wide). Drop the macOS-only 'nodejs'
prefix from the example to match SKILL.md; the shim still accepts it.
- package.json: drop the unused 'bin' entry; the symlink in install.sh is
the canonical install path.
- spaces-server: export the cast-pool factory under a test-only name so the
detach/release ordering has a regression test that does not boot Chrome.
- tests: add unit tests for the body cap, the close/open race, the detach-
fail path, and a static XSS check on spaces-ui.mjs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
skills/ego-browser/scripts/install.shpreviously opened withso the only way to run the harness on Linux was to fork the repo. This PR adds the missing half instead of replacing the existing one.
main()was renamed tomain_macos()and lost exactly one line — the guard above. Every DMG function (install_ego_lite,find_ego_lite_app,strip_quarantine_attributes,cleanup, thetrap) is byte-identical.main()dispatches onuname -s:Darwin→ the existing flow,Linux→ the new one, anything else →unsupported platform: <name>rather than a macOS-specific message.package/ego-linux(new, 39 files) supplies theglobalThis.egoobject the macOS app injects natively, backed by a stock Chrome/Chromium over CDP.Why it does not touch
package/ego-browserpackage/ego-browseris unchanged in this PR — 0 files. Every helper, locator, driver and format runs as-is on both platforms; the port is a backing implementation, not a second harness. The test suite below is what checks it.Install on Linux
A build plus a symlink — there is nothing to download:
It verifies Node >= 22 and a browser on PATH before touching anything.
EGO_LINUX_CHROMEpoints it at a browser that is not on PATH;EGO_LINUX_BIN_DIRlinks somewhere other than~/.local/bin. There is no GUI onboarding step on Linux: when the script returns, the command is ready.Verification
Run on Linux against an unmodified
package/ego-browser:package/ego-linuxsuitesh skills/ego-browser/scripts/install.shend to endnpm ci, build, symlink, post-install smoke checkunamestubbed toDarwinrequire_command hdiutilunamestubbed toFreeBSDerror: unsupported platform: FreeBSD (supported: macOS, Linux)sh -non the installerReview fixes (over PR #234)
closeAll/retain/ the two error paths inopen()used to fireTarget.detachFromTargetand immediately callreleaseSession; frames in flight were forwarded intodrainEvents(→ the agent). NowPromise.all+awaitwaits for each detach to settle before the release. Backed by a regression test (closeAll awaits detach+release still happens when detach fails).ResponseError(413)inreadBody; the 413 response carriesConnection: closesoserver.close()does not stall on the half-written socket. Tested.EGO_LINUX_CDP_URLreturns a port. The previous shape was{ wsUrl, launched: false }with no port, which silently disabled MRU tab ordering increateTabsApi. Now the port is parsed from the URL and best-effort probed; a dead endpoint is surfaced instead of hanging.error. Detached +unref'd, an unhandled'error'on the child process kills Node — exactly what--spacesis trying to avoid. ExtractedspawnDetachedhelper used byopenPanelWindow,runSpacesDaemon, andopenSpaces.set -euo pipefail+ splitnpm ci/npm run buildso each dies with its own message.listTabsis scoped to the selected space (was described as browser-wide). Dropped the macOS-onlynodejsprefix from the example to matchSKILL.md; the shim still accepts it for backward compatibility.binentry. The symlink ininstall.shis the canonical install path.spaces-ui.mjs— fails the moment any user-controlled field is assigned viainnerHTMLinstead oftextContent/createTextNode.Scope
Carved down from a working Linux fork to the platform-support core. Deliberately not included:
README.md), fork-specific docs and experimentsdriver/pointer.tsdrag-timing fix that is platform-agnostic — belongs in its own PR