Conversation
057722e to
96608ac
Compare
commit a9209e2 Author: nas <[email protected]> Date: Fri Dec 12 05:11:10 2025 -0500 chore: add more runtime tests for state machine (#243) commit dd1113f Author: junhsss <[email protected]> Date: Wed Dec 10 16:43:26 2025 +0900 fix: test commit b95d82e Author: junhsss <[email protected]> Date: Wed Dec 10 16:37:34 2025 +0900 feat: better state allocation commit 65c7e65 Author: junhsss <[email protected]> Date: Wed Dec 10 16:37:22 2025 +0900 feat: cleanup browser listeners commit ad3666e Author: junhsss <[email protected]> Date: Wed Dec 10 06:58:17 2025 +0900 feat: handle browser crash commit e3048ed Author: junhsss <[email protected]> Date: Wed Dec 10 06:43:31 2025 +0900 feat: idempotent launch commit d72013e Author: junhsss <[email protected]> Date: Wed Dec 10 06:34:09 2025 +0900 feat: better browser close commit 9684c37 Author: junhsss <[email protected]> Date: Wed Dec 10 06:25:33 2025 +0900 feat: cleanup properly commit 95e005a Author: junhsss <[email protected]> Date: Wed Dec 10 06:19:00 2025 +0900 chore: update lockfile commit b289364 Author: junhsss <[email protected]> Date: Wed Dec 10 06:02:23 2025 +0900 feat: mutex guard + error state commit ba91c57 Author: junhsss <[email protected]> Date: Wed Dec 10 05:32:19 2025 +0900 refactor: type state pattern
There was a problem hiding this comment.
Pull request overview
Introduces a new state-machine-driven browser runtime (XState-based) intended to replace ad-hoc CDPService orchestration while preserving a CDPService-compatible API surface.
Changes:
- Added XState-powered
BrowserRuntimefacade, machine, actors (proxy, data plane, logger, drain, task registry), and new logging/tracing utilities. - Introduced Vitest multi-project test setup (unit/jsdom/integration) with substantial new runtime test coverage.
- Updated public service wiring to depend on a shared
BrowserRuntimeinterface and added optional state transition instrumentation.
Reviewed changes
Copilot reviewed 67 out of 69 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| package.json | Formatting-only adjustment at EOF. |
| api/vitest.config.ts | Adds Vitest multi-project configuration (unit/jsdom/integration). |
| api/tsconfig.build.json | Build tsconfig excludes tests from compilation output. |
| api/tests/integration/setup.ts | Adds integration test preflight check for Chrome availability. |
| api/tests/integration/browser-runtime.integration.test.ts | Adds end-to-end integration tests covering runtime lifecycle, proxying, events, and security. |
| api/src/types/enums.ts | Adds StateTransition browser event type. |
| api/src/types/browser.ts | Adds optional sessionId to launcher options. |
| api/src/types/browser-runtime.interface.ts | Introduces common BrowserRuntime interface shared by CDPService and new runtime. |
| api/src/steel-browser-plugin.ts | Switches Fastify decoration type from CDPService to BrowserRuntime. |
| api/src/services/session.service.ts | Uses BrowserRuntime, adds 409 error on concurrent session creation, passes sessionId through launch options. |
| api/src/services/cdp/plugins/core/plugin-manager.ts | Adds waitUntil helper to track async plugin tasks. |
| api/src/services/cdp/instrumentation/types.ts | Adds StateTransitionEvent and extends union. |
| api/src/services/cdp/cdp.service.ts | Implements BrowserRuntime interface and adds plugin accessors / waitUntil. |
| api/src/plugins/browser.ts | Chooses between legacy CDPService and new XState runtime via env flags; sets up transition logging storage. |
| api/src/modules/sessions/sessions.routes.ts | Makes instrumentation logger optional when recording. |
| api/src/modules/sessions/sessions.controller.ts | Returns statusCode from thrown errors; uses runtime getTargetId. |
| api/src/modules/actions/actions.controller.ts | Switches controller dependencies to BrowserRuntime. |
| api/src/env.ts | Adds flags for runtime selection and state transition logging/tracing controls. |
| api/src/browser-runtime/utils/validation.ts | Adds timezone validation helper with timeout. |
| api/src/browser-runtime/utils/timezone.ts | Adds timezone lookup helper with proxy support and fallback. |
| api/src/browser-runtime/utils/extensions.ts | Adds helper to resolve extension directories. |
| api/src/browser-runtime/utils/browser-utils.ts | Adds Chrome path resolution and mouse helper injection utilities. |
| api/src/browser-runtime/utils.ts | Adds deepMerge utility used by runtime config resolution. |
| api/src/browser-runtime/types.ts | Re-exports driver types and SessionData for runtime package boundary. |
| api/src/browser-runtime/tracing/runtime-tracer.ts | Adds OpenTelemetry tracing helpers with minimal vs detailed gating. |
| api/src/browser-runtime/tracing/index.ts | Re-exports tracing helpers. |
| api/src/browser-runtime/storage/rolling-file-storage.ts | Adds NDJSON rolling storage implementation for transition logs. |
| api/src/browser-runtime/storage/index.ts | Re-exports rolling storage. |
| api/src/browser-runtime/services/proxy.service.ts | Adds proxy-chain based proxy server with passthrough for internal bypass. |
| api/src/browser-runtime/services/fingerprint.service.ts | Adds fingerprint generation + safe injection with fallback injector. |
| api/src/browser-runtime/services/config-resolver.ts | Adds config resolution (timezone, userDataDir, user prefs merge, fingerprint generation). |
| api/src/browser-runtime/plugins/base-plugin.ts | Defines new runtime plugin interface used by the machine. |
| api/src/browser-runtime/machine/browser.machine.ts | Adds XState supervisor machine wiring boot/ready/drain/cleanup phases and event bridging. |
| api/src/browser-runtime/machine/browser.machine.test.ts | Adds unit tests for the machine transitions and error paths. |
| api/src/browser-runtime/machine/actors/task-registry.actor.ts | Adds background task registry actor with drain/cancel semantics. |
| api/src/browser-runtime/machine/actors/proxy-launcher.actor.ts | Adds actor to launch/close proxy server. |
| api/src/browser-runtime/machine/actors/plugin-manager.actor.ts | Adds actor to invoke plugin lifecycle hooks and page-created hooks. |
| api/src/browser-runtime/machine/actors/logger.actor.ts | Adds actor to attach CDP instrumentation, inject fingerprint, and restore storage. |
| api/src/browser-runtime/machine/actors/drain.actor.ts | Adds drain actor to drain tasks, notify plugins, flush logs, cancel remaining tasks. |
| api/src/browser-runtime/machine/actors/data-plane.actor.ts | Adds HTTP+WS “data plane” to proxy CDP WebSocket and detect disconnects. |
| api/src/browser-runtime/machine/actors/cleanup-phases.actor.ts | Adds cleanup phase helpers (close browser/proxy, flush logs, notify plugin shutdown). |
| api/src/browser-runtime/machine/actors/tests/proxy-launcher.actor.test.ts | Tests proxy launcher behavior with mocked proxy service. |
| api/src/browser-runtime/machine/actors/tests/plugin-manager.actor.test.ts | Tests plugin hooks invocation and error isolation. |
| api/src/browser-runtime/machine/actors/tests/logger-actor.test.ts | Tests logger actor target attachment behavior. |
| api/src/browser-runtime/machine/actors/tests/drain.actor.test.ts | Tests drain sequencing and plugin notifications. |
| api/src/browser-runtime/machine/actors/tests/data-plane.actor.test.ts | Tests server startup, EADDRINUSE fatal error, disconnect handling. |
| api/src/browser-runtime/machine/actors/tests/cleanup-phases.actor.test.ts | Tests each cleanup phase helper. |
| api/src/browser-runtime/logging/state-transition-logger.ts | Adds state transition event recorder to logger/storage/span events. |
| api/src/browser-runtime/logging/index.ts | Re-exports state transition logger. |
| api/src/browser-runtime/index.ts | Public export surface for the runtime package. |
| api/src/browser-runtime/facade/browser-runtime.ts | Adds runtime facade implementing BrowserRuntime via XState actor + hooks + proxy. |
| api/src/browser-runtime/facade/browser-runtime.test.ts | Adds comprehensive facade tests (config reuse, hooks, ws proxy, plugins, keepAlive). |
| api/src/browser-runtime/drivers/types.ts | Defines driver/runtime config types and supervisor events. |
| api/src/browser-runtime/drivers/simulated-launcher.ts | Adds simulated launcher for load-testing. |
| api/src/browser-runtime/drivers/puppeteer-launcher.ts | Adds Puppeteer-based launcher with proxy/extensions/fingerprint/timezone/security hardening. |
| api/src/browser-runtime/drivers/mock-launcher.ts | Adds mock launcher for tests and crash simulation. |
| api/src/browser-runtime/drivers/index.ts | Re-exports drivers. |
| api/src/browser-runtime/drivers/tests/puppeteer-launcher.test.ts | Adds Puppeteer launcher tests including file:// blocking behavior. |
| api/src/browser-runtime/tests/task-registry.test.ts | Adds task registry actor tests (drain/cancel/status). |
| api/src/browser-runtime/tests/state-transition-logger.test.ts | Adds transition logger tests. |
| api/src/browser-runtime/tests/rolling-file-storage.test.ts | Adds rolling storage tests (write/rotate/cleanup). |
| api/src/browser-runtime/tests/machine-with-mock.test.ts | Adds runtime+machine tests using MockLauncher. |
| api/src/browser-runtime/tests/load.test.ts | Adds load tests using SimulatedLauncher (concurrent + sequential sessions). |
| api/src/browser-runtime/tests/helpers.ts | Adds shared mock helpers for runtime tests. |
| api/src/browser-runtime/tests/fingerprint.test.ts | Adds fingerprint generation/injection tests. |
| api/src/browser-runtime/tests/disconnect-recovery.test.ts | Adds keepAlive disconnect recovery tests. |
| api/package.json | Adds Vitest scripts, build tsconfig, and runtime dependencies (xstate, async-mutex). |
| .husky/pre-commit | Adds typecheck + tests to pre-commit, alongside formatting/lint/build. |
Comments suppressed due to low confidence (5)
api/src/browser-runtime/machine/browser.machine.ts:1
- The
off("fileProtocolViolation", () => {})call will not remove the listener because it passes a new function reference. Store the handler in a variable and use that same reference in bothonandoffto avoid leaking listeners across machine restarts.
api/src/browser-runtime/machine/actors/plugin-manager.actor.ts:1 fromCallbackcleanups are expected to be synchronous; returning anasynccleanup means the promise is ignored and can mask shutdown issues. Make the cleanup a non-async function (and avoid awaiting inside it) so teardown is deterministic.
api/src/browser-runtime/utils.ts:1- Iterating
for...inoversourcecan merge inherited/prototype properties and enables prototype-pollution vectors (e.g.,__proto__,constructor,prototype) if any part ofsourceis user-influenced (such as preferences/config). Iterate overObject.keys/Object.entriesand explicitly block dangerous keys before assignment.
api/vitest.config.ts:1 pathis imported but not used in this config file. Removing it reduces noise and avoids lint warnings in stricter setups.
api/src/modules/sessions/sessions.controller.ts:1- Correct typo in log message: "lauching" → "launching".
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let timezone = "UTC"; | ||
| try { | ||
| if (config.skipFingerprintInjection) { | ||
| console.log("[PuppeteerLauncher] Skipping timezone validation"); | ||
| } else { | ||
| timezone = await validateTimezone(config.timezone); | ||
| } | ||
| } catch (error) { | ||
| console.warn(`[PuppeteerLauncher] Timezone validation failed: ${error}`); | ||
| } |
There was a problem hiding this comment.
When skipFingerprintInjection is true, this skips timezone validation and leaves timezone as "UTC", ignoring config.timezone. This will unintentionally force sessions into UTC even when a valid timezone was resolved. Consider always setting timezone from config.timezone (and optionally validating it), independent of fingerprint injection.
| event: snapshot._nodes?.[0]?.key || "unknown", | ||
| context: { browser: !!snapshot.context.browser }, | ||
| }); | ||
| } else { | ||
| this.logger.info( | ||
| { from: previousState, to: currentState, event: snapshot._nodes?.[0]?.key }, |
There was a problem hiding this comment.
Using snapshot._nodes relies on XState internal/private fields that can change across releases, and it also doesn’t represent the triggering event (it’s a node key). Prefer capturing the actual triggering event via supported snapshot fields (if available) or by tracking the last sent event in the facade/machine and logging that instead.
| event: snapshot._nodes?.[0]?.key || "unknown", | |
| context: { browser: !!snapshot.context.browser }, | |
| }); | |
| } else { | |
| this.logger.info( | |
| { from: previousState, to: currentState, event: snapshot._nodes?.[0]?.key }, | |
| event: snapshot.event?.type ?? "unknown", | |
| context: { browser: !!snapshot.context.browser }, | |
| }); | |
| } else { | |
| this.logger.info( | |
| { from: previousState, to: currentState, event: snapshot.event?.type }, |
| echo "🎨 Running code formatting..." | ||
| npm run typecheck -w api | ||
|
|
||
| # Code formatting and linting | ||
| echo "🎨 Running code formatting..." |
There was a problem hiding this comment.
The echoed message says “Running code formatting...” but the command is typecheck. Update the message to reflect what’s actually running (and consider avoiding duplicate “formatting” echo lines) to make pre-commit output easier to interpret.
| echo "🎨 Running code formatting..." | |
| npm run typecheck -w api | |
| # Code formatting and linting | |
| echo "🎨 Running code formatting..." | |
| echo "🔧 Running API type checking..." | |
| npm run typecheck -w api | |
| # Code formatting and linting | |
| echo "🎨 Running code formatting and linting for API..." |
Overview
This introduces a new predictable, state-machine-based runtime to replace the ad-hoc CDPService orchestration.
Architecture
Components
States
Events
launchSucceeded: Browser launched successfullylaunchFailed: Browser launch faileddisconnected: Browser disconnected unexpectedlytargetCreated/Changed/Destroyed: Page lifecycle eventsfileProtocolViolation: Fatal security violationCommands
start(config): Start a new sessionend(reason): End current session