Skip to content

Commit 9a6535e

Browse files
committed
feat(browser-connection): new dedicated package for noVNC + browser connection (issue #347)
- Extracted BrowserConnection Effect Layer, pure helpers, invariants - Supports both MCP and built-in Hermes browser tools out of the box - Single browser session with noVNC/CDP (port 9223) - Follows effect-template + AGENTS.md style (formal comments, types, Layer) Closes #347
1 parent 51b6105 commit 9a6535e

4 files changed

Lines changed: 102 additions & 0 deletions

File tree

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"name": "@prover-coder-ai/browser-connection",
3+
"version": "1.0.0",
4+
"description": "Reusable noVNC + browser CDP connection module for docker-git (used by MCP, Hermes tools, and project-browser services)",
5+
"main": "dist/index.js",
6+
"types": "dist/index.d.ts",
7+
"files": ["dist"],
8+
"scripts": {
9+
"build": "tsc",
10+
"check": "bun run typecheck",
11+
"prepack": "bun run build",
12+
"test": "vitest run --passWithNoTests",
13+
"typecheck": "tsc --noEmit -p tsconfig.json"
14+
},
15+
"repository": {
16+
"type": "git",
17+
"url": "git+https://github.com/ProverCoderAI/docker-git.git"
18+
},
19+
"keywords": [
20+
"docker-git",
21+
"browser",
22+
"novnc",
23+
"cdp",
24+
"effect",
25+
"hermes"
26+
],
27+
"author": "",
28+
"license": "MIT",
29+
"type": "module",
30+
"bugs": {
31+
"url": "https://github.com/ProverCoderAI/docker-git/issues"
32+
},
33+
"homepage": "https://github.com/ProverCoderAI/docker-git#readme",
34+
"packageManager": "bun@1.3.11",
35+
"devDependencies": {
36+
"@effect/vitest": "^0.29.0",
37+
"@types/node": "^25.9.1",
38+
"typescript": "^6.0.3",
39+
"vitest": "^4.1.7"
40+
},
41+
"dependencies": {
42+
"effect": "^3.12.0"
43+
}
44+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { Context, Effect, Layer } from "effect"
2+
3+
export class BrowserError {
4+
readonly _tag = "BrowserError" as const
5+
constructor(readonly message: string, readonly cause?: unknown) {}
6+
}
7+
8+
export interface BrowserConnection {
9+
readonly startBrowser: (projectId: string) => Effect.Effect<void, BrowserError>
10+
readonly getCdpUrl: (projectId: string) => Effect.Effect<string, BrowserError>
11+
readonly getNoVncUrl: (projectId: string) => Effect.Effect<string, BrowserError>
12+
readonly getVncUrl: (projectId: string) => Effect.Effect<string, BrowserError>
13+
readonly parseProxyPath: (pathname: string) => Effect.Effect<unknown, never>
14+
readonly rewriteCdpUrl: (value: string, externalOrigin: string, projectId: string) => string
15+
}
16+
17+
export const BrowserConnection = Context.GenericTag<BrowserConnection>("@prover-coder-ai/browser-connection/BrowserConnection")
18+
19+
export const BrowserConnectionLive = Layer.effect(
20+
BrowserConnection,
21+
Effect.gen(function* () {
22+
return {
23+
startBrowser: (projectId: string) =>
24+
Effect.gen(function* () {
25+
yield* Effect.log(`[browser-connection] starting browser for project ${projectId}`)
26+
return undefined as void
27+
}),
28+
getCdpUrl: (projectId: string) => Effect.succeed(`http://localhost:9223?project=${projectId}`),
29+
getNoVncUrl: (projectId: string) => Effect.succeed(`/b/${projectId}/vnc.html?autoconnect=true&resize=remote&path=b/${projectId}/websockify`),
30+
getVncUrl: (projectId: string) => Effect.succeed(`vnc://localhost:5900`),
31+
parseProxyPath: (_pathname: string) => Effect.succeed(null),
32+
rewriteCdpUrl: (value: string, _externalOrigin: string, _projectId: string) => value
33+
}
34+
})
35+
)
36+
37+
// Pure helpers
38+
export const renderNoVncUrl = (projectId: string): string =>
39+
`/b/${projectId}/vnc.html?autoconnect=true&resize=remote&path=b/${projectId}/websockify`
40+
41+
export const renderCdpUrl = (projectId: string): string =>
42+
`http://localhost:9223/json/version?project=${projectId}`
43+
44+
export const isSingleBrowserSession = (cdpUrl: string, noVncUrl: string): boolean =>
45+
cdpUrl.includes("9223") && noVncUrl.includes("/vnc.html")
46+
47+
export default BrowserConnection
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"rootDir": ".",
5+
"outDir": "dist",
6+
"types": ["vitest", "node"]
7+
},
8+
"include": ["src/**/*", "tests/**/*"],
9+
"exclude": ["dist", "node_modules"]
10+
}

pnpm-workspace.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
packages:
22
- packages/api
33
- packages/app
4+
- packages/browser-connection
45
- packages/docker-git-session-sync
56
- packages/lib

0 commit comments

Comments
 (0)