camou 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +229 -0
  2. package/dist/browser/actions.d.ts +4 -0
  3. package/dist/browser/actions.js +15 -0
  4. package/dist/browser/actions.js.map +1 -0
  5. package/dist/browser/manager.d.ts +85 -0
  6. package/dist/browser/manager.js +300 -0
  7. package/dist/browser/manager.js.map +1 -0
  8. package/dist/browser/snapshot.d.ts +17 -0
  9. package/dist/browser/snapshot.js +93 -0
  10. package/dist/browser/snapshot.js.map +1 -0
  11. package/dist/browser/tabs.d.ts +24 -0
  12. package/dist/browser/tabs.js +8 -0
  13. package/dist/browser/tabs.js.map +1 -0
  14. package/dist/camoufox/config.d.ts +67 -0
  15. package/dist/camoufox/config.js +121 -0
  16. package/dist/camoufox/config.js.map +1 -0
  17. package/dist/camoufox/env.d.ts +3 -0
  18. package/dist/camoufox/env.js +27 -0
  19. package/dist/camoufox/env.js.map +1 -0
  20. package/dist/camoufox/installer.d.ts +24 -0
  21. package/dist/camoufox/installer.js +291 -0
  22. package/dist/camoufox/installer.js.map +1 -0
  23. package/dist/camoufox/launcher.d.ts +22 -0
  24. package/dist/camoufox/launcher.js +105 -0
  25. package/dist/camoufox/launcher.js.map +1 -0
  26. package/dist/camoufox/prefs.d.ts +5 -0
  27. package/dist/camoufox/prefs.js +27 -0
  28. package/dist/camoufox/prefs.js.map +1 -0
  29. package/dist/camoufox/presets.d.ts +14 -0
  30. package/dist/camoufox/presets.js +73 -0
  31. package/dist/camoufox/presets.js.map +1 -0
  32. package/dist/camoufox/registry.d.ts +30 -0
  33. package/dist/camoufox/registry.js +195 -0
  34. package/dist/camoufox/registry.js.map +1 -0
  35. package/dist/camoufox/validation.d.ts +4 -0
  36. package/dist/camoufox/validation.js +103 -0
  37. package/dist/camoufox/validation.js.map +1 -0
  38. package/dist/cli/daemon.d.ts +2 -0
  39. package/dist/cli/daemon.js +59 -0
  40. package/dist/cli/daemon.js.map +1 -0
  41. package/dist/cli/main.d.ts +2 -0
  42. package/dist/cli/main.js +147 -0
  43. package/dist/cli/main.js.map +1 -0
  44. package/dist/cli/output.d.ts +1 -0
  45. package/dist/cli/output.js +108 -0
  46. package/dist/cli/output.js.map +1 -0
  47. package/dist/cli/program.d.ts +42 -0
  48. package/dist/cli/program.js +214 -0
  49. package/dist/cli/program.js.map +1 -0
  50. package/dist/daemon/daemon.d.ts +12 -0
  51. package/dist/daemon/daemon.js +36 -0
  52. package/dist/daemon/daemon.js.map +1 -0
  53. package/dist/daemon/main.d.ts +2 -0
  54. package/dist/daemon/main.js +28 -0
  55. package/dist/daemon/main.js.map +1 -0
  56. package/dist/daemon/router.d.ts +7 -0
  57. package/dist/daemon/router.js +43 -0
  58. package/dist/daemon/router.js.map +1 -0
  59. package/dist/daemon/runtime.d.ts +11 -0
  60. package/dist/daemon/runtime.js +54 -0
  61. package/dist/daemon/runtime.js.map +1 -0
  62. package/dist/doctor/diagnostics.d.ts +38 -0
  63. package/dist/doctor/diagnostics.js +152 -0
  64. package/dist/doctor/diagnostics.js.map +1 -0
  65. package/dist/ipc/client.d.ts +6 -0
  66. package/dist/ipc/client.js +63 -0
  67. package/dist/ipc/client.js.map +1 -0
  68. package/dist/ipc/protocol.d.ts +775 -0
  69. package/dist/ipc/protocol.js +128 -0
  70. package/dist/ipc/protocol.js.map +1 -0
  71. package/dist/ipc/server.d.ts +10 -0
  72. package/dist/ipc/server.js +99 -0
  73. package/dist/ipc/server.js.map +1 -0
  74. package/dist/state/paths.d.ts +32 -0
  75. package/dist/state/paths.js +121 -0
  76. package/dist/state/paths.js.map +1 -0
  77. package/dist/state/store.d.ts +4 -0
  78. package/dist/state/store.js +30 -0
  79. package/dist/state/store.js.map +1 -0
  80. package/dist/util/errors.d.ts +45 -0
  81. package/dist/util/errors.js +82 -0
  82. package/dist/util/errors.js.map +1 -0
  83. package/dist/util/log.d.ts +19 -0
  84. package/dist/util/log.js +71 -0
  85. package/dist/util/log.js.map +1 -0
  86. package/dist/util/platform.d.ts +12 -0
  87. package/dist/util/platform.js +44 -0
  88. package/dist/util/platform.js.map +1 -0
  89. package/package.json +58 -0
