electron: move backend readiness, boot telemetry, the frontend server, port choice and runtime paths out of main.js - #151
Draft
kai-openswarm wants to merge 6 commits into
Draft
Conversation
… a window, so reducer tests run under node:test Both modules touched window at import time (port/host derivation, the fetch interceptor install, the debug handle), so any node:test file that imports a reducer importing API_BASE died with 'window is not defined' before its first assertion; fetchSessionsStrip.test.ts has been red that way since the resilience work landed, unnoticed because nothing runs these tests in CI. In a renderer (window present) nothing changes: same port/host, same interceptor, same handle. Without one the module answers with the defaults and installs nothing.
Nothing ran any of them in CI: the 235-file backend pytest suite, the 22 renderer node:test files and the edge suite were run by hand, one file at a time, so a regression only surfaced when someone happened to run the right one. Three small workflows, hosted ubuntu, path-filtered, read-only token: - backend-tests: pytest on Python 3.13 from the locked requirements, plus a completion assertion (junit testcase count == collect-only count) so a test process that dies mid-run can never read as green - frontend-tests: tsc --noEmit + node:test via tsx over src/**/*.test.ts(x), through frontend/scripts/run-tests.mjs (the runner the tests already name) - edge-tests: pytest for openswarm-edge All three are green on the current tree: 2951 backend tests, 143 frontend tests across 22 files, 14 edge tests.
Two of five hosted runs of the backend suite stalled at 99% until the job cap with no summary and no junit: one test blocked forever on a bare ws.receive_json() (fixed on its own in a separate change). A CI lane should never depend on every test being unable to hang, so add pytest-timeout to the dev requirements and run the suite with --timeout=300. On Linux the default signal method fails just the offending test and the run continues, so the report and the "every collected test ran" assertion stay meaningful.
test_ws_endpoint_streams_a_full_turn_end_to_end read the socket with a bare
ws.receive_json() in a 40-iteration loop and broke only on the assistant reply.
When the loop ends early for any reason (fewer than 40 events, no reply), the
next receive blocks forever and the whole pytest run stalls at 99% until the
job cap. On hosted runners it does exactly that intermittently, on Linux and
Windows alike: the turn path's configure_provider_env decides whether 9Router
needs reviving from provider evidence earlier tests may leave behind, and that
revival spawns/installs the router behind a module-level asyncio.Lock; the
background turn-label aux call reaches the same machinery. Neither is part of
this test's contract ("SDK and WS auth mocked, everything else real").
Pin both out with monkeypatch, bound every receive at 5s (a regression now
fails this test instead of hanging the runner), and wait for the turn's
completed status before asserting on session.messages so the assertion cannot
race the loop's tail.
Same class as the config/backendConnection change: safeMode.ts read `window` at import, and dashboardLayoutSlice imports it, so any reducer test that imports the slice died under node:test before it ran. Guard the read; in a renderer nothing changes.
…, port choice and runtime paths out of main.js
main.js was 4,259 lines. Five concerns that had grown inside it are now
modules of their own, each with a node:test file, and main.js keeps the
wiring (3,980 lines):
backend-readiness.js auth-token path/read, the backend import warm-up, and
waitForBackend (the health poll main.js runs at boot)
boot-telemetry.js boot beacon assembly and the phase timings it carries
frontend-server.js the loopback http server that serves the packaged
renderer bundle (the file:// replacement)
port-manager.js backend/frontend port choice (preferred port, then
get-port's OS-assigned fallback)
runtime-paths.js one place for the bundled-node / data / auth-token
paths that main.js previously derived inline
Two small hardening changes ride along in startBackend: PYTHONNOUSERSITE=1
(the embedded runtime must never import from the host user's roaming Python
site-packages) and PYTHONUNBUFFERED=1; and getBuildInfo tolerates a BOM on
build-info.json (Windows editors add one).
Verified on the packaged macOS app: upstream smoke (paint, preload bridge,
backend health, provenance, version) and the resilience e2e (backend crash →
respawn → reload).
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.
main.jswas 4,259 lines. Five concerns that had grown inside it are now modules with node:test files, andmain.jskeeps the wiring (3,980 lines):backend-readiness.jswaitForBackend(the boot health poll)boot-telemetry.jsfrontend-server.jsport-manager.jsget-port's OS-assigned fallback)runtime-paths.jsmain.jspreviously derived inlineruntime-paths.pythonExecutable()followsgetPythonPath()exactly (Windowspython.exe; macOSPython.app/Contents/MacOS/python3wrapper when shipped, elsebin/python3);pythonSitePackages()discovers the onelib/python3.Nthe bundled env ships instead of pinning a minor version, and fails loud on none/several.Two small hardening changes ride along in
startBackend:PYTHONNOUSERSITE=1(the embedded runtime must never import from the host user's roaming Python site-packages) andPYTHONUNBUFFERED=1;getBuildInfotolerates a BOM onbuild-info.json.Proof:
npm testinelectron/77/77; packaged macOS app: upstream smoke 5/5 (paint, preload bridge, backend health, provenance, version) + the characterization suite (#146) 19/19 including the resilience specs (backend crash → respawn → reload).Not in this PR: a live-shell PTY bridge (native dep, product decision) and the preload additions for it.