package/README.md ADDED
@@ -0,0 +1,229 @@
1
+ # Camoucli
2
+
3
+ Camoucli is a Node.js-first CLI and local daemon for driving Camoufox through Playwright.
4
+
5
+ The published npm package is `camou`, and the installed command is `camou`.
6
+
7
+ It is built for local agent-style workflows:
8
+
9
+ - keep a browser session alive across CLI invocations
10
+ - preserve login state with persistent profiles
11
+ - target named tabs and sessions
12
+ - work with stable `@eN` refs from text snapshots
13
+ - install and switch Camoufox versions without the Python SDK
14
+
15
+ ## Requirements
16
+
17
+ - Node.js `>=20`
18
+ - a supported OS for Camoufox releases
19
+
20
+ ## Install
21
+
22
+ End users:
23
+
24
+ ```bash
25
+ npm install -g camou
26
+ ```
27
+
28
+ Contributors / local development:
29
+
30
+ ```bash
31
+ npm install
32
+ npm run build
33
+ ```
34
+
35
+ For local development:
36
+
37
+ ```bash
38
+ npm run dev -- --help
39
+ npm run dev:daemon
40
+ ```
41
+
42
+ ## Quick Start
43
+
44
+ Install a browser build:
45
+
46
+ ```bash
47
+ camou install
48
+ ```
49
+
50
+ `install` runs a quick launch probe after download so it can warn if the installed browser does not work with the current `playwright-core` version.
51
+ `use` runs the same check when you switch versions.
52
+
53
+ Open a page and capture refs:
54
+
55
+ ```bash
56
+ camou open https://example.com
57
+ camou snapshot -i
58
+ ```
59
+
60
+ Use refs in later commands:
61
+
62
+ ```bash
63
+ camou click @e1
64
+ camou fill @e2 "hello"
65
+ camou get title
66
+ ```
67
+
68
+ When working from this repo without a global install, prefix commands with `npm run dev --`.
69
+
70
+ The daemon auto-starts on demand, so later commands reuse the same session and profile.
71
+
72
+ ## What Works Today
73
+
74
+ ### Browser management
75
+
76
+ - `camou install [version]`
77
+ - `camou remove [version]`
78
+ - `camou use <version>`
79
+ - `camou versions`
80
+ - `camou presets`
81
+ - `camou version`
82
+ - `camou path`
83
+ - `camou doctor`
84
+
85
+ ### Page automation
86
+
87
+ - `camou open <url>`
88
+ - `camou snapshot [-i]`
89
+ - `camou click <selectorOrRef>`
90
+ - `camou fill <selectorOrRef> <text>`
91
+ - `camou press <key>`
92
+ - `camou wait <selectorOrRef>`
93
+ - `camou screenshot [path]`
94
+ - `camou get url`
95
+ - `camou get title`
96
+ - `camou get text <selectorOrRef>`
97
+
98
+ ### Session and tab management
99
+
100
+ - `camou session list`
101
+ - `camou session stop [name]`
102
+ - `camou tab list`
103
+ - `camou tab new [url]`
104
+ - `camou tab close [nameOrIndex]`
105
+
106
+ ## Common Flags
107
+
108
+ Most browser commands support:
109
+
110
+ - `--session <name>`
111
+ - `--tabname <name>`
112
+ - `--headless`
113
+ - `--browser <version>`
114
+ - `--config <path>`
115
+ - `--config-json <json>`
116
+ - `--prefs <path>`
117
+ - `--prefs-json <json>`
118
+ - `--preset <name>`
119
+ - `--proxy <url>`
120
+ - `--locale <locale>`
121
+ - `--timezone <timezone>`
122
+ - `--width <px>` / `--height <px>`
123
+ - `--json`
124
+ - `--verbose`
125
+
126
+ ## Example Flows
127
+
128
+ Use a named session and tab:
129
+
130
+ ```bash
131
+ camou open https://github.com --session work --tabname github
132
+ camou snapshot -i --session work --tabname github
133
+ ```
134
+
135
+ Install and switch versions:
136
+
137
+ ```bash
138
+ camou install 135.0.1-beta.24
139
+ camou install 134.0.0-beta.20
140
+ camou versions
141
+ camou use 134.0.0-beta.20
142
+ camou version
143
+ ```
144
+
145
+ Check the current install inventory and launch compatibility:
146
+
147
+ ```bash
148
+ camou doctor --json
149
+ ```
150
+
151
+ Launch a session with an explicit installed browser version without changing the global default:
152
+
153
+ ```bash
154
+ camou open https://example.com --session canary --browser 135.0.1-beta.24
155
+ ```
156
+
157
+ Save a screenshot to the session artifacts directory:
158
+
159
+ ```bash
160
+ camou screenshot --session work --tabname github
161
+ ```
162
+
163
+ ## Storage Layout
164
+
165
+ Camoucli uses platform-specific app directories for its own state and profiles.
166
+
167
+ - session profiles live under `profiles/<session>/{user-data,downloads,artifacts}`
168
+ - daemon state and logs live under the platform state/runtime dirs
169
+
170
+ Camoufox binaries are stored in the shared cache layout used by the Python library when possible:
171
+
172
+ - Linux: `~/.cache/camoufox/browsers/official/<version>/`
173
+ - macOS: `~/Library/Caches/camoufox/browsers/official/<version>/`
174
+ - Windows: `%LOCALAPPDATA%\camoufox\Cache\browsers\official\<version>\`
175
+
176
+ This lets Camoucli reuse compatible Camoufox installs from the Python ecosystem and vice versa.
177
+
178
+ ## Presets
179
+
180
+ Built-in presets give you a small layer of tested ergonomics on top of raw config and prefs JSON:
181
+
182
+ - `default` - baseline launch with no additional overrides
183
+ - `cache` - enables the Firefox cache/session prefs used by the Python library
184
+ - `low-bandwidth` - blocks images and speculative requests for lighter automation sessions
185
+ - `disable-coop` - relaxes Cross-Origin-Opener-Policy isolation for troublesome embedded flows
186
+
187
+ List them from the CLI:
188
+
189
+ ```bash
190
+ camou presets
191
+ ```
192
+
193
+ Apply one or more presets to a browser command:
194
+
195
+ ```bash
196
+ camou open https://example.com --preset cache --preset low-bandwidth
197
+ ```
198
+
199
+ ## Compatibility Matrix
200
+
201
+ Current local verification with `playwright-core` `1.51.1`:
202
+
203
+ | Camoufox | Status | Notes |
204
+ | --- | --- | --- |
205
+ | `135.0.1-beta.24` | launches | smoke-tested successfully |
206
+ | `135.0.1-beta.23` | incompatible | `Browser.setContrast` is not supported |
207
+
208
+ ## Notes
209
+
210
+ - The CLI is intentionally thin; the daemon owns browser lifecycle and persistent state.
211
+ - `snapshot` creates per-tab `@eN` refs, and refs are cleared after navigation or a new snapshot.
212
+ - Browser installation is explicit; the package does not download Camoufox during `npm install`.
213
+ - `install` and `use` include a quick compatibility hint based on a real headless launch probe of the selected version.
214
+ - `doctor` reports installed versions, a per-version launch compatibility matrix, shared-library diagnostics, and remediation hints.
215
+ - Passing `--json` returns structured machine-readable errors for both top-level CLI failures and daemon responses.
216
+
217
+ ## Development
218
+
219
+ ```bash
220
+ npm install
221
+ npm run build
222
+ npm test
223
+ ```
224
+
225
+ Optional targeted integration suite:
226
+
227
+ ```bash
228
+ npm run test:integration
229
+ ```
@@ -0,0 +1,4 @@
1
+ import type { Locator, Page } from 'playwright-core';
2
+ import type { TabRuntime } from './tabs.js';
3
+ export declare function resolveSelectorOrRef(tab: TabRuntime, target: string): string;
4
+ export declare function locatorForTarget(page: Page, tab: TabRuntime, target: string): Locator;
@@ -0,0 +1,15 @@
1
+ import { RefNotFoundError } from '../util/errors.js';
2
+ export function resolveSelectorOrRef(tab, target) {
3
+ if (!target.startsWith('@')) {
4
+ return target;
5
+ }
6
+ const selector = tab.refMap.get(target);
7
+ if (!selector) {
8
+ throw new RefNotFoundError(target);
9
+ }
10
+ return selector;
11
+ }
12
+ export function locatorForTarget(page, tab, target) {
13
+ return page.locator(resolveSelectorOrRef(tab, target));
14
+ }
15
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/browser/actions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGrD,MAAM,UAAU,oBAAoB,CAAC,GAAe,EAAE,MAAc;IAClE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAU,EAAE,GAAe,EAAE,MAAc;IAC1E,OAAO,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,85 @@
1
+ import type { LaunchInput } from '../camoufox/config.js';
2
+ import type { CamoucliPaths } from '../state/paths.js';
3
+ import type { Logger } from '../util/log.js';
4
+ interface BrowserManagerOptions {
5
+ paths: CamoucliPaths;
6
+ logger: Logger;
7
+ }
8
+ export declare class BrowserManager {
9
+ private readonly paths;
10
+ private readonly logger;
11
+ private readonly sessions;
12
+ private readonly startingSessions;
13
+ constructor(options: BrowserManagerOptions);
14
+ listSessions(): Promise<Array<Record<string, unknown>>>;
15
+ stopSession(sessionName: string): Promise<{
16
+ stopped: boolean;
17
+ }>;
18
+ stopAllSessions(): Promise<void>;
19
+ open(input: LaunchInput & {
20
+ session: string;
21
+ tabName: string;
22
+ url: string;
23
+ }): Promise<Record<string, unknown>>;
24
+ snapshot(input: LaunchInput & {
25
+ session: string;
26
+ tabName: string;
27
+ interactive: boolean;
28
+ }): Promise<Record<string, unknown>>;
29
+ click(input: LaunchInput & {
30
+ session: string;
31
+ tabName: string;
32
+ target: string;
33
+ }): Promise<Record<string, unknown>>;
34
+ fill(input: LaunchInput & {
35
+ session: string;
36
+ tabName: string;
37
+ target: string;
38
+ text: string;
39
+ }): Promise<Record<string, unknown>>;
40
+ press(input: LaunchInput & {
41
+ session: string;
42
+ tabName: string;
43
+ key: string;
44
+ }): Promise<Record<string, unknown>>;
45
+ screenshot(input: LaunchInput & {
46
+ session: string;
47
+ tabName: string;
48
+ path?: string | undefined;
49
+ }): Promise<Record<string, unknown>>;
50
+ getUrl(input: LaunchInput & {
51
+ session: string;
52
+ tabName: string;
53
+ }): Promise<Record<string, unknown>>;
54
+ getTitle(input: LaunchInput & {
55
+ session: string;
56
+ tabName: string;
57
+ }): Promise<Record<string, unknown>>;
58
+ getText(input: LaunchInput & {
59
+ session: string;
60
+ tabName: string;
61
+ target: string;
62
+ }): Promise<Record<string, unknown>>;
63
+ wait(input: LaunchInput & {
64
+ session: string;
65
+ tabName: string;
66
+ target: string;
67
+ timeoutMs?: number | undefined;
68
+ }): Promise<Record<string, unknown>>;
69
+ listTabs(sessionName: string): Promise<Array<Record<string, unknown>>>;
70
+ newTab(input: LaunchInput & {
71
+ session: string;
72
+ tabName: string;
73
+ url?: string | undefined;
74
+ }): Promise<Record<string, unknown>>;
75
+ closeTab(sessionName: string, target: string): Promise<{
76
+ closed: boolean;
77
+ tabName?: string;
78
+ }>;
79
+ private ensureSession;
80
+ private ensureTab;
81
+ private assertSessionCompatible;
82
+ private trackPage;
83
+ private findTab;
84
+ }
85
+ export {};
@@ -0,0 +1,300 @@
1
+ import path from 'node:path';
2
+ import { launchPersistentCamoufox } from '../camoufox/launcher.js';
3
+ import { SessionError } from '../util/errors.js';
4
+ import { locatorForTarget } from './actions.js';
5
+ import { clearSnapshotRefs, takeSnapshot } from './snapshot.js';
6
+ import { createTabRuntime } from './tabs.js';
7
+ export class BrowserManager {
8
+ paths;
9
+ logger;
10
+ sessions = new Map();
11
+ startingSessions = new Map();
12
+ constructor(options) {
13
+ this.paths = options.paths;
14
+ this.logger = options.logger;
15
+ }
16
+ async listSessions() {
17
+ return Array.from(this.sessions.values()).map((session) => ({
18
+ sessionName: session.name,
19
+ status: session.status,
20
+ browserVersion: session.browserVersion,
21
+ profileDir: session.paths.profileDir,
22
+ downloadsDir: session.paths.downloadsDir,
23
+ artifactsDir: session.paths.artifactsDir,
24
+ headless: session.resolvedConfig.headless,
25
+ tabs: Array.from(session.tabs.values()).map((tab) => ({
26
+ tabName: tab.name,
27
+ url: tab.page.url(),
28
+ })),
29
+ }));
30
+ }
31
+ async stopSession(sessionName) {
32
+ const session = this.sessions.get(sessionName);
33
+ if (!session) {
34
+ return { stopped: false };
35
+ }
36
+ await session.context.close();
37
+ this.sessions.delete(sessionName);
38
+ this.logger.info('Stopped browser session', { sessionName });
39
+ return { stopped: true };
40
+ }
41
+ async stopAllSessions() {
42
+ await Promise.all(Array.from(this.sessions.keys()).map((sessionName) => this.stopSession(sessionName)));
43
+ }
44
+ async open(input) {
45
+ const tab = await this.ensureTab(input.session, input.tabName, input);
46
+ await tab.page.goto(input.url, { waitUntil: 'domcontentloaded' });
47
+ return {
48
+ sessionName: input.session,
49
+ tabName: tab.name,
50
+ url: tab.page.url(),
51
+ title: await tab.page.title(),
52
+ };
53
+ }
54
+ async snapshot(input) {
55
+ const tab = await this.ensureTab(input.session, input.tabName, input);
56
+ const result = await takeSnapshot(tab.page, input.interactive);
57
+ tab.lastSnapshot = result;
58
+ tab.refMap = new Map(Object.entries(result.refs));
59
+ return {
60
+ sessionName: input.session,
61
+ tabName: tab.name,
62
+ interactive: input.interactive,
63
+ count: result.entries.length,
64
+ snapshot: result.text,
65
+ entries: result.entries,
66
+ };
67
+ }
68
+ async click(input) {
69
+ const tab = await this.ensureTab(input.session, input.tabName, input);
70
+ await locatorForTarget(tab.page, tab, input.target).click();
71
+ return {
72
+ sessionName: input.session,
73
+ tabName: tab.name,
74
+ target: input.target,
75
+ url: tab.page.url(),
76
+ };
77
+ }
78
+ async fill(input) {
79
+ const tab = await this.ensureTab(input.session, input.tabName, input);
80
+ await locatorForTarget(tab.page, tab, input.target).fill(input.text);
81
+ return {
82
+ sessionName: input.session,
83
+ tabName: tab.name,
84
+ target: input.target,
85
+ valueLength: input.text.length,
86
+ };
87
+ }
88
+ async press(input) {
89
+ const tab = await this.ensureTab(input.session, input.tabName, input);
90
+ await tab.page.keyboard.press(input.key);
91
+ return {
92
+ sessionName: input.session,
93
+ tabName: tab.name,
94
+ key: input.key,
95
+ };
96
+ }
97
+ async screenshot(input) {
98
+ const tab = await this.ensureTab(input.session, input.tabName, input);
99
+ const session = await this.ensureSession(input.session, input);
100
+ const filePath = input.path ?? path.join(session.paths.artifactsDir, `${tab.name}-${Date.now()}.png`);
101
+ await tab.page.screenshot({ path: filePath, fullPage: true });
102
+ return {
103
+ sessionName: input.session,
104
+ tabName: tab.name,
105
+ path: filePath,
106
+ };
107
+ }
108
+ async getUrl(input) {
109
+ const tab = await this.ensureTab(input.session, input.tabName, input);
110
+ return {
111
+ sessionName: input.session,
112
+ tabName: tab.name,
113
+ url: tab.page.url(),
114
+ };
115
+ }
116
+ async getTitle(input) {
117
+ const tab = await this.ensureTab(input.session, input.tabName, input);
118
+ return {
119
+ sessionName: input.session,
120
+ tabName: tab.name,
121
+ title: await tab.page.title(),
122
+ };
123
+ }
124
+ async getText(input) {
125
+ const tab = await this.ensureTab(input.session, input.tabName, input);
126
+ const text = await locatorForTarget(tab.page, tab, input.target).innerText();
127
+ return {
128
+ sessionName: input.session,
129
+ tabName: tab.name,
130
+ target: input.target,
131
+ text,
132
+ };
133
+ }
134
+ async wait(input) {
135
+ const tab = await this.ensureTab(input.session, input.tabName, input);
136
+ const waitOptions = input.timeoutMs ? { timeout: input.timeoutMs } : undefined;
137
+ await locatorForTarget(tab.page, tab, input.target).waitFor(waitOptions);
138
+ return {
139
+ sessionName: input.session,
140
+ tabName: tab.name,
141
+ target: input.target,
142
+ url: tab.page.url(),
143
+ };
144
+ }
145
+ async listTabs(sessionName) {
146
+ const session = await this.ensureSession(sessionName, { headless: false });
147
+ return Promise.all(Array.from(session.tabs.values()).map(async (tab, index) => ({
148
+ index,
149
+ tabName: tab.name,
150
+ url: tab.page.url(),
151
+ title: tab.page.isClosed() ? '' : await tab.page.title(),
152
+ })));
153
+ }
154
+ async newTab(input) {
155
+ const session = await this.ensureSession(input.session, input);
156
+ if (session.tabs.has(input.tabName)) {
157
+ throw new SessionError(`Tab ${input.tabName} already exists in session ${input.session}.`);
158
+ }
159
+ const page = await session.context.newPage();
160
+ const tab = this.trackPage(session, input.tabName, page);
161
+ if (input.url) {
162
+ await page.goto(input.url, { waitUntil: 'domcontentloaded' });
163
+ }
164
+ return {
165
+ sessionName: input.session,
166
+ tabName: tab.name,
167
+ url: page.url(),
168
+ };
169
+ }
170
+ async closeTab(sessionName, target) {
171
+ const session = this.sessions.get(sessionName);
172
+ if (!session) {
173
+ return { closed: false };
174
+ }
175
+ const tab = this.findTab(session, target);
176
+ if (!tab) {
177
+ return { closed: false };
178
+ }
179
+ await tab.page.close();
180
+ session.tabs.delete(tab.name);
181
+ return {
182
+ closed: true,
183
+ tabName: tab.name,
184
+ };
185
+ }
186
+ async ensureSession(sessionName, input) {
187
+ const existing = this.sessions.get(sessionName);
188
+ if (existing) {
189
+ return existing;
190
+ }
191
+ const inFlight = this.startingSessions.get(sessionName);
192
+ if (inFlight) {
193
+ return inFlight;
194
+ }
195
+ const startPromise = (async () => {
196
+ const launched = await launchPersistentCamoufox(this.paths, sessionName, input, this.logger);
197
+ const session = {
198
+ name: sessionName,
199
+ status: 'running',
200
+ context: launched.context,
201
+ tabs: new Map(),
202
+ browserVersion: launched.browserVersion,
203
+ installPath: launched.installPath,
204
+ paths: launched.sessionPaths,
205
+ resolvedConfig: launched.resolvedConfig,
206
+ launchInput: input,
207
+ startedAt: new Date().toISOString(),
208
+ };
209
+ const pages = session.context.pages();
210
+ if (pages.length === 0) {
211
+ const page = await session.context.newPage();
212
+ this.trackPage(session, 'main', page);
213
+ }
214
+ else {
215
+ pages.forEach((page, index) => {
216
+ this.trackPage(session, index === 0 ? 'main' : `restored-${index + 1}`, page);
217
+ });
218
+ }
219
+ session.context.on('close', () => {
220
+ session.status = 'stopped';
221
+ this.sessions.delete(session.name);
222
+ });
223
+ this.sessions.set(sessionName, session);
224
+ this.logger.info('Started browser session', { sessionName, browserVersion: session.browserVersion });
225
+ return session;
226
+ })();
227
+ this.startingSessions.set(sessionName, startPromise);
228
+ try {
229
+ return await startPromise;
230
+ }
231
+ catch (error) {
232
+ this.logger.error('Failed to start browser session', { sessionName, error: String(error) });
233
+ throw error;
234
+ }
235
+ finally {
236
+ this.startingSessions.delete(sessionName);
237
+ }
238
+ }
239
+ async ensureTab(sessionName, tabName, input) {
240
+ const session = await this.ensureSession(sessionName, input);
241
+ const existing = session.tabs.get(tabName);
242
+ if (existing && !existing.page.isClosed()) {
243
+ return existing;
244
+ }
245
+ if (existing?.page.isClosed()) {
246
+ session.tabs.delete(tabName);
247
+ }
248
+ const page = await session.context.newPage();
249
+ return this.trackPage(session, tabName, page);
250
+ }
251
+ assertSessionCompatible(session, input) {
252
+ if (input.configPath || input.configJson || input.prefsPath || input.prefsJson || input.preset?.length) {
253
+ throw new SessionError(`Session ${session.name} is already running. Stop it before changing config, prefs, or presets for that session.`);
254
+ }
255
+ if (input.browser && input.browser !== session.browserVersion) {
256
+ throw new SessionError(`Session ${session.name} is already running with browser ${session.browserVersion}. Use a different session name or stop the existing session first.`);
257
+ }
258
+ if (input.headless !== undefined && input.headless !== session.resolvedConfig.headless) {
259
+ throw new SessionError(`Session ${session.name} is already running with headless=${String(session.resolvedConfig.headless)}. Use a different session name or stop the existing session first.`);
260
+ }
261
+ if (input.proxy && input.proxy !== session.resolvedConfig.proxy?.server) {
262
+ throw new SessionError(`Session ${session.name} is already running with proxy ${session.resolvedConfig.proxy?.server ?? 'none'}. Use a different session name or stop the existing session first.`);
263
+ }
264
+ if (input.locale && input.locale !== session.resolvedConfig.locale) {
265
+ throw new SessionError(`Session ${session.name} is already running with locale ${session.resolvedConfig.locale ?? 'default'}. Use a different session name or stop the existing session first.`);
266
+ }
267
+ if (input.timezone && input.timezone !== session.resolvedConfig.timezoneId) {
268
+ throw new SessionError(`Session ${session.name} is already running with timezone ${session.resolvedConfig.timezoneId ?? 'default'}. Use a different session name or stop the existing session first.`);
269
+ }
270
+ if ((input.width || input.height) && (!session.resolvedConfig.viewport || session.resolvedConfig.viewport.width !== input.width || session.resolvedConfig.viewport.height !== input.height)) {
271
+ throw new SessionError(`Session ${session.name} is already running with a different window size. Use a different session name or stop the existing session first.`);
272
+ }
273
+ }
274
+ trackPage(session, tabName, page) {
275
+ const tab = createTabRuntime(tabName, page);
276
+ page.on('framenavigated', (frame) => {
277
+ if (frame === page.mainFrame()) {
278
+ void clearSnapshotRefs(page);
279
+ tab.refMap.clear();
280
+ delete tab.lastSnapshot;
281
+ }
282
+ });
283
+ page.on('close', () => {
284
+ session.tabs.delete(tab.name);
285
+ });
286
+ session.tabs.set(tabName, tab);
287
+ return tab;
288
+ }
289
+ findTab(session, target) {
290
+ if (session.tabs.has(target)) {
291
+ return session.tabs.get(target);
292
+ }
293
+ const numericIndex = Number(target);
294
+ if (Number.isInteger(numericIndex)) {
295
+ return Array.from(session.tabs.values())[numericIndex];
296
+ }
297
+ return undefined;
298
+ }
299
+ }
300
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/browser/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { Page } from 'playwright-core';
2
+ export interface SnapshotEntry {
3
+ ref: string;
4
+ selector: string;
5
+ tag: string;
6
+ role?: string | undefined;
7
+ inputType?: string | undefined;
8
+ text: string;
9
+ }
10
+ export interface SnapshotResult {
11
+ interactive: boolean;
12
+ text: string;
13
+ entries: SnapshotEntry[];
14
+ refs: Record<string, string>;
15
+ }
16
+ export declare function clearSnapshotRefs(page: Page): Promise<void>;
17
+ export declare function takeSnapshot(page: Page, interactiveOnly: boolean): Promise<SnapshotResult>